int main(int argc, char* argv[]) { struct connection conn; iopoll_fd fds[2]; int selfpipe; int i; msg_debug_init(); testmode = getenv("TESTMODE") != 0; if ((shell_argv = malloc((argc + 3) * sizeof *argv)) == 0) die_oom(111); for (i = 1; i < argc; ++i) shell_argv[i-1] = argv[i]; for (; i < argc + 4; ++i) shell_argv[i-1] = 0; shell_argc = argc - 1; if ((path = getenv("PATH")) == 0) die1(111, "No PATH is set"); if ((devnull = open("/dev/null", O_RDWR)) == -1) die1sys(111, "Could not open \"/dev/null\""); if (!nonblock_on(0)) die1sys(111, "Could not set non-blocking status"); if ((selfpipe = selfpipe_init()) == -1) die1sys(111, "Could not create self-pipe"); init_slots(); connection_init(&conn, 0, 0); fds[0].fd = 0; fds[0].events = IOPOLL_READ; fds[1].fd = selfpipe; fds[1].events = IOPOLL_READ; for (;;) { if (iopoll_restart(fds, 2, -1) == -1) die1sys(111, "Poll failed"); if (fds[0].revents) if (connection_read(&conn, handle_packet) <= 0) break; if (fds[1].revents) { read(selfpipe, &i, 1); handle_child(WNOHANG); } } msg1("Waiting for remaining slots to complete"); while (slots_used > 0) handle_child(0); return 0; }
void mainloop(int sock) { char code; int newsock; iopoll_fd fds; fds.fd = sock; fds.events = IOPOLL_READ; for (;;) { switch (iopoll_restart(&fds, 1, timeout*1000)) { case -1: return; case 0: /* Timed out */ if (kill(ppid, 0) == -1) return; continue; default: if (read(sock, &code, 1) != 1) return; code = 0; if ((newsock = socket_tcp()) == -1) { error1sys("Creating socket failed"); code = 1; } else if (!socket_reuse(newsock)) { error1sys("Setting flags on socket failed"); code = 2; } else if (!socket_bind4(newsock, &ip, port)) { error1sys("Binding socket failed"); code = 3; } if (write(sock, &code, 1) != 1) error1sys("Sending the result code failed"); if (!code) if (!socket_sendfd(sock, newsock)) error1sys("Sending the bound socket failed"); close(newsock); } } }
/** Connect a socket to an IPv4 address, honouring a timeout. * * \note The socket will have nonblocking mode turned on on return from * this function. */ int socket_connect4_timeout(int sock, const ipv4addr* ip, ipv4port port, int timeout) { iopoll_fd pf; if (!nonblock_on(sock)) return 0; if (socket_connect4(sock, ip, port)) return 1; if (errno != EINPROGRESS && errno != EWOULDBLOCK) return 0; pf.fd = sock; pf.events = IOPOLL_WRITE; switch (iopoll_restart(&pf, 1, timeout)) { case 0: errno = ETIMEDOUT; return 0; case 1: if (socket_connected(sock)) return 1; /* No break, fall through */ default: return 0; } }