source: trunk/athena/etc/ftpd/logwtmp.c @ 9393

Revision 9393, 8.8 KB checked in by ghudson, 28 years ago (diff)
Contrary to the Solaris 2.4 man page, gettimeofday() actually wants a second argument which must be NULL. See the C++-only prototype in Solaris 2.4's <sys/time.h> for reference. This is documented and enforced in Solaris 2.5.1, so we need to add a second NULL argument to the gettimeofday() calls for Solaris.
Line 
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley.  The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * static char sccsid[] = "@(#)logwtmp.c        5.2 (Berkeley) 9/20/88";
18 */
19
20#ifndef lint
21static char sccsid[] = "@(#)logwtmp.c   5.2 (Berkeley) 9/22/88";
22#endif /* not lint */
23
24#include <sys/types.h>
25#include <sys/file.h>
26#include <sys/time.h>
27#include <sys/stat.h>
28#ifdef POSIX
29#include <unistd.h>
30#include <fcntl.h>
31#include <string.h>
32#else
33#include <ttyent.h>
34#endif
35#include <utmp.h>
36#ifdef SOLARIS
37#include <utmpx.h>
38#endif
39#ifdef ATHENA
40#define UTMPFILE        "/etc/utmp"
41#endif
42#define WTMPFILE        "/usr/adm/wtmp"
43#ifdef SOLARIS
44#define UTMPXFILE       "/etc/utmpx"
45#define WTMPXFILE       "/usr/adm/wtmpx"
46#endif
47static int fd;
48#ifdef ATHENA
49static int utmpfd = -1, ptrvalid = 0;
50static off_t ptr;
51#endif
52
53#ifdef ATHENA
54
55#ifndef MAX
56#define MAX(x,y) ((x > y) ? x : y)
57#endif
58
59loguwtmp(linepid, name, host)
60        char *linepid, *name, *host;
61{
62#ifndef SOLARIS
63  struct utmp ut;
64#else
65  struct utmpx ut;
66#endif
67  struct stat buf;
68  time_t time();
69#ifndef _AIX
70  char *strncpy();
71#endif
72  int cc, ttynum;
73  char line[10];
74  static int ftpline = 0, firsttime = 1;
75#ifdef SOLARIS
76    struct flock lock;
77#endif
78  if (firsttime)
79    {
80      if (utmpfd == -1)
81#ifndef SOLARIS
82        utmpfd = open(UTMPFILE, O_RDWR, 0);
83#else
84        utmpfd = open(UTMPXFILE, O_RDWR, 0);
85#endif
86      ptrvalid = 0; ptr = 0;
87
88      /*
89       * We find the entry in utmp we want to use only once,
90       * then just continue using it until we exit.
91       * Unfortunately, utmp handling doesn't work with
92       * a general mechanism; it's dependent on assumptions
93       * about ttys or small numbers of lines for both BSD
94       * in general and in AIX convenience routines.
95       */
96      if (utmpfd >= 0)
97        {
98#if defined(_AIX) || defined(SOLARIS)
99          /*
100           * Under AIX, we run through all of utmp looking for
101           * the appropriate place to put an ftp entry.
102           */
103          /*
104           * Same for SOLARIS
105           */
106#else
107          /*
108           * Under BSD, the utmp entry location is determined
109           * by where your tty is in /etc/ttys. But we aren't
110           * using a tty. So we figure out how many ttys there
111           * are, and then write to utmp BEYOND the location
112           * of the last tty so we don't collide.
113           */
114          setttyent();
115          ttynum = 20; /* Safety in case /etc/ttys grows... */
116          while (getttyent() != 0)
117            ttynum++;
118          endttyent();
119          ptr = ttynum * sizeof(ut);
120#endif
121
122          /*
123           * Standard tty handling in BSD doesn't require utmp
124           * to be locked since the /dev/tty* files provide the
125           * required locking mechanism. We have no such luxury;
126           * furthermore, locking of the utmp file is required
127           * under AIX, even if IBM's own software doesn't do it.
128           */
129#ifndef SOLARIS
130          flock(utmpfd, LOCK_EX);
131#else
132          lock.l_type = F_WRLCK;
133          lock.l_start = 0;
134          lock.l_whence = 0;
135          lock.l_len = 0;
136          fcntl(utmpfd, F_SETLK, &lock);
137#endif
138          lseek(utmpfd, ptr, L_SET);
139
140          /* Scan for a line with the name ftpX */
141          while ((cc = read(utmpfd, &ut, sizeof(ut))) == sizeof(ut))
142            {
143              if (!strncmp("ftp", ut.ut_line, 3))
144                {
145                  /* If the ftp line here is empty, we're set. Emptiness
146                   * is determined by a null username under BSD, and
147                   * type DEAD_PROCESS under AIX - because I say so.
148                   * The AIX manpage is not rich in suggestions
149                   * of how this _should_ be done, and other software
150                   * varies. */
151#if defined(_AIX) || defined(SOLARIS)
152                  if (ut.ut_type == DEAD_PROCESS)
153#else
154                  if (ut.ut_name[0] == '\0')
155#endif
156                    break;
157                  ftpline++;
158                }
159              ptr += cc;
160            }
161          if (cc == 0) /* EOF: add a new entry; leave ptr unchanged */
162            {
163              if (!fstat(utmpfd, &buf))
164                {
165                  ptrvalid = 1;
166                }
167              else
168                { /*
169                   * The fstat should never fail. The only reason
170                   * it is done here is to get the current length
171                   * of the file should it later prove necessary
172                   * to truncate it to its original length when
173                   * a write only partially succeeds.
174                   */
175#ifndef SOLARIS
176                  flock(utmpfd, LOCK_UN);
177#else
178                  lock.l_type = F_UNLCK;
179                  lock.l_start = 0;
180                  lock.l_whence = 0;
181                  lock.l_len = 0;
182                  fcntl(utmpfd, F_SETLK, &lock);
183#endif
184                  close(utmpfd);
185                  utmpfd = -1;
186                }
187            }
188          else
189            if (cc == sizeof(ut))
190              {
191                ptrvalid = 1;
192              }
193            else /* The utmp file has a bad length. Don't touch it. */
194              {
195#ifndef SOLARIS
196                flock(utmpfd, LOCK_UN);
197#else
198                lock.l_type = F_UNLCK;
199                lock.l_start = 0;
200                lock.l_whence = 0;
201                lock.l_len = 0;
202                fcntl(utmpfd, F_SETLK, &lock);
203#endif
204                close(utmpfd);
205                utmpfd = -1;
206              }
207        }
208    }
209
210  memset(&ut, 0, sizeof(ut));
211  if (ptrvalid)
212    {
213      /* Do this if we got to deal with utmp and got a real line number */
214      sprintf(line, "ftp%d", ftpline);
215      (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
216    }
217  else /* otherwise, use the passed in line for wtmp logging only */
218    (void)strncpy(ut.ut_line, linepid, sizeof(ut.ut_line));
219  (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
220  (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
221#ifndef SOLARIS
222  (void)time(&ut.ut_time);
223#else
224  (void) gettimeofday(&ut.ut_tv, NULL);
225#endif
226#if defined(_AIX) || defined(SOLARIS)
227  /* Note that name is only \0 in the case where the program
228   * is exiting. */
229  ut.ut_type = (name[0] == '\0' ? DEAD_PROCESS : USER_PROCESS);
230  ut.ut_exit.e_exit = 2;
231  ut.ut_pid = getpid();
232#endif
233
234  if (ptrvalid)
235    {
236      lseek(utmpfd, ptr, L_SET);
237      cc = write(utmpfd, &ut, sizeof(ut));
238      if (firsttime && cc != sizeof(ut))
239        {
240          (void)ftruncate(utmpfd, buf.st_size);
241          ptrvalid = 0;
242#ifndef SOLARIS
243          flock(utmpfd, LOCK_UN);
244#else
245          lock.l_type = F_UNLCK;
246          lock.l_start = 0;
247          lock.l_whence = 0;
248          lock.l_len = 0;
249          fcntl(utmpfd, F_SETLK, &lock);
250#endif
251
252          close(utmpfd);
253          utmpfd = -1;
254        }
255      else
256        if (firsttime)
257#ifndef SOLARIS
258          flock(utmpfd, LOCK_UN);
259#else
260          lock.l_type = F_UNLCK;
261          lock.l_start = 0;
262          lock.l_whence = 0;
263          lock.l_len = 0;
264          fcntl(utmpfd, F_SETLK, &lock);
265#endif
266
267      /* In case this was the first time around and we had it locked...
268       * Note that the file lock is only necessary for when we allocate
269       * our slot. Afterwards, until we release the slot, its ours.
270       */
271    }
272
273  firsttime = 0;
274
275#ifndef SOLARIS
276  if (!fd && (fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
277    return;
278  if (!fstat(fd, &buf)) {
279    if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
280        sizeof(struct utmp))
281      (void)ftruncate(fd, buf.st_size);
282  }
283#else
284  (void) updwtmpx(WTMPXFILE, &ut);
285#endif
286}
287
288int user_logged_in(who)
289     char *who;
290{
291#ifndef SOLARIS
292  struct utmp ut;
293#else
294  struct utmpx ut;
295#endif
296  off_t p = 0;
297#if defined(_AIX) || defined(SOLARIS)
298  static int pid = 0;
299
300  if (pid == 0)
301    pid = getpid();
302#endif
303
304  if (utmpfd == -1)
305    {
306#ifndef SOLARIS
307      utmpfd = open(UTMPFILE, O_RDWR, 0);
308#else
309      utmpfd = open(UTMPXFILE, O_RDWR, 0);
310#endif
311      if (utmpfd == -1)
312        return 0; /* should this be what we do? XXX */
313    }
314
315  lseek(utmpfd, p, L_SET);
316  while (read(utmpfd, &ut, sizeof(ut)) == sizeof(ut))
317    {
318      if (!strcmp(ut.ut_name, who) &&
319#if defined(_AIX) || defined(SOLARIS)
320          (ut.ut_type == USER_PROCESS) &&
321          (ut.ut_pid != pid))
322#else
323          ((ptrvalid && p != ptr) || !ptrvalid))
324#endif
325        return 1;
326      else
327        p += sizeof(ut);
328    }
329
330  return 0;
331}
332#endif /* ATHENA */
333
334logwtmp(line, name, host)
335        char *line, *name, *host;
336{
337#ifndef SOLARIS
338        struct utmp ut;
339#else
340        struct utmpx ut;
341#endif
342        struct stat buf;
343        time_t time();
344#ifndef _AIX
345        char *strncpy();
346#endif
347
348#ifndef SOLARIS
349        if (!fd && (fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
350#else
351        if (!fd && (fd = open(WTMPXFILE, O_WRONLY|O_APPEND, 0)) < 0)
352#endif
353                return;
354        if (!fstat(fd, &buf)) {
355                memset(&ut, 0, sizeof(ut));
356                (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
357                (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
358                (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
359#ifndef SOLARIS
360                (void)time(&ut.ut_time);
361#else
362                (void) gettimeofday(&ut.ut_tv);
363#endif
364#if defined(_AIX) || defined(SOLARIS)
365                ut.ut_pid = getpid();
366                if (name[0] != '\0')
367                  ut.ut_type = USER_PROCESS;
368                else
369                  ut.ut_type = DEAD_PROCESS;
370#endif /* _AIX */
371
372                if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
373                    sizeof(struct utmp))
374                        (void)ftruncate(fd, buf.st_size);
375        }
376}
Note: See TracBrowser for help on using the repository browser.