xref: /csrg-svn/old/dbx/library.c (revision 9666)
1*9666Slinton /* Copyright (c) 1982 Regents of the University of California */
2*9666Slinton 
3*9666Slinton /* static char sccsid[] = "@(#)library.c 1.1 9/2/82"; */
4*9666Slinton 
5*9666Slinton /*
6*9666Slinton  * General purpose routines.
7*9666Slinton  */
8*9666Slinton 
9*9666Slinton #include <stdio.h>
10*9666Slinton #include <errno.h>
11*9666Slinton #include <signal.h>
12*9666Slinton 
13*9666Slinton #define public
14*9666Slinton #define private static
15*9666Slinton #define and &&
16*9666Slinton #define or ||
17*9666Slinton #define not !
18*9666Slinton #define ord(enumcon)	((int) enumcon)
19*9666Slinton #define nil(type)	((type) 0)
20*9666Slinton 
21*9666Slinton typedef enum { FALSE, TRUE } Boolean;
22*9666Slinton typedef char *String;
23*9666Slinton typedef FILE *File;
24*9666Slinton typedef String Filename;
25*9666Slinton 
26*9666Slinton #undef FILE
27*9666Slinton 
28*9666Slinton /*
29*9666Slinton  * Definitions of standard C library routines that aren't in the
30*9666Slinton  * standard I/O library, but which are generally useful.
31*9666Slinton  */
32*9666Slinton 
33*9666Slinton extern long atol();		/* ascii to long */
34*9666Slinton extern double atof();		/* ascii to floating point */
35*9666Slinton extern char *mktemp();		/* make a temporary file name */
36*9666Slinton 
37*9666Slinton String cmdname;			/* name of command for error messages */
38*9666Slinton Filename errfilename;		/* current file associated with error */
39*9666Slinton short errlineno;		/* line number associated with error */
40*9666Slinton 
41*9666Slinton /*
42*9666Slinton  * Definitions for doing memory allocation.
43*9666Slinton  */
44*9666Slinton 
45*9666Slinton extern char *malloc();
46*9666Slinton 
47*9666Slinton #define alloc(n, type)	((type *) malloc((unsigned) (n) * sizeof(type)))
48*9666Slinton #define dispose(p)	{ free((char *) p); p = 0; }
49*9666Slinton 
50*9666Slinton /*
51*9666Slinton  * Macros for doing freads + fwrites.
52*9666Slinton  */
53*9666Slinton 
54*9666Slinton #define get(fp, var)	fread((char *) &(var), sizeof(var), 1, fp)
55*9666Slinton #define put(fp, var)	fwrite((char *) &(var), sizeof(var), 1, fp)
56*9666Slinton 
57*9666Slinton /*
58*9666Slinton  * String definitions.
59*9666Slinton  */
60*9666Slinton 
61*9666Slinton extern String strcpy(), index(), rindex();
62*9666Slinton extern int strlen();
63*9666Slinton 
64*9666Slinton #define strdup(s)		strcpy(malloc((unsigned) strlen(s) + 1), s)
65*9666Slinton #define streq(s1, s2)	(strcmp(s1, s2) == 0)
66*9666Slinton 
67*9666Slinton typedef int INTFUNC();
68*9666Slinton 
69*9666Slinton typedef struct {
70*9666Slinton     INTFUNC *func;
71*9666Slinton } ERRINFO;
72*9666Slinton 
73*9666Slinton #define ERR_IGNORE ((INTFUNC *) 0)
74*9666Slinton #define ERR_CATCH  ((INTFUNC *) 1)
75*9666Slinton 
76*9666Slinton /*
77*9666Slinton  * Call a program.
78*9666Slinton  *
79*9666Slinton  * Four entries:
80*9666Slinton  *
81*9666Slinton  *	call, callv - call a program and wait for it, returning status
82*9666Slinton  *	back, backv - call a program and don't wait, returning process id
83*9666Slinton  *
84*9666Slinton  * The command's standard input and output are passed as FILE's.
85*9666Slinton  */
86*9666Slinton 
87*9666Slinton 
88*9666Slinton #define MAXNARGS 100    /* unchecked upper limit on max num of arguments */
89*9666Slinton #define BADEXEC 127	/* exec fails */
90*9666Slinton 
91*9666Slinton #define ischild(pid)    ((pid) == 0)
92*9666Slinton 
93*9666Slinton /* VARARGS3 */
94*9666Slinton public int call(name, in, out, args)
95*9666Slinton String name;
96*9666Slinton File in;
97*9666Slinton File out;
98*9666Slinton String args;
99*9666Slinton {
100*9666Slinton     String *ap, *argp;
101*9666Slinton     String argv[MAXNARGS];
102*9666Slinton 
103*9666Slinton     argp = &argv[0];
104*9666Slinton     *argp++ = name;
105*9666Slinton     ap = &args;
106*9666Slinton     while (*ap != nil(String)) {
107*9666Slinton 	*argp++ = *ap++;
108*9666Slinton     }
109*9666Slinton     *argp = nil(String);
110*9666Slinton     return callv(name, in, out, argv);
111*9666Slinton }
112*9666Slinton 
113*9666Slinton /* VARARGS3 */
114*9666Slinton public int back(name, in, out, args)
115*9666Slinton String name;
116*9666Slinton File in;
117*9666Slinton File out;
118*9666Slinton String args;
119*9666Slinton {
120*9666Slinton     String *ap, *argp;
121*9666Slinton     String argv[MAXNARGS];
122*9666Slinton 
123*9666Slinton     argp = &argv[0];
124*9666Slinton     *argp++ = name;
125*9666Slinton     ap = &args;
126*9666Slinton     while (*ap != nil(String)) {
127*9666Slinton 	*argp++ = *ap++;
128*9666Slinton     }
129*9666Slinton     *argp = nil(String);
130*9666Slinton     return backv(name, in, out, argv);
131*9666Slinton }
132*9666Slinton 
133*9666Slinton public int callv(name, in, out, argv)
134*9666Slinton String name;
135*9666Slinton File in;
136*9666Slinton File out;
137*9666Slinton String *argv;
138*9666Slinton {
139*9666Slinton     int pid, status;
140*9666Slinton 
141*9666Slinton     pid = backv(name, in, out, argv);
142*9666Slinton     pwait(pid, &status);
143*9666Slinton     return status;
144*9666Slinton }
145*9666Slinton 
146*9666Slinton public int backv(name, in, out, argv)
147*9666Slinton String name;
148*9666Slinton File in;
149*9666Slinton File out;
150*9666Slinton String *argv;
151*9666Slinton {
152*9666Slinton     int pid;
153*9666Slinton 
154*9666Slinton     fflush(stdout);
155*9666Slinton     if (ischild(pid = fork())) {
156*9666Slinton 	fswap(0, fileno(in));
157*9666Slinton 	fswap(1, fileno(out));
158*9666Slinton 	onsyserr(EACCES, ERR_IGNORE);
159*9666Slinton 	execvp(name, argv);
160*9666Slinton 	_exit(BADEXEC);
161*9666Slinton     }
162*9666Slinton     return pid;
163*9666Slinton }
164*9666Slinton 
165*9666Slinton /*
166*9666Slinton  * Swap file numbers so as to redirect standard input and output.
167*9666Slinton  */
168*9666Slinton 
169*9666Slinton private fswap(oldfd, newfd)
170*9666Slinton int oldfd;
171*9666Slinton int newfd;
172*9666Slinton {
173*9666Slinton     if (oldfd != newfd) {
174*9666Slinton 	close(oldfd);
175*9666Slinton 	dup(newfd);
176*9666Slinton 	close(newfd);
177*9666Slinton     }
178*9666Slinton }
179*9666Slinton 
180*9666Slinton /*
181*9666Slinton  * Invoke a shell on a command line.
182*9666Slinton  */
183*9666Slinton 
184*9666Slinton #define DEF_SHELL	"csh"
185*9666Slinton 
186*9666Slinton public shell(s)
187*9666Slinton String s;
188*9666Slinton {
189*9666Slinton     extern String getenv();
190*9666Slinton     String sh;
191*9666Slinton 
192*9666Slinton     if ((sh = getenv("SHELL")) == nil(String)) {
193*9666Slinton 	sh = DEF_SHELL;
194*9666Slinton     }
195*9666Slinton     if (s != nil(String) and *s != '\0') {
196*9666Slinton 	call(sh, stdin, stdout, "-c", s, 0);
197*9666Slinton     } else {
198*9666Slinton 	call(sh, stdin, stdout, 0);
199*9666Slinton     }
200*9666Slinton }
201*9666Slinton 
202*9666Slinton /*
203*9666Slinton  * Wait for a process the right way.  We wait for a particular
204*9666Slinton  * process and if any others come along in between, we remember them
205*9666Slinton  * in case they are eventually waited for.
206*9666Slinton  *
207*9666Slinton  * This routine is not very efficient when the number of processes
208*9666Slinton  * to be remembered is large.
209*9666Slinton  */
210*9666Slinton 
211*9666Slinton typedef struct pidlist {
212*9666Slinton     int pid;
213*9666Slinton     int status;
214*9666Slinton     struct pidlist *next;
215*9666Slinton } Pidlist;
216*9666Slinton 
217*9666Slinton private Pidlist *pidlist, *pfind();
218*9666Slinton 
219*9666Slinton public pwait(pid, statusp)
220*9666Slinton int pid, *statusp;
221*9666Slinton {
222*9666Slinton 	Pidlist *p;
223*9666Slinton 	int pnum, status;
224*9666Slinton 
225*9666Slinton 	p = pfind(pid);
226*9666Slinton 	if (p != nil(Pidlist *)) {
227*9666Slinton 	    *statusp = p->status;
228*9666Slinton 	    dispose(p);
229*9666Slinton 	    return;
230*9666Slinton 	}
231*9666Slinton 	while ((pnum = wait(&status)) != pid && pnum >= 0) {
232*9666Slinton 	    p = alloc(1, Pidlist);
233*9666Slinton 	    p->pid = pnum;
234*9666Slinton 	    p->status = status;
235*9666Slinton 	    p->next = pidlist;
236*9666Slinton 	    pidlist = p;
237*9666Slinton 	}
238*9666Slinton 	if (pnum < 0) {
239*9666Slinton 	    p = pfind(pid);
240*9666Slinton 	    if (p == nil(Pidlist *)) {
241*9666Slinton 		panic("pwait: pid %d not found", pid);
242*9666Slinton 	    }
243*9666Slinton 	    *statusp = p->status;
244*9666Slinton 	    dispose(p);
245*9666Slinton 	} else {
246*9666Slinton 		*statusp = status;
247*9666Slinton 	}
248*9666Slinton }
249*9666Slinton 
250*9666Slinton /*
251*9666Slinton  * Look for the given process id on the pidlist.
252*9666Slinton  *
253*9666Slinton  * Unlink it from list if found.
254*9666Slinton  */
255*9666Slinton 
256*9666Slinton private Pidlist *pfind(pid)
257*9666Slinton int pid;
258*9666Slinton {
259*9666Slinton     register Pidlist *p, *prev;
260*9666Slinton 
261*9666Slinton     prev = nil(Pidlist *);
262*9666Slinton     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
263*9666Slinton 	if (p->pid == pid) {
264*9666Slinton 	    break;
265*9666Slinton 	}
266*9666Slinton 	prev = p;
267*9666Slinton     }
268*9666Slinton     if (p != nil(Pidlist *)) {
269*9666Slinton 	if (prev == nil(Pidlist *)) {
270*9666Slinton 	    pidlist = p->next;
271*9666Slinton 	} else {
272*9666Slinton 	    prev->next = p->next;
273*9666Slinton 	}
274*9666Slinton     }
275*9666Slinton     return p;
276*9666Slinton }
277*9666Slinton 
278*9666Slinton /*
279*9666Slinton  * System call error handler.
280*9666Slinton  *
281*9666Slinton  * The syserr routine is called when a system call is about to
282*9666Slinton  * set the c-bit to report an error.  Certain errors are caught
283*9666Slinton  * and cause the process to print a message and immediately exit.
284*9666Slinton  */
285*9666Slinton 
286*9666Slinton extern int sys_nerr;
287*9666Slinton extern char *sys_errlist[];
288*9666Slinton 
289*9666Slinton /*
290*9666Slinton  * Before calling syserr, the integer errno is set to contain the
291*9666Slinton  * number of the error.  The routine "_mycerror" is a dummy which
292*9666Slinton  * is used to force the loader to get my version of cerror rather
293*9666Slinton  * than the usual one.
294*9666Slinton  */
295*9666Slinton 
296*9666Slinton extern int errno;
297*9666Slinton extern _mycerror();
298*9666Slinton 
299*9666Slinton /*
300*9666Slinton  * Default error handling.
301*9666Slinton  */
302*9666Slinton 
303*9666Slinton private ERRINFO errinfo[] ={
304*9666Slinton /* no error */	ERR_IGNORE,
305*9666Slinton /* EPERM */	ERR_IGNORE,
306*9666Slinton /* ENOENT */	ERR_IGNORE,
307*9666Slinton /* ESRCH */	ERR_IGNORE,
308*9666Slinton /* EINTR */	ERR_CATCH,
309*9666Slinton /* EIO */	ERR_CATCH,
310*9666Slinton /* ENXIO */	ERR_CATCH,
311*9666Slinton /* E2BIG */	ERR_CATCH,
312*9666Slinton /* ENOEXEC */	ERR_CATCH,
313*9666Slinton /* EBADF */	ERR_IGNORE,
314*9666Slinton /* ECHILD */	ERR_CATCH,
315*9666Slinton /* EAGAIN */	ERR_CATCH,
316*9666Slinton /* ENOMEM */	ERR_CATCH,
317*9666Slinton /* EACCES */	ERR_CATCH,
318*9666Slinton /* EFAULT */	ERR_CATCH,
319*9666Slinton /* ENOTBLK */	ERR_CATCH,
320*9666Slinton /* EBUSY */	ERR_CATCH,
321*9666Slinton /* EEXIST */	ERR_CATCH,
322*9666Slinton /* EXDEV */	ERR_CATCH,
323*9666Slinton /* ENODEV */	ERR_CATCH,
324*9666Slinton /* ENOTDIR */	ERR_CATCH,
325*9666Slinton /* EISDIR */	ERR_CATCH,
326*9666Slinton /* EINVAL */	ERR_CATCH,
327*9666Slinton /* ENFILE */	ERR_CATCH,
328*9666Slinton /* EMFILE */	ERR_CATCH,
329*9666Slinton /* ENOTTY */	ERR_IGNORE,
330*9666Slinton /* ETXTBSY */	ERR_CATCH,
331*9666Slinton /* EFBIG */	ERR_CATCH,
332*9666Slinton /* ENOSPC */	ERR_CATCH,
333*9666Slinton /* ESPIPE */	ERR_CATCH,
334*9666Slinton /* EROFS */	ERR_CATCH,
335*9666Slinton /* EMLINK */	ERR_CATCH,
336*9666Slinton /* EPIPE */	ERR_CATCH,
337*9666Slinton /* EDOM */	ERR_CATCH,
338*9666Slinton /* ERANGE */	ERR_CATCH,
339*9666Slinton /* EQUOT */	ERR_CATCH,
340*9666Slinton };
341*9666Slinton 
342*9666Slinton public syserr()
343*9666Slinton {
344*9666Slinton     ERRINFO *e;
345*9666Slinton 
346*9666Slinton     e = &errinfo[errno];
347*9666Slinton     if (e->func == ERR_CATCH) {
348*9666Slinton 	if (errno < sys_nerr) {
349*9666Slinton 	    fatal(sys_errlist[errno]);
350*9666Slinton 	} else {
351*9666Slinton 	    fatal("errno %d", errno);
352*9666Slinton 	}
353*9666Slinton     } else if (e->func != ERR_IGNORE) {
354*9666Slinton 	(*e->func)();
355*9666Slinton     }
356*9666Slinton }
357*9666Slinton 
358*9666Slinton /*
359*9666Slinton  * Catcherrs only purpose is to get this module loaded and make
360*9666Slinton  * sure my cerror is loaded (only applicable when this is in a library).
361*9666Slinton  */
362*9666Slinton 
363*9666Slinton public catcherrs()
364*9666Slinton {
365*9666Slinton     _mycerror();
366*9666Slinton }
367*9666Slinton 
368*9666Slinton /*
369*9666Slinton  * Change the action on receipt of an error.
370*9666Slinton  */
371*9666Slinton 
372*9666Slinton public onsyserr(n, f)
373*9666Slinton int n;
374*9666Slinton INTFUNC *f;
375*9666Slinton {
376*9666Slinton     errinfo[n].func = f;
377*9666Slinton }
378*9666Slinton 
379*9666Slinton /*
380*9666Slinton  * Print the message associated with the given signal.
381*9666Slinton  * Like a "perror" for signals.
382*9666Slinton  */
383*9666Slinton 
384*9666Slinton public int sys_nsig = NSIG;
385*9666Slinton public String sys_siglist[] = {
386*9666Slinton     "no signal",
387*9666Slinton     "hangup",
388*9666Slinton     "interrupt",
389*9666Slinton     "quit",
390*9666Slinton     "illegal instruction",
391*9666Slinton     "trace trap",
392*9666Slinton     "IOT instruction",
393*9666Slinton     "EMT instruction",
394*9666Slinton     "floating point exception",
395*9666Slinton     "kill",
396*9666Slinton     "bus error",
397*9666Slinton     "segmentation violation",
398*9666Slinton     "bad argument to system call",
399*9666Slinton     "broken pipe",
400*9666Slinton     "alarm clock",
401*9666Slinton     "soft kill",
402*9666Slinton     "urgent I/O condition",
403*9666Slinton     "stop signal not from tty",
404*9666Slinton     "stop signal from tty",
405*9666Slinton     "continue",
406*9666Slinton     "child termination",
407*9666Slinton     "stop (tty input)",
408*9666Slinton     "stop (tty output)",
409*9666Slinton     "possible input/output",
410*9666Slinton     "exceeded CPU time limit",
411*9666Slinton     "exceeded file size limit",
412*9666Slinton     nil(String)
413*9666Slinton };
414*9666Slinton 
415*9666Slinton public psig(s)
416*9666Slinton String s;
417*9666Slinton {
418*9666Slinton     String c;
419*9666Slinton     int n;
420*9666Slinton 
421*9666Slinton     c = "Unknown signal";
422*9666Slinton     if (errno < sys_nsig) {
423*9666Slinton 	c = sys_errlist[errno];
424*9666Slinton     }
425*9666Slinton     n = strlen(s);
426*9666Slinton     if (n > 0) {
427*9666Slinton 	write(2, s, n);
428*9666Slinton 	write(2, ": ", 2);
429*9666Slinton     }
430*9666Slinton     write(2, c, strlen(c));
431*9666Slinton     write(2, "\n", 1);
432*9666Slinton }
433*9666Slinton 
434*9666Slinton /*
435*9666Slinton  * Standard error handling routines.
436*9666Slinton  */
437*9666Slinton 
438*9666Slinton private short nerrs;
439*9666Slinton private short nwarnings;
440*9666Slinton 
441*9666Slinton /*
442*9666Slinton  * Main driver of error message reporting.
443*9666Slinton  */
444*9666Slinton 
445*9666Slinton /* VARARGS2 */
446*9666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
447*9666Slinton String errname;
448*9666Slinton Boolean shouldquit;
449*9666Slinton String s;
450*9666Slinton {
451*9666Slinton     fflush(stdout);
452*9666Slinton     if (shouldquit and cmdname != nil(String)) {
453*9666Slinton 	fprintf(stderr, "%s: ", cmdname);
454*9666Slinton     }
455*9666Slinton     if (errfilename != nil(Filename)) {
456*9666Slinton 	fprintf(stderr, "%s: ", errfilename);
457*9666Slinton     }
458*9666Slinton     if (errlineno > 0) {
459*9666Slinton 	fprintf(stderr, "%d: ", errlineno);
460*9666Slinton     }
461*9666Slinton     if (errname != nil(String)) {
462*9666Slinton 	fprintf(stderr, "%s: ", errname);
463*9666Slinton     }
464*9666Slinton     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
465*9666Slinton     putc('\n', stderr);
466*9666Slinton     if (shouldquit) {
467*9666Slinton 	quit(1);
468*9666Slinton     }
469*9666Slinton }
470*9666Slinton 
471*9666Slinton /*
472*9666Slinton  * For when printf isn't sufficient for printing the error message ...
473*9666Slinton  */
474*9666Slinton 
475*9666Slinton public beginerrmsg()
476*9666Slinton {
477*9666Slinton     fflush(stdout);
478*9666Slinton     if (errfilename != nil(String)) {
479*9666Slinton 	fprintf(stderr, "%s: ", errfilename);
480*9666Slinton     }
481*9666Slinton     if (errlineno > 0) {
482*9666Slinton 	fprintf(stderr, "%d: ", errlineno);
483*9666Slinton     }
484*9666Slinton }
485*9666Slinton 
486*9666Slinton public enderrmsg()
487*9666Slinton {
488*9666Slinton     putc('\n', stderr);
489*9666Slinton     erecover();
490*9666Slinton }
491*9666Slinton 
492*9666Slinton /*
493*9666Slinton  * The messages are listed in increasing order of seriousness.
494*9666Slinton  *
495*9666Slinton  * First are warnings.
496*9666Slinton  */
497*9666Slinton 
498*9666Slinton /* VARARGS1 */
499*9666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
500*9666Slinton String s;
501*9666Slinton {
502*9666Slinton     nwarnings++;
503*9666Slinton     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
504*9666Slinton }
505*9666Slinton 
506*9666Slinton /*
507*9666Slinton  * Errors are a little worse, they mean something is wrong,
508*9666Slinton  * but not so bad that processing can't continue.
509*9666Slinton  *
510*9666Slinton  * The routine "erecover" is called to recover from the error,
511*9666Slinton  * a default routine is provided that does nothing.
512*9666Slinton  */
513*9666Slinton 
514*9666Slinton /* VARARGS1 */
515*9666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
516*9666Slinton String s;
517*9666Slinton {
518*9666Slinton     extern erecover();
519*9666Slinton 
520*9666Slinton     nerrs++;
521*9666Slinton     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
522*9666Slinton     erecover();
523*9666Slinton }
524*9666Slinton 
525*9666Slinton /*
526*9666Slinton  * Non-recoverable user error.
527*9666Slinton  */
528*9666Slinton 
529*9666Slinton /* VARARGS1 */
530*9666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
531*9666Slinton String s;
532*9666Slinton {
533*9666Slinton     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
534*9666Slinton }
535*9666Slinton 
536*9666Slinton /*
537*9666Slinton  * Panics indicate an internal program error.
538*9666Slinton  */
539*9666Slinton 
540*9666Slinton /* VARARGS1 */
541*9666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
542*9666Slinton String s;
543*9666Slinton {
544*9666Slinton     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
545*9666Slinton }
546*9666Slinton 
547*9666Slinton short numerrors()
548*9666Slinton {
549*9666Slinton     short r;
550*9666Slinton 
551*9666Slinton     r = nerrs;
552*9666Slinton     nerrs = 0;
553*9666Slinton     return r;
554*9666Slinton }
555*9666Slinton 
556*9666Slinton short numwarnings()
557*9666Slinton {
558*9666Slinton     short r;
559*9666Slinton 
560*9666Slinton     r = nwarnings;
561*9666Slinton     nwarnings = 0;
562*9666Slinton     return r;
563*9666Slinton }
564*9666Slinton 
565*9666Slinton /*
566*9666Slinton  * Recover from an error.
567*9666Slinton  *
568*9666Slinton  * This is the default routine which we aren't using since we have our own.
569*9666Slinton  *
570*9666Slinton public erecover()
571*9666Slinton {
572*9666Slinton }
573*9666Slinton  *
574*9666Slinton  */
575*9666Slinton 
576*9666Slinton /*
577*9666Slinton  * Default way to quit from a program is just to exit.
578*9666Slinton  *
579*9666Slinton public quit(r)
580*9666Slinton int r;
581*9666Slinton {
582*9666Slinton     exit(r);
583*9666Slinton }
584*9666Slinton  *
585*9666Slinton  */
586*9666Slinton 
587*9666Slinton /*
588*9666Slinton  * Compare n-byte areas pointed to by s1 and s2
589*9666Slinton  * if n is 0 then compare up until one has a null byte.
590*9666Slinton  */
591*9666Slinton 
592*9666Slinton public int cmp(s1, s2, n)
593*9666Slinton register char *s1, *s2;
594*9666Slinton register unsigned int n;
595*9666Slinton {
596*9666Slinton     if (s1 == nil(char *) || s2 == nil(char *)) {
597*9666Slinton 	panic("cmp: nil pointer");
598*9666Slinton     }
599*9666Slinton     if (n == 0) {
600*9666Slinton 	while (*s1 == *s2++) {
601*9666Slinton 	    if (*s1++ == '\0') {
602*9666Slinton 		return(0);
603*9666Slinton 	    }
604*9666Slinton 	}
605*9666Slinton 	return(*s1 - *(s2-1));
606*9666Slinton     } else {
607*9666Slinton 	for (; n != 0; n--) {
608*9666Slinton 	    if (*s1++ != *s2++) {
609*9666Slinton 		return(*(s1-1) - *(s2-1));
610*9666Slinton 	    }
611*9666Slinton 	}
612*9666Slinton 	return(0);
613*9666Slinton     }
614*9666Slinton }
615*9666Slinton 
616*9666Slinton /*
617*9666Slinton  * Move n bytes from src to dest.
618*9666Slinton  * If n is 0 move until a null is found.
619*9666Slinton  */
620*9666Slinton 
621*9666Slinton public mov(src, dest, n)
622*9666Slinton register char *src, *dest;
623*9666Slinton register unsigned int n;
624*9666Slinton {
625*9666Slinton     if (src == nil(char *))
626*9666Slinton 	panic("mov: nil source");
627*9666Slinton     if (dest == nil(char *))
628*9666Slinton 	panic("mov: nil destination");
629*9666Slinton     if (n != 0) {
630*9666Slinton 	for (; n != 0; n--) {
631*9666Slinton 	    *dest++ = *src++;
632*9666Slinton 	}
633*9666Slinton     } else {
634*9666Slinton 	while ((*dest++ = *src++) != '\0');
635*9666Slinton     }
636*9666Slinton }
637