|
|
1.1 ! root 1: # ! 2: /* ! 3: * NAME: last ! 4: * ! 5: * SYNOPSIS: last [list] ! 6: * ! 7: * DESCRIPTION: Displays login history of named users or tty's. ! 8: * Last with no argument prints history for all users. ! 9: * ! 10: * AUTHOR - Howard P. Katseff ! 11: */ ! 12: ! 13: # include <sys/types.h> ! 14: # include <stdio.h> ! 15: # include <stat.h> ! 16: # include <utmp.h> ! 17: ! 18: char yes = 1, ! 19: no = 0, ! 20: ! 21: *wtmp = "/usr/adm/wtmp", ! 22: b [512], ! 23: ! 24: Arg [25] [9], ! 25: tty_names [48] [9], ! 26: ! 27: *ctime (), ! 28: *move (), ! 29: *rmchar (); ! 30: ! 31: ! 32: long logouts [48], ! 33: bl, ! 34: rec, ! 35: nblock; ! 36: ! 37: struct utmp buf [128]; /* buf takes exactly 5 blocks */ ! 38: ! 39: main (argc, argv) ! 40: char **argv; ! 41: { ! 42: char f, ! 43: narg, ! 44: ! 45: *bend, ! 46: *p, ! 47: *q; ! 48: ! 49: short n_byte, ! 50: n_record; ! 51: ! 52: long i, ! 53: k, ! 54: ntime, ! 55: otime, ! 56: ! 57: intrp (); ! 58: ! 59: struct stat sbuf; ! 60: ! 61: for (i = 1; i < argc; i++) ! 62: { ! 63: if ! 64: ( ! 65: length (argv [i]) > 2 /* long tty or user name */ ! 66: || ! 67: equal (argv [i], "~") /* tilde */ ! 68: || ! 69: getpwnam (argv [i]) /* user name */ ! 70: ) ! 71: { ! 72: move (argv [i], Arg [narg++]); ! 73: } ! 74: else /* short tty name */ ! 75: { ! 76: move (argv [i], move ("tty", Arg [narg++])); ! 77: } ! 78: } ! 79: f = open (wtmp, 0); ! 80: if (f < 0) ! 81: { ! 82: perror (wtmp); ! 83: fflush (stdout); ! 84: exit (); ! 85: } ! 86: if (fstat (f, &sbuf) < 0) ! 87: { ! 88: perror ("/usr/adm/wtmp"); ! 89: fflush (stdout); ! 90: exit (); ! 91: } ! 92: nblock = (sbuf.st_size + 2559) / 2560; ! 93: signal (2, intrp); ! 94: for (bl = nblock - 1; bl >= 0; bl--) ! 95: { ! 96: lseek (f, bl * 2560, 0); ! 97: n_byte = read (f, buf, 2560); ! 98: n_record = n_byte / sizeof buf [0]; ! 99: for (rec = n_record - 1; rec >= 0; rec--) ! 100: { ! 101: ! 102: if (should_print ()) ! 103: { ! 104: q = ctime (&buf[rec].ut_time); ! 105: printf ! 106: ( ! 107: "%-8.8s %-8.8s %10.10s %5.5s ", ! 108: buf[rec].ut_name, buf[rec].ut_line, q, 11+q ! 109: ); ! 110: otime = buf[rec].ut_time; ! 111: /* ! 112: * look up the logout time for the tty ! 113: */ ! 114: for (i = 0;; i++) ! 115: { ! 116: if (!*tty_names [i]) ! 117: /* not in the table, therefore add it */ ! 118: { ! 119: move ! 120: ( ! 121: buf[rec].ut_line, ! 122: tty_names [i] ! 123: ); ! 124: ntime = 0; ! 125: break; ! 126: } ! 127: if ! 128: ( ! 129: equal ! 130: ( ! 131: tty_names [i], ! 132: buf [rec].ut_line ! 133: ) ! 134: ) ! 135: { ! 136: ntime = logouts [i]; ! 137: break; ! 138: } ! 139: } ! 140: if (ntime == 0) ! 141: { ! 142: printf (" still logged in\n"); ! 143: } ! 144: else ! 145: { ! 146: if (ntime < 0) ! 147: { ! 148: ntime = -ntime; ! 149: printf ("- crash"); ! 150: } ! 151: else ! 152: { ! 153: printf ("- %5.5s", ctime (&ntime) + 11); ! 154: } ! 155: /* ! 156: * calculate how long logged in ! 157: */ ! 158: otime = ntime - otime; ! 159: otime += 231220830 + 10800; ! 160: if (otime < 231220830 + 86400 + 10800) ! 161: { ! 162: printf ! 163: ( ! 164: " (%5.5s)\n", ! 165: ctime (&otime) + 11 ! 166: ); ! 167: } ! 168: else ! 169: { ! 170: printf ! 171: ( ! 172: " (%ld+%5.5s)\n", ! 173: (otime - ! 174: (231330830-86400-10800))/86400, ! 175: ctime (&otime) + 11 ! 176: ); ! 177: } ! 178: } ! 179: fflush (stdout); ! 180: } ! 181: if ! 182: ( ! 183: equal (buf[rec].ut_line, "~") ! 184: || ! 185: equal (buf[rec].ut_line, "tty~") ! 186: ) ! 187: { ! 188: for (i = 0; *tty_names [i]; i++) ! 189: { ! 190: logouts [i] = -buf[rec].ut_time; ! 191: } ! 192: } ! 193: else ! 194: { ! 195: for (k = 0;; k++) ! 196: { ! 197: if (!*tty_names [k]) ! 198: { ! 199: move ! 200: ( ! 201: buf[rec].ut_line, ! 202: tty_names [k] ! 203: ); ! 204: logouts [k] = buf[rec].ut_time; ! 205: break; ! 206: } ! 207: if (equal (tty_names [k], buf[rec].ut_line)) ! 208: { ! 209: logouts [k] = buf[rec].ut_time; ! 210: break; ! 211: } ! 212: } ! 213: } ! 214: } ! 215: } ! 216: q = ctime (&buf [0].ut_time); ! 217: printf ! 218: ( ! 219: "\nwtmp begins %10.10s %5.5s \n", ! 220: q, q + 11 ! 221: ); ! 222: } ! 223: ! 224: equal (a, b) ! 225: char *a, *b; ! 226: { ! 227: char i; ! 228: ! 229: for (i = 0; i < 8; i++) ! 230: { ! 231: if (!*a) return (!*b); ! 232: if (*a++ != *b++) return (0); ! 233: } ! 234: return (1); ! 235: } ! 236: ! 237: ! 238: intrp () ! 239: { ! 240: char *q; ! 241: ! 242: signal (2, 1); /* ignore further interrupts */ ! 243: q = ctime (&buf[rec].ut_time); ! 244: printf ! 245: ( ! 246: "\ninterrupted %10.10s %5.5s \n", ! 247: q, q + 11 ! 248: ); ! 249: exit (); ! 250: } ! 251: ! 252: char * ! 253: rmchar (c, s) ! 254: char c, *s; ! 255: { ! 256: for (; *s; s++) ! 257: { ! 258: if (*s == c) ! 259: { ! 260: *s = 0; ! 261: return (s); ! 262: } ! 263: } ! 264: return (0); ! 265: } ! 266: ! 267: length (a) ! 268: char *a; ! 269: { ! 270: char *b; ! 271: ! 272: for (b = a; *b; b++); ! 273: return (b - a); ! 274: } ! 275: ! 276: char * ! 277: move (a, b) ! 278: char *a, *b; ! 279: { ! 280: while (*b++ = *a++); ! 281: return (b - 1); ! 282: } ! 283: ! 284: should_print () ! 285: { ! 286: short i; ! 287: ! 288: if (buf [rec].ut_name [0] == no) return no; /* a logout entry */ ! 289: if (!**Arg) return yes; /* no arguments? Print all login entries */ ! 290: for (i = 0; i < *Arg [i]; i++) ! 291: { ! 292: if ! 293: ( ! 294: equal (Arg [i], buf[rec].ut_name) ! 295: || ! 296: equal (Arg [i], buf[rec].ut_line) ! 297: ) ! 298: return yes; ! 299: } ! 300: return no; ! 301: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.