From owner-svn-src-stable-10@freebsd.org Wed Jun 27 04:56:04 2018 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EBAE0102EEBC; Wed, 27 Jun 2018 04:56:03 +0000 (UTC) (envelope-from eadler@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 9D81F93FB7; Wed, 27 Jun 2018 04:56:03 +0000 (UTC) (envelope-from eadler@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7E8941E663; Wed, 27 Jun 2018 04:56:03 +0000 (UTC) (envelope-from eadler@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w5R4u3oA003716; Wed, 27 Jun 2018 04:56:03 GMT (envelope-from eadler@FreeBSD.org) Received: (from eadler@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w5R4u29X003709; Wed, 27 Jun 2018 04:56:02 GMT (envelope-from eadler@FreeBSD.org) Message-Id: <201806270456.w5R4u29X003709@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: eadler set sender to eadler@FreeBSD.org using -f From: Eitan Adler Date: Wed, 27 Jun 2018 04:56:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r335694 - stable/10/usr.bin/mail X-SVN-Group: stable-10 X-SVN-Commit-Author: eadler X-SVN-Commit-Paths: stable/10/usr.bin/mail X-SVN-Commit-Revision: 335694 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Jun 2018 04:56:04 -0000 Author: eadler Date: Wed Jun 27 04:56:01 2018 New Revision: 335694 URL: https://svnweb.freebsd.org/changeset/base/335694 Log: MFC r302776, r302799: mail(1): Bring some fixes from other BSDs. - Use varargs properly - Use pid_t - Better handling of error conditions on forked jobs. - Some prototype and warning cleanups. Fix missing forked job changes from r302776 in wait_child(). Modified: stable/10/usr.bin/mail/cmd1.c stable/10/usr.bin/mail/cmd2.c stable/10/usr.bin/mail/cmd3.c stable/10/usr.bin/mail/edit.c stable/10/usr.bin/mail/extern.h stable/10/usr.bin/mail/fio.c stable/10/usr.bin/mail/getname.c stable/10/usr.bin/mail/popen.c Directory Properties: stable/10/ (props changed) Modified: stable/10/usr.bin/mail/cmd1.c ============================================================================== --- stable/10/usr.bin/mail/cmd1.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/cmd1.c Wed Jun 27 04:56:01 2018 (r335694) @@ -439,7 +439,7 @@ folders(void) } if ((cmd = value("LISTER")) == NULL) cmd = "ls"; - (void)run_command(cmd, 0, -1, -1, dirname, NULL, NULL); + (void)run_command(cmd, 0, -1, -1, dirname, NULL); return (0); } Modified: stable/10/usr.bin/mail/cmd2.c ============================================================================== --- stable/10/usr.bin/mail/cmd2.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/cmd2.c Wed Jun 27 04:56:01 2018 (r335694) @@ -130,8 +130,9 @@ hitit: * so we can discard when the user quits. */ int -save(char str[]) +save(void *v) { + char *str = v; return (save1(str, 1, "save", saveignore)); } @@ -140,8 +141,9 @@ save(char str[]) * Copy a message to a file without affected its saved-ness */ int -copycmd(char str[]) +copycmd(void *v) { + char *str = v; return (save1(str, 0, "copy", saveignore)); } Modified: stable/10/usr.bin/mail/cmd3.c ============================================================================== --- stable/10/usr.bin/mail/cmd3.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/cmd3.c Wed Jun 27 04:56:01 2018 (r335694) @@ -79,7 +79,7 @@ dosh(char *str __unused) if ((sh = value("SHELL")) == NULL) sh = _PATH_CSHELL; - (void)run_command(sh, 0, -1, -1, NULL, NULL, NULL); + (void)run_command(sh, 0, -1, -1, NULL); (void)signal(SIGINT, sigint); printf("\n"); return (0); @@ -102,7 +102,7 @@ bangexp(char *str, size_t strsize) n = sizeof(bangbuf); while (*cp != '\0') { if (*cp == '!') { - if (n < strlen(lastbang)) { + if (n < (int)strlen(lastbang)) { overf: printf("Command buffer overflow\n"); return (-1); Modified: stable/10/usr.bin/mail/edit.c ============================================================================== --- stable/10/usr.bin/mail/edit.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/edit.c Wed Jun 27 04:56:01 2018 (r335694) @@ -180,7 +180,7 @@ run_editor(FILE *fp, off_t size, int type, int readonl nf = NULL; if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NULL) edit = type == 'e' ? _PATH_EX : _PATH_VI; - if (run_command(edit, 0, -1, -1, tempname, NULL, NULL) < 0) { + if (run_command(edit, 0, -1, -1, tempname, NULL) < 0) { (void)rm(tempname); goto out; } Modified: stable/10/usr.bin/mail/extern.h ============================================================================== --- stable/10/usr.bin/mail/extern.h Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/extern.h Wed Jun 27 04:56:01 2018 (r335694) @@ -49,7 +49,7 @@ char *copyin(char *, char **); char *detract(struct name *, int); char *expand(char *); char *getdeadletter(void); -char *getname(int); +char *getname(uid_t); char *hfield(const char *, struct message *); FILE *infix(struct header *, FILE *); char *ishfield(char [], char *, const char *); @@ -95,7 +95,7 @@ void collhup(int); void collint(int); void collstop(int); void commands(void); -int copycmd(char []); +int copycmd(void *v); int core(void); int count(struct name *); int delete(int []); @@ -130,7 +130,7 @@ int getfold(char *, int); int gethfield(FILE *, char [], int, char **); int getmsglist(char *, int *, int); int getrawlist(char [], char **, int); -int getuserid(char []); +uid_t getuserid(char []); int grabh(struct header *, int); int group(char **); void hangup(int); @@ -198,8 +198,8 @@ int respond(int *); int retfield(char *[]); int rexit(int); int rm(char *); -int run_command(char *, sigset_t *, int, int, char *, char *, char *); -int save(char []); +int run_command(char *, sigset_t *, int, int, ...); +int save(void *v); int save1(char [], int, const char *, struct ignoretab *); void savedeadletter(FILE *); int saveigfield(char *[]); @@ -223,7 +223,7 @@ void sort(char **); int source(char **); void spreserve(void); void sreset(void); -int start_command(char *, sigset_t *, int, int, char *, char *, char *); +int start_command(char *, sigset_t *, int, int, ...); void statusput(struct message *, FILE *, char *); void stop(int); int stouch(int []); Modified: stable/10/usr.bin/mail/fio.c ============================================================================== --- stable/10/usr.bin/mail/fio.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/fio.c Wed Jun 27 04:56:01 2018 (r335694) @@ -235,7 +235,7 @@ makemessage(FILE *f, int omsgCount) size -= (omsgCount + 1) * sizeof(struct message); (void)fflush(f); (void)lseek(fileno(f), (off_t)sizeof(*message), 0); - if (read(fileno(f), (char *)&message[omsgCount], size) != size) + if (read(fileno(f), (void *)&message[omsgCount], size) != size) errx(1, "Message temporary file corrupted"); message[msgCount].m_size = 0; message[msgCount].m_lines = 0; Modified: stable/10/usr.bin/mail/getname.c ============================================================================== --- stable/10/usr.bin/mail/getname.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/getname.c Wed Jun 27 04:56:01 2018 (r335694) @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$"); * Search the passwd file for a uid. Return name on success, NULL on failure. */ char * -getname(int uid) +getname(uid_t uid) { struct passwd *pw; @@ -58,7 +58,7 @@ getname(int uid) * Convert the passed name to a user id and return it. Return -1 * on error. */ -int +uid_t getuserid(char name[]) { struct passwd *pw; Modified: stable/10/usr.bin/mail/popen.c ============================================================================== --- stable/10/usr.bin/mail/popen.c Wed Jun 27 04:37:22 2018 (r335693) +++ stable/10/usr.bin/mail/popen.c Wed Jun 27 04:56:01 2018 (r335694) @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include "rcv.h" #include #include +#include +#include #include "extern.h" #define READ 0 @@ -46,22 +48,23 @@ __FBSDID("$FreeBSD$"); struct fp { FILE *fp; int pipe; - int pid; + pid_t pid; struct fp *link; }; static struct fp *fp_head; struct child { - int pid; + pid_t pid; char done; char free; int status; struct child *link; }; -static struct child *child; -static struct child *findchild(int); +static struct child *child, *child_freelist = NULL; + static void delchild(struct child *); -static int file_pid(FILE *); +static pid_t file_pid(FILE *); +static pid_t start_commandv(char *, sigset_t *, int, int, va_list); FILE * Fopen(const char *path, const char *mode) @@ -90,6 +93,7 @@ Fdopen(int fd, const char *mode) int Fclose(FILE *fp) { + unregister_file(fp); return (fclose(fp)); } @@ -99,7 +103,7 @@ Popen(char *cmd, const char *mode) { int p[2]; int myside, hisside, fd0, fd1; - int pid; + pid_t pid; sigset_t nset; FILE *fp; @@ -109,15 +113,15 @@ Popen(char *cmd, const char *mode) (void)fcntl(p[WRITE], F_SETFD, 1); if (*mode == 'r') { myside = p[READ]; - fd0 = -1; - hisside = fd1 = p[WRITE]; + hisside = fd0 = fd1 = p[WRITE]; } else { myside = p[WRITE]; hisside = fd0 = p[READ]; fd1 = -1; } (void)sigemptyset(&nset); - if ((pid = start_command(cmd, &nset, fd0, fd1, NULL, NULL, NULL)) < 0) { + pid = start_command(value("SHELL"), &nset, fd0, fd1, "-c", cmd, NULL); + if (pid < 0) { (void)close(p[READ]); (void)close(p[WRITE]); return (NULL); @@ -158,7 +162,7 @@ close_all_files(void) } void -register_file(FILE *fp, int pipe, int pid) +register_file(FILE *fp, int pipe, pid_t pid) { struct fp *fpp; @@ -186,7 +190,7 @@ unregister_file(FILE *fp) /*NOTREACHED*/ } -int +pid_t file_pid(FILE *fp) { struct fp *p; @@ -200,30 +204,17 @@ file_pid(FILE *fp) /* * Run a command without a shell, with optional arguments and splicing - * of stdin and stdout. The command name can be a sequence of words. + * of stdin (-1 means none) and stdout. The command name can be a sequence + * of words. * Signals must be handled by the caller. - * "Mask" contains the signals to ignore in the new process. - * SIGINT is enabled unless it's in the mask. + * "nset" contains the signals to ignore in the new process. + * SIGINT is enabled unless it's in "nset". */ -/*VARARGS4*/ -int -run_command(char *cmd, sigset_t *mask, int infd, int outfd, char *a0, - char *a1, char *a2) +static pid_t +start_commandv(char *cmd, sigset_t *nset, int infd, int outfd, va_list args) { - int pid; + pid_t pid; - if ((pid = start_command(cmd, mask, infd, outfd, a0, a1, a2)) < 0) - return (-1); - return (wait_command(pid)); -} - -/*VARARGS4*/ -int -start_command(char *cmd, sigset_t *mask, int infd, int outfd, char *a0, - char *a1, char *a2) -{ - int pid; - if ((pid = fork()) < 0) { warn("fork"); return (-1); @@ -232,11 +223,10 @@ start_command(char *cmd, sigset_t *mask, int infd, int char *argv[100]; int i = getrawlist(cmd, argv, sizeof(argv) / sizeof(*argv)); - if ((argv[i++] = a0) != NULL && - (argv[i++] = a1) != NULL && - (argv[i++] = a2) != NULL) - argv[i] = NULL; - prepare_child(mask, infd, outfd); + while ((argv[i++] = va_arg(args, char *))) + ; + argv[i] = NULL; + prepare_child(nset, infd, outfd); execvp(argv[0], argv); warn("%s", argv[0]); _exit(1); @@ -244,6 +234,32 @@ start_command(char *cmd, sigset_t *mask, int infd, int return (pid); } +int +run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) +{ + pid_t pid; + va_list args; + + va_start(args, outfd); + pid = start_commandv(cmd, nset, infd, outfd, args); + va_end(args); + if (pid < 0) + return -1; + return wait_command(pid); +} + +int +start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...) +{ + va_list args; + int r; + + va_start(args, outfd); + r = start_commandv(cmd, nset, infd, outfd, args); + va_end(args); + return r; +} + void prepare_child(sigset_t *nset, int infd, int outfd) { @@ -268,7 +284,7 @@ prepare_child(sigset_t *nset, int infd, int outfd) } int -wait_command(int pid) +wait_command(pid_t pid) { if (wait_child(pid) < 0) { @@ -279,7 +295,7 @@ wait_command(int pid) } static struct child * -findchild(int pid) +findchild(pid_t pid, int dont_alloc) { struct child **cpp; @@ -287,9 +303,16 @@ findchild(int pid) cpp = &(*cpp)->link) ; if (*cpp == NULL) { - *cpp = malloc(sizeof(struct child)); - if (*cpp == NULL) - err(1, "Out of memory"); + if (dont_alloc) + return(NULL); + if (child_freelist) { + *cpp = child_freelist; + child_freelist = (*cpp)->link; + } else { + *cpp = malloc(sizeof(struct child)); + if (*cpp == NULL) + err(1, "malloc"); + } (*cpp)->pid = pid; (*cpp)->done = (*cpp)->free = 0; (*cpp)->link = NULL; @@ -305,19 +328,22 @@ delchild(struct child *cp) for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link) ; *cpp = cp->link; - (void)free(cp); + cp->link = child_freelist; + child_freelist = cp; } /*ARGSUSED*/ void sigchild(int signo __unused) { - int pid; + pid_t pid; int status; struct child *cp; + int save_errno; + save_errno = errno; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - cp = findchild(pid); + cp = findchild(pid, 1); if (cp->free) delchild(cp); else { @@ -325,6 +351,7 @@ sigchild(int signo __unused) cp->status = status; } } + errno = save_errno; } int wait_status; @@ -333,41 +360,51 @@ int wait_status; * Wait for a specific child to die. */ int -wait_child(int pid) +wait_child(pid_t pid) { - sigset_t nset, oset; struct child *cp; + sigset_t nset, oset; + pid_t rv = 0; (void)sigemptyset(&nset); (void)sigaddset(&nset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - cp = findchild(pid); - - while (!cp->done) - (void)sigsuspend(&oset); - wait_status = cp->status; - delchild(cp); + (void)sigprocmask(SIG_BLOCK, &nset, &oset); + /* + * If we have not already waited on the pid (via sigchild) + * wait on it now. Otherwise, use the wait status stashed + * by sigchild. + */ + cp = findchild(pid, 1); + if (cp == NULL || !cp->done) + rv = waitpid(pid, &wait_status, 0); + else + wait_status = cp->status; + if (cp != NULL) + delchild(cp); (void)sigprocmask(SIG_SETMASK, &oset, NULL); - return ((WIFEXITED(wait_status) && WEXITSTATUS(wait_status)) ? -1 : 0); + if (rv == -1 || (WIFEXITED(wait_status) && WEXITSTATUS(wait_status))) + return -1; + else + return 0; } /* * Mark a child as don't care. */ void -free_child(int pid) +free_child(pid_t pid) { + struct child *cp; sigset_t nset, oset; - struct child *cp = findchild(pid); (void)sigemptyset(&nset); (void)sigaddset(&nset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - if (cp->done) - delchild(cp); - else - cp->free = 1; + (void)sigprocmask(SIG_BLOCK, &nset, &oset); + if ((cp = findchild(pid, 0)) != NULL) { + if (cp->done) + delchild(cp); + else + cp->free = 1; + } (void)sigprocmask(SIG_SETMASK, &oset, NULL); }