setupterm.c revision 1.7
1/* $NetBSD: setupterm.c,v 1.7 2017/03/23 00:55:39 roy Exp $ */ 2 3/* 4 * Copyright (c) 2009, 2011 The NetBSD Foundation, Inc. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Roy Marples. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__RCSID("$NetBSD: setupterm.c,v 1.7 2017/03/23 00:55:39 roy Exp $"); 32 33#include <sys/ioctl.h> 34#include <assert.h> 35#include <err.h> 36#include <stdbool.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <strings.h> 40#include <unistd.h> 41#include <term_private.h> 42#include <term.h> 43 44/* 45 * use_env is really a curses function - POSIX mandates it's in curses.h 46 * But it has to live in terminfo because it must precede a call to setupterm(). 47 */ 48#include <curses.h> 49 50static bool __use_env = true; 51 52void 53use_env(bool value) 54{ 55 56 __use_env = value; 57} 58#define reterr(code, msg) \ 59 do { \ 60 if (errret == NULL) \ 61 errx(EXIT_FAILURE, msg); \ 62 else { \ 63 *errret = code; \ 64 return ERR; \ 65 } \ 66 } while (0 /* CONSTCOND */) 67 68#define reterrarg(code, msg, arg) \ 69 do { \ 70 if (errret == NULL) \ 71 errx(EXIT_FAILURE, msg, arg); \ 72 else { \ 73 *errret = code; \ 74 return ERR; \ 75 } \ 76 } while (0 /* CONSTCOND */) 77 78 79int 80ti_setupterm(TERMINAL **nterm, const char *term, int fildes, int *errret) 81{ 82 int error; 83 struct winsize win; 84 85 _DIAGASSERT(nterm != NULL); 86 87 if (term == NULL) 88 term = getenv("TERM"); 89 if (term == NULL || *term == '\0') { 90 *nterm = NULL; 91 reterr(0, "TERM environment variable not set"); 92 } 93 if (fildes == STDOUT_FILENO && !isatty(fildes)) 94 fildes = STDERR_FILENO; 95 96 *nterm = calloc(1, sizeof(**nterm)); 97 if (*nterm == NULL) 98 reterr(-1, "not enough memory to create terminal structure"); 99 100 error = _ti_getterm(*nterm, term, 0); 101 if (error != 1) { 102 del_curterm(*nterm); 103 *nterm = NULL; 104 switch (error) { 105 case -1: 106 reterr(error, "cannot access the terminfo database"); 107 /* NOTREACHED */ 108 case 0: 109 reterrarg(error, 110 "%s: terminal not listed in terminfo datase", 111 term); 112 /* NOTREACHED */ 113 default: 114 reterr(-1, "unknown error"); 115 /* NOTREACHED */ 116 } 117 } 118 119 (*nterm)->fildes = fildes; 120 _ti_setospeed(*nterm); 121 if (t_generic_type(*nterm)) 122 reterrarg(0, "%s: generic terminal", term); 123 if (t_hard_copy(*nterm)) 124 reterrarg(1, "%s: hardcopy terminal", term); 125 126 /* If TIOCGWINSZ works, then set initial lines and columns. */ 127 if (ioctl(fildes, TIOCGWINSZ, &win) != -1 && 128 win.ws_row != 0 && win.ws_col != 0) 129 { 130 t_lines(*nterm) = win.ws_row; 131 t_columns(*nterm) = win.ws_col; 132 } 133 134 /* POSIX 1003.2 requires that the environment override. */ 135 if (__use_env) { 136 char *p; 137 138 if ((p = getenv("LINES")) != NULL) 139 t_lines(*nterm) = (int)strtol(p, NULL, 0); 140 if ((p = getenv("COLUMNS")) != NULL) 141 t_columns(*nterm) = (int)strtol(p, NULL, 0); 142 } 143 144 /* POSIX requires 1 for success */ 145 if (errret) 146 *errret = 1; 147 return OK; 148} 149 150int 151setupterm(const char *term, int fildes, int *errret) 152{ 153 TERMINAL *nterm; 154 int ret; 155 156 if (errret != NULL) 157 *errret = ERR; 158 ret = ti_setupterm(&nterm, term, fildes, errret); 159 if (nterm != NULL) 160 set_curterm(nterm); 161 return ret; 162} 163