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