xref: /csrg-svn/old/dbx/library.c (revision 18221)
19666Slinton /* Copyright (c) 1982 Regents of the University of California */
29666Slinton 
3*18221Slinton static	char sccsid[] = "@(#)library.c	1.6 (Berkeley) 03/01/85";
416611Ssam 
5*18221Slinton static char rcsid[] = "$Header: library.c,v 1.5 84/12/26 10:39:52 linton Exp $";
6*18221Slinton 
79666Slinton /*
89666Slinton  * General purpose routines.
99666Slinton  */
109666Slinton 
119666Slinton #include <stdio.h>
129666Slinton #include <errno.h>
139666Slinton #include <signal.h>
149666Slinton 
159666Slinton #define public
169666Slinton #define private static
179666Slinton #define and &&
189666Slinton #define or ||
199666Slinton #define not !
209666Slinton #define ord(enumcon)	((int) enumcon)
219666Slinton #define nil(type)	((type) 0)
229666Slinton 
2316611Ssam typedef int integer;
2416611Ssam typedef enum { FALSE, TRUE } boolean;
259666Slinton typedef char *String;
269666Slinton typedef FILE *File;
279666Slinton typedef String Filename;
289666Slinton 
299666Slinton #undef FILE
309666Slinton 
319666Slinton String cmdname;			/* name of command for error messages */
329666Slinton Filename errfilename;		/* current file associated with error */
339666Slinton short errlineno;		/* line number associated with error */
349666Slinton 
359666Slinton /*
369666Slinton  * Definitions for doing memory allocation.
379666Slinton  */
389666Slinton 
399666Slinton extern char *malloc();
409666Slinton 
419666Slinton #define alloc(n, type)	((type *) malloc((unsigned) (n) * sizeof(type)))
429666Slinton #define dispose(p)	{ free((char *) p); p = 0; }
439666Slinton 
449666Slinton /*
459666Slinton  * Macros for doing freads + fwrites.
469666Slinton  */
479666Slinton 
489666Slinton #define get(fp, var)	fread((char *) &(var), sizeof(var), 1, fp)
499666Slinton #define put(fp, var)	fwrite((char *) &(var), sizeof(var), 1, fp)
509666Slinton 
519666Slinton /*
529666Slinton  * String definitions.
539666Slinton  */
549666Slinton 
559666Slinton extern String strcpy(), index(), rindex();
569666Slinton extern int strlen();
579666Slinton 
589666Slinton #define strdup(s)		strcpy(malloc((unsigned) strlen(s) + 1), s)
599666Slinton #define streq(s1, s2)	(strcmp(s1, s2) == 0)
609666Slinton 
619666Slinton typedef int INTFUNC();
629666Slinton 
639666Slinton typedef struct {
649666Slinton     INTFUNC *func;
659666Slinton } ERRINFO;
669666Slinton 
679666Slinton #define ERR_IGNORE ((INTFUNC *) 0)
689666Slinton #define ERR_CATCH  ((INTFUNC *) 1)
699666Slinton 
709666Slinton /*
719666Slinton  * Call a program.
729666Slinton  *
739666Slinton  * Four entries:
749666Slinton  *
759666Slinton  *	call, callv - call a program and wait for it, returning status
769666Slinton  *	back, backv - call a program and don't wait, returning process id
779666Slinton  *
789666Slinton  * The command's standard input and output are passed as FILE's.
799666Slinton  */
809666Slinton 
819666Slinton 
8216611Ssam #define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
839666Slinton #define BADEXEC 127	/* exec fails */
849666Slinton 
859666Slinton #define ischild(pid)    ((pid) == 0)
869666Slinton 
879666Slinton /* VARARGS3 */
889666Slinton public int call(name, in, out, args)
899666Slinton String name;
909666Slinton File in;
919666Slinton File out;
929666Slinton String args;
939666Slinton {
949666Slinton     String *ap, *argp;
959666Slinton     String argv[MAXNARGS];
969666Slinton 
979666Slinton     argp = &argv[0];
989666Slinton     *argp++ = name;
999666Slinton     ap = &args;
1009666Slinton     while (*ap != nil(String)) {
1019666Slinton 	*argp++ = *ap++;
1029666Slinton     }
1039666Slinton     *argp = nil(String);
1049666Slinton     return callv(name, in, out, argv);
1059666Slinton }
1069666Slinton 
1079666Slinton /* VARARGS3 */
1089666Slinton public int back(name, in, out, args)
1099666Slinton String name;
1109666Slinton File in;
1119666Slinton File out;
1129666Slinton String args;
1139666Slinton {
1149666Slinton     String *ap, *argp;
1159666Slinton     String argv[MAXNARGS];
1169666Slinton 
1179666Slinton     argp = &argv[0];
1189666Slinton     *argp++ = name;
1199666Slinton     ap = &args;
1209666Slinton     while (*ap != nil(String)) {
1219666Slinton 	*argp++ = *ap++;
1229666Slinton     }
1239666Slinton     *argp = nil(String);
1249666Slinton     return backv(name, in, out, argv);
1259666Slinton }
1269666Slinton 
1279666Slinton public int callv(name, in, out, argv)
1289666Slinton String name;
1299666Slinton File in;
1309666Slinton File out;
1319666Slinton String *argv;
1329666Slinton {
1339666Slinton     int pid, status;
1349666Slinton 
1359666Slinton     pid = backv(name, in, out, argv);
1369666Slinton     pwait(pid, &status);
1379666Slinton     return status;
1389666Slinton }
1399666Slinton 
1409666Slinton public int backv(name, in, out, argv)
1419666Slinton String name;
1429666Slinton File in;
1439666Slinton File out;
1449666Slinton String *argv;
1459666Slinton {
1469666Slinton     int pid;
1479666Slinton 
1489666Slinton     fflush(stdout);
1499666Slinton     if (ischild(pid = fork())) {
1509666Slinton 	fswap(0, fileno(in));
1519666Slinton 	fswap(1, fileno(out));
1529666Slinton 	onsyserr(EACCES, ERR_IGNORE);
1539666Slinton 	execvp(name, argv);
1549666Slinton 	_exit(BADEXEC);
1559666Slinton     }
1569666Slinton     return pid;
1579666Slinton }
1589666Slinton 
1599666Slinton /*
1609666Slinton  * Swap file numbers so as to redirect standard input and output.
1619666Slinton  */
1629666Slinton 
1639666Slinton private fswap(oldfd, newfd)
1649666Slinton int oldfd;
1659666Slinton int newfd;
1669666Slinton {
1679666Slinton     if (oldfd != newfd) {
1689666Slinton 	close(oldfd);
1699666Slinton 	dup(newfd);
1709666Slinton 	close(newfd);
1719666Slinton     }
1729666Slinton }
1739666Slinton 
1749666Slinton /*
1759666Slinton  * Invoke a shell on a command line.
1769666Slinton  */
1779666Slinton 
1789666Slinton #define DEF_SHELL	"csh"
1799666Slinton 
1809666Slinton public shell(s)
1819666Slinton String s;
1829666Slinton {
1839666Slinton     extern String getenv();
1849666Slinton     String sh;
1859666Slinton 
1869666Slinton     if ((sh = getenv("SHELL")) == nil(String)) {
1879666Slinton 	sh = DEF_SHELL;
1889666Slinton     }
1899666Slinton     if (s != nil(String) and *s != '\0') {
1909666Slinton 	call(sh, stdin, stdout, "-c", s, 0);
1919666Slinton     } else {
1929666Slinton 	call(sh, stdin, stdout, 0);
1939666Slinton     }
1949666Slinton }
1959666Slinton 
1969666Slinton /*
1979666Slinton  * Wait for a process the right way.  We wait for a particular
1989666Slinton  * process and if any others come along in between, we remember them
1999666Slinton  * in case they are eventually waited for.
2009666Slinton  *
2019666Slinton  * This routine is not very efficient when the number of processes
2029666Slinton  * to be remembered is large.
20314394Slinton  *
20414394Slinton  * To deal with a kernel idiosyncrasy, we keep a list on the side
20514394Slinton  * of "traced" processes, and do not notice them when waiting for
20614394Slinton  * another process.
2079666Slinton  */
2089666Slinton 
2099666Slinton typedef struct pidlist {
2109666Slinton     int pid;
2119666Slinton     int status;
2129666Slinton     struct pidlist *next;
2139666Slinton } Pidlist;
2149666Slinton 
21514394Slinton private Pidlist *pidlist, *ptrclist, *pfind();
2169666Slinton 
21714394Slinton public ptraced(pid)
21814394Slinton int pid;
21914394Slinton {
22014394Slinton     Pidlist *p;
22114394Slinton 
22214394Slinton     p = alloc(1, Pidlist);
22314394Slinton     p->pid = pid;
22414394Slinton     p->next = ptrclist;
22514394Slinton     ptrclist = p;
22614394Slinton }
22714394Slinton 
22814394Slinton public unptraced(pid)
22914394Slinton int pid;
23014394Slinton {
23114394Slinton     register Pidlist *p, *prev;
23214394Slinton 
23314394Slinton     prev = nil(Pidlist *);
23414394Slinton     p = ptrclist;
23514394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
23614394Slinton 	prev = p;
23714394Slinton 	p = p->next;
23814394Slinton     }
23914394Slinton     if (p != nil(Pidlist *)) {
24014394Slinton 	if (prev == nil(Pidlist *)) {
24114394Slinton 	    ptrclist = p->next;
24214394Slinton 	} else {
24314394Slinton 	    prev->next = p->next;
24414394Slinton 	}
24514394Slinton 	dispose(p);
24614394Slinton     }
24714394Slinton }
24814394Slinton 
24916611Ssam private boolean isptraced(pid)
25014394Slinton int pid;
25114394Slinton {
25214394Slinton     register Pidlist *p;
25314394Slinton 
25414394Slinton     p = ptrclist;
25514394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
25614394Slinton 	p = p->next;
25714394Slinton     }
25816611Ssam     return (boolean) (p != nil(Pidlist *));
25914394Slinton }
26014394Slinton 
2619666Slinton public pwait(pid, statusp)
2629666Slinton int pid, *statusp;
2639666Slinton {
26414393Slinton     Pidlist *p;
26514393Slinton     int pnum, status;
2669666Slinton 
26714393Slinton     p = pfind(pid);
26814393Slinton     if (p != nil(Pidlist *)) {
26914393Slinton 	*statusp = p->status;
27014393Slinton 	dispose(p);
27114394Slinton     } else {
27214394Slinton 	pnum = wait(&status);
27314394Slinton 	while (pnum != pid and pnum >= 0) {
27414394Slinton 	    if (not isptraced(pnum)) {
27514394Slinton 		p = alloc(1, Pidlist);
27614394Slinton 		p->pid = pnum;
27714394Slinton 		p->status = status;
27814394Slinton 		p->next = pidlist;
27914394Slinton 		pidlist = p;
28014394Slinton 	    }
28114394Slinton 	    pnum = wait(&status);
2829666Slinton 	}
28314394Slinton 	if (pnum < 0) {
28414394Slinton 	    p = pfind(pid);
28514394Slinton 	    if (p == nil(Pidlist *)) {
28614394Slinton 		panic("pwait: pid %d not found", pid);
28714394Slinton 	    }
28814394Slinton 	    *statusp = p->status;
28914394Slinton 	    dispose(p);
29014394Slinton 	} else {
29114394Slinton 	    *statusp = status;
29214394Slinton 	}
29314393Slinton     }
2949666Slinton }
2959666Slinton 
2969666Slinton /*
2979666Slinton  * Look for the given process id on the pidlist.
2989666Slinton  *
2999666Slinton  * Unlink it from list if found.
3009666Slinton  */
3019666Slinton 
3029666Slinton private Pidlist *pfind(pid)
3039666Slinton int pid;
3049666Slinton {
3059666Slinton     register Pidlist *p, *prev;
3069666Slinton 
3079666Slinton     prev = nil(Pidlist *);
3089666Slinton     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
3099666Slinton 	if (p->pid == pid) {
3109666Slinton 	    break;
3119666Slinton 	}
3129666Slinton 	prev = p;
3139666Slinton     }
3149666Slinton     if (p != nil(Pidlist *)) {
3159666Slinton 	if (prev == nil(Pidlist *)) {
3169666Slinton 	    pidlist = p->next;
3179666Slinton 	} else {
3189666Slinton 	    prev->next = p->next;
3199666Slinton 	}
3209666Slinton     }
3219666Slinton     return p;
3229666Slinton }
3239666Slinton 
3249666Slinton /*
3259666Slinton  * System call error handler.
3269666Slinton  *
3279666Slinton  * The syserr routine is called when a system call is about to
3289666Slinton  * set the c-bit to report an error.  Certain errors are caught
3299666Slinton  * and cause the process to print a message and immediately exit.
3309666Slinton  */
3319666Slinton 
3329666Slinton extern int sys_nerr;
3339666Slinton extern char *sys_errlist[];
3349666Slinton 
3359666Slinton /*
3369666Slinton  * Before calling syserr, the integer errno is set to contain the
3379666Slinton  * number of the error.  The routine "_mycerror" is a dummy which
3389666Slinton  * is used to force the loader to get my version of cerror rather
3399666Slinton  * than the usual one.
3409666Slinton  */
3419666Slinton 
3429666Slinton extern int errno;
3439666Slinton extern _mycerror();
3449666Slinton 
3459666Slinton /*
34616611Ssam  * Initialize error information, setting defaults for handling errors.
3479666Slinton  */
3489666Slinton 
34916611Ssam private ERRINFO *errinfo;
3509666Slinton 
35116611Ssam private initErrInfo ()
35216611Ssam {
35316611Ssam     integer i;
35416611Ssam 
35516611Ssam     errinfo = alloc(sys_nerr, ERRINFO);
35616611Ssam     for (i = 0; i < sys_nerr; i++) {
35716611Ssam 	errinfo[i].func = ERR_CATCH;
35816611Ssam     }
35916611Ssam     errinfo[0].func = ERR_IGNORE;
36016611Ssam     errinfo[EPERM].func = ERR_IGNORE;
36116611Ssam     errinfo[ENOENT].func = ERR_IGNORE;
36216611Ssam     errinfo[ESRCH].func = ERR_IGNORE;
36316611Ssam     errinfo[EBADF].func = ERR_IGNORE;
36416611Ssam     errinfo[ENOTTY].func = ERR_IGNORE;
36516611Ssam     errinfo[EOPNOTSUPP].func = ERR_IGNORE;
36616611Ssam }
36716611Ssam 
3689666Slinton public syserr()
3699666Slinton {
3709666Slinton     ERRINFO *e;
3719666Slinton 
37216611Ssam     if (errno < 0 or errno > sys_nerr) {
37316611Ssam 	fatal("errno %d", errno);
37416611Ssam     } else {
37516611Ssam 	if (errinfo == nil(ERRINFO *)) {
37616611Ssam 	    initErrInfo();
37716611Ssam 	}
37816611Ssam 	e = &(errinfo[errno]);
37916611Ssam 	if (e->func == ERR_CATCH) {
3809666Slinton 	    fatal(sys_errlist[errno]);
38116611Ssam 	} else if (e->func != ERR_IGNORE) {
38216611Ssam 	    (*e->func)();
3839666Slinton 	}
3849666Slinton     }
3859666Slinton }
3869666Slinton 
3879666Slinton /*
38816611Ssam  * Catcherrs' purpose is to initialize the errinfo table, get this module
38916611Ssam  * loaded, and make sure my cerror is loaded (only applicable when this is
39016611Ssam  * in a library).
3919666Slinton  */
3929666Slinton 
3939666Slinton public catcherrs()
3949666Slinton {
3959666Slinton     _mycerror();
39616611Ssam     initErrInfo();
3979666Slinton }
3989666Slinton 
3999666Slinton /*
400*18221Slinton  * Turn off the error catching mechanism completely by having all errors
401*18221Slinton  * ignored.  This is most useful between a fork and an exec.
402*18221Slinton  */
403*18221Slinton 
404*18221Slinton public nocatcherrs()
405*18221Slinton {
406*18221Slinton     integer i;
407*18221Slinton 
408*18221Slinton     for (i = 0; i < sys_nerr; i++) {
409*18221Slinton 	errinfo[i].func = ERR_IGNORE;
410*18221Slinton     }
411*18221Slinton }
412*18221Slinton 
413*18221Slinton /*
4149666Slinton  * Change the action on receipt of an error.
4159666Slinton  */
4169666Slinton 
4179666Slinton public onsyserr(n, f)
4189666Slinton int n;
4199666Slinton INTFUNC *f;
4209666Slinton {
42116611Ssam     if (errinfo == nil(ERRINFO *)) {
42216611Ssam 	initErrInfo();
42316611Ssam     }
4249666Slinton     errinfo[n].func = f;
4259666Slinton }
4269666Slinton 
4279666Slinton /*
4289666Slinton  * Print the message associated with the given signal.
4299666Slinton  * Like a "perror" for signals.
4309666Slinton  */
4319666Slinton 
4329666Slinton public int sys_nsig = NSIG;
4339666Slinton public String sys_siglist[] = {
4349666Slinton     "no signal",
4359666Slinton     "hangup",
4369666Slinton     "interrupt",
4379666Slinton     "quit",
4389666Slinton     "illegal instruction",
4399666Slinton     "trace trap",
4409666Slinton     "IOT instruction",
4419666Slinton     "EMT instruction",
4429666Slinton     "floating point exception",
4439666Slinton     "kill",
4449666Slinton     "bus error",
4459666Slinton     "segmentation violation",
4469666Slinton     "bad argument to system call",
4479666Slinton     "broken pipe",
4489666Slinton     "alarm clock",
4499666Slinton     "soft kill",
4509666Slinton     "urgent I/O condition",
4519666Slinton     "stop signal not from tty",
4529666Slinton     "stop signal from tty",
4539666Slinton     "continue",
4549666Slinton     "child termination",
4559666Slinton     "stop (tty input)",
4569666Slinton     "stop (tty output)",
4579666Slinton     "possible input/output",
4589666Slinton     "exceeded CPU time limit",
4599666Slinton     "exceeded file size limit",
4609666Slinton     nil(String)
4619666Slinton };
4629666Slinton 
46316611Ssam public psignal(s, n)
4649666Slinton String s;
46516611Ssam integer n;
4669666Slinton {
46716611Ssam     String msg;
46816611Ssam     integer len;
4699666Slinton 
47016611Ssam     if (n >= 0 and n < sys_nsig) {
47116611Ssam 	msg = sys_siglist[n];
47216611Ssam     } else {
47316611Ssam 	msg = "Unknown signal";
4749666Slinton     }
47516611Ssam     len = strlen(s);
47616611Ssam     if (len > 0) {
47716611Ssam 	write(2, s, len);
4789666Slinton 	write(2, ": ", 2);
4799666Slinton     }
48016611Ssam     write(2, msg, strlen(msg));
4819666Slinton     write(2, "\n", 1);
4829666Slinton }
4839666Slinton 
4849666Slinton /*
4859666Slinton  * Standard error handling routines.
4869666Slinton  */
4879666Slinton 
4889666Slinton private short nerrs;
4899666Slinton private short nwarnings;
4909666Slinton 
4919666Slinton /*
4929666Slinton  * Main driver of error message reporting.
4939666Slinton  */
4949666Slinton 
4959666Slinton /* VARARGS2 */
4969666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
4979666Slinton String errname;
49816611Ssam boolean shouldquit;
4999666Slinton String s;
5009666Slinton {
5019666Slinton     fflush(stdout);
5029666Slinton     if (shouldquit and cmdname != nil(String)) {
5039666Slinton 	fprintf(stderr, "%s: ", cmdname);
5049666Slinton     }
5059666Slinton     if (errfilename != nil(Filename)) {
5069666Slinton 	fprintf(stderr, "%s: ", errfilename);
5079666Slinton     }
5089666Slinton     if (errlineno > 0) {
5099666Slinton 	fprintf(stderr, "%d: ", errlineno);
5109666Slinton     }
5119666Slinton     if (errname != nil(String)) {
5129666Slinton 	fprintf(stderr, "%s: ", errname);
5139666Slinton     }
5149666Slinton     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5159666Slinton     putc('\n', stderr);
5169666Slinton     if (shouldquit) {
5179666Slinton 	quit(1);
5189666Slinton     }
5199666Slinton }
5209666Slinton 
5219666Slinton /*
5229666Slinton  * For when printf isn't sufficient for printing the error message ...
5239666Slinton  */
5249666Slinton 
5259666Slinton public beginerrmsg()
5269666Slinton {
5279666Slinton     fflush(stdout);
5289666Slinton     if (errfilename != nil(String)) {
5299666Slinton 	fprintf(stderr, "%s: ", errfilename);
5309666Slinton     }
5319666Slinton     if (errlineno > 0) {
5329666Slinton 	fprintf(stderr, "%d: ", errlineno);
5339666Slinton     }
5349666Slinton }
5359666Slinton 
5369666Slinton public enderrmsg()
5379666Slinton {
5389666Slinton     putc('\n', stderr);
5399666Slinton     erecover();
5409666Slinton }
5419666Slinton 
5429666Slinton /*
5439666Slinton  * The messages are listed in increasing order of seriousness.
5449666Slinton  *
5459666Slinton  * First are warnings.
5469666Slinton  */
5479666Slinton 
5489666Slinton /* VARARGS1 */
5499666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5509666Slinton String s;
5519666Slinton {
5529666Slinton     nwarnings++;
5539666Slinton     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5549666Slinton }
5559666Slinton 
5569666Slinton /*
5579666Slinton  * Errors are a little worse, they mean something is wrong,
5589666Slinton  * but not so bad that processing can't continue.
5599666Slinton  *
5609666Slinton  * The routine "erecover" is called to recover from the error,
5619666Slinton  * a default routine is provided that does nothing.
5629666Slinton  */
5639666Slinton 
5649666Slinton /* VARARGS1 */
5659666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5669666Slinton String s;
5679666Slinton {
5689666Slinton     extern erecover();
5699666Slinton 
5709666Slinton     nerrs++;
5719666Slinton     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5729666Slinton     erecover();
5739666Slinton }
5749666Slinton 
5759666Slinton /*
5769666Slinton  * Non-recoverable user error.
5779666Slinton  */
5789666Slinton 
5799666Slinton /* VARARGS1 */
5809666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5819666Slinton String s;
5829666Slinton {
5839666Slinton     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5849666Slinton }
5859666Slinton 
5869666Slinton /*
5879666Slinton  * Panics indicate an internal program error.
5889666Slinton  */
5899666Slinton 
5909666Slinton /* VARARGS1 */
5919666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5929666Slinton String s;
5939666Slinton {
5949666Slinton     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5959666Slinton }
5969666Slinton 
5979666Slinton short numerrors()
5989666Slinton {
5999666Slinton     short r;
6009666Slinton 
6019666Slinton     r = nerrs;
6029666Slinton     nerrs = 0;
6039666Slinton     return r;
6049666Slinton }
6059666Slinton 
6069666Slinton short numwarnings()
6079666Slinton {
6089666Slinton     short r;
6099666Slinton 
6109666Slinton     r = nwarnings;
6119666Slinton     nwarnings = 0;
6129666Slinton     return r;
6139666Slinton }
6149666Slinton 
6159666Slinton /*
6169666Slinton  * Recover from an error.
6179666Slinton  *
6189666Slinton  * This is the default routine which we aren't using since we have our own.
6199666Slinton  *
6209666Slinton public erecover()
6219666Slinton {
6229666Slinton }
6239666Slinton  *
6249666Slinton  */
6259666Slinton 
6269666Slinton /*
6279666Slinton  * Default way to quit from a program is just to exit.
6289666Slinton  *
6299666Slinton public quit(r)
6309666Slinton int r;
6319666Slinton {
6329666Slinton     exit(r);
6339666Slinton }
6349666Slinton  *
6359666Slinton  */
6369666Slinton 
6379666Slinton /*
6389666Slinton  * Compare n-byte areas pointed to by s1 and s2
6399666Slinton  * if n is 0 then compare up until one has a null byte.
6409666Slinton  */
6419666Slinton 
6429666Slinton public int cmp(s1, s2, n)
6439666Slinton register char *s1, *s2;
6449666Slinton register unsigned int n;
6459666Slinton {
6469666Slinton     if (s1 == nil(char *) || s2 == nil(char *)) {
6479666Slinton 	panic("cmp: nil pointer");
6489666Slinton     }
6499666Slinton     if (n == 0) {
6509666Slinton 	while (*s1 == *s2++) {
6519666Slinton 	    if (*s1++ == '\0') {
6529666Slinton 		return(0);
6539666Slinton 	    }
6549666Slinton 	}
6559666Slinton 	return(*s1 - *(s2-1));
6569666Slinton     } else {
6579666Slinton 	for (; n != 0; n--) {
6589666Slinton 	    if (*s1++ != *s2++) {
6599666Slinton 		return(*(s1-1) - *(s2-1));
6609666Slinton 	    }
6619666Slinton 	}
6629666Slinton 	return(0);
6639666Slinton     }
6649666Slinton }
6659666Slinton 
6669666Slinton /*
6679666Slinton  * Move n bytes from src to dest.
6689666Slinton  * If n is 0 move until a null is found.
6699666Slinton  */
6709666Slinton 
6719666Slinton public mov(src, dest, n)
6729666Slinton register char *src, *dest;
6739666Slinton register unsigned int n;
6749666Slinton {
6759666Slinton     if (src == nil(char *))
6769666Slinton 	panic("mov: nil source");
6779666Slinton     if (dest == nil(char *))
6789666Slinton 	panic("mov: nil destination");
6799666Slinton     if (n != 0) {
6809666Slinton 	for (; n != 0; n--) {
6819666Slinton 	    *dest++ = *src++;
6829666Slinton 	}
6839666Slinton     } else {
6849666Slinton 	while ((*dest++ = *src++) != '\0');
6859666Slinton     }
6869666Slinton }
687