xref: /aosp_15_r20/external/ltp/testcases/kernel/ipc/pipeio/pipeio.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  */
33*49cdfc7eSAndroid Build Coastguard Worker /* $Header: /cvsroot/ltp/ltp/testcases/kernel/ipc/pipeio/pipeio.c,v 1.18 2009/03/19 07:10:02 subrata_modak Exp $ */
34*49cdfc7eSAndroid Build Coastguard Worker /*
35*49cdfc7eSAndroid Build Coastguard Worker  *  This tool can be used to beat on system or named pipes.
36*49cdfc7eSAndroid Build Coastguard Worker  *  See the help() function below for user information.
37*49cdfc7eSAndroid Build Coastguard Worker  */
38*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
39*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
40*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
41*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
42*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
43*49cdfc7eSAndroid Build Coastguard Worker #include <sys/param.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <sys/wait.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
46*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
47*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
48*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
49*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker #include "tlibio.h"
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
54*49cdfc7eSAndroid Build Coastguard Worker #include "safe_macros.h"
55*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/sem.h"
56*49cdfc7eSAndroid Build Coastguard Worker 
57*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "pipeio";
58*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;
59*49cdfc7eSAndroid Build Coastguard Worker 
60*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
61*49cdfc7eSAndroid Build Coastguard Worker 
62*49cdfc7eSAndroid Build Coastguard Worker #if defined(__linux__)
63*49cdfc7eSAndroid Build Coastguard Worker #define NBPW sizeof(int)
64*49cdfc7eSAndroid Build Coastguard Worker #endif
65*49cdfc7eSAndroid Build Coastguard Worker 
66*49cdfc7eSAndroid Build Coastguard Worker #define OCTAL	'o'
67*49cdfc7eSAndroid Build Coastguard Worker #define HEX	'x'
68*49cdfc7eSAndroid Build Coastguard Worker #define DECIMAL	'd'
69*49cdfc7eSAndroid Build Coastguard Worker #define ASCII	'a'
70*49cdfc7eSAndroid Build Coastguard Worker #define NO_OUT	'n'
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker #define PIPE_NAMED	"named pipe,"
73*49cdfc7eSAndroid Build Coastguard Worker #define PIPE_UNNAMED	"sys pipe,"
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker #define BLOCKING_IO	"blking,"
76*49cdfc7eSAndroid Build Coastguard Worker #define NON_BLOCKING_IO	"non-blking,"
77*49cdfc7eSAndroid Build Coastguard Worker #define UNNAMED_IO	""
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker #define MAX_ERRS 16
80*49cdfc7eSAndroid Build Coastguard Worker #define MAX_EMPTY 256
81*49cdfc7eSAndroid Build Coastguard Worker 
82*49cdfc7eSAndroid Build Coastguard Worker static int parse_options(int argc, char *argv[]);
83*49cdfc7eSAndroid Build Coastguard Worker static void setup(int argc, char *argv[]);
84*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void);
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker static void do_child(void);
87*49cdfc7eSAndroid Build Coastguard Worker static void do_parent(void);
88*49cdfc7eSAndroid Build Coastguard Worker 
89*49cdfc7eSAndroid Build Coastguard Worker static void help(void), usage(void), prt_examples(void);
90*49cdfc7eSAndroid Build Coastguard Worker static void prt_buf(char **addr, char *buf, int length, int format);
91*49cdfc7eSAndroid Build Coastguard Worker static void sig_child(int sig);
92*49cdfc7eSAndroid Build Coastguard Worker static int check_rw_buf(void);
93*49cdfc7eSAndroid Build Coastguard Worker 
94*49cdfc7eSAndroid Build Coastguard Worker static volatile sig_atomic_t nchildcompleted;
95*49cdfc7eSAndroid Build Coastguard Worker 
96*49cdfc7eSAndroid Build Coastguard Worker /* variables may be modified in setup() */
97*49cdfc7eSAndroid Build Coastguard Worker static int num_writers = 1;	/* number of writers */
98*49cdfc7eSAndroid Build Coastguard Worker static int num_writes = 1;	/* number of writes per child */
99*49cdfc7eSAndroid Build Coastguard Worker static int loop;		/* loop indefinitely */
100*49cdfc7eSAndroid Build Coastguard Worker static int exit_error = 1;	/* exit on error #, zero means no exit */
101*49cdfc7eSAndroid Build Coastguard Worker static int size = 327;		/* default size */
102*49cdfc7eSAndroid Build Coastguard Worker static int unpipe;		/* un-named pipe if non-zero */
103*49cdfc7eSAndroid Build Coastguard Worker static int verbose;		/* verbose mode if set */
104*49cdfc7eSAndroid Build Coastguard Worker static int quiet;		/* quiet mode if set */
105*49cdfc7eSAndroid Build Coastguard Worker static int num_rpt;		/* ping number, how often to print message */
106*49cdfc7eSAndroid Build Coastguard Worker static int chld_wait;	/* max time to wait between writes, 1 == no wait */
107*49cdfc7eSAndroid Build Coastguard Worker static int parent_wait;	/* max time to wait between reads, 1 == no wait */
108*49cdfc7eSAndroid Build Coastguard Worker static int ndelay = O_NDELAY;	/* additional flag to open */
109*49cdfc7eSAndroid Build Coastguard Worker static char *writebuf;
110*49cdfc7eSAndroid Build Coastguard Worker static char *readbuf;
111*49cdfc7eSAndroid Build Coastguard Worker static char pname[PATH_MAX];	/* contains the name of the named pipe */
112*49cdfc7eSAndroid Build Coastguard Worker static char *blk_type = NON_BLOCKING_IO; /* blocking i/o or not */
113*49cdfc7eSAndroid Build Coastguard Worker static char *pipe_type;		/* type of pipe under test */
114*49cdfc7eSAndroid Build Coastguard Worker static int format = HEX;
115*49cdfc7eSAndroid Build Coastguard Worker static int format_size = -1;
116*49cdfc7eSAndroid Build Coastguard Worker static int iotype;		/* sync io */
117*49cdfc7eSAndroid Build Coastguard Worker 
118*49cdfc7eSAndroid Build Coastguard Worker /* variables will be modified in running */
119*49cdfc7eSAndroid Build Coastguard Worker static int error;
120*49cdfc7eSAndroid Build Coastguard Worker static int count;
121*49cdfc7eSAndroid Build Coastguard Worker static int read_fd;
122*49cdfc7eSAndroid Build Coastguard Worker static int write_fd;
123*49cdfc7eSAndroid Build Coastguard Worker static int empty_read;
124*49cdfc7eSAndroid Build Coastguard Worker static int sem_id;
125*49cdfc7eSAndroid Build Coastguard Worker 
126*49cdfc7eSAndroid Build Coastguard Worker static union semun u;
127*49cdfc7eSAndroid Build Coastguard Worker 
main(int ac,char * av[])128*49cdfc7eSAndroid Build Coastguard Worker int main(int ac, char *av[])
129*49cdfc7eSAndroid Build Coastguard Worker {
130*49cdfc7eSAndroid Build Coastguard Worker 	int i;
131*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int j;
132*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int uwait_iter = 1000, uwait_total = 5000000;
133*49cdfc7eSAndroid Build Coastguard Worker 	pid_t child;
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker 	setup(ac, av);
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	for (i = num_writers; i > 0; --i) {
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker 		child = tst_fork();
140*49cdfc7eSAndroid Build Coastguard Worker 		switch (child) {
141*49cdfc7eSAndroid Build Coastguard Worker 		case -1:
142*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
143*49cdfc7eSAndroid Build Coastguard Worker 		case 0:
144*49cdfc7eSAndroid Build Coastguard Worker 			do_child();
145*49cdfc7eSAndroid Build Coastguard Worker 			exit(0);
146*49cdfc7eSAndroid Build Coastguard Worker 		default:
147*49cdfc7eSAndroid Build Coastguard Worker 			break;
148*49cdfc7eSAndroid Build Coastguard Worker 		}
149*49cdfc7eSAndroid Build Coastguard Worker 	}
150*49cdfc7eSAndroid Build Coastguard Worker 
151*49cdfc7eSAndroid Build Coastguard Worker 	do_parent();
152*49cdfc7eSAndroid Build Coastguard Worker 
153*49cdfc7eSAndroid Build Coastguard Worker 	if (empty_read)
154*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN, "%d empty reads", empty_read);
155*49cdfc7eSAndroid Build Coastguard Worker 
156*49cdfc7eSAndroid Build Coastguard Worker 	if (error) {
157*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL, "%d data errors on pipe, read size = %d, %s %s",
158*49cdfc7eSAndroid Build Coastguard Worker 			 error, size, pipe_type, blk_type);
159*49cdfc7eSAndroid Build Coastguard Worker 	} else if (!quiet) {
160*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TPASS, "%d pipe reads complete, read size = %d, %s %s",
161*49cdfc7eSAndroid Build Coastguard Worker 			 count + 1, size, pipe_type, blk_type);
162*49cdfc7eSAndroid Build Coastguard Worker 	}
163*49cdfc7eSAndroid Build Coastguard Worker 
164*49cdfc7eSAndroid Build Coastguard Worker 	/*
165*49cdfc7eSAndroid Build Coastguard Worker 	 * wait for all children to finish, timeout after uwait_total
166*49cdfc7eSAndroid Build Coastguard Worker 	 * semtimedop might not be available everywhere
167*49cdfc7eSAndroid Build Coastguard Worker 	 */
168*49cdfc7eSAndroid Build Coastguard Worker 	for (j = 0; j < uwait_total; j += uwait_iter) {
169*49cdfc7eSAndroid Build Coastguard Worker 		if (semctl(sem_id, 1, GETVAL) == 0)
170*49cdfc7eSAndroid Build Coastguard Worker 			break;
171*49cdfc7eSAndroid Build Coastguard Worker 		usleep(uwait_iter);
172*49cdfc7eSAndroid Build Coastguard Worker 	}
173*49cdfc7eSAndroid Build Coastguard Worker 
174*49cdfc7eSAndroid Build Coastguard Worker 	if (j >= uwait_total) {
175*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN,
176*49cdfc7eSAndroid Build Coastguard Worker 			 "Timed out waiting for child processes to exit");
177*49cdfc7eSAndroid Build Coastguard Worker 	}
178*49cdfc7eSAndroid Build Coastguard Worker 
179*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
180*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
181*49cdfc7eSAndroid Build Coastguard Worker }
182*49cdfc7eSAndroid Build Coastguard Worker 
parse_options(int argc,char * argv[])183*49cdfc7eSAndroid Build Coastguard Worker static int parse_options(int argc, char *argv[])
184*49cdfc7eSAndroid Build Coastguard Worker {
185*49cdfc7eSAndroid Build Coastguard Worker 	char *cp;
186*49cdfc7eSAndroid Build Coastguard Worker 	int c;
187*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
188*49cdfc7eSAndroid Build Coastguard Worker 	static double d;
189*49cdfc7eSAndroid Build Coastguard Worker 
190*49cdfc7eSAndroid Build Coastguard Worker 	while ((c = getopt(argc, argv, "T:bc:D:he:Ef:i:I:ln:p:qs:uvW:w:"))
191*49cdfc7eSAndroid Build Coastguard Worker 	       != -1) {
192*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
193*49cdfc7eSAndroid Build Coastguard Worker 		case 'T':
194*49cdfc7eSAndroid Build Coastguard Worker 			TCID = optarg;
195*49cdfc7eSAndroid Build Coastguard Worker 			break;
196*49cdfc7eSAndroid Build Coastguard Worker 		case 'h':
197*49cdfc7eSAndroid Build Coastguard Worker 			help();
198*49cdfc7eSAndroid Build Coastguard Worker 			ret = 1;
199*49cdfc7eSAndroid Build Coastguard Worker 			break;
200*49cdfc7eSAndroid Build Coastguard Worker 		case 'D':	/* pipe name */
201*49cdfc7eSAndroid Build Coastguard Worker 			strcpy(pname, optarg);
202*49cdfc7eSAndroid Build Coastguard Worker 			break;
203*49cdfc7eSAndroid Build Coastguard Worker 		case 'b':	/* blocked */
204*49cdfc7eSAndroid Build Coastguard Worker 			ndelay = 0;
205*49cdfc7eSAndroid Build Coastguard Worker 			blk_type = BLOCKING_IO;
206*49cdfc7eSAndroid Build Coastguard Worker 			break;
207*49cdfc7eSAndroid Build Coastguard Worker 		case 'c':	/* number childern */
208*49cdfc7eSAndroid Build Coastguard Worker 			if (sscanf(optarg, "%d", &num_writers) != 1) {
209*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
210*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --c option invalid arg '%s'.\n",
211*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
212*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
213*49cdfc7eSAndroid Build Coastguard Worker 			} else if (num_writers <= 0) {
214*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --c option must be "
215*49cdfc7eSAndroid Build Coastguard Worker 					"greater than zero.\n", TCID);
216*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
217*49cdfc7eSAndroid Build Coastguard Worker 			}
218*49cdfc7eSAndroid Build Coastguard Worker 			break;
219*49cdfc7eSAndroid Build Coastguard Worker 		case 'e':	/* exit on error # */
220*49cdfc7eSAndroid Build Coastguard Worker 			if (sscanf(optarg, "%d", &exit_error) != 1) {
221*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
222*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --e option invalid arg '%s'.\n",
223*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
224*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
225*49cdfc7eSAndroid Build Coastguard Worker 			} else if (exit_error < 0) {
226*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --e option must be "
227*49cdfc7eSAndroid Build Coastguard Worker 					"greater than zero.\n", TCID);
228*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
229*49cdfc7eSAndroid Build Coastguard Worker 			}
230*49cdfc7eSAndroid Build Coastguard Worker 			break;
231*49cdfc7eSAndroid Build Coastguard Worker 		case 'E':
232*49cdfc7eSAndroid Build Coastguard Worker 			prt_examples();
233*49cdfc7eSAndroid Build Coastguard Worker 			ret = 1;
234*49cdfc7eSAndroid Build Coastguard Worker 			break;
235*49cdfc7eSAndroid Build Coastguard Worker 		case 'f':	/* format of buffer on error */
236*49cdfc7eSAndroid Build Coastguard Worker 			switch (optarg[0]) {
237*49cdfc7eSAndroid Build Coastguard Worker 			case 'x':
238*49cdfc7eSAndroid Build Coastguard Worker 			case 'X':
239*49cdfc7eSAndroid Build Coastguard Worker 				format = HEX;
240*49cdfc7eSAndroid Build Coastguard Worker 				break;
241*49cdfc7eSAndroid Build Coastguard Worker 			case 'o':
242*49cdfc7eSAndroid Build Coastguard Worker 			case 'O':
243*49cdfc7eSAndroid Build Coastguard Worker 				format = OCTAL;
244*49cdfc7eSAndroid Build Coastguard Worker 				break;
245*49cdfc7eSAndroid Build Coastguard Worker 			case 'd':
246*49cdfc7eSAndroid Build Coastguard Worker 			case 'D':
247*49cdfc7eSAndroid Build Coastguard Worker 				format = DECIMAL;
248*49cdfc7eSAndroid Build Coastguard Worker 				break;
249*49cdfc7eSAndroid Build Coastguard Worker 			case 'a':
250*49cdfc7eSAndroid Build Coastguard Worker 			case 'A':
251*49cdfc7eSAndroid Build Coastguard Worker 				format = ASCII;
252*49cdfc7eSAndroid Build Coastguard Worker 				break;
253*49cdfc7eSAndroid Build Coastguard Worker 			case 'n':	/* not output */
254*49cdfc7eSAndroid Build Coastguard Worker 			case 'N':
255*49cdfc7eSAndroid Build Coastguard Worker 				format = NO_OUT;
256*49cdfc7eSAndroid Build Coastguard Worker 				break;
257*49cdfc7eSAndroid Build Coastguard Worker 
258*49cdfc7eSAndroid Build Coastguard Worker 			default:
259*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
260*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --f option invalid arg '%s'.\n",
261*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
262*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "\tIt must be x(hex), o(octal),"
263*49cdfc7eSAndroid Build Coastguard Worker 					"d(decimal), a(ascii) or n(none) with "
264*49cdfc7eSAndroid Build Coastguard Worker 					"opt sz\n");
265*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
266*49cdfc7eSAndroid Build Coastguard Worker 				break;
267*49cdfc7eSAndroid Build Coastguard Worker 			}
268*49cdfc7eSAndroid Build Coastguard Worker 			cp = optarg;
269*49cdfc7eSAndroid Build Coastguard Worker 			cp++;
270*49cdfc7eSAndroid Build Coastguard Worker 			if (*cp) {
271*49cdfc7eSAndroid Build Coastguard Worker 				if (sscanf(cp, "%i", &format_size) != 1) {
272*49cdfc7eSAndroid Build Coastguard Worker 					fprintf(stderr, "%s: --f option invalid"
273*49cdfc7eSAndroid Build Coastguard Worker 						"arg '%s'.\n", TCID, optarg);
274*49cdfc7eSAndroid Build Coastguard Worker 					fprintf(stderr, "\tIt must be x(hex),"
275*49cdfc7eSAndroid Build Coastguard Worker 						"o(octal), d(decimal), a(ascii)"
276*49cdfc7eSAndroid Build Coastguard Worker 						" or n(none) with opt sz\n");
277*49cdfc7eSAndroid Build Coastguard Worker 					ret = 1;
278*49cdfc7eSAndroid Build Coastguard Worker 					break;
279*49cdfc7eSAndroid Build Coastguard Worker 				}
280*49cdfc7eSAndroid Build Coastguard Worker 			}
281*49cdfc7eSAndroid Build Coastguard Worker 			break;
282*49cdfc7eSAndroid Build Coastguard Worker 
283*49cdfc7eSAndroid Build Coastguard Worker 		case 'I':
284*49cdfc7eSAndroid Build Coastguard Worker 			iotype = lio_parse_io_arg1(optarg);
285*49cdfc7eSAndroid Build Coastguard Worker 			if (iotype == -1) {
286*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --I arg is invalid, "
287*49cdfc7eSAndroid Build Coastguard Worker 					"must be s, p, f, a, l, L or r.\n",
288*49cdfc7eSAndroid Build Coastguard Worker 					TCID);
289*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
290*49cdfc7eSAndroid Build Coastguard Worker 			}
291*49cdfc7eSAndroid Build Coastguard Worker 			break;
292*49cdfc7eSAndroid Build Coastguard Worker 
293*49cdfc7eSAndroid Build Coastguard Worker 		case 'l':	/* loop forever */
294*49cdfc7eSAndroid Build Coastguard Worker 			++loop;
295*49cdfc7eSAndroid Build Coastguard Worker 			break;
296*49cdfc7eSAndroid Build Coastguard Worker 
297*49cdfc7eSAndroid Build Coastguard Worker 		case 'i':
298*49cdfc7eSAndroid Build Coastguard Worker 		case 'n':	/* number writes per child */
299*49cdfc7eSAndroid Build Coastguard Worker 			if (sscanf(optarg, "%d", &num_writes) != 1) {
300*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --i/n option invalid "
301*49cdfc7eSAndroid Build Coastguard Worker 					"arg '%s'.\n", TCID, optarg);
302*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
303*49cdfc7eSAndroid Build Coastguard Worker 			} else if (num_writes < 0) {
304*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --i/n option must be "
305*49cdfc7eSAndroid Build Coastguard Worker 					"greater than equal to zero.\n",
306*49cdfc7eSAndroid Build Coastguard Worker 					TCID);
307*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
308*49cdfc7eSAndroid Build Coastguard Worker 			}
309*49cdfc7eSAndroid Build Coastguard Worker 
310*49cdfc7eSAndroid Build Coastguard Worker 			if (num_writes == 0)	/* loop forever */
311*49cdfc7eSAndroid Build Coastguard Worker 				++loop;
312*49cdfc7eSAndroid Build Coastguard Worker 			break;
313*49cdfc7eSAndroid Build Coastguard Worker 		case 'p':	/* ping */
314*49cdfc7eSAndroid Build Coastguard Worker 			if (sscanf(optarg, "%d", &num_rpt) != 1) {
315*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
316*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --p option invalid arg '%s'.\n",
317*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
318*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
319*49cdfc7eSAndroid Build Coastguard Worker 			} else if (num_rpt < 0) {
320*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --p option must be greater"
321*49cdfc7eSAndroid Build Coastguard Worker 					" than equal to zero.\n", TCID);
322*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
323*49cdfc7eSAndroid Build Coastguard Worker 			}
324*49cdfc7eSAndroid Build Coastguard Worker 			break;
325*49cdfc7eSAndroid Build Coastguard Worker 		case 'q':	/* Quiet - NOPASS */
326*49cdfc7eSAndroid Build Coastguard Worker 			quiet = 1;
327*49cdfc7eSAndroid Build Coastguard Worker 			break;
328*49cdfc7eSAndroid Build Coastguard Worker 		case 's':	/* size */
329*49cdfc7eSAndroid Build Coastguard Worker 			if (sscanf(optarg, "%d", &size) != 1) {
330*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
331*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --s option invalid arg '%s'.\n",
332*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
333*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
334*49cdfc7eSAndroid Build Coastguard Worker 			} else if (size <= 0) {
335*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --s option must be greater"
336*49cdfc7eSAndroid Build Coastguard Worker 					" than zero.\n", TCID);
337*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
338*49cdfc7eSAndroid Build Coastguard Worker 			}
339*49cdfc7eSAndroid Build Coastguard Worker 			break;
340*49cdfc7eSAndroid Build Coastguard Worker 		case 'u':
341*49cdfc7eSAndroid Build Coastguard Worker 			unpipe = 1;	/* un-named pipe */
342*49cdfc7eSAndroid Build Coastguard Worker 			break;
343*49cdfc7eSAndroid Build Coastguard Worker 		case 'v':	/* verbose */
344*49cdfc7eSAndroid Build Coastguard Worker 			verbose = 1;
345*49cdfc7eSAndroid Build Coastguard Worker 			break;
346*49cdfc7eSAndroid Build Coastguard Worker 		case 'W':	/* max wait time between reads */
347*49cdfc7eSAndroid Build Coastguard Worker 			d = strtod(optarg, &cp);
348*49cdfc7eSAndroid Build Coastguard Worker 			if (*cp != '\0') {
349*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
350*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --w option invalid arg '%s'.\n",
351*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
352*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
353*49cdfc7eSAndroid Build Coastguard Worker 			} else if (d < 0) {
354*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --w option must be greater"
355*49cdfc7eSAndroid Build Coastguard Worker 					" than zero.\n", TCID);
356*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
357*49cdfc7eSAndroid Build Coastguard Worker 			}
358*49cdfc7eSAndroid Build Coastguard Worker 			parent_wait = (int)(d * 1000000.0);
359*49cdfc7eSAndroid Build Coastguard Worker 			break;
360*49cdfc7eSAndroid Build Coastguard Worker 		case 'w':	/* max wait time between writes */
361*49cdfc7eSAndroid Build Coastguard Worker 			d = strtod(optarg, &cp);
362*49cdfc7eSAndroid Build Coastguard Worker 			if (*cp != '\0') {
363*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr,
364*49cdfc7eSAndroid Build Coastguard Worker 					"%s: --w option invalid arg '%s'.\n",
365*49cdfc7eSAndroid Build Coastguard Worker 					TCID, optarg);
366*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
367*49cdfc7eSAndroid Build Coastguard Worker 			} else if (d < 0) {
368*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "%s: --w option must be greater"
369*49cdfc7eSAndroid Build Coastguard Worker 					" than zero.\n", TCID);
370*49cdfc7eSAndroid Build Coastguard Worker 				ret = 1;
371*49cdfc7eSAndroid Build Coastguard Worker 			}
372*49cdfc7eSAndroid Build Coastguard Worker 			chld_wait = (int)(d * 1000000.0);
373*49cdfc7eSAndroid Build Coastguard Worker 			break;
374*49cdfc7eSAndroid Build Coastguard Worker 		case '?':
375*49cdfc7eSAndroid Build Coastguard Worker 			ret = 1;
376*49cdfc7eSAndroid Build Coastguard Worker 			break;
377*49cdfc7eSAndroid Build Coastguard Worker 		}
378*49cdfc7eSAndroid Build Coastguard Worker 
379*49cdfc7eSAndroid Build Coastguard Worker 		if (ret == 1) {
380*49cdfc7eSAndroid Build Coastguard Worker 			usage();
381*49cdfc7eSAndroid Build Coastguard Worker 			return ret;
382*49cdfc7eSAndroid Build Coastguard Worker 		}
383*49cdfc7eSAndroid Build Coastguard Worker 	}
384*49cdfc7eSAndroid Build Coastguard Worker 
385*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
386*49cdfc7eSAndroid Build Coastguard Worker }
387*49cdfc7eSAndroid Build Coastguard Worker 
setup(int argc,char * argv[])388*49cdfc7eSAndroid Build Coastguard Worker static void setup(int argc, char *argv[])
389*49cdfc7eSAndroid Build Coastguard Worker {
390*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
391*49cdfc7eSAndroid Build Coastguard Worker 	char *toutput;
392*49cdfc7eSAndroid Build Coastguard Worker 	int fds[2];
393*49cdfc7eSAndroid Build Coastguard Worker 
394*49cdfc7eSAndroid Build Coastguard Worker 	tst_sig(FORK, DEF_HANDLER, cleanup);
395*49cdfc7eSAndroid Build Coastguard Worker 
396*49cdfc7eSAndroid Build Coastguard Worker 	TEST_PAUSE;
397*49cdfc7eSAndroid Build Coastguard Worker 
398*49cdfc7eSAndroid Build Coastguard Worker 	tst_tmpdir();
399*49cdfc7eSAndroid Build Coastguard Worker 
400*49cdfc7eSAndroid Build Coastguard Worker 	if (signal(SIGCHLD, sig_child) == SIG_ERR) {
401*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
402*49cdfc7eSAndroid Build Coastguard Worker 			 "set signal handler for SIGCHLD failed");
403*49cdfc7eSAndroid Build Coastguard Worker 	}
404*49cdfc7eSAndroid Build Coastguard Worker 
405*49cdfc7eSAndroid Build Coastguard Worker 	toutput = getenv("TOUTPUT");
406*49cdfc7eSAndroid Build Coastguard Worker 	if (toutput != NULL && strcmp(toutput, "NOPASS") == 0)
407*49cdfc7eSAndroid Build Coastguard Worker 		quiet = 1;
408*49cdfc7eSAndroid Build Coastguard Worker 
409*49cdfc7eSAndroid Build Coastguard Worker 	sprintf(pname, "%s", "tpipe");
410*49cdfc7eSAndroid Build Coastguard Worker 
411*49cdfc7eSAndroid Build Coastguard Worker 	ret = parse_options(argc, argv);
412*49cdfc7eSAndroid Build Coastguard Worker 	if (ret == 1)
413*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, cleanup, "options parse error");
414*49cdfc7eSAndroid Build Coastguard Worker 
415*49cdfc7eSAndroid Build Coastguard Worker 	if (format_size == -1)
416*49cdfc7eSAndroid Build Coastguard Worker 		format_size = size;
417*49cdfc7eSAndroid Build Coastguard Worker 
418*49cdfc7eSAndroid Build Coastguard Worker 	/*
419*49cdfc7eSAndroid Build Coastguard Worker 	 * If there is more than one writer, all writes and reads
420*49cdfc7eSAndroid Build Coastguard Worker 	 * must be the same size.  Only writes of a size <= PIPE_BUF
421*49cdfc7eSAndroid Build Coastguard Worker 	 * are atomic.  T
422*49cdfc7eSAndroid Build Coastguard Worker 	 * Therefore, if size is greater than PIPE_BUF, we will break
423*49cdfc7eSAndroid Build Coastguard Worker 	 * the writes into PIPE_BUF chunks.  We will also increase the
424*49cdfc7eSAndroid Build Coastguard Worker 	 * number of writes to ensure the same (or more) amount of
425*49cdfc7eSAndroid Build Coastguard Worker 	 * data is written.  This is the same as erroring and telling
426*49cdfc7eSAndroid Build Coastguard Worker 	 * the user the new cmd line to do the same thing.
427*49cdfc7eSAndroid Build Coastguard Worker 	 * Example:
428*49cdfc7eSAndroid Build Coastguard Worker 	 *      pipeio -s 5000 -n 10 -c 5
429*49cdfc7eSAndroid Build Coastguard Worker 	 *      (each child will write at least 50000 bytes, since all
430*49cdfc7eSAndroid Build Coastguard Worker 	 *      writes have to be in 4096 chuncks or 13*4096 (53248)
431*49cdfc7eSAndroid Build Coastguard Worker 	 *      bytes will be written.)  This is the same as:
432*49cdfc7eSAndroid Build Coastguard Worker 	 *      pipeio -s 4096 -n 13 -c 5
433*49cdfc7eSAndroid Build Coastguard Worker 	 */
434*49cdfc7eSAndroid Build Coastguard Worker 	if (size > PIPE_BUF && num_writers > 1) {
435*49cdfc7eSAndroid Build Coastguard Worker 		if (!loop) {
436*49cdfc7eSAndroid Build Coastguard Worker 			/*
437*49cdfc7eSAndroid Build Coastguard Worker 			 * we must set num_writes*num_writers
438*49cdfc7eSAndroid Build Coastguard Worker 			 * doesn't overflow later
439*49cdfc7eSAndroid Build Coastguard Worker 			 */
440*49cdfc7eSAndroid Build Coastguard Worker 			num_writes = MIN(((long long)num_writes * size +
441*49cdfc7eSAndroid Build Coastguard Worker 					 PIPE_BUF - 1) / PIPE_BUF,
442*49cdfc7eSAndroid Build Coastguard Worker 					 INT_MAX / num_writers);
443*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TINFO, "adjusting i/o size to %d, and # of "
444*49cdfc7eSAndroid Build Coastguard Worker 				 "writes to %d", PIPE_BUF, num_writes);
445*49cdfc7eSAndroid Build Coastguard Worker 		} else {
446*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TINFO, "adjusting i/o size to %d", PIPE_BUF);
447*49cdfc7eSAndroid Build Coastguard Worker 		}
448*49cdfc7eSAndroid Build Coastguard Worker 		size = PIPE_BUF;
449*49cdfc7eSAndroid Build Coastguard Worker 	}
450*49cdfc7eSAndroid Build Coastguard Worker 
451*49cdfc7eSAndroid Build Coastguard Worker 	writebuf = SAFE_MALLOC(cleanup, size);
452*49cdfc7eSAndroid Build Coastguard Worker 	readbuf = SAFE_MALLOC(cleanup, size);
453*49cdfc7eSAndroid Build Coastguard Worker 
454*49cdfc7eSAndroid Build Coastguard Worker 	memset(writebuf, 'Z', size);
455*49cdfc7eSAndroid Build Coastguard Worker 	writebuf[size - 1] = 'A';
456*49cdfc7eSAndroid Build Coastguard Worker 
457*49cdfc7eSAndroid Build Coastguard Worker 	sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | S_IRWXU);
458*49cdfc7eSAndroid Build Coastguard Worker 	if (sem_id == -1) {
459*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
460*49cdfc7eSAndroid Build Coastguard Worker 			 "Couldn't allocate semaphore");
461*49cdfc7eSAndroid Build Coastguard Worker 	}
462*49cdfc7eSAndroid Build Coastguard Worker 
463*49cdfc7eSAndroid Build Coastguard Worker 	if (semctl(sem_id, 0, SETVAL, u) == -1) {
464*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
465*49cdfc7eSAndroid Build Coastguard Worker 			 "Couldn't initialize semaphore 0 value");
466*49cdfc7eSAndroid Build Coastguard Worker 	}
467*49cdfc7eSAndroid Build Coastguard Worker 
468*49cdfc7eSAndroid Build Coastguard Worker 	if (semctl(sem_id, 1, SETVAL, u) == -1) {
469*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
470*49cdfc7eSAndroid Build Coastguard Worker 			 "Couldn't initialize semaphore 1 value");
471*49cdfc7eSAndroid Build Coastguard Worker 	}
472*49cdfc7eSAndroid Build Coastguard Worker 
473*49cdfc7eSAndroid Build Coastguard Worker 	if (unpipe) {
474*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_PIPE(cleanup, fds);
475*49cdfc7eSAndroid Build Coastguard Worker 		read_fd = fds[0];
476*49cdfc7eSAndroid Build Coastguard Worker 		write_fd = fds[1];
477*49cdfc7eSAndroid Build Coastguard Worker 		pipe_type = PIPE_UNNAMED;
478*49cdfc7eSAndroid Build Coastguard Worker 		blk_type = UNNAMED_IO;
479*49cdfc7eSAndroid Build Coastguard Worker 	} else {
480*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_MKFIFO(cleanup, pname, 0777);
481*49cdfc7eSAndroid Build Coastguard Worker 		pipe_type = PIPE_NAMED;
482*49cdfc7eSAndroid Build Coastguard Worker 	}
483*49cdfc7eSAndroid Build Coastguard Worker }
484*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)485*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
486*49cdfc7eSAndroid Build Coastguard Worker {
487*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FREE(writebuf);
488*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_FREE(readbuf);
489*49cdfc7eSAndroid Build Coastguard Worker 
490*49cdfc7eSAndroid Build Coastguard Worker 	semctl(sem_id, 0, IPC_RMID);
491*49cdfc7eSAndroid Build Coastguard Worker 
492*49cdfc7eSAndroid Build Coastguard Worker 	if (!unpipe)
493*49cdfc7eSAndroid Build Coastguard Worker 		unlink(pname);
494*49cdfc7eSAndroid Build Coastguard Worker 
495*49cdfc7eSAndroid Build Coastguard Worker 	tst_rmdir();
496*49cdfc7eSAndroid Build Coastguard Worker }
497*49cdfc7eSAndroid Build Coastguard Worker 
do_child(void)498*49cdfc7eSAndroid Build Coastguard Worker static void do_child(void)
499*49cdfc7eSAndroid Build Coastguard Worker {
500*49cdfc7eSAndroid Build Coastguard Worker 	int *count_word;        /* holds address where to write writers count */
501*49cdfc7eSAndroid Build Coastguard Worker 	int *pid_word;          /* holds address where to write writers pid */
502*49cdfc7eSAndroid Build Coastguard Worker 	int nb, j;
503*49cdfc7eSAndroid Build Coastguard Worker 	long clock;
504*49cdfc7eSAndroid Build Coastguard Worker 	char *cp;
505*49cdfc7eSAndroid Build Coastguard Worker 	long int n;
506*49cdfc7eSAndroid Build Coastguard Worker 	struct sembuf sem_op;
507*49cdfc7eSAndroid Build Coastguard Worker 	pid_t self_pid =  getpid();
508*49cdfc7eSAndroid Build Coastguard Worker 
509*49cdfc7eSAndroid Build Coastguard Worker 	if (!unpipe) {
510*49cdfc7eSAndroid Build Coastguard Worker 		write_fd = open(pname, O_WRONLY);
511*49cdfc7eSAndroid Build Coastguard Worker 		if (write_fd == -1) {
512*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "child pipe open(%s, %#o) failed",
513*49cdfc7eSAndroid Build Coastguard Worker 				pname, O_WRONLY | ndelay);
514*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
515*49cdfc7eSAndroid Build Coastguard Worker 		}
516*49cdfc7eSAndroid Build Coastguard Worker 		if (ndelay && fcntl(write_fd, F_SETFL, O_NONBLOCK) == -1) {
517*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "Failed setting the pipe to "
518*49cdfc7eSAndroid Build Coastguard Worker 				"nonblocking mode");
519*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
520*49cdfc7eSAndroid Build Coastguard Worker 		}
521*49cdfc7eSAndroid Build Coastguard Worker 	} else {
522*49cdfc7eSAndroid Build Coastguard Worker 		close(read_fd);
523*49cdfc7eSAndroid Build Coastguard Worker 	}
524*49cdfc7eSAndroid Build Coastguard Worker 
525*49cdfc7eSAndroid Build Coastguard Worker 	sem_op = (struct sembuf) {
526*49cdfc7eSAndroid Build Coastguard Worker 		 .sem_num = 0, .sem_op = 1, .sem_flg = 0};
527*49cdfc7eSAndroid Build Coastguard Worker 
528*49cdfc7eSAndroid Build Coastguard Worker 	if (semop(sem_id, &sem_op, 1) == -1) {
529*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "child: %d couldn't raise the semaphore 0",
530*49cdfc7eSAndroid Build Coastguard Worker 			self_pid);
531*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
532*49cdfc7eSAndroid Build Coastguard Worker 	}
533*49cdfc7eSAndroid Build Coastguard Worker 
534*49cdfc7eSAndroid Build Coastguard Worker 	pid_word = (int *)&writebuf[0];
535*49cdfc7eSAndroid Build Coastguard Worker 	count_word = (int *)&writebuf[NBPW];
536*49cdfc7eSAndroid Build Coastguard Worker 
537*49cdfc7eSAndroid Build Coastguard Worker 	for (j = 0; j < num_writes || loop; ++j) {
538*49cdfc7eSAndroid Build Coastguard Worker 		/*
539*49cdfc7eSAndroid Build Coastguard Worker 		 * writes are only in one unit when the size of the write
540*49cdfc7eSAndroid Build Coastguard Worker 		 * is <= PIPE_BUF.
541*49cdfc7eSAndroid Build Coastguard Worker 		 * Therefore, if size is greater than PIPE_BUF, we will break
542*49cdfc7eSAndroid Build Coastguard Worker 		 * the writes into PIPE_BUF chunks.
543*49cdfc7eSAndroid Build Coastguard Worker 		 * All writes and read need to be same size.
544*49cdfc7eSAndroid Build Coastguard Worker 		 */
545*49cdfc7eSAndroid Build Coastguard Worker 
546*49cdfc7eSAndroid Build Coastguard Worker 		/*
547*49cdfc7eSAndroid Build Coastguard Worker 		 * write pid and count in first two
548*49cdfc7eSAndroid Build Coastguard Worker 		 * words of buffer
549*49cdfc7eSAndroid Build Coastguard Worker 		 */
550*49cdfc7eSAndroid Build Coastguard Worker 		*count_word = j;
551*49cdfc7eSAndroid Build Coastguard Worker 		*pid_word = self_pid;
552*49cdfc7eSAndroid Build Coastguard Worker 
553*49cdfc7eSAndroid Build Coastguard Worker 		nb = lio_write_buffer(write_fd, iotype, writebuf, size,
554*49cdfc7eSAndroid Build Coastguard Worker 				      SIGUSR1, &cp, 0);
555*49cdfc7eSAndroid Build Coastguard Worker 		if (nb < 0) {
556*49cdfc7eSAndroid Build Coastguard Worker 			/*
557*49cdfc7eSAndroid Build Coastguard Worker 			 * If lio_write_buffer returns a negative number,
558*49cdfc7eSAndroid Build Coastguard Worker 			 * the return will be -errno.
559*49cdfc7eSAndroid Build Coastguard Worker 			 */
560*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "pass %d: lio_write_buffer(%s) failed;"
561*49cdfc7eSAndroid Build Coastguard Worker 				" it returned %d: %s",
562*49cdfc7eSAndroid Build Coastguard Worker 				j, cp, nb, strerror(-nb));
563*49cdfc7eSAndroid Build Coastguard Worker 				exit(1);
564*49cdfc7eSAndroid Build Coastguard Worker 		} else if (nb != size) {
565*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "pass %d: lio_write_buffer(%s) failed,"
566*49cdfc7eSAndroid Build Coastguard Worker 				" write count %d, but expected to write %d",
567*49cdfc7eSAndroid Build Coastguard Worker 				j, cp, nb, size);
568*49cdfc7eSAndroid Build Coastguard Worker 		}
569*49cdfc7eSAndroid Build Coastguard Worker 		if (verbose) {
570*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "pass %d: pid %d: wrote %d bytes,"
571*49cdfc7eSAndroid Build Coastguard Worker 				"expected %d bytes",
572*49cdfc7eSAndroid Build Coastguard Worker 				j, self_pid, nb, size);
573*49cdfc7eSAndroid Build Coastguard Worker 		}
574*49cdfc7eSAndroid Build Coastguard Worker 
575*49cdfc7eSAndroid Build Coastguard Worker 		if (chld_wait) {
576*49cdfc7eSAndroid Build Coastguard Worker 			clock = time(0);
577*49cdfc7eSAndroid Build Coastguard Worker 			srand48(clock);
578*49cdfc7eSAndroid Build Coastguard Worker 			n = lrand48() % chld_wait;
579*49cdfc7eSAndroid Build Coastguard Worker 			usleep(n);
580*49cdfc7eSAndroid Build Coastguard Worker 		}
581*49cdfc7eSAndroid Build Coastguard Worker 		fflush(stderr);
582*49cdfc7eSAndroid Build Coastguard Worker 	}
583*49cdfc7eSAndroid Build Coastguard Worker 
584*49cdfc7eSAndroid Build Coastguard Worker 	/* child waits until parent completes open() */
585*49cdfc7eSAndroid Build Coastguard Worker 	sem_op = (struct sembuf) {
586*49cdfc7eSAndroid Build Coastguard Worker 		  .sem_num = 1, .sem_op = -1, .sem_flg = 0};
587*49cdfc7eSAndroid Build Coastguard Worker 	if (semop(sem_id, &sem_op, 1) == -1)
588*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Couldn't lower the semaphore 1");
589*49cdfc7eSAndroid Build Coastguard Worker 
590*49cdfc7eSAndroid Build Coastguard Worker 	exit(0);
591*49cdfc7eSAndroid Build Coastguard Worker }
592*49cdfc7eSAndroid Build Coastguard Worker 
check_rw_buf(void)593*49cdfc7eSAndroid Build Coastguard Worker static int check_rw_buf(void)
594*49cdfc7eSAndroid Build Coastguard Worker {
595*49cdfc7eSAndroid Build Coastguard Worker 	int i;
596*49cdfc7eSAndroid Build Coastguard Worker 
597*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 2 * NBPW; i < size; ++i) {
598*49cdfc7eSAndroid Build Coastguard Worker 		if (writebuf[i] != readbuf[i]) {
599*49cdfc7eSAndroid Build Coastguard Worker 			++error;
600*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL,
601*49cdfc7eSAndroid Build Coastguard Worker 				 "FAIL data error on byte %d; rd# %d, sz= %d, "
602*49cdfc7eSAndroid Build Coastguard Worker 				 "%s %s empty_reads= %d, err= %d",
603*49cdfc7eSAndroid Build Coastguard Worker 				 i, count, size, pipe_type, blk_type,
604*49cdfc7eSAndroid Build Coastguard Worker 				 empty_read, error);
605*49cdfc7eSAndroid Build Coastguard Worker 			prt_buf(&readbuf, readbuf, format_size, format);
606*49cdfc7eSAndroid Build Coastguard Worker 			fflush(stdout);
607*49cdfc7eSAndroid Build Coastguard Worker 			return 1;
608*49cdfc7eSAndroid Build Coastguard Worker 		}
609*49cdfc7eSAndroid Build Coastguard Worker 	}
610*49cdfc7eSAndroid Build Coastguard Worker 
611*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
612*49cdfc7eSAndroid Build Coastguard Worker }
613*49cdfc7eSAndroid Build Coastguard Worker 
do_parent(void)614*49cdfc7eSAndroid Build Coastguard Worker static void do_parent(void)
615*49cdfc7eSAndroid Build Coastguard Worker {
616*49cdfc7eSAndroid Build Coastguard Worker 	int i, nb;
617*49cdfc7eSAndroid Build Coastguard Worker 	long clock;
618*49cdfc7eSAndroid Build Coastguard Worker 	time_t start_time, current_time, diff_time;
619*49cdfc7eSAndroid Build Coastguard Worker 	char *cp;
620*49cdfc7eSAndroid Build Coastguard Worker 	long int n;
621*49cdfc7eSAndroid Build Coastguard Worker 	struct sembuf sem_op;
622*49cdfc7eSAndroid Build Coastguard Worker 
623*49cdfc7eSAndroid Build Coastguard Worker 	start_time = time(0);
624*49cdfc7eSAndroid Build Coastguard Worker 	if (!unpipe) {
625*49cdfc7eSAndroid Build Coastguard Worker 		read_fd = SAFE_OPEN(cleanup, pname, O_RDONLY);
626*49cdfc7eSAndroid Build Coastguard Worker 		if (ndelay && fcntl(read_fd, F_SETFL, O_NONBLOCK) == -1) {
627*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, cleanup,
628*49cdfc7eSAndroid Build Coastguard Worker 				 "Failed setting the pipe to nonblocking mode");
629*49cdfc7eSAndroid Build Coastguard Worker 		}
630*49cdfc7eSAndroid Build Coastguard Worker 	} else {
631*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(cleanup, write_fd);
632*49cdfc7eSAndroid Build Coastguard Worker 	}
633*49cdfc7eSAndroid Build Coastguard Worker 
634*49cdfc7eSAndroid Build Coastguard Worker 	/* raise semaphore so children can exit */
635*49cdfc7eSAndroid Build Coastguard Worker 	sem_op = (struct sembuf) {
636*49cdfc7eSAndroid Build Coastguard Worker 		  .sem_num = 1, .sem_op = num_writers, .sem_flg = 0};
637*49cdfc7eSAndroid Build Coastguard Worker 	if (semop(sem_id, &sem_op, 1) == -1) {
638*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
639*49cdfc7eSAndroid Build Coastguard Worker 			 "Couldn't raise the semaphore 1");
640*49cdfc7eSAndroid Build Coastguard Worker 	}
641*49cdfc7eSAndroid Build Coastguard Worker 
642*49cdfc7eSAndroid Build Coastguard Worker 	sem_op = (struct sembuf) {
643*49cdfc7eSAndroid Build Coastguard Worker 		  .sem_num = 0, .sem_op = -num_writers, .sem_flg = 0};
644*49cdfc7eSAndroid Build Coastguard Worker 
645*49cdfc7eSAndroid Build Coastguard Worker 	while (nchildcompleted < num_writers
646*49cdfc7eSAndroid Build Coastguard Worker 	       && semop(sem_id, &sem_op, 1) == -1) {
647*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == EINTR)
648*49cdfc7eSAndroid Build Coastguard Worker 			continue;
649*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup,
650*49cdfc7eSAndroid Build Coastguard Worker 			 "Couldn't wait on semaphore 0");
651*49cdfc7eSAndroid Build Coastguard Worker 	}
652*49cdfc7eSAndroid Build Coastguard Worker 
653*49cdfc7eSAndroid Build Coastguard Worker 	/* parent start to read pipe */
654*49cdfc7eSAndroid Build Coastguard Worker 	for (i = num_writers * num_writes; i > 0 || loop; --i) {
655*49cdfc7eSAndroid Build Coastguard Worker 		if (error >= MAX_ERRS || empty_read >= MAX_EMPTY)
656*49cdfc7eSAndroid Build Coastguard Worker 			break;
657*49cdfc7eSAndroid Build Coastguard Worker 		if (parent_wait) {
658*49cdfc7eSAndroid Build Coastguard Worker 			clock = time(0);
659*49cdfc7eSAndroid Build Coastguard Worker 			srand48(clock);
660*49cdfc7eSAndroid Build Coastguard Worker 			n = lrand48() % parent_wait;
661*49cdfc7eSAndroid Build Coastguard Worker 			usleep(n);
662*49cdfc7eSAndroid Build Coastguard Worker 		}
663*49cdfc7eSAndroid Build Coastguard Worker 		++count;
664*49cdfc7eSAndroid Build Coastguard Worker 		nb = lio_read_buffer(read_fd, iotype, readbuf, size,
665*49cdfc7eSAndroid Build Coastguard Worker 				     SIGUSR1, &cp, 0);
666*49cdfc7eSAndroid Build Coastguard Worker 		if (nb < 0) {
667*49cdfc7eSAndroid Build Coastguard Worker 			/*
668*49cdfc7eSAndroid Build Coastguard Worker 			 * If lio_read_buffer returns a negative number,
669*49cdfc7eSAndroid Build Coastguard Worker 			 * the return will be -errno.
670*49cdfc7eSAndroid Build Coastguard Worker 			 */
671*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL, "pass %d: lio_read_buffer(%s) failed; "
672*49cdfc7eSAndroid Build Coastguard Worker 				 "returned %d: %s", i, cp, nb, strerror(-nb));
673*49cdfc7eSAndroid Build Coastguard Worker 			++i;
674*49cdfc7eSAndroid Build Coastguard Worker 			count--;
675*49cdfc7eSAndroid Build Coastguard Worker 			error++;
676*49cdfc7eSAndroid Build Coastguard Worker 			continue;
677*49cdfc7eSAndroid Build Coastguard Worker 		} else {
678*49cdfc7eSAndroid Build Coastguard Worker 			if (nb == 0) {
679*49cdfc7eSAndroid Build Coastguard Worker 				if (nchildcompleted >= num_writers && !loop) {
680*49cdfc7eSAndroid Build Coastguard Worker 					tst_resm(TWARN, "The children have "
681*49cdfc7eSAndroid Build Coastguard Worker 						 "died prematurely");
682*49cdfc7eSAndroid Build Coastguard Worker 					break;	/* All children have died */
683*49cdfc7eSAndroid Build Coastguard Worker 				}
684*49cdfc7eSAndroid Build Coastguard Worker 				empty_read++;
685*49cdfc7eSAndroid Build Coastguard Worker 				++i;
686*49cdfc7eSAndroid Build Coastguard Worker 				count--;
687*49cdfc7eSAndroid Build Coastguard Worker 				continue;
688*49cdfc7eSAndroid Build Coastguard Worker 			} else if (nb < size && size <= PIPE_BUF) {
689*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TFAIL, "pass %d: partial read from the"
690*49cdfc7eSAndroid Build Coastguard Worker 					" pipe: read %d bytes, expected %d, "
691*49cdfc7eSAndroid Build Coastguard Worker 					"read count %d", i, nb, size, count);
692*49cdfc7eSAndroid Build Coastguard Worker 				++error;
693*49cdfc7eSAndroid Build Coastguard Worker 			} else if (nb == size) {
694*49cdfc7eSAndroid Build Coastguard Worker 				check_rw_buf();
695*49cdfc7eSAndroid Build Coastguard Worker 				if (exit_error && exit_error == error)
696*49cdfc7eSAndroid Build Coastguard Worker 					return;
697*49cdfc7eSAndroid Build Coastguard Worker 			}
698*49cdfc7eSAndroid Build Coastguard Worker 
699*49cdfc7eSAndroid Build Coastguard Worker 			if (verbose || (num_rpt && !(count % num_rpt))) {
700*49cdfc7eSAndroid Build Coastguard Worker 				current_time = time(0);
701*49cdfc7eSAndroid Build Coastguard Worker 				diff_time = current_time - start_time;
702*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TFAIL,
703*49cdfc7eSAndroid Build Coastguard Worker 					 "(%d) rd# %d, sz= %d, %s %s "
704*49cdfc7eSAndroid Build Coastguard Worker 					 "empty_reads= %d, err= %d\n",
705*49cdfc7eSAndroid Build Coastguard Worker 					 (int)diff_time, count, size,
706*49cdfc7eSAndroid Build Coastguard Worker 					 pipe_type, blk_type,
707*49cdfc7eSAndroid Build Coastguard Worker 					 empty_read, error);
708*49cdfc7eSAndroid Build Coastguard Worker 				fflush(stdout);
709*49cdfc7eSAndroid Build Coastguard Worker 			}
710*49cdfc7eSAndroid Build Coastguard Worker 		}
711*49cdfc7eSAndroid Build Coastguard Worker 	}
712*49cdfc7eSAndroid Build Coastguard Worker 
713*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_CLOSE(cleanup, read_fd);
714*49cdfc7eSAndroid Build Coastguard Worker }
715*49cdfc7eSAndroid Build Coastguard Worker 
usage(void)716*49cdfc7eSAndroid Build Coastguard Worker static void usage(void)
717*49cdfc7eSAndroid Build Coastguard Worker {
718*49cdfc7eSAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: %s [-bEv][-c #writers][-D pname][-h]"
719*49cdfc7eSAndroid Build Coastguard Worker 		"[-e exit_num][-f fmt][-l][-i #writes][-n #writes][-p num_rpt]"
720*49cdfc7eSAndroid Build Coastguard Worker 		"\n\t[-s size][-W max_wait][-w max_wait][-u]\n", TCID);
721*49cdfc7eSAndroid Build Coastguard Worker 	fflush(stderr);
722*49cdfc7eSAndroid Build Coastguard Worker }
723*49cdfc7eSAndroid Build Coastguard Worker 
help(void)724*49cdfc7eSAndroid Build Coastguard Worker static void help(void)
725*49cdfc7eSAndroid Build Coastguard Worker {
726*49cdfc7eSAndroid Build Coastguard Worker 	usage();
727*49cdfc7eSAndroid Build Coastguard Worker 
728*49cdfc7eSAndroid Build Coastguard Worker 	printf(" -b    - blocking reads and writes. default non-block\n\
729*49cdfc7eSAndroid Build Coastguard Worker   -c #writers  - number of writers (childern)\n\
730*49cdfc7eSAndroid Build Coastguard Worker   -D pname     - name of fifo (def tpipe<pid>)\n\
731*49cdfc7eSAndroid Build Coastguard Worker   -h           - print this help message\n\
732*49cdfc7eSAndroid Build Coastguard Worker   -e exit_num  - exit on error exit_num, 0 is ignore errors, 1 is default.\n\
733*49cdfc7eSAndroid Build Coastguard Worker   -E           - print cmd line examples and exit\n\
734*49cdfc7eSAndroid Build Coastguard Worker   -f format    - define format of bad buffer: h(hex), o(octal)\n\
735*49cdfc7eSAndroid Build Coastguard Worker                  d(decimal), a(ascii), n (none). hex is default\n\
736*49cdfc7eSAndroid Build Coastguard Worker 	         option size can be added to control output\n\
737*49cdfc7eSAndroid Build Coastguard Worker   -i #writes   - number write per child, zero means forever.\n\
738*49cdfc7eSAndroid Build Coastguard Worker   -I io_type   - Specifies io type: s - sync, p - polled async, a - async (def s)\n\
739*49cdfc7eSAndroid Build Coastguard Worker                  l - listio sync, L - listio async, r - random\n\
740*49cdfc7eSAndroid Build Coastguard Worker   -l           - loop forever (implied by -n 0).\n\
741*49cdfc7eSAndroid Build Coastguard Worker   -n #writes   - same as -i (for compatability).\n\
742*49cdfc7eSAndroid Build Coastguard Worker   -p num_rpt   - number of reads before a report\n\
743*49cdfc7eSAndroid Build Coastguard Worker   -q           - quiet mode, no PASS results are printed\n\
744*49cdfc7eSAndroid Build Coastguard Worker   -s size      - size of read and write (def 327)\n\
745*49cdfc7eSAndroid Build Coastguard Worker                  if size >= 4096, i/o will be in 4096 chuncks\n\
746*49cdfc7eSAndroid Build Coastguard Worker   -w max_wait  - max time (seconds) for sleep between writes.\n\
747*49cdfc7eSAndroid Build Coastguard Worker                  max_wait is interpreted as a double with ms accuracy.\n\
748*49cdfc7eSAndroid Build Coastguard Worker   -W max_wait  - max time (seconds) for sleep between reads\n\
749*49cdfc7eSAndroid Build Coastguard Worker                  max_wait is interpreted as a double with ms accuracy.\n\
750*49cdfc7eSAndroid Build Coastguard Worker   -u           - un-named pipe instead of named pipe\n\
751*49cdfc7eSAndroid Build Coastguard Worker   -v           - verbose mode, all writes/reads resutlts printed\n");
752*49cdfc7eSAndroid Build Coastguard Worker 
753*49cdfc7eSAndroid Build Coastguard Worker 	fflush(stdout);
754*49cdfc7eSAndroid Build Coastguard Worker }
755*49cdfc7eSAndroid Build Coastguard Worker 
prt_buf(char ** addr,char * buf,int length,int format)756*49cdfc7eSAndroid Build Coastguard Worker static void prt_buf(char **addr, char *buf, int length, int format)
757*49cdfc7eSAndroid Build Coastguard Worker {
758*49cdfc7eSAndroid Build Coastguard Worker 	int i;
759*49cdfc7eSAndroid Build Coastguard Worker 	int num_words = length / NBPW;	/* given length in bytes, get length in words */
760*49cdfc7eSAndroid Build Coastguard Worker 	int width;		/* number of columns */
761*49cdfc7eSAndroid Build Coastguard Worker 	int extra_words = 0;	/* odd or even number of words */
762*49cdfc7eSAndroid Build Coastguard Worker 	char *a = buf;
763*49cdfc7eSAndroid Build Coastguard Worker 	char b[NBPW];
764*49cdfc7eSAndroid Build Coastguard Worker 	char c[NBPW * 2];
765*49cdfc7eSAndroid Build Coastguard Worker 	char *p;
766*49cdfc7eSAndroid Build Coastguard Worker 	long *word;
767*49cdfc7eSAndroid Build Coastguard Worker 
768*49cdfc7eSAndroid Build Coastguard Worker 	if (format == NO_OUT)	/* if no output wanted, return */
769*49cdfc7eSAndroid Build Coastguard Worker 		return;
770*49cdfc7eSAndroid Build Coastguard Worker 
771*49cdfc7eSAndroid Build Coastguard Worker 	if (length % NBPW)
772*49cdfc7eSAndroid Build Coastguard Worker 		++num_words;	/* is length in full words? */
773*49cdfc7eSAndroid Build Coastguard Worker 	if (format == ASCII) {
774*49cdfc7eSAndroid Build Coastguard Worker 		width = 3;
775*49cdfc7eSAndroid Build Coastguard Worker 	} else {
776*49cdfc7eSAndroid Build Coastguard Worker 		width = 2;
777*49cdfc7eSAndroid Build Coastguard Worker 		/* do we have an odd number of words? */
778*49cdfc7eSAndroid Build Coastguard Worker 		extra_words = num_words % width;
779*49cdfc7eSAndroid Build Coastguard Worker 	}
780*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < num_words; ++i, a += NBPW, addr++) {
781*49cdfc7eSAndroid Build Coastguard Worker 		word = (long *)a;
782*49cdfc7eSAndroid Build Coastguard Worker 		if (!(i % width)) {
783*49cdfc7eSAndroid Build Coastguard Worker 			if (i > 0 && format != ASCII) {
784*49cdfc7eSAndroid Build Coastguard Worker 				/*
785*49cdfc7eSAndroid Build Coastguard Worker 				 * print the ascii equivalent of the data
786*49cdfc7eSAndroid Build Coastguard Worker 				 * before beginning the next line of output.
787*49cdfc7eSAndroid Build Coastguard Worker 				 */
788*49cdfc7eSAndroid Build Coastguard Worker 				memset(c, 0x00, width * NBPW);
789*49cdfc7eSAndroid Build Coastguard Worker 				/*
790*49cdfc7eSAndroid Build Coastguard Worker 				 * get the last 2 words printed
791*49cdfc7eSAndroid Build Coastguard Worker 				 */
792*49cdfc7eSAndroid Build Coastguard Worker 				memcpy(c, a - (width * NBPW), width * NBPW);
793*49cdfc7eSAndroid Build Coastguard Worker 				for (p = c; (p - c) < (int)(width*NBPW); ++p) {
794*49cdfc7eSAndroid Build Coastguard Worker 					if (*p < '!' || *p > '~')
795*49cdfc7eSAndroid Build Coastguard Worker 						*p = '.';
796*49cdfc7eSAndroid Build Coastguard Worker 				}
797*49cdfc7eSAndroid Build Coastguard Worker 				printf("\t%16.16s", c);
798*49cdfc7eSAndroid Build Coastguard Worker 			}
799*49cdfc7eSAndroid Build Coastguard Worker 			printf("\n%p: ", addr);
800*49cdfc7eSAndroid Build Coastguard Worker 			/***printf("\n%7o (%d): ",addr,i);***/
801*49cdfc7eSAndroid Build Coastguard Worker 		}
802*49cdfc7eSAndroid Build Coastguard Worker 
803*49cdfc7eSAndroid Build Coastguard Worker 		switch (format) {
804*49cdfc7eSAndroid Build Coastguard Worker 		case HEX:
805*49cdfc7eSAndroid Build Coastguard Worker 			printf("%16.16lx ", *word);
806*49cdfc7eSAndroid Build Coastguard Worker 			break;
807*49cdfc7eSAndroid Build Coastguard Worker 		case DECIMAL:
808*49cdfc7eSAndroid Build Coastguard Worker 			printf("%10.10ld ", *word);
809*49cdfc7eSAndroid Build Coastguard Worker 			break;
810*49cdfc7eSAndroid Build Coastguard Worker 		case ASCII:
811*49cdfc7eSAndroid Build Coastguard Worker 			memcpy(b, a, NBPW);
812*49cdfc7eSAndroid Build Coastguard Worker 			for (p = b; (p - b) < (int)NBPW; ++p) {
813*49cdfc7eSAndroid Build Coastguard Worker 				if (*p < '!' || *p > '~')
814*49cdfc7eSAndroid Build Coastguard Worker 					*p = '.';
815*49cdfc7eSAndroid Build Coastguard Worker 			}
816*49cdfc7eSAndroid Build Coastguard Worker 			printf("%8.8s ", b);
817*49cdfc7eSAndroid Build Coastguard Worker 			break;
818*49cdfc7eSAndroid Build Coastguard Worker 		default:
819*49cdfc7eSAndroid Build Coastguard Worker 			printf("%22.22lo ", *word);
820*49cdfc7eSAndroid Build Coastguard Worker 			break;
821*49cdfc7eSAndroid Build Coastguard Worker 		}
822*49cdfc7eSAndroid Build Coastguard Worker 	}
823*49cdfc7eSAndroid Build Coastguard Worker 	if (format != ASCII) {
824*49cdfc7eSAndroid Build Coastguard Worker 		/*
825*49cdfc7eSAndroid Build Coastguard Worker 		 * print the ascii equivalent of the last words in the buffer
826*49cdfc7eSAndroid Build Coastguard Worker 		 * before returning.
827*49cdfc7eSAndroid Build Coastguard Worker 		 */
828*49cdfc7eSAndroid Build Coastguard Worker 		memset(c, 0x00, width * NBPW);
829*49cdfc7eSAndroid Build Coastguard Worker 		if (extra_words)
830*49cdfc7eSAndroid Build Coastguard Worker 			width = extra_words;	/* odd number of words */
831*49cdfc7eSAndroid Build Coastguard Worker 		memcpy(c, a - (width * NBPW), width * NBPW);
832*49cdfc7eSAndroid Build Coastguard Worker 		for (p = c; (p - c) < (int)(width * NBPW); ++p) {
833*49cdfc7eSAndroid Build Coastguard Worker 			if (*p < '!' || *p > '~')
834*49cdfc7eSAndroid Build Coastguard Worker 				*p = '.';
835*49cdfc7eSAndroid Build Coastguard Worker 		}
836*49cdfc7eSAndroid Build Coastguard Worker 		if (width == 2)
837*49cdfc7eSAndroid Build Coastguard Worker 			printf("\t%16.16s", c);
838*49cdfc7eSAndroid Build Coastguard Worker 		else
839*49cdfc7eSAndroid Build Coastguard Worker 			printf("\t\t%16.8s", c);
840*49cdfc7eSAndroid Build Coastguard Worker 	}
841*49cdfc7eSAndroid Build Coastguard Worker 	printf("\n");
842*49cdfc7eSAndroid Build Coastguard Worker 	fflush(stdout);
843*49cdfc7eSAndroid Build Coastguard Worker }
844*49cdfc7eSAndroid Build Coastguard Worker 
prt_examples(void)845*49cdfc7eSAndroid Build Coastguard Worker static void prt_examples(void)
846*49cdfc7eSAndroid Build Coastguard Worker {
847*49cdfc7eSAndroid Build Coastguard Worker 	printf("%s -c 5 -i 0 -s 4090 -b\n", TCID);
848*49cdfc7eSAndroid Build Coastguard Worker 	printf("%s -c 5 -i 0 -s 4090 -b -u \n", TCID);
849*49cdfc7eSAndroid Build Coastguard Worker 	printf("%s -c 5 -i 0 -s 4090 -b -W 3 -w 3 \n", TCID);
850*49cdfc7eSAndroid Build Coastguard Worker }
851*49cdfc7eSAndroid Build Coastguard Worker 
sig_child(int sig)852*49cdfc7eSAndroid Build Coastguard Worker static void sig_child(int sig)
853*49cdfc7eSAndroid Build Coastguard Worker {
854*49cdfc7eSAndroid Build Coastguard Worker 	int status;
855*49cdfc7eSAndroid Build Coastguard Worker 
856*49cdfc7eSAndroid Build Coastguard Worker 	nchildcompleted++;
857*49cdfc7eSAndroid Build Coastguard Worker #if DEBUG
858*49cdfc7eSAndroid Build Coastguard Worker 	#define STR	"parent: received SIGCHLD\n"
859*49cdfc7eSAndroid Build Coastguard Worker 	write(STDOUT_FILENO, str, strlen(STR));
860*49cdfc7eSAndroid Build Coastguard Worker #endif
861*49cdfc7eSAndroid Build Coastguard Worker 	waitpid(-1, &status, WNOHANG);
862*49cdfc7eSAndroid Build Coastguard Worker }
863