13151Seric # include <stdio.h> 24538Seric # include <sys/types.h> 34538Seric # include <sys/stat.h> 4298Seric # include <sysexits.h> 56890Seric # include <errno.h> 62900Seric # include <ctype.h> 76890Seric # include "sendmail.h" 8298Seric 9*10030Seric SCCSID(@(#)util.c 3.37 12/30/82); 10409Seric 11298Seric /* 12298Seric ** STRIPQUOTES -- Strip quotes & quote bits from a string. 13298Seric ** 14298Seric ** Runs through a string and strips off unquoted quote 15298Seric ** characters and quote bits. This is done in place. 16298Seric ** 17298Seric ** Parameters: 18298Seric ** s -- the string to strip. 194101Seric ** qf -- if set, remove actual `` " '' characters 204101Seric ** as well as the quote bits. 21298Seric ** 22298Seric ** Returns: 23298Seric ** none. 24298Seric ** 25298Seric ** Side Effects: 26298Seric ** none. 27298Seric ** 28298Seric ** Called By: 29298Seric ** deliver 30298Seric */ 31298Seric 324101Seric stripquotes(s, qf) 33298Seric char *s; 344101Seric bool qf; 35298Seric { 36298Seric register char *p; 37298Seric register char *q; 38298Seric register char c; 39298Seric 404101Seric if (s == NULL) 414101Seric return; 424101Seric 43298Seric for (p = q = s; (c = *p++) != '\0'; ) 44298Seric { 454101Seric if (c != '"' || !qf) 46298Seric *q++ = c & 0177; 47298Seric } 48298Seric *q = '\0'; 49298Seric } 50298Seric /* 519043Seric ** QSTRLEN -- give me the string length assuming 0200 bits add a char 529043Seric ** 539043Seric ** Parameters: 549043Seric ** s -- the string to measure. 559043Seric ** 569043Seric ** Reurns: 579043Seric ** The length of s, including space for backslash escapes. 589043Seric ** 599043Seric ** Side Effects: 609043Seric ** none. 619043Seric */ 629043Seric 639043Seric qstrlen(s) 649043Seric register char *s; 659043Seric { 669043Seric register int l = 0; 679043Seric register char c; 689043Seric 699043Seric while ((c = *s++) != '\0') 709043Seric { 719043Seric if (bitset(0200, c)) 729043Seric l++; 739043Seric l++; 749043Seric } 759043Seric return (l); 769043Seric } 779043Seric /* 782900Seric ** CAPITALIZE -- return a copy of a string, properly capitalized. 792900Seric ** 802900Seric ** Parameters: 812900Seric ** s -- the string to capitalize. 822900Seric ** 832900Seric ** Returns: 842900Seric ** a pointer to a properly capitalized string. 852900Seric ** 862900Seric ** Side Effects: 872900Seric ** none. 882900Seric */ 892900Seric 902900Seric char * 912900Seric capitalize(s) 922900Seric register char *s; 932900Seric { 942900Seric static char buf[50]; 952900Seric register char *p; 962900Seric 972900Seric p = buf; 982900Seric 992900Seric for (;;) 1002900Seric { 1012900Seric while (!isalpha(*s) && *s != '\0') 1022900Seric *p++ = *s++; 1032900Seric if (*s == '\0') 1042900Seric break; 1052900Seric *p++ = toupper(*s++); 1062900Seric while (isalpha(*s)) 1072900Seric *p++ = *s++; 1082900Seric } 1092900Seric 1102900Seric *p = '\0'; 1112900Seric return (buf); 1122900Seric } 1132900Seric /* 114298Seric ** XALLOC -- Allocate memory and bitch wildly on failure. 115298Seric ** 116298Seric ** THIS IS A CLUDGE. This should be made to give a proper 117298Seric ** error -- but after all, what can we do? 118298Seric ** 119298Seric ** Parameters: 120298Seric ** sz -- size of area to allocate. 121298Seric ** 122298Seric ** Returns: 123298Seric ** pointer to data region. 124298Seric ** 125298Seric ** Side Effects: 126298Seric ** Memory is allocated. 127298Seric */ 128298Seric 129298Seric char * 130298Seric xalloc(sz) 1317007Seric register int sz; 132298Seric { 133298Seric register char *p; 134298Seric 135298Seric p = malloc(sz); 136298Seric if (p == NULL) 137298Seric { 138298Seric syserr("Out of memory!!"); 1391598Seric exit(EX_UNAVAILABLE); 140298Seric } 141298Seric return (p); 142298Seric } 143298Seric /* 1442900Seric ** NEWSTR -- make copy of string. 1452900Seric ** 1462900Seric ** Space is allocated for it using xalloc. 1472900Seric ** 1482900Seric ** Parameters: 1492900Seric ** string to copy. 1502900Seric ** 1512900Seric ** Returns: 1522900Seric ** pointer to new string. 1532900Seric ** 1542900Seric ** Side Effects: 1552900Seric ** none. 1562900Seric */ 1572900Seric 1582900Seric char * 1592900Seric newstr(s) 1602900Seric register char *s; 1612900Seric { 1622900Seric register char *p; 1632900Seric 1647007Seric p = xalloc(strlen(s) + 1); 1657007Seric (void) strcpy(p, s); 1662900Seric return (p); 1672900Seric } 1683151Seric /* 1693151Seric ** COPYPLIST -- copy list of pointers. 1703151Seric ** 1713151Seric ** This routine is the equivalent of newstr for lists of 1723151Seric ** pointers. 1733151Seric ** 1743151Seric ** Parameters: 1753151Seric ** list -- list of pointers to copy. 1763151Seric ** Must be NULL terminated. 1773151Seric ** copycont -- if TRUE, copy the contents of the vector 1783151Seric ** (which must be a string) also. 1793151Seric ** 1803151Seric ** Returns: 1813151Seric ** a copy of 'list'. 1823151Seric ** 1833151Seric ** Side Effects: 1843151Seric ** none. 1853151Seric */ 1863151Seric 1873151Seric char ** 1883151Seric copyplist(list, copycont) 1893151Seric char **list; 1903151Seric bool copycont; 1913151Seric { 1923151Seric register char **vp; 1933151Seric register char **newvp; 1943151Seric 1953151Seric for (vp = list; *vp != NULL; vp++) 1963151Seric continue; 1973151Seric 1983151Seric vp++; 1993151Seric 2007007Seric newvp = (char **) xalloc((vp - list) * sizeof *vp); 2014086Seric bmove((char *) list, (char *) newvp, (vp - list) * sizeof *vp); 2023151Seric 2033151Seric if (copycont) 2043151Seric { 2053151Seric for (vp = newvp; *vp != NULL; vp++) 2063151Seric *vp = newstr(*vp); 2073151Seric } 2083151Seric 2093151Seric return (newvp); 2103151Seric } 2113151Seric /* 2123151Seric ** PRINTAV -- print argument vector. 2133151Seric ** 2143151Seric ** Parameters: 2153151Seric ** av -- argument vector. 2163151Seric ** 2173151Seric ** Returns: 2183151Seric ** none. 2193151Seric ** 2203151Seric ** Side Effects: 2213151Seric ** prints av. 2223151Seric */ 2233151Seric 2243151Seric # ifdef DEBUG 2253151Seric printav(av) 2263151Seric register char **av; 2273151Seric { 2283151Seric while (*av != NULL) 2293151Seric { 2308063Seric if (tTd(0, 44)) 2318063Seric printf("\n\t%08x=", *av); 2328063Seric else 2338063Seric putchar(' '); 2343151Seric xputs(*av++); 2353151Seric } 2368063Seric putchar('\n'); 2373151Seric } 2383151Seric # endif DEBUG 2393151Seric /* 2403151Seric ** LOWER -- turn letter into lower case. 2413151Seric ** 2423151Seric ** Parameters: 2433151Seric ** c -- character to turn into lower case. 2443151Seric ** 2453151Seric ** Returns: 2463151Seric ** c, in lower case. 2473151Seric ** 2483151Seric ** Side Effects: 2493151Seric ** none. 2503151Seric */ 2513151Seric 2523151Seric char 2533151Seric lower(c) 2543151Seric register char c; 2553151Seric { 2563151Seric if (isascii(c) && isupper(c)) 2573151Seric c = c - 'A' + 'a'; 2583151Seric return (c); 2593151Seric } 2603151Seric /* 2613151Seric ** XPUTS -- put string doing control escapes. 2623151Seric ** 2633151Seric ** Parameters: 2643151Seric ** s -- string to put. 2653151Seric ** 2663151Seric ** Returns: 2673151Seric ** none. 2683151Seric ** 2693151Seric ** Side Effects: 2703151Seric ** output to stdout 2713151Seric */ 2723151Seric 2733151Seric # ifdef DEBUG 2743151Seric xputs(s) 2753151Seric register char *s; 2763151Seric { 2773151Seric register char c; 2783151Seric 2798055Seric if (s == NULL) 2808055Seric { 2818055Seric printf("<null>"); 2828055Seric return; 2838055Seric } 2848063Seric putchar('"'); 2853151Seric while ((c = *s++) != '\0') 2863151Seric { 2873151Seric if (!isascii(c)) 2883151Seric { 2893151Seric putchar('\\'); 2903151Seric c &= 0177; 2913151Seric } 2923151Seric if (iscntrl(c)) 2933151Seric { 2943151Seric putchar('^'); 2953151Seric c |= 0100; 2963151Seric } 2973151Seric putchar(c); 2983151Seric } 2998063Seric putchar('"'); 3004086Seric (void) fflush(stdout); 3013151Seric } 3023151Seric # endif DEBUG 3033151Seric /* 3043151Seric ** MAKELOWER -- Translate a line into lower case 3053151Seric ** 3063151Seric ** Parameters: 3073151Seric ** p -- the string to translate. If NULL, return is 3083151Seric ** immediate. 3093151Seric ** 3103151Seric ** Returns: 3113151Seric ** none. 3123151Seric ** 3133151Seric ** Side Effects: 3143151Seric ** String pointed to by p is translated to lower case. 3153151Seric ** 3163151Seric ** Called By: 3173151Seric ** parse 3183151Seric */ 3193151Seric 3203151Seric makelower(p) 3213151Seric register char *p; 3223151Seric { 3233151Seric register char c; 3243151Seric 3253151Seric if (p == NULL) 3263151Seric return; 3273151Seric for (; (c = *p) != '\0'; p++) 3283151Seric if (isascii(c) && isupper(c)) 3293151Seric *p = c - 'A' + 'a'; 3303151Seric } 3314059Seric /* 3324059Seric ** SAMEWORD -- return TRUE if the words are the same 3334059Seric ** 3344059Seric ** Ignores case. 3354059Seric ** 3364059Seric ** Parameters: 3374059Seric ** a, b -- the words to compare. 3384059Seric ** 3394059Seric ** Returns: 3404059Seric ** TRUE if a & b match exactly (modulo case) 3414059Seric ** FALSE otherwise. 3424059Seric ** 3434059Seric ** Side Effects: 3444059Seric ** none. 3454059Seric */ 3464059Seric 3474059Seric bool 3484059Seric sameword(a, b) 3494059Seric register char *a, *b; 3504059Seric { 3514059Seric while (lower(*a) == lower(*b)) 3524059Seric { 3534059Seric if (*a == '\0') 3544059Seric return (TRUE); 3554059Seric a++; 3564059Seric b++; 3574059Seric } 3584059Seric return (FALSE); 3594059Seric } 3604086Seric /* 3614101Seric ** CLEAR -- clear a block of memory 3624101Seric ** 3634101Seric ** Parameters: 3644101Seric ** p -- location to clear. 3654101Seric ** l -- number of bytes to clear. 3664101Seric ** 3674101Seric ** Returns: 3684101Seric ** none. 3694101Seric ** 3704101Seric ** Side Effects: 3714101Seric ** none. 3724101Seric */ 3734101Seric 3744101Seric clear(p, l) 3754101Seric register char *p; 3764101Seric register int l; 3774101Seric { 3784101Seric while (l-- > 0) 3794101Seric *p++ = 0; 3804101Seric } 3814101Seric /* 3825196Seric ** BUILDFNAME -- build full name from gecos style entry. 3834375Seric ** 3845196Seric ** This routine interprets the strange entry that would appear 3855196Seric ** in the GECOS field of the password file. 3865196Seric ** 3874375Seric ** Parameters: 3885196Seric ** p -- name to build. 3895196Seric ** login -- the login name of this user (for &). 3905196Seric ** buf -- place to put the result. 3914375Seric ** 3924375Seric ** Returns: 3934375Seric ** none. 3944375Seric ** 3954375Seric ** Side Effects: 3964375Seric ** none. 3974375Seric */ 3984375Seric 3995196Seric buildfname(p, login, buf) 4005196Seric register char *p; 4015196Seric char *login; 4024375Seric char *buf; 4034375Seric { 4044375Seric register char *bp = buf; 4054375Seric 4064438Seric if (*p == '*') 4074438Seric p++; 4086278Seric while (*p != '\0' && *p != ',' && *p != ';' && *p != '%') 4094375Seric { 4104375Seric if (*p == '&') 4114375Seric { 4125196Seric (void) strcpy(bp, login); 4134375Seric *bp = toupper(*bp); 4144375Seric while (*bp != '\0') 4154375Seric bp++; 4164375Seric p++; 4174375Seric } 4184375Seric else 4194375Seric *bp++ = *p++; 4204375Seric } 4214375Seric *bp = '\0'; 4224375Seric } 4234375Seric /* 4244538Seric ** SAFEFILE -- return true if a file exists and is safe for a user. 4254538Seric ** 4264538Seric ** Parameters: 4274538Seric ** fn -- filename to check. 4284538Seric ** uid -- uid to compare against. 4294538Seric ** mode -- mode bits that must match. 4304538Seric ** 4314538Seric ** Returns: 4324538Seric ** TRUE if fn exists, is owned by uid, and matches mode. 4334538Seric ** FALSE otherwise. 4344538Seric ** 4354538Seric ** Side Effects: 4364538Seric ** none. 4374538Seric */ 4384538Seric 4394538Seric bool 4404538Seric safefile(fn, uid, mode) 4414538Seric char *fn; 4424538Seric int uid; 4434538Seric int mode; 4444538Seric { 4454538Seric struct stat stbuf; 4464538Seric 4474538Seric if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid && 4484538Seric (stbuf.st_mode & mode) == mode) 4494538Seric return (TRUE); 4504538Seric return (FALSE); 4514538Seric } 4524538Seric /* 4534557Seric ** FIXCRLF -- fix <CR><LF> in line. 4544557Seric ** 4554557Seric ** Looks for the <CR><LF> combination and turns it into the 4564557Seric ** UNIX canonical <NL> character. It only takes one line, 4574557Seric ** i.e., it is assumed that the first <NL> found is the end 4584557Seric ** of the line. 4594557Seric ** 4604557Seric ** Parameters: 4614557Seric ** line -- the line to fix. 4624557Seric ** stripnl -- if true, strip the newline also. 4634557Seric ** 4644557Seric ** Returns: 4654557Seric ** none. 4664557Seric ** 4674557Seric ** Side Effects: 4684557Seric ** line is changed in place. 4694557Seric */ 4704557Seric 4714557Seric fixcrlf(line, stripnl) 4724557Seric char *line; 4734557Seric bool stripnl; 4744557Seric { 4754557Seric register char *p; 4764557Seric 4774557Seric p = index(line, '\n'); 4784557Seric if (p == NULL) 4794557Seric return; 4804794Seric if (p[-1] == '\r') 4814557Seric p--; 4824557Seric if (!stripnl) 4834557Seric *p++ = '\n'; 4844557Seric *p = '\0'; 4854557Seric } 4864557Seric /* 4874086Seric ** SYSLOG -- fake entry to fool lint 4884086Seric */ 4894086Seric 4904086Seric # ifdef LOG 4914086Seric # ifdef lint 4924086Seric 4934086Seric /*VARARGS2*/ 4944086Seric syslog(pri, fmt, args) 4954086Seric int pri; 4964086Seric char *fmt; 4974086Seric { 4984086Seric pri = *fmt; 4994086Seric args = pri; 5004086Seric pri = args; 5014086Seric } 5024086Seric 5034086Seric # endif lint 5044086Seric # endif LOG 5056890Seric /* 5066890Seric ** DFOPEN -- determined file open 5076890Seric ** 5086890Seric ** This routine has the semantics of fopen, except that it will 5096890Seric ** keep trying a few times to make this happen. The idea is that 5106890Seric ** on very loaded systems, we may run out of resources (inodes, 5116890Seric ** whatever), so this tries to get around it. 5126890Seric */ 5136890Seric 5146890Seric FILE * 5156890Seric dfopen(filename, mode) 5166890Seric char *filename; 5176890Seric char *mode; 5186890Seric { 5196890Seric register int tries; 5206890Seric register FILE *fp; 5216890Seric 5226890Seric for (tries = 0; tries < 10; tries++) 5236890Seric { 5246890Seric sleep(10 * tries); 5256890Seric errno = 0; 5266890Seric fp = fopen(filename, mode); 5279376Seric if (fp != NULL) 5286890Seric break; 5299376Seric if (errno != ENFILE && errno != EINTR) 5309376Seric break; 5316890Seric } 5326890Seric return (fp); 5336890Seric } 5347124Seric /* 5357124Seric ** PUTLINE -- put a line like fputs obeying SMTP conventions 5367124Seric ** 5377753Seric ** This routine always guarantees outputing a newline (or CRLF, 5387753Seric ** as appropriate) at the end of the string. 5397753Seric ** 5407124Seric ** Parameters: 5417124Seric ** l -- line to put. 5427124Seric ** fp -- file to put it onto. 5437124Seric ** fullsmtp -- if set, obey strictest SMTP conventions. 5447124Seric ** 5457124Seric ** Returns: 5467124Seric ** none 5477124Seric ** 5487124Seric ** Side Effects: 5497124Seric ** output of l to fp. 5507124Seric */ 5517124Seric 5527753Seric # define SMTPLINELIM 990 /* maximum line length */ 5537124Seric 5547124Seric putline(l, fp, fullsmtp) 5557753Seric register char *l; 5567124Seric FILE *fp; 5577124Seric bool fullsmtp; 5587124Seric { 5597124Seric register char *p; 5607753Seric char svchar; 5617124Seric 5627753Seric do 5637124Seric { 5647753Seric /* find the end of the line */ 5657753Seric p = index(l, '\n'); 5667753Seric if (p == NULL) 5677753Seric p = &l[strlen(l)]; 5687124Seric 5697753Seric /* check for line overflow */ 5707753Seric while (fullsmtp && (p - l) > SMTPLINELIM) 5717753Seric { 5727753Seric register char *q = &l[SMTPLINELIM - 1]; 5737124Seric 5747753Seric svchar = *q; 5757753Seric *q = '\0'; 5767753Seric fputs(l, fp); 5777753Seric fputs("!\r\n", fp); 5787753Seric *q = svchar; 5797753Seric l = q; 5807753Seric } 5817124Seric 5827753Seric /* output last part */ 5837753Seric svchar = *p; 5847753Seric *p = '\0'; 5857124Seric fputs(l, fp); 5867753Seric if (fullsmtp) 5877753Seric fputc('\r', fp); 5887753Seric fputc('\n', fp); 5897753Seric *p = svchar; 5907753Seric l = p; 5917753Seric if (*l == '\n') 5927753Seric l++; 5937753Seric } while (l[0] != '\0'); 5947124Seric } 5957676Seric /* 5967676Seric ** XUNLINK -- unlink a file, doing logging as appropriate. 5977676Seric ** 5987676Seric ** Parameters: 5997676Seric ** f -- name of file to unlink. 6007676Seric ** 6017676Seric ** Returns: 6027676Seric ** none. 6037676Seric ** 6047676Seric ** Side Effects: 6057676Seric ** f is unlinked. 6067676Seric */ 6077676Seric 6087676Seric xunlink(f) 6097676Seric char *f; 6107676Seric { 6117676Seric register int i; 6127676Seric 6137676Seric # ifdef LOG 6147676Seric if (LogLevel > 20) 6157812Seric syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f); 6167676Seric # endif LOG 6177676Seric 6187676Seric i = unlink(f); 6197676Seric # ifdef LOG 6207676Seric if (i < 0 && LogLevel > 21) 6217942Seric syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno); 6227676Seric # endif LOG 6237676Seric } 6247685Seric /* 6257685Seric ** SFGETS -- "safe" fgets -- times out. 6267685Seric ** 6277685Seric ** Parameters: 6287685Seric ** buf -- place to put the input line. 6297685Seric ** siz -- size of buf. 6307685Seric ** fp -- file to read from. 6317685Seric ** 6327685Seric ** Returns: 6337685Seric ** NULL on error (including timeout). 6347685Seric ** buf otherwise. 6357685Seric ** 6367685Seric ** Side Effects: 6377685Seric ** none. 6387685Seric */ 6397685Seric 6407942Seric static bool TimeoutFlag; 6417685Seric 6427685Seric char * 6437685Seric sfgets(buf, siz, fp) 6447685Seric char *buf; 6457685Seric int siz; 6467685Seric FILE *fp; 6477685Seric { 6487942Seric register EVENT *ev = NULL; 6497685Seric register char *p; 6507685Seric extern readtimeout(); 6517685Seric 6527942Seric if (ReadTimeout != 0) 6537942Seric ev = setevent(ReadTimeout, readtimeout, 0); 6547942Seric TimeoutFlag = FALSE; 6557942Seric do 6567942Seric { 6577942Seric errno = 0; 6587942Seric p = fgets(buf, siz, fp); 6597942Seric } while (!(p != NULL || TimeoutFlag || errno != EINTR)); 6607685Seric clrevent(ev); 6618055Seric LineNumber++; 6629581Seric if (TimeoutFlag) 6639581Seric syserr("sfgets: timeout on read (mailer may be hung)"); 6647685Seric return (p); 6657685Seric } 6667685Seric 6677685Seric static 6687685Seric readtimeout() 6697685Seric { 6707942Seric TimeoutFlag = TRUE; 6717685Seric } 6727786Seric /* 6737786Seric ** FGETFOLDED -- like fgets, but know about folded lines. 6747786Seric ** 6757786Seric ** Parameters: 6767786Seric ** buf -- place to put result. 6777786Seric ** n -- bytes available. 6787786Seric ** f -- file to read from. 6797786Seric ** 6807786Seric ** Returns: 6817786Seric ** buf on success, NULL on error or EOF. 6827786Seric ** 6837786Seric ** Side Effects: 6847786Seric ** buf gets lines from f, with continuation lines (lines 6857786Seric ** with leading white space) appended. CRLF's are mapped 6867786Seric ** into single newlines. Any trailing NL is stripped. 6877786Seric */ 6887786Seric 6897786Seric char * 6907786Seric fgetfolded(buf, n, f) 6917786Seric char *buf; 6927786Seric register int n; 6937786Seric FILE *f; 6947786Seric { 6957786Seric register char *p = buf; 6967786Seric register int i; 6977786Seric 6987786Seric n--; 699*10030Seric while (fgets(p, n, f) != NULL) 7007786Seric { 701*10030Seric LineNumber++; 7027786Seric fixcrlf(p, TRUE); 7037786Seric i = fgetc(f); 7047786Seric if (i != EOF) 7057786Seric ungetc(i, f); 7067786Seric if (i != ' ' && i != '\t') 7077786Seric return (buf); 7087786Seric i = strlen(p); 7097786Seric p += i; 7107786Seric *p++ = '\n'; 7117786Seric n -= i + 1; 7127786Seric } 7137786Seric return (NULL); 7147786Seric } 7157860Seric /* 7167886Seric ** CURTIME -- return current time. 7177886Seric ** 7187886Seric ** Parameters: 7197886Seric ** none. 7207886Seric ** 7217886Seric ** Returns: 7227886Seric ** the current time. 7237886Seric ** 7247886Seric ** Side Effects: 7257886Seric ** none. 7267886Seric */ 7277886Seric 7287886Seric time_t 7297886Seric curtime() 7307886Seric { 7317886Seric auto time_t t; 7327886Seric 7337886Seric (void) time(&t); 7347886Seric return (t); 7357886Seric } 7368264Seric /* 7378264Seric ** ATOBOOL -- convert a string representation to boolean. 7388264Seric ** 7398264Seric ** Defaults to "TRUE" 7408264Seric ** 7418264Seric ** Parameters: 7428264Seric ** s -- string to convert. Takes "tTyY" as true, 7438264Seric ** others as false. 7448264Seric ** 7458264Seric ** Returns: 7468264Seric ** A boolean representation of the string. 7478264Seric ** 7488264Seric ** Side Effects: 7498264Seric ** none. 7508264Seric */ 7518264Seric 7528264Seric bool 7538264Seric atobool(s) 7548264Seric register char *s; 7558264Seric { 7568264Seric if (*s == '\0' || index("tTyY", *s) != NULL) 7578264Seric return (TRUE); 7588264Seric return (FALSE); 7598264Seric } 7609048Seric /* 7619048Seric ** ATOOCT -- convert a string representation to octal. 7629048Seric ** 7639048Seric ** Parameters: 7649048Seric ** s -- string to convert. 7659048Seric ** 7669048Seric ** Returns: 7679048Seric ** An integer representing the string interpreted as an 7689048Seric ** octal number. 7699048Seric ** 7709048Seric ** Side Effects: 7719048Seric ** none. 7729048Seric */ 7739048Seric 7749048Seric atooct(s) 7759048Seric register char *s; 7769048Seric { 7779048Seric register int i = 0; 7789048Seric 7799048Seric while (*s >= '0' && *s <= '7') 7809048Seric i = (i << 3) | (*s++ - '0'); 7819048Seric return (i); 7829048Seric } 7839376Seric /* 7849376Seric ** WAITFOR -- wait for a particular process id. 7859376Seric ** 7869376Seric ** Parameters: 7879376Seric ** pid -- process id to wait for. 7889376Seric ** 7899376Seric ** Returns: 7909376Seric ** status of pid. 7919376Seric ** -1 if pid never shows up. 7929376Seric ** 7939376Seric ** Side Effects: 7949376Seric ** none. 7959376Seric */ 7969376Seric 7979376Seric waitfor(pid) 7989376Seric int pid; 7999376Seric { 8009376Seric auto int st; 8019376Seric int i; 8029376Seric 8039376Seric do 8049376Seric { 8059376Seric errno = 0; 8069376Seric i = wait(&st); 8079376Seric } while ((i >= 0 || errno == EINTR) && i != pid); 8089376Seric if (i < 0) 8099376Seric st = -1; 8109376Seric return (st); 8119376Seric } 8129376Seric /* 8139376Seric ** CLOSEALL -- close all extraneous file descriptors 8149376Seric ** 8159376Seric ** Parameters: 8169376Seric ** none. 8179376Seric ** 8189376Seric ** Returns: 8199376Seric ** none. 8209376Seric ** 8219376Seric ** Side Effects: 8229376Seric ** Closes all file descriptors except zero, one, and two. 8239376Seric */ 8249376Seric 8259376Seric closeall() 8269376Seric { 8279376Seric int i; 8289376Seric 8299376Seric for (i = 3; i < 50; i++) 8309376Seric (void) close(i); 8319376Seric } 832