10e3d5408SPeter Wemm /**************************************************************************** 2*aae38d10SBaptiste Daroussin * Copyright (c) 1998-2018,2019 Free Software Foundation, Inc. * 30e3d5408SPeter Wemm * * 40e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 50e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 60e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 70e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 80e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 90e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 100e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 110e3d5408SPeter Wemm * * 120e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 130e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 140e3d5408SPeter Wemm * * 150e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 160e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 170e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 180e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 190e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 200e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 210e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 220e3d5408SPeter Wemm * * 230e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 240e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 250e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 260e3d5408SPeter Wemm * authorization. * 270e3d5408SPeter Wemm ****************************************************************************/ 280e3d5408SPeter Wemm 290e3d5408SPeter Wemm /**************************************************************************** 300e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 310e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32*aae38d10SBaptiste Daroussin * and: Thomas E. Dickey 1996-on * 330e3d5408SPeter Wemm ****************************************************************************/ 340e3d5408SPeter Wemm 350e3d5408SPeter Wemm /* 360e3d5408SPeter Wemm * tput.c -- shellscript access to terminal capabilities 370e3d5408SPeter Wemm * 380e3d5408SPeter Wemm * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from 390e3d5408SPeter Wemm * Ross Ridge's mytinfo package. 400e3d5408SPeter Wemm */ 410e3d5408SPeter Wemm 42*aae38d10SBaptiste Daroussin #include <tparm_type.h> 43*aae38d10SBaptiste Daroussin #include <clear_cmd.h> 44*aae38d10SBaptiste Daroussin #include <reset_cmd.h> 4518259542SPeter Wemm 4618259542SPeter Wemm #if !PURE_TERMINFO 475d08fb1fSRong-En Fan #include <dump_entry.h> 480e3d5408SPeter Wemm #include <termsort.c> 490e3d5408SPeter Wemm #endif 5018259542SPeter Wemm #include <transform.h> 51*aae38d10SBaptiste Daroussin #include <tty_settings.h> 520e3d5408SPeter Wemm 53*aae38d10SBaptiste Daroussin MODULE_ID("$Id: tput.c,v 1.80 2019/07/28 18:18:41 tom Exp $") 540e3d5408SPeter Wemm 550e3d5408SPeter Wemm #define PUTS(s) fputs(s, stdout) 560e3d5408SPeter Wemm 57*aae38d10SBaptiste Daroussin const char *_nc_progname = "tput"; 5818259542SPeter Wemm 590e3d5408SPeter Wemm static char *prg_name; 6018259542SPeter Wemm static bool is_init = FALSE; 6118259542SPeter Wemm static bool is_reset = FALSE; 62*aae38d10SBaptiste Daroussin static bool is_clear = FALSE; 630e3d5408SPeter Wemm 6415589c42SPeter Wemm static void 6515589c42SPeter Wemm quit(int status, const char *fmt,...) 660e3d5408SPeter Wemm { 670e3d5408SPeter Wemm va_list argp; 680e3d5408SPeter Wemm 690e3d5408SPeter Wemm va_start(argp, fmt); 704a1a9510SRong-En Fan fprintf(stderr, "%s: ", prg_name); 710e3d5408SPeter Wemm vfprintf(stderr, fmt, argp); 720e3d5408SPeter Wemm fprintf(stderr, "\n"); 730e3d5408SPeter Wemm va_end(argp); 744a1a9510SRong-En Fan ExitProgram(status); 750e3d5408SPeter Wemm } 760e3d5408SPeter Wemm 7715589c42SPeter Wemm static void 7815589c42SPeter Wemm usage(void) 790e3d5408SPeter Wemm { 80*aae38d10SBaptiste Daroussin #define KEEP(s) s "\n" 81*aae38d10SBaptiste Daroussin static const char msg[] = 8218259542SPeter Wemm { 83*aae38d10SBaptiste Daroussin KEEP("") 84*aae38d10SBaptiste Daroussin KEEP("Options:") 85*aae38d10SBaptiste Daroussin KEEP(" -S << read commands from standard input") 86*aae38d10SBaptiste Daroussin KEEP(" -T TERM use this instead of $TERM") 87*aae38d10SBaptiste Daroussin KEEP(" -V print curses-version") 88*aae38d10SBaptiste Daroussin KEEP(" -x do not try to clear scrollback") 89*aae38d10SBaptiste Daroussin KEEP("") 90*aae38d10SBaptiste Daroussin KEEP("Commands:") 91*aae38d10SBaptiste Daroussin KEEP(" clear clear the screen") 92*aae38d10SBaptiste Daroussin KEEP(" init initialize the terminal") 93*aae38d10SBaptiste Daroussin KEEP(" reset reinitialize the terminal") 94*aae38d10SBaptiste Daroussin KEEP(" capname unlike clear/init/reset, print value for capability \"capname\"") 9518259542SPeter Wemm }; 96*aae38d10SBaptiste Daroussin #undef KEEP 97*aae38d10SBaptiste Daroussin (void) fprintf(stderr, "Usage: %s [options] [command]\n", prg_name); 98*aae38d10SBaptiste Daroussin fputs(msg, stderr); 99*aae38d10SBaptiste Daroussin ExitProgram(ErrUsage); 100*aae38d10SBaptiste Daroussin } 10118259542SPeter Wemm 102*aae38d10SBaptiste Daroussin static char * 103*aae38d10SBaptiste Daroussin check_aliases(char *name, bool program) 104*aae38d10SBaptiste Daroussin { 105*aae38d10SBaptiste Daroussin static char my_init[] = "init"; 106*aae38d10SBaptiste Daroussin static char my_reset[] = "reset"; 107*aae38d10SBaptiste Daroussin static char my_clear[] = "clear"; 108*aae38d10SBaptiste Daroussin 109*aae38d10SBaptiste Daroussin char *result = name; 110*aae38d10SBaptiste Daroussin if ((is_init = same_program(name, program ? PROG_INIT : my_init))) 111*aae38d10SBaptiste Daroussin result = my_init; 112*aae38d10SBaptiste Daroussin if ((is_reset = same_program(name, program ? PROG_RESET : my_reset))) 113*aae38d10SBaptiste Daroussin result = my_reset; 114*aae38d10SBaptiste Daroussin if ((is_clear = same_program(name, program ? PROG_CLEAR : my_clear))) 115*aae38d10SBaptiste Daroussin result = my_clear; 11618259542SPeter Wemm return result; 11718259542SPeter Wemm } 11818259542SPeter Wemm 11915589c42SPeter Wemm static int 1204a1a9510SRong-En Fan exit_code(int token, int value) 1214a1a9510SRong-En Fan { 1224a1a9510SRong-En Fan int result = 99; 1234a1a9510SRong-En Fan 1244a1a9510SRong-En Fan switch (token) { 1254a1a9510SRong-En Fan case BOOLEAN: 1264a1a9510SRong-En Fan result = !value; /* TRUE=0, FALSE=1 */ 1274a1a9510SRong-En Fan break; 1284a1a9510SRong-En Fan case NUMBER: 1294a1a9510SRong-En Fan result = 0; /* always zero */ 1304a1a9510SRong-En Fan break; 1314a1a9510SRong-En Fan case STRING: 1324a1a9510SRong-En Fan result = value; /* 0=normal, 1=missing */ 1334a1a9510SRong-En Fan break; 1344a1a9510SRong-En Fan } 1354a1a9510SRong-En Fan return result; 1364a1a9510SRong-En Fan } 1374a1a9510SRong-En Fan 138*aae38d10SBaptiste Daroussin /* 139*aae38d10SBaptiste Daroussin * Returns nonzero on error. 140*aae38d10SBaptiste Daroussin */ 1414a1a9510SRong-En Fan static int 142*aae38d10SBaptiste Daroussin tput_cmd(int fd, TTY * saved_settings, bool opt_x, int argc, char *argv[]) 1430e3d5408SPeter Wemm { 14415589c42SPeter Wemm NCURSES_CONST char *name; 1450e3d5408SPeter Wemm char *s; 14618259542SPeter Wemm int status; 14706bfebdeSXin LI #if !PURE_TERMINFO 14806bfebdeSXin LI bool termcap = FALSE; 14906bfebdeSXin LI #endif 1500e3d5408SPeter Wemm 151*aae38d10SBaptiste Daroussin name = check_aliases(argv[0], FALSE); 15218259542SPeter Wemm if (is_reset || is_init) { 153*aae38d10SBaptiste Daroussin TTY oldmode; 1540e3d5408SPeter Wemm 155*aae38d10SBaptiste Daroussin int terasechar = -1; /* new erase character */ 156*aae38d10SBaptiste Daroussin int intrchar = -1; /* new interrupt character */ 157*aae38d10SBaptiste Daroussin int tkillchar = -1; /* new kill character */ 1580e3d5408SPeter Wemm 159*aae38d10SBaptiste Daroussin if (is_reset) { 160*aae38d10SBaptiste Daroussin reset_start(stdout, TRUE, FALSE); 161*aae38d10SBaptiste Daroussin reset_tty_settings(fd, saved_settings); 162*aae38d10SBaptiste Daroussin } else { 163*aae38d10SBaptiste Daroussin reset_start(stdout, FALSE, TRUE); 1640e3d5408SPeter Wemm } 1650e3d5408SPeter Wemm 166*aae38d10SBaptiste Daroussin #if HAVE_SIZECHANGE 167*aae38d10SBaptiste Daroussin set_window_size(fd, &lines, &columns); 168*aae38d10SBaptiste Daroussin #else 169*aae38d10SBaptiste Daroussin (void) fd; 17039f2269fSPeter Wemm #endif 171*aae38d10SBaptiste Daroussin set_control_chars(saved_settings, terasechar, intrchar, tkillchar); 172*aae38d10SBaptiste Daroussin set_conversions(saved_settings); 173*aae38d10SBaptiste Daroussin if (send_init_strings(fd, &oldmode)) { 174*aae38d10SBaptiste Daroussin reset_flush(); 1750e3d5408SPeter Wemm } 1760e3d5408SPeter Wemm 177*aae38d10SBaptiste Daroussin update_tty_settings(&oldmode, saved_settings); 1780e3d5408SPeter Wemm return 0; 1790e3d5408SPeter Wemm } 1800e3d5408SPeter Wemm 1810e3d5408SPeter Wemm if (strcmp(name, "longname") == 0) { 1820e3d5408SPeter Wemm PUTS(longname()); 1830e3d5408SPeter Wemm return 0; 1840e3d5408SPeter Wemm } 18518259542SPeter Wemm #if !PURE_TERMINFO 18606bfebdeSXin LI retry: 18706bfebdeSXin LI #endif 188*aae38d10SBaptiste Daroussin if (strcmp(name, "clear") == 0) { 189*aae38d10SBaptiste Daroussin return (clear_cmd(opt_x) == ERR) ? ErrUsage : 0; 190*aae38d10SBaptiste Daroussin } else if ((status = tigetflag(name)) != -1) { 19106bfebdeSXin LI return exit_code(BOOLEAN, status); 19206bfebdeSXin LI } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 19306bfebdeSXin LI (void) printf("%d\n", status); 19406bfebdeSXin LI return exit_code(NUMBER, 0); 19506bfebdeSXin LI } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 19606bfebdeSXin LI #if !PURE_TERMINFO 19706bfebdeSXin LI if (!termcap) { 1980e3d5408SPeter Wemm const struct name_table_entry *np; 1990e3d5408SPeter Wemm 20006bfebdeSXin LI termcap = TRUE; 20106bfebdeSXin LI if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) { 20215589c42SPeter Wemm switch (np->nte_type) { 2030e3d5408SPeter Wemm case BOOLEAN: 2040e3d5408SPeter Wemm name = boolnames[np->nte_index]; 2050e3d5408SPeter Wemm break; 2060e3d5408SPeter Wemm 2070e3d5408SPeter Wemm case NUMBER: 2080e3d5408SPeter Wemm name = numnames[np->nte_index]; 2090e3d5408SPeter Wemm break; 2100e3d5408SPeter Wemm 2110e3d5408SPeter Wemm case STRING: 2120e3d5408SPeter Wemm name = strnames[np->nte_index]; 2130e3d5408SPeter Wemm break; 2140e3d5408SPeter Wemm } 21506bfebdeSXin LI goto retry; 21606bfebdeSXin LI } 2170e3d5408SPeter Wemm } 2180e3d5408SPeter Wemm #endif 219*aae38d10SBaptiste Daroussin quit(ErrCapName, "unknown terminfo capability '%s'", name); 220*aae38d10SBaptiste Daroussin } else if (VALID_STRING(s)) { 2210e3d5408SPeter Wemm if (argc > 1) { 2220e3d5408SPeter Wemm int k; 22373f0a83dSXin LI int ignored; 2244a1a9510SRong-En Fan long numbers[1 + NUM_PARM]; 2254a1a9510SRong-En Fan char *strings[1 + NUM_PARM]; 2264a1a9510SRong-En Fan char *p_is_s[NUM_PARM]; 2270e3d5408SPeter Wemm 2280e3d5408SPeter Wemm /* Nasty hack time. The tparm function needs to see numeric 2290e3d5408SPeter Wemm * parameters as numbers, not as pointers to their string 2300e3d5408SPeter Wemm * representations 2310e3d5408SPeter Wemm */ 2320e3d5408SPeter Wemm 233*aae38d10SBaptiste Daroussin for (k = 1; (k < argc) && (k < NUM_PARM); k++) { 23418259542SPeter Wemm char *tmp = 0; 23518259542SPeter Wemm strings[k] = argv[k]; 23618259542SPeter Wemm numbers[k] = strtol(argv[k], &tmp, 0); 23718259542SPeter Wemm if (tmp == 0 || *tmp != 0) 23818259542SPeter Wemm numbers[k] = 0; 2390e3d5408SPeter Wemm } 2404a1a9510SRong-En Fan for (k = argc; k <= NUM_PARM; k++) { 24118259542SPeter Wemm numbers[k] = 0; 24218259542SPeter Wemm strings[k] = 0; 24315589c42SPeter Wemm } 2440e3d5408SPeter Wemm 24518259542SPeter Wemm switch (tparm_type(name)) { 24618259542SPeter Wemm case Num_Str: 2474a1a9510SRong-En Fan s = TPARM_2(s, numbers[1], strings[2]); 24818259542SPeter Wemm break; 24918259542SPeter Wemm case Num_Str_Str: 2504a1a9510SRong-En Fan s = TPARM_3(s, numbers[1], strings[2], strings[3]); 25118259542SPeter Wemm break; 2525ca44d1cSRong-En Fan case Numbers: 25318259542SPeter Wemm default: 25473f0a83dSXin LI (void) _nc_tparm_analyze(s, p_is_s, &ignored); 25573f0a83dSXin LI #define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n]) 2564a1a9510SRong-En Fan s = TPARM_9(s, 2574a1a9510SRong-En Fan myParam(1), 2584a1a9510SRong-En Fan myParam(2), 2594a1a9510SRong-En Fan myParam(3), 2604a1a9510SRong-En Fan myParam(4), 2614a1a9510SRong-En Fan myParam(5), 2624a1a9510SRong-En Fan myParam(6), 2634a1a9510SRong-En Fan myParam(7), 2644a1a9510SRong-En Fan myParam(8), 2654a1a9510SRong-En Fan myParam(9)); 26618259542SPeter Wemm break; 26718259542SPeter Wemm } 2680e3d5408SPeter Wemm } 2690e3d5408SPeter Wemm 2700e3d5408SPeter Wemm /* use putp() in order to perform padding */ 2710e3d5408SPeter Wemm putp(s); 2724a1a9510SRong-En Fan return exit_code(STRING, 0); 2730e3d5408SPeter Wemm } 2744a1a9510SRong-En Fan return exit_code(STRING, 1); 2750e3d5408SPeter Wemm } 2760e3d5408SPeter Wemm 27715589c42SPeter Wemm int 27815589c42SPeter Wemm main(int argc, char **argv) 2790e3d5408SPeter Wemm { 28018259542SPeter Wemm char *term; 28118259542SPeter Wemm int errret; 28218259542SPeter Wemm bool cmdline = TRUE; 2830e3d5408SPeter Wemm int c; 2840e3d5408SPeter Wemm char buf[BUFSIZ]; 2854a1a9510SRong-En Fan int result = 0; 286*aae38d10SBaptiste Daroussin int fd; 287*aae38d10SBaptiste Daroussin TTY tty_settings; 288*aae38d10SBaptiste Daroussin bool opt_x = FALSE; /* clear scrollback if possible */ 289*aae38d10SBaptiste Daroussin bool is_alias; 290*aae38d10SBaptiste Daroussin bool need_tty; 2910e3d5408SPeter Wemm 292*aae38d10SBaptiste Daroussin prg_name = check_aliases(_nc_rootname(argv[0]), TRUE); 2930e3d5408SPeter Wemm 2940e3d5408SPeter Wemm term = getenv("TERM"); 2950e3d5408SPeter Wemm 296*aae38d10SBaptiste Daroussin while ((c = getopt(argc, argv, "ST:Vx")) != -1) { 29715589c42SPeter Wemm switch (c) { 2980e3d5408SPeter Wemm case 'S': 29918259542SPeter Wemm cmdline = FALSE; 3000e3d5408SPeter Wemm break; 3010e3d5408SPeter Wemm case 'T': 3020e3d5408SPeter Wemm use_env(FALSE); 303*aae38d10SBaptiste Daroussin use_tioctl(TRUE); 3040e3d5408SPeter Wemm term = optarg; 3050e3d5408SPeter Wemm break; 30618259542SPeter Wemm case 'V': 30718259542SPeter Wemm puts(curses_version()); 3084a1a9510SRong-En Fan ExitProgram(EXIT_SUCCESS); 309*aae38d10SBaptiste Daroussin case 'x': /* do not try to clear scrollback */ 310*aae38d10SBaptiste Daroussin opt_x = TRUE; 311*aae38d10SBaptiste Daroussin break; 3120e3d5408SPeter Wemm default: 3130e3d5408SPeter Wemm usage(); 3140e3d5408SPeter Wemm /* NOTREACHED */ 3150e3d5408SPeter Wemm } 31618259542SPeter Wemm } 31718259542SPeter Wemm 318*aae38d10SBaptiste Daroussin is_alias = (is_clear || is_reset || is_init); 319*aae38d10SBaptiste Daroussin need_tty = ((is_reset || is_init) || 320*aae38d10SBaptiste Daroussin (optind < argc && 321*aae38d10SBaptiste Daroussin (!strcmp(argv[optind], "reset") || 322*aae38d10SBaptiste Daroussin !strcmp(argv[optind], "init")))); 323*aae38d10SBaptiste Daroussin 32418259542SPeter Wemm /* 32518259542SPeter Wemm * Modify the argument list to omit the options we processed. 32618259542SPeter Wemm */ 327*aae38d10SBaptiste Daroussin if (is_alias) { 32818259542SPeter Wemm if (optind-- < argc) { 3290e3d5408SPeter Wemm argc -= optind; 3300e3d5408SPeter Wemm argv += optind; 33118259542SPeter Wemm } 33218259542SPeter Wemm argv[0] = prg_name; 33318259542SPeter Wemm } else { 33418259542SPeter Wemm argc -= optind; 33518259542SPeter Wemm argv += optind; 3360e3d5408SPeter Wemm } 3370e3d5408SPeter Wemm 33815589c42SPeter Wemm if (term == 0 || *term == '\0') 339*aae38d10SBaptiste Daroussin quit(ErrUsage, "No value for $TERM and no -T specified"); 3400e3d5408SPeter Wemm 341*aae38d10SBaptiste Daroussin fd = save_tty_settings(&tty_settings, need_tty); 342*aae38d10SBaptiste Daroussin 343*aae38d10SBaptiste Daroussin if (setupterm(term, fd, &errret) != OK && errret <= 0) 344*aae38d10SBaptiste Daroussin quit(ErrTermType, "unknown terminal \"%s\"", term); 3450e3d5408SPeter Wemm 34618259542SPeter Wemm if (cmdline) { 347*aae38d10SBaptiste Daroussin if ((argc <= 0) && !is_alias) 34818259542SPeter Wemm usage(); 349*aae38d10SBaptiste Daroussin ExitProgram(tput_cmd(fd, &tty_settings, opt_x, argc, argv)); 35018259542SPeter Wemm } 3510e3d5408SPeter Wemm 35215589c42SPeter Wemm while (fgets(buf, sizeof(buf), stdin) != 0) { 3530e3d5408SPeter Wemm char *argvec[16]; /* command, 9 parms, null, & slop */ 3540e3d5408SPeter Wemm int argnum = 0; 3550e3d5408SPeter Wemm char *cp; 3560e3d5408SPeter Wemm 3570e3d5408SPeter Wemm /* crack the argument list into a dope vector */ 3580e3d5408SPeter Wemm for (cp = buf; *cp; cp++) { 35939f2269fSPeter Wemm if (isspace(UChar(*cp))) { 3600e3d5408SPeter Wemm *cp = '\0'; 36139f2269fSPeter Wemm } else if (cp == buf || cp[-1] == 0) { 3620e3d5408SPeter Wemm argvec[argnum++] = cp; 36339f2269fSPeter Wemm if (argnum >= (int) SIZEOF(argvec) - 1) 36439f2269fSPeter Wemm break; 36539f2269fSPeter Wemm } 3660e3d5408SPeter Wemm } 36715589c42SPeter Wemm argvec[argnum] = 0; 3680e3d5408SPeter Wemm 36939f2269fSPeter Wemm if (argnum != 0 370*aae38d10SBaptiste Daroussin && tput_cmd(fd, &tty_settings, opt_x, argnum, argvec) != 0) { 3714a1a9510SRong-En Fan if (result == 0) 372*aae38d10SBaptiste Daroussin result = ErrSystem(0); /* will return value >4 */ 3734a1a9510SRong-En Fan ++result; 3744a1a9510SRong-En Fan } 3750e3d5408SPeter Wemm } 3760e3d5408SPeter Wemm 3774a1a9510SRong-En Fan ExitProgram(result); 3780e3d5408SPeter Wemm } 379