tgetent() of libtermlib does not use private termcaps correctly.
Karl Kleinpaste
karl at osu-eddie.UUCP
Fri Dec 14 13:30:23 AEST 1984
While working with the tenex csh distributed around Oct 1983, it became
obvious that the vb capability advertised by the man page is not in fact
available at all times. Specifically, it does not deal with any capabilities
in a personalized termcap file referenced by a TERMCAP env variable. The
problem is that termcap.c in libtermlib.a has a bogus check for what
constitutes a valid file descriptor, and inadvertently throws away the
reference to one's personalized termcap file. This bug report is for both
4BSD and USG5.0, but I believe it applies to all libtermlibs.
Subject: tgetent() of libtermlib does not use private termcaps correctly.
Index: /usr/src/usr.lib/libtermlib/termcap.c 4.2BSD
Description:
Routine tgetent() of libtermlib has an incorrect check for whether
or not the open of a personalized termcap file (referenced by an
environment variable TERMCAP) succeeds: it checks against 0 as an
invalid descriptor, when in fact 0 is a perfectly reasonable (if
somewhat unusual) file descriptor for use with an interactive
program as something other than stdin. This may sometimes cause
the reference to the personalized termcap file to be ignored, and
/etc/termcap will be substituted.
Repeat-By:
% vi ~/.termcap
[Create a termcap entry for the current terminal from a similar
entry in /etc/termcap. Add a vb capability to the entry; anything
will do, it doesn't matter what you use. Make sure that the
original /etc/termcap version of the termcap entry does not have a
vb capability, or at least that it's a different vb.]
% setenv TERMCAP ~/.termcap
% csh [Use tenex csh, not /bin/csh.]
[Subshell starts up...next prompt is from that csh.]
% ^[ [Hit an ESC.]
[The csh will beep at you, using ^G, instead of the vb capability
just added above in ~/.termcap, and will then erase the ^[ as it's
supposed to.]
The problem is that the open of ~/.termcap showed up as file
descriptor 0, which caused tgetent() to ignore it. (Csh moves
stdin, stdout, and stderr away from 0, 1, and 2 frequently.)
Fix:
The routine tgetent() must be fixed so that it checks for file
descriptors less than zero as an "invalid" condition. Diffs follow.
*** termcap.c~ Thu Dec 13 18:24:33 1984
--- termcap.c Thu Dec 13 18:26:50 1984
***************
*** 44,50
int tf;
tbuf = bp;
! tf = 0;
#ifndef V6
cp = getenv("TERMCAP");
/*
--- 44,50 -----
int tf;
tbuf = bp;
! tf = -1; /* fixed initialization: used to be 0. */
#ifndef V6
cp = getenv("TERMCAP");
/*
***************
*** 66,72
} else
tf = open(cp, 0);
}
! if (tf==0)
tf = open(E_TERMCAP, 0);
#else
tf = open(E_TERMCAP, 0);
--- 66,72 -----
} else
tf = open(cp, 0);
}
! if (tf < 0) /* fixed test: used to be "tf == 0". */
tf = open(E_TERMCAP, 0);
#else
tf = open(E_TERMCAP, 0);
Workaround:
For those who lack appropriate privileges to edit/recompile the
source files for libtermlib, the following is a (generally) suitable
fix for the problem:
All occurrences of
if (tgetent(term, area) < 0)
{
/* recover from no-termcap-file error condition. */
}
can be bracketed thusly:
{
int dummyfile = -1;
dummyfile = open ("/dev/null", 0);
if (tgetent (term, area) < 0)
{
/* recover from error as before. */
}
close (dummyfile);
}
This makes sure that file descriptor 0 is occupied by some open
file, since Unix always assigns the lowest-available file descriptor
when a new file is opened.
Note that this will not always work. Since it occupies another file
descriptor, it may cause programs needing large numbers of files to
reach the EMFILE "too many open files" conditon.
--
>From the badly beaten keyboards of him who speaks +---best address
in textured Technicolor *TyPe* f-O-n-T-s... |
|
Karl Kleinpaste @ Bell Labs, Columbus 614/860-5107 +-----> cbrma!kk
@ Ohio State University 614/422-0915 osu-eddie!karl
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list