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

Revision 7262, 8.7 KB checked in by root, 31 years ago (diff)
update utmpx instead of utmp, for Solaris use fcntl for locking files on 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 <sys/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#define MAX(x,y) ((x > y) ? x : y)
56
57loguwtmp(linepid, name, host)
58        char *linepid, *name, *host;
59{
60#ifndef SOLARIS
61  struct utmp ut;
62#else
63  struct utmpx ut;
64#endif
65  struct stat buf;
66  time_t time();
67  char *strncpy();
68  int cc, ttynum;
69  char line[10];
70  static int ftpline = 0, firsttime = 1;
71#ifdef SOLARIS
72    struct flock lock;
73#endif
74  if (firsttime)
75    {
76      if (utmpfd == -1)
77#ifndef SOLARIS
78        utmpfd = open(UTMPFILE, O_RDWR, 0);
79#else
80        utmpfd = open(UTMPXFILE, O_RDWR, 0);
81#endif
82      ptrvalid = 0; ptr = 0;
83
84      /*
85       * We find the entry in utmp we want to use only once,
86       * then just continue using it until we exit.
87       * Unfortunately, utmp handling doesn't work with
88       * a general mechanism; it's dependent on assumptions
89       * about ttys or small numbers of lines for both BSD
90       * in general and in AIX convenience routines.
91       */
92      if (utmpfd >= 0)
93        {
94#if defined(_AIX) || defined(SOLARIS)
95          /*
96           * Under AIX, we run through all of utmp looking for
97           * the appropriate place to put an ftp entry.
98           */
99          /*
100           * Same for SOLARIS
101           */
102#else
103          /*
104           * Under BSD, the utmp entry location is determined
105           * by where your tty is in /etc/ttys. But we aren't
106           * using a tty. So we figure out how many ttys there
107           * are, and then write to utmp BEYOND the location
108           * of the last tty so we don't collide.
109           */
110          setttyent();
111          ttynum = 20; /* Safety in case /etc/ttys grows... */
112          while (getttyent() != 0)
113            ttynum++;
114          endttyent();
115          ptr = ttynum * sizeof(ut);
116#endif
117
118          /*
119           * Standard tty handling in BSD doesn't require utmp
120           * to be locked since the /dev/tty* files provide the
121           * required locking mechanism. We have no such luxury;
122           * furthermore, locking of the utmp file is required
123           * under AIX, even if IBM's own software doesn't do it.
124           */
125#ifndef SOLARIS
126          flock(utmpfd, LOCK_EX);
127#else
128          lock.l_type = F_WRLCK;
129          lock.l_start = 0;
130          lock.l_whence = 0;
131          lock.l_len = 0;
132          fcntl(utmpfd, F_SETLK, &lock);
133#endif
134          lseek(utmpfd, ptr, L_SET);
135
136          /* Scan for a line with the name ftpX */
137          while ((cc = read(utmpfd, &ut, sizeof(ut))) == sizeof(ut))
138            {
139              if (!strncmp("ftp", ut.ut_line, 3))
140                {
141                  /* If the ftp line here is empty, we're set. Emptiness
142                   * is determined by a null username under BSD, and
143                   * type DEAD_PROCESS under AIX - because I say so.
144                   * The AIX manpage is not rich in suggestions
145                   * of how this _should_ be done, and other software
146                   * varies. */
147#if defined(_AIX) || defined(SOLARIS)
148                  if (ut.ut_type == DEAD_PROCESS)
149#else
150                  if (ut.ut_name[0] == '\0')
151#endif
152                    break;
153                  ftpline++;
154                }
155              ptr += cc;
156            }
157          if (cc == 0) /* EOF: add a new entry; leave ptr unchanged */
158            {
159              if (!fstat(utmpfd, &buf))
160                {
161                  ptrvalid = 1;
162                }
163              else
164                { /*
165                   * The fstat should never fail. The only reason
166                   * it is done here is to get the current length
167                   * of the file should it later prove necessary
168                   * to truncate it to its original length when
169                   * a write only partially succeeds.
170                   */
171#ifndef SOLARIS
172                  flock(utmpfd, LOCK_UN);
173#else
174                  lock.l_type = F_UNLCK;
175                  lock.l_start = 0;
176                  lock.l_whence = 0;
177                  lock.l_len = 0;
178                  fcntl(utmpfd, F_SETLK, &lock);
179#endif
180                  close(utmpfd);
181                  utmpfd = -1;
182                }
183            }
184          else
185            if (cc == sizeof(ut))
186              {
187                ptrvalid = 1;
188              }
189            else /* The utmp file has a bad length. Don't touch it. */
190              {
191#ifndef SOLARIS
192                flock(utmpfd, LOCK_UN);
193#else
194                lock.l_type = F_UNLCK;
195                lock.l_start = 0;
196                lock.l_whence = 0;
197                lock.l_len = 0;
198                fcntl(utmpfd, F_SETLK, &lock);
199#endif
200                close(utmpfd);
201                utmpfd = -1;
202              }
203        }
204    }
205
206  memset(&ut, 0, sizeof(ut));
207  if (ptrvalid)
208    {
209      /* Do this if we got to deal with utmp and got a real line number */
210      sprintf(line, "ftp%d", ftpline);
211      (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
212    }
213  else /* otherwise, use the passed in line for wtmp logging only */
214    (void)strncpy(ut.ut_line, linepid, sizeof(ut.ut_line));
215  (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
216  (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
217#ifndef SOLARIS
218  (void)time(&ut.ut_time);
219#else
220  (void) gettimeofday(&ut.ut_tv);
221#endif
222#if defined(_AIX) || defined(SOLARIS)
223  /* Note that name is only \0 in the case where the program
224   * is exiting. */
225  ut.ut_type = (name[0] == '\0' ? DEAD_PROCESS : USER_PROCESS);
226  ut.ut_exit.e_exit = 2;
227  ut.ut_pid = getpid();
228#endif
229
230  if (ptrvalid)
231    {
232      lseek(utmpfd, ptr, L_SET);
233      cc = write(utmpfd, &ut, sizeof(ut));
234      if (firsttime && cc != sizeof(ut))
235        {
236          (void)ftruncate(utmpfd, buf.st_size);
237          ptrvalid = 0;
238#ifndef SOLARIS
239          flock(utmpfd, LOCK_UN);
240#else
241          lock.l_type = F_UNLCK;
242          lock.l_start = 0;
243          lock.l_whence = 0;
244          lock.l_len = 0;
245          fcntl(utmpfd, F_SETLK, &lock);
246#endif
247
248          close(utmpfd);
249          utmpfd = -1;
250        }
251      else
252        if (firsttime)
253#ifndef SOLARIS
254          flock(utmpfd, LOCK_UN);
255#else
256          lock.l_type = F_UNLCK;
257          lock.l_start = 0;
258          lock.l_whence = 0;
259          lock.l_len = 0;
260          fcntl(utmpfd, F_SETLK, &lock);
261#endif
262
263      /* In case this was the first time around and we had it locked...
264       * Note that the file lock is only necessary for when we allocate
265       * our slot. Afterwards, until we release the slot, its ours.
266       */
267    }
268
269  firsttime = 0;
270
271#ifndef SOLARIS
272  if (!fd && (fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
273    return;
274  if (!fstat(fd, &buf)) {
275    if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
276        sizeof(struct utmp))
277      (void)ftruncate(fd, buf.st_size);
278  }
279#else
280  (void) updwtmpx(WTMPXFILE, &ut);
281#endif
282}
283
284int user_logged_in(who)
285     char *who;
286{
287#ifndef SOLARIS
288  struct utmp ut;
289#else
290  struct utmpx ut;
291#endif
292  off_t p = 0;
293#if defined(_AIX) || defined(SOLARIS)
294  static int pid = 0;
295
296  if (pid == 0)
297    pid = getpid();
298#endif
299
300  if (utmpfd == -1)
301    {
302#ifndef SOLARIS
303      utmpfd = open(UTMPFILE, O_RDWR, 0);
304#else
305      utmpfd = open(UTMPXFILE, O_RDWR, 0);
306#endif
307      if (utmpfd == -1)
308        return 0; /* should this be what we do? XXX */
309    }
310
311  lseek(utmpfd, p, L_SET);
312  while (read(utmpfd, &ut, sizeof(ut)) == sizeof(ut))
313    {
314      if (!strcmp(ut.ut_name, who) &&
315#if defined(_AIX) || defined(SOLARIS)
316          (ut.ut_type == USER_PROCESS) &&
317          (ut.ut_pid != pid))
318#else
319          ((ptrvalid && p != ptr) || !ptrvalid))
320#endif
321        return 1;
322      else
323        p += sizeof(ut);
324    }
325
326  return 0;
327}
328#endif /* ATHENA */
329
330logwtmp(line, name, host)
331        char *line, *name, *host;
332{
333#ifndef SOLARIS
334        struct utmp ut;
335#else
336        struct utmpx ut;
337#endif
338        struct stat buf;
339        time_t time();
340        char *strncpy();
341
342#ifndef SOLARIS
343        if (!fd && (fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
344#else
345        if (!fd && (fd = open(WTMPXFILE, O_WRONLY|O_APPEND, 0)) < 0)
346#endif
347                return;
348        if (!fstat(fd, &buf)) {
349                memset(&ut, 0, sizeof(ut));
350                (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
351                (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
352                (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
353#ifndef SOLARIS
354                (void)time(&ut.ut_time);
355#else
356                (void) gettimeofday(&ut.ut_tv);
357#endif
358#if defined(_AIX) || defined(SOLARIS)
359                ut.ut_pid = getpid();
360                if (name[0] != '\0')
361                  ut.ut_type = USER_PROCESS;
362                else
363                  ut.ut_type = DEAD_PROCESS;
364#endif /* _AIX */
365
366                if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
367                    sizeof(struct utmp))
368                        (void)ftruncate(fd, buf.st_size);
369        }
370}
Note: See TracBrowser for help on using the repository browser.