* An error occured in select? Just die
* An error occurred in select? Just die
main(argc, argv)	int     argc;	char   *argv[];{	int     len;	struct sockaddr_storage sa, sa2;	/* 	struct sockaddr_in sin;*/	struct sockaddr_in * sin;	struct sockaddr_in6 * sin6;	struct in_addr laddr, faddr;	struct in6_addr laddr6, faddr6;	struct passwd *pwd;	struct group *grp;	int     background_flag = 0;	int     timeout = 0;	char   *portno = "auth";	char   *bind_address = NULL;	int     set_uid = 0;	int     set_gid = 0;	extern char *optarg;	extern int optind;	int ch;	/*	 * Parse the command line arguments	 */	while ((ch = getopt(argc, argv, "hbwit:p:a:u:g:c:r:loenVvdmNU")) != -1) {		switch (ch) {		case 'h':			token_flag = 1;			break;		case 'b':	/* Start as standalone daemon */			background_flag = 1;			break;		case 'w':	/* Start from Inetd, wait mode */			background_flag = 2;			break;		case 'i':	/* Start from Inetd, nowait mode */			background_flag = 0;			break;		case 't':			timeout = atoi(optarg);			break;		case 'p':			portno = optarg;			break;		case 'a':			bind_address = optarg;			break;		case 'u':			if (isdigit(optarg[0])) {				set_uid = atoi(optarg);				break;			}			pwd = getpwnam(optarg);			if (!pwd)				ERROR1("no such user (%s) for -u option", optarg);			else {				set_uid = pwd->pw_uid;				if (setgid == 0)					set_gid = pwd->pw_gid;			}			break;		case 'g':			if (isdigit(optarg[0])) {				set_gid = atoi(optarg);				break;			}			grp = getgrnam(optarg);			if (!grp)				ERROR1("no such group (%s) for -g option", optarg);			else				set_gid = grp->gr_gid;			break;		case 'c':			charset_name = optarg;			charset_sep = " , ";			break;		case 'r':			indirect_host = optarg;			break;		case 'l':	/* Use the Syslog daemon for logging */			syslog_flag++;			break;		case 'o':			opsys_name = "OTHER";			break;		case 'e':			unknown_flag = 1;			break;		case 'n':			number_flag = 1;			break;		case 'V':	/* Give version of this daemon */			printf("[identd version %s]\r\n", version);			exit(0);			break;		case 'v':	/* Be verbose */			verbose_flag++;			break;		case 'd':	/* Enable debugging */			debug_flag++;			break;		case 'm':	/* Enable multiline queries */			multi_flag++;			break;		case 'N':	/* Enable users ".noident" files */			noident_flag++;			break;		case 'U':	/* Enable user ".ident" files */			userident_flag++;			break;		default:			usage();		}	}	/*	 * Do the special handling needed for the "-b" flag	 */	if (background_flag == 1) {		struct sockaddr_in addr;		struct servent *sp;		int     fd;		if (fork())			exit(0);		close(0);		close(1);		close(2);		if (fork())			exit(0);		fd = socket(AF_INET, SOCK_STREAM, 0);		if (fd == -1)			ERROR("main: socket");		if (fd != 0)			dup2(fd, 0);		memset(&addr, 0, sizeof(addr));		addr.sin_len = sizeof(struct sockaddr_in);		addr.sin_family = AF_INET;		if (bind_address == NULL)			addr.sin_addr.s_addr = htonl(INADDR_ANY);		else {			if (inet_aton(bind_address, &addr.sin_addr) == 0) {				struct hostent *hp;				hp = gethostbyname(bind_address);				if (!hp)					ERROR1("no such address (%s) for -a switch",					    bind_address);				memcpy(&addr.sin_addr, hp->h_addr,				    sizeof(addr.sin_addr));			}		}		if (isdigit(portno[0]))			addr.sin_port = htons(atoi(portno));		else {			sp = getservbyname(portno, "tcp");			if (sp == NULL)				ERROR1("main: getservbyname: %s", portno);			addr.sin_port = sp->s_port;		}		if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)			ERROR("main: bind");		if (listen(0, 3) < 0)			ERROR("main: listen");	}	if (set_gid) {		if (setegid(set_gid) == -1)			ERROR("main: setgid");		if (setgid(set_gid) == -1)			ERROR("main: setgid");	}	if (set_uid) {		if (seteuid(set_uid) == -1)			ERROR("main: setuid");		if (setuid(set_uid) == -1)			ERROR("main: setuid");	}	/*	 * Do some special handling if the "-b" or "-w" flags are used	 */	if (background_flag) {		int     nfds, fd;		struct	pollfd pfd[1];		/*		 * Loop and dispatch client handling processes		 */		do {			/*			 * Terminate if we've been idle for 'timeout' seconds			 */			if (background_flag == 2 && timeout) {				signal(SIGALRM, alarm_handler);				alarm(timeout);			}						/*			 * Wait for a connection request to occur.			 * Ignore EINTR (Interrupted System Call).			 */			do {				if (alarm_fired) {					if (syslog_flag)						syslog(LOG_DEBUG,						    "SIGALRM triggered, exiting");					exit(0);				}				pfd[0].fd = 0;				pfd[0].events = POLLIN;				if (timeout)					nfds = poll(pfd, 1, timeout * 1000);				else					nfds = poll(pfd, 1, INFTIM);			} while (nfds < 0 && errno == EINTR);			/*			 * An error occured in select? Just die			 */			if (nfds < 0)				ERROR("main: select");			/*			 * Timeout limit reached. Exit nicely			 */			if (nfds == 0)				exit(0);			/*			 * Disable the alarm timeout			 */			alarm(0);			/*			 * Accept the new client			 */			fd = accept(0, NULL, NULL);			if (fd == -1)				ERROR1("main: accept. errno = %d", errno);			/*			 * And fork, then close the fd if we are the parent.			 */			child_pid = fork();			while (waitpid(-1, NULL, WNOHANG) > 0)				;		} while (child_pid && (close(fd), 1));		/*		 * We are now in child, the parent has returned to "do" above.		 */		if (dup2(fd, 0) == -1)			ERROR("main: dup2: failed fd 0");		if (dup2(fd, 1) == -1)			ERROR("main: dup2: failed fd 1");		if (dup2(fd, 2) == -1)			ERROR("main: dup2: failed fd 2");	}	/*	 * Get foreign internet address	 */	len = sizeof(sa);	if (getpeername(0, (struct sockaddr *) &sa, &len) == -1) {		/*		 * A user has tried to start us from the command line or		 * the network link died, in which case this message won't		 * reach to other end anyway, so lets give the poor user some		 * errors.		 */		perror("in.identd: getpeername()");		exit(1);	}	if (sa.ss_family == AF_INET6) {		sin6 = (struct sockaddr_in6 *)&sa;		faddr6 = sin6->sin6_addr;	}	else {		sin = (struct sockaddr_in *)&sa;		faddr = sin->sin_addr;	}	/*	 * Open the connection to the Syslog daemon if requested	 */	if (syslog_flag) {#ifdef LOG_DAEMON		openlog("identd", LOG_PID, syslog_facility);#else		openlog("identd", LOG_PID);#endif		syslog(LOG_INFO, "Connection from %s", gethost(&sa));	}	/*	 * Get local internet address	 */	len = sizeof(sa2);	if (getsockname(0, (struct sockaddr *) &sa2, &len) == -1) {		/*		 * We can just die here, because if this fails then the		 * network has died and we haven't got anyone to return		 * errors to.		 */		exit(1);	}	/* are we V4 or V6? */	if (sa2.ss_family == AF_INET6) {		sin6 = (struct sockaddr_in6 *)&sa2;		laddr6 = sin6->sin6_addr;		/*		 * Get the local/foreign port pair from the luser		 */		parse6(STDIN_FILENO, (struct sockaddr_in6 *)&sa2,		    (struct sockaddr_in6 *)&sa);	}	else {		sin = (struct sockaddr_in *)&sa2;		laddr = sin->sin_addr;		/*		 * Get the local/foreign port pair from the luser		 */		parse(STDIN_FILENO, &laddr, &faddr);	}	exit(0);}