* to do, and decide if we need to to block
* to do, and decide if we need to block
main(ac, av)	int	ac;	char	**av;{	PLAYER		*pp;	int		had_char;	static fd_set	read_fds;	static FLAG	first = TRUE;	static FLAG	server = FALSE;	extern int	optind;	extern char	*optarg;	int		c;	static struct timeval	linger = { 0, 0 };	static struct timeval	timeout = { 0, 0 }, *to;	struct spawn	*sp, *spnext;	int		ret;	int		nready;	int		fd;	First_arg = av[0];	config();	while ((c = getopt(ac, av, "sp:a:D:")) != -1) {		switch (c) {		  case 's':			server = TRUE;			break;		  case 'p':			should_announce = FALSE;			Server_port = atoi(optarg);			break;		  case 'a':			if (!inet_aton(optarg, (struct in_addr *)&Server_addr))				err(1, "bad interface address: %s", optarg);			break;		  case 'D':			config_arg(optarg);			break;		  default:erred:			fprintf(stderr, "Usage: %s [-s] [-p port] [-a addr]\n",			    av[0]);			exit(2);		}	}	if (optind < ac)		goto erred;	/* Open syslog: */	openlog("huntd", LOG_PID | (conf_logerr && !server? LOG_PERROR : 0),		LOG_DAEMON);	/* Initialise game parameters: */	init();again:	do {		/* First, poll to see if we can get input */		do {			read_fds = Fds_mask;			errno = 0;			timerclear(&timeout);			nready = select(Num_fds, &read_fds, NULL, NULL, 			    &timeout);			if (nready < 0 && errno != EINTR) {				log(LOG_ERR, "select");				cleanup(1);			}		} while (nready < 0);		if (nready == 0) {			/*			 * Nothing was ready. We do some work now			 * to see if the simulation has any pending work			 * to do, and decide if we need to to block 			 * indefinitely or just timeout.			 */			do {				if (conf_simstep && can_moveshots()) {				/*				 * block for a short time before continuing				 * with explosions, bullets and whatnot				 */					to = &timeout;					to->tv_sec =  conf_simstep / 1000000;					to->tv_usec = conf_simstep % 1000000;				} else				/*				 * since there's nothing going on,				 * just block waiting for external activity				 */					to = NULL;								read_fds = Fds_mask;				errno = 0;				nready = select(Num_fds, &read_fds, NULL, NULL, 				    to);				if (nready < 0 && errno != EINTR) {					log(LOG_ERR, "select");					cleanup(1);				}			} while (nready < 0);		}		/* Remember which descriptors are active: */		Have_inp = read_fds;		/* Answer new player connections: */		if (FD_ISSET(Socket, &Have_inp))			answer_first();		/* Continue answering new player connections: */		for (sp = Spawn; sp; ) {			spnext = sp->next;			fd = sp->fd;			if (FD_ISSET(fd, &Have_inp) && answer_next(sp)) {				/*				 * Remove from the spawn list. (fd remains in 				 * read set).				 */				*sp->prevnext = sp->next;				if (sp->next)					sp->next->prevnext = sp->prevnext;				free(sp);				/* We probably consumed all data. */				FD_CLR(fd, &Have_inp);				/* Announce game if this is the first spawn. */				if (first && should_announce)					announce_game();				first = FALSE;			} 			sp = spnext;		}		/* Process input and move bullets until we've exhausted input */		had_char = TRUE;		while (had_char) {			moveshots();			for (pp = Player; pp < End_player; )				if (pp->p_death[0] != '\0')					zap(pp, TRUE);				else					pp++;			for (pp = Monitor; pp < End_monitor; )				if (pp->p_death[0] != '\0')					zap(pp, FALSE);				else					pp++;			had_char = FALSE;			for (pp = Player; pp < End_player; pp++)				if (havechar(pp)) {					execute(pp);					pp->p_nexec++;					had_char = TRUE;				}			for (pp = Monitor; pp < End_monitor; pp++)				if (havechar(pp)) {					mon_execute(pp);					pp->p_nexec++;					had_char = TRUE;				}		}		/* Handle a datagram sent to the server socket: */		if (FD_ISSET(Server_socket, &Have_inp))			handle_wkport(Server_socket);		/* Answer statistics connections: */		if (FD_ISSET(Status, &Have_inp))			send_stats();		/* Flush/synchronize all the displays: */		for (pp = Player; pp < End_player; pp++) {			if (FD_ISSET(pp->p_fd, &read_fds)) {				sendcom(pp, READY, pp->p_nexec);				pp->p_nexec = 0;			}			flush(pp);		}		for (pp = Monitor; pp < End_monitor; pp++) {			if (FD_ISSET(pp->p_fd, &read_fds)) {				sendcom(pp, READY, pp->p_nexec);				pp->p_nexec = 0;			}			flush(pp);		}	} while (Nplayer > 0);	/* No more players! */	/* No players yet or a continuous game? */	if (first || conf_linger < 0)		goto again;	/* Wait a short while for one to come back: */	read_fds = Fds_mask;	linger.tv_sec = conf_linger;	while ((ret = select(Num_fds, &read_fds, NULL, NULL, &linger)) < 0) {		if (errno != EINTR) {			log(LOG_WARNING, "select");			break;		}		read_fds = Fds_mask;		linger.tv_sec = conf_linger;		linger.tv_usec = 0;	}	if (ret > 0)		/* Someone returned! Resume the game: */		goto again;	/* else, it timed out, and the game is really over. */	/* If we are an inetd server, we should re-init the map and restart: */	if (server) {		clear_scores();		makemaze();		clearwalls();		makeboots();		first = TRUE;		goto again;	}	/* Get rid of any attached monitors: */	for (pp = Monitor; pp < End_monitor; )		zap(pp, FALSE);	/* Fin: */	cleanup(0);	exit(0);}