pipe_test_02.c revision 450ff20648579497cb788007438625aa74518d20
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
17d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
76d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
77d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * DEFAULT_NUM_CHILDREN: default number of child processes spawned
78d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
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)
84d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
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)
92d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#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:
102d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
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 */
111d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup (int, char **);
112d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid child (int [], int []);
113d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid cleanup ();
114d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid sys_error (const char *, int);
115d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid error (const char *, int);
116d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup_signal_handlers ();
117d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid handler (int, int, struct sigcontext *);
118d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
119d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
120d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Structures & Global variables
121d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
122d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * num_children: number of child processes to be spawned
123d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
124d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * num_packets: number of packets to be sent to each child process
125d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
126d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * 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 {
140d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	pid_t		pid;		/* Child process id */
141d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int 		last;		/* Indicates last packet when set */
142d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long 		valid;		/* Insure packet was not garbled */
143d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long 		seq_number;	/* Packet sequence number */
144d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned long	checksum;	/* Cumulative checksum so far */
145d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned char	data;		/* Data sent in packet */
146d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj};
147d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojtypedef struct data_packet data_packet;
148d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
149d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint     num_children = DEFAULT_NUM_CHILDREN;
150d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojlong	num_packets  = DEFAULT_PACKETS_TO_SEND;
151d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	non_blocking_flag = 0;	/* Uses NON-BLOCKING pipes when set */
152d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	bflg = 0;		/* Data quantity flag (MB) */
153d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	mflg = 0;		/* Data quantity flag (bytes) */
154d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
155d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojpid_t	parent_pid;		/* Parent's process id */
156d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojpid_t	pid [MAXCHILD];		/* Process id's of spawned processes */
157d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	p2child [MAXCHILD][2]; 	/* Pipes from parent to child processes */
158d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	p2parent [2];  		/* Pipe from child processes to parent */
159d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojchar	err_msg [256];		/* Generic error message buffer */
160d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
161d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
162d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
163d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               main ()                                |
164d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
165d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
166d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Main program  (see prolog for more details)               |
167d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
168d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Returns:   (0)  Successful completion                                |
169d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            (-1) Error occurred                                       |
170d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
171d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
172d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint main (int argc, char **argv)
173d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
174d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int 	i;
175d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int 	n;		/* Number of bytes written */
176d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	status;		/* Child's exit status */
177d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long	packets_sent;
178d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned char 	data;
179d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned long 	cksum_parent = 0;
180d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	data_packet	packet;
181d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
182d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
183d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Parse command line arguments, initialize global variables and
184d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * print program header
185d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
186d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	setup (argc, argv);
187d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("%s: IPC Pipe TestSuite program\n", *argv);
188d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stdout);
189d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
190d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
191d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Create two sets of half duplex pipes:
192d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
193d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * p2child: for sending packets from the parent process to the child
194d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *          processes and
195d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * p2parent: for sending checksums from the child processes to the
196d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *           parent
197d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
198d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * If the non-blocking command line option was specified, use fcntl ()
199d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * to set the O_NONBLOCK file descriptor status flags.  This will
200d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * prevent reads & and writes from blocking if the data is not yet
201d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * available
202d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
203d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tCreating pipes...\n");
204d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stdout);
205d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
206d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (pipe (p2parent) < 0)
207d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("pipe failed", __LINE__);
208d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
209d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (non_blocking_flag) {
210d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		printf ("\n\tSending data NON-BLOCKING!\n");
211d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		fflush (stdout);
212d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
213d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
214d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
215d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (pipe (&p2child [i][0]) < 0)
216d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("pipe failed", __LINE__);
217d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (non_blocking_flag) {
218d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (fcntl (p2child [i][READ], F_SETFL, O_NONBLOCK) < 0)
219d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("fcntl (O_NONBLOCK) failed", __LINE__);
220d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (fcntl (p2child [i][WRITE], F_SETFL, O_NONBLOCK) < 0)
221d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("fcntl (O_NONBLOCK) failed", __LINE__);
222d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
223d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
224d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
225d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
226d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Spawn num_children processes
227d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
228d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Fork of the child process & record the newly created process's
229d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * id for future reference.
230d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
231d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then close the READ end of the p2child pipe, since the parent
232d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * process will be writing into this pipe rather than reading.
233d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Also close the WRITE end of the p2parent pipe, for just the
234d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the reverse reasons...
235d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
236d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tSpawning %d child processes ... \n", num_children);
237d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stdout);
238d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
239d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
240d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
241d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if ((pid [i] = fork()) == 0) {
242d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
243d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Child process */
244d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			child (&p2child[i][0], p2parent);
245d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			exit (0);
246d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
247d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		} else if (pid [i] < (pid_t)0)
248d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("fork failed", __LINE__);
249d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
250d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (close (p2child [i][READ]) < 0)
251d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("close failed", __LINE__);
252d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
253d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [WRITE]) < 0)
254d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
255d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
256d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
257d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send data packets to the child processes
258d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
259d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Build packets (initialize all of the packets fields) and then
260d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * send the packets to all of the child processes.
261d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
262d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING writes
263d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * if the resource is not immediately available.
264d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
265f3a83d59cce260ab513313b2c43c41fc16983959robbiew	printf ("\n\tParent: sending %ld packets (%ld bytes) to child processes ...\n",
266d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		num_packets, num_packets * sizeof (struct data_packet));
267d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
268d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.last = 0;
269d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.valid = VALID_PACKET;
270d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
271d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (packets_sent = data = 0; num_packets > 0; num_packets--) {
272d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
273d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.seq_number = ++packets_sent;
274d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.data = data++;
275d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.pid = pid [i];
276d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.checksum = cksum_parent += packet.data;
277d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
278f3a83d59cce260ab513313b2c43c41fc16983959robbiew		for (i=0; i<num_children; i++) {
279d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			try_write_ETXN_again:
280045fd16a63837924a0f20d2419fbd497f8e36764robbiew			if ((n = write (p2child [i][WRITE], &packet,
281045fd16a63837924a0f20d2419fbd497f8e36764robbiew					sizeof (packet))) < 0) {
282045fd16a63837924a0f20d2419fbd497f8e36764robbiew				if (non_blocking_flag && errno == EAGAIN) {
283d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					goto try_write_ETXN_again;
284045fd16a63837924a0f20d2419fbd497f8e36764robbiew				} else {
285d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					sys_error ("write failed", __LINE__);
286045fd16a63837924a0f20d2419fbd497f8e36764robbiew				}
287045fd16a63837924a0f20d2419fbd497f8e36764robbiew			}
288f3a83d59cce260ab513313b2c43c41fc16983959robbiew		}
289d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
290d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
291d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
292d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send the last packet to the child processes
293d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
294d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * [ Upon receiving this packet, the child process will know that all
295d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *   of the packets have been sent and that the parent process is
296d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *   expecting the child to send it's checksum back. ]
297d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
298d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * After sending the last packet, close the WRITE end of the p2child
299d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * pipe as we are finish sending packets to the child processes.
300d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
301d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then wait for all of the child processes to send the checksum
302d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * packets.  Upon receiving the checksum packets verify that the
303d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * child's checksum matches that of the parent.
304d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
305d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING writes
306d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * if the resource is not immediately available.
307d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
308d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Finally, close READ end of p2parent pipe as we have finished
309d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * receiving checksums from the child.
310d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
311d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.last = 1;
312d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tParent: done sending packets & waiting for children to complete!\n");
313d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
314d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		try_read_again:
315045fd16a63837924a0f20d2419fbd497f8e36764robbiew		if (write (p2child [i][WRITE], &packet, sizeof (packet)) < 0) {
316045fd16a63837924a0f20d2419fbd497f8e36764robbiew			if (non_blocking_flag && errno == EAGAIN) {
317d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				goto try_read_again;
318045fd16a63837924a0f20d2419fbd497f8e36764robbiew			} else {
319d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("write failed", __LINE__);
320045fd16a63837924a0f20d2419fbd497f8e36764robbiew			}
321045fd16a63837924a0f20d2419fbd497f8e36764robbiew		}
322d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (close (p2child [i][WRITE]) < 0)
323d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("close failed", __LINE__);
324d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
325d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (read (p2parent [READ], &packet, sizeof (packet)) <= 0)
326d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("read failed", __LINE__);
327d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
328d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (packet.valid != VALID_PACKET)
329d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			error ("received packet with corrupted data from child!",
330d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				__LINE__);
331d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
332d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (cksum_parent != packet.checksum) {
333d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sprintf (err_msg, "checksum of data sent by parent " \
334d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				"does not match checksum of data received by " \
335d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				"child [pid %d]\n"	\
336f3a83d59cce260ab513313b2c43c41fc16983959robbiew				"\tchild's checksum: %08lx\n" \
337f3a83d59cce260ab513313b2c43c41fc16983959robbiew				"\tparent's checksum: %08lx\n",
338d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				packet.pid, packet.checksum, cksum_parent);
339d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			error (err_msg, __LINE__);
340d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
341d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
342d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [READ]) < 0)
343d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
344d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
345d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
346d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Wait for all of the child processes to complete & check their
347d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * exit status.
348d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
349d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Upon completion of the child proccesses, exit program with success.
350d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
351d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
352d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		waitpid (pid [i], &status, 0);
353d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
354d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (!WIFEXITED (status))
355d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("child process terminated abnormally",
356d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				__LINE__);
357d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
358d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tParent: children received all packets & exited successfully\n");
359d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
360d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/* Program completed successfully -- exit */
361d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\nsuccessful!\n");
362d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
363d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	return (0);
364d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
365d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
366d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
367d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
368d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               child ()                               |
369d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
370d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
371d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Receive packets from the parent, insure they are valid    |
372d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            and not out of sequence, and calculate a running          |
373d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            checksum.  Upon receiving the last packet from the        |
374d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            parent, build a checksum packet and send it to the parent.|
375d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
376d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Args:      p2child   - Pipe from parent to child                     |
377d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            p2parent  - Pipe from child to parent                     |
378d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
379d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Returns:   Exits with (-1) if an error occurs                        |
380d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
381d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
382d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid child (int p2child [], int p2parent [])
383d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
384d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	n;			/* Bytes read */
385d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	pid_t	pid = getpid ();	/* Process id of child */
386d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	end_of_transmission = 0;/* End of transaction flag */
387d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long	packets_received = 0;	/* Number of packets received
388d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					 * from parent
389d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					 */
390d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
391d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	data_packet 	packet;		/* Packet used to transmiting data */
392d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned long 	cksum_child = 0;/* Checksum of data fields received */
393d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
394d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
395d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Close the WRITE end of the p2child pipe, since the child
396d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * process will be reading from this pipe rather than writing.
397d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Also close the READ end of the p2parent pipe, for just the
398d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the reverse reasons...
399d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
400d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2child [WRITE]) < 0)
401d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
402d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [READ]) < 0)
403d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
404d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
405d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
406d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Receive packets from parent & insure packets are valid
407d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
408d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Read packets from the parent through p2child pipe.  Upon
409d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * recieving the packet, verify that it is valid, in sequence
410d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * and that both the parent's and child's checksums match.
411d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
412d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING
413d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * reads if the resource is not immediately available.
414d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
415d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Continue reading packets until the "last" packet is received
416d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * from the parent.  Upon receiving the last packet, close
417d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the p2child READ pipe, as we are finished receiving packets
418d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * from the parent.
419d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
420d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	while (!end_of_transmission) {
421d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		try_write_again:
422d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		n = read (p2child [READ], &packet, sizeof (packet));
423d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (n < 0) {
424d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Resource not available */
425d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (non_blocking_flag && errno == EAGAIN)
426d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				goto try_write_again;
427d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			else
428d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("read failed", __LINE__);
429d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		} else if (n > 0) {
430d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Insure packet is valid */
431d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (packet.valid != VALID_PACKET) {
432d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sprintf (err_msg,
433d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					"child received invalid packet " \
434f3a83d59cce260ab513313b2c43c41fc16983959robbiew					"from parent:\n\tpacket #: %ld\n",
435d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					packets_received);
436d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				error (err_msg, __LINE__);
437d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			}
438d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Received last packet */
439d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (packet.last) {
440d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				end_of_transmission = 1;
441d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			} else {
442d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
443d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				/* Insure packet was not received out of sequence */
444d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				packets_received++;
445d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				if (packets_received != packet.seq_number) {
446d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					sprintf (err_msg,
447d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						"child received packet out of sequence\n" \
448f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\texpecting packet: %ld\n" \
449f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\treceived packet:  %ld\n",
450d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						packets_received, packet.seq_number);
451d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					error (err_msg, __LINE__);
452d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				}
453d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
454d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				/* Insure checksums still match */
455d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				cksum_child += packet.data;
456d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				if (cksum_child != packet.checksum) {
457d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					sprintf (err_msg,
458d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						"child & parent checksums do not match\n" \
459f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tchild checksum:  %08lx\n" \
460f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tparent checksum: %08lx\n" \
461f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tpacket number:   %ld\n",
462d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						cksum_child, packet.checksum, packets_received);
463d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					error (err_msg, __LINE__);
464d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				}
465d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			}
466d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
467d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
468d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2child [READ]) < 0)
469d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
470d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
471d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
472d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
473d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send parent packet containing child's checksum
474d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
475d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Build a checksum packet (initialize packet fields) and then
476d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * send the packet to the parent.
477d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
478d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then close the WRITE p2parent pipe as we have finished sending packets
479d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * to the parent.
480d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
481f3a83d59cce260ab513313b2c43c41fc16983959robbiew	printf ("\t\tChild:  pid [%d] received %ld packets from parent\n",
482d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		pid, packets_received);
483d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
484d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.pid = pid;
485d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.valid = VALID_PACKET;
486d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.checksum = cksum_child;
487d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
488d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (write (p2parent [WRITE], &packet, sizeof (packet)) < 0)
489d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("write failed", __LINE__);
490d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [WRITE]) < 0)
491d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
492d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
493d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
494d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
495d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
496d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               setup ()                               |
497d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
498d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
499d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Parse the command line arguments & initialize global      |
500d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            variables.                                                |
501d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
502d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Updates:   (command line options)                                    |
503d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
504d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-n] non_blocking_flag: prevents read & write calls from  |
505d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                 from blocking if the resource is not available.      |
506d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
507d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-p] num_packets: number of packets ...                   |
508d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
509d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-c] num_children: number of child processes to spawn ... |
510d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
511d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
512d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup (int argc, char **argv)
513d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
514d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	i;
515d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	errflag = 0;
516f3a83d59cce260ab513313b2c43c41fc16983959robbiew	int 	bytes = 0, megabytes = 0;
517d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	char	*program_name = *argv;
518d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	extern char 	*optarg;	/* Command line option */
519d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
520d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	while ((i = getopt(argc, argv, "nm:b:p:?")) != EOF) {
521d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		switch (i) {
522d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'n':		/* NON-BLOCKING flag */
523d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				non_blocking_flag++;
524d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
525d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'm':		/* MB */
526d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				mflg++;
527d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				megabytes = atoi (optarg);
528d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
529d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'b':		/* bytes */
530d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				bflg++;
531d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				bytes = atoi (optarg);
532d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
533d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'p':		/* number of child procs */
534d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				num_children = atoi (optarg);
535d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
536d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case '?':
537d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				errflag++;
538d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
539d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
540d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
541d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (mflg) {
542d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		num_packets = megabytes * MB / sizeof (struct data_packet);
543d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else if (bflg) {
544d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		num_packets = bytes / sizeof (struct data_packet);
545d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
546d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
547d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (num_packets == 0 || num_children == 0 || num_children > MAXCHILD)
548d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		errflag++;
549d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
550d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (errflag) {
551d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		fprintf (stderr, USAGE, program_name, MAXCHILD);
552d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		exit (2);
553d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
554d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
555d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Setup signal catching function for SIGPIPE & SIGINT, record
556d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the process id of the parent and initialize the child process
557d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * id array.
558d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
559d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	setup_signal_handlers ();
560d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
561d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	parent_pid = getpid ();
562d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
563d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
564d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		pid [i] = (pid_t)0;
565d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
566d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
567d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
568d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
569d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                          setup_handler ()                            |
570d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
571d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
572d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Setup the signal handler for SIGPIPE.                     |
573d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
574d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
575d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup_signal_handlers ()
576d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
577d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	struct sigaction invec;
578d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
579d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	invec.sa_handler = (void (*)(int)) handler;
580d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	sigemptyset (&invec.sa_mask);
581d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	invec.sa_flags = 0;
582d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
583d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sigaction (SIGINT, &invec, (struct sigaction *) NULL) < 0)
584d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("sigaction failed", __LINE__);
585d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
586d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sigaction (SIGPIPE, &invec, (struct sigaction *) NULL) < 0)
587d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("sigaction failed", __LINE__);
588d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
589d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
590d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
591d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
592d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             handler ()                               |
593d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
594d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
595d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Signal catching function for SIGPIPE signal.              |
596d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
597d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  SIGPIPE: Print message and abort program...            |
598d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
599d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  SIGINT:  Parent process calls cleanup, child processes |
600d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                        simply exit                                   |
601d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
602d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  Other:   Print message and abort program...            |
603d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
604d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
605d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid handler (int sig, int code, struct sigcontext *scp)
606d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
607d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	char 	msg [100];	/* Buffer for error message */
608d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
609d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sig == SIGPIPE) {
610d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		error ("wrote to pipe with closed read end", __LINE__);
611d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else if (sig == SIGINT) {
612d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (getpid () == parent_pid) {
613d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
614d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			fprintf (stderr, "Received SIGINT -- cleaning up...\n");
615d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			fflush (stderr);
616d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
617d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			cleanup ();
618d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
619d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		else
620d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			exit (-1);
621d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else {
622d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sprintf (msg, "Received an unexpected signal (%d)", sig);
623d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		error (msg, __LINE__);
624d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
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+---------------------------------------------------------------------*/
636d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid cleanup ()
637d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
638d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int i;
639d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
640d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (getpid () == parent_pid) {
641d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		for (i=0; i<num_children; i++) {
642d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (pid [i] > (pid_t)0 && kill (pid [i], SIGKILL) < 0)
643d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("signal failed", __LINE__);
644d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
645d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2child [i][READ]);
646d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2child [i][WRITE]);
647d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2parent [READ]);
648d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2parent [WRITE]);
649d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
650d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
651d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
652d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	exit (-1);
653d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
654d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
655d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
656d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
657d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             sys_error ()                             |
658d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
659d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
660d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Creates system error message and calls error ()           |
661d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
662d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
663d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid sys_error (const char *msg, int line)
664d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
665d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	char syserr_msg [256];
666d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
667d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	sprintf (syserr_msg, "%s: %s\n", msg, strerror (errno));
668d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	error (syserr_msg, line);
669d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
670d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
671d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
672d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
673d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               error ()                               |
674d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
675d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
676d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Prints out message and calls cleanup...                   |
677d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
678d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
679d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid error (const char *msg, int line)
680d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
681d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fprintf (stderr, "ERROR [line: %d] %s\n", line, msg);
682d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stderr);
683d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	cleanup ();
684d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
685