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