1d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
2450ff20648579497cb788007438625aa74518d20subrata_modak *   Copyright (C) Bull S.A. 1996
3d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   Copyright (c) International Business Machines  Corp., 2001
4d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
5d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   This program is free software;  you can redistribute it and/or modify
6d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   it under the terms of the GNU General Public License as published by
7d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   the Free Software Foundation; either version 2 of the License, or
8d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   (at your option) any later version.
9d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
10d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   This program is distributed in the hope that it will be useful,
11d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   the GNU General Public License for more details.
14d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
15d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   You should have received a copy of the GNU General Public License
16d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   along with this program;  if not, write to the Free Software
174548c6cf9bcdd96d8303caa4130ab638b61f8a30Wanlong Gao *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
19d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
20d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                            pipe_test_02                              |
21d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
22d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
23d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Description:  Max data transfer through pipe interprocess channel    |
24d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               in non-blocking mode                                   |
25d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
26d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Algorithm:    o  Create a pipe                                       |
27d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  Make write & read end of pipe non-blocking          |
28d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  Spawn a child process                               |
29d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  parent:                                             |
30d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  create & send data packets to the child          |
31d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  compute checksum on sent packets                 |
32d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  child:                                              |
33d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  recieve packets from parent & compute checksum   |
34d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  send final checksum to parent                    |
35d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  parent:                                             |
36d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  compare checksum of sent packets with the        |
37d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                     child's checksum                                 |
38d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
39d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| System calls: The following system calls are tested:                 |
40d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
41d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               pipe () - Creates an interprocess channel              |
42d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               fork () - Creates a new process                        |
43d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               fcntl () -                                             |
44d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               waitpid () - Waits for a child process to stop or      |
45d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
46d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Usage:        pipe_test_02                                           |
47d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
48d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| To compile:   cc -o pipe_test_02 pipe_test_02.c                      |
49d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
50d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Last update:   Ver. 1.3, 3/3/94 12:06:38                           |
51d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
52d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Change Activity                                                      |
53d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
54d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|   Version  Date    Name  Reason                                      |
55d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|    0.1     010393  DJK   Initial version for AIX 4.1                 |
56d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|    1.2     021394  DJK   Move to "prod" directory                    |
57d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
58d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
59d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
60d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <errno.h>
61d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <fcntl.h>
62d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <signal.h>
63d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <stdio.h>
64f3a83d59cce260ab513313b2c43c41fc16983959robbiew#include <stdlib.h>
65d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <string.h>
66d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <sys/types.h>
67d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <sys/wait.h>
68d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <unistd.h>
69d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
70d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/* Defines:
71d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
72d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * MB: one megabyte (MB)
73d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
74d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * VALID_PACKET: value sent with each packet, used to verify that the
75d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * packets contents were not garbled.
764bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
77d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * DEFAULT_NUM_CHILDREN: default number of child processes spawned
782c28215423293e443469a07ae7011135d058b671Garrett Cooper *
79d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * DEFAULT_PACKETS_TO_SEND: default number of packets sent to each child
80d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * process.
81d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
82d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * MAXCHILD: maximum number of child processes which may be spawned
83d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * (based upon the number of file descriptors that a process may use)
842c28215423293e443469a07ae7011135d058b671Garrett Cooper *
85d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * USAGE: usage statement
86d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
87d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define MB			(1024*1024)
88d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define DEFAULT_PACKETS_TO_SEND 1024
89d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define DEFAULT_NUM_CHILDREN	1
9028e814915bc75e3ee3184c2bdf17d7a6edffcb1asubrata_modak#define OPEN_MAX		256
91d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define MAXCHILD 		(OPEN_MAX/2 - 2)
92bdbaec51a423e715c2b03ed9e497e9a1fba6103esubrata_modak#define VALID_PACKET		0xabcdef01
93d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define USAGE	"\nUsage: %s [-n] [-p nprocs] [{-m totmegs | -b totbytes}]\n\n" \
94d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-n          transfer data with NON-BLOCKING reads & writes\n" \
95d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-p nprocs   number of child processes to spawn\n" \
96d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-m totmegs  number of MB to send through pipe\n" \
97d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-b totmegs  number of bytes to send through pipe\n" \
98d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t                  (must be less than %d)\n\n"
99d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
100d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
101d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Function Prototypes:
1022c28215423293e443469a07ae7011135d058b671Garrett Cooper *
103d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * setup (): Parse command line arguments and intialize variables
104d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * child (): Child process
105d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * cleanup (): Close all pipes and kill child processes
106d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * sys_error (): System error message function
107d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * error (): Error message function
108d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * setup_signal_handlers (): Sets up signal catching functions
109d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * handler (): Signal catching function
110d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid setup(int, char **);
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid child(int[], int[]);
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid cleanup();
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid sys_error(const char *, int);
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid error(const char *, int);
116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid setup_signal_handlers();
117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid handler(int, int, struct sigcontext *);
118d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
119d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
120d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Structures & Global variables
1214bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
1224bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak * num_children: number of child processes to be spawned
1234bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak *
124d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * num_packets: number of packets to be sent to each child process
125d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
1264bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak * non_blocking_flag: uses NON-BLOCKING
127d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
128d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * pid: process id's of the spawned processes
129d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
130d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * p2child: half duplex pipes from parent to child (parent writes,
131d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *          child reads).
132d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
133d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * p2parent: half duplex pipe from child to parent (child writes,
134d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *           parent reads).
135d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
136d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
137d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojenum { READ, WRITE };		/* Pipe read & write end indices */
138d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
139d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojstruct data_packet {
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pid_t pid;		/* Child process id */
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int last;		/* Indicates last packet when set */
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	long valid;		/* Insure packet was not garbled */
143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	long seq_number;	/* Packet sequence number */
144354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned long checksum;	/* Cumulative checksum so far */
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned char data;	/* Data sent in packet */
146d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj};
147d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojtypedef struct data_packet data_packet;
148d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint num_children = DEFAULT_NUM_CHILDREN;
150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaolong num_packets = DEFAULT_PACKETS_TO_SEND;
151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint non_blocking_flag = 0;	/* Uses NON-BLOCKING pipes when set */
152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint bflg = 0;			/* Data quantity flag (MB) */
153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint mflg = 0;			/* Data quantity flag (bytes) */
154d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaopid_t parent_pid;		/* Parent's process id */
156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaopid_t pid[MAXCHILD];		/* Process id's of spawned processes */
157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint p2child[MAXCHILD][2];	/* Pipes from parent to child processes */
158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint p2parent[2];		/* Pipe from child processes to parent */
159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaochar err_msg[256];		/* Generic error message buffer */
160d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
161d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
162d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               main ()                                |
163d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
164d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
165d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Main program  (see prolog for more details)               |
166d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
167d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Returns:   (0)  Successful completion                                |
168d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            (-1) Error occurred                                       |
169d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
170d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char **argv)
172d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int i;
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int n;			/* Number of bytes written */
175354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int status;		/* Child's exit status */
176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	long packets_sent;
177354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned char data;
178354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned long cksum_parent = 0;
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	data_packet packet;
180d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
181d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
182d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Parse command line arguments, initialize global variables and
183d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * print program header
184d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
185354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	setup(argc, argv);
186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf("%s: IPC Pipe TestSuite program\n", *argv);
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fflush(stdout);
1882c28215423293e443469a07ae7011135d058b671Garrett Cooper
1894bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	/*
1902c28215423293e443469a07ae7011135d058b671Garrett Cooper	 * Create two sets of half duplex pipes:
1914bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
1924bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * p2child: for sending packets from the parent process to the child
193d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *          processes and
1944bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * p2parent: for sending checksums from the child processes to the
195d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *           parent
1964bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
197d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * If the non-blocking command line option was specified, use fcntl ()
198d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * to set the O_NONBLOCK file descriptor status flags.  This will
199d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * prevent reads & and writes from blocking if the data is not yet
200d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * available
201d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf("\n\tCreating pipes...\n");
203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fflush(stdout);
204d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
205354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (pipe(p2parent) < 0)
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("pipe failed", __LINE__);
207d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
208d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (non_blocking_flag) {
209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("\n\tSending data NON-BLOCKING!\n");
210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fflush(stdout);
211d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
212d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < num_children; i++) {
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (pipe(&p2child[i][0]) < 0)
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sys_error("pipe failed", __LINE__);
216d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (non_blocking_flag) {
217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (fcntl(p2child[i][READ], F_SETFL, O_NONBLOCK) < 0)
218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sys_error("fcntl (O_NONBLOCK) failed",
219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					  __LINE__);
220354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (fcntl(p2child[i][WRITE], F_SETFL, O_NONBLOCK) < 0)
221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sys_error("fcntl (O_NONBLOCK) failed",
222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					  __LINE__);
223d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
224d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
225d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
226d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
227d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Spawn num_children processes
2284bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
229d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Fork of the child process & record the newly created process's
2302c28215423293e443469a07ae7011135d058b671Garrett Cooper	 * id for future reference.
2312c28215423293e443469a07ae7011135d058b671Garrett Cooper	 *
2324bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Then close the READ end of the p2child pipe, since the parent
233d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * process will be writing into this pipe rather than reading.
2344bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Also close the WRITE end of the p2parent pipe, for just the
235d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the reverse reasons...
236d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf("\n\tSpawning %d child processes ... \n", num_children);
238354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fflush(stdout);
239d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < num_children; i++) {
241d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((pid[i] = fork()) == 0) {
243d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
244d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Child process */
245354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			child(&p2child[i][0], p2parent);
246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(0);
247d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else if (pid[i] < (pid_t) 0)
249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sys_error("fork failed", __LINE__);
250d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
251354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (close(p2child[i][READ]) < 0)
252354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sys_error("close failed", __LINE__);
253d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (close(p2parent[WRITE]) < 0)
255354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("close failed", __LINE__);
256d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
257d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
258d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send data packets to the child processes
2594bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
260d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Build packets (initialize all of the packets fields) and then
261d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * send the packets to all of the child processes.
2624bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
2634bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Might have to make several attempts with the NON-BLOCKING writes
264d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * if the resource is not immediately available.
265d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    ("\n\tParent: sending %ld packets (%ld bytes) to child processes ...\n",
268354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	     num_packets, num_packets * sizeof(struct data_packet));
269d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
270d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.last = 0;
271d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.valid = VALID_PACKET;
272d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
273d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (packets_sent = data = 0; num_packets > 0; num_packets--) {
274d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
275d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.seq_number = ++packets_sent;
276d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.data = data++;
277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		packet.pid = pid[i];
278d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.checksum = cksum_parent += packet.data;
279d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (i = 0; i < num_children; i++) {
281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotry_write_ETXN_again:
282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if ((n = write(p2child[i][WRITE], &packet,
283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       sizeof(packet))) < 0) {
284045fd16a63837924a0f20d2419fbd497f8e36764robbiew				if (non_blocking_flag && errno == EAGAIN) {
285d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					goto try_write_ETXN_again;
286045fd16a63837924a0f20d2419fbd497f8e36764robbiew				} else {
287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					sys_error("write failed", __LINE__);
288045fd16a63837924a0f20d2419fbd497f8e36764robbiew				}
289045fd16a63837924a0f20d2419fbd497f8e36764robbiew			}
290f3a83d59cce260ab513313b2c43c41fc16983959robbiew		}
291d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
292d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
293d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
294d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send the last packet to the child processes
2954bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
296d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * [ Upon receiving this packet, the child process will know that all
2974bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *   of the packets have been sent and that the parent process is
298d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *   expecting the child to send it's checksum back. ]
2994bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
300d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * After sending the last packet, close the WRITE end of the p2child
301d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * pipe as we are finish sending packets to the child processes.
3022c28215423293e443469a07ae7011135d058b671Garrett Cooper	 *
3034bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Then wait for all of the child processes to send the checksum
3044bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * packets.  Upon receiving the checksum packets verify that the
3054bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * child's checksum matches that of the parent.
3064bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
3074bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Might have to make several attempts with the NON-BLOCKING writes
308d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * if the resource is not immediately available.
3094bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
310d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Finally, close READ end of p2parent pipe as we have finished
311d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * receiving checksums from the child.
312d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
313d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.last = 1;
314354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf
315354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    ("\n\tParent: done sending packets & waiting for children to complete!\n");
316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < num_children; i++) {
317354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotry_read_again:
318354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (write(p2child[i][WRITE], &packet, sizeof(packet)) < 0) {
319045fd16a63837924a0f20d2419fbd497f8e36764robbiew			if (non_blocking_flag && errno == EAGAIN) {
320d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				goto try_read_again;
321045fd16a63837924a0f20d2419fbd497f8e36764robbiew			} else {
322354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sys_error("write failed", __LINE__);
323045fd16a63837924a0f20d2419fbd497f8e36764robbiew			}
324045fd16a63837924a0f20d2419fbd497f8e36764robbiew		}
325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (close(p2child[i][WRITE]) < 0)
326354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sys_error("close failed", __LINE__);
3272c28215423293e443469a07ae7011135d058b671Garrett Cooper
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (read(p2parent[READ], &packet, sizeof(packet)) <= 0)
329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sys_error("read failed", __LINE__);
330d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
3314bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak		if (packet.valid != VALID_PACKET)
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			error("received packet with corrupted data from child!",
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			      __LINE__);
334d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
335d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (cksum_parent != packet.checksum) {
336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sprintf(err_msg, "checksum of data sent by parent "
337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				"does not match checksum of data received by "
338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				"child [pid %d]\n"
339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				"\tchild's checksum: %08lx\n"
3404bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak				"\tparent's checksum: %08lx\n",
341d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				packet.pid, packet.checksum, cksum_parent);
342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			error(err_msg, __LINE__);
343d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
344d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
345354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (close(p2parent[READ]) < 0)
346354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("close failed", __LINE__);
347d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
3484bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	/*
349d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Wait for all of the child processes to complete & check their
350d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * exit status.
351d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
352d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Upon completion of the child proccesses, exit program with success.
353d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < num_children; i++) {
355354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		waitpid(pid[i], &status, 0);
356d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
357354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (!WIFEXITED(status))
358354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			sys_error("child process terminated abnormally",
359354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				  __LINE__);
360d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
361354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf
362354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	    ("\n\tParent: children received all packets & exited successfully\n");
363d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
364d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/* Program completed successfully -- exit */
365354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf("\nsuccessful!\n");
366d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
367d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	return (0);
368d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
369d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
370d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
371d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               child ()                               |
372d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
373d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
374d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Receive packets from the parent, insure they are valid    |
375d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            and not out of sequence, and calculate a running          |
376d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            checksum.  Upon receiving the last packet from the        |
377d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            parent, build a checksum packet and send it to the parent.|
378d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
379d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Args:      p2child   - Pipe from parent to child                     |
380d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            p2parent  - Pipe from child to parent                     |
381d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
382d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Returns:   Exits with (-1) if an error occurs                        |
383d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
384d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
385354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid child(int p2child[], int p2parent[])
386d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
387354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int n;			/* Bytes read */
388354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pid_t pid = getpid();	/* Process id of child */
389354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int end_of_transmission = 0;
390354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	long packets_received = 0;	/* Number of packets received
391d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					 * from parent
392d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					 */
393d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
394354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	data_packet packet;	/* Packet used to transmiting data */
395354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned long cksum_child = 0;	/* Checksum of data fields received */
396d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
397d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
3984bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Close the WRITE end of the p2child pipe, since the child
399d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * process will be reading from this pipe rather than writing.
4004bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 * Also close the READ end of the p2parent pipe, for just the
401d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the reverse reasons...
402d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
403354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (close(p2child[WRITE]) < 0)
404354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("close failed", __LINE__);
405354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (close(p2parent[READ]) < 0)
406354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("close failed", __LINE__);
407d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
408d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
409d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Receive packets from parent & insure packets are valid
4104bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
411d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Read packets from the parent through p2child pipe.  Upon
412d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * recieving the packet, verify that it is valid, in sequence
413d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * and that both the parent's and child's checksums match.
4144bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
415d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING
416d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * reads if the resource is not immediately available.
4174bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
418d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Continue reading packets until the "last" packet is received
419d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * from the parent.  Upon receiving the last packet, close
420d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the p2child READ pipe, as we are finished receiving packets
421d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * from the parent.
422d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
423d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	while (!end_of_transmission) {
424354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotry_write_again:
425354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		n = read(p2child[READ], &packet, sizeof(packet));
426d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (n < 0) {
427d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Resource not available */
428d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (non_blocking_flag && errno == EAGAIN)
429d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				goto try_write_again;
430d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			else
431354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sys_error("read failed", __LINE__);
432d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		} else if (n > 0) {
433d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Insure packet is valid */
434d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (packet.valid != VALID_PACKET) {
435354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sprintf(err_msg,
436354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					"child received invalid packet "
437f3a83d59cce260ab513313b2c43c41fc16983959robbiew					"from parent:\n\tpacket #: %ld\n",
438d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					packets_received);
439354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				error(err_msg, __LINE__);
4404bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak			}
441d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Received last packet */
442d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (packet.last) {
443d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				end_of_transmission = 1;
444d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			} else {
445d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
446d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				/* Insure packet was not received out of sequence */
447d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				packets_received++;
448d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				if (packets_received != packet.seq_number) {
449354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					sprintf(err_msg,
450354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"child received packet out of sequence\n"
451354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"\texpecting packet: %ld\n"
452f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\treceived packet:  %ld\n",
453354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						packets_received,
454354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						packet.seq_number);
455354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					error(err_msg, __LINE__);
456d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				}
457d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
458d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				/* Insure checksums still match */
459d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				cksum_child += packet.data;
460d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				if (cksum_child != packet.checksum) {
461354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					sprintf(err_msg,
462354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"child & parent checksums do not match\n"
463354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"\tchild checksum:  %08lx\n"
464354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"\tparent checksum: %08lx\n"
465f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tpacket number:   %ld\n",
466354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						cksum_child, packet.checksum,
467354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						packets_received);
468354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					error(err_msg, __LINE__);
469d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				}
470d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			}
471d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
472d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
473354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (close(p2child[READ]) < 0)
474354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("close failed", __LINE__);
475d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
476d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
477d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send parent packet containing child's checksum
4784bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
479d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Build a checksum packet (initialize packet fields) and then
480d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * send the packet to the parent.
4814bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak	 *
482d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then close the WRITE p2parent pipe as we have finished sending packets
483d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * to the parent.
484d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
485354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	printf("\t\tChild:  pid [%d] received %ld packets from parent\n",
486354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	       pid, packets_received);
487d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
488d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.pid = pid;
489d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.valid = VALID_PACKET;
490d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.checksum = cksum_child;
491d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
492354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (write(p2parent[WRITE], &packet, sizeof(packet)) < 0)
493354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("write failed", __LINE__);
494354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (close(p2parent[WRITE]) < 0)
495354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("close failed", __LINE__);
496d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
497d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
498d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
499d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               setup ()                               |
500d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
501d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
502d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Parse the command line arguments & initialize global      |
503d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            variables.                                                |
504d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
505d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Updates:   (command line options)                                    |
506d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
507d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-n] non_blocking_flag: prevents read & write calls from  |
508d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                 from blocking if the resource is not available.      |
509d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
510d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-p] num_packets: number of packets ...                   |
511d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
512d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-c] num_children: number of child processes to spawn ... |
513d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
514d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
515354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid setup(int argc, char **argv)
516d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
517354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int i;
518354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int errflag = 0;
519354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int bytes = 0, megabytes = 0;
520354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *program_name = *argv;
521354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	extern char *optarg;	/* Command line option */
522d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
523d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	while ((i = getopt(argc, argv, "nm:b:p:?")) != EOF) {
524d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		switch (i) {
525354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'n':	/* NON-BLOCKING flag */
526354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			non_blocking_flag++;
527354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
528354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'm':	/* MB */
529354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			mflg++;
530354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			megabytes = atoi(optarg);
531354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
532354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'b':	/* bytes */
533354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bflg++;
534354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			bytes = atoi(optarg);
535354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
536354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'p':	/* number of child procs */
537354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			num_children = atoi(optarg);
538354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
539354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case '?':
540354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			errflag++;
541354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
542d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
543d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
544d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (mflg) {
545354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		num_packets = megabytes * MB / sizeof(struct data_packet);
546d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else if (bflg) {
547354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		num_packets = bytes / sizeof(struct data_packet);
548d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
549d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
550d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (num_packets == 0 || num_children == 0 || num_children > MAXCHILD)
551d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		errflag++;
552d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
553d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (errflag) {
554354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, USAGE, program_name, MAXCHILD);
555354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(2);
556d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
557d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
558d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Setup signal catching function for SIGPIPE & SIGINT, record
559d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the process id of the parent and initialize the child process
560d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * id array.
561d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
562354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	setup_signal_handlers();
563d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
564354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	parent_pid = getpid();
565d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
566354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < num_children; i++) {
567354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pid[i] = (pid_t) 0;
568d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
569d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
570d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
571d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
572d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                          setup_handler ()                            |
573d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
574d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
575d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Setup the signal handler for SIGPIPE.                     |
576d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
577d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
578354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid setup_signal_handlers()
579d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
580d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	struct sigaction invec;
581d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
582354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	invec.sa_handler = (void (*)(int))handler;
583354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sigemptyset(&invec.sa_mask);
584d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	invec.sa_flags = 0;
585d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
586cf0d626fe6224db3c714843dc7007e9f81d94a80Cyril Hrubis	if (sigaction(SIGINT, &invec, NULL) < 0)
587354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("sigaction failed", __LINE__);
588d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
589cf0d626fe6224db3c714843dc7007e9f81d94a80Cyril Hrubis	if (sigaction(SIGPIPE, &invec, NULL) < 0)
590354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sys_error("sigaction failed", __LINE__);
591d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
592d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
593d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
594d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             handler ()                               |
595d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
596d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
597d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Signal catching function for SIGPIPE signal.              |
598d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
599d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  SIGPIPE: Print message and abort program...            |
600d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
601d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  SIGINT:  Parent process calls cleanup, child processes |
602d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                        simply exit                                   |
603d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
604d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  Other:   Print message and abort program...            |
605d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
606d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
607354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid handler(int sig, int code, struct sigcontext *scp)
608d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
609354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char msg[100];		/* Buffer for error message */
610d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
611d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sig == SIGPIPE) {
612354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		error("wrote to pipe with closed read end", __LINE__);
613d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else if (sig == SIGINT) {
614354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (getpid() == parent_pid) {
615d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
616354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fprintf(stderr, "Received SIGINT -- cleaning up...\n");
617354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fflush(stderr);
618d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
619354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			cleanup();
620354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else
621354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			exit(-1);
622d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else {
623354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sprintf(msg, "Received an unexpected signal (%d)", sig);
624354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		error(msg, __LINE__);
625d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
626d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
627d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
628d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
629d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             cleanup ()                               |
630d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
631d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
632d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Closes all of the pipes, kills all of the child           |
633d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            processes and exits the program...                        |
634d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
635d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
636354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid cleanup()
637d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
638d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int i;
639d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
640354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (getpid() == parent_pid) {
641354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (i = 0; i < num_children; i++) {
642354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (pid[i] > (pid_t) 0 && kill(pid[i], SIGKILL) < 0)
643354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				sys_error("signal failed", __LINE__);
644d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
645354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			close(p2child[i][READ]);
646354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			close(p2child[i][WRITE]);
647354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			close(p2parent[READ]);
648354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			close(p2parent[WRITE]);
649d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
650d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
651d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
652354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	exit(-1);
653d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
654d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
655d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
656d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             sys_error ()                             |
657d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
658d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
659d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Creates system error message and calls error ()           |
660d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
661d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
662354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid sys_error(const char *msg, int line)
663d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
664354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char syserr_msg[256];
665d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
666354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno));
667354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	error(syserr_msg, line);
668d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
669d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
670d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
671d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               error ()                               |
672d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
673d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
674d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Prints out message and calls cleanup...                   |
675d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
676d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
677354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid error(const char *msg, int line)
678d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
679354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fprintf(stderr, "ERROR [line: %d] %s\n", line, msg);
680354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fflush(stderr);
681354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	cleanup();
682ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
683