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

📄 listen.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
				error(E_SYS_ERROR, EXIT | NO_MSG);			case POLLOUT:				logmessage("poll() returned POLLOUT");				error(E_SYS_ERROR, EXIT | NO_MSG);			default:				logmessage("poll() returned unrecognized event");				error(E_SYS_ERROR, EXIT | NO_MSG);			}		}	}}/* * doevent:	handle an asynchronous event */doevent(fhead, phead, fd)struct call_list *fhead;struct call_list *phead;int fd;{	register struct callsave *current;	register struct t_call *call;	char scratch[BUFSIZ];	DEBUG((9, "in doevent"));	switch (t_look(fd)) {	case 0:		sys_error(E_POLL, EXIT);		/* no return */	case T_LISTEN:		current = dequeue(fhead);		call = current->c_cp;		if (t_listen(fd, call) < 0) {			tli_error(E_T_LISTEN, CONTINUE);			return;		}		queue(phead, current);		sprintf(scratch, "Connect pending on fd %d, seq # %d", fd, call->sequence);		logmessage(scratch);		DEBUG((9, "incoming call seq # %d", call->sequence));		break;	case T_DISCONNECT:		if (t_rcvdis(fd, disc) < 0) {			tli_error(E_T_RCVDIS, EXIT);			/* no return */		}		sprintf(scratch, "Disconnect on fd %d, seq # %d", fd, disc->sequence);		logmessage(scratch);		DEBUG((9, "incoming disconnect seq # %d", disc->sequence));		pitchcall(fhead, phead, disc);		break;	default:		tli_error(E_T_LOOK, CONTINUE);		break;	}}/* * trycon:	try to accept a connection */trycon(fhead, phead, fd)struct call_list *fhead;struct call_list *phead;int fd;{	register struct callsave *current;	register struct t_call *call;	int pid;	char scratch[BUFSIZ];	DEBUG((9, "in trycon"));	while (!EMPTY(phead)) {		current = dequeue(phead);		call = current->c_cp;		DEBUG((9, "try to accept #%d", call->sequence));		close(0);		SPLhi();		if ((Nfd3 = open_bind(NULL, 0, 0, (unsigned int *) 0)) != 0) {			error(E_OPENBIND, CONTINUE);			clr_call(call);			queue(fhead, current);			continue;	/* let transport provider generate disconnect */		}		SPLlo();		if (t_accept(fd, Nfd3, call) < 0) {			if (t_errno == TLOOK) {				t_close(Nfd3);				SPLhi();				if (dup(1) != 0)					logmessage("Trouble duping fd 0");				SPLlo();				logmessage("t_accept collision");				DEBUG((9, "save call #%d", call->sequence));				pqueue(phead, current);				return;			}			else {				t_close(Nfd3);				SPLhi();				if (dup(1) != 0)					logmessage("Trouble duping fd 0");				SPLlo();				tli_error(E_T_ACCEPT, CONTINUE);				clr_call(call);				queue(fhead, current);				return;			}		}		sprintf(scratch, "Accepted request on fd %d, seq # %d", Nfd3, call->sequence);		logmessage(scratch);		DEBUG((9, "Accepted call %d", call->sequence));		check_dbf();		if ((pid = fork()) < 0)			log(E_FORK_SERVICE);		else if (!pid) {			startit(Nfd3, call, (fd == Nfd1 ? LOGIN : GEN));			/* no return */		}		clr_call(call);		t_close(Nfd3);		queue(fhead, current);		SPLhi();		if (dup(1) != 0)			logmessage("Trouble duping fd 0");		SPLlo();	}}/* * startit:	start up a server */startit(fd, call, servtype)int fd;struct t_call *call;int servtype;{	DEBUG((9, "in startit"));	setpgrp();	Child = 1;	if (servtype == LOGIN)		login(fd, call);	else		process(fd, call);/* * if login() or process() returns, an error * was encountered.  Errors should be logged * by the subroutines -- exit done here. * (Subroutines shouldn't care if they are * a parent/child/whatever.) * * NOTE: timeout() is an exception;  * it does an exit. * There can be no TLI calls after this point. * (non-tli modules may have been pushed) * */	DEBUG((9, "return in startit"));#ifdef	COREDUMP	abort();#endif	exit(1); /* server failed, don't log */}/* * process:	process an accepted connection request *		for ms-net or NLP service. */process(fd, call)register fd;struct t_call *call;{	register size;	char buf[RCVBUFSZ];	char **argv;	register char *bp = buf;	register dbf_t *dbp;	extern dbf_t *getdbfentry();	extern char **mkdbfargv();	DEBUG((9,"in process (NLPS/SMB message)"));	if ((size = getrequest(fd, bp)) <= 0)  {		logmessage("process(): No/bad service request received");		return(-1);	}	if (size < MINMSGSZ)  {		DEBUG((7,"process(): msg size (%d) too small",size));		logmessage("process(): Message size too small");		return(-1);	}	/*	 * if message is NLPS protocol...	 */	if ((!strncmp(bp,NLPSIDSTR,NLPSIDSZ))  && 	/* NLPS request	*/	    (*(bp + NLPSIDSZ) == NLPSSEPCHAR)) {		nls_service(fd, bp, size, call);		(void)sleep(10);	/* if returned to here, then 				 * must sleep for a short period of time to				 * insure that the client received any possible				 * exit response message from the listener.					 */	/*	 * else if message is for the MS-NET file server...	 */	} else if ( (*bp == (char)0xff) && (!strncmp(bp+1,SMBIDSTR,SMBIDSZ)) )  {		if (dbp = getdbfentry(DBF_SMB_CODE))		    if (dbp->dbf_flags & DBF_OFF)			logmessage("SMB message, server disabled in data base");		    else    {			argv = mkdbfargv(dbp);			smbservice(fd, bp, size, call, argv);		    }		else			logmessage("SMB message, no data base entry");	/*	 * else, message type is unknown...	 */	} else  {		logmessage("Process(): Unknown service request (ignored)");		DEBUG((7,"msg size: %d; 1st four chars (hex) %x %x %x %x",			*bp, *(bp+1), *(bp+2), *(bp+3)));	}	/*	 * the routines that start servers return only if there was an error	 * and will have logged their own errors.	 */	return(-1);}/* * getrequest:	read in a full message.  Timeout, in case the client died. *		returns: -1 = timeout or other error. *			 positive number = message size. */intgetrequest(fd, bp)register fd;register char *bp;{	register size;	register char *tmp = bp;	int flags;	extern void timeout();	extern unsigned alarm();	unsigned short cnt;	DEBUG((9,"in getrequest"));	signal(SIGALRM, timeout);	(void)alarm(ALARMTIME);	/* read in MINMSGSZ to determine type of msg */	if ((size = l_rcv(fd, bp, MINMSGSZ, &flags)) != MINMSGSZ) {		DEBUG((9, "getrequest: l_rcv returned %d", size));		tli_error(E_RCV_MSG, CONTINUE);		return(-1);	}	tmp += size;	/*	 * if message is NLPS protocol...	 */	if ((!strncmp(bp,NLPSIDSTR,NLPSIDSZ))  && 	/* NLPS request	*/	    (*(bp + NLPSIDSZ) == NLPSSEPCHAR)) {		do {			if (++size > RCVBUFSZ) {				logmessage("Getrequest(): recieve buffer not large enough");				return(-1);			}			if (t_rcv(fd, tmp, sizeof(char), &flags) != sizeof(char)) {				tli_error(E_RCV_MSG, CONTINUE);				return(-1);			}		} while (*tmp++ != '\0');	/*	 * else if message is for the MS-NET file server...	 */	} else if ( (*bp == (char)0xff) && (!strncmp(bp+1,SMBIDSTR,SMBIDSZ)) )  {		/* read in 28 more bytes to get count of paramter words */		if (l_rcv(fd, tmp, 28, &flags) != 28) {			tli_error(E_RCV_MSG, CONTINUE);			return(-1);		}		tmp += 28;		size += 28;		/*		 * read amount of paramater words plus word for                 * the number of data bytes to follow (2 bytes/word)                 */		cnt = (int)*(tmp - 1) * 2 + 2;		if ((size += cnt) > RCVBUFSZ) {			logmessage("Getrequest(): recieve buffer not large enough");			return(-1);		}		if (l_rcv(fd, tmp, cnt, &flags) != cnt) {			tli_error(E_RCV_MSG, CONTINUE);			return(-1);		}		tmp += cnt;		getword(tmp - 2, &cnt);		if ((size += cnt) > RCVBUFSZ) {			logmessage("Getrequest(): recieve buffer not large enough");			return(-1);		}		if (l_rcv(fd, tmp, cnt, &flags) != cnt) {			tli_error(E_RCV_MSG, CONTINUE);			return(-1);		}		nullfix(fd);	/*	 * else, message type is unknown...	 */	} else  {		logmessage("Getrequest(): Unknown service request (ignored)");		DEBUG((7,"msg size: %d; 1st four chars (hex) %x %x %x %x",			*bp, *(bp+1), *(bp+2), *(bp+3)));		return(-1);	}	(void)alarm(0);	signal(SIGALRM, SIG_IGN);	DEBUG((7,"t_rcv returned %d, flags: %x",size,flags));	return(size);}/* * The following code is for patching a 6300 side bug.  The original * message that comes over may contain 2 null bytes which aren't * part of the message, and if left on the stream, will poison the * server.  Peek into the stream and snarf up those bytes if they * are there.  If anything goes wrong with the I_PEEK, just continue, * if the nulls weren't there, it'll work, and if they were, all that * will happen is that the server will fail.  Just note what happened * in the log file. */nullfix(fd)int fd;{	struct strpeek peek;	register struct strpeek *peekp;	char scratch[BUFSIZ];	char junk[2];	int flags;	int ret;	peekp = &peek;	peekp->flags = 0;	/* need to ask for ctl info to avoid bug in I_PEEK code */	peekp->ctlbuf.maxlen = 1;	peekp->ctlbuf.buf = junk;	peekp->databuf.maxlen = 2;	peekp->databuf.buf = junk;	ret = ioctl(fd, I_PEEK, &peek);	if (ret == -1) {		sprintf(scratch, "nullfix(): unable to PEEK, errno is %d", errno);		DEBUG((9, "nullfix(): I_PEEK failed, errno is %d", errno));		logmessage(scratch);	}	else if (ret == 0) {		DEBUG((9, "nullfix(): no messages on stream to PEEK"));	}	else {		if (peekp->databuf.len == 2) {			/* Note: junk contains "peeked" data */			DEBUG((9, "peeked <%x> <%x>", junk[0], junk[1]));			if ((junk[0] == 0) && (junk[1] == 0)) {				/* pitch the nulls */				DEBUG((9, "pitching 2 nulls from first peek"));				l_rcv(fd, junk, 2, &flags);			}		}		/*		 * this represents a somewhat pathological case where		 * the "2 nulls" are broken across message boundaries.		 * Pitch the first and hope the next one is there		 */		else if (peekp->databuf.len == 1) {			DEBUG((9, "peeked <%x>", junk[0]));			if (junk[0] == 0) {				/* pitch the first */				DEBUG((9, "split nulls, pitching first"));				l_rcv(fd, junk, 1, &flags);				peekp->databuf.maxlen = 1;				ret = ioctl(fd, I_PEEK, &peek);				if (ret == -1) {					sprintf(scratch, "nullfix(): unable to PEEK second time, errno is %d", errno);					DEBUG((9, "second peek failed, errno %d", errno));					logmessage(scratch);				}				else if (ret == 0) {					DEBUG((9, "no messages for 2nd peek"));				}				else {					if (peekp->databuf.len == 1) {						DEBUG((9, "2nd peek <%x>", junk[0]));						if (junk[0] == 0) {							/* pitch the second */							DEBUG((9, "pitching 2nd single null"));							l_rcv(fd, junk, 1, &flags);						}						else {							/* uh oh, server will most likely fail */							DEBUG((9, "2nd null not found"));							logmessage("nullfix(): threw away a valid null byte");						}					}				}			}		}	}}/* * timeout:	SIGALRM signal handler.  Invoked if t_rcv timed out. *		See comments about 'exit' in process(). */voidtimeout(){	DEBUG((9, "TIMEOUT"));	error(E_RCV_TMO, EXIT | NOCORE);}/* * nls_service:	Validate and start a server requested via the NLPS protocol * *		version 0:1 -- expect "NLPS:000:001:service_code". * *	returns only if there was an error (either msg format, or couldn't exec) */static char *badversion =	"Unknown version of an NLPS service request: %d:%d";static char *disabledmsg =	"Request for service code <%s> denied, service is disabled";static char *nlsunknown =	"Request for service code <%s> denied, unknown service code";/* * Nlsversion can be used as a NLPS flag (< 0 == not nls service) * and when >= 0, indicates the version of the NLPS protocol used */static int Nlsversion = -1;	/* protocol version	*/intnls_service(fd, bp, size, call)int fd, size;char *bp;struct t_call *call;{	int low, high;	char svc_buf[64];	register char *svc_code_p = svc_buf;	char scratch[256];	register dbf_t *dbp;	extern dbf_t *getdbfentry();	extern char **mkdbfargv();	if (nls_chkmsg(bp, size, &low, &high, svc_code_p))  {		if ((low == 0) || (low == 2))			Nlsversion = low;		else  {			sprintf(scratch, badversion, low, high);			logmessage(scratch);			error(E_BAD_VERSION, CONTINUE);			return(-1);		}		DEBUG((9,"nls_service: protocol version %d", Nlsversion));		/*		 * common code for protocol version 0 or 2		 * version 0 allows no answerback message		 * version 2 allows exactly 1 answerback message		 */		if (dbp = getdbfentry(svc_code_p))		    if (dbp->dbf_flags & DBF_OFF)  {			sprintf(scratch, disabledmsg, svc_code_p);			logmessage(scratch);			nls_reply(NLSDISABLED, scratch);		    }  else			start_server(fd, dbp, (char **)0, call);			/* return is an error	*/		else  {

⌨️ 快捷键说明

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