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