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, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1988 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 /*
  31  * University Copyright- Copyright (c) 1982, 1986, 1988
  32  * The Regents of the University of California
  33  * All Rights Reserved
  34  *
  35  * University Acknowledgment- Portions of this document are derived from
  36  * software developed by the University of California, Berkeley, and its
  37  * contributors.
  38  */
  39 
  40 #pragma ident   "%Z%%M% %I%     %E% SMI"
  41 
  42 /*LINTLIBRARY*/
  43 
  44 #include        <stdio.h>
  45 #include        <sys/types.h>
  46 #include        <fcntl.h>
  47 #include        <stdlib.h>
  48 #include        <string.h>
  49 #include        <unistd.h>
  50 #include        <errno.h>
  51 #include        "curses_inc.h"
  52 
  53 #define TERMPATH        "/usr/share/lib/terminfo/"
  54 #define TERMPATHLEN     512
  55 
  56 extern  bool    _use_env;       /* in curses.c */
  57 
  58 chtype  bit_attributes[NUM_ATTRIBUTES] = {
  59             A_STANDOUT,
  60             A_UNDERLINE,
  61             A_ALTCHARSET,
  62             A_REVERSE,
  63             A_BLINK,
  64             A_DIM,
  65             A_BOLD,
  66             A_INVIS,
  67             A_PROTECT
  68         };
  69 
  70 char    *Def_term = "unknown",  /* default terminal type */
  71         term_parm_err[32], ttytype[BUFSIZ], _frst_tblstr[1400];
  72 
  73 TERMINAL                _first_term, *cur_term = &_first_term;
  74 struct  _bool_struct    _frst_bools, *cur_bools = &_frst_bools;
  75 struct  _num_struct     _frst_nums, *cur_nums = &_frst_nums;
  76 struct  _str_struct     _frst_strs, *cur_strs = &_frst_strs;
  77 
  78 /* _called_before is used/cleared by delterm.c and restart.c */
  79 char    _called_before = 0;
  80 short   term_errno = -1;
  81 
  82 #ifdef SYSV
  83 int     prog_istermios = -1;
  84 int     shell_istermios = -1;
  85 #endif
  86 
  87 #ifdef  DUMPTI
  88 extern  char    *boolfnames[], *boolnames[], *boolcodes[],
  89                 *numfnames[], *numnames[], *numcodes[],
  90                 *strfnames[], *strnames[], *strcodes[];
  91 
  92 main(int argc, char **argv)     /* FOR DEBUG ONLY */
  93 {
  94         if (argc > 1)
  95                 setupterm(argv[1], 1, (int *)0);
  96         else
  97                 setupterm((char *)0, 1, (int *)0);
  98         return (0);
  99 }
 100 
 101 _Pr(int ch)     /* FOR DEBUG ONLY */
 102 {
 103         if (ch >= 0200) {
 104                 printf("M-");
 105                 ch -= 0200;
 106         }
 107         if ((ch < ' ') || (ch == 0177))
 108                 printf("^%c", ch ^ 0100);
 109         else
 110                 printf("%c", ch);
 111 }
 112 
 113 _Sprint(int n, char *string)    /* FOR DEBUG ONLY */
 114 {
 115         int     ch;
 116 
 117         if (n == -1) {
 118                 printf(".\n");
 119                 return;
 120         }
 121         printf(", string = '");
 122         while (ch = *string++)
 123                 _Pr(ch&0377);
 124 
 125         printf("'.\n");
 126 }
 127 
 128 _Mprint(int n, char *memory)    /* FOR DEBUG ONLY */
 129 {
 130         unsigned        char    ch;
 131 
 132         while (ch = *memory++, n-- > 0)
 133                 _Pr(ch&0377);
 134 }
 135 
 136 #define _Vr2getshi()    _Vr2getsh(ip-2)
 137 
 138 #if     vax || pdp11
 139 #define _Vr2getsh(ip)   (* (short *)(ip))
 140 #endif  /* vax || pdp11 */
 141 
 142 #ifndef _Vr2getsh
 143 /*
 144  * Here is a more portable version, which does not assume byte ordering
 145  * in shorts, sign extension, etc.
 146  */
 147 _Vr2getsh(char *p)
 148 {
 149         int     rv;
 150 
 151         if (*p == (char)0377)
 152                 return (-1);
 153         rv = (unsigned char) *p++;
 154         rv += (unsigned char) *p * 256;
 155         return (rv);
 156 }
 157 #endif  /* _Vr2getsh */
 158 
 159 #endif  /* DUMPTI */
 160 
 161 #define _Getshi()       _Getsh(ip); ip += 2
 162 
 163 /*
 164  * "function" to get a short from a pointer.  The short is in a standard
 165  * format: two bytes, the first is the low order byte, the second is
 166  * the high order byte (base 256).  The only negative numbers allowed are
 167  * -1 and -2, which are represented as 255,255 and 255,254  This format
 168  * happens to be the same as the hardware on the pdp-11, vax, and 386,
 169  * making it fast and convenient and small to do this on a pdp-11.
 170  */
 171 
 172 #if     vax || pdp11 || i386
 173 #define _Getsh(ip)      (* (short *)ip)
 174 #endif  /* vax || pdp11 */
 175 /*
 176  * The following macro is partly due to Mike Laman, laman@sdcsvax
 177  *      NCR @ Torrey Pines.             - Tony Hansen
 178  */
 179 #if     u3b || u3b15 || u3b2 || m68000
 180 #define _Getsh(ip)      ((short)(*((unsigned char *)ip) | (*(ip+1) << 8)))
 181 #endif  /* u3b || u3b15 || u3b2 || m68000 */
 182 
 183 #ifndef _Getsh
 184 /*
 185  * Here is a more portable version, which does not assume byte ordering
 186  * in shorts, sign extension, etc.  For the sake of the porters,
 187  * two alternative implementations, for the machines that don't have
 188  * casting to "unsigned char", are also given, but commented out.
 189  * Not ANSI C implementation assumes that the * C preprocessor does
 190  * sign-extension the same as on the machine being compiled for.
 191  */
 192 static int
 193 _Getsh(char *p)
 194 {
 195         int     rv, rv2;
 196 
 197         rv  = (unsigned char) p[0];
 198         rv2 = (unsigned char) p[1];
 199 
 200         /* the following stuff is only for porting.  See the comment above */
 201 
 202 #ifdef FOR_PORTING
 203 #if    CHAR_MIN < 0
 204         rv = (*p++) & 0377;
 205         rv2 = (*p) & 0377;
 206 #else   /* CHAR_MIN < 0 */
 207         rv = *p++;
 208         rv2 = *p;
 209 #endif  /* CHAR_MIN < 0 */
 210 
 211 #endif  /* FOR_PORTING  */
 212 
 213         if ((rv2 == 0377) && ((rv == 0377) || (rv == 0376)))
 214                 return (-1);
 215         return (rv + (rv2 * 256));
 216 }
 217 #endif  /* _Getsh */
 218 
 219 /*
 220  * setupterm: low level routine to dig up terminfo from database
 221  * and read it in.  Parms are terminal type (0 means use getenv("TERM"),
 222  * file descriptor all output will go to (for ioctls), and a pointer
 223  * to an int into which the error return code goes (0 means to bomb
 224  * out with an error message if there's an error).  Thus,
 225  * setupterm((char *)0, 1, (int *)0) is a reasonable way for a simple
 226  * program to set up.
 227  */
 228 int
 229 setupterm(char *term, int filenum, int *errret)
 230         /* filenum - This is a UNIX file descriptor, not a stdio ptr. */
 231 {
 232         char    tiebuf[4096];
 233         char    fname[TERMPATHLEN];
 234         char    *ip;
 235         char    *cp;
 236         int     n, tfd;
 237         char    *lcp, *ccp, **on_sequences, **str_array;
 238         int     snames, nbools, nints, nstrs, sstrtab;
 239         char    *strtab;
 240 #ifdef  DUMPTI
 241         int             Vr2val;
 242 #endif  /* DUMPTI */
 243 
 244         (void) mbgetwidth();
 245 
 246         if (term == NULL)
 247                 term = getenv("TERM");
 248 
 249         if (term == NULL || *term == '\0')
 250                 term = Def_term;
 251 
 252         tfd = -1;
 253         errno = 0;      /* ehr3 */
 254 
 255         if (errret != 0)
 256                 *errret = -1;
 257 
 258         if (((cp = getenv("TERMINFO")) != 0) && *cp) {
 259                 /* $TERMINFO/?/$TERM */
 260                 if (snprintf(fname, sizeof (fname),
 261                         "%s/%c/%s", cp, *term, term) >= sizeof (fname)) {
 262                         term_errno = TERMINFO_TOO_LONG;
 263                         goto out_err;
 264                 }
 265 
 266                 tfd = open(fname, 0);
 267 #ifdef  DUMPTI
 268                 printf("looking in file %s\n", fname);
 269 #endif  /* DUMPTI */
 270                 if ((tfd < 0) && (errno == EACCES))
 271                         goto cant_read;
 272         }
 273 
 274         if (tfd < 0) {
 275                 /* /usr/share/lib/terminfo/?/$TERM */
 276                 if (snprintf(fname, sizeof (fname),
 277                         "%s/%c/%s", TERMPATH, *term, term) >= sizeof (fname)) {
 278                         term_errno = TERMINFO_TOO_LONG;
 279                         goto out_err;
 280                 }
 281 
 282                 tfd = open(fname, 0);
 283 #ifdef  DUMPTI
 284                 printf("looking in file %s\n", fname);
 285 #endif  /* DUMPTI */
 286 
 287         }
 288 
 289         if (tfd < 0) {
 290                 if (errno == EACCES) {
 291 cant_read:
 292                         term_errno = NOT_READABLE;
 293                 } else {
 294                         if (access(TERMPATH, 0) == -1)
 295                                 term_errno = UNACCESSIBLE;
 296                         else {
 297                                 term_errno = NO_TERMINAL;
 298                                 if (errret != 0)
 299                                         *errret = 0;
 300                         }
 301                 }
 302                 /*
 303                  * if the length of the specified terminal name is longer
 304                  * than 31, it will be chopped after the 31st byte.
 305                  * This should be a rare case.
 306                  */
 307                 (void) strncpy(term_parm_err, term, 31);
 308                 term_parm_err[31] = '\0';
 309                 goto out_err;
 310         }
 311 
 312         /* LINTED */
 313         n = (int)read(tfd, tiebuf, sizeof (tiebuf));
 314         (void) close(tfd);
 315 
 316         if (n <= 0) {
 317 corrupt:
 318                 term_errno = CORRUPTED;
 319                 goto out_err;
 320         } else
 321                 if (n == sizeof (tiebuf)) {
 322                         term_errno = ENTRY_TOO_LONG;
 323                         goto out_err;
 324                 }
 325         cp = ttytype;
 326         ip = tiebuf;
 327 
 328         /* Pick up header */
 329         snames = _Getshi();
 330 #ifdef  DUMPTI
 331         Vr2val = _Vr2getshi();
 332         printf("Magic number = %d, %#o [%d, %#o].\n", snames,
 333             snames, Vr2val, Vr2val);
 334 #endif  /* DUMPTI */
 335         if (snames != MAGNUM)
 336                 goto corrupt;
 337         snames = _Getshi();
 338 #ifdef  DUMPTI
 339         Vr2val = _Vr2getshi();
 340         printf("Size of names = %d, %#o [%d, %#o].\n", snames,
 341             snames, Vr2val, Vr2val);
 342 #endif  /* DUMPTI */
 343 
 344         nbools = _Getshi();
 345 #ifdef  DUMPTI
 346         Vr2val = _Vr2getshi();
 347         printf("Number of bools = %d, %#o [%d, %#o].\n", nbools,
 348             nbools, Vr2val, Vr2val);
 349 #endif  /* DUMPTI */
 350 
 351         nints = _Getshi();
 352 #ifdef  DUMPTI
 353         Vr2val = _Vr2getshi();
 354         printf("Number of ints = %d, %#o [%d, %#o].\n", nints, nints,
 355             Vr2val, Vr2val);
 356 #endif  /* DUMPTI */
 357 
 358         nstrs = _Getshi();
 359 #ifdef  DUMPTI
 360         Vr2val = _Vr2getshi();
 361         printf("Number of strings = %d, %#o [%d, %#o].\n", nstrs, nstrs,
 362             Vr2val, Vr2val);
 363 #endif  /* DUMPTI */
 364 
 365         sstrtab = _Getshi();
 366 #ifdef  DUMPTI
 367         Vr2val = _Vr2getshi();
 368         printf("Size of string table = %d, %#o [%d, %#o].\n", sstrtab,
 369             sstrtab, Vr2val, Vr2val);
 370         printf("Names are: %.*s.\n", snames, ip);
 371 #endif  /* DUMPTI */
 372 
 373         /* allocate all of the space */
 374         strtab = NULL;
 375         if (_called_before) {
 376                 /* 2nd or more times through */
 377                 if ((cur_term = (TERMINAL *)
 378                     calloc(sizeof (TERMINAL), 1)) == NULL)
 379                         goto badmalloc;
 380                 if ((cur_bools = (struct _bool_struct *)
 381                     calloc(sizeof (struct _bool_struct), 1)) == NULL)
 382                         goto freeterminal;
 383                 if ((cur_nums = (struct _num_struct *)
 384                     calloc(sizeof (struct _num_struct), 1)) == NULL)
 385                         goto freebools;
 386                 if ((cur_strs = (struct _str_struct *)
 387                     calloc(sizeof (struct _str_struct), 1)) == NULL) {
 388 freenums:
 389                         free((char *)cur_nums);
 390 freebools:
 391                         free((char *)cur_bools);
 392 freeterminal:
 393                         free((char *)cur_term);
 394 badmalloc:
 395                         term_errno = TERM_BAD_MALLOC;
 396 #ifdef  DEBUG
 397                         strcpy(term_parm_err, "setupterm");
 398 #endif  /* DEBUG */
 399 out_err:
 400                         if (errret == 0) {
 401                                 termerr();
 402                                 exit(-term_errno);
 403                         } else
 404                                 return (ERR);
 405                 }
 406         } else {
 407                 /* First time through */
 408                 _called_before = TRUE;
 409                 cur_term = &_first_term;
 410                 cur_bools = &_frst_bools;
 411                 cur_nums = &_frst_nums;
 412                 cur_strs = &_frst_strs;
 413                 if (sstrtab < sizeof (_frst_tblstr))
 414                         strtab = _frst_tblstr;
 415         }
 416 
 417         if (strtab == NULL) {
 418                 if ((strtab = (char *)malloc((unsigned)sstrtab)) == NULL) {
 419                         if (cur_strs != &_frst_strs)
 420                                 free((char *)cur_strs);
 421                         goto freenums;
 422                 }
 423         }
 424 
 425         /* no more catchable errors */
 426         if (errret)
 427                 *errret = 1;
 428 
 429         (void) strncpy(cur_term->_termname, term, 14);
 430         /* In case the name is exactly 15 characters */
 431         cur_term->_termname[14] = '\0';
 432         cur_term->_bools = cur_bools;
 433         cur_term->_nums = cur_nums;
 434         cur_term->_strs = cur_strs;
 435         cur_term->_strtab = strtab;
 436         cur_term->sgr_mode = cur_term->sgr_faked = A_NORMAL;
 437 
 438         if (filenum == 1 && !isatty(filenum))
 439                 filenum = 2;    /* Allow output redirect */
 440         /* LINTED */
 441         cur_term->Filedes = (short)filenum;
 442         _blast_keys(cur_term);
 443         cur_term->_iwait = cur_term->fl_typeahdok = cur_term->_chars_on_queue =
 444                 cur_term->_fl_rawmode = cur_term->_ungotten = 0;
 445         cur_term->_cursorstate = 1;
 446         cur_term->_delay = cur_term->_inputfd = cur_term->_check_fd = -1;
 447         (void) memset((char *)cur_term->_regs, 0, 26 * sizeof (short));
 448 
 449 #ifndef DUMPTI
 450         (void) def_shell_mode();
 451         /* This is a useful default for PROGTTY, too */
 452 #ifdef SYSV
 453         if (shell_istermios < 0) {
 454                 int i;
 455 
 456                 SHELLTTY.c_lflag = SHELLTTYS.c_lflag;
 457                 SHELLTTY.c_oflag = SHELLTTYS.c_oflag;
 458                 SHELLTTY.c_iflag = SHELLTTYS.c_iflag;
 459                 SHELLTTY.c_cflag = SHELLTTYS.c_cflag;
 460                 for (i = 0; i < NCC; i++)
 461                         SHELLTTY.c_cc[i] = SHELLTTYS.c_cc[i];
 462                 PROGTTY = SHELLTTY;
 463                 prog_istermios = -1;
 464 
 465                 PROGTTYS.c_lflag = PROGTTY.c_lflag;
 466                 PROGTTYS.c_oflag = PROGTTY.c_oflag;
 467                 PROGTTYS.c_iflag = PROGTTY.c_iflag;
 468                 PROGTTYS.c_cflag = PROGTTY.c_cflag;
 469                 for (i = 0; i < NCC; i++)
 470                         PROGTTYS.c_cc[i] = PROGTTY.c_cc[i];
 471         } else {
 472                 PROGTTYS = SHELLTTYS;
 473                 prog_istermios = 0;
 474         }
 475 #else   /* SYSV */
 476         PROGTTY = SHELLTTY;
 477 #endif  /* SYSV */
 478 #endif  /* DUMPTI */
 479 
 480         /* Skip names of terminals */
 481         (void) memcpy((char *)cp, (char *)ip, (snames * sizeof (*cp)));
 482         ip += snames;
 483 
 484         /*
 485          * Pull out the booleans.
 486          * The for loop below takes care of a new curses with an old tic
 487          * file and visa-versa.  nbools says how many bools the tic file has.
 488          * So, we only loop for as long as there are bools to read.
 489          * However, if this is an old curses that doesn't have all the
 490          * bools that this new tic has dumped, then the extra if
 491          * "if (cp < fp)" says that if we are going to read into our structure
 492          * passed its size don't do it but we still need to keep bumping
 493          * up the pointer of what we read in from the terminfo file.
 494          */
 495         {
 496                 char    *fp = &cur_bools->Sentinel;
 497                 char    s;
 498 #ifdef  DUMPTI
 499                 int     tempindex = 0;
 500 #endif  /* DUMPTI */
 501                 cp = &cur_bools->_auto_left_margin;
 502                 while (nbools--) {
 503                         s = *ip++;
 504 #ifdef  DUMPTI
 505                         printf("Bool %s [%s] (%s) = %d.\n",
 506                             boolfnames[tempindex], boolnames[tempindex],
 507                             boolcodes[tempindex], s);
 508                         tempindex++;
 509 #endif  /* DUMPTI */
 510                         if (cp < fp)
 511                                 *cp++ = s & 01;
 512                 }
 513                 if (cp < fp)
 514                         (void) memset(cp, 0, ((fp - cp) * sizeof (bool)));
 515         }
 516 
 517         /* Force proper alignment */
 518         if (((unsigned long) ip) & 1)
 519                 ip++;
 520 
 521         /*
 522          * Pull out the numbers.
 523          */
 524         {
 525                 short   *sp = &cur_nums->_columns;
 526                 short   *fp = &cur_nums->Sentinel;
 527                 int     s;
 528 #ifdef  DUMPTI
 529                 int     tempindex = 0;
 530 #endif  /* DUMPTI */
 531 
 532                 while (nints--) {
 533                         s = _Getshi();
 534 #ifdef  DUMPTI
 535                         Vr2val = _Vr2getshi();
 536                         printf("Num %s [%s] (%s) = %d [%d].\n",
 537                             numfnames[tempindex], numnames[tempindex],
 538                             numcodes[tempindex], s, Vr2val);
 539                         tempindex++;
 540 #endif  /* DUMPTI */
 541                         if (sp < fp)
 542                                 if (s < 0)
 543                                         *sp++ = -1;
 544                                 else
 545                                         /* LINTED */
 546                                         *sp++ = (short)s;
 547                 }
 548                 if (sp < fp)
 549                         (void) memset((char *)sp, '\377',
 550                             ((fp - sp) * sizeof (short)));
 551         }
 552 
 553         if (_use_env) {
 554                 /*
 555                  * This ioctl defines the window size and overrides what
 556                  * it says in terminfo.
 557                  */
 558                 {
 559                         struct  winsize w;
 560 
 561                         if (ioctl(filenum, TIOCGWINSZ, &w) != -1) {
 562                                 if (w.ws_row != 0)
 563                                         cur_nums->_lines = w.ws_row;
 564                                 if (w.ws_col != 0)
 565                                         cur_nums->_columns = w.ws_col;
 566 #ifdef  DUMPTI
 567                                 printf("ioctl TIOCGWINSZ override: "
 568                                     "(lines, columns) = (%d, %d)\n",
 569                                     w.ws_row, w.ws_col);
 570 #endif  /* DUMPTI */
 571                         }
 572                 }
 573 
 574                 /*
 575                  * Check $LINES and $COLUMNS.
 576                  */
 577                 {
 578                         int     ilines, icolumns;
 579 
 580                         lcp = getenv("LINES");
 581                         ccp = getenv("COLUMNS");
 582                         if (lcp)
 583                                 if ((ilines = atoi(lcp)) > 0) {
 584                                         /* LINTED */
 585                                         cur_nums->_lines = (short)ilines;
 586 #ifdef  DUMPTI
 587                                         printf("$LINES override: lines = %d\n",
 588                                             ilines);
 589 #endif  /* DUMPTI */
 590                                 }
 591                         if (ccp)
 592                                 if ((icolumns = atoi(ccp)) > 0) {
 593                                         /* LINTED */
 594                                         cur_nums->_columns = (short)icolumns;
 595 #ifdef  DUMPTI
 596                                         printf("$COLUMNS override: columns = "
 597                                             "%d\n", icolumns);
 598 #endif  /* DUMPTI */
 599                                 }
 600                 }
 601         }
 602 
 603         /* Pull out the strings. */
 604         {
 605                 char    **pp = &cur_strs->strs._back_tab;
 606                 char    **fp = &cur_strs->strs4.Sentinel;
 607 #ifdef  DUMPTI
 608                 int     tempindex = 0;
 609                 char    *startstr = ip + sizeof (short) *
 610                                             nstrs;
 611 
 612                 printf("string table = '");
 613                 _Mprint(sstrtab, startstr);
 614                 printf("'\n");
 615 #endif  /* DUMPTI */
 616 
 617                 while (nstrs--) {
 618                         n = _Getshi();
 619 #ifdef  DUMPTI
 620                         Vr2val = _Vr2getshi();
 621                         printf("String %s [%s] (%s) offset = %d [%d]",
 622                             strfnames[tempindex], strnames[tempindex],
 623                             strcodes[tempindex], n, Vr2val);
 624                         tempindex++;
 625 #endif  /* DUMPTI */
 626                         if (pp < fp) {
 627 #ifdef  DUMPTI
 628                                 _Sprint(n, startstr+n);
 629 #endif  /* DUMPTI */
 630                                 if (n < 0)
 631                                         *pp++ = NULL;
 632                                 else
 633                                         *pp++ = strtab + n;
 634                         }
 635 #ifdef  DUMPTI
 636                         else
 637                                 _Sprint(-1, (char *)0);
 638 #endif  /* DUMPTI */
 639                 }
 640                 if (pp < fp)
 641                 (void) memset((char *)pp, 0, ((fp - pp) * sizeof (charptr)));
 642         }
 643 
 644         (void) memcpy(strtab, ip, sstrtab);
 645 
 646 #ifndef DUMPTI
 647 
 648         /*
 649          * If tabs are being expanded in software, turn this off
 650          * so output won't get messed up.  Also, don't use tab
 651          * or backtab, even if the terminal has them, since the
 652          * user might not have hardware tabs set right.
 653          */
 654 #ifdef  SYSV
 655         if ((PROGTTYS.c_oflag & TABDLY) == TAB3) {
 656                 PROGTTYS.c_oflag &= ~TABDLY;
 657                 (void) reset_prog_mode();
 658                 goto next;
 659         }
 660 #else   /* SYSV */
 661         if ((PROGTTY.sg_flags & XTABS) == XTABS) {
 662                 PROGTTY.sg_flags &= ~XTABS;
 663                 (void) reset_prog_mode();
 664                 goto next;
 665         }
 666 #endif  /* SYSV */
 667         if (dest_tabs_magic_smso) {
 668 next:
 669                 cur_strs->strs2._tab = cur_strs->strs._back_tab = NULL;
 670         }
 671 
 672 #ifdef  LTILDE
 673         ioctl(cur_term -> Filedes, TIOCLGET, &n);
 674 #endif  /* LTILDE */
 675 #endif  /* DUMPTI */
 676 
 677 #ifdef  _VR2_COMPAT_CODE
 678         (void) memcpy(&cur_term->_b1, &cur_bools->_auto_left_margin,
 679             (char *)&cur_term->_c1 - (char *)&cur_term->_b1);
 680         (void) memcpy((char *)&cur_term->_c1, (char *)&cur_nums->_columns,
 681             (char *)&cur_term->_Vr2_Astrs._s1 - (char *)&cur_term->_c1);
 682         (void) memcpy((char *)&cur_term->_Vr2_Astrs._s1,
 683             (char *)&cur_strs->strs._back_tab,
 684             (char *)&cur_term->Filedes - (char *)&cur_term->_Vr2_Astrs._s1);
 685 #endif  /* _VR2_COMPAT_CODE */
 686 
 687         on_sequences = cur_term->turn_on_seq;
 688         str_array = (char **)cur_strs;
 689         {
 690                 static  char    offsets[] = {
 691                             35, /* enter_standout_mode, */
 692                             36, /* enter_underline_mode, */
 693                             25, /* enter_alt_charset_mode, */
 694                             34, /* enter_reverse_mode, */
 695                             26, /* enter_blink_mode, */
 696                             30, /* enter_dim_mode, */
 697                             27, /* enter_bold_mode, */
 698                             32, /* enter_secure_mode, */
 699                             33, /* enter_protected_mode, */
 700                         };
 701 
 702                 for (n = 0; n < NUM_ATTRIBUTES; n++) {
 703                         if ((on_sequences[n] = str_array[offsets[n]]) != 0)
 704                                 cur_term->bit_vector |= bit_attributes[n];
 705                 }
 706         }
 707 
 708         if (!(set_attributes)) {
 709                 static  char    faked_attrs[] = { 1, 3, 4, 6 },
 710                         offsets[] = {
 711                             43, /* exit_standout_mode, */
 712                             44, /* exit_underline_mode, */
 713                             38, /* exit_alt_charset_mode, */
 714                         };
 715                 char            **off_sequences = cur_term->turn_off_seq;
 716                 int             i;
 717 
 718                 if ((max_attributes == -1) && (ceol_standout_glitch ||
 719                     (magic_cookie_glitch >= 0)))
 720                         max_attributes = 1;
 721 
 722                 /* Figure out what attributes need to be faked. */
 723                 /* See vidupdate.c */
 724 
 725                 for (n = 0; n < sizeof (faked_attrs); n++) {
 726                         if (on_sequences[0] != NULL) {
 727                                 if ((!on_sequences[i = faked_attrs[n]]) ||
 728                                     (strcmp(on_sequences[i],
 729                                     on_sequences[0]) == 0)) {
 730                                         cur_term->sgr_faked |=
 731                                             bit_attributes[i];
 732                                 }
 733                         } else {
 734                                 if (!on_sequences[i = faked_attrs[n]]) {
 735                                         cur_term->sgr_faked |=
 736                                             bit_attributes[i];
 737                                 }
 738                         }
 739                 }
 740 
 741                 cur_term->check_turn_off = A_STANDOUT | A_UNDERLINE |
 742                     A_ALTCHARSET;
 743 
 744                 for (n = 0; n < sizeof (offsets); n++) {
 745                         if ((!(off_sequences[n] = str_array[offsets[n]])) ||
 746                             ((n > 0) && off_sequences[0] &&
 747                             (strcmp(off_sequences[n], off_sequences[0]) ==
 748                             0)) || ((n == 2) && (exit_attribute_mode) &&
 749                             (strcmp(exit_attribute_mode, off_sequences[n]) ==
 750                             0))) {
 751                                 cur_term->check_turn_off &= ~bit_attributes[n];
 752                         }
 753                 }
 754         }
 755         cur_term->cursor_seq[0] = cursor_invisible;
 756         cur_term->cursor_seq[1] = cursor_normal;
 757         cur_term->cursor_seq[2] = cursor_visible;
 758         cur_term->_pairs_tbl = (_Color_pair *) NULL;
 759         cur_term->_color_tbl = (_Color *) NULL;
 760 
 761         return (OK);
 762 }
 763 
 764 void
 765 _blast_keys(TERMINAL *terminal)
 766 {
 767         terminal->_keys = NULL;
 768         terminal->internal_keys = NULL;
 769         terminal->_ksz = terminal->_first_macro = 0;
 770         terminal->_lastkey_ordered = terminal->_lastmacro_ordered = -1;
 771         (void) memset((char *)terminal->funckeystarter, 0, 0400 *
 772             sizeof (bool));
 773 }
 774 
 775 #ifndef DUMPTI
 776 
 777 int
 778 reset_prog_mode(void)
 779 {
 780 #ifdef  SYSV
 781         if (_BRS(PROGTTYS)) {
 782                 if (prog_istermios < 0) {
 783                         int i;
 784 
 785                         PROGTTY.c_lflag = PROGTTYS.c_lflag;
 786                         PROGTTY.c_oflag = PROGTTYS.c_oflag;
 787                         PROGTTY.c_iflag = PROGTTYS.c_iflag;
 788                         PROGTTY.c_cflag = PROGTTYS.c_cflag;
 789                         for (i = 0; i < NCC; i++)
 790                                 PROGTTY.c_cc[i] = PROGTTYS.c_cc[i];
 791                         (void) ioctl(cur_term -> Filedes, TCSETAW, &PROGTTY);
 792                 } else
 793                         (void) ioctl(cur_term -> Filedes, TCSETSW, &PROGTTYS);
 794         }
 795 #else   /* SYSV */
 796         if (_BR(PROGTTY))
 797                 (void) ioctl(cur_term -> Filedes, TIOCSETN, &PROGTTY);
 798 #endif  /* SYSV */
 799 
 800 #ifdef  LTILDE
 801         ioctl(cur_term -> Filedes, TIOCLGET, &cur_term -> oldlmode);
 802         cur_term -> newlmode = cur_term -> oldlmode & ~LTILDE;
 803         if (cur_term -> newlmode != cur_term -> oldlmode)
 804                 ioctl(cur_term -> Filedes, TIOCLSET, &cur_term -> newlmode);
 805 #endif  /* LTILDE */
 806 #ifdef  DIOCSETT
 807         if (cur_term -> old.st_termt == 0)
 808                 ioctl(cur_term->Filedes, DIOCGETT, &cur_term -> old);
 809         cur_term -> new = cur_term -> old;
 810         cur_term -> new.st_termt = 0;
 811         cur_term -> new.st_flgs |= TM_SET;
 812         ioctl(cur_term->Filedes, DIOCSETT, &cur_term -> new);
 813 #endif  /* DIOCSETT */
 814         return (OK);
 815 }
 816 
 817 int
 818 def_shell_mode(void)
 819 {
 820 #ifdef  SYSV
 821         if ((shell_istermios =
 822             ioctl(cur_term -> Filedes, TCGETS, &SHELLTTYS)) < 0) {
 823                 int i;
 824 
 825                 (void) ioctl(cur_term -> Filedes, TCGETA, &SHELLTTY);
 826                 SHELLTTYS.c_lflag = SHELLTTY.c_lflag;
 827                 SHELLTTYS.c_oflag = SHELLTTY.c_oflag;
 828                 SHELLTTYS.c_iflag = SHELLTTY.c_iflag;
 829                 SHELLTTYS.c_cflag = SHELLTTY.c_cflag;
 830                 for (i = 0; i < NCC; i++)
 831                         SHELLTTYS.c_cc[i] = SHELLTTY.c_cc[i];
 832         }
 833 #else   /* SYSV */
 834         (void) ioctl(cur_term -> Filedes, TIOCGETP, &SHELLTTY);
 835 #endif  /* SYSV */
 836         return (OK);
 837 }
 838 
 839 #endif  /* DUMPTI */