* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)remcap.c 5.1 (Berkeley) %G%";
* remcap - routines for dealing with the remote host data base
#define MAXHOP 32 /* max number of tc= indirections */
#define SYSREMOTE "/etc/remote" /* system remote file */
#define tnamatch rnamatch
#define tgetflag rgetflag
#define E_TERMCAP RM = SYSREMOTE
#define V_TERMCAP "REMOTE"
* 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 int hopcount
; /* detect infinite loops in termcap, init 0 */
* Get an entry for terminal name in buffer bp,
* from the termcap file. Parse is very rudimentary;
* we just notice escaped newlines.
char lbuf
[BUFSIZ
], *cp
, *p
;
remotefile
= cp
= getenv(V_TERMCAP
);
if (cp
== (char *)0 || strcmp(cp
, SYSREMOTE
) == 0) {
remotefile
= cp
= SYSREMOTE
;
return (getent(bp
, name
, cp
));
if ((rc1
= getent(bp
, name
, cp
)) != 1)
remotefile
= cp
= SYSREMOTE
;
rc2
= getent(lbuf
, name
, cp
);
if (rc1
!= 1 && rc2
!= 1)
if (strlen(bp
) + strlen(p
) > BUFSIZ
) {
write(2, "Remcap entry too long\n", 23);
register int i
= 0, cnt
= 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 (cp2
== (char *)0 || strcmp(name
,cp2
) == 0) {
tf
= open(E_TERMCAP
, O_RDONLY
);
tf
= open(RM
= cp
, O_RDONLY
);
tf
= open(E_TERMCAP
, O_RDONLY
);
cnt
= read(tf
, ibuf
, BUFSIZ
);
if (cp
> bp
&& cp
[-1] == '\\') {
write(2,"Remcap entry too long\n", 23);
* The real work for the match.
* 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.
char tcname
[16]; /* name of similar terminal */
p
= tbuf
+ strlen(tbuf
) - 2; /* before the last colon */
write(2, "Bad remcap entry\n", 18);
/* p now points to beginning of last field */
if (p
[0] != 't' || p
[1] != 'c')
if (++hopcount
> MAXHOP
) {
write(2, "Infinite tc= loop\n", 18);
if (getent(tcbuf
, tcname
, remotefile
) != 1) {
if (strcmp(remotefile
, SYSREMOTE
) == 0)
else if (getent(tcbuf
, tcname
, SYSREMOTE
) != 1)
for (q
= tcbuf
; *q
++ != ':'; )
l
= p
- holdtbuf
+ strlen(q
);
write(2, "Remcap entry too long\n", 23);
q
[BUFSIZ
- (p
-holdtbuf
)] = 0;
* 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.
for (Np
= np
; *Np
&& *Bp
== *Np
; Bp
++, Np
++)
if (*Np
== 0 && (*Bp
== '|' || *Bp
== ':' || *Bp
== 0))
while (*Bp
&& *Bp
!= ':' && *Bp
!= '|')
if (*Bp
== 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.
while (*bp
&& *bp
!= ':')
* Return the (numeric) option id.
* Numeric options look like
* 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.
register char *bp
= tbuf
;
if (*bp
++ != id
[0] || *bp
== 0 || *bp
++ != id
[1])
i
*= base
, i
+= *bp
++ - '0';
* 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
register char *bp
= tbuf
;
if (*bp
++ == id
[0] && *bp
!= 0 && *bp
++ == id
[1]) {
* Get a string valued option.
* 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.
register char *bp
= tbuf
;
if (*bp
++ != id
[0] || *bp
== 0 || *bp
++ != id
[1])
return (tdecode(bp
, area
));
* Tdecode does the grung work to decode the
* string capability escapes.
while ((c
= *str
++) && c
!= ':') {
dp
= "E\033^^\\\\::n\nr\rt\tb\bf\f";
c
<<= 3, c
|= *str
++ - '0';
while (--i
&& isdigit(*str
));