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*14885Seric SCCSID(@(#)util.c 4.2 08/31/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!!"); 13910685Seric abort(); 14010685Seric /* exit(EX_UNAVAILABLE); */ 141298Seric } 142298Seric return (p); 143298Seric } 144298Seric /* 1453151Seric ** COPYPLIST -- copy list of pointers. 1463151Seric ** 1473151Seric ** This routine is the equivalent of newstr for lists of 1483151Seric ** pointers. 1493151Seric ** 1503151Seric ** Parameters: 1513151Seric ** list -- list of pointers to copy. 1523151Seric ** Must be NULL terminated. 1533151Seric ** copycont -- if TRUE, copy the contents of the vector 1543151Seric ** (which must be a string) also. 1553151Seric ** 1563151Seric ** Returns: 1573151Seric ** a copy of 'list'. 1583151Seric ** 1593151Seric ** Side Effects: 1603151Seric ** none. 1613151Seric */ 1623151Seric 1633151Seric char ** 1643151Seric copyplist(list, copycont) 1653151Seric char **list; 1663151Seric bool copycont; 1673151Seric { 1683151Seric register char **vp; 1693151Seric register char **newvp; 1703151Seric 1713151Seric for (vp = list; *vp != NULL; vp++) 1723151Seric continue; 1733151Seric 1743151Seric vp++; 1753151Seric 1767007Seric newvp = (char **) xalloc((vp - list) * sizeof *vp); 1774086Seric bmove((char *) list, (char *) newvp, (vp - list) * sizeof *vp); 1783151Seric 1793151Seric if (copycont) 1803151Seric { 1813151Seric for (vp = newvp; *vp != NULL; vp++) 1823151Seric *vp = newstr(*vp); 1833151Seric } 1843151Seric 1853151Seric return (newvp); 1863151Seric } 1873151Seric /* 1883151Seric ** PRINTAV -- print argument vector. 1893151Seric ** 1903151Seric ** Parameters: 1913151Seric ** av -- argument vector. 1923151Seric ** 1933151Seric ** Returns: 1943151Seric ** none. 1953151Seric ** 1963151Seric ** Side Effects: 1973151Seric ** prints av. 1983151Seric */ 1993151Seric 2003151Seric # ifdef DEBUG 2013151Seric printav(av) 2023151Seric register char **av; 2033151Seric { 2043151Seric while (*av != NULL) 2053151Seric { 2068063Seric if (tTd(0, 44)) 2078063Seric printf("\n\t%08x=", *av); 2088063Seric else 2098063Seric putchar(' '); 2103151Seric xputs(*av++); 2113151Seric } 2128063Seric putchar('\n'); 2133151Seric } 2143151Seric # endif DEBUG 2153151Seric /* 2163151Seric ** LOWER -- turn letter into lower case. 2173151Seric ** 2183151Seric ** Parameters: 2193151Seric ** c -- character to turn into lower case. 2203151Seric ** 2213151Seric ** Returns: 2223151Seric ** c, in lower case. 2233151Seric ** 2243151Seric ** Side Effects: 2253151Seric ** none. 2263151Seric */ 2273151Seric 2283151Seric char 2293151Seric lower(c) 2303151Seric register char c; 2313151Seric { 2323151Seric if (isascii(c) && isupper(c)) 2333151Seric c = c - 'A' + 'a'; 2343151Seric return (c); 2353151Seric } 2363151Seric /* 2373151Seric ** XPUTS -- put string doing control escapes. 2383151Seric ** 2393151Seric ** Parameters: 2403151Seric ** s -- string to put. 2413151Seric ** 2423151Seric ** Returns: 2433151Seric ** none. 2443151Seric ** 2453151Seric ** Side Effects: 2463151Seric ** output to stdout 2473151Seric */ 2483151Seric 2493151Seric # ifdef DEBUG 2503151Seric xputs(s) 2513151Seric register char *s; 2523151Seric { 2533151Seric register char c; 2543151Seric 2558055Seric if (s == NULL) 2568055Seric { 2578055Seric printf("<null>"); 2588055Seric return; 2598055Seric } 2608063Seric putchar('"'); 2613151Seric while ((c = *s++) != '\0') 2623151Seric { 2633151Seric if (!isascii(c)) 2643151Seric { 2653151Seric putchar('\\'); 2663151Seric c &= 0177; 2673151Seric } 26810326Seric if (c < 040 || c >= 0177) 2693151Seric { 2703151Seric putchar('^'); 27110326Seric c ^= 0100; 2723151Seric } 2733151Seric putchar(c); 2743151Seric } 2758063Seric putchar('"'); 2764086Seric (void) fflush(stdout); 2773151Seric } 2783151Seric # endif DEBUG 2793151Seric /* 2803151Seric ** MAKELOWER -- Translate a line into lower case 2813151Seric ** 2823151Seric ** Parameters: 2833151Seric ** p -- the string to translate. If NULL, return is 2843151Seric ** immediate. 2853151Seric ** 2863151Seric ** Returns: 2873151Seric ** none. 2883151Seric ** 2893151Seric ** Side Effects: 2903151Seric ** String pointed to by p is translated to lower case. 2913151Seric ** 2923151Seric ** Called By: 2933151Seric ** parse 2943151Seric */ 2953151Seric 2963151Seric makelower(p) 2973151Seric register char *p; 2983151Seric { 2993151Seric register char c; 3003151Seric 3013151Seric if (p == NULL) 3023151Seric return; 3033151Seric for (; (c = *p) != '\0'; p++) 3043151Seric if (isascii(c) && isupper(c)) 3053151Seric *p = c - 'A' + 'a'; 3063151Seric } 3074059Seric /* 3084059Seric ** SAMEWORD -- return TRUE if the words are the same 3094059Seric ** 3104059Seric ** Ignores case. 3114059Seric ** 3124059Seric ** Parameters: 3134059Seric ** a, b -- the words to compare. 3144059Seric ** 3154059Seric ** Returns: 3164059Seric ** TRUE if a & b match exactly (modulo case) 3174059Seric ** FALSE otherwise. 3184059Seric ** 3194059Seric ** Side Effects: 3204059Seric ** none. 3214059Seric */ 3224059Seric 3234059Seric bool 3244059Seric sameword(a, b) 3254059Seric register char *a, *b; 3264059Seric { 3274059Seric while (lower(*a) == lower(*b)) 3284059Seric { 3294059Seric if (*a == '\0') 3304059Seric return (TRUE); 3314059Seric a++; 3324059Seric b++; 3334059Seric } 3344059Seric return (FALSE); 3354059Seric } 3364086Seric /* 3374101Seric ** CLEAR -- clear a block of memory 3384101Seric ** 3394101Seric ** Parameters: 3404101Seric ** p -- location to clear. 3414101Seric ** l -- number of bytes to clear. 3424101Seric ** 3434101Seric ** Returns: 3444101Seric ** none. 3454101Seric ** 3464101Seric ** Side Effects: 3474101Seric ** none. 3484101Seric */ 3494101Seric 3504101Seric clear(p, l) 3514101Seric register char *p; 3524101Seric register int l; 3534101Seric { 3544101Seric while (l-- > 0) 3554101Seric *p++ = 0; 3564101Seric } 3574101Seric /* 3585196Seric ** BUILDFNAME -- build full name from gecos style entry. 3594375Seric ** 3605196Seric ** This routine interprets the strange entry that would appear 3615196Seric ** in the GECOS field of the password file. 3625196Seric ** 3634375Seric ** Parameters: 3645196Seric ** p -- name to build. 3655196Seric ** login -- the login name of this user (for &). 3665196Seric ** buf -- place to put the result. 3674375Seric ** 3684375Seric ** Returns: 3694375Seric ** none. 3704375Seric ** 3714375Seric ** Side Effects: 3724375Seric ** none. 3734375Seric */ 3744375Seric 3755196Seric buildfname(p, login, buf) 3765196Seric register char *p; 3775196Seric char *login; 3784375Seric char *buf; 3794375Seric { 3804375Seric register char *bp = buf; 3814375Seric 3824438Seric if (*p == '*') 3834438Seric p++; 3846278Seric while (*p != '\0' && *p != ',' && *p != ';' && *p != '%') 3854375Seric { 3864375Seric if (*p == '&') 3874375Seric { 3885196Seric (void) strcpy(bp, login); 3894375Seric *bp = toupper(*bp); 3904375Seric while (*bp != '\0') 3914375Seric bp++; 3924375Seric p++; 3934375Seric } 3944375Seric else 3954375Seric *bp++ = *p++; 3964375Seric } 3974375Seric *bp = '\0'; 3984375Seric } 3994375Seric /* 4004538Seric ** SAFEFILE -- return true if a file exists and is safe for a user. 4014538Seric ** 4024538Seric ** Parameters: 4034538Seric ** fn -- filename to check. 4044538Seric ** uid -- uid to compare against. 4054538Seric ** mode -- mode bits that must match. 4064538Seric ** 4074538Seric ** Returns: 4084538Seric ** TRUE if fn exists, is owned by uid, and matches mode. 4094538Seric ** FALSE otherwise. 4104538Seric ** 4114538Seric ** Side Effects: 4124538Seric ** none. 4134538Seric */ 4144538Seric 4154538Seric bool 4164538Seric safefile(fn, uid, mode) 4174538Seric char *fn; 4184538Seric int uid; 4194538Seric int mode; 4204538Seric { 4214538Seric struct stat stbuf; 4224538Seric 4234538Seric if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid && 4244538Seric (stbuf.st_mode & mode) == mode) 4254538Seric return (TRUE); 42611936Seric errno = 0; 4274538Seric return (FALSE); 4284538Seric } 4294538Seric /* 4304557Seric ** FIXCRLF -- fix <CR><LF> in line. 4314557Seric ** 4324557Seric ** Looks for the <CR><LF> combination and turns it into the 4334557Seric ** UNIX canonical <NL> character. It only takes one line, 4344557Seric ** i.e., it is assumed that the first <NL> found is the end 4354557Seric ** of the line. 4364557Seric ** 4374557Seric ** Parameters: 4384557Seric ** line -- the line to fix. 4394557Seric ** stripnl -- if true, strip the newline also. 4404557Seric ** 4414557Seric ** Returns: 4424557Seric ** none. 4434557Seric ** 4444557Seric ** Side Effects: 4454557Seric ** line is changed in place. 4464557Seric */ 4474557Seric 4484557Seric fixcrlf(line, stripnl) 4494557Seric char *line; 4504557Seric bool stripnl; 4514557Seric { 4524557Seric register char *p; 4534557Seric 4544557Seric p = index(line, '\n'); 4554557Seric if (p == NULL) 4564557Seric return; 4574794Seric if (p[-1] == '\r') 4584557Seric p--; 4594557Seric if (!stripnl) 4604557Seric *p++ = '\n'; 4614557Seric *p = '\0'; 4624557Seric } 4634557Seric /* 4644086Seric ** SYSLOG -- fake entry to fool lint 4654086Seric */ 4664086Seric 4674086Seric # ifdef LOG 4684086Seric # ifdef lint 4694086Seric 4704086Seric /*VARARGS2*/ 4714086Seric syslog(pri, fmt, args) 4724086Seric int pri; 4734086Seric char *fmt; 4744086Seric { 4754086Seric pri = *fmt; 4764086Seric args = pri; 4774086Seric pri = args; 4784086Seric } 4794086Seric 4804086Seric # endif lint 4814086Seric # endif LOG 4826890Seric /* 4836890Seric ** DFOPEN -- determined file open 4846890Seric ** 4856890Seric ** This routine has the semantics of fopen, except that it will 4866890Seric ** keep trying a few times to make this happen. The idea is that 4876890Seric ** on very loaded systems, we may run out of resources (inodes, 4886890Seric ** whatever), so this tries to get around it. 4896890Seric */ 4906890Seric 4916890Seric FILE * 4926890Seric dfopen(filename, mode) 4936890Seric char *filename; 4946890Seric char *mode; 4956890Seric { 4966890Seric register int tries; 4976890Seric register FILE *fp; 4986890Seric 4996890Seric for (tries = 0; tries < 10; tries++) 5006890Seric { 5016890Seric sleep(10 * tries); 5026890Seric errno = 0; 5036890Seric fp = fopen(filename, mode); 5049376Seric if (fp != NULL) 5056890Seric break; 5069376Seric if (errno != ENFILE && errno != EINTR) 5079376Seric break; 5086890Seric } 50911936Seric errno = 0; 5106890Seric return (fp); 5116890Seric } 5127124Seric /* 5137124Seric ** PUTLINE -- put a line like fputs obeying SMTP conventions 5147124Seric ** 5157753Seric ** This routine always guarantees outputing a newline (or CRLF, 5167753Seric ** as appropriate) at the end of the string. 5177753Seric ** 5187124Seric ** Parameters: 5197124Seric ** l -- line to put. 5207124Seric ** fp -- file to put it onto. 52110172Seric ** m -- the mailer used to control output. 5227124Seric ** 5237124Seric ** Returns: 5247124Seric ** none 5257124Seric ** 5267124Seric ** Side Effects: 5277124Seric ** output of l to fp. 5287124Seric */ 5297124Seric 5307753Seric # define SMTPLINELIM 990 /* maximum line length */ 5317124Seric 53210172Seric putline(l, fp, m) 5337753Seric register char *l; 5347124Seric FILE *fp; 53510172Seric MAILER *m; 5367124Seric { 5377124Seric register char *p; 5387753Seric char svchar; 5397124Seric 54011275Seric /* strip out 0200 bits -- these can look like TELNET protocol */ 54111275Seric if (bitnset(M_LIMITS, m->m_flags)) 54211275Seric { 54311275Seric p = l; 54411275Seric while ((*p++ &= ~0200) != 0) 54511275Seric continue; 54611275Seric } 54711275Seric 5487753Seric do 5497124Seric { 5507753Seric /* find the end of the line */ 5517753Seric p = index(l, '\n'); 5527753Seric if (p == NULL) 5537753Seric p = &l[strlen(l)]; 5547124Seric 5557753Seric /* check for line overflow */ 55611275Seric while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags)) 5577753Seric { 5587753Seric register char *q = &l[SMTPLINELIM - 1]; 5597124Seric 5607753Seric svchar = *q; 5617753Seric *q = '\0'; 56210685Seric if (l[0] == '.' && bitnset(M_XDOT, m->m_flags)) 56310172Seric fputc('.', fp); 5647753Seric fputs(l, fp); 56510066Seric fputc('!', fp); 56610326Seric fputs(m->m_eol, fp); 5677753Seric *q = svchar; 5687753Seric l = q; 5697753Seric } 5707124Seric 5717753Seric /* output last part */ 5727753Seric svchar = *p; 5737753Seric *p = '\0'; 57410685Seric if (l[0] == '.' && bitnset(M_XDOT, m->m_flags)) 57510172Seric fputc('.', fp); 5767124Seric fputs(l, fp); 57710326Seric fputs(m->m_eol, fp); 5787753Seric *p = svchar; 5797753Seric l = p; 5807753Seric if (*l == '\n') 5817753Seric l++; 5827753Seric } while (l[0] != '\0'); 5837124Seric } 5847676Seric /* 5857676Seric ** XUNLINK -- unlink a file, doing logging as appropriate. 5867676Seric ** 5877676Seric ** Parameters: 5887676Seric ** f -- name of file to unlink. 5897676Seric ** 5907676Seric ** Returns: 5917676Seric ** none. 5927676Seric ** 5937676Seric ** Side Effects: 5947676Seric ** f is unlinked. 5957676Seric */ 5967676Seric 5977676Seric xunlink(f) 5987676Seric char *f; 5997676Seric { 6007676Seric register int i; 6017676Seric 6027676Seric # ifdef LOG 6037676Seric if (LogLevel > 20) 6047812Seric syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f); 6057676Seric # endif LOG 6067676Seric 6077676Seric i = unlink(f); 6087676Seric # ifdef LOG 6097676Seric if (i < 0 && LogLevel > 21) 6107942Seric syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno); 6117676Seric # endif LOG 6127676Seric } 6137685Seric /* 614*14885Seric ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 6157685Seric ** 6167685Seric ** Parameters: 6177685Seric ** buf -- place to put the input line. 6187685Seric ** siz -- size of buf. 6197685Seric ** fp -- file to read from. 6207685Seric ** 6217685Seric ** Returns: 6227685Seric ** NULL on error (including timeout). 6237685Seric ** buf otherwise. 6247685Seric ** 6257685Seric ** Side Effects: 6267685Seric ** none. 6277685Seric */ 6287685Seric 629*14885Seric static jmp_buf CtxReadTimeout; 6307685Seric 6317685Seric char * 6327685Seric sfgets(buf, siz, fp) 6337685Seric char *buf; 6347685Seric int siz; 6357685Seric FILE *fp; 6367685Seric { 6377942Seric register EVENT *ev = NULL; 6387685Seric register char *p; 6397685Seric extern readtimeout(); 6407685Seric 641*14885Seric /* set the timeout */ 6427942Seric if (ReadTimeout != 0) 643*14885Seric { 644*14885Seric if (setjmp(CtxReadTimeout) != 0) 645*14885Seric { 646*14885Seric syserr("sfgets: timeout on read (mailer may be hung)"); 647*14885Seric return (NULL); 648*14885Seric } 6497942Seric ev = setevent(ReadTimeout, readtimeout, 0); 650*14885Seric } 651*14885Seric 652*14885Seric /* try to read */ 6537942Seric do 6547942Seric { 6557942Seric errno = 0; 6567942Seric p = fgets(buf, siz, fp); 657*14885Seric } while (p == NULL && errno == EINTR); 658*14885Seric 659*14885Seric /* clear the event if it has not sprung */ 6607685Seric clrevent(ev); 661*14885Seric 662*14885Seric /* clean up the books and exit */ 6638055Seric LineNumber++; 6647685Seric return (p); 6657685Seric } 6667685Seric 6677685Seric static 6687685Seric readtimeout() 6697685Seric { 670*14885Seric longjmp(CtxReadTimeout, 1); 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--; 69910030Seric while (fgets(p, n, f) != NULL) 7007786Seric { 70110030Seric 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 } 83210685Seric /* 83310685Seric ** BITINTERSECT -- tell if two bitmaps intersect 83410685Seric ** 83510685Seric ** Parameters: 83610685Seric ** a, b -- the bitmaps in question 83710685Seric ** 83810685Seric ** Returns: 83910685Seric ** TRUE if they have a non-null intersection 84010685Seric ** FALSE otherwise 84110685Seric ** 84210685Seric ** Side Effects: 84310685Seric ** none. 84410685Seric */ 84510685Seric 84610685Seric bool 84710685Seric bitintersect(a, b) 84810685Seric BITMAP a; 84910685Seric BITMAP b; 85010685Seric { 85110685Seric int i; 85210685Seric 85310685Seric for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 85410685Seric if ((a[i] & b[i]) != 0) 85510685Seric return (TRUE); 85610685Seric return (FALSE); 85710685Seric } 85810685Seric /* 85910685Seric ** BITZEROP -- tell if a bitmap is all zero 86010685Seric ** 86110685Seric ** Parameters: 86210685Seric ** map -- the bit map to check 86310685Seric ** 86410685Seric ** Returns: 86510685Seric ** TRUE if map is all zero. 86610685Seric ** FALSE if there are any bits set in map. 86710685Seric ** 86810685Seric ** Side Effects: 86910685Seric ** none. 87010685Seric */ 87110685Seric 87210685Seric bool 87310685Seric bitzerop(map) 87410685Seric BITMAP map; 87510685Seric { 87610685Seric int i; 87710685Seric 87810685Seric for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 87910685Seric if (map[i] != 0) 88010685Seric return (FALSE); 88110685Seric return (TRUE); 88210685Seric } 883