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

📄 nim.c

📁 早期freebsd实现
💻 C
字号:
/* * Network Interface Machine Server * * Frank Pronk * Copyright (c) 1984 */#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <signal.h>#include <errno.h>#include <setjmp.h>#include <sgtty.h>#include <pwd.h>#include "../h/x29.h"#include "buf.h"#include "nim.h"extern	char chartab[128];jmp_buf	JmpBuf;			/* non-local goto buffer for interval timer */short	PtyFd = -1, NetFd = -1;short	LogFd = -1;char	*LogDev;short	TimerOn;		/* interval timer armed */char	Banner[] = "NIM daemon\r";extern	int errno;char	*TraceFile;		/* trace file name */char	*PtyName;struct	bufhd ptyoqueue, netoqueue;struct	buf *packet;char	user_name[50];struct	netinfo NetInfo = { CCITT1980, NX29_1980_PARMS, 128 };struct	PtyPacket {	char	p_type;	char	p_data[1];	/* usually more than one byte */};char	*x25err();main(argc, argv)register char **argv;{	register int s;	register char *p;	int on = 1, uid;	struct passwd *pw;#ifdef waterloo	/*	 * If this host doesn't support X.25, give up.	 */	s = socket(AF_CCITT, SOCK_STREAM, 0);	if (s < 0 && errno == EPROTONOSUPPORT) {		fprint(2, "nimd: X.25 is not supported on this machine\n");		exit(1);	}	close(s);#endif	for (argv++; argc > 1; argc--, argv++)		if (**argv == '-')			for (p = *argv+1; *p; p++)			switch (*p) {			case 'c':				if (argc > 1) {					argc--; argv++;					if (strcmp (*argv, "1978") == 0) {						NetInfo.n_nparms = NX29_1978_PARMS;						break;					} else if (strcmp (*argv, "1980") == 0) {						NetInfo.n_nparms = NX29_1980_PARMS;						break;					}				}				fatal ("1978 or 1980 expected after -c");				break;			case 't':				if (argc > 1) {					argc--; argv++;					TraceFile = *argv;				} else					fatal ("trace file name expected");				break;			default:				fatal("usage: nimd [-c ccitt-date] [-h size] [-n size] [-t trace_file] pty_name");			}		else			PtyName = *argv;	if (PtyName == 0)		fatal ("No pseudo-tty specified");	if (fork())		exit(0);	for (s = 0; s < 10; s++)		(void) close(s);	(void) open("/", 0);	(void) dup2(0, 1);	(void) dup2(0, 2);	{ int tt = open("/dev/tty", 2);	  if (tt > 0) {		ioctl(tt, TIOCNOTTY, (char *)0);		close(tt);	  }	}	OpenLog ();	packet = getbuf (MAXPSIZ);	ResetBufs ();	signal (SIGPIPE, SIG_IGN);	for (;;) {		int bits;		if ((PtyFd = open (PtyName, 2)) < 0)			fatal (x25err(PtyName));		ioctl (PtyFd, FIONBIO, (char *)&on);		ioctl (PtyFd, TIOCPKT, (char *)&on);		ioctl (PtyFd, TIOCREMOTE, (char *)&on);		bits = (1 << PtyFd);		select (16, (int *)0, &bits, (int *)0, (struct timeval *)0);		sleep (1);	/* wait for pty to settle down */#ifdef TIOCGSUID		/*		 * Get the slave's uid.		 */		uid = -1;		if (ioctl(PtyFd, TIOCGSUID, &uid) < 0) {			perror("nimd: ioctl TIOCGSUID");			close(PtyFd);			continue;		}		if (uid < 0 || (pw = getpwuid(uid)) == 0) {			message("nimd: uid %d: Who are you?\n", uid);			close(PtyFd);			continue;		}		strcpy(user_name, pw->pw_name);		/*		 * Set effective uid to the slave		 * so he/she will be charged for X.25 usage.		 */		setreuid(0, pw->pw_uid);#endif		nim ();		sleep (1);	/* wait for slave to disconnect */		setreuid(0, 0);		CloseLog(); OpenLog();	/* allow log rollover */	}	/*NOTREACHED*/}fatal (msg)char *msg;{	OpenLog ();	log ("%s", msg);	print ("nimd: %s\n", msg);	exit (1);}/*VARARGS*/message(fmt, a1, a2, a3, a4, a5)char *fmt;{	char buf[128];	sprint (buf, fmt, a1, a2, a3, a4, a5);	ToPty (buf, strlen (buf), FROMNIM);}error(){	register char *errp;	errp = x25err ((char *)0);	log (errp);	message ("nimd: %s\r", errp);}/* * Main loop.  Select from pty and network, and * hand data to nim receiver. */nim(){	register int len;	char buf[MAXPSIZ];	int on = 1, ibits, obits, first = 1;	InitProfile (DEFAULT_PROFILE);	message (Banner);	State = ST_COMMAND;	OpenLog ();	if (user_name[0])		log("slave connect: %s", user_name);	else		log ("slave connect");	for (;;) {		(void) setjmp (JmpBuf);		if (first) {			obits = (1 << PtyFd);			ibits = 0;			first = 0;			goto do_io;		}		ibits = obits = 0;		/*		 * Never look for input if there's still		 * stuff in the corresponding output buffer		 */		if (PtyFd >= 0)			if (!QEMPTY(&ptyoqueue))				obits |= (1 << PtyFd);			else				if (NetFd >= 0 && State == ST_DATA)					ibits |= (1 << NetFd);		if (!QEMPTY(&netoqueue) && NetFd >= 0) {			if (!OutputBlocked)				obits |= (1 << NetFd);		} else			if (PtyFd >= 0)				ibits |= (1 << PtyFd);		if (ibits == 0 && obits == 0)	/* nothing to do; go home */			break;		if (State & ST_COMMAND) {			struct timeval TimeOut;			TimeOut.tv_sec = 60;			TimeOut.tv_usec = 0;			if (select (16, &ibits, &obits, (int *)0, &TimeOut) <= 0) {				log ("slave inactivity timeout");				break;			}		} else {			if (TimerOn)				sigsetmask (0);			(void) select (16, &ibits, &obits, (int *)0, (struct timeval *)0);			if (TimerOn)				sigsetmask (1 << (SIGALRM -1 ));		}	do_io:		/*		 * Something to read from the network...		 */		if (ibits & (1 << NetFd))			if ((len = ReadAndTrace(NetFd, buf, MAXPSIZ, "net rx")) == 0) {				if (errno != EWOULDBLOCK)					NetworkError ();			} else				FromNet (buf, len);		/*		 * Something to read from the pty...		 */		if (ibits & (1 << PtyFd))			if ((len = ReadAndTrace (PtyFd, buf, NetInfo.n_psize+1, "pty rx")) == 0) {				if (errno != EWOULDBLOCK) {					close (PtyFd);					PtyFd = -1;				}			} else				FromPty ((struct PtyPacket *)buf, len);		if (obits & (1<<NetFd)) {			if (FlushQueue (NetFd, &netoqueue, "net tx") < 0 && 				errno != EWOULDBLOCK)				NetworkError ();		}		if (obits & (1 << PtyFd))			if (FlushQueue (PtyFd, &ptyoqueue, "pty tx") < 0 &&				errno != EWOULDBLOCK) {				close (PtyFd);				PtyFd = -1;			}	}	cleanup ();}ReadAndTrace (fd, buf, len, who)char *buf, *who;{	register int bytes;	bytes = read (fd, buf, len);	if (bytes <= 0)		return (0);	NimTrace (who, buf, bytes);	return (bytes);}NetworkError (){	error ();	State = ST_COMMAND;	close (NetFd);	NetFd = -1;	message (Banner);}cleanup (){	log ("slave disconnect");	close (NetFd);	close (PtyFd);	NetFd = PtyFd = -1;	if (TimerOn)		ClearTimer ();	ResetBufs ();}ResetBufs (){	InitQueue (&ptyoqueue);	InitQueue (&netoqueue);	RESET (packet);}ToPty (str, len, from)register char *str;{	register char *end = str + len, c, c1;	register struct buf *bp = 0;	register int lfcode;	while (str < end) {		c = *str++;		c1 = c & 0177;		if (CurrentX29Parms[X29_AUX_DEV_CONTROL_CODE]) {			if (c1 == 023) {				OutputBlocked++;				continue;			}			if (c1 == 021) {				OutputBlocked = 0;				continue;			}		}		if (ptyoqueue.b_count > 256)			continue;		if (bp == 0)			bp = getbuf (MAXPSIZ);		PUTCHAR (c, bp);		if (SIZE (bp) >= MAXPSIZ-1) {			enqueue (bp, &ptyoqueue);			bp = 0;		}		if (c1 != '\r' || (lfcode = CurrentX29Parms[X29_LF_AFTER_CR]) <= 0)			continue;		if ((lfcode & 01) && from == FROMNET ||		    (lfcode & 04) && from == FROMPTY ||		     from == FROMNIM)			PUTCHAR ('\n', bp);	}	if (bp)		enqueue (bp, &ptyoqueue);}FromPty(pp, len)register struct PtyPacket *pp;{	register int echo;	register struct buf *tp = packet;	register char *cp, c;	char c1;	if (pp->p_type != TIOCPKT_DATA) {	/* fetch control byte */		PtyControl (pp);		return;	}	if (State & ST_UGLY_50_BAUD_BREAK_IN_PROGRESS)		return;	cp = pp->p_data;	echo = CurrentX29Parms[X29_ECHO_CODE] > 0 && ptyoqueue.b_count < 256;	while (cp < ((char *)pp)+len) {		c = (c1 = *cp++) & 0177;		if (State & ST_ESCSEEN && C_TYPE(c) != C_ESCAPE)			EnterCommandState ();		switch (C_TYPE(c)) {		case C_ERASE:			if (!ISEMPTY(tp)) {				tp->b_top--;				if (echo)					if (c == '\b')						ToPty ("\b \b", 3, FROMPTY);					else						ToPty (&c1, 1, FROMPTY);			}			continue;		case C_KILL:			RESET (tp);			if (echo)				ToPty ("*poof*\r", 7, FROMPTY);			continue;		case C_DISPLAY:			ToPty (tp->b_bot, SIZE (tp), FROMPTY);			continue;		case C_ESCAPE:			if ((State & (ST_COMMAND|ST_ESCSEEN)) == 0) {				State |= ST_ESCSEEN;				continue;			}			State &= ~ST_ESCSEEN;			/* fall through */		default:			if (State & ST_COMMAND) {				if (c == '\r') {					if (echo)						ToPty (&c1, 1, FROMPTY);					PUTCHAR ('\0', tp);					FlushQueue (PtyFd, &ptyoqueue, "pty tx");					NimCommand (tp->b_bot);					RESET(tp);					continue;				}				if (SIZE (tp) < MAXPSIZ-1) {					PUTCHAR (c, tp);					if (echo)						ToPty (&c1, 1, FROMPTY);				} else/*					ToPty ("\007", 1, FROMPTY)*/;			} else {				PUTCHAR (c1, tp);				if (echo)					ToPty (&c1, 1, FROMPTY);				if (ISFORWARD(c) || SIZE (tp) >= NetInfo.n_psize) {					ForwardPacket ();					continue;				}			}		}	}	if (!ISEMPTY (tp) && (State & ST_COMMAND) == 0)		SetTimer ();}PtyControl(pp)register struct PtyPacket *pp;{#ifdef notdef	if ((pp->p_type & (TIOCPKT_FLUSHWRITE|TIOCPKT_FLUSHREAD)) ==	   (TIOCPKT_FLUSHWRITE|TIOCPKT_FLUSHREAD)) {	/* break indication from pty */		if (State & ST_COMMAND)			RESET (packet);		else			Break (CurrentX29Parms[X29_BREAK_PROCEDURE_CODE]);		return;	   }#endif#ifdef TIOCPKT_IOCTL	if (pp->p_type & TIOCPKT_IOCTL) {	/* some kind of set tty done by slave */		static short UnixToX29Speed[] = {			0, 10, 5, 0, 1, 6, 8, 2, 4, 3,	/* B0 thru B1200 */			12, 13, 14, 15, 16		/* B2400 thru EXTB */		};		struct sgttyb sg;		ioctl(PtyFd, TIOCGETP, (char *)&sg);		if (sg.sg_ospeed == B50) {			State |= ST_UGLY_50_BAUD_BREAK_IN_PROGRESS;			return;		}		CurrentX29Parms[X29_TRANSMISSION_SPEED_CODE]			= UnixToX29Speed[sg.sg_ospeed];		if (State & ST_UGLY_50_BAUD_BREAK_IN_PROGRESS && sg.sg_ospeed != B50) {			State &= ~ST_UGLY_50_BAUD_BREAK_IN_PROGRESS;			if (State & ST_COMMAND)				RESET (packet);			else				Break (CurrentX29Parms[X29_BREAK_PROCEDURE_CODE]);		}	}#endif}EnterCommandState (){	State &= ~ST_ESCSEEN;	State |= ST_COMMAND | ST_ESCCOMM;	ForwardPacket ();}ExitDataState (cause)char *cause;{	ResetBufs ();	close (NetFd);	NetFd = -1;	State = ST_COMMAND;	OutputBlocked = 0;	CurrentX29Parms[X29_DISCARD_OUTPUT_CODE] = 0;	message ("nimd: Call cleared - %s\r", cause);	log ("Call cleared - %s", cause);}ForwardPacket (){	register struct buf *bp, *tp = packet;	if (!ISEMPTY(tp) && (State & ST_COMMAND) == 0) {		AddParity (tp->b_bot, SIZE (tp));		bp = getbuf (SIZE (tp) + 1);		PUTCHAR(0, bp);		BufCopy(tp, bp);		enqueue (bp, &netoqueue);	}	RESET (tp);	if (TimerOn)		ClearTimer ();}ToNet (pp, len)struct packet *pp;{	register struct buf *bp;	/*	 * round buffer size up to a multiple of 64 bytes	 * to reduce accumulation of small and usually	 * useless buffers in the free list.  This speeds	 * up malloc().	 */	bp = getbuf ((len + 63) & ~63);	bcopy ((char *)pp, bp->b_bot, len);	bp->b_top = bp->b_bot + len;	enqueue (bp, &netoqueue);}timeout(){	TimerOn = 0;	ForwardPacket ();	longjmp (JmpBuf, 0);}SetTimer (){	register int t;	struct itimerval itv;	if (TimerOn || (t = CurrentX29Parms[X29_IDLE_TIMER_CODE]) <= 0)		return;	itv.it_interval.tv_sec = 0;	itv.it_interval.tv_usec = 0;	itv.it_value.tv_sec = t / 20;	itv.it_value.tv_usec = t % 20 * 1000000 / 20;	signal (SIGALRM, SIG_IGN);	/* cancel possible pending signal */	signal (SIGALRM, timeout);	sigsetmask (1 << (SIGALRM - 1));	TimerOn++;	setitimer (ITIMER_REAL, &itv, (struct itimerval *)0);}ClearTimer (){	struct itimerval itv;	signal (SIGALRM, SIG_IGN);	bzero ((char *)&itv, sizeof (itv));	setitimer (ITIMER_REAL, &itv, (struct itimerval *)0);	TimerOn = 0;}FromNet (bp, len)char *bp;{	if ((*bp & Q_BIT) == 0) {		register struct x25packet *xp = (struct x25packet *)bp;		if (CurrentX29Parms[X29_DISCARD_OUTPUT_CODE] == 0) {			AddParity (xp->p_x25data, len - 1);			ToPty (xp->p_x25data, len - 1, FROMNET);		}		return;	}	X29ControlMessage ((struct x29packet *)bp, len);}SendX25Interrupt(){	char c = 0x77;	send (NetFd, &c, 1, MSG_OOB);}#ifdef fastidious	/* we need stdio *//* * Sorry about this... * Defining this dummy procedure prevents the stdio package * (about 17K bytes worth) from being loaded.  This program * does not require any support from the 4.2bsd stdio library. */#ifdef vax_cleanup(){}#endif#endifNimTrace(who, bp, n)char *who, *bp;{	static int fd;	if (TraceFile == 0)		return;	if(fd <= 0 && (fd = creat(TraceFile, 0640)) < 0)		return;	DisplayPacketContents (fd, who, bp, n);}OpenLog (){	if (LogFd >= 0)		return;	if (LogDev = rindex (PtyName, '/'))		LogDev++;	else		LogDev = PtyName;	if ((LogFd = open (LOGFILE, 1)) >= 0)		return;	LogFd = creat (LOGFILE, 0640);}CloseLog(){	if (LogFd >= 0) {		close(LogFd);		LogFd = -1;	}}/*VARARGS*/log(fmt, a1, a2, a3, a4, a5)char *fmt;{	register char *DateTime;	char format[128], *ctime ();	time_t t;	if (LogFd < 0)		return;	(void) time (&t);	DateTime = ctime (&t);	DateTime[19] = '\0';	sprint (format, "%s %s %s\n", DateTime+4, LogDev, fmt);	lseek (LogFd, (long)0, 2);	fprint (LogFd, format, a1, a2, a3, a4, a5);}LogPacket (bp, len)char *bp;{	if (LogFd < 0)		return;	DisplayPacketContents (LogFd, "net rx", bp, len);}DisplayPacketContents (fd, from, pp, len)char *from;register char *pp;register int len;{	register int first = 1;	char buf[128];	lseek (fd, (long)0, 2);	do {		ConvertToOctal (pp, len, buf);		if (first) {			fprint (fd, "%s[%d]\t%s\n", from, len, buf);			first = 0;		} else			fprint (fd, "\t\t%s\n", buf);		ConvertToAscii (pp, len, buf);		fprint (fd, "\t\t%s\n", buf);		pp += 16;		len -= 16;	} while (len > 0);}ConvertToOctal (start, len, bp)register char *start, *bp;{	register char *cp;	if (len > 16)		len = 16;	for (cp = start; cp - start < len; cp++) {		*bp++ = ((*cp & 0300) >> 6) + '0';		*bp++ = ((*cp & 070) >> 3) + '0';		*bp++ = (*cp & 07) + '0';		*bp++ = ' ';	}	bp[-1] = '\0';}			ConvertToAscii (start, len, bp)register char *start, *bp;{	register char *cp;	if (len > 16)		len = 16;	for (cp = start; cp - start < len; cp++) {		*bp++ = ' ';		switch (*cp) {		case '\b':			*bp++ = '\\';			*bp++ = 'b';			break;		case '\t':			*bp++ = '\\';			*bp++ = 't';			break;		case '\n':			*bp++ = '\\';			*bp++ = 'n';			break;		case '\f':			*bp++ = '\\';			*bp++ = 'f';			break;		case '\r':			*bp++ = '\\';			*bp++ = 'r';			break;		default:			*bp++ = ' ';			if ((*cp&0177) > ' ' && (*cp&0177) < 0177)				*bp++ = *cp;			else				*bp++ = ' ';		}		*bp++ = ' ';	}	bp[-1] = '\0';}

⌨️ 快捷键说明

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