=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/make/main.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- src/usr.bin/make/main.c 1996/04/21 23:43:21 1.7 +++ src/usr.bin/make/main.c 1996/09/02 16:04:13 1.8 @@ -1,5 +1,5 @@ -/* $OpenBSD: main.c,v 1.7 1996/04/21 23:43:21 deraadt Exp $ */ -/* $NetBSD: main.c,v 1.28 1996/03/31 21:30:05 christos Exp $ */ +/* $OpenBSD: main.c,v 1.8 1996/09/02 16:04:13 briggs Exp $ */ +/* $NetBSD: main.c,v 1.30 1996/08/13 16:42:08 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -50,7 +50,7 @@ static char sccsid[] = "@(#)main.c 5.25 (Berkeley) 4/1/91"; static char rcsid[] = "$NetBSD: main.c,v 1.26 1996/03/11 13:45:33 christos Exp $"; #else -static char rcsid[] = "$OpenBSD: main.c,v 1.7 1996/04/21 23:43:21 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: main.c,v 1.8 1996/09/02 16:04:13 briggs Exp $"; #endif #endif /* not lint */ @@ -88,6 +88,7 @@ #include #include #include +#include #include #include #include @@ -337,7 +338,7 @@ optind = 1; /* - */ goto rearg; } - (void)Lst_AtEnd(create, (ClientData)strdup(*argv)); + (void)Lst_AtEnd(create, (ClientData)estrdup(*argv)); } } @@ -825,6 +826,142 @@ } /*- + * Cmd_Exec -- + * Execute the command in cmd, and return the output of that command + * in a string. + * + * Results: + * A string containing the output of the command, or the empty string + * If err is not NULL, it contains the reason for the command failure + * + * Side Effects: + * The string must be freed by the caller. + */ +char * +Cmd_Exec(cmd, err) + char *cmd; + char **err; +{ + char *args[4]; /* Args for invoking the shell */ + int fds[2]; /* Pipe streams */ + int cpid; /* Child PID */ + int pid; /* PID from wait() */ + char *res; /* result */ + int status; /* command exit status */ + Buffer buf; /* buffer to store the result */ + char *cp; + int cc; + + + *err = NULL; + + /* + * Set up arguments for shell + */ + args[0] = "sh"; + args[1] = "-c"; + args[2] = cmd; + args[3] = NULL; + + /* + * Open a pipe for fetching its output + */ + if (pipe(fds) == -1) { + *err = "Couldn't create pipe for \"%s\""; + goto bad; + } + + /* + * Fork + */ + switch (cpid = vfork()) { + case 0: + /* + * Close input side of pipe + */ + (void) close(fds[0]); + + /* + * Duplicate the output stream to the shell's output, then + * shut the extra thing down. Note we don't fetch the error + * stream...why not? Why? + */ + (void) dup2(fds[1], 1); + (void) close(fds[1]); + + (void) execv("/bin/sh", args); + _exit(1); + /*NOTREACHED*/ + + case -1: + *err = "Couldn't exec \"%s\""; + goto bad; + + default: + /* + * No need for the writing half + */ + (void) close(fds[1]); + + buf = Buf_Init (MAKE_BSIZE); + + do { + char result[BUFSIZ]; + cc = read(fds[0], result, sizeof(result)); + if (cc > 0) + Buf_AddBytes(buf, cc, (Byte *) result); + } + while (cc > 0 || (cc == -1 && errno == EINTR)); + + /* + * Close the input side of the pipe. + */ + (void) close(fds[0]); + + /* + * Wait for the process to exit. + */ + while(((pid = wait(&status)) != cpid) && (pid >= 0)) + continue; + + res = (char *)Buf_GetAll (buf, &cc); + Buf_Destroy (buf, FALSE); + + if (cc == 0) + *err = "Couldn't read shell's output for \"%s\""; + + if (status) + *err = "\"%s\" returned non-zero status"; + + /* + * Null-terminate the result, convert newlines to spaces and + * install it in the variable. + */ + res[cc] = '\0'; + cp = &res[cc] - 1; + + if (*cp == '\n') { + /* + * A final newline is just stripped + */ + *cp-- = '\0'; + } + while (cp >= res) { + if (*cp == '\n') { + *cp = ' '; + } + cp--; + } + break; + } + return res; +bad: + res = emalloc(1); + *res = '\0'; + return res; +} + +/*- * Error -- * Print an error message given its format. * @@ -988,6 +1125,21 @@ void *p; if ((p = malloc(len)) == NULL) + enomem(); + return(p); +} + +/* + * emalloc -- + * strdup, but die on error. + */ +char * +estrdup(str) + const char *str; +{ + char *p; + + if ((p = strdup(str)) == NULL) enomem(); return(p); }