tput.c revision 166124
150276Speter/**************************************************************************** 2166124Srafan * Copyright (c) 1998-2005,2006 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 4150276Speter#include <progs.priv.h> 4266963Speter 4366963Speter#if !PURE_TERMINFO 4450276Speter#include <termsort.c> 4550276Speter#endif 4666963Speter#include <transform.h> 4750276Speter 48166124SrafanMODULE_ID("$Id: tput.c,v 1.38 2006/11/26 00:27:47 tom Exp $") 4950276Speter 5050276Speter#define PUTS(s) fputs(s, stdout) 5150276Speter#define PUTCHAR(c) putchar(c) 5250276Speter#define FLUSH fflush(stdout) 5350276Speter 5466963Spetertypedef enum { 5566963Speter Numbers = 0 5666963Speter ,Num_Str 5766963Speter ,Num_Str_Str 5866963Speter} TParams; 5966963Speter 6050276Speterstatic char *prg_name; 6166963Speterstatic bool is_init = FALSE; 6266963Speterstatic bool is_reset = FALSE; 6350276Speter 6462449Speterstatic void 6562449Speterquit(int status, const char *fmt,...) 6650276Speter{ 6762449Speter va_list argp; 6850276Speter 6962449Speter va_start(argp, fmt); 70166124Srafan fprintf(stderr, "%s: ", prg_name); 7162449Speter vfprintf(stderr, fmt, argp); 7262449Speter fprintf(stderr, "\n"); 7362449Speter va_end(argp); 74166124Srafan ExitProgram(status); 7550276Speter} 7650276Speter 7762449Speterstatic void 7862449Speterusage(void) 7950276Speter{ 8066963Speter fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name); 81166124Srafan ExitProgram(EXIT_FAILURE); 8250276Speter} 8350276Speter 8466963Speterstatic void 8566963Spetercheck_aliases(const char *name) 8666963Speter{ 8766963Speter is_init = (strcmp(name, PROG_INIT) == 0); 8866963Speter is_reset = (strcmp(name, PROG_RESET) == 0); 8966963Speter} 9066963Speter 9166963Speter/* 9266963Speter * Lookup the type of call we should make to tparm(). This ignores the actual 9366963Speter * terminfo capability (bad, because it is not extensible), but makes this 9466963Speter * code portable to platforms where sizeof(int) != sizeof(char *). 9566963Speter * 9666963Speter * FIXME: If we want extensibility, analyze the capability string as we do 9766963Speter * in tparm() to decide how to parse the varargs list. 9866963Speter */ 9966963Speterstatic TParams 10076726Spetertparm_type(const char *name) 10166963Speter{ 10266963Speter#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc} 10366963Speter TParams result = Numbers; 10466963Speter /* *INDENT-OFF* */ 10566963Speter static const struct { 10666963Speter TParams code; 10766963Speter const char *name; 10866963Speter } table[] = { 10966963Speter TD(Num_Str, "pkey_key", "pfkey", "pk"), 11066963Speter TD(Num_Str, "pkey_local", "pfloc", "pl"), 11166963Speter TD(Num_Str, "pkey_xmit", "pfx", "px"), 11266963Speter TD(Num_Str, "plab_norm", "pln", "pn"), 11366963Speter TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), 11466963Speter }; 11566963Speter /* *INDENT-ON* */ 11666963Speter 11766963Speter unsigned n; 11866963Speter for (n = 0; n < SIZEOF(table); n++) { 11966963Speter if (!strcmp(name, table[n].name)) { 12066963Speter result = table[n].code; 12166963Speter break; 12266963Speter } 12366963Speter } 12466963Speter return result; 12566963Speter} 12666963Speter 12762449Speterstatic int 128166124Srafanexit_code(int token, int value) 129166124Srafan{ 130166124Srafan int result = 99; 131166124Srafan 132166124Srafan switch (token) { 133166124Srafan case BOOLEAN: 134166124Srafan result = !value; /* TRUE=0, FALSE=1 */ 135166124Srafan break; 136166124Srafan case NUMBER: 137166124Srafan result = 0; /* always zero */ 138166124Srafan break; 139166124Srafan case STRING: 140166124Srafan result = value; /* 0=normal, 1=missing */ 141166124Srafan break; 142166124Srafan } 143166124Srafan return result; 144166124Srafan} 145166124Srafan 146166124Srafanstatic int 14762449Spetertput(int argc, char *argv[]) 14850276Speter{ 14962449Speter NCURSES_CONST char *name; 15062449Speter char *s; 15162449Speter int i, j, c; 15266963Speter int status; 15362449Speter FILE *f; 15450276Speter 15597049Speter if ((name = argv[0]) == 0) 15697049Speter name = ""; 15797049Speter check_aliases(name); 15866963Speter if (is_reset || is_init) { 15962449Speter if (init_prog != 0) { 16062449Speter system(init_prog); 16150276Speter } 16262449Speter FLUSH; 16350276Speter 16466963Speter if (is_reset && reset_1string != 0) { 16562449Speter PUTS(reset_1string); 16662449Speter } else if (init_1string != 0) { 16762449Speter PUTS(init_1string); 16862449Speter } 16962449Speter FLUSH; 17050276Speter 17166963Speter if (is_reset && reset_2string != 0) { 17262449Speter PUTS(reset_2string); 17362449Speter } else if (init_2string != 0) { 17462449Speter PUTS(init_2string); 17562449Speter } 17662449Speter FLUSH; 17750276Speter 17897049Speter#ifdef set_lr_margin 17962449Speter if (set_lr_margin != 0) { 180166124Srafan PUTS(TPARM_2(set_lr_margin, 0, columns - 1)); 18197049Speter } else 18297049Speter#endif 18397049Speter#ifdef set_left_margin_parm 18497049Speter if (set_left_margin_parm != 0 18597049Speter && set_right_margin_parm != 0) { 186166124Srafan PUTS(TPARM_1(set_left_margin_parm, 0)); 187166124Srafan PUTS(TPARM_1(set_right_margin_parm, columns - 1)); 18897049Speter } else 18997049Speter#endif 19097049Speter if (clear_margins != 0 19197049Speter && set_left_margin != 0 19297049Speter && set_right_margin != 0) { 19362449Speter PUTS(clear_margins); 19462449Speter if (carriage_return != 0) { 19562449Speter PUTS(carriage_return); 19662449Speter } else { 19762449Speter PUTCHAR('\r'); 19862449Speter } 19962449Speter PUTS(set_left_margin); 20062449Speter if (parm_right_cursor) { 201166124Srafan PUTS(TPARM_1(parm_right_cursor, columns - 1)); 20262449Speter } else { 20362449Speter for (i = 0; i < columns - 1; i++) { 20462449Speter PUTCHAR(' '); 20550276Speter } 20662449Speter } 20762449Speter PUTS(set_right_margin); 20862449Speter if (carriage_return != 0) { 20962449Speter PUTS(carriage_return); 21062449Speter } else { 21162449Speter PUTCHAR('\r'); 21262449Speter } 21362449Speter } 21462449Speter FLUSH; 21550276Speter 21662449Speter if (init_tabs != 8) { 21762449Speter if (clear_all_tabs != 0 && set_tab != 0) { 21862449Speter for (i = 0; i < columns - 1; i += 8) { 21962449Speter if (parm_right_cursor) { 220166124Srafan PUTS(TPARM_1(parm_right_cursor, 8)); 22162449Speter } else { 22262449Speter for (j = 0; j < 8; j++) 22362449Speter PUTCHAR(' '); 22462449Speter } 22562449Speter PUTS(set_tab); 22650276Speter } 22750276Speter FLUSH; 22862449Speter } 22962449Speter } 23050276Speter 23166963Speter if (is_reset && reset_file != 0) { 23262449Speter f = fopen(reset_file, "r"); 23362449Speter if (f == 0) { 234166124Srafan quit(4 + errno, "Can't open reset_file: '%s'", reset_file); 23562449Speter } 23662449Speter while ((c = fgetc(f)) != EOF) { 23762449Speter PUTCHAR(c); 23862449Speter } 23962449Speter fclose(f); 24062449Speter } else if (init_file != 0) { 24162449Speter f = fopen(init_file, "r"); 24262449Speter if (f == 0) { 243166124Srafan quit(4 + errno, "Can't open init_file: '%s'", init_file); 24462449Speter } 24562449Speter while ((c = fgetc(f)) != EOF) { 24662449Speter PUTCHAR(c); 24762449Speter } 24862449Speter fclose(f); 24950276Speter } 25062449Speter FLUSH; 25150276Speter 25266963Speter if (is_reset && reset_3string != 0) { 25362449Speter PUTS(reset_3string); 254166124Srafan } else if (init_3string != 0) { 255166124Srafan PUTS(init_3string); 25650276Speter } 25762449Speter FLUSH; 25862449Speter return 0; 25962449Speter } 26050276Speter 26162449Speter if (strcmp(name, "longname") == 0) { 26262449Speter PUTS(longname()); 26362449Speter return 0; 26462449Speter } 26566963Speter#if !PURE_TERMINFO 26662449Speter { 26762449Speter const struct name_table_entry *np; 26850276Speter 26962449Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0) 27062449Speter switch (np->nte_type) { 27162449Speter case BOOLEAN: 27262449Speter if (bool_from_termcap[np->nte_index]) 27362449Speter name = boolnames[np->nte_index]; 27462449Speter break; 27550276Speter 27662449Speter case NUMBER: 27762449Speter if (num_from_termcap[np->nte_index]) 27862449Speter name = numnames[np->nte_index]; 27962449Speter break; 28050276Speter 28162449Speter case STRING: 28262449Speter if (str_from_termcap[np->nte_index]) 28362449Speter name = strnames[np->nte_index]; 28462449Speter break; 28562449Speter } 28662449Speter } 28750276Speter#endif 28850276Speter 28962449Speter if ((status = tigetflag(name)) != -1) { 290166124Srafan return exit_code(BOOLEAN, status); 29162449Speter } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 29262449Speter (void) printf("%d\n", status); 293166124Srafan return exit_code(NUMBER, 0); 29462449Speter } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 295166124Srafan quit(4, "unknown terminfo capability '%s'", name); 29666963Speter } else if (s != ABSENT_STRING) { 29762449Speter if (argc > 1) { 29862449Speter int k; 299166124Srafan int popcount; 300166124Srafan long numbers[1 + NUM_PARM]; 301166124Srafan char *strings[1 + NUM_PARM]; 302166124Srafan char *p_is_s[NUM_PARM]; 30350276Speter 30462449Speter /* Nasty hack time. The tparm function needs to see numeric 30562449Speter * parameters as numbers, not as pointers to their string 30662449Speter * representations 30762449Speter */ 30850276Speter 30962449Speter for (k = 1; k < argc; k++) { 31066963Speter char *tmp = 0; 31166963Speter strings[k] = argv[k]; 31266963Speter numbers[k] = strtol(argv[k], &tmp, 0); 31366963Speter if (tmp == 0 || *tmp != 0) 31466963Speter numbers[k] = 0; 31562449Speter } 316166124Srafan for (k = argc; k <= NUM_PARM; k++) { 31766963Speter numbers[k] = 0; 31866963Speter strings[k] = 0; 31966963Speter } 32050276Speter 32166963Speter switch (tparm_type(name)) { 32266963Speter case Num_Str: 323166124Srafan s = TPARM_2(s, numbers[1], strings[2]); 32466963Speter break; 32566963Speter case Num_Str_Str: 326166124Srafan s = TPARM_3(s, numbers[1], strings[2], strings[3]); 32766963Speter break; 32866963Speter default: 329166124Srafan (void) _nc_tparm_analyze(s, p_is_s, &popcount); 330166124Srafan#define myParam(n) (p_is_s[n - 1] != 0 ? ((long) strings[n]) : numbers[n]) 331166124Srafan s = TPARM_9(s, 332166124Srafan myParam(1), 333166124Srafan myParam(2), 334166124Srafan myParam(3), 335166124Srafan myParam(4), 336166124Srafan myParam(5), 337166124Srafan myParam(6), 338166124Srafan myParam(7), 339166124Srafan myParam(8), 340166124Srafan myParam(9)); 34166963Speter break; 34266963Speter } 34350276Speter } 34462449Speter 34562449Speter /* use putp() in order to perform padding */ 34662449Speter putp(s); 347166124Srafan return exit_code(STRING, 0); 34862449Speter } 349166124Srafan return exit_code(STRING, 1); 35050276Speter} 35150276Speter 35262449Speterint 35362449Spetermain(int argc, char **argv) 35450276Speter{ 35566963Speter char *term; 35666963Speter int errret; 35766963Speter bool cmdline = TRUE; 35862449Speter int c; 35962449Speter char buf[BUFSIZ]; 360166124Srafan int result = 0; 36150276Speter 36297049Speter check_aliases(prg_name = _nc_rootname(argv[0])); 36350276Speter 36462449Speter term = getenv("TERM"); 36550276Speter 36666963Speter while ((c = getopt(argc, argv, "ST:V")) != EOF) { 36762449Speter switch (c) { 36862449Speter case 'S': 36966963Speter cmdline = FALSE; 37062449Speter break; 37162449Speter case 'T': 37262449Speter use_env(FALSE); 37362449Speter term = optarg; 37462449Speter break; 37566963Speter case 'V': 37666963Speter puts(curses_version()); 377166124Srafan ExitProgram(EXIT_SUCCESS); 37862449Speter default: 37962449Speter usage(); 38062449Speter /* NOTREACHED */ 38150276Speter } 38266963Speter } 38350276Speter 38466963Speter /* 38566963Speter * Modify the argument list to omit the options we processed. 38666963Speter */ 38766963Speter if (is_reset || is_init) { 38866963Speter if (optind-- < argc) { 38966963Speter argc -= optind; 39066963Speter argv += optind; 39166963Speter } 39266963Speter argv[0] = prg_name; 39366963Speter } else { 39466963Speter argc -= optind; 39566963Speter argv += optind; 39662449Speter } 39750276Speter 39862449Speter if (term == 0 || *term == '\0') 39962449Speter quit(2, "No value for $TERM and no -T specified"); 40050276Speter 40162449Speter if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 40262449Speter quit(3, "unknown terminal \"%s\"", term); 40350276Speter 40466963Speter if (cmdline) { 40566963Speter if ((argc <= 0) && !is_reset && !is_init) 40666963Speter usage(); 407166124Srafan ExitProgram(tput(argc, argv)); 40866963Speter } 40950276Speter 41062449Speter while (fgets(buf, sizeof(buf), stdin) != 0) { 41162449Speter char *argvec[16]; /* command, 9 parms, null, & slop */ 41262449Speter int argnum = 0; 41362449Speter char *cp; 41450276Speter 41562449Speter /* crack the argument list into a dope vector */ 41662449Speter for (cp = buf; *cp; cp++) { 41797049Speter if (isspace(UChar(*cp))) { 41862449Speter *cp = '\0'; 41997049Speter } else if (cp == buf || cp[-1] == 0) { 42062449Speter argvec[argnum++] = cp; 42197049Speter if (argnum >= (int) SIZEOF(argvec) - 1) 42297049Speter break; 42397049Speter } 42450276Speter } 42562449Speter argvec[argnum] = 0; 42650276Speter 42797049Speter if (argnum != 0 428166124Srafan && tput(argnum, argvec) != 0) { 429166124Srafan if (result == 0) 430166124Srafan result = 4; /* will return value >4 */ 431166124Srafan ++result; 432166124Srafan } 43362449Speter } 43462449Speter 435166124Srafan ExitProgram(result); 43650276Speter} 437