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

📄 remcap.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1983, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)remcap.c	8.1 (Berkeley) 6/6/93";#endif /* not lint *//* * remcap - routines for dealing with the remote host data base * * derived from termcap */#include <sys/types.h>#include <fcntl.h>#include <ctype.h>#include <stdlib.h>#include "pathnames.h"#ifndef BUFSIZ#define	BUFSIZ		1024#endif#define MAXHOP		32		/* max number of tc= indirections */#define	tgetent		rgetent#define	tnchktc		rnchktc#define	tnamatch	rnamatch#define	tgetnum		rgetnum#define	tgetflag	rgetflag#define	tgetstr		rgetstr#define	E_TERMCAP	RM = _PATH_REMOTE#define V_TERMCAP	"REMOTE"#define V_TERM		"HOST"char	*RM;/* * termcap - routines for dealing with the terminal capability data base * * BUG:		Should use a "last" pointer in tbuf, so that searching *		for capabilities alphabetically would not be a n**2/2 *		process when large numbers of capabilities are given. * Note:	If we add a last pointer now we will screw up the *		tc capability. We really should compile termcap. * * Essentially all the work here is scanning and decoding escapes * in string capabilities.  We don't use stdio because the editor * doesn't, and because living w/o it is not hard. */static	char *tbuf;static	int hopcount;	/* detect infinite loops in termcap, init 0 */static	char *tskip();char	*tgetstr();static	char *tdecode();static	char *remotefile;/* * Get an entry for terminal name in buffer bp, * from the termcap file.  Parse is very rudimentary; * we just notice escaped newlines. */tgetent(bp, name)	char *bp, *name;{	char lbuf[BUFSIZ], *cp, *p;	int rc1, rc2;	remotefile = cp = getenv(V_TERMCAP);	if (cp == (char *)0 || strcmp(cp, _PATH_REMOTE) == 0) {		remotefile = cp = _PATH_REMOTE;		return (getent(bp, name, cp));	} else {		if ((rc1 = getent(bp, name, cp)) != 1)			*bp = '\0';		remotefile = cp = _PATH_REMOTE;		rc2 = getent(lbuf, name, cp);		if (rc1 != 1 && rc2 != 1)			return (rc2);		if (rc2 == 1) {			p = lbuf;			if (rc1 == 1)				while (*p++ != ':')					;			if (strlen(bp) + strlen(p) > BUFSIZ) {				write(2, "Remcap entry too long\n", 23);				return (-1);			}			strcat(bp, p);		}		tbuf = bp;		return (1);	}}getent(bp, name, cp)	char *bp, *name, *cp;{	register int c;	register int i = 0, cnt = 0;	char ibuf[BUFSIZ], *cp2;	int tf;	tbuf = bp;	tf = 0;	/*	 * TERMCAP can have one of two things in it. It can be the	 * name of a file to use instead of /etc/termcap. In this	 * case it better start with a "/". Or it can be an entry to	 * use so we don't have to read the file. In this case it	 * has to already have the newlines crunched out.	 */	if (cp && *cp) {		if (*cp!='/') {			cp2 = getenv(V_TERM);			if (cp2 == (char *)0 || strcmp(name,cp2) == 0) {				strcpy(bp,cp);				return (tnchktc());			} else				tf = open(E_TERMCAP, O_RDONLY);		} else			tf = open(RM = cp, O_RDONLY);	}	if (tf == 0)		tf = open(E_TERMCAP, O_RDONLY);	if (tf < 0)		return (-1);	for (;;) {		cp = bp;		for (;;) {			if (i == cnt) {				cnt = read(tf, ibuf, BUFSIZ);				if (cnt <= 0) {					close(tf);					return (0);				}				i = 0;			}			c = ibuf[i++];			if (c == '\n') {				if (cp > bp && cp[-1] == '\\') {					cp--;					continue;				}				break;			}			if (cp >= bp+BUFSIZ) {				write(2,"Remcap entry too long\n", 23);				break;			} else				*cp++ = c;		}		*cp = 0;		/*		 * The real work for the match.		 */		if (tnamatch(name)) {			close(tf);			return (tnchktc());		}	}}/* * tnchktc: check the last entry, see if it's tc=xxx. If so, * recursively find xxx and append that entry (minus the names) * to take the place of the tc=xxx entry. This allows termcap * entries to say "like an HP2621 but doesn't turn on the labels". * Note that this works because of the left to right scan. */tnchktc(){	register char *p, *q;	char tcname[16];	/* name of similar terminal */	char tcbuf[BUFSIZ];	char *holdtbuf = tbuf;	int l;	char *cp;	p = tbuf + strlen(tbuf) - 2;	/* before the last colon */	while (*--p != ':')		if (p<tbuf) {			write(2, "Bad remcap entry\n", 18);			return (0);		}	p++;	/* p now points to beginning of last field */	if (p[0] != 't' || p[1] != 'c')		return (1);	strcpy(tcname, p+3);	q = tcname;	while (*q && *q != ':')		q++;	*q = 0;	if (++hopcount > MAXHOP) {		write(2, "Infinite tc= loop\n", 18);		return (0);	}	if (getent(tcbuf, tcname, remotefile) != 1) {		if (strcmp(remotefile, _PATH_REMOTE) == 0)			return (0);		else if (getent(tcbuf, tcname, _PATH_REMOTE) != 1)			return (0);	}	for (q = tcbuf; *q++ != ':'; )		;	l = p - holdtbuf + strlen(q);	if (l > BUFSIZ) {		write(2, "Remcap entry too long\n", 23);		q[BUFSIZ - (p-holdtbuf)] = 0;	}	strcpy(p, q);	tbuf = holdtbuf;	return (1);}/* * Tnamatch deals with name matching.  The first field of the termcap * entry is a sequence of names separated by |'s, so we compare * against each such name.  The normal : terminator after the last * name (before the first field) stops us. */tnamatch(np)	char *np;{	register char *Np, *Bp;	Bp = tbuf;	if (*Bp == '#')		return (0);	for (;;) {		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)			continue;		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))			return (1);		while (*Bp && *Bp != ':' && *Bp != '|')			Bp++;		if (*Bp == 0 || *Bp == ':')			return (0);		Bp++;	}}/* * Skip to the next field.  Notice that this is very dumb, not * knowing about \: escapes or any such.  If necessary, :'s can be put * into the termcap file in octal. */static char *tskip(bp)	register char *bp;{	while (*bp && *bp != ':')		bp++;	if (*bp == ':')		bp++;	return (bp);}/* * Return the (numeric) option id. * Numeric options look like *	li#80 * i.e. the option string is separated from the numeric value by * a # character.  If the option is not found we return -1. * Note that we handle octal numbers beginning with 0. */tgetnum(id)	char *id;{	register int i, base;	register char *bp = tbuf;	for (;;) {		bp = tskip(bp);		if (*bp == 0)			return (-1);		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])			continue;		if (*bp == '@')			return (-1);		if (*bp != '#')			continue;		bp++;		base = 10;		if (*bp == '0')			base = 8;		i = 0;		while (isdigit(*bp))			i *= base, i += *bp++ - '0';		return (i);	}}/* * Handle a flag option. * Flag options are given "naked", i.e. followed by a : or the end * of the buffer.  Return 1 if we find the option, or 0 if it is * not given. */tgetflag(id)	char *id;{	register char *bp = tbuf;	for (;;) {		bp = tskip(bp);		if (!*bp)			return (0);		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {			if (!*bp || *bp == ':')				return (1);			else if (*bp == '@')				return (0);		}	}}/* * Get a string valued option. * These are given as *	cl=^Z * Much decoding is done on the strings, and the strings are * placed in area, which is a ref parameter which is updated. * No checking on area overflow. */char *tgetstr(id, area)	char *id, **area;{	register char *bp = tbuf;	for (;;) {		bp = tskip(bp);		if (!*bp)			return (0);		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])			continue;		if (*bp == '@')			return (0);		if (*bp != '=')			continue;		bp++;		return (tdecode(bp, area));	}}/* * Tdecode does the grung work to decode the * string capability escapes. */static char *tdecode(str, area)	register char *str;	char **area;{	register char *cp;	register int c;	register char *dp;	int i;	cp = *area;	while ((c = *str++) && c != ':') {		switch (c) {		case '^':			c = *str++ & 037;			break;		case '\\':			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";			c = *str++;nextc:			if (*dp++ == c) {				c = *dp++;				break;			}			dp++;			if (*dp)				goto nextc;			if (isdigit(c)) {				c -= '0', i = 2;				do					c <<= 3, c |= *str++ - '0';				while (--i && isdigit(*str));			}			break;		}		*cp++ = c;	}	*cp++ = 0;	str = *area;	*area = cp;	return (str);}

⌨️ 快捷键说明

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