13 static const unsigned int StringSize = 4096;
17 static void my_close(int fd);
18 static void my_dup2(int old_fd, int new_fd) ;
24 void pipex_open(pipex_t *pipex,
26 const char *working_dir,
28 char string[StringSize];
32 int from_child[2], to_child[2];
38 pipex->quit_pending=FALSE;
39 pipex->command=command;
42 pipex->io->in_fd = STDIN_FILENO;
43 pipex->io->out_fd = STDOUT_FILENO;
45 // attach standard error to standard output
47 my_dup2(STDOUT_FILENO,STDERR_FILENO);
51 // parse the command line and create the argument list
53 if (strlen(command) >= StringSize) my_fatal("pipex_open(): buffer overflow\n");
54 strcpy(string,command);
57 for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) {
63 //printf("command=[%s]\n",command);
64 //Buffer overflow alert
65 ret=wordexp(command, &p, 0);
67 my_fatal("pipex_open(): %s: Unable to parse command.\n",command);
71 my_fatal("pipex_open(): %s: Too many arguments.\n",command);
74 argv[i] = p.we_wordv[i];
77 //for(i=0;i<argc;i++){
78 // printf("[%s]",argv[i]);
85 if (pipe(from_child) == -1) {
86 my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
89 if (pipe(to_child) == -1) {
90 my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
93 // create the child process
97 if (pipex->pid == -1) {
99 my_fatal("pipex_open(): fork(): %s\n",strerror(errno));
101 } else if (pipex->pid == 0) {
105 // close unused pipe descriptors to avoid deadlocks
107 my_close(from_child[0]);
108 my_close(to_child[1]);
110 // attach the pipe to standard input
112 my_dup2(to_child[0],STDIN_FILENO);
113 my_close(to_child[0]);
115 // attach the pipe to standard output
117 my_dup2(from_child[1],STDOUT_FILENO);
118 my_close(from_child[1]);
120 // attach standard error to standard output
121 // commenting this out gives error messages on the console
123 /* my_dup2(STDOUT_FILENO,STDERR_FILENO); */
125 if(chdir(working_dir)){
126 my_fatal("pipex_open(): cannot change directory: %s\n",
130 // launch the new executable file
132 execvp(argv[0],&argv[0]);
134 // execvp() only returns when an error has occured
136 my_fatal("engine_open(): execvp(): %s: %s\n",argv[0],strerror(errno));
140 ASSERT(pipex->pid>0);
144 // close unused pipe descriptors to avoid deadlocks
146 my_close(from_child[1]);
147 my_close(to_child[0]);
149 // fill in the pipex struct
151 pipex->io->in_fd = from_child[0];
152 pipex->io->out_fd = to_child[1];
153 pipex->state|=PIPEX_ACTIVE; // can we test if this really TRUE?
160 void pipex_wait_event(pipex_t *pipex[]){
174 while((p=*(q++))!=NULL){
175 ASSERT(p->io->in_fd>=0);
176 FD_SET(p->io->in_fd,set);
177 if (p->io->in_fd > fd_max){
178 fd_max = p->io->in_fd;
182 // wait for something to read (no timeout)
185 val = select(fd_max+1,set,NULL,NULL,NULL);
186 if (val == -1 && errno != EINTR) my_fatal("pipex_wait_event(): select(): %s\n",strerror(errno));
190 while((p=*(q++))!=NULL){
191 if (FD_ISSET(p->io->in_fd,set)) io_get_update(p->io);
198 bool pipex_active(pipex_t *pipex){
199 return (pipex->state&PIPEX_ACTIVE)!=0;
204 bool pipex_eof(pipex_t *pipex){
205 return (pipex->state&PIPEX_EOF)!=0;
209 // pipex_set_priority()
211 void pipex_set_priority(pipex_t *pipex, int value){
213 setpriority(PRIO_PROCESS,pipex->pid,value);
217 // pipex_set_affinity()
219 void pipex_set_affinity(pipex_t *pipex, int value){
220 my_log("POLYGLOT Setting affinity is not yet implemented on posix\n");
225 void pipex_send_eof(pipex_t *pipex){
231 void pipex_exit(pipex_t *pipex){
233 my_log("POLYGLOT Waiting for child process to exit.\n");
234 waitpid(pipex->pid,&status,0);
235 if(WIFEXITED(status)){
236 if(pipex->quit_pending){
237 my_log("POLYGLOT Child exited with status %d.\n",WEXITSTATUS(status));
239 // Suppress further messages.
240 pipex->quit_pending=TRUE;
241 my_fatal("pipex_exit(): %s: child exited with status %d.\n",pipex->command,WEXITSTATUS(status));
243 }else if(WIFSIGNALED(status)){
244 if(pipex->quit_pending){
245 my_log("POLYGLOT pipex_exit(): %s: child terminated with signal %d.\n",pipex->command,WTERMSIG(status));
247 // Suppress further messages.
248 pipex->quit_pending=TRUE;
249 my_fatal("pipex_exit(): %s: child terminated with signal %d.\n",pipex->command,WTERMSIG(status));
257 bool pipex_readln(pipex_t *pipex, char *string){
258 while (!io_line_ready(pipex->io)) {
259 io_get_update(pipex->io);
261 if (!io_get_line(pipex->io,string,StringSize)) { // EOF
263 pipex->state|=PIPEX_EOF;
273 bool pipex_readln_nb(pipex_t *pipex, char *string){
274 if(io_line_ready(pipex->io)){
275 return pipex_readln(pipex,string);
284 void pipex_write(pipex_t *pipex, const char *string){
285 io_send_queue(pipex->io,"%s",string);
291 void pipex_writeln(pipex_t *pipex, const char *string){
292 io_send(pipex->io,"%s",string);
297 static void my_close(int fd) {
301 if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
306 static void my_dup2(int old_fd, int new_fd) {
311 if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));