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