Date: Wed, 18 Feb 2004 12:00:49 -0800 (PST) From: Wartan Hachaturow <wart@tepkom.ru> To: freebsd-standards@FreeBSD.org Subject: Re: standards/61934: [PATCH] FreeBSD's mailx not completely SUSv3-compliant Message-ID: <200402182000.i1IK0nX8008318@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR standards/61934; it has been noted by GNATS. From: Wartan Hachaturow <wart@tepkom.ru> To: Mike Heffner <mheffner@vt.edu> Cc: FreeBSD-gnats-submit@FreeBSD.org Subject: Re: standards/61934: [PATCH] FreeBSD's mailx not completely SUSv3-compliant Date: Wed, 18 Feb 2004 22:55:37 +0300 --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Feb 18, 2004 at 09:20:40AM -0500, Mike Heffner wrote: > Therefore, changing setfile to have a tri-state return value (< 0, 0, 1) > will still work in these cases that are simply testing for a failure. Okay, here's the new patch that (hopefully :) fixes the issues you've pointed. Note also that -e works with -f, which is a SUS extension (SUS requires only to check the system mailbox) -- quite handy. Solaris does the same. -- Regards, Wartan. "Be different: conform." --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mailx.patch.2" diff -ur ./mail_HEAD.orig/extern.h ./mail_HEAD.patched/extern.h --- ./mail_HEAD.orig/extern.h Tue Jun 25 09:24:29 2002 +++ ./mail_HEAD.patched/extern.h Fri Jan 23 12:57:04 2004 @@ -73,6 +73,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 *); diff -ur ./mail_HEAD.orig/glob.h ./mail_HEAD.patched/glob.h --- ./mail_HEAD.orig/glob.h Sun Mar 25 08:57:04 2001 +++ ./mail_HEAD.patched/glob.h Wed Feb 18 17:23:46 2004 @@ -51,6 +51,8 @@ int sourcing; /* Currently reading variant file */ int loading; /* Loading user definitions */ int cond; /* Current state of conditional exc. */ +int record_recip; /* -F flag set */ +int check_mode; /* -e flag set */ FILE *itf; /* Input temp file buffer */ FILE *otf; /* Output temp file buffer */ int image; /* File descriptor for image of msg */ diff -ur ./mail_HEAD.orig/lex.c ./mail_HEAD.patched/lex.c --- ./mail_HEAD.orig/lex.c Sun Jun 30 09:25:06 2002 +++ ./mail_HEAD.patched/lex.c Wed Feb 18 22:30:52 2004 @@ -60,6 +60,9 @@ * 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. + * This function is also used for -e option implementation, so + * exit codes are designed to serve that need: + * Return -1 in case of error, 0 if there's no mail, 1 if there is. */ int setfile(name) @@ -147,9 +150,17 @@ (void)Fclose(ibuf); relsesigs(); sawcom = 0; + if (check_mode) { + if (msgCount >= 1) + return (1); + else + return (0); + } + if (!edit && msgCount == 0) { nomail: - fprintf(stderr, "No mail for %s\n", who); + if (!check_mode) + fprintf(stderr, "No mail for %s\n", who); return (-1); } return (0); diff -ur ./mail_HEAD.orig/mail.1 ./mail_HEAD.patched/mail.1 --- ./mail_HEAD.orig/mail.1 Thu Jan 9 04:08:33 2003 +++ ./mail_HEAD.patched/mail.1 Wed Feb 18 22:53:45 2004 @@ -46,15 +46,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 H .Sh INTRODUCTION The .Nm @@ -69,6 +77,13 @@ 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 @@ -126,6 +141,15 @@ .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 diff -ur ./mail_HEAD.orig/main.c ./mail_HEAD.patched/main.c --- ./mail_HEAD.orig/main.c Sun Jun 30 09:25:06 2002 +++ ./mail_HEAD.patched/main.c Wed Feb 18 22:53:34 2004 @@ -65,6 +65,7 @@ char *argv[]; { int i; + int header_sum_mode = 0; struct name *to, *cc, *bcc, *smopts; char *subject, *replyto; char *ef, *rc; @@ -93,7 +94,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:edfins:u:v")) != -1) { switch (i) { case 'T': /* @@ -123,6 +124,25 @@ case 'd': debug++; break; + case 'e': + /* + * User wants to check mail and exit. + */ + check_mode++; + break; + case 'H': + /* + * User wants a header summary only. + */ + header_sum_mode++; + break; + case 'F': + /* + * User wants to record messages to files + * named after first recipient username. + */ + record_recip++; + break; case 's': /* * Give a subject field for sending from @@ -189,11 +209,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); } } @@ -240,6 +262,19 @@ */ exit(senderr); } + + if(check_mode) { + if (ef == NULL) + ef = "%"; + if (setfile(ef) <= 0) { + exit(1); /* Either an error has occured, or no mail */ + } else { + exit(0); + } + /* NOTREACHED */ + exit(1); + } + /* * Ok, we are reading mail. * Decide whether we are editing a mailbox or reading @@ -259,6 +294,11 @@ (void)fflush(stdout); (void)signal(SIGINT, prevint); } + + /* If we were in header summary mode, it's time to exit. */ + if (header_sum_mode) + exit(0); + commands(); (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); diff -ur ./mail_HEAD.orig/names.c ./mail_HEAD.patched/names.c --- ./mail_HEAD.orig/names.c Sun Jun 30 09:25:06 2002 +++ ./mail_HEAD.patched/names.c Mon Jan 26 13:51:04 2004 @@ -210,6 +210,79 @@ } /* + * Grab a single login name (liberal word) + * Throw away things between ()'s, take anything between <>, + * and look for words before metacharacters %, @, !. + */ +char * +yanklogin(ap, wbuf) + char *ap, wbuf[]; +{ + char *cp, *cp2, *cp_temp; + int n; + + cp = ap; + for (;;) { + if (*cp == '\0') + return (NULL); + if (*cp == '(') { + int 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. diff -ur ./mail_HEAD.orig/send.c ./mail_HEAD.patched/send.c --- ./mail_HEAD.orig/send.c Sun Jun 30 09:25:06 2002 +++ ./mail_HEAD.patched/send.c Fri Jan 23 12:56:28 2004 @@ -303,9 +303,10 @@ int printheaders; { char *cp; + char *nbuf; int pid; char **namelist; - struct name *to; + struct name *to, *nsto; FILE *mtf; /* @@ -354,6 +355,18 @@ to = elide(to); if (count(to) == 0) goto out; + if (record_recip) { + /* + * 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"); @@ -369,8 +382,21 @@ printf("\n"); goto out; } - if ((cp = value("record")) != NULL) - (void)savemail(expand(cp), mtf); + if (record_recip) { + /* + * 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) + (void)savemail(expand(nbuf), mtf); + free(nbuf); + free(nsto); + } else { + 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 --Q68bSM7Ycu6FN28Q--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200402182000.i1IK0nX8008318>