BSD 4_3 development
[unix-history] / usr / contrib / jove / jove.c
CommitLineData
e8fa588c
C
1/*************************************************************************
2 * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3 * provided to you without charge for use only on a licensed Unix *
4 * system. You may copy JOVE provided that this notice is included with *
5 * the copy. You may not sell copies of this program or versions *
6 * modified for use on microcomputer systems, unless the copies are *
7 * included with a Unix system distribution and the source is provided. *
8 *************************************************************************/
9
10/* Contains the main loop initializations, and some system dependent
11 type things, e.g. putting terminal in CBREAK mode, etc. */
12
13#include "jove.h"
14#include "io.h"
15#include "termcap.h"
16
17#include <varargs.h>
18#include <sys/stat.h>
19#include <signal.h>
20#include <errno.h>
21#ifndef SYSV
22#include <sgtty.h>
23#include <fcntl.h>
24#else
25#include <termio.h>
26#endif SYSV
27
28#ifdef TIOCSLTC
29struct ltchars ls1,
30 ls2;
31#endif TIOCSLTC
32
33#ifdef TIOCGETC
34struct tchars tc1,
35 tc2;
36#endif
37
38#ifdef BRLUNIX
39struct sg_brl sg1, sg2;
40#else
41#ifdef SYSV
42struct termio sg1, sg2;
43#else SYSV
44struct sgttyb sg1, sg2;
45#endif SYSV
46#endif BRLUNIX
47
48#ifdef BIFF
49private struct stat tt_stat; /* for biff */
50#ifndef BSD4_2
51private char *tt_name = 0; /* name of the control tty */
52extern char *ttyname(); /* for systems w/o fchmod ... */
53#endif
54private int dw_biff = NO; /* whether or not to fotz at all */
55#endif
56
57time_t time0; /* when jove started up */
58int errormsg;
59extern char *tfname;
60char NullStr[] = "";
61
62finish(code)
63{
64 int CoreDump = (code != 0 && code != SIGHUP),
65 DelTmps = 1; /* Usually we delete them. */
66
67#ifdef LSRHS
68 if (CoreDump)
69 setdump(1);
70#endif
71 if (code == SIGINT) {
72 char c;
73
74#ifndef MENLO_JCL
75 (void) signal(code, finish);
76#endif
77 f_mess("Abort (Type 'n' if you're not sure)? ");
78 (void) read(0, &c, 1);
79 message(NullStr);
80 if ((c & 0377) != 'y') {
81 redisplay();
82 return;
83 }
84 }
85 ttyset(OFF);
86 UnsetTerm(NullStr);
87 if (code != 0) {
88 if (!Crashing) {
89 Crashing++;
90 lsave();
91 SyncRec();
92 printf("JOVE CRASH!! (code %d)\n", code);
93 if (ModBufs(1)) {
94 printf("Your buffers have been saved.\n");
95 printf("Use \"jove_recover\" or \"jove -r\"\n");
96 printf("to have a look at them.\n");
97 DelTmps = 0; /* Don't delete anymore. */
98 } else
99 printf("You didn't lose any work.\n");
100 } else
101 printf("\r\nYou may have lost your work!\n");
102 }
103 flusho();
104 if (DelTmps) {
105 tmpclose();
106 recclose();
107 }
108 if (CoreDump)
109 abort();
110#ifdef PROFILING
111 exit(exp_p);
112#else
113 _exit(exp_p);
114#endif
115}
116
117private char smbuf[20],
118 *bp = smbuf;
119private int nchars = 0;
120
121private char peekbuf[10],
122 *peekp = peekbuf;
123
124#ifdef SYSV
125void
126setblock(fd, on) /* turn blocking on or off */
127register int fd, on;
128{
129 static int blockf, nonblockf;
130 static int first = 1;
131 int flags;
132
133 if (first) {
134 first = 0;
135 if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
136 finish(SIGHUP);
137 blockf = flags & ~O_NDELAY; /* make sure O_NDELAY is off */
138 nonblockf = flags | O_NDELAY; /* make sure O_NDELAY is on */
139 }
140 if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
141 finish(SIGHUP);
142 return;
143}
144#endif SYSV
145
146Peekc()
147{
148 int c;
149
150 if (peekp == peekbuf)
151 c = -1;
152 else
153 c = *--peekp & 0377;
154 return c;
155}
156
157Ungetc(c)
158{
159 if (peekp == &peekbuf[(sizeof peekbuf) - 1])
160 return; /* Sorry, can't oblige you ... */
161 *peekp++ = c;
162}
163
164char *Inputp = 0;
165
166#ifdef IPROCS
167#ifdef PIPEPROCS
168getchar()
169{
170 extern int errno;
171 register int c;
172
173 if (nchars <= 0) {
174 do
175 nchars = read(0, smbuf, sizeof smbuf);
176#ifdef SYSV
177 while (nchars == 0 || (nchars < 0 && errno == EINTR));
178 if (nchars < 0)
179#else
180 while (nchars < 0 && errno == EINTR);
181 if (nchars <= 0)
182#endif SYSV
183 finish(SIGHUP);
184 bp = smbuf;
185 InputPending = nchars > 1;
186 }
187 if (((c = *bp) & 0200) && MetaKey != 0) {
188 *bp = (c & 0177);
189 return '\033';
190 }
191 nchars--;
192 return (*bp++ & 0177);
193}
194#else PIPEPROCS
195getchar()
196{
197 extern int global_fd,
198 NumProcs,
199 errno;
200 register int tmp,
201 nfds;
202 int reads,
203 c;
204
205 if (nchars <= 0) {
206 /* Get a character from the keyboard, first checking for
207 any input from a process. Handle that first, and then
208 deal with the terminal input. */
209 if (NumProcs > 0) {
210 do {
211 do {
212 reads = global_fd;
213 nfds = select(32, &reads, (int *) 0, (int *) 0, (struct timeval *) 0);
214 } while (nfds < 0 && errno == EINTR);
215
216 switch (nfds) {
217 case -1:
218 printf("\rerror %d in select %d", errno, global_fd);
219 global_fd = 1;
220 break;
221 default:
222 if (reads & 01) {
223 nchars = read(0, smbuf, sizeof(smbuf));
224 reads &= ~01;
225 --nfds;
226 }
227
228 while (nfds--) {
229 tmp = ffs(reads) - 1;
230 read_proc(tmp);
231 reads &= ~tmp;
232 }
233
234 break;
235 }
236 } while (nchars <= 0);
237 } else {
238 do
239 nchars = read(0, smbuf, sizeof(smbuf));
240 while (nchars < 0 && errno == EINTR);
241 }
242
243 if (nchars <= 0)
244 finish(SIGHUP);
245
246 bp = smbuf;
247 InputPending = (nchars > 1);
248 }
249
250 if (((c = *bp) & 0200) && MetaKey != 0) {
251 *bp = (c & 0177);
252 return '\033';
253 }
254 nchars--;
255 return *bp++ & 0377;
256}
257#endif PIPEPROCS
258#else IPROCS
259getchar()
260{
261 extern int errno;
262 register int c;
263
264 if (nchars <= 0) {
265 do
266 nchars = read(0, smbuf, sizeof smbuf);
267 while (nchars < 0 && errno == EINTR);
268
269 if (nchars <= 0)
270 finish(SIGHUP);
271 bp = smbuf;
272 InputPending = nchars > 1;
273 }
274 if (((c = *bp) & 0200) && MetaKey != 0) {
275 *bp = (c & 0177);
276 return '\033';
277 }
278 nchars--;
279 return *bp++ & 0377;
280}
281#endif IPROCS
282
283int InputPending = 0;
284
285/* Returns non-zero if a character waiting */
286
287charp()
288{
289 int some = 0;
290
291 if (InJoverc != 0 || nchars > 0 || Inputp != 0)
292 return 1;
293#ifdef BRLUNIX
294 {
295 static struct sg_brl gttyBuf;
296
297 gtty(0, (char *) &gttyBuf);
298 if (gttyBuf.sg_xflags & INWAIT)
299 some++;
300 }
301#endif
302#ifdef FIONREAD
303 {
304 long c;
305
306 if (ioctl(0, FIONREAD, (struct sgttyb *) &c) == -1)
307 c = 0;
308 some = (c > 0);
309 }
310#endif FIONREAD
311#ifdef SYSV
312 setblock(0, 0); /* turn blocking off */
313 nchars = read(0, smbuf, sizeof smbuf); /* Is anything there? */
314 setblock(0, 1); /* turn blocking on */
315 if (nchars > 0) /* something was there */
316 bp = smbuf; /* make sure bp points to it */
317 some = (nchars > 0); /* just say we found something */
318#endif SYSV
319#ifdef c70
320 some = !empty(0);
321#endif
322 return some;
323}
324
325ResetTerm()
326{
327 putpad(TI, 1);
328 putpad(VS, 1);
329 putpad(KS, 1);
330#ifdef BIFF
331 if (BiffChk != dw_biff)
332 biff_init();
333 /* just in case we changed our minds about whether to deal with
334 biff */
335#endif
336 chkmail(YES); /* force it to check to we can be accurate */
337 do_sgtty(); /* this is so if you change baudrate or stuff
338 like that, JOVE will notice. */
339 ttyset(ON);
340}
341
342UnsetTerm(mesg)
343char *mesg;
344{
345 ttyset(OFF);
346 putpad(KE, 1);
347 putpad(VE, 1);
348 putpad(TE, 1);
349#ifdef ID_CHAR
350 INSmode(0);
351#endif
352 Placur(ILI, 0);
353 printf("%s", mesg);
354 putpad(CE, 1);
355 flusho();
356}
357
358#ifdef JOB_CONTROL
359PauseJove()
360{
361 UnsetTerm(ModBufs(0) ? "[There are modified buffers]" : NullStr);
362 (void) kill(0, SIGTSTP);
363 ResetTerm();
364 ClAndRedraw();
365}
366#endif
367
368Push()
369{
370 int pid;
371
372 switch (pid = fork()) {
373 case -1:
374 complain("[Fork failed]");
375
376 case 0:
377 UnsetTerm(NullStr);
378 (void) signal(SIGTERM, SIG_DFL);
379 (void) signal(SIGINT, SIG_DFL);
380 execl(Shell, basename(Shell), 0);
381 message("[Execl failed]");
382 _exit(1);
383
384 default:
385 {
386 int (*old_int)() = signal(SIGINT, SIG_IGN);
387 int (*old_quit)() = signal(SIGQUIT, SIG_IGN);
388
389#ifdef IPROCS
390 sighold(SIGCHLD);
391#endif
392 dowait(pid, (int *) 0);
393#ifdef IPROCS
394 sigrelse(SIGCHLD);
395#endif
396 ResetTerm();
397 ClAndRedraw();
398 (void) signal(SIGINT, old_int);
399 (void) signal(SIGQUIT, old_quit);
400 }
401 }
402}
403
404int OKXonXoff = 0; /* ^S and ^Q initially DON'T work */
405
406ttsize()
407{
408#ifdef TIOCGWINSZ
409 struct winsize win;
410
411 if (ioctl (0, TIOCGWINSZ, &win) == 0) {
412 if (win.ws_col)
413 CO = win.ws_col;
414 if (win.ws_row)
415 LI = win.ws_row;
416 }
417#else TIOCGWINSZ
418#ifdef BTL_BLIT
419#include <sys/jioctl.h>
420 struct jwinsize jwin;
421
422 if (ioctl(0, JWINSIZE, &jwin) == 0) {
423 if (jwin.bytesx)
424 CO = jwin.bytesx;
425 if (jwin.bytesy)
426 LI = jwin.bytesy;
427 }
428#endif BTL_BLIT
429#endif TIOCGWINSZ
430 ILI = LI - 1;
431}
432
433#ifdef BIFF
434biff_init()
435{
436 dw_biff = ((BiffChk) &&
437#ifndef BSD4_2
438 ((tt_name != 0) || (tt_name = ttyname(0))) &&
439 (stat(tt_name, &tt_stat) != -1) &&
440#else
441 (fstat(0, &tt_stat) != -1) &&
442#endif
443 (tt_stat.st_mode & S_IEXEC)); /* he's using biff */
444
445}
446
447biff(on)
448{
449 if (dw_biff == NO)
450 return;
451#ifndef BSD4_2
452 (void) chmod(tt_name, on ? tt_stat.st_mode :
453 (tt_stat.st_mode & ~S_IEXEC));
454#else
455 (void) fchmod(0, on ? tt_stat.st_mode :
456 (tt_stat.st_mode & ~S_IEXEC));
457#endif
458}
459
460#endif
461
462ttinit()
463{
464#ifdef BIFF
465 biff_init();
466#endif
467#ifdef TIOCSLTC
468 (void) ioctl(0, TIOCGLTC, (struct sgttyb *) &ls1);
469 ls2 = ls1;
470 ls2.t_suspc = (char) -1;
471 ls2.t_dsuspc = (char) -1;
472 ls2.t_flushc = (char) -1;
473 ls2.t_lnextc = (char) -1;
474#endif
475
476#ifdef TIOCGETC
477 /* Change interupt and quit. */
478 (void) ioctl(0, TIOCGETC, (struct sgttyb *) &tc1);
479 tc2 = tc1;
480 tc2.t_intrc = CTL(]);
481 tc2.t_quitc = (char) -1;
482 if (OKXonXoff) {
483 tc2.t_stopc = (char) -1;
484 tc2.t_startc = (char) -1;
485 }
486#endif TIOCGETC
487 do_sgtty();
488}
489
490private int done_ttinit = 0;
491
492do_sgtty()
493{
494#ifdef SYSV
495 (void) ioctl(0, TCGETA, (char *) &sg1);
496#else
497 (void) gtty(0, &sg1);
498#endif SYSV
499 sg2 = sg1;
500
501#ifdef SYSV
502 TABS = !((sg1.c_oflag & TAB3) == TAB3);
503 ospeed = sg1.c_cflag & CBAUD;
504
505 sg2.c_iflag &= ~(INLCR|ICRNL|IGNCR);
506 sg2.c_lflag &= ~(ISIG|ICANON|ECHO);
507 sg2.c_oflag &= ~(OCRNL|ONLCR);
508 sg2.c_cc[VMIN] = sizeof smbuf;
509 sg2.c_cc[VTIME] = 1;
510#else
511 TABS = !(sg1.sg_flags & XTABS);
512 ospeed = sg1.sg_ospeed;
513#ifdef BRLUNIX
514 sg2.sg_flags &= ~(ECHO | CRMOD);
515 sg2.sg_flags |= CBREAK;
516
517 /* VT100 Kludge: leave STALL on for flow control if DC3DC1 (Yuck.) */
518 sg2.sg_xflags &= ~((sg2.sg_xflags&DC3DC1 ? 0 : STALL) | PAGE);
519#else
520 sg2.sg_flags &= ~(ECHO | CRMOD);
521#endif BRLUNIX
522
523#ifdef EUNICE
524 sg2.sg_flags |= RAW; /* Eunice needs RAW mode last I heard. */
525#else
526#ifdef PURDUE_EE
527# ifdef pdp11
528 sg2.sg_flags |= RAW;
529# else
530 sg2.sg_flags |= (MetaKey ? RAW : CBREAK);
531# endif
532#else
533 sg2.sg_flags |= (MetaKey ? RAW : CBREAK);
534#endif PURDUE_EE
535#endif EUNICE
536#endif SYSV
537}
538
539tty_reset()
540{
541 if (!done_ttinit)
542 return;
543 ttyset(OFF); /* go back to original modes */
544 ttinit();
545 ttyset(ON);
546}
547
548/* If n is OFF reset to original modes */
549
550ttyset(n)
551{
552 if (!done_ttinit && n == 0) /* Try to reset before we've set! */
553 return;
554#ifdef SYSV
555 (void) ioctl(0, TCSETAW, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2);
556#else
557#ifdef BRLUNIX
558 (void) stty(0, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2);
559#else
560 (void) ioctl(0, TIOCSETN, n == 0 ? (struct sgttyb *) &sg1 : (struct sgttyb *) &sg2);
561#endif BRLUNIX
562#endif SYSV
563
564#ifdef TIOCSETC
565 (void) ioctl(0, TIOCSETC, n == 0 ? (struct sgttyb *) &tc1 : (struct sgttyb *) &tc2);
566#endif TIOCSETC
567#ifdef TIOCSLTC
568 (void) ioctl(0, TIOCSLTC, n == 0 ? (struct sgttyb *) &ls1 : (struct sgttyb *) &ls2);
569#endif TIOCSLTC
570 done_ttinit = 1;
571#ifdef BIFF
572 biff(!n);
573#endif
574}
575
576int this_cmd,
577 last_cmd;
578
579dispatch(c)
580register int c;
581{
582 data_obj *cp;
583
584 this_cmd = 0;
585 cp = mainmap[c & 0177];
586
587 if (cp == 0) {
588 rbell();
589 exp = 1;
590 exp_p = errormsg = 0;
591 message(NullStr);
592 return;
593 }
594 ExecCmd(cp);
595}
596
597int LastKeyStruck,
598 MetaKey = 0;
599
600getch()
601{
602 register int c,
603 peekc;
604#ifdef IPROCS
605 extern int NumProcs;
606#endif
607 extern int ModCount,
608 Interactive;
609
610 if (Inputp) {
611 if ((c = *Inputp++) != 0)
612 return LastKeyStruck = c;
613 Inputp = 0;
614 }
615
616 if (InJoverc)
617 return EOF; /* somethings wrong if Inputp runs out while
618 we're reading a .joverc file. */
619
620 if (ModCount >= SyncFreq) {
621 ModCount = 0;
622 SyncRec();
623 }
624
625 /* If we're not interactive and we're not executing a macro,
626 AND there are no ungetc'd characters, we read from the
627 terminal (i.e., getch()). And characters only get put
628 in macros from inside this if. */
629 if (((peekc = c = Peekc()) == -1) && (Interactive || ((c = mac_getc()) == -1))) {
630 /* So messages that aren't error messages don't
631 hang around forever. */
632 if (!UpdMesg && !Asking) { /* Don't erase if we are asking */
633 if (mesgbuf[0] && !errormsg)
634 message(NullStr);
635 }
636 redisplay();
637#ifdef IPROCS
638# ifdef PIPEPROCS
639 if (NumProcs > 0) {
640 sigrelse(INPUT_SIG);
641 sigrelse(SIGCHLD);
642 }
643# endif
644#endif
645 inIOread = 1;
646 if ((c = getchar()) == EOF)
647 finish(SIGHUP);
648 inIOread = 0;
649
650#ifdef IPROCS
651# ifdef PIPEPROCS
652 if (NumProcs > 0) {
653 sighold(INPUT_SIG);
654 sighold(SIGCHLD);
655 }
656# endif
657#endif
658 if (!Interactive && (KeyMacro.m_flags & DEFINE))
659 mac_putc(c);
660 }
661 if (peekc == -1) /* Don't add_stroke peekc's */
662 add_stroke(c);
663 return LastKeyStruck = c;
664}
665
666dorecover()
667{
668 execl(RECOVER, "jove_recover", 0);
669 printf("%s: execl failed!\n", RECOVER);
670 flusho();
671 _exit(-1);
672}
673
674
675ShowVersion()
676{
677 extern char *version;
678
679 s_mess("Jonathan's Own Version of Emacs (%s)", version);
680}
681
682UNIX_cmdline(argc, argv)
683char *argv[];
684{
685 int lineno = 0,
686 nwinds = 1;
687 Buffer *b;
688
689 ShowVersion();
690 while (argc > 1) {
691 if (argv[1][0] != '-' && argv[1][0] != '+') {
692 int force = (nwinds > 0 || lineno != 0);
693
694 minib_add(argv[1], force ? YES : NO);
695 b = do_find(nwinds > 0 ? curwind : (Window *) 0,
696 argv[1], force);
697 if (force) {
698 SetABuf(curbuf);
699 SetBuf(b);
700 SetLine(next_line(curbuf->b_first, lineno));
701 if (nwinds > 1)
702 NextWindow();
703 if (nwinds)
704 nwinds--;
705 }
706 lineno = 0;
707 } else switch (argv[1][1]) {
708 case 'd':
709 ++argv;
710 --argc;
711 break;
712
713 case 'j': /* Ignore .joverc in HOME */
714 break;
715
716 case 'p':
717 ++argv;
718 --argc;
719 SetBuf(do_find(curwind, argv[1], 0));
720 ParseAll();
721 nwinds = 0;
722 break;
723
724 case 't':
725 ++argv;
726 --argc;
727 exp_p = 1;
728 find_tag(argv[1], YES);
729 break;
730
731 case 'w':
732 if (argv[1][2] == '\0')
733 nwinds++;
734 else
735 nwinds += -1 + chr_to_int(&argv[1][2], 10, NIL);
736 (void) div_wind(curwind, nwinds - 1);
737 break;
738
739 case '0':
740 case '1':
741 case '2':
742 case '3':
743 case '4':
744 case '5':
745 case '6':
746 case '7':
747 case '8':
748 case '9':
749 lineno = chr_to_int(&argv[1][1], 10, 0) - 1;
750 break;
751 }
752 ++argv;
753 --argc;
754 }
755}
756
757#ifdef lint
758Ignore(a)
759 char *a;
760{
761
762 a = a;
763}
764
765Ignorf(a)
766 int (*a)();
767{
768
769 a = a;
770}
771
772Ignorl(a)
773long a;
774{
775 a = a;
776}
777#endif
778
779/* VARARGS1 */
780
781error(fmt, va_alist)
782char *fmt;
783va_dcl
784{
785 va_list ap;
786
787 if (fmt) {
788 va_start(ap);
789 format(mesgbuf, sizeof mesgbuf, fmt, ap);
790 va_end(ap);
791 UpdMesg++;
792 }
793 rbell();
794 (void) longjmp(mainjmp, ERROR);
795}
796
797/* VARARGS1 */
798
799complain(fmt, va_alist)
800char *fmt;
801va_dcl
802{
803 va_list ap;
804
805 if (fmt) {
806 va_start(ap);
807 format(mesgbuf, sizeof mesgbuf, fmt, ap);
808 va_end(ap);
809 UpdMesg++;
810 }
811 rbell();
812 (void) longjmp(mainjmp, COMPLAIN);
813}
814
815/* VARARGS1 */
816
817confirm(fmt, va_alist)
818char *fmt;
819va_dcl
820{
821 char *yorn;
822 va_list ap;
823
824 va_start(ap);
825 format(mesgbuf, sizeof mesgbuf, fmt, ap);
826 va_end(ap);
827 yorn = ask((char *) 0, mesgbuf);
828 if (*yorn != 'Y' && *yorn != 'y')
829 (void) longjmp(mainjmp, COMPLAIN);
830}
831
832int RecDepth = 0;
833
834Recur()
835{
836 char bname[128];
837 Mark *m;
838
839 sprintf(bname, "%s", curbuf->b_name);
840 m = MakeMark(curline, curchar, FLOATER);
841
842 RecDepth++;
843 UpdModLine++;
844 DoKeys(1); /* 1 means not first time */
845 UpdModLine++;
846 RecDepth--;
847 SetBuf(do_select(curwind, bname));
848 if (!exp_p)
849 ToMark(m);
850 DelMark(m);
851}
852
853jmp_buf mainjmp;
854int iniargc; /* main sets these for DoKeys() */
855char **iniargv;
856
857DoKeys(nocmdline)
858{
859 int c;
860 jmp_buf savejmp;
861
862 push_env(savejmp);
863
864 switch (setjmp(mainjmp)) {
865 case 0:
866 if (!nocmdline)
867 UNIX_cmdline(iniargc, iniargv);
868 break;
869
870 case QUIT:
871 if (RecDepth == 0) {
872 if (ModMacs()) {
873 rbell();
874 if (Upper(*ask("No",
875"Some MACROS haven't been saved; leave anyway? ")) != 'Y')
876 break;
877 }
878 if (ModBufs(0)) {
879 rbell();
880 if (Upper(*ask("No",
881"Some buffers haven't been saved; leave anyway? ")) != 'Y')
882 break;
883 }
884#ifdef IPROCS
885 KillProcs();
886#endif
887 }
888 pop_env(savejmp);
889 return;
890
891 case ERROR:
892 getDOT(); /* God knows what state linebuf was in */
893
894 case COMPLAIN:
895 gc_openfiles(); /* close any files we left open */
896 errormsg++;
897 fix_macros();
898 Asking = 0;
899 curwind->w_bufp = curbuf;
900 redisplay();
901 break;
902 }
903
904 this_cmd = last_cmd = 0;
905
906 for (;;) {
907 if (this_cmd != ARG_CMD) {
908 exp = 1;
909 exp_p = 0;
910 last_cmd = this_cmd;
911 init_strokes();
912 }
913 c = getch();
914 if (c == -1)
915 continue;
916 dispatch(c);
917 }
918}
919
920int Crashing = 0;
921
922char **
923scanvec(args, str)
924register char **args,
925 *str;
926{
927 while (*args) {
928 if (strcmp(*args, str) == 0)
929 return args;
930 args++;
931 }
932 return 0;
933}
934
935int UpdFreq = 30,
936 inIOread = 0;
937
938updmode()
939{
940 UpdModLine++;
941 if (inIOread)
942 redisplay();
943#ifndef JOB_CONTROL
944 (void) signal(SIGALRM, updmode);
945#endif
946 (void) alarm((unsigned) UpdFreq);
947}
948
949#ifdef TIOCGWINSZ
950#ifdef SIGWINCH
951extern win_reshape();
952#endif
953#endif
954
955#ifdef TIOCGWINSZ
956#ifdef SIGWINCH
957win_reshape()
958{
959 register int diff;
960
961 (void) signal(SIGWINCH, SIG_IGN);
962
963 /*
964 * Save old number of lines.
965 */
966 diff = LI;
967
968 /*
969 * Get new line/col info.
970 */
971 ttsize();
972
973 /*
974 * LI has changed, and now holds the
975 * new value. See how much the size
976 * changed.
977 */
978 diff = LI - diff;
979
980 /*
981 * Change the size of the current window
982 * only. If they shrank by more than
983 * the window size, tough.
984 */
985 if ((curwind->w_height + diff) < 2)
986 curwind->w_height = 2;
987 else
988 curwind->w_height += diff;
989
990 make_scr();
991 redisplay();
992
993 (void) signal(SIGWINCH, win_reshape);
994}
995#endif
996#endif
997
998main(argc, argv)
999char *argv[];
1000{
1001 char ttbuf[512],
1002#ifndef VMUNIX
1003 s_iobuff[LBSIZE],
1004 s_genbuf[LBSIZE],
1005 s_linebuf[LBSIZE],
1006#endif
1007 *cp;
1008
1009
1010#ifndef VMUNIX
1011 /* The way I look at it, there ain't no way I is gonna run
1012 out of stack space UNLESS I have some kind of infinite
1013 recursive bug. So why use up some valuable memory, when
1014 there is plenty of space on the stack? (This only matters
1015 on wimpy pdp11's, of course.) */
1016
1017 iobuff = s_iobuff;
1018 genbuf = s_genbuf;
1019 linebuf = s_linebuf;
1020#endif
1021
1022 errormsg = 0;
1023
1024 iniargc = argc;
1025 iniargv = argv;
1026
1027 if (setjmp(mainjmp)) {
1028 printf("\rAck! I can't deal with error \"%s\" now.\n\r", mesgbuf);
1029 finish(0);
1030 }
1031
1032 if (scanvec(argv, "-r"))
1033 dorecover();
1034
1035 getTERM(); /* Get terminal. */
1036 if (getenv("METAKEY"))
1037 MetaKey = 1;
1038 ttsize();
1039 InitCM();
1040
1041 tmpinit(); /* Init temp file. */
1042
1043 if (cp = getenv("SHELL"))
1044 strcpy(Shell, cp);
1045
1046 make_scr();
1047 mac_init(); /* Initialize Macros */
1048 winit(); /* Initialize Window */
1049#ifdef IPROCS
1050 pinit(); /* Pipes/process initialization */
1051#endif
1052 SetBuf(do_select(curwind, Mainbuf));
1053
1054#ifdef CHDIR
1055 {
1056 char **argp;
1057
1058 if ((argp = scanvec(argv, "-d")) && (argp[1][0] == '/'))
1059 setCWD(argp[1]);
1060 else
1061 getCWD(); /* After we setup curbuf in case we have to getwd() */
1062 }
1063#endif
1064 HomeDir = getenv("HOME");
1065 if (HomeDir == 0)
1066 HomeDir = "/";
1067 HomeLen = strlen(HomeDir);
1068 (void) joverc(JOVERC);
1069 if (!scanvec(argv, "-j")) {
1070 char tmpbuf[100];
1071
1072 sprintf(tmpbuf, "%s/.joverc", HomeDir);
1073 (void) joverc(tmpbuf);
1074 }
1075#ifdef SYSV
1076 sprintf(MailBox, "/usr/mail/%s", getenv("LOGNAME"));
1077#else
1078 sprintf(Mailbox, "/usr/spool/mail/%s", getenv("USER"));
1079#endif SYSV
1080 (void) time(&time0);
1081 ttinit(); /* initialize terminal (after ~/.joverc) */
1082 settout(ttbuf); /* not until we know baudrate */
1083 ResetTerm();
1084
1085 (void) signal(SIGHUP, finish);
1086 (void) signal(SIGINT, finish);
1087 (void) signal(SIGQUIT, SIG_IGN);
1088 (void) signal(SIGBUS, finish);
1089 (void) signal(SIGSEGV, finish);
1090 (void) signal(SIGPIPE, finish);
1091 (void) signal(SIGTERM, SIG_IGN);
1092#ifdef TIOCGWINSZ
1093#ifdef SIGWINCH
1094 (void) signal(SIGWINCH, win_reshape);
1095#endif
1096#endif
1097
1098 /* set things up to update the modeline every UpdFreq seconds */
1099 (void) signal(SIGALRM, updmode);
1100 (void) alarm((unsigned) UpdFreq);
1101
1102 cl_scr(1);
1103 flusho();
1104 RedrawDisplay(); /* start the redisplay process. */
1105 DoKeys(0);
1106 finish(0);
1107}