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