This example shows how to use the spawn() API to create a child process that inherits the socket descriptor from the parent.
/**************************************************************************/ /* Application creates an child process using spawn(). */ /**************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <spawn.h> #define SERVER_PORT 12345 main (int argc, char *argv[]) { int i, num, pid, rc, on = 1; int listen_sd, accept_sd; int spawn_fdmap[1]; char *spawn_argv[1]; char *spawn_envp[1]; struct inheritance inherit; struct sockaddr_in addr; /*************************************************/ /* If an argument was specified, use it to */ /* control the number of incoming connections */ /*************************************************/ if (argc >= 2) num = atoi(argv[1]); else num = 1; /*************************************************/ /* Create an AF_INET stream socket to receive */ /* incoming connections on */ /*************************************************/ listen_sd = socket(AF_INET, SOCK_STREAM, 0); if (listen_sd < 0) { perror("socket() failed"); exit(-1); } /*************************************************/ /* Allow socket descriptor to be reuseable */ /*************************************************/ rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (rc < 0) { perror("setsockopt() failed"); close(listen_sd); exit(-1); } /*************************************************/ /* Bind the socket */ /*************************************************/ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(SERVER_PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); rc = bind(listen_sd, (struct sockaddr *)&addr, sizeof(addr)); if (rc < 0) { perror("bind() failed"); close(listen_sd); exit(-1); } /*************************************************/ /* Set the listen back log */ /*************************************************/ rc = listen(listen_sd, 5); if (rc < 0) { perror("listen() failed"); close(listen_sd); exit(-1); } /*************************************************/ /* Inform the user that the server is ready */ /*************************************************/ printf("The server is ready\n"); /*************************************************/ /* Go through the loop once for each connection */ /*************************************************/ for (i=0; i < num; i++) { /**********************************************/ /* Wait for an incoming connection */ /**********************************************/ printf("Interation: %d\n", i+1); printf(" waiting on accept()\n"); accept_sd = accept(listen_sd, NULL, NULL); if (accept_sd < 0) { perror("accept() failed"); close(listen_sd); exit(-1); } printf(" accept completed successfully\n"); /**********************************************/ /* Initialize the spawn parameters */ /* */ /* The socket descriptor for the new */ /* connection is mapped over to descriptor 0 */ /* in the child program. */ /**********************************************/ memset(&inherit, 0, sizeof(inherit)); spawn_argv[0] = NULL; spawn_envp[0] = NULL; spawn_fdmap[0] = accept_sd; /**********************************************/ /* Create the worker job */ /**********************************************/ printf(" creating worker job\n"); pid = spawn("/QSYS.LIB/QGPL.LIB/WRKR1.PGM", 1, spawn_fdmap, &inherit, spawn_argv, spawn_envp); if (pid < 0) { perror("spawn() failed"); close(listen_sd); close(accept_sd); exit(-1); } printf(" spawn completed successfully\n"); /**********************************************/ /* Close down the incoming connection since */ /* it has been given to a worker to handle */ /**********************************************/ close(accept_sd); } /*************************************************/ /* Close down the listen socket */ /*************************************************/ close(listen_sd); }