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.
117 lines
2.4 KiB
117 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);
|
|
}
|
|
|