|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T u
Length: 20822 (0x5156) Types: TextFile Names: »util.c,v«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« └─⟦f9e35cd84⟧ └─⟦this⟧ »sendmail/src/RCS/util.c,v«
head 5.18; branch 5.18.0; access; symbols UICSO:5.18.0 VANILLA:5.18; locks; strict; comment @ * @; 5.18 date 90.06.20.08.37.21; author paul; state Exp; branches 5.18.0.1; next ; 5.18.0.1 date 90.06.20.09.44.16; author paul; state Exp; branches; next 5.18.0.2; 5.18.0.2 date 90.10.13.19.23.30; author paul; state Exp; branches; next 5.18.0.3; 5.18.0.3 date 90.11.24.17.11.49; author paul; state Exp; branches; next 5.18.0.4; 5.18.0.4 date 90.11.29.21.17.22; author paul; state Exp; branches; next 5.18.0.5; 5.18.0.5 date 91.01.19.19.26.02; author paul; state Exp; branches; next 5.18.0.6; 5.18.0.6 date 91.03.04.21.48.23; author paul; state Exp; branches; next 5.18.0.7; 5.18.0.7 date 91.03.06.15.14.22; author paul; state Exp; branches; next 5.18.0.8; 5.18.0.8 date 91.03.06.17.32.56; author paul; state Exp; branches; next ; desc @@ 5.18 log @5.64 Berkeley release @ text @/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char sccsid[] = "@@(#)util.c 5.18 (Berkeley) 6/1/90"; #endif /* not lint */ # include <stdio.h> # include <sys/types.h> # include <sys/stat.h> # include <sysexits.h> # include <errno.h> # include "sendmail.h" /* ** STRIPQUOTES -- Strip quotes & quote bits from a string. ** ** Runs through a string and strips off unquoted quote ** characters and quote bits. This is done in place. ** ** Parameters: ** s -- the string to strip. ** qf -- if set, remove actual `` " '' characters ** as well as the quote bits. ** ** Returns: ** none. ** ** Side Effects: ** none. ** ** Called By: ** deliver */ stripquotes(s, qf) char *s; bool qf; { register char *p; register char *q; register char c; if (s == NULL) return; for (p = q = s; (c = *p++) != '\0'; ) { if (c != '"' || !qf) *q++ = c & 0177; } *q = '\0'; } \f /* ** QSTRLEN -- give me the string length assuming 0200 bits add a char ** ** Parameters: ** s -- the string to measure. ** ** Reurns: ** The length of s, including space for backslash escapes. ** ** Side Effects: ** none. */ qstrlen(s) register char *s; { register int l = 0; register char c; while ((c = *s++) != '\0') { if (bitset(0200, c)) l++; l++; } return (l); } \f /* ** CAPITALIZE -- return a copy of a string, properly capitalized. ** ** Parameters: ** s -- the string to capitalize. ** ** Returns: ** a pointer to a properly capitalized string. ** ** Side Effects: ** none. */ char * capitalize(s) register char *s; { static char buf[50]; register char *p; p = buf; for (;;) { while (!isalpha(*s) && *s != '\0') *p++ = *s++; if (*s == '\0') break; *p++ = toupper(*s); s++; while (isalpha(*s)) *p++ = *s++; } *p = '\0'; return (buf); } \f /* ** XALLOC -- Allocate memory and bitch wildly on failure. ** ** THIS IS A CLUDGE. This should be made to give a proper ** error -- but after all, what can we do? ** ** Parameters: ** sz -- size of area to allocate. ** ** Returns: ** pointer to data region. ** ** Side Effects: ** Memory is allocated. */ char * xalloc(sz) register int sz; { register char *p; extern char *malloc(); p = malloc((unsigned) sz); if (p == NULL) { syserr("Out of memory!!"); abort(); /* exit(EX_UNAVAILABLE); */ } return (p); } \f /* ** COPYPLIST -- copy list of pointers. ** ** This routine is the equivalent of newstr for lists of ** pointers. ** ** Parameters: ** list -- list of pointers to copy. ** Must be NULL terminated. ** copycont -- if TRUE, copy the contents of the vector ** (which must be a string) also. ** ** Returns: ** a copy of 'list'. ** ** Side Effects: ** none. */ char ** copyplist(list, copycont) char **list; bool copycont; { register char **vp; register char **newvp; for (vp = list; *vp != NULL; vp++) continue; vp++; newvp = (char **) xalloc((int) (vp - list) * sizeof *vp); bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp); if (copycont) { for (vp = newvp; *vp != NULL; vp++) *vp = newstr(*vp); } return (newvp); } \f /* ** PRINTAV -- print argument vector. ** ** Parameters: ** av -- argument vector. ** ** Returns: ** none. ** ** Side Effects: ** prints av. */ printav(av) register char **av; { while (*av != NULL) { if (tTd(0, 44)) printf("\n\t%08x=", *av); else (void) putchar(' '); xputs(*av++); } (void) putchar('\n'); } \f /* ** LOWER -- turn letter into lower case. ** ** Parameters: ** c -- character to turn into lower case. ** ** Returns: ** c, in lower case. ** ** Side Effects: ** none. */ char lower(c) register char c; { return(isascii(c) && isupper(c) ? tolower(c) : c); } \f /* ** XPUTS -- put string doing control escapes. ** ** Parameters: ** s -- string to put. ** ** Returns: ** none. ** ** Side Effects: ** output to stdout */ xputs(s) register char *s; { register char c; if (s == NULL) { printf("<null>"); return; } (void) putchar('"'); while ((c = *s++) != '\0') { if (!isascii(c)) { (void) putchar('\\'); c &= 0177; } if (c < 040 || c >= 0177) { (void) putchar('^'); c ^= 0100; } (void) putchar(c); } (void) putchar('"'); (void) fflush(stdout); } \f /* ** MAKELOWER -- Translate a line into lower case ** ** Parameters: ** p -- the string to translate. If NULL, return is ** immediate. ** ** Returns: ** none. ** ** Side Effects: ** String pointed to by p is translated to lower case. ** ** Called By: ** parse */ makelower(p) register char *p; { register char c; if (p == NULL) return; for (; (c = *p) != '\0'; p++) if (isascii(c) && isupper(c)) *p = tolower(c); } \f /* ** BUILDFNAME -- build full name from gecos style entry. ** ** This routine interprets the strange entry that would appear ** in the GECOS field of the password file. ** ** Parameters: ** p -- name to build. ** login -- the login name of this user (for &). ** buf -- place to put the result. ** ** Returns: ** none. ** ** Side Effects: ** none. */ buildfname(p, login, buf) register char *p; char *login; char *buf; { register char *bp = buf; if (*p == '*') p++; while (*p != '\0' && *p != ',' && *p != ';' && *p != '%') { if (*p == '&') { (void) strcpy(bp, login); *bp = toupper(*bp); while (*bp != '\0') bp++; p++; } else *bp++ = *p++; } *bp = '\0'; } \f /* ** SAFEFILE -- return true if a file exists and is safe for a user. ** ** Parameters: ** fn -- filename to check. ** uid -- uid to compare against. ** mode -- mode bits that must match. ** ** Returns: ** TRUE if fn exists, is owned by uid, and matches mode. ** FALSE otherwise. ** ** Side Effects: ** none. */ bool safefile(fn, uid, mode) char *fn; int uid; int mode; { struct stat stbuf; if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid && (stbuf.st_mode & mode) == mode) return (TRUE); errno = 0; return (FALSE); } \f /* ** FIXCRLF -- fix <CR><LF> in line. ** ** Looks for the <CR><LF> combination and turns it into the ** UNIX canonical <NL> character. It only takes one line, ** i.e., it is assumed that the first <NL> found is the end ** of the line. ** ** Parameters: ** line -- the line to fix. ** stripnl -- if true, strip the newline also. ** ** Returns: ** none. ** ** Side Effects: ** line is changed in place. */ fixcrlf(line, stripnl) char *line; bool stripnl; { register char *p; p = index(line, '\n'); if (p == NULL) return; if (p > line && p[-1] == '\r') p--; if (!stripnl) *p++ = '\n'; *p = '\0'; } \f /* ** DFOPEN -- determined file open ** ** This routine has the semantics of fopen, except that it will ** keep trying a few times to make this happen. The idea is that ** on very loaded systems, we may run out of resources (inodes, ** whatever), so this tries to get around it. */ FILE * dfopen(filename, mode) char *filename; char *mode; { register int tries; register FILE *fp; for (tries = 0; tries < 10; tries++) { sleep((unsigned) (10 * tries)); errno = 0; fp = fopen(filename, mode); if (fp != NULL) break; if (errno != ENFILE && errno != EINTR) break; } errno = 0; return (fp); } \f /* ** PUTLINE -- put a line like fputs obeying SMTP conventions ** ** This routine always guarantees outputing a newline (or CRLF, ** as appropriate) at the end of the string. ** ** Parameters: ** l -- line to put. ** fp -- file to put it onto. ** m -- the mailer used to control output. ** ** Returns: ** none ** ** Side Effects: ** output of l to fp. */ # define SMTPLINELIM 990 /* maximum line length */ putline(l, fp, m) register char *l; FILE *fp; MAILER *m; { register char *p; char svchar; /* strip out 0200 bits -- these can look like TELNET protocol */ if (bitnset(M_LIMITS, m->m_flags)) { p = l; while ((*p++ &= ~0200) != 0) continue; } do { /* find the end of the line */ p = index(l, '\n'); if (p == NULL) p = &l[strlen(l)]; /* check for line overflow */ while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags)) { register char *q = &l[SMTPLINELIM - 1]; svchar = *q; *q = '\0'; if (l[0] == '.' && bitnset(M_XDOT, m->m_flags)) (void) putc('.', fp); fputs(l, fp); (void) putc('!', fp); fputs(m->m_eol, fp); *q = svchar; l = q; } /* output last part */ svchar = *p; *p = '\0'; if (l[0] == '.' && bitnset(M_XDOT, m->m_flags)) (void) putc('.', fp); fputs(l, fp); fputs(m->m_eol, fp); *p = svchar; l = p; if (*l == '\n') l++; } while (l[0] != '\0'); } \f /* ** XUNLINK -- unlink a file, doing logging as appropriate. ** ** Parameters: ** f -- name of file to unlink. ** ** Returns: ** none. ** ** Side Effects: ** f is unlinked. */ xunlink(f) char *f; { register int i; # ifdef LOG if (LogLevel > 20) syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f); # endif LOG i = unlink(f); # ifdef LOG if (i < 0 && LogLevel > 21) syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno); # endif LOG } \f /* ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. ** ** Parameters: ** buf -- place to put the input line. ** siz -- size of buf. ** fp -- file to read from. ** ** Returns: ** NULL on error (including timeout). This will also leave ** buf containing a null string. ** buf otherwise. ** ** Side Effects: ** none. */ static jmp_buf CtxReadTimeout; char * sfgets(buf, siz, fp) char *buf; int siz; FILE *fp; { register EVENT *ev = NULL; register char *p; extern readtimeout(); /* set the timeout */ if (ReadTimeout != 0) { if (setjmp(CtxReadTimeout) != 0) { # ifdef LOG syslog(LOG_NOTICE, "timeout waiting for input from %s\n", RealHostName? RealHostName: "local"); # endif errno = 0; usrerr("451 timeout waiting for input"); buf[0] = '\0'; return (NULL); } ev = setevent((time_t) ReadTimeout, readtimeout, 0); } /* try to read */ p = NULL; while (p == NULL && !feof(fp) && !ferror(fp)) { errno = 0; p = fgets(buf, siz, fp); if (errno == EINTR) clearerr(fp); } /* clear the event if it has not sprung */ clrevent(ev); /* clean up the books and exit */ LineNumber++; if (p == NULL) { buf[0] = '\0'; return (NULL); } for (p = buf; *p != '\0'; p++) *p &= ~0200; return (buf); } static readtimeout() { longjmp(CtxReadTimeout, 1); } \f /* ** FGETFOLDED -- like fgets, but know about folded lines. ** ** Parameters: ** buf -- place to put result. ** n -- bytes available. ** f -- file to read from. ** ** Returns: ** buf on success, NULL on error or EOF. ** ** Side Effects: ** buf gets lines from f, with continuation lines (lines ** with leading white space) appended. CRLF's are mapped ** into single newlines. Any trailing NL is stripped. */ char * fgetfolded(buf, n, f) char *buf; register int n; FILE *f; { register char *p = buf; register int i; n--; while ((i = getc(f)) != EOF) { if (i == '\r') { i = getc(f); if (i != '\n') { if (i != EOF) (void) ungetc(i, f); i = '\r'; } } if (--n > 0) *p++ = i; if (i == '\n') { LineNumber++; i = getc(f); if (i != EOF) (void) ungetc(i, f); if (i != ' ' && i != '\t') { *--p = '\0'; return (buf); } } } return (NULL); } \f /* ** CURTIME -- return current time. ** ** Parameters: ** none. ** ** Returns: ** the current time. ** ** Side Effects: ** none. */ time_t curtime() { auto time_t t; (void) time(&t); return (t); } \f /* ** ATOBOOL -- convert a string representation to boolean. ** ** Defaults to "TRUE" ** ** Parameters: ** s -- string to convert. Takes "tTyY" as true, ** others as false. ** ** Returns: ** A boolean representation of the string. ** ** Side Effects: ** none. */ bool atobool(s) register char *s; { if (*s == '\0' || index("tTyY", *s) != NULL) return (TRUE); return (FALSE); } \f /* ** ATOOCT -- convert a string representation to octal. ** ** Parameters: ** s -- string to convert. ** ** Returns: ** An integer representing the string interpreted as an ** octal number. ** ** Side Effects: ** none. */ atooct(s) register char *s; { register int i = 0; while (*s >= '0' && *s <= '7') i = (i << 3) | (*s++ - '0'); return (i); } \f /* ** WAITFOR -- wait for a particular process id. ** ** Parameters: ** pid -- process id to wait for. ** ** Returns: ** status of pid. ** -1 if pid never shows up. ** ** Side Effects: ** none. */ waitfor(pid) int pid; { auto int st; int i; do { errno = 0; i = wait(&st); } while ((i >= 0 || errno == EINTR) && i != pid); if (i < 0) st = -1; return (st); } \f /* ** BITINTERSECT -- tell if two bitmaps intersect ** ** Parameters: ** a, b -- the bitmaps in question ** ** Returns: ** TRUE if they have a non-null intersection ** FALSE otherwise ** ** Side Effects: ** none. */ bool bitintersect(a, b) BITMAP a; BITMAP b; { int i; for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) if ((a[i] & b[i]) != 0) return (TRUE); return (FALSE); } \f /* ** BITZEROP -- tell if a bitmap is all zero ** ** Parameters: ** map -- the bit map to check ** ** Returns: ** TRUE if map is all zero. ** FALSE if there are any bits set in map. ** ** Side Effects: ** none. */ bool bitzerop(map) BITMAP map; { int i; for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) if (map[i] != 0) return (FALSE); return (TRUE); } @ 5.18.0.1 log @IDA patches @ text @a31 2 bool catPrint = FALSE; /* xputs: print strings for catenation */ a271 1 register struct metamac *m; a272 5 if (s == MACNULL) { printf("<macnull>"); return; } d278 1 a278 16 if (s[0] == MATCHREPL && isdigit(s[1]) && s[2] == '\0') { printf("$%c", s[1]); return; } else for (m = MetaMacros; m->metaname != '\0'; m++) if (m->metaval == *s) { printf("$%c%s", m->metaname, &s[1]); return; } if (!catPrint) (void) putchar('"'); d293 1 a293 2 if (!catPrint) (void) putchar('"'); a316 1 register bool quoted_string = FALSE; d321 1 a321 3 if (c == '"') quoted_string = !quoted_string; else if (!quoted_string && isascii(c) && isupper(c)) d553 1 a553 1 # endif /* LOG */ d559 1 a559 1 # endif /* LOG */ a589 7 /* check for reasonable siz arg */ if (siz < 1) { buf[0] = '\0'; return (NULL); } d599 1 a599 1 # endif /* LOG */ a841 44 /* ** PRINTCAV -- Print concatenated argument vector ** ** Parameters: ** av -- argument vector. ** ** Returns: ** none. ** ** Side Effects: ** prints av. */ printcav(av) register char **av; { bool oldCatPrint = catPrint; catPrint = TRUE; printav(av); catPrint = oldCatPrint; } #ifdef OUTPUT_PID write_pid_to_file () { extern char *PidFile; FILE *f; (void) unlink (PidFile); /* try to be safe :-) */ f = dfopen (PidFile, "w"); if (errno == 0) { fprintf (f, "%d\n", getpid()); (void) chmod (PidFile, 0444); (void) fclose (f); } #ifdef LOG else syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s\n", getpid(), PidFile); #endif } #endif /* OUTPUT_PID */ @ 5.18.0.2 log @Bruce Lilly (bruce%balilly@@sonyd1.broadcast.sony.com) contributed putline() changes: efficiency (don't re-compute XDOT inside loops), and readability (let fprintf do the hard work). Also strip extraneous newlines from syslog() statements. @ text @a513 1 int limitsflag, xdotflag; a514 1 limitsflag = bitnset(M_LIMITS, m->m_flags); d516 6 a521 4 if (limitsflag) for (p=l; (*p & ~0200)!=0; p++) if (*p & 0200) *p &= ~0200; a522 1 xdotflag = bitnset(M_XDOT, m->m_flags); d531 1 a531 1 while (((p - l) > SMTPLINELIM) && limitsflag) d535 3 a537 1 if ((*l == '.') && xdotflag) d539 4 a542 1 fprintf(fp, "%.*s!%s", SMTPLINELIM-1, l, m->m_eol); d547 3 a549 1 if ((*l == '.') && xdotflag) d551 3 a553 1 fprintf(fp, "%.*s%s", p-l, l, m->m_eol); d557 1 a557 1 } while (*l != '\0'); d579 1 a579 1 syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f); d615 1 a615 1 static readtimeout(); d631 1 a631 1 "timeout waiting for input from %s", d915 1 a915 1 syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s", @ 5.18.0.3 log @Fixed forward declaration of readtimeout(). @ text @a597 1 void readtimeout(); d607 1 d659 1 a659 1 static void @ 5.18.0.4 log @Deleted #ifdef/#define OUTPUT_PID in favor of testing whether _PATH_SENDMAILPID is set. sendmail.h now #include's pathnames.h instead of the other modules. @ text @d25 6 a30 6 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sysexits.h> #include <errno.h> #include "sendmail.h" d505 1 a505 1 #define SMTPLINELIM 990 /* maximum line length */ d569 1 a569 1 #ifdef LOG d572 1 a572 1 #endif /* LOG */ d575 1 a575 1 #ifdef LOG d578 1 a578 1 #endif /* LOG */ d621 1 a621 1 #ifdef LOG d625 1 a625 1 #endif /* LOG */ d892 2 a893 15 /* ** WRITEPID -- Write process id to file ** ** Parameters: ** none ** ** Returns: ** none. ** ** Side Effects: ** writes pid file, creating if necessary */ #ifdef _PATH_SENDMAILPID WritePid() d897 2 a898 3 (void) unlink(PidFile); /* try to be safe :-) */ f = dfopen(PidFile, "w"); d901 3 a903 3 fprintf(f, "%d\n", getpid()); (void) chmod(PidFile, 0444); (void) fclose(f); d905 1 a905 1 # ifdef LOG d907 1 a907 1 syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s: %m", d909 1 a909 1 # endif /* LOG */ d911 1 a911 1 #endif /* _PATH_SENDMAILPID */ @ 5.18.0.5 log @Deleted #include <sys/types.h> as it's already included via sendmail.h from useful.h. #include "sendmail.h" relocated to top of #include list. @ text @a24 1 #include "sendmail.h" d26 1 d30 1 @ 5.18.0.6 log @ANSIfied. @ text @a30 2 static void readtimeout(); a53 1 void d78 1 a78 1 ** Returns: d86 1 a86 1 register const char *s; d114 1 a114 1 register const char *s; a223 1 void a268 1 void d270 1 a270 1 register const char *s; a335 1 void a367 1 void d369 2 a370 2 register const char *p; const char *login; a440 1 void d467 2 a468 2 const char *filename; const char *mode; d475 1 a475 1 Xsleep((unsigned) (10 * tries)); a505 1 void d544 1 a544 10 /* * Some broken compilers evaluate %.0s%s as %s%s. This * doubles blank lines. I have to remember that portability * is one of my goals (*sigh*). -pbp */ if ((p-l) == 0) fprintf(fp, "%s", m->m_eol); else fprintf(fp, "%.*s%s", p-l, l, m->m_eol); a562 1 void d564 1 a564 1 const char *f; d597 1 d758 1 a758 1 register const char *s; d779 1 a779 1 register const char *s; a810 2 if (i > 0 && tTd(4, 2)) printf("waitfor: wait (pid = %d)\n", i); a880 1 void d882 1 a882 1 register char **av; d884 1 a884 1 bool oldCatPrint = catPrint; d886 3 a888 3 catPrint = TRUE; printav(av); catPrint = oldCatPrint; a904 1 void @ 5.18.0.7 log @Deleted extern declaration of malloc() (moved to def.h), deleted inappropriate const qualifier. @ text @d160 1 d583 1 a583 1 char *f; @ 5.18.0.8 log @WritePid() was checking errno and not return value from dfopen(). @ text @d932 2 a933 1 if ((f = dfopen(PidFile, "w")) != NULL) @