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