From c3db12b88fda05670222f143a68755bb673c0a31 Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 8 Apr 1998 02:50:27 +0000 Subject: [PATCH 1/1] As submitted as bug and sent to PJB and RJK. --- cprogs/.cvsignore | 1 + cprogs/Makefile | 6 + cprogs/acctdump.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++ cprogs/myopt.c | 81 ++++++++++++ cprogs/myopt.h | 42 +++++++ 5 files changed, 441 insertions(+) create mode 100644 cprogs/.cvsignore create mode 100644 cprogs/Makefile create mode 100644 cprogs/acctdump.c create mode 100644 cprogs/myopt.c create mode 100644 cprogs/myopt.h diff --git a/cprogs/.cvsignore b/cprogs/.cvsignore new file mode 100644 index 0000000..f750d64 --- /dev/null +++ b/cprogs/.cvsignore @@ -0,0 +1 @@ +acctdump diff --git a/cprogs/Makefile b/cprogs/Makefile new file mode 100644 index 0000000..48e6d93 --- /dev/null +++ b/cprogs/Makefile @@ -0,0 +1,6 @@ +CC= gcc -g -Wall +CFLAGS= -Werror -Wstrict-prototypes -Wmissing-prototypes \ + -Wwrite-strings -Wpointer-arith $(OPTIMISE) +OPTIMISE=-O2 + +acctdump: acctdump.o myopt.o diff --git a/cprogs/acctdump.c b/cprogs/acctdump.c new file mode 100644 index 0000000..2bc85f3 --- /dev/null +++ b/cprogs/acctdump.c @@ -0,0 +1,311 @@ +/* + * acctdump.c - accounting data dump utility + * + * Copyright (C) 1998 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "myopt.h" + +static int forwards, nobanner, usestdin, raw, usages; + +static int de_used, de_allocd; +static struct deventry { + const char *fn; + dev_t dev; +} *deventries; + +static const struct cmdinfo cmdinfos[]= { + { "--forwards", 'f', 0, &forwards, 0, 0, 1, 0, 0 }, + { "--no-banner", 'q', 0, &nobanner, 0, 0, 1, 0, 0 }, + { "--stdin", 'p', 0, &usestdin, 0, 0, 1, 0, 0 }, + { "--raw", 'r', 0, &raw, 0, 0, 1, 0, 0 }, + { "--resource", 'u', 0, &usages, 0, 0, 1, 0, 0 }, + { 0 } +}; + +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" +}; + +static void usage(FILE *file) { + 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); +} + +static void checkstdout(void) { + if (ferror(stdout)) { perror("stdout"); exit(8); } +} + +static void scandev(const char *basename, int levelsleft) { + /* We deliberately ignore most errors */ + DIR *dir; + struct dirent *de; + struct stat stab; + int fnbufalloc, fnbufreq, r, basel, nallocd; + char *fnbuf, *nfnbuf; + struct deventry *ndeventries; + + if (levelsleft==0) return; + + dir= opendir(basename); if (!dir) return; + fnbufalloc= 0; + fnbuf= 0; + basel= strlen(basename); + + while ((de= readdir(dir))) { + fnbufreq= basel+1+strlen(de->d_name)+1; + if (fnbufallocd_name); + r= lstat(fnbuf,&stab); + if (S_ISCHR(stab.st_mode)) { + if (de_used >= de_allocd) { + nallocd= (de_allocd+10)<<1; + ndeventries= realloc(deventries,nallocd*sizeof(*deventries)); + if (!ndeventries) continue; + de_allocd= nallocd; + deventries= ndeventries; + } + deventries[de_used].fn= strdup(fnbuf+5); /* remove /dev */ + if (!deventries[de_used].fn) continue; + deventries[de_used].dev= stab.st_rdev; + de_used++; + } else if (S_ISDIR(stab.st_mode) && de->d_name[0] != '.') { + scandev(fnbuf,levelsleft-1); + } + } + closedir(dir); + free(fnbuf); +} + +static int walkdev_cptr(const void *av, const void *bv) { + const struct deventry *a= av; + const struct deventry *b= bv; + return a->dev - b->dev; +} + +static void printbanner(void) { + if (raw) { + fputs("begin date command " + "uid gid tty dev FSDX exit", + stdout); + } else { + fputs("begin date and time command " + "user group tty dev FSDX sigexit", + stdout); + } + if (usages) { + fputs(" user time sys time elap time minflt maxflt", + stdout); + } + putchar('\n'); + checkstdout(); +} + +static void printrecord(const struct acct *as, const char *filename) { + static int walkeddev; + + int i, dc, r; + const char *fp; + char buf[100]; + struct tm *tm; + struct deventry *deve, devlookfor; + struct passwd *pw; + struct group *gr; + + 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; + printf("%19s ",buf); + } + + printf("%-16.16s ", as->ac_comm); + + pw= raw ? 0 : getpwuid(as->ac_uid); + if (pw) printf("%-8s ",pw->pw_name); + else printf("%-8ld ",(long)as->ac_uid); + + gr= raw ? 0 : getgrgid(as->ac_gid); + if (gr) printf("%-8s ",gr->gr_name); + else printf("%-8ld ",(long)as->ac_gid); + + if (raw) { + if (as->ac_tty == (dev_t)-1) { + printf("- "); + } else { + printf("%08lx ",(unsigned long)as->ac_tty); + } + } else { + if (as->ac_tty == (dev_t)-1) { + printf("- "); + } else { + if (!walkeddev) { + scandev("/dev",4); + qsort(deventries,de_used,sizeof(*deventries),walkdev_cptr); + walkeddev= 1; + } + devlookfor.fn= 0; + devlookfor.dev= as->ac_tty; + deve= bsearch(&devlookfor,deventries,de_used,sizeof(*deventries),walkdev_cptr); + if (deve) { + printf("%-10s ",deve->fn); + } else { + printf("%08lx ",(unsigned long)as->ac_tty); + } + } + } + + r= as->ac_flag; + for (i=1, fp= "FSDX"; *fp; fp++, i<<=1) { + if (r&i) { + putchar(*fp); + r &= ~i; + } else { + putchar(' '); + } + } + if (r) { + printf("#%x",r); + } + putchar(' '); + + dc= WCOREDUMP(as->ac_exitcode) ? 'd' : 'k'; + if (raw) { + if (WIFEXITED(as->ac_exitcode)) { + printf(" %3d",WEXITSTATUS(as->ac_exitcode)); + } else if (WIFSIGNALED(as->ac_exitcode)) { + printf("%c%3d", + dc, + WTERMSIG(as->ac_exitcode)); + } else { + printf("%04lx",(unsigned long)as->ac_exitcode); + } + } else { + if (WIFEXITED(as->ac_exitcode)) { + printf(" %6d",WEXITSTATUS(as->ac_exitcode)); + } else if (WIFSIGNALED(as->ac_exitcode)) { + r= WTERMSIG(as->ac_exitcode); + if (r>0 && r<=sizeof(sigabbrev)/sizeof(*sigabbrev)) { + printf("%c%6s", + dc, + sigabbrev[r-1]); + } else { + printf("%cSIG%-3d", + dc, + r); + } + } else { + printf("#%04lx",(unsigned long)as->ac_exitcode); + } + } + + if (usages) { + printf(" %10lu %10lu %10lu %8ld %8ld", + (unsigned long)as->ac_utime, + (unsigned long)as->ac_stime, + (unsigned long)as->ac_etime, + (unsigned long)as->ac_minflt, + (unsigned long)as->ac_majflt); + } + putchar('\n'); + + checkstdout(); +} + +static void processfile(FILE *file, const char *filename) { + fpos_t pos; + struct acct as; + int r; + + if (forwards) { + while ((r= fread(&as,1,sizeof(as),file)) == sizeof(as)) { + printrecord(&as,filename); + } + } else { + r= fseek(file,0,SEEK_END); if (r) { perror(filename); exit(8); } + r= fgetpos(file,&pos); if (r) { perror(filename); exit(8); } + for (;;) { + if (pos"); + } else if (!*argv) { + processnamedfile("/var/account/pacct"); + } else { + while (*argv) { + processnamedfile(*argv); + argv++; + } + } + checkstdout(); + if (fflush(stdout)) { perror("flush stdout"); exit(8); } + return 0; +} diff --git a/cprogs/myopt.c b/cprogs/myopt.c new file mode 100644 index 0000000..e776f92 --- /dev/null +++ b/cprogs/myopt.c @@ -0,0 +1,81 @@ +/* + * myopt.c - my very own option parsing + * + * Copyright (C) 1994,1995,1998 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "myopt.h" + +void myopt(const char *const **argvp, const struct cmdinfo *cmdinfos) { + const struct cmdinfo *cip; + const char *p, *value; + int l; + + ++(*argvp); + while ((p= **argvp) && *p == '-') { + ++(*argvp); + if (!strcmp(p,"--")) break; + if (*++p == '-') { + ++p; value=0; + for (cip= cmdinfos; + cip->olong || cip->oshort; + cip++) { + if (!cip->olong) continue; + if (!strcmp(p,cip->olong)) break; + l= strlen(cip->olong); + if (!strncmp(p,cip->olong,l) && + (p[l]== ((cip->takesvalue==2) ? '-' : '='))) { value=p+l+1; break; } + } + if (!cip->olong) badusage("unknown option --%s",p); + if (cip->takesvalue) { + if (!value) { + value= *(*argvp)++; + if (!value) badusage("--%s option takes a value",cip->olong); + } + if (cip->call) cip->call(cip,value); + else *cip->sassignto= value; + } else { + if (value) badusage("--%s option does not take a value",cip->olong); + if (cip->call) cip->call(cip,0); + else *cip->iassignto= cip->arg; + } + } else { + while (*p) { + for (cip= cmdinfos; (cip->olong || cip->oshort) && *p != cip->oshort; cip++); + if (!cip->oshort) badusage("unknown option -%c",*p); + p++; + if (cip->takesvalue) { + if (!*p) { + value= *(*argvp)++; + if (!value) badusage("-%c option takes a value",cip->oshort); + } else { + value= p; p=""; + if (*value == '=') value++; + } + if (cip->call) cip->call(cip,value); + else *cip->sassignto= value; + } else { + if (*p == '=') badusage("-%c option does not take a value",cip->oshort); + if (cip->call) cip->call(cip,0); + else *cip->iassignto= cip->arg; + } + } + } + } +} diff --git a/cprogs/myopt.h b/cprogs/myopt.h new file mode 100644 index 0000000..227d108 --- /dev/null +++ b/cprogs/myopt.h @@ -0,0 +1,42 @@ +/* + * myopt.h - declarations for my very own option parsing + * + * Copyright (C) 1994,1995,1998 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef MYOPT_H +#define MYOPT_H + +typedef void (*voidfnp)(void); + +struct cmdinfo { + const char *olong; + char oshort; + int takesvalue; /* 0 = normal 1 = standard value 2 = option string cont */ + int *iassignto; + const char **sassignto; + void (*call)(const struct cmdinfo*, const char *value); + int arg; + void *parg; + voidfnp farg; +}; + +void myopt(const char *const **argvp, const struct cmdinfo *cmdinfos); + +void badusage(const char *fmt, ...); + +#endif /* MYOPT_H */ -- 2.30.2