[6079] | 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 |
---|
| 21 | static 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> |
---|
[7262] | 28 | #ifdef POSIX |
---|
| 29 | #include <unistd.h> |
---|
[7299] | 30 | #include <fcntl.h> |
---|
[7262] | 31 | #include <string.h> |
---|
| 32 | #else |
---|
[6085] | 33 | #include <ttyent.h> |
---|
[7262] | 34 | #endif |
---|
[6079] | 35 | #include <utmp.h> |
---|
[7262] | 36 | #ifdef SOLARIS |
---|
| 37 | #include <utmpx.h> |
---|
| 38 | #endif |
---|
[6085] | 39 | #ifdef ATHENA |
---|
| 40 | #define UTMPFILE "/etc/utmp" |
---|
| 41 | #endif |
---|
[6079] | 42 | #define WTMPFILE "/usr/adm/wtmp" |
---|
[7262] | 43 | #ifdef SOLARIS |
---|
| 44 | #define UTMPXFILE "/etc/utmpx" |
---|
| 45 | #define WTMPXFILE "/usr/adm/wtmpx" |
---|
| 46 | #endif |
---|
[6079] | 47 | static int fd; |
---|
[6085] | 48 | #ifdef ATHENA |
---|
| 49 | static int utmpfd = -1, ptrvalid = 0; |
---|
| 50 | static off_t ptr; |
---|
| 51 | #endif |
---|
[6079] | 52 | |
---|
[6085] | 53 | #ifdef ATHENA |
---|
| 54 | |
---|
[7299] | 55 | #ifndef MAX |
---|
[6085] | 56 | #define MAX(x,y) ((x > y) ? x : y) |
---|
[7299] | 57 | #endif |
---|
[6085] | 58 | |
---|
| 59 | loguwtmp(linepid, name, host) |
---|
| 60 | char *linepid, *name, *host; |
---|
| 61 | { |
---|
[7262] | 62 | #ifndef SOLARIS |
---|
[6085] | 63 | struct utmp ut; |
---|
[7262] | 64 | #else |
---|
| 65 | struct utmpx ut; |
---|
| 66 | #endif |
---|
[6085] | 67 | struct stat buf; |
---|
| 68 | time_t time(); |
---|
[7299] | 69 | #ifndef _AIX |
---|
[6085] | 70 | char *strncpy(); |
---|
[7299] | 71 | #endif |
---|
[6085] | 72 | int cc, ttynum; |
---|
| 73 | char line[10]; |
---|
| 74 | static int ftpline = 0, firsttime = 1; |
---|
[7262] | 75 | #ifdef SOLARIS |
---|
| 76 | struct flock lock; |
---|
| 77 | #endif |
---|
[6085] | 78 | if (firsttime) |
---|
| 79 | { |
---|
| 80 | if (utmpfd == -1) |
---|
[7262] | 81 | #ifndef SOLARIS |
---|
[6085] | 82 | utmpfd = open(UTMPFILE, O_RDWR, 0); |
---|
[7262] | 83 | #else |
---|
| 84 | utmpfd = open(UTMPXFILE, O_RDWR, 0); |
---|
| 85 | #endif |
---|
[6085] | 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 | { |
---|
[7262] | 98 | #if defined(_AIX) || defined(SOLARIS) |
---|
[6085] | 99 | /* |
---|
| 100 | * Under AIX, we run through all of utmp looking for |
---|
| 101 | * the appropriate place to put an ftp entry. |
---|
| 102 | */ |
---|
[7262] | 103 | /* |
---|
| 104 | * Same for SOLARIS |
---|
| 105 | */ |
---|
[6085] | 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 | */ |
---|
[7262] | 129 | #ifndef SOLARIS |
---|
[6085] | 130 | flock(utmpfd, LOCK_EX); |
---|
[7262] | 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 |
---|
[6085] | 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. */ |
---|
[7262] | 151 | #if defined(_AIX) || defined(SOLARIS) |
---|
[6085] | 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 | */ |
---|
[7262] | 175 | #ifndef SOLARIS |
---|
[6085] | 176 | flock(utmpfd, LOCK_UN); |
---|
[7262] | 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 |
---|
[6085] | 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 | { |
---|
[7262] | 195 | #ifndef SOLARIS |
---|
[6085] | 196 | flock(utmpfd, LOCK_UN); |
---|
[7262] | 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 |
---|
[6085] | 204 | close(utmpfd); |
---|
| 205 | utmpfd = -1; |
---|
| 206 | } |
---|
| 207 | } |
---|
| 208 | } |
---|
| 209 | |
---|
[7262] | 210 | memset(&ut, 0, sizeof(ut)); |
---|
[6085] | 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)); |
---|
[7262] | 221 | #ifndef SOLARIS |
---|
[6085] | 222 | (void)time(&ut.ut_time); |
---|
[7262] | 223 | #else |
---|
[9393] | 224 | (void) gettimeofday(&ut.ut_tv, NULL); |
---|
[7262] | 225 | #endif |
---|
| 226 | #if defined(_AIX) || defined(SOLARIS) |
---|
[6085] | 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; |
---|
[7262] | 242 | #ifndef SOLARIS |
---|
[6085] | 243 | flock(utmpfd, LOCK_UN); |
---|
[7262] | 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 | |
---|
[6085] | 252 | close(utmpfd); |
---|
| 253 | utmpfd = -1; |
---|
| 254 | } |
---|
| 255 | else |
---|
| 256 | if (firsttime) |
---|
[7262] | 257 | #ifndef SOLARIS |
---|
[6085] | 258 | flock(utmpfd, LOCK_UN); |
---|
[7262] | 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 | |
---|
[6085] | 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 | |
---|
[7262] | 275 | #ifndef SOLARIS |
---|
[6085] | 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 | } |
---|
[7262] | 283 | #else |
---|
| 284 | (void) updwtmpx(WTMPXFILE, &ut); |
---|
| 285 | #endif |
---|
[6085] | 286 | } |
---|
| 287 | |
---|
| 288 | int user_logged_in(who) |
---|
| 289 | char *who; |
---|
| 290 | { |
---|
[7262] | 291 | #ifndef SOLARIS |
---|
[6085] | 292 | struct utmp ut; |
---|
[7262] | 293 | #else |
---|
| 294 | struct utmpx ut; |
---|
| 295 | #endif |
---|
[6085] | 296 | off_t p = 0; |
---|
[7262] | 297 | #if defined(_AIX) || defined(SOLARIS) |
---|
[6085] | 298 | static int pid = 0; |
---|
| 299 | |
---|
| 300 | if (pid == 0) |
---|
| 301 | pid = getpid(); |
---|
| 302 | #endif |
---|
| 303 | |
---|
| 304 | if (utmpfd == -1) |
---|
| 305 | { |
---|
[7262] | 306 | #ifndef SOLARIS |
---|
[6085] | 307 | utmpfd = open(UTMPFILE, O_RDWR, 0); |
---|
[7262] | 308 | #else |
---|
| 309 | utmpfd = open(UTMPXFILE, O_RDWR, 0); |
---|
| 310 | #endif |
---|
[6085] | 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) && |
---|
[7262] | 319 | #if defined(_AIX) || defined(SOLARIS) |
---|
[6085] | 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 | |
---|
[6079] | 334 | logwtmp(line, name, host) |
---|
| 335 | char *line, *name, *host; |
---|
| 336 | { |
---|
[7262] | 337 | #ifndef SOLARIS |
---|
[6079] | 338 | struct utmp ut; |
---|
[7262] | 339 | #else |
---|
| 340 | struct utmpx ut; |
---|
| 341 | #endif |
---|
[6079] | 342 | struct stat buf; |
---|
| 343 | time_t time(); |
---|
[7299] | 344 | #ifndef _AIX |
---|
[6079] | 345 | char *strncpy(); |
---|
[7299] | 346 | #endif |
---|
[6079] | 347 | |
---|
[7262] | 348 | #ifndef SOLARIS |
---|
[6079] | 349 | if (!fd && (fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0) |
---|
[7262] | 350 | #else |
---|
| 351 | if (!fd && (fd = open(WTMPXFILE, O_WRONLY|O_APPEND, 0)) < 0) |
---|
| 352 | #endif |
---|
[6079] | 353 | return; |
---|
| 354 | if (!fstat(fd, &buf)) { |
---|
[7262] | 355 | memset(&ut, 0, sizeof(ut)); |
---|
[6079] | 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)); |
---|
[7262] | 359 | #ifndef SOLARIS |
---|
[6079] | 360 | (void)time(&ut.ut_time); |
---|
[7262] | 361 | #else |
---|
| 362 | (void) gettimeofday(&ut.ut_tv); |
---|
| 363 | #endif |
---|
| 364 | #if defined(_AIX) || defined(SOLARIS) |
---|
[6085] | 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 | |
---|
[6079] | 372 | if (write(fd, (char *)&ut, sizeof(struct utmp)) != |
---|
| 373 | sizeof(struct utmp)) |
---|
| 374 | (void)ftruncate(fd, buf.st_size); |
---|
| 375 | } |
---|
| 376 | } |
---|