/************************************************************************
 *									*
 *			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.							*
 *									*
 ************************************************************************
 */


/*
 *  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
 *
 */
/*
 *  881003  Turbo C has no fopenp(), so enclose this function call in
 *	    #ifndef __TURBOC__.  This means that the routine will not
 *	    search the path for TERMCAP under Turbo C. -3.
 */

#include <stdio.h>
#include <string.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 MSDOS
# define DEFAULT_ROOT "termcap"         /* name without path component */
  FILE *fopenp();
#endif
# define DEFAULT_FILE "/etc/termcap"	/* default termcap filename */

char *_tcpbuf;				/* Place to remember buffer pointer */

/*
 *  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
 *		While records left to process
 *		    If this is entry is what we want then
 *			Close the termcap file.
 *			If entry was truncated then
 *			    Return TRUNCATED status
 *			Else
 *			    Return SUCCESS status.
 *			End if
 *		    End if
 *		End while
 *		Return NO_ENTRY status.
 *	    End if
 *	End tgetent
 *			
 */

int tgetent(bp,name)
char *bp;				/* Pointer to buffer (1024 char min) */
char *name;				/* Pointer to terminal entry to find */
{
    FILE *fp, *find_file();

    *bp = NULL;
    _tcpbuf = bp;
    if ((fp = find_file(bp)) == NULL) {
	if (*bp != NULL) {
	    return(SUCCESS);
	} else {
	    return(NO_FILE);
	}
    } else {
	while (fgetlr(bp,BUFSIZE,fp)) {
	    if (gotcha(bp,name)) {
		fclose(fp);
		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
 *
 */

static FILE *find_file(bp)
char *bp;
{
    FILE *fp, *fopen();
    char *cp, *ncp, *getenv();

    if ((cp = getenv("TERMCAP")) != NULL) {
	if (*cp != NULL) {
        if (*cp == '/' || *cp == '\\' || *cp + 1 == ':') {
		if ((fp = fopen(cp,"r")) != NULL) {
		    return(fp);
		}
	    } else {
		if ((ncp = getenv("TERM")) != NULL) {
		    if (strcmp(cp,ncp) == 0) {
			strcpy(bp,cp);
			return((FILE *)NULL);
		    }
		}
	    }
	}
    }
# ifdef MSDOS
        /* Try current directory, then /etc/termcap, then along the path
	 */
	if (fp = fopen(DEFAULT_ROOT, "r"))
		return fp;
	else if (fp = fopen(DEFAULT_FILE, "r"))
		return fp;
# ifndef __TURBOC__
        else
		return fopenp(DEFAULT_ROOT, "r", NULL);
# endif
# else
    return(fopen(DEFAULT_FILE,"r"));
# endif
}

/*
 *  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));
	    }
	}
    }
}
