/*------------------------------------------------------------------------ * main - Super-server main program *------------------------------------------------------------------------ */ int main(int argc, char *argv[]) { struct service *psv, /* service table pointer */ *fd2sv[NOFILE]; /* map fd to service pointer */ int fd, nfds; fd_set afds, rfds; /* readable file descriptors */ switch (argc) { case 1: break; case 2: portbase = (u_short) atoi(argv[1]); break; default: errexit("usage: superd [portbase]\n"); } nfds = 0; FD_ZERO(&afds); for (psv = &svent[0]; psv->sv_name; ++psv) { if (psv->sv_useTCP) psv->sv_sock = passiveTCP(psv->sv_name, QLEN); else psv->sv_sock = passiveUDP(psv->sv_name); fd2sv[psv->sv_sock] = psv; nfds = MAX(psv->sv_sock+1, nfds); FD_SET(psv->sv_sock, &afds); } (void) signal(SIGCHLD, reaper); while (1) { memcpy(&rfds, &afds, sizeof(rfds)); if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) { if (errno == EINTR) continue; errexit("select error: %s\n", strerror(errno)); } for (fd=0; fd<nfds; ++fd) if (FD_ISSET(fd, &rfds)) { psv = fd2sv[fd]; if (psv->sv_useTCP) doTCP(psv); else psv->sv_func(psv->sv_sock); } } }
// multiple-protocol super server int main(int argc, char **argv) { Service *psv, *fd2sv[NOFILE]; int fd, nfds; fd_set afds, rfds; // set port base portbase = 0; // check the arguments switch (argc) { case 1: break; case 2: portbase = atoi(argv[1]); break; default: ERROR("usage: superd [portbase]", EINVAL); return(1); } // signal handlers for exiting setCleanUp(); // check of any port base offset if (portbase == 0) checkPortBase(); // initialize array of services nfds = 0; FD_ZERO(&afds); for (psv = services; psv->service != NULL; psv++) { // allocate a socket switch (psv->protocol) { case UseUDP: psv->socket = passiveUDP(psv->service); if (psv->socket < 0) { ERRORD("passiveUDP failed", psv->socket, errno); return(2); } break; case UseTCP: psv->socket = passiveTCP(psv->service, QueueLength); if (psv->socket < 0) { ERRORD("passiveTCP failed", psv->socket, errno); return(2); } break; default: ERROR("invalid protocol in service table", EINVAL); return(2); } // map descriptor to service fd2sv[psv->socket] = psv; nfds = mymax(psv->socket+1, nfds); FD_SET(psv->socket, &afds); } // wait for a message and process it. while (1) { // copy active descriptors memcpy(&rfds, &afds, sizeof(rfds)); // wait for a calling if (select(nfds, &rfds, 0, 0, 0) < 0) { if (errno == EINTR) continue; ERROR("select error", errno); return(2); } // process active descriptors for (fd = 0; fd < nfds; fd++) { // check if active if ( ! FD_ISSET(fd, &rfds)) continue; // active, process according to protocol psv = fd2sv[fd]; switch (psv->protocol) { case UseTCP: doTCP(psv); break; case UseUDP: psv->server(psv->socket); break; default: ERRORD("invalid protocol", psv->protocol, EINVAL); return(2); } } } }