Add forgotten files 1.4.70b
[polyglot.git] / pipex_posix.c
index 34b32cc..9ce06f3 100644 (file)
@@ -3,13 +3,12 @@
 // includes
 
 #include <string.h>
+#include <stdlib.h>
 #include <errno.h>
+#include <wordexp.h>
+#include <sys/wait.h>
 #include "pipex.h"
 
-// constants
-
-static const unsigned int StringSize = 4096;
-
 // prototypes
 
 static void my_close(int fd);
@@ -28,9 +27,13 @@ void pipex_open(pipex_t *pipex,
     char * ptr;
     char * argv[256];
     int from_child[2], to_child[2];
+    wordexp_t p;
+    int i,ret;
 
     pipex->pid=-1;
     pipex->io->name=name;
+    pipex->quit_pending=FALSE;
+    pipex->command=command;
     
     if(command==NULL){
         pipex->io->in_fd = STDIN_FILENO;
@@ -43,7 +46,7 @@ void pipex_open(pipex_t *pipex,
     }else{
     
         // parse the command line and create the argument list
-    
+#if 0    
         if (strlen(command) >= StringSize) my_fatal("pipex_open(): buffer overflow\n");
         strcpy(string,command);
         argc = 0;
@@ -53,7 +56,27 @@ void pipex_open(pipex_t *pipex,
         }
 
         argv[argc] = NULL;
-        
+#else
+       //printf("command=[%s]\n",command);
+       //Buffer overflow alert
+       ret=wordexp(command, &p, 0);
+       if(ret!=0){
+         my_fatal("pipex_open(): %s: Unable to parse command.\n",command);
+       }
+       argc = p.we_wordc;
+       if(argc>=256-2){
+         my_fatal("pipex_open(): %s: Too many arguments.\n",command);
+       }
+       for(i=0;i<argc;i++){
+         argv[i] = p.we_wordv[i];
+       }
+       //      int i;
+       //for(i=0;i<argc;i++){
+       //  printf("[%s]",argv[i]);
+       //}
+       //printf("\n");
+       argv[argc] = NULL;
+#endif        
       // create the pipes
         
         if (pipe(from_child) == -1) {
@@ -64,7 +87,7 @@ void pipex_open(pipex_t *pipex,
             my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
         }
         
-            // create the child process
+            // create the child process 
         
         pipex->pid = fork();
         
@@ -94,11 +117,14 @@ void pipex_open(pipex_t *pipex,
                 // attach standard error to standard output
                 // commenting this out gives error messages on the console
             
-           /* my_dup2(STDOUT_FILENO,STDERR_FILENO); */
+            my_dup2(STDOUT_FILENO,STDERR_FILENO); 
             
             if(chdir(working_dir)){
-                my_fatal("pipex_open(): cannot change directory: %s\n",
-                         strerror(errno));
+                printf("%s pipex_open(): %s: %s\n",
+                      PIPEX_MAGIC,
+                      working_dir,
+                      strerror(errno));
+               goto wait_for_eof;
             }
             
             // launch the new executable file
@@ -106,8 +132,14 @@ void pipex_open(pipex_t *pipex,
             execvp(argv[0],&argv[0]);
             
                 // execvp() only returns when an error has occured
-            
-            my_fatal("engine_open(): execvp(): %s\n",strerror(errno));
+
+           printf("%s pipex_open(): execvp(): %s: %s\n",
+                  PIPEX_MAGIC,
+                  argv[0],
+                  strerror(errno));
+       wait_for_eof:
+           while(fgets(string,StringSize,stdin));
+           exit(EXIT_SUCCESS);
             
         } else { // pid > 0
             
@@ -162,7 +194,9 @@ void pipex_wait_event(pipex_t *pipex[]){
    q=pipex;
    if (val > 0) {
        while((p=*(q++))!=NULL){
-           if (FD_ISSET(p->io->in_fd,set)) io_get_update(p->io); 
+           if (FD_ISSET(p->io->in_fd,set) /*&& !io_line_ready(p->io)*/){
+              io_get_update(p->io); 
+          }
        }
    }    
 }
@@ -202,23 +236,80 @@ void pipex_send_eof(pipex_t *pipex){
 
 // pipex_exit()
 
-void pipex_exit(pipex_t *pipex){
-        // NOOP for now
+/* This routine waits for kill_timeout milliseconds for 
+ * the process to exit by itself. If that doesn't
+ * happen it will kill the process.
+ */
+
+
+
+void pipex_exit(pipex_t *pipex, int kill_timeout){
+    int status;
+    int elapsed_time;
+    bool exited;
+    int ret;
+
+    my_log("POLYGLOT Waiting for child process to exit.\n");
+
+    elapsed_time=0;
+    exited=FALSE;
+    ret=0;
+    while(elapsed_time<kill_timeout){
+      ret=waitpid(pipex->pid,&status,WNOHANG);
+      if(ret==0){
+       my_log("POLYGLOT Child has not exited yet. Sleeping %dms.\n", WAIT_GRANULARITY);
+       my_sleep(WAIT_GRANULARITY);
+       elapsed_time+=WAIT_GRANULARITY;
+      }else{
+       exited=TRUE;
+       break;
+      }
+    }
+    if(!exited){
+      my_log("POLYGLOT Child wouldn't exit by itself. Terminating it.\n");
+      kill(pipex->pid,SIGKILL);
+      waitpid(pipex->pid,&status,0);    
+    }
+    if(WIFEXITED(status)){
+      if(pipex->quit_pending){
+       my_log("POLYGLOT Child exited with status %d.\n",WEXITSTATUS(status));
+      }else{
+       // Suppress further messages.
+       pipex->quit_pending=TRUE;
+       my_fatal("pipex_exit(): %s: child exited with status %d.\n",pipex->command,WEXITSTATUS(status));
+      }
+    }else if(WIFSIGNALED(status)){
+      if(pipex->quit_pending){
+       my_log("POLYGLOT pipex_exit(): %s: child terminated with signal %d.\n",pipex->command,WTERMSIG(status));
+      }else{
+       // Suppress further messages.
+       pipex->quit_pending=TRUE;
+         my_fatal("pipex_exit(): %s: child terminated with signal %d.\n",pipex->command,WTERMSIG(status));
+      }
+    }
     return;
 }
 
+// pipex_get_buffer()
+
+char * pipex_get_buffer(pipex_t *pipex){
+  return pipex->io->in_buffer;
+}
+
 // pipex_readln()
 
 bool pipex_readln(pipex_t *pipex, char *string){
     while (!io_line_ready(pipex->io)) {
-      io_get_update(pipex->io);
+       io_get_update(pipex->io);
    }
    if (!io_get_line(pipex->io,string,StringSize)) { // EOF
        string[0]='\0';
        pipex->state|=PIPEX_EOF;
        return FALSE;
    }
-   
+   if(strncmp(PIPEX_MAGIC,string,strlen(PIPEX_MAGIC))==0){
+     my_fatal("%s\n",string+strlen(PIPEX_MAGIC)+1);
+   }
 
    return TRUE;
 }
@@ -226,12 +317,21 @@ bool pipex_readln(pipex_t *pipex, char *string){
 // pipex_readln_nb()
 
 bool pipex_readln_nb(pipex_t *pipex, char *string){
-    if(io_line_ready(pipex->io)){
-        return pipex_readln(pipex,string);
-    }else{  
-        string[0]='\0';
-        return FALSE;
-    }
+
+    while(!pipex->io->in_eof && !io_line_ready(pipex->io) && io_peek(pipex->io)){
+      io_get_update(pipex->io);
+  }
+  
+  if(io_line_ready(pipex->io)){
+    return pipex_readln(pipex,string);
+  }else if(pipex->io->in_eof){
+    string[0]='\0';
+    pipex->state|=PIPEX_EOF;
+    return FALSE;
+  }else {  
+    string[0]='\0';
+    return FALSE;
+  }
 }
 
 // pipex_write()