14 static const unsigned int StringSize = 4096;
18 static void my_close(int fd);
19 static void my_dup2(int old_fd, int new_fd) ;
25 void pipex_open(pipex_t *pipex,
27 const char *working_dir,
29 char string[StringSize];
33 int from_child[2], to_child[2];
39 pipex->quit_pending=FALSE;
40 pipex->command=command;
43 pipex->io->in_fd = STDIN_FILENO;
44 pipex->io->out_fd = STDOUT_FILENO;
46 // attach standard error to standard output
48 my_dup2(STDOUT_FILENO,STDERR_FILENO);
52 // parse the command line and create the argument list
54 if (strlen(command) >= StringSize) my_fatal("pipex_open(): buffer overflow\n");
55 strcpy(string,command);
58 for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) {
64 //printf("command=[%s]\n",command);
65 //Buffer overflow alert
66 ret=wordexp(command, &p, 0);
68 my_fatal("pipex_open(): %s: Unable to parse command.\n",command);
72 my_fatal("pipex_open(): %s: Too many arguments.\n",command);
75 argv[i] = p.we_wordv[i];
78 //for(i=0;i<argc;i++){
79 // printf("[%s]",argv[i]);
86 if (pipe(from_child) == -1) {
87 my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
90 if (pipe(to_child) == -1) {
91 my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
94 // create the child process
98 if (pipex->pid == -1) {
100 my_fatal("pipex_open(): fork(): %s\n",strerror(errno));
102 } else if (pipex->pid == 0) {
106 // close unused pipe descriptors to avoid deadlocks
108 my_close(from_child[0]);
109 my_close(to_child[1]);
111 // attach the pipe to standard input
113 my_dup2(to_child[0],STDIN_FILENO);
114 my_close(to_child[0]);
116 // attach the pipe to standard output
118 my_dup2(from_child[1],STDOUT_FILENO);
119 my_close(from_child[1]);
121 // attach standard error to standard output
122 // commenting this out gives error messages on the console
124 my_dup2(STDOUT_FILENO,STDERR_FILENO);
126 if(chdir(working_dir)){
127 printf("%s pipex_open(): %s: %s\n",
134 // launch the new executable file
136 execvp(argv[0],&argv[0]);
138 // execvp() only returns when an error has occured
140 printf("%s pipex_open(): execvp(): %s: %s\n",
145 while(fgets(string,StringSize,stdin));
150 ASSERT(pipex->pid>0);
154 // close unused pipe descriptors to avoid deadlocks
156 my_close(from_child[1]);
157 my_close(to_child[0]);
159 // fill in the pipex struct
161 pipex->io->in_fd = from_child[0];
162 pipex->io->out_fd = to_child[1];
163 pipex->state|=PIPEX_ACTIVE; // can we test if this really TRUE?
170 void pipex_wait_event(pipex_t *pipex[]){
184 while((p=*(q++))!=NULL){
185 ASSERT(p->io->in_fd>=0);
186 FD_SET(p->io->in_fd,set);
187 if (p->io->in_fd > fd_max){
188 fd_max = p->io->in_fd;
192 // wait for something to read (no timeout)
195 val = select(fd_max+1,set,NULL,NULL,NULL);
196 if (val == -1 && errno != EINTR) my_fatal("pipex_wait_event(): select(): %s\n",strerror(errno));
200 while((p=*(q++))!=NULL){
201 if (FD_ISSET(p->io->in_fd,set) /*&& !io_line_ready(p->io)*/){
202 io_get_update(p->io);
210 bool pipex_active(pipex_t *pipex){
211 return (pipex->state&PIPEX_ACTIVE)!=0;
216 bool pipex_eof(pipex_t *pipex){
217 return (pipex->state&PIPEX_EOF)!=0;
221 // pipex_set_priority()
223 void pipex_set_priority(pipex_t *pipex, int value){
225 setpriority(PRIO_PROCESS,pipex->pid,value);
229 // pipex_set_affinity()
231 void pipex_set_affinity(pipex_t *pipex, int value){
232 my_log("POLYGLOT Setting affinity is not yet implemented on posix\n");
237 void pipex_send_eof(pipex_t *pipex){
243 /* This routine waits for kill_timeout milliseconds for
244 * the process to exit by itself. If that doesn't
245 * happen it will kill the process.
250 void pipex_exit(pipex_t *pipex, int kill_timeout){
256 my_log("POLYGLOT Waiting for child process to exit.\n");
261 while(elapsed_time<kill_timeout){
262 ret=waitpid(pipex->pid,&status,WNOHANG);
264 my_log("POLYGLOT Child has not exited yet. Sleeping %dms.\n", WAIT_GRANULARITY);
265 my_sleep(WAIT_GRANULARITY);
266 elapsed_time+=WAIT_GRANULARITY;
273 my_log("POLYGLOT Child wouldn't exit by itself. Terminating it.\n");
274 kill(pipex->pid,SIGKILL);
275 waitpid(pipex->pid,&status,0);
277 if(WIFEXITED(status)){
278 if(pipex->quit_pending){
279 my_log("POLYGLOT Child exited with status %d.\n",WEXITSTATUS(status));
281 // Suppress further messages.
282 pipex->quit_pending=TRUE;
283 my_fatal("pipex_exit(): %s: child exited with status %d.\n",pipex->command,WEXITSTATUS(status));
285 }else if(WIFSIGNALED(status)){
286 if(pipex->quit_pending){
287 my_log("POLYGLOT pipex_exit(): %s: child terminated with signal %d.\n",pipex->command,WTERMSIG(status));
289 // Suppress further messages.
290 pipex->quit_pending=TRUE;
291 my_fatal("pipex_exit(): %s: child terminated with signal %d.\n",pipex->command,WTERMSIG(status));
297 // pipex_get_buffer()
299 char * pipex_get_buffer(pipex_t *pipex){
300 return pipex->io->in_buffer;
305 bool pipex_readln(pipex_t *pipex, char *string){
306 while (!io_line_ready(pipex->io)) {
307 io_get_update(pipex->io);
309 if (!io_get_line(pipex->io,string,StringSize)) { // EOF
311 pipex->state|=PIPEX_EOF;
314 if(strncmp(PIPEX_MAGIC,string,strlen(PIPEX_MAGIC))==0){
315 my_fatal("%s\n",string+strlen(PIPEX_MAGIC)+1);
323 bool pipex_readln_nb(pipex_t *pipex, char *string){
325 while(!pipex->io->in_eof && !io_line_ready(pipex->io) && io_peek(pipex->io)){
326 io_get_update(pipex->io);
329 if(io_line_ready(pipex->io)){
330 return pipex_readln(pipex,string);
331 }else if(pipex->io->in_eof){
333 pipex->state|=PIPEX_EOF;
343 void pipex_write(pipex_t *pipex, const char *string){
344 io_send_queue(pipex->io,"%s",string);
350 void pipex_writeln(pipex_t *pipex, const char *string){
351 io_send(pipex->io,"%s",string);
356 static void my_close(int fd) {
360 if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
365 static void my_dup2(int old_fd, int new_fd) {
370 if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));