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*10066Seric SCCSID(@(#)util.c 3.38 01/01/83); 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. 543*10066Seric ** crlf -- if set, output Carriage Return/Line Feed on lines 544*10066Seric ** instead of newline. 5457124Seric ** fullsmtp -- if set, obey strictest SMTP conventions. 5467124Seric ** 5477124Seric ** Returns: 5487124Seric ** none 5497124Seric ** 5507124Seric ** Side Effects: 5517124Seric ** output of l to fp. 5527124Seric */ 5537124Seric 5547753Seric # define SMTPLINELIM 990 /* maximum line length */ 5557124Seric 556*10066Seric putline(l, fp, crlf, fullsmtp) 5577753Seric register char *l; 5587124Seric FILE *fp; 559*10066Seric bool crlf; 5607124Seric bool fullsmtp; 5617124Seric { 5627124Seric register char *p; 5637753Seric char svchar; 5647124Seric 5657753Seric do 5667124Seric { 5677753Seric /* find the end of the line */ 5687753Seric p = index(l, '\n'); 5697753Seric if (p == NULL) 5707753Seric p = &l[strlen(l)]; 5717124Seric 5727753Seric /* check for line overflow */ 5737753Seric while (fullsmtp && (p - l) > SMTPLINELIM) 5747753Seric { 5757753Seric register char *q = &l[SMTPLINELIM - 1]; 5767124Seric 5777753Seric svchar = *q; 5787753Seric *q = '\0'; 5797753Seric fputs(l, fp); 580*10066Seric fputc('!', fp); 581*10066Seric if (crlf) 582*10066Seric fputc('\r', fp); 583*10066Seric fputc('\n', fp); 5847753Seric *q = svchar; 5857753Seric l = q; 5867753Seric } 5877124Seric 5887753Seric /* output last part */ 5897753Seric svchar = *p; 5907753Seric *p = '\0'; 5917124Seric fputs(l, fp); 592*10066Seric if (crlf) 5937753Seric fputc('\r', fp); 5947753Seric fputc('\n', fp); 5957753Seric *p = svchar; 5967753Seric l = p; 5977753Seric if (*l == '\n') 5987753Seric l++; 5997753Seric } while (l[0] != '\0'); 6007124Seric } 6017676Seric /* 6027676Seric ** XUNLINK -- unlink a file, doing logging as appropriate. 6037676Seric ** 6047676Seric ** Parameters: 6057676Seric ** f -- name of file to unlink. 6067676Seric ** 6077676Seric ** Returns: 6087676Seric ** none. 6097676Seric ** 6107676Seric ** Side Effects: 6117676Seric ** f is unlinked. 6127676Seric */ 6137676Seric 6147676Seric xunlink(f) 6157676Seric char *f; 6167676Seric { 6177676Seric register int i; 6187676Seric 6197676Seric # ifdef LOG 6207676Seric if (LogLevel > 20) 6217812Seric syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f); 6227676Seric # endif LOG 6237676Seric 6247676Seric i = unlink(f); 6257676Seric # ifdef LOG 6267676Seric if (i < 0 && LogLevel > 21) 6277942Seric syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno); 6287676Seric # endif LOG 6297676Seric } 6307685Seric /* 6317685Seric ** SFGETS -- "safe" fgets -- times out. 6327685Seric ** 6337685Seric ** Parameters: 6347685Seric ** buf -- place to put the input line. 6357685Seric ** siz -- size of buf. 6367685Seric ** fp -- file to read from. 6377685Seric ** 6387685Seric ** Returns: 6397685Seric ** NULL on error (including timeout). 6407685Seric ** buf otherwise. 6417685Seric ** 6427685Seric ** Side Effects: 6437685Seric ** none. 6447685Seric */ 6457685Seric 6467942Seric static bool TimeoutFlag; 6477685Seric 6487685Seric char * 6497685Seric sfgets(buf, siz, fp) 6507685Seric char *buf; 6517685Seric int siz; 6527685Seric FILE *fp; 6537685Seric { 6547942Seric register EVENT *ev = NULL; 6557685Seric register char *p; 6567685Seric extern readtimeout(); 6577685Seric 6587942Seric if (ReadTimeout != 0) 6597942Seric ev = setevent(ReadTimeout, readtimeout, 0); 6607942Seric TimeoutFlag = FALSE; 6617942Seric do 6627942Seric { 6637942Seric errno = 0; 6647942Seric p = fgets(buf, siz, fp); 6657942Seric } while (!(p != NULL || TimeoutFlag || errno != EINTR)); 6667685Seric clrevent(ev); 6678055Seric LineNumber++; 6689581Seric if (TimeoutFlag) 6699581Seric syserr("sfgets: timeout on read (mailer may be hung)"); 6707685Seric return (p); 6717685Seric } 6727685Seric 6737685Seric static 6747685Seric readtimeout() 6757685Seric { 6767942Seric TimeoutFlag = TRUE; 6777685Seric } 6787786Seric /* 6797786Seric ** FGETFOLDED -- like fgets, but know about folded lines. 6807786Seric ** 6817786Seric ** Parameters: 6827786Seric ** buf -- place to put result. 6837786Seric ** n -- bytes available. 6847786Seric ** f -- file to read from. 6857786Seric ** 6867786Seric ** Returns: 6877786Seric ** buf on success, NULL on error or EOF. 6887786Seric ** 6897786Seric ** Side Effects: 6907786Seric ** buf gets lines from f, with continuation lines (lines 6917786Seric ** with leading white space) appended. CRLF's are mapped 6927786Seric ** into single newlines. Any trailing NL is stripped. 6937786Seric */ 6947786Seric 6957786Seric char * 6967786Seric fgetfolded(buf, n, f) 6977786Seric char *buf; 6987786Seric register int n; 6997786Seric FILE *f; 7007786Seric { 7017786Seric register char *p = buf; 7027786Seric register int i; 7037786Seric 7047786Seric n--; 70510030Seric while (fgets(p, n, f) != NULL) 7067786Seric { 70710030Seric LineNumber++; 7087786Seric fixcrlf(p, TRUE); 7097786Seric i = fgetc(f); 7107786Seric if (i != EOF) 7117786Seric ungetc(i, f); 7127786Seric if (i != ' ' && i != '\t') 7137786Seric return (buf); 7147786Seric i = strlen(p); 7157786Seric p += i; 7167786Seric *p++ = '\n'; 7177786Seric n -= i + 1; 7187786Seric } 7197786Seric return (NULL); 7207786Seric } 7217860Seric /* 7227886Seric ** CURTIME -- return current time. 7237886Seric ** 7247886Seric ** Parameters: 7257886Seric ** none. 7267886Seric ** 7277886Seric ** Returns: 7287886Seric ** the current time. 7297886Seric ** 7307886Seric ** Side Effects: 7317886Seric ** none. 7327886Seric */ 7337886Seric 7347886Seric time_t 7357886Seric curtime() 7367886Seric { 7377886Seric auto time_t t; 7387886Seric 7397886Seric (void) time(&t); 7407886Seric return (t); 7417886Seric } 7428264Seric /* 7438264Seric ** ATOBOOL -- convert a string representation to boolean. 7448264Seric ** 7458264Seric ** Defaults to "TRUE" 7468264Seric ** 7478264Seric ** Parameters: 7488264Seric ** s -- string to convert. Takes "tTyY" as true, 7498264Seric ** others as false. 7508264Seric ** 7518264Seric ** Returns: 7528264Seric ** A boolean representation of the string. 7538264Seric ** 7548264Seric ** Side Effects: 7558264Seric ** none. 7568264Seric */ 7578264Seric 7588264Seric bool 7598264Seric atobool(s) 7608264Seric register char *s; 7618264Seric { 7628264Seric if (*s == '\0' || index("tTyY", *s) != NULL) 7638264Seric return (TRUE); 7648264Seric return (FALSE); 7658264Seric } 7669048Seric /* 7679048Seric ** ATOOCT -- convert a string representation to octal. 7689048Seric ** 7699048Seric ** Parameters: 7709048Seric ** s -- string to convert. 7719048Seric ** 7729048Seric ** Returns: 7739048Seric ** An integer representing the string interpreted as an 7749048Seric ** octal number. 7759048Seric ** 7769048Seric ** Side Effects: 7779048Seric ** none. 7789048Seric */ 7799048Seric 7809048Seric atooct(s) 7819048Seric register char *s; 7829048Seric { 7839048Seric register int i = 0; 7849048Seric 7859048Seric while (*s >= '0' && *s <= '7') 7869048Seric i = (i << 3) | (*s++ - '0'); 7879048Seric return (i); 7889048Seric } 7899376Seric /* 7909376Seric ** WAITFOR -- wait for a particular process id. 7919376Seric ** 7929376Seric ** Parameters: 7939376Seric ** pid -- process id to wait for. 7949376Seric ** 7959376Seric ** Returns: 7969376Seric ** status of pid. 7979376Seric ** -1 if pid never shows up. 7989376Seric ** 7999376Seric ** Side Effects: 8009376Seric ** none. 8019376Seric */ 8029376Seric 8039376Seric waitfor(pid) 8049376Seric int pid; 8059376Seric { 8069376Seric auto int st; 8079376Seric int i; 8089376Seric 8099376Seric do 8109376Seric { 8119376Seric errno = 0; 8129376Seric i = wait(&st); 8139376Seric } while ((i >= 0 || errno == EINTR) && i != pid); 8149376Seric if (i < 0) 8159376Seric st = -1; 8169376Seric return (st); 8179376Seric } 8189376Seric /* 8199376Seric ** CLOSEALL -- close all extraneous file descriptors 8209376Seric ** 8219376Seric ** Parameters: 8229376Seric ** none. 8239376Seric ** 8249376Seric ** Returns: 8259376Seric ** none. 8269376Seric ** 8279376Seric ** Side Effects: 8289376Seric ** Closes all file descriptors except zero, one, and two. 8299376Seric */ 8309376Seric 8319376Seric closeall() 8329376Seric { 8339376Seric int i; 8349376Seric 8359376Seric for (i = 3; i < 50; i++) 8369376Seric (void) close(i); 8379376Seric } 838