150276Speter/**************************************************************************** 2262685Sdelphij * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 3250276Speter ****************************************************************************/ 3350276Speter 3450276Speter/* 3550276Speter * tput.c -- shellscript access to terminal capabilities 3650276Speter * 3750276Speter * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from 3850276Speter * Ross Ridge's mytinfo package. 3950276Speter */ 4050276Speter 41174993Srafan#define USE_LIBTINFO 4250276Speter#include <progs.priv.h> 4366963Speter 4466963Speter#if !PURE_TERMINFO 45184989Srafan#include <dump_entry.h> 4650276Speter#include <termsort.c> 4750276Speter#endif 4866963Speter#include <transform.h> 4950276Speter 50262685SdelphijMODULE_ID("$Id: tput.c,v 1.49 2013/09/28 20:57:25 tom Exp $") 5150276Speter 5250276Speter#define PUTS(s) fputs(s, stdout) 5350276Speter#define PUTCHAR(c) putchar(c) 5450276Speter#define FLUSH fflush(stdout) 5550276Speter 5666963Spetertypedef enum { 5766963Speter Numbers = 0 5866963Speter ,Num_Str 5966963Speter ,Num_Str_Str 6066963Speter} TParams; 6166963Speter 6250276Speterstatic char *prg_name; 6366963Speterstatic bool is_init = FALSE; 6466963Speterstatic bool is_reset = FALSE; 6550276Speter 6662449Speterstatic void 6762449Speterquit(int status, const char *fmt,...) 6850276Speter{ 6962449Speter va_list argp; 7050276Speter 7162449Speter va_start(argp, fmt); 72166124Srafan fprintf(stderr, "%s: ", prg_name); 7362449Speter vfprintf(stderr, fmt, argp); 7462449Speter fprintf(stderr, "\n"); 7562449Speter va_end(argp); 76166124Srafan ExitProgram(status); 7750276Speter} 7850276Speter 7962449Speterstatic void 8062449Speterusage(void) 8150276Speter{ 8266963Speter fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name); 83166124Srafan ExitProgram(EXIT_FAILURE); 8450276Speter} 8550276Speter 8666963Speterstatic void 8766963Spetercheck_aliases(const char *name) 8866963Speter{ 89262629Sdelphij is_init = same_program(name, PROG_INIT); 90262629Sdelphij is_reset = same_program(name, PROG_RESET); 9166963Speter} 9266963Speter 9366963Speter/* 9466963Speter * Lookup the type of call we should make to tparm(). This ignores the actual 9566963Speter * terminfo capability (bad, because it is not extensible), but makes this 9666963Speter * code portable to platforms where sizeof(int) != sizeof(char *). 9766963Speter */ 9866963Speterstatic TParams 9976726Spetertparm_type(const char *name) 10066963Speter{ 10166963Speter#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc} 10266963Speter TParams result = Numbers; 10366963Speter /* *INDENT-OFF* */ 10466963Speter static const struct { 10566963Speter TParams code; 10666963Speter const char *name; 10766963Speter } table[] = { 10866963Speter TD(Num_Str, "pkey_key", "pfkey", "pk"), 10966963Speter TD(Num_Str, "pkey_local", "pfloc", "pl"), 11066963Speter TD(Num_Str, "pkey_xmit", "pfx", "px"), 11166963Speter TD(Num_Str, "plab_norm", "pln", "pn"), 11266963Speter TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), 11366963Speter }; 11466963Speter /* *INDENT-ON* */ 11566963Speter 11666963Speter unsigned n; 11766963Speter for (n = 0; n < SIZEOF(table); n++) { 11866963Speter if (!strcmp(name, table[n].name)) { 11966963Speter result = table[n].code; 12066963Speter break; 12166963Speter } 12266963Speter } 12366963Speter return result; 12466963Speter} 12566963Speter 12662449Speterstatic int 127166124Srafanexit_code(int token, int value) 128166124Srafan{ 129166124Srafan int result = 99; 130166124Srafan 131166124Srafan switch (token) { 132166124Srafan case BOOLEAN: 133166124Srafan result = !value; /* TRUE=0, FALSE=1 */ 134166124Srafan break; 135166124Srafan case NUMBER: 136166124Srafan result = 0; /* always zero */ 137166124Srafan break; 138166124Srafan case STRING: 139166124Srafan result = value; /* 0=normal, 1=missing */ 140166124Srafan break; 141166124Srafan } 142166124Srafan return result; 143166124Srafan} 144166124Srafan 145166124Srafanstatic int 14662449Spetertput(int argc, char *argv[]) 14750276Speter{ 14862449Speter NCURSES_CONST char *name; 14962449Speter char *s; 15062449Speter int i, j, c; 15166963Speter int status; 15262449Speter FILE *f; 153262629Sdelphij#if !PURE_TERMINFO 154262629Sdelphij bool termcap = FALSE; 155262629Sdelphij#endif 15650276Speter 15797049Speter if ((name = argv[0]) == 0) 15897049Speter name = ""; 15997049Speter check_aliases(name); 16066963Speter if (is_reset || is_init) { 16162449Speter if (init_prog != 0) { 16262449Speter system(init_prog); 16350276Speter } 16462449Speter FLUSH; 16550276Speter 16666963Speter if (is_reset && reset_1string != 0) { 16762449Speter PUTS(reset_1string); 16862449Speter } else if (init_1string != 0) { 16962449Speter PUTS(init_1string); 17062449Speter } 17162449Speter FLUSH; 17250276Speter 17366963Speter if (is_reset && reset_2string != 0) { 17462449Speter PUTS(reset_2string); 17562449Speter } else if (init_2string != 0) { 17662449Speter PUTS(init_2string); 17762449Speter } 17862449Speter FLUSH; 17950276Speter 18097049Speter#ifdef set_lr_margin 18162449Speter if (set_lr_margin != 0) { 182166124Srafan PUTS(TPARM_2(set_lr_margin, 0, columns - 1)); 18397049Speter } else 18497049Speter#endif 18597049Speter#ifdef set_left_margin_parm 18697049Speter if (set_left_margin_parm != 0 18797049Speter && set_right_margin_parm != 0) { 188166124Srafan PUTS(TPARM_1(set_left_margin_parm, 0)); 189166124Srafan PUTS(TPARM_1(set_right_margin_parm, columns - 1)); 19097049Speter } else 19197049Speter#endif 19297049Speter if (clear_margins != 0 19397049Speter && set_left_margin != 0 19497049Speter && set_right_margin != 0) { 19562449Speter PUTS(clear_margins); 19662449Speter if (carriage_return != 0) { 19762449Speter PUTS(carriage_return); 19862449Speter } else { 19962449Speter PUTCHAR('\r'); 20062449Speter } 20162449Speter PUTS(set_left_margin); 20262449Speter if (parm_right_cursor) { 203166124Srafan PUTS(TPARM_1(parm_right_cursor, columns - 1)); 20462449Speter } else { 20562449Speter for (i = 0; i < columns - 1; i++) { 20662449Speter PUTCHAR(' '); 20750276Speter } 20862449Speter } 20962449Speter PUTS(set_right_margin); 21062449Speter if (carriage_return != 0) { 21162449Speter PUTS(carriage_return); 21262449Speter } else { 21362449Speter PUTCHAR('\r'); 21462449Speter } 21562449Speter } 21662449Speter FLUSH; 21750276Speter 21862449Speter if (init_tabs != 8) { 21962449Speter if (clear_all_tabs != 0 && set_tab != 0) { 22062449Speter for (i = 0; i < columns - 1; i += 8) { 22162449Speter if (parm_right_cursor) { 222166124Srafan PUTS(TPARM_1(parm_right_cursor, 8)); 22362449Speter } else { 22462449Speter for (j = 0; j < 8; j++) 22562449Speter PUTCHAR(' '); 22662449Speter } 22762449Speter PUTS(set_tab); 22850276Speter } 22950276Speter FLUSH; 23062449Speter } 23162449Speter } 23250276Speter 23366963Speter if (is_reset && reset_file != 0) { 23462449Speter f = fopen(reset_file, "r"); 23562449Speter if (f == 0) { 236166124Srafan quit(4 + errno, "Can't open reset_file: '%s'", reset_file); 23762449Speter } 23862449Speter while ((c = fgetc(f)) != EOF) { 23962449Speter PUTCHAR(c); 24062449Speter } 24162449Speter fclose(f); 24262449Speter } else if (init_file != 0) { 24362449Speter f = fopen(init_file, "r"); 24462449Speter if (f == 0) { 245166124Srafan quit(4 + errno, "Can't open init_file: '%s'", init_file); 24662449Speter } 24762449Speter while ((c = fgetc(f)) != EOF) { 24862449Speter PUTCHAR(c); 24962449Speter } 25062449Speter fclose(f); 25150276Speter } 25262449Speter FLUSH; 25350276Speter 25466963Speter if (is_reset && reset_3string != 0) { 25562449Speter PUTS(reset_3string); 256166124Srafan } else if (init_3string != 0) { 257166124Srafan PUTS(init_3string); 25850276Speter } 25962449Speter FLUSH; 26062449Speter return 0; 26162449Speter } 26250276Speter 26362449Speter if (strcmp(name, "longname") == 0) { 26462449Speter PUTS(longname()); 26562449Speter return 0; 26662449Speter } 26766963Speter#if !PURE_TERMINFO 268262629Sdelphij retry: 26950276Speter#endif 27062449Speter if ((status = tigetflag(name)) != -1) { 271166124Srafan return exit_code(BOOLEAN, status); 27262449Speter } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 27362449Speter (void) printf("%d\n", status); 274166124Srafan return exit_code(NUMBER, 0); 27562449Speter } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 276262629Sdelphij#if !PURE_TERMINFO 277262629Sdelphij if (!termcap) { 278262629Sdelphij const struct name_table_entry *np; 279262629Sdelphij 280262629Sdelphij termcap = TRUE; 281262629Sdelphij if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) { 282262629Sdelphij switch (np->nte_type) { 283262629Sdelphij case BOOLEAN: 284262629Sdelphij if (bool_from_termcap[np->nte_index]) 285262629Sdelphij name = boolnames[np->nte_index]; 286262629Sdelphij break; 287262629Sdelphij 288262629Sdelphij case NUMBER: 289262629Sdelphij if (num_from_termcap[np->nte_index]) 290262629Sdelphij name = numnames[np->nte_index]; 291262629Sdelphij break; 292262629Sdelphij 293262629Sdelphij case STRING: 294262629Sdelphij if (str_from_termcap[np->nte_index]) 295262629Sdelphij name = strnames[np->nte_index]; 296262629Sdelphij break; 297262629Sdelphij } 298262629Sdelphij goto retry; 299262629Sdelphij } 300262629Sdelphij } 301262629Sdelphij#endif 302166124Srafan quit(4, "unknown terminfo capability '%s'", name); 30366963Speter } else if (s != ABSENT_STRING) { 30462449Speter if (argc > 1) { 30562449Speter int k; 306262685Sdelphij int ignored; 307166124Srafan long numbers[1 + NUM_PARM]; 308166124Srafan char *strings[1 + NUM_PARM]; 309166124Srafan char *p_is_s[NUM_PARM]; 31050276Speter 31162449Speter /* Nasty hack time. The tparm function needs to see numeric 31262449Speter * parameters as numbers, not as pointers to their string 31362449Speter * representations 31462449Speter */ 31550276Speter 31662449Speter for (k = 1; k < argc; k++) { 31766963Speter char *tmp = 0; 31866963Speter strings[k] = argv[k]; 31966963Speter numbers[k] = strtol(argv[k], &tmp, 0); 32066963Speter if (tmp == 0 || *tmp != 0) 32166963Speter numbers[k] = 0; 32262449Speter } 323166124Srafan for (k = argc; k <= NUM_PARM; k++) { 32466963Speter numbers[k] = 0; 32566963Speter strings[k] = 0; 32666963Speter } 32750276Speter 32866963Speter switch (tparm_type(name)) { 32966963Speter case Num_Str: 330166124Srafan s = TPARM_2(s, numbers[1], strings[2]); 33166963Speter break; 33266963Speter case Num_Str_Str: 333166124Srafan s = TPARM_3(s, numbers[1], strings[2], strings[3]); 33466963Speter break; 335174993Srafan case Numbers: 33666963Speter default: 337262685Sdelphij (void) _nc_tparm_analyze(s, p_is_s, &ignored); 338262685Sdelphij#define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n]) 339166124Srafan s = TPARM_9(s, 340166124Srafan myParam(1), 341166124Srafan myParam(2), 342166124Srafan myParam(3), 343166124Srafan myParam(4), 344166124Srafan myParam(5), 345166124Srafan myParam(6), 346166124Srafan myParam(7), 347166124Srafan myParam(8), 348166124Srafan myParam(9)); 34966963Speter break; 35066963Speter } 35150276Speter } 35262449Speter 35362449Speter /* use putp() in order to perform padding */ 35462449Speter putp(s); 355166124Srafan return exit_code(STRING, 0); 35662449Speter } 357166124Srafan return exit_code(STRING, 1); 35850276Speter} 35950276Speter 36062449Speterint 36162449Spetermain(int argc, char **argv) 36250276Speter{ 36366963Speter char *term; 36466963Speter int errret; 36566963Speter bool cmdline = TRUE; 36662449Speter int c; 36762449Speter char buf[BUFSIZ]; 368166124Srafan int result = 0; 36950276Speter 37097049Speter check_aliases(prg_name = _nc_rootname(argv[0])); 37150276Speter 37262449Speter term = getenv("TERM"); 37350276Speter 374174993Srafan while ((c = getopt(argc, argv, "ST:V")) != -1) { 37562449Speter switch (c) { 37662449Speter case 'S': 37766963Speter cmdline = FALSE; 37862449Speter break; 37962449Speter case 'T': 38062449Speter use_env(FALSE); 38162449Speter term = optarg; 38262449Speter break; 38366963Speter case 'V': 38466963Speter puts(curses_version()); 385166124Srafan ExitProgram(EXIT_SUCCESS); 38662449Speter default: 38762449Speter usage(); 38862449Speter /* NOTREACHED */ 38950276Speter } 39066963Speter } 39150276Speter 39266963Speter /* 39366963Speter * Modify the argument list to omit the options we processed. 39466963Speter */ 39566963Speter if (is_reset || is_init) { 39666963Speter if (optind-- < argc) { 39766963Speter argc -= optind; 39866963Speter argv += optind; 39966963Speter } 40066963Speter argv[0] = prg_name; 40166963Speter } else { 40266963Speter argc -= optind; 40366963Speter argv += optind; 40462449Speter } 40550276Speter 40662449Speter if (term == 0 || *term == '\0') 40762449Speter quit(2, "No value for $TERM and no -T specified"); 40850276Speter 40962449Speter if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 41062449Speter quit(3, "unknown terminal \"%s\"", term); 41150276Speter 41266963Speter if (cmdline) { 41366963Speter if ((argc <= 0) && !is_reset && !is_init) 41466963Speter usage(); 415166124Srafan ExitProgram(tput(argc, argv)); 41666963Speter } 41750276Speter 41862449Speter while (fgets(buf, sizeof(buf), stdin) != 0) { 41962449Speter char *argvec[16]; /* command, 9 parms, null, & slop */ 42062449Speter int argnum = 0; 42162449Speter char *cp; 42250276Speter 42362449Speter /* crack the argument list into a dope vector */ 42462449Speter for (cp = buf; *cp; cp++) { 42597049Speter if (isspace(UChar(*cp))) { 42662449Speter *cp = '\0'; 42797049Speter } else if (cp == buf || cp[-1] == 0) { 42862449Speter argvec[argnum++] = cp; 42997049Speter if (argnum >= (int) SIZEOF(argvec) - 1) 43097049Speter break; 43197049Speter } 43250276Speter } 43362449Speter argvec[argnum] = 0; 43450276Speter 43597049Speter if (argnum != 0 436166124Srafan && tput(argnum, argvec) != 0) { 437166124Srafan if (result == 0) 438166124Srafan result = 4; /* will return value >4 */ 439166124Srafan ++result; 440166124Srafan } 44162449Speter } 44262449Speter 443166124Srafan ExitProgram(result); 44450276Speter} 445