source: trunk/minix/commands/elle/eemain.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 11.9 KB
Line 
1/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author.
5 */
6/*
7 * EEMAIN ELLE Main Command Loop
8 */
9
10#include "elle.h"
11
12#include <stdio.h>
13#if !(V6)
14#include <signal.h>
15#else
16#include "eesigs.h" /* Use this on V6 system */
17#endif /*V6*/
18
19char *argfile[MAXARGFILES]; /* Filename args at startup */
20
21extern int (*sbm_debug)();
22extern int (*sbv_debug)();
23int (*vfy_vec)(); /* If non-zero, routine to verify data
24 * after each main-loop command */
25
26main (argc, argv)
27int argc;
28char **argv;
29{
30 register int c; /* Current command character */
31 register int i;
32 static int waitct;
33 extern int errsbm();
34#if SUN
35 extern int sun_rdevf; /* from EESUN */
36#endif
37#ifdef STKMEM
38 char stackm[STKMEM]; /* Allocate some unused stack space */
39#endif /*STKMEM*/
40
41 sbv_debug = errsbm; /* Load with addrs of routine to */
42 sbm_debug = errsbm; /* process SB and SBM errors. */
43
44#ifdef STKMEM
45 sbm_init(&stackm[0],(SBMO)STKMEM); /* Initialize mem alloc rtns */
46#endif /*STKMEM*/
47#if SUN
48 sun_main(&argc, argv); /* On SUN, invoke window startup */
49#endif /*SUN*/
50
51 setbuf(stdout, (char *)NULL); /* Remove all stdio buffering */
52 setbuf(stderr, (char *)NULL); /* in case of error reports. */
53
54 waitct = 0; /* debugging */
55 doargs(argc,argv); /* Set up args */
56 initialize (); /* Initialize the editor */
57
58 if (argfile[0]) /* shell line arg */
59 find_file(argfile[0]);
60#if MAXARGFILES > 1
61 if(argfile[1])
62 { f_2winds(); /* Make 2 windows, go to 2nd */
63 i = 1;
64#if MAXARGFILES > 2
65 for (; i < MAXARGFILES; ++i)
66#endif /* > 2 files */
67 find_file(argfile[i]); /* Get further file(s) */
68 f_othwind(); /* Move back to 1st window */
69 }
70#endif /* > 1 file */
71
72 redp(RD_SCREEN|RD_MODE); /* Clear and show mode line */
73 setexit(0); /* catch for ints, ^G throws */
74
75/* -----------------------------------------------------------
76** ELLE MAIN LOOP
77**
78*/
79 for (;;)
80 {
81 /* First set up default arg unless last cmd specified it */
82 if(this_cmd != ARGCMD)
83 { exp = 1; /* Default arg is 1 */
84 exp_p = 0; /* Say no explicit arg */
85 last_cmd = this_cmd;
86 }
87 this_cmd = 0;
88
89 askclr(); /* If stuff asked, say to clear it */
90 if(cmd_wait())
91 waitct++;
92 else if(rd_type != 0)
93 redisplay(); /* Redisplay if needed and no input */
94#if SUN
95 sun_rdevf = 1; /* Allow mouse events on this input */
96#endif
97 c = cmd_read(); /* Read an editor command */
98 sayclr(); /* Ask to clear echo area cleverly */
99
100#if SUN
101 if(c != -1) /* SUN may not have real input */
102#endif /* if mouse event happened. */
103 cmd_xct(c); /* Execute the command char! */
104
105 if(vfy_vec) /* If debugging, */
106 (*vfy_vec)(1); /* verify data structs right away */
107 }
108}
109
110
111char *prof_file; /* Can specify user profile filename */
112
113doargs(argc,argv)
114int argc;
115char **argv;
116{ register int cnt, c;
117 register char **av;
118 extern int tibfmsk;
119 int argfiles = 0;
120 int argsignored = 0;
121
122 av = argv;
123 cnt = argc;
124
125#if V6 /* V6 doesn't have environment thus no TERM var */
126 /* Hack to force terminal type; analyze pgm name to get
127 * possible ".type" suffix.
128 */
129 if(cnt && (c = strlen(*av)))
130 while(--c >= 0)
131 { switch(av[0][c])
132 { case '.':
133 tv_stype = &av[0][c+1];
134 case '/':
135 break;
136 default: continue;
137 }
138 break;
139 }
140#endif /*V6*/
141
142 while(--cnt > 0)
143 { ++av;
144 if(*av[0] != '-') /* If not switch, */
145 { /* assume it's an input filename */
146 if (argfiles < MAXARGFILES)
147 argfile[argfiles++] = *av;
148 else
149 ++argsignored;
150 continue;
151 }
152 c = upcase(av[0][1]);
153 switch(c) /* Switches without args */
154 { case 'I': /* Allow debug ints */
155 dbg_isw = 1;
156 continue;
157 case '8': /* Ask for 8-bit input */
158 tibfmsk = 0377;
159 continue;
160 case '7': /* Ask for 7-bit input */
161 tibfmsk = 0177;
162 continue;
163#if IMAGEN
164 case 'R': /* Debug redisplay stuff */
165 dbg_redp = 1;
166 continue;
167#endif /*IMAGEN*/
168 }
169 if(--cnt <= 0)
170 goto stop;
171 ++av;
172 switch(c) /* Switches with args */
173 { case 'T': /* Terminal type */
174 tv_stype = *av;
175 break;
176 case 'P':
177 prof_file = *av;
178 default:
179 goto stop;
180 }
181 continue;
182 stop: printf("ELLE: bad switch: %s\n",*av);
183 exit(1);
184 }
185 if (argsignored > 0)
186 { printf("ELLE: more than %d file args, %d ignored.\n",
187 MAXARGFILES, argsignored);
188 sleep(2); /* Complain but continue after pause */
189 }
190}
191
192
193int f_throw(); /* throw function */
194int bite_bag(); /* Error handling routine */
195int hup_exit(); /* Hangup handling routine */
196
197struct majmode ifunmode = { "Fundamental" };
198
199initialize () /* Initialization */
200{
201#if SUN
202 extern int sun_winfd;
203#endif
204 cur_mode = fun_mode = &ifunmode; /* Set current major mode */
205 unrchf = pgoal = -1;
206 if(!homedir)
207 {
208#if V6
209 extern char *logdir();
210 homedir = logdir();
211#else /* V7 */
212 homedir = getenv("HOME");
213#endif /*-V6*/
214 }
215
216 sbx_tset((chroff)0,0); /* Create swapout file */
217 /* (Temporary hack, fix up later) */
218 hoard(); /* Hoard a FD for write purposes */
219
220 redp_init(); /* Set up the display routines */
221 init_buf(); /* Set up initial buffers */
222 set_profile(prof_file); /* Set up user profile */
223
224#if SUN
225 if(sun_winfd) sun_init();
226#endif /*SUN*/
227
228 /* Set up signal handlers */
229#if 0 /* not really used */
230 signal (SIGQUIT, f_throw); /* Quit - on ^G */
231#endif
232#if !(MINIX)
233 signal (SIGSYS, bite_bag); /* Bad arg to Sys call */
234#endif
235 signal (SIGSEGV, bite_bag); /* Segmentation Violation */
236#if !(COHERENT)
237 signal (SIGILL, bite_bag); /* Illegal Instruction interrupt */
238 signal (SIGBUS, bite_bag); /* Bus Error interrupt */
239#endif /*-COHERENT*/
240#if !(TOPS20) /* T20 just detaches job */
241 signal (SIGHUP, hup_exit); /* Terminal Hangup interrupt */
242#endif /*-TOPS20*/
243}
244
245
246/* NOTE: This routine is not actually used, because ELLE does not
247 * allow interrupts to do anything.
248 */
249/* EFUN: "Error Throw" */
250f_throw () /* abort whatever is going on */
251{
252 ring_bell ();
253 curs_lin = -1000; /* make t_curpos do something */
254 redp(RD_MOVE); /* crock: cursor seems to move, so fix it */
255 signal(SIGQUIT, f_throw); /* rearm signal */
256/* unwind_stack(main); */
257 reset(1); /* throw to main loop */
258}
259
260/* RING_BELL - General-purpose feeper when something goes wrong with
261 * a function.
262 */
263ring_bell()
264{ t_bell(); /* Tell user something's wrong */
265
266#if FX_SKMAC
267 f_ekmac(); /* Stop collecting keyboard macro if any */
268#endif /*FX_SKMAC*/
269}
270
271
272/* EFUN: "Return to Superior"
273 * Behavior here is somewhat system-dependent. If it is possible to
274 * suspend the process and continue later, we do not ask about modified
275 * buffers. Otherwise, we do. Questioning can always be forced by using
276 * the prefix ^U.
277 * Note that here we try to be very careful about not letting the user
278 * exit while buffers are still modified, since UNIX flushes the process
279 * if we exit. Also, the code here conspires with sel_mbuf to rotate
280 * through all modified buffers, complaining about a different one each time,
281 * so that the user need not even know how to select a buffer!
282 */
283f_retsup()
284{ register char *reply;
285 register int c;
286 register struct buffer *b, *b2;
287 extern struct buffer *sel_mbuf();
288 extern int tsf_pause;
289
290 /* If we have capability of pausing and later continuing, do that,
291 * except if CTRL-U forces us into question/save/quit behavior.
292 */
293 if(tsf_pause && (exp_p != 4))
294 { clean_exit(); /* Return TTY to normal mode */
295 ts_pause(); /* Pause this inferior */
296 set_tty(); /* Continued, return to edit mode */
297 redp(RD_SCREEN);
298 return;
299 }
300
301 /* Sigh, do more typical "Are you sure" questioning prior to
302 * killing the editor permanently.
303 */
304 b = cur_buf;
305 if((b = sel_mbuf(b)) || (b = sel_mbuf((struct buffer *)0)) )
306 { if(b2 = sel_mbuf(b))
307 reply = ask(
308 "Quit: buffers %s, %s,... still have changes - forget them? ",
309 b->b_name, b2->b_name);
310 else
311 reply = ask(
312 "Quit: buffer %s still has changes - forget them? ",
313 b->b_name);
314
315 }
316 else
317 {
318#if IMAGEN /* Do not ask further if nothing modified */
319 barf("Bye");
320 clean_exit();
321 exit(0);
322#else
323 reply = ask("Quit? ");
324#endif /*-IMAGEN*/
325 }
326
327 if (reply == 0)
328 return; /* Aborted, just return */
329
330 c = upcase(*reply); /* Get 1st char of reply */
331 chkfree(reply);
332
333 switch(c)
334 { case 'Y':
335#if IMAGEN
336 barf("Bye");
337#endif /*IMAGEN*/
338 clean_exit();
339 exit(0);
340#if 0
341 case 'S': /* Suspend command for debugging */
342 bkpt();
343 return;
344#endif /*COMMENT*/
345 default: /* Complain */
346 ring_bell();
347 case 'N':
348 if(b) /* B set if we have any modified buffers */
349 { sel_buf(b);
350 if(b->b_fn)
351 saynow("Use ^X ^S to save buffer");
352 else saynow("Use ^X ^W to write out buffer");
353 }
354 }
355}
356
357
358
359#if FX_WFEXIT
360/* EFUN: "Write File Exit" (not EMACS) - from IMAGEN config */
361f_wfexit()
362{
363 exp_p = 1; /* Ensure f_savefiles asks no questions */
364 if (! f_savefiles()) /* Save all modified buffers, but */
365 return; /* stay here if any save fails */
366 saynow("Bye");
367 clean_exit();
368 exit(0);
369}
370#endif /*FX_WFEXIT*/
371
372
373/* Subprocess-handling stuff; put here for time being. */
374
375/* EFUN: "Push to Inferior" */
376#if TOPS20
377#include <frkxec.h> /* Support for KCC forkexec() call */
378#endif
379f_pshinf()
380{
381 register int res;
382 register int (*sav2)(), (*sav3)();
383 int pid, status;
384 char *shellname;
385#if IMAGEN
386 char fullshell[64];
387#endif /*IMAGEN*/
388
389 sav2 = signal(SIGINT, SIG_IGN); /* Ignore TTY interrupts */
390 sav3 = signal(SIGQUIT, SIG_IGN); /* Ditto TTY "quit"s */
391 clean_exit(); /* Restore normal TTY modes */
392
393#if TOPS20
394 {
395 struct frkxec fx;
396 fx.fx_flags = FX_WAIT | FX_T20_PGMNAME;
397 fx.fx_name = "SYS:EXEC.EXE";
398 fx.fx_argv = fx.fx_envp = NULL;
399 if (forkexec(&fx) < 0)
400 writerr("Cannot run EXEC");
401 }
402#else /*-TOPS20*/
403 switch(pid = fork())
404 { case -1:
405 writerr("Cannot fork");
406 break;
407 case 0: /* We're the child */
408 for(res = 3; res < 20;) /* Don't let inf hack fd's */
409 close(res++);
410#if V6
411 execl("/bin/sh","-sh",0);
412#else
413 signal(SIGINT, SIG_DFL); /* V7 shell wants this?? */
414 signal(SIGQUIT, SIG_DFL); /* */
415#if IMAGEN
416 if((shellname = getenv("SHELL")) == 0)
417 shellname = "sh";
418 strcpy(fullshell, "/bin/");
419 strcat(fullshell, shellname);
420 shellname = fullshell;
421#else
422 if((shellname = getenv("SHELL")) == 0)
423 shellname = "/bin/sh";
424#endif /*-IMAGEN*/
425
426 if((shellname = getenv("SHELL")) == 0)
427 shellname = "/bin/sh";
428 execl(shellname, shellname, 0);
429#endif /*-V6*/
430 writerr("No shell!");
431 exit(1);
432 break;
433 default:
434 while((res = wait(&status)) != pid && res != -1);
435 break;
436 }
437#endif /*-TOPS20*/
438
439 signal(SIGINT, sav2); /* Restore signal settings */
440 signal(SIGQUIT, sav3);
441 set_tty(); /* Restore editor TTY modes */
442 redp(RD_SCREEN|RD_MODE); /* Done, redisplay */
443}
444
445
446/* Miscellaneous utility routines - memory alloc/free and string hacking.
447 * If this page becomes overly large, it can be split off into a separate
448 * file called E_MISC.
449 */
450char *
451strdup(s)
452char *s; /* Note that STRCPY's return val must be its 1st arg */
453{ char *strcpy();
454 return(strcpy(memalloc((SBMO)(strlen(s)+1)), s));
455}
456
457char *
458memalloc(size)
459SBMO size;
460{ register SBMA ptr;
461 extern SBMA sbx_malloc();
462
463 if ((ptr = (SBMA)sbx_malloc(size)) != 0)
464 return((char *)ptr);
465 barf("ELLE: No memory left");
466 askerr();
467 return(0); /* If we dare to continue... */
468}
469
470chkfree (ptr)
471SBMA ptr;
472{
473 if(!free(ptr))
474 { errbarf("Something overwrote an allocated block!");
475 askerr();
476 }
477}
478
479
480/* USTRCMP - Uppercase String Compare.
481 * Returns 0 if mismatch,
482 * 1 if full match,
483 * -1 if str1 runs out first (partial match)
484 */
485ustrcmp(str1,str2)
486char *str1, *str2;
487{ register char *s1, *s2;
488 register int c;
489 s1 = str1; s2 = str2;
490 while(c = *s1++)
491 { if(c != *s2 && upcase(c) != upcase(*s2))
492 return(0);
493 s2++;
494 }
495 return(c == *s2 ? 1 : -1);
496}
497
498
499/* WRITERR(str) - Output string to standard error output.
500** This is a separate routine to save a little space on calls.
501*/
502writerr(str)
503char *str;
504{ return(writez(2, str));
505}
506
507/* WRITEZ(fd, str) - Miscellaneous general-purpose string output.
508 */
509writez(fd,acp)
510int fd;
511char *acp;
512{ register char *cp;
513 cp = acp;
514 while(*cp++);
515 write(fd,acp,cp-acp-1);
516}
Note: See TracBrowser for help on using the repository browser.