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