diff options
author | subrata_modak <subrata_modak> | 2009-06-01 10:25:49 +0000 |
---|---|---|
committer | subrata_modak <subrata_modak> | 2009-06-01 10:25:49 +0000 |
commit | 5c4b532c88c2029567c69b77a60b0b1a66aa94db (patch) | |
tree | a786294717d08cdfddaaff9e60cb135ebc16cee2 /pan | |
parent | 988a9a5cb925f5f6a290e8662df4129843412d00 (diff) |
Reverting ltp-pan.c to http://ltp.cvs.sourceforge.net/viewvc/*checkout*/ltp/ltp/pan/pan.c?revision=1.32, as the existing one was not running and was hung at runtime. Signed-off-by: Subrata Modak <subrata@linux.vnet.ibm.com>.
Diffstat (limited to 'pan')
-rw-r--r-- | pan/ltp-pan.c | 2146 |
1 files changed, 1031 insertions, 1115 deletions
diff --git a/pan/ltp-pan.c b/pan/ltp-pan.c index 15d314420..607c0075f 100644 --- a/pan/ltp-pan.c +++ b/pan/ltp-pan.c @@ -49,7 +49,7 @@ * - added option to create a command file with all failed tests. * */ -/* $Id: ltp-pan.c,v 1.1 2009/05/19 09:39:11 subrata_modak Exp $ */ +/* $Id: ltp-pan.c,v 1.2 2009/06/01 10:25:49 subrata_modak Exp $ */ #include <errno.h> #include <string.h> @@ -62,7 +62,6 @@ #include <stdlib.h> #include <limits.h> #include <sys/utsname.h> -#include <unistd.h> #include "splitstr.h" #include "zoolib.h" @@ -70,35 +69,35 @@ /* One entry in the command line collection. */ struct coll_entry { - char *name; /* tag name */ - char *cmdline; /* command line */ - char *pcnt_f; /* location of %f in the command line args, flag */ - struct coll_entry *next; + char *name; /* tag name */ + char *cmdline; /* command line */ + char *pcnt_f; /* location of %f in the command line args, flag */ + struct coll_entry *next; }; struct collection { - int cnt; - struct coll_entry **ary; + int cnt; + struct coll_entry **ary; }; struct tag_pgrp { - int pgrp; - int stopping; - time_t mystime; - struct coll_entry *cmd; - char output[PATH_MAX]; + int pgrp; + int stopping; + time_t mystime; + struct coll_entry *cmd; + char output[PATH_MAX]; }; struct orphan_pgrp { - int pgrp; - struct orphan_pgrp *next; + int pgrp; + struct orphan_pgrp *next; }; static pid_t run_child(struct coll_entry *colle, struct tag_pgrp *active, - int quiet_mode); + int quiet_mode); static char *slurp(char *file); static struct collection *get_collection(char *file, int optind, int argc, char **argv); @@ -114,12 +113,14 @@ static char *subst_pcnt_f(struct coll_entry *colle); static void mark_orphan(struct orphan_pgrp *orphans, pid_t cpid); static void orphans_running(struct orphan_pgrp *orphans); static void check_orphans(struct orphan_pgrp *orphans, int sig); + static void copy_buffered_output(struct tag_pgrp *running); static void write_test_start(struct tag_pgrp *running, const char *init_status); static void write_test_end(struct tag_pgrp *running, time_t exit_time, char *term_type, int stat_loc, int term_id, struct tms *tms1, struct tms *tms2); +//wjh static char PAN_STOP_FILE[] = "PAN_STOP_FILE"; static char *panname = NULL; @@ -142,515 +143,454 @@ int Debug = 0; #define Dstart 0x000002 /* started command */ #define Dwait 0x000001 /* wait interrupted */ -/* - * Print help and exit. - */ -static void print_help(void) +int +main(int argc, char **argv) { - fprintf(stdout, "Usage: ltp-pan -n name [ -SyAehpq ] [ -s starts ]" - " [-t time[s|m|h|d] [ -x nactive ] [ -l logfile ]\n\t" - "[ -a active-file ] [ -f command-file ] " - "[ -C fail-command-file ] " - "[ -d debug-level ]\n\t[-o output-file] " - "[-O output-buffer-directory] [cmd]\n"); - exit(0); -} - -/* - * Parse time from string. - */ -static void parse_time(const char *str, int *run_time, int *timed, int quiet_mode) -{ - char modifier = 'm'; - int ret = sscanf(str, "%d%c", run_time, &modifier); - - if (ret == 0) { - fprintf(stderr, "Need proper time input: ####x where" - "x is one of s,m,h,d\n"); - return; - } - - if (ret == 1) { - fprintf(stderr, "Only got a time value of %d " - "modifiers need to come immediately after #" - " assuming %c\n", run_time, modifier); - } - - switch (modifier) { - case 's': *run_time = *run_time; break; - case 'm': *run_time = *run_time * 60; break; - case 'h': *run_time = *run_time * 60 * 60; break; - case 'd': *run_time = *run_time * 60 * 60 * 24; break; - default: - fprintf(stderr, "Invalid time modifier, try: s|h|m|d\n"); exit(-1); - } - - if (!quiet_mode) - printf("PAN will run for %d seconds\n", run_time); - - timed = 1; /* -t implies run as many starts as possible, by default */ -} - -/* - * Prepares logfile. - */ -static void open_logfile(const char *logfilename, FILE **logfile, int fmt_print) -{ - time_t startup; - char *s; - - if (logfilename != NULL) { - if (logfilename[0] != "-") { - *logfile = stdout; - } else { - if ((*logfile = fopen(logfilename, "a+")) == NULL) { - fprintf(stderr, "ltp-pan(%s): Error %s (%d) opening log file '%s'\n", - panname, strerror(errno), errno, logfilename); - exit(1); - } - } - - time(&startup); - s = ctime(&startup); - s[strlen(s) - 1] = '\0'; - - if (!fmt_print) - fprintf(logfile, "startup='%s'\n", s); - else { - fprintf(logfile, "Test Start Time: %s\n", s); - fprintf(logfile, "-----------------------------------------\n"); - fprintf(logfile, "%-30.20s %-10.10s %-10.10s\n", - "Testcase", "Result", "Exit Value"); - fprintf(logfile, "%-30.20s %-10.10s %-10.10s\n", - "--------", "------", "------------"); - } - } -} - - -int main(int argc, char **argv) -{ - char *zooname = NULL; /* name of the zoo file to use */ - char *filename = "/dev/null"; /* filename to read test tags from */ - char *logfilename = NULL; - char *failcmdfilename = NULL; - char *outputfilename = NULL; - struct collection *coll = NULL; - struct tag_pgrp *running; - struct orphan_pgrp *orphans, *orph; + extern char *optarg; + extern int optind; + char *zooname = NULL; /* name of the zoo file to use */ + char *filename = "/dev/null"; /* filename to read test tags from */ + char *logfilename = NULL; + char *failcmdfilename = NULL; + char *outputfilename = NULL; + struct collection *coll = NULL; + struct tag_pgrp *running; + struct orphan_pgrp *orphans, *orph; struct utsname unamebuf; - FILE *logfile = NULL; - FILE *failcmdfile = NULL; - int keep_active = 1; - int num_active = 0; - int failcnt = 0; /* count of total testcases that failed. */ - int err, i; - int starts = -1; - int timed = 0; - int run_time = -1; - int ret = 0; - int stop; - int go_idle; - int has_brakes = 0; /* stop everything if a test case fails */ - int sequential = 0; /* run tests sequentially */ - int fork_in_road = 0; - int exit_stat; - int track_exit_stats = 0; /* exit non-zero if any test exits non-zero */ - int fmt_print = 0; /* enables formatted printing of logfiles. */ - int quiet_mode = 0; /* supresses test start and test end tags. */ - int c; - pid_t cpid; - struct sigaction sa; - - while ((c = getopt(argc, argv, "AO:Sa:C:d:ef:hl:n:o:pqr:s:t:x:y")) != -1) { - switch (c) { - case 'A': /* all-stop flag */ - has_brakes = 1; - track_exit_stats = 1; - break; - case 'O': /* output buffering directory */ - test_out_dir = strdup(optarg); - break; - case 'S': /* run tests sequentially */ - sequential = 1; - break; - case 'a': /* name of the zoo file to use */ - zooname = strdup(optarg); - break; - case 'C': /* name of the file where all failed commands will be */ - failcmdfilename = strdup(optarg); - break; - case 'd': /* debug options */ - sscanf(optarg, "%i", &Debug); - break; - case 'e': /* exit non-zero if any test exists non-zero */ - track_exit_stats = 1; - break; - case 'f': /* filename to read test tags from */ - filename = strdup(optarg); - break; - case 'h': /* help */ - print_help(); - case 'l': /* log file */ - logfilename = strdup(optarg); - break; - case 'n': /* tag given to ltp-pan */ - panname = strdup(optarg); - break; - case 'o': /* send test output here */ - outputfilename = strdup(optarg); - break; - case 'p': /* formatted printing. */ - fmt_print = 1; - break; - case 'q': /* supress test start and test end messages */ - quiet_mode = 1; - break; - case 'r': /* reporting type: none, rts */ - reporttype = strdup(optarg); - break; - case 's': /* number of tags to run */ - starts = atoi(optarg); - break; - case 't': /* run_time to run */ - parse_time(optarg, &run_time, &timed, quiet_mode); - case 'x': /* number of tags to keep running */ - keep_active = atoi(optarg); - break; - case 'y': /* restart on failure or signal */ - fork_in_road = 1; - break; - } + FILE *logfile = NULL; + FILE *failcmdfile = NULL; + int keep_active = 1; + int num_active = 0; + int failcnt = 0; /* count of total testcases that failed. */ + int err, i; + int starts = -1; + int timed = 0; + int run_time = -1; char modifier = 'm'; int ret = 0; + int stop; + int go_idle; + int has_brakes = 0; /* stop everything if a test case fails */ + int sequential = 0; /* run tests sequentially */ + int fork_in_road = 0; + int exit_stat; + int track_exit_stats = 0; /* exit non-zero if any test exits non-zero */ + int fmt_print = 0; /* enables formatted printing of logfiles. */ + int quiet_mode = 0; /* supresses test start and test end tags. */ + int c; + pid_t cpid; + struct sigaction sa; + + while ((c = getopt(argc, argv, "AO:Sa:C:d:ef:hl:n:o:pqr:s:t:x:y")) != -1) { + switch (c) { + case 'A': /* all-stop flag */ + has_brakes = 1; + track_exit_stats = 1; + break; + case 'O': /* output buffering directory */ + test_out_dir = strdup(optarg); + break; + case 'S': /* run tests sequentially */ + sequential = 1; + break; + case 'a': /* name of the zoo file to use */ + zooname = strdup(optarg); + break; + case 'C': /* name of the file where all failed commands will be */ + failcmdfilename = strdup(optarg); + break; + case 'd': /* debug options */ + sscanf(optarg, "%i", &Debug); + break; + case 'e': /* exit non-zero if any test exists non-zero */ + track_exit_stats = 1; + break; + case 'f': /* filename to read test tags from */ + filename = strdup(optarg); + break; + case 'h': /* help */ + fprintf(stdout, "Usage: pan -n name [ -SyAehpq ] [ -s starts ]" + " [-t time[s|m|h|d] [ -x nactive ] [ -l logfile ]\n\t" + "[ -a active-file ] [ -f command-file ] " + "[ -C fail-command-file ] " + "[ -d debug-level ]\n\t[-o output-file] " + "[-O output-buffer-directory] [cmd]\n"); + exit(0); + case 'l': /* log file */ + logfilename = strdup(optarg); + break; + case 'n': /* tag given to pan */ + panname = strdup(optarg); + break; + case 'o': /* send test output here */ + outputfilename = strdup(optarg); + break; + case 'p': /* formatted printing. */ + fmt_print = 1; + break; + case 'q': /* supress test start and test end messages */ + quiet_mode = 1; + break; + case 'r': /* reporting type: none, rts */ + reporttype = strdup(optarg); + break; + case 's': /* number of tags to run */ + starts = atoi(optarg); + break; + case 't': /* run_time to run */ + ret = sscanf(optarg, "%d%c", &run_time, &modifier); + if (ret == 0) { fprintf(stderr, "Need proper time input: ####x where" + "x is one of s,m,h,d\n"); break; } + else if (ret == 1) { fprintf(stderr, "Only got a time value of %d " + "modifiers need to come immediately after #" + " assuming %c\n", run_time, modifier); } + else + { + switch (modifier) + { + case 's': run_time = run_time; break; + case 'm': run_time = run_time * 60; break; + case 'h': run_time = run_time * 60 * 60; break; + case 'd': run_time = run_time * 60 * 60 * 24; break; + default: + fprintf(stderr, "Invalid time modifier, try: s|h|m|d\n"); exit(-1); + } + if (!quiet_mode) + printf("PAN will run for %d seconds\n", run_time); + } + timed = 1; //-t implies run as many starts as possible, by default + break; + case 'x': /* number of tags to keep running */ + keep_active = atoi(optarg); + break; + case 'y': /* restart on failure or signal */ + fork_in_road = 1; + break; } - - if (panname == NULL) { - fprintf(stderr, "ltp-pan: Must supply -n\n"); - exit(1); - } - + } + + if (panname == NULL) { + fprintf(stderr, "pan: Must supply -n\n"); + exit(1); + } + if (zooname == NULL) { + zooname = zoo_getname(); if (zooname == NULL) { - zooname = zoo_getname(); - if (zooname == NULL) { - fprintf(stderr, - "ltp-pan(%s): Must supply -a or set ZOO env variable\n", - panname); - exit(1); - } + fprintf(stderr, + "pan(%s): Must supply -a or set ZOO env variable\n", + panname); + exit(1); } - + } + if (reporttype) { /* make sure we understand the report type */ - if (reporttype) { - if (strcasecmp(reporttype, "rts") && strcasecmp(reporttype, "none")) - reporttype = "rts"; - } else - /* set the default */ - reporttype = "rts"; - - open_logfile(logfilename, &logfile, fmt_print); + if (strcasecmp(reporttype, "rts") + && strcasecmp(reporttype, "none") + /* && strcasecmp(reporttype, "xml")*/) + reporttype = "rts"; + } else { + /* set the default */ + reporttype = "rts"; + } + + if (logfilename != NULL) { + time_t startup; + char *s; - coll = get_collection(filename, optind, argc, argv); - - if(!coll) - exit(1); - - if (coll->cnt == 0) { + if (!strcmp(logfilename, "-")) { + logfile = stdout; + } else { + if ((logfile = fopen(logfilename, "a+")) == NULL) { fprintf(stderr, - "ltp-pan(%s): Must supply a file collection or a command\n", - panname); + "pan(%s): Error %s (%d) opening log file '%s'\n", + panname, strerror(errno), errno, logfilename); exit(1); + } } - if (Debug & Dsetup) - dump_coll(coll); - - /* a place to store the pgrps we're watching */ - running = malloc((keep_active + 1) * sizeof(struct tag_pgrp)); - if (running == NULL) { - fprintf(stderr, "ltp-pan: malloc failed.\n"); - exit(1); + time(&startup); + s = ctime(&startup); + *(s + strlen(s) - 1) = '\0'; + if (!fmt_print) + fprintf(logfile, "startup='%s'\n", s); + else + { + fprintf(logfile, "Test Start Time: %s\n", s); + fprintf(logfile, "-----------------------------------------\n"); + fprintf(logfile, "%-30.20s %-10.10s %-10.10s\n", + "Testcase", "Result", "Exit Value"); + fprintf(logfile, "%-30.20s %-10.10s %-10.10s\n", + "--------", "------", "------------"); } - memset(running, 0, keep_active * sizeof(struct tag_pgrp)); - running[keep_active].pgrp = -1; /* end sentinel */ - - /* a head to the orphaned pgrp list */ - orphans = malloc(sizeof(struct orphan_pgrp)); - if (orphans == NULL) { - fprintf(stderr, "ltp-pan: malloc failed.\n"); - exit(1); + } + + coll = get_collection(filename, optind, argc, argv); + if(!coll) + exit(1); + if (coll->cnt == 0) { + fprintf(stderr, + "pan(%s): Must supply a file collection or a command\n", + panname); + exit(1); + } + + if (Debug & Dsetup) + dump_coll(coll); + + /* a place to store the pgrps we're watching */ + running = (struct tag_pgrp *)malloc((keep_active + 1) * sizeof(struct tag_pgrp)); + memset(running, 0, keep_active * sizeof(struct tag_pgrp)); + running[keep_active].pgrp = -1; /* end sentinel */ + + /* a head to the orphaned pgrp list */ + orphans = (struct orphan_pgrp *) malloc(sizeof(struct orphan_pgrp)); + memset(orphans, 0, sizeof(struct orphan_pgrp)); + + srand48(time(NULL) ^ (getpid() + (getpid() << 15))); + + /* Supply a default for starts. If we are in sequential mode, use + * the number of commands available; otherwise 1. + */ + if (timed == 1 && starts == -1) { /* timed, infinite by default */ + starts = -1; + } else if (starts == -1) { + if (sequential) { + starts = coll->cnt; + } else { + starts = 1; } - memset(orphans, 0, sizeof(struct orphan_pgrp)); - - srand48(time(NULL) ^ (getpid() + (getpid() << 15))); + } else if (starts == 0) { /* if the user specified infinite, set it */ + starts = -1; + } else { /* else, make sure we are starting at least keep_active processes */ + if (starts < keep_active) + starts = keep_active; + } + + /* if we're buffering output, but we're only running on process at a time, + * then essentially "turn off buffering" + */ + if (test_out_dir && (keep_active == 1)) { + free(test_out_dir); + test_out_dir = NULL; + } + + if (test_out_dir) { + struct stat sbuf; - /* Supply a default for starts. If we are in sequential mode, use - * the number of commands available; otherwise 1. - */ - if (timed != 1 || starts != -1) { /* timed, infinite by default */ - if (starts == -1) { - if (sequential) - starts = coll->cnt; - else - starts = 1; - } else { - if (starts == 0) /* if the user specified infinite, set it */ - starts = -1; - else /* else, make sure we are starting at least keep_active processes */ - if (starts < keep_active) - starts = keep_active; - } + if (stat(test_out_dir, &sbuf) < 0) { + fprintf(stderr, + "pan(%s): stat of -O arg '%s' failed. errno: %d %s\n", + panname, test_out_dir, errno, strerror(errno)); + exit(1); } - - /* if we're buffering output, but we're only running on process at a time, - * then essentially "turn off buffering" - */ - if (test_out_dir && (keep_active == 1)) { - free(test_out_dir); - test_out_dir = NULL; + if (!S_ISDIR(sbuf.st_mode)) { + fprintf(stderr, "pan(%s): -O arg '%s' must be a directory.\n", + panname, test_out_dir); + exit(1); } - - if (test_out_dir) { - struct stat sbuf; - - if (stat(test_out_dir, &sbuf) < 0) { - fprintf(stderr, - "ltp-pan(%s): stat of -O arg '%s' failed. errno: %d %s\n", - panname, test_out_dir, errno, strerror(errno)); - exit(1); - } - if (!S_ISDIR(sbuf.st_mode)) { - fprintf(stderr, "ltp-pan(%s): -O arg '%s' must be a directory.\n", - panname, test_out_dir); - exit(1); - } - if (access(test_out_dir, W_OK | R_OK | X_OK) < 0) { - fprintf(stderr, - "ltp-pan(%s): permission denied on -O arg '%s'. errno: %d %s\n", - panname, test_out_dir, errno, strerror(errno)); - exit(1); - } + if (access(test_out_dir, W_OK | R_OK | X_OK) < 0) { + fprintf(stderr, + "pan(%s): permission denied on -O arg '%s'. errno: %d %s\n", + panname, test_out_dir, errno, strerror(errno)); + exit(1); } - - if (outputfilename) { - if (!freopen(outputfilename, "a+", stdout)) { - fprintf(stderr, - "ltp-pan(%s): Error %s (%d) openning output file '%s'\n", - panname, strerror(errno), errno, outputfilename); - exit(1); - } + } + + if (outputfilename) { + if (!freopen(outputfilename, "a+", stdout)) { + fprintf(stderr, + "pan(%s): Error %s (%d) openning output file '%s'\n", + panname, strerror(errno), errno, outputfilename); + exit(1); } - - if (failcmdfilename) { - if (!(failcmdfile = fopen(failcmdfilename, "a+"))) { - fprintf(stderr, - "ltp-pan(%s): Error %s (%d) opening fail cmd file '%s'\n", - panname, strerror(errno), errno, failcmdfilename); - exit(1); - } - } - - if ((zoofile = zoo_open(zooname)) == NULL) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); + } + + if (failcmdfilename) { + if (!(failcmdfile = fopen(failcmdfilename, "a+"))) { + fprintf(stderr, + "pan(%s): Error %s (%d) opening fail cmd file '%s'\n", + panname, strerror(errno), errno, failcmdfilename); + exit(1); + } + } + + if ((zoofile = zoo_open(zooname)) == NULL) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); + exit(1); + } + if (zoo_mark_args(zoofile, getpid(), panname, argc, argv)) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); + exit(1); + } + + /* Allocate N spaces for max-arg commands. + * this is an "active file cleanliness" thing + */ + { + char *av[2], bigarg[82]; + + memset(bigarg, '.', 81); + bigarg[81] = '\0'; + av[0] = bigarg; + av[1] = NULL; + + for (c = 0; c < keep_active; c++) { + if (zoo_mark_cmdline(zoofile, c, panname, "")) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); exit(1); + } } - - if (zoo_mark_args(zoofile, getpid(), panname, argc, argv)) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); + for (c = 0; c < keep_active; c++) { + if (zoo_clear(zoofile, c)) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); exit(1); + } } + } - /* Allocate N spaces for max-arg commands. - * this is an "active file cleanliness" thing - */ - { - char *av[2], bigarg[82]; + rec_signal = send_signal = 0; + if (run_time != -1) { alarm(run_time); } - memset(bigarg, '.', 81); - bigarg[81] = '\0'; - av[0] = bigarg; - av[1] = NULL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = wait_handler; - for (c = 0; c < keep_active; c++) { - if (zoo_mark_cmdline(zoofile, c, panname, "")) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - exit(1); - } - } - - for (c = 0; c < keep_active; c++) { - if (zoo_clear(zoofile, c)) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - exit(1); - } - } - } - - rec_signal = send_signal = 0; - if (run_time != -1) - alarm(run_time); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = wait_handler; - - sigaction(SIGALRM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGUSR1, &sa, NULL); /* ignore fork_in_road */ - sigaction(SIGUSR2, &sa, NULL); /* stop the scheduler */ - - c = 0; /* in this loop, c is the command index */ - stop = 0; - exit_stat = 0; - go_idle = 0; - - while (1) { - - while ((num_active < keep_active) && (starts != 0)) { - if (stop || rec_signal || go_idle) - break; - - if (!sequential) - c = lrand48() % coll->cnt; - - /* find a slot for the child */ - for (i = 0; i < keep_active; ++i) - if (running[i].pgrp == 0) - break; - - if (i == keep_active) { - fprintf(stderr, "ltp-pan(%s): Aborting: i == keep_active = %d\n", - panname, i); - wait_handler(SIGINT); - exit_stat++; - break; - } - - cpid = run_child(coll->ary[c], running + i, quiet_mode); - - if (cpid != -1) - ++num_active; - if ((cpid != -1 || sequential) && starts > 0) - --starts; + sigaction(SIGALRM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); /* ignore fork_in_road */ + sigaction(SIGUSR2, &sa, NULL); /* stop the scheduler */ - if (sequential) - if (++c >= coll->cnt) - c = 0; - - } + c = 0; /* in this loop, c is the command index */ + stop = 0; + exit_stat = 0; + go_idle = 0; + while (1) { - if (starts == 0) - { - if (!quiet_mode) - printf("incrementing stop\n"); - ++stop; - } else - if (starts == -1) { - FILE *f = (FILE*)-1; - if ((f = fopen(PAN_STOP_FILE, "r")) != 0) { - printf("Got %s Stopping!\n", PAN_STOP_FILE); - fclose(f); - unlink(PAN_STOP_FILE); - stop++; - } - } + while ((num_active < keep_active) && (starts != 0)) { + if (stop || rec_signal || go_idle) + break; - if (rec_signal) { - /* propagate everything except sigusr2 */ - - if (rec_signal == SIGUSR2) { - if (fork_in_road) - ++go_idle; - else - ++stop; - rec_signal = send_signal = 0; - } else { - if (rec_signal == SIGUSR1) - fork_in_road = 0; - propagate_signal(running, keep_active, orphans); - - if (fork_in_road) - ++go_idle; - else - ++stop; - } - } + if (!sequential) + c = lrand48() % coll->cnt; - err = check_pids(running, &num_active, keep_active, logfile, - failcmdfile, orphans, fmt_print, &failcnt, quiet_mode); - - if (Debug & Drunning) { - pids_running(running, keep_active); - orphans_running(orphans); - } - - if (err) { - if (fork_in_road) - ++go_idle; - - if (track_exit_stats) - exit_stat++; - - if (has_brakes) { - fprintf(stderr, "ltp-pan(%s): All stop!%s\n", panname, - go_idle ? " (idling)" : ""); - wait_handler(SIGINT); - } - } - - if (stop && (num_active == 0)) - break; - - if (go_idle && (num_active == 0)) { - go_idle = 0; /* It is idle, now resume scheduling. */ - wait_handler(0); /* Reset the signal ratchet. */ - } + /* find a slot for the child */ + for (i = 0; i < keep_active; ++i) { + if (running[i].pgrp == 0) + break; + } + if (i == keep_active) { + fprintf(stderr, "pan(%s): Aborting: i == keep_active = %d\n", + panname, i); + wait_handler(SIGINT); + exit_stat++; + break; + } + + cpid = run_child(coll->ary[c], running + i, quiet_mode); + if (cpid != -1) + ++num_active; + if ((cpid != -1 || sequential) && starts > 0) + --starts; + + if (sequential) + if (++c >= coll->cnt) + c = 0; + + } /* while( (num_active < keep_active) && (starts != 0) ) */ + + if (starts == 0) + { + if (!quiet_mode) + printf("incrementing stop\n"); + ++stop; + } + else if (starts == -1) //wjh + { + FILE *f = (FILE*)-1; + if ((f = fopen(PAN_STOP_FILE, "r")) != 0) + { printf("Got %s Stopping!\n", PAN_STOP_FILE); + fclose(f); unlink(PAN_STOP_FILE); stop++; + } } - /* Wait for orphaned pgrps */ - while (1) { - - for (orph = orphans; orph != NULL; orph = orph->next) { - - if (orph->pgrp == 0) - continue; - - /* Yes, we have orphaned pgrps */ - sleep(5); - - if (!rec_signal) { - - /* force an artificial signal, move us - * through the signal ratchet. - */ - wait_handler(SIGINT); - } - - propagate_signal(running, keep_active, orphans); - - if (Debug & Drunning) - orphans_running(orphans); - - break; - } + if (rec_signal) { + /* propagate everything except sigusr2 */ + if (rec_signal == SIGUSR2) { + if (fork_in_road) + ++go_idle; + else + ++stop; + rec_signal = send_signal = 0; + } else { + if (rec_signal == SIGUSR1) + fork_in_road = 0; + propagate_signal(running, keep_active, orphans); + if (fork_in_road) + ++go_idle; + else + ++stop; + } + } - if (orph == NULL) - break; + err = check_pids(running, &num_active, keep_active, logfile, + failcmdfile, orphans, fmt_print, &failcnt, quiet_mode); + if (Debug & Drunning) { + pids_running(running, keep_active); + orphans_running(orphans); + } + if (err) { + if (fork_in_road) + ++go_idle; + if (track_exit_stats) + exit_stat++; + if (has_brakes) { + fprintf(stderr, "pan(%s): All stop!%s\n", panname, + go_idle ? " (idling)" : ""); + wait_handler(SIGINT); + } } + if (stop && (num_active == 0)) + break; - if (zoo_clear(zoofile, getpid())) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - ++exit_stat; + if (go_idle && (num_active == 0)) { + go_idle = 0; /* It is idle, now resume scheduling. */ + wait_handler(0); /* Reset the signal ratchet. */ } + } - fclose(zoofile); - - if (logfile && fmt_print) { + /* Wait for orphaned pgrps */ + while (1) { + for (orph = orphans; orph != NULL; orph = orph->next) { + if (orph->pgrp == 0) + continue; + /* Yes, we have orphaned pgrps */ + sleep(5); + if (!rec_signal) { + /* force an artificial signal, move us + * through the signal ratchet. + */ + wait_handler(SIGINT); + } + propagate_signal(running, keep_active, orphans); + if (Debug & Drunning) + orphans_running(orphans); + break; + } + if (orph == NULL) + break; + } + + if (zoo_clear(zoofile, getpid())) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); + ++exit_stat; + } + fclose(zoofile); + if (logfile && fmt_print) + { if (uname(&unamebuf) == -1) fprintf(stderr, "ERROR: uname(): %s\n", strerror(errno)); - fprintf(logfile, "\n-----------------------------------------------\n"); fprintf(logfile, "Total Tests: %d\n", coll->cnt); fprintf(logfile, "Total Failures: %d\n", failcnt); @@ -658,737 +598,713 @@ int main(int argc, char **argv) fprintf(logfile, "Machine Architecture: %s\n", unamebuf.machine); fprintf(logfile, "Hostname: %s\n\n", unamebuf.nodename); } + if (logfile && (logfile != stdout)) + fclose(logfile); - if (logfile && (logfile != stdout)) - fclose(logfile); - - exit(exit_stat); + exit(exit_stat); } -static void propagate_signal(struct tag_pgrp *running, int keep_active, - struct orphan_pgrp *orphans) +static void +propagate_signal(struct tag_pgrp *running, int keep_active, + struct orphan_pgrp *orphans) { - int i; + int i; - if (Debug & Dshutdown) - fprintf(stderr, "ltp-pan was signaled with sig %d...\n", rec_signal); + if (Debug & Dshutdown) + fprintf(stderr, "pan was signaled with sig %d...\n", rec_signal); - if (rec_signal == SIGALRM) { - printf("PAN stop Alarm was received\n"); - rec_signal = SIGTERM; - } + if (rec_signal == SIGALRM) + { + printf("PAN stop Alarm was received\n"); + rec_signal = SIGTERM; + } - for (i = 0; i < keep_active; ++i) { - if (running[i].pgrp == 0) - continue; + for (i = 0; i < keep_active; ++i) { + if (running[i].pgrp == 0) + continue; - if (Debug & Dshutdown) - fprintf(stderr, " propagating sig %d to %d\n", - send_signal, -running[i].pgrp); - - if (kill(-running[i].pgrp, send_signal) != 0) { - fprintf(stderr, - "ltp-pan(%s): kill(%d,%d) failed on tag (%s). errno:%d %s\n", - panname, -running[i].pgrp, send_signal, - running[i].cmd->name, errno, strerror(errno)); - } - - running[i].stopping = 1; + if (Debug & Dshutdown) + fprintf(stderr, " propagating sig %d to %d\n", + send_signal, -running[i].pgrp); + if (kill(-running[i].pgrp, send_signal) != 0) { + fprintf(stderr, + "pan(%s): kill(%d,%d) failed on tag (%s). errno:%d %s\n", + panname, -running[i].pgrp, send_signal, + running[i].cmd->name, errno, strerror(errno)); } + running[i].stopping = 1; + } - check_orphans(orphans, send_signal); + check_orphans(orphans, send_signal); - rec_signal = send_signal = 0; + rec_signal = send_signal = 0; } -static int check_pids(struct tag_pgrp *running, int *num_active, int - keep_active, FILE * logfile, FILE * failcmdfile, - struct orphan_pgrp *orphans, int fmt_print, - int *failcnt, int quiet_mode) +static int +check_pids(struct tag_pgrp *running, int *num_active, int keep_active, + FILE * logfile, FILE * failcmdfile, struct orphan_pgrp *orphans, + int fmt_print, int *failcnt, int quiet_mode) { - int w; - pid_t cpid; - int stat_loc; - int ret = 0; - int i; - time_t t; - char *status; - int signaled = 0; - struct tms tms1, tms2; - clock_t tck; - - check_orphans(orphans, 0); - - tck = times(&tms1); - - if (tck == -1) - fprintf(stderr, "ltp-pan(%s): times(&tms1) failed. errno:%d %s\n", - panname, errno, strerror(errno)); - - cpid = wait(&stat_loc); - tck = times(&tms2); - - if (tck == -1) - fprintf(stderr, "ltp-pan(%s): times(&tms2) failed. errno:%d %s\n", - panname, errno, strerror(errno)); - - if (cpid < 0) { - if (errno == EINTR) { - if (Debug) - fprintf(stderr, "ltp-pan(%s): wait() interrupted\n", panname); - } else - if (errno != ECHILD) { - fprintf(stderr, "ltp-pan(%s): wait() failed. errno:%d %s\n", - panname, errno, strerror(errno)); - } - } else - if (cpid > 0) { - - if (WIFSIGNALED(stat_loc)) { - w = WTERMSIG(stat_loc); - status = "signaled"; - if (Debug & Dexit) - fprintf(stderr, "child %d terminated with signal %d\n", cpid, w); - --*num_active; - signaled = 1; - } else - if (WIFEXITED(stat_loc)) { - w = WEXITSTATUS(stat_loc); - status = "exited"; - if (Debug & Dexit) - fprintf(stderr, "child %d exited with status %d\n", cpid, w); - --*num_active; - if (w != 0) - ret++; - } else - if (WIFSTOPPED(stat_loc)) { /* should never happen */ - w = WSTOPSIG(stat_loc); - status = "stopped"; - ret++; - } else { /* should never happen */ - w = 0; - status = "unknown"; - ret++; - } - - for (i = 0; i < keep_active; ++i) { - if (running[i].pgrp == cpid) { - if ((w == 130) && running[i].stopping && (strcmp(status, "exited") == 0)) { - /* The child received sigint, but - * did not trap for it? Compensate - * for it here. - */ - w = 0; - ret--; /* undo */ - if (Debug & Drunning) - fprintf(stderr, - "ltp-pan(%s): tag=%s exited 130, known to be signaled; will give it an exit 0.\n", - panname, running[i].cmd->name); - } - time(&t); - - if (logfile != NULL) { - if (!fmt_print) - fprintf(logfile, "tag=%s stime=%d dur=%d exit=%s stat=%d core=%s cu=%d cs=%d\n", - running[i].cmd->name, (int) (running[i].mystime), - (int) (t - running[i].mystime), status, w, - (stat_loc & 0200) ? "yes" : "no", - (int) (tms2.tms_cutime - tms1.tms_cutime), - (int) (tms2.tms_cstime - tms1.tms_cstime)); - else { - if (w != 0) - ++*failcnt; - - fprintf(logfile, "%-30.30s %-10.10s %-5d\n", - running[i].cmd->name, ((w != 0) ? "FAIL" : "PASS"), w); - } - - fflush(logfile); - } - - if ((failcmdfile != NULL) && (w !=0)) - fprintf(failcmdfile, "%s %s\n", running[i].cmd->name, running[i].cmd->cmdline); - - if (running[i].stopping) - status = "driver_interrupt"; - - if (test_out_dir) { - if (!quiet_mode) - write_test_start(running+i, "ok"); - copy_buffered_output(running + i); - unlink(running[i].output); - } - - if (!quiet_mode) - write_test_end(running+i, t, status, stat_loc, w, &tms1, &tms2); - - /* If signaled and we weren't expecting - * this to be stopped then the proc - * had a problem. - */ - if (signaled && !running[i].stopping) - ret++; - - running[i].pgrp = 0; - - if (zoo_clear(zoofile, cpid)) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - exit(1); - } - - /* Check for orphaned pgrps */ - if ((kill(-cpid, 0) == 0) || (errno == EPERM)) { - if (zoo_mark_cmdline(zoofile, cpid, "panorphan", running[i].cmd->cmdline)) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - exit(1); - } - - mark_orphan(orphans, cpid); - /* status of kill doesn't matter */ - kill(-cpid, SIGTERM); - } - - break; - } - } + int w; + pid_t cpid; + int stat_loc; + int ret = 0; + int i; + time_t t; + char *status; + int signaled = 0; + struct tms tms1, tms2; + clock_t tck; + + check_orphans(orphans, 0); + + tck = times(&tms1); + if (tck == -1) { + fprintf(stderr, "pan(%s): times(&tms1) failed. errno:%d %s\n", + panname, errno, strerror(errno)); + } + cpid = wait(&stat_loc); + tck = times(&tms2); + if (tck == -1) { + fprintf(stderr, "pan(%s): times(&tms2) failed. errno:%d %s\n", + panname, errno, strerror(errno)); + } + + if (cpid < 0) { + if (errno == EINTR) { + if (Debug) + fprintf(stderr, "pan(%s): wait() interrupted\n", panname); + } else if (errno != ECHILD) { + fprintf(stderr, "pan(%s): wait() failed. errno:%d %s\n", + panname, errno, strerror(errno)); + } + } else if (cpid > 0) { + + if (WIFSIGNALED(stat_loc)) { + w = WTERMSIG(stat_loc); + status = "signaled"; + if (Debug & Dexit) + fprintf(stderr, "child %d terminated with signal %d\n", cpid, + w); + --*num_active; + signaled = 1; + } else if (WIFEXITED(stat_loc)) { + w = WEXITSTATUS(stat_loc); + status = "exited"; + if (Debug & Dexit) + fprintf(stderr, "child %d exited with status %d\n", cpid, w); + --*num_active; + if (w != 0) + ret++; + } else if (WIFSTOPPED(stat_loc)) { /* should never happen */ + w = WSTOPSIG(stat_loc); + status = "stopped"; + ret++; + } else { /* should never happen */ + w = 0; + status = "unknown"; + ret++; } - - return ret; -} - -static pid_t run_child(struct coll_entry *colle, struct tag_pgrp *active, int quiet_mode) -{ - int cpid; - int c_stdout = -1; /* child's stdout, stderr */ - int capturing = 0; /* output is going to a file instead of stdout */ - char *c_cmdline; - static long cmdno = 0; - int errpipe[2]; /* way to communicate to parent that the tag */ - char errbuf[1024]; /* didn't actually start */ - int errlen; - - /* Try to open the file that will be stdout for the test */ - if (test_out_dir) { - capturing = 1; - - do { - sprintf(active->output, "%s/%s.%ld", - test_out_dir, colle->name, cmdno++); - c_stdout = open(active->output, O_CREAT | O_RDWR | O_EXCL | O_SYNC, 0666); - } while (c_stdout < 0 && errno == EEXIST); - - if (c_stdout < 0) { + for (i = 0; i < keep_active; ++i) { + if (running[i].pgrp == cpid) { + if ((w == 130) && running[i].stopping && + (strcmp(status, "exited") == 0)) { + /* The child received sigint, but + * did not trap for it? Compensate + * for it here. + */ + w = 0; + ret--; /* undo */ + if (Debug & Drunning) fprintf(stderr, - "ltp-pan(%s): open of stdout file failed (tag %s). errno: %d %s\n file: %s\n", - panname, colle->name, errno, strerror(errno), - active->output); - return -1; + "pan(%s): tag=%s exited 130, known to be signaled; will give it an exit 0.\n", + panname, running[i].cmd->name); } - } + time(&t); + if (logfile != NULL) { + if (!fmt_print) + fprintf(logfile, + "tag=%s stime=%d dur=%d exit=%s stat=%d core=%s cu=%d cs=%d\n", + running[i].cmd->name, (int) (running[i].mystime), + (int) (t - running[i].mystime), status, w, + (stat_loc & 0200) ? "yes" : "no", + (int) (tms2.tms_cutime - tms1.tms_cutime), + (int) (tms2.tms_cstime - tms1.tms_cstime)); + else + { + if (w != 0) + ++*failcnt; + fprintf(logfile, "%-30.30s %-10.10s %-5d\n", + running[i].cmd->name, ((w != 0) ? "FAIL" : "PASS"), + w); + } - /* get the tag's command line arguments ready. subst_pcnt_f() uses a - * static counter, that's why we do it here instead of after we fork. - */ - if (colle->pcnt_f) - c_cmdline = subst_pcnt_f(colle); - else - c_cmdline = colle->cmdline; - - if (pipe(errpipe) < 0) { - fprintf(stderr, "ltp-pan(%s): pipe() failed. errno:%d %s\n", - panname, errno, strerror(errno)); - if (capturing) { - close(c_stdout); - unlink(active->output); + fflush(logfile); } - return -1; - } + if ((failcmdfile != NULL) && (w !=0)) { + fprintf(failcmdfile, "%s %s\n", running[i].cmd->name, running[i].cmd->cmdline); + } + + if (running[i].stopping) + status = "driver_interrupt"; - if ((cpid = fork()) < 0) { - fprintf(stderr, "ltp-pan(%s): fork failed (tag %s). errno:%d %s\n", - panname, colle->name, errno, strerror(errno)); - - if (capturing) { - unlink(active->output); - close(c_stdout); + if (test_out_dir) { + if (!quiet_mode) + write_test_start(running+i, "ok"); + copy_buffered_output(running + i); + unlink(running[i].output); } + if (!quiet_mode) + write_test_end(running+i, t, status, + stat_loc, w, &tms1, &tms2); - close(errpipe[0]); - close(errpipe[1]); - - return -1; - } else - if (cpid == 0) { - /* child */ - fclose(zoofile); - close(errpipe[0]); - fcntl(errpipe[1], F_SETFD, 1); /* close the pipe if we succeed */ - setpgrp(); - umask(0); - - /* if we're putting output into a buffer file, we need to do the - * redirection now. If we fail - */ - if (capturing) { - if (dup2(c_stdout, fileno(stdout)) == -1) { - errlen = sprintf(errbuf, "ltp-pan(%s): couldn't redirect stdout for tag %s. errno:%d %s", - panname, colle->name, errno, strerror(errno)); - write(errpipe[1], &errlen, sizeof(errlen)); - write(errpipe[1], errbuf, errlen); - exit(2); - } - - if (dup2(c_stdout, fileno(stderr)) == -1) { - errlen = sprintf(errbuf, "ltp-pan(%s): couldn't redirect stderr for tag %s. errno:%d %s", - panname, colle->name, errno, strerror(errno)); - write(errpipe[1], &errlen, sizeof(errlen)); - write(errpipe[1], errbuf, errlen); - exit(2); - } - } else { /* stderr still needs to be redirected */ - if (dup2(fileno(stdout), fileno(stderr)) == -1) { - errlen = sprintf(errbuf, "ltp-pan(%s): couldn't redirect stderr for tag %s. errno:%d %s", - panname, colle->name, errno, strerror(errno)); - write(errpipe[1], &errlen, sizeof(errlen)); - write(errpipe[1], errbuf, errlen); - exit(2); - } - } - - /* If there are any shell-type characters in the cmdline - * such as '>', '<', '$', '|', etc, then we exec a shell and - * run the cmd under a shell. - * - * Otherwise, break the cmdline at white space and exec the - * cmd directly. + /* If signaled and we weren't expecting + * this to be stopped then the proc + * had a problem. */ - if (strpbrk(c_cmdline, "\"';|<>$\\")) { - execlp("sh", "sh", "-c", c_cmdline, (char*)0); - errlen = sprintf(errbuf, - "ltp-pan(%s): execlp of '%s' (tag %s) failed. errno:%d %s", - panname, c_cmdline, colle->name, errno, strerror(errno)); - } else { - char **arg_v; - - arg_v = (char **)splitstr(c_cmdline, NULL, NULL); - - execvp(arg_v[0], arg_v); - errlen = sprintf(errbuf, - "ltp-pan(%s): execvp of '%s' (tag %s) failed. errno:%d %s", - panname, arg_v[0], colle->name, errno, strerror(errno)); + if (signaled && !running[i].stopping) + ret++; + + running[i].pgrp = 0; + if (zoo_clear(zoofile, cpid)) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); + exit(1); } - write(errpipe[1], &errlen, sizeof(errlen)); - write(errpipe[1], errbuf, errlen); - exit(errno); - } + /* Check for orphaned pgrps */ + if ((kill(-cpid, 0) == 0) || (errno == EPERM)) { + if (zoo_mark_cmdline(zoofile, cpid, "panorphan", + running[i].cmd->cmdline)) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); + exit(1); + } + mark_orphan(orphans, cpid); + /* status of kill doesn't matter */ + kill(-cpid, SIGTERM); + } - /* parent */ + break; + } + } + } + return ret; +} - /* subst_pcnt_f() allocates the command line dynamically - * free the malloc to prevent a memory leak - */ - if (colle->pcnt_f) - free(c_cmdline); +static pid_t +run_child(struct coll_entry *colle, struct tag_pgrp *active, int quiet_mode) +{ + int cpid; + int c_stdout = -1; /* child's stdout, stderr */ + int capturing = 0; /* output is going to a file instead of stdout */ + char *c_cmdline; + static long cmdno = 0; + int errpipe[2]; /* way to communicate to parent that the tag */ + char errbuf[1024]; /* didn't actually start */ + int errlen; + + /* Try to open the file that will be stdout for the test */ + if (test_out_dir) { + capturing = 1; + do { + sprintf(active->output, "%s/%s.%ld", + test_out_dir, colle->name, cmdno++); + c_stdout = open(active->output, O_CREAT | O_RDWR | O_EXCL | O_SYNC, 0666); + } while (c_stdout < 0 && errno == EEXIST); + if (c_stdout < 0) { + fprintf(stderr, + "pan(%s): open of stdout file failed (tag %s). errno: %d %s\n file: %s\n", + panname, colle->name, errno, strerror(errno), + active->output); + return -1; + } + } + + /* get the tag's command line arguments ready. subst_pcnt_f() uses a + * static counter, that's why we do it here instead of after we fork. + */ + if (colle->pcnt_f) { + c_cmdline = subst_pcnt_f(colle); + } else { + c_cmdline = colle->cmdline; + } + + if (pipe(errpipe) < 0) { + fprintf(stderr, "pan(%s): pipe() failed. errno:%d %s\n", + panname, errno, strerror(errno)); + if (capturing) { + close(c_stdout); + unlink(active->output); + } + return -1; + } + + if ((cpid = fork()) < 0) { + fprintf(stderr, "pan(%s): fork failed (tag %s). errno:%d %s\n", + panname, colle->name, errno, strerror(errno)); + if (capturing) { + unlink(active->output); + close(c_stdout); + } + close(errpipe[0]); close(errpipe[1]); - time(&active->mystime); - active->cmd = colle; + return -1; + } else if (cpid == 0) { + /* child */ - /* if the child couldn't go through with the exec, - * clean up the mess, note it, and move on - */ - if(read(errpipe[0], &errlen, sizeof(errlen))) { - int status; - time_t end_time; - int termid; - char *termtype; - struct tms notime = {0, 0, 0, 0}; - - read(errpipe[0], errbuf, errlen); - close(errpipe[0]); - errbuf[errlen] = '\0'; - /* fprintf(stderr, "%s", errbuf); */ - waitpid(cpid, &status, 0); - if (WIFSIGNALED(status)) { - termid = WTERMSIG(status); - termtype = "signaled"; - } else - if (WIFEXITED(status)) { - termid = WEXITSTATUS(status); - termtype = "exited"; - } else - if (WIFSTOPPED(status)) { - termid = WSTOPSIG(status); - termtype = "stopped"; - } else { - termid = 0; - termtype = "unknown"; - } - - time(&end_time); - if (!quiet_mode) - { - write_test_start(active, errbuf); - write_test_end(active, end_time, termtype, status, - termid, ¬ime, ¬ime); - } + fclose(zoofile); + close(errpipe[0]); + fcntl(errpipe[1], F_SETFD, 1); /* close the pipe if we succeed */ + setpgrp(); - if (capturing) { - close(c_stdout); - unlink(active->output); - } - - return -1; - } + umask(0); + /* if we're putting output into a buffer file, we need to do the + * redirection now. If we fail + */ + if (capturing) { + if (dup2(c_stdout, fileno(stdout)) == -1) { + errlen = sprintf(errbuf, "pan(%s): couldn't redirect stdout for tag %s. errno:%d %s", + panname, colle->name, errno, strerror(errno)); + write(errpipe[1], &errlen, sizeof(errlen)); + write(errpipe[1], errbuf, errlen); + exit(2); + } + if (dup2(c_stdout, fileno(stderr)) == -1) { + errlen = sprintf(errbuf, "pan(%s): couldn't redirect stderr for tag %s. errno:%d %s", + panname, colle->name, errno, strerror(errno)); + write(errpipe[1], &errlen, sizeof(errlen)); + write(errpipe[1], errbuf, errlen); + exit(2); + } + } else { /* stderr still needs to be redirected */ + if (dup2(fileno(stdout), fileno(stderr)) == -1) { + errlen = sprintf(errbuf, "pan(%s): couldn't redirect stderr for tag %s. errno:%d %s", + panname, colle->name, errno, strerror(errno)); + write(errpipe[1], &errlen, sizeof(errlen)); + write(errpipe[1], errbuf, errlen); + exit(2); + } + } + /* If there are any shell-type characters in the cmdline + * such as '>', '<', '$', '|', etc, then we exec a shell and + * run the cmd under a shell. + * + * Otherwise, break the cmdline at white space and exec the + * cmd directly. + */ + if (strpbrk(c_cmdline, "\"';|<>$\\")) { + execlp("sh", "sh", "-c", c_cmdline, (char*)0); + errlen = sprintf(errbuf, + "pan(%s): execlp of '%s' (tag %s) failed. errno:%d %s", + panname, c_cmdline, colle->name, errno, strerror(errno)); + } else { + char **arg_v; + + arg_v = (char **)splitstr(c_cmdline, NULL, NULL); + + execvp(arg_v[0], arg_v); + errlen = sprintf(errbuf, + "pan(%s): execvp of '%s' (tag %s) failed. errno:%d %s", + panname, arg_v[0], colle->name, errno, strerror(errno)); + } + write(errpipe[1], &errlen, sizeof(errlen)); + write(errpipe[1], errbuf, errlen); + exit(errno); + } + + /* parent */ + + /* subst_pcnt_f() allocates the command line dynamically + * free the malloc to prevent a memory leak + */ + if (colle->pcnt_f) free(c_cmdline); + + close(errpipe[1]); + time(&active->mystime); + active->cmd = colle; + + /* if the child couldn't go through with the exec, + * clean up the mess, note it, and move on + */ + if(read(errpipe[0], &errlen, sizeof(errlen))) { + int status; + time_t end_time; + int termid; + char *termtype; + struct tms notime = {0, 0, 0, 0}; + + read(errpipe[0], errbuf, errlen); close(errpipe[0]); + errbuf[errlen] = '\0'; + /* fprintf(stderr, "%s", errbuf); */ + waitpid(cpid, &status, 0); + if (WIFSIGNALED(status)) { + termid = WTERMSIG(status); + termtype = "signaled"; + } else if (WIFEXITED(status)) { + termid = WEXITSTATUS(status); + termtype = "exited"; + } else if (WIFSTOPPED(status)) { + termid = WSTOPSIG(status); + termtype = "stopped"; + } else { + termid = 0; + termtype = "unknown"; + } + time(&end_time); + if (!quiet_mode) + { + write_test_start(active, errbuf); + write_test_end(active, end_time, termtype, status, + termid, ¬ime, ¬ime); + } + if (capturing) { + close(c_stdout); + unlink(active->output); + } + return -1; + } + + close(errpipe[0]); + if (capturing) close(c_stdout); - if (capturing) - close(c_stdout); - - if (!test_out_dir && !quiet_mode) - write_test_start(active, "ok"); + if (!test_out_dir) + if (!quiet_mode) + write_test_start(active, "ok"); - active->pgrp = cpid; - active->stopping = 0; + active->pgrp = cpid; + active->stopping = 0; - if (zoo_mark_cmdline(zoofile, cpid, colle->name, colle->cmdline)) { - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - exit(1); - } + if (zoo_mark_cmdline(zoofile, cpid, colle->name, colle->cmdline)) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); + exit(1); + } - if (Debug & Dstartup) - fprintf(stderr, "started %s cpid=%d at %s", - colle->name, cpid, ctime(&active->mystime)); + if (Debug & Dstartup) + fprintf(stderr, "started %s cpid=%d at %s", + colle->name, cpid, ctime(&active->mystime)); - if (Debug & Dstart) { - - fprintf(stderr, "Executing test = %s as %s", colle->name, colle->cmdline); - - if (capturing) - fprintf(stderr, "with output file = %s\n", active->output); - else - fprintf(stderr, "\n"); - } + if (Debug & Dstart) { + fprintf(stderr, "Executing test = %s as %s", colle->name, colle->cmdline); + if (capturing) + fprintf(stderr, "with output file = %s\n", active->output); + else + fprintf(stderr, "\n"); + } - return cpid; + return cpid; } -static char *subst_pcnt_f(struct coll_entry *colle) +static char * +subst_pcnt_f(struct coll_entry *colle) { - static int counter = 1; - char pid_and_counter[20]; - char new_cmdline[1024]; + static int counter = 1; + char pid_and_counter[20]; + char new_cmdline[1024]; - /* if we get called falsely, do the right thing anyway */ - if (!colle->pcnt_f) + /* if we get called falsely, do the right thing anyway */ + if (!colle->pcnt_f) return colle->cmdline; - snprintf(pid_and_counter, 20, "%d_%d", getpid(), counter++); - snprintf(new_cmdline, 1024, colle->cmdline, pid_and_counter); - return strdup(new_cmdline); + snprintf(pid_and_counter, 20, "%d_%d", getpid(), counter++); + snprintf(new_cmdline, 1024, colle->cmdline, pid_and_counter); + return strdup(new_cmdline); } -/* - * This code is broken as it's doesn't check NULL from malloc, strdup and so; - * but I'm just too lazy to rewrite this as pan is broken by design. - */ -static struct collection *get_collection(char *file, int optind, int argc, char **argv) +static struct collection * +get_collection(char *file, int optind, int argc, char **argv) { - char *buf, *a, *b; - struct coll_entry *head, *p, *n; - struct collection *coll; - int i; - - buf = slurp(file); - - if(!buf) - return NULL; - - coll = malloc(sizeof(struct collection)); - coll->cnt = 0; - - head = p = n = NULL; - a = b = buf; - - while (a) { - /* set b to the start of the next line and add a NULL character - * to separate the two lines */ - if ((b = strchr(a, '\n')) != NULL) - *b++ = '\0'; - - /* If this is line isn't a comment */ - if ((*a != '#') && (*a != '\0') && (*a != ' ')) { - n = malloc(sizeof(struct coll_entry)); - - if ((n->pcnt_f = strstr(a, "%f"))) - n->pcnt_f[1] = 's'; - - n->name = strdup(strsep(&a, " \t")); - n->cmdline = strdup(a); - n->next = NULL; - - if (p) - p->next = n; - - if (head == NULL) - head = n; - - p = n; - coll->cnt++; - } - - a = b; + char *buf, *a, *b; + struct coll_entry *head, *p, *n; + struct collection *coll; + int i; + + buf = slurp(file); + if(!buf) + return NULL; + + coll = (struct collection *) malloc(sizeof(struct collection)); + coll->cnt = 0; + + head = p = n = NULL; + a = b = buf; + while (a) { + /* set b to the start of the next line and add a NULL character + * to separate the two lines */ + if ((b = strchr(a, '\n')) != NULL) + *b++ = '\0'; + + /* If this is line isn't a comment */ + if ((*a != '#') && (*a != '\0') && (*a != ' ')) { + n = (struct coll_entry *) malloc(sizeof(struct coll_entry)); + if ((n->pcnt_f = strstr(a, "%f"))) { + n->pcnt_f[1] = 's'; + } + n->name = strdup(strsep(&a, " \t")); + n->cmdline = strdup(a); + n->next = NULL; + + if (p) { + p->next = n; + } + if (head == NULL) { + head = n; + } + p = n; + coll->cnt++; } - - free(buf); - - /* is there something on the commandline to be counted? */ - if (optind < argc) { - char workstr[1024] = ""; - int workstr_left = 1023; + a = b; + } + free(buf); + + /* is there something on the commandline to be counted? */ + if (optind < argc) { + char workstr[1024] = ""; + int workstr_left = 1023; - /* fill arg list */ - for (i = 0; optind < argc; ++optind, ++i) { - strncat(workstr, argv[optind], workstr_left); - workstr_left = workstr_left - strlen(argv[optind]); - strncat(workstr, " ", workstr_left); - workstr_left--; - } - - n = (struct coll_entry *) malloc(sizeof(struct coll_entry)); - - if ((n->pcnt_f = strstr(workstr, "%f"))) - n->pcnt_f[1] = 's'; - - n->cmdline = strdup(workstr); - n->name = "cmdln"; - n->next = NULL; - - if (p) - p->next = n; - - if (head == NULL) - head = n; - - coll->cnt++; + /* fill arg list */ + for (i = 0; optind < argc; ++optind, ++i) { + strncat(workstr, argv[optind], workstr_left); + workstr_left = workstr_left - strlen(argv[optind]); + strncat(workstr, " ", workstr_left); + workstr_left--; } - /* get an array */ - coll->ary = malloc(coll->cnt * sizeof(struct coll_entry *)); - - /* fill the array */ - i = 0; - n = head; - - while (n != NULL) { - coll->ary[i] = n; - n = n->next; - ++i; + n = (struct coll_entry *) malloc(sizeof(struct coll_entry)); + if ((n->pcnt_f = strstr(workstr, "%f"))) { + n->pcnt_f[1] = 's'; } - - if (i != coll->cnt) - fprintf(stderr, "ltp-pan(%s): i doesn't match cnt\n", panname); - - return coll; -} - -static char *slurp(char *file) -{ - char *buf; - int fd; - struct stat sbuf; - - if ((fd = open(file, O_RDONLY)) < 0) { - fprintf(stderr, "ltp-pan(%s): open(%s,O_RDONLY) failed. errno:%d %s\n", - panname, file, errno, strerror(errno)); - return NULL; + n->cmdline = strdup(workstr); + n->name = "cmdln"; + n->next = NULL; + if (p) { + p->next = n; } - - if (fstat(fd, &sbuf) < 0) { - fprintf(stderr, "ltp-pan(%s): fstat(%s) failed. errno:%d %s\n", - panname, file, errno, strerror(errno)); - return NULL; + if (head == NULL) { + head = n; } + coll->cnt++; + } + + /* get an array */ + coll->ary = (struct coll_entry **) malloc(coll->cnt * + sizeof(struct coll_entry *)); + + /* fill the array */ + i = 0; + n = head; + while (n != NULL) { + coll->ary[i] = n; + n = n->next; + ++i; + } + if (i != coll->cnt) + fprintf(stderr, "pan(%s): i doesn't match cnt\n", panname); + + return coll; +} - buf = malloc(sbuf.st_size + 1); - - if (read(fd, buf, sbuf.st_size) != sbuf.st_size) { - fprintf(stderr, "ltp-pan(%s): slurp failed. errno:%d %s\n", - panname, errno, strerror(errno)); - return NULL; - } - - buf[sbuf.st_size] = '\0'; - close(fd); - return buf; +static char * +slurp(char *file) +{ + char *buf; + int fd; + struct stat sbuf; + + if ((fd = open(file, O_RDONLY)) < 0) { + fprintf(stderr, "pan(%s): open(%s,O_RDONLY) failed. errno:%d %s\n", + panname, file, errno, strerror(errno)); + return NULL; + } + + if (fstat(fd, &sbuf) < 0) { + fprintf(stderr, "pan(%s): fstat(%s) failed. errno:%d %s\n", + panname, file, errno, strerror(errno)); + return NULL; + } + + buf = (char *) malloc(sbuf.st_size + 1); + if (read(fd, buf, sbuf.st_size) != sbuf.st_size) { + fprintf(stderr, "pan(%s): slurp failed. errno:%d %s\n", + panname, errno, strerror(errno)); + return NULL; + } + buf[sbuf.st_size] = '\0'; + + close(fd); + return buf; } -static void check_orphans(struct orphan_pgrp *orphans, int sig) +static void +check_orphans(struct orphan_pgrp *orphans, int sig) { - struct orphan_pgrp *orph; + struct orphan_pgrp *orph; - for (orph = orphans; orph != NULL; orph = orph->next) { - if (orph->pgrp == 0) - continue; - - if (Debug & Dshutdown) - fprintf(stderr, " propagating sig %d to orphaned pgrp %d\n", - sig, -(orph->pgrp)); - if (kill(-(orph->pgrp), sig) != 0) { - if (errno == ESRCH) { - /* This pgrp is now empty */ - if (zoo_clear(zoofile, orph->pgrp)) - fprintf(stderr, "ltp-pan(%s): %s\n", panname, zoo_error); - orph->pgrp = 0; - } else { - fprintf(stderr, - "ltp-pan(%s): kill(%d,%d) on orphaned pgrp failed. errno:%d %s\n", - panname, -(orph->pgrp), sig, errno, strerror(errno)); - } + for (orph = orphans; orph != NULL; orph = orph->next) { + if (orph->pgrp == 0) + continue; + + if (Debug & Dshutdown) + fprintf(stderr, " propagating sig %d to orphaned pgrp %d\n", + sig, -(orph->pgrp)); + if (kill(-(orph->pgrp), sig) != 0) { + if (errno == ESRCH) { + /* This pgrp is now empty */ + if (zoo_clear(zoofile, orph->pgrp)) { + fprintf(stderr, "pan(%s): %s\n", panname, zoo_error); } + orph->pgrp = 0; + } else { + fprintf(stderr, + "pan(%s): kill(%d,%d) on orphaned pgrp failed. errno:%d %s\n", + panname, -(orph->pgrp), sig, errno, strerror(errno)); + } } + } } -static void mark_orphan(struct orphan_pgrp *orphans, pid_t cpid) +static void +mark_orphan(struct orphan_pgrp *orphans, pid_t cpid) { - struct orphan_pgrp *orph; - - for (orph = orphans; orph != NULL; orph = orph->next) - if (orph->pgrp == 0) - break; - - if (orph == NULL) { - /* make a new struct */ - orph = (struct orphan_pgrp *) malloc(sizeof(struct orphan_pgrp)); - - /* plug in the new struct just after the head */ - orph->next = orphans->next; - orphans->next = orph; - } - - orph->pgrp = cpid; + struct orphan_pgrp *orph; + + for (orph = orphans; orph != NULL; orph = orph->next) { + if (orph->pgrp == 0) + break; + } + if (orph == NULL) { + /* make a new struct */ + orph = (struct orphan_pgrp *) malloc(sizeof(struct orphan_pgrp)); + + /* plug in the new struct just after the head */ + orph->next = orphans->next; + orphans->next = orph; + } + orph->pgrp = cpid; } -static void copy_buffered_output(struct tag_pgrp *running) +static void +copy_buffered_output(struct tag_pgrp *running) { - char *tag_output; - - tag_output = slurp(running->output); - - if (tag_output) { - printf("%s", tag_output); - /* make sure the output ends with a newline */ - if (tag_output[strlen(tag_output) - 1] != '\n') - printf("\n"); - fflush(stdout); - free(tag_output); - } + char *tag_output; + + tag_output = slurp(running->output); + if (tag_output) { + printf("%s", tag_output); + /* make sure the output ends with a newline */ + if (tag_output[strlen(tag_output) - 1] != '\n') + printf("\n"); + fflush(stdout); + free(tag_output); + } } -static void write_test_start(struct tag_pgrp *running, const char *init_status) +static void +write_test_start(struct tag_pgrp *running, const char *init_status) { - if (!strcmp(reporttype, "rts")) - printf("%s\ntag=%s stime=%ld\ncmdline=\"%s\"\ncontacts=\"%s\"\nanalysis=%s\ninitiation_status=\"%s\"\n%s\n", - "<<<test_start>>>", - running->cmd->name, running->mystime, running->cmd->cmdline, "", - "exit", init_status, - "<<<test_output>>>"); - - fflush(stdout); + if (!strcmp(reporttype, "rts")) { + + printf("%s\ntag=%s stime=%ld\ncmdline=\"%s\"\ncontacts=\"%s\"\nanalysis=%s\ninitiation_status=\"%s\"\n%s\n", + "<<<test_start>>>", + running->cmd->name, running->mystime, running->cmd->cmdline, "", + "exit", init_status, + "<<<test_output>>>"); + } + fflush(stdout); } -static void write_test_end(struct tag_pgrp *running, time_t exit_time, - char *term_type, int stat_loc, int term_id, - struct tms *tms1, struct tms *tms2) +static void +write_test_end(struct tag_pgrp *running, time_t exit_time, + char *term_type, int stat_loc, int term_id, + struct tms *tms1, struct tms *tms2) { - if (!strcmp(reporttype, "rts")) - printf("%s\nduration=%ld termination_type=%s termination_id=%d corefile=%s\ncutime=%d cstime=%d\n%s\n", - "<<<execution_status>>>", - (long) (exit_time - running->mystime), - term_type, term_id, (stat_loc & 0200) ? "yes" : "no", - (int) (tms2->tms_cutime - tms1->tms_cutime), - (int) (tms2->tms_cstime - tms1->tms_cstime), - "<<<test_end>>>"); - - fflush(stdout); + if (!strcmp(reporttype, "rts")) { + printf("%s\nduration=%ld termination_type=%s termination_id=%d corefile=%s\ncutime=%d cstime=%d\n%s\n", + "<<<execution_status>>>", + (long) (exit_time - running->mystime), + term_type, term_id, (stat_loc & 0200) ? "yes" : "no", + (int) (tms2->tms_cutime - tms1->tms_cutime), + (int) (tms2->tms_cstime - tms1->tms_cstime), + "<<<test_end>>>"); + } + fflush(stdout); } -/* Debugging functions */ +/* The functions below are all debugging related */ -static void pids_running(struct tag_pgrp *running, int keep_active) +static void +pids_running(struct tag_pgrp *running, int keep_active) { - int i; - - fprintf(stderr, "pids still running: "); - for (i = 0; i < keep_active; ++i) { - if (running[i].pgrp != 0) - fprintf(stderr, "%d ", running[i].pgrp); - } - fprintf(stderr, "\n"); + int i; + + fprintf(stderr, "pids still running: "); + for (i = 0; i < keep_active; ++i) { + if (running[i].pgrp != 0) + fprintf(stderr, "%d ", running[i].pgrp); + } + fprintf(stderr, "\n"); } -static void orphans_running(struct orphan_pgrp *orphans) +static void +orphans_running(struct orphan_pgrp *orphans) { - struct orphan_pgrp *orph; - - fprintf(stderr, "orphans still running: "); - - for (orph = orphans; orph != NULL; orph = orph->next) { - if (orph->pgrp != 0) - fprintf(stderr, "%d ", -(orph->pgrp)); - } - fprintf(stderr, "\n"); + struct orphan_pgrp *orph; + + fprintf(stderr, "orphans still running: "); + for (orph = orphans; orph != NULL; orph = orph->next) { + if (orph->pgrp != 0) + fprintf(stderr, "%d ", -(orph->pgrp)); + } + fprintf(stderr, "\n"); } -static void dump_coll(struct collection *coll) +static void +dump_coll(struct collection *coll) { - int i; + int i; - for (i = 0; i < coll->cnt; ++i) { - fprintf(stderr, "coll %d\n", i); - fprintf(stderr, " name=%s cmdline=%s\n", coll->ary[i]->name, - coll->ary[i]->cmdline); - } + for (i = 0; i < coll->cnt; ++i) { + fprintf(stderr, "coll %d\n", i); + fprintf(stderr, " name=%s cmdline=%s\n", coll->ary[i]->name, + coll->ary[i]->cmdline); + } } -void wait_handler(int sig) +void +wait_handler( int sig ) { - int lastsent = 0; + static int lastsent = 0; - if (sig == 0) { - lastsent = 0; - return; - } - + if( sig == 0 ){ + lastsent = 0; + } else { rec_signal = sig; - - if(sig == SIGUSR2) - return; - - if(lastsent == 0) - send_signal = sig; - else if(lastsent == SIGUSR1) - send_signal = SIGINT; - else if(lastsent == sig) - send_signal = SIGTERM; - else if(lastsent == SIGTERM) - send_signal = SIGHUP; - else if(lastsent == SIGHUP) - send_signal = SIGKILL; - + if( sig == SIGUSR2 ) + return; + if( lastsent == 0 ) + send_signal = sig; + else if( lastsent == SIGUSR1 ) + send_signal = SIGINT; + else if( lastsent == sig ) + send_signal = SIGTERM; + else if( lastsent == SIGTERM ) + send_signal = SIGHUP; + else if( lastsent == SIGHUP ) + send_signal = SIGKILL; lastsent = send_signal; + } } + |