int look_for_raw(int r, int c) { int i; if (check_child(r, c)) return 1; for (i = 0; i < lists[r]->cnt; ++i) if (look_for(lists[r]->tt[i], c)) return 1; return 0; }
void check_child(struct Node** G, int node_count, int current_id, int * sign, int max_id){ // display_graph2(G, max_id + 1); struct Node* current_node = G[current_id]; // printf("check %i has %i children should have id: %i\n", current_node->node_id, current_node->neighbour_count, current_id); for (int j = 0; j < current_node->neighbour_count; j ++) { int child_id = current_node->neighbours[j]; // printf("!!!!!!!\n"); // if (child_id == 0) { // display_graph2(G, max_id); // } // printf("index is %i the child id is %i\n", j, child_id); int in = tagged(sign, node_count, child_id, max_id); if (in == 1) { check_child(G, node_count, child_id, sign, max_id); } } }
int is_graph_connected(struct Node* G, int node_count, struct Node** id2Node, int max_node_id){ // printf("in connecttion"); // display_graph2(id2Node, max_node_id + 1); // exit(2); int* sign = (int *)malloc(sizeof(int) * (max_node_id + 1)); for (int i = 0; i < max_node_id + 1; i++) { sign[i] = 0; } // start with a certain node, if all node visited, so that the graph is connected int start_id = G[0].node_id; tagged((int *)sign, node_count, start_id, max_node_id); // display_graph2(id2Node, max_node_id + 1); check_child(id2Node, node_count, start_id, sign, max_node_id); for (int i = 0; i < node_count; i ++) { if (sign[G[i].node_id] == 0) { free(sign); return 0; } } free(sign); return 1; }
int main(int argc, char *argv[]) { struct ntpd_conf lconf; struct pollfd pfd[POLL_MAX]; pid_t chld_pid = 0, pid; const char *conffile; int fd_ctl, ch, nfds; int pipe_chld[2]; struct passwd *pw; extern char *__progname; if (strcmp(__progname, "ntpctl") == 0) { ctl_main(argc, argv); /* NOTREACHED */ } conffile = CONFFILE; bzero(&lconf, sizeof(lconf)); log_init(1); /* log to stderr until daemonized */ while ((ch = getopt(argc, argv, "df:nsSv")) != -1) { switch (ch) { case 'd': lconf.debug = 1; log_verbose(1); break; case 'f': conffile = optarg; break; case 'n': lconf.noaction = 1; break; case 's': lconf.settime = 1; break; case 'S': lconf.settime = 0; break; case 'v': log_verbose(1); break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc > 0) usage(); if (parse_config(conffile, &lconf)) exit(1); if (lconf.noaction) { fprintf(stderr, "configuration OK\n"); exit(0); } if (geteuid()) errx(1, "need root privileges"); if ((pw = getpwnam(NTPD_USER)) == NULL) errx(1, "unknown user %s", NTPD_USER); if (setpriority(PRIO_PROCESS, 0, -20) == -1) warn("can't set priority"); reset_adjtime(); if (!lconf.settime) { log_init(lconf.debug); if (!lconf.debug) if (daemon(1, 0)) fatal("daemon"); } else timeout = SETTIME_TIMEOUT * 1000; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) fatal("socketpair"); if ((fd_ctl = control_init(CTLSOCKET)) == -1) fatalx("control socket init failed"); if (control_listen(fd_ctl) == -1) fatalx("control socket listen failed"); signal(SIGCHLD, sighdlr); /* fork child process */ chld_pid = ntp_main(pipe_chld, fd_ctl, &lconf, pw); setproctitle("[priv]"); readfreq(); signal(SIGTERM, sighdlr); signal(SIGINT, sighdlr); signal(SIGHUP, sighdlr); close(pipe_chld[1]); if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); imsg_init(ibuf, pipe_chld[0]); while (quit == 0) { pfd[PFD_PIPE].fd = ibuf->fd; pfd[PFD_PIPE].events = POLLIN; if (ibuf->w.queued) pfd[PFD_PIPE].events |= POLLOUT; if ((nfds = poll(pfd, 1, timeout)) == -1) if (errno != EINTR) { log_warn("poll error"); quit = 1; } if (nfds == 0 && lconf.settime) { lconf.settime = 0; timeout = INFTIM; log_init(lconf.debug); log_warnx("no reply received in time, skipping initial " "time setting"); if (!lconf.debug) if (daemon(1, 0)) fatal("daemon"); } if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT)) if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) { log_warn("pipe write error (to child)"); quit = 1; } if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) { nfds--; if (dispatch_imsg(&lconf) == -1) quit = 1; } if (sigchld) { if (check_child(chld_pid, "child")) { quit = 1; chld_pid = 0; } sigchld = 0; } } signal(SIGCHLD, SIG_DFL); if (chld_pid) kill(chld_pid, SIGTERM); do { if ((pid = wait(NULL)) == -1 && errno != EINTR && errno != ECHILD) fatal("wait"); } while (pid != -1 || (pid == -1 && errno == EINTR)); msgbuf_clear(&ibuf->w); free(ibuf); log_info("Terminating"); return (0); }
int main (int argc, char *argv[]) { int use_stdin = 0; FILE *newsfile; FILE *newsfile_copy; char *bodyfile_name = NULL; FILE *bodyfile_r; FILE *bodyfile_w; char *mergefile_name = NULL; FILE *mergefile; #if defined(MAINLOOP) volatile int w = 1; while (w); #endif parse_commandline (argc, argv); if (printversion) { printf ("%s (" PACKAGE ") " VERSION "\n", Name); return 0; } if (!strcmp (newsfile_name, "-")) { use_stdin = 1; newsfile_name = nb_tmpnam (); newsfile_copy = open_write (newsfile_name); newsfile = stdin; mergefile = stdout; } else { newsfile_copy = NULL; newsfile = open_read (newsfile_name); mergefile_name = nb_tmpnam (); mergefile = open_write (mergefile_name); } if (filter) { expand_argv (new_argv, "-"); exec_filter (new_argv, &bodyfile_w, &bodyfile_r); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); newsfile = open_read (newsfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); check_child (); } else { bodyfile_name = nb_tmpnam (); bodyfile_w = open_write (bodyfile_name); expand_argv (new_argv, bodyfile_name); writebody (newsfile, newsfile_copy, bodyfile_w, remove_header, remove_quote, remove_sig, keep); exec_program (new_argv); check_child (); newsfile = open_read (newsfile_name); bodyfile_r = open_read (bodyfile_name); readbody (newsfile, bodyfile_r, mergefile, remove_header, remove_quote, remove_sig, keep); } if (use_stdin) nb_unlink (newsfile_name); else nb_rename (mergefile_name, newsfile_name); if (!filter) nb_unlink (bodyfile_name); return 0; }
int main(int argc, char *argv[]) { struct ntpd_conf conf; struct pollfd pfd[POLL_MAX]; pid_t chld_pid = 0, pid; const char *conffile; int ch, nfds, timeout = INFTIM; int pipe_chld[2]; extern char *__progname; __progname = _compat_get_progname(argv[0]); conffile = CONFFILE; bzero(&conf, sizeof(conf)); log_init(1); /* log to stderr until daemonized */ res_init(); /* XXX */ while ((ch = getopt(argc, argv, "df:sS")) != -1) { switch (ch) { case 'd': conf.debug = 1; break; case 'f': conffile = optarg; break; case 's': conf.settime = 1; break; case 'S': conf.settime = 0; break; default: usage(); /* NOTREACHED */ } } if (parse_config(conffile, &conf)) exit(1); if (geteuid()) { fprintf(stderr, "ntpd: need root privileges\n"); exit(1); } if (getpwnam(NTPD_USER) == NULL) { fprintf(stderr, "ntpd: unknown user %s\n", NTPD_USER); exit(1); } endpwent(); #ifndef HAVE_ARC4RANDOM seed_rng(); #endif if (!conf.settime) { log_init(conf.debug); if (!conf.debug) if (daemon(1, 0)) fatal("daemon"); } else timeout = SETTIME_TIMEOUT * 1000; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) fatal("socketpair"); /* fork child process */ chld_pid = ntp_main(pipe_chld, &conf); setproctitle("[priv]"); signal(SIGTERM, sighdlr); signal(SIGINT, sighdlr); signal(SIGCHLD, sighdlr); signal(SIGHUP, sighdlr); close(pipe_chld[1]); if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); imsg_init(ibuf, pipe_chld[0]); while (quit == 0) { pfd[PFD_PIPE].fd = ibuf->fd; pfd[PFD_PIPE].events = POLLIN; if (ibuf->w.queued) pfd[PFD_PIPE].events |= POLLOUT; if ((nfds = poll(pfd, 1, timeout)) == -1) if (errno != EINTR) { log_warn("poll error"); quit = 1; } if (nfds == 0 && conf.settime) { conf.settime = 0; timeout = INFTIM; // RCP // log_init(conf.debug); // log_debug("no reply received in time, skipping initial " // "time setting"); // if (!conf.debug) // if (daemon(1, 0)) // fatal("daemon"); // RCP system("/opt/rcp/bin/rcplog 5 \"no replay received in time, restarting NTP\""); break; // RCP } if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT)) if (msgbuf_write(&ibuf->w) < 0) { log_warn("pipe write error (to child)"); quit = 1; } if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) { nfds--; if (dispatch_imsg(&conf) == -1) quit = 1; } if (sigchld) { if (check_child(chld_pid, "child")) { quit = 1; chld_pid = 0; } sigchld = 0; } } signal(SIGCHLD, SIG_DFL); if (chld_pid) kill(chld_pid, SIGTERM); do { if ((pid = wait(NULL)) == -1 && errno != EINTR && errno != ECHILD) fatal("wait"); } while (pid != -1 || (pid == -1 && errno == EINTR)); msgbuf_clear(&ibuf->w); free(ibuf); // log_info("Terminating"); return (0); }
/* * Run one client loop. Return -1 to exit */ static int do_client(BINKD_CONFIG *config) { FTN_NODE *r; int pid; if (!config->q_present) { q_free (SCAN_LISTED, config); if (config->printq) Log (-1, "scan\r"); q_scan (SCAN_LISTED, config); config->q_present = 1; if (config->printq) { LockSem (&lsem); q_list (stderr, SCAN_LISTED, config); ReleaseSem (&lsem); Log (-1, "idle\r"); } } if (n_clients < config->max_clients) { if ((r = q_next_node (config)) != 0) { struct call_args args; if (!bsy_test (&r->fa, F_BSY, config) || !bsy_test (&r->fa, F_CSY, config)) { char szDestAddr[FTN_ADDR_SZ + 1]; ftnaddress_to_str (szDestAddr, &r->fa); Log (4, "%s busy, skipping", szDestAddr); return 0; /* go to the next node */ } rel_grow_handles (6); threadsafe(++n_clients); lock_config_structure(config); args.node = r; args.config = config; if ((pid = branch (call, &args, sizeof (args))) < 0) { unlock_config_structure(config, 0); rel_grow_handles (-6); threadsafe(--n_clients); PostSem(&eothread); Log (1, "cannot branch out"); unblocksig(); SLEEP(1); blocksig(); check_child(&n_clients); } #if !defined(DEBUGCHILD) else { Log (5, "started client #%i, id=%i", n_clients, pid); #if defined(HAVE_FORK) && !defined(AMIGA) unlock_config_structure(config, 0); /* Forked child has own copy */ #endif } #endif } else { if (poll_flag) { if (n_clients <= 0 && q_not_empty (config) == 0) { Log (4, "the queue is empty, quitting..."); return -1; } } else config->q_present = 0; unblocksig(); SLEEP (config->rescan_delay); blocksig(); check_child(&n_clients); } } else { unblocksig(); SLEEP (config->call_delay); blocksig(); check_child(&n_clients); } return 0; }
int main(int ac, char **av) { int lc; const char *msg; int fd_notify_backup = -1; if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { int ret, len = 0, i = 0, test_num = 0; if (fd_notify_backup == -1) { fd_notify_backup = dup(fd_notify); if (fd_notify_backup < 0) tst_brkm(TBROK | TERRNO, cleanup, "dup(%d) failed", fd_notify); } run_child(); tst_count = 0; event_set[tst_count] = FAN_OPEN_PERM; event_resp[tst_count++] = FAN_ALLOW; event_set[tst_count] = FAN_ACCESS_PERM; event_resp[tst_count++] = FAN_DENY; /* tst_count + 1 is for checking child return value */ if (TST_TOTAL != tst_count + 1) { tst_brkm(TBROK, cleanup, "TST_TOTAL and tst_count do not match"); } tst_count = 0; /* * check events */ while (test_num < TST_TOTAL && fd_notify != -1) { struct fanotify_event_metadata *event; if (i == len) { /* Get more events */ ret = read(fd_notify, event_buf + len, EVENT_BUF_LEN - len); if (fd_notify == -1) break; if (ret < 0) { tst_brkm(TBROK, cleanup, "read(%d, buf, %zu) failed", fd_notify, EVENT_BUF_LEN); } len += ret; } event = (struct fanotify_event_metadata *)&event_buf[i]; if (!(event->mask & event_set[test_num])) { tst_resm(TFAIL, "get event: mask=%llx (expected %llx) " "pid=%u fd=%u", (unsigned long long)event->mask, event_set[test_num], (unsigned)event->pid, event->fd); } else if (event->pid != child_pid) { tst_resm(TFAIL, "get event: mask=%llx pid=%u " "(expected %u) fd=%u", (unsigned long long)event->mask, (unsigned)event->pid, (unsigned)child_pid, event->fd); } else { tst_resm(TPASS, "get event: mask=%llx pid=%u fd=%u", (unsigned long long)event->mask, (unsigned)event->pid, event->fd); } /* Write response to permission event */ if (event_set[test_num] & FAN_ALL_PERM_EVENTS) { struct fanotify_response resp; resp.fd = event->fd; resp.response = event_resp[test_num]; SAFE_WRITE(cleanup, 1, fd_notify, &resp, sizeof(resp)); } event->mask &= ~event_set[test_num]; /* No events left in current mask? Go for next event */ if (event->mask == 0) { i += event->event_len; close(event->fd); } test_num++; } for (; test_num < TST_TOTAL - 1; test_num++) { tst_resm(TFAIL, "didn't get event: mask=%llx", event_set[test_num]); } check_child(); /* We got SIGCHLD while running, resetup fd_notify */ if (fd_notify == -1) { fd_notify = fd_notify_backup; fd_notify_backup = -1; } } cleanup(); tst_exit(); }
int main(int argc, char *const *argv) { int c, /* control descriptor (stdin) */ s; /* socket descriptor (PuTTY) */ Buffer cbuf, /* control buffer */ pbuf, /* pty buffer */ sbuf; /* socket buffer */ DBUG_INIT_ENV("main",argv[0],"DBUG_OPTS"); #ifndef DBUG_OFF setvbuf(DBUG_FILE, 0, _IONBF, 0); #endif /* General steps: 1. connect to cygterm backend 2. create pty 3. fork child process (/bin/bash) 4. select on pty, cygterm backend forwarding pty data and messages */ if (argc < 4) { DBUG_PRINT("error", ("Too few arguments")); DBUG_RETURN(CthelperInvalidUsage); } DBUG_PRINT("startup", ("isatty: (%d,%d,%d)", isatty(STDIN_FILENO), isatty(STDOUT_FILENO), isatty(STDERR_FILENO))); DBUG_PRINT("startup", ( "cmdline: [%s] %s %s %s ...", argv[0], argv[1], argv[2], argv[3])); { extern char **environ; char **envp; for (envp = environ; *envp; envp++) DBUG_PRINT("startup", ("%s", *envp)); } /* It is not necessary to close all open descriptors. There are no * files inherited from the PuTTY process except standard input. */ #ifndef DEBUG close(STDERR_FILENO); #endif /* Duplicate c and open /dev/null as 0 so that 0 can mean "closed". */ c = dup(STDIN_FILENO); close(STDIN_FILENO); open("/dev/null", O_RDWR); /* Command line: * argv[1] = port number * argv[2] = terminal name * argv[3] = terminal characteristics string * Any remaining arguments are the command to execute. If there are no * other arguments, use the user's default login shell with a - prefix * for its argv[0]. */ /* cthelper command line parameters: cthelper PORT TERM ATTRS [COMMAND [ARGS]] PORT port number for PuTTY pty input data socket TERM name of terminal (set TERM environment variable) ATTRS a colon-separated list of terminal attributes See init_pty() for details. COMMAND Runs COMMAND with ARGS as child process. If COMMAND is not supplied, cthelper will run the user's login shell as specified in /etc/passwd specifying "-" for its argv[0] as typical. */ /* connect to cygterm */ { int ct_port = strtol(argv[1], 0, 0); #ifdef DEBUG if (ct_port == 0) { /* For debugging purposes, make the tty we are started * in the "socket". This allows to test cthelper without * putty.exe */ assert(isatty(STDOUT_FILENO)); raw(); atexit(restore); c = open("/dev/null", O_RDONLY); s = dup(STDOUT_FILENO); } else #endif if (ct_port <= 0) { DBUG_PRINT("startup", ("invalid port")); DBUG_RETURN(CthelperInvalidPort); } DBUG_PRINT("startup", ("connect cygterm")); if (0 > (s = connect_cygterm(ct_port))) { DBUG_PRINT("startup", ("connect_cygterm: bad")); DBUG_RETURN(CthelperConnectFailed); } DBUG_PRINT("startup", ("OK")); } /* initialize buffers */ DBUG_PRINT("startup", ("initialize buffers")); BUFFER_ALLOCA(cbuf, CTLBUF); BUFFER_ALLOCA(pbuf, PTOBUF); BUFFER_ALLOCA(sbuf, PTIBUF); /* set up signal handling */ signal(SIGCHLD, handle_sigchld); /* start child process */ if (0 > (t = setup_child(&child, argv[2], argv[3], argv + 4))) { DBUG_PRINT("startup", ("setup_child failed: %s", strerror(-t))); DBUG_RETURN(CthelperPtyforkFailure); } /* To explain what is happening here: * 's' is the socket between PuTTY and cthelper; it is read to get * input for the tty and written to display output from the pty. * 't' is the pseudo terminal; it is read to get pty input which is sent to * PuTTY and written to pass input from PuTTY to the pty. * 'c' is standard input, which is a one-way anonymous pipe from PuTTY. * It is read to receive special messages from PuTTY such as * terminal resize events. * * This is the flow of data through the buffers: * s => sbuf => t * t => pbuf => s * c => cbuf => process_message() * * When 't' is closed, we close(s) to signal PuTTY we are done. * When 's' is closed, we kill(child, HUP) to kill the child process. */ setnonblock(c); setnonblock(s); setnonblock(t); DBUG_PRINT("info", ("c==%d, s==%d, t==%d", c, s, t)); /* allow easy select() and FD_ISSET() stuff */ assert(0 < c && c < s && s < t); DBUG_PRINT("startup", ("starting select loop")); while (s || t) { int n = 0; fd_set r, w; DBUG_ENTER("select"); FD_ZERO(&r); FD_ZERO(&w); if (c && !buffer_isfull(cbuf)) { FD_SET(c, &r); n = c; } if (s && !buffer_isfull(sbuf)) { FD_SET(s, &r); n = s; } if (s && !buffer_isempty(pbuf)) { FD_SET(s, &w); n = s; } if (t && !buffer_isfull(pbuf)) { FD_SET(t, &r); n = t; } if (t && !buffer_isempty(sbuf)) { FD_SET(t, &w); n = t; } switch (n = select(n + 1, &r, &w, 0, 0)) { case -1: DBUG_PRINT("error", ("%s", strerror(errno))); if (errno != EINTR) { /* Something bad happened */ close(c); c = 0; close(s); s = 0; close(t); t = 0; } break; case 0: DBUG_PRINT("info", ("select timeout")); break; default: DBUG_PRINT("info", ("%d ready descriptors [[r==%lx,w==%lx]]", n, *(unsigned long *)&r, *(unsigned long *)&w)); if (FD_ISSET(c, &r)) { DBUG_ENTER("c=>cbuf"); switch (buffer_read(cbuf, c)) { case -1: DBUG_PRINT("error", ("error reading c: %s", strerror(errno))); if (errno == EINTR || errno == EWOULDBLOCK) break; /*FALLTHRU*/ case 0: /* PuTTY closed the message pipe */ DBUG_PRINT("io", ("c closed")); close(c); c = 0; break; default: DBUG_PRINT("io", ("cbuf => process_message()")); process_message(cbuf, t); break; } DBUG_LEAVE; if (!--n) break; } if (FD_ISSET(s, &r)) { DBUG_ENTER("s=>sbuf"); switch (buffer_read(sbuf, s)) { case -1: DBUG_PRINT("error", ("error reading s: %s", strerror(errno))); if (errno == EINTR || errno == EWOULDBLOCK) break; /*FALLTHRU*/ case 0: /* PuTTY closed the socket */ DBUG_PRINT("io", ("s closed")); close(s); s = 0; break; default: FD_SET(t, &w); break; } DBUG_LEAVE; if (!--n) break; } if (FD_ISSET(t, &r)) { DBUG_ENTER("t=>pbuf"); switch (buffer_read(pbuf, t)) { case -1: DBUG_PRINT("error", ("error reading t: %s", strerror(errno))); if (errno == EINTR || errno == EWOULDBLOCK) break; /*FALLTHRU*/ case 0: /* pty closed */ DBUG_PRINT("io", ("t closed")); if (!FD_ISSET(t, &w)) { close(t); t = 0; } break; default: FD_SET(s, &w); break; } DBUG_LEAVE; if (!--n) break; } if (FD_ISSET(t, &w)) { DBUG_ENTER("sbuf=>t"); switch (buffer_write(sbuf, t)) { case -1: DBUG_PRINT("error", ("error writing t: %s", strerror(errno))); if (errno == EINTR || errno == EWOULDBLOCK) break; /*FALLTHRU*/ case 0: /* pty closed */ DBUG_PRINT("io", ("t closed")); close(t); t = 0; break; } DBUG_LEAVE; if (!--n) break; } if (FD_ISSET(s, &w)) { DBUG_ENTER("pbuf=>s"); switch (buffer_write(pbuf, s)) { case -1: DBUG_PRINT("error", ("error writing s: %s", strerror(errno))); if (errno == EINTR || errno == EWOULDBLOCK) break; /*FALLTHRU*/ case 0: /* PuTTY closed the socket */ DBUG_PRINT("io", ("s closed")); close(s); s = 0; break; } DBUG_LEAVE; if (!--n) break; } DBUG_PRINT("info", ("[[n==%d,r==%lx,w==%lx]]", n, *(unsigned long *)&r, *(unsigned long *)&w)); assert(n == 0); break; } if (child_signalled) check_child(); if (!t && buffer_isempty(pbuf)) { DBUG_PRINT("info", ("shutdown socket")); shutdown(s, SHUT_WR); } if (!s && buffer_isempty(sbuf) && child_alive()) { DBUG_PRINT("sig", ("kill child")); kill(child, SIGHUP); /* handle_sigchld() will close(t) */ } DBUG_LEAVE; } DBUG_PRINT("info", ("end of select loop")); /* ensure child process killed */ /* XXX I'm not sure if all of this is necessary, but it probably won't * hurt anything. */ if (child_alive() && sleep(1) == 0) { DBUG_PRINT("sig", ("waiting for child")); waitpid(child, 0, WNOHANG); } DBUG_PRINT("info", ("goodbye")); if (exit_status == 111) DBUG_RETURN(CthelperExecFailure); DBUG_RETURN(EXIT_SUCCESS); }
static int do_server(BINKD_CONFIG *config) { struct addrinfo *ai, *aiHead, hints; int aiErr; SOCKET new_sockfd; int pid; socklen_t client_addr_len; struct sockaddr_storage client_addr; int opt = 1; int save_errno; struct listenchain *listen_list; /* setup hints for getaddrinfo */ memset((void *)&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; for (listen_list = config->listen.first; listen_list; listen_list = listen_list->next) { if ((aiErr = getaddrinfo(listen_list->addr[0] ? listen_list->addr : NULL, listen_list->port, &hints, &aiHead)) != 0) { Log(0, "servmgr getaddrinfo: %s (%d)", gai_strerror(aiErr), aiErr); return -1; } for (ai = aiHead; ai != NULL && sockfd_used < MAX_LISTENSOCK; ai = ai->ai_next) { sockfd[sockfd_used] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd[sockfd_used] < 0) { Log (0, "servmgr socket(): %s", TCPERR ()); continue; } #ifdef UNIX /* Not sure how to set NOINHERIT flag for socket on Windows and OS/2 */ if (fcntl(sockfd[sockfd_used], F_SETFD, FD_CLOEXEC) != 0) Log(1, "servmgr fcntl set FD_CLOEXEC error: %s", strerror(errno)); #endif #ifdef IPV6_V6ONLY if (ai->ai_family == PF_INET6) { int v6only = 1; if (setsockopt(sockfd[sockfd_used], IPPROTO_IPV6, IPV6_V6ONLY, (char *) &v6only, sizeof(v6only)) == SOCKET_ERROR) Log(1, "servmgr setsockopt (IPV6_V6ONLY): %s", TCPERR()); } #endif if (setsockopt (sockfd[sockfd_used], SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof opt) == SOCKET_ERROR) Log (1, "servmgr setsockopt (SO_REUSEADDR): %s", TCPERR ()); if (bind (sockfd[sockfd_used], ai->ai_addr, ai->ai_addrlen) != 0) { Log (0, "servmgr bind(): %s", TCPERR ()); soclose(sockfd[sockfd_used]); continue; } if (listen (sockfd[sockfd_used], 5) != 0) { Log(0, "servmgr listen(): %s", TCPERR ()); soclose(sockfd[sockfd_used]); continue; } sockfd_used++; } Log (3, "servmgr listen on %s:%s", listen_list->addr[0] ? listen_list->addr : "*", listen_list->port); freeaddrinfo(aiHead); } if (sockfd_used == 0) { Log(0, "servmgr: No listen socket open"); return -1; } setproctitle ("server manager (listen %s)", config->listen.first->port); for (;;) { struct timeval tv; int n; int curfd, maxfd = 0; fd_set r; FD_ZERO (&r); for (curfd=0; curfd<sockfd_used; curfd++) { FD_SET (sockfd[curfd], &r); if (sockfd[curfd] > maxfd) maxfd = sockfd[curfd]; } tv.tv_usec = 0; tv.tv_sec = CHECKCFG_INTERVAL; unblocksig(); check_child(&n_servers); n = select(maxfd+1, &r, NULL, NULL, &tv); blocksig(); switch (n) { case 0: /* timeout */ if (checkcfg()) { for (curfd=0; curfd<sockfd_used; curfd++) soclose(sockfd[curfd]); sockfd_used = 0; return 0; } unblocksig(); check_child(&n_servers); blocksig(); continue; case -1: save_errno = TCPERRNO; if (binkd_exit) goto accepterr; if (TCPERRNO == EINTR) { unblocksig(); check_child(&n_servers); blocksig(); if (checkcfg()) { for (curfd=0; curfd<sockfd_used; curfd++) soclose(sockfd[curfd]); sockfd_used = 0; return 0; } continue; } Log (1, "servmgr select(): %s", TCPERR ()); goto accepterr; } for (curfd=0; curfd<sockfd_used; curfd++) { if (!FD_ISSET(sockfd[curfd], &r)) continue; client_addr_len = sizeof (client_addr); if ((new_sockfd = accept (sockfd[curfd], (struct sockaddr *)&client_addr, &client_addr_len)) == INVALID_SOCKET) { save_errno = TCPERRNO; if (save_errno != EINVAL && save_errno != EINTR) { if (!binkd_exit) Log (1, "servmgr accept(): %s", TCPERR ()); #ifdef UNIX if (save_errno == ECONNRESET || save_errno == ETIMEDOUT || save_errno == ECONNABORTED || save_errno == EHOSTUNREACH) continue; #endif accepterr: #ifdef OS2 /* Buggy external process closed our socket? Or OS/2 bug? */ if (save_errno == ENOTSOCK) return 0; /* will force socket re-creation */ #endif return -1; } } else { char host[BINKD_FQDNLEN + 1]; char service[MAXSERVNAME + 1]; int aiErr; add_socket(new_sockfd); /* Was the socket created after close_sockets loop in exitfunc()? */ if (binkd_exit) { del_socket(new_sockfd); soclose(new_sockfd); continue; } rel_grow_handles (6); ext_rand=rand(); /* never resolve name in here, will be done during session */ aiErr = getnameinfo((struct sockaddr *)&client_addr, client_addr_len, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); if (aiErr == 0) Log (3, "incoming from %s (%s)", host, service); else { Log(2, "Error in getnameinfo(): %s (%d)", gai_strerror(aiErr), aiErr); Log(3, "incoming from unknown"); } /* Creating a new process for the incoming connection */ threadsafe(++n_servers); if ((pid = branch (serv, (void *) &new_sockfd, sizeof (new_sockfd))) < 0) { del_socket(new_sockfd); soclose(new_sockfd); rel_grow_handles (-6); threadsafe(--n_servers); PostSem(&eothread); Log (1, "servmgr branch(): cannot branch out"); sleep(1); } else { Log (5, "started server #%i, id=%i", n_servers, pid); #if defined(HAVE_FORK) && !defined(HAVE_THREADS) soclose (new_sockfd); #endif } } } } }