121606Sdist /* 238105Sbostic * Copyright (c) 1983 The Regents of the University of California. 338105Sbostic * All rights reserved. 438105Sbostic * 5*42683Sbostic * %sccs.include.redist.c% 621606Sdist */ 79666Slinton 821606Sdist #ifndef lint 9*42683Sbostic static char sccsid[] = "@(#)library.c 5.4 (Berkeley) 06/01/90"; 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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]; 48033321Sdonn #endif 4819666Slinton 48216611Ssam public psignal(s, n) 4839666Slinton String s; 48416611Ssam integer n; 4859666Slinton { 48616611Ssam String msg; 48716611Ssam integer len; 48818538Sralph extern String sys_siglist[]; 4899666Slinton 49016611Ssam if (n >= 0 and n < sys_nsig) { 49116611Ssam msg = sys_siglist[n]; 49216611Ssam } else { 49316611Ssam msg = "Unknown signal"; 4949666Slinton } 49516611Ssam len = strlen(s); 49616611Ssam if (len > 0) { 49716611Ssam write(2, s, len); 4989666Slinton write(2, ": ", 2); 4999666Slinton } 50016611Ssam write(2, msg, strlen(msg)); 5019666Slinton write(2, "\n", 1); 5029666Slinton } 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 6199666Slinton short numerrors() 6209666Slinton { 6219666Slinton short r; 6229666Slinton 6239666Slinton r = nerrs; 6249666Slinton nerrs = 0; 6259666Slinton return r; 6269666Slinton } 6279666Slinton 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 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 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 71233321Sdonn public bcopy (fromaddr, toaddr, n) 71333321Sdonn char *fromaddr, *toaddr; 71433321Sdonn int n; 71533321Sdonn { 71633321Sdonn blt(toaddr, fromaddr, n); 71733321Sdonn } 71833321Sdonn 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 73433321Sdonn public char *index (s, c) 73533321Sdonn char *s, c; 73633321Sdonn { 73733321Sdonn return strchr(s, c); 73833321Sdonn } 73933321Sdonn 74033321Sdonn public char *rindex (s, c) 74133321Sdonn char *s, c; 74233321Sdonn { 74333321Sdonn return strrchr(s, c); 74433321Sdonn } 74533321Sdonn 74633321Sdonn #endif 747