xref: /csrg-svn/old/adb/common_source/main.c (revision 36577)
136559Sbostic #ifndef lint
2*36577Storek static char sccsid[] = "@(#)main.c	5.2 (Berkeley) 01/17/89";
336559Sbostic #endif
436559Sbostic 
536559Sbostic /*
636559Sbostic  * adb - main command loop and error/interrupt handling
736559Sbostic  */
836559Sbostic 
936559Sbostic #include "defs.h"
1036559Sbostic #include <setjmp.h>
1136559Sbostic #include <sys/file.h>
1236559Sbostic #include <sys/uio.h>
1336559Sbostic 
1436559Sbostic extern char NOEOR[];		/* "newline expected" */
1536559Sbostic 
1636559Sbostic /*
1736559Sbostic  * executing is set by command.c whenever we are running a subprocess.
1836559Sbostic  */
1936559Sbostic int	executing;
2036559Sbostic 
2136559Sbostic int	infile;			/* XXX */
2236559Sbostic char	*Ipath = "/usr/lib/adb";/* XXX */
2336559Sbostic 
2436559Sbostic static int xargc;		/* remembers argc for getfile() */
2536559Sbostic 
2636559Sbostic static int reading;		/* set whenever reading input */
2736559Sbostic static jmp_buf mainloop;	/* label for error jumps */
2836559Sbostic 
2936559Sbostic int	fault();
3036559Sbostic off_t	lseek();
3136559Sbostic 
3236559Sbostic main(argc, argv)
3336559Sbostic 	register int argc;
3436559Sbostic 	register char **argv;
3536559Sbostic {
3636559Sbostic 	int waserr;
3736559Sbostic 	char line[LINELEN];
3836559Sbostic 
3936559Sbostic 	radix = 16;		/* default radix is hex */
4036559Sbostic 	maxoff = MAXOFF;
4136559Sbostic 	maxcol = MAXCOL;
4236559Sbostic 
4336559Sbostic 	/*
4436559Sbostic 	 * Set up machine dependent code (e.g., instruction decoding tables),
4536559Sbostic 	 * then look at arguments, and open the object and core files;
4636559Sbostic 	 * finally, set up signal handlers.  Alas, cannot really use getopt.
4736559Sbostic 	 */
4836559Sbostic 	mch_init();
4936559Sbostic 	symfile.name = "a.out";
5036559Sbostic 	corefile.name = "core";
5136559Sbostic 	while (argc > 1 && argv[1][0] == '-') {
5236559Sbostic 		register char *p = argv[1] + 1;
5336559Sbostic 
5436559Sbostic 		if (*p == 'w' && p[1] == 0) {
5536559Sbostic 			wtflag = 2;	/* suitable for open() */
5636559Sbostic 			argc--, argv++;
5736559Sbostic 		} else if (*p == 'k' && p[1] == 0) {
5836559Sbostic 			kernel = 1;
5936559Sbostic 			argc--, argv++;
6036559Sbostic 		} else if (*p == 'I') {
6136559Sbostic 			Ipath = argv[1] + 2;
6236559Sbostic 			argc--, argv++;
6336559Sbostic 		} else
6436559Sbostic 			break;
6536559Sbostic 	}
6636559Sbostic 	if (argc > 1)
6736559Sbostic 		symfile.name = argv[1];
6836559Sbostic 	if (argc > 2)
6936559Sbostic 		corefile.name = argv[2];
7036559Sbostic 	xargc = argc;		/* remember for getfile() */
7136559Sbostic 	setsym();
7236559Sbostic 	setcore();
7336559Sbostic 	if ((sigint = signal(SIGINT, SIG_IGN)) != SIG_IGN) {
7436559Sbostic 		intcatch = fault;
7536559Sbostic 		(void) signal(SIGINT, fault);
7636559Sbostic 	}
7736559Sbostic 	sigquit = signal(SIGQUIT, SIG_IGN);
7836559Sbostic 
7936559Sbostic 	/*
8036559Sbostic 	 * Errors jump back to the main loop here.
8136559Sbostic 	 * If the error occurred while the process was running,
8236559Sbostic 	 * we need to remove any breakpoints.
8336559Sbostic 	 */
8436559Sbostic 	(void) setjmp(mainloop);
8536559Sbostic 	if (executing) {
8636559Sbostic 		executing = 0;
8736559Sbostic 		delbp();
8836559Sbostic 	}
8936559Sbostic 
9036559Sbostic 	/*
9136559Sbostic 	 * Main loop:
9236559Sbostic 	 *	flush pending output, and print any error message(s);
9336559Sbostic 	 *	read a line; if end of file, close current input and
9436559Sbostic 	 *	continue, unless input == stdin; otherwise, perform
9536559Sbostic 	 *	the command(s) on the line and make sure that that
9636559Sbostic 	 *	consumed the whole line.
9736559Sbostic 	 */
9836559Sbostic 	for (;;) {
9936559Sbostic 		flushbuf();
10036559Sbostic 		if (errflag) {
10136559Sbostic 			adbprintf("%s\n", errflag);
10236559Sbostic 			waserr = 1;
10336559Sbostic 			errflag = NULL;
10436559Sbostic 		}
10536559Sbostic 		if (mkfault) {
10636559Sbostic 			mkfault = 0;
10736559Sbostic 			prints("\nadb\n");
10836559Sbostic 		}
10936559Sbostic 		if (readline(line, sizeof line)) {
11036559Sbostic 			if (infile == 0)
11136559Sbostic 				done(waserr);
11236559Sbostic 			iclose(-1, 0);
11336559Sbostic 		} else {
11436559Sbostic 			waserr = 0;
11536559Sbostic 			command(line, 0);
11636559Sbostic 			if (/* lp && */ lastc != '\n')
11736559Sbostic 				errflag = NOEOR;
11836559Sbostic 		}
11936559Sbostic 	}
12036559Sbostic }
12136559Sbostic 
12236559Sbostic /*
12336559Sbostic  * Exit with optional error status.
12436559Sbostic  */
12536559Sbostic done(err)
12636559Sbostic 	int err;
12736559Sbostic {
12836559Sbostic 
12936559Sbostic 	endpcs();
13036559Sbostic 	exit(err);
13136559Sbostic }
13236559Sbostic 
13336559Sbostic /*
13436559Sbostic  * Open the a.out (1) or core (2) file.  If the name was given,
13536559Sbostic  * rather than defaulted, and we were asked to open for writing,
13636559Sbostic  * create the file if necessary.
13736559Sbostic  */
13836559Sbostic getfile(which)
13936559Sbostic 	int which;
14036559Sbostic {
14136559Sbostic 	char *fname;
14236559Sbostic 	int flags, fd;
143*36577Storek 	char *strerror();
14436559Sbostic 
14536559Sbostic 	switch (which) {
14636559Sbostic 	case 1:
14736559Sbostic 		fname = symfile.name;
14836559Sbostic 		break;
14936559Sbostic 	case 2:
15036559Sbostic 		fname = corefile.name;
15136559Sbostic 		break;
15236559Sbostic 	default:
15336559Sbostic 		panic("getfile");
15436559Sbostic 		/* NOTREACHED */
15536559Sbostic 	}
15636559Sbostic 	if (fname[0] == '-' && fname[1] == 0)
15736559Sbostic 		return (-1);
15836559Sbostic 	if ((flags = wtflag) != 0 && xargc > which)
15936559Sbostic 		flags |= O_CREAT;
160*36577Storek 	if ((fd = open(fname, flags, 0666)) < 0 && xargc > which)
161*36577Storek 		adbprintf("cannot open `%s': %s\n", fname, strerror(errno));
16236559Sbostic 	return (fd);
16336559Sbostic }
16436559Sbostic 
16536559Sbostic 
16636559Sbostic /*
16736559Sbostic  * Input routines
16836559Sbostic  */
16936559Sbostic 
17036559Sbostic /*
17136559Sbostic  * Read a character, skipping white space.
17236559Sbostic  */
17336559Sbostic rdc()
17436559Sbostic {
17536559Sbostic 
17636559Sbostic 	while (*lp == ' ' || *lp == '\t')
17736559Sbostic 		lp++;
17836559Sbostic 	return (readchar());
17936559Sbostic }
18036559Sbostic 
18136559Sbostic #ifndef readchar
18236559Sbostic /*
18336559Sbostic  * Read a character, incrementing the pointer if not at end.
18436559Sbostic  */
18536559Sbostic readchar()
18636559Sbostic {
18736559Sbostic 
18836559Sbostic 	if ((lastc = *lp) != 0)
18936559Sbostic 		lp++;
19036559Sbostic 	return (lastc);
19136559Sbostic }
19236559Sbostic #endif
19336559Sbostic 
19436559Sbostic /*
19536559Sbostic  * Read a line.  Return -1 at end of file.
19636559Sbostic  * Alas, cannot read more than one character at a time here (except
19736559Sbostic  * possibly on tty devices; must think about that later).
19836559Sbostic  */
19936559Sbostic static
20036559Sbostic readline(p, n)
20136559Sbostic 	register char *p;
20236559Sbostic 	register int n;
20336559Sbostic {
20436559Sbostic 
20536559Sbostic 	n--;		/* for \0 */
20636559Sbostic 	reading++;
20736559Sbostic 	do {
20836559Sbostic 		if (--n > 0) {
20936559Sbostic 			if (read(infile, p, 1) != 1)
21036559Sbostic 				return (-1);
21136559Sbostic 		} else
21236559Sbostic 			*p = '\n';
21336559Sbostic 	} while (*p++ != '\n');
21436559Sbostic 	reading = 0;
21536559Sbostic 	*p = 0;		/* can we perhaps eliminate this? */
21636559Sbostic 	return (0);
21736559Sbostic }
21836559Sbostic 
21936559Sbostic /*
22036559Sbostic  * Return the next non-white non-end-of-line character.
22136559Sbostic  */
22236559Sbostic nextchar()
22336559Sbostic {
22436559Sbostic 	int c = rdc();
22536559Sbostic 
22636559Sbostic 	if (eol(c)) {
22736559Sbostic 		unreadc();
22836559Sbostic 		return (0);
22936559Sbostic 	}
23036559Sbostic 	return (c);
23136559Sbostic }
23236559Sbostic 
23336559Sbostic 
23436559Sbostic /*
23536559Sbostic  * Error handlers
23636559Sbostic  */
23736559Sbostic 
23836559Sbostic #ifndef checkerr
23936559Sbostic /*
24036559Sbostic  * If there has been an error or a fault, take the error.
24136559Sbostic  */
24236559Sbostic checkerr()
24336559Sbostic {
24436559Sbostic 
24536559Sbostic 	if (errflag || mkfault)
24636559Sbostic 		error(errflag);
24736559Sbostic }
24836559Sbostic #endif
24936559Sbostic 
25036559Sbostic /*
25136559Sbostic  * An error occurred.  Save the message for later printing,
25236559Sbostic  * close open files, and reset to main command loop.
25336559Sbostic  */
25436559Sbostic error(which)
25536559Sbostic 	char *which;
25636559Sbostic {
25736559Sbostic 
25836559Sbostic 	errflag = which;
25936559Sbostic 	iclose(0, 1);
26036559Sbostic 	oclose();
26136559Sbostic 	longjmp(mainloop, 1);
26236559Sbostic 	/* NOTREACHED */
26336559Sbostic }
26436559Sbostic 
26536559Sbostic /*
26636559Sbostic  * An interrupt occurred.  Seek to the end of the current input file.
26736559Sbostic  * If we were reading commands, jump back to the main loop.
26836559Sbostic  */
26936559Sbostic /* ARGSUSED */
27036559Sbostic fault(sig)
27136559Sbostic 	int sig;
27236559Sbostic {
27336559Sbostic 
27436559Sbostic 	/* (void) signal(sig, fault); */	/* unnecessary */
27536559Sbostic 	(void) lseek(infile, 0L, 2);
27636559Sbostic 	mkfault++;
27736559Sbostic 	if (reading) {
27836559Sbostic 		reading = 0;
27936559Sbostic 		error((char *)NULL);
28036559Sbostic 	}
28136559Sbostic }
28236559Sbostic 
28336559Sbostic /*
28436559Sbostic  * Panic announces an internally detected error.
28536559Sbostic  */
28636559Sbostic panic(s)
28736559Sbostic 	char *s;
28836559Sbostic {
28936559Sbostic 	static char p[] = "panic: \n";
29036559Sbostic 	static struct iovec iov[3] = { { p, 7 }, { 0 }, { p + 7, 1 } };
29136559Sbostic 
29236559Sbostic 	iov[1].iov_base = s;
29336559Sbostic 	iov[1].iov_len = strlen(s);
29436559Sbostic 	(void) writev(2, iov, 3);
29536559Sbostic 	abort();	/* beware, overwrites current core file! */
29636559Sbostic /*	exit(1); */
29736559Sbostic }
298