[comp.sources.unix] v18i001: Display mail queue and "from" output

rsalz@uunet.uu.net (Rich Salz) (03/07/89)

Submitted-by: Kevin Sweet <sweet@scubed.arpa>
Posting-number: Volume 18, Issue 2
Archive-name: mq

Replacements for mailq and from:

mq -	selectively display the mail queue. 
	options exist to list mail from or to a particular site, list 
	mail exclusive of a particular site, and list mail without the 
	truncation of long pathnames.

from -	makes `from' output look somewhat like `Mail' "header" output 
	in that it prints out a minimalistic pathname to the sender and 
	the subject line. It catches subject titles that `Mail' some-
	times misses like news articles saved in mbox format. 

I have listed the machine/OS combinations (BSD/SysV) that I have 
successfully compiled and run the programs in the Makefile. 

One comment, however.  No checking is done with respect to what other 
programs (or users) are doing to the mail queue files and mailboxes. 
(I have received segmentation faults _occasionally_ when, I assume, 
 `sendmail' is deleting a file that `mq' wants to read. I'm a scientific
 programmer that did this for "fun" and don't know what to do about this
 situation. `From' seems to be pretty resilient, though.)

Kevin Sweet
--
Kevin Sweet ----------------------------------------- sweet@scubed.arpa
S-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095, (619)587-8499
(home)  12205 Carmel Vista 242, San Diego, CA 92130-2237, (619)259-9338
UUCP/ARPA:            [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet
DECNET:                         SDSC::"SWEET@S3VAX.SPAN" , 1.312::SWEET

#---cut here---cut here---cut here---cut here---cut here---cut here---
#! /bin/sh
# This is a shell archive, meaning:
#     1. Remove everything above the #! /bin/sh line.
#     2. Save the resulting text in a file.
#     3. Execute the file with /bin/sh (not csh) to create:
#        README
#        Makefile
#        mq.c
#        from.c
#        from.1
#        mq.8
#
echo shar: extracting "README" '(1426 characters)'
if test -f README
then
  echo shar: will not over-write existing file "README"
else
sed 's/^XX//' << \SHAR_EOF > README
XXReplacements for mailq and from:
XX
XXmq -	selectively display the mail queue. 
XX	options exist to list mail from or to a particular site, list 
XX	mail exclusive of a particular site, and list mail without the 
XX	truncation of long pathnames.
XX
XXfrom -	makes `from' output look somewhat like `Mail' "header" output 
XX	in that it prints out a minimalistic pathname to the sender and 
XX	the subject line. It catches subject titles that `Mail' some-
XX	times misses like news articles saved in mbox format. 
XX
XXI have listed the machine/OS combinations (BSD/SysV) that I have 
XXsuccessfully compiled and run the programs in the Makefile. 
XX
XXOne comment, however.  No checking is done with respect to what other 
XXprograms (or users) are doing to the mail queue files and mailboxes. 
XX(I have received segmentation faults _occasionally_ when, I assume, 
XX `sendmail' is deleting a file that `mq' wants to read. I'm a scientific
XX programmer that did this for "fun" and don't know what to do about this
XX situation. `From' seems to be pretty resilient, though.)
XX
XXKevin Sweet, 22 April 1988
XX--
XXKevin Sweet ----------------------------------------- sweet@scubed.arpa
XXS-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095, (619)587-8499
XX(home)  12205 Carmel Vista 242, San Diego, CA 92130-2237, (619)259-9338
XXUUCP/ARPA:            [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet
XXDECNET:                         SDSC::"SWEET@S3VAX.SPAN" , 1.312::SWEET
SHAR_EOF
if test 1426 -ne "`wc -c < README`"
then
  echo shar: error transmitting "README" '(should have been 1426 characters)'
fi
fi # end of overwriting check
echo shar: extracting "Makefile" '(1345 characters)'
if test -f Makefile
then
  echo shar: will not over-write existing file "Makefile"
else
sed 's/^XX//' << \SHAR_EOF > Makefile
XX# `C' compiler void compatibility
XXVOID='-DVOID=(void)'
XX
XX# BSD compatibility
XX# kelvin.arpa: Celerity C1230/C1260 UNIX 3.4.78
XX# scubed.arpa: Ultrix V2.0-1
XX# s3sun.arpa: Sun UNIX 4.2 Release 3.0
XX# s3dawn.scubed.arpa: Sun UNIX 4.2 Release 3.4
XX
XX## SysV compatitibilty
XX## space.scubed.arpa: Ridge 32/3200 running RX/V 1.1 (V.2)
XX## sdcc15.ucsd.edu: UNIX System V Release 2.1.1v4 AT&T 3B20
XX#NDIR=	-I/usr/local
XX#LIBNDIR= -L/usr/local/lib -lndir
XX## if the default set-up for the directory files doesn't work, 
XX## `$man directory' should tell you where the appropriate files are 
XX## located on your system (if they are there at all). Comment out the 
XX## above two lines and adjust $(LIBNDIR) below as well as changing the 
XX## include line in mq.c to the appropriate value. 
XX##LIBNDIR= -L/usr/ucb.lib -lucb
XX#OS=	-DSYSV $(NDIR)
XX
XX# system mailbox directory (the trailing slash is needed) and
XX# system mail queue directory (no trailing slash!)
XXMAIL=	'-DMAILDIR="/usr/spool/mail/"' '-DMQUEUE="/usr/spool/mqueue"'
XX
XXCFLAGS=	-O $(OS) $(VOID) $(MAIL)
XX
XXall:	mq from
XX
XXmq:	mq.o
XX	cc -o mq mq.o $(LIBNDIR)
XX
XXfrom:	from.o
XX	cc -o from from.o
XX
XXclean:	Makefile
XX	@rm -f core mq.o from.o
XX
XXclobber: clean
XX	@rm -f mq from mq.shar
XX
XXcleanse: clean shar
XX	@rm -f mq from mq.c from.c mq.8 from.1 README Makefile
XX
XXshar:	Makefile
XX	shar README Makefile mq.c from.c from.1 mq.8 > mq.shar
SHAR_EOF
if test 1345 -ne "`wc -c < Makefile`"
then
  echo shar: error transmitting "Makefile" '(should have been 1345 characters)'
fi
fi # end of overwriting check
echo shar: extracting "mq.c" '(9946 characters)'
if test -f mq.c
then
  echo shar: will not over-write existing file "mq.c"
else
sed 's/^XX//' << \SHAR_EOF > mq.c
XX/* program for selectively displaying the mail queue. 
XX *
XX * usage:
XX *	mq [-w] [-n] [-v] [-f [name]] [-t [name]] [-d name]
XX *
XX * caveats/comments:
XX *	-> 1) no checking is done w.r.t. what other programs are doing 
XX *	      to the mail queue files.
XX *	   2) items in the queue without a control file are ignored and 
XX *	      not counted. 
XX *	   3) one might also want to sort by priority.
XX *
XX * author:
XX *	Kevin Sweet ---------------------------------- sweet@scubed.arpa
XX *	S-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095
XX *	(home)  12205 Carmel Vista 242, San Diego, CA 92130-2237
XX *	------- [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet ------
XX *
XX * This work is copyright 1988 by Kevin Sweet. Permission is granted 
XX * to modify and distribute this work under the provision that the 
XX * author is informed of any non-cosmetic changes to the code and that 
XX * the author's name remain part of the documentaion. 
XX */
XX
XX#ifndef VOID
XX# define VOID
XX#endif
XX#include <sys/types.h>
XX#include <sys/stat.h>
XX#ifdef SYSV
XX# include <string.h>
XX# define index		strchr
XX# define rindex		strrchr
XX# include <ndir.h>	/* see Makefile... */
XX#else /* SYSV */
XX# include <strings.h>
XX# include <sys/dir.h>
XX#endif
XX#include <stdio.h>
XX#include <ctype.h>
XX
XXint order();
XXextern int free(), qsort();
XXextern long atol();
XXextern char *ctime(), *getenv(), *malloc();
XXstatic int gethelp();
XX
XX#define FALSE		0
XX#define LSIZE		256
XX#define MALLOC(a)	(char *) malloc( (unsigned) sizeof(char) * \
XX			                 ((a) + 1) )
XX#define NUMQ		128
XX/* #define SORT_BY_ID	/**/
XX#define SORT_BY_TIME	/**/
XX#define SWITCHAR	'-'
XX#define TRUE		1
XX
XXstruct mqueue {
XX	long l;		/* location in directory stream */
XX	long t;		/* time entered queue */
XX	char q[8];	/* queue id */
XX};
XXtypedef unsigned short int BOOLEAN;
XX
XXmain(argc, argv)
XXint argc;
XXchar *argv[];
XX{
XX	BOOLEAN DONT, FROM, NUMBER, TO, VERBOSE, WIDE;
XX	DIR *dp;
XX	FILE *fp;
XX	char dont[80], from[80], line[LSIZE], to[80];
XX	register char *cp, *fg, *message, *qdir, *user;
XX	register int i, icnt, ldont, lfrom, lto, mcnt, qcnt, qdlen;
XX	register long size;
XX	struct direct *dirp;
XX	struct mqueue qinfo[NUMQ];
XX	struct stat sbuf;
XX
XX	/* find the print options
XX	 */
XX#ifdef SYSV
XX	user = getenv("LOGNAME");
XX#else
XX	user = getenv("USER");
XX#endif
XX	DONT = FROM = NUMBER = TO = VERBOSE = WIDE = FALSE;
XX	for (i = 1, cp = argv[1]; i < argc; i++, cp = argv[i]) 
XX	if (cp[0] == SWITCHAR) 
XX	switch (cp[1]) {
XX		case 'h': case 'H': 
XX			gethelp(argv[0], 0);
XX		case 'n': case 'N': 
XX			NUMBER = TRUE;
XX			break;
XX		case 'w': case 'W': 
XX			WIDE = TRUE;
XX			break;
XX		case 'v': case 'V': 
XX			VERBOSE = TRUE;
XX			break;
XX		case 'f': case 'F': 
XX			FROM = TRUE;
XX			if (cp[2]) 
XX				sprintf(from, "%.79s", &argv[i][2]);
XX			else 
XX			if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
XX				sprintf(from, "%.79s", argv[i+1]);
XX				i++;
XX			}
XX			else
XX			sprintf(from, "%.79s", user);
XX			lfrom = strlen(from);
XX			break;
XX		case 't': case 'T': 
XX			TO = TRUE;
XX			if (cp[2]) 
XX				sprintf(to, "%.79s", &argv[i][2]);
XX			else 
XX			if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
XX				sprintf(to, "%.79s", argv[i+1]);
XX				i++;
XX			}
XX			else
XX			sprintf(to, "%.79s", user);
XX			lto = strlen(to);
XX			break;
XX		case 'd': case 'D': 
XX			DONT = TRUE;
XX			if (cp[2]) 
XX				sprintf(dont, "%.79s", &argv[i][2]);
XX			else 
XX			if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
XX				sprintf(dont, "%.79s", argv[i+1]);
XX				i++;
XX			}
XX			else 
XX			sprintf(dont, "%c", '\0');
XX			ldont = strlen(dont);
XX			if (!ldont) DONT = FALSE;
XX			break;
XX		default: 
XX			printf("invalid option '%c': ", cp[1]);
XX			gethelp(argv[0], -1);
XX	}	/* end switch */
XX	else 
XX	{
XX		gethelp(argv[0], 0);
XX	}	/* end for/if */
XX
XX	/* find the mqueue directory. 
XX	 */
XX	qcnt = 0;
XX#ifndef DEBUG
XX	if ( !(fp = fopen("/usr/lib/sendmail.cf", "r")) ) {
XX		printf("fatal error: ");
XX		printf("unable to read /usr/lib/sendmail.cf\n");
XX		gethelp(argv[0], 1);
XX	}
XX	while ((fg = fgets(line, LSIZE, fp)) != (char *) NULL) {
XX		if (strncmp(fg, "OQ", 2)) continue;
XX		fg[strlen(line)-1] = '\0';
XX		fg += 2;
XX		qcnt++;
XX		qdlen = strlen(fg) + 1;
XX		qdir = MALLOC(qdlen);
XX		strncpy(qdir, fg, qdlen - 1);
XX		break;
XX	}
XX	fclose(fp);
XX#endif /* DEBUG */
XX	if (!qcnt) {
XX		qdlen = strlen(MQUEUE) + 1;
XX		qdir = MALLOC(qdlen);
XX		strncpy(qdir, MQUEUE, qdlen - 1);
XX	}
XX
XX	/* find queue files in the mqueue directory: 
XX	 * save the location in the directory stream, the queue id and 
XX	 * the time for each vaild (non-zero length) queue control file.
XX	 */
XX	if ( !(dp = opendir(qdir)) ) {
XX		printf("fatal error: ");
XX		printf("unable to open directory %s\n", qdir);
XX		gethelp(argv[0], 2);
XX	}
XX	mcnt = qcnt = 0;
XX	for (dirp = readdir(dp); dirp != (struct direct *) NULL; 
XX	     dirp = readdir(dp)) 
XX	if (!strncmp(dirp->d_name, "qf", 2)) {
XX		/*
XX		 * open the file and test it for validity 
XX		 */
XX		cp = MALLOC(qdlen + 1 + strlen(dirp->d_name));
XX		sprintf(cp, "%s/%s", qdir, dirp->d_name);
XX		fp = fopen(cp, "r");
XX		VOID stat(cp, &sbuf);
XX		VOID free(cp);
XX		if (!fp) continue;
XX		if (!sbuf.st_size) {
XX			fclose(fp);
XX			continue;
XX		}
XX		/* 
XX		 * do book-keeping
XX		 */
XX		icnt = 0;
XX		mcnt++;
XX		if (qcnt < NUMQ) 
XX		/*
XX		 * check to see if we are supposed to print the entry
XX		 */
XX		while ( fg = fgets(line, LSIZE, fp) ) {
XX			fg[strlen(line)-1] = '\0';
XX			if (*fg == 'S') {
XX				if (FROM) {
XX					for (; *fg; *fg++) 
XX					if (!strncmp(fg, from, lfrom)) 
XX					icnt |= 0x001;
XX				} else 
XX				icnt |= 0x001;
XX			} else
XX			if (*fg == 'R') {
XX				if (TO) {
XX					for (; *fg; *fg++) 
XX					if (!strncmp(fg, to, lto)) 
XX					icnt |= 0x002;
XX				} else 
XX				icnt |= 0x002;
XX				if (DONT) {
XX					for (; *fg; *fg++) 
XX					if (!strncmp(fg, dont, ldont)) 
XX					icnt |= 0x004;
XX				} 
XX			}
XX		}	/* end while loop */
XX
XX		if ( (icnt & 0x004) || 
XX		    !(icnt & 0x002) || 
XX		    !(icnt & 0x001) ) {
XX			/*
XX			 * either DONT was specified _and_ we found 
XX			 * the dont field in the Receiver field, 
XX			 * or TO was specified _and_ we did not find 
XX			 * the to field in the Receiver field, 
XX			 * or FROM was specified _and_ we did not find 
XX			 * the from field in the Sender field; 
XX			 * or we have exceeded the array dimension for 
XX			 * holding queue information. 
XX			 */
XX			fclose(fp);
XX			continue;
XX		}
XX		/*
XX		 * save the location in the directory stream
XX		 */
XX		qinfo[qcnt].l = telldir(dp);
XX		/*
XX		 * save the queue id
XX		 */
XX		sprintf(qinfo[qcnt].q, "%.7s", 
XX		        index(dirp->d_name, 'f')+1);
XX		/*
XX		 * save the queue time
XX		 */
XX		VOID fseek(fp, 0L, 0);
XX		while ((fg = fgets(line, LSIZE, fp)) && *fg != 'D') 
XX		if (*fg == 'T') qinfo[qcnt].t = atol(&line[1]);
XX		/*
XX		 * increment the valid queue file counter
XX		 */
XX		qcnt++;
XX		fclose(fp);
XX	}
XX	closedir(dp);
XX
XX	/* print the requisite header 
XX	 */
XX	if (!qcnt) {
XX		if (!mcnt) printf("Mail queue is empty\n");
XX		else {
XX			printf("Mail Queue (%d request%c", 
XX			       mcnt, mcnt > 1 ? 's' : '\0');
XX			printf(", none %s)\n", 
XX			       NUMBER == TRUE ? "applied" : "printed");
XX		}
XX		exit(0);
XX	} 
XX	printf("%sMail Queue (%d request%c", NUMBER == TRUE ? "" : 
XX	       ( VERBOSE == TRUE ? "      " : "\t\t" ), 
XX	       mcnt, mcnt > 1 ? 's' : '\0');
XX	if (qcnt != mcnt) 
XX	printf(", only %d %s", qcnt, 
XX	       NUMBER == TRUE ? "applied" : "printed");
XX	printf(")\n");
XX
XX	if (NUMBER) exit(0);
XX
XX	if (VERBOSE == FALSE) 
XX	printf("%s%s\n", "--QID-- --Size-- -----Q-Time----- ", 
XX	       "------------Sender/Recipient-----------------");
XX
XX	/* sort the queue files
XX	 */
XX	VOID qsort(qinfo, qcnt, sizeof(struct mqueue), order);
XX
XX	/* loop through the valid queue files: 
XX	 */
XX	for (icnt = 0; icnt < qcnt; icnt++) {
XX		cp = MALLOC(qdlen + 2 + strlen(qinfo[icnt].q));
XX		sprintf(cp, "%s/qf%s", qdir, qinfo[icnt].q);
XX		fp = fopen(cp, "r");
XX		VOID free(cp);
XX
XX		/* read in everything up to the first header line
XX		 */
XX		mcnt = 0;
XX		while ( fg = fgets(line, LSIZE, fp) ) {
XX
XX			/* get rid of the trailing newline
XX			 */
XX			fg[strlen(line)-1] = '\0';
XX
XX			/* get the size of the data file (long)
XX			 */
XX			if (*fg == 'D') {
XX				cp = MALLOC(qdlen + strlen(fg));
XX				sprintf(cp, "%s/%s", qdir, &line[1]);
XX				VOID stat(cp, &sbuf);
XX				size = (long) sbuf.st_size;
XX				VOID free(cp);
XX			} else 
XX			/*
XX			 * get the error message (char *)
XX			 */
XX			if (*fg == 'M') {
XX				message = MALLOC(strlen(fg));
XX				sprintf(message, "%s", &line[1]);
XX				mcnt++;
XX			} else 
XX			/*
XX			 * get the sender (char *)
XX			 */
XX			if (*fg == 'S') {
XX/*
XX * print out what we have so far 
XX */
XXif (VERBOSE) {
XX	if (WIDE) printf("from: %s\n", &line[1]);
XX	else printf("from: %.73s\n", &line[1]);
XX} else {
XX	printf("%-7.7s %8ld %.16s ", 
XX	       qinfo[icnt].q, size, ctime(&qinfo[icnt].t));
XX	if (WIDE) {
XX		printf("%s\n", &line[1]);
XX		if (mcnt) printf("\t\t\t\t  (%s)\n", message);
XX	} else {
XX		printf("%.45s\n", &line[1]);
XX		if (mcnt) printf("\t\t\t\t  (%.43s)\n", message);
XX	}
XX}
XX				size = 0L;
XX				if (mcnt) VOID free(message);
XX			} else 
XX			/*
XX			 * get the recipients (char *)
XX			 */
XX			if (*fg == 'R') {
XX				/*
XX				 * print out the rest
XX				 */
XX				if (VERBOSE) {
XX					printf("      to: ");
XX					if (WIDE) 
XX					printf("%s\n", &line[1]);
XX					else 
XX					printf("%.69s\n", &line[1]);
XX				} else {
XX					printf("\t\t\t\t  ");
XX					if (WIDE) 
XX					printf("%s\n", &line[1]);
XX					else 
XX					printf("%.45s\n", &line[1]);
XX				}
XX			}
XX
XX		}	/* end fp loop */
XX		fclose(fp);
XX
XX		if (VERBOSE) printf("      in queue since: %.16s\n", 
XX		                    ctime(&qinfo[icnt].t));
XX
XX	}	/* end valid queue file loop */
XX
XX	exit(0);
XX}
XX
XX/* qsort comparison function. 
XX */
XXint 
XXorder(e1, e2)
XXstruct mqueue *e1;
XXstruct mqueue *e2;
XX{
XX#ifdef SORT_BY_TIME
XX	if (e1->t < e2->t) return(-1);
XX	else if (e1->t > e2->t) return(1);
XX	else return(0);
XX#endif
XX#ifdef SORT_BY_ID
XX	return(strcmp(e1->q, e2->q));
XX#endif
XX}
XX
XX/* the help/usage message 
XX */
XXstatic 
XXint 
XXgethelp(program, exit_status)
XXchar *program;
XXint exit_status;
XX{
XX	register char *name;
XX
XX	name = rindex(program, '/');
XX	if (name) *name++;
XX	else {
XX		name = rindex(program, '\\');
XX		if (name) *name++;
XX		else name = program;
XX	}
XX	printf("usage: %s [-w] [-n] [-v]", name);
XX	printf(" [-f [name]] [-t [name]] [-d name]\n");
XX	exit(exit_status);
XX}
XX
SHAR_EOF
if test 9946 -ne "`wc -c < mq.c`"
then
  echo shar: error transmitting "mq.c" '(should have been 9946 characters)'
fi
fi # end of overwriting check
echo shar: extracting "from.c" '(6741 characters)'
if test -f from.c
then
  echo shar: will not over-write existing file "from.c"
else
sed 's/^XX//' << \SHAR_EOF > from.c
XX/*
XX * usage:
XX *      from [-f] [file] [-d] [-w] [-s sender] [-u user]
XX *
XX * caveats/comments:
XX *	no checking is done w.r.t. what other programs are doing to the 
XX *	mailboxes.
XX *
XX * author:
XX *	Kevin Sweet ---------------------------------- sweet@scubed.arpa
XX *	S-CUBED, 3398 Carmel Mountain,  San Diego, CA 92121-1095
XX *	(home)  12205 Carmel Vista 242, San Diego, CA 92130-2237
XX *	------- [ames,att,harvard,rutgers,ucsd,uunet]scubed!sweet ------
XX *
XX * This work is copyright 1988 by Kevin Sweet. Permission is granted 
XX * to modify and distribute this work under the provision that the 
XX * author is informed of any non-cosmetic changes to the code and that 
XX * the author's name remain part of the documentaion. 
XX */
XX
XX#ifdef SYSV
XX# define MAXPATHLEN	1024
XX# include <string.h>
XX# define index		strchr
XX# define rindex		strrchr
XX#else
XX# include <sys/param.h>
XX# include <strings.h>
XX#endif
XX#include <stdio.h>
XX
XXextern char *getenv();
XXstatic char *getmbox();
XXstatic int gethelp();
XX
XX#define FORWARD		0
XX#define LSIZE		256
XX#define NUMQ		256
XX#define SWITCHAR	'-'
XX
XXstruct mbox {
XX	char from[LSIZE];
XX	char subject[LSIZE];
XX};
XX
XXmain(argc, argv)
XXint argc;
XXchar *argv[];
XX{
XX	FILE *fp;
XX	char line[LSIZE], mbox[MAXPATHLEN], path[LSIZE], sender[LSIZE];
XX	register char *bang, *cp;
XX	register int DATE, SENDER, WIDE, 
XX	             from, i, j, left, mcnt, subject;
XX	struct mbox mail[NUMQ];
XX
XX	/* find the mail file to list along with any options
XX	 */
XX	strcpy(mbox, "\0");
XX	DATE = SENDER = WIDE = 0;
XX	for (i = 1, cp = argv[1]; i < argc; i++, cp = argv[i]) {
XX
XX		if (cp[0] == SWITCHAR) 
XX		switch (cp[1]) {
XX		case 'h': case 'H': 
XX			gethelp(argv[0], 0);
XX		case 'd': case 'D': 
XX			DATE = 1;
XX			break;
XX		case 'w': case 'W': 
XX			WIDE ++;
XX			if (cp[2] == 'w' || cp[2] == 'W') WIDE++;
XX			break;
XX		case 'f': case 'F': 
XX			if (cp[2]) 
XX				strncpy(mbox, &argv[i][2], MAXPATHLEN);
XX			else 
XX			if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
XX				strncpy(mbox, argv[i+1], MAXPATHLEN);
XX				i++;
XX			}
XX			else 
XX			strncpy(mbox, getmbox(), MAXPATHLEN);
XX			break;
XX		case 's': case 'S': 
XX			if (cp[2]) 
XX				strncpy(sender, &argv[i][2], LSIZE);
XX			else 
XX			if (i != argc-1 && argv[i+1][0] != SWITCHAR) {
XX				strncpy(sender, argv[i+1], LSIZE);
XX				i++;
XX			}
XX			else 
XX#ifdef SYSV
XX			strncpy(sender, getenv("LOGNAME"), LSIZE);
XX#else
XX			strncpy(sender, getenv("USER"), LSIZE);
XX#endif
XX			SENDER = strlen(sender);
XX			break;
XX		case 'u': case 'U': 
XX			if (cp[2]) {
XX				strncpy(mbox, MAILDIR, MAXPATHLEN);
XX				strncat(mbox, &argv[i][2], 
XX				        MAXPATHLEN - strlen(mbox));
XX			}
XX			else 
XX			if (i != argc-1 || argv[i+1][0] != SWITCHAR) {
XX				strncpy(mbox, MAILDIR, MAXPATHLEN);
XX				strncat(mbox, argv[i+1], 
XX				        MAXPATHLEN - strlen(mbox));
XX				i++;
XX			}
XX			else
XX			strcpy(mbox, "\0");
XX			break;
XX		default: 
XX			printf("invalid option '%c': ", cp[1]);
XX			gethelp(argv[0], -1);
XX		}	/* end if/switch */
XX		else 
XX		strncpy(mbox, argv[i], MAXPATHLEN);
XX
XX	}	/* end for */
XX
XX	/* use the system mailbox if there are no arguments or if 
XX	 * there are any (fatal) errors
XX	 */
XX	if (!strlen(mbox)) {
XX		strncpy(mbox, MAILDIR, MAXPATHLEN);
XX#ifdef SYSV
XX		strncat(mbox, getenv("LOGNAME"), 
XX#else
XX		strncat(mbox, getenv("USER"), 
XX#endif
XX		        MAXPATHLEN - strlen(mbox));
XX	} 
XX
XX	/* if we can't open the mailbox, exit quitely
XX	 */
XX	fp = fopen(mbox, "r");
XX	if (!fp) exit(1);
XX
XX	/* read in the sender and subject of each letter
XX	 */
XX	mcnt = -1;
XX	while ( cp = fgets(line, LSIZE, fp) ) {
XX		cp[strlen(line)-1] = '\0';
XX		if (!strncmp(line, "From ", 5)) {
XX			if (mcnt >= 0 && !strlen(mail[mcnt].from)) 
XX			   strcpy(mail[mcnt].from, path);
XX			strcpy(path, index(line, ' ')+1);
XX			if (!DATE) {
XX				cp = index(path, ' ');
XX				if (cp) cp[0] = '\0';
XX			}
XX			if (SENDER) {
XX				from = 1;
XX				subject = 1;
XX				cp = path;
XX				j = 0;
XX				for (; *cp; *cp++) 
XX				if (!strncmp(cp, sender, SENDER)) j++;
XX			} else 
XX			j = 1;
XX			if (j) {
XX				mcnt++;
XX				from = 0;
XX				subject = 0;
XX			}
XX		} else 
XX		if (!from && ( !strncmp(line, "From: ", 6) || 
XX		    !strncmp(line+1, "From: ", 6) )) {
XX			if (!FORWARD) from = 1;
XX			if (DATE || WIDE > 1) {
XX				strcpy(mail[mcnt].from, path);
XX				continue;
XX			}
XX			cp = index(line, '<');
XX			if (cp) *cp++;
XX			else cp = index(line, ' ')+1;
XX			strcpy(mail[mcnt].from, cp);
XX			cp = index(mail[mcnt].from, '>');
XX			if (!cp) cp = index(mail[mcnt].from, ' ');
XX			if (cp) cp[0] = '\0';
XX		} else 
XX		if (!subject && !strncmp(line, "Subject: ", 9)) {
XX			if (!FORWARD) subject = 1;
XX			strcpy(mail[mcnt].subject, index(line, ' ')+1);
XX			if (DATE && !WIDE) 
XX			   strcpy(mail[mcnt].subject, "\0");
XX		} 
XX	}
XX	if (!strlen(mail[mcnt].from)) strcpy(mail[mcnt].from, path);
XX
XX	/* display each entry: 
XX	 * if this isn't a wide list, use the shortest available name 
XX	 * for the sender and make sure that the subject does not 
XX	 * wrap 80 columns 
XX	 */
XX	for (i = 0; i <= mcnt; i++) {
XX		cp = index(mail[i].from, '!');
XX		bang = rindex(mail[i].from, '!');
XX		if (!DATE && WIDE < 2) {
XX			if (!bang || !strcmp(cp, bang)) 
XX			   cp = mail[i].from;
XX			else 
XX			{
XX				cp++;
XX				while (strcmp(index(cp, '!'), bang)) {
XX					cp = index(cp, '!');
XX					cp++;
XX				}	/* end while */
XX			}
XX		} else 
XX	       	cp = mail[i].from;
XX		left = 71 - (int) strlen(cp);
XX		printf("From %s", cp);
XX		if (DATE && !WIDE) putchar('\n');
XX		else 
XX		if (strlen(mail[i].subject)) {
XX			printf(", ");
XX			if (!WIDE) {
XX				putchar('"');
XX				cp = mail[i].subject;
XX				for (j = 0; j < left; j++) 
XX				    if (*cp) putchar(*cp++);
XX				printf("\"\n");
XX			} else 
XX			printf("\"%s\"\n", mail[i].subject);
XX		} 
XX		else
XX		printf(", (no subject)\n");
XX	} 
XX
XX	fclose(fp);
XX}
XX
XXstatic 
XXchar *
XXgetmbox()
XX{
XX	FILE *fp;
XX	char line[LSIZE], mailrc[MAXPATHLEN], mbox[MAXPATHLEN];
XX	register char *cp;
XX
XX	/* find out where to look for mail startup file
XX	 */
XX	strncpy(mailrc, getenv("HOME"), MAXPATHLEN);
XX	strncat(mailrc, "/.mailrc", MAXPATHLEN - strlen(mailrc));
XX	if (getenv("MAILRC")) 
XX		strncpy(mailrc, getenv("MAILRC"), MAXPATHLEN);
XX
XX	/* find out where to look for the default mailbox
XX	 */
XX	strncpy(mbox, getenv("HOME"), MAXPATHLEN);
XX	strncat(mbox, "/mbox", MAXPATHLEN - strlen(mbox));
XX	fp = fopen(mailrc, "r");
XX	if (fp) {
XX		while ( cp = fgets(line, LSIZE, fp) ) {
XX			cp[strlen(line)-1] = '\0';
XX			if (strncmp(line, "set MBOX=", 9)) continue;
XX			cp += 9;
XX			strncpy(mbox, cp, MAXPATHLEN);
XX			break;
XX		}
XX		fclose(fp);
XX	}
XX	if (getenv("MBOX")) 
XX		strncpy(mbox, getenv("MBOX"), MAXPATHLEN);
XX
XX	return(mbox);
XX}
XX
XX/* the help/usage message 
XX */
XXstatic 
XXint 
XXgethelp(program, exit_status)
XXchar *program;
XXint exit_status;
XX{
XX	register char *name;
XX
XX	name = rindex(program, '/');
XX	if (name) *name++;
XX	else {
XX		name = rindex(program, '\\');
XX		if (name) *name++;
XX		else name = program;
XX	}
XX	printf("usage: %s [-f] [file] ", name);
XX	printf("[-d] [-w] [-s sender] [-u user]\n");
XX	exit(exit_status);
XX}
XX
SHAR_EOF
if test 6741 -ne "`wc -c < from.c`"
then
  echo shar: error transmitting "from.c" '(should have been 6741 characters)'
fi
fi # end of overwriting check
echo shar: extracting "from.1" '(2208 characters)'
if test -f from.1
then
  echo shar: will not over-write existing file "from.1"
else
sed 's/^XX//' << \SHAR_EOF > from.1
XX.de KS
XX.if t .B \\$1 \\$2
XX.if n .I \\$1 \\$2
XX..
XX.de UL
XX.if t \\$1\l'|0\(ul'\\$2
XX.if n .I \\$1 \\$2
XX..
XX.de Sh
XX.PP
XX\fB\\$1\fR
XX.PP
XX..
XX.TH FROM 1L local "22 April 1988"
XX.SH NAME
XXfrom \- list sender and subject of mail
XX.SH SYNTAX
XX.B from
XX[\fB\-f\fR]
XX[\fBfile\fR]
XX[\fB\-d\fR]
XX[\fB\-w\fR]
XX[\fB\-s\fR [sender]]
XX[\fB\-u\fR user]
XX.SH DESCRIPTION
XX.I From
XXlists an abbreviated name for the sender of each letter in the
XXspecified mail file
XX.KS file
XX(which 
XX.UL may 
XXbe preceded or prepended on the command line by \fB\-f\fR)
XXalong with the subject of the letter so that both sets of information
XXcan fit into 80 columns of standard output.
XX.Sh Options
XXWith no options, \fIfrom\fR lists the mail in the user's system mailbox.
XX.TP 1i
XX.B \-f
XXIf 
XX.KS file
XXis not specified, then mail in the file \fImbox\fR in
XXthe user's home directory is listed (see ENVIRONMENT section for
XXfurther details).
XXOtherwise, mail in the mailbox
XX.I file
XXis listed.
XX.TP
XX.B \-h
XXPrint the \fIfrom\fR syntax.
XX.TP
XX.B \-d
XXThe complete return path and the date received are displayed.
XX(This duplicates \fI/usr/ucb/from\fR.)
XX.TP
XX.B \-w
XXThe \fB\-w\fR option is similar to that for \fIps\fR on BSD systems.
XXSelecting \fB\-w\fR displays each entry in long form (in this case,
XXa minimalist sender's address and the full subject);
XXwhereas, \fB\-ww\fR displays each entry in unabridged form (i.e., the
XXfull subject and the complete return path for the sender are listed).
XX.TP
XX.BR \-s " sender"
XXOnly mail from \fIsender\fR is listed. \fISender\fR defaults to
XX$LOGNAME on System V and to $USER on BSD systems.
XX.TP
XX.BR \-u " user"
XXMail in \fIuser\fR's system mailbox is listed.
XX.SH ENVIRONMENT
XX.I From
XXuses the following environment variables:
XX.TP 1.375i
XXHOME
XXThe user's home (default login) directory.
XX.TP
XXUSER/LOGNAME
XXThe user's user (login) name.
XX.PP
XXIf the environment variable MAILRC is set,
XX.I from
XXwill check the mail startup file specified by $MAILRC instead of
XX\fI$HOME/.mailrc\fR.
XXIf the environment variable MBOX is set,
XX.I from
XXwill recognize the default mailbox specified by $MBOX rather than
XXthat specified in the mail startup file
XXor
XX\fI$HOME/mbox\fR.
XX.SH "SEE ALSO"
XX.ta 12n
XXBSD \-	\fIMail\fR(1)
XX.br
XXSystem V \-	\fImailx\fR(1)
XX.SH AUTHOR
XXKevin Sweet
SHAR_EOF
if test 2208 -ne "`wc -c < from.1`"
then
  echo shar: error transmitting "from.1" '(should have been 2208 characters)'
fi
fi # end of overwriting check
echo shar: extracting "mq.8" '(1850 characters)'
if test -f mq.8
then
  echo shar: will not over-write existing file "mq.8"
else
sed 's/^XX//' << \SHAR_EOF > mq.8
XX.de KS
XX.if t .B \\$1 \\$2
XX.if n .I \\$1 \\$2
XX..
XX.de UL
XX.if t \\$1\l'|0\(ul'\\$2
XX.if n \\$1 \\$2
XX..
XX.de Sh
XX.PP
XX\fB\\$1\fR
XX.PP
XX..
XX.TH MQ 8L local "22 April 1988"
XX.SH NAME
XXmq \- print the contents of the mail queue
XX.SH SYNTAX
XX.B mq
XX[\fB\-w\fR]
XX[\fB\-n\fR]
XX[\fB\-v\fR]
XX[\fB\-f\fR [name]]
XX[\fB\-t\fR [name]]
XX[\fB\-d\fR name]
XX.SH DESCRIPTION
XXBy default,
XX.I mq
XXlists the contents of the mail queue in the same format as
XX.I sendmail
XXwhen invoked as \fImailq\fR except that 
XXitems in the queue without a control file are not displayed by \fImq\fR.
XXThat is,
XXit displays an error message (if any), the queue identification code, 
XXfile size, queue time, sender, and recipient(s) for each entry in the
XXqueue
XXso that the result can fit into 80 columns of standard output.
XX.Sh Options
XX.TP 1i
XX.B \-f
XX\fBfrom\fR.
XXIf 
XX.KS name
XXis specified, \fImq\fR lists only messages with 
XX.KS name
XXin the `sender' field. Otherwise, \fImq\fR will list only messages
XXwith the user's login name (as given by the environment variable
XXLOGNAME on System V and by USER on BSD systems) in the `sender' field.
XX.TP
XX.B \-t
XX\fBto\fR.
XXIf 
XX.KS name
XXis specified, \fImq\fR lists only messages with 
XX.KS name
XXin the `recipient' field. Otherwise, \fImq\fR will list only messages
XXwith $USER/$LOGNAME in the `recipient' field.
XX.TP
XX.BR \-d " name"
XX\fBdon't\fR.
XXList all messages that 
XX.UL "do not"
XXcontain the string 
XX.KS name
XXin the `recipient' field.
XX.TP
XX.B \-h
XX\fBhelp\fR.
XXPrint the \fImq\fR syntax.
XX.TP
XX.B \-w
XX\fBwide\fR.
XX.I Mq
XXwill not truncate `sender' and `recipient' fields on output.
XX.TP
XX.B \-n
XX\fBnumber\fR.
XXList only a count of the selected files in the mail queue.
XX.TP
XX.B \-v
XX\fBverbose\fR.
XXDisplay the contents of the mail queue listing the sender,
XXrecipient(s) and queue time in noncolumnar format.
XX.SH FILES
XX/usr/lib/sendmail.cf
XX.SH "SEE ALSO"
XX\fIsendmail\fR(8)
XX.SH AUTHOR
XXKevin Sweet
SHAR_EOF
if test 1850 -ne "`wc -c < mq.8`"
then
  echo shar: error transmitting "mq.8" '(should have been 1850 characters)'
fi
fi # end of overwriting check
#
# End of shell archive
exit 0
--

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.