Annotation of src/usr.bin/make/cmd_exec.c, Revision 1.4
1.1 espie 1: /* $OpenPackages$ */
1.4 ! tedu 2: /* $OpenBSD: cmd_exec.c,v 1.3 2002/08/05 17:04:36 millert 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 *
41: Cmd_Exec(cmd, err)
42: const char *cmd;
43: char **err;
44: {
45: char *args[4]; /* Args for invoking the shell */
46: int fds[2]; /* Pipe streams */
47: pid_t cpid; /* Child PID */
48: pid_t pid; /* PID from wait() */
49: char *result; /* Result */
50: int status; /* Command exit status */
51: BUFFER buf; /* Buffer to store the result. */
52: char *cp; /* Pointer into result. */
53: ssize_t cc; /* Characters read from pipe. */
54: size_t length; /* Total length of result. */
55:
56:
57: *err = NULL;
58:
59: /* Set up arguments for the shell. */
60: args[0] = "sh";
61: args[1] = "-c";
62: args[2] = (char *)cmd;
63: args[3] = NULL;
64:
65: /* Open a pipe for retrieving shell's output. */
66: if (pipe(fds) == -1) {
67: *err = "Couldn't create pipe for \"%s\"";
68: goto bad;
69: }
70:
71: /* Fork */
1.2 mickey 72: switch (cpid = fork()) {
1.1 espie 73: case 0:
74: /* Close input side of pipe */
75: (void)close(fds[0]);
76:
77: /* Duplicate the output stream to the shell's output, then
78: * shut the extra thing down. Note we don't fetch the error
79: * stream: user can use redirection to grab it as this goes
80: * through /bin/sh.
81: */
1.3 millert 82: if (fds[1] != 1) {
83: (void)dup2(fds[1], 1);
1.1 espie 84: (void)close(fds[1]);
1.3 millert 85: }
1.1 espie 86:
87: (void)execv(_PATH_BSHELL, args);
88: _exit(1);
89: /*NOTREACHED*/
90:
91: case -1:
92: *err = "Couldn't exec \"%s\"";
93: goto bad;
94:
95: default:
96: /* No need for the writing half. */
97: (void)close(fds[1]);
98:
99: Buf_Init(&buf, MAKE_BSIZE);
100:
101: do {
102: char grab[BUFSIZ];
103:
104: cc = read(fds[0], grab, sizeof(grab));
105: if (cc > 0)
106: Buf_AddChars(&buf, cc, grab);
107: }
108: while (cc > 0 || (cc == -1 && errno == EINTR));
109:
110: /* Close the input side of the pipe. */
111: (void)close(fds[0]);
112:
113: /* Wait for the child to exit. */
114: while ((pid = wait(&status)) != cpid && pid >= 0)
115: continue;
116:
117: if (cc == -1)
118: *err = "Couldn't read shell's output for \"%s\"";
119:
120: if (status)
121: *err = "\"%s\" returned non-zero status";
122:
123: length = Buf_Size(&buf);
124: result = Buf_Retrieve(&buf);
125:
126: /* The result is null terminated, Convert newlines to spaces. */
127: cp = result + length - 1;
128:
1.4 ! tedu 129: if (cp >= result && *cp == '\n')
1.1 espie 130: /* A final newline is just stripped. */
131: *cp-- = '\0';
132:
133: while (cp >= result) {
134: if (*cp == '\n')
135: *cp = ' ';
136: cp--;
137: }
138: break;
139: }
140: return result;
141: bad:
142: return estrdup("");
143: }
144: