121606Sdist /*
238105Sbostic * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic * All rights reserved.
438105Sbostic *
542683Sbostic * %sccs.include.redist.c%
621606Sdist */
79666Slinton
821606Sdist #ifndef lint
9*46995Sbostic static char sccsid[] = "@(#)library.c 5.5 (Berkeley) 03/05/91";
1038105Sbostic #endif /* not lint */
1116611Ssam
129666Slinton /*
139666Slinton * General purpose routines.
149666Slinton */
159666Slinton
169666Slinton #include <stdio.h>
179666Slinton #include <errno.h>
189666Slinton #include <signal.h>
199666Slinton
209666Slinton #define public
219666Slinton #define private static
229666Slinton #define and &&
239666Slinton #define or ||
249666Slinton #define not !
259666Slinton #define ord(enumcon) ((int) enumcon)
269666Slinton #define nil(type) ((type) 0)
279666Slinton
2816611Ssam typedef int integer;
2916611Ssam typedef enum { FALSE, TRUE } boolean;
309666Slinton typedef char *String;
319666Slinton typedef FILE *File;
329666Slinton typedef String Filename;
339666Slinton
349666Slinton #undef FILE
359666Slinton
369666Slinton String cmdname; /* name of command for error messages */
379666Slinton Filename errfilename; /* current file associated with error */
389666Slinton short errlineno; /* line number associated with error */
399666Slinton
409666Slinton /*
419666Slinton * Definitions for doing memory allocation.
429666Slinton */
439666Slinton
449666Slinton extern char *malloc();
459666Slinton
469666Slinton #define alloc(n, type) ((type *) malloc((unsigned) (n) * sizeof(type)))
479666Slinton #define dispose(p) { free((char *) p); p = 0; }
489666Slinton
499666Slinton /*
509666Slinton * Macros for doing freads + fwrites.
519666Slinton */
529666Slinton
539666Slinton #define get(fp, var) fread((char *) &(var), sizeof(var), 1, fp)
549666Slinton #define put(fp, var) fwrite((char *) &(var), sizeof(var), 1, fp)
559666Slinton
569666Slinton /*
579666Slinton * String definitions.
589666Slinton */
599666Slinton
609666Slinton extern String strcpy(), index(), rindex();
619666Slinton extern int strlen();
629666Slinton
639666Slinton #define strdup(s) strcpy(malloc((unsigned) strlen(s) + 1), s)
649666Slinton #define streq(s1, s2) (strcmp(s1, s2) == 0)
659666Slinton
6633321Sdonn typedef int IntFunc();
679666Slinton
6833321Sdonn IntFunc *onsyserr();
6933321Sdonn
709666Slinton typedef struct {
7133321Sdonn IntFunc *func;
7233321Sdonn } ErrInfo;
739666Slinton
7433321Sdonn #define ERR_IGNORE ((IntFunc *) 0)
7533321Sdonn #define ERR_CATCH ((IntFunc *) 1)
769666Slinton
779666Slinton /*
789666Slinton * Call a program.
799666Slinton *
809666Slinton * Four entries:
819666Slinton *
829666Slinton * call, callv - call a program and wait for it, returning status
839666Slinton * back, backv - call a program and don't wait, returning process id
849666Slinton *
859666Slinton * The command's standard input and output are passed as FILE's.
869666Slinton */
879666Slinton
889666Slinton
8916611Ssam #define MAXNARGS 1000 /* unchecked upper limit on max num of arguments */
909666Slinton #define BADEXEC 127 /* exec fails */
919666Slinton
929666Slinton #define ischild(pid) ((pid) == 0)
939666Slinton
949666Slinton /* VARARGS3 */
call(name,in,out,args)959666Slinton public int call(name, in, out, args)
969666Slinton String name;
979666Slinton File in;
989666Slinton File out;
999666Slinton String args;
1009666Slinton {
1019666Slinton String *ap, *argp;
1029666Slinton String argv[MAXNARGS];
1039666Slinton
1049666Slinton argp = &argv[0];
1059666Slinton *argp++ = name;
1069666Slinton ap = &args;
1079666Slinton while (*ap != nil(String)) {
1089666Slinton *argp++ = *ap++;
1099666Slinton }
1109666Slinton *argp = nil(String);
1119666Slinton return callv(name, in, out, argv);
1129666Slinton }
1139666Slinton
1149666Slinton /* VARARGS3 */
back(name,in,out,args)1159666Slinton public int back(name, in, out, args)
1169666Slinton String name;
1179666Slinton File in;
1189666Slinton File out;
1199666Slinton String args;
1209666Slinton {
1219666Slinton String *ap, *argp;
1229666Slinton String argv[MAXNARGS];
1239666Slinton
1249666Slinton argp = &argv[0];
1259666Slinton *argp++ = name;
1269666Slinton ap = &args;
1279666Slinton while (*ap != nil(String)) {
1289666Slinton *argp++ = *ap++;
1299666Slinton }
1309666Slinton *argp = nil(String);
1319666Slinton return backv(name, in, out, argv);
1329666Slinton }
1339666Slinton
callv(name,in,out,argv)1349666Slinton public int callv(name, in, out, argv)
1359666Slinton String name;
1369666Slinton File in;
1379666Slinton File out;
1389666Slinton String *argv;
1399666Slinton {
1409666Slinton int pid, status;
1419666Slinton
1429666Slinton pid = backv(name, in, out, argv);
1439666Slinton pwait(pid, &status);
1449666Slinton return status;
1459666Slinton }
1469666Slinton
backv(name,in,out,argv)1479666Slinton public int backv(name, in, out, argv)
1489666Slinton String name;
1499666Slinton File in;
1509666Slinton File out;
1519666Slinton String *argv;
1529666Slinton {
1539666Slinton int pid;
1549666Slinton
1559666Slinton fflush(stdout);
1569666Slinton if (ischild(pid = fork())) {
1579666Slinton fswap(0, fileno(in));
1589666Slinton fswap(1, fileno(out));
1599666Slinton onsyserr(EACCES, ERR_IGNORE);
1609666Slinton execvp(name, argv);
1619666Slinton _exit(BADEXEC);
1629666Slinton }
1639666Slinton return pid;
1649666Slinton }
1659666Slinton
1669666Slinton /*
1679666Slinton * Swap file numbers so as to redirect standard input and output.
1689666Slinton */
1699666Slinton
fswap(oldfd,newfd)1709666Slinton private fswap(oldfd, newfd)
1719666Slinton int oldfd;
1729666Slinton int newfd;
1739666Slinton {
1749666Slinton if (oldfd != newfd) {
1759666Slinton close(oldfd);
1769666Slinton dup(newfd);
1779666Slinton close(newfd);
1789666Slinton }
1799666Slinton }
1809666Slinton
1819666Slinton /*
1829666Slinton * Invoke a shell on a command line.
1839666Slinton */
1849666Slinton
1859666Slinton #define DEF_SHELL "csh"
1869666Slinton
shell(s)1879666Slinton public shell(s)
1889666Slinton String s;
1899666Slinton {
1909666Slinton extern String getenv();
1919666Slinton String sh;
1929666Slinton
1939666Slinton if ((sh = getenv("SHELL")) == nil(String)) {
1949666Slinton sh = DEF_SHELL;
1959666Slinton }
1969666Slinton if (s != nil(String) and *s != '\0') {
1979666Slinton call(sh, stdin, stdout, "-c", s, 0);
1989666Slinton } else {
1999666Slinton call(sh, stdin, stdout, 0);
2009666Slinton }
2019666Slinton }
2029666Slinton
2039666Slinton /*
2049666Slinton * Wait for a process the right way. We wait for a particular
2059666Slinton * process and if any others come along in between, we remember them
2069666Slinton * in case they are eventually waited for.
2079666Slinton *
2089666Slinton * This routine is not very efficient when the number of processes
2099666Slinton * to be remembered is large.
21014394Slinton *
21114394Slinton * To deal with a kernel idiosyncrasy, we keep a list on the side
21214394Slinton * of "traced" processes, and do not notice them when waiting for
21314394Slinton * another process.
2149666Slinton */
2159666Slinton
2169666Slinton typedef struct pidlist {
2179666Slinton int pid;
2189666Slinton int status;
2199666Slinton struct pidlist *next;
2209666Slinton } Pidlist;
2219666Slinton
22214394Slinton private Pidlist *pidlist, *ptrclist, *pfind();
2239666Slinton
ptraced(pid)22414394Slinton public ptraced(pid)
22514394Slinton int pid;
22614394Slinton {
22714394Slinton Pidlist *p;
22814394Slinton
22914394Slinton p = alloc(1, Pidlist);
23014394Slinton p->pid = pid;
23114394Slinton p->next = ptrclist;
23214394Slinton ptrclist = p;
23314394Slinton }
23414394Slinton
unptraced(pid)23514394Slinton public unptraced(pid)
23614394Slinton int pid;
23714394Slinton {
23814394Slinton register Pidlist *p, *prev;
23914394Slinton
24014394Slinton prev = nil(Pidlist *);
24114394Slinton p = ptrclist;
24214394Slinton while (p != nil(Pidlist *) and p->pid != pid) {
24314394Slinton prev = p;
24414394Slinton p = p->next;
24514394Slinton }
24614394Slinton if (p != nil(Pidlist *)) {
24714394Slinton if (prev == nil(Pidlist *)) {
24814394Slinton ptrclist = p->next;
24914394Slinton } else {
25014394Slinton prev->next = p->next;
25114394Slinton }
25214394Slinton dispose(p);
25314394Slinton }
25414394Slinton }
25514394Slinton
isptraced(pid)25616611Ssam private boolean isptraced(pid)
25714394Slinton int pid;
25814394Slinton {
25914394Slinton register Pidlist *p;
26014394Slinton
26114394Slinton p = ptrclist;
26214394Slinton while (p != nil(Pidlist *) and p->pid != pid) {
26314394Slinton p = p->next;
26414394Slinton }
26516611Ssam return (boolean) (p != nil(Pidlist *));
26614394Slinton }
26714394Slinton
pwait(pid,statusp)2689666Slinton public pwait(pid, statusp)
2699666Slinton int pid, *statusp;
2709666Slinton {
27114393Slinton Pidlist *p;
27214393Slinton int pnum, status;
2739666Slinton
27414393Slinton p = pfind(pid);
27514393Slinton if (p != nil(Pidlist *)) {
27614393Slinton *statusp = p->status;
27714393Slinton dispose(p);
27814394Slinton } else {
27914394Slinton pnum = wait(&status);
28014394Slinton while (pnum != pid and pnum >= 0) {
28114394Slinton if (not isptraced(pnum)) {
28214394Slinton p = alloc(1, Pidlist);
28314394Slinton p->pid = pnum;
28414394Slinton p->status = status;
28514394Slinton p->next = pidlist;
28614394Slinton pidlist = p;
28714394Slinton }
28814394Slinton pnum = wait(&status);
2899666Slinton }
29014394Slinton if (pnum < 0) {
29114394Slinton p = pfind(pid);
29214394Slinton if (p == nil(Pidlist *)) {
29314394Slinton panic("pwait: pid %d not found", pid);
29414394Slinton }
29514394Slinton *statusp = p->status;
29614394Slinton dispose(p);
29714394Slinton } else {
29814394Slinton *statusp = status;
29914394Slinton }
30014393Slinton }
3019666Slinton }
3029666Slinton
3039666Slinton /*
3049666Slinton * Look for the given process id on the pidlist.
3059666Slinton *
3069666Slinton * Unlink it from list if found.
3079666Slinton */
3089666Slinton
pfind(pid)3099666Slinton private Pidlist *pfind(pid)
3109666Slinton int pid;
3119666Slinton {
3129666Slinton register Pidlist *p, *prev;
3139666Slinton
3149666Slinton prev = nil(Pidlist *);
3159666Slinton for (p = pidlist; p != nil(Pidlist *); p = p->next) {
3169666Slinton if (p->pid == pid) {
3179666Slinton break;
3189666Slinton }
3199666Slinton prev = p;
3209666Slinton }
3219666Slinton if (p != nil(Pidlist *)) {
3229666Slinton if (prev == nil(Pidlist *)) {
3239666Slinton pidlist = p->next;
3249666Slinton } else {
3259666Slinton prev->next = p->next;
3269666Slinton }
3279666Slinton }
3289666Slinton return p;
3299666Slinton }
3309666Slinton
3319666Slinton /*
3329666Slinton * System call error handler.
3339666Slinton *
3349666Slinton * The syserr routine is called when a system call is about to
3359666Slinton * set the c-bit to report an error. Certain errors are caught
3369666Slinton * and cause the process to print a message and immediately exit.
3379666Slinton */
3389666Slinton
3399666Slinton extern int sys_nerr;
3409666Slinton extern char *sys_errlist[];
3419666Slinton
3429666Slinton /*
3439666Slinton * Before calling syserr, the integer errno is set to contain the
3449666Slinton * number of the error. The routine "_mycerror" is a dummy which
3459666Slinton * is used to force the loader to get my version of cerror rather
3469666Slinton * than the usual one.
3479666Slinton */
3489666Slinton
3499666Slinton extern int errno;
3509666Slinton extern _mycerror();
3519666Slinton
3529666Slinton /*
35316611Ssam * Initialize error information, setting defaults for handling errors.
3549666Slinton */
3559666Slinton
35633321Sdonn private ErrInfo *errinfo;
3579666Slinton
initErrInfo()35816611Ssam private initErrInfo ()
35916611Ssam {
36016611Ssam integer i;
36116611Ssam
36233321Sdonn errinfo = alloc(sys_nerr, ErrInfo);
36316611Ssam for (i = 0; i < sys_nerr; i++) {
36416611Ssam errinfo[i].func = ERR_CATCH;
36516611Ssam }
36616611Ssam errinfo[0].func = ERR_IGNORE;
36716611Ssam errinfo[EPERM].func = ERR_IGNORE;
36816611Ssam errinfo[ENOENT].func = ERR_IGNORE;
36916611Ssam errinfo[ESRCH].func = ERR_IGNORE;
37016611Ssam errinfo[EBADF].func = ERR_IGNORE;
37116611Ssam errinfo[ENOTTY].func = ERR_IGNORE;
37216611Ssam errinfo[EOPNOTSUPP].func = ERR_IGNORE;
37316611Ssam }
37416611Ssam
syserr()3759666Slinton public syserr()
3769666Slinton {
37733321Sdonn register ErrInfo *e;
3789666Slinton
37916611Ssam if (errno < 0 or errno > sys_nerr) {
38016611Ssam fatal("errno %d", errno);
38116611Ssam } else {
38233321Sdonn if (errinfo == nil(ErrInfo *)) {
38316611Ssam initErrInfo();
38416611Ssam }
38516611Ssam e = &(errinfo[errno]);
38616611Ssam if (e->func == ERR_CATCH) {
3879666Slinton fatal(sys_errlist[errno]);
38816611Ssam } else if (e->func != ERR_IGNORE) {
38916611Ssam (*e->func)();
3909666Slinton }
3919666Slinton }
3929666Slinton }
3939666Slinton
3949666Slinton /*
39516611Ssam * Catcherrs' purpose is to initialize the errinfo table, get this module
39616611Ssam * loaded, and make sure my cerror is loaded (only applicable when this is
39716611Ssam * in a library).
3989666Slinton */
3999666Slinton
catcherrs()4009666Slinton public catcherrs()
4019666Slinton {
4029666Slinton _mycerror();
40316611Ssam initErrInfo();
4049666Slinton }
4059666Slinton
4069666Slinton /*
40718221Slinton * Turn off the error catching mechanism completely by having all errors
40818221Slinton * ignored. This is most useful between a fork and an exec.
40918221Slinton */
41018221Slinton
nocatcherrs()41118221Slinton public nocatcherrs()
41218221Slinton {
41318221Slinton integer i;
41418221Slinton
41518221Slinton for (i = 0; i < sys_nerr; i++) {
41618221Slinton errinfo[i].func = ERR_IGNORE;
41718221Slinton }
41818221Slinton }
41918221Slinton
42018221Slinton /*
42133321Sdonn * Change the action on receipt of an error, returning the previous action.
4229666Slinton */
4239666Slinton
onsyserr(n,f)42433321Sdonn public IntFunc *onsyserr(n, f)
4259666Slinton int n;
42633321Sdonn IntFunc *f;
4279666Slinton {
42833321Sdonn IntFunc *oldf;
42933321Sdonn
43033321Sdonn if (errinfo == nil(ErrInfo *)) {
43116611Ssam initErrInfo();
43216611Ssam }
43333321Sdonn oldf = errinfo[n].func;
4349666Slinton errinfo[n].func = f;
43533321Sdonn return oldf;
4369666Slinton }
4379666Slinton
4389666Slinton /*
4399666Slinton * Print the message associated with the given signal.
4409666Slinton * Like a "perror" for signals.
4419666Slinton */
4429666Slinton
44333321Sdonn #ifdef SIGWINCH
4449666Slinton public int sys_nsig = NSIG;
44533321Sdonn #else not 4.3 BSD
44633321Sdonn /*
44733321Sdonn * This table is correct for 4.2-like systems but will
44833321Sdonn * be inadequate for System V (which is the sort of
44933321Sdonn * Unix that needs it!).
45033321Sdonn */
45133321Sdonn public String sys_siglist[] = {
45233321Sdonn "no signal",
45333321Sdonn "hangup",
45433321Sdonn "interrupt",
45533321Sdonn "quit",
45633321Sdonn "illegal instruction",
45733321Sdonn "trace trap",
45833321Sdonn "IOT instruction",
45933321Sdonn "EMT instruction",
46033321Sdonn "floating point exception",
46133321Sdonn "kill",
46233321Sdonn "bus error",
46333321Sdonn "segmentation violation",
46433321Sdonn "bad argument to system call",
46533321Sdonn "broken pipe",
46633321Sdonn "alarm clock",
46733321Sdonn "soft kill",
46833321Sdonn "urgent I/O condition",
46933321Sdonn "stop signal not from tty",
47033321Sdonn "stop signal from tty",
47133321Sdonn "continue",
47233321Sdonn "child termination",
47333321Sdonn "stop (tty input)",
47433321Sdonn "stop (tty output)",
47533321Sdonn "possible input/output",
47633321Sdonn "exceeded CPU time limit",
47733321Sdonn "exceeded file size limit"
47833321Sdonn };
47933321Sdonn public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
4809666Slinton
psignal(s,n)48116611Ssam public psignal(s, n)
4829666Slinton String s;
48316611Ssam integer n;
4849666Slinton {
48516611Ssam String msg;
48616611Ssam integer len;
48718538Sralph extern String sys_siglist[];
4889666Slinton
48916611Ssam if (n >= 0 and n < sys_nsig) {
49016611Ssam msg = sys_siglist[n];
49116611Ssam } else {
49216611Ssam msg = "Unknown signal";
4939666Slinton }
49416611Ssam len = strlen(s);
49516611Ssam if (len > 0) {
49616611Ssam write(2, s, len);
4979666Slinton write(2, ": ", 2);
4989666Slinton }
49916611Ssam write(2, msg, strlen(msg));
5009666Slinton write(2, "\n", 1);
5019666Slinton }
502*46995Sbostic #endif
5039666Slinton
5049666Slinton /*
5059666Slinton * Standard error handling routines.
5069666Slinton */
5079666Slinton
5089666Slinton private short nerrs;
5099666Slinton private short nwarnings;
5109666Slinton
5119666Slinton /*
5129666Slinton * Main driver of error message reporting.
5139666Slinton */
5149666Slinton
5159666Slinton /* VARARGS2 */
errmsg(errname,shouldquit,s,a,b,c,d,e,f,g,h,i,j,k,l,m)5169666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5179666Slinton String errname;
51816611Ssam boolean shouldquit;
5199666Slinton String s;
5209666Slinton {
5219666Slinton fflush(stdout);
5229666Slinton if (shouldquit and cmdname != nil(String)) {
5239666Slinton fprintf(stderr, "%s: ", cmdname);
5249666Slinton }
5259666Slinton if (errfilename != nil(Filename)) {
5269666Slinton fprintf(stderr, "%s: ", errfilename);
5279666Slinton }
5289666Slinton if (errlineno > 0) {
5299666Slinton fprintf(stderr, "%d: ", errlineno);
5309666Slinton }
5319666Slinton if (errname != nil(String)) {
5329666Slinton fprintf(stderr, "%s: ", errname);
5339666Slinton }
5349666Slinton fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5359666Slinton putc('\n', stderr);
53633321Sdonn fflush(stderr);
5379666Slinton if (shouldquit) {
5389666Slinton quit(1);
5399666Slinton }
5409666Slinton }
5419666Slinton
5429666Slinton /*
5439666Slinton * For when printf isn't sufficient for printing the error message ...
5449666Slinton */
5459666Slinton
beginerrmsg()5469666Slinton public beginerrmsg()
5479666Slinton {
5489666Slinton fflush(stdout);
5499666Slinton if (errfilename != nil(String)) {
5509666Slinton fprintf(stderr, "%s: ", errfilename);
5519666Slinton }
5529666Slinton if (errlineno > 0) {
5539666Slinton fprintf(stderr, "%d: ", errlineno);
5549666Slinton }
5559666Slinton }
5569666Slinton
enderrmsg()5579666Slinton public enderrmsg()
5589666Slinton {
5599666Slinton putc('\n', stderr);
56033321Sdonn fflush(stderr);
5619666Slinton erecover();
5629666Slinton }
5639666Slinton
5649666Slinton /*
5659666Slinton * The messages are listed in increasing order of seriousness.
5669666Slinton *
5679666Slinton * First are warnings.
5689666Slinton */
5699666Slinton
5709666Slinton /* VARARGS1 */
warning(s,a,b,c,d,e,f,g,h,i,j,k,l,m)5719666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5729666Slinton String s;
5739666Slinton {
5749666Slinton nwarnings++;
5759666Slinton errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5769666Slinton }
5779666Slinton
5789666Slinton /*
5799666Slinton * Errors are a little worse, they mean something is wrong,
5809666Slinton * but not so bad that processing can't continue.
5819666Slinton *
5829666Slinton * The routine "erecover" is called to recover from the error,
5839666Slinton * a default routine is provided that does nothing.
5849666Slinton */
5859666Slinton
5869666Slinton /* VARARGS1 */
error(s,a,b,c,d,e,f,g,h,i,j,k,l,m)5879666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
5889666Slinton String s;
5899666Slinton {
5909666Slinton extern erecover();
5919666Slinton
5929666Slinton nerrs++;
5939666Slinton errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
5949666Slinton erecover();
5959666Slinton }
5969666Slinton
5979666Slinton /*
5989666Slinton * Non-recoverable user error.
5999666Slinton */
6009666Slinton
6019666Slinton /* VARARGS1 */
fatal(s,a,b,c,d,e,f,g,h,i,j,k,l,m)6029666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6039666Slinton String s;
6049666Slinton {
6059666Slinton errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6069666Slinton }
6079666Slinton
6089666Slinton /*
6099666Slinton * Panics indicate an internal program error.
6109666Slinton */
6119666Slinton
6129666Slinton /* VARARGS1 */
panic(s,a,b,c,d,e,f,g,h,i,j,k,l,m)6139666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
6149666Slinton String s;
6159666Slinton {
6169666Slinton errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
6179666Slinton }
6189666Slinton
numerrors()6199666Slinton short numerrors()
6209666Slinton {
6219666Slinton short r;
6229666Slinton
6239666Slinton r = nerrs;
6249666Slinton nerrs = 0;
6259666Slinton return r;
6269666Slinton }
6279666Slinton
numwarnings()6289666Slinton short numwarnings()
6299666Slinton {
6309666Slinton short r;
6319666Slinton
6329666Slinton r = nwarnings;
6339666Slinton nwarnings = 0;
6349666Slinton return r;
6359666Slinton }
6369666Slinton
6379666Slinton /*
6389666Slinton * Recover from an error.
6399666Slinton *
6409666Slinton * This is the default routine which we aren't using since we have our own.
6419666Slinton *
6429666Slinton public erecover()
6439666Slinton {
6449666Slinton }
6459666Slinton *
6469666Slinton */
6479666Slinton
6489666Slinton /*
6499666Slinton * Default way to quit from a program is just to exit.
6509666Slinton *
6519666Slinton public quit(r)
6529666Slinton int r;
6539666Slinton {
6549666Slinton exit(r);
6559666Slinton }
6569666Slinton *
6579666Slinton */
6589666Slinton
6599666Slinton /*
6609666Slinton * Compare n-byte areas pointed to by s1 and s2
6619666Slinton * if n is 0 then compare up until one has a null byte.
6629666Slinton */
6639666Slinton
cmp(s1,s2,n)6649666Slinton public int cmp(s1, s2, n)
6659666Slinton register char *s1, *s2;
6669666Slinton register unsigned int n;
6679666Slinton {
6689666Slinton if (s1 == nil(char *) || s2 == nil(char *)) {
6699666Slinton panic("cmp: nil pointer");
6709666Slinton }
6719666Slinton if (n == 0) {
6729666Slinton while (*s1 == *s2++) {
6739666Slinton if (*s1++ == '\0') {
6749666Slinton return(0);
6759666Slinton }
6769666Slinton }
6779666Slinton return(*s1 - *(s2-1));
6789666Slinton } else {
6799666Slinton for (; n != 0; n--) {
6809666Slinton if (*s1++ != *s2++) {
6819666Slinton return(*(s1-1) - *(s2-1));
6829666Slinton }
6839666Slinton }
6849666Slinton return(0);
6859666Slinton }
6869666Slinton }
6879666Slinton
6889666Slinton /*
6899666Slinton * Move n bytes from src to dest.
6909666Slinton * If n is 0 move until a null is found.
6919666Slinton */
6929666Slinton
mov(src,dest,n)6939666Slinton public mov(src, dest, n)
6949666Slinton register char *src, *dest;
6959666Slinton register unsigned int n;
6969666Slinton {
6979666Slinton if (src == nil(char *))
6989666Slinton panic("mov: nil source");
6999666Slinton if (dest == nil(char *))
7009666Slinton panic("mov: nil destination");
7019666Slinton if (n != 0) {
7029666Slinton for (; n != 0; n--) {
7039666Slinton *dest++ = *src++;
7049666Slinton }
7059666Slinton } else {
7069666Slinton while ((*dest++ = *src++) != '\0');
7079666Slinton }
7089666Slinton }
70933321Sdonn
71033321Sdonn #ifdef IRIS /* or in general for 4.2 - System V C library interface */
71133321Sdonn
bcopy(fromaddr,toaddr,n)71233321Sdonn public bcopy (fromaddr, toaddr, n)
71333321Sdonn char *fromaddr, *toaddr;
71433321Sdonn int n;
71533321Sdonn {
71633321Sdonn blt(toaddr, fromaddr, n);
71733321Sdonn }
71833321Sdonn
bzero(addr,n)71933321Sdonn public bzero (addr, n)
72033321Sdonn char *addr;
72133321Sdonn int n;
72233321Sdonn {
72333321Sdonn register char *p, *q;
72433321Sdonn
72533321Sdonn p = addr;
72633321Sdonn q = p + n;
72733321Sdonn while (p < q) {
72833321Sdonn *p++ = '\0';
72933321Sdonn }
73033321Sdonn }
73133321Sdonn
73233321Sdonn #include <string.h>
73333321Sdonn
index(s,c)73433321Sdonn public char *index (s, c)
73533321Sdonn char *s, c;
73633321Sdonn {
73733321Sdonn return strchr(s, c);
73833321Sdonn }
73933321Sdonn
rindex(s,c)74033321Sdonn public char *rindex (s, c)
74133321Sdonn char *s, c;
74233321Sdonn {
74333321Sdonn return strrchr(s, c);
74433321Sdonn }
74533321Sdonn
74633321Sdonn #endif
747