示例#1
0
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;
}
示例#2
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);
        }
    }
}
示例#3
0
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;
}
示例#4
0
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);
}
示例#5
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;
}
示例#6
0
文件: ntpd.c 项目: a5216652166/rcp100
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);
}
示例#7
0
文件: client.c 项目: askovpen/binkd
/*
 * 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;
}
示例#8
0
文件: fanotify03.c 项目: MohdVara/ltp
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();
}
示例#9
0
文件: cthelper.c 项目: Chaz6/futty
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);
}
示例#10
0
文件: server.c 项目: wvvelzen/binkd
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
        }
      }
    }
  }
}