From: Walter Alejandro Iglesias Subject: Re: mail(1) add any header from command line (working version) To: tech@openbsd.org Date: Sat, 31 Aug 2024 15:13:45 +0200 Thanks to off-line corrections and help from Henry Ford now the diff is working. It needs more testing but so far it works. I even corrected a bug present in the Debian's version, if under Debian you run: $ sudo apt install bsd-mailx $ echo hello | mail -s hello -a "Subject: hello" You get duplicated the Subject, the same happens with any header processed in puthead(). This bug is corrected in this version. Index: cmd3.c =================================================================== RCS file: /cvs/src/usr.bin/mail/cmd3.c,v diff -u -p -r1.30 cmd3.c --- cmd3.c 8 Mar 2023 04:43:11 -0000 1.30 +++ cmd3.c 30 Aug 2024 13:21:28 -0000 @@ -193,6 +193,8 @@ _respond(int *msgvec) struct name *np; struct header head; + memset(&head, 0, sizeof(head)); + if (msgvec[1] != 0) { puts("Sorry, can't reply to multiple messages at once"); return(1); @@ -601,6 +603,8 @@ _Respond(int *msgvec) struct message *mp; int *ap; char *cp; + + memset(&head, 0, sizeof(head)); head.h_to = NULL; for (ap = msgvec; *ap != 0; ap++) { Index: def.h =================================================================== RCS file: /cvs/src/usr.bin/mail/def.h,v diff -u -p -r1.17 def.h --- def.h 28 Jan 2022 06:18:41 -0000 1.17 +++ def.h 30 Aug 2024 13:21:28 -0000 @@ -173,6 +173,7 @@ struct header { struct name *h_to; /* Dynamic "To:" string */ char *h_from; /* User-specified "From:" string */ char *h_subject; /* Subject string */ + char *h_header; /* Additional header string */ struct name *h_cc; /* Carbon copies string */ struct name *h_bcc; /* Blind carbon copies */ struct name *h_smopts; /* Sendmail options */ Index: extern.h =================================================================== RCS file: /cvs/src/usr.bin/mail/extern.h,v diff -u -p -r1.30 extern.h --- extern.h 21 May 2024 05:00:48 -0000 1.30 +++ extern.h 30 Aug 2024 13:21:28 -0000 @@ -162,7 +162,7 @@ void load(char *); struct var * lookup(char *); int mail(struct name *, struct name *, struct name *, struct name *, - char *, char *); + char *, char *, char *); void mail1(struct header *, int); void makemessage(FILE *, int); void mark(int); Index: mail.1 =================================================================== RCS file: /cvs/src/usr.bin/mail/mail.1,v diff -u -p -r1.83 mail.1 --- mail.1 31 Mar 2022 17:27:25 -0000 1.83 +++ mail.1 30 Aug 2024 13:21:28 -0000 @@ -63,6 +63,12 @@ with lines replaced by messages. .Pp The options are as follows: .Bl -tag -width Ds +.It Fl a +Specify additional header fields on the command line such as "X-Loop: +foo@bar" etc. +You have to use quotes if the string contains spaces. +This argument may be specified more than once, the headers will then +be concatenated. .It Fl b Ar list Send blind carbon copies to .Ar list . @@ -1254,7 +1260,7 @@ and are not supported by this implementa .Nm mailx . .Pp The flags -.Op Fl bcdEIrv +.Op Fl abcdEIrv are extensions to the specification. .Sh HISTORY A Index: main.c =================================================================== RCS file: /cvs/src/usr.bin/mail/main.c,v diff -u -p -r1.35 main.c --- main.c 26 Jan 2021 18:21:47 -0000 1.35 +++ main.c 30 Aug 2024 13:21:28 -0000 @@ -103,6 +103,9 @@ main(int argc, char **argv) struct name *to, *cc, *bcc, *smopts; char *fromaddr; char *subject; + char *header; + char *tmp; + size_t hlen = 0; char *ef; char nosrc = 0; char *rc; @@ -136,7 +139,9 @@ main(int argc, char **argv) smopts = NULL; fromaddr = NULL; subject = NULL; - while ((i = getopt(argc, argv, "EINb:c:dfinr:s:u:v")) != -1) { + header = NULL; + tmp = NULL; + while ((i = getopt(argc, argv, "EINa:b:c:dfinr:s:u:v")) != -1) { switch (i) { case 'u': /* @@ -171,6 +176,24 @@ main(int argc, char **argv) */ subject = optarg; break; + + case 'a': + /* + * Give additional header fields for sending from + * non terminal + */ + if (header == NULL) { + header = strdup(optarg); + if (header == NULL) + err(1, NULL); + } else { + if (asprintf(&tmp, "%s\n%s", header, + optarg) == -1) + err(1, NULL); + free(header); + header = tmp; + } + break; case 'f': /* * User is specifying file to "edit" with Mail, @@ -269,7 +292,7 @@ main(int argc, char **argv) rc = "~/.mailrc"; load(expand(rc)); if (!rcvmode) { - mail(to, cc, bcc, smopts, fromaddr, subject); + mail(to, cc, bcc, smopts, fromaddr, subject, header); /* * why wait? */ Index: send.c =================================================================== RCS file: /cvs/src/usr.bin/mail/send.c,v diff -u -p -r1.26 send.c --- send.c 8 Mar 2023 04:43:11 -0000 1.26 +++ send.c 30 Aug 2024 13:21:28 -0000 @@ -279,13 +279,14 @@ statusput(struct message *mp, FILE *obuf */ int mail(struct name *to, struct name *cc, struct name *bcc, struct name *smopts, - char *fromaddr, char *subject) + char *fromaddr, char *subject, char *header) { struct header head; head.h_to = to; head.h_from = fromaddr; head.h_subject = subject; + head.h_header = header; head.h_cc = cc; head.h_bcc = bcc; head.h_smopts = smopts; @@ -306,6 +307,7 @@ sendmail(void *v) head.h_to = extract(str, GTO); head.h_from = NULL; head.h_subject = NULL; + head.h_header = NULL; head.h_cc = NULL; head.h_bcc = NULL; head.h_smopts = NULL; @@ -519,16 +521,23 @@ puthead(struct header *hp, FILE *fo, int gotcha = 0; from = hp->h_from ? hp->h_from : value("from"); - if (from != NULL) + if (from != NULL && + (hp->h_header == NULL || strstr(hp->h_header, "From:") == NULL)) fprintf(fo, "From: %s\n", from), gotcha++; - if (hp->h_to != NULL && w & GTO) + if (hp->h_to != NULL && w & GTO && + (hp->h_header == NULL || strstr(hp->h_header, "To:") == NULL)) fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++; - if (hp->h_subject != NULL && w & GSUBJECT) + if (hp->h_subject != NULL && w & GSUBJECT && + (hp->h_header == NULL || strstr(hp->h_header, "Subject:") == NULL)) fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; - if (hp->h_cc != NULL && w & GCC) + if (hp->h_cc != NULL && w & GCC && + (hp->h_header == NULL || strstr(hp->h_header, "Cc:") == NULL)) fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++; - if (hp->h_bcc != NULL && w & GBCC) + if (hp->h_bcc != NULL && w & GBCC && + (hp->h_header == NULL || strstr(hp->h_header, "bcc:") == NULL)) fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++; + if (hp->h_header != NULL && w) + fprintf(fo, "%s\n", hp->h_header), gotcha++; if (gotcha && w & GNL) (void)putc('\n', fo); return(0); -- Walter