pipe_test_02.c revision 045fd16a63837924a0f20d2419fbd497f8e36764
1d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
2d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
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/*
21d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Copyright (C) Bull S.A. 1996
22d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Level 1,5 Years Bull Confidential and Proprietary Information
23d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
24d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
25d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
26d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                            pipe_test_02                              |
27d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
28d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
29d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Description:  Max data transfer through pipe interprocess channel    |
30d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               in non-blocking mode                                   |
31d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
32d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Algorithm:    o  Create a pipe                                       |
33d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  Make write & read end of pipe non-blocking          |
34d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  Spawn a child process                               |
35d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  parent:                                             |
36d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  create & send data packets to the child          |
37d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  compute checksum on sent packets                 |
38d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  child:                                              |
39d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  recieve packets from parent & compute checksum   |
40d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  send final checksum to parent                    |
41d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               o  parent:                                             |
42d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                  -  compare checksum of sent packets with the        |
43d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                     child's checksum                                 |
44d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
45d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| System calls: The following system calls are tested:                 |
46d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
47d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               pipe () - Creates an interprocess channel              |
48d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               fork () - Creates a new process                        |
49d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               fcntl () -                                             |
50d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|               waitpid () - Waits for a child process to stop or      |
51d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
52d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Usage:        pipe_test_02                                           |
53d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
54d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| To compile:   cc -o pipe_test_02 pipe_test_02.c                      |
55d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
56d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Last update:   Ver. 1.3, 3/3/94 12:06:38                           |
57d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
58d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Change Activity                                                      |
59d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
60d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|   Version  Date    Name  Reason                                      |
61d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|    0.1     010393  DJK   Initial version for AIX 4.1                 |
62d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|    1.2     021394  DJK   Move to "prod" directory                    |
63d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
64d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
65d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
66d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <errno.h>
67d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <fcntl.h>
68d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <signal.h>
69d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <stdio.h>
70f3a83d59cce260ab513313b2c43c41fc16983959robbiew#include <stdlib.h>
71d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <string.h>
72d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <sys/types.h>
73d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <sys/wait.h>
74d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <unistd.h>
75d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
76d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#ifdef _LINUX_
77d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#include <linux/limits.h>
78d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#endif
79d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
80d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
81d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/* Defines:
82d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
83d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * MB: one megabyte (MB)
84d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
85d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * VALID_PACKET: value sent with each packet, used to verify that the
86d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * packets contents were not garbled.
87d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
88d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * DEFAULT_NUM_CHILDREN: default number of child processes spawned
89d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
90d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * DEFAULT_PACKETS_TO_SEND: default number of packets sent to each child
91d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * process.
92d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
93d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * MAXCHILD: maximum number of child processes which may be spawned
94d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * (based upon the number of file descriptors that a process may use)
95d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
96d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * USAGE: usage statement
97d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
98d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define MB			(1024*1024)
99d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define DEFAULT_PACKETS_TO_SEND 1024
100d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define DEFAULT_NUM_CHILDREN	1
101d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define MAXCHILD 		(OPEN_MAX/2 - 2)
102d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define VALID_PACKET		0xabcdef01
103d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj#define USAGE	"\nUsage: %s [-n] [-p nprocs] [{-m totmegs | -b totbytes}]\n\n" \
104d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-n          transfer data with NON-BLOCKING reads & writes\n" \
105d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-p nprocs   number of child processes to spawn\n" \
106d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-m totmegs  number of MB to send through pipe\n" \
107d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t-b totmegs  number of bytes to send through pipe\n" \
108d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		"\t                  (must be less than %d)\n\n"
109d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
110d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
111d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Function Prototypes:
112d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
113d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * setup (): Parse command line arguments and intialize variables
114d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * child (): Child process
115d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * cleanup (): Close all pipes and kill child processes
116d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * sys_error (): System error message function
117d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * error (): Error message function
118d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * setup_signal_handlers (): Sets up signal catching functions
119d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * handler (): Signal catching function
120d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
121d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup (int, char **);
122d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid child (int [], int []);
123d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid cleanup ();
124d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid sys_error (const char *, int);
125d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid error (const char *, int);
126d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup_signal_handlers ();
127d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid handler (int, int, struct sigcontext *);
128d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
129d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*
130d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * Structures & Global variables
131d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
132d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * num_children: number of child processes to be spawned
133d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
134d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * num_packets: number of packets to be sent to each child process
135d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
136d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * non_blocking_flag: uses NON-BLOCKING
137d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
138d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * pid: process id's of the spawned processes
139d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
140d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * p2child: half duplex pipes from parent to child (parent writes,
141d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *          child reads).
142d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *
143d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj * p2parent: half duplex pipe from child to parent (child writes,
144d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj *           parent reads).
145d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj */
146d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
147d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojenum { READ, WRITE };		/* Pipe read & write end indices */
148d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
149d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojstruct data_packet {
150d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	pid_t		pid;		/* Child process id */
151d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int 		last;		/* Indicates last packet when set */
152d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long 		valid;		/* Insure packet was not garbled */
153d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long 		seq_number;	/* Packet sequence number */
154d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned long	checksum;	/* Cumulative checksum so far */
155d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned char	data;		/* Data sent in packet */
156d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj};
157d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojtypedef struct data_packet data_packet;
158d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
159d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint     num_children = DEFAULT_NUM_CHILDREN;
160d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojlong	num_packets  = DEFAULT_PACKETS_TO_SEND;
161d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	non_blocking_flag = 0;	/* Uses NON-BLOCKING pipes when set */
162d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	bflg = 0;		/* Data quantity flag (MB) */
163d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	mflg = 0;		/* Data quantity flag (bytes) */
164d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
165d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojpid_t	parent_pid;		/* Parent's process id */
166d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojpid_t	pid [MAXCHILD];		/* Process id's of spawned processes */
167d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	p2child [MAXCHILD][2]; 	/* Pipes from parent to child processes */
168d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint	p2parent [2];  		/* Pipe from child processes to parent */
169d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojchar	err_msg [256];		/* Generic error message buffer */
170d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
171d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
172d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
173d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               main ()                                |
174d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
175d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
176d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Main program  (see prolog for more details)               |
177d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
178d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Returns:   (0)  Successful completion                                |
179d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            (-1) Error occurred                                       |
180d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
181d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
182d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojint main (int argc, char **argv)
183d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
184d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int 	i;
185d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int 	n;		/* Number of bytes written */
186d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	status;		/* Child's exit status */
187d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long	packets_sent;
188d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned char 	data;
189d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned long 	cksum_parent = 0;
190d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	data_packet	packet;
191d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
192d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
193d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Parse command line arguments, initialize global variables and
194d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * print program header
195d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
196d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	setup (argc, argv);
197d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("%s: IPC Pipe TestSuite program\n", *argv);
198d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stdout);
199d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
200d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
201d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Create two sets of half duplex pipes:
202d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
203d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * p2child: for sending packets from the parent process to the child
204d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *          processes and
205d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * p2parent: for sending checksums from the child processes to the
206d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *           parent
207d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
208d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * If the non-blocking command line option was specified, use fcntl ()
209d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * to set the O_NONBLOCK file descriptor status flags.  This will
210d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * prevent reads & and writes from blocking if the data is not yet
211d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * available
212d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
213d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tCreating pipes...\n");
214d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stdout);
215d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
216d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (pipe (p2parent) < 0)
217d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("pipe failed", __LINE__);
218d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
219d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (non_blocking_flag) {
220d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		printf ("\n\tSending data NON-BLOCKING!\n");
221d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		fflush (stdout);
222d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
223d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
224d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
225d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (pipe (&p2child [i][0]) < 0)
226d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("pipe failed", __LINE__);
227d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (non_blocking_flag) {
228d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (fcntl (p2child [i][READ], F_SETFL, O_NONBLOCK) < 0)
229d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("fcntl (O_NONBLOCK) failed", __LINE__);
230d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (fcntl (p2child [i][WRITE], F_SETFL, O_NONBLOCK) < 0)
231d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("fcntl (O_NONBLOCK) failed", __LINE__);
232d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
233d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
234d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
235d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
236d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Spawn num_children processes
237d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
238d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Fork of the child process & record the newly created process's
239d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * id for future reference.
240d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
241d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then close the READ end of the p2child pipe, since the parent
242d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * process will be writing into this pipe rather than reading.
243d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Also close the WRITE end of the p2parent pipe, for just the
244d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the reverse reasons...
245d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
246d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tSpawning %d child processes ... \n", num_children);
247d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stdout);
248d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
249d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
250d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
251d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if ((pid [i] = fork()) == 0) {
252d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
253d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Child process */
254d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			child (&p2child[i][0], p2parent);
255d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			exit (0);
256d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
257d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		} else if (pid [i] < (pid_t)0)
258d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("fork failed", __LINE__);
259d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
260d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (close (p2child [i][READ]) < 0)
261d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("close failed", __LINE__);
262d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
263d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [WRITE]) < 0)
264d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
265d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
266d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
267d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send data packets to the child processes
268d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
269d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Build packets (initialize all of the packets fields) and then
270d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * send the packets to all of the child processes.
271d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
272d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING writes
273d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * if the resource is not immediately available.
274d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
275f3a83d59cce260ab513313b2c43c41fc16983959robbiew	printf ("\n\tParent: sending %ld packets (%ld bytes) to child processes ...\n",
276d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		num_packets, num_packets * sizeof (struct data_packet));
277d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
278d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.last = 0;
279d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.valid = VALID_PACKET;
280d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
281d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (packets_sent = data = 0; num_packets > 0; num_packets--) {
282d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
283d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.seq_number = ++packets_sent;
284d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.data = data++;
285d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.pid = pid [i];
286d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		packet.checksum = cksum_parent += packet.data;
287d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
288f3a83d59cce260ab513313b2c43c41fc16983959robbiew		for (i=0; i<num_children; i++) {
289d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			try_write_ETXN_again:
290045fd16a63837924a0f20d2419fbd497f8e36764robbiew			if ((n = write (p2child [i][WRITE], &packet,
291045fd16a63837924a0f20d2419fbd497f8e36764robbiew					sizeof (packet))) < 0) {
292045fd16a63837924a0f20d2419fbd497f8e36764robbiew				if (non_blocking_flag && errno == EAGAIN) {
293d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					goto try_write_ETXN_again;
294045fd16a63837924a0f20d2419fbd497f8e36764robbiew				} else {
295d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					sys_error ("write failed", __LINE__);
296045fd16a63837924a0f20d2419fbd497f8e36764robbiew				}
297045fd16a63837924a0f20d2419fbd497f8e36764robbiew			}
298f3a83d59cce260ab513313b2c43c41fc16983959robbiew		}
299d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
300d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
301d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
302d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send the last packet to the child processes
303d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
304d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * [ Upon receiving this packet, the child process will know that all
305d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *   of the packets have been sent and that the parent process is
306d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *   expecting the child to send it's checksum back. ]
307d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
308d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * After sending the last packet, close the WRITE end of the p2child
309d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * pipe as we are finish sending packets to the child processes.
310d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
311d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then wait for all of the child processes to send the checksum
312d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * packets.  Upon receiving the checksum packets verify that the
313d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * child's checksum matches that of the parent.
314d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
315d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING writes
316d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * if the resource is not immediately available.
317d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
318d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Finally, close READ end of p2parent pipe as we have finished
319d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * receiving checksums from the child.
320d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
321d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.last = 1;
322d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tParent: done sending packets & waiting for children to complete!\n");
323d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
324d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		try_read_again:
325045fd16a63837924a0f20d2419fbd497f8e36764robbiew		if (write (p2child [i][WRITE], &packet, sizeof (packet)) < 0) {
326045fd16a63837924a0f20d2419fbd497f8e36764robbiew			if (non_blocking_flag && errno == EAGAIN) {
327d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				goto try_read_again;
328045fd16a63837924a0f20d2419fbd497f8e36764robbiew			} else {
329d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("write failed", __LINE__);
330045fd16a63837924a0f20d2419fbd497f8e36764robbiew			}
331045fd16a63837924a0f20d2419fbd497f8e36764robbiew		}
332d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (close (p2child [i][WRITE]) < 0)
333d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("close failed", __LINE__);
334d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
335d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (read (p2parent [READ], &packet, sizeof (packet)) <= 0)
336d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("read failed", __LINE__);
337d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
338d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (packet.valid != VALID_PACKET)
339d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			error ("received packet with corrupted data from child!",
340d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				__LINE__);
341d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
342d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (cksum_parent != packet.checksum) {
343d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sprintf (err_msg, "checksum of data sent by parent " \
344d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				"does not match checksum of data received by " \
345d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				"child [pid %d]\n"	\
346f3a83d59cce260ab513313b2c43c41fc16983959robbiew				"\tchild's checksum: %08lx\n" \
347f3a83d59cce260ab513313b2c43c41fc16983959robbiew				"\tparent's checksum: %08lx\n",
348d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				packet.pid, packet.checksum, cksum_parent);
349d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			error (err_msg, __LINE__);
350d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
351d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
352d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [READ]) < 0)
353d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
354d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
355d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
356d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Wait for all of the child processes to complete & check their
357d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * exit status.
358d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
359d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Upon completion of the child proccesses, exit program with success.
360d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
361d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
362d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		waitpid (pid [i], &status, 0);
363d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
364d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (!WIFEXITED (status))
365d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			sys_error ("child process terminated abnormally",
366d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				__LINE__);
367d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
368d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\n\tParent: children received all packets & exited successfully\n");
369d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
370d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/* Program completed successfully -- exit */
371d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	printf ("\nsuccessful!\n");
372d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
373d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	return (0);
374d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
375d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
376d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
377d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
378d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               child ()                               |
379d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
380d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
381d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Receive packets from the parent, insure they are valid    |
382d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            and not out of sequence, and calculate a running          |
383d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            checksum.  Upon receiving the last packet from the        |
384d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            parent, build a checksum packet and send it to the parent.|
385d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
386d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Args:      p2child   - Pipe from parent to child                     |
387d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            p2parent  - Pipe from child to parent                     |
388d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
389d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Returns:   Exits with (-1) if an error occurs                        |
390d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
391d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
392d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid child (int p2child [], int p2parent [])
393d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
394d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	n;			/* Bytes read */
395d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	pid_t	pid = getpid ();	/* Process id of child */
396d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	end_of_transmission = 0;/* End of transaction flag */
397d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	long	packets_received = 0;	/* Number of packets received
398d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					 * from parent
399d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					 */
400d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
401d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	data_packet 	packet;		/* Packet used to transmiting data */
402d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	unsigned long 	cksum_child = 0;/* Checksum of data fields received */
403d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
404d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
405d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Close the WRITE end of the p2child pipe, since the child
406d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * process will be reading from this pipe rather than writing.
407d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Also close the READ end of the p2parent pipe, for just the
408d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the reverse reasons...
409d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
410d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2child [WRITE]) < 0)
411d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
412d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [READ]) < 0)
413d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
414d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
415d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
416d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Receive packets from parent & insure packets are valid
417d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
418d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Read packets from the parent through p2child pipe.  Upon
419d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * recieving the packet, verify that it is valid, in sequence
420d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * and that both the parent's and child's checksums match.
421d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
422d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Might have to make several attempts with the NON-BLOCKING
423d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * reads if the resource is not immediately available.
424d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
425d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Continue reading packets until the "last" packet is received
426d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * from the parent.  Upon receiving the last packet, close
427d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the p2child READ pipe, as we are finished receiving packets
428d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * from the parent.
429d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
430d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	while (!end_of_transmission) {
431d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		try_write_again:
432d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		n = read (p2child [READ], &packet, sizeof (packet));
433d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (n < 0) {
434d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Resource not available */
435d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (non_blocking_flag && errno == EAGAIN)
436d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				goto try_write_again;
437d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			else
438d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("read failed", __LINE__);
439d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		} else if (n > 0) {
440d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Insure packet is valid */
441d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (packet.valid != VALID_PACKET) {
442d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sprintf (err_msg,
443d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					"child received invalid packet " \
444f3a83d59cce260ab513313b2c43c41fc16983959robbiew					"from parent:\n\tpacket #: %ld\n",
445d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					packets_received);
446d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				error (err_msg, __LINE__);
447d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			}
448d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			/* Received last packet */
449d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (packet.last) {
450d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				end_of_transmission = 1;
451d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			} else {
452d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
453d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				/* Insure packet was not received out of sequence */
454d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				packets_received++;
455d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				if (packets_received != packet.seq_number) {
456d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					sprintf (err_msg,
457d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						"child received packet out of sequence\n" \
458f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\texpecting packet: %ld\n" \
459f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\treceived packet:  %ld\n",
460d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						packets_received, packet.seq_number);
461d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					error (err_msg, __LINE__);
462d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				}
463d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
464d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				/* Insure checksums still match */
465d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				cksum_child += packet.data;
466d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				if (cksum_child != packet.checksum) {
467d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					sprintf (err_msg,
468d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						"child & parent checksums do not match\n" \
469f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tchild checksum:  %08lx\n" \
470f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tparent checksum: %08lx\n" \
471f3a83d59cce260ab513313b2c43c41fc16983959robbiew						"\tpacket number:   %ld\n",
472d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj						cksum_child, packet.checksum, packets_received);
473d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj					error (err_msg, __LINE__);
474d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				}
475d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			}
476d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
477d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
478d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2child [READ]) < 0)
479d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
480d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
481d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
482d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
483d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Send parent packet containing child's checksum
484d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
485d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Build a checksum packet (initialize packet fields) and then
486d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * send the packet to the parent.
487d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 *
488d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Then close the WRITE p2parent pipe as we have finished sending packets
489d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * to the parent.
490d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
491f3a83d59cce260ab513313b2c43c41fc16983959robbiew	printf ("\t\tChild:  pid [%d] received %ld packets from parent\n",
492d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		pid, packets_received);
493d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
494d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.pid = pid;
495d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.valid = VALID_PACKET;
496d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	packet.checksum = cksum_child;
497d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
498d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (write (p2parent [WRITE], &packet, sizeof (packet)) < 0)
499d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("write failed", __LINE__);
500d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (close (p2parent [WRITE]) < 0)
501d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("close failed", __LINE__);
502d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
503d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
504d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
505d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
506d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               setup ()                               |
507d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
508d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
509d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Parse the command line arguments & initialize global      |
510d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            variables.                                                |
511d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
512d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Updates:   (command line options)                                    |
513d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
514d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-n] non_blocking_flag: prevents read & write calls from  |
515d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                 from blocking if the resource is not available.      |
516d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
517d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-p] num_packets: number of packets ...                   |
518d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
519d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            [-c] num_children: number of child processes to spawn ... |
520d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
521d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
522d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup (int argc, char **argv)
523d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
524d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	i;
525d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int	errflag = 0;
526f3a83d59cce260ab513313b2c43c41fc16983959robbiew	int 	bytes = 0, megabytes = 0;
527d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	char	*program_name = *argv;
528d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	extern char 	*optarg;	/* Command line option */
529d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
530d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	while ((i = getopt(argc, argv, "nm:b:p:?")) != EOF) {
531d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		switch (i) {
532d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'n':		/* NON-BLOCKING flag */
533d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				non_blocking_flag++;
534d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
535d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'm':		/* MB */
536d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				mflg++;
537d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				megabytes = atoi (optarg);
538d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
539d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'b':		/* bytes */
540d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				bflg++;
541d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				bytes = atoi (optarg);
542d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
543d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case 'p':		/* number of child procs */
544d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				num_children = atoi (optarg);
545d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
546d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			case '?':
547d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				errflag++;
548d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				break;
549d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
550d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
551d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (mflg) {
552d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		num_packets = megabytes * MB / sizeof (struct data_packet);
553d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else if (bflg) {
554d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		num_packets = bytes / sizeof (struct data_packet);
555d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
556d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
557d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (num_packets == 0 || num_children == 0 || num_children > MAXCHILD)
558d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		errflag++;
559d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
560d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (errflag) {
561d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		fprintf (stderr, USAGE, program_name, MAXCHILD);
562d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		exit (2);
563d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
564d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	/*
565d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * Setup signal catching function for SIGPIPE & SIGINT, record
566d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * the process id of the parent and initialize the child process
567d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 * id array.
568d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	 */
569d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	setup_signal_handlers ();
570d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
571d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	parent_pid = getpid ();
572d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
573d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	for (i=0; i<num_children; i++) {
574d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		pid [i] = (pid_t)0;
575d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
576d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
577d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
578d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
579d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                          setup_handler ()                            |
580d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
581d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
582d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Setup the signal handler for SIGPIPE.                     |
583d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
584d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
585d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid setup_signal_handlers ()
586d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
587d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	struct sigaction invec;
588d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
589d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	invec.sa_handler = (void (*)(int)) handler;
590d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	sigemptyset (&invec.sa_mask);
591d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	invec.sa_flags = 0;
592d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
593d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sigaction (SIGINT, &invec, (struct sigaction *) NULL) < 0)
594d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("sigaction failed", __LINE__);
595d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
596d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sigaction (SIGPIPE, &invec, (struct sigaction *) NULL) < 0)
597d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sys_error ("sigaction failed", __LINE__);
598d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
599d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
600d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
601d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
602d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             handler ()                               |
603d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
604d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
605d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Signal catching function for SIGPIPE signal.              |
606d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
607d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  SIGPIPE: Print message and abort program...            |
608d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
609d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  SIGINT:  Parent process calls cleanup, child processes |
610d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                        simply exit                                   |
611d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
612d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            o  Other:   Print message and abort program...            |
613d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
614d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
615d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid handler (int sig, int code, struct sigcontext *scp)
616d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
617d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	char 	msg [100];	/* Buffer for error message */
618d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
619d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (sig == SIGPIPE) {
620d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		error ("wrote to pipe with closed read end", __LINE__);
621d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else if (sig == SIGINT) {
622d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		if (getpid () == parent_pid) {
623d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
624d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			fprintf (stderr, "Received SIGINT -- cleaning up...\n");
625d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			fflush (stderr);
626d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
627d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			cleanup ();
628d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
629d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		else
630d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			exit (-1);
631d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	} else {
632d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		sprintf (msg, "Received an unexpected signal (%d)", sig);
633d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		error (msg, __LINE__);
634d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
635d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
636d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
637d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
638d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
639d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             cleanup ()                               |
640d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
641d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
642d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Closes all of the pipes, kills all of the child           |
643d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|            processes and exits the program...                        |
644d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
645d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
646d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid cleanup ()
647d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
648d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	int i;
649d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
650d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	if (getpid () == parent_pid) {
651d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		for (i=0; i<num_children; i++) {
652d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			if (pid [i] > (pid_t)0 && kill (pid [i], SIGKILL) < 0)
653d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj				sys_error ("signal failed", __LINE__);
654d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
655d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2child [i][READ]);
656d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2child [i][WRITE]);
657d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2parent [READ]);
658d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj			close (p2parent [WRITE]);
659d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj		}
660d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	}
661d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
662d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	exit (-1);
663d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
664d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
665d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
666d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
667d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                             sys_error ()                             |
668d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
669d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
670d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Creates system error message and calls error ()           |
671d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
672d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
673d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid sys_error (const char *msg, int line)
674d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
675d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	char syserr_msg [256];
676d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
677d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	sprintf (syserr_msg, "%s: %s\n", msg, strerror (errno));
678d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	error (syserr_msg, line);
679d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
680d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
681d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj
682d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj/*---------------------------------------------------------------------+
683d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                               error ()                               |
684d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| ==================================================================== |
685d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
686d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj| Function:  Prints out message and calls cleanup...                   |
687d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj|                                                                      |
688d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj+---------------------------------------------------------------------*/
689d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanojvoid error (const char *msg, int line)
690d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj{
691d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fprintf (stderr, "ERROR [line: %d] %s\n", line, msg);
692d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	fflush (stderr);
693d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj	cleanup ();
694d1c7ea471d417c9319bdf0ce5bb1fed011283b65iyermanoj}
695