1 /* Written by Anthony Liguori <aliguori@us.ibm.com> */
2 
3 #include <stdio.h>
4 #include <getopt.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <err.h>
8 
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #include <unistd.h>
12 
13 #define PACKAGE_NAME "procpipe"
14 #define PACKAGE_VERSION "0.0.1"
15 
16 #define GPL_SHORT \
17 "This is free software; see the source for copying conditions.  There is NO\n"\
18 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
19 
20 #define PACKAGE_BUGS "aliguori@us.ibm.com"
21 #define PACKAGE_AUTHOR "Anthony Liguori"
22 #define PACKAGE_OWNER "IBM, Corp."
23 #define PACKAGE_LICENSE GPL_SHORT
24 
usage(const char * name)25 static void usage(const char *name)
26 {
27 	printf("Usage: %s [OPTIONS]\n"
28 	       "\n"
29 	       "  -h, --help      display this help and exit\n"
30 	       "  -V, --version   output version information and exit\n"
31 	       "\n"
32 	       "Report bugs to <%s>.\n"
33 	       , name, PACKAGE_BUGS);
34 }
35 
version(const char * name)36 static void version(const char *name)
37 {
38 	printf("%s (%s) %s\n"
39 	       "Written by %s.\n"
40 	       "\n"
41 	       "Copyright (C) 2005 %s.\n"
42 	       "%s\n"
43 	       , name, PACKAGE_NAME, PACKAGE_VERSION,
44 	       PACKAGE_AUTHOR, PACKAGE_OWNER, PACKAGE_LICENSE);
45 }
46 
exec(int stdout,int stdin,const char * cmd)47 static pid_t exec(int stdout, int stdin, const char *cmd)
48 {
49 	pid_t pid;
50 
51 	pid = fork();
52 	if (pid == 0) {
53 		close(STDOUT_FILENO);
54 		dup2(stdout, STDOUT_FILENO);
55 		close(STDIN_FILENO);
56 		dup2(stdin, STDIN_FILENO);
57 
58 		execlp("/bin/sh", "sh", "-c", cmd, NULL);
59 	}
60 
61 	return pid;
62 }
63 
main(int argc,char ** argv)64 int main(int argc, char **argv)
65 {
66 	int ch, opt_ind = 0;
67 	const char *sopt = "hV";
68 	struct option lopt[] = {
69 		{ "help", 0, 0, 'h' },
70 		{ "version", 0, 0, 'V' },
71 		{ 0 }
72 	};
73 	int host_stdout[2];
74 	int host_stdin[2];
75 	int res;
76 	pid_t pid1, pid2;
77 	int status;
78 
79 	while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
80 		switch (ch) {
81 		case 'h':
82 			usage(argv[0]);
83 			exit(0);
84 		case 'V':
85 			version(argv[0]);
86 			exit(0);
87 		case '?':
88 			errx(EINVAL, "Try `%s --help' for more information.",
89 			     argv[0]);
90 		}
91 	}
92 
93 	if ((argc - optind) != 2) {
94 		errx(EINVAL, "Two commands are required.\n"
95 		     "Try `%s --help' for more information.", argv[0]);
96 	}
97 
98 	res = pipe(host_stdout);
99 	if (res == -1) {
100 		err(errno, "pipe() failed");
101 	}
102 
103 	res = pipe(host_stdin);
104 	if (res == -1) {
105 		err(errno, "pipe() failed");
106 	}
107 
108 	pid1 = exec(host_stdout[1], host_stdin[0], argv[optind]);
109 	if (pid1 == -1) {
110 		err(errno, "exec(%s)", argv[optind]);
111 	}
112 
113 	pid2 = exec(host_stdin[1], host_stdout[0], argv[optind + 1]);
114 	if (pid2 == -1) {
115 		err(errno, "exec(%s)", argv[optind + 1]);
116 	}
117 
118 	waitpid(pid1, &status, 0);
119 	if (WIFEXITED(status)) status = WEXITSTATUS(status);
120 
121 	if (status != 0) {
122 		printf("Child exited with status %d\n", status);
123 	}
124 
125 	waitpid(pid2, &status, 0);
126 	if (WIFEXITED(status)) status = WEXITSTATUS(status);
127 
128 	if (status != 0) {
129 		printf("Child2 exited with status %d\n", status);
130 	}
131 
132 	return 0;
133 }
134