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