|
|
1.1 ! root 1: # ! 2: ! 3: /* ! 4: * last command ! 5: */ ! 6: ! 7: # include <stdio.h> ! 8: # include <sys/types.h> ! 9: # include <sys/acct.h> ! 10: # include <signal.h> ! 11: # include <pwd.h> ! 12: # include <stat.h> ! 13: ! 14: # define N_USER 1000 ! 15: ! 16: struct acct acct_buff [BUFSIZ / sizeof (struct acct)]; ! 17: ! 18: char yes = 1, ! 19: no = 0, ! 20: ! 21: user_list [1000][9]; ! 22: ! 23: time_t expand (); ! 24: ! 25: struct passwd ! 26: *passwd, ! 27: *getpwent (); ! 28: ! 29: struct stat stat_buff; ! 30: ! 31: main (argc, argv) ! 32: char **argv; ! 33: { ! 34: char acct_desc, ! 35: *p; ! 36: ! 37: long i, ! 38: j, ! 39: i_block, ! 40: n_blocks, ! 41: n_byte, ! 42: n_entry; ! 43: ! 44: float x; ! 45: ! 46: /* ! 47: * set up user names ! 48: */ ! 49: while (passwd = getpwent ()) ! 50: { ! 51: move (passwd->pw_name, user_list [passwd->pw_uid]); ! 52: } ! 53: ! 54: acct_desc = open ("/usr/adm/acct", 0); ! 55: if (acct_desc < 0) ! 56: { ! 57: perror ("/usr/adm/acct"); ! 58: return; ! 59: } ! 60: fstat (acct_desc, &stat_buff); ! 61: n_blocks = (stat_buff.st_size + BUFSIZ - 1) / BUFSIZ; ! 62: ! 63: /* ! 64: * read one block's worth ! 65: */ ! 66: for (i_block = n_blocks - 1; i_block >= 0; i_block--) ! 67: { ! 68: lseek (acct_desc, i_block * BUFSIZ, 0); ! 69: n_byte = read (acct_desc, acct_buff, BUFSIZ); ! 70: n_entry = n_byte / sizeof acct_buff [0]; ! 71: for (i = n_entry - 1; i >= 0; i--) ! 72: { ! 73: if (!*user_list [acct_buff [i].ac_uid]) continue; ! 74: /* ! 75: * get the times ! 76: */ ! 77: x = expand (acct_buff [i].ac_utime) ! 78: + ! 79: expand (acct_buff [i].ac_stime); ! 80: /* ! 81: * null terminate the command name ! 82: */ ! 83: acct_buff [i].ac_comm [10] = 0; ! 84: /* ! 85: * replace missing command names with question marks ! 86: */ ! 87: if (!*acct_buff [i].ac_comm) ! 88: { ! 89: move ("?", acct_buff [i].ac_comm); ! 90: } ! 91: /* ! 92: * replace control characters with question marks ! 93: */ ! 94: for (p = acct_buff [i].ac_comm; *p; p++) ! 95: { ! 96: if (*p < '!' || '~' < *p) *p = '?'; ! 97: } ! 98: for (j = 1; j < argc; j++) ! 99: { ! 100: if ! 101: ( ! 102: equal (acct_buff [i].ac_comm, argv [j]) ! 103: || ! 104: equal ! 105: ( ! 106: user_list [acct_buff [i].ac_uid], ! 107: argv [j] ! 108: ) ! 109: ) ! 110: { ! 111: break; ! 112: } ! 113: } ! 114: if (argc == 1 || j != argc) ! 115: { ! 116: printf ! 117: ( ! 118: "%-10s %-8s %6.2f %.16s\n", ! 119: acct_buff [i].ac_comm, ! 120: user_list [acct_buff [i].ac_uid], ! 121: x / 60.0, ! 122: ctime (&acct_buff [i].ac_btime) ! 123: ); ! 124: } ! 125: } ! 126: } ! 127: } ! 128: ! 129: time_t ! 130: expand (t) ! 131: unsigned t; ! 132: { ! 133: register time_t nt; ! 134: ! 135: nt = t & 017777; ! 136: t >>= 13; ! 137: while (t) ! 138: { ! 139: t--; ! 140: nt <<= 3; ! 141: } ! 142: return (nt); ! 143: } ! 144: ! 145: move (a, b) ! 146: char *a, *b; ! 147: { ! 148: while (*b++ = *a++); ! 149: } ! 150: ! 151: equal (a, b) ! 152: char *a, *b; ! 153: { ! 154: for (;; a++, b++) ! 155: { ! 156: if (*a != *b) return no; ! 157: if (!*a) return yes; ! 158: } ! 159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.