Annotation of src/usr.bin/make/cmd_exec.c, Revision 1.6
1.1 espie 1: /* $OpenPackages$ */
1.6 ! espie 2: /* $OpenBSD: cmd_exec.c,v 1.5 2004/04/07 13:11:35 espie Exp $ */
1.1 espie 3: /*
4: * Copyright (c) 2001 Marc Espie.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
16: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
19: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
29: #include <sys/wait.h>
30: #include <errno.h>
31: #include <stdio.h>
32: #include <unistd.h>
33: #include "config.h"
34: #include "defines.h"
35: #include "cmd_exec.h"
36: #include "buf.h"
37: #include "memory.h"
38: #include "pathnames.h"
39:
40: char *
1.5 espie 41: Cmd_Exec(const char *cmd, char **err)
1.1 espie 42: {
1.6 ! espie 43: char *args[4]; /* Args for invoking the shell */
! 44: int fds[2]; /* Pipe streams */
! 45: pid_t cpid; /* Child PID */
! 46: pid_t pid; /* PID from wait() */
! 47: char *result; /* Result */
! 48: int status; /* Command exit status */
! 49: BUFFER buf; /* Buffer to store the result. */
! 50: char *cp; /* Pointer into result. */
! 51: ssize_t cc; /* Characters read from pipe. */
! 52: size_t length; /* Total length of result. */
! 53:
! 54:
! 55: *err = NULL;
! 56:
! 57: /* Set up arguments for the shell. */
! 58: args[0] = "sh";
! 59: args[1] = "-c";
! 60: args[2] = (char *)cmd;
! 61: args[3] = NULL;
! 62:
! 63: /* Open a pipe for retrieving shell's output. */
! 64: if (pipe(fds) == -1) {
! 65: *err = "Couldn't create pipe for \"%s\"";
! 66: goto bad;
1.3 millert 67: }
1.1 espie 68:
1.6 ! espie 69: /* Fork */
! 70: switch (cpid = fork()) {
! 71: case 0:
! 72: /* Close input side of pipe */
! 73: (void)close(fds[0]);
! 74:
! 75: /* Duplicate the output stream to the shell's output, then
! 76: * shut the extra thing down. Note we don't fetch the error
! 77: * stream: user can use redirection to grab it as this goes
! 78: * through /bin/sh.
! 79: */
! 80: if (fds[1] != 1) {
! 81: (void)dup2(fds[1], 1);
! 82: (void)close(fds[1]);
! 83: }
! 84:
! 85: (void)execv(_PATH_BSHELL, args);
! 86: _exit(1);
! 87: /*NOTREACHED*/
! 88:
! 89: case -1:
! 90: *err = "Couldn't exec \"%s\"";
! 91: goto bad;
! 92:
! 93: default:
! 94: /* No need for the writing half. */
! 95: (void)close(fds[1]);
! 96:
! 97: Buf_Init(&buf, MAKE_BSIZE);
! 98:
! 99: do {
! 100: char grab[BUFSIZ];
! 101:
! 102: cc = read(fds[0], grab, sizeof(grab));
! 103: if (cc > 0)
! 104: Buf_AddChars(&buf, cc, grab);
! 105: } while (cc > 0 || (cc == -1 && errno == EINTR));
! 106:
! 107: /* Close the input side of the pipe. */
! 108: (void)close(fds[0]);
! 109:
! 110: /* Wait for the child to exit. */
! 111: while ((pid = wait(&status)) != cpid && pid >= 0)
! 112: continue;
! 113:
! 114: if (cc == -1)
! 115: *err = "Couldn't read shell's output for \"%s\"";
! 116:
! 117: if (status)
! 118: *err = "\"%s\" returned non-zero status";
! 119:
! 120: length = Buf_Size(&buf);
! 121: result = Buf_Retrieve(&buf);
! 122:
! 123: /* The result is null terminated, Convert newlines to spaces. */
! 124: cp = result + length - 1;
! 125:
! 126: if (cp >= result && *cp == '\n')
! 127: /* A final newline is just stripped. */
! 128: *cp-- = '\0';
! 129:
! 130: while (cp >= result) {
! 131: if (*cp == '\n')
! 132: *cp = ' ';
! 133: cp--;
! 134: }
! 135: break;
1.1 espie 136: }
1.6 ! espie 137: return result;
! 138: bad:
! 139: return estrdup("");
1.1 espie 140: }
141: