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