home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d147
/
mg.lha
/
termlib
/
termlib.zoo
/
tgetent.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-25
|
12KB
|
467 lines
/************************************************************************
* *
* Copyright (c) 1982, Fred Fish *
* All Rights Reserved *
* *
* This software and/or documentation is released for public *
* distribution for personal, non-commercial use only. *
* Limited rights to use, modify, and redistribute are hereby *
* granted for non-commercial purposes, provided that all *
* copyright notices remain intact and all changes are clearly *
* documented. The author makes no warranty of any kind with *
* respect to this product and explicitly disclaims any implied *
* warranties of merchantability or fitness for any particular *
* purpose. *
* *
************************************************************************
*/
/*
* Modified:
* 30-Apr-86 Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Instead of using VAX C getenv("TERM"), which does not
* return the value of logical name "TERM", translate the
* logical name by hand.
* 11-Oct-86 Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
* Support tc capability to allow the library to use standard
* termcaps. Rewrote tgetent to look for tc capability
* and add new terminal definition to the caller's buffer.
* This makes it rather possible to overflow the caller's
* buffer, but the library doesn't make any claim that it
* won't overwrite the buffer anyway...
* 27-Jan-88 Bob Larson blarson@ecla.usc.edu
* Add primos (__50SERIES) support.
* 1-Feb-88 Sandra Loosemore (sandra@cs.utah.edu)
* Change default termcap file for VMS to be the same place
* that GNU puts it.
* 23-Apr-88 Bob Larson
* merge primos and vms changes
*/
/*
* LIBRARY FUNCTION
*
* tgetent load buffer with entry for specified terminal
*
* KEY WORDS
*
* termcap functions
* utility routines
*
* SYNOPSIS
*
* int tgetent(bp,name)
* char *bp;
* char *name;
*
* DESCRIPTION
*
* Extracts the entry for terminal <name> from the termcap file
* and places it in the character buffer <bp>. It is currently
* assumed that bp is at least 1024 characters. If the entry in
* the termcap file is larger than 1023 characters the excess
* characters will be discarded and appropriate status will
* be returned.
*
* Also note that since bp is used by other termcap
* routines, the storage associated with the termcap entry
* cannot be freed until all termcap calls are completed.
*
* Tgetent can be directed to look in a file other than
* the default (/etc/termcap) by defining an environment
* variable called TERMCAP to be the pathname of the desired
* termcap file. This is useful for debugging new entries.
* NOTE: the pathname MUST begin with a '/' character.
*
* Also, if the string assigned to TERMCAP does not begin with
* a '/' and if the environment variable TERM matches <name> then
* the string assigned to TERMCAP is copied to buffer <bp>
* instead of reading a termcap file.
*
* RETURNS
*
* -1 if the termcap file cannot be opened
* 0 if no entry in termcap file matches <name>
* 1 if extraction is successful with no errors
* 2 if extraction is successful but entry truncated
*
* SEE ALSO
*
* tgetnum extract numeric type capability
* tgetflag test boolean type capability
* tgetstr get string value of capability
*
* AUTHOR
*
* Fred Fish
*
*/
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define BUFSIZE 1024 /* Assumed size of external buffer */
#define NO_FILE -1 /* Returned if can't open file */
#define NO_ENTRY 0 /* Returned if can't find entry */
#define SUCCESS 1 /* Returned if entry found ok */
#define TRUNCATED 2 /* Returned if entry found but trunc */
#ifdef __50SERIES
#define DEFAULT_FILE "mg*>termcap"
#else
#define DEFAULT_FILE "/etc/termcap" /* default termcap filename */
#ifdef VAXC
#define index strchr
#endif
#endif
char *_tcpbuf; /* Place to remember buffer pointer */
FILE *fp; /* Termcap file */
static FILE *find_file();
extern char *index();
/*
* PSEUDO CODE
*
* Begin tgetent
* Erase any previous buffer contents.
* Remember the buffer pointer.
* If termcap file is not found then
* If buffer was filled anyway then
* Return SUCCESS.
* Else
* Return NO_FILE.
* End if
* Else
* Find entry associated with name
* While an entry was found and limit not reached
* If no tc capability found Then
* Exit while loop with status = SUCCESS
* Else
* Call getent to get entry indicated by tc=
* If entry not found then
* Exit loop with status != SUCCESS
* End if
* Concatenate entry into buffer
* End If
* End while
* End if
* Close termcap file
* Return status code
* End tgetent
*
*/
static int getent();
int tgetent(bp,name)
char *bp;
char *name;
{
char *tc, *tcbufp, tcbuf[80], termbuf[BUFSIZE], *tgetstr();
char *bufp, *cp; /* current start of buffer */
int limit = 10; /* maximum nesting */
int status; /* return from getent() */
*bp = '\0'; /* clear buffer */
_tcpbuf = bp; /* save base of buffer */
/* Look for termcap file. If NULL, find_file may have found a */
/* a valid termcap string in the environment variable TERMCAP. */
/* If non-null, attempt to find the entry in the termcap file */
if ((fp = find_file(bp)) == NULL) {
if (*bp != NULL)
return(SUCCESS);
else
return(NO_FILE);
}
status = getent(bp, name);/* look for main entry */
/* Start looking for tc capabilities in the termcap. If
* found, concatenate the entry for the new terminal to the
* current buffer and try again. To avoid infinite loops,
* allow only 10 loops through this process.
*/
while ((status == SUCCESS) && limit--) {
/* look for tc capability. If none found, exit loop */
tcbufp = tcbuf;
if (((tc = tgetstr("tc",&tcbufp)) == NULL)
|| (*tc == '\0')) {
status = SUCCESS;/* no more tc= entries */
break;
}
/* Attempt to get next entry. Exit loop if unsuccessful */
if ((status = getent(termbuf, tcbuf)) != SUCCESS)
break;
/* Copy new entry into buffer, right at "tc=" */
for (bufp = bp; *bufp; bufp++) /* find tc= */
if ((*bufp=='t') && (bufp[1]=='c') && (bufp[2]=='='))
break;
if ((cp = index(termbuf,':')) == NULL)
cp = termbuf;
strcpy(bufp, cp + 1);
}
/* close termcap file and return the status */
fclose(fp);
return status;
}
/*
* INTERNAL FUNCTION
*
* getent find termcap entry in termcap file
*
* KEY WORDS
*
* internal functions
* getent
*
* SYNOPSIS
*
* static int getent(bp,name)
* char *bp;
* char *name;
*
* DESCRIPTION
*
* Getent is called by tgetent each time tgetent attempts to
* read a capability from the termcap database file. Places
* the entry in the buffer pointed to by bp
*
*
* PSEUDOCODE
*
* Begin Getent
* Seek to beginning of termcap file
* Clear buffer
* While records left to process
* If this is entry is what we want then
* If entry was truncated then
* Return TRUNCATED status
* Else
* Return SUCCESS status.
* End if
* End if
* End while
* Return NO_ENTRY status.
* End
*/
static int getent(bp,name)
char *bp; /* Pointer to buffer (1024 char min) */
char *name; /* Pointer to terminal entry to find */
{
*bp = '\0'; /* clear buffer */
lseek(fileno(fp), 0L, 0l); /* rewind termcap file */
while (fgetlr(bp,BUFSIZE,fp)) {
if (gotcha(bp,name)) {
if (bp[strlen(bp)-1] != '\n') {
return(TRUNCATED);
} else {
return(SUCCESS);
}
}
}
return(NO_ENTRY);
}
/*
* INTERNAL FUNCTION
*
* find_file find the termcap file and open it if possible
*
* KEY WORDS
*
* internal functions
* find_file
*
* SYNOPSIS
*
* static FILE *find_file(bp)
* char *bp;
*
* DESCRIPTION
*
* Attempts to locate and open the termcap file. Also handles
* using the environment TERMCAP string as the actual buffer
* (that's why bp has to be an input parameter).
*
* If TERMCAP is defined an begins with a '/' character then
* it is taken to be the pathname of the termcap file and
* an attempt is made to open it. If this fails then
* the default termcap file is used instead.
*
* If TERMCAP is defined but does not begin with a '/' then
* it is assumed to be the actual buffer contents provided
* that <name> matches the environment variable TERM.
*
* BUGS
*
* There is currently no way to be sure which termcap
* file was opened since the default will always be
* tried.
*
*/
/*
* PSEUDO CODE
*
* Begin find_file
* If there is a TERMCAP environment string then
* If the string is not null then
* If the string is a pathname then
* If that file is opened successfully then
* Return its pointer.
* End if
* Else
* If there is a TERM environment string then
* If TERM matches <name> then
* Copy TERMCAP string to buffer.
* Return NULL for no file.
* End if
* End if
* End if
* End if
* End if
* Open default termcap file and return results.
* End find_file
*
*/
#ifdef __50SERIES
static FILE *find_file(bp)
char *bp;
{
char *cp;
char *gvget();
if((cp = gvget(".TERMCAP")) != NULL && *cp)
return fopen(cp, "r");
if((cp = gvget(".TERMCAP$")) != NULL && *cp)
return fopen(cp, "r");
return fopen(DEFAULT_FILE, "r");
}
#else
#ifdef VAXC
char *trnlnm();
#endif
static FILE *find_file(bp)
char *bp;
{
FILE *fp, *fopen();
char *cp, *ncp, *getenv(), vmsname[132];
if ((cp = getenv("TERMCAP")) != NULL) {
if (*cp != NULL) {
if (*cp == '/') {
if ((fp = fopen(cp,"r")) != NULL) {
return(fp);
}
} else {
#ifdef VAXC
if ((ncp = trnlnm("TERM")) != NULL) {
#else
if ((ncp = getenv("TERM")) != NULL) {
#endif
if (strcmp(cp,ncp) == 0) {
strcpy(bp,cp);
return((FILE *)NULL);
}
}
}
}
}
#ifdef VAXC
if ((fp = fopen("emacs_library:[etc]termcap.dat","r")) != NULL)
return(fp);
#endif
return(fopen(DEFAULT_FILE,"r"));
}
#endif /* __50SERIES */
/*
* INTERNAL FUNCTION
*
* gotcha test to see if entry is for specified terminal
*
* SYNOPSIS
*
* gotcha(bp,name)
* char *bp;
* char *name;
*
* DESCRIPTION
*
* Tests to see if the entry in buffer bp matches the terminal
* specified by name. Returns TRUE if match is detected, FALSE
* otherwise.
*
*/
/*
* PSEUDO CODE
*
* Begin gotcha
* If buffer character is comment character then
* Return FALSE since remainder is comment
* Else
* Initialize name scan pointer.
* Compare name and buffer until end or mismatch.
* If valid terminators for both name and buffer strings
* Return TRUE since a match was found.
* Else
* Find next non-name character in buffer.
* If not an alternate name separater character
* Return FALSE since no more names to check.
* Else
* Test next name and return results.
* End if
* End if
* End if
* End gotcha
*
*/
gotcha(bp,name)
char *bp;
char *name;
{
char *np;
if (*bp == '#') {
return(FALSE);
} else {
np = name;
while (*np == *bp && *np != NULL) {np++; bp++;}
if (*np == NULL && (*bp == NULL || *bp == '|' || *bp == ':')) {
return(TRUE);
} else {
while (*bp != NULL && *bp != ':' && *bp != '|') {bp++;}
if (*bp != '|') {
return(FALSE);
} else {
return(gotcha(++bp,name));
}
}
}
}