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