xref: /csrg-svn/old/dbx/library.c (revision 38105)
121606Sdist /*
2*38105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38105Sbostic  * All rights reserved.
4*38105Sbostic  *
5*38105Sbostic  * Redistribution and use in source and binary forms are permitted
6*38105Sbostic  * provided that the above copyright notice and this paragraph are
7*38105Sbostic  * duplicated in all such forms and that any documentation,
8*38105Sbostic  * advertising materials, and other materials related to such
9*38105Sbostic  * distribution and use acknowledge that the software was developed
10*38105Sbostic  * by the University of California, Berkeley.  The name of the
11*38105Sbostic  * University may not be used to endorse or promote products derived
12*38105Sbostic  * from this software without specific prior written permission.
13*38105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621606Sdist  */
179666Slinton 
1821606Sdist #ifndef lint
19*38105Sbostic static char sccsid[] = "@(#)library.c	5.3 (Berkeley) 05/23/89";
20*38105Sbostic #endif /* not lint */
2116611Ssam 
229666Slinton /*
239666Slinton  * General purpose routines.
249666Slinton  */
259666Slinton 
269666Slinton #include <stdio.h>
279666Slinton #include <errno.h>
289666Slinton #include <signal.h>
299666Slinton 
309666Slinton #define public
319666Slinton #define private static
329666Slinton #define and &&
339666Slinton #define or ||
349666Slinton #define not !
359666Slinton #define ord(enumcon)	((int) enumcon)
369666Slinton #define nil(type)	((type) 0)
379666Slinton 
3816611Ssam typedef int integer;
3916611Ssam typedef enum { FALSE, TRUE } boolean;
409666Slinton typedef char *String;
419666Slinton typedef FILE *File;
429666Slinton typedef String Filename;
439666Slinton 
449666Slinton #undef FILE
459666Slinton 
469666Slinton String cmdname;			/* name of command for error messages */
479666Slinton Filename errfilename;		/* current file associated with error */
489666Slinton short errlineno;		/* line number associated with error */
499666Slinton 
509666Slinton /*
519666Slinton  * Definitions for doing memory allocation.
529666Slinton  */
539666Slinton 
549666Slinton extern char *malloc();
559666Slinton 
569666Slinton #define alloc(n, type)	((type *) malloc((unsigned) (n) * sizeof(type)))
579666Slinton #define dispose(p)	{ free((char *) p); p = 0; }
589666Slinton 
599666Slinton /*
609666Slinton  * Macros for doing freads + fwrites.
619666Slinton  */
629666Slinton 
639666Slinton #define get(fp, var)	fread((char *) &(var), sizeof(var), 1, fp)
649666Slinton #define put(fp, var)	fwrite((char *) &(var), sizeof(var), 1, fp)
659666Slinton 
669666Slinton /*
679666Slinton  * String definitions.
689666Slinton  */
699666Slinton 
709666Slinton extern String strcpy(), index(), rindex();
719666Slinton extern int strlen();
729666Slinton 
739666Slinton #define strdup(s)		strcpy(malloc((unsigned) strlen(s) + 1), s)
749666Slinton #define streq(s1, s2)	(strcmp(s1, s2) == 0)
759666Slinton 
7633321Sdonn typedef int IntFunc();
779666Slinton 
7833321Sdonn IntFunc *onsyserr();
7933321Sdonn 
809666Slinton typedef struct {
8133321Sdonn     IntFunc *func;
8233321Sdonn } ErrInfo;
839666Slinton 
8433321Sdonn #define ERR_IGNORE ((IntFunc *) 0)
8533321Sdonn #define ERR_CATCH  ((IntFunc *) 1)
869666Slinton 
879666Slinton /*
889666Slinton  * Call a program.
899666Slinton  *
909666Slinton  * Four entries:
919666Slinton  *
929666Slinton  *	call, callv - call a program and wait for it, returning status
939666Slinton  *	back, backv - call a program and don't wait, returning process id
949666Slinton  *
959666Slinton  * The command's standard input and output are passed as FILE's.
969666Slinton  */
979666Slinton 
989666Slinton 
9916611Ssam #define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
1009666Slinton #define BADEXEC 127	/* exec fails */
1019666Slinton 
1029666Slinton #define ischild(pid)    ((pid) == 0)
1039666Slinton 
1049666Slinton /* VARARGS3 */
1059666Slinton public int call(name, in, out, args)
1069666Slinton String name;
1079666Slinton File in;
1089666Slinton File out;
1099666Slinton String args;
1109666Slinton {
1119666Slinton     String *ap, *argp;
1129666Slinton     String argv[MAXNARGS];
1139666Slinton 
1149666Slinton     argp = &argv[0];
1159666Slinton     *argp++ = name;
1169666Slinton     ap = &args;
1179666Slinton     while (*ap != nil(String)) {
1189666Slinton 	*argp++ = *ap++;
1199666Slinton     }
1209666Slinton     *argp = nil(String);
1219666Slinton     return callv(name, in, out, argv);
1229666Slinton }
1239666Slinton 
1249666Slinton /* VARARGS3 */
1259666Slinton public int back(name, in, out, args)
1269666Slinton String name;
1279666Slinton File in;
1289666Slinton File out;
1299666Slinton String args;
1309666Slinton {
1319666Slinton     String *ap, *argp;
1329666Slinton     String argv[MAXNARGS];
1339666Slinton 
1349666Slinton     argp = &argv[0];
1359666Slinton     *argp++ = name;
1369666Slinton     ap = &args;
1379666Slinton     while (*ap != nil(String)) {
1389666Slinton 	*argp++ = *ap++;
1399666Slinton     }
1409666Slinton     *argp = nil(String);
1419666Slinton     return backv(name, in, out, argv);
1429666Slinton }
1439666Slinton 
1449666Slinton public int callv(name, in, out, argv)
1459666Slinton String name;
1469666Slinton File in;
1479666Slinton File out;
1489666Slinton String *argv;
1499666Slinton {
1509666Slinton     int pid, status;
1519666Slinton 
1529666Slinton     pid = backv(name, in, out, argv);
1539666Slinton     pwait(pid, &status);
1549666Slinton     return status;
1559666Slinton }
1569666Slinton 
1579666Slinton public int backv(name, in, out, argv)
1589666Slinton String name;
1599666Slinton File in;
1609666Slinton File out;
1619666Slinton String *argv;
1629666Slinton {
1639666Slinton     int pid;
1649666Slinton 
1659666Slinton     fflush(stdout);
1669666Slinton     if (ischild(pid = fork())) {
1679666Slinton 	fswap(0, fileno(in));
1689666Slinton 	fswap(1, fileno(out));
1699666Slinton 	onsyserr(EACCES, ERR_IGNORE);
1709666Slinton 	execvp(name, argv);
1719666Slinton 	_exit(BADEXEC);
1729666Slinton     }
1739666Slinton     return pid;
1749666Slinton }
1759666Slinton 
1769666Slinton /*
1779666Slinton  * Swap file numbers so as to redirect standard input and output.
1789666Slinton  */
1799666Slinton 
1809666Slinton private fswap(oldfd, newfd)
1819666Slinton int oldfd;
1829666Slinton int newfd;
1839666Slinton {
1849666Slinton     if (oldfd != newfd) {
1859666Slinton 	close(oldfd);
1869666Slinton 	dup(newfd);
1879666Slinton 	close(newfd);
1889666Slinton     }
1899666Slinton }
1909666Slinton 
1919666Slinton /*
1929666Slinton  * Invoke a shell on a command line.
1939666Slinton  */
1949666Slinton 
1959666Slinton #define DEF_SHELL	"csh"
1969666Slinton 
1979666Slinton public shell(s)
1989666Slinton String s;
1999666Slinton {
2009666Slinton     extern String getenv();
2019666Slinton     String sh;
2029666Slinton 
2039666Slinton     if ((sh = getenv("SHELL")) == nil(String)) {
2049666Slinton 	sh = DEF_SHELL;
2059666Slinton     }
2069666Slinton     if (s != nil(String) and *s != '\0') {
2079666Slinton 	call(sh, stdin, stdout, "-c", s, 0);
2089666Slinton     } else {
2099666Slinton 	call(sh, stdin, stdout, 0);
2109666Slinton     }
2119666Slinton }
2129666Slinton 
2139666Slinton /*
2149666Slinton  * Wait for a process the right way.  We wait for a particular
2159666Slinton  * process and if any others come along in between, we remember them
2169666Slinton  * in case they are eventually waited for.
2179666Slinton  *
2189666Slinton  * This routine is not very efficient when the number of processes
2199666Slinton  * to be remembered is large.
22014394Slinton  *
22114394Slinton  * To deal with a kernel idiosyncrasy, we keep a list on the side
22214394Slinton  * of "traced" processes, and do not notice them when waiting for
22314394Slinton  * another process.
2249666Slinton  */
2259666Slinton 
2269666Slinton typedef struct pidlist {
2279666Slinton     int pid;
2289666Slinton     int status;
2299666Slinton     struct pidlist *next;
2309666Slinton } Pidlist;
2319666Slinton 
23214394Slinton private Pidlist *pidlist, *ptrclist, *pfind();
2339666Slinton 
23414394Slinton public ptraced(pid)
23514394Slinton int pid;
23614394Slinton {
23714394Slinton     Pidlist *p;
23814394Slinton 
23914394Slinton     p = alloc(1, Pidlist);
24014394Slinton     p->pid = pid;
24114394Slinton     p->next = ptrclist;
24214394Slinton     ptrclist = p;
24314394Slinton }
24414394Slinton 
24514394Slinton public unptraced(pid)
24614394Slinton int pid;
24714394Slinton {
24814394Slinton     register Pidlist *p, *prev;
24914394Slinton 
25014394Slinton     prev = nil(Pidlist *);
25114394Slinton     p = ptrclist;
25214394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
25314394Slinton 	prev = p;
25414394Slinton 	p = p->next;
25514394Slinton     }
25614394Slinton     if (p != nil(Pidlist *)) {
25714394Slinton 	if (prev == nil(Pidlist *)) {
25814394Slinton 	    ptrclist = p->next;
25914394Slinton 	} else {
26014394Slinton 	    prev->next = p->next;
26114394Slinton 	}
26214394Slinton 	dispose(p);
26314394Slinton     }
26414394Slinton }
26514394Slinton 
26616611Ssam private boolean isptraced(pid)
26714394Slinton int pid;
26814394Slinton {
26914394Slinton     register Pidlist *p;
27014394Slinton 
27114394Slinton     p = ptrclist;
27214394Slinton     while (p != nil(Pidlist *) and p->pid != pid) {
27314394Slinton 	p = p->next;
27414394Slinton     }
27516611Ssam     return (boolean) (p != nil(Pidlist *));
27614394Slinton }
27714394Slinton 
2789666Slinton public pwait(pid, statusp)
2799666Slinton int pid, *statusp;
2809666Slinton {
28114393Slinton     Pidlist *p;
28214393Slinton     int pnum, status;
2839666Slinton 
28414393Slinton     p = pfind(pid);
28514393Slinton     if (p != nil(Pidlist *)) {
28614393Slinton 	*statusp = p->status;
28714393Slinton 	dispose(p);
28814394Slinton     } else {
28914394Slinton 	pnum = wait(&status);
29014394Slinton 	while (pnum != pid and pnum >= 0) {
29114394Slinton 	    if (not isptraced(pnum)) {
29214394Slinton 		p = alloc(1, Pidlist);
29314394Slinton 		p->pid = pnum;
29414394Slinton 		p->status = status;
29514394Slinton 		p->next = pidlist;
29614394Slinton 		pidlist = p;
29714394Slinton 	    }
29814394Slinton 	    pnum = wait(&status);
2999666Slinton 	}
30014394Slinton 	if (pnum < 0) {
30114394Slinton 	    p = pfind(pid);
30214394Slinton 	    if (p == nil(Pidlist *)) {
30314394Slinton 		panic("pwait: pid %d not found", pid);
30414394Slinton 	    }
30514394Slinton 	    *statusp = p->status;
30614394Slinton 	    dispose(p);
30714394Slinton 	} else {
30814394Slinton 	    *statusp = status;
30914394Slinton 	}
31014393Slinton     }
3119666Slinton }
3129666Slinton 
3139666Slinton /*
3149666Slinton  * Look for the given process id on the pidlist.
3159666Slinton  *
3169666Slinton  * Unlink it from list if found.
3179666Slinton  */
3189666Slinton 
3199666Slinton private Pidlist *pfind(pid)
3209666Slinton int pid;
3219666Slinton {
3229666Slinton     register Pidlist *p, *prev;
3239666Slinton 
3249666Slinton     prev = nil(Pidlist *);
3259666Slinton     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
3269666Slinton 	if (p->pid == pid) {
3279666Slinton 	    break;
3289666Slinton 	}
3299666Slinton 	prev = p;
3309666Slinton     }
3319666Slinton     if (p != nil(Pidlist *)) {
3329666Slinton 	if (prev == nil(Pidlist *)) {
3339666Slinton 	    pidlist = p->next;
3349666Slinton 	} else {
3359666Slinton 	    prev->next = p->next;
3369666Slinton 	}
3379666Slinton     }
3389666Slinton     return p;
3399666Slinton }
3409666Slinton 
3419666Slinton /*
3429666Slinton  * System call error handler.
3439666Slinton  *
3449666Slinton  * The syserr routine is called when a system call is about to
3459666Slinton  * set the c-bit to report an error.  Certain errors are caught
3469666Slinton  * and cause the process to print a message and immediately exit.
3479666Slinton  */
3489666Slinton 
3499666Slinton extern int sys_nerr;
3509666Slinton extern char *sys_errlist[];
3519666Slinton 
3529666Slinton /*
3539666Slinton  * Before calling syserr, the integer errno is set to contain the
3549666Slinton  * number of the error.  The routine "_mycerror" is a dummy which
3559666Slinton  * is used to force the loader to get my version of cerror rather
3569666Slinton  * than the usual one.
3579666Slinton  */
3589666Slinton 
3599666Slinton extern int errno;
3609666Slinton extern _mycerror();
3619666Slinton 
3629666Slinton /*
36316611Ssam  * Initialize error information, setting defaults for handling errors.
3649666Slinton  */
3659666Slinton 
36633321Sdonn private ErrInfo *errinfo;
3679666Slinton 
36816611Ssam private initErrInfo ()
36916611Ssam {
37016611Ssam     integer i;
37116611Ssam 
37233321Sdonn     errinfo = alloc(sys_nerr, ErrInfo);
37316611Ssam     for (i = 0; i < sys_nerr; i++) {
37416611Ssam 	errinfo[i].func = ERR_CATCH;
37516611Ssam     }
37616611Ssam     errinfo[0].func = ERR_IGNORE;
37716611Ssam     errinfo[EPERM].func = ERR_IGNORE;
37816611Ssam     errinfo[ENOENT].func = ERR_IGNORE;
37916611Ssam     errinfo[ESRCH].func = ERR_IGNORE;
38016611Ssam     errinfo[EBADF].func = ERR_IGNORE;
38116611Ssam     errinfo[ENOTTY].func = ERR_IGNORE;
38216611Ssam     errinfo[EOPNOTSUPP].func = ERR_IGNORE;
38316611Ssam }
38416611Ssam 
3859666Slinton public syserr()
3869666Slinton {
38733321Sdonn     register ErrInfo *e;
3889666Slinton 
38916611Ssam     if (errno < 0 or errno > sys_nerr) {
39016611Ssam 	fatal("errno %d", errno);
39116611Ssam     } else {
39233321Sdonn 	if (errinfo == nil(ErrInfo *)) {
39316611Ssam 	    initErrInfo();
39416611Ssam 	}
39516611Ssam 	e = &(errinfo[errno]);
39616611Ssam 	if (e->func == ERR_CATCH) {
3979666Slinton 	    fatal(sys_errlist[errno]);
39816611Ssam 	} else if (e->func != ERR_IGNORE) {
39916611Ssam 	    (*e->func)();
4009666Slinton 	}
4019666Slinton     }
4029666Slinton }
4039666Slinton 
4049666Slinton /*
40516611Ssam  * Catcherrs' purpose is to initialize the errinfo table, get this module
40616611Ssam  * loaded, and make sure my cerror is loaded (only applicable when this is
40716611Ssam  * in a library).
4089666Slinton  */
4099666Slinton 
4109666Slinton public catcherrs()
4119666Slinton {
4129666Slinton     _mycerror();
41316611Ssam     initErrInfo();
4149666Slinton }
4159666Slinton 
4169666Slinton /*
41718221Slinton  * Turn off the error catching mechanism completely by having all errors
41818221Slinton  * ignored.  This is most useful between a fork and an exec.
41918221Slinton  */
42018221Slinton 
42118221Slinton public nocatcherrs()
42218221Slinton {
42318221Slinton     integer i;
42418221Slinton 
42518221Slinton     for (i = 0; i < sys_nerr; i++) {
42618221Slinton 	errinfo[i].func = ERR_IGNORE;
42718221Slinton     }
42818221Slinton }
42918221Slinton 
43018221Slinton /*
43133321Sdonn  * Change the action on receipt of an error, returning the previous action.
4329666Slinton  */
4339666Slinton 
43433321Sdonn public IntFunc *onsyserr(n, f)
4359666Slinton int n;
43633321Sdonn IntFunc *f;
4379666Slinton {
43833321Sdonn     IntFunc *oldf;
43933321Sdonn 
44033321Sdonn     if (errinfo == nil(ErrInfo *)) {
44116611Ssam 	initErrInfo();
44216611Ssam     }
44333321Sdonn     oldf = errinfo[n].func;
4449666Slinton     errinfo[n].func = f;
44533321Sdonn     return oldf;
4469666Slinton }
4479666Slinton 
4489666Slinton /*
4499666Slinton  * Print the message associated with the given signal.
4509666Slinton  * Like a "perror" for signals.
4519666Slinton  */
4529666Slinton 
45333321Sdonn #ifdef SIGWINCH
4549666Slinton public int sys_nsig = NSIG;
45533321Sdonn #else not 4.3 BSD
45633321Sdonn /*
45733321Sdonn  * This table is correct for 4.2-like systems but will
45833321Sdonn  * be inadequate for System V (which is the sort of
45933321Sdonn  * Unix that needs it!).
46033321Sdonn  */
46133321Sdonn public String sys_siglist[] = {
46233321Sdonn     "no signal",
46333321Sdonn     "hangup",
46433321Sdonn     "interrupt",
46533321Sdonn     "quit",
46633321Sdonn     "illegal instruction",
46733321Sdonn     "trace trap",
46833321Sdonn     "IOT instruction",
46933321Sdonn     "EMT instruction",
47033321Sdonn     "floating point exception",
47133321Sdonn     "kill",
47233321Sdonn     "bus error",
47333321Sdonn     "segmentation violation",
47433321Sdonn     "bad argument to system call",
47533321Sdonn     "broken pipe",
47633321Sdonn     "alarm clock",
47733321Sdonn     "soft kill",
47833321Sdonn     "urgent I/O condition",
47933321Sdonn     "stop signal not from tty",
48033321Sdonn     "stop signal from tty",
48133321Sdonn     "continue",
48233321Sdonn     "child termination",
48333321Sdonn     "stop (tty input)",
48433321Sdonn     "stop (tty output)",
48533321Sdonn     "possible input/output",
48633321Sdonn     "exceeded CPU time limit",
48733321Sdonn     "exceeded file size limit"
48833321Sdonn };
48933321Sdonn public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
49033321Sdonn #endif
4919666Slinton 
49216611Ssam public psignal(s, n)
4939666Slinton String s;
49416611Ssam integer n;
4959666Slinton {
49616611Ssam     String msg;
49716611Ssam     integer len;
49818538Sralph     extern String sys_siglist[];
4999666Slinton 
50016611Ssam     if (n >= 0 and n < sys_nsig) {
50116611Ssam 	msg = sys_siglist[n];
50216611Ssam     } else {
50316611Ssam 	msg = "Unknown signal";
5049666Slinton     }
50516611Ssam     len = strlen(s);
50616611Ssam     if (len > 0) {
50716611Ssam 	write(2, s, len);
5089666Slinton 	write(2, ": ", 2);
5099666Slinton     }
51016611Ssam     write(2, msg, strlen(msg));
5119666Slinton     write(2, "\n", 1);
5129666Slinton }
5139666Slinton 
5149666Slinton /*
5159666Slinton  * Standard error handling routines.
5169666Slinton  */
5179666Slinton 
5189666Slinton private short nerrs;
5199666Slinton private short nwarnings;
5209666Slinton 
5219666Slinton /*
5229666Slinton  * Main driver of error message reporting.
5239666Slinton  */
5249666Slinton 
5259666Slinton /* VARARGS2 */
5269666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5279666Slinton String errname;
52816611Ssam boolean shouldquit;
5299666Slinton String s;
5309666Slinton {
5319666Slinton     fflush(stdout);
5329666Slinton     if (shouldquit and cmdname != nil(String)) {
5339666Slinton 	fprintf(stderr, "%s: ", cmdname);
5349666Slinton     }
5359666Slinton     if (errfilename != nil(Filename)) {
5369666Slinton 	fprintf(stderr, "%s: ", errfilename);
5379666Slinton     }
5389666Slinton     if (errlineno > 0) {
5399666Slinton 	fprintf(stderr, "%d: ", errlineno);
5409666Slinton     }
5419666Slinton     if (errname != nil(String)) {
5429666Slinton 	fprintf(stderr, "%s: ", errname);
5439666Slinton     }
5449666Slinton     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5459666Slinton     putc('\n', stderr);
54633321Sdonn     fflush(stderr);
5479666Slinton     if (shouldquit) {
5489666Slinton 	quit(1);
5499666Slinton     }
5509666Slinton }
5519666Slinton 
5529666Slinton /*
5539666Slinton  * For when printf isn't sufficient for printing the error message ...
5549666Slinton  */
5559666Slinton 
5569666Slinton public beginerrmsg()
5579666Slinton {
5589666Slinton     fflush(stdout);
5599666Slinton     if (errfilename != nil(String)) {
5609666Slinton 	fprintf(stderr, "%s: ", errfilename);
5619666Slinton     }
5629666Slinton     if (errlineno > 0) {
5639666Slinton 	fprintf(stderr, "%d: ", errlineno);
5649666Slinton     }
5659666Slinton }
5669666Slinton 
5679666Slinton public enderrmsg()
5689666Slinton {
5699666Slinton     putc('\n', stderr);
57033321Sdonn     fflush(stderr);
5719666Slinton     erecover();
5729666Slinton }
5739666Slinton 
5749666Slinton /*
5759666Slinton  * The messages are listed in increasing order of seriousness.
5769666Slinton  *
5779666Slinton  * First are warnings.
5789666Slinton  */
5799666Slinton 
5809666Slinton /* VARARGS1 */
5819666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5829666Slinton String s;
5839666Slinton {
5849666Slinton     nwarnings++;
5859666Slinton     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5869666Slinton }
5879666Slinton 
5889666Slinton /*
5899666Slinton  * Errors are a little worse, they mean something is wrong,
5909666Slinton  * but not so bad that processing can't continue.
5919666Slinton  *
5929666Slinton  * The routine "erecover" is called to recover from the error,
5939666Slinton  * a default routine is provided that does nothing.
5949666Slinton  */
5959666Slinton 
5969666Slinton /* VARARGS1 */
5979666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5989666Slinton String s;
5999666Slinton {
6009666Slinton     extern erecover();
6019666Slinton 
6029666Slinton     nerrs++;
6039666Slinton     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6049666Slinton     erecover();
6059666Slinton }
6069666Slinton 
6079666Slinton /*
6089666Slinton  * Non-recoverable user error.
6099666Slinton  */
6109666Slinton 
6119666Slinton /* VARARGS1 */
6129666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6139666Slinton String s;
6149666Slinton {
6159666Slinton     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6169666Slinton }
6179666Slinton 
6189666Slinton /*
6199666Slinton  * Panics indicate an internal program error.
6209666Slinton  */
6219666Slinton 
6229666Slinton /* VARARGS1 */
6239666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6249666Slinton String s;
6259666Slinton {
6269666Slinton     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6279666Slinton }
6289666Slinton 
6299666Slinton short numerrors()
6309666Slinton {
6319666Slinton     short r;
6329666Slinton 
6339666Slinton     r = nerrs;
6349666Slinton     nerrs = 0;
6359666Slinton     return r;
6369666Slinton }
6379666Slinton 
6389666Slinton short numwarnings()
6399666Slinton {
6409666Slinton     short r;
6419666Slinton 
6429666Slinton     r = nwarnings;
6439666Slinton     nwarnings = 0;
6449666Slinton     return r;
6459666Slinton }
6469666Slinton 
6479666Slinton /*
6489666Slinton  * Recover from an error.
6499666Slinton  *
6509666Slinton  * This is the default routine which we aren't using since we have our own.
6519666Slinton  *
6529666Slinton public erecover()
6539666Slinton {
6549666Slinton }
6559666Slinton  *
6569666Slinton  */
6579666Slinton 
6589666Slinton /*
6599666Slinton  * Default way to quit from a program is just to exit.
6609666Slinton  *
6619666Slinton public quit(r)
6629666Slinton int r;
6639666Slinton {
6649666Slinton     exit(r);
6659666Slinton }
6669666Slinton  *
6679666Slinton  */
6689666Slinton 
6699666Slinton /*
6709666Slinton  * Compare n-byte areas pointed to by s1 and s2
6719666Slinton  * if n is 0 then compare up until one has a null byte.
6729666Slinton  */
6739666Slinton 
6749666Slinton public int cmp(s1, s2, n)
6759666Slinton register char *s1, *s2;
6769666Slinton register unsigned int n;
6779666Slinton {
6789666Slinton     if (s1 == nil(char *) || s2 == nil(char *)) {
6799666Slinton 	panic("cmp: nil pointer");
6809666Slinton     }
6819666Slinton     if (n == 0) {
6829666Slinton 	while (*s1 == *s2++) {
6839666Slinton 	    if (*s1++ == '\0') {
6849666Slinton 		return(0);
6859666Slinton 	    }
6869666Slinton 	}
6879666Slinton 	return(*s1 - *(s2-1));
6889666Slinton     } else {
6899666Slinton 	for (; n != 0; n--) {
6909666Slinton 	    if (*s1++ != *s2++) {
6919666Slinton 		return(*(s1-1) - *(s2-1));
6929666Slinton 	    }
6939666Slinton 	}
6949666Slinton 	return(0);
6959666Slinton     }
6969666Slinton }
6979666Slinton 
6989666Slinton /*
6999666Slinton  * Move n bytes from src to dest.
7009666Slinton  * If n is 0 move until a null is found.
7019666Slinton  */
7029666Slinton 
7039666Slinton public mov(src, dest, n)
7049666Slinton register char *src, *dest;
7059666Slinton register unsigned int n;
7069666Slinton {
7079666Slinton     if (src == nil(char *))
7089666Slinton 	panic("mov: nil source");
7099666Slinton     if (dest == nil(char *))
7109666Slinton 	panic("mov: nil destination");
7119666Slinton     if (n != 0) {
7129666Slinton 	for (; n != 0; n--) {
7139666Slinton 	    *dest++ = *src++;
7149666Slinton 	}
7159666Slinton     } else {
7169666Slinton 	while ((*dest++ = *src++) != '\0');
7179666Slinton     }
7189666Slinton }
71933321Sdonn 
72033321Sdonn #ifdef IRIS /* or in general for 4.2 - System V C library interface */
72133321Sdonn 
72233321Sdonn public bcopy (fromaddr, toaddr, n)
72333321Sdonn char *fromaddr, *toaddr;
72433321Sdonn int n;
72533321Sdonn {
72633321Sdonn     blt(toaddr, fromaddr, n);
72733321Sdonn }
72833321Sdonn 
72933321Sdonn public bzero (addr, n)
73033321Sdonn char *addr;
73133321Sdonn int n;
73233321Sdonn {
73333321Sdonn     register char *p, *q;
73433321Sdonn 
73533321Sdonn     p = addr;
73633321Sdonn     q = p + n;
73733321Sdonn     while (p < q) {
73833321Sdonn 	*p++ = '\0';
73933321Sdonn     }
74033321Sdonn }
74133321Sdonn 
74233321Sdonn #include <string.h>
74333321Sdonn 
74433321Sdonn public char *index (s, c)
74533321Sdonn char *s, c;
74633321Sdonn {
74733321Sdonn     return strchr(s, c);
74833321Sdonn }
74933321Sdonn 
75033321Sdonn public char *rindex (s, c)
75133321Sdonn char *s, c;
75233321Sdonn {
75333321Sdonn     return strrchr(s, c);
75433321Sdonn }
75533321Sdonn 
75633321Sdonn #endif
757