148255Sbostic /*-
2*63046Sbostic * Copyright (c) 1980, 1993
3*63046Sbostic * The Regents of the University of California. All rights reserved.
448255Sbostic *
548255Sbostic * %sccs.include.proprietary.c%
621665Sdist */
721665Sdist
821665Sdist #ifndef lint
9*63046Sbostic static char sccsid[] = "@(#)ex_subr.c 8.1 (Berkeley) 06/09/93";
1048255Sbostic #endif /* not lint */
1121665Sdist
12441Smark #include "ex.h"
13441Smark #include "ex_re.h"
14441Smark #include "ex_tty.h"
15441Smark #include "ex_vis.h"
1637881Sbostic #include "pathnames.h"
17441Smark
18441Smark /*
19441Smark * Random routines, in alphabetical order.
20441Smark */
21441Smark
any(c,s)22441Smark any(c, s)
23441Smark int c;
24441Smark register char *s;
25441Smark {
26441Smark register int x;
27441Smark
28441Smark while (x = *s++)
29441Smark if (x == c)
30441Smark return (1);
31441Smark return (0);
32441Smark }
33441Smark
backtab(i)34441Smark backtab(i)
35441Smark register int i;
36441Smark {
37441Smark register int j;
38441Smark
39441Smark j = i % value(SHIFTWIDTH);
40441Smark if (j == 0)
41441Smark j = value(SHIFTWIDTH);
42441Smark i -= j;
43441Smark if (i < 0)
44441Smark i = 0;
45441Smark return (i);
46441Smark }
47441Smark
change()48441Smark change()
49441Smark {
50441Smark
51441Smark tchng++;
52441Smark chng = tchng;
53441Smark }
54441Smark
55441Smark /*
56441Smark * Column returns the number of
57441Smark * columns occupied by printing the
58441Smark * characters through position cp of the
59441Smark * current line.
60441Smark */
column(cp)61441Smark column(cp)
62441Smark register char *cp;
63441Smark {
64441Smark
65441Smark if (cp == 0)
66441Smark cp = &linebuf[LBSIZE - 2];
67441Smark return (qcolumn(cp, (char *) 0));
68441Smark }
69441Smark
70519Smark /*
71519Smark * Ignore a comment to the end of the line.
72519Smark * This routine eats the trailing newline so don't call newline().
73519Smark */
comment()74519Smark comment()
75519Smark {
76519Smark register int c;
77519Smark
78519Smark do {
7930596Sconrad c = ex_getchar();
80519Smark } while (c != '\n' && c != EOF);
81519Smark if (c == EOF)
82519Smark ungetchar(c);
83519Smark }
84519Smark
Copy(to,from,size)85441Smark Copy(to, from, size)
86441Smark register char *from, *to;
87441Smark register int size;
88441Smark {
89441Smark
90441Smark if (size > 0)
91441Smark do
92441Smark *to++ = *from++;
93441Smark while (--size > 0);
94441Smark }
95441Smark
copyw(to,from,size)96441Smark copyw(to, from, size)
97441Smark register line *from, *to;
98441Smark register int size;
99441Smark {
100441Smark if (size > 0)
101441Smark do
102441Smark *to++ = *from++;
103441Smark while (--size > 0);
104441Smark }
105441Smark
copywR(to,from,size)106441Smark copywR(to, from, size)
107441Smark register line *from, *to;
108441Smark register int size;
109441Smark {
110441Smark
111441Smark while (--size >= 0)
112441Smark to[size] = from[size];
113441Smark }
114441Smark
ctlof(c)115441Smark ctlof(c)
116441Smark int c;
117441Smark {
118441Smark
119441Smark return (c == TRIM ? '?' : c | ('A' - 1));
120441Smark }
121441Smark
dingdong()122441Smark dingdong()
123441Smark {
124441Smark
125441Smark if (VB)
126441Smark putpad(VB);
127441Smark else if (value(ERRORBELLS))
128441Smark putch('\207');
129441Smark }
130441Smark
fixindent(indent)131441Smark fixindent(indent)
132441Smark int indent;
133441Smark {
134441Smark register int i;
135441Smark register char *cp;
136441Smark
137441Smark i = whitecnt(genbuf);
138441Smark cp = vpastwh(genbuf);
139441Smark if (*cp == 0 && i == indent && linebuf[0] == 0) {
140441Smark genbuf[0] = 0;
141441Smark return (i);
142441Smark }
143441Smark CP(genindent(i), cp);
144441Smark return (i);
145441Smark }
146441Smark
filioerr(cp)147441Smark filioerr(cp)
148441Smark char *cp;
149441Smark {
150441Smark register int oerrno = errno;
151441Smark
152441Smark lprintf("\"%s\"", cp);
153441Smark errno = oerrno;
154441Smark syserror();
155441Smark }
156441Smark
157441Smark char *
genindent(indent)158441Smark genindent(indent)
159441Smark register int indent;
160441Smark {
161441Smark register char *cp;
162441Smark
163441Smark for (cp = genbuf; indent >= value(TABSTOP); indent -= value(TABSTOP))
164441Smark *cp++ = '\t';
165441Smark for (; indent > 0; indent--)
166441Smark *cp++ = ' ';
167441Smark return (cp);
168441Smark }
169441Smark
getDOT()170441Smark getDOT()
171441Smark {
172441Smark
173441Smark getline(*dot);
174441Smark }
175441Smark
176441Smark line *
getmark(c)177441Smark getmark(c)
178441Smark register int c;
179441Smark {
180441Smark register line *addr;
181441Smark
182441Smark for (addr = one; addr <= dol; addr++)
183441Smark if (names[c - 'a'] == (*addr &~ 01)) {
184441Smark return (addr);
185441Smark }
186441Smark return (0);
187441Smark }
188441Smark
getn(cp)189441Smark getn(cp)
190441Smark register char *cp;
191441Smark {
192441Smark register int i = 0;
193441Smark
194441Smark while (isdigit(*cp))
195441Smark i = i * 10 + *cp++ - '0';
196441Smark if (*cp)
197441Smark return (0);
198441Smark return (i);
199441Smark }
200441Smark
ignnEOF()201441Smark ignnEOF()
202441Smark {
20330596Sconrad register int c = ex_getchar();
204441Smark
205441Smark if (c == EOF)
206441Smark ungetchar(c);
207519Smark else if (c=='"')
208519Smark comment();
209441Smark }
210441Smark
iswhite(c)211441Smark iswhite(c)
212441Smark int c;
213441Smark {
214441Smark
215441Smark return (c == ' ' || c == '\t');
216441Smark }
217441Smark
junk(c)218441Smark junk(c)
219441Smark register int c;
220441Smark {
221441Smark
222441Smark if (c && !value(BEAUTIFY))
223441Smark return (0);
224441Smark if (c >= ' ' && c != TRIM)
225441Smark return (0);
226441Smark switch (c) {
227441Smark
228441Smark case '\t':
229441Smark case '\n':
230441Smark case '\f':
231441Smark return (0);
232441Smark
233441Smark default:
234441Smark return (1);
235441Smark }
236441Smark }
237441Smark
killed()238441Smark killed()
239441Smark {
240441Smark
241441Smark killcnt(addr2 - addr1 + 1);
242441Smark }
243441Smark
killcnt(cnt)244441Smark killcnt(cnt)
245441Smark register int cnt;
246441Smark {
247441Smark
248441Smark if (inopen) {
249441Smark notecnt = cnt;
250441Smark notenam = notesgn = "";
251441Smark return;
252441Smark }
253441Smark if (!notable(cnt))
254441Smark return;
25530596Sconrad ex_printf("%d lines", cnt);
256441Smark if (value(TERSE) == 0) {
25730596Sconrad ex_printf(" %c%s", Command[0] | ' ', Command + 1);
258441Smark if (Command[strlen(Command) - 1] != 'e')
25930596Sconrad ex_putchar('e');
26030596Sconrad ex_putchar('d');
261441Smark }
262441Smark putNFL();
263441Smark }
264441Smark
lineno(a)265441Smark lineno(a)
266441Smark line *a;
267441Smark {
268441Smark
269441Smark return (a - zero);
270441Smark }
271441Smark
lineDOL()272441Smark lineDOL()
273441Smark {
274441Smark
275441Smark return (lineno(dol));
276441Smark }
277441Smark
lineDOT()278441Smark lineDOT()
279441Smark {
280441Smark
281441Smark return (lineno(dot));
282441Smark }
283441Smark
markDOT()284441Smark markDOT()
285441Smark {
286441Smark
287441Smark markpr(dot);
288441Smark }
289441Smark
markpr(which)290441Smark markpr(which)
291441Smark line *which;
292441Smark {
293441Smark
294441Smark if ((inglobal == 0 || inopen) && which <= endcore) {
295441Smark names['z'-'a'+1] = *which & ~01;
296441Smark if (inopen)
297441Smark ncols['z'-'a'+1] = cursor;
298441Smark }
299441Smark }
300441Smark
markreg(c)301441Smark markreg(c)
302441Smark register int c;
303441Smark {
304441Smark
305441Smark if (c == '\'' || c == '`')
306441Smark return ('z' + 1);
307441Smark if (c >= 'a' && c <= 'z')
308441Smark return (c);
309441Smark return (0);
310441Smark }
311441Smark
312441Smark /*
313441Smark * Mesg decodes the terse/verbose strings. Thus
314441Smark * 'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
315441Smark * 'xxx|yyy' -> 'xxx' if terse, else 'yyy'
316441Smark * All others map to themselves.
317441Smark */
318441Smark char *
mesg(str)319441Smark mesg(str)
320441Smark register char *str;
321441Smark {
322441Smark register char *cp;
323441Smark
324441Smark str = strcpy(genbuf, str);
325441Smark for (cp = str; *cp; cp++)
326441Smark switch (*cp) {
327441Smark
328441Smark case '@':
329441Smark if (value(TERSE))
330441Smark *cp = 0;
331441Smark else
332441Smark *cp = ' ';
333441Smark break;
334441Smark
335441Smark case '|':
336441Smark if (value(TERSE) == 0)
337441Smark return (cp + 1);
338441Smark *cp = 0;
339441Smark break;
340441Smark }
341441Smark return (str);
342441Smark }
343441Smark
344441Smark /*VARARGS2*/
merror(seekpt,i)345441Smark merror(seekpt, i)
34630596Sconrad #ifndef EXSTRINGS
347441Smark char *seekpt;
348441Smark #else
349474Smark # ifdef lint
350474Smark char *seekpt;
351474Smark # else
352441Smark int seekpt;
353474Smark # endif
354441Smark #endif
355441Smark int i;
356441Smark {
357441Smark register char *cp = linebuf;
358441Smark
359441Smark if (seekpt == 0)
360441Smark return;
361441Smark merror1(seekpt);
362441Smark if (*cp == '\n')
363441Smark putnl(), cp++;
36421690Sdist if (inopen > 0 && CE)
365441Smark vclreol();
366441Smark if (SO && SE)
367441Smark putpad(SO);
36830596Sconrad ex_printf(mesg(cp), i);
369441Smark if (SO && SE)
370441Smark putpad(SE);
371441Smark }
372441Smark
merror1(seekpt)373441Smark merror1(seekpt)
37430596Sconrad #ifndef EXSTRINGS
375441Smark char *seekpt;
376441Smark #else
377474Smark # ifdef lint
378474Smark char *seekpt;
379474Smark # else
380441Smark int seekpt;
381474Smark # endif
382441Smark #endif
383441Smark {
384441Smark
38530596Sconrad #ifndef EXSTRINGS
386474Smark strcpy(linebuf, seekpt);
387474Smark #else
388441Smark lseek(erfile, (long) seekpt, 0);
389441Smark if (read(erfile, linebuf, 128) < 2)
390441Smark CP(linebuf, "ERROR");
391474Smark #endif
392441Smark }
393441Smark
morelines()394441Smark morelines()
395441Smark {
39630596Sconrad #ifdef UNIX_SBRK
39730596Sconrad char *sbrk();
398441Smark
399441Smark if ((int) sbrk(1024 * sizeof (line)) == -1)
400441Smark return (-1);
401441Smark endcore += 1024;
402441Smark return (0);
40330596Sconrad #else
40430596Sconrad /*
40530596Sconrad * We can never be guaranteed that we can get more memory
40630596Sconrad * beyond "endcore". So we just punt every time.
40730596Sconrad */
40830596Sconrad return -1;
40930596Sconrad #endif
410441Smark }
411441Smark
nonzero()412441Smark nonzero()
413441Smark {
414441Smark
415441Smark if (addr1 == zero) {
416441Smark notempty();
417441Smark error("Nonzero address required@on this command");
418441Smark }
419441Smark }
420441Smark
notable(i)421441Smark notable(i)
422441Smark int i;
423441Smark {
424441Smark
425441Smark return (hush == 0 && !inglobal && i > value(REPORT));
426441Smark }
427441Smark
428441Smark
notempty()429441Smark notempty()
430441Smark {
431441Smark
432441Smark if (dol == zero)
433441Smark error("No lines@in the buffer");
434441Smark }
435441Smark
436441Smark
netchHAD(cnt)437441Smark netchHAD(cnt)
438441Smark int cnt;
439441Smark {
440441Smark
441441Smark netchange(lineDOL() - cnt);
442441Smark }
443441Smark
netchange(i)444441Smark netchange(i)
445441Smark register int i;
446441Smark {
447441Smark register char *cp;
448441Smark
449441Smark if (i > 0)
450441Smark notesgn = cp = "more ";
451441Smark else
452441Smark notesgn = cp = "fewer ", i = -i;
453441Smark if (inopen) {
454441Smark notecnt = i;
455441Smark notenam = "";
456441Smark return;
457441Smark }
458441Smark if (!notable(i))
459441Smark return;
46030596Sconrad ex_printf(mesg("%d %slines@in file after %s"), i, cp, Command);
461441Smark putNFL();
462441Smark }
463441Smark
putmark(addr)464441Smark putmark(addr)
465441Smark line *addr;
466441Smark {
467441Smark
468441Smark putmk1(addr, putline());
469441Smark }
470441Smark
putmk1(addr,n)471441Smark putmk1(addr, n)
472441Smark register line *addr;
473441Smark int n;
474441Smark {
475441Smark register line *markp;
476519Smark register oldglobmk;
477441Smark
478519Smark oldglobmk = *addr & 1;
479441Smark *addr &= ~1;
480441Smark for (markp = (anymarks ? names : &names['z'-'a'+1]);
481441Smark markp <= &names['z'-'a'+1]; markp++)
482441Smark if (*markp == *addr)
483441Smark *markp = n;
484519Smark *addr = n | oldglobmk;
485441Smark }
486441Smark
487441Smark char *
plural(i)488441Smark plural(i)
489441Smark long i;
490441Smark {
491441Smark
492441Smark return (i == 1 ? "" : "s");
493441Smark }
494441Smark
495441Smark int qcount();
496441Smark short vcntcol;
497441Smark
qcolumn(lim,gp)498441Smark qcolumn(lim, gp)
499441Smark register char *lim, *gp;
500441Smark {
501441Smark register int x;
502441Smark int (*OO)();
503441Smark
504441Smark OO = Outchar;
505441Smark Outchar = qcount;
506441Smark vcntcol = 0;
507441Smark if (lim != NULL)
508441Smark x = lim[1], lim[1] = 0;
509441Smark pline(0);
510441Smark if (lim != NULL)
511441Smark lim[1] = x;
512441Smark if (gp)
513441Smark while (*gp)
51430596Sconrad ex_putchar(*gp++);
515441Smark Outchar = OO;
516441Smark return (vcntcol);
517441Smark }
518441Smark
519441Smark int
qcount(c)520441Smark qcount(c)
521441Smark int c;
522441Smark {
523441Smark
524441Smark if (c == '\t') {
525441Smark vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
526441Smark return;
527441Smark }
528441Smark vcntcol++;
529441Smark }
530441Smark
reverse(a1,a2)531441Smark reverse(a1, a2)
532441Smark register line *a1, *a2;
533441Smark {
534441Smark register line t;
535441Smark
536441Smark for (;;) {
537441Smark t = *--a2;
538441Smark if (a2 <= a1)
539441Smark return;
540441Smark *a2 = *a1;
541441Smark *a1++ = t;
542441Smark }
543441Smark }
544441Smark
save(a1,a2)545441Smark save(a1, a2)
546441Smark line *a1;
547441Smark register line *a2;
548441Smark {
549441Smark register int more;
550441Smark
551493Smark if (!FIXUNDO)
552493Smark return;
553493Smark #ifdef TRACE
554493Smark if (trace)
555493Smark vudump("before save");
556493Smark #endif
557441Smark undkind = UNDNONE;
558441Smark undadot = dot;
559441Smark more = (a2 - a1 + 1) - (unddol - dol);
560441Smark while (more > (endcore - truedol))
561441Smark if (morelines() < 0)
56230596Sconrad #ifdef UNIX_SBRK
56321690Sdist error("Out of memory@saving lines for undo - try using ed");
56430596Sconrad #else
56530596Sconrad error("Out of memory@saving lines for undo - try increasing linelimit");
56630596Sconrad #endif
567441Smark if (more)
568441Smark (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
569441Smark (truedol - unddol));
570441Smark unddol += more;
571441Smark truedol += more;
572441Smark copyw(dol + 1, a1, a2 - a1 + 1);
573441Smark undkind = UNDALL;
574441Smark unddel = a1 - 1;
575441Smark undap1 = a1;
576441Smark undap2 = a2 + 1;
577493Smark #ifdef TRACE
578493Smark if (trace)
579493Smark vudump("after save");
580493Smark #endif
581441Smark }
582441Smark
save12()583441Smark save12()
584441Smark {
585441Smark
586441Smark save(addr1, addr2);
587441Smark }
588441Smark
saveall()589441Smark saveall()
590441Smark {
591441Smark
592441Smark save(one, dol);
593441Smark }
594441Smark
span()595441Smark span()
596441Smark {
597441Smark
598441Smark return (addr2 - addr1 + 1);
599441Smark }
600441Smark
ex_sync()60130596Sconrad ex_sync()
602441Smark {
603441Smark
604441Smark chng = 0;
605441Smark tchng = 0;
606441Smark xchng = 0;
607441Smark }
608441Smark
609441Smark
skipwh()610441Smark skipwh()
611441Smark {
612441Smark register int wh;
613441Smark
614441Smark wh = 0;
615441Smark while (iswhite(peekchar())) {
616441Smark wh++;
617441Smark ignchar();
618441Smark }
619441Smark return (wh);
620441Smark }
621441Smark
622441Smark /*VARARGS2*/
smerror(seekpt,cp)623441Smark smerror(seekpt, cp)
624441Smark #ifdef lint
625441Smark char *seekpt;
626441Smark #else
627441Smark int seekpt;
628441Smark #endif
629441Smark char *cp;
630441Smark {
631441Smark
632441Smark if (seekpt == 0)
633441Smark return;
634441Smark merror1(seekpt);
635441Smark if (inopen && CE)
636441Smark vclreol();
637441Smark if (SO && SE)
638441Smark putpad(SO);
639441Smark lprintf(mesg(linebuf), cp);
640441Smark if (SO && SE)
641441Smark putpad(SE);
642441Smark }
643441Smark
644441Smark char *
strend(cp)645441Smark strend(cp)
646441Smark register char *cp;
647441Smark {
648441Smark
649441Smark while (*cp)
650441Smark cp++;
651441Smark return (cp);
652441Smark }
653441Smark
strcLIN(dp)654441Smark strcLIN(dp)
655441Smark char *dp;
656441Smark {
657441Smark
658441Smark CP(linebuf, dp);
659441Smark }
660441Smark
syserror()661441Smark syserror()
662441Smark {
66342421Sbostic char *strerror();
664441Smark
665441Smark dirtcnt = 0;
66630596Sconrad ex_putchar(' ');
66742421Sbostic error(strerror(errno));
668441Smark }
669441Smark
670519Smark /*
671519Smark * Return the column number that results from being in column col and
672519Smark * hitting a tab, where tabs are set every ts columns. Work right for
673519Smark * the case where col > COLUMNS, even if ts does not divide COLUMNS.
674519Smark */
tabcol(col,ts)675519Smark tabcol(col, ts)
676519Smark int col, ts;
677519Smark {
678519Smark int offset, result;
679519Smark
680519Smark if (col >= COLUMNS) {
681519Smark offset = COLUMNS * (col/COLUMNS);
682519Smark col -= offset;
683519Smark } else
684519Smark offset = 0;
685519Smark result = col + ts - (col % ts) + offset;
686519Smark return (result);
687519Smark }
688519Smark
689441Smark char *
vfindcol(i)690441Smark vfindcol(i)
691441Smark int i;
692441Smark {
693441Smark register char *cp;
694441Smark register int (*OO)() = Outchar;
695441Smark
696441Smark Outchar = qcount;
697441Smark ignore(qcolumn(linebuf - 1, NOSTR));
698441Smark for (cp = linebuf; *cp && vcntcol < i; cp++)
69930596Sconrad ex_putchar(*cp);
700441Smark if (cp != linebuf)
701441Smark cp--;
702441Smark Outchar = OO;
703441Smark return (cp);
704441Smark }
705441Smark
706441Smark char *
vskipwh(cp)707441Smark vskipwh(cp)
708441Smark register char *cp;
709441Smark {
710441Smark
711441Smark while (iswhite(*cp) && cp[1])
712441Smark cp++;
713441Smark return (cp);
714441Smark }
715441Smark
716441Smark
717441Smark char *
vpastwh(cp)718441Smark vpastwh(cp)
719441Smark register char *cp;
720441Smark {
721441Smark
722441Smark while (iswhite(*cp))
723441Smark cp++;
724441Smark return (cp);
725441Smark }
726441Smark
whitecnt(cp)727441Smark whitecnt(cp)
728441Smark register char *cp;
729441Smark {
730441Smark register int i;
731441Smark
732441Smark i = 0;
733441Smark for (;;)
734441Smark switch (*cp++) {
735441Smark
736441Smark case '\t':
737441Smark i += value(TABSTOP) - i % value(TABSTOP);
738441Smark break;
739441Smark
740441Smark case ' ':
741441Smark i++;
742441Smark break;
743441Smark
744441Smark default:
745441Smark return (i);
746441Smark }
747441Smark }
748441Smark
749441Smark #ifdef lint
Ignore(a)750441Smark Ignore(a)
751441Smark char *a;
752441Smark {
753441Smark
754441Smark a = a;
755441Smark }
756441Smark
757441Smark Ignorf(a)
758441Smark int (*a)();
759441Smark {
760441Smark
761441Smark a = a;
762441Smark }
763441Smark #endif
764441Smark
markit(addr)765441Smark markit(addr)
766441Smark line *addr;
767441Smark {
768441Smark
769441Smark if (addr != dot && addr >= one && addr <= dol)
770441Smark markDOT();
771441Smark }
77221690Sdist
77321690Sdist /*
77421690Sdist * The following code is defensive programming against a bug in the
77521690Sdist * pdp-11 overlay implementation. Sometimes it goes nuts and asks
77621690Sdist * for an overlay with some garbage number, which generates an emt
77721690Sdist * trap. This is a less than elegant solution, but it is somewhat
77821690Sdist * better than core dumping and losing your work, leaving your tty
77921690Sdist * in a weird state, etc.
78021690Sdist */
78121690Sdist int _ovno;
78246826Sbostic void
onemt()78321690Sdist onemt()
78421690Sdist {
78521690Sdist signal(SIGEMT, onemt);
78621690Sdist /* 2 and 3 are valid on 11/40 type vi, so */
78721690Sdist if (_ovno < 0 || _ovno > 3)
78821690Sdist _ovno = 0;
78921690Sdist error("emt trap, _ovno is %d @ - try again");
79021690Sdist }
79121690Sdist
79221690Sdist /*
79321690Sdist * When a hangup occurs our actions are similar to a preserve
79421690Sdist * command. If the buffer has not been [Modified], then we do
79521690Sdist * nothing but remove the temporary files and exit.
79621690Sdist * Otherwise, we sync the temp file and then attempt a preserve.
79721690Sdist * If the preserve succeeds, we unlink our temp files.
79821690Sdist * If the preserve fails, we leave the temp files as they are
79921690Sdist * as they are a backup even without preservation if they
80021690Sdist * are not removed.
80121690Sdist */
80246826Sbostic void
onhup()80321690Sdist onhup()
80421690Sdist {
80521690Sdist
80621690Sdist /*
80721690Sdist * USG tty driver can send multiple HUP's!!
80821690Sdist */
80921690Sdist signal(SIGINT, SIG_IGN);
81021690Sdist signal(SIGHUP, SIG_IGN);
81121690Sdist if (chng == 0) {
81221690Sdist cleanup(1);
81330596Sconrad ex_exit(0);
81421690Sdist }
81521690Sdist if (setexit() == 0) {
81621690Sdist if (preserve()) {
81721690Sdist cleanup(1);
81830596Sconrad ex_exit(0);
81921690Sdist }
82021690Sdist }
82130596Sconrad ex_exit(1);
82221690Sdist }
82321690Sdist
82421690Sdist /*
82521690Sdist * An interrupt occurred. Drain any output which
82621690Sdist * is still in the output buffering pipeline.
82721690Sdist * Catch interrupts again. Unless we are in visual
82821690Sdist * reset the output state (out of -nl mode, e.g).
82921690Sdist * Then like a normal error (with the \n before Interrupt
83021690Sdist * suppressed in visual mode).
83121690Sdist */
83246826Sbostic void
onintr()83321690Sdist onintr()
83421690Sdist {
83521690Sdist
83621690Sdist #ifndef CBREAK
83721690Sdist signal(SIGINT, onintr);
83821690Sdist #else
83921690Sdist signal(SIGINT, inopen ? vintr : onintr);
84021690Sdist #endif
84121690Sdist alarm(0); /* in case we were called from map */
84221690Sdist draino();
84321690Sdist if (!inopen) {
84421690Sdist pstop();
84521690Sdist setlastchar('\n');
84621690Sdist #ifdef CBREAK
84721690Sdist }
84821690Sdist #else
84921690Sdist } else
85021690Sdist vraw();
85121690Sdist #endif
85221690Sdist error("\nInterrupt" + inopen);
85321690Sdist }
85421690Sdist
85521690Sdist /*
85621690Sdist * If we are interruptible, enable interrupts again.
85721690Sdist * In some critical sections we turn interrupts off,
85821690Sdist * but not very often.
85921690Sdist */
setrupt()86021690Sdist setrupt()
86121690Sdist {
86221690Sdist
86321690Sdist if (ruptible) {
86421690Sdist #ifndef CBREAK
86521690Sdist signal(SIGINT, onintr);
86621690Sdist #else
86721690Sdist signal(SIGINT, inopen ? vintr : onintr);
86821690Sdist #endif
86921690Sdist #ifdef SIGTSTP
87021690Sdist if (dosusp)
87121690Sdist signal(SIGTSTP, onsusp);
87221690Sdist #endif
87321690Sdist }
87421690Sdist }
87521690Sdist
preserve()87621690Sdist preserve()
87721690Sdist {
87821690Sdist
87921690Sdist #ifdef VMUNIX
88021690Sdist tflush();
88121690Sdist #endif
88221690Sdist synctmp();
88330596Sconrad pid = vfork();
88421690Sdist if (pid < 0)
88521690Sdist return (0);
88621690Sdist if (pid == 0) {
88721690Sdist close(0);
88821690Sdist dup(tfile);
88937881Sbostic execl(_PATH_EXPRESERVE, "expreserve", (char *) 0);
89030596Sconrad ex_exit(1);
89121690Sdist }
89221690Sdist waitfor();
89321690Sdist if (rpid == pid && status == 0)
89421690Sdist return (1);
89521690Sdist return (0);
89621690Sdist }
89721690Sdist
89821690Sdist #ifndef V6
ex_exit(i)89930596Sconrad ex_exit(i)
90021690Sdist int i;
90121690Sdist {
90221690Sdist
90321690Sdist # ifdef TRACE
90421690Sdist if (trace)
90521690Sdist fclose(trace);
90621690Sdist # endif
90721690Sdist _exit(i);
90821690Sdist }
90921690Sdist #endif
91021690Sdist
91121690Sdist #ifdef SIGTSTP
91221690Sdist /*
91321690Sdist * We have just gotten a susp. Suspend and prepare to resume.
91421690Sdist */
91546826Sbostic void
onsusp()91621690Sdist onsusp()
91721690Sdist {
91821690Sdist ttymode f;
91921690Sdist struct winsize win;
92021690Sdist
92121690Sdist f = setty(normf);
92221690Sdist vnfl();
92321690Sdist putpad(TE);
92421690Sdist flush();
92521690Sdist
92621690Sdist (void) sigsetmask(0);
92721690Sdist signal(SIGTSTP, SIG_DFL);
92821690Sdist kill(0, SIGTSTP);
92921690Sdist
93021690Sdist /* the pc stops here */
93121690Sdist
93221690Sdist signal(SIGTSTP, onsusp);
93321690Sdist vcontin(0);
93430596Sconrad ignore(setty(f));
93521690Sdist if (!inopen)
93630596Sconrad error((char *) 0);
93721690Sdist else {
93830596Sconrad #ifdef TIOCGWINSZ
93921690Sdist if (ioctl(0, TIOCGWINSZ, &win) >= 0)
94021690Sdist if (win.ws_row != winsz.ws_row ||
94121690Sdist win.ws_col != winsz.ws_col)
94221690Sdist winch();
94330596Sconrad #endif
94421690Sdist if (vcnt < 0) {
94521690Sdist vcnt = -vcnt;
94621690Sdist if (state == VISUAL)
94721690Sdist vclear();
94821690Sdist else if (state == CRTOPEN)
94921690Sdist vcnt = 0;
95021690Sdist }
95121690Sdist vdirty(0, LINES);
95221690Sdist vrepaint(cursor);
95321690Sdist }
95421690Sdist }
95521690Sdist #endif
956