// 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);
// 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;
}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;
}
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) {
my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
}
- // create the child process
+ // create the child process
pipex->pid = fork();
// 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
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);
+ }
}
}
}
// 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;
}
// 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){