122717Sdist /* 233731Sbostic * Copyright (c) 1988 Regents of the University of California. 333731Sbostic * All rights reserved. 433731Sbostic * 533731Sbostic * Redistribution and use in source and binary forms are permitted 633731Sbostic * provided that this notice is preserved and that due credit is given 733731Sbostic * to the University of California at Berkeley. The name of the University 833731Sbostic * may not be used to endorse or promote products derived from this 933731Sbostic * software without specific prior written permission. This software 1033731Sbostic * is provided ``as is'' without express or implied warranty. 1133731Sbostic * 1233731Sbostic * Sendmail 1333731Sbostic * Copyright (c) 1983 Eric P. Allman 1433731Sbostic * Berkeley, California 1533731Sbostic */ 1622717Sdist 1722717Sdist #ifndef lint 18*40999Sbostic static char sccsid[] = "@(#)util.c 5.17 (Berkeley) 04/19/90"; 1933731Sbostic #endif /* not lint */ 2022717Sdist 213151Seric # include <stdio.h> 224538Seric # include <sys/types.h> 234538Seric # include <sys/stat.h> 24298Seric # include <sysexits.h> 256890Seric # include <errno.h> 266890Seric # include "sendmail.h" 27298Seric 28298Seric /* 29298Seric ** STRIPQUOTES -- Strip quotes & quote bits from a string. 30298Seric ** 31298Seric ** Runs through a string and strips off unquoted quote 32298Seric ** characters and quote bits. This is done in place. 33298Seric ** 34298Seric ** Parameters: 35298Seric ** s -- the string to strip. 364101Seric ** qf -- if set, remove actual `` " '' characters 374101Seric ** as well as the quote bits. 38298Seric ** 39298Seric ** Returns: 40298Seric ** none. 41298Seric ** 42298Seric ** Side Effects: 43298Seric ** none. 44298Seric ** 45298Seric ** Called By: 46298Seric ** deliver 47298Seric */ 48298Seric 494101Seric stripquotes(s, qf) 50298Seric char *s; 514101Seric bool qf; 52298Seric { 53298Seric register char *p; 54298Seric register char *q; 55298Seric register char c; 56298Seric 574101Seric if (s == NULL) 584101Seric return; 594101Seric 60298Seric for (p = q = s; (c = *p++) != '\0'; ) 61298Seric { 624101Seric if (c != '"' || !qf) 63298Seric *q++ = c & 0177; 64298Seric } 65298Seric *q = '\0'; 66298Seric } 67298Seric /* 689043Seric ** QSTRLEN -- give me the string length assuming 0200 bits add a char 699043Seric ** 709043Seric ** Parameters: 719043Seric ** s -- the string to measure. 729043Seric ** 739043Seric ** Reurns: 749043Seric ** The length of s, including space for backslash escapes. 759043Seric ** 769043Seric ** Side Effects: 779043Seric ** none. 789043Seric */ 799043Seric 809043Seric qstrlen(s) 819043Seric register char *s; 829043Seric { 839043Seric register int l = 0; 849043Seric register char c; 859043Seric 869043Seric while ((c = *s++) != '\0') 879043Seric { 889043Seric if (bitset(0200, c)) 899043Seric l++; 909043Seric l++; 919043Seric } 929043Seric return (l); 939043Seric } 949043Seric /* 952900Seric ** CAPITALIZE -- return a copy of a string, properly capitalized. 962900Seric ** 972900Seric ** Parameters: 982900Seric ** s -- the string to capitalize. 992900Seric ** 1002900Seric ** Returns: 1012900Seric ** a pointer to a properly capitalized string. 1022900Seric ** 1032900Seric ** Side Effects: 1042900Seric ** none. 1052900Seric */ 1062900Seric 1072900Seric char * 1082900Seric capitalize(s) 1092900Seric register char *s; 1102900Seric { 1112900Seric static char buf[50]; 1122900Seric register char *p; 1132900Seric 1142900Seric p = buf; 1152900Seric 1162900Seric for (;;) 1172900Seric { 1182900Seric while (!isalpha(*s) && *s != '\0') 1192900Seric *p++ = *s++; 1202900Seric if (*s == '\0') 1212900Seric break; 122*40999Sbostic *p++ = toupper(*s); 123*40999Sbostic s++; 1242900Seric while (isalpha(*s)) 1252900Seric *p++ = *s++; 1262900Seric } 1272900Seric 1282900Seric *p = '\0'; 1292900Seric return (buf); 1302900Seric } 1312900Seric /* 132298Seric ** XALLOC -- Allocate memory and bitch wildly on failure. 133298Seric ** 134298Seric ** THIS IS A CLUDGE. This should be made to give a proper 135298Seric ** error -- but after all, what can we do? 136298Seric ** 137298Seric ** Parameters: 138298Seric ** sz -- size of area to allocate. 139298Seric ** 140298Seric ** Returns: 141298Seric ** pointer to data region. 142298Seric ** 143298Seric ** Side Effects: 144298Seric ** Memory is allocated. 145298Seric */ 146298Seric 147298Seric char * 148298Seric xalloc(sz) 1497007Seric register int sz; 150298Seric { 151298Seric register char *p; 15223121Seric extern char *malloc(); 153298Seric 15423121Seric p = malloc((unsigned) sz); 155298Seric if (p == NULL) 156298Seric { 157298Seric syserr("Out of memory!!"); 15810685Seric abort(); 15910685Seric /* exit(EX_UNAVAILABLE); */ 160298Seric } 161298Seric return (p); 162298Seric } 163298Seric /* 1643151Seric ** COPYPLIST -- copy list of pointers. 1653151Seric ** 1663151Seric ** This routine is the equivalent of newstr for lists of 1673151Seric ** pointers. 1683151Seric ** 1693151Seric ** Parameters: 1703151Seric ** list -- list of pointers to copy. 1713151Seric ** Must be NULL terminated. 1723151Seric ** copycont -- if TRUE, copy the contents of the vector 1733151Seric ** (which must be a string) also. 1743151Seric ** 1753151Seric ** Returns: 1763151Seric ** a copy of 'list'. 1773151Seric ** 1783151Seric ** Side Effects: 1793151Seric ** none. 1803151Seric */ 1813151Seric 1823151Seric char ** 1833151Seric copyplist(list, copycont) 1843151Seric char **list; 1853151Seric bool copycont; 1863151Seric { 1873151Seric register char **vp; 1883151Seric register char **newvp; 1893151Seric 1903151Seric for (vp = list; *vp != NULL; vp++) 1913151Seric continue; 1923151Seric 1933151Seric vp++; 1943151Seric 19516897Seric newvp = (char **) xalloc((int) (vp - list) * sizeof *vp); 19616897Seric bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp); 1973151Seric 1983151Seric if (copycont) 1993151Seric { 2003151Seric for (vp = newvp; *vp != NULL; vp++) 2013151Seric *vp = newstr(*vp); 2023151Seric } 2033151Seric 2043151Seric return (newvp); 2053151Seric } 2063151Seric /* 2073151Seric ** PRINTAV -- print argument vector. 2083151Seric ** 2093151Seric ** Parameters: 2103151Seric ** av -- argument vector. 2113151Seric ** 2123151Seric ** Returns: 2133151Seric ** none. 2143151Seric ** 2153151Seric ** Side Effects: 2163151Seric ** prints av. 2173151Seric */ 2183151Seric 2193151Seric printav(av) 2203151Seric register char **av; 2213151Seric { 2223151Seric while (*av != NULL) 2233151Seric { 2248063Seric if (tTd(0, 44)) 2258063Seric printf("\n\t%08x=", *av); 2268063Seric else 22723105Seric (void) putchar(' '); 2283151Seric xputs(*av++); 2293151Seric } 23023105Seric (void) putchar('\n'); 2313151Seric } 2323151Seric /* 2333151Seric ** LOWER -- turn letter into lower case. 2343151Seric ** 2353151Seric ** Parameters: 2363151Seric ** c -- character to turn into lower case. 2373151Seric ** 2383151Seric ** Returns: 2393151Seric ** c, in lower case. 2403151Seric ** 2413151Seric ** Side Effects: 2423151Seric ** none. 2433151Seric */ 2443151Seric 2453151Seric char 2463151Seric lower(c) 2473151Seric register char c; 2483151Seric { 24933724Sbostic return(isascii(c) && isupper(c) ? tolower(c) : c); 2503151Seric } 2513151Seric /* 2523151Seric ** XPUTS -- put string doing control escapes. 2533151Seric ** 2543151Seric ** Parameters: 2553151Seric ** s -- string to put. 2563151Seric ** 2573151Seric ** Returns: 2583151Seric ** none. 2593151Seric ** 2603151Seric ** Side Effects: 2613151Seric ** output to stdout 2623151Seric */ 2633151Seric 2643151Seric xputs(s) 2653151Seric register char *s; 2663151Seric { 2673151Seric register char c; 2683151Seric 2698055Seric if (s == NULL) 2708055Seric { 2718055Seric printf("<null>"); 2728055Seric return; 2738055Seric } 27423105Seric (void) putchar('"'); 2753151Seric while ((c = *s++) != '\0') 2763151Seric { 2773151Seric if (!isascii(c)) 2783151Seric { 27923105Seric (void) putchar('\\'); 2803151Seric c &= 0177; 2813151Seric } 28210326Seric if (c < 040 || c >= 0177) 2833151Seric { 28423105Seric (void) putchar('^'); 28510326Seric c ^= 0100; 2863151Seric } 28723105Seric (void) putchar(c); 2883151Seric } 28923105Seric (void) putchar('"'); 2904086Seric (void) fflush(stdout); 2913151Seric } 2923151Seric /* 2933151Seric ** MAKELOWER -- Translate a line into lower case 2943151Seric ** 2953151Seric ** Parameters: 2963151Seric ** p -- the string to translate. If NULL, return is 2973151Seric ** immediate. 2983151Seric ** 2993151Seric ** Returns: 3003151Seric ** none. 3013151Seric ** 3023151Seric ** Side Effects: 3033151Seric ** String pointed to by p is translated to lower case. 3043151Seric ** 3053151Seric ** Called By: 3063151Seric ** parse 3073151Seric */ 3083151Seric 3093151Seric makelower(p) 3103151Seric register char *p; 3113151Seric { 3123151Seric register char c; 3133151Seric 3143151Seric if (p == NULL) 3153151Seric return; 3163151Seric for (; (c = *p) != '\0'; p++) 3173151Seric if (isascii(c) && isupper(c)) 31833724Sbostic *p = tolower(c); 3193151Seric } 3204059Seric /* 3215196Seric ** BUILDFNAME -- build full name from gecos style entry. 3224375Seric ** 3235196Seric ** This routine interprets the strange entry that would appear 3245196Seric ** in the GECOS field of the password file. 3255196Seric ** 3264375Seric ** Parameters: 3275196Seric ** p -- name to build. 3285196Seric ** login -- the login name of this user (for &). 3295196Seric ** buf -- place to put the result. 3304375Seric ** 3314375Seric ** Returns: 3324375Seric ** none. 3334375Seric ** 3344375Seric ** Side Effects: 3354375Seric ** none. 3364375Seric */ 3374375Seric 3385196Seric buildfname(p, login, buf) 3395196Seric register char *p; 3405196Seric char *login; 3414375Seric char *buf; 3424375Seric { 3434375Seric register char *bp = buf; 3444375Seric 3454438Seric if (*p == '*') 3464438Seric p++; 3476278Seric while (*p != '\0' && *p != ',' && *p != ';' && *p != '%') 3484375Seric { 3494375Seric if (*p == '&') 3504375Seric { 3515196Seric (void) strcpy(bp, login); 3524375Seric *bp = toupper(*bp); 3534375Seric while (*bp != '\0') 3544375Seric bp++; 3554375Seric p++; 3564375Seric } 3574375Seric else 3584375Seric *bp++ = *p++; 3594375Seric } 3604375Seric *bp = '\0'; 3614375Seric } 3624375Seric /* 3634538Seric ** SAFEFILE -- return true if a file exists and is safe for a user. 3644538Seric ** 3654538Seric ** Parameters: 3664538Seric ** fn -- filename to check. 3674538Seric ** uid -- uid to compare against. 3684538Seric ** mode -- mode bits that must match. 3694538Seric ** 3704538Seric ** Returns: 3714538Seric ** TRUE if fn exists, is owned by uid, and matches mode. 3724538Seric ** FALSE otherwise. 3734538Seric ** 3744538Seric ** Side Effects: 3754538Seric ** none. 3764538Seric */ 3774538Seric 3784538Seric bool 3794538Seric safefile(fn, uid, mode) 3804538Seric char *fn; 3814538Seric int uid; 3824538Seric int mode; 3834538Seric { 3844538Seric struct stat stbuf; 3854538Seric 3864538Seric if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid && 3874538Seric (stbuf.st_mode & mode) == mode) 3884538Seric return (TRUE); 38911936Seric errno = 0; 3904538Seric return (FALSE); 3914538Seric } 3924538Seric /* 3934557Seric ** FIXCRLF -- fix <CR><LF> in line. 3944557Seric ** 3954557Seric ** Looks for the <CR><LF> combination and turns it into the 3964557Seric ** UNIX canonical <NL> character. It only takes one line, 3974557Seric ** i.e., it is assumed that the first <NL> found is the end 3984557Seric ** of the line. 3994557Seric ** 4004557Seric ** Parameters: 4014557Seric ** line -- the line to fix. 4024557Seric ** stripnl -- if true, strip the newline also. 4034557Seric ** 4044557Seric ** Returns: 4054557Seric ** none. 4064557Seric ** 4074557Seric ** Side Effects: 4084557Seric ** line is changed in place. 4094557Seric */ 4104557Seric 4114557Seric fixcrlf(line, stripnl) 4124557Seric char *line; 4134557Seric bool stripnl; 4144557Seric { 4154557Seric register char *p; 4164557Seric 4174557Seric p = index(line, '\n'); 4184557Seric if (p == NULL) 4194557Seric return; 42036291Sbostic if (p > line && p[-1] == '\r') 4214557Seric p--; 4224557Seric if (!stripnl) 4234557Seric *p++ = '\n'; 4244557Seric *p = '\0'; 4254557Seric } 4264557Seric /* 4276890Seric ** DFOPEN -- determined file open 4286890Seric ** 4296890Seric ** This routine has the semantics of fopen, except that it will 4306890Seric ** keep trying a few times to make this happen. The idea is that 4316890Seric ** on very loaded systems, we may run out of resources (inodes, 4326890Seric ** whatever), so this tries to get around it. 4336890Seric */ 4346890Seric 4356890Seric FILE * 4366890Seric dfopen(filename, mode) 4376890Seric char *filename; 4386890Seric char *mode; 4396890Seric { 4406890Seric register int tries; 4416890Seric register FILE *fp; 4426890Seric 4436890Seric for (tries = 0; tries < 10; tries++) 4446890Seric { 44525618Seric sleep((unsigned) (10 * tries)); 4466890Seric errno = 0; 4476890Seric fp = fopen(filename, mode); 4489376Seric if (fp != NULL) 4496890Seric break; 4509376Seric if (errno != ENFILE && errno != EINTR) 4519376Seric break; 4526890Seric } 45311936Seric errno = 0; 4546890Seric return (fp); 4556890Seric } 4567124Seric /* 4577124Seric ** PUTLINE -- put a line like fputs obeying SMTP conventions 4587124Seric ** 4597753Seric ** This routine always guarantees outputing a newline (or CRLF, 4607753Seric ** as appropriate) at the end of the string. 4617753Seric ** 4627124Seric ** Parameters: 4637124Seric ** l -- line to put. 4647124Seric ** fp -- file to put it onto. 46510172Seric ** m -- the mailer used to control output. 4667124Seric ** 4677124Seric ** Returns: 4687124Seric ** none 4697124Seric ** 4707124Seric ** Side Effects: 4717124Seric ** output of l to fp. 4727124Seric */ 4737124Seric 4747753Seric # define SMTPLINELIM 990 /* maximum line length */ 4757124Seric 47610172Seric putline(l, fp, m) 4777753Seric register char *l; 4787124Seric FILE *fp; 47910172Seric MAILER *m; 4807124Seric { 4817124Seric register char *p; 4827753Seric char svchar; 4837124Seric 48411275Seric /* strip out 0200 bits -- these can look like TELNET protocol */ 48511275Seric if (bitnset(M_LIMITS, m->m_flags)) 48611275Seric { 48711275Seric p = l; 48811275Seric while ((*p++ &= ~0200) != 0) 48911275Seric continue; 49011275Seric } 49111275Seric 4927753Seric do 4937124Seric { 4947753Seric /* find the end of the line */ 4957753Seric p = index(l, '\n'); 4967753Seric if (p == NULL) 4977753Seric p = &l[strlen(l)]; 4987124Seric 4997753Seric /* check for line overflow */ 50011275Seric while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags)) 5017753Seric { 5027753Seric register char *q = &l[SMTPLINELIM - 1]; 5037124Seric 5047753Seric svchar = *q; 5057753Seric *q = '\0'; 50610685Seric if (l[0] == '.' && bitnset(M_XDOT, m->m_flags)) 50723105Seric (void) putc('.', fp); 5087753Seric fputs(l, fp); 50923105Seric (void) putc('!', fp); 51010326Seric fputs(m->m_eol, fp); 5117753Seric *q = svchar; 5127753Seric l = q; 5137753Seric } 5147124Seric 5157753Seric /* output last part */ 5167753Seric svchar = *p; 5177753Seric *p = '\0'; 51810685Seric if (l[0] == '.' && bitnset(M_XDOT, m->m_flags)) 51923105Seric (void) putc('.', fp); 5207124Seric fputs(l, fp); 52110326Seric fputs(m->m_eol, fp); 5227753Seric *p = svchar; 5237753Seric l = p; 5247753Seric if (*l == '\n') 5257753Seric l++; 5267753Seric } while (l[0] != '\0'); 5277124Seric } 5287676Seric /* 5297676Seric ** XUNLINK -- unlink a file, doing logging as appropriate. 5307676Seric ** 5317676Seric ** Parameters: 5327676Seric ** f -- name of file to unlink. 5337676Seric ** 5347676Seric ** Returns: 5357676Seric ** none. 5367676Seric ** 5377676Seric ** Side Effects: 5387676Seric ** f is unlinked. 5397676Seric */ 5407676Seric 5417676Seric xunlink(f) 5427676Seric char *f; 5437676Seric { 5447676Seric register int i; 5457676Seric 5467676Seric # ifdef LOG 5477676Seric if (LogLevel > 20) 5487812Seric syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f); 5497676Seric # endif LOG 5507676Seric 5517676Seric i = unlink(f); 5527676Seric # ifdef LOG 5537676Seric if (i < 0 && LogLevel > 21) 5547942Seric syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno); 5557676Seric # endif LOG 5567676Seric } 5577685Seric /* 55814885Seric ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 5597685Seric ** 5607685Seric ** Parameters: 5617685Seric ** buf -- place to put the input line. 5627685Seric ** siz -- size of buf. 5637685Seric ** fp -- file to read from. 5647685Seric ** 5657685Seric ** Returns: 56615533Seric ** NULL on error (including timeout). This will also leave 56715533Seric ** buf containing a null string. 5687685Seric ** buf otherwise. 5697685Seric ** 5707685Seric ** Side Effects: 5717685Seric ** none. 5727685Seric */ 5737685Seric 57414885Seric static jmp_buf CtxReadTimeout; 5757685Seric 5767685Seric char * 5777685Seric sfgets(buf, siz, fp) 5787685Seric char *buf; 5797685Seric int siz; 5807685Seric FILE *fp; 5817685Seric { 5827942Seric register EVENT *ev = NULL; 5837685Seric register char *p; 5847685Seric extern readtimeout(); 5857685Seric 58614885Seric /* set the timeout */ 5877942Seric if (ReadTimeout != 0) 58814885Seric { 58914885Seric if (setjmp(CtxReadTimeout) != 0) 59014885Seric { 59136233Skarels # ifdef LOG 59236230Skarels syslog(LOG_NOTICE, 59336230Skarels "timeout waiting for input from %s\n", 59440998Sbostic RealHostName? RealHostName: "local"); 59536233Skarels # endif 59636230Skarels errno = 0; 59740964Sbostic usrerr("451 timeout waiting for input"); 59819037Seric buf[0] = '\0'; 59914885Seric return (NULL); 60014885Seric } 60116138Seric ev = setevent((time_t) ReadTimeout, readtimeout, 0); 60214885Seric } 60314885Seric 60414885Seric /* try to read */ 60515533Seric p = NULL; 60615533Seric while (p == NULL && !feof(fp) && !ferror(fp)) 6077942Seric { 6087942Seric errno = 0; 6097942Seric p = fgets(buf, siz, fp); 61015533Seric if (errno == EINTR) 61115533Seric clearerr(fp); 61215533Seric } 61314885Seric 61414885Seric /* clear the event if it has not sprung */ 6157685Seric clrevent(ev); 61614885Seric 61714885Seric /* clean up the books and exit */ 6188055Seric LineNumber++; 61915533Seric if (p == NULL) 62016880Seric { 62115533Seric buf[0] = '\0'; 62216880Seric return (NULL); 62316880Seric } 62416880Seric for (p = buf; *p != '\0'; p++) 62516880Seric *p &= ~0200; 62616880Seric return (buf); 6277685Seric } 6287685Seric 6297685Seric static 6307685Seric readtimeout() 6317685Seric { 63214885Seric longjmp(CtxReadTimeout, 1); 6337685Seric } 6347786Seric /* 6357786Seric ** FGETFOLDED -- like fgets, but know about folded lines. 6367786Seric ** 6377786Seric ** Parameters: 6387786Seric ** buf -- place to put result. 6397786Seric ** n -- bytes available. 6407786Seric ** f -- file to read from. 6417786Seric ** 6427786Seric ** Returns: 6437786Seric ** buf on success, NULL on error or EOF. 6447786Seric ** 6457786Seric ** Side Effects: 6467786Seric ** buf gets lines from f, with continuation lines (lines 6477786Seric ** with leading white space) appended. CRLF's are mapped 6487786Seric ** into single newlines. Any trailing NL is stripped. 6497786Seric */ 6507786Seric 6517786Seric char * 6527786Seric fgetfolded(buf, n, f) 6537786Seric char *buf; 6547786Seric register int n; 6557786Seric FILE *f; 6567786Seric { 6577786Seric register char *p = buf; 6587786Seric register int i; 6597786Seric 6607786Seric n--; 66117350Seric while ((i = getc(f)) != EOF) 6627786Seric { 66317350Seric if (i == '\r') 66417350Seric { 66517350Seric i = getc(f); 66617350Seric if (i != '\n') 66717350Seric { 66817350Seric if (i != EOF) 66923105Seric (void) ungetc(i, f); 67017350Seric i = '\r'; 67117350Seric } 67217350Seric } 67317350Seric if (--n > 0) 67417350Seric *p++ = i; 67517350Seric if (i == '\n') 67617350Seric { 67717350Seric LineNumber++; 67817350Seric i = getc(f); 67917350Seric if (i != EOF) 68023105Seric (void) ungetc(i, f); 68117350Seric if (i != ' ' && i != '\t') 68217350Seric { 68317350Seric *--p = '\0'; 68417350Seric return (buf); 68517350Seric } 68617350Seric } 6877786Seric } 6887786Seric return (NULL); 6897786Seric } 6907860Seric /* 6917886Seric ** CURTIME -- return current time. 6927886Seric ** 6937886Seric ** Parameters: 6947886Seric ** none. 6957886Seric ** 6967886Seric ** Returns: 6977886Seric ** the current time. 6987886Seric ** 6997886Seric ** Side Effects: 7007886Seric ** none. 7017886Seric */ 7027886Seric 7037886Seric time_t 7047886Seric curtime() 7057886Seric { 7067886Seric auto time_t t; 7077886Seric 7087886Seric (void) time(&t); 7097886Seric return (t); 7107886Seric } 7118264Seric /* 7128264Seric ** ATOBOOL -- convert a string representation to boolean. 7138264Seric ** 7148264Seric ** Defaults to "TRUE" 7158264Seric ** 7168264Seric ** Parameters: 7178264Seric ** s -- string to convert. Takes "tTyY" as true, 7188264Seric ** others as false. 7198264Seric ** 7208264Seric ** Returns: 7218264Seric ** A boolean representation of the string. 7228264Seric ** 7238264Seric ** Side Effects: 7248264Seric ** none. 7258264Seric */ 7268264Seric 7278264Seric bool 7288264Seric atobool(s) 7298264Seric register char *s; 7308264Seric { 7318264Seric if (*s == '\0' || index("tTyY", *s) != NULL) 7328264Seric return (TRUE); 7338264Seric return (FALSE); 7348264Seric } 7359048Seric /* 7369048Seric ** ATOOCT -- convert a string representation to octal. 7379048Seric ** 7389048Seric ** Parameters: 7399048Seric ** s -- string to convert. 7409048Seric ** 7419048Seric ** Returns: 7429048Seric ** An integer representing the string interpreted as an 7439048Seric ** octal number. 7449048Seric ** 7459048Seric ** Side Effects: 7469048Seric ** none. 7479048Seric */ 7489048Seric 7499048Seric atooct(s) 7509048Seric register char *s; 7519048Seric { 7529048Seric register int i = 0; 7539048Seric 7549048Seric while (*s >= '0' && *s <= '7') 7559048Seric i = (i << 3) | (*s++ - '0'); 7569048Seric return (i); 7579048Seric } 7589376Seric /* 7599376Seric ** WAITFOR -- wait for a particular process id. 7609376Seric ** 7619376Seric ** Parameters: 7629376Seric ** pid -- process id to wait for. 7639376Seric ** 7649376Seric ** Returns: 7659376Seric ** status of pid. 7669376Seric ** -1 if pid never shows up. 7679376Seric ** 7689376Seric ** Side Effects: 7699376Seric ** none. 7709376Seric */ 7719376Seric 7729376Seric waitfor(pid) 7739376Seric int pid; 7749376Seric { 7759376Seric auto int st; 7769376Seric int i; 7779376Seric 7789376Seric do 7799376Seric { 7809376Seric errno = 0; 7819376Seric i = wait(&st); 7829376Seric } while ((i >= 0 || errno == EINTR) && i != pid); 7839376Seric if (i < 0) 7849376Seric st = -1; 7859376Seric return (st); 7869376Seric } 7879376Seric /* 78810685Seric ** BITINTERSECT -- tell if two bitmaps intersect 78910685Seric ** 79010685Seric ** Parameters: 79110685Seric ** a, b -- the bitmaps in question 79210685Seric ** 79310685Seric ** Returns: 79410685Seric ** TRUE if they have a non-null intersection 79510685Seric ** FALSE otherwise 79610685Seric ** 79710685Seric ** Side Effects: 79810685Seric ** none. 79910685Seric */ 80010685Seric 80110685Seric bool 80210685Seric bitintersect(a, b) 80310685Seric BITMAP a; 80410685Seric BITMAP b; 80510685Seric { 80610685Seric int i; 80710685Seric 80810685Seric for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 80910685Seric if ((a[i] & b[i]) != 0) 81010685Seric return (TRUE); 81110685Seric return (FALSE); 81210685Seric } 81310685Seric /* 81410685Seric ** BITZEROP -- tell if a bitmap is all zero 81510685Seric ** 81610685Seric ** Parameters: 81710685Seric ** map -- the bit map to check 81810685Seric ** 81910685Seric ** Returns: 82010685Seric ** TRUE if map is all zero. 82110685Seric ** FALSE if there are any bits set in map. 82210685Seric ** 82310685Seric ** Side Effects: 82410685Seric ** none. 82510685Seric */ 82610685Seric 82710685Seric bool 82810685Seric bitzerop(map) 82910685Seric BITMAP map; 83010685Seric { 83110685Seric int i; 83210685Seric 83310685Seric for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 83410685Seric if (map[i] != 0) 83510685Seric return (FALSE); 83610685Seric return (TRUE); 83710685Seric } 838