1 /*
2 * This code contains changes by
3 * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
4 *
5 * Conditions 1, 2, and 4 and the no-warranty notice below apply
6 * to these changes.
7 *
8 *
9 * Copyright (c) 1980, 1993
10 * The Regents of the University of California. All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 *
41 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * Redistributions of source code and documentation must retain the
47 * above copyright notice, this list of conditions and the following
48 * disclaimer.
49 * Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed or owned by Caldera
55 * International, Inc.
56 * Neither the name of Caldera International, Inc. nor the names of
57 * other contributors may be used to endorse or promote products
58 * derived from this software without specific prior written permission.
59 *
60 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
65 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
68 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
69 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
71 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72 */
73
74 #ifndef lint
75 #ifdef DOSCCS
76 static char sccsid[] = "@(#)ex_subr.c 1.37 (gritter) 2/15/05";
77 #endif
78 #endif
79
80 /* from ex_subr.c 7.10.1 (2.11BSD) 1996/3/22 */
81
82 #include "ex.h"
83 #include "ex_re.h"
84 #include "ex_tty.h"
85 #include "ex_vis.h"
86
87 static short lastsc;
88
89 /*
90 * Random routines, in alphabetical order.
91 */
92
93 int
any(int c,register char * s)94 any(int c, register char *s)
95 {
96 register int x;
97
98 while (x = *s++)
99 if (x == c)
100 return (1);
101 return (0);
102 }
103
104 int
backtab(register int i)105 backtab(register int i)
106 {
107 register int j;
108
109 j = i % value(SHIFTWIDTH);
110 if (j == 0)
111 j = value(SHIFTWIDTH);
112 i -= j;
113 if (i < 0)
114 i = 0;
115 return (i);
116 }
117
118 void
change(void)119 change(void)
120 {
121
122 tchng++;
123 chng = tchng;
124 fixedzero = 0;
125 }
126
127 /*
128 * Column returns the number of
129 * columns occupied by printing the
130 * characters through position cp of the
131 * current line.
132 */
133 int
column(register char * cp)134 column(register char *cp)
135 {
136
137 if (cp == 0)
138 cp = &linebuf[LBSIZE - 2];
139 return (qcolumn(cp, NULL));
140 }
141
142 int
lcolumn(register char * cp)143 lcolumn(register char *cp)
144 {
145 return column(cp) - (lastsc - 1);
146 }
147
148 /*
149 * Ignore a comment to the end of the line.
150 * This routine eats the trailing newline so don't call newline().
151 */
152 void
comment(void)153 comment(void)
154 {
155 register int c;
156
157 do {
158 c = getchar();
159 } while (c != '\n' && c != EOF);
160 if (c == EOF)
161 ungetchar(c);
162 }
163
164 void
Copy(register char * to,register char * from,register int size)165 Copy(register char *to, register char *from, register int size)
166 {
167
168 if (size > 0)
169 do
170 *to++ = *from++;
171 while (--size > 0);
172 }
173
174 void
copyw(register line * to,register line * from,register int size)175 copyw(register line *to, register line *from, register int size)
176 {
177
178 if (size > 0)
179 do
180 *to++ = *from++;
181 while (--size > 0);
182 }
183
184 void
copywR(register line * to,register line * from,register int size)185 copywR(register line *to, register line *from, register int size)
186 {
187
188 while (--size >= 0)
189 to[size] = from[size];
190 }
191
192 int
ctlof(int c)193 ctlof(int c)
194 {
195
196 return (c == DELETE ? '?' : c | ('A' - 1));
197 }
198
199 void
dingdong(void)200 dingdong(void)
201 {
202
203 if (VB)
204 putpad(VB);
205 else if (value(ERRORBELLS))
206 putch('\207');
207 }
208
209 int
fixindent(int indent)210 fixindent(int indent)
211 {
212 register int i;
213 register char *cp;
214
215 i = whitecnt(genbuf);
216 cp = vpastwh(genbuf);
217 if (*cp == 0 && i == indent && linebuf[0] == 0) {
218 genbuf[0] = 0;
219 return (i);
220 }
221 CP(genindent(i), cp);
222 return (i);
223 }
224
225 void
filioerr(char * cp)226 filioerr(char *cp)
227 {
228 register int oerrno = errno;
229
230 lprintf("\"%s\"", cp);
231 errno = oerrno;
232 syserror();
233 }
234
235 char *
genindent(register int indent)236 genindent(register int indent)
237 {
238 register char *cp;
239
240 for (cp = genbuf; indent >= value(TABSTOP); indent -= value(TABSTOP))
241 *cp++ = '\t';
242 for (; indent > 0; indent--)
243 *cp++ = ' ';
244 return (cp);
245 }
246
247 void
getDOT(void)248 getDOT(void)
249 {
250
251 getline(*dot);
252 }
253
254 line *
getmark(register int c)255 getmark(register int c)
256 {
257 register line *addr;
258
259 for (addr = one; addr <= dol; addr++)
260 if (names[c - 'a'] == (*addr &~ 01)) {
261 return (addr);
262 }
263 return (0);
264 }
265
266 int
getn(register char * cp)267 getn(register char *cp)
268 {
269 register int i = 0;
270
271 while (isdigit(*cp&0377))
272 i = i * 10 + *cp++ - '0';
273 if (*cp)
274 return (0);
275 return (i);
276 }
277
278 void
ignnEOF(void)279 ignnEOF(void)
280 {
281 register int c = getchar();
282
283 if (c == EOF)
284 ungetchar(c);
285 else if (c=='"')
286 comment();
287 }
288
289 int
is_white(int c)290 is_white(int c)
291 {
292
293 #ifndef BIT8
294 return (c == ' ' || c == '\t');
295 #else
296 return (isspace(c&0377) && c != '\n' && c != '\r'
297 && c != '\f' && c != '\v');
298 #endif
299 }
300
301 int
junk(register int c)302 junk(register int c)
303 {
304
305 if (c && !value(BEAUTIFY))
306 return (0);
307 #ifndef BIT8
308 if (c >= ' ' && c != DELETE)
309 #else
310 if (printable(c))
311 #endif
312 return (0);
313 switch (c) {
314
315 case '\t':
316 case '\n':
317 case '\f':
318 return (0);
319
320 default:
321 return (1);
322 }
323 }
324
325 void
killed(void)326 killed(void)
327 {
328
329 killcnt(addr2 - addr1 + 1);
330 }
331
332 void
killcnt(register int cnt)333 killcnt(register int cnt)
334 {
335
336 if (inopen) {
337 notecnt = cnt;
338 notenam = notesgn = "";
339 return;
340 }
341 if (!notable(cnt))
342 return;
343 printf(catgets(catd, 1, 170, "%d lines"), cnt);
344 if (value(TERSE) == 0) {
345 printf(catgets(catd, 1, 171, " %c%s"),
346 Command[0] | ' ', Command + 1);
347 if (Command[strlen(Command) - 1] != 'e')
348 putchar('e');
349 putchar('d');
350 }
351 putNFL();
352 }
353
354 int
lineno(line * a)355 lineno(line *a)
356 {
357
358 return (a - zero);
359 }
360
361 int
lineDOL(void)362 lineDOL(void)
363 {
364
365 return (lineno(dol));
366 }
367
368 int
lineDOT(void)369 lineDOT(void)
370 {
371
372 return (lineno(dot));
373 }
374
375 void
markDOT(void)376 markDOT(void)
377 {
378
379 markpr(dot);
380 }
381
382 void
markpr(line * which)383 markpr(line *which)
384 {
385
386 if ((inglobal == 0 || inopen) && which <= endcore) {
387 names['z'-'a'+1] = *which & ~01;
388 if (inopen)
389 ncols['z'-'a'+1] = cursor;
390 }
391 }
392
393 int
markreg(register int c)394 markreg(register int c)
395 {
396
397 if (c == '\'' || c == '`')
398 return ('z' + 1);
399 if (c >= 'a' && c <= 'z')
400 return (c);
401 return (0);
402 }
403
404 /*
405 * Mesg decodes the terse/verbose strings. Thus
406 * 'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
407 * 'xxx|yyy' -> 'xxx' if terse, else 'yyy'
408 * All others map to themselves.
409 */
410 char *
mesg(register char * str)411 mesg(register char *str)
412 {
413 register char *cp;
414
415 str = strcpy(genbuf, str);
416 for (cp = str; *cp; cp++)
417 switch (*cp) {
418
419 case '@':
420 if (value(TERSE))
421 *cp = 0;
422 else
423 *cp = ' ';
424 break;
425
426 case '|':
427 if (value(TERSE) == 0)
428 return (cp + 1);
429 *cp = 0;
430 break;
431 }
432 return (str);
433 }
434
435 void
merror1(intptr_t seekpt)436 merror1(intptr_t seekpt)
437 {
438
439 #ifdef VMUNIX
440 strcpy(linebuf, (char *)seekpt);
441 #else
442 lseek(erfile, (off_t) seekpt, SEEK_SET);
443 if (read(erfile, linebuf, 128) < 2)
444 CP(linebuf, "ERROR");
445 #endif
446 }
447
448 /*VARARGS2*/
449 void
vmerror(char * seekpt,va_list ap)450 vmerror(char *seekpt, va_list ap)
451 {
452
453 register char *cp = linebuf;
454
455 if (seekpt == 0)
456 return;
457 merror1((intptr_t)seekpt);
458 if (*cp == '\n')
459 putnl(), cp++;
460 if (inopen > 0 && CE)
461 vclreol();
462 if (SO && SE)
463 putpad(SO);
464 vprintf(mesg(cp), ap);
465 if (SO && SE)
466 putpad(SE);
467 }
468
469 void
merror(char * cp,...)470 merror(char *cp, ...)
471 {
472 va_list ap;
473
474 if (cp == NULL)
475 return;
476 va_start(ap, cp);
477 vmerror(cp, ap);
478 va_end(ap);
479 }
480
481 int
morelines(void)482 morelines(void)
483 {
484 #ifdef _SC_PAGESIZE
485 static long pg;
486
487 if (pg == 0) {
488 pg = sysconf(_SC_PAGESIZE);
489 if (pg <= 0 || pg >= 65536)
490 pg = 4096;
491 pg /= sizeof (line);
492 }
493 if ((char *)sbrk(pg * sizeof (line)) == (char *)-1)
494 return (-1);
495 endcore += pg;
496 return (0);
497 #else /* !_SC_PAGESIZE */
498 if (sbrk(1024 * sizeof (line)) == (char *)-1)
499 return (-1);
500 endcore += 1024;
501 return (0);
502 #endif /* !_SC_PAGESIZE */
503 }
504
505 void
nonzero(void)506 nonzero(void)
507 {
508
509 if (addr1 == zero) {
510 notempty();
511 error(catgets(catd, 1, 172,
512 "Nonzero address required@on this command"));
513 }
514 }
515
516 int
notable(int i)517 notable(int i)
518 {
519
520 return (hush == 0 && !inglobal && i > value(REPORT));
521 }
522
523
524 void
notempty(void)525 notempty(void)
526 {
527
528 if (dol == zero)
529 error(catgets(catd, 1, 173, "No lines@in the buffer"));
530 }
531
532
533 void
netchHAD(int cnt)534 netchHAD(int cnt)
535 {
536
537 netchange(lineDOL() - cnt);
538 }
539
540 void
netchange(register int i)541 netchange(register int i)
542 {
543 register char *cp;
544
545 if (i > 0)
546 notesgn = cp = catgets(catd, 1, 174, "more ");
547 else
548 notesgn = cp = catgets(catd, 1, 175, "fewer "), i = -i;
549 if (inopen) {
550 notecnt = i;
551 notenam = catgets(catd, 1, 176, "");
552 return;
553 }
554 if (!notable(i))
555 return;
556 printf(mesg(catgets(catd, 1, 177, "%d %slines@in file after %s")),
557 i, cp, Command);
558 putNFL();
559 }
560
561 /*
562 * Print an escape sequence corresponding to c.
563 */
564 #ifdef BIT8
565 int
printof(int c)566 printof(int c)
567 {
568 char *nums = "01234567";
569 int d;
570
571 #ifdef MB
572 if (mb_cur_max > 1 && (c & INVBIT) == 0 && c & ~0177) {
573 char mb[MB_LEN_MAX];
574 int i, n, x = EOF;
575 if ((n = wctomb(mb, c & TRIM)) <= 0) {
576 n = 1;
577 *mb = 0;
578 }
579 for (i = 0; i < n; i++) {
580 x = printof(mb[i] | INVBIT);
581 if (i+1 < n)
582 normchar(x);
583 }
584 return x;
585 }
586 #endif /* MB */
587 c &= 0377;
588 if (c < 040 || c == DELETE) {
589 normchar('^');
590 return (c == DELETE ? '?' : c | ('A' - 1));
591 }
592 normchar('\\');
593 normchar(nums[(c & ~077) >> 6]);
594 c &= 077;
595 d = c & 07;
596 if (c > d)
597 normchar(nums[(c - d) >> 3]);
598 else
599 normchar(nums[0]);
600 return nums[d];
601 }
602 #endif
603
604 void
putmark(line * addr)605 putmark(line *addr)
606 {
607
608 putmk1(addr, putline());
609 }
610
611 void
putmk1(register line * addr,int n)612 putmk1(register line *addr, int n)
613 {
614 register line *markp;
615 register int oldglobmk;
616
617 oldglobmk = *addr & 1;
618 *addr &= ~1;
619 for (markp = (anymarks ? names : &names['z'-'a'+1]);
620 markp <= &names['z'-'a'+1]; markp++)
621 if (*markp == *addr)
622 *markp = n;
623 *addr = n | oldglobmk;
624 }
625
626 char *
plural(long i)627 plural(long i)
628 {
629
630 return (i == 1 ? catgets(catd, 1, 178, "")
631 : catgets(catd, 1, 179, "s"));
632 }
633
634 static short vcntcol;
635
636 int
qcolumn(register char * lim,register char * gp)637 qcolumn(register char *lim, register char *gp)
638 {
639 register int x = 0, n = 1;
640 int c, i;
641 int (*OO)();
642
643 OO = Outchar;
644 Outchar = qcount;
645 vcntcol = 0;
646 if (lim != NULL) {
647 if (lim < linebuf) {
648 lim = linebuf;
649 n = 0;
650 } else
651 n = skipright(linebuf, lim);
652 x = lim[n], lim[n] = 0;
653 }
654 pline(0);
655 if (lim != NULL)
656 lim[n] = x;
657 if (gp)
658 while (*gp) {
659 nextc(c, gp, i);
660 putchar(c);
661 gp += i;
662 }
663 Outchar = OO;
664 return (vcntcol);
665 }
666
667 int
qcount(int c)668 qcount(int c)
669 {
670 if (c == '\t') {
671 vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
672 lastsc = 1;
673 return c;
674 }
675 /*
676 * Take account of filler characters inserted at the end of
677 * the visual line if a multi-column character does not fit.
678 */
679 lastsc = colsc(c&TRIM&~MULTICOL);
680 while (vcntcol < WCOLS && vcntcol + lastsc - 1 >= WCOLS)
681 vcntcol++;
682 vcntcol += c & MULTICOL ? 1 : lastsc;
683 return c;
684 }
685
686 void
reverse(register line * a1,register line * a2)687 reverse(register line *a1, register line *a2)
688 {
689 register line t;
690
691 for (;;) {
692 t = *--a2;
693 if (a2 <= a1)
694 return;
695 *a2 = *a1;
696 *a1++ = t;
697 }
698 }
699
700 void
save(line * a1,register line * a2)701 save(line *a1, register line *a2)
702 {
703 register int more;
704
705 if (!FIXUNDO)
706 return;
707 #ifdef TRACE
708 if (trace)
709 vudump("before save");
710 #endif
711 undkind = UNDNONE;
712 undadot = dot;
713 more = (a2 - a1 + 1) - (unddol - dol);
714 while (more > (endcore - truedol))
715 if (morelines() < 0)
716 error(catgets(catd, 1, 180,
717 "Out of memory@saving lines for undo - try using ed"));
718 if (more)
719 (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
720 (truedol - unddol));
721 unddol += more;
722 truedol += more;
723 copyw(dol + 1, a1, a2 - a1 + 1);
724 undkind = UNDALL;
725 unddel = a1 - 1;
726 undap1 = a1;
727 undap2 = a2 + 1;
728 #ifdef TRACE
729 if (trace)
730 vudump("after save");
731 #endif
732 }
733
734 void
save12(void)735 save12(void)
736 {
737
738 save(addr1, addr2);
739 }
740
741 void
saveall(void)742 saveall(void)
743 {
744
745 save(one, dol);
746 }
747
748 int
span(void)749 span(void)
750 {
751
752 return (addr2 - addr1 + 1);
753 }
754
755 void
synced(void)756 synced(void)
757 {
758
759 chng = 0;
760 tchng = 0;
761 xchng = 0;
762 }
763
764
765 int
skipwh(void)766 skipwh(void)
767 {
768 register int wh;
769
770 wh = 0;
771 while (is_white(peekchar())) {
772 wh++;
773 ignchar();
774 }
775 return (wh);
776 }
777
778 void
vsmerror(char * seekpt,va_list ap)779 vsmerror(char *seekpt, va_list ap)
780 {
781
782 if (seekpt == 0)
783 return;
784 merror1((intptr_t)seekpt);
785 if (inopen && CE)
786 vclreol();
787 if (SO && SE)
788 putpad(SO);
789 vlprintf(mesg(linebuf), ap);
790 if (SO && SE)
791 putpad(SE);
792 }
793
794 void
smerror(char * seekpt,...)795 smerror(char *seekpt, ...)
796 {
797 va_list ap;
798
799 if (seekpt == NULL)
800 return;
801 va_start(ap, seekpt);
802 vsmerror(seekpt, ap);
803 va_end(ap);
804 }
805
806 char *
strend(register char * cp)807 strend(register char *cp)
808 {
809
810 while (*cp)
811 cp++;
812 return (cp);
813 }
814
815 void
strcLIN(char * dp)816 strcLIN(char *dp)
817 {
818
819 CP(linebuf, dp);
820 }
821
822 void
syserror(void)823 syserror(void)
824 {
825
826 dirtcnt = 0;
827 putchar(' ');
828 error("%s", strerror(errno));
829 }
830
831 /*
832 * Return the column number that results from being in column col and
833 * hitting a tab, where tabs are set every ts columns. Work right for
834 * the case where col > TCOLUMNS, even if ts does not divide TCOLUMNS.
835 */
836 int
tabcol(int col,int ts)837 tabcol(int col, int ts)
838 {
839 int offset, result;
840
841 if (col >= TCOLUMNS) {
842 offset = TCOLUMNS * (col/TCOLUMNS);
843 col -= offset;
844 } else
845 offset = 0;
846 result = col + ts - (col % ts) + offset;
847 return (result);
848 }
849
850 char *
vfindcol(int i)851 vfindcol(int i)
852 {
853 register char *cp;
854 register int (*OO)() = Outchar;
855 int c, n = 0;
856
857 Outchar = qcount;
858 ignore(qcolumn(linebuf - 1, NOSTR));
859 for (cp = linebuf; *cp && vcntcol < i; cp += n) {
860 nextc(c, cp, n);
861 putchar(c);
862 }
863 if (cp != linebuf)
864 cp -= n;
865 Outchar = OO;
866 return (cp);
867 }
868
869 char *
vskipwh(register char * cp)870 vskipwh(register char *cp)
871 {
872
873 while (is_white(*cp) && cp[1])
874 cp++;
875 return (cp);
876 }
877
878
879 char *
vpastwh(register char * cp)880 vpastwh(register char *cp)
881 {
882
883 while (is_white(*cp))
884 cp++;
885 return (cp);
886 }
887
888 int
whitecnt(register char * cp)889 whitecnt(register char *cp)
890 {
891 register int i;
892
893 i = 0;
894 for (;;)
895 switch (*cp++) {
896
897 case '\t':
898 i += value(TABSTOP) - i % value(TABSTOP);
899 break;
900
901 case ' ':
902 i++;
903 break;
904
905 default:
906 return (i);
907 }
908 }
909
910 void
markit(line * addr)911 markit(line *addr)
912 {
913
914 if (addr != dot && addr >= one && addr <= dol)
915 markDOT();
916 }
917
918 #ifdef SIGEMT
919 /*
920 * The following code is defensive programming against a bug in the
921 * pdp-11 overlay implementation. Sometimes it goes nuts and asks
922 * for an overlay with some garbage number, which generates an emt
923 * trap. This is a less than elegant solution, but it is somewhat
924 * better than core dumping and losing your work, leaving your tty
925 * in a weird state, etc.
926 */
927 int _ovno;
928 void
onemt(int signum)929 onemt(int signum)
930 {
931 int oovno;
932
933 oovno = _ovno;
934 /* 2 and 3 are valid on 11/40 type vi, so */
935 if (_ovno < 0 || _ovno > 3)
936 _ovno = 0;
937 error(catgets(catd, 1, 181, "emt trap, _ovno is %d @ - try again"));
938 }
939 #endif
940
941 /*
942 * When a hangup occurs our actions are similar to a preserve
943 * command. If the buffer has not been [Modified], then we do
944 * nothing but remove the temporary files and exit.
945 * Otherwise, we sync the temp file and then attempt a preserve.
946 * If the preserve succeeds, we unlink our temp files.
947 * If the preserve fails, we leave the temp files as they are
948 * as they are a backup even without preservation if they
949 * are not removed.
950 */
951 void
onhup(int signum)952 onhup(int signum)
953 {
954
955 /*
956 * USG tty driver can send multiple HUP's!!
957 */
958 signal(SIGINT, SIG_IGN);
959 signal(SIGHUP, SIG_IGN);
960 if (chng == 0) {
961 cleanup(1);
962 exitex(0);
963 }
964 if (setexit() == 0) {
965 if (preserve()) {
966 cleanup(1);
967 exitex(0);
968 }
969 }
970 exitex(1);
971 }
972
973 /*
974 * An interrupt occurred. Drain any output which
975 * is still in the output buffering pipeline.
976 * Catch interrupts again. Unless we are in visual
977 * reset the output state (out of -nl mode, e.g).
978 * Then like a normal error (with the \n before Interrupt
979 * suppressed in visual mode).
980 */
981 void
onintr(int signum)982 onintr(int signum)
983 {
984
985 alarm(0); /* in case we were called from map */
986 draino();
987 if (!inopen) {
988 pstop();
989 setlastchar('\n');
990 }
991 error(catgets(catd, 1, 182, "\nInterrupt") + inopen);
992 }
993
994 /*
995 * If we are interruptible, enable interrupts again.
996 * In some critical sections we turn interrupts off,
997 * but not very often.
998 */
999 void
setrupt(void)1000 setrupt(void)
1001 {
1002
1003 if (ruptible) {
1004 signal(SIGINT, inopen ? vintr : onintr);
1005 #ifdef SIGTSTP
1006 if (dosusp)
1007 signal(SIGTSTP, onsusp);
1008 #endif
1009 }
1010 }
1011
1012 int
preserve(void)1013 preserve(void)
1014 {
1015
1016 #ifdef INCORB
1017 tflush();
1018 #endif
1019 synctmp();
1020 pid = fork();
1021 if (pid < 0)
1022 return (0);
1023 if (pid == 0) {
1024 close(0);
1025 dup(tfile);
1026 execl(EXPRESERVE, "expreserve", (char *)0);
1027 exitex(1);
1028 }
1029 waitfor();
1030 if (rpid == pid && status == 0)
1031 return (1);
1032 return (0);
1033 }
1034
1035 int
exitex(int i)1036 exitex(int i)
1037 {
1038
1039 # ifdef TRACE
1040 if (trace)
1041 fclose(trace);
1042 # endif
1043 if (failed != 0 && i == 0)
1044 i = failed;
1045 _exit(i);
1046 /*NOTREACHED*/
1047 return 0;
1048 }
1049
1050 #ifdef SIGTSTP
1051 /*
1052 * We have just gotten a susp. Suspend and prepare to resume.
1053 */
1054 void
onsusp(int signum)1055 onsusp(int signum)
1056 {
1057 struct termios f;
1058 /* int omask; */
1059 #ifdef TIOCGWINSZ
1060 struct winsize win;
1061 #endif
1062 sigset_t set;
1063
1064 f = setty(normf);
1065 vnfl();
1066 putpad(TE);
1067 flush();
1068
1069 sigemptyset(&set);
1070 sigprocmask(SIG_SETMASK, &set, NULL);
1071 signal(SIGTSTP, SIG_DFL);
1072 kill(0, SIGTSTP);
1073
1074 /* the pc stops here */
1075
1076 signal(SIGTSTP, onsusp);
1077 vcontin(0);
1078 setty(f);
1079 if (!inopen)
1080 error(0);
1081 #ifdef TIOCGWINSZ
1082 else {
1083 if (ioctl(0, TIOCGWINSZ, &win) >= 0)
1084 if (win.ws_row != winsz.ws_row ||
1085 win.ws_col != winsz.ws_col)
1086 onwinch(SIGWINCH);
1087 if (vcnt < 0) {
1088 vcnt = -vcnt;
1089 if (state == VISUAL)
1090 vclear();
1091 else if (state == CRTOPEN)
1092 vcnt = 0;
1093 }
1094 vdirty(0, TLINES);
1095 vrepaint(cursor);
1096 }
1097 #endif /* TIOCGWINSZ */
1098 }
1099 #endif /* SIGTSTP */
1100
1101 /*
1102 * For regular strcpy(), source and destination may not overlap.
1103 */
1104 char *
movestr(char * s1,const char * s2)1105 movestr(char *s1, const char *s2)
1106 {
1107 char *cp = s1;
1108
1109 while (*s1++ = *s2++);
1110 return cp;
1111 }
1112
1113 /*
1114 * strcpy() checking the maximum size of s1, printing msg in case of overflow.
1115 */
1116 char *
safecp(char * s1,const char * s2,size_t max,char * msg,...)1117 safecp(char *s1, const char *s2, size_t max, char *msg, ...)
1118 {
1119 va_list ap;
1120 char *cp = s1;
1121
1122 while (max--)
1123 if ((*s1++ = *s2++) == '\0')
1124 return cp;
1125 va_start(ap, msg);
1126 verror(msg, ap);
1127 va_end(ap);
1128 exitex(0175);
1129 /*NOTREACHED*/
1130 return NULL;
1131 }
1132
1133 /*
1134 * strcat() checking the maximum size of s1, printing msg in case of overflow.
1135 */
1136 char *
safecat(char * s1,const char * s2,size_t max,char * msg,...)1137 safecat(char *s1, const char *s2, size_t max, char *msg, ...)
1138 {
1139 va_list ap;
1140 char *cp = s1;
1141
1142 while (max && *s1)
1143 max--, s1++;
1144 while (max--)
1145 if ((*s1++ = *s2++) == '\0')
1146 return cp;
1147 va_start(ap, msg);
1148 verror(msg, ap);
1149 va_end(ap);
1150 exitex(0175);
1151 /*NOTREACHED*/
1152 return NULL;
1153 }
1154