1*1886Smark static char *sccsid = "@(#)lastcomm.c 4.2 (Berkeley) 12/14/80"; 21037Sbill # 31037Sbill 41037Sbill /* 51037Sbill * last command 61037Sbill */ 71037Sbill 81037Sbill # include <stdio.h> 91037Sbill # include <sys/types.h> 101037Sbill # include <sys/acct.h> 111037Sbill # include <signal.h> 121037Sbill # include <pwd.h> 131037Sbill # include <stat.h> 141037Sbill 151037Sbill # define N_USER 1000 161037Sbill 171037Sbill struct acct acct_buff [BUFSIZ / sizeof (struct acct)]; 181037Sbill 191037Sbill char yes = 1, 201037Sbill no = 0, 211037Sbill 221037Sbill user_list [1000][9]; 231037Sbill 241037Sbill time_t expand (); 251037Sbill 261037Sbill struct passwd 271037Sbill *passwd, 281037Sbill *getpwent (); 291037Sbill 301037Sbill struct stat stat_buff; 311037Sbill 321037Sbill main (argc, argv) 331037Sbill char **argv; 341037Sbill { 351037Sbill char acct_desc, 361037Sbill *p; 371037Sbill 381037Sbill long i, 391037Sbill j, 401037Sbill i_block, 411037Sbill n_blocks, 421037Sbill n_byte, 431037Sbill n_entry; 441037Sbill 451037Sbill float x; 461037Sbill 471037Sbill /* 481037Sbill * set up user names 491037Sbill */ 501037Sbill while (passwd = getpwent ()) 511037Sbill { 52*1886Smark if (user_list[passwd->pw_uid][0]) 53*1886Smark move (passwd->pw_name, user_list [passwd->pw_uid]); 541037Sbill } 551037Sbill 561037Sbill acct_desc = open ("/usr/adm/acct", 0); 571037Sbill if (acct_desc < 0) 581037Sbill { 591037Sbill perror ("/usr/adm/acct"); 601037Sbill return; 611037Sbill } 621037Sbill fstat (acct_desc, &stat_buff); 631037Sbill n_blocks = (stat_buff.st_size + BUFSIZ - 1) / BUFSIZ; 641037Sbill 651037Sbill /* 661037Sbill * read one block's worth 671037Sbill */ 681037Sbill for (i_block = n_blocks - 1; i_block >= 0; i_block--) 691037Sbill { 701037Sbill lseek (acct_desc, i_block * BUFSIZ, 0); 711037Sbill n_byte = read (acct_desc, acct_buff, BUFSIZ); 721037Sbill n_entry = n_byte / sizeof acct_buff [0]; 731037Sbill for (i = n_entry - 1; i >= 0; i--) 741037Sbill { 751037Sbill if (!*user_list [acct_buff [i].ac_uid]) continue; 761037Sbill /* 771037Sbill * get the times 781037Sbill */ 791037Sbill x = expand (acct_buff [i].ac_utime) 801037Sbill + 811037Sbill expand (acct_buff [i].ac_stime); 821037Sbill /* 831037Sbill * null terminate the command name 841037Sbill */ 851037Sbill acct_buff [i].ac_comm [10] = 0; 861037Sbill /* 871037Sbill * replace missing command names with question marks 881037Sbill */ 891037Sbill if (!*acct_buff [i].ac_comm) 901037Sbill { 911037Sbill move ("?", acct_buff [i].ac_comm); 921037Sbill } 931037Sbill /* 941037Sbill * replace control characters with question marks 951037Sbill */ 961037Sbill for (p = acct_buff [i].ac_comm; *p; p++) 971037Sbill { 981037Sbill if (*p < '!' || '~' < *p) *p = '?'; 991037Sbill } 1001037Sbill for (j = 1; j < argc; j++) 1011037Sbill { 1021037Sbill if 1031037Sbill ( 1041037Sbill equal (acct_buff [i].ac_comm, argv [j]) 1051037Sbill || 1061037Sbill equal 1071037Sbill ( 1081037Sbill user_list [acct_buff [i].ac_uid], 1091037Sbill argv [j] 1101037Sbill ) 1111037Sbill ) 1121037Sbill { 1131037Sbill break; 1141037Sbill } 1151037Sbill } 1161037Sbill if (argc == 1 || j != argc) 1171037Sbill { 1181037Sbill printf 1191037Sbill ( 1201037Sbill "%-10s %-8s %6.2f %.16s\n", 1211037Sbill acct_buff [i].ac_comm, 1221037Sbill user_list [acct_buff [i].ac_uid], 1231037Sbill x / 60.0, 1241037Sbill ctime (&acct_buff [i].ac_btime) 1251037Sbill ); 1261037Sbill } 1271037Sbill } 1281037Sbill } 1291037Sbill } 1301037Sbill 1311037Sbill time_t 1321037Sbill expand (t) 1331037Sbill unsigned t; 1341037Sbill { 1351037Sbill register time_t nt; 1361037Sbill 1371037Sbill nt = t & 017777; 1381037Sbill t >>= 13; 1391037Sbill while (t) 1401037Sbill { 1411037Sbill t--; 1421037Sbill nt <<= 3; 1431037Sbill } 1441037Sbill return (nt); 1451037Sbill } 1461037Sbill 1471037Sbill move (a, b) 1481037Sbill char *a, *b; 1491037Sbill { 1501037Sbill while (*b++ = *a++); 1511037Sbill } 1521037Sbill 1531037Sbill equal (a, b) 1541037Sbill char *a, *b; 1551037Sbill { 1561037Sbill for (;; a++, b++) 1571037Sbill { 1581037Sbill if (*a != *b) return no; 1591037Sbill if (!*a) return yes; 1601037Sbill } 1611037Sbill } 162