121606Sdist /* 221606Sdist * Copyright (c) 1983 Regents of the University of California. 321606Sdist * All rights reserved. The Berkeley software License Agreement 421606Sdist * specifies the terms and conditions for redistribution. 521606Sdist */ 69666Slinton 721606Sdist #ifndef lint 8*33321Sdonn static char sccsid[] = "@(#)library.c 5.2 (Berkeley) 01/12/88"; 921606Sdist #endif not lint 1016611Ssam 11*33321Sdonn static char rcsid[] = "$Header: library.c,v 1.2 87/03/25 20:50:14 donn Exp $"; 1218221Slinton 139666Slinton /* 149666Slinton * General purpose routines. 159666Slinton */ 169666Slinton 179666Slinton #include <stdio.h> 189666Slinton #include <errno.h> 199666Slinton #include <signal.h> 209666Slinton 219666Slinton #define public 229666Slinton #define private static 239666Slinton #define and && 249666Slinton #define or || 259666Slinton #define not ! 269666Slinton #define ord(enumcon) ((int) enumcon) 279666Slinton #define nil(type) ((type) 0) 289666Slinton 2916611Ssam typedef int integer; 3016611Ssam typedef enum { FALSE, TRUE } boolean; 319666Slinton typedef char *String; 329666Slinton typedef FILE *File; 339666Slinton typedef String Filename; 349666Slinton 359666Slinton #undef FILE 369666Slinton 379666Slinton String cmdname; /* name of command for error messages */ 389666Slinton Filename errfilename; /* current file associated with error */ 399666Slinton short errlineno; /* line number associated with error */ 409666Slinton 419666Slinton /* 429666Slinton * Definitions for doing memory allocation. 439666Slinton */ 449666Slinton 459666Slinton extern char *malloc(); 469666Slinton 479666Slinton #define alloc(n, type) ((type *) malloc((unsigned) (n) * sizeof(type))) 489666Slinton #define dispose(p) { free((char *) p); p = 0; } 499666Slinton 509666Slinton /* 519666Slinton * Macros for doing freads + fwrites. 529666Slinton */ 539666Slinton 549666Slinton #define get(fp, var) fread((char *) &(var), sizeof(var), 1, fp) 559666Slinton #define put(fp, var) fwrite((char *) &(var), sizeof(var), 1, fp) 569666Slinton 579666Slinton /* 589666Slinton * String definitions. 599666Slinton */ 609666Slinton 619666Slinton extern String strcpy(), index(), rindex(); 629666Slinton extern int strlen(); 639666Slinton 649666Slinton #define strdup(s) strcpy(malloc((unsigned) strlen(s) + 1), s) 659666Slinton #define streq(s1, s2) (strcmp(s1, s2) == 0) 669666Slinton 67*33321Sdonn typedef int IntFunc(); 689666Slinton 69*33321Sdonn IntFunc *onsyserr(); 70*33321Sdonn 719666Slinton typedef struct { 72*33321Sdonn IntFunc *func; 73*33321Sdonn } ErrInfo; 749666Slinton 75*33321Sdonn #define ERR_IGNORE ((IntFunc *) 0) 76*33321Sdonn #define ERR_CATCH ((IntFunc *) 1) 779666Slinton 789666Slinton /* 799666Slinton * Call a program. 809666Slinton * 819666Slinton * Four entries: 829666Slinton * 839666Slinton * call, callv - call a program and wait for it, returning status 849666Slinton * back, backv - call a program and don't wait, returning process id 859666Slinton * 869666Slinton * The command's standard input and output are passed as FILE's. 879666Slinton */ 889666Slinton 899666Slinton 9016611Ssam #define MAXNARGS 1000 /* unchecked upper limit on max num of arguments */ 919666Slinton #define BADEXEC 127 /* exec fails */ 929666Slinton 939666Slinton #define ischild(pid) ((pid) == 0) 949666Slinton 959666Slinton /* VARARGS3 */ 969666Slinton public int call(name, in, out, args) 979666Slinton String name; 989666Slinton File in; 999666Slinton File out; 1009666Slinton String args; 1019666Slinton { 1029666Slinton String *ap, *argp; 1039666Slinton String argv[MAXNARGS]; 1049666Slinton 1059666Slinton argp = &argv[0]; 1069666Slinton *argp++ = name; 1079666Slinton ap = &args; 1089666Slinton while (*ap != nil(String)) { 1099666Slinton *argp++ = *ap++; 1109666Slinton } 1119666Slinton *argp = nil(String); 1129666Slinton return callv(name, in, out, argv); 1139666Slinton } 1149666Slinton 1159666Slinton /* VARARGS3 */ 1169666Slinton public int back(name, in, out, args) 1179666Slinton String name; 1189666Slinton File in; 1199666Slinton File out; 1209666Slinton String args; 1219666Slinton { 1229666Slinton String *ap, *argp; 1239666Slinton String argv[MAXNARGS]; 1249666Slinton 1259666Slinton argp = &argv[0]; 1269666Slinton *argp++ = name; 1279666Slinton ap = &args; 1289666Slinton while (*ap != nil(String)) { 1299666Slinton *argp++ = *ap++; 1309666Slinton } 1319666Slinton *argp = nil(String); 1329666Slinton return backv(name, in, out, argv); 1339666Slinton } 1349666Slinton 1359666Slinton public int callv(name, in, out, argv) 1369666Slinton String name; 1379666Slinton File in; 1389666Slinton File out; 1399666Slinton String *argv; 1409666Slinton { 1419666Slinton int pid, status; 1429666Slinton 1439666Slinton pid = backv(name, in, out, argv); 1449666Slinton pwait(pid, &status); 1459666Slinton return status; 1469666Slinton } 1479666Slinton 1489666Slinton public int backv(name, in, out, argv) 1499666Slinton String name; 1509666Slinton File in; 1519666Slinton File out; 1529666Slinton String *argv; 1539666Slinton { 1549666Slinton int pid; 1559666Slinton 1569666Slinton fflush(stdout); 1579666Slinton if (ischild(pid = fork())) { 1589666Slinton fswap(0, fileno(in)); 1599666Slinton fswap(1, fileno(out)); 1609666Slinton onsyserr(EACCES, ERR_IGNORE); 1619666Slinton execvp(name, argv); 1629666Slinton _exit(BADEXEC); 1639666Slinton } 1649666Slinton return pid; 1659666Slinton } 1669666Slinton 1679666Slinton /* 1689666Slinton * Swap file numbers so as to redirect standard input and output. 1699666Slinton */ 1709666Slinton 1719666Slinton private fswap(oldfd, newfd) 1729666Slinton int oldfd; 1739666Slinton int newfd; 1749666Slinton { 1759666Slinton if (oldfd != newfd) { 1769666Slinton close(oldfd); 1779666Slinton dup(newfd); 1789666Slinton close(newfd); 1799666Slinton } 1809666Slinton } 1819666Slinton 1829666Slinton /* 1839666Slinton * Invoke a shell on a command line. 1849666Slinton */ 1859666Slinton 1869666Slinton #define DEF_SHELL "csh" 1879666Slinton 1889666Slinton public shell(s) 1899666Slinton String s; 1909666Slinton { 1919666Slinton extern String getenv(); 1929666Slinton String sh; 1939666Slinton 1949666Slinton if ((sh = getenv("SHELL")) == nil(String)) { 1959666Slinton sh = DEF_SHELL; 1969666Slinton } 1979666Slinton if (s != nil(String) and *s != '\0') { 1989666Slinton call(sh, stdin, stdout, "-c", s, 0); 1999666Slinton } else { 2009666Slinton call(sh, stdin, stdout, 0); 2019666Slinton } 2029666Slinton } 2039666Slinton 2049666Slinton /* 2059666Slinton * Wait for a process the right way. We wait for a particular 2069666Slinton * process and if any others come along in between, we remember them 2079666Slinton * in case they are eventually waited for. 2089666Slinton * 2099666Slinton * This routine is not very efficient when the number of processes 2109666Slinton * to be remembered is large. 21114394Slinton * 21214394Slinton * To deal with a kernel idiosyncrasy, we keep a list on the side 21314394Slinton * of "traced" processes, and do not notice them when waiting for 21414394Slinton * another process. 2159666Slinton */ 2169666Slinton 2179666Slinton typedef struct pidlist { 2189666Slinton int pid; 2199666Slinton int status; 2209666Slinton struct pidlist *next; 2219666Slinton } Pidlist; 2229666Slinton 22314394Slinton private Pidlist *pidlist, *ptrclist, *pfind(); 2249666Slinton 22514394Slinton public ptraced(pid) 22614394Slinton int pid; 22714394Slinton { 22814394Slinton Pidlist *p; 22914394Slinton 23014394Slinton p = alloc(1, Pidlist); 23114394Slinton p->pid = pid; 23214394Slinton p->next = ptrclist; 23314394Slinton ptrclist = p; 23414394Slinton } 23514394Slinton 23614394Slinton public unptraced(pid) 23714394Slinton int pid; 23814394Slinton { 23914394Slinton register Pidlist *p, *prev; 24014394Slinton 24114394Slinton prev = nil(Pidlist *); 24214394Slinton p = ptrclist; 24314394Slinton while (p != nil(Pidlist *) and p->pid != pid) { 24414394Slinton prev = p; 24514394Slinton p = p->next; 24614394Slinton } 24714394Slinton if (p != nil(Pidlist *)) { 24814394Slinton if (prev == nil(Pidlist *)) { 24914394Slinton ptrclist = p->next; 25014394Slinton } else { 25114394Slinton prev->next = p->next; 25214394Slinton } 25314394Slinton dispose(p); 25414394Slinton } 25514394Slinton } 25614394Slinton 25716611Ssam private boolean isptraced(pid) 25814394Slinton int pid; 25914394Slinton { 26014394Slinton register Pidlist *p; 26114394Slinton 26214394Slinton p = ptrclist; 26314394Slinton while (p != nil(Pidlist *) and p->pid != pid) { 26414394Slinton p = p->next; 26514394Slinton } 26616611Ssam return (boolean) (p != nil(Pidlist *)); 26714394Slinton } 26814394Slinton 2699666Slinton public pwait(pid, statusp) 2709666Slinton int pid, *statusp; 2719666Slinton { 27214393Slinton Pidlist *p; 27314393Slinton int pnum, status; 2749666Slinton 27514393Slinton p = pfind(pid); 27614393Slinton if (p != nil(Pidlist *)) { 27714393Slinton *statusp = p->status; 27814393Slinton dispose(p); 27914394Slinton } else { 28014394Slinton pnum = wait(&status); 28114394Slinton while (pnum != pid and pnum >= 0) { 28214394Slinton if (not isptraced(pnum)) { 28314394Slinton p = alloc(1, Pidlist); 28414394Slinton p->pid = pnum; 28514394Slinton p->status = status; 28614394Slinton p->next = pidlist; 28714394Slinton pidlist = p; 28814394Slinton } 28914394Slinton pnum = wait(&status); 2909666Slinton } 29114394Slinton if (pnum < 0) { 29214394Slinton p = pfind(pid); 29314394Slinton if (p == nil(Pidlist *)) { 29414394Slinton panic("pwait: pid %d not found", pid); 29514394Slinton } 29614394Slinton *statusp = p->status; 29714394Slinton dispose(p); 29814394Slinton } else { 29914394Slinton *statusp = status; 30014394Slinton } 30114393Slinton } 3029666Slinton } 3039666Slinton 3049666Slinton /* 3059666Slinton * Look for the given process id on the pidlist. 3069666Slinton * 3079666Slinton * Unlink it from list if found. 3089666Slinton */ 3099666Slinton 3109666Slinton private Pidlist *pfind(pid) 3119666Slinton int pid; 3129666Slinton { 3139666Slinton register Pidlist *p, *prev; 3149666Slinton 3159666Slinton prev = nil(Pidlist *); 3169666Slinton for (p = pidlist; p != nil(Pidlist *); p = p->next) { 3179666Slinton if (p->pid == pid) { 3189666Slinton break; 3199666Slinton } 3209666Slinton prev = p; 3219666Slinton } 3229666Slinton if (p != nil(Pidlist *)) { 3239666Slinton if (prev == nil(Pidlist *)) { 3249666Slinton pidlist = p->next; 3259666Slinton } else { 3269666Slinton prev->next = p->next; 3279666Slinton } 3289666Slinton } 3299666Slinton return p; 3309666Slinton } 3319666Slinton 3329666Slinton /* 3339666Slinton * System call error handler. 3349666Slinton * 3359666Slinton * The syserr routine is called when a system call is about to 3369666Slinton * set the c-bit to report an error. Certain errors are caught 3379666Slinton * and cause the process to print a message and immediately exit. 3389666Slinton */ 3399666Slinton 3409666Slinton extern int sys_nerr; 3419666Slinton extern char *sys_errlist[]; 3429666Slinton 3439666Slinton /* 3449666Slinton * Before calling syserr, the integer errno is set to contain the 3459666Slinton * number of the error. The routine "_mycerror" is a dummy which 3469666Slinton * is used to force the loader to get my version of cerror rather 3479666Slinton * than the usual one. 3489666Slinton */ 3499666Slinton 3509666Slinton extern int errno; 3519666Slinton extern _mycerror(); 3529666Slinton 3539666Slinton /* 35416611Ssam * Initialize error information, setting defaults for handling errors. 3559666Slinton */ 3569666Slinton 357*33321Sdonn private ErrInfo *errinfo; 3589666Slinton 35916611Ssam private initErrInfo () 36016611Ssam { 36116611Ssam integer i; 36216611Ssam 363*33321Sdonn errinfo = alloc(sys_nerr, ErrInfo); 36416611Ssam for (i = 0; i < sys_nerr; i++) { 36516611Ssam errinfo[i].func = ERR_CATCH; 36616611Ssam } 36716611Ssam errinfo[0].func = ERR_IGNORE; 36816611Ssam errinfo[EPERM].func = ERR_IGNORE; 36916611Ssam errinfo[ENOENT].func = ERR_IGNORE; 37016611Ssam errinfo[ESRCH].func = ERR_IGNORE; 37116611Ssam errinfo[EBADF].func = ERR_IGNORE; 37216611Ssam errinfo[ENOTTY].func = ERR_IGNORE; 37316611Ssam errinfo[EOPNOTSUPP].func = ERR_IGNORE; 37416611Ssam } 37516611Ssam 3769666Slinton public syserr() 3779666Slinton { 378*33321Sdonn register ErrInfo *e; 3799666Slinton 38016611Ssam if (errno < 0 or errno > sys_nerr) { 38116611Ssam fatal("errno %d", errno); 38216611Ssam } else { 383*33321Sdonn if (errinfo == nil(ErrInfo *)) { 38416611Ssam initErrInfo(); 38516611Ssam } 38616611Ssam e = &(errinfo[errno]); 38716611Ssam if (e->func == ERR_CATCH) { 3889666Slinton fatal(sys_errlist[errno]); 38916611Ssam } else if (e->func != ERR_IGNORE) { 39016611Ssam (*e->func)(); 3919666Slinton } 3929666Slinton } 3939666Slinton } 3949666Slinton 3959666Slinton /* 39616611Ssam * Catcherrs' purpose is to initialize the errinfo table, get this module 39716611Ssam * loaded, and make sure my cerror is loaded (only applicable when this is 39816611Ssam * in a library). 3999666Slinton */ 4009666Slinton 4019666Slinton public catcherrs() 4029666Slinton { 4039666Slinton _mycerror(); 40416611Ssam initErrInfo(); 4059666Slinton } 4069666Slinton 4079666Slinton /* 40818221Slinton * Turn off the error catching mechanism completely by having all errors 40918221Slinton * ignored. This is most useful between a fork and an exec. 41018221Slinton */ 41118221Slinton 41218221Slinton public nocatcherrs() 41318221Slinton { 41418221Slinton integer i; 41518221Slinton 41618221Slinton for (i = 0; i < sys_nerr; i++) { 41718221Slinton errinfo[i].func = ERR_IGNORE; 41818221Slinton } 41918221Slinton } 42018221Slinton 42118221Slinton /* 422*33321Sdonn * Change the action on receipt of an error, returning the previous action. 4239666Slinton */ 4249666Slinton 425*33321Sdonn public IntFunc *onsyserr(n, f) 4269666Slinton int n; 427*33321Sdonn IntFunc *f; 4289666Slinton { 429*33321Sdonn IntFunc *oldf; 430*33321Sdonn 431*33321Sdonn if (errinfo == nil(ErrInfo *)) { 43216611Ssam initErrInfo(); 43316611Ssam } 434*33321Sdonn oldf = errinfo[n].func; 4359666Slinton errinfo[n].func = f; 436*33321Sdonn return oldf; 4379666Slinton } 4389666Slinton 4399666Slinton /* 4409666Slinton * Print the message associated with the given signal. 4419666Slinton * Like a "perror" for signals. 4429666Slinton */ 4439666Slinton 444*33321Sdonn #ifdef SIGWINCH 4459666Slinton public int sys_nsig = NSIG; 446*33321Sdonn #else not 4.3 BSD 447*33321Sdonn /* 448*33321Sdonn * This table is correct for 4.2-like systems but will 449*33321Sdonn * be inadequate for System V (which is the sort of 450*33321Sdonn * Unix that needs it!). 451*33321Sdonn */ 452*33321Sdonn public String sys_siglist[] = { 453*33321Sdonn "no signal", 454*33321Sdonn "hangup", 455*33321Sdonn "interrupt", 456*33321Sdonn "quit", 457*33321Sdonn "illegal instruction", 458*33321Sdonn "trace trap", 459*33321Sdonn "IOT instruction", 460*33321Sdonn "EMT instruction", 461*33321Sdonn "floating point exception", 462*33321Sdonn "kill", 463*33321Sdonn "bus error", 464*33321Sdonn "segmentation violation", 465*33321Sdonn "bad argument to system call", 466*33321Sdonn "broken pipe", 467*33321Sdonn "alarm clock", 468*33321Sdonn "soft kill", 469*33321Sdonn "urgent I/O condition", 470*33321Sdonn "stop signal not from tty", 471*33321Sdonn "stop signal from tty", 472*33321Sdonn "continue", 473*33321Sdonn "child termination", 474*33321Sdonn "stop (tty input)", 475*33321Sdonn "stop (tty output)", 476*33321Sdonn "possible input/output", 477*33321Sdonn "exceeded CPU time limit", 478*33321Sdonn "exceeded file size limit" 479*33321Sdonn }; 480*33321Sdonn public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0]; 481*33321Sdonn #endif 4829666Slinton 48316611Ssam public psignal(s, n) 4849666Slinton String s; 48516611Ssam integer n; 4869666Slinton { 48716611Ssam String msg; 48816611Ssam integer len; 48918538Sralph extern String sys_siglist[]; 4909666Slinton 49116611Ssam if (n >= 0 and n < sys_nsig) { 49216611Ssam msg = sys_siglist[n]; 49316611Ssam } else { 49416611Ssam msg = "Unknown signal"; 4959666Slinton } 49616611Ssam len = strlen(s); 49716611Ssam if (len > 0) { 49816611Ssam write(2, s, len); 4999666Slinton write(2, ": ", 2); 5009666Slinton } 50116611Ssam write(2, msg, strlen(msg)); 5029666Slinton write(2, "\n", 1); 5039666Slinton } 5049666Slinton 5059666Slinton /* 5069666Slinton * Standard error handling routines. 5079666Slinton */ 5089666Slinton 5099666Slinton private short nerrs; 5109666Slinton private short nwarnings; 5119666Slinton 5129666Slinton /* 5139666Slinton * Main driver of error message reporting. 5149666Slinton */ 5159666Slinton 5169666Slinton /* VARARGS2 */ 5179666Slinton private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m) 5189666Slinton String errname; 51916611Ssam boolean shouldquit; 5209666Slinton String s; 5219666Slinton { 5229666Slinton fflush(stdout); 5239666Slinton if (shouldquit and cmdname != nil(String)) { 5249666Slinton fprintf(stderr, "%s: ", cmdname); 5259666Slinton } 5269666Slinton if (errfilename != nil(Filename)) { 5279666Slinton fprintf(stderr, "%s: ", errfilename); 5289666Slinton } 5299666Slinton if (errlineno > 0) { 5309666Slinton fprintf(stderr, "%d: ", errlineno); 5319666Slinton } 5329666Slinton if (errname != nil(String)) { 5339666Slinton fprintf(stderr, "%s: ", errname); 5349666Slinton } 5359666Slinton fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m); 5369666Slinton putc('\n', stderr); 537*33321Sdonn fflush(stderr); 5389666Slinton if (shouldquit) { 5399666Slinton quit(1); 5409666Slinton } 5419666Slinton } 5429666Slinton 5439666Slinton /* 5449666Slinton * For when printf isn't sufficient for printing the error message ... 5459666Slinton */ 5469666Slinton 5479666Slinton public beginerrmsg() 5489666Slinton { 5499666Slinton fflush(stdout); 5509666Slinton if (errfilename != nil(String)) { 5519666Slinton fprintf(stderr, "%s: ", errfilename); 5529666Slinton } 5539666Slinton if (errlineno > 0) { 5549666Slinton fprintf(stderr, "%d: ", errlineno); 5559666Slinton } 5569666Slinton } 5579666Slinton 5589666Slinton public enderrmsg() 5599666Slinton { 5609666Slinton putc('\n', stderr); 561*33321Sdonn fflush(stderr); 5629666Slinton erecover(); 5639666Slinton } 5649666Slinton 5659666Slinton /* 5669666Slinton * The messages are listed in increasing order of seriousness. 5679666Slinton * 5689666Slinton * First are warnings. 5699666Slinton */ 5709666Slinton 5719666Slinton /* VARARGS1 */ 5729666Slinton public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m) 5739666Slinton String s; 5749666Slinton { 5759666Slinton nwarnings++; 5769666Slinton errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); 5779666Slinton } 5789666Slinton 5799666Slinton /* 5809666Slinton * Errors are a little worse, they mean something is wrong, 5819666Slinton * but not so bad that processing can't continue. 5829666Slinton * 5839666Slinton * The routine "erecover" is called to recover from the error, 5849666Slinton * a default routine is provided that does nothing. 5859666Slinton */ 5869666Slinton 5879666Slinton /* VARARGS1 */ 5889666Slinton public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m) 5899666Slinton String s; 5909666Slinton { 5919666Slinton extern erecover(); 5929666Slinton 5939666Slinton nerrs++; 5949666Slinton errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); 5959666Slinton erecover(); 5969666Slinton } 5979666Slinton 5989666Slinton /* 5999666Slinton * Non-recoverable user error. 6009666Slinton */ 6019666Slinton 6029666Slinton /* VARARGS1 */ 6039666Slinton public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m) 6049666Slinton String s; 6059666Slinton { 6069666Slinton errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); 6079666Slinton } 6089666Slinton 6099666Slinton /* 6109666Slinton * Panics indicate an internal program error. 6119666Slinton */ 6129666Slinton 6139666Slinton /* VARARGS1 */ 6149666Slinton public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m) 6159666Slinton String s; 6169666Slinton { 6179666Slinton errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); 6189666Slinton } 6199666Slinton 6209666Slinton short numerrors() 6219666Slinton { 6229666Slinton short r; 6239666Slinton 6249666Slinton r = nerrs; 6259666Slinton nerrs = 0; 6269666Slinton return r; 6279666Slinton } 6289666Slinton 6299666Slinton short numwarnings() 6309666Slinton { 6319666Slinton short r; 6329666Slinton 6339666Slinton r = nwarnings; 6349666Slinton nwarnings = 0; 6359666Slinton return r; 6369666Slinton } 6379666Slinton 6389666Slinton /* 6399666Slinton * Recover from an error. 6409666Slinton * 6419666Slinton * This is the default routine which we aren't using since we have our own. 6429666Slinton * 6439666Slinton public erecover() 6449666Slinton { 6459666Slinton } 6469666Slinton * 6479666Slinton */ 6489666Slinton 6499666Slinton /* 6509666Slinton * Default way to quit from a program is just to exit. 6519666Slinton * 6529666Slinton public quit(r) 6539666Slinton int r; 6549666Slinton { 6559666Slinton exit(r); 6569666Slinton } 6579666Slinton * 6589666Slinton */ 6599666Slinton 6609666Slinton /* 6619666Slinton * Compare n-byte areas pointed to by s1 and s2 6629666Slinton * if n is 0 then compare up until one has a null byte. 6639666Slinton */ 6649666Slinton 6659666Slinton public int cmp(s1, s2, n) 6669666Slinton register char *s1, *s2; 6679666Slinton register unsigned int n; 6689666Slinton { 6699666Slinton if (s1 == nil(char *) || s2 == nil(char *)) { 6709666Slinton panic("cmp: nil pointer"); 6719666Slinton } 6729666Slinton if (n == 0) { 6739666Slinton while (*s1 == *s2++) { 6749666Slinton if (*s1++ == '\0') { 6759666Slinton return(0); 6769666Slinton } 6779666Slinton } 6789666Slinton return(*s1 - *(s2-1)); 6799666Slinton } else { 6809666Slinton for (; n != 0; n--) { 6819666Slinton if (*s1++ != *s2++) { 6829666Slinton return(*(s1-1) - *(s2-1)); 6839666Slinton } 6849666Slinton } 6859666Slinton return(0); 6869666Slinton } 6879666Slinton } 6889666Slinton 6899666Slinton /* 6909666Slinton * Move n bytes from src to dest. 6919666Slinton * If n is 0 move until a null is found. 6929666Slinton */ 6939666Slinton 6949666Slinton public mov(src, dest, n) 6959666Slinton register char *src, *dest; 6969666Slinton register unsigned int n; 6979666Slinton { 6989666Slinton if (src == nil(char *)) 6999666Slinton panic("mov: nil source"); 7009666Slinton if (dest == nil(char *)) 7019666Slinton panic("mov: nil destination"); 7029666Slinton if (n != 0) { 7039666Slinton for (; n != 0; n--) { 7049666Slinton *dest++ = *src++; 7059666Slinton } 7069666Slinton } else { 7079666Slinton while ((*dest++ = *src++) != '\0'); 7089666Slinton } 7099666Slinton } 710*33321Sdonn 711*33321Sdonn #ifdef IRIS /* or in general for 4.2 - System V C library interface */ 712*33321Sdonn 713*33321Sdonn public bcopy (fromaddr, toaddr, n) 714*33321Sdonn char *fromaddr, *toaddr; 715*33321Sdonn int n; 716*33321Sdonn { 717*33321Sdonn blt(toaddr, fromaddr, n); 718*33321Sdonn } 719*33321Sdonn 720*33321Sdonn public bzero (addr, n) 721*33321Sdonn char *addr; 722*33321Sdonn int n; 723*33321Sdonn { 724*33321Sdonn register char *p, *q; 725*33321Sdonn 726*33321Sdonn p = addr; 727*33321Sdonn q = p + n; 728*33321Sdonn while (p < q) { 729*33321Sdonn *p++ = '\0'; 730*33321Sdonn } 731*33321Sdonn } 732*33321Sdonn 733*33321Sdonn #include <string.h> 734*33321Sdonn 735*33321Sdonn public char *index (s, c) 736*33321Sdonn char *s, c; 737*33321Sdonn { 738*33321Sdonn return strchr(s, c); 739*33321Sdonn } 740*33321Sdonn 741*33321Sdonn public char *rindex (s, c) 742*33321Sdonn char *s, c; 743*33321Sdonn { 744*33321Sdonn return strrchr(s, c); 745*33321Sdonn } 746*33321Sdonn 747*33321Sdonn #endif 748