X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=blobdiff_plain;f=cprogs%2Facctdump.c;h=b9040ac710f91eebe6a83af73262a2027a4e4e29;hp=2bc85f350269806a3359131da082551a21e717fa;hb=b075ddbfbdbf7d15d9f0c43d7316533cf9ed6229;hpb=c3db12b88fda05670222f143a68755bb673c0a31 diff --git a/cprogs/acctdump.c b/cprogs/acctdump.c index 2bc85f3..b9040ac 100644 --- a/cprogs/acctdump.c +++ b/cprogs/acctdump.c @@ -28,9 +28,41 @@ #include #include #include +#include #include + +typedef unsigned long long u64; + + +/* Sadly this thing is not very portable */ + +#if defined(__linux__) + +#include +#include + +typedef struct acct_v3 struct_acct; +#define HAVE_AC_EXITCODE +#define HAVE_AC_FLT +#define FIELD_AC_FLAG(as) ((as)->ac_flag) + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + +#include +#include #include +typedef struct acctv2 struct_acct; +#define HAVE_AC_IO_MEM +#define FIELD_AC_FLAG(as) ((as)->ac_flagx & ~ANVER) + +#else + +#error Do not know what struct_acct to use on this platform + +#endif + + #include "myopt.h" static int forwards, nobanner, usestdin, raw, usages; @@ -50,30 +82,20 @@ static const struct cmdinfo cmdinfos[]= { { 0 } }; +#ifdef HAVE_AC_EXITCODE static const char *sigabbrev[]= { "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO" }; +#endif -static void usage(FILE *file) { +void usagemessage(void) { fputs("usage: acctdump [] [ ...]\n" "options: -f|--forwards -q|--no-banner -p|--stdin -r|--raw -u|--resource\n", - file); - if (ferror(file)) { perror("print usage"); exit(8); } -} - -void badusage(const char *fmt, ...) { - va_list al; - - fputs("usage error: ",stderr); - va_start(al,fmt); - vfprintf(stderr,fmt,al); - va_end(al); - fputs("\n",stderr); - usage(stderr); - exit(12); + stderr); + if (ferror(stderr)) { perror("print usage"); exit(8); } } static void checkstdout(void) { @@ -91,12 +113,16 @@ static void scandev(const char *basename, int levelsleft) { if (levelsleft==0) return; - dir= opendir(basename); if (!dir) return; + dir= opendir(basename); + if (!dir) { + fprintf(stderr, "%s: opendir: %s\n", basename, strerror(errno)); + return; + } fnbufalloc= 0; fnbuf= 0; basel= strlen(basename); - while ((de= readdir(dir))) { + while ((errno=0, de= readdir(dir))) { fnbufreq= basel+1+strlen(de->d_name)+1; if (fnbufallocd_name); r= lstat(fnbuf,&stab); + if (r) { + fprintf(stderr, "%s: %s\n", fnbuf, strerror(errno)); + continue; + } if (S_ISCHR(stab.st_mode)) { if (de_used >= de_allocd) { nallocd= (de_allocd+10)<<1; @@ -122,6 +152,8 @@ static void scandev(const char *basename, int levelsleft) { scandev(fnbuf,levelsleft-1); } } + if (errno) + fprintf(stderr, "%s: readdir: %s\n", basename, strerror(errno)); closedir(dir); free(fnbuf); } @@ -135,41 +167,64 @@ static int walkdev_cptr(const void *av, const void *bv) { static void printbanner(void) { if (raw) { fputs("begin date command " - "uid gid tty dev FSDX exit", - stdout); + "uid gid tty dev FSDX " +#ifdef HAVE_AC_EXITCODE + "exit" +#endif + , stdout); } else { fputs("begin date and time command " - "user group tty dev FSDX sigexit", - stdout); + "user group tty dev FSDX " +#ifdef HAVE_AC_EXITCODE + "sigexit" +#endif + , stdout); } if (usages) { - fputs(" user time sys time elap time minflt maxflt", - stdout); + fputs(" user time sys time elap time " +#ifdef HAVE_AC_FLT + " minflt maxflt" +#endif +#ifdef HAVE_AC_IO_MEM + " avg.mem io" +#endif + , stdout); } putchar('\n'); checkstdout(); } -static void printrecord(const struct acct *as, const char *filename) { +static void printrecord(const struct_acct *as, const char *filename) { static int walkeddev; - int i, dc, r; + int i, r; const char *fp; char buf[100]; struct tm *tm; struct deventry *deve, devlookfor; struct passwd *pw; struct group *gr; + time_t btime; + char commbuf[sizeof(as->ac_comm)]; if (raw) { printf("%10lu ",(unsigned long)as->ac_btime); } else { - tm= localtime(&as->ac_btime); - strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",tm); buf[sizeof(buf)-1]= 0; + btime= as->ac_btime; + tm= localtime(&btime); + if (tm) { + strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",tm); buf[sizeof(buf)-1]= 0; + } else { + snprintf(buf,sizeof(buf),"@%lu",(unsigned long)btime); + } printf("%19s ",buf); } - - printf("%-16.16s ", as->ac_comm); + + for (i=0; iac_comm); i++) { + int c=as->ac_comm[i]; + commbuf[i]= ((c!=0 && c<=32) || c>=127) ? '?' : c; + } + printf("%-*.*s ", (int)sizeof(commbuf),(int)sizeof(commbuf), commbuf); pw= raw ? 0 : getpwuid(as->ac_uid); if (pw) printf("%-8s ",pw->pw_name); @@ -180,13 +235,13 @@ static void printrecord(const struct acct *as, const char *filename) { else printf("%-8ld ",(long)as->ac_gid); if (raw) { - if (as->ac_tty == (dev_t)-1) { + if (!(as->ac_tty + 1) /* check for -1 without knowing type */) { printf("- "); } else { printf("%08lx ",(unsigned long)as->ac_tty); } } else { - if (as->ac_tty == (dev_t)-1) { + if (!(as->ac_tty + 1)) { printf("- "); } else { if (!walkeddev) { @@ -205,12 +260,12 @@ static void printrecord(const struct acct *as, const char *filename) { } } - r= as->ac_flag; - for (i=1, fp= "FSDX"; *fp; fp++, i<<=1) { + r= FIELD_AC_FLAG(as); + for (i=1, fp= "FS4DX"; *fp; fp++, i<<=1) { if (r&i) { putchar(*fp); r &= ~i; - } else { + } else if (!isdigit(*fp)) { putchar(' '); } } @@ -218,7 +273,9 @@ static void printrecord(const struct acct *as, const char *filename) { printf("#%x",r); } putchar(' '); - + +#ifdef HAVE_AC_EXITCODE + int dc; dc= WCOREDUMP(as->ac_exitcode) ? 'd' : 'k'; if (raw) { if (WIFEXITED(as->ac_exitcode)) { @@ -248,14 +305,23 @@ static void printrecord(const struct acct *as, const char *filename) { printf("#%04lx",(unsigned long)as->ac_exitcode); } } +#endif /*HAVE_AC_EXITCODE*/ if (usages) { - printf(" %10lu %10lu %10lu %8ld %8ld", + printf(" %10lu %10lu %10lu", (unsigned long)as->ac_utime, (unsigned long)as->ac_stime, - (unsigned long)as->ac_etime, + (unsigned long)as->ac_etime); +#ifdef HAVE_AC_FLT + printf(" %8lu %8lu", (unsigned long)as->ac_minflt, (unsigned long)as->ac_majflt); +#endif +#ifdef HAVE_AC_IO_MEM + printf(" %4e %4e", + as->ac_mem, + as->ac_io); +#endif } putchar('\n'); @@ -263,8 +329,8 @@ static void printrecord(const struct acct *as, const char *filename) { } static void processfile(FILE *file, const char *filename) { - fpos_t pos; - struct acct as; + struct_acct as; + long pos; int r; if (forwards) { @@ -273,11 +339,16 @@ static void processfile(FILE *file, const char *filename) { } } else { r= fseek(file,0,SEEK_END); if (r) { perror(filename); exit(8); } - r= fgetpos(file,&pos); if (r) { perror(filename); exit(8); } + pos= ftell(file); if (pos==-1) { perror(filename); exit(8); } + if (pos % sizeof(as)) { + fprintf(stderr, "%s: File size is not an integral number " + "of accounting records\n", filename); + exit(8); + } for (;;) { if (pos"); } else if (!*argv) { - processnamedfile("/var/account/pacct"); + processnamedfile("/var/log/account/pacct"); } else { while (*argv) { processnamedfile(*argv);