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