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 1996 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 /* Copyright (c) 1981 Regents of the University of California */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #include <sys/stropts.h> 36 #include <sys/eucioctl.h> 37 #ifndef PRESUNEUC 38 #include <locale.h> 39 /* Undef putchar/getchar if they're defined. */ 40 #ifdef putchar 41 # undef putchar 42 #endif 43 #ifdef getchar 44 # undef getchar 45 #endif 46 #endif /* PRESUNEUC */ 47 48 #include "ex.h" 49 #include "ex_re.h" 50 #include "ex_tty.h" 51 #include "ex_vis.h" 52 53 /* 54 * Random routines, in alphabetical order. 55 */ 56 57 any(c, s) 58 int c; 59 register unsigned char *s; 60 { 61 register int x; 62 63 while (x = *s++) 64 if (x == c) 65 return (1); 66 return (0); 67 } 68 69 backtab(i) 70 register int i; 71 { 72 register int j; 73 74 j = i % value(vi_SHIFTWIDTH); 75 if (j == 0) 76 j = value(vi_SHIFTWIDTH); 77 i -= j; 78 if (i < 0) 79 i = 0; 80 return (i); 81 } 82 83 change() 84 { 85 86 tchng++; 87 chng = tchng; 88 } 89 90 /* 91 * Column returns the number of 92 * columns occupied by printing the 93 * characters through position cp of the 94 * current line. 95 */ 96 column(cp) 97 register unsigned char *cp; 98 { 99 100 if (cp == 0) 101 cp = &linebuf[LBSIZE - 2]; 102 return (qcolumn(cp, (char *) 0)); 103 } 104 105 /* lcolumn is same as column except it returns number of columns 106 * occupied by characters before position 107 * cp of the current line 108 */ 109 lcolumn(cp) 110 register unsigned char *cp; 111 { 112 113 if (cp == 0) 114 cp = &linebuf[LBSIZE - 2]; 115 return(nqcolumn(lastchr(linebuf, cp), (char *)0)); 116 } 117 118 /* 119 * Ignore a comment to the end of the line. 120 * This routine eats the trailing newline so don't call donewline(). 121 */ 122 comment() 123 { 124 register int c; 125 126 do { 127 c = getchar(); 128 } while (c != '\n' && c != EOF); 129 if (c == EOF) 130 ungetchar(c); 131 } 132 133 Copy(to, from, size) 134 register unsigned char *from, *to; 135 register int size; 136 { 137 138 if (size > 0) 139 do 140 *to++ = *from++; 141 while (--size > 0); 142 } 143 144 copyw(to, from, size) 145 register line *from, *to; 146 register int size; 147 { 148 149 if (size > 0) 150 do 151 *to++ = *from++; 152 while (--size > 0); 153 } 154 155 copywR(to, from, size) 156 register line *from, *to; 157 register int size; 158 { 159 160 while (--size >= 0) 161 to[size] = from[size]; 162 } 163 164 ctlof(c) 165 int c; 166 { 167 168 return (c == DELETE ? '?' : c | ('A' - 1)); 169 } 170 171 dingdong() 172 { 173 174 if (flash_screen && value(vi_FLASH)) 175 putpad(flash_screen); 176 else if (value(vi_ERRORBELLS)) 177 putpad(bell); 178 } 179 180 fixindent(indent) 181 int indent; 182 { 183 register int i; 184 register unsigned char *cp; 185 186 i = whitecnt(genbuf); 187 cp = vpastwh(genbuf); 188 if (*cp == 0 && i == indent && linebuf[0] == 0) { 189 genbuf[0] = 0; 190 return (i); 191 } 192 CP(genindent(i), cp); 193 return (i); 194 } 195 196 filioerr(cp) 197 unsigned char *cp; 198 { 199 register int oerrno = errno; 200 201 lprintf("\"%s\"", cp); 202 errno = oerrno; 203 syserror(1); 204 } 205 206 unsigned char * 207 genindent(indent) 208 register int indent; 209 { 210 register unsigned char *cp; 211 212 for (cp = genbuf; indent >= value(vi_TABSTOP); indent -= value(vi_TABSTOP)) 213 *cp++ = '\t'; 214 for (; indent > 0; indent--) 215 *cp++ = ' '; 216 return (cp); 217 } 218 219 getDOT() 220 { 221 222 getline(*dot); 223 } 224 225 line * 226 getmark(c) 227 register int c; 228 { 229 register line *addr; 230 231 for (addr = one; addr <= dol; addr++) 232 if (names[c - 'a'] == (*addr &~ 01)) { 233 return (addr); 234 } 235 return (0); 236 } 237 238 getn(cp) 239 register unsigned char *cp; 240 { 241 register int i = 0; 242 243 while (isdigit(*cp)) 244 i = i * 10 + *cp++ - '0'; 245 if (*cp) 246 return (0); 247 return (i); 248 } 249 250 ignnEOF() 251 { 252 register int c = getchar(); 253 254 if (c == EOF) 255 ungetchar(c); 256 else if (c=='"') 257 comment(); 258 } 259 260 iswhite(c) 261 int c; 262 { 263 264 return (c == ' ' || c == '\t'); 265 } 266 267 junk(c) 268 register wchar_t c; 269 { 270 271 if (c && !value(vi_BEAUTIFY)) 272 return (0); 273 if (c >= ' ' && c != DELETE) 274 return (0); 275 switch (c) { 276 277 case '\t': 278 case '\n': 279 case '\f': 280 return (0); 281 282 default: 283 return (1); 284 } 285 } 286 287 killed() 288 { 289 290 killcnt(addr2 - addr1 + 1); 291 } 292 293 killcnt(cnt) 294 register int cnt; 295 { 296 extern char *verbalize(); 297 298 if (inopen) { 299 notecnt = cnt; 300 notenam = notesgn = (unsigned char *)""; 301 return; 302 } 303 if (!notable(cnt)) 304 return; 305 if (value(vi_TERSE) == 0) { 306 verbalize(cnt, Command, ""); 307 } else { 308 if (cnt == 1) { 309 printf(gettext("1 line"), cnt); 310 } else { 311 printf(gettext("%d lines"), cnt); 312 } 313 } 314 putNFL(); 315 } 316 317 lineno(a) 318 line *a; 319 { 320 321 return (a - zero); 322 } 323 324 lineDOL() 325 { 326 327 return (lineno(dol)); 328 } 329 330 lineDOT() 331 { 332 333 return (lineno(dot)); 334 } 335 336 markDOT() 337 { 338 339 markpr(dot); 340 } 341 342 markpr(which) 343 line *which; 344 { 345 346 if ((inglobal == 0 || inopen) && which <= endcore) { 347 names['z'-'a'+1] = *which & ~01; 348 if (inopen) 349 ncols['z'-'a'+1] = cursor; 350 } 351 } 352 353 markreg(c) 354 register int c; 355 { 356 357 if (c == '\'' || c == '`') 358 return ('z' + 1); 359 if (c >= 'a' && c <= 'z') 360 return (c); 361 return (0); 362 } 363 364 /* 365 * Mesg decodes the terse/verbose strings. Thus 366 * 'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy' 367 * 'xxx|yyy' -> 'xxx' if terse, else 'yyy' 368 * All others map to themselves. 369 */ 370 /* 371 * The feature described above was disabled for localizable messaging. 372 */ 373 unsigned char * 374 mesg(str) 375 register unsigned char *str; 376 { 377 register unsigned char *cp; 378 379 str = (unsigned char *)strcpy(genbuf, str); 380 /* commented out for localizable messaging */ 381 /* for (cp = str; *cp; cp++) 382 switch (*cp) { 383 384 case '@': 385 if (value(vi_TERSE)) 386 *cp = 0; 387 else 388 *cp = ' '; 389 break; 390 391 case '|': 392 if (value(vi_TERSE) == 0) 393 return (cp + 1); 394 *cp = 0; 395 break; 396 } */ 397 return (str); 398 } 399 400 /*VARARGS2*/ 401 merror(seekpt, i) 402 unsigned char *seekpt; 403 int i; 404 { 405 register unsigned char *cp = linebuf; 406 407 if (seekpt == 0) 408 return; 409 merror1(seekpt); 410 if (*cp == '\n') 411 putnl(), cp++; 412 if (inopen > 0 && clr_eol) 413 vclreol(); 414 if (enter_standout_mode && exit_bold) 415 putpad(enter_standout_mode); 416 #ifdef PRESUNEUC 417 printf(mesg(cp), i); 418 #else 419 printf((char *)mesg(cp), i); 420 #endif /* PRESUNEUC */ 421 if (enter_standout_mode && exit_bold) 422 putpad(exit_bold); 423 } 424 425 merror1(seekpt) 426 unsigned char *seekpt; 427 { 428 429 strcpy(linebuf, seekpt); 430 } 431 432 #define MAXDATA (56*1024) 433 morelines() 434 { 435 register unsigned char *end; 436 437 if ((int) sbrk(1024 * sizeof (line)) == -1) { 438 if (endcore >= (line *) MAXDATA) 439 return -1; 440 end = (unsigned char *) MAXDATA; 441 /* 442 * Ask for end+2 sice we want end to be the last used location. 443 */ 444 while (brk(end+2) == -1) 445 end -= 64; 446 if (end <= (unsigned char *) endcore) 447 return -1; 448 endcore = (line *) end; 449 } else { 450 endcore += 1024; 451 } 452 return (0); 453 } 454 455 nonzero() 456 { 457 458 if (addr1 == zero) { 459 notempty(); 460 error(value(vi_TERSE) ? gettext("Nonzero address required") : 461 gettext("Nonzero address required on this command")); 462 } 463 } 464 465 notable(i) 466 int i; 467 { 468 469 return (hush == 0 && !inglobal && i > value(vi_REPORT)); 470 } 471 472 473 notempty() 474 { 475 476 if (dol == zero) 477 error(value(vi_TERSE) ? gettext("No lines") : 478 gettext("No lines in the buffer")); 479 } 480 481 482 netchHAD(cnt) 483 int cnt; 484 { 485 486 netchange(lineDOL() - cnt); 487 } 488 489 netchange(i) 490 register int i; 491 { 492 register unsigned char *cp; 493 494 if (i > 0) 495 notesgn = cp = (unsigned char *)"more "; 496 else 497 notesgn = cp = (unsigned char *)"fewer ", i = -i; 498 if (inopen) { 499 notecnt = i; 500 notenam = (unsigned char *)""; 501 return; 502 } 503 if (!notable(i)) 504 return; 505 if (*cp == 'm') /* for ease of messge localization */ 506 #ifdef PRESUNEUC 507 printf(mesg(value(vi_TERSE) ? 508 #else 509 printf((char *)mesg(value(vi_TERSE) ? 510 #endif /* PRESUNEUC */ 511 gettext("%d more lines") : 512 /* 513 * TRANSLATION_NOTE 514 * Reference order of arguments must not 515 * be changed using '%digit$', since vi's 516 * printf() does not support it. 517 */ 518 gettext("%d more lines in file after %s")), i, Command); 519 else 520 #ifdef PRESUNEUC 521 printf(mesg(value(vi_TERSE) ? 522 #else 523 printf((char *)mesg(value(vi_TERSE) ? 524 #endif /* PRESUNEUC */ 525 gettext("%d fewer lines") : 526 /* 527 * TRANSLATION_NOTE 528 * Reference order of arguments must not 529 * be changed using '%digit$', since vi's 530 * printf() does not support it. 531 */ 532 gettext("%d fewer lines in file after %s")), i, Command); 533 putNFL(); 534 } 535 536 putmark(addr) 537 line *addr; 538 { 539 540 putmk1(addr, putline()); 541 } 542 543 putmk1(addr, n) 544 register line *addr; 545 int n; 546 { 547 register line *markp; 548 register oldglobmk; 549 550 oldglobmk = *addr & 1; 551 *addr &= ~1; 552 for (markp = (anymarks ? names : &names['z'-'a'+1]); 553 markp <= &names['z'-'a'+1]; markp++) 554 if (*markp == *addr) 555 *markp = n; 556 *addr = n | oldglobmk; 557 } 558 559 unsigned char * 560 plural(i) 561 long i; 562 { 563 564 return (i == 1 ? (unsigned char *)"" : (unsigned char *)"s"); 565 } 566 567 int qcount(); 568 short vcntcol; 569 570 qcolumn(lim, gp) 571 register unsigned char *lim, *gp; 572 { 573 register int x, length; 574 int col; 575 wchar_t wchar; 576 int (*OO)(); 577 578 OO = Outchar; 579 Outchar = qcount; 580 vcntcol = 0; 581 if (lim != NULL) { 582 if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2]) 583 length = 1; 584 else 585 length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX); 586 if(length < 0) 587 length = 1; 588 x = lim[length]; 589 lim[length] = 0; 590 } 591 pline(0); 592 if (lim != NULL) 593 lim[length] = x; 594 if(length > 1 && !gp) { 595 /* put cursor at beginning of multibyte character */ 596 if ((col = wcwidth(wchar)) < 0) 597 col = 0; 598 vcntcol = vcntcol - col + 1; 599 } 600 if (gp) 601 while (*gp) { 602 length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX); 603 if(length < 0) { 604 putoctal = 1; 605 putchar(*gp++); 606 putoctal = 0; 607 } else { 608 putchar(wchar); 609 gp += length; 610 } 611 } 612 Outchar = OO; 613 return (vcntcol); 614 } 615 616 /* This routine puts cursor after multibyte character */ 617 nqcolumn(lim, gp) 618 register unsigned char *lim, *gp; 619 { 620 register int x, length; 621 wchar_t wchar; 622 int (*OO)(); 623 624 OO = Outchar; 625 Outchar = qcount; 626 vcntcol = 0; 627 if (lim != NULL) { 628 if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2]) 629 length = 1; 630 else 631 length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX); 632 if(length < 0) 633 length = 1; 634 x = lim[length]; 635 lim[length] = 0; 636 } 637 pline(0); 638 if (lim != NULL) 639 lim[length] = x; 640 if (gp) 641 while (*gp) { 642 length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX); 643 if(length < 0) { 644 putoctal = 1; 645 putchar(*gp++); 646 putoctal = 0; 647 } else { 648 putchar(wchar); 649 gp += length; 650 } 651 } 652 Outchar = OO; 653 return (vcntcol); 654 } 655 656 int 657 qcount(c) 658 wchar_t c; 659 { 660 register int cols; 661 #ifndef PRESUNEUC 662 register int remcols; 663 register short OWCOLS; 664 #endif /* PRESUNEUC */ 665 666 if (c == '\t') { 667 vcntcol += value(vi_TABSTOP) - vcntcol % value(vi_TABSTOP); 668 return; 669 } 670 #ifdef PRESUNEUC 671 if ((cols = wcwidth(c)) > 0) 672 vcntcol += cols; 673 #else 674 if ((cols = wcwidth(c)) < 0) 675 cols = 0; 676 OWCOLS = WCOLS; 677 if (WCOLS == 0) 678 WCOLS = columns; 679 if ((mc_wrap) == 1 && (remcols = (WCOLS - (vcntcol % WCOLS))) < cols) 680 vcntcol += remcols; 681 WCOLS = OWCOLS; 682 vcntcol += cols; 683 #endif /* PRESUNEUC */ 684 } 685 686 reverse(a1, a2) 687 register line *a1, *a2; 688 { 689 register line t; 690 691 for (;;) { 692 t = *--a2; 693 if (a2 <= a1) 694 return; 695 *a2 = *a1; 696 *a1++ = t; 697 } 698 } 699 700 save(a1, a2) 701 line *a1; 702 register line *a2; 703 { 704 register int more; 705 706 if (!FIXUNDO) 707 return; 708 #ifdef UNDOTRACE 709 if (trace) 710 vudump("before save"); 711 #endif 712 undkind = UNDNONE; 713 undadot = dot; 714 more = (a2 - a1 + 1) - (unddol - dol); 715 while (more > (endcore - truedol)) 716 if (morelines() < 0) 717 error(value(vi_TERSE) ? gettext("Out of memory") : 718 gettext("Out of memory saving lines for undo - try using ed")); 719 if (more) 720 (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1, 721 (truedol - unddol)); 722 unddol += more; 723 truedol += more; 724 copyw(dol + 1, a1, a2 - a1 + 1); 725 undkind = UNDALL; 726 unddel = a1 - 1; 727 undap1 = a1; 728 undap2 = a2 + 1; 729 #ifdef UNDOTRACE 730 if (trace) 731 vudump("after save"); 732 #endif 733 } 734 735 save12() 736 { 737 738 save(addr1, addr2); 739 } 740 741 saveall() 742 { 743 744 save(one, dol); 745 } 746 747 span() 748 { 749 750 return (addr2 - addr1 + 1); 751 } 752 753 sync() 754 { 755 756 chng = 0; 757 tchng = 0; 758 xchng = 0; 759 } 760 761 762 skipwh() 763 { 764 register int wh; 765 766 wh = 0; 767 while (iswhite(peekchar())) { 768 wh++; 769 ignchar(); 770 } 771 return (wh); 772 } 773 774 /*VARARGS2*/ 775 smerror(seekpt, cp) 776 unsigned char *seekpt; 777 unsigned char *cp; 778 { 779 780 errcnt++; 781 merror1(seekpt); 782 if (inopen && clr_eol) 783 vclreol(); 784 if (enter_standout_mode && exit_bold) 785 putpad(enter_standout_mode); 786 lprintf(mesg(linebuf), cp); 787 if (enter_standout_mode && exit_bold) 788 putpad(exit_bold); 789 } 790 791 unsigned char * 792 strend(cp) 793 register unsigned char *cp; 794 { 795 796 while (*cp) 797 cp++; 798 return (cp); 799 } 800 801 strcLIN(dp) 802 unsigned char *dp; 803 { 804 805 CP(linebuf, dp); 806 } 807 808 /* 809 * A system error has occurred that we need to perror. 810 * danger is true if we are unsure of the contents of 811 * the file or our buffer, e.g. a write error in the 812 * middle of a write operation, or a temp file error. 813 */ 814 syserror(danger) 815 int danger; 816 { 817 register int e = errno; 818 char *errstr; 819 extern char *strerror(); 820 821 dirtcnt = 0; 822 putchar(' '); 823 if (danger) 824 edited = 0; /* for temp file errors, for example */ 825 if ((errstr = strerror(e)) != NULL) 826 error(errstr); 827 else 828 error(gettext("System error %d"), e); 829 } 830 831 /* 832 * Return the column number that results from being in column col and 833 * hitting a tab, where tabs are set every ts columns. Work right for 834 * the case where col > columns, even if ts does not divide columns. 835 */ 836 tabcol(col, ts) 837 int col, ts; 838 { 839 int offset, result; 840 841 if (col >= columns) { 842 offset = columns * (col/columns); 843 col -= offset; 844 } else 845 offset = 0; 846 result = col + ts - (col % ts) + offset; 847 return (result); 848 } 849 850 unsigned char * 851 vfindcol(i) 852 int i; 853 { 854 register unsigned char *cp, *oldcp; 855 register int (*OO)() = Outchar; 856 register int length; 857 unsigned char x; 858 wchar_t wchar; 859 860 Outchar = qcount; 861 (void)qcolumn(linebuf - 1, NOSTR); 862 for (cp = linebuf; *cp && vcntcol < i; ) { 863 oldcp = cp; 864 length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX); 865 if(length < 0) { 866 putoctal = 1; 867 putchar(*cp++); 868 putoctal = 0; 869 } else { 870 putchar(wchar); 871 cp += length; 872 } 873 } 874 if (cp != linebuf) 875 cp = oldcp; 876 Outchar = OO; 877 return (cp); 878 } 879 880 unsigned char * 881 vskipwh(cp) 882 register unsigned char *cp; 883 { 884 885 while (iswhite(*cp) && cp[1]) 886 cp++; 887 return (cp); 888 } 889 890 891 unsigned char * 892 vpastwh(cp) 893 register unsigned char *cp; 894 { 895 896 while (iswhite(*cp)) 897 cp++; 898 return (cp); 899 } 900 901 whitecnt(cp) 902 register unsigned char *cp; 903 { 904 register int i; 905 906 i = 0; 907 for (;;) 908 switch (*cp++) { 909 910 case '\t': 911 i += value(vi_TABSTOP) - i % value(vi_TABSTOP); 912 break; 913 914 case ' ': 915 i++; 916 break; 917 918 default: 919 return (i); 920 } 921 } 922 923 markit(addr) 924 line *addr; 925 { 926 927 if (addr != dot && addr >= one && addr <= dol) 928 markDOT(); 929 } 930 931 /* 932 * The following code is defensive programming against a bug in the 933 * pdp-11 overlay implementation. Sometimes it goes nuts and asks 934 * for an overlay with some garbage number, which generates an emt 935 * trap. This is a less than elegant solution, but it is somewhat 936 * better than core dumping and losing your work, leaving your tty 937 * in a weird state, etc. 938 */ 939 int _ovno; 940 941 /*ARGSUSED*/ 942 void 943 onemt(sig) 944 int sig; 945 { 946 int oovno; 947 948 signal(SIGEMT, onemt); 949 oovno = _ovno; 950 /* 2 and 3 are valid on 11/40 type vi, so */ 951 if (_ovno < 0 || _ovno > 3) 952 _ovno = 0; 953 error(value(vi_TERSE) ? gettext("emt trap, _ovno is %d ") : 954 gettext("emt trap, _ovno is %d - try again")); 955 } 956 957 /* 958 * When a hangup occurs our actions are similar to a preserve 959 * command. If the buffer has not been [Modified], then we do 960 * nothing but remove the temporary files and exit. 961 * Otherwise, we sync the temp file and then attempt a preserve. 962 * If the preserve succeeds, we unlink our temp files. 963 * If the preserve fails, we leave the temp files as they are 964 * as they are a backup even without preservation if they 965 * are not removed. 966 */ 967 968 /*ARGSUSED*/ 969 void 970 onhup(sig) 971 int sig; 972 { 973 974 /* 975 * USG tty driver can send multiple HUP's!! 976 */ 977 signal(SIGINT, SIG_IGN); 978 signal(SIGHUP, SIG_IGN); 979 if (chng == 0) { 980 cleanup(1); 981 exit(++errcnt); 982 } 983 if (setexit() == 0) { 984 if (preserve()) { 985 cleanup(1); 986 exit(++errcnt); 987 } 988 } 989 if (kflag) 990 crypt_close(perm); 991 if (xtflag) 992 crypt_close(tperm); 993 exit(++errcnt); 994 } 995 996 /* 997 * Similar to onhup. This happens when any random core dump occurs, 998 * e.g. a bug in vi. We preserve the file and then generate a core. 999 */ 1000 void oncore(sig) 1001 int sig; 1002 { 1003 static int timescalled = 0; 1004 char *messagep; /* for message localization */ 1005 1006 /* 1007 * USG tty driver can send multiple HUP's!! 1008 */ 1009 signal(SIGINT, SIG_IGN); 1010 signal(SIGHUP, SIG_IGN); 1011 signal(sig, SIG_DFL); /* Insure that we don't catch it again */ 1012 messagep = (char *)gettext("\r\nYour file has been preserved\r\n"); 1013 if (timescalled++ == 0 && chng && setexit() == 0) { 1014 if (inopen) 1015 vsave(); 1016 preserve(); 1017 write(1, messagep, strlen(messagep)); 1018 } 1019 if (timescalled < 2) { 1020 normal(normf); 1021 cleanup(2); 1022 kill(getpid(), sig); /* Resend ourselves the same signal */ 1023 /* We won't get past here */ 1024 } 1025 if (kflag) 1026 crypt_close(perm); 1027 if (xtflag) 1028 crypt_close(tperm); 1029 exit(++errcnt); 1030 } 1031 1032 /* 1033 * An interrupt occurred. Drain any output which 1034 * is still in the output buffering pipeline. 1035 * Catch interrupts again. Unless we are in visual 1036 * reset the output state (out of -nl mode, e.g). 1037 * Then like a normal error (with the \n before Interrupt 1038 * suppressed in visual mode). 1039 */ 1040 1041 /*ARGSUSED*/ 1042 void 1043 onintr(sig) 1044 int sig; 1045 { 1046 #ifndef CBREAK 1047 signal(SIGINT, onintr); 1048 #else 1049 signal(SIGINT, inopen ? vintr : onintr); 1050 #endif 1051 cancelalarm(); 1052 draino(); 1053 if (!inopen) { 1054 pstop(); 1055 setlastchar('\n'); 1056 #ifdef CBREAK 1057 } 1058 #else 1059 } else 1060 vraw(); 1061 #endif 1062 error(gettext("\nInterrupt") + (inopen!=0)); 1063 } 1064 1065 /* 1066 * If we are interruptible, enable interrupts again. 1067 * In some critical sections we turn interrupts off, 1068 * but not very often. 1069 */ 1070 setrupt() 1071 { 1072 1073 if (ruptible) { 1074 #ifndef CBREAK 1075 signal(SIGINT, onintr); 1076 #else 1077 signal(SIGINT, inopen ? vintr : onintr); 1078 #endif 1079 #ifdef SIGTSTP 1080 if (dosusp) 1081 signal(SIGTSTP, onsusp); 1082 #endif 1083 } 1084 } 1085 1086 preserve() 1087 { 1088 1089 #ifdef VMUNIX 1090 tflush(); 1091 #endif 1092 synctmp(); 1093 pid = fork(); 1094 if (pid < 0) 1095 return (0); 1096 if (pid == 0) { 1097 close(0); 1098 dup(tfile); 1099 execlp(EXPRESERVE, "expreserve", (char *) 0); 1100 exit(++errcnt); 1101 } 1102 waitfor(); 1103 if (rpid == pid && status == 0) 1104 return (1); 1105 return (0); 1106 } 1107 1108 #ifndef V6 1109 void exit(i) 1110 int i; 1111 { 1112 1113 #ifdef TRACE 1114 if (trace) 1115 fclose(trace); 1116 #endif 1117 _exit(i); 1118 } 1119 #endif 1120 1121 #ifdef SIGTSTP 1122 /* 1123 * We have just gotten a susp. Suspend and prepare to resume. 1124 */ 1125 extern void redraw(); 1126 1127 /*ARGSUSED*/ 1128 void 1129 onsusp(sig) 1130 int sig; 1131 { 1132 ttymode f; 1133 int savenormtty; 1134 1135 f = setty(normf); 1136 vnfl(); 1137 putpad(exit_ca_mode); 1138 flush(); 1139 resetterm(); 1140 savenormtty = normtty; 1141 normtty = 0; 1142 1143 signal(SIGTSTP, SIG_DFL); 1144 kill(0, SIGTSTP); 1145 1146 /* the pc stops here */ 1147 1148 signal(SIGTSTP, onsusp); 1149 normtty = savenormtty; 1150 vcontin(0); 1151 flush(); 1152 setty(f); 1153 if (!inopen) 1154 error(0); 1155 else { 1156 if(vcnt < 0) { 1157 vcnt = -vcnt; 1158 if(state == VISUAL) 1159 vclear(); 1160 else if(state == CRTOPEN) 1161 vcnt = 0; 1162 } 1163 vdirty(0, lines); 1164 if (sig) 1165 vrepaint(cursor); 1166 } 1167 } 1168 #endif 1169 1170 unsigned char *nextchr(cursor) 1171 unsigned char *cursor; 1172 { 1173 1174 wchar_t wchar; 1175 int length; 1176 length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX); 1177 if(length <= 0) 1178 return(++cursor); 1179 return(cursor + length); 1180 } 1181 1182 unsigned char *lastchr(linebuf, cursor) 1183 unsigned char *linebuf, *cursor; 1184 { 1185 wchar_t wchar; 1186 int length; 1187 unsigned char *ccursor, *ocursor; 1188 if(cursor == linebuf) 1189 return(linebuf - 1); 1190 ccursor = ocursor = linebuf; 1191 while(ccursor < cursor) { 1192 length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX); 1193 ocursor = ccursor; 1194 if(length <= 0) 1195 ccursor++; 1196 else 1197 ccursor += length; 1198 } 1199 return(ocursor); 1200 } 1201 1202 ixlatctl(flag) 1203 int flag; 1204 { 1205 static struct strioctl sb = {0, 0, 0, 0}; 1206 1207 if (!(MULTI_BYTE_MAX > 1)) 1208 return (0); 1209 1210 switch (flag) { 1211 case 0: 1212 sb.ic_cmd = EUC_MSAVE; 1213 sb.ic_len = 0; 1214 sb.ic_dp = 0; 1215 if (ioctl(0, I_STR, &sb) < 0) 1216 return (-1); 1217 return (0); 1218 case 1: 1219 sb.ic_cmd = EUC_MREST; 1220 sb.ic_len = 0; 1221 sb.ic_dp = 0; 1222 if (ioctl(0, I_STR, &sb) < 0) 1223 return (-1); 1224 return (0); 1225 case 11: 1226 return (0); 1227 default: 1228 return (-1); 1229 } 1230 } 1231 #ifndef PRESUNEUC 1232 1233 /* locale specific initialization */ 1234 int localize() 1235 { 1236 wchar_t fillerchar; 1237 extern int wdchkind(); 1238 extern int wdbindf(); 1239 extern wchar_t *wddelim(); 1240 extern wchar_t mcfiller(); 1241 1242 wdwc = wdchkind; 1243 wdbdg = wdbindf; 1244 wddlm = wddelim; 1245 mcfllr = mcfiller; 1246 mc_wrap = 1; 1247 fillerchar = mcfiller(); 1248 mc_filler = isascii(fillerchar) ? (fillerchar & 0x7f) : '~'; 1249 } 1250 #endif /* PRESUNEUC */ 1251