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