Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/5/84; site sunybcs.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!harvard!seismo!rochester!rocksanne!sunybcs!uggworek From: uggworek@sunybcs.UUCP (Don Gworek) Newsgroups: net.wanted.sources,net.unix-wizards Subject: Re: Extra MAIL messages (cobwebs) Message-ID: <2281@sunybcs.UUCP> Date: Sat, 21-Sep-85 07:42:38 EDT Article-I.D.: sunybcs.2281 Posted: Sat Sep 21 07:42:38 1985 Date-Received: Wed, 25-Sep-85 03:39:13 EDT References: <10283@ucbvax.ARPA> <1161@srcsip.UUCP> Organization: SUNY/Buffalo Computer Science Lines: 395 Xref: watmath net.wanted.sources:1352 net.unix-wizards:14961 > On our system we have a problem of defined users not reading their mail > messages and since we have many people, our disk gets filled up. > > Any programs or ideas would be appreciated. Thank you very much. Here's a handy little program that points out the mailboxes which are unusually large or unusually old -- cobwebs # To unbundle, sh this file. This archive contains: # cobwebs.l cobwebs.c echo Extracting\: cobwebs.l sed 's/^X//' >cobwebs.l <<'E*O*F cobwebs.l' X.TH COBWEBS l "21 September 1985" X.SH NAME Xcobwebs - check for unusually large or old mailboxes X.SH SYNOPSIS X.B cobwebs X[ X-glq X] X[ X-d days X] X[ X-s size X] X[ Xusername ... X] X.PP X.SH DESCRIPTION X.I Cobwebs Xreports the size and age of system mailboxes, plus Xthe last login time of each mailbox owner. The Xdefault is to report mailboxes which are larger Xthan 40000 bytes. X.SH OPTIONS X.PP X-g General report -- all mailboxes, alphabetically. X.PP X-l Don't report the last login time (program runs faster). X.PP X-q Quiet option -- no top banner. X.PP X-d Report mailboxes older than this age in days. X.PP X-s Report mailboxes larger than this size in bytes. X.SH FILES X/usr/spool/mail /etc/passwd /usr/adm/lastlog X.SH AUTHOR XDon Gworek E*O*F cobwebs.l ls -lg cobwebs.l echo Extracting\: cobwebs.c sed 's/^X//' >cobwebs.c <<'E*O*F cobwebs.c' X#ifndef lint Xstatic char *sccsid = "@(#)cobwebs.c 1.2 (Don Gworek) 9/21/85"; X#endif X X/* X * cobwebs [-glq] [-d days] [-s size] [username ...] X * X * -g general report -- list all mailboxes, alphabetically X * -l don't read LASTLOG -- program runs faster X * -q quiet flag -- no top banner X * X * -d report mailboxes older than this age in days X * -s report mailboxes larger than this size in bytes X */ X X#include X#include X#include X#include X#include X#include X X#define MAILDIR "/usr/spool/mail" X#define LASTLOG "/usr/adm/lastlog" X#define DEF_SIZE 40000 /* default mbox size limit */ X#define MAXUSERNAMES 400 /* max username args */ X#define MAXPACKS 1000 /* max mailboxes to report */ X#define NMAX 10 /* max username length */ X#define HMAX 10 /* max hostname length */ X#define TRUE 1 X#define FALSE 0 X X/* X * sortf values X */ X#define SIZE 0 X#define ALPHA 1 X#define DAYS 2 X Xstruct packet { X char name[NMAX]; X off_t size; X time_t filetime; X}; Xstruct packet *packs[MAXPACKS]; Xstruct packet **packp = packs; Xstruct packet *calloc (); X Xchar *malloc (), *ctime(), *progname; Xchar usernames[MAXUSERNAMES][NMAX]; X Xint now, scmp(), packcmp(); Xint sizeval = DEF_SIZE; Xint daysval = 0; Xlong dtimeval = 0; X Xint mboxcount = 0; Xint namecount = 0; Xint packcount = 0; Xlong sizeaccum = 0; Xlong ageaccum = 0; X Xint sortf = SIZE; Xint generalf = FALSE; Xint lastlogf = TRUE; Xint quietf = FALSE; X Xint ARGC; /* global argc and argv */ Xchar **ARGV; X Xmain (argc, argv) Xint argc; Xchar *argv[]; X{ X ARGC = argc; X ARGV = argv; X (void) time (&now); X progname = (progname = (char *) rindex (*ARGV, '/')) ? ++progname : *ARGV; X while ((ARGC-- > 0) && (*(*++ARGV) == '-') && getoptions ()); X if (ARGC && !generalf) { X while ((ARGC-- > 0) && (namecount < MAXUSERNAMES)) X (void) strcpy (usernames[namecount++], *ARGV++); X if (namecount >= MAXUSERNAMES) { X fprintf (stderr, "%s: MAXUSERNAMES %d reached\n", X progname, MAXUSERNAMES); X exit (namecount); X } X } X if (namecount) X qsort (usernames, namecount, sizeof usernames[0], scmp); X check_mailboxes (); X printout (); X} X Xgetoptions () { X while (*++(*ARGV)) X switch (**ARGV) { X case '\0': X ARGC--, ARGV++; X return (FALSE); X case 's': X sortf = SIZE; X if ((*++(*ARGV)) || (ARGC-- && *++ARGV && (**ARGV != '-'))) X sizeval = atoi (*ARGV); X else X usage(); X return (TRUE); X case 'd': X sortf = DAYS; X if ((*++(*ARGV)) || (ARGC-- && *++ARGV && (**ARGV != '-'))) X daysval = atoi (*ARGV); X else X usage(); X dtimeval = now - 86400 * daysval; X return (TRUE); X case 'g': X sortf = ALPHA; X generalf = TRUE; X break; X case 'l': X lastlogf = FALSE; X break; X case 'q': X quietf = TRUE; X break; X default: X usage (); X } X return (TRUE); X} X Xstruct stat stbuf; X Xcheck_mailboxes () { X DIR * etc; X struct direct *dp; X if (chdir (MAILDIR) < 0) { X perror (MAILDIR); X exit (1); X } X if ((etc = opendir (".")) == NULL) { X perror (MAILDIR); X exit (1); X } X while (dp = readdir (etc)) { X if (dp -> d_ino == 0) X continue; X if (stat (dp -> d_name, &stbuf) < 0) X continue; X if ((stbuf.st_mode & S_IFMT) == S_IFDIR) X continue; X if (packcount >= MAXPACKS) X fprintf (stderr, "%s: MAXPACKS %d reached\n", progname, MAXPACKS); X if (namecount) { X if (binsearch (dp -> d_name)) { X take_note (dp -> d_name); X if (packcount >= namecount) X return; X } X continue; X } X mboxcount++; X ageaccum += (stbuf.st_ctime - now); X sizeaccum += stbuf.st_size; X if (generalf) { X take_note (dp -> d_name); X continue; X } X switch (sortf) { X case DAYS: X if (stbuf.st_ctime < dtimeval) X take_note (dp -> d_name); X break; X case SIZE: X if (stbuf.st_size > sizeval) X take_note (dp -> d_name); X break; X } X } X} X Xtake_note (name) Xchar *name; X{ X packcount++; X *packp = calloc (1, sizeof (struct packet)); X (void) strcpy ((*packp) -> name, name); X (*packp) -> size = stbuf.st_size; X (*packp) -> filetime = stbuf.st_ctime; X packp++; X} X Xchar agestring[50]; X Xprintout () { X register struct packet **p; X int f; X struct passwd *pwd; X struct lastlog ll; X int i; X char *s, *nowyear; X char host[HMAX]; X if (packcount == 0) { X printf ("No Report.\n"); X return; X } X qsort (packs, packp - packs, sizeof packs[0], packcmp); X s = ctime (&now); X nowyear = s + 20; X if (lastlogf && (f = open (LASTLOG, 0)) < 0) { X perror (LASTLOG); X lastlogf = FALSE; X } X if (!quietf) { X for (i = 65; i-- > 0; putchar ('-')); X putchar ('\n'); X (void) gethostname (host, 10); X printf ("%10s %.12s %d Mailbox%s", X host, (s + 4), packcount, (packcount==1) ? " " : "es"); X if (!generalf && !namecount) X if (sortf == DAYS) X printf (" Older Than %d Days", daysval); X else X if (sortf == SIZE) X printf (" Larger Than %d", sizeval); X putchar ('\n'); X if (!namecount) { X age_is ((ageaccum + now) / mboxcount); X printf ("\nTotal: %d Average Size: %d Average Age:%-16s\n", X mboxcount, (sizeaccum / mboxcount), agestring); X } X printf ("\n NAME MAILBOX SIZE MAILBOX AGE%s\n", X (lastlogf) ? " LAST LOGIN" : ""); X for (i = 65; i-- > 0; putchar ('-')); X putchar ('\n'); X } X for (p = packs; p < packp; p++) { X printf ("%-8s", (*p) -> name); X printf (" %6d ", (*p) -> size); X age_is (now - (*p) -> filetime); X printf ("%-16s", agestring); X if (lastlogf) { X if (((pwd = getpwnam ((*p) -> name)) != NULL) X && (lseek (f, (long) pwd -> pw_uid * X sizeof (struct lastlog), 0) >= 0) X && (read (f, (char *) & ll, sizeof ll) == sizeof ll) X && (ll.ll_time <= 0)) X printf (" no login record"); X else { X s = ctime (&ll.ll_time); X printf (" %.6s", (s + 4)); X if (strncmp (nowyear, (s + 20), 4)) X printf (", %.4s", (s + 20)); X else X printf (" %.5s", (s + 11)); X } X } X putchar ('\n'); X } X (void) close (f); X} X Xage_is (period) Xlong period; X{ X int days, hours; X char temp1[20], temp2[20]; X days = period / 86400; X hours = (period % 86400) / 3600; X if (days) X (void) sprintf (temp1, "%3d Day%s", days, (days == 1) ? " " : "s"); X else X (void) sprintf (temp1, " "); X if (hours) X (void) sprintf (temp2, "%2d Hour%s", hours, (hours == 1) ? " " : "s"); X else X (void) sprintf (temp2, "%2d Mins ", (((period % 86400) % 3600) / 60)); X (void) sprintf (agestring, "%s %s", temp1, temp2); X} X Xbinsearch (target) Xchar *target; X{ X int hi, lo, mid, val; X lo = 0; X hi = namecount - 1; X while (TRUE) X if (hi < lo) X return (FALSE); X else X if ((val = strcmp (target, usernames[(mid = (lo + hi) / 2)])) == 0) X return (TRUE); X else X if (val > 0) X lo = mid + 1; X else X hi = mid - 1; X} X Xscmp (p, q) Xchar *p, *q; X{ X return (strcmp (p, q)); X} X Xpackcmp (p, q) Xstruct packet **p, **q; X{ X switch (sortf) { X case ALPHA: X return (strcmp ((*p) -> name, (*q) -> name)); X case DAYS: X if ((*p) -> filetime == (*q) -> filetime) X return (0); X if ((*p) -> filetime > (*q) -> filetime) X return (1); X return (-1); X case SIZE: X if ((*p) -> size == (*q) -> size) X return (0); X if ((*p) -> size > (*q) -> size) X return (-1); X return (1); X } X return (0); /* keep lint quiet */ X} X Xusage () { X fprintf (stderr, "Usage: %s [-glq] [-d days]", progname); X fprintf (stderr, " [-s size] [username ...]\n"); X exit (1); X} E*O*F cobwebs.c ls -lg cobwebs.c exit 0 Brought to you by Super Global Mega Corp .com