pci: don't do sanity check for missing pci bus, the check can misfire.
[minix.git] / commands / elle / eemain.c
blobf457858eeae96e825fb696aa84b0dd4a70b2cd51
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 */
10 #include "elle.h"
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*/
19 char *argfile[MAXARGFILES]; /* Filename args at startup */
21 extern int (*sbm_debug)();
22 extern int (*sbv_debug)();
23 int (*vfy_vec)(); /* If non-zero, routine to verify data
24 * after each main-loop command */
26 main (argc, argv)
27 int argc;
28 char **argv;
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*/
41 sbv_debug = errsbm; /* Load with addrs of routine to */
42 sbm_debug = errsbm; /* process SB and SBM errors. */
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*/
51 setbuf(stdout, (char *)NULL); /* Remove all stdio buffering */
52 setbuf(stderr, (char *)NULL); /* in case of error reports. */
54 waitct = 0; /* debugging */
55 doargs(argc,argv); /* Set up args */
56 initialize (); /* Initialize the editor */
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 */
70 #endif /* > 1 file */
72 redp(RD_SCREEN|RD_MODE); /* Clear and show mode line */
73 setexit(0); /* catch for ints, ^G throws */
75 /* -----------------------------------------------------------
76 ** ELLE MAIN LOOP
79 for (;;)
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;
87 this_cmd = 0;
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 */
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! */
105 if(vfy_vec) /* If debugging, */
106 (*vfy_vec)(1); /* verify data structs right away */
110 char *prof_file; /* Can specify user profile filename */
112 doargs(argc,argv)
113 int argc;
114 char **argv;
115 { register int cnt, c;
116 register char **av;
117 extern int tibfmsk;
118 int argfiles = 0;
119 int argsignored = 0;
121 av = argv;
122 cnt = argc;
124 #if V6 /* V6 doesn't have environment thus no TERM var */
125 /* Hack to force terminal type; analyze pgm name to get
126 * possible ".type" suffix.
128 if(cnt && (c = strlen(*av)))
129 while(--c >= 0)
130 { switch(av[0][c])
131 { case '.':
132 tv_stype = &av[0][c+1];
133 case '/':
134 break;
135 default: continue;
137 break;
139 #endif /*V6*/
141 while(--cnt > 0)
142 { ++av;
143 if(*av[0] != '-') /* If not switch, */
144 { /* assume it's an input filename */
145 if (argfiles < MAXARGFILES)
146 argfile[argfiles++] = *av;
147 else
148 ++argsignored;
149 continue;
151 c = upcase(av[0][1]);
152 switch(c) /* Switches without args */
153 { case 'I': /* Allow debug ints */
154 dbg_isw = 1;
155 continue;
156 case '8': /* Ask for 8-bit input */
157 tibfmsk = 0377;
158 continue;
159 case '7': /* Ask for 7-bit input */
160 tibfmsk = 0177;
161 continue;
162 #if IMAGEN
163 case 'R': /* Debug redisplay stuff */
164 dbg_redp = 1;
165 continue;
166 #endif /*IMAGEN*/
168 if(--cnt <= 0)
169 goto stop;
170 ++av;
171 switch(c) /* Switches with args */
172 { case 'T': /* Terminal type */
173 tv_stype = *av;
174 break;
175 case 'P':
176 prof_file = *av;
177 default:
178 goto stop;
180 continue;
181 stop: printf("ELLE: bad switch: %s\n",*av);
182 exit(1);
184 if (argsignored > 0)
185 { printf("ELLE: more than %d file args, %d ignored.\n",
186 MAXARGFILES, argsignored);
187 sleep(2); /* Complain but continue after pause */
191 int f_throw(); /* throw function */
192 int bite_bag(); /* Error handling routine */
193 int hup_exit(); /* Hangup handling routine */
195 struct majmode ifunmode = { "Fundamental" };
197 initialize () /* Initialization */
199 #if SUN
200 extern int sun_winfd;
201 #endif
202 cur_mode = fun_mode = &ifunmode; /* Set current major mode */
203 unrchf = pgoal = -1;
204 if(!homedir)
206 #if V6
207 extern char *logdir();
208 homedir = logdir();
209 #else /* V7 */
210 homedir = getenv("HOME");
211 #endif /*-V6*/
214 sbx_tset((chroff)0,0); /* Create swapout file */
215 /* (Temporary hack, fix up later) */
216 hoard(); /* Hoard a FD for write purposes */
218 redp_init(); /* Set up the display routines */
219 init_buf(); /* Set up initial buffers */
220 set_profile(prof_file); /* Set up user profile */
222 #if SUN
223 if(sun_winfd) sun_init();
224 #endif /*SUN*/
226 /* Set up signal handlers */
227 #if 0 /* not really used */
228 signal (SIGQUIT, f_throw); /* Quit - on ^G */
229 #endif
230 #if !(MINIX)
231 signal (SIGSYS, bite_bag); /* Bad arg to Sys call */
232 #endif
233 signal (SIGSEGV, bite_bag); /* Segmentation Violation */
234 #if !(COHERENT)
235 signal (SIGILL, bite_bag); /* Illegal Instruction interrupt */
236 signal (SIGBUS, bite_bag); /* Bus Error interrupt */
237 #endif /*-COHERENT*/
238 #if !(TOPS20) /* T20 just detaches job */
239 signal (SIGHUP, hup_exit); /* Terminal Hangup interrupt */
240 #endif /*-TOPS20*/
244 /* NOTE: This routine is not actually used, because ELLE does not
245 * allow interrupts to do anything.
247 /* EFUN: "Error Throw" */
248 f_throw () /* abort whatever is going on */
250 ring_bell ();
251 curs_lin = -1000; /* make t_curpos do something */
252 redp(RD_MOVE); /* crock: cursor seems to move, so fix it */
253 signal(SIGQUIT, f_throw); /* rearm signal */
254 /* unwind_stack(main); */
255 reset(1); /* throw to main loop */
258 /* RING_BELL - General-purpose feeper when something goes wrong with
259 * a function.
261 ring_bell()
262 { t_bell(); /* Tell user something's wrong */
264 #if FX_SKMAC
265 f_ekmac(); /* Stop collecting keyboard macro if any */
266 #endif /*FX_SKMAC*/
269 /* EFUN: "Return to Superior"
270 * Behavior here is somewhat system-dependent. If it is possible to
271 * suspend the process and continue later, we do not ask about modified
272 * buffers. Otherwise, we do. Questioning can always be forced by using
273 * the prefix ^U.
274 * Note that here we try to be very careful about not letting the user
275 * exit while buffers are still modified, since UNIX flushes the process
276 * if we exit. Also, the code here conspires with sel_mbuf to rotate
277 * through all modified buffers, complaining about a different one each time,
278 * so that the user need not even know how to select a buffer!
280 f_retsup()
281 { register char *reply;
282 register int c;
283 register struct buffer *b, *b2;
284 extern struct buffer *sel_mbuf();
285 extern int tsf_pause;
287 /* If we have capability of pausing and later continuing, do that,
288 * except if CTRL-U forces us into question/save/quit behavior.
290 if(tsf_pause && (exp_p != 4))
291 { clean_exit(); /* Return TTY to normal mode */
292 ts_pause(); /* Pause this inferior */
293 set_tty(); /* Continued, return to edit mode */
294 redp(RD_SCREEN);
295 return;
298 /* Sigh, do more typical "Are you sure" questioning prior to
299 * killing the editor permanently.
301 b = cur_buf;
302 if((b = sel_mbuf(b)) || (b = sel_mbuf((struct buffer *)0)) )
303 { if(b2 = sel_mbuf(b))
304 reply = ask(
305 "Quit: buffers %s, %s,... still have changes - forget them? ",
306 b->b_name, b2->b_name);
307 else
308 reply = ask(
309 "Quit: buffer %s still has changes - forget them? ",
310 b->b_name);
313 else
315 #if IMAGEN /* Do not ask further if nothing modified */
316 barf("Bye");
317 clean_exit();
318 exit(0);
319 #else
320 reply = ask("Quit? ");
321 #endif /*-IMAGEN*/
324 if (reply == 0)
325 return; /* Aborted, just return */
327 c = upcase(*reply); /* Get 1st char of reply */
328 chkfree(reply);
330 switch(c)
331 { case 'Y':
332 #if IMAGEN
333 barf("Bye");
334 #endif /*IMAGEN*/
335 clean_exit();
336 exit(0);
337 #if 0
338 case 'S': /* Suspend command for debugging */
339 bkpt();
340 return;
341 #endif /*COMMENT*/
342 default: /* Complain */
343 ring_bell();
344 case 'N':
345 if(b) /* B set if we have any modified buffers */
346 { sel_buf(b);
347 if(b->b_fn)
348 saynow("Use ^X ^S to save buffer");
349 else saynow("Use ^X ^W to write out buffer");
355 #if FX_WFEXIT
356 /* EFUN: "Write File Exit" (not EMACS) - from IMAGEN config */
357 f_wfexit()
359 exp_p = 1; /* Ensure f_savefiles asks no questions */
360 if (! f_savefiles()) /* Save all modified buffers, but */
361 return; /* stay here if any save fails */
362 saynow("Bye");
363 clean_exit();
364 exit(0);
366 #endif /*FX_WFEXIT*/
368 /* Subprocess-handling stuff; put here for time being. */
370 /* EFUN: "Push to Inferior" */
371 #if TOPS20
372 #include <frkxec.h> /* Support for KCC forkexec() call */
373 #endif
374 f_pshinf()
376 register int res;
377 register int (*sav2)(), (*sav3)();
378 int pid, status;
379 char *shellname;
380 #if IMAGEN
381 char fullshell[64];
382 #endif /*IMAGEN*/
384 sav2 = signal(SIGINT, SIG_IGN); /* Ignore TTY interrupts */
385 sav3 = signal(SIGQUIT, SIG_IGN); /* Ditto TTY "quit"s */
386 clean_exit(); /* Restore normal TTY modes */
388 #if TOPS20
390 struct frkxec fx;
391 fx.fx_flags = FX_WAIT | FX_T20_PGMNAME;
392 fx.fx_name = "SYS:EXEC.EXE";
393 fx.fx_argv = fx.fx_envp = NULL;
394 if (forkexec(&fx) < 0)
395 writerr("Cannot run EXEC");
397 #else /*-TOPS20*/
398 switch(pid = fork())
399 { case -1:
400 writerr("Cannot fork");
401 break;
402 case 0: /* We're the child */
403 for(res = 3; res < 20;) /* Don't let inf hack fd's */
404 close(res++);
405 #if V6
406 execl("/bin/sh","-sh",0);
407 #else
408 signal(SIGINT, SIG_DFL); /* V7 shell wants this?? */
409 signal(SIGQUIT, SIG_DFL); /* */
410 #if IMAGEN
411 if((shellname = getenv("SHELL")) == 0)
412 shellname = "sh";
413 strcpy(fullshell, "/bin/");
414 strcat(fullshell, shellname);
415 shellname = fullshell;
416 #else
417 if((shellname = getenv("SHELL")) == 0)
418 shellname = "/bin/sh";
419 #endif /*-IMAGEN*/
421 if((shellname = getenv("SHELL")) == 0)
422 shellname = "/bin/sh";
423 execl(shellname, shellname, 0);
424 #endif /*-V6*/
425 writerr("No shell!");
426 exit(1);
427 break;
428 default:
429 while((res = wait(&status)) != pid && res != -1);
430 break;
432 #endif /*-TOPS20*/
434 signal(SIGINT, sav2); /* Restore signal settings */
435 signal(SIGQUIT, sav3);
436 set_tty(); /* Restore editor TTY modes */
437 redp(RD_SCREEN|RD_MODE); /* Done, redisplay */
440 /* Miscellaneous utility routines - memory alloc/free and string hacking.
441 * If this page becomes overly large, it can be split off into a separate
442 * file called E_MISC.
444 char *
445 strdup(s)
446 char *s; /* Note that STRCPY's return val must be its 1st arg */
447 { char *strcpy();
448 return(strcpy(memalloc((SBMO)(strlen(s)+1)), s));
451 char *
452 memalloc(size)
453 SBMO size;
454 { register SBMA ptr;
455 extern SBMA sbx_malloc();
457 if ((ptr = (SBMA)sbx_malloc(size)) != 0)
458 return((char *)ptr);
459 barf("ELLE: No memory left");
460 askerr();
461 return(0); /* If we dare to continue... */
464 chkfree (ptr)
465 SBMA ptr;
467 if(!free(ptr))
468 { errbarf("Something overwrote an allocated block!");
469 askerr();
474 /* USTRCMP - Uppercase String Compare.
475 * Returns 0 if mismatch,
476 * 1 if full match,
477 * -1 if str1 runs out first (partial match)
479 ustrcmp(str1,str2)
480 char *str1, *str2;
481 { register char *s1, *s2;
482 register int c;
483 s1 = str1; s2 = str2;
484 while(c = *s1++)
485 { if(c != *s2 && upcase(c) != upcase(*s2))
486 return(0);
487 s2++;
489 return(c == *s2 ? 1 : -1);
493 /* WRITERR(str) - Output string to standard error output.
494 ** This is a separate routine to save a little space on calls.
496 writerr(str)
497 char *str;
498 { return(writez(2, str));
501 /* WRITEZ(fd, str) - Miscellaneous general-purpose string output.
503 writez(fd,acp)
504 int fd;
505 char *acp;
506 { register char *cp;
507 cp = acp;
508 while(*cp++);
509 write(fd,acp,cp-acp-1);