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