119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * fpopen.c --- unlike the libc popen, it directly executes the 319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * command instead of call out to the shell. 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright Theodore Ts'o, 1996-1999. 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Permission to use this file is granted for any purposes, as long as 819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * this copyright statement is kept intact and the author is not held 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * liable for any damages resulting from the use of this program. 1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * USE OF THIS SOFTWARE. 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h> 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h> 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h> 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h> 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <ctype.h> 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define MAX_ARGV 256 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern FILE *fpopen(const char *cmd, const char *mode); 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source ProjectFILE *fpopen(const char *cmd, const char *mode) 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *argv[MAX_ARGV]; 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int i = 0; 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf, *prog = 0; 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *p; 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int do_stdin, do_stderr = 0; 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int fds[2]; 4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pid_t pid; 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!mode) { 4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errno = EFAULT; 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return NULL; 4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (*mode) { 5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'r': 5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project do_stdin = 0; 5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case 'w': 5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project do_stdin = 1; 5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project default: 5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errno = EINVAL; 5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return NULL; 6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project switch (*(mode+1)) { 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project case '&': 6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project do_stderr = 1; 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Create the argv vector.... 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project buf = malloc(strlen(cmd)+1); 7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!buf) 7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return NULL; 7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project strcpy(buf, cmd); 7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p = buf; 7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (p && *p) { 7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (isspace(*p)) { 7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p++; 7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project continue; 7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (i == 0) 8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project prog = p; 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project argv[i++] = p; 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project p = strchr(p, ' '); 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (p) 8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *p++ = 0; 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project argv[i] = 0; 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Get the pipe 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pipe(fds) < 0) 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return NULL; 943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Fork and execute the correct program. */ 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((pid = fork()) < 0) { 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project perror("fork"); 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return NULL; 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else if (pid == 0) { 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (do_stdin) { 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fds[1]); 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dup2(fds[0], 0); 10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fds[0]); 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dup2(fds[1], 1); 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (do_stderr) 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dup2(fds[1], 2); 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (void) execvp(prog, argv); 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project perror(prog); 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(1); 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return fdopen(do_stdin ? fds[1] : fds[0], mode); 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 116