tput.c revision 97049
150276Speter/**************************************************************************** 297049Speter * Copyright (c) 1998,1999,2000,2001 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 4897049SpeterMODULE_ID("$Id: tput.c,v 1.30 2001/07/22 00:16:33 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); 7062449Speter vfprintf(stderr, fmt, argp); 7162449Speter fprintf(stderr, "\n"); 7262449Speter va_end(argp); 7362449Speter exit(status); 7450276Speter} 7550276Speter 7662449Speterstatic void 7762449Speterusage(void) 7850276Speter{ 7966963Speter fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name); 8062449Speter exit(EXIT_FAILURE); 8150276Speter} 8250276Speter 8366963Speterstatic void 8466963Spetercheck_aliases(const char *name) 8566963Speter{ 8666963Speter is_init = (strcmp(name, PROG_INIT) == 0); 8766963Speter is_reset = (strcmp(name, PROG_RESET) == 0); 8866963Speter} 8966963Speter 9066963Speter/* 9166963Speter * Lookup the type of call we should make to tparm(). This ignores the actual 9266963Speter * terminfo capability (bad, because it is not extensible), but makes this 9366963Speter * code portable to platforms where sizeof(int) != sizeof(char *). 9466963Speter * 9566963Speter * FIXME: If we want extensibility, analyze the capability string as we do 9666963Speter * in tparm() to decide how to parse the varargs list. 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 12762449Spetertput(int argc, char *argv[]) 12850276Speter{ 12962449Speter NCURSES_CONST char *name; 13062449Speter char *s; 13162449Speter int i, j, c; 13266963Speter int status; 13362449Speter FILE *f; 13450276Speter 13597049Speter if ((name = argv[0]) == 0) 13697049Speter name = ""; 13797049Speter check_aliases(name); 13866963Speter if (is_reset || is_init) { 13962449Speter if (init_prog != 0) { 14062449Speter system(init_prog); 14150276Speter } 14262449Speter FLUSH; 14350276Speter 14466963Speter if (is_reset && reset_1string != 0) { 14562449Speter PUTS(reset_1string); 14662449Speter } else if (init_1string != 0) { 14762449Speter PUTS(init_1string); 14862449Speter } 14962449Speter FLUSH; 15050276Speter 15166963Speter if (is_reset && reset_2string != 0) { 15262449Speter PUTS(reset_2string); 15362449Speter } else if (init_2string != 0) { 15462449Speter PUTS(init_2string); 15562449Speter } 15662449Speter FLUSH; 15750276Speter 15897049Speter#ifdef set_lr_margin 15962449Speter if (set_lr_margin != 0) { 16062449Speter PUTS(tparm(set_lr_margin, 0, columns - 1)); 16197049Speter } else 16297049Speter#endif 16397049Speter#ifdef set_left_margin_parm 16497049Speter if (set_left_margin_parm != 0 16597049Speter && set_right_margin_parm != 0) { 16662449Speter PUTS(tparm(set_left_margin_parm, 0)); 16762449Speter PUTS(tparm(set_right_margin_parm, columns - 1)); 16897049Speter } else 16997049Speter#endif 17097049Speter if (clear_margins != 0 17197049Speter && set_left_margin != 0 17297049Speter && set_right_margin != 0) { 17362449Speter PUTS(clear_margins); 17462449Speter if (carriage_return != 0) { 17562449Speter PUTS(carriage_return); 17662449Speter } else { 17762449Speter PUTCHAR('\r'); 17862449Speter } 17962449Speter PUTS(set_left_margin); 18062449Speter if (parm_right_cursor) { 18162449Speter PUTS(tparm(parm_right_cursor, columns - 1)); 18262449Speter } else { 18362449Speter for (i = 0; i < columns - 1; i++) { 18462449Speter PUTCHAR(' '); 18550276Speter } 18662449Speter } 18762449Speter PUTS(set_right_margin); 18862449Speter if (carriage_return != 0) { 18962449Speter PUTS(carriage_return); 19062449Speter } else { 19162449Speter PUTCHAR('\r'); 19262449Speter } 19362449Speter } 19462449Speter FLUSH; 19550276Speter 19662449Speter if (init_tabs != 8) { 19762449Speter if (clear_all_tabs != 0 && set_tab != 0) { 19862449Speter for (i = 0; i < columns - 1; i += 8) { 19962449Speter if (parm_right_cursor) { 20062449Speter PUTS(tparm(parm_right_cursor, 8)); 20162449Speter } else { 20262449Speter for (j = 0; j < 8; j++) 20362449Speter PUTCHAR(' '); 20462449Speter } 20562449Speter PUTS(set_tab); 20650276Speter } 20750276Speter FLUSH; 20862449Speter } 20962449Speter } 21050276Speter 21166963Speter if (is_reset && reset_file != 0) { 21262449Speter f = fopen(reset_file, "r"); 21362449Speter if (f == 0) { 21462449Speter quit(errno, "Can't open reset_file: '%s'", reset_file); 21562449Speter } 21662449Speter while ((c = fgetc(f)) != EOF) { 21762449Speter PUTCHAR(c); 21862449Speter } 21962449Speter fclose(f); 22062449Speter } else if (init_file != 0) { 22162449Speter f = fopen(init_file, "r"); 22262449Speter if (f == 0) { 22362449Speter quit(errno, "Can't open init_file: '%s'", init_file); 22462449Speter } 22562449Speter while ((c = fgetc(f)) != EOF) { 22662449Speter PUTCHAR(c); 22762449Speter } 22862449Speter fclose(f); 22950276Speter } 23062449Speter FLUSH; 23150276Speter 23266963Speter if (is_reset && reset_3string != 0) { 23362449Speter PUTS(reset_3string); 23462449Speter } else if (init_2string != 0) { 23562449Speter PUTS(init_2string); 23650276Speter } 23762449Speter FLUSH; 23862449Speter return 0; 23962449Speter } 24050276Speter 24162449Speter if (strcmp(name, "longname") == 0) { 24262449Speter PUTS(longname()); 24362449Speter return 0; 24462449Speter } 24566963Speter#if !PURE_TERMINFO 24662449Speter { 24762449Speter const struct name_table_entry *np; 24850276Speter 24962449Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0) 25062449Speter switch (np->nte_type) { 25162449Speter case BOOLEAN: 25262449Speter if (bool_from_termcap[np->nte_index]) 25362449Speter name = boolnames[np->nte_index]; 25462449Speter break; 25550276Speter 25662449Speter case NUMBER: 25762449Speter if (num_from_termcap[np->nte_index]) 25862449Speter name = numnames[np->nte_index]; 25962449Speter break; 26050276Speter 26162449Speter case STRING: 26262449Speter if (str_from_termcap[np->nte_index]) 26362449Speter name = strnames[np->nte_index]; 26462449Speter break; 26562449Speter } 26662449Speter } 26750276Speter#endif 26850276Speter 26962449Speter if ((status = tigetflag(name)) != -1) { 27062449Speter return (status != 0); 27162449Speter } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 27262449Speter (void) printf("%d\n", status); 27362449Speter return (0); 27462449Speter } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 27562449Speter quit(4, "%s: unknown terminfo capability '%s'", prg_name, name); 27666963Speter } else if (s != ABSENT_STRING) { 27762449Speter if (argc > 1) { 27862449Speter int k; 27966963Speter int numbers[10]; 28066963Speter char *strings[10]; 28150276Speter 28262449Speter /* Nasty hack time. The tparm function needs to see numeric 28362449Speter * parameters as numbers, not as pointers to their string 28462449Speter * representations 28562449Speter */ 28650276Speter 28762449Speter for (k = 1; k < argc; k++) { 28866963Speter char *tmp = 0; 28966963Speter strings[k] = argv[k]; 29066963Speter numbers[k] = strtol(argv[k], &tmp, 0); 29166963Speter if (tmp == 0 || *tmp != 0) 29266963Speter numbers[k] = 0; 29362449Speter } 29466963Speter for (k = argc; k <= 9; k++) { 29566963Speter numbers[k] = 0; 29666963Speter strings[k] = 0; 29766963Speter } 29850276Speter 29966963Speter switch (tparm_type(name)) { 30066963Speter case Num_Str: 30166963Speter s = tparm(s, numbers[1], strings[2]); 30266963Speter break; 30366963Speter case Num_Str_Str: 30466963Speter s = tparm(s, numbers[1], strings[2], strings[3]); 30566963Speter break; 30666963Speter default: 30766963Speter s = tparm(s, 30866963Speter numbers[1], numbers[2], numbers[3], 30966963Speter numbers[4], numbers[5], numbers[6], 31066963Speter numbers[7], numbers[8], numbers[9]); 31166963Speter break; 31266963Speter } 31350276Speter } 31462449Speter 31562449Speter /* use putp() in order to perform padding */ 31662449Speter putp(s); 31762449Speter return (0); 31862449Speter } 31962449Speter return (0); 32050276Speter} 32150276Speter 32262449Speterint 32362449Spetermain(int argc, char **argv) 32450276Speter{ 32566963Speter char *term; 32666963Speter int errret; 32766963Speter bool cmdline = TRUE; 32862449Speter int c; 32962449Speter char buf[BUFSIZ]; 33062449Speter int errors = 0; 33150276Speter 33297049Speter check_aliases(prg_name = _nc_rootname(argv[0])); 33350276Speter 33462449Speter term = getenv("TERM"); 33550276Speter 33666963Speter while ((c = getopt(argc, argv, "ST:V")) != EOF) { 33762449Speter switch (c) { 33862449Speter case 'S': 33966963Speter cmdline = FALSE; 34062449Speter break; 34162449Speter case 'T': 34262449Speter use_env(FALSE); 34362449Speter term = optarg; 34462449Speter break; 34566963Speter case 'V': 34666963Speter puts(curses_version()); 34766963Speter return EXIT_SUCCESS; 34862449Speter default: 34962449Speter usage(); 35062449Speter /* NOTREACHED */ 35150276Speter } 35266963Speter } 35350276Speter 35466963Speter /* 35566963Speter * Modify the argument list to omit the options we processed. 35666963Speter */ 35766963Speter if (is_reset || is_init) { 35866963Speter if (optind-- < argc) { 35966963Speter argc -= optind; 36066963Speter argv += optind; 36166963Speter } 36266963Speter argv[0] = prg_name; 36366963Speter } else { 36466963Speter argc -= optind; 36566963Speter argv += optind; 36662449Speter } 36750276Speter 36862449Speter if (term == 0 || *term == '\0') 36962449Speter quit(2, "No value for $TERM and no -T specified"); 37050276Speter 37162449Speter if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 37262449Speter quit(3, "unknown terminal \"%s\"", term); 37350276Speter 37466963Speter if (cmdline) { 37566963Speter if ((argc <= 0) && !is_reset && !is_init) 37666963Speter usage(); 37762449Speter return tput(argc, argv); 37866963Speter } 37950276Speter 38062449Speter while (fgets(buf, sizeof(buf), stdin) != 0) { 38162449Speter char *argvec[16]; /* command, 9 parms, null, & slop */ 38262449Speter int argnum = 0; 38362449Speter char *cp; 38450276Speter 38562449Speter /* crack the argument list into a dope vector */ 38662449Speter for (cp = buf; *cp; cp++) { 38797049Speter if (isspace(UChar(*cp))) { 38862449Speter *cp = '\0'; 38997049Speter } else if (cp == buf || cp[-1] == 0) { 39062449Speter argvec[argnum++] = cp; 39197049Speter if (argnum >= (int) SIZEOF(argvec) - 1) 39297049Speter break; 39397049Speter } 39450276Speter } 39562449Speter argvec[argnum] = 0; 39650276Speter 39797049Speter if (argnum != 0 39897049Speter && tput(argnum, argvec) != 0) 39962449Speter errors++; 40062449Speter } 40162449Speter 40262449Speter return errors > 0; 40350276Speter} 404