]>
Commit | Line | Data |
---|---|---|
f3db3566 TT |
1 | /* |
2 | * fpopen.c --- unlike the libc popen, it directly executes the | |
3 | * command instead of call out to the shell. | |
e2e69ba4 TT |
4 | * |
5 | * Copyright Theodore Ts'o, 1996-1999. | |
6 | * | |
7 | * Permission to use this file is granted for any purposes, as long as | |
8 | * this copyright statement is kept intact and the author is not held | |
9 | * liable for any damages resulting from the use of this program. | |
10 | * | |
11 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
12 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
13 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF | |
14 | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
15 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
16 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT | |
17 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
18 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
19 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
21 | * USE OF THIS SOFTWARE. | |
f3db3566 TT |
22 | */ |
23 | ||
d1154eb4 | 24 | #include "config.h" |
f3db3566 TT |
25 | #include <unistd.h> |
26 | #include <stdlib.h> | |
27 | #include <stdio.h> | |
28 | #include <errno.h> | |
29 | #include <string.h> | |
30 | #include <ctype.h> | |
31 | ||
32 | #define MAX_ARGV 256 | |
33 | ||
34 | extern FILE *fpopen(const char *cmd, const char *mode); | |
35 | ||
36 | FILE *fpopen(const char *cmd, const char *mode) | |
37 | { | |
38 | char *argv[MAX_ARGV]; | |
39 | int i = 0; | |
40 | char *buf, *prog = 0; | |
41 | char *p; | |
e2e69ba4 | 42 | int do_stdin, do_stderr = 0; |
f3db3566 TT |
43 | int fds[2]; |
44 | pid_t pid; | |
45 | ||
46 | if (!mode) { | |
47 | errno = EFAULT; | |
48 | return NULL; | |
49 | } | |
efc6f628 | 50 | |
f3db3566 TT |
51 | switch (*mode) { |
52 | case 'r': | |
53 | do_stdin = 0; | |
54 | break; | |
55 | case 'w': | |
56 | do_stdin = 1; | |
57 | break; | |
58 | default: | |
59 | errno = EINVAL; | |
60 | return NULL; | |
61 | } | |
e2e69ba4 TT |
62 | switch (*(mode+1)) { |
63 | case '&': | |
64 | do_stderr = 1; | |
65 | } | |
f3db3566 TT |
66 | |
67 | /* | |
68 | * Create the argv vector.... | |
69 | */ | |
70 | buf = malloc(strlen(cmd)+1); | |
71 | if (!buf) | |
72 | return NULL; | |
73 | strcpy(buf, cmd); | |
74 | p = buf; | |
75 | while (p && *p) { | |
76 | if (isspace(*p)) { | |
77 | p++; | |
78 | continue; | |
79 | } | |
80 | if (i == 0) | |
81 | prog = p; | |
82 | argv[i++] = p; | |
83 | p = strchr(p, ' '); | |
84 | if (p) | |
85 | *p++ = 0; | |
86 | } | |
87 | ||
88 | argv[i] = 0; | |
89 | ||
90 | /* | |
91 | * Get the pipe | |
92 | */ | |
93 | if (pipe(fds) < 0) | |
94 | return NULL; | |
efc6f628 | 95 | |
f3db3566 TT |
96 | /* Fork and execute the correct program. */ |
97 | if ((pid = fork()) < 0) { | |
98 | perror("fork"); | |
99 | return NULL; | |
100 | } else if (pid == 0) { | |
101 | if (do_stdin) { | |
102 | close(fds[1]); | |
103 | dup2(fds[0], 0); | |
104 | } else { | |
105 | close(fds[0]); | |
106 | dup2(fds[1], 1); | |
e2e69ba4 TT |
107 | if (do_stderr) |
108 | dup2(fds[1], 2); | |
f3db3566 TT |
109 | } |
110 | (void) execvp(prog, argv); | |
111 | perror(prog); | |
112 | exit(1); | |
113 | } | |
114 | return fdopen(do_stdin ? fds[1] : fds[0], mode); | |
115 | } | |
116 |