xref: /csrg-svn/old/adb/common_source/main.c (revision 36559)
1 #ifndef lint
2 static char sccsid[] = "@(#)main.c	5.1 (Berkeley) 01/16/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 
144 	switch (which) {
145 	case 1:
146 		fname = symfile.name;
147 		break;
148 	case 2:
149 		fname = corefile.name;
150 		break;
151 	default:
152 		panic("getfile");
153 		/* NOTREACHED */
154 	}
155 	if (fname[0] == '-' && fname[1] == 0)
156 		return (-1);
157 	if ((flags = wtflag) != 0 && xargc > which)
158 		flags |= O_CREAT;
159 	if ((fd = open(fname, flags, 0666)) < 0 && flags & O_CREAT)
160 		adbprintf("cannot open `%s'\n", fname);
161 	return (fd);
162 }
163 
164 
165 /*
166  * Input routines
167  */
168 
169 /*
170  * Read a character, skipping white space.
171  */
172 rdc()
173 {
174 
175 	while (*lp == ' ' || *lp == '\t')
176 		lp++;
177 	return (readchar());
178 }
179 
180 #ifndef readchar
181 /*
182  * Read a character, incrementing the pointer if not at end.
183  */
184 readchar()
185 {
186 
187 	if ((lastc = *lp) != 0)
188 		lp++;
189 	return (lastc);
190 }
191 #endif
192 
193 /*
194  * Read a line.  Return -1 at end of file.
195  * Alas, cannot read more than one character at a time here (except
196  * possibly on tty devices; must think about that later).
197  */
198 static
199 readline(p, n)
200 	register char *p;
201 	register int n;
202 {
203 
204 	n--;		/* for \0 */
205 	reading++;
206 	do {
207 		if (--n > 0) {
208 			if (read(infile, p, 1) != 1)
209 				return (-1);
210 		} else
211 			*p = '\n';
212 	} while (*p++ != '\n');
213 	reading = 0;
214 	*p = 0;		/* can we perhaps eliminate this? */
215 	return (0);
216 }
217 
218 /*
219  * Return the next non-white non-end-of-line character.
220  */
221 nextchar()
222 {
223 	int c = rdc();
224 
225 	if (eol(c)) {
226 		unreadc();
227 		return (0);
228 	}
229 	return (c);
230 }
231 
232 
233 /*
234  * Error handlers
235  */
236 
237 #ifndef checkerr
238 /*
239  * If there has been an error or a fault, take the error.
240  */
241 checkerr()
242 {
243 
244 	if (errflag || mkfault)
245 		error(errflag);
246 }
247 #endif
248 
249 /*
250  * An error occurred.  Save the message for later printing,
251  * close open files, and reset to main command loop.
252  */
253 error(which)
254 	char *which;
255 {
256 
257 	errflag = which;
258 	iclose(0, 1);
259 	oclose();
260 	longjmp(mainloop, 1);
261 	/* NOTREACHED */
262 }
263 
264 /*
265  * An interrupt occurred.  Seek to the end of the current input file.
266  * If we were reading commands, jump back to the main loop.
267  */
268 /* ARGSUSED */
269 fault(sig)
270 	int sig;
271 {
272 
273 	/* (void) signal(sig, fault); */	/* unnecessary */
274 	(void) lseek(infile, 0L, 2);
275 	mkfault++;
276 	if (reading) {
277 		reading = 0;
278 		error((char *)NULL);
279 	}
280 }
281 
282 /*
283  * Panic announces an internally detected error.
284  */
285 panic(s)
286 	char *s;
287 {
288 	static char p[] = "panic: \n";
289 	static struct iovec iov[3] = { { p, 7 }, { 0 }, { p + 7, 1 } };
290 
291 	iov[1].iov_base = s;
292 	iov[1].iov_len = strlen(s);
293 	(void) writev(2, iov, 3);
294 	abort();	/* beware, overwrites current core file! */
295 /*	exit(1); */
296 }
297