1 /**************************************************************************** 2 * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /**************************************************************************** 30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32 * and: Thomas E. Dickey 1996-on * 33 ****************************************************************************/ 34 35 /* 36 * tput.c -- shellscript access to terminal capabilities 37 * 38 * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from 39 * Ross Ridge's mytinfo package. 40 */ 41 42 #include <tparm_type.h> 43 44 #if !PURE_TERMINFO 45 #include <dump_entry.h> 46 #include <termsort.c> 47 #endif 48 #include <transform.h> 49 50 MODULE_ID("$Id: tput.c,v 1.51 2015/05/23 23:42:55 tom Exp $") 51 52 #define PUTS(s) fputs(s, stdout) 53 #define PUTCHAR(c) putchar(c) 54 #define FLUSH fflush(stdout) 55 56 static char *prg_name; 57 static bool is_init = FALSE; 58 static bool is_reset = FALSE; 59 60 static void 61 quit(int status, const char *fmt,...) 62 { 63 va_list argp; 64 65 va_start(argp, fmt); 66 fprintf(stderr, "%s: ", prg_name); 67 vfprintf(stderr, fmt, argp); 68 fprintf(stderr, "\n"); 69 va_end(argp); 70 ExitProgram(status); 71 } 72 73 static void 74 usage(void) 75 { 76 fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name); 77 ExitProgram(EXIT_FAILURE); 78 } 79 80 static void 81 check_aliases(const char *name) 82 { 83 is_init = same_program(name, PROG_INIT); 84 is_reset = same_program(name, PROG_RESET); 85 } 86 87 static int 88 exit_code(int token, int value) 89 { 90 int result = 99; 91 92 switch (token) { 93 case BOOLEAN: 94 result = !value; /* TRUE=0, FALSE=1 */ 95 break; 96 case NUMBER: 97 result = 0; /* always zero */ 98 break; 99 case STRING: 100 result = value; /* 0=normal, 1=missing */ 101 break; 102 } 103 return result; 104 } 105 106 static int 107 tput(int argc, char *argv[]) 108 { 109 NCURSES_CONST char *name; 110 char *s; 111 int i, j, c; 112 int status; 113 FILE *f; 114 #if !PURE_TERMINFO 115 bool termcap = FALSE; 116 #endif 117 118 if ((name = argv[0]) == 0) 119 name = ""; 120 check_aliases(name); 121 if (is_reset || is_init) { 122 if (init_prog != 0) { 123 IGNORE_RC(system(init_prog)); 124 } 125 FLUSH; 126 127 if (is_reset && reset_1string != 0) { 128 PUTS(reset_1string); 129 } else if (init_1string != 0) { 130 PUTS(init_1string); 131 } 132 FLUSH; 133 134 if (is_reset && reset_2string != 0) { 135 PUTS(reset_2string); 136 } else if (init_2string != 0) { 137 PUTS(init_2string); 138 } 139 FLUSH; 140 141 #ifdef set_lr_margin 142 if (set_lr_margin != 0) { 143 PUTS(TPARM_2(set_lr_margin, 0, columns - 1)); 144 } else 145 #endif 146 #ifdef set_left_margin_parm 147 if (set_left_margin_parm != 0 148 && set_right_margin_parm != 0) { 149 PUTS(TPARM_1(set_left_margin_parm, 0)); 150 PUTS(TPARM_1(set_right_margin_parm, columns - 1)); 151 } else 152 #endif 153 if (clear_margins != 0 154 && set_left_margin != 0 155 && set_right_margin != 0) { 156 PUTS(clear_margins); 157 if (carriage_return != 0) { 158 PUTS(carriage_return); 159 } else { 160 PUTCHAR('\r'); 161 } 162 PUTS(set_left_margin); 163 if (parm_right_cursor) { 164 PUTS(TPARM_1(parm_right_cursor, columns - 1)); 165 } else { 166 for (i = 0; i < columns - 1; i++) { 167 PUTCHAR(' '); 168 } 169 } 170 PUTS(set_right_margin); 171 if (carriage_return != 0) { 172 PUTS(carriage_return); 173 } else { 174 PUTCHAR('\r'); 175 } 176 } 177 FLUSH; 178 179 if (init_tabs != 8) { 180 if (clear_all_tabs != 0 && set_tab != 0) { 181 for (i = 0; i < columns - 1; i += 8) { 182 if (parm_right_cursor) { 183 PUTS(TPARM_1(parm_right_cursor, 8)); 184 } else { 185 for (j = 0; j < 8; j++) 186 PUTCHAR(' '); 187 } 188 PUTS(set_tab); 189 } 190 FLUSH; 191 } 192 } 193 194 if (is_reset && reset_file != 0) { 195 f = fopen(reset_file, "r"); 196 if (f == 0) { 197 quit(4 + errno, "Can't open reset_file: '%s'", reset_file); 198 } 199 while ((c = fgetc(f)) != EOF) { 200 PUTCHAR(c); 201 } 202 fclose(f); 203 } else if (init_file != 0) { 204 f = fopen(init_file, "r"); 205 if (f == 0) { 206 quit(4 + errno, "Can't open init_file: '%s'", init_file); 207 } 208 while ((c = fgetc(f)) != EOF) { 209 PUTCHAR(c); 210 } 211 fclose(f); 212 } 213 FLUSH; 214 215 if (is_reset && reset_3string != 0) { 216 PUTS(reset_3string); 217 } else if (init_3string != 0) { 218 PUTS(init_3string); 219 } 220 FLUSH; 221 return 0; 222 } 223 224 if (strcmp(name, "longname") == 0) { 225 PUTS(longname()); 226 return 0; 227 } 228 #if !PURE_TERMINFO 229 retry: 230 #endif 231 if ((status = tigetflag(name)) != -1) { 232 return exit_code(BOOLEAN, status); 233 } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { 234 (void) printf("%d\n", status); 235 return exit_code(NUMBER, 0); 236 } else if ((s = tigetstr(name)) == CANCELLED_STRING) { 237 #if !PURE_TERMINFO 238 if (!termcap) { 239 const struct name_table_entry *np; 240 241 termcap = TRUE; 242 if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) { 243 switch (np->nte_type) { 244 case BOOLEAN: 245 if (bool_from_termcap[np->nte_index]) 246 name = boolnames[np->nte_index]; 247 break; 248 249 case NUMBER: 250 if (num_from_termcap[np->nte_index]) 251 name = numnames[np->nte_index]; 252 break; 253 254 case STRING: 255 if (str_from_termcap[np->nte_index]) 256 name = strnames[np->nte_index]; 257 break; 258 } 259 goto retry; 260 } 261 } 262 #endif 263 quit(4, "unknown terminfo capability '%s'", name); 264 } else if (s != ABSENT_STRING) { 265 if (argc > 1) { 266 int k; 267 int ignored; 268 long numbers[1 + NUM_PARM]; 269 char *strings[1 + NUM_PARM]; 270 char *p_is_s[NUM_PARM]; 271 272 /* Nasty hack time. The tparm function needs to see numeric 273 * parameters as numbers, not as pointers to their string 274 * representations 275 */ 276 277 for (k = 1; k < argc; k++) { 278 char *tmp = 0; 279 strings[k] = argv[k]; 280 numbers[k] = strtol(argv[k], &tmp, 0); 281 if (tmp == 0 || *tmp != 0) 282 numbers[k] = 0; 283 } 284 for (k = argc; k <= NUM_PARM; k++) { 285 numbers[k] = 0; 286 strings[k] = 0; 287 } 288 289 switch (tparm_type(name)) { 290 case Num_Str: 291 s = TPARM_2(s, numbers[1], strings[2]); 292 break; 293 case Num_Str_Str: 294 s = TPARM_3(s, numbers[1], strings[2], strings[3]); 295 break; 296 case Numbers: 297 default: 298 (void) _nc_tparm_analyze(s, p_is_s, &ignored); 299 #define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n]) 300 s = TPARM_9(s, 301 myParam(1), 302 myParam(2), 303 myParam(3), 304 myParam(4), 305 myParam(5), 306 myParam(6), 307 myParam(7), 308 myParam(8), 309 myParam(9)); 310 break; 311 } 312 } 313 314 /* use putp() in order to perform padding */ 315 putp(s); 316 return exit_code(STRING, 0); 317 } 318 return exit_code(STRING, 1); 319 } 320 321 int 322 main(int argc, char **argv) 323 { 324 char *term; 325 int errret; 326 bool cmdline = TRUE; 327 int c; 328 char buf[BUFSIZ]; 329 int result = 0; 330 331 check_aliases(prg_name = _nc_rootname(argv[0])); 332 333 term = getenv("TERM"); 334 335 while ((c = getopt(argc, argv, "ST:V")) != -1) { 336 switch (c) { 337 case 'S': 338 cmdline = FALSE; 339 break; 340 case 'T': 341 use_env(FALSE); 342 term = optarg; 343 break; 344 case 'V': 345 puts(curses_version()); 346 ExitProgram(EXIT_SUCCESS); 347 default: 348 usage(); 349 /* NOTREACHED */ 350 } 351 } 352 353 /* 354 * Modify the argument list to omit the options we processed. 355 */ 356 if (is_reset || is_init) { 357 if (optind-- < argc) { 358 argc -= optind; 359 argv += optind; 360 } 361 argv[0] = prg_name; 362 } else { 363 argc -= optind; 364 argv += optind; 365 } 366 367 if (term == 0 || *term == '\0') 368 quit(2, "No value for $TERM and no -T specified"); 369 370 if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) 371 quit(3, "unknown terminal \"%s\"", term); 372 373 if (cmdline) { 374 if ((argc <= 0) && !is_reset && !is_init) 375 usage(); 376 ExitProgram(tput(argc, argv)); 377 } 378 379 while (fgets(buf, sizeof(buf), stdin) != 0) { 380 char *argvec[16]; /* command, 9 parms, null, & slop */ 381 int argnum = 0; 382 char *cp; 383 384 /* crack the argument list into a dope vector */ 385 for (cp = buf; *cp; cp++) { 386 if (isspace(UChar(*cp))) { 387 *cp = '\0'; 388 } else if (cp == buf || cp[-1] == 0) { 389 argvec[argnum++] = cp; 390 if (argnum >= (int) SIZEOF(argvec) - 1) 391 break; 392 } 393 } 394 argvec[argnum] = 0; 395 396 if (argnum != 0 397 && tput(argnum, argvec) != 0) { 398 if (result == 0) 399 result = 4; /* will return value >4 */ 400 ++result; 401 } 402 } 403 404 ExitProgram(result); 405 } 406