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