⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loop.c

📁 APUE(第二版)的随书源代码,与第一版的代码相比增加了一些章节的代码(详见第二版的说明)
💻 C
字号:
#include	"calld.h"#include	<sys/time.h>#include	<errno.h>static void	cli_done(int);static void child_done(int);static fd_set	allset;	/* one bit per client conn, plus one for listenfd */						/* modified by loop() and cli_done() */voidloop(void){	int		 i, n, maxfd, maxi, listenfd, nread;	char	 buf[MAXLINE];	Client	*cliptr;	uid_t	 uid;	fd_set	 rset;	if (signal_intr(SIGCHLD, sig_chld) == SIG_ERR)		log_sys("signal error");				/* obtain descriptor to listen for client requests on */	if ( (listenfd = serv_listen(CS_CALL)) < 0)		log_sys("serv_listen error");	FD_ZERO(&allset);	FD_SET(listenfd, &allset);	maxfd = listenfd;	maxi = -1;	for ( ; ; ) {		if (chld_flag)			child_done(maxi);		rset = allset;		/* rset gets modified each time around */		if ( (n = select(maxfd + 1, &rset, NULL, NULL, NULL)) < 0) {			if (errno == EINTR) {					/* caught SIGCHLD, find entry with childdone set */				child_done(maxi);				continue;		/* issue the select again */			} else				log_sys("select error");		}		if (FD_ISSET(listenfd, &rset)) {					/* accept new client request */			if ( (clifd = serv_accept(listenfd, &uid)) < 0)				log_sys("serv_accept error: %d", clifd);			i = client_add(clifd, uid);			FD_SET(clifd, &allset);			if (clifd > maxfd)				maxfd = clifd;	/* max fd for select() */			if (i > maxi)				maxi = i;		/* max index in client[] array */			log_msg("new connection: uid %d, fd %d", uid, clifd);			continue;		}			/* Go through client[] array.			   Read any client data that has arrived. */		for (cliptr = &client[0]; cliptr <= &client[maxi]; cliptr++) {			if ( (clifd = cliptr->fd) < 0)				continue;			if (FD_ISSET(clifd, &rset)) {						/* read argument buffer from client */				if ( (nread = read(clifd, buf, MAXLINE)) < 0)					log_sys("read error on fd %d", clifd);				else if (nread == 0) {					/* The client has terminated or closed the stream					   pipe.  Now we can release its device lock. */					log_msg("closed: uid %d, fd %d",										cliptr->uid, clifd);					lock_rel(cliptr->pid);					cli_done(clifd);					continue;				}				/* Data has arrived from the client.  Process the				   client's request. */				if (buf[nread-1] != 0) {					log_quit("request from uid %d not null terminated:"							 " %*.*s", uid, nread, nread, buf);					cli_done(clifd);					continue;				}				log_msg("starting: %s, from uid %d", buf, uid);						/* Parse the arguments, set options.  Since						   we may need to try calling again for this						   client, save options in client[] array. */				if (buf_args(buf, cli_args) < 0)					log_quit("command line error: %s", buf);				cliptr->Debug = Debug;				cliptr->parity = parity;				strcpy(cliptr->sysname, sysname);				strcpy(cliptr->speed, (speed == NULL) ? "" : speed);				cliptr->childdone = 0;				cliptr->sysftell = 0;				cliptr->foundone = 0;				if (request(cliptr) < 0) {						/* system not found, or unable to connect */					if (send_err(cliptr->fd, -1, errmsg) < 0)						log_sys("send_err error");					cli_done(clifd);					continue;				}				/* At this point request() has forked a child that is				   trying to dial the remote system.  We'll find				   out the child's status when it terminates. */			}		}	}}/* Go through the client[] array looking for clients whose dialing   children have terminated.  This function is called by loop() when   chld_flag (the flag set by the SIGCHLD handler) is nonzero. */static voidchild_done(int maxi){	Client	*cliptr;again:	chld_flag = 0;	/* to check when done with loop for more SIGCHLDs */	for (cliptr = &client[0]; cliptr <= &client[maxi]; cliptr++) {		if ( (clifd = cliptr->fd) < 0)			continue;		if (cliptr->childdone) {			log_msg("child done: pid %d, status %d",							cliptr->pid, cliptr->childdone-1);			/* If the child was successful (exit(0)), just clear			   the flag.  When the client terminates, we'll read			   the EOF on the stream pipe above and release			   the device lock. */			if (cliptr->childdone == 1) {	/* child did exit(0) */				cliptr->childdone = 0;				continue;			}			/* Unsuccessful: child did exit(1).  Release the device			   lock and try again from where we left off. */			cliptr->childdone = 0;			lock_rel(cliptr->pid);	/* unlock the device entry */			if (request(cliptr) < 0) {						/* still unable, time to give up */				if (send_err(cliptr->fd, -1, errmsg) < 0)					log_sys("send_err error");				cli_done(clifd);				continue;			}			/* request() has forked another child for this client */		}	}	if (chld_flag)	/* additional SIGCHLDs have been caught */		goto again;	/* need to check all childdone flags again */}/* Clean up when we're done with a client. */static voidcli_done(int clifd){	client_del(clifd);		/* delete entry in client[] array */	FD_CLR(clifd, &allset);	/* turn off bit in select() set */	close(clifd);			/* close our end of stream pipe */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -