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