136559Sbostic #ifndef lint 2*46181Storek static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 01/31/91"; 336559Sbostic #endif 436559Sbostic 536559Sbostic /* 636559Sbostic * adb - main command loop and error/interrupt handling 736559Sbostic */ 836559Sbostic 936559Sbostic #include "defs.h" 1036559Sbostic #include <setjmp.h> 1136559Sbostic #include <sys/file.h> 1236559Sbostic #include <sys/uio.h> 1337676Sbostic #include "pathnames.h" 1436559Sbostic 1536559Sbostic extern char NOEOR[]; /* "newline expected" */ 1636559Sbostic 1736559Sbostic /* 1836559Sbostic * executing is set by command.c whenever we are running a subprocess. 1936559Sbostic */ 2036559Sbostic int executing; 2136559Sbostic 2236559Sbostic int infile; /* XXX */ 2337676Sbostic char *Ipath = _PATH_SCRIPTS; /* XXX */ 2436559Sbostic 2536559Sbostic static int xargc; /* remembers argc for getfile() */ 2636559Sbostic 2736559Sbostic static int reading; /* set whenever reading input */ 2836559Sbostic static jmp_buf mainloop; /* label for error jumps */ 2936559Sbostic 3039153Sbostic void fault(); 3136559Sbostic off_t lseek(); 3236559Sbostic 33*46181Storek static int readline(); 34*46181Storek 3536559Sbostic main(argc, argv) 3636559Sbostic register int argc; 3736559Sbostic register char **argv; 3836559Sbostic { 3936559Sbostic int waserr; 4036559Sbostic char line[LINELEN]; 4136559Sbostic 4236559Sbostic radix = 16; /* default radix is hex */ 4336559Sbostic maxoff = MAXOFF; 4436559Sbostic maxcol = MAXCOL; 4536559Sbostic 4636559Sbostic /* 4736559Sbostic * Set up machine dependent code (e.g., instruction decoding tables), 4836559Sbostic * then look at arguments, and open the object and core files; 4936559Sbostic * finally, set up signal handlers. Alas, cannot really use getopt. 5036559Sbostic */ 5136559Sbostic mch_init(); 5236559Sbostic symfile.name = "a.out"; 5336559Sbostic corefile.name = "core"; 5436559Sbostic while (argc > 1 && argv[1][0] == '-') { 5536559Sbostic register char *p = argv[1] + 1; 5636559Sbostic 5736559Sbostic if (*p == 'w' && p[1] == 0) { 5836559Sbostic wtflag = 2; /* suitable for open() */ 5936559Sbostic argc--, argv++; 6036559Sbostic } else if (*p == 'k' && p[1] == 0) { 6136559Sbostic kernel = 1; 6236559Sbostic argc--, argv++; 6336559Sbostic } else if (*p == 'I') { 6436559Sbostic Ipath = argv[1] + 2; 6536559Sbostic argc--, argv++; 6636559Sbostic } else 6736559Sbostic break; 6836559Sbostic } 6936559Sbostic if (argc > 1) 7036559Sbostic symfile.name = argv[1]; 7136559Sbostic if (argc > 2) 7236559Sbostic corefile.name = argv[2]; 7336559Sbostic xargc = argc; /* remember for getfile() */ 7436559Sbostic setsym(); 7536559Sbostic setcore(); 7636559Sbostic if ((sigint = signal(SIGINT, SIG_IGN)) != SIG_IGN) { 7736559Sbostic intcatch = fault; 7836559Sbostic (void) signal(SIGINT, fault); 7936559Sbostic } 8036559Sbostic sigquit = signal(SIGQUIT, SIG_IGN); 8136559Sbostic 8236559Sbostic /* 8336559Sbostic * Errors jump back to the main loop here. 8436559Sbostic * If the error occurred while the process was running, 8536559Sbostic * we need to remove any breakpoints. 8636559Sbostic */ 87*46181Storek if (setjmp(mainloop)) 88*46181Storek waserr = 1; /* well, presumably */ 89*46181Storek else 90*46181Storek waserr = 0; 9136559Sbostic if (executing) { 9236559Sbostic executing = 0; 9336559Sbostic delbp(); 9436559Sbostic } 9536559Sbostic 9636559Sbostic /* 9736559Sbostic * Main loop: 9836559Sbostic * flush pending output, and print any error message(s); 9936559Sbostic * read a line; if end of file, close current input and 10036559Sbostic * continue, unless input == stdin; otherwise, perform 10136559Sbostic * the command(s) on the line and make sure that that 10236559Sbostic * consumed the whole line. 10336559Sbostic */ 10436559Sbostic for (;;) { 10536559Sbostic flushbuf(); 10636559Sbostic if (errflag) { 10736559Sbostic adbprintf("%s\n", errflag); 10836559Sbostic waserr = 1; 10936559Sbostic errflag = NULL; 11036559Sbostic } 11136559Sbostic if (mkfault) { 11236559Sbostic mkfault = 0; 11336559Sbostic prints("\nadb\n"); 11436559Sbostic } 11536559Sbostic if (readline(line, sizeof line)) { 11636559Sbostic if (infile == 0) 11736559Sbostic done(waserr); 11836559Sbostic iclose(-1, 0); 11936559Sbostic } else { 12036559Sbostic waserr = 0; 12136559Sbostic command(line, 0); 12236559Sbostic if (/* lp && */ lastc != '\n') 12336559Sbostic errflag = NOEOR; 12436559Sbostic } 12536559Sbostic } 12636559Sbostic } 12736559Sbostic 12836559Sbostic /* 12936559Sbostic * Exit with optional error status. 13036559Sbostic */ 13136559Sbostic done(err) 13236559Sbostic int err; 13336559Sbostic { 13436559Sbostic 13536559Sbostic endpcs(); 13636559Sbostic exit(err); 13736559Sbostic } 13836559Sbostic 13936559Sbostic /* 14036559Sbostic * Open the a.out (1) or core (2) file. If the name was given, 14136559Sbostic * rather than defaulted, and we were asked to open for writing, 14236559Sbostic * create the file if necessary. 14336559Sbostic */ 14436559Sbostic getfile(which) 14536559Sbostic int which; 14636559Sbostic { 14736559Sbostic char *fname; 14836559Sbostic int flags, fd; 14936577Storek char *strerror(); 15036559Sbostic 15136559Sbostic switch (which) { 15236559Sbostic case 1: 15336559Sbostic fname = symfile.name; 15436559Sbostic break; 15536559Sbostic case 2: 15636559Sbostic fname = corefile.name; 15736559Sbostic break; 15836559Sbostic default: 15936559Sbostic panic("getfile"); 16036559Sbostic /* NOTREACHED */ 16136559Sbostic } 16236559Sbostic if (fname[0] == '-' && fname[1] == 0) 16336559Sbostic return (-1); 16436559Sbostic if ((flags = wtflag) != 0 && xargc > which) 16536559Sbostic flags |= O_CREAT; 16636577Storek if ((fd = open(fname, flags, 0666)) < 0 && xargc > which) 16736577Storek adbprintf("cannot open `%s': %s\n", fname, strerror(errno)); 16836559Sbostic return (fd); 16936559Sbostic } 17036559Sbostic 17136559Sbostic 17236559Sbostic /* 17336559Sbostic * Input routines 17436559Sbostic */ 17536559Sbostic 17636559Sbostic /* 17736559Sbostic * Read a character, skipping white space. 17836559Sbostic */ 17936559Sbostic rdc() 18036559Sbostic { 18136559Sbostic 18236559Sbostic while (*lp == ' ' || *lp == '\t') 18336559Sbostic lp++; 18436559Sbostic return (readchar()); 18536559Sbostic } 18636559Sbostic 18736559Sbostic #ifndef readchar 18836559Sbostic /* 18936559Sbostic * Read a character, incrementing the pointer if not at end. 19036559Sbostic */ 19136559Sbostic readchar() 19236559Sbostic { 19336559Sbostic 19436559Sbostic if ((lastc = *lp) != 0) 19536559Sbostic lp++; 19636559Sbostic return (lastc); 19736559Sbostic } 19836559Sbostic #endif 19936559Sbostic 20036559Sbostic /* 20136559Sbostic * Read a line. Return -1 at end of file. 20236559Sbostic * Alas, cannot read more than one character at a time here (except 20336559Sbostic * possibly on tty devices; must think about that later). 20436559Sbostic */ 205*46181Storek static int 20636559Sbostic readline(p, n) 20736559Sbostic register char *p; 20836559Sbostic register int n; 20936559Sbostic { 21036559Sbostic 21136559Sbostic n--; /* for \0 */ 21236559Sbostic reading++; 21336559Sbostic do { 21436559Sbostic if (--n > 0) { 21536559Sbostic if (read(infile, p, 1) != 1) 21636559Sbostic return (-1); 21736559Sbostic } else 21836559Sbostic *p = '\n'; 21936559Sbostic } while (*p++ != '\n'); 22036559Sbostic reading = 0; 22136559Sbostic *p = 0; /* can we perhaps eliminate this? */ 22236559Sbostic return (0); 22336559Sbostic } 22436559Sbostic 22536559Sbostic /* 22636559Sbostic * Return the next non-white non-end-of-line character. 22736559Sbostic */ 22836559Sbostic nextchar() 22936559Sbostic { 23036559Sbostic int c = rdc(); 23136559Sbostic 23236559Sbostic if (eol(c)) { 23336559Sbostic unreadc(); 23436559Sbostic return (0); 23536559Sbostic } 23636559Sbostic return (c); 23736559Sbostic } 23836559Sbostic 23936559Sbostic 24036559Sbostic /* 24136559Sbostic * Error handlers 24236559Sbostic */ 24336559Sbostic 24436559Sbostic #ifndef checkerr 24536559Sbostic /* 24636559Sbostic * If there has been an error or a fault, take the error. 24736559Sbostic */ 24836559Sbostic checkerr() 24936559Sbostic { 25036559Sbostic 25136559Sbostic if (errflag || mkfault) 25236559Sbostic error(errflag); 25336559Sbostic } 25436559Sbostic #endif 25536559Sbostic 25636559Sbostic /* 25736559Sbostic * An error occurred. Save the message for later printing, 25836559Sbostic * close open files, and reset to main command loop. 25936559Sbostic */ 26036559Sbostic error(which) 26136559Sbostic char *which; 26236559Sbostic { 26336559Sbostic 26436559Sbostic errflag = which; 26536559Sbostic iclose(0, 1); 26636559Sbostic oclose(); 26736559Sbostic longjmp(mainloop, 1); 26836559Sbostic /* NOTREACHED */ 26936559Sbostic } 27036559Sbostic 27136559Sbostic /* 27236559Sbostic * An interrupt occurred. Seek to the end of the current input file. 27336559Sbostic * If we were reading commands, jump back to the main loop. 27436559Sbostic */ 27536559Sbostic /* ARGSUSED */ 27639153Sbostic void 27736559Sbostic fault(sig) 27836559Sbostic int sig; 27936559Sbostic { 28036559Sbostic /* (void) signal(sig, fault); */ /* unnecessary */ 28136559Sbostic (void) lseek(infile, 0L, 2); 28236559Sbostic mkfault++; 28336559Sbostic if (reading) { 28436559Sbostic reading = 0; 28536559Sbostic error((char *)NULL); 28636559Sbostic } 28736559Sbostic } 28836559Sbostic 28936559Sbostic /* 29036559Sbostic * Panic announces an internally detected error. 29136559Sbostic */ 29236559Sbostic panic(s) 29336559Sbostic char *s; 29436559Sbostic { 29536559Sbostic static char p[] = "panic: \n"; 29636559Sbostic static struct iovec iov[3] = { { p, 7 }, { 0 }, { p + 7, 1 } }; 29736559Sbostic 29836559Sbostic iov[1].iov_base = s; 29936559Sbostic iov[1].iov_len = strlen(s); 30036559Sbostic (void) writev(2, iov, 3); 30136559Sbostic abort(); /* beware, overwrites current core file! */ 30236559Sbostic /* exit(1); */ 30336559Sbostic } 304