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