Index: aux.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/aux.c,v
retrieving revision 1.3
diff -u -r1.3 aux.c
--- aux.c	4 Oct 2003 20:36:48 -0000	1.3
+++ aux.c	30 Aug 2004 14:28:31 -0000
@@ -300,7 +300,7 @@
 		sourcing = 0;
 		return (1);
 	}
-	(void)Fclose(input);
+	Fclose(input);
 	if (cond != CANY)
 		printf("Unmatched \"if\"\n");
 	ssp--;
@@ -324,10 +324,10 @@
 
 	if (stat(name, &sb))
 		return;
-	(void)gettimeofday(&tv[0], (struct timezone *)NULL);
+	gettimeofday(&tv[0], (struct timezone *)NULL);
 	tv[0].tv_sec++;
 	TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec);
-	(void)utimes(name, tv);
+	utimes(name, tv);
 }
 
 /*
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.bin/mail/extern.h,v
retrieving revision 1.3
diff -u -r1.3 extern.h
--- extern.h	22 Aug 2003 19:38:36 -0000	1.3
+++ extern.h	30 Aug 2004 15:21:44 -0000
@@ -74,6 +74,7 @@
 char	*value(const char *);
 char	*vcopy(const char *);
 char	*yankword(char *, char []);
+char    *yanklogin(char *, char []);
 int	 Fclose(FILE *);
 int	 More(int *);
 int	 Pclose(FILE *);
Index: lex.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/lex.c,v
retrieving revision 1.4
diff -u -r1.4 lex.c
--- lex.c	4 Oct 2003 20:36:48 -0000	1.4
+++ lex.c	30 Aug 2004 15:30:55 -0000
@@ -56,18 +56,24 @@
  * If the first character of name is %, we are considered to be
  * editing the file, otherwise we are reading our mail which has
  * signficance for mbox and so forth.
+ * 
+ * If the -e option is being passed to mail, this function has a 
+ * tri-state return code: -1 on error, 0 on no mail, 1 if there is 
+ * mail. 
  */
 int
 setfile(char *name)
 {
 	FILE *ibuf;
-	int i, fd;
+	int checkmode, i, fd;
 	struct stat stb;
 	char isedit = *name != '%' || getuserid(myname) != getuid();
 	char *who = name[1] ? name + 1 : myname;
 	char tempname[PATHSIZE];
 	static int shudclob;
 
+	checkmode = value("checkmode") != NULL;
+
 	if ((name = expand(name)) == NULL)
 		return (-1);
 
@@ -80,12 +86,12 @@
 
 	if (fstat(fileno(ibuf), &stb) < 0) {
 		warn("fstat");
-		(void)Fclose(ibuf);
+		Fclose(ibuf);
 		return (-1);
 	}
 
 	if (S_ISDIR(stb.st_mode) || !S_ISREG(stb.st_mode)) {
-		(void)Fclose(ibuf);
+		Fclose(ibuf);
 		errno = S_ISDIR(stb.st_mode) ? EISDIR : EINVAL;
 		warn("%s", name);
 		return (-1);
@@ -111,10 +117,10 @@
 	if ((i = open(name, 1)) < 0)
 		readonly++;
 	else
-		(void)close(i);
+		close(i);
 	if (shudclob) {
-		(void)fclose(itf);
-		(void)fclose(otf);
+		fclose(itf);
+		fclose(otf);
 	}
 	shudclob = 1;
 	edit = isedit;
@@ -122,15 +128,15 @@
 	if (name != mailname)
 		strlcpy(mailname, name, sizeof(mailname));
 	mailsize = fsize(ibuf);
-	(void)snprintf(tempname, sizeof(tempname),
+	snprintf(tempname, sizeof(tempname),
 	    "%s/mail.RxXXXXXXXXXX", tmpdir);
 	if ((fd = mkstemp(tempname)) == -1 || (otf = fdopen(fd, "w")) == NULL)
 		err(1, "%s", tempname);
-	(void)fcntl(fileno(otf), F_SETFD, 1);
+	fcntl(fileno(otf), F_SETFD, 1);
 	if ((itf = fopen(tempname, "r")) == NULL)
 		err(1, "%s", tempname);
-	(void)fcntl(fileno(itf), F_SETFD, 1);
-	(void)rm(tempname);
+	fcntl(fileno(itf), F_SETFD, 1);
+	rm(tempname);
 	setptr(ibuf, 0);
 	setmsize(msgCount);
 	/*
@@ -139,15 +145,21 @@
 	 * we really are in the file...
 	 */
 	mailsize = ftello(ibuf);
-	(void)Fclose(ibuf);
+	Fclose(ibuf);
 	relsesigs();
 	sawcom = 0;
-	if (!edit && msgCount == 0) {
+    
+        if ((checkmode || !edit) && msgCount == 0) { 
 nomail:
-		fprintf(stderr, "No mail for %s\n", who);
-		return (-1);
-	}
-	return (0);
+	        if (!checkmode) {
+			fprintf(stderr, "No mail for %s\n", who);
+			return (-1);
+		} else {
+			return (0);
+		}
+        }
+
+        return (checkmode ? 1 : 0); 
 }
 
 /*
Index: mail.1
===================================================================
RCS file: /cvs/src/usr.bin/mail/mail.1,v
retrieving revision 1.2
diff -u -r1.2 mail.1
--- mail.1	17 Jun 2003 04:29:28 -0000	1.2
+++ mail.1	30 Aug 2004 15:50:21 -0000
@@ -33,7 +33,7 @@
 .\" $FreeBSD: src/usr.bin/mail/mail.1,v 1.18.2.12 2003/01/06 05:46:03 mikeh Exp $
 .\" $DragonFly: src/usr.bin/mail/mail.1,v 1.2 2003/06/17 04:29:28 dillon Exp $
 .\"
-.Dd April 28, 1995
+.Dd August 30, 2004
 .Dt MAIL 1
 .Os
 .Sh NAME
@@ -47,15 +47,23 @@
 .Op Fl s Ar subject
 .Op Fl c Ar cc-addr
 .Op Fl b Ar bcc-addr
+.Op Fl F
 .Ar to-addr ...
 .Op Fl Ar sendmail-option ...
 .Nm
-.Op Fl EiInNv
+.Op Fl EHiInNv
+.Op Fl F
 .Fl f
 .Op Ar name
 .Nm
-.Op Fl EiInNv
+.Op Fl EHiInNv
+.Op Fl F
 .Op Fl u Ar user
+.Nm 
+.Fl e 
+.Op Fl f Ar name 
+.Nm 
+.Op Fl  
 .Sh INTRODUCTION
 The
 .Nm
@@ -70,6 +78,14 @@
 Verbose mode.
 The details of
 delivery are displayed on the user's terminal.
+.It Fl e 
+Test for the presence of mail in the (by default, system) 
+mailbox.
+An exit status of 0 is returned if 
+it has mail; otherwise, an exit status 
+of 1 is returned. 
+.It Fl H 
+Write a header summary only. 
 .It Fl E
 Do not send messages with an empty body.
 This is useful for piping errors from
@@ -127,6 +143,16 @@
 .Ic quit ,
 .Nm
 writes undeleted messages back to this file.
+.It Fl F 
+Record the message in a file named after the first  
+recipient.
+The name is the login-name portion of the 
+address found first on the  
+.Dq Li To: 
+line in the mail header. 
+Overrides the  
+.Va record 
+variable, if set. 
 .It Fl u
 Is equivalent to:
 .Pp
@@ -875,7 +901,7 @@
 If an option is not set,
 .Nm
 will look for an environment variable of the same name.
-The binary options include the following:
+The available options include the following:
 .Bl -tag -width indent
 .It Va append
 Causes messages saved in
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/main.c,v
retrieving revision 1.3
diff -u -r1.3 main.c
--- main.c	4 Oct 2003 20:36:48 -0000	1.3
+++ main.c	30 Aug 2004 15:20:56 -0000
@@ -65,7 +65,7 @@
 	 * Figure out whether we are being run interactively,
 	 * start the SIGCHLD catcher, and so forth.
 	 */
-	(void)signal(SIGCHLD, sigchild);
+	signal(SIGCHLD, sigchild);
 	if (isatty(0))
 		assign("interactive", "");
 	image = -1;
@@ -82,7 +82,7 @@
 	bcc = NULL;
 	smopts = NULL;
 	subject = NULL;
-	while ((i = getopt(argc, argv, "EINT:b:c:dfins:u:v")) != -1) {
+	while ((i = getopt(argc, argv, "FEHINT:b:c:defins:u:v")) != -1) {
 		switch (i) {
 		case 'T':
 			/*
@@ -93,7 +93,7 @@
 			if ((i = open(Tflag, O_CREAT | O_TRUNC | O_WRONLY,
 			    0600)) < 0)
 				err(1, "%s", Tflag);
-			(void)close(i);
+			close(i);
 			break;
 		case 'u':
 			/*
@@ -112,6 +112,25 @@
 		case 'd':
 			debug++;
 			break;
+                case 'e': 
+                        /* 
+                         * User wants to check mail and exit. 
+                         */ 
+                        assign("checkmode", ""); 
+                        break; 
+                case 'H': 
+                        /* 
+                         * User wants a header summary only. 
+                         */ 
+                        assign("headersummary", ""); 
+                        break; 
+                case 'F': 
+                        /* 
+                         * User wants to record messages to files 
+                         * named after first recipient username. 
+                         */ 
+                        assign("recordrecip", ""); 
+                        break; 
 		case 's':
 			/*
 			 * Give a subject field for sending from
@@ -178,11 +197,13 @@
 			break;
 		case '?':
 			fprintf(stderr, "\
-Usage: %s [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] to-addr ...\n\
+Usage: %s [-EiInv] [-s subject] [-c cc-addr] [-b bcc-addr] [-F] to-addr ...\n\
        %*s [- sendmail-options ...]\n\
-       %s [-EiInNv] -f [name]\n\
-       %s [-EiInNv] [-u user]\n",__progname, strlen(__progname), "",
-			    __progname, __progname);
+       %s [-EHiInNv] [-F] -f [name]\n\
+       %s [-EHiInNv] [-F] [-u user]\n\
+       %s -e [-f name]\n\
+       %s -H\n", __progname, strlen(__progname), "", __progname,
+			__progname, __progname, __progname);
 			exit(1);
 		}
 	}
@@ -229,6 +250,17 @@
 		 */
 		exit(senderr);
 	}
+
+        if(value("checkmode") != NULL) { 
+                if (ef == NULL) 
+                        ef = "%"; 
+                if (setfile(ef) <= 0) 
+                        /* Either an error has occured, or no mail */ 
+                        exit(1); 
+                else 
+                        exit(0); 
+                /* NOTREACHED */ 
+        } 
 	/*
 	 * Ok, we are reading mail.
 	 * Decide whether we are editing a mailbox or reading
@@ -240,18 +272,23 @@
 		exit(1);		/* error already reported */
 	if (setjmp(hdrjmp) == 0) {
 		if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
-			(void)signal(SIGINT, hdrstop);
+			signal(SIGINT, hdrstop);
 		if (value("quiet") == NULL)
 			printf("Mail version %s.  Type ? for help.\n",
 				version);
 		announce();
-		(void)fflush(stdout);
-		(void)signal(SIGINT, prevint);
+		fflush(stdout);
+		signal(SIGINT, prevint);
 	}
+
+        /* If we were in header summary mode, it's time to exit. */ 
+        if (value("headersummary") != NULL) 
+                exit(0); 
+
 	commands();
-	(void)signal(SIGHUP, SIG_IGN);
-	(void)signal(SIGINT, SIG_IGN);
-	(void)signal(SIGQUIT, SIG_IGN);
+	signal(SIGHUP, SIG_IGN);
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
 	quit();
 	exit(0);
 }
@@ -264,7 +301,7 @@
 hdrstop(int signo)
 {
 
-	(void)fflush(stdout);
+	fflush(stdout);
 	fprintf(stderr, "\nInterrupt\n");
 	longjmp(hdrjmp, 1);
 }
Index: names.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/names.c,v
retrieving revision 1.3
diff -u -r1.3 names.c
--- names.c	4 Oct 2003 20:36:48 -0000	1.3
+++ names.c	30 Aug 2004 15:34:37 -0000
@@ -198,6 +198,80 @@
 }
 
 /*
+ * Grab a single login name (liberal word) 
+ * Throw away things between ()'s, take anything between <>, 
+ * and look for words before metacharacters %, @, !. 
+ */ 
+char * 
+yanklogin(char *ap, char wbuf[])
+{ 
+        char *cp, *cp2, *cp_temp; 
+        int n; 
+    
+        cp = ap; 
+        for (;;) { 
+                if (*cp == '\0') 
+                        return (NULL); 
+                if (*cp == '(') { 
+                        int nesting;
+
+			nesting = 0; 
+    
+                        while (*cp != '\0') { 
+                            switch (*cp++) { 
+                             case '(': 
+                                        nesting++; 
+                                        break; 
+                                case ')': 
+                                        --nesting; 
+                                        break; 
+                                } 
+                                if (nesting <= 0) 
+                                       break; 
+                        } 
+                } else if (*cp == ' ' || *cp == '\t' || *cp == ',') 
+                        cp++; 
+                else 
+                       break; 
+        } 
+    
+        /* 
+         * Now, let's go forward till we meet the needed character, 
+         * and step one word back. 
+         */ 
+   
+        /* First, remember current point. */ 
+        cp_temp = cp; 
+        n = 0; 
+    
+        /* 
+         * Note that we look ahead in a cycle. This is safe, since 
+         * non-end of string is checked first. 
+         */ 
+        while(*cp != '\0' && strchr("@%!", *(cp + 1)) == NULL) 
+                cp++; 
+   
+        /* 
+         * Now, start stepping back to the first non-word character, 
+         * while counting the number of symbols in a word. 
+         */ 
+        while(cp != cp_temp && strchr(" \t,<>", *(cp - 1)) == NULL) { 
+                n++; 
+                cp--; 
+        } 
+    
+        /* Finally, grab the word forward. */ 
+        cp2 = wbuf; 
+        while(n >= 0) { 
+                *cp2++=*cp++; 
+                n--; 
+        } 
+    
+        *cp2 = '\0'; 
+        return (cp); 
+} 
+    
+/* 
  * For each recipient in the passed name list with a /
  * in the name, append the message to the end of the named file
  * and remove him from the recipient list.
Index: send.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/send.c,v
retrieving revision 1.3
diff -u -r1.3 send.c
--- send.c	4 Oct 2003 20:36:48 -0000	1.3
+++ send.c	30 Aug 2004 15:40:09 -0000
@@ -133,7 +133,7 @@
 				}
 				if (doign != ignoreall)
 					/* add blank line */
-					(void)putc('\n', obuf);
+					putc('\n', obuf);
 				ishead = 0;
 				ignoring = 0;
 			} else {
@@ -171,10 +171,10 @@
 				if (length > 1)
 					fputs(prefix, obuf);
 				else
-					(void)fwrite(prefix, sizeof(*prefix),
+					fwrite(prefix, sizeof(*prefix),
 					    prefixlen, obuf);
 			}
-			(void)fwrite(line, sizeof(*line), length, obuf);
+			fwrite(line, sizeof(*line), length, obuf);
 			if (ferror(obuf))
 				return (-1);
 		}
@@ -198,9 +198,9 @@
 			if (c > 1)
 				fputs(prefix, obuf);
 			else
-				(void)fwrite(prefix, sizeof(*prefix),
+				fwrite(prefix, sizeof(*prefix),
 				    prefixlen, obuf);
-			(void)fwrite(line, sizeof(*line), c, obuf);
+			fwrite(line, sizeof(*line), c, obuf);
 			if (ferror(obuf))
 				return (-1);
 		}
@@ -288,10 +288,10 @@
 void
 mail1(struct header *hp, int printheaders)
 {
-	char *cp;
+	char *cp, *nbuf;
 	int pid;
 	char **namelist;
-	struct name *to;
+	struct name *to, *nsto;
 	FILE *mtf;
 
 	/*
@@ -308,7 +308,7 @@
 				grabh(hp, GBCC);
 		} else {
 			printf("EOT\n");
-			(void)fflush(stdout);
+			fflush(stdout);
 		}
 	}
 	if (fsize(mtf) == 0) {
@@ -340,6 +340,18 @@
 	to = elide(to);
 	if (count(to) == 0)
 		goto out;
+        if (value("recordrecip") != NULL) { 
+                /* 
+                 * Before fixing the header, save old To:. 
+                 * We do this because elide above has sorted To: list, and 
+                 * we would like to save message in a file named by the first 
+                 * recipient the user has entered, not the one being the first 
+                 * after sorting happened. 
+                 */ 
+                if ((nsto = malloc(sizeof(struct name))) == NULL) 
+                        err(1, "Out of memory"); 
+                bcopy(hp->h_to, nsto, sizeof(struct name)); 
+        } 
 	fixhead(hp, to);
 	if ((mtf = infix(hp, mtf)) == NULL) {
 		fprintf(stderr, ". . . message lost, sorry.\n");
@@ -355,8 +367,19 @@
 		printf("\n");
 		goto out;
 	}
-	if ((cp = value("record")) != NULL)
-		(void)savemail(expand(cp), mtf);
+        if (value("recordrecip") != NULL) { 
+                /* 
+                 * Extract first recipient username from saved To: and use it 
+                 * as a filename. 
+                 */ 
+                if ((nbuf = malloc(strlen(detract(nsto, 0)) + 1)) == NULL) 
+                        err(1, "Out of memory"); 
+                if ((cp = yanklogin(detract(nsto, 0), nbuf)) != NULL) 
+                        savemail(expand(nbuf), mtf); 
+                free(nbuf); 
+                free(nsto); 
+        } else if ((cp = value("record")) != NULL) 
+		savemail(expand(cp), mtf);
 	/*
 	 * Fork, set up the temporary mail file as standard
 	 * input for "mail", and exec with the user list we generated
@@ -370,13 +393,13 @@
 	}
 	if (pid == 0) {
 		sigset_t nset;
-		(void)sigemptyset(&nset);
-		(void)sigaddset(&nset, SIGHUP);
-		(void)sigaddset(&nset, SIGINT);
-		(void)sigaddset(&nset, SIGQUIT);
-		(void)sigaddset(&nset, SIGTSTP);
-		(void)sigaddset(&nset, SIGTTIN);
-		(void)sigaddset(&nset, SIGTTOU);
+		sigemptyset(&nset);
+		sigaddset(&nset, SIGHUP);
+		sigaddset(&nset, SIGINT);
+		sigaddset(&nset, SIGQUIT);
+		sigaddset(&nset, SIGTSTP);
+		sigaddset(&nset, SIGTTIN);
+		sigaddset(&nset, SIGTTOU);
 		prepare_child(&nset, fileno(mtf), -1);
 		if ((cp = value("sendmail")) != NULL)
 			cp = expand(cp);
@@ -387,11 +410,11 @@
 		_exit(1);
 	}
 	if (value("verbose") != NULL)
-		(void)wait_child(pid);
+		wait_child(pid);
 	else
 		free_child(pid);
 out:
-	(void)Fclose(mtf);
+	Fclose(mtf);
 }
 
 /*
@@ -433,7 +456,7 @@
 	int c, fd;
 	char tempname[PATHSIZE];
 
-	(void)snprintf(tempname, sizeof(tempname),
+	snprintf(tempname, sizeof(tempname),
 	    "%s/mail.RsXXXXXXXXXX", tmpdir);
 	if ((fd = mkstemp(tempname)) == -1 ||
 	    (nfo = Fdopen(fd, "w")) == NULL) {
@@ -442,16 +465,16 @@
 	}
 	if ((nfi = Fopen(tempname, "r")) == NULL) {
 		warn("%s", tempname);
-		(void)Fclose(nfo);
-		(void)rm(tempname);
+		Fclose(nfo);
+		rm(tempname);
 		return (fi);
 	}
-	(void)rm(tempname);
-	(void)puthead(hp, nfo,
+	rm(tempname);
+	puthead(hp, nfo,
 	    GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO|GNL|GCOMMA);
 	c = getc(fi);
 	while (c != EOF) {
-		(void)putc(c, nfo);
+		putc(c, nfo);
 		c = getc(fi);
 	}
 	if (ferror(fi)) {
@@ -459,16 +482,16 @@
 		rewind(fi);
 		return (fi);
 	}
-	(void)fflush(nfo);
+	fflush(nfo);
 	if (ferror(nfo)) {
 		warn("%s", tempname);
-		(void)Fclose(nfo);
-		(void)Fclose(nfi);
+		Fclose(nfo);
+		Fclose(nfi);
 		rewind(fi);
 		return (fi);
 	}
-	(void)Fclose(nfo);
-	(void)Fclose(fi);
+	Fclose(nfo);
+	Fclose(fi);
 	rewind(nfi);
 	return (nfi);
 }
@@ -496,7 +519,7 @@
 	if (hp->h_inreplyto != NULL && w & GINREPLYTO)
 		fprintf(fo, "In-Reply-To: <%s>\n", hp->h_inreplyto), gotcha++;
 	if (gotcha && w & GNL)
-		(void)putc('\n', fo);
+		putc('\n', fo);
 	return (0);
 }
 
@@ -547,15 +570,15 @@
 		warn("%s", name);
 		return (-1);
 	}
-	(void)time(&now);
+	time(&now);
 	fprintf(fo, "From %s %s", myname, ctime(&now));
 	while ((i = fread(buf, 1, sizeof(buf), fi)) > 0)
-		(void)fwrite(buf, 1, i, fo);
+		fwrite(buf, 1, i, fo);
 	fprintf(fo, "\n");
-	(void)fflush(fo);
+	fflush(fo);
 	if (ferror(fo))
 		warn("%s", name);
-	(void)Fclose(fo);
+	Fclose(fo);
 	rewind(fi);
 	return (0);
 }
