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