xref: /aosp_15_r20/external/ltp/pan/ltp-pan.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3*49cdfc7eSAndroid Build Coastguard Worker  *
4*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify it
5*49cdfc7eSAndroid Build Coastguard Worker  * under the terms of version 2 of the GNU General Public License as
6*49cdfc7eSAndroid Build Coastguard Worker  * published by the Free Software Foundation.
7*49cdfc7eSAndroid Build Coastguard Worker  *
8*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it would be useful, but
9*49cdfc7eSAndroid Build Coastguard Worker  * WITHOUT ANY WARRANTY; without even the implied warranty of
10*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * Further, this software is distributed without any warranty that it is
13*49cdfc7eSAndroid Build Coastguard Worker  * free of the rightful claim of any third person regarding infringement
14*49cdfc7eSAndroid Build Coastguard Worker  * or the like.  Any license provided herein, whether implied or
15*49cdfc7eSAndroid Build Coastguard Worker  * otherwise, applies only to this software file.  Patent licenses, if
16*49cdfc7eSAndroid Build Coastguard Worker  * any, provided herein do not apply to combinations of this program with
17*49cdfc7eSAndroid Build Coastguard Worker  * other software, or any other product whatsoever.
18*49cdfc7eSAndroid Build Coastguard Worker  *
19*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License along
20*49cdfc7eSAndroid Build Coastguard Worker  * with this program; if not, write the Free Software Foundation, Inc.,
21*49cdfc7eSAndroid Build Coastguard Worker  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22*49cdfc7eSAndroid Build Coastguard Worker  *
23*49cdfc7eSAndroid Build Coastguard Worker  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24*49cdfc7eSAndroid Build Coastguard Worker  * Mountain View, CA  94043, or:
25*49cdfc7eSAndroid Build Coastguard Worker  *
26*49cdfc7eSAndroid Build Coastguard Worker  * http://www.sgi.com
27*49cdfc7eSAndroid Build Coastguard Worker  *
28*49cdfc7eSAndroid Build Coastguard Worker  * For further information regarding this notice, see:
29*49cdfc7eSAndroid Build Coastguard Worker  *
30*49cdfc7eSAndroid Build Coastguard Worker  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31*49cdfc7eSAndroid Build Coastguard Worker  *
32*49cdfc7eSAndroid Build Coastguard Worker  * Changelog:
33*49cdfc7eSAndroid Build Coastguard Worker  *
34*49cdfc7eSAndroid Build Coastguard Worker  *	Added timer options: William Jay Huie, IBM
35*49cdfc7eSAndroid Build Coastguard Worker  *	01/27/03 - Added: Manoj Iyer, [email protected]
36*49cdfc7eSAndroid Build Coastguard Worker  *			   - option '-p' (pretty printing)i to enabled formatted printing
37*49cdfc7eSAndroid Build Coastguard Worker  *			     of results.
38*49cdfc7eSAndroid Build Coastguard Worker  *
39*49cdfc7eSAndroid Build Coastguard Worker  *	01/27/03 - Added: Manoj Iyer, [email protected]
40*49cdfc7eSAndroid Build Coastguard Worker  *			   - added code to print system information
41*49cdfc7eSAndroid Build Coastguard Worker  *
42*49cdfc7eSAndroid Build Coastguard Worker  *	01/28/03 - Added: Manoj Iyer, [email protected]
43*49cdfc7eSAndroid Build Coastguard Worker  *			   - added code to print test exit value.
44*49cdfc7eSAndroid Build Coastguard Worker  *
45*49cdfc7eSAndroid Build Coastguard Worker  *	01/29/03 - Added: Manoj Iyer, [email protected]
46*49cdfc7eSAndroid Build Coastguard Worker  *			   - added code supresses test start and test end tags.
47*49cdfc7eSAndroid Build Coastguard Worker  *
48*49cdfc7eSAndroid Build Coastguard Worker  * 	07/22/07 - Added: Ricardo Salveti de Araujo, [email protected]
49*49cdfc7eSAndroid Build Coastguard Worker  *			   - added option to create a command file with all failed tests.
50*49cdfc7eSAndroid Build Coastguard Worker  *
51*49cdfc7eSAndroid Build Coastguard Worker  */
52*49cdfc7eSAndroid Build Coastguard Worker /* $Id: ltp-pan.c,v 1.4 2009/10/15 18:45:55 yaberauneya Exp $ */
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker #include <sys/param.h>
55*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
56*49cdfc7eSAndroid Build Coastguard Worker #include <stdarg.h>
57*49cdfc7eSAndroid Build Coastguard Worker #include <sys/times.h>
58*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
59*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
60*49cdfc7eSAndroid Build Coastguard Worker #include <sys/utsname.h>
61*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
62*49cdfc7eSAndroid Build Coastguard Worker #include <err.h>
63*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
64*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
65*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
66*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
67*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
68*49cdfc7eSAndroid Build Coastguard Worker #include <ctype.h>
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker #include "splitstr.h"
71*49cdfc7eSAndroid Build Coastguard Worker #include "zoolib.h"
72*49cdfc7eSAndroid Build Coastguard Worker #include "tst_res_flags.h"
73*49cdfc7eSAndroid Build Coastguard Worker 
74*49cdfc7eSAndroid Build Coastguard Worker /* One entry in the command line collection.  */
75*49cdfc7eSAndroid Build Coastguard Worker struct coll_entry {
76*49cdfc7eSAndroid Build Coastguard Worker 	char *name;		/* tag name */
77*49cdfc7eSAndroid Build Coastguard Worker 	char *cmdline;		/* command line */
78*49cdfc7eSAndroid Build Coastguard Worker 	char *pcnt_f;		/* location of %f in the command line args, flag */
79*49cdfc7eSAndroid Build Coastguard Worker 	struct coll_entry *next;
80*49cdfc7eSAndroid Build Coastguard Worker };
81*49cdfc7eSAndroid Build Coastguard Worker 
82*49cdfc7eSAndroid Build Coastguard Worker struct collection {
83*49cdfc7eSAndroid Build Coastguard Worker 	int cnt;
84*49cdfc7eSAndroid Build Coastguard Worker 	struct coll_entry **ary;
85*49cdfc7eSAndroid Build Coastguard Worker };
86*49cdfc7eSAndroid Build Coastguard Worker 
87*49cdfc7eSAndroid Build Coastguard Worker struct tag_pgrp {
88*49cdfc7eSAndroid Build Coastguard Worker 	int pgrp;
89*49cdfc7eSAndroid Build Coastguard Worker 	int stopping;
90*49cdfc7eSAndroid Build Coastguard Worker 	time_t mystime;
91*49cdfc7eSAndroid Build Coastguard Worker 	struct coll_entry *cmd;
92*49cdfc7eSAndroid Build Coastguard Worker 	char output[PATH_MAX];
93*49cdfc7eSAndroid Build Coastguard Worker };
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker struct orphan_pgrp {
96*49cdfc7eSAndroid Build Coastguard Worker 	int pgrp;
97*49cdfc7eSAndroid Build Coastguard Worker 	struct orphan_pgrp *next;
98*49cdfc7eSAndroid Build Coastguard Worker };
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker static pid_t run_child(struct coll_entry *colle, struct tag_pgrp *active,
101*49cdfc7eSAndroid Build Coastguard Worker 		       int quiet_mode, int *failcnt, int fmt_print,
102*49cdfc7eSAndroid Build Coastguard Worker 		       FILE * logfile, int no_kmsg);
103*49cdfc7eSAndroid Build Coastguard Worker static char *slurp(char *file);
104*49cdfc7eSAndroid Build Coastguard Worker static struct collection *get_collection(char *file, int optind, int argc,
105*49cdfc7eSAndroid Build Coastguard Worker 					 char **argv);
106*49cdfc7eSAndroid Build Coastguard Worker static void pids_running(struct tag_pgrp *running, int keep_active);
107*49cdfc7eSAndroid Build Coastguard Worker static int check_pids(struct tag_pgrp *running, int *num_active,
108*49cdfc7eSAndroid Build Coastguard Worker 		      int keep_active, FILE * logfile, FILE * failcmdfile,
109*49cdfc7eSAndroid Build Coastguard Worker 		      FILE *tconfcmdfile, struct orphan_pgrp *orphans,
110*49cdfc7eSAndroid Build Coastguard Worker 		      int fmt_print, int *failcnt, int *tconfcnt,
111*49cdfc7eSAndroid Build Coastguard Worker 		      int quiet_mode, int no_kmsg);
112*49cdfc7eSAndroid Build Coastguard Worker static void propagate_signal(struct tag_pgrp *running, int keep_active,
113*49cdfc7eSAndroid Build Coastguard Worker 			     struct orphan_pgrp *orphans);
114*49cdfc7eSAndroid Build Coastguard Worker static void dump_coll(struct collection *coll);
115*49cdfc7eSAndroid Build Coastguard Worker static char *subst_pcnt_f(struct coll_entry *colle);
116*49cdfc7eSAndroid Build Coastguard Worker static void mark_orphan(struct orphan_pgrp *orphans, pid_t cpid);
117*49cdfc7eSAndroid Build Coastguard Worker static void orphans_running(struct orphan_pgrp *orphans);
118*49cdfc7eSAndroid Build Coastguard Worker static void check_orphans(struct orphan_pgrp *orphans, int sig);
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker static void copy_buffered_output(struct tag_pgrp *running);
121*49cdfc7eSAndroid Build Coastguard Worker static void write_test_start(struct tag_pgrp *running, int no_kmsg);
122*49cdfc7eSAndroid Build Coastguard Worker static void write_test_end(struct tag_pgrp *running, const char *init_status,
123*49cdfc7eSAndroid Build Coastguard Worker 			   time_t exit_time, char *term_type, int stat_loc,
124*49cdfc7eSAndroid Build Coastguard Worker 			   int term_id, struct tms *tms1, struct tms *tms2);
125*49cdfc7eSAndroid Build Coastguard Worker 
126*49cdfc7eSAndroid Build Coastguard Worker //wjh
127*49cdfc7eSAndroid Build Coastguard Worker static char PAN_STOP_FILE[] = "PAN_STOP_FILE";
128*49cdfc7eSAndroid Build Coastguard Worker 
129*49cdfc7eSAndroid Build Coastguard Worker static char *panname = NULL;
130*49cdfc7eSAndroid Build Coastguard Worker static char *test_out_dir = NULL;	/* dir to buffer output to */
131*49cdfc7eSAndroid Build Coastguard Worker zoo_t zoofile;
132*49cdfc7eSAndroid Build Coastguard Worker static char *reporttype = NULL;
133*49cdfc7eSAndroid Build Coastguard Worker 
134*49cdfc7eSAndroid Build Coastguard Worker /* Common format string for ltp-pan results */
135*49cdfc7eSAndroid Build Coastguard Worker #define ResultFmt	"%-50s %-10.10s"
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker /* zoolib */
138*49cdfc7eSAndroid Build Coastguard Worker int rec_signal;			/* received signal */
139*49cdfc7eSAndroid Build Coastguard Worker int send_signal;		/* signal to send */
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker /* Debug Bits */
142*49cdfc7eSAndroid Build Coastguard Worker int Debug = 0;
143*49cdfc7eSAndroid Build Coastguard Worker #define Dbuffile	0x000400	/* buffer file use */
144*49cdfc7eSAndroid Build Coastguard Worker #define	Dsetup		0x000200	/* one-time set-up */
145*49cdfc7eSAndroid Build Coastguard Worker #define	Dshutdown	0x000100	/* killed by signal */
146*49cdfc7eSAndroid Build Coastguard Worker #define	Dexit		0x000020	/* exit status */
147*49cdfc7eSAndroid Build Coastguard Worker #define	Drunning	0x000010	/* current pids running */
148*49cdfc7eSAndroid Build Coastguard Worker #define	Dstartup	0x000004	/* started command */
149*49cdfc7eSAndroid Build Coastguard Worker #define	Dstart		0x000002	/* started command */
150*49cdfc7eSAndroid Build Coastguard Worker #define Dwait		0x000001	/* wait interrupted */
151*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char ** argv)152*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char **argv)
153*49cdfc7eSAndroid Build Coastguard Worker {
154*49cdfc7eSAndroid Build Coastguard Worker 	extern char *optarg;
155*49cdfc7eSAndroid Build Coastguard Worker 	extern int optind;
156*49cdfc7eSAndroid Build Coastguard Worker 	char *zooname = NULL;	/* name of the zoo file to use */
157*49cdfc7eSAndroid Build Coastguard Worker 	char *filename = "/dev/null";	/* filename to read test tags from */
158*49cdfc7eSAndroid Build Coastguard Worker 	char *logfilename = NULL;
159*49cdfc7eSAndroid Build Coastguard Worker 	char *failcmdfilename = NULL;
160*49cdfc7eSAndroid Build Coastguard Worker 	char *tconfcmdfilename = NULL;
161*49cdfc7eSAndroid Build Coastguard Worker 	char *outputfilename = NULL;
162*49cdfc7eSAndroid Build Coastguard Worker 	struct collection *coll = NULL;
163*49cdfc7eSAndroid Build Coastguard Worker 	struct tag_pgrp *running;
164*49cdfc7eSAndroid Build Coastguard Worker 	struct orphan_pgrp *orphans, *orph;
165*49cdfc7eSAndroid Build Coastguard Worker 	struct utsname unamebuf;
166*49cdfc7eSAndroid Build Coastguard Worker 	FILE *logfile = NULL;
167*49cdfc7eSAndroid Build Coastguard Worker 	FILE *failcmdfile = NULL;
168*49cdfc7eSAndroid Build Coastguard Worker 	FILE *tconfcmdfile = NULL;
169*49cdfc7eSAndroid Build Coastguard Worker 	int keep_active = 1;
170*49cdfc7eSAndroid Build Coastguard Worker 	int num_active = 0;
171*49cdfc7eSAndroid Build Coastguard Worker 	int failcnt = 0;  /* count of total testcases that failed. */
172*49cdfc7eSAndroid Build Coastguard Worker 	int tconfcnt = 0; /* count of total testcases that return TCONF */
173*49cdfc7eSAndroid Build Coastguard Worker 	int err, i;
174*49cdfc7eSAndroid Build Coastguard Worker 	int starts = -1;
175*49cdfc7eSAndroid Build Coastguard Worker 	int timed = 0;
176*49cdfc7eSAndroid Build Coastguard Worker 	int run_time = -1;
177*49cdfc7eSAndroid Build Coastguard Worker 	char modifier = 'm';
178*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
179*49cdfc7eSAndroid Build Coastguard Worker 	int stop;
180*49cdfc7eSAndroid Build Coastguard Worker 	int go_idle;
181*49cdfc7eSAndroid Build Coastguard Worker 	int has_brakes = 0;	/* stop everything if a test case fails */
182*49cdfc7eSAndroid Build Coastguard Worker 	int sequential = 0;	/* run tests sequentially */
183*49cdfc7eSAndroid Build Coastguard Worker 	int fork_in_road = 0;
184*49cdfc7eSAndroid Build Coastguard Worker 	int exit_stat;
185*49cdfc7eSAndroid Build Coastguard Worker 	int track_exit_stats = 0;	/* exit non-zero if any test exits non-zero */
186*49cdfc7eSAndroid Build Coastguard Worker 	int fmt_print = 0;	/* enables formatted printing of logfiles. */
187*49cdfc7eSAndroid Build Coastguard Worker 	int quiet_mode = 0;	/* supresses test start and test end tags. */
188*49cdfc7eSAndroid Build Coastguard Worker 	int no_kmsg = 0;	/* don't log into /dev/kmsg */
189*49cdfc7eSAndroid Build Coastguard Worker 	int c;
190*49cdfc7eSAndroid Build Coastguard Worker 	pid_t cpid;
191*49cdfc7eSAndroid Build Coastguard Worker 	struct sigaction sa;
192*49cdfc7eSAndroid Build Coastguard Worker 
193*49cdfc7eSAndroid Build Coastguard Worker 	while ((c =
194*49cdfc7eSAndroid Build Coastguard Worker 		getopt(argc, argv, "AO:Sa:C:QT:d:ef:hl:n:o:pqr:s:t:x:y"))
195*49cdfc7eSAndroid Build Coastguard Worker 		       != -1) {
196*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
197*49cdfc7eSAndroid Build Coastguard Worker 		case 'A':	/* all-stop flag */
198*49cdfc7eSAndroid Build Coastguard Worker 			has_brakes = 1;
199*49cdfc7eSAndroid Build Coastguard Worker 			track_exit_stats = 1;
200*49cdfc7eSAndroid Build Coastguard Worker 			break;
201*49cdfc7eSAndroid Build Coastguard Worker 		case 'O':	/* output buffering directory */
202*49cdfc7eSAndroid Build Coastguard Worker 			test_out_dir = strdup(optarg);
203*49cdfc7eSAndroid Build Coastguard Worker 			break;
204*49cdfc7eSAndroid Build Coastguard Worker 		case 'S':	/* run tests sequentially */
205*49cdfc7eSAndroid Build Coastguard Worker 			sequential = 1;
206*49cdfc7eSAndroid Build Coastguard Worker 			break;
207*49cdfc7eSAndroid Build Coastguard Worker 		case 'a':	/* name of the zoo file to use */
208*49cdfc7eSAndroid Build Coastguard Worker 			zooname = strdup(optarg);
209*49cdfc7eSAndroid Build Coastguard Worker 			break;
210*49cdfc7eSAndroid Build Coastguard Worker 		case 'C':	/* name of the file where all failed commands will be */
211*49cdfc7eSAndroid Build Coastguard Worker 			failcmdfilename = strdup(optarg);
212*49cdfc7eSAndroid Build Coastguard Worker 			break;
213*49cdfc7eSAndroid Build Coastguard Worker 		case 'Q':
214*49cdfc7eSAndroid Build Coastguard Worker 			no_kmsg = 1;
215*49cdfc7eSAndroid Build Coastguard Worker 			break;
216*49cdfc7eSAndroid Build Coastguard Worker 		case 'T':
217*49cdfc7eSAndroid Build Coastguard Worker 			/*
218*49cdfc7eSAndroid Build Coastguard Worker 			 * test cases that are not fully tested will be recorded
219*49cdfc7eSAndroid Build Coastguard Worker 			 * in this file
220*49cdfc7eSAndroid Build Coastguard Worker 			 */
221*49cdfc7eSAndroid Build Coastguard Worker 			tconfcmdfilename = strdup(optarg);
222*49cdfc7eSAndroid Build Coastguard Worker 			break;
223*49cdfc7eSAndroid Build Coastguard Worker 		case 'd':	/* debug options */
224*49cdfc7eSAndroid Build Coastguard Worker 			sscanf(optarg, "%i", &Debug);
225*49cdfc7eSAndroid Build Coastguard Worker 			break;
226*49cdfc7eSAndroid Build Coastguard Worker 		case 'e':	/* exit non-zero if any test exists non-zero */
227*49cdfc7eSAndroid Build Coastguard Worker 			track_exit_stats = 1;
228*49cdfc7eSAndroid Build Coastguard Worker 			break;
229*49cdfc7eSAndroid Build Coastguard Worker 		case 'f':	/* filename to read test tags from */
230*49cdfc7eSAndroid Build Coastguard Worker 			filename = strdup(optarg);
231*49cdfc7eSAndroid Build Coastguard Worker 			break;
232*49cdfc7eSAndroid Build Coastguard Worker 		case 'h':	/* help */
233*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stdout,
234*49cdfc7eSAndroid Build Coastguard Worker 				"Usage: pan -n name [ -SyAehpqQ ] [ -s starts ]"
235*49cdfc7eSAndroid Build Coastguard Worker 				" [-t time[s|m|h|d] [ -x nactive ] [ -l logfile ]\n\t"
236*49cdfc7eSAndroid Build Coastguard Worker 				"[ -a active-file ] [ -f command-file ] "
237*49cdfc7eSAndroid Build Coastguard Worker 				"[ -C fail-command-file ] "
238*49cdfc7eSAndroid Build Coastguard Worker 				"[ -d debug-level ]\n\t[-o output-file] "
239*49cdfc7eSAndroid Build Coastguard Worker 				"[-O output-buffer-directory] [cmd]\n");
240*49cdfc7eSAndroid Build Coastguard Worker 			exit(0);
241*49cdfc7eSAndroid Build Coastguard Worker 		case 'l':	/* log file */
242*49cdfc7eSAndroid Build Coastguard Worker 			logfilename = strdup(optarg);
243*49cdfc7eSAndroid Build Coastguard Worker 			break;
244*49cdfc7eSAndroid Build Coastguard Worker 		case 'n':	/* tag given to pan */
245*49cdfc7eSAndroid Build Coastguard Worker 			panname = strdup(optarg);
246*49cdfc7eSAndroid Build Coastguard Worker 			break;
247*49cdfc7eSAndroid Build Coastguard Worker 		case 'o':	/* send test output here */
248*49cdfc7eSAndroid Build Coastguard Worker 			outputfilename = strdup(optarg);
249*49cdfc7eSAndroid Build Coastguard Worker 			break;
250*49cdfc7eSAndroid Build Coastguard Worker 		case 'p':	/* formatted printing. */
251*49cdfc7eSAndroid Build Coastguard Worker 			fmt_print = 1;
252*49cdfc7eSAndroid Build Coastguard Worker 			break;
253*49cdfc7eSAndroid Build Coastguard Worker 		case 'q':	/* supress test start and test end messages */
254*49cdfc7eSAndroid Build Coastguard Worker 			quiet_mode = 1;
255*49cdfc7eSAndroid Build Coastguard Worker 			break;
256*49cdfc7eSAndroid Build Coastguard Worker 		case 'r':	/* reporting type: none, rts */
257*49cdfc7eSAndroid Build Coastguard Worker 			reporttype = strdup(optarg);
258*49cdfc7eSAndroid Build Coastguard Worker 			break;
259*49cdfc7eSAndroid Build Coastguard Worker 		case 's':	/* number of tags to run */
260*49cdfc7eSAndroid Build Coastguard Worker 			starts = atoi(optarg);
261*49cdfc7eSAndroid Build Coastguard Worker 			break;
262*49cdfc7eSAndroid Build Coastguard Worker 		case 't':	/* run_time to run */
263*49cdfc7eSAndroid Build Coastguard Worker 			ret = sscanf(optarg, "%d%c", &run_time, &modifier);
264*49cdfc7eSAndroid Build Coastguard Worker 			if (ret == 0) {
265*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
266*49cdfc7eSAndroid Build Coastguard Worker 					"Need proper time input: ####x where "
267*49cdfc7eSAndroid Build Coastguard Worker 					"x is one of s,m,h,d\n");
268*49cdfc7eSAndroid Build Coastguard Worker 				break;
269*49cdfc7eSAndroid Build Coastguard Worker 			} else if (ret == 1) {
270*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "Only got a time value of %d "
271*49cdfc7eSAndroid Build Coastguard Worker 					"modifiers need to come immediately after #"
272*49cdfc7eSAndroid Build Coastguard Worker 					" assuming %c\n", run_time, modifier);
273*49cdfc7eSAndroid Build Coastguard Worker 			} else {
274*49cdfc7eSAndroid Build Coastguard Worker 				switch (modifier) {
275*49cdfc7eSAndroid Build Coastguard Worker 				case 's':
276*49cdfc7eSAndroid Build Coastguard Worker 					run_time = run_time;
277*49cdfc7eSAndroid Build Coastguard Worker 					break;
278*49cdfc7eSAndroid Build Coastguard Worker 				case 'm':
279*49cdfc7eSAndroid Build Coastguard Worker 					run_time = run_time * 60;
280*49cdfc7eSAndroid Build Coastguard Worker 					break;
281*49cdfc7eSAndroid Build Coastguard Worker 				case 'h':
282*49cdfc7eSAndroid Build Coastguard Worker 					run_time = run_time * 60 * 60;
283*49cdfc7eSAndroid Build Coastguard Worker 					break;
284*49cdfc7eSAndroid Build Coastguard Worker 				case 'd':
285*49cdfc7eSAndroid Build Coastguard Worker 					run_time = run_time * 60 * 60 * 24;
286*49cdfc7eSAndroid Build Coastguard Worker 					break;
287*49cdfc7eSAndroid Build Coastguard Worker 				default:
288*49cdfc7eSAndroid Build Coastguard Worker 					fprintf(stderr,
289*49cdfc7eSAndroid Build Coastguard Worker 						"Invalid time modifier, try: s|h|m|d\n");
290*49cdfc7eSAndroid Build Coastguard Worker 					exit(-1);
291*49cdfc7eSAndroid Build Coastguard Worker 				}
292*49cdfc7eSAndroid Build Coastguard Worker 				if (!quiet_mode)
293*49cdfc7eSAndroid Build Coastguard Worker 					printf("PAN will run for %d seconds\n",
294*49cdfc7eSAndroid Build Coastguard Worker 					       run_time);
295*49cdfc7eSAndroid Build Coastguard Worker 			}
296*49cdfc7eSAndroid Build Coastguard Worker 			timed = 1;	//-t implies run as many starts as possible, by default
297*49cdfc7eSAndroid Build Coastguard Worker 			break;
298*49cdfc7eSAndroid Build Coastguard Worker 		case 'x':	/* number of tags to keep running */
299*49cdfc7eSAndroid Build Coastguard Worker 			keep_active = atoi(optarg);
300*49cdfc7eSAndroid Build Coastguard Worker 			break;
301*49cdfc7eSAndroid Build Coastguard Worker 		case 'y':	/* restart on failure or signal */
302*49cdfc7eSAndroid Build Coastguard Worker 			fork_in_road = 1;
303*49cdfc7eSAndroid Build Coastguard Worker 			break;
304*49cdfc7eSAndroid Build Coastguard Worker 		}
305*49cdfc7eSAndroid Build Coastguard Worker 	}
306*49cdfc7eSAndroid Build Coastguard Worker 
307*49cdfc7eSAndroid Build Coastguard Worker 	if (panname == NULL) {
308*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan: Must supply -n\n");
309*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
310*49cdfc7eSAndroid Build Coastguard Worker 	}
311*49cdfc7eSAndroid Build Coastguard Worker 	if (zooname == NULL) {
312*49cdfc7eSAndroid Build Coastguard Worker 		zooname = zoo_getname();
313*49cdfc7eSAndroid Build Coastguard Worker 		if (zooname == NULL) {
314*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
315*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): Must supply -a or set ZOO env variable\n",
316*49cdfc7eSAndroid Build Coastguard Worker 				panname);
317*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
318*49cdfc7eSAndroid Build Coastguard Worker 		}
319*49cdfc7eSAndroid Build Coastguard Worker 	}
320*49cdfc7eSAndroid Build Coastguard Worker 	if (reporttype) {
321*49cdfc7eSAndroid Build Coastguard Worker 		/* make sure we understand the report type */
322*49cdfc7eSAndroid Build Coastguard Worker 		if (strcasecmp(reporttype, "rts")
323*49cdfc7eSAndroid Build Coastguard Worker 		    && strcasecmp(reporttype, "none")
324*49cdfc7eSAndroid Build Coastguard Worker 		    /* && strcasecmp(reporttype, "xml") */
325*49cdfc7eSAndroid Build Coastguard Worker 		    )
326*49cdfc7eSAndroid Build Coastguard Worker 			reporttype = "rts";
327*49cdfc7eSAndroid Build Coastguard Worker 	} else {
328*49cdfc7eSAndroid Build Coastguard Worker 		/* set the default */
329*49cdfc7eSAndroid Build Coastguard Worker 		reporttype = "rts";
330*49cdfc7eSAndroid Build Coastguard Worker 	}
331*49cdfc7eSAndroid Build Coastguard Worker 
332*49cdfc7eSAndroid Build Coastguard Worker 	if (logfilename != NULL) {
333*49cdfc7eSAndroid Build Coastguard Worker 		time_t startup;
334*49cdfc7eSAndroid Build Coastguard Worker 		char *s;
335*49cdfc7eSAndroid Build Coastguard Worker 
336*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(logfilename, "-")) {
337*49cdfc7eSAndroid Build Coastguard Worker 			logfile = stdout;
338*49cdfc7eSAndroid Build Coastguard Worker 		} else {
339*49cdfc7eSAndroid Build Coastguard Worker 			if ((logfile = fopen(logfilename, "a+e")) == NULL) {
340*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
341*49cdfc7eSAndroid Build Coastguard Worker 					"pan(%s): Error %s (%d) opening log file '%s'\n",
342*49cdfc7eSAndroid Build Coastguard Worker 					panname, strerror(errno), errno,
343*49cdfc7eSAndroid Build Coastguard Worker 					logfilename);
344*49cdfc7eSAndroid Build Coastguard Worker 				exit(1);
345*49cdfc7eSAndroid Build Coastguard Worker 			}
346*49cdfc7eSAndroid Build Coastguard Worker 		}
347*49cdfc7eSAndroid Build Coastguard Worker 
348*49cdfc7eSAndroid Build Coastguard Worker 		time(&startup);
349*49cdfc7eSAndroid Build Coastguard Worker 		s = ctime(&startup);
350*49cdfc7eSAndroid Build Coastguard Worker 		*(s + strlen(s) - 1) = '\0';
351*49cdfc7eSAndroid Build Coastguard Worker 		if (!fmt_print)
352*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(logfile, "startup='%s'\n", s);
353*49cdfc7eSAndroid Build Coastguard Worker 		else {
354*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(logfile, "Test Start Time: %s\n", s);
355*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(logfile,
356*49cdfc7eSAndroid Build Coastguard Worker 				"-----------------------------------------\n");
357*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(logfile, ResultFmt" %-10.10s\n",
358*49cdfc7eSAndroid Build Coastguard Worker 				"Testcase", "Result", "Exit Value");
359*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(logfile, ResultFmt" %-10.10s\n",
360*49cdfc7eSAndroid Build Coastguard Worker 				"--------", "------", "------------");
361*49cdfc7eSAndroid Build Coastguard Worker 		}
362*49cdfc7eSAndroid Build Coastguard Worker 		fflush(logfile);
363*49cdfc7eSAndroid Build Coastguard Worker 	}
364*49cdfc7eSAndroid Build Coastguard Worker 
365*49cdfc7eSAndroid Build Coastguard Worker 	coll = get_collection(filename, optind, argc, argv);
366*49cdfc7eSAndroid Build Coastguard Worker 	if (!coll)
367*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
368*49cdfc7eSAndroid Build Coastguard Worker 	if (coll->cnt == 0) {
369*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr,
370*49cdfc7eSAndroid Build Coastguard Worker 			"pan(%s): Must supply a file collection or a command\n",
371*49cdfc7eSAndroid Build Coastguard Worker 			panname);
372*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
373*49cdfc7eSAndroid Build Coastguard Worker 	}
374*49cdfc7eSAndroid Build Coastguard Worker 
375*49cdfc7eSAndroid Build Coastguard Worker 	if (Debug & Dsetup)
376*49cdfc7eSAndroid Build Coastguard Worker 		dump_coll(coll);
377*49cdfc7eSAndroid Build Coastguard Worker 
378*49cdfc7eSAndroid Build Coastguard Worker 	/* a place to store the pgrps we're watching */
379*49cdfc7eSAndroid Build Coastguard Worker 	running =
380*49cdfc7eSAndroid Build Coastguard Worker 		malloc((keep_active + 1) *
381*49cdfc7eSAndroid Build Coastguard Worker 			sizeof(struct tag_pgrp));
382*49cdfc7eSAndroid Build Coastguard Worker 	if (running == NULL) {
383*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): Failed to allocate memory: %s\n",
384*49cdfc7eSAndroid Build Coastguard Worker 			panname, strerror(errno));
385*49cdfc7eSAndroid Build Coastguard Worker 		exit(2);
386*49cdfc7eSAndroid Build Coastguard Worker 	}
387*49cdfc7eSAndroid Build Coastguard Worker 	memset(running, 0, keep_active * sizeof(struct tag_pgrp));
388*49cdfc7eSAndroid Build Coastguard Worker 	running[keep_active].pgrp = -1;	/* end sentinel */
389*49cdfc7eSAndroid Build Coastguard Worker 
390*49cdfc7eSAndroid Build Coastguard Worker 	/* a head to the orphaned pgrp list */
391*49cdfc7eSAndroid Build Coastguard Worker 	orphans = malloc(sizeof(struct orphan_pgrp));
392*49cdfc7eSAndroid Build Coastguard Worker 	memset(orphans, 0, sizeof(struct orphan_pgrp));
393*49cdfc7eSAndroid Build Coastguard Worker 
394*49cdfc7eSAndroid Build Coastguard Worker 	srand48(time(NULL) ^ (getpid() + (getpid() << 15)));
395*49cdfc7eSAndroid Build Coastguard Worker 
396*49cdfc7eSAndroid Build Coastguard Worker 	/* Supply a default for starts.  If we are in sequential mode, use
397*49cdfc7eSAndroid Build Coastguard Worker 	 * the number of commands available; otherwise 1.
398*49cdfc7eSAndroid Build Coastguard Worker 	 */
399*49cdfc7eSAndroid Build Coastguard Worker 	if (timed == 1 && starts == -1) {	/* timed, infinite by default */
400*49cdfc7eSAndroid Build Coastguard Worker 		starts = -1;
401*49cdfc7eSAndroid Build Coastguard Worker 	} else if (starts == -1) {
402*49cdfc7eSAndroid Build Coastguard Worker 		if (sequential) {
403*49cdfc7eSAndroid Build Coastguard Worker 			starts = coll->cnt;
404*49cdfc7eSAndroid Build Coastguard Worker 		} else {
405*49cdfc7eSAndroid Build Coastguard Worker 			starts = 1;
406*49cdfc7eSAndroid Build Coastguard Worker 		}
407*49cdfc7eSAndroid Build Coastguard Worker 	} else if (starts == 0) {	/* if the user specified infinite, set it */
408*49cdfc7eSAndroid Build Coastguard Worker 		starts = -1;
409*49cdfc7eSAndroid Build Coastguard Worker 	} else {		/* else, make sure we are starting at least keep_active processes */
410*49cdfc7eSAndroid Build Coastguard Worker 		if (starts < keep_active)
411*49cdfc7eSAndroid Build Coastguard Worker 			starts = keep_active;
412*49cdfc7eSAndroid Build Coastguard Worker 	}
413*49cdfc7eSAndroid Build Coastguard Worker 
414*49cdfc7eSAndroid Build Coastguard Worker 	/* if we're buffering output, but we're only running on process at a time,
415*49cdfc7eSAndroid Build Coastguard Worker 	 * then essentially "turn off buffering"
416*49cdfc7eSAndroid Build Coastguard Worker 	 */
417*49cdfc7eSAndroid Build Coastguard Worker 	if (test_out_dir && (keep_active == 1)) {
418*49cdfc7eSAndroid Build Coastguard Worker 		free(test_out_dir);
419*49cdfc7eSAndroid Build Coastguard Worker 		test_out_dir = NULL;
420*49cdfc7eSAndroid Build Coastguard Worker 	}
421*49cdfc7eSAndroid Build Coastguard Worker 
422*49cdfc7eSAndroid Build Coastguard Worker 	if (test_out_dir) {
423*49cdfc7eSAndroid Build Coastguard Worker 		struct stat sbuf;
424*49cdfc7eSAndroid Build Coastguard Worker 
425*49cdfc7eSAndroid Build Coastguard Worker 		if (stat(test_out_dir, &sbuf) < 0) {
426*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
427*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): stat of -O arg '%s' failed.  errno: %d  %s\n",
428*49cdfc7eSAndroid Build Coastguard Worker 				panname, test_out_dir, errno, strerror(errno));
429*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
430*49cdfc7eSAndroid Build Coastguard Worker 		}
431*49cdfc7eSAndroid Build Coastguard Worker 		if (!S_ISDIR(sbuf.st_mode)) {
432*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
433*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): -O arg '%s' must be a directory.\n",
434*49cdfc7eSAndroid Build Coastguard Worker 				panname, test_out_dir);
435*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
436*49cdfc7eSAndroid Build Coastguard Worker 		}
437*49cdfc7eSAndroid Build Coastguard Worker 		if (access(test_out_dir, W_OK | R_OK | X_OK) < 0) {
438*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
439*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): permission denied on -O arg '%s'.  errno: %d  %s\n",
440*49cdfc7eSAndroid Build Coastguard Worker 				panname, test_out_dir, errno, strerror(errno));
441*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
442*49cdfc7eSAndroid Build Coastguard Worker 		}
443*49cdfc7eSAndroid Build Coastguard Worker 	}
444*49cdfc7eSAndroid Build Coastguard Worker 
445*49cdfc7eSAndroid Build Coastguard Worker 	if (outputfilename) {
446*49cdfc7eSAndroid Build Coastguard Worker 		if (!freopen(outputfilename, "a+", stdout)) {
447*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
448*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): Error %s (%d) opening output file '%s'\n",
449*49cdfc7eSAndroid Build Coastguard Worker 				panname, strerror(errno), errno,
450*49cdfc7eSAndroid Build Coastguard Worker 				outputfilename);
451*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
452*49cdfc7eSAndroid Build Coastguard Worker 		}
453*49cdfc7eSAndroid Build Coastguard Worker 	}
454*49cdfc7eSAndroid Build Coastguard Worker 
455*49cdfc7eSAndroid Build Coastguard Worker 	if (failcmdfilename) {
456*49cdfc7eSAndroid Build Coastguard Worker 		if (!(failcmdfile = fopen(failcmdfilename, "a+e"))) {
457*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
458*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): Error %s (%d) opening fail cmd file '%s'\n",
459*49cdfc7eSAndroid Build Coastguard Worker 				panname, strerror(errno), errno,
460*49cdfc7eSAndroid Build Coastguard Worker 				failcmdfilename);
461*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
462*49cdfc7eSAndroid Build Coastguard Worker 		}
463*49cdfc7eSAndroid Build Coastguard Worker 	}
464*49cdfc7eSAndroid Build Coastguard Worker 
465*49cdfc7eSAndroid Build Coastguard Worker 	if (tconfcmdfilename) {
466*49cdfc7eSAndroid Build Coastguard Worker 		tconfcmdfile = fopen(tconfcmdfilename, "a+e");
467*49cdfc7eSAndroid Build Coastguard Worker 		if (!tconfcmdfile) {
468*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "pan(%s): Error %s (%d) opening "
469*49cdfc7eSAndroid Build Coastguard Worker 				"tconf cmd file '%s'\n", panname,
470*49cdfc7eSAndroid Build Coastguard Worker 				strerror(errno), errno, tconfcmdfilename);
471*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
472*49cdfc7eSAndroid Build Coastguard Worker 		}
473*49cdfc7eSAndroid Build Coastguard Worker 	}
474*49cdfc7eSAndroid Build Coastguard Worker 
475*49cdfc7eSAndroid Build Coastguard Worker 	if ((zoofile = zoo_open(zooname)) == NULL) {
476*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
477*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
478*49cdfc7eSAndroid Build Coastguard Worker 	}
479*49cdfc7eSAndroid Build Coastguard Worker 	if (zoo_mark_args(zoofile, getpid(), panname, argc, argv)) {
480*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
481*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
482*49cdfc7eSAndroid Build Coastguard Worker 	}
483*49cdfc7eSAndroid Build Coastguard Worker 
484*49cdfc7eSAndroid Build Coastguard Worker 	/* Allocate N spaces for max-arg commands.
485*49cdfc7eSAndroid Build Coastguard Worker 	 * this is an "active file cleanliness" thing
486*49cdfc7eSAndroid Build Coastguard Worker 	 */
487*49cdfc7eSAndroid Build Coastguard Worker 	{
488*49cdfc7eSAndroid Build Coastguard Worker 		for (c = 0; c < keep_active; c++) {
489*49cdfc7eSAndroid Build Coastguard Worker 			if (zoo_mark_cmdline(zoofile, c, panname, "")) {
490*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "pan(%s): %s\n", panname,
491*49cdfc7eSAndroid Build Coastguard Worker 					zoo_error);
492*49cdfc7eSAndroid Build Coastguard Worker 				exit(1);
493*49cdfc7eSAndroid Build Coastguard Worker 			}
494*49cdfc7eSAndroid Build Coastguard Worker 		}
495*49cdfc7eSAndroid Build Coastguard Worker 		for (c = 0; c < keep_active; c++) {
496*49cdfc7eSAndroid Build Coastguard Worker 			if (zoo_clear(zoofile, c)) {
497*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "pan(%s): %s\n", panname,
498*49cdfc7eSAndroid Build Coastguard Worker 					zoo_error);
499*49cdfc7eSAndroid Build Coastguard Worker 				exit(1);
500*49cdfc7eSAndroid Build Coastguard Worker 			}
501*49cdfc7eSAndroid Build Coastguard Worker 		}
502*49cdfc7eSAndroid Build Coastguard Worker 	}
503*49cdfc7eSAndroid Build Coastguard Worker 
504*49cdfc7eSAndroid Build Coastguard Worker 	rec_signal = send_signal = 0;
505*49cdfc7eSAndroid Build Coastguard Worker 	if (run_time != -1) {
506*49cdfc7eSAndroid Build Coastguard Worker 		alarm(run_time);
507*49cdfc7eSAndroid Build Coastguard Worker 	}
508*49cdfc7eSAndroid Build Coastguard Worker 
509*49cdfc7eSAndroid Build Coastguard Worker 	sigemptyset(&sa.sa_mask);
510*49cdfc7eSAndroid Build Coastguard Worker 	sa.sa_flags = 0;
511*49cdfc7eSAndroid Build Coastguard Worker 	sa.sa_handler = wait_handler;
512*49cdfc7eSAndroid Build Coastguard Worker 
513*49cdfc7eSAndroid Build Coastguard Worker 	sigaction(SIGALRM, &sa, NULL);
514*49cdfc7eSAndroid Build Coastguard Worker 	sigaction(SIGINT, &sa, NULL);
515*49cdfc7eSAndroid Build Coastguard Worker 	sigaction(SIGTERM, &sa, NULL);
516*49cdfc7eSAndroid Build Coastguard Worker 	sigaction(SIGHUP, &sa, NULL);
517*49cdfc7eSAndroid Build Coastguard Worker 	sigaction(SIGUSR1, &sa, NULL);	/* ignore fork_in_road */
518*49cdfc7eSAndroid Build Coastguard Worker 	sigaction(SIGUSR2, &sa, NULL);	/* stop the scheduler */
519*49cdfc7eSAndroid Build Coastguard Worker 
520*49cdfc7eSAndroid Build Coastguard Worker 	c = 0;			/* in this loop, c is the command index */
521*49cdfc7eSAndroid Build Coastguard Worker 	stop = 0;
522*49cdfc7eSAndroid Build Coastguard Worker 	exit_stat = 0;
523*49cdfc7eSAndroid Build Coastguard Worker 	go_idle = 0;
524*49cdfc7eSAndroid Build Coastguard Worker 	while (1) {
525*49cdfc7eSAndroid Build Coastguard Worker 
526*49cdfc7eSAndroid Build Coastguard Worker 		while ((num_active < keep_active) && (starts != 0)) {
527*49cdfc7eSAndroid Build Coastguard Worker 			if (stop || rec_signal || go_idle)
528*49cdfc7eSAndroid Build Coastguard Worker 				break;
529*49cdfc7eSAndroid Build Coastguard Worker 
530*49cdfc7eSAndroid Build Coastguard Worker 			if (!sequential)
531*49cdfc7eSAndroid Build Coastguard Worker 				c = lrand48() % coll->cnt;
532*49cdfc7eSAndroid Build Coastguard Worker 
533*49cdfc7eSAndroid Build Coastguard Worker 			/* find a slot for the child */
534*49cdfc7eSAndroid Build Coastguard Worker 			for (i = 0; i < keep_active; ++i) {
535*49cdfc7eSAndroid Build Coastguard Worker 				if (running[i].pgrp == 0)
536*49cdfc7eSAndroid Build Coastguard Worker 					break;
537*49cdfc7eSAndroid Build Coastguard Worker 			}
538*49cdfc7eSAndroid Build Coastguard Worker 			if (i == keep_active) {
539*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
540*49cdfc7eSAndroid Build Coastguard Worker 					"pan(%s): Aborting: i == keep_active = %d\n",
541*49cdfc7eSAndroid Build Coastguard Worker 					panname, i);
542*49cdfc7eSAndroid Build Coastguard Worker 				wait_handler(SIGINT);
543*49cdfc7eSAndroid Build Coastguard Worker 				exit_stat++;
544*49cdfc7eSAndroid Build Coastguard Worker 				break;
545*49cdfc7eSAndroid Build Coastguard Worker 			}
546*49cdfc7eSAndroid Build Coastguard Worker 
547*49cdfc7eSAndroid Build Coastguard Worker 			cpid =
548*49cdfc7eSAndroid Build Coastguard Worker 			    run_child(coll->ary[c], running + i, quiet_mode,
549*49cdfc7eSAndroid Build Coastguard Worker 				      &failcnt, fmt_print, logfile, no_kmsg);
550*49cdfc7eSAndroid Build Coastguard Worker 			if (cpid != -1)
551*49cdfc7eSAndroid Build Coastguard Worker 				++num_active;
552*49cdfc7eSAndroid Build Coastguard Worker 			if ((cpid != -1 || sequential) && starts > 0)
553*49cdfc7eSAndroid Build Coastguard Worker 				--starts;
554*49cdfc7eSAndroid Build Coastguard Worker 
555*49cdfc7eSAndroid Build Coastguard Worker 			if (sequential)
556*49cdfc7eSAndroid Build Coastguard Worker 				if (++c >= coll->cnt)
557*49cdfc7eSAndroid Build Coastguard Worker 					c = 0;
558*49cdfc7eSAndroid Build Coastguard Worker 
559*49cdfc7eSAndroid Build Coastguard Worker 		}		/* while ((num_active < keep_active) && (starts != 0)) */
560*49cdfc7eSAndroid Build Coastguard Worker 
561*49cdfc7eSAndroid Build Coastguard Worker 		if (starts == 0) {
562*49cdfc7eSAndroid Build Coastguard Worker 			if (!quiet_mode)
563*49cdfc7eSAndroid Build Coastguard Worker 				printf("incrementing stop\n");
564*49cdfc7eSAndroid Build Coastguard Worker 			++stop;
565*49cdfc7eSAndroid Build Coastguard Worker 		} else if (starts == -1)	//wjh
566*49cdfc7eSAndroid Build Coastguard Worker 		{
567*49cdfc7eSAndroid Build Coastguard Worker 			FILE *f = (FILE *) - 1;
568*49cdfc7eSAndroid Build Coastguard Worker 			if ((f = fopen(PAN_STOP_FILE, "r")) != 0) {
569*49cdfc7eSAndroid Build Coastguard Worker 				printf("Got %s Stopping!\n", PAN_STOP_FILE);
570*49cdfc7eSAndroid Build Coastguard Worker 				fclose(f);
571*49cdfc7eSAndroid Build Coastguard Worker 				unlink(PAN_STOP_FILE);
572*49cdfc7eSAndroid Build Coastguard Worker 				stop++;
573*49cdfc7eSAndroid Build Coastguard Worker 			}
574*49cdfc7eSAndroid Build Coastguard Worker 		}
575*49cdfc7eSAndroid Build Coastguard Worker 
576*49cdfc7eSAndroid Build Coastguard Worker 		if (rec_signal) {
577*49cdfc7eSAndroid Build Coastguard Worker 			/* propagate everything except sigusr2 */
578*49cdfc7eSAndroid Build Coastguard Worker 
579*49cdfc7eSAndroid Build Coastguard Worker 			if (rec_signal == SIGUSR2) {
580*49cdfc7eSAndroid Build Coastguard Worker 				if (fork_in_road)
581*49cdfc7eSAndroid Build Coastguard Worker 					++go_idle;
582*49cdfc7eSAndroid Build Coastguard Worker 				else
583*49cdfc7eSAndroid Build Coastguard Worker 					++stop;
584*49cdfc7eSAndroid Build Coastguard Worker 				rec_signal = send_signal = 0;
585*49cdfc7eSAndroid Build Coastguard Worker 			} else {
586*49cdfc7eSAndroid Build Coastguard Worker 				if (rec_signal == SIGUSR1)
587*49cdfc7eSAndroid Build Coastguard Worker 					fork_in_road = 0;
588*49cdfc7eSAndroid Build Coastguard Worker 				propagate_signal(running, keep_active, orphans);
589*49cdfc7eSAndroid Build Coastguard Worker 				if (fork_in_road)
590*49cdfc7eSAndroid Build Coastguard Worker 					++go_idle;
591*49cdfc7eSAndroid Build Coastguard Worker 				else
592*49cdfc7eSAndroid Build Coastguard Worker 					++stop;
593*49cdfc7eSAndroid Build Coastguard Worker 			}
594*49cdfc7eSAndroid Build Coastguard Worker 		}
595*49cdfc7eSAndroid Build Coastguard Worker 
596*49cdfc7eSAndroid Build Coastguard Worker 		err = check_pids(running, &num_active, keep_active, logfile,
597*49cdfc7eSAndroid Build Coastguard Worker 				 failcmdfile, tconfcmdfile, orphans, fmt_print,
598*49cdfc7eSAndroid Build Coastguard Worker 				 &failcnt, &tconfcnt, quiet_mode, no_kmsg);
599*49cdfc7eSAndroid Build Coastguard Worker 		if (Debug & Drunning) {
600*49cdfc7eSAndroid Build Coastguard Worker 			pids_running(running, keep_active);
601*49cdfc7eSAndroid Build Coastguard Worker 			orphans_running(orphans);
602*49cdfc7eSAndroid Build Coastguard Worker 		}
603*49cdfc7eSAndroid Build Coastguard Worker 		if (err) {
604*49cdfc7eSAndroid Build Coastguard Worker 			if (fork_in_road)
605*49cdfc7eSAndroid Build Coastguard Worker 				++go_idle;
606*49cdfc7eSAndroid Build Coastguard Worker 			if (track_exit_stats)
607*49cdfc7eSAndroid Build Coastguard Worker 				exit_stat++;
608*49cdfc7eSAndroid Build Coastguard Worker 			if (has_brakes) {
609*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "pan(%s): All stop!%s\n",
610*49cdfc7eSAndroid Build Coastguard Worker 					panname, go_idle ? " (idling)" : "");
611*49cdfc7eSAndroid Build Coastguard Worker 				wait_handler(SIGINT);
612*49cdfc7eSAndroid Build Coastguard Worker 			}
613*49cdfc7eSAndroid Build Coastguard Worker 		}
614*49cdfc7eSAndroid Build Coastguard Worker 
615*49cdfc7eSAndroid Build Coastguard Worker 		if (stop && (num_active == 0))
616*49cdfc7eSAndroid Build Coastguard Worker 			break;
617*49cdfc7eSAndroid Build Coastguard Worker 
618*49cdfc7eSAndroid Build Coastguard Worker 		if (go_idle && (num_active == 0)) {
619*49cdfc7eSAndroid Build Coastguard Worker 			go_idle = 0;	/* It is idle, now resume scheduling. */
620*49cdfc7eSAndroid Build Coastguard Worker 			wait_handler(0);	/* Reset the signal ratchet. */
621*49cdfc7eSAndroid Build Coastguard Worker 		}
622*49cdfc7eSAndroid Build Coastguard Worker 	}
623*49cdfc7eSAndroid Build Coastguard Worker 
624*49cdfc7eSAndroid Build Coastguard Worker 	/* Wait for orphaned pgrps */
625*49cdfc7eSAndroid Build Coastguard Worker 	while (1) {
626*49cdfc7eSAndroid Build Coastguard Worker 		for (orph = orphans; orph != NULL; orph = orph->next) {
627*49cdfc7eSAndroid Build Coastguard Worker 			if (orph->pgrp == 0)
628*49cdfc7eSAndroid Build Coastguard Worker 				continue;
629*49cdfc7eSAndroid Build Coastguard Worker 			/* Yes, we have orphaned pgrps */
630*49cdfc7eSAndroid Build Coastguard Worker 			sleep(5);
631*49cdfc7eSAndroid Build Coastguard Worker 			if (!rec_signal) {
632*49cdfc7eSAndroid Build Coastguard Worker 				/* force an artificial signal, move us
633*49cdfc7eSAndroid Build Coastguard Worker 				 * through the signal ratchet.
634*49cdfc7eSAndroid Build Coastguard Worker 				 */
635*49cdfc7eSAndroid Build Coastguard Worker 				wait_handler(SIGINT);
636*49cdfc7eSAndroid Build Coastguard Worker 			}
637*49cdfc7eSAndroid Build Coastguard Worker 			propagate_signal(running, keep_active, orphans);
638*49cdfc7eSAndroid Build Coastguard Worker 			if (Debug & Drunning)
639*49cdfc7eSAndroid Build Coastguard Worker 				orphans_running(orphans);
640*49cdfc7eSAndroid Build Coastguard Worker 			break;
641*49cdfc7eSAndroid Build Coastguard Worker 		}
642*49cdfc7eSAndroid Build Coastguard Worker 		if (orph == NULL)
643*49cdfc7eSAndroid Build Coastguard Worker 			break;
644*49cdfc7eSAndroid Build Coastguard Worker 	}
645*49cdfc7eSAndroid Build Coastguard Worker 
646*49cdfc7eSAndroid Build Coastguard Worker 	if (zoo_clear(zoofile, getpid())) {
647*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
648*49cdfc7eSAndroid Build Coastguard Worker 		++exit_stat;
649*49cdfc7eSAndroid Build Coastguard Worker 	}
650*49cdfc7eSAndroid Build Coastguard Worker 	fclose(zoofile);
651*49cdfc7eSAndroid Build Coastguard Worker 	if (logfile && fmt_print) {
652*49cdfc7eSAndroid Build Coastguard Worker 		if (uname(&unamebuf) == -1)
653*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "ERROR: uname(): %s\n",
654*49cdfc7eSAndroid Build Coastguard Worker 				strerror(errno));
655*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile,
656*49cdfc7eSAndroid Build Coastguard Worker 			"\n-----------------------------------------------\n");
657*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile, "Total Tests: %d\n", coll->cnt);
658*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile, "Total Skipped Tests: %d\n", tconfcnt);
659*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile, "Total Failures: %d\n", failcnt);
660*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile, "Kernel Version: %s\n", unamebuf.release);
661*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile, "Machine Architecture: %s\n",
662*49cdfc7eSAndroid Build Coastguard Worker 			unamebuf.machine);
663*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(logfile, "Hostname: %s\n\n", unamebuf.nodename);
664*49cdfc7eSAndroid Build Coastguard Worker 	}
665*49cdfc7eSAndroid Build Coastguard Worker 	if (logfile && (logfile != stdout))
666*49cdfc7eSAndroid Build Coastguard Worker 		fclose(logfile);
667*49cdfc7eSAndroid Build Coastguard Worker 
668*49cdfc7eSAndroid Build Coastguard Worker 	if (failcmdfile)
669*49cdfc7eSAndroid Build Coastguard Worker 		fclose(failcmdfile);
670*49cdfc7eSAndroid Build Coastguard Worker 
671*49cdfc7eSAndroid Build Coastguard Worker 	if (tconfcmdfile)
672*49cdfc7eSAndroid Build Coastguard Worker 		fclose(tconfcmdfile);
673*49cdfc7eSAndroid Build Coastguard Worker 	exit(exit_stat);
674*49cdfc7eSAndroid Build Coastguard Worker }
675*49cdfc7eSAndroid Build Coastguard Worker 
676*49cdfc7eSAndroid Build Coastguard Worker static void
propagate_signal(struct tag_pgrp * running,int keep_active,struct orphan_pgrp * orphans)677*49cdfc7eSAndroid Build Coastguard Worker propagate_signal(struct tag_pgrp *running, int keep_active,
678*49cdfc7eSAndroid Build Coastguard Worker 		 struct orphan_pgrp *orphans)
679*49cdfc7eSAndroid Build Coastguard Worker {
680*49cdfc7eSAndroid Build Coastguard Worker 	int i;
681*49cdfc7eSAndroid Build Coastguard Worker 
682*49cdfc7eSAndroid Build Coastguard Worker 	if (Debug & Dshutdown)
683*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan was signaled with sig %d...\n",
684*49cdfc7eSAndroid Build Coastguard Worker 			rec_signal);
685*49cdfc7eSAndroid Build Coastguard Worker 
686*49cdfc7eSAndroid Build Coastguard Worker 	if (rec_signal == SIGALRM) {
687*49cdfc7eSAndroid Build Coastguard Worker 		printf("PAN stop Alarm was received\n");
688*49cdfc7eSAndroid Build Coastguard Worker 		rec_signal = SIGTERM;
689*49cdfc7eSAndroid Build Coastguard Worker 	}
690*49cdfc7eSAndroid Build Coastguard Worker 
691*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < keep_active; ++i) {
692*49cdfc7eSAndroid Build Coastguard Worker 		if (running[i].pgrp == 0)
693*49cdfc7eSAndroid Build Coastguard Worker 			continue;
694*49cdfc7eSAndroid Build Coastguard Worker 
695*49cdfc7eSAndroid Build Coastguard Worker 		if (Debug & Dshutdown)
696*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "  propagating sig %d to %d\n",
697*49cdfc7eSAndroid Build Coastguard Worker 				send_signal, -running[i].pgrp);
698*49cdfc7eSAndroid Build Coastguard Worker 		if (kill(-running[i].pgrp, send_signal) != 0) {
699*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
700*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): kill(%d,%d) failed on tag (%s).  errno:%d  %s\n",
701*49cdfc7eSAndroid Build Coastguard Worker 				panname, -running[i].pgrp, send_signal,
702*49cdfc7eSAndroid Build Coastguard Worker 				running[i].cmd->name, errno, strerror(errno));
703*49cdfc7eSAndroid Build Coastguard Worker 		}
704*49cdfc7eSAndroid Build Coastguard Worker 		running[i].stopping = 1;
705*49cdfc7eSAndroid Build Coastguard Worker 	}
706*49cdfc7eSAndroid Build Coastguard Worker 
707*49cdfc7eSAndroid Build Coastguard Worker 	check_orphans(orphans, send_signal);
708*49cdfc7eSAndroid Build Coastguard Worker 
709*49cdfc7eSAndroid Build Coastguard Worker 	rec_signal = send_signal = 0;
710*49cdfc7eSAndroid Build Coastguard Worker }
711*49cdfc7eSAndroid Build Coastguard Worker 
712*49cdfc7eSAndroid Build Coastguard Worker static int
check_pids(struct tag_pgrp * running,int * num_active,int keep_active,FILE * logfile,FILE * failcmdfile,FILE * tconfcmdfile,struct orphan_pgrp * orphans,int fmt_print,int * failcnt,int * tconfcnt,int quiet_mode,int no_kmsg)713*49cdfc7eSAndroid Build Coastguard Worker check_pids(struct tag_pgrp *running, int *num_active, int keep_active,
714*49cdfc7eSAndroid Build Coastguard Worker 	   FILE *logfile, FILE *failcmdfile, FILE *tconfcmdfile,
715*49cdfc7eSAndroid Build Coastguard Worker 	   struct orphan_pgrp *orphans, int fmt_print, int *failcnt,
716*49cdfc7eSAndroid Build Coastguard Worker 	   int *tconfcnt, int quiet_mode, int no_kmsg)
717*49cdfc7eSAndroid Build Coastguard Worker {
718*49cdfc7eSAndroid Build Coastguard Worker 	int w;
719*49cdfc7eSAndroid Build Coastguard Worker 	pid_t cpid;
720*49cdfc7eSAndroid Build Coastguard Worker 	int stat_loc;
721*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
722*49cdfc7eSAndroid Build Coastguard Worker 	int i;
723*49cdfc7eSAndroid Build Coastguard Worker 	time_t t;
724*49cdfc7eSAndroid Build Coastguard Worker 	char *status;
725*49cdfc7eSAndroid Build Coastguard Worker 	char *result_str;
726*49cdfc7eSAndroid Build Coastguard Worker 	int signaled = 0;
727*49cdfc7eSAndroid Build Coastguard Worker 	struct tms tms1, tms2;
728*49cdfc7eSAndroid Build Coastguard Worker 	clock_t tck;
729*49cdfc7eSAndroid Build Coastguard Worker 
730*49cdfc7eSAndroid Build Coastguard Worker 	check_orphans(orphans, 0);
731*49cdfc7eSAndroid Build Coastguard Worker 
732*49cdfc7eSAndroid Build Coastguard Worker 	tck = times(&tms1);
733*49cdfc7eSAndroid Build Coastguard Worker 	if (tck == -1) {
734*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): times(&tms1) failed.  errno:%d  %s\n",
735*49cdfc7eSAndroid Build Coastguard Worker 			panname, errno, strerror(errno));
736*49cdfc7eSAndroid Build Coastguard Worker 	}
737*49cdfc7eSAndroid Build Coastguard Worker 	cpid = wait(&stat_loc);
738*49cdfc7eSAndroid Build Coastguard Worker 	tck = times(&tms2);
739*49cdfc7eSAndroid Build Coastguard Worker 	if (tck == -1) {
740*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): times(&tms2) failed.  errno:%d  %s\n",
741*49cdfc7eSAndroid Build Coastguard Worker 			panname, errno, strerror(errno));
742*49cdfc7eSAndroid Build Coastguard Worker 	}
743*49cdfc7eSAndroid Build Coastguard Worker 
744*49cdfc7eSAndroid Build Coastguard Worker 	if (cpid < 0) {
745*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == EINTR) {
746*49cdfc7eSAndroid Build Coastguard Worker 			if (Debug)
747*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "pan(%s): wait() interrupted\n",
748*49cdfc7eSAndroid Build Coastguard Worker 					panname);
749*49cdfc7eSAndroid Build Coastguard Worker 		} else if (errno != ECHILD) {
750*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
751*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): wait() failed.  errno:%d  %s\n",
752*49cdfc7eSAndroid Build Coastguard Worker 				panname, errno, strerror(errno));
753*49cdfc7eSAndroid Build Coastguard Worker 		}
754*49cdfc7eSAndroid Build Coastguard Worker 	} else if (cpid > 0) {
755*49cdfc7eSAndroid Build Coastguard Worker 
756*49cdfc7eSAndroid Build Coastguard Worker 		if (WIFSIGNALED(stat_loc)) {
757*49cdfc7eSAndroid Build Coastguard Worker 			w = WTERMSIG(stat_loc);
758*49cdfc7eSAndroid Build Coastguard Worker 			status = "signaled";
759*49cdfc7eSAndroid Build Coastguard Worker 			if (Debug & Dexit)
760*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
761*49cdfc7eSAndroid Build Coastguard Worker 					"child %d terminated with signal %d\n",
762*49cdfc7eSAndroid Build Coastguard Worker 					cpid, w);
763*49cdfc7eSAndroid Build Coastguard Worker 			--*num_active;
764*49cdfc7eSAndroid Build Coastguard Worker 			signaled = 1;
765*49cdfc7eSAndroid Build Coastguard Worker 		} else if (WIFEXITED(stat_loc)) {
766*49cdfc7eSAndroid Build Coastguard Worker 			w = WEXITSTATUS(stat_loc);
767*49cdfc7eSAndroid Build Coastguard Worker 			status = "exited";
768*49cdfc7eSAndroid Build Coastguard Worker 			if (Debug & Dexit)
769*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
770*49cdfc7eSAndroid Build Coastguard Worker 					"child %d exited with status %d\n",
771*49cdfc7eSAndroid Build Coastguard Worker 					cpid, w);
772*49cdfc7eSAndroid Build Coastguard Worker 			--*num_active;
773*49cdfc7eSAndroid Build Coastguard Worker 			if (w != 0 && w != TCONF)
774*49cdfc7eSAndroid Build Coastguard Worker 				ret++;
775*49cdfc7eSAndroid Build Coastguard Worker 		} else if (WIFSTOPPED(stat_loc)) {	/* should never happen */
776*49cdfc7eSAndroid Build Coastguard Worker 			w = WSTOPSIG(stat_loc);
777*49cdfc7eSAndroid Build Coastguard Worker 			status = "stopped";
778*49cdfc7eSAndroid Build Coastguard Worker 			ret++;
779*49cdfc7eSAndroid Build Coastguard Worker 		} else {	/* should never happen */
780*49cdfc7eSAndroid Build Coastguard Worker 			w = 0;
781*49cdfc7eSAndroid Build Coastguard Worker 			status = "unknown";
782*49cdfc7eSAndroid Build Coastguard Worker 			ret++;
783*49cdfc7eSAndroid Build Coastguard Worker 		}
784*49cdfc7eSAndroid Build Coastguard Worker 
785*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < keep_active; ++i) {
786*49cdfc7eSAndroid Build Coastguard Worker 			if (running[i].pgrp == cpid) {
787*49cdfc7eSAndroid Build Coastguard Worker 				if ((w == 130) && running[i].stopping &&
788*49cdfc7eSAndroid Build Coastguard Worker 				    (strcmp(status, "exited") == 0)) {
789*49cdfc7eSAndroid Build Coastguard Worker 					/* The child received sigint, but
790*49cdfc7eSAndroid Build Coastguard Worker 					 * did not trap for it?  Compensate
791*49cdfc7eSAndroid Build Coastguard Worker 					 * for it here.
792*49cdfc7eSAndroid Build Coastguard Worker 					 */
793*49cdfc7eSAndroid Build Coastguard Worker 					w = 0;
794*49cdfc7eSAndroid Build Coastguard Worker 					ret--;	/* undo */
795*49cdfc7eSAndroid Build Coastguard Worker 					if (Debug & Drunning)
796*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(stderr,
797*49cdfc7eSAndroid Build Coastguard Worker 							"pan(%s): tag=%s exited 130, known to be signaled; will give it an exit 0.\n",
798*49cdfc7eSAndroid Build Coastguard Worker 							panname,
799*49cdfc7eSAndroid Build Coastguard Worker 							running[i].cmd->name);
800*49cdfc7eSAndroid Build Coastguard Worker 				}
801*49cdfc7eSAndroid Build Coastguard Worker 				time(&t);
802*49cdfc7eSAndroid Build Coastguard Worker 				if (logfile != NULL) {
803*49cdfc7eSAndroid Build Coastguard Worker 					if (!fmt_print)
804*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(logfile,
805*49cdfc7eSAndroid Build Coastguard Worker 							"tag=%s stime=%d dur=%d exit=%s stat=%d core=%s cu=%d cs=%d\n",
806*49cdfc7eSAndroid Build Coastguard Worker 							running[i].cmd->name,
807*49cdfc7eSAndroid Build Coastguard Worker 							(int)(running[i].
808*49cdfc7eSAndroid Build Coastguard Worker 							      mystime),
809*49cdfc7eSAndroid Build Coastguard Worker 							(int)(t -
810*49cdfc7eSAndroid Build Coastguard Worker 							      running[i].
811*49cdfc7eSAndroid Build Coastguard Worker 							      mystime), status,
812*49cdfc7eSAndroid Build Coastguard Worker 							w,
813*49cdfc7eSAndroid Build Coastguard Worker 							(stat_loc & 0200) ?
814*49cdfc7eSAndroid Build Coastguard Worker 							"yes" : "no",
815*49cdfc7eSAndroid Build Coastguard Worker 							(int)(tms2.tms_cutime -
816*49cdfc7eSAndroid Build Coastguard Worker 							      tms1.tms_cutime),
817*49cdfc7eSAndroid Build Coastguard Worker 							(int)(tms2.tms_cstime -
818*49cdfc7eSAndroid Build Coastguard Worker 							      tms1.tms_cstime));
819*49cdfc7eSAndroid Build Coastguard Worker 					else {
820*49cdfc7eSAndroid Build Coastguard Worker 						if (strcmp(status, "exited") ==
821*49cdfc7eSAndroid Build Coastguard Worker 						    0 && w == TCONF) {
822*49cdfc7eSAndroid Build Coastguard Worker 							++*tconfcnt;
823*49cdfc7eSAndroid Build Coastguard Worker 							result_str = "CONF";
824*49cdfc7eSAndroid Build Coastguard Worker 						} else if (w != 0) {
825*49cdfc7eSAndroid Build Coastguard Worker 							++*failcnt;
826*49cdfc7eSAndroid Build Coastguard Worker 							result_str = "FAIL";
827*49cdfc7eSAndroid Build Coastguard Worker 						} else {
828*49cdfc7eSAndroid Build Coastguard Worker 							result_str = "PASS";
829*49cdfc7eSAndroid Build Coastguard Worker 						}
830*49cdfc7eSAndroid Build Coastguard Worker 
831*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(logfile,
832*49cdfc7eSAndroid Build Coastguard Worker 							ResultFmt" %-5d\n",
833*49cdfc7eSAndroid Build Coastguard Worker 							running[i].cmd->name,
834*49cdfc7eSAndroid Build Coastguard Worker 							result_str,
835*49cdfc7eSAndroid Build Coastguard Worker 							w);
836*49cdfc7eSAndroid Build Coastguard Worker 					}
837*49cdfc7eSAndroid Build Coastguard Worker 
838*49cdfc7eSAndroid Build Coastguard Worker 					fflush(logfile);
839*49cdfc7eSAndroid Build Coastguard Worker 				}
840*49cdfc7eSAndroid Build Coastguard Worker 
841*49cdfc7eSAndroid Build Coastguard Worker 				if (w != 0) {
842*49cdfc7eSAndroid Build Coastguard Worker 					if (tconfcmdfile != NULL &&
843*49cdfc7eSAndroid Build Coastguard Worker 					    w == TCONF) {
844*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(tconfcmdfile, "%s %s\n",
845*49cdfc7eSAndroid Build Coastguard Worker 						running[i].cmd->name,
846*49cdfc7eSAndroid Build Coastguard Worker 						running[i].cmd->cmdline);
847*49cdfc7eSAndroid Build Coastguard Worker 					} else if (failcmdfile != NULL) {
848*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(failcmdfile, "%s %s\n",
849*49cdfc7eSAndroid Build Coastguard Worker 						running[i].cmd->name,
850*49cdfc7eSAndroid Build Coastguard Worker 						running[i].cmd->cmdline);
851*49cdfc7eSAndroid Build Coastguard Worker 					}
852*49cdfc7eSAndroid Build Coastguard Worker 				}
853*49cdfc7eSAndroid Build Coastguard Worker 
854*49cdfc7eSAndroid Build Coastguard Worker 				if (running[i].stopping)
855*49cdfc7eSAndroid Build Coastguard Worker 					status = "driver_interrupt";
856*49cdfc7eSAndroid Build Coastguard Worker 
857*49cdfc7eSAndroid Build Coastguard Worker 				if (test_out_dir) {
858*49cdfc7eSAndroid Build Coastguard Worker 					if (!quiet_mode)
859*49cdfc7eSAndroid Build Coastguard Worker 						write_test_start(running + i, no_kmsg);
860*49cdfc7eSAndroid Build Coastguard Worker 					copy_buffered_output(running + i);
861*49cdfc7eSAndroid Build Coastguard Worker 					unlink(running[i].output);
862*49cdfc7eSAndroid Build Coastguard Worker 				}
863*49cdfc7eSAndroid Build Coastguard Worker 				if (!quiet_mode)
864*49cdfc7eSAndroid Build Coastguard Worker 					write_test_end(running + i, "ok", t,
865*49cdfc7eSAndroid Build Coastguard Worker 						       status, stat_loc, w,
866*49cdfc7eSAndroid Build Coastguard Worker 						       &tms1, &tms2);
867*49cdfc7eSAndroid Build Coastguard Worker 
868*49cdfc7eSAndroid Build Coastguard Worker 				/* If signaled and we weren't expecting
869*49cdfc7eSAndroid Build Coastguard Worker 				 * this to be stopped then the proc
870*49cdfc7eSAndroid Build Coastguard Worker 				 * had a problem.
871*49cdfc7eSAndroid Build Coastguard Worker 				 */
872*49cdfc7eSAndroid Build Coastguard Worker 				if (signaled && !running[i].stopping)
873*49cdfc7eSAndroid Build Coastguard Worker 					ret++;
874*49cdfc7eSAndroid Build Coastguard Worker 
875*49cdfc7eSAndroid Build Coastguard Worker 				running[i].pgrp = 0;
876*49cdfc7eSAndroid Build Coastguard Worker 				if (zoo_clear(zoofile, cpid)) {
877*49cdfc7eSAndroid Build Coastguard Worker 					fprintf(stderr, "pan(%s): %s\n",
878*49cdfc7eSAndroid Build Coastguard Worker 						panname, zoo_error);
879*49cdfc7eSAndroid Build Coastguard Worker 					exit(1);
880*49cdfc7eSAndroid Build Coastguard Worker 				}
881*49cdfc7eSAndroid Build Coastguard Worker 
882*49cdfc7eSAndroid Build Coastguard Worker 				/* Check for orphaned pgrps */
883*49cdfc7eSAndroid Build Coastguard Worker 				if ((kill(-cpid, 0) == 0) || (errno == EPERM)) {
884*49cdfc7eSAndroid Build Coastguard Worker 					if (zoo_mark_cmdline
885*49cdfc7eSAndroid Build Coastguard Worker 					    (zoofile, cpid, "panorphan",
886*49cdfc7eSAndroid Build Coastguard Worker 					     running[i].cmd->cmdline)) {
887*49cdfc7eSAndroid Build Coastguard Worker 						fprintf(stderr, "pan(%s): %s\n",
888*49cdfc7eSAndroid Build Coastguard Worker 							panname, zoo_error);
889*49cdfc7eSAndroid Build Coastguard Worker 						exit(1);
890*49cdfc7eSAndroid Build Coastguard Worker 					}
891*49cdfc7eSAndroid Build Coastguard Worker 					mark_orphan(orphans, cpid);
892*49cdfc7eSAndroid Build Coastguard Worker 					/* status of kill doesn't matter */
893*49cdfc7eSAndroid Build Coastguard Worker 					kill(-cpid, SIGTERM);
894*49cdfc7eSAndroid Build Coastguard Worker 				}
895*49cdfc7eSAndroid Build Coastguard Worker 
896*49cdfc7eSAndroid Build Coastguard Worker 				break;
897*49cdfc7eSAndroid Build Coastguard Worker 			}
898*49cdfc7eSAndroid Build Coastguard Worker 		}
899*49cdfc7eSAndroid Build Coastguard Worker 	}
900*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
901*49cdfc7eSAndroid Build Coastguard Worker }
902*49cdfc7eSAndroid Build Coastguard Worker 
903*49cdfc7eSAndroid Build Coastguard Worker static pid_t
run_child(struct coll_entry * colle,struct tag_pgrp * active,int quiet_mode,int * failcnt,int fmt_print,FILE * logfile,int no_kmsg)904*49cdfc7eSAndroid Build Coastguard Worker run_child(struct coll_entry *colle, struct tag_pgrp *active, int quiet_mode,
905*49cdfc7eSAndroid Build Coastguard Worker 	  int *failcnt, int fmt_print, FILE * logfile, int no_kmsg)
906*49cdfc7eSAndroid Build Coastguard Worker {
907*49cdfc7eSAndroid Build Coastguard Worker 	ssize_t errlen;
908*49cdfc7eSAndroid Build Coastguard Worker 	int cpid;
909*49cdfc7eSAndroid Build Coastguard Worker 	int c_stdout = -1;	/* child's stdout, stderr */
910*49cdfc7eSAndroid Build Coastguard Worker 	int capturing = 0;	/* output is going to a file instead of stdout */
911*49cdfc7eSAndroid Build Coastguard Worker 	char *c_cmdline;
912*49cdfc7eSAndroid Build Coastguard Worker 	static long cmdno = 0;
913*49cdfc7eSAndroid Build Coastguard Worker 	int errpipe[2];		/* way to communicate to parent that the tag  */
914*49cdfc7eSAndroid Build Coastguard Worker 	char errbuf[1024];	/* didn't actually start */
915*49cdfc7eSAndroid Build Coastguard Worker 
916*49cdfc7eSAndroid Build Coastguard Worker 	/* Try to open the file that will be stdout for the test */
917*49cdfc7eSAndroid Build Coastguard Worker 	if (test_out_dir) {
918*49cdfc7eSAndroid Build Coastguard Worker 		capturing = 1;
919*49cdfc7eSAndroid Build Coastguard Worker 		do {
920*49cdfc7eSAndroid Build Coastguard Worker 			sprintf(active->output, "%s/%s.%ld",
921*49cdfc7eSAndroid Build Coastguard Worker 				test_out_dir, colle->name, cmdno++);
922*49cdfc7eSAndroid Build Coastguard Worker 			c_stdout =
923*49cdfc7eSAndroid Build Coastguard Worker 			    open(active->output,
924*49cdfc7eSAndroid Build Coastguard Worker 				 O_CREAT | O_RDWR | O_EXCL | O_SYNC, 0666);
925*49cdfc7eSAndroid Build Coastguard Worker 		} while (c_stdout < 0 && errno == EEXIST);
926*49cdfc7eSAndroid Build Coastguard Worker 		if (c_stdout < 0) {
927*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
928*49cdfc7eSAndroid Build Coastguard Worker 				"pan(%s): open of stdout file failed (tag %s).  errno: %d  %s\n  file: %s\n",
929*49cdfc7eSAndroid Build Coastguard Worker 				panname, colle->name, errno, strerror(errno),
930*49cdfc7eSAndroid Build Coastguard Worker 				active->output);
931*49cdfc7eSAndroid Build Coastguard Worker 			return -1;
932*49cdfc7eSAndroid Build Coastguard Worker 		}
933*49cdfc7eSAndroid Build Coastguard Worker 	}
934*49cdfc7eSAndroid Build Coastguard Worker 
935*49cdfc7eSAndroid Build Coastguard Worker 	/* get the tag's command line arguments ready.  subst_pcnt_f() uses a
936*49cdfc7eSAndroid Build Coastguard Worker 	 * static counter, that's why we do it here instead of after we fork.
937*49cdfc7eSAndroid Build Coastguard Worker 	 */
938*49cdfc7eSAndroid Build Coastguard Worker 	if (colle->pcnt_f) {
939*49cdfc7eSAndroid Build Coastguard Worker 		c_cmdline = subst_pcnt_f(colle);
940*49cdfc7eSAndroid Build Coastguard Worker 	} else {
941*49cdfc7eSAndroid Build Coastguard Worker 		c_cmdline = colle->cmdline;
942*49cdfc7eSAndroid Build Coastguard Worker 	}
943*49cdfc7eSAndroid Build Coastguard Worker 
944*49cdfc7eSAndroid Build Coastguard Worker 	if (pipe(errpipe) < 0) {
945*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): pipe() failed. errno:%d %s\n",
946*49cdfc7eSAndroid Build Coastguard Worker 			panname, errno, strerror(errno));
947*49cdfc7eSAndroid Build Coastguard Worker 		if (capturing) {
948*49cdfc7eSAndroid Build Coastguard Worker 			close(c_stdout);
949*49cdfc7eSAndroid Build Coastguard Worker 			unlink(active->output);
950*49cdfc7eSAndroid Build Coastguard Worker 		}
951*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
952*49cdfc7eSAndroid Build Coastguard Worker 	}
953*49cdfc7eSAndroid Build Coastguard Worker 
954*49cdfc7eSAndroid Build Coastguard Worker 	time(&active->mystime);
955*49cdfc7eSAndroid Build Coastguard Worker 	active->cmd = colle;
956*49cdfc7eSAndroid Build Coastguard Worker 
957*49cdfc7eSAndroid Build Coastguard Worker 	if (!test_out_dir && !quiet_mode)
958*49cdfc7eSAndroid Build Coastguard Worker 		write_test_start(active, no_kmsg);
959*49cdfc7eSAndroid Build Coastguard Worker 
960*49cdfc7eSAndroid Build Coastguard Worker 	fflush(NULL);
961*49cdfc7eSAndroid Build Coastguard Worker 
962*49cdfc7eSAndroid Build Coastguard Worker 	if ((cpid = fork()) == -1) {
963*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr,
964*49cdfc7eSAndroid Build Coastguard Worker 			"pan(%s): fork failed (tag %s).  errno:%d  %s\n",
965*49cdfc7eSAndroid Build Coastguard Worker 			panname, colle->name, errno, strerror(errno));
966*49cdfc7eSAndroid Build Coastguard Worker 		if (capturing) {
967*49cdfc7eSAndroid Build Coastguard Worker 			unlink(active->output);
968*49cdfc7eSAndroid Build Coastguard Worker 			close(c_stdout);
969*49cdfc7eSAndroid Build Coastguard Worker 		}
970*49cdfc7eSAndroid Build Coastguard Worker 		close(errpipe[0]);
971*49cdfc7eSAndroid Build Coastguard Worker 		close(errpipe[1]);
972*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
973*49cdfc7eSAndroid Build Coastguard Worker 	} else if (cpid == 0) {
974*49cdfc7eSAndroid Build Coastguard Worker 		/* child */
975*49cdfc7eSAndroid Build Coastguard Worker 
976*49cdfc7eSAndroid Build Coastguard Worker 		fclose(zoofile);
977*49cdfc7eSAndroid Build Coastguard Worker 		close(errpipe[0]);
978*49cdfc7eSAndroid Build Coastguard Worker 		fcntl(errpipe[1], F_SETFD, 1);	/* close the pipe if we succeed */
979*49cdfc7eSAndroid Build Coastguard Worker 		setpgrp();
980*49cdfc7eSAndroid Build Coastguard Worker 
981*49cdfc7eSAndroid Build Coastguard Worker 		umask(0);
982*49cdfc7eSAndroid Build Coastguard Worker 
983*49cdfc7eSAndroid Build Coastguard Worker #define WRITE_OR_DIE(fd, buf, buflen) do {				\
984*49cdfc7eSAndroid Build Coastguard Worker 	if (write((fd), (buf), (buflen)) != (buflen)) {			\
985*49cdfc7eSAndroid Build Coastguard Worker 		err(1, "failed to write out %zd bytes at line %d",	\
986*49cdfc7eSAndroid Build Coastguard Worker 		    buflen, __LINE__);					\
987*49cdfc7eSAndroid Build Coastguard Worker 	}								\
988*49cdfc7eSAndroid Build Coastguard Worker } while(0)
989*49cdfc7eSAndroid Build Coastguard Worker 
990*49cdfc7eSAndroid Build Coastguard Worker 		/* if we're putting output into a buffer file, we need to do the
991*49cdfc7eSAndroid Build Coastguard Worker 		 * redirection now.  If we fail
992*49cdfc7eSAndroid Build Coastguard Worker 		 */
993*49cdfc7eSAndroid Build Coastguard Worker 		if (capturing) {
994*49cdfc7eSAndroid Build Coastguard Worker 			if (dup2(c_stdout, fileno(stdout)) == -1) {
995*49cdfc7eSAndroid Build Coastguard Worker 				errlen =
996*49cdfc7eSAndroid Build Coastguard Worker 				    sprintf(errbuf,
997*49cdfc7eSAndroid Build Coastguard Worker 					    "pan(%s): couldn't redirect stdout for tag %s.  errno:%d  %s",
998*49cdfc7eSAndroid Build Coastguard Worker 					    panname, colle->name, errno,
999*49cdfc7eSAndroid Build Coastguard Worker 					    strerror(errno));
1000*49cdfc7eSAndroid Build Coastguard Worker 				WRITE_OR_DIE(errpipe[1], &errlen,
1001*49cdfc7eSAndroid Build Coastguard Worker 					     sizeof(errlen));
1002*49cdfc7eSAndroid Build Coastguard Worker 				WRITE_OR_DIE(errpipe[1], errbuf, errlen);
1003*49cdfc7eSAndroid Build Coastguard Worker 				exit(2);
1004*49cdfc7eSAndroid Build Coastguard Worker 			}
1005*49cdfc7eSAndroid Build Coastguard Worker 			if (dup2(c_stdout, fileno(stderr)) == -1) {
1006*49cdfc7eSAndroid Build Coastguard Worker 				errlen =
1007*49cdfc7eSAndroid Build Coastguard Worker 				    sprintf(errbuf,
1008*49cdfc7eSAndroid Build Coastguard Worker 					    "pan(%s): couldn't redirect stderr for tag %s.  errno:%d  %s",
1009*49cdfc7eSAndroid Build Coastguard Worker 					    panname, colle->name, errno,
1010*49cdfc7eSAndroid Build Coastguard Worker 					    strerror(errno));
1011*49cdfc7eSAndroid Build Coastguard Worker 				WRITE_OR_DIE(errpipe[1], &errlen,
1012*49cdfc7eSAndroid Build Coastguard Worker 					     sizeof(errlen));
1013*49cdfc7eSAndroid Build Coastguard Worker 				WRITE_OR_DIE(errpipe[1], errbuf, errlen);
1014*49cdfc7eSAndroid Build Coastguard Worker 				exit(2);
1015*49cdfc7eSAndroid Build Coastguard Worker 			}
1016*49cdfc7eSAndroid Build Coastguard Worker 		} else {	/* stderr still needs to be redirected */
1017*49cdfc7eSAndroid Build Coastguard Worker 			if (dup2(fileno(stdout), fileno(stderr)) == -1) {
1018*49cdfc7eSAndroid Build Coastguard Worker 				errlen =
1019*49cdfc7eSAndroid Build Coastguard Worker 				    sprintf(errbuf,
1020*49cdfc7eSAndroid Build Coastguard Worker 					    "pan(%s): couldn't redirect stderr for tag %s.  errno:%d  %s",
1021*49cdfc7eSAndroid Build Coastguard Worker 					    panname, colle->name, errno,
1022*49cdfc7eSAndroid Build Coastguard Worker 					    strerror(errno));
1023*49cdfc7eSAndroid Build Coastguard Worker 				WRITE_OR_DIE(errpipe[1], &errlen,
1024*49cdfc7eSAndroid Build Coastguard Worker 					     sizeof(errlen));
1025*49cdfc7eSAndroid Build Coastguard Worker 				WRITE_OR_DIE(errpipe[1], errbuf, errlen);
1026*49cdfc7eSAndroid Build Coastguard Worker 				exit(2);
1027*49cdfc7eSAndroid Build Coastguard Worker 			}
1028*49cdfc7eSAndroid Build Coastguard Worker 		}
1029*49cdfc7eSAndroid Build Coastguard Worker 		/* If there are any shell-type characters in the cmdline
1030*49cdfc7eSAndroid Build Coastguard Worker 		 * such as '>', '<', '$', '|', etc, then we exec a shell and
1031*49cdfc7eSAndroid Build Coastguard Worker 		 * run the cmd under a shell.
1032*49cdfc7eSAndroid Build Coastguard Worker 		 *
1033*49cdfc7eSAndroid Build Coastguard Worker 		 * Otherwise, break the cmdline at white space and exec the
1034*49cdfc7eSAndroid Build Coastguard Worker 		 * cmd directly.
1035*49cdfc7eSAndroid Build Coastguard Worker 		 */
1036*49cdfc7eSAndroid Build Coastguard Worker 		if (strpbrk(c_cmdline, "\"';|<>$\\")) {
1037*49cdfc7eSAndroid Build Coastguard Worker 			execlp("sh", "sh", "-c", c_cmdline, NULL);
1038*49cdfc7eSAndroid Build Coastguard Worker 			errlen = sprintf(errbuf,
1039*49cdfc7eSAndroid Build Coastguard Worker 					 "pan(%s): execlp of '%s' (tag %s) failed.  errno:%d %s",
1040*49cdfc7eSAndroid Build Coastguard Worker 					 panname, c_cmdline, colle->name, errno,
1041*49cdfc7eSAndroid Build Coastguard Worker 					 strerror(errno));
1042*49cdfc7eSAndroid Build Coastguard Worker 		} else {
1043*49cdfc7eSAndroid Build Coastguard Worker 			char **arg_v;
1044*49cdfc7eSAndroid Build Coastguard Worker 
1045*49cdfc7eSAndroid Build Coastguard Worker 			arg_v = (char **)splitstr(c_cmdline, NULL, NULL);
1046*49cdfc7eSAndroid Build Coastguard Worker 
1047*49cdfc7eSAndroid Build Coastguard Worker 			execvp(arg_v[0], arg_v);
1048*49cdfc7eSAndroid Build Coastguard Worker 			errlen = sprintf(errbuf,
1049*49cdfc7eSAndroid Build Coastguard Worker 					 "pan(%s): execvp of '%s' (tag %s) failed.  errno:%d  %s",
1050*49cdfc7eSAndroid Build Coastguard Worker 					 panname, arg_v[0], colle->name, errno,
1051*49cdfc7eSAndroid Build Coastguard Worker 					 strerror(errno));
1052*49cdfc7eSAndroid Build Coastguard Worker 		}
1053*49cdfc7eSAndroid Build Coastguard Worker 		WRITE_OR_DIE(errpipe[1], &errlen, sizeof(errlen));
1054*49cdfc7eSAndroid Build Coastguard Worker 		WRITE_OR_DIE(errpipe[1], errbuf, errlen);
1055*49cdfc7eSAndroid Build Coastguard Worker 		exit(errno);
1056*49cdfc7eSAndroid Build Coastguard Worker 	}
1057*49cdfc7eSAndroid Build Coastguard Worker 
1058*49cdfc7eSAndroid Build Coastguard Worker 	/* parent */
1059*49cdfc7eSAndroid Build Coastguard Worker 
1060*49cdfc7eSAndroid Build Coastguard Worker 	/* subst_pcnt_f() allocates the command line dynamically
1061*49cdfc7eSAndroid Build Coastguard Worker 	 * free the malloc to prevent a memory leak
1062*49cdfc7eSAndroid Build Coastguard Worker 	 */
1063*49cdfc7eSAndroid Build Coastguard Worker 	if (colle->pcnt_f)
1064*49cdfc7eSAndroid Build Coastguard Worker 		free(c_cmdline);
1065*49cdfc7eSAndroid Build Coastguard Worker 
1066*49cdfc7eSAndroid Build Coastguard Worker 	close(errpipe[1]);
1067*49cdfc7eSAndroid Build Coastguard Worker 
1068*49cdfc7eSAndroid Build Coastguard Worker 	/* if the child couldn't go through with the exec,
1069*49cdfc7eSAndroid Build Coastguard Worker 	 * clean up the mess, note it, and move on
1070*49cdfc7eSAndroid Build Coastguard Worker 	 */
1071*49cdfc7eSAndroid Build Coastguard Worker 	if (read(errpipe[0], &errlen, sizeof(errlen))) {
1072*49cdfc7eSAndroid Build Coastguard Worker 		int status;
1073*49cdfc7eSAndroid Build Coastguard Worker 		time_t end_time;
1074*49cdfc7eSAndroid Build Coastguard Worker 		int termid;
1075*49cdfc7eSAndroid Build Coastguard Worker 		char *termtype;
1076*49cdfc7eSAndroid Build Coastguard Worker 		struct tms notime = { 0, 0, 0, 0 };
1077*49cdfc7eSAndroid Build Coastguard Worker 
1078*49cdfc7eSAndroid Build Coastguard Worker 		if (read(errpipe[0], errbuf, errlen) < 0)
1079*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Failed to read from errpipe[0]\n");
1080*49cdfc7eSAndroid Build Coastguard Worker 		close(errpipe[0]);
1081*49cdfc7eSAndroid Build Coastguard Worker 		errbuf[errlen] = '\0';
1082*49cdfc7eSAndroid Build Coastguard Worker 		/* fprintf(stderr, "%s", errbuf); */
1083*49cdfc7eSAndroid Build Coastguard Worker 		waitpid(cpid, &status, 0);
1084*49cdfc7eSAndroid Build Coastguard Worker 		if (WIFSIGNALED(status)) {
1085*49cdfc7eSAndroid Build Coastguard Worker 			termid = WTERMSIG(status);
1086*49cdfc7eSAndroid Build Coastguard Worker 			termtype = "signaled";
1087*49cdfc7eSAndroid Build Coastguard Worker 		} else if (WIFEXITED(status)) {
1088*49cdfc7eSAndroid Build Coastguard Worker 			termid = WEXITSTATUS(status);
1089*49cdfc7eSAndroid Build Coastguard Worker 			termtype = "exited";
1090*49cdfc7eSAndroid Build Coastguard Worker 		} else if (WIFSTOPPED(status)) {
1091*49cdfc7eSAndroid Build Coastguard Worker 			termid = WSTOPSIG(status);
1092*49cdfc7eSAndroid Build Coastguard Worker 			termtype = "stopped";
1093*49cdfc7eSAndroid Build Coastguard Worker 		} else {
1094*49cdfc7eSAndroid Build Coastguard Worker 			termid = 0;
1095*49cdfc7eSAndroid Build Coastguard Worker 			termtype = "unknown";
1096*49cdfc7eSAndroid Build Coastguard Worker 		}
1097*49cdfc7eSAndroid Build Coastguard Worker 		time(&end_time);
1098*49cdfc7eSAndroid Build Coastguard Worker 		if (logfile != NULL) {
1099*49cdfc7eSAndroid Build Coastguard Worker 			if (!fmt_print) {
1100*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(logfile,
1101*49cdfc7eSAndroid Build Coastguard Worker 					"tag=%s stime=%d dur=%d exit=%s "
1102*49cdfc7eSAndroid Build Coastguard Worker 					"stat=%d core=%s cu=%d cs=%d\n",
1103*49cdfc7eSAndroid Build Coastguard Worker 					colle->name, (int)(active->mystime),
1104*49cdfc7eSAndroid Build Coastguard Worker 					(int)(end_time - active->mystime),
1105*49cdfc7eSAndroid Build Coastguard Worker 					termtype, termid,
1106*49cdfc7eSAndroid Build Coastguard Worker 					(status & 0200) ? "yes" : "no", 0, 0);
1107*49cdfc7eSAndroid Build Coastguard Worker 			} else {
1108*49cdfc7eSAndroid Build Coastguard Worker 				if (termid != 0)
1109*49cdfc7eSAndroid Build Coastguard Worker 					++ * failcnt;
1110*49cdfc7eSAndroid Build Coastguard Worker 
1111*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(logfile, ResultFmt" %-5d\n",
1112*49cdfc7eSAndroid Build Coastguard Worker 					colle->name,
1113*49cdfc7eSAndroid Build Coastguard Worker 					((termid != 0) ? "FAIL" : "PASS"),
1114*49cdfc7eSAndroid Build Coastguard Worker 					termid);
1115*49cdfc7eSAndroid Build Coastguard Worker 			}
1116*49cdfc7eSAndroid Build Coastguard Worker 			fflush(logfile);
1117*49cdfc7eSAndroid Build Coastguard Worker 		}
1118*49cdfc7eSAndroid Build Coastguard Worker 
1119*49cdfc7eSAndroid Build Coastguard Worker 		if (!quiet_mode) {
1120*49cdfc7eSAndroid Build Coastguard Worker 			write_test_end(active, errbuf, end_time, termtype,
1121*49cdfc7eSAndroid Build Coastguard Worker 				       status, termid, &notime, &notime);
1122*49cdfc7eSAndroid Build Coastguard Worker 		}
1123*49cdfc7eSAndroid Build Coastguard Worker 		if (capturing) {
1124*49cdfc7eSAndroid Build Coastguard Worker 			close(c_stdout);
1125*49cdfc7eSAndroid Build Coastguard Worker 			unlink(active->output);
1126*49cdfc7eSAndroid Build Coastguard Worker 		}
1127*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
1128*49cdfc7eSAndroid Build Coastguard Worker 	}
1129*49cdfc7eSAndroid Build Coastguard Worker 
1130*49cdfc7eSAndroid Build Coastguard Worker 	close(errpipe[0]);
1131*49cdfc7eSAndroid Build Coastguard Worker 	if (capturing)
1132*49cdfc7eSAndroid Build Coastguard Worker 		close(c_stdout);
1133*49cdfc7eSAndroid Build Coastguard Worker 
1134*49cdfc7eSAndroid Build Coastguard Worker 	active->pgrp = cpid;
1135*49cdfc7eSAndroid Build Coastguard Worker 	active->stopping = 0;
1136*49cdfc7eSAndroid Build Coastguard Worker 
1137*49cdfc7eSAndroid Build Coastguard Worker 	if (zoo_mark_cmdline(zoofile, cpid, colle->name, colle->cmdline)) {
1138*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
1139*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
1140*49cdfc7eSAndroid Build Coastguard Worker 	}
1141*49cdfc7eSAndroid Build Coastguard Worker 
1142*49cdfc7eSAndroid Build Coastguard Worker 	if (Debug & Dstartup)
1143*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "started %s cpid=%d at %s",
1144*49cdfc7eSAndroid Build Coastguard Worker 			colle->name, cpid, ctime(&active->mystime));
1145*49cdfc7eSAndroid Build Coastguard Worker 
1146*49cdfc7eSAndroid Build Coastguard Worker 	if (Debug & Dstart) {
1147*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Executing test = %s as %s", colle->name,
1148*49cdfc7eSAndroid Build Coastguard Worker 			colle->cmdline);
1149*49cdfc7eSAndroid Build Coastguard Worker 		if (capturing)
1150*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "with output file = %s\n",
1151*49cdfc7eSAndroid Build Coastguard Worker 				active->output);
1152*49cdfc7eSAndroid Build Coastguard Worker 		else
1153*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "\n");
1154*49cdfc7eSAndroid Build Coastguard Worker 	}
1155*49cdfc7eSAndroid Build Coastguard Worker 
1156*49cdfc7eSAndroid Build Coastguard Worker 	return cpid;
1157*49cdfc7eSAndroid Build Coastguard Worker }
1158*49cdfc7eSAndroid Build Coastguard Worker 
subst_pcnt_f(struct coll_entry * colle)1159*49cdfc7eSAndroid Build Coastguard Worker static char *subst_pcnt_f(struct coll_entry *colle)
1160*49cdfc7eSAndroid Build Coastguard Worker {
1161*49cdfc7eSAndroid Build Coastguard Worker 	static int counter = 1;
1162*49cdfc7eSAndroid Build Coastguard Worker 	char pid_and_counter[20];
1163*49cdfc7eSAndroid Build Coastguard Worker 	char new_cmdline[1024];
1164*49cdfc7eSAndroid Build Coastguard Worker 
1165*49cdfc7eSAndroid Build Coastguard Worker 	/* if we get called falsely, do the right thing anyway */
1166*49cdfc7eSAndroid Build Coastguard Worker 	if (!colle->pcnt_f)
1167*49cdfc7eSAndroid Build Coastguard Worker 		return colle->cmdline;
1168*49cdfc7eSAndroid Build Coastguard Worker 
1169*49cdfc7eSAndroid Build Coastguard Worker 	snprintf(pid_and_counter, 20, "%d_%d", getpid(), counter++);
1170*49cdfc7eSAndroid Build Coastguard Worker 	snprintf(new_cmdline, 1024, colle->cmdline, pid_and_counter);
1171*49cdfc7eSAndroid Build Coastguard Worker 	return strdup(new_cmdline);
1172*49cdfc7eSAndroid Build Coastguard Worker }
1173*49cdfc7eSAndroid Build Coastguard Worker 
get_collection(char * file,int optind,int argc,char ** argv)1174*49cdfc7eSAndroid Build Coastguard Worker static struct collection *get_collection(char *file, int optind, int argc,
1175*49cdfc7eSAndroid Build Coastguard Worker 					 char **argv)
1176*49cdfc7eSAndroid Build Coastguard Worker {
1177*49cdfc7eSAndroid Build Coastguard Worker 	char *buf, *a, *b;
1178*49cdfc7eSAndroid Build Coastguard Worker 	struct coll_entry *head, *p, *n;
1179*49cdfc7eSAndroid Build Coastguard Worker 	struct collection *coll;
1180*49cdfc7eSAndroid Build Coastguard Worker 	int i;
1181*49cdfc7eSAndroid Build Coastguard Worker 
1182*49cdfc7eSAndroid Build Coastguard Worker 	buf = slurp(file);
1183*49cdfc7eSAndroid Build Coastguard Worker 	if (!buf)
1184*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
1185*49cdfc7eSAndroid Build Coastguard Worker 
1186*49cdfc7eSAndroid Build Coastguard Worker 	coll = malloc(sizeof(struct collection));
1187*49cdfc7eSAndroid Build Coastguard Worker 	coll->cnt = 0;
1188*49cdfc7eSAndroid Build Coastguard Worker 
1189*49cdfc7eSAndroid Build Coastguard Worker 	head = p = n = NULL;
1190*49cdfc7eSAndroid Build Coastguard Worker 	a = b = buf;
1191*49cdfc7eSAndroid Build Coastguard Worker 	while (a) {
1192*49cdfc7eSAndroid Build Coastguard Worker 		/* set b to the start of the next line and add a NULL character
1193*49cdfc7eSAndroid Build Coastguard Worker 		 * to separate the two lines */
1194*49cdfc7eSAndroid Build Coastguard Worker 		if ((b = strchr(a, '\n')) != NULL)
1195*49cdfc7eSAndroid Build Coastguard Worker 			*b++ = '\0';
1196*49cdfc7eSAndroid Build Coastguard Worker 
1197*49cdfc7eSAndroid Build Coastguard Worker 		/* If this is line isn't a comment */
1198*49cdfc7eSAndroid Build Coastguard Worker 		if ((*a != '#') && (*a != '\0') && (*a != ' ')) {
1199*49cdfc7eSAndroid Build Coastguard Worker 			n = malloc(sizeof(struct coll_entry));
1200*49cdfc7eSAndroid Build Coastguard Worker 			if ((n->pcnt_f = strstr(a, "%f"))) {
1201*49cdfc7eSAndroid Build Coastguard Worker 				n->pcnt_f[1] = 's';
1202*49cdfc7eSAndroid Build Coastguard Worker 			}
1203*49cdfc7eSAndroid Build Coastguard Worker 			n->name = strdup(strsep(&a, " \t"));
1204*49cdfc7eSAndroid Build Coastguard Worker 			while (a != NULL && isspace(*a))
1205*49cdfc7eSAndroid Build Coastguard Worker 				a++;
1206*49cdfc7eSAndroid Build Coastguard Worker 			if (a == NULL || a[0] == 0) {
1207*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
1208*49cdfc7eSAndroid Build Coastguard Worker 					"pan(%s): Testcase '%s' requires a command to execute.\n",
1209*49cdfc7eSAndroid Build Coastguard Worker 					panname, n->name);
1210*49cdfc7eSAndroid Build Coastguard Worker 				return NULL;
1211*49cdfc7eSAndroid Build Coastguard Worker 			}
1212*49cdfc7eSAndroid Build Coastguard Worker 			n->cmdline = strdup(a);
1213*49cdfc7eSAndroid Build Coastguard Worker 			n->next = NULL;
1214*49cdfc7eSAndroid Build Coastguard Worker 
1215*49cdfc7eSAndroid Build Coastguard Worker 			if (p) {
1216*49cdfc7eSAndroid Build Coastguard Worker 				p->next = n;
1217*49cdfc7eSAndroid Build Coastguard Worker 			}
1218*49cdfc7eSAndroid Build Coastguard Worker 			if (head == NULL) {
1219*49cdfc7eSAndroid Build Coastguard Worker 				head = n;
1220*49cdfc7eSAndroid Build Coastguard Worker 			}
1221*49cdfc7eSAndroid Build Coastguard Worker 			p = n;
1222*49cdfc7eSAndroid Build Coastguard Worker 			coll->cnt++;
1223*49cdfc7eSAndroid Build Coastguard Worker 		}
1224*49cdfc7eSAndroid Build Coastguard Worker 		a = b;
1225*49cdfc7eSAndroid Build Coastguard Worker 	}
1226*49cdfc7eSAndroid Build Coastguard Worker 	free(buf);
1227*49cdfc7eSAndroid Build Coastguard Worker 
1228*49cdfc7eSAndroid Build Coastguard Worker 	/* is there something on the commandline to be counted? */
1229*49cdfc7eSAndroid Build Coastguard Worker 	if (optind < argc) {
1230*49cdfc7eSAndroid Build Coastguard Worker 		char workstr[1024] = "";
1231*49cdfc7eSAndroid Build Coastguard Worker 		int workstr_left = 1023;
1232*49cdfc7eSAndroid Build Coastguard Worker 
1233*49cdfc7eSAndroid Build Coastguard Worker 		/* fill arg list */
1234*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; optind < argc; ++optind, ++i) {
1235*49cdfc7eSAndroid Build Coastguard Worker 			strncat(workstr, argv[optind], workstr_left);
1236*49cdfc7eSAndroid Build Coastguard Worker 			workstr_left = workstr_left - strlen(argv[optind]);
1237*49cdfc7eSAndroid Build Coastguard Worker 			strncat(workstr, " ", workstr_left);
1238*49cdfc7eSAndroid Build Coastguard Worker 			workstr_left--;
1239*49cdfc7eSAndroid Build Coastguard Worker 		}
1240*49cdfc7eSAndroid Build Coastguard Worker 
1241*49cdfc7eSAndroid Build Coastguard Worker 		n = malloc(sizeof(struct coll_entry));
1242*49cdfc7eSAndroid Build Coastguard Worker 		if ((n->pcnt_f = strstr(workstr, "%f"))) {
1243*49cdfc7eSAndroid Build Coastguard Worker 			n->pcnt_f[1] = 's';
1244*49cdfc7eSAndroid Build Coastguard Worker 		}
1245*49cdfc7eSAndroid Build Coastguard Worker 		n->cmdline = strdup(workstr);
1246*49cdfc7eSAndroid Build Coastguard Worker 		n->name = "cmdln";
1247*49cdfc7eSAndroid Build Coastguard Worker 		n->next = NULL;
1248*49cdfc7eSAndroid Build Coastguard Worker 		if (p) {
1249*49cdfc7eSAndroid Build Coastguard Worker 			p->next = n;
1250*49cdfc7eSAndroid Build Coastguard Worker 		}
1251*49cdfc7eSAndroid Build Coastguard Worker 		if (head == NULL) {
1252*49cdfc7eSAndroid Build Coastguard Worker 			head = n;
1253*49cdfc7eSAndroid Build Coastguard Worker 		}
1254*49cdfc7eSAndroid Build Coastguard Worker 		coll->cnt++;
1255*49cdfc7eSAndroid Build Coastguard Worker 	}
1256*49cdfc7eSAndroid Build Coastguard Worker 
1257*49cdfc7eSAndroid Build Coastguard Worker 	/* get an array */
1258*49cdfc7eSAndroid Build Coastguard Worker 	coll->ary = malloc(coll->cnt * sizeof(struct coll_entry *));
1259*49cdfc7eSAndroid Build Coastguard Worker 
1260*49cdfc7eSAndroid Build Coastguard Worker 	/* fill the array */
1261*49cdfc7eSAndroid Build Coastguard Worker 	i = 0;
1262*49cdfc7eSAndroid Build Coastguard Worker 	n = head;
1263*49cdfc7eSAndroid Build Coastguard Worker 	while (n != NULL) {
1264*49cdfc7eSAndroid Build Coastguard Worker 		coll->ary[i] = n;
1265*49cdfc7eSAndroid Build Coastguard Worker 		n = n->next;
1266*49cdfc7eSAndroid Build Coastguard Worker 		++i;
1267*49cdfc7eSAndroid Build Coastguard Worker 	}
1268*49cdfc7eSAndroid Build Coastguard Worker 	if (i != coll->cnt)
1269*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): i doesn't match cnt\n", panname);
1270*49cdfc7eSAndroid Build Coastguard Worker 
1271*49cdfc7eSAndroid Build Coastguard Worker 	return coll;
1272*49cdfc7eSAndroid Build Coastguard Worker }
1273*49cdfc7eSAndroid Build Coastguard Worker 
slurp(char * file)1274*49cdfc7eSAndroid Build Coastguard Worker static char *slurp(char *file)
1275*49cdfc7eSAndroid Build Coastguard Worker {
1276*49cdfc7eSAndroid Build Coastguard Worker 	char *buf;
1277*49cdfc7eSAndroid Build Coastguard Worker 	int fd;
1278*49cdfc7eSAndroid Build Coastguard Worker 	struct stat sbuf;
1279*49cdfc7eSAndroid Build Coastguard Worker 
1280*49cdfc7eSAndroid Build Coastguard Worker 	if ((fd = open(file, O_RDONLY)) < 0) {
1281*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr,
1282*49cdfc7eSAndroid Build Coastguard Worker 			"pan(%s): open(%s,O_RDONLY) failed.  errno:%d  %s\n",
1283*49cdfc7eSAndroid Build Coastguard Worker 			panname, file, errno, strerror(errno));
1284*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
1285*49cdfc7eSAndroid Build Coastguard Worker 	}
1286*49cdfc7eSAndroid Build Coastguard Worker 
1287*49cdfc7eSAndroid Build Coastguard Worker 	if (fstat(fd, &sbuf) < 0) {
1288*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): fstat(%s) failed.  errno:%d  %s\n",
1289*49cdfc7eSAndroid Build Coastguard Worker 			panname, file, errno, strerror(errno));
1290*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
1291*49cdfc7eSAndroid Build Coastguard Worker 	}
1292*49cdfc7eSAndroid Build Coastguard Worker 
1293*49cdfc7eSAndroid Build Coastguard Worker 	buf = malloc(sbuf.st_size + 1);
1294*49cdfc7eSAndroid Build Coastguard Worker 	if (read(fd, buf, sbuf.st_size) != sbuf.st_size) {
1295*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "pan(%s): slurp failed.  errno:%d  %s\n",
1296*49cdfc7eSAndroid Build Coastguard Worker 			panname, errno, strerror(errno));
1297*49cdfc7eSAndroid Build Coastguard Worker 		free(buf);
1298*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
1299*49cdfc7eSAndroid Build Coastguard Worker 	}
1300*49cdfc7eSAndroid Build Coastguard Worker 	buf[sbuf.st_size] = '\0';
1301*49cdfc7eSAndroid Build Coastguard Worker 
1302*49cdfc7eSAndroid Build Coastguard Worker 	close(fd);
1303*49cdfc7eSAndroid Build Coastguard Worker 	return buf;
1304*49cdfc7eSAndroid Build Coastguard Worker }
1305*49cdfc7eSAndroid Build Coastguard Worker 
check_orphans(struct orphan_pgrp * orphans,int sig)1306*49cdfc7eSAndroid Build Coastguard Worker static void check_orphans(struct orphan_pgrp *orphans, int sig)
1307*49cdfc7eSAndroid Build Coastguard Worker {
1308*49cdfc7eSAndroid Build Coastguard Worker 	struct orphan_pgrp *orph;
1309*49cdfc7eSAndroid Build Coastguard Worker 
1310*49cdfc7eSAndroid Build Coastguard Worker 	for (orph = orphans; orph != NULL; orph = orph->next) {
1311*49cdfc7eSAndroid Build Coastguard Worker 		if (orph->pgrp == 0)
1312*49cdfc7eSAndroid Build Coastguard Worker 			continue;
1313*49cdfc7eSAndroid Build Coastguard Worker 
1314*49cdfc7eSAndroid Build Coastguard Worker 		if (Debug & Dshutdown)
1315*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr,
1316*49cdfc7eSAndroid Build Coastguard Worker 				"  propagating sig %d to orphaned pgrp %d\n",
1317*49cdfc7eSAndroid Build Coastguard Worker 				sig, -(orph->pgrp));
1318*49cdfc7eSAndroid Build Coastguard Worker 		if (kill(-(orph->pgrp), sig) != 0) {
1319*49cdfc7eSAndroid Build Coastguard Worker 			if (errno == ESRCH) {
1320*49cdfc7eSAndroid Build Coastguard Worker 				/* This pgrp is now empty */
1321*49cdfc7eSAndroid Build Coastguard Worker 				if (zoo_clear(zoofile, orph->pgrp)) {
1322*49cdfc7eSAndroid Build Coastguard Worker 					fprintf(stderr, "pan(%s): %s\n",
1323*49cdfc7eSAndroid Build Coastguard Worker 						panname, zoo_error);
1324*49cdfc7eSAndroid Build Coastguard Worker 				}
1325*49cdfc7eSAndroid Build Coastguard Worker 				orph->pgrp = 0;
1326*49cdfc7eSAndroid Build Coastguard Worker 			} else {
1327*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
1328*49cdfc7eSAndroid Build Coastguard Worker 					"pan(%s): kill(%d,%d) on orphaned pgrp failed.  errno:%d  %s\n",
1329*49cdfc7eSAndroid Build Coastguard Worker 					panname, -(orph->pgrp), sig, errno,
1330*49cdfc7eSAndroid Build Coastguard Worker 					strerror(errno));
1331*49cdfc7eSAndroid Build Coastguard Worker 			}
1332*49cdfc7eSAndroid Build Coastguard Worker 		}
1333*49cdfc7eSAndroid Build Coastguard Worker 	}
1334*49cdfc7eSAndroid Build Coastguard Worker }
1335*49cdfc7eSAndroid Build Coastguard Worker 
mark_orphan(struct orphan_pgrp * orphans,pid_t cpid)1336*49cdfc7eSAndroid Build Coastguard Worker static void mark_orphan(struct orphan_pgrp *orphans, pid_t cpid)
1337*49cdfc7eSAndroid Build Coastguard Worker {
1338*49cdfc7eSAndroid Build Coastguard Worker 	struct orphan_pgrp *orph;
1339*49cdfc7eSAndroid Build Coastguard Worker 
1340*49cdfc7eSAndroid Build Coastguard Worker 	for (orph = orphans; orph != NULL; orph = orph->next) {
1341*49cdfc7eSAndroid Build Coastguard Worker 		if (orph->pgrp == 0)
1342*49cdfc7eSAndroid Build Coastguard Worker 			break;
1343*49cdfc7eSAndroid Build Coastguard Worker 	}
1344*49cdfc7eSAndroid Build Coastguard Worker 	if (orph == NULL) {
1345*49cdfc7eSAndroid Build Coastguard Worker 		/* make a new struct */
1346*49cdfc7eSAndroid Build Coastguard Worker 		orph = malloc(sizeof(struct orphan_pgrp));
1347*49cdfc7eSAndroid Build Coastguard Worker 
1348*49cdfc7eSAndroid Build Coastguard Worker 		/* plug in the new struct just after the head */
1349*49cdfc7eSAndroid Build Coastguard Worker 		orph->next = orphans->next;
1350*49cdfc7eSAndroid Build Coastguard Worker 		orphans->next = orph;
1351*49cdfc7eSAndroid Build Coastguard Worker 	}
1352*49cdfc7eSAndroid Build Coastguard Worker 	orph->pgrp = cpid;
1353*49cdfc7eSAndroid Build Coastguard Worker }
1354*49cdfc7eSAndroid Build Coastguard Worker 
copy_buffered_output(struct tag_pgrp * running)1355*49cdfc7eSAndroid Build Coastguard Worker static void copy_buffered_output(struct tag_pgrp *running)
1356*49cdfc7eSAndroid Build Coastguard Worker {
1357*49cdfc7eSAndroid Build Coastguard Worker 	char *tag_output;
1358*49cdfc7eSAndroid Build Coastguard Worker 
1359*49cdfc7eSAndroid Build Coastguard Worker 	tag_output = slurp(running->output);
1360*49cdfc7eSAndroid Build Coastguard Worker 	if (tag_output) {
1361*49cdfc7eSAndroid Build Coastguard Worker 		printf("%s", tag_output);
1362*49cdfc7eSAndroid Build Coastguard Worker 		/* make sure the output ends with a newline */
1363*49cdfc7eSAndroid Build Coastguard Worker 		if (tag_output[strlen(tag_output) - 1] != '\n')
1364*49cdfc7eSAndroid Build Coastguard Worker 			printf("\n");
1365*49cdfc7eSAndroid Build Coastguard Worker 		fflush(stdout);
1366*49cdfc7eSAndroid Build Coastguard Worker 		free(tag_output);
1367*49cdfc7eSAndroid Build Coastguard Worker 	}
1368*49cdfc7eSAndroid Build Coastguard Worker }
1369*49cdfc7eSAndroid Build Coastguard Worker 
write_kmsg(const char * fmt,...)1370*49cdfc7eSAndroid Build Coastguard Worker static void write_kmsg(const char *fmt, ...)
1371*49cdfc7eSAndroid Build Coastguard Worker {
1372*49cdfc7eSAndroid Build Coastguard Worker 	FILE *kmsg;
1373*49cdfc7eSAndroid Build Coastguard Worker 	va_list ap;
1374*49cdfc7eSAndroid Build Coastguard Worker 
1375*49cdfc7eSAndroid Build Coastguard Worker 	if ((kmsg = fopen("/dev/kmsg", "r+")) == NULL) {
1376*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Error %s: (%d) opening /dev/kmsg\n",
1377*49cdfc7eSAndroid Build Coastguard Worker 				strerror(errno), errno);
1378*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
1379*49cdfc7eSAndroid Build Coastguard Worker 	}
1380*49cdfc7eSAndroid Build Coastguard Worker 
1381*49cdfc7eSAndroid Build Coastguard Worker 	va_start(ap, fmt);
1382*49cdfc7eSAndroid Build Coastguard Worker 	vfprintf(kmsg, fmt, ap);
1383*49cdfc7eSAndroid Build Coastguard Worker 	va_end(ap);
1384*49cdfc7eSAndroid Build Coastguard Worker 	fclose(kmsg);
1385*49cdfc7eSAndroid Build Coastguard Worker }
1386*49cdfc7eSAndroid Build Coastguard Worker 
write_test_start(struct tag_pgrp * running,int no_kmsg)1387*49cdfc7eSAndroid Build Coastguard Worker static void write_test_start(struct tag_pgrp *running, int no_kmsg)
1388*49cdfc7eSAndroid Build Coastguard Worker {
1389*49cdfc7eSAndroid Build Coastguard Worker 	if (!strcmp(reporttype, "rts")) {
1390*49cdfc7eSAndroid Build Coastguard Worker 
1391*49cdfc7eSAndroid Build Coastguard Worker 		printf
1392*49cdfc7eSAndroid Build Coastguard Worker 		    ("%s\ntag=%s stime=%lld\ncmdline=\"%s\"\ncontacts=\"%s\"\nanalysis=%s\n%s\n",
1393*49cdfc7eSAndroid Build Coastguard Worker 		     "<<<test_start>>>", running->cmd->name, (long long)running->mystime,
1394*49cdfc7eSAndroid Build Coastguard Worker 		     running->cmd->cmdline, "", "exit", "<<<test_output>>>");
1395*49cdfc7eSAndroid Build Coastguard Worker 	}
1396*49cdfc7eSAndroid Build Coastguard Worker 	fflush(stdout);
1397*49cdfc7eSAndroid Build Coastguard Worker 	if (no_kmsg)
1398*49cdfc7eSAndroid Build Coastguard Worker 		return;
1399*49cdfc7eSAndroid Build Coastguard Worker 
1400*49cdfc7eSAndroid Build Coastguard Worker 	if (strcmp(running->cmd->name, running->cmd->cmdline))
1401*49cdfc7eSAndroid Build Coastguard Worker 		write_kmsg("LTP: starting %s (%s)\n", running->cmd->name,
1402*49cdfc7eSAndroid Build Coastguard Worker 			   running->cmd->cmdline);
1403*49cdfc7eSAndroid Build Coastguard Worker 	else
1404*49cdfc7eSAndroid Build Coastguard Worker 		write_kmsg("LTP: starting %s\n", running->cmd->name);
1405*49cdfc7eSAndroid Build Coastguard Worker }
1406*49cdfc7eSAndroid Build Coastguard Worker 
1407*49cdfc7eSAndroid Build Coastguard Worker static void
write_test_end(struct tag_pgrp * running,const char * init_status,time_t exit_time,char * term_type,int stat_loc,int term_id,struct tms * tms1,struct tms * tms2)1408*49cdfc7eSAndroid Build Coastguard Worker write_test_end(struct tag_pgrp *running, const char *init_status,
1409*49cdfc7eSAndroid Build Coastguard Worker 	       time_t exit_time, char *term_type, int stat_loc,
1410*49cdfc7eSAndroid Build Coastguard Worker 	       int term_id, struct tms *tms1, struct tms *tms2)
1411*49cdfc7eSAndroid Build Coastguard Worker {
1412*49cdfc7eSAndroid Build Coastguard Worker 	if (!strcmp(reporttype, "rts")) {
1413*49cdfc7eSAndroid Build Coastguard Worker 		printf
1414*49cdfc7eSAndroid Build Coastguard Worker 		    ("%s\ninitiation_status=\"%s\"\nduration=%ld termination_type=%s "
1415*49cdfc7eSAndroid Build Coastguard Worker 		     "termination_id=%d corefile=%s\ncutime=%d cstime=%d\n%s\n",
1416*49cdfc7eSAndroid Build Coastguard Worker 		     "<<<execution_status>>>", init_status,
1417*49cdfc7eSAndroid Build Coastguard Worker 		     (long)(exit_time - running->mystime), term_type, term_id,
1418*49cdfc7eSAndroid Build Coastguard Worker 		     (stat_loc & 0200) ? "yes" : "no",
1419*49cdfc7eSAndroid Build Coastguard Worker 		     (int)(tms2->tms_cutime - tms1->tms_cutime),
1420*49cdfc7eSAndroid Build Coastguard Worker 		     (int)(tms2->tms_cstime - tms1->tms_cstime),
1421*49cdfc7eSAndroid Build Coastguard Worker 		     "<<<test_end>>>");
1422*49cdfc7eSAndroid Build Coastguard Worker 	}
1423*49cdfc7eSAndroid Build Coastguard Worker 	fflush(stdout);
1424*49cdfc7eSAndroid Build Coastguard Worker }
1425*49cdfc7eSAndroid Build Coastguard Worker 
1426*49cdfc7eSAndroid Build Coastguard Worker /* The functions below are all debugging related */
1427*49cdfc7eSAndroid Build Coastguard Worker 
pids_running(struct tag_pgrp * running,int keep_active)1428*49cdfc7eSAndroid Build Coastguard Worker static void pids_running(struct tag_pgrp *running, int keep_active)
1429*49cdfc7eSAndroid Build Coastguard Worker {
1430*49cdfc7eSAndroid Build Coastguard Worker 	int i;
1431*49cdfc7eSAndroid Build Coastguard Worker 
1432*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "pids still running: ");
1433*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < keep_active; ++i) {
1434*49cdfc7eSAndroid Build Coastguard Worker 		if (running[i].pgrp != 0)
1435*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "%d ", running[i].pgrp);
1436*49cdfc7eSAndroid Build Coastguard Worker 	}
1437*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
1438*49cdfc7eSAndroid Build Coastguard Worker }
1439*49cdfc7eSAndroid Build Coastguard Worker 
orphans_running(struct orphan_pgrp * orphans)1440*49cdfc7eSAndroid Build Coastguard Worker static void orphans_running(struct orphan_pgrp *orphans)
1441*49cdfc7eSAndroid Build Coastguard Worker {
1442*49cdfc7eSAndroid Build Coastguard Worker 	struct orphan_pgrp *orph;
1443*49cdfc7eSAndroid Build Coastguard Worker 
1444*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "orphans still running: ");
1445*49cdfc7eSAndroid Build Coastguard Worker 	for (orph = orphans; orph != NULL; orph = orph->next) {
1446*49cdfc7eSAndroid Build Coastguard Worker 		if (orph->pgrp != 0)
1447*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "%d ", -(orph->pgrp));
1448*49cdfc7eSAndroid Build Coastguard Worker 	}
1449*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
1450*49cdfc7eSAndroid Build Coastguard Worker }
1451*49cdfc7eSAndroid Build Coastguard Worker 
dump_coll(struct collection * coll)1452*49cdfc7eSAndroid Build Coastguard Worker static void dump_coll(struct collection *coll)
1453*49cdfc7eSAndroid Build Coastguard Worker {
1454*49cdfc7eSAndroid Build Coastguard Worker 	int i;
1455*49cdfc7eSAndroid Build Coastguard Worker 
1456*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < coll->cnt; ++i) {
1457*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "coll %d\n", i);
1458*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "  name=%s cmdline=%s\n", coll->ary[i]->name,
1459*49cdfc7eSAndroid Build Coastguard Worker 			coll->ary[i]->cmdline);
1460*49cdfc7eSAndroid Build Coastguard Worker 	}
1461*49cdfc7eSAndroid Build Coastguard Worker }
1462*49cdfc7eSAndroid Build Coastguard Worker 
wait_handler(int sig)1463*49cdfc7eSAndroid Build Coastguard Worker void wait_handler(int sig)
1464*49cdfc7eSAndroid Build Coastguard Worker {
1465*49cdfc7eSAndroid Build Coastguard Worker 	static int lastsent = 0;
1466*49cdfc7eSAndroid Build Coastguard Worker 
1467*49cdfc7eSAndroid Build Coastguard Worker 	if (sig == 0) {
1468*49cdfc7eSAndroid Build Coastguard Worker 		lastsent = 0;
1469*49cdfc7eSAndroid Build Coastguard Worker 	} else {
1470*49cdfc7eSAndroid Build Coastguard Worker 		rec_signal = sig;
1471*49cdfc7eSAndroid Build Coastguard Worker 		if (sig == SIGUSR2)
1472*49cdfc7eSAndroid Build Coastguard Worker 			return;
1473*49cdfc7eSAndroid Build Coastguard Worker 		if (lastsent == 0)
1474*49cdfc7eSAndroid Build Coastguard Worker 			send_signal = sig;
1475*49cdfc7eSAndroid Build Coastguard Worker 		else if (lastsent == SIGUSR1)
1476*49cdfc7eSAndroid Build Coastguard Worker 			send_signal = SIGINT;
1477*49cdfc7eSAndroid Build Coastguard Worker 		else if (lastsent == sig)
1478*49cdfc7eSAndroid Build Coastguard Worker 			send_signal = SIGTERM;
1479*49cdfc7eSAndroid Build Coastguard Worker 		else if (lastsent == SIGTERM)
1480*49cdfc7eSAndroid Build Coastguard Worker 			send_signal = SIGHUP;
1481*49cdfc7eSAndroid Build Coastguard Worker 		else if (lastsent == SIGHUP)
1482*49cdfc7eSAndroid Build Coastguard Worker 			send_signal = SIGKILL;
1483*49cdfc7eSAndroid Build Coastguard Worker 		lastsent = send_signal;
1484*49cdfc7eSAndroid Build Coastguard Worker 	}
1485*49cdfc7eSAndroid Build Coastguard Worker }
1486