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