blob: ddf881899c9cb57413f88c6b03e5f23a3affbce7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
/*
* Modified 3/03/2001 Manuel Novoa III
*
* Added check for legal mode arg.
* Call fdopen and check return value before forking.
* Reduced code size by using variables pr and pnr instead of array refs.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */
#include <sys/syscall.h>
#if ! defined __NR_vfork
#define vfork fork
#endif
FILE *popen (const char *command, const char *mode)
{
FILE *fp;
int pipe_fd[2];
int pid, reading;
int pr, pnr;
reading = (mode[0] == 'r');
if ((!reading && (mode[0] != 'w')) || mode[1]) {
__set_errno(EINVAL); /* Invalid mode arg. */
} else if (pipe(pipe_fd) == 0) {
pr = pipe_fd[reading];
pnr = pipe_fd[1-reading];
if ((fp = fdopen(pnr, mode)) != NULL) {
if ((pid = vfork()) == 0) { /* vfork -- child */
close(pnr);
if (pr != reading) {
close(reading);
dup2(pr, reading);
close(pr);
}
execl("/bin/sh", "sh", "-c", command, (char *) 0);
_exit(255); /* execl failed! */
} else { /* vfork -- parent or failed */
close(pr);
if (pid > 0) { /* vfork -- parent */
return fp;
} else { /* vfork -- failed! */
fclose(fp);
}
}
} else { /* fdopen failed */
close(pr);
close(pnr);
}
}
return NULL;
}
int pclose(FILE *fd)
{
int waitstat;
if (fclose(fd) != 0) {
return EOF;
}
wait(&waitstat);
return waitstat;
}
|