Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / lib / fpopen.c
1 /*
2  * fpopen.c --- unlike the libc popen, it directly executes the
3  * command instead of call out to the shell.
4  */
5
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 #define MAX_ARGV 256
14
15 extern FILE *fpopen(const char *cmd, const char *mode);
16
17 FILE *fpopen(const char *cmd, const char *mode)
18 {
19         char    *argv[MAX_ARGV];
20         int     i = 0;
21         char    *buf, *prog = 0;
22         char    *p;
23         int     do_stdin;
24         int     fds[2];
25         pid_t   pid;
26
27         if (!mode) {
28                 errno = EFAULT;
29                 return NULL;
30         }
31         
32         switch (*mode) {
33         case 'r':
34                 do_stdin = 0;
35                 break;
36         case 'w':
37                 do_stdin = 1;
38                 break;
39         default:
40                 errno = EINVAL;
41                 return NULL;
42         }
43
44         /*
45          * Create the argv vector....
46          */
47         buf = malloc(strlen(cmd)+1);
48         if (!buf)
49                 return NULL;
50         strcpy(buf, cmd);
51         p = buf;
52         while (p && *p) {
53                 if (isspace(*p)) {
54                         p++;
55                         continue;
56                 }
57                 if (i == 0)
58                         prog = p;
59                 argv[i++] = p;
60                 p = strchr(p, ' ');
61                 if (p)
62                         *p++ = 0;
63         }
64
65         argv[i] = 0;
66
67         /*
68          * Get the pipe
69          */
70         if (pipe(fds) < 0)
71                 return NULL;
72         
73         /* Fork and execute the correct program. */
74         if ((pid = fork()) < 0) {
75                 perror("fork");
76                 return NULL;
77         } else if (pid == 0) {
78                 if (do_stdin) {
79                         close(fds[1]);
80                         dup2(fds[0], 0);
81                 } else {
82                         close(fds[0]);
83                         dup2(fds[1], 1);
84                 }
85                 (void) execvp(prog, argv);
86                 perror(prog);
87                 exit(1);
88         }
89         return fdopen(do_stdin ? fds[1] : fds[0], mode);
90 }
91