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
main(argc,argv)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 */
done(err)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 */
getfile(which)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 */
rdc()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 */
readchar()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
readline(p,n)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 */
nextchar()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 */
checkerr()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 */
error(which)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
fault(sig)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 */
panic(s)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