119304Speter/*-
219304Speter * Copyright (c) 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter *
719304Speter * See the LICENSE file for redistribution information.
886201Srwatson *
986201Srwatson * $FreeBSD$
1019304Speter */
1119304Speter
1219304Speter#include "config.h"
1319304Speter
1419304Speter#ifndef lint
1519304Speterstatic const char sccsid[] = "@(#)cl_screen.c	10.49 (Berkeley) 9/24/96";
1619304Speter#endif /* not lint */
1719304Speter
1819304Speter#include <sys/types.h>
1919304Speter#include <sys/queue.h>
2019304Speter
2119304Speter#include <bitstring.h>
2219304Speter#include <curses.h>
2319304Speter#include <errno.h>
2419304Speter#include <signal.h>
2519304Speter#include <stdio.h>
2619304Speter#include <stdlib.h>
2719304Speter#include <string.h>
28170371Srafan#include <term.h>
2919304Speter#include <termios.h>
3019304Speter#include <unistd.h>
3119304Speter
3219304Speter#include "../common/common.h"
3319304Speter#include "cl.h"
3419304Speter
3519304Speterstatic int	cl_ex_end __P((GS *));
3619304Speterstatic int	cl_ex_init __P((SCR *));
3719304Speterstatic void	cl_freecap __P((CL_PRIVATE *));
3819304Speterstatic int	cl_vi_end __P((GS *));
3919304Speterstatic int	cl_vi_init __P((SCR *));
4019304Speterstatic int	cl_putenv __P((char *, char *, u_long));
4119304Speter
4219304Speter/*
4319304Speter * cl_screen --
4419304Speter *	Switch screen types.
4519304Speter *
4619304Speter * PUBLIC: int cl_screen __P((SCR *, u_int32_t));
4719304Speter */
4819304Speterint
4919304Spetercl_screen(sp, flags)
5019304Speter	SCR *sp;
5119304Speter	u_int32_t flags;
5219304Speter{
5319304Speter	CL_PRIVATE *clp;
5419304Speter	GS *gp;
5519304Speter
5619304Speter	gp = sp->gp;
5719304Speter	clp = CLP(sp);
5819304Speter
5919304Speter	/* See if the current information is incorrect. */
6019304Speter	if (F_ISSET(gp, G_SRESTART)) {
6119304Speter		if (cl_quit(gp))
6219304Speter			return (1);
6319304Speter		F_CLR(gp, G_SRESTART);
6419304Speter	}
6519304Speter
6619304Speter	/* See if we're already in the right mode. */
6719304Speter	if (LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX) ||
6819304Speter	    LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI))
6919304Speter		return (0);
7019304Speter
7119304Speter	/*
7219304Speter	 * Fake leaving ex mode.
7319304Speter	 *
7419304Speter	 * We don't actually exit ex or vi mode unless forced (e.g. by a window
7519304Speter	 * size change).  This is because many curses implementations can't be
7619304Speter	 * called twice in a single program.  Plus, it's faster.  If the editor
7719304Speter	 * "leaves" vi to enter ex, when it exits ex we'll just fall back into
7819304Speter	 * vi.
7919304Speter	 */
8019304Speter	if (F_ISSET(sp, SC_SCR_EX))
8119304Speter		F_CLR(sp, SC_SCR_EX);
8219304Speter
8319304Speter	/*
8419304Speter	 * Fake leaving vi mode.
8519304Speter	 *
8619304Speter	 * Clear out the rest of the screen if we're in the middle of a split
8719304Speter	 * screen.  Move to the last line in the current screen -- this makes
8819304Speter	 * terminal scrolling happen naturally.  Note: *don't* move past the
8919304Speter	 * end of the screen, as there are ex commands (e.g., :read ! cat file)
9019304Speter	 * that don't want to.  Don't clear the info line, its contents may be
9119304Speter	 * valid, e.g. :file|append.
9219304Speter	 */
9319304Speter	if (F_ISSET(sp, SC_SCR_VI)) {
9419304Speter		F_CLR(sp, SC_SCR_VI);
9519304Speter
9619304Speter		if (sp->q.cqe_next != (void *)&gp->dq) {
9719304Speter			(void)move(RLNO(sp, sp->rows), 0);
9819304Speter			clrtobot();
9919304Speter		}
10019304Speter		(void)move(RLNO(sp, sp->rows) - 1, 0);
10119304Speter		refresh();
10219304Speter	}
10319304Speter
10419304Speter	/* Enter the requested mode. */
10519304Speter	if (LF_ISSET(SC_EX)) {
10619304Speter		if (cl_ex_init(sp))
10719304Speter			return (1);
10819304Speter		F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);
10919304Speter
11019304Speter		/*
11119304Speter		 * If doing an ex screen for ex mode, move to the last line
11219304Speter		 * on the screen.
11319304Speter		 */
11419304Speter		if (F_ISSET(sp, SC_EX) && clp->cup != NULL)
11519304Speter			tputs(tgoto(clp->cup,
11619304Speter			    0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
11719304Speter	} else {
11819304Speter		if (cl_vi_init(sp))
11919304Speter			return (1);
12019304Speter		F_CLR(clp, CL_IN_EX);
12119304Speter		F_SET(clp, CL_SCR_VI_INIT);
12219304Speter	}
12319304Speter	return (0);
12419304Speter}
12519304Speter
12619304Speter/*
12719304Speter * cl_quit --
12819304Speter *	Shutdown the screens.
12919304Speter *
13019304Speter * PUBLIC: int cl_quit __P((GS *));
13119304Speter */
13219304Speterint
13319304Spetercl_quit(gp)
13419304Speter	GS *gp;
13519304Speter{
13619304Speter	CL_PRIVATE *clp;
13719304Speter	int rval;
13819304Speter
13919304Speter	rval = 0;
14019304Speter	clp = GCLP(gp);
14119304Speter
14219304Speter	/*
14319304Speter	 * If we weren't really running, ignore it.  This happens if the
14419304Speter	 * screen changes size before we've called curses.
14519304Speter	 */
14619304Speter	if (!F_ISSET(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT))
14719304Speter		return (0);
14819304Speter
14919304Speter	/* Clean up the terminal mappings. */
15019304Speter	if (cl_term_end(gp))
15119304Speter		rval = 1;
15219304Speter
15319304Speter	/* Really leave vi mode. */
15419304Speter	if (F_ISSET(clp, CL_STDIN_TTY) &&
15519304Speter	    F_ISSET(clp, CL_SCR_VI_INIT) && cl_vi_end(gp))
15619304Speter		rval = 1;
15719304Speter
15819304Speter	/* Really leave ex mode. */
15919304Speter	if (F_ISSET(clp, CL_STDIN_TTY) &&
16019304Speter	    F_ISSET(clp, CL_SCR_EX_INIT) && cl_ex_end(gp))
16119304Speter		rval = 1;
16219304Speter
16319304Speter	/*
16419304Speter	 * If we were running ex when we quit, or we're using an implementation
16519304Speter	 * of curses where endwin() doesn't get this right, restore the original
16619304Speter	 * terminal modes.
16719304Speter	 *
16819304Speter	 * XXX
16919304Speter	 * We always do this because it's too hard to figure out what curses
17019304Speter	 * implementations get it wrong.  It may discard type-ahead characters
17119304Speter	 * from the tty queue.
17219304Speter	 */
17319304Speter	(void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
17419304Speter
17519304Speter	F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
17619304Speter	return (rval);
17719304Speter}
17819304Speter
17919304Speter/*
18019304Speter * cl_vi_init --
18119304Speter *	Initialize the curses vi screen.
18219304Speter */
18319304Speterstatic int
18419304Spetercl_vi_init(sp)
18519304Speter	SCR *sp;
18619304Speter{
18719304Speter	CL_PRIVATE *clp;
18819304Speter	GS *gp;
18919304Speter	char *o_cols, *o_lines, *o_term, *ttype;
19019304Speter
19119304Speter	gp = sp->gp;
19219304Speter	clp = CLP(sp);
19319304Speter
19419304Speter	/* If already initialized, just set the terminal modes. */
19519304Speter	if (F_ISSET(clp, CL_SCR_VI_INIT))
19619304Speter		goto fast;
19719304Speter
19819304Speter	/* Curses vi always reads from (and writes to) a terminal. */
19919304Speter	if (!F_ISSET(clp, CL_STDIN_TTY) || !isatty(STDOUT_FILENO)) {
20019304Speter		msgq(sp, M_ERR,
20119304Speter		    "016|Vi's standard input and output must be a terminal");
20219304Speter		return (1);
20319304Speter	}
20419304Speter
20519304Speter	/* We'll need a terminal type. */
20619304Speter	if (opts_empty(sp, O_TERM, 0))
20719304Speter		return (1);
20819304Speter	ttype = O_STR(sp, O_TERM);
20919304Speter
21019304Speter	/*
21119304Speter	 * XXX
21219304Speter	 * Changing the row/column and terminal values is done by putting them
21319304Speter	 * into the environment, which is then read by curses.  What this loses
21419304Speter	 * in ugliness, it makes up for in stupidity.  We can't simply put the
21519304Speter	 * values into the environment ourselves, because in the presence of a
21619304Speter	 * kernel mechanism for returning the window size, entering values into
21719304Speter	 * the environment will screw up future screen resizing events, e.g. if
21819304Speter	 * the user enters a :shell command and then resizes their window.  So,
21919304Speter	 * if they weren't already in the environment, we make sure to delete
22019304Speter	 * them immediately after setting them.
22119304Speter	 *
22219304Speter	 * XXX
22319304Speter	 * Putting the TERM variable into the environment is necessary, even
22419304Speter	 * though we're using newterm() here.  We may be using initscr() as
22519304Speter	 * the underlying function.
22619304Speter	 */
22719304Speter	o_term = getenv("TERM");
22819304Speter	cl_putenv("TERM", ttype, 0);
22919304Speter	o_lines = getenv("LINES");
23019304Speter	cl_putenv("LINES", NULL, (u_long)O_VAL(sp, O_LINES));
23119304Speter	o_cols = getenv("COLUMNS");
23219304Speter	cl_putenv("COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));
23319304Speter
23419304Speter	/*
23519304Speter	 * We don't care about the SCREEN reference returned by newterm, we
23619304Speter	 * never have more than one SCREEN at a time.
23719304Speter	 *
23819304Speter	 * XXX
23919304Speter	 * The SunOS initscr() can't be called twice.  Don't even think about
24019304Speter	 * using it.  It fails in subtle ways (e.g. select(2) on fileno(stdin)
24119304Speter	 * stops working).  (The SVID notes that applications should only call
24219304Speter	 * initscr() once.)
24319304Speter	 *
24419304Speter	 * XXX
24519304Speter	 * The HP/UX newterm doesn't support the NULL first argument, so we
24619304Speter	 * have to specify the terminal type.
24719304Speter	 */
24819304Speter	errno = 0;
24919304Speter	if (newterm(ttype, stdout, stdin) == NULL) {
25019304Speter		if (errno)
25119304Speter			msgq(sp, M_SYSERR, "%s", ttype);
25219304Speter		else
25319304Speter			msgq(sp, M_ERR, "%s: unknown terminal type", ttype);
25419304Speter		return (1);
25519304Speter	}
25619304Speter
25719304Speter	if (o_term == NULL)
25819304Speter		unsetenv("TERM");
25919304Speter	if (o_lines == NULL)
26019304Speter		unsetenv("LINES");
26119304Speter	if (o_cols == NULL)
26219304Speter		unsetenv("COLUMNS");
26319304Speter
26419304Speter	/*
26519304Speter	 * XXX
26619304Speter	 * Someone got let out alone without adult supervision -- the SunOS
26719304Speter	 * newterm resets the signal handlers.  There's a race, but it's not
26819304Speter	 * worth closing.
26919304Speter	 */
27019304Speter	(void)sig_init(sp->gp, sp);
27119304Speter
27219304Speter	/*
27319304Speter	 * We use raw mode.  What we want is 8-bit clean, however, signals
27419304Speter	 * and flow control should continue to work.  Admittedly, it sounds
27519304Speter	 * like cbreak, but it isn't.  Using cbreak() can get you additional
27619304Speter	 * things like IEXTEN, which turns on flags like DISCARD and LNEXT.
27719304Speter	 *
27819304Speter	 * !!!
27919304Speter	 * If raw isn't turning off echo and newlines, something's wrong.
28019304Speter	 * However, it shouldn't hurt.
28119304Speter	 */
28219304Speter	noecho();			/* No character echo. */
28319304Speter	nonl();				/* No CR/NL translation. */
28419304Speter	raw();				/* 8-bit clean. */
28519304Speter	idlok(stdscr, 1);		/* Use hardware insert/delete line. */
28619304Speter
28719304Speter	/* Put the cursor keys into application mode. */
28819304Speter	(void)keypad(stdscr, TRUE);
28919304Speter
29019304Speter	/*
29119304Speter	 * XXX
29219304Speter	 * The screen TI sequence just got sent.  See the comment in
29319304Speter	 * cl_funcs.c:cl_attr().
29419304Speter	 */
29519304Speter	clp->ti_te = TI_SENT;
29619304Speter
29719304Speter	/*
29819304Speter	 * XXX
29919304Speter	 * Historic implementations of curses handled SIGTSTP signals
30019304Speter	 * in one of three ways.  They either:
30119304Speter	 *
30219304Speter	 *	1: Set their own handler, regardless.
30319304Speter	 *	2: Did not set a handler if a handler was already installed.
30419304Speter	 *	3: Set their own handler, but then called any previously set
30519304Speter	 *	   handler after completing their own cleanup.
30619304Speter	 *
30719304Speter	 * We don't try and figure out which behavior is in place, we force
30819304Speter	 * it to SIG_DFL after initializing the curses interface, which means
30919304Speter	 * that curses isn't going to take the signal.  Since curses isn't
31019304Speter	 * reentrant (i.e., the whole curses SIGTSTP interface is a fantasy),
31119304Speter	 * we're doing The Right Thing.
31219304Speter	 */
31319304Speter	(void)signal(SIGTSTP, SIG_DFL);
31419304Speter
31519304Speter	/*
31619304Speter	 * If flow control was on, turn it back on.  Turn signals on.  ISIG
31719304Speter	 * turns on VINTR, VQUIT, VDSUSP and VSUSP.   The main curses code
31819304Speter	 * already installed a handler for VINTR.  We're going to disable the
31919304Speter	 * other three.
32019304Speter	 *
32119304Speter	 * XXX
32219304Speter	 * We want to use ^Y as a vi scrolling command.  If the user has the
32319304Speter	 * DSUSP character set to ^Y (common practice) clean it up.  As it's
32419304Speter	 * equally possible that the user has VDSUSP set to 'a', we disable
32519304Speter	 * it regardless.  It doesn't make much sense to suspend vi at read,
32619304Speter	 * so I don't think anyone will care.  Alternatively, we could look
32719304Speter	 * it up in the table of legal command characters and turn it off if
32819304Speter	 * it matches one.  VDSUSP wasn't in POSIX 1003.1-1990, so we test for
32919304Speter	 * it.
33019304Speter	 *
33119304Speter	 * XXX
33219304Speter	 * We don't check to see if the user had signals enabled originally.
33319304Speter	 * If they didn't, it's unclear what we're supposed to do here, but
33419304Speter	 * it's also pretty unlikely.
33519304Speter	 */
33619304Speter	if (tcgetattr(STDIN_FILENO, &clp->vi_enter)) {
33719304Speter		msgq(sp, M_SYSERR, "tcgetattr");
33819304Speter		goto err;
33919304Speter	}
34019304Speter	if (clp->orig.c_iflag & IXON)
34119304Speter		clp->vi_enter.c_iflag |= IXON;
34219304Speter	if (clp->orig.c_iflag & IXOFF)
34319304Speter		clp->vi_enter.c_iflag |= IXOFF;
34419304Speter
34519304Speter	clp->vi_enter.c_lflag |= ISIG;
34619304Speter#ifdef VDSUSP
34719304Speter	clp->vi_enter.c_cc[VDSUSP] = _POSIX_VDISABLE;
34819304Speter#endif
34919304Speter	clp->vi_enter.c_cc[VQUIT] = _POSIX_VDISABLE;
35019304Speter	clp->vi_enter.c_cc[VSUSP] = _POSIX_VDISABLE;
35119304Speter
35219304Speter	/*
35319304Speter	 * XXX
35419304Speter	 * OSF/1 doesn't turn off the <discard>, <literal-next> or <status>
35519304Speter	 * characters when curses switches into raw mode.  It should be OK
35619304Speter	 * to do it explicitly for everyone.
35719304Speter	 */
35819304Speter#ifdef VDISCARD
35919304Speter	clp->vi_enter.c_cc[VDISCARD] = _POSIX_VDISABLE;
36019304Speter#endif
36119304Speter#ifdef VLNEXT
36219304Speter	clp->vi_enter.c_cc[VLNEXT] = _POSIX_VDISABLE;
36319304Speter#endif
36419304Speter#ifdef VSTATUS
36519304Speter	clp->vi_enter.c_cc[VSTATUS] = _POSIX_VDISABLE;
36619304Speter#endif
36719304Speter
36819304Speter	/* Initialize terminal based information. */
36919304Speter	if (cl_term_init(sp))
37019304Speter		goto err;
37119304Speter
37219304Speterfast:	/* Set the terminal modes. */
37319304Speter	if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
37486201Srwatson		if (errno == EINTR)
37586201Srwatson			goto fast;
37619304Speter		msgq(sp, M_SYSERR, "tcsetattr");
37719304Spetererr:		(void)cl_vi_end(sp->gp);
37819304Speter		return (1);
37919304Speter	}
38019304Speter	return (0);
38119304Speter}
38219304Speter
38319304Speter/*
38419304Speter * cl_vi_end --
38519304Speter *	Shutdown the vi screen.
38619304Speter */
38719304Speterstatic int
38819304Spetercl_vi_end(gp)
38919304Speter	GS *gp;
39019304Speter{
39119304Speter	CL_PRIVATE *clp;
39219304Speter
39319304Speter	clp = GCLP(gp);
39419304Speter
39519304Speter	/* Restore the cursor keys to normal mode. */
39619304Speter	(void)keypad(stdscr, FALSE);
39719304Speter
39819304Speter	/*
39919304Speter	 * If we were running vi when we quit, scroll the screen up a single
40019304Speter	 * line so we don't lose any information.
40119304Speter	 *
40219304Speter	 * Move to the bottom of the window (some endwin implementations don't
40319304Speter	 * do this for you).
40419304Speter	 */
40519304Speter	if (!F_ISSET(clp, CL_IN_EX)) {
40619304Speter		(void)move(0, 0);
40719304Speter		(void)deleteln();
40819304Speter		(void)move(LINES - 1, 0);
40919304Speter		(void)refresh();
41019304Speter	}
41119304Speter
41219304Speter	cl_freecap(clp);
41319304Speter
41419304Speter	/* End curses window. */
41519304Speter	(void)endwin();
41619304Speter
41719304Speter	/*
41819304Speter	 * XXX
41919304Speter	 * The screen TE sequence just got sent.  See the comment in
42019304Speter	 * cl_funcs.c:cl_attr().
42119304Speter	 */
42219304Speter	clp->ti_te = TE_SENT;
42319304Speter
42419304Speter	return (0);
42519304Speter}
42619304Speter
42719304Speter/*
42819304Speter * cl_ex_init --
42919304Speter *	Initialize the ex screen.
43019304Speter */
43119304Speterstatic int
43219304Spetercl_ex_init(sp)
43319304Speter	SCR *sp;
43419304Speter{
43519304Speter	CL_PRIVATE *clp;
43619304Speter
43719304Speter	clp = CLP(sp);
43819304Speter
43919304Speter	/* If already initialized, just set the terminal modes. */
44019304Speter	if (F_ISSET(clp, CL_SCR_EX_INIT))
44119304Speter		goto fast;
44219304Speter
44319304Speter	/* If not reading from a file, we're done. */
44419304Speter	if (!F_ISSET(clp, CL_STDIN_TTY))
44519304Speter		return (0);
44619304Speter
44719304Speter	/* Get the ex termcap/terminfo strings. */
44819304Speter	(void)cl_getcap(sp, "cup", &clp->cup);
44919304Speter	(void)cl_getcap(sp, "smso", &clp->smso);
45019304Speter	(void)cl_getcap(sp, "rmso", &clp->rmso);
45119304Speter	(void)cl_getcap(sp, "el", &clp->el);
45219304Speter	(void)cl_getcap(sp, "cuu1", &clp->cuu1);
45319304Speter
45419304Speter	/* Enter_standout_mode and exit_standout_mode are paired. */
45519304Speter	if (clp->smso == NULL || clp->rmso == NULL) {
45619304Speter		if (clp->smso != NULL) {
45719304Speter			free(clp->smso);
45819304Speter			clp->smso = NULL;
45919304Speter		}
46019304Speter		if (clp->rmso != NULL) {
46119304Speter			free(clp->rmso);
46219304Speter			clp->rmso = NULL;
46319304Speter		}
46419304Speter	}
46519304Speter
46619304Speter	/*
46719304Speter	 * Turn on canonical mode, with normal input and output processing.
46819304Speter	 * Start with the original terminal settings as the user probably
46919304Speter	 * had them (including any local extensions) set correctly for the
47019304Speter	 * current terminal.
47119304Speter	 *
47219304Speter	 * !!!
47319304Speter	 * We can't get everything that we need portably; for example, ONLCR,
47419304Speter	 * mapping <newline> to <carriage-return> on output isn't required
47519304Speter	 * by POSIX 1003.1b-1993.  If this turns out to be a problem, then
47619304Speter	 * we'll either have to play some games on the mapping, or we'll have
47719304Speter	 * to make all ex printf's output \r\n instead of \n.
47819304Speter	 */
47919304Speter	clp->ex_enter = clp->orig;
48019304Speter	clp->ex_enter.c_lflag  |= ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
48119304Speter#ifdef ECHOCTL
48219304Speter	clp->ex_enter.c_lflag |= ECHOCTL;
48319304Speter#endif
48419304Speter#ifdef ECHOKE
48519304Speter	clp->ex_enter.c_lflag |= ECHOKE;
48619304Speter#endif
48719304Speter	clp->ex_enter.c_iflag |= ICRNL;
48819304Speter	clp->ex_enter.c_oflag |= OPOST;
48919304Speter#ifdef ONLCR
49019304Speter	clp->ex_enter.c_oflag |= ONLCR;
49119304Speter#endif
49219304Speter
49319304Speterfast:	if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) {
49486201Srwatson		if (errno == EINTR)
49586201Srwatson			goto fast;
49619304Speter		msgq(sp, M_SYSERR, "tcsetattr");
49719304Speter		return (1);
49819304Speter	}
49919304Speter	return (0);
50019304Speter}
50119304Speter
50219304Speter/*
50319304Speter * cl_ex_end --
50419304Speter *	Shutdown the ex screen.
50519304Speter */
50619304Speterstatic int
50719304Spetercl_ex_end(gp)
50819304Speter	GS *gp;
50919304Speter{
51019304Speter	CL_PRIVATE *clp;
51119304Speter
51219304Speter	clp = GCLP(gp);
51319304Speter
51419304Speter	cl_freecap(clp);
51519304Speter
51619304Speter	return (0);
51719304Speter}
51819304Speter
51919304Speter/*
52019304Speter * cl_getcap --
52119304Speter *	Retrieve termcap/terminfo strings.
52219304Speter *
52319304Speter * PUBLIC: int cl_getcap __P((SCR *, char *, char **));
52419304Speter */
52519304Speterint
52619304Spetercl_getcap(sp, name, elementp)
52719304Speter	SCR *sp;
52819304Speter	char *name, **elementp;
52919304Speter{
53019304Speter	size_t len;
53119304Speter	char *t;
53219304Speter
53319304Speter	if ((t = tigetstr(name)) != NULL &&
53419304Speter	    t != (char *)-1 && (len = strlen(t)) != 0) {
53519304Speter		MALLOC_RET(sp, *elementp, char *, len + 1);
53619304Speter		memmove(*elementp, t, len + 1);
53719304Speter	}
53819304Speter	return (0);
53919304Speter}
54019304Speter
54119304Speter/*
54219304Speter * cl_freecap --
54319304Speter *	Free any allocated termcap/terminfo strings.
54419304Speter */
54519304Speterstatic void
54619304Spetercl_freecap(clp)
54719304Speter	CL_PRIVATE *clp;
54819304Speter{
54919304Speter	if (clp->el != NULL) {
55019304Speter		free(clp->el);
55119304Speter		clp->el = NULL;
55219304Speter	}
55319304Speter	if (clp->cup != NULL) {
55419304Speter		free(clp->cup);
55519304Speter		clp->cup = NULL;
55619304Speter	}
55719304Speter	if (clp->cuu1 != NULL) {
55819304Speter		free(clp->cuu1);
55919304Speter		clp->cuu1 = NULL;
56019304Speter	}
56119304Speter	if (clp->rmso != NULL) {
56219304Speter		free(clp->rmso);
56319304Speter		clp->rmso = NULL;
56419304Speter	}
56519304Speter	if (clp->smso != NULL) {
56619304Speter		free(clp->smso);
56719304Speter		clp->smso = NULL;
56819304Speter	}
56919304Speter}
57019304Speter
57119304Speter/*
57219304Speter * cl_putenv --
57319304Speter *	Put a value into the environment.
57419304Speter */
57519304Speterstatic int
57619304Spetercl_putenv(name, str, value)
57719304Speter	char *name, *str;
57819304Speter	u_long value;
57919304Speter
58019304Speter{
58119304Speter	char buf[40];
58219304Speter
58319304Speter	if (str == NULL) {
58419304Speter		(void)snprintf(buf, sizeof(buf), "%lu", value);
58519304Speter		return (setenv(name, buf, 1));
58619304Speter	} else
58719304Speter		return (setenv(name, str, 1));
58819304Speter}
589