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