fpopen.c revision efc6f628e15de95bcd13e4f0ee223cb42115d520
123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)/* 223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * fpopen.c --- unlike the libc popen, it directly executes the 323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * command instead of call out to the shell. 423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Copyright Theodore Ts'o, 1996-1999. 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Permission to use this file is granted for any purposes, as long as 823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * this copyright statement is kept intact and the author is not held 923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * liable for any damages resulting from the use of this program. 1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * 1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * USE OF THIS SOFTWARE. 2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <unistd.h> 2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <stdlib.h> 2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <stdio.h> 2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <errno.h> 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <string.h> 2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include <ctype.h> 3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#define MAX_ARGV 256 3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)extern FILE *fpopen(const char *cmd, const char *mode); 3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)FILE *fpopen(const char *cmd, const char *mode) 3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles){ 3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) char *argv[MAX_ARGV]; 3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int i = 0; 3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) char *buf, *prog = 0; 4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) char *p; 4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int do_stdin, do_stderr = 0; 4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int fds[2]; 4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) pid_t pid; 4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!mode) { 4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) errno = EFAULT; 4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return NULL; 4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) switch (*mode) { 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case 'r': 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) do_stdin = 0; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case 'w': 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) do_stdin = 1; 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) default: 5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) errno = EINVAL; 5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return NULL; 6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) switch (*(mode+1)) { 6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case '&': 6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) do_stderr = 1; 6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /* 6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * Create the argv vector.... 6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) buf = malloc(strlen(cmd)+1); 7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!buf) 7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return NULL; 7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) strcpy(buf, cmd); 7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) p = buf; 7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) while (p && *p) { 7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (isspace(*p)) { 76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch p++; 77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch continue; 78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (i == 0) 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch prog = p; 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch argv[i++] = p; 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch p = strchr(p, ' '); 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (p) 84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *p++ = 0; 85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch argv[i] = 0; 88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /* 90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * Get the pipe 9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (pipe(fds) < 0) 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) /* Fork and execute the correct program. */ 9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if ((pid = fork()) < 0) { 9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) perror("fork"); 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else if (pid == 0) { 10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (do_stdin) { 10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) close(fds[1]); 10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) dup2(fds[0], 0); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) close(fds[0]); 10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) dup2(fds[1], 1); 10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (do_stderr) 10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) dup2(fds[1], 2); 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 109 (void) execvp(prog, argv); 110 perror(prog); 111 exit(1); 112 } 113 return fdopen(do_stdin ? fds[1] : fds[0], mode); 114} 115 116