1 /* 2 * fpopen.c --- unlike the libc popen, it directly executes the 3 * command instead of call out to the shell. 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. 22 */ 23 24 #include "config.h" 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; 42 int do_stdin, do_stderr = 0; 43 int fds[2]; 44 pid_t pid; 45 46 if (!mode) { 47 errno = EFAULT; 48 return NULL; 49 } 50 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 } 62 switch (*(mode+1)) { 63 case '&': 64 do_stderr = 1; 65 } 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; 95 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); 107 if (do_stderr) 108 dup2(fds[1], 2); 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 117