Mercurial > hg > CbC > CbC_gcc
comparison fixincludes/procopen.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 | |
2 /* | |
3 * server.c Set up and handle communications with a server process. | |
4 * | |
5 * Server Handling copyright 1992-1999, 2004 The Free Software Foundation | |
6 * | |
7 * Server Handling is free software. | |
8 * You may redistribute it and/or modify it under the terms of the | |
9 * GNU General Public License, as published by the Free Software | |
10 * Foundation; either version 2, or (at your option) any later version. | |
11 * | |
12 * Server Handling is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with Server Handling. See the file "COPYING". If not, | |
19 * write to: The Free Software Foundation, Inc., | |
20 * 51 Franklin Street, Fifth Floor, | |
21 * Boston, MA 02110-1301, USA. | |
22 * | |
23 * As a special exception, The Free Software Foundation gives | |
24 * permission for additional uses of the text contained in his release | |
25 * of ServerHandler. | |
26 * | |
27 * The exception is that, if you link the ServerHandler library with other | |
28 * files to produce an executable, this does not by itself cause the | |
29 * resulting executable to be covered by the GNU General Public License. | |
30 * Your use of that executable is in no way restricted on account of | |
31 * linking the ServerHandler library code into it. | |
32 * | |
33 * This exception does not however invalidate any other reasons why | |
34 * the executable file might be covered by the GNU General Public License. | |
35 * | |
36 * This exception applies only to the code released by The Free | |
37 * Software Foundation under the name ServerHandler. If you copy code | |
38 * from other sources under the General Public License into a copy of | |
39 * ServerHandler, as the General Public License permits, the exception | |
40 * does not apply to the code that you add in this way. To avoid | |
41 * misleading anyone as to the status of such modified files, you must | |
42 * delete this exception notice from them. | |
43 * | |
44 * If you write modifications of your own for ServerHandler, it is your | |
45 * choice whether to permit this exception to apply to your modifications. | |
46 * If you do not wish that, delete this exception notice. | |
47 */ | |
48 | |
49 #include "fixlib.h" | |
50 #include "server.h" | |
51 | |
52 STATIC const char* def_args[] = | |
53 { (char *) NULL, (char *) NULL }; | |
54 | |
55 /* | |
56 * chain_open | |
57 * | |
58 * Given an FD for an inferior process to use as stdin, | |
59 * start that process and return a NEW FD that that process | |
60 * will use for its stdout. Requires the argument vector | |
61 * for the new process and, optionally, a pointer to a place | |
62 * to store the child's process id. | |
63 */ | |
64 int | |
65 chain_open (int stdin_fd, tCC** pp_args, pid_t* p_child) | |
66 { | |
67 t_fd_pair stdout_pair; | |
68 pid_t ch_id; | |
69 tCC *pz_cmd; | |
70 | |
71 stdout_pair.read_fd = stdout_pair.write_fd = -1; | |
72 | |
73 /* | |
74 * Create a pipe it will be the child process' stdout, | |
75 * and the parent will read from it. | |
76 */ | |
77 if (pipe ((int *) &stdout_pair) < 0) | |
78 { | |
79 if (p_child != (pid_t *) NULL) | |
80 *p_child = NOPROCESS; | |
81 return -1; | |
82 } | |
83 | |
84 /* | |
85 * If we did not get an arg list, use the default | |
86 */ | |
87 if (pp_args == (tCC **) NULL) | |
88 pp_args = def_args; | |
89 | |
90 /* | |
91 * If the arg list does not have a program, | |
92 * assume the "SHELL" from the environment, or, failing | |
93 * that, then sh. Set argv[0] to whatever we decided on. | |
94 */ | |
95 if (pz_cmd = *pp_args, | |
96 (pz_cmd == (char *) NULL) || (*pz_cmd == '\0')) | |
97 { | |
98 | |
99 pz_cmd = getenv ("SHELL"); | |
100 if (pz_cmd == (char *) NULL) | |
101 pz_cmd = "sh"; | |
102 } | |
103 | |
104 #ifdef DEBUG_PRINT | |
105 printf ("START: %s\n", pz_cmd); | |
106 { | |
107 int idx = 0; | |
108 | |
109 while (pp_args[++idx] != (char *) NULL) | |
110 printf (" ARG %2d: %s\n", idx, pp_args[idx]); | |
111 } | |
112 #endif | |
113 | |
114 /* | |
115 * Call fork() and see which process we become | |
116 */ | |
117 ch_id = fork (); | |
118 switch (ch_id) | |
119 { | |
120 case NOPROCESS: /* parent - error in call */ | |
121 close (stdout_pair.read_fd); | |
122 close (stdout_pair.write_fd); | |
123 if (p_child != (pid_t *) NULL) | |
124 *p_child = NOPROCESS; | |
125 return -1; | |
126 | |
127 default: /* parent - return opposite FD's */ | |
128 if (p_child != (pid_t *) NULL) | |
129 *p_child = ch_id; | |
130 #ifdef DEBUG_PRINT | |
131 printf ("for pid %d: stdin from %d, stdout to %d\n" | |
132 "for parent: read from %d\n", | |
133 ch_id, stdin_fd, stdout_pair.write_fd, stdout_pair.read_fd); | |
134 #endif | |
135 close (stdin_fd); | |
136 close (stdout_pair.write_fd); | |
137 return stdout_pair.read_fd; | |
138 | |
139 case NULLPROCESS: /* child - continue processing */ | |
140 break; | |
141 } | |
142 | |
143 /* | |
144 * Close the pipe end handed back to the parent process | |
145 */ | |
146 close (stdout_pair.read_fd); | |
147 | |
148 /* | |
149 * Close our current stdin and stdout | |
150 */ | |
151 close (STDIN_FILENO); | |
152 close (STDOUT_FILENO); | |
153 | |
154 /* | |
155 * Make the fd passed in the stdin, and the write end of | |
156 * the new pipe become the stdout. | |
157 */ | |
158 dup2 (stdout_pair.write_fd, STDOUT_FILENO); | |
159 dup2 (stdin_fd, STDIN_FILENO); | |
160 | |
161 if (*pp_args == (char *) NULL) | |
162 *pp_args = pz_cmd; | |
163 | |
164 execvp (pz_cmd, (char**)pp_args); | |
165 fprintf (stderr, "Error %d: Could not execvp( '%s', ... ): %s\n", | |
166 errno, pz_cmd, xstrerror (errno)); | |
167 exit (EXIT_PANIC); | |
168 } | |
169 | |
170 | |
171 /* | |
172 * proc2_open | |
173 * | |
174 * Given a pointer to an argument vector, start a process and | |
175 * place its stdin and stdout file descriptors into an fd pair | |
176 * structure. The "write_fd" connects to the inferior process | |
177 * stdin, and the "read_fd" connects to its stdout. The calling | |
178 * process should write to "write_fd" and read from "read_fd". | |
179 * The return value is the process id of the created process. | |
180 */ | |
181 pid_t | |
182 proc2_open (t_fd_pair* p_pair, tCC** pp_args) | |
183 { | |
184 pid_t ch_id; | |
185 | |
186 /* Create a bi-directional pipe. Writes on 0 arrive on 1 and vice | |
187 versa, so the parent and child processes will read and write to | |
188 opposite FD's. */ | |
189 if (pipe ((int *) p_pair) < 0) | |
190 return NOPROCESS; | |
191 | |
192 p_pair->read_fd = chain_open (p_pair->read_fd, pp_args, &ch_id); | |
193 if (ch_id == NOPROCESS) | |
194 close (p_pair->write_fd); | |
195 | |
196 return ch_id; | |
197 } | |
198 | |
199 | |
200 /* | |
201 * proc2_fopen | |
202 * | |
203 * Identical to "proc2_open()", except that the "fd"'s are | |
204 * "fdopen(3)"-ed into file pointers instead. | |
205 */ | |
206 pid_t | |
207 proc2_fopen (t_pf_pair* pf_pair, tCC** pp_args) | |
208 { | |
209 t_fd_pair fd_pair; | |
210 pid_t ch_id = proc2_open (&fd_pair, pp_args); | |
211 | |
212 if (ch_id == NOPROCESS) | |
213 return ch_id; | |
214 | |
215 pf_pair->pf_read = fdopen (fd_pair.read_fd, "r"); | |
216 pf_pair->pf_write = fdopen (fd_pair.write_fd, "w"); | |
217 return ch_id; | |
218 } |