Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/5/84; site yale.ARPA Path: utzoo!watmath!clyde!cbosgd!ihnp4!zehntel!dual!amdcad!decwrl!decvax!yale!kaufman From: kaufman@yale.ARPA (Qux the Barbarian) Newsgroups: net.wanted.sources Subject: Re: local netnews usage statistics Message-ID: <6644@yale.ARPA> Date: Sun, 2-Dec-84 22:07:50 EST Article-I.D.: yale.6644 Posted: Sun Dec 2 22:07:50 1984 Date-Received: Tue, 4-Dec-84 19:35:29 EST Reply-To: kaufman@yale-comix.UUCP (Qux the Barbarian) Distribution: net Organization: Cordon Bulldog (Yale School of Strike Survival) Lines: 266 As long as we're all posting our News statistics generators... Unlike the others, this is a C program not a shell script (sorry, Henry!). Since it computes disk usages, it takes a while to run. I run it out of /usr/lib/news/trimlib. shar+enjoy, Qux Kaufman@Yale.Arpa Kaufman@YaleCS.Bitnet ..!decvax!yale!kaufman : to unbundle, "sh" this file -- DO NOT use csh : SHAR archive format. Archive created Sun Dec 2 22:03:08 EST 1984 echo x - ngstats.c sed 's/^X//' >ngstats.c <<'+FUNKY+STUFF+' X#includeX#include X#include X#include X#include X X/* A hack! A hack! My kingdom for a hack! */ X X/* ngstats.c X * X * Generate news readership statistics. Best run by cron, perhaps from X * /usr/lib/news/trimlib. X * X * Written by Qux the Barbarian (Kaufman@Yale.Arpa, Kaufman@YaleCS.Bitnet, X * ..!decvax!yale!kaufman). Hereby placed in the Public Domain, for what X * that's worth; I would appreciate hearing about bugs/fixes/extensions X * and ports to other Operating Systems or versions of Unix. X * X * Tested under 4.2 BSD; should work without changes under 4.1 BSD with the X * ndir upward compatibility routines. X */ X X#define ACTIVE "/usr/lib/news/active" X#define SPOOLDIR "/usr/spool/news" X X#define WEEKS 7 * 24 * 60 * 60 X#define READ_DELTA (2*WEEKS) X/*#define RAPIDOFLEX /* don't actually gather stats */ X Xstruct NG { X char name[100]; X int rdrs; X int first_art; X int last_art; X int du; X int artcnt; X} ngs[512]; X Xint ngcnt = 0, unknownngcnt = 0; Xint cmprdrs = -1; X X#define rdr_du(a) ((a).rdrs ? (a).du / (a).rdrs : (a).du) X Xngcmp(a, b) Xstruct NG *a, *b; { X X if ((cmprdrs && a->rdrs == b->rdrs) || X (!cmprdrs && rdr_du(*a) == rdr_du(*b))) X return(strcmp(a->name, b->name)); X else if (cmprdrs) X return(a->rdrs < b->rdrs ? 1 : -1); X else X return(rdr_du(*a) < rdr_du(*b) ? 1 : -1); X} X Xmain (argc, argv) Xint argc; Xchar **argv; { X struct passwd *pp, *getpwent(); X FILE *fp; X int newsrccnt = 0, i, noreadcnt = 0; X int notreadcnt = 0, norccnt = 0; X int accounts = 0, dusum = 0; X char buf[100], c; X long last_read_time; X X /* set up some time junk */ X time(&last_read_time); X last_read_time -= READ_DELTA; X X /* read in active file */ X if ((fp = fopen(ACTIVE, "r")) == NULL) { X perror(ACTIVE); X exit(1); X } X while (!feof(fp)) { X fscanf(fp, "%s %d %d %c\n", X ngs[ngcnt].name, &ngs[ngcnt].last_art, X &ngs[ngcnt].first_art, &c); X ngs[ngcnt].rdrs = 0; X ngs[ngcnt++].du = 0; X } X fclose(fp); X X /* Compute disk usages (hack hack hack) */ X for (i=0; i pw_dir); X if (access(buf, 0)) X norccnt++; X else { X struct stat stbuf; X X if (!stat(buf, &stbuf) && stbuf.st_mtime < last_read_time) X notreadcnt++; X else if ((fp = fopen(buf, "r")) == NULL) X noreadcnt++; X else { X newsrccnt++; X readnewsrc(fp, buf); X fclose(fp); X } X } X } X X /* sort the stats */ X qsort(ngs, ngcnt, sizeof(struct NG), ngcmp); X X /* Now, print the statistics */ X printf("\nFor %d accounts on system %s:\n", accounts, sysname()); X printf("\t%d have no .newsrc\n", norccnt); X printf("\t%d have an unreadable .newsrc\n", noreadcnt); X printf("\t%d have an out of date .newsrc\n", notreadcnt); X printf("\t%d .newsrc's were read\n", newsrccnt); X printf("\nFor %d newsgroups received:\n", ngcnt); X printf("\t%d unknown newsgroups referenced in .newsrc's read.\n", unknownngcnt); X printf("\t%d blocks total disk usage\n\n", dusum); X puts("Statistics sorted by decreasing number of readers per newsgroup:\n"); X X puts("Readers\t # Articles\tDisk Space\tBlocks/Rdr\tNewsgroup"); X for (i=0; i < ngcnt; i++) X printf("%5d\t %5d\t %6d\t %5d\t\t%s\n", X ngs[i].rdrs, ngs[i].artcnt, X ngs[i].du, rdr_du(ngs[i]), X ngs[i].name); X X X /* resort the stats */ X cmprdrs = 0; X qsort(ngs, ngcnt, sizeof(struct NG), ngcmp); X X /* Do it again sorted differently */ X puts("\nSorted by decreasing number of blocks per newsgroup reader:\n"); X puts("Readers\t # Articles\tDisk Space\tBlocks/Rdr\tNewsgroup"); X for (i=0; i < ngcnt; i++) X printf("%5d\t %5d\t %6d\t %5d\t\t%s\n", X ngs[i].rdrs, ngs[i].artcnt, X ngs[i].du, rdr_du(ngs[i]), X ngs[i].name); X X} X Xreadnewsrc(rcp, filename) Xchar *filename; XFILE *rcp; { X char buf[100], *cp, *index(); X int i; X X#ifdef RAPIDOFLEX X return; X#endif RAPIDOFLEX X X while (fgets(buf, 100, rcp)) { X X if ((cp = index(buf, ':')) == NULL) X continue; X X *cp = '\0'; X for (i = 0; i < ngcnt; i++) X if (!strcmp(buf, ngs[i].name)) { X ngs[i].rdrs++; X break; X } X if (i == ngcnt) X unknownngcnt++; X } X} X Xngdu(ng) Xstruct NG *ng; { X char ngdir[256], ngart[256], *cp; X struct stat stbuf; X DIR *dir; X struct direct *dirent; X int pad = 0; /* hack hack hack */ X int i; X X#ifdef RAPIDOFLEX X return(0); X#endif RAPIDOFLEX X X /* create directory name */ X sprintf(ngdir, "%s/%s", SPOOLDIR, ng->name); X cp = ngdir; X while (cp = index(cp, '.')) X *cp = '/'; X X /* calculate usage of all articles combined */ X if ((dir = opendir(ngdir)) == NULL) { X perror(ngdir); X return(0); X } X seekdir(dir, 2); X while (dirent = readdir(dir)) { X /* skip deleted files */ X if (!dirent->d_ino) X continue; X X /* skip directories */ X sprintf(ngart, "%s/%s", ngdir, dirent->d_name); X if (stat(ngart, &stbuf) || (stbuf.st_mode & S_IFMT) == S_IFDIR) X continue; X X /* increment article count and disk usage */ X ng->artcnt++; X if ((stbuf.st_mode & S_IFMT) == S_IFREG) X ng->du += (stbuf.st_size + 511) / 512; X } X closedir(dir); X X /* compare article counts */ X if (ng->last_art == 0 && ng->first_art == 1) X i = 0; X else X i = ng->last_art - ng->first_art; X if (ng->artcnt != i && ng->artcnt != i+1) { X printf("Article count mismatch for newsgroup %s: ", ng->name); X printf("active claims %d, actual is %d.\n", i, ng->artcnt); X } X return(ng->du); X} +FUNKY+STUFF+ ls -l ngstats.c echo x - sysname.c sed 's/^X//' >sysname.c <<'+FUNKY+STUFF+' X#include X X/* sysname() X * Ala 4.1, but now only an interface to gethostname(). X * David H. Kaufman X */ X X#define SYSNAMELEN 255 Xstatic char systemname[SYSNAMELEN]; X Xchar *sysname() { X if (!*systemname) X if (gethostname(systemname, SYSNAMELEN)) X return(NULL); X X return(systemname); X} +FUNKY+STUFF+ ls -l sysname.c exit 0