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 24d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 25f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <unistd.h> 26f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <stdlib.h> 27f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <stdio.h> 28f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <errno.h> 29f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <string.h> 30f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <ctype.h> 31f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 32f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define MAX_ARGV 256 33f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 34f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'oextern FILE *fpopen(const char *cmd, const char *mode); 35f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'oFILE *fpopen(const char *cmd, const char *mode) 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o char *argv[MAX_ARGV]; 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int i = 0; 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o char *buf, *prog = 0; 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o char *p; 42e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o int do_stdin, do_stderr = 0; 43f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int fds[2]; 44f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o pid_t pid; 45f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 46f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!mode) { 47f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o errno = EFAULT; 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return NULL; 49f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 50efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 51f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o switch (*mode) { 52f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o case 'r': 53f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o do_stdin = 0; 54f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o break; 55f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o case 'w': 56f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o do_stdin = 1; 57f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o break; 58f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o default: 59f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o errno = EINVAL; 60f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return NULL; 61f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 62e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o switch (*(mode+1)) { 63e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o case '&': 64e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o do_stderr = 1; 65e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o } 66f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 67f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 68f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * Create the argv vector.... 69f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 70f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o buf = malloc(strlen(cmd)+1); 71f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!buf) 72f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return NULL; 73f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o strcpy(buf, cmd); 74f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o p = buf; 75f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o while (p && *p) { 76f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (isspace(*p)) { 77f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o p++; 78f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o continue; 79f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 80f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (i == 0) 81f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o prog = p; 82f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o argv[i++] = p; 83f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o p = strchr(p, ' '); 84f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (p) 85f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *p++ = 0; 86f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 87f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 88f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o argv[i] = 0; 89f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 90f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 91f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * Get the pipe 92f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 93f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (pipe(fds) < 0) 94f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return NULL; 95efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* Fork and execute the correct program. */ 97f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if ((pid = fork()) < 0) { 98f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o perror("fork"); 99f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return NULL; 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else if (pid == 0) { 101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (do_stdin) { 102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o close(fds[1]); 103f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o dup2(fds[0], 0); 104f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else { 105f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o close(fds[0]); 106f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o dup2(fds[1], 1); 107e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o if (do_stderr) 108e2e69ba4553ea6c84b6d3d48284170aa1d1a2b80Theodore Ts'o dup2(fds[1], 2); 109f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (void) execvp(prog, argv); 111f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o perror(prog); 112f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit(1); 113f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 114f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return fdopen(do_stdin ? fds[1] : fds[0], mode); 115f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 116f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 117