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