Here's a version that does not rely on non-standard "sendmail -t"
behavior.

 - todd

Index: usr.bin/mail/cmd3.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/cmd3.c,v
retrieving revision 1.25
diff -u -r1.25 cmd3.c
--- usr.bin/mail/cmd3.c 6 Apr 2011 11:36:26 -0000       1.25
+++ usr.bin/mail/cmd3.c 7 Jan 2015 18:07:06 -0000
@@ -227,6 +227,7 @@
        }
        np = elide(np);
        head.h_to = np;
+       head.h_from = NULL;
        if ((head.h_subject = hfield("subject", mp)) == NULL)
                head.h_subject = hfield("subj", mp);
        head.h_subject = reedit(head.h_subject);
@@ -619,6 +620,7 @@
        if ((head.h_subject = hfield("subject", mp)) == NULL)
                head.h_subject = hfield("subj", mp);
        head.h_subject = reedit(head.h_subject);
+       head.h_from = NULL;
        head.h_cc = NULL;
        head.h_bcc = NULL;
        head.h_smopts = NULL;
Index: usr.bin/mail/def.h
===================================================================
RCS file: /cvs/src/usr.bin/mail/def.h,v
retrieving revision 1.13
diff -u -r1.13 def.h
--- usr.bin/mail/def.h  25 Jun 2003 15:13:32 -0000      1.13
+++ usr.bin/mail/def.h  7 Jan 2015 21:08:11 -0000
@@ -172,6 +172,7 @@
  */
 struct header {
        struct name *h_to;              /* Dynamic "To:" string */
+       char *h_from;                   /* User-specified "From:" string */
        char *h_subject;                /* Subject string */
        struct name *h_cc;              /* Carbon copies string */
        struct name *h_bcc;             /* Blind carbon copies */
Index: usr.bin/mail/extern.h
===================================================================
RCS file: /cvs/src/usr.bin/mail/extern.h,v
retrieving revision 1.27
diff -u -r1.27 extern.h
--- usr.bin/mail/extern.h       28 Jul 2009 16:05:04 -0000      1.27
+++ usr.bin/mail/extern.h       7 Jan 2015 17:59:52 -0000
@@ -163,8 +163,8 @@
 void    load(char *);
 struct var *
         lookup(char *);
-int     mail (struct name *, struct name *, struct name *, struct name *,
-              char *);
+int     mail(struct name *, struct name *, struct name *, struct name *,
+              char *, char *);
 void    mail1(struct header *, int);
 void    makemessage(FILE *, int);
 void    mark(int);
Index: usr.bin/mail/mail.1
===================================================================
RCS file: /cvs/src/usr.bin/mail/mail.1,v
retrieving revision 1.72
diff -u -r1.72 mail.1
--- usr.bin/mail/mail.1 7 Jan 2015 17:08:21 -0000       1.72
+++ usr.bin/mail/mail.1 7 Jan 2015 21:25:55 -0000
@@ -43,6 +43,7 @@
 .Op Fl dEIinv
 .Op Fl b Ar list
 .Op Fl c Ar list
+.Op Fl r Ar from-addr
 .Op Fl s Ar subject
 .Ar to-addr ...
 .Ek
@@ -109,6 +110,13 @@
 Inhibits reading
 .Pa /etc/mail.rc
 upon startup.
+.It Fl r Ar from-addr
+Use
+.Ar from-addr
+as the from address in the message and envelope.
+Overrides any
+.Em from
+options in the startup files.
 .It Fl s Ar subject
 Specify subject on command line
 (only the first argument after the
@@ -969,6 +977,19 @@
 .Nm mail
 to expand message recipient addresses, as explained in the section
 .Sx Recipient address specifications .
+.It Ar from
+Causes
+.Nm mail
+to use the specified sender address in the
+.Dq From:
+field of the message header.
+A stripped down version of the address is also used in the message envelope.
+If unset, the message will not include an explicit sender address and
+a default value will be added by the MTA, typically
+.Dq user@host .
+This value can be overridden by specifying the
+.Fl r
+flag on the command line.
 .It Ar hold
 This option is used to hold messages in the system mailbox
 by default.
Index: usr.bin/mail/main.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/main.c,v
retrieving revision 1.26
diff -u -r1.26 main.c
--- usr.bin/mail/main.c 16 Dec 2014 18:37:17 -0000      1.26
+++ usr.bin/mail/main.c 7 Jan 2015 21:27:04 -0000
@@ -49,6 +49,7 @@
 {
        int i;
        struct name *to, *cc, *bcc, *smopts;
+       char *fromaddr;
        char *subject;
        char *ef;
        char nosrc = 0;
@@ -77,8 +78,9 @@
        cc = NULL;
        bcc = NULL;
        smopts = NULL;
+       fromaddr = NULL;
        subject = NULL;
-       while ((i = getopt(argc, argv, "EIN:b:c:dfins:u:v")) != -1) {
+       while ((i = getopt(argc, argv, "EIN:b:c:dfinr:s:u:v")) != -1) {
                switch (i) {
                case 'u':
                        /*
@@ -100,6 +102,12 @@
                case 'd':
                        debug++;
                        break;
+               case 'r':
+                       /*
+                        * Set From: address
+                        */
+                       fromaddr = optarg;
+                       break;
                case 's':
                        /*
                         * Give a subject field for sending from
@@ -203,7 +211,7 @@
                rc = "~/.mailrc";
        load(expand(rc));
        if (!rcvmode) {
-               mail(to, cc, bcc, smopts, subject);
+               mail(to, cc, bcc, smopts, fromaddr, subject);
                /*
                 * why wait?
                 */
@@ -272,7 +280,7 @@
 {
 
        fprintf(stderr, "usage: %s [-dEIinv] [-b list] [-c list] "
-           "[-s subject] to-addr ...\n", __progname);
+           "[-r from-addr] [-s subject] to-addr ...\n", __progname);
        fprintf(stderr, "       %s [-dEIiNnv] -f [file]\n", __progname);
        fprintf(stderr, "       %s [-dEIiNnv] [-u user]\n", __progname);
        exit(1);
Index: usr.bin/mail/names.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/names.c,v
retrieving revision 1.21
diff -u -r1.21 names.c
--- usr.bin/mail/names.c        16 Dec 2014 18:36:46 -0000      1.21
+++ usr.bin/mail/names.c        7 Jan 2015 17:54:59 -0000
@@ -456,52 +456,6 @@
 }
 
 /*
- * Unpack the name list onto a vector of strings.
- * Return an error if the name list won't fit.
- */
-char **
-unpack(struct name *sm, struct name *np)
-{
-       char **ap, **top;
-       int t, extra, metoo, verbose;
-
-       if ((t = count(np)) == 0)
-               errx(1, "No names to unpack");
-       t += count(sm);
-
-       /*
-        * Compute the number of extra arguments we will need.
-        * We need at least four extra -- one for "send-mail", one for the
-        * "-i" flag, one for the "--" to signal end of command line
-        * arguments, and one for the terminating 0 pointer.
-        */
-       extra = 4;
-       metoo = value("metoo") != NULL;
-       if (metoo)
-               extra++;
-       verbose = value("verbose") != NULL;
-       if (verbose)
-               extra++;
-       top = (char **)salloc((t + extra) * sizeof(*top));
-       ap = top;
-       *ap++ = "send-mail";
-       *ap++ = "-i";
-       if (metoo)
-               *ap++ = "-m";
-       if (verbose)
-               *ap++ = "-v";
-       for (; sm != NULL; sm = sm->n_flink)
-               if ((sm->n_type & GDEL) == 0)
-                       *ap++ = sm->n_name;
-       *ap++ = "--";
-       for (; np != NULL; np = np->n_flink)
-               if ((np->n_type & GDEL) == 0)
-                       *ap++ = np->n_name;
-       *ap = NULL;
-       return(top);
-}
-
-/*
  * Remove all of the duplicates from the passed name list by
  * insertion sorting them, then checking for dups.
  * Return the head of the new list.
Index: usr.bin/mail/send.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/send.c,v
retrieving revision 1.23
diff -u -r1.23 send.c
--- usr.bin/mail/send.c 17 Jan 2014 18:42:30 -0000      1.23
+++ usr.bin/mail/send.c 7 Jan 2015 21:08:37 -0000
@@ -279,11 +279,12 @@
  */
 int
 mail(struct name *to, struct name *cc, struct name *bcc, struct name *smopts,
-     char *subject)
+     char *fromaddr, char *subject)
 {
        struct header head;
 
        head.h_to = to;
+       head.h_from = fromaddr;
        head.h_subject = subject;
        head.h_cc = cc;
        head.h_bcc = bcc;
@@ -292,7 +293,6 @@
        return(0);
 }
 
-
 /*
  * Send mail to a bunch of user names.  The interface is through
  * the mail routine below.
@@ -304,6 +304,7 @@
        struct header head;
 
        head.h_to = extract(str, GTO);
+       head.h_from = NULL;
        head.h_subject = NULL;
        head.h_cc = NULL;
        head.h_bcc = NULL;
@@ -319,9 +320,10 @@
 void
 mail1(struct header *hp, int printheaders)
 {
-       char *cp;
+       char *cp, *envfrom = NULL;
+       char *argv[8];
+       char **ap = argv;
        pid_t pid;
-       char **namelist;
        struct name *to;
        FILE *mtf;
 
@@ -365,18 +367,33 @@
                fputs(". . . message lost, sorry.\n", stderr);
                return;
        }
-       namelist = unpack(hp->h_smopts, to);
+       if ((cp = value("record")) != NULL)
+               (void)savemail(expand(cp), mtf);
+       
+       /* Setup sendmail arguments. */
+        *ap++ = "send-mail";
+        *ap++ = "-i";
+        *ap++ = "-t";
+       cp = hp->h_from ? hp->h_from : value("from");
+       if (cp != NULL) {
+               envfrom = skin(cp);
+               *ap++ = "-f";
+               *ap++ = envfrom;
+               if (envfrom == cp)
+                       envfrom = NULL;
+       }
+       if (value("metoo") != NULL)
+                *ap++ = "-m";
+       if (value("verbose") != NULL)
+                *ap++ = "-v";
+       *ap = NULL;
        if (debug) {
-               char **t;
-
                fputs("Sendmail arguments:", stdout);
-               for (t = namelist; *t != NULL; t++)
-                       printf(" \"%s\"", *t);
+               for (ap = argv; *ap != NULL; ap++)
+                       printf(" \"%s\"", *ap);
                putchar('\n');
                goto out;
        }
-       if ((cp = value("record")) != NULL)
-               (void)savemail(expand(cp), mtf);
        /*
         * Fork, set up the temporary mail file as standard
         * input for "mail", and exec with the user list we generated
@@ -403,10 +420,11 @@
                        cp = expand(cp);
                else
                        cp = _PATH_SENDMAIL;
-               execv(cp, namelist);
+               execv(cp, argv);
                warn("%s", cp);
                _exit(1);
        }
+       free(envfrom);
        if (value("verbose") != NULL)
                (void)wait_child(pid);
        else
@@ -497,8 +515,12 @@
 puthead(struct header *hp, FILE *fo, int w)
 {
        int gotcha;
+       char *from;
 
        gotcha = 0;
+       from = hp->h_from ? hp->h_from : value("from");
+       if (from != NULL)
+               fprintf(fo, "From: %s\n", from), gotcha++;
        if (hp->h_to != NULL && w & GTO)
                fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
        if (hp->h_subject != NULL && w & GSUBJECT)

Reply via email to