Annotation of src/usr.bin/make/cmd_exec.c, Revision 1.5
1.1 espie 1: /* $OpenPackages$ */
1.5 ! espie 2: /* $OpenBSD: cmd_exec.c,v 1.4 2003/10/19 20:23:34 tedu 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: {
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;
67: }
68:
69: /* Fork */
1.2 mickey 70: switch (cpid = fork()) {
1.1 espie 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: */
1.3 millert 80: if (fds[1] != 1) {
81: (void)dup2(fds[1], 1);
1.1 espie 82: (void)close(fds[1]);
1.3 millert 83: }
1.1 espie 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: }
106: while (cc > 0 || (cc == -1 && errno == EINTR));
107:
108: /* Close the input side of the pipe. */
109: (void)close(fds[0]);
110:
111: /* Wait for the child to exit. */
112: while ((pid = wait(&status)) != cpid && pid >= 0)
113: continue;
114:
115: if (cc == -1)
116: *err = "Couldn't read shell's output for \"%s\"";
117:
118: if (status)
119: *err = "\"%s\" returned non-zero status";
120:
121: length = Buf_Size(&buf);
122: result = Buf_Retrieve(&buf);
123:
124: /* The result is null terminated, Convert newlines to spaces. */
125: cp = result + length - 1;
126:
1.4 tedu 127: if (cp >= result && *cp == '\n')
1.1 espie 128: /* A final newline is just stripped. */
129: *cp-- = '\0';
130:
131: while (cp >= result) {
132: if (*cp == '\n')
133: *cp = ' ';
134: cp--;
135: }
136: break;
137: }
138: return result;
139: bad:
140: return estrdup("");
141: }
142: