Index | Thread | Search

From:
Walter Alejandro Iglesias <wai@roquesor.com>
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

Download raw body.

Thread
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" <user>

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