tput.c revision 262629
150276Speter/**************************************************************************** 2262629Sdelphij * Copyright (c) 1998-2009,2010 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 50262629SdelphijMODULE_ID("$Id: tput.c,v 1.46 2010/01/09 16:53:24 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 * 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; 156262629Sdelphij#if !PURE_TERMINFO 157262629Sdelphij bool termcap = FALSE; 158262629Sdelphij#endif 15950276Speter 16097049Speter if ((name = argv[0]) == 0) 16197049Speter name = ""; 16297049Speter check_aliases(name); 16366963Speter if (is_reset || is_init) { 16462449Speter if (init_prog != 0) { 16562449Speter system(init_prog); 16650276Speter } 16762449Speter FLUSH; 16850276Speter 16966963Speter if (is_reset && reset_1string != 0) { 17062449Speter PUTS(reset_1string); 17162449Speter } else if (init_1string != 0) { 17262449Speter PUTS(init_1string); 17362449Speter } 17462449Speter FLUSH; 17550276Speter 17666963Speter if (is_reset && reset_2string != 0) { 17762449Speter PUTS(reset_2string); 17862449Speter } else if (init_2string != 0) { 17962449Speter PUTS(init_2string); 18062449Speter } 18162449Speter FLUSH; 18250276Speter 18397049Speter#ifdef set_lr_margin 18462449Speter if (set_lr_margin != 0) { 185166124Srafan PUTS(TPARM_2(set_lr_margin, 0, columns - 1)); 18697049Speter } else 18797049Speter#endif 18897049Speter#ifdef set_left_margin_parm 18997049Speter if (set_left_margin_parm != 0 19097049Speter && set_right_margin_parm != 0) { 191166124Srafan PUTS(TPARM_1(set_left_margin_parm, 0)); 192166124Srafan PUTS(TPARM_1(set_right_margin_parm, columns - 1)); 19397049Speter } else 19497049Speter#endif 19597049Speter if (clear_margins != 0 19697049Speter && set_left_margin != 0 19797049Speter && set_right_margin != 0) { 19862449Speter PUTS(clear_margins); 19962449Speter if (carriage_return != 0) { 20062449Speter PUTS(carriage_return); 20162449Speter } else { 20262449Speter PUTCHAR('\r'); 20362449Speter } 20462449Speter PUTS(set_left_margin); 20562449Speter if (parm_right_cursor) { 206166124Srafan PUTS(TPARM_1(parm_right_cursor, columns - 1)); 20762449Speter } else { 20862449Speter for (i = 0; i < columns - 1; i++) { 20962449Speter PUTCHAR(' '); 21050276Speter } 21162449Speter } 21262449Speter PUTS(set_right_margin); 21362449Speter if (carriage_return != 0) { 21462449Speter PUTS(carriage_return); 21562449Speter } else { 21662449Speter PUTCHAR('\r'); 21762449Speter } 21862449Speter } 21962449Speter FLUSH; 22050276Speter 22162449Speter if (init_tabs != 8) { 22262449Speter if (clear_all_tabs != 0 && set_tab != 0) { 22362449Speter for (i = 0; i < columns - 1; i += 8) { 22462449Speter if (parm_right_cursor) { 225166124Srafan PUTS(TPARM_1(parm_right_cursor, 8)); 22662449Speter } else { 22762449Speter for (j = 0; j < 8; j++) 22862449Speter PUTCHAR(' '); 22962449Speter } 23062449Speter PUTS(set_tab); 23150276Speter } 23250276Speter FLUSH; 23362449Speter } 23462449Speter } 23550276Speter 23666963Speter if (is_reset && reset_file != 0) { 23762449Speter f = fopen(reset_file, "r"); 23862449Speter if (f == 0) { 239166124Srafan quit(4 + errno, "Can't open reset_file: '%s'", reset_file); 24062449Speter } 24162449Speter while ((c = fgetc(f)) != EOF) { 24262449Speter PUTCHAR(c); 24362449Speter } 24462449Speter fclose(f); 24562449Speter } else if (init_file != 0) { 24662449Speter f = fopen(init_file, "r"); 24762449Speter if (f == 0) { 248166124Srafan quit(4 + errno, "Can't open init_file: '%s'", init_file); 24962449Speter } 25062449Speter while ((c = fgetc(f)) != EOF) { 25162449Speter PUTCHAR(c); 25262449Speter } 25362449Speter fclose(f); 25450276Speter } 25562449Speter FLUSH; 25650276Speter 25766963Speter if (is_reset && reset_3string != 0) { 25862449Speter PUTS(reset_3string); 259166124Srafan } else if (init_3string != 0) { 260166124Srafan PUTS(init_3string); 26150276Speter } 26262449Speter FLUSH; 26362449Speter return 0; 26462449Speter } 26550276Speter 26662449Speter if (strcmp(name, "longname") == 0) { 26762449Speter PUTS(longname()); 26862449Speter return 0; 26962449Speter } 27066963Speter#if !PURE_TERMINFO 271262629Sdelphij retry: 27250276Speter#endif 27362449Speter if ((status = tigetflag(name)) != -1) { 274166124Srafan return exit_code(BOOLEAN, status); 27562449Speter } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 27662449Speter (void) printf("%d\n", status); 277166124Srafan return exit_code(NUMBER, 0); 27862449Speter } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 279262629Sdelphij#if !PURE_TERMINFO 280262629Sdelphij if (!termcap) { 281262629Sdelphij const struct name_table_entry *np; 282262629Sdelphij 283262629Sdelphij termcap = TRUE; 284262629Sdelphij if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) { 285262629Sdelphij switch (np->nte_type) { 286262629Sdelphij case BOOLEAN: 287262629Sdelphij if (bool_from_termcap[np->nte_index]) 288262629Sdelphij name = boolnames[np->nte_index]; 289262629Sdelphij break; 290262629Sdelphij 291262629Sdelphij case NUMBER: 292262629Sdelphij if (num_from_termcap[np->nte_index]) 293262629Sdelphij name = numnames[np->nte_index]; 294262629Sdelphij break; 295262629Sdelphij 296262629Sdelphij case STRING: 297262629Sdelphij if (str_from_termcap[np->nte_index]) 298262629Sdelphij name = strnames[np->nte_index]; 299262629Sdelphij break; 300262629Sdelphij } 301262629Sdelphij goto retry; 302262629Sdelphij } 303262629Sdelphij } 304262629Sdelphij#endif 305166124Srafan quit(4, "unknown terminfo capability '%s'", name); 30666963Speter } else if (s != ABSENT_STRING) { 30762449Speter if (argc > 1) { 30862449Speter int k; 309166124Srafan int popcount; 310166124Srafan long numbers[1 + NUM_PARM]; 311166124Srafan char *strings[1 + NUM_PARM]; 312166124Srafan char *p_is_s[NUM_PARM]; 31350276Speter 31462449Speter /* Nasty hack time. The tparm function needs to see numeric 31562449Speter * parameters as numbers, not as pointers to their string 31662449Speter * representations 31762449Speter */ 31850276Speter 31962449Speter for (k = 1; k < argc; k++) { 32066963Speter char *tmp = 0; 32166963Speter strings[k] = argv[k]; 32266963Speter numbers[k] = strtol(argv[k], &tmp, 0); 32366963Speter if (tmp == 0 || *tmp != 0) 32466963Speter numbers[k] = 0; 32562449Speter } 326166124Srafan for (k = argc; k <= NUM_PARM; k++) { 32766963Speter numbers[k] = 0; 32866963Speter strings[k] = 0; 32966963Speter } 33050276Speter 33166963Speter switch (tparm_type(name)) { 33266963Speter case Num_Str: 333166124Srafan s = TPARM_2(s, numbers[1], strings[2]); 33466963Speter break; 33566963Speter case Num_Str_Str: 336166124Srafan s = TPARM_3(s, numbers[1], strings[2], strings[3]); 33766963Speter break; 338174993Srafan case Numbers: 33966963Speter default: 340166124Srafan (void) _nc_tparm_analyze(s, p_is_s, &popcount); 341166124Srafan#define myParam(n) (p_is_s[n - 1] != 0 ? ((long) strings[n]) : numbers[n]) 342166124Srafan s = TPARM_9(s, 343166124Srafan myParam(1), 344166124Srafan myParam(2), 345166124Srafan myParam(3), 346166124Srafan myParam(4), 347166124Srafan myParam(5), 348166124Srafan myParam(6), 349166124Srafan myParam(7), 350166124Srafan myParam(8), 351166124Srafan myParam(9)); 35266963Speter break; 35366963Speter } 35450276Speter } 35562449Speter 35662449Speter /* use putp() in order to perform padding */ 35762449Speter putp(s); 358166124Srafan return exit_code(STRING, 0); 35962449Speter } 360166124Srafan return exit_code(STRING, 1); 36150276Speter} 36250276Speter 36362449Speterint 36462449Spetermain(int argc, char **argv) 36550276Speter{ 36666963Speter char *term; 36766963Speter int errret; 36866963Speter bool cmdline = TRUE; 36962449Speter int c; 37062449Speter char buf[BUFSIZ]; 371166124Srafan int result = 0; 37250276Speter 37397049Speter check_aliases(prg_name = _nc_rootname(argv[0])); 37450276Speter 37562449Speter term = getenv("TERM"); 37650276Speter 377174993Srafan while ((c = getopt(argc, argv, "ST:V")) != -1) { 37862449Speter switch (c) { 37962449Speter case 'S': 38066963Speter cmdline = FALSE; 38162449Speter break; 38262449Speter case 'T': 38362449Speter use_env(FALSE); 38462449Speter term = optarg; 38562449Speter break; 38666963Speter case 'V': 38766963Speter puts(curses_version()); 388166124Srafan ExitProgram(EXIT_SUCCESS); 38962449Speter default: 39062449Speter usage(); 39162449Speter /* NOTREACHED */ 39250276Speter } 39366963Speter } 39450276Speter 39566963Speter /* 39666963Speter * Modify the argument list to omit the options we processed. 39766963Speter */ 39866963Speter if (is_reset || is_init) { 39966963Speter if (optind-- < argc) { 40066963Speter argc -= optind; 40166963Speter argv += optind; 40266963Speter } 40366963Speter argv[0] = prg_name; 40466963Speter } else { 40566963Speter argc -= optind; 40666963Speter argv += optind; 40762449Speter } 40850276Speter 40962449Speter if (term == 0 || *term == '\0') 41062449Speter quit(2, "No value for $TERM and no -T specified"); 41150276Speter 41262449Speter if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 41362449Speter quit(3, "unknown terminal \"%s\"", term); 41450276Speter 41566963Speter if (cmdline) { 41666963Speter if ((argc <= 0) && !is_reset && !is_init) 41766963Speter usage(); 418166124Srafan ExitProgram(tput(argc, argv)); 41966963Speter } 42050276Speter 42162449Speter while (fgets(buf, sizeof(buf), stdin) != 0) { 42262449Speter char *argvec[16]; /* command, 9 parms, null, & slop */ 42362449Speter int argnum = 0; 42462449Speter char *cp; 42550276Speter 42662449Speter /* crack the argument list into a dope vector */ 42762449Speter for (cp = buf; *cp; cp++) { 42897049Speter if (isspace(UChar(*cp))) { 42962449Speter *cp = '\0'; 43097049Speter } else if (cp == buf || cp[-1] == 0) { 43162449Speter argvec[argnum++] = cp; 43297049Speter if (argnum >= (int) SIZEOF(argvec) - 1) 43397049Speter break; 43497049Speter } 43550276Speter } 43662449Speter argvec[argnum] = 0; 43750276Speter 43897049Speter if (argnum != 0 439166124Srafan && tput(argnum, argvec) != 0) { 440166124Srafan if (result == 0) 441166124Srafan result = 4; /* will return value >4 */ 442166124Srafan ++result; 443166124Srafan } 44462449Speter } 44562449Speter 446166124Srafan ExitProgram(result); 44750276Speter} 448