tput.c revision 66963
1195333Simp/**************************************************************************** 2195333Simp * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * 3195333Simp * * 4195333Simp * Permission is hereby granted, free of charge, to any person obtaining a * 5195333Simp * copy of this software and associated documentation files (the * 6195333Simp * "Software"), to deal in the Software without restriction, including * 7195333Simp * without limitation the rights to use, copy, modify, merge, publish, * 8195333Simp * distribute, distribute with modifications, sublicense, and/or sell * 9195333Simp * copies of the Software, and to permit persons to whom the Software is * 10195333Simp * furnished to do so, subject to the following conditions: * 11195333Simp * * 12195333Simp * The above copyright notice and this permission notice shall be included * 13195333Simp * in all copies or substantial portions of the Software. * 14195333Simp * * 15195333Simp * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16195333Simp * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17195333Simp * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18195333Simp * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19195333Simp * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20195333Simp * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21195333Simp * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22195333Simp * * 23195333Simp * Except as contained in this notice, the name(s) of the above copyright * 24195333Simp * holders shall not be used in advertising or otherwise to promote the * 25195333Simp * sale, use or other dealings in this Software without prior written * 26195333Simp * authorization. * 27195333Simp ****************************************************************************/ 28195333Simp 29195333Simp/**************************************************************************** 30195333Simp * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31195333Simp * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32195333Simp ****************************************************************************/ 33195333Simp 34195333Simp/* 35195333Simp * tput.c -- shellscript access to terminal capabilities 36195333Simp * 37195333Simp * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from 38195333Simp * Ross Ridge's mytinfo package. 39195333Simp */ 40195333Simp 41195333Simp#include <progs.priv.h> 42195333Simp 43195333Simp#if !PURE_TERMINFO 44195333Simp#include <termsort.c> 45195333Simp#endif 46195333Simp#include <transform.h> 47195333Simp 48195333SimpMODULE_ID("$Id: tput.c,v 1.24 2000/10/05 00:05:04 tom Exp $") 49195333Simp 50195333Simp#define PUTS(s) fputs(s, stdout) 51195333Simp#define PUTCHAR(c) putchar(c) 52195333Simp#define FLUSH fflush(stdout) 53195333Simp 54195333Simptypedef enum { 55195333Simp Numbers = 0 56195333Simp ,Num_Str 57195333Simp ,Num_Str_Str 58195333Simp} TParams; 59195333Simp 60195333Simpstatic char *prg_name; 61195333Simpstatic bool is_init = FALSE; 62195333Simpstatic bool is_reset = FALSE; 63195333Simp 64195333Simpstatic void 65195333Simpquit(int status, const char *fmt,...) 66195333Simp{ 67195333Simp va_list argp; 68195333Simp 69195333Simp va_start(argp, fmt); 70195333Simp vfprintf(stderr, fmt, argp); 71195333Simp fprintf(stderr, "\n"); 72195333Simp va_end(argp); 73195333Simp exit(status); 74195333Simp} 75195333Simp 76195333Simpstatic void 77195333Simpusage(void) 78195333Simp{ 79195333Simp fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name); 80195333Simp exit(EXIT_FAILURE); 81195333Simp} 82195333Simp 83195333Simpstatic void 84195333Simpcheck_aliases(const char *name) 85195333Simp{ 86195333Simp is_init = (strcmp(name, PROG_INIT) == 0); 87195333Simp is_reset = (strcmp(name, PROG_RESET) == 0); 88195333Simp} 89195333Simp 90195333Simp/* 91195333Simp * Lookup the type of call we should make to tparm(). This ignores the actual 92195333Simp * terminfo capability (bad, because it is not extensible), but makes this 93195333Simp * code portable to platforms where sizeof(int) != sizeof(char *). 94195333Simp * 95195333Simp * FIXME: If we want extensibility, analyze the capability string as we do 96203000Sneel * in tparm() to decide how to parse the varargs list. 97203000Sneel */ 98198669Srrsstatic TParams 99198669Srrstparm_type(char *name) 100198669Srrs{ 101198669Srrs#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc} 102198669Srrs TParams result = Numbers; 103198669Srrs /* *INDENT-OFF* */ 104195333Simp static const struct { 105195333Simp TParams code; 106195333Simp const char *name; 107195333Simp } table[] = { 108195333Simp TD(Num_Str, "pkey_key", "pfkey", "pk"), 109195333Simp TD(Num_Str, "pkey_local", "pfloc", "pl"), 110195333Simp TD(Num_Str, "pkey_xmit", "pfx", "px"), 111195333Simp TD(Num_Str, "plab_norm", "pln", "pn"), 112195333Simp TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), 113195333Simp }; 114195333Simp /* *INDENT-ON* */ 115195333Simp 116195333Simp unsigned n; 117195333Simp for (n = 0; n < SIZEOF(table); n++) { 118195333Simp if (!strcmp(name, table[n].name)) { 119195333Simp result = table[n].code; 120195333Simp break; 121195333Simp } 122195333Simp } 123195333Simp return result; 124195333Simp} 125195333Simp 126195333Simpstatic int 127195333Simptput(int argc, char *argv[]) 128195333Simp{ 129195333Simp NCURSES_CONST char *name; 130195333Simp char *s; 131195333Simp int i, j, c; 132195333Simp int status; 133195333Simp FILE *f; 134195333Simp 135195333Simp check_aliases(name = argv[0]); 136195333Simp if (is_reset || is_init) { 137195333Simp if (init_prog != 0) { 138195333Simp system(init_prog); 139195333Simp } 140195333Simp FLUSH; 141195333Simp 142195333Simp if (is_reset && reset_1string != 0) { 143195333Simp PUTS(reset_1string); 144195333Simp } else if (init_1string != 0) { 145195333Simp PUTS(init_1string); 146195333Simp } 147195333Simp FLUSH; 148195333Simp 149195333Simp if (is_reset && reset_2string != 0) { 150195333Simp PUTS(reset_2string); 151195333Simp } else if (init_2string != 0) { 152195333Simp PUTS(init_2string); 153195333Simp } 154195333Simp FLUSH; 155195333Simp 156195333Simp if (set_lr_margin != 0) { 157195333Simp PUTS(tparm(set_lr_margin, 0, columns - 1)); 158195333Simp } else if (set_left_margin_parm != 0 159195333Simp && set_right_margin_parm != 0) { 160195333Simp PUTS(tparm(set_left_margin_parm, 0)); 161195333Simp PUTS(tparm(set_right_margin_parm, columns - 1)); 162195333Simp } else if (clear_margins != 0 163195333Simp && set_left_margin != 0 164195333Simp && set_right_margin != 0) { 165195333Simp PUTS(clear_margins); 166195333Simp if (carriage_return != 0) { 167195333Simp PUTS(carriage_return); 168195333Simp } else { 169195333Simp PUTCHAR('\r'); 170195333Simp } 171195333Simp PUTS(set_left_margin); 172195333Simp if (parm_right_cursor) { 173195333Simp PUTS(tparm(parm_right_cursor, columns - 1)); 174202954Sgonzo } else { 175195333Simp for (i = 0; i < columns - 1; i++) { 176195333Simp PUTCHAR(' '); 177195333Simp } 178195333Simp } 179195333Simp PUTS(set_right_margin); 180195333Simp if (carriage_return != 0) { 181195333Simp PUTS(carriage_return); 182195333Simp } else { 183195333Simp PUTCHAR('\r'); 184195333Simp } 185195333Simp } 186195333Simp FLUSH; 187195333Simp 188203000Sneel if (init_tabs != 8) { 189203000Sneel if (clear_all_tabs != 0 && set_tab != 0) { 190203000Sneel for (i = 0; i < columns - 1; i += 8) { 191203000Sneel if (parm_right_cursor) { 192203000Sneel PUTS(tparm(parm_right_cursor, 8)); 193203000Sneel } else { 194203000Sneel for (j = 0; j < 8; j++) 195203000Sneel PUTCHAR(' '); 196203000Sneel } 197203000Sneel PUTS(set_tab); 198203000Sneel } 199203000Sneel FLUSH; 200203000Sneel } 201203000Sneel } 202203000Sneel 203203000Sneel if (is_reset && reset_file != 0) { 204203000Sneel f = fopen(reset_file, "r"); 205203000Sneel if (f == 0) { 206203000Sneel quit(errno, "Can't open reset_file: '%s'", reset_file); 207203000Sneel } 208203000Sneel while ((c = fgetc(f)) != EOF) { 209203000Sneel PUTCHAR(c); 210195333Simp } 211195333Simp fclose(f); 212195333Simp } else if (init_file != 0) { 213195333Simp f = fopen(init_file, "r"); 214195333Simp if (f == 0) { 215195333Simp quit(errno, "Can't open init_file: '%s'", init_file); 216195333Simp } 217195333Simp while ((c = fgetc(f)) != EOF) { 218195333Simp PUTCHAR(c); 219195333Simp } 220195333Simp fclose(f); 221195333Simp } 222195333Simp FLUSH; 223195333Simp 224195333Simp if (is_reset && reset_3string != 0) { 225195333Simp PUTS(reset_3string); 226195333Simp } else if (init_2string != 0) { 227195333Simp PUTS(init_2string); 228195333Simp } 229195333Simp FLUSH; 230195333Simp return 0; 231195333Simp } 232195333Simp 233195333Simp if (strcmp(name, "longname") == 0) { 234195333Simp PUTS(longname()); 235195333Simp return 0; 236195333Simp } 237195333Simp#if !PURE_TERMINFO 238195333Simp { 239195333Simp const struct name_table_entry *np; 240195333Simp 241195333Simp if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0) 242195333Simp switch (np->nte_type) { 243195333Simp case BOOLEAN: 244195333Simp if (bool_from_termcap[np->nte_index]) 245195333Simp name = boolnames[np->nte_index]; 246195333Simp break; 247195333Simp 248195333Simp case NUMBER: 249195333Simp if (num_from_termcap[np->nte_index]) 250195333Simp name = numnames[np->nte_index]; 251195333Simp break; 252195333Simp 253195333Simp case STRING: 254195333Simp if (str_from_termcap[np->nte_index]) 255195333Simp name = strnames[np->nte_index]; 256195333Simp break; 257202864Sneel } 258202864Sneel } 259202864Sneel#endif 260202864Sneel 261202864Sneel if ((status = tigetflag(name)) != -1) { 262202864Sneel return (status != 0); 263202864Sneel } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 264202864Sneel (void) printf("%d\n", status); 265202864Sneel return (0); 266202864Sneel } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 267202864Sneel quit(4, "%s: unknown terminfo capability '%s'", prg_name, name); 268202864Sneel } else if (s != ABSENT_STRING) { 269195333Simp if (argc > 1) { 270201631Sneel int k; 271201631Sneel int numbers[10]; 272195333Simp char *strings[10]; 273202864Sneel 274202864Sneel /* Nasty hack time. The tparm function needs to see numeric 275202864Sneel * parameters as numbers, not as pointers to their string 276202864Sneel * representations 277202864Sneel */ 278195333Simp 279195333Simp for (k = 1; k < argc; k++) { 280202954Sgonzo char *tmp = 0; 281195333Simp strings[k] = argv[k]; 282201845Simp numbers[k] = strtol(argv[k], &tmp, 0); 283201881Simp if (tmp == 0 || *tmp != 0) 284201845Simp numbers[k] = 0; 285195333Simp } 286195333Simp for (k = argc; k <= 9; k++) { 287195333Simp numbers[k] = 0; 288195333Simp strings[k] = 0; 289201631Sneel } 290201631Sneel 291201631Sneel switch (tparm_type(name)) { 292201631Sneel case Num_Str: 293201631Sneel s = tparm(s, numbers[1], strings[2]); 294195333Simp break; 295201631Sneel case Num_Str_Str: 296201631Sneel s = tparm(s, numbers[1], strings[2], strings[3]); 297195333Simp break; 298195333Simp default: 299195333Simp s = tparm(s, 300195333Simp numbers[1], numbers[2], numbers[3], 301195333Simp numbers[4], numbers[5], numbers[6], 302195333Simp numbers[7], numbers[8], numbers[9]); 303195333Simp break; 304 } 305 } 306 307 /* use putp() in order to perform padding */ 308 putp(s); 309 return (0); 310 } 311 return (0); 312} 313 314int 315main(int argc, char **argv) 316{ 317 char *term; 318 int errret; 319 bool cmdline = TRUE; 320 int c; 321 char buf[BUFSIZ]; 322 int errors = 0; 323 324 check_aliases(prg_name = _nc_basename(argv[0])); 325 326 term = getenv("TERM"); 327 328 while ((c = getopt(argc, argv, "ST:V")) != EOF) { 329 switch (c) { 330 case 'S': 331 cmdline = FALSE; 332 break; 333 case 'T': 334 use_env(FALSE); 335 term = optarg; 336 break; 337 case 'V': 338 puts(curses_version()); 339 return EXIT_SUCCESS; 340 default: 341 usage(); 342 /* NOTREACHED */ 343 } 344 } 345 346 /* 347 * Modify the argument list to omit the options we processed. 348 */ 349 if (is_reset || is_init) { 350 if (optind-- < argc) { 351 argc -= optind; 352 argv += optind; 353 } 354 argv[0] = prg_name; 355 } else { 356 argc -= optind; 357 argv += optind; 358 } 359 360 if (term == 0 || *term == '\0') 361 quit(2, "No value for $TERM and no -T specified"); 362 363 if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 364 quit(3, "unknown terminal \"%s\"", term); 365 366 if (cmdline) { 367 if ((argc <= 0) && !is_reset && !is_init) 368 usage(); 369 return tput(argc, argv); 370 } 371 372 while (fgets(buf, sizeof(buf), stdin) != 0) { 373 char *argvec[16]; /* command, 9 parms, null, & slop */ 374 int argnum = 0; 375 char *cp; 376 377 /* crack the argument list into a dope vector */ 378 for (cp = buf; *cp; cp++) { 379 if (isspace(*cp)) 380 *cp = '\0'; 381 else if (cp == buf || cp[-1] == 0) 382 argvec[argnum++] = cp; 383 } 384 argvec[argnum] = 0; 385 386 if (tput(argnum, argvec) != 0) 387 errors++; 388 } 389 390 return errors > 0; 391} 392