You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.4 KiB
116 lines
2.4 KiB
/* |
|
* fpopen.c --- unlike the libc popen, it directly executes the |
|
* command instead of call out to the shell. |
|
* |
|
* Copyright Theodore Ts'o, 1996-1999. |
|
* |
|
* Permission to use this file is granted for any purposes, as long as |
|
* this copyright statement is kept intact and the author is not held |
|
* liable for any damages resulting from the use of this program. |
|
* |
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF |
|
* WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE |
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|
* USE OF THIS SOFTWARE. |
|
*/ |
|
|
|
#include "config.h" |
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <errno.h> |
|
#include <string.h> |
|
#include <ctype.h> |
|
|
|
#define MAX_ARGV 256 |
|
|
|
extern FILE *fpopen(const char *cmd, const char *mode); |
|
|
|
FILE *fpopen(const char *cmd, const char *mode) |
|
{ |
|
char *argv[MAX_ARGV]; |
|
int i = 0; |
|
char *buf, *prog = 0; |
|
char *p; |
|
int do_stdin, do_stderr = 0; |
|
int fds[2]; |
|
pid_t pid; |
|
|
|
if (!mode) { |
|
errno = EFAULT; |
|
return NULL; |
|
} |
|
|
|
switch (*mode) { |
|
case 'r': |
|
do_stdin = 0; |
|
break; |
|
case 'w': |
|
do_stdin = 1; |
|
break; |
|
default: |
|
errno = EINVAL; |
|
return NULL; |
|
} |
|
switch (*(mode+1)) { |
|
case '&': |
|
do_stderr = 1; |
|
} |
|
|
|
/* |
|
* Create the argv vector.... |
|
*/ |
|
buf = malloc(strlen(cmd)+1); |
|
if (!buf) |
|
return NULL; |
|
strcpy(buf, cmd); |
|
p = buf; |
|
while (p && *p) { |
|
if (isspace(*p)) { |
|
p++; |
|
continue; |
|
} |
|
if (i == 0) |
|
prog = p; |
|
argv[i++] = p; |
|
p = strchr(p, ' '); |
|
if (p) |
|
*p++ = 0; |
|
} |
|
|
|
argv[i] = 0; |
|
|
|
/* |
|
* Get the pipe |
|
*/ |
|
if (pipe(fds) < 0) |
|
return NULL; |
|
|
|
/* Fork and execute the correct program. */ |
|
if ((pid = fork()) < 0) { |
|
perror("fork"); |
|
return NULL; |
|
} else if (pid == 0) { |
|
if (do_stdin) { |
|
close(fds[1]); |
|
dup2(fds[0], 0); |
|
} else { |
|
close(fds[0]); |
|
dup2(fds[1], 1); |
|
if (do_stderr) |
|
dup2(fds[1], 2); |
|
} |
|
(void) execvp(prog, argv); |
|
perror(prog); |
|
exit(1); |
|
} |
|
return fdopen(do_stdin ? fds[1] : fds[0], mode); |
|
} |
|
|
|
|