Modernize from(1) a bit. Use getline() to support longer lines and
authormillert <millert@openbsd.org>
Tue, 2 Jun 2015 15:44:17 +0000 (15:44 +0000)
committermillert <millert@openbsd.org>
Tue, 2 Jun 2015 15:44:17 +0000 (15:44 +0000)
document the environment variables used.  OK deraadt@

usr.bin/from/from.1
usr.bin/from/from.c

index 3f2c589..8026e4d 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: from.1,v 1.12 2013/08/12 14:19:53 jmc Exp $
+.\"    $OpenBSD: from.1,v 1.13 2015/06/02 15:44:17 millert Exp $
 .\"    $NetBSD: from.1,v 1.4 1995/09/01 01:39:09 jtc Exp $
 .\"
 .\" Copyright (c) 1980, 1990, 1993
@@ -30,7 +30,7 @@
 .\"
 .\"    @(#)from.1      8.2 (Berkeley) 12/30/93
 .\"
-.Dd $Mdocdate: August 12 2013 $
+.Dd $Mdocdate: June 2 2015 $
 .Dt FROM 1
 .Os
 .Sh NAME
@@ -68,6 +68,19 @@ is given, the
 .Ar user Ns 's
 mailbox is examined instead of the invoker's own mailbox.
 (Privileges are required.)
+.Sh ENVIRONMENT
+.Nm
+utilizes the
+.Ev LOGNAME ,
+.Ev MAIL ,
+and
+.Ev USER
+environment variables.
+.Pp
+If the
+.Ev MAIL
+environment variable is set, its value is used as the path to the
+user's mail spool.
 .Sh FILES
 .Bl -tag -width /var/mail/* -compact
 .It Pa /var/mail/*
index 07abc2c..da2230f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: from.c,v 1.17 2015/01/16 06:40:07 deraadt Exp $       */
+/*     $OpenBSD: from.c,v 1.18 2015/06/02 15:44:17 millert Exp $       */
 /*     $NetBSD: from.c,v 1.6 1995/09/01 01:39:10 jtc Exp $     */
 
 /*
 #include <err.h>
 
 int    match(char *, char *);
+FILE   *open_mbox(const char *file, const char *user);
 
 int
 main(int argc, char *argv[])
 {
-       struct passwd *pwd;
        int ch, newline;
-       char *file, *sender, *p;
-#if PATH_MAX > BUFSIZ
-       char buf[PATH_MAX];
-#else
-       char buf[BUFSIZ];
-#endif
+       char *file, *line, *sender, *p;
+       size_t linesize = 0;
+       ssize_t linelen;
+       FILE *fp;
 
-       file = sender = NULL;
-       while ((ch = getopt(argc, argv, "f:s:")) != -1)
+       file = line = sender = NULL;
+       while ((ch = getopt(argc, argv, "f:s:")) != -1) {
                switch(ch) {
                case 'f':
                        file = optarg;
@@ -66,54 +64,65 @@ main(int argc, char *argv[])
                                if (isupper((unsigned char)*p))
                                        *p = tolower((unsigned char)*p);
                        break;
-               case '?':
                default:
                        fprintf(stderr,
                            "usage: from [-f file] [-s sender] [user]\n");
-                       exit(1);
+                       exit(EXIT_FAILURE);
                }
+       }
        argv += optind;
 
+       if ((fp = open_mbox(file, *argv)) == NULL)
+               err(1, "%s", file);
+       for (newline = 1; (linelen = getline(&line, &linesize, fp)) != -1;) {
+               if (*line == '\n') {
+                       newline = 1;
+                       continue;
+               }
+               if (newline && !strncmp(line, "From ", 5) &&
+                   (!sender || match(line + 5, sender)))
+                       printf("%s", line);
+               newline = 0;
+       }
+       free(line);
+       exit(EXIT_SUCCESS);
+}
+
+FILE *
+open_mbox(const char *file, const char *user)
+{
+       struct passwd *pwd;
+       char *buf = NULL;
+       FILE *fp;
+
        /*
         * We find the mailbox by:
         *      1 -f flag
-        *      2 user
+        *      2 _PATH_MAILDIR/user (from argv)
         *      2 MAIL environment variable
-        *      3 _PATH_MAILDIR/file
+        *      3 _PATH_MAILDIR/user (from environment or passwd db)
         */
-       if (!file) {
-               if (!(file = *argv)) {
-                       if (!(file = getenv("MAIL"))) {
-                               if (!(pwd = getpwuid(getuid())))
-                                       errx(1, "no password file entry for you");
-                               if ((file = getenv("USER"))) {
-                                       (void)snprintf(buf, sizeof(buf),
-                                           "%s/%s", _PATH_MAILDIR, file);
-                                       file = buf;
-                               } else
-                                       (void)snprintf(file = buf, sizeof(buf),
-                                           "%s/%s", _PATH_MAILDIR,
-                                           pwd->pw_name);
+       if (file == NULL) {
+               if (user == NULL) {
+                       if ((file = getenv("MAIL")) == NULL) {
+                               if ((user = getenv("LOGNAME")) == NULL &&
+                                   (user = getenv("USER")) == NULL) {
+                                       if (!(pwd = getpwuid(getuid())))
+                                               errx(1, "no password file "
+                                                   "entry for you");
+                                       user = pwd->pw_name;
+                               }
                        }
-               } else {
-                       (void)snprintf(buf, sizeof(buf), "%s/%s",
-                           _PATH_MAILDIR, file);
-                       file = buf;
                }
-       }
-       if (!freopen(file, "r", stdin))
-               err(1, "%s", file);
-       for (newline = 1; fgets(buf, sizeof(buf), stdin);) {
-               if (*buf == '\n') {
-                       newline = 1;
-                       continue;
+               if (file == NULL) {
+                       if (asprintf(&buf, "%s/%s", _PATH_MAILDIR, user) == -1)
+                               err(1, NULL);
+                       file = buf;
                }
-               if (newline && !strncmp(buf, "From ", 5) &&
-                   (!sender || match(buf + 5, sender)))
-                       printf("%s", buf);
-               newline = 0;
        }
-       exit(0);
+       fp = fopen(file, "r");
+       free(buf);
+       return(fp);
 }
 
 int