X-Git-Url: http://winboard.nl/cgi-bin?p=polyglot.git;a=blobdiff_plain;f=pipex_posix.c;h=9ce06f3533adba85c80c5bf5cf248cdbf0a8d530;hp=5d2edfaba6bffe7f5bedb1ed23266a358239c893;hb=HEAD;hpb=e15efca6667b2673b4c1a5879a6917eab6800e58 diff --git a/pipex_posix.c b/pipex_posix.c index 5d2edfa..9ce06f3 100644 --- a/pipex_posix.c +++ b/pipex_posix.c @@ -3,13 +3,12 @@ // includes #include +#include #include +#include +#include #include "pipex.h" -// constants - -static const unsigned int StringSize = 4096; - // prototypes static void my_close(int fd); @@ -19,15 +18,22 @@ static void my_dup2(int old_fd, int new_fd) ; // pipex_open() -void pipex_open(pipex_t *pipex, const char *name, const char *command){ +void pipex_open(pipex_t *pipex, + const char *name, + const char *working_dir, + const char *command){ char string[StringSize]; int argc; 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; @@ -40,7 +46,7 @@ void pipex_open(pipex_t *pipex, const char *name, const char *command){ }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; @@ -50,7 +56,27 @@ void pipex_open(pipex_t *pipex, const char *name, const char *command){ } 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;ipid = fork(); @@ -91,15 +117,29 @@ void pipex_open(pipex_t *pipex, const char *name, const char *command){ // 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); - // launch the new executable file + if(chdir(working_dir)){ + printf("%s pipex_open(): %s: %s\n", + PIPEX_MAGIC, + working_dir, + strerror(errno)); + goto wait_for_eof; + } + // launch the new executable file + 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 @@ -154,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); + } } } } @@ -194,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_timepid,&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; } @@ -218,14 +317,30 @@ 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() + +void pipex_write(pipex_t *pipex, const char *string){ + io_send_queue(pipex->io,"%s",string); +} + + // pipex_writeln() void pipex_writeln(pipex_t *pipex, const char *string){