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