if ((pw = calloc(1, sizeof(struct passwd))) == NULL) fatal(NULL, errno);  if ((pw = getpwnam(BGPD_USER)) == NULL) fatal(NULL, errno);
session_main(struct bgpd_config *config, int pipe_m2s[2], int pipe_s2r[2]){	int		 sock, nfds, i, j, timeout;	pid_t		 pid;	time_t		 nextaction;	struct passwd	*pw;	struct peer	*p, *peers[OPEN_MAX], *last, *next;	struct pollfd	 pfd[OPEN_MAX];	conf = config;	if ((pw = calloc(1, sizeof(struct passwd))) == NULL)		fatal(NULL, errno);	if ((pw = getpwnam(BGPD_USER)) == NULL)		fatal(NULL, errno);	switch (pid = fork()) {	case -1:		fatal("cannot fork", errno);	case 0:		break;	default:		return (pid);	}	if (chroot(pw->pw_dir) < 0)		fatal("chroot failed", errno);	chdir("/");	setproctitle("session engine");	if ((sock = setup_listener()) < 0)		fatal("listener setup failed", 0);	if (setgroups(1, &pw->pw_gid) ||	    setegid(pw->pw_gid) || setgid(pw->pw_gid) ||	    seteuid(pw->pw_uid) || setuid(pw->pw_uid))		fatal("can't drop privileges", errno);	signal(SIGTERM, session_sighdlr);	logit(LOG_INFO, "session engine ready");	s2r_sock = pipe_s2r[0];	close(pipe_m2s[0]);	close(pipe_s2r[1]);	init_imsg_buf();	init_peers();	while (session_quit == 0) {		bzero(&pfd, sizeof(pfd));		pfd[PFD_LISTEN].fd = sock;		pfd[PFD_LISTEN].events = POLLIN;		pfd[PFD_PIPE_MAIN].fd = pipe_m2s[1];		pfd[PFD_PIPE_MAIN].events = POLLIN;		pfd[PFD_PIPE_ROUTE].fd = pipe_s2r[0];		pfd[PFD_PIPE_ROUTE].events = POLLIN;		if (s2r_queued_writes > 0)			pfd[PFD_PIPE_ROUTE].events |= POLLOUT;		nextaction = time(NULL) + 240;	/* loop every 240s at least */		i = PFD_PEERS_START;		last = NULL;		for (p = conf->peers; p != NULL; p = next) {			next = p->next;			if (!pending_reconf) {				/* needs init? */				if (p->state == STATE_NONE)					change_state(p, STATE_IDLE, EVNT_NONE);				/* reinit due? */				if (p->conf.reconf_action == RECONF_REINIT) {					bgp_fsm(p, EVNT_STOP);					p->StartTimer = time(NULL);				}				/* deletion due? */				if (p->conf.reconf_action == RECONF_DELETE) {					bgp_fsm(p, EVNT_STOP);					log_errx(p, "removed");					if (last != NULL)						last->next = next;					else						conf->peers = next;					free(p);					continue;				}				p->conf.reconf_action = RECONF_NONE;			}			last = p;			/* check timers */			if (timer_due(p->HoldTimer))				bgp_fsm(p, EVNT_TIMER_HOLDTIME);			if (timer_due(p->ConnectRetryTimer))				bgp_fsm(p, EVNT_TIMER_CONNRETRY);			if (timer_due(p->KeepaliveTimer))				bgp_fsm(p, EVNT_TIMER_KEEPALIVE);			if (timer_due(p->StartTimer))				bgp_fsm(p, EVNT_START);			/* set nextaction to the first expiring timer */			if (p->ConnectRetryTimer &&			    p->ConnectRetryTimer < nextaction)				nextaction = p->ConnectRetryTimer;			if (p->HoldTimer && p->HoldTimer < nextaction)				nextaction = p->HoldTimer;			if (p->KeepaliveTimer && p->KeepaliveTimer < nextaction)				nextaction = p->KeepaliveTimer;			if (p->StartTimer && p->StartTimer < nextaction)				nextaction = p->StartTimer;			/* are we waiting for a write? */			if (p->queued_writes > 0)				p->events |= POLLOUT;			/* poll events */			if (p->sock != -1 && p->events != 0) {				pfd[i].fd = p->sock;				pfd[i].events = p->events;				peers[i] = p;				i++;			}		}		timeout = nextaction - time(NULL);		if (timeout < 0)			timeout = 0;		nfds = poll(pfd, i, timeout * 1000);		/*		 * what do we do on poll error?		 */		if (nfds > 0 && pfd[PFD_LISTEN].revents & POLLIN) {			nfds--;			session_accept(sock);		}		if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLIN) {			nfds--;			session_dispatch_imsg(pfd[PFD_PIPE_MAIN].fd,			    PFD_PIPE_MAIN);		}		if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLOUT)			session_write_imsg(pfd[PFD_PIPE_ROUTE].fd);		if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLIN) {			nfds--;			session_dispatch_imsg(pfd[PFD_PIPE_ROUTE].fd,			    PFD_PIPE_ROUTE);		}		for (j = PFD_PEERS_START; nfds > 0 && j < i; j++) {			nfds -= session_dispatch_msg(&pfd[j], peers[j]);		}	}	session_terminate();	shutdown(sock, SHUT_RDWR);	close(sock);	logit(LOG_INFO, "session engine exiting");	_exit(0);}