| 19 |  | */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 20 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 21 |  | #include <stdio.h> | 
 
 
 
 
 
 
 
 
 
 
 | 22 | < | #include <glib.h> | 
 
 
 
 
 
 
 
 
 | 22 | > | #include <stdlib.h> | 
 
 
 
 
 
 
 
 
 
 
 | 23 |  | #include <unistd.h> | 
 
 
 
 
 
 
 
 | 24 | + | #include <string.h> | 
 
 
 
 
 
 
 
 | 25 | + | #include <glib.h> | 
 
 
 
 
 
 
 
 | 26 | + | #include <glib/gprintf.h> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 27 |  | #include <poll.h> | 
 
 
 
 
 
 
 
 | 28 | + | #include <sys/types.h> | 
 
 
 
 
 
 
 
 | 29 | + | #include <sys/wait.h> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 30 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 31 |  | #define DEFNUMTHREAD 10 | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 32 |  | #define DEFTIMEOUT 60 | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 37 |  | gchar *jobname; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 38 |  | GTimer *timer; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 39 |  | GPid pid; | 
 
 
 
 
 
 
 
 | 40 | + | gint stat_loc; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 41 |  | gchar *file_stdout; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 42 |  | gchar *file_stderr; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 43 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 57 |  | static gchar *outdir = NULL; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 58 |  | static gchar *infile = NULL; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 59 |  | static gchar *arglist = NULL; | 
 
 
 
 
 
 
 
 
 | 54 | – | static gchar *stdindata = NULL; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 60 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 61 |  | /* Command line options */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 62 |  | static GOptionEntry options[] = | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 88 |  | struct pollfd fds[3]; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 89 |  | gint fdssize=2; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 90 |  |  | 
 
 
 
 
 
 
 
 
 
 
 | 91 | < | /*if((pipe(outpipes)) != 0){ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 92 | < | g_printerr("Failed to create pipe\n"); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 88 | < | return ; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 89 | < | }*/ | 
 
 
 
 
 
 
 
 
 | 91 | > | proc->timer = g_timer_new(); | 
 
 
 
 
 | 92 | > | g_timer_start(proc->timer); | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 93 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 94 |  | /* Setup files in output dir if requested to do so */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 95 |  | if(outdir != NULL){ | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 127 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 128 |  | /* Exec the job */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 129 |  | if (infile == NULL){ | 
 
 
 
 
 
 
 
 
 
 
 | 130 | < | if( ! g_spawn_async_with_pipes(NULL, execargv, NULL, 0, NULL, NULL, &(proc->pid), NULL, &(outpipes[0]), &(outpipes[1]), &err)){ | 
 
 
 
 
 
 
 
 
 | 130 | > | if( ! g_spawn_async_with_pipes(NULL, execargv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &(proc->pid), NULL, &(outpipes[0]), &(outpipes[1]), &err)){ | 
 
 
 
 
 
 
 
 
 
 
 | 131 |  | g_printerr("Failed to execute job %s: %s\n", proc->jobname, err->message); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 132 |  | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 133 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 134 |  | }else{ | 
 
 
 
 
 
 
 
 
 
 
 | 135 | < | if( ! g_spawn_async_with_pipes(NULL, execargv, NULL, 0, NULL, NULL, &(proc->pid), &(inpipes[1]), &(outpipes[0]), &(outpipes[1]), &err)){ | 
 
 
 
 
 
 
 
 
 | 135 | > | if( ! g_spawn_async_with_pipes(NULL, execargv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &(proc->pid), &(inpipes[1]), &(outpipes[0]), &(outpipes[1]), &err)){ | 
 
 
 
 
 
 
 
 
 
 
 | 136 |  | g_printerr("Failed to execute job %s: %s\n", proc->jobname, err->message); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 137 |  | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 138 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 168 |  | poll(fds, fdssize, -1); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 169 |  | /* For stdout and stderr see if there is any data, and read it */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 170 |  | for(x=0; x<2; x++){ | 
 
 
 
 
 
 
 
 
 
 
 | 171 | < | if(fds[x].revents|POLLIN == fds[x].revents){ | 
 
 
 
 
 
 
 
 
 | 171 | > | if((fds[x].revents & POLLIN) == 0){ | 
 
 
 
 
 
 
 
 
 
 
 | 172 |  | /* We have data to read */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 173 |  | g_io_channel_read_line(sout[x], &readbuf, &rdatasize, NULL, NULL); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 174 |  | if(rdatasize > 0){ | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 186 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 187 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 188 |  | /* See if we need to pump more data down stdin */ | 
 
 
 
 
 
 
 
 
 
 
 | 189 | < | if(fds[2].revents|POLLOUT == fds[2].revents){ | 
 
 
 
 
 
 
 
 
 | 189 | > | if((fds[2].revents & POLLOUT) != 0){ | 
 
 
 
 
 
 
 
 
 
 
 | 190 |  | /* We have data we can write */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 191 |  | gchar *nextline; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 192 |  | gint nextlinesize; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 196 |  | /* Get the next line, and write it down the stream */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 197 |  | s = g_io_channel_read_line(sinfile, &nextline, &nextlinesize, NULL, NULL); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 198 |  | if (nextlinesize > 0){ | 
 
 
 
 
 
 
 
 
 | 196 | – | printf("Going to write '%s'\n", nextline); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 199 |  | g_io_channel_write_chars(sin, nextline, nextlinesize, &nextlinewritesize, NULL); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 200 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 201 |  | if (s == G_IO_STATUS_EOF){ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 202 |  | g_io_channel_shutdown(sin, TRUE, NULL); | 
 
 
 
 
 
 
 
 
 
 
 | 203 | < | sin == NULL; | 
 
 
 
 
 
 
 
 
 | 203 | > | sin = NULL; | 
 
 
 
 
 
 
 
 
 
 
 | 204 |  | fdssize=2; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 205 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 206 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 208 |  | /* Even if we did get a hangup - lets make sure there is no more data to read first by looping again */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 209 |  | if (readdata) continue; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 210 |  |  | 
 
 
 
 
 
 
 
 
 
 
 | 211 | < | if((fds[0].revents|POLLHUP == fds[0].revents) && (fds[1].revents|POLLHUP == fds[1].revents)) break; | 
 
 
 
 
 
 
 
 
 | 211 | > | if(((fds[0].revents & POLLHUP) != 0) && ((fds[1].revents & POLLHUP) != 0)) break; | 
 
 
 
 
 
 
 
 
 
 
 | 212 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 213 |  |  | 
 
 
 
 
 
 
 
 
 
 
 | 214 | < | /* For some batty reason, it starts with a ref count of 1. Lets decrement it so we can shut it */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 213 | < | /*g_io_channel_unref(sout[0]); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 214 | < | g_io_channel_unref(sout[1]);*/ | 
 
 
 
 
 
 
 
 
 | 214 | > | while((waitpid(proc->pid, &(proc->stat_loc), 0)) != proc->pid); | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 215 |  |  | 
 
 
 
 
 
 
 
 | 216 | + | g_timer_stop(proc->timer); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 217 |  |  | 
 
 
 
 
 
 
 
 | 218 | + | /* If process exited cleanly */ | 
 
 
 
 
 
 
 
 | 219 | + | if (WIFEXITED(proc->stat_loc)){ | 
 
 
 
 
 
 
 
 | 220 | + | /* Get the exit code */ | 
 
 
 
 
 
 
 
 | 221 | + | if (verbose) g_fprintf(stderr, "Job '%s' exited with code %d. Exec time: %.2f\n", proc->jobname, WEXITSTATUS(proc->stat_loc), g_timer_elapsed(proc->timer, 0)); | 
 
 
 
 
 
 
 
 | 222 | + | }else{ | 
 
 
 
 
 
 
 
 | 223 | + | /* Otherwise - find out what it died with */ | 
 
 
 
 
 
 
 
 | 224 | + | /* TODO - this doesn't work quite right.. Mainly because its looking at the shell process, so the | 
 
 
 
 
 
 
 
 | 225 | + | * child of the /bin/sh which does get a signal, this isn't passed up. Although, it handly tells | 
 
 
 
 
 
 
 
 | 226 | + | * us if the /bin/sh gets a SEGV etc ;) | 
 
 
 
 
 
 
 
 | 227 | + | */ | 
 
 
 
 
 
 
 
 | 228 | + | g_fprintf(stderr, "Job %s exited with signal %d. Exec time: %.2f\n", proc->jobname, (WTERMSIG(proc->stat_loc)), g_timer_elapsed(proc->timer, 0)); | 
 
 
 
 
 
 
 
 | 229 | + | } | 
 
 
 
 
 
 
 
 | 230 | + |  | 
 
 
 
 
 
 
 
 | 231 | + |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 232 |  | g_io_channel_shutdown(sout[0], TRUE, NULL); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 233 |  | g_io_channel_shutdown(sout[1], TRUE, NULL); | 
 
 
 
 
 
 
 
 
 | 219 | – | /*close(outpipes[0]); | 
 
 
 
 
 
 
 
 
 | 220 | – | close(outpipes[1]);*/ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 234 |  |  | 
 
 
 
 
 
 
 
 
 | 222 | – | /* BUG - Causes glib error saying its already closed */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 235 |  | if((infile != NULL) && (sin != NULL)){ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 236 |  | g_io_channel_shutdown(sin, TRUE, NULL); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 237 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 242 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 243 |  | g_spawn_close_pid(proc->pid); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 244 |  |  | 
 
 
 
 
 
 
 
 
 | 233 | – | if (verbose) g_fprintf(stderr, "Ending job '%s'\n", proc->jobname); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 245 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 246 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 247 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 281 |  | * and a line for doign the substitution with. Fills in jobname | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 282 |  | */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 283 |  | gchar *genexeccmd(gchar *cmd, gchar *fmt, gchar *line, gchar **jobname){ | 
 
 
 
 
 
 
 
 
 | 273 | – | gchar **fmttok; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 284 |  | gchar *newexec, *ptr; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 285 |  | int x; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 286 |  | gchar *linesep = " "; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 412 |  | /* Wait for the jobs to finish */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 413 |  | /* TODO - Kill jobs that don't finish in time */ | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 414 |  | while(g_thread_pool_get_num_threads(procpool) > 0){ | 
 
 
 
 
 
 
 
 
 
 
 | 415 | < | sleep(1); | 
 
 
 
 
 
 
 
 
 | 415 | > | g_usleep(1000); | 
 
 
 
 
 
 
 
 
 
 
 | 416 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 417 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 418 |  | return 0; |