1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright (c) 2012 Gary Mills
  26  */
  27 
  28 /*      Copyright (c) 1988 AT&T     */
  29 /*        All Rights Reserved   */
  30 
  31 /*
  32  *      tput - print terminal attribute
  33  *
  34  *  return-codes - command line arguments:
  35  *      0: ok if boolean capname -> TRUE
  36  *      1: for boolean capname -> FALSE
  37  *
  38  *  return-codes - standard input arguments:
  39  *      0: ok; tput for all lines was successful
  40  *
  41  *  return-codes - both cases:
  42  *      2       usage error
  43  *      3       bad terminal type given or no terminfo database
  44  *      4       unknown capname
  45  *      -1      capname is a numeric variable that is not specified in the
  46  *              terminfo database(E.g. tpu -T450 lines).
  47  *
  48  *  tput printfs a value if an INT capname was given; e.g. cols.
  49  *      putp's a string if a STRING capname was given; e.g. clear. and
  50  *  for BOOLEAN capnames, e.g. hard-copy, just returns the boolean value.
  51  */
  52 
  53 #include <curses.h>
  54 #include <term.h>
  55 #include <fcntl.h>
  56 #include <ctype.h>
  57 #include <stdlib.h>
  58 #include <string.h>
  59 #include <sys/types.h>
  60 #include <unistd.h>
  61 #include <locale.h>
  62 
  63 /* externs from libcurses */
  64 extern int tigetnum();
  65 
  66 static int outputcap(char *cap, int argc, char **argv);
  67 static int allnumeric(char *string);
  68 static int getpad(char *cap);
  69 static void setdelay();
  70 static void settabs();
  71 static void cat(char *file);
  72 static void initterm();
  73 static void reset_term();
  74 
  75 static char *progname;          /* argv[0] */
  76 static int CurrentBaudRate;     /* current baud rate */
  77 static int reset = 0;           /* called as reset_term */
  78 static int fildes = 1;
  79 
  80 int
  81 main(int argc, char **argv)
  82 {
  83         int i, std_argc;
  84         char *term = getenv("TERM");
  85         char *cap, std_input = FALSE;
  86         int setuperr;
  87 
  88         (void) setlocale(LC_ALL, "");
  89 #if !defined(TEXT_DOMAIN)
  90 #define TEXT_DOMAIN "SYS_TEST"
  91 #endif
  92         (void) textdomain(TEXT_DOMAIN);
  93 
  94         progname = argv[0];
  95 
  96         while ((i = getopt(argc, argv, "ST:")) != EOF) {
  97                 switch (i) {
  98                 case 'T':
  99                         fildes = -1;
 100                         (void) putenv("LINES=");
 101                         (void) putenv("COLUMNS=");
 102                         term = optarg;
 103                         break;
 104 
 105                 case 'S':
 106                         std_input = TRUE;
 107                         break;
 108 
 109                 case '?':                       /* FALLTHROUGH          */
 110                 usage:                          /* FALLTHROUGH          */
 111                 default:
 112                         (void) fprintf(stderr, gettext(
 113                             "usage:\t%s [-T [term]] capname "
 114                             "[parm argument...]\n"), progname);
 115                         (void) fprintf(stderr, gettext("OR:\t%s -S <<\n"),
 116                             progname);
 117                         exit(2);
 118                 }
 119         }
 120 
 121         if (!term || !*term) {
 122                 (void) fprintf(stderr,
 123                     gettext("%s: No value for $TERM and no -T specified\n"),
 124                     progname);
 125                 exit(2);
 126         }
 127 
 128         (void) setupterm(term, fildes, &setuperr);
 129 
 130         switch (setuperr) {
 131         case -2:
 132                 (void) fprintf(stderr,
 133                     gettext("%s: unreadable terminal descriptor \"%s\"\n"),
 134                     progname, term);
 135                 exit(3);
 136                 break;
 137 
 138         case -1:
 139                 (void) fprintf(stderr,
 140                     gettext("%s: no terminfo database\n"), progname);
 141                 exit(3);
 142                 break;
 143 
 144         case 0:
 145                 (void) fprintf(stderr,
 146                     gettext("%s: unknown terminal \"%s\"\n"),
 147                     progname, term);
 148                 exit(3);
 149         }
 150 
 151         reset_shell_mode();
 152 
 153         /* command line arguments */
 154         if (!std_input) {
 155                 if (argc == optind)
 156                         goto usage;
 157 
 158                 cap = argv[optind++];
 159 
 160                 if (strcmp(cap, "init") == 0)
 161                         initterm();
 162                 else if (strcmp(cap, "reset") == 0)
 163                         reset_term();
 164                 else if (strcmp(cap, "longname") == 0)
 165                         (void) printf("%s\n", longname());
 166                 else
 167                         exit(outputcap(cap, argc, argv));
 168                 return (0);
 169         } else {                        /* standard input argumets      */
 170                 char buff[128];
 171                 char **v;
 172 
 173                 /* allocate storage for the 'faked' argv[] array        */
 174                 v = (char **)malloc(10 * sizeof (char *));
 175                 for (i = 0; i < 10; i++)
 176                         v[i] = (char *)malloc(32 * sizeof (char));
 177 
 178                 while (fgets(buff, sizeof (buff), stdin) != NULL) {
 179                         /* read standard input line; skip over empty lines */
 180                         if ((std_argc =
 181                             sscanf(buff,
 182                             "%31s %31s %31s %31s %31s %31s %31s %31s "
 183                             "%31s %31s",
 184                             v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
 185                             v[8], v[9])) < 1) {
 186                                 continue;
 187                         }
 188 
 189                         cap = v[0];
 190                         optind = 1;
 191 
 192                         if (strcmp(cap, "init") == 0) {
 193                                 initterm();
 194                         } else if (strcmp(cap, "reset") == 0) {
 195                                 reset_term();
 196                         } else if (strcmp(cap, "longname") == 0) {
 197                                 (void) printf("%s\n", longname());
 198                         } else {
 199                                 (void) outputcap(cap, std_argc, v);
 200                         }
 201                         (void) fflush(stdout);
 202                 }
 203 
 204                 return (0);
 205         }
 206 }
 207 
 208 static long parm[9] = {
 209     0, 0, 0, 0, 0, 0, 0, 0, 0
 210 };
 211 
 212 static int
 213 outputcap(char *cap, int argc, char **argv)
 214 {
 215         int parmset = 0;
 216         char *thisstr;
 217         int i;
 218 
 219         if ((i = tigetflag(cap)) >= 0)
 220                 return (1 - i);
 221 
 222         if ((i = tigetnum(cap)) >= -1) {
 223                 (void) printf("%d\n", i);
 224                 return (0);
 225         }
 226 
 227         if ((thisstr = tigetstr(cap)) != (char *)-1) {
 228                 if (!thisstr) {
 229                         return (1);
 230                 }
 231                 for (parmset = 0; optind < argc; optind++, parmset++)
 232                         if (allnumeric(argv[optind]))
 233                                 parm[parmset] = atoi(argv[optind]);
 234                         else
 235                                 parm[parmset] = (int)argv[optind];
 236 
 237                 if (parmset)
 238                         putp(tparm(thisstr,
 239                             parm[0], parm[1], parm[2], parm[3],
 240                             parm[4], parm[5], parm[6], parm[7], parm[8]));
 241                 else
 242                         putp(thisstr);
 243                 return (0);
 244         }
 245 
 246         (void) fprintf(stderr,
 247             gettext("%s: unknown terminfo capability '%s'\n"), progname, cap);
 248 
 249         exit(4);
 250         /* NOTREACHED */
 251 }
 252 
 253 /*
 254  *  The decision as to whether an argument is a number or not is to simply
 255  *  look at whether there are any non-digits in the string.
 256  */
 257 static int
 258 allnumeric(char *string)
 259 {
 260         if (*string) {
 261                 while (*string) {
 262                         if (!isdigit(*string++)) {
 263                                 return (0);
 264                         }
 265                 }
 266                 return (1);
 267         } else {
 268                 return (0);
 269         }
 270 }
 271 
 272 /*
 273  *  SYSTEM DEPENDENT TERMINAL DELAY TABLES
 274  *
 275  *      These tables maintain the correspondence between the delays
 276  *      defined in terminfo and the delay algorithms in the tty driver
 277  *      on the particular systems. For each type of delay, the bits used
 278  *      for that delay must be specified, in XXbits, and a table
 279  *      must be defined giving correspondences between delays and
 280  *      algorithms. Algorithms which are not fixed delays, such
 281  *      as dependent on current column or line number, must be
 282  *      kludged in some way at this time.
 283  *
 284  *      Some of this was taken from tset(1).
 285  */
 286 
 287 struct delay
 288 {
 289     int d_delay;
 290     int d_bits;
 291 };
 292 
 293 /* The appropriate speeds for various termio settings. */
 294 static int speeds[] = {
 295                 0,      /*  B0,         */
 296                 50,     /*  B50,        */
 297                 75,     /*  B75,        */
 298                 110,    /*  B110,       */
 299                 134,    /*  B134,       */
 300                 150,    /*  B150,       */
 301                 200,    /*  B200,       */
 302                 300,    /*  B300,       */
 303                 600,    /*  B600,       */
 304                 1200,   /*  B1200,      */
 305                 1800,   /*  B1800,      */
 306                 2400,   /*  B2400,      */
 307                 4800,   /*  B4800,      */
 308                 9600,   /*  B9600,      */
 309                 19200,  /*  EXTA,       */
 310                 38400,  /*  EXTB,       */
 311                 57600,  /*  B57600,     */
 312                 76800,  /*  B76800,     */
 313                 115200, /*  B115200,    */
 314                 153600, /*  B153600,    */
 315                 230400, /*  B230400,    */
 316                 307200, /*  B307200,    */
 317                 460800, /*  B460800,    */
 318                 921600, /*  B921600,    */
 319                 0,
 320 };
 321 
 322 #if defined(SYSV) || defined(USG)
 323 /*      Unix 3.0 on up */
 324 
 325 /*    Carriage Return delays    */
 326 
 327 static int      CRbits = CRDLY;
 328 static struct delay     CRdelay[] =
 329 {
 330         0,      CR0,
 331         80,     CR1,
 332         100,    CR2,
 333         150,    CR3,
 334         -1
 335 };
 336 
 337 /*      New Line delays */
 338 
 339 static int      NLbits = NLDLY;
 340 static struct delay     NLdelay[] =
 341 {
 342         0,      NL0,
 343         100,    NL1,
 344         -1
 345 };
 346 
 347 /*      Back Space delays       */
 348 
 349 static int      BSbits = BSDLY;
 350 static struct delay     BSdelay[] =
 351 {
 352         0,      BS0,
 353         50,     BS1,
 354         -1
 355 };
 356 
 357 /*      TaB delays      */
 358 
 359 static int      TBbits = TABDLY;
 360 static struct delay     TBdelay[] =
 361 {
 362         0,      TAB0,
 363         11,     TAB1,           /* special M37 delay */
 364         100,    TAB2,
 365                                 /* TAB3 is XTABS and not a delay */
 366         -1
 367 };
 368 
 369 /*      Form Feed delays        */
 370 
 371 static int      FFbits = FFDLY;
 372 static struct delay     FFdelay[] =
 373 {
 374         0,      FF0,
 375         2000,   FF1,
 376         -1
 377 };
 378 
 379 #else   /* BSD */
 380 
 381 /*      Carriage Return delays  */
 382 
 383 int     CRbits = CRDELAY;
 384 struct delay    CRdelay[] =
 385 {
 386         0,      CR0,
 387         9,      CR3,
 388         80,     CR1,
 389         160,    CR2,
 390         -1
 391 };
 392 
 393 /*      New Line delays */
 394 
 395 int     NLbits = NLDELAY;
 396 struct delay    NLdelay[] =
 397 {
 398         0,      NL0,
 399         66,     NL1,            /* special M37 delay */
 400         100,    NL2,
 401         -1
 402 };
 403 
 404 /*      Tab delays      */
 405 
 406 int     TBbits = TBDELAY;
 407 struct delay    TBdelay[] =
 408 {
 409         0,      TAB0,
 410         11,     TAB1,           /* special M37 delay */
 411         -1
 412 };
 413 
 414 /*      Form Feed delays        */
 415 
 416 int     FFbits = VTDELAY;
 417 struct delay    FFdelay[] =
 418 {
 419         0,      FF0,
 420         2000,   FF1,
 421         -1
 422 };
 423 #endif  /* BSD */
 424 
 425 /*
 426  *  Initterm, a.k.a. reset_term, does terminal specific initialization. In
 427  *  particular, the init_strings from terminfo are output and tabs are
 428  *  set, if they aren't hardwired in. Much of this stuff was done by
 429  *  the tset(1) program.
 430  */
 431 
 432 /*
 433  *  Figure out how many milliseconds of padding the capability cap
 434  *  needs and return that number. Padding is stored in the string as "$<n>",
 435  *  where n is the number of milliseconds of padding. More than one
 436  *  padding string is allowed within the string, although this is unlikely.
 437  */
 438 
 439 static int
 440 getpad(char *cap)
 441 {
 442         int padding = 0;
 443 
 444         /* No padding needed at speeds below padding_baud_rate */
 445         if (padding_baud_rate > CurrentBaudRate || cap == NULL)
 446                 return (0);
 447 
 448         while (*cap) {
 449                 if ((cap[0] == '$') && (cap[1] == '<')) {
 450                         cap++;
 451                         cap++;
 452                         padding += atoi(cap);
 453                         while (isdigit (*cap))
 454                                 cap++;
 455                         while (*cap == '.' || *cap == '/' || *cap == '*' ||
 456                             isdigit(*cap))
 457                                 cap++;
 458                         while (*cap == '>')
 459                                 cap++;
 460                 } else {
 461                         cap++;
 462                 }
 463         }
 464 
 465         return (padding);
 466 }
 467 
 468 /*
 469  *  Set the appropriate delay bits in the termio structure for
 470  *  the given delay.
 471  */
 472 static void
 473 setdelay(delay, delaytable, bits, flags)
 474 register int delay;
 475 struct delay delaytable[];
 476 int bits;
 477 #ifdef SYSV
 478 tcflag_t *flags;
 479 #else   /* SYSV */
 480 unsigned short *flags;
 481 #endif  /* SYSV */
 482 {
 483         register struct delay  *p;
 484         register struct delay  *lastdelay;
 485 
 486         /* Clear out the bits, replace with new ones */
 487         *flags &= ~bits;
 488 
 489         /* Scan the delay table for first entry with adequate delay */
 490         for (lastdelay = p = delaytable;
 491             (p -> d_delay >= 0) && (p -> d_delay < delay);
 492             p++) {
 493                 lastdelay = p;
 494         }
 495 
 496         /* use last entry if none will do */
 497         *flags |= lastdelay -> d_bits;
 498 }
 499 
 500 /*
 501  * Set the hardware tabs on the terminal, using clear_all_tabs,
 502  * set_tab, and column_address capabilities. Cursor_address and cursor_right
 503  * may also be used, if necessary.
 504  * This is done before the init_file and init_3string, so they can patch in
 505  * case we blow this.
 506  */
 507 
 508 static void
 509 settabs()
 510 {
 511         register int c;
 512 
 513         /* Do not set tabs if they power up properly. */
 514         if (init_tabs == 8)
 515                 return;
 516 
 517         if (set_tab) {
 518                 /* Force the cursor to be at the left margin. */
 519                 if (carriage_return)
 520                         putp(carriage_return);
 521                 else
 522                         (void) putchar('\r');
 523 
 524                 /* Clear any current tab settings. */
 525                 if (clear_all_tabs)
 526                         putp(clear_all_tabs);
 527 
 528                 /* Set the tabs. */
 529                 for (c = 8; c < columns; c += 8) {
 530                         /* Get to that column. */
 531                         (void) fputs("        ", stdout);
 532 
 533                         /* Set the tab. */
 534                         putp(set_tab);
 535                 }
 536 
 537                 /* Get back to the left column. */
 538                 if (carriage_return)
 539                         putp(carriage_return);
 540                 else
 541                         (void) putchar('\r');
 542 
 543         }
 544 }
 545 
 546 /*
 547  *  Copy "file" onto standard output.
 548  */
 549 
 550 static void
 551 cat(file)
 552 char *file;                             /* File to copy. */
 553 {
 554         register int fd;                        /* File descriptor. */
 555         register ssize_t i;                     /* Number characters read. */
 556         char buf[BUFSIZ];                       /* Buffer to read into. */
 557 
 558         fd = open(file, O_RDONLY);
 559 
 560         if (fd < 0) {
 561                 perror("Cannot open initialization file");
 562         } else {
 563                 while ((i = read(fd, buf, BUFSIZ)) > (ssize_t)0)
 564                         (void) write(fileno(stdout), buf, (unsigned)i);
 565                 (int)close(fd);
 566         }
 567 }
 568 
 569 /*
 570  *  Initialize the terminal.
 571  *  Send the initialization strings to the terminal.
 572  */
 573 
 574 static void
 575 initterm()
 576 {
 577         register int filedes;           /* File descriptor for ioctl's. */
 578 #if defined(SYSV) || defined(USG)
 579         struct termio termmode;         /* To hold terminal settings. */
 580         struct termios termmodes;       /* To hold terminal settings. */
 581         int i;
 582         int istermios = -1;
 583 #define GTTY(fd, mode)  ioctl(fd, TCGETA, mode)
 584 #define GTTYS(fd, mode) \
 585         (istermios = ioctl(fd, TCGETS, mode))
 586 #define STTY(fd, mode)  ioctl(fd, TCSETAW, mode)
 587 #define STTYS(fd, mode) ioctl(fd, TCSETSW, mode)
 588 #define SPEED(mode)     (mode.c_cflag & CBAUD)
 589 #define SPEEDS(mode)    (cfgetospeed(&mode))
 590 #define OFLAG(mode)     mode.c_oflag
 591 #else   /* BSD */
 592         struct sgttyb termmode;         /* To hold terminal settings. */
 593 #define GTTY(fd, mode)  gtty(fd, mode)
 594 #define STTY(fd, mode)  stty(fd, mode)
 595 #define SPEED(mode)     (mode.sg_ospeed & 017)
 596 #define OFLAG(mode)     mode.sg_flags
 597 #define TAB3            XTABS
 598 #endif
 599 
 600         /* Get the terminal settings. */
 601         /* First try standard output, then standard error, */
 602         /* then standard input, then /dev/tty. */
 603 #ifdef SYSV
 604         if ((filedes = 1, GTTYS(filedes, &termmodes) < 0) ||
 605             (filedes = 2, GTTYS(filedes, &termmodes) < 0) ||
 606             (filedes = 0, GTTYS(filedes, &termmodes) < 0) ||
 607             (filedes = open("/dev/tty", O_RDWR),
 608             GTTYS(filedes, &termmodes) < 0)) {
 609 #endif  /* SYSV */
 610                 if ((filedes = 1, GTTY(filedes, &termmode) == -1) ||
 611                     (filedes = 2, GTTY(filedes, &termmode) == -1) ||
 612                     (filedes = 0, GTTY(filedes, &termmode) == -1) ||
 613                     (filedes = open("/dev/tty", O_RDWR),
 614                     GTTY(filedes, &termmode) == -1)) {
 615                         filedes = -1;
 616                         CurrentBaudRate = speeds[B1200];
 617                 } else
 618                         CurrentBaudRate = speeds[SPEED(termmode)];
 619 #ifdef SYSV
 620                 termmodes.c_lflag = termmode.c_lflag;
 621                 termmodes.c_oflag = termmode.c_oflag;
 622                 termmodes.c_iflag = termmode.c_iflag;
 623                 termmodes.c_cflag = termmode.c_cflag;
 624                 for (i = 0; i < NCC; i++)
 625                         termmodes.c_cc[i] = termmode.c_cc[i];
 626         } else
 627                 CurrentBaudRate = speeds[SPEEDS(termmodes)];
 628 #endif  /* SYSV */
 629 
 630         if (xon_xoff) {
 631 #ifdef SYSV
 632                 OFLAG(termmodes) &=
 633                     ~(NLbits | CRbits | BSbits | FFbits | TBbits);
 634 #else   /* SYSV */
 635                 OFLAG(termmode) &=
 636                     ~(NLbits | CRbits | BSbits | FFbits | TBbits);
 637 #endif  /* SYSV */
 638         } else {
 639 #ifdef SYSV
 640                 setdelay(getpad(carriage_return),
 641                     CRdelay, CRbits, &OFLAG(termmodes));
 642                 setdelay(getpad(scroll_forward),
 643                     NLdelay, NLbits, &OFLAG(termmodes));
 644                 setdelay(getpad(cursor_left),
 645                     BSdelay, BSbits, &OFLAG(termmodes));
 646                 setdelay(getpad(form_feed),
 647                     FFdelay, FFbits, &OFLAG(termmodes));
 648                 setdelay(getpad(tab),
 649                     TBdelay, TBbits, &OFLAG(termmodes));
 650 #else   /* SYSV */
 651                 setdelay(getpad(carriage_return),
 652                     CRdelay, CRbits, &OFLAG(termmode));
 653                 setdelay(getpad(scroll_forward),
 654                     NLdelay, NLbits, &OFLAG(termmode));
 655                 setdelay(getpad(cursor_left),
 656                     BSdelay, BSbits, &OFLAG(termmode));
 657                 setdelay(getpad(form_feed),
 658                     FFdelay, FFbits, &OFLAG(termmode));
 659                 setdelay(getpad(tab),
 660                     TBdelay, TBbits, &OFLAG(termmode));
 661 #endif  /* SYSV */
 662         }
 663 
 664         /* If tabs can be sent to the tty, turn off their expansion. */
 665         if (tab && set_tab || init_tabs == 8) {
 666 #ifdef SYSV
 667                 OFLAG(termmodes) &= ~(TAB3);
 668 #else   /* SYSV */
 669                 OFLAG(termmode) &= ~(TAB3);
 670 #endif  /* SYSV */
 671         } else {
 672 #ifdef SYSV
 673                 OFLAG(termmodes) |= TAB3;
 674 #else   /* SYSV */
 675                 OFLAG(termmode) |= TAB3;
 676 #endif  /* SYSV */
 677         }
 678 
 679         /* Do the changes to the terminal settings */
 680 #ifdef SYSV
 681         if (istermios < 0) {
 682                 int i;
 683 
 684                 termmode.c_lflag = termmodes.c_lflag;
 685                 termmode.c_oflag = termmodes.c_oflag;
 686                 termmode.c_iflag = termmodes.c_iflag;
 687                 termmode.c_cflag = termmodes.c_cflag;
 688                 for (i = 0; i < NCC; i++)
 689                         termmode.c_cc[i] = termmodes.c_cc[i];
 690                 (void) STTY(filedes, &termmode);
 691         } else
 692                 (void) STTYS(filedes, &termmodes);
 693 
 694 #else   /* SYSV */
 695         (void) STTY(filedes, &termmode);
 696 #endif  /* SYSV */
 697 
 698         /* Send first initialization strings. */
 699         if (init_prog)
 700         (void) system(init_prog);
 701 
 702         if (reset && reset_1string) {
 703                 putp(reset_1string);
 704         } else if (init_1string) {
 705                 putp(init_1string);
 706         }
 707 
 708         if (reset && reset_2string) {
 709                 putp(reset_2string);
 710         } else if (init_2string) {
 711                 putp(init_2string);
 712         }
 713 
 714         /* Set up the tabs stops. */
 715         settabs();
 716 
 717         /* Send out initializing file. */
 718         if (reset && reset_file) {
 719                 cat(reset_file);
 720         } else if (init_file) {
 721                 cat(init_file);
 722         }
 723 
 724         /* Send final initialization strings. */
 725         if (reset && reset_3string) {
 726                 putp(reset_3string);
 727         } else if (init_3string) {
 728                 putp(init_3string);
 729         }
 730 
 731         if (carriage_return) {
 732                 putp(carriage_return);
 733         } else {
 734                 (void) putchar('\r');
 735         }
 736 
 737         /* Send color initialization strings */
 738 
 739         if (orig_colors)
 740                 putp(orig_colors);
 741 
 742         if (orig_pair)
 743         putp(orig_pair);
 744 
 745         /* Let the terminal settle down. */
 746         (void) fflush(stdout);
 747         (void) sleep(1);
 748 }
 749 
 750 static void
 751 reset_term()
 752 {
 753         reset++;
 754         initterm();
 755 }