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
any(int c,unsigned char * s)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
backtab(int i)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
change(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
column(unsigned char * cp)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
lcolumn(unsigned char * cp)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
comment(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
Copy(unsigned char * to,unsigned char * from,int size)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
copyw(line * to,line * from,int size)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
copywR(line * to,line * from,int size)152 copywR(line *to, line *from, int size)
153 {
154
155 while (--size >= 0)
156 to[size] = from[size];
157 }
158
159 int
ctlof(int c)160 ctlof(int c)
161 {
162
163 return (c == DELETE ? '?' : c | ('A' - 1));
164 }
165
166 void
dingdong(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
fixindent(int indent)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
filioerr(unsigned char * cp)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 *
genindent(indent)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
getDOT(void)216 getDOT(void)
217 {
218
219 getaline(*dot);
220 }
221
222 line *
getmark(c)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
ignnEOF(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
iswhite(int c)247 iswhite(int c)
248 {
249
250 return (c == ' ' || c == '\t');
251 }
252
253 int
junk(wchar_t c)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
killed(void)274 killed(void)
275 {
276
277 killcnt(addr2 - addr1 + 1);
278 }
279
280 void
killcnt(int cnt)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
lineno(line * a)305 lineno(line *a)
306 {
307
308 return (a - zero);
309 }
310
311 int
lineDOL(void)312 lineDOL(void)
313 {
314
315 return (lineno(dol));
316 }
317
318 int
lineDOT(void)319 lineDOT(void)
320 {
321
322 return (lineno(dot));
323 }
324
325 void
markDOT(void)326 markDOT(void)
327 {
328
329 markpr(dot);
330 }
331
332 void
markpr(line * which)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
markreg(int c)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 *
mesg(str)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
merror(unsigned char * seekpt,int i)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
merror1(unsigned char * seekpt)415 merror1(unsigned char *seekpt)
416 {
417
418 strcpy(linebuf, seekpt);
419 }
420
421 #define MAXDATA (56*1024)
422 int
morelines(void)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
nonzero(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
notable(int i)457 notable(int i)
458 {
459
460 return (hush == 0 && !inglobal && i > value(vi_REPORT));
461 }
462
463
464 void
notempty(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
netchHAD(int cnt)475 netchHAD(int cnt)
476 {
477
478 netchange(lineDOL() - cnt);
479 }
480
481 void
netchange(int i)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
putmark(line * addr)529 putmark(line *addr)
530 {
531
532 putmk1(addr, putline());
533 }
534
535 void
putmk1(line * addr,int n)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 *
plural(i)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
qcolumn(unsigned char * lim,unsigned char * gp)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
nqcolumn(unsigned char * lim,unsigned char * gp)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
qcount(c)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
reverse(line * a1,line * a2)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
save(line * a1,line * a2)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
save12(void)727 save12(void)
728 {
729
730 save(addr1, addr2);
731 }
732
733 void
saveall(void)734 saveall(void)
735 {
736
737 save(one, dol);
738 }
739
740 int
span(void)741 span(void)
742 {
743
744 return (addr2 - addr1 + 1);
745 }
746
747 void
sync(void)748 sync(void)
749 {
750
751 chng = 0;
752 tchng = 0;
753 xchng = 0;
754 }
755
756
757 int
skipwh(void)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
smerror(unsigned char * seekpt,unsigned char * cp)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 *
strend(cp)787 strend(cp)
788 unsigned char *cp;
789 {
790
791 while (*cp)
792 cp++;
793 return (cp);
794 }
795
796 void
strcLIN(unsigned char * dp)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
syserror(int danger)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
tabcol(int col,int ts)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 *
vfindcol(i)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 *
vskipwh(cp)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 *
vpastwh(cp)887 vpastwh(cp)
888 unsigned char *cp;
889 {
890
891 while (iswhite(*cp))
892 cp++;
893 return (cp);
894 }
895
896 int
whitecnt(unsigned char * cp)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
markit(line * addr)919 markit(line *addr)
920 {
921
922 if (addr != dot && addr >= one && addr <= dol)
923 markDOT();
924 }
925
926 /*
927 * When a hangup occurs our actions are similar to a preserve
928 * command. If the buffer has not been [Modified], then we do
929 * nothing but remove the temporary files and exit.
930 * Otherwise, we sync the temp file and then attempt a preserve.
931 * If the preserve succeeds, we unlink our temp files.
932 * If the preserve fails, we leave the temp files as they are
933 * as they are a backup even without preservation if they
934 * are not removed.
935 */
936
937 /*ARGSUSED*/
938 void
onhup(sig)939 onhup(sig)
940 int sig;
941 {
942
943 /*
944 * USG tty driver can send multiple HUP's!!
945 */
946 signal(SIGINT, SIG_IGN);
947 signal(SIGHUP, SIG_IGN);
948 if (chng == 0) {
949 cleanup(1);
950 exit(++errcnt);
951 }
952 if (setexit() == 0) {
953 if (preserve()) {
954 cleanup(1);
955 exit(++errcnt);
956 }
957 }
958 if (kflag)
959 crypt_close(perm);
960 if (xtflag)
961 crypt_close(tperm);
962 exit(++errcnt);
963 }
964
965 /*
966 * Similar to onhup. This happens when any random core dump occurs,
967 * e.g. a bug in vi. We preserve the file and then generate a core.
968 */
oncore(sig)969 void oncore(sig)
970 int sig;
971 {
972 static int timescalled = 0;
973 char *messagep; /* for message localization */
974
975 /*
976 * USG tty driver can send multiple HUP's!!
977 */
978 signal(SIGINT, SIG_IGN);
979 signal(SIGHUP, SIG_IGN);
980 signal(sig, SIG_DFL); /* Insure that we don't catch it again */
981 messagep = (char *)gettext("\r\nYour file has been preserved\r\n");
982 if (timescalled++ == 0 && chng && setexit() == 0) {
983 if (inopen)
984 vsave();
985 (void) preserve();
986 write(1, messagep, strlen(messagep));
987 }
988 if (timescalled < 2) {
989 normal(normf);
990 cleanup(2);
991 kill(getpid(), sig); /* Resend ourselves the same signal */
992 /* We won't get past here */
993 }
994 if (kflag)
995 crypt_close(perm);
996 if (xtflag)
997 crypt_close(tperm);
998 exit(++errcnt);
999 }
1000
1001 /*
1002 * An interrupt occurred. Drain any output which
1003 * is still in the output buffering pipeline.
1004 * Catch interrupts again. Unless we are in visual
1005 * reset the output state (out of -nl mode, e.g).
1006 * Then like a normal error (with the \n before Interrupt
1007 * suppressed in visual mode).
1008 */
1009
1010 /*ARGSUSED*/
1011 void
onintr(sig)1012 onintr(sig)
1013 int sig;
1014 {
1015 #ifndef CBREAK
1016 signal(SIGINT, onintr);
1017 #else
1018 signal(SIGINT, inopen ? vintr : onintr);
1019 #endif
1020 cancelalarm();
1021 draino();
1022 if (!inopen) {
1023 pstop();
1024 setlastchar('\n');
1025 #ifdef CBREAK
1026 }
1027 #else
1028 } else
1029 vraw();
1030 #endif
1031 error(gettext("\nInterrupt") + (inopen!=0));
1032 }
1033
1034 /*
1035 * If we are interruptible, enable interrupts again.
1036 * In some critical sections we turn interrupts off,
1037 * but not very often.
1038 */
1039 void
setrupt(void)1040 setrupt(void)
1041 {
1042
1043 if (ruptible) {
1044 #ifndef CBREAK
1045 signal(SIGINT, onintr);
1046 #else
1047 signal(SIGINT, inopen ? vintr : onintr);
1048 #endif
1049 #ifdef SIGTSTP
1050 if (dosusp)
1051 signal(SIGTSTP, onsusp);
1052 #endif
1053 }
1054 }
1055
1056 int
preserve(void)1057 preserve(void)
1058 {
1059
1060 #ifdef VMUNIX
1061 tflush();
1062 #endif
1063 synctmp();
1064 pid = fork();
1065 if (pid < 0)
1066 return (0);
1067 if (pid == 0) {
1068 close(0);
1069 dup(tfile);
1070 execlp(EXPRESERVE, "expreserve", (char *) 0);
1071 exit(++errcnt);
1072 }
1073 waitfor();
1074 if (rpid == pid && status == 0)
1075 return (1);
1076 return (0);
1077 }
1078
1079 #ifndef V6
exit(i)1080 void exit(i)
1081 int i;
1082 {
1083
1084 extern void _exit(int) __NORETURN;
1085 #ifdef TRACE
1086 if (trace)
1087 fclose(trace);
1088 #endif
1089 _exit(i);
1090 }
1091 #endif
1092
1093 #ifdef SIGTSTP
1094 /*
1095 * We have just gotten a susp. Suspend and prepare to resume.
1096 */
1097 extern void redraw();
1098
1099 /*ARGSUSED*/
1100 void
onsusp(sig)1101 onsusp(sig)
1102 int sig;
1103 {
1104 ttymode f;
1105 int savenormtty;
1106
1107 f = setty(normf);
1108 vnfl();
1109 putpad((unsigned char *)exit_ca_mode);
1110 flush();
1111 resetterm();
1112 savenormtty = normtty;
1113 normtty = 0;
1114
1115 signal(SIGTSTP, SIG_DFL);
1116 kill(0, SIGTSTP);
1117
1118 /* the pc stops here */
1119
1120 signal(SIGTSTP, onsusp);
1121 normtty = savenormtty;
1122 vcontin(0);
1123 flush();
1124 setty(f);
1125 if (!inopen)
1126 error(0);
1127 else {
1128 if(vcnt < 0) {
1129 vcnt = -vcnt;
1130 if(state == VISUAL)
1131 vclear();
1132 else if(state == CRTOPEN)
1133 vcnt = 0;
1134 }
1135 vdirty(0, lines);
1136 if (sig)
1137 vrepaint(cursor);
1138 }
1139 }
1140 #endif
1141
nextchr(cursor)1142 unsigned char *nextchr(cursor)
1143 unsigned char *cursor;
1144 {
1145
1146 wchar_t wchar;
1147 int length;
1148 length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX);
1149 if(length <= 0)
1150 return(++cursor);
1151 return(cursor + length);
1152 }
1153
lastchr(linebuf,cursor)1154 unsigned char *lastchr(linebuf, cursor)
1155 unsigned char *linebuf, *cursor;
1156 {
1157 wchar_t wchar;
1158 int length;
1159 unsigned char *ccursor, *ocursor;
1160 if(cursor == linebuf)
1161 return(linebuf - 1);
1162 ccursor = ocursor = linebuf;
1163 while(ccursor < cursor) {
1164 length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX);
1165 ocursor = ccursor;
1166 if(length <= 0)
1167 ccursor++;
1168 else
1169 ccursor += length;
1170 }
1171 return(ocursor);
1172 }
1173
1174 int
ixlatctl(int flag)1175 ixlatctl(int flag)
1176 {
1177 static struct strioctl sb = {0, 0, 0, 0};
1178
1179 if (!(MULTI_BYTE_MAX > 1))
1180 return (0);
1181
1182 switch (flag) {
1183 case 0:
1184 sb.ic_cmd = EUC_MSAVE;
1185 sb.ic_len = 0;
1186 sb.ic_dp = 0;
1187 if (ioctl(0, I_STR, &sb) < 0)
1188 return (-1);
1189 return (0);
1190 case 1:
1191 sb.ic_cmd = EUC_MREST;
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 11:
1198 return (0);
1199 default:
1200 return (-1);
1201 }
1202 }
1203 #ifndef PRESUNEUC
1204
1205 /* locale specific initialization */
1206 void
localize(void)1207 localize(void)
1208 {
1209 wchar_t fillerchar;
1210 extern int wdchkind();
1211 extern int wdbindf();
1212 extern wchar_t *wddelim();
1213 extern wchar_t mcfiller();
1214
1215 wdwc = wdchkind;
1216 wdbdg = wdbindf;
1217 wddlm = wddelim;
1218 mcfllr = mcfiller;
1219 mc_wrap = 1;
1220 fillerchar = mcfiller();
1221 mc_filler = isascii(fillerchar) ? (fillerchar & 0x7f) : '~';
1222 }
1223 #endif /* PRESUNEUC */
1224