tput.c revision 174993
150276Speter/**************************************************************************** 2174993Srafan * Copyright (c) 1998-2006,2007 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 4550276Speter#include <termsort.c> 4650276Speter#endif 4766963Speter#include <transform.h> 4850276Speter 49174993SrafanMODULE_ID("$Id: tput.c,v 1.41 2007/10/13 20:34:16 tom Exp $") 5050276Speter 5150276Speter#define PUTS(s) fputs(s, stdout) 5250276Speter#define PUTCHAR(c) putchar(c) 5350276Speter#define FLUSH fflush(stdout) 5450276Speter 5566963Spetertypedef enum { 5666963Speter Numbers = 0 5766963Speter ,Num_Str 5866963Speter ,Num_Str_Str 5966963Speter} TParams; 6066963Speter 6150276Speterstatic char *prg_name; 6266963Speterstatic bool is_init = FALSE; 6366963Speterstatic bool is_reset = FALSE; 6450276Speter 6562449Speterstatic void 6662449Speterquit(int status, const char *fmt,...) 6750276Speter{ 6862449Speter va_list argp; 6950276Speter 7062449Speter va_start(argp, fmt); 71166124Srafan fprintf(stderr, "%s: ", prg_name); 7262449Speter vfprintf(stderr, fmt, argp); 7362449Speter fprintf(stderr, "\n"); 7462449Speter va_end(argp); 75166124Srafan ExitProgram(status); 7650276Speter} 7750276Speter 7862449Speterstatic void 7962449Speterusage(void) 8050276Speter{ 8166963Speter fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name); 82166124Srafan ExitProgram(EXIT_FAILURE); 8350276Speter} 8450276Speter 8566963Speterstatic void 8666963Spetercheck_aliases(const char *name) 8766963Speter{ 8866963Speter is_init = (strcmp(name, PROG_INIT) == 0); 8966963Speter is_reset = (strcmp(name, PROG_RESET) == 0); 9066963Speter} 9166963Speter 9266963Speter/* 9366963Speter * Lookup the type of call we should make to tparm(). This ignores the actual 9466963Speter * terminfo capability (bad, because it is not extensible), but makes this 9566963Speter * code portable to platforms where sizeof(int) != sizeof(char *). 9666963Speter * 9766963Speter * FIXME: If we want extensibility, analyze the capability string as we do 9866963Speter * in tparm() to decide how to parse the varargs list. 9966963Speter */ 10066963Speterstatic TParams 10176726Spetertparm_type(const char *name) 10266963Speter{ 10366963Speter#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc} 10466963Speter TParams result = Numbers; 10566963Speter /* *INDENT-OFF* */ 10666963Speter static const struct { 10766963Speter TParams code; 10866963Speter const char *name; 10966963Speter } table[] = { 11066963Speter TD(Num_Str, "pkey_key", "pfkey", "pk"), 11166963Speter TD(Num_Str, "pkey_local", "pfloc", "pl"), 11266963Speter TD(Num_Str, "pkey_xmit", "pfx", "px"), 11366963Speter TD(Num_Str, "plab_norm", "pln", "pn"), 11466963Speter TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), 11566963Speter }; 11666963Speter /* *INDENT-ON* */ 11766963Speter 11866963Speter unsigned n; 11966963Speter for (n = 0; n < SIZEOF(table); n++) { 12066963Speter if (!strcmp(name, table[n].name)) { 12166963Speter result = table[n].code; 12266963Speter break; 12366963Speter } 12466963Speter } 12566963Speter return result; 12666963Speter} 12766963Speter 12862449Speterstatic int 129166124Srafanexit_code(int token, int value) 130166124Srafan{ 131166124Srafan int result = 99; 132166124Srafan 133166124Srafan switch (token) { 134166124Srafan case BOOLEAN: 135166124Srafan result = !value; /* TRUE=0, FALSE=1 */ 136166124Srafan break; 137166124Srafan case NUMBER: 138166124Srafan result = 0; /* always zero */ 139166124Srafan break; 140166124Srafan case STRING: 141166124Srafan result = value; /* 0=normal, 1=missing */ 142166124Srafan break; 143166124Srafan } 144166124Srafan return result; 145166124Srafan} 146166124Srafan 147166124Srafanstatic int 14862449Spetertput(int argc, char *argv[]) 14950276Speter{ 15062449Speter NCURSES_CONST char *name; 15162449Speter char *s; 15262449Speter int i, j, c; 15366963Speter int status; 15462449Speter FILE *f; 15550276Speter 15697049Speter if ((name = argv[0]) == 0) 15797049Speter name = ""; 15897049Speter check_aliases(name); 15966963Speter if (is_reset || is_init) { 16062449Speter if (init_prog != 0) { 16162449Speter system(init_prog); 16250276Speter } 16362449Speter FLUSH; 16450276Speter 16566963Speter if (is_reset && reset_1string != 0) { 16662449Speter PUTS(reset_1string); 16762449Speter } else if (init_1string != 0) { 16862449Speter PUTS(init_1string); 16962449Speter } 17062449Speter FLUSH; 17150276Speter 17266963Speter if (is_reset && reset_2string != 0) { 17362449Speter PUTS(reset_2string); 17462449Speter } else if (init_2string != 0) { 17562449Speter PUTS(init_2string); 17662449Speter } 17762449Speter FLUSH; 17850276Speter 17997049Speter#ifdef set_lr_margin 18062449Speter if (set_lr_margin != 0) { 181166124Srafan PUTS(TPARM_2(set_lr_margin, 0, columns - 1)); 18297049Speter } else 18397049Speter#endif 18497049Speter#ifdef set_left_margin_parm 18597049Speter if (set_left_margin_parm != 0 18697049Speter && set_right_margin_parm != 0) { 187166124Srafan PUTS(TPARM_1(set_left_margin_parm, 0)); 188166124Srafan PUTS(TPARM_1(set_right_margin_parm, columns - 1)); 18997049Speter } else 19097049Speter#endif 19197049Speter if (clear_margins != 0 19297049Speter && set_left_margin != 0 19397049Speter && set_right_margin != 0) { 19462449Speter PUTS(clear_margins); 19562449Speter if (carriage_return != 0) { 19662449Speter PUTS(carriage_return); 19762449Speter } else { 19862449Speter PUTCHAR('\r'); 19962449Speter } 20062449Speter PUTS(set_left_margin); 20162449Speter if (parm_right_cursor) { 202166124Srafan PUTS(TPARM_1(parm_right_cursor, columns - 1)); 20362449Speter } else { 20462449Speter for (i = 0; i < columns - 1; i++) { 20562449Speter PUTCHAR(' '); 20650276Speter } 20762449Speter } 20862449Speter PUTS(set_right_margin); 20962449Speter if (carriage_return != 0) { 21062449Speter PUTS(carriage_return); 21162449Speter } else { 21262449Speter PUTCHAR('\r'); 21362449Speter } 21462449Speter } 21562449Speter FLUSH; 21650276Speter 21762449Speter if (init_tabs != 8) { 21862449Speter if (clear_all_tabs != 0 && set_tab != 0) { 21962449Speter for (i = 0; i < columns - 1; i += 8) { 22062449Speter if (parm_right_cursor) { 221166124Srafan PUTS(TPARM_1(parm_right_cursor, 8)); 22262449Speter } else { 22362449Speter for (j = 0; j < 8; j++) 22462449Speter PUTCHAR(' '); 22562449Speter } 22662449Speter PUTS(set_tab); 22750276Speter } 22850276Speter FLUSH; 22962449Speter } 23062449Speter } 23150276Speter 23266963Speter if (is_reset && reset_file != 0) { 23362449Speter f = fopen(reset_file, "r"); 23462449Speter if (f == 0) { 235166124Srafan quit(4 + errno, "Can't open reset_file: '%s'", reset_file); 23662449Speter } 23762449Speter while ((c = fgetc(f)) != EOF) { 23862449Speter PUTCHAR(c); 23962449Speter } 24062449Speter fclose(f); 24162449Speter } else if (init_file != 0) { 24262449Speter f = fopen(init_file, "r"); 24362449Speter if (f == 0) { 244166124Srafan quit(4 + errno, "Can't open init_file: '%s'", init_file); 24562449Speter } 24662449Speter while ((c = fgetc(f)) != EOF) { 24762449Speter PUTCHAR(c); 24862449Speter } 24962449Speter fclose(f); 25050276Speter } 25162449Speter FLUSH; 25250276Speter 25366963Speter if (is_reset && reset_3string != 0) { 25462449Speter PUTS(reset_3string); 255166124Srafan } else if (init_3string != 0) { 256166124Srafan PUTS(init_3string); 25750276Speter } 25862449Speter FLUSH; 25962449Speter return 0; 26062449Speter } 26150276Speter 26262449Speter if (strcmp(name, "longname") == 0) { 26362449Speter PUTS(longname()); 26462449Speter return 0; 26562449Speter } 26666963Speter#if !PURE_TERMINFO 26762449Speter { 26862449Speter const struct name_table_entry *np; 26950276Speter 27062449Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0) 27162449Speter switch (np->nte_type) { 27262449Speter case BOOLEAN: 27362449Speter if (bool_from_termcap[np->nte_index]) 27462449Speter name = boolnames[np->nte_index]; 27562449Speter break; 27650276Speter 27762449Speter case NUMBER: 27862449Speter if (num_from_termcap[np->nte_index]) 27962449Speter name = numnames[np->nte_index]; 28062449Speter break; 28150276Speter 28262449Speter case STRING: 28362449Speter if (str_from_termcap[np->nte_index]) 28462449Speter name = strnames[np->nte_index]; 28562449Speter break; 28662449Speter } 28762449Speter } 28850276Speter#endif 28950276Speter 29062449Speter if ((status = tigetflag(name)) != -1) { 291166124Srafan return exit_code(BOOLEAN, status); 29262449Speter } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 29362449Speter (void) printf("%d\n", status); 294166124Srafan return exit_code(NUMBER, 0); 29562449Speter } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 296166124Srafan quit(4, "unknown terminfo capability '%s'", name); 29766963Speter } else if (s != ABSENT_STRING) { 29862449Speter if (argc > 1) { 29962449Speter int k; 300166124Srafan int popcount; 301166124Srafan long numbers[1 + NUM_PARM]; 302166124Srafan char *strings[1 + NUM_PARM]; 303166124Srafan char *p_is_s[NUM_PARM]; 30450276Speter 30562449Speter /* Nasty hack time. The tparm function needs to see numeric 30662449Speter * parameters as numbers, not as pointers to their string 30762449Speter * representations 30862449Speter */ 30950276Speter 31062449Speter for (k = 1; k < argc; k++) { 31166963Speter char *tmp = 0; 31266963Speter strings[k] = argv[k]; 31366963Speter numbers[k] = strtol(argv[k], &tmp, 0); 31466963Speter if (tmp == 0 || *tmp != 0) 31566963Speter numbers[k] = 0; 31662449Speter } 317166124Srafan for (k = argc; k <= NUM_PARM; k++) { 31866963Speter numbers[k] = 0; 31966963Speter strings[k] = 0; 32066963Speter } 32150276Speter 32266963Speter switch (tparm_type(name)) { 32366963Speter case Num_Str: 324166124Srafan s = TPARM_2(s, numbers[1], strings[2]); 32566963Speter break; 32666963Speter case Num_Str_Str: 327166124Srafan s = TPARM_3(s, numbers[1], strings[2], strings[3]); 32866963Speter break; 329174993Srafan case Numbers: 33066963Speter default: 331166124Srafan (void) _nc_tparm_analyze(s, p_is_s, &popcount); 332166124Srafan#define myParam(n) (p_is_s[n - 1] != 0 ? ((long) strings[n]) : numbers[n]) 333166124Srafan s = TPARM_9(s, 334166124Srafan myParam(1), 335166124Srafan myParam(2), 336166124Srafan myParam(3), 337166124Srafan myParam(4), 338166124Srafan myParam(5), 339166124Srafan myParam(6), 340166124Srafan myParam(7), 341166124Srafan myParam(8), 342166124Srafan myParam(9)); 34366963Speter break; 34466963Speter } 34550276Speter } 34662449Speter 34762449Speter /* use putp() in order to perform padding */ 34862449Speter putp(s); 349166124Srafan return exit_code(STRING, 0); 35062449Speter } 351166124Srafan return exit_code(STRING, 1); 35250276Speter} 35350276Speter 35462449Speterint 35562449Spetermain(int argc, char **argv) 35650276Speter{ 35766963Speter char *term; 35866963Speter int errret; 35966963Speter bool cmdline = TRUE; 36062449Speter int c; 36162449Speter char buf[BUFSIZ]; 362166124Srafan int result = 0; 36350276Speter 36497049Speter check_aliases(prg_name = _nc_rootname(argv[0])); 36550276Speter 36662449Speter term = getenv("TERM"); 36750276Speter 368174993Srafan while ((c = getopt(argc, argv, "ST:V")) != -1) { 36962449Speter switch (c) { 37062449Speter case 'S': 37166963Speter cmdline = FALSE; 37262449Speter break; 37362449Speter case 'T': 37462449Speter use_env(FALSE); 37562449Speter term = optarg; 37662449Speter break; 37766963Speter case 'V': 37866963Speter puts(curses_version()); 379166124Srafan ExitProgram(EXIT_SUCCESS); 38062449Speter default: 38162449Speter usage(); 38262449Speter /* NOTREACHED */ 38350276Speter } 38466963Speter } 38550276Speter 38666963Speter /* 38766963Speter * Modify the argument list to omit the options we processed. 38866963Speter */ 38966963Speter if (is_reset || is_init) { 39066963Speter if (optind-- < argc) { 39166963Speter argc -= optind; 39266963Speter argv += optind; 39366963Speter } 39466963Speter argv[0] = prg_name; 39566963Speter } else { 39666963Speter argc -= optind; 39766963Speter argv += optind; 39862449Speter } 39950276Speter 40062449Speter if (term == 0 || *term == '\0') 40162449Speter quit(2, "No value for $TERM and no -T specified"); 40250276Speter 40362449Speter if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 40462449Speter quit(3, "unknown terminal \"%s\"", term); 40550276Speter 40666963Speter if (cmdline) { 40766963Speter if ((argc <= 0) && !is_reset && !is_init) 40866963Speter usage(); 409166124Srafan ExitProgram(tput(argc, argv)); 41066963Speter } 41150276Speter 41262449Speter while (fgets(buf, sizeof(buf), stdin) != 0) { 41362449Speter char *argvec[16]; /* command, 9 parms, null, & slop */ 41462449Speter int argnum = 0; 41562449Speter char *cp; 41650276Speter 41762449Speter /* crack the argument list into a dope vector */ 41862449Speter for (cp = buf; *cp; cp++) { 41997049Speter if (isspace(UChar(*cp))) { 42062449Speter *cp = '\0'; 42197049Speter } else if (cp == buf || cp[-1] == 0) { 42262449Speter argvec[argnum++] = cp; 42397049Speter if (argnum >= (int) SIZEOF(argvec) - 1) 42497049Speter break; 42597049Speter } 42650276Speter } 42762449Speter argvec[argnum] = 0; 42850276Speter 42997049Speter if (argnum != 0 430166124Srafan && tput(argnum, argvec) != 0) { 431166124Srafan if (result == 0) 432166124Srafan result = 4; /* will return value >4 */ 433166124Srafan ++result; 434166124Srafan } 43562449Speter } 43662449Speter 437166124Srafan ExitProgram(result); 43850276Speter} 439