#include /* for inet_ntoa() */ #include /* for errno() */ #include #include /* for signal(), SIG* */ #include /* for sprintf(), stderr, ... */ #include /* for exit() */ #include /* for strerror() */ #include /* for wait() */ #include /* for wait() */ #include /* for time() */ #include /* for sleep(), fork() and execlp() */ #include #include "funcs.h" /* for infomsg(), errormsg() */ /* * Macros */ #define MAX_CHILDREN 1000 #define MYPORT 2345 #define MAXPENDING 10 #define CHILD_RUN_TIME 20 #define USE_SA_RESTART FALSE #define BLOCK_SIGCHLD FALSE /* * Type and struct definitions */ struct child { pid_t pid; time_t start; }; /* * Global variables */ struct child children[MAX_CHILDREN]; /* * Forward declarations */ pid_t start_child_server(int); void handler(int); /* * Functions */ int main( int argc, char *argv[]) { int i; int listening_sfd, toclient_sfd; struct sockaddr_in listening_spars; struct sockaddr_in toclient_spars; int actual_toclient_spars_size; int sockoptval; sigset_t sigset, old_sigset, suspend_sigset; struct sigaction act, old_chld_act, old_alrm_act, old_usr1_act; /* * Initialise. */ infomsg("parent setting up listening socket ..."); /* create addressless IPv4 TCP socket */ if ((listening_sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) errormsg("socket() failed"); /* ensure bind() doesn't find old stale socket */ sockoptval = 1; setsockopt(listening_sfd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(sockoptval)); /* define other socket parameters */ memset(&listening_spars, 0, sizeof(struct sockaddr_in)); listening_spars.sin_family = AF_INET; /* IPv4 */ listening_spars.sin_port = htons(MYPORT); /* port */ listening_spars.sin_addr.s_addr = INADDR_ANY; /* listen on all NICs */ /* apply socket parameters */ if (bind(listening_sfd, (struct sockaddr *) &listening_spars, sizeof(struct sockaddr)) == -1) errormsg("bind() failed"); /* mark socket for listening */ if (listen(listening_sfd, MAXPENDING) == -1) errormsg("listen() failed"); infomsg("parent initialising children status table ..."); for (i=0; i 0) { children[i].pid = pid; children[i].start = time(NULL); return(pid); } /* * Only the child gets here */ infomsg("child is pid %d", (int) getpid()); infomsg("child sending message to client ..."); if (send(toclient_sfd, msg, strlen(msg), 0) == -1) errormsg("send"); infomsg("child sleeping a bit ..."); sleep(CHILD_RUN_TIME); infomsg("child exiting ..."); close(toclient_sfd); exit(EXIT_SUCCESS); } void handler( int sig) { int wstatus; pid_t pid; int i; switch (sig) { case SIGCHLD: while ((pid=waitpid(-1, &wstatus, WNOHANG)) > 0) { infomsg("parent received SIGCHLD; reaping and clearing child data ..."); for (i=0; i