/* * Execute a single command. * Return value is a COMMAND_RESULT_* constant, or * a value from 0 to 255 to indicate the exit code * from the utility. */ static int command_execute(struct i_fn_args *a, struct dfui_progress *pr, struct command *cmd) { FILE *log = NULL; char *filename; int cancelled = 0, done = 0, report_done = 0; if (cmd->desc != NULL) dfui_info_set_short_desc(dfui_progress_get_info(pr), cmd->desc); else dfui_info_set_short_desc(dfui_progress_get_info(pr), cmd->cmdline); if (!dfui_be_progress_update(a->c, pr, &cancelled)) abort_backend(); while (!done) { asprintf(&filename, "%sinstall.log", a->tmp); log = fopen(filename, "a"); free(filename); if (cmd->log_mode != COMMAND_LOG_SILENT) i_log(a, ",-<<< Executing `%s'", cmd->cmdline); cmd->result = pipe_loop(a, pr, cmd, &cancelled); if (cmd->log_mode != COMMAND_LOG_SILENT) i_log(a, "`->>> Exit status: %d\n", cmd->result); if (log != NULL) fclose(log); if (cancelled) { if (!dfui_be_progress_end(a->c)) abort_backend(); report_done = 0; while (!report_done) { switch (dfui_be_present_dialog(a->c, "Cancelled", "View Log|Retry|Cancel|Skip", "Execution of the command\n\n%s\n\n" "was cancelled.", cmd->cmdline)) { case 1: /* View Log */ view_command_log(a); break; case 2: /* Retry */ cancelled = 0; report_done = 1; break; case 3: /* Cancel */ cmd->result = COMMAND_RESULT_CANCELLED; report_done = 1; done = 1; break; case 4: /* Skip */ cmd->result = COMMAND_RESULT_SKIPPED; report_done = 1; done = 1; break; } } if (!dfui_be_progress_begin(a->c, pr)) abort_backend(); } else if (cmd->failure_mode == COMMAND_FAILURE_IGNORE) { cmd->result = 0; done = 1; } else if (cmd->result != 0 && cmd->failure_mode != COMMAND_FAILURE_WARN) { if (!dfui_be_progress_end(a->c)) abort_backend(); report_done = 0; while (!report_done) { switch (dfui_be_present_dialog(a->c, "Command Failed!", "View Log|Retry|Cancel|Skip", "Execution of the command\n\n%s\n\n" "FAILED with a return code of %d.", cmd->cmdline, cmd->result)) { case 1: /* View Log */ view_command_log(a); break; case 2: /* Retry */ report_done = 1; break; case 3: /* Cancel */ /* XXX need a better way to retain actual result */ cmd->result = COMMAND_RESULT_CANCELLED; report_done = 1; done = 1; break; case 4: /* Skip */ /* XXX need a better way to retain actual result */ cmd->result = COMMAND_RESULT_SKIPPED; report_done = 1; done = 1; break; } } if (!dfui_be_progress_begin(a->c, pr)) abort_backend(); } else { done = 1; } } return(cmd->result); }
int main(int argc, char *argv[]) { int procnum = 0; int i = 0; pid_t pid; while (1) { int option_index = 0; int c; c = getopt_long(argc, argv, "d:p:hv", LongOptions, &option_index); if (c == EOF) break; switch(c) { case 'v': version (); break; case 'd': duration = atoi (optarg); break; case 'p': nproc = atoi (optarg); break; case '?': fprintf (stdout, "invalid usgae\n"); case 'h': usage (); break; default: fprintf (stdout, "Unknown usage %c.\n", c); exit (ERR_CMD); } } procnum = nproc / 2; while (i < procnum) { if ((pid = fork ()) < 0) { #ifdef DEBUG perror ("fork error"); fprintf (stderr, "%d processes has been created\n"); #endif break; } if (pid == 0) { /* Child process will never return from pipe_loop() */ return pipe_loop (); } i++; } #if 1 /* Should we wait a little more until all the child processes * have been initialized? FIXME*/ sleep (3); #endif #if 0 /* This would be buggy, especially when huge of child processes * are created. It's better to disable this feature */ /* Ok, until now, we can send SIGUSR1 to all the child processes * to inform them to begin executed. */ /* Ignore the SIGUSR1 signal */ signal (SIGUSR1, SIG_IGN); if (kill (0, SIGUSR1) == -1) { #ifdef DEBUG perror ("kill error"); #endif exit (ERR_SIG); } #endif /* wait for termination of all the child process */ wait_child (); /* Calculate the final results and print to the stdout */ calculate(); return 0; } // MAIN