1*36559Sbostic #ifndef lint 2*36559Sbostic static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 01/16/89"; 3*36559Sbostic #endif 4*36559Sbostic 5*36559Sbostic /* 6*36559Sbostic * adb - main command loop and error/interrupt handling 7*36559Sbostic */ 8*36559Sbostic 9*36559Sbostic #include "defs.h" 10*36559Sbostic #include <setjmp.h> 11*36559Sbostic #include <sys/file.h> 12*36559Sbostic #include <sys/uio.h> 13*36559Sbostic 14*36559Sbostic extern char NOEOR[]; /* "newline expected" */ 15*36559Sbostic 16*36559Sbostic /* 17*36559Sbostic * executing is set by command.c whenever we are running a subprocess. 18*36559Sbostic */ 19*36559Sbostic int executing; 20*36559Sbostic 21*36559Sbostic int infile; /* XXX */ 22*36559Sbostic char *Ipath = "/usr/lib/adb";/* XXX */ 23*36559Sbostic 24*36559Sbostic static int xargc; /* remembers argc for getfile() */ 25*36559Sbostic 26*36559Sbostic static int reading; /* set whenever reading input */ 27*36559Sbostic static jmp_buf mainloop; /* label for error jumps */ 28*36559Sbostic 29*36559Sbostic int fault(); 30*36559Sbostic off_t lseek(); 31*36559Sbostic 32*36559Sbostic main(argc, argv) 33*36559Sbostic register int argc; 34*36559Sbostic register char **argv; 35*36559Sbostic { 36*36559Sbostic int waserr; 37*36559Sbostic char line[LINELEN]; 38*36559Sbostic 39*36559Sbostic radix = 16; /* default radix is hex */ 40*36559Sbostic maxoff = MAXOFF; 41*36559Sbostic maxcol = MAXCOL; 42*36559Sbostic 43*36559Sbostic /* 44*36559Sbostic * Set up machine dependent code (e.g., instruction decoding tables), 45*36559Sbostic * then look at arguments, and open the object and core files; 46*36559Sbostic * finally, set up signal handlers. Alas, cannot really use getopt. 47*36559Sbostic */ 48*36559Sbostic mch_init(); 49*36559Sbostic symfile.name = "a.out"; 50*36559Sbostic corefile.name = "core"; 51*36559Sbostic while (argc > 1 && argv[1][0] == '-') { 52*36559Sbostic register char *p = argv[1] + 1; 53*36559Sbostic 54*36559Sbostic if (*p == 'w' && p[1] == 0) { 55*36559Sbostic wtflag = 2; /* suitable for open() */ 56*36559Sbostic argc--, argv++; 57*36559Sbostic } else if (*p == 'k' && p[1] == 0) { 58*36559Sbostic kernel = 1; 59*36559Sbostic argc--, argv++; 60*36559Sbostic } else if (*p == 'I') { 61*36559Sbostic Ipath = argv[1] + 2; 62*36559Sbostic argc--, argv++; 63*36559Sbostic } else 64*36559Sbostic break; 65*36559Sbostic } 66*36559Sbostic if (argc > 1) 67*36559Sbostic symfile.name = argv[1]; 68*36559Sbostic if (argc > 2) 69*36559Sbostic corefile.name = argv[2]; 70*36559Sbostic xargc = argc; /* remember for getfile() */ 71*36559Sbostic setsym(); 72*36559Sbostic setcore(); 73*36559Sbostic if ((sigint = signal(SIGINT, SIG_IGN)) != SIG_IGN) { 74*36559Sbostic intcatch = fault; 75*36559Sbostic (void) signal(SIGINT, fault); 76*36559Sbostic } 77*36559Sbostic sigquit = signal(SIGQUIT, SIG_IGN); 78*36559Sbostic 79*36559Sbostic /* 80*36559Sbostic * Errors jump back to the main loop here. 81*36559Sbostic * If the error occurred while the process was running, 82*36559Sbostic * we need to remove any breakpoints. 83*36559Sbostic */ 84*36559Sbostic (void) setjmp(mainloop); 85*36559Sbostic if (executing) { 86*36559Sbostic executing = 0; 87*36559Sbostic delbp(); 88*36559Sbostic } 89*36559Sbostic 90*36559Sbostic /* 91*36559Sbostic * Main loop: 92*36559Sbostic * flush pending output, and print any error message(s); 93*36559Sbostic * read a line; if end of file, close current input and 94*36559Sbostic * continue, unless input == stdin; otherwise, perform 95*36559Sbostic * the command(s) on the line and make sure that that 96*36559Sbostic * consumed the whole line. 97*36559Sbostic */ 98*36559Sbostic for (;;) { 99*36559Sbostic flushbuf(); 100*36559Sbostic if (errflag) { 101*36559Sbostic adbprintf("%s\n", errflag); 102*36559Sbostic waserr = 1; 103*36559Sbostic errflag = NULL; 104*36559Sbostic } 105*36559Sbostic if (mkfault) { 106*36559Sbostic mkfault = 0; 107*36559Sbostic prints("\nadb\n"); 108*36559Sbostic } 109*36559Sbostic if (readline(line, sizeof line)) { 110*36559Sbostic if (infile == 0) 111*36559Sbostic done(waserr); 112*36559Sbostic iclose(-1, 0); 113*36559Sbostic } else { 114*36559Sbostic waserr = 0; 115*36559Sbostic command(line, 0); 116*36559Sbostic if (/* lp && */ lastc != '\n') 117*36559Sbostic errflag = NOEOR; 118*36559Sbostic } 119*36559Sbostic } 120*36559Sbostic } 121*36559Sbostic 122*36559Sbostic /* 123*36559Sbostic * Exit with optional error status. 124*36559Sbostic */ 125*36559Sbostic done(err) 126*36559Sbostic int err; 127*36559Sbostic { 128*36559Sbostic 129*36559Sbostic endpcs(); 130*36559Sbostic exit(err); 131*36559Sbostic } 132*36559Sbostic 133*36559Sbostic /* 134*36559Sbostic * Open the a.out (1) or core (2) file. If the name was given, 135*36559Sbostic * rather than defaulted, and we were asked to open for writing, 136*36559Sbostic * create the file if necessary. 137*36559Sbostic */ 138*36559Sbostic getfile(which) 139*36559Sbostic int which; 140*36559Sbostic { 141*36559Sbostic char *fname; 142*36559Sbostic int flags, fd; 143*36559Sbostic 144*36559Sbostic switch (which) { 145*36559Sbostic case 1: 146*36559Sbostic fname = symfile.name; 147*36559Sbostic break; 148*36559Sbostic case 2: 149*36559Sbostic fname = corefile.name; 150*36559Sbostic break; 151*36559Sbostic default: 152*36559Sbostic panic("getfile"); 153*36559Sbostic /* NOTREACHED */ 154*36559Sbostic } 155*36559Sbostic if (fname[0] == '-' && fname[1] == 0) 156*36559Sbostic return (-1); 157*36559Sbostic if ((flags = wtflag) != 0 && xargc > which) 158*36559Sbostic flags |= O_CREAT; 159*36559Sbostic if ((fd = open(fname, flags, 0666)) < 0 && flags & O_CREAT) 160*36559Sbostic adbprintf("cannot open `%s'\n", fname); 161*36559Sbostic return (fd); 162*36559Sbostic } 163*36559Sbostic 164*36559Sbostic 165*36559Sbostic /* 166*36559Sbostic * Input routines 167*36559Sbostic */ 168*36559Sbostic 169*36559Sbostic /* 170*36559Sbostic * Read a character, skipping white space. 171*36559Sbostic */ 172*36559Sbostic rdc() 173*36559Sbostic { 174*36559Sbostic 175*36559Sbostic while (*lp == ' ' || *lp == '\t') 176*36559Sbostic lp++; 177*36559Sbostic return (readchar()); 178*36559Sbostic } 179*36559Sbostic 180*36559Sbostic #ifndef readchar 181*36559Sbostic /* 182*36559Sbostic * Read a character, incrementing the pointer if not at end. 183*36559Sbostic */ 184*36559Sbostic readchar() 185*36559Sbostic { 186*36559Sbostic 187*36559Sbostic if ((lastc = *lp) != 0) 188*36559Sbostic lp++; 189*36559Sbostic return (lastc); 190*36559Sbostic } 191*36559Sbostic #endif 192*36559Sbostic 193*36559Sbostic /* 194*36559Sbostic * Read a line. Return -1 at end of file. 195*36559Sbostic * Alas, cannot read more than one character at a time here (except 196*36559Sbostic * possibly on tty devices; must think about that later). 197*36559Sbostic */ 198*36559Sbostic static 199*36559Sbostic readline(p, n) 200*36559Sbostic register char *p; 201*36559Sbostic register int n; 202*36559Sbostic { 203*36559Sbostic 204*36559Sbostic n--; /* for \0 */ 205*36559Sbostic reading++; 206*36559Sbostic do { 207*36559Sbostic if (--n > 0) { 208*36559Sbostic if (read(infile, p, 1) != 1) 209*36559Sbostic return (-1); 210*36559Sbostic } else 211*36559Sbostic *p = '\n'; 212*36559Sbostic } while (*p++ != '\n'); 213*36559Sbostic reading = 0; 214*36559Sbostic *p = 0; /* can we perhaps eliminate this? */ 215*36559Sbostic return (0); 216*36559Sbostic } 217*36559Sbostic 218*36559Sbostic /* 219*36559Sbostic * Return the next non-white non-end-of-line character. 220*36559Sbostic */ 221*36559Sbostic nextchar() 222*36559Sbostic { 223*36559Sbostic int c = rdc(); 224*36559Sbostic 225*36559Sbostic if (eol(c)) { 226*36559Sbostic unreadc(); 227*36559Sbostic return (0); 228*36559Sbostic } 229*36559Sbostic return (c); 230*36559Sbostic } 231*36559Sbostic 232*36559Sbostic 233*36559Sbostic /* 234*36559Sbostic * Error handlers 235*36559Sbostic */ 236*36559Sbostic 237*36559Sbostic #ifndef checkerr 238*36559Sbostic /* 239*36559Sbostic * If there has been an error or a fault, take the error. 240*36559Sbostic */ 241*36559Sbostic checkerr() 242*36559Sbostic { 243*36559Sbostic 244*36559Sbostic if (errflag || mkfault) 245*36559Sbostic error(errflag); 246*36559Sbostic } 247*36559Sbostic #endif 248*36559Sbostic 249*36559Sbostic /* 250*36559Sbostic * An error occurred. Save the message for later printing, 251*36559Sbostic * close open files, and reset to main command loop. 252*36559Sbostic */ 253*36559Sbostic error(which) 254*36559Sbostic char *which; 255*36559Sbostic { 256*36559Sbostic 257*36559Sbostic errflag = which; 258*36559Sbostic iclose(0, 1); 259*36559Sbostic oclose(); 260*36559Sbostic longjmp(mainloop, 1); 261*36559Sbostic /* NOTREACHED */ 262*36559Sbostic } 263*36559Sbostic 264*36559Sbostic /* 265*36559Sbostic * An interrupt occurred. Seek to the end of the current input file. 266*36559Sbostic * If we were reading commands, jump back to the main loop. 267*36559Sbostic */ 268*36559Sbostic /* ARGSUSED */ 269*36559Sbostic fault(sig) 270*36559Sbostic int sig; 271*36559Sbostic { 272*36559Sbostic 273*36559Sbostic /* (void) signal(sig, fault); */ /* unnecessary */ 274*36559Sbostic (void) lseek(infile, 0L, 2); 275*36559Sbostic mkfault++; 276*36559Sbostic if (reading) { 277*36559Sbostic reading = 0; 278*36559Sbostic error((char *)NULL); 279*36559Sbostic } 280*36559Sbostic } 281*36559Sbostic 282*36559Sbostic /* 283*36559Sbostic * Panic announces an internally detected error. 284*36559Sbostic */ 285*36559Sbostic panic(s) 286*36559Sbostic char *s; 287*36559Sbostic { 288*36559Sbostic static char p[] = "panic: \n"; 289*36559Sbostic static struct iovec iov[3] = { { p, 7 }, { 0 }, { p + 7, 1 } }; 290*36559Sbostic 291*36559Sbostic iov[1].iov_base = s; 292*36559Sbostic iov[1].iov_len = strlen(s); 293*36559Sbostic (void) writev(2, iov, 3); 294*36559Sbostic abort(); /* beware, overwrites current core file! */ 295*36559Sbostic /* exit(1); */ 296*36559Sbostic } 297