Extra MAIL messages (cobwebs)
Don Gworek
uggworek at sunybcs.UUCP
Sat Sep 21 21:42:38 AEST 1985
> 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 <sys/param.h>
X#include <stdio.h>
X#include <sys/dir.h>
X#include <sys/stat.h>
X#include <lastlog.h>
X#include <pwd.h>
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
More information about the Comp.unix.wizards
mailing list