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