tput.c revision 184989
150276Speter/**************************************************************************** 2184989Srafan * Copyright (c) 1998-2007,2008 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 50184989SrafanMODULE_ID("$Id: tput.c,v 1.42 2008/07/13 11:05:12 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{ 8966963Speter is_init = (strcmp(name, PROG_INIT) == 0); 9066963Speter is_reset = (strcmp(name, PROG_RESET) == 0); 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 * 9866963Speter * FIXME: If we want extensibility, analyze the capability string as we do 9966963Speter * in tparm() to decide how to parse the varargs list. 10066963Speter */ 10166963Speterstatic TParams 10276726Spetertparm_type(const char *name) 10366963Speter{ 10466963Speter#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc} 10566963Speter TParams result = Numbers; 10666963Speter /* *INDENT-OFF* */ 10766963Speter static const struct { 10866963Speter TParams code; 10966963Speter const char *name; 11066963Speter } table[] = { 11166963Speter TD(Num_Str, "pkey_key", "pfkey", "pk"), 11266963Speter TD(Num_Str, "pkey_local", "pfloc", "pl"), 11366963Speter TD(Num_Str, "pkey_xmit", "pfx", "px"), 11466963Speter TD(Num_Str, "plab_norm", "pln", "pn"), 11566963Speter TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), 11666963Speter }; 11766963Speter /* *INDENT-ON* */ 11866963Speter 11966963Speter unsigned n; 12066963Speter for (n = 0; n < SIZEOF(table); n++) { 12166963Speter if (!strcmp(name, table[n].name)) { 12266963Speter result = table[n].code; 12366963Speter break; 12466963Speter } 12566963Speter } 12666963Speter return result; 12766963Speter} 12866963Speter 12962449Speterstatic int 130166124Srafanexit_code(int token, int value) 131166124Srafan{ 132166124Srafan int result = 99; 133166124Srafan 134166124Srafan switch (token) { 135166124Srafan case BOOLEAN: 136166124Srafan result = !value; /* TRUE=0, FALSE=1 */ 137166124Srafan break; 138166124Srafan case NUMBER: 139166124Srafan result = 0; /* always zero */ 140166124Srafan break; 141166124Srafan case STRING: 142166124Srafan result = value; /* 0=normal, 1=missing */ 143166124Srafan break; 144166124Srafan } 145166124Srafan return result; 146166124Srafan} 147166124Srafan 148166124Srafanstatic int 14962449Spetertput(int argc, char *argv[]) 15050276Speter{ 15162449Speter NCURSES_CONST char *name; 15262449Speter char *s; 15362449Speter int i, j, c; 15466963Speter int status; 15562449Speter FILE *f; 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 26862449Speter { 26962449Speter const struct name_table_entry *np; 27050276Speter 27162449Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0) 27262449Speter switch (np->nte_type) { 27362449Speter case BOOLEAN: 27462449Speter if (bool_from_termcap[np->nte_index]) 27562449Speter name = boolnames[np->nte_index]; 27662449Speter break; 27750276Speter 27862449Speter case NUMBER: 27962449Speter if (num_from_termcap[np->nte_index]) 28062449Speter name = numnames[np->nte_index]; 28162449Speter break; 28250276Speter 28362449Speter case STRING: 28462449Speter if (str_from_termcap[np->nte_index]) 28562449Speter name = strnames[np->nte_index]; 28662449Speter break; 28762449Speter } 28862449Speter } 28950276Speter#endif 29050276Speter 29162449Speter if ((status = tigetflag(name)) != -1) { 292166124Srafan return exit_code(BOOLEAN, status); 29362449Speter } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 29462449Speter (void) printf("%d\n", status); 295166124Srafan return exit_code(NUMBER, 0); 29662449Speter } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 297166124Srafan quit(4, "unknown terminfo capability '%s'", name); 29866963Speter } else if (s != ABSENT_STRING) { 29962449Speter if (argc > 1) { 30062449Speter int k; 301166124Srafan int popcount; 302166124Srafan long numbers[1 + NUM_PARM]; 303166124Srafan char *strings[1 + NUM_PARM]; 304166124Srafan char *p_is_s[NUM_PARM]; 30550276Speter 30662449Speter /* Nasty hack time. The tparm function needs to see numeric 30762449Speter * parameters as numbers, not as pointers to their string 30862449Speter * representations 30962449Speter */ 31050276Speter 31162449Speter for (k = 1; k < argc; k++) { 31266963Speter char *tmp = 0; 31366963Speter strings[k] = argv[k]; 31466963Speter numbers[k] = strtol(argv[k], &tmp, 0); 31566963Speter if (tmp == 0 || *tmp != 0) 31666963Speter numbers[k] = 0; 31762449Speter } 318166124Srafan for (k = argc; k <= NUM_PARM; k++) { 31966963Speter numbers[k] = 0; 32066963Speter strings[k] = 0; 32166963Speter } 32250276Speter 32366963Speter switch (tparm_type(name)) { 32466963Speter case Num_Str: 325166124Srafan s = TPARM_2(s, numbers[1], strings[2]); 32666963Speter break; 32766963Speter case Num_Str_Str: 328166124Srafan s = TPARM_3(s, numbers[1], strings[2], strings[3]); 32966963Speter break; 330174993Srafan case Numbers: 33166963Speter default: 332166124Srafan (void) _nc_tparm_analyze(s, p_is_s, &popcount); 333166124Srafan#define myParam(n) (p_is_s[n - 1] != 0 ? ((long) strings[n]) : numbers[n]) 334166124Srafan s = TPARM_9(s, 335166124Srafan myParam(1), 336166124Srafan myParam(2), 337166124Srafan myParam(3), 338166124Srafan myParam(4), 339166124Srafan myParam(5), 340166124Srafan myParam(6), 341166124Srafan myParam(7), 342166124Srafan myParam(8), 343166124Srafan myParam(9)); 34466963Speter break; 34566963Speter } 34650276Speter } 34762449Speter 34862449Speter /* use putp() in order to perform padding */ 34962449Speter putp(s); 350166124Srafan return exit_code(STRING, 0); 35162449Speter } 352166124Srafan return exit_code(STRING, 1); 35350276Speter} 35450276Speter 35562449Speterint 35662449Spetermain(int argc, char **argv) 35750276Speter{ 35866963Speter char *term; 35966963Speter int errret; 36066963Speter bool cmdline = TRUE; 36162449Speter int c; 36262449Speter char buf[BUFSIZ]; 363166124Srafan int result = 0; 36450276Speter 36597049Speter check_aliases(prg_name = _nc_rootname(argv[0])); 36650276Speter 36762449Speter term = getenv("TERM"); 36850276Speter 369174993Srafan while ((c = getopt(argc, argv, "ST:V")) != -1) { 37062449Speter switch (c) { 37162449Speter case 'S': 37266963Speter cmdline = FALSE; 37362449Speter break; 37462449Speter case 'T': 37562449Speter use_env(FALSE); 37662449Speter term = optarg; 37762449Speter break; 37866963Speter case 'V': 37966963Speter puts(curses_version()); 380166124Srafan ExitProgram(EXIT_SUCCESS); 38162449Speter default: 38262449Speter usage(); 38362449Speter /* NOTREACHED */ 38450276Speter } 38566963Speter } 38650276Speter 38766963Speter /* 38866963Speter * Modify the argument list to omit the options we processed. 38966963Speter */ 39066963Speter if (is_reset || is_init) { 39166963Speter if (optind-- < argc) { 39266963Speter argc -= optind; 39366963Speter argv += optind; 39466963Speter } 39566963Speter argv[0] = prg_name; 39666963Speter } else { 39766963Speter argc -= optind; 39866963Speter argv += optind; 39962449Speter } 40050276Speter 40162449Speter if (term == 0 || *term == '\0') 40262449Speter quit(2, "No value for $TERM and no -T specified"); 40350276Speter 40462449Speter if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 40562449Speter quit(3, "unknown terminal \"%s\"", term); 40650276Speter 40766963Speter if (cmdline) { 40866963Speter if ((argc <= 0) && !is_reset && !is_init) 40966963Speter usage(); 410166124Srafan ExitProgram(tput(argc, argv)); 41166963Speter } 41250276Speter 41362449Speter while (fgets(buf, sizeof(buf), stdin) != 0) { 41462449Speter char *argvec[16]; /* command, 9 parms, null, & slop */ 41562449Speter int argnum = 0; 41662449Speter char *cp; 41750276Speter 41862449Speter /* crack the argument list into a dope vector */ 41962449Speter for (cp = buf; *cp; cp++) { 42097049Speter if (isspace(UChar(*cp))) { 42162449Speter *cp = '\0'; 42297049Speter } else if (cp == buf || cp[-1] == 0) { 42362449Speter argvec[argnum++] = cp; 42497049Speter if (argnum >= (int) SIZEOF(argvec) - 1) 42597049Speter break; 42697049Speter } 42750276Speter } 42862449Speter argvec[argnum] = 0; 42950276Speter 43097049Speter if (argnum != 0 431166124Srafan && tput(argnum, argvec) != 0) { 432166124Srafan if (result == 0) 433166124Srafan result = 4; /* will return value >4 */ 434166124Srafan ++result; 435166124Srafan } 43662449Speter } 43762449Speter 438166124Srafan ExitProgram(result); 43950276Speter} 440