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

📄 chan.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  $Revision: 1.30 $****  I/O channel (and buffer) processing.*/#include "innd.h"STATIC FDSET	RCHANmask;STATIC FDSET	SCHANmask;STATIC FDSET	WCHANmask;STATIC int	SCHANcount;STATIC int	CHANlastfd;STATIC int	CHANlastsleepfd;STATIC int	CHANccfd;STATIC int	CHANtablesize;STATIC CHANNEL	*CHANtable;STATIC CHANNEL	*CHANcc;STATIC CHANNEL	CHANnull = { CTfree, CSerror, -1 };/***  Set a buffer's contents, ignoring anything that might have**  been there.*/voidBUFFset(bp, p, length)    register BUFFER	*bp;    register char	*p;    register int	length;{    register char	*dest;    if ((bp->Left = length) != 0) {	/* Need more space? */	if (bp->Size < length) {	    bp->Size = GROW_AMOUNT(length);	    RENEW(bp->Data, char, bp->Size);	}	if (length > MEMCPY_THRESHOLD)	    (void)memcpy((POINTER)bp->Data, (POINTER)p, (SIZE_T)length);	else {	    for (dest = bp->Data, length++; --length > 0; )		*dest++ = *p++;	}    }    bp->Used = 0;}/***  Initialize all the I/O channels.*/voidCHANsetup(i)    register int	i;{    register CHANNEL	*cp;    FD_ZERO(&RCHANmask);    FD_ZERO(&SCHANmask);    FD_ZERO(&WCHANmask);    if (CHANtable)	DISPOSE(CHANtable);    CHANtablesize = i;    CHANtable = NEW(CHANNEL, CHANtablesize);    (void)memset((POINTER)CHANtable, 0,	    (SIZE_T)(CHANtablesize * sizeof *CHANtable));    CHANnull.NextLog = CHANNEL_INACTIVE_TIME;    CHANnull.Address.s_addr = MyAddress.s_addr;    for (cp = CHANtable; --i >= 0; cp++)	*cp = CHANnull;}/***  Create a channel from a descriptor.*/CHANNEL *CHANcreate(fd, Type, State, Reader, WriteDone)    int			fd;    CHANNELTYPE		Type;    CHANNELSTATE	State;    FUNCPTR		Reader;    FUNCPTR		WriteDone;{    register CHANNEL	*cp;    BUFFER		in;    BUFFER		out;    cp = &CHANtable[fd];    /* Don't overwrite the buffers with CHANnull. */    in = cp->In;    if (in.Size == 0) {	in.Size = START_BUFF_SIZE;	in.Data = NEW(char, in.Size);    }    in.Used = 0;    in.Left = in.Size;    out = cp->Out;    if (out.Size == 0) {	out.Size = SMBUF;	out.Data = NEW(char, out.Size);    }    out.Used = 0;    out.Left = 0;    /* Set up the channel's info. */    *cp = CHANnull;    cp->fd = fd;    cp->Type = Type;    cp->State = State;    cp->Reader = Reader;    cp->WriteDone = WriteDone;    cp->Started = cp->LastActive = Now.time;    cp->In = in;    cp->Out = out;    cp->Tracing = Tracing;    /* Make the descriptor close-on-exec and non-blocking. */    CloseOnExec(fd, TRUE);#if	defined(ENOTSOCK)    if (SetNonBlocking(fd, TRUE) < 0 && errno != ENOTSOCK)	syslog(L_ERROR, "%s cant nonblock %d %m", LogName, fd);#else    if (SetNonBlocking(fd, TRUE) < 0)	syslog(L_ERROR, "%s cant nonblock %d %m", LogName, fd);#endif	/* defined(ENOTSOCK) */    /* Note control channel, for efficiency. */    if (Type == CTcontrol) {	CHANcc = cp;	CHANccfd = fd;    }    return cp;}/***  Start tracing a channel.*/voidCHANtracing(cp, Flag)    register CHANNEL	*cp;    BOOL		Flag;{    char		*p;    p = CHANname(cp);    syslog(L_NOTICE, "%s trace %s", p, Flag ? "on" : "off");    cp->Tracing = Flag;    if (Flag) {	syslog(L_NOTICE, "%s trace badwrites %d blockwrites %d badreads %d",	    p, cp->BadWrites, cp->BadReads, cp->BlockedWrites);	syslog(L_NOTICE, "%s trace address %s lastactive %ld nextlod %ld",	    p, inet_ntoa(cp->Address), cp->LastActive, cp->NextLog);	if (FD_ISSET(cp->fd, &SCHANmask))	    syslog(L_NOTICE, "%s trace sleeping %ld 0x%x",		p, (long)cp->Waketime, cp->Waker);	if (FD_ISSET(cp->fd, &RCHANmask))	    syslog(L_NOTICE, "%s trace reading %d %s",		p, cp->In.Used, MaxLength(cp->In.Data, cp->In.Data));	if (FD_ISSET(cp->fd, &WCHANmask))	    syslog(L_NOTICE, "%s trace writing %d %s",		p, cp->Out.Left, MaxLength(cp->Out.Data, cp->Out.Data));    }}/***  Close a channel.*/voidCHANclose(cp, name)    register CHANNEL	*cp;    char		*name;{    if (cp->Type == CTfree)	syslog(L_ERROR, "%s internal closing free channel", name);    else {	if (cp->Type == CTnntp)	    syslog(L_NOTICE,		"%s closed seconds %ld accepted %ld refused %ld rejected %ld",		name, (long)(Now.time - cp->Started),		cp->Received, cp->Refused, cp->Rejected);	else	    syslog(L_NOTICE, "%s closed", name);	WCHANremove(cp);	RCHANremove(cp);	SCHANremove(cp);	if (cp->Argument != NULL)	    /* Set to NULL below. */	    DISPOSE(cp->Argument);	if (cp->fd >= 0 && close(cp->fd) < 0)	    syslog(L_ERROR, "%s cant close %s %m", LogName, name);    }    /* Mark it unused. */    cp->Type = CTfree;    cp->State = CSerror;    cp->fd = -1;    cp->Argument = NULL;    /* Free the buffers if they got big. */    if (cp->In.Size > BIG_BUFFER) {	cp->In.Size = 0;	DISPOSE(cp->In.Data);    }    if (cp->Out.Size > BIG_BUFFER) {	cp->Out.Size = 0;	DISPOSE(cp->Out.Data);    }}/***  Return a printable name for the channel.*/char *CHANname(cp)    register CHANNEL	*cp;{    static char		buff[SMBUF];    register int	i;    register SITE	*sp;    STRING		p;    PID_T		pid;    switch (cp->Type) {    default:	(void)sprintf(buff, "?%d(#%d@%d)?", cp->Type, cp->fd, cp - CHANtable);	break;    case CTany:	(void)sprintf(buff, "any:%d", cp->fd);	break;    case CTfree:	(void)sprintf(buff, "free:%d", cp->fd);	break;    case CTremconn:	(void)sprintf(buff, "remconn:%d", cp->fd);	break;    case CTnntp:	(void)sprintf(buff, "%s:%d",		cp->Address.s_addr == 0 ? "localhost" : RChostname(cp),		cp->fd);	break;    case CTlocalconn:	(void)sprintf(buff, "localconn:%d", cp->fd);	break;    case CTcontrol:	(void)sprintf(buff, "control:%d", cp->fd);	break;    case CTexploder:    case CTfile:    case CTprocess:	/* Find the site that has this channel. */	for (p = "?", i = nSites, sp = Sites, pid = 0; --i >= 0; sp++)	    if (sp->Channel == cp) {		p = sp->Name;		if (cp->Type != CTfile)		    pid = sp->pid;		break;	    }	if (pid == 0)	    (void)sprintf(buff, "%s:%d:%s",		    MaxLength(p, p), cp->fd,		    cp->Type == CTfile ? "file" : "proc");	else	    (void)sprintf(buff, "%s:%d:%s:%ld",		    MaxLength(p, p), cp->fd,		    cp->Type == CTfile ? "file" : "proc", (long)pid);	break;    }    return buff;}/***  Return the channel for a specified descriptor.*/CHANNEL *CHANfromdescriptor(fd)    int		fd;{    if (fd <0 || fd > CHANtablesize)	return NULL;    return &CHANtable[fd];}/***  Iterate over all channels of a specified type.*/CHANNEL *CHANiter(ip, Type)    int			*ip;    CHANNELTYPE		Type;{    register CHANNEL	*cp;    register int	i;    if ((i = *ip) >= 0 && i < CHANtablesize) {	do {	    cp = &CHANtable[i];	    if (Type == CTany || cp->Type == Type) {		*ip = ++i;		return cp;	    }	} while (++i < CHANtablesize);    }    return NULL;}/***  Mark a channel as an active reader.*/voidRCHANadd(cp)    register CHANNEL	*cp;{    FD_SET(cp->fd, &RCHANmask);    if (cp->fd > CHANlastfd)	CHANlastfd = cp->fd;    /* Start reading at the beginning of the buffer. */    cp->In.Used = 0;}/***  Remove a channel from the set of readers.*/voidRCHANremove(cp)    register CHANNEL	*cp;{    if (FD_ISSET(cp->fd, &RCHANmask)) {	FD_CLR(cp->fd, &RCHANmask);	if (cp->fd == CHANlastfd) {	    /* This was the highest descriptor, get a new highest. */	    while (!FD_ISSET(CHANlastfd, &RCHANmask)	      && !FD_ISSET(CHANlastfd, &WCHANmask)	      && CHANlastfd > 1)		CHANlastfd--;	}    }}/***  Put a channel to sleep, call a function when it wakes.**  Note that the Argument must be NULL or allocated memory!*/voidSCHANadd(cp, Waketime, Event, Waker, Argument)    register CHANNEL	*cp;    time_t		Waketime;    POINTER		Event;    FUNCPTR		Waker;    POINTER		Argument;{    if (!FD_ISSET(cp->fd, &SCHANmask)) {	SCHANcount++;	FD_SET(cp->fd, &SCHANmask);    }    if (cp->fd > CHANlastsleepfd)	CHANlastsleepfd = cp->fd;    cp->Waketime = Waketime;    cp->Waker = Waker;    if (cp->Argument != Argument) {	DISPOSE(cp->Argument);	cp->Argument = Argument;    }    cp->Event = Event;}/***  Take a channel off the sleep list.*/voidSCHANremove(cp)    register CHANNEL	*cp;{    if (FD_ISSET(cp->fd, &SCHANmask)) {	FD_CLR(cp->fd, &SCHANmask);	SCHANcount--;	cp->Waketime = 0;	if (cp->fd == CHANlastsleepfd) {	    /* This was the highest descriptor, get a new highest. */	    while (!FD_ISSET(CHANlastsleepfd, &WCHANmask)	      && CHANlastsleepfd > 1)		CHANlastsleepfd--;	}    }}/***  Is a channel on the sleep list?*/BOOLCHANsleeping(cp)    CHANNEL	*cp;{    return FD_ISSET(cp->fd, &SCHANmask);}/***  Wake up channels waiting for a specific event.*/voidSCHANwakeup(Event)    register POINTER	Event;{    register CHANNEL	*cp;    register int	i;    for (cp = CHANtable, i = CHANtablesize; --i >= 0; cp++)	if (cp->Type != CTfree && cp->Event == Event && CHANsleeping(cp))	    cp->Waketime = 0;}/*

⌨️ 快捷键说明

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