[net.wanted.sources] Extra MAIL messages

notch@srcsip.UUCP (Michael k Notch) (09/10/85)

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. 
Does anyone know of a way to set a time limit on how long a mail message
exists?

Any programs or ideas would be appreciated. Thank you very much.
--
    But...   What about Naomi? 

USENET:   ihnp4!umn-cs!srcsip!notch
US-SMAIL: Michael k Notch (The small k is on purpose)
 	   MN17-2349   [1-612-378-5338]
 	   Honeywell Inc. Systems & Research Center
	   2600 Ridgeway Parkway NE
	   Minneapolis, Minnesota 55440
--

ken@rochester.UUCP (Blittermuis) (09/16/85)

In article <1161@srcsip.UUCP> notch@srcsip.UUCP (Michael k Notch) writes:
>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. 
>Does anyone know of a way to set a time limit on how long a mail message
>exists?

In 4.x BSD you could make /usr/spool/mail/<user> a symlink to a file in
the user's directories.

It won't save any disk space but at least it will keep /usr/spool from
overflowing and encourage users to dispose of their mail if you are
imposing quotas.

	Ken
-- 
UUCP: ..!{allegra,decvax,seismo}!rochester!ken ARPA: ken@rochester.arpa
USnail:	Dept. of Comp. Sci., U. of Rochester, NY 14627. Voice: Ken!

Thomas@uwai.UUCP (09/17/85)

***  notch@srcsip.UUCP (Michael k Notch) :
> >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. 
> >Does anyone know of a way to set a time limit on how long a mail message
> >exists?

*** ..!{allegra,decvax,seismo}!rochester!ken ARPA: ken@rochester.arpa :
> In 4.x BSD you could make /usr/spool/mail/<user> a symlink to a file in
> the user's directories.

> It won't save any disk space but at least it will keep /usr/spool from
> overflowing and encourage users to dispose of their mail if you are
> imposing quotas.


this still won't work as is.  sendmail refuses to deliver to a symbolic
link.  or a file with more than one hard link, for that matter.

tom

-- 

Tom Christiansen
University of Wisconsin
Computer Science Systems Lab 
...!{allegra,heurikon,ihnp4,seismo,uwm-evax}!uwvax!tom
tom@wisc-ai.arpa

uggworek@sunybcs.UUCP (Don Gworek) (09/21/85)

> 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

henry@utzoo.UUCP (Henry Spencer) (09/26/85)

> Here's a handy little program that points out the mailboxes
> which are unusually large or unusually old -- cobwebs
> ... [there follows about 300 lines of C]

What's wrong with

	find /usr/spool/mail -type f '(' -size +50 -o -atime +30 ')' -print

(Find all mailboxes which are bigger than 50 blocks or have not been
read in the last 30 days, and print their names.)
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry