dk-milter-1.0.0.dfsg/0000755000175000017500000000000010767324234014074 5ustar madhackmadhackdk-milter-1.0.0.dfsg/KNOWNBUGS0000644000175000017500000000200710764720752015375 0ustar madhackmadhack K N O W N B U G S I N D K - M I L T E R The following are bugs or deficiencies in the dk-milter package that we are aware of but which have not been fixed in the current release. You probably want to get the most up to date version of this from http://sourceforge.net/projects/dk-milter. For descriptions of bugs that have been fixed, see the file RELEASE_NOTES. This list is not guaranteed to be complete. SIGNING REPEATED HEADERS SourceForge bug #1538398 There is a known problem with signing messages that have a header field which repeats (e.g. a message with multiple "Received:" header fields). As the industry is transitioning to use of DKIM instead of DomainKeys, and the amount of work required to resolve the problem in the canonicalization code is substantial, no permanent fix for this is expected in the short-term. The workaround is to arrange via use of the "-o" command line switch that such headers will be ignored when signing. $Revision: 1.3 $, Last updated $Date: 2008/03/09 08:38:02 $ dk-milter-1.0.0.dfsg/libsm/0000755000175000017500000000000010766324734015206 5ustar madhackmadhackdk-milter-1.0.0.dfsg/libsm/vsnprintf.c0000644000175000017500000000357307347306541017410 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: vsnprintf.c,v 1.23 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include "local.h" /* ** SM_VSNPRINTF -- format data for "output" into a string ** ** Assigned 'str' to a "fake" file pointer. This allows common ** o/p formatting function sm_vprintf() to be used. ** ** Parameters: ** str -- location for output ** n -- maximum size for o/p ** fmt -- format directives ** ap -- data unit vectors for use by 'fmt' ** ** Results: ** result from sm_io_vfprintf() ** ** Side Effects: ** Limits the size ('n') to INT_MAX. */ int sm_vsnprintf(str, n, fmt, ap) char *str; size_t n; const char *fmt; SM_VA_LOCAL_DECL { int ret; char dummy; SM_FILE_T fake; /* While snprintf(3) specifies size_t stdio uses an int internally */ if (n > INT_MAX) n = INT_MAX; /* Stdio internals do not deal correctly with zero length buffer */ if (n == 0) { str = &dummy; n = 1; } fake.sm_magic = SmFileMagic; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; fake.f_file = -1; fake.f_flags = SMWR | SMSTR; fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; fake.f_bf.smb_size = fake.f_w = n - 1; fake.f_close = NULL; fake.f_open = NULL; fake.f_read = NULL; fake.f_write = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_vsnprintf:fake"; ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); *fake.f_p = 0; return ret; } dk-milter-1.0.0.dfsg/libsm/t-event.c0000644000175000017500000000401610253661450016723 0ustar madhackmadhack/* * Copyright (c) 2001-2002, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: t-event.c,v 1.13 2005/06/14 23:07:20 ca Exp $") #include #include #include #ifndef WIN32 # include #endif /* !WIN32 */ #if SM_CONF_SETITIMER # include #endif /* SM_CONF_SETITIMER */ #include #include static void evcheck __P((int)); static void ev1 __P((int)); static int check; static void evcheck(arg) int arg; { SM_TEST(arg == 3); SM_TEST(check == 0); check++; } static void ev1(arg) int arg; { SM_TEST(arg == 1); } /* define as x if you want debug output */ #define DBG_OUT(x) int main(argc, argv) int argc; char *argv[]; { SM_EVENT *ev; sm_test_begin(argc, argv, "test event handling"); fprintf(stdout, "This test may hang. If there is no output within twelve seconds, abort it\nand recompile with -DSM_CONF_SETITIMER=%d\n", SM_CONF_SETITIMER == 0 ? 1 : 0); sleep(1); SM_TEST(1 == 1); DBG_OUT(fprintf(stdout, "We're back, test 1 seems to work.\n")); ev = sm_seteventm(1000, ev1, 1); sleep(1); SM_TEST(2 == 2); DBG_OUT(fprintf(stdout, "We're back, test 2 seems to work.\n")); /* schedule an event in 9s */ ev = sm_seteventm(9000, ev1, 2); sleep(1); /* clear the event before it can fire */ sm_clrevent(ev); SM_TEST(3 == 3); DBG_OUT(fprintf(stdout, "We're back, test 3 seems to work.\n")); #ifdef WIN32 #pragma message(__FILE__ "NB: It occurs that the event handling code was never completely implemented for win32 platform") #else /* WIN32 */ /* schedule an event in 1s */ check = 0; ev = sm_seteventm(1000, evcheck, 3); sleep(2); /* clear the event */ sm_clrevent(ev); SM_TEST(4 == 4); SM_TEST(check == 1); DBG_OUT(fprintf(stdout, "We're back, test 4 seems to work.\n")); #endif /* WIN32 */ return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/fvwrite.c0000644000175000017500000001443007347306540017036 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fvwrite.c,v 1.49 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include #include #include #include #include #include #include "local.h" #include "fvwrite.h" /* ** SM_FVWRITE -- write memory regions and buffer for file pointer ** ** Parameters: ** fp -- the file pointer to write to ** timeout -- time length for function to return by ** uio -- the memory regions to write ** ** Returns: ** Failure: returns SM_IO_EOF and sets errno ** Success: returns 0 (zero) ** ** This routine is large and unsightly, but most of the ugliness due ** to the different kinds of output buffering handled here. */ #define COPY(n) (void)memcpy((void *)fp->f_p, (void *)p, (size_t)(n)) #define GETIOV(extra_work) \ while (len == 0) \ { \ extra_work; \ p = iov->iov_base; \ len = iov->iov_len; \ iov++; \ } int sm_fvwrite(fp, timeout, uio) register SM_FILE_T *fp; int timeout; register struct sm_uio *uio; { register size_t len; register char *p; register struct sm_iov *iov; register int w, s; char *nl; int nlknown, nldist; #ifndef WIN32 int fd; struct timeval to; #endif /* !WIN32 */ if (uio->uio_resid == 0) return 0; /* make sure we can write */ if (cantwrite(fp)) { errno = EBADF; return SM_IO_EOF; } SM_CONVERT_TIME(fp, fd, timeout, &to); iov = uio->uio_iov; p = iov->iov_base; len = iov->iov_len; iov++; if (fp->f_flags & SMNBF) { /* Unbuffered: write up to BUFSIZ bytes at a time. */ do { GETIOV(;); errno = 0; /* needed to ensure EOF correctly found */ w = (*fp->f_write)(fp, p, SM_MIN(len, SM_IO_BUFSIZ)); if (w <= 0) { if (w == 0 && errno == 0) break; /* EOF found */ if (IS_IO_ERROR(fd, w, timeout)) goto err; /* errno set */ /* write would block */ SM_IO_WR_TIMEOUT(fp, fd, timeout); w = 0; } else { p += w; len -= w; } } while ((uio->uio_resid -= w) != 0); } else if ((fp->f_flags & SMLBF) == 0) { /* ** Not SMLBF (line-buffered). Either SMFBF or SMNOW ** buffered: fill partially full buffer, if any, ** and then flush. If there is no partial buffer, write ** one bf._size byte chunk directly (without copying). ** ** String output is a special case: write as many bytes ** as fit, but pretend we wrote everything. This makes ** snprintf() return the number of bytes needed, rather ** than the number used, and avoids its write function ** (so that the write function can be invalid). */ do { GETIOV(;); if ((((fp->f_flags & (SMALC | SMSTR)) == (SMALC | SMSTR)) || ((fp->f_flags & SMNOW) != 0)) && (size_t) fp->f_w < len) { size_t blen = fp->f_p - fp->f_bf.smb_base; unsigned char *tbase; int tsize; /* Allocate space exponentially. */ tsize = fp->f_bf.smb_size; do { tsize = (tsize << 1) + 1; } while ((size_t) tsize < blen + len); tbase = (unsigned char *) sm_realloc(fp->f_bf.smb_base, tsize + 1); if (tbase == NULL) { errno = ENOMEM; goto err; /* errno set */ } fp->f_w += tsize - fp->f_bf.smb_size; fp->f_bf.smb_base = tbase; fp->f_bf.smb_size = tsize; fp->f_p = tbase + blen; } w = fp->f_w; errno = 0; /* needed to ensure EOF correctly found */ if (fp->f_flags & SMSTR) { if (len < (size_t) w) w = len; COPY(w); /* copy SM_MIN(fp->f_w,len), */ fp->f_w -= w; fp->f_p += w; w = len; /* but pretend copied all */ } else if (fp->f_p > fp->f_bf.smb_base && len > (size_t) w) { /* fill and flush */ COPY(w); fp->f_p += w; if (sm_flush(fp, &timeout)) goto err; /* errno set */ } else if (len >= (size_t) (w = fp->f_bf.smb_size)) { /* write directly */ w = (*fp->f_write)(fp, p, w); if (w <= 0) { if (w == 0 && errno == 0) break; /* EOF found */ if (IS_IO_ERROR(fd, w, timeout)) goto err; /* errno set */ /* write would block */ SM_IO_WR_TIMEOUT(fp, fd, timeout); w = 0; } } else { /* fill and done */ w = len; COPY(w); fp->f_w -= w; fp->f_p += w; } p += w; len -= w; } while ((uio->uio_resid -= w) != 0); if ((fp->f_flags & SMNOW) != 0 && sm_flush(fp, &timeout)) goto err; /* errno set */ } else { /* ** Line buffered: like fully buffered, but we ** must check for newlines. Compute the distance ** to the first newline (including the newline), ** or `infinity' if there is none, then pretend ** that the amount to write is SM_MIN(len,nldist). */ nlknown = 0; nldist = 0; /* XXX just to keep gcc happy */ do { GETIOV(nlknown = 0); if (!nlknown) { nl = memchr((void *)p, '\n', len); nldist = nl != NULL ? nl + 1 - p : len + 1; nlknown = 1; } s = SM_MIN(len, ((size_t) nldist)); w = fp->f_w + fp->f_bf.smb_size; errno = 0; /* needed to ensure EOF correctly found */ if (fp->f_p > fp->f_bf.smb_base && s > w) { COPY(w); /* fp->f_w -= w; */ fp->f_p += w; if (sm_flush(fp, &timeout)) goto err; /* errno set */ } else if (s >= (w = fp->f_bf.smb_size)) { w = (*fp->f_write)(fp, p, w); if (w <= 0) { if (w == 0 && errno == 0) break; /* EOF found */ if (IS_IO_ERROR(fd, w, timeout)) goto err; /* errno set */ /* write would block */ SM_IO_WR_TIMEOUT(fp, fd, timeout); w = 0; } } else { w = s; COPY(w); fp->f_w -= w; fp->f_p += w; } if ((nldist -= w) == 0) { /* copied the newline: flush and forget */ if (sm_flush(fp, &timeout)) goto err; /* errno set */ nlknown = 0; } p += w; len -= w; } while ((uio->uio_resid -= w) != 0); } return 0; err: /* errno set before goto places us here */ fp->f_flags |= SMERR; return SM_IO_EOF; } dk-milter-1.0.0.dfsg/libsm/sscanf.c0000644000175000017500000000440407426376460016633 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: sscanf.c,v 1.25 2002/02/01 02:28:00 ca Exp $") #include #include #include #include "local.h" /* ** SM_EOFREAD -- dummy read function for faked file below ** ** Parameters: ** fp -- file pointer ** buf -- location to place read data ** len -- number of bytes to read ** ** Returns: ** 0 (zero) always */ static ssize_t sm_eofread __P(( SM_FILE_T *fp, char *buf, size_t len)); /* ARGSUSED0 */ static ssize_t sm_eofread(fp, buf, len) SM_FILE_T *fp; char *buf; size_t len; { return 0; } /* ** SM_IO_SSCANF -- scan a string to find data units ** ** Parameters: ** str -- strings containing data ** fmt -- format directive for finding data units ** ... -- memory locations to place format found data units ** ** Returns: ** Failure: SM_IO_EOF ** Success: number of data units found ** ** Side Effects: ** Attempts to strlen() 'str'; if not a '\0' terminated string ** then the call may SEGV/fail. ** Faking the string 'str' as a file. */ int #if SM_VA_STD sm_io_sscanf(const char *str, char const *fmt, ...) #else /* SM_VA_STD */ sm_io_sscanf(str, fmt, va_alist) const char *str; char *fmt; va_dcl #endif /* SM_VA_STD */ { int ret; SM_FILE_T fake; SM_VA_LOCAL_DECL fake.sm_magic = SmFileMagic; fake.f_flags = SMRD; fake.f_bf.smb_base = fake.f_p = (unsigned char *) str; fake.f_bf.smb_size = fake.f_r = strlen(str); fake.f_file = -1; fake.f_read = sm_eofread; fake.f_write = NULL; fake.f_close = NULL; fake.f_open = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_io_sscanf:fake"; fake.f_flushfp = NULL; fake.f_ub.smb_base = NULL; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; SM_VA_START(ap, fmt); ret = sm_vfscanf(&fake, SM_TIME_FOREVER, fmt, ap); SM_VA_END(ap); return ret; } dk-milter-1.0.0.dfsg/libsm/Makefile.m40000644000175000017500000000406710470704327017164 0ustar madhackmadhackdnl $Id: Makefile.m4,v 1.72 2006/08/16 21:06:31 ca Exp $ define(`confREQUIRE_LIBUNIX') include(confBUILDTOOLSDIR`/M4/switch.m4') define(`confREQUIRE_LIBSM', `true') define(`confREQUIRE_SM_OS_H', `true') PREPENDDEF(`confENVDEF', `confMAPDEF') #if WIN32 ifdef(`confNT', `APPENDDEF(`confINCDIRS', `-I${REL_SRC_DIR}/../nt-extensions/include -I${REL_SRC_DIR}/../pkgs/openldap/src/include -I${REL_SRC_DIR}/../pkgs/openldap/src/include/SMI-WIN32 -I${REL_SRC_DIR}/../nt-extensions')') #endif /* WIN32 */ bldPRODUCT_START(`library', `libsm') define(`bldSOURCES', ` assert.c debug.c errstring.c exc.c heap.c match.c rpool.c strdup.c strerror.c strl.c clrerr.c fclose.c feof.c ferror.c fflush.c fget.c fpos.c findfp.c flags.c fopen.c fprintf.c fpurge.c fput.c fread.c fscanf.c fseek.c fvwrite.c fwalk.c fwrite.c get.c makebuf.c put.c refill.c rewind.c setvbuf.c smstdio.c snprintf.c sscanf.c stdio.c strio.c ungetc.c vasprintf.c vfprintf.c vfscanf.c vprintf.c vsnprintf.c wbuf.c wsetup.c string.c stringf.c xtrap.c strto.c test.c path.c strcasecmp.c strrevcmp.c signal.c clock.c config.c shm.c sem.c mbdb.c strexit.c cf.c ldap.c niprop.c mpeix.c memstat.c util.c ') bldPRODUCT_END dnl msg.c dnl syslogio.c define(`confCHECK_LIBS',`libsm.a')dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/check.m4') smcheck(`t-event', `compile-run') smcheck(`t-exc', `compile-run') smcheck(`t-rpool', `compile-run') smcheck(`t-string', `compile-run') smcheck(`t-smstdio', `compile-run') smcheck(`t-match', `compile-run') smcheck(`t-strio', `compile-run') smcheck(`t-heap', `compile-run') smcheck(`t-fopen', `compile-run') smcheck(`t-strl', `compile-run') smcheck(`t-strrevcmp', `compile-run') smcheck(`t-types', `compile-run') smcheck(`t-path', `compile-run') smcheck(`t-float', `compile-run') smcheck(`t-scanf', `compile-run') smcheck(`t-shm', `compile-run') smcheck(`t-sem', `compile-run') dnl smcheck(`t-msg', `compile-run') smcheck(`t-cf') smcheck(`b-strcmp') dnl SM_CONF_STRL cannot be turned off dnl smcheck(`b-strl') smcheck(`t-memstat') smcheck(`t-qic', `compile-run') divert(bldTARGETS_SECTION) divert(0) bldFINISH dk-milter-1.0.0.dfsg/libsm/wbuf.c0000644000175000017500000000501607347306541016314 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: wbuf.c,v 1.21 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include "local.h" /* Note: This function is called from a macro located in */ /* ** SM_WBUF -- write character to and flush (likely now full) buffer ** ** Write the given character into the (probably full) buffer for ** the given file. Flush the buffer out if it is or becomes full, ** or if c=='\n' and the file is line buffered. ** ** Parameters: ** fp -- the file pointer ** timeout -- time to complete operation (milliseconds) ** c -- int representation of the character to add ** ** Results: ** Failure: -1 and sets errno ** Success: int value of 'c' */ int sm_wbuf(fp, timeout, c) register SM_FILE_T *fp; int timeout; register int c; { register int n; /* ** In case we cannot write, or longjmp takes us out early, ** make sure w is 0 (if fully- or un-buffered) or -bf.smb_size ** (if line buffered) so that we will get called again. ** If we did not do this, a sufficient number of sm_io_putc() ** calls might wrap w from negative to positive. */ fp->f_w = fp->f_lbfsize; if (cantwrite(fp)) { errno = EBADF; return SM_IO_EOF; } c = (unsigned char)c; /* ** If it is completely full, flush it out. Then, in any case, ** stuff c into the buffer. If this causes the buffer to fill ** completely, or if c is '\n' and the file is line buffered, ** flush it (perhaps a second time). The second flush will always ** happen on unbuffered streams, where bf.smb_size==1; sm_io_flush() ** guarantees that sm_io_putc() will always call sm_wbuf() by setting ** w to 0, so we need not do anything else. ** Note for the timeout, only one of the sm_io_flush's will get called. */ n = fp->f_p - fp->f_bf.smb_base; if (n >= fp->f_bf.smb_size) { if (sm_io_flush(fp, timeout)) return SM_IO_EOF; /* sm_io_flush() sets errno */ n = 0; } fp->f_w--; *fp->f_p++ = c; if (++n == fp->f_bf.smb_size || (fp->f_flags & SMLBF && c == '\n')) if (sm_io_flush(fp, timeout)) return SM_IO_EOF; /* sm_io_flush() sets errno */ return c; } dk-milter-1.0.0.dfsg/libsm/match.c0000644000175000017500000000543407347306540016450 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: match.c,v 1.10 2001/09/11 04:04:48 gshapiro Exp $") #include /* ** SM_MATCH -- Match a character string against a glob pattern. ** ** Parameters: ** str -- string. ** par -- pattern to find in str. ** ** Returns: ** true on match, false on non-match. ** ** A pattern consists of normal characters, which match themselves, ** and meta-sequences. A * matches any sequence of characters. ** A ? matches any single character. A [ introduces a character class. ** A ] marks the end of a character class; if the ] is missing then ** the [ matches itself rather than introducing a character class. ** A character class matches any of the characters between the brackets. ** The range of characters from X to Y inclusive is written X-Y. ** If the first character after the [ is ! then the character class is ** complemented. ** ** To include a ] in a character class, make it the first character ** listed (after the !, if any). To include a -, make it the first ** character listed (after the !, if any) or the last character. ** It is impossible for a ] to be the final character in a range. ** For glob patterns that literally match "*", "?" or "[", ** use [*], [?] or [[]. */ bool sm_match(str, pat) const char *str; const char *pat; { bool ccnot, ccmatch, ccfirst; const char *ccstart; char c, c2; for (;;) { switch (*pat) { case '\0': return *str == '\0'; case '?': if (*str == '\0') return false; ++pat; ++str; continue; case '*': ++pat; if (*pat == '\0') { /* optimize case of trailing '*' */ return true; } for (;;) { if (sm_match(pat, str)) return true; if (*str == '\0') return false; ++str; } /* NOTREACHED */ case '[': ccstart = pat++; ccnot = false; if (*pat == '!') { ccnot = true; ++pat; } ccmatch = false; ccfirst = true; for (;;) { if (*pat == '\0') { pat = ccstart; goto defl; } if (*pat == ']' && !ccfirst) break; c = *pat++; ccfirst = false; if (*pat == '-' && pat[1] != ']') { ++pat; if (*pat == '\0') { pat = ccstart; goto defl; } c2 = *pat++; if (*str >= c && *str <= c2) ccmatch = true; } else { if (*str == c) ccmatch = true; } } if (ccmatch ^ ccnot) { ++pat; ++str; } else return false; continue; default: defl: if (*pat != *str) return false; ++pat; ++str; continue; } } } dk-milter-1.0.0.dfsg/libsm/fput.c0000644000175000017500000000240307347306540016323 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fput.c,v 1.20 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include #include "local.h" #include "fvwrite.h" /* ** SM_IO_FPUTS -- add a string to the buffer for the file pointer ** ** Parameters: ** fp -- the file pointer for the buffer to be written to ** timeout -- time to complete the put-string ** s -- string to be placed in the buffer ** ** Returns: ** Failure: returns SM_IO_EOF ** Success: returns 0 (zero) */ int sm_io_fputs(fp, timeout, s) SM_FILE_T *fp; int timeout; const char *s; { struct sm_uio uio; struct sm_iov iov; SM_REQUIRE_ISA(fp, SmFileMagic); iov.iov_base = (void *) s; iov.iov_len = uio.uio_resid = strlen(s); uio.uio_iov = &iov; uio.uio_iovcnt = 1; return sm_fvwrite(fp, timeout, &uio); } dk-milter-1.0.0.dfsg/libsm/vfscanf.c0000644000175000017500000004543310513535710016775 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: vfscanf.c,v 1.54 2006/10/12 22:03:52 ca Exp $") #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #define BUF 513 /* Maximum length of numeric string. */ /* Flags used during conversion. */ #define LONG 0x01 /* l: long or double */ #define SHORT 0x04 /* h: short */ #define QUAD 0x08 /* q: quad (same as ll) */ #define SUPPRESS 0x10 /* suppress assignment */ #define POINTER 0x20 /* weird %p pointer (`fake hex') */ #define NOSKIP 0x40 /* do not skip blanks */ /* ** The following are used in numeric conversions only: ** SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; ** SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. */ #define SIGNOK 0x080 /* +/- is (still) legal */ #define NDIGITS 0x100 /* no digits detected */ #define DPTOK 0x200 /* (float) decimal point is still legal */ #define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */ #define PFXOK 0x200 /* 0x prefix is (still) legal */ #define NZDIGITS 0x400 /* no zero digits detected */ /* Conversion types. */ #define CT_CHAR 0 /* %c conversion */ #define CT_CCL 1 /* %[...] conversion */ #define CT_STRING 2 /* %s conversion */ #define CT_INT 3 /* integer, i.e., strtoll or strtoull */ #define CT_FLOAT 4 /* floating, i.e., strtod */ static void scanalrm __P((int)); static unsigned char *sm_sccl __P((char *, unsigned char *)); static jmp_buf ScanTimeOut; /* ** SCANALRM -- handler when timeout activated for sm_io_vfscanf() ** ** Returns flow of control to where setjmp(ScanTimeOut) was set. ** ** Parameters: ** sig -- unused ** ** Returns: ** does not return ** ** Side Effects: ** returns flow of control to setjmp(ScanTimeOut). ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED0 */ static void scanalrm(sig) int sig; { longjmp(ScanTimeOut, 1); } /* ** SM_VFSCANF -- convert input into data units ** ** Parameters: ** fp -- file pointer for input data ** timeout -- time intvl allowed to complete (milliseconds) ** fmt0 -- format for finding data units ** ap -- vectors for memory location for storing data units ** ** Results: ** Success: number of data units assigned ** Failure: SM_IO_EOF */ int sm_vfscanf(fp, timeout, fmt0, ap) register SM_FILE_T *fp; int SM_NONVOLATILE timeout; char const *fmt0; va_list SM_NONVOLATILE ap; { register unsigned char *SM_NONVOLATILE fmt = (unsigned char *) fmt0; register int c; /* character from format, or conversion */ register size_t width; /* field width, or 0 */ register char *p; /* points into all kinds of strings */ register int n; /* handy integer */ register int flags; /* flags as defined above */ register char *p0; /* saves original value of p when necessary */ int nassigned; /* number of fields assigned */ int nread; /* number of characters consumed from fp */ int base; /* base argument to strtoll/strtoull */ /* conversion function (strtoll/strtoull) */ ULONGLONG_T (*ccfn) __P((const char *, char **, int)); char ccltab[256]; /* character class table for %[...] */ char buf[BUF]; /* buffer for numeric conversions */ SM_EVENT *evt = NULL; /* `basefix' is used to avoid `if' tests in the integer scanner */ static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; if (timeout == SM_TIME_DEFAULT) timeout = fp->f_timeout; if (timeout == SM_TIME_IMMEDIATE) { /* ** Filling the buffer will take time and we are wanted to ** return immediately. So... */ errno = EAGAIN; return SM_IO_EOF; } if (timeout != SM_TIME_FOREVER) { if (setjmp(ScanTimeOut) != 0) { errno = EAGAIN; return SM_IO_EOF; } evt = sm_seteventm(timeout, scanalrm, 0); } nassigned = 0; nread = 0; base = 0; /* XXX just to keep gcc happy */ ccfn = NULL; /* XXX just to keep gcc happy */ for (;;) { c = *fmt++; if (c == 0) { if (evt != NULL) sm_clrevent(evt); /* undo our timeout */ return nassigned; } if (isspace(c)) { while ((fp->f_r > 0 || sm_refill(fp, SM_TIME_FOREVER) == 0) && isspace(*fp->f_p)) nread++, fp->f_r--, fp->f_p++; continue; } if (c != '%') goto literal; width = 0; flags = 0; /* ** switch on the format. continue if done; ** break once format type is derived. */ again: c = *fmt++; switch (c) { case '%': literal: if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) goto input_failure; if (*fp->f_p != c) goto match_failure; fp->f_r--, fp->f_p++; nread++; continue; case '*': flags |= SUPPRESS; goto again; case 'h': flags |= SHORT; goto again; case 'l': if (*fmt == 'l') { fmt++; flags |= QUAD; } else { flags |= LONG; } goto again; case 'q': flags |= QUAD; goto again; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': width = width * 10 + c - '0'; goto again; /* ** Conversions. ** Those marked `compat' are for 4.[123]BSD compatibility. ** ** (According to ANSI, E and X formats are supposed ** to the same as e and x. Sorry about that.) */ case 'D': /* compat */ flags |= LONG; /* FALLTHROUGH */ case 'd': c = CT_INT; ccfn = (ULONGLONG_T (*)())sm_strtoll; base = 10; break; case 'i': c = CT_INT; ccfn = (ULONGLONG_T (*)())sm_strtoll; base = 0; break; case 'O': /* compat */ flags |= LONG; /* FALLTHROUGH */ case 'o': c = CT_INT; ccfn = sm_strtoull; base = 8; break; case 'u': c = CT_INT; ccfn = sm_strtoull; base = 10; break; case 'X': case 'x': flags |= PFXOK; /* enable 0x prefixing */ c = CT_INT; ccfn = sm_strtoull; base = 16; break; case 'E': case 'G': case 'e': case 'f': case 'g': c = CT_FLOAT; break; case 's': c = CT_STRING; break; case '[': fmt = sm_sccl(ccltab, fmt); flags |= NOSKIP; c = CT_CCL; break; case 'c': flags |= NOSKIP; c = CT_CHAR; break; case 'p': /* pointer format is like hex */ flags |= POINTER | PFXOK; c = CT_INT; ccfn = sm_strtoull; base = 16; break; case 'n': if (flags & SUPPRESS) /* ??? */ continue; if (flags & SHORT) *SM_VA_ARG(ap, short *) = nread; else if (flags & LONG) *SM_VA_ARG(ap, long *) = nread; else *SM_VA_ARG(ap, int *) = nread; continue; /* Disgusting backwards compatibility hacks. XXX */ case '\0': /* compat */ if (evt != NULL) sm_clrevent(evt); /* undo our timeout */ return SM_IO_EOF; default: /* compat */ if (isupper(c)) flags |= LONG; c = CT_INT; ccfn = (ULONGLONG_T (*)()) sm_strtoll; base = 10; break; } /* We have a conversion that requires input. */ if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) goto input_failure; /* ** Consume leading white space, except for formats ** that suppress this. */ if ((flags & NOSKIP) == 0) { while (isspace(*fp->f_p)) { nread++; if (--fp->f_r > 0) fp->f_p++; else if (sm_refill(fp, SM_TIME_FOREVER)) goto input_failure; } /* ** Note that there is at least one character in ** the buffer, so conversions that do not set NOSKIP ** can no longer result in an input failure. */ } /* Do the conversion. */ switch (c) { case CT_CHAR: /* scan arbitrary characters (sets NOSKIP) */ if (width == 0) width = 1; if (flags & SUPPRESS) { size_t sum = 0; for (;;) { if ((size_t) (n = fp->f_r) < width) { sum += n; width -= n; fp->f_p += n; if (sm_refill(fp, SM_TIME_FOREVER)) { if (sum == 0) goto input_failure; break; } } else { sum += width; fp->f_r -= width; fp->f_p += width; break; } } nread += sum; } else { size_t r; r = sm_io_read(fp, SM_TIME_FOREVER, (void *) SM_VA_ARG(ap, char *), width); if (r == 0) goto input_failure; nread += r; nassigned++; } break; case CT_CCL: /* scan a (nonempty) character class (sets NOSKIP) */ if (width == 0) width = (size_t)~0; /* `infinity' */ /* take only those things in the class */ if (flags & SUPPRESS) { n = 0; while (ccltab[*fp->f_p] != '\0') { n++, fp->f_r--, fp->f_p++; if (--width == 0) break; if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) { if (n == 0) /* XXX how? */ goto input_failure; break; } } if (n == 0) goto match_failure; } else { p0 = p = SM_VA_ARG(ap, char *); while (ccltab[*fp->f_p] != '\0') { fp->f_r--; *p++ = *fp->f_p++; if (--width == 0) break; if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) { if (p == p0) goto input_failure; break; } } n = p - p0; if (n == 0) goto match_failure; *p = 0; nassigned++; } nread += n; break; case CT_STRING: /* like CCL, but zero-length string OK, & no NOSKIP */ if (width == 0) width = (size_t)~0; if (flags & SUPPRESS) { n = 0; while (!isspace(*fp->f_p)) { n++, fp->f_r--, fp->f_p++; if (--width == 0) break; if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) break; } nread += n; } else { p0 = p = SM_VA_ARG(ap, char *); while (!isspace(*fp->f_p)) { fp->f_r--; *p++ = *fp->f_p++; if (--width == 0) break; if (fp->f_r <= 0 && sm_refill(fp, SM_TIME_FOREVER)) break; } *p = 0; nread += p - p0; nassigned++; } continue; case CT_INT: /* scan an integer as if by strtoll/strtoull */ #if SM_CONF_BROKEN_SIZE_T if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; #else /* SM_CONF_BROKEN_SIZE_T */ /* size_t is unsigned, hence this optimisation */ if (--width > sizeof(buf) - 2) width = sizeof(buf) - 2; width++; #endif /* SM_CONF_BROKEN_SIZE_T */ flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width > 0; width--) { c = *fp->f_p; /* ** Switch on the character; `goto ok' ** if we accept it as a part of number. */ switch (c) { /* ** The digit 0 is always legal, but is ** special. For %i conversions, if no ** digits (zero or nonzero) have been ** scanned (only signs), we will have ** base==0. In that case, we should set ** it to 8 and enable 0x prefixing. ** Also, if we have not scanned zero digits ** before this, do not turn off prefixing ** (someone else will turn it off if we ** have scanned any nonzero digits). */ case '0': if (base == 0) { base = 8; flags |= PFXOK; } if (flags & NZDIGITS) flags &= ~(SIGNOK|NZDIGITS|NDIGITS); else flags &= ~(SIGNOK|PFXOK|NDIGITS); goto ok; /* 1 through 7 always legal */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': base = basefix[base]; flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* digits 8 and 9 ok iff decimal or hex */ case '8': case '9': base = basefix[base]; if (base <= 8) break; /* not legal here */ flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* letters ok iff hex */ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': /* no need to fix base here */ if (base <= 10) break; /* not legal here */ flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* sign ok only as first character */ case '+': case '-': if (flags & SIGNOK) { flags &= ~SIGNOK; goto ok; } break; /* x ok iff flag still set & 2nd char */ case 'x': case 'X': if (flags & PFXOK && p == buf + 1) { base = 16; /* if %i */ flags &= ~PFXOK; goto ok; } break; } /* ** If we got here, c is not a legal character ** for a number. Stop accumulating digits. */ break; ok: /* c is legal: store it and look at the next. */ *p++ = c; if (--fp->f_r > 0) fp->f_p++; else if (sm_refill(fp, SM_TIME_FOREVER)) break; /* SM_IO_EOF */ } /* ** If we had only a sign, it is no good; push ** back the sign. If the number ends in `x', ** it was [sign] '0' 'x', so push back the x ** and treat it as [sign] '0'. */ if (flags & NDIGITS) { if (p > buf) (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, *(unsigned char *)--p); goto match_failure; } c = ((unsigned char *)p)[-1]; if (c == 'x' || c == 'X') { --p; (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); } if ((flags & SUPPRESS) == 0) { ULONGLONG_T res; *p = 0; res = (*ccfn)(buf, (char **)NULL, base); if (flags & POINTER) *SM_VA_ARG(ap, void **) = (void *)(long) res; else if (flags & QUAD) *SM_VA_ARG(ap, LONGLONG_T *) = res; else if (flags & LONG) *SM_VA_ARG(ap, long *) = res; else if (flags & SHORT) *SM_VA_ARG(ap, short *) = res; else *SM_VA_ARG(ap, int *) = res; nassigned++; } nread += p - buf; break; case CT_FLOAT: /* scan a floating point number as if by strtod */ if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; for (p = buf; width; width--) { c = *fp->f_p; /* ** This code mimicks the integer conversion ** code, but is much simpler. */ switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': flags &= ~(SIGNOK | NDIGITS); goto fok; case '+': case '-': if (flags & SIGNOK) { flags &= ~SIGNOK; goto fok; } break; case '.': if (flags & DPTOK) { flags &= ~(SIGNOK | DPTOK); goto fok; } break; case 'e': case 'E': /* no exponent without some digits */ if ((flags&(NDIGITS|EXPOK)) == EXPOK) { flags = (flags & ~(EXPOK|DPTOK)) | SIGNOK | NDIGITS; goto fok; } break; } break; fok: *p++ = c; if (--fp->f_r > 0) fp->f_p++; else if (sm_refill(fp, SM_TIME_FOREVER)) break; /* SM_IO_EOF */ } /* ** If no digits, might be missing exponent digits ** (just give back the exponent) or might be missing ** regular digits, but had sign and/or decimal point. */ if (flags & NDIGITS) { if (flags & EXPOK) { /* no digits at all */ while (p > buf) (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, *(unsigned char *)--p); goto match_failure; } /* just a bad exponent (e and maybe sign) */ c = *(unsigned char *) --p; if (c != 'e' && c != 'E') { (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); /* sign */ c = *(unsigned char *)--p; } (void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c); } if ((flags & SUPPRESS) == 0) { double res; *p = 0; res = strtod(buf, (char **) NULL); if (flags & LONG) *SM_VA_ARG(ap, double *) = res; else *SM_VA_ARG(ap, float *) = res; nassigned++; } nread += p - buf; break; } } input_failure: if (evt != NULL) sm_clrevent(evt); /* undo our timeout */ return nassigned ? nassigned : -1; match_failure: if (evt != NULL) sm_clrevent(evt); /* undo our timeout */ return nassigned; } /* ** SM_SCCL -- sequenced character comparison list ** ** Fill in the given table from the scanset at the given format ** (just after `['). Return a pointer to the character past the ** closing `]'. The table has a 1 wherever characters should be ** considered part of the scanset. ** ** Parameters: ** tab -- array flagging "active" char's to match (returned) ** fmt -- character list (within "[]") ** ** Results: */ static unsigned char * sm_sccl(tab, fmt) register char *tab; register unsigned char *fmt; { register int c, n, v; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ if (c == '^') { v = 1; /* default => accept */ c = *fmt++; /* get new first char */ } else v = 0; /* default => reject */ /* should probably use memset here */ for (n = 0; n < 256; n++) tab[n] = v; if (c == 0) return fmt - 1; /* format ended before closing ] */ /* ** Now set the entries corresponding to the actual scanset ** to the opposite of the above. ** ** The first character may be ']' (or '-') without being special; ** the last character may be '-'. */ v = 1 - v; for (;;) { tab[c] = v; /* take character c */ doswitch: n = *fmt++; /* and examine the next */ switch (n) { case 0: /* format ended too soon */ return fmt - 1; case '-': /* ** A scanset of the form ** [01+-] ** is defined as `the digit 0, the digit 1, ** the character +, the character -', but ** the effect of a scanset such as ** [a-zA-Z0-9] ** is implementation defined. The V7 Unix ** scanf treats `a-z' as `the letters a through ** z', but treats `a-a' as `the letter a, the ** character -, and the letter a'. ** ** For compatibility, the `-' is not considerd ** to define a range if the character following ** it is either a close bracket (required by ANSI) ** or is not numerically greater than the character ** we just stored in the table (c). */ n = *fmt; if (n == ']' || n < c) { c = '-'; break; /* resume the for(;;) */ } fmt++; do { /* fill in the range */ tab[++c] = v; } while (c < n); #if 1 /* XXX another disgusting compatibility hack */ /* ** Alas, the V7 Unix scanf also treats formats ** such as [a-c-e] as `the letters a through e'. ** This too is permitted by the standard.... */ goto doswitch; #else c = *fmt++; if (c == 0) return fmt - 1; if (c == ']') return fmt; break; #endif case ']': /* end of scanset */ return fmt; default: /* just another character */ c = n; break; } } /* NOTREACHED */ } dk-milter-1.0.0.dfsg/libsm/t-heap.c0000644000175000017500000000253307347306541016530 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-heap.c,v 1.10 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include #if SM_HEAP_CHECK extern SM_DEBUG_T SmHeapCheck; # define HEAP_CHECK sm_debug_active(&SmHeapCheck, 1) #else /* SM_HEAP_CHECK */ # define HEAP_CHECK 0 #endif /* SM_HEAP_CHECK */ int main(argc, argv) int argc; char **argv; { void *p; sm_test_begin(argc, argv, "test heap handling"); if (argc > 1) sm_debug_addsettings_x(argv[1]); p = sm_malloc(10); SM_TEST(p != NULL); p = sm_realloc_x(p, 20); SM_TEST(p != NULL); p = sm_realloc(p, 30); SM_TEST(p != NULL); if (HEAP_CHECK) { sm_dprintf("heap with 1 30-byte block allocated:\n"); sm_heap_report(smioout, 3); } if (HEAP_CHECK) { sm_free(p); sm_dprintf("heap with 0 blocks allocated:\n"); sm_heap_report(smioout, 3); sm_dprintf("xtrap count = %d\n", SmXtrapCount); } #if DEBUG /* this will cause a core dump */ sm_dprintf("about to free %p for the second time\n", p); sm_free(p); #endif /* DEBUG */ return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/t-strrevcmp.c0000644000175000017500000000174607347306541017645 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-strrevcmp.c,v 1.3 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include int main(argc, argv) int argc; char **argv; { char *s1; char *s2; sm_test_begin(argc, argv, "test string compare"); s1 = "equal"; s2 = "equal"; SM_TEST(sm_strrevcmp(s1, s2) == 0); s1 = "equal"; s2 = "qual"; SM_TEST(sm_strrevcmp(s1, s2) > 0); s1 = "qual"; s2 = "equal"; SM_TEST(sm_strrevcmp(s1, s2) < 0); s1 = "Equal"; s2 = "equal"; SM_TEST(sm_strrevcmp(s1, s2) < 0); s1 = "Equal"; s2 = "equal"; SM_TEST(sm_strrevcasecmp(s1, s2) == 0); s1 = "Equal"; s2 = "eQuaL"; SM_TEST(sm_strrevcasecmp(s1, s2) == 0); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/wsetup.c0000644000175000017500000000361007430540505016667 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: wsetup.c,v 1.20 2002/02/07 18:02:45 ca Exp $") #include #include #include #include "local.h" /* ** SM_WSETUP -- check writing is safe ** ** Various output routines call wsetup to be sure it is safe to write, ** because either flags does not include SMMWR, or buf is NULL. ** Used in the macro "cantwrite" found in "local.h". ** ** Parameters: ** fp -- the file pointer ** ** Results: ** Failure: SM_IO_EOF and sets errno ** Success: 0 (zero) */ int sm_wsetup(fp) register SM_FILE_T *fp; { /* make sure stdio is set up */ if (!Sm_IO_DidInit) sm_init(); /* If we are not writing, we had better be reading and writing. */ if ((fp->f_flags & SMWR) == 0) { if ((fp->f_flags & SMRW) == 0) { errno = EBADF; return SM_IO_EOF; } if (fp->f_flags & SMRD) { /* clobber any ungetc data */ if (HASUB(fp)) FREEUB(fp); /* discard read buffer */ fp->f_flags &= ~(SMRD|SMFEOF); fp->f_r = 0; fp->f_p = fp->f_bf.smb_base; } fp->f_flags |= SMWR; } /* Make a buffer if necessary, then set w. */ if (fp->f_bf.smb_base == NULL) sm_makebuf(fp); if (fp->f_flags & SMLBF) { /* ** It is line buffered, so make lbfsize be -bufsize ** for the sm_putc() macro. We will change lbfsize back ** to 0 whenever we turn off SMWR. */ fp->f_w = 0; fp->f_lbfsize = -fp->f_bf.smb_size; } else fp->f_w = fp->f_flags & SMNBF ? 0 : fp->f_bf.smb_size; return 0; } dk-milter-1.0.0.dfsg/libsm/README0000644000175000017500000001065607771012444016070 0ustar madhackmadhack# Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # $Id: README,v 1.24 2003/12/20 09:23:48 gshapiro Exp $ # Libsm is a library of generally useful C abstractions. For documentation, see index.html. Libsm stands alone; it depends on no other sendmail libraries, and the only sendmail header files it depends on are its own, which reside in ../include/sm. The t-*.c files are regression tests. These tests are incomplete: we do not yet test all of the APIs, and we have not yet converted all tests to use the test harness. If a test fails read the explanation it generates. Sometimes it is sufficient to change a compile time flag, which are also listed below. If that does not help, check the sendmail/README files for problems on your OS. The b-*.c files are benchmarks that compare system routines with those provided by libsm. By default sendmail uses the routines provided by the OS. In several cases, the routines provided by libsm are faster than those of the OS. If your OS provides the routines, you can compare the performance of them with the libsm versions by running the programs with the option -d (by default the programs just issue an explanation when/how to use them). The programs are: b-strcmp.c tests strcasecmp(). +----------------------+ | CONFIGURATION MACROS | +----------------------+ Libsm uses a set of C preprocessor macros to specify platform specific features of the C compiler and standard C libraries. If you are porting sendmail to a new platform, you may need to tweak the values of some of these macros. The following macros are given default values in . If the default value is wrong for a given platform, then a platform specific value is specified in one of two ways: - A -D option is added to the confENVDEF macro; this change can be made to the platform M4 file in devtools/OS, or to the site.config.m4 file in devtools/Site. - The confSM_OS_HEADER macro in the platform M4 file defines sm_os_foo, which forces "sm/os/sm_os_foo.h" to be included by "sm/config.h" via a link that is made from "sm_os.h" to "sm/os/sm_os_foo.h". Platform specific configuration macro settings are added to . SM_CONF_STDBOOL_H Set to 1 if the header file exists, and defines true, false and bool. SM_CONF_SYS_CDEFS_H Set to 1 if the header file exists, and defines __P. You may need to do this to eliminate warnings about __P being multiply defined. SM_CONF_STDDEF_H Set to 0 if the header file does not exist. SM_CONF_SETITIMER Set to 0 if the setitimer function is not available. SM_CONF_SYSEXITS_H Set to 1 if exists, and sets the EX_* macros to values different from the default BSD values in . SM_CONF_UID_GID Set to 0 if does not define uid_t and gid_t. SM_CONF_SSIZE_T Set to 0 if does not define ssize_t. SM_CONF_BROKEN_SIZE_T Set to 1 if size_t is not unsigned. SM_CONF_LONGLONG Set to 1 if your C compiler supports the 'long long' type. This will be set automatically if you use gcc or a C compiler that conforms to the 1999 ISO C standard. SM_CONF_QUAD_T Set to 1 if your C compiler does not support 'long long', but defines quad_t as an integral type. SM_CONF_SHM Set to 1 if System V shared memory APIs are available. SM_CONF_MSG Set to 1 if System V message queues are available. SM_CONF_SEM Set to 1 if semaphores are available. SM_CONF_BROKEN_STRTOD Set to 1 if your strtod() does not work properly. SM_CONF_GETOPT Set to 1 if your operating system does not include getopt(3). SM_CONF_LDAP_INITIALIZE Set to 1 if your LDAP client libraries include ldap_initialize(3). SM_CONF_LDAP_MEMFREE Set to 1 if your LDAP client libraries include ldap_memfree(3). SM_IO_MAX_BUF_FILE Set this to a useful buffer size for regular files if stat(2) does not return a value for st_blksize that is the "optimal blocksize for I/O". SM_IO_MAX_BUF Set this to a useful maximum buffer size for other than regular files if stat(2) does not return a value for st_blksize that is the "optimal blocksize for I/O". SM_IO_MIN_BUF Set this to a useful minimum buffer size for other than regular files if stat(2) does not return a value for st_blksize that is the "optimal blocksize for I/O". dk-milter-1.0.0.dfsg/libsm/t-memstat.c0000644000175000017500000000407710576065765017302 0ustar madhackmadhack/* * Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-memstat.c,v 1.9 2007/03/14 21:41:09 ca Exp $") #include /* ** Simple test program for memstat */ #include #include #include #include #include extern char *optarg; extern int optind; void usage(prg) char *prg; { fprintf(stderr, "usage: %s [options]\n", prg); fprintf(stderr, "options:\n"); fprintf(stderr, "-l n loop n times\n"); fprintf(stderr, "-m n allocate n bytes per iteration\n"); fprintf(stderr, "-r name use name as resource to query\n"); fprintf(stderr, "-s n sleep n seconds per iteration\n"); } int main(argc, argv) int argc; char **argv; { int r, r2, i, l, slp, sz; long v; char *resource; l = 1; sz = slp = 0; resource = NULL; while ((r = getopt(argc, argv, "l:m:r:s:")) != -1) { switch ((char) r) { case 'l': l = strtol(optarg, NULL, 0); break; case 'm': sz = strtol(optarg, NULL, 0); break; case 'r': resource = strdup(optarg); break; case 's': slp = strtol(optarg, NULL, 0); break; default: usage(argv[0]); exit(1); } } r = sm_memstat_open(); r2 = -1; for (i = 0; i < l; i++) { char *mem; r2 = sm_memstat_get(resource, &v); if (slp > 0 && i + 1 < l && 0 == r) { printf("open=%d, memstat=%d, %s=%ld\n", r, r2, resource != NULL ? resource : "default-value", v); sleep(slp); if (sz > 0) { /* ** Just allocate some memory to test the ** values that are returned. ** Note: this is a memory leak, but that ** doesn't matter here. */ mem = malloc(sz); if (NULL == mem) printf("malloc(%d) failed\n", sz); } } } printf("open=%d, memstat=%d, %s=%ld\n", r, r2, resource != NULL ? resource : "default-value", v); r = sm_memstat_close(); return r; } dk-milter-1.0.0.dfsg/libsm/b-strl.c0000644000175000017500000001177710253661450016560 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ /* ** Compile this program using a command line similar to: ** cc -O -L../OBJ/libsm -o b-strl b-strl.c -lsm ** where "OBJ" is the name of the object directory for the platform ** you are compiling on. ** Then run the program: ** ./b-strl ** and read the output for results and how to interpret the results. */ #include SM_RCSID("@(#)$Id: b-strl.c,v 1.25 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #define SRC_SIZE 512 #define toseconds(x, y) (x.tv_sec - y.tv_sec) #define LOOPS 4000000L /* initial number of loops */ #define MAXTIME 30L /* "maximum" time to run single test */ void fatal(str) char *str; { perror(str); exit(1); } void purpose() { printf("This program benchmarks the performance differences between\n"); printf("strlcpy() and sm_strlcpy(), and strlcat() and sm_strlcat().\n"); printf("These tests may take several minutes to complete.\n"); } int main(argc, argv) int argc; char *argv[]; { #if !SM_CONF_STRL printf("The configuration indicates the system needs the libsm\n"); printf("versions of strlcpy(3) and strlcat(3). Thus, performing\n"); printf("these tests will not be of much use.\n"); printf("If your OS has strlcpy(3) and strlcat(3) then set the macro\n"); printf("SM_CONF_STRL to 1 in your site.config.m4 file\n"); printf("(located in ../devtools/Site) and recompile this program.\n"); #else /* !SM_CONF_STRL */ int ch; long a; bool doit = false; long loops = LOOPS; long one, two; struct timeval t1, t2; char dest[SRC_SIZE], source[SRC_SIZE]; # define OPTIONS "d" while ((ch = getopt(argc, argv, OPTIONS)) != -1) { switch ((char) ch) { case 'd': doit = true; break; default: break; } } if (!doit) { purpose(); printf("If you want to run it, specify -d as option.\n"); return 0; } /* ** Let's place a small string at the head of dest for ** catenation to happen (it'll be ignored for the copy). */ (void) sm_strlcpy(dest, "a small string at the start! ", SRC_SIZE - 1); /* ** Let's place a larger string into source for the catenation and ** the copy. */ (void) strlcpy(source, " This is the longer string that will be used for catenation and copying for the the performace testing. The longer the string being catenated or copied the greater the difference in measureable performance\n", SRC_SIZE - 1); /* Run-time comments to the user */ purpose(); printf("\n"); printf("Test 1: strlcat() versus sm_strlcat()\n"); redo_cat: if (gettimeofday(&t1, NULL) < 0) fatal("gettimeofday"); for (a = 0; a < loops; a++) strlcat(dest, source, SRC_SIZE - 1); if (gettimeofday(&t2, NULL) < 0) fatal("gettimeofday"); printf("\tstrlcat() result: %ld seconds\n", one = toseconds(t2, t1)); if (gettimeofday(&t1, NULL) < 0) fatal("gettimeofday"); for (a = 0; a < loops; a++) sm_strlcat(dest, source, SRC_SIZE - 1); if (gettimeofday(&t2, NULL) < 0) fatal("gettimeofday"); printf("\tsm_strlcat() result: %ld seconds\n", two = toseconds(t2, t1)); if (one - two >= -2 && one - two <= 2) { loops += loops; if (loops < 0L || one > MAXTIME) { printf("\t\t** results too close: no decision\n"); } else { printf("\t\t** results too close redoing test %ld times **\n", loops); goto redo_cat; } } printf("\n"); printf("Test 2: strlcpy() versus sm_strlpy()\n"); loops = LOOPS; redo_cpy: if (gettimeofday(&t1, NULL) < 0) fatal("gettimeofday"); for (a = 0; a < loops; a++) strlcpy(dest, source, SRC_SIZE - 1); if (gettimeofday(&t2, NULL) < 0) fatal("gettimeofday"); printf("\tstrlcpy() result: %ld seconds\n", one = toseconds(t2, t1)); if (gettimeofday(&t1, NULL) < 0) fatal("gettimeofday"); for (a = 0; a < loops; a++) sm_strlcpy(dest, source, SRC_SIZE - 1); if (gettimeofday(&t2, NULL) < 0) fatal("gettimeofday"); printf("\tsm_strlcpy() result: %ld seconds\n", two = toseconds(t2, t1)); if (one - two >= -2 && one - two <= 2) { loops += loops; if (loops < 0L || one > MAXTIME) { printf("\t\t** results too close: no decision\n"); } else { printf("\t\t** results too close redoing test %ld times **\n", loops); goto redo_cpy; } } printf("\n\n"); printf("Interpreting the results:\n"); printf("\tFor differences larger than 2 seconds, the lower value is\n"); printf("\tbetter and that function should be used for performance\n"); printf("\treasons.\n\n"); printf("This program will re-run the tests when the difference is\n"); printf("less than 2 seconds.\n"); printf("The result will vary depending on the compiler optimization\n"); printf("level used. Compiling the sendmail libsm library with a\n"); printf("better optimization level can change the results.\n"); #endif /* !SM_CONF_STRL */ return 0; } dk-milter-1.0.0.dfsg/libsm/mpeix.c0000644000175000017500000003354010621135452016464 0ustar madhackmadhack/* * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: mpeix.c,v 1.7 2007/05/11 18:51:22 gshapiro Exp $") #ifdef MPE /* ** MPE lacks many common functions required across all sendmail programs ** so we define implementations for these functions here. */ # include # include # include # include # include # include # include # include # include # include /* ** CHROOT -- dummy chroot() function ** ** The MPE documentation for sendmail says that chroot-based ** functionality is not implemented because MPE lacks chroot. But ** rather than mucking around with all the sendmail calls to chroot, ** we define this dummy function to return an ENOSYS failure just in ** case a sendmail user attempts to enable chroot-based functionality. ** ** Parameters: ** path -- pathname of new root (ignored). ** ** Returns: ** -1 and errno == ENOSYS (function not implemented) */ int chroot(path) char *path; { errno = ENOSYS; return -1; } /* ** ENDPWENT -- dummy endpwent() function ** ** Parameters: ** none ** ** Returns: ** none */ void endpwent() { return; } /* ** In addition to missing functions, certain existing MPE functions have ** slightly different semantics (or bugs) compared to normal Unix OSes. ** ** Here we define wrappers for these functions to make them behave in the ** manner expected by sendmail. */ /* ** SENDMAIL_MPE_BIND -- shadow function for the standard socket bind() ** ** MPE requires GETPRIVMODE() for AF_INET sockets less than port 1024. ** ** Parameters: ** sd -- socket descriptor. ** addr -- socket address. ** addrlen -- length of socket address. ** ** Results: ** 0 -- success ** != 0 -- failure */ #undef bind int sendmail_mpe_bind(sd, addr, addrlen) int sd; void *addr; int addrlen; { bool priv = false; int result; extern void GETPRIVMODE __P((void)); extern void GETUSERMODE __P((void)); if (addrlen == sizeof(struct sockaddr_in) && ((struct sockaddr_in *)addr)->sin_family == AF_INET) { /* AF_INET */ if (((struct sockaddr_in *)addr)->sin_port > 0 && ((struct sockaddr_in *)addr)->sin_port < 1024) { priv = true; GETPRIVMODE(); } ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; result = bind(sd, addr, addrlen); if (priv) GETUSERMODE(); return result; } /* AF_UNIX */ return bind(sd, addr, addrlen); } /* ** SENDMAIL_MPE__EXIT -- wait for children to terminate, then _exit() ** ** Child processes cannot survive the death of their parent on MPE, so ** we must call wait() before _exit() in order to prevent this ** infanticide. ** ** Parameters: ** status -- _exit status value. ** ** Returns: ** none. */ #undef _exit void sendmail_mpe__exit(status) int status; { int result; /* Wait for all children to terminate. */ do { result = wait(NULL); } while (result > 0 || errno == EINTR); _exit(status); } /* ** SENDMAIL_MPE_EXIT -- wait for children to terminate, then exit() ** ** Child processes cannot survive the death of their parent on MPE, so ** we must call wait() before exit() in order to prevent this ** infanticide. ** ** Parameters: ** status -- exit status value. ** ** Returns: ** none. */ #undef exit void sendmail_mpe_exit(status) int status; { int result; /* Wait for all children to terminate. */ do { result = wait(NULL); } while (result > 0 || errno == EINTR); exit(status); } /* ** SENDMAIL_MPE_FCNTL -- shadow function for fcntl() ** ** MPE requires sfcntl() for sockets, and fcntl() for everything ** else. This shadow routine determines the descriptor type and ** makes the appropriate call. ** ** Parameters: ** same as fcntl(). ** ** Returns: ** same as fcntl(). */ #undef fcntl int sendmail_mpe_fcntl(int fildes, int cmd, ...) { int len, result; struct sockaddr sa; void *arg; va_list ap; va_start(ap, cmd); arg = va_arg(ap, void *); va_end(ap); len = sizeof sa; if (getsockname(fildes, &sa, &len) == -1) { if (errno == EAFNOSUPPORT) { /* AF_UNIX socket */ return sfcntl(fildes, cmd, arg); } else if (errno == ENOTSOCK) { /* file or pipe */ return fcntl(fildes, cmd, arg); } /* unknown getsockname() failure */ return (-1); } else { /* AF_INET socket */ if ((result = sfcntl(fildes, cmd, arg)) != -1 && cmd == F_GETFL) result |= O_RDWR; /* fill in some missing flags */ return result; } } /* ** SENDMAIL_MPE_GETPWNAM - shadow function for getpwnam() ** ** Several issues apply here: ** ** - MPE user names MUST have one '.' separator character ** - MPE user names MUST be in upper case ** - MPE does not initialize all fields in the passwd struct ** ** Parameters: ** name -- username string. ** ** Returns: ** pointer to struct passwd if found else NULL */ static char *sendmail_mpe_nullstr = ""; #undef getpwnam extern struct passwd *getpwnam(const char *); struct passwd * sendmail_mpe_getpwnam(name) const char *name; { int dots = 0; int err; int i = strlen(name); char *upper; struct passwd *result = NULL; if (i <= 0) { errno = EINVAL; return result; } if ((upper = (char *)malloc(i + 1)) != NULL) { /* upshift the username parameter and count the dots */ while (i >= 0) { if (name[i] == '.') { dots++; upper[i] = '.'; } else upper[i] = toupper(name[i]); i--; } if (dots != 1) { /* prevent bug when dots == 0 */ err = EINVAL; } else if ((result = getpwnam(upper)) != NULL) { /* init the uninitialized fields */ result->pw_gecos = sendmail_mpe_nullstr; result->pw_passwd = sendmail_mpe_nullstr; result->pw_age = sendmail_mpe_nullstr; result->pw_comment = sendmail_mpe_nullstr; result->pw_audid = 0; result->pw_audflg = 0; } err = errno; free(upper); } errno = err; return result; } /* ** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid() ** ** Initializes the uninitalized fields in the passwd struct. ** ** Parameters: ** uid -- uid to obtain passwd data for ** ** Returns: ** pointer to struct passwd or NULL if not found */ #undef getpwuid extern struct passwd *getpwuid __P((uid_t)); struct passwd * sendmail_mpe_getpwuid(uid) uid_t uid; { struct passwd *result; if ((result = getpwuid(uid)) != NULL) { /* initialize the uninitialized fields */ result->pw_gecos = sendmail_mpe_nullstr; result->pw_passwd = sendmail_mpe_nullstr; result->pw_age = sendmail_mpe_nullstr; result->pw_comment = sendmail_mpe_nullstr; result->pw_audid = 0; result->pw_audflg = 0; } return result; } /* ** OK boys and girls, time for some serious voodoo! ** ** MPE does not have a complete implementation of POSIX users and groups: ** ** - there is no uid 0 superuser ** - setuid/setgid file permission bits exist but have no-op functionality ** - setgid() exists, but only supports new gid == current gid (boring!) ** - setuid() forces a gid change to the new uid's primary (and only) gid ** ** ...all of which thoroughly annoys sendmail. ** ** So what to do? We can't go on an #ifdef MPE rampage throughout ** sendmail, because there are only about a zillion references to uid 0 ** and so success (and security) would probably be rather dubious by the ** time we finished. ** ** Instead we take the approach of defining wrapper functions for the ** gid/uid management functions getegid(), geteuid(), setgid(), and ** setuid() in order to implement the following model: ** ** - the sendmail program thinks it is a setuid-root (uid 0) program ** - uid 0 is recognized as being valid, but does not grant extra powers ** - MPE priv mode allows sendmail to call setuid(), not uid 0 ** - file access is still controlled by the real non-zero uid ** - the other programs (vacation, etc) have standard MPE POSIX behavior ** ** This emulation model is activated by use of the program file setgid and ** setuid mode bits which exist but are unused by MPE. If the setgid mode ** bit is on, then gid emulation will be enabled. If the setuid mode bit is ** on, then uid emulation will be enabled. So for the mail daemon, we need ** to do chmod u+s,g+s /SENDMAIL/CURRENT/SENDMAIL. ** ** The following flags determine the current emulation state: ** ** true == emulation enabled ** false == emulation disabled, use unmodified MPE semantics */ static bool sendmail_mpe_flaginit = false; static bool sendmail_mpe_gidflag = false; static bool sendmail_mpe_uidflag = false; /* ** SENDMAIL_MPE_GETMODE -- return the mode bits for the current process ** ** Parameters: ** none. ** ** Returns: ** file mode bits for the current process program file. */ mode_t sendmail_mpe_getmode() { int status = 666; int myprogram_length; int myprogram_syntax = 2; char formaldesig[28]; char myprogram[PATH_MAX + 2]; char path[PATH_MAX + 1]; struct stat st; extern HPMYPROGRAM __P((int parms, char *formaldesig, int *status, int *length, char *myprogram, int *myprogram_length, int *myprogram_syntax)); myprogram_length = sizeof(myprogram); HPMYPROGRAM(6, formaldesig, &status, NULL, myprogram, &myprogram_length, &myprogram_syntax); /* should not occur, do not attempt emulation */ if (status != 0) return 0; memcpy(&path, &myprogram[1], myprogram_length - 2); path[myprogram_length - 2] = '\0'; /* should not occur, do not attempt emulation */ if (stat(path, &st) < 0) return 0; return st.st_mode; } /* ** SENDMAIL_MPE_EMULGID -- should we perform gid emulation? ** ** If !sendmail_mpe_flaginit then obtain the mode bits to determine ** if the setgid bit is on, we want gid emulation and so set ** sendmail_mpe_gidflag to true. Otherwise we do not want gid emulation ** and so set sendmail_mpe_gidflag to false. ** ** Parameters: ** none. ** ** Returns: ** true -- perform gid emulation ** false -- do not perform gid emulation */ bool sendmail_mpe_emulgid() { if (!sendmail_mpe_flaginit) { mode_t mode; mode = sendmail_mpe_getmode(); sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); sendmail_mpe_flaginit = true; } return sendmail_mpe_gidflag; } /* ** SENDMAIL_MPE_EMULUID -- should we perform uid emulation? ** ** If sendmail_mpe_uidflag == -1 then obtain the mode bits to determine ** if the setuid bit is on, we want uid emulation and so set ** sendmail_mpe_uidflag to true. Otherwise we do not want uid emulation ** and so set sendmail_mpe_uidflag to false. ** ** Parameters: ** none. ** ** Returns: ** true -- perform uid emulation ** false -- do not perform uid emulation */ bool sendmail_mpe_emuluid() { if (!sendmail_mpe_flaginit) { mode_t mode; mode = sendmail_mpe_getmode(); sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); sendmail_mpe_flaginit = true; } return sendmail_mpe_uidflag; } /* ** SENDMAIL_MPE_GETEGID -- shadow function for getegid() ** ** If emulation mode is in effect and the saved egid has been ** initialized, return the saved egid; otherwise return the value of the ** real getegid() function. ** ** Parameters: ** none. ** ** Returns: ** emulated egid if present, else true egid. */ static gid_t sendmail_mpe_egid = -1; #undef getegid gid_t sendmail_mpe_getegid() { if (sendmail_mpe_emulgid() && sendmail_mpe_egid != -1) return sendmail_mpe_egid; return getegid(); } /* ** SENDMAIL_MPE_GETEUID -- shadow function for geteuid() ** ** If emulation mode is in effect, return the saved euid; otherwise ** return the value of the real geteuid() function. ** ** Note that the initial value of the saved euid is zero, to simulate ** a setuid-root program. ** ** Parameters: ** none ** ** Returns: ** emulated euid if in emulation mode, else true euid. */ static uid_t sendmail_mpe_euid = 0; #undef geteuid uid_t sendmail_mpe_geteuid() { if (sendmail_mpe_emuluid()) return sendmail_mpe_euid; return geteuid(); } /* ** SENDMAIL_MPE_SETGID -- shadow function for setgid() ** ** Simulate a call to setgid() without actually calling the real ** function. Implement the expected uid 0 semantics. ** ** Note that sendmail will also be calling setuid() which will force an ** implicit real setgid() to the proper primary gid. So it doesn't matter ** that we don't actually alter the real gid in this shadow function. ** ** Parameters: ** gid -- desired gid. ** ** Returns: ** 0 -- emulated success ** -1 -- emulated failure */ #undef setgid int sendmail_mpe_setgid(gid) gid_t gid; { if (sendmail_mpe_emulgid()) { if (gid == getgid() || sendmail_mpe_euid == 0) { sendmail_mpe_egid = gid; return 0; } errno = EINVAL; return -1; } return setgid(gid); } /* ** SENDMAIL_MPE_SETUID -- shadow function for setuid() ** ** setuid() is broken as of MPE 7.0 in that it changes the current ** working directory to be the home directory of the new uid. Thus ** we must obtain the cwd and restore it after the setuid(). ** ** Note that expected uid 0 semantics have been added, as well as ** remembering the new uid for later use by the other shadow functions. ** ** Parameters: ** uid -- desired uid. ** ** Returns: ** 0 -- success ** -1 -- failure ** ** Globals: ** sendmail_mpe_euid */ #undef setuid int sendmail_mpe_setuid(uid) uid_t uid; { char *cwd; char cwd_buf[PATH_MAX + 1]; int result; extern void GETPRIVMODE __P((void)); extern void GETUSERMODE __P((void)); if (sendmail_mpe_emuluid()) { if (uid == 0) { if (sendmail_mpe_euid != 0) { errno = EINVAL; return -1; } sendmail_mpe_euid = 0; return 0; } /* Preserve the current working directory */ if ((cwd = getcwd(cwd_buf, PATH_MAX + 1)) == NULL) return -1; GETPRIVMODE(); result = setuid(uid); GETUSERMODE(); /* Restore the current working directory */ chdir(cwd_buf); if (result == 0) sendmail_mpe_euid = uid; return result; } return setuid(uid); } #endif /* MPE */ dk-milter-1.0.0.dfsg/libsm/rewind.c0000644000175000017500000000212107347306541016633 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: rewind.c,v 1.18 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include "local.h" /* ** SM_IO_REWIND -- rewind the file ** ** Seeks the file to the begining and clears any outstanding errors. ** ** Parameters: ** fp -- the flie pointer for rewind ** timeout -- time to complete the rewind ** ** Returns: ** none. */ void sm_io_rewind(fp, timeout) register SM_FILE_T *fp; int timeout; { SM_REQUIRE_ISA(fp, SmFileMagic); (void) sm_io_seek(fp, timeout, 0L, SM_IO_SEEK_SET); (void) sm_io_clearerr(fp); errno = 0; /* not required, but seems reasonable */ } dk-milter-1.0.0.dfsg/libsm/strerror.c0000644000175000017500000000247507347306541017241 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: strerror.c,v 1.23 2001/09/11 04:04:49 gshapiro Exp $") /* ** define strerror for platforms that lack it. */ #include #include /* sys_errlist, on some platforms */ #include /* sm_snprintf */ #include #include #include #if !defined(ERRLIST_PREDEFINED) extern char *sys_errlist[]; extern int sys_nerr; #endif /* !defined(ERRLIST_PREDEFINED) */ #if !HASSTRERROR /* ** STRERROR -- return error message string corresponding to an error number. ** ** Parameters: ** err -- error number. ** ** Returns: ** Error string (might be pointer to static buffer). */ char * strerror(err) int err; { static char buf[64]; if (err >= 0 && err < sys_nerr) return (char *) sys_errlist[err]; else { (void) sm_snprintf(buf, sizeof(buf), "Error %d", err); return buf; } } #endif /* !HASSTRERROR */ dk-milter-1.0.0.dfsg/libsm/strl.c0000644000175000017500000001703207422420105016321 0ustar madhackmadhack/* * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: strl.c,v 1.31 2002/01/20 01:41:25 gshapiro Exp $") #include #include /* ** Notice: this file is used by libmilter. Please try to avoid ** using libsm specific functions. */ /* ** XXX the type of the length parameter has been changed ** from size_t to ssize_t to avoid theoretical problems with negative ** numbers passed into these functions. ** The real solution to this problem is to make sure that this doesn't ** happen, but for now we'll use this workaround. */ /* ** SM_STRLCPY -- size bounded string copy ** ** This is a bounds-checking variant of strcpy. ** If size > 0, copy up to size-1 characters from the nul terminated ** string src to dst, nul terminating the result. If size == 0, ** the dst buffer is not modified. ** Additional note: this function has been "tuned" to run fast and tested ** as such (versus versions in some OS's libc). ** ** The result is strlen(src). You can detect truncation (not all ** of the characters in the source string were copied) using the ** following idiom: ** ** char *s, buf[BUFSIZ]; ** ... ** if (sm_strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) ** goto overflow; ** ** Parameters: ** dst -- destination buffer ** src -- source string ** size -- size of destination buffer ** ** Returns: ** strlen(src) */ size_t sm_strlcpy(dst, src, size) register char *dst; register const char *src; ssize_t size; { register ssize_t i; if (size-- <= 0) return strlen(src); for (i = 0; i < size && (dst[i] = src[i]) != 0; i++) continue; dst[i] = '\0'; if (src[i] == '\0') return i; else return i + strlen(src + i); } /* ** SM_STRLCAT -- size bounded string concatenation ** ** This is a bounds-checking variant of strcat. ** If strlen(dst) < size, then append at most size - strlen(dst) - 1 ** characters from the source string to the destination string, ** nul terminating the result. Otherwise, dst is not modified. ** ** The result is the initial length of dst + the length of src. ** You can detect overflow (not all of the characters in the ** source string were copied) using the following idiom: ** ** char *s, buf[BUFSIZ]; ** ... ** if (sm_strlcat(buf, s, sizeof(buf)) >= sizeof(buf)) ** goto overflow; ** ** Parameters: ** dst -- nul-terminated destination string buffer ** src -- nul-terminated source string ** size -- size of destination buffer ** ** Returns: ** total length of the string tried to create ** (= initial length of dst + length of src) */ size_t sm_strlcat(dst, src, size) register char *dst; register const char *src; ssize_t size; { register ssize_t i, j, o; o = strlen(dst); if (size < o + 1) return o + strlen(src); size -= o + 1; for (i = 0, j = o; i < size && (dst[j] = src[i]) != 0; i++, j++) continue; dst[j] = '\0'; if (src[i] == '\0') return j; else return j + strlen(src + i); } /* ** SM_STRLCAT2 -- append two strings to dst obeying length and ** '\0' terminate it ** ** strlcat2 will append at most len - strlen(dst) - 1 chars. ** terminates with '\0' if len > 0 ** dst = dst "+" src1 "+" src2 ** use this instead of sm_strlcat(dst,src1); sm_strlcat(dst,src2); ** for better speed. ** ** Parameters: ** dst -- "destination" string. ** src1 -- "from" string 1. ** src2 -- "from" string 2. ** len -- max. length of "destination" string. ** ** Returns: ** total length of the string tried to create ** (= initial length of dst + length of src) ** if this is greater than len then an overflow would have ** occurred. ** */ size_t sm_strlcat2(dst, src1, src2, len) register char *dst; register const char *src1; register const char *src2; ssize_t len; { register ssize_t i, j, o; /* current size of dst */ o = strlen(dst); /* max. size is less than current? */ if (len < o + 1) return o + strlen(src1) + strlen(src2); len -= o + 1; /* space left in dst */ /* copy the first string; i: index in src1; j: index in dst */ for (i = 0, j = o; i < len && (dst[j] = src1[i]) != 0; i++, j++) continue; /* src1: end reached? */ if (src1[i] != '\0') { /* no: terminate dst; there is space since i < len */ dst[j] = '\0'; return j + strlen(src1 + i) + strlen(src2); } len -= i; /* space left in dst */ /* copy the second string; i: index in src2; j: index in dst */ for (i = 0; i < len && (dst[j] = src2[i]) != 0; i++, j++) continue; dst[j] = '\0'; /* terminate dst; there is space since i < len */ if (src2[i] == '\0') return j; else return j + strlen(src2 + i); } /* ** SM_STRLCPYN -- concatenate n strings and assign the result to dst ** while obeying length and '\0' terminate it ** ** dst = src1 "+" src2 "+" ... ** use this instead of sm_snprintf() for string values ** and repeated sm_strlc*() calls for better speed. ** ** Parameters: ** dst -- "destination" string. ** len -- max. length of "destination" string. ** n -- number of strings ** strings... ** ** Returns: ** total length of the string tried to create ** (= initial length of dst + length of src) ** if this is greater than len then an overflow would have ** occurred. */ size_t #ifdef __STDC__ sm_strlcpyn(char *dst, ssize_t len, int n, ...) #else /* __STDC__ */ sm_strlcpyn(dst, len, n, va_alist) register char *dst; ssize_t len; int n; va_dcl #endif /* __STDC__ */ { register ssize_t i, j; char *str; SM_VA_LOCAL_DECL SM_VA_START(ap, n); if (len-- <= 0) /* This allows space for the terminating '\0' */ { i = 0; while (n-- > 0) i += strlen(SM_VA_ARG(ap, char *)); SM_VA_END(ap); return i; } j = 0; /* index in dst */ /* loop through all source strings */ while (n-- > 0) { str = SM_VA_ARG(ap, char *); /* copy string; i: index in str; j: index in dst */ for (i = 0; j < len && (dst[j] = str[i]) != 0; i++, j++) continue; /* str: end reached? */ if (str[i] != '\0') { /* no: terminate dst; there is space since j < len */ dst[j] = '\0'; j += strlen(str + i); while (n-- > 0) j += strlen(SM_VA_ARG(ap, char *)); SM_VA_END(ap); return j; } } SM_VA_END(ap); dst[j] = '\0'; /* terminate dst; there is space since j < len */ return j; } #if 0 /* ** SM_STRLAPP -- append string if it fits into buffer. ** ** If size > 0, copy up to size-1 characters from the nul terminated ** string src to dst, nul terminating the result. If size == 0, ** the dst buffer is not modified. ** ** This routine is useful for appending strings in a loop, e.g, instead of ** s = buf; ** for (ptr, ptr != NULL, ptr = next->ptr) ** { ** (void) sm_strlcpy(s, ptr->string, sizeof buf - (s - buf)); ** s += strlen(s); ** } ** replace the loop body with: ** if (!sm_strlapp(*s, ptr->string, sizeof buf - (s - buf))) ** break; ** it's faster... ** ** XXX interface isn't completely clear (yet), hence this code is ** not available. ** ** ** Parameters: ** dst -- (pointer to) destination buffer ** src -- source string ** size -- size of destination buffer ** ** Returns: ** true if strlen(src) < size ** ** Side Effects: ** modifies dst if append succeeds (enough space). */ bool sm_strlapp(dst, src, size) register char **dst; register const char *src; ssize_t size; { register size_t i; if (size-- <= 0) return false; for (i = 0; i < size && ((*dst)[i] = src[i]) != '\0'; i++) continue; (*dst)[i] = '\0'; if (src[i] == '\0') { *dst += i; return true; } /* undo */ (*dst)[0] = '\0'; return false; } #endif /* 0 */ dk-milter-1.0.0.dfsg/libsm/t-exc.c0000644000175000017500000000541707347306541016376 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-exc.c,v 1.20 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include const SM_EXC_TYPE_T EtypeTest1 = { SmExcTypeMagic, "E:test1", "i", sm_etype_printf, "test1 exception argv[0]=%0", }; const SM_EXC_TYPE_T EtypeTest2 = { SmExcTypeMagic, "E:test2", "i", sm_etype_printf, "test2 exception argv[0]=%0", }; int main(argc, argv) int argc; char **argv; { void *p; int volatile x; char *unknown, *cant; sm_test_begin(argc, argv, "test exception handling"); /* ** SM_TRY */ cant = "can't happen"; x = 0; SM_TRY x = 1; SM_END_TRY SM_TEST(x == 1); /* ** SM_FINALLY-0 */ x = 0; SM_TRY x = 1; SM_FINALLY x = 2; SM_END_TRY SM_TEST(x == 2); /* ** SM_FINALLY-1 */ x = 0; SM_TRY SM_TRY x = 1; sm_exc_raisenew_x(&EtypeTest1, 17); SM_FINALLY x = 2; sm_exc_raisenew_x(&EtypeTest2, 42); SM_END_TRY SM_EXCEPT(exc, "E:test2") (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "got exception test2: can't happen\n"); SM_EXCEPT(exc, "E:test1") SM_TEST(x == 2 && exc->exc_argv[0].v_int == 17); if (!(x == 2 && exc->exc_argv[0].v_int == 17)) { (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "can't happen: x=%d argv[0]=%d\n", x, exc->exc_argv[0].v_int); } SM_EXCEPT(exc, "*") { unknown = "unknown exception: "; SM_TEST(strcmp(unknown, cant) == 0); } SM_END_TRY x = 3; SM_TRY x = 4; sm_exc_raisenew_x(&EtypeTest1, 94); SM_FINALLY x = 5; sm_exc_raisenew_x(&EtypeTest2, 95); SM_EXCEPT(exc, "E:test2") { unknown = "got exception test2: "; SM_TEST(strcmp(unknown, cant) == 0); } SM_EXCEPT(exc, "E:test1") SM_TEST(x == 5 && exc->exc_argv[0].v_int == 94); if (!(x == 5 && exc->exc_argv[0].v_int == 94)) { (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "can't happen: x=%d argv[0]=%d\n", x, exc->exc_argv[0].v_int); } SM_EXCEPT(exc, "*") { unknown = "unknown exception: "; SM_TEST(strcmp(unknown, cant) == 0); } SM_END_TRY SM_TRY sm_exc_raisenew_x(&SmEtypeErr, "test %d", 0); SM_EXCEPT(exc, "*") #if DEBUG (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "test 0 got an exception, as expected:\n"); sm_exc_print(exc, smioout); #endif /* DEBUG */ return sm_test_end(); SM_END_TRY p = sm_malloc_x((size_t)(-1)); (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "sm_malloc_x unexpectedly succeeded, returning %p\n", p); unknown = "sm_malloc_x unexpectedly succeeded"; SM_TEST(strcmp(unknown, cant) == 0); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/rpool.c0000644000175000017500000002725210103774424016503 0ustar madhackmadhack/* * Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: rpool.c,v 1.28 2004/08/03 20:44:04 ca Exp $") /* ** resource pools ** For documentation, see rpool.html */ #include #include #include #include #include #if _FFR_PERF_RPOOL # include #endif /* _FFR_PERF_RPOOL */ const char SmRpoolMagic[] = "sm_rpool"; typedef union { SM_POOLLINK_T link; char align[SM_ALIGN_SIZE]; } SM_POOLHDR_T; static char *sm_rpool_allocblock_x __P((SM_RPOOL_T *, size_t)); static char *sm_rpool_allocblock __P((SM_RPOOL_T *, size_t)); /* ** Tune this later */ #define POOLSIZE 4096 #define BIG_OBJECT_RATIO 10 /* ** SM_RPOOL_ALLOCBLOCK_X -- allocate a new block for an rpool. ** ** Parameters: ** rpool -- rpool to which the block should be added. ** size -- size of block. ** ** Returns: ** Pointer to block. ** ** Exceptions: ** F:sm_heap -- out of memory */ static char * sm_rpool_allocblock_x(rpool, size) SM_RPOOL_T *rpool; size_t size; { SM_POOLLINK_T *p; p = sm_malloc_x(sizeof(SM_POOLHDR_T) + size); p->sm_pnext = rpool->sm_pools; rpool->sm_pools = p; return (char*) p + sizeof(SM_POOLHDR_T); } /* ** SM_RPOOL_ALLOCBLOCK -- allocate a new block for an rpool. ** ** Parameters: ** rpool -- rpool to which the block should be added. ** size -- size of block. ** ** Returns: ** Pointer to block, NULL on failure. */ static char * sm_rpool_allocblock(rpool, size) SM_RPOOL_T *rpool; size_t size; { SM_POOLLINK_T *p; p = sm_malloc(sizeof(SM_POOLHDR_T) + size); if (p == NULL) return NULL; p->sm_pnext = rpool->sm_pools; rpool->sm_pools = p; return (char*) p + sizeof(SM_POOLHDR_T); } /* ** SM_RPOOL_MALLOC_TAGGED_X -- allocate memory from rpool ** ** Parameters: ** rpool -- rpool from which memory should be allocated; ** can be NULL, use sm_malloc() then. ** size -- size of block. ** file -- filename. ** line -- line number in file. ** group -- heap group for debugging. ** ** Returns: ** Pointer to block. ** ** Exceptions: ** F:sm_heap -- out of memory ** ** Notice: XXX ** if size == 0 and the rpool is new (no memory ** allocated yet) NULL is returned! ** We could solve this by ** - wasting 1 byte (size < avail) ** - checking for rpool->sm_poolptr != NULL ** - not asking for 0 sized buffer */ void * #if SM_HEAP_CHECK sm_rpool_malloc_tagged_x(rpool, size, file, line, group) SM_RPOOL_T *rpool; size_t size; char *file; int line; int group; #else /* SM_HEAP_CHECK */ sm_rpool_malloc_x(rpool, size) SM_RPOOL_T *rpool; size_t size; #endif /* SM_HEAP_CHECK */ { char *ptr; if (rpool == NULL) return sm_malloc_tagged_x(size, file, line, group); /* Ensure that size is properly aligned. */ if (size & SM_ALIGN_BITS) size = (size & ~SM_ALIGN_BITS) + SM_ALIGN_SIZE; /* The common case. This is optimized for speed. */ if (size <= rpool->sm_poolavail) { ptr = rpool->sm_poolptr; rpool->sm_poolptr += size; rpool->sm_poolavail -= size; return ptr; } /* ** The slow case: we need to call malloc. ** The SM_REQUIRE assertion is deferred until now, for speed. ** That's okay: we set rpool->sm_poolavail to 0 when we free an rpool, ** so the common case code won't be triggered on a dangling pointer. */ SM_REQUIRE(rpool->sm_magic == SmRpoolMagic); /* ** If size > sm_poolsize, then malloc a new block especially for ** this request. Future requests will be allocated from the ** current pool. ** ** What if the current pool is mostly unallocated, and the current ** request is larger than the available space, but < sm_poolsize? ** If we discard the current pool, and start allocating from a new ** pool, then we will be wasting a lot of space. For this reason, ** we malloc a block just for the current request if size > ** sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize. ** Thus, the most space that we will waste at the end of a pool ** is sm_bigobjectsize - 1. */ if (size > rpool->sm_bigobjectsize) { #if _FFR_PERF_RPOOL ++rpool->sm_nbigblocks; #endif /* _FFR_PERF_RPOOL */ return sm_rpool_allocblock_x(rpool, size); } SM_ASSERT(rpool->sm_bigobjectsize <= rpool->sm_poolsize); ptr = sm_rpool_allocblock_x(rpool, rpool->sm_poolsize); rpool->sm_poolptr = ptr + size; rpool->sm_poolavail = rpool->sm_poolsize - size; #if _FFR_PERF_RPOOL ++rpool->sm_npools; #endif /* _FFR_PERF_RPOOL */ return ptr; } /* ** SM_RPOOL_MALLOC_TAGGED -- allocate memory from rpool ** ** Parameters: ** rpool -- rpool from which memory should be allocated; ** can be NULL, use sm_malloc() then. ** size -- size of block. ** file -- filename. ** line -- line number in file. ** group -- heap group for debugging. ** ** Returns: ** Pointer to block, NULL on failure. ** ** Notice: XXX ** if size == 0 and the rpool is new (no memory ** allocated yet) NULL is returned! ** We could solve this by ** - wasting 1 byte (size < avail) ** - checking for rpool->sm_poolptr != NULL ** - not asking for 0 sized buffer */ void * #if SM_HEAP_CHECK sm_rpool_malloc_tagged(rpool, size, file, line, group) SM_RPOOL_T *rpool; size_t size; char *file; int line; int group; #else /* SM_HEAP_CHECK */ sm_rpool_malloc(rpool, size) SM_RPOOL_T *rpool; size_t size; #endif /* SM_HEAP_CHECK */ { char *ptr; if (rpool == NULL) return sm_malloc_tagged(size, file, line, group); /* Ensure that size is properly aligned. */ if (size & SM_ALIGN_BITS) size = (size & ~SM_ALIGN_BITS) + SM_ALIGN_SIZE; /* The common case. This is optimized for speed. */ if (size <= rpool->sm_poolavail) { ptr = rpool->sm_poolptr; rpool->sm_poolptr += size; rpool->sm_poolavail -= size; return ptr; } /* ** The slow case: we need to call malloc. ** The SM_REQUIRE assertion is deferred until now, for speed. ** That's okay: we set rpool->sm_poolavail to 0 when we free an rpool, ** so the common case code won't be triggered on a dangling pointer. */ SM_REQUIRE(rpool->sm_magic == SmRpoolMagic); /* ** If size > sm_poolsize, then malloc a new block especially for ** this request. Future requests will be allocated from the ** current pool. ** ** What if the current pool is mostly unallocated, and the current ** request is larger than the available space, but < sm_poolsize? ** If we discard the current pool, and start allocating from a new ** pool, then we will be wasting a lot of space. For this reason, ** we malloc a block just for the current request if size > ** sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize. ** Thus, the most space that we will waste at the end of a pool ** is sm_bigobjectsize - 1. */ if (size > rpool->sm_bigobjectsize) { #if _FFR_PERF_RPOOL ++rpool->sm_nbigblocks; #endif /* _FFR_PERF_RPOOL */ return sm_rpool_allocblock(rpool, size); } SM_ASSERT(rpool->sm_bigobjectsize <= rpool->sm_poolsize); ptr = sm_rpool_allocblock(rpool, rpool->sm_poolsize); if (ptr == NULL) return NULL; rpool->sm_poolptr = ptr + size; rpool->sm_poolavail = rpool->sm_poolsize - size; #if _FFR_PERF_RPOOL ++rpool->sm_npools; #endif /* _FFR_PERF_RPOOL */ return ptr; } /* ** SM_RPOOL_NEW_X -- create a new rpool. ** ** Parameters: ** parent -- pointer to parent rpool, can be NULL. ** ** Returns: ** Pointer to new rpool. */ SM_RPOOL_T * sm_rpool_new_x(parent) SM_RPOOL_T *parent; { SM_RPOOL_T *rpool; rpool = sm_malloc_x(sizeof(SM_RPOOL_T)); if (parent == NULL) rpool->sm_parentlink = NULL; else { SM_TRY rpool->sm_parentlink = sm_rpool_attach_x(parent, (SM_RPOOL_RFREE_T) sm_rpool_free, (void *) rpool); SM_EXCEPT(exc, "*") sm_free(rpool); sm_exc_raise_x(exc); SM_END_TRY } rpool->sm_magic = SmRpoolMagic; rpool->sm_poolsize = POOLSIZE - sizeof(SM_POOLHDR_T); rpool->sm_bigobjectsize = rpool->sm_poolsize / BIG_OBJECT_RATIO; rpool->sm_poolptr = NULL; rpool->sm_poolavail = 0; rpool->sm_pools = NULL; rpool->sm_rptr = NULL; rpool->sm_ravail = 0; rpool->sm_rlists = NULL; #if _FFR_PERF_RPOOL rpool->sm_nbigblocks = 0; rpool->sm_npools = 0; #endif /* _FFR_PERF_RPOOL */ return rpool; } /* ** SM_RPOOL_SETSIZES -- set sizes for rpool. ** ** Parameters: ** poolsize -- size of a single rpool block. ** bigobjectsize -- if this size is exceeded, an individual ** block is allocated (must be less or equal poolsize). ** ** Returns: ** none. */ void sm_rpool_setsizes(rpool, poolsize, bigobjectsize) SM_RPOOL_T *rpool; size_t poolsize; size_t bigobjectsize; { SM_REQUIRE(poolsize >= bigobjectsize); if (poolsize == 0) poolsize = POOLSIZE - sizeof(SM_POOLHDR_T); if (bigobjectsize == 0) bigobjectsize = poolsize / BIG_OBJECT_RATIO; rpool->sm_poolsize = poolsize; rpool->sm_bigobjectsize = bigobjectsize; } /* ** SM_RPOOL_FREE -- free an rpool and release all of its resources. ** ** Parameters: ** rpool -- rpool to free. ** ** Returns: ** none. */ void sm_rpool_free(rpool) SM_RPOOL_T *rpool; { SM_RLIST_T *rl, *rnext; SM_RESOURCE_T *r, *rmax; SM_POOLLINK_T *pp, *pnext; if (rpool == NULL) return; /* ** It's important to free the resources before the memory pools, ** because the resource free functions might modify the contents ** of the memory pools. */ rl = rpool->sm_rlists; if (rl != NULL) { rmax = rpool->sm_rptr; for (;;) { for (r = rl->sm_rvec; r < rmax; ++r) { if (r->sm_rfree != NULL) r->sm_rfree(r->sm_rcontext); } rnext = rl->sm_rnext; sm_free(rl); if (rnext == NULL) break; rl = rnext; rmax = &rl->sm_rvec[SM_RLIST_MAX]; } } /* ** Now free the memory pools. */ for (pp = rpool->sm_pools; pp != NULL; pp = pnext) { pnext = pp->sm_pnext; sm_free(pp); } /* ** Disconnect rpool from its parent. */ if (rpool->sm_parentlink != NULL) *rpool->sm_parentlink = NULL; /* ** Setting these fields to zero means that any future to attempt ** to use the rpool after it is freed will cause an assertion failure. */ rpool->sm_magic = NULL; rpool->sm_poolavail = 0; rpool->sm_ravail = 0; #if _FFR_PERF_RPOOL if (rpool->sm_nbigblocks > 0 || rpool->sm_npools > 1) syslog(LOG_NOTICE, "perf: rpool=%lx, sm_nbigblocks=%d, sm_npools=%d", (long) rpool, rpool->sm_nbigblocks, rpool->sm_npools); rpool->sm_nbigblocks = 0; rpool->sm_npools = 0; #endif /* _FFR_PERF_RPOOL */ sm_free(rpool); } /* ** SM_RPOOL_ATTACH_X -- attach a resource to an rpool. ** ** Parameters: ** rpool -- rpool to which resource should be attached. ** rfree -- function to call when rpool is freed. ** rcontext -- argument for function to call when rpool is freed. ** ** Returns: ** Pointer to allocated function. ** ** Exceptions: ** F:sm_heap -- out of memory */ SM_RPOOL_ATTACH_T sm_rpool_attach_x(rpool, rfree, rcontext) SM_RPOOL_T *rpool; SM_RPOOL_RFREE_T rfree; void *rcontext; { SM_RLIST_T *rl; SM_RPOOL_ATTACH_T a; SM_REQUIRE_ISA(rpool, SmRpoolMagic); if (rpool->sm_ravail == 0) { rl = sm_malloc_x(sizeof(SM_RLIST_T)); rl->sm_rnext = rpool->sm_rlists; rpool->sm_rlists = rl; rpool->sm_rptr = rl->sm_rvec; rpool->sm_ravail = SM_RLIST_MAX; } a = &rpool->sm_rptr->sm_rfree; rpool->sm_rptr->sm_rfree = rfree; rpool->sm_rptr->sm_rcontext = rcontext; ++rpool->sm_rptr; --rpool->sm_ravail; return a; } #if DO_NOT_USE_STRCPY /* ** SM_RPOOL_STRDUP_X -- Create a copy of a C string ** ** Parameters: ** rpool -- rpool to use. ** s -- the string to copy. ** ** Returns: ** pointer to newly allocated string. */ char * sm_rpool_strdup_x(rpool, s) SM_RPOOL_T *rpool; const char *s; { size_t l; char *n; l = strlen(s); SM_ASSERT(l + 1 > l); n = sm_rpool_malloc_x(rpool, l + 1); sm_strlcpy(n, s, l + 1); return n; } #endif /* DO_NOT_USE_STRCPY */ dk-milter-1.0.0.dfsg/libsm/flags.c0000644000175000017500000000241610542040427016433 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004, 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: flags.c,v 1.23 2006/12/19 19:44:23 ca Exp $") #include #include #include #include #include "local.h" /* ** SM_FLAGS -- translate external (user) flags into internal flags ** ** Paramters: ** flags -- user select flags ** ** Returns: ** Internal flag value matching user selected flags */ int sm_flags(flags) int flags; { int ret; switch(SM_IO_MODE(flags)) { case SM_IO_RDONLY: /* open for reading */ ret = SMRD; break; case SM_IO_WRONLY: /* open for writing */ ret = SMWR; break; case SM_IO_APPEND: /* open for appending */ ret = SMWR; break; case SM_IO_RDWR: /* open for read and write */ ret = SMRW; break; default: ret = 0; break; } if (SM_IS_BINARY(flags)) ret |= SM_IO_BINARY; return ret; } dk-milter-1.0.0.dfsg/libsm/vsscanf.c0000644000175000017500000000407107426376460017021 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: vsscanf.c,v 1.23 2002/02/01 02:28:00 ca Exp $") #include #include /* ** SM_EOFREAD -- dummy read function for faked file below ** ** Parameters: ** fp -- file pointer ** buf -- location to place read data ** len -- number of bytes to read ** ** Returns: ** 0 (zero) always */ /* type declaration for later use */ static ssize_t sm_eofread __P((SM_FILE_T *, char *, size_t)); /* ARGSUSED0 */ static ssize_t sm_eofread(fp, buf, len) SM_FILE_T *fp; char *buf; size_t len; { return 0; } /* ** SM_VSSCANF -- scan a string to find data units ** ** Parameters: ** str -- strings containing data ** fmt -- format directive for finding data units ** ap -- memory locations to place format found data units ** ** Returns: ** Failure: SM_IO_EOF ** Success: number of data units found ** ** Side Effects: ** Attempts to strlen() 'str'; if not a '\0' terminated string ** then the call may SEGV/fail. ** Faking the string 'str' as a file. */ int sm_vsscanf(str, fmt, ap) const char *str; const char *fmt; SM_VA_LOCAL_DECL { SM_FILE_T fake; fake.sm_magic = SmFileMagic; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; fake.f_file = -1; fake.f_flags = SMRD; fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; fake.f_bf.smb_size = fake.f_r = strlen(str); fake.f_read = sm_eofread; fake.f_ub.smb_base = NULL; fake.f_close = NULL; fake.f_open = NULL; fake.f_write = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_vsscanf:fake"; return sm_vfscanf(&fake, SM_TIME_FOREVER, fmt, ap); } dk-milter-1.0.0.dfsg/libsm/setvbuf.c0000644000175000017500000001036607347306541017033 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: setvbuf.c,v 1.32 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include #include #include #include "local.h" /* ** SM_IO_SETVBUF -- set the buffering type for a file ** ** Set one of the different kinds of buffering, optionally including ** a buffer. ** If 'size' is == 0 then an "optimal" size will be selected. ** If 'buf' is == NULL then space will be allocated at 'size'. ** ** Parameters: ** fp -- the file that buffering is to be changed for ** timeout -- time allowed for completing the function ** buf -- buffer to use ** mode -- buffering method to use ** size -- size of 'buf' ** ** Returns: ** Failure: SM_IO_EOF ** Success: 0 (zero) */ int sm_io_setvbuf(fp, timeout, buf, mode, size) SM_FILE_T *fp; int timeout; char *buf; int mode; size_t size; { int ret, flags; size_t iosize; int ttyflag; #ifndef WIN32 int fd; struct timeval to; #endif /* WIN32 */ SM_REQUIRE_ISA(fp, SmFileMagic); /* ** Verify arguments. The `int' limit on `size' is due to this ** particular implementation. Note, buf and size are ignored ** when setting SM_IO_NBF. */ if (mode != SM_IO_NBF) if ((mode != SM_IO_FBF && mode != SM_IO_LBF && mode != SM_IO_NOW) || (int) size < 0) return SM_IO_EOF; /* ** Write current buffer, if any. Discard unread input (including ** ungetc data), cancel line buffering, and free old buffer if ** malloc()ed. We also clear any eof condition, as if this were ** a seek. */ ret = 0; SM_CONVERT_TIME(fp, fd, timeout, &to); (void) sm_flush(fp, &timeout); if (HASUB(fp)) FREEUB(fp); fp->f_r = fp->f_lbfsize = 0; flags = fp->f_flags; if (flags & SMMBF) { sm_free((void *) fp->f_bf.smb_base); fp->f_bf.smb_base = NULL; } flags &= ~(SMLBF | SMNBF | SMMBF | SMOPT | SMNPT | SMFEOF | SMNOW | SMFBF); /* If setting unbuffered mode, skip all the hard work. */ if (mode == SM_IO_NBF) goto nbf; /* ** Find optimal I/O size for seek optimization. This also returns ** a `tty flag' to suggest that we check isatty(fd), but we do not ** care since our caller told us how to buffer. */ flags |= sm_whatbuf(fp, &iosize, &ttyflag); if (size == 0) { buf = NULL; /* force local allocation */ size = iosize; } /* Allocate buffer if needed. */ if (buf == NULL) { if ((buf = sm_malloc(size)) == NULL) { /* ** Unable to honor user's request. We will return ** failure, but try again with file system size. */ ret = SM_IO_EOF; if (size != iosize) { size = iosize; buf = sm_malloc(size); } } if (buf == NULL) { /* No luck; switch to unbuffered I/O. */ nbf: fp->f_flags = flags | SMNBF; fp->f_w = 0; fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; fp->f_bf.smb_size = 1; return ret; } flags |= SMMBF; } /* ** Kill any seek optimization if the buffer is not the ** right size. ** ** SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)? */ if (size != iosize) flags |= SMNPT; /* ** Fix up the SM_FILE_T fields, and set sm_cleanup for output flush on ** exit (since we are buffered in some way). */ if (mode == SM_IO_LBF) flags |= SMLBF; else if (mode == SM_IO_NOW) flags |= SMNOW; else if (mode == SM_IO_FBF) flags |= SMFBF; fp->f_flags = flags; fp->f_bf.smb_base = fp->f_p = (unsigned char *)buf; fp->f_bf.smb_size = size; /* fp->f_lbfsize is still 0 */ if (flags & SMWR) { /* ** Begin or continue writing: see sm_wsetup(). Note ** that SMNBF is impossible (it was handled earlier). */ if (flags & SMLBF) { fp->f_w = 0; fp->f_lbfsize = -fp->f_bf.smb_size; } else fp->f_w = size; } else { /* begin/continue reading, or stay in intermediate state */ fp->f_w = 0; } atexit(sm_cleanup); return ret; } dk-milter-1.0.0.dfsg/libsm/b-strcmp.c0000644000175000017500000000662610253661450017101 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: b-strcmp.c,v 1.14 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #define toseconds(x, y) (x.tv_sec - y.tv_sec) #define SIZE 512 #define LOOPS 4000000L /* initial number of loops */ #define MAXTIME 30L /* "maximum" time to run single test */ void fatal __P((char *)); void purpose __P((void)); int main __P((int, char *[])); void fatal(str) char *str; { perror(str); exit(1); } void purpose() { printf("This program benchmarks the performance differences between\n"); printf("strcasecmp() and sm_strcasecmp().\n"); printf("These tests may take several minutes to complete.\n"); } int main(argc, argv) int argc; char *argv[]; { long a; int k; bool doit = false; long loops; long j; long one, two; struct timeval t1, t2; char src1[SIZE], src2[SIZE]; # define OPTIONS "d" while ((k = getopt(argc, argv, OPTIONS)) != -1) { switch ((char) k) { case 'd': doit = true; break; default: break; } } if (!doit) { purpose(); printf("If you want to run it, specify -d as option.\n"); return 0; } /* Run-time comments to the user */ purpose(); printf("\n"); for (k = 0; k < 3; k++) { switch (k) { case 0: (void) sm_strlcpy(src1, "1234567890", SIZE); (void) sm_strlcpy(src2, "1234567890", SIZE); break; case 1: (void) sm_strlcpy(src1, "1234567890", SIZE); (void) sm_strlcpy(src2, "1234567891", SIZE); break; case 2: (void) sm_strlcpy(src1, "1234567892", SIZE); (void) sm_strlcpy(src2, "1234567891", SIZE); break; } printf("Test %d: strcasecmp(%s, %s) versus sm_strcasecmp()\n", k, src1, src2); loops = LOOPS; for (;;) { j = 0; if (gettimeofday(&t1, NULL) < 0) fatal("gettimeofday"); for (a = 0; a < loops; a++) j += strcasecmp(src1, src2); if (gettimeofday(&t2, NULL) < 0) fatal("gettimeofday"); one = toseconds(t2, t1); printf("\tstrcasecmp() result: %ld seconds [%ld]\n", one, j); j = 0; if (gettimeofday(&t1, NULL) < 0) fatal("gettimeofday"); for (a = 0; a < loops; a++) j += sm_strcasecmp(src1, src2); if (gettimeofday(&t2, NULL) < 0) fatal("gettimeofday"); two = toseconds(t2, t1); printf("\tsm_strcasecmp() result: %ld seconds [%ld]\n", two, j); if (abs(one - two) > 2) break; loops += loops; if (loops < 0L || one > MAXTIME) { printf("\t\t** results too close: no decision\n"); break; } else { printf("\t\t** results too close redoing test %ld times **\n", loops); } } } printf("\n\n"); printf("Interpreting the results:\n"); printf("\tFor differences larger than 2 seconds, the lower value is\n"); printf("\tbetter and that function should be used for performance\n"); printf("\treasons.\n\n"); printf("This program will re-run the tests when the difference is\n"); printf("less than 2 seconds.\n"); printf("The result will vary depending on the compiler optimization\n"); printf("level used. Compiling the sendmail libsm library with a\n"); printf("better optimization level can change the results.\n"); return 0; } dk-milter-1.0.0.dfsg/libsm/fscanf.c0000644000175000017500000000254307347306540016612 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fscanf.c,v 1.17 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include "local.h" /* ** SM_IO_FSCANF -- convert input data to translated format ** ** Parameters: ** fp -- the file pointer to obtain the data from ** timeout -- time to complete scan ** fmt -- the format to translate the data to ** ... -- memory locations to place the formated data ** ** Returns: ** Failure: returns SM_IO_EOF ** Success: returns the number of data units translated */ int #if SM_VA_STD sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) #else /* SM_VA_STD */ sm_io_fscanf(fp, timeout, fmt, va_alist) SM_FILE_T *fp; int timeout; char *fmt; va_dcl #endif /* SM_VA_STD */ { int ret; SM_VA_LOCAL_DECL SM_REQUIRE_ISA(fp, SmFileMagic); SM_VA_START(ap, fmt); ret = sm_vfscanf(fp, timeout, fmt, ap); SM_VA_END(ap); return ret; } dk-milter-1.0.0.dfsg/libsm/refill.c0000644000175000017500000001633610401115371016615 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2005-2006 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: refill.c,v 1.53 2006/02/28 18:48:25 ca Exp $") #include #include #include #include #include #include #include #include #include #include #include #include "local.h" static int sm_lflush __P((SM_FILE_T *, int *)); #ifndef WIN32 /* ** SM_IO_RD_TIMEOUT -- measured timeout for reads ** ** This #define uses a select() to wait for the 'fd' to become readable. ** The select() can be active for up to 'To' time. The select() may not ** use all of the the 'To' time. Hence, the amount of "wall-clock" time is ** measured to decide how much to subtract from 'To' to update it. On some ** BSD-based/like systems the timeout for a select() is updated for the ** amount of time used. On many/most systems this does not happen. Therefore ** the updating of 'To' must be done ourselves; a copy of 'To' is passed ** since a BSD-like system will have updated it and we don't want to ** double the time used! ** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the ** sendmail buffered file type in sendmail/bf.c; see use below). ** ** Parameters ** fp -- the file pointer for the active file ** fd -- raw file descriptor (from 'fp') to use for select() ** to -- struct timeval of the timeout ** timeout -- the original timeout value ** sel_ret -- the return value from the select() ** ** Returns: ** nothing, flow through code */ #define SM_IO_RD_TIMEOUT(fp, fd, to, timeout, sel_ret) \ { \ struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \ fd_set sm_io_to_mask, sm_io_x_mask; \ errno = 0; \ if (timeout == SM_TIME_IMMEDIATE) \ { \ errno = EAGAIN; \ return SM_IO_EOF; \ } \ if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \ { \ errno = EINVAL; \ return SM_IO_EOF; \ } \ FD_ZERO(&sm_io_to_mask); \ FD_SET((fd), &sm_io_to_mask); \ FD_ZERO(&sm_io_x_mask); \ FD_SET((fd), &sm_io_x_mask); \ if (gettimeofday(&sm_io_to_before, NULL) < 0) \ return SM_IO_EOF; \ do \ { \ (sel_ret) = select((fd) + 1, &sm_io_to_mask, NULL, \ &sm_io_x_mask, (to)); \ } while ((sel_ret) < 0 && errno == EINTR); \ if ((sel_ret) < 0) \ { \ /* something went wrong, errno set */ \ fp->f_r = 0; \ fp->f_flags |= SMERR; \ return SM_IO_EOF; \ } \ else if ((sel_ret) == 0) \ { \ /* timeout */ \ errno = EAGAIN; \ return SM_IO_EOF; \ } \ /* calulate wall-clock time used */ \ if (gettimeofday(&sm_io_to_after, NULL) < 0) \ return SM_IO_EOF; \ timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \ timersub((to), &sm_io_to_diff, (to)); \ } #endif /* ! WIN32 */ /* ** SM_LFLUSH -- flush a file if it is line buffered and writable ** ** Parameters: ** fp -- file pointer to flush ** timeout -- original timeout value (in milliseconds) ** ** Returns: ** Failure: returns SM_IO_EOF and sets errno ** Success: returns 0 */ static int sm_lflush(fp, timeout) SM_FILE_T *fp; int *timeout; { if ((fp->f_flags & (SMLBF|SMWR)) == (SMLBF|SMWR)) return sm_flush(fp, timeout); return 0; } /* ** SM_REFILL -- refill a buffer ** ** Parameters: ** fp -- file pointer for buffer refill ** timeout -- time to complete filling the buffer in milliseconds ** ** Returns: ** Success: returns 0 ** Failure: returns SM_IO_EOF */ int sm_refill(fp, timeout) register SM_FILE_T *fp; int timeout; { int ret, r; #ifndef WIN32 struct timeval to; int fd; #endif /* !WIN32 */ if (timeout == SM_TIME_DEFAULT) timeout = fp->f_timeout; if (timeout == SM_TIME_IMMEDIATE) { /* ** Filling the buffer will take time and we are wanted to ** return immediately. And we're not EOF or ERR really. ** So... the failure is we couldn't do it in time. */ errno = EAGAIN; fp->f_r = 0; /* just to be sure */ return 0; } /* make sure stdio is set up */ if (!Sm_IO_DidInit) sm_init(); fp->f_r = 0; /* largely a convenience for callers */ if (fp->f_flags & SMFEOF) return SM_IO_EOF; SM_CONVERT_TIME(fp, fd, timeout, &to); /* if not already reading, have to be reading and writing */ if ((fp->f_flags & SMRD) == 0) { if ((fp->f_flags & SMRW) == 0) { errno = EBADF; fp->f_flags |= SMERR; return SM_IO_EOF; } /* switch to reading */ if (fp->f_flags & SMWR) { if (sm_flush(fp, &timeout)) return SM_IO_EOF; fp->f_flags &= ~SMWR; fp->f_w = 0; fp->f_lbfsize = 0; } fp->f_flags |= SMRD; } else { /* ** We were reading. If there is an ungetc buffer, ** we must have been reading from that. Drop it, ** restoring the previous buffer (if any). If there ** is anything in that buffer, return. */ if (HASUB(fp)) { FREEUB(fp); if ((fp->f_r = fp->f_ur) != 0) { fp->f_p = fp->f_up; /* revert blocking state */ return 0; } } } if (fp->f_bf.smb_base == NULL) sm_makebuf(fp); /* ** Before reading from a line buffered or unbuffered file, ** flush all line buffered output files, per the ANSI C standard. */ if (fp->f_flags & (SMLBF|SMNBF)) (void) sm_fwalk(sm_lflush, &timeout); /* ** If this file is linked to another, and we are going to hang ** on the read, flush the linked file before continuing. */ if (fp->f_flushfp != NULL && (*fp->f_getinfo)(fp, SM_IO_IS_READABLE, NULL) <= 0) sm_flush(fp->f_flushfp, &timeout); fp->f_p = fp->f_bf.smb_base; /* ** The do-while loop stops trying to read when something is read ** or it appears that the timeout has expired before finding ** something available to be read (via select()). */ ret = 0; do { errno = 0; /* needed to ensure EOF correctly found */ r = (*fp->f_read)(fp, (char *)fp->f_p, fp->f_bf.smb_size); if (r <= 0) { if (r == 0 && errno == 0) break; /* EOF found */ #ifdef WIN32 else goto err; #else /* WIN32 */ if (IS_IO_ERROR(fd, r, timeout)) goto err; /* errno set */ /* read would block */ SM_IO_RD_TIMEOUT(fp, fd, &to, timeout, ret); #endif /* WIN32 */ } } while (r <= 0 && ret > 0); err: if (r <= 0) { if (r == 0) fp->f_flags |= SMFEOF; else fp->f_flags |= SMERR; fp->f_r = 0; return SM_IO_EOF; } fp->f_r = r; return 0; } /* ** SM_RGET -- refills buffer and returns first character ** ** Handle sm_getc() when the buffer ran out: ** Refill, then return the first character in the newly-filled buffer. ** ** Parameters: ** fp -- file pointer to work on ** timeout -- time to complete refill ** ** Returns: ** Success: first character in refilled buffer as an int ** Failure: SM_IO_EOF */ int sm_rget(fp, timeout) register SM_FILE_T *fp; int timeout; { if (sm_refill(fp, timeout) == 0) { fp->f_r--; return *fp->f_p++; } return SM_IO_EOF; } dk-milter-1.0.0.dfsg/libsm/strexit.c0000644000175000017500000000541507347306541017056 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: strexit.c,v 1.5 2001/09/11 04:04:49 gshapiro Exp $") #include #include /* ** SM_STREXIT -- convert EX_* value from to a character string ** ** This function is analogous to strerror(), except that it ** operates on EX_* values from . ** ** Parameters: ** ex -- EX_* value ** ** Results: ** pointer to a static message string */ char * sm_strexit(ex) int ex; { char *msg; static char buf[64]; msg = sm_sysexitmsg(ex); if (msg == NULL) { (void) sm_snprintf(buf, sizeof buf, "Unknown exit status %d", ex); msg = buf; } return msg; } /* ** SM_SYSEXITMSG -- convert an EX_* value to a character string, or NULL ** ** Parameters: ** ex -- EX_* value ** ** Results: ** If ex is a known exit value, then a pointer to a static ** message string is returned. Otherwise NULL is returned. */ char * sm_sysexitmsg(ex) int ex; { char *msg; msg = sm_sysexmsg(ex); if (msg != NULL) return &msg[11]; else return msg; } /* ** SM_SYSEXMSG -- convert an EX_* value to a character string, or NULL ** ** Parameters: ** ex -- EX_* value ** ** Results: ** If ex is a known exit value, then a pointer to a static ** string is returned. Otherwise NULL is returned. ** The string contains the following fixed width fields: ** [0] ':' if there is an errno value associated with this ** exit value, otherwise ' '. ** [1,3] 3 digit SMTP error code ** [4] ' ' ** [5,9] 3 digit SMTP extended error code ** [10] ' ' ** [11,] message string */ char * sm_sysexmsg(ex) int ex; { switch (ex) { case EX_USAGE: return " 500 5.0.0 Command line usage error"; case EX_DATAERR: return " 501 5.6.0 Data format error"; case EX_NOINPUT: return ":550 5.3.0 Cannot open input"; case EX_NOUSER: return " 550 5.1.1 User unknown"; case EX_NOHOST: return " 550 5.1.2 Host unknown"; case EX_UNAVAILABLE: return " 554 5.0.0 Service unavailable"; case EX_SOFTWARE: return ":554 5.3.0 Internal error"; case EX_OSERR: return ":451 4.0.0 Operating system error"; case EX_OSFILE: return ":554 5.3.5 System file missing"; case EX_CANTCREAT: return ":550 5.0.0 Can't create output"; case EX_IOERR: return ":451 4.0.0 I/O error"; case EX_TEMPFAIL: return " 450 4.0.0 Deferred"; case EX_PROTOCOL: return " 554 5.5.0 Remote protocol error"; case EX_NOPERM: return ":550 5.0.0 Insufficient permission"; case EX_CONFIG: return " 554 5.3.5 Local configuration error"; default: return NULL; } } dk-milter-1.0.0.dfsg/libsm/string.c0000644000175000017500000000166207347306541016662 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: string.c,v 1.3 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include /* ** 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. ** ** Returns: ** none. ** ** Side Effects: ** none. */ void stripquotes(s) char *s; { register char *p; register char *q; register char c; if (s == NULL) return; p = q = s; do { c = *p++; if (c == '\\') c = *p++; else if (c == '"') continue; *q++ = c; } while (c != '\0'); } dk-milter-1.0.0.dfsg/libsm/put.c0000644000175000017500000000316207410021547016150 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: put.c,v 1.27 2001/12/19 05:19:35 ca Exp $") #include #include #include #include #include #include #include "local.h" #include "fvwrite.h" /* ** SM_IO_PUTC -- output a character to the file ** ** Function version of the macro sm_io_putc (in ). ** ** Parameters: ** fp -- file to output to ** timeout -- time to complete putc ** c -- int value of character to output ** ** Returns: ** Failure: returns SM_IO_EOF _and_ sets errno ** Success: returns sm_putc() value. ** */ #undef sm_io_putc int sm_io_putc(fp, timeout, c) SM_FILE_T *fp; int timeout; int c; { SM_REQUIRE_ISA(fp, SmFileMagic); if (cantwrite(fp)) { errno = EBADF; return SM_IO_EOF; } return sm_putc(fp, timeout, c); } /* ** SM_PERROR -- print system error messages to smioerr ** ** Parameters: ** s -- message to print ** ** Returns: ** none */ void sm_perror(s) const char *s; { int save_errno = errno; if (s != NULL && *s != '\0') (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: ", s); (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", sm_errstring(save_errno)); } dk-milter-1.0.0.dfsg/libsm/t-shm.c0000644000175000017500000001065710171625362016402 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: t-shm.c,v 1.22 2005/01/14 02:14:10 ca Exp $") #include #if SM_CONF_SHM # include # include # include # include # include # include # include # define SHMSIZE 1024 # define SHM_MAX 6400000 # define T_SHMKEY 21 /* ** SHMINTER -- interactive testing of shared memory ** ** Parameters: ** owner -- create segment. ** ** Returns: ** 0 on success ** < 0 on failure. */ int shminter __P((bool)); int shminter(owner) bool owner; { int *shm, shmid; int i, t; shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner); if (shm == (int *) 0) { perror("shminit failed"); return -1; } while ((t = getchar()) != EOF) { switch (t) { case 'c': *shm = 0; break; case 'i': ++*shm; break; case 'd': --*shm; break; case 's': sleep(1); break; case 'l': t = *shm; for (i = 0; i < SHM_MAX; i++) { ++*shm; } if (*shm != SHM_MAX + t) fprintf(stderr, "error: %d != %d\n", *shm, SHM_MAX + t); break; case 'v': printf("shmval: %d\n", *shm); break; case 'S': i = sm_shmsetowner(shmid, getuid(), getgid(), 0644); printf("sm_shmsetowner=%d\n", i); break; } } return sm_shmstop((void *) shm, shmid, owner); } /* ** SHMBIG -- testing of shared memory ** ** Parameters: ** owner -- create segment. ** size -- size of segment. ** ** Returns: ** 0 on success ** < 0 on failure. */ int shmbig __P((bool, int)); int shmbig(owner, size) bool owner; int size; { int *shm, shmid; int i; shm = (int *) sm_shmstart(T_SHMKEY, size, 0, &shmid, owner); if (shm == (int *) 0) { perror("shminit failed"); return -1; } for (i = 0; i < size / sizeof(int); i++) shm[i] = i; for (i = 0; i < size / sizeof(int); i++) { if (shm[i] != i) { fprintf(stderr, "failed at %d: %d", i, shm[i]); } } return sm_shmstop((void *) shm, shmid, owner); } /* ** SHMTEST -- test of shared memory ** ** Parameters: ** owner -- create segment. ** ** Returns: ** 0 on success ** < 0 on failure. */ # define MAX_CNT 10 int shmtest __P((int)); int shmtest(owner) int owner; { int *shm, shmid; int cnt = 0; shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner); if (shm == (int *) 0) { perror("shminit failed"); return -1; } if (owner) { int r; r = sm_shmsetowner(shmid, getuid(), getgid(), 0660); SM_TEST(r == 0); *shm = 1; while (*shm == 1 && cnt++ < MAX_CNT) sleep(1); SM_TEST(cnt <= MAX_CNT); /* release and re-acquire the segment */ r = sm_shmstop((void *) shm, shmid, owner); SM_TEST(r == 0); shm = (int *) sm_shmstart(T_SHMKEY, SHMSIZE, 0, &shmid, owner); SM_TEST(shm != (int *) 0); } else { while (*shm != 1 && cnt++ < MAX_CNT) sleep(1); SM_TEST(cnt <= MAX_CNT); *shm = 2; /* wait a momemt so the segment is still in use */ sleep(2); } return sm_shmstop((void *) shm, shmid, owner); } int main(argc, argv) int argc; char *argv[]; { bool interactive = false; bool owner = false; int big = -1; int ch; int r = 0; int status; extern char *optarg; # define OPTIONS "b:io" while ((ch = getopt(argc, argv, OPTIONS)) != -1) { switch ((char) ch) { case 'b': big = atoi(optarg); break; case 'i': interactive = true; break; case 'o': owner = true; break; default: break; } } if (interactive) r = shminter(owner); else if (big > 0) r = shmbig(true, big); else { pid_t pid; extern int SmTestNumErrors; if ((pid = fork()) < 0) { perror("fork failed\n"); return -1; } sm_test_begin(argc, argv, "test shared memory"); if (pid == 0) { /* give the parent the chance to setup data */ sleep(1); r = shmtest(false); } else { r = shmtest(true); (void) wait(&status); } SM_TEST(r == 0); if (SmTestNumErrors > 0) printf("add -DSM_CONF_SHM=0 to confENVDEF in devtools/Site/site.config.m4\nand start over.\n"); return sm_test_end(); } return r; } #else /* SM_CONF_SHM */ int main(argc, argv) int argc; char *argv[]; { printf("No support for shared memory configured on this machine\n"); return 0; } #endif /* SM_CONF_SHM */ dk-milter-1.0.0.dfsg/libsm/vasprintf.c0000644000175000017500000000564207667002200017360 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ /* * Copyright (c) 1997 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include SM_RCSID("@(#)$Id: vasprintf.c,v 1.27 2003/06/03 02:14:24 ca Exp $") #include #include #include #include #include "local.h" /* ** SM_VASPRINTF -- printf to a dynamically allocated string ** ** Write 'printf' output to a dynamically allocated string ** buffer which is returned to the caller. ** ** Parameters: ** str -- *str receives a pointer to the allocated string ** fmt -- format directives for printing ** ap -- variable argument list ** ** Results: ** On failure, set *str to NULL, set errno, and return -1. ** ** On success, set *str to a pointer to a nul-terminated ** string buffer containing printf output, and return the ** length of the string (not counting the nul). */ #define SM_VA_BUFSIZE 128 int sm_vasprintf(str, fmt, ap) char **str; const char *fmt; SM_VA_LOCAL_DECL { int ret; SM_FILE_T fake; unsigned char *base; fake.sm_magic = SmFileMagic; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; fake.f_file = -1; fake.f_flags = SMWR | SMSTR | SMALC; fake.f_bf.smb_base = fake.f_p = (unsigned char *)sm_malloc(SM_VA_BUFSIZE); if (fake.f_bf.smb_base == NULL) goto err2; fake.f_close = NULL; fake.f_open = NULL; fake.f_read = NULL; fake.f_write = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_vasprintf:fake"; fake.f_bf.smb_size = fake.f_w = SM_VA_BUFSIZE - 1; fake.f_timeout = SM_TIME_FOREVER; ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); if (ret == -1) goto err; *fake.f_p = '\0'; /* use no more space than necessary */ base = (unsigned char *) sm_realloc(fake.f_bf.smb_base, ret + 1); if (base == NULL) goto err; *str = (char *)base; return ret; err: if (fake.f_bf.smb_base != NULL) { sm_free(fake.f_bf.smb_base); fake.f_bf.smb_base = NULL; } err2: *str = NULL; errno = ENOMEM; return -1; } dk-milter-1.0.0.dfsg/libsm/cf.c0000644000175000017500000000375407347306537015755 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: cf.c,v 1.6 2001/09/11 04:04:47 gshapiro Exp $") #include #include #include #include #include #include /* ** SM_CF_GETOPT -- look up option values in the sendmail.cf file ** ** Open the sendmail.cf file and parse all of the 'O' directives. ** Each time one of the options named in the option vector optv ** is found, store a malloced copy of the option value in optv. ** ** Parameters: ** path -- pathname of sendmail.cf file ** optc -- size of option vector ** optv -- pointer to option vector ** ** Results: ** 0 on success, or an errno value on failure. ** An exception is raised on malloc failure. */ int sm_cf_getopt(path, optc, optv) char *path; int optc; SM_CF_OPT_T *optv; { SM_FILE_T *cfp; char buf[2048]; char *p; char *id; char *idend; char *val; int i; cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, path, SM_IO_RDONLY, NULL); if (cfp == NULL) return errno; while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL) { p = strchr(buf, '\n'); if (p != NULL) *p = '\0'; if (buf[0] != 'O' || buf[1] != ' ') continue; id = &buf[2]; val = strchr(id, '='); if (val == NULL) val = idend = id + strlen(id); else { idend = val; ++val; while (*val == ' ') ++val; while (idend > id && idend[-1] == ' ') --idend; *idend = '\0'; } for (i = 0; i < optc; ++i) { if (sm_strcasecmp(optv[i].opt_name, id) == 0) { optv[i].opt_val = sm_strdup_x(val); break; } } } if (sm_io_error(cfp)) { int save_errno = errno; (void) sm_io_close(cfp, SM_TIME_DEFAULT); errno = save_errno; return errno; } (void) sm_io_close(cfp, SM_TIME_DEFAULT); return 0; } dk-milter-1.0.0.dfsg/libsm/util.c0000644000175000017500000001072610475355207016331 0ustar madhackmadhack/* * Copyright (c) 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: util.c,v 1.9 2006/08/30 18:35:51 ca Exp $") #include #include #include #include #include #include #include /* ** STR2PRT -- convert "unprintable" characters in a string to \oct ** ** Parameters: ** s -- string to convert ** ** Returns: ** converted string. ** This is a static local buffer, string must be copied ** before this function is called again! */ char * str2prt(s) char *s; { int l; char c, *h; bool ok; static int len = 0; static char *buf = NULL; if (s == NULL) return NULL; ok = true; for (h = s, l = 1; *h != '\0'; h++, l++) { if (*h == '\\') { ++l; ok = false; } else if (!(isascii(*h) && isprint(*h))) { l += 3; ok = false; } } if (ok) return s; if (l > len) { char *nbuf = sm_pmalloc_x(l); if (buf != NULL) sm_free(buf); len = l; buf = nbuf; } for (h = buf; *s != '\0' && l > 0; s++, l--) { c = *s; if (isascii(c) && isprint(c) && c != '\\') { *h++ = c; } else { *h++ = '\\'; --l; switch (c) { case '\\': *h++ = '\\'; break; case '\t': *h++ = 't'; break; case '\n': *h++ = 'n'; break; case '\r': *h++ = 'r'; break; default: SM_ASSERT(l >= 2); (void) sm_snprintf(h, l, "%03o", (unsigned int)((unsigned char) c)); /* ** XXX since l is unsigned this may ** wrap around if the calculation is screwed ** up... */ l -= 2; h += 3; break; } } } *h = '\0'; buf[len - 1] = '\0'; return buf; } /* ** QUOTE_INTERNAL_CHARS -- do quoting of internal characters ** ** Necessary to make sure that we don't have metacharacters such ** as the internal versions of "$*" or "$&" in a string. ** The input and output pointers can be the same. ** ** Parameters: ** ibp -- a pointer to the string to translate ** obp -- a pointer to an output buffer ** bsp -- pointer to the length of the output buffer ** ** Returns: ** A possibly new bp (if the buffer needed to grow); if ** it is different, *bsp will updated to the size of ** the new buffer and the caller is responsible for ** freeing the memory. */ #define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200)) char * quote_internal_chars(ibp, obp, bsp) char *ibp; char *obp; int *bsp; { char *ip, *op; int bufused, olen; bool buffer_same, needs_quoting; buffer_same = ibp == obp; needs_quoting = false; /* determine length of output string (starts at 1 for trailing '\0') */ for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++) { if (SM_MM_QUOTE(*ip)) { olen++; needs_quoting = true; } } /* is the output buffer big enough? */ if (olen > *bsp) { obp = sm_malloc_x(olen); buffer_same = false; *bsp = olen; } /* ** shortcut: no change needed? ** Note: we don't check this first as some bozo may use the same ** buffers but restrict the size of the output buffer to less ** than the length of the input buffer in which case we need to ** allocate a new buffer. */ if (!needs_quoting) { if (!buffer_same) { bufused = sm_strlcpy(obp, ibp, *bsp); SM_ASSERT(bufused <= olen); } return obp; } if (buffer_same) { obp = sm_malloc_x(olen); buffer_same = false; *bsp = olen; } for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++) { if (SM_MM_QUOTE(*ip)) { SM_ASSERT(bufused < olen); op[bufused++] = METAQUOTE; } SM_ASSERT(bufused < olen); op[bufused++] = *ip; } op[bufused] = '\0'; return obp; } /* ** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars ** ** Parameters: ** ibp -- a pointer to the string to be translated. ** obp -- a pointer to the output buffer. Can be the ** same as ibp. ** obs -- the size of the output buffer. ** ** Returns: ** number of character added to obp */ int dequote_internal_chars(ibp, obp, obs) char *ibp; char *obp; int obs; { char *ip, *op; int len; bool quoted; quoted = false; len = 0; for (ip = ibp, op = obp; *ip != '\0'; ip++) { if ((*ip & 0377) == METAQUOTE && !quoted) { quoted = true; continue; } if (op < &obp[obs - 1]) { *op++ = *ip; ++len; } quoted = false; } *op = '\0'; return len; } dk-milter-1.0.0.dfsg/libsm/assert.c0000644000175000017500000001022107764205204016641 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: assert.c,v 1.26 2003/12/05 22:45:24 ca Exp $") /* ** Abnormal program termination and assertion checking. ** For documentation, see assert.html. */ #include #include #include #include #include #include #include /* ** Debug categories that are used to guard expensive assertion checks. */ SM_DEBUG_T SmExpensiveAssert = SM_DEBUG_INITIALIZER("sm_check_assert", "@(#)$Debug: sm_check_assert - check assertions $"); SM_DEBUG_T SmExpensiveRequire = SM_DEBUG_INITIALIZER("sm_check_require", "@(#)$Debug: sm_check_require - check function preconditions $"); SM_DEBUG_T SmExpensiveEnsure = SM_DEBUG_INITIALIZER("sm_check_ensure", "@(#)$Debug: sm_check_ensure - check function postconditions $"); /* ** Debug category: send self SIGSTOP on fatal error, ** so that you can run a debugger on the stopped process. */ SM_DEBUG_T SmAbortStop = SM_DEBUG_INITIALIZER("sm_abort_stop", "@(#)$Debug: sm_abort_stop - stop process on fatal error $"); /* ** SM_ABORT_DEFAULTHANDLER -- Default procedure for abnormal program ** termination. ** ** The goal is to display an error message without disturbing the ** process state too much, then dump core. ** ** Parameters: ** filename -- filename (can be NULL). ** lineno -- line number. ** msg -- message. ** ** Returns: ** doesn't return. */ static void sm_abort_defaulthandler __P(( const char *filename, int lineno, const char *msg)); static void sm_abort_defaulthandler(filename, lineno, msg) const char *filename; int lineno; const char *msg; { if (filename != NULL) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s:%d: %s\n", filename, lineno, msg); else sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", msg); sm_io_flush(smioerr, SM_TIME_DEFAULT); #ifdef SIGSTOP if (sm_debug_active(&SmAbortStop, 1)) kill(getpid(), SIGSTOP); #endif /* SIGSTOP */ abort(); } /* ** This is the action to be taken to cause abnormal program termination. */ static SM_ABORT_HANDLER_T SmAbortHandler = sm_abort_defaulthandler; /* ** SM_ABORT_SETHANDLER -- Set handler for SM_ABORT() ** ** This allows you to set a handler function for causing abnormal ** program termination; it is called when a logic bug is detected. ** ** Parameters: ** f -- handler. ** ** Returns: ** none. */ void sm_abort_sethandler(f) SM_ABORT_HANDLER_T f; { if (f == NULL) SmAbortHandler = sm_abort_defaulthandler; else SmAbortHandler = f; } /* ** SM_ABORT -- Call it when you have detected a logic bug. ** ** Parameters: ** fmt -- format string. ** ... -- arguments. ** ** Returns: ** doesn't. */ void SM_DEAD_D #if SM_VA_STD sm_abort(char *fmt, ...) #else /* SM_VA_STD */ sm_abort(fmt, va_alist) char *fmt; va_dcl #endif /* SM_VA_STD */ { char msg[128]; SM_VA_LOCAL_DECL SM_VA_START(ap, fmt); sm_vsnprintf(msg, sizeof msg, fmt, ap); SM_VA_END(ap); sm_abort_at(NULL, 0, msg); } /* ** SM_ABORT_AT -- Initiate abnormal program termination. ** ** This is the low level function that is called to initiate abnormal ** program termination. It prints an error message and terminates the ** program. It is called by sm_abort and by the assertion macros. ** If filename != NULL then filename and lineno specify the line of source ** code at which the bug was detected. ** ** Parameters: ** filename -- filename (can be NULL). ** lineno -- line number. ** msg -- message. ** ** Returns: ** doesn't. */ void SM_DEAD_D sm_abort_at(filename, lineno, msg) const char *filename; int lineno; const char *msg; { SM_TRY (*SmAbortHandler)(filename, lineno, msg); SM_EXCEPT(exc, "*") sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "exception raised by abort handler:\n"); sm_exc_print(exc, smioerr); sm_io_flush(smioerr, SM_TIME_DEFAULT); SM_END_TRY /* ** SmAbortHandler isn't supposed to return. ** Since it has, let's make sure that the program is terminated. */ abort(); } dk-milter-1.0.0.dfsg/libsm/fprintf.c0000644000175000017500000000255107347306540017021 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fprintf.c,v 1.17 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include "local.h" /* ** SM_IO_FPRINTF -- format and print a string to a file pointer ** ** Parameters: ** fp -- file pointer to be printed to ** timeout -- time to complete print ** fmt -- markup format for the string to be printed ** ... -- additional information for 'fmt' ** ** Returns: ** Failure: returns SM_IO_EOF and sets errno ** Success: returns the number of characters o/p */ int #if SM_VA_STD sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...) #else /* SM_VA_STD */ sm_io_fprintf(fp, timeout, fmt, va_alist) SM_FILE_T *fp; int timeout; char *fmt; va_dcl #endif /* SM_VA_STD */ { int ret; SM_VA_LOCAL_DECL SM_REQUIRE_ISA(fp, SmFileMagic); SM_VA_START(ap, fmt); ret = sm_io_vfprintf(fp, timeout, fmt, ap); SM_VA_END(ap); return ret; } dk-milter-1.0.0.dfsg/libsm/t-sem.c0000644000175000017500000001221410600337042016356 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2005-2007 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: t-sem.c,v 1.16 2007/03/21 23:22:10 ca Exp $") #include #if SM_CONF_SEM # include # include # include # include # include # include # include # include # define T_SM_SEM_KEY (4321L) static void delay(t, s) int t; char *s; { if (t > 0) { #if DEBUG fprintf(stderr, "sleep(%d) before %s\n", t, s); #endif /* DEBUG */ sleep(t); } #if DEBUG fprintf(stderr, "%s\n", s); #endif /* DEBUG */ } /* ** SEMINTER -- interactive testing of semaphores. ** ** Parameters: ** owner -- create semaphores. ** ** Returns: ** 0 on success ** < 0 on failure. */ static int seminter(owner) bool owner; { int semid; int t; semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner); if (semid < 0) { perror("sm_sem_start failed"); return 1; } while ((t = getchar()) != EOF) { switch (t) { case 'a': delay(0, "try to acq"); if (sm_sem_acq(semid, 0, 2) < 0) { perror("sm_sem_acq failed"); return 1; } delay(0, "acquired"); break; case 'r': delay(0, "try to rel"); if (sm_sem_rel(semid, 0, 2) < 0) { perror("sm_sem_rel failed"); return 1; } delay(0, "released"); break; case 'v': if ((t = sm_sem_get(semid, 0)) < 0) { perror("get_sem failed"); return 1; } printf("semval: %d\n", t); break; } } if (owner) return sm_sem_stop(semid); return 0; } /* ** SEM_CLEANUP -- cleanup if something breaks ** ** Parameters: ** sig -- signal. ** ** Returns: ** none. */ static int semid_c = -1; void sem_cleanup(sig) int sig; { if (semid_c >= 0) (void) sm_sem_stop(semid_c); exit(EX_UNAVAILABLE); } /* ** SEMTEST -- test of semaphores ** ** Parameters: ** owner -- create semaphores. ** ** Returns: ** 0 on success ** < 0 on failure. */ # define MAX_CNT 10 static int semtest(owner) int owner; { int semid, r; int cnt = 0; semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner); if (semid < 0) { perror("sm_sem_start failed"); return -1; } if (owner) { /* just in case someone kills the program... */ semid_c = semid; (void) sm_signal(SIGHUP, sem_cleanup); (void) sm_signal(SIGINT, sem_cleanup); (void) sm_signal(SIGTERM, sem_cleanup); delay(1, "parent: acquire 1"); cnt = 0; do { r = sm_sem_acq(semid, 0, 0); if (r < 0) { sleep(1); ++cnt; } } while (r < 0 && cnt <= MAX_CNT); SM_TEST(r >= 0); if (r < 0) return r; delay(3, "parent: release 1"); cnt = 0; do { r = sm_sem_rel(semid, 0, 0); if (r < 0) { sleep(1); ++cnt; } } while (r < 0 && cnt <= MAX_CNT); SM_TEST(r >= 0); if (r < 0) return r; delay(1, "parent: getval"); cnt = 0; do { r = sm_sem_get(semid, 0); if (r <= 0) { sleep(1); ++cnt; } } while (r <= 0 && cnt <= MAX_CNT); SM_TEST(r > 0); if (r <= 0) return r; delay(1, "parent: acquire 2"); cnt = 0; do { r = sm_sem_acq(semid, 0, 0); if (r < 0) { sleep(1); ++cnt; } } while (r < 0 && cnt <= MAX_CNT); SM_TEST(r >= 0); if (r < 0) return r; cnt = 0; do { r = sm_sem_rel(semid, 0, 0); if (r < 0) { sleep(1); ++cnt; } } while (r < 0 && cnt <= MAX_CNT); SM_TEST(r >= 0); if (r < 0) return r; } else { delay(1, "child: acquire 1"); cnt = 0; do { r = sm_sem_acq(semid, 0, 0); if (r < 0) { sleep(1); ++cnt; } } while (r < 0 && cnt <= MAX_CNT); SM_TEST(r >= 0); if (r < 0) return r; delay(1, "child: release 1"); cnt = 0; do { r = sm_sem_rel(semid, 0, 0); if (r < 0) { sleep(1); ++cnt; } } while (r < 0 && cnt <= MAX_CNT); SM_TEST(r >= 0); if (r < 0) return r; } if (owner) return sm_sem_stop(semid); return 0; } int main(argc, argv) int argc; char *argv[]; { bool interactive = false; bool owner = false; int ch; int r = 0; # define OPTIONS "io" while ((ch = getopt(argc, argv, OPTIONS)) != -1) { switch ((char) ch) { case 'i': interactive = true; break; case 'o': owner = true; break; default: break; } } if (interactive) r = seminter(owner); else { pid_t pid; printf("This test takes about 8 seconds.\n"); printf("If it takes longer than 30 seconds, please interrupt it\n"); printf("and compile again without semaphore support, i.e.,"); printf("-DSM_CONF_SEM=0\n"); if ((pid = fork()) < 0) { perror("fork failed\n"); return -1; } sm_test_begin(argc, argv, "test semaphores"); if (pid == 0) { /* give the parent the chance to setup data */ sleep(1); r = semtest(false); } else { r = semtest(true); } SM_TEST(r == 0); return sm_test_end(); } return r; } #else /* SM_CONF_SEM */ int main(argc, argv) int argc; char *argv[]; { printf("No support for semaphores configured on this machine\n"); return 0; } #endif /* SM_CONF_SEM */ dk-milter-1.0.0.dfsg/libsm/memstat.c0000644000175000017500000001217510600066624017016 0ustar madhackmadhack/* * Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: memstat.c,v 1.6 2007/03/20 23:26:12 ca Exp $") #include #include #if USESWAPCTL #include #include static long sc_page_size; /* ** SM_MEMSTAT_OPEN -- open memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_open() { sc_page_size = sysconf(_SC_PAGE_SIZE); if (sc_page_size == -1) return (errno != 0) ? errno : -1; return 0; } /* ** SM_MEMSTAT_CLOSE -- close memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_close() { return 0; } /* ** SM_MEMSTAT_GET -- get memory statistics ** ** Parameters: ** resource -- resource to look up ** pvalue -- (pointer to) memory statistics value (output) ** ** Results: ** 0: success ** !=0: error */ int sm_memstat_get(resource, pvalue) char *resource; long *pvalue; { int r; struct anoninfo ai; r = swapctl(SC_AINFO, &ai); if (r == -1) return (errno != 0) ? errno : -1; r = ai.ani_max - ai.ani_resv; r *= sc_page_size >> 10; *pvalue = r; return 0; } #elif USEKSTAT #include #include static kstat_ctl_t *kc; static kstat_t *kst; /* ** SM_MEMSTAT_OPEN -- open memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_open() { kstat_named_t *kn; kc = kstat_open(); if (kc == NULL) return (errno != 0) ? errno : -1; kst = kstat_lookup(kc, "unix", 0, (name != NULL) ? name : "system_pages"); if (kst == 0) return (errno != 0) ? errno : -2; return 0; } /* ** SM_MEMSTAT_CLOSE -- close memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_close() { int r; if (kc == NULL) return 0; r = kstat_close(kc); if (r != 0) return (errno != 0) ? errno : -1; return 0; } /* ** SM_MEMSTAT_GET -- get memory statistics ** ** Parameters: ** resource -- resource to look up ** pvalue -- (pointer to) memory statistics value (output) ** ** Results: ** 0: success ** !=0: error */ int sm_memstat_get(resource, pvalue) char *resource; long *pvalue; { int r; kstat_named_t *kn; if (kc == NULL || kst == NULL) return -1; if (kstat_read(kc, kst, NULL) == -1) return (errno != 0) ? errno : -2; kn = kstat_data_lookup(kst, (resource != NULL) ? resource: "freemem"); if (kn == NULL) return (errno != 0) ? errno : -3; *pvalue = kn->value.ul; return 0; } #elif USEPROCMEMINFO /* /proc/meminfo? total: used: free: shared: buffers: cached: Mem: 261468160 252149760 9318400 0 3854336 109813760 Swap: 1052794880 62185472 990609408 MemTotal: 255340 kB MemFree: 9100 kB MemShared: 0 kB Buffers: 3764 kB Cached: 107240 kB Active: 104340 kB Inact_dirty: 4220 kB Inact_clean: 2444 kB Inact_target: 4092 kB HighTotal: 0 kB HighFree: 0 kB LowTotal: 255340 kB LowFree: 9100 kB SwapTotal: 1028120 kB SwapFree: 967392 kB */ #include #include static FILE *fp; /* ** SM_MEMSTAT_OPEN -- open memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_open() { fp = fopen("/proc/meminfo", "r"); return (fp != NULL) ? 0 : errno; } /* ** SM_MEMSTAT_CLOSE -- close memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_close() { if (fp != NULL) { fclose(fp); fp = NULL; } return 0; } /* ** SM_MEMSTAT_GET -- get memory statistics ** ** Parameters: ** resource -- resource to look up ** pvalue -- (pointer to) memory statistics value (output) ** ** Results: ** 0: success ** !=0: error */ int sm_memstat_get(resource, pvalue) char *resource; long *pvalue; { int r; size_t l; char buf[80]; if (resource == NULL) return EINVAL; if (pvalue == NULL) return EINVAL; if (fp == NULL) return -1; /* try to reopen? */ rewind(fp); l = strlen(resource); if (l >= sizeof(buf)) return EINVAL; while (fgets(buf, sizeof(buf), fp) != NULL) { if (strncmp(buf, resource, l) == 0 && buf[l] == ':') { r = sscanf(buf + l + 1, "%ld", pvalue); return (r > 0) ? 0 : -1; } } return 0; } #else /* USEPROCMEMINFO */ /* ** SM_MEMSTAT_OPEN -- open memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_open() { return -1; } /* ** SM_MEMSTAT_CLOSE -- close memory statistics ** ** Parameters: ** none ** ** Results: ** errno as error code, 0: ok */ int sm_memstat_close() { return 0; } /* ** SM_MEMSTAT_GET -- get memory statistics ** ** Parameters: ** resource -- resource to look up ** pvalue -- (pointer to) memory statistics value (output) ** ** Results: ** 0: success ** !=0: error */ int sm_memstat_get(resource, pvalue) char *resource; long *pvalue; { return -1; } #endif /* USEKSTAT */ dk-milter-1.0.0.dfsg/libsm/stdio.c0000644000175000017500000002441010253661450016463 0ustar madhackmadhack/* * Copyright (c) 2000-2005 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: stdio.c,v 1.71 2005/06/14 23:07:20 ca Exp $") #include #include #include #include /* FreeBSD: FD_ZERO needs */ #include #include #include #include #include #include #include #include #include #include "local.h" static int sm_stdsetmode __P((SM_FILE_T *, const int *)); static int sm_stdgetmode __P((SM_FILE_T *, int *)); /* ** Overall: ** Small standard I/O/seek/close functions. ** These maintain the `known seek offset' for seek optimization. */ /* ** SM_STDOPEN -- open a file with stdio behavior ** ** Not associated with the system's stdio in libc. ** ** Parameters: ** fp -- file pointer to be associated with the open ** info -- pathname of the file to be opened ** flags -- indicates type of access methods ** rpool -- ignored ** ** Returns: ** Failure: -1 and set errno ** Success: 0 or greater (fd of file from open(2)). ** */ /* ARGSUSED3 */ int sm_stdopen(fp, info, flags, rpool) SM_FILE_T *fp; const void *info; int flags; const void *rpool; { char *path = (char *) info; int oflags; switch (SM_IO_MODE(flags)) { case SM_IO_RDWR: oflags = O_RDWR; break; case SM_IO_RDWRTR: oflags = O_RDWR | O_CREAT | O_TRUNC; break; case SM_IO_RDONLY: oflags = O_RDONLY; break; case SM_IO_WRONLY: oflags = O_WRONLY | O_CREAT | O_TRUNC; break; case SM_IO_APPEND: oflags = O_APPEND | O_WRONLY | O_CREAT; break; case SM_IO_APPENDRW: oflags = O_APPEND | O_RDWR | O_CREAT; break; default: errno = EINVAL; return -1; } #ifdef O_BINARY if (SM_IS_BINARY(flags)) oflags |= O_BINARY; #endif /* O_BINARY */ fp->f_file = open(path, oflags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); if (fp->f_file < 0) return -1; /* errno set by open() */ if (oflags & O_APPEND) (void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END); return fp->f_file; } /* ** SM_STDREAD -- read from the file ** ** Parameters: ** fp -- file pointer to read from ** buf -- location to place read data ** n -- number of bytes to read ** ** Returns: ** Failure: -1 and sets errno ** Success: number of bytes read ** ** Side Effects: ** Updates internal offset into file. */ ssize_t sm_stdread(fp, buf, n) SM_FILE_T *fp; char *buf; size_t n; { register int ret; ret = read(fp->f_file, buf, n); /* if the read succeeded, update the current offset */ if (ret > 0) fp->f_lseekoff += ret; return ret; } /* ** SM_STDWRITE -- write to the file ** ** Parameters: ** fp -- file pointer ro write to ** buf -- location of data to be written ** n - number of bytes to write ** ** Returns: ** Failure: -1 and sets errno ** Success: number of bytes written */ ssize_t sm_stdwrite(fp, buf, n) SM_FILE_T *fp; char const *buf; size_t n; { return write(fp->f_file, buf, n); } /* ** SM_STDSEEK -- set the file offset position ** ** Parmeters: ** fp -- file pointer to position ** offset -- how far to position from "base" (set by 'whence') ** whence -- indicates where the "base" of the 'offset' to start ** ** Results: ** Failure: -1 and sets errno ** Success: the current offset ** ** Side Effects: ** Updates the internal value of the offset. */ off_t sm_stdseek(fp, offset, whence) SM_FILE_T *fp; off_t offset; int whence; { register off_t ret; ret = lseek(fp->f_file, (off_t) offset, whence); if (ret != (off_t) -1) fp->f_lseekoff = ret; return ret; } /* ** SM_STDCLOSE -- close the file ** ** Parameters: ** fp -- the file pointer to close ** ** Returns: ** Success: 0 (zero) ** Failure: -1 and sets errno */ int sm_stdclose(fp) SM_FILE_T *fp; { return close(fp->f_file); } /* ** SM_STDSETMODE -- set the access mode for the file ** ** Called by sm_stdsetinfo(). ** ** Parameters: ** fp -- file pointer ** mode -- new mode to set the file access to ** ** Results: ** Success: 0 (zero); ** Failure: -1 and sets errno */ static int sm_stdsetmode(fp, mode) SM_FILE_T *fp; const int *mode; { int flags = 0; switch (SM_IO_MODE(*mode)) { case SM_IO_RDWR: flags |= SMRW; break; case SM_IO_RDONLY: flags |= SMRD; break; case SM_IO_WRONLY: flags |= SMWR; break; case SM_IO_APPEND: default: errno = EINVAL; return -1; } fp->f_flags = fp->f_flags & ~SMMODEMASK; fp->f_flags |= flags; return 0; } /* ** SM_STDGETMODE -- for getinfo determine open mode ** ** Called by sm_stdgetinfo(). ** ** Parameters: ** fp -- the file mode being determined ** mode -- internal mode to map to external value ** ** Results: ** Failure: -1 and sets errno ** Success: external mode value */ static int sm_stdgetmode(fp, mode) SM_FILE_T *fp; int *mode; { switch (fp->f_flags & SMMODEMASK) { case SMRW: *mode = SM_IO_RDWR; break; case SMRD: *mode = SM_IO_RDONLY; break; case SMWR: *mode = SM_IO_WRONLY; break; default: errno = EINVAL; return -1; } return 0; } /* ** SM_STDSETINFO -- set/modify information for a file ** ** Parameters: ** fp -- file to set info for ** what -- type of info to set ** valp -- location of data used for setting ** ** Returns: ** Failure: -1 and sets errno ** Success: >=0 */ int sm_stdsetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch (what) { case SM_IO_WHAT_MODE: return sm_stdsetmode(fp, (const int *)valp); default: errno = EINVAL; return -1; } } /* ** SM_GETINFO -- get information about the open file ** ** Parameters: ** fp -- file to get info for ** what -- type of info to get ** valp -- location to place found info ** ** Returns: ** Success: may or may not place info in 'valp' depending ** on 'what' value, and returns values >=0. Return ** value may be the obtained info ** Failure: -1 and sets errno */ int sm_stdgetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch (what) { case SM_IO_WHAT_MODE: return sm_stdgetmode(fp, (int *)valp); case SM_IO_WHAT_FD: return fp->f_file; case SM_IO_WHAT_SIZE: { struct stat st; if (fstat(fp->f_file, &st) == 0) return st.st_size; else return -1; } case SM_IO_IS_READABLE: { fd_set readfds; struct timeval timeout; if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE) { errno = EINVAL; return -1; } FD_ZERO(&readfds); SM_FD_SET(fp->f_file, &readfds); timeout.tv_sec = 0; timeout.tv_usec = 0; if (select(fp->f_file + 1, FDSET_CAST &readfds, NULL, NULL, &timeout) > 0 && SM_FD_ISSET(fp->f_file, &readfds)) return 1; return 0; } default: errno = EINVAL; return -1; } } /* ** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname ** ** I/O function to handle fdopen() stdio equivalence. The rest of ** the functions are the same as the sm_stdopen() above. ** ** Parameters: ** fp -- the file pointer to be associated with the open ** name -- the primitive file descriptor for association ** flags -- indicates type of access methods ** rpool -- ignored ** ** Results: ** Success: primitive file descriptor value ** Failure: -1 and sets errno */ /* ARGSUSED3 */ int sm_stdfdopen(fp, info, flags, rpool) SM_FILE_T *fp; const void *info; int flags; const void *rpool; { int oflags, tmp, fdflags, fd = *((int *) info); #ifdef WIN32 struct _stat stat_buf; #endif /* WIN32 */ switch (SM_IO_MODE(flags)) { case SM_IO_RDWR: oflags = O_RDWR | O_CREAT; break; case SM_IO_RDONLY: oflags = O_RDONLY; break; case SM_IO_WRONLY: oflags = O_WRONLY | O_CREAT | O_TRUNC; break; case SM_IO_APPEND: oflags = O_APPEND | O_WRONLY | O_CREAT; break; case SM_IO_APPENDRW: oflags = O_APPEND | O_RDWR | O_CREAT; break; default: errno = EINVAL; return -1; } #ifdef O_BINARY if (SM_IS_BINARY(flags)) oflags |= O_BINARY; #endif /* O_BINARY */ /* Make sure the mode the user wants is a subset of the actual mode. */ #ifdef WIN32 if (_fstat(fd, &stat_buf) != 0) { errno = EINVAL; return -1; } /* Sockets and pipes don't have _S_IWRITE or _S_IREAD flags. */ if ((stat_buf.st_mode & (_S_IFSOCK|_S_IFIFO)) == 0) { if ((oflags & (O_WRONLY|O_RDWR)) != 0 && !(stat_buf.st_mode & _S_IWRITE)) { errno = EACCES; return -1; } if ((oflags & (O_RDONLY|O_RDWR)) != 0 && !(stat_buf.st_mode & _S_IREAD)) { errno = EACCES; return -1; } } #else /* WIN32 */ if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0) return -1; tmp = fdflags & O_ACCMODE; if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return -1; } #endif /* WIN32 */ fp->f_file = fd; if (oflags & O_APPEND) (void) (*fp->f_seek)(fp, (off_t)0, SEEK_END); return fp->f_file; } /* ** SM_IO_FOPEN -- open a file ** ** Same interface and semantics as the open() system call, ** except that it returns SM_FILE_T* instead of a file descriptor. ** ** Parameters: ** pathname -- path of file to open ** flags -- flags controlling the open ** ... -- option "mode" for opening the file ** ** Returns: ** Raises an exception on heap exhaustion. ** Returns NULL and sets errno if open() fails. ** Returns an SM_FILE_T pointer on success. */ SM_FILE_T * #if SM_VA_STD sm_io_fopen(char *pathname, int flags, ...) #else /* SM_VA_STD */ sm_io_fopen(pathname, flags, va_alist) char *pathname; int flags; va_dcl #endif /* SM_VA_STD */ { MODE_T mode; SM_FILE_T *fp; int ioflags; if (flags & O_CREAT) { SM_VA_LOCAL_DECL SM_VA_START(ap, flags); mode = (MODE_T) SM_VA_ARG(ap, int); SM_VA_END(ap); } else mode = 0; switch (flags & O_ACCMODE) { case O_RDONLY: ioflags = SMRD; break; case O_WRONLY: ioflags = SMWR; break; case O_RDWR: ioflags = SMRW; break; default: sm_abort("sm_io_fopen: bad flags 0%o", flags); } fp = sm_fp(SmFtStdio, ioflags, NULL); fp->f_file = open(pathname, flags, mode); if (fp->f_file == -1) { fp->f_flags = 0; fp->sm_magic = NULL; return NULL; } return fp; } dk-milter-1.0.0.dfsg/libsm/heap.html0000644000175000017500000003210607214252626017005 0ustar madhackmadhack libsm : Memory Allocation Back to libsm overview

libsm : Memory Allocation


$Id: heap.html,v 1.9 2000/12/08 21:41:42 ca Exp $

Introduction

The heap package provides a layer of abstraction on top of malloc, realloc and free that provides optional error checking and memory leak detection, and which optionally raises an exception when an allocation request cannot be satisfied.

Synopsis

#include <sm/heap.h>

/*
**  Wrappers for malloc, realloc, free
*/
void *sm_malloc(size_t size);
void *sm_realloc(void *ptr, size_t size);
void  sm_free(void *ptr);

/*
**  Wrappers for malloc, realloc that raise an exception instead of
**  returning NULL on heap exhaustion.
*/
void *sm_malloc_x(size_t size);
void *sm_realloc_x(void *ptr, size_t size);

/*
**  Print a list of currently allocated blocks,
**  used to diagnose memory leaks.
*/
void  sm_heap_report(FILE *stream, int verbosity);

/*
**  Low level interfaces.
*/
int sm_heap_group();
int sm_heap_setgroup(int g);
int sm_heap_newgroup();
void *sm_malloc_tagged(size_t size, char *file, int line, int group);
void *sm_malloc_tagged_x(size_t size, char *file, int line, int group);
bool  sm_heap_register(void *ptr, size_t size, char *file, int line);

How to allocate and free memory

sm_malloc, sm_realloc and sm_free are portable plug in replacements for malloc, realloc and free that provide error checking and memory leak detection. sm_malloc_x and sm_realloc_x are variants of sm_malloc and sm_realloc that raise an exception on error. To use the package effectively, all calls to malloc, realloc and free should be replaced by calls to the corresponding sm_* routines.
void *sm_malloc(size_t size)
This function is a plug-in replacement for malloc. It allocates size bytes of memory on the heap and returns a pointer to it, or it returns NULL on failure.

The C standard says that malloc(0) may return either NULL or a non-NULL value. To ensure consistent behaviour on all platforms, sm_malloc(0) is equivalent to sm_malloc(1).

In addition, if heap checking is enabled, then sm_malloc maintains a hash table describing all currently allocated memory blocks. This table is used for argument validity checking in sm_realloc and sm_free, and it can be printed using sm_heap_report as an aid to finding memory leaks.

void *sm_malloc_x(size_t size)
This function is just like sm_malloc except that it raises the SmHeapOutOfMemory exception instead of returning NULL on error.

void *sm_realloc(void *ptr, size_t size)
This function is a plug-in replacement for realloc. If ptr is null then this call is equivalent to sm_malloc(size). Otherwise, the size of the object pointed to by ptr is changed to size bytes, and a pointer to the (possibly moved) object is returned. If the space cannot be allocated, then the object pointed to by ptr is unchanged and NULL is returned.

If size is 0 then we pretend that size is 1. This may be a mistake.

If ptr is not NULL and heap checking is enabled, then ptr is required to be a value that was previously returned by sm_malloc or sm_realloc, and which has not yet been freed by sm_free. If this condition is not met, then the program is aborted using sm_abort.

void *sm_realloc_x(void *ptr, size_t size)
This function is just like sm_realloc except that it raises the SmHeapOutOfMemory exception instead of returning NULL on error.

void sm_free(void *ptr)
This function is a plug-in replacement for free. If heap checking is disabled, then this function is equivalent to a call to free. Otherwise, the following additional semantics apply.

If ptr is NULL, this function has no effect.

Otherwise, ptr is required to be a value that was previously returned by sm_malloc or sm_realloc, and which has not yet been freed by sm_free. If this condition is not met, then the program is aborted using sm_abort.

Otherwise, if there is no error, then the block pointed to by ptr will be set to all zeros before free() is called. This is intended to assist in detecting the use of dangling pointers.

How to control tag information

When heap checking is enabled, the heap package maintains a hash table which associates the following values with each currently allocated block:
size_t size
The size of the block.
char *tag
By default, this is the name of the source file from which the block was allocated, but you can specify an arbitrary string pointer, or NULL.
int num
By default, this is the line number from which the block was allocated.
int group
By convention, group==0 indicates that the block is permanently allocated and will never be freed. The meanings of other group numbers are defined by the application developer. Unless you take special action, all blocks allocated by sm_malloc and sm_malloc_x will be assigned to group 1.
These tag values are printed by sm_heap_report, and are used to help analyze memory allocation behaviour and to find memory leaks. The following functions give you precise control over the tag values associated with each allocated block.
void *sm_malloc_tagged(size_t size, int tag, int num, int group)
Just like sm_malloc, except you directly specify all of the tag values. If heap checking is disabled at compile time, then a call to sm_malloc_tagged is macro expanded to a call to malloc.

Note that the expression sm_malloc(size) is macro expanded to

sm_malloc_tagged(size, __FILE__, __LINE__, sm_heap_group())
void *sm_malloc_tagged_x(size_t size, int tag, int num, int group)
A variant of sm_malloc_tagged that raises an exception on error. A call to sm_malloc_x is macro expanded to a call to sm_malloc_tagged_x.

int sm_heap_group()
The heap package maintains a thread-local variable containing the current group number. This is the group that sm_malloc and sm_malloc_x will assign a newly allocated block to. The initial value of this variable is 1. The current value of this variable is returned by sm_heap_group().

int sm_heap_setgroup(int g)
Set the current group to the specified value.
Here are two examples of how you might use these interfaces.
  1. One way to detect memory leaks is to turn on heap checking and call sm_heap_report(stdout,2) when the program exits. This prints a list of all allocated blocks that do not belong to group 0. (Blocks in group 0 are assumed to be permanently allocated, and so their existence at program exit does not indicate a leak.) If you want to allocate a block and assign it to group 0, you have two choices:
    int g = sm_heap_group();
    sm_heap_setgroup(0);
    p = sm_malloc_x(size);
    sm_heap_setgroup(g);
    
    or
    p = sm_malloc_tagged_x(size, __FILE__, __LINE__, 0);
    
  2. Suppose you have a utility function foo_alloc which allocates and initializes a 'foo' object. When sm_heap_report is called, all unfreed 'foo' objects will be reported to have the same source code file name and line number. That might make it difficult to determine where a memory leak is.

    Here is how you can arrange for more precise reporting for unfreed foo objects:

    #include <sm/heap.h>
    
    #if SM_HEAP_CHECK
    #  define foo_alloc_x() foo_alloc_tagged_x(__FILE__,__LINE)
       FOO *foo_alloc_tagged_x(char *, int);
    #else
       FOO *foo_alloc_x(void);
    #  define foo_alloc_tagged_x(file,line) foo_alloc_x()
    #endif
    
    ...
    
    #if SM_HEAP_CHECK
    FOO *
    foo_alloc_tagged_x(char *file, int line)
    #else
    FOO *
    foo_alloc_x(void)
    #endif
    {
    	FOO *p;
    
    	p = sm_malloc_tagged_x(sizeof(FOO), file, line, sm_heap_group());
    	...
    	return p;
    }
    

How to dump the block list

To perform memory leak detection, you need to arrange for your program to call sm_heap_report at appropriate times.
void sm_heap_report(FILE *stream, int verbosity)
If heap checking is disabled, this function does nothing. If verbosity <= 0, this function does nothing.

If verbosity >= 1, then sm_heap_report prints a single line to stream giving the total number of bytes currently allocated. If you call sm_heap_report each time the program has reached a "ground state", and the reported amount of heap storage is monotonically increasing, that indicates a leak.

If verbosity >= 2, then sm_heap_report additionally prints one line for each block of memory currently allocated, providing that the group != 0. (Such blocks are assumed to be permanently allocated storage, and are not reported to cut down the level of noise.)

If verbosity >= 3, then sm_heap_report prints one line for each allocated block, regardless of the group.

How to enable heap checking

The overhead of using the package can be made as small as you want. You have three options:
  1. If you compile your software with -DSM_HEAP_CHECK=0 then sm_malloc, sm_realloc and sm_free will be redefined as macros that call malloc, realloc, and free. In this case, there is zero overhead.
  2. If you do not define -DSM_HEAP_CHECK=0, and you do not explicitly turn on heap checking at run time, then your program will run without error checking and memory leak detection, and the additional cost of calling sm_malloc, sm_realloc and sm_free is a function call and test. That overhead is sufficiently low that the checking code can be left compiled in a production environment.
  3. If you do not define -DSM_HEAP_CHECK=0, and you explicitly turn on heap checking at run time, then the additional cost of calling sm_malloc, sm_realloc and sm_free is a hash table lookup.
Here's how to modify your application to use the heap package. First, change all calls to malloc, realloc and free to sm_malloc, sm_realloc and sm_free. Make sure that there is a -d command line option that uses the libsm debug package to enable named debug options. Add the following code to your program just before it calls exit, or register an atexit handler function containing the following code:
#if SM_HEAP_CHECK
	/* dump the heap, if we are checking for memory leaks */
	if (sm_debug_active(&SmHeapCheck, 2))
		sm_heap_report(stdout, sm_debug_level(&SmHeapCheck) - 1);
#endif
To turn on heap checking, use the command line option "-dsm_check_heap.1". This will cause a table of all currently allocated blocks to be maintained. The table is used by sm_realloc and sm_free to perform validity checking on the first argument.

The command line option "-dsm_check_heap.2" will cause your application to invoke sm_heap_report with verbosity=1 just before exit. That will print a single line reporting total storage allocation.

The command line option "-dsm_check_heap.3" will cause your application to invoke sm_heap_report with verbosity=2 just before exit. This will print a list of all leaked blocks.

The command line option "-dsm_check_heap.4" will cause your application to invoke sm_heap_report with verbosity=3 just before exit. This will print a list of all allocated blocks.

Using sm_heap_register

Suppose you call a library routine foo that allocates a block of storage for you using malloc, and expects you to free the block later using free. Because the storage was not allocated using sm_malloc, you will normally get an abort if you try to pass the pointer to sm_free. The way to fix this problem is to 'register' the pointer returned by foo with the heap package, by calling sm_heap_register:
bool sm_heap_register(ptr, size, file, line, group)
The 'ptr' argument is the pointer returned by foo. The 'size' argument can be smaller than the actual size of the allocated block, but it must not be larger. The file and line arguments indicate at which line of source code the block was allocated, and is printed by sm_heap_report. For group, you probably want to pass sm_heap_group().

This function returns true on success, or false if it failed due to heap exhaustion. dk-milter-1.0.0.dfsg/libsm/fpurge.c0000644000175000017500000000223407347306540016637 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fpurge.c,v 1.20 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include #include "local.h" /* ** SM_IO_PURGE -- purge/empty the buffer without committing buffer content ** ** Parameters: ** fp -- file pointer to purge ** ** Returns: ** Failure: returns SM_IO_EOF and sets errno ** Success: returns 0 (zero) */ int sm_io_purge(fp) register SM_FILE_T *fp; { SM_REQUIRE_ISA(fp, SmFileMagic); if (!fp->f_flags) { errno = EBADF; return SM_IO_EOF; } if (HASUB(fp)) FREEUB(fp); fp->f_p = fp->f_bf.smb_base; fp->f_r = 0; /* implies SMFBF */ fp->f_w = fp->f_flags & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; return 0; } dk-milter-1.0.0.dfsg/libsm/fvwrite.h0000644000175000017500000000134207247563313017043 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: fvwrite.h,v 1.7 2001/03/02 00:18:19 ca Exp $ */ /* I/O descriptors for sm_fvwrite() */ struct sm_iov { void *iov_base; size_t iov_len; }; struct sm_uio { struct sm_iov *uio_iov; int uio_iovcnt; int uio_resid; }; extern int sm_fvwrite __P((SM_FILE_T *, int, struct sm_uio *)); dk-milter-1.0.0.dfsg/libsm/fwalk.c0000644000175000017500000000265107347306540016456 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fwalk.c,v 1.21 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include "local.h" #include "glue.h" /* ** SM_FWALK -- apply a function to all found-open file pointers ** ** Parameters: ** function -- a function vector to be applied ** timeout -- time to complete actions (milliseconds) ** ** Returns: ** The (binary) OR'd result of each function call */ int sm_fwalk(function, timeout) int (*function) __P((SM_FILE_T *, int *)); int *timeout; { register SM_FILE_T *fp; register int n, ret; register struct sm_glue *g; int fptimeout; ret = 0; for (g = &smglue; g != NULL; g = g->gl_next) { for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++) { if (fp->f_flags != 0) { if (*timeout == SM_TIME_DEFAULT) fptimeout = fp->f_timeout; else fptimeout = *timeout; if (fptimeout == SM_TIME_IMMEDIATE) continue; /* skip it */ ret |= (*function)(fp, &fptimeout); } } } return ret; } dk-milter-1.0.0.dfsg/libsm/t-strl.c0000644000175000017500000000704207347306541016577 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_IDSTR(id, "@(#)$Id: t-strl.c,v 1.15 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include #define MAXL 16 #define N 5 #define SIZE 128 int main(argc, argv) int argc; char *argv[]; { char *s1, *s2, *s3; int one, two, k; char src1[N][SIZE], dst1[SIZE], dst2[SIZE]; char *r; sm_test_begin(argc, argv, "test strl* string functions"); s1 = "abc"; s2 = "123"; s3 = sm_malloc_x(MAXL); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); SM_TEST(strcmp(s1, s3) == 0); SM_TEST(sm_strlcat(s3, s2, 8) == 6); r ="abc123"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 2) == 3); r = "a"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcat(s3, s2, 3) == 4); r = "a1"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); r = ":"; SM_TEST(sm_strlcat2(s3, r, s2, MAXL) == 7); r = "abc:123"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); r = ":"; SM_TEST(sm_strlcat2(s3, r, s2, 6) == 7); r = "abc:1"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); r = ":"; SM_TEST(sm_strlcat2(s3, r, s2, 2) == 7); r = "abc"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); r = ":"; SM_TEST(sm_strlcat2(s3, r, s2, 4) == 7); r = "abc"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); r = ":"; SM_TEST(sm_strlcat2(s3, r, s2, 5) == 7); r = "abc:"; SM_TEST(strcmp(s3, r) == 0); SM_TEST(sm_strlcpy(s3, s1, 4) == 3); r = ":"; SM_TEST(sm_strlcat2(s3, r, s2, 6) == 7); r = "abc:1"; SM_TEST(strcmp(s3, r) == 0); for (k = 0; k < N; k++) { (void) sm_strlcpy(src1[k], "abcdef", sizeof src1); } one = sm_strlcpyn(dst1, sizeof dst1, 3, src1[0], "/", src1[1]); two = sm_snprintf(dst2, sizeof dst2, "%s/%s", src1[0], src1[1]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, 10, 3, src1[0], "/", src1[1]); two = sm_snprintf(dst2, 10, "%s/%s", src1[0], src1[1]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, 5, 3, src1[0], "/", src1[1]); two = sm_snprintf(dst2, 5, "%s/%s", src1[0], src1[1]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, 0, 3, src1[0], "/", src1[1]); two = sm_snprintf(dst2, 0, "%s/%s", src1[0], src1[1]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, sizeof dst1, 5, src1[0], "/", src1[1], "/", src1[2]); two = sm_snprintf(dst2, sizeof dst2, "%s/%s/%s", src1[0], src1[1], src1[2]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, 15, 5, src1[0], "/", src1[1], "/", src1[2]); two = sm_snprintf(dst2, 15, "%s/%s/%s", src1[0], src1[1], src1[2]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, 20, 5, src1[0], "/", src1[1], "/", src1[2]); two = sm_snprintf(dst2, 20, "%s/%s/%s", src1[0], src1[1], src1[2]); SM_TEST(one == two); SM_TEST(strcmp(dst1, dst2) == 0); one = sm_strlcpyn(dst1, sizeof dst1, 0); SM_TEST(one == 0); r = ""; SM_TEST(strcmp(dst1, r) == 0); one = sm_strlcpyn(dst1, 20, 1, src1[0]); two = sm_snprintf(dst2, 20, "%s", src1[0]); SM_TEST(one == two); one = sm_strlcpyn(dst1, 2, 1, src1[0]); two = sm_snprintf(dst2, 2, "%s", src1[0]); SM_TEST(one == two); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/glue.h0000644000175000017500000000133107233136675016311 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: glue.h,v 1.6 2001/01/22 23:09:49 ca Exp $ */ /* ** The first few FILEs are statically allocated; others are dynamically ** allocated and linked in via this glue structure. */ extern struct sm_glue { struct sm_glue *gl_next; int gl_niobs; SM_FILE_T *gl_iobs; } smglue; dk-milter-1.0.0.dfsg/libsm/fwrite.c0000644000175000017500000000306107347306540016646 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fwrite.c,v 1.24 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include "local.h" #include "fvwrite.h" /* ** SM_IO_WRITE -- write to a file pointer ** ** Parameters: ** fp -- file pointer writing to ** timeout -- time to complete the write ** buf -- location of data to be written ** size -- number of bytes to be written ** ** Result: ** Failure: returns 0 _and_ sets errno ** Success: returns >=0 with errno unchanged, where the ** number returned is the number of bytes written. */ size_t sm_io_write(fp, timeout, buf, size) SM_FILE_T *fp; int timeout; const void *buf; size_t size; { struct sm_uio uio; struct sm_iov iov; SM_REQUIRE_ISA(fp, SmFileMagic); if (fp->f_write == NULL) { errno = ENODEV; return 0; } iov.iov_base = (void *) buf; uio.uio_resid = iov.iov_len = size; uio.uio_iov = &iov; uio.uio_iovcnt = 1; /* The usual case is success (sm_fvwrite returns 0) */ if (sm_fvwrite(fp, timeout, &uio) == 0) return size; /* else return number of bytes actually written */ return size - uio.uio_resid; } dk-milter-1.0.0.dfsg/libsm/ferror.c0000644000175000017500000000165007347306540016647 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: ferror.c,v 1.13 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include "local.h" /* ** SM_IO_ERROR -- subroutine version of the macro sm_io_error. ** ** Parameters: ** fp -- file pointer ** ** Returns: ** 0 (zero) when 'fp' is not in an error state ** non-zero when 'fp' is in an error state */ #undef sm_io_error int sm_io_error(fp) SM_FILE_T *fp; { SM_REQUIRE_ISA(fp, SmFileMagic); return sm_error(fp); } dk-milter-1.0.0.dfsg/libsm/rpool.html0000644000175000017500000001412607213744725017232 0ustar madhackmadhack libsm : Resource Pools Back to libsm overview

libsm : Resource Pools


$Id: rpool.html,v 1.4 2000/12/07 17:33:09 dmoen Exp $

Introduction

A resource pool is an object that owns a collection of objects that can be freed all at once.

Resource pools simplify storage management.

Resource pools also speed up memory management. For example, here are some memory allocation statistics from a run of `sendmail -q` that delivered 3 messages:

     18	1	     82	12	     87	24	      7	42	      2	84
   3046	2	     18	13	      6	25	     89	44	      2	88
    728	3	     15	14	      2	26	     14	48	      1	91
     31	4	      9	15	      3	27	    104	52	      3	92
    103	5	    394	16	     80	28	      8	56	      2	96
    125	6	     16	17	      1	31	      2	60	      1	100
     45	7	     14	18	     59	32	     10	64	      9	108
    130	8	      6	19	      1	33	      6	68	      3	135
     40	9	    111	20	      7	34	      1	72	     10	140
     37	10	      7	21	     54	36	     10	76
     34	11	      4	22	     38	40	      5	80
The second number in each pair is the size of a memory block; the first number is the number of blocks of that size. We can see that sendmail allocates large numbers of 2 byte blocks. These memory blocks can be allocated and freed more quickly using resource pools, because:
  • When you allocate a small block from a resource pool, the rpool implementation carves off a chunk of a large preallocated block, and hands you a pointer to it.
  • When you free a resource pool, only a small number of large blocks need to be freed.

Synopsis

#include <sm/rpool.h>

typedef void (*SM_RPOOL_RFREE_T)(void *rcontext);
typedef struct sm_rpool SM_RPOOL_T;
typedef ... SM_RPOOL_ATTACH_T;

SM_RPOOL_T *
sm_rpool_new_x(
	SM_RPOOL_T *parent);

void
sm_rpool_free(
	SM_RPOOL_T *rpool);

void *
sm_rpool_malloc_x(
	SM_RPOOL_T *rpool,
	size_t size);

SM_RPOOL_ATTACH_T
sm_rpool_attach_x(
	SM_RPOOL_T *rpool,
	SM_RPOOL_RFREE_T rfree,
	void *rcontext);

void
sm_rpool_detach(
	SM_RPOOL_ATTACH_T);

void
sm_rpool_setsizes(
	SM_RPOOL_T *rpool,
	size_t poolsize,
	size_t bigobjectsize);

Description

SM_RPOOL_T *sm_rpool_new_x(SM_RPOOL_T *parent)
Create a new resource pool object. Raise an exception if there is insufficient heap space. Initially, no memory is allocated for memory pools or resource lists.

If parent != NULL then the new rpool will be added as a resource to the specified parent rpool, so that when the parent is freed, the child is also freed. However, even if a parent is specified, you can free the rpool at any time, and it will be automatically disconnected from the parent.

void *sm_rpool_malloc_x(SM_RPOOL_T *rpool, size_t size)
Allocate a block of memory from a memory pool owned by the rpool. Raise an exception if there is insufficient heap space. A series of small allocation requests can be satisfied allocating them from the same memory pool, which reduces the number of calls to malloc. All of the memory allocated by sm_rpool_malloc_x is freed when the rpool is freed, and not before then.

void sm_rpool_setsizes(SM_RPOOL_T *rpool, size_t poolsize, size_t bigobjectsize)
Set memory pool parameters. You can safely call this function at any time, but an especially good time to call it is immediately after creating the rpool, before any pooled objects have been allocated using sm_rpool_malloc_x.

poolsize is the number of bytes of pool memory that will be available in the next pool object to be allocated. If you happen to know the total number of bytes of memory that you will allocate from an rpool using sm_rpool_malloc_x (including alignment padding), then you can pass that value as the poolsize, and only a single pool will be allocated during the lifetime of the rpool. poolsize is an optimization, not a hard limit: if you allocate more than this number of bytes from the rpool, then more than one memory pool may be allocated by the rpool to satisfy your requests.

bigobjectsize is a value <= poolsize. It is used when an sm_rpool_malloc_x request exceeds the number of bytes available in the current pool. If the request is > bigobjectsize then the request will be satisfied by allocating a new block just for this specific request, and the current pool is not affected. If the request is <= bigobjectsize then the current pool is closed and a new memory pool is allocated, from which the request is satisfied. Consequently, no more than bigobjectsize-1 bytes will ever be wasted at the end of a given pool.

If poolsize or bigobjectsize are 0, then suitable default values are chosen.

SM_RPOOL_ATTACH_T sm_rpool_attach_x(SM_RPOOL_T *rpool, SM_RPOOL_RFREE_T rfree, void *rcontext)
Attach an object to a resource pool, along with its free function. When the rpool is freed, the specified object will also be freed. Raise an exception if there is insufficient heap space.

The return value is a magic cookie which, if passed to sm_rpool_detach, disconnects the object from the resource pool, which prevents the object's free function from being called when the rpool is freed.

void sm_rpool_detach(SM_RPOOL_ATTACH_T a)
The argument is a magic cookie returned by sm_rpool_attach_t, and refers to the object that was attached to an rpool by a specific call to sm_rpool_attach_t. Disconnect the object from the resource pool, which prevents the object's free function from being called when the rpool is freed.

void sm_rpool_free(SM_RPOOL_T *rpool)
Free an rpool object. All memory allocated using sm_rpool_malloc_x and all objects attached using sm_rpool_attach_x are freed at this time. If the rpool has a parent rpool, it is detached from its parent.
dk-milter-1.0.0.dfsg/libsm/signal.c0000644000175000017500000001633110253661450016621 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: signal.c,v 1.17 2005/06/14 23:07:20 ca Exp $") #if SM_CONF_SETITIMER # include #endif /* SM_CONF_SETITIMER */ #include #include #include #include #include #include #include #include unsigned int volatile InCriticalSection; /* >0 if inside critical section */ int volatile PendingSignal; /* pending signal to resend */ /* ** SM_SIGNAL -- set a signal handler ** ** This is essentially old BSD "signal(3)". ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ sigfunc_t sm_signal(sig, handler) int sig; sigfunc_t handler; { #ifdef WIN32 return handler; #else /* WIN32 */ # if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) struct sigaction n, o; # endif /* defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) */ /* ** First, try for modern signal calls ** and restartable syscalls */ # ifdef SA_RESTART (void) memset(&n, '\0', sizeof n); # if USE_SA_SIGACTION n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler; n.sa_flags = SA_RESTART|SA_SIGINFO; # else /* USE_SA_SIGACTION */ n.sa_handler = handler; n.sa_flags = SA_RESTART; # endif /* USE_SA_SIGACTION */ if (sigaction(sig, &n, &o) < 0) return SIG_ERR; return o.sa_handler; # else /* SA_RESTART */ /* ** Else check for SYS5SIGNALS or ** BSD4_3 signals */ # if defined(SYS5SIGNALS) || defined(BSD4_3) # ifdef BSD4_3 return signal(sig, handler); # else /* BSD4_3 */ return sigset(sig, handler); # endif /* BSD4_3 */ # else /* defined(SYS5SIGNALS) || defined(BSD4_3) */ /* ** Finally, if nothing else is available, ** go for a default */ (void) memset(&n, '\0', sizeof n); n.sa_handler = handler; if (sigaction(sig, &n, &o) < 0) return SIG_ERR; return o.sa_handler; # endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */ # endif /* SA_RESTART */ #endif /* WIN32 */ } /* ** SM_BLOCKSIGNAL -- hold a signal to prevent delivery ** ** Parameters: ** sig -- the signal to block. ** ** Returns: ** 1 signal was previously blocked ** 0 signal was not previously blocked ** -1 on failure. */ int sm_blocksignal(sig) int sig; { #ifdef WIN32 return 0; #else /* WIN32 */ # ifdef BSD4_3 # ifndef sigmask # define sigmask(s) (1 << ((s) - 1)) # endif /* ! sigmask */ return (sigblock(sigmask(sig)) & sigmask(sig)) != 0; # else /* BSD4_3 */ # ifdef ALTOS_SYSTEM_V sigfunc_t handler; handler = sigset(sig, SIG_HOLD); if (handler == SIG_ERR) return -1; else return handler == SIG_HOLD; # else /* ALTOS_SYSTEM_V */ sigset_t sset, oset; (void) sigemptyset(&sset); (void) sigaddset(&sset, sig); if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0) return -1; else return sigismember(&oset, sig); # endif /* ALTOS_SYSTEM_V */ # endif /* BSD4_3 */ #endif /* WIN32 */ } /* ** SM_RELEASESIGNAL -- release a held signal ** ** Parameters: ** sig -- the signal to release. ** ** Returns: ** 1 signal was previously blocked ** 0 signal was not previously blocked ** -1 on failure. */ int sm_releasesignal(sig) int sig; { #ifdef WIN32 return 0; #else /* WIN32 */ # ifdef BSD4_3 return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0; # else /* BSD4_3 */ # ifdef ALTOS_SYSTEM_V sigfunc_t handler; handler = sigset(sig, SIG_HOLD); if (sigrelse(sig) < 0) return -1; else return handler == SIG_HOLD; # else /* ALTOS_SYSTEM_V */ sigset_t sset, oset; (void) sigemptyset(&sset); (void) sigaddset(&sset, sig); if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0) return -1; else return sigismember(&oset, sig); # endif /* ALTOS_SYSTEM_V */ # endif /* BSD4_3 */ #endif /* WIN32 */ } /* ** PEND_SIGNAL -- Add a signal to the pending signal list ** ** Parameters: ** sig -- signal to add ** ** Returns: ** none. ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ void pend_signal(sig) int sig; { int sigbit; int save_errno = errno; #if SM_CONF_SETITIMER struct itimerval clr; #endif /* SM_CONF_SETITIMER */ /* ** Don't want to interrupt something critical, hence delay ** the alarm for one second. Hopefully, by then we ** will be out of the critical section. If not, then ** we will just delay again. The events to be run will ** still all be run, maybe just a little bit late. */ switch (sig) { case SIGHUP: sigbit = PEND_SIGHUP; break; case SIGINT: sigbit = PEND_SIGINT; break; case SIGTERM: sigbit = PEND_SIGTERM; break; case SIGUSR1: sigbit = PEND_SIGUSR1; break; case SIGALRM: /* don't have to pend these */ sigbit = 0; break; default: /* If we get here, we are in trouble */ abort(); /* NOTREACHED */ /* shut up stupid compiler warning on HP-UX 11 */ sigbit = 0; break; } if (sigbit != 0) PendingSignal |= sigbit; (void) sm_signal(SIGALRM, sm_tick); #if SM_CONF_SETITIMER clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; clr.it_value.tv_sec = 1; clr.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &clr, NULL); #else /* SM_CONF_SETITIMER */ (void) alarm(1); #endif /* SM_CONF_SETITIMER */ errno = save_errno; } /* ** SM_ALLSIGNALS -- act on all signals ** ** Parameters: ** block -- whether to block or release all signals. ** ** Returns: ** none. */ void sm_allsignals(block) bool block; { #ifdef WIN32 return; #else /* WIN32 */ # ifdef BSD4_3 # ifndef sigmask # define sigmask(s) (1 << ((s) - 1)) # endif /* ! sigmask */ if (block) { int mask = 0; mask |= sigmask(SIGALRM); mask |= sigmask(SIGCHLD); mask |= sigmask(SIGHUP); mask |= sigmask(SIGINT); mask |= sigmask(SIGTERM); mask |= sigmask(SIGUSR1); (void) sigblock(mask); } else sigsetmask(0); # else /* BSD4_3 */ # ifdef ALTOS_SYSTEM_V if (block) { (void) sigset(SIGALRM, SIG_HOLD); (void) sigset(SIGCHLD, SIG_HOLD); (void) sigset(SIGHUP, SIG_HOLD); (void) sigset(SIGINT, SIG_HOLD); (void) sigset(SIGTERM, SIG_HOLD); (void) sigset(SIGUSR1, SIG_HOLD); } else { (void) sigset(SIGALRM, SIG_DFL); (void) sigset(SIGCHLD, SIG_DFL); (void) sigset(SIGHUP, SIG_DFL); (void) sigset(SIGINT, SIG_DFL); (void) sigset(SIGTERM, SIG_DFL); (void) sigset(SIGUSR1, SIG_DFL); } # else /* ALTOS_SYSTEM_V */ sigset_t sset; (void) sigemptyset(&sset); (void) sigaddset(&sset, SIGALRM); (void) sigaddset(&sset, SIGCHLD); (void) sigaddset(&sset, SIGHUP); (void) sigaddset(&sset, SIGINT); (void) sigaddset(&sset, SIGTERM); (void) sigaddset(&sset, SIGUSR1); (void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL); # endif /* ALTOS_SYSTEM_V */ # endif /* BSD4_3 */ #endif /* WIN32 */ } /* ** SM_SIGNAL_NOOP -- A signal no-op function ** ** Parameters: ** sig -- signal received ** ** Returns: ** SIGFUNC_RETURN */ /* ARGSUSED */ SIGFUNC_DECL sm_signal_noop(sig) int sig; { int save_errno = errno; FIX_SYSV_SIGNAL(sig, sm_signal_noop); errno = save_errno; return SIGFUNC_RETURN; } dk-milter-1.0.0.dfsg/libsm/fflush.c0000644000175000017500000000621010402141074016615 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2005, 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fflush.c,v 1.45 2006/03/03 22:25:00 ca Exp $") #include #include #include #include #include #include #include #include #include #include "local.h" #include /* ** SM_IO_FLUSH -- flush the buffer for a 'fp' to the "file" ** ** Flush a single file. We don't allow this function to flush ** all open files when fp==NULL any longer. ** ** Parameters: ** fp -- the file pointer buffer to flush ** timeout -- time to complete the flush ** ** Results: ** Failure: SM_IO_EOF and sets errno ** Success: 0 (zero) */ int sm_io_flush(fp, timeout) register SM_FILE_T *fp; int SM_NONVOLATILE timeout; { #ifndef WIN32 int fd; struct timeval to; #endif /* !WIN32 */ SM_REQUIRE_ISA(fp, SmFileMagic); if ((fp->f_flags & (SMWR | SMRW)) == 0) { /* ** The file is not opened for writing, so it cannot be flushed ** (writable means SMWR [write] or SMRW [read/write]. */ errno = EBADF; return SM_IO_EOF; } SM_CONVERT_TIME(fp, fd, timeout, &to); /* Now do the flush */ return sm_flush(fp, (int *) &timeout); } /* ** SM_FLUSH -- perform the actual flush ** ** Assumes that 'fp' has been validated before this function called. ** ** Parameters: ** fp -- file pointer to be flushed ** timeout -- max time allowed for flush (milliseconds) ** ** Results: ** Success: 0 (zero) ** Failure: SM_IO_EOF and errno set ** ** Side Effects: ** timeout will get updated with the time remaining (if any) */ int sm_flush(fp, timeout) register SM_FILE_T *fp; int *timeout; { register unsigned char *p; register int n, t; int fd; SM_REQUIRE_ISA(fp, SmFileMagic); t = fp->f_flags; if ((t & SMWR) == 0) return 0; if (t & SMSTR) { *fp->f_p = '\0'; return 0; } if ((p = fp->f_bf.smb_base) == NULL) return 0; n = fp->f_p - p; /* write this much */ if ((fd = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) { /* can't get an fd, likely internal 'fake' fp */ errno = 0; fd = -1; } /* ** Set these immediately to avoid problems with longjmp and to allow ** exchange buffering (via setvbuf) in user write function. */ fp->f_p = p; fp->f_w = t & (SMLBF|SMNBF) ? 0 : fp->f_bf.smb_size; /* implies SMFBF */ for (; n > 0; n -= t, p += t) { errno = 0; /* needed to ensure EOF correctly found */ /* Call the file type's write function */ t = (*fp->f_write)(fp, (char *)p, n); if (t <= 0) { if (t == 0 && errno == 0) break; /* EOF found */ if (IS_IO_ERROR(fd, t, *timeout)) { fp->f_flags |= SMERR; /* errno set by fp->f_write */ return SM_IO_EOF; } SM_IO_WR_TIMEOUT(fp, fd, *timeout); t = 0; } } return 0; } dk-milter-1.0.0.dfsg/libsm/vprintf.c0000644000175000017500000000175307347306541017045 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: vprintf.c,v 1.14 2001/09/11 04:04:49 gshapiro Exp $") #include #include "local.h" /* ** SM_VPRINTF -- print to standard out with variable length args ** ** Parameters: ** timeout -- length of time allow to do the print ** fmt -- the format of the output ** ap -- the variable number of args to be used for output ** ** Returns: ** as sm_io_vfprintf() does. */ int sm_vprintf(timeout, fmt, ap) int timeout; char const *fmt; SM_VA_LOCAL_DECL { return sm_io_vfprintf(smiostdout, timeout, fmt, ap); } dk-milter-1.0.0.dfsg/libsm/clock.c0000644000175000017500000003620310253661450016437 0ustar madhackmadhack/* * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: clock.c,v 1.47 2005/06/14 23:07:20 ca Exp $") #include #include #include #if SM_CONF_SETITIMER # include #endif /* SM_CONF_SETITIMER */ #include #include #include #include #include "local.h" #if _FFR_SLEEP_USE_SELECT > 0 # include #endif /* _FFR_SLEEP_USE_SELECT > 0 */ #if defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 # include #endif /* defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 */ #ifndef sigmask # define sigmask(s) (1 << ((s) - 1)) #endif /* ! sigmask */ #ifdef WIN32 static void (*alarm_handler)(int); #endif /* WIN32 */ /* ** SM_SETEVENTM -- set an event to happen at a specific time in milliseconds. ** ** Events are stored in a sorted list for fast processing. ** An event only applies to the process that set it. ** Source is #ifdef'd to work with older OS's that don't have setitimer() ** (that is, don't have a timer granularity less than 1 second). ** ** Parameters: ** intvl -- interval until next event occurs (milliseconds). ** func -- function to call on event. ** arg -- argument to func on event. ** ** Returns: ** On success returns the SM_EVENT entry created. ** On failure returns NULL. ** ** Side Effects: ** none. */ static SM_EVENT *volatile SmEventQueue; /* head of event queue */ static SM_EVENT *volatile SmFreeEventList; /* list of free events */ SM_EVENT * sm_seteventm(intvl, func, arg) int intvl; void (*func)__P((int)); int arg; { ENTER_CRITICAL(); if (SmFreeEventList == NULL) { SmFreeEventList = (SM_EVENT *) sm_pmalloc_x(sizeof *SmFreeEventList); SmFreeEventList->ev_link = NULL; } LEAVE_CRITICAL(); return sm_sigsafe_seteventm(intvl, func, arg); } /* ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ SM_EVENT * sm_sigsafe_seteventm(intvl, func, arg) int intvl; void (*func)__P((int)); int arg; { register SM_EVENT **evp; register SM_EVENT *ev; #if SM_CONF_SETITIMER auto struct timeval now, nowi, ival; auto struct itimerval itime; #else /* SM_CONF_SETITIMER */ auto time_t now, nowi; #endif /* SM_CONF_SETITIMER */ #ifndef WIN32 int wasblocked; #endif /* ! WIN32 */ /* negative times are not allowed */ if (intvl <= 0) return NULL; #ifndef WIN32 wasblocked = sm_blocksignal(SIGALRM); #else /* ! WIN32 */ alarm_handler = NULL; #endif /* ! WIN32 */ #if SM_CONF_SETITIMER ival.tv_sec = intvl / 1000; ival.tv_usec = (intvl - ival.tv_sec * 1000) * 10; (void) gettimeofday(&now, NULL); nowi = now; timeradd(&now, &ival, &nowi); #else /* SM_CONF_SETITIMER */ now = time(NULL); nowi = now + (time_t)(intvl / 1000); #endif /* SM_CONF_SETITIMER */ /* search event queue for correct position */ for (evp = (SM_EVENT **) (&SmEventQueue); (ev = *evp) != NULL; evp = &ev->ev_link) { #if SM_CONF_SETITIMER if (timercmp(&(ev->ev_time), &nowi, >=)) #else /* SM_CONF_SETITIMER */ if (ev->ev_time >= nowi) #endif /* SM_CONF_SETITIMER */ break; } ENTER_CRITICAL(); if (SmFreeEventList == NULL) { /* ** This shouldn't happen. If called from sm_seteventm(), ** we have just malloced a SmFreeEventList entry. If ** called from a signal handler, it should have been ** from an existing event which sm_tick() just added to ** SmFreeEventList. */ LEAVE_CRITICAL(); #ifndef WIN32 if (wasblocked == 0) (void) sm_releasesignal(SIGALRM); #endif /* ! WIN32 */ return NULL; } else { ev = SmFreeEventList; SmFreeEventList = ev->ev_link; } LEAVE_CRITICAL(); /* insert new event */ ev->ev_time = nowi; #ifdef WIN32 ev->ev_func = (void (__cdecl *)(int))func; /* even at W1 !!! */ #else /* WIN32 */ ev->ev_func = func; #endif /* WIN32 */ ev->ev_arg = arg; ev->ev_pid = getpid(); ENTER_CRITICAL(); ev->ev_link = *evp; *evp = ev; LEAVE_CRITICAL(); #ifndef WIN32 (void) sm_signal(SIGALRM, sm_tick); # if SM_CONF_SETITIMER timersub(&SmEventQueue->ev_time, &now, &itime.it_value); itime.it_interval.tv_sec = 0; itime.it_interval.tv_usec = 0; if (itime.it_value.tv_sec < 0) itime.it_value.tv_sec = 0; if (itime.it_value.tv_sec == 0 && itime.it_value.tv_usec == 0) itime.it_value.tv_usec = 1000; (void) setitimer(ITIMER_REAL, &itime, NULL); # else /* SM_CONF_SETITIMER */ intvl = SmEventQueue->ev_time - now; (void) alarm((unsigned) (intvl < 1 ? 1 : intvl)); # endif /* SM_CONF_SETITIMER */ if (wasblocked == 0) (void) sm_releasesignal(SIGALRM); #endif /* ! WIN32 */ return ev; } /* ** SM_CLREVENT -- remove an event from the event queue. ** ** Parameters: ** ev -- pointer to event to remove. ** ** Returns: ** none. ** ** Side Effects: ** arranges for event ev to not happen. */ void sm_clrevent(ev) register SM_EVENT *ev; { register SM_EVENT **evp; #ifndef WIN32 int wasblocked; # if SM_CONF_SETITIMER struct itimerval clr; # endif /* SM_CONF_SETITIMER */ #endif /* ! WIN32 */ if (ev == NULL) return; /* find the parent event */ #ifndef WIN32 wasblocked = sm_blocksignal(SIGALRM); #else /* ! WIN32 */ alarm_handler = NULL; #endif /* ! WIN32 */ for (evp = (SM_EVENT **) (&SmEventQueue); *evp != NULL; evp = &(*evp)->ev_link) { if (*evp == ev) break; } /* now remove it */ if (*evp != NULL) { ENTER_CRITICAL(); *evp = ev->ev_link; ev->ev_link = SmFreeEventList; SmFreeEventList = ev; LEAVE_CRITICAL(); } /* restore clocks and pick up anything spare */ #ifndef WIN32 if (wasblocked == 0) (void) sm_releasesignal(SIGALRM); if (SmEventQueue != NULL) (void) kill(getpid(), SIGALRM); else { /* nothing left in event queue, no need for an alarm */ # if SM_CONF_SETITIMER clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; clr.it_value.tv_sec = 0; clr.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &clr, NULL); # else /* SM_CONF_SETITIMER */ (void) alarm(0); # endif /* SM_CONF_SETITIMER */ } #endif /* ! WIN32 */ } /* ** SM_CLEAR_EVENTS -- remove all events from the event queue. ** ** Parameters: ** none. ** ** Returns: ** none. */ void sm_clear_events() { register SM_EVENT *ev; #if SM_CONF_SETITIMER struct itimerval clr; #endif /* SM_CONF_SETITIMER */ #ifndef WIN32 int wasblocked; #endif /* ! WIN32 */ /* nothing will be left in event queue, no need for an alarm */ #if SM_CONF_SETITIMER clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; clr.it_value.tv_sec = 0; clr.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &clr, NULL); #else /* SM_CONF_SETITIMER */ (void) alarm(0); #endif /* SM_CONF_SETITIMER */ if (SmEventQueue == NULL) return; #ifndef WIN32 wasblocked = sm_blocksignal(SIGALRM); #endif /* ! WIN32 */ /* find the end of the EventQueue */ for (ev = SmEventQueue; ev->ev_link != NULL; ev = ev->ev_link) continue; ENTER_CRITICAL(); ev->ev_link = SmFreeEventList; SmFreeEventList = SmEventQueue; SmEventQueue = NULL; LEAVE_CRITICAL(); #ifndef WIN32 /* restore clocks and pick up anything spare */ if (wasblocked == 0) (void) sm_releasesignal(SIGALRM); #endif /* ! WIN32 */ } /* ** SM_TICK -- take a clock tick ** ** Called by the alarm clock. This routine runs events as needed. ** Always called as a signal handler, so we assume that SIGALRM ** has been blocked. ** ** Parameters: ** One that is ignored; for compatibility with signal handlers. ** ** Returns: ** none. ** ** Side Effects: ** calls the next function in EventQueue. ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED */ SIGFUNC_DECL sm_tick(sig) int sig; { register SM_EVENT *ev; pid_t mypid; int save_errno = errno; #if SM_CONF_SETITIMER struct itimerval clr; struct timeval now; #else /* SM_CONF_SETITIMER */ register time_t now; #endif /* SM_CONF_SETITIMER */ #if SM_CONF_SETITIMER clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; clr.it_value.tv_sec = 0; clr.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &clr, NULL); gettimeofday(&now, NULL); #else /* SM_CONF_SETITIMER */ (void) alarm(0); now = time(NULL); #endif /* SM_CONF_SETITIMER */ FIX_SYSV_SIGNAL(sig, sm_tick); errno = save_errno; CHECK_CRITICAL(sig); mypid = getpid(); while (PendingSignal != 0) { int sigbit = 0; int sig = 0; if (bitset(PEND_SIGHUP, PendingSignal)) { sigbit = PEND_SIGHUP; sig = SIGHUP; } else if (bitset(PEND_SIGINT, PendingSignal)) { sigbit = PEND_SIGINT; sig = SIGINT; } else if (bitset(PEND_SIGTERM, PendingSignal)) { sigbit = PEND_SIGTERM; sig = SIGTERM; } else if (bitset(PEND_SIGUSR1, PendingSignal)) { sigbit = PEND_SIGUSR1; sig = SIGUSR1; } else { /* If we get here, we are in trouble */ abort(); } PendingSignal &= ~sigbit; #ifndef WIN32 kill(mypid, sig); #endif /* ! WIN32 */ } #if SM_CONF_SETITIMER gettimeofday(&now, NULL); #else /* SM_CONF_SETITIMER */ now = time(NULL); #endif /* SM_CONF_SETITIMER */ while ((ev = SmEventQueue) != NULL && (ev->ev_pid != mypid || #if SM_CONF_SETITIMER timercmp(&ev->ev_time, &now, <=) #else /* SM_CONF_SETITIMER */ ev->ev_time <= now #endif /* SM_CONF_SETITIMER */ )) { void (*f)__P((int)); int arg; pid_t pid; /* process the event on the top of the queue */ ev = SmEventQueue; SmEventQueue = SmEventQueue->ev_link; /* we must be careful in here because ev_func may not return */ f = ev->ev_func; arg = ev->ev_arg; pid = ev->ev_pid; ENTER_CRITICAL(); ev->ev_link = SmFreeEventList; SmFreeEventList = ev; LEAVE_CRITICAL(); if (pid != getpid()) continue; if (SmEventQueue != NULL) { #if SM_CONF_SETITIMER if (timercmp(&SmEventQueue->ev_time, &now, >)) { timersub(&SmEventQueue->ev_time, &now, &clr.it_value); clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; if (clr.it_value.tv_sec < 0) clr.it_value.tv_sec = 0; if (clr.it_value.tv_sec == 0 && clr.it_value.tv_usec == 0) clr.it_value.tv_usec = 1000; (void) setitimer(ITIMER_REAL, &clr, NULL); } else { clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; clr.it_value.tv_sec = 3; clr.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &clr, NULL); } #else /* SM_CONF_SETITIMER */ if (SmEventQueue->ev_time > now) (void) alarm((unsigned) (SmEventQueue->ev_time - now)); else (void) alarm(3); #endif /* SM_CONF_SETITIMER */ } /* call ev_func */ errno = save_errno; (*f)(arg); #if SM_CONF_SETITIMER clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; clr.it_value.tv_sec = 0; clr.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &clr, NULL); gettimeofday(&now, NULL); #else /* SM_CONF_SETITIMER */ (void) alarm(0); now = time(NULL); #endif /* SM_CONF_SETITIMER */ } if (SmEventQueue != NULL) { #if SM_CONF_SETITIMER timersub(&SmEventQueue->ev_time, &now, &clr.it_value); clr.it_interval.tv_sec = 0; clr.it_interval.tv_usec = 0; if (clr.it_value.tv_sec < 0) clr.it_value.tv_sec = 0; if (clr.it_value.tv_sec == 0 && clr.it_value.tv_usec == 0) clr.it_value.tv_usec = 1000; (void) setitimer(ITIMER_REAL, &clr, NULL); #else /* SM_CONF_SETITIMER */ (void) alarm((unsigned) (SmEventQueue->ev_time - now)); #endif /* SM_CONF_SETITIMER */ } errno = save_errno; return SIGFUNC_RETURN; } /* ** SLEEP -- a version of sleep that works with this stuff ** ** Because Unix sleep uses the alarm facility, I must reimplement ** it here. ** ** Parameters: ** intvl -- time to sleep. ** ** Returns: ** zero. ** ** Side Effects: ** waits for intvl time. However, other events can ** be run during that interval. */ #ifndef WIN32 # if !HAVE_NANOSLEEP static void sm_endsleep __P((int)); static bool volatile SmSleepDone; # endif /* !HAVE_NANOSLEEP */ #ifndef SLEEP_T # define SLEEP_T unsigned int #endif /* ! SLEEP_T */ SLEEP_T sleep(intvl) unsigned int intvl; { #if HAVE_NANOSLEEP struct timespec rqtp; if (intvl == 0) return (SLEEP_T) 0; rqtp.tv_sec = intvl; rqtp.tv_nsec = 0; nanosleep(&rqtp, NULL); return (SLEEP_T) 0; #else /* HAVE_NANOSLEEP */ int was_held; SM_EVENT *ev; #if _FFR_SLEEP_USE_SELECT > 0 int r; # if _FFR_SLEEP_USE_SELECT > 0 struct timeval sm_io_to; # endif /* _FFR_SLEEP_USE_SELECT > 0 */ #endif /* _FFR_SLEEP_USE_SELECT > 0 */ #if SM_CONF_SETITIMER struct timeval now, begin, diff; # if _FFR_SLEEP_USE_SELECT > 0 struct timeval slpv; # endif /* _FFR_SLEEP_USE_SELECT > 0 */ #else /* SM_CONF_SETITIMER */ time_t begin, now; #endif /* SM_CONF_SETITIMER */ if (intvl == 0) return (SLEEP_T) 0; #if defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 if (intvl > _FFR_MAX_SLEEP_TIME) { syslog(LOG_ERR, "sleep: interval=%u exceeds max value %d", intvl, _FFR_MAX_SLEEP_TIME); # if 0 SM_ASSERT(intvl < (unsigned int) INT_MAX); # endif /* 0 */ intvl = _FFR_MAX_SLEEP_TIME; } #endif /* defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 */ SmSleepDone = false; #if SM_CONF_SETITIMER # if _FFR_SLEEP_USE_SELECT > 0 slpv.tv_sec = intvl; slpv.tv_usec = 0; # endif /* _FFR_SLEEP_USE_SELECT > 0 */ (void) gettimeofday(&now, NULL); begin = now; #else /* SM_CONF_SETITIMER */ now = begin = time(NULL); #endif /* SM_CONF_SETITIMER */ ev = sm_setevent((time_t) intvl, sm_endsleep, 0); if (ev == NULL) { /* COMPLAIN */ #if 0 syslog(LOG_ERR, "sleep: sm_setevent(%u) failed", intvl); #endif /* 0 */ SmSleepDone = true; } was_held = sm_releasesignal(SIGALRM); while (!SmSleepDone) { #if SM_CONF_SETITIMER (void) gettimeofday(&now, NULL); timersub(&now, &begin, &diff); if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_usec == 0)) break; # if _FFR_SLEEP_USE_SELECT > 0 timersub(&slpv, &diff, &sm_io_to); # endif /* _FFR_SLEEP_USE_SELECT > 0 */ #else /* SM_CONF_SETITIMER */ now = time(NULL); /* ** Check whether time expired before signal is released. ** Due to the granularity of time() add 1 to be on the ** safe side. */ if (!(begin + (time_t) intvl + 1 > now)) break; # if _FFR_SLEEP_USE_SELECT > 0 sm_io_to.tv_sec = intvl - (now - begin); if (sm_io_to.tv_sec <= 0) sm_io_to.tv_sec = 1; sm_io_to.tv_usec = 0; # endif /* _FFR_SLEEP_USE_SELECT > 0 */ #endif /* SM_CONF_SETITIMER */ #if _FFR_SLEEP_USE_SELECT > 0 if (intvl <= _FFR_SLEEP_USE_SELECT) { r = select(0, NULL, NULL, NULL, &sm_io_to); if (r == 0) break; } else #endif /* _FFR_SLEEP_USE_SELECT > 0 */ (void) pause(); } /* if out of the loop without the event being triggered remove it */ if (!SmSleepDone) sm_clrevent(ev); if (was_held > 0) (void) sm_blocksignal(SIGALRM); return (SLEEP_T) 0; #endif /* HAVE_NANOSLEEP */ } #if !HAVE_NANOSLEEP static void sm_endsleep(ignore) int ignore; { /* ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ SmSleepDone = true; } #endif /* !HAVE_NANOSLEEP */ #endif /* ! WIN32 */ dk-milter-1.0.0.dfsg/libsm/fclose.c0000644000175000017500000000620010253661450016611 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fclose.c,v 1.44 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #include #include #include #include #include "local.h" static void closealrm __P((int)); static jmp_buf CloseTimeOut; /* ** CLOSEALRM -- handler when timeout activated for sm_io_close() ** ** Returns flow of control to where setjmp(CloseTimeOut) was set. ** ** Parameters: ** sig -- unused ** ** Returns: ** does not return ** ** Side Effects: ** returns flow of control to setjmp(CloseTimeOut). ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED0 */ static void closealrm(sig) int sig; { longjmp(CloseTimeOut, 1); } /* ** SM_IO_CLOSE -- close a file handle/pointer ** ** Parameters: ** fp -- file pointer to be closed ** timeout -- maximum time allowed to perform the close (millisecs) ** ** Returns: ** 0 on success ** -1 on failure and sets errno ** ** Side Effects: ** file pointer 'fp' will no longer be valid. */ int sm_io_close(fp, timeout) register SM_FILE_T *fp; int SM_NONVOLATILE timeout; { register int SM_NONVOLATILE r; SM_EVENT *evt = NULL; if (fp == NULL) { errno = EBADF; return SM_IO_EOF; } SM_REQUIRE_ISA(fp, SmFileMagic); /* XXX this won't be reached if above macro is active */ if (fp->sm_magic == NULL) { /* not open! */ errno = EBADF; return SM_IO_EOF; } if (fp->f_close == NULL) { /* no close function! */ errno = ENODEV; return SM_IO_EOF; } if (fp->f_dup_cnt > 0) { /* decrement file pointer open count */ fp->f_dup_cnt--; return 0; } /* Okay, this is where we set the timeout. */ if (timeout == SM_TIME_DEFAULT) timeout = fp->f_timeout; if (timeout == SM_TIME_IMMEDIATE) { errno = EAGAIN; return -1; } /* No more duplicates of file pointer. Flush buffer and close */ r = fp->f_flags & SMWR ? sm_flush(fp, (int *) &timeout) : 0; /* sm_flush() has updated to.it_value for the time it's used */ if (timeout != SM_TIME_FOREVER) { if (setjmp(CloseTimeOut) != 0) { errno = EAGAIN; return SM_IO_EOF; } evt = sm_seteventm(timeout, closealrm, 0); } if ((*fp->f_close)(fp) < 0) r = SM_IO_EOF; /* We're back. So undo our timeout and handler */ if (evt != NULL) sm_clrevent(evt); if (fp->f_flags & SMMBF) { sm_free((char *)fp->f_bf.smb_base); fp->f_bf.smb_base = NULL; } if (HASUB(fp)) FREEUB(fp); fp->f_flags = 0; /* clear flags */ fp->sm_magic = NULL; /* Release this SM_FILE_T for reuse. */ fp->f_r = fp->f_w = 0; /* Mess up if reaccessed. */ return r; } dk-milter-1.0.0.dfsg/libsm/syslogio.c0000644000175000017500000001017707347306541017225 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: syslogio.c,v 1.29 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include #ifdef SM_RPOOL # include #endif /* SM_RPOOL */ #include #include "local.h" /* ** Overall: ** This is a output file type that copies its output to the syslog daemon. ** Each line of output is written as a separate syslog message. ** The client is responsible for calling openlog() before writing to ** any syslog file, and calling closelog() after all syslog output is complete. ** The only state associated with a syslog file is 'int priority', ** which we store in fp->f_ival. */ /* ** SM_SYSLOGOPEN -- open a file pointer to syslog ** ** Parameters: ** fp -- file pointer assigned for the open ** info -- priority level of the syslog messages ** flags -- not used ** rpool -- ignored ** ** Returns: ** 0 (zero) success always (see Overall) */ int sm_syslogopen(fp, info, flags, rpool) SM_FILE_T *fp; const void *info; int flags; const void *rpool; { int *priority = (int *)info; fp->f_ival = *priority; return 0; } /* ** SM_SYSLOGREAD -- read function for syslog ** ** This is a "stub" function (placeholder) that always returns an error. ** It is an error to read syslog. ** ** Parameters: ** fp -- the file pointer ** buf -- buffer to place the data read ** n -- number of bytes to read ** ** Returns: ** -1 (error) always and sets errno */ ssize_t sm_syslogread(fp, buf, n) SM_FILE_T *fp; char *buf; size_t n; { /* an error to read */ errno = ENODEV; return -1; } /* ** SM_SYSLOGWRITE -- write function for syslog ** ** Send output to syslog. ** ** Parameters: ** fp -- the file pointer ** buf -- buffer that the write data comes from ** n -- number of bytes to write ** ** Returns: ** 0 (zero) for success always */ /* ** XXX TODO: more work needs to be done to ensure that each line of output ** XXX written to a syslog file is mapped to exactly one syslog message. */ ssize_t sm_syslogwrite(fp, buf, n) SM_FILE_T *fp; char const *buf; size_t n; { syslog(fp->f_ival, "%s", buf); return 0; } /* ** SM_SYSLOGSEEK -- position the syslog file offset ** ** This is a "stub" function (placeholder) that always returns an error. ** It is an error to seek syslog. ** ** Parameters: ** fp -- the file pointer ** offset -- the new offset position relative to 'whence' ** whence -- flag indicating start of 'offset' ** ** Returns: ** -1 (error) always. */ off_t sm_syslogseek(fp, offset, whence) SM_FILE_T *fp; off_t offset; int whence; { errno = ENODEV; return -1; } /* ** SM_SYSLOGCLOSE -- close the syslog file pointer ** ** Parameters: ** fp -- the file pointer ** ** Returns: ** 0 (zero) success always (see Overall) ** */ int sm_syslogclose(fp) SM_FILE_T *fp; { return 0; } /* ** SM_SYSLOGSETINFO -- set information for the file pointer ** ** Parameters: ** fp -- the file pointer being set ** what -- what information is being set ** valp -- information content being set to ** ** Returns: ** -1 on failure ** 0 (zero) on success ** ** Side Effects: ** Sets internal file pointer data */ int sm_syslogsetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch (what) { case SM_IO_SL_PRIO: fp->f_ival = *((int *)(valp)); return 0; default: errno = EINVAL; return -1; } } /* ** SM_SYSLOGGETINFO -- get information relating to the file pointer ** ** Parameters: ** fp -- the file pointer being queried ** what -- the information type being queried ** valp -- location to placed queried information ** ** Returns: ** 0 (zero) on success ** -1 on failure ** ** Side Effects: ** Fills in 'valp' with data. */ int sm_sysloggetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch (what) { case SM_IO_SL_PRIO: *((int *)(valp)) = fp->f_ival; return 0; default: errno = EINVAL; return -1; } } dk-milter-1.0.0.dfsg/libsm/smstdio.c0000644000175000017500000001422010103774652017024 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: smstdio.c,v 1.34 2004/08/03 20:46:34 ca Exp $") #include #include #include #include #include #include #include #include #include "local.h" static void setup __P((SM_FILE_T *)); /* ** Overall: ** This is a file type which implements a layer on top of the system ** stdio. fp->f_cookie is the FILE* of stdio. The cookie may be ** "bound late" because of the manner which Linux implements stdio. ** When binding late (when fp->f_cookie==NULL) then the value of ** fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or ** stderr. */ /* ** SM_STDIOOPEN -- open a file to system stdio implementation ** ** Parameters: ** fp -- file pointer assign for this open ** info -- info about file to open ** flags -- indicating method of opening ** rpool -- ignored ** ** Returns: ** Failure: -1 ** Success: 0 (zero) */ /* ARGSUSED3 */ int sm_stdioopen(fp, info, flags, rpool) SM_FILE_T *fp; const void *info; int flags; const void *rpool; { register FILE *s; char *stdiomode; switch (flags) { case SM_IO_RDONLY: stdiomode = "r"; break; case SM_IO_WRONLY: stdiomode = "w"; break; case SM_IO_APPEND: stdiomode = "a"; break; case SM_IO_APPENDRW: stdiomode = "a+"; break; #if SM_IO_BINARY != 0 case SM_IO_RDONLY_B: stdiomode = "rb"; break; case SM_IO_WRONLY_B: stdiomode = "wb"; break; case SM_IO_APPEND_B: stdiomode = "ab"; break; case SM_IO_APPENDRW_B: stdiomode = "a+b"; break; case SM_IO_RDWR_B: stdiomode = "r+b"; break; #endif /* SM_IO_BINARY != 0 */ case SM_IO_RDWR: default: stdiomode = "r+"; break; } if ((s = fopen((char *)info, stdiomode)) == NULL) return -1; fp->f_cookie = s; return 0; } /* ** SETUP -- assign file type cookie when not already assigned ** ** Parameters: ** fp - the file pointer to get the cookie assigned ** ** Return: ** none. */ static void setup(fp) SM_FILE_T *fp; { if (fp->f_cookie == NULL) { switch (fp->f_ival) { case 0: fp->f_cookie = stdin; break; case 1: fp->f_cookie = stdout; break; case 2: fp->f_cookie = stderr; break; default: sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival); break; } } } /* ** SM_STDIOREAD -- read from the file ** ** Parameters: ** fp -- the file pointer ** buf -- location to place the read data ** n - number of bytes to read ** ** Returns: ** result from fread(). */ ssize_t sm_stdioread(fp, buf, n) SM_FILE_T *fp; char *buf; size_t n; { register FILE *s; if (fp->f_cookie == NULL) setup(fp); s = fp->f_cookie; return fread(buf, 1, n, s); } /* ** SM_STDIOWRITE -- write to the file ** ** Parameters: ** fp -- the file pointer ** buf -- location of data to write ** n - number of bytes to write ** ** Returns: ** result from fwrite(). */ ssize_t sm_stdiowrite(fp, buf, n) SM_FILE_T *fp; char const *buf; size_t n; { register FILE *s; if (fp->f_cookie == NULL) setup(fp); s = fp->f_cookie; return fwrite(buf, 1, n, s); } /* ** SM_STDIOSEEK -- set position within file ** ** Parameters: ** fp -- the file pointer ** offset -- new location based on 'whence' ** whence -- indicates "base" for 'offset' ** ** Returns: ** result from fseek(). */ off_t sm_stdioseek(fp, offset, whence) SM_FILE_T *fp; off_t offset; int whence; { register FILE *s; if (fp->f_cookie == NULL) setup(fp); s = fp->f_cookie; return fseek(s, offset, whence); } /* ** SM_STDIOCLOSE -- close the file ** ** Parameters: ** fp -- close file pointer ** ** Return: ** status from fclose() */ int sm_stdioclose(fp) SM_FILE_T *fp; { register FILE *s; if (fp->f_cookie == NULL) setup(fp); s = fp->f_cookie; return fclose(s); } /* ** SM_STDIOSETINFO -- set info for this open file ** ** Parameters: ** fp -- the file pointer ** what -- type of information setting ** valp -- memory location of info to set ** ** Return: ** Failure: -1 and sets errno ** Success: none (currently). */ /* ARGSUSED2 */ int sm_stdiosetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch (what) { case SM_IO_WHAT_MODE: default: errno = EINVAL; return -1; } } /* ** SM_STDIOGETINFO -- get info for this open file ** ** Parameters: ** fp -- the file pointer ** what -- type of information request ** valp -- memory location to place info ** ** Return: ** Failure: -1 and sets errno ** Success: none (currently). */ /* ARGSUSED2 */ int sm_stdiogetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch (what) { case SM_IO_WHAT_SIZE: { int fd; struct stat st; if (fp->f_cookie == NULL) setup(fp); fd = fileno((FILE *) fp->f_cookie); if (fd < 0) return -1; if (fstat(fd, &st) == 0) return st.st_size; else return -1; } case SM_IO_WHAT_MODE: default: errno = EINVAL; return -1; } } /* ** SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE ** ** Parameters: ** stream -- an open stdio stream, as returned by fopen() ** mode -- the mode argument to fopen() which describes stream ** ** Return: ** On success, return a pointer to an SM_FILE object which ** can be used for reading and writing 'stream'. ** Abort if mode is gibberish or stream is bad. ** Raise an exception if we can't allocate memory. */ SM_FILE_T * sm_io_stdioopen(stream, mode) FILE *stream; char *mode; { int fd; bool r, w; int ioflags; SM_FILE_T *fp; fd = fileno(stream); SM_REQUIRE(fd >= 0); r = w = false; switch (mode[0]) { case 'r': r = true; break; case 'w': case 'a': w = true; break; default: sm_abort("sm_io_stdioopen: mode '%s' is bad", mode); } if (strchr(&mode[1], '+') != NULL) r = w = true; if (r && w) ioflags = SMRW; else if (r) ioflags = SMRD; else ioflags = SMWR; fp = sm_fp(SmFtRealStdio, ioflags, NULL); fp->f_file = fd; fp->f_cookie = stream; return fp; } dk-milter-1.0.0.dfsg/libsm/cdefs.html0000644000175000017500000000462007213744725017161 0ustar madhackmadhack libsm : C Language Portability Macros Back to libsm overview

libsm : C Language Portability Macros


$Id: cdefs.html,v 1.2 2000/12/07 17:33:09 dmoen Exp $

Description

The header file <sm/cdefs.h> defines portable interfaces to non-portable features of various C compilers. It also assists you in writing C header files that are compatible with C++.
__P(parameterlist)
This macro is used to write portable function prototypes. For example,
int foo __P((int));
__CONCAT(x,y)
This macro concatenates two tokens x and y, forming a single token xy. Warning: make sure there is no white space around the arguments x and y.

__STRING(x)
This macro converts the token sequence x into a string literal.

__BEGIN_DECLS, __END_DECLS
These macros are used to write C header files that are compatible with C++ compilers. Put __BEGIN_DECLS before the first function or variable declaration in your header file, and put __END_DECLS after the last function or variable declaration.

const, signed, volatile
For pre-ANSI C compilers, const, signed and volatile are defined as empty macros. This means you can use these keywords without introducing portability problems.

SM_DEAD(function_declaration)
This macro modifies a prototype of a function that does not return to its caller. With some versions of gcc, this will result in slightly better code, and can suppress some useless warnings produced by gcc -Wall. For example,
SM_DEAD(void exit __P((int)));
SM_UNUSED(variable_declaration)
This macro modifies a definition of an unused local variable, global variable or function parameter in order to suppress compiler warnings. Examples:
SM_UNUSED(static const char Id[]) = "@(#)$Id: cdefs.html,v 1.2 2000/12/07 17:33:09 dmoen Exp $";
void
foo(x)
	SM_UNUSED(int x);
{
	SM_UNUSED(int y) = 0;
	return 0;
}
void
bar(SM_UNUSED(int x))
{
	return 0;
}
dk-milter-1.0.0.dfsg/libsm/t-cf.c0000644000175000017500000000165207347306541016204 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_IDSTR(id, "@(#)$Id: t-cf.c,v 1.7 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include int main(argc, argv) int argc; char **argv; { SM_CF_OPT_T opt; int err; if (argc != 3) { fprintf(stderr, "Usage: %s .cf-file option\n", argv[0]); exit(1); } opt.opt_name = argv[2]; opt.opt_val = NULL; err = sm_cf_getopt(argv[1], 1, &opt); if (err) { fprintf(stderr, "%s: %s\n", argv[1], strerror(err)); exit(1); } if (opt.opt_val == NULL) printf("Error: option \"%s\" not found\n", opt.opt_name); else printf("%s=%s\n", opt.opt_name, opt.opt_val); return 0; } dk-milter-1.0.0.dfsg/libsm/t-scanf.c0000644000175000017500000000263407374067220016705 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-scanf.c,v 1.5 2001/11/13 00:51:28 ca Exp $") #include #include #include #include #include int main(argc, argv) int argc; char **argv; { int i, d, h; char buf[128]; char *r; sm_test_begin(argc, argv, "test scanf point stuff"); #if !SM_CONF_BROKEN_SIZE_T (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "If tests for \"h == 2\" fail, check whether size_t is signed on your OS.\n\ If that is the case, add -DSM_CONF_BROKEN_SIZE_T to confENVDEF\n\ and start over. Otherwise contact sendmail.org.\n"); #endif /* !SM_CONF_BROKEN_SIZE_T */ d = 2; sm_snprintf(buf, sizeof(buf), "%d", d); r = "2"; if (!SM_TEST(strcmp(buf, r) == 0)) (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "got %s instead\n", buf); i = sm_io_sscanf(buf, "%d", &h); SM_TEST(i == 1); SM_TEST(h == 2); d = 2; sm_snprintf(buf, sizeof(buf), "%d\n", d); r = "2\n"; if (!SM_TEST(strcmp(buf, r) == 0)) (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "got %s instead\n", buf); i = sm_io_sscanf(buf, "%d", &h); SM_TEST(i == 1); SM_TEST(h == 2); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/feof.c0000644000175000017500000000170507347306540016270 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: feof.c,v 1.13 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include "local.h" /* ** SM_IO_EOF -- subroutine version of the macro sm_io_eof. ** ** Tests if the file for 'fp' has reached the end. ** ** Parameters: ** fp -- file pointer. ** ** Returns: ** 0 (zero) when the file is not at end ** non-zero when EOF has been found */ #undef sm_io_eof int sm_io_eof(fp) SM_FILE_T *fp; { SM_REQUIRE_ISA(fp, SmFileMagic); return sm_eof(fp); } dk-milter-1.0.0.dfsg/libsm/config.c0000644000175000017500000001244210576063555016622 0ustar madhackmadhack/* * Copyright (c) 2000-2003, 2007 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: config.c,v 1.31 2007/03/14 21:21:49 ca Exp $") #include #include #include #include /* ** PUTENV -- emulation of putenv() in terms of setenv() ** ** Not needed on Posix-compliant systems. ** This doesn't have full Posix semantics, but it's good enough ** for sendmail. ** ** Parameter: ** env -- the environment to put. ** ** Returns: ** 0 on success, < 0 on failure. */ #if NEEDPUTENV # if NEEDPUTENV == 2 /* no setenv(3) call available */ int putenv(str) char *str; { char **current; int matchlen, envlen = 0; char *tmp; char **newenv; static bool first = true; extern char **environ; /* ** find out how much of str to match when searching ** for a string to replace. */ if ((tmp = strchr(str, '=')) == NULL || tmp == str) matchlen = strlen(str); else matchlen = (int) (tmp - str); ++matchlen; /* ** Search for an existing string in the environment and find the ** length of environ. If found, replace and exit. */ for (current = environ; *current != NULL; current++) { ++envlen; if (strncmp(str, *current, matchlen) == 0) { /* found it, now insert the new version */ *current = (char *) str; return 0; } } /* ** There wasn't already a slot so add space for a new slot. ** If this is our first time through, use malloc(), else realloc(). */ if (first) { newenv = (char **) sm_malloc(sizeof(char *) * (envlen + 2)); if (newenv == NULL) return -1; first = false; (void) memcpy(newenv, environ, sizeof(char *) * envlen); } else { newenv = (char **) sm_realloc((char *) environ, sizeof(char *) * (envlen + 2)); if (newenv == NULL) return -1; } /* actually add in the new entry */ environ = newenv; environ[envlen] = (char *) str; environ[envlen + 1] = NULL; return 0; } # else /* NEEDPUTENV == 2 */ int putenv(env) char *env; { char *p; int l; char nbuf[100]; p = strchr(env, '='); if (p == NULL) return 0; l = p - env; if (l > sizeof nbuf - 1) l = sizeof nbuf - 1; memmove(nbuf, env, l); nbuf[l] = '\0'; return setenv(nbuf, ++p, 1); } # endif /* NEEDPUTENV == 2 */ #endif /* NEEDPUTENV */ /* ** UNSETENV -- remove a variable from the environment ** ** Not needed on newer systems. ** ** Parameters: ** name -- the string name of the environment variable to be ** deleted from the current environment. ** ** Returns: ** none. ** ** Globals: ** environ -- a pointer to the current environment. ** ** Side Effects: ** Modifies environ. */ #if !HASUNSETENV # ifdef WIN32 void unsetenv(name) char *name; { int len = strlen(name) + 2; char *p = sm_malloc_x(len); (void) sm_strlcpyn(p, len, 2, name, "="); putenv(p); sm_free(p); } # else /* WIN32 */ void unsetenv(name) char *name; { extern char **environ; register char **pp; int len = strlen(name); for (pp = environ; *pp != NULL; pp++) { if (strncmp(name, *pp, len) == 0 && ((*pp)[len] == '=' || (*pp)[len] == '\0')) break; } for (; *pp != NULL; pp++) *pp = pp[1]; } # endif /* WIN32 */ #endif /* !HASUNSETENV */ char *SmCompileOptions[] = { #if SM_CONF_BROKEN_STRTOD "SM_CONF_BROKEN_STRTOD", #endif /* SM_CONF_BROKEN_STRTOD */ #if SM_CONF_GETOPT "SM_CONF_GETOPT", #endif /* SM_CONF_GETOPT */ #if SM_CONF_LDAP_INITIALIZE "SM_CONF_LDAP_INITIALIZE", #endif /* SM_CONF_LDAP_INITIALIZE */ #if SM_CONF_LDAP_MEMFREE "SM_CONF_LDAP_MEMFREE", #endif /* SM_CONF_LDAP_MEMFREE */ #if SM_CONF_LONGLONG "SM_CONF_LONGLONG", #endif /* SM_CONF_LONGLONG */ #if SM_CONF_MEMCHR "SM_CONF_MEMCHR", #endif /* SM_CONF_MEMCHR */ #if SM_CONF_MSG "SM_CONF_MSG", #endif /* SM_CONF_MSG */ #if SM_CONF_QUAD_T "SM_CONF_QUAD_T", #endif /* SM_CONF_QUAD_T */ #if SM_CONF_SEM "SM_CONF_SEM", #endif /* SM_CONF_SEM */ #if SM_CONF_SETITIMER "SM_CONF_SETITIMER", #endif /* SM_CONF_SETITIMER */ #if SM_CONF_SIGSETJMP "SM_CONF_SIGSETJMP", #endif /* SM_CONF_SIGSETJMP */ #if SM_CONF_SHM "SM_CONF_SHM", #endif /* SM_CONF_SHM */ #if SM_CONF_SHM_DELAY "SM_CONF_SHM_DELAY", #endif /* SM_CONF_SHM_DELAY */ #if SM_CONF_SSIZE_T "SM_CONF_SSIZE_T", #endif /* SM_CONF_SSIZE_T */ #if SM_CONF_STDBOOL_H "SM_CONF_STDBOOL_H", #endif /* SM_CONF_STDBOOL_H */ #if SM_CONF_STDDEF_H "SM_CONF_STDDEF_H", #endif /* SM_CONF_STDDEF_H */ #if 0 /* XXX this is always enabled (for now) */ #if SM_CONF_STRL "SM_CONF_STRL", #endif /* SM_CONF_STRL */ #endif /* 0 */ #if SM_CONF_SYS_CDEFS_H "SM_CONF_SYS_CDEFS_H", #endif /* SM_CONF_SYS_CDEFS_H */ #if SM_CONF_SYSEXITS_H "SM_CONF_SYSEXITS_H", #endif /* SM_CONF_SYSEXITS_H */ #if SM_CONF_UID_GID "SM_CONF_UID_GID", #endif /* SM_CONF_UID_GID */ #if DO_NOT_USE_STRCPY "DO_NOT_USE_STRCPY", #endif /* DO_NOT_USE_STRCPY */ #if SM_HEAP_CHECK "SM_HEAP_CHECK", #endif /* SM_HEAP_CHECK */ #if defined(SM_OS_NAME) && defined(__STDC__) "SM_OS=sm_os_" SM_OS_NAME, #endif /* defined(SM_OS_NAME) && defined(__STDC__) */ #if SM_VA_STD "SM_VA_STD", #endif /* SM_VA_STD */ #if USEKSTAT "USEKSTAT", #endif /* USEKSTAT */ #if USEPROCMEMINFO "USEPROCMEMINFO", #endif /* USEPROCMEMINFO */ #if USESWAPCTL "USESWAPCTL", #endif /* USESWAPCTL */ NULL }; dk-milter-1.0.0.dfsg/libsm/findfp.c0000644000175000017500000002561310474657436016633 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: findfp.c,v 1.67 2006/08/28 21:24:46 ca Exp $") #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #include "glue.h" bool Sm_IO_DidInit; /* IO system has been initialized? */ const char SmFileMagic[] = "sm_file"; /* An open type to map to fopen()-like behavior */ SM_FILE_T SmFtStdio_def = {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0, sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, SM_TIME_BLOCK, "stdio" }; /* An open type to map to fdopen()-like behavior */ SM_FILE_T SmFtStdiofd_def = {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0, sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, SM_TIME_BLOCK, "stdiofd" }; /* A string file type */ SM_FILE_T SmFtString_def = {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0, sm_strclose, sm_strread, sm_strseek, sm_strwrite, sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER, SM_TIME_BLOCK, "string" }; #if 0 /* A file type for syslog communications */ SM_FILE_T SmFtSyslog_def = {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0, sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite, sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER, SM_TIME_BLOCK, "syslog" }; #endif /* 0 */ #define NDYNAMIC 10 /* add ten more whenever necessary */ #define smio(flags, file, name) \ {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0, \ sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, \ sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, \ SM_TIME_BLOCK, name} /* sm_magic p r w flags file bf lbfsize cookie ival */ #define smstd(flags, file, name) \ {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file, \ sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite, \ sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\ SM_TIME_BLOCK, name} /* A file type for interfacing to stdio FILE* streams. */ SM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio"); /* the usual - (stdin + stdout + stderr) */ static SM_FILE_T usual[SM_IO_OPEN_MAX - 3]; static struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual }; /* List of builtin automagically already open file pointers */ SM_FILE_T SmIoF[6] = { smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"), /* smioin */ smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"), /* smioout */ smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"), /* smioerr */ smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"), /* smiostdin */ smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */ smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */ }; /* Structure containing list of currently open file pointers */ struct sm_glue smglue = { &smuglue, 3, SmIoF }; /* ** SM_MOREGLUE -- adds more space for open file pointers ** ** Parameters: ** n -- number of new spaces for file pointers ** ** Returns: ** Raises an exception if no more memory. ** Otherwise, returns a pointer to new spaces. */ static struct sm_glue *sm_moreglue_x __P((int)); static SM_FILE_T empty; static struct sm_glue * sm_moreglue_x(n) register int n; { register struct sm_glue *g; register SM_FILE_T *p; g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + SM_ALIGN_BITS + n * sizeof(SM_FILE_T)); p = (SM_FILE_T *) SM_ALIGN(g + 1); g->gl_next = NULL; g->gl_niobs = n; g->gl_iobs = p; while (--n >= 0) *p++ = empty; return g; } /* ** SM_FP -- allocate and initialize an SM_FILE structure ** ** Parameters: ** t -- file type requested to be opened. ** flags -- control flags for file type behavior ** oldfp -- file pointer to reuse if available (optional) ** ** Returns: ** Raises exception on memory exhaustion. ** Aborts if type is invalid. ** Otherwise, returns file pointer for requested file type. */ SM_FILE_T * sm_fp(t, flags, oldfp) const SM_FILE_T *t; const int flags; SM_FILE_T *oldfp; { register SM_FILE_T *fp; register int n; register struct sm_glue *g; SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write)); if (!Sm_IO_DidInit) sm_init(); if (oldfp != NULL) { fp = oldfp; goto found; /* for opening reusing an 'fp' */ } for (g = &smglue;; g = g->gl_next) { for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++) if (fp->sm_magic == NULL) goto found; if (g->gl_next == NULL) g->gl_next = sm_moreglue_x(NDYNAMIC); } found: fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */ fp->f_p = NULL; /* no current pointer */ fp->f_w = 0; /* nothing to write */ fp->f_r = 0; /* nothing to read */ fp->f_flags = flags; fp->f_file = -1; /* no file */ fp->f_bf.smb_base = NULL; /* no buffer */ fp->f_bf.smb_size = 0; /* no buffer size with no buffer */ fp->f_lbfsize = 0; /* not line buffered */ fp->f_flushfp = NULL; /* no associated flush file */ fp->f_cookie = fp; /* default: *open* overrides cookie setting */ fp->f_close = t->f_close; /* assign close function */ fp->f_read = t->f_read; /* assign read function */ fp->f_seek = t->f_seek; /* assign seek function */ fp->f_write = t->f_write; /* assign write function */ fp->f_open = t->f_open; /* assign open function */ fp->f_setinfo = t->f_setinfo; /* assign setinfo function */ fp->f_getinfo = t->f_getinfo; /* assign getinfo function */ fp->f_type = t->f_type; /* file type */ fp->f_ub.smb_base = NULL; /* no ungetc buffer */ fp->f_ub.smb_size = 0; /* no size for no ungetc buffer */ if (fp->f_timeout == SM_TIME_DEFAULT) fp->f_timeout = SM_TIME_FOREVER; else fp->f_timeout = t->f_timeout; /* traditional behavior */ fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */ return fp; } /* ** SM_CLEANUP -- cleanup function when exit called. ** ** This function is registered via atexit(). ** ** Parameters: ** none ** ** Returns: ** nothing. ** ** Side Effects: ** flushes open files before they are forced closed */ void sm_cleanup() { int timeout = SM_TIME_DEFAULT; (void) sm_fwalk(sm_flush, &timeout); /* `cheating' */ } /* ** SM_INIT -- called whenever sm_io's internal variables must be set up. ** ** Parameters: ** none ** ** Returns: ** none ** ** Side Effects: ** Registers sm_cleanup() using atexit(). */ void sm_init() { if (Sm_IO_DidInit) /* paranoia */ return; /* more paranoia: initialize pointers in a static variable */ empty.f_type = NULL; empty.sm_magic = NULL; /* make sure we clean up on exit */ atexit(sm_cleanup); /* conservative */ Sm_IO_DidInit = true; } /* ** SM_IO_SETINFO -- change info for an open file type (fp) ** ** The generic SM_IO_WHAT_VECTORS is auto supplied for all file types. ** If the request is to set info other than SM_IO_WHAT_VECTORS then ** the request is passed on to the file type's specific setinfo vector. ** WARNING: this is working on an active/open file type. ** ** Parameters: ** fp -- file to make the setting on ** what -- type of information to set ** valp -- structure to obtain info from ** ** Returns: ** 0 on success ** -1 on error and sets errno: ** - when what != SM_IO_WHAT_VECTORS and setinfo vector ** not set ** - when vectored setinfo returns -1 */ int sm_io_setinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { SM_FILE_T *v = (SM_FILE_T *) valp; SM_REQUIRE_ISA(fp, SmFileMagic); switch (what) { case SM_IO_WHAT_VECTORS: /* ** This is the "generic" available for all. ** This allows the function vectors to be replaced ** while the file type is active. */ fp->f_close = v->f_close; fp->f_read = v->f_read; fp->f_seek = v->f_seek; fp->f_write = v->f_write; fp->f_open = v->f_open; fp->f_setinfo = v->f_setinfo; fp->f_getinfo = v->f_getinfo; sm_free(fp->f_type); fp->f_type = sm_strdup_x(v->f_type); return 0; case SM_IO_WHAT_TIMEOUT: fp->f_timeout = *((int *)valp); return 0; } /* Otherwise the vector will check it out */ if (fp->f_setinfo == NULL) { errno = EINVAL; return -1; } else return (*fp->f_setinfo)(fp, what, valp); } /* ** SM_IO_GETINFO -- get information for an active file type (fp) ** ** This function supplies for all file types the answers for the ** three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and ** SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo ** vector if available for the open file type. ** SM_IO_WHAT_VECTORS returns information for the file pointer vectors. ** SM_IO_WHAT_TYPE returns the type identifier for the file pointer ** SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the ** file pointer's type. ** SM_IO_IS_READABLE returns 1 if there is data available for reading, ** 0 otherwise. ** ** Parameters: ** fp -- file pointer for active file type ** what -- type of information request ** valp -- structure to place obtained info into ** ** Returns: ** -1 on error and sets errno: ** - when valp==NULL and request expects otherwise ** - when request is not SM_IO_WHAT_VECTORS and not ** SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE ** and getinfo vector is NULL ** - when getinfo type vector returns -1 ** >=0 on success */ int sm_io_getinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { SM_FILE_T *v = (SM_FILE_T *) valp; SM_REQUIRE_ISA(fp, SmFileMagic); switch (what) { case SM_IO_WHAT_VECTORS: if (valp == NULL) { errno = EINVAL; return -1; } /* This is the "generic" available for all */ v->f_close = fp->f_close; v->f_read = fp->f_read; v->f_seek = fp->f_seek; v->f_write = fp->f_write; v->f_open = fp->f_open; v->f_setinfo = fp->f_setinfo; v->f_getinfo = fp->f_getinfo; v->f_type = fp->f_type; return 0; case SM_IO_WHAT_TYPE: if (valp == NULL) { errno = EINVAL; return -1; } valp = sm_strdup_x(fp->f_type); return 0; case SM_IO_WHAT_ISTYPE: if (valp == NULL) { errno = EINVAL; return -1; } return strcmp(fp->f_type, valp) == 0; case SM_IO_IS_READABLE: /* if there is data in the buffer, it must be readable */ if (fp->f_r > 0) return 1; /* otherwise query the underlying file */ break; case SM_IO_WHAT_TIMEOUT: *((int *) valp) = fp->f_timeout; return 0; case SM_IO_WHAT_FD: if (fp->f_file > -1) return fp->f_file; /* try the file type specific getinfo to see if it knows */ break; } /* Otherwise the vector will check it out */ if (fp->f_getinfo == NULL) { errno = EINVAL; return -1; } return (*fp->f_getinfo)(fp, what, valp); } dk-milter-1.0.0.dfsg/libsm/io.html0000644000175000017500000006517407254554212016512 0ustar madhackmadhack libsm sm_io general overview Back to libsm overview

libsm sm_io general overview


$Id: io.html,v 1.3 2001/03/17 03:22:50 gshapiro Exp $

Introduction

The sm_io portion of the libsm library is similar to the stdio library. It is derived from the Chris Torek version of the stdio library (BSD). There are some key differences described below between sm_io and stdio but many similarities will be noticed.

A key difference between stdio and sm_io is that the functional code that does the open, close, read, write, etc. on a file can be different for different files. For example, with stdio the functional code (read, write) is either the default supplied in the library or a "programmer specified" set of functions set via sm_io_open(). Whichever set of functions are specified all open's, read's, write's, etc use the same set of functions. In contrast, with sm_io a different set of functions can be specified with each active file for read's, write's, etc. These different function sets are identified as file types (see sm_io_open()). Each function set can handle the actions directly, pass the action request to another function set or do some work before passing it on to another function set. The setting of a function set for a file type can be done for a file type at any time (even after the type is open).

A second difference is the use of rpools. An rpool is specified with the opening of a file (sm_io_open()). This allows of a file to be associated with an rpool so that when the rpool is released the open file will be closed; the sm_io_open() registers that sm_io_close() should be called when the rpool is released.

A third difference is that the I/O functions take a timeout argument. This allows the setting of a maximum amount of time allowable for the I/O to be completed. This means the calling program does not need to setup it's own timeout mechanism. NOTE: SIGALRM's should not be active in the calling program when an I/O function with a timeout is used.

When converting source code from stdio to sm_io be very careful to NOTE: the arguments to functions have been rationalized. That is, unlike stdio, all sm_io functions that take a file pointer (SM_FILE_T *) argument have the file pointer as the first argument. Also not all functions with stdio have an identical matching sm_io API: the API list has been thinned since a number of stdio API's overlapped in functionality. Remember many functions also have a timeout argument added.

When a file is going to be opened, the file type is included with sm_io_open(). A file type is either one automatically included with the sm_io library or one created by the program at runtime. File types can be either buffered or unbuffered. When buffered the buffering is either the builtin sm_io buffering or as done by the file type. File types can be disk files, strings, TCP/IP connections or whatever your imagination can come up with that can be read and/or written to.

Information about a particular file type or pointer can be obtained or set with the sm_io "info" functions. The sm_io_setinfo() and sm_io_getinfo() functions work on an active file pointer.

Include files

There is one main include file for use with sm_io: io.h. Since the use of rpools is specified with sm_io_open() an rpool may be created and thus rpool.h may need to be included as well (before io.h).

#include <rpool.h>
#include <io.h>

Functions/API's

Below is a list of the functions for sm_io listed in alphabetical order. Currently these functions return error codes and set errno when appropriate. These (may?/will?) change to raising exceptions later.

SM_FILE_T *sm_io_autoflush(SM_FILE_T *fp, SM_FILE_T *)

void sm_io_automode(SM_FILE_T *fp, SM_FILE_T *)

void sm_io_clearerr(SM_FILE_T *fp)

int sm_io_close(SM_FILE_T *fp, int timeout)

int sm_io_dup(SM_FILE_T *fp)

int sm_io_eof(SM_FILE_T *fp)

int sm_io_error(SM_FILE_T *fp)

char * sm_io_fgets(SM_FILE_T *fp, int timeout, char *buf, int n)

int sm_io_flush(SM_FILE_T *fp, int timeout)

int sm_io_fopen(char *pathname, int flags [, MODE_T mode])

int sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...)

int sm_io_fputs(s, int, SM_FILE_T *fp)

int sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) 

int sm_io_getc(SM_FILE_T *fp, int timeout)

void sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)

SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)

int sm_io_purge(SM_FILE_T *fp)

int sm_io_putc(SM_FILE_T *fp, int timeout, int c)

size_t sm_io_read(SM_FILE_T *fp, int timeout, char *buf, size_t size)

SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)

void sm_io_rewind(SM_FILE_T *fp, int timeout)

int sm_io_seek(SM_FILE_T *fp, off_t offset, int timeout, int whence)

void sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)

int sm_io_setvbuf(SM_FILE_T *fp, int timeout, char *buf, int mode, size_t size)

int sm_io_sscanf(const char *str, char const *fmt, ...)

long sm_io_tell(SM_FILE_T *fp, int timeout)

int sm_io_ungetc(SM_FILE_T *fp, int timeout, int c)

size_t sm_io_write(SM_FILE_T *fp, int timeout, char *buf, size_t size)

int sm_snprintf(char *str, size_t n, char const *fmt, ...)

Timeouts

For many of the functions a timeout argument is given. This limits the amount of time allowed for the function to complete. There are three pre-defined values:

  • SM_TIME_DEFAULT - timeout using the default setting for this file type
  • SM_TIME_FOREVER - timeout will take forever; blocks until task completed
  • SM_TIME_IMMEDIATE - timeout (virtually) now
  • A function caller can also specify a positive integer value in milliseconds. A function will return with errno set to EINVAL if a bad value is given for timeout. When a function times out the function returns in error with errno set to EAGAIN. In the future this may change to an exception being thrown.

    Function Descriptions

    SM_FILE_T *
    sm_io_fopen(char *pathname, int flags)
    SM_FILE_T *
    sm_io_fopen(char *pathname, int flags, MODE_T mode)
    Open the file named by pathname, and associate a stream with it. The arguments are the same as for the open(2) system call.
    If memory could not be allocated, an exception is raised. If successful, an SM_FILE_T pointer is returned. Otherwise, NULL is returned and errno is set.

    SM_FILE_T *
    sm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool)
    Opens a file by type directed by info. Type is a filled-in SM_FILE_T structure from the following builtin list (descriptions below) or one specified by the program.
  • SmFtString
  • SmFtStdio
  • SmFtStdiofd
  • smioin *
  • smioout *
  • smioerr *
  • smiostdin *
  • smiostdout *
  • smiostderr *
  • SmFtSyslog

  • The above list of file types are already appropriately filled in. Those marked with a "*" are already open and may be used directly and immediately. For program specified types, to set the type argument easily and with minimal error the macro SM_IO_SET_TYPE should be used. The SM_FILE_T structure is fairly large, but only a small portion of it need to be initialized for a new type. See also "Writing Functions for a File Type".
    SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
    

    Timeout is set as described in the Timeouts section.
    Info is information that describes for the file type what is to be opened and any associated information. For a disk file this would be a file path; with a TCP connection this could be an a structure containing an IP address and port.
    Flags is a set of sm_io flags that describes how the file is to be interacted with:
  • SM_IO_RDWR - read and write
  • SM_IO_RDONLY - read only
  • SM_IO_WRONLY - write only
  • SM_IO_APPEND - allow write to EOF only
  • SM_IO_APPENDRW - allow read-write from EOF only
  • SM_IO_RDWRTR - read and write with truncation of file first
  • Rpool is the address of the rpool that this open is to be associated with. When the rpool is released then the close function for this file type will be automatically called to close the file for cleanup. If NULL is specified for rpool then the close function is not associated (attached) to an rpool.
    On cannot allocate memory, an exception is raised. If the type is invalid, sm_io_open will abort the process. On success an SM_FILE_T * pointer is returned. On failure the NULL pointer is returned and errno is set.

    int
    sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)
    For the open file sfp set the indicated information (what) to the new value (valp). This will make the change for this SM_FILE_T only. The file type that sfp originally belonged to will still be configured the same way (this is to prevent side-effect to other open's of the same file type, particularly with threads). The value of what will be file-type dependant since this function is one of the per file type setable functions. One value for what that is valid for all file types is SM_WHAT_VECTORS. This sets the currently open file with a new function vector set for open, close, etc. The new values are taken from valp a SM_FILE_T filled in by the used via the macro SM_IO_SET_TYPE (see and "Writing Functions for a File Type" for more information).
    On success 0 (zero) is returned. On failure -1 is returned and errno is set.

    int
    sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)
    For the open file sfp get the indicated information (what) and place the result in (valp). This will obtain information for SM_FILE_T only and may be different than the information for the file type it was originally opened as. The value of what will be file type dependant since this function is one of the per file type setable functions. One value for what that is valid for all file types is SM_WHAT_VECTORS. This gets from the currently open file a copy of the function vectors and stores them in valp a SM_FILE_T (see "Writing Functions for a File Type" for more information).
    On success 0 (zero) is returned. On failure -1 is returned and errno is set.

    void
    sm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2)
    Associate a read of fp1 with a data flush for fp2. If a read of fp1 discovers that there is no data available to be read, then fp2 will have it's data buffer flushed for writable data. It is assumed that fp1 is open for reading and fp2 is open for writing.
    On return the old file pointer associated with fp1 for flushing is returned. A return of NULL is no an error; this merely indicates no previous association.

    void
    sm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2)
    Associate the two file pointers for blocking/non-blocking mode changes. In the handling of timeouts sm_io may need to switch the mode of a file between blocking and non-blocking. If the underlying file descriptor has been duplicated with dup(2) and these descriptors are used by sm_io (for example with an SmFtStdiofd file type), then this API should be called to associate them. Otherwise odd behavior (i.e. errors) may result that is not consistently reproducable nor easily identifiable.

    int
    sm_io_close(SM_FILE_T *sfp, int timeout)
    Release all resources (file handles, memory, etc.) associated with the open SM_FILE_T sfp. If buffering is active then the buffer is flushed before any resources are released. Timeout is set as described in the Timeouts section. The first resources released after buffer flushing will be the buffer itself. Then the close function specified in the file type at open will be called. It is the responsibility of the close function to release any file type specific resources allocated and to call sm_io_close() for the next file type layer(s) that the current file type uses (if any).
    On success 0 (zero) is returned. On failure SM_IO_EOF is returned and errno is set.

    Description of Builtin File Types

    There are several builtin file types as mentioned in sm_io_open(). More file types may be added later.

    SmFtString
    Operates on a character string. SmFtString is a file type only. The string starts at the location 0 (zero) and ends at the last character. A read will obtain the requested number of characters if available; else as many as possible. A read will not terminate the read characters with a NULL ('\0'). A write will place the number of requested characters at the current location. To append to a string either the pointer must currently be at the end of the string or a seek done to position the pointer. The file type handles the space needed for the string. Thus space needed for the string will be grown automagically without the user worrying about space management.
    SmFtStdio
    A predefined SM_FILE_T structure with function vectors pointing to functions that result in the file-type behaving as the system stdio normally does. The info portion of the sm_io_open is the path of the file to be opened. Note that this file type does not interact with the system's stdio. Thus a program mixing system stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input and output.
    SmFtStdiofd
    A predefined SM_FILE_T structure with function vectors pointing to functions that result in the file-type behaving as the system stdio normally does. The info portion of the sm_io_open is a file descriptor (the value returned by open(2)). Note that this file type does not interact with the system's stdio. Thus a program mixing system stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input and output.
    smioin
    smioout
    smioerr
    The three types smioin, smioout and smioerr are grouped together. These three types perform in the same manner as stdio's stdin, stdout and stderr. These types are both the names and the file pointers. They are already open when a program starts (unless the parent explictly closed file descriptors 0, 1 and 2). Thus sm_io_open() should never be called for these types: the named file pointers should be used directly. Smioin and smioout are buffered by default. Smioerr is not buffered by default. Calls to stdio are safe to make when using these threesm_io file pointers. There is no interaction between sm_io and stdio. Hence, due to buffering, the sequence of input and output data from both sm_io and stdio at the same time may appear unordered. For coordination between sm_io and stdio use the three file pointers below (smiostdin, smiostdout, smiostderr).
    smiostdin
    smiostdout
    smiostderr
    The three types smiostdin, smioostdut and smiostderr are grouped together. These three types perform in the same manner as stdio's stdin, stdout and stderr. These types are both the names and file pointers. They are already open when a program starts (unless the parent explictly close file descriptors 0, 1 and 2). Thus sm_io_open() should never be called: the named file pointers should be used directly. Calls to stdio are safe to make when using these threesm_io file pointers though no code is shared between the two libaries. However, the input and output between sm_io and stdio is coordinated for these three file pointers: smiostdin, smiostdout and smiostderr are layered on-top-of the system's stdio. Smiostdin, smiostdout and Smiostderr are not buffered by default. Hence, due to buffering in stdio only, the sequence of input and output data from both sm_io and stdio at the same time will appear ordered. If sm_io buffering is turned on then the input and output can appear unordered or lost.
    SmFtSyslog
    This opens the channel to the system log. Reads are not allowed. Writes cannot be undone once they have left the sm_io buffer. The man pages for syslog(3) should be read for information on syslog.


    Writing Functions for a File Type

    When writing functions to create a file type a function needs to be created for each function vector in the SM_FILE_T structure that will be passed to sm_io_open() or sm_io_setinfo(). Otherwise the setting will be rejected and errno set to EINVAL. Each function should accept and handle the number and types of arguments as described in the portion of the SM_FILE_T structure shown below:

            int      (*open) __P((SM_FILE_T *fp, const void *, int flags,
                                  const void *rpool));
            int      (*close) __P((SM_FILE_T *fp));
            int      (*read)  __P((SM_FILE_T *fp, char *buf, size_t size));
            int      (*write) __P((SM_FILE_T *fp, const char *buf, size_t size));
            off_t    (*seek)  __P((SM_FILE_T *fp, off_t offset, int whence));
            int      (*getinfo) __P((SM_FILE_T *fp, int what, void *valp));
            int      (*setinfo) __P((SM_FILE_T *fp, int what, void *valp));
    

    The macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file type for an sm_io_open():

    SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
    

    where:
  • type - is the SM_FILE_T being filled-in
  • name - a human readable character string for human identification purposes
  • open - the vector to the open function
  • close - the vector to the close function
  • read - the vector to the read function
  • write - the vector to the write function
  • seek - the vector to the seek function
  • set - the vector to the set function
  • get - the vector to the get function
  • timeout - the default to be used for a timeout when SM_TIME_DEFAULT specified
  • You should avoid trying to change or use the other structure members of the SM_FILE_T. The file pointer content (internal structure members) of an active file should only be set and observed with the "info" functions. The two exceptions to the above statement are the structure members cookie and ival. Cookie is of type void * while ival is of type int. These two structure members exist specificly for your created file type to use. The sm_io functions will not change or set these two structure members; only specific file type will change or set these variables.

    For maintaining information privately about status for a file type the information should be encapsulated in a cookie. A cookie is an opaque type that contains information that is only known to the file type layer itself. The sm_io package will know nothing about the contents of the cookie; sm_io only maintains the location of the cookie so that it may be passed to the functions of a file type. It is up to the file type to determine what to do with the cookie. It is the responsibility of the file type's open to create the cookie and point the SM_FILE_T's cookie at the address of the cookie. It is the responsibility of close to clean up any resources that the cookie and instance of the file type have used.

    For the cookie to be passed to all members of a function type cleanly the location of the cookie must assigned during the call to open. The file type functions should not attempt to maintain the cookie internally since the file type may have serveral instances (file pointers).

    The SM_FILE_T's member ival may be used in a manner similar to cookie. It is not to be used for maintaining the file's offset or access status (other members do that). It is intended as a "light" reference.

    The file type vector functions are called by the sm_io_*() functions after sm_io processing has occurred. The sm_io processing validates SM_FILE_T's and may then handle the call entirely itself or pass the request to the file type vector functions.

    All of the "int" functions should return -1 (minus one) on failure and 0 (zero) or greater on success. Errno should be set to provide diagnostic information to the caller if it has not already been set by another function the file type function used.

    Examples are a wonderful manner of clarifying details. Below is an example of an open function.

    This shows the setup.

    SM_FILE_T *fp;
    SM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite,
    				myseek, myget, myset, SM_TIME_FOREVER);
    
    fp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL);
    
    if (fp == NULL)
    	return(-1);
    
    The above code open's a file of type "my_type". The info is set to a string "data". "data" may be the name of a file or have some special meaning to the file type. For sake of the example, we will have it be the name of a file in the home directory of the user running the program. Now the only file type function that is dependent on this information will be the open function.
    We have also specified read-only access (SM_IO_RDONLY) and that no rpool will be used. The timeout has been set to 1000 milliseconds which directs that the file and all associated setup should be done within 1000 milliseconds or return that the function erred (with errno==EAGAIN).
    int myopen(fp, info, flags, rpools)
    	SM_FILE_T *fp;
            const void *info; 
            int flags;
            void *rpool;
    {
    	/*
    	**  now we could do the open raw (i.e with read(2)), but we will
    	**  use file layering instead. We will use the stdio file
    	**  type (different than the system's stdio).
    	*/
    	struct passwd *pw;
    	char path[PATH_MAX];
    
    	pw = getpwuid(getuid());
    	sm_io_snprintf(path, PATH_MAX, "%s/%s", pw->pw_dir, info);
    
    	/*
    	**  Okay. Now the path pass-in has been prefixed with the
    	**  user's HOME directory. We'll call the regular stdio (SmFtStdio)
    	**  now to handle the rest of the open.
    	*/
    	fp->cookie = sm_io_open(SmFtStdio, path, flags, rpools);
    	if (fp->cookie == NULL)
    		return(-1) /* errno set by sm_io_open call */
    	else
    		return(0);
    }
    
    Later on when a write is performed the function mywrite will be invoked. To match the above myopen, mywrite could be written as:
    int mywrite(fp, buf, size)
    	SM_FILE_T *fp;
            char *buf;
            size_t size;
    {
    	/*
    	**  As an example, we can change, modify, refuse, filter, etc.
    	**  the content being passed through before we ask the SmFtStdio
    	**  to do the actual write.
    	**  This example is very simple and contrived, but this keeps it
    	**  clear.
    	*/
    	if (size == 0)
    		return(0); /* why waste the cycles? */
    	if (*buf == 'X')
    		*buf = 'Y';
    
    	/*
    	**  Note that the file pointer passed to the next level is the
    	**  one that was stored in the cookie during the open.
    	*/
    	return(sm_io_write(fp->cookie, buf, size));
    }
    
    As a thought-exercise for the fair reader: how would you modify the above two functions to make a "tee". That is the program will call sm_io_open or sm_io_write and two or more files will be opened and written to. (Hint: create a cookie to hold two or more file pointers).




    libsm sm_io default API definition

    Introduction

    A number of sm_io API's perform similar to their stdio counterparts (same name as when the "sm_io_" is removed). One difference between sm_io and stdio functions is that if a "file pointer" (FILE/SM_FILE_T) is one of the arguments for the function, then it is now the first argument. Sm_io is standardized so that when a file pointer is one of the arguments to function then it will always be the first arguement. Many of the sm_io function take a timeout argument (see Timeouts).

    The API you have selected is one of these. Please consult the appropriate stdio man page for now.

    dk-milter-1.0.0.dfsg/libsm/gen.html0000644000175000017500000000161607214252626016643 0ustar madhackmadhack libsm : General Definitions Back to libsm overview

    libsm : General Definitions


    $Id: gen.html,v 1.5 2000/12/08 21:41:42 ca Exp $

    Introduction

    The header file <sm/gen.h> contains general definitions that are used by every other header file in libsm.

    Synopsis

    #include <sm/gen.h>
    
    #define NULL		((void*)0)
    
    typedef int bool;
    #define false	0
    #define true	1
    
    #define SM_MAX(a, b)	((a) > (b) ? (a) : (b))
    #define SM_MIN(a, b)	((a) < (b) ? (a) : (b))
    
    /*
    **  The following types can be accessed and updated atomically.
    **  This is relevant in the context of signal handlers and threads.
    */
    typedef some signed integral type SM_ATOMIC_INT_T;
    typedef some unsigned integral type SM_ATOMIC_UINT_T;
    
    dk-milter-1.0.0.dfsg/libsm/t-smstdio.c0000644000175000017500000000306607347306541017277 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-smstdio.c,v 1.11 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include int main(argc, argv) int argc; char **argv; { FILE *stream; SM_FILE_T *fp; char buf[128]; size_t n; static char testmsg[] = "hello, world\n"; sm_test_begin(argc, argv, "test sm_io_stdioopen, smiostdin, smiostdout"); stream = fopen("t-smstdio.1", "w"); SM_TEST(stream != NULL); fp = sm_io_stdioopen(stream, "w"); SM_TEST(fp != NULL); (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", testmsg); sm_io_close(fp, SM_TIME_DEFAULT); #if 0 /* ** stream should now be closed. This is a tricky way to test ** if it is still open. Alas, it core dumps on Linux. */ fprintf(stream, "oops! stream is still open!\n"); fclose(stream); #endif stream = fopen("t-smstdio.1", "r"); SM_TEST(stream != NULL); fp = sm_io_stdioopen(stream, "r"); SM_TEST(fp != NULL); n = sm_io_read(fp, SM_TIME_DEFAULT, buf, sizeof(buf)); if (SM_TEST(n == strlen(testmsg))) { buf[n] = '\0'; SM_TEST(strcmp(buf, testmsg) == 0); } #if 0 /* ** Copy smiostdin to smiostdout ** gotta think some more about how to test smiostdin and smiostdout */ while ((c = sm_io_getc(smiostdin)) != SM_IO_EOF) sm_io_putc(smiostdout, c); #endif return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/debug.html0000644000175000017500000001726507427014360017164 0ustar madhackmadhack libsm : Debugging and Tracing Back to libsm overview

    libsm : Debugging and Tracing


    $Id: debug.html,v 1.9 2002/02/02 16:50:56 ca Exp $

    Introduction

    The debug and trace package provides abstractions for writing trace messages, and abstractions for enabling and disabling debug and trace code at run time.

    Sendmail 8.11 and earlier has a -d option which lets you turn on debug and trace code. Debug categories are integers from 0 to 99, with the sole exception of "ANSI", which is a named debug category.

    The libsm debug package supports named debug categories. Debug category names have the form of C identifiers. For example, sm_trace_heap controls the output of trace messages from the sm heap package, while sm_check_heap controls the argument validity checking and memory leak detection features of the sm heap package.

    In sendmail 8.12, the -d flag is generalized to support both the original style numeric categories, for backwards compatibility, and the new style named categories implemented by libsm. With this change, "-dANSI" is implemented using a libsm named debug category. You will be able to set a collection of named debug categories to the same activation level by specifying a glob pattern. For example,

    -dANSI
    sets the named category "ANSI" to level 1,
    -dfoo_*.3
    sets all named categories matching the glob pattern "foo_*" to level 3,
    -d0-99.1
    sets the numeric categories 0 through 99 to level 1, and
    -dANSI,foo_*.3,0-99.1
    does all of the above.

    Synopsis

    #include <sm/debug.h>
    
    /*
    **  abstractions for printing trace messages
    */
    void sm_dprintf(char *fmt, ...)
    void sm_dflush()
    void sm_debug_setfile(SM_FILE_T *)
    
    /*
    **  abstractions for setting and testing debug activation levels
    */
    void sm_debug_addsettings(char *settings)
    void sm_debug_addsetting(char *pattern, int level)
    
    typedef struct sm_debug SM_DEBUG_T;
    SM_DEBUG_T dbg = SM_DEBUG_INITIALIZER("name", "@(#)$Debug: name - description $");
    
    bool sm_debug_active(SM_DEBUG_T *debug, int level)
    int  sm_debug_level(SM_DEBUG_T *debug)
    bool sm_debug_unknown(SM_DEBUG_T *debug)
    

    Naming Conventions

    All debug categories defined by libsm have names of the form sm_*. Debug categories that turn on trace output have names of the form *_trace_*. Debug categories that turn on run time checks have names of the form *_check_*. Here are all of the libsm debug categories as of March 2000:
    Variable name Category name Meaning
    SmExpensiveAssert sm_check_assert enable expensive SM_ASSERT checking
    SmExpensiveRequire sm_check_require enable expensive SM_REQUIRE checking
    SmExpensiveEnsure sm_check_ensure enable expensive SM_ENSURE checking
    SmHeapTrace sm_trace_heap trace sm_{malloc,realloc,free} calls
    SmHeapCheck sm_check_heap enable checking and memory leak detection in sm_{malloc,realloc,free}

    Function Reference

    SM_DEBUG_INITIALIZER
    To create a new debug category, use the SM_DEBUG_INITIALIZER macro to initialize a static variable of type SM_DEBUG_T. For example,
    SM_DEBUG_T ANSI_debug = SM_DEBUG_INITIALIZER("ANSI",
    	    "@(#)$Debug: ANSI - enable reverse video in debug output $");
    
    There is no centralized table of category names that needs to be edited in order to add a new debug category. The sole purpose of the second argument to SM_DEBUG_INITIALIZER is to provide an easy way to find out what named debug categories are present in a sendmail binary. You can use:
    ident /usr/sbin/sendmail | grep Debug
    
    or:
    what /usr/sbin/sendmail | grep Debug
    
    void sm_debug_addsetting(char *pattern, int level)
    All debug categories default to activation level 0, which means no activity. This function updates an internal database of debug settings, setting all categories whose name matches the specified glob pattern to the specified activation level. The level argument must be >= 0.

    void sm_debug_addsettings(char *settings)
    This function is used to process the -d command line option of Sendmail 9.x, and of other programs that support the setting of named debug categories. The settings argument is a comma-separated list of settings; each setting is a glob pattern, optionally followed by a '.' and a decimal numeral.

    bool sm_debug_active(SM_DEBUG_T *debug, int level)
    This macro returns true if the activation level of the statically initialized debug structure debug is >= the specified level. The test is performed very efficiently: in the most common case, when the result is false, only a single comparison operation is performed.

    This macro performs a function call only if the debug structure has an unknown activation level. All debug structures are in this state at the beginning of program execution, and after a call to sm_debug_addsetting.

    int sm_debug_level(SM_DEBUG_T *debug)
    This macro returns the activation level of the specified debug structure. The comparison
    sm_debug_level(debug) >= level
    
    is slightly less efficient than, but otherwise semantically equivalent to
    sm_debug_active(debug, level)
    

    bool sm_debug_unknown(SM_DEBUG_T *debug)
    This macro returns true if the activation level of the specified debug structure is unknown. Here is an example of how the macro might be used:
    if (sm_debug_unknown(&FooDebug))
    {
    	if (sm_debug_active(&FooDebug, 1))
    	{
    		... perform some expensive data structure initializations
    		... in order to enable the "foo" debugging mechanism
    	}
    	else
    	{
    		... disable the "foo" debugging mechanism
    	}
    }
    
    The purpose of using sm_debug_unknown in the above example is to avoid performing the expensive initializations each time through the code. So it's a performance hack. A debug structure is in the "unknown" state at the beginning of program execution, and after a call to sm_debug_addsetting. A side effect of calling sm_debug_active is that the activation level becomes known.

    void sm_dprintf(char *fmt, ...)
    This function is used to print a debug message. The standard idiom is
    if (sm_debug_active(&BarDebug, 1))
    	sm_dprintf("bar: about to test tensile strength of bar %d\n", i);
    

    void sm_dflush()
    Flush the debug output stream.

    void sm_debug_setfile(SM_FILE_T *file)
    This function lets you specify where debug output is printed. By default, debug output is written to standard output.

    We want to allow you to direct debug output to syslog. The current plan is to provide a standard interface for creating an SM_FILE_T object that writes to syslog.

    dk-milter-1.0.0.dfsg/libsm/t-path.c0000644000175000017500000000212707347306541016546 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-path.c,v 1.8 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include int main(argc, argv) int argc; char **argv; { char *r; sm_test_begin(argc, argv, "test path handling"); SM_TEST(sm_path_isdevnull(SM_PATH_DEVNULL)); #ifdef WIN32 r = "nul"; SM_TEST(sm_path_isdevnull(r)); r = "NUL"; SM_TEST(sm_path_isdevnull(r)); r = "/dev/nul"; SM_TEST(sm_path_isdevnull(r)); r = "\\dev\\nul"; SM_TEST(sm_path_isdevnull(r)); r = "/DEV/NUL"; SM_TEST(sm_path_isdevnull(r)); r = "\\DEV\\NUL"; SM_TEST(sm_path_isdevnull(r)); r = "/dev/null"; SM_TEST(!sm_path_isdevnull(r)); #else r = "/dev/null"; SM_TEST(sm_path_isdevnull(r)); r = "/nev/dull"; SM_TEST(!sm_path_isdevnull(r)); r = "nul"; SM_TEST(!sm_path_isdevnull(r)); #endif return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/shm.c0000644000175000017500000001117310265564164016141 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2003, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: shm.c,v 1.19 2005/07/14 22:34:28 ca Exp $") #if SM_CONF_SHM # include # include # include # include # include # ifdef WIN32 # include # include "sm/errstring.h" /* ** Some internal non-exposable handles for a memory-mapped file, ** mapping object and map view object. */ static HANDLE hFile = NULL; /* handle to the map file */ static HANDLE hMapObject = NULL; /* handle to map object */ static void *pSharedMem = NULL; /* pointer to the shared memory */ static char shm_pathname[_MAX_PATH]; # endif /* WIN32 */ /* ** SM_SHMSTART -- initialize shared memory segment. ** ** Parameters: ** key -- key for shared memory. ** size -- size of segment. ** shmflag -- initial flags. ** shmid -- pointer to return id. ** owner -- create segment. ** ** Returns: ** pointer to shared memory segment, ** NULL on failure. ** ** Side Effects: ** attaches shared memory segment. */ # ifndef WIN32 void * sm_shmstart(key, size, shmflg, shmid, owner) key_t key; int size; int shmflg; int *shmid; bool owner; { int save_errno; void *shm = SM_SHM_NULL; /* default: user/group accessible */ if (shmflg == 0) shmflg = SHM_R|SHM_W|(SHM_R>>3)|(SHM_W>>3); if (owner) shmflg |= IPC_CREAT|IPC_EXCL; *shmid = shmget(key, size, shmflg); if (*shmid < 0) goto error; shm = shmat(*shmid, (void *) 0, 0); if (shm == SM_SHM_NULL) goto error; return shm; error: save_errno = errno; if (shm != SM_SHM_NULL || *shmid >= 0) sm_shmstop(shm, *shmid, owner); *shmid = SM_SHM_NO_ID; errno = save_errno; return (void *) 0; } # else /* WIN32 */ void * sm_shmstart(key_t key, int size, int shmflg, int * shmid, BOOL owner) { unsigned long saved_errno; (void) sm_snprintf(shm_pathname, sizeof shm_pathname, "%ssendmail_%ld.dat", get_shm_path(), (long) key); /* Create or open the shared memory map file */ hFile = CreateFile(shm_pathname, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, owner ? CREATE_NEW : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0); if (hFile == INVALID_HANDLE_VALUE) goto error; /* Create file mapping */ hMapObject = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, size, NULL); if (hMapObject == NULL) goto error; /* Map to process address space */ pSharedMem = MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, size); if (pSharedMem == NULL) goto error; *shmid = 1; return pSharedMem; error: saved_errno = sm_win32_geterror(); (void) sm_shmstop(pSharedMem, *shmid, owner); errno = saved_errno; return NULL; } # endif /* WIN32 */ /* ** SM_SHMSTOP -- stop using shared memory segment. ** ** Parameters: ** shm -- pointer to shared memory. ** shmid -- id. ** owner -- delete segment. ** ** Returns: ** 0 on success. ** < 0 on failure. ** ** Side Effects: ** detaches (and maybe removes) shared memory segment. */ # ifndef WIN32 int sm_shmstop(shm, shmid, owner) void *shm; int shmid; bool owner; { int r; if (shm != SM_SHM_NULL && (r = shmdt(shm)) < 0) return r; if (owner && shmid >= 0 && (r = shmctl(shmid, IPC_RMID, NULL)) < 0) return r; return 0; } # else /* WIN32 */ int sm_shmstop(void *shm, int shmid, bool owner) { /* Unmap file view */ if (shm != NULL && !UnmapViewOfFile(shm)) goto error; if (hMapObject != NULL && !CloseHandle(hMapObject)) goto error; if (hFile != NULL && hFile != INVALID_HANDLE_VALUE && !CloseHandle(hFile)) goto error; if (owner && shmid >= 0) { assert(strlen(shm_pathname) != 0); if (!DeleteFile(shm_pathname)) goto error; } return 0; error: errno = sm_win32_geterror(); return -1; } # endif /* WIN32 */ /* ** SM_SHMSETOWNER -- set owner/group/mode of shared memory segment. ** ** Parameters: ** shmid -- id. ** uid -- uid to use ** gid -- gid to use ** mode -- mode to use ** ** Returns: ** 0 on success. ** < 0 on failure. */ int sm_shmsetowner(shmid, uid, gid, mode) int shmid; uid_t uid; gid_t gid; mode_t mode; { # ifndef WIN32 int r; struct shmid_ds shmid_ds; memset(&shmid_ds, 0, sizeof(shmid_ds)); if ((r = shmctl(shmid, IPC_STAT, &shmid_ds)) < 0) return r; shmid_ds.shm_perm.uid = uid; shmid_ds.shm_perm.gid = gid; shmid_ds.shm_perm.mode = mode; if ((r = shmctl(shmid, IPC_SET, &shmid_ds)) < 0) return r; # endif /* WIN32 */ return 0; } #endif /* SM_CONF_SHM */ dk-milter-1.0.0.dfsg/libsm/exc.html0000644000175000017500000005642310446026730016653 0ustar madhackmadhack libsm : Exception Handling Back to libsm overview

    libsm : Exception Handling


    $Id: exc.html,v 1.13 2006/06/20 17:18:16 ca Exp $

    Introduction

    The exception handling package provides the facilities that functions in libsm use to report errors. Here are the basic concepts:
    1. When a function detects an exceptional condition at the library level, it does not print an error message, or call syslog, or exit the program. Instead, it reports the error back to its caller, and lets the caller decide what to do. This improves modularity, because error handling is separated from error reporting.

    2. Errors are not represented by a single integer error code, because then you can't represent everything that an error handler might need to know about an error by a single integer. Instead, errors are represented by exception objects. An exception object contains an exception code and an array of zero or more exception arguments. The exception code is a string that specifies what kind of exception this is, and the arguments may be integers, strings or exception objects.

    3. Errors are not reported using a special return value, because if you religiously check for error returns from every function call that could fail, then most of your code ends up being error handling code. Errors are reported by raising an exception. When an exception is raised, we unwind the call stack until we find an exception handler. If the exception is not handled, then we print the exception on stderr and exit the program.

    Synopsis

    #include <sm/exc.h>
    
    typedef struct sm_exc_type SM_EXC_TYPE_T;
    typedef struct sm_exc SM_EXC_T;
    typedef union sm_val SM_VAL_T;
    
    /*
    **  Exception types
    */
    
    extern const char SmExcTypeMagic[];
    
    struct sm_exc_type
    {
    	const char	*sm_magic;
    	const char	*etype_category;
    	const char	*etype_argformat;
    	void 		(*etype_print)(SM_EXC_T *exc, SM_FILE_T *stream);
    	const char	*etype_printcontext;
    };
    
    extern const SM_EXC_TYPE_T SmEtypeOs;
    extern const SM_EXC_TYPE_T SmEtypeErr;
    
    void
    sm_etype_printf(
    	SM_EXC_T *exc,
    	SM_FILE_T *stream);
    
    /*
    **  Exception objects
    */
    
    extern const char SmExcMagic[];
    
    union sm_val
    {
    	int		v_int;
    	long		v_long;
    	char		*v_str;
    	SM_EXC_T	*v_exc;
    };
    
    struct sm_exc
    {
    	const char		*sm_magic;
    	size_t			exc_refcount;
    	const SM_EXC_TYPE_T	*exc_type;
    	SM_VAL_T		*exc_argv;
    };
    
    SM_EXC_T *
    sm_exc_new_x(
    	const SM_EXC_TYPE_T *type,
    	...);
    
    SM_EXC_T *
    sm_exc_addref(
    	SM_EXC_T *exc);
    
    void
    sm_exc_free(
    	SM_EXC_T *exc);
    
    bool
    sm_exc_match(
    	SM_EXC_T *exc,
    	const char *pattern);
    
    void
    sm_exc_print(
    	SM_EXC_T *exc,
    	SM_FILE_T *stream);
    
    void
    sm_exc_write(
    	SM_EXC_T *exc,
    	SM_FILE_T *stream);
    
    void
    sm_exc_raise_x(
    	SM_EXC_T *exc);
    
    void
    sm_exc_raisenew_x(
    	const SM_EXC_TYPE_T *type,
    	...);
    
    /*
    **  Ensure that cleanup code is executed,
    **  and/or handle an exception.
    */
    SM_TRY
    	Block of code that may raise an exception.
    SM_FINALLY
    	Cleanup code that may raise an exception.
    	This clause is guaranteed to be executed even if an exception is
    	raised by the SM_TRY clause or by an earlier SM_FINALLY clause.
    	You may have 0 or more SM_FINALLY clauses.
    SM_EXCEPT(exc, pattern)
    	Exception handling code, triggered by an exception
    	whose category matches 'pattern'.
    	You may have 0 or more SM_EXCEPT clauses.
    SM_END_TRY
    

    Overview

    An exception is an object which represents an exceptional condition, which might be an error condition like "out of memory", or might be a condition like "end of file".

    Functions in libsm report errors and other unusual conditions by raising an exception, rather than by returning an error code or setting a global variable such as errno. If a libsm function is capable of raising an exception, its name ends in "_x". (We do not raise an exception when a bug is detected in the program; instead, we terminate the program using sm_abort. See the assertion package for details.)

    When you are using the libsm exception handling package, you are using a new programming paradigm. You will need to abandon some of the programming idioms you are accustomed to, and switch to new idioms. Here is an overview of some of these idioms.

    1. When a function is unable to complete its task because of an exceptional condition, it reports this condition by raising an exception.

      Here is an example of how to construct an exception object and raise an exception. In this example, we convert a Unix system error into an exception.

      fd = open(path, O_RDONLY);
      if (fd == -1)
      	sm_exc_raise_x(sm_exc_new_x(&SmEtypeOs, errno, "open", "%s", path));
      
      Because the idiom sm_exc_raise_x(sm_exc_new_x(...)) is so common, it can be abbreviated as sm_exc_raisenew_x(...).

    2. When you detect an error at the application level, you don't call a function like BSD's errx, which prints an error message on stderr and exits the program. Instead, you raise an exception. This causes cleanup code in surrounding exception handlers to be run before the program exits. For example, instead of this:
      errx(1, "%s:%d: syntax error", filename, lineno);
      
      use this:
      sm_exc_raisenew_x(&SmEtypeErr, "%s:%d: syntax error", filename, lineno);
      
      The latter code raises an exception, unwinding the call stack and executing cleanup code. If the exception is not handled, then the exception is printed to stderr and the program exits. The end result is substantially the same as a call to errx.

    3. The SM_TRY ... SM_FINALLY ... control structure ensures that cleanup code is executed and resources are released in the presence of exceptions.

      For example, suppose that you have written the following code:

      rpool = sm_rpool_new_x(&SmRpoolRoot, 0);
      ... some code ...
      sm_rpool_free_x(rpool);
      
      If any of the functions called within "... some code ..." have names ending in _x, then it is possible that an exception will be raised, and if that happens, then "rpool" will not be freed. And that's a bug. To fix this bug, change your code so it looks like this:
      rpool = sm_rpool_new_x(&SmRpoolRoot, 0);
      SM_TRY
      	... some code that can raise an exception ...
      SM_FINALLY
      	sm_rpool_free_x(rpool);
      SM_END_TRY
      
    4. The SM_TRY ... SM_EXCEPT ... control structure handles an exception. Unhandled exceptions terminate the program. For example, here is a simple exception handler that traps all exceptions, and prints the exceptions:
      SM_TRY
      	/* code that can raise an exception */
      	...
      SM_EXCEPT(exc, "*")
      	/* catch all exceptions */
      	sm_exc_print(exc, stderr);
      SM_END_TRY
      
      Exceptions are reference counted. The SM_END_TRY macro contains a call to sm_exc_free, so you don't normally need to worry about freeing an exception after handling it. In the rare case that you want an exception to outlive an exception handler, then you increment its reference count by calling sm_exc_addref.

    5. The second argument of the SM_EXCEPT macro is a glob pattern which specifies the types of exceptions that are to be handled. For example, you might want to handle an end-of-file exception differently from other exceptions. Here's how you do that:
      SM_TRY
      	/* code that might raise end-of-file, or some other exception */
      	...
      SM_EXCEPT(exc, "E:sm.eof")
      	/* what to do if end-of-file is encountered */
      	...
      SM_EXCEPT(exc, "*")
      	/* what to do if some other exception is raised */
      	...
      SM_END_TRY
      

    Exception Values

    In traditional C code, errors are usually denoted by a single integer, such as errno. In practice, errno does not carry enough information to describe everything that an error handler might want to know about an error. And the scheme is not very extensible: if several different packages want to add additional error codes, it is hard to avoid collisions.

    In libsm, an exceptional condition is described by an object of type SM_EXC_T. An exception object is created by specifying an exception type and a list of exception arguments.

    The exception arguments are an array of zero or more values. The values may be a mixture of ints, longs, strings, and exceptions. In the SM_EXC_T structure, the argument vector is represented by SM_VAL_T *exc_argv, where SM_VAL_T is a union of the possible argument types. The number and types of exception arguments is determined by the exception type.

    An exception type is a statically initialized const object of type SM_EXC_TYPE_T, which has the following members:

    const char *sm_magic
    A pointer to SmExcTypeMagic.

    const char *etype_category
    This is a string of the form "class:name".

    The class is used to assign the exception type to one of a number of broad categories of exceptions on which an exception handler might want to discriminate. I suspect that what we want is a hierarchical taxonomy, but I don't have a full design for this yet. For now, I am recommending the following classes:

    "F"
    A fatal error has occurred. This is an error that prevents the application from making any further progress, so the only recourse is to raise an exception, execute cleanup code as the stack is unwound, then exit the application. The out-of-memory exception raised by sm_malloc_x has category "F:sm.heap" because sendmail commits suicide (after logging the error and cleaning up) when it runs out of memory.
    "E"
    The function could not complete its task because an error occurred. (It might be useful to define subclasses of this category, in which case our taxonony becomes a tree, and 'F' becomes a subclass of 'E'.)
    "J"
    This exception is being raised in order to effect a non-local jump. No error has occurred; we are just performing the non-local equivalent of a continue, break or return.
    "S"
    The function was interrupted by a signal. Signals are not errors because they occur asynchronously, and they are semantically unrelated to the function that happens to be executing when the signal arrives. Note that it is extremely dangerous to raise an exception from a signal handler. For example, if you are in the middle of a call to malloc, you might corrupt the heap.
    Eric's libsm paper defines "W", "D" and "I" for Warning, Debug and Informational: I suspect these categories only make sense in the context of Eric's 1985 exception handling system which allowed you to raise conditions without terminating the calling function.

    The name uniquely identifies the exception type. I recommend a string of the form library.package.detail.

    const char *etype_argformat
    This is an array of single character codes. Each code indicates the type of one of the exception arguments. sm_exc_new_x uses this string to decode its variable argument list into an exception argument vector. The following type codes are supported:
    i
    The exception argument has type int.
    l
    The exception argument has type long.
    e
    The exception argument has type SM_EXC_T*. The value may either be NULL or a pointer to an exception. The pointer value is simply copied into the exception argument vector.
    s
    The exception argument has type char*. The value may either be NULL or a pointer to a character string. In the latter case, sm_exc_new_x will make a copy of the string.
    r
    The exception argument has type char*. sm_exc_new_x will read a printf-style format string argument followed by a list of printf arguments from its variable argument list, and convert these into a string. This type code can only occur as the last element of exc_argformat.

    void (*etype_print)(SM_EXC_T *exc, SM_FILE_T *stream)
    This function prints an exception of the specified type onto an output stream. The final character printed is not a newline.

    Standard Exceptions and Exception Types

    Libsm defines one standard exception value, SmHeapOutOfMemory. This is a statically initialized const variable, because it seems like a bad idea to dynamically allocate an exception object to report a low memory condition. This exception has category "F:sm.heap". If you need to, you can explicitly raise this exception with sm_exc_raise_x(&SmHeapOutOfMemory).

    Statically initialized exception values cannot contain any run-time parameters, so the normal case is to dynamically allocate a new exception object whenever you raise an exception. Before you can create an exception, you need an exception type. Libsm defines the following standard exception types.

    SmEtypeOs
    This represents a generic operating system error. The category is "E:sm.os". The argformat is "isr", where argv[0] is the value of errno after a system call has failed, argv[1] is the name of the function (usually a system call) that failed, and argv[2] is either NULL or a character string which describes some of the arguments to the failing system call (usually it is just a file name). Here's an example of raising an exception:
    fd = open(filename, O_RDONLY);
    if (fd == -1)
    	sm_exc_raisenew_x(&SmEtypeOs, errno, "open", "%s", filename);
    
    If errno is ENOENT and filename is "/etc/mail/snedmail.cf", then the exception raised by the above code will be printed as
    /etc/mail/snedmail.cf: open failed: No such file or directory
    
    SmEtypeErr
    This represents a generic error. The category is "E:sm.err", and the argformat is "r". You can use it in application contexts where you are raising an exception for the purpose of terminating the program. You know the exception won't be handled, so you don't need to worry about packaging the error for later analysis by an exception handler. All you need to specify is the message string that will be printed to stderr before the program exits. For example,
    sm_exc_raisenew_x(&SmEtypeErr, "name lookup failed: %s", name);
    

    Custom Exception Types

    If you are writing a library package, and you need to raise exceptions that are not standard Unix system errors, then you need to define one or more new exception types.

    Every new exception type needs a print function. The standard print function sm_etype_printf is all you need in the majority of cases. It prints the etype_printcontext string of the exception type, substituting occurrences of %0 through %9 with the corresponding exception argument. If exception argument 3 is an int or long, then %3 will print the argument in decimal, and %o3 or %x3 will print it in octal or hex.

    In the following example, I will assume that your library package implements regular expressions, and can raise 5 different exceptions. When compiling a regular expression, 3 different syntax errors can be reported:

    • unbalanced parenthesis
    • unbalanced bracket
    • missing argument for repetition operator
    Whenever one of these errors is reported, you will also report the index of the character within the regex string at which the syntax error was detected. The fourth exception is raised if a compiled regular expression is invalid: this exception has no arguments. The fifth exception is raised if the package runs out of memory: for this, you use the standard SmHeapOutOfMemory exception.

    The obvious approach is to define 4 separate exception types. Here they are:

    /* print a regular expression syntax error */
    void
    rx_esyntax_print(SM_EXC_T *exc, SM_FILE_T *stream)
    {
    	sm_io_fprintf(stream, "rx syntax error at character %d: %s",
    		exc->exc_argv[0].v_int,
    		exc->exc_type->etype_printcontext);
    }
    SM_EXC_TYPE_T RxSyntaxParen = {
    	SmExcTypeMagic,
    	"E:mylib.rx.syntax.paren",
    	"i",
    	rx_esyntax_print,
    	"unbalanced parenthesis"
    };
    SM_EXC_TYPE_T RxSyntaxBracket = {
    	SmExcTypeMagic,
    	"E:mylib.rx.syntax.bracket",
    	"i",
    	rx_esyntax_print,
    	"unbalanced bracket"
    };
    SM_EXC_TYPE_T RxSyntaxMissingArg = {
    	SmExcTypeMagic,
    	"E:mylib.rx.syntax.missingarg",
    	"i",
    	rx_esyntax_print,
    	"missing argument for repetition operator"
    };
    
    SM_EXC_TYPE_T RxRunCorrupt = {
    	SmExcTypeMagic,
    	"E:mylib.rx.run.corrupt",
    	"",
    	sm_etype_printf,
    	"rx runtime error: compiled regular expression is corrupt"
    };
    

    With the above definitions, you can raise a syntax error reporting an unbalanced parenthesis at string offset i using:

    sm_exc_raisenew_x(&RxSyntaxParen, i);
    
    If i==42 then this exception will be printed as:
    rx syntax error at character 42: unbalanced parenthesis
    
    An exception handler can provide special handling for regular expression syntax errors using this code:
    SM_TRY
    	... code that might raise an exception ...
    SM_EXCEPT(exc, "E:mylib.rx.syntax.*")
    	int i = exc->exc_argv[0].v_int;
    	... handle a regular expression syntax error ...
    SM_END_TRY
    

    External requirements may force you to define an integer code for each error reported by your package. Or you may be wrapping an existing package that works this way. In this case, it might make sense to define a single exception type, patterned after SmEtypeOs, and include the integer code as an exception argument.

    Your package might intercept an exception E generated by a lower level package, and then reclassify it as a different expression E'. For example, a package for reading a configuration file might reclassify one of the regular expression syntax errors from the previous example as a configuration file syntax error. When you do this, the new exception E' should include the original exception E as an exception parameter, and the print function for exception E' should print the high level description of the exception (eg, "syntax error in configuration file %s at line %d\n"), then print the subexception that is stored as an exception parameter.

    Function Reference

    SM_EXC_T *sm_exc_new_x(const SM_EXC_TYPE_T *type, ...)
    Create a new exception. Raise an exception on heap exhaustion. The new exception has a reference count of 1.

    A list of zero or more exception arguments follows the exception type; these are copied into the new exception object. The number and types of these arguments is determined by type->etype_argformat.

    Note that there is no rpool argument to sm_exc_new_x. Exceptions are allocated directly from the heap. This is because exceptions are normally raised at low levels of abstraction and handled at high levels. Because the low level code typically has no idea of how or at what level the exception will be handled, it also has no idea of which resource pool, if any, should own the exception.

    SM_EXC_T *sm_exc_addref(SM_EXC_T *exc)
    Increment the reference count of an exception. Return the first argument.

    void sm_exc_free(SM_EXC_T *exc)
    Decrement the reference count of an exception. If it reaches 0, free the exception object.

    bool sm_exc_match(SM_EXC_T *exc, const char *pattern)
    Compare the exception's category to the specified glob pattern, return true if they match.

    void sm_exc_print(SM_EXC_T *exc, SM_FILE_T *stream)
    Print the exception on the stream as a sequence of one or more newline terminated lines.

    void sm_exc_write(SM_EXC_T *exc, SM_FILE_T *stream)
    Write the exception on the stream without a terminating newline.

    void sm_exc_raise_x(SM_EXC_T *exc)
    Raise the exception. This function does not return to its caller.

    void sm_exc_raisenew_x(const SM_EXC_TYPE_T *type, ...)
    A short form for sm_exc_raise_x(sm_exc_new_x(type,...)).

    Macro Reference

    The SM_TRY ... SM_END_TRY control structure ensures that cleanup code is executed in the presence of exceptions, and permits exceptions to be handled.
    SM_TRY
    	A block of code that may raise an exception.
    SM_FINALLY
    	Cleanup code that may raise an exception.
    	This code is guaranteed to be executed whether or not
    	an exception was raised by a previous clause.
    	You may have 0 or more SM_FINALLY clauses.
    SM_EXCEPT(e, pat)
    	Exception handling code, which is triggered by an exception
    	whose category matches the glob pattern 'pat'.
    	The exception value is bound to the local variable 'e'.
    	You may have 0 or more SM_EXCEPT clauses.
    SM_END_TRY
    
    First, the SM_TRY clause is executed, then each SM_FINALLY clause is executed in sequence. If one or more of these clauses was terminated by an exception, then the first such exception is remembered, and the other exceptions are lost. If no exception was raised, then we are done. Otherwise, each of the SM_EXCEPT clauses is examined in sequence. and the first SM_EXCEPT clause whose pattern argument matches the exception (see sm_exc_match) is executed. If none of the SM_EXCEPT clauses matched the exception, or if there are no SM_EXCEPT clauses, then the remembered exception is re-raised.

    SM_TRY .. SM_END_TRY clauses may be nested arbitrarily.

    It is illegal to jump out of a SM_TRY or SM_FINALLY clause using goto, break, continue, return or longjmp. If you do this, you will corrupt the internal exception handling stack. You can't use break or continue in an SM_EXCEPT clause; these are reserved for use by the implementation. It is legal to jump out of an SM_EXCEPT clause using goto or return; however, in this case, you must take responsibility for freeing the exception object.

    The SM_TRY and SM_FINALLY macros contain calls to setjmp, and consequently, they suffer from the limitations imposed on setjmp by the C standard. Suppose you declare an auto variable i outside of a SM_TRY ... SM_END_TRY statement, initializing it to 0. Then you modify i inside of a SM_TRY or SM_FINALLY clause, setting it to 1. If you reference i in a different SM_FINALLY clause, or in an SM_EXCEPT clause, then it is implementation dependent whether i will be 0 or 1, unless you have declared i to be volatile.

    int volatile i = 0;
    
    SM_TRY
    	i = 1;
    	...
    SM_FINALLY
    	/* the following reference to i only works if i is declared volatile */
    	use(i);
    	...
    SM_EXCEPT(exc, "*")
    	/* the following reference to i only works if i is declared volatile */
    	use(i);
    	...
    SM_END_TRY
    
    dk-milter-1.0.0.dfsg/libsm/vfprintf.c0000644000175000017500000006021110242014340017162 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: vfprintf.c,v 1.54 2005/05/16 03:52:00 ca Exp $") /* ** Overall: ** Actual printing innards. ** This code is large and complicated... */ #include #include #include #include #include #include #include #include #include #include "local.h" #include "fvwrite.h" static int sm_bprintf __P((SM_FILE_T *, const char *, va_list)); static void sm_find_arguments __P((const char *, va_list , va_list **)); static void sm_grow_type_table_x __P((unsigned char **, int *)); static int sm_print __P((SM_FILE_T *, int, struct sm_uio *)); /* ** SM_PRINT -- print/flush to the file ** ** Flush out all the vectors defined by the given uio, ** then reset it so that it can be reused. ** ** Parameters: ** fp -- file pointer ** timeout -- time to complete operation (milliseconds) ** uio -- vector list of memory locations of data for printing ** ** Results: ** Success: 0 (zero) ** Failure: */ static int sm_print(fp, timeout, uio) SM_FILE_T *fp; int timeout; register struct sm_uio *uio; { register int err; if (uio->uio_resid == 0) { uio->uio_iovcnt = 0; return 0; } err = sm_fvwrite(fp, timeout, uio); uio->uio_resid = 0; uio->uio_iovcnt = 0; return err; } /* ** SM_BPRINTF -- allow formating to an unbuffered file. ** ** Helper function for `fprintf to unbuffered unix file': creates a ** temporary buffer (via a "fake" file pointer). ** We only work on write-only files; this avoids ** worries about ungetc buffers and so forth. ** ** Parameters: ** fp -- the file to send the o/p to ** fmt -- format instructions for the o/p ** ap -- vectors of data units used for formating ** ** Results: ** Failure: SM_IO_EOF and errno set ** Success: number of data units used in the formating ** ** Side effects: ** formatted o/p can be SM_IO_BUFSIZ length maximum */ static int sm_bprintf(fp, fmt, ap) SM_FILE_T *fp; const char *fmt; SM_VA_LOCAL_DECL { int ret; SM_FILE_T fake; unsigned char buf[SM_IO_BUFSIZ]; extern const char SmFileMagic[]; /* copy the important variables */ fake.sm_magic = SmFileMagic; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; fake.f_flags = fp->f_flags & ~SMNBF; fake.f_file = fp->f_file; fake.f_cookie = fp->f_cookie; fake.f_write = fp->f_write; fake.f_close = NULL; fake.f_open = NULL; fake.f_read = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_bprintf:fake"; /* set up the buffer */ fake.f_bf.smb_base = fake.f_p = buf; fake.f_bf.smb_size = fake.f_w = sizeof(buf); fake.f_lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); if (ret >= 0 && sm_io_flush(&fake, SM_TIME_FOREVER)) ret = SM_IO_EOF; /* errno set by sm_io_flush */ if (fake.f_flags & SMERR) fp->f_flags |= SMERR; return ret; } #define BUF 40 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ /* Macros for converting digits to letters and vice versa */ #define to_digit(c) ((c) - '0') #define is_digit(c) ((unsigned) to_digit(c) <= 9) #define to_char(n) ((char) (n) + '0') /* Flags used during conversion. */ #define ALT 0x001 /* alternate form */ #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ #define LADJUST 0x004 /* left adjustment */ #define LONGINT 0x010 /* long integer */ #define QUADINT 0x020 /* quad integer */ #define SHORTINT 0x040 /* short integer */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ #define FPT 0x100 /* Floating point number */ /* ** SM_IO_VPRINTF -- performs actual formating for o/p ** ** Parameters: ** fp -- file pointer for o/p ** timeout -- time to complete the print ** fmt0 -- formating directives ** ap -- vectors with data units for formating ** ** Results: ** Success: number of data units used for formatting ** Failure: SM_IO_EOF and sets errno */ int sm_io_vfprintf(fp, timeout, fmt0, ap) SM_FILE_T *fp; int timeout; const char *fmt0; SM_VA_LOCAL_DECL { register char *fmt; /* format string */ register int ch; /* character from fmt */ register int n, m, n2; /* handy integers (short term usage) */ register char *cp; /* handy char pointer (short term usage) */ register struct sm_iov *iovp;/* for PRINT macro */ register int flags; /* flags as above */ int ret; /* return value accumulator */ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ wchar_t wc; ULONGLONG_T _uquad; /* integer arguments %[diouxX] */ enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ int dprec; /* a copy of prec if [diouxX], 0 otherwise */ int realsz; /* field size expanded by dprec */ int size; /* size of converted field or string */ char *xdigs="0123456789abcdef"; /* digits for [xX] conversion */ #define NIOV 8 struct sm_uio uio; /* output information: summary */ struct sm_iov iov[NIOV];/* ... and individual io vectors */ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ char ox[2]; /* space for 0x hex-prefix */ va_list *argtable; /* args, built due to positional arg */ va_list statargtable[STATIC_ARG_TBL_SIZE]; int nextarg; /* 1-based argument index */ va_list orgap; /* original argument pointer */ /* ** Choose PADSIZE to trade efficiency vs. size. If larger printf ** fields occur frequently, increase PADSIZE and make the initialisers ** below longer. */ #define PADSIZE 16 /* pad chunk size */ static char blanks[PADSIZE] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; static char zeroes[PADSIZE] = {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; /* ** BEWARE, these `goto error' on error, and PAD uses `n'. */ #define PRINT(ptr, len) do { \ iovp->iov_base = (ptr); \ iovp->iov_len = (len); \ uio.uio_resid += (len); \ iovp++; \ if (++uio.uio_iovcnt >= NIOV) \ { \ if (sm_print(fp, timeout, &uio)) \ goto error; \ iovp = iov; \ } \ } while (0) #define PAD(howmany, with) do \ { \ if ((n = (howmany)) > 0) \ { \ while (n > PADSIZE) { \ PRINT(with, PADSIZE); \ n -= PADSIZE; \ } \ PRINT(with, n); \ } \ } while (0) #define FLUSH() do \ { \ if (uio.uio_resid && sm_print(fp, timeout, &uio)) \ goto error; \ uio.uio_iovcnt = 0; \ iovp = iov; \ } while (0) /* ** To extend shorts properly, we need both signed and unsigned ** argument extraction methods. */ #define SARG() \ (flags&QUADINT ? SM_VA_ARG(ap, LONGLONG_T) : \ flags&LONGINT ? GETARG(long) : \ flags&SHORTINT ? (long) (short) GETARG(int) : \ (long) GETARG(int)) #define UARG() \ (flags&QUADINT ? SM_VA_ARG(ap, ULONGLONG_T) : \ flags&LONGINT ? GETARG(unsigned long) : \ flags&SHORTINT ? (unsigned long) (unsigned short) GETARG(int) : \ (unsigned long) GETARG(unsigned int)) /* ** Get * arguments, including the form *nn$. Preserve the nextarg ** that the argument can be gotten once the type is determined. */ #define GETASTER(val) \ n2 = 0; \ cp = fmt; \ while (is_digit(*cp)) \ { \ n2 = 10 * n2 + to_digit(*cp); \ cp++; \ } \ if (*cp == '$') \ { \ int hold = nextarg; \ if (argtable == NULL) \ { \ argtable = statargtable; \ sm_find_arguments(fmt0, orgap, &argtable); \ } \ nextarg = n2; \ val = GETARG(int); \ nextarg = hold; \ fmt = ++cp; \ } \ else \ { \ val = GETARG(int); \ } /* ** Get the argument indexed by nextarg. If the argument table is ** built, use it to get the argument. If its not, get the next ** argument (and arguments must be gotten sequentially). */ #if SM_VA_STD # define GETARG(type) \ (((argtable != NULL) ? (void) (ap = argtable[nextarg]) : (void) 0), \ nextarg++, SM_VA_ARG(ap, type)) #else /* SM_VA_STD */ # define GETARG(type) \ ((argtable != NULL) ? (*((type*)(argtable[nextarg++]))) : \ (nextarg++, SM_VA_ARG(ap, type))) #endif /* SM_VA_STD */ /* sorry, fprintf(read_only_file, "") returns SM_IO_EOF, not 0 */ if (cantwrite(fp)) { errno = EBADF; return SM_IO_EOF; } /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->f_flags & (SMNBF|SMWR|SMRW)) == (SMNBF|SMWR) && fp->f_file >= 0) return sm_bprintf(fp, fmt0, ap); fmt = (char *) fmt0; argtable = NULL; nextarg = 1; SM_VA_COPY(orgap, ap); uio.uio_iov = iovp = iov; uio.uio_resid = 0; uio.uio_iovcnt = 0; ret = 0; /* Scan the format for conversions (`%' character). */ for (;;) { cp = fmt; n = 0; while ((wc = *fmt) != '\0') { if (wc == '%') { n = 1; break; } fmt++; } if ((m = fmt - cp) != 0) { PRINT(cp, m); ret += m; } if (n <= 0) goto done; fmt++; /* skip over '%' */ flags = 0; dprec = 0; width = 0; prec = -1; sign = '\0'; rflag: ch = *fmt++; reswitch: switch (ch) { case ' ': /* ** ``If the space and + flags both appear, the space ** flag will be ignored.'' ** -- ANSI X3J11 */ if (!sign) sign = ' '; goto rflag; case '#': flags |= ALT; goto rflag; case '*': /* ** ``A negative field width argument is taken as a ** - flag followed by a positive field width.'' ** -- ANSI X3J11 ** They don't exclude field widths read from args. */ GETASTER(width); if (width >= 0) goto rflag; width = -width; /* FALLTHROUGH */ case '-': flags |= LADJUST; goto rflag; case '+': sign = '+'; goto rflag; case '.': if ((ch = *fmt++) == '*') { GETASTER(n); prec = n < 0 ? -1 : n; goto rflag; } n = 0; while (is_digit(ch)) { n = 10 * n + to_digit(ch); ch = *fmt++; } if (ch == '$') { nextarg = n; if (argtable == NULL) { argtable = statargtable; sm_find_arguments(fmt0, orgap, &argtable); } goto rflag; } prec = n < 0 ? -1 : n; goto reswitch; case '0': /* ** ``Note that 0 is taken as a flag, not as the ** beginning of a field width.'' ** -- ANSI X3J11 */ flags |= ZEROPAD; goto rflag; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n = 10 * n + to_digit(ch); ch = *fmt++; } while (is_digit(ch)); if (ch == '$') { nextarg = n; if (argtable == NULL) { argtable = statargtable; sm_find_arguments(fmt0, orgap, &argtable); } goto rflag; } width = n; goto reswitch; case 'h': flags |= SHORTINT; goto rflag; case 'l': if (*fmt == 'l') { fmt++; flags |= QUADINT; } else { flags |= LONGINT; } goto rflag; case 'q': flags |= QUADINT; goto rflag; case 'c': *(cp = buf) = GETARG(int); size = 1; sign = '\0'; break; case 'D': flags |= LONGINT; /*FALLTHROUGH*/ case 'd': case 'i': _uquad = SARG(); if ((LONGLONG_T) _uquad < 0) { _uquad = -(LONGLONG_T) _uquad; sign = '-'; } base = DEC; goto number; case 'e': case 'E': case 'f': case 'g': case 'G': { double val; char *p; char fmt[16]; char out[150]; size_t len; /* ** This code implements floating point output ** in the most portable manner possible, ** relying only on 'sprintf' as defined by ** the 1989 ANSI C standard. ** We silently cap width and precision ** at 120, to avoid buffer overflow. */ val = GETARG(double); p = fmt; *p++ = '%'; if (sign) *p++ = sign; if (flags & ALT) *p++ = '#'; if (flags & LADJUST) *p++ = '-'; if (flags & ZEROPAD) *p++ = '0'; *p++ = '*'; if (prec >= 0) { *p++ = '.'; *p++ = '*'; } *p++ = ch; *p = '\0'; if (width > 120) width = 120; if (prec > 120) prec = 120; if (prec >= 0) #if HASSNPRINTF snprintf(out, sizeof(out), fmt, width, prec, val); #else /* HASSNPRINTF */ sprintf(out, fmt, width, prec, val); #endif /* HASSNPRINTF */ else #if HASSNPRINTF snprintf(out, sizeof(out), fmt, width, val); #else /* HASSNPRINTF */ sprintf(out, fmt, width, val); #endif /* HASSNPRINTF */ len = strlen(out); PRINT(out, len); FLUSH(); continue; } case 'n': if (flags & QUADINT) *GETARG(LONGLONG_T *) = ret; else if (flags & LONGINT) *GETARG(long *) = ret; else if (flags & SHORTINT) *GETARG(short *) = ret; else *GETARG(int *) = ret; continue; /* no output */ case 'O': flags |= LONGINT; /*FALLTHROUGH*/ case 'o': _uquad = UARG(); base = OCT; goto nosign; case 'p': /* ** ``The argument shall be a pointer to void. The ** value of the pointer is converted to a sequence ** of printable characters, in an implementation- ** defined manner.'' ** -- ANSI X3J11 */ /* NOSTRICT */ { union { void *p; ULONGLONG_T ll; unsigned long l; unsigned i; } u; u.p = GETARG(void *); if (sizeof(void *) == sizeof(ULONGLONG_T)) _uquad = u.ll; else if (sizeof(void *) == sizeof(long)) _uquad = u.l; else _uquad = u.i; } base = HEX; xdigs = "0123456789abcdef"; flags |= HEXPREFIX; ch = 'x'; goto nosign; case 's': if ((cp = GETARG(char *)) == NULL) cp = "(null)"; if (prec >= 0) { /* ** can't use strlen; can only look for the ** NUL in the first `prec' characters, and ** strlen() will go further. */ char *p = memchr(cp, 0, prec); if (p != NULL) { size = p - cp; if (size > prec) size = prec; } else size = prec; } else size = strlen(cp); sign = '\0'; break; case 'U': flags |= LONGINT; /*FALLTHROUGH*/ case 'u': _uquad = UARG(); base = DEC; goto nosign; case 'X': xdigs = "0123456789ABCDEF"; goto hex; case 'x': xdigs = "0123456789abcdef"; hex: _uquad = UARG(); base = HEX; /* leading 0x/X only if non-zero */ if (flags & ALT && _uquad != 0) flags |= HEXPREFIX; /* unsigned conversions */ nosign: sign = '\0'; /* ** ``... diouXx conversions ... if a precision is ** specified, the 0 flag will be ignored.'' ** -- ANSI X3J11 */ number: if ((dprec = prec) >= 0) flags &= ~ZEROPAD; /* ** ``The result of converting a zero value with an ** explicit precision of zero is no characters.'' ** -- ANSI X3J11 */ cp = buf + BUF; if (_uquad != 0 || prec != 0) { /* ** Unsigned mod is hard, and unsigned mod ** by a constant is easier than that by ** a variable; hence this switch. */ switch (base) { case OCT: do { *--cp = to_char(_uquad & 7); _uquad >>= 3; } while (_uquad); /* handle octal leading 0 */ if (flags & ALT && *cp != '0') *--cp = '0'; break; case DEC: /* many numbers are 1 digit */ while (_uquad >= 10) { *--cp = to_char(_uquad % 10); _uquad /= 10; } *--cp = to_char(_uquad); break; case HEX: do { *--cp = xdigs[_uquad & 15]; _uquad >>= 4; } while (_uquad); break; default: cp = "bug in sm_io_vfprintf: bad base"; size = strlen(cp); goto skipsize; } } size = buf + BUF - cp; skipsize: break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; /* pretend it was %c with argument ch */ cp = buf; *cp = ch; size = 1; sign = '\0'; break; } /* ** All reasonable formats wind up here. At this point, `cp' ** points to a string which (if not flags&LADJUST) should be ** padded out to `width' places. If flags&ZEROPAD, it should ** first be prefixed by any sign or other prefix; otherwise, ** it should be blank padded before the prefix is emitted. ** After any left-hand padding and prefixing, emit zeroes ** required by a decimal [diouxX] precision, then print the ** string proper, then emit zeroes required by any leftover ** floating precision; finally, if LADJUST, pad with blanks. ** ** Compute actual size, so we know how much to pad. ** size excludes decimal prec; realsz includes it. */ realsz = dprec > size ? dprec : size; if (sign) realsz++; else if (flags & HEXPREFIX) realsz+= 2; /* right-adjusting blank padding */ if ((flags & (LADJUST|ZEROPAD)) == 0) PAD(width - realsz, blanks); /* prefix */ if (sign) { PRINT(&sign, 1); } else if (flags & HEXPREFIX) { ox[0] = '0'; ox[1] = ch; PRINT(ox, 2); } /* right-adjusting zero padding */ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) PAD(width - realsz, zeroes); /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); /* the string or number proper */ PRINT(cp, size); /* left-adjusting padding (always blank) */ if (flags & LADJUST) PAD(width - realsz, blanks); /* finally, adjust ret */ ret += width > realsz ? width : realsz; FLUSH(); /* copy out the I/O vectors */ } done: FLUSH(); error: if ((argtable != NULL) && (argtable != statargtable)) sm_free(argtable); return sm_error(fp) ? SM_IO_EOF : ret; /* NOTREACHED */ } /* Type ids for argument type table. */ #define T_UNUSED 0 #define T_SHORT 1 #define T_U_SHORT 2 #define TP_SHORT 3 #define T_INT 4 #define T_U_INT 5 #define TP_INT 6 #define T_LONG 7 #define T_U_LONG 8 #define TP_LONG 9 #define T_QUAD 10 #define T_U_QUAD 11 #define TP_QUAD 12 #define T_DOUBLE 13 #define TP_CHAR 15 #define TP_VOID 16 /* ** SM_FIND_ARGUMENTS -- find all args when a positional parameter is found. ** ** Find all arguments when a positional parameter is encountered. Returns a ** table, indexed by argument number, of pointers to each arguments. The ** initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. ** It will be replaced with a malloc-ed one if it overflows. ** ** Parameters: ** fmt0 -- formating directives ** ap -- vector list of data unit for formating consumption ** argtable -- an indexable table (returned) of 'ap' ** ** Results: ** none. */ static void sm_find_arguments(fmt0, ap, argtable) const char *fmt0; SM_VA_LOCAL_DECL va_list **argtable; { register char *fmt; /* format string */ register int ch; /* character from fmt */ register int n, n2; /* handy integer (short term usage) */ register char *cp; /* handy char pointer (short term usage) */ register int flags; /* flags as above */ unsigned char *typetable; /* table of types */ unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; int tablesize; /* current size of type table */ int tablemax; /* largest used index in table */ int nextarg; /* 1-based argument index */ /* Add an argument type to the table, expanding if necessary. */ #define ADDTYPE(type) \ ((nextarg >= tablesize) ? \ (sm_grow_type_table_x(&typetable, &tablesize), 0) : 0, \ typetable[nextarg++] = type, \ (nextarg > tablemax) ? tablemax = nextarg : 0) #define ADDSARG() \ ((flags & LONGINT) ? ADDTYPE(T_LONG) : \ ((flags & SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT))) #define ADDUARG() \ ((flags & LONGINT) ? ADDTYPE(T_U_LONG) : \ ((flags & SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT))) /* Add * arguments to the type array. */ #define ADDASTER() \ n2 = 0; \ cp = fmt; \ while (is_digit(*cp)) \ { \ n2 = 10 * n2 + to_digit(*cp); \ cp++; \ } \ if (*cp == '$') \ { \ int hold = nextarg; \ nextarg = n2; \ ADDTYPE (T_INT); \ nextarg = hold; \ fmt = ++cp; \ } \ else \ { \ ADDTYPE (T_INT); \ } fmt = (char *) fmt0; typetable = stattypetable; tablesize = STATIC_ARG_TBL_SIZE; tablemax = 0; nextarg = 1; (void) memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); /* Scan the format for conversions (`%' character). */ for (;;) { for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) /* void */; if (ch == '\0') goto done; fmt++; /* skip over '%' */ flags = 0; rflag: ch = *fmt++; reswitch: switch (ch) { case ' ': case '#': goto rflag; case '*': ADDASTER(); goto rflag; case '-': case '+': goto rflag; case '.': if ((ch = *fmt++) == '*') { ADDASTER(); goto rflag; } while (is_digit(ch)) { ch = *fmt++; } goto reswitch; case '0': goto rflag; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n = 10 * n + to_digit(ch); ch = *fmt++; } while (is_digit(ch)); if (ch == '$') { nextarg = n; goto rflag; } goto reswitch; case 'h': flags |= SHORTINT; goto rflag; case 'l': flags |= LONGINT; goto rflag; case 'q': flags |= QUADINT; goto rflag; case 'c': ADDTYPE(T_INT); break; case 'D': flags |= LONGINT; /*FALLTHROUGH*/ case 'd': case 'i': if (flags & QUADINT) { ADDTYPE(T_QUAD); } else { ADDSARG(); } break; case 'e': case 'E': case 'f': case 'g': case 'G': ADDTYPE(T_DOUBLE); break; case 'n': if (flags & QUADINT) ADDTYPE(TP_QUAD); else if (flags & LONGINT) ADDTYPE(TP_LONG); else if (flags & SHORTINT) ADDTYPE(TP_SHORT); else ADDTYPE(TP_INT); continue; /* no output */ case 'O': flags |= LONGINT; /*FALLTHROUGH*/ case 'o': if (flags & QUADINT) ADDTYPE(T_U_QUAD); else ADDUARG(); break; case 'p': ADDTYPE(TP_VOID); break; case 's': ADDTYPE(TP_CHAR); break; case 'U': flags |= LONGINT; /*FALLTHROUGH*/ case 'u': if (flags & QUADINT) ADDTYPE(T_U_QUAD); else ADDUARG(); break; case 'X': case 'x': if (flags & QUADINT) ADDTYPE(T_U_QUAD); else ADDUARG(); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; break; } } done: /* Build the argument table. */ if (tablemax >= STATIC_ARG_TBL_SIZE) { *argtable = (va_list *) sm_malloc(sizeof(va_list) * (tablemax + 1)); } for (n = 1; n <= tablemax; n++) { SM_VA_COPY((*argtable)[n], ap); switch (typetable [n]) { case T_UNUSED: (void) SM_VA_ARG(ap, int); break; case T_SHORT: (void) SM_VA_ARG(ap, int); break; case T_U_SHORT: (void) SM_VA_ARG(ap, int); break; case TP_SHORT: (void) SM_VA_ARG(ap, short *); break; case T_INT: (void) SM_VA_ARG(ap, int); break; case T_U_INT: (void) SM_VA_ARG(ap, unsigned int); break; case TP_INT: (void) SM_VA_ARG(ap, int *); break; case T_LONG: (void) SM_VA_ARG(ap, long); break; case T_U_LONG: (void) SM_VA_ARG(ap, unsigned long); break; case TP_LONG: (void) SM_VA_ARG(ap, long *); break; case T_QUAD: (void) SM_VA_ARG(ap, LONGLONG_T); break; case T_U_QUAD: (void) SM_VA_ARG(ap, ULONGLONG_T); break; case TP_QUAD: (void) SM_VA_ARG(ap, LONGLONG_T *); break; case T_DOUBLE: (void) SM_VA_ARG(ap, double); break; case TP_CHAR: (void) SM_VA_ARG(ap, char *); break; case TP_VOID: (void) SM_VA_ARG(ap, void *); break; } } if ((typetable != NULL) && (typetable != stattypetable)) sm_free(typetable); } /* ** SM_GROW_TYPE_TABLE -- Increase the size of the type table. ** ** Parameters: ** tabletype -- type of table to grow ** tablesize -- requested new table size ** ** Results: ** Raises an exception if can't allocate memory. */ static void sm_grow_type_table_x(typetable, tablesize) unsigned char **typetable; int *tablesize; { unsigned char *oldtable = *typetable; int newsize = *tablesize * 2; if (*tablesize == STATIC_ARG_TBL_SIZE) { *typetable = (unsigned char *) sm_malloc_x(sizeof(unsigned char) * newsize); (void) memmove(*typetable, oldtable, *tablesize); } else { *typetable = (unsigned char *) sm_realloc_x(typetable, sizeof(unsigned char) * newsize); } (void) memset(&typetable [*tablesize], T_UNUSED, (newsize - *tablesize)); *tablesize = newsize; } dk-milter-1.0.0.dfsg/libsm/strdup.c0000644000175000017500000000544307741571351016677 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: strdup.c,v 1.15 2003/10/10 17:56:57 ca Exp $") #include #include /* ** SM_STRNDUP_X -- Duplicate a string of a given length ** ** Allocates memory and copies source string (of given length) into it. ** ** Parameters: ** s -- string to copy. ** n -- length to copy. ** ** Returns: ** copy of string, raises exception if out of memory. ** ** Side Effects: ** allocate memory for new string. */ char * sm_strndup_x(s, n) const char *s; size_t n; { char *d = sm_malloc_x(n + 1); (void) memcpy(d, s, n); d[n] = '\0'; return d; } /* ** SM_STRDUP -- Duplicate a string ** ** Allocates memory and copies source string into it. ** ** Parameters: ** s -- string to copy. ** ** Returns: ** copy of string, NULL if out of memory. ** ** Side Effects: ** allocate memory for new string. */ char * sm_strdup(s) char *s; { size_t l; char *d; l = strlen(s) + 1; d = sm_malloc_tagged(l, "sm_strdup", 0, sm_heap_group()); if (d != NULL) (void) sm_strlcpy(d, s, l); return d; } #if DO_NOT_USE_STRCPY /* ** SM_STRDUP_X -- Duplicate a string ** ** Allocates memory and copies source string into it. ** ** Parameters: ** s -- string to copy. ** ** Returns: ** copy of string, exception if out of memory. ** ** Side Effects: ** allocate memory for new string. */ char * sm_strdup_x(s) const char *s; { size_t l; char *d; l = strlen(s) + 1; d = sm_malloc_tagged_x(l, "sm_strdup_x", 0, sm_heap_group()); (void) sm_strlcpy(d, s, l); return d; } /* ** SM_PSTRDUP_X -- Duplicate a string (using "permanent" memory) ** ** Allocates memory and copies source string into it. ** ** Parameters: ** s -- string to copy. ** ** Returns: ** copy of string, exception if out of memory. ** ** Side Effects: ** allocate memory for new string. */ char * sm_pstrdup_x(s) const char *s; { size_t l; char *d; l = strlen(s) + 1; d = sm_pmalloc_x(l); (void) sm_strlcpy(d, s, l); return d; } /* ** SM_STRDUP_X -- Duplicate a string ** ** Allocates memory and copies source string into it. ** ** Parameters: ** s -- string to copy. ** file -- name of source file ** line -- line in source file ** group -- heap group ** ** Returns: ** copy of string, exception if out of memory. ** ** Side Effects: ** allocate memory for new string. */ char * sm_strdup_tagged_x(s, file, line, group) const char *s; char *file; int line, group; { size_t l; char *d; l = strlen(s) + 1; d = sm_malloc_tagged_x(l, file, line, group); (void) sm_strlcpy(d, s, l); return d; } #endif /* DO_NOT_USE_STRCPY */ dk-milter-1.0.0.dfsg/libsm/strrevcmp.c0000644000175000017500000000316507347306541017401 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: strrevcmp.c,v 1.5 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include /* strcasecmp.c */ extern const unsigned char charmap[]; /* ** SM_STRREVCASECMP -- compare two strings starting at the end (ignore case) ** ** Parameters: ** s1 -- first string. ** s2 -- second string. ** ** Returns: ** strcasecmp(reverse(s1), reverse(s2)) */ int sm_strrevcasecmp(s1, s2) const char *s1, *s2; { register int i1, i2; i1 = strlen(s1) - 1; i2 = strlen(s2) - 1; while (i1 >= 0 && i2 >= 0 && charmap[(unsigned char) s1[i1]] == charmap[(unsigned char) s2[i2]]) { --i1; --i2; } if (i1 < 0) { if (i2 < 0) return 0; else return -1; } else { if (i2 < 0) return 1; else return (charmap[(unsigned char) s1[i1]] - charmap[(unsigned char) s2[i2]]); } } /* ** SM_STRREVCMP -- compare two strings starting at the end ** ** Parameters: ** s1 -- first string. ** s2 -- second string. ** ** Returns: ** strcmp(reverse(s1), reverse(s2)) */ int sm_strrevcmp(s1, s2) const char *s1, *s2; { register int i1, i2; i1 = strlen(s1) - 1; i2 = strlen(s2) - 1; while (i1 >= 0 && i2 >= 0 && s1[i1] == s2[i2]) { --i1; --i2; } if (i1 < 0) { if (i2 < 0) return 0; else return -1; } else { if (i2 < 0) return 1; else return s1[i1] - s2[i2]; } } dk-milter-1.0.0.dfsg/libsm/fseek.c0000644000175000017500000001651110253661450016441 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fseek.c,v 1.47 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #define POS_ERR (-(off_t)1) static void seekalrm __P((int)); static jmp_buf SeekTimeOut; /* ** SEEKALRM -- handler when timeout activated for sm_io_seek() ** ** Returns flow of control to where setjmp(SeekTimeOut) was set. ** ** Parameters: ** sig -- unused ** ** Returns: ** does not return ** ** Side Effects: ** returns flow of control to setjmp(SeekTimeOut). ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED0 */ static void seekalrm(sig) int sig; { longjmp(SeekTimeOut, 1); } /* ** SM_IO_SEEK -- position the file pointer ** ** Parameters: ** fp -- the file pointer to be seek'd ** timeout -- time to complete seek (milliseconds) ** offset -- seek offset based on 'whence' ** whence -- indicates where seek is relative from. ** One of SM_IO_SEEK_{CUR,SET,END}. ** Returns: ** Failure: returns -1 (minus 1) and sets errno ** Success: returns 0 (zero) */ int sm_io_seek(fp, timeout, offset, whence) register SM_FILE_T *fp; int SM_NONVOLATILE timeout; long SM_NONVOLATILE offset; int SM_NONVOLATILE whence; { bool havepos; off_t target, curoff; size_t n; struct stat st; int ret; SM_EVENT *evt = NULL; register off_t (*seekfn) __P((SM_FILE_T *, off_t, int)); SM_REQUIRE_ISA(fp, SmFileMagic); /* make sure stdio is set up */ if (!Sm_IO_DidInit) sm_init(); /* Have to be able to seek. */ if ((seekfn = fp->f_seek) == NULL) { errno = ESPIPE; /* historic practice */ return -1; } if (timeout == SM_TIME_DEFAULT) timeout = fp->f_timeout; if (timeout == SM_TIME_IMMEDIATE) { /* ** Filling the buffer will take time and we are wanted to ** return immediately. So... */ errno = EAGAIN; return -1; } #define SM_SET_ALARM() \ if (timeout != SM_TIME_FOREVER) \ { \ if (setjmp(SeekTimeOut) != 0) \ { \ errno = EAGAIN; \ return -1; \ } \ evt = sm_seteventm(timeout, seekalrm, 0); \ } /* ** Change any SM_IO_SEEK_CUR to SM_IO_SEEK_SET, and check `whence' ** argument. After this, whence is either SM_IO_SEEK_SET or ** SM_IO_SEEK_END. */ switch (whence) { case SM_IO_SEEK_CUR: /* ** In order to seek relative to the current stream offset, ** we have to first find the current stream offset a la ** ftell (see ftell for details). */ /* may adjust seek offset on append stream */ sm_flush(fp, (int *) &timeout); SM_SET_ALARM(); if (fp->f_flags & SMOFF) curoff = fp->f_lseekoff; else { curoff = (*seekfn)(fp, (off_t) 0, SM_IO_SEEK_CUR); if (curoff == -1L) { ret = -1; goto clean; } } if (fp->f_flags & SMRD) { curoff -= fp->f_r; if (HASUB(fp)) curoff -= fp->f_ur; } else if (fp->f_flags & SMWR && fp->f_p != NULL) curoff += fp->f_p - fp->f_bf.smb_base; offset += curoff; whence = SM_IO_SEEK_SET; havepos = true; break; case SM_IO_SEEK_SET: case SM_IO_SEEK_END: SM_SET_ALARM(); curoff = 0; /* XXX just to keep gcc quiet */ havepos = false; break; default: errno = EINVAL; return -1; } /* ** Can only optimise if: ** reading (and not reading-and-writing); ** not unbuffered; and ** this is a `regular' Unix file (and hence seekfn==sm_stdseek). ** We must check SMNBF first, because it is possible to have SMNBF ** and SMSOPT both set. */ if (fp->f_bf.smb_base == NULL) sm_makebuf(fp); if (fp->f_flags & (SMWR | SMRW | SMNBF | SMNPT)) goto dumb; if ((fp->f_flags & SMOPT) == 0) { if (seekfn != sm_stdseek || fp->f_file < 0 || fstat(fp->f_file, &st) || (st.st_mode & S_IFMT) != S_IFREG) { fp->f_flags |= SMNPT; goto dumb; } #ifdef WIN32 fp->f_blksize = 4096; /* XXXX temp */ #else fp->f_blksize = st.st_blksize; #endif /* WIN32 */ fp->f_flags |= SMOPT; } /* ** We are reading; we can try to optimise. ** Figure out where we are going and where we are now. */ if (whence == SM_IO_SEEK_SET) target = offset; else { if (fstat(fp->f_file, &st)) goto dumb; target = st.st_size + offset; } if (!havepos) { if (fp->f_flags & SMOFF) curoff = fp->f_lseekoff; else { curoff = (*seekfn)(fp, (off_t) 0, SM_IO_SEEK_CUR); if (curoff == POS_ERR) goto dumb; } curoff -= fp->f_r; if (HASUB(fp)) curoff -= fp->f_ur; } /* ** Compute the number of bytes in the input buffer (pretending ** that any ungetc() input has been discarded). Adjust current ** offset backwards by this count so that it represents the ** file offset for the first byte in the current input buffer. */ if (HASUB(fp)) { curoff += fp->f_r; /* kill off ungetc */ n = fp->f_up - fp->f_bf.smb_base; curoff -= n; n += fp->f_ur; } else { n = fp->f_p - fp->f_bf.smb_base; curoff -= n; n += fp->f_r; } /* ** If the target offset is within the current buffer, ** simply adjust the pointers, clear SMFEOF, undo ungetc(), ** and return. (If the buffer was modified, we have to ** skip this; see getln in fget.c.) */ if (target >= curoff && target < curoff + (off_t) n) { register int o = target - curoff; fp->f_p = fp->f_bf.smb_base + o; fp->f_r = n - o; if (HASUB(fp)) FREEUB(fp); fp->f_flags &= ~SMFEOF; ret = 0; goto clean; } /* ** The place we want to get to is not within the current buffer, ** but we can still be kind to the kernel copyout mechanism. ** By aligning the file offset to a block boundary, we can let ** the kernel use the VM hardware to map pages instead of ** copying bytes laboriously. Using a block boundary also ** ensures that we only read one block, rather than two. */ curoff = target & ~(fp->f_blksize - 1); if ((*seekfn)(fp, curoff, SM_IO_SEEK_SET) == POS_ERR) goto dumb; fp->f_r = 0; fp->f_p = fp->f_bf.smb_base; if (HASUB(fp)) FREEUB(fp); fp->f_flags &= ~SMFEOF; n = target - curoff; if (n) { /* Note: SM_TIME_FOREVER since fn timeout already set */ if (sm_refill(fp, SM_TIME_FOREVER) || fp->f_r < (int) n) goto dumb; fp->f_p += n; fp->f_r -= n; } ret = 0; clean: /* We're back. So undo our timeout and handler */ if (evt != NULL) sm_clrevent(evt); return ret; dumb: /* ** We get here if we cannot optimise the seek ... just ** do it. Allow the seek function to change fp->f_bf.smb_base. */ /* Note: SM_TIME_FOREVER since fn timeout already set */ ret = SM_TIME_FOREVER; if (sm_flush(fp, &ret) != 0 || (*seekfn)(fp, (off_t) offset, whence) == POS_ERR) { ret = -1; goto clean; } /* success: clear SMFEOF indicator and discard ungetc() data */ if (HASUB(fp)) FREEUB(fp); fp->f_p = fp->f_bf.smb_base; fp->f_r = 0; fp->f_flags &= ~SMFEOF; ret = 0; goto clean; } dk-milter-1.0.0.dfsg/libsm/index.html0000644000175000017500000001372007242322525017175 0ustar madhackmadhack libsm Overview

    libsm Overview


    $Id: index.html,v 1.14 2001/02/13 21:21:25 gshapiro Exp $

    Introduction

    Libsm is a library of generally useful C abstractions. Libsm stands alone; it depends on no other sendmail libraries, and the only sendmail header files it depends on are its own, which reside in ../include/sm.

    Contents

    Here is the current set of packages:
    gen: general definitions
    debug: debugging and tracing
    assert: assertion handling and aborts
    heap: memory allocation
    exc: exception handling
    rpool: resource pools
    cdefs: C language portability macros
    io: buffered i/o

    Naming Conventions

    Some of the symbols defined by libsm come from widely used defacto or dejure standards. Examples include size_t (from the C 89 standard), bool (from the C 99 standard), strerror (from Posix), and __P (from BSD and Linux). In these cases, we use the standard name rather than inventing a new name. We import the name from the appropriate header file when possible, or define it ourselves when necessary. When you are using one of these abstractions, you must include the appropriate libsm header file. For example, when you are using strerror, you must include <sm/string.h> instead of <string.h>.

    When we aren't implementing a standard interface, we use a naming convention that attempts to maximize portability across platforms, and minimize conflicts with other libraries. Except for a few seemingly benign exceptions, all names begin with SM_, Sm or sm_.

    The ISO C, Posix and Unix standards forbid applications from using names beginning with __ or _[A-Z], and place restrictions on what sorts of names can begin with _[a-z]. Such names are reserved for the compiler and the standard libraries. For this reason, we avoid defining any names that begin with _. For example, all libsm header file idempotency macros have the form SM_FOO_H (no leading _).

    Type names begin with SM_ and end with _T. Note that the Posix standard reserves all identifiers ending with _t.

    All functions that are capable of raising an exception have names ending in _x, and developers are encouraged to use this convention when writing new code. This naming convention may seem unnecessary at first, but it becomes extremely useful during maintenance, when you are attempting to reason about the correctness of a block of code, and when you are trying to track down exception-related bugs in existing code.

    Coding Conventions

    The official style for function prototypes in libsm header files is
    extern int
    foo __P((
    	int _firstarg,
    	int _secondarg));
    
    The extern is useless, but required for stylistic reasons. The parameter names are optional; if present they are lowercase and begin with _ to avoid namespace conflicts. Each parameter is written on its own line to avoid very long lines.

    For each structure struct sm_foo defined by libsm, there is a typedef:

    typedef struct sm_foo SM_FOO_T;
    
    and there is a global variable which is defined as follows:
    const char SmFooMagic[] = "sm_foo";
    
    The first member of each structure defined by libsm is
    const char *sm_magic;
    
    For all instances of struct sm_foo, sm_magic contains SmFooMagic, which points to a unique character string naming the type. It is used for debugging and run time type checking.

    Each function with a parameter declared SM_FOO_T *foo contains the following assertion:

    SM_REQUIRE_ISA(foo, SmFooMagic);
    
    which is equivalent to
    SM_REQUIRE(foo != NULL && foo->sm_magic == SmFooMagic);
    
    When an object of type SM_FOO_T is deallocated, the member sm_magic is set to NULL. That will cause the above assertion to fail if a dangling pointer is used.

    Additional Design Goals

    Here are some of my design goals:

    • The sm library is self contained; it does not depend on any other sendmail libraries or header files.

    • The sm library must be compatible with shared libraries, even on platforms with weird implementation restrictions. I assume that a shared library can export global variables; the debug package relies on this assumption. I do not assume that if an application redefines a function defined in a shared library, the shared library will use the version of the function defined in the application in preference to the version that it defines. For this reason, I provide interfaces for registering handler functions in cases where an application might need to override standard behaviour.

    • The sm library must be compatible with threads. The debug package presents a small problem: I don't want sm_debug_active to acquire and release a lock. So I assume that there exists an integral type SM_ATOMIC_INT_T (see <sm/gen.h>) that can be accessed and updated atomically. I assume that locking must be used to guard updates and accesses to any other type, and I have designed the interfaces accordingly.
    dk-milter-1.0.0.dfsg/libsm/t-match.c0000644000175000017500000000215207347306541016704 0ustar madhackmadhack/* * Copyright (c) 2000 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-match.c,v 1.9 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #define try(str, pat, want) \ got = sm_match(str, pat); \ if (!SM_TEST(got == want)) \ (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \ "sm_match(\"%s\", \"%s\") returns %s\n", \ str, pat, got ? "true" : "false"); int main(argc, argv) int argc; char **argv; { bool got; sm_test_begin(argc, argv, "test sm_match"); try("foo", "foo", true); try("foo", "bar", false); try("foo[bar", "foo[bar", true); try("foo[bar]", "foo[bar]", false); try("foob", "foo[bar]", true); try("a-b", "a[]-]b", true); try("abcde", "a*e", true); try("[", "[[]", true); try("c", "[a-z]", true); try("C", "[a-z]", false); try("F:sm.heap", "[!F]*", false); try("E:sm.err", "[!F]*", true); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/vsprintf.c0000644000175000017500000000322207347306541017221 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: vsprintf.c,v 1.21 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include "local.h" /* ** SM_VSPRINTF -- format data for "output" into a string ** ** Assigned 'str' to a "fake" file pointer. This allows common ** o/p formatting function sm_vprintf() to be used. ** ** Parameters: ** str -- location for output ** fmt -- format directives ** ap -- data unit vectors for use by 'fmt' ** ** Results: ** result from sm_io_vfprintf() ** ** Side Effects: ** Quietly limits the size to INT_MAX though this may ** not prevent SEGV's. */ int sm_vsprintf(str, fmt, ap) char *str; const char *fmt; SM_VA_LOCAL_DECL { int ret; SM_FILE_T fake; fake.sm_magic = SmFileMagic; fake.f_file = -1; fake.f_flags = SMWR | SMSTR; fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; fake.f_bf.smb_size = fake.f_w = INT_MAX; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; fake.f_close = NULL; fake.f_open = NULL; fake.f_read = NULL; fake.f_write = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_vsprintf:fake"; ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); *fake.f_p = '\0'; return ret; } dk-milter-1.0.0.dfsg/libsm/assert.html0000644000175000017500000003356307342537727017413 0ustar madhackmadhack libsm : Assert and Abort Back to libsm overview

    libsm : Assert and Abort


    $Id: assert.html,v 1.6 2001/08/27 21:47:03 ca Exp $

    Introduction

    This package contains abstractions for assertion checking and abnormal program termination.

    Synopsis

    #include <sm/assert.h>
    
    /*
    **  abnormal program termination
    */
    
    void sm_abort_at(char *filename, int lineno, char *msg);
    typedef void (*SM_ABORT_HANDLER)(char *filename, int lineno, char *msg);
    void sm_abort_sethandler(SM_ABORT_HANDLER);
    void sm_abort(char *fmt, ...)
    
    /*
    **  assertion checking
    */
    
    SM_REQUIRE(expression)
    SM_ASSERT(expression)
    SM_ENSURE(expression)
    
    extern SM_DEBUG_T SmExpensiveRequire;
    extern SM_DEBUG_T SmExpensiveAssert;
    extern SM_DEBUG_T SmExpensiveEnsure;
    
    #if SM_CHECK_REQUIRE
    #if SM_CHECK_ASSERT
    #if SM_CHECK_ENSURE
    
    cc -DSM_CHECK_ALL=0 -DSM_CHECK_REQUIRE=1 ...
    

    Abnormal Program Termination

    The functions sm_abort and sm_abort_at are used to report a logic bug and terminate the program. They can be invoked directly, and they are also used by the assertion checking macros.
    void sm_abort_at(char *filename, int lineno, char *msg)
    This is the low level interface for causing abnormal program termination. It is intended to be invoked from a macro, such as the assertion checking macros. If filename != NULL then filename and lineno specify the line of source code on which the logic bug is detected. These arguments are normally either set to __FILE__ and __LINE__ from an assertion checking macro, or they are set to NULL and 0. The default action is to print an error message to smioerr using the arguments, and then call abort(). This default behaviour can be changed by calling sm_abort_sethandler.

    void sm_abort_sethandler(SM_ABORT_HANDLER handler)
    Install 'handler' as the callback function that is invoked by sm_abort_at. This callback function is passed the same arguments as sm_abort_at, and is expected to log an error message and terminate the program. The callback function should not raise an exception or perform cleanup: see Rationale. sm_abort_sethandler is intended to be called once, from main(), before any additional threads are created: see Rationale. You should not use sm_abort_sethandler to switch back and forth between several handlers; this is particularly dangerous when there are multiple threads, or when you are in a library routine.

    void sm_abort(char *fmt, ...)
    This is the high level interface for causing abnormal program termination. It takes printf arguments. There is no need to include a trailing newline in the format string; a trailing newline will be printed if appropriate by the handler function.

    Assertions

    The assertion handling package supports a style of programming in which assertions are used liberally throughout the code, both as a form of documentation, and as a way of detecting bugs in the code by performing runtime checks.

    There are three kinds of assertion:

    SM_REQUIRE(expr)
    This is an assertion used at the beginning of a function to check that the preconditions for calling the function have been satisfied by the caller.

    SM_ENSURE(expr)
    This is an assertion used just before returning from a function to check that the function has satisfied all of the postconditions that it is required to satisfy by its contract with the caller.

    SM_ASSERT(expr)
    This is an assertion that is used in the middle of a function, to check loop invariants, and for any other kind of check that is not a "require" or "ensure" check.
    If any of the above assertion macros fail, then sm_abort_at is called. By default, a message is printed to stderr and the program is aborted. For example, if SM_REQUIRE(arg > 0) fails because arg <= 0, then the message
    foo.c:47: SM_REQUIRE(arg > 0) failed
    
    is printed to stderr, and abort() is called. You can change this default behaviour using sm_abort_sethandler.

    How To Disable Assertion Checking At Compile Time

    You can use compile time macros to selectively enable or disable each of the three kinds of assertions, for performance reasons. For example, you might want to enable SM_REQUIRE checking (because it finds the most bugs), but disable the other two types.

    By default, all three types of assertion are enabled. You can selectively disable individual assertion types by setting one or more of the following cpp macros to 0 before <sm/assert.h> is included for the first time:

    SM_CHECK_REQUIRE
    SM_CHECK_ENSURE
    SM_CHECK_ASSERT
    Or, you can define SM_CHECK_ALL as 0 to disable all assertion types, then selectively define one or more of SM_CHECK_REQUIRE, SM_CHECK_ENSURE or SM_CHECK_ASSERT as 1. For example, to disable all assertions except for SM_REQUIRE, you can use these C compiler flags:
    -DSM_CHECK_ALL=0 -DSM_CHECK_REQUIRE=1
    After <sm/assert.h> is included, the macros SM_CHECK_REQUIRE, SM_CHECK_ENSURE and SM_CHECK_ASSERT are each set to either 0 or 1.

    How To Write Complex or Expensive Assertions

    Sometimes an assertion check requires more code than a simple boolean expression. For example, it might require an entire statement block with its own local variables. You can code such assertion checks by making them conditional on SM_CHECK_REQUIRE, SM_CHECK_ENSURE or SM_CHECK_ASSERT, and using sm_abort to signal failure.

    Sometimes an assertion check is significantly more expensive than one or two comparisons. In such cases, it is not uncommon for developers to comment out the assertion once the code is unit tested. Please don't do this: it makes it hard to turn the assertion check back on for the purposes of regression testing. What you should do instead is make the assertion check conditional on one of these predefined debug objects:

    SmExpensiveRequire
    SmExpensiveAssert
    SmExpensiveEnsure
    By doing this, you bring the cost of the assertion checking code back down to a single comparison, unless expensive assertion checking has been explicitly enabled. By the way, the corresponding debug category names are
    sm_check_require
    sm_check_assert
    sm_check_ensure
    What activation level should you check for? Higher levels correspond to more expensive assertion checks. Here are some basic guidelines:
    level 1: < 10 basic C operations
    level 2: < 100 basic C operations
    level 3: < 1000 basic C operations
    ...

    Here's a contrived example of both techniques:

    void
    w_munge(WIDGET *w)
    {
        SM_REQUIRE(w != NULL);
    #if SM_CHECK_REQUIRE
        /*
        **  We run this check at level 3 because we expect to check a few hundred
        **  table entries.
        */
    
        if (sm_debug_active(&SmExpensiveRequire, 3))
        {
            int i;
    
            for (i = 0; i < WIDGET_MAX; ++i)
            {
                if (w[i] == NULL)
                    sm_abort("w_munge: NULL entry %d in widget table", i);
            }
        }
    #endif /* SM_CHECK_REQUIRE */
    

    Other Guidelines

    You should resist the urge to write SM_ASSERT(0) when the code has reached an impossible place. It's better to call sm_abort, because then you can generate a better error message. For example,
    switch (foo)
    {
        ...
      default:
        sm_abort("impossible value %d for foo", foo);
    }
    
    Note that I did not bother to guard the default clause of the switch statement with #if SM_CHECK_ASSERT ... #endif, because there is probably no performance gain to be had by disabling this particular check.

    Avoid including code that has side effects inside of assert macros, or inside of SM_CHECK_* guards. You don't want the program to stop working if assertion checking is disabled.

    Rationale for Logic Bug Handling

    When a logic bug is detected, our philosophy is to log an error message and terminate the program, dumping core if possible. It is not a good idea to raise an exception, attempt cleanup, or continue program execution. Here's why.

    First of all, to facilitate post-mortem analysis, we want to dump core on detecting a logic bug, disturbing the process image as little as possible before dumping core. We don't want to raise an exception and unwind the stack, executing cleanup code, before dumping core, because that would obliterate information we need to analyze the cause of the abort.

    Second, it is a bad idea to raise an exception on an assertion failure because this places unacceptable restrictions on code that uses the assertion macros. The reason is this: the sendmail code must be written so that anywhere it is possible for an assertion to be raised, the code will catch the exception and clean up if necessary, restoring data structure invariants and freeing resources as required. If an assertion failure was signalled by raising an exception, then every time you added an assertion, you would need to check both the function containing the assertion and its callers to see if any exception handling code needed to be added to clean up properly on assertion failure. That is far too great a burden.

    It is a bad idea to attempt cleanup upon detecting a logic bug for several reasons:

    • If you need to perform cleanup actions in order to preserve the integrity of the data that the program is handling, then the program is not fault tolerant, and needs to be redesigned. There are several reasons why a program might be terminated unexpectedly: the system might crash, the program might receive a signal 9, the program might be terminated by a memory fault (possibly as a side effect of earlier data structure corruption), and the program might detect a logic bug and terminate itself. Note that executing cleanup actions is not feasible in most of the above cases. If the program has a fault tolerant design, then it will not lose data even if the system crashes in the middle of an operation.

    • If the cause of the logic bug is earlier data structure corruption, then cleanup actions intended to preserve the integrity of the data that the program is handling might cause more harm than good: they might cause information to be corrupted or lost.

    • If the program uses threads, then cleanup is much more problematic. Suppose that thread A is holding some locks, and is in the middle of modifying a shared data structure. The locks are needed because the data structure is currently in an inconsistent state. At this point, a logic bug is detected deep in a library routine called by A. How do we get all of the running threads to stop what they are doing and perform their thread-specific cleanup actions before terminating? We may not be able to get B to clean up and terminate cleanly until A has restored the invariants on the data structure it is modifying and releases its locks. So, we raise an exception and unwind the stack, restoring data structure invariants and releasing locks at each level of abstraction, and performing an orderly shutdown. There are certainly many classes of error conditions for which using the exception mechanism to perform an orderly shutdown is appropriate and feasible, but there are also classes of error conditions for which exception handling and orderly shutdown is dangerous or impossible. The abnormal program termination system is intended for this second class of error conditions. If you want to trigger orderly shutdown, don't call sm_abort: raise an exception instead.

    Here is a strategy for making sendmail fault tolerant. Sendmail is structured as a collection of processes. The "root" process does as little as possible, except spawn children to do all of the real work, monitor the children, and act as traffic cop. We use exceptions to signal expected but infrequent error conditions, so that the process encountering the exceptional condition can clean up and keep going. (Worker processes are intended to be long lived, in order to minimize forking and increase performance.) But when a bug is detected in a sendmail worker process, the worker process does minimal or no cleanup and then dies. A bug might be detected in several ways: the process might dereference a NULL pointer, receive a signal 11, core dump and die, or an assertion might fail, in which case the process commits suicide. Either way, the root process detects the death of the worker, logs the event, and spawns another worker.

    Rationale for Naming Conventions

    The names "require" and "ensure" come from the writings of Bertrand Meyer, a prominent evangelist for assertion checking who has written a number of papers about the "Design By Contract" programming methodology, and who created the Eiffel programming language. Many other assertion checking packages for C also have "require" and "ensure" assertion types. In short, we are conforming to a de-facto standard.

    We use the names SM_REQUIRE, SM_ASSERT and SM_ENSURE in preference to to REQUIRE, ASSERT and ENSURE because at least two other open source libraries (libisc and libnana) define REQUIRE and ENSURE macros, and many libraries define ASSERT. We want to avoid name conflicts with other libraries. dk-milter-1.0.0.dfsg/libsm/t-fopen.c0000644000175000017500000000155007430341371016711 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-fopen.c,v 1.9 2002/02/06 23:57:45 ca Exp $") #include #include #include /* ARGSUSED0 */ int main(argc, argv) int argc; char *argv[]; { int m, r; SM_FILE_T *out; sm_test_begin(argc, argv, "test sm_io_fopen"); out = sm_io_fopen("foo", O_WRONLY|O_APPEND|O_CREAT, 0666); SM_TEST(out != NULL); if (out != NULL) { (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "foo\n"); r = sm_io_getinfo(out, SM_IO_WHAT_MODE, &m); SM_TEST(r == 0); SM_TEST(m == SM_IO_WRONLY); sm_io_close(out, SM_TIME_DEFAULT); } return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/sem.c0000644000175000017500000000727510277204437016143 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: sem.c,v 1.13 2005/08/12 20:39:59 ca Exp $") #if SM_CONF_SEM # include # include # include # include # include /* ** SM_SEM_START -- initialize semaphores ** ** Parameters: ** key -- key for semaphores. ** nsem -- number of semaphores. ** semflg -- flag for semget(), if 0, use a default. ** owner -- create semaphores. ** ** Returns: ** id for semaphores. ** < 0 on failure. */ int sm_sem_start(key, nsem, semflg, owner) key_t key; int nsem; int semflg; bool owner; { int semid, i, err; unsigned short *semvals; semvals = NULL; if (semflg == 0) semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3); if (owner) semflg |= IPC_CREAT|IPC_EXCL; semid = semget(key, nsem, semflg); if (semid < 0) goto error; if (owner) { union semun semarg; semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals); if (semvals == NULL) goto error; semarg.array = semvals; /* initialize semaphore values to be available */ for (i = 0; i < nsem; i++) semvals[i] = 1; if (semctl(semid, 0, SETALL, semarg) < 0) goto error; } return semid; error: err = errno; if (semvals != NULL) sm_free(semvals); if (semid >= 0) sm_sem_stop(semid); return (err > 0) ? (0 - err) : -1; } /* ** SM_SEM_STOP -- stop using semaphores. ** ** Parameters: ** semid -- id for semaphores. ** ** Returns: ** 0 on success. ** < 0 on failure. */ int sm_sem_stop(semid) int semid; { return semctl(semid, 0, IPC_RMID, NULL); } /* ** SM_SEM_ACQ -- acquire semaphore. ** ** Parameters: ** semid -- id for semaphores. ** semnum -- number of semaphore. ** timeout -- how long to wait for operation to succeed. ** ** Returns: ** 0 on success. ** < 0 on failure. */ int sm_sem_acq(semid, semnum, timeout) int semid; int semnum; int timeout; { int r; struct sembuf semops[1]; semops[0].sem_num = semnum; semops[0].sem_op = -1; semops[0].sem_flg = SEM_UNDO | (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) return semop(semid, semops, 1); do { r = semop(semid, semops, 1); if (r == 0) return r; sleep(1); --timeout; } while (timeout > 0); return r; } /* ** SM_SEM_REL -- release semaphore. ** ** Parameters: ** semid -- id for semaphores. ** semnum -- number of semaphore. ** timeout -- how long to wait for operation to succeed. ** ** Returns: ** 0 on success. ** < 0 on failure. */ int sm_sem_rel(semid, semnum, timeout) int semid; int semnum; int timeout; { int r; struct sembuf semops[1]; #if PARANOID /* XXX should we check whether the value is already 0 ? */ SM_REQUIRE(sm_get_sem(semid, semnum) > 0); #endif /* PARANOID */ semops[0].sem_num = semnum; semops[0].sem_op = 1; semops[0].sem_flg = SEM_UNDO | (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) return semop(semid, semops, 1); do { r = semop(semid, semops, 1); if (r == 0) return r; sleep(1); --timeout; } while (timeout > 0); return r; } /* ** SM_SEM_GET -- get semaphore value. ** ** Parameters: ** semid -- id for semaphores. ** semnum -- number of semaphore. ** ** Returns: ** value of semaphore on success. ** < 0 on failure. */ int sm_sem_get(semid, semnum) int semid; int semnum; { int semval; if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0) return -1; return semval; } #endif /* SM_CONF_SEM */ dk-milter-1.0.0.dfsg/libsm/stringf.c0000644000175000017500000000342407347306541017026 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: stringf.c,v 1.15 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include #include /* ** SM_STRINGF_X -- printf() to dynamically allocated string. ** ** Takes the same arguments as printf. ** It returns a pointer to a dynamically allocated string ** containing the text that printf would print to standard output. ** It raises an exception on error. ** The name comes from a PWB Unix function called stringf. ** ** Parameters: ** fmt -- format string. ** ... -- arguments for format. ** ** Returns: ** Pointer to a dynamically allocated string. ** ** Exceptions: ** F:sm_heap -- out of memory (via sm_vstringf_x()). */ char * #if SM_VA_STD sm_stringf_x(const char *fmt, ...) #else /* SM_VA_STD */ sm_stringf_x(fmt, va_alist) const char *fmt; va_dcl #endif /* SM_VA_STD */ { SM_VA_LOCAL_DECL char *s; SM_VA_START(ap, fmt); s = sm_vstringf_x(fmt, ap); SM_VA_END(ap); return s; } /* ** SM_VSTRINGF_X -- printf() to dynamically allocated string. ** ** Parameters: ** fmt -- format string. ** ap -- arguments for format. ** ** Returns: ** Pointer to a dynamically allocated string. ** ** Exceptions: ** F:sm_heap -- out of memory */ char * sm_vstringf_x(fmt, ap) const char *fmt; SM_VA_LOCAL_DECL { char *s; sm_vasprintf(&s, fmt, ap); if (s == NULL) { if (errno == ENOMEM) sm_exc_raise_x(&SmHeapOutOfMemory); sm_exc_raisenew_x(&SmEtypeOs, errno, "sm_vasprintf", NULL); } return s; } dk-milter-1.0.0.dfsg/libsm/Build0000755000175000017500000000053407242406022016157 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: Build,v 1.4 2001/02/14 04:39:46 gshapiro Exp $ exec sh ../devtools/bin/Build $* dk-milter-1.0.0.dfsg/libsm/t-rpool.c0000644000175000017500000000300507347306541016741 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-rpool.c,v 1.18 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include static void rfree __P(( void *cx)); static void rfree(cx) void *cx; { (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "rfree freeing `%s'\n", (char *) cx); } int main(argc, argv) int argc; char *argv[]; { SM_RPOOL_T *rpool; char *a[26]; int i, j; SM_RPOOL_ATTACH_T att; sm_test_begin(argc, argv, "test rpool"); sm_debug_addsetting_x("sm_check_heap", 1); rpool = sm_rpool_new_x(NULL); SM_TEST(rpool != NULL); att = sm_rpool_attach_x(rpool, rfree, "attachment #1"); SM_TEST(att != NULL); for (i = 0; i < 26; ++i) { size_t sz = i * i * i; a[i] = sm_rpool_malloc_x(rpool, sz); for (j = 0; j < sz; ++j) a[i][j] = 'a' + i; } att = sm_rpool_attach_x(rpool, rfree, "attachment #2"); (void) sm_rpool_attach_x(rpool, rfree, "attachment #3"); sm_rpool_detach(att); /* XXX more tests? */ #if DEBUG sm_dprintf("heap after filling up rpool:\n"); sm_heap_report(smioout, 3); sm_dprintf("freeing rpool:\n"); sm_rpool_free(rpool); sm_dprintf("heap after freeing rpool:\n"); sm_heap_report(smioout, 3); #endif /* DEBUG */ return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/t-string.c0000644000175000017500000000171407347306541017121 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-string.c,v 1.11 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include int main(argc, argv) int argc; char **argv; { char *s; char buf[4096]; char foo[4]; char *r; int n; sm_test_begin(argc, argv, "test string utilities"); s = sm_stringf_x("%.3s%03d", "foobar", 42); r = "foo042"; SM_TEST(strcmp(s, r) == 0); s = sm_stringf_x("+%*x+", 2000, 0xCAFE); sm_snprintf(buf, 4096, "+%*x+", 2000, 0xCAFE); SM_TEST(strcmp(s, buf) == 0); foo[3] = 1; n = sm_snprintf(foo, sizeof(foo), "foobar%dbaz", 42); SM_TEST(n == 11); r = "foo"; SM_TEST(strcmp(foo, r) == 0); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/test.c0000644000175000017500000000534607416631140016327 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(Id, "@(#)$Id: test.c,v 1.16 2002/01/08 17:54:40 ca Exp $") /* ** Abstractions for writing libsm test programs. */ #include #include #include #include #include extern char *optarg; extern int optind; extern int optopt; extern int opterr; int SmTestIndex; int SmTestNumErrors; bool SmTestVerbose; static char Help[] = "\ %s [-h] [-d debugging] [-v]\n\ \n\ %s\n\ \n\ -h Display this help information.\n\ -d debugging Set debug activation levels.\n\ -v Verbose output.\n\ "; static char Usage[] = "\ Usage: %s [-h] [-v]\n\ Use %s -h for help.\n\ "; /* ** SM_TEST_BEGIN -- initialize test system. ** ** Parameters: ** argc -- argument counter. ** argv -- argument vector. ** testname -- description of tests. ** ** Results: ** none. */ void sm_test_begin(argc, argv, testname) int argc; char **argv; char *testname; { int c; SmTestIndex = 0; SmTestNumErrors = 0; SmTestVerbose = false; opterr = 0; while ((c = getopt(argc, argv, "vhd:")) != -1) { switch (c) { case 'v': SmTestVerbose = true; break; case 'd': sm_debug_addsettings_x(optarg); break; case 'h': (void) fprintf(stdout, Help, argv[0], testname); exit(0); default: (void) fprintf(stderr, "Unknown command line option -%c\n", optopt); (void) fprintf(stderr, Usage, argv[0], argv[0]); exit(1); } } } /* ** SM_TEST -- single test. ** ** Parameters: ** success -- did test succeeed? ** expr -- expression that has been evaluated. ** filename -- guess... ** lineno -- line number. ** ** Results: ** value of success. */ bool sm_test(success, expr, filename, lineno) bool success; char *expr; char *filename; int lineno; { ++SmTestIndex; if (SmTestVerbose) (void) fprintf(stderr, "%d..", SmTestIndex); if (!success) { ++SmTestNumErrors; if (!SmTestVerbose) (void) fprintf(stderr, "%d..", SmTestIndex); (void) fprintf(stderr, "bad! %s:%d %s\n", filename, lineno, expr); } else { if (SmTestVerbose) (void) fprintf(stderr, "ok\n"); } return success; } /* ** SM_TEST_END -- end of test system. ** ** Parameters: ** none. ** ** Results: ** number of errors. */ int sm_test_end() { (void) fprintf(stderr, "%d of %d tests completed successfully\n", SmTestIndex - SmTestNumErrors, SmTestIndex); if (SmTestNumErrors != 0) (void) fprintf(stderr, "*** %d error%s in test! ***\n", SmTestNumErrors, SmTestNumErrors > 1 ? "s" : ""); return SmTestNumErrors; } dk-milter-1.0.0.dfsg/libsm/local.h0000644000175000017500000002333710542040427016443 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004-2006 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: local.h,v 1.58 2006/12/19 19:44:23 ca Exp $ */ /* ** Information local to this implementation of stdio, ** in particular, macros and private variables. */ #include #if !SM_CONF_MEMCHR # include #endif /* !SM_CONF_MEMCHR */ #include int sm_flush __P((SM_FILE_T *, int *)); SM_FILE_T *smfp __P((void)); int sm_refill __P((SM_FILE_T *, int)); void sm_init __P((void)); void sm_cleanup __P((void)); void sm_makebuf __P((SM_FILE_T *)); int sm_whatbuf __P((SM_FILE_T *, size_t *, int *)); int sm_fwalk __P((int (*)(SM_FILE_T *, int *), int *)); int sm_wsetup __P((SM_FILE_T *)); int sm_flags __P((int)); SM_FILE_T *sm_fp __P((const SM_FILE_T *, const int, SM_FILE_T *)); int sm_vprintf __P((int, char const *, va_list)); /* std io functions */ ssize_t sm_stdread __P((SM_FILE_T *, char *, size_t)); ssize_t sm_stdwrite __P((SM_FILE_T *, char const *, size_t)); off_t sm_stdseek __P((SM_FILE_T *, off_t, int)); int sm_stdclose __P((SM_FILE_T *)); int sm_stdopen __P((SM_FILE_T *, const void *, int, const void *)); int sm_stdfdopen __P((SM_FILE_T *, const void *, int, const void *)); int sm_stdsetinfo __P((SM_FILE_T *, int , void *)); int sm_stdgetinfo __P((SM_FILE_T *, int , void *)); /* stdio io functions */ ssize_t sm_stdioread __P((SM_FILE_T *, char *, size_t)); ssize_t sm_stdiowrite __P((SM_FILE_T *, char const *, size_t)); off_t sm_stdioseek __P((SM_FILE_T *, off_t, int)); int sm_stdioclose __P((SM_FILE_T *)); int sm_stdioopen __P((SM_FILE_T *, const void *, int, const void *)); int sm_stdiosetinfo __P((SM_FILE_T *, int , void *)); int sm_stdiogetinfo __P((SM_FILE_T *, int , void *)); /* string io functions */ ssize_t sm_strread __P((SM_FILE_T *, char *, size_t)); ssize_t sm_strwrite __P((SM_FILE_T *, char const *, size_t)); off_t sm_strseek __P((SM_FILE_T *, off_t, int)); int sm_strclose __P((SM_FILE_T *)); int sm_stropen __P((SM_FILE_T *, const void *, int, const void *)); int sm_strsetinfo __P((SM_FILE_T *, int , void *)); int sm_strgetinfo __P((SM_FILE_T *, int , void *)); /* syslog io functions */ ssize_t sm_syslogread __P((SM_FILE_T *, char *, size_t)); ssize_t sm_syslogwrite __P((SM_FILE_T *, char const *, size_t)); off_t sm_syslogseek __P((SM_FILE_T *, off_t, int)); int sm_syslogclose __P((SM_FILE_T *)); int sm_syslogopen __P((SM_FILE_T *, const void *, int, const void *)); int sm_syslogsetinfo __P((SM_FILE_T *, int , void *)); int sm_sysloggetinfo __P((SM_FILE_T *, int , void *)); extern bool Sm_IO_DidInit; /* Return true iff the given SM_FILE_T cannot be written now. */ #define cantwrite(fp) \ ((((fp)->f_flags & SMWR) == 0 || (fp)->f_bf.smb_base == NULL) && \ sm_wsetup(fp)) /* ** Test whether the given stdio file has an active ungetc buffer; ** release such a buffer, without restoring ordinary unread data. */ #define HASUB(fp) ((fp)->f_ub.smb_base != NULL) #define FREEUB(fp) \ { \ if ((fp)->f_ub.smb_base != (fp)->f_ubuf) \ sm_free((char *)(fp)->f_ub.smb_base); \ (fp)->f_ub.smb_base = NULL; \ } extern const char SmFileMagic[]; #define SM_ALIGN(p) (((unsigned long)(p) + SM_ALIGN_BITS) & ~SM_ALIGN_BITS) #define sm_io_flockfile(fp) ((void) 0) #define sm_io_funlockfile(fp) ((void) 0) int sm_flags __P((int)); #ifndef FDSET_CAST # define FDSET_CAST /* empty cast for fd_set arg to select */ #endif /* ** SM_CONVERT_TIME -- convert the API timeout flag for select() usage. ** ** This takes a 'fp' (a file type pointer) and obtains the "raw" ** file descriptor (fd) if possible. The 'fd' is needed to possibly ** switch the mode of the file (blocking/non-blocking) to match ** the type of timeout. If timeout is SM_TIME_FOREVER then the ** timeout using select won't be needed and the file is best placed ** in blocking mode. If there is to be a finite timeout then the file ** is best placed in non-blocking mode. Then, if not enough can be ** written, select() can be used to test when something can be written ** yet still timeout if the wait is too long. ** If the mode is already in the correct state we don't change it. ** Iff (yes "iff") the 'fd' is "-1" in value then the mode change ** will not happen. This situation arises when a late-binding-to-disk ** file type is in use. An example of this is the sendmail buffered ** file type (in sendmail/bf.c). ** ** Parameters ** fp -- the file pointer the timeout is for ** fd -- to become the file descriptor value from 'fp' ** val -- the timeout value to be converted ** time -- a struct timeval holding the converted value ** ** Returns ** nothing, this is flow-through code ** ** Side Effects: ** May or may not change the mode of a currently open file. ** The file mode may be changed to O_NONBLOCK or ~O_NONBLOCK ** (meaning block). This is done to best match the type of ** timeout and for (possible) use with select(). */ #ifdef WIN32 # define SM_CONVERT_TIME(fp, fd, val, time) { /*empty */ } #else /* WIN32 */ # define SM_CONVERT_TIME(fp, fd, val, time) { \ if (((fd) = sm_io_getinfo(fp, SM_IO_WHAT_FD, NULL)) == -1) \ { \ /* can't get an fd, likely internal 'fake' fp */ \ errno = 0; \ } \ if ((val) == SM_TIME_DEFAULT) \ (val) = (fp)->f_timeout; \ if ((val) == SM_TIME_IMMEDIATE || (val) == SM_TIME_FOREVER) \ { \ (time)->tv_sec = 0; \ (time)->tv_usec = 0; \ } \ else \ { \ (time)->tv_sec = (val) / 1000; \ (time)->tv_usec = ((val) - ((time)->tv_sec * 1000)) * 1000; \ } \ if ((val) == SM_TIME_FOREVER) \ { \ if ((fp)->f_timeoutstate == SM_TIME_NONBLOCK && (fd) != -1) \ { \ int ret; \ ret = fcntl((fd), F_GETFL, 0); \ if (ret == -1 || fcntl((fd), F_SETFL, \ ret & ~O_NONBLOCK) == -1) \ { \ /* errno should be set */ \ return SM_IO_EOF; \ } \ (fp)->f_timeoutstate = SM_TIME_BLOCK; \ if ((fp)->f_modefp != NULL) \ (fp)->f_modefp->f_timeoutstate = SM_TIME_BLOCK; \ } \ } \ else { \ if ((fp)->f_timeoutstate == SM_TIME_BLOCK && (fd) != -1) \ { \ int ret; \ ret = fcntl((fd), F_GETFL, 0); \ if (ret == -1 || fcntl((fd), F_SETFL, \ ret | O_NONBLOCK) == -1) \ { \ /* errno should be set */ \ return SM_IO_EOF; \ } \ (fp)->f_timeoutstate = SM_TIME_NONBLOCK; \ if ((fp)->f_modefp != NULL) \ (fp)->f_modefp->f_timeoutstate = SM_TIME_NONBLOCK; \ } \ } \ } #endif /* WIN32 */ #ifndef WIN32 /* ** SM_IO_WR_TIMEOUT -- setup the timeout for the write ** ** This #define uses a select() to wait for the 'fd' to become writable. ** The select() can be active for up to 'to' time. The select may not ** use all of the the 'to' time. Hence, the amount of "wall-clock" time is ** measured to decide how much to subtract from 'to' to update it. On some ** BSD-based/like systems the timeout for a select is updated for the ** amount of time used. On many/most systems this does not happen. Therefore ** the updating of 'to' must be done ourselves; a copy of 'to' is passed ** since a BSD-like system will have updated it and we don't want to ** double the time used! ** Note: if a valid 'fd' doesn't exist yet, don't use this (e.g. the ** sendmail buffered file type in sendmail/bf.c; see fvwrite.c). ** ** Parameters ** fd -- a file descriptor for doing select() with ** timeout -- the original user set value. ** ** Returns ** nothing, this is flow through code ** ** Side Effects: ** adjusts 'timeout' for time used */ #define SM_IO_WR_TIMEOUT(fp, fd, to) { \ struct timeval sm_io_to_before, sm_io_to_after, sm_io_to_diff; \ struct timeval sm_io_to; \ int sm_io_to_sel; \ fd_set sm_io_to_mask, sm_io_x_mask; \ errno = 0; \ if ((to) == SM_TIME_DEFAULT) \ (to) = (fp)->f_timeout; \ if ((to) == SM_TIME_IMMEDIATE) \ { \ errno = EAGAIN; \ return SM_IO_EOF; \ } \ else if ((to) == SM_TIME_FOREVER) \ { \ errno = EINVAL; \ return SM_IO_EOF; \ } \ else \ { \ sm_io_to.tv_sec = (to) / 1000; \ sm_io_to.tv_usec = ((to) - (sm_io_to.tv_sec * 1000)) * 1000; \ } \ if (FD_SETSIZE > 0 && (fd) >= FD_SETSIZE) \ { \ errno = EINVAL; \ return SM_IO_EOF; \ } \ FD_ZERO(&sm_io_to_mask); \ FD_SET((fd), &sm_io_to_mask); \ FD_ZERO(&sm_io_x_mask); \ FD_SET((fd), &sm_io_x_mask); \ if (gettimeofday(&sm_io_to_before, NULL) < 0) \ return SM_IO_EOF; \ do \ { \ sm_io_to_sel = select((fd) + 1, NULL, &sm_io_to_mask, \ &sm_io_x_mask, &sm_io_to); \ } while (sm_io_to_sel < 0 && errno == EINTR); \ if (sm_io_to_sel < 0) \ { \ /* something went wrong, errno set */ \ return SM_IO_EOF; \ } \ else if (sm_io_to_sel == 0) \ { \ /* timeout */ \ errno = EAGAIN; \ return SM_IO_EOF; \ } \ /* else loop again */ \ if (gettimeofday(&sm_io_to_after, NULL) < 0) \ return SM_IO_EOF; \ timersub(&sm_io_to_after, &sm_io_to_before, &sm_io_to_diff); \ (to) -= (sm_io_to_diff.tv_sec * 1000); \ (to) -= (sm_io_to_diff.tv_usec / 1000); \ if ((to) < 0) \ (to) = 0; \ } /* ** If there is no 'fd' just error (we can't timeout). If the timeout ** is SM_TIME_FOREVER then there is no need to do a timeout with ** select since this will be a real error. If the error is not ** EAGAIN/EWOULDBLOCK (from a nonblocking) then it's a real error. ** Specify the condition here as macro so it can be used in several places. */ #define IS_IO_ERROR(fd, ret, to) \ ((fd) < 0 || \ ((ret) < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || \ (to) == SM_TIME_FOREVER) #else /* ! WIN32 */ #define IS_IO_ERROR(fd, ret, to) ((ret) < 0 || (to) == SM_TIME_FOREVER) #define SM_IO_WR_TIMEOUT(fp, fd, timeout) (void) 0 #endif /* ! WIN32 */ dk-milter-1.0.0.dfsg/libsm/fopen.c0000644000175000017500000002051210253661450016447 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fopen.c,v 1.62 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #include #include #include "local.h" static void openalrm __P((int)); static void reopenalrm __P((int)); extern int sm_io_fclose __P((SM_FILE_T *)); static jmp_buf OpenTimeOut, ReopenTimeOut; /* ** OPENALRM -- handler when timeout activated for sm_io_open() ** ** Returns flow of control to where setjmp(OpenTimeOut) was set. ** ** Parameters: ** sig -- unused ** ** Returns: ** does not return ** ** Side Effects: ** returns flow of control to setjmp(OpenTimeOut). ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED0 */ static void openalrm(sig) int sig; { longjmp(OpenTimeOut, 1); } /* ** REOPENALRM -- handler when timeout activated for sm_io_reopen() ** ** Returns flow of control to where setjmp(ReopenTimeOut) was set. ** ** Parameters: ** sig -- unused ** ** Returns: ** does not return ** ** Side Effects: ** returns flow of control to setjmp(ReopenTimeOut). ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED0 */ static void reopenalrm(sig) int sig; { longjmp(ReopenTimeOut, 1); } /* ** SM_IO_OPEN -- open a file of a specific type ** ** Parameters: ** type -- type of file to open ** timeout -- time to complete the open ** info -- info describing what is to be opened (type dependant) ** flags -- user selected flags ** rpool -- pointer to rpool to be used for this open ** ** Returns: ** Raises exception on heap exhaustion. ** Aborts if type is invalid. ** Returns NULL and sets errno ** - when the type specific open fails ** - when open vector errors ** - when flags not set or invalid ** Success returns a file pointer to the opened file type. */ SM_FILE_T * sm_io_open(type, timeout, info, flags, rpool) const SM_FILE_T *type; int SM_NONVOLATILE timeout; /* this is not the file type timeout */ const void *info; int flags; const void *rpool; { register SM_FILE_T *fp; int ioflags; SM_EVENT *evt = NULL; ioflags = sm_flags(flags); if (ioflags == 0) { /* must give some indication/intent */ errno = EINVAL; return NULL; } if (timeout == SM_TIME_DEFAULT) timeout = SM_TIME_FOREVER; if (timeout == SM_TIME_IMMEDIATE) { errno = EAGAIN; return NULL; } fp = sm_fp(type, ioflags, NULL); /* Okay, this is where we set the timeout. */ if (timeout != SM_TIME_FOREVER) { if (setjmp(OpenTimeOut) != 0) { errno = EAGAIN; return NULL; } evt = sm_seteventm(timeout, openalrm, 0); } if ((*fp->f_open)(fp, info, flags, rpool) < 0) { fp->f_flags = 0; /* release */ fp->sm_magic = NULL; /* release */ return NULL; } /* We're back. So undo our timeout and handler */ if (evt != NULL) sm_clrevent(evt); #if SM_RPOOL if (rpool != NULL) sm_rpool_attach_x(rpool, sm_io_fclose, fp); #endif /* SM_RPOOL */ return fp; } /* ** SM_IO_DUP -- duplicate a file pointer ** ** Parameters: ** fp -- file pointer to duplicate ** ** Returns: ** Success - the duplicated file pointer ** Failure - NULL (was an invalid file pointer or too many open) ** ** Increments the duplicate counter (dup_cnt) for the open file pointer. ** The counter counts the number of duplicates. When the duplicate ** counter is 0 (zero) then the file pointer is the only one left ** (no duplicates, it is the only one). */ SM_FILE_T * sm_io_dup(fp) SM_FILE_T *fp; { SM_REQUIRE_ISA(fp, SmFileMagic); if (fp->sm_magic != SmFileMagic) { errno = EBADF; return NULL; } if (fp->f_dup_cnt >= INT_MAX - 1) { /* Can't let f_dup_cnt wrap! */ errno = EMFILE; return NULL; } fp->f_dup_cnt++; return fp; } /* ** SM_IO_REOPEN -- open a new file using the old file pointer ** ** Parameters: ** type -- file type to be opened ** timeout -- time to complete the reopen ** info -- infomation about what is to be "re-opened" (type dep.) ** flags -- user flags to map to internal flags ** rpool -- rpool file to be associated with ** fp -- the file pointer to reuse ** ** Returns: ** Raises an exception on heap exhaustion. ** Aborts if type is invalid. ** Failure: returns NULL ** Success: returns "reopened" file pointer */ SM_FILE_T * sm_io_reopen(type, timeout, info, flags, rpool, fp) const SM_FILE_T *type; int SM_NONVOLATILE timeout; const void *info; int flags; const void *rpool; SM_FILE_T *fp; { int ioflags, ret; SM_FILE_T *fp2; SM_EVENT *evt = NULL; if ((ioflags = sm_flags(flags)) == 0) { (void) sm_io_close(fp, timeout); return NULL; } if (!Sm_IO_DidInit) sm_init(); if (timeout == SM_TIME_DEFAULT) timeout = SM_TIME_FOREVER; if (timeout == SM_TIME_IMMEDIATE) { /* ** Filling the buffer will take time and we are wanted to ** return immediately. So... */ errno = EAGAIN; return NULL; } /* Okay, this is where we set the timeout. */ if (timeout != SM_TIME_FOREVER) { if (setjmp(ReopenTimeOut) != 0) { errno = EAGAIN; return NULL; } evt = sm_seteventm(timeout, reopenalrm, 0); } /* ** There are actually programs that depend on being able to "reopen" ** descriptors that weren't originally open. Keep this from breaking. ** Remember whether the stream was open to begin with, and which file ** descriptor (if any) was associated with it. If it was attached to ** a descriptor, defer closing it; reopen("/dev/stdin", "r", stdin) ** should work. This is unnecessary if it was not a Unix file. */ if (fp != NULL) { if (fp->sm_magic != SmFileMagic) fp->f_flags = SMFEOF; /* hold on to it */ else { /* flush the stream; ANSI doesn't require this. */ (void) sm_io_flush(fp, SM_TIME_FOREVER); (void) sm_io_close(fp, SM_TIME_FOREVER); } } fp2 = sm_fp(type, ioflags, fp); ret = (*fp2->f_open)(fp2, info, flags, rpool); /* We're back. So undo our timeout and handler */ if (evt != NULL) sm_clrevent(evt); if (ret < 0) { fp2->f_flags = 0; /* release */ fp2->sm_magic = NULL; /* release */ return NULL; } /* ** We're not preserving this logic (below) for sm_io because it is now ** abstracted at least one "layer" away. By closing and reopening ** the 1st fd used should be the just released one (when Unix ** behavior followed). Old comment:: ** If reopening something that was open before on a real file, try ** to maintain the descriptor. Various C library routines (perror) ** assume stderr is always fd STDERR_FILENO, even if being reopen'd. */ #if SM_RPOOL if (rpool != NULL) sm_rpool_attach_x(rpool, sm_io_close, fp2); #endif /* SM_RPOOL */ return fp2; } /* ** SM_IO_AUTOFLUSH -- link another file to this for auto-flushing ** ** When a read occurs on fp, fp2 will be flushed iff there is no ** data waiting on fp. ** ** Parameters: ** fp -- the file opened for reading. ** fp2 -- the file opened for writing. ** ** Returns: ** The old flush file pointer. */ SM_FILE_T * sm_io_autoflush(fp, fp2) SM_FILE_T *fp; SM_FILE_T *fp2; { SM_FILE_T *savefp; SM_REQUIRE_ISA(fp, SmFileMagic); if (fp2 != NULL) SM_REQUIRE_ISA(fp2, SmFileMagic); savefp = fp->f_flushfp; fp->f_flushfp = fp2; return savefp; } /* ** SM_IO_AUTOMODE -- link another file to this for auto-moding ** ** When the mode (blocking or non-blocking) changes for fp1 then ** update fp2's mode at the same time. This is to be used when ** a system dup() has generated a second file descriptor for ** another sm_io_open() by file descriptor. The modes have been ** linked in the system and this formalizes it for sm_io internally. ** ** Parameters: ** fp1 -- the first file ** fp2 -- the second file ** ** Returns: ** nothing */ void sm_io_automode(fp1, fp2) SM_FILE_T *fp1; SM_FILE_T *fp2; { SM_REQUIRE_ISA(fp1, SmFileMagic); SM_REQUIRE_ISA(fp2, SmFileMagic); fp1->f_modefp = fp2; fp2->f_modefp = fp1; } dk-milter-1.0.0.dfsg/libsm/mbdb.c0000644000175000017500000004103407765510253016256 0ustar madhackmadhack/* * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: mbdb.c,v 1.40 2003/12/10 03:19:07 gshapiro Exp $") #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef WIN32 # ifdef EX_OK # undef EX_OK /* for SVr4.2 SMP */ # endif /* EX_OK */ #endif /* ! WIN32 */ #include #if LDAPMAP # if _LDAP_EXAMPLE_ # include # endif /* _LDAP_EXAMPLE_ */ #endif /* LDAPMAP */ typedef struct { char *mbdb_typename; int (*mbdb_initialize) __P((char *)); int (*mbdb_lookup) __P((char *name, SM_MBDB_T *user)); void (*mbdb_terminate) __P((void)); } SM_MBDB_TYPE_T; static int mbdb_pw_initialize __P((char *)); static int mbdb_pw_lookup __P((char *name, SM_MBDB_T *user)); static void mbdb_pw_terminate __P((void)); #if LDAPMAP # if _LDAP_EXAMPLE_ static struct sm_ldap_struct LDAPLMAP; static int mbdb_ldap_initialize __P((char *)); static int mbdb_ldap_lookup __P((char *name, SM_MBDB_T *user)); static void mbdb_ldap_terminate __P((void)); # endif /* _LDAP_EXAMPLE_ */ #endif /* LDAPMAP */ static SM_MBDB_TYPE_T SmMbdbTypes[] = { { "pw", mbdb_pw_initialize, mbdb_pw_lookup, mbdb_pw_terminate }, #if LDAPMAP # if _LDAP_EXAMPLE_ { "ldap", mbdb_ldap_initialize, mbdb_ldap_lookup, mbdb_ldap_terminate }, # endif /* _LDAP_EXAMPLE_ */ #endif /* LDAPMAP */ { NULL, NULL, NULL, NULL } }; static SM_MBDB_TYPE_T *SmMbdbType = &SmMbdbTypes[0]; /* ** SM_MBDB_INITIALIZE -- specify which mailbox database to use ** ** If this function is not called, then the "pw" implementation ** is used by default; this implementation uses getpwnam(). ** ** Parameters: ** mbdb -- Which mailbox database to use. ** The argument has the form "name" or "name.arg". ** "pw" means use getpwnam(). ** ** Results: ** EX_OK on success, or an EX_* code on failure. */ int sm_mbdb_initialize(mbdb) char *mbdb; { size_t namelen; int err; char *name; char *arg; SM_MBDB_TYPE_T *t; SM_REQUIRE(mbdb != NULL); name = mbdb; arg = strchr(mbdb, '.'); if (arg == NULL) namelen = strlen(name); else { namelen = arg - name; ++arg; } for (t = SmMbdbTypes; t->mbdb_typename != NULL; ++t) { if (strlen(t->mbdb_typename) == namelen && strncmp(name, t->mbdb_typename, namelen) == 0) { err = EX_OK; if (t->mbdb_initialize != NULL) err = t->mbdb_initialize(arg); if (err == EX_OK) SmMbdbType = t; return err; } } return EX_UNAVAILABLE; } /* ** SM_MBDB_TERMINATE -- terminate connection to the mailbox database ** ** Because this function closes any cached file descriptors that ** are being held open for the connection to the mailbox database, ** it should be called for security reasons prior to dropping privileges ** and execing another process. ** ** Parameters: ** none. ** ** Results: ** none. */ void sm_mbdb_terminate() { if (SmMbdbType->mbdb_terminate != NULL) SmMbdbType->mbdb_terminate(); } /* ** SM_MBDB_LOOKUP -- look up a local mail recipient, given name ** ** Parameters: ** name -- name of local mail recipient ** user -- pointer to structure to fill in on success ** ** Results: ** On success, fill in *user and return EX_OK. ** If the user does not exist, return EX_NOUSER. ** If a temporary failure (eg, a network failure) occurred, ** return EX_TEMPFAIL. Otherwise return EX_OSERR. */ int sm_mbdb_lookup(name, user) char *name; SM_MBDB_T *user; { int ret = EX_NOUSER; if (SmMbdbType->mbdb_lookup != NULL) ret = SmMbdbType->mbdb_lookup(name, user); return ret; } /* ** SM_MBDB_FROMPW -- copy from struct pw to SM_MBDB_T ** ** Parameters: ** user -- destination user information structure ** pw -- source passwd structure ** ** Results: ** none. */ void sm_mbdb_frompw(user, pw) SM_MBDB_T *user; struct passwd *pw; { SM_REQUIRE(user != NULL); (void) sm_strlcpy(user->mbdb_name, pw->pw_name, sizeof(user->mbdb_name)); user->mbdb_uid = pw->pw_uid; user->mbdb_gid = pw->pw_gid; sm_pwfullname(pw->pw_gecos, pw->pw_name, user->mbdb_fullname, sizeof(user->mbdb_fullname)); (void) sm_strlcpy(user->mbdb_homedir, pw->pw_dir, sizeof(user->mbdb_homedir)); (void) sm_strlcpy(user->mbdb_shell, pw->pw_shell, sizeof(user->mbdb_shell)); } /* ** SM_PWFULLNAME -- build full name of user from pw_gecos field. ** ** This routine interprets the strange entry that would appear ** in the GECOS field of the password file. ** ** Parameters: ** gecos -- name to build. ** user -- the login name of this user (for &). ** buf -- place to put the result. ** buflen -- length of buf. ** ** Returns: ** none. */ #if _FFR_HANDLE_ISO8859_GECOS static char Latin1ToASCII[128] = { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 99, 80, 36, 89, 124, 36, 34, 99, 97, 60, 45, 45, 114, 45, 111, 42, 50, 51, 39, 117, 80, 46, 44, 49, 111, 62, 42, 42, 42, 63, 65, 65, 65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73, 68, 78, 79, 79, 79, 79, 79, 88, 79, 85, 85, 85, 85, 89, 80, 66, 97, 97, 97, 97, 97, 97, 97, 99, 101, 101, 101, 101, 105, 105, 105, 105, 100, 110, 111, 111, 111, 111, 111, 47, 111, 117, 117, 117, 117, 121, 112, 121 }; #endif /* _FFR_HANDLE_ISO8859_GECOS */ void sm_pwfullname(gecos, user, buf, buflen) register char *gecos; char *user; char *buf; size_t buflen; { register char *p; register char *bp = buf; if (*gecos == '*') gecos++; /* copy gecos, interpolating & to be full name */ for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) { if (bp >= &buf[buflen - 1]) { /* buffer overflow -- just use login name */ (void) sm_strlcpy(buf, user, buflen); return; } if (*p == '&') { /* interpolate full name */ (void) sm_strlcpy(bp, user, buflen - (bp - buf)); *bp = toupper(*bp); bp += strlen(bp); } else { #if _FFR_HANDLE_ISO8859_GECOS if ((unsigned char) *p >= 128) *bp++ = Latin1ToASCII[(unsigned char) *p - 128]; else #endif /* _FFR_HANDLE_ISO8859_GECOS */ *bp++ = *p; } } *bp = '\0'; } /* ** /etc/passwd implementation. */ /* ** MBDB_PW_INITIALIZE -- initialize getpwnam() version ** ** Parameters: ** arg -- unused. ** ** Results: ** EX_OK. */ /* ARGSUSED0 */ static int mbdb_pw_initialize(arg) char *arg; { return EX_OK; } /* ** MBDB_PW_LOOKUP -- look up a local mail recipient, given name ** ** Parameters: ** name -- name of local mail recipient ** user -- pointer to structure to fill in on success ** ** Results: ** On success, fill in *user and return EX_OK. ** Failure: EX_NOUSER. */ static int mbdb_pw_lookup(name, user) char *name; SM_MBDB_T *user; { struct passwd *pw; #ifdef HESIOD /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */ { char *p; for (p = name; *p != '\0'; p++) if (!isascii(*p) || !isdigit(*p)) break; if (*p == '\0') return EX_NOUSER; } #endif /* HESIOD */ errno = 0; pw = getpwnam(name); if (pw == NULL) { #ifdef WIN32 errno = pwd_errno(); #endif /* WIN32 */ #if 0 /* ** getpwnam() isn't advertised as setting errno. ** In fact, under FreeBSD, non-root getpwnam() on ** non-existant users returns NULL with errno = EPERM. ** This test won't work. */ switch (errno) { case 0: return EX_NOUSER; case EIO: return EX_OSERR; default: return EX_TEMPFAIL; } #endif /* 0 */ return EX_NOUSER; } sm_mbdb_frompw(user, pw); return EX_OK; } /* ** MBDB_PW_TERMINATE -- terminate connection to the mailbox database ** ** Parameters: ** none. ** ** Results: ** none. */ static void mbdb_pw_terminate() { endpwent(); } #if LDAPMAP # if _LDAP_EXAMPLE_ /* ** LDAP example implementation based on RFC 2307, "An Approach for Using ** LDAP as a Network Information Service": ** ** ( nisSchema.1.0 NAME 'uidNumber' ** DESC 'An integer uniquely identifying a user in an ** administrative domain' ** EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE ) ** ** ( nisSchema.1.1 NAME 'gidNumber' ** DESC 'An integer uniquely identifying a group in an ** administrative domain' ** EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE ) ** ** ( nisSchema.1.2 NAME 'gecos' ** DESC 'The GECOS field; the common name' ** EQUALITY caseIgnoreIA5Match ** SUBSTRINGS caseIgnoreIA5SubstringsMatch ** SYNTAX 'IA5String' SINGLE-VALUE ) ** ** ( nisSchema.1.3 NAME 'homeDirectory' ** DESC 'The absolute path to the home directory' ** EQUALITY caseExactIA5Match ** SYNTAX 'IA5String' SINGLE-VALUE ) ** ** ( nisSchema.1.4 NAME 'loginShell' ** DESC 'The path to the login shell' ** EQUALITY caseExactIA5Match ** SYNTAX 'IA5String' SINGLE-VALUE ) ** ** ( nisSchema.2.0 NAME 'posixAccount' SUP top AUXILIARY ** DESC 'Abstraction of an account with POSIX attributes' ** MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) ** MAY ( userPassword $ loginShell $ gecos $ description ) ) ** */ # define MBDB_LDAP_LABEL "MailboxDatabase" # ifndef MBDB_LDAP_FILTER # define MBDB_LDAP_FILTER "(&(objectClass=posixAccount)(uid=%0))" # endif /* MBDB_LDAP_FILTER */ # ifndef MBDB_DEFAULT_LDAP_BASEDN # define MBDB_DEFAULT_LDAP_BASEDN NULL # endif /* MBDB_DEFAULT_LDAP_BASEDN */ # ifndef MBDB_DEFAULT_LDAP_SERVER # define MBDB_DEFAULT_LDAP_SERVER NULL # endif /* MBDB_DEFAULT_LDAP_SERVER */ /* ** MBDB_LDAP_INITIALIZE -- initialize LDAP version ** ** Parameters: ** arg -- LDAP specification ** ** Results: ** EX_OK on success, or an EX_* code on failure. */ static int mbdb_ldap_initialize(arg) char *arg; { sm_ldap_clear(&LDAPLMAP); LDAPLMAP.ldap_base = MBDB_DEFAULT_LDAP_BASEDN; LDAPLMAP.ldap_host = MBDB_DEFAULT_LDAP_SERVER; LDAPLMAP.ldap_filter = MBDB_LDAP_FILTER; /* Only want one match */ LDAPLMAP.ldap_sizelimit = 1; /* interpolate new ldap_base and ldap_host from arg if given */ if (arg != NULL && *arg != '\0') { char *new; char *sep; size_t len; len = strlen(arg) + 1; new = sm_malloc(len); if (new == NULL) return EX_TEMPFAIL; (void) sm_strlcpy(new, arg, len); sep = strrchr(new, '@'); if (sep != NULL) { *sep++ = '\0'; LDAPLMAP.ldap_host = sep; } LDAPLMAP.ldap_base = new; } return EX_OK; } /* ** MBDB_LDAP_LOOKUP -- look up a local mail recipient, given name ** ** Parameters: ** name -- name of local mail recipient ** user -- pointer to structure to fill in on success ** ** Results: ** On success, fill in *user and return EX_OK. ** Failure: EX_NOUSER. */ #define NEED_FULLNAME 0x01 #define NEED_HOMEDIR 0x02 #define NEED_SHELL 0x04 #define NEED_UID 0x08 #define NEED_GID 0x10 static int mbdb_ldap_lookup(name, user) char *name; SM_MBDB_T *user; { int msgid; int need; int ret; int save_errno; LDAPMessage *entry; BerElement *ber; char *attr = NULL; if (strlen(name) >= sizeof(user->mbdb_name)) { errno = EINVAL; return EX_NOUSER; } if (LDAPLMAP.ldap_filter == NULL) { /* map not initialized, but don't have arg here */ errno = EFAULT; return EX_TEMPFAIL; } if (LDAPLMAP.ldap_pid != getpid()) { /* re-open map in this child process */ LDAPLMAP.ldap_ld = NULL; } if (LDAPLMAP.ldap_ld == NULL) { /* map not open, try to open now */ if (!sm_ldap_start(MBDB_LDAP_LABEL, &LDAPLMAP)) return EX_TEMPFAIL; } sm_ldap_setopts(LDAPLMAP.ldap_ld, &LDAPLMAP); msgid = sm_ldap_search(&LDAPLMAP, name); if (msgid == -1) { save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld) + E_LDAPBASE; # ifdef LDAP_SERVER_DOWN if (errno == LDAP_SERVER_DOWN) { /* server disappeared, try reopen on next search */ sm_ldap_close(&LDAPLMAP); } # endif /* LDAP_SERVER_DOWN */ errno = save_errno; return EX_TEMPFAIL; } /* Get results */ ret = ldap_result(LDAPLMAP.ldap_ld, msgid, 1, (LDAPLMAP.ldap_timeout.tv_sec == 0 ? NULL : &(LDAPLMAP.ldap_timeout)), &(LDAPLMAP.ldap_res)); if (ret != LDAP_RES_SEARCH_RESULT && ret != LDAP_RES_SEARCH_ENTRY) { if (ret == 0) errno = ETIMEDOUT; else errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); ret = EX_TEMPFAIL; goto abort; } entry = ldap_first_entry(LDAPLMAP.ldap_ld, LDAPLMAP.ldap_res); if (entry == NULL) { save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); if (save_errno == LDAP_SUCCESS) { errno = ENOENT; ret = EX_NOUSER; } else { errno = save_errno; ret = EX_TEMPFAIL; } goto abort; } # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) /* ** Reset value to prevent lingering ** LDAP_DECODING_ERROR due to ** OpenLDAP 1.X's hack (see below) */ LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS; # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ ret = EX_OK; need = NEED_FULLNAME|NEED_HOMEDIR|NEED_SHELL|NEED_UID|NEED_GID; for (attr = ldap_first_attribute(LDAPLMAP.ldap_ld, entry, &ber); attr != NULL; attr = ldap_next_attribute(LDAPLMAP.ldap_ld, entry, ber)) { char **vals; vals = ldap_get_values(LDAPLMAP.ldap_ld, entry, attr); if (vals == NULL) { errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); if (errno == LDAP_SUCCESS) { ldap_memfree(attr); continue; } /* Must be an error */ errno += E_LDAPBASE; ret = EX_TEMPFAIL; goto abort; } # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) /* ** Reset value to prevent lingering ** LDAP_DECODING_ERROR due to ** OpenLDAP 1.X's hack (see below) */ LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS; # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ if (vals[0] == NULL || vals[0][0] == '\0') goto skip; if (strcasecmp(attr, "gecos") == 0) { if (!bitset(NEED_FULLNAME, need) || strlen(vals[0]) >= sizeof(user->mbdb_fullname)) goto skip; sm_pwfullname(vals[0], name, user->mbdb_fullname, sizeof(user->mbdb_fullname)); need &= ~NEED_FULLNAME; } else if (strcasecmp(attr, "homeDirectory") == 0) { if (!bitset(NEED_HOMEDIR, need) || strlen(vals[0]) >= sizeof(user->mbdb_homedir)) goto skip; (void) sm_strlcpy(user->mbdb_homedir, vals[0], sizeof(user->mbdb_homedir)); need &= ~NEED_HOMEDIR; } else if (strcasecmp(attr, "loginShell") == 0) { if (!bitset(NEED_SHELL, need) || strlen(vals[0]) >= sizeof(user->mbdb_shell)) goto skip; (void) sm_strlcpy(user->mbdb_shell, vals[0], sizeof(user->mbdb_shell)); need &= ~NEED_SHELL; } else if (strcasecmp(attr, "uidNumber") == 0) { char *p; if (!bitset(NEED_UID, need)) goto skip; for (p = vals[0]; *p != '\0'; p++) { /* allow negative numbers */ if (p == vals[0] && *p == '-') { /* but not simply '-' */ if (*(p + 1) == '\0') goto skip; } else if (!isascii(*p) || !isdigit(*p)) goto skip; } user->mbdb_uid = atoi(vals[0]); need &= ~NEED_UID; } else if (strcasecmp(attr, "gidNumber") == 0) { char *p; if (!bitset(NEED_GID, need)) goto skip; for (p = vals[0]; *p != '\0'; p++) { /* allow negative numbers */ if (p == vals[0] && *p == '-') { /* but not simply '-' */ if (*(p + 1) == '\0') goto skip; } else if (!isascii(*p) || !isdigit(*p)) goto skip; } user->mbdb_gid = atoi(vals[0]); need &= ~NEED_GID; } skip: ldap_value_free(vals); ldap_memfree(attr); } errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld); /* ** We check errno != LDAP_DECODING_ERROR since ** OpenLDAP 1.X has a very ugly *undocumented* ** hack of returning this error code from ** ldap_next_attribute() if the library freed the ** ber attribute. See: ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html */ if (errno != LDAP_SUCCESS && errno != LDAP_DECODING_ERROR) { /* Must be an error */ errno += E_LDAPBASE; ret = EX_TEMPFAIL; goto abort; } abort: save_errno = errno; if (attr != NULL) { ldap_memfree(attr); attr = NULL; } if (LDAPLMAP.ldap_res != NULL) { ldap_msgfree(LDAPLMAP.ldap_res); LDAPLMAP.ldap_res = NULL; } if (ret == EX_OK) { if (need == 0) { (void) sm_strlcpy(user->mbdb_name, name, sizeof(user->mbdb_name)); save_errno = 0; } else { ret = EX_NOUSER; save_errno = EINVAL; } } errno = save_errno; return ret; } /* ** MBDB_LDAP_TERMINATE -- terminate connection to the mailbox database ** ** Parameters: ** none. ** ** Results: ** none. */ static void mbdb_ldap_terminate() { sm_ldap_close(&LDAPLMAP); } # endif /* _LDAP_EXAMPLE_ */ #endif /* LDAPMAP */ dk-milter-1.0.0.dfsg/libsm/strto.c0000644000175000017500000001271107413517471016524 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1992 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: strto.c,v 1.18 2001/12/30 04:59:37 gshapiro Exp $") #include #include #include #include #include #include #include #include /* ** SM_STRTOLL -- Convert a string to a (signed) long long integer. ** ** Ignores `locale' stuff. Assumes that the upper and lower case ** alphabets and digits are each contiguous. ** ** Parameters: ** nptr -- string containing number ** endptr -- location of first invalid character ** base -- numeric base that 'nptr' number is based in ** ** Returns: ** Failure: on underflow LLONG_MIN is returned; on overflow ** LLONG_MAX is returned and errno is set. ** When 'endptr' == '\0' then the entire string 'nptr' ** was valid. ** Success: returns the converted number */ LONGLONG_T sm_strtoll(nptr, endptr, base) const char *nptr; char **endptr; register int base; { register bool neg; register const char *s; register LONGLONG_T acc, cutoff; register int c; register int any, cutlim; /* ** Skip white space and pick up leading +/- sign if any. ** If base is 0, allow 0x for hex and 0 for octal, else ** assume decimal; if base is already 16, allow 0x. */ s = nptr; do { c = (unsigned char) *s++; } while (isascii(c) && isspace(c)); if (c == '-') { neg = true; c = *s++; } else { neg = false; if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; /* ** Compute the cutoff value between legal numbers and illegal ** numbers. That is the largest legal value, divided by the ** base. An input number that is greater than this value, if ** followed by a legal input character, is too big. One that ** is equal to this value may be valid or not; the limit ** between valid and invalid numbers is then based on the last ** digit. For instance, if the range for long-long's is ** [-9223372036854775808..9223372036854775807] and the input base ** is 10, cutoff will be set to 922337203685477580 and cutlim to ** either 7 (!neg) or 8 (neg), meaning that if we have ** accumulated a value > 922337203685477580, or equal but the ** next digit is > 7 (or 8), the number is too big, and we will ** return a range error. ** ** Set any if any `digits' consumed; make it negative to indicate ** overflow. */ cutoff = neg ? LLONG_MIN : LLONG_MAX; cutlim = cutoff % base; cutoff /= base; if (neg) { if (cutlim > 0) { cutlim -= base; cutoff += 1; } cutlim = -cutlim; } for (acc = 0, any = 0;; c = (unsigned char) *s++) { if (isascii(c) && isdigit(c)) c -= '0'; else if (isascii(c) && isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0) continue; if (neg) { if (acc < cutoff || (acc == cutoff && c > cutlim)) { any = -1; acc = LLONG_MIN; errno = ERANGE; } else { any = 1; acc *= base; acc -= c; } } else { if (acc > cutoff || (acc == cutoff && c > cutlim)) { any = -1; acc = LLONG_MAX; errno = ERANGE; } else { any = 1; acc *= base; acc += c; } } } if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return acc; } /* ** SM_STRTOULL -- Convert a string to an unsigned long long integer. ** ** Ignores `locale' stuff. Assumes that the upper and lower case ** alphabets and digits are each contiguous. ** ** Parameters: ** nptr -- string containing (unsigned) number ** endptr -- location of first invalid character ** base -- numeric base that 'nptr' number is based in ** ** Returns: ** Failure: on overflow ULLONG_MAX is returned and errno is set. ** When 'endptr' == '\0' then the entire string 'nptr' ** was valid. ** Success: returns the converted number */ ULONGLONG_T sm_strtoull(nptr, endptr, base) const char *nptr; char **endptr; register int base; { register const char *s; register ULONGLONG_T acc, cutoff; register int c; register bool neg; register int any, cutlim; /* See sm_strtoll for comments as to the logic used. */ s = nptr; do { c = (unsigned char) *s++; } while (isascii(c) && isspace(c)); neg = (c == '-'); if (neg) { c = *s++; } else { if (c == '+') c = *s++; } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; cutoff = ULLONG_MAX / (ULONGLONG_T)base; cutlim = ULLONG_MAX % (ULONGLONG_T)base; for (acc = 0, any = 0;; c = (unsigned char) *s++) { if (isascii(c) && isdigit(c)) c -= '0'; else if (isascii(c) && isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0) continue; if (acc > cutoff || (acc == cutoff && c > cutlim)) { any = -1; acc = ULLONG_MAX; errno = ERANGE; } else { any = 1; acc *= (ULONGLONG_T)base; acc += c; } } if (neg && any > 0) acc = -((LONGLONG_T) acc); if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return acc; } dk-milter-1.0.0.dfsg/libsm/ldap.c0000644000175000017500000007552510703536640016300 0ustar madhackmadhack/* * Copyright (c) 2001-2007 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ /* some "deprecated" calls are used, e.g., ldap_get_values() */ #define LDAP_DEPRECATED 1 #include SM_RCSID("@(#)$Id: ldap.c,v 1.80 2007/10/12 00:19:44 ca Exp $") #if LDAPMAP # include # include # include # include # include # include # include # include # include # include # include # include # ifndef WIN32 # ifdef EX_OK # undef EX_OK /* for SVr4.2 SMP */ # endif /* EX_OK */ # endif /* ! WIN32 */ # include SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap", "@(#)$Debug: sm_trace_ldap - trace LDAP operations $"); static void ldaptimeout __P((int)); static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *)); static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *)); /* ** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT ** ** Parameters: ** lmap -- pointer to SM_LDAP_STRUCT to clear ** ** Returns: ** None. ** */ #if _FFR_LDAP_VERSION # if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX ERROR FFR_LDAP_VERSION > _LDAP_VERSION_MAX # endif /* defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX */ # if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN ERROR FFR_LDAP_VERSION < _LDAP_VERSION_MIN # endif /* defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN */ # define SM_LDAP_VERSION_DEFAULT _FFR_LDAP_VERSION #else /* _FFR_LDAP_VERSION */ # define SM_LDAP_VERSION_DEFAULT 0 #endif /* _FFR_LDAP_VERSION */ void sm_ldap_clear(lmap) SM_LDAP_STRUCT *lmap; { if (lmap == NULL) return; lmap->ldap_host = NULL; lmap->ldap_port = LDAP_PORT; lmap->ldap_uri = NULL; lmap->ldap_version = SM_LDAP_VERSION_DEFAULT; lmap->ldap_deref = LDAP_DEREF_NEVER; lmap->ldap_timelimit = LDAP_NO_LIMIT; lmap->ldap_sizelimit = LDAP_NO_LIMIT; # ifdef LDAP_REFERRALS lmap->ldap_options = LDAP_OPT_REFERRALS; # else /* LDAP_REFERRALS */ lmap->ldap_options = 0; # endif /* LDAP_REFERRALS */ lmap->ldap_attrsep = '\0'; lmap->ldap_binddn = NULL; lmap->ldap_secret = NULL; lmap->ldap_method = LDAP_AUTH_SIMPLE; lmap->ldap_base = NULL; lmap->ldap_scope = LDAP_SCOPE_SUBTREE; lmap->ldap_attrsonly = LDAPMAP_FALSE; lmap->ldap_timeout.tv_sec = 0; lmap->ldap_timeout.tv_usec = 0; lmap->ldap_ld = NULL; lmap->ldap_filter = NULL; lmap->ldap_attr[0] = NULL; lmap->ldap_attr_type[0] = SM_LDAP_ATTR_NONE; lmap->ldap_attr_needobjclass[0] = NULL; lmap->ldap_res = NULL; lmap->ldap_next = NULL; lmap->ldap_pid = 0; lmap->ldap_multi_args = false; } /* ** SM_LDAP_START -- actually connect to an LDAP server ** ** Parameters: ** name -- name of map for debug output. ** lmap -- the LDAP map being opened. ** ** Returns: ** true if connection is successful, false otherwise. ** ** Side Effects: ** Populates lmap->ldap_ld. */ static jmp_buf LDAPTimeout; #define SM_LDAP_SETTIMEOUT(to) \ do \ { \ if (to != 0) \ { \ if (setjmp(LDAPTimeout) != 0) \ { \ errno = ETIMEDOUT; \ return false; \ } \ ev = sm_setevent(to, ldaptimeout, 0); \ } \ } while (0) #define SM_LDAP_CLEARTIMEOUT() \ do \ { \ if (ev != NULL) \ sm_clrevent(ev); \ } while (0) bool sm_ldap_start(name, lmap) char *name; SM_LDAP_STRUCT *lmap; { int bind_result; int save_errno = 0; char *id; SM_EVENT *ev = NULL; LDAP *ld = NULL; if (sm_debug_active(&SmLDAPTrace, 2)) sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name); if (lmap->ldap_host != NULL) id = lmap->ldap_host; else if (lmap->ldap_uri != NULL) id = lmap->ldap_uri; else id = "localhost"; if (sm_debug_active(&SmLDAPTrace, 9)) { /* Don't print a port number for LDAP URIs */ if (lmap->ldap_uri != NULL) sm_dprintf("ldapmap_start(%s)\n", id); else sm_dprintf("ldapmap_start(%s, %d)\n", id, lmap->ldap_port); } if (lmap->ldap_uri != NULL) { #if SM_CONF_LDAP_INITIALIZE /* LDAP server supports URIs so use them directly */ save_errno = ldap_initialize(&ld, lmap->ldap_uri); #else /* SM_CONF_LDAP_INITIALIZE */ int err; LDAPURLDesc *ludp = NULL; /* Blast apart URL and use the ldap_init/ldap_open below */ err = ldap_url_parse(lmap->ldap_uri, &ludp); if (err != 0) { errno = err + E_LDAPURLBASE; return false; } lmap->ldap_host = sm_strdup_x(ludp->lud_host); if (lmap->ldap_host == NULL) { save_errno = errno; ldap_free_urldesc(ludp); errno = save_errno; return false; } lmap->ldap_port = ludp->lud_port; ldap_free_urldesc(ludp); #endif /* SM_CONF_LDAP_INITIALIZE */ } if (ld == NULL) { # if USE_LDAP_INIT ld = ldap_init(lmap->ldap_host, lmap->ldap_port); save_errno = errno; # else /* USE_LDAP_INIT */ /* ** If using ldap_open(), the actual connection to the server ** happens now so we need the timeout here. For ldap_init(), ** the connection happens at bind time. */ SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); ld = ldap_open(lmap->ldap_host, lmap->ldap_port); save_errno = errno; /* clear the event if it has not sprung */ SM_LDAP_CLEARTIMEOUT(); # endif /* USE_LDAP_INIT */ } errno = save_errno; if (ld == NULL) return false; sm_ldap_setopts(ld, lmap); # if USE_LDAP_INIT /* ** If using ldap_init(), the actual connection to the server ** happens at ldap_bind_s() so we need the timeout here. */ SM_LDAP_SETTIMEOUT(lmap->ldap_timeout.tv_sec); # endif /* USE_LDAP_INIT */ # ifdef LDAP_AUTH_KRBV4 if (lmap->ldap_method == LDAP_AUTH_KRBV4 && lmap->ldap_secret != NULL) { /* ** Need to put ticket in environment here instead of ** during parseargs as there may be different tickets ** for different LDAP connections. */ (void) putenv(lmap->ldap_secret); } # endif /* LDAP_AUTH_KRBV4 */ bind_result = ldap_bind_s(ld, lmap->ldap_binddn, lmap->ldap_secret, lmap->ldap_method); # if USE_LDAP_INIT /* clear the event if it has not sprung */ SM_LDAP_CLEARTIMEOUT(); # endif /* USE_LDAP_INIT */ if (bind_result != LDAP_SUCCESS) { errno = bind_result + E_LDAPBASE; return false; } /* Save PID to make sure only this PID closes the LDAP connection */ lmap->ldap_pid = getpid(); lmap->ldap_ld = ld; return true; } /* ARGSUSED */ static void ldaptimeout(unused) int unused; { /* ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ errno = ETIMEDOUT; longjmp(LDAPTimeout, 1); } /* ** SM_LDAP_SEARCH_M -- initiate multi-key LDAP search ** ** Initiate an LDAP search, return the msgid. ** The calling function must collect the results. ** ** Parameters: ** lmap -- LDAP map information ** argv -- key vector of substitutions in LDAP filter ** NOTE: argv must have SM_LDAP_ARGS elements to prevent ** out of bound array references ** ** Returns: ** <0 on failure (SM_LDAP_ERR*), msgid on success ** */ int sm_ldap_search_m(lmap, argv) SM_LDAP_STRUCT *lmap; char **argv; { int msgid; char *fp, *p, *q; char filter[LDAPMAP_MAX_FILTER + 1]; SM_REQUIRE(lmap != NULL); SM_REQUIRE(argv != NULL); SM_REQUIRE(argv[0] != NULL); memset(filter, '\0', sizeof filter); fp = filter; p = lmap->ldap_filter; while ((q = strchr(p, '%')) != NULL) { char *key; if (lmap->ldap_multi_args) { #if SM_LDAP_ARGS < 10 # ERROR _SM_LDAP_ARGS must be 10 #endif /* SM_LDAP_ARGS < 10 */ if (q[1] == 's') key = argv[0]; else if (q[1] >= '0' && q[1] <= '9') { key = argv[q[1] - '0']; if (key == NULL) { # if SM_LDAP_ERROR_ON_MISSING_ARGS return SM_LDAP_ERR_ARG_MISS; # else /* SM_LDAP_ERROR_ON_MISSING_ARGS */ key = ""; # endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ } } else key = NULL; } else key = argv[0]; if (q[1] == 's') { (void) sm_snprintf(fp, SPACELEFT(filter, fp), "%.*s%s", (int) (q - p), p, key); fp += strlen(fp); p = q + 2; } else if (q[1] == '0' || (lmap->ldap_multi_args && q[1] >= '0' && q[1] <= '9')) { char *k = key; (void) sm_snprintf(fp, SPACELEFT(filter, fp), "%.*s", (int) (q - p), p); fp += strlen(fp); p = q + 2; /* Properly escape LDAP special characters */ while (SPACELEFT(filter, fp) > 0 && *k != '\0') { if (*k == '*' || *k == '(' || *k == ')' || *k == '\\') { (void) sm_strlcat(fp, (*k == '*' ? "\\2A" : (*k == '(' ? "\\28" : (*k == ')' ? "\\29" : (*k == '\\' ? "\\5C" : "\00")))), SPACELEFT(filter, fp)); fp += strlen(fp); k++; } else *fp++ = *k++; } } else { (void) sm_snprintf(fp, SPACELEFT(filter, fp), "%.*s", (int) (q - p + 1), p); p = q + (q[1] == '%' ? 2 : 1); fp += strlen(fp); } } (void) sm_strlcpy(fp, p, SPACELEFT(filter, fp)); if (sm_debug_active(&SmLDAPTrace, 20)) sm_dprintf("ldap search filter=%s\n", filter); lmap->ldap_res = NULL; msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, filter, (lmap->ldap_attr[0] == NULL ? NULL : lmap->ldap_attr), lmap->ldap_attrsonly); return msgid; } /* ** SM_LDAP_SEARCH -- initiate LDAP search ** ** Initiate an LDAP search, return the msgid. ** The calling function must collect the results. ** Note this is just a wrapper into sm_ldap_search_m() ** ** Parameters: ** lmap -- LDAP map information ** key -- key to substitute in LDAP filter ** ** Returns: ** <0 on failure, msgid on success ** */ int sm_ldap_search(lmap, key) SM_LDAP_STRUCT *lmap; char *key; { char *argv[SM_LDAP_ARGS]; memset(argv, '\0', sizeof argv); argv[0] = key; return sm_ldap_search_m(lmap, argv); } /* ** SM_LDAP_HAS_OBJECTCLASS -- determine if an LDAP entry is part of a ** particular objectClass ** ** Parameters: ** lmap -- pointer to SM_LDAP_STRUCT in use ** entry -- current LDAP entry struct ** ocvalue -- particular objectclass in question. ** may be of form (fee|foo|fum) meaning ** any entry can be part of either fee, ** foo or fum objectclass ** ** Returns: ** true if item has that objectClass */ static bool sm_ldap_has_objectclass(lmap, entry, ocvalue) SM_LDAP_STRUCT *lmap; LDAPMessage *entry; char *ocvalue; { char **vals = NULL; int i; if (ocvalue == NULL) return false; vals = ldap_get_values(lmap->ldap_ld, entry, "objectClass"); if (vals == NULL) return false; for (i = 0; vals[i] != NULL; i++) { char *p; char *q; p = q = ocvalue; while (*p != '\0') { while (*p != '\0' && *p != '|') p++; if ((p - q) == strlen(vals[i]) && sm_strncasecmp(vals[i], q, p - q) == 0) { ldap_value_free(vals); return true; } while (*p == '|') p++; q = p; } } ldap_value_free(vals); return false; } /* ** SM_LDAP_RESULTS -- return results from an LDAP lookup in result ** ** Parameters: ** lmap -- pointer to SM_LDAP_STRUCT in use ** msgid -- msgid returned by sm_ldap_search() ** flags -- flags for the lookup ** delim -- delimiter for result concatenation ** rpool -- memory pool for storage ** result -- return string ** recurse -- recursion list ** ** Returns: ** status (sysexit) */ # define SM_LDAP_ERROR_CLEANUP() \ { \ if (lmap->ldap_res != NULL) \ { \ ldap_msgfree(lmap->ldap_res); \ lmap->ldap_res = NULL; \ } \ (void) ldap_abandon(lmap->ldap_ld, msgid); \ } static SM_LDAP_RECURSE_ENTRY * sm_ldap_add_recurse(top, item, type, rpool) SM_LDAP_RECURSE_LIST **top; char *item; int type; SM_RPOOL_T *rpool; { int n; int m; int p; int insertat; int moveb; int oldsizeb; int rc; SM_LDAP_RECURSE_ENTRY *newe; SM_LDAP_RECURSE_ENTRY **olddata; /* ** This code will maintain a list of ** SM_LDAP_RECURSE_ENTRY structures ** in ascending order. */ if (*top == NULL) { /* Allocate an initial SM_LDAP_RECURSE_LIST struct */ *top = sm_rpool_malloc_x(rpool, sizeof **top); (*top)->lrl_cnt = 0; (*top)->lrl_size = 0; (*top)->lrl_data = NULL; } if ((*top)->lrl_cnt >= (*top)->lrl_size) { /* Grow the list of SM_LDAP_RECURSE_ENTRY ptrs */ olddata = (*top)->lrl_data; if ((*top)->lrl_size == 0) { oldsizeb = 0; (*top)->lrl_size = 256; } else { oldsizeb = (*top)->lrl_size * sizeof *((*top)->lrl_data); (*top)->lrl_size *= 2; } (*top)->lrl_data = sm_rpool_malloc_x(rpool, (*top)->lrl_size * sizeof *((*top)->lrl_data)); if (oldsizeb > 0) memcpy((*top)->lrl_data, olddata, oldsizeb); } /* ** Binary search/insert item:type into list. ** Return current entry pointer if already exists. */ n = 0; m = (*top)->lrl_cnt - 1; if (m < 0) insertat = 0; else insertat = -1; while (insertat == -1) { p = (m + n) / 2; rc = sm_strcasecmp(item, (*top)->lrl_data[p]->lr_search); if (rc == 0) rc = type - (*top)->lrl_data[p]->lr_type; if (rc < 0) m = p - 1; else if (rc > 0) n = p + 1; else return (*top)->lrl_data[p]; if (m == -1) insertat = 0; else if (n >= (*top)->lrl_cnt) insertat = (*top)->lrl_cnt; else if (m < n) insertat = m + 1; } /* ** Not found in list, make room ** at insert point and add it. */ newe = sm_rpool_malloc_x(rpool, sizeof *newe); if (newe != NULL) { moveb = ((*top)->lrl_cnt - insertat) * sizeof *((*top)->lrl_data); if (moveb > 0) memmove(&((*top)->lrl_data[insertat + 1]), &((*top)->lrl_data[insertat]), moveb); newe->lr_search = sm_rpool_strdup_x(rpool, item); newe->lr_type = type; newe->lr_ludp = NULL; newe->lr_attrs = NULL; newe->lr_done = false; ((*top)->lrl_data)[insertat] = newe; (*top)->lrl_cnt++; } return newe; } int sm_ldap_results(lmap, msgid, flags, delim, rpool, result, resultln, resultsz, recurse) SM_LDAP_STRUCT *lmap; int msgid; int flags; int delim; SM_RPOOL_T *rpool; char **result; int *resultln; int *resultsz; SM_LDAP_RECURSE_LIST *recurse; { bool toplevel; int i; int statp; int vsize; int ret; int save_errno; char *p; SM_LDAP_RECURSE_ENTRY *rl; /* Are we the top top level of the search? */ toplevel = (recurse == NULL); /* Get results */ statp = EX_NOTFOUND; while ((ret = ldap_result(lmap->ldap_ld, msgid, 0, (lmap->ldap_timeout.tv_sec == 0 ? NULL : &(lmap->ldap_timeout)), &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) { LDAPMessage *entry; /* If we don't want multiple values and we have one, break */ if ((char) delim == '\0' && !bitset(SM_LDAP_SINGLEMATCH, flags) && *result != NULL) break; /* Cycle through all entries */ for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); entry != NULL; entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) { BerElement *ber; char *attr; char **vals = NULL; char *dn; /* ** If matching only and found an entry, ** no need to spin through attributes */ if (bitset(SM_LDAP_MATCHONLY, flags)) { statp = EX_OK; continue; } #if _FFR_LDAP_SINGLEDN if (bitset(SM_LDAP_SINGLEDN, flags) && *result != NULL) { /* only wanted one match */ SM_LDAP_ERROR_CLEANUP(); errno = ENOENT; return EX_NOTFOUND; } #endif /* _FFR_LDAP_SINGLEDN */ /* record completed DN's to prevent loops */ dn = ldap_get_dn(lmap->ldap_ld, entry); if (dn == NULL) { save_errno = sm_ldap_geterrno(lmap->ldap_ld); save_errno += E_LDAPBASE; SM_LDAP_ERROR_CLEANUP(); errno = save_errno; return EX_TEMPFAIL; } rl = sm_ldap_add_recurse(&recurse, dn, SM_LDAP_ATTR_DN, rpool); if (rl == NULL) { ldap_memfree(dn); SM_LDAP_ERROR_CLEANUP(); errno = ENOMEM; return EX_OSERR; } else if (rl->lr_done) { /* already on list, skip it */ ldap_memfree(dn); continue; } ldap_memfree(dn); # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) /* ** Reset value to prevent lingering ** LDAP_DECODING_ERROR due to ** OpenLDAP 1.X's hack (see below) */ lmap->ldap_ld->ld_errno = LDAP_SUCCESS; # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ for (attr = ldap_first_attribute(lmap->ldap_ld, entry, &ber); attr != NULL; attr = ldap_next_attribute(lmap->ldap_ld, entry, ber)) { char *tmp, *vp_tmp; int type; char *needobjclass = NULL; type = SM_LDAP_ATTR_NONE; for (i = 0; lmap->ldap_attr[i] != NULL; i++) { if (sm_strcasecmp(lmap->ldap_attr[i], attr) == 0) { type = lmap->ldap_attr_type[i]; needobjclass = lmap->ldap_attr_needobjclass[i]; break; } } if (bitset(SM_LDAP_USE_ALLATTR, flags) && type == SM_LDAP_ATTR_NONE) { /* URL lookups specify attrs to use */ type = SM_LDAP_ATTR_NORMAL; needobjclass = NULL; } if (type == SM_LDAP_ATTR_NONE) { /* attribute not requested */ ldap_memfree(attr); SM_LDAP_ERROR_CLEANUP(); errno = EFAULT; return EX_SOFTWARE; } /* ** For recursion on a particular attribute, ** we may need to see if this entry is ** part of a particular objectclass. ** Also, ignore objectClass attribute. ** Otherwise we just ignore this attribute. */ if (type == SM_LDAP_ATTR_OBJCLASS || (needobjclass != NULL && !sm_ldap_has_objectclass(lmap, entry, needobjclass))) { ldap_memfree(attr); continue; } if (lmap->ldap_attrsonly == LDAPMAP_FALSE) { vals = ldap_get_values(lmap->ldap_ld, entry, attr); if (vals == NULL) { save_errno = sm_ldap_geterrno(lmap->ldap_ld); if (save_errno == LDAP_SUCCESS) { ldap_memfree(attr); continue; } /* Must be an error */ save_errno += E_LDAPBASE; ldap_memfree(attr); SM_LDAP_ERROR_CLEANUP(); errno = save_errno; return EX_TEMPFAIL; } } statp = EX_OK; # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT) /* ** Reset value to prevent lingering ** LDAP_DECODING_ERROR due to ** OpenLDAP 1.X's hack (see below) */ lmap->ldap_ld->ld_errno = LDAP_SUCCESS; # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */ /* ** If matching only, ** no need to spin through entries */ if (bitset(SM_LDAP_MATCHONLY, flags)) { if (lmap->ldap_attrsonly == LDAPMAP_FALSE) ldap_value_free(vals); ldap_memfree(attr); continue; } /* ** If we don't want multiple values, ** return first found. */ if ((char) delim == '\0') { if (*result != NULL) { /* already have a value */ if (bitset(SM_LDAP_SINGLEMATCH, flags)) { /* only wanted one match */ SM_LDAP_ERROR_CLEANUP(); errno = ENOENT; return EX_NOTFOUND; } break; } if (lmap->ldap_attrsonly == LDAPMAP_TRUE) { *result = sm_rpool_strdup_x(rpool, attr); ldap_memfree(attr); break; } if (vals[0] == NULL) { ldap_value_free(vals); ldap_memfree(attr); continue; } vsize = strlen(vals[0]) + 1; if (lmap->ldap_attrsep != '\0') vsize += strlen(attr) + 1; *result = sm_rpool_malloc_x(rpool, vsize); if (lmap->ldap_attrsep != '\0') sm_snprintf(*result, vsize, "%s%c%s", attr, lmap->ldap_attrsep, vals[0]); else sm_strlcpy(*result, vals[0], vsize); ldap_value_free(vals); ldap_memfree(attr); break; } /* attributes only */ if (lmap->ldap_attrsonly == LDAPMAP_TRUE) { if (*result == NULL) *result = sm_rpool_strdup_x(rpool, attr); else { if (bitset(SM_LDAP_SINGLEMATCH, flags) && *result != NULL) { /* only wanted one match */ SM_LDAP_ERROR_CLEANUP(); errno = ENOENT; return EX_NOTFOUND; } vsize = strlen(*result) + strlen(attr) + 2; tmp = sm_rpool_malloc_x(rpool, vsize); (void) sm_snprintf(tmp, vsize, "%s%c%s", *result, (char) delim, attr); *result = tmp; } ldap_memfree(attr); continue; } /* ** If there is more than one, munge then ** into a map_coldelim separated string. ** If we are recursing we may have an entry ** with no 'normal' values to put in the ** string. ** This is not an error. */ if (type == SM_LDAP_ATTR_NORMAL && bitset(SM_LDAP_SINGLEMATCH, flags) && *result != NULL) { /* only wanted one match */ SM_LDAP_ERROR_CLEANUP(); errno = ENOENT; return EX_NOTFOUND; } vsize = 0; for (i = 0; vals[i] != NULL; i++) { if (type == SM_LDAP_ATTR_DN || type == SM_LDAP_ATTR_FILTER || type == SM_LDAP_ATTR_URL) { /* add to recursion */ if (sm_ldap_add_recurse(&recurse, vals[i], type, rpool) == NULL) { SM_LDAP_ERROR_CLEANUP(); errno = ENOMEM; return EX_OSERR; } continue; } vsize += strlen(vals[i]) + 1; if (lmap->ldap_attrsep != '\0') vsize += strlen(attr) + 1; } /* ** Create/Append to string any normal ** attribute values. Otherwise, just free ** memory and move on to the next ** attribute in this entry. */ if (type == SM_LDAP_ATTR_NORMAL && vsize > 0) { char *pe; /* Grow result string if needed */ if ((*resultln + vsize) >= *resultsz) { while ((*resultln + vsize) >= *resultsz) { if (*resultsz == 0) *resultsz = 1024; else *resultsz *= 2; } vp_tmp = sm_rpool_malloc_x(rpool, *resultsz); *vp_tmp = '\0'; if (*result != NULL) sm_strlcpy(vp_tmp, *result, *resultsz); *result = vp_tmp; } p = *result + *resultln; pe = *result + *resultsz; for (i = 0; vals[i] != NULL; i++) { if (*resultln > 0 && p < pe) *p++ = (char) delim; if (lmap->ldap_attrsep != '\0') { p += sm_strlcpy(p, attr, pe - p); if (p < pe) *p++ = lmap->ldap_attrsep; } p += sm_strlcpy(p, vals[i], pe - p); *resultln = p - (*result); if (p >= pe) { /* Internal error: buffer too small for LDAP values */ SM_LDAP_ERROR_CLEANUP(); errno = ENOMEM; return EX_OSERR; } } } ldap_value_free(vals); ldap_memfree(attr); } save_errno = sm_ldap_geterrno(lmap->ldap_ld); /* ** We check save_errno != LDAP_DECODING_ERROR since ** OpenLDAP 1.X has a very ugly *undocumented* ** hack of returning this error code from ** ldap_next_attribute() if the library freed the ** ber attribute. See: ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html */ if (save_errno != LDAP_SUCCESS && save_errno != LDAP_DECODING_ERROR) { /* Must be an error */ save_errno += E_LDAPBASE; SM_LDAP_ERROR_CLEANUP(); errno = save_errno; return EX_TEMPFAIL; } /* mark this DN as done */ rl->lr_done = true; if (rl->lr_ludp != NULL) { ldap_free_urldesc(rl->lr_ludp); rl->lr_ludp = NULL; } if (rl->lr_attrs != NULL) { free(rl->lr_attrs); rl->lr_attrs = NULL; } /* We don't want multiple values and we have one */ if ((char) delim == '\0' && !bitset(SM_LDAP_SINGLEMATCH, flags) && *result != NULL) break; } save_errno = sm_ldap_geterrno(lmap->ldap_ld); if (save_errno != LDAP_SUCCESS && save_errno != LDAP_DECODING_ERROR) { /* Must be an error */ save_errno += E_LDAPBASE; SM_LDAP_ERROR_CLEANUP(); errno = save_errno; return EX_TEMPFAIL; } ldap_msgfree(lmap->ldap_res); lmap->ldap_res = NULL; } if (ret == 0) save_errno = ETIMEDOUT; else save_errno = sm_ldap_geterrno(lmap->ldap_ld); if (save_errno != LDAP_SUCCESS) { statp = EX_TEMPFAIL; switch (save_errno) { #ifdef LDAP_SERVER_DOWN case LDAP_SERVER_DOWN: #endif /* LDAP_SERVER_DOWN */ case LDAP_TIMEOUT: case ETIMEDOUT: case LDAP_UNAVAILABLE: /* ** server disappeared, ** try reopen on next search */ statp = EX_RESTART; break; } if (ret != 0) save_errno += E_LDAPBASE; SM_LDAP_ERROR_CLEANUP(); errno = save_errno; return statp; } if (lmap->ldap_res != NULL) { ldap_msgfree(lmap->ldap_res); lmap->ldap_res = NULL; } if (toplevel) { int rlidx; /* ** Spin through the built-up recurse list at the top ** of the recursion. Since new items are added at the ** end of the shared list, we actually only ever get ** one level of recursion before things pop back to the ** top. Any items added to the list during that recursion ** will be expanded by the top level. */ for (rlidx = 0; recurse != NULL && rlidx < recurse->lrl_cnt; rlidx++) { int newflags; int sid; int status; rl = recurse->lrl_data[rlidx]; newflags = flags; if (rl->lr_done) { /* already expanded */ continue; } if (rl->lr_type == SM_LDAP_ATTR_DN) { /* do DN search */ sid = ldap_search(lmap->ldap_ld, rl->lr_search, lmap->ldap_scope, "(objectClass=*)", (lmap->ldap_attr[0] == NULL ? NULL : lmap->ldap_attr), lmap->ldap_attrsonly); } else if (rl->lr_type == SM_LDAP_ATTR_FILTER) { /* do new search */ sid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, rl->lr_search, (lmap->ldap_attr[0] == NULL ? NULL : lmap->ldap_attr), lmap->ldap_attrsonly); } else if (rl->lr_type == SM_LDAP_ATTR_URL) { /* Parse URL */ sid = ldap_url_parse(rl->lr_search, &rl->lr_ludp); if (sid != 0) { errno = sid + E_LDAPURLBASE; return EX_TEMPFAIL; } /* We need to add objectClass */ if (rl->lr_ludp->lud_attrs != NULL) { int attrnum = 0; while (rl->lr_ludp->lud_attrs[attrnum] != NULL) { if (strcasecmp(rl->lr_ludp->lud_attrs[attrnum], "objectClass") == 0) { /* already requested */ attrnum = -1; break; } attrnum++; } if (attrnum >= 0) { int i; rl->lr_attrs = (char **)malloc(sizeof(char *) * (attrnum + 2)); if (rl->lr_attrs == NULL) { save_errno = errno; ldap_free_urldesc(rl->lr_ludp); errno = save_errno; return EX_TEMPFAIL; } for (i = 0 ; i < attrnum; i++) { rl->lr_attrs[i] = rl->lr_ludp->lud_attrs[i]; } rl->lr_attrs[i++] = "objectClass"; rl->lr_attrs[i++] = NULL; } } /* ** Use the existing connection ** for this search. It really ** should use lud_scheme://lud_host:lud_port/ ** instead but that would require ** opening a new connection. ** This should be fixed ASAP. */ sid = ldap_search(lmap->ldap_ld, rl->lr_ludp->lud_dn, rl->lr_ludp->lud_scope, rl->lr_ludp->lud_filter, rl->lr_attrs, lmap->ldap_attrsonly); /* Use the attributes specified by URL */ newflags |= SM_LDAP_USE_ALLATTR; } else { /* unknown or illegal attribute type */ errno = EFAULT; return EX_SOFTWARE; } /* Collect results */ if (sid == -1) { save_errno = sm_ldap_geterrno(lmap->ldap_ld); statp = EX_TEMPFAIL; switch (save_errno) { #ifdef LDAP_SERVER_DOWN case LDAP_SERVER_DOWN: #endif /* LDAP_SERVER_DOWN */ case LDAP_TIMEOUT: case ETIMEDOUT: case LDAP_UNAVAILABLE: /* ** server disappeared, ** try reopen on next search */ statp = EX_RESTART; break; } errno = save_errno + E_LDAPBASE; return statp; } status = sm_ldap_results(lmap, sid, newflags, delim, rpool, result, resultln, resultsz, recurse); save_errno = errno; if (status != EX_OK && status != EX_NOTFOUND) { errno = save_errno; return status; } /* Mark as done */ rl->lr_done = true; if (rl->lr_ludp != NULL) { ldap_free_urldesc(rl->lr_ludp); rl->lr_ludp = NULL; } if (rl->lr_attrs != NULL) { free(rl->lr_attrs); rl->lr_attrs = NULL; } /* Reset rlidx as new items may have been added */ rlidx = -1; } } return statp; } /* ** SM_LDAP_CLOSE -- close LDAP connection ** ** Parameters: ** lmap -- LDAP map information ** ** Returns: ** None. ** */ void sm_ldap_close(lmap) SM_LDAP_STRUCT *lmap; { if (lmap->ldap_ld == NULL) return; if (lmap->ldap_pid == getpid()) ldap_unbind(lmap->ldap_ld); lmap->ldap_ld = NULL; lmap->ldap_pid = 0; } /* ** SM_LDAP_SETOPTS -- set LDAP options ** ** Parameters: ** ld -- LDAP session handle ** lmap -- LDAP map information ** ** Returns: ** None. ** */ void sm_ldap_setopts(ld, lmap) LDAP *ld; SM_LDAP_STRUCT *lmap; { # if USE_LDAP_SET_OPTION if (lmap->ldap_version != 0) { ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &lmap->ldap_version); } ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); else ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); # if _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &lmap->ldap_networktmo); # endif /* _FFR_LDAP_NETWORK_TIMEOUT && defined(LDAP_OPT_NETWORK_TIMEOUT) */ # ifdef LDAP_OPT_RESTART ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); # endif /* LDAP_OPT_RESTART */ # else /* USE_LDAP_SET_OPTION */ /* From here on in we can use ldap internal timelimits */ ld->ld_deref = lmap->ldap_deref; ld->ld_options = lmap->ldap_options; ld->ld_sizelimit = lmap->ldap_sizelimit; ld->ld_timelimit = lmap->ldap_timelimit; # endif /* USE_LDAP_SET_OPTION */ } /* ** SM_LDAP_GETERRNO -- get ldap errno value ** ** Parameters: ** ld -- LDAP session handle ** ** Returns: ** LDAP errno. ** */ int sm_ldap_geterrno(ld) LDAP *ld; { int err = LDAP_SUCCESS; # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ # ifdef LDAP_OPT_SIZELIMIT err = ldap_get_lderrno(ld, NULL, NULL); # else /* LDAP_OPT_SIZELIMIT */ err = ld->ld_errno; /* ** Reset value to prevent lingering LDAP_DECODING_ERROR due to ** OpenLDAP 1.X's hack (see above) */ ld->ld_errno = LDAP_SUCCESS; # endif /* LDAP_OPT_SIZELIMIT */ # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ return err; } # endif /* LDAPMAP */ dk-milter-1.0.0.dfsg/libsm/strio.c0000644000175000017500000002233510252133503016475 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: strio.c,v 1.44 2005/06/09 21:40:19 ca Exp $") #include #include #include #include #include #include #include #include #include #include "local.h" static int sm_strsetmode __P((SM_FILE_T*, const int *)); static int sm_strgetmode __P((SM_FILE_T*, int *)); /* ** Cookie structure for the "strio" file type */ struct sm_str_obj { char *strio_base; char *strio_end; size_t strio_size; size_t strio_offset; int strio_flags; const void *strio_rpool; }; typedef struct sm_str_obj SM_STR_OBJ_T; /* ** SM_STRGROW -- increase storage space for string ** ** Parameters: ** s -- current cookie ** size -- new storage size request ** ** Returns: ** true iff successful. */ static bool sm_strgrow __P((SM_STR_OBJ_T *, size_t)); static bool sm_strgrow(s, size) SM_STR_OBJ_T *s; size_t size; { register void *p; if (s->strio_size >= size) return true; p = sm_realloc(s->strio_base, size); if (p == NULL) return false; s->strio_base = p; s->strio_end = s->strio_base + size; s->strio_size = size; return true; } /* ** SM_STRREAD -- read a portion of the string ** ** Parameters: ** fp -- the file pointer ** buf -- location to place read data ** n -- number of bytes to read ** ** Returns: ** Failure: -1 and sets errno ** Success: >=0, number of bytes read */ ssize_t sm_strread(fp, buf, n) SM_FILE_T *fp; char *buf; size_t n; { register SM_STR_OBJ_T *s = fp->f_cookie; int len; if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW)) { errno = EBADF; return -1; } len = SM_MIN(s->strio_size - s->strio_offset, n); (void) memmove(buf, s->strio_base + s->strio_offset, len); s->strio_offset += len; return len; } /* ** SM_STRWRITE -- write a portion of the string ** ** Parameters: ** fp -- the file pointer ** buf -- location of data for writing ** n -- number of bytes to write ** ** Returns: ** Failure: -1 and sets errno ** Success: >=0, number of bytes written */ ssize_t sm_strwrite(fp, buf, n) SM_FILE_T *fp; char const *buf; size_t n; { register SM_STR_OBJ_T *s = fp->f_cookie; if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW)) { errno = EBADF; return -1; } if (n + s->strio_offset > s->strio_size) { if (!sm_strgrow(s, n + s->strio_offset)) return 0; } (void) memmove(s->strio_base + s->strio_offset, buf, n); s->strio_offset += n; return n; } /* ** SM_STRSEEK -- position the offset pointer for the string ** ** Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid ** values for whence. ** ** Parameters: ** fp -- the file pointer ** offset -- number of bytes offset from "base" ** whence -- determines "base" for 'offset' ** ** Returns: ** Failure: -1 and sets errno ** Success: >=0, number of bytes read */ off_t sm_strseek(fp, offset, whence) SM_FILE_T *fp; off_t offset; int whence; { register off_t ret; register SM_STR_OBJ_T *s = fp->f_cookie; reseek: switch (whence) { case SM_IO_SEEK_SET: ret = offset; break; case SM_IO_SEEK_CUR: ret = s->strio_offset + offset; break; case SM_IO_SEEK_END: ret = s->strio_size; break; default: errno = EINVAL; return -1; } if (ret < 0 || ret > (off_t)(size_t)(-1)) /* XXX ugly */ return -1; if ((size_t) ret > s->strio_size) { if (sm_strgrow(s, (size_t)ret)) goto reseek; /* errno set by sm_strgrow */ return -1; } s->strio_offset = (size_t) ret; return ret; } /* ** SM_STROPEN -- open a string file type ** ** Parameters: ** fp -- file pointer open to be associated with ** info -- initial contents (NULL for none) ** flags -- flags for methods of access (was mode) ** rpool -- resource pool to use memory from (if applicable) ** ** Results: ** Success: 0 (zero) ** Failure: -1 and sets errno */ int sm_stropen(fp, info, flags, rpool) SM_FILE_T *fp; const void *info; int flags; const void *rpool; { register SM_STR_OBJ_T *s; #if SM_RPOOL s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T)); #else /* SM_RPOOL */ s = sm_malloc(sizeof(SM_STR_OBJ_T)); if (s == NULL) return -1; #endif /* SM_RPOOL */ fp->f_cookie = s; s->strio_rpool = rpool; s->strio_offset = 0; s->strio_size = 0; s->strio_base = NULL; s->strio_end = 0; switch (flags) { case SM_IO_RDWR: s->strio_flags = SMRW; break; case SM_IO_RDONLY: s->strio_flags = SMRD; break; case SM_IO_WRONLY: s->strio_flags = SMWR; break; case SM_IO_APPEND: if (s->strio_rpool == NULL) sm_free(s); errno = EINVAL; return -1; default: if (s->strio_rpool == NULL) sm_free(s); errno = EINVAL; return -1; } if (info != NULL) { s->strio_base = sm_strdup_x(info); if (s->strio_base == NULL) { int save_errno = errno; if (s->strio_rpool == NULL) sm_free(s); errno = save_errno; return -1; } s->strio_size = strlen(info); s->strio_end = s->strio_base + s->strio_size; } return 0; } /* ** SM_STRCLOSE -- close the string file type and free resources ** ** Parameters: ** fp -- file pointer ** ** Results: ** Success: 0 (zero) */ int sm_strclose(fp) SM_FILE_T *fp; { SM_STR_OBJ_T *s = fp->f_cookie; #if !SM_RPOOL sm_free(s->strio_base); s->strio_base = NULL; #endif /* !SM_RPOOL */ return 0; } /* ** SM_STRSETMODE -- set mode info for the file ** ** Note: changing the mode can be a safe way to have the "parent" ** set up a string that the "child" is not to modify ** ** Parameters: ** fp -- the file pointer ** mode -- location of new mode to set ** ** Results: ** Success: 0 (zero) ** Failure: -1 and sets errno */ static int sm_strsetmode(fp, mode) SM_FILE_T *fp; const int *mode; { register SM_STR_OBJ_T *s = fp->f_cookie; int flags; switch (*mode) { case SM_IO_RDWR: flags = SMRW; break; case SM_IO_RDONLY: flags = SMRD; break; case SM_IO_WRONLY: flags = SMWR; break; case SM_IO_APPEND: errno = EINVAL; return -1; default: errno = EINVAL; return -1; } s->strio_flags &= ~SMMODEMASK; s->strio_flags |= flags; return 0; } /* ** SM_STRGETMODE -- get mode info for the file ** ** Parameters: ** fp -- the file pointer ** mode -- location to store current mode ** ** Results: ** Success: 0 (zero) ** Failure: -1 and sets errno */ static int sm_strgetmode(fp, mode) SM_FILE_T *fp; int *mode; { register SM_STR_OBJ_T *s = fp->f_cookie; switch (s->strio_flags & SMMODEMASK) { case SMRW: *mode = SM_IO_RDWR; break; case SMRD: *mode = SM_IO_RDONLY; break; case SMWR: *mode = SM_IO_WRONLY; break; default: errno = EINVAL; return -1; } return 0; } /* ** SM_STRSETINFO -- set info for the file ** ** Currently only SM_IO_WHAT_MODE is supported for 'what'. ** ** Parameters: ** fp -- the file pointer ** what -- type of information to set ** valp -- location to data for doing set ** ** Results: ** Failure: -1 and sets errno ** Success: sm_strsetmode() return [0 (zero)] */ int sm_strsetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch(what) { case SM_IO_WHAT_MODE: return sm_strsetmode(fp, (int *) valp); default: errno = EINVAL; return -1; } } /* ** SM_STRGETINFO -- get info for the file ** ** Currently only SM_IO_WHAT_MODE is supported for 'what'. ** ** Parameters: ** fp -- the file pointer ** what -- type of information requested ** valp -- location to return information in ** ** Results: ** Failure: -1 and sets errno ** Success: sm_strgetmode() return [0 (zero)] */ int sm_strgetinfo(fp, what, valp) SM_FILE_T *fp; int what; void *valp; { switch(what) { case SM_IO_WHAT_MODE: return sm_strgetmode(fp, (int *) valp); default: errno = EINVAL; return -1; } } /* ** SM_STRIO_INIT -- initializes a write-only string type ** ** Original comments below. This function does not appear to be used anywhere. ** The same functionality can be done by changing the mode of the file. ** ------------ ** sm_strio_init initializes an SM_FILE_T structure as a write-only file ** that writes into the specified buffer: ** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer. ** Attempts to write more than size-1 characters into the buffer will fail ** silently (no error is reported). ** - Use sm_io_fflush to nul terminate the string in the buffer ** (the write pointer is not advanced). ** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc. ** ** Parameters: ** fp -- file pointer ** buf -- memory location for stored data ** size -- size of 'buf' ** ** Results: ** none. */ void sm_strio_init(fp, buf, size) SM_FILE_T *fp; char *buf; size_t size; { fp->sm_magic = SmFileMagic; fp->f_flags = SMWR | SMSTR; fp->f_file = -1; fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf; fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0); fp->f_lbfsize = 0; fp->f_r = 0; fp->f_read = NULL; fp->f_seek = NULL; fp->f_getinfo = NULL; fp->f_setinfo = NULL; } dk-milter-1.0.0.dfsg/libsm/t-strio.c0000644000175000017500000000141307347306541016747 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-strio.c,v 1.11 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include int main(argc, argv) int argc; char *argv[]; { char buf[20]; char *r; SM_FILE_T f; sm_test_begin(argc, argv, "test strio"); (void) memset(buf, '.', 20); sm_strio_init(&f, buf, 10); (void) sm_io_fprintf(&f, SM_TIME_DEFAULT, "foobarbazoom"); sm_io_flush(&f, SM_TIME_DEFAULT); r = "foobarbaz"; SM_TEST(strcmp(buf, r) == 0); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/path.c0000644000175000017500000000260007347306541016301 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: path.c,v 1.9 2001/09/11 04:04:49 gshapiro Exp $") #include #include #ifdef WIN32 /* ** SM_PATH_ISDEVNULL -- Does path specify the null device? ** ** Parameters: ** path -- path name. ** ** Returns: ** true if a simple string comparison indicates that the ** specified path names the null device. ** false otherwise. */ bool sm_path_isdevnull(path) const char *path; { size_t len = strlen(path); if (len == 3 && sm_strcasecmp(path, "nul") == 0) return true; else if (len > 3 && (path[len - 4] == '/' || path[len - 4] == '\\') && sm_strcasecmp(path + len - 3, "nul") == 0) return true; return false; } /* ** SM_LAST_DIR_DELIM -- Returns pointer to last directory delimiter. ** ** Parameters: ** path -- path name. ** ** Returns: ** pointer to last directory delimiter. ** NULL if path doesn't contain a directory delimiter. */ char * sm_last_dir_delim(path) const char *path; { char *p, *n; if ((p = strpbrk(path, "/\\")) == NULL) return NULL; for (;;) { n = strpbrk(p + 1, "/\\"); if (n == NULL) return p; p = n; } } #endif /* WIN32 */ dk-milter-1.0.0.dfsg/libsm/fpos.c0000644000175000017500000000616310253661450016315 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fpos.c,v 1.39 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #include #include #include "local.h" static void tellalrm __P((int)); static jmp_buf TellTimeOut; /* ** TELLALRM -- handler when timeout activated for sm_io_tell() ** ** Returns flow of control to where setjmp(TellTimeOut) was set. ** ** Parameters: ** sig -- unused ** ** Returns: ** does not return ** ** Side Effects: ** returns flow of control to setjmp(TellTimeOut). ** ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. */ /* ARGSUSED0 */ static void tellalrm(sig) int sig; { longjmp(TellTimeOut, 1); } /* ** SM_IO_TELL -- position the file pointer ** ** Paramters: ** fp -- the file pointer to get repositioned ** timeout -- time to complete the tell (milliseconds) ** ** Returns: ** Success -- the repositioned location. ** Failure -- -1 (minus 1) and sets errno */ long sm_io_tell(fp, timeout) register SM_FILE_T *fp; int SM_NONVOLATILE timeout; { register off_t pos; SM_EVENT *evt = NULL; SM_REQUIRE_ISA(fp, SmFileMagic); if (fp->f_seek == NULL) { errno = ESPIPE; /* historic practice */ return -1L; } if (timeout == SM_TIME_DEFAULT) timeout = fp->f_timeout; if (timeout == SM_TIME_IMMEDIATE) { /* ** Filling the buffer will take time and we are wanted to ** return immediately. So... */ errno = EAGAIN; return -1L; } /* ** Find offset of underlying I/O object, then adjust byte position ** may adjust seek offset on append stream */ (void) sm_flush(fp, (int *) &timeout); /* This is where we start the timeout */ if (timeout != SM_TIME_FOREVER) { if (setjmp(TellTimeOut) != 0) { errno = EAGAIN; return -1L; } evt = sm_seteventm(timeout, tellalrm, 0); } if (fp->f_flags & SMOFF) pos = fp->f_lseekoff; else { /* XXX only set the timeout here? */ pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); if (pos == -1L) goto clean; } if (fp->f_flags & SMRD) { /* ** Reading. Any unread characters (including ** those from ungetc) cause the position to be ** smaller than that in the underlying object. */ pos -= fp->f_r; if (HASUB(fp)) pos -= fp->f_ur; } else if (fp->f_flags & SMWR && fp->f_p != NULL) { /* ** Writing. Any buffered characters cause the ** position to be greater than that in the ** underlying object. */ pos += fp->f_p - fp->f_bf.smb_base; } clean: /* We're back. So undo our timeout and handler */ if (evt != NULL) sm_clrevent(evt); return pos; } dk-milter-1.0.0.dfsg/libsm/exc.c0000644000175000017500000003212210542036511016112 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: exc.c,v 1.49 2006/12/19 19:28:09 ca Exp $") /* ** exception handling ** For documentation, see exc.html */ #include #include #include #include #include #include #include #include const char SmExcMagic[] = "sm_exc"; const char SmExcTypeMagic[] = "sm_exc_type"; /* ** SM_ETYPE_PRINTF -- printf for exception types. ** ** Parameters: ** exc -- exception. ** stream -- file for output. ** ** Returns: ** none. */ /* ** A simple formatted print function that can be used as the print function ** by most exception types. It prints the printcontext string, interpreting ** occurrences of %0 through %9 as references to the argument vector. ** If exception argument 3 is an int or long, then %3 will print the ** argument in decimal, and %o3 or %x3 will print it in octal or hex. */ void sm_etype_printf(exc, stream) SM_EXC_T *exc; SM_FILE_T *stream; { size_t n = strlen(exc->exc_type->etype_argformat); const char *p, *s; char format; for (p = exc->exc_type->etype_printcontext; *p != '\0'; ++p) { if (*p != '%') { (void) sm_io_putc(stream, SM_TIME_DEFAULT, *p); continue; } ++p; if (*p == '\0') { (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); break; } if (*p == '%') { (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); continue; } format = '\0'; if (isalpha(*p)) { format = *p++; if (*p == '\0') { (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); (void) sm_io_putc(stream, SM_TIME_DEFAULT, format); break; } } if (isdigit(*p)) { size_t i = *p - '0'; if (i < n) { switch (exc->exc_type->etype_argformat[i]) { case 's': case 'r': s = exc->exc_argv[i].v_str; if (s == NULL) s = "(null)"; sm_io_fputs(stream, SM_TIME_DEFAULT, s); continue; case 'i': sm_io_fprintf(stream, SM_TIME_DEFAULT, format == 'o' ? "%o" : format == 'x' ? "%x" : "%d", exc->exc_argv[i].v_int); continue; case 'l': sm_io_fprintf(stream, SM_TIME_DEFAULT, format == 'o' ? "%lo" : format == 'x' ? "%lx" : "%ld", exc->exc_argv[i].v_long); continue; case 'e': sm_exc_write(exc->exc_argv[i].v_exc, stream); continue; } } } (void) sm_io_putc(stream, SM_TIME_DEFAULT, '%'); if (format) (void) sm_io_putc(stream, SM_TIME_DEFAULT, format); (void) sm_io_putc(stream, SM_TIME_DEFAULT, *p); } } /* ** Standard exception types. */ /* ** SM_ETYPE_OS_PRINT -- Print OS related exception. ** ** Parameters: ** exc -- exception. ** stream -- file for output. ** ** Returns: ** none. */ static void sm_etype_os_print __P(( SM_EXC_T *exc, SM_FILE_T *stream)); static void sm_etype_os_print(exc, stream) SM_EXC_T *exc; SM_FILE_T *stream; { int err = exc->exc_argv[0].v_int; char *syscall = exc->exc_argv[1].v_str; char *sysargs = exc->exc_argv[2].v_str; if (sysargs) sm_io_fprintf(stream, SM_TIME_DEFAULT, "%s: %s failed: %s", sysargs, syscall, sm_errstring(err)); else sm_io_fprintf(stream, SM_TIME_DEFAULT, "%s failed: %s", syscall, sm_errstring(err)); } /* ** SmEtypeOs represents the failure of a Unix system call. ** The three arguments are: ** int errno (eg, ENOENT) ** char *syscall (eg, "open") ** char *sysargs (eg, NULL or "/etc/mail/sendmail.cf") */ const SM_EXC_TYPE_T SmEtypeOs = { SmExcTypeMagic, "E:sm.os", "isr", sm_etype_os_print, NULL, }; /* ** SmEtypeErr is a completely generic error which should only be ** used in applications and test programs. Libraries should use ** more specific exception codes. */ const SM_EXC_TYPE_T SmEtypeErr = { SmExcTypeMagic, "E:sm.err", "r", sm_etype_printf, "%0", }; /* ** SM_EXC_VNEW_X -- Construct a new exception object. ** ** Parameters: ** etype -- type of exception. ** ap -- varargs. ** ** Returns: ** pointer to exception object. */ /* ** This is an auxiliary function called by sm_exc_new_x and sm_exc_raisenew_x. ** ** If an exception is raised, then to avoid a storage leak, we must: ** (a) Free all storage we have allocated. ** (b) Free all exception arguments in the varargs list. ** Getting this right is tricky. ** ** To see why (b) is required, consider the code fragment ** SM_EXCEPT(exc, "*") ** sm_exc_raisenew_x(&MyEtype, exc); ** SM_END_TRY ** In the normal case, sm_exc_raisenew_x will allocate and raise a new ** exception E that owns exc. When E is eventually freed, exc is also freed. ** In the exceptional case, sm_exc_raisenew_x must free exc before raising ** an out-of-memory exception so that exc is not leaked. */ static SM_EXC_T *sm_exc_vnew_x __P((const SM_EXC_TYPE_T *, va_list SM_NONVOLATILE)); static SM_EXC_T * sm_exc_vnew_x(etype, ap) const SM_EXC_TYPE_T *etype; va_list SM_NONVOLATILE ap; { /* ** All variables that are modified in the SM_TRY clause and ** referenced in the SM_EXCEPT clause must be declared volatile. */ /* NOTE: Type of si, i, and argc *must* match */ SM_EXC_T * volatile exc = NULL; int volatile si = 0; SM_VAL_T * volatile argv = NULL; int i, argc; SM_REQUIRE_ISA(etype, SmExcTypeMagic); argc = strlen(etype->etype_argformat); SM_TRY { /* ** Step 1. Allocate the exception structure. ** On failure, scan the varargs list and free all ** exception arguments. */ exc = sm_malloc_x(sizeof(SM_EXC_T)); exc->sm_magic = SmExcMagic; exc->exc_refcount = 1; exc->exc_type = etype; exc->exc_argv = NULL; /* ** Step 2. Allocate the argument vector. ** On failure, free exc, scan the varargs list and free all ** exception arguments. On success, scan the varargs list, ** and copy the arguments into argv. */ argv = sm_malloc_x(argc * sizeof(SM_VAL_T)); exc->exc_argv = argv; for (i = 0; i < argc; ++i) { switch (etype->etype_argformat[i]) { case 'i': argv[i].v_int = SM_VA_ARG(ap, int); break; case 'l': argv[i].v_long = SM_VA_ARG(ap, long); break; case 'e': argv[i].v_exc = SM_VA_ARG(ap, SM_EXC_T*); break; case 's': argv[i].v_str = SM_VA_ARG(ap, char*); break; case 'r': SM_REQUIRE(etype->etype_argformat[i+1] == '\0'); argv[i].v_str = SM_VA_ARG(ap, char*); break; default: sm_abort("sm_exc_vnew_x: bad argformat '%c'", etype->etype_argformat[i]); } } /* ** Step 3. Scan argv, and allocate space for all ** string arguments. si is the number of elements ** of argv that have been processed so far. ** On failure, free exc, argv, all the exception arguments ** and all of the strings that have been copied. */ for (si = 0; si < argc; ++si) { switch (etype->etype_argformat[si]) { case 's': { char *str = argv[si].v_str; if (str != NULL) argv[si].v_str = sm_strdup_x(str); } break; case 'r': { char *fmt = argv[si].v_str; if (fmt != NULL) argv[si].v_str = sm_vstringf_x(fmt, ap); } break; } } } SM_EXCEPT(e, "*") { if (exc == NULL || argv == NULL) { /* ** Failure in step 1 or step 2. ** Scan ap and free all exception arguments. */ for (i = 0; i < argc; ++i) { switch (etype->etype_argformat[i]) { case 'i': (void) SM_VA_ARG(ap, int); break; case 'l': (void) SM_VA_ARG(ap, long); break; case 'e': sm_exc_free(SM_VA_ARG(ap, SM_EXC_T*)); break; case 's': case 'r': (void) SM_VA_ARG(ap, char*); break; } } } else { /* ** Failure in step 3. Scan argv and free ** all exception arguments and all string ** arguments that have been duplicated. ** Then free argv. */ for (i = 0; i < argc; ++i) { switch (etype->etype_argformat[i]) { case 'e': sm_exc_free(argv[i].v_exc); break; case 's': case 'r': if (i < si) sm_free(argv[i].v_str); break; } } sm_free(argv); } sm_free(exc); sm_exc_raise_x(e); } SM_END_TRY return exc; } /* ** SM_EXC_NEW_X -- Construct a new exception object. ** ** Parameters: ** etype -- type of exception. ** ... -- varargs. ** ** Returns: ** pointer to exception object. */ SM_EXC_T * #if SM_VA_STD sm_exc_new_x( const SM_EXC_TYPE_T *etype, ...) #else /* SM_VA_STD */ sm_exc_new_x(etype, va_alist) const SM_EXC_TYPE_T *etype; va_dcl #endif /* SM_VA_STD */ { SM_EXC_T *exc; SM_VA_LOCAL_DECL SM_VA_START(ap, etype); exc = sm_exc_vnew_x(etype, ap); SM_VA_END(ap); return exc; } /* ** SM_EXC_FREE -- Destroy a reference to an exception object. ** ** Parameters: ** exc -- exception object. ** ** Returns: ** none. */ void sm_exc_free(exc) SM_EXC_T *exc; { if (exc == NULL) return; SM_REQUIRE(exc->sm_magic == SmExcMagic); if (exc->exc_refcount == 0) return; if (--exc->exc_refcount == 0) { int i, c; for (i = 0; (c = exc->exc_type->etype_argformat[i]) != '\0'; ++i) { switch (c) { case 's': case 'r': sm_free(exc->exc_argv[i].v_str); break; case 'e': sm_exc_free(exc->exc_argv[i].v_exc); break; } } exc->sm_magic = NULL; sm_free(exc->exc_argv); sm_free(exc); } } /* ** SM_EXC_MATCH -- Match exception category against a glob pattern. ** ** Parameters: ** exc -- exception. ** pattern -- glob pattern. ** ** Returns: ** true iff match. */ bool sm_exc_match(exc, pattern) SM_EXC_T *exc; const char *pattern; { if (exc == NULL) return false; SM_REQUIRE(exc->sm_magic == SmExcMagic); return sm_match(exc->exc_type->etype_category, pattern); } /* ** SM_EXC_WRITE -- Write exception message to a stream (wo trailing newline). ** ** Parameters: ** exc -- exception. ** stream -- file for output. ** ** Returns: ** none. */ void sm_exc_write(exc, stream) SM_EXC_T *exc; SM_FILE_T *stream; { SM_REQUIRE_ISA(exc, SmExcMagic); exc->exc_type->etype_print(exc, stream); } /* ** SM_EXC_PRINT -- Print exception message to a stream (with trailing newline). ** ** Parameters: ** exc -- exception. ** stream -- file for output. ** ** Returns: ** none. */ void sm_exc_print(exc, stream) SM_EXC_T *exc; SM_FILE_T *stream; { SM_REQUIRE_ISA(exc, SmExcMagic); exc->exc_type->etype_print(exc, stream); (void) sm_io_putc(stream, SM_TIME_DEFAULT, '\n'); } SM_EXC_HANDLER_T *SmExcHandler = NULL; static SM_EXC_DEFAULT_HANDLER_T SmExcDefaultHandler = NULL; /* ** SM_EXC_NEWTHREAD -- Initialize exception handling for new process/thread. ** ** Parameters: ** h -- default exception handler. ** ** Returns: ** none. */ /* ** Initialize a new process or a new thread by clearing the ** exception handler stack and optionally setting a default ** exception handler function. Call this at the beginning of main, ** or in a new process after calling fork, or in a new thread. ** ** This function is a luxury, not a necessity. ** If h != NULL then you can get the same effect by ** wrapping the body of main, or the body of a forked child ** or a new thread in SM_TRY ... SM_EXCEPT(e,"*") h(e); SM_END_TRY. */ void sm_exc_newthread(h) SM_EXC_DEFAULT_HANDLER_T h; { SmExcHandler = NULL; SmExcDefaultHandler = h; } /* ** SM_EXC_RAISE_X -- Raise an exception. ** ** Parameters: ** exc -- exception. ** ** Returns: ** doesn't. */ void SM_DEAD_D sm_exc_raise_x(exc) SM_EXC_T *exc; { SM_REQUIRE_ISA(exc, SmExcMagic); if (SmExcHandler == NULL) { if (SmExcDefaultHandler != NULL) { SM_EXC_DEFAULT_HANDLER_T h; /* ** If defined, the default handler is expected ** to terminate the current thread of execution ** using exit() or pthread_exit(). ** If it instead returns normally, then we fall ** through to the default case below. If it ** raises an exception, then sm_exc_raise_x is ** re-entered and, because we set SmExcDefaultHandler ** to NULL before invoking h, we will again ** end up in the default case below. */ h = SmExcDefaultHandler; SmExcDefaultHandler = NULL; (*h)(exc); } /* ** No exception handler, so print the error and exit. ** To override this behaviour on a program wide basis, ** call sm_exc_newthread or put an exception handler in main(). ** ** XXX TODO: map the exception category to an exit code ** XXX from . */ sm_exc_print(exc, smioerr); exit(255); } if (SmExcHandler->eh_value == NULL) SmExcHandler->eh_value = exc; else sm_exc_free(exc); sm_longjmp_nosig(SmExcHandler->eh_context, 1); } /* ** SM_EXC_RAISENEW_X -- shorthand for sm_exc_raise_x(sm_exc_new_x(...)) ** ** Parameters: ** etype -- type of exception. ** ap -- varargs. ** ** Returns: ** none. */ void SM_DEAD_D #if SM_VA_STD sm_exc_raisenew_x( const SM_EXC_TYPE_T *etype, ...) #else sm_exc_raisenew_x(etype, va_alist) const SM_EXC_TYPE_T *etype; va_dcl #endif { SM_EXC_T *exc; SM_VA_LOCAL_DECL SM_VA_START(ap, etype); exc = sm_exc_vnew_x(etype, ap); SM_VA_END(ap); sm_exc_raise_x(exc); } dk-milter-1.0.0.dfsg/libsm/xtrap.c0000644000175000017500000000122107347306541016501 0ustar madhackmadhack/* * Copyright (c) 2000 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: xtrap.c,v 1.5 2001/09/11 04:04:49 gshapiro Exp $") #include SM_ATOMIC_UINT_T SmXtrapCount; SM_DEBUG_T SmXtrapDebug = SM_DEBUG_INITIALIZER("sm_xtrap", "@(#)$Debug: sm_xtrap - raise exception at N'th xtrap point $"); SM_DEBUG_T SmXtrapReport = SM_DEBUG_INITIALIZER("sm_xtrap_report", "@(#)$Debug: sm_xtrap_report - report xtrap count on exit $"); dk-milter-1.0.0.dfsg/libsm/get.c0000644000175000017500000000217307347306540016130 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: get.c,v 1.18 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include "local.h" /* ** SM_IO_GETC -- get a character from a file ** ** Parameters: ** fp -- the file to get the character from ** timeout -- time to complete getc ** ** Returns: ** Success: the value of the character read. ** Failure: SM_IO_EOF ** ** This is a function version of the macro (in ). ** It is guarded with locks (which are currently not functional) ** for multi-threaded programs. */ #undef sm_io_getc int sm_io_getc(fp, timeout) register SM_FILE_T *fp; int timeout; { SM_REQUIRE_ISA(fp, SmFileMagic); return sm_getc(fp, timeout); } dk-milter-1.0.0.dfsg/libsm/strcasecmp.c0000644000175000017500000000622707347306541017522 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1987, 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include SM_RCSID("@(#)$Id: strcasecmp.c,v 1.15 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include /* ** SM_STRCASECMP -- 8-bit clean version of strcasecmp ** ** Thank you, vendors, for making this all necessary. */ /* ** This array is designed for mapping upper and lower case letter ** together for a case independent comparison. The mappings are ** based upon ascii character sequences. */ const unsigned char charmap[] = { 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, }; int sm_strcasecmp(s1, s2) const char *s1, *s2; { const unsigned char *us1 = (const unsigned char *)s1; const unsigned char *us2 = (const unsigned char *)s2; while (charmap[*us1] == charmap[*us2]) { if (*us1 == '\0') return 0; ++us1; ++us2; } return charmap[*us1] - charmap[*us2]; } int sm_strncasecmp(s1, s2, n) const char *s1, *s2; register size_t n; { if (n != 0) { register const unsigned char *cm = charmap; register const unsigned char *us1 = (const unsigned char *)s1; register const unsigned char *us2 = (const unsigned char *)s2; do { if (cm[*us1] != cm[*us2++]) return (cm[*us1] - cm[*--us2]); if (*us1++ == '\0') break; } while (--n != 0); } return 0; } dk-milter-1.0.0.dfsg/libsm/clrerr.c0000644000175000017500000000155407347306540016644 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: clrerr.c,v 1.13 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include "local.h" /* ** SM_IO_CLEARERR -- public function to clear a file pointer's error status ** ** Parameters: ** fp -- the file pointer ** ** Returns: ** nothing. */ #undef sm_io_clearerr void sm_io_clearerr(fp) SM_FILE_T *fp; { SM_REQUIRE_ISA(fp, SmFileMagic); sm_clearerr(fp); } dk-milter-1.0.0.dfsg/libsm/snprintf.c0000644000175000017500000000445210513534222017203 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: snprintf.c,v 1.24 2006/10/12 21:50:10 ca Exp $") #include #include #include #include #include "local.h" /* ** SM_SNPRINTF -- format a string to a memory location of restricted size ** ** Parameters: ** str -- memory location to place formatted string ** n -- size of buffer pointed to by str, capped to ** a maximum of INT_MAX ** fmt -- the formatting directives ** ... -- the data to satisfy the formatting ** ** Returns: ** Failure: -1 ** Success: number of bytes that would have been written ** to str, not including the trailing '\0', ** up to a maximum of INT_MAX, as if there was ** no buffer size limitation. If the result >= n ** then the output was truncated. ** ** Side Effects: ** If n > 0, then between 0 and n-1 bytes of formatted output ** are written into 'str', followed by a '\0'. */ int #if SM_VA_STD sm_snprintf(char *str, size_t n, char const *fmt, ...) #else /* SM_VA_STD */ sm_snprintf(str, n, fmt, va_alist) char *str; size_t n; char *fmt; va_dcl #endif /* SM_VA_STD */ { int ret; SM_VA_LOCAL_DECL SM_FILE_T fake; /* While snprintf(3) specifies size_t stdio uses an int internally */ if (n > INT_MAX) n = INT_MAX; SM_VA_START(ap, fmt); /* XXX put this into a static? */ fake.sm_magic = SmFileMagic; fake.f_file = -1; fake.f_flags = SMWR | SMSTR; fake.f_cookie = &fake; fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; fake.f_bf.smb_size = fake.f_w = n ? n - 1 : 0; fake.f_timeout = SM_TIME_FOREVER; fake.f_timeoutstate = SM_TIME_BLOCK; fake.f_close = NULL; fake.f_open = NULL; fake.f_read = NULL; fake.f_write = NULL; fake.f_seek = NULL; fake.f_setinfo = fake.f_getinfo = NULL; fake.f_type = "sm_snprintf:fake"; ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); if (n > 0) *fake.f_p = '\0'; SM_VA_END(ap); return ret; } dk-milter-1.0.0.dfsg/libsm/heap.c0000644000175000017500000004245410103773100016254 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: heap.c,v 1.51 2004/08/03 20:32:00 ca Exp $") /* ** debugging memory allocation package ** See heap.html for documentation. */ #include #include #include #include #include #include #include #include /* undef all macro versions of the "functions" so they can be specified here */ #undef sm_malloc #undef sm_malloc_x #undef sm_malloc_tagged #undef sm_malloc_tagged_x #undef sm_free #undef sm_free_tagged #undef sm_realloc #if SM_HEAP_CHECK # undef sm_heap_register # undef sm_heap_checkptr # undef sm_heap_report #endif /* SM_HEAP_CHECK */ #if SM_HEAP_CHECK SM_DEBUG_T SmHeapCheck = SM_DEBUG_INITIALIZER("sm_check_heap", "@(#)$Debug: sm_check_heap - check sm_malloc, sm_realloc, sm_free calls $"); # define HEAP_CHECK sm_debug_active(&SmHeapCheck, 1) static int ptrhash __P((void *p)); #endif /* SM_HEAP_CHECK */ const SM_EXC_TYPE_T SmHeapOutOfMemoryType = { SmExcTypeMagic, "F:sm.heap", "", sm_etype_printf, "out of memory", }; SM_EXC_T SmHeapOutOfMemory = SM_EXC_INITIALIZER(&SmHeapOutOfMemoryType, NULL); /* ** The behaviour of malloc with size==0 is platform dependent (it ** says so in the C standard): it can return NULL or non-NULL. We ** don't want sm_malloc_x(0) to raise an exception on some platforms ** but not others, so this case requires special handling. We've got ** two choices: "size = 1" or "return NULL". We use the former in the ** following. ** If we had something like autoconf we could figure out the ** behaviour of the platform and either use this hack or just ** use size. */ #define MALLOC_SIZE(size) ((size) == 0 ? 1 : (size)) /* ** SM_MALLOC_X -- wrapper around malloc(), raises an exception on error. ** ** Parameters: ** size -- size of requested memory. ** ** Returns: ** Pointer to memory region. ** ** Note: ** sm_malloc_x only gets called from source files in which heap ** debugging is disabled at compile time. Otherwise, a call to ** sm_malloc_x is macro expanded to a call to sm_malloc_tagged_x. ** ** Exceptions: ** F:sm_heap -- out of memory */ void * sm_malloc_x(size) size_t size; { void *ptr; ENTER_CRITICAL(); ptr = malloc(MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (ptr == NULL) sm_exc_raise_x(&SmHeapOutOfMemory); return ptr; } #if !SM_HEAP_CHECK /* ** SM_MALLOC -- wrapper around malloc() ** ** Parameters: ** size -- size of requested memory. ** ** Returns: ** Pointer to memory region. */ void * sm_malloc(size) size_t size; { void *ptr; ENTER_CRITICAL(); ptr = malloc(MALLOC_SIZE(size)); LEAVE_CRITICAL(); return ptr; } /* ** SM_REALLOC -- wrapper for realloc() ** ** Parameters: ** ptr -- pointer to old memory area. ** size -- size of requested memory. ** ** Returns: ** Pointer to new memory area, NULL on failure. */ void * sm_realloc(ptr, size) void *ptr; size_t size; { void *newptr; ENTER_CRITICAL(); newptr = realloc(ptr, MALLOC_SIZE(size)); LEAVE_CRITICAL(); return newptr; } /* ** SM_REALLOC_X -- wrapper for realloc() ** ** Parameters: ** ptr -- pointer to old memory area. ** size -- size of requested memory. ** ** Returns: ** Pointer to new memory area. ** ** Exceptions: ** F:sm_heap -- out of memory */ void * sm_realloc_x(ptr, size) void *ptr; size_t size; { void *newptr; ENTER_CRITICAL(); newptr = realloc(ptr, MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (newptr == NULL) sm_exc_raise_x(&SmHeapOutOfMemory); return newptr; } /* ** SM_FREE -- wrapper around free() ** ** Parameters: ** ptr -- pointer to memory region. ** ** Returns: ** none. */ void sm_free(ptr) void *ptr; { if (ptr == NULL) return; ENTER_CRITICAL(); free(ptr); LEAVE_CRITICAL(); return; } #else /* !SM_HEAP_CHECK */ /* ** Each allocated block is assigned a "group number". ** By default, all blocks are assigned to group #1. ** By convention, group #0 is for memory that is never freed. ** You can use group numbers any way you want, in order to help make ** sense of sm_heap_report output. */ int SmHeapGroup = 1; int SmHeapMaxGroup = 1; /* ** Total number of bytes allocated. ** This is only maintained if the sm_check_heap debug category is active. */ size_t SmHeapTotal = 0; /* ** High water mark: the most that SmHeapTotal has ever been. */ size_t SmHeapMaxTotal = 0; /* ** Maximum number of bytes that may be allocated at any one time. ** 0 means no limit. ** This is only honoured if sm_check_heap is active. */ SM_DEBUG_T SmHeapLimit = SM_DEBUG_INITIALIZER("sm_heap_limit", "@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $"); /* ** This is the data structure that keeps track of all currently ** allocated blocks of memory known to the heap package. */ typedef struct sm_heap_item SM_HEAP_ITEM_T; struct sm_heap_item { void *hi_ptr; size_t hi_size; char *hi_tag; int hi_num; int hi_group; SM_HEAP_ITEM_T *hi_next; }; #define SM_HEAP_TABLE_SIZE 256 static SM_HEAP_ITEM_T *SmHeapTable[SM_HEAP_TABLE_SIZE]; /* ** This is a randomly generated table ** which contains exactly one occurrence ** of each of the numbers between 0 and 255. ** It is used by ptrhash. */ static unsigned char hashtab[SM_HEAP_TABLE_SIZE] = { 161, 71, 77,187, 15,229, 9,176,221,119,239, 21, 85,138,203, 86, 102, 65, 80,199,235, 32,140, 96,224, 78,126,127,144, 0, 11,179, 64, 30,120, 23,225,226, 33, 50,205,167,130,240,174, 99,206, 73, 231,210,189,162, 48, 93,246, 54,213,141,135, 39, 41,192,236,193, 157, 88, 95,104,188, 63,133,177,234,110,158,214,238,131,233, 91, 125, 82, 94, 79, 66, 92,151, 45,252, 98, 26,183, 7,191,171,106, 145,154,251,100,113, 5, 74, 62, 76,124, 14,217,200, 75,115,190, 103, 28,198,196,169,219, 37,118,150, 18,152,175, 49,136, 6,142, 89, 19,243,254, 47,137, 24,166,180, 10, 40,186,202, 46,184, 67, 148,108,181, 81, 25,241, 13,139, 58, 38, 84,253,201, 12,116, 17, 195, 22,112, 69,255, 43,147,222,111, 56,194,216,149,244, 42,173, 232,220,249,105,207, 51,197,242, 72,211,208, 59,122,230,237,170, 165, 44, 68,123,129,245,143,101, 8,209,215,247,185, 57,218, 53, 114,121, 3,128, 4,204,212,146, 2,155, 83,250, 87, 29, 31,159, 60, 27,107,156,227,182, 1, 61, 36,160,109, 97, 90, 20,168,132, 223,248, 70,164, 55,172, 34, 52,163,117, 35,153,134, 16,178,228 }; /* ** PTRHASH -- hash a pointer value ** ** Parameters: ** p -- pointer. ** ** Returns: ** hash value. ** ** ptrhash hashes a pointer value to a uniformly distributed random ** number between 0 and 255. ** ** This hash algorithm is based on Peter K. Pearson, ** "Fast Hashing of Variable-Length Text Strings", ** in Communications of the ACM, June 1990, vol 33 no 6. */ static int ptrhash(p) void *p; { int h; if (sizeof(void*) == 4 && sizeof(unsigned long) == 4) { unsigned long n = (unsigned long)p; h = hashtab[n & 0xFF]; h = hashtab[h ^ ((n >> 8) & 0xFF)]; h = hashtab[h ^ ((n >> 16) & 0xFF)]; h = hashtab[h ^ ((n >> 24) & 0xFF)]; } # if 0 else if (sizeof(void*) == 8 && sizeof(unsigned long) == 8) { unsigned long n = (unsigned long)p; h = hashtab[n & 0xFF]; h = hashtab[h ^ ((n >> 8) & 0xFF)]; h = hashtab[h ^ ((n >> 16) & 0xFF)]; h = hashtab[h ^ ((n >> 24) & 0xFF)]; h = hashtab[h ^ ((n >> 32) & 0xFF)]; h = hashtab[h ^ ((n >> 40) & 0xFF)]; h = hashtab[h ^ ((n >> 48) & 0xFF)]; h = hashtab[h ^ ((n >> 56) & 0xFF)]; } # endif /* 0 */ else { unsigned char *cp = (unsigned char *)&p; int i; h = 0; for (i = 0; i < sizeof(void*); ++i) h = hashtab[h ^ cp[i]]; } return h; } /* ** SM_MALLOC_TAGGED -- wrapper around malloc(), debugging version. ** ** Parameters: ** size -- size of requested memory. ** tag -- tag for debugging. ** num -- additional value for debugging. ** group -- heap group for debugging. ** ** Returns: ** Pointer to memory region. */ void * sm_malloc_tagged(size, tag, num, group) size_t size; char *tag; int num; int group; { void *ptr; if (!HEAP_CHECK) { ENTER_CRITICAL(); ptr = malloc(MALLOC_SIZE(size)); LEAVE_CRITICAL(); return ptr; } if (sm_xtrap_check()) return NULL; if (sm_debug_active(&SmHeapLimit, 1) && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size) return NULL; ENTER_CRITICAL(); ptr = malloc(MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group)) { ENTER_CRITICAL(); free(ptr); LEAVE_CRITICAL(); ptr = NULL; } SmHeapTotal += size; if (SmHeapTotal > SmHeapMaxTotal) SmHeapMaxTotal = SmHeapTotal; return ptr; } /* ** SM_MALLOC_TAGGED_X -- wrapper around malloc(), debugging version. ** ** Parameters: ** size -- size of requested memory. ** tag -- tag for debugging. ** num -- additional value for debugging. ** group -- heap group for debugging. ** ** Returns: ** Pointer to memory region. ** ** Exceptions: ** F:sm_heap -- out of memory */ void * sm_malloc_tagged_x(size, tag, num, group) size_t size; char *tag; int num; int group; { void *ptr; if (!HEAP_CHECK) { ENTER_CRITICAL(); ptr = malloc(MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (ptr == NULL) sm_exc_raise_x(&SmHeapOutOfMemory); return ptr; } sm_xtrap_raise_x(&SmHeapOutOfMemory); if (sm_debug_active(&SmHeapLimit, 1) && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size) { sm_exc_raise_x(&SmHeapOutOfMemory); } ENTER_CRITICAL(); ptr = malloc(MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group)) { ENTER_CRITICAL(); free(ptr); LEAVE_CRITICAL(); ptr = NULL; } if (ptr == NULL) sm_exc_raise_x(&SmHeapOutOfMemory); SmHeapTotal += size; if (SmHeapTotal > SmHeapMaxTotal) SmHeapMaxTotal = SmHeapTotal; return ptr; } /* ** SM_HEAP_REGISTER -- register a pointer into the heap for debugging. ** ** Parameters: ** ptr -- pointer to register. ** size -- size of requested memory. ** tag -- tag for debugging. ** num -- additional value for debugging. ** group -- heap group for debugging. ** ** Returns: ** true iff successfully registered (not yet in table). */ bool sm_heap_register(ptr, size, tag, num, group) void *ptr; size_t size; char *tag; int num; int group; { int i; SM_HEAP_ITEM_T *hi; if (!HEAP_CHECK) return true; SM_REQUIRE(ptr != NULL); i = ptrhash(ptr); # if SM_CHECK_REQUIRE /* ** We require that ptr is not already in SmHeapTable. */ for (hi = SmHeapTable[i]; hi != NULL; hi = hi->hi_next) { if (hi->hi_ptr == ptr) sm_abort("sm_heap_register: ptr %p is already registered (%s:%d)", ptr, hi->hi_tag, hi->hi_num); } # endif /* SM_CHECK_REQUIRE */ ENTER_CRITICAL(); hi = (SM_HEAP_ITEM_T *) malloc(sizeof(SM_HEAP_ITEM_T)); LEAVE_CRITICAL(); if (hi == NULL) return false; hi->hi_ptr = ptr; hi->hi_size = size; hi->hi_tag = tag; hi->hi_num = num; hi->hi_group = group; hi->hi_next = SmHeapTable[i]; SmHeapTable[i] = hi; return true; } /* ** SM_REALLOC -- wrapper for realloc(), debugging version. ** ** Parameters: ** ptr -- pointer to old memory area. ** size -- size of requested memory. ** ** Returns: ** Pointer to new memory area, NULL on failure. */ void * sm_realloc(ptr, size) void *ptr; size_t size; { void *newptr; SM_HEAP_ITEM_T *hi, **hp; if (!HEAP_CHECK) { ENTER_CRITICAL(); newptr = realloc(ptr, MALLOC_SIZE(size)); LEAVE_CRITICAL(); return newptr; } if (ptr == NULL) return sm_malloc_tagged(size, "realloc", 0, SmHeapGroup); for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next) { if ((**hp).hi_ptr == ptr) { if (sm_xtrap_check()) return NULL; hi = *hp; if (sm_debug_active(&SmHeapLimit, 1) && sm_debug_level(&SmHeapLimit) < SmHeapTotal - hi->hi_size + size) { return NULL; } ENTER_CRITICAL(); newptr = realloc(ptr, MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (newptr == NULL) return NULL; SmHeapTotal = SmHeapTotal - hi->hi_size + size; if (SmHeapTotal > SmHeapMaxTotal) SmHeapMaxTotal = SmHeapTotal; *hp = hi->hi_next; hi->hi_ptr = newptr; hi->hi_size = size; hp = &SmHeapTable[ptrhash(newptr)]; hi->hi_next = *hp; *hp = hi; return newptr; } } sm_abort("sm_realloc: bad argument (%p)", ptr); /* NOTREACHED */ return NULL; /* keep Irix compiler happy */ } /* ** SM_REALLOC_X -- wrapper for realloc(), debugging version. ** ** Parameters: ** ptr -- pointer to old memory area. ** size -- size of requested memory. ** ** Returns: ** Pointer to new memory area. ** ** Exceptions: ** F:sm_heap -- out of memory */ void * sm_realloc_x(ptr, size) void *ptr; size_t size; { void *newptr; SM_HEAP_ITEM_T *hi, **hp; if (!HEAP_CHECK) { ENTER_CRITICAL(); newptr = realloc(ptr, MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (newptr == NULL) sm_exc_raise_x(&SmHeapOutOfMemory); return newptr; } if (ptr == NULL) return sm_malloc_tagged_x(size, "realloc", 0, SmHeapGroup); for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next) { if ((**hp).hi_ptr == ptr) { sm_xtrap_raise_x(&SmHeapOutOfMemory); hi = *hp; if (sm_debug_active(&SmHeapLimit, 1) && sm_debug_level(&SmHeapLimit) < SmHeapTotal - hi->hi_size + size) { sm_exc_raise_x(&SmHeapOutOfMemory); } ENTER_CRITICAL(); newptr = realloc(ptr, MALLOC_SIZE(size)); LEAVE_CRITICAL(); if (newptr == NULL) sm_exc_raise_x(&SmHeapOutOfMemory); SmHeapTotal = SmHeapTotal - hi->hi_size + size; if (SmHeapTotal > SmHeapMaxTotal) SmHeapMaxTotal = SmHeapTotal; *hp = hi->hi_next; hi->hi_ptr = newptr; hi->hi_size = size; hp = &SmHeapTable[ptrhash(newptr)]; hi->hi_next = *hp; *hp = hi; return newptr; } } sm_abort("sm_realloc_x: bad argument (%p)", ptr); /* NOTREACHED */ return NULL; /* keep Irix compiler happy */ } /* ** SM_FREE_TAGGED -- wrapper around free(), debugging version. ** ** Parameters: ** ptr -- pointer to memory region. ** tag -- tag for debugging. ** num -- additional value for debugging. ** ** Returns: ** none. */ void sm_free_tagged(ptr, tag, num) void *ptr; char *tag; int num; { SM_HEAP_ITEM_T **hp; if (ptr == NULL) return; if (!HEAP_CHECK) { ENTER_CRITICAL(); free(ptr); LEAVE_CRITICAL(); return; } for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next) { if ((**hp).hi_ptr == ptr) { SM_HEAP_ITEM_T *hi = *hp; *hp = hi->hi_next; /* ** Fill the block with zeros before freeing. ** This is intended to catch problems with ** dangling pointers. The block is filled with ** zeros, not with some non-zero value, because ** it is common practice in some C code to store ** a zero in a structure member before freeing the ** structure, as a defense against dangling pointers. */ (void) memset(ptr, 0, hi->hi_size); SmHeapTotal -= hi->hi_size; ENTER_CRITICAL(); free(ptr); free(hi); LEAVE_CRITICAL(); return; } } sm_abort("sm_free: bad argument (%p) (%s:%d)", ptr, tag, num); } /* ** SM_HEAP_CHECKPTR_TAGGED -- check whether ptr is a valid argument to sm_free ** ** Parameters: ** ptr -- pointer to memory region. ** tag -- tag for debugging. ** num -- additional value for debugging. ** ** Returns: ** none. ** ** Side Effects: ** aborts if check fails. */ void sm_heap_checkptr_tagged(ptr, tag, num) void *ptr; char *tag; int num; { SM_HEAP_ITEM_T *hp; if (!HEAP_CHECK) return; if (ptr == NULL) return; for (hp = SmHeapTable[ptrhash(ptr)]; hp != NULL; hp = hp->hi_next) { if (hp->hi_ptr == ptr) return; } sm_abort("sm_heap_checkptr(%p): bad ptr (%s:%d)", ptr, tag, num); } /* ** SM_HEAP_REPORT -- output "map" of used heap. ** ** Parameters: ** stream -- the file pointer to write to. ** verbosity -- how much info? ** ** Returns: ** none. */ void sm_heap_report(stream, verbosity) SM_FILE_T *stream; int verbosity; { int i; unsigned long group0total, group1total, otherstotal, grandtotal; if (!HEAP_CHECK || verbosity <= 0) return; group0total = group1total = otherstotal = grandtotal = 0; for (i = 0; i < sizeof(SmHeapTable) / sizeof(SmHeapTable[0]); ++i) { SM_HEAP_ITEM_T *hi = SmHeapTable[i]; while (hi != NULL) { if (verbosity > 2 || (verbosity > 1 && hi->hi_group != 0)) { sm_io_fprintf(stream, SM_TIME_DEFAULT, "%4d %*lx %7lu bytes", hi->hi_group, (int) sizeof(void *) * 2, (long)hi->hi_ptr, (unsigned long)hi->hi_size); if (hi->hi_tag != NULL) { sm_io_fprintf(stream, SM_TIME_DEFAULT, " %s", hi->hi_tag); if (hi->hi_num) { sm_io_fprintf(stream, SM_TIME_DEFAULT, ":%d", hi->hi_num); } } sm_io_fprintf(stream, SM_TIME_DEFAULT, "\n"); } switch (hi->hi_group) { case 0: group0total += hi->hi_size; break; case 1: group1total += hi->hi_size; break; default: otherstotal += hi->hi_size; break; } grandtotal += hi->hi_size; hi = hi->hi_next; } } sm_io_fprintf(stream, SM_TIME_DEFAULT, "heap max=%lu, total=%lu, ", (unsigned long) SmHeapMaxTotal, grandtotal); sm_io_fprintf(stream, SM_TIME_DEFAULT, "group 0=%lu, group 1=%lu, others=%lu\n", group0total, group1total, otherstotal); if (grandtotal != SmHeapTotal) { sm_io_fprintf(stream, SM_TIME_DEFAULT, "BUG => SmHeapTotal: got %lu, expected %lu\n", (unsigned long) SmHeapTotal, grandtotal); } } #endif /* !SM_HEAP_CHECK */ dk-milter-1.0.0.dfsg/libsm/ungetc.c0000644000175000017500000000766710253661450016645 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: ungetc.c,v 1.30 2005/06/14 23:07:20 ca Exp $") #include #include #include #include #include #include #include #include #include #include "local.h" static void sm_submore_x __P((SM_FILE_T *)); /* ** SM_SUBMORE_X -- expand ungetc buffer ** ** Expand the ungetc buffer `in place'. That is, adjust fp->f_p when ** the buffer moves, so that it points the same distance from the end, ** and move the bytes in the buffer around as necessary so that they ** are all at the end (stack-style). ** ** Parameters: ** fp -- the file pointer ** ** Results: ** none. ** ** Exceptions: ** F:sm_heap -- out of memory */ static void sm_submore_x(fp) SM_FILE_T *fp; { register int i; register unsigned char *p; if (fp->f_ub.smb_base == fp->f_ubuf) { /* Get a buffer; f_ubuf is fixed size. */ p = sm_malloc_x((size_t) SM_IO_BUFSIZ); fp->f_ub.smb_base = p; fp->f_ub.smb_size = SM_IO_BUFSIZ; p += SM_IO_BUFSIZ - sizeof(fp->f_ubuf); for (i = sizeof(fp->f_ubuf); --i >= 0;) p[i] = fp->f_ubuf[i]; fp->f_p = p; return; } i = fp->f_ub.smb_size; p = sm_realloc_x(fp->f_ub.smb_base, i << 1); /* no overlap (hence can use memcpy) because we doubled the size */ (void) memcpy((void *) (p + i), (void *) p, (size_t) i); fp->f_p = p + i; fp->f_ub.smb_base = p; fp->f_ub.smb_size = i << 1; } /* ** SM_IO_UNGETC -- place a character back into the buffer just read ** ** Parameters: ** fp -- the file pointer affected ** timeout -- time to complete ungetc ** c -- the character to place back ** ** Results: ** On success, returns value of character placed back, 0-255. ** Returns SM_IO_EOF if c == SM_IO_EOF or if last operation ** was a write and flush failed. ** ** Exceptions: ** F:sm_heap -- out of memory */ int sm_io_ungetc(fp, timeout, c) register SM_FILE_T *fp; int timeout; int c; { SM_REQUIRE_ISA(fp, SmFileMagic); if (c == SM_IO_EOF) return SM_IO_EOF; if (timeout == SM_TIME_IMMEDIATE) { /* ** Ungetting the buffer will take time and we are wanted to ** return immediately. So... */ errno = EAGAIN; return SM_IO_EOF; } if (!Sm_IO_DidInit) sm_init(); if ((fp->f_flags & SMRD) == 0) { /* ** Not already reading: no good unless reading-and-writing. ** Otherwise, flush any current write stuff. */ if ((fp->f_flags & SMRW) == 0) return SM_IO_EOF; if (fp->f_flags & SMWR) { if (sm_flush(fp, &timeout)) return SM_IO_EOF; fp->f_flags &= ~SMWR; fp->f_w = 0; fp->f_lbfsize = 0; } fp->f_flags |= SMRD; } c = (unsigned char) c; /* ** If we are in the middle of ungetc'ing, just continue. ** This may require expanding the current ungetc buffer. */ if (HASUB(fp)) { if (fp->f_r >= fp->f_ub.smb_size) sm_submore_x(fp); *--fp->f_p = c; fp->f_r++; return c; } fp->f_flags &= ~SMFEOF; /* ** If we can handle this by simply backing up, do so, ** but never replace the original character. ** (This makes sscanf() work when scanning `const' data.) */ if (fp->f_bf.smb_base != NULL && fp->f_p > fp->f_bf.smb_base && fp->f_p[-1] == c) { fp->f_p--; fp->f_r++; return c; } /* ** Create an ungetc buffer. ** Initially, we will use the `reserve' buffer. */ fp->f_ur = fp->f_r; fp->f_up = fp->f_p; fp->f_ub.smb_base = fp->f_ubuf; fp->f_ub.smb_size = sizeof(fp->f_ubuf); fp->f_ubuf[sizeof(fp->f_ubuf) - 1] = c; fp->f_p = &fp->f_ubuf[sizeof(fp->f_ubuf) - 1]; fp->f_r = 1; return c; } dk-milter-1.0.0.dfsg/libsm/debug.c0000644000175000017500000001663110103770462016433 0ustar madhackmadhack/* * Copyright (c) 2000, 2001, 2003, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: debug.c,v 1.30 2004/08/03 20:10:26 ca Exp $") /* ** libsm debugging and tracing ** For documentation, see debug.html. */ #include #include #include #include #include #include #include #include #include #include static void sm_debug_reset __P((void)); static const char *parse_named_setting_x __P((const char *)); /* ** Abstractions for printing trace messages. */ /* ** The output file to which trace output is directed. ** There is a controversy over whether this variable ** should be process global or thread local. ** To make the interface more abstract, we've hidden the ** variable behind access functions. */ static SM_FILE_T *SmDebugOutput = smioout; /* ** SM_DEBUG_FILE -- Returns current debug file pointer. ** ** Parameters: ** none. ** ** Returns: ** current debug file pointer. */ SM_FILE_T * sm_debug_file() { return SmDebugOutput; } /* ** SM_DEBUG_SETFILE -- Sets debug file pointer. ** ** Parameters: ** fp -- new debug file pointer. ** ** Returns: ** none. ** ** Side Effects: ** Sets SmDebugOutput. */ void sm_debug_setfile(fp) SM_FILE_T *fp; { SmDebugOutput = fp; } /* ** SM_DEBUG_CLOSE -- Close debug file pointer. ** ** Parameters: ** none. ** ** Returns: ** none. ** ** Side Effects: ** Closes SmDebugOutput. */ void sm_debug_close() { if (SmDebugOutput != NULL && SmDebugOutput != smioout) { sm_io_close(SmDebugOutput, SM_TIME_DEFAULT); SmDebugOutput = NULL; } } /* ** SM_DPRINTF -- printf() for debug output. ** ** Parameters: ** fmt -- format for printf() ** ** Returns: ** none. */ void #if SM_VA_STD sm_dprintf(char *fmt, ...) #else /* SM_VA_STD */ sm_dprintf(fmt, va_alist) char *fmt; va_dcl #endif /* SM_VA_STD */ { SM_VA_LOCAL_DECL if (SmDebugOutput == NULL) return; SM_VA_START(ap, fmt); sm_io_vfprintf(SmDebugOutput, SmDebugOutput->f_timeout, fmt, ap); SM_VA_END(ap); } /* ** SM_DFLUSH -- Flush debug output. ** ** Parameters: ** none. ** ** Returns: ** none. */ void sm_dflush() { sm_io_flush(SmDebugOutput, SM_TIME_DEFAULT); } /* ** This is the internal database of debug settings. ** The semantics of looking up a setting in the settings database ** are that the *last* setting specified in a -d option on the sendmail ** command line that matches a given SM_DEBUG structure is the one that is ** used. That is necessary to conform to the existing semantics of ** the sendmail -d option. We store the settings as a linked list in ** reverse order, so when we do a lookup, we take the *first* entry ** that matches. */ typedef struct sm_debug_setting SM_DEBUG_SETTING_T; struct sm_debug_setting { const char *ds_pattern; unsigned int ds_level; SM_DEBUG_SETTING_T *ds_next; }; SM_DEBUG_SETTING_T *SmDebugSettings = NULL; /* ** We keep a linked list of SM_DEBUG structures that have been initialized, ** for use by sm_debug_reset. */ SM_DEBUG_T *SmDebugInitialized = NULL; const char SmDebugMagic[] = "sm_debug"; /* ** SM_DEBUG_RESET -- Reset SM_DEBUG structures. ** ** Reset all SM_DEBUG structures back to the uninitialized state. ** This is used by sm_debug_addsetting to ensure that references to ** SM_DEBUG structures that occur before sendmail processes its -d flags ** do not cause those structures to be permanently forced to level 0. ** ** Parameters: ** none. ** ** Returns: ** none. */ static void sm_debug_reset() { SM_DEBUG_T *debug; for (debug = SmDebugInitialized; debug != NULL; debug = debug->debug_next) { debug->debug_level = SM_DEBUG_UNKNOWN; } SmDebugInitialized = NULL; } /* ** SM_DEBUG_ADDSETTING_X -- add an entry to the database of debug settings ** ** Parameters: ** pattern -- a shell-style glob pattern (see sm_match). ** WARNING: the storage for 'pattern' will be owned by ** the debug package, so it should either be a string ** literal or the result of a call to sm_strdup_x. ** level -- a non-negative integer. ** ** Returns: ** none. ** ** Exceptions: ** F:sm_heap -- out of memory */ void sm_debug_addsetting_x(pattern, level) const char *pattern; int level; { SM_DEBUG_SETTING_T *s; SM_REQUIRE(pattern != NULL); SM_REQUIRE(level >= 0); s = sm_malloc_x(sizeof(SM_DEBUG_SETTING_T)); s->ds_pattern = pattern; s->ds_level = (unsigned int) level; s->ds_next = SmDebugSettings; SmDebugSettings = s; sm_debug_reset(); } /* ** PARSE_NAMED_SETTING_X -- process a symbolic debug setting ** ** Parameters: ** s -- Points to a non-empty \0 or , terminated string, ** of which the initial character is not a digit. ** ** Returns: ** pointer to terminating \0 or , character. ** ** Exceptions: ** F:sm.heap -- out of memory. ** ** Side Effects: ** adds the setting to the database. */ static const char * parse_named_setting_x(s) const char *s; { const char *pat, *endpat; int level; pat = s; while (*s != '\0' && *s != ',' && *s != '.') ++s; endpat = s; if (*s == '.') { ++s; level = 0; while (isascii(*s) && isdigit(*s)) { level = level * 10 + (*s - '0'); ++s; } if (level < 0) level = 0; } else level = 1; sm_debug_addsetting_x(sm_strndup_x(pat, endpat - pat), level); /* skip trailing junk */ while (*s != '\0' && *s != ',') ++s; return s; } /* ** SM_DEBUG_ADDSETTINGS_X -- process a list of debug options ** ** Parameters: ** s -- a list of debug settings, eg the argument to the ** sendmail -d option. ** ** The syntax of the string s is as follows: ** ** ::= | "," ** ::= | "." ** ::= [a-zA-Z_*?][a-zA-Z0-9_*?]* ** ** However, note that we skip over anything we don't ** understand, rather than report an error. ** ** Returns: ** none. ** ** Exceptions: ** F:sm.heap -- out of memory ** ** Side Effects: ** updates the database of debug settings. */ void sm_debug_addsettings_x(s) const char *s; { for (;;) { if (*s == '\0') return; if (*s == ',') { ++s; continue; } s = parse_named_setting_x(s); } } /* ** SM_DEBUG_LOADLEVEL -- Get activation level of the specified debug object. ** ** Parameters: ** debug -- debug object. ** ** Returns: ** Activation level of the specified debug object. ** ** Side Effects: ** Ensures that the debug object is initialized. */ int sm_debug_loadlevel(debug) SM_DEBUG_T *debug; { if (debug->debug_level == SM_DEBUG_UNKNOWN) { SM_DEBUG_SETTING_T *s; for (s = SmDebugSettings; s != NULL; s = s->ds_next) { if (sm_match(debug->debug_name, s->ds_pattern)) { debug->debug_level = s->ds_level; goto initialized; } } debug->debug_level = 0; initialized: debug->debug_next = SmDebugInitialized; SmDebugInitialized = debug; } return (int) debug->debug_level; } /* ** SM_DEBUG_LOADACTIVE -- Activation level reached? ** ** Parameters: ** debug -- debug object. ** level -- level to check. ** ** Returns: ** true iff the activation level of the specified debug ** object >= level. ** ** Side Effects: ** Ensures that the debug object is initialized. */ bool sm_debug_loadactive(debug, level) SM_DEBUG_T *debug; int level; { return sm_debug_loadlevel(debug) >= level; } dk-milter-1.0.0.dfsg/libsm/fget.c0000644000175000017500000000463507347306540016303 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fget.c,v 1.24 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include #include "local.h" /* ** SM_IO_FGETS -- get a string from a file ** ** Read at most n-1 characters from the given file. ** Stop when a newline has been read, or the count ('n') runs out. ** ** Parameters: ** fp -- the file to read from ** timeout -- time to complete reading the string in milliseconds ** buf -- buffer to place read string in ** n -- size of 'buf' ** ** Returns: ** success: returns value of 'buf' ** failure: NULL (no characters were read) ** timeout: NULL and errno set to EAGAIN ** ** Side Effects: ** may move the file pointer */ char * sm_io_fgets(fp, timeout, buf, n) register SM_FILE_T *fp; int timeout; char *buf; register int n; { register int len; register char *s; register unsigned char *p, *t; SM_REQUIRE_ISA(fp, SmFileMagic); if (n <= 0) /* sanity check */ return NULL; s = buf; n--; /* leave space for NUL */ while (n > 0) { /* If the buffer is empty, refill it. */ if ((len = fp->f_r) <= 0) { /* ** Timeout is only passed if we can't get the data ** from the buffer (which is counted as immediately). */ if (sm_refill(fp, timeout) != 0) { /* EOF/error: stop with partial or no line */ if (s == buf) return NULL; break; } len = fp->f_r; } p = fp->f_p; /* ** Scan through at most n bytes of the current buffer, ** looking for '\n'. If found, copy up to and including ** newline, and stop. Otherwise, copy entire chunk ** and loop. */ if (len > n) len = n; t = (unsigned char *) memchr((void *) p, '\n', len); if (t != NULL) { len = ++t - p; fp->f_r -= len; fp->f_p = t; (void) memcpy((void *) s, (void *) p, len); s[len] = 0; return buf; } fp->f_r -= len; fp->f_p += len; (void) memcpy((void *) s, (void *) p, len); s += len; n -= len; } *s = 0; return buf; } dk-milter-1.0.0.dfsg/libsm/t-types.c0000644000175000017500000000531607443706221016755 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-types.c,v 1.18 2002/03/13 17:29:53 gshapiro Exp $") #include #include #include #include #include int main(argc, argv) int argc; char **argv; { LONGLONG_T ll; LONGLONG_T volatile lt; ULONGLONG_T ull; char buf[128]; char *r; sm_test_begin(argc, argv, "test standard integral types"); SM_TEST(sizeof(LONGLONG_T) == sizeof(ULONGLONG_T)); /* ** sendmail assumes that ino_t, off_t and void* can be cast ** to ULONGLONG_T without losing information. */ if (!SM_TEST(sizeof(ino_t) <= sizeof(ULONGLONG_T)) || !SM_TEST(sizeof(off_t) <= sizeof(ULONGLONG_T)) || !SM_TEST(sizeof(void*) <= sizeof(ULONGLONG_T))) { (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "\ Your C compiler appears to support a 64 bit integral type,\n\ but libsm is not configured to use it. You will need to set\n\ either SM_CONF_LONGLONG or SM_CONF_QUAD_T to 1. See libsm/README\n\ for more details.\n"); } /* ** Most compilers notice that LLONG_MIN - 1 generate an underflow. ** Some compiler generate code that will use the 'X' status bit ** in a CPU and hence (LLONG_MIN - 1 > LLONG_MIN) will be false. ** So we have to decide whether we want compiler warnings or ** a wrong test... ** Question: where do we really need what this test tests? */ #if SM_CONF_TEST_LLONG ll = LLONG_MIN; (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "\ Your C compiler maybe issued a warning during compilation,\n\ please IGNORE the compiler warning!.\n"); lt = LLONG_MIN - 1; SM_TEST(lt > ll); sm_snprintf(buf, sizeof(buf), "%llx", ll); r = "0"; if (!SM_TEST(buf[0] == '8') || !SM_TEST(strspn(&buf[1], r) == sizeof(ll) * 2 - 1)) { (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "oops: LLONG_MIN=%s\n", buf); } ll = LLONG_MAX; lt = ll + 1; SM_TEST(lt < ll); sm_snprintf(buf, sizeof(buf), "%llx", ll); r = "f"; if (!SM_TEST(buf[0] == '7') || !SM_TEST(strspn(&buf[1], r) == sizeof(ll) * 2 - 1)) { (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "oops: LLONG_MAX=%s\n", buf); } #endif /* SM_CONF_TEST_LLONG */ ull = ULLONG_MAX; SM_TEST(ull + 1 == 0); sm_snprintf(buf, sizeof(buf), "%llx", ull); r = "f"; SM_TEST(strspn(buf, r) == sizeof(ll) * 2); /* ** If QUAD_MAX is defined by then quad_t is defined. ** Make sure LONGLONG_T is at least as big as quad_t. */ #ifdef QUAD_MAX SM_TEST(QUAD_MAX <= LLONG_MAX); #endif return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/errstring.c0000644000175000017500000001453107765514241017374 0ustar madhackmadhack/* * Copyright (c) 2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: errstring.c,v 1.19 2003/12/10 03:53:05 gshapiro Exp $") #include #include /* sys_errlist, on some platforms */ #include /* sm_snprintf */ #include #include #if NAMED_BIND # include #endif #if LDAPMAP # include # include /* for LDAP error codes */ #endif /* LDAPMAP */ /* ** Notice: this file is used by libmilter. Please try to avoid ** using libsm specific functions. */ /* ** SM_ERRSTRING -- return string description of error code ** ** Parameters: ** errnum -- the error number to translate ** ** Returns: ** A string description of errnum. ** ** Note: this may point to a local (static) buffer. */ const char * sm_errstring(errnum) int errnum; { char *ret; #ifdef WIN32 if (errnum >= E_WIN32BASE) return sm_win32_strerror(errnum - E_WIN32BASE); #endif /* WIN32 */ switch (errnum) { case EPERM: /* SunOS gives "Not owner" -- this is the POSIX message */ return "Operation not permitted"; /* ** Error messages used internally in sendmail. */ case E_SM_OPENTIMEOUT: return "Timeout on file open"; case E_SM_NOSLINK: return "Symbolic links not allowed"; case E_SM_NOHLINK: return "Hard links not allowed"; case E_SM_REGONLY: return "Regular files only"; case E_SM_ISEXEC: return "Executable files not allowed"; case E_SM_WWDIR: return "World writable directory"; case E_SM_GWDIR: return "Group writable directory"; case E_SM_FILECHANGE: return "File changed after open"; case E_SM_WWFILE: return "World writable file"; case E_SM_GWFILE: return "Group writable file"; case E_SM_GRFILE: return "Group readable file"; case E_SM_WRFILE: return "World readable file"; /* ** DNS error messages. */ #if NAMED_BIND case HOST_NOT_FOUND + E_DNSBASE: return "Name server: host not found"; case TRY_AGAIN + E_DNSBASE: return "Name server: host name lookup failure"; case NO_RECOVERY + E_DNSBASE: return "Name server: non-recoverable error"; case NO_DATA + E_DNSBASE: return "Name server: no data known"; #endif /* NAMED_BIND */ /* ** libsmdb error messages. */ case SMDBE_MALLOC: return "Memory allocation failed"; case SMDBE_GDBM_IS_BAD: return "GDBM is not supported"; case SMDBE_UNSUPPORTED: return "Unsupported action"; case SMDBE_DUPLICATE: return "Key already exists"; case SMDBE_BAD_OPEN: return "Database open failed"; case SMDBE_NOT_FOUND: return "Key not found"; case SMDBE_UNKNOWN_DB_TYPE: return "Unknown database type"; case SMDBE_UNSUPPORTED_DB_TYPE: return "Support for database type not compiled into this program"; case SMDBE_INCOMPLETE: return "DB sync did not finish"; case SMDBE_KEY_EMPTY: return "Key is empty"; case SMDBE_KEY_EXIST: return "Key already exists"; case SMDBE_LOCK_DEADLOCK: return "Locker killed to resolve deadlock"; case SMDBE_LOCK_NOT_GRANTED: return "Lock unavailable"; case SMDBE_LOCK_NOT_HELD: return "Lock not held by locker"; case SMDBE_RUN_RECOVERY: return "Database panic, run recovery"; case SMDBE_IO_ERROR: return "I/O error"; case SMDBE_READ_ONLY: return "Database opened read-only"; case SMDBE_DB_NAME_TOO_LONG: return "Name too long"; case SMDBE_INVALID_PARAMETER: return "Invalid parameter"; case SMDBE_ONLY_SUPPORTS_ONE_CURSOR: return "Only one cursor allowed"; case SMDBE_NOT_A_VALID_CURSOR: return "Invalid cursor"; case SMDBE_OLD_VERSION: return "Berkeley DB file is an old version, recreate it"; case SMDBE_VERSION_MISMATCH: return "Berkeley DB version mismatch between include file and library"; #if LDAPMAP /* ** LDAP URL error messages. */ /* OpenLDAP errors */ # ifdef LDAP_URL_ERR_MEM case E_LDAPURLBASE + LDAP_URL_ERR_MEM: return "LDAP URL can't allocate memory space"; # endif /* LDAP_URL_ERR_MEM */ # ifdef LDAP_URL_ERR_PARAM case E_LDAPURLBASE + LDAP_URL_ERR_PARAM: return "LDAP URL parameter is bad"; # endif /* LDAP_URL_ERR_PARAM */ # ifdef LDAP_URL_ERR_BADSCHEME case E_LDAPURLBASE + LDAP_URL_ERR_BADSCHEME: return "LDAP URL doesn't begin with \"ldap[si]://\""; # endif /* LDAP_URL_ERR_BADSCHEME */ # ifdef LDAP_URL_ERR_BADENCLOSURE case E_LDAPURLBASE + LDAP_URL_ERR_BADENCLOSURE: return "LDAP URL is missing trailing \">\""; # endif /* LDAP_URL_ERR_BADENCLOSURE */ # ifdef LDAP_URL_ERR_BADURL case E_LDAPURLBASE + LDAP_URL_ERR_BADURL: return "LDAP URL is bad"; # endif /* LDAP_URL_ERR_BADURL */ # ifdef LDAP_URL_ERR_BADHOST case E_LDAPURLBASE + LDAP_URL_ERR_BADHOST: return "LDAP URL host port is bad"; # endif /* LDAP_URL_ERR_BADHOST */ # ifdef LDAP_URL_ERR_BADATTRS case E_LDAPURLBASE + LDAP_URL_ERR_BADATTRS: return "LDAP URL bad (or missing) attributes"; # endif /* LDAP_URL_ERR_BADATTRS */ # ifdef LDAP_URL_ERR_BADSCOPE case E_LDAPURLBASE + LDAP_URL_ERR_BADSCOPE: return "LDAP URL scope string is invalid (or missing)"; # endif /* LDAP_URL_ERR_BADSCOPE */ # ifdef LDAP_URL_ERR_BADFILTER case E_LDAPURLBASE + LDAP_URL_ERR_BADFILTER: return "LDAP URL bad or missing filter"; # endif /* LDAP_URL_ERR_BADFILTER */ # ifdef LDAP_URL_ERR_BADEXTS case E_LDAPURLBASE + LDAP_URL_ERR_BADEXTS: return "LDAP URL bad or missing extensions"; # endif /* LDAP_URL_ERR_BADEXTS */ /* Sun LDAP errors */ # ifdef LDAP_URL_ERR_NOTLDAP case E_LDAPURLBASE + LDAP_URL_ERR_NOTLDAP: return "LDAP URL doesn't begin with \"ldap://\""; # endif /* LDAP_URL_ERR_NOTLDAP */ # ifdef LDAP_URL_ERR_NODN case E_LDAPURLBASE + LDAP_URL_ERR_NODN: return "LDAP URL has no DN (required)"; # endif /* LDAP_URL_ERR_NODN */ #endif /* LDAPMAP */ } #if LDAPMAP /* ** LDAP error messages. */ if (errnum >= E_LDAPBASE) return ldap_err2string(errnum - E_LDAPBASE); #endif /* LDAPMAP */ ret = strerror(errnum); if (ret == NULL) { static char buf[30]; (void) sm_snprintf(buf, sizeof buf, "Error %d", errnum); return buf; } return ret; } dk-milter-1.0.0.dfsg/libsm/fread.c0000644000175000017500000000444507347306540016436 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: fread.c,v 1.28 2001/09/11 04:04:48 gshapiro Exp $") #include #include #include #include #include "local.h" /* ** SM_IO_READ -- read data from the file pointer ** ** Parameters: ** fp -- file pointer to read from ** timeout -- time to complete the read ** buf -- location to place read data ** size -- size of each chunk of data ** ** Returns: ** Failure: returns 0 (zero) _and_ sets errno ** Success: returns the number of whole chunks read. ** ** A read returning 0 (zero) is only an indication of error when errno ** has been set. */ size_t sm_io_read(fp, timeout, buf, size) SM_FILE_T *fp; int timeout; void *buf; size_t size; { register size_t resid = size; register char *p; register int r; SM_REQUIRE_ISA(fp, SmFileMagic); if (fp->f_read == NULL) { errno = ENODEV; return 0; } /* ** The ANSI standard requires a return value of 0 for a count ** or a size of 0. Peculiarily, it imposes no such requirements ** on fwrite; it only requires read to be broken. */ if (resid == 0) return 0; if (fp->f_r < 0) fp->f_r = 0; p = buf; while ((int) resid > (r = fp->f_r)) { (void) memcpy((void *) p, (void *) fp->f_p, (size_t) r); fp->f_p += r; /* fp->f_r = 0 ... done in sm_refill */ p += r; resid -= r; if ((fp->f_flags & SMNOW) != 0 && r > 0) { /* ** Take whatever we have available. Spend no more time ** trying to get all that has been requested. ** This is needed on some file types (such as ** SASL) that would jam when given extra, untimely ** reads. */ fp->f_r -= r; return size - resid; } if (sm_refill(fp, timeout) != 0) { /* no more input: return partial result */ return size - resid; } } (void) memcpy((void *) p, (void *) fp->f_p, resid); fp->f_r -= resid; fp->f_p += resid; return size; } dk-milter-1.0.0.dfsg/libsm/Makefile0000644000175000017500000000053210470704326016635 0ustar madhackmadhack# $Id: Makefile,v 1.2 2006/08/16 21:06:30 ca Exp $ SHELL= /bin/sh BUILD= ./Build OPTIONS= $(CONFIG) $(FLAGS) all: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ clean: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ install: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ check: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ fresh: FRC $(SHELL) $(BUILD) $(OPTIONS) -c FRC: dk-milter-1.0.0.dfsg/libsm/makebuf.c0000644000175000017500000000664607370020370016762 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: makebuf.c,v 1.26 2001/10/31 16:04:08 ca Exp $") #include #include #include #include #include #include #include #include "local.h" /* ** SM_MAKEBUF -- make a buffer for the file ** ** Parameters: ** fp -- the file to be buffered ** ** Returns: ** nothing ** ** Allocate a file buffer, or switch to unbuffered I/O. ** By default tty devices default to line buffered. */ void sm_makebuf(fp) register SM_FILE_T *fp; { register void *p; register int flags; size_t size; int couldbetty; if (fp->f_flags & SMNBF) { fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; fp->f_bf.smb_size = 1; return; } flags = sm_whatbuf(fp, &size, &couldbetty); if ((p = sm_malloc(size)) == NULL) { fp->f_flags |= SMNBF; fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; fp->f_bf.smb_size = 1; return; } if (!Sm_IO_DidInit) sm_init(); flags |= SMMBF; fp->f_bf.smb_base = fp->f_p = p; fp->f_bf.smb_size = size; if (couldbetty && isatty(fp->f_file)) flags |= SMLBF; fp->f_flags |= flags; } /* ** SM_WHATBUF -- determine proper buffer for a file (internal) ** ** Plus it fills in 'bufsize' for recommended buffer size and ** fills in flag to indicate if 'fp' could be a tty (nothing ** to do with "betty" :-) ). ** ** Parameters: ** fp -- file pointer to be buffered ** bufsize -- new buffer size (a return) ** couldbetty -- could be a tty (returns) ** ** Returns: ** Success: ** on error: ** SMNPT -- not seek opimized ** SMOPT -- seek opimized */ int sm_whatbuf(fp, bufsize, couldbetty) register SM_FILE_T *fp; size_t *bufsize; int *couldbetty; { struct stat st; if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) { *couldbetty = 0; *bufsize = SM_IO_BUFSIZ; return SMNPT; } /* could be a tty iff it is a character device */ *couldbetty = S_ISCHR(st.st_mode); if (st.st_blksize == 0) { *bufsize = SM_IO_BUFSIZ; return SMNPT; } #if SM_IO_MAX_BUF_FILE > 0 if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) st.st_blksize = SM_IO_MAX_BUF_FILE; #endif /* SM_IO_MAX_BUF_FILE > 0 */ #if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 if (!S_ISREG(st.st_mode)) { # if SM_IO_MAX_BUF > 0 if (st.st_blksize > SM_IO_MAX_BUF) st.st_blksize = SM_IO_MAX_BUF; # if SM_IO_MIN_BUF > 0 else # endif /* SM_IO_MIN_BUF > 0 */ # endif /* SM_IO_MAX_BUF > 0 */ # if SM_IO_MIN_BUF > 0 if (st.st_blksize < SM_IO_MIN_BUF) st.st_blksize = SM_IO_MIN_BUF; # endif /* SM_IO_MIN_BUF > 0 */ } #endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ /* ** Optimise fseek() only if it is a regular file. (The test for ** sm_std_seek is mainly paranoia.) It is safe to set _blksize ** unconditionally; it will only be used if SMOPT is also set. */ if ((fp->f_flags & SMSTR) == 0) { *bufsize = st.st_blksize; fp->f_blksize = st.st_blksize; } else *bufsize = SM_IO_BUFSIZ; if ((st.st_mode & S_IFMT) == S_IFREG && fp->f_seek == sm_stdseek) return SMOPT; else return SMNPT; } dk-milter-1.0.0.dfsg/libsm/t-float.c0000644000175000017500000000344307347306541016721 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_IDSTR(id, "@(#)$Id: t-float.c,v 1.18 2001/09/11 04:04:49 gshapiro Exp $") #include #include #include #include #include int main(argc, argv) int argc; char **argv; { double d, d2; double ld; char buf[128]; char *r; /* ** Sendmail uses printf and scanf with doubles, ** so make sure that this works. */ sm_test_begin(argc, argv, "test floating point stuff"); d = 1.125; sm_snprintf(buf, sizeof(buf), "%d %.3f %d", 0, d, 1); r = "0 1.125 1"; if (!SM_TEST(strcmp(buf, r) == 0)) (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "got %s instead\n", buf); d = 1.125; sm_snprintf(buf, sizeof(buf), "%.3f", d); r = "1.125"; if (!SM_TEST(strcmp(buf, r) == 0)) (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "got %s instead\n", buf); d2 = 0.0; sm_io_sscanf(buf, "%lf", &d2); #if SM_CONF_BROKEN_STRTOD if (d != d2) { (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "wanted %f, got %f\n", d, d2); (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "error ignored since SM_CONF_BROKEN_STRTOD is set for this OS\n"); } #else /* SM_CONF_BROKEN_STRTOD */ if (!SM_TEST(d == d2)) (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "wanted %f, got %f\n", d, d2); #endif /* SM_CONF_BROKEN_STRTOD */ ld = 2.5; sm_snprintf(buf, sizeof(buf), "%.3f %.1f", d, ld); r = "1.125 2.5"; if (!SM_TEST(strcmp(buf, r) == 0)) (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "got %s instead\n", buf); return sm_test_end(); } dk-milter-1.0.0.dfsg/libsm/niprop.c0000644000175000017500000001130007347306540016650 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include SM_RCSID("@(#)$Id: niprop.c,v 1.8 2001/09/11 04:04:48 gshapiro Exp $") #if NETINFO #include #include #include #include #include #include #include #include /* ** NI_PROPVAL -- NetInfo property value lookup routine ** ** Parameters: ** keydir -- the NetInfo directory name in which to search ** for the key. ** keyprop -- the name of the property in which to find the ** property we are interested. Defaults to "name". ** keyval -- the value for which we are really searching. ** valprop -- the property name for the value in which we ** are interested. ** sepchar -- if non-nil, this can be multiple-valued, and ** we should return a string separated by this ** character. ** ** Returns: ** NULL -- if: ** 1. the directory is not found ** 2. the property name is not found ** 3. the property contains multiple values ** 4. some error occurred ** else -- the value of the lookup. ** ** Example: ** To search for an alias value, use: ** ni_propval("/aliases", "name", aliasname, "members", ',') ** ** Notes: ** Caller should free the return value of ni_proval */ # include # define LOCAL_NETINFO_DOMAIN "." # define PARENT_NETINFO_DOMAIN ".." # define MAX_NI_LEVELS 256 char * ni_propval(keydir, keyprop, keyval, valprop, sepchar) char *keydir; char *keyprop; char *keyval; char *valprop; int sepchar; { char *propval = NULL; int i; int j, alen, l; void *ni = NULL; void *lastni = NULL; ni_status nis; ni_id nid; ni_namelist ninl; register char *p; char keybuf[1024]; /* ** Create the full key from the two parts. ** ** Note that directory can end with, e.g., "name=" to specify ** an alternate search property. */ i = strlen(keydir) + strlen(keyval) + 2; if (keyprop != NULL) i += strlen(keyprop) + 1; if (i >= sizeof keybuf) return NULL; (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/"); if (keyprop != NULL) { (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf); } (void) sm_strlcat(keybuf, keyval, sizeof keybuf); #if 0 if (tTd(38, 21)) sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", keydir, keyprop, keyval, valprop, sepchar, keybuf); #endif /* 0 */ /* ** If the passed directory and property name are found ** in one of netinfo domains we need to search (starting ** from the local domain moving all the way back to the ** root domain) set propval to the property's value ** and return it. */ for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) { if (i == 0) { nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); #if 0 if (tTd(38, 20)) sm_dprintf("ni_open(LOCAL) = %d\n", nis); #endif /* 0 */ } else { if (lastni != NULL) ni_free(lastni); lastni = ni; nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); #if 0 if (tTd(38, 20)) sm_dprintf("ni_open(PARENT) = %d\n", nis); #endif /* 0 */ } /* ** Don't bother if we didn't get a handle on a ** proper domain. This is not necessarily an error. ** We would get a positive ni_status if, for instance ** we never found the directory or property and tried ** to open the parent of the root domain! */ if (nis != 0) break; /* ** Find the path to the server information. */ if (ni_pathsearch(ni, &nid, keybuf) != 0) continue; /* ** Find associated value information. */ if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) continue; #if 0 if (tTd(38, 20)) sm_dprintf("ni_lookupprop: len=%d\n", ninl.ni_namelist_len); #endif /* 0 */ /* ** See if we have an acceptable number of values. */ if (ninl.ni_namelist_len <= 0) continue; if (sepchar == '\0' && ninl.ni_namelist_len > 1) { ni_namelist_free(&ninl); continue; } /* ** Calculate number of bytes needed and build result */ alen = 1; for (j = 0; j < ninl.ni_namelist_len; j++) alen += strlen(ninl.ni_namelist_val[j]) + 1; propval = p = sm_malloc(alen); if (propval == NULL) goto cleanup; for (j = 0; j < ninl.ni_namelist_len; j++) { (void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen); l = strlen(p); p += l; *p++ = sepchar; alen -= l + 1; } *--p = '\0'; ni_namelist_free(&ninl); } cleanup: if (ni != NULL) ni_free(ni); if (lastni != NULL && ni != lastni) ni_free(lastni); #if 0 if (tTd(38, 20)) sm_dprintf("ni_propval returns: '%s'\n", propval); #endif /* 0 */ return propval; } #endif /* NETINFO */ dk-milter-1.0.0.dfsg/README0000644000175000017500000001556310627613213014757 0ustar madhackmadhack DK-MILTER PACKAGE This directory has the latest open source DomainKeys filter software from Sendmail, Inc. There is a web site at http://sourceforge.net/projects/dk-milter that is home for the latest updates. There is also a mailing list available there for discussion and support called "dk-milter-discuss". If you are using this filter, you should be on the list. Report any bugs to dk-milter-discuss@lists.sourceforge.net. +--------------+ | INTRODUCTION | +--------------+ The dk-milter package is an open source implementation of the DomainKeys sender authentication system proposed by Yahoo!, Inc. It consists of a library that implements the DomainKeys service, and a milter-based filter application that can plug in to the sendmail MTA to provide that service to sufficiently recent sendmail MTAs. An optional asynchronous resolver library is also provided to work around limitations of the basic BIND resolver which comes installed on most systems. +--------------+ | DEPENDENCIES | +--------------+ To compile and operate, this package requires the following: o OpenSSL (http://www.openssl.org, or ask your software vendor for a package) o sendmail v8.13.0 (or later), and libmilter from the same distribution (http://www.sendmail.org) +-----------------------+ | RELATED DOCUMENTATION | +-----------------------+ Documentation about Sendmail, Inc.'s sender authentication scheme testing program is available at http://www.sendmail.net. Yahoo!'s DomainKeys page is available at http://antispam.yahoo.com/domainkeys. The man page for dk-filter (the actual filter program) is present in the dk-filter directory of this source distribution. HTML-style documentation for libdk is available in libdk/docs in this source distribution. Refer to the INSTALL file for information about how to install dk-milter. Additional compile-time features are listed in the FEATURES file. The formal (historical) specification for DomainKeys can be found in RFC4870 from the IETF, a copy of which is included in this distribution. +---------+ | WARNING | +---------+ Since dk-milter uses cryptography, the following information from OpenSSL applies to this package as well. PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG CRYPTOGRAPHY SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST COMMUNICATING TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS ILLEGAL IN SOME PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE TO YOUR COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL TECHNICAL SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR OTHER PEOPLE YOU ARE STRONGLY ADVISED TO PAY CLOSE ATTENTION TO ANY EXPORT/IMPORT AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHORS ARE NOT LIABLE FOR ANY VIOLATIONS YOU MAKE HERE. SO BE CAREFUL, IT IS YOUR RESPONSIBILITY. If you use OpenSSL then make sure you read their README file which contains information about patents etc. +---------------------+ | DIRECTORY STRUCTURE | +---------------------+ devtools m4-based build scripts and other data needed to compile the package. libar An optional thread-safe asynchronous resolver library. libdk A library that implements the proposed DomainKeys standard. libdk/docs HTML documentation describing the API provided by libdk. dk-filter A milter-based filter application which uses libdk (and optionally libar) to provide DomainKeys service via a sendmail MTA and the milter protocol. +-------------------+ | PERFORMANCE NOTES | +-------------------+ Courtesy of Thom O'Connor from Sendmail, Inc. who's doing a lot of the initial performance and stress testing (slightly edited): The key to building a dk-filter binary built for very high performance is two-fold: 1. If poll() is available on your system, build libmilter to use poll() rather than select(). This is accomplished by modifying your build file (devtools/Site/site.config.m4) to contain this: dnl # use poll() instead of select() in libmilter APPENDDEF(`confENVDEF', `-DSM_CONF_POLL=1')dnl Then build dk-filter with the resulting libmilter.a. poll() is able to handle higher descriptors than select() is on some systems. During high loads where lots of descriptors can be in simultaneous use, this can become important. 2. Make sure to build dk-filter using the asynchronous (ARLIB) resolver. This is accomplished by modifying libdk/Makefile.m4 to enable these lines: APPENDDEF(`confENVDEF', `-DUSE_ARLIB ') APPENDDEF(`confINCDIRS', `-I../libar/ ') Also, edit dk-filter/Makefile.m4 to enable this line: bldPUSH_SMLIB(`ar') Obviously, overall throughput performance is then based on factors such as CPU resource available, DNS performance, etc. However, in benchmark tests using 100% message signing or verification, on a 2-cpu linux box, I'm getting consistent rates of over 100 messages signed or verified per second with a 32kB average message size, and upwards of 200 messages signed/verified per second when using 1kB messages. +----------------+ | RUNTIME ISSUES | +----------------+ WARNING: sendmail symbol 'X' not available The filter attempted to get some information from the MTA which the MTA did not provide. At various points in the interaction between the MTA and the filter, certain macros containing information about the job in progress or the connection being handled are passed from the MTA to the filter. The names of the macros the MTA should pass to the filter are defined by the "Milter.macros" settings in sendmail.cf, e.g. "Milter.macros.connect", "Milter.macros.envfrom", etc. This message indicates that the filter needed the contents of macro X, but that macro was not passed down from the MTA. Typically the values needed by this filter are passed from the MTA if the sendmail.cf was generated by the usual m4 method. If you do not have those options defined in your sendmail.cf, make sure your M4 configuration files are current and rebuild your sendmail.cf to get appropriate lines added to your sendmail.cf, and then restart sendmail. MTA Timeouts By default, the MTA is configured to wait up to ten seconds for a response from a filter before giving up. When querying remote nameservers for key and policy data, the DKIM filter may not get a response from the resolver within that time frame, and thus this MTA timeout will occur. This can cause messages to be rejected, temp-failed or delivered without verification, depending on the failure mode selected for the filter. When using the standard resolver library provided with your system, the DNS timeout cannot be adjusted. If you encounter this problem, you must increase the time the MTA waits for replies. See the documentation in the sendmail open source distribution (libmilter/README in particular) for instructions on changing these timeouts. When using the provided asynchronous resolver library, you can use the "-T" command line option to change the timeout so that it is shorter than the MTA timeout. $Revision: 1.11 $, Last updated $Date: 2007/05/31 18:40:11 $ dk-milter-1.0.0.dfsg/dk-filter/0000755000175000017500000000000010766324725015761 5ustar madhackmadhackdk-milter-1.0.0.dfsg/dk-filter/dk-filter.80000644000175000017500000002331110765764003017727 0ustar madhackmadhack.TH dk-filter 8 "Sendmail, Inc." .SH NAME .B dk-filter - DomainKeys filter for sendmail .SH SYNOPSIS .B dk-filter -p socketspec [-a peerlist] [-A] [-b modes] [-c canon] [-C config] [-d domains] [-D] [-f] [-i ilist] [-I eilist] [-h] [-H] [-k] [-l] [-m mtas] [-M macro[=value][,...]] [-o hdrlist] [-P pidfile] [-q] [-R] [-s keyfile] [-S selector] [-T secs] [-u userid] [-U popdb] [-V] .SH DESCRIPTION .B dk-filter implements Yahoo!, Inc.'s .B DomainKeys draft standard for signing and verifying e-mail messages on a per-domain basis. Details regarding the protocol and other issues related to the draft standard can be found at http://antispam.yahoo.com/domainkeys. .SH OPTIONS .TP .I -a peerlist Identifies a file of "peers" which identifies clients whose connections should be accepted without processing by this filter. The .I peerlist should contain on each line a hostname, domain name (e.g. ".example.com"), IP address, an IPv6 address (including an IPv4 mapped address), or a CIDR-style IP specification (e.g. "192.168.1.0/24"). .TP .I -A Automatically re-start on failures. Use with caution; if the filter fails instantly after it starts, this can cause a tight .I fork(2) loop. .TP .I -b modes Selects operating modes. .I modes is a concatenation of characters which indicate which mode(s) of operation are desired. Valid modes are .I s (signer) and .I v (verifier). The default is .I sv. .TP .I -c canon Selects the canonicalization method to be used when signing messages. When verifying, the message's DomainKey-Signature: header specifies the canonicalization method. The recognized values are .I nofws and .I simple as defined by the DomainKeys draft. The default is .I simple. .TP .I -C config Configuration control. See the CONFIGURATION section for details. .TP .I -d domain [,...] A comma-separated list of domains whose mail should be signed by this filter. Mail from other domains will be verified rather than being signed. If the value of this parameter starts with a "/" character, it is assumed to be a filename from which the domain list will be read, one per line, with "#" characters indicating the beginning of a comment. In either case, the domain name(s) may contain the special character "*" which is treated as a wildcard character matching zero or more characters in a domain name. .TP .I -D Sign subdomains of those listed by the .I -d option as well as the actual domains. .TP .I -f Normally .I dk-filter forks and exits immediately, leaving the service running in the background. This flag suppresses that behaviour so that it runs in the foreground. .TP .I -h Causes .I dk-filter to add a header indicating the presence of this filter in the path of the message from injection to delivery. The product's name, version, and the job ID are included in the header's contents. .TP .I -H Includes on DomainKey signatures the list of headers that were included in the signature. This makes the signature header larger by explicitly listing the included headers, but this also allows verifying agents to ignore headers that were added in transit. .TP .I -i ilist Identifies a file of internal hosts whose mail should be signed rather than verified. Entries in this file follow the same form as those of the .I -a option above. If not specified, the default of "127.0.0.1" is applied. .TP .I -I eilist Identifies a file of "external" hosts which may send mail through the server as one of the signing domains without credentials as such; basically suppresses the "external host (hostname) tried to send mail as (domain)" log messages. Entries in this file follow the same form as those of the .I -a option above. .TP .I -k Causes .I -s to be interpreted as the location of a key list, which is a file listing rules for signing with multiple keys. The key list should contain a set of lines of the form .I sender-pattern:keypath where .I sender-pattern is a pattern to match against message senders (with the special character "*" interpreted as "zero or more characters"), and .I keypath is the path to the PEM-formatted private key to be used for signing messages which match the .I sender-pattern. The selector used in the signature will be the filename portion of .I keypath. .TP .I -l Log via calls to .I syslog(3) any interesting activity. .TP .I -m mta [,...] A comma-separated list of MTA names (a la the .I sendmail(8) DaemonPortOptions Name parameter) whose mail should be signed by this filter. There is no default. .TP .I -M macro[=value][,...] Defines a set of MTA-provided .I macros which should be checked to see if the sender has been determined to be a local user and therefore whether or not the message should be signed; if a .I value is specified, the value of the macro must match the value specified (matching is case-insensitive), otherwise the macro must be defined but may contain any value. The list is empty by default. .TP .I -o header [,...] A comma-separated list of headers which should not be signed. Ignored when verifying. .TP .I -p socketspec Specifies the socket that should be established by the filter to receive connections from .I sendmail(8) in order to provide service. .I socketspec is in one of two forms: .I local:path which creates a UNIX domain socket at the specified .I path, or .I inet:port[@host] which creates a TCP socket on the specified .I port. If the .I host is not given as either a hostname or an IP address, the socket will be listening on all interfaces. This option is mandatory. .TP .I -P pidfile Writes the process ID of the filter, once started, to the filename given. .TP .I -q Requests that messages which fail verification be quarantined by the MTA. (Requires a sufficiently recent version of the milter library.) .TP .I -R When a signature verification fails and the signing site advertises a reporting address (i.e. .I r=user@host in its policy record), send a structured report to that address containing details needed to reproduce the problem. .TP .I -s keyfile Gives the location of a PEM-formatted private key to be used for message signing. .TP .I -S selector Defines the name of the selector to be used when signing messages. See the .B DomainKeys specification for details. .TP .I -T secs Sets the DNS timeout in seconds. A value of 0 causes an infinite wait. The default is 5. Ignored if not using the asynchronous resolver package. See also the NOTES section below. .TP .I -u userid Attempts to be come the specified .I userid before starting operations. .TP .I -U popdb Requests that the filter consult a POP authentication database for IP addresses that should be allowed for signing. The filter must be specially compiled to enable this feature, since it adds a library dependency. .TP .I -V Print the version number and exit without doing anything else. .SH CONFIGURATION The value of the .I -C switch is a comma-separated list of settings of the form .I result=action which defines what the filter should do with messages that produce certain results. Each result and each action has a full name and an abbreviated name. Either is accepted. Below, the abbreviated name appears in parentheses. .TP .I results .I badsignature (bad) the signature found in the message did not verify successfully against the message; .I dnserror (dns) an error was encountered attempting to retrieve a public key from the nameserver; .I internal (int) an internal error occurred; .I nosignature (no) no signature was present on the message; .I signaturemissing (miss) no signature was present on the message which claims to sign all messages. .TP .I action .I accept (a) accept the message; .I discard (d) discard the message; .I tempfail (t) temp-fail the message; .I reject (r) reject the message. .PP In the interests of minimal initial impact, the defaults for .I badsignature, .I nosignature and .I signaturemissing are all .I accept, and the default for the others is .I tempfail. .SH OPERATION A message will be verified unless it conforms to the signing criteria, which are: (1) the domain on the From: address or Sender: address (if present) must be listed by the .I -d command line switch, and (2) the client connecting to the MTA must (a) have authenticated, or (b) be listed in the file referenced by the .I -i command line switch (or be in the default list for that option), or (c) be connected to daemon port named by the .I -m command line switch. When signing a message, a .I DomainKey-Signature: header will be prepended to the message. The signature is computed using the private key provided. You must be running a version of .I sendmail(8) recent enough to be able to do header prepend operations (8.13.0 or later). When verifying a message, an .I Authentication-Results: header will be prepended to indicate the presence of a signature and whether or not it could be validated against the body of the message using the public key advertised by the sender's nameserver. The value of this header can be used by mail user agents to sort or discard messages that were not signed or could not be verified. .SH ENVIRONMENT The following environment variable(s) can be used to adjust the behaviour of this filter: .TP .I DK_TMPDIR The directory to use when creating temporary files. The default is .I /var/tmp. .SH NOTES When using DNS timeouts (see the .I -T option above), be sure not to use a timeout that is larger than the timeout being used for interaction between .I sendmail and the filter. Otherwise, the MTA could abort a message while waiting for a reply from the filter, which in turn is still waiting for a DNS reply. .SH VERSION This man page covers version 1.0.0 of .I dk-filter. .SH COPYRIGHT Copyright (c) 2004-2008, Sendmail, Inc. and its suppliers. All rights reserved. .SH SEE ALSO .I sendmail(8) .P Sendmail Operations Guide .P RFC2821 - Simple Mail Transfer Protocol .P RFC2822 - Internet Messages .P DomainKeys Internet Draft .P http://antispam.yahoo.com/domainkeys dk-milter-1.0.0.dfsg/dk-filter/dk-filter.h0000644000175000017500000000255010766324503020007 0ustar madhackmadhack/* ** Copyright (c) 2004-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: dk-filter.h,v 1.101 2008/03/13 22:22:59 msk Exp $ */ #ifndef _DK_FILTER_H_ #define _DK_FILTER_H_ #ifndef lint static char dk_filter_h_id[] = "@(#)$Id: dk-filter.h,v 1.101 2008/03/13 22:22:59 msk Exp $"; #endif /* !lint */ #define DKF_PRODUCT "Sendmail DomainKeys Filter" #define DKF_VERSION "1.0.0" /* libdk */ #include /* make sure we have TRUE and FALSE */ #ifndef FALSE # define FALSE 0 #endif /* !FALSE */ #ifndef TRUE # define TRUE 1 #endif /* !TRUE */ /* defaults, limits, etc. */ #define BUFRSZ 256 #define CMDLINEOPTS "a:Ab:c:C:d:DfFhHi:I:klm:M:o:p:P:qrRs:S:T:u:U:V" #define DEFTIMEOUT 5 #define HEADERMARGIN 75 #define HOSTUNKNOWN "unknown-host" #define JOBIDUNKNOWN "(unknown-jobid)" #define LOCALHOST "127.0.0.1" #define MAXADDRESS 256 #define MAXARGV 65536 #define MAXHDRLEN 78 #define MAXHEADER 1000 #define MAXSIGNATURE 1024 #define TEMPFILE "/var/tmp/dkXXXXXX" #define UNKNOWN "unknown" #define AUTHRESULTSHDR "Authentication-Results" #define XHEADERNAME "X-DomainKeys" #define XSELECTCANONHDR "X-Canonicalization" /* ** PEER -- peer list, listing clients to ignore */ typedef struct Peer * Peer; struct Peer { char * peer_info; struct Peer * peer_next; }; /* externs */ extern bool dolog; extern char *progname; #endif /* _DK_FILTER_H_ */ dk-milter-1.0.0.dfsg/dk-filter/Makefile.m40000644000175000017500000000173310627630213017730 0ustar madhackmadhackdnl Build description for dk-filter dnl dnl NO USER SERVICEABLE PARTS INSIDE dnl See the package README file for details. include(confBUILDTOOLSDIR`/M4/switch.m4') define(`confMT', `TRUE') define(`confREQUIRE_LIBSM', `true') APPENDDEF(`confLIBS', `-lssl -lcrypto') ifdef(`bld_USE_ARLIB', `bldPUSH_SMLIB(`ar')', `') bldPUSH_SMLIB(`dk') APPENDDEF(`confINCDIRS', `-I../libdk/ ') bldPUSH_SMLIB(`sm') ifdef(`bld_dk_filter_INCDIRS', `APPENDDEF(`confINCDIRS', bld_dk_filter_INCDIRS)', `') ifdef(`bld_dk_filter_LIBDIRS', `APPENDDEF(`confLIBDIRS', bld_dk_filter_LIBDIRS)', `') ifdef(`conf_dk_filter_ENVDEF', `APPENDDEF(`confENVDEF', conf_dk_filter_ENVDEF)', `') ifdef(`conf_dk_filter_LIBS', `APPENDDEF(`confLIBS', conf_dk_filter_LIBS)', `') bldPRODUCT_START(`executable', `dk-filter') define(`bldSOURCES', `dk-filter.c util.c ') PREPENDDEF(`confLIBS', `-lmilter ') bldPRODUCT_END bldPRODUCT_START(`manpage', `dk-filter') define(`bldSOURCES', `dk-filter.8') bldPRODUCT_END bldFINISH dk-milter-1.0.0.dfsg/dk-filter/README0000644000175000017500000002215110763561132016632 0ustar madhackmadhack$Id: README,v 1.15 2008/03/05 18:11:38 msk Exp $ INTRODUCTION ============ This is the development area for Sendmail's DomainKeys filter, which is our implementation of the Yahoo! DomainKeys service. The filter implemented here, if plugged into the Sendmail MTA, provides signing and verification service as per Yahoo!'s DomainKeys specification. ADVISORY ======== THIS IS PRE-RELEASE SOFTWARE, and should not be used in any critical production environments (yet). However, we hope this pre-release period will be as brief as possible so that it can be sanctioned for mainstream use. COMPILING ========= Requires sendmail v8.13.0 or later, for required milter protocol enhancements. To build this package in the public domain: (1) Download and unpack the source package. (2) Change to the dk-milter-(version) directory. (3) Edit libdk/Makefile.m4 and dk-filter/Makefile.m4 as indicated in those files to specify the locations of the OpenSSL include and library files. (4) Type "sh Build". INSTALLING ========== (1) Configure sendmail: (a) Choose a socket at which the MTA and the filter will rendezvous (see the documentation in libmilter for details) (b) Add a line like this example to your sendmail.mc using your desired socket specification: INPUT_MAIL_FILTER(`dk-filter', `S=inet:8891@localhost') (c) Rebuild your sendmail.cf in the usual way (2) Choose a selector name. Current convention is to use the hostname (hostname only, not the fully-qualified domain name) of the host that will be providing the service, but you are free to choose any name you wish, especially if you have a selector assignment scheme in mind. (3) Either: (a) Run the script gentxt.csh. This will generate a public and private key in PEM format and output a TXT record appropriate for insertion into your DNS zone file. Insert it in your zone file and reload your DNS system so the data is published. -OR- (b) Manually generate a public and private key: (i) % openssl genrsa -out rsa.private 512 (ii) % openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM (iii) Add a TXT DNS record containing the base64 encoding of your public key, which is everything between the BEGIN and END lines in the rsa.public file generated above, with spaces and newlines removed. It should be in this form: "k=rsa; t=y; p=MFwwDQYJ...AwEAAQ==" ...using, of course, your own public key's base64 data. The name of the TXT record should be SELECTOR._domainkey.example.com (where "SELECTOR" is the name you chose and "example.com" is your domain name). You might want to set a short TTL on this record. Reload your nameserver so that the record gets published. For a translation of the parameter and value pairs shown here, see the draft spec; basically this just announces an RSA public key and also declares that your site is using this key in test mode so nobody should take any real action based on success or failure of the use of this key to verify a message. (4) Store the private key in a safe place. We generally use a path like /var/db/domainkeys/SELECTOR.key.pem (where "SELECTOR" is the name you chose). (5) Start dk-filter. You will need at least the "-p" option. The current recommended set of command line options is: -l -p SOCKETSPEC -d DOMAIN -s KEYPATH -S SELECTOR ...where SOCKETSPEC is the socket you told sendmail to use above, DOMAIN is the domain or set of domains for which you want to sign mail, KEYPATH is the path to the private key file you generated, and SELECTOR is the selector name you picked. You can tack "-f" on there if you want it to run in the foreground instead of in the background as a daemon. (7) Restart sendmail. DEBUG FEATURES ============== The DKDEBUG environment variable, if set, specifies debugging options to be applied by the filter. Note that libdk uses the same variable name (for now) so there may be some overlap in the debug flags used. See libdk/README for details. The contents of DKDEBUG should be a string containing characters representing the required debug options as depicted in this list: t thread progress; each callback is logged at LOG_INFO along with the thread ID You can also compile the package with the -DDEBUG flag, which builds a version of dk-filter that reads from standard input and dumps trace data to standard output. The input should be an RFC2822 message with the following lines prepended: Fuser@example.com . The first line, starting with "F", defines the envelope sender. The value of this is not actually used, but the mechanism is present and requires the input. The "." line separates the message headers and body from the envelope and must also be included. On standard output you will see each of the milter callbacks that are made by the filter in response to the input, and ultimately the milter return values, the headers that are added, modified or removed, and any changes to the message body that result. You can only feed one message per execution of the debug mode of the program, and the program will terminate when a result is produced. COMMON PROBLEMS =============== 1) MASQUERADE, etc. Since dk-filter plugs into the sendmail MTA at the SMTP level (i.e. before most MTA processing), the headers it sees are the raw headers as provided but the SMTP client. Therefore, if the MTA changes any of the headers which are used in the signature, the message which gets signed outbound and the message which gets verified at the receiver will not be the same and signatures will fail. The solutions available to solve this are: a) Don't use MASQUERADE, genericstable, or any other feature which alters the headers before they are sent to the next hop. b) Run a second MTA which receives messages after they have been altered as described above. c) Anticipate the rewrites the MTA will do and send your mail with those modifications already made. For example, if user@hostname.example.com will be rewritten by your MTA as user@example.com, arrange that your MUAs will send mail that way so that the MTA doesn't actually rewrite anything. 2) Spacing rewrites The MTA will helpfully remove extraneous spaces at the beginning and end of headers. Thus, a message injected with a header that reads: From: ...will be reduced and sent by the MTA as: From: However, dk-filter sees the earlier form and signs based on that. Therefore, again, the signed message and the verified message differ and verification will not succeed. Thunderbird and Mozilla are known to have this problem when configured a certain way. The solutions available: a) Don't inject messages with spaces the MTA will strip. b) Compile with the ANTICIPATE_SENDMAIL_MUNGE enabled. 3) Missing Message-Id: header The DomainKeys specification stipulates that normally all headers below the signature header are included in the signed version of the message. Thus, the positions of headers added by the MTA are significant when applying this specification. If you inject a message with SMTP but don't include a Message-Id: header, the MTA will generate one for you. The problem here is that dk-filter never sees the header that gets added so it's not included in the signed message; however, that header will be added in such a position that the verifier will assume that it is part of the signed message, and thus the signed and verified messages won't match and the verification will fail. The solutions available: a) Restart dk-filter with the "-H" flag, which adds an additional tag to DomainKeys signatures that indicate specifically which headers should when reconstructing the message during verification. Thus, even if the Message-Id: header is not present during signing and the MTA adds it later below the signature, the verifier will be informed that it should be omitted during signature verification. b) Always send mail with a proper Message-Id: header included in the message. 4) Added Headers Similarly, if you are running filters which add headers that appear in the flow of mail after dk-filter signs the message, those headers will be included when verifying although they were not included when signing. The solutions available: a) Have those filters insert their headers above the DomainKey-Signature: header rather than adding them below. b) Restart dk-filter with the "-H" flag as described above. SUPPORT ======= To get support or report bugs, you can access the Sourceforge "tracker" facilities at http://sourceforge.net/projects/dk-milter. There are two public mailing lists available for news and questions about dk-milter. To keep up to date on the latest developments, please subscribe to one or both of the following: dk-milter-announce@lists.sourceforge.net (release announcements) dk-milter-discuss@lists.sourceforge.net (general discussion) You can subscribe to these lists via the project URL above. There is also a private mailing list which should be used to report security bugs or other potentially sensitive issues: dk-milter-security@lists.sourceforge.net (security issues) dk-milter-1.0.0.dfsg/dk-filter/dk-filter.c0000644000175000017500000024431210766324564020015 0ustar madhackmadhack/* ** Copyright (c) 2004-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: dk-filter.c,v 1.180 2008/03/12 14:17:17 msk Exp $ */ #ifndef lint static char dk_filter_c_id[] = "@(#)$Id: dk-filter.c,v 1.180 2008/03/12 14:17:17 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include #if DEBUG # include # include #endif /* DEBUG */ #include #if SOLARIS # if SOLARIS > 20700 # include # else /* SOLARIS > 20700 */ # include # endif /* SOLARIS > 20700 */ #endif /* SOLARIS */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if SOLARIS # define _PATH_DEVNULL "/dev/null" # ifndef _PATH_SENDMAIL # define _PATH_SENDMAIL "/usr/sbin/sendmail" # endif /* ! _PATH_SENDMAIL */ #else /* SOLARIS */ # include #endif /* SOLARIS */ /* openssl includes */ #include #include #include /* sendmail includes */ #include #include /* libmilter includes */ #ifndef DEBUG #include "libmilter/mfapi.h" #endif /* !DEBUG */ /* libdk includes */ #include #if POPAUTH /* libdb includes */ # include #endif /* POPAUTH */ /* dk-filter includes */ #include "dk-filter.h" #include "util.h" #ifdef DEBUG /* DEBUGGING STUFF */ # define MI_SUCCESS 1 # define MI_FAILURE (-1) # define SMFIS_CONTINUE 0 # define SMFIS_ACCEPT 1 # define SMFIS_REJECT 2 # define SMFIS_DISCARD 3 # define SMFIS_TEMPFAIL 4 # define sfsistat int # define SMFICTX void # define _SOCK_ADDR struct sockaddr int smfi_addheader __P((void *, char *, char *)); int smfi_chgheader __P((void *, char *, int, char *)); void *smfi_getpriv __P((void *)); char *smfi_getsymval __P((void *, char *)); int smfi_insheader __P((void *, int, char *, char *)); int smfi_replacebody __P((void *, char *, size_t)); void smfi_setconn __P((char *)); void smfi_setpriv __P((void *, void *)); void smfi_setreply __P((void *, char *, char *, char *)); char *smfis_ret[] = { "SMFIS_CONTINUE", "SMFIS_ACCEPT", "SMFIS_REJECT", "SMFIS_DISCARD", "SMFIS_TEMPFAIL", }; #endif /* DEBUG */ /* ** Header -- a handle referring to a header */ typedef struct Header * Header; struct Header { char * hdr_hdr; char * hdr_val; struct Header * hdr_next; }; /* ** KEYTABLE -- table of keys */ struct keytable { char * key_selector; /* selector */ regex_t key_re; /* regex for matching */ size_t key_len; /* key length */ unsigned char * key_data; /* private key data */ struct keytable * key_next; /* next record */ }; /* ** MSGCTX -- message context, containing transaction-specific data */ typedef struct msgctx * msgctx; struct msgctx { bool mctx_addheader; /* Authentication-Results: */ bool mctx_signing; /* true iff signing */ bool mctx_headeronly; /* in EOM, only add headers */ int mctx_status; /* status to report back */ dk_canon_t mctx_canonalg; /* canonicalization algorithm */ dk_alg_t mctx_signalg; /* signature algorithm */ int mctx_queryalg; /* query algorithm */ char * mctx_jobid; /* job ID */ char * mctx_domain; /* domain doing the signing */ DK * mctx_dk; /* DomainKeys handle */ struct Header * mctx_hqhead; /* header queue head */ struct Header * mctx_hqtail; /* header queue tail */ struct keytable * mctx_key; /* key information */ char mctx_hlist[MAXHEADERS]; /* header buffer */ }; /* ** CONNCTX -- connection context, containing thread-specific data */ typedef struct connctx * connctx; struct connctx { bool cctx_noleadspc; /* no leading spaces */ char cctx_host[MAXHOSTNAMELEN + 1]; /* hostname */ _SOCK_ADDR cctx_ip; /* IP info */ struct msgctx * cctx_msg; /* message context */ }; /* ** CONFIG -- configuration information */ typedef struct Config * Config; struct Config { int cfg_nosig; /* no signature */ int cfg_badsig; /* bad signature */ int cfg_sigmissing; /* missing signature */ int cfg_dnserr; /* DNS error */ int cfg_internal; /* internal error */ }; struct Config defaults = { SMFIS_ACCEPT, /* SMFIS_REJECT, */ SMFIS_ACCEPT, /* SMFIS_REJECT, */ SMFIS_ACCEPT, SMFIS_TEMPFAIL, SMFIS_TEMPFAIL }; /* ** LOOKUP -- lookup table */ struct lookup { char * str; int code; }; #define CFG_NOSIGNATURE 1 #define CFG_BADSIGNATURE 2 #define CFG_SIGMISSING 3 #define CFG_DNSERROR 4 #define CFG_INTERNAL 5 #define DKF_MODE_SIGNER 0x01 #define DKF_MODE_VERIFIER 0x02 #define DKF_MODE_DEFAULT (DKF_MODE_SIGNER|DKF_MODE_VERIFIER) #define DKF_STATUS_GOOD 0 #define DKF_STATUS_BAD 1 #define DKF_STATUS_NOKEY 2 #define DKF_STATUS_REVOKED 3 #define DKF_STATUS_NOSIGNATURE 4 #define DKF_STATUS_BADFORMAT 6 #define DKF_STATUS_NONPART 7 #define DKF_STATUS_UNKNOWN 8 struct lookup dkf_params[] = { { "no", CFG_NOSIGNATURE }, { "nosignature", CFG_NOSIGNATURE }, { "bad", CFG_BADSIGNATURE }, { "badsignature", CFG_BADSIGNATURE }, { "miss", CFG_SIGMISSING }, { "signaturemissing", CFG_SIGMISSING }, { "dns", CFG_DNSERROR }, { "dnserror", CFG_DNSERROR }, { "int", CFG_INTERNAL }, { "internal", CFG_INTERNAL }, { NULL, -1 }, }; struct lookup dkf_values[] = { { "a", SMFIS_ACCEPT }, { "accept", SMFIS_ACCEPT }, { "d", SMFIS_DISCARD }, { "discard", SMFIS_DISCARD }, { "r", SMFIS_REJECT }, { "reject", SMFIS_REJECT }, { "t", SMFIS_TEMPFAIL }, { "tempfail", SMFIS_TEMPFAIL }, { NULL, -1 }, }; struct lookup dkf_status[] = { { "unknown", DKF_STATUS_UNKNOWN }, { "good", DKF_STATUS_GOOD }, { "bad", DKF_STATUS_BAD }, { "no key", DKF_STATUS_NOKEY }, { "revoked", DKF_STATUS_REVOKED }, { "no signature", DKF_STATUS_NOSIGNATURE }, { "bad format", DKF_STATUS_BADFORMAT }, { "non-participant", DKF_STATUS_NONPART }, { NULL, -1 }, }; struct lookup dkf_canon[] = { { "nofws", DK_CANON_NOFWS }, { "simple", DK_CANON_SIMPLE }, { NULL, -1 }, }; /* PROTOTYPES */ sfsistat mlfi_abort __P((SMFICTX *)); sfsistat mlfi_body __P((SMFICTX *, u_char *, size_t)); sfsistat mlfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *)); sfsistat mlfi_envfrom __P((SMFICTX *, char **)); sfsistat mlfi_envrcpt __P((SMFICTX *, char **)); sfsistat mlfi_eoh __P((SMFICTX *)); sfsistat mlfi_eom __P((SMFICTX *)); sfsistat mlfi_header __P((SMFICTX *, char *, char *)); static void dkf_cleanup __P((SMFICTX *)); /* GLOBALS */ bool addxhdr; /* add identifying header? */ bool hdrlist; /* signature includes hdrlist */ bool dolog; /* syslog */ bool quarantine; /* quarantine failures? */ bool no_i_whine; /* noted ${i} is undefined */ bool send_reports; /* send failure reports */ #if _FFR_FLUSH_HEADERS bool flushheaders; /* flush old DK headers */ #endif /* _FFR_FLUSH_HEADERS */ #if _FFR_REQUIRED_HEADERS bool req_hdrs; /* required header checks */ #endif /* _FFR_REQUIRED_HEADERS */ bool subdomains; /* sign subdomains */ bool die; /* global "die" flag */ unsigned int tmo; /* DNS timeout */ unsigned int mode; /* operating mode */ int diesig; /* signal to distribute */ size_t keylen; /* size of secret key */ dk_canon_t canon; /* canon. method for signing */ char *progname; /* program name */ unsigned char *seckey; /* secret key data */ char *selector; /* key selector */ struct Config config; /* configuration */ DK_LIB *libdk; /* libdk handle */ struct keytable *keyhead; /* key list */ struct keytable *keytail; /* key list */ Peer peerlist; /* queue of "peers" */ Peer internal; /* queue of "internal" hosts */ Peer exignore; /* "external ignore" hosts */ char **domains; /* domains to sign */ regex_t **dompats; /* domain patterns */ char **mtas; /* MTA ports to sign */ char **omithdrs; /* headers to omit */ char **macros; /* macros/values to check */ char **values; /* macros/values to check */ #if POPAUTH DB *popdb; /* POP auth DB */ #endif /* POPAUTH */ pthread_mutex_t count_lock; /* counter lock */ int thread_count; /* thread count */ pthread_mutex_t popen_lock; /* popen() lock */ #ifdef DEBUG static void *fakepriv; /* fake private space */ #endif /* DEBUG */ /* Other useful definitions */ #define CRLF "\r\n" /* CRLF */ #define DK_DEFAULT_SELECTOR "main" /* default selector name */ #ifndef SENDMAIL_OPTIONS # define SENDMAIL_OPTIONS "" /* options for reports */ #endif /* SENDMAIL_OPTIONS */ /* MACROS */ #define DK_DEBUG(x) (getenv("DKDEBUG") != NULL && \ strchr(getenv("DKDEBUG"), (x)) != NULL) #define JOBID(x) ((x) == NULL ? JOBIDUNKNOWN : (x)) #define TRYFREE(x) do { \ if ((x) != NULL) \ { \ free(x); \ (x) = NULL; \ } \ } while (0) #define DKF_EOHMACROS "i {daemon_name} {auth_type}" /* ** ================================================================== ** BEGIN private section */ /* ** DKF_SIGHANDLER -- signal handler ** ** Parameters: ** sig -- signal received ** ** Return value: ** None. */ static void dkf_sighandler(int sig) { if (sig == SIGINT || sig == SIGTERM || sig == SIGHUP) { diesig = sig; die = TRUE; } } /* ** DKF_KILLCHILD -- kill child process ** ** Parameters: ** pid -- process ID to signal ** sig -- signal to use ** ** Return value: ** None. */ static void dkf_killchild(pid_t pid, int sig) { if (kill(pid, sig) == -1 && dolog) { syslog(LOG_ERR, "kill(%d, %d): %s", pid, sig, strerror(errno)); } } /* ** DKF_ZAPKEY -- clobber the copy of the private key ** ** Parameters: ** None. ** ** Return value: ** None. */ static void dkf_zapkey(void) { if (seckey != NULL) { memset(seckey, '\0', keylen); free(seckey); } if (keyhead != NULL) { struct keytable *key; for (key = keyhead; key != NULL; key = key->key_next) { memset(key->key_data, '\0', key->key_len); free(key->key_data); } } } /* ** DKF_STDIO -- set up the base descriptors to go nowhere ** ** Parameters: ** None. ** ** Return value: ** None. */ static void dkf_stdio(void) { int devnull; /* this only fails silently, but that's OK */ devnull = open(_PATH_DEVNULL, O_RDWR, 0); if (devnull != -1) { (void) dup2(devnull, 0); (void) dup2(devnull, 1); (void) dup2(devnull, 2); (void) close(devnull); } (void) setsid(); } /* ** DKF_SIGNALG -- return text version of the signing algorithm ** ** Parameters: ** alg -- A dk_alg_t ** ** Return value: ** Pointer to a string which is the text version of the provided code. */ static char * dkf_signalg(dk_alg_t alg) { switch (alg) { case DK_SIGN_RSASHA1: return "rsa-sha1"; case DK_SIGN_UNKNOWN: return "unknown"; default: return NULL; } } /* ** DKF_CANONALG -- return text version of the canonicalization algorithm ** ** Parameters: ** alg -- A dk_canon_t ** ** Return value: ** Pointer to a string which is the text version of the provided code. */ static char * dkf_canonalg(dk_canon_t alg) { switch (alg) { case DK_CANON_NOFWS: return "nofws"; case DK_CANON_SIMPLE: return "simple"; case DK_CANON_UNKNOWN: return "unknown"; default: return NULL; } } /* ** DKF_QUERYALG -- return text version of the query algorithm ** ** Parameters: ** alg -- integer representing the query algorithm used ** ** Return value: ** Pointer to a string which is the text version of the provided code. */ static char * dkf_queryalg(int alg) { switch (alg) { case DK_QUERY_DNS: return "dns"; case DK_QUERY_UNKNOWN: return "unknown"; default: return NULL; } } /* ** DKF_INITCONTEXT -- initialize filter context ** ** Parameters: ** None. ** ** Return value: ** A pointer to an allocated and initialized filter context, or NULL ** on failure. ** ** Side effects: ** Crop circles near Birmingham. */ static msgctx dkf_initcontext(void) { msgctx ctx; ctx = (msgctx) malloc(sizeof(struct msgctx)); if (ctx == NULL) return NULL; (void) memset(ctx, '\0', sizeof(struct msgctx)); ctx->mctx_status = DKF_STATUS_UNKNOWN; ctx->mctx_canonalg = canon; ctx->mctx_signalg = DK_SIGN_DEFAULT; ctx->mctx_queryalg = DK_QUERY_DEFAULT; return ctx; } /* ** DKF_CLEANUP -- release local resources related to a message ** ** Parameters: ** ctx -- milter context ** ** Return value: ** None. */ static void dkf_cleanup(SMFICTX *ctx) { msgctx dfc; connctx cc; #ifndef DEBUG assert(ctx != NULL); #endif /* !DEBUG */ cc = (connctx) smfi_getpriv(ctx); if (cc == NULL) return; dfc = cc->cctx_msg; /* release memory */ if (dfc != NULL) { TRYFREE(dfc->mctx_domain); /* TRYFREE(dfc->mctx_jobid); */ if (dfc->mctx_hqhead != NULL) { Header hdr; Header prev; hdr = dfc->mctx_hqhead; while (hdr != NULL) { TRYFREE(hdr->hdr_hdr); TRYFREE(hdr->hdr_val); prev = hdr; hdr = hdr->hdr_next; TRYFREE(prev); } } if (dfc->mctx_dk != NULL) dk_free(dfc->mctx_dk); free(dfc); cc->cctx_msg = NULL; } } /* ** DKF_CONFIGLOOKUP -- look up the integer code for a config option or value ** ** Parameters: ** opt -- option to look up ** table -- lookup table to use ** ** Return value: ** Integer version of the option, or -1 on error. */ static int dkf_configlookup(char *opt, struct lookup *table) { int c; for (c = 0; ; c++) { if (table[c].str == NULL || strcasecmp(opt, table[c].str) == 0) return table[c].code; } } /* ** DKF_PARSECONFIG -- parse configuration and/or apply defaults ** ** Parameters: ** config -- configuration string, or NULL to apply defaults only ** ** Return value: ** TRUE on success, FALSE on failure. */ static bool dkf_parseconfig(char *confstr) { int vs; char *p; char *v; char *tmp; /* load defaults */ memcpy(&config, &defaults, sizeof(config)); if (confstr == NULL) return TRUE; tmp = strdup(confstr); if (tmp == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); return FALSE; } /* process configuration */ for (p = strtok(tmp, ","); p != NULL; p = strtok(NULL, ",")) { v = strchr(p, '='); if (v == NULL) return FALSE; *v = '\0'; v++; vs = dkf_configlookup(v, dkf_values); if (vs == -1) { fprintf(stderr, "%s: invalid configuration value `%s'\n", progname, v); return FALSE; } /* apply what's been found */ switch (dkf_configlookup(p, dkf_params)) { case CFG_NOSIGNATURE: config.cfg_nosig = vs; break; case CFG_BADSIGNATURE: config.cfg_badsig = vs; break; case CFG_SIGMISSING: config.cfg_sigmissing = vs; break; case CFG_DNSERROR: config.cfg_dnserr = vs; break; case CFG_INTERNAL: config.cfg_internal = vs; break; default: *v = '='; fprintf(stderr, "%s: invalid configuration parameter `%s'\n", progname, p); return FALSE; } } return TRUE; } /* ** DKF_LIBSTATUS -- process a final status returned from libdk ** ** Parameters: ** ctx -- milter context ** where -- what function reported the error ** status -- status returned by a libdk call (DK_STAT_*) ** ** Return value: ** An smfistat value to be returned to libmilter. */ static sfsistat dkf_libstatus(SMFICTX *ctx, char *where, int status) { int retcode = SMFIS_CONTINUE; msgctx dfc; connctx cc; #ifndef DEBUG assert(ctx != NULL); #endif /* ! DEBUG */ cc = smfi_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); switch (status) { case DK_STAT_OK: retcode = SMFIS_CONTINUE; break; case DK_STAT_INTERNAL: retcode = config.cfg_internal; if (dolog) { const char *err; err = dk_geterror(dfc->mctx_dk); if (err == NULL) err = strerror(errno); syslog(LOG_ERR, "%s: %s%sinternal error from libdk: %s", JOBID(dfc->mctx_jobid), where == NULL ? "" : where, where == NULL ? "" : ": ", err); } break; case DK_STAT_BADSIG: retcode = config.cfg_badsig; if (dolog) { syslog(LOG_ERR, "%s: bad signature data", JOBID(dfc->mctx_jobid)); } break; case DK_STAT_NOSIG: retcode = config.cfg_nosig; if (dolog) { syslog(LOG_ERR, "%s: no signature data", JOBID(dfc->mctx_jobid)); } break; case DK_STAT_NORESOURCE: retcode = config.cfg_internal; if (dolog) { const char *err; err = dk_geterror(dfc->mctx_dk); if (err == NULL) err = strerror(errno); syslog(LOG_ERR, "%s: %s%sresource unavailable: %s", JOBID(dfc->mctx_jobid), where == NULL ? "" : where, where == NULL ? "" : ": ", err); } break; case DK_STAT_CANTVRFY: retcode = config.cfg_badsig; if (dolog) { const char *err; err = dk_geterror(dfc->mctx_dk); if (err == NULL) err = "unknown cause"; syslog(LOG_ERR, "%s: signature verification failed: %s", JOBID(dfc->mctx_jobid), err); } break; case DK_STAT_SYNTAX: retcode = config.cfg_badsig; if (dolog) { const char *err; err = dk_geterror(dfc->mctx_dk); if (err == NULL) err = "unspecified"; syslog(LOG_ERR, "%s: syntax error: %s", JOBID(dfc->mctx_jobid), err); } break; } if (ERR_peek_error() != 0 && dolog) { int n; unsigned long e; char errbuf[BUFRSZ + 1]; char tmp[BUFRSZ + 1]; memset(errbuf, '\0', sizeof errbuf); for (n = 0; ; n++) { e = ERR_get_error(); if (e == 0) break; memset(tmp, '\0', sizeof tmp); (void) ERR_error_string_n(e, tmp, sizeof tmp); if (n != 0) sm_strlcat(errbuf, "; ", sizeof errbuf); sm_strlcat(errbuf, tmp, sizeof errbuf); } syslog(LOG_INFO, "%s SSL %s", JOBID(dfc->mctx_jobid), errbuf); } if (status != DK_STAT_OK) dkf_cleanup(ctx); return retcode; } /* ** DKF_FINDHEADER -- find a header ** ** Parameters: ** dfc -- filter context ** hname -- name of the header of interest ** instance -- which instance is wanted (0 = first) ** ** Return value: ** Header handle, or NULL if not found. */ Header dkf_findheader(msgctx dfc, char *hname, int instance) { Header hdr; assert(dfc != NULL); assert(hname != NULL); hdr = dfc->mctx_hqhead; while (hdr != NULL) { if (strcasecmp(hdr->hdr_hdr, hname) == 0) { if (instance == 0) return hdr; else instance--; } hdr = hdr->hdr_next; } return NULL; } /* ** DKF_LOADKEYS -- load multiple keys ** ** Parameters: ** file -- input file ** ** Return value: ** 0 on success, !0 on failure ** ** Side effects: ** keyhead, keytail are updated. */ static int dkf_loadkeys(char *file) { bool blank = TRUE; int line = 0; FILE *f; char *p; char buf[BUFRSZ + 1]; assert(file != NULL); f = fopen(file, "r"); if (f == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, file, strerror(errno)); return -1; } memset(buf, '\0', sizeof buf); while (fgets(buf, sizeof buf, f) != NULL) { /* skip comments */ if (buf[0] == '#') continue; blank = TRUE; /* chomp trailing newline */ for (p = buf; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; break; } if (isascii(*p) && !isspace(*p)) blank = FALSE; } /* skip blank lines */ if (blank) continue; line++; p = strchr(buf, ':'); if (p == NULL) { fprintf(stderr, "%s: %s: line %d: malformed\n", progname, file, line); fclose(f); return -1; } else { int status; char *q; char *r; char *end; size_t n; struct keytable *newkey; int keyfd; struct stat s; char retmp[BUFRSZ]; keyfd = open(p + 1, O_RDONLY, 0); if (keyfd == -1) { fprintf(stderr, "%s: %s: open(): %s\n", progname, p + 1, strerror(errno)); fclose(f); return -1; } status = fstat(keyfd, &s); if (status == -1) { fprintf(stderr, "%s: %s: fstat(): %s\n", progname, p + 1, strerror(errno)); close(keyfd); fclose(f); return -1; } q = p + 1; *p = '\0'; end = retmp + sizeof retmp - 1; memset(retmp, '\0', sizeof retmp); retmp[0] = '^'; r = &retmp[1]; for (p = buf; *p != '\0'; p++) { switch (*p) { case '*': if (r + 3 >= end) { fprintf(stderr, "%s: %s: line %d: \"%s\": expression too large\n", progname, file, line, buf); close(keyfd); fclose(f); return -1; } (void) sm_strlcat(retmp, ".*", sizeof retmp); r += 2; break; case '.': case '$': case '[': case ']': case '(': case ')': if (r + 3 >= end) { fprintf(stderr, "%s: %s: line %d: \"%s\": expression too large\n", progname, file, line, buf); close(keyfd); fclose(f); return -1; } *r = '\\'; r++; /* FALLTHROUGH */ default: *r = *p; r++; break; } } (void) sm_strlcat(retmp, "$", sizeof retmp); newkey = (struct keytable *) malloc(sizeof(struct keytable)); if (newkey == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); close(keyfd); fclose(f); return -1; } newkey->key_next = NULL; r = strrchr(q, '/'); newkey->key_selector = strdup (r == NULL ? q : r + 1); if (newkey->key_selector == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); close(keyfd); fclose(f); return -1; } status = regcomp(&newkey->key_re, retmp, REG_EXTENDED); if (status != 0) { char err[BUFRSZ]; memset(err, '\0', sizeof err); (void) regerror(status, &newkey->key_re, err, sizeof err); fprintf(stderr, "%s: %s: line %d: regcomp(): %s\n", progname, file, line, err); close(keyfd); fclose(f); return -1; } newkey->key_data = malloc(s.st_size); if (newkey->key_data == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); close(keyfd); fclose(f); return -1; } newkey->key_len = s.st_size; n = read(keyfd, newkey->key_data, s.st_size); if (n < s.st_size) { if (n == -1) { fprintf(stderr, "%s: %s: read(): %s\n", progname, q, strerror(errno)); } else { fprintf(stderr, "%s: %s: read() truncated\n", progname, q); } close(keyfd); fclose(f); return -1; } close(keyfd); if (keyhead == NULL) { keyhead = newkey; keytail = newkey; } else { keytail->key_next = newkey; keytail = newkey; } } } fclose(f); return 0; } /* ** DKF_REPORT -- generate a report on failure if possible ** ** Parameters: ** dk -- DK handle ** reason -- reason to report ** ** Return value: ** None. */ void dkf_report(msgctx dfc, char *result, char *reason) { int cfd; int status; DK_STAT dkstatus; size_t inl; size_t outl; FILE *out; BIO *b64; BIO *bout; struct Header *hdr; char buf[BUFRSZ]; char addr[MAXADDRESS + 1]; char hostname[MAXHOSTNAMELEN + 1]; assert(dfc != NULL); if (!send_reports) return; memset(addr, '\0', sizeof addr); memset(hostname, '\0', sizeof hostname); (void) gethostname(hostname, sizeof hostname); dkstatus = dk_reportinfo(dfc->mctx_dk, &cfd, addr, sizeof addr); if (dkstatus != DK_STAT_OK || addr[0] == '\0') return; pthread_mutex_lock(&popen_lock); out = popen(_PATH_SENDMAIL " -t" SENDMAIL_OPTIONS, "w"); pthread_mutex_unlock(&popen_lock); if (out == NULL) { if (dolog) { syslog(LOG_ERR, "%s: popen(): %s", dfc->mctx_jobid, strerror(errno)); } return; } /* we presume sendmail will add From: and Date: ... */ /* To: */ fprintf(out, "To: %s\n", addr); /* Subject: */ fprintf(out, "Subject: DomainKeys failure report for %s\n", dfc->mctx_jobid); /* MIME stuff */ fprintf(out, "MIME-Version: 1.0\n"); fprintf(out, "Content-Type: multipart/report; boundary=\"dkreport/%s/%s\"", hostname, dfc->mctx_jobid); /* ok, now then... */ fprintf(out, "\n"); /* first part: a text blob explaining what this is */ fprintf(out, "--dkreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: text/plain\n"); fprintf(out, "\n"); fprintf(out, "DomainKeys failure report for job %s on %s\n\n", dfc->mctx_jobid, hostname); fprintf(out, "The canonicalized form of the failed message is attached.\n"); fprintf(out, "\n"); /* second part: formatted gunk */ fprintf(out, "--dkreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: message/x-dk-report\n"); fprintf(out, "\n"); fprintf(out, "MTA: %s\n", hostname); fprintf(out, "Agent: %s %s\n", DKF_PRODUCT, DKF_VERSION); fprintf(out, "Result: %s\n", result == NULL ? "(none)" : result); fprintf(out, "Reason: %s\n", reason == NULL ? "(none)" : reason); fprintf(out, "\n"); /* third part: headers */ fprintf(out, "--dkreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: text/rfc822-headers\n"); fprintf(out, "\n"); for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) fprintf(out, "%s: %s\n", hdr->hdr_hdr, hdr->hdr_val); fprintf(out, "\n"); /* fourth part: canonicalized form */ fprintf(out, "--dkreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: text/plain\n"); /* ? */ fprintf(out, "Content-Disposition: attachment; filename=\"%s.txt\"\n", dfc->mctx_jobid); fprintf(out, "Content-Transfer-Encoding: base64\n"); fprintf(out, "\n"); (void) lseek(cfd, SEEK_SET, 0); bout = BIO_new(BIO_s_file()); BIO_set_fp(bout, out, BIO_NOCLOSE); b64 = BIO_new(BIO_f_base64()); bout = BIO_push(b64, bout); for (;;) { inl = read(cfd, buf, sizeof buf); if (inl == 0) break; outl = BIO_write(bout, (char *) buf, inl); if (outl != inl || inl < sizeof buf) break; } BIO_free(bout); /* end */ fprintf(out, "\n--dkreport/%s/%s--\n", hostname, dfc->mctx_jobid); /* send it */ pthread_mutex_lock(&popen_lock); status = pclose(out); pthread_mutex_unlock(&popen_lock); if (status != 0 && dolog) { if (dolog) { syslog(LOG_ERR, "%s: pclose(): %s", dfc->mctx_jobid, strerror(errno)); } } } /* ** END private section ** ================================================================== ** BEGIN milter section */ #if SMFI_VERSION >= 0x01000000 /* ** MLFI_NEGOTIATE -- handler called on new SMTP connection to negotiate ** MTA options ** ** Parameters: ** ctx -- milter context ** f0 -- actions offered by the MTA ** f1 -- protocol steps offered by the MTA ** f2 -- reserved for future extensions ** f3 -- reserved for future extensions ** pf0 -- actions requested by the milter ** pf1 -- protocol steps requested by the milter ** pf2 -- reserved for future extensions ** pf3 -- reserved for future extensions ** ** Return value: ** An SMFIS_* constant. */ static sfsistat mlfi_negotiate(SMFICTX *ctx, unsigned long f0, unsigned long f1, SM_UNUSED(unsigned long f2), SM_UNUSED(unsigned long f3), unsigned long *pf0, unsigned long *pf1, unsigned long *pf2, unsigned long *pf3) { unsigned long reqactions = (SMFIF_ADDHDRS|SMFIF_CHGHDRS); unsigned long wantactions = (SMFIF_SETSYMLIST); unsigned long protosteps = (SMFIP_NOHELO|SMFIP_NORCPT|SMFIP_NOUNKNOWN| SMFIP_NODATA); connctx cc; /* initialize connection context */ cc = malloc(sizeof(struct connctx)); if (cc != NULL) { memset(cc, '\0', sizeof(struct connctx)); smfi_setpriv(ctx, cc); } /* verify the actions we need are available */ if (quarantine) reqactions |= SMFIF_QUARANTINE; if ((f0 & reqactions) != reqactions) { if (dolog) { syslog(LOG_ERR, "mlfi_negotiate(): required milter action(s) not available (got 0x%lx, need 0x%lx)", f0, reqactions); } return SMFIS_REJECT; } /* also try to get some nice features */ wantactions = (wantactions & f0); /* set the actions we want */ *pf0 = (reqactions | wantactions); /* disable as many protocol steps we don't need as are available */ *pf1 = (protosteps & f1); # ifdef SMFIP_HDR_LEADSPC /* request preservation of leading spaces if possible */ if ((f1 & SMFIP_HDR_LEADSPC) != 0) { if (cc != NULL) { cc->cctx_noleadspc = TRUE; *pf1 |= SMFIP_HDR_LEADSPC; } } # endif /* SMFIP_HDR_LEADSPC */ *pf2 = 0; *pf3 = 0; /* request macros if able */ if (macros != NULL && (wantactions & SMFIF_SETSYMLIST) != 0) { int c; char macrolist[BUFRSZ]; memset(macrolist, '\0', sizeof macrolist); sm_strlcpy(macrolist, DKF_EOHMACROS, sizeof macrolist); for (c = 0; macros[c] != NULL; c++) { if (macrolist[0] != '\0') sm_strlcat(macrolist, " ", sizeof macrolist); if (sm_strlcat(macrolist, macros[c], sizeof macrolist) >= sizeof macrolist) { if (dolog) { syslog(LOG_ERR, "mlfi_negotiate(): macro list overflow"); } return SMFIS_REJECT; } } if (smfi_setsymlist(ctx, SMFIM_EOH, macrolist) != MI_SUCCESS) { if (dolog) syslog(LOG_ERR, "smfi_setsymlist() failed"); return SMFIS_REJECT; } } return SMFIS_CONTINUE; } #endif /* SMFI_VERSION >= 0x01000000 */ /* ** MLFI_CONNECT -- connection handler ** ** Parameters: ** ctx -- milter context ** host -- hostname ** ip -- address, in in_addr form ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_connect(SMFICTX *ctx, char *host, _SOCK_ADDR *ip) { connctx cc; if (DK_DEBUG('t')) { pthread_mutex_lock(&count_lock); thread_count++; syslog(LOG_INFO, "thread %p connect (%d)", pthread_self(), thread_count); pthread_mutex_unlock(&count_lock); } /* if the client is on an ignored host, then ignore it */ if (peerlist != NULL) { /* try hostname, if available */ if (host != NULL && host[0] != '\0' && host[0] != '[') { dkf_lowercase(host); if (dkf_checkhost(peerlist, host)) return SMFIS_ACCEPT; } /* try IP address, if available */ if (ip != NULL && ip->sa_family == AF_INET) { if (dkf_checkip(peerlist, ip)) return SMFIS_ACCEPT; } } /* copy hostname and IP information to a connection context */ cc = smfi_getpriv(ctx); if (cc == NULL) { cc = malloc(sizeof(struct connctx)); if (cc == NULL) { if (dolog) { syslog(LOG_ERR, "%s malloc(): %s", host, strerror(errno)); } return SMFIS_TEMPFAIL; } memset(cc, '\0', sizeof(struct connctx)); } sm_strlcpy(cc->cctx_host, host, sizeof cc->cctx_host); if (ip == NULL) { struct sockaddr_in sin; memset(&sin, '\0', sizeof sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); memcpy(&cc->cctx_ip, &sin, sizeof(cc->cctx_ip)); } else { memcpy(&cc->cctx_ip, ip, sizeof(cc->cctx_ip)); } cc->cctx_msg = NULL; smfi_setpriv(ctx, cc); return SMFIS_CONTINUE; } /* ** MLFI_ENVFROM -- handler for MAIL FROM command (start of message) ** ** Parameters: ** ctx -- milter context ** envfrom -- envelope from arguments ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_envfrom(SMFICTX *ctx, char **envfrom) { connctx cc; msgctx dfc; #ifndef DEBUG assert(ctx != NULL); assert(envfrom != NULL); #endif /* !DEBUG */ cc = (connctx) smfi_getpriv(ctx); assert(cc != NULL); if (DK_DEBUG('t')) syslog(LOG_INFO, "thread %p envfrom", pthread_self()); /* ** Initialize a filter context. */ dkf_cleanup(ctx); dfc = dkf_initcontext(); if (dfc == NULL) { if (dolog) { syslog(LOG_INFO, "message requeueing (internal error)"); } dkf_cleanup(ctx); return SMFIS_TEMPFAIL; } /* ** Save it in this thread's private space. */ cc->cctx_msg = dfc; /* ** Continue processing. */ return SMFIS_CONTINUE; } /* ** MLFI_HEADER -- handler for mail headers; stores the header in a vector ** of headers for later perusal, removing RFC822 comment ** substrings ** ** Parameters: ** ctx -- milter context ** headerf -- header ** headerv -- value ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_header(SMFICTX *ctx, char *headerf, char *headerv) { msgctx dfc; connctx cc; Header newhdr; #ifdef _FFR_ANTICIPATE_SENDMAIL_MUNGE char *end; char *p; char *q; char hv[MAXHEADER]; #endif /* _FFR_ANTICIPATE_SENDMAIL_MUNGE */ #ifndef DEBUG assert(ctx != NULL); #endif /* !DEBUG */ assert(headerf != NULL); assert(headerv != NULL); if (DK_DEBUG('t')) syslog(LOG_INFO, "thread %p header", pthread_self()); cc = (connctx) smfi_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); newhdr = (Header) malloc(sizeof(struct Header)); if (newhdr == NULL) { if (dolog) syslog(LOG_ERR, "malloc(): %s", strerror(errno)); dkf_cleanup(ctx); return SMFIS_TEMPFAIL; } (void) memset(newhdr, '\0', sizeof(struct Header)); newhdr->hdr_hdr = strdup(headerf); #ifdef _FFR_ANTICIPATE_SENDMAIL_MUNGE /* ** The sendmail MTA does some minor header rewriting on outgoing ** mail. This makes things slightly prettier for the MUA, but ** these changes are made after this filter has already generated ** and added a signature. As a result, verification of the ** signature will fail because what got signed isn't the same ** as what actually goes out. This chunk of code attempts to ** compensate by arranging to feed to the canonicalization ** algorithms the headers exactly as the MTA will modify them, so ** verification should still work. This is based on experimentation ** and on reading sendmail/headers.c, and may require more tweaking ** before it's precisely right. */ (void) memset(hv, '\0', sizeof hv); end = hv + sizeof hv; for (p = headerv, q = hv; *p != '\0' && q < end; p++) { /* skip initial spaces */ if (q == hv && isascii(*p) && isspace(*p)) continue; *q = *p; q++; } newhdr->hdr_val = strdup(hv); #else /* _FFR_ANTICIPATE_SENDMAIL_MUNGE */ newhdr->hdr_val = strdup(headerv); #endif /* _FFR_ANTICIPATE_SENDMAIL_MUNGE */ newhdr->hdr_next = NULL; if (newhdr->hdr_hdr == NULL || newhdr->hdr_val == NULL) { if (dolog) syslog(LOG_ERR, "malloc(): %s", strerror(errno)); TRYFREE(newhdr->hdr_hdr); TRYFREE(newhdr->hdr_val); TRYFREE(newhdr); dkf_cleanup(ctx); return SMFIS_TEMPFAIL; } if (dfc->mctx_hqhead == NULL) dfc->mctx_hqhead = newhdr; if (dfc->mctx_hqtail != NULL) dfc->mctx_hqtail->hdr_next = newhdr; dfc->mctx_hqtail = newhdr; #if _FFR_SELECT_CANONICALIZATION if (strcasecmp(headerf, XSELECTCANONHDR) == 0) { int c; c = dkf_configlookup(headerv, dkf_canon); if (c != -1) dfc->mctx_canonalg = (dk_canon_t) c; } #endif /* _FFR_SELECT_CANONICALIZATION */ return SMFIS_CONTINUE; } /* ** MLFI_EOH -- handler called when there are no more headers ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_eoh(SMFICTX *ctx) { bool msgsigned; bool domainok; bool originok; bool skip; int status; connctx cc; msgctx dfc; char *p; char *domain = NULL; Header from; Header hdr; char addr[MAXADDRESS + 1]; char hdrbuf[MAXHEADER + 1]; #ifndef DEBUG assert(ctx != NULL); #endif /* !DEBUG */ if (DK_DEBUG('t')) syslog(LOG_INFO, "thread %p eoh", pthread_self()); cc = (connctx) smfi_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); /* ** Determine the message ID for logging. */ dfc->mctx_jobid = smfi_getsymval(ctx, "i"); if (dfc->mctx_jobid == NULL) dfc->mctx_jobid = JOBIDUNKNOWN; #if _FFR_REQUIRED_HEADERS /* if requested, verify RFC2822-required headers */ if (req_hdrs) { bool ok = TRUE; /* exactly one From: */ if (dkf_findheader(dfc, "From", 0) == NULL || dkf_findheader(dfc, "From", 1) != NULL) ok = FALSE; /* exactly one Date: */ if (dkf_findheader(dfc, "Date", 0) == NULL || dkf_findheader(dfc, "Date", 1) != NULL) ok = FALSE; if (!ok) { if (dolog) { syslog(LOG_INFO, "%s RFC2822-required header(s) missing", dfc->mctx_jobid); } dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; dfc->mctx_status = DKF_STATUS_BADFORMAT; return SMFIS_CONTINUE; } } #endif /* _FFR_REQUIRED_HEADERS */ msgsigned = (dkf_findheader(dfc, DK_SIGNHEADER, 0) != NULL); /* find the Sender: or From: header */ memset(addr, '\0', sizeof addr); from = dkf_findheader(dfc, "Sender", 0); if (from == NULL) from = dkf_findheader(dfc, "From", 0); if (from == NULL) { if (dolog) { syslog(LOG_INFO, "%s: no From: or Sender: header; accepting", dfc->mctx_jobid); } if (msgsigned) dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; dfc->mctx_status = DKF_STATUS_BADFORMAT; return SMFIS_CONTINUE; } /* extract the sender's domain */ sm_strlcpy(addr, from->hdr_val, sizeof addr); status = rfc2822_mailbox_split(addr, &p, &domain); if (status != 0 || p == NULL || domain == NULL) { if (dolog) { syslog(LOG_INFO, "%s: can't parse From: header", dfc->mctx_jobid); } dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; dfc->mctx_status = DKF_STATUS_BADFORMAT; return SMFIS_CONTINUE; } /* assume we're not signing */ dfc->mctx_signalg = DK_SIGN_UNKNOWN; dfc->mctx_signing = FALSE; domainok = FALSE; originok = FALSE; /* is it a domain we sign for? */ if (!msgsigned && domains != NULL && domain != NULL) { int n; if (dompats != NULL) { for (n = 0; dompats[n] != NULL; n++) { status = regexec(dompats[n], domain, 0, NULL, 0); if (status == 0) { domainok = TRUE; break; } } } else { for (n = 0; domains[n] != NULL; n++) { if (strcasecmp(domain, domains[n]) == 0) { domain = domains[n]; domainok = TRUE; break; } } } if (!domainok && subdomains) { for (p = strchr(domain, '.'); p != NULL && !domainok; p = strchr(p + 1, '.')) { p++; if (*p == '\0') break; if (dompats != NULL) { for (n = 0; dompats[n] != NULL; n++) { status = regexec(dompats[n], domain, 0, NULL, 0); if (status == 0) { domainok = TRUE; break; } } } else { for (n = 0; domains[n] != NULL; n++) { if (strcasecmp(p, domains[n]) == 0) { domain = domains[n]; domainok = TRUE; break; } } } } } dfc->mctx_domain = strdup(domain); } /* is it a domain we sign for? (take two) */ if (keyhead != NULL) { struct keytable *curkey; char srchaddr[MAXADDRESS + 1]; snprintf(srchaddr, sizeof srchaddr, "%s@%s", p, dfc->mctx_domain); /* select the key */ for (curkey = keyhead; curkey != NULL; curkey = curkey->key_next) { status = regexec(&curkey->key_re, srchaddr, 0, NULL, 0); if (status == 0) break; if (status != REG_NOMATCH) { if (dolog) { char err[BUFRSZ]; (void) regerror(status, &curkey->key_re, err, sizeof err); syslog(LOG_ERR, "%s regexec(): %s", dfc->mctx_jobid, err); } dkf_cleanup(ctx); return SMFIS_TEMPFAIL; } } if (curkey != NULL) { dfc->mctx_key = curkey; domainok = TRUE; } } /* see if it came in on an authorized MSA/MTA connection */ if (mtas != NULL) { int n; char *mtaname; mtaname = smfi_getsymval(ctx, "{daemon_name}"); if (mtaname != NULL) { for (n = 0; mtas[n] != NULL; n++) { if (strcasecmp(mtaname, mtas[n]) == 0) { originok = TRUE; break; } } } } /* see if macro tests passed */ if (macros != NULL) { int n; char *val; char name[BUFRSZ + 1]; for (n = 0; macros[n] != NULL; n++) { snprintf(name, sizeof name, "{%s}", macros[n]); val = smfi_getsymval(ctx, name); if (val == NULL) continue; if (values[n] == NULL || (values[n] != NULL && strcasecmp(values[n], val) == 0)) { originok = TRUE; break; } } } /* see if it came from an internal or authenticated source */ if (!originok) { char *authtype; authtype = smfi_getsymval(ctx, "{auth_type}"); if ((authtype == NULL || authtype[0] == '\0') && #if POPAUTH !dkf_checkpopauth(popdb, &cc->cctx_ip) && #endif /* POPAUTH */ !dkf_checkhost(internal, cc->cctx_host) && !dkf_checkip(internal, &cc->cctx_ip)) { if (domainok && dolog && !dkf_checkhost(exignore, cc->cctx_host) && !dkf_checkip(exignore, &cc->cctx_ip)) { syslog(LOG_NOTICE, "%s external host %s attempted to send as %s", dfc->mctx_jobid, cc->cctx_host, dfc->mctx_domain); } } else { originok = TRUE; } } /* set signing mode if the tests passed */ if (domainok && originok) { dfc->mctx_signalg = DK_SIGN_RSASHA1; dfc->mctx_signing = TRUE; dfc->mctx_addheader = TRUE; } /* ** If we're not operating in the role matching the required operation, ** just accept the message and be done with it. */ if ((dfc->mctx_signing && (mode & DKF_MODE_SIGNER) == 0) || (!dfc->mctx_signing && (mode & DKF_MODE_VERIFIER) == 0)) return SMFIS_ACCEPT; /* grab an appropriate handle for message processing */ if (!dfc->mctx_signing) { dfc->mctx_dk = dk_verify(libdk, dfc->mctx_jobid, NULL, &status); } else if (dfc->mctx_key != NULL) { dfc->mctx_dk = dk_sign(libdk, dfc->mctx_jobid, NULL, (dk_sigkey_t *) dfc->mctx_key->key_data, dfc->mctx_canonalg, dfc->mctx_signalg, &status); } else { dfc->mctx_dk = dk_sign(libdk, dfc->mctx_jobid, NULL, (dk_sigkey_t *) seckey, dfc->mctx_canonalg, dfc->mctx_signalg, &status); } if (dfc->mctx_dk == NULL && status != DK_STAT_OK) return dkf_libstatus(ctx, "dk_new()", status); (void) dk_timeout(dfc->mctx_dk, tmo, NULL); /* run the headers */ memset(hdrbuf, '\0', sizeof hdrbuf); for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { skip = FALSE; if (omithdrs != NULL && dfc->mctx_signing) { int c; for (c = 0; omithdrs[c] != NULL; c++) { if (strcasecmp(hdr->hdr_hdr, omithdrs[c]) == 0) { skip = TRUE; break; } } if (skip) continue; } snprintf(hdrbuf, MAXHEADER, "%s:%s%s%s", hdr->hdr_hdr, cc->cctx_noleadspc ? "" : " ", hdr->hdr_val, CRLF); status = dk_header(dfc->mctx_dk, hdrbuf, strlen(hdrbuf)); if (status != DK_STAT_OK) return dkf_libstatus(ctx, "dk_header()", status); } /* signal end of headers */ status = dk_eoh(dfc->mctx_dk); switch (status) { case DK_STAT_REVOKED: dfc->mctx_status = DKF_STATUS_REVOKED; dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; return SMFIS_CONTINUE; case DK_STAT_BADSIG: dfc->mctx_status = DKF_STATUS_BAD; dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; return SMFIS_CONTINUE; case DK_STAT_NOSIG: dfc->mctx_status = DKF_STATUS_NOSIGNATURE; dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; return SMFIS_CONTINUE; case DK_STAT_NOKEY: dfc->mctx_status = DKF_STATUS_NOKEY; dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; return SMFIS_CONTINUE; /* XXX -- other codes? */ case DK_STAT_OK: return SMFIS_CONTINUE; default: return dkf_libstatus(ctx, "dk_eoh()", status); } } /* ** MLFI_BODY -- handler for an arbitrary body block ** ** Parameters: ** ctx -- milter context ** bodyp -- body block ** bodylen -- amount of data available at bodyp ** ** Return value: ** An SMFIS_* constant. ** ** Description: ** This function reads the body chunks passed by the MTA and ** stores them for later wrapping, if needed. */ sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t bodylen) { int status; msgctx dfc; connctx cc; #ifndef DEBUG assert(ctx != NULL); #endif /* !DEBUG */ assert(bodyp != NULL); if (DK_DEBUG('t')) syslog(LOG_INFO, "thread %p body", pthread_self()); cc = (connctx) smfi_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); /* ** No need to do anything if the body was empty. */ if (bodylen == 0 || dfc->mctx_headeronly) return SMFIS_CONTINUE; status = dk_body(dfc->mctx_dk, bodyp, bodylen); if (status != DK_STAT_OK) return dkf_libstatus(ctx, "dk_body()", status); return SMFIS_CONTINUE; } /* ** MLFI_EOM -- handler called at the end of the message; we can now decide ** based on the configuration if and how to add the text ** to this message, then release resources ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_eom(SMFICTX *ctx) { int status = DK_STAT_OK; int c; int n; int w; int s; int dkf; sfsistat ret; connctx cc; msgctx dfc; char *hostname; #if _FFR_FLUSH_HEADERS Header hdr; #endif /* _FFR_FLUSH_HEADERS */ unsigned char sig[MAXSIGNATURE]; unsigned char header[MAXHEADER + 1]; #ifndef DEBUG assert(ctx != NULL); #endif /* !DEBUG */ if (DK_DEBUG('t')) syslog(LOG_INFO, "thread %p eom", pthread_self()); cc = (connctx) smfi_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); /* ** If necessary, try again to get the job ID in case it came down ** later than expected (e.g. postfix). */ if (dfc->mctx_jobid == JOBIDUNKNOWN) { dfc->mctx_jobid = smfi_getsymval(ctx, "i"); if (dfc->mctx_jobid == NULL) { if (no_i_whine && dolog) { syslog(LOG_WARNING, "WARNING: sendmail symbol 'i' not available"); no_i_whine = FALSE; } dfc->mctx_jobid = JOBIDUNKNOWN; } } /* get hostname; used in the X header and in new MIME boundaries */ hostname = smfi_getsymval(ctx, "j"); if (hostname == NULL) hostname = HOSTUNKNOWN; #if _FFR_FLUSH_HEADERS if (flushheaders) { for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { if ((dfc->mctx_signing && strcasecmp(hdr->hdr_hdr, DK_SIGNHEADER) == 0) || strcasecmp(hdr->hdr_hdr, AUTHRESULTSHDR) == 0) { if (smfi_chgheader(ctx, hdr->hdr_hdr, 0, NULL) != MI_SUCCESS) { if (dolog) { syslog(LOG_WARNING, "failed to remove %s: header", hdr->hdr_hdr); } } } } } #endif /* _FFR_FLUSH_HEADERS */ if (!dfc->mctx_headeronly) { /* ** Signal end-of-message to DomainKeys */ dkf = 0; status = dk_eom(dfc->mctx_dk, &dkf); switch (status) { case DK_STAT_OK: if (!dfc->mctx_signing && dkf_findheader(dfc, DK_SIGNHEADER, 0) != NULL) { dfc->mctx_addheader = TRUE; dfc->mctx_status = DKF_STATUS_GOOD; } break; case DK_STAT_BADSIG: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKF_STATUS_BAD; break; case DK_STAT_NOSIG: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKF_STATUS_NOSIGNATURE; break; case DK_STAT_NOKEY: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKF_STATUS_NOKEY; break; default: return dkf_libstatus(ctx, "dk_eom()", status); } #ifdef SMFIF_QUARANTINE /* quarantine for "bad" results if requested */ if (quarantine && (status == DK_STAT_BADSIG || (status == DK_STAT_NOSIG && dfc->mctx_addheader))) { char *failstatus; char qreason[BUFRSZ + 1]; failstatus = "bad signature"; if (status == DK_STAT_NOSIG) failstatus = "no signature"; snprintf(qreason, sizeof qreason, "%s: %s", progname, failstatus); if (smfi_quarantine(ctx, qreason) != MI_SUCCESS) { if (dolog) { syslog(LOG_ERR, "%s smfi_quarantine() failed", dfc->mctx_jobid); } } } #endif /* SMFIF_QUARANTINE */ /* compute and insert the signature, if we're signing */ if (dfc->mctx_signing) { int hcnt = 0; char *sel; sel = selector; if (dfc->mctx_key != NULL) sel = dfc->mctx_key->key_selector; memset(sig, '\0', sizeof sig); status = dk_getsig(dfc->mctx_dk, sig, sizeof sig); if (status != DK_STAT_OK) { return dkf_libstatus(ctx, "dk_getsig()", status); } memset(dfc->mctx_hlist, '\0', sizeof dfc->mctx_hlist); if (hdrlist) { sm_strlcpy(dfc->mctx_hlist, "h=", sizeof dfc->mctx_hlist); status = dk_gethdrs(dfc->mctx_dk, &hcnt, dfc->mctx_hlist + 2, sizeof dfc->mctx_hlist - 4); if (status != DK_STAT_OK) { return dkf_libstatus(ctx, "dk_gethdrs()", status); } if (sm_strlcat(dfc->mctx_hlist, ";\n\t", sizeof dfc->mctx_hlist) >= sizeof dfc->mctx_hlist) { if (dolog) { syslog(LOG_ERR, "%s header list too long", dfc->mctx_jobid); } dkf_cleanup(ctx); return SMFIS_TEMPFAIL; } if (hcnt == 0) { dfc->mctx_hlist[0] = '\0'; } else { dkf_splithdrs(dfc->mctx_hlist, sizeof(dfc->mctx_hlist)); } } memset(header, '\0', sizeof header); snprintf(header, sizeof header, "%sa=%s; s=%s; d=%s; c=%s; q=%s;\n\t%sb=", cc->cctx_noleadspc ? " " : "", dkf_signalg(dfc->mctx_signalg), sel == NULL ? DK_DEFAULT_SELECTOR : sel, dfc->mctx_domain, dkf_canonalg(dfc->mctx_canonalg), dkf_queryalg(dfc->mctx_queryalg), dfc->mctx_hlist); n = strlen(header); s = strlen(sig); w = 10; for (c = 0; c < s && n < sizeof header; c++) { header[n] = sig[c]; n++; w++; if (w >= HEADERMARGIN && (c < s - 1)) { sm_strlcat(header, "\n\t", sizeof header); n += 2; w = 8; } } if (smfi_insheader(ctx, 1, DK_SIGNHEADER, header) == MI_FAILURE) { if (dolog) { syslog(LOG_ERR, "%s smfi_insheader() failed", dfc->mctx_jobid); } } } } /* insert DomainKeys status */ if (dfc->mctx_addheader && dfc->mctx_status != DKF_STATUS_UNKNOWN) { char *authresult; char *comment = NULL; switch (dfc->mctx_status) { case DKF_STATUS_GOOD: authresult = "pass"; break; case DKF_STATUS_BAD: case DKF_STATUS_REVOKED: case DKF_STATUS_NOSIGNATURE: authresult = "fail"; if (dfc->mctx_status == DKF_STATUS_REVOKED) comment = "revoked"; else if (dfc->mctx_status == DKF_STATUS_NOSIGNATURE) comment = "no signature"; break; case DKF_STATUS_BADFORMAT: authresult = "permerror"; comment = "bad format"; break; default: authresult = "neutral"; break; } if (dfc->mctx_dk != NULL) { char hdr[MAXHEADER + 1]; char val[MAXADDRESS + 1]; sm_strlcpy(hdr, "unknown", sizeof hdr); sm_strlcpy(val, "unknown", sizeof val); (void) dk_getidentity(dfc->mctx_dk, hdr, sizeof hdr, val, sizeof val); snprintf(header, sizeof header, "%s%s; domainkeys=%s%s%s%s%s header.%s=%s", cc->cctx_noleadspc ? " " : "", hostname, authresult, comment == NULL ? "" : " (", comment == NULL ? "" : comment, comment == NULL ? "" : ")", !(dkf & DK_FLAG_TESTING) ? "" : " (testing)", hdr, val); } else { snprintf(header, sizeof header, "%s%s; domainkeys=%s%s%s%s%s", cc->cctx_noleadspc ? " " : "", hostname, authresult, comment == NULL ? "" : " (", comment == NULL ? "" : comment, comment == NULL ? "" : ")", !(dkf & DK_FLAG_TESTING) ? "" : " (testing)"); } if (smfi_insheader(ctx, 1, AUTHRESULTSHDR, header) == MI_FAILURE) { if (dolog) { syslog(LOG_ERR, "%s smfi_insheader() failed", dfc->mctx_jobid); } } if (dfc->mctx_status == DKF_STATUS_BAD && dfc->mctx_dk != NULL) dkf_report(dfc, authresult, comment); } /* ** Identify the filter, if requested. */ if (addxhdr) { char xfhdr[MAXHEADER + 1]; memset(xfhdr, '\0', sizeof xfhdr); snprintf(xfhdr, sizeof xfhdr, "%s%s v%s %s %s", cc->cctx_noleadspc ? " " : "", DKF_PRODUCT, DKF_VERSION, hostname, dfc->mctx_jobid != NULL ? dfc->mctx_jobid : JOBIDUNKNOWN); if (smfi_insheader(ctx, 1, XHEADERNAME, xfhdr) != MI_SUCCESS) { if (dolog) syslog(LOG_ERR, "smfi_insheader() failed"); dkf_cleanup(ctx); return SMFIS_TEMPFAIL; } } /* ** If we got this far, we're ready to complete. */ ret = SMFIS_ACCEPT; /* translate the stored status */ switch (dfc->mctx_status) { case DKF_STATUS_GOOD: break; case DKF_STATUS_BAD: ret = dkf_libstatus(ctx, "mlfi_eom()", DK_STAT_BADSIG); break; case DKF_STATUS_NOKEY: ret = dkf_libstatus(ctx, "mlfi_eom()", DK_STAT_NOKEY); break; case DKF_STATUS_REVOKED: ret = SMFIS_TEMPFAIL; break; case DKF_STATUS_NOSIGNATURE: ret = dkf_libstatus(ctx, "mlfi_eom()", DK_STAT_NOSIG); break; case DKF_STATUS_BADFORMAT: case DKF_STATUS_NONPART: ret = SMFIS_ACCEPT; break; case DKF_STATUS_UNKNOWN: break; default: if (status != DK_STAT_OK) ret = dkf_libstatus(ctx, "mlfi_eom()", status); break; } if ((dkf & DK_FLAG_TESTING) != 0) ret = SMFIS_ACCEPT; return ret; } /* ** MLFI_ABORT -- handler called if an earlier filter in the filter process ** rejects the message ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_abort(SMFICTX *ctx) { if (DK_DEBUG('t')) syslog(LOG_INFO, "thread %p abort", pthread_self()); dkf_cleanup(ctx); return SMFIS_CONTINUE; } /* ** MLFI_CLOSE -- handler called on connection shutdown ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_close(SMFICTX *ctx) { connctx cc; #ifndef DEBUG assert(ctx != NULL); #endif /* !DEBUG */ if (DK_DEBUG('t')) { pthread_mutex_lock(&count_lock); thread_count--; syslog(LOG_INFO, "thread %p close (%d)", pthread_self(), thread_count); pthread_mutex_unlock(&count_lock); } dkf_cleanup(ctx); cc = (connctx) smfi_getpriv(ctx); free(cc); smfi_setpriv(ctx, NULL); return SMFIS_CONTINUE; } #ifndef DEBUG /* ** smfilter -- the milter module description */ struct smfiDesc smfilter = { DKF_PRODUCT, /* filter name */ SMFI_VERSION, /* version code -- do not change */ (SMFIF_ADDHDRS | SMFIF_CHGHDRS | #ifdef SMFIF_QUARANTINE SMFIF_QUARANTINE | #endif /* SMFIF_QUARANTINE */ #ifdef SMFIF_SETSYMLIST SMFIF_SETSYMLIST | #endif /* SMFIF_SETSYMLIST */ 0), /* flags */ mlfi_connect, /* connection info filter */ NULL, /* SMTP HELO command filter */ mlfi_envfrom, /* envelope sender filter */ NULL, /* envelope recipient filter */ mlfi_header, /* header filter */ mlfi_eoh, /* end of header */ mlfi_body, /* body block filter */ mlfi_eom, /* end of message */ mlfi_abort, /* message aborted */ mlfi_close, /* shutdown */ #if SMFI_VERSION > 2 NULL, /* unrecognised command */ #endif #if SMFI_VERSION > 3 NULL, /* DATA */ #endif #if SMFI_VERSION >= 0x01000000 mlfi_negotiate /* negotiation callback */ #endif }; #endif /* !DEBUG */ #ifdef DEBUG int smfi_chgheader(void *ctx, char *hdr, int idx, char *val) { printf("smfi_chgheader(, `%s', `%d', `%s')\n", hdr, idx, val == NULL ? "(null)" : val); return MI_SUCCESS; } int smfi_replacebody(void *ctx, char *p, size_t len) { printf("smfi_replacebody(, `%.20s%s', `%d')\n", p, strlen(p) > 20 ? "..." : "", len); return MI_SUCCESS; } int smfi_addheader(void *ctx, char *hdr, char *val) { printf("smfi_addheader(, `%s', `%s')\n", hdr, val); return MI_SUCCESS; } int smfi_insheader(void *ctx, int idx, char *hdr, char *val) { printf("smfi_insheader(, %d, `%s', `%s')\n", idx, hdr, val); return MI_SUCCESS; } void smfi_setconn(char *file) { printf("smfi_setconn(`%s')\n", file); } void smfi_setpriv(void *ctx, void *priv) { fakepriv = priv; } void * smfi_getpriv(void *ctx) { return fakepriv; } void smfi_setreply(void *ctx, char *sc, char *esc, char *reply) { printf("smfi_setreply(, `%s', `%s', `%s')\n", sc, esc, reply); } char * smfi_getsymval(void *ctx, char *sym) { char *ret; size_t l; connctx cc; l = strlen(sym) + 6 + 1; cc = fakepriv; printf("smfi_getsymval(, `%s')\n", sym); ret = malloc(l); snprintf(ret, l, "DEBUG-%s", sym); return ret; } /* ** DKF_DEBUG -- debugging code; simulates libmilter calls ** ** Parameters: ** None. ** ** Return value: ** None. */ int dkf_debug(void) { bool done; int status; size_t len; time_t now; char *p; char *env[2]; char tmphdr[4096]; char data[513]; char block[4096]; struct sockaddr_in sin; time(&now); srandom(now); memset(data, '\0', sizeof data); memset(tmphdr, '\0', sizeof tmphdr); memset(&sin, '\0', sizeof sin); sin.sin_family = AF_INET; sin.sin_port = time(NULL) % 65536; sin.sin_addr.s_addr = inet_addr("127.0.0.1"); status = mlfi_connect(NULL, "localhost", (_SOCK_ADDR *) &sin); printf("mlfi_connect(NULL, `%s', ) returns %s\n", "localhost", smfis_ret[status]); for (;;) { if (fgets(data, 512, stdin) == NULL) return 1; for (p = data; *p != '\0'; p++) if (*p == '\r' || *p == '\n') { *p = '\0'; break; } if (strcmp(data, ".") == 0) break; env[0] = &data[1]; env[1] = NULL; if (data[0] == 'F') { status = mlfi_envfrom(NULL, env); printf("mlfi_envfrom(NULL, `%s') returns %s\n", env[0], smfis_ret[status]); } /* else if (data[0] == 'T') { status = mlfi_envrcpt(NULL, env); printf("mlfi_envrcpt(NULL, `%s') returns %s\n", env[0], smfis_ret[status]); } */ else { return 1; } if (status != SMFIS_CONTINUE) return 0; } for (;;) { memset(data, '\0', 513); if (fgets(data, 512, stdin) == NULL) return 1; for (p = data; *p != '\0'; p++) { if (*p == '\r' || *p == '\n') { *p = '\0'; break; } } if (strlen(data) > 0 && isascii(data[0]) && isspace(data[0])) { sm_strlcat(tmphdr, "\r\n", sizeof tmphdr); sm_strlcat(tmphdr, data, sizeof tmphdr); continue; } if (strlen(tmphdr) != 0) { char *q; p = strchr(tmphdr, ':'); *p = '\0'; for (q = p + 1; isspace(*q); q++) continue; status = mlfi_header(NULL, tmphdr, q); printf("mlfi_header(NULL, `%s', `%s') returns %s\n", tmphdr, q, smfis_ret[status]); if (status != SMFIS_CONTINUE) return 0; memset(tmphdr, '\0', sizeof tmphdr); } if (strlen(data) == 0) break; sm_strlcat(tmphdr, data, sizeof tmphdr); } status = mlfi_eoh(NULL); printf("mlfi_eoh(NULL) returns %s\n", smfis_ret[status]); if (status != SMFIS_CONTINUE) return 0; done = FALSE; while (!done) { len = fread(block, 1, 4096, stdin); status = mlfi_body(NULL, block, len); printf("mlfi_body(NULL, , %d) returns %s\n", len, smfis_ret[status]); if (status != SMFIS_CONTINUE) return 0; if (len < 4096) done = TRUE; } status = mlfi_eom(NULL); printf("mlfi_eom(NULL) returns %s\n", smfis_ret[status]); status = mlfi_close(NULL); printf("mlfi_close(NULL) returns %s\n", smfis_ret[status]); return 0; } #endif /* DEBUG */ /* ** USAGE -- print a usage message and return the appropriate exit status ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE. */ static int usage(void) { fprintf(stderr, "%s: usage: %s -p socketfile [options]\n" "-a peerlist \tfile containing list of hosts to ignore\n" "-A \tauto-restart\n" "-b modes \tselect operating modes\n" "-c canon \tcanonicalization to use when signing\n" "-C config \tconfiguration info (see man page)\n" "-d domlist \tdomains to sign\n" "-D \talso sign subdomains\n" "-f \tdon't fork-and-exit\n" #if _FFR_FLUSH_HEADERS "-F \tflush special headers before signing\n" #endif /* _FFR_FLUSH_HEADERS */ "-h \tappend identifying header\n" "-H \tsign with explicit header lists\n" "-i ilist \tfile containing list of internal (signing) hosts\n" "-I elist \tfile containing list of external domain clients\n" "-k \tload a key set instead of a single key\n" "-l \tlog activity to system log\n" "-m mtalist \tMTA daemon names for which to sign\n" "-M macrolist\tMTA macros which enable signing\n" "-o hdrlist \tlist of headers to omit from signing\n" "-P pidfile \tfile to which to write pid\n" #if _FFR_REQUIRED_HEADERS "-r \trequire basic RFC2822 header compliance\n" #endif /* _FFR_REQUIRED_HEADERS */ "-R \tgenerate verification failure reports\n" "-s keyfile \tlocation of secret key file\n" "-S selector \tselector to use when signing\n" "-u userid \tchange to specified userid\n" #if POPAUTH "-U dbfile \tuser POP AUTH database\n" #endif /* POPAUTH */ "-V \tprint version number and terminate\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Process command line arguments and call the milter mainline. */ int main(int argc, char **argv) { bool autorestart = FALSE; bool gotp = FALSE; bool dofork = TRUE; bool multikey = FALSE; int c; int status; #ifndef DEBUG int n; #endif /* ! DEBUG */ const char *args = CMDLINEOPTS; FILE *f; char *be = NULL; char *become = NULL; char *domlist = NULL; char *mtalist = NULL; char *p; char *pidfile = NULL; char *keyfile = NULL; char *confstr = NULL; char *peerfile = NULL; char *ilist = NULL; char *omitlist = NULL; #if POPAUTH char *popdbfile = NULL; #endif /* POPAUTH */ char *elist = NULL; char *canonstr = NULL; char *macrolist = NULL; unsigned char *s33krit = NULL; #ifndef DEBUG char *end; char argstr[MAXARGV]; #endif /* ! DEBUG */ /* initialize */ addxhdr = FALSE; dolog = FALSE; subdomains = FALSE; hdrlist = FALSE; dompats = NULL; omithdrs = NULL; #if POPAUTH popdb = NULL; #endif /* POPAUTH */ #if _FFR_FLUSH_HEADERS flushheaders = FALSE; #endif /* _FFR_FLUSH_HEADERS */ send_reports = FALSE; keyhead = NULL; keytail = NULL; no_i_whine = TRUE; selector = NULL; seckey = NULL; libdk = NULL; domains = NULL; mtas = NULL; macros = NULL; values = NULL; peerlist = NULL; internal = NULL; exignore = NULL; quarantine = FALSE; canon = DK_CANON_SIMPLE; tmo = DEFTIMEOUT; if (DK_DEBUG('t')) { thread_count = 0; pthread_mutex_init(&count_lock, NULL); } progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; /* process command line options */ while ((c = getopt(argc, argv, args)) != -1) { switch (c) { case 'a': if (optarg == NULL || *optarg == '\0') return usage(); peerfile = optarg; break; case 'A': autorestart = TRUE; break; case 'b': if (optarg == NULL || *optarg == '\0') return usage(); be = optarg; break; case 'c': if (optarg == NULL || *optarg == '\0') return usage(); canonstr = optarg; break; case 'C': if (optarg == NULL || *optarg == '\0') return usage(); confstr = optarg; break; case 'd': if (optarg == NULL || *optarg == '\0') return usage(); domlist = strdup(optarg); if (domlist == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); return EX_SOFTWARE; } break; case 'D': subdomains = TRUE; break; case 'f': dofork = FALSE; break; #if _FFR_FLUSH_HEADERS case 'F': flushheaders = TRUE; break; #endif /* _FFR_FLUSH_HEADERS */ case 'h': addxhdr = TRUE; break; case 'H': hdrlist = TRUE; break; case 'i': if (optarg == NULL || *optarg == '\0') return usage(); ilist = optarg; break; case 'I': if (optarg == NULL || *optarg == '\0') return usage(); elist = optarg; break; case 'k': multikey = TRUE; break; case 'l': #ifndef DEBUG dolog = TRUE; #endif /* !DEBUG */ break; case 'm': if (optarg == NULL || *optarg == '\0') return usage(); mtalist = optarg; break; case 'M': if (optarg == NULL || *optarg == '\0') return usage(); macrolist = optarg; break; case 'o': if (optarg == NULL || *optarg == '\0') return usage(); omitlist = optarg; break; case 'p': if (optarg == NULL || *optarg == '\0') return usage(); (void) smfi_setconn(optarg); gotp = TRUE; break; case 'P': if (optarg == NULL || *optarg == '\0') return usage(); pidfile = optarg; break; case 'q': quarantine = TRUE; break; #if _FFR_REQUIRED_HEADERS case 'r': req_hdrs = TRUE; break; #endif /* _FFR_REQUIRED_HEADERS */ case 'R': send_reports = TRUE; break; case 's': if (optarg == NULL || *optarg == '\0') return usage(); keyfile = optarg; break; case 'S': if (optarg == NULL || *optarg == '\0') return usage(); selector = optarg; break; case 'T': if (optarg == NULL || *optarg == '\0') return usage(); tmo = strtoul(optarg, &p, 10); if (*p != '\0') { fprintf(stderr, "%s: invalid value for -%c\n", progname, c); return EX_USAGE; } break; case 'u': if (optarg == NULL || *optarg == '\0') return usage(); become = optarg; break; #if POPAUTH case 'U': if (optarg == NULL || *optarg == '\0') return usage(); popdbfile = optarg; break; #endif /* POPAUTH */ case 'V': printf("%s: %s v%s\n", progname, DKF_PRODUCT, DKF_VERSION); dkf_optlist(stdout); return EX_OK; default: return usage(); } } if (optind != argc) return usage(); if (!dkf_parseconfig(confstr)) return EX_USAGE; if (!gotp) return usage(); if (be == NULL) { mode = DKF_MODE_DEFAULT; } else { mode = 0; for (p = be; *p != '\0'; p++) { switch (*p) { case 's': mode |= DKF_MODE_SIGNER; break; case 'v': mode |= DKF_MODE_VERIFIER; break; default: fprintf(stderr, "%s: unknown role flag '%c'\n", progname, *p); return EX_USAGE; } } } if (canonstr != NULL) { canon = dkf_configlookup(canonstr, dkf_canon); if (canon == -1) { fprintf(stderr, "%s: unknown canonicalization \"%s\"\n", progname, canonstr); return EX_USAGE; } } if (domlist != NULL) { int n; bool makepats = FALSE; if (domlist[0] == '/' && access(domlist, F_OK) == 0) { int nalloc = 0; FILE *f; char line[BUFRSZ + 1]; n = 0; f = fopen(domlist, "r"); if (f == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, domlist, strerror(errno)); return EX_UNAVAILABLE; } memset(line, '\0', sizeof line); while (fgets(line, BUFRSZ, f) != NULL) { for (p = line; *p != '\0'; p++) { if (*p == '\n' || *p == '#') { *p = '\0'; break; } } dkf_trimspaces(line); if (strlen(line) == 0) continue; if (nalloc <= n) { if (nalloc == 0) { domains = (char **) malloc(2 * sizeof(char *)); nalloc = 1; } else { domains = (char **) realloc(domains, (nalloc * 2 + 1) * sizeof(char *)); nalloc = nalloc * 2; } if (domains == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } } domains[n] = strdup(line); if (domains[n] == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } if (strchr(domains[n], '*') != NULL) makepats = TRUE; n++; } if (domains != NULL) domains[n] = NULL; fclose(f); } else { n = 1; for (p = domlist; *p != '\0'; p++) { if (*p == ',') n++; } domains = (char **) malloc((n + 1) * sizeof(char *)); if (domains == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } n = 0; for (p = strtok(domlist, ","); p != NULL; p = strtok(NULL, ",")) { domains[n] = p; if (strchr(domains[n], '*') != NULL) makepats = TRUE; n++; } domains[n] = NULL; } if (makepats) { char *end; char *q; char patbuf[BUFRSZ + 1]; dompats = (regex_t **) malloc ((n + 1) * sizeof (regex_t *)); if (dompats == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } memset(dompats, '\0', (n + 1) * sizeof (regex_t *)); for (c = 0; c < n; c++) { memset(patbuf, '\0', sizeof patbuf); end = patbuf + sizeof patbuf; patbuf[0] = '^'; for (p = domains[c], q = patbuf + 1; *p != '\0' && q < end; p++) { switch (*p) { case '*': *q = '.'; q++; *q = '*'; q++; break; case '.': *q = '\\'; q++; *q = '.'; q++; break; default: *q = *p; q++; break; } } *q++ = '$'; if (q >= end) { fprintf(stderr, "%s: regular expression for \"%s\" too large\n", progname, domains[c]); return EX_UNAVAILABLE; } dompats[c] = (regex_t *) malloc(sizeof(regex_t)); if (dompats[c] == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } status = regcomp(dompats[c], patbuf, (REG_EXTENDED|REG_ICASE)); if (status != 0) { (void) regerror(status, dompats[c], patbuf, sizeof patbuf); fprintf(stderr, "%s: regcomp(): %s\n", progname, patbuf); return EX_UNAVAILABLE; } } } } if (omitlist != NULL) { int n = 1; for (p = omitlist; *p != '\0'; p++) { if (*p == ',') n++; } omithdrs = (char **) malloc((n + 1) * sizeof(char *)); if (omithdrs == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } n = 0; for (p = strtok(omitlist, ","); p != NULL; p = strtok(NULL, ",")) omithdrs[n++] = p; omithdrs[n] = NULL; } if (macrolist != NULL) { int n = 1; char *macrocopy; for (p = macrolist; *p != '\0'; p++) { if (*p == ',') n++; } macros = (char **) malloc((n + 1) * sizeof(char *)); values = (char **) malloc((n + 1) * sizeof(char *)); macrocopy = strdup(macrolist); if (macros == NULL || values == NULL || macrocopy == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } n = 0; for (p = strtok(macrocopy, ","); p != NULL; p = strtok(NULL, ",")) { macros[n] = p; values[n] = strchr(p, '='); if (values[n] != NULL) { *(values[n]) = '\0'; values[n] += 1; } n++; } macros[n] = NULL; values[n] = NULL; } if (mtalist != NULL) { int n = 1; for (p = mtalist; *p != '\0'; p++) { if (*p == ',') n++; } mtas = (char **) malloc((n + 1) * sizeof(char *)); if (mtas == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } n = 0; for (p = strtok(mtalist, ","); p != NULL; p = strtok(NULL, ",")) mtas[n++] = p; mtas[n] = NULL; } /* peer list */ if (peerfile != NULL) { FILE *f; f = fopen(peerfile, "r"); if (f == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, peerfile, strerror(errno)); return EX_UNAVAILABLE; } if (!dkf_load_list(f, &peerlist)) { fclose(f); return EX_UNAVAILABLE; } fclose(f); } /* internal list */ if (ilist != NULL) { FILE *f; f = fopen(ilist, "r"); if (f == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, ilist, strerror(errno)); return EX_UNAVAILABLE; } if (!dkf_load_list(f, &internal)) { fclose(f); return EX_UNAVAILABLE; } fclose(f); } else { Peer newpeer; newpeer = (struct Peer *) malloc(sizeof(struct Peer)); if (newpeer == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } newpeer->peer_next = NULL; newpeer->peer_info = LOCALHOST; internal = newpeer; } /* external ignore list */ if (elist != NULL) { FILE *f; f = fopen(elist, "r"); if (f == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, elist, strerror(errno)); return EX_UNAVAILABLE; } if (!dkf_load_list(f, &exignore)) { fclose(f); return EX_UNAVAILABLE; } fclose(f); } /* activate logging */ if (dolog) { #ifdef LOG_MAIL openlog(progname, LOG_PID, LOG_MAIL); #else /* LOG_MAIL */ openlog(progname, LOG_PID); #endif /* LOG_MAIL */ } dkf_setmaxfd(); /* change user if appropriate */ if (become != NULL) { struct passwd *pw; pw = getpwnam(become); if (pw == NULL) { uid_t uid; uid = atoi(become); if (uid != 0 && uid != LONG_MIN && uid != LONG_MAX) pw = getpwuid(uid); if (pw == NULL) { if (dolog) { syslog(LOG_ERR, "no such user or uid `%s'", become); } fprintf(stderr, "%s: no such user `%s'\n", progname, become); return EX_DATAERR; } } (void) endpwent(); if (setgid(pw->pw_gid) != 0) { if (dolog) { syslog(LOG_ERR, "setgid(): %s", strerror(errno)); } fprintf(stderr, "%s: setgid(): %s\n", progname, strerror(errno)); return EX_NOPERM; } else if (setuid(pw->pw_uid) != 0) { if (dolog) { syslog(LOG_ERR, "setuid(): %s", strerror(errno)); } fprintf(stderr, "%s: setuid(): %s\n", progname, strerror(errno)); return EX_NOPERM; } } /* load the secret key, if one was specified */ if (keyfile != NULL && multikey) { status = dkf_loadkeys(keyfile); if (status != 0) return EX_UNAVAILABLE; } else if (keyfile != NULL) { int fd; size_t rlen; struct stat s; status = stat(keyfile, &s); if (status != 0) { if (dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "%s: stat(): %s", keyfile, strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: %s: stat(): %s\n", progname, keyfile, strerror(errno)); return EX_UNAVAILABLE; } s33krit = malloc(s.st_size + 1); if (s33krit == NULL) { if (dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "malloc(): %s", strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_UNAVAILABLE; } keylen = s.st_size + 1; fd = open(keyfile, O_RDONLY, 0); if (fd < 0) { if (dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "%s: open(): %s", keyfile, strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: %s: open(): %s\n", progname, keyfile, strerror(errno)); free(s33krit); return EX_UNAVAILABLE; } rlen = read(fd, s33krit, s.st_size + 1); if (rlen == -1) { if (dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "%s: read(): %s", keyfile, strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: %s: read(): %s\n", progname, keyfile, strerror(errno)); close(fd); free(s33krit); return EX_UNAVAILABLE; } else if (rlen != s.st_size) { if (dolog) { syslog(LOG_ERR, "%s: read() wrong size (%u)", keyfile, rlen); } fprintf(stderr, "%s: %s: read() wrong size (%u)\n", progname, keyfile, rlen); close(fd); free(s33krit); return EX_UNAVAILABLE; } close(fd); s33krit[s.st_size] = '\0'; seckey = s33krit; } die = FALSE; if (autorestart) { bool quitloop = FALSE; int status; pid_t pid; pid_t wpid; struct sigaction sa; if (dofork) { pid = fork(); switch (pid) { case -1: if (dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "fork(): %s", strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); dkf_zapkey(); return EX_OSERR; case 0: dkf_stdio(); break; default: dkf_zapkey(); return EX_OK; } } if (pidfile != NULL) { f = fopen(pidfile, "w"); if (f != NULL) { fprintf(f, "%ld\n", (long) getpid()); (void) fclose(f); } else { if (dolog) { syslog(LOG_ERR, "can't write pid to %s: %s", pidfile, strerror(errno)); } } } sa.sa_handler = dkf_sighandler; /* XXX -- HAHAHAH => sa.sa_sigaction = NULL; */ sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGTERM); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) != 0 || sigaction(SIGINT, &sa, NULL) != 0 || sigaction(SIGTERM, &sa, NULL) != 0) { if (dolog) { syslog(LOG_ERR, "[parent] sigaction(): %s", strerror(errno)); } } while (!quitloop) { pid = fork(); switch (pid) { case -1: if (dolog) { syslog(LOG_ERR, "fork(): %s", strerror(errno)); } dkf_zapkey(); return EX_OSERR; case 0: sa.sa_handler = SIG_DFL; if (sigaction(SIGHUP, &sa, NULL) != 0 || sigaction(SIGINT, &sa, NULL) != 0 || sigaction(SIGTERM, &sa, NULL) != 0) { if (dolog) { syslog(LOG_ERR, "[child] sigaction(): %s", strerror(errno)); } } quitloop = TRUE; break; default: for (;;) { wpid = wait(&status); if (wpid == -1 && errno == EINTR) { if (die) { dkf_killchild(pid, diesig); dkf_zapkey(); exit(EX_OK); } } if (pid != wpid) continue; if (wpid != -1 && dolog) { if (WIFSIGNALED(status)) { syslog(LOG_NOTICE, "terminated with signal %d, restarting", WTERMSIG(status)); } else if (WIFEXITED(status)) { syslog(LOG_NOTICE, "exited with status %d, restarting", WEXITSTATUS(status)); } } break; } break; } } } #ifndef DEBUG /* register with the milter interface */ if (smfi_register(smfilter) == MI_FAILURE) { if (dolog) syslog(LOG_ERR, "smfi_register() failed"); fprintf(stderr, "%s: smfi_register() failed\n", progname); dkf_zapkey(); return EX_UNAVAILABLE; } /* try to establish the milter socket */ if (smfi_opensocket(FALSE) == MI_FAILURE) { if (dolog) syslog(LOG_ERR, "smfi_opensocket() failed"); fprintf(stderr, "%s: smfi_opensocket() failed\n", progname); dkf_zapkey(); return EX_UNAVAILABLE; } #endif /* !DEBUG */ if (!autorestart && dofork) { pid_t pid; pid = fork(); switch(pid) { case -1: if (dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "fork(): %s", strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); dkf_zapkey(); return EX_OSERR; case 0: dkf_stdio(); break; default: dkf_zapkey(); return EX_OK; } } /* write out the pid */ if (!autorestart && pidfile != NULL) { f = fopen(pidfile, "w"); if (f != NULL) { fprintf(f, "%ld\n", (long) getpid()); (void) fclose(f); } else { if (dolog) { syslog(LOG_ERR, "can't write pid to %s: %s", pidfile, strerror(errno)); } } } ERR_load_crypto_strings(); /* initialize the DomainKeys package */ libdk = dk_init(NULL, NULL); if (libdk == NULL) { if (dolog) syslog(LOG_ERR, "can't initialize DomainKeys library"); dkf_zapkey(); return EX_UNAVAILABLE; } if (hdrlist) { int opts; opts = DK_LIBFLAGS_HDRLIST; (void) dk_options(libdk, DK_OP_SETOPT, DK_OPTS_FLAGS, &opts, sizeof opts); } if (send_reports) { int opts; (void) dk_options(libdk, DK_OP_GETOPT, DK_OPTS_FLAGS, &opts, sizeof opts); opts |= DK_LIBFLAGS_TMPFILES; (void) dk_options(libdk, DK_OP_SETOPT, DK_OPTS_FLAGS, &opts, sizeof opts); } pthread_mutex_init(&popen_lock, NULL); #ifdef DEBUG return dkf_debug(); #else /* DEBUG */ memset(argstr, '\0', sizeof argstr); end = &argstr[sizeof argstr - 1]; n = sizeof argstr; for (c = 1, p = argstr; c < argc && p < end; c++) { if (strchr(argv[c], ' ') != NULL) { status = snprintf(p, n, "%s \"%s\"", c == 1 ? "args:" : "", argv[c]); } else { status = snprintf(p, n, "%s %s", c == 1 ? "args:" : "", argv[c]); } p += status; n -= status; } #if POPAUTH if (popdbfile != NULL) { status = dkf_initpopauth(); if (status != 0) { fprintf(stderr, "%s: can't initialize mutex: %s\n", progname, strerror(status)); syslog(LOG_ERR, "can't initialize mutex: %s", popdbfile); } status = 0; # if DB_VERSION_MAJOR > 2 status = db_create(&popdb, NULL, 0); if (status == 0) { # if DB_VERSION_MAJOR > 3 status = popdb->open(popdb, NULL, popdbfile, NULL, DB_UNKNOWN, (DB_RDONLY|DB_THREAD), 0); # else /* DB_VERSION_MAJOR > 3 */ status = popdb->open(popdb, popdbfile, NULL, DB_UNKNOWN, (DB_RDONLY|DB_THREAD), 0); # endif /* DB_VERSION_MAJOR > 3 */ } # elif DB_VERSION_MAJOR == 2 status = db_open(popdbfile, DB_HASH, DB_RDONLY, DB_MODE, NULL, NULL, &popdb); # else /* DB_VERSION_MAJOR < 2 */ popdb = dbopen(dbfile, O_RDONLY, DB_HASH, NULL); if (popdb == NULL) status = errno; # endif /* DB_VERSION_MAJOR */ if (status != 0) { fprintf(stderr, "%s: can't open database %s\n", progname, db_strerror(errno)); syslog(LOG_ERR, "can't open database %s", popdbfile); dkf_zapkey(); return EX_UNAVAILABLE; } } #endif /* POPAUTH */ if (dolog) { syslog(LOG_INFO, "%s v%s starting (%s)", DKF_PRODUCT, DKF_VERSION, argstr); } /* call the milter mainline */ errno = 0; status = smfi_main(); if (dolog) { syslog(LOG_INFO, "%s v%s terminating with status %d, errno = %d", DKF_PRODUCT, DKF_VERSION, status, errno); } #if POPAUTH if (popdb != NULL) { # if DB_VERSION_MAJOR < 2 (void) popdb->close(popdb); # else /* DB_VERSION_MAJOR < 2 */ (void) popdb->close(popdb, 0); # endif /* DB_VERSION_MAJOR */ } #endif /* POPAUTH */ dkf_zapkey(); dk_close(libdk); return status; #endif /* DEBUG */ } dk-milter-1.0.0.dfsg/dk-filter/util.c0000644000175000017500000003066410765762755017123 0ustar madhackmadhack/* ** Copyright (c) 2004, 2005, 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: util.c,v 1.48 2008/03/12 14:17:17 msk Exp $ */ #ifndef lint static char util_c_id[] = "@(#)$Id: util.c,v 1.48 2008/03/12 14:17:17 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* libsm includes */ #include #include #if POPAUTH /* system includes */ # include /* libdb includes */ # include #endif /* POPAUTH */ /* dk-filter includes */ #include "dk-filter.h" #include "util.h" /* globals */ #if POPAUTH static pthread_mutex_t pop_lock; #endif /* POPAUTH */ static char *optlist[] = { #if POPAUTH "POPAUTH", #endif /* POPAUTH */ #if _FFR_ANTICIPATE_SENDMAIL_MUNGE "_FFR_ANTICIPATE_SENDMAIL_MUNGE", #endif /* _FFR_ANTICIPATE_SENDMAIL_MUNGE */ #if _FFR_FLUSH_HEADERS "_FFR_FLUSH_HEADERS", #endif /* _FFR_FLUSH_HEADERS */ #if _FFR_REQUIRED_HEADERS "_FFR_REQUIRED_HEADERS", #endif /* _FFR_REQUIRED_HEADERS */ #if _FFR_SELECT_CANONICALIZATION "_FFR_SELECT_CANONICALIZATION", #endif /* _FFR_SELECT_CANONICALIZATION */ NULL }; /* ** DKF_OPTLIST -- print active options ** ** Parameters: ** where -- where to write the list ** ** Return value: ** None. */ void dkf_optlist(FILE *where) { bool first = TRUE; int c; assert(where != NULL); for (c = 0; optlist[c] != NULL; c++) { if (first) { fprintf(where, "Active code options:\n"); first = FALSE; } fprintf(where, "\t%s\n", optlist[c]); } } /* ** DKF_SETMAXFD -- increase the file descriptor limit as much as possible ** ** Parameters: ** None. ** ** Return value: ** None. */ void dkf_setmaxfd(void) { struct rlimit rlp; if (getrlimit(RLIMIT_NOFILE, &rlp) != 0) { syslog(LOG_WARNING, "getrlimit(): %s", strerror(errno)); } else { rlp.rlim_cur = rlp.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rlp) != 0) { syslog(LOG_WARNING, "setrlimit(): %s", strerror(errno)); } } } /* ** DKF_STRIPBRACKETS -- remove angle brackets from the sender address ** ** Parameters: ** addr -- address to be processed ** ** Return value: ** None. */ void dkf_stripbrackets(char *addr) { char *p, *q; assert(addr != NULL); p = addr; q = addr + strlen(addr) - 1; while (*p == '<' && *q == '>') { p++; *q-- = '\0'; } if (p != addr) { for (q = addr; *p != '\0'; p++, q++) *q = *p; *q = '\0'; } } /* ** DKF_LOWERCASE -- lowercase-ize a string ** ** Parameters: ** str -- string to convert ** ** Return value: ** None. */ void dkf_lowercase(char *str) { char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (isascii(*p) && isupper(*p)) *p = tolower(*p); } } /* ** DKF_LIST_LOOKUP -- look up a name in a peerlist ** ** Parameters: ** list -- list of records to check ** data -- record to find ** ** Return value: ** TRUE if found, FALSE otherwise */ static bool dkf_list_lookup(Peer list, char *data) { Peer current; assert(data != NULL); for (current = list; current != NULL; current = current->peer_next) { if (strcasecmp(data, current->peer_info) == 0) return TRUE; } return FALSE; } /* ** DKF_CHECKHOST -- check the peerlist for a host and its wildcards ** ** Parameters: ** list -- list of records to check ** host -- hostname to find ** ** Return value: ** TRUE if there's a match, FALSE otherwise. */ bool dkf_checkhost(Peer list, char *host) { char *p; assert(host != NULL); /* short circuit */ if (list == NULL) return FALSE; if (dkf_list_lookup(list, host)) return TRUE; for (p = strchr(host, '.'); p != NULL; p = strchr(p + 1, '.')) { if (dkf_list_lookup(list, p)) return TRUE; } return FALSE; } /* ** DKF_CHECKIP -- check a peerlist table for an IP address or its matching ** wildcards ** ** Parameters: ** list -- list to check ** ip -- IP address to find ** ** Return value: ** TRUE if there's a match, FALSE otherwise. */ bool dkf_checkip(Peer list, struct sockaddr *ip) { int c; char tmpbuf[MAXHOSTNAMELEN + 1]; char ipbuf[MAXHOSTNAMELEN + 1]; struct in_addr addr; struct in_addr mask; assert(ip != NULL); /* short circuit */ if (list == NULL) return FALSE; #if NETINET6 if (ip->sa_family == AF_INET6) { struct in6_addr addr; memcpy(&addr, &((struct sockaddr_in6 *)ip)->sin6_addr, sizeof addr); if (IN6_IS_ADDR_V4MAPPED(&addr)) { inet_ntop(AF_INET, &addr.s6_addr[INET6_ADDRSTRLEN - INET_ADDRSTRLEN], tmpbuf, sizeof tmpbuf); } else { char *d; char *dst; size_t sz; size_t dst_len; dst = tmpbuf; d = dst; dst_len = sizeof tmpbuf; memset(tmpbuf, '\0', sizeof tmpbuf); sz = sm_strlcpy(tmpbuf, "IPv6:", sizeof tmpbuf); if (sz >= sizeof tmpbuf) return FALSE; dst += sz; dst_len -= sz; inet_ntop(AF_INET6, &addr, dst, dst_len); } return (dkf_list_lookup(list, tmpbuf)); } #endif /* NETINET6 */ memcpy(&addr.s_addr, &((struct sockaddr_in *)ip)->sin_addr, sizeof(addr.s_addr)); /* test the IP by itself */ (void) dkf_inet_ntoa(addr, ipbuf, sizeof ipbuf); if (dkf_list_lookup(list, ipbuf)) return TRUE; /* test the IP/32 */ sm_strlcat(ipbuf, "/32", sizeof ipbuf); if (dkf_list_lookup(list, ipbuf)) return TRUE; /* ** Prepare to cycle through the other IP/bits possibilities. ** Turn on all the possible network bits in our bitmask. */ mask.s_addr = 0; for (c = 0; c < 32; c++) mask.s_addr |= htonl(1 << (31 - c)); /* decompose the address bit-by-bit and try the appropriate entry */ for (c = 0; c < 32; c++) { mask.s_addr ^= htonl(1 << c); addr.s_addr = (addr.s_addr & mask.s_addr); dkf_inet_ntoa(addr, tmpbuf, sizeof tmpbuf); snprintf(ipbuf, sizeof ipbuf, "%s/%d", tmpbuf, 31 - c); if (dkf_list_lookup(list, ipbuf)) return TRUE; } return FALSE; } #if POPAUTH /* ** DKF_INITPOPAUTH -- initialize POPAUTH stuff ** ** Parameters: ** None. ** ** Return value: ** 0 on success, an error code on failure. See pthread_mutex_init(). */ int dkf_initpopauth(void) { return pthread_mutex_init(&pop_lock, NULL); } /* ** DKF_CHECKPOPAUTH -- check a POP before SMTP database for client ** authentication ** ** Parameters: ** db -- DB handle to use for searching ** ip -- IP address to find ** ** Return value: ** TRUE iff the database could be opened and the client was verified. ** ** Notes: ** - should be a shared handle rather than a per-thread handle to ** reduce descriptor consumption ** - needs locking ** - should be able to return TRUE/FALSE as well as errors ** - path should be runtime-configurable rather than hard-coded ** - does the key contain anything meaningful, like an expiry time? */ bool dkf_checkpopauth(DB *db, struct sockaddr *ip) { bool ret = FALSE; int status; int fd; struct sockaddr_in *sin; struct in_addr addr; DBT d; DBT q; char ipbuf[MAXHOSTNAMELEN + 1]; assert(ip != NULL); if (db == NULL) return FALSE; /* skip anything not IPv4 (for now) */ if (ip->sa_family != AF_INET) return FALSE; else sin = (struct sockaddr_in *) ip; memset(&d, 0, sizeof d); memset(&q, 0, sizeof q); /* we don't care what the value is for now */ d.flags = DB_DBT_USERMEM|DB_DBT_PARTIAL; memcpy(&addr.s_addr, &sin->sin_addr, sizeof addr.s_addr); dkf_inet_ntoa(addr, ipbuf, sizeof ipbuf); q.data = ipbuf; q.size = strlen(q.data); /* establish read-lock */ fd = -1; # if DB_VERSION_MAJOR >= 2 status = -1; status = db->fd(db, &fd); # else /* DB_VERSION_MAJOR >= 2 */ status = 0; fd = db->fd(db); # endif /* DB_VERSION_MAJOR >= 2 */ /* XXX -- allow multiple readers? */ (void) pthread_mutex_lock(&pop_lock); if (status == 0 && fd != -1) { # ifdef LOCK_SH status = flock(fd, LOCK_SH); if (status != 0 && dolog) { syslog(LOG_WARNING, "flock(LOCK_SH): %s", strerror(errno)); } # else /* LOCK_SH */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_RDLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0 && dolog) { syslog(LOG_WARNING, "fcntl(F_RDLCK): %s", strerror(errno)); } # endif /* LOCK_SH */ } # if DB_VERSION_MAJOR < 2 status = db->get(db, &q, &d, 0); # else /* DB_VERSION_MAJOR < 2 */ status = db->get(db, NULL, &q, &d, 0); # endif /* DB_VERSION_MAJOR */ if (status == 0) { ret = TRUE; } else if (status != DB_NOTFOUND && dolog) { syslog(LOG_ERR, "db->get(): %s", db_strerror(status)); } /* surrender read-lock */ if (fd != -1) { # ifdef LOCK_SH status = flock(fd, LOCK_UN); if (status != 0 && dolog) { syslog(LOG_WARNING, "flock(LOCK_UN): %s", strerror(errno)); } # else /* LOCK_SH */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_UNLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0 && dolog) { syslog(LOG_WARNING, "fcntl(F_UNLCK): %s", strerror(errno)); } # endif /* LOCK_SH */ } (void) pthread_mutex_unlock(&pop_lock); return ret; } #endif /* POPAUTH */ /* ** DKF_LOAD_LIST -- load a list of hosts/CIDR blocks into memory ** ** Parameters: ** in -- input stream (must already be open) ** list -- list to be updated ** ** Return value: ** TRUE if successful, FALSE otherwise ** ** Side effects: ** Prints an error message when appropriate. */ bool dkf_load_list(FILE *in, struct Peer **list) { char *p; struct Peer *newpeer; char peer[BUFRSZ + 1]; assert(in != NULL); assert(list != NULL); memset(peer, '\0', sizeof peer); while (fgets(peer, sizeof(peer) - 1, in) != NULL) { for (p = peer; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; break; } } newpeer = (struct Peer *) malloc(sizeof(struct Peer)); if (newpeer == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return FALSE; } newpeer->peer_next = *list; *list = newpeer; newpeer->peer_info = strdup(peer); if (newpeer->peer_info == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); return FALSE; } } return TRUE; } /* ** DKF_INET_NTOA -- thread-safe inet_ntoa() ** ** Parameters: ** a -- (struct in_addr) to be converted ** buf -- destination buffer ** buflen -- number of bytes at buf ** ** Return value: ** Size of the resultant string. If the result is greater than buflen, ** then buf does not contain the complete result. */ size_t dkf_inet_ntoa(struct in_addr a, char *buf, size_t buflen) { uint32_t addr; assert(buf != NULL); addr = ntohl(a.s_addr); return snprintf(buf, buflen, "%u.%u.%u.%u", (addr >> 24), (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); } /* ** DKF_SPLITHDRS -- split up a "h=" stanza to look pretty ** ** Parameters: ** buf -- input string ** buflen -- number of bytes at "buf" ** ** Return value: ** None. */ void dkf_splithdrs(char *buf, size_t buflen) { bool first = TRUE; size_t len = 0; char *last; char *start; char *p; char tmp[MAXHEADERS]; assert(buf != NULL); memset(tmp, '\0', sizeof tmp); len = 8; last = NULL; start = buf; for (p = buf; *p != '\0'; p++) { switch (*p) { case ':': if (len + (size_t) (p - start) > MAXHDRLEN) { sm_strlcat(tmp, ":\n\t", sizeof tmp); len = 8; } else if (!first) { sm_strlcat(tmp, ":", sizeof tmp); len++; } first = FALSE; *p = '\0'; sm_strlcat(tmp, start, sizeof tmp); *p = ':'; start = NULL; break; case '=': *p = '\0'; sm_strlcat(tmp, start, sizeof tmp); *p = '='; sm_strlcat(tmp, "=", sizeof tmp); start = NULL; len++; break; default: if (start == NULL) start = p; len++; break; } } if (start != NULL) { if (!first) sm_strlcat(tmp, ":", sizeof tmp); sm_strlcat(tmp, start, sizeof tmp); } sm_strlcpy(buf, tmp, buflen); } /* ** DKF_TRIMSPACES -- trim trailing whitespace ** ** Parameters: ** str -- string to modify ** ** Return value: ** None. */ void dkf_trimspaces(char *str) { char *p; char *last; assert(str != NULL); last = NULL; for (p = str; *p != '\0'; p++) { if (isascii(*p) && isspace(*p) && last == NULL) { last = p; continue; } if (!isascii(*p) || !isspace(*p)) last = NULL; } if (last != NULL) *last = '\0'; } dk-milter-1.0.0.dfsg/dk-filter/util.h0000644000175000017500000000211710606024254017073 0ustar madhackmadhack/* ** Copyright (c) 2004, 2005, 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: util.h,v 1.19 2007/04/07 23:26:36 msk Exp $ */ #ifndef _UTIL_H_ #define _UTIL_H_ /* system includes */ #include #include #include /* libsm includes */ #include /* dk-filter includes */ #include "dk-filter.h" #ifndef lint static char util_h_id[] = "@(#)$Id: util.h,v 1.19 2007/04/07 23:26:36 msk Exp $"; #endif /* !lint */ /* PROTOTYPES */ extern bool dkf_checkhost(Peer list, char *host); extern bool dkf_checkip(Peer list, struct sockaddr *ip); #if POPAUTH extern bool dkf_checkpopauth(DB *db, struct sockaddr *ip); #endif /* POPAUTH */ extern size_t dkf_inet_ntoa(struct in_addr a, char *buf, size_t buflen); extern bool dkf_load_list(FILE *in, struct Peer **list); extern void dkf_lowercase(char *str); extern void dkf_optlist(FILE *where); extern void dkf_setmaxfd(void); extern void dkf_splithdrs(char *buf, size_t buflen); extern void dkf_stripbrackets(char *addr); extern void dkf_trimspaces(char *str); #endif /* _UTIL_H_ */ dk-milter-1.0.0.dfsg/dk-filter/gentxt.csh0000755000175000017500000000257610763561132017776 0ustar madhackmadhack#!/bin/csh -f ## ## $Id: gentxt.csh,v 1.6 2008/03/05 18:11:38 msk Exp $ ## ## Copyright (c) 2004-2006, 2008 Sendmail, Inc. and its suppliers. ## All rights reserved. ## ## gentxt.csh -- generate a TXT record for DomainKeys service ## ## Usage: gentext.csh [] ## ## This will write a TXT record suitable for insertion into a DNS zone file ## on standard output, and the matching public/private keys will be in ## PEM-formatted files called .public and .private, ## respectively, in the current directory. ## ## To translate the record produced by this script, see the DomainKeys ## draft. The script will output a record which advertises an RSA-style ## public key in test mode. # verify usage if ("$3" != "" || "$1" == "") then echo "usage: $0 selector [domain]" exit 1 endif # copy the argument set selector="$1" set domain="$2" # generate a private key openssl genrsa -out ${selector}.private 512 >& /dev/null # generate a public key based on the private key openssl rsa -in ${selector}.private -out ${selector}.public -pubout \ -outform PEM >& /dev/null # prepare the data set keydata = `grep -v '^-' ${selector}.public` set pubkey = `echo $keydata | sed 's/ //g'` # output the record echo -n ${selector}._domainkey IN TXT '"'k=rsa\; t=y\; p=$pubkey'"' if ("$domain" != "") then echo " ; ----- DomainKey $selector for $domain" else echo "" endif dk-milter-1.0.0.dfsg/dk-filter/autorespond.csh0000755000175000017500000000177110101125061021003 0ustar madhackmadhack#!/bin/csh -f ## ## $Id: autorespond.csh,v 1.2 2004/07/26 06:52:33 msk Exp $ ## ## Copyright (c) 2004 Sendmail, Inc. and its suppliers. ## All rights reserved. ## ## autorespond.csh -- accept a message and reply to it to test signing and ## verifying of dk-filter ## Setup set infile=/var/tmp/ari.$$ set tmpfile=/var/tmp/aro.$$ set hostname=`hostname` ## Capture the incoming message cat > $infile ## Build the reply echo From: autorespond@$hostname >> $tmpfile grep '^From:' < $infile | sed 's/^From/To/g' >> $tmpfile ## Enable the next line to allow remote canonicalization selection: # grep '^X-Canonicalization:' < $infile >> $tmpfile echo Subject: Auto-response from $hostname >> $tmpfile echo "" >> $tmpfile echo "Original message:" >> $tmpfile echo "" >> $tmpfile cat $infile >> $tmpfile echo "" >> $tmpfile echo "And some random data:" >> $tmpfile echo "" >> $tmpfile dd if=/dev/urandom count=10 | base64 -e >> $tmpfile ## Send the reply sendmail -t < $tmpfile ## Clean up rm -f $tmpfile $infile exit 0 dk-milter-1.0.0.dfsg/dk-filter/Build0000755000175000017500000000052210020711074016721 0ustar madhackmadhack#!/bin/sh # Copyright (c) 2000 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: Build,v 1.1 2004/03/01 19:42:52 msk Exp $ exec sh ../devtools/bin/Build $* dk-milter-1.0.0.dfsg/dk-filter/Makefile0000644000175000017500000000056610023220401017374 0ustar madhackmadhack# $Id: Makefile,v 1.2 2004/03/09 01:42:25 msk Exp $ SHELL= /bin/sh BUILD= ./Build OPTIONS= $(CONFIG) $(FLAGS) all: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ clean: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ install: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ fresh: FRC $(SHELL) $(BUILD) $(OPTIONS) -c FRC: (cd $(BUILD_ROOT)/pkgs/openssl; $(SHELL) Build -v $(BUILD_VARIANT); ) dk-milter-1.0.0.dfsg/devtools/0000755000175000017500000000000010766324730015733 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/README0000644000175000017500000003776110754345745016637 0ustar madhackmadhackThis directory contains tools. Do not attempt to actually build anything in this directory. The Build script allows you to specify a base location for the object files by using the -O flag: ./Build -O /tmp will put the object files in /tmp/obj.*/. Also, if the SENDMAIL_SUFFIX environment variable is set, its value will be used in the obj.* directory name. The Build script allows you to specify a site configuration file by using the -f flag: ./Build -f siteconfig.m4 You can put such site configuration files in the Site sub-directory; see Site/README for details. If you need to support multiple build configurations from the same tree, you can use prefixes to differentiate your configurations. Use the -Q flag to Build: ./Build -Q prefix Build will select a prefix.*.m4 file instead of the site.*.m4 file according to the conventions in Site/README, and use it to modify the build configuration. The object directory used will be obj.prefix.*/. Your prefix.*.m4 files should reside in the Site directory. You may not use -Q and -f simultaneously. While building a site configuration file, beyond using define() to set variables, you can also add to a definition using the APPENDDEF() and PREPENDDEF() macros. For example: APPENDDEF(`confINCDIRS', `-I/usr/local/bind/include') will add -I/usr/local/bind/include to the already existing confINCDIRS. Note: There must be no trailing spaces after the last quote mark and before the closing parenthesis. Also you may need to properly quote m4 reserved words as specified by your vendor's m4 command. By default, sendmail will search your system for include and library directories as well as certain libraries (libdb.* for Berkeley DB and libbind.a or libresolv.* for name resolution). You can turn off this configuration step by specifying the -S flag with the Build command. The OS subtree contains definitions for variations on a standard model for system installation. The M4 variables that can be defined and their defaults before referencing the appropriate OS definitions are listed below. Note that variables preceded by an asterisk (*) are currently not used in the open source distribution. confBEFORE [empty] Files to create before sendmail is compiled. The methods must be defined in the Makefile using PUSHDIVERT(3). confBLDVARIANT OPTIMIZED This controls which object variant will be built and is controlled with the -v flag to the Build script. Internally, this macro is used to select compiler options in the devtools/OS/*.m4 files. Valid arguments for the Build -v flag are "optimized", "debug", and "purify" which map to confBLDVARIANT values of "OPTIMIZED", "DEBUG", and "PURIFY". This is a work in progress, and as such not all devtools/OS/*.m4 have been updated yet. (See Linux for an example of one that has.) Also, in the future it may be desirable to append a variant identifier to the object directory name to allow different variants to independently co-exist on a given target platform. Note: the PURIFY variant has not been fully implemented on any platforms yet. Other variants can be added as needed in the future. Changing this macro from its default will affect other default values. confBUILDBIN ../../devtools/bin The location of the build support binaries, relative to the obj.* directory. confCC cc The C compiler to use. confCCOPTS [empty] Additional options to pass to confCC. *confCCOPTS_SO -fPIC Additional options for compiling shared object libraries. confCCLINK confCC Linker to use (for executables). confCOPY cp A program that copies files. confMKDIR [empty] A program that creates directories (mkdir) and takes the -p parameter to create also intermediate directories as required. If this macro is set, then it used by "make install" to create the required installation directories. confDEPEND_TYPE generic How to build dependencies. This should be the name of a file in devtools/M4/depend confDEPLIBS [empty] Dependent libraries when building shared objects. confDONT_INSTALL_CATMAN [undefined] Don't install the formatted manual pages. confEBINDIR /usr/libexec The location for binaries executed from other binaries, e.g., mail.local or smrsh. confENVDEF [empty] -D flags passed to C compiler. confFORCE_RMAIL [undefined] If defined, install the rmail program without question. confGBINGRP smmsp The group for set-group-ID binaries. confGBINMODE 2555 The mode for set-group-ID binaries. confGBINOWN root The owner for set-group-ID binaries. confMSPQOWN smmsp The owner of the MSP queue. confMSP_QUEUE_DIR /var/spool/clientmqueue The MSP queue directory. confMSP_STFILE sm-client.st Name of the MSP statistics file. confHFDIR /etc/mail Location of the sendmail helpfile. confHFFILE helpfile Name of the installed helpfile. confINCDIRS [empty] -I flags passed to C compiler. confINCGRP bin The group for include files. confINCMODE 444 The mode of installed include files. confINCOWN root The owner for include files. confINCLUDEDIR /usr/include Where to install include files. confINSTALL install The BSD-compatible install program. Use ${BUILDBIN}/install.sh if none is available on your system. confINSTALL_RAWMAN [undefined] Install the unformatted manual pages. *confLD confCC Linker to use (for libraries). confLDOPTS [empty] Linker options. *confLDOPTS_SO -shared -Wl Additional linker options for linking shared object libraries. confLIBDIR /usr/lib Where to install library files. confLIBDIRS [empty] -L flags passed to ld. confLIBGRP bin The group for libraries. confLIBMODE 444 The mode of installed libraries. confLIBOWN root The owner for libraries. confLIBS [varies] -l flags passed to ld. confLIBSEARCH db bind resolv 44bsd Search for these libraries for linking with programs. confLIBSEARCHPATH /lib /usr/lib /usr/shlib Locations to search for the libraries specified by confLIBSEARCH. confLINKS ${UBINDIR}/newaliases ${UBINDIR}/mailq \ ${UBINDIR}/hoststat ${UBINDIR}/purgestat Names of links to sendmail. confLN ln The command used to create links. confLNOPTS -f -s The parameters for confLN. confMAN1 confMANROOT 1 The location of man1 files. confMAN1EXT 1 The extension on files in confMAN1. confMAN1SRC 0 The source for man pages installed in confMAN1. confMAN3 confMANROOT 3 The location of man3 files. confMAN3EXT 3 The extension on files in confMAN3. confMAN3SRC 0 The source for man pages installed in confMAN3. confMAN4 confMANROOT 4 The location of man4 files. confMAN4EXT 4 The extension on files in confMAN4. confMAN4SRC 0 The source for man pages installed in confMAN4. confMAN5 confMANROOT 5 The location of man5 files. confMAN5EXT 5 The extension on files in confMAN5. confMAN5SRC 0 The source for man pages installed in confMAN5. confMAN8 confMANROOT 8 The location of man8 files. confMAN8EXT 8 The extension on files in confMAN8. confMAN8SRC 0 The source for man pages installed in confMAN8. confMANDOC -man The macros used to format man pages. confMANGRP bin The group of installed man pages. confMANMODE 444 The mode of installed man pages. confMANOWN bin The owner of installed man pages. confMANROOT /usr/share/man/cat The root of the man subtree. confMANROOTMAN /usr/share/man/man The root of the man subtree, for unformatted manual pages. confMAPDEF [varies] The map definitions, e.g., -DNDBM -DNEWDB. -DNEWDB is always added if libdb.* can be found. confMBINDIR /usr/sbin The location of the MTA (sm-mta, sendmail) binary. confMBINGRP bin The group of the MTA binary (sm-mta). confMBINMODE 550 The mode of the MTA binary (sm-mta). confMBINOWN root The owner of the MTA binary (sm-mta). confMTCCOPTS [empty] Additional options for compiling multi-threaded object files. confMTLDOPTS [empty] Additional linker options for linking multithreaded binaries. confNO_HELPFILE_INSTALL [undefined] If defined, don't install the sendmail helpfile by default. confNO_MAN_BUILD [undefined] If defined, don't build the man pages. confNO_MAN_INSTALL [undefined] If defined, don't install the man pages by default. confNO_STATISTICS_INSTALL [undefined] If defined, don't install the sendmail statistics file by default. confNROFF groff -Tascii The command to format man pages. confOBJADD [empty] Objects that should be included in when linking sendmail and the associated utilities. See also confSRCADD. confOPTIMIZE -O Flags passed to C compiler as ${O}. confRANLIB echo The path to the program to use as ranlib. confRANLIBOPTS [empty] Options to pass to ranlib. confREQUIRE_LIBSM [empty] Define if libsm is required. confSBINDIR /usr/sbin The location of root-oriented commands, such as makemap. confSBINGRP bin The group for set-user-ID binaries. confSBINMODE 4555 The mode for set-user-ID binaries. confSBINOWN root The owner for set-user-ID binaries. confSETUSERID_INSTALL [undefined] Needs to be defined to enable the install-set-user-id target for sendmail. See sendmail/SECURITY. confSHAREDLIB_EXT .so Shared library file extenion name. confSHAREDLIB_SUFFIX [empty] Shared object version suffix. confSHAREDLIBDIR /usr/lib/ Directory for installing shared library. Note: if the value is not empty, it must end with a slash ('/') otherwise it will not be taken as a directory (but as the beginning of a path). confSHELL /bin/sh The shell to use inside make. confSM_OS_HEADER [varies] The name of the platform specific include file. Undefine this if libsm is not used. confSMOBJADD [empty] Objects that should be included in when linking sendmail. See also confSMSRCADD. confSMSRCADD [empty] C source files which correspond to objects listed in confSMOBJADD. confSMSRCDIR [varies] The sendmail source directory relative to support program obj.* directories. If not set, the Makefile will use a path set by the Build script. confSRCADD [empty] C source files which correspond to objects listed in confOBJADD. confSRCDIR [varies] The root of the source directories relative to support program obj.* directories. If not set, the Makefile will use a path set by the Build script. confSONAME [empty] ld flag for recording the shared object name into shared object. confSTDIR /etc/mail The directory in which to store the sendmail statistics file. confSTFILE statistics Name of the installed statistics file. confSTMODE 0600 Mode of the installed statistics file. confSTRIP strip What program to use for stripping executables. confSTRIPOPTS [empty] Options to pass to the strip program. confUBINDIR /usr/bin The directory for user-executable binaries. confUBINGRP bin The group for user-executable binaries. confUBINMODE 555 The mode for user-executable binaries. confUBINOWN bin The owner for user-executable binaries. There are also program specific variables for each of the programs in the sendmail distribution. Each has the form `conf_prog_ENVDEF', for example, `conf_sendmail_ENVDEF'. If the program name contains a '.' it must be replaced by '_' first, e.g., use `conf_mail_local_LIBS' instead of `conf_mail.local_LIBS'. The variables are: conf_prog_ENVDEF [empty] -D flags passed to C compiler when compiling prog. conf_prog_LIB_POST [empty] -l flags passed to ld when linking prog (after other libraries). conf_prog_LIBS [varies] -l flags passed to ld when linking prog (before other libraries). conf_prog_OBJADD [empty] Additional object files given to ld when linking prog. conf_prog_SRCADD [empty] C source files to compile and link for prog. The order of the different conf*LIBS* is as follows: conf_prog_LIBS confLIBS conf_prog_LIB_POST ---------------------------------------------------------------- ---------------- New build system ---------------- Sendmail's build system has undergone some rearrangement to accommodate future development. To the end user building sendmail from a distribution, this should have little effect. All the same configuration files and macros should still behave the same. If you need to make some radical changes to a Makefile.m4 or are adding new libraries or utilities, you may want to read the rest of this document on how to work with the new system. -------- Overview -------- The purpose of the redesign is twofold. First, it cuts down massively on replicated information. Second, the new design should lend itself better to working on platforms with somewhat different build tools than on standard unix. The main idea is to have the Makefile.m4 in each subdirectory contain the minimum amount of information needed to describe the elements needed for the build process and the products produced. Each product has a type and each type has a template that provides a basic makefile for that type. Right now the templates are organized by the broad type of the operating system. The two existing types are UNIX and NT. ------------------ Makefile.m4 basics ------------------ Each Makefile.m4 is split into separate products. For the most part, the products are considered totally separate from other products in the Makefile.m4. Each products is delineated by two macros: bldPRODUCT_START and bldPRODUCT_END. The form for bldPRODUCT_START is: bldPRODUCT_START(, ) where is the type of product to be produced (e.g., executable, library, manpage) and is a unique identifier within the product_type name space for this Makefile.m4 The form for bldPRODUCT_END is: bldPRODUCT_END This is marks the end of all the information for the current product. There is one other macro required in any Makefile.m4 and that is bldFINISH which takes no arguments and must appear after all the products have been defined. When the actual makefile is generated each product appears in two sections. The first is where makefile variables are set (e.g., CFLAGS=-O). The second is where the targets appear (e.g., foo.o: foo.c). Anything diverted to bldTARGETS_SECTION ends up in the second part of the makefile. Anything else turns up in the header part where variables are defined. As always, any straight text put into Makefile.m4 will just show up as is in the finished makefile. ------------- Product Types ------------- executable ---------- This means an executable created from C sources. The name of the executable is derived from the product_name in the bldPRODUCT_START macro. bldSOURCES - This should be defined to a space separated list of source files that make up the executable. bldBIN_TYPE - This determines where the binaries will be installed and what permissions they will have. Available types are `M', `U', `K', `S', and `E'. See M4/UNIX/make/executable.m4 for what the different types mean. bldTARGET_LINKS - This determines where additional symbolic links to the executable are placed. These should be full pathnames, separated by spaces. test ---- This is just like 'executable', but is used for test programs. The program cannot be installed. Each time it is built, it is executed by make with no arguments. manpage ------- This builds manpages from source using *roff. bldSOURCES - This should be defined to a space separated list of man source files. library ------- This builds a static library from C sources. bldSOURCES - This should be defined to a space separated list of C source files that make up the library. bldINSTALLABLE - This should be set if the library should be installed in confLIBDIR. $Revision: 8.102 $, Last updated $Date: 2008/02/12 16:40:05 $ dk-milter-1.0.0.dfsg/devtools/OS/0000755000175000017500000000000010766324730016254 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/OS/GNU0000644000175000017500000000122707446471735016643 0ustar madhackmadhack# $Id: GNU,v 8.3 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confOPTIMIZE', `-g -O2') define(`confDEPEND_TYPE', `CC-M') define(`confEBINDIR', `/libexec') define(`confMANROOT', `/man/man') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confMANMODE', `644') define(`confMBINDIR', `/sbin') define(`confSBINDIR', `/sbin') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') define(`confSBINMODE', `4755') define(`confUBINDIR', `/bin') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confUBINMODE', `755') dk-milter-1.0.0.dfsg/devtools/OS/Linux0000644000175000017500000000146607446471735017316 0ustar madhackmadhack# $Id: Linux,v 8.30 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confDEPEND_TYPE', `CC-M') define(`confSM_OS_HEADER', `sm_os_linux') define(`confMANROOT', `/usr/man/man') define(`confLIBS', `-ldl') define(`confEBINDIR', `/usr/sbin') APPENDDEF(`confLIBSEARCH', `crypt nsl') define(`confLD', `ld') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-shared') define(`confSONAME',`-soname') ifelse(confBLDVARIANT, `DEBUG', dnl Debug build ` define(`confOPTIMIZE',`-g -Wall') ', dnl Optimized build confBLDVARIANT, `OPTIMIZED', ` define(`confOPTIMIZE',`-O2') ', dnl Purify build confBLDVARIANT, `PURIFY', ` define(`confOPTIMIZE',`-g') ', dnl default ` define(`confOPTIMIZE',`-O2') ') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.50000644000175000017500000000126507446471736017532 0ustar madhackmadhack# $Id: SunOS.5.5,v 8.18 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=20500') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl -lkstat') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/UNICOS-mp0000644000175000017500000000110107651022170017572 0ustar madhackmadhack# $Id: UNICOS-mp,v 8.1 2003/04/21 17:03:52 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-DUNICOSMP') define(`confDEPEND_TYPE', `CC-M') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confMANGRP', `sys') define(`confMANOWN', `root') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confSBINGRP', `sys') define(`confSBINOWN', `root') define(`confSM_OS_HEADER', `sm_os_unicosmp') define(`confUBINGRP', `sys') define(`confUBINOWN', `root') dk-milter-1.0.0.dfsg/devtools/OS/OpenBSD0000644000175000017500000000070707446471735017446 0ustar madhackmadhack# $Id: OpenBSD,v 8.20 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confLD', `cc') define(`confLDOPTS_SO', `-shared') define(`confCCOPTS_SO', `-fPIC') define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confENVDEF', ` -DNETISO -DFAST_PID_RECYCLE') define(`confSM_OS_HEADER', `sm_os_openbsd') define(`confMTCCOPTS', `-pthread') define(`confMTLDOPTS', `-pthread') dk-milter-1.0.0.dfsg/devtools/OS/UnixWare.5.i3860000644000175000017500000000142607556055506020604 0ustar madhackmadhack# $Id: UnixWare.5.i386,v 8.7 2002/10/24 20:42:46 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # # System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatiblity Libs ie. native) # Contributed by Paul Gampe # define(`confSM_OS_HEADER', `sm_os_unixware') define(`confCC', `/usr/ccs/bin/cc') define(`confMAPDEF', `-DNDBM -DMAP_REGEX') define(`confENVDEF', `-D__svr5__') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confSHELL', `/usr/bin/sh') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/etc/mail') define(`confUBINDIR', `/etc/mail') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confMTCCOPTS', `-Kpthread') define(`confMTLDOPTS', `-lpthread') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.110000644000175000017500000000143310255653277017576 0ustar madhackmadhack# $Id: SunOS.5.11,v 1.1 2005/06/20 23:52:31 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confLDOPTS_SO', `-G') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=21100 -DNETINET6') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/Darwin.8.x0000644000175000017500000000157510761101332020031 0ustar madhackmadhack# $Id: Darwin.8.x,v 1.4 2008/02/26 21:21:30 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # define(`confCC', `cc -pipe ${Extra_CC_Flags}') define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confENVDEF', `-DDARWIN=80000 -DBIND_8_COMPAT -DNETINET6') define(`confLDOPTS', `${Extra_LD_Flags}') define(`confMTLDOPTS', `-lpthread') define(`confMILTER_STATIC', `') define(`confDEPEND_TYPE', `CC-M') define(`confOPTIMIZE', `-O3') define(`confRANLIBOPTS', `-c') define(`confHFDIR', `/usr/share/sendmail') define(`confINSTALL_RAWMAN') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') define(`confLDOPTS_SO', `-dynamiclib -flat_namespace -undefined suppress -single_module') define(`confSHAREDLIB_EXT', `.dylib') dk-milter-1.0.0.dfsg/devtools/OS/KSR0000644000175000017500000000051407446471735016647 0ustar madhackmadhack# $Id: KSR,v 8.7 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS') define(`confLIBDIRS', `-L/usr/shlib -L/usr/lib') define(`confLIBS', `-ldbm') define(`confSTDIR', `/var/adm/sendmail') define(`confINSTALL', `installbsd') dk-milter-1.0.0.dfsg/devtools/OS/HP-UX.10.x0000644000175000017500000000151207757262305017531 0ustar madhackmadhack# $Id: HP-UX.10.x,v 8.20 2003/11/21 01:05:09 lijian Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -Aa') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_HPUX_SOURCE -DHPUX10 -DV4FS') define(`confSM_OS_HEADER', `sm_os_hp') define(`confLIBS', `-lndbm') define(`confSHELL', `/usr/bin/sh') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confSBINGRP', `mail') dnl Don't indent or put any tab/space in this file. dnl Tab/space here causes make syntax error ifelse(confBLDVARIANT, `DEBUG', dnl Debug build ` define(`confOPTIMIZE',`-g') ', dnl Optimized build confBLDVARIANT, `OPTIMIZED', ` define(`confOPTIMIZE',`+O3') ', dnl Purify build confBLDVARIANT, `PURIFY', ` define(`confOPTIMIZE',`-g') ', dnl default ` define(`confOPTIMIZE',`+O3') ') dk-milter-1.0.0.dfsg/devtools/OS/CSOS0000644000175000017500000000054207446471735016760 0ustar madhackmadhack# $Id: CSOS,v 8.8 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confLIBS', `-lnet') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confEBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/ucb') define(`confINSTALL', `${BUILDBIN}/install.sh') dk-milter-1.0.0.dfsg/devtools/OS/IRIX64.6.50000644000175000017500000000141007446471735017440 0ustar madhackmadhack# $Id: IRIX64.6.5,v 8.21 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -mips3 -n32 -OPT:Olimit=0') define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-DIRIX6') define(`confSM_OS_HEADER', `sm_os_irix') define(`confMANOWN', `root') define(`confMANGRP', `sys') define(`confUBINOWN', `root') define(`confUBINGRP', `sys') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/SCO0000644000175000017500000000055407446471736016641 0ustar madhackmadhack# $Id: SCO,v 8.7 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-D_SCO_unix_') define(`confLIBS', `-lsocket -lprot_s -lx -lc_s') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') dk-milter-1.0.0.dfsg/devtools/OS/Dynix0000644000175000017500000000100007446471735017272 0ustar madhackmadhack# $Id: Dynix,v 8.11 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confOPTIMIZE', `-O -g') define(`confLIBS', `-lseq') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `staff # no kmem group,') define(`confOBJADD', `strtol.o') define(`confSRCADD', `strtol.c') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/IRIX64.6.10000644000175000017500000000123607446471735017442 0ustar madhackmadhack# $Id: IRIX64.6.1,v 8.21 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DIRIX64') define(`confSM_OS_HEADER', `sm_os_irix') define(`confLIBS', `-lelf -lmalloc') define(`confMANOWN', `root') define(`confMANGRP', `sys') define(`confUBINOWN', `root') define(`confUBINGRP', `sys') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/NCR.MP-RAS.2.x0000644000175000017500000000123207446471735020174 0ustar madhackmadhack# $Id: NCR.MP-RAS.2.x,v 8.14 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DNCR_MP_RAS2') define(`confOPTIMIZE', `-O2') APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') define(`confLIBDIRS', `-L/usr/ucblib') define(`confLIBS', `-lnsl -lnet -lsocket -lelf -lc -lucb') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSTDIR', `/var/ucblib') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `NCR') dk-milter-1.0.0.dfsg/devtools/OS/NeXT.2.x0000644000175000017500000000127507446471735017441 0ustar madhackmadhack# $Id: NeXT.2.x,v 8.13 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confSM_OS_HEADER', `sm_os_next') define(`confBEFORE', `unistd.h dirent.h') define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') define(`confENVDEF', `-DNeXT') define(`confLIBS', `-ldbm') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confRANLIBOPTS', `-c') PUSHDIVERT(3) unistd.h: cp /dev/null unistd.h dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/SVR40000644000175000017500000000102507446471736016745 0ustar madhackmadhack# $Id: SVR4,v 8.10 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-D__svr4__') define(`confLIBS', `-ldbm -lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/Darwin0000644000175000017500000000155307532523361017425 0ustar madhackmadhack# $Id: Darwin,v 8.6 2002/08/26 22:08:49 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # # Wilfredo Sanchez : # We look a lot more like 4.4BSD than NeXTStep or OpenStep. # define(`confCC', `cc -traditional-cpp -pipe ${Extra_CC_Flags}') define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX -DNETINFO -DAUTO_NETINFO_ALIASES -DAUTO_NETINFO_HOSTS') define(`confENVDEF', `-DDARWIN') define(`confLDOPTS', `${Extra_LD_Flags}') define(`confMILTER_STATIC', `') define(`confDEPEND_TYPE', `CC-M') define(`confOPTIMIZE', `-O3') define(`confRANLIBOPTS', `-c') define(`confHFDIR', `/usr/share/sendmail') define(`confINSTALL_RAWMAN') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') dk-milter-1.0.0.dfsg/devtools/OS/BSD430000644000175000017500000000105207446471735016765 0ustar madhackmadhack# $Id: BSD43,v 8.11 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confBEFORE', `unistd.h stddef.h stdlib.h dirent.h sys/time.h') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DoldBSD43') define(`confLIBS', `-ldbm -ll') define(`confUBINDIR', `/usr/ucb') PUSHDIVERT(3) unistd.h stddef.h stdlib.h sys/time.h: cp /dev/null $@ sys/time.h: sys sys: mkdir sys dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.20000644000175000017500000000134707446471736017530 0ustar madhackmadhack# $Id: SunOS.5.2,v 8.15 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-DSOLARIS=20100') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/ucbinclude/sysexits.h ]; \ then \ ln -s /usr/ucbinclude/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/386BSD0000644000175000017500000000060107446471735017056 0ustar madhackmadhack# $Id: 386BSD,v 8.3 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', ` -DMIME') define(`confLIBS', `-lutil') define(`confLINKS', `/usr/sbin/sendmail /usr/bin/newaliases \ /usr/sbin/sendmail /usr/bin/mailq \ /usr/sbin/sendmail /usr/bin/hoststat \ /usr/sbin/sendmail /usr/bin/purgestat') dk-milter-1.0.0.dfsg/devtools/OS/UMAX0000644000175000017500000000102107446471736016755 0ustar madhackmadhack# $Id: UMAX,v 8.8 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confBEFORE', `stddef.h') define(`confMAPDEF', `-DNIS') define(`confENVDEF', `-DUMAXV') define(`confLIBS', `-lyp -lrpc') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confHFDIR', `/usr/lib') PUSHDIVERT(3) stddef.h: echo "#define _STDDEF_H" > stddef.h chmod 444 stddef.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/NEWS-OS.4.x0000644000175000017500000000065307446471735017717 0ustar madhackmadhack# $Id: NEWS-OS.4.x,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confBEFORE', `limits.h') define(`confMAPDEF', `-DNDBM') define(`confLIBS', `-lmld') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') PUSHDIVERT(3) limits.h: touch limits.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/m88k0000644000175000017500000000145507446471736017005 0ustar madhackmadhack# $Id: m88k,v 8.3 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # # Contributed by Sergey Rusanov # define(`confCC', `gcc') define(`confOPTIMIZE', `-O2') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DMOTO') define(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') define(`confLIBDIRS', `-L/usr/lib -L/usr/ucblib') define(`confLIBS', `-lc -ldbm -lsocket -lnsl -lelf -lucb') define(`confMBINDIR', `/usr/local/sbin') define(`confSBINDIR', `/usr/ucb') define(`confUBINDIR', `/usr/local/bin') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confSTDIR', `/var/log') define(`confHFDIR', `/usr/local/sbin') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/DomainOS0000644000175000017500000000107207446471735017661 0ustar madhackmadhack# $Id: DomainOS,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -A nansi -A,systype,any -A,runtype,bsd4.3') define(`confBEFORE', `unistd.h dirent.h') define(`confMAPDEF', `-DNDBM') define(`confSBINDIR', `/usr/etc') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') PUSHDIVERT(3) unistd.h: cp /dev/null unistd.h dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/UXPDS.V200000644000175000017500000000144307446471736017464 0ustar madhackmadhack# $Id: UXPDS.V20,v 8.13 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/ccs/bin/cc') define(`confBEFORE', `netinet/ip_var.h') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-DUXPDS=20') define(`confLIBS', `/usr/ucblib/libdbm.a -lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confMANROOT', `/usr/local/man/man') PUSHDIVERT(3) netinet/ip_var.h: netinet /usr/include/netinet/ip_var.h sed '/ip_var_f.h/d' /usr/include/netinet/ip_var.h > netinet/ip_var.h netinet: mkdir netinet POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/RISCos0000644000175000017500000000140507446471735017312 0ustar madhackmadhack# $Id: RISCos,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -systype bsd43 -Olimit 900') define(`confBEFORE', `stdlib.h dirent.h unistd.h stddef.h') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DRISCOS') define(`confLIBS', `-lmld') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `/usr/bsd43/bin/install') PUSHDIVERT(3) stdlib.h stddef.h: cp /dev/null $@ unistd.h: echo "typedef unsigned short mode_t;" > unistd.h dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/uts.systemV0000644000175000017500000000167407446471736020505 0ustar madhackmadhack# $Id: uts.systemV,v 8.15 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 PUSHDIVERT(1) # Sendmail 8 on UTS requires BIND 4.9's include files and lib44bsd and # libresolv libraries. The BIND version on UTS is much too old. # BINDPATH=../../../bind POPDIVERT define(`confBEFORE', `stddef.h') define(`confMAPDEF', `-DNIS -DNDBM') define(`confENVDEF', `-D_UTS') define(`confOPTIMIZE', `-g') APPENDDEF(`confINCDIRS', `-I${BINDPATH}/include -I${BINDPATH}/compat/include') define(`confLIBDIRS', `-L${BINDPATH}/res -L${BINDPATH}/compat/lib') define(`confLIBS', `-lyp -lrpc -lbsd -lsocket -la') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `mail') define(`confINSTALL', `${BUILDBIN}/install.sh') PUSHDIVERT(3) stddef.h: echo "#include " > stddef.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/RISCos.4_00000644000175000017500000000142707446471735017677 0ustar madhackmadhack# $Id: RISCos.4_0,v 8.10 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -systype bsd43 -Olimit 900') define(`confBEFORE', `stdlib.h dirent.h unistd.h stddef.h') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DRISCOS -DRISCOS_4_0') define(`confLIBS', `-lmld') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') PUSHDIVERT(3) stdlib.h stddef.h: cp /dev/null $@ unistd.h: echo "typedef unsigned short mode_t;" > unistd.h dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/ULTRIX0000644000175000017500000000071707446471736017245 0ustar madhackmadhack# $Id: ULTRIX,v 8.15 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -Olimit 1350') define(`confMAPDEF', `-DNDBM -DNIS') define(`confSM_OS_HEADER', `sm_os_ultrix') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confHFDIR', `/usr/lib') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/EWS-UX_V0000644000175000017500000000204507446471735017466 0ustar madhackmadhack# $Id: EWS-UX_V,v 8.11 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/abiccs/bin/cc -KOlimit=1000') define(`confBEFORE', `sysexits.h ndbm.h ndbm.o') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-Dnec_ews_svr4') define(`confLIBS', `ndbm.o -lsocket -lnsl -lelf # # with NDBM') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var/ucblib') define(`confINSTALL', `/usr/ucb/install') PUSHDIVERT(3) sysexits.h: echo '#ifndef _LOCAL_SYSEXITS_H_' > sysexits.h; echo '#define _LOCAL_SYSEXITS_H_' >> sysexits.h; cat /usr/abiccs/ucbinclude/sysexits.h >> sysexits.h; echo '#endif /* _LOCAL_SYSEXITS_H_ */' >> sysexits.h; # ln -s /usr/abiccs/ucbinclude/sysexits.h . ndbm.h: ln -s /usr/abiccs/ucbinclude/ndbm.h . ndbm.o: ar x /usr/abiccs/ucblib/libucb.a ndbm.o # ar x /usr/ucblib/libucb.a ndbm.o POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/AIX.5.00000644000175000017500000000126207446471735017133 0ustar madhackmadhack# $Id: AIX.5.0,v 1.6 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX5=50000') define(`confOPTIMIZE', `-O3 -qstrict') define(`confCC', `/usr/vac/bin/xlc') define(`confLIBS', `-ldbm') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') define(`confSM_OS_HEADER', `sm_os_aix') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.100000644000175000017500000000143307563075677017607 0ustar madhackmadhack# $Id: SunOS.5.10,v 1.2 2002/11/09 03:06:39 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confLDOPTS_SO', `-G') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=21000 -DNETINET6') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/Titan0000644000175000017500000000072307446471736017272 0ustar madhackmadhack# $Id: Titan,v 8.7 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -43') define(`confBEFORE', `stddef.h stdlib.h') define(`confMAPDEF', `-DNDBM') define(`confLIBS', `-ldbm') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') PUSHDIVERT(3) stddef.h stdlib.h: cp /dev/null $@ POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/UXPDS.V100000644000175000017500000000122707446471736017463 0ustar madhackmadhack# $Id: UXPDS.V10,v 8.14 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/ccs/bin/cc') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-DUXPDS=10') APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') define(`confLIBS', `/usr/ucblib/libdbm.a /usr/ucblib/libucb.a -lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confMANROOT', `/usr/local/man/man') dk-milter-1.0.0.dfsg/devtools/OS/ISC0000644000175000017500000000072407446471735016631 0ustar madhackmadhack# $Id: ISC,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-DISC_UNIX -D_POSIX_SOURCE -D_SYSV3') define(`confLIBS', `-lyp -lrpc -lndbm -linet -lcposix') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSTDIR', `/usr/spool/log') dk-milter-1.0.0.dfsg/devtools/OS/AIX.5.20000644000175000017500000000125407653335461017131 0ustar madhackmadhack# $Id: AIX.5.2,v 1.2 2003/04/28 23:37:21 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX5=50200') define(`confOPTIMIZE', `-O3 -qstrict') define(`confCC', `/usr/vac/bin/xlc') define(`confLIBS', `-ldbm') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') define(`confSM_OS_HEADER', `sm_os_aix') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') dk-milter-1.0.0.dfsg/devtools/OS/SINIX.5.430000644000175000017500000000100207446471736017464 0ustar madhackmadhack# $Id: SINIX.5.43,v 8.3 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/bin/cc') define(`confENVDEF', `-W0 -D__svr4__') define(`confLIBS', `-lsocket -lnsl -lelf -lmproc') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confLDOPTS', `-s') dk-milter-1.0.0.dfsg/devtools/OS/AIX.4.x0000644000175000017500000000101307446471735017234 0ustar madhackmadhack# $Id: AIX.4.x,v 8.17 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX4') define(`confOPTIMIZE', `-O3 -qstrict') define(`confLIBS', `-ldbm') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') define(`confSM_OS_HEADER', `sm_os_aix') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.90000644000175000017500000000144007446471736017531 0ustar madhackmadhack# $Id: SunOS.5.9,v 8.9 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confLDOPTS_SO', `-G') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=20900 -DNETINET6') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/IRIX64.6.00000644000175000017500000000123607446471735017441 0ustar madhackmadhack# $Id: IRIX64.6.0,v 8.21 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DIRIX64') define(`confSM_OS_HEADER', `sm_os_irix') define(`confLIBS', `-lelf -lmalloc') define(`confMANOWN', `root') define(`confMANGRP', `sys') define(`confUBINOWN', `root') define(`confUBINGRP', `sys') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/FreeBSD0000644000175000017500000000176207700700741017411 0ustar madhackmadhack# $Id: FreeBSD,v 8.36 2003/07/03 01:07:45 jutta Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confLIBS', `-lutil') define(`confLD', `cc') define(`confMTLDOPTS', `-pthread') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confLDOPTS_SO', `-shared') define(`confCCOPTS_SO', `-fPIC') define(`confSONAME', `-soname') define(`confSM_OS_HEADER', `sm_os_freebsd') define(`confPERL_CONFIGURE_ARGS', `-Dlddlflags=-shared -Dccdlflags="-export-dynamic"') ifelse(confBLDVARIANT, `DEBUG', dnl Debug build ` define(`confOPTIMIZE',`-g') ', dnl Optimized build confBLDVARIANT, `OPTIMIZED', ` define(`confOPTIMIZE',`-O') ', dnl Purify build confBLDVARIANT, `PURIFY', ` define(`confOPTIMIZE',`-g') ', dnl default ` define(`confOPTIMIZE',`-O') ') define(`USE_ICONV',` APPENDDEF(`confLIBS',`-liconv ')dnl APPENDDEF(`confLIBDIRS',`-L/usr/local/lib ')dnl APPENDDEF(`confINCDIRS',`-I/usr/local/include ')dnl ')dnl dk-milter-1.0.0.dfsg/devtools/OS/IRIX.5.x0000644000175000017500000000111007446471735017365 0ustar madhackmadhack# $Id: IRIX.5.x,v 8.16 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -mips2 -OPT:Olimit=1400') define(`confMAPDEF', `-DNDBM -DNIS') define(`confLIBS', `-lmld -lmalloc') define(`confSM_OS_HEADER', `sm_os_irix') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/AIX.5.10000644000175000017500000000126207446471735017134 0ustar madhackmadhack# $Id: AIX.5.1,v 1.2 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX5=50100') define(`confOPTIMIZE', `-O3 -qstrict') define(`confCC', `/usr/vac/bin/xlc') define(`confLIBS', `-ldbm') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') define(`confSM_OS_HEADER', `sm_os_aix') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') dk-milter-1.0.0.dfsg/devtools/OS/dgux0000644000175000017500000000071507446471736017163 0ustar madhackmadhack# $Id: dgux,v 8.9 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS') define(`confLIBS', `-ldbm') define(`confMBINDIR', `/usr/bin') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `bin') define(`confINSTALL', `${BUILDBIN}/install.sh') APPENDDEF(`confLIBSEARCH', `socket nsl') dk-milter-1.0.0.dfsg/devtools/OS/UNIX_SV.4.x.i3860000644000175000017500000000102407446471736020501 0ustar madhackmadhack# $Id: UNIX_SV.4.x.i386,v 8.11 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-D__svr4__ -DUNIXWARE') define(`confLIBS', `-lc -ldbm -lsocket -lnsl -lgen -lelf') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') dk-milter-1.0.0.dfsg/devtools/OS/MPE-iX0000644000175000017500000000325507446471735017214 0ustar madhackmadhack# $Id: MPE-iX,v 1.2 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confOPTIMIZE', `-O') define(`confMAPDEF', `-DNEWDB -DMAP_REGEX') define(`confENVDEF', `-DMPE -D_SOCKET_SOURCE -D_POSIX_SOURCE -DIS_SOCKET_CLIB_ITSELF') APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_DOTTED_USERNAMES -D_FFR_DROP_TRUSTUSER_WARNING -D_FFR_TRUSTED_QF') define(`confINCDIRS', `-I/BINDFW/CURRENT/include -I/SYSLOG/PUB -I/${HPACCOUNT}/${HPGROUP}/include -I/usr/contrib/include') define(`confLIBDIRS', `-L/BINDFW/CURRENT/lib -L/SYSLOG/PUB -L/${HPACCOUNT}/${HPGROUP}/lib') define(`confLIBS', `-lsyslog -ldb -lsocket -lsvipc') define(`confSM_OS_HEADER', `sm_os_mpeix') define(`conf_sendmail_LIB_POST', `--for-linker="-WL,cap=ia,ba,ph,pm"') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confEBINDIR', `/${HPACCOUNT}/${HPGROUP}/sbin') define(`confGBINGRP', `${HPACCOUNT}') define(`confGBINOWN', `MGR.${HPACCOUNT}') define(`confMSPQOWN', `SERVER.${HPACCOUNT}') define(`confMANROOT', `/${HPACCOUNT}/${HPGROUP}/man/cat') define(`confMANROOTMAN', `/${HPACCOUNT}/${HPGROUP}/man/man') define(`confMANGRP', `${HPACCOUNT}') define(`confMANOWN', `MGR.${HPACCOUNT}') define(`confMBINDIR', `/${HPACCOUNT}/${HPGROUP}/sbin') define(`confMBINGRP', `${HPACCOUNT}') define(`confMBINMODE', `555') define(`confMBINOWN', `MGR.${HPACCOUNT}') define(`confSBINDIR', `/${HPACCOUNT}/${HPGROUP}/sbin') define(`confSBINGRP', `${HPACCOUNT}') define(`confSBINMODE', `6555') define(`confSBINOWN', `MGR.${HPACCOUNT}') define(`confUBINDIR', `/${HPACCOUNT}/${HPGROUP}/bin') define(`confUBINGRP', `${HPACCOUNT}') define(`confUBINOWN', `MGR.${HPACCOUNT}') dk-milter-1.0.0.dfsg/devtools/OS/IRIX.6.x0000644000175000017500000000140607446471735017376 0ustar madhackmadhack# $Id: IRIX.6.x,v 8.30 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -mips3 -n32 -OPT:Olimit=0') define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-DIRIX6') define(`confSM_OS_HEADER', `sm_os_irix') define(`confMANOWN', `root') define(`confMANGRP', `sys') define(`confUBINOWN', `root') define(`confUBINGRP', `sys') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/DomainOS.10.40000644000175000017500000000102407446471735020237 0ustar madhackmadhack# $Id: DomainOS.10.4,v 8.4 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -A nansi -A,systype,any -A,runtype,bsd4.3') define(`confBEFORE', `dirent.h') define(`confMAPDEF', `-DNDBM') define(`confSBINDIR', `/usr/etc') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') PUSHDIVERT(3) dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.30000644000175000017500000000125507446471736017527 0ustar madhackmadhack# $Id: SunOS.5.3,v 8.15 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS') define(`confENVDEF', `-DSOLARIS=20300') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/ucbinclude/sysexits.h ]; \ then \ ln -s /usr/ucbinclude/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/NetBSD.8.30000644000175000017500000000030707446471735017576 0ustar madhackmadhack# $Id: NetBSD.8.3,v 8.11 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') dk-milter-1.0.0.dfsg/devtools/OS/SINIX.5.440000644000175000017500000000102107446471736017466 0ustar madhackmadhack# $Id: SINIX.5.44,v 8.3 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/bin/cc') define(`confENVDEF', `-W0 -D__svr4__ -Klp64') define(`confLIBS', `-lsocket -lnsl -lelf -lmproc') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confLDOPTS', `-Klp64 -s') dk-milter-1.0.0.dfsg/devtools/OS/OSF1.V5.x0000644000175000017500000000111507446471735017455 0ustar madhackmadhack# $Id: OSF1.V5.x,v 8.4 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -std1 -Olimit 1000') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `') define(`confLIBS', `-ldbm') define(`confSM_OS_HEADER', `sm_os_osf1') define(`confSTDIR', `/var/adm/sendmail') define(`confINSTALL', `installbsd') define(`confEBINDIR', `/usr/lbin') define(`confUBINDIR', `${BINDIR}') define(`confDEPEND_TYPE', `CC-M') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') dk-milter-1.0.0.dfsg/devtools/OS/Darwin.7.x0000644000175000017500000000131010003045122020004 0ustar madhackmadhack# $Id: Darwin.7.x,v 1.2 2004/01/19 21:21:22 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # define(`confCC', `cc -pipe ${Extra_CC_Flags}') define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confENVDEF', `-DDARWIN -DBIND_8_COMPAT') define(`confLDOPTS', `${Extra_LD_Flags}') define(`confMILTER_STATIC', `') define(`confDEPEND_TYPE', `CC-M') define(`confOPTIMIZE', `-O3') define(`confRANLIBOPTS', `-c') define(`confHFDIR', `/usr/share/sendmail') define(`confINSTALL_RAWMAN') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') dk-milter-1.0.0.dfsg/devtools/OS/DragonFly0000644000175000017500000000177010104600335020051 0ustar madhackmadhack# $Id: DragonFly,v 1.1 2004/08/06 03:54:05 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confLIBS', `-lutil') define(`confLD', `cc') define(`confMTLDOPTS', `-pthread') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confLDOPTS_SO', `-shared') define(`confCCOPTS_SO', `-fPIC') define(`confSONAME', `-soname') define(`confSM_OS_HEADER', `sm_os_dragonfly') define(`confPERL_CONFIGURE_ARGS', `-Dlddlflags=-shared -Dccdlflags="-export-dynamic"') ifelse(confBLDVARIANT, `DEBUG', dnl Debug build ` define(`confOPTIMIZE',`-g') ', dnl Optimized build confBLDVARIANT, `OPTIMIZED', ` define(`confOPTIMIZE',`-O') ', dnl Purify build confBLDVARIANT, `PURIFY', ` define(`confOPTIMIZE',`-g') ', dnl default ` define(`confOPTIMIZE',`-O') ') define(`USE_ICONV',` APPENDDEF(`confLIBS',`-liconv ')dnl APPENDDEF(`confLIBDIRS',`-L/usr/local/lib ')dnl APPENDDEF(`confINCDIRS',`-I/usr/local/include ')dnl ')dnl dk-milter-1.0.0.dfsg/devtools/OS/NEXTSTEP.4.x0000644000175000017500000000226007446471735020072 0ustar madhackmadhack# $Id: NEXTSTEP.4.x,v 8.7 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 PUSHDIVERT(1) # NEXTSTEP 3.1 and 3.2 only support m68k and i386 #ARCH= -arch m68k -arch i386 -arch hppa -arch sparc #ARCH= -arch m68k -arch i386 #ARCH= ${RC_CFLAGS} # For new sendmail Makefile structure, this must go in the ENVDEF and LDOPTS POPDIVERT define(`confBEFORE', `unistd.h dirent.h') define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') define(`confENVDEF', `-DNeXT -Wno-precomp -pipe ${RC_CFLAGS}') define(`confLDOPTS', `${RC_CFLAGS}') define(`confLIBS', `-ldbm') define(`confINSTALL_RAWMAN') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') define(`confEBINDIR', `/usr/etc') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confRANLIBOPTS', `-c') PUSHDIVERT(3) unistd.h: cp /dev/null unistd.h dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/SCO.5.x0000644000175000017500000000072207446471736017247 0ustar madhackmadhack# $Id: SCO.5.x,v 8.14 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -b elf') define(`confLIBS', `-lsocket -lndbm -lprot -lcurses -lm -lx -lgen') define(`confMAPDEF', `-DMAP_REGEX -DNDBM') define(`confSBINGRP', `bin') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/bin') define(`confINSTALL', `${BUILDBIN}/install.sh') dk-milter-1.0.0.dfsg/devtools/OS/OSF10000644000175000017500000000116707446471735016725 0ustar madhackmadhack# $Id: OSF1,v 8.19 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -std1 -Olimit 1000') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confLIBS', `-ldbm') define(`confSM_OS_HEADER', `sm_os_osf1') define(`confSTDIR', `/var/adm/sendmail') define(`confINSTALL', `installbsd') define(`confEBINDIR', `/usr/lbin') define(`confUBINDIR', `${BINDIR}') define(`confDEPEND_TYPE', `CC-M') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confDEPLIBS', `-lpthread -lc') define(`confSONAME', `-soname') dk-milter-1.0.0.dfsg/devtools/OS/IRIX.6.50000644000175000017500000000143007446471735017270 0ustar madhackmadhack# $Id: IRIX.6.5,v 8.23 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -mips3 -n32 -OPT:Olimit=0') define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') define(`confMAPDEF', `-DNEWDB -DNDBM -DNIS -DMAP_REGEX -DMAP_NSD') define(`confENVDEF', `-DIRIX6') define(`confSM_OS_HEADER', `sm_os_irix') define(`confMANOWN', `root') define(`confMANGRP', `sys') define(`confUBINOWN', `root') define(`confUBINGRP', `sys') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.70000644000175000017500000000146007446471736017531 0ustar madhackmadhack# $Id: SunOS.5.7,v 8.22 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confLDOPTS_SO', `-G') define(`confSONAME',`-h') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=20700') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/A-UX0000644000175000017500000000064507446471735016727 0ustar madhackmadhack# $Id: A-UX,v 8.8 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-D_POSIX_SOURCE') define(`confLIBS', `-ldbm -lposix -lUTIL') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') dk-milter-1.0.0.dfsg/devtools/OS/QNX0000644000175000017500000000113007446471735016651 0ustar madhackmadhack# $Id: QNX,v 8.7 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 PUSHDIVERT(1) # # For this Makefile to work you must compile and install the libdb package # and then change DBMINC and DBMLIB as appropriate. # DBMINC= /usr/local/include DBMLIB= /usr/local/lib POPDIVERT define(`confENVDEF', `-Osax -w4 -zc -fr= -D__BIT_TYPES_DEFINED__') APPENDDEF(`confINCDIRS', `${DBMINC}') define(`confLIBDIRS', `${DBMLIB}') define(`confLIBS', `-lsocket') define(`confLDOPTS', `-M -N256k') define(`confINSTALL', `${BUILDBIN}/install.sh') dk-milter-1.0.0.dfsg/devtools/OS/OpenUNIX.5.i3860000644000175000017500000000131007446471735020443 0ustar madhackmadhack# $Id: OpenUNIX.5.i386,v 1.3 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # # System V Rel 5.x (a.k.a OpenUNIX) # define(`confSM_OS_HEADER', `sm_os_openunix') define(`confCC', `/usr/ccs/bin/cc') define(`confMAPDEF', `-DNDBM -DMAP_REGEX') define(`confENVDEF', `-D__svr5__') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confSHELL', `/usr/bin/sh') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/etc/mail') define(`confUBINDIR', `/etc/mail') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confMTCCOPTS', `-Kpthread') define(`confMTLDOPTS', `-lpthread') dk-milter-1.0.0.dfsg/devtools/OS/IRIX0000644000175000017500000000077707446471735016776 0ustar madhackmadhack# $Id: IRIX,v 8.14 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS') define(`confLIBS', `-lmld -lmalloc -lsun') define(`confSM_OS_HEADER', `sm_os_irix') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/NetBSD0000644000175000017500000000107410064104110017233 0ustar madhackmadhack# $Id: NetBSD,v 8.15 2004/06/16 17:50:00 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confLIBS', `-lutil') define(`confENVDEF', ` -DNETISO') define(`confDEPEND_TYPE', `CC-M') define(`confSBINGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confMAN1EXT', `0') define(`confMAN3EXT', `0') define(`confMAN4EXT', `0') define(`confMAN5EXT', `0') define(`confMAN8EXT', `0') dk-milter-1.0.0.dfsg/devtools/OS/UX48000000644000175000017500000000161107446471736017060 0ustar madhackmadhack# $Id: UX4800,v 8.15 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/abiccs/bin/cc -KOlimit=1000') define(`confBEFORE', `sysexits.h ndbm.h') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var/ucblib') define(`confINSTALL', `/usr/ucb/install') PUSHDIVERT(3) sysexits.h: echo '#ifndef _LOCAL_SYSEXITS_H_' > sysexits.h; echo '#define _LOCAL_SYSEXITS_H_' >> sysexits.h; cat /usr/abiccs/ucbinclude/sysexits.h >> sysexits.h; echo '#endif /* _LOCAL_SYSEXITS_H_ */' >> sysexits.h; ndbm.h: sed 's/void/char/' /usr/abiccs/include/ndbm.h > ndbm.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/Interix0000644000175000017500000000124207777574217017637 0ustar madhackmadhack# $Id: Interix,v 1.2 2004/01/09 18:53:03 ca Exp $ # Contributed by Nedelcho Stanev dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 dnl: Interix 3.0: /usr/local/bin/gcc dnl: Interix 3.5: /opt/gcc.3.3/bin/gcc define(`confCC', `gcc') define(`confOPTIMIZE', `-O2') APPENDDEF(`confMAPDEF', `-DMAP_REGEX') APPENDDEF(`confENVDEF', `-D__INTERIX -D_ALL_SOURCE') APPENDDEF(`confINCDIRS', `-I/usr/local/include/bind') APPENDDEF(`confLIBDIRS', `-L/usr/local/lib/bind') APPENDDEF(`confLIBS', `-lbind') APPENDDEF(`confLIBS', `-ll') define(`confMAN1EXT', `0') define(`confMAN5EXT', `0') define(`confMAN8EXT', `0') dk-milter-1.0.0.dfsg/devtools/OS/SCO.4.20000644000175000017500000000070407446471736017140 0ustar madhackmadhack# $Id: SCO.4.2,v 8.9 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-D_SCO_unix_4_2') define(`confLIBS', `-lsocket -lndbm -lprot_s -lx -lc_s') define(`confMAPDEF', `-DNDBM') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `bin') define(`confINSTALL', `${BUILDBIN}/install.sh') dk-milter-1.0.0.dfsg/devtools/OS/dcosx.1.x.NILE0000644000175000017500000000054007446471736020463 0ustar madhackmadhack# $Id: dcosx.1.x.NILE,v 8.6 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-D__svr4__ -DDCOSx') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confHFDIR', `/usr/share/lib/mail') define(`confINSTALL', `/usr/ucb/install') define(`confSBINGRP', `sys') dk-milter-1.0.0.dfsg/devtools/OS/Mach3860000644000175000017500000000061607446471735017324 0ustar madhackmadhack# $Id: Mach386,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confMAPDEF', `-DNDBM') define(`confLIBS', `-ldbm') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/Dell0000644000175000017500000000106307446471735017070 0ustar madhackmadhack# $Id: Dell,v 8.12 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-D__svr4__') define(`confOPTIMIZE', `-O2') define(`confLIBS', `-ldbm -lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucblib') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/Paragon0000644000175000017500000000055507446471735017604 0ustar madhackmadhack# $Id: Paragon,v 8.6 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM') define(`confLIBDIRS', `-L/usr/shlib -L/usr/lib') define(`confLIBS', `-ldbm') define(`confSTDIR', `/var/adm/sendmail') define(`confINSTALL', `installbsd') define(`confUBINDIR', `${BINDIR}') dk-milter-1.0.0.dfsg/devtools/OS/PTX0000644000175000017500000000060407446471735016663 0ustar madhackmadhack# $Id: PTX,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM') define(`confOPTIMIZE', `-g') define(`confLIBS', `-lsocket -linet -lelf -lnsl -lseq') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') dk-milter-1.0.0.dfsg/devtools/OS/NeXT.4.x0000644000175000017500000000250407446471735017437 0ustar madhackmadhack# $Id: NeXT.4.x,v 8.20 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 PUSHDIVERT(1) # NEXTSTEP 3.1 and 3.2 only support m68k and i386 #ARCH= -arch m68k -arch i386 -arch hppa -arch sparc #ARCH= -arch m68k -arch i386 #ARCH= ${RC_CFLAGS} # For new sendmail Makefile structure, this must go in the ENVDEF and LDOPTS POPDIVERT define(`confSM_OS_HEADER', `sm_os_next') define(`confBEFORE', `unistd.h dirent.h') define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') define(`confENVDEF', `-DNeXT -Wno-precomp -pipe ${RC_CFLAGS}') define(`confLDOPTS', `${RC_CFLAGS}') define(`confLIBS', `-ldbm') define(`confRANLIBOPTS', `-c') define(`confINSTALL_RAWMAN') define(`confMANROOT', `/usr/man/cat') define(`confMANROOTMAN', `/usr/man/man') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') define(`confEBINDIR', `/usr/etc') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confRANLIBOPTS', `-c') PUSHDIVERT(3) unistd.h: cp /dev/null unistd.h dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/maxion0000644000175000017500000000107707446471736017511 0ustar madhackmadhack# $Id: maxion,v 8.9 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/usr/ucb/cc') define(`confMAPDEF', `-DNDBM -DNIS') define(`confLIBDIRS', `-L/usr/ucblib') define(`confLIBS', `-ldbm -lgen -lucb') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINOWN', `smtp') define(`confSBINGRP', `mail') define(`confSTDIR', `/var/adm/log') define(`confINSTALL', `/usr/ucb/install') dk-milter-1.0.0.dfsg/devtools/OS/AIX0000644000175000017500000000070107446471735016627 0ustar madhackmadhack# $Id: AIX,v 8.12 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-D_AIX3') define(`confOPTIMIZE', `-g') define(`confLIBS', `-ldbm') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `AIX') define(`confSM_OS_HEADER', `sm_os_aix') dk-milter-1.0.0.dfsg/devtools/OS/ConvexOS0000644000175000017500000000067507446471735017724 0ustar madhackmadhack# $Id: ConvexOS,v 8.9 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DYPCOMPAT -DNIS') define(`confENVDEF', `-D__STDC__ -d non_int_bit_field') define(`confOPTIMIZE', `-g') define(`confLIBS', `-lshare') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') dk-milter-1.0.0.dfsg/devtools/OS/Darwin.9.x0000644000175000017500000000157510761101332020032 0ustar madhackmadhack# $Id: Darwin.9.x,v 1.3 2008/02/26 21:21:30 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # define(`confCC', `cc -pipe ${Extra_CC_Flags}') define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') define(`confENVDEF', `-DDARWIN=90000 -DBIND_8_COMPAT -DNETINET6') define(`confLDOPTS', `${Extra_LD_Flags}') define(`confMTLDOPTS', `-lpthread') define(`confMILTER_STATIC', `') define(`confDEPEND_TYPE', `CC-M') define(`confOPTIMIZE', `-O3') define(`confRANLIBOPTS', `-c') define(`confHFDIR', `/usr/share/sendmail') define(`confINSTALL_RAWMAN') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') define(`confLDOPTS_SO', `-dynamiclib -flat_namespace -undefined suppress -single_module') define(`confSHAREDLIB_EXT', `.dylib') dk-milter-1.0.0.dfsg/devtools/OS/AIX.5.30000644000175000017500000000125410242236247017120 0ustar madhackmadhack# $Id: AIX.5.3,v 1.1 2005/05/17 00:36:55 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX5=50300') define(`confOPTIMIZE', `-O3 -qstrict') define(`confCC', `/usr/vac/bin/xlc') define(`confLIBS', `-ldbm') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') define(`confSM_OS_HEADER', `sm_os_aix') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.60000644000175000017500000000146707446471736017537 0ustar madhackmadhack# $Id: SunOS.5.6,v 8.20 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confLDOPTS_SO',`-G') define(`confSONAME',`-h') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=20600') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl -lkstat') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.10000644000175000017500000000134707446471736017527 0ustar madhackmadhack# $Id: SunOS.5.1,v 8.15 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-DSOLARIS=20100') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/ucbinclude/sysexits.h ]; \ then \ ln -s /usr/ucbinclude/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/IRIX64.6.x0000644000175000017500000000141007446471735017543 0ustar madhackmadhack# $Id: IRIX64.6.x,v 8.30 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -mips3 -n32 -OPT:Olimit=0') define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-DIRIX6') define(`confSM_OS_HEADER', `sm_os_irix') define(`confMANOWN', `root') define(`confMANGRP', `sys') define(`confUBINOWN', `root') define(`confUBINGRP', `sys') define(`confMBINDIR', `/usr/lib') define(`confUBINDIR', `/usr/bsd') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confSTDIR', `/var') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/HP-UX0000644000175000017500000000103107446471735017044 0ustar madhackmadhack# $Id: HP-UX,v 8.14 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `cc -Aa') define(`confENVDEF', `-D_HPUX_SOURCE') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confSM_OS_HEADER', `sm_os_hp') define(`confOPTIMIZE', `+O1') define(`confLIBS', `-lndbm') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `mail') define(`confINSTALL', `${BUILDBIN}/install.sh') dk-milter-1.0.0.dfsg/devtools/OS/UNICOS-mk0000644000175000017500000000075307651022170017601 0ustar madhackmadhack# $Id: UNICOS-mk,v 8.1 2003/04/21 17:03:52 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-DUNICOS -DUNICOSMK') define(`confDEPEND_TYPE', `CC-M') define(`confMAPDEF', `-DNDBM') define(`confOPTIMIZE', `-O') define(`confINSTALL', `cpset') define(`confSM_OS_HEADER', `sm_os_unicosmk') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') dk-milter-1.0.0.dfsg/devtools/OS/NeXT.3.x0000644000175000017500000000221307446471735017433 0ustar madhackmadhack# $Id: NeXT.3.x,v 8.19 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 PUSHDIVERT(1) # NEXTSTEP 3.1 and 3.2 only support m68k and i386 #ARCH= -arch m68k -arch i386 -arch hppa -arch sparc #ARCH= -arch m68k -arch i386 #ARCH= ${RC_CFLAGS} # For new sendmail Makefile structure, this must go in the ENVDEF and LDOPTS POPDIVERT define(`confSM_OS_HEADER', `sm_os_next') define(`confCCOPTS', `-posix') define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') define(`confENVDEF', `-DNeXT -Wno-precomp -pipe ${RC_CFLAGS}') define(`confLDOPTS', `${RC_CFLAGS} -posix') define(`confLIBS', `-ldbm') define(`confINSTALL_RAWMAN') define(`confMANROOT', `/usr/man/cat') define(`confMANROOTMAN', `/usr/man/man') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') define(`confEBINDIR', `/usr/etc') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confRANLIBOPTS', `-c') dk-milter-1.0.0.dfsg/devtools/OS/Altos0000644000175000017500000000071307446471735017273 0ustar madhackmadhack# $Id: Altos,v 8.10 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confENVDEF', `-DALTOS_SYSTEM_V') define(`confLIBS', `-lsocket -lrpc') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/NonStop-UX0000644000175000017500000000121507446471735020141 0ustar madhackmadhack# $Id: NonStop-UX,v 8.13 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DNonStop_UX_BXX -D_SVID') APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') define(`confLIBDIRS', `-L/usr/ucblib') define(`confLIBS', `-lsocket -lnsl -lelf -lucb') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/NEWS-OS.6.x0000644000175000017500000000144407446471735017720 0ustar madhackmadhack# $Id: NEWS-OS.6.x,v 8.14 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `/bin/cc') define(`confBEFORE', `sysexits.h ndbm.o') define(`confMAPDEF', `-DNDBM -DNIS') define(`confLIBS', `ndbm.o -lelf -lsocket -lnsl') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `/usr/ucb/install') PUSHDIVERT(3) sysexits.h: ln -s /usr/ucbinclude/sysexits.h . ndbm.o: if [ ! -f /usr/include/ndbm.h ]; then \ ln -s /usr/ucbinclude/ndbm.h .; \ fi; \ if [ -f /usr/lib/libndbm.a ]; then \ ar x /usr/lib/libndbm.a ndbm.o; \ else \ ar x /usr/ucblib/libucb.a ndbm.o; \ fi; POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/BSD-OS0000644000175000017500000000056007446471735017140 0ustar madhackmadhack# $Id: BSD-OS,v 8.16 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNEWDB -DMAP_REGEX') define(`confENVDEF', `-DNETISO') define(`confLIBS', `-lutil -lkvm') define(`confOPTIMIZE', `-O2') define(`confMAN1EXT', `0') define(`confMAN5EXT', `0') define(`confMAN8EXT', `0') dk-milter-1.0.0.dfsg/devtools/OS/HP-UX.11.x0000644000175000017500000000220007757262305017525 0ustar madhackmadhack# $Id: HP-UX.11.x,v 8.26 2003/11/21 01:05:09 lijian Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # +z is to generate position independant code define(`confCClibsmi', `cc -Ae +Z') define(`confCC', `cc -Ae') define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-DV4FS -DHPUX11') define(`confSM_OS_HEADER', `sm_os_hp') define(`confOPTIMIZE',`+O2') define(`confLIBS', `-ldbm -lnsl') define(`confSHELL', `/usr/bin/sh') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confSBINGRP', `mail') define(`confEBINDIR', `/usr/sbin') define(`confMTCCOPTS', `-D_POSIX_C_SOURCE=199506L +z') define(`confMTLDOPTS', `-lpthread') define(`confLD', `ld') define(`confLDOPTS_SO', `-b') define(`confCCOPTS_SO', `') dnl Don't indent or put any tab/space in this file. dnl Tab/space here causes make syntax error ifelse(confBLDVARIANT, `DEBUG', dnl Debug build ` define(`confOPTIMIZE',`-g') ', dnl Optimized build confBLDVARIANT, `OPTIMIZED', ` define(`confOPTIMIZE',`+O2') ', dnl Purify build confBLDVARIANT, `PURIFY', ` define(`confOPTIMIZE',`-g') ', dnl default ` define(`confOPTIMIZE',`+O2') ') dk-milter-1.0.0.dfsg/devtools/OS/Rhapsody0000644000175000017500000000151207446471736020001 0ustar madhackmadhack# $Id: Rhapsody,v 8.7 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 # # Wilfredo Sanchez : # We look a lot more like 4.4BSD than NeXTStep or OpenStep. # define(`confCC', `cc -traditional-cpp -pipe ${Extra_CC_Flags}') define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX -DNETINFO -DAUTO_NETINFO_ALIASES -DAUTO_NETINFO_HOSTS') define(`confENVDEF', `-DDARWIN -DNETISO') define(`confLDOPTS', `${Extra_LD_Flags}') define(`confDEPEND_TYPE', `CC-M') define(`confOPTIMIZE', `-O3') define(`confRANLIBOPTS', `-c') define(`confHFDIR', `/usr/share/sendmail') define(`confMANOWN', `root') define(`confMANGRP', `wheel') define(`confUBINOWN', `root') define(`confUBINGRP', `wheel') define(`confSBINOWN', `root') define(`confSBINGRP', `wheel') dk-milter-1.0.0.dfsg/devtools/OS/AIX.4.20000644000175000017500000000107407446471735017135 0ustar madhackmadhack# $Id: AIX.4.2,v 8.16 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX4=40200') define(`confOPTIMIZE', `-O3 -qstrict') define(`confLIBS', `-ldbm') define(`confLIBSEARCH', `db resolv 44bsd') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confSM_OS_HEADER', `sm_os_aix') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.4.00000644000175000017500000000104707446471736017522 0ustar madhackmadhack# $Id: SunOS.4.0,v 8.13 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confBEFORE', `stdlib.h stddef.h limits.h') define(`confMAPDEF', `-DNDBM -DNIS') define(`confENVDEF', `-DSUNOS403') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLDOPTS', `-Bstatic') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') PUSHDIVERT(3) stddef.h stdlib.h limits.h: cp /dev/null $@ POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/UNICOS0000644000175000017500000000073407651022170017173 0ustar madhackmadhack# $Id: UNICOS,v 8.12 2003/04/21 17:03:52 ca Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-DUNICOS') define(`confDEPEND_TYPE', `CC-M') define(`confMAPDEF', `-DNDBM') define(`confOPTIMIZE', `-O') define(`confINSTALL', `cpset') define(`confSM_OS_HEADER', `sm_os_unicos') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.80000644000175000017500000000144107446471736017531 0ustar madhackmadhack# $Id: SunOS.5.8,v 8.14 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confLDOPTS_SO', `-G') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') define(`confENVDEF', `-DSOLARIS=20800 -DNETINET6') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl') define(`confMTCCOPTS', `-D_REENTRANT') define(`confMTLDOPTS', `-lpthread') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/PowerUX0000644000175000017500000000072607446471735017566 0ustar madhackmadhack# $Id: PowerUX,v 8.8 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confENVDEF', `-D__svr4__') define(`confLIBS', `-Bstatic -lsocket -lnsl -lelf -lgen') define(`confMBINDIR', `/usr/local/etc') define(`confSBINDIR', `/usr/local/etc') define(`confUBINDIR', `/usr/local/bin') define(`confEBINDIR', `/usr/local/lib') define(`confSBINGRP', `mail') define(`confINSTALL', `/usr/ucb/install') dk-milter-1.0.0.dfsg/devtools/OS/LUNA0000644000175000017500000000231607446471735016751 0ustar madhackmadhack# $Id: LUNA,v 8.11 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confBEFORE', `dirent.h stddef.h stdlib.h unistd.h limits.h time.h sys/time.h') define(`confMAPDEF', `-DNDBM') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') PUSHDIVERT(3) dirent.h: echo "#include " > dirent.h echo "#define dirent direct" >> dirent.h stddef.h unistd.h limits.h: if [ -f /usr/include/$@ ]; then \ ln -s /usr/include/$@ .; \ else \ cp /dev/null $@; \ fi stdlib.h: if [ -f /usr/include/stdlib.h ]; then \ ln -s /usr/include/stdlib.h .; \ else \ if [ -f /usr/include/libc.h ]; then \ ln -s /usr/include/libc.h stdlib.h; \ else \ cp /dev/null stdlib.h; \ fi; \ fi # just for UNIOS-B time.h: echo "#ifndef _LOCAL_TIME_H_" > time.h echo "#define _LOCAL_TIME_H_" >> time.h cat /usr/include/time.h >> time.h echo "#endif" >> time.h sys/time.h: -mkdir sys echo "#ifndef _LOCAL_SYS_TIME_H_" > sys/time.h echo "#define _LOCAL_SYS_TIME_H_" >> sys/time.h cat /usr/include/sys/time.h >> sys/time.h echo "#endif" >> sys/time.h POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/SunOS0000644000175000017500000000065207446471736017223 0ustar madhackmadhack# $Id: SunOS,v 8.12 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLDOPTS', `-Bstatic') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/lib') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/NCR.MP-RAS.3.x0000644000175000017500000000107007446471735020175 0ustar madhackmadhack# $Id: NCR.MP-RAS.3.x,v 8.20 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DMAP_REGEX') define(`confENVDEF', `-DNCR_MP_RAS3') define(`confOPTIMIZE', `-O2') define(`confLIBS', `-lsocket -lnsl -lelf -lc89') define(`confMBINDIR', `/usr/ucblib') define(`confSBINDIR', `/usr/ucbetc') define(`confUBINDIR', `/usr/ucb') define(`confEBINDIR', `/usr/ucblib') define(`confSTDIR', `/var/ucblib') define(`confINSTALL', `/usr/ucb/install') define(`confDEPEND_TYPE', `NCR') dk-milter-1.0.0.dfsg/devtools/OS/SunOS.5.40000644000175000017500000000124707446471736017531 0ustar madhackmadhack# $Id: SunOS.5.4,v 8.17 2002/03/21 23:59:26 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confBEFORE', `sysexits.h') define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS') define(`confENVDEF', `-DSOLARIS=20400') define(`confSM_OS_HEADER', `sm_os_sunos') define(`confLIBS', `-lsocket -lnsl -lelf') define(`confMBINDIR', `/usr/lib') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `sys') define(`confINSTALL', `${BUILDBIN}/install.sh') define(`confDEPEND_TYPE', `CC-M') PUSHDIVERT(3) sysexits.h: if [ -r /usr/include/sysexits.h ]; \ then \ ln -s /usr/include/sysexits.h; \ fi POPDIVERT dk-milter-1.0.0.dfsg/devtools/OS/CLIX0000644000175000017500000000076407446471735016756 0ustar madhackmadhack# $Id: CLIX,v 8.13 2002/03/21 23:59:25 gshapiro Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confCC', `gcc') define(`confMAPDEF', `-DNDBM') define(`confENVDEF', `-DCLIX') APPENDDEF(`confINCDIRS', `-I/usr/include') define(`confLIBS', `-lnsl -lbsd') define(`confMBINDIR', `/usr/lib') define(`confSBINDIR', `/usr/etc') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `mail') define(`confINSTALL', `cp') define(`confDEPEND_TYPE', `CC-M') dk-milter-1.0.0.dfsg/devtools/OS/AIX.4.30000644000175000017500000000135507700703442017122 0ustar madhackmadhack# $Id: AIX.4.3,v 8.20 2003/07/03 01:30:10 jutta Exp $ dnl DO NOT EDIT THIS FILE. dnl Place personal settings in devtools/Site/site.config.m4 define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') define(`confENVDEF', `-D_AIX4=40300') define(`confOPTIMIZE', `-O3 -qstrict') define(`confCC', `/usr/bin/xlc') define(`confLIBS', `-ldbm') define(`confINSTALL', `/usr/ucb/install') define(`confEBINDIR', `/usr/lib') define(`confSBINGRP', `system') define(`confDEPEND_TYPE', `AIX') define(`confLDOPTS', `-blibpath:/usr/lib:/lib') define(`confSM_OS_HEADER', `sm_os_aix') define(`confMTCCOPTS', `-D_THREAD_SAFE') define(`confMTLDOPTS', `-lpthread') define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') define(`USE_ICONV',` APPENDDEF(`confLIBS',`-liconv ')dnl ')dnl dk-milter-1.0.0.dfsg/devtools/bin/0000755000175000017500000000000010766324726016510 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/bin/install.sh0000755000175000017500000000331107254521673020511 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1998, 1999, 2001 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: install.sh,v 8.14 2001/03/16 23:37:31 gshapiro Exp $ # Set default program program=mv owner="" group="" mode="" strip="" # chown program -- ultrix keeps it in /etc/chown and /usr/etc/chown if [ -f /etc/chown ] then chown=/etc/chown elif [ -f /usr/etc/chown ] then chown=/usr/etc/chown else chown=chown fi # Check arguments while [ ! -z "$1" ] do case $1 in -o) owner=$2 shift; shift ;; -g) group=$2 shift; shift ;; -m) mode=$2 shift; shift ;; -c) program=cp shift ;; -s) strip="strip" shift ;; -*) echo $0: Unknown option $1 exit 1 ;; *) break ;; esac done # Check source file if [ -z "$1" ] then echo "Source file required" >&2 exit 1 elif [ -f $1 -o $1 = /dev/null ] then src=$1 else echo "Source file must be a regular file or /dev/null" >&2 exit 1 fi # Check destination if [ -z "$2" ] then echo "Destination required" >&2 exit 1 elif [ -d $2 ] then srcfile=`basename $src` dst=$2/$srcfile else dst=$2 fi # Do install operation $program $src $dst if [ $? != 0 ] then exit 1 fi # Strip if requested if [ ! -z "$strip" ] then $strip $dst fi # Change owner if requested if [ ! -z "$owner" ] then $chown $owner $dst if [ $? != 0 ] then exit 1 fi fi # Change group if requested if [ ! -z "$group" ] then chgrp $group $dst if [ $? != 0 ] then exit 1 fi fi # Change mode if requested if [ ! -z "$mode" ] then chmod $mode $dst if [ $? != 0 ] then exit 1 fi fi exit 0 dk-milter-1.0.0.dfsg/devtools/bin/configure.sh0000644000175000017500000000644207720734443021030 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: configure.sh,v 8.46 2003/08/20 18:08:35 gshapiro Exp $ # # Special script to autoconfigure for M4 generation of Makefile # SHELL=/bin/sh os="" resolver="" sflag="" bin_dir=`echo $0 | sed -e 's%\/[^/]*$%%'` if [ ! -d $bin_dir ] then bin_dir="." fi find_prog=$bin_dir/find_in_path.sh while [ ! -z "$1" ] do case $1 in -s) # skip auto-configure sflag=1 shift ;; *) # OS definition os=$1 shift ;; esac done usewhoami=0 usehostname=0 for p in `echo $PATH | sed 's/:/ /g'` do if [ "x$p" = "x" ] then p="." fi if [ -f $p/whoami ] then usewhoami=1 if [ $usehostname -ne 0 ] then break; fi fi if [ -f $p/hostname ] then usehostname=1 if [ $usewhoami -ne 0 ] then break; fi fi done #ifdef WIN32 if [ $os = "WINNT.4.0" -o $os = "WINNT.5.0" -o $os = "WINNT" ] then user=$USERNAME else #endif /* WIN32 */ if [ $usewhoami -ne 0 ] then user=`whoami` else user=$LOGNAME fi #ifdef WIN32 fi #endif /* WIN32 */ if [ $usehostname -ne 0 ] then host=`hostname` else host=`uname -n` fi echo "PUSHDIVERT(0)" echo "####################################################################" echo "##### This file is automatically generated -- edit at your own risk" echo '#####' Built by $user@$host echo '#####' on `date` using template OS/$os if [ ! -z "$SITECONFIG" ] then echo '#####' including $SITECONFIG fi echo '#####' in `pwd` | sed 's/\/tmp_mnt//' echo "####################################################################" echo "" echo "POPDIVERT" echo "define(\`__HOST__', \`$host')dnl" echo "ifdef(\`confMAPDEF',, \`define(\`confMAPDEF', \`')')dnl" echo "ifdef(\`confLIBS',, \`define(\`confLIBS', \`')')dnl" LIBDIRS="$LIBDIRS $LIBPATH" libs="" mapdef="" for l in $LIBSRCH do for p in `echo $LIBDIRS | sed -e 's/:/ /g' -e 's/^-L//g' -e 's/ -L/ /g'` do if [ "x$p" = "x" ] then p = "." fi if [ -f $p/lib$l.a -o -f $p/lib$l.so ] then case $l in db) mapdef="$mapdef -DNEWDB" ;; bind|resolv) if [ -n "$resolver" ] then continue else resolver=$l fi ;; 44bsd) if [ "x$resolver" != "xresolv" ] then continue fi ;; esac libs="$libs -l$l" break fi done done for p in `echo $PATH | sed 's/:/ /g'` do pbase=`echo $p | sed -e 's,/bin,,'` if [ "x$p" = "x" ] then p="." fi if [ -f $p/mkdep ] then echo "ifdef(\`confDEPEND_TYPE',, \`define(\`confDEPEND_TYPE', \`BSD')')dnl" fi done if [ -z "$sflag" ] then echo "define(\`confMAPDEF', \`$mapdef' confMAPDEF)dnl" echo "define(\`confLIBS', \`$libs' confLIBS)dnl" fi if [ ! -z "`$SHELL $find_prog ranlib`" ] then echo "define(\`confRANLIB', \`ranlib')dnl" fi roff_progs="groff nroff" for roff_prog in $roff_progs do if [ ! -z "`$SHELL $find_prog $roff_prog`" ] then found_roff=$roff_prog break; fi done case $found_roff in groff) echo "ifdef(\`confNROFF',,\`define(\`confNROFF', \`$found_roff -Tascii')')dnl" ;; nroff) echo "ifdef(\`confNROFF',,\`define(\`confNROFF', \`$found_roff')')dnl" ;; *) echo "ifdef(\`confNROFF',,\`define(\`confNO_MAN_BUILD')')dnl" ;; esac dk-milter-1.0.0.dfsg/devtools/bin/find_m4.sh0000755000175000017500000000472407233161301020355 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: find_m4.sh,v 8.13 2001/01/23 01:47:45 gshapiro Exp $ # # Try to find a working M4 program. # If $M4 is already set, we use it, otherwise we prefer GNU m4. EX_UNAVAILABLE=69 test="ifdef(\`pushdef', \`', \`errprint(\`You need a newer version of M4, at least as new as System V or GNU') include(NoSuchFile)') define(\`BadNumber', \`10') ifdef(\`BadNumber', \`', \`errprint(\`This version of m4 is broken: trailing zero problem') include(NoSuchFile)') define(\`LongList', \` assert.c debug.c exc.c heap.c match.c rpool.c strdup.c strerror.c strl.c clrerr.c fclose.c feof.c ferror.c fflush.c fget.c fpos.c findfp.c flags.c fopen.c fprintf.c fpurge.c fput.c fread.c fscanf.c fseek.c fvwrite.c fwalk.c fwrite.c get.c makebuf.c put.c refill.c rewind.c rget.c setvbuf.c smstdio.c snprintf.c sscanf.c stdio.c strio.c syslogio.c ungetc.c vasprintf.c vfprintf.c vfscanf.c vprintf.c vsnprintf.c vsprintf.c vsscanf.c wbuf.c wsetup.c stringf.c xtrap.c strto.c test.c path.c strcasecmp.c signal.c clock.c config.c shm.c ') define(\`SameList', \`substr(LongList, 0, index(LongList, \`.'))\`'substr(LongList, index(LongList, \`.'))') ifelse(len(LongList), len(SameList), \`', \`errprint(\`This version of m4 is broken: length problem') include(NoSuchFile)')" if [ "$M4" ] then err="`(echo "$test" | $M4) 2>&1 >/dev/null`" code=$? else firstfound= ifs="$IFS"; IFS="${IFS}:" for m4 in gm4 gnum4 pdm4 m4 do for dir in $PATH /usr/5bin /usr/ccs/bin do [ -z "$dir" ] && dir=. if [ -f $dir/$m4 ] then err="`(echo "$test" | $dir/$m4) 2>&1 >/dev/null`" ret=$? if [ $ret -eq 0 -a "X$err" = "X" ] then M4=$dir/$m4 code=0 break else case "$firstfound:$err" in :*version\ of*) firstfound=$dir/$m4 firsterr="$err" firstcode=$ret ;; esac fi fi done [ "$M4" ] && break done IFS="$ifs" if [ ! "$M4" ] then if [ "$firstfound" ] then M4=$firstfound err="$firsterr" code=$firstcode else echo "ERROR: Can not locate an M4 program" >&2 exit $EX_UNAVAILABLE fi fi fi if [ $code -ne 0 ] then echo "ERROR: Using M4=$M4: $err" | grep -v NoSuchFile >&2 exit $EX_UNAVAILABLE elif [ "X$err" != "X" ] then echo "WARNING: $err" >&2 fi echo $M4 exit 0 dk-milter-1.0.0.dfsg/devtools/bin/find_in_path.sh0000755000175000017500000000041006772510256021461 0ustar madhackmadhack#! /bin/sh # # $Id: find_in_path.sh,v 8.2 1999/09/23 20:42:22 gshapiro Exp $ # EX_OK=0 EX_NOT_FOUND=1 ifs="$IFS"; IFS="${IFS}:" for dir in $PATH /usr/5bin /usr/ccs/bin do if [ -r $dir/$1 ] then echo $dir/$1 exit $EX_OK fi done IFS=$ifs exit $EX_NOT_FOUND dk-milter-1.0.0.dfsg/devtools/bin/Build0000755000175000017500000005163610741734021017472 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1998-2002, 2008 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1993, 1996-1997 Eric P. Allman. All rights reserved. # Copyright (c) 1993 # The Regents of the University of California. All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: Build,v 8.187 2008/01/11 18:40:17 ca Exp $ # # # A quick-and-dirty script to compile sendmail and related programs # in the presence of multiple architectures. To use, just use # "sh Build". # trap "rm -f $obj/.settings$$; exit" 1 2 3 15 cflag="" mflag="" Mflag="" Aflag="" sflag="" makeargs="" libdirs="" incdirs="" libsrch="" libpath="" siteconfig="" pfx="" obj="" oscf="" arch="" os="" rel="" mkdir="mkdir -p" SENDMAIL_BUILD_FLAGS="" EX_OK=0 EX_USAGE=64 EX_NOINPUT=66 EX_UNAVAILABLE=69 SHELL=/bin/sh # default to a optimized build to behave like the old system. build_variant="optimized" full_src_dir=`pwd` if [ -z "$src_dir" ] then src_dir=`basename ${full_src_dir}` fi absolute_base_dir=`echo ${full_src_dir} | sed "s#${src_dir}\\$##"` obj_rel_base_dir='../..' while [ ! -z "$1" ] do case $1 in -src) # Specify pathname of source directory relative to # root of cvs tree. This relative pathname may have # multiple components, as in 'foo/bar/baz', and will also # be used to form the pathname of the object directory. shift arg=$1 if [ -z "$arg" ] then echo "Missing arg for -src" >&2 exit $EX_USAGE fi case $arg in /*) echo "Arg for -src must not begin with / ($arg)" >&2 exit $EX_USAGE ;; esac src_dir="$arg" absolute_base_dir=`echo ${full_src_dir} | sed "s;/${src_dir}$;;"` obj_rel_base_dir=`echo x/${src_dir} | sed "s;[^/][^/]*;..;g"` SMROOT=${absolute_base_dir} shift ;; -c) # clean out existing $obj tree cflag=1 SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" shift ;; -m) # show Makefile name only mflag=1 shift ;; -M) # show the name of the obj. directory Mflag=1 shift ;; -A) # show the name of the architecture Aflag=1 shift ;; -E*) # environment variables to pass into Build arg=`echo $1 | sed 's/^-E//'` if [ -z "$arg" ] then shift # move to argument arg=$1 fi if [ -z "$arg" ] then echo "Empty -E flag" >&2 exit $EX_USAGE else case $arg in *=*) # check format eval $arg export `echo $arg | sed 's;=.*;;'` SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -E \"$arg\"" ;; *) # bad format echo "Bad format for -E argument ($arg)" >&2 exit $EX_USAGE ;; esac shift fi ;; -L*) # set up LIBDIRS libdirs="$libdirs $1" SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" shift ;; -I*) # set up INCDIRS incdirs="$incdirs $1" SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" shift ;; -f*) # select site config file arg=`echo $1 | sed 's/^-f//'` if [ -z "$arg" ] then shift # move to argument arg=$1 fi if [ "$pfx" ] then echo "May not use -f and -Q together" exit $EX_USAGE fi if [ "$siteconfig" ] then echo "Only one -f flag allowed" >&2 exit $EX_USAGE else siteconfig=$arg if [ -z "$siteconfig" ] then echo "Missing argument for -f flag" >&2 exit $EX_USAGE elif [ ! -f "$siteconfig" ] then echo "${siteconfig}: File not found" exit $EX_NOINPUT else shift # move past argument case $arg in /*) SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -f \"$siteconfig\"" ;; *) SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -f \"${full_src_dir}/$siteconfig\"" ;; esac fi fi ;; -O*) # Set object directory manually. arg="`echo $1 | sed 's/^-O//'`" if [ -z "$arg" ] then shift # move to argument arg="$1" fi case $arg in /*) OBJ_ROOT="$arg" SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -O \"$OBJ_ROOT\"" obj_rel_base_dir=$absolute_base_dir ;; *) echo "Absolute directory path required for -O flag" >&2 exit $EX_USAGE ;; esac shift ;; -S) # skip auto-configure sflag="-s" SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" shift ;; -Q*) # Select a prefix for the Site/*.config.m4 file arg=`echo $1 | sed 's/^-Q//'` if [ -z "$arg" ] then shift # move to argument arg=$1 fi if [ -z "$arg" ] then echo "Empty -Q flag" >&2 exit $EX_USAGE elif [ "$siteconfig" ] then echo "May not use -Q and -f together" >&2 exit $EX_USAGE elif [ "$pfx" ] then echo "Only one -Q allowed" >&2 exit $EX_USAGE else pfx=$arg SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -Q \"$pfx\"" fi shift ;; -v) # Select a build variant: debug, optimized, purify, whatever. shift build_variant=$1 if [ -z "$build_variant" ] then echo "Usage error with \"-v\" " >&2 echo "You must specify exactly one build variant of debug|optimized|purify" >&2 exit $EX_USAGE fi shift ;; *) # pass argument to make makeargs="$makeargs \"$1\"" #SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS \"$1\"" shift ;; esac done # process selected build variant. case $build_variant in debug) M4_BLDVARIANT_FLAGS="-DconfBLDVARIANT=DEBUG" ;; optimized) M4_BLDVARIANT_FLAGS="-DconfBLDVARIANT=OPTIMIZED" ;; purify) M4_BLDVARIANT_FLAGS="-DconfBLDVARIANT=PURIFY" echo "Sorry, the purify build variant has not been plumbed yet. (Bummer.)" >&2 exit $EX_USAGE ;; *) exit $EX_USAGE ;; esac # # Do heuristic guesses !ONLY! for machines that do not have uname # if [ -d /NextApps -a ! -f /bin/uname -a ! -f /usr/bin/uname ] then # probably a NeXT box arch=`hostinfo | sed -n 's/.*Processor type: \([^ ]*\).*/\1/p'` os=NeXT rel=`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'` elif [ -f /usr/sony/bin/machine -a -f /etc/osversion ] then # probably a Sony NEWS 4.x os=NEWS-OS rel=`awk '{ print $3}' /etc/osversion` arch=`/usr/sony/bin/machine` elif [ -d /usr/omron -a -f /bin/luna ] then # probably a Omron LUNA os=LUNA if [ -f /bin/luna1 ] && /bin/luna1 then rel=unios-b arch=luna1 elif [ -f /bin/luna2 ] && /bin/luna2 then rel=Mach arch=luna2 elif [ -f /bin/luna88k ] && /bin/luna88k then rel=Mach arch=luna88k fi elif [ -d /usr/apollo -a -d \`node_data ] then # probably a Apollo/DOMAIN os=DomainOS arch=$ISP rel=`/usr/apollo/bin/bldt | grep Domain | awk '{ print $4 }' | sed -e 's/,//g'` #ifdef WIN32 elif [ `uname` = "CYGWIN_NT-4.0" -o `uname` = "CYGWIN_NT-5.0" ] then # Windows NT 4.0 or Windows 2000 arch=`uname -m | sed -e 's/ //g' -e 's/\//-/g'` os=`uname -s | sed -e 's/CYG//g' -e 's/ //g' -e 's/_//g' -e 's/-/./g'` rel=`uname -r | sed -e 's/(/_/g' -e 's/)//g' -e 's/ //g' -e 's/\//-/g'` elif [ `uname` = "CYGWIN_NT-5.1" ] then # Treat Windows XP as Windows 2000 arch="i686" os="WINNT.5.0" rel="20.1_0.3-1-1" #endif /* WIN32 */ fi if [ ! "$arch" -a ! "$os" -a ! "$rel" ] then arch=`uname -m | sed -e 's/ //g' -e 's/\//-/g'` os=`uname -s | sed -e 's/\//-/g' -e 's/ //g'` rel=`uname -r | sed -e 's/(/-/g' -e 's/)//g' -e 's/ //g'` fi # # Tweak the values we have already got. PLEASE LIMIT THESE to # tweaks that are absolutely necessary because your system uname # routine doesn't return something sufficiently unique. Don't do # it just because you don't like the name that is returned. You # can combine the architecture name with the os name to create a # unique Makefile name. # # tweak machine architecture case $arch in sun4*) arch=sun4;; 9000/*) arch=`echo $arch | sed -e 's/9000.//' -e 's/..$/xx/'`;; DS/907000) arch=ds90;; NILE*) arch=NILE os=`uname -v`;; CRAYT3E) os=UNICOS-mk;; CRAY[CJT]90*|CRAYTS|CRAYSV1*|CRAYY-MP) os=UNICOS;; esac # tweak operating system type and release node=`uname -n | sed -e 's/\//-/g' -e 's/ //g'` if [ "$os" = "$node" -a "$arch" = "i386" -a "$rel" = 3.2 -a "`uname -v`" = 2 ] then # old versions of SCO UNIX set uname -s the same as uname -n os=SCO_SV fi if [ "$rel" = 4.0 ] then case $arch in 3[34]??|3[34]??,*|3[34]??[A-Z]|4[48]??|56??) if [ -d /usr/sadm/sysadm/add-ons/WIN-TCP ] then os=NCR.MP-RAS rel=2.x arch=i486 elif [ -d /usr/sadm/sysadm/add-ons/inet ] then os=NCR.MP-RAS rel=3.x arch=i486 fi ;; esac fi case $os in DYNIX-ptx) os=PTX;; Paragon*) os=Paragon;; HP-UX) rel=`echo $rel | sed -e 's/^[^.]*\.0*//'`;; AIX) osl="" if [ -x /bin/lslpp ] then osl=`/bin/lslpp -Lcq bos.rte | cut -f3 -d: | cut -f1-3 -d. 2>/dev/null` if [ $? = 0 -a -n "$osl" ] then rel=$osl else # command failed; fall back to old method osl="" fi fi # check whether it worked if [ -z "$osl" ] then rela=$rel rel=`uname -v` rel=$rel.$rela fi arch=PPC ;; BSD-386) os=BSD-OS;; SCO_SV) rel=`uname -X | sed -n 's/Release = //p'` if [ "$rel" = "5v6.0.0" ] then os=OSR; rel=`uname -X | sed -n 's/Release = //p'` else os=SCO; rel=`uname -X | sed -n 's/Release = 3.2v//p'` fi;; UNIX_System_V) if [ "$arch" = "ds90" ] then os="UXPDS" rel=`uname -v | sed -e 's/\(V.*\)L.*/\1/'` fi;; ReliantUNIX-?|SINIX-?) os=SINIX;; DomainOS) case $rel in 10.4*) rel=10.4;; esac ;; IRIX*) rel=`echo $rel | sed -e 's/-.*$//'`;; NeXT) mkdir="mkdirs";; UNICOSMK) rel=`echo $rel | sed -e 's/\(.*\)\.\(.*\)\.\(.*\)\..*$/\1.\2.\3/'`;; UNICOS*) rel=`echo $rel | sed -e 's/\(.*\)\.\(.*\)\..*$/\1.\2/'`;; esac # get "base part" of operating system release rroot=`echo $rel | sed -e 's/\.[^.]*$//'` rbase=`echo $rel | sed -e 's/\..*//'` if [ "$rroot" = "$rbase" ] then rroot=$rel fi # heuristic tweaks to clean up names -- PLEASE LIMIT THESE! if [ "$os" = "unix" ] then # might be Altos System V case $rel in 5.3*) os=Altos;; esac elif [ -r /unix -a -r /usr/lib/libseq.a -a -r /lib/cpp ] then # might be a DYNIX/ptx 2.x system, which has a broken uname if strings /lib/cpp | grep _SEQUENT_ > /dev/null then os=PTX fi elif [ -d /usr/nec ] then # NEC machine -- what is it running? if [ "$os" = "UNIX_System_V" ] then os=EWS-UX_V elif [ "$os" = "UNIX_SV" ] then os=UX4800 fi elif [ "$arch" = "mips" ] then case $rel in 4_*) if [ `uname -v` = "UMIPS" ] then os=RISCos fi;; esac fi # see if there is a "user suffix" specified if [ "${SENDMAIL_SUFFIX-}x" = "x" ] then sfx="" else sfx=".${SENDMAIL_SUFFIX}" fi if [ ! -n "$Mflag" -a ! -n "$Aflag" ] then echo "Configuration: pfx=$pfx, os=$os, rel=$rel, rbase=$rbase, rroot=$rroot, arch=$arch, sfx=$sfx, variant=$build_variant" fi SMROOT=${SMROOT-`(cd ..;pwd)`} BUILDTOOLS=${BUILDTOOLS-$SMROOT/devtools} export SMROOT BUILDTOOLS # see if we are in a Build-able directory if [ ! -f Makefile.m4 -a ! -n "$Aflag" ]; then echo "Makefile.m4 not found. Build can only be run from a source directory." exit $EX_UNAVAILABLE fi incdirs="$incdirs -I\${SRCDIR}/include" if [ -z "$OBJ_ROOT" ]; then OBJ_ROOT=${SMROOT} fi if [ "${pfx}x" = "x" ] then prefix="" else prefix=".$pfx" fi # Print out the architecture (to build up an obj dir path) and exit if [ -n "$Aflag" ] then echo "$os.$rel.$arch$sfx" exit $EX_OK fi # now try to find a reasonable object directory if [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rel.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$rel.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rroot.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$rroot.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rbase.x.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$rbase.x.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rel$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$rel$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rbase.x$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$rbase.x$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$rel.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$rel.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$rbase.x.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$rbase.x.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$os$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$arch$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$arch$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$rel$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$rel$sfx elif [ -r ${OBJ_ROOT}/obj${prefix}.$sfx ]; then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$sfx fi if [ -n "$abs_obj_dir" ] then obj=${abs_obj_dir}/${src_dir} fi # Print the directory which would be used for the build and exit if [ -n "$Mflag" ] then if [ ! -n "$obj" ] then obj=${OBJ_ROOT}/obj.$os.$rel.$arch$sfx/${src_dir} fi echo "$obj" exit $EX_OK fi # Check if trying to use -f with an existing obj directory if [ -n "$siteconfig" -a -n "$obj" -a -d "$obj" -a -z "$cflag" ] then echo "Can not use Build's -f flag with an existing object tree." echo "If you wish to change configuration information, use the -c flag to clear" echo "the existing $obj tree." exit $EX_USAGE fi # Check if trying to use -Q with an existing obj directory if [ -n "$pfx" -a -n "$obj" -a -d "$obj" -a -z "$cflag" ] then echo "Can not use Build's -Q flag with an existing object tree." echo "If you wish to change configuration information, use the -c flag to clear" echo "the existing $obj tree." exit $EX_USAGE fi # Clean out the directory before building. if [ "$cflag" ] then if [ -n "$obj" ] then echo "Clearing out existing $obj tree" rm -rf $obj fi fi # If we didn't detect an existing obj directory, makeup a new obj name. if [ -z "$obj" ] then abs_obj_dir=${OBJ_ROOT}/obj${prefix}.$os.$rel.$arch$sfx obj=${abs_obj_dir}/${src_dir} fi # Check if obj directory exists if [ ! -r "$obj" ] then if [ -r $BUILDTOOLS/OS/$os.$rel.$arch$sfx ]; then oscf=$os.$rel.$arch$sfx elif [ -r $BUILDTOOLS/OS/$os.$rel.$arch ]; then oscf=$os.$rel.$arch elif [ -r $BUILDTOOLS/OS/$os.$rroot.$arch$sfx ]; then oscf=$os.$rroot.$arch$sfx elif [ -r $BUILDTOOLS/OS/$os.$rroot.$arch ]; then oscf=$os.$rroot.$arch elif [ -r $BUILDTOOLS/OS/$os.$rbase.x.$arch$sfx ]; then oscf=$os.$rbase.x.$arch$sfx elif [ -r $BUILDTOOLS/OS/$os.$rbase.x.$arch ]; then oscf=$os.$rbase.x.$arch elif [ -r $BUILDTOOLS/OS/$os.$rel$sfx ]; then oscf=$os.$rel$sfx elif [ -r $BUILDTOOLS/OS/$os.$rel ]; then oscf=$os.$rel elif [ -r $BUILDTOOLS/OS/$os.$rroot$sfx ]; then oscf=$os.$rroot$sfx elif [ -r $BUILDTOOLS/OS/$os.$rroot ]; then oscf=$os.$rroot elif [ -r $BUILDTOOLS/OS/$os.$rbase.x$sfx ]; then oscf=$os.$rbase.x$sfx elif [ -r $BUILDTOOLS/OS/$os.$rbase.x ]; then oscf=$os.$rbase.x elif [ -r $BUILDTOOLS/OS/$os.$arch$sfx ]; then oscf=$os.$arch$sfx elif [ -r $BUILDTOOLS/OS/$os.$arch ]; then oscf=$os.$arch elif [ -r $BUILDTOOLS/OS/$rel.$arch$sfx ]; then oscf=$rel.$arch$sfx elif [ -r $BUILDTOOLS/OS/$rel.$arch ]; then oscf=$rel.$arch elif [ -r $BUILDTOOLS/OS/$rroot.$arch$sfx ]; then oscf=$rroot.$arch$sfx elif [ -r $BUILDTOOLS/OS/$rroot.$arch ]; then oscf=$rroot.$arch elif [ -r $BUILDTOOLS/OS/$rbase.x.$arch$sfx ]; then oscf=$rbase.x.$arch$sfx elif [ -r $BUILDTOOLS/OS/$rbase.x.$arch ]; then oscf=$rbase.x.$arch elif [ -r $BUILDTOOLS/OS/$os$sfx ]; then oscf=$os$sfx elif [ -r $BUILDTOOLS/OS/$os ]; then oscf=$os elif [ -r $BUILDTOOLS/OS/$arch$sfx ]; then oscf=$arch$sfx elif [ -r $BUILDTOOLS/OS/$arch ]; then oscf=$arch elif [ -r $BUILDTOOLS/OS/$rel$sfx ]; then oscf=$rel$sfx elif [ -r $BUILDTOOLS/OS/$rel ]; then oscf=$rel elif [ -r $BUILDTOOLS/OS/$rel$sfx ]; then oscf=$rel$sfx else echo "Cannot determine how to support $os.$rel.$arch" >&2 exit $EX_UNAVAILABLE fi M4=`$SHELL $BUILDTOOLS/bin/find_m4.sh` ret=$? if [ $ret -ne 0 ] then exit $ret fi echo "Using M4=$M4" export M4 if [ "$mflag" ] then echo "Will run in virgin $obj using $BUILDTOOLS/OS/$oscf" exit $EX_OK fi echo "Creating $obj using $BUILDTOOLS/OS/$oscf" ${mkdir} $obj #ifdef WIN32 # If this is WINNT then compile with relative paths # (based on REL_SRC_DIR), so we don't need to do any "linking" if [ ! $os = "WINNT.4.0" -a ! $os = "WINNT.5.0" -a ! $os = "WINNT" ] then #endif /* WIN32 */ ln="ln -s" (cd $obj # This glob doesn't actually glob to something everywhere, # thus the protective measures. for i in ${obj_rel_base_dir}/${src_dir}/*.[chly13458] do if [ -f $i ] then $ln $i . fi done # This glob doesn't actually glob to something everywhere, # thus the protective measures. for i in ${obj_rel_base_dir}/${src_dir}/*.0 do if [ -f $i ] then $ln $i `basename $i`.dist fi done) if [ -f helpfile ] then (cd $obj; $ln ${obj_rel_base_dir}/${src_dir}/helpfile .) fi #ifdef WIN32 fi #endif /* WIN32 */ rm -f $obj/.settings$$ echo 'divert(-1)' > $obj/.settings$$ cat $BUILDTOOLS/M4/header.m4 >> $obj/.settings$$ echo "define(\`bldOS', \`\`$os'')" >> $obj/.settings$$ echo "define(\`bldREL', \`\`$rel'')" >> $obj/.settings$$ echo "define(\`bldARCH', \`\`$arch'')" >> $obj/.settings$$ cat $BUILDTOOLS/OS/$oscf >> $obj/.settings$$ cur_dir=`pwd` cd $obj/.. absolute_obj_dir=`pwd` #ifdef WIN32 if [ $os = "WINNT.4.0" -o $os = "WINNT.5.0" -o $os = "WINNT" ] then absolute_obj_dir=`cygpath -w $absolute_obj_dir | sed 's#\\\\#/#g'` fi #endif /* WIN32 */ cd $cur_dir echo "ifdef(\`bldABS_OBJ_DIR',,\`define(\`bldABS_OBJ_DIR', \`$absolute_obj_dir')')" >> $obj/.settings$$ rel_src_dir="$obj_rel_base_dir/$src_dir" echo "define(\`bldSRC_NAME', \`$src_dir')" >> $obj/.settings$$ echo "define(\`bldREL_SRC_DIR', \`$rel_src_dir')" >> $obj/.settings$$ if [ ! -z "$pfx" ] then # They gave us a specific prefix, let's try it out. if [ -f $BUILDTOOLS/Site/$pfx.$oscf$sfx.m4 ] then siteconfig=$BUILDTOOLS/Site/$pfx.$oscf$sfx.m4 elif [ -f $BUILDTOOLS/Site/$pfx.$oscf.m4 ] then siteconfig=$BUILDTOOLS/Site/$pfx.$oscf.m4 fi if [ -f $BUILDTOOLS/Site/$pfx.config.m4 ] then siteconfig="$BUILDTOOLS/Site/$pfx.config.m4 $siteconfig" fi elif [ -z "$siteconfig" ] then # none specified, use defaults if [ -f $BUILDTOOLS/Site/site.$oscf$sfx.m4 ] then siteconfig=$BUILDTOOLS/Site/site.$oscf$sfx.m4 elif [ -f $BUILDTOOLS/Site/site.$oscf.m4 ] then siteconfig=$BUILDTOOLS/Site/site.$oscf.m4 fi if [ -f $BUILDTOOLS/Site/site.config.m4 ] then siteconfig="$BUILDTOOLS/Site/site.config.m4 $siteconfig" fi if [ -f $BUILDTOOLS/Site/site.post.m4 ] then siteconfig="$siteconfig $BUILDTOOLS/Site/site.post.m4" fi fi if [ ! -z "$siteconfig" ] then echo "Including $siteconfig" cat $siteconfig >> $obj/.settings$$ fi if [ "$libdirs" ] then echo "define(\`confLIBDIRS', confLIBDIRS \`\`$libdirs'')" >> $obj/.settings$$ fi if [ "$incdirs" ] then echo "define(\`confINCDIRS', \`\`$incdirs'' confINCDIRS)" >> $obj/.settings$$ fi echo "define(\`_SRC_PATH_', \`\`$obj_rel_base_dir'')" >> $obj/.settings$$ echo "define(\`bldSRC_PATH', \`\`$obj_rel_base_dir'')" >> $obj/.settings$$ echo 'divert(0)dnl' >> $obj/.settings$$ libdirs=`(cat $obj/.settings$$; echo "_SRIDBIL_= confLIBDIRS" ) | \ sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' | \ ${M4} ${M4_BLDVARIANT_FLAGS} -DconfBUILDTOOLSDIR=$BUILDTOOLS - | \ grep "^_SRIDBIL_=" | \ sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e "s/^_SRIDBIL_=//"` libsrch=`(cat $obj/.settings$$; echo "_HCRSBIL_= confLIBSEARCH" ) | \ sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' | \ ${M4} ${M4_BLDVARIANT_FLAGS} -DconfBUILDTOOLSDIR=$BUILDTOOLS - | \ grep "^_HCRSBIL_=" | \ sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e "s/^_HCRSBIL_=//"` libpath=`(cat $obj/.settings$$; echo "_HCRSBIL_= confLIBSEARCHPATH" ) | \ sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' | \ ${M4} ${M4_BLDVARIANT_FLAGS} -DconfBUILDTOOLSDIR=$BUILDTOOLS - | \ grep "^_HCRSBIL_=" | \ sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e "s/^_HCRSBIL_=//"` echo 'divert(-1)' >> $obj/.settings$$ LIBDIRS="$libdirs" LIBSRCH="$libsrch" LIBPATH="$libpath" SITECONFIG="$siteconfig" $SHELL $BUILDTOOLS/bin/configure.sh $sflag $oscf >> $obj/.settings$$ echo 'divert(0)dnl' >> $obj/.settings$$ sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' -e 's/ //g' $obj/.settings$$ | \ ${M4} ${M4_BLDVARIANT_FLAGS} -DconfBUILDTOOLSDIR=$BUILDTOOLS - Makefile.m4 | \ sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e 's/ //g' > $obj/Makefile # That ^M up there was added by quoting it in emacs. # Make has problems if lines end in ^M^M, but not in ^M apparently if [ $? -ne 0 -o ! -s $obj/Makefile ] then echo "ERROR: ${M4} failed; You may need a newer version of M4, at least as new as System V or GNU" 1>&2 rm -rf $obj exit $EX_UNAVAILABLE fi rm -f $obj/.settings$$ echo "Making dependencies in $obj" (cd $obj; ${MAKE-make} depend) fi if [ "$mflag" ] then makefile=`ls -l $obj/Makefile | sed 's/.* //'` if [ -z "$makefile" ] then echo "ERROR: $obj exists but has no Makefile" >&2 exit $EX_NOINPUT fi echo "Will run in existing $obj using $makefile" exit $EX_OK fi echo "Making in $obj" cd $obj eval exec ${MAKE-make} SENDMAIL_BUILD_FLAGS=\"$SENDMAIL_BUILD_FLAGS\" $makeargs dk-milter-1.0.0.dfsg/devtools/M4/0000755000175000017500000000000010766324726016220 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/M4/list.m40000644000175000017500000000132206743462255017433 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: list.m4,v 8.3 1999/07/15 22:46:05 rand Exp $ # divert(0)dnl define(`bldLIST_PUSH_ITEM', `define(`$1', ifdef(`$1', `$1 $2 ', `$2 '))' )dnl define(`bldFOREACH', `$1substr($2, `0', index($2, ` ')))`'ifelse(index($2, ` '), eval(len($2)-1), , `bldFOREACH(`$1', substr($2, index($2, ` ')))')'dnl )dnl define(`bldADD_PATH', `$1/$2 ')dnl define(`bldADD_PATHS', `bldFOREACH(`bldADD_PATH(`$1',', $2)'dnl )dnl dk-milter-1.0.0.dfsg/devtools/M4/depend/0000755000175000017500000000000010766324726017457 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/M4/depend/CC-M.m40000644000175000017500000000054606723340460020374 0ustar madhackmadhack# $Id: CC-M.m4,v 8.5 1999/05/27 22:03:28 peterh Exp $ depend: ${BEFORE} ${LINKS} @mv Makefile Makefile.old @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile @echo "# Do not edit or remove this line or anything below it." >> Makefile ${CC} -M ${COPTS} ${SRCS} >> Makefile # End of $RCSfile: CC-M.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/depend/generic.m40000644000175000017500000000026206722316251021324 0ustar madhackmadhack# $Id: generic.m4,v 8.5 1999/05/24 18:38:33 rand Exp $ # dependencies # give a null "depend" list so that the startup script will work depend: # End of $RCSfile: generic.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/depend/NCR.m40000644000175000017500000000055406723340461020337 0ustar madhackmadhack# $Id: NCR.m4,v 8.6 1999/05/27 22:03:29 peterh Exp $ depend: ${BEFORE} ${LINKS} @mv Makefile Makefile.old @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile @echo "# Do not edit or remove this line or anything below it." >> Makefile ${CC} -w0 -Hmake ${COPTS} ${SRCS} >> Makefile # End of $RCSfile: NCR.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/depend/BSD.m40000644000175000017500000000054406723340460020323 0ustar madhackmadhack# $Id: BSD.m4,v 8.6 1999/05/27 22:03:28 peterh Exp $ depend: ${BEFORE} ${LINKS} @mv Makefile Makefile.old @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile @echo "# Do not edit or remove this line or anything below it." >> Makefile mkdep -a -f Makefile ${COPTS} ${SRCS} # End of $RCSfile: BSD.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/depend/AIX.m40000644000175000017500000000076406723427622020346 0ustar madhackmadhack# $Id: AIX.m4,v 8.2 1999/05/28 05:54:26 gshapiro Exp $ depend: ${BEFORE} ${LINKS} @mv Makefile Makefile.old @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile @echo "# Do not edit or remove this line or anything below it." >> Makefile changequote([,]) for i in ${SRCS}; \ do \ ${CC} -M -E ${COPTS} $$i > /dev/null; \ cat `basename $$i .c`.u >> Makefile ; \ rm -f `basename $$i .c`.u ; \ done; changequote # End of $RCSfile: AIX.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/depend/Solaris.m40000644000175000017500000000055506723340461021332 0ustar madhackmadhack# $Id: Solaris.m4,v 8.4 1999/05/27 22:03:29 peterh Exp $ depend: ${BEFORE} ${LINKS} @mv Makefile Makefile.old @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile @echo "# Do not edit or remove this line or anything below it." >> Makefile ${CC} -xM ${COPTS} ${SRCS} >> Makefile # End of $RCSfile: Solaris.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/depend/X11.m40000644000175000017500000000022206723340461020256 0ustar madhackmadhack# $Id: X11.m4,v 8.4 1999/05/27 22:03:29 peterh Exp $ depend: ${BEFORE} ${LINKS} makedepend -- ${COPTS} -- ${SRCS} # End of $RCSfile: X11.m4,v $ dk-milter-1.0.0.dfsg/devtools/M4/subst_ext.m40000644000175000017500000000136306722315232020472 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: subst_ext.m4,v 8.3 1999/05/24 18:29:46 rand Exp $ # divert(0)dnl define(`bldSUBST_EXTENSION', `substr($2, 0, bldRINDEX($2, `.'))`'.$1 'dnl )dnl define(`bldSUBST_EXTENSIONS', `bldFOREACH(`bldSUBST_EXTENSION(`$1',', $2)'dnl )dnl define(`bldREMOVE_COMMAS', `$1 ifelse($#, 1, , `bldREMOVE_COMMAS(shift($@))')'dnl )dnl define(`bldADD_EXTENSION', `$2.$1 ')dnl define(`bldADD_EXTENSIONS', `bldFOREACH(`bldADD_EXTENSION(`$1',', $2)'dnl )dnl dk-milter-1.0.0.dfsg/devtools/M4/UNIX/0000755000175000017500000000000010766324726017003 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/M4/UNIX/defines.m40000644000175000017500000001361210511366514020652 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999-2001, 2006 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: defines.m4,v 8.47 2006/10/06 05:44:44 ca Exp $ # # temporary hack: if confREQUIRE_LIBSM is set then also set confREQUIRE_SM_OS_H ifdef(`confREQUIRE_LIBSM',` ifdef(`confREQUIRE_SM_OS_H',`', `define(`confREQUIRE_SM_OS_H', `1')')') # divert(0)dnl # C compiler CC= confCC CCOPTS= ifdef(`confCCOPTS', `confCCOPTS', ` ') ifdef(`confMT', ifdef(`confMTCCOPTS', `confMTCCOPTS', `'), `') # Linker for executables CCLINK = ifdef(`confCCLINK', `confCCLINK', `confCC') # Linker for libraries LD= ifdef(`confLD', `confLD', `confCC') LDOPTS= ifdef(`confLDOPTS', `confLDOPTS') ifdef(`confMT', ifdef(`confMTLDOPTS', `confMTLDOPTS', `'), `') LDOPTS_SO= ${LDOPTS} ifdef(`confLDOPTS_SO', `confLDOPTS_SO', `-shared') # Shell SHELL= confSHELL # use O=-O (usual) or O=-g (debugging) O= ifdef(`confOPTIMIZE', `confOPTIMIZE', `-O') # Object archiver AR= ifdef(`confAR', `confAR', `ar') AROPTS= ifdef(`confAROPTS', `confAROPTS', `crv') # Remove command RM= ifdef(`confRM', `confRM', `rm') RMOPTS= ifdef(`confRMOPTS', `confRMOPTS', `-f') # Link command LN= ifdef(`confLN', `confLN', `ln') LNOPTS= ifdef(`confLNOPTS', `confLNOPTS', `-f -s') # Ranlib (or echo) RANLIB= ifdef(`confRANLIB', `confRANLIB', `ranlib') RANLIBOPTS= ifdef(`confRANLIBOPTS', `confRANLIBOPTS', `') # Object stripper STRIP= ifdef(`confSTRIP', `confSTRIP', `strip') STRIPOPTS= ifdef(`confSTRIPOPTS', `confSTRIPOPTS', `') # environment definitions (e.g., -D_AIX3) ENVDEF= ifdef(`confENVDEF', `confENVDEF') ifdef(`conf_'bldCURRENT_PRD`_ENVDEF', `conf_'bldCURRENT_PRD`_ENVDEF') # location of the source directory SRCDIR= ifdef(`confSRCDIR', `confSRCDIR', `_SRC_PATH_') # inc`'lude directories INCDIRS= confINCDIRS # library directories LIBDIRS=confLIBDIRS # Additional libs needed LIBADD= ifdef(`conf_'bldCURRENT_PRD`_LIBS', `conf_'bldCURRENT_PRD`_LIBS') # libraries required on your system LIBS= ${LIBADD} ifdef(`confLIBS', `confLIBS') ifdef(`conf_'bldCURRENT_PRD`_LIB_POST', `conf_'bldCURRENT_PRD`_LIB_POST') # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ifdef(`confMBINDIR', `confMBINDIR', `/usr/sbin') # location of "user" binaries (usually /usr/bin or /usr/ucb) UBINDIR=ifdef(`confUBINDIR', `confUBINDIR', `/usr/bin') # location of "root" binaries (usually /usr/sbin or /usr/etc) SBINDIR=ifdef(`confSBINDIR', `confSBINDIR', `/usr/sbin') # location of "root" binaries (usually /usr/sbin or /usr/etc) MBINDIR=ifdef(`confMBINDIR', `confMBINDIR', `/usr/sbin') # location of "libexec" binaries (usually /usr/libexec or /usr/etc) EBINDIR=ifdef(`confEBINDIR', `confEBINDIR', `/usr/libexec') # where to install inc`'lude files (usually /usr/inc`'lude) INCLUDEDIR=ifdef(`confINCLUDEDIR', `confINCLUDEDIR', `/usr/inc`'lude') # where to install library files (usually /usr/lib) LIBDIR=ifdef(`confLIBDIR', `confLIBDIR', `/usr/lib') # additional .c files needed SRCADD= ifdef(`confSRCADD', `confSRCADD') ifdef(`conf_'bldCURRENT_PRD`_SRCADD', `bldLIST_PUSH_ITEM(`bldSOURCES', `conf_'bldCURRENT_PRD`_SRCADD')') # additional .o files needed OBJADD= ifdef(`confOBJADD', `confOBJADD') bldCURRENT_PRODUCT`OBJADD'= ifdef(`conf_'bldCURRENT_PRD`_OBJADD', `conf_'bldCURRENT_PRD`_OBJADD') ifdef(`confLIBADD', `bldADD_EXTENSIONS(`a', confLIBADD)', `') # copy files CP= ifdef(`confCOPY', `confCOPY', `cp') # In some places windows wants nmake where unix would just want make NMAKE=ifdef(`confNMAKE', `confNMAKE', `${MAKE}') ################### end of user configuration flags ###################### BUILDBIN=confBUILDBIN COPTS= -I. ${INCDIRS} ${ENVDEF} ${CCOPTS} CFLAGS= $O ${COPTS} ifdef(`confMT', ifdef(`confMTCFLAGS', `confMTCFLAGS -DXP_MT', `-DXP_MT'), `') BEFORE= confBEFORE ifdef(`confREQUIRE_SM_OS_H',`sm_os.h') LINKS=ifdef(`bldLINK_SOURCES', `bldLINK_SOURCES', `') bldCURRENT_PRODUCT`SRCS'= bldSOURCES ${SRCADD} bldCURRENT_PRODUCT`OBJS'= bldSUBST_EXTENSIONS(`o', bldSOURCES) ifdef(`bldLINK_SOURCES', `bldSUBST_EXTENSIONS(`o', bldLINK_SOURCES)') ${OBJADD} ${bldCURRENT_PRODUCT`OBJADD'} bldCURRENT_PRODUCT`SMDEPLIBS'= ifdef(`bldSMDEPLIBS', `bldSMDEPLIBS', `') bldCURRENT_PRODUCT`TARGET_LINKS'= ifdef(`bldTARGET_LINKS', `bldTARGET_LINKS', `') bldPUSH_ALL_SRCS(bldCURRENT_PRODUCT`SRCS')dnl ifdef(`bldBIN_TYPE', , `define(`bldBIN_TYPE', `U')')dnl ifdef(`bldINSTALL_DIR', , `define(`bldINSTALL_DIR', `U')')dnl NROFF= ifdef(`confNROFF', `confNROFF', `groff -Tascii') MANDOC= ifdef(`confMANDOC', `confMANDOC', `-man') INSTALL=ifdef(`confINSTALL', `confINSTALL', `install') # User binary ownership/permissions UBINOWN=ifdef(`confUBINOWN', `confUBINOWN', `bin') UBINGRP=ifdef(`confUBINGRP', `confUBINGRP', `bin') UBINMODE=ifdef(`confUBINMODE', `confUBINMODE', `555') # Setuid binary ownership/permissions SBINOWN=ifdef(`confSBINOWN', `confSBINOWN', `root') SBINGRP=ifdef(`confSBINGRP', `confSBINGRP', `bin') SBINMODE=ifdef(`confSBINMODE', `confSBINMODE', `4555') # Setgid binary ownership/permissions GBINOWN=ifdef(`confGBINOWN', `confGBINOWN', `root') GBINGRP=ifdef(`confGBINGRP', `confGBINGRP', `smmsp') GBINMODE=ifdef(`confGBINMODE', `confGBINMODE', `2555') # owner of MSP queue MSPQOWN=ifdef(`confMSPQOWN', `confMSPQOWN', `smmsp') # MTA binary ownership/permissions MBINOWN=ifdef(`confMBINOWN', `confMBINOWN', `root') MBINGRP=ifdef(`confMBINGRP', `confMBINGRP', `bin') MBINMODE=ifdef(`confMBINMODE', `confMBINMODE', `550') # Library ownership/permissions LIBOWN=ifdef(`confLIBOWN', `confLIBOWN', `root') LIBGRP=ifdef(`confLIBGRP', `confLIBGRP', `bin') LIBMODE=ifdef(`confLIBMODE', `confLIBMODE', `0444') # Include file ownership/permissions INCOWN=ifdef(`confINCOWN', `confINCOWN', `root') INCGRP=ifdef(`confINCGRP', `confINCGRP', `bin') INCMODE=ifdef(`confINCMODE', `confINCMODE', `0444') dk-milter-1.0.0.dfsg/devtools/M4/UNIX/footer.m40000644000175000017500000000106506716575343020550 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: footer.m4,v 8.2 1999/05/13 16:16:35 gshapiro Exp $ # divert(0)dnl ################ Dependency scripts include(confBUILDTOOLSDIR/M4/depend/ifdef(`confDEPEND_TYPE', `confDEPEND_TYPE', `generic').m4)dnl ################ End of dependency scripts dk-milter-1.0.0.dfsg/devtools/M4/UNIX/sm-test.m40000644000175000017500000000154507426551177020647 0ustar madhackmadhackdivert(-1) # # Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # Compile/run a test program for libsm. # # $Id: sm-test.m4,v 1.7 2002/02/01 17:38:07 ca Exp $ # define(`smtest', `bldPUSH_TARGET($1)dnl bldLIST_PUSH_ITEM(`bldC_PRODUCTS', $1)dnl bldPUSH_CLEAN_TARGET($1`-clean')dnl divert(bldTARGETS_SECTION) $1`'SRCS=$1.c $1: ${BEFORE} $1.o ifdef(`confREQUIRE_LIBSM', `libsm.a') ${CC} -o $1 ${LDOPTS} ${LIBDIRS} $1.o ifdef(`confREQUIRE_LIBSM', `libsm.a') ${LIBS} ifelse(len(X`'$2), `1', `', ` @echo ============================================================ ./$1 @echo ============================================================') $1-clean: rm -f $1 $1.o divert(0)') dk-milter-1.0.0.dfsg/devtools/M4/UNIX/all.m40000644000175000017500000000630410444067423020007 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999-2000, 2006 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: all.m4,v 8.21 2006/06/14 20:18:27 ca Exp $ # divert(0)dnl ALL=${BEFORE} ${LINKS} bldTARGETS all: ${ALL} clean: bldCLEAN_TARGETS define(`bldADD_SRC', ${$1SRCS} )dnl SRCS=bldFOREACH(`bldADD_SRC(', bldC_PRODUCTS) define(`bldADD_OBJS', ${$1OBJS} )dnl OBJS=bldFOREACH(`bldADD_OBJS(', bldC_PRODUCTS) ifdef(`bldCHECK_PROGRAMS',`dnl check_PROGRAMS=bldCHECK_PROGRAMS') ifdef(`bldCHECK_TARGETS',`dnl TESTS=bldCHECK_TARGETS') VPATH=${srcdir} changequote([[, ]]) check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; \ list='$(TESTS)'; \ srcdir=$(srcdir); export srcdir; \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ echo "XPASS: $$tst"; \ ;; \ *) \ echo "PASS: $$tst"; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ echo "XFAIL: $$tst"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ echo "FAIL: $$tst"; \ ;; \ esac; \ fi; \ done; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="All $$all tests passed"; \ else \ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all tests failed"; \ else \ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ fi; \ fi; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes"; \ test "$$failed" -eq 0; \ fi changequote(`, ') check-am: all $(MAKE) $(check_PROGRAMS) $(MAKE) check-TESTS check: check-am define(`bldADD_SRC_CHK', ${$1SRCS_CHK} )dnl SRCS_CHK=bldFOREACH(`bldADD_SRC_CHK(', bldC_CHECKS) define(`bldADD_OBJS_CHK', ${$1OBJS_CHK} )dnl OBJS_CHK=bldFOREACH(`bldADD_OBJS(', bldC_CHECKS) ifdef(`bldNO_INSTALL', `divert(-1)') install: bldINSTALL_TARGETS install-strip: bldINSTALL_TARGETS ifdef(`bldSTRIP_TARGETS', `bldSTRIP_TARGETS') ifdef(`bldNO_INSTALL', `divert(0)') ifdef(`confREQUIRE_SM_OS_H',` ifdef(`confSM_OS_HEADER', `sm_os.h: ${SRCDIR}/inc`'lude/sm/os/confSM_OS_HEADER.h ${RM} ${RMOPTS} sm_os.h ${LN} ${LNOPTS} ${SRCDIR}/inc`'lude/sm/os/confSM_OS_HEADER.h sm_os.h', `sm_os.h: ${CP} /dev/null sm_os.h')') divert(bldDEPENDENCY_SECTION) ################ Dependency scripts include(confBUILDTOOLSDIR/M4/depend/ifdef(`confDEPEND_TYPE', `confDEPEND_TYPE', `generic').m4)dnl ################ End of dependency scripts divert(0) dk-milter-1.0.0.dfsg/devtools/M4/UNIX/manpage.m40000644000175000017500000000724110500114563020637 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: manpage.m4,v 8.15 2006/09/07 22:13:07 ca Exp $ # divert(0)dnl define(`bldGET_MAN_SOURCE_NUM', `substr($1, eval(len($1) - 1))'dnl )dnl define(`bldGET_MAN_BASE_NAME', `substr($1, 0, eval(len($1) - 2))'dnl )dnl ifdef(`confNO_MAN_BUILD',, ` bldPUSH_TARGET(`${MANPAGES}') bldPUSH_INSTALL_TARGET(`install-docs')') bldLIST_PUSH_ITEM(`bldMAN_PAGES', `bldSOURCES')dnl MANOWN= ifdef(`confMANOWN', `confMANOWN', `bin') MANGRP= ifdef(`confMANGRP', `confMANGRP', `bin') MANMODE=ifdef(`confMANMODE', `confMANMODE', `444') MANROOT=ifdef(`confMANROOT', `confMANROOT', `/usr/share/man/cat') MANROOTMAN=ifdef(`confMANROOTMAN', `confMANROOTMAN', `/usr/share/man/man') MAN1= ${MANROOT}ifdef(`confMAN1', `confMAN1', `1') MAN1MAN=${MANROOTMAN}ifdef(`confMAN1', `confMAN1', `1') MAN1EXT=ifdef(`confMAN1EXT', `confMAN1EXT', `1') MAN1SRC=ifdef(`confMAN1SRC', `confMAN1SRC', `0') MAN3= ${MANROOT}ifdef(`confMAN3', `confMAN3', `3') MAN3MAN=${MANROOTMAN}ifdef(`confMAN3', `confMAN3', `3') MAN3EXT=ifdef(`confMAN3EXT', `confMAN3EXT', `3') MAN3SRC=ifdef(`confMAN3SRC', `confMAN3SRC', `0') MAN4= ${MANROOT}ifdef(`confMAN4', `confMAN4', `4') MAN4MAN=${MANROOTMAN}ifdef(`confMAN4', `confMAN4', `4') MAN4EXT=ifdef(`confMAN4EXT', `confMAN4EXT', `4') MAN4SRC=ifdef(`confMAN4SRC', `confMAN4SRC', `0') MAN5= ${MANROOT}ifdef(`confMAN5', `confMAN5', `5') MAN5MAN=${MANROOTMAN}ifdef(`confMAN5', `confMAN5', `5') MAN5EXT=ifdef(`confMAN5EXT', `confMAN5EXT', `5') MAN5SRC=ifdef(`confMAN5SRC', `confMAN5SRC', `0') MAN8= ${MANROOT}ifdef(`confMAN8', `confMAN8', `8') MAN8MAN=${MANROOTMAN}ifdef(`confMAN8', `confMAN8', `8') MAN8EXT=ifdef(`confMAN8EXT', `confMAN8EXT', `8') MAN8SRC=ifdef(`confMAN8SRC', `confMAN8SRC', `0') define(`bldMAN_TARGET_NAME', `bldGET_MAN_BASE_NAME($1).${MAN`'bldGET_MAN_SOURCE_NUM($1)`SRC}' 'dnl )dnl MANPAGES= bldFOREACH(`bldMAN_TARGET_NAME(', `bldMAN_PAGES') divert(bldTARGETS_SECTION) define(`bldMAN_BUILD_CMD', `bldGET_MAN_BASE_NAME($1).${MAN`'bldGET_MAN_SOURCE_NUM($1)`SRC}': bldGET_MAN_BASE_NAME($1).bldGET_MAN_SOURCE_NUM($1) ${NROFF} ${MANDOC} bldGET_MAN_BASE_NAME($1).bldGET_MAN_SOURCE_NUM($1) > bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}' || ${CP} bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}'.dist bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}'' )dnl bldFOREACH(`bldMAN_BUILD_CMD(', `bldMAN_PAGES') install-docs: ${MANPAGES} ifdef(`confNO_MAN_INSTALL', `divert(-1)', `dnl') define(`bldMAN_INSTALL_CMD', `ifdef(`confDONT_INSTALL_CATMAN', `dnl', ` ifdef(`confMKDIR', `if [ ! -d ${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC} ]; then confMKDIR -p ${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}; else :; fi ') ${INSTALL} -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} bldGET_MAN_BASE_NAME($1).`${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}' `${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)}/bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`EXT}'') ifdef(`confINSTALL_RAWMAN', ` ifdef(`confMKDIR', `if [ ! -d ${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)`MAN} ]; then confMKDIR -p ${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)`MAN}; else :; fi ') ${INSTALL} -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} bldGET_MAN_BASE_NAME($1).bldGET_MAN_SOURCE_NUM($1) `${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)`MAN}'/bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`EXT}'', `dnl')' )dnl bldFOREACH(`bldMAN_INSTALL_CMD(', `bldMAN_PAGES') ifdef(`confNO_MAN_INSTALL', `divert(0)', `dnl') divert(0) dk-milter-1.0.0.dfsg/devtools/M4/UNIX/smlib.m40000644000175000017500000000132107131423347020337 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: smlib.m4,v 8.3 2000/07/07 18:52:23 dmoen Exp $ # divert(0)dnl define(`confLIBEXT', `a')dnl define(`bldPUSH_SMLIB', `bldPUSH_TARGET(bldABS_OBJ_DIR`/lib$1/lib$1.a') bldPUSH_SMDEPLIB(bldABS_OBJ_DIR`/lib$1/lib$1.a') PREPENDDEF(`confLIBS', bldABS_OBJ_DIR`/lib$1/lib$1.a') divert(bldTARGETS_SECTION) bldABS_OBJ_DIR/lib$1/lib$1.a: (cd ${SRCDIR}/lib$1; sh Build ${SENDMAIL_BUILD_FLAGS}) divert ')dnl dk-milter-1.0.0.dfsg/devtools/M4/UNIX/executable.m40000644000175000017500000000346510511366514021363 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999, 2001, 2006 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: executable.m4,v 8.24 2006/10/06 05:44:44 ca Exp $ # divert(0)dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/links.m4')dnl bldLIST_PUSH_ITEM(`bldC_PRODUCTS', bldCURRENT_PRODUCT)dnl bldPUSH_TARGET(bldCURRENT_PRODUCT)dnl bldPUSH_INSTALL_TARGET(`install-'bldCURRENT_PRODUCT)dnl bldPUSH_CLEAN_TARGET(bldCURRENT_PRODUCT`-clean')dnl bldPUSH_ALL_SRCS(bldCURRENT_PRODUCT`SRCS')dnl bldPUSH_STRIP_TARGET(`strip-'bldCURRENT_PRODUCT)dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/defines.m4') divert(bldTARGETS_SECTION) bldCURRENT_PRODUCT: ${bldCURRENT_PRODUCT`OBJS'} ${bldCURRENT_PRODUCT`SMDEPLIBS'} ${CCLINK} -o bldCURRENT_PRODUCT ${LDOPTS} ${LIBDIRS} ${bldCURRENT_PRODUCT`OBJS'} ${LIBS} ifdef(`bldLINK_SOURCES', `bldMAKE_SOURCE_LINKS(bldLINK_SOURCES)') ifdef(`bldNO_INSTALL', , `install-`'bldCURRENT_PRODUCT: bldCURRENT_PRODUCT ifdef(`bldTARGET_INST_DEP', `bldTARGET_INST_DEP') ifdef(`confMKDIR', `if [ ! -d ${DESTDIR}${bldINSTALL_DIR`'BINDIR} ]; then confMKDIR -p ${DESTDIR}${bldINSTALL_DIR`'BINDIR}; else :; fi ') ${INSTALL} -c -o ${bldBIN_TYPE`'BINOWN} -g ${bldBIN_TYPE`'BINGRP} -m ${bldBIN_TYPE`'BINMODE} bldCURRENT_PRODUCT ${DESTDIR}${bldINSTALL_DIR`'BINDIR} ifdef(`bldTARGET_LINKS', `bldMAKE_TARGET_LINKS(${bldINSTALL_DIR`'BINDIR}/bldCURRENT_PRODUCT, ${bldCURRENT_PRODUCT`'TARGET_LINKS})')') strip-`'bldCURRENT_PRODUCT: bldCURRENT_PRODUCT ${STRIP} ${STRIPOPTS} ${DESTDIR}${bldINSTALL_DIR`'BINDIR}`'/bldCURRENT_PRODUCT bldCURRENT_PRODUCT-clean: rm -f ${OBJS} bldCURRENT_PRODUCT ${MANPAGES} divert(0) dk-milter-1.0.0.dfsg/devtools/M4/UNIX/check.m40000644000175000017500000000160310474700346020312 0ustar madhackmadhackdivert(-1) # # Copyright (c) 2006 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # Compile/run a test program. # # $Id: check.m4,v 8.5 2006/08/28 23:48:54 ca Exp $ # define(`smcheck', `dnl ifelse(X`'$2, `X', `', `ifelse(index($2, `run'), `-1', `', `dnl bldLIST_PUSH_ITEM(`bldCHECK_TARGETS', $1)dnl ')') ifelse(X`'$2, `X', `', `ifelse(index($2, `compile'), `-1', `', `dnl bldLIST_PUSH_ITEM(`bldC_CHECKS', $1)dnl bldLIST_PUSH_ITEM(`bldCHECK_PROGRAMS', $1)dnl bldPUSH_CLEAN_TARGET($1`-clean')dnl divert(bldTARGETS_SECTION) $1`'SRCS=$1.c $1: ${BEFORE} $1.o ifdef(`confCHECK_LIBS', `confCHECK_LIBS') ${CC} -o $1 ${LDOPTS} ${LIBDIRS} $1.o ifdef(`confCHECK_LIBS', `confCHECK_LIBS') ${LIBS} $1-clean: rm -f $1 $1.o')') divert(0)') dk-milter-1.0.0.dfsg/devtools/M4/UNIX/library.m40000644000175000017500000000255410477400265020707 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999-2001, 2006 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: library.m4,v 8.11 2006/09/05 22:56:53 ca Exp $ # divert(0)dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/links.m4')dnl bldLIST_PUSH_ITEM(`bldC_PRODUCTS', bldCURRENT_PRODUCT)dnl bldPUSH_TARGET(bldCURRENT_PRODUCT`.a')dnl bldPUSH_INSTALL_TARGET(`install-'bldCURRENT_PRODUCT)dnl bldPUSH_CLEAN_TARGET(bldCURRENT_PRODUCT`-clean')dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/defines.m4') divert(bldTARGETS_SECTION) bldCURRENT_PRODUCT.a: ${BEFORE} ${bldCURRENT_PRODUCT`OBJS'} ${AR} ${AROPTS} bldCURRENT_PRODUCT.a ${bldCURRENT_PRODUCT`OBJS'} ${RANLIB} ${RANLIBOPTS} bldCURRENT_PRODUCT.a ifdef(`bldLINK_SOURCES', `bldMAKE_SOURCE_LINKS(bldLINK_SOURCES)') install-`'bldCURRENT_PRODUCT: bldCURRENT_PRODUCT.a ifdef(`bldINSTALLABLE', ` ifdef(`confMKDIR', `if [ ! -d ${DESTDIR}${bldINSTALL_DIR`'LIBDIR} ]; then confMKDIR -p ${DESTDIR}${bldINSTALL_DIR`'LIBDIR}; else :; fi ') ${INSTALL} -c -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} bldCURRENT_PRODUCT.a ${DESTDIR}${LIBDIR}') bldCURRENT_PRODUCT-clean: rm -f ${OBJS} bldCURRENT_PRODUCT.a ${MANPAGES} divert(0) dk-milter-1.0.0.dfsg/devtools/M4/UNIX/links.m40000644000175000017500000000120206746505044020355 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: links.m4,v 8.5 1999/07/25 03:53:08 gshapiro Exp $ # divert(0)dnl define(`bldMAKE_SOURCE_LINK', `$1: ${SRCDIR}/$1 -ln -s ${SRCDIR}/$1 $1' )dnl define(`bldMAKE_SOURCE_LINKS', `bldFOREACH(`bldMAKE_SOURCE_LINK(', $1)'dnl )dnl define(`bldMAKE_TARGET_LINKS', ` for i in $2; do \ rm -f $$i; \ ln -s $1 $$i; \ done' )dnl dk-milter-1.0.0.dfsg/devtools/M4/string.m40000644000175000017500000000102206716575341017764 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: string.m4,v 8.2 1999/05/13 16:16:33 gshapiro Exp $ # divert(0)dnl define(`bldRINDEX', `ifelse(index($1, $2), `-1', `-1', `eval(index($1, $2) + bldRINDEX(substr($1, eval(index($1, $2) + 1)), $2) + 1)')'dnl )dnl dk-milter-1.0.0.dfsg/devtools/M4/switch.m40000644000175000017500000000315107073155502017752 0ustar madhackmadhackdivert(-1) # # Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: switch.m4,v 8.16 2000/04/06 18:45:22 peterh Exp $ # divert(0)dnl include(confBUILDTOOLSDIR`/M4/string.m4')dnl include(confBUILDTOOLSDIR`/M4/list.m4')dnl include(confBUILDTOOLSDIR`/M4/subst_ext.m4')dnl define(`bldDEPENDENCY_SECTION', `3')dnl define(`bldTARGETS_SECTION', `6')dnl define(`bldPUSH_TARGET', `bldLIST_PUSH_ITEM(`bldTARGETS', `$1')'dnl )dnl define(`bldPUSH_INSTALL_TARGET', `bldLIST_PUSH_ITEM(`bldINSTALL_TARGETS', `$1')'dnl )dnl define(`bldPUSH_CLEAN_TARGET', `bldLIST_PUSH_ITEM(`bldCLEAN_TARGETS', `$1')'dnl )dnl define(`bldPUSH_ALL_SRCS', `bldLIST_PUSH_ITEM(`bldALL_SRCS', `$1')'dnl )dnl define(`bldPUSH_SMDEPLIB', `bldLIST_PUSH_ITEM(`bldSMDEPLIBS', `$1')'dnl )dnl define(`bldM4_TYPE_DIR',ifdef(`confNT', `NT', ``UNIX''))dnl define(`bldPUSH_STRIP_TARGET', `bldLIST_PUSH_ITEM(`bldSTRIP_TARGETS', `$1')'dnl )dnl define(`bldPRODUCT_START', `define(`bldCURRENT_PRODUCT', `$2')dnl define(`bldCURRENT_PRD', translit(`$2', `.', `_'))dnl define(`bldPRODUCT_TYPE', `$1')dnl' )dnl define(`bldPRODUCT_END', `include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/'bldPRODUCT_TYPE`.m4')' )dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/smlib.m4')dnl define(`bldFINISH', ifdef(`bldDONT_INCLUDE_ALL', ,``include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/all.m4')'')dnl undivert(bldTARGETS_SECTION)dnl )dnl dk-milter-1.0.0.dfsg/devtools/M4/header.m40000644000175000017500000000223007522327402017675 0ustar madhackmadhack# # Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # Definitions for Makefile construction for sendmail # # $Id: header.m4,v 8.27 2002/08/01 21:58:26 gshapiro Exp $ # changecom(^A) undefine(`format') undefine(`hpux') undefine(`unix') ifdef(`pushdef', `', `errprint(`You need a newer version of M4, at least as new as System V or GNU') include(NoSuchFile)') define(`confABI', `') define(`confCC', `cc') define(`confSHELL', `/bin/sh') define(`confBEFORE', `') define(`confLIBDIRS', `') define(`confINCDIRS', `') define(`confLIBSEARCH', `db bind resolv 44bsd') define(`confLIBSEARCHPATH', `/lib /usr/lib /usr/shlib') define(`confSITECONFIG', `site.config') define(`confBUILDBIN', `${SRCDIR}/devtools/bin') define(`confRANLIB', `echo') define(`PUSHDIVERT', `pushdef(`__D__', divnum)divert($1)') define(`POPDIVERT', `divert(__D__)popdef(`__D__')') define(`APPENDDEF', `define(`$1', ifdef(`$1', `$1 $2', `$2'))') define(`PREPENDDEF', `define(`$1', ifdef(`$1', `$2 $1', `$2'))') dk-milter-1.0.0.dfsg/devtools/Site/0000755000175000017500000000000010766324730016637 5ustar madhackmadhackdk-milter-1.0.0.dfsg/devtools/Site/site.config.m4.sample0000644000175000017500000000716307610047705022576 0ustar madhackmadhackdnl ##################################################################### dnl ### ### dnl ### This is a sample "site.config.m4". It is not intended to be ### dnl ### used directly. It is intended to illustrate, by example, ### dnl ### how to make your own site configuration file. ### dnl ### ### dnl ##################################################################### dnl $Id: site.config.m4.sample,v 1.1 2003/01/11 17:09:25 ca Exp $ dnl ##################################################################### dnl ### ### dnl ### This illustrates how to turn off an option that is defined by ### dnl ### default. Check your compiler documentation to make sure that ### dnl ### it supports "-U". ### dnl ### ### dnl ##################################################################### dnl ### Changes to disable the default NIS support APPENDDEF(`confENVDEF', `-UNIS') dnl ##################################################################### dnl ### ### dnl ### The next group of statements illustrates how to add support ### dnl ### for a particular map class. If you have not heard of this ### dnl ### particular map type, then you probably don't need it. ### dnl ### ### dnl ### Note that the map define goes in confMAPDEF, and that any ### dnl ### special library must be defined. Note, also that include ### dnl ### directories and library directories must also be defined if ### dnl ### they are places that your compiler does not automatically ### dnl ### search. ### dnl ### ### dnl ##################################################################### dnl ### Changes for PH_MAP support. APPENDDEF(`confMAPDEF',`-DPH_MAP') APPENDDEF(`confLIBS', `-lphclient') APPENDDEF(`confINCDIRS', `-I/opt/nph/include') APPENDDEF(`confLIBDIRS', `-L/opt/nph/lib') dnl ##################################################################### dnl ### ### dnl ### The next group illustrates how to add support for a compile ### dnl ### time option. In addition to the compile time define, any ### dnl ### required libraries must be given. In addition, include and ### dnl ### library directories must be given if they are not standardly ### dnl ### searched by your compiler. ### dnl ### ### dnl ### Note the "-R" for the library directory. On some systems, ### dnl ### that can be used to tell the run time loader where to find ### dnl ### dynamic libraries (shared objects). Check your system ### dnl ### documentation (man ld) to see if this is appropriate for your ### dnl ### system. ### dnl ### ### dnl ##################################################################### dnl ### Changes for STARTTLS support APPENDDEF(`confENVDEF',`-DSTARTTLS') APPENDDEF(`confLIBS', `-lssl -lcrypto') APPENDDEF(`confLIBDIRS', `-L/usr/local/ssl/lib -R/usr/local/ssl/lib') APPENDDEF(`confINCDIRS', `-I/usr/local/ssl/include') dk-milter-1.0.0.dfsg/devtools/Site/README0000644000175000017500000000144607434265234017525 0ustar madhackmadhackThe Build script will look for the default site configuration files in this directory. Build will include the following files if they are present in this directory: site.config.m4 site.OS.$SENDMAIL_SUFFIX.m4 site.OS.m4 site.post.m4 OS is the name of the operating system file selected from the devtools/OS directory. SENDMAIL_SUFFIX is a user environment variable which can be used to further distinguish between site configuration files in this directory. If set, it will also be used in generating the obj.* directory name. Notice: if any of the above files is changed, the -c flag must be specified with the Build command, otherwise those changes will have no effect. See the README in the devtools directory for more information. $Revision: 8.8 $, Last updated $Date: 2002/02/18 20:57:00 $ dk-milter-1.0.0.dfsg/INSTALL0000644000175000017500000001177410627641427015140 0ustar madhackmadhack Installing dk-filter COMPILING ========= Requires sendmail v8.13.0 or later, for required milter protocol enhancements. To build this package you must first have installed or at least have available the OpenSSL package and libmilter. The former is available from http://www.openssl.org or in package form from your vendor; the latter is part of the sendmail Open Source distribution and can be built and installed from there. Steps to compiling the library and the filter: (1) Download the source from Sourceforge (project name "dk-milter"). (2) Unpack the tarball. (3) Change to the release directory (dk-milter-). (4) Either: (a) Copy site.config.m4.dist to devtools/Site/site.config.m4 and follow instructions in there for adjusting compile-time feature and path settings. -OR- (b) Copy devtools/Site/site.config.m4 from a prior build. (5) Type "sh Build". INSTALLING ========== (1) Configure sendmail: (a) Choose a socket at which the MTA and the filter will rendezvous (see the documentation in libmilter for details) (b) Add a line like this example to your sendmail.mc using your desired socket specification: INPUT_MAIL_FILTER(`dk-filter', `S=inet:8891@localhost') (c) Rebuild your sendmail.cf in the usual way (2) Choose a selector name. Current convention is to use the hostname (hostname only, not the fully-qualified domain name) of the host that will be providing the service, but you are free to choose any name you wish, especially if you have a selector assignment scheme in mind. (3) Either: (a) Run the script gentxt.csh. This will generate a public and private key in PEM format and output a TXT record appropriate for insertion into your DNS zone file. Insert it in your zone file and reload your DNS system so the data is published. -OR- (b) Manually generate a public and private key: (i) % openssl genrsa -out rsa.private 512 (ii) % openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM (iii) Add a TXT DNS record containing the base64 encoding of your public key, which is everything between the BEGIN and END lines in the rsa.public file generated above, with spaces and newlines removed. It should be in this form: "g=; k=rsa; t=y; p=MFwwDQYJ...AwEAAQ==" ...using, of course, your own public key's base64 data. The name of the TXT record should be SELECTOR._domainkey.example.com (where "SELECTOR" is the name you chose and "example.com" is your domain name). You might want to set a short TTL on this record. Reload your nameserver so that the record gets published. For a translation of the parameter and value pairs shown here, see the draft spec; basically this just announces an RSA public key and also declares that your site is using this key in test mode so nobody should take any real action based on success or failure of the use of this key to verify a message. (4) Store the private key in a safe place. We generally use a path like /var/db/domainkeys/SELECTOR.key.pem (where "SELECTOR" is the name you chose). (5) Start dk-filter. You will need at least the "-p" option. The current recommended set of command line options is: -l -p SOCKETSPEC -d DOMAIN -s KEYPATH -S SELECTOR ...where SOCKETSPEC is the socket you told sendmail to use above, DOMAIN is the domain or set of domains for which you want to sign mail, KEYPATH is the path to the private key file you generated, and SELECTOR is the selector name you picked. You can tack "-f" on there if you want it to run in the foreground instead of in the background as a daemon. (7) Restart sendmail. TESTING ======= To test, send a piece of e-mail through the MTA doing signing for your domain to sa-test@sendmail.net. It should be returned to you shortly showing your message in the body of a new message, including all of the header changes that were made in transit. The message you generated should appear there with a DomainKey-Signature: header added, containing the signature data your dk-filter added, and a DomainKey-Status: header which the testing machine's dk-filter added after verifying the signature. The value of this header should be "good". If it isn't, something in between has altered your message in a way that invalidated the signature. Perhaps you have other filters running which appended or modified a header. The reply from the test machine will also itself be signed, and in the headers of the reply you should see its signature and another DomainKey-Status: header, which should also read "good". Note also that as the DomainKeys standards are changing, so in place of a DomainKey-Status: header, you may see an Authentication-Results: header. In that case you're looking for "pass" instead of "good". Refer to the COMMON PROBLEMS section of the dk-filter/README for more information if your tests are not succeeding. $Id: INSTALL,v 1.9 2007/05/31 21:50:15 msk Exp $ dk-milter-1.0.0.dfsg/libar/0000755000175000017500000000000010766324725015171 5ustar madhackmadhackdk-milter-1.0.0.dfsg/libar/Makefile.m40000644000175000017500000000062710626055374017151 0ustar madhackmadhackdnl Build description for libar dnl dnl NO USER SERVICEABLE PARTS INSIDE dnl See the package README file for details. include(confBUILDTOOLSDIR`/M4/switch.m4') define(`confREQUIRE_LIBSM', `true') define(`confMT', `true') bldPRODUCT_START(`library', `libar') define(`bldSOURCES', `ar.c manual.c ') bldPRODUCT_END bldPRODUCT_START(`manpage', `ar') define(`bldSOURCES', `ar.3') bldPRODUCT_END bldFINISH dk-milter-1.0.0.dfsg/libar/ar.h0000644000175000017500000000354510756625700015747 0ustar madhackmadhack/* ** Copyright (c) 2004, 2005, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef _AR_H_ #define _AR_H_ #ifndef lint static char ar_h_id[] = "@(#)$Id: ar.h,v 1.10 2008/02/19 19:19:28 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include /* useful stuff */ #ifndef NULL # define NULL 0 #endif /* ! NULL */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* DATA TYPES */ struct ar_libhandle; typedef struct ar_libhandle * AR_LIB; struct ar_query; typedef struct ar_query * AR_QUERY; /* TYPES */ typedef void *ar_malloc_t(void *, size_t); typedef void ar_free_t(void *, void *); /* DEFINITIONS */ #define AR_FLAG_USETCP 0x01 /* use TCP instead of UDP */ #define AR_FLAG_DEAD 0x02 /* service now unavailable */ #define AR_STAT_ERROR (-1) /* error in transit */ #define AR_STAT_SUCCESS 0 /* reply available */ #define AR_STAT_NOREPLY 1 /* reply not available (yet) */ #define AR_STAT_EXPIRED 2 /* no reply, query expired */ #define QUERY_ERRNO_TOOBIG (-1) /* query too large */ #define QUERY_ERRNO_RETRIES (-2) /* too many retries */ #define AR_MAXTIMEOUT 10000000 /* max. allowed timeout (s) */ /* PROTOTYPES */ extern AR_QUERY ar_addquery(AR_LIB, char *, int, int, int, unsigned char *, size_t, int *, struct timeval *); extern int ar_cancelquery(AR_LIB, AR_QUERY); extern char *ar_strerror(int err); extern int ar_waitreply(AR_LIB, AR_QUERY, size_t *, struct timeval *); extern AR_LIB ar_init(ar_malloc_t *, ar_free_t *, void *, int); extern void ar_recycle(AR_LIB, AR_QUERY); extern int ar_resend(AR_LIB, AR_QUERY); extern void ar_setmaxretry(AR_LIB lib, int new, int *old); extern void ar_setretry(AR_LIB lib, struct timeval *new, struct timeval *old); extern int ar_shutdown(AR_LIB); #endif /* ! _AR_H_ */ dk-milter-1.0.0.dfsg/libar/README0000644000175000017500000000054610475655516016060 0ustar madhackmadhack$Id: README,v 1.5 2006/08/31 21:57:34 msk Exp $ INTRODUCTION ============ This is the development area for Sendmail's libar, which is a reusable (i.e. not tied to any particular package) asynchronous resolver. NOTES ===== o Uses pthreads, and thus may not be compatible with applications using other threading systems (state threads, event threads). dk-milter-1.0.0.dfsg/libar/manual.c0000644000175000017500000001325610756634413016616 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char manual_c_id[] = "@(#)$Id: manual.c,v 1.7 2008/02/19 20:16:11 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include #ifdef DARWIN # include #endif /* DARWIN */ #include #include #include #include #include /* macros */ #ifndef _PATH_RESCONF # define _PATH_RESCONF "/etc/resolv.conf" #endif /* ! _PATH_RESCONF */ #ifndef RES_RETRY # define RES_RETRY 4 #endif /* ! RES_RETRY */ #ifndef RES_TIMEOUT # define RES_TIMEOUT 5 #endif /* ! RES_TIMEOUT */ #define BUFRSZ 1024 #define SERVICE "domain" #define PROTOCOL "udp" /* ** AR_RES_PARSE -- read resolv.conf and determine the nameservers ** ** Parameters: ** nscount -- count of nameservers to load (in/out) ** out -- location of array to populate ** retry -- maximum retry count (returned) ** retrans -- retransmission timeout (returned) ** ** Return value: ** 0 on success, -1 on failure. ** ** Notes: ** Includes IPv6 support if AF_INET6 is defined. This presumes ** further that there's a "struct sockaddr_storage" defined ** in the system include files. I haven't seen anything yet ** yet that guarantees this is a valid assumption, but ** so far so good... */ int #ifdef AF_INET6 ar_res_parse(int *nscount, struct sockaddr_storage *out, int *retry, int *retrans) #else /* AF_INET6 */ ar_res_parse(int *nscount, struct sockaddr_in *out, int *retry, int *retrans) #endif /* AF_INET6 */ { int data; int ns = 0; FILE *f; char *p; char *q; char *r; struct servent *srv; char buf[BUFRSZ]; assert(out != NULL); assert(retry != NULL); assert(retrans != NULL); srv = getservbyname(SERVICE, PROTOCOL); if (srv == NULL) return -1; f = fopen(_PATH_RESCONF, "r"); if (f == NULL) { struct sockaddr *sa; struct sockaddr_in *sin; /* apply defaults */ #ifdef AF_INET6 sa = (struct sockaddr *) &out[0]; sin = (struct sockaddr_in *) sa; sin->sin_family = AF_INET; sin->sin_port = srv->s_port; sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); #else /* AF_INET6 */ out[0].sin_family = AF_INET; out[0].sin_port = srv->s_port; out[0].sin_addr.s_addr = htonl(INADDR_LOOPBACK); #endif /* AF_INET6 */ ns = 1; *nscount = ns; return 0; } clearerr(f); while (fgets(buf, sizeof buf, f) != NULL) { /* chomp at \n, #, or ; */ for (p = buf; *p != '\0'; p++) { if (*p == '\n' || *p == ';' || *p == '#') { *p = '\0'; break; } } /* now eat leading and trailing spaces */ data = 0; r = NULL; for (p = buf, q = buf; *p != '\0'; p++) { if (data == 0 && isascii(*p) && isspace(*p)) continue; data = 1; *q = *p; if (!(isascii(*p) && isspace(*p))) r = q; q++; } if (r != NULL) *(r + 1) = '\0'; /* use the data */ if (strncasecmp(buf, "nameserver", 10) == 0) { struct in_addr addr; #ifdef AF_INET6 struct in6_addr addr6; struct sockaddr *sa; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; #endif /* AF_INET6 */ for (p = &buf[10]; *p != '\0'; p++) { if (!isascii(*p) || !isspace(*p)) break; } if (*p == '\0') continue; #ifdef AF_INET6 sa = (struct sockaddr *) &out[ns]; if (inet_pton(AF_INET, p, (void *) &addr) == 1) { sin = (struct sockaddr_in *) sa; memcpy(&sin->sin_addr, &addr, sizeof sin->sin_addr); sin->sin_family = AF_INET; sin->sin_port = srv->s_port; ns++; } else if (inet_pton(AF_INET6, p, (void *) &addr6.s6_addr) == 1) { sin6 = (struct sockaddr_in6 *) sa; memcpy(&sin6->sin6_addr, &addr6.s6_addr, sizeof sin6->sin6_addr); sin6->sin6_family = AF_INET6; sin6->sin6_port = srv->s_port; ns++; } #else /* AF_INET6 */ addr = inet_addr(p); if (addr == INADDR_NONE) continue; memcpy(&out[ns].sin_addr.s_addr, &addr, sizeof out[ns].sin_addr.s_addr); out[ns].sin_family = AF_INET; out[ns].sin_port = srv->s_port; ns++; #endif /* AF_INET6 */ if (ns == *nscount) break; } } fclose(f); *retry = RES_RETRY; *retrans = RES_TIMEOUT; /* if no "nameserver" lines were found, add a default one */ if (ns == 0) { #ifdef AF_INET6 struct sockaddr *sa; struct sockaddr_in *sin; sa = (struct sockaddr *) &out[0]; sin = (struct sockaddr_in *) sa; sin->sin_family = AF_INET; sin->sin_port = srv->s_port; sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); #else /* AF_INET6 */ out[0].sin_family = AF_INET; out[0].sin_port = srv->s_port; out[0].sin_addr.s_addr = htonl(INADDR_LOOPBACK); #endif /* AF_INET6 */ ns = 1; } *nscount = ns; return 0; } #ifdef TEST int main() { int c; struct sockaddr *sa; struct sockaddr_in *sin; # ifdef AF_INET6 struct sockaddr_in6 *sin6; struct sockaddr_storage nsaddrs[MAXNS]; # else /* AF_INET6 */ struct sockaddr_in nsaddrs[MAXNS]; # endif /* AF_INET6 */ char buf[256]; memset(nsaddrs, '\0', sizeof nsaddrs); ar_res_parse(MAXNS, (void *) nsaddrs); for (c = 0; c < MAXNS; c++) { memset(buf, '\0', sizeof buf); sa = (struct sockaddr *) &nsaddrs[c]; switch (sa->sa_family) { case AF_INET: sin = (struct sockaddr_in *) &nsaddrs[c]; printf("IPv4: %s:%u\n", inet_ntop(AF_INET, (void *) &sin->sin_addr, buf, sizeof buf), ntohs(sin->sin_port)); break; # ifdef AF_INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *) &nsaddrs[c]; printf("IPv6: %s:%u\n", inet_ntop(AF_INET6, (void *) &sin6->sin6_addr, buf, sizeof buf), ntohs(sin6->sin6_port)); break; } # endif /* AF_INET6 */ } } #endif /* TEST */ dk-milter-1.0.0.dfsg/libar/ar.c0000644000175000017500000012102310756625700015732 0ustar madhackmadhack/* ** Copyright (c) 2004-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char ar_c_id[] = "@(#)$Id: ar.c,v 1.74 2008/02/19 19:19:28 msk Exp $"; #endif /* !lint */ /* OS stuff */ #if HPUX11 # define _XOPEN_SOURCE_EXTENDED #endif /* HPUX11 */ /* system includes */ #include #include #ifdef SOLARIS # include #endif /* SOLARIS */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* libsm includes */ #include #include /* important macros */ #ifndef MAXHOSTNAMELEN # define MAXHOSTNAMELEN 256 #endif /* ! MAXHOSTNAMELEN */ #ifndef MAXPACKET # define MAXPACKET 8192 #endif /* ! MAXPACKET */ #define QUERYLIMIT 32768 #ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ! MAX */ #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ #if !POLL && !KQUEUES # define SELECT 1 # define READ_READY(x, y) FD_ISSET((y), &(x)) #endif /* !POLL && !KQUEUES */ #ifndef MSG_WAITALL # define MSG_WAITALL 0 #endif /* ! MSG_WAITALL */ /* ar includes */ #include "ar.h" /* ** DATA TYPES */ struct ar_query { int q_depth; int q_flags; int q_class; int q_type; int q_id; int q_tries; size_t q_buflen; size_t q_replylen; int * q_errno; unsigned char * q_buf; pthread_cond_t q_reply; pthread_mutex_t q_lock; struct ar_query * q_next; struct timeval q_timeout; struct timeval q_sent; char q_name[MAXHOSTNAMELEN + 1]; }; #ifdef AF_INET6 typedef struct sockaddr_storage SOCKADDR; #else /* AF_INET6 */ typedef struct sockaddr_in SOCKADDR; #endif /* AF_INET6 */ struct ar_libhandle { int ar_nsfd; int ar_nsfdpf; int ar_control[2]; int ar_flags; int ar_nscount; int ar_nsidx; int ar_deaderrno; int ar_resend; int ar_retries; size_t ar_tcpbuflen; size_t ar_writelen; size_t ar_querybuflen; pthread_t ar_dispatcher; pthread_mutex_t ar_lock; unsigned char * ar_querybuf; unsigned char * ar_tcpbuf; SOCKADDR * ar_nsaddrs; void * (*ar_malloc) (void *closure, size_t nbytes); void (*ar_free) (void *closure, void *p); void * ar_closure; struct ar_query * ar_pending; /* to be sent (queue head) */ struct ar_query * ar_pendingtail; /* to be sent (queue tail) */ struct ar_query * ar_queries; /* awaiting replies (head) */ struct ar_query * ar_queriestail; /* awaiting replies (tail) */ struct ar_query * ar_recycle; /* recyclable queries */ struct timeval ar_retry; /* retry interval */ }; /* ** DEFINITIONS */ #define QUERY_INFINIWAIT 0x01 /* infinite wait */ #define QUERY_REPLY 0x02 /* reply stored */ #define QUERY_NOREPLY 0x04 /* query expired */ #define QUERY_ERROR 0x08 /* error sending */ #define QUERY_RESEND 0x10 /* resend pending */ /* ** PROTOTYPES */ static void *ar_malloc(AR_LIB, size_t); static void ar_free(AR_LIB lib, void *ptr); static int ar_res_init(AR_LIB); /* ** LIBRARY GLOBALS */ static struct __res_state ar_res; /* ** ========================= PRIVATE FUNCTIONS ========================= */ /* ** AR_MALLOC -- allocate memory ** ** Parameters: ** lib -- library handle ** bytes -- how many bytes to get ** ** Return value: ** Pointer to newly available memory, or NULL on error. */ static void * ar_malloc(AR_LIB lib, size_t bytes) { assert(lib != NULL); if (lib->ar_malloc != NULL) return ar_malloc(lib->ar_closure, bytes); else return malloc(bytes); } /* ** AR_FREE -- release memory ** ** Parameters: ** lib -- library handle ** ptr -- pointer to memory to release ** ** Return value: ** None. */ static void ar_free(AR_LIB lib, void *ptr) { assert(lib != NULL); assert(ptr != NULL); if (lib->ar_free != NULL) ar_free(lib->ar_closure, ptr); else free(ptr); } /* ** AR_SMASHQUEUE -- smash everything in a list of queue handles ** ** Parameters: ** q -- query at the head of the list to clobber ** ** Return value: ** None. ** ** Notes: ** Very destructive. */ static void ar_smashqueue(AR_LIB lib, AR_QUERY q) { AR_QUERY cur; AR_QUERY next; assert(lib != NULL); if (q == NULL) return; cur = q; while (cur != NULL) { next = cur->q_next; ar_free(lib, cur); cur = next; } } /* ** AR_TIMELEFT -- given a start time and a duration, see how much is left ** ** Parameters: ** start -- start time ** length -- run time ** remain -- how much time is left (updated) ** ** Return value: ** None. ** ** Notes: ** If "start" is NULL, "length" is taken to be the end time. */ static void ar_timeleft(struct timeval *start, struct timeval *length, struct timeval *remain) { struct timeval now; struct timeval end; assert(length != NULL); assert(remain != NULL); (void) gettimeofday(&now, NULL); if (start == NULL) { memcpy(&end, length, sizeof end); } else { end.tv_sec = start->tv_sec + length->tv_sec; end.tv_usec = start->tv_usec + length->tv_usec; end.tv_sec += end.tv_usec / 1000000; end.tv_usec = end.tv_usec % 1000000; } if (now.tv_sec > end.tv_sec || (now.tv_sec == end.tv_sec && now.tv_usec > end.tv_usec)) { remain->tv_sec = 0; remain->tv_usec = 0; } else { remain->tv_sec = end.tv_sec - now.tv_sec; if (end.tv_usec < now.tv_usec) { remain->tv_sec--; remain->tv_usec = end.tv_usec - now.tv_usec + 1000000; } else { remain->tv_usec = end.tv_usec - now.tv_usec; } } } /* ** AR_ELAPSED -- determine whether or not a certain amount of time has ** elapsed ** ** Parameters: ** start -- start time ** length -- run time ** ** Return value: ** TRUE iff length has elapsed since start. */ static bool ar_elapsed(struct timeval *start, struct timeval *length) { struct timeval now; struct timeval tmp; assert(start != NULL); assert(length != NULL); (void) gettimeofday(&now, NULL); tmp.tv_sec = start->tv_sec + length->tv_sec; tmp.tv_usec = start->tv_usec + length->tv_usec; if (tmp.tv_usec > 1000000) { tmp.tv_usec -= 1000000; tmp.tv_sec += 1; } if (tmp.tv_sec < now.tv_sec || (tmp.tv_sec == now.tv_sec && tmp.tv_usec < now.tv_usec)) return TRUE; return FALSE; } /* ** AR_UNDOT -- remove a trailing dot if there is one ** ** Parameters: ** str -- string to modify ** ** Return value: ** None. */ static void ar_undot(char *str) { char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (*p == '.' && *(p + 1) == '\0') { *p = '\0'; break; } } } /* ** AR_EXPIRED -- see if a query has expired ** ** Parameters: ** q -- query being checked ** ** Return value: ** 1 if the query has expired, 0 otherwise */ static int ar_expired(AR_QUERY q) { struct timeval now; assert(q != NULL); if (q->q_timeout.tv_sec == 0 || (q->q_flags & QUERY_INFINIWAIT) != 0) return 0; (void) gettimeofday(&now, NULL); if (q->q_timeout.tv_sec < now.tv_sec) return 1; if (q->q_timeout.tv_sec == now.tv_sec && q->q_timeout.tv_usec < now.tv_usec) return 1; return 0; } /* ** AR_ALLDEAD -- mark all pending and active queries dead ** ** Parameters: ** lib -- library handle ** ** Return value: ** None. */ static void ar_alldead(AR_LIB lib) { AR_QUERY q; assert(lib != NULL); /* tack the pending list to the end of the active list */ if (lib->ar_pending != NULL) { if (lib->ar_queriestail != NULL) { lib->ar_queriestail->q_next = lib->ar_pending; } else { lib->ar_queries = lib->ar_pending; } lib->ar_queriestail = lib->ar_pendingtail; lib->ar_pending = NULL; lib->ar_pendingtail = NULL; } /* mark everything with QUERY_ERROR and wake them all up */ for (q = lib->ar_queries; q != NULL; q = q->q_next) { pthread_mutex_lock(&q->q_lock); q->q_flags |= (QUERY_NOREPLY|QUERY_ERROR); pthread_cond_signal(&q->q_reply); pthread_mutex_unlock(&q->q_lock); } } /* ** AR_RECONNECT -- reconnect when TCP service dies ** ** Parameters: ** lib -- library handle ** ** Return value: ** TRUE iff reconnect was successful. ** ** Notes: ** If reconnection was impossible, all queries are marked with ** QUERY_ERROR and signalled immediately. ar_flags is marked with ** AR_FLAG_DEAD, preventing further calls to ar_addquery(). ** Assumes the caller does not currently hold ar_lock. */ static bool ar_reconnect(AR_LIB lib) { int c; int saveerrno; int nsnum; int socklen; struct sockaddr *sa; assert(lib != NULL); close(lib->ar_nsfd); lib->ar_nsfd = -1; lib->ar_nsfdpf = -1; /* try to connect to someone */ for (c = 0; c < lib->ar_nscount; c++) { nsnum = (c + lib->ar_nsidx) % lib->ar_nscount; sa = (struct sockaddr *) &lib->ar_nsaddrs[nsnum]; #ifdef AF_INET6 if (sa->sa_family == AF_INET6) socklen = sizeof(struct sockaddr_in6); else socklen = sizeof(struct sockaddr_in); #else /* AF_INET6 */ socklen = sizeof(struct sockaddr_in); #endif /* AF_INET6 */ lib->ar_nsfd = socket(sa->sa_family, SOCK_STREAM, 0); if (lib->ar_nsfd == -1) continue; lib->ar_nsfdpf = sa->sa_family; if (connect(lib->ar_nsfd, sa, socklen) == 0) return TRUE; close(lib->ar_nsfd); lib->ar_nsfd = -1; lib->ar_nsfdpf = -1; } saveerrno = errno; /* unable to reconnect; arrange to terminate */ pthread_mutex_lock(&lib->ar_lock); ar_alldead(lib); lib->ar_flags |= AR_FLAG_DEAD; lib->ar_deaderrno = saveerrno; pthread_mutex_unlock(&lib->ar_lock); return FALSE; } /* ** AR_REQUERY -- position an active query at the front of the pending queue ** ** Parameters: ** lib -- library handle ** query -- query to send ** ** Return value: ** None. ** ** Notes: ** Presumes the caller has acquired a lock on the "lib" handle. */ static void ar_requery(AR_LIB lib, AR_QUERY query) { AR_QUERY q; AR_QUERY last; assert(lib != NULL); assert(query != NULL); /* remove from active queries */ for (q = lib->ar_queries, last = NULL; q != NULL; last = q, q = q->q_next) { if (query == q) { if (last == NULL) { lib->ar_queries = q->q_next; if (lib->ar_queries == NULL) lib->ar_queriestail = NULL; } else { last->q_next = q->q_next; if (lib->ar_queriestail == q) lib->ar_queriestail = last; } if ((q->q_flags & QUERY_RESEND) != 0) lib->ar_resend--; } } /* insert at front of pending queue */ if (lib->ar_pending == NULL) { lib->ar_pending = query; lib->ar_pendingtail = query; query->q_next = NULL; } else { query->q_next = lib->ar_pending; lib->ar_pending = query; } } /* ** AR_REQUEUE -- arrange to re-send everything after a reconnect ** ** Parameters: ** lib -- library handle ** ** Return value: ** None. ** ** Notes: ** Jobs to retry get priority over currently pending jobs. ** Presumes the caller holds the lock in the library handle. */ static void ar_requeue(AR_LIB lib) { assert(lib != NULL); if (lib->ar_queries != NULL) { int maxfd; int status; fd_set wfds; AR_QUERY x = NULL; struct timeval stimeout; if (lib->ar_pending != NULL) { lib->ar_queriestail->q_next = lib->ar_pending; } else { lib->ar_pendingtail = lib->ar_queriestail; } lib->ar_pending = lib->ar_queries; lib->ar_queries = NULL; lib->ar_queriestail = NULL; #if SELECT /* XXX -- do this as ar_trywrite() or something */ maxfd = lib->ar_control[0]; FD_ZERO(&wfds); FD_SET(lib->ar_control[0], &wfds); stimeout.tv_sec = 0; stimeout.tv_usec = 0; status = select(maxfd + 1, NULL, &wfds, NULL, &stimeout); if (status == 1) (void) write(lib->ar_control[0], &x, sizeof x); #endif /* SELECT */ } } /* ** AR_SENDQUERY -- send a query ** ** Parameters: ** lib -- library handle ** query -- query to send ** ** Return value: ** None. */ static void ar_sendquery(AR_LIB lib, AR_QUERY query) { size_t n; HEADER hdr; assert(lib != NULL); assert(query != NULL); if (lib->ar_retries > 0 && query->q_tries == lib->ar_retries) { query->q_flags |= QUERY_ERROR; if (query->q_errno != NULL) *query->q_errno = QUERY_ERRNO_RETRIES; pthread_cond_signal(&query->q_reply); return; } for (;;) { #if (defined(__RES) && (__RES <= 19960801)) n = res_mkquery(QUERY, query->q_name, query->q_class, query->q_type, NULL, 0, NULL, lib->ar_querybuf, lib->ar_querybuflen); #else /* defined(__RES) && (__RES <= 19960801) */ n = res_nmkquery(&ar_res, QUERY, query->q_name, query->q_class, query->q_type, NULL, 0, NULL, lib->ar_querybuf, lib->ar_querybuflen); #endif /* defined(__RES) && (__RES <= 19960801) */ if (n != (size_t) -1) { lib->ar_writelen = n; break; } if (lib->ar_querybuflen >= QUERYLIMIT) { query->q_flags |= QUERY_ERROR; if (query->q_errno != NULL) *query->q_errno = QUERY_ERRNO_TOOBIG; pthread_cond_signal(&query->q_reply); return; } ar_free(lib, lib->ar_querybuf); lib->ar_querybuflen *= 2; lib->ar_querybuf = ar_malloc(lib, lib->ar_querybuflen); } memcpy(&hdr, lib->ar_querybuf, sizeof hdr); query->q_id = hdr.id; #ifdef DEBUG printf("*** SEND `%s' class=%d type=%d id=%d time=%d\n", query->q_name, query->q_class, query->q_type, hdr.id, time(NULL)); #endif /* DEBUG */ /* send it */ if ((lib->ar_flags & AR_FLAG_USETCP) != 0) { u_short len; struct iovec io[2]; len = htons(n); io[0].iov_base = (void *) &len; io[0].iov_len = sizeof len; io[1].iov_base = (void *) lib->ar_querybuf; io[1].iov_len = lib->ar_writelen; n = writev(lib->ar_nsfd, io, 2); } else { int nsnum; int socklen; struct sockaddr *sa; nsnum = query->q_tries % lib->ar_nscount; sa = (struct sockaddr *) &lib->ar_nsaddrs[nsnum]; /* change to the right family if needed */ if (sa->sa_family != lib->ar_nsfdpf) { close(lib->ar_nsfd); lib->ar_nsfdpf = -1; lib->ar_nsfd = socket(sa->sa_family, SOCK_DGRAM, 0); if (lib->ar_nsfd != -1) lib->ar_nsfdpf = sa->sa_family; } #ifdef AF_INET6 if (sa->sa_family == AF_INET6) socklen = sizeof(struct sockaddr_in6); else socklen = sizeof(struct sockaddr_in); #else /* AF_INET */ socklen = sizeof(struct sockaddr_in); #endif /* AF_INET */ n = sendto(lib->ar_nsfd, lib->ar_querybuf, lib->ar_writelen, 0, sa, socklen); } if (n == (size_t) -1) { query->q_flags |= QUERY_REPLY; if (query->q_errno != NULL) *query->q_errno = errno; pthread_cond_signal(&query->q_reply); } query->q_tries += 1; (void) gettimeofday(&query->q_sent, NULL); } /* ** AR_DISPATCHER -- dispatcher thread ** ** Parameters: ** tp -- thread pointer; miscellaneous data set up at init time ** ** Return value: ** Always NULL. */ static void * ar_dispatcher(void *tp) { bool wrote; bool usetimeout; int status; int maxfd; AR_LIB lib; AR_QUERY q; #if SELECT fd_set rfds; fd_set wfds; #endif /* SELECT */ struct timeval timeout; struct timeval timeleft; sigset_t set; assert(tp != NULL); lib = tp; pthread_mutex_lock(&lib->ar_lock); lib->ar_resend = 0; /* block signals that should be caught elsewhere */ sigemptyset(&set); sigaddset(&set, SIGHUP); sigaddset(&set, SIGTERM); sigaddset(&set, SIGINT); pthread_sigmask(SIG_BLOCK, &set, NULL); for (;;) { maxfd = MAX(lib->ar_nsfd, lib->ar_control[1]); /* check on the control descriptor and the NS descriptor */ #if SELECT FD_ZERO(&rfds); FD_ZERO(&wfds); if (lib->ar_pending != NULL || lib->ar_resend > 0) FD_SET(lib->ar_nsfd, &wfds); FD_SET(lib->ar_nsfd, &rfds); FD_SET(lib->ar_control[1], &rfds); /* determine how long to wait */ timeout.tv_sec = AR_MAXTIMEOUT; timeout.tv_usec = 0; usetimeout = (lib->ar_queries != NULL); for (q = lib->ar_queries; q != NULL; q = q->q_next) { /* check for absolute timeout */ if (q->q_timeout.tv_sec != 0 && (q->q_flags & QUERY_INFINIWAIT) == 0) { ar_timeleft(NULL, &q->q_timeout, &timeleft); if (timeleft.tv_sec < timeout.tv_sec || (timeleft.tv_sec == timeout.tv_sec && timeleft.tv_usec < timeout.tv_usec)) { memcpy(&timeout, &timeleft, sizeof timeout); } } /* check for re-send timeout */ ar_timeleft(&q->q_sent, &lib->ar_retry, &timeleft); if (timeleft.tv_sec < timeout.tv_sec || (timeleft.tv_sec == timeout.tv_sec && timeleft.tv_usec < timeout.tv_usec)) memcpy(&timeout, &timeleft, sizeof timeout); } pthread_mutex_unlock(&lib->ar_lock); /* XXX -- effect a poll if we knew there was more pending */ status = select(maxfd + 1, &rfds, &wfds, NULL, usetimeout ? &timeout : NULL); if (status == -1) { if (errno == EINTR) continue; else assert(status >= 0); } pthread_mutex_lock(&lib->ar_lock); #endif /* SELECT */ wrote = FALSE; /* read what's available for dispatch */ if (READ_READY(rfds, lib->ar_nsfd)) { bool requeued = FALSE; size_t r; u_char *buf; HEADER hdr; if ((lib->ar_flags & AR_FLAG_USETCP) == 0) { r = recvfrom(lib->ar_nsfd, lib->ar_querybuf, lib->ar_querybuflen, 0, NULL, NULL); if (r == (size_t) -1) continue; buf = lib->ar_querybuf; } else { u_short len; bool err = FALSE; int part; unsigned char *where; /* first get the length */ len = 0; r = recvfrom(lib->ar_nsfd, &len, sizeof len, MSG_WAITALL, NULL, NULL); if (r == (size_t) -1) { if (errno == EINTR) continue; else err = TRUE; } else if (r == 0) { err = TRUE; } else if (r < sizeof len) { continue; } if (err) { /* reconnect */ pthread_mutex_unlock(&lib->ar_lock); if (!ar_reconnect(lib)) return NULL; pthread_mutex_lock(&lib->ar_lock); /* arrange to re-send everything */ ar_requeue(lib); continue; } len = ntohs(len); /* allocate a buffer */ if (lib->ar_tcpbuf == NULL || lib->ar_tcpbuflen < len) { if (lib->ar_tcpbuf != NULL) { ar_free(lib, lib->ar_tcpbuf); lib->ar_tcpbuf = NULL; } lib->ar_tcpbuf = ar_malloc(lib, len); lib->ar_tcpbuflen = len; } /* ** XXX -- improve multiplexing here by making ** this its own case */ /* grab the reply (maybe in pieces) */ r = 0; where = lib->ar_tcpbuf; while (len > 0) { part = recvfrom(lib->ar_nsfd, where, len, 0, NULL, NULL); if (part == 0 || part == (size_t) -1) { if (errno == EINTR) continue; err = TRUE; break; } r += part; len -= part; where += part; } if (err) { /* reconnect */ pthread_mutex_unlock(&lib->ar_lock); if (!ar_reconnect(lib)) return NULL; pthread_mutex_lock(&lib->ar_lock); /* arrange to re-send everything */ ar_requeue(lib); continue; } buf = lib->ar_tcpbuf; } /* truncate extra data */ if (r > MAXPACKET) r = MAXPACKET; memcpy(&hdr, buf, sizeof hdr); /* find the matching query */ for (q = lib->ar_queries; q != NULL; q = q->q_next) { pthread_mutex_lock(&q->q_lock); if (q->q_id == hdr.id) { pthread_mutex_unlock(&q->q_lock); break; } pthread_mutex_unlock(&q->q_lock); } #ifdef DEBUG printf("*** RECEIVE id=%d time=%d\n", hdr.id, time(NULL)); #endif /* DEBUG */ /* don't recurse if user buffer is too small */ if (q != NULL && r > q->q_buflen) q->q_depth = 0; /* check CNAME and depth */ if (q != NULL && q->q_depth > 0) { int n; int class; int type; int qdcount; int ancount; size_t anslen; u_char *cp; u_char *eom; anslen = r; cp = (u_char *) buf + HFIXEDSZ; eom = (u_char *) buf + anslen; qdcount = ntohs((unsigned short) hdr.qdcount); ancount = ntohs((unsigned short) hdr.ancount); for (; qdcount > 0; qdcount--) { if ((n = dn_skipname(cp, eom)) < 0) break; cp += n; if (cp + INT16SZ + INT16SZ > eom) break; GETSHORT(type, cp); GETSHORT(class, cp); } if (hdr.rcode == NOERROR || ancount == 0) { if ((n = dn_skipname(cp, eom)) < 0) break; cp += n; GETSHORT(type, cp); GETSHORT(class, cp); cp += INT32SZ; /* CNAME found; recurse */ if (type == T_CNAME) { char cname[MAXHOSTNAMELEN + 1]; GETSHORT(n, cp); memset(cname, '\0', sizeof cname); (void) dn_expand(buf, eom, cp, cname, MAXHOSTNAMELEN); q->q_depth--; ar_undot(cname); sm_strlcpy(q->q_name, cname, sizeof q->q_name); ar_requery(lib, q); requeued = TRUE; } } } /* pack up the reply */ if (q != NULL && !requeued) { pthread_mutex_lock(&q->q_lock); memcpy(q->q_buf, buf, MIN(r, q->q_buflen)); q->q_flags |= QUERY_REPLY; q->q_replylen = r; pthread_cond_signal(&q->q_reply); pthread_mutex_unlock(&q->q_lock); if ((q->q_flags & QUERY_RESEND) != 0) lib->ar_resend--; } } /* send a pending query */ if (READ_READY(wfds, lib->ar_nsfd) && lib->ar_pending != NULL) { q = lib->ar_pending; lib->ar_pending = q->q_next; if (lib->ar_pending == NULL) lib->ar_pendingtail = NULL; q->q_next = NULL; /* make and write the query */ pthread_mutex_lock(&q->q_lock); ar_sendquery(lib, q); pthread_mutex_unlock(&q->q_lock); wrote = TRUE; if (lib->ar_queriestail == NULL) { lib->ar_queries = q; lib->ar_queriestail = q; } else { lib->ar_queriestail->q_next = q; lib->ar_queriestail = q; } } /* pending resends */ if (!wrote && lib->ar_resend > 0 && READ_READY(wfds, lib->ar_nsfd)) { for (q = lib->ar_queries; !wrote && q != NULL && lib->ar_resend > 0; q = q->q_next) { pthread_mutex_lock(&q->q_lock); if ((q->q_flags & QUERY_RESEND) != 0) { ar_sendquery(lib, q); q->q_flags &= ~QUERY_RESEND; wrote = TRUE; lib->ar_resend--; } pthread_mutex_unlock(&q->q_lock); } } /* control socket messages */ if (READ_READY(rfds, lib->ar_control[1])) { size_t rlen; AR_QUERY q; rlen = read(lib->ar_control[1], &q, sizeof q); if (rlen == 0) { pthread_mutex_unlock(&lib->ar_lock); return NULL; } /* resend request */ if (q != NULL && (q->q_flags & QUERY_RESEND) == 0) { q->q_flags |= QUERY_RESEND; lib->ar_resend++; } } /* look through active queries for timeouts */ for (q = lib->ar_queries; q != NULL; q = q->q_next) { pthread_mutex_lock(&q->q_lock); if ((q->q_flags & (QUERY_NOREPLY|QUERY_REPLY)) == 0 && ar_expired(q)) { q->q_flags |= QUERY_NOREPLY; pthread_cond_signal(&q->q_reply); } pthread_mutex_unlock(&q->q_lock); } /* look through what's left for retries */ for (q = lib->ar_queries; q != NULL; q = q->q_next) { pthread_mutex_lock(&q->q_lock); if (ar_elapsed(&q->q_sent, &lib->ar_retry)) { if ((lib->ar_flags & AR_FLAG_USETCP) == 0) { ar_sendquery(lib, q); } else { lib->ar_nsidx = (lib->ar_nsidx + 1) % lib->ar_nscount; /* reconnect */ pthread_mutex_unlock(&lib->ar_lock); if (!ar_reconnect(lib)) return NULL; pthread_mutex_lock(&lib->ar_lock); /* arrange to re-send everything */ ar_requeue(lib); } pthread_mutex_unlock(&q->q_lock); break; } pthread_mutex_unlock(&q->q_lock); } } return NULL; } /* ** AR_RES_INIT -- res_init()/res_ninit() wrapper ** ** Parameters: ** None. ** ** Return value: ** 0 on success, -1 on failure. */ static int ar_res_init(AR_LIB new) { size_t bytes; SOCKADDR *sa; assert(new != NULL); h_errno = NETDB_SUCCESS; memset(&ar_res, '\0', sizeof ar_res); /* ** We'll trust that res_init()/res_ninit() will give us things ** like NS counts and retransmission times, but can't always rely ** on it for the nameservers. */ #if (defined(__RES) && (__RES <= 19960801)) /* old-school (bind4) */ res_init(); memcpy(&ar_res, &_res, sizeof ar_res); #else /* defined(__RES) && (__RES <= 19960801) */ /* new-school (bind8 and up) */ (void) res_ninit(&ar_res); #endif /* defined(__RES) && (__RES <= 19960801) */ new->ar_nscount = ar_res.nscount; new->ar_retry.tv_sec = ar_res.retrans; new->ar_retry.tv_usec = 0; new->ar_retries = ar_res.retry; if (new->ar_nscount == 0) new->ar_nscount = MAXNS; bytes = sizeof(SOCKADDR) * new->ar_nscount; if (new->ar_malloc != NULL) { new->ar_nsaddrs = (SOCKADDR *) new->ar_malloc(new->ar_closure, bytes); } else { new->ar_nsaddrs = (SOCKADDR *) malloc(bytes); } if (new->ar_nsaddrs == NULL) return -1; memset(new->ar_nsaddrs, '\0', sizeof(SOCKADDR) * ar_res.nscount); #if defined(AR_RES_MANUAL) || defined(AF_INET6) ar_res_parse(&new->ar_nscount, new->ar_nsaddrs, &new->ar_retries, &new->ar_retry.tv_sec); #else /* defined(AR_RES_MANUAL) || defined(AF_INET6) */ memcpy(new->ar_nsaddrs, ar_res.nsaddr_list, sizeof(SOCKADDR) * ar_res.nscount); /* an address of 0 (INADDR_ANY) should become INADDR_LOOPBACK */ for (c = 0; c < new->ar_nscount; c++) { sa = (SOCKADDR *) new->ar_nsaddrs[c]; if (sa->sa_family == AF_INET) { struct sockaddr_in *sin; sin = (struct sockaddr_in *) sa; if (sin->sin_addr.s_addr == INADDR_ANY) sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); } } #endif /* defined(AR_RES_MANUAL) || defined(AF_INET6) */ return 0; } /* ** ========================= PUBLIC FUNCTIONS ========================= */ /* ** AR_INIT -- instantiate the service ** ** Parameters: ** user_malloc -- malloc() replacement function ** user_free -- free() replacement function ** user_closure -- memory closure to be used for library allocations ** flags -- flags ** ** Return value: ** An AR_LIB handle on success, NULL on failure (check errno) */ AR_LIB ar_init(ar_malloc_t user_malloc, ar_free_t user_free, void *user_closure, int flags) { int status; int c; AR_LIB new; struct sockaddr *sa; #define TMP_MALLOC(x) (user_malloc == NULL ? malloc((x)) \ : user_malloc(user_closure, ((x)))); #define TMP_FREE(x) (user_free == NULL ? free((x)) \ : user_free(user_closure, ((x)))); #define TMP_CLOSE(x) if ((x) != -1) \ close((x)); new = TMP_MALLOC(sizeof(struct ar_libhandle)); if (new == NULL) return NULL; new->ar_malloc = user_malloc; new->ar_free = user_free; new->ar_closure = user_closure; new->ar_flags = flags; new->ar_nsfd = -1; new->ar_nsfdpf = -1; new->ar_tcpbuflen = 0; new->ar_tcpbuf = NULL; new->ar_pending = NULL; new->ar_pendingtail = NULL; new->ar_queries = NULL; new->ar_queriestail = NULL; new->ar_recycle = NULL; new->ar_querybuflen = HFIXEDSZ + MAXPACKET; new->ar_control[0] = -1; new->ar_control[1] = -1; new->ar_nsidx = 0; new->ar_writelen = 0; if (ar_res_init(new) != 0) { TMP_FREE(new); return NULL; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, new->ar_control) != 0) { TMP_FREE(new); return NULL; } /* establish socket; connect if necessary */ for (c = 0; c < new->ar_nscount; c++) { sa = (struct sockaddr *) &new->ar_nsaddrs[c]; if ((new->ar_flags & AR_FLAG_USETCP) == 0) /* UDP */ { new->ar_nsfd = socket(sa->sa_family, SOCK_DGRAM, 0); if (new->ar_nsfd != -1) { new->ar_nsfdpf = sa->sa_family; break; } } else /* TCP */ { int socklen; new->ar_nsfd = socket(sa->sa_family, SOCK_STREAM, 0); if (new->ar_nsfd == -1) continue; #ifdef AF_INET6 if (sa->sa_family == AF_INET6) socklen = sizeof(struct sockaddr_in6); else socklen = sizeof(struct sockaddr_in); #else /* AF_INET */ socklen = sizeof(struct sockaddr_in); #endif /* AF_INET */ if (connect(new->ar_nsfd, sa, socklen) == 0) { new->ar_nsfdpf = sa->sa_family; break; } close(new->ar_nsfd); new->ar_nsfd = -1; } } if (new->ar_nsfd == -1) { TMP_CLOSE(new->ar_control[0]); TMP_CLOSE(new->ar_control[1]); TMP_FREE(new); return NULL; } new->ar_querybuf = TMP_MALLOC(new->ar_querybuflen); if (new->ar_querybuf == NULL) { TMP_CLOSE(new->ar_control[0]); TMP_CLOSE(new->ar_control[1]); TMP_CLOSE(new->ar_nsfd); TMP_FREE(new->ar_nsaddrs); TMP_FREE(new); return NULL; } (void) pthread_mutex_init(&new->ar_lock, NULL); status = pthread_create(&new->ar_dispatcher, NULL, ar_dispatcher, new); if (status != 0) { TMP_CLOSE(new->ar_control[0]); TMP_CLOSE(new->ar_control[1]); TMP_CLOSE(new->ar_nsfd); TMP_FREE(new->ar_querybuf); TMP_FREE(new->ar_nsaddrs); TMP_FREE(new); return NULL; } return new; } /* ** AR_SHUTDOWN -- terminate an instance of the service ** ** Parameters: ** lib -- library handle ** ** Return value: ** 0 on success, or an errno on failure. */ int ar_shutdown(AR_LIB lib) { int status; assert(lib != NULL); close(lib->ar_control[0]); status = pthread_join(lib->ar_dispatcher, NULL); if (status == 0) { void *closure; void (*user_free)(void *, void *); close(lib->ar_nsfd); close(lib->ar_control[1]); pthread_mutex_destroy(&lib->ar_lock); ar_smashqueue(lib, lib->ar_pending); ar_smashqueue(lib, lib->ar_queries); ar_smashqueue(lib, lib->ar_recycle); if (lib->ar_tcpbuf != NULL) ar_free(lib, lib->ar_tcpbuf); ar_free(lib, lib->ar_querybuf); ar_free(lib, lib->ar_nsaddrs); closure = lib->ar_closure; user_free = lib->ar_free; if (user_free != NULL) user_free(closure, lib); else free(lib); } return status; } /* ** AR_SETRETRY -- set retry interval ** ** Parameters: ** lib -- library handle ** new -- new retry interval (may be NULL); ** old -- current retry interval (returned; may be NULL) ** ** Return value: ** None. */ void ar_setretry(AR_LIB lib, struct timeval *new, struct timeval *old) { assert(lib != NULL); if (old != NULL) memcpy(old, &lib->ar_retry, sizeof lib->ar_retry); if (new != NULL) memcpy(&lib->ar_retry, new, sizeof lib->ar_retry); } /* ** AR_SETMAXRETRY -- set max retry count ** ** Parameters: ** lib -- library handle ** new -- new value (or -1 to leave unchanged) ** old -- current value (returned; may be NULL) ** ** Return value: ** None. */ void ar_setmaxretry(AR_LIB lib, int new, int *old) { assert(lib != NULL); if (old != NULL) *old = lib->ar_retries; if (new != -1) lib->ar_retries = new; } /* ** AR_ADDQUERY -- add a query for processing ** ** Parameters: ** lib -- library handle ** name -- name of the query to be submitted ** class -- class of the query to be submitted ** type -- type of the query to be submitted ** depth -- chase CNAMEs to this depth (0 == don't) ** buf -- buffer into which to write the result ** buflen -- bytes available at "buf" ** err -- pointer to an int which should receive errno on send errors ** timeout -- timeout (or NULL) ** ** Return value: ** NULL -- error; see errno and/or the value returned in err ** otherwise, an AR_QUERY handle */ AR_QUERY ar_addquery(AR_LIB lib, char *name, int class, int type, int depth, unsigned char *buf, size_t buflen, int *err, struct timeval *timeout) { char prev; int status; int maxfd; size_t wlen; AR_QUERY q; AR_QUERY x; char *p; #if SELECT fd_set wfds; struct timeval stimeout; #endif /* SELECT */ assert(lib != NULL); assert(name != NULL); /* ** Sanity-check the name. Look for invalid characters or patterns ** that will make res_mkquery() return -1 for reasons other than ** "buffer too short". ** ** In particular, look for: ** - non-ASCII characters ** - non-printable characters ** - things that start with "." ** - things that contain adjacent "."s */ wlen = 0; prev = '\0'; for (p = name; *p != '\0'; p++) { if (!isascii(*p) || !isprint(*p) || (*p == '.' && (prev == '.' || prev == '\0'))) { if (err != NULL) *err = EINVAL; errno = EINVAL; return NULL; } prev = *p; } /* sanity-check the timeout, if provided */ if (timeout != NULL) { if (timeout->tv_sec < 0 || timeout->tv_sec > AR_MAXTIMEOUT || timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) { errno = EINVAL; return NULL; } } pthread_mutex_lock(&lib->ar_lock); if ((lib->ar_flags & AR_FLAG_DEAD) != 0) { pthread_mutex_unlock(&lib->ar_lock); if (err != NULL) *err = lib->ar_deaderrno; errno = lib->ar_deaderrno; return NULL; } if (lib->ar_recycle != NULL) { q = lib->ar_recycle; lib->ar_recycle = q->q_next; pthread_mutex_unlock(&lib->ar_lock); } else { pthread_mutex_unlock(&lib->ar_lock); q = ar_malloc(lib, sizeof(struct ar_query)); if (q == NULL) { if (err != NULL) *err = errno; return NULL; } memset(q, '\0', sizeof(struct ar_query)); pthread_mutex_init(&q->q_lock, NULL); pthread_cond_init(&q->q_reply, NULL); } /* construct the query */ q->q_class = class; q->q_type = type; q->q_flags = 0; q->q_depth = depth; q->q_errno = err; q->q_next = NULL; q->q_buf = buf; q->q_buflen = buflen; q->q_tries = 0; if (timeout == NULL) { q->q_flags |= QUERY_INFINIWAIT; q->q_timeout.tv_sec = 0; q->q_timeout.tv_usec = 0; } else { (void) gettimeofday(&q->q_timeout, NULL); q->q_timeout.tv_sec += timeout->tv_sec; q->q_timeout.tv_usec += timeout->tv_usec; if (q->q_timeout.tv_usec >= 1000000) { q->q_timeout.tv_sec += 1; q->q_timeout.tv_usec -= 1000000; } } sm_strlcpy(q->q_name, name, sizeof q->q_name); /* enqueue the query and signal the dispatcher */ pthread_mutex_lock(&lib->ar_lock); if (lib->ar_pending == NULL) { lib->ar_pending = q; lib->ar_pendingtail = q; } else { lib->ar_pendingtail->q_next = q; lib->ar_pendingtail = q; } x = NULL; /* ** Write a four-byte NULL to the control descriptor to indicate ** to the dispatcher there's general work to do. This will cause ** it to check its "pending" list for work to do and dispatch it. ** If the descriptor is not writeable, we don't much care because ** that means the pipe is full of messages already which will wake ** up the dispatcher anyway. */ #if SELECT /* XXX -- do this as ar_trywrite() or something */ maxfd = lib->ar_control[0]; FD_ZERO(&wfds); FD_SET(lib->ar_control[0], &wfds); stimeout.tv_sec = 0; stimeout.tv_usec = 0; status = select(maxfd + 1, NULL, &wfds, NULL, &stimeout); if (status == 1) { wlen = write(lib->ar_control[0], &x, sizeof x); } else if (status == 0) { wlen = sizeof x; } else { if (err != NULL) *err = errno; } #endif /* SELECT */ pthread_mutex_unlock(&lib->ar_lock); switch (wlen) { case sizeof x: return q; default: ar_recycle(lib, q); return NULL; } } /* ** AR_CANCELQUERY -- cancel a pending query ** ** Parameters: ** lib -- library handle ** query -- AR_QUERY handle which should be terminated ** ** Return value: ** 0 -- cancel successful ** 1 -- cancel not successful (record not found) */ int ar_cancelquery(AR_LIB lib, AR_QUERY query) { AR_QUERY q; AR_QUERY last; assert(lib != NULL); assert(query != NULL); pthread_mutex_lock(&lib->ar_lock); /* first, look in pending queries */ for (q = lib->ar_pending, last = NULL; q != NULL; last = q, q = q->q_next) { if (query == q) { if (last == NULL) { lib->ar_pending = q->q_next; if (lib->ar_pending == NULL) lib->ar_pendingtail = NULL; } else { last->q_next = q->q_next; if (lib->ar_pendingtail == q) lib->ar_pendingtail = last; } q->q_next = lib->ar_recycle; if ((q->q_flags & QUERY_RESEND) != 0) lib->ar_resend--; lib->ar_recycle = q; pthread_mutex_unlock(&lib->ar_lock); return 0; } } /* next, look in active queries */ for (q = lib->ar_queries, last = NULL; q != NULL; last = q, q = q->q_next) { if (query == q) { if (last == NULL) { lib->ar_queries = q->q_next; if (lib->ar_queries == NULL) lib->ar_queriestail = NULL; } else { last->q_next = q->q_next; if (lib->ar_queriestail == q) lib->ar_queriestail = last; } q->q_next = lib->ar_recycle; if ((q->q_flags & QUERY_RESEND) != 0) lib->ar_resend--; lib->ar_recycle = q; pthread_mutex_unlock(&lib->ar_lock); return 0; } } pthread_mutex_unlock(&lib->ar_lock); return 1; } /* ** AR_WAITREPLY -- go to sleep waiting for a reply ** ** Parameters: ** lib -- library handle ** query -- AR_QUERY handle of interest ** len -- length of the received reply (returned) ** timeout -- timeout for the wait, or NULL to wait for the query ** to time out ** ** Return value: ** AR_STAT_SUCCESS -- success; reply available ** AR_STAT_NOREPLY -- timeout; no reply available yet ** AR_STAT_EXPIRED -- timeout; query expired ** AR_STAT_ERROR -- error; see errno ** ** Notes: ** If *len is greater than the size of the buffer provided when ** ar_addquery() was called, then there was some data truncated ** because the buffer was not big enough to receive the whole reply. ** The caller should resubmit with a larger buffer. */ int ar_waitreply(AR_LIB lib, AR_QUERY query, size_t *len, struct timeval *timeout) { bool infinite; bool maintimeout = FALSE; int status; struct timespec until; struct timeval now; assert(lib != NULL); assert(query != NULL); pthread_mutex_lock(&query->q_lock); if ((query->q_flags & QUERY_REPLY) != 0) { if (len != NULL) *len = query->q_replylen; pthread_mutex_unlock(&query->q_lock); return AR_STAT_SUCCESS; } else if ((query->q_flags & QUERY_ERROR) != 0) { pthread_mutex_unlock(&query->q_lock); return AR_STAT_ERROR; } else if ((query->q_flags & QUERY_NOREPLY) != 0) { pthread_mutex_unlock(&query->q_lock); if (query->q_errno != NULL) *query->q_errno = ETIMEDOUT; return AR_STAT_EXPIRED; } /* ** Pick the soonest of: ** - timeout specified above ** - timeout specified on the query ** - forever */ (void) gettimeofday(&now, NULL); infinite = FALSE; until.tv_sec = 0; until.tv_nsec = 0; if (timeout == NULL && (query->q_flags & QUERY_INFINIWAIT) != 0) { infinite = TRUE; } else { /* if a timeout was specified above */ if (timeout != NULL) { until.tv_sec = now.tv_sec + timeout->tv_sec; until.tv_nsec = now.tv_usec + timeout->tv_usec; if (until.tv_nsec > 1000000) { until.tv_sec += 1; until.tv_nsec -= 1000000; } until.tv_nsec *= 1000; } /* if a timeout was specified on the query */ if ((query->q_flags & QUERY_INFINIWAIT) == 0) { if (until.tv_sec == 0 || until.tv_sec > query->q_timeout.tv_sec || (until.tv_sec == query->q_timeout.tv_sec && until.tv_nsec > query->q_timeout.tv_usec * 1000)) { until.tv_sec = query->q_timeout.tv_sec; until.tv_nsec = query->q_timeout.tv_usec * 1000; maintimeout = TRUE; } } } while ((query->q_flags & (QUERY_REPLY|QUERY_NOREPLY)) == 0) { if (infinite == 1) { status = pthread_cond_wait(&query->q_reply, &query->q_lock); } else { status = pthread_cond_timedwait(&query->q_reply, &query->q_lock, &until); if (status == ETIMEDOUT) break; } } /* recheck flags */ if ((query->q_flags & QUERY_ERROR) != 0) { pthread_mutex_unlock(&query->q_lock); errno = lib->ar_deaderrno; return AR_STAT_ERROR; } else if ((query->q_flags & QUERY_REPLY) == 0) { pthread_mutex_unlock(&query->q_lock); if (maintimeout && query->q_errno != NULL) *query->q_errno = ETIMEDOUT; return (maintimeout ? AR_STAT_EXPIRED : AR_STAT_NOREPLY); } pthread_mutex_unlock(&query->q_lock); if (len != NULL) *len = query->q_replylen; return AR_STAT_SUCCESS; } /* ** AR_RECYCLE -- recycle a query when the caller is done with it ** ** Parameters: ** lib -- library handle ** query -- AR_QUERY handle to recycle ** ** Return value: ** None. */ void ar_recycle(AR_LIB lib, AR_QUERY query) { assert(lib != NULL); assert(query != NULL); pthread_mutex_lock(&lib->ar_lock); query->q_next = lib->ar_recycle; lib->ar_recycle = query; pthread_mutex_unlock(&lib->ar_lock); } /* ** AR_RESEND -- enqueue re-sending of a pending request ** ** Parameters: ** lib -- library handle ** query -- query to re-send ** ** Return value: ** 0 on success, -1 on failure. */ int ar_resend(AR_LIB lib, AR_QUERY query) { size_t wlen; assert(lib != NULL); assert(query != NULL); wlen = write(lib->ar_control[1], query, sizeof query); return (wlen == 4 ? 0 : -1); } /* ** AR_STRERROR -- translate an error code ** ** Parameters: ** err -- error code ** ** Return value: ** Pointer to a text string which represents that error code. */ char * ar_strerror(int err) { switch (err) { case QUERY_ERRNO_RETRIES: return "Too many retries"; case QUERY_ERRNO_TOOBIG: return "Unable to construct query"; default: return strerror(errno); } } dk-milter-1.0.0.dfsg/libar/Build0000755000175000017500000000053010052726024016136 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1999, 2004 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: Build,v 1.1 2004/05/19 18:48:52 msk Exp $ exec sh ../devtools/bin/Build $* dk-milter-1.0.0.dfsg/libar/Makefile0000644000175000017500000000045710052726024016621 0ustar madhackmadhack# $Id: Makefile,v 1.1 2004/05/19 18:48:52 msk Exp $ SHELL= /bin/sh BUILD= ./Build OPTIONS= $(CONFIG) $(FLAGS) all: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ clean: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ install: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ fresh: FRC $(SHELL) $(BUILD) $(OPTIONS) -c FRC: dk-milter-1.0.0.dfsg/libar/ar.30000644000175000017500000002111510225537731015650 0ustar madhackmadhack.TH libar 3 .SH NAME .B ar_init(), ar_addquery(), ar_waitreply(), ar_cancelquery(), ar_resend(), .B ar_recycle(), ar_shutdown() -- asynchronous DNS resolver facility .SH SYNOPSIS #include .I typedef void * .B ar_malloc_t (void *, size_t); typedef void .B ar_free_t (void *, void *); AR_LIB .B ar_init (ar_malloc_t .B mallocf, ar_free_t .B freef, void * .B memclosure, int .B flags ); int .B ar_shutdown (AR_LIB .B lib ); void .B ar_setretry (AR_LIB .B lib, struct timeval * .B new, struct timeval * .B old ); void .B ar_setmaxretry (AR_LIB .B lib, int .B new, int * .B old); AR_QUERY .B ar_addquery (AR_LIB .B lib, const char * .B query, int .B class, int .B type, int .B depth, unsigned char * .B buf, size_t .B buflen, int * .B err, struct timeval * .B timeout ); int .B ar_waitreply (AR_LIB .B lib, AR_QUERY .B query, int * .B len, struct timeval * .B timeout ); int .B ar_cancelquery (AR_LIB .B lib, AR_QUERY .B query ); void .B ar_recycle (AR_LIB .B lib, AR_QUERY .B query ); int .B ar_resend (AR_LIB .B lib, AR_QUERY .B query ); char * .B ar_strerror (int .B err ); .SH DESCRIPTION These functions are an interface to an asynchronous resolver facility. The functions provided by .B resolver(3) and the .B gethostbyxxx(3) functions are not thread-safe since they use static storage, don't multiplex efficiently, and don't have timeouts associated with them. This library of functions was drafted to provide those facilities. An application first initializes the package by calling .B ar_init(). The optional .I mallocf parameter is a caller-provided memory allocation function taking a pointer to a caller-provided opaque data structure (the .I memclosure parameter) and a number of bytes to allocate. If .I mallocf is not provided, the default system memory allocator function .B malloc(3) is used. The optional .I freef parameter specifies a matching caller-provided memory deallocator function, taking a pointer to a caller-provided opaque data structure (the .I memclosure parameter) and a pointer to the memory to be released. If .I freef is not provided, the default system memory release function .B free(3) is used. The .I flags parameter is a bitwise OR of a set of available flags to tailor the operation of the package. Currently the only flag is AR_FLAG_USETCP, which instructs the package to submit its queries via a TCP connection rather than the default, UDP. The handle returned by .B ar_init() is passed to later functions in order to share resources among transactions. By default the package will not retransmit queries for which no reply has arrived until requested to do so with .B ar_resend(). Moreover, that function re-uses the same nameserver as the previous attempt. Instead, the caller can use .B ar_setretry() to define (or retrieve) a time interval after which, if no reply has been received, the query will be re-sent to the next nameserver in the list of nameservers. In the TCP case, this will disconnect from the nameserver, reconnect, and re-send all pending queries. A time of {0, 0} disables this feature. The default is the same as whatever the local resolver uses. To leave the current value unchanged, specify a value of NULL for .I new. If the current value is not of interest, specify a value of NULL for .I old. The .B ar_setmaxretry() function gets and/or sets the maximum number of times a query can be attempted before the package will give up trying. The default is the same as whatever the local resolver uses. To retrieve the current value but leave it unchanged, specify a value of -1 for .I new. If the current value is not of interest, specify a value of NULL for .I old. To submit a new query to the nameserver, the application calls .B ar_addquery(). The .I lib parameter is the handle returned from .B ar_init(). The .I query, .I class and .I type parameters specify the query that is to be performed. .I buf specifies where the result should be written when a reply is received, and .I buflen indicates how many bytes are available there. .I err is an optional pointer to an integer which will receive the value of .I errno if there is a transmission error between this package and the nameserver. .I depth indicates how many CNAME references will be re-queried before the package gives up and returns whatever result is current. Finally, .I timeout is an optional pointer to a timeval structure that indicates the total time allowed for this query to resolve. If NULL, this query never times out. To wait for a query result, the application calls .B ar_waitreply(). .I lib is again the library handle as returned by .B ar_init(). .I query is the query handle returned by .B ar_addquery(). .I len is a pointer to an integer which will receive the number of bytes that were contained in the reply. It can be NULL if that information is not of interest to the caller. This number may be larger than the value of .I buflen in the call to .B ar_addquery(), in which case there was not enough space in the provided buffer to receive the reply and the application should resubmit with a bigger buffer. .I timeout specifies how long this particular call should wait for a reply before returning. If the reply has already arrived (even if it's an NXDOMAIN reply), this function will return immediately, otherwise it will wait until either the requested timeout expires, or the timeout set on the .B ar_addquery() call expires. When a reply has been retrieved, the query handle needs to be recycled via a call to .B ar_recycle(). To abort a query, use .B ar_cancelquery(). This implicitly recycles the .I query handle passed to it. To arrange to re-send a query for which a reply has not yet arrived, use .B ar_resend(). When all queries are done and the facility is no longer desired, a call to .B ar_shutdown() will close down the service and release related resources. The function .B ar_strerror() is provided to handle error codes returned by the library. Positive error codes are standard POSIX error codes and will be passed to .I strerror(3) while negative error codes are internal to the library and will be translated to a human-readable form by this function. .SH RETURN VALUES .B ar_lib() returns a handle to a newly-initialized instantiation of the library. If operating in TCP mode, a TCP connection now exists to a nameserver. NULL is returned if any of this initialization fails, with .I errno set to indicate the error. .B ar_shutdown() returns 0 on success, or an .I errno value on failure. .B ar_addquery() returns a newly-initialized .I AR_QUERY handle on success, or NULL on failure with .I errno set to indicate the error. EINVAL will be used if the query submitted was malformed (i.e. contained invalid characters or character sequences). .B ar_cancelquery() returns 0 on success or 1 on error (i.e. invalid query handle specified). .B ar_waitreply() returns AR_STAT_SUCCESS (0) on success, indicating a reply is available for processing; AR_STAT_NOREPLY (1) if a timeout is specified on the call but expired, indicating no reply is available yet but there might be one later; AR_STAT_EXPIRED (2) if the timeout specified on the call to .B ar_addquery() has expired; or AR_STAT_ERROR (-1) on error with .I errno set to indicate the error. .B ar_resend() returns 0 on success or -1 on error with .I errno set to indicate the error. .SH NOTES This system uses .B pthreads for synchronization and signalling. Applications that use another threading mechanism may not work with this library. If operating in TCP mode and the remote nameserver disconnects, the library will attempt to connect to each of the nameservers published in .I resolv.conf(4) before giving up. Once it gives up, all pending and future calls to .B ar_waitreply() or .B ar_addquery() will fail. The only option after that is to shut down the library and start again. CNAME recursion is done at most .I depth times while evaluating the result of a query. The time specified in the call to .B ar_addquery() should allow for recursion time, since that defines the total amount of time the entire query, including recursion, is allowed to take. The buffer provided in the call to .B ar_addquery() is sometimes used for temporary storage, specifically when chasing CNAME references. If a particular CNAME recursion is too large for the buffer, the search will be interrupted and returned as-is, and the .I len value returned will indicate that a lack of buffer space caused the recursion to terminate (see above). .B ar_strerror() returns a pointer to a character string representing the supplied error code. .SH COPYRIGHT Copyright (c) 2004, 2005, Sendmail, Inc. and its suppliers. All rights reserved. .SH SEE ALSO gethostbyaddr(3), gethostbyname(3), resolv.conf(4), resolver(3) dk-milter-1.0.0.dfsg/LICENSE0000644000175000017500000001044210057143764015101 0ustar madhackmadhack SENDMAIL OPEN SOURCE LICENSE The following license terms and conditions apply to this open source software ("Software"), unless a different license is obtained directly from Sendmail, Inc. ("Sendmail") located at 6425 Christie Ave, Fourth Floor, Emeryville, CA 94608, USA. Use, modification and redistribution (including distribution of any modified or derived work) of the Software in source and binary forms is permitted only if each of the following conditions of 1-6 are met: 1. Redistributions of the Software qualify as "freeware" or "open source software" under one of the following terms: (a) Redistributions are made at no charge beyond the reasonable cost of materials and delivery; or (b) Redistributions are accompanied by a copy of the modified Source Code (on an acceptable machine-readable medium) or by an irrevocable offer to provide a copy of the modified Source Code (on an acceptable machine-readable medium) for up to three years at the cost of materials and delivery. Such redistributions must allow further use, modification, and redistribution of the Source Code under substantially the same terms as this license. For the purposes of redistribution "Source Code" means the complete human-readable, compilable, linkable, and operational source code of the redistributed module(s) including all modifications. 2. Redistributions of the Software Source Code must retain the copyright notices as they appear in each Source Code file, these license terms and conditions, and the disclaimer/limitation of liability set forth in paragraph 6 below. Redistributions of the Software Source Code must also comply with the copyright notices and/or license terms and conditions imposed by contributors on embedded code. The contributors' license terms and conditions and/or copyright notices are contained in the Source Code distribution. 3. Redistributions of the Software in binary form must reproduce the Copyright Notice described below, these license terms and conditions, and the disclaimer/limitation of liability set forth in paragraph 6 below, in the documentation and/or other materials provided with the binary distribution. For the purposes of binary distribution, "Copyright Notice" refers to the following language: "Copyright (c) 1998-2004 Sendmail, Inc. All rights reserved." 4. Neither the name, trademark or logo of Sendmail, Inc. (including without limitation its subsidiaries or affiliates) or its contributors may be used to endorse or promote products, or software or services derived from this Software without specific prior written permission. The name "sendmail" is a registered trademark and service mark of Sendmail, Inc. 5. We reserve the right to cancel this license if you do not comply with the terms. This license is governed by California law and both of us agree that for any dispute arising out of or relating to this Software, that jurisdiction and venue is proper in San Francisco or Alameda counties. These license terms and conditions reflect the complete agreement for the license of the Software (which means this supercedes prior or contemporaneous agreements or representations). If any term or condition under this license is found to be invalid, the remaining terms and conditions still apply. 6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY SENDMAIL AND ITS CONTRIBUTORS "AS IS" WITHOUT WARRANTY OF ANY KIND AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. IN NO EVENT SHALL SENDMAIL OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING WITHOUT LIMITATION NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. $Revision: 1.1 $ $Date: 2004/06/01 18:16:20 $ dk-milter-1.0.0.dfsg/include/0000755000175000017500000000000010766324730015517 5ustar madhackmadhackdk-milter-1.0.0.dfsg/include/sm/0000755000175000017500000000000010766324731016137 5ustar madhackmadhackdk-milter-1.0.0.dfsg/include/sm/exc.h0000644000175000017500000000704707307757145017105 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: exc.h,v 1.23 2001/06/07 20:04:53 ca Exp $ */ /* ** libsm exception handling ** See libsm/exc.html for documentation. */ #ifndef SM_EXC_H # define SM_EXC_H #include #include #include #include typedef struct sm_exc SM_EXC_T; typedef struct sm_exc_type SM_EXC_TYPE_T; typedef union sm_val SM_VAL_T; /* ** Exception types */ extern const char SmExcTypeMagic[]; struct sm_exc_type { const char *sm_magic; const char *etype_category; const char *etype_argformat; void (*etype_print) __P((SM_EXC_T *, SM_FILE_T *)); const char *etype_printcontext; }; extern const SM_EXC_TYPE_T SmEtypeOs; extern const SM_EXC_TYPE_T SmEtypeErr; extern void sm_etype_printf __P(( SM_EXC_T *_exc, SM_FILE_T *_stream)); /* ** Exception objects */ extern const char SmExcMagic[]; union sm_val { int v_int; long v_long; char *v_str; SM_EXC_T *v_exc; }; struct sm_exc { const char *sm_magic; size_t exc_refcount; const SM_EXC_TYPE_T *exc_type; SM_VAL_T *exc_argv; }; # define SM_EXC_INITIALIZER(type, argv) \ { \ SmExcMagic, \ 0, \ type, \ argv, \ } extern SM_EXC_T * sm_exc_new_x __P(( const SM_EXC_TYPE_T *_type, ...)); extern SM_EXC_T * sm_exc_addref __P(( SM_EXC_T *_exc)); extern void sm_exc_free __P(( SM_EXC_T *_exc)); extern bool sm_exc_match __P(( SM_EXC_T *_exc, const char *_pattern)); extern void sm_exc_write __P(( SM_EXC_T *_exc, SM_FILE_T *_stream)); extern void sm_exc_print __P(( SM_EXC_T *_exc, SM_FILE_T *_stream)); extern SM_DEAD(void sm_exc_raise_x __P(( SM_EXC_T *_exc))); extern SM_DEAD(void sm_exc_raisenew_x __P(( const SM_EXC_TYPE_T *_type, ...))); /* ** Exception handling */ typedef void (*SM_EXC_DEFAULT_HANDLER_T) __P((SM_EXC_T *)); extern void sm_exc_newthread __P(( SM_EXC_DEFAULT_HANDLER_T _handle)); typedef struct sm_exc_handler SM_EXC_HANDLER_T; struct sm_exc_handler { SM_EXC_T *eh_value; SM_JMPBUF_T eh_context; SM_EXC_HANDLER_T *eh_parent; int eh_state; }; /* values for eh_state */ enum { SM_EH_PUSHED = 2, SM_EH_POPPED = 0, SM_EH_HANDLED = 1 }; extern SM_EXC_HANDLER_T *SmExcHandler; # define SM_TRY { SM_EXC_HANDLER_T _h; \ do { \ _h.eh_value = NULL; \ _h.eh_parent = SmExcHandler; \ _h.eh_state = SM_EH_PUSHED; \ SmExcHandler = &_h; \ if (sm_setjmp_nosig(_h.eh_context) == 0) { # define SM_FINALLY SM_ASSERT(SmExcHandler == &_h); \ } \ if (sm_setjmp_nosig(_h.eh_context) == 0) { # define SM_EXCEPT(e,pat) } \ if (_h.eh_state == SM_EH_HANDLED) \ break; \ if (_h.eh_state == SM_EH_PUSHED) { \ SM_ASSERT(SmExcHandler == &_h); \ SmExcHandler = _h.eh_parent; \ } \ _h.eh_state = sm_exc_match(_h.eh_value,pat) \ ? SM_EH_HANDLED : SM_EH_POPPED; \ if (_h.eh_state == SM_EH_HANDLED) { \ SM_UNUSED(SM_EXC_T *e) = _h.eh_value; # define SM_END_TRY } \ } while (0); \ if (_h.eh_state == SM_EH_PUSHED) { \ SM_ASSERT(SmExcHandler == &_h); \ SmExcHandler = _h.eh_parent; \ if (_h.eh_value != NULL) \ sm_exc_raise_x(_h.eh_value); \ } else if (_h.eh_state == SM_EH_POPPED) { \ if (_h.eh_value != NULL) \ sm_exc_raise_x(_h.eh_value); \ } else \ sm_exc_free(_h.eh_value); \ } #endif /* SM_EXC_H */ dk-milter-1.0.0.dfsg/include/sm/bitops.h0000644000175000017500000000343407353205466017615 0ustar madhackmadhack/* * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * * $Id: bitops.h,v 1.2 2001/09/22 22:05:42 ca Exp $ */ #ifndef SM_BITOPS_H # define SM_BITOPS_H /* ** Data structure for bit maps. ** ** Each bit in this map can be referenced by an ascii character. ** This is 256 possible bits, or 32 8-bit bytes. */ # define BITMAPBITS 256 /* number of bits in a bit map */ # define BYTEBITS 8 /* number of bits in a byte */ # define BITMAPBYTES (BITMAPBITS / BYTEBITS) /* number of bytes in bit map */ # define BITMAPMAX ((BITMAPBYTES / sizeof (int)) - 1) /* internal macros */ /* make sure this index never leaves the allowed range: 0 to BITMAPMAX */ # define _BITWORD(bit) (((unsigned char)(bit) / (BYTEBITS * sizeof (int))) & BITMAPMAX) # define _BITBIT(bit) ((unsigned int)1 << ((unsigned char)(bit) % (BYTEBITS * sizeof (int)))) typedef unsigned int BITMAP256[BITMAPBYTES / sizeof (int)]; /* properly case and truncate bit */ # define bitidx(bit) ((unsigned int) (bit) & 0xff) /* test bit number N */ # define bitnset(bit, map) ((map)[_BITWORD(bit)] & _BITBIT(bit)) /* set bit number N */ # define setbitn(bit, map) (map)[_BITWORD(bit)] |= _BITBIT(bit) /* clear bit number N */ # define clrbitn(bit, map) (map)[_BITWORD(bit)] &= ~_BITBIT(bit) /* clear an entire bit map */ # define clrbitmap(map) memset((char *) map, '\0', BITMAPBYTES) /* bit hacking */ # define bitset(bit, word) (((word) & (bit)) != 0) #endif /* ! SM_BITOPS_H */ dk-milter-1.0.0.dfsg/include/sm/path.h0000644000175000017500000000252607262226374017252 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: path.h,v 1.6 2001/04/03 01:53:00 gshapiro Exp $ */ /* ** Portable names for standard filesystem paths ** and macros for directories. */ #ifndef SM_PATH_H # define SM_PATH_H # include # ifdef WIN32 # define SM_PATH_DEVNULL "NUL" # define SM_IS_DIR_DELIM(c) ((c) == '/' || (c) == '\\') # define SM_FIRST_DIR_DELIM(s) strpbrk(s, "/\\") # define SM_LAST_DIR_DELIM(s) sm_last_dir_delim(s) /* Warning: this must be accessible as array */ # define SM_IS_DIR_START(s) (((s)[1] == ':' && \ (((s)[2] == '/') || ((s)[2] == '\\'))) \ || (((s)[0] == '/') || ((s)[0] == '\\'))) extern char *sm_last_dir_delim __P((const char *)); extern bool sm_path_isdevnull __P((const char *)); # else /* WIN32 */ # define SM_PATH_DEVNULL "/dev/null" # define SM_IS_DIR_DELIM(c) ((c) == '/') # define SM_FIRST_DIR_DELIM(s) strchr(s, '/') # define SM_LAST_DIR_DELIM(s) strrchr(s, '/') /* Warning: this must be accessible as array */ # define SM_IS_DIR_START(s) ((s)[0] == '/') # define sm_path_isdevnull(path) (strcmp(path, "/dev/null") == 0) # endif /* WIN32 */ #endif /* ! SM_PATH_H */ dk-milter-1.0.0.dfsg/include/sm/fdset.h0000644000175000017500000000166207575442403017423 0ustar madhackmadhack/* * Copyright (c) 2001, 2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: fdset.h,v 1.5 2002/12/10 19:48:19 ca Exp $ */ #ifndef SM_FDSET_H # define SM_FDSET_H /* ** Note: SM_FD_OK_SELECT(fd) requires that ValidSocket(fd) has been checked ** before. */ # ifdef WIN32 # include # define SM_FD_SET(fd, pfdset) _FD_SET(fd, pfdset) # define SM_FD_ISSET(fd, pfdset) _FD_ISSET(fd, pfdset) # define SM_FD_SETSIZE FD_SETSIZE # define SM_FD_OK_SELECT(fd) true # else /* WIN32 */ # define SM_FD_SET(fd, pfdset) FD_SET(fd, pfdset) # define SM_FD_ISSET(fd, pfdset) FD_ISSET(fd, pfdset) # define SM_FD_SETSIZE FD_SETSIZE # define SM_FD_OK_SELECT(fd) (FD_SETSIZE <= 0 || (fd) < FD_SETSIZE) # endif /* WIN32 */ #endif /* SM_FDSET_H */ dk-milter-1.0.0.dfsg/include/sm/sysexits.h0000644000175000017500000001036007252462231020175 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sysexits.h,v 1.5 2001/03/10 17:30:01 ca Exp $ * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 */ #ifndef SM_SYSEXITS_H # define SM_SYSEXITS_H # include /* ** SYSEXITS.H -- Exit status codes for system programs. ** ** This include file attempts to categorize possible error ** exit statuses for system programs, notably delivermail ** and the Berkeley network. ** ** Error numbers begin at EX__BASE to reduce the possibility of ** clashing with other exit statuses that random programs may ** already return. The meaning of the codes is approximately ** as follows: ** ** EX_USAGE -- The command was used incorrectly, e.g., with ** the wrong number of arguments, a bad flag, a bad ** syntax in a parameter, or whatever. ** EX_DATAERR -- The input data was incorrect in some way. ** This should only be used for user's data & not ** system files. ** EX_NOINPUT -- An input file (not a system file) did not ** exist or was not readable. This could also include ** errors like "No message" to a mailer (if it cared ** to catch it). ** EX_NOUSER -- The user specified did not exist. This might ** be used for mail addresses or remote logins. ** EX_NOHOST -- The host specified did not exist. This is used ** in mail addresses or network requests. ** EX_UNAVAILABLE -- A service is unavailable. This can occur ** if a support program or file does not exist. This ** can also be used as a catchall message when something ** you wanted to do doesn't work, but you don't know ** why. ** EX_SOFTWARE -- An internal software error has been detected. ** This should be limited to non-operating system related ** errors as possible. ** EX_OSERR -- An operating system error has been detected. ** This is intended to be used for such things as "cannot ** fork", "cannot create pipe", or the like. It includes ** things like getuid returning a user that does not ** exist in the passwd file. ** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, ** etc.) does not exist, cannot be opened, or has some ** sort of error (e.g., syntax error). ** EX_CANTCREAT -- A (user specified) output file cannot be ** created. ** EX_IOERR -- An error occurred while doing I/O on some file. ** EX_TEMPFAIL -- temporary failure, indicating something that ** is not really an error. In sendmail, this means ** that a mailer (e.g.) could not create a connection, ** and the request should be reattempted later. ** EX_PROTOCOL -- the remote system returned something that ** was "not possible" during a protocol exchange. ** EX_NOPERM -- You did not have sufficient permission to ** perform the operation. This is not intended for ** file system problems, which should use NOINPUT or ** CANTCREAT, but rather for higher level permissions. */ # if SM_CONF_SYSEXITS_H # include # else /* SM_CONF_SYSEXITS_H */ # define EX_OK 0 /* successful termination */ # define EX__BASE 64 /* base value for error messages */ # define EX_USAGE 64 /* command line usage error */ # define EX_DATAERR 65 /* data format error */ # define EX_NOINPUT 66 /* cannot open input */ # define EX_NOUSER 67 /* addressee unknown */ # define EX_NOHOST 68 /* host name unknown */ # define EX_UNAVAILABLE 69 /* service unavailable */ # define EX_SOFTWARE 70 /* internal software error */ # define EX_OSERR 71 /* system error (e.g., can't fork) */ # define EX_OSFILE 72 /* critical OS file missing */ # define EX_CANTCREAT 73 /* can't create (user) output file */ # define EX_IOERR 74 /* input/output error */ # define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ # define EX_PROTOCOL 76 /* remote error in protocol */ # define EX_NOPERM 77 /* permission denied */ # define EX_CONFIG 78 /* configuration error */ # define EX__MAX 78 /* maximum listed value */ # endif /* SM_CONF_SYSEXITS_H */ extern char *sm_strexit __P((int)); extern char *sm_sysexitmsg __P((int)); extern char *sm_sysexmsg __P((int)); #endif /* ! SM_SYSEXITS_H */ dk-milter-1.0.0.dfsg/include/sm/xtrap.h0000644000175000017500000000155707262226375017460 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: xtrap.h,v 1.7 2001/04/03 01:53:01 gshapiro Exp $ */ /* ** scaffolding for testing exception handler code */ #ifndef SM_XTRAP_H # define SM_XTRAP_H # include # include extern SM_ATOMIC_UINT_T SmXtrapCount; extern SM_DEBUG_T SmXtrapDebug; extern SM_DEBUG_T SmXtrapReport; # if SM_DEBUG_CHECK # define sm_xtrap_check() (++SmXtrapCount == sm_debug_level(&SmXtrapDebug)) # else /* SM_DEBUG_CHECK */ # define sm_xtrap_check() (0) # endif /* SM_DEBUG_CHECK */ # define sm_xtrap_raise_x(exc) \ if (sm_xtrap_check()) \ { \ sm_exc_raise_x(exc); \ } else #endif /* ! SM_XTRAP_H */ dk-milter-1.0.0.dfsg/include/sm/limits.h0000644000175000017500000000254307251575434017620 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: limits.h,v 1.6 2001/03/08 03:23:08 ca Exp $ */ /* ** ** This header file is a portability wrapper for . ** It includes , then it ensures that the following macros ** from the C 1999 standard for are defined: ** LLONG_MIN, LLONG_MAX ** ULLONG_MAX */ #ifndef SM_LIMITS_H # define SM_LIMITS_H # include # include # include /* ** The following assumes two's complement binary arithmetic. */ # ifndef LLONG_MIN # define LLONG_MIN ((LONGLONG_T)(~(ULLONG_MAX >> 1))) # endif /* ! LLONG_MIN */ # ifndef LLONG_MAX # define LLONG_MAX ((LONGLONG_T)(ULLONG_MAX >> 1)) # endif /* ! LLONG_MAX */ # ifndef ULLONG_MAX # define ULLONG_MAX ((ULONGLONG_T)(-1)) # endif /* ! ULLONG_MAX */ /* ** PATH_MAX is defined by the POSIX standard. All modern systems ** provide it. Older systems define MAXPATHLEN in instead. */ # ifndef PATH_MAX # ifdef MAXPATHLEN # define PATH_MAX MAXPATHLEN # else /* MAXPATHLEN */ # define PATH_MAX 2048 # endif /* MAXPATHLEN */ # endif /* ! PATH_MAX */ #endif /* ! SM_LIMITS_H */ dk-milter-1.0.0.dfsg/include/sm/io.h0000644000175000017500000002766010021427251016713 0ustar madhackmadhack/* * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: io.h,v 1.24 2004/03/03 19:14:49 ca Exp $ */ /*- * @(#)stdio.h 5.17 (Berkeley) 6/3/91 */ #ifndef SM_IO_H #define SM_IO_H #include #include #include #ifdef WIN32 # include typedef _off_t off_t; #endif /* WIN32 */ /* mode for sm io (exposed) */ #define SM_IO_RDWR 1 /* read-write */ #define SM_IO_RDONLY 2 /* read-only */ #define SM_IO_WRONLY 3 /* write-only */ #define SM_IO_APPEND 4 /* write-only from eof */ #define SM_IO_APPENDRW 5 /* read-write from eof */ #define SM_IO_RDWRTR 6 /* read-write with truncation indicated */ #ifdef WIN32 # define SM_IO_BINARY 0x10 /* binary mode */ #else /* WIN32 */ # define SM_IO_BINARY 0x0 /* binary mode: not used in Unix */ #endif /* WIN32 */ #define SM_IS_BINARY(mode) (((mode) & SM_IO_BINARY) != 0) #define SM_IO_MODE(mode) ((mode) & 0x0f) #define SM_IO_RDWR_B (SM_IO_RDWR|SM_IO_BINARY) #define SM_IO_RDONLY_B (SM_IO_RDONLY|SM_IO_BINARY) #define SM_IO_WRONLY_B (SM_IO_WRONLY|SM_IO_BINARY) #define SM_IO_APPEND_B (SM_IO_APPEND|SM_IO_BINARY) #define SM_IO_APPENDRW_B (SM_IO_APPENDRW|SM_IO_BINARY) #define SM_IO_RDWRTR_B (SM_IO_RDWRTR|SM_IO_BINARY) /* for sm_io_fseek, et al api's (exposed) */ #define SM_IO_SEEK_SET 0 #define SM_IO_SEEK_CUR 1 #define SM_IO_SEEK_END 2 /* flags for info what's with different types (exposed) */ #define SM_IO_WHAT_MODE 1 #define SM_IO_WHAT_VECTORS 2 #define SM_IO_WHAT_FD 3 #define SM_IO_WHAT_TYPE 4 #define SM_IO_WHAT_ISTYPE 5 #define SM_IO_IS_READABLE 6 #define SM_IO_WHAT_TIMEOUT 7 #define SM_IO_WHAT_SIZE 8 /* info flags (exposed) */ #define SM_IO_FTYPE_CREATE 1 #define SM_IO_FTYPE_MODIFY 2 #define SM_IO_FTYPE_DELETE 3 #define SM_IO_SL_PRIO 1 #define SM_IO_OPEN_MAX 20 /* for internal buffers */ struct smbuf { unsigned char *smb_base; int smb_size; }; /* ** sm I/O state variables (internal only). ** ** The following always hold: ** ** if (flags&(SMLBF|SMWR)) == (SMLBF|SMWR), ** lbfsize is -bf.size, else lbfsize is 0 ** if flags&SMRD, w is 0 ** if flags&SMWR, r is 0 ** ** This ensures that the getc and putc macros (or inline functions) never ** try to write or read from a file that is in `read' or `write' mode. ** (Moreover, they can, and do, automatically switch from read mode to ** write mode, and back, on "r+" and "w+" files.) ** ** lbfsize is used only to make the inline line-buffered output stream ** code as compact as possible. ** ** ub, up, and ur are used when ungetc() pushes back more characters ** than fit in the current bf, or when ungetc() pushes back a character ** that does not match the previous one in bf. When this happens, ** ub.base becomes non-nil (i.e., a stream has ungetc() data iff ** ub.base!=NULL) and up and ur save the current values of p and r. */ typedef struct sm_file SM_FILE_T; struct sm_file { const char *sm_magic; /* This SM_FILE_T is free when NULL */ unsigned char *f_p; /* current position in (some) buffer */ int f_r; /* read space left for getc() */ int f_w; /* write space left for putc() */ long f_flags; /* flags, below */ short f_file; /* fileno, if Unix fd, else -1 */ struct smbuf f_bf; /* the buffer (>= 1 byte, if !NULL) */ int f_lbfsize; /* 0 or -bf.size, for inline putc */ /* These can be used for any purpose by a file type implementation: */ void *f_cookie; int f_ival; /* operations */ int (*f_close) __P((SM_FILE_T *)); ssize_t (*f_read) __P((SM_FILE_T *, char *, size_t)); off_t (*f_seek) __P((SM_FILE_T *, off_t, int)); ssize_t (*f_write) __P((SM_FILE_T *, const char *, size_t)); int (*f_open) __P((SM_FILE_T *, const void *, int, const void *)); int (*f_setinfo) __P((SM_FILE_T *, int , void *)); int (*f_getinfo) __P((SM_FILE_T *, int , void *)); int f_timeout; int f_timeoutstate; /* either blocking or non-blocking */ char *f_type; /* for by-type lookups */ struct sm_file *f_flushfp; /* flush this before reading parent */ struct sm_file *f_modefp; /* sync mode with this fp */ /* separate buffer for long sequences of ungetc() */ struct smbuf f_ub; /* ungetc buffer */ unsigned char *f_up; /* saved f_p when f_p is doing ungetc */ int f_ur; /* saved f_r when f_r is counting ungetc */ /* tricks to meet minimum requirements even when malloc() fails */ unsigned char f_ubuf[3]; /* guarantee an ungetc() buffer */ unsigned char f_nbuf[1]; /* guarantee a getc() buffer */ /* Unix stdio files get aligned to block boundaries on fseek() */ int f_blksize; /* stat.st_blksize (may be != bf.size) */ off_t f_lseekoff; /* current lseek offset */ int f_dup_cnt; /* count file dup'd */ }; __BEGIN_DECLS extern SM_FILE_T SmIoF[]; extern const char SmFileMagic[]; extern SM_FILE_T SmFtStdio_def; extern SM_FILE_T SmFtStdiofd_def; extern SM_FILE_T SmFtString_def; extern SM_FILE_T SmFtSyslog_def; extern SM_FILE_T SmFtRealStdio_def; #define SMIOIN_FILENO 0 #define SMIOOUT_FILENO 1 #define SMIOERR_FILENO 2 #define SMIOSTDIN_FILENO 3 #define SMIOSTDOUT_FILENO 4 #define SMIOSTDERR_FILENO 5 /* Common predefined and already (usually) open files (exposed) */ #define smioin (&SmIoF[SMIOIN_FILENO]) #define smioout (&SmIoF[SMIOOUT_FILENO]) #define smioerr (&SmIoF[SMIOERR_FILENO]) #define smiostdin (&SmIoF[SMIOSTDIN_FILENO]) #define smiostdout (&SmIoF[SMIOSTDOUT_FILENO]) #define smiostderr (&SmIoF[SMIOSTDERR_FILENO]) #define SmFtStdio (&SmFtStdio_def) #define SmFtStdiofd (&SmFtStdiofd_def) #define SmFtString (&SmFtString_def) #define SmFtSyslog (&SmFtSyslog_def) #define SmFtRealStdio (&SmFtRealStdio_def) #ifdef __STDC__ # define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \ (f) = {SmFileMagic, (unsigned char *) 0, 0, 0, 0L, -1, {0}, 0, (void *) 0,\ 0, (close), (read), (seek), (write), (open), (set), (get), (timeout),\ 0, (name)} # define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) #else /* __STDC__ */ # define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) (f) # define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \ (f).sm_magic = SmFileMagic; \ (f).f_p = (unsigned char *) 0; \ (f).f_r = 0; \ (f).f_w = 0; \ (f).f_flags = 0L; \ (f).f_file = 0; \ (f).f_bf.smb_base = (unsigned char *) 0; \ (f).f_bf.smb_size = 0; \ (f).f_lbfsize = 0; \ (f).f_cookie = (void *) 0; \ (f).f_ival = 0; \ (f).f_close = (close); \ (f).f_read = (read); \ (f).f_seek = (seek); \ (f).f_write = (write); \ (f).f_open = (open); \ (f).f_setinfo = (set); \ (f).f_getinfo = (get); \ (f).f_timeout = (timeout); \ (f).f_timeoutstate = 0; \ (f).f_type = (name); #endif /* __STDC__ */ __END_DECLS /* Internal flags */ #define SMFBF 0x000001 /* XXXX fully buffered */ #define SMLBF 0x000002 /* line buffered */ #define SMNBF 0x000004 /* unbuffered */ #define SMNOW 0x000008 /* Flush each write; take read now */ #define SMRD 0x000010 /* OK to read */ #define SMWR 0x000020 /* OK to write */ /* RD and WR are never simultaneously asserted */ #define SMRW 0x000040 /* open for reading & writing */ #define SMFEOF 0x000080 /* found EOF */ #define SMERR 0x000100 /* found error */ #define SMMBF 0x000200 /* buf is from malloc */ #define SMAPP 0x000400 /* fdopen()ed in append mode */ #define SMSTR 0x000800 /* this is an snprintf string */ #define SMOPT 0x001000 /* do fseek() optimisation */ #define SMNPT 0x002000 /* do not do fseek() optimisation */ #define SMOFF 0x004000 /* set iff offset is in fact correct */ #define SMALC 0x010000 /* allocate string space dynamically */ #define SMMODEMASK 0x0070 /* read/write mode */ /* defines for timeout constants */ #define SM_TIME_IMMEDIATE (0) #define SM_TIME_FOREVER (-1) #define SM_TIME_DEFAULT (-2) /* timeout state for blocking */ #define SM_TIME_BLOCK (0) /* XXX just bool? */ #define SM_TIME_NONBLOCK (1) /* Exposed buffering type flags */ #define SM_IO_FBF 0 /* setvbuf should set fully buffered */ #define SM_IO_LBF 1 /* setvbuf should set line buffered */ #define SM_IO_NBF 2 /* setvbuf should set unbuffered */ /* setvbuf buffered, but through at lower file type layers */ #define SM_IO_NOW 3 /* ** size of buffer used by setbuf. ** If underlying filesystem blocksize is discoverable that is used instead */ #define SM_IO_BUFSIZ 4096 #define SM_IO_EOF (-1) /* Functions defined in ANSI C standard. */ __BEGIN_DECLS SM_FILE_T *sm_io_autoflush __P((SM_FILE_T *, SM_FILE_T *)); void sm_io_automode __P((SM_FILE_T *, SM_FILE_T *)); void sm_io_clearerr __P((SM_FILE_T *)); int sm_io_close __P((SM_FILE_T *, int SM_NONVOLATILE)); SM_FILE_T *sm_io_dup __P((SM_FILE_T *)); int sm_io_eof __P((SM_FILE_T *)); int sm_io_error __P((SM_FILE_T *)); char *sm_io_fgets __P((SM_FILE_T *, int, char *, int)); int sm_io_flush __P((SM_FILE_T *, int SM_NONVOLATILE)); int PRINTFLIKE(3, 4) sm_io_fprintf __P((SM_FILE_T *, int, const char *, ...)); int sm_io_fputs __P((SM_FILE_T *, int, const char *)); int SCANFLIKE(3, 4) sm_io_fscanf __P((SM_FILE_T *, int, const char *, ...)); int sm_io_getc __P((SM_FILE_T *, int)); int sm_io_getinfo __P((SM_FILE_T *, int, void *)); SM_FILE_T *sm_io_open __P((const SM_FILE_T *, int SM_NONVOLATILE, const void *, int, const void *)); int sm_io_purge __P((SM_FILE_T *)); int sm_io_putc __P((SM_FILE_T *, int, int)); size_t sm_io_read __P((SM_FILE_T *, int, void *, size_t)); SM_FILE_T *sm_io_reopen __P((const SM_FILE_T *, int SM_NONVOLATILE, const void *, int, const void *, SM_FILE_T *)); void sm_io_rewind __P((SM_FILE_T *, int)); int sm_io_seek __P((SM_FILE_T *, int SM_NONVOLATILE, long SM_NONVOLATILE, int SM_NONVOLATILE)); int sm_io_setinfo __P((SM_FILE_T *, int, void *)); int sm_io_setvbuf __P((SM_FILE_T *, int, char *, int, size_t)); int SCANFLIKE(2, 3) sm_io_sscanf __P((const char *, char const *, ...)); long sm_io_tell __P((SM_FILE_T *, int SM_NONVOLATILE)); int sm_io_ungetc __P((SM_FILE_T *, int, int)); int sm_io_vfprintf __P((SM_FILE_T *, int, const char *, va_list)); size_t sm_io_write __P((SM_FILE_T *, int, const void *, size_t)); void sm_strio_init __P((SM_FILE_T *, char *, size_t)); extern SM_FILE_T * sm_io_fopen __P(( char *_pathname, int _flags, ...)); extern SM_FILE_T * sm_io_stdioopen __P(( FILE *_stream, char *_mode)); extern int sm_vasprintf __P(( char **_str, const char *_fmt, va_list _ap)); extern int sm_vsnprintf __P(( char *, size_t, const char *, va_list)); extern void sm_perror __P(( const char *)); __END_DECLS /* ** Functions internal to the implementation. */ __BEGIN_DECLS int sm_rget __P((SM_FILE_T *, int)); int sm_vfscanf __P((SM_FILE_T *, int SM_NONVOLATILE, const char *, va_list SM_NONVOLATILE)); int sm_wbuf __P((SM_FILE_T *, int, int)); __END_DECLS /* ** The macros are here so that we can ** define function versions in the library. */ #define sm_getc(f, t) \ (--(f)->f_r < 0 ? \ sm_rget(f, t) : \ (int)(*(f)->f_p++)) /* ** This has been tuned to generate reasonable code on the vax using pcc. ** (It also generates reasonable x86 code using gcc.) */ #define sm_putc(f, t, c) \ (--(f)->f_w < 0 ? \ (f)->f_w >= (f)->f_lbfsize ? \ (*(f)->f_p = (c)), *(f)->f_p != '\n' ? \ (int)*(f)->f_p++ : \ sm_wbuf(f, t, '\n') : \ sm_wbuf(f, t, (int)(c)) : \ (*(f)->f_p = (c), (int)*(f)->f_p++)) #define sm_eof(p) (((p)->f_flags & SMFEOF) != 0) #define sm_error(p) (((p)->f_flags & SMERR) != 0) #define sm_clearerr(p) ((void)((p)->f_flags &= ~(SMERR|SMFEOF))) #define sm_io_eof(p) sm_eof(p) #define sm_io_error(p) sm_error(p) #define sm_io_clearerr(p) sm_clearerr(p) #ifndef lint # ifndef _POSIX_SOURCE # define sm_io_getc(fp, t) sm_getc(fp, t) # define sm_io_putc(fp, t, x) sm_putc(fp, t, x) # endif /* _POSIX_SOURCE */ #endif /* lint */ #endif /* SM_IO_H */ dk-milter-1.0.0.dfsg/include/sm/cdefs.h0000644000175000017500000001021107764205205017365 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: cdefs.h,v 1.16 2003/12/05 22:45:25 ca Exp $ */ /* ** libsm C language portability macros ** See libsm/cdefs.html for documentation. */ #ifndef SM_CDEFS_H # define SM_CDEFS_H # include /* ** BSD and Linux have which defines a set of C language ** portability macros that are a defacto standard in the open source ** community. */ # if SM_CONF_SYS_CDEFS_H # include # endif /* SM_CONF_SYS_CDEFS_H */ /* ** Define the standard C language portability macros ** for platforms that lack . */ # if !SM_CONF_SYS_CDEFS_H # if defined(__cplusplus) # define __BEGIN_DECLS extern "C" { # define __END_DECLS }; # else /* defined(__cplusplus) */ # define __BEGIN_DECLS # define __END_DECLS # endif /* defined(__cplusplus) */ # if defined(__STDC__) || defined(__cplusplus) # ifndef __P # define __P(protos) protos # endif /* __P */ # define __CONCAT(x,y) x ## y # define __STRING(x) #x # else /* defined(__STDC__) || defined(__cplusplus) */ # define __P(protos) () # define __CONCAT(x,y) x/**/y # define __STRING(x) "x" # define const # define signed # define volatile # endif /* defined(__STDC__) || defined(__cplusplus) */ # endif /* !SM_CONF_SYS_CDEFS_H */ /* ** Define SM_DEAD, a macro used to declare functions that do not return ** to their caller. */ # ifndef SM_DEAD # if __GNUC__ >= 2 # if __GNUC__ == 2 && __GNUC_MINOR__ < 5 # define SM_DEAD(proto) volatile proto # define SM_DEAD_D volatile # else /* __GNUC__ == 2 && __GNUC_MINOR__ < 5 */ # define SM_DEAD(proto) proto __attribute__((__noreturn__)) # define SM_DEAD_D # endif /* __GNUC__ == 2 && __GNUC_MINOR__ < 5 */ # else /* __GNUC__ >= 2 */ # define SM_DEAD(proto) proto # define SM_DEAD_D # endif /* __GNUC__ >= 2 */ # endif /* SM_DEAD */ /* ** Define SM_UNUSED, a macro used to declare variables that may be unused. */ # ifndef SM_UNUSED # if __GNUC__ >= 2 # if __GNUC__ == 2 && __GNUC_MINOR__ < 7 # define SM_UNUSED(decl) decl # else /* __GNUC__ == 2 && __GNUC_MINOR__ < 7 */ # define SM_UNUSED(decl) decl __attribute__((__unused__)) # endif /* __GNUC__ == 2 && __GNUC_MINOR__ < 7 */ # else /* __GNUC__ >= 2 */ # define SM_UNUSED(decl) decl # endif /* __GNUC__ >= 2 */ # endif /* SM_UNUSED */ /* ** The SM_NONVOLATILE macro is used to declare variables that are not ** volatile, but which must be declared volatile when compiling with ** gcc -O -Wall in order to suppress bogus warning messages. ** ** Variables that actually are volatile should be declared volatile ** using the "volatile" keyword. If a variable actually is volatile, ** then SM_NONVOLATILE should not be used. ** ** To compile sendmail with gcc and see all non-bogus warnings, ** you should use ** gcc -O -Wall -DSM_OMIT_BOGUS_WARNINGS ... ** Do not use -DSM_OMIT_BOGUS_WARNINGS when compiling the production ** version of sendmail, because there is a performance hit. */ # ifdef SM_OMIT_BOGUS_WARNINGS # define SM_NONVOLATILE volatile # else /* SM_OMIT_BOGUS_WARNINGS */ # define SM_NONVOLATILE # endif /* SM_OMIT_BOGUS_WARNINGS */ /* ** Turn on format string argument checking. */ # ifndef SM_CONF_FORMAT_TEST # if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 # define SM_CONF_FORMAT_TEST 1 # else /* __GNUC__ == 2 && __GNUC_MINOR__ >= 7 */ # define SM_CONF_FORMAT_TEST 0 # endif /* __GNUC__ == 2 && __GNUC_MINOR__ >= 7 */ # endif /* SM_CONF_FORMAT_TEST */ # ifndef PRINTFLIKE # if SM_CONF_FORMAT_TEST # define PRINTFLIKE(x,y) __attribute__ ((__format__ (__printf__, x, y))) # else /* SM_CONF_FORMAT_TEST */ # define PRINTFLIKE(x,y) # endif /* SM_CONF_FORMAT_TEST */ # endif /* ! PRINTFLIKE */ # ifndef SCANFLIKE # if SM_CONF_FORMAT_TEST # define SCANFLIKE(x,y) __attribute__ ((__format__ (__scanf__, x, y))) # else /* SM_CONF_FORMAT_TEST */ # define SCANFLIKE(x,y) # endif /* SM_CONF_FORMAT_TEST */ # endif /* ! SCANFLIKE */ #endif /* ! SM_CDEFS_H */ dk-milter-1.0.0.dfsg/include/sm/heap.h0000644000175000017500000000632410470215432017217 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: heap.h,v 1.23 2006/08/15 00:53:46 ca Exp $ */ /* ** Sendmail debugging memory allocation package. ** See libsm/heap.html for documentation. */ #ifndef SM_HEAP_H # define SM_HEAP_H # include # include # include # include /* change default to 0 for production? */ # ifndef SM_HEAP_CHECK # define SM_HEAP_CHECK 1 # endif /* ! SM_HEAP_CHECK */ # if SM_HEAP_CHECK # define sm_malloc_x(sz) sm_malloc_tagged_x(sz, __FILE__, __LINE__, SmHeapGroup) # define sm_malloc(size) sm_malloc_tagged(size, __FILE__, __LINE__, SmHeapGroup) # define sm_free(ptr) sm_free_tagged(ptr, __FILE__, __LINE__) extern void *sm_malloc_tagged __P((size_t, char *, int, int)); extern void *sm_malloc_tagged_x __P((size_t, char *, int, int)); extern void sm_free_tagged __P((void *, char *, int)); extern void *sm_realloc_x __P((void *, size_t)); extern bool sm_heap_register __P((void *, size_t, char *, int, int)); extern void sm_heap_checkptr_tagged __P((void *, char *, int)); extern void sm_heap_report __P((SM_FILE_T *, int)); # else /* SM_HEAP_CHECK */ # define sm_malloc_tagged(size, file, line, grp) sm_malloc(size) # define sm_malloc_tagged_x(size, file, line, grp) sm_malloc_x(size) # define sm_free_tagged(ptr, file, line) sm_free(ptr) # define sm_heap_register(ptr, size, file, line, grp) (true) # define sm_heap_checkptr_tagged(ptr, tag, num) ((void)0) # define sm_heap_report(file, verbose) ((void)0) extern void *sm_malloc __P((size_t)); extern void *sm_malloc_x __P((size_t)); extern void *sm_realloc_x __P((void *, size_t)); extern void sm_free __P((void *)); # endif /* SM_HEAP_CHECK */ extern void *sm_realloc __P((void *, size_t)); # define sm_heap_checkptr(ptr) sm_heap_checkptr_tagged(ptr, __FILE__, __LINE__) #if 0 /* ** sm_f[mc]alloc are plug in replacements for malloc and calloc ** which can be used in a context requiring a function pointer, ** and which are compatible with sm_free. Warning: sm_heap_report ** cannot report where storage leaked by sm_f[mc]alloc was allocated. */ /* XXX unused right now */ extern void * sm_fmalloc __P(( size_t)); extern void * sm_fcalloc __P(( size_t, size_t)); #endif /* 0 */ /* ** Allocate 'permanent' storage that can be freed but may still be ** allocated when the process exits. sm_heap_report will not complain ** about a storage leak originating from a call to sm_pmalloc. */ # define sm_pmalloc(size) sm_malloc_tagged(size, __FILE__, __LINE__, 0) # define sm_pmalloc_x(size) sm_malloc_tagged_x(size, __FILE__, __LINE__, 0) # define sm_heap_group() SmHeapGroup # define sm_heap_setgroup(g) (SmHeapGroup = (g)) # define sm_heap_newgroup() (SmHeapGroup = ++SmHeapMaxGroup) #define SM_FREE(ptr) \ do \ { \ if ((ptr) != NULL) \ { \ sm_free(ptr); \ (ptr) = NULL; \ } \ } while (0) extern int SmHeapGroup; extern int SmHeapMaxGroup; extern SM_DEBUG_T SmHeapTrace; extern SM_DEBUG_T SmHeapCheck; extern SM_EXC_T SmHeapOutOfMemory; #endif /* ! SM_HEAP_H */ dk-milter-1.0.0.dfsg/include/sm/shm.h0000644000175000017500000000215110171576300017065 0ustar madhackmadhack/* * Copyright (c) 2000-2003, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: shm.h,v 1.11 2005/01/13 22:57:04 ca Exp $ */ #ifndef SM_SHM_H # define SM_SHM_H # if SM_CONF_SHM # include # include # include /* # include "def.h" */ /* key for shared memory */ # define SM_SHM_KEY ((key_t) 42) /* return value for failed shmget() */ # define SM_SHM_NULL ((void *) -1) # define SM_SHM_NO_ID (-2) extern void *sm_shmstart __P((key_t, int , int , int *, bool)); extern int sm_shmstop __P((void *, int, bool)); extern int sm_shmsetowner __P((int, uid_t, gid_t, mode_t)); # ifdef WIN32 extern char const *get_shm_path __P((void)); # endif /* WIN32 */ /* for those braindead systems... (e.g., SunOS 4) */ # ifndef SHM_R # define SHM_R 0400 # endif /* SHM_R */ # ifndef SHM_W # define SHM_W 0200 # endif /* SHM_W */ # endif /* SM_CONF_SHM */ #endif /* ! SM_SHM_H */ dk-milter-1.0.0.dfsg/include/sm/config.h0000644000175000017500000001126610137542163017554 0ustar madhackmadhack/* * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: config.h,v 1.47 2004/10/26 21:41:07 gshapiro Exp $ */ /* ** libsm configuration macros. ** The values of these macros are platform dependent. ** The default values are given here. ** If the default is incorrect, then the correct value can be specified ** in the m4 configuration file in devtools/OS. */ #ifndef SM_CONFIG_H # define SM_CONFIG_H # ifdef WIN32 # include # else /* WIN32 */ # include "sm_os.h" # endif /* WIN32 */ /* ** SM_CONF_STDBOOL_H is 1 if exists */ # ifndef SM_CONF_STDBOOL_H # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L # define SM_CONF_STDBOOL_H 1 # else /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ # define SM_CONF_STDBOOL_H 0 # endif /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ # endif /* ! SM_CONF_STDBOOL_H */ /* ** Configuration macros that specify how __P is defined. */ # ifndef SM_CONF_SYS_CDEFS_H # define SM_CONF_SYS_CDEFS_H 0 # endif /* ! SM_CONF_SYS_CDEFS_H */ /* ** SM_CONF_STDDEF_H is 1 if exists */ # ifndef SM_CONF_STDDEF_H # define SM_CONF_STDDEF_H 1 # endif /* ! SM_CONF_STDDEF_H */ /* ** Configuration macro that specifies whether strlcpy/strlcat are available. ** Note: this is the default so that the libsm version (optimized) will ** be used by default (sm_strlcpy/sm_strlcat). */ # ifndef SM_CONF_STRL # define SM_CONF_STRL 0 # endif /* ! SM_CONF_STRL */ /* ** Configuration macro indicating that setitimer is available */ # ifndef SM_CONF_SETITIMER # define SM_CONF_SETITIMER 1 # endif /* ! SM_CONF_SETITIMER */ /* ** Does define uid_t and gid_t? */ # ifndef SM_CONF_UID_GID # define SM_CONF_UID_GID 1 # endif /* ! SM_CONF_UID_GID */ /* ** Does define ssize_t? */ # ifndef SM_CONF_SSIZE_T # define SM_CONF_SSIZE_T 1 # endif /* ! SM_CONF_SSIZE_T */ /* ** Does the C compiler support long long? */ # ifndef SM_CONF_LONGLONG # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L # define SM_CONF_LONGLONG 1 # else /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ # if defined(__GNUC__) # define SM_CONF_LONGLONG 1 # else /* defined(__GNUC__) */ # define SM_CONF_LONGLONG 0 # endif /* defined(__GNUC__) */ # endif /* defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ # endif /* ! SM_CONF_LONGLONG */ /* ** Does define quad_t and u_quad_t? ** We only care if long long is not available. */ # ifndef SM_CONF_QUAD_T # define SM_CONF_QUAD_T 0 # endif /* ! SM_CONF_QUAD_T */ /* ** Configuration macro indicating that shared memory is available */ # ifndef SM_CONF_SHM # define SM_CONF_SHM 0 # endif /* ! SM_CONF_SHM */ /* ** Does define sigsetjmp? */ # ifndef SM_CONF_SIGSETJMP # define SM_CONF_SIGSETJMP 1 # endif /* ! SM_CONF_SIGSETJMP */ /* ** Does exist, and define the EX_* macros with values ** that differ from the default BSD values in ? */ # ifndef SM_CONF_SYSEXITS_H # define SM_CONF_SYSEXITS_H 0 # endif /* ! SM_CONF_SYSEXITS_H */ /* has memchr() prototype? (if not: needs memory.h) */ # ifndef SM_CONF_MEMCHR # define SM_CONF_MEMCHR 1 # endif /* ! SM_CONF_MEMCHR */ /* try LLONG tests in libsm/t-types.c? */ # ifndef SM_CONF_TEST_LLONG # define SM_CONF_TEST_LLONG 1 # endif /* !SM_CONF_TEST_LLONG */ /* LDAP Checks */ # if LDAPMAP # include # include /* Does the LDAP library have ldap_memfree()? */ # ifndef SM_CONF_LDAP_MEMFREE /* ** The new LDAP C API (draft-ietf-ldapext-ldap-c-api-04.txt) includes ** ldap_memfree() in the API. That draft states to use LDAP_API_VERSION ** of 2004 to identify the API. */ # if USING_NETSCAPE_LDAP || LDAP_API_VERSION >= 2004 # define SM_CONF_LDAP_MEMFREE 1 # else /* USING_NETSCAPE_LDAP || LDAP_API_VERSION >= 2004 */ # define SM_CONF_LDAP_MEMFREE 0 # endif /* USING_NETSCAPE_LDAP || LDAP_API_VERSION >= 2004 */ # endif /* ! SM_CONF_LDAP_MEMFREE */ /* Does the LDAP library have ldap_initialize()? */ # ifndef SM_CONF_LDAP_INITIALIZE /* ** Check for ldap_initialize() support for support for LDAP URI's with ** non-ldap:// schemes. */ /* OpenLDAP does it with LDAP_OPT_URI */ # ifdef LDAP_OPT_URI # define SM_CONF_LDAP_INITIALIZE 1 # endif /* LDAP_OPT_URI */ # endif /* !SM_CONF_LDAP_INITIALIZE */ # endif /* LDAPMAP */ /* don't use strcpy() */ # ifndef DO_NOT_USE_STRCPY # define DO_NOT_USE_STRCPY 1 # endif /* ! DO_NOT_USE_STRCPY */ #endif /* ! SM_CONFIG_H */ dk-milter-1.0.0.dfsg/include/sm/types.h0000644000175000017500000000326107262226375017460 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: types.h,v 1.13 2001/04/03 01:53:01 gshapiro Exp $ */ /* ** This header file defines standard integral types. ** - It includes , and fixes portability problems that ** exist on older Unix platforms. ** - It defines LONGLONG_T and ULONGLONG_T, which are portable locutions ** for 'long long' and 'unsigned long long'. */ #ifndef SM_TYPES_H # define SM_TYPES_H # include /* ** On BSD 4.2 systems, was not idempotent. ** This problem is circumvented by replacing all occurrences ** of with , which is idempotent. */ # include /* ** On some old Unix platforms, some of the standard types are missing. ** We fix that here. */ # if !SM_CONF_UID_GID # define uid_t int # define gid_t int # endif /* !SM_CONF_UID_GID */ # if !SM_CONF_SSIZE_T # define ssize_t int # endif /* !SM_CONF_SSIZE_T */ /* ** Define LONGLONG_T and ULONGLONG_T, which are portable locutions ** for 'long long' and 'unsigned long long' from the C 1999 standard. */ # if SM_CONF_LONGLONG typedef long long LONGLONG_T; typedef unsigned long long ULONGLONG_T; # else /* SM_CONF_LONGLONG */ # if SM_CONF_QUAD_T typedef quad_t LONGLONG_T; typedef u_quad_t ULONGLONG_T; # else /* SM_CONF_QUAD_T */ typedef long LONGLONG_T; typedef unsigned long ULONGLONG_T; # endif /* SM_CONF_QUAD_T */ # endif /* SM_CONF_LONGLONG */ #endif /* ! SM_TYPES_H */ dk-milter-1.0.0.dfsg/include/sm/rpool.h0000644000175000017500000001021007726213505017433 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: rpool.h,v 1.16 2003/09/05 23:07:49 ca Exp $ */ /* ** libsm resource pools ** See libsm/rpool.html for documentation. */ #ifndef SM_RPOOL_H # define SM_RPOOL_H # include # include # include /* ** Each memory pool object consists of an SM_POOLLINK_T, ** followed by a platform specific amount of padding, ** followed by 'poolsize' bytes of pool data, ** where 'poolsize' is the value of rpool->sm_poolsize at the time ** the pool is allocated. */ typedef struct sm_poollink SM_POOLLINK_T; struct sm_poollink { SM_POOLLINK_T *sm_pnext; }; typedef void (*SM_RPOOL_RFREE_T) __P((void *_rcontext)); typedef SM_RPOOL_RFREE_T *SM_RPOOL_ATTACH_T; typedef struct sm_resource SM_RESOURCE_T; struct sm_resource { /* ** Function for freeing this resource. It may be NULL, ** meaning that this resource has already been freed. */ SM_RPOOL_RFREE_T sm_rfree; void *sm_rcontext; /* resource data */ }; # define SM_RLIST_MAX 511 typedef struct sm_rlist SM_RLIST_T; struct sm_rlist { SM_RESOURCE_T sm_rvec[SM_RLIST_MAX]; SM_RLIST_T *sm_rnext; }; typedef struct { /* Points to SmRpoolMagic, or is NULL if rpool is freed. */ const char *sm_magic; /* ** If this rpool object has no parent, then sm_parentlink ** is NULL. Otherwise, we set *sm_parentlink = NULL ** when this rpool is freed, so that it isn't freed a ** second time when the parent is freed. */ SM_RPOOL_RFREE_T *sm_parentlink; /* ** Memory pools */ /* Size of the next pool to be allocated, not including the header. */ size_t sm_poolsize; /* ** If an sm_rpool_malloc_x request is too big to fit ** in the current pool, and the request size > bigobjectsize, ** then the object will be given its own malloc'ed block. ** sm_bigobjectsize <= sm_poolsize. The maximum wasted space ** at the end of a pool is maxpooledobjectsize - 1. */ size_t sm_bigobjectsize; /* Points to next free byte in the current pool. */ char *sm_poolptr; /* ** Number of bytes available in the current pool. ** Initially 0. Set to 0 by sm_rpool_free. */ size_t sm_poolavail; /* Linked list of memory pools. Initially NULL. */ SM_POOLLINK_T *sm_pools; /* ** Resource lists */ SM_RESOURCE_T *sm_rptr; /* Points to next free resource slot. */ /* ** Number of available resource slots in current list. ** Initially 0. Set to 0 by sm_rpool_free. */ size_t sm_ravail; /* Linked list of resource lists. Initially NULL. */ SM_RLIST_T *sm_rlists; #if _FFR_PERF_RPOOL int sm_nbigblocks; int sm_npools; #endif /* _FFR_PERF_RPOOL */ } SM_RPOOL_T; extern SM_RPOOL_T * sm_rpool_new_x __P(( SM_RPOOL_T *_parent)); extern void sm_rpool_free __P(( SM_RPOOL_T *_rpool)); # if SM_HEAP_CHECK extern void * sm_rpool_malloc_tagged_x __P(( SM_RPOOL_T *_rpool, size_t _size, char *_file, int _line, int _group)); # define sm_rpool_malloc_x(rpool, size) \ sm_rpool_malloc_tagged_x(rpool, size, __FILE__, __LINE__, SmHeapGroup) extern void * sm_rpool_malloc_tagged __P(( SM_RPOOL_T *_rpool, size_t _size, char *_file, int _line, int _group)); # define sm_rpool_malloc(rpool, size) \ sm_rpool_malloc_tagged(rpool, size, __FILE__, __LINE__, SmHeapGroup) # else /* SM_HEAP_CHECK */ extern void * sm_rpool_malloc_x __P(( SM_RPOOL_T *_rpool, size_t _size)); extern void * sm_rpool_malloc __P(( SM_RPOOL_T *_rpool, size_t _size)); # endif /* SM_HEAP_CHECK */ #if DO_NOT_USE_STRCPY extern char *sm_rpool_strdup_x __P((SM_RPOOL_T *rpool, const char *s)); #else /* DO_NOT_USE_STRCPY */ # define sm_rpool_strdup_x(rpool, str) \ strcpy(sm_rpool_malloc_x(rpool, strlen(str) + 1), str) #endif /* DO_NOT_USE_STRCPY */ extern SM_RPOOL_ATTACH_T sm_rpool_attach_x __P(( SM_RPOOL_T *_rpool, SM_RPOOL_RFREE_T _rfree, void *_rcontext)); # define sm_rpool_detach(a) ((void)(*(a) = NULL)) extern void sm_rpool_setsizes __P(( SM_RPOOL_T *_rpool, size_t _poolsize, size_t _bigobjectsize)); #endif /* ! SM_RPOOL_H */ dk-milter-1.0.0.dfsg/include/sm/varargs.h0000644000175000017500000000226607521332024017750 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: varargs.h,v 1.8 2002/07/29 21:31:00 gshapiro Exp $ */ /* ** libsm variable argument lists */ #ifndef SM_VARARGS_H # define SM_VARARGS_H # if defined(__STDC__) || defined(__cplusplus) # define SM_VA_STD 1 # include # define SM_VA_START(ap, f) va_start(ap, f) # else /* defined(__STDC__) || defined(__cplusplus) */ # define SM_VA_STD 0 # include # define SM_VA_START(ap, f) va_start(ap) # endif /* defined(__STDC__) || defined(__cplusplus) */ # if defined(va_copy) # define SM_VA_COPY(dst, src) va_copy((dst), (src)) # elif defined(__va_copy) # define SM_VA_COPY(dst, src) __va_copy((dst), (src)) # else # define SM_VA_COPY(dst, src) memcpy(&(dst), &(src), sizeof((dst))) # endif /* ** The following macros are useless, but are provided for symmetry. */ # define SM_VA_LOCAL_DECL va_list ap; # define SM_VA_ARG(ap, type) va_arg(ap, type) # define SM_VA_END(ap) va_end(ap) #endif /* ! SM_VARARGS_H */ dk-milter-1.0.0.dfsg/include/sm/conf.h0000644000175000017500000030420710676041301017230 0ustar madhackmadhack/* * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * * $Id: conf.h,v 1.134 2007/09/24 23:05:37 ca Exp $ */ /* ** CONF.H -- All user-configurable parameters for sendmail ** ** Send updates to Sendmail.ORG so they will be ** included in the next release; see ** http://www.sendmail.org/email-addresses.html ** for current e-mail address. */ #ifndef SM_CONF_H # define SM_CONF_H 1 # ifdef WIN32 # include # endif /* WIN32 */ # include # include /* ** General "standard C" defines. ** ** These may be undone later, to cope with systems that claim to ** be Standard C but aren't. Gcc is the biggest offender -- it ** doesn't realize that the library is part of the language. ** ** Life would be much easier if we could get rid of this sort ** of bozo problems. */ # ifdef __STDC__ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # endif /* __STDC__ */ /* ** Assume you have standard calls; can be #undefed below if necessary. */ # ifndef HASLSTAT # define HASLSTAT 1 /* has lstat(2) call */ # endif /* ! HASLSTAT */ # ifndef HASNICE # define HASNICE 1 /* has nice(2) call */ # endif /* ! HASNICE */ # ifndef HASRRESVPORT # define HASRRESVPORT 1 /* has rrsevport(3) call */ # endif /* ! HASRRESVPORT */ /********************************************************************** ** "Hard" compilation options. ** #define these if they are available; comment them out otherwise. ** These cannot be overridden from the Makefile, and should really not ** be turned off unless absolutely necessary. **********************************************************************/ #define LOG 1 /* enable logging -- don't turn off */ /********************************************************************** ** Operating system configuration. ** ** Unless you are porting to a new OS, you shouldn't have to ** change these. **********************************************************************/ /* ** HP-UX -- tested for 8.07, 9.00, and 9.01. ** ** If V4FS is defined, compile for HP-UX 10.0. ** 11.x support from Richard Allen . */ # ifdef __hpux /* common definitions for HP-UX 9.x and 10.x */ # undef m_flags /* conflict between Berkeley DB 1.85 db.h & sys/sysmacros.h on HP 300 */ # define SYSTEM5 1 /* include all the System V defines */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASSETRESGID 1 /* use setresgid(2) to set saved gid */ # define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ # define seteuid(e) setresuid(-1, e, -1) # define IP_SRCROUTE 1 /* can check IP source routing */ # define LA_TYPE LA_HPUX # define SPT_TYPE SPT_PSTAT # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # define GIDSET_T gid_t # define LDA_USE_LOCKF 1 # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ # endif /* ! HASGETUSERSHELL */ # ifdef HPUX10 # define _PATH_SENDMAIL "/usr/sbin/sendmail" # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/var/adm/sm.bin" # endif /* ! SMRSH_CMDDIR */ # endif /* HPUX10 */ # ifdef HPUX11 # define HASSETREUID 1 /* setreuid(2) works on HP-UX 11.x */ # define HASFCHOWN 1 /* has fchown(2) */ # ifndef BROKEN_RES_SEARCH # define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ # endif /* ! BROKEN_RES_SEARCH */ # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/var/adm/sm.bin" # endif /* ! SMRSH_CMDDIR */ # define _PATH_SENDMAIL "/usr/sbin/sendmail" # else /* HPUX11 */ # ifndef NOT_SENDMAIL # define syslog hard_syslog # endif /* ! NOT_SENDMAIL */ # endif /* HPUX11 */ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # ifdef V4FS /* HP-UX 10.x */ # define _PATH_UNIX "/stand/vmunix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # ifndef IDENTPROTO # define IDENTPROTO 1 /* TCP/IP implementation fixed in 10.0 */ # endif /* ! IDENTPROTO */ # include /* for mpctl() in get_num_procs_online() */ # else /* V4FS */ /* HP-UX 9.x */ # define _PATH_UNIX "/hp-ux" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # ifdef __STDC__ extern void hard_syslog(int, char *, ...); # else /* __STDC__ */ extern void hard_syslog(); # endif /* __STDC__ */ # define FDSET_CAST (int *) /* cast for fd_set parameters to select */ # endif /* V4FS */ # endif /* __hpux */ /* ** IBM AIX 5.x */ # ifdef _AIX5 # include # include # define _AIX4 40300 # define SOCKADDR_LEN_T socklen_t /* e.g., arg#3 to accept, getsockname */ # define SOCKOPT_LEN_T socklen_t /* arg#5 to getsockopt */ # if _AIX5 >= 50200 # define HASUNSETENV 1 /* has unsetenv(3) call */ # endif /* _AIX5 >= 50200 */ # endif /* _AIX5 */ /* ** IBM AIX 4.x */ # ifdef _AIX4 # define _AIX3 1 /* pull in AIX3 stuff */ # define BSD4_4_SOCKADDR /* has sa_len */ # define USESETEUID 1 /* seteuid(2) works */ # define TZ_TYPE TZ_NAME /* use tzname[] vector */ # ifndef SOCKOPT_LEN_T # define SOCKOPT_LEN_T size_t /* arg#5 to getsockopt */ # endif /* SOCKOPT_LEN_T */ # if _AIX4 >= 40200 # define HASSETREUID 1 /* setreuid(2) works as of AIX 4.2 */ # ifndef SOCKADDR_LEN_T # define SOCKADDR_LEN_T size_t /* e.g., arg#3 to accept, getsockname */ # endif /* SOCKADDR_LEN_T */ # endif /* _AIX4 >= 40200 */ # if defined(_ILS_MACROS) /* IBM versions aren't side-effect clean */ # undef isascii # define isascii(c) !(c & ~0177) # undef isdigit # define isdigit(__a) (_IS(__a,_ISDIGIT)) # undef isspace # define isspace(__a) (_IS(__a,_ISSPACE)) # endif /* defined(_ILS_MACROS) */ # endif /* _AIX4 */ /* ** IBM AIX 3.x -- actually tested for 3.2.3 */ # ifdef _AIX3 # include # include /* to get byte order */ # include # define HASFCHOWN 1 /* has fchown(2) */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define GIDSET_T gid_t # define SFS_TYPE SFS_STATFS /* use statfs() impl */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ # ifndef LA_TYPE # define LA_TYPE LA_INT # endif /* LA_TYPE */ # define FSHIFT 16 # define LA_AVENRUN "avenrun" # if !defined(_AIX4) || _AIX4 < 40300 # ifndef __BIT_TYPES_DEFINED__ # define SM_INT32 int # endif /* __BIT_TYPES_DEFINED__ */ # endif /* !defined(_AIX4) || _AIX4 < 40300 */ # if !defined(_AIX4) || _AIX4 < 40200 # define SM_CONF_SYSLOG 0 # endif /* !defined(_AIX4) || _AIX4 < 40200 */ # endif /* _AIX3 */ /* ** IBM AIX 2.2.1 -- actually tested for osupdate level 2706+1773 ** ** From Mark Whetzel . */ # ifdef AIX /* AIX/RT compiler pre-defines this */ # include # include /* AIX/RT resource.h does NOT include this */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define HASFCHMOD 0 /* does not have fchmod(2) syscall */ # define HASSETREUID 1 /* use setreuid(2) -lbsd system call */ # define HASSETVBUF 1 /* use setvbuf(2) system call */ # define HASSETRLIMIT 0 /* does not have setrlimit call */ # define HASFLOCK 0 /* does not have flock call - use fcntl */ # define HASULIMIT 1 /* use ulimit instead of setrlimit call */ # define SM_CONF_GETOPT 0 /* Do we need theirs or ours */ # define SYS5SETPGRP 1 /* don't have setpgid on AIX/RT */ # define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define BSD4_3 1 /* NOT bsd 4.4 or posix signals */ # define GIDSET_T int # define SFS_TYPE SFS_STATFS /* use statfs() impl */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ # define LA_TYPE LA_SUBR /* use our ported loadavgd daemon */ # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ # define ARBPTR_T int * # define void int typedef int pid_t; /* RTisms for BSD compatibility, specified in the Makefile define BSD 1 define BSD_INCLUDES 1 define BSD_REMAP_SIGNAL_TO_SIGVEC RTisms needed above */ /* make this sendmail in a completely different place */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/local/newmail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/local/newmail/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # endif /* AIX */ # if defined(_AIX) # define LDA_USE_LOCKF 1 # define LDA_USE_SETEUID 1 # endif /* defined(_AIX) */ /* ** Silicon Graphics IRIX ** ** Compiles on 4.0.1. ** ** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0). ** Use IRIX5 instead of IRIX for IRIX 5.x. ** ** IRIX64 changes from Mark R. Levinson . ** IRIX5 changes from Kari E. Hurtta . */ # ifdef IRIX # define SYSTEM5 1 /* this is a System-V derived system */ # define HASSETREUID 1 /* has setreuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define IP_SRCROUTE 1 /* can check IP source routing */ # define setpgid BSDsetpgrp # define GIDSET_T gid_t # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define SYSLOG_BUFSIZE 512 # if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) /* _SC_NPROC_ONLN is 'mpadmin -u', total # of unrestricted processors */ # define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN # endif /* if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) */ # ifdef IRIX6 # define STAT64 1 # define QUAD_T unsigned long long # define LA_TYPE LA_IRIX6 /* figure out at run time */ # define SAFENFSPATHCONF 0 /* pathconf(2) lies on NFS filesystems */ # else /* IRIX6 */ # define LA_TYPE LA_INT # ifdef IRIX64 # define STAT64 1 # define QUAD_T unsigned long long # define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */ # else /* IRIX64 */ # define STAT64 0 # define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ # endif /* IRIX64 */ # endif /* IRIX6 */ # if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) # include # include # define ARGV_T char *const * # define HASFCHOWN 1 /* has fchown(2) */ # define HASSETRLIMIT 1 /* has setrlimit(2) syscall */ # define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ # else /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ # define ARGV_T const char ** # define WAITUNION 1 /* use "union wait" as wait argument type */ # endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ # endif /* IRIX */ /* ** SunOS and Solaris ** ** Tested on SunOS 4.1.x (a.k.a. Solaris 1.1.x) and ** Solaris 2.4 (a.k.a. SunOS 5.4). */ # if defined(sun) && !defined(BSD) # include # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define IP_SRCROUTE 1 /* can check IP source routing */ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # ifndef HASFCHOWN # define HASFCHOWN 1 /* fchown(2) */ # endif /* ! HASFCHOWN */ # ifdef __svr4__ # define LDA_USE_LOCKF 1 # define LDA_USE_SETEUID 1 # define _PATH_MAILDIR "/var/mail" # endif /* __svr4__ */ # ifdef SOLARIS_2_3 # define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */ # endif /* SOLARIS_2_3 */ # if defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) # define SOLARIS 1 /* unknown Solaris version */ # endif /* defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) */ # ifdef SOLARIS /* Solaris 2.x (a.k.a. SunOS 5.x) */ # ifndef __svr4__ # define __svr4__ /* use all System V Release 4 defines below */ # endif /* ! __svr4__ */ # define GIDSET_T gid_t # define USE_SA_SIGACTION 1 /* use sa_sigaction field */ # define BROKEN_PTHREAD_SLEEP 1 /* sleep after pthread_create() fails */ # define HASSTRERROR 1 /* has strerror(3) */ # ifndef _PATH_UNIX # define _PATH_UNIX "/dev/ksyms" # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # ifndef _PATH_HOSTS # define _PATH_HOSTS "/etc/inet/hosts" # endif /* ! _PATH_HOSTS */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ # endif /* ! SYSLOG_BUFSIZE */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME # endif /* ! TZ_TYPE */ # if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) # define USESETEUID 1 /* seteuid works as of 2.3 */ # define LDA_CONTENTLENGTH 1 /* Needs the Content-Length header */ # endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ # if SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) # define HASSETREUID 1 /* setreuid works as of 2.5 */ # define HASSETREGID 1 /* use setregid(2) to set saved gid */ # if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) # define HASSNPRINTF 1 /* has snprintf(3c) starting in 2.6 */ # endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ # if SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) # ifndef LA_TYPE # define LA_TYPE LA_KSTAT /* use kstat(3k) -- may work in < 2.5 */ # endif /* ! LA_TYPE */ # ifndef RANDOMSHIFT /* random() doesn't work well (sometimes) */ # define RANDOMSHIFT 8 # endif /* ! RANDOMSHIFT */ # endif /* SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) */ # else /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ # ifndef HASRANDOM # define HASRANDOM 0 /* doesn't have random(3) */ # endif /* ! HASRANDOM */ # endif /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ # if (SOLARIS > 10000 && SOLARIS < 20600) || SOLARIS < 206 # define SM_INT32 int /* 32bit integer */ # endif /* (SOLARIS > 10000 && SOLARIS < 20600) || SOLARIS < 206 */ # if SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) # ifndef LA_TYPE # include # if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) # include # define LA_TYPE LA_PSET /* pset_getloadavg(3c) appears in 2.9 */ # else /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ # define LA_TYPE LA_SUBR /* getloadavg(3c) appears in 2.7 */ # endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ # endif /* ! LA_TYPE */ # define HASGETUSERSHELL 1 /* getusershell(3c) bug fixed in 2.7 */ # endif /* SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) */ # if SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) # undef _PATH_SENDMAILPID /* tmpfs /var/run added in 2.8 */ # define _PATH_SENDMAILPID "/var/run/sendmail.pid" # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/var/adm/sm.bin" # endif /* ! SMRSH_CMDDIR */ # define SL_FUDGE 34 /* fudge offset for SyslogPrefixLen */ # define HASLDAPGETALIASBYNAME 1 /* added in S8 */ # endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */ # if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) # define HASURANDOMDEV 1 /* /dev/[u]random added in S9 */ # define HASCLOSEFROM 1 /* closefrom(3c) added in S9 */ # define HASFDWALK 1 /* fdwalk(3c) added in S9 */ # endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ # if SOLARIS >= 21000 || (SOLARIS < 10000 && SOLARIS >= 210) # define HASUNSETENV 1 /* unsetenv() added in S10 */ # endif /* SOLARIS >= 21000 || (SOLARIS < 10000 && SOLARIS >= 210) */ # if SOLARIS >= 21100 || (SOLARIS < 10000 && SOLARIS >= 211) # define GETLDAPALIASBYNAME_VERSION 2 /* changed in S11 */ # endif /* SOLARIS >= 21100 || (SOLARIS < 10000 && SOLARIS >= 211) */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ # endif /* ! HASGETUSERSHELL */ # else /* SOLARIS */ /* SunOS 4.0.3 or 4.1.x */ # define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ # define HASSETREUID 1 /* has setreuid(2) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ # include # include # ifdef __GNUC__ # define strtoul strtol /* gcc library bogosity */ # endif /* __GNUC__ */ # define memmove(d, s, l) (bcopy((s), (d), (l))) # define atexit(f) on_exit((f), 0) /* ugly hack for SunOS */ # define SM_INT32 int /* 32bit integer */ # define SM_ALIGN_SIZE (sizeof(long)) # define GIDSET_T int # define SM_CONF_SYSLOG 0 # ifdef SUNOS403 /* special tweaking for SunOS 4.0.3 */ # include # define BSD4_3 1 /* 4.3 BSD-based */ # define NEEDSTRSTR 1 /* need emulation of strstr(3) routine */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # undef WIFEXITED # undef WEXITSTATUS # undef HASUNAME # define setpgid setpgrp # define MODE_T int typedef int pid_t; extern char *getenv(); # else /* SUNOS403 */ /* 4.1.x specifics */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # endif /* SUNOS403 */ # endif /* SOLARIS */ # ifndef LA_TYPE # define LA_TYPE LA_INT # endif /* ! LA_TYPE */ # endif /* defined(sun) && !defined(BSD) */ /* ** DG/UX ** ** Tested on 5.4.2 and 5.4.3. Use DGUX_5_4_2 to get the ** older support. ** 5.4.3 changes from Mark T. Robinson . */ # ifdef DGUX_5_4_2 # define DGUX 1 # endif /* DGUX_5_4_2 */ # ifdef DGUX # define SYSTEM5 1 # define LA_TYPE LA_DGUX # define HASSETREUID 1 /* has setreuid(2) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define IP_SRCROUTE 0 /* does not have */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # define SPT_TYPE SPT_NONE /* don't use setproctitle */ # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define LDA_USE_LOCKF 1 /* these include files must be included early on DG/UX */ # include # include /* compiler doesn't understand const? */ # define const # ifdef DGUX_5_4_2 # define inet_addr dgux_inet_addr extern long dgux_inet_addr(); # endif /* DGUX_5_4_2 */ # endif /* DGUX */ /* ** Digital Ultrix 4.2 - 4.5 ** ** Apparently, fcntl locking is broken on 4.2A, in that locks are ** not dropped when the process exits. This causes major problems, ** so flock is the only alternative. */ # ifdef ultrix # define HASSETREUID 1 /* has setreuid(2) call */ # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFCHOWN 1 /* has fchown(2) syscall */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # ifndef BROKEN_RES_SEARCH # define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ # endif /* ! BROKEN_RES_SEARCH */ # if !defined(NEEDLOCAL_HOSTNAME_LENGTH) && NAMED_BIND && __RES >= 19931104 && __RES < 19950621 # define NEEDLOCAL_HOSTNAME_LENGTH 1 /* see sendmail/README */ # endif /* !defined(NEEDLOCAL_HOSTNAME_LENGTH) && NAMED_BIND && __RES >= 19931104 && __RES < 19950621 */ # ifdef vax # define LA_TYPE LA_FLOAT # else /* vax */ # define LA_TYPE LA_INT # define LA_AVENRUN "avenrun" # endif /* vax */ # define SFS_TYPE SFS_MOUNT /* use statfs() impl */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # define SYSLOG_BUFSIZE 256 # define SM_CONF_SYSLOG 0 # endif /* ultrix */ /* ** OSF/1 for KSR. ** ** Contributed by Todd C. Miller */ # ifdef __ksr__ # define __osf__ 1 /* get OSF/1 defines below */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ # endif /* ! TZ_TYPE */ # endif /* __ksr__ */ /* ** OSF/1 for Intel Paragon. ** ** Contributed by Jeff A. Earickson ** of Intel Scalable Systems Divison. */ # ifdef __PARAGON__ # define __osf__ 1 /* get OSF/1 defines below */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ # endif /* ! TZ_TYPE */ # define GIDSET_T gid_t # define MAXNAMLEN NAME_MAX # endif /* __PARAGON__ */ /* ** Tru64 UNIX, formerly known as Digital UNIX, formerly known as DEC OSF/1 ** ** Tested for 3.2 and 4.0. */ # ifdef __osf__ # define HASUNAME 1 /* has uname(2) call */ # define HASUNSETENV 1 /* has unsetenv(3) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFCHOWN 1 /* has fchown(2) syscall */ # define HASSETLOGIN 1 /* has setlogin(2) */ # define IP_SRCROUTE 1 /* can check IP source routing */ # define HAS_ST_GEN 1 /* has st_gen field in stat struct */ # define GIDSET_T gid_t # define SM_INT32 int /* 32bit integer */ # ifndef HASFLOCK # include # if _XOPEN_SOURCE+0 >= 400 # define HASFLOCK 0 /* 5.0 and later has bad flock(2) call */ # else /* _XOPEN_SOURCE+0 >= 400 */ # define HASFLOCK 1 /* has flock(2) call */ # endif /* _XOPEN_SOURCE+0 >= 400 */ # endif /* ! HASFLOCK */ # define LA_TYPE LA_ALPHAOSF # define SFS_TYPE SFS_STATVFS /* use statfs() impl */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/var/run/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # if _FFR_DIGUNIX_SAFECHOWN /* ** Testing on a Digital UNIX 4.0a system showed this to be the correct ** setting but given the security consequences, more testing and ** verification is needed. Unfortunately, the man page offers no ** assistance. */ # define IS_SAFE_CHOWN >= 0 # endif /* _FFR_DIGUNIX_SAFECHOWN */ # endif /* __osf__ */ /* ** NeXTstep */ # ifdef NeXT # define HASINITGROUPS 1 /* has initgroups(3) call */ # define NEEDPUTENV 2 /* need putenv(3) call; no setenv(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # define UID_T int /* compiler gripes on uid_t */ # define GID_T int /* ditto for gid_t */ # define MODE_T int /* and mode_t */ # define setpgid setpgrp # ifndef NOT_SENDMAIL # define sleep sleepX # endif /* ! NOT_SENDMAIL */ # ifndef LA_TYPE # define LA_TYPE LA_MACH # endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # ifdef _POSIX_SOURCE extern struct passwd *getpwent(); # else /* _POSIX_SOURCE */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define WAITUNION 1 /* use "union wait" as wait argument type */ typedef int pid_t; # undef WEXITSTATUS # undef WIFEXITED # undef WIFSTOPPED # undef WTERMSIG # endif /* _POSIX_SOURCE */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/sendmail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # define SM_INT32 int /* 32bit integer */ # ifdef TCPWRAPPERS # ifndef HASUNSETENV # define HASUNSETENV 1 # endif /* ! HASUNSETENV */ # undef NEEDPUTENV # endif /* TCPWRAPPERS */ # ifndef __APPLE__ # include # ifndef S_IRUSR # define S_IRUSR S_IREAD # endif /* ! S_IRUSR */ # ifndef S_IWUSR # define S_IWUSR S_IWRITE # endif /* ! S_IWUSR */ # define _PATH_MAILDIR "/usr/spool/mail" # endif /* ! __APPLE__ */ # ifndef isascii # define isascii(c) ((unsigned)(c) <= 0177) # endif /* ! isascii */ # endif /* NeXT */ /* ** Apple Darwin ** Contributed by Wilfredo Sanchez */ # if defined(DARWIN) # define HASFCHMOD 1 /* has fchmod(2) */ # define HASFCHOWN 1 /* has fchown(2) */ # define HASFLOCK 1 /* has flock(2) */ # define HASUNAME 1 /* has uname(2) */ # define HASUNSETENV 1 /* has unsetenv(3) */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) */ # define HASSETVBUF 1 /* has setvbuf (3) */ # define HASSETREUID 0 /* setreuid(2) unusable */ # define HASSETEUID 1 /* has seteuid(2) */ # define USESETEUID 1 /* has seteuid(2) */ # define HASSETEGID 1 /* has setegid(2) */ # define HASSETREGID 1 /* has setregid(2) */ # define HASSETRESGID 0 /* no setresgid(2) */ # define HASLSTAT 1 /* has lstat(2) */ # define HASSETRLIMIT 1 /* has setrlimit(2) */ # define HASWAITPID 1 /* has waitpid(2) */ # define HASGETDTABLESIZE 1 /* has getdtablesize(2) */ # define HAS_ST_GEN 1 /* has st_gen field in struct stat */ # define HASURANDOMDEV 1 /* has urandom(4) */ # define HASSTRERROR 1 /* has strerror(3) */ # define HASGETUSERSHELL 1 /* had getusershell(3) */ # define GIDSET_T gid_t /* getgroups(2) takes gid_t */ # define LA_TYPE LA_SUBR /* use getloadavg(3) */ # define SFS_TYPE SFS_MOUNT /* use statfs() impl */ # if DARWIN >= 70000 # define SOCKADDR_LEN_T socklen_t # endif # if DARWIN >= 80000 # define SPT_TYPE SPT_REUSEARGV # define SPT_PADCHAR '\0' # define SOCKOPT_LEN_T socklen_t # else # define SPT_TYPE SPT_PSSTRINGS /* use magic PS_STRINGS pointer for setproctitle */ # endif # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* struct sockaddr has sa_len */ # define SAFENFSPATHCONF 0 /* unverified: pathconf(2) doesn't work on NFS */ # define HAS_IN_H 1 # define NETLINK 1 /* supports AF_LINK */ # ifndef NOT_SENDMAIL # define sleep sleepX extern unsigned int sleepX __P((unsigned int seconds)); # endif /* ! NOT_SENDMAIL */ # endif /* defined(DARWIN) */ /* ** 4.4 BSD ** ** See also BSD defines. */ # if defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) && !defined(DARWIN) # include # define HASUNSETENV 1 /* has unsetenv(3) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFCHOWN 1 /* has fchown(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ # define HAS_ST_GEN 1 /* has st_gen field in stat struct */ # include # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* has sa_len */ # define NEED_PRINTF_PERCENTQ 1 /* doesn't have %lld */ # define NETLINK 1 /* supports AF_LINK */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif /* ! LA_TYPE */ # define SFS_TYPE SFS_MOUNT /* use statfs() impl */ # define SPT_TYPE SPT_PSSTRINGS /* use PS_STRINGS pointer */ # endif /* defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) && !defined(DARWIN)*/ /* ** BSD/OS (was BSD/386) (all versions) ** From Tony Sanders, BSDI */ # ifdef __bsdi__ # include # define HASUNSETENV 1 /* has the unsetenv(3) call */ # define HASSETREUID 0 /* BSD-OS has broken setreuid(2) emulation */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASSETLOGIN 1 /* has setlogin(2) */ # define HASUNAME 1 /* has uname(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ # define HAS_ST_GEN 1 /* has st_gen field in stat struct */ # include # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* has sa_len */ # define NETLINK 1 /* supports AF_LINK */ # define SFS_TYPE SFS_MOUNT /* use statfs() impl */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif /* ! LA_TYPE */ # define GIDSET_T gid_t # define QUAD_T quad_t # if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 /* version 1.1 or later */ # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # else /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ /* version 1.0 or earlier */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ # endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ # if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 /* on 3.x */ # define HASSETUSERCONTEXT 1 /* has setusercontext */ # endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 */ # if defined(_BSDI_VERSION) && _BSDI_VERSION <= 199701 /* 3.1 and earlier */ # define MODE_T int /* va_arg() can't handle less than int */ # endif /* defined(_BSDI_VERSION) && _BSDI_VERSION <= 199701 */ # if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199910 /* on 4.x */ # define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199910 */ # endif /* __bsdi__ */ # if defined(__QNX__) # if defined(__QNXNTO__) /* QNX 6 */ # include # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFCHOWN 1 /* has fchown(2) syscall */ # define HASUNAME 1 /* has uname(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ # define BSD4_4_SOCKADDR /* has sa_len */ # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define NETLINK 1 /* supports AF_LINK */ # define GIDSET_T gid_t # define QUAD_T uint64_t # define HASSNPRINTF 1 /* has snprintf(3) (all versions?) */ # define HASGETUSERSHELL 0 /* ** We have a strrev() that doesn't allocate anything. ** Make sure the one here is used. */ # define strrev strrev_sendmail # else /* defined(__QNXNTO__) */ /* ** QNX 4.2x ** Contributed by Glen McCready . ** ** Should work with all versions of QNX 4. */ # include # include # undef NGROUPS_MAX # define HASSETSID 1 /* has POSIX setsid(2) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ # define HASSETREUID 1 /* has setreuid(2) call */ # define HASSTRERROR 1 /* has strerror(3) */ # define HASFLOCK 0 # undef HASINITGROUPS /* has initgroups(3) call */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define IP_SRCROUTE 1 /* can check IP source routing */ # define TZ_TYPE TZ_TMNAME /* use tmname variable */ # define GIDSET_T gid_t # define LA_TYPE LA_ZERO # define SFS_TYPE SFS_NONE # define SPT_TYPE SPT_REUSEARGV # define SPT_PADCHAR '\0' /* pad process title with nulls */ # define HASGETUSERSHELL 0 # define _FILE_H_INCLUDED # endif /* defined(__QNXNTO__) */ # endif /* defined(__QNX__) */ /* ** DragonFly BSD/ FreeBSD / NetBSD / OpenBSD (all architectures, all versions) ** ** 4.3BSD clone, closer to 4.4BSD for FreeBSD 1.x and NetBSD 0.9x ** 4.4BSD-Lite based for FreeBSD 2.x and NetBSD 1.x ** ** See also BSD defines. */ # if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # include # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFCHOWN 1 /* has fchown(2) syscall */ # define HASUNAME 1 /* has uname(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ # define HAS_ST_GEN 1 /* has st_gen field in stat struct */ # define NEED_PRINTF_PERCENTQ 1 /* doesn't have %lld */ # include # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR /* has sa_len */ # define NETLINK 1 /* supports AF_LINK */ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # define GIDSET_T gid_t # define QUAD_T unsigned long long # define HASSNPRINTF 1 /* has snprintf(3) (all versions?) */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif /* ! LA_TYPE */ # if defined(__NetBSD__) && defined(__NetBSD_Version__) && \ ((__NetBSD_Version__ >= 200040000 && __NetBSD_Version__ < 200090000) || \ (__NetBSD_Version__ >= 299000900)) # undef SFS_TYPE # define SFS_TYPE SFS_STATVFS # else # define SFS_TYPE SFS_MOUNT /* use statfs() impl */ # endif # if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # endif /* defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) */ # if defined(__NetBSD__) && ((__NetBSD_Version__ > 102070000) || (NetBSD1_2 > 8) || defined(NetBSD1_4) || defined(NetBSD1_3)) # define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # endif /* defined(__NetBSD__) && ((__NetBSD_Version__ > 102070000) || (NetBSD1_2 > 8) || defined(NetBSD1_4) || defined(NetBSD1_3)) */ # if defined(__NetBSD__) && defined(__NetBSD_Version__) && __NetBSD_Version__ >= 104170000 # define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ # endif # if defined(__NetBSD__) && defined(__NetBSD_Version__) && \ ((__NetBSD_Version__ >= 200060000 && __NetBSD_Version__ < 200090000) || \ (__NetBSD_Version__ >= 299000900)) # define HASCLOSEFROM 1 /* closefrom(3) added in 2.0F */ # endif # if defined(__NetBSD__) # define USESYSCTL 1 /* use sysctl(3) for getting ncpus */ # include # include # endif # if defined(__DragonFly__) # define HASSETLOGIN 1 /* has setlogin(2) */ # define HASSRANDOMDEV 1 /* has srandomdev(3) */ # define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # undef SPT_TYPE # include # define SPT_TYPE SPT_BUILTIN # define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/usr/libexec/sm.bin" # endif /* ! SMRSH_CMDDIR */ # ifndef SMRSH_PATH # define SMRSH_PATH "/bin:/usr/bin" # endif /* ! SMRSH_PATH */ # define USESYSCTL 1 /* use sysctl(3) for getting ncpus */ # include # endif /* defined(__DragonFly__) */ # if defined(__FreeBSD__) # define HASSETLOGIN 1 /* has setlogin(2) */ # if __FreeBSD_version >= 227001 # define HASSRANDOMDEV 1 /* has srandomdev(3) */ # define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # endif /* __FreeBSD_version >= 227001 */ # undef SPT_TYPE # if __FreeBSD__ >= 2 # include # if __FreeBSD_version >= 199512 /* 2.2-current when it appeared */ # include # define SPT_TYPE SPT_BUILTIN # endif /* __FreeBSD_version >= 199512 */ # if __FreeBSD_version >= 222000 /* 2.2.2-release and later */ # define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ # endif /* __FreeBSD_version >= 222000 */ # if __FreeBSD_version >= 330000 /* 3.3.0-release and later */ # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/usr/libexec/sm.bin" # endif /* ! SMRSH_CMDDIR */ # ifndef SMRSH_PATH # define SMRSH_PATH "/bin:/usr/bin" # endif /* ! SMRSH_PATH */ # endif /* __FreeBSD_version >= 330000 */ # define USESYSCTL 1 /* use sysctl(3) for getting ncpus */ # include # endif /* __FreeBSD__ >= 2 */ # ifndef SPT_TYPE # define SPT_TYPE SPT_REUSEARGV # define SPT_PADCHAR '\0' /* pad process title with nulls */ # endif /* ! SPT_TYPE */ # endif /* defined(__FreeBSD__) */ # if defined(__OpenBSD__) # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # define HASSETLOGIN 1 /* has setlogin(2) */ # if OpenBSD < 200305 # define HASSETREUID 0 /* setreuid(2) broken in OpenBSD < 3.3 */ # endif /* OpenBSD < 200305 */ # define HASSETEGID 1 /* use setegid(2) to set saved gid */ # define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # if OpenBSD >= 200006 # define HASSRANDOMDEV 1 /* has srandomdev(3) */ # endif /* OpenBSD >= 200006 */ # if OpenBSD >= 200012 # define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ # endif /* OpenBSD >= 200012 */ # if OpenBSD >= 200405 # define HASCLOSEFROM 1 /* closefrom(3) added in 3.5 */ # endif /* OpenBSD >= 200405 */ # if OpenBSD >= 200505 # undef NETISO /* iso.h removed in 3.7 */ # endif /* OpenBSD >= 200505 */ # endif /* defined(__OpenBSD__) */ # endif /* defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) */ /* ** Mach386 ** ** For mt Xinu's Mach386 system. */ # if defined(MACH) && defined(i386) && !defined(__GNU__) # define MACH386 1 # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define NEEDSTRTOL 1 /* need the strtol() function */ # define setpgid setpgrp # ifndef LA_TYPE # define LA_TYPE LA_FLOAT # endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # undef HASSETVBUF /* don't actually have setvbuf(3) */ # undef WEXITSTATUS # undef WIFEXITED # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # endif /* defined(MACH) && defined(i386) && !defined(__GNU__) */ /* ** GNU OS (hurd) ** Largely BSD & posix compatible. ** Port contributed by Miles Bader . ** Updated by Mark Kettenis . */ # if defined(__GNU__) && !defined(NeXT) # include # define HASFCHMOD 1 /* has fchmod(2) call */ # define HASFCHOWN 1 /* has fchown(2) call */ # define HASUNAME 1 /* has uname(2) call */ # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HAS_ST_GEN 1 /* has st_gen field in stat struct */ # define HASSTRERROR 1 /* has strerror(3) */ # define GIDSET_T gid_t # define SOCKADDR_LEN_T socklen_t # define SOCKOPT_LEN_T socklen_t # if (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 # define LA_TYPE LA_SUBR # else /* (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 */ # define LA_TYPE LA_MACH /* GNU uses mach[34], which renames some rpcs from mach2.x. */ # define host_self mach_host_self # endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 */ # define SFS_TYPE SFS_STATFS # define SPT_TYPE SPT_CHANGEARGV # define ERRLIST_PREDEFINED 1 /* don't declare sys_errlist */ # define BSD4_4_SOCKADDR 1 /* has sa_len */ # define SIOCGIFCONF_IS_BROKEN 1 /* SIOCGFCONF doesn't work */ # define HAS_IN_H 1 /* GNU has netinet/in.h. */ /* GNU has no MAXPATHLEN; ideally the code should be changed to not use it. */ # define MAXPATHLEN 2048 # endif /* defined(__GNU__) && !defined(NeXT) */ /* ** 4.3 BSD -- this is for very old systems ** ** Should work for mt Xinu MORE/BSD and Mips UMIPS-BSD 2.1. ** ** You'll also have to install a new resolver library. ** I don't guarantee that support for this environment is complete. */ # if defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) # define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define ARBPTR_T char * # define setpgid setpgrp # ifndef LA_TYPE # define LA_TYPE LA_FLOAT # endif /* ! LA_TYPE */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # undef WEXITSTATUS # undef WIFEXITED typedef short pid_t; # endif /* defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) */ /* ** SCO Unix ** ** This includes three parts: ** ** The first is for SCO OpenServer 5. ** (Contributed by Keith Reynolds ). ** ** SCO OpenServer 5 has a compiler version number macro, ** which we can use to figure out what version we're on. ** This may have to change in future releases. ** ** The second is for SCO UNIX 3.2v4.2/Open Desktop 3.0. ** (Contributed by Philippe Brand ). ** ** The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier. */ /* SCO OpenServer 5 */ # if _SCO_DS >= 1 # include # define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM returns bogus value */ # define HASFCHMOD 1 /* has fchmod(2) call */ # define HASFCHOWN 1 /* has fchown(2) call */ # define HASSETRLIMIT 1 /* has setrlimit(2) call */ # define USESETEUID 1 /* has seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ # define RLIMIT_NEEDS_SYS_TIME_H 1 # define LDA_USE_LOCKF 1 # ifndef LA_TYPE # define LA_TYPE LA_DEVSHORT # endif /* ! LA_TYPE */ # define _PATH_AVENRUN "/dev/table/avenrun" # ifndef _SCO_unix_4_2 # define _SCO_unix_4_2 # else /* ! _SCO_unix_4_2 */ # define SOCKADDR_LEN_T size_t /* e.g., arg#3 to accept, getsockname */ # define SOCKOPT_LEN_T size_t /* arg#5 to getsockopt */ # endif /* ! _SCO_unix_4_2 */ # endif /* _SCO_DS >= 1 */ /* SCO UNIX 3.2v4.2/Open Desktop 3.0 */ # ifdef _SCO_unix_4_2 # define _SCO_unix_ # define HASSETREUID 1 /* has setreuid(2) call */ # endif /* _SCO_unix_4_2 */ /* SCO UNIX 3.2v4.0 Open Desktop 2.0 and earlier */ # ifdef _SCO_unix_ # include /* needed for IP_SRCROUTE */ # define SYSTEM5 1 /* include all the System V defines */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define NOFTRUNCATE 0 /* has (simulated) ftruncate call */ # ifndef USE_SIGLONGJMP # define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ # endif /* ! USE_SIGLONGJMP */ # define MAXPATHLEN PATHSIZE # define SFS_TYPE SFS_4ARGS /* use 4-arg impl */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define SPT_TYPE SPT_SCO /* write kernel u. area */ # define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */ # define UID_T uid_t # define GID_T gid_t # define GIDSET_T gid_t # define _PATH_UNIX "/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ /* stuff fixed in later releases */ # ifndef _SCO_unix_4_2 # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # endif /* ! _SCO_unix_4_2 */ # ifndef _SCO_DS # define ftruncate chsize /* use chsize(2) to emulate ftruncate */ # define NEEDFSYNC 1 /* needs the fsync(2) call stub */ # define NETUNIX 0 /* no unix domain socket support */ # define LA_TYPE LA_SHORT # endif /* ! _SCO_DS */ # endif /* _SCO_unix_ */ /* ** ISC (SunSoft) Unix. ** ** Contributed by J.J. Bailey */ # ifdef ISC_UNIX # include # include /* needed for IP_SRCROUTE */ # include # define SYSTEM5 1 /* include all the System V defines */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define HASSETREUID 1 /* has setreuid(2) call */ # define NEEDFSYNC 1 /* needs the fsync(2) call stub */ # define NETUNIX 0 /* no unix domain socket support */ # define MAXPATHLEN 1024 # define LA_TYPE LA_SHORT # define SFS_TYPE SFS_STATFS /* use statfs() impl */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define _PATH_UNIX "/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # endif /* ISC_UNIX */ /* ** Altos System V (5.3.1) ** Contributed by Tim Rice . */ # ifdef ALTOS_SYSTEM_V # include # include # define SYSTEM5 1 /* include all the System V defines */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # define NEEDFSYNC 1 /* no fsync(2) in system library */ # define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ # define NOFTRUNCATE 1 /* do not have ftruncate(2) */ # define MAXPATHLEN PATH_MAX # define LA_TYPE LA_SHORT # define SFS_TYPE SFS_STATFS /* use statfs() impl */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ # define NETUNIX 0 /* no unix domain socket support */ # undef WIFEXITED # undef WEXITSTATUS # define strtoul strtol /* gcc library bogosity */ typedef unsigned short uid_t; typedef unsigned short gid_t; typedef short pid_t; typedef unsigned long mode_t; /* some stuff that should have been in the include files */ extern char *malloc(); extern struct passwd *getpwent(); extern struct passwd *getpwnam(); extern struct passwd *getpwuid(); extern char *getenv(); extern struct group *getgrgid(); extern struct group *getgrnam(); # endif /* ALTOS_SYSTEM_V */ /* ** ConvexOS 11.0 and later ** ** "Todd C. Miller" claims this ** works on 9.1 as well. ** ** ConvexOS 11.5 and later, should work on 11.0 as defined. ** For pre-ConvexOOS 11.0, define SM_CONF_GETOPT=0, undef IDENTPROTO ** ** Eric Schnoebelen (eric@cirr.com) For CONVEX Computer Corp. ** (now the CONVEX Technologies Center of Hewlett Packard) */ # ifdef _CONVEX_SOURCE # define HASGETDTABLESIZE 1 /* has getdtablesize(2) */ # define HASINITGROUPS 1 /* has initgroups(3) */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASUNSETENV 1 /* has unsetenv(3) */ # define HASFLOCK 1 /* has flock(2) */ # define HASSETRLIMIT 1 /* has setrlimit(2) */ # define HASSETREUID 1 /* has setreuid(2) */ # define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_error=0 */ # define NEEDPUTENV 1 /* needs putenv (written in terms of setenv) */ # define SM_CONF_GETOPT 1 /* need a replacement for getopt(3) */ # define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define LA_TYPE LA_FLOAT # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef S_IREAD # define S_IREAD _S_IREAD # define S_IWRITE _S_IWRITE # define S_IEXEC _S_IEXEC # define S_IFMT _S_IFMT # define S_IFCHR _S_IFCHR # define S_IFBLK _S_IFBLK # endif /* ! S_IREAD */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TIMEZONE # endif /* ! TZ_TYPE */ # ifndef IDENTPROTO # define IDENTPROTO 1 # endif /* ! IDENTPROTO */ # ifndef SHARE_V1 # define SHARE_V1 1 /* version 1 of the fair share scheduler */ # endif /* ! SHARE_V1 */ # if !defined(__GNUC__ ) # define UID_T int /* GNUC gets it right, ConvexC botches */ # define GID_T int /* GNUC gets it right, ConvexC botches */ # endif /* !defined(__GNUC__ ) */ # if SECUREWARE # define FORK fork /* SecureWare wants the real fork! */ # else /* SECUREWARE */ # define FORK vfork /* the rest of the OS versions don't care */ # endif /* SECUREWARE */ # endif /* _CONVEX_SOURCE */ /* ** RISC/os 4.52 ** ** Gives a ton of warning messages, but otherwise compiles. */ # ifdef RISCOS # define HASUNSETENV 1 /* has unsetenv(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define NEEDPUTENV 1 /* need putenv(3) call */ # define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # define LA_TYPE LA_INT # define LA_AVENRUN "avenrun" # define _PATH_UNIX "/unix" # undef WIFEXITED # define setpgid setpgrp typedef int pid_t; # define SIGFUNC_DEFINED # define SIGFUNC_RETURN (0) # define SIGFUNC_DECL int typedef int (*sigfunc_t)(); extern char *getenv(); extern void *malloc(); /* added for RISC/os 4.01...which is dumber than 4.50 */ # ifdef RISCOS_4_0 # ifndef ARBPTR_T # define ARBPTR_T char * # endif /* ! ARBPTR_T */ # undef HASFLOCK # define HASFLOCK 0 # endif /* RISCOS_4_0 */ # include # endif /* RISCOS */ /* ** Linux 0.99pl10 and above... ** ** Thanks to, in reverse order of contact: ** ** John Kennedy ** Andrew Pam ** Florian La Roche ** Karl London ** ** NOTE: Override HASFLOCK as you will but, as of 1.99.6, mixed-style ** file locking is no longer allowed. In particular, make sure ** your DBM library and sendmail are both using either flock(2) ** *or* fcntl(2) file locking, but not both. */ # ifdef __linux__ # include # if !defined(KERNEL_VERSION) /* not defined in 2.0.x kernel series */ # define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) # endif /* !defined(KERNEL_VERSION) */ # define BSD 1 /* include BSD defines */ # define HASSETREGID 1 /* use setregid(2) to set saved gid */ # ifndef REQUIRES_DIR_FSYNC # define REQUIRES_DIR_FSYNC 1 /* requires fsync() on directory */ # endif /* REQUIRES_DIR_FSYNC */ # ifndef USESETEUID # define USESETEUID 0 /* has it due to POSIX, but doesn't work */ # endif /* USESETEUID */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASUNSETENV 1 /* has unsetenv(3) call */ # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define GIDSET_T gid_t /* from */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */ # endif /* HASGETUSERSHELL */ # ifndef IP_SRCROUTE # define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */ # endif /* ! IP_SRCROUTE */ # ifndef HAS_IN_H # define HAS_IN_H 1 /* use netinet/in.h */ # endif /* ! HAS_IN_H */ # ifndef USE_SIGLONGJMP # define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ # endif /* ! USE_SIGLONGJMP */ # ifndef HASFLOCK # if LINUX_VERSION_CODE < 66399 # define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */ # else /* LINUX_VERSION_CODE < 66399 */ # if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) # define HASFLOCK 1 /* flock(2) fixed after 1.3.95 */ # else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) */ # define HASFLOCK 0 /* flock(2) is broken (again) after 2.4.0 */ # endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) */ # endif /* LINUX_VERSION_CODE < 66399 */ # endif /* ! HASFLOCK */ # ifndef LA_TYPE # define LA_TYPE LA_PROCSTR # endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use statfs() impl */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ # if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0)) # ifndef HASURANDOMDEV # define HASURANDOMDEV 1 /* 2.0 (at least) has linux/drivers/char/random.c */ # endif /* ! HASURANDOMDEV */ # endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0)) */ # if defined(__GLIBC__) && defined(__GLIBC_MINOR__) # define HASSTRERROR 1 /* has strerror(3) */ # endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ # ifndef TZ_TYPE # define TZ_TYPE TZ_NONE /* no standard for Linux */ # endif /* ! TZ_TYPE */ # if (__GLIBC__ >= 2) # include # endif /* (__GLIBC__ >= 2) */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/var/run/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # include # undef atol /* wounded in */ # if NETINET6 /* ** Linux doesn't have a good way to tell userland what interfaces are ** IPv6-capable. Therefore, the BIND resolver can not determine if there ** are IPv6 interfaces to honor AI_ADDRCONFIG. Unfortunately, it assumes ** that none are present. (Excuse the macro name ADDRCONFIG_IS_BROKEN.) */ # define ADDRCONFIG_IS_BROKEN 1 /* ** Indirectly included from glibc's . IPv6 support is native ** in 2.1 and later, but the APIs appear before the functions. */ # if defined(__GLIBC__) && defined(__GLIBC_MINOR__) # define GLIBC_VERSION ((__GLIBC__ << 8) + __GLIBC_MINOR__) # if (GLIBC_VERSION >= 0x201) # undef IPPROTO_ICMPV6 /* linux #defines, glibc enums */ # else /* (GLIBC_VERSION >= 0x201) */ # include /* IPv6 support */ # endif /* (GLIBC_VERSION >= 0x201) */ # if (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) /* Have APIs in , but no support in glibc */ # define NEEDSGETIPNODE 1 # endif /* (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) */ # undef GLIBC_VERSION # endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ # endif /* NETINET6 */ # ifndef HASFCHOWN # define HASFCHOWN 1 /* fchown(2) */ # endif /* ! HASFCHOWN */ # if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36)) && !defined(HASFCHMOD) # define HASFCHMOD 1 /* fchmod(2) */ # endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36)) && !defined(HASFCHMOD) */ # endif /* __linux__ */ /* ** DELL SVR4 Issue 2.2, and others ** From Kimmo Suominen ** ** It's on #ifdef DELL_SVR4 because Solaris also gets __svr4__ ** defined, and the definitions conflict. ** ** Peter Wemm claims that the setreuid ** trick works on DELL 2.2 (SVR4.0/386 version 4.0) and ESIX 4.0.3A ** (SVR4.0/386 version 3.0). */ # ifdef DELL_SVR4 /* no changes necessary */ /* see general __svr4__ defines below */ # endif /* DELL_SVR4 */ /* ** Apple A/UX 3.0 */ # ifdef _AUX_SOURCE # include # define BSD /* has BSD routines */ # define HASSETRLIMIT 0 /* ... but not setrlimit(2) */ # define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ # define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASSETVBUF 1 /* has setvbuf(3) in libc */ # define HASSTRERROR 1 /* has strerror(3) */ # define SIGFUNC_DEFINED /* sigfunc_t already defined */ # define SIGFUNC_RETURN /* POSIX-mode */ # define SIGFUNC_DECL void /* POSIX-mode */ # define ERRLIST_PREDEFINED 1 # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # ifndef LA_TYPE # define LA_TYPE LA_INT # define FSHIFT 16 # endif /* ! LA_TYPE */ # define LA_AVENRUN "avenrun" # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # define TZ_TYPE TZ_TZNAME # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" /* should be in */ # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # undef WIFEXITED # undef WEXITSTATUS # endif /* _AUX_SOURCE */ /* ** Encore UMAX V ** ** Not extensively tested. */ # ifdef UMAXV # define HASUNAME 1 /* use System V uname(2) system call */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define MAXPATHLEN PATH_MAX extern struct passwd *getpwent(), *getpwnam(), *getpwuid(); extern struct group *getgrent(), *getgrnam(), *getgrgid(); # undef WIFEXITED # undef WEXITSTATUS # endif /* UMAXV */ /* ** Stardent Titan 3000 running TitanOS 4.2. ** ** Must be compiled in "cc -43" mode. ** ** From Kate Hedstrom . ** ** Note the tweaking below after the BSD defines are set. */ # ifdef titan # define setpgid setpgrp typedef int pid_t; # undef WIFEXITED # undef WEXITSTATUS # endif /* titan */ /* ** Sequent DYNIX 3.2.0 ** ** From Jim Davis . */ # ifdef sequent # define BSD 1 # define HASUNSETENV 1 # define BSD4_3 1 /* to get signal() in conf.c */ # define WAITUNION 1 # define LA_TYPE LA_FLOAT # ifdef _POSIX_VERSION # undef _POSIX_VERSION /* set in */ # endif /* _POSIX_VERSION */ # undef HASSETVBUF /* don't actually have setvbuf(3) */ # define setpgid setpgrp /* Have to redefine WIFEXITED to take an int, to work with waitfor() */ # undef WIFEXITED # define WIFEXITED(s) (((union wait*)&(s))->w_stopval != WSTOPPED && \ ((union wait*)&(s))->w_termsig == 0) # define WEXITSTATUS(s) (((union wait*)&(s))->w_retcode) typedef int pid_t; # define isgraph(c) (isprint(c) && (c != ' ')) # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # ifndef _PATH_UNIX # define _PATH_UNIX "/dynix" # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # endif /* sequent */ /* ** Sequent DYNIX/ptx v2.0 (and higher) ** ** For DYNIX/ptx v1.x, undefine HASSETREUID. ** ** From Tim Wright . ** Update from Jack Woolley , 26 Dec 1995, ** for DYNIX/ptx 4.0.2. */ # ifdef _SEQUENT_ # include # define SYSTEM5 1 /* include all the System V defines */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASSETREUID 1 /* has setreuid(2) call */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define GIDSET_T gid_t # define LA_TYPE LA_INT # define SFS_TYPE SFS_STATFS /* use statfs() impl */ # define SPT_TYPE SPT_NONE /* don't use setproctitle */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # endif /* _SEQUENT_ */ /* ** Cray UNICOS, UNICOS/mk, and UNICOS/mp ** ** UNICOS: ** Ported by David L. Kensiski, Sterling Sofware ** Update Brian Ginsbach ** UNICOS/mk (Cray T3E): ** Contributed by Manu Mahonen ** of Center for Scientific Computing. ** Update Brian Ginsbach ** UNICOS/mp: ** From Aaron Davis & Brian Ginsbach */ # if defined(_CRAY) || defined(UNICOS) || defined(_UNICOSMP) # define SYSTEM5 1 /* include all the System V defines */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFCHOWN 1 /* has fchown(2) */ # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASSETREUID 1 /* has setreuid(2) call */ # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */ # define HASSTRERROR 1 /* has strerror(3) */ # define GIDSET_T gid_t # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # ifdef UNICOS # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define LA_TYPE LA_ZERO # define _PATH_MAILDIR "/usr/spool/mail" # define GET_IPOPT_DST(dst) *(struct in_addr *)&(dst) # ifndef MAXPATHLEN # define MAXPATHLEN PATHSIZE # endif /* ! MAXPATHLEN */ # ifndef _PATH_UNIX # ifdef UNICOSMK # define _PATH_UNIX "/unicosmk.ar" # else # define _PATH_UNIX "/unicos" # endif /* UNICOSMK */ # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # endif /* UNICOS */ # ifdef _UNICOSMP # if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) /* _SC_NPROC_ONLN is 'mpadmin -u', total # of unrestricted processors */ # define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN # endif /* if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define HASSETRLIMIT 1 /* has setrlimit(2) syscall */ # define LA_TYPE LA_IRIX6 /* figure out at run time */ # include # include # define ARGV_T char *const * # endif /* _UNICOSMP */ # endif /* _CRAY */ /* ** Apollo DomainOS ** ** From Todd Martin & Don Lewis ** ** 15 Jan 1994; updated 2 Aug 1995 ** */ # ifdef apollo # define HASSETREUID 1 /* has setreuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(2) call */ # define IP_SRCROUTE 0 /* does not have */ # define SPT_TYPE SPT_NONE /* don't use setproctitle */ # define LA_TYPE LA_SUBR /* use getloadavg.c */ # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define TZ_TYPE TZ_TZNAME # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # undef S_IFSOCK /* S_IFSOCK and S_IFIFO are the same */ # undef S_IFIFO # define S_IFIFO 0010000 # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # define RLIMIT_NEEDS_SYS_TIME_H 1 # if defined(NGROUPS_MAX) && !NGROUPS_MAX # undef NGROUPS_MAX # endif /* defined(NGROUPS_MAX) && !NGROUPS_MAX */ # endif /* apollo */ /* ** MPE-iX ** ** Requires MPE 6.0 or greater. See sendmail/README for more info. ** ** From Mark Bixby or . */ # ifdef MPE # include # include /* Sendmail stuff */ # define HASFCHOWN 0 /* lacks fchown() */ # define HASGETUSERSHELL 0 /* lacks getusershell() */ # ifdef HASNICE # undef HASNICE # endif /* HASNICE */ # define HASNICE 0 /* lacks nice() */ # define HASRANDOM 0 /* lacks random() */ # ifdef HASRRESVPORT # undef HASRRESVPORT # endif /* HASRRESVPORT */ # define HASRRESVPORT 0 /* lacks rresvport() */ # define IP_SRCROUTE 0 /* lacks IP source routing fields */ # ifdef MATCHGECOS # undef MATCHGECOS # endif /* MATCHGECOS */ # define MATCHGECOS 0 /* lacks an initialized GECOS field */ # define NEEDFSYNC 1 /* use sendmail's fsync() */ # define NEEDLINK 1 /* use sendmail's link() */ # define NOFTRUNCATE 1 /* lacks ftruncate() */ # define SFS_TYPE SFS_NONE /* can't determine disk space */ # define SM_CONF_SYSLOG 0 /* use sendmail decl of syslog() */ # define USE_DOUBLE_FORK 0 /* don't fork an intermediate zombie */ # define USE_ENVIRON 1 /* use environ instead of envp */ /* Missing header stuff */ # define AF_UNSPEC 0 # define AF_MAX AF_INET # define IFF_LOOPBACK 0x8 # define IN_LOOPBACKNET 127 # define MAXNAMLEN NAME_MAX # define S_IEXEC S_IXUSR # define S_IREAD S_IRUSR # define S_IWRITE S_IWUSR /* Present header stuff that needs to be missing */ # undef NGROUPS_MAX /* Shadow functions */ # define bind sendmail_mpe_bind # define _exit sendmail_mpe__exit # define exit sendmail_mpe_exit # define fcntl sendmail_mpe_fcntl # define getegid sendmail_mpe_getegid # define geteuid sendmail_mpe_geteuid # define getpwnam sendmail_mpe_getpwnam # define getpwuid sendmail_mpe_getpwuid # define setgid sendmail_mpe_setgid # define setuid sendmail_mpe_setuid extern int sendmail_mpe_fcntl __P((int, int, ...)); extern struct passwd * sendmail_mpe_getpwnam __P((const char *)); extern struct passwd * sendmail_mpe_getpwuid __P((uid_t)); # endif /* MPE */ /* ** System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatibility Libs ie. native) ** ** Contributed by Paul Gampe */ # ifdef __svr5__ # include # define __svr4__ # define SYS5SIGNALS 1 # define HASFCHOWN 1 /* has fchown(2) call */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASSETREUID 1 # define HASWAITPID 1 # define HASGETDTABLESIZE 1 # define GIDSET_T gid_t # define SOCKADDR_LEN_T size_t # define SOCKOPT_LEN_T size_t # ifndef _PATH_UNIX # define _PATH_UNIX "/stand/unix" # endif /* ! _PATH_UNIX */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* unsure */ # endif /* ! SYSLOG_BUFSIZE */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ #if !defined(SM_SET_H_ERRNO) && defined(_REENTRANT) # define SM_SET_H_ERRNO(err) set_h_errno((err)) #endif /* ! SM_SET_H_ERRNO && _REENTRANT */ # endif /* __svr5__ */ /* ###################################################################### */ /* ** UnixWare 2.x */ # ifdef UNIXWARE2 # define UNIXWARE 1 # undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ # endif /* UNIXWARE2 */ /* ** UnixWare 1.1.2. ** ** Updated by Petr Lampa . ** From Evan Champion . */ # ifdef UNIXWARE # include # define SYSTEM5 1 # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # define HASSETREUID 1 # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASINITGROUPS 1 # define GIDSET_T gid_t # define SLEEP_T unsigned # define SFS_TYPE SFS_STATVFS # define LA_TYPE LA_ZERO # undef WIFEXITED # undef WEXITSTATUS # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # define SYSLOG_BUFSIZE 128 # endif /* UNIXWARE */ /* ** Intergraph CLIX 3.1 ** ** From Paul Southworth */ # ifdef CLIX # define SYSTEM5 1 /* looks like System V */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # endif /* ! HASGETUSERSHELL */ # define DEV_BSIZE 512 /* device block size not defined */ # define GIDSET_T gid_t # undef LOG /* syslog not available */ # define NEEDFSYNC 1 /* no fsync in system library */ # define GETSHORT _getshort # endif /* CLIX */ /* ** NCR MP-RAS 2.x (SysVr4) with Wollongong TCP/IP ** ** From Kevin Darcy . */ # ifdef NCR_MP_RAS2 # include # define __svr4__ # define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define SYSLOG_BUFSIZE 1024 # define SPT_TYPE SPT_NONE # endif /* NCR_MP_RAS2 */ /* ** NCR MP-RAS 3.x (SysVr4) with STREAMware TCP/IP ** ** From Tom Moore */ # ifdef NCR_MP_RAS3 # define __svr4__ # define HASFCHOWN 1 /* has fchown(2) call */ # define LDA_USE_LOCKF 1 # define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM has non-std interface */ # define SO_REUSEADDR_IS_BROKEN 1 /* doesn't work if accept() fails */ # define SYSLOG_BUFSIZE 1024 # define SPT_TYPE SPT_NONE # define _PATH_MAILDIR "/var/mail" # ifndef _XOPEN_SOURCE # define _XOPEN_SOURCE # define _XOPEN_SOURCE_EXTENDED 1 # include # undef _XOPEN_SOURCE # undef _XOPEN_SOURCE_EXTENDED # endif /* ! _XOPEN_SOURCE */ # endif /* NCR_MP_RAS3 */ /* ** Tandem NonStop-UX SVR4 ** ** From Rick McCarty . */ # ifdef NonStop_UX_BXX # define __svr4__ # endif /* NonStop_UX_BXX */ /* ** Hitachi 3050R/3050RX and 3500 Workstations running HI-UX/WE2. ** ** Tested for 1.04, 1.03 ** From Akihiro Hashimoto ("Hash") . ** ** Tested for 4.02, 6.10 and 7.10 ** From Motonori NAKAMURA . */ # if !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) # define SYSTEM5 1 /* include all the System V defines */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define setreuid(r, e) setresuid(r, e, -1) # define LA_TYPE LA_FLOAT # define SPT_TYPE SPT_PSTAT # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # ifndef HASSETVBUF # define HASSETVBUF /* HI-UX has no setlinebuf */ # endif /* ! HASSETVBUF */ # ifndef GIDSET_T # define GIDSET_T gid_t # endif /* ! GIDSET_T */ # ifndef _PATH_UNIX # define _PATH_UNIX "/HI-UX" # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ # endif /* ! HASGETUSERSHELL */ # define FDSET_CAST (int *) /* cast for fd_set parameters to select */ /* ** avoid m_flags conflict between Berkeley DB 1.85 db.h & sys/sysmacros.h ** on HIUX 3050 */ # undef m_flags # define SM_CONF_SYSLOG 0 # endif /* !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) */ /* ** Amdahl UTS System V 2.1.5 (SVr3-based) ** ** From: Janet Jackson . */ # ifdef _UTS # include # undef HASLSTAT /* has symlinks, but they cause problems */ # define NEEDFSYNC 1 /* system fsync(2) fails on non-EFS filesys */ # define SYS5SIGNALS 1 /* System V signal semantics */ # define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASINITGROUPS 1 /* has initgroups(3) function */ # define HASSETVBUF 1 /* has setvbuf(3) function */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) function */ # endif /* ! HASGETUSERSHELL */ # define GIDSET_T gid_t /* type of 2nd arg to getgroups(2) isn't int */ # define LA_TYPE LA_ZERO /* doesn't have load average */ # define SFS_TYPE SFS_4ARGS /* use 4-arg statfs() */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define _PATH_UNIX "/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # endif /* _UTS */ /* ** Cray Computer Corporation's CSOS ** ** From Scott Bolte . */ # ifdef _CRAYCOM # define SYSTEM5 1 /* include all the System V defines */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define NEEDFSYNC 1 /* no fsync in system library */ # define MAXPATHLEN PATHSIZE # define LA_TYPE LA_ZERO # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ # define SFS_BAVAIL f_bfree /* alternate field name */ # define _POSIX_CHOWN_RESTRICTED -1 extern struct group *getgrent(), *getgrnam(), *getgrgid(); # endif /* _CRAYCOM */ /* ** Sony NEWS-OS 4.2.1R and 6.0.3 ** ** From Motonori NAKAMURA . */ # ifdef sony_news # ifndef __svr4 /* NEWS-OS 4.2.1R */ # ifndef BSD # define BSD /* has BSD routines */ # endif /* ! BSD */ # define HASUNSETENV 1 /* has unsetenv(2) call */ # undef HASSETVBUF /* don't actually have setvbuf(3) */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # define LA_TYPE LA_INT # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # define setpgid setpgrp # undef WIFEXITED # undef WEXITSTATUS # define MODE_T int /* system include files have no mode_t */ typedef int pid_t; typedef int (*sigfunc_t)(); # define SIGFUNC_DEFINED # define SIGFUNC_RETURN (0) # define SIGFUNC_DECL int # else /* ! __svr4 */ /* NEWS-OS 6.0.3 with /bin/cc */ # ifndef __svr4__ # define __svr4__ /* use all System V Release 4 defines below */ # endif /* ! __svr4__ */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ # define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ # ifndef SPT_TYPE # define SPT_TYPE SPT_SYSMIPS /* use sysmips() (OS 6.0.2 or later) */ # endif /* ! SPT_TYPE */ # define GIDSET_T gid_t # undef WIFEXITED # undef WEXITSTATUS # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 256 # endif /* ! SYSLOG_BUFSIZE */ # define _PATH_UNIX "/stand/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # endif /* ! __svr4 */ # endif /* sony_news */ /* ** Omron LUNA/UNIOS-B 3.0, LUNA2/Mach and LUNA88K Mach ** ** From Motonori NAKAMURA . */ # ifdef luna # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # define HASUNSETENV 1 /* has unsetenv(2) call */ # define NEEDPUTENV 1 /* need putenv(3) call */ # define SM_CONF_GETOPT 0 /* need a replacement for getopt(3) */ # define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # ifdef uniosb # include # define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */ # define LA_TYPE LA_INT # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ # endif /* uniosb */ # ifdef luna2 # define LA_TYPE LA_SUBR # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ # endif /* luna2 */ # ifdef luna88k # define LA_TYPE LA_INT # endif /* luna88k */ # define SFS_TYPE SFS_VFS /* use statfs() implementation */ # define setpgid setpgrp # undef WIFEXITED # undef WEXITSTATUS typedef int pid_t; typedef int (*sigfunc_t)(); # define SIGFUNC_DEFINED # define SIGFUNC_RETURN (0) # define SIGFUNC_DECL int extern char *getenv(); # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # endif /* luna */ /* ** NEC EWS-UX/V 4.2 (with /usr/ucb/cc) ** ** From Motonori NAKAMURA . */ # if defined(nec_ews_svr4) || defined(_nec_ews_svr4) # ifndef __svr4__ # define __svr4__ /* use all System V Release 4 defines below */ # endif /* ! __svr4__ */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define LA_TYPE LA_READKSYM /* use MIOC_READSYM ioctl */ # define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ # define GIDSET_T gid_t # undef WIFEXITED # undef WEXITSTATUS # define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ # endif /* ! SYSLOG_BUFSIZE */ # endif /* defined(nec_ews_svr4) || defined(_nec_ews_svr4) */ /* ** Fujitsu/ICL UXP/DS (For the DS/90 Series) ** ** From Diego R. Lopez . ** Additional changes from Fumio Moriya and Toshiaki Nomura of the ** Fujitsu Fresoftware group . */ # ifdef __uxp__ # include # include # include # define __svr4__ # define HASGETUSERSHELL 0 # define HASFLOCK 0 # define _PATH_UNIX "/stand/unix" # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # endif /* __uxp__ */ /* ** Pyramid DC/OSx ** ** From Earle Ake . */ # ifdef DCOSx # define GIDSET_T gid_t # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif /* ! IDENTPROTO */ # endif /* DCOSx */ /* ** Concurrent Computer Corporation Maxion ** ** From Donald R. Laster Jr. . */ # ifdef __MAXION__ # include # define __svr4__ 1 /* SVR4.2MP */ # define HASSETREUID 1 /* have setreuid(2) */ # define HASLSTAT 1 /* have lstat(2) */ # define HASSETRLIMIT 1 /* have setrlimit(2) */ # define HASGETDTABLESIZE 1 /* have getdtablesize(2) */ # define HASGETUSERSHELL 1 /* have getusershell(3) */ # define NOFTRUNCATE 1 /* do not have ftruncate(2) */ # define SLEEP_T unsigned # define SFS_TYPE SFS_STATVFS # define SFS_BAVAIL f_bavail # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 256 /* Use 256 bytes */ # endif /* ! SYSLOG_BUFSIZE */ # undef WUNTRACED # undef WIFEXITED # undef WIFSIGNALED # undef WIFSTOPPED # undef WEXITSTATUS # undef WTERMSIG # undef WSTOPSIG # endif /* __MAXION__ */ /* ** Harris Nighthawk PowerUX (nh6000 box) ** ** Contributed by Bob Miorelli, Pratt & Whitney */ # ifdef _PowerUX # ifndef __svr4__ # define __svr4__ # endif /* ! __svr4__ */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # define SYSLOG_BUFSIZE 1024 # define LA_TYPE LA_ZERO typedef struct msgb mblk_t; # undef offsetof /* avoid stddefs.h and sys/sysmacros.h conflict */ # endif /* _PowerUX */ /* ** Siemens Nixdorf Informationssysteme AG SINIX ** ** Contributed by Gerald Rinske of Siemens Business Services VAS. */ # ifdef sinix # define HASRANDOM 0 /* has random(3) */ # define SYSLOG_BUFSIZE 1024 # define SM_INT32 int /* 32bit integer */ # endif /* sinix */ /* ** Motorola 922, MC88110, UNIX SYSTEM V/88 Release 4.0 Version 4.3 ** ** Contributed by Sergey Rusanov */ # ifdef MOTO # define HASFCHMOD 1 # define HASSETRLIMIT 0 # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASSETREUID 1 # define HASULIMIT 1 # define HASWAITPID 1 # define HASGETDTABLESIZE 1 # define HASGETUSERSHELL 1 # define IP_SRCROUTE 0 # define IDENTPROTO 0 # define RES_DNSRCH_VARIABLE _res_dnsrch # define _PATH_UNIX "/unix" # define _PATH_VENDOR_CF "/etc/sendmail.cf" # define _PATH_SENDMAILPID "/var/run/sendmail.pid" # endif /* MOTO */ /* ** Interix ** Contributed by Nedelcho Stanev ** ** Used for Interix support. */ # if defined(__INTERIX) # define HASURANDOMDEV 1 # define HASGETUSERSHELL 0 # define HASSTRERROR 1 # define HASUNSETENV 1 # define HASFCHOWN 1 # undef HAVE_SYS_ERRLIST # define sys_errlist __sys_errlist # define sys_nerr __sys_nerr # include # ifndef major # define major(dev) ((int)(((dev) >> 8) & 0xff)) # endif /* ! major */ # ifndef minor # define minor(dev) ((int)((dev) & 0xff)) # endif /* ! minor */ # endif /* defined(__INTERIX) */ # ifdef WIN32 /* ** Windows NT/2000 */ # undef HASSETSID # define HASSETSID 0 # undef HASLSTAT # define HASLSTAT 0 # define IDENTPROTO 1 # define IP_SRCROUTE 0 # define HASGETUSERSHELL 0 # define NETUNIX 0 # define HASFLOCK 1 # define HASSETREUID 0 # define HASFCHMOD 0 # define USESETEUID 0 # define HASSETRLIMIT 0 # define HASULIMIT 0 # define SNPRINTF_IS_BROKEN 1 # define SM_CONF_GETOPT 1 # define OLD_NEWDB 0 # define HASRANDOM 0 # define SECUREWARE 0 # define UID_T int # define GIT_T int # define MODE_T int # define SPT_TYPE SPT_WIN32 # define SFS_TYPE SFS_NT # define LA_TYPE LA_WIN32 # define SM_INT32 long /* ** WARNING: ulgy hack ahead! ** Since file permissions don't work here as sendmail expects it ** (e.g., -rw-r--r-- has mode 100666 which screws up readqf()) ** the permission bits are set to 0 which essentially turns off ** all file permission checks! */ /* get rid of compiler complaints due to redefinitions */ # ifdef S_IWUSR # undef S_IWUSR # endif /* S_IWUSR */ # ifdef S_IWGRP # undef S_IWGRP # endif /* S_IWGRP */ # ifdef S_IWOTH # undef S_IWOTH # endif /* S_IWOTH */ # ifdef S_ISLNK # undef S_ISLNK # endif /* S_ISLNK */ # ifdef S_ISREG # undef S_ISREG # endif /* S_ISREG */ # ifdef S_ISDIR # undef S_ISDIR # endif /* S_ISDIR */ # define S_IWUSR 0 # define S_IWGRP 0 # define S_IWOTH 0 # define S_ISLNK(s) 0 # define S_ISREG(s) ((s) & _S_IFREG) # define S_ISDIR(s) ((s) & _S_IFDIR) # if SM_CONF_UID_GID typedef int uid_t; typedef int gid_t; # endif /* SM_CONF_UID_GID */ # define _PATH_SENDMAILCF PATH_SENDMAILCF # define _PATH_SENDMAILPID PATH_SENDMAILPID # ifdef MATCHGECOS # undef MATCHGECOS # endif /* MATCHGECOS */ # define MATCHGECOS 0 # ifndef NEWDB # define NEWDB 1 # endif /* ! NEWDB */ # define WIFEXITED(st) ((st) < 0x100) # define WEXITSTATUS(st) (st) # define major(fd) (0) # define minor(fd) (0) # define pause() (sleep(1)) # define getegid() (0) # define SM_SET_H_ERRNO(err) WSASetLastError((err)) # if 0 # pragma message( " " __FILE__ "(2369) : Temporary disabled references to the BIND header files...." ) # endif /* 0 */ # endif /* WIN32 */ /********************************************************************** ** End of Per-Operating System defines **********************************************************************/ /********************************************************************** ** More general defines **********************************************************************/ /* general BSD defines */ # ifdef BSD # define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ # ifndef HASSETREUID # define HASSETREUID 1 /* has setreuid(2) call */ # endif /* ! HASSETREUID */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # ifndef IP_SRCROUTE # define IP_SRCROUTE 1 /* can check IP source routing */ # endif /* ! IP_SRCROUTE */ # ifndef HASSETRLIMIT # define HASSETRLIMIT 1 /* has setrlimit(2) call */ # endif /* ! HASSETRLIMIT */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif /* ! HASFLOCK */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone variable */ # endif /* ! TZ_TYPE */ # endif /* BSD */ /* general System V Release 4 defines */ # ifdef __svr4__ # define SYSTEM5 1 # define USESETEUID 1 /* has usable seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define BSD_COMP 1 /* get BSD ioctl calls */ # ifndef HASSETRLIMIT # define HASSETRLIMIT 1 /* has setrlimit(2) call */ # endif /* ! HASSETRLIMIT */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # endif /* ! HASGETUSERSHELL */ # ifndef HASFCHMOD # define HASFCHMOD 1 /* most (all?) SVr4s seem to have fchmod(2) */ # endif /* ! HASFCHMOD */ # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" # endif /* ! _PATH_UNIX */ # ifndef _PATH_VENDOR_CF # define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" # endif /* ! _PATH_VENDOR_CF */ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 128 # endif /* ! SYSLOG_BUFSIZE */ # ifndef SFS_TYPE # define SFS_TYPE SFS_STATVFS # endif /* ! SFS_TYPE */ # ifndef USE_SIGLONGJMP # define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ # endif /* ! USE_SIGLONGJMP */ # endif /* __svr4__ */ # ifdef __SVR4 # define LDA_USE_LOCKF 1 # define LDA_USE_SETEUID 1 # define _PATH_MAILDIR "/var/mail" # endif /* __SVR4 */ /* general System V defines */ # ifdef SYSTEM5 # include # define HASUNAME 1 /* use System V uname(2) system call */ # define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # ifndef HASULIMIT # define HASULIMIT 1 /* has the ulimit(2) syscall */ # endif /* ! HASULIMIT */ # ifndef LA_TYPE # ifdef MIOC_READKSYM # define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ # else /* MIOC_READKSYM */ # define LA_TYPE LA_INT /* assume integer load average */ # endif /* MIOC_READKSYM */ # endif /* ! LA_TYPE */ # ifndef SFS_TYPE # define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ # endif /* ! SFS_TYPE */ # ifndef TZ_TYPE # define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ # endif /* ! TZ_TYPE */ # endif /* SYSTEM5 */ /* general POSIX defines */ # ifdef _POSIX_VERSION # define HASSETSID 1 /* has POSIX setsid(2) call */ # define HASWAITPID 1 /* has POSIX waitpid(2) call */ # if _POSIX_VERSION >= 199500 && !defined(USESETEUID) # define USESETEUID 1 /* has usable seteuid(2) call */ # endif /* _POSIX_VERSION >= 199500 && !defined(USESETEUID) */ # endif /* _POSIX_VERSION */ /* ** Tweaking for systems that (for example) claim to be BSD or POSIX ** but don't have all the standard BSD or POSIX routines (boo hiss). */ # ifdef titan # undef HASINITGROUPS /* doesn't have initgroups(3) call */ # endif /* titan */ # ifdef _CRAYCOM # undef HASSETSID /* despite POSIX claim, doesn't have setsid */ # endif /* _CRAYCOM */ # ifdef MOTO # undef USESETEUID # endif /* MOTO */ /* ** Due to a "feature" in some operating systems such as Ultrix 4.3 and ** HPUX 8.0, if you receive a "No route to host" message (ICMP message ** ICMP_UNREACH_HOST) on _any_ connection, all connections to that host ** are closed. Some firewalls return this error if you try to connect ** to the IDENT port (113), so you can't receive email from these hosts ** on these systems. The firewall really should use a more specific ** message such as ICMP_UNREACH_PROTOCOL or _PORT or _FILTER_PROHIB. If ** not explicitly set to zero above, default it on. */ # ifndef IDENTPROTO # define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */ # endif /* ! IDENTPROTO */ # ifndef IP_SRCROUTE # define IP_SRCROUTE 1 /* Detect IP source routing */ # endif /* ! IP_SRCROUTE */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 1 /* libc has getusershell(3) call */ # endif /* ! HASGETUSERSHELL */ # ifndef NETUNIX # define NETUNIX 1 /* include unix domain support */ # endif /* ! NETUNIX */ # ifndef HASRANDOM # define HASRANDOM 1 /* has random(3) support */ # endif /* ! HASRANDOM */ # ifndef HASFLOCK # define HASFLOCK 0 /* assume no flock(2) support */ # endif /* ! HASFLOCK */ # ifndef HASSETREUID # define HASSETREUID 0 /* assume no setreuid(2) call */ # endif /* ! HASSETREUID */ # ifndef HASFCHMOD # define HASFCHMOD 0 /* assume no fchmod(2) syscall */ # endif /* ! HASFCHMOD */ # ifndef USESETEUID # define USESETEUID 0 /* assume no seteuid(2) call or no saved ids */ # endif /* ! USESETEUID */ # ifndef HASSETRLIMIT # define HASSETRLIMIT 0 /* assume no setrlimit(2) support */ # endif /* ! HASSETRLIMIT */ # ifndef HASULIMIT # define HASULIMIT 0 /* assume no ulimit(2) support */ # endif /* ! HASULIMIT */ # ifndef SECUREWARE # define SECUREWARE 0 /* assume no SecureWare C2 auditing hooks */ # endif /* ! SECUREWARE */ # ifndef USE_DOUBLE_FORK # define USE_DOUBLE_FORK 1 /* avoid intermediate zombies */ # endif /* ! USE_DOUBLE_FORK */ # ifndef USE_ENVIRON # define USE_ENVIRON 0 /* use main() envp instead of extern environ */ # endif /* ! USE_ENVIRON */ # ifndef USE_SIGLONGJMP # define USE_SIGLONGJMP 0 /* assume setjmp handles signals properly */ # endif /* ! USE_SIGLONGJMP */ # ifndef FDSET_CAST # define FDSET_CAST /* (empty) cast for fd_set arg to select */ # endif /* ! FDSET_CAST */ /* ** Pick a mailer setuid method for changing the current uid */ # define USE_SETEUID 0 # define USE_SETREUID 1 # define USE_SETUID 2 # if USESETEUID # define MAILER_SETUID_METHOD USE_SETEUID # else /* USESETEUID */ # if HASSETREUID # define MAILER_SETUID_METHOD USE_SETREUID # else /* HASSETREUID */ # define MAILER_SETUID_METHOD USE_SETUID # endif /* HASSETREUID */ # endif /* USESETEUID */ /* ** If no type for argument two of getgroups call is defined, assume ** it's an integer -- unfortunately, there seem to be several choices ** here. */ # ifndef GIDSET_T # define GIDSET_T int # endif /* ! GIDSET_T */ # ifndef UID_T # define UID_T uid_t # endif /* ! UID_T */ # ifndef GID_T # define GID_T gid_t # endif /* ! GID_T */ # ifndef MODE_T # define MODE_T mode_t # endif /* ! MODE_T */ # ifndef ARGV_T # define ARGV_T char ** # endif /* ! ARGV_T */ # ifndef SOCKADDR_LEN_T # define SOCKADDR_LEN_T int # endif /* ! SOCKADDR_LEN_T */ # ifndef SOCKOPT_LEN_T # define SOCKOPT_LEN_T int # endif /* ! SOCKOPT_LEN_T */ # ifndef QUAD_T # define QUAD_T unsigned long # endif /* ! QUAD_T */ /********************************************************************** ** Remaining definitions should never have to be changed. They are ** primarily to provide back compatibility for older systems -- for ** example, it includes some POSIX compatibility definitions **********************************************************************/ /* System 5 compatibility */ # ifndef S_ISREG # define S_ISREG(foo) ((foo & S_IFMT) == S_IFREG) # endif /* ! S_ISREG */ # ifndef S_ISDIR # define S_ISDIR(foo) ((foo & S_IFMT) == S_IFDIR) # endif /* ! S_ISDIR */ # if !defined(S_ISLNK) && defined(S_IFLNK) # define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK) # endif /* !defined(S_ISLNK) && defined(S_IFLNK) */ # if !defined(S_ISFIFO) # if defined(S_IFIFO) # define S_ISFIFO(foo) ((foo & S_IFMT) == S_IFIFO) # else /* defined(S_IFIFO) */ # define S_ISFIFO(foo) false # endif /* defined(S_IFIFO) */ # endif /* !defined(S_ISFIFO) */ # ifndef S_IRUSR # define S_IRUSR 0400 # endif /* ! S_IRUSR */ # ifndef S_IWUSR # define S_IWUSR 0200 # endif /* ! S_IWUSR */ # ifndef S_IRGRP # define S_IRGRP 0040 # endif /* ! S_IRGRP */ # ifndef S_IWGRP # define S_IWGRP 0020 # endif /* ! S_IWGRP */ # ifndef S_IROTH # define S_IROTH 0004 # endif /* ! S_IROTH */ # ifndef S_IWOTH # define S_IWOTH 0002 # endif /* ! S_IWOTH */ /* close-on-exec flag */ # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif /* ! FD_CLOEXEC */ /* ** Older systems don't have this error code -- it should be in ** /usr/include/sysexits.h. */ # ifndef EX_CONFIG # define EX_CONFIG 78 /* configuration error */ # endif /* ! EX_CONFIG */ /* pseudo-codes */ # define EX_QUIT 22 /* drop out of server immediately */ # define EX_RESTART 23 /* restart sendmail daemon */ # define EX_SHUTDOWN 24 /* shutdown sendmail daemon */ #ifndef EX_NOTFOUND # define EX_NOTFOUND EX_NOHOST #endif /* ! EX_NOTFOUND */ /* pseudo-code used for mci_setstat */ # define EX_NOTSTICKY (-5) /* don't save persistent status */ /* ** An "impossible" file mode to indicate that the file does not exist. */ # define ST_MODE_NOFILE 0171147 /* unlikely to occur */ /* type of arbitrary pointer */ # ifndef ARBPTR_T # define ARBPTR_T void * # endif /* ! ARBPTR_T */ # ifndef __P # include "sm/cdefs.h" # endif /* ! __P */ # if HESIOD && !defined(NAMED_BIND) # define NAMED_BIND 1 /* not one without the other */ # endif /* HESIOD && !defined(NAMED_BIND) */ # ifndef WIN32 # if NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) extern int h_errno; # endif /* NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) */ # endif /* ! WIN32 */ # if NEEDPUTENV extern int putenv __P((char *)); # endif /* NEEDPUTENV */ #if !HASUNSETENV extern void unsetenv __P((char *)); #endif /* !HASUNSETENV */ # ifdef LDAPMAP # include # include # include /* Some LDAP constants */ # define LDAPMAP_FALSE 0 # define LDAPMAP_TRUE 1 /* ** ldap_init(3) is broken in Umich 3.x and OpenLDAP 1.0/1.1. ** Use the lack of LDAP_OPT_SIZELIMIT to detect old API implementations ** and assume (falsely) that all old API implementations are broken. ** (OpenLDAP 1.2 and later have a working ldap_init(), add -DUSE_LDAP_INIT) */ # if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT) # define USE_LDAP_INIT 1 # endif /* defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT) */ /* ** LDAP_OPT_SIZELIMIT is not defined under Umich 3.x nor OpenLDAP 1.x, ** hence ldap_set_option() must not exist. */ # if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION) # define USE_LDAP_SET_OPTION 1 # endif /* defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION) */ # endif /* LDAPMAP */ # if HASUNAME # include # ifdef newstr # undef newstr # endif /* newstr */ # else /* HASUNAME */ # define NODE_LENGTH 32 struct utsname { char nodename[NODE_LENGTH + 1]; }; # endif /* HASUNAME */ # if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) # define MAXHOSTNAMELEN 256 # endif /* !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) */ # if !defined(SIGCHLD) && defined(SIGCLD) # define SIGCHLD SIGCLD # endif /* !defined(SIGCHLD) && defined(SIGCLD) */ # ifndef STDIN_FILENO # define STDIN_FILENO 0 # endif /* ! STDIN_FILENO */ # ifndef STDOUT_FILENO # define STDOUT_FILENO 1 # endif /* ! STDOUT_FILENO */ # ifndef STDERR_FILENO # define STDERR_FILENO 2 # endif /* ! STDERR_FILENO */ # ifndef LOCK_SH # define LOCK_SH 0x01 /* shared lock */ # define LOCK_EX 0x02 /* exclusive lock */ # define LOCK_NB 0x04 /* non-blocking lock */ # define LOCK_UN 0x08 /* unlock */ # endif /* ! LOCK_SH */ # ifndef S_IXOTH # define S_IXOTH (S_IEXEC >> 6) # endif /* ! S_IXOTH */ # ifndef S_IXGRP # define S_IXGRP (S_IEXEC >> 3) # endif /* ! S_IXGRP */ # ifndef S_IXUSR # define S_IXUSR (S_IEXEC) # endif /* ! S_IXUSR */ #ifndef O_ACCMODE # define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) #endif /* ! O_ACCMODE */ # ifndef SEEK_SET # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 # endif /* ! SEEK_SET */ # ifndef SIG_ERR # define SIG_ERR ((void (*)()) -1) # endif /* ! SIG_ERR */ # ifndef WEXITSTATUS # define WEXITSTATUS(st) (((st) >> 8) & 0377) # endif /* ! WEXITSTATUS */ # ifndef WIFEXITED # define WIFEXITED(st) (((st) & 0377) == 0) # endif /* ! WIFEXITED */ # ifndef WIFSTOPPED # define WIFSTOPPED(st) (((st) & 0100) == 0) # endif /* ! WIFSTOPPED */ # ifndef WCOREDUMP # define WCOREDUMP(st) (((st) & 0200) != 0) # endif /* ! WCOREDUMP */ # ifndef WTERMSIG # define WTERMSIG(st) (((st) & 0177)) # endif /* ! WTERMSIG */ # ifndef SIGFUNC_DEFINED typedef void (*sigfunc_t) __P((int)); # endif /* ! SIGFUNC_DEFINED */ # ifndef SIGFUNC_RETURN # define SIGFUNC_RETURN # endif /* ! SIGFUNC_RETURN */ # ifndef SIGFUNC_DECL # define SIGFUNC_DECL void # endif /* ! SIGFUNC_DECL */ /* size of syslog buffer */ # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 # endif /* ! SYSLOG_BUFSIZE */ /* for FD_SET() */ #ifndef FD_SETSIZE # define FD_SETSIZE 256 #endif /* ! FD_SETSIZE */ /* ** Size of prescan buffer. ** Despite comments in the _sendmail_ book, this probably should ** not be changed; there are some hard-to-define dependencies. */ # define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */ /* fork routine -- set above using #ifdef _osname_ or in Makefile */ # ifndef FORK # define FORK fork /* function to call to fork mailer */ # endif /* ! FORK */ /* setting h_errno */ # ifndef SM_SET_H_ERRNO # define SM_SET_H_ERRNO(err) h_errno = (err) # endif /* SM_SET_H_ERRNO */ # ifndef SM_CONF_GETOPT # define SM_CONF_GETOPT 1 # endif /* ! SM_CONF_GETOPT */ /* random routine -- set above using #ifdef _osname_ or in Makefile */ # if HASRANDOM # define get_random() random() # else /* HASRANDOM */ # define get_random() ((long) rand()) # ifndef RANDOMSHIFT # define RANDOMSHIFT 8 # endif /* ! RANDOMSHIFT */ # endif /* HASRANDOM */ /* ** Default to using scanf in readcf. */ # ifndef SCANF # define SCANF 1 # endif /* ! SCANF */ /* XXX 32 bit type */ # ifndef SM_INT32 # define SM_INT32 int32_t # endif /* ! SM_INT32 */ /* ** SVr4 and similar systems use different routines for setjmp/longjmp ** with signal support */ # if USE_SIGLONGJMP # ifdef jmp_buf # undef jmp_buf # endif /* jmp_buf */ # define jmp_buf sigjmp_buf # ifdef setjmp # undef setjmp # endif /* setjmp */ # define setjmp(env) sigsetjmp(env, 1) # ifdef longjmp # undef longjmp # endif /* longjmp */ # define longjmp(env, val) siglongjmp(env, val) # endif /* USE_SIGLONGJMP */ # if !defined(NGROUPS_MAX) && defined(NGROUPS) # define NGROUPS_MAX NGROUPS /* POSIX naming convention */ # endif /* !defined(NGROUPS_MAX) && defined(NGROUPS) */ /* ** Some snprintf() implementations are rumored not to NUL terminate. */ # if SNPRINTF_IS_BROKEN # ifdef snprintf # undef snprintf # endif /* snprintf */ # define snprintf sm_snprintf # ifdef vsnprintf # undef vsnprintf # endif /* vsnprintf */ # define vsnprintf sm_vsnprintf # endif /* SNPRINTF_IS_BROKEN */ /* ** If we don't have a system syslog, simulate it. */ # if !LOG # define LOG_EMERG 0 /* system is unusable */ # define LOG_ALERT 1 /* action must be taken immediately */ # define LOG_CRIT 2 /* critical conditions */ # define LOG_ERR 3 /* error conditions */ # define LOG_WARNING 4 /* warning conditions */ # define LOG_NOTICE 5 /* normal but significant condition */ # define LOG_INFO 6 /* informational */ # define LOG_DEBUG 7 /* debug-level messages */ # endif /* !LOG */ # ifndef SM_CONF_SYSLOG # define SM_CONF_SYSLOG 1 /* syslog.h has prototype for syslog() */ # endif /* SM_CONF_SYSLOG */ # if !SM_CONF_SYSLOG # ifdef __STDC__ extern void syslog(int, const char *, ...); # else /* __STDC__ */ extern void syslog(); # endif /* __STDC__ */ # endif /* !SM_CONF_SYSLOG */ /* portable(?) definition for alignment */ # ifndef SM_ALIGN_SIZE struct sm_align { char al_c; union { long al_l; void *al_p; double al_d; void (*al_f) __P((void)); } al_u; }; # define SM_ALIGN_SIZE offsetof(struct sm_align, al_u) # endif /* ! SM_ALIGN_SIZE */ # define SM_ALIGN_BITS (SM_ALIGN_SIZE - 1) #endif /* ! SM_CONF_H */ dk-milter-1.0.0.dfsg/include/sm/ldap.h0000644000175000017500000000705010703013624017215 0ustar madhackmadhack/* * Copyright (c) 2001-2003, 2005-2007 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: ldap.h,v 1.33 2007/10/10 00:06:44 ca Exp $ */ #ifndef SM_LDAP_H # define SM_LDAP_H # include # include /* ** NOTE: These should be changed from LDAPMAP_* to SM_LDAP_* ** in the next major release (8.x+1) of sendmail. */ # ifndef LDAPMAP_MAX_ATTR # define LDAPMAP_MAX_ATTR 64 # endif /* ! LDAPMAP_MAX_ATTR */ # ifndef LDAPMAP_MAX_FILTER # define LDAPMAP_MAX_FILTER 1024 # endif /* ! LDAPMAP_MAX_FILTER */ # ifndef LDAPMAP_MAX_PASSWD # define LDAPMAP_MAX_PASSWD 256 # endif /* ! LDAPMAP_MAX_PASSWD */ # if LDAPMAP /* maximum number of arguments in a map lookup, see sendmail.h: MAX_MAP_ARGS */ # define SM_LDAP_ARGS 10 /* error codes from sm_ldap_search*() */ # define SM_LDAP_ERR (-1) /* generic error: ldap_search(3) */ # define SM_LDAP_ERR_ARG_MISS (-2) /* an argument is missing */ /* Attribute types */ # define SM_LDAP_ATTR_NONE (-1) # define SM_LDAP_ATTR_OBJCLASS 0 # define SM_LDAP_ATTR_NORMAL 1 # define SM_LDAP_ATTR_DN 2 # define SM_LDAP_ATTR_FILTER 3 # define SM_LDAP_ATTR_URL 4 /* sm_ldap_results() flags */ # define SM_LDAP_SINGLEMATCH 0x0001 # define SM_LDAP_MATCHONLY 0x0002 # define SM_LDAP_USE_ALLATTR 0x0004 # define SM_LDAP_SINGLEDN 0x0008 struct sm_ldap_struct { /* needed for ldap_open or ldap_init */ char *ldap_uri; char *ldap_host; int ldap_port; int ldap_version; pid_t ldap_pid; /* options set in ld struct before ldap_bind_s */ int ldap_deref; time_t ldap_timelimit; int ldap_sizelimit; int ldap_options; /* args for ldap_bind_s */ LDAP *ldap_ld; char *ldap_binddn; char *ldap_secret; int ldap_method; /* args for ldap_search */ char *ldap_base; int ldap_scope; char *ldap_filter; char *ldap_attr[LDAPMAP_MAX_ATTR + 1]; int ldap_attr_type[LDAPMAP_MAX_ATTR + 1]; char *ldap_attr_needobjclass[LDAPMAP_MAX_ATTR + 1]; bool ldap_attrsonly; bool ldap_multi_args; /* args for ldap_result */ struct timeval ldap_timeout; LDAPMessage *ldap_res; /* ldapmap_lookup options */ char ldap_attrsep; # if _FFR_LDAP_NETWORK_TIMEOUT struct timeval ldap_networktmo; # endif /* _FFR_LDAP_NETWORK_TIMEOUT */ /* Linked list of maps sharing the same LDAP binding */ void *ldap_next; }; typedef struct sm_ldap_struct SM_LDAP_STRUCT; struct sm_ldap_recurse_entry { char *lr_search; int lr_type; LDAPURLDesc *lr_ludp; char **lr_attrs; bool lr_done; }; struct sm_ldap_recurse_list { int lrl_size; int lrl_cnt; struct sm_ldap_recurse_entry **lrl_data; }; typedef struct sm_ldap_recurse_entry SM_LDAP_RECURSE_ENTRY; typedef struct sm_ldap_recurse_list SM_LDAP_RECURSE_LIST; /* functions */ extern void sm_ldap_clear __P((SM_LDAP_STRUCT *)); extern bool sm_ldap_start __P((char *, SM_LDAP_STRUCT *)); extern int sm_ldap_search __P((SM_LDAP_STRUCT *, char *)); extern int sm_ldap_search_m __P((SM_LDAP_STRUCT *, char **)); extern int sm_ldap_results __P((SM_LDAP_STRUCT *, int, int, int, SM_RPOOL_T *, char **, int *, int *, SM_LDAP_RECURSE_LIST *)); extern void sm_ldap_setopts __P((LDAP *, SM_LDAP_STRUCT *)); extern int sm_ldap_geterrno __P((LDAP *)); extern void sm_ldap_close __P((SM_LDAP_STRUCT *)); /* Portability defines */ # if !SM_CONF_LDAP_MEMFREE # define ldap_memfree(x) ((void) 0) # endif /* !SM_CONF_LDAP_MEMFREE */ # endif /* LDAPMAP */ #endif /* ! SM_LDAP_H */ dk-milter-1.0.0.dfsg/include/sm/signal.h0000644000175000017500000000407507326105405017564 0ustar madhackmadhack/* * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: signal.h,v 1.16 2001/07/20 19:48:21 gshapiro Exp $ */ /* ** SIGNAL.H -- libsm (and sendmail) signal facilities ** Extracted from sendmail/conf.h and focusing ** on signal configuration. */ #ifndef SM_SIGNAL_H #define SM_SIGNAL_H 1 #ifdef WIN32 # pragma once #endif /* WIN32 */ #include #include #include #include #include /* ** Critical signal sections */ #define PEND_SIGHUP 0x0001 #define PEND_SIGINT 0x0002 #define PEND_SIGTERM 0x0004 #define PEND_SIGUSR1 0x0008 #define ENTER_CRITICAL() InCriticalSection++ #define LEAVE_CRITICAL() \ do \ { \ if (InCriticalSection > 0) \ InCriticalSection--; \ } while (0) #define CHECK_CRITICAL(sig) \ do \ { \ if (InCriticalSection > 0 && (sig) != 0) \ { \ pend_signal((sig)); \ return SIGFUNC_RETURN; \ } \ } while (0) /* variables */ extern unsigned int volatile InCriticalSection; /* >0 if in critical section */ extern int volatile PendingSignal; /* pending signal to resend */ /* functions */ extern void pend_signal __P((int)); /* reset signal in case System V semantics */ #ifdef SYS5SIGNALS # define FIX_SYSV_SIGNAL(sig, handler) \ { \ if ((sig) != 0) \ (void) sm_signal((sig), (handler)); \ } #else /* SYS5SIGNALS */ # define FIX_SYSV_SIGNAL(sig, handler) { /* EMPTY */ } #endif /* SYS5SIGNALS */ extern void sm_allsignals __P((bool)); extern int sm_blocksignal __P((int)); extern int sm_releasesignal __P((int)); extern sigfunc_t sm_signal __P((int, sigfunc_t)); extern SIGFUNC_DECL sm_signal_noop __P((int)); #endif /* SM_SIGNAL_H */ dk-milter-1.0.0.dfsg/include/sm/gen.h0000644000175000017500000000354407751772512017073 0ustar madhackmadhack/* * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: gen.h,v 1.23 2003/11/04 18:51:54 ca Exp $ */ /* ** libsm general definitions ** See libsm/gen.html for documentation. */ #ifndef SM_GEN_H # define SM_GEN_H # ifdef WIN32 # include # endif /* WIN32 */ # include # include # include /* ** Define SM_RCSID and SM_IDSTR, ** macros used to embed RCS and SCCS identification strings in object files. */ # ifdef lint # define SM_RCSID(str) # define SM_IDSTR(id,str) # else /* lint */ # define SM_RCSID(str) SM_UNUSED(static const char RcsId[]) = str; # define SM_IDSTR(id,str) SM_UNUSED(static const char id[]) = str; # endif /* lint */ /* ** Define NULL and offsetof (from the C89 standard) */ # if SM_CONF_STDDEF_H # include # else /* SM_CONF_STDDEF_H */ # ifndef NULL # define NULL 0 # endif /* ! NULL */ # define offsetof(type, member) ((size_t)(&((type *)0)->member)) # endif /* SM_CONF_STDDEF_H */ /* ** Define bool, true, false (from the C99 standard) */ # if SM_CONF_STDBOOL_H # include # else /* SM_CONF_STDBOOL_H */ # ifndef __cplusplus typedef int bool; # define false 0 # define true 1 # define __bool_true_false_are_defined 1 # endif /* ! __cplusplus */ # endif /* SM_CONF_STDBOOL_H */ /* ** Define SM_MAX and SM_MIN */ # define SM_MAX(a, b) ((a) > (b) ? (a) : (b)) # define SM_MIN(a, b) ((a) < (b) ? (a) : (b)) /* Define SM_SUCCESS and SM_FAILURE */ # define SM_SUCCESS 0 # define SM_FAILURE (-1) /* XXX This needs to be fixed when we start to use threads: */ typedef int SM_ATOMIC_INT_T; typedef unsigned int SM_ATOMIC_UINT_T; #endif /* SM_GEN_H */ dk-milter-1.0.0.dfsg/include/sm/errstring.h0000644000175000017500000000651110600343043020312 0ustar madhackmadhack/* * Copyright (c) 1998-2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: errstring.h,v 1.10 2007/03/21 23:56:19 ca Exp $ */ /* ** Error codes. */ #ifndef SM_ERRSTRING_H # define SM_ERRSTRING_H #if defined(__QNX__) # define E_PSEUDOBASE 512 #endif /* defined(__QNX__) */ #include #if NEEDINTERRNO extern int errno; #endif /* NEEDINTERRNO */ /* ** These are used in a few cases where we need some special ** error codes, but where the system doesn't provide something ** reasonable. They are printed in sm_errstring. */ #ifndef E_PSEUDOBASE # define E_PSEUDOBASE 256 #endif /* ! E_PSEUDOBASE */ #define E_SM_OPENTIMEOUT (E_PSEUDOBASE + 0) /* Timeout on file open */ #define E_SM_NOSLINK (E_PSEUDOBASE + 1) /* Symbolic links not allowed */ #define E_SM_NOHLINK (E_PSEUDOBASE + 2) /* Hard links not allowed */ #define E_SM_REGONLY (E_PSEUDOBASE + 3) /* Regular files only */ #define E_SM_ISEXEC (E_PSEUDOBASE + 4) /* Executable files not allowed */ #define E_SM_WWDIR (E_PSEUDOBASE + 5) /* World writable directory */ #define E_SM_GWDIR (E_PSEUDOBASE + 6) /* Group writable directory */ #define E_SM_FILECHANGE (E_PSEUDOBASE + 7) /* File changed after open */ #define E_SM_WWFILE (E_PSEUDOBASE + 8) /* World writable file */ #define E_SM_GWFILE (E_PSEUDOBASE + 9) /* Group writable file */ #define E_SM_GRFILE (E_PSEUDOBASE + 10) /* g readable file */ #define E_SM_WRFILE (E_PSEUDOBASE + 11) /* o readable file */ #define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */ #define E_SMDBBASE (E_PSEUDOBASE + 40) /* base for libsmdb errors */ #define E_LDAPBASE (E_PSEUDOBASE + 70) /* base for LDAP errors */ #define E_LDAPURLBASE (E_PSEUDOBASE + 200) /* base for LDAP URL errors */ #ifdef WIN32 # define E_WIN32BASE (E_PSEUDOBASE + 1000) /* base for win32 API errors */ #endif /* WIN32 */ /* libsmdb */ #define SMDBE_OK 0 #define SMDBE_MALLOC (E_SMDBBASE + 1) #define SMDBE_GDBM_IS_BAD (E_SMDBBASE + 2) #define SMDBE_UNSUPPORTED (E_SMDBBASE + 3) #define SMDBE_DUPLICATE (E_SMDBBASE + 4) #define SMDBE_BAD_OPEN (E_SMDBBASE + 5) #define SMDBE_NOT_FOUND (E_SMDBBASE + 6) #define SMDBE_UNKNOWN_DB_TYPE (E_SMDBBASE + 7) #define SMDBE_UNSUPPORTED_DB_TYPE (E_SMDBBASE + 8) #define SMDBE_INCOMPLETE (E_SMDBBASE + 9) #define SMDBE_KEY_EMPTY (E_SMDBBASE + 10) #define SMDBE_KEY_EXIST (E_SMDBBASE + 11) #define SMDBE_LOCK_DEADLOCK (E_SMDBBASE + 12) #define SMDBE_LOCK_NOT_GRANTED (E_SMDBBASE + 13) #define SMDBE_LOCK_NOT_HELD (E_SMDBBASE + 14) #define SMDBE_RUN_RECOVERY (E_SMDBBASE + 15) #define SMDBE_IO_ERROR (E_SMDBBASE + 16) #define SMDBE_READ_ONLY (E_SMDBBASE + 17) #define SMDBE_DB_NAME_TOO_LONG (E_SMDBBASE + 18) #define SMDBE_INVALID_PARAMETER (E_SMDBBASE + 19) #define SMDBE_ONLY_SUPPORTS_ONE_CURSOR (E_SMDBBASE + 20) #define SMDBE_NOT_A_VALID_CURSOR (E_SMDBBASE + 21) #define SMDBE_LAST_ENTRY (E_SMDBBASE + 22) #define SMDBE_OLD_VERSION (E_SMDBBASE + 23) #define SMDBE_VERSION_MISMATCH (E_SMDBBASE + 24) extern const char *sm_errstring __P((int _errno)); # ifdef WIN32 extern const char *sm_win32_strerror(unsigned int win32_error); # define sm_win32_geterror() (GetLastError() + E_WIN32BASE) # endif /* WIN32 */ #endif /* SM_ERRSTRING_H */ dk-milter-1.0.0.dfsg/include/sm/assert.h0000644000175000017500000000574407307757145017631 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: assert.h,v 1.10 2001/06/07 20:04:53 ca Exp $ */ /* ** libsm abnormal program termination and assertion checking ** See libsm/assert.html for documentation. */ #ifndef SM_ASSERT_H # define SM_ASSERT_H # include # include /* ** abnormal program termination */ typedef void (*SM_ABORT_HANDLER_T) __P((const char *, int, const char *)); extern SM_DEAD(void sm_abort_at __P(( const char *, int, const char *))); extern void sm_abort_sethandler __P(( SM_ABORT_HANDLER_T)); extern SM_DEAD(void PRINTFLIKE(1, 2) sm_abort __P(( char *, ...))); /* ** assertion checking */ # ifndef SM_CHECK_ALL # define SM_CHECK_ALL 1 # endif /* ! SM_CHECK_ALL */ # ifndef SM_CHECK_REQUIRE # define SM_CHECK_REQUIRE SM_CHECK_ALL # endif /* ! SM_CHECK_REQUIRE */ # ifndef SM_CHECK_ENSURE # define SM_CHECK_ENSURE SM_CHECK_ALL # endif /* ! SM_CHECK_ENSURE */ # ifndef SM_CHECK_ASSERT # define SM_CHECK_ASSERT SM_CHECK_ALL # endif /* ! SM_CHECK_ASSERT */ # if SM_CHECK_REQUIRE # if defined(__STDC__) || defined(__cplusplus) # define SM_REQUIRE(cond) \ ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ "SM_REQUIRE(" #cond ") failed"), 0))) # else /* defined(__STDC__) || defined(__cplusplus) */ # define SM_REQUIRE(cond) \ ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ "SM_REQUIRE(cond) failed"), 0))) # endif /* defined(__STDC__) || defined(__cplusplus) */ # else /* SM_CHECK_REQUIRE */ # define SM_REQUIRE(cond) ((void) 0) # endif /* SM_CHECK_REQUIRE */ # define SM_REQUIRE_ISA(obj, magic) \ SM_REQUIRE((obj) != NULL && (obj)->sm_magic == (magic)) # if SM_CHECK_ENSURE # if defined(__STDC__) || defined(__cplusplus) # define SM_ENSURE(cond) \ ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ "SM_ENSURE(" #cond ") failed"), 0))) # else /* defined(__STDC__) || defined(__cplusplus) */ # define SM_ENSURE(cond) \ ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ "SM_ENSURE(cond) failed"), 0))) # endif /* defined(__STDC__) || defined(__cplusplus) */ # else /* SM_CHECK_ENSURE */ # define SM_ENSURE(cond) ((void) 0) # endif /* SM_CHECK_ENSURE */ # if SM_CHECK_ASSERT # if defined(__STDC__) || defined(__cplusplus) # define SM_ASSERT(cond) \ ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ "SM_ASSERT(" #cond ") failed"), 0))) # else /* defined(__STDC__) || defined(__cplusplus) */ # define SM_ASSERT(cond) \ ((void) ((cond) || (sm_abort_at(__FILE__, __LINE__, \ "SM_ASSERT(cond) failed"), 0))) # endif /* defined(__STDC__) || defined(__cplusplus) */ # else /* SM_CHECK_ASSERT */ # define SM_ASSERT(cond) ((void) 0) # endif /* SM_CHECK_ASSERT */ extern SM_DEBUG_T SmExpensiveRequire; extern SM_DEBUG_T SmExpensiveEnsure; extern SM_DEBUG_T SmExpensiveAssert; #endif /* ! SM_ASSERT_H */ dk-milter-1.0.0.dfsg/include/sm/setjmp.h0000644000175000017500000000275507251575434017626 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: setjmp.h,v 1.3 2001/03/08 03:23:08 ca Exp $ */ #ifndef SM_SETJMP_H # define SM_SETJMP_H # include # include /* ** sm_setjmp_sig is a setjmp that saves the signal mask. ** sm_setjmp_nosig is a setjmp that does *not* save the signal mask. ** SM_JMPBUF_T is used with both of the above macros. ** ** On most systems, these can be implemented using sigsetjmp. ** Some old BSD systems do not have sigsetjmp, but they do have ** setjmp and _setjmp, which are just as good. */ # if SM_CONF_SIGSETJMP typedef sigjmp_buf SM_JMPBUF_T; # define sm_setjmp_sig(buf) sigsetjmp(buf, 1) # define sm_setjmp_nosig(buf) sigsetjmp(buf, 0) # define sm_longjmp_sig(buf, val) siglongjmp(buf, val) # define sm_longjmp_nosig(buf, val) siglongjmp(buf, val) # else /* SM_CONF_SIGSETJMP */ typedef jmp_buf SM_JMPBUF_T; # define sm_setjmp_sig(buf) setjmp(buf) # define sm_longjmp_sig(buf, val) longjmp(buf, val) # ifdef WIN32 # define sm_setjmp_nosig(buf) setjmp(buf) # define sm_longjmp_nosig(buf, val) longjmp(buf, val) # else /* WIN32 */ # define sm_setjmp_nosig(buf) _setjmp(buf) # define sm_longjmp_nosig(buf, val) _longjmp(buf, val) # endif /* WIN32 */ # endif /* SM_CONF_SIGSETJMP */ #endif /* ! SM_SETJMP_H */ dk-milter-1.0.0.dfsg/include/sm/sem.h0000644000175000017500000000251510205212772017064 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sem.h,v 1.9 2005/02/17 22:08:58 ca Exp $ */ #ifndef SM_SEM_H # define SM_SEM_H 1 #include /* key for semaphores */ # define SM_SEM_KEY (41L) # define SM_SEM_NO_ID (-1) # define SM_NO_SEM(id) ((id) < 0) # if SM_CONF_SEM > 0 # include # include # include # if SM_CONF_SEM == 2 union semun { int val; struct semid_ds *buf; ushort *array; }; # endif /* SM_CONF_SEM == 2 */ # ifndef SEM_A # define SEM_A 0200 # endif /* SEM_A */ # ifndef SEM_R # define SEM_R 0400 # endif /* SEM_R */ # define SM_NSEM 1 extern int sm_sem_start __P((key_t, int, int, bool)); extern int sm_sem_stop __P((int)); extern int sm_sem_acq __P((int, int, int)); extern int sm_sem_rel __P((int, int, int)); extern int sm_sem_get __P((int, int)); # else /* SM_CONF_SEM > 0 */ # define sm_sem_start(key, nsem, semflg, owner) 0 # define sm_sem_stop(semid) 0 # define sm_sem_acq(semid, semnum, timeout) 0 # define sm_sem_rel(semid, semnum, timeout) 0 # define sm_sem_get(semid, semnum) 0 # endif /* SM_CONF_SEM > 0 */ #endif /* ! SM_SEM_H */ dk-milter-1.0.0.dfsg/include/sm/cf.h0000644000175000017500000000102307251575433016676 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: cf.h,v 1.2 2001/03/08 03:23:07 ca Exp $ */ #ifndef SM_CF_H # define SM_CF_H #include typedef struct { char *opt_name; char *opt_val; } SM_CF_OPT_T; extern int sm_cf_getopt __P(( char *path, int optc, SM_CF_OPT_T *optv)); #endif /* ! SM_CF_H */ dk-milter-1.0.0.dfsg/include/sm/time.h0000644000175000017500000000251110253661447017244 0ustar madhackmadhack/* * Copyright (c) 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: time.h,v 1.1 2005/06/14 23:07:19 ca Exp $ */ #ifndef SM_TIME_H # define SM_TIME_H 1 # include # include /* should be defined in sys/time.h */ #ifndef timersub # define timersub(tvp, uvp, vvp) \ do \ { \ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ if ((vvp)->tv_usec < 0) \ { \ (vvp)->tv_sec--; \ (vvp)->tv_usec += 1000000; \ } \ } while (0) #endif /* !timersub */ #ifndef timeradd # define timeradd(tvp, uvp, vvp) \ do \ { \ (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ if ((vvp)->tv_usec >= 1000000) \ { \ (vvp)->tv_sec++; \ (vvp)->tv_usec -= 1000000; \ } \ } while (0) #endif /* !timeradd */ #ifndef timercmp # define timercmp(tvp, uvp, cmp) \ (((tvp)->tv_sec == (uvp)->tv_sec) ? \ ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ ((tvp)->tv_sec cmp (uvp)->tv_sec)) #endif /* !timercmp */ #endif /* ! SM_TIME_H */ dk-milter-1.0.0.dfsg/include/sm/string.h0000644000175000017500000000517407741571351017626 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: string.h,v 1.38 2003/10/10 17:56:57 ca Exp $ */ /* ** libsm string manipulation */ #ifndef SM_STRING_H # define SM_STRING_H # include # include # include /* strlc{py,at}, strerror */ /* return number of bytes left in a buffer */ #define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf)) extern int PRINTFLIKE(3, 4) sm_snprintf __P((char *, size_t, const char *, ...)); extern bool sm_match __P((const char *_str, const char *_pattern)); extern char * sm_strdup __P((char *)); extern char * sm_strndup_x __P((const char *_str, size_t _len)); #if DO_NOT_USE_STRCPY /* for "normal" data (free'd before end of process) */ extern char * sm_strdup_x __P((const char *_str)); /* for data that is supposed to be persistent. */ extern char * sm_pstrdup_x __P((const char *_str)); extern char * sm_strdup_tagged_x __P((const char *str, char *file, int line, int group)); #else /* DO_NOT_USE_STRCPY */ /* for "normal" data (free'd before end of process) */ # define sm_strdup_x(str) strcpy(sm_malloc_x(strlen(str) + 1), str) /* for data that is supposed to be persistent. */ # define sm_pstrdup_x(str) strcpy(sm_pmalloc_x(strlen(str) + 1), str) # define sm_strdup_tagged_x(str, file, line, group) \ strcpy(sm_malloc_tagged_x(strlen(str) + 1, file, line, group), str) #endif /* DO_NOT_USE_STRCPY */ extern char * sm_stringf_x __P((const char *_fmt, ...)); extern char * sm_vstringf_x __P((const char *_fmt, va_list _ap)); extern size_t sm_strlcpy __P((char *_dst, const char *_src, ssize_t _len)); extern size_t sm_strlcat __P((char *_dst, const char *_src, ssize_t _len)); extern size_t sm_strlcat2 __P((char *, const char *, const char *, ssize_t)); extern size_t #ifdef __STDC__ sm_strlcpyn(char *dst, ssize_t len, int n, ...); #else /* __STDC__ */ sm_strlcpyn __P((char *, ssize_t, int, va_dcl)); #endif /* __STDC__ */ # if !HASSTRERROR extern char * strerror __P((int _errno)); # endif /* !HASSTRERROR */ extern int sm_strrevcmp __P((const char *, const char *)); extern int sm_strrevcasecmp __P((const char *, const char *)); extern int sm_strcasecmp __P((const char *, const char *)); extern int sm_strncasecmp __P((const char *, const char *, size_t)); extern LONGLONG_T sm_strtoll __P((const char *, char**, int)); extern ULONGLONG_T sm_strtoull __P((const char *, char**, int)); extern void stripquotes __P((char *)); #endif /* SM_STRING_H */ dk-milter-1.0.0.dfsg/include/sm/misc.h0000644000175000017500000000074710450613607017244 0ustar madhackmadhack/* * Copyright (c) 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: misc.h,v 1.1 2006/06/28 23:57:59 ca Exp $ */ #ifndef SM_MISC_H # define SM_MISC_H 1 int sm_memstat_open __P((void)); int sm_memstat_close __P((void)); int sm_memstat_get __P((char *, long *)); #endif /* ! SM_MISC_H */ dk-milter-1.0.0.dfsg/include/sm/clock.h0000644000175000017500000000435410103767041017377 0ustar madhackmadhack/* * Copyright (c) 1998-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: clock.h,v 1.12 2004/08/03 19:57:21 ca Exp $ */ /* ** CLOCK.H -- for co-ordinating timed events */ #ifndef _SM_CLOCK_H # define _SM_CLOCK_H 1 # include # if SM_CONF_SETITIMER # include # endif /* SM_CONF_SETITIMER */ /* ** STRUCT SM_EVENT -- event queue. ** ** Maintained in sorted order. ** ** We store the pid of the process that set this event to insure ** that when we fork we will not take events intended for the parent. */ struct sm_event { # if SM_CONF_SETITIMER struct timeval ev_time; /* time of the call (microseconds) */ # else /* SM_CONF_SETITIMER */ time_t ev_time; /* time of the call (seconds) */ # endif /* SM_CONF_SETITIMER */ void (*ev_func)__P((int)); /* function to call */ int ev_arg; /* argument to ev_func */ pid_t ev_pid; /* pid that set this event */ struct sm_event *ev_link; /* link to next item */ }; typedef struct sm_event SM_EVENT; /* functions */ extern void sm_clrevent __P((SM_EVENT *)); extern void sm_clear_events __P((void)); extern SM_EVENT *sm_seteventm __P((int, void(*)__P((int)), int)); extern SM_EVENT *sm_sigsafe_seteventm __P((int, void(*)__P((int)), int)); extern SIGFUNC_DECL sm_tick __P((int)); /* ** SM_SETEVENT -- set an event to happen at a specific time in seconds. ** ** Translates the seconds into millseconds and calls sm_seteventm() ** to get a specific event to happen in the future at a specific time. ** ** Parameters: ** t -- intvl until next event occurs (seconds). ** f -- function to call on event. ** a -- argument to func on event. ** ** Returns: ** result of sm_seteventm(). ** ** Side Effects: ** Any that sm_seteventm() have. */ #define sm_setevent(t, f, a) sm_seteventm((int)((t) * 1000), (f), (a)) #define sm_sigsafe_setevent(t, f, a) sm_sigsafe_seteventm((int)((t) * 1000), (f), (a)) #endif /* _SM_CLOCK_H */ dk-milter-1.0.0.dfsg/include/sm/debug.h0000644000175000017500000000612307607411436017377 0ustar madhackmadhack/* * Copyright (c) 2000, 2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: debug.h,v 1.16 2003/01/10 00:26:06 ca Exp $ */ /* ** libsm debugging and tracing ** See libsm/debug.html for documentation. */ #ifndef SM_DEBUG_H # define SM_DEBUG_H # include # include /* ** abstractions for printing trace messages */ extern SM_FILE_T * sm_debug_file __P((void)); extern void sm_debug_setfile __P(( SM_FILE_T *)); extern void PRINTFLIKE(1, 2) sm_dprintf __P((char *_fmt, ...)); extern void sm_dflush __P((void)); extern void sm_debug_close __P((void)); /* ** abstractions for setting and testing debug activation levels */ extern void sm_debug_addsettings_x __P((const char *)); extern void sm_debug_addsetting_x __P((const char *, int)); # define SM_DEBUG_UNKNOWN ((SM_ATOMIC_UINT_T)(-1)) extern const char SmDebugMagic[]; typedef struct sm_debug SM_DEBUG_T; struct sm_debug { const char *sm_magic; /* points to SmDebugMagic */ /* ** debug_level is the activation level of this debug ** object. Level 0 means no debug activity. ** It is initialized to SM_DEBUG_UNKNOWN, which indicates ** that the true value is unknown. If debug_level == ** SM_DEBUG_UNKNOWN, then the access functions will look up ** its true value in the internal table of debug settings. */ SM_ATOMIC_UINT_T debug_level; /* ** debug_name is the name used to reference this SM_DEBUG ** structure via the sendmail -d option. */ char *debug_name; /* ** debug_desc is a literal character string of the form ** "@(#)$Debug: - $" */ char *debug_desc; /* ** We keep a linked list of initialized SM_DEBUG structures ** so that when sm_debug_addsetting is called, we can reset ** them all back to the uninitialized state. */ SM_DEBUG_T *debug_next; }; # ifndef SM_DEBUG_CHECK # define SM_DEBUG_CHECK 1 # endif /* ! SM_DEBUG_CHECK */ # if SM_DEBUG_CHECK /* ** This macro is cleverly designed so that if the debug object is below ** the specified level, then the only overhead is a single comparison ** (except for the first time this macro is invoked). */ # define sm_debug_active(debug, level) \ ((debug)->debug_level >= (level) && \ ((debug)->debug_level != SM_DEBUG_UNKNOWN || \ sm_debug_loadactive(debug, level))) # define sm_debug_level(debug) \ ((debug)->debug_level == SM_DEBUG_UNKNOWN \ ? sm_debug_loadlevel(debug) : (debug)->debug_level) # define sm_debug_unknown(debug) ((debug)->debug_level == SM_DEBUG_UNKNOWN) # else /* SM_DEBUG_CHECK */ # define sm_debug_active(debug, level) 0 # define sm_debug_level(debug) 0 # define sm_debug_unknown(debug) 0 # endif /* SM_DEBUG_CHECK */ extern bool sm_debug_loadactive __P((SM_DEBUG_T *, int)); extern int sm_debug_loadlevel __P((SM_DEBUG_T *)); # define SM_DEBUG_INITIALIZER(name, desc) { \ SmDebugMagic, \ SM_DEBUG_UNKNOWN, \ name, \ desc, \ NULL} #endif /* ! SM_DEBUG_H */ dk-milter-1.0.0.dfsg/include/sm/sendmail.h0000644000175000017500000000122410473107725020100 0ustar madhackmadhack/* * Copyright (c) 2006 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ /* ** SENDMAIL.H -- MTA-specific definitions for sendmail. */ #ifndef _SM_SENDMAIL_H # define _SM_SENDMAIL_H 1 /* "out of band" indicator */ #define METAQUOTE ((unsigned char)0377) /* quotes the next octet */ extern int dequote_internal_chars __P((char *, char *, int)); extern char *quote_internal_chars __P((char *, char *, int *)); extern char *str2prt __P((char *)); #endif /* ! _SM_SENDMAIL_H */ dk-milter-1.0.0.dfsg/include/sm/mbdb.h0000644000175000017500000000206707473523606017224 0ustar madhackmadhack/* * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: mbdb.h,v 1.6 2002/05/24 20:50:14 gshapiro Exp $ */ #ifndef SM_MBDB_H # define SM_MBDB_H #include #include #include /* ** This is an abstract interface for looking up local mail recipients. */ #define MBDB_MAXNAME 256 #define SM_NO_UID ((uid_t)(-1)) #define SM_NO_GID ((gid_t)(-1)) typedef struct { uid_t mbdb_uid; gid_t mbdb_gid; char mbdb_name[MBDB_MAXNAME]; char mbdb_fullname[MBDB_MAXNAME]; char mbdb_homedir[PATH_MAX]; char mbdb_shell[PATH_MAX]; } SM_MBDB_T; extern int sm_mbdb_initialize __P((char *)); extern void sm_mbdb_terminate __P((void)); extern int sm_mbdb_lookup __P((char *, SM_MBDB_T *)); extern void sm_mbdb_frompw __P((SM_MBDB_T *, struct passwd *)); extern void sm_pwfullname __P((char *, char *, char *, size_t)); #endif /* ! SM_MBDB_H */ dk-milter-1.0.0.dfsg/include/sm/test.h0000644000175000017500000000176407262226375017301 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: test.h,v 1.6 2001/04/03 01:53:01 gshapiro Exp $ */ /* ** Abstractions for writing a libsm test program. */ #ifndef SM_TEST_H # define SM_TEST_H # include # if defined(__STDC__) || defined(__cplusplus) # define SM_TEST(cond) sm_test(cond, #cond, __FILE__, __LINE__) # else /* defined(__STDC__) || defined(__cplusplus) */ # define SM_TEST(cond) sm_test(cond, "cond", __FILE__, __LINE__) # endif /* defined(__STDC__) || defined(__cplusplus) */ extern int SmTestIndex; extern int SmTestNumErrors; extern void sm_test_begin __P(( int _argc, char **_argv, char *_testname)); extern bool sm_test __P(( bool _success, char *_expr, char *_filename, int _lineno)); extern int sm_test_end __P((void)); #endif /* ! SM_TEST_H */ dk-milter-1.0.0.dfsg/include/sm/os/0000755000175000017500000000000010766324731016560 5ustar madhackmadhackdk-milter-1.0.0.dfsg/include/sm/os/sm_os_mpeix.h0000644000175000017500000000134007406243146021246 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_mpeix.h,v 1.2 2001/12/14 00:23:02 ca Exp $ */ /* ** sm_os_mpeix.h -- platform definitions for HP MPE/iX */ #define SM_OS_NAME "mpeix" #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ #ifndef SM_CONF_SEM # define SM_CONF_SEM 2 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ #define SM_CONF_SETITIMER 0 #ifndef SM_CONF_CANT_SETRGID # define SM_CONF_CANT_SETRGID 1 #endif /* SM_CONF_CANT_SETRGID */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_hp.h0000644000175000017500000000144707370015230020532 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_hp.h,v 1.8 2001/10/31 15:36:56 ca Exp $ */ /* ** sm_os_hp.h -- platform definitions for HP */ #define SM_OS_NAME "hp" #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ #ifndef SM_CONF_SEM # define SM_CONF_SEM 2 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ /* max/min buffer size of other than regular files */ #ifndef SM_IO_MAX_BUF # define SM_IO_MAX_BUF 8192 #endif /* SM_IO_MAX_BUF */ #ifndef SM_IO_MIN_BUF # define SM_IO_MIN_BUF 4096 #endif /* SM_IO_MIN_BUF */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_dragonfly.h0000644000175000017500000000142210104600337022076 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_dragonfly.h,v 1.1 2004/08/06 03:54:07 gshapiro Exp $ */ /* ** Platform definitions for DragonFly BSD */ #define SM_OS_NAME "dragonfly" #define SM_CONF_SYS_CDEFS_H 1 #define MI_SOMAXCONN -1 /* listen() max backlog for milter */ #ifndef SM_CONF_STRL # define SM_CONF_STRL 1 #endif /* SM_CONF_STRL */ #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ #ifndef SM_CONF_SEM # define SM_CONF_SEM 1 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_ultrix.h0000644000175000017500000000063507360702115021454 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_ultrix.h,v 1.3 2001/10/09 23:12:13 ca Exp $ */ /* ** platform definitions for Ultrix */ #define SM_OS_NAME "ultrix" #define SM_CONF_SSIZE_T 0 dk-milter-1.0.0.dfsg/include/sm/os/sm_os_sunos.h0000644000175000017500000000276507336264546021320 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_sunos.h,v 1.14 2001/08/14 18:09:42 ca Exp $ */ /* ** platform definitions for SunOS 4.0.3, SunOS 4.1.x and Solaris 2.x */ #define SM_OS_NAME "sunos" #ifdef SOLARIS /* ** Solaris 2.x (aka SunOS 5.x) ** M4 config file is devtools/OS/SunOS.5.x, which defines the SOLARIS macro. */ # define SM_CONF_LONGLONG 1 # ifndef SM_CONF_SHM # define SM_CONF_SHM 1 # endif /* SM_CONF_SHM */ # ifndef SM_CONF_SEM # define SM_CONF_SEM 2 # endif /* SM_CONF_SEM */ # ifndef SM_CONF_MSG # define SM_CONF_MSG 1 # endif /* SM_CONF_MSG */ #else /* SOLARIS */ /* ** SunOS 4.0.3 or 4.1.x */ # define SM_CONF_SSIZE_T 0 # ifndef SM_CONF_BROKEN_SIZE_T # define SM_CONF_BROKEN_SIZE_T 1 /* size_t is signed? */ # endif /* SM_CONF_BROKEN_SIZE_T */ # ifndef SM_CONF_BROKEN_STRTOD # define SM_CONF_BROKEN_STRTOD 1 # endif /* ! SM_CONF_BROKEN_STRTOD */ /* has memchr() prototype? (if not: needs memory.h) */ # ifndef SM_CONF_MEMCHR # define SM_CONF_MEMCHR 0 # endif /* ! SM_CONF_MEMCHR */ # ifdef SUNOS403 /* ** SunOS 4.0.3 ** M4 config file is devtools/OS/SunOS4.0, which defines the SUNOS403 macro. */ # else /* SUNOS403 */ /* ** SunOS 4.1.x ** M4 config file is devtools/OS/SunOS, which defines no macros. */ # endif /* SUNOS403 */ #endif /* SOLARIS */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_openbsd.h0000644000175000017500000000136407213235537021565 0ustar madhackmadhack/* * Copyright (c) 2000 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_openbsd.h,v 1.7 2000/12/05 19:00:47 dmoen Exp $ */ /* ** sm_os_openbsd.h -- platform definitions for OpenBSD ** ** Note: this header file cannot be called OpenBSD.h ** because defines the macro OpenBSD. */ #define SM_OS_NAME "openbsd" #define SM_CONF_SYS_CDEFS_H 1 #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ #ifndef SM_CONF_SEM # define SM_CONF_SEM 1 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_openunix.h0000644000175000017500000000115207373524000021764 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_openunix.h,v 1.5 2001/11/11 16:32:00 ca Exp $ */ #define SM_OS_NAME "openunix" /* needs alarm(), our sleep() otherwise hangs. */ #define SM_CONF_SETITIMER 0 /* long long seems to work */ #define SM_CONF_LONGLONG 1 /* don't use flock() in mail.local.c */ #define LDA_USE_LOCKF 1 #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_aix.h0000644000175000017500000000157107653336137020722 0ustar madhackmadhack/* * Copyright (c) 2000-2001, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_aix.h,v 1.11 2003/04/28 23:42:23 ca Exp $ */ /* ** sm_os_aix.h -- platform definitions for AIX */ #define SM_OS_NAME "aix" #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ #ifndef SM_CONF_SEM # define SM_CONF_SEM 2 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ /* AIX 3 doesn't have a prototype for syslog()? */ #ifdef _AIX3 # ifndef _AIX4 # ifndef SM_CONF_SYSLOG # define SM_CONF_SYSLOG 0 # endif /* SM_CONF_SYSLOG */ # endif /* ! _AIX4 */ #endif /* _AIX3 */ #if _AIX5 >= 50200 # define SM_CONF_LONGLONG 1 #endif /* _AIX5 >= 50200 */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_unicosmp.h0000644000175000017500000000076407651022167021772 0ustar madhackmadhack/* * Copyright (c) 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_unicosmp.h,v 1.1 2003/04/21 17:03:51 ca Exp $ */ /* ** Cray UNICOS/mp */ #define SM_OS_NAME "unicosmp" #define SM_CONF_LONGLONG 1 #define SM_CONF_SYS_CDEFS_H 1 #define SM_CONF_MSG 1 #define SM_CONF_SHM 1 #define SM_CONF_SEM 1 dk-milter-1.0.0.dfsg/include/sm/os/sm_os_osf1.h0000644000175000017500000000064107360702115020772 0ustar madhackmadhack/* * Copyright (c) 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_osf1.h,v 1.3 2001/10/09 23:12:13 ca Exp $ */ /* ** platform definitions for Digital UNIX */ #define SM_OS_NAME "osf1" #define SM_CONF_SETITIMER 0 dk-milter-1.0.0.dfsg/include/sm/os/sm_os_unicosmk.h0000644000175000017500000000062107651022167021755 0ustar madhackmadhack/* * Copyright (c) 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_unicosmk.h,v 1.1 2003/04/21 17:03:51 ca Exp $ */ /* ** Cray UNICOS/mk */ #define SM_OS_NAME "unicosmk" #define SM_CONF_LONGLONG 1 dk-milter-1.0.0.dfsg/include/sm/os/sm_os_unixware.h0000644000175000017500000000221407556033106021766 0ustar madhackmadhack/* * Copyright (c) 2001, 2002 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_unixware.h,v 1.8 2002/10/24 18:04:54 ca Exp $ */ #define SM_OS_NAME "unixware" #ifndef SM_CONF_LONGLONG # if defined(__SCO_VERSION__) && __SCO_VERSION__ > 400000000L # define SM_CONF_LONGLONG 1 # define SM_CONF_TEST_LLONG 1 # define SM_CONF_BROKEN_SIZE_T 0 # endif /* defined(__SCO_VERSION__) && __SCO_VERSION__ > 400000000L */ #endif /* !SM_CONF_LONGLONG */ /* try LLONG tests in libsm/t-types.c? */ #ifndef SM_CONF_TEST_LLONG # define SM_CONF_TEST_LLONG 0 #endif /* !SM_CONF_TEST_LLONG */ /* needs alarm(), our sleep() otherwise hangs. */ #define SM_CONF_SETITIMER 0 #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ /* size_t seems to be signed */ #ifndef SM_CONF_BROKEN_SIZE_T # define SM_CONF_BROKEN_SIZE_T 1 #endif /* SM_CONF_BROKEN_SIZE_T */ /* don't use flock() in mail.local.c */ #ifndef LDA_USE_LOCKF # define LDA_USE_LOCKF 1 #endif /* LDA_USE_LOCKF */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_linux.h0000644000175000017500000000204207357211151021257 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_linux.h,v 1.12 2001/10/05 01:52:41 ca Exp $ */ /* ** Platform definitions for Linux */ #define SM_OS_NAME "linux" /* to get version number */ #include # if !defined(KERNEL_VERSION) /* not defined in 2.0.x kernel series */ # define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) # endif /* ! KERNEL_VERSION */ /* doesn't seem to work on Linux */ #ifndef SM_CONF_SETITIMER # define SM_CONF_SETITIMER 0 #endif /* SM_CONF_SETITIMER */ #ifndef SM_CONF_SHM # if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,19)) # define SM_CONF_SHM 1 # endif /* LINUX_VERSION_CODE */ #endif /* SM_CONF_SHM */ #define SM_CONF_SYS_CDEFS_H 1 #ifndef SM_CONF_SEM # define SM_CONF_SEM 2 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_unicos.h0000644000175000017500000000064607651022167021434 0ustar madhackmadhack/* * Copyright (c) 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_unicos.h,v 1.1 2003/04/21 17:03:51 ca Exp $ */ /* ** Cray UNICOS */ #define SM_OS_NAME "unicos" #define SM_CONF_LONGLONG 1 #define SM_CONF_SETITIMER 0 dk-milter-1.0.0.dfsg/include/sm/os/sm_os_next.h0000644000175000017500000000130407262226402021076 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_next.h,v 1.7 2001/04/03 01:53:06 gshapiro Exp $ */ /* ** Platform definitions for NeXT */ #define SM_OS_NAME "next" #define SM_CONF_SIGSETJMP 0 #define SM_CONF_SSIZE_T 0 #define SM_CONF_FORMAT_TEST 0 /* doesn't seem to work on NeXT 3.x */ #define SM_DEAD(proto) proto #define SM_UNUSED(decl) decl /* try LLONG tests in libsm/t-types.c? */ #ifndef SM_CONF_TEST_LLONG # define SM_CONF_TEST_LLONG 0 #endif /* !SM_CONF_TEST_LLONG */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_irix.h0000644000175000017500000000321207360702115021072 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_irix.h,v 1.7 2001/10/09 23:12:13 ca Exp $ */ /* ** Silicon Graphics IRIX ** ** Compiles on 4.0.1. ** ** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0). ** Use IRIX5 instead of IRIX for IRIX 5.x. ** ** This version tries to be adaptive using _MIPS_SIM: ** _MIPS_SIM == _ABIO32 (= 1) Abi: -32 on IRIX 6.2 ** _MIPS_SIM == _ABIN32 (= 2) Abi: -n32 on IRIX 6.2 ** _MIPS_SIM == _ABI64 (= 3) Abi: -64 on IRIX 6.2 ** ** _MIPS_SIM is 1 also on IRIX 5.3 ** ** IRIX64 changes from Mark R. Levinson . ** IRIX5 changes from Kari E. Hurtta . ** Adaptive changes from Kari E. Hurtta . */ #ifndef IRIX # define IRIX #endif /* ! IRIX */ #if _MIPS_SIM > 0 && !defined(IRIX5) # define IRIX5 /* IRIX5 or IRIX6 */ #endif /* _MIPS_SIM > 0 && !defined(IRIX5) */ #if _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) # define IRIX6 /* IRIX6 */ #endif /* _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) */ #define SM_OS_NAME "irix" #if defined(IRIX6) || defined(IRIX64) # define SM_CONF_LONGLONG 1 #endif /* defined(IRIX6) || defined(IRIX64) */ #if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) # define SM_CONF_SYS_CDEFS_H 1 #endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ /* try LLONG tests in libsm/t-types.c? */ #ifndef SM_CONF_TEST_LLONG # define SM_CONF_TEST_LLONG 0 #endif /* !SM_CONF_TEST_LLONG */ dk-milter-1.0.0.dfsg/include/sm/os/sm_os_freebsd.h0000644000175000017500000000206007456605421021541 0ustar madhackmadhack/* * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * $Id: sm_os_freebsd.h,v 1.11 2002/04/15 17:17:05 gshapiro Exp $ */ /* ** Platform definitions for FreeBSD */ #define SM_OS_NAME "freebsd" #define SM_CONF_SYS_CDEFS_H 1 #if __FreeBSD__ >= 2 # include /* defines __FreeBSD_version */ # if __FreeBSD_version >= 199512 /* 2.2-current when it appeared */ # define MI_SOMAXCONN -1 /* listen() max backlog for milter */ # endif /* __FreeBSD_version >= 199512 */ # if __FreeBSD_version >= 330000 /* 3.3.0-release and later have strlcpy()/strlcat() */ # ifndef SM_CONF_STRL # define SM_CONF_STRL 1 # endif # endif #endif #ifndef SM_CONF_SHM # define SM_CONF_SHM 1 #endif /* SM_CONF_SHM */ #ifndef SM_CONF_SEM # define SM_CONF_SEM 1 #endif /* SM_CONF_SEM */ #ifndef SM_CONF_MSG # define SM_CONF_MSG 1 #endif /* SM_CONF_MSG */ dk-milter-1.0.0.dfsg/include/sm/bdb.h0000644000175000017500000000235407631673615017050 0ustar madhackmadhack/* * Copyright (c) 2002, 2003 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * * * $Id: bdb.h,v 1.4 2003/03/06 16:30:05 ca Exp $ */ #ifndef SM_BDB_H #define SM_BDB_H #if NEWDB # include # ifndef DB_VERSION_MAJOR # define DB_VERSION_MAJOR 1 # endif /* ! DB_VERSION_MAJOR */ # if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 # define DBTXN NULL , /* ** Always turn on DB_FCNTL_LOCKING for DB 4.1.x since its ** "workaround" for accepting an empty (locked) file depends on ** this flag. Notice: this requires 4.1.24 + patch (which should be ** part of 4.1.25). */ # define SM_DB_FLAG_ADD(flag) (flag) |= DB_FCNTL_LOCKING # else /* DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 */ # define DBTXN # if !HASFLOCK && defined(DB_FCNTL_LOCKING) # define SM_DB_FLAG_ADD(flag) (flag) |= DB_FCNTL_LOCKING # else /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ # define SM_DB_FLAG_ADD(flag) ((void) 0) # endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ # endif /* DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 */ #endif /* NEWDB */ #endif /* ! SM_BDB_H */ dk-milter-1.0.0.dfsg/libdk/0000755000175000017500000000000010766324725015165 5ustar madhackmadhackdk-milter-1.0.0.dfsg/libdk/Makefile.m40000644000175000017500000000166010764775026017151 0ustar madhackmadhackdnl Build description for libdk dnl dnl NO USER SERVICEABLE PARTS INSIDE dnl See the package README file for details. define(`confREQUIRE_LIBUNIX') include(confBUILDTOOLSDIR`/M4/switch.m4') define(`confREQUIRE_LIBSM', `true') bldPUSH_SMLIB(`sm') APPENDDEF(`confLIBS', `-lssl -lcrypto') ifdef(`bld_USE_ARLIB', ` bldPUSH_SMLIB(`ar') APPENDDEF(`confENVDEF', `-DUSE_ARLIB ') APPENDDEF(`confINCDIRS', `-I../libar/ ') ', `') define(`confMT', `true') bldPRODUCT_START(`library', `libdk') define(`bldSOURCES', `dk.c rfc2822.c util.c ') bldPRODUCT_END define(`confCHECK_LIBS', `libdk.a')dnl include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/check.m4') smcheck(`t-setup', `compile-run') smcheck(`t-test00', `compile-run') smcheck(`t-test01', `compile-run') smcheck(`t-test02', `compile-run') smcheck(`t-test03', `compile-run') smcheck(`t-test04', `compile-run') smcheck(`t-test05', `compile-run') smcheck(`t-cleanup', `compile-run') bldFINISH dk-milter-1.0.0.dfsg/libdk/t-setup.c0000644000175000017500000000200710764722646016733 0ustar madhackmadhack/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_setup_c_id[] = "@(#)$Id: t-setup.c,v 1.1 2008/03/09 08:53:58 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include /* libdkim includes */ #include "dk.h" #include "t-testdata.h" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { char *p; FILE *f; printf("*** test setup\n"); f = fopen(KEYFILE, "w"); assert(f != NULL); fprintf(f, "%s.%s.%s ", SELECTOR, DK_DNSNAME, DOMAIN); for (p = PUBLICKEY; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTOR2, DK_DNSNAME, DOMAIN); for (p = PUBLICKEY2; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s ", DK_DNSNAME, DOMAIN2); fprintf(f, "o=~; r=%s\n", REPLYADDRESS); fclose(f); return 0; } dk-milter-1.0.0.dfsg/libdk/t-test01.c0000644000175000017500000000640010764775266016722 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_test01_c_id[] = "@(#)$Id: t-test01.c,v 1.2 2008/03/09 14:56:54 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libdk includes */ #include "dk.h" #include "t-testdata.h" #define SIG "EtmLAYbPraB1+W58az0tQwQwPswCzpRu0/vYV8yXq3Czriqap8sBFl+uHSWqVXUFjVB9gog/DXIdbLaRFvw+Y8q1/sci4JRat6fn3ZatXBhmDqEFHEauggMb0Xv7V4WVZARXR3nF9Lvqas5pt/BExsazfTLDQPR9GU00seeT0xQ=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DK_STAT status; DK *dk; DK_LIB *lib; dk_sigkey_t *key; unsigned char sig[MAXHEADER + 1]; printf("*** simple rsa-sha1 signing\n"); /* instantiate the library */ lib = dk_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DK_LIBFLAGS_TMPFILES|DK_LIBFLAGS_KEEPFILES); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = (dk_sigkey_t *) KEY; dk = dk_sign(lib, JOBID, NULL, key, DK_CANON_SIMPLE, DK_SIGN_RSASHA1, &status); assert(dk != NULL); status = dk_header(dk, HEADER05, strlen(HEADER05)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER06, strlen(HEADER06)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER07, strlen(HEADER07)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER08, strlen(HEADER08)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER09, strlen(HEADER09)); assert(status == DK_STAT_OK); status = dk_eoh(dk); assert(status == DK_STAT_OK); status = dk_body(dk, BODY00, strlen(BODY00)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01, strlen(BODY01)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01A, strlen(BODY01A)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01B, strlen(BODY01B)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01C, strlen(BODY01C)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01D, strlen(BODY01D)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01E, strlen(BODY01E)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY02, strlen(BODY02)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY04, strlen(BODY04)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY05, strlen(BODY05)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_eom(dk, NULL); assert(status == DK_STAT_OK); memset(sig, '\0', sizeof sig); status = dk_getsig(dk, sig, sizeof sig); assert(status == DK_STAT_OK); assert(strcmp(SIG, sig) == 0); status = dk_free(dk); assert(status == DK_STAT_OK); dk_close(lib); return 0; } dk-milter-1.0.0.dfsg/libdk/dk.h0000644000175000017500000002467710764722077015754 0ustar madhackmadhack/* ** Copyright (c) 2004-2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: dk.h,v 1.54 2008/03/09 08:47:59 msk Exp $ */ #ifndef _SMI_DK_H_ #define _SMI_DK_H_ #ifndef lint static char dk_h_id[] = "@(#)$Id: dk.h,v 1.54 2008/03/09 08:47:59 msk Exp $"; #endif /* !lint */ /* system includes */ #include /* libsm includes */ #include /* ** version -- 0xrrMMmmpp ** ** rr == release number ** MM == major revision number ** mm == minor revision number ** pp == patch number */ #define DK_LIB_VERSION 0x01000000 #define DK_DNSNAME "_domainkey" /* common DNS label */ /* limits, macros, etc. */ #define MAXADDRESS 256 /* biggest user@host we accept */ #define MAXCNAMEDEPTH 3 /* max. CNAME recursion we allow */ #define MAXHDRCNT 64 /* max. headers signed */ #define MAXHEADER 1000 /* buffer for caching one header */ #define MAXHEADERS 32768 /* buffer for caching headers */ /* headers */ #define DK_SIGNHEADER "DomainKey-Signature" /* DomainKeys signature header */ /* ** DK_STAT -- status code type */ typedef int DK_STAT; #define DK_STAT_OK 0 /* function completed successfully */ #define DK_STAT_BADSIG 1 /* signature available but failed */ #define DK_STAT_NOSIG 2 /* no signature available */ #define DK_STAT_NOKEY 3 /* public key not found */ #define DK_STAT_CANTVRFY 4 /* can't get domain key to verify */ #define DK_STAT_SYNTAX 5 /* message is not valid syntax */ #define DK_STAT_NORESOURCE 6 /* resource unavailable */ #define DK_STAT_INTERNAL 7 /* internal error */ #define DK_STAT_REVOKED 8 /* key found, but revoked */ #define DK_STAT_INVALID 9 /* invalid argument */ /* ** DK_CANON -- canonicalization method */ typedef int dk_canon_t; #define DK_CANON_UNKNOWN -1 /* unknown method */ #define DK_CANON_SIMPLE 0 /* as specified in DomainKeys draft */ #define DK_CANON_NOFWS 1 /* as specified in DomainKeys draft */ #define DK_CANON_DEFAULT DK_CANON_SIMPLE /* ** DK_SIGN -- signing method */ typedef int dk_alg_t; #define DK_SIGN_UNKNOWN -1 /* unknown method */ #define DK_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */ #define DK_SIGN_DEFAULT DK_SIGN_RSASHA1 /* ** DK_QUERY -- query method */ typedef int dk_query_t; #define DK_QUERY_UNKNOWN -1 /* unknown method */ #define DK_QUERY_DNS 0 /* DNS query method (per the draft) */ #define DK_QUERY_FILE 1 /* text file method (for testing) */ #define DK_QUERY_DEFAULT DK_QUERY_DNS /* ** DK_PARAM -- known parameters */ #define DK_PARAM_SIGNATURE 0 #define DK_PARAM_SIGNALG 1 #define DK_PARAM_DOMAIN 2 #define DK_PARAM_CANONALG 3 #define DK_PARAM_QUERYMETHOD 4 #define DK_PARAM_SELECTOR 5 #define DK_PARAM_HDRLIST 6 /* ** DK_FLAGS -- flags */ typedef int DK_FLAGS; #define DK_FLAG_TESTING 0x01 #define DK_FLAG_SIGNSALL 0x02 #define DK_FLAG_HDRLIST 0x04 /* ** DK_OPTS -- options */ typedef int dk_opt_t; #define DK_OP_GETOPT 0 #define DK_OP_SETOPT 1 typedef int dk_opts_t; #define DK_OPTS_FLAGS 0 #define DK_OPTS_TMPDIR 1 #define DK_OPTS_QUERYMETHOD 2 #define DK_OPTS_QUERYINFO 3 #define DK_LIBFLAGS_NONE 0x00 #define DK_LIBFLAGS_TMPFILES 0x01 #define DK_LIBFLAGS_HDRLIST 0x02 #define DK_LIBFLAGS_KEEPFILES 0x04 #define DK_LIBFLAGS_DEFAULT DK_LIBFLAGS_NONE /* ** DK -- DomainKeys context */ struct dk; typedef struct dk DK; /* ** DK_SIG_T -- key data */ typedef unsigned char * dk_sigkey_t; /* ** DK_LIB -- library handle */ struct dk_lib; typedef struct dk_lib DK_LIB; /* ** PROTOTYPES */ /* ** DK_INIT -- initialize the DomainKeys package ** ** Parameters: ** None. ** ** Return value: ** A DK_STAT value. */ extern DK_LIB *dk_init __P((void *(*mallocf)(void *closure, size_t nbytes), void (*freef)(void *closure, void *p))); /* ** DK_CLOSE -- shut down the DK package ** ** Parameters: ** lib -- DK_LIB handle to shut down ** ** Return value: ** None. */ extern void dk_close __P((DK_LIB *lib)); /* ** DK_SIGN -- make a new DomainKeys context for signing ** ** Parameters: ** libhandle -- library handle, returned by dk_init() ** id -- an opaque printable string for identifying this message, suitable ** for use in logging or debug output; may not be NULL ** memclosure -- memory closure, for use by user-provided malloc/free ** secretkey -- pointer to secret key data to use; if NULL, it will be ** obtained from disk ** canon_alg -- canonicalization algorithm to use; one of the DK_CANON_* ** macros, or -1 for default ** sign_alg -- signing algorithm to use; one of the DK_SIGN_* macros, ** or -1 for default ** statp -- pointer to a DK_STAT which is updated by this call ** ** Return value: ** A newly-allocated DK handle, or NULL on failure. "statp" will be ** updated. */ extern DK *dk_sign __P((DK_LIB *libhandle, const char *id, void *memclosure, const dk_sigkey_t *secretkey, dk_canon_t canon_alg, dk_alg_t sign_alg, DK_STAT *statp)); /* ** DK_VERIFY -- make a new DomainKeys context for verifying ** ** Parameters: ** libhandle -- library handle, returned by dk_init() ** id -- an opaque printable string for identifying this message, suitable ** for use in logging or debug output; may not be NULL ** memclosure -- memory closure, for use by user-provided malloc/free ** statp -- pointer to a DK_STAT which is updated by this call ** ** Return value: ** A newly-allocated DK handle, or NULL on failure. "statp" will be ** updated. */ extern DK *dk_verify __P((DK_LIB *libhandle, const char *id, void *memclosure, DK_STAT *statp)); /* ** DK_HEADER -- process a header ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** hdr -- the header to be processed, in canonical format ** len -- number of bytes to process starting at "hdr" ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_header __P((DK *dk, u_char *hdr, size_t len)); /* ** DK_EOH -- identify end of headers ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** ** Return value: ** A DK_STAT value. DK_STAT_NOSIG will be returned if we're validating ** a signature but no DomainKeys signature was found in the headers. */ extern DK_STAT dk_eoh __P((DK *dk)); /* ** DK_BODY -- process a body chunk ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** buf -- the body chunk to be processed, in canonical format ** len -- number of bytes to process starting at "hdr" ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_body __P((DK *dk, u_char *buf, size_t len)); /* ** DK_EOM -- identify end of body ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** flags -- pointer to a DK_FLAGS that receives flag bits ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_eom __P((DK *dk, DK_FLAGS *flags)); /* ** DK_GETSIG -- compute and return a signature for a message ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** buf -- buffer into which to write the signature ** len -- number of bytes available at "sig" ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_getsig __P((DK *dk, u_char *buf, size_t len)); /* ** DK_GETHDRS -- report which headers were included in calculation of ** the signature ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** hcnt -- pointer to an int that will receive the header count ** buf -- buffer into which to write the signature ** len -- number of bytes available at "sig" ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_gethdrs __P((DK *dk, int *hcnt, u_char *buf, size_t buflen)); /* ** DK_REPORTINFO -- return info needed to generate failure report ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** fd -- pointer to receive temporary file descriptor ** raddr -- buffer to receive report address ** rlen -- bytes available at raddr ** ** Return vlalue: ** A DK_STAT value. */ extern DK_STAT dk_reportinfo __P((DK *dk, int *fd, char *raddr, size_t rlen)); /* ** DK_OPTIONS -- set/get options ** ** Parameters: ** dklib -- DK library handle ** op -- operation (DK_OPT_GET or DK_OPT_SET) ** opt -- which option (a DK_OPTS_* constant) ** ptr -- value (in or out) ** len -- bytes available at "ptr" ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_options __P((DK_LIB *dklib, int op, dk_opts_t opt, void *ptr, size_t len)); /* ** DK_GETIDENTITY -- retrieve signer's apparent identity ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** hname -- buffer to receive name of the header from which identity ** was extracted ** hnamelen -- number of bytes available at hname ** hval -- buffer to receive decommented value of the header from which ** identity was extracted ** hvallen -- number of bytes available at hval ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_getidentity __P((DK *dk, char *hname, size_t hnamelen, char *hval, size_t hvallen)); /* ** DK_TIMEOUT -- set/get the current DNS timeout ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** new -- new timeout, in seconds (or -1 for no change) ** old -- pointer to an int into which to write current timeout ** (or NULL if not needed) ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_timeout __P((DK *dk, int newt, int *oldt)); /* ** DK_FREE -- release resources associated with a DK handle ** ** Parameters: ** dk -- a DK handle previously returned by dk_new() ** ** Return value: ** A DK_STAT value. */ extern DK_STAT dk_free __P((DK *dk)); /* ** DK_GETERROR -- return any stored error string from within the DK ** context handle ** ** Parameters: ** dk -- DK handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ extern const char *dk_geterror __P((DK *dk)); /* ** RFC2822_MAILBOX_SPLIT -- extract the userid and host from a structured ** header ** ** Parameters: ** addr -- the header to parse; see RFC2822 for format ** user -- local-part of the parsed header (returned) ** domain -- domain part of the parsed header (returned) ** ** Return value: ** 0 on success; other on error (see source) */ extern int rfc2822_mailbox_split __P((char *addr, char **user, char **domain)); #endif /* ! _SMI_DK_H_ */ dk-milter-1.0.0.dfsg/libdk/dk.c0000644000175000017500000020744610765003262015731 0ustar madhackmadhack/* ** Copyright (c) 2004-2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: dk.c,v 1.186 2008/03/09 15:48:02 msk Exp $ */ #ifndef lint static char dk_c_id[] = "@(#)$Id: dk.c,v 1.186 2008/03/09 15:48:02 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* OpenSSL includes */ #include #include #include #include /* libdk includes */ #include #include #include /* libsm includes */ #include #include #include /* libar includes */ #if USE_ARLIB # include "ar.h" #endif /* USE_ARLIB */ /* libdk includes */ #include "rfc2822.h" /* useful stuff */ #ifndef NULL # define NULL 0 #endif /* ! NULL */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifndef MAXHOSTNAMELEN # define MAXHOSTNAMELEN 256 #endif /* ! MAXHOSTNAMELEN */ #ifndef __P # ifdef __STDC__ # define __P(x) x # else /* __STDC__ */ # define __P(x) () # endif /* __STDC__ */ #endif /* ! __P */ #define CRLF "\r\n" /* CRLF */ /* limits, macros, etc. */ #define BUFRSZ 1024 /* block I/O buffer size */ #define DEFERRLEN 128 /* default error buffer size */ #define DEFTIMEOUT 5 /* default DNS timeout */ #define MAXPARAMETER 256 /* biggest parameter we accept */ #ifdef _FFR_HASH_BUFFERING # define DK_HASHBUFSIZE 4096 /* hash buffer size */ #endif /* _FFR_HASH_BUFFERING */ /* defaults */ #define DK_DEFAULT_SELECTOR "main" /* default selector (filename only) */ #define DK_TMPDIR "/var/tmp" /* default dir. for temp files */ /* states */ #define DK_STATE_INIT 0 /* initialized */ #define DK_STATE_HEADER 1 /* receiving headers */ #define DK_STATE_EOH 2 /* at or past EOH */ #define DK_STATE_BODY 3 /* receiving body */ #define DK_STATE_EOM 4 /* at EOM */ /* files */ #define DK_PRIVATEKEY "/var/db/domainkeys/%s.key.pem" /* template filename for private keys */ /* prototypes */ static void dk_error(DK *dk, const char *format, ...); static void dk_canon __P((DK *, u_char *, size_t)); #ifdef _FFR_HASH_BUFFERING static void dk_canonbuffer __P((DK *, u_char *, size_t)); #endif /* _FFR_HASH_BUFFERING */ #ifdef _FFR_HASH_BUFFERING # define DK_CANON(x,y,z) dk_canonbuffer(x,y,z) #else /* _FFR_HASH_BUFFERING */ # define DK_CANON(x,y,z) dk_canon(x,y,z) #endif /* _FFR_HASH_BUFFERING */ /* parameter lookup table */ struct lookup { char *str; int code; }; struct lookup params[] = { { "a", DK_PARAM_SIGNALG }, { "b", DK_PARAM_SIGNATURE }, { "c", DK_PARAM_CANONALG }, { "d", DK_PARAM_DOMAIN }, { "h", DK_PARAM_HDRLIST }, { "q", DK_PARAM_QUERYMETHOD }, { "s", DK_PARAM_SELECTOR }, { NULL, -1 } }; /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ /* base64 alphabet */ static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* base64 decode stuff */ static int decoder[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; struct dk_lib { int dkl_flags; int dkl_querymethod; void * (*dkl_malloc) (void *closure, size_t nbytes); void (*dkl_free) (void *closure, void *p); #if USE_ARLIB AR_LIB dkl_arlib; #endif /* USE_ARLIB */ char dkl_tmpdir[MAXPATHLEN + 1]; u_char dkl_queryinfo[MAXPATHLEN + 1]; }; /* other stuff */ #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ #define DK_DEBUG(x) (getenv("DKDEBUG") != NULL && \ strchr(getenv("DKDEBUG"), (x)) != NULL) #define DK_DECODE_SIGNATURE 0 #define DK_DECODE_KEY 1 #define DK_CRLF_UNKNOWN (-1) #define DK_CRLF_CRLF 0 #define DK_CRLF_LF 1 #define DK_MODE_UNKNOWN (-1) #define DK_MODE_SIGN 0 #define DK_MODE_VERIFY 1 #define DK_FLAG_FREESIGNATURE 0001 /* ** ===== PRIVATE SECTION */ /* ** DK_MALLOC -- allocate some memory ** ** Parameters: ** libhandle -- DK_LIB handle ** closure -- closure to use ** nbytes -- how many bytes we want ** ** Return value: ** Pointer to new memory, or NULL if it failed. */ static void * dk_malloc(DK_LIB *libhandle, void *closure, size_t nbytes) { assert(libhandle != NULL); if (libhandle->dkl_malloc == NULL) return malloc(nbytes); else return libhandle->dkl_malloc(closure, nbytes); } /* ** DK_MFREE -- free some memory ** ** Parameters: ** libhandle -- DK_LIB handle ** closure -- closure to use ** p -- pointer referring to memory to release ** ** Return value: ** None. */ static void dk_mfree(DK_LIB *libhandle, void *closure, void *p) { assert(libhandle != NULL); if (libhandle->dkl_free == NULL) free(p); else libhandle->dkl_free(closure, p); } /* ** DK_STRDUP -- duplicate a string ** ** Parameters: ** libhandle -- DK_LIB handle ** closure -- closure to use ** str -- string to clone ** ** Return value: ** Pointer to copy of "str", or NULL on failure. */ static char * dk_strdup(DK_LIB *libhandle, void *closure, char *str) { char *newc; size_t len; assert(libhandle != NULL); assert(str != NULL); len = strlen(str) + 1; newc = dk_malloc(libhandle, closure, len); if (newc != NULL) sm_strlcpy(newc, str, len); return newc; } /* ** DK_ISFWS -- return TRUE iff the specified character is folding whitespace ** ** Parameters: ** c -- character ** ** Return value: ** TRUE iff the specified character is folding whitespace. */ static bool dk_isfws(int c) { return (c == 0x09 || c == 0x0a || c == 0x0d || c == 0x20); } /* ** DK_DECODE -- decode a base64-encoded key or signature ** ** Parameters: ** dk -- DK handle ** what -- what to decode (DK_DECODE_KEY or DK_DECODE_SIGNATURE) ** ** Return value: ** TRUE on success, FALSE otherwise (malloc() failure). */ static bool dk_decode(DK *dk, int what) { int n; int bits = 0; int char_count = 0; size_t keyidx; unsigned char *c; unsigned char *x; assert(dk != NULL); assert(what == DK_DECODE_KEY || what == DK_DECODE_SIGNATURE); if (what == DK_DECODE_KEY) { dk->dk_key = dk_malloc(dk->dk_libhandle, dk->dk_closure, dk->dk_b64len); if (dk->dk_key == NULL) { dk_error(dk, "unable to allocate %d byte(s)", dk->dk_b64len); return FALSE; } memset(dk->dk_key, '\0', dk->dk_b64len); x = dk->dk_key; } else { dk->dk_signature = dk_malloc(dk->dk_libhandle, dk->dk_closure, dk->dk_b64len); if (dk->dk_signature == NULL) { dk_error(dk, "unable to allocate %d byte(s)", dk->dk_b64len); return FALSE; } memset(dk->dk_signature, '\0', dk->dk_b64len); x = dk->dk_signature; dk->dk_flags |= DK_FLAG_FREESIGNATURE; } keyidx = 0; for (c = dk->dk_b64, n = 0; n < dk->dk_b64len; c++, n++) { /* end padding */ if (*c == '=') break; /* skip stuff not part of the base64 alphabet (RFC2045) */ if (!((*c >= 'A' && *c <= 'Z') || (*c >= 'a' && *c <= 'z') || (*c >= '0' && *c <= '9') || (*c == '+') || (*c == '/'))) continue; /* everything else gets decoded */ bits += decoder[(int) *c]; char_count++; if (char_count == 4) { x[keyidx++] = (bits >> 16); x[keyidx++] = ((bits >> 8) & 0xff); x[keyidx++] = (bits & 0xff); bits = 0; char_count = 0; } else { bits <<= 6; } } /* XXX -- don't bother checking for proper termination (for now) */ /* process trailing data, if any */ switch (char_count) { case 0: break; case 1: /* base64 decoding incomplete; at least two bits missing */ break; case 2: x[keyidx++] = (bits >> 10); break; case 3: x[keyidx++] = (bits >> 16); x[keyidx++] = ((bits >> 8) & 0xff); break; } /* store the length of what was decoded */ if (what == DK_DECODE_KEY) { dk->dk_keylen = keyidx; } else { dk->dk_signlen = keyidx; } return TRUE; } /* ** DK_IN_USE -- see if a domain seems to be using DomainKeys ** ** Parameters: ** dk -- DK handle ** ** Return value: ** -1 -- error ** 0 -- domain does not appear to use DomainKeys ** 1 -- domain appears to use DomainKeys */ static int dk_in_use(DK *dk) { int qdcount; int ancount; int status; int n; int c; int type = -1; int class = -1; int state; #if USE_ARLIB int error; #endif /* USE_ARLIB */ size_t plen = 0; size_t anslen; #if USE_ARLIB AR_QUERY q; #endif /* USE_ARLIB */ char *ssel; unsigned char *p; unsigned char *cp; unsigned char *eom; unsigned char ansbuf[MAXPACKET]; unsigned char buf[BUFRSZ + 1]; char qname[MAXHOSTNAMELEN + 1]; char tag[MAXPARAMETER + 1]; char value[MAXPARAMETER + 1]; #if USE_ARLIB struct timeval timeout; #endif /* USE_ARLIB */ HEADER hdr; assert(dk != NULL); ssel = dk_sterilize(dk->dk_domain); if (ssel == NULL) return -1; /* send the NS query */ memset(qname, '\0', sizeof qname); snprintf(qname, sizeof qname - 1, "%s.%s", DK_DNSNAME, dk_sterilize(dk->dk_domain)); #if USE_ARLIB timeout.tv_sec = dk->dk_timeout; timeout.tv_usec = 0; if (DK_DEBUG('r')) { syslog(LOG_INFO, "thread %p ar_addquery(`%s')", pthread_self(), qname); } q = ar_addquery(dk->dk_libhandle->dkl_arlib, qname, C_IN, T_TXT, MAXCNAMEDEPTH, ansbuf, sizeof ansbuf, &error, dk->dk_timeout == 0 ? NULL : &timeout); if (DK_DEBUG('r')) { syslog(LOG_INFO, "thread %p ar_addquery(`%s') done", pthread_self(), qname); } if (q == NULL) return -1; status = ar_waitreply(dk->dk_libhandle->dkl_arlib, q, NULL, NULL); (void) ar_cancelquery(dk->dk_libhandle->dkl_arlib, q); if (DK_DEBUG('r')) { syslog(LOG_INFO, "thread %p ar_cancelquery(`%s')", pthread_self(), qname); } #else /* USE_ARLIB */ status = res_query(qname, C_IN, T_TXT, ansbuf, sizeof ansbuf); #endif /* USE_ARLIB */ #if USE_ARLIB if (status == AR_STAT_ERROR || status == AR_STAT_EXPIRED) { if (DK_DEBUG('d') && dk->dk_id != NULL) { syslog(LOG_NOTICE, "%s: ar_waitreply(): %s", dk->dk_id, ar_strerror(error)); } return -1; } #else /* USE_ARLIB */ /* ** A -1 return from res_query could mean a bunch of things, ** not just NXDOMAIN. You can use h_errno to determine what ** -1 means. This is poorly documented. */ if (status == -1) { switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: return 0; case TRY_AGAIN: case NO_RECOVERY: default: return -1; } } #endif /* USE_ARLIB */ /* set up pointers */ anslen = sizeof ansbuf; memcpy(&hdr, ansbuf, sizeof hdr); cp = (u_char *) &ansbuf + HFIXEDSZ; eom = (u_char *) &ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) &ansbuf, eom, cp, qname, sizeof qname); if ((n = dn_skipname(cp, eom)) < 0) return DK_STAT_INTERNAL; cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return -1; GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_TXT || class != C_IN) return -1; /* if NXDOMAIN, return DK_STAT_CANTVRFY */ if (hdr.rcode == NXDOMAIN) return 0; /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) return 0; /* if truncated, we can't do it */ if (hdr.tc) return -1; /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) &ansbuf, eom, cp, (RES_UNC_T) qname, sizeof qname)) < 0) return DK_STAT_INTERNAL; /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return -1; GETSHORT(type, cp); GETSHORT(class, cp); /* reject anything that's not valid (stupid wildcards) */ if (type != T_TXT || class != C_IN) return -1; /* skip the TTL */ cp += INT32SZ; /* get payload length */ if (cp + INT16SZ > eom) return -1; GETSHORT(n, cp); /* XXX -- maybe deal with a partial reply rather than require it all */ if (cp + n > eom) return -1; /* extract the payload */ memset(buf, '\0', sizeof buf); p = buf; while (n > 0) { c = *cp++; n--; while (c > 0) { *p++ = *cp++; c--; n--; } } state = 0; for (p = buf; ; p++) { if (*p == '\0') { switch (state) { case 0: case 4: return 1; case 1: case 2: /* malformed */ return -1; case 3: state = 4; break; } } switch (state) { case 0: /* before tag */ if (isascii(*p) && isspace(*p)) continue; memset(tag, '\0', sizeof tag); plen = 0; state = 1; /* FALLTHROUGH */ case 1: /* in tag */ if (*p == '=') { state = 2; continue; } else if (isascii(*p) && isspace(*p)) { continue; } else if (plen < sizeof tag) { tag[plen++] = *p; continue; } /* FALLTHROUGH */ case 2: /* before value */ if (isascii(*p) && isspace(*p)) continue; memset(value, '\0', sizeof value); plen = 0; state = 3; /* FALLTHROUGH */ case 3: /* in value */ if (*p == ';') { state = 4; /* FALLTHROUGH */ } else if (isascii(*p) && isspace(*p)) { continue; } else if (plen < sizeof tag) { value[plen++] = *p; continue; } else { continue; } /* FALLTHROUGH */ case 4: /* after value */ if (strcasecmp(tag, "t") == 0) { if (value[0] == 'y') dk->dk_testing = TRUE; } else if (strcasecmp(tag, "o") == 0) { if (value[0] == '-') dk->dk_signall = TRUE; } else if (strcasecmp(tag, "n") == 0) { /* XXX -- other info? or something */ /* XXX -- yahoo-inc.com uses it, so tolerate */ /* XXX -- (i.e. ignore) it for now */ } else if (strcasecmp(tag, "r") == 0) { sm_strlcpy(dk->dk_reportaddr, value, sizeof dk->dk_reportaddr); } else { return -1; } state = 0; break; } if (*p == '\0') break; } return 1; } /* ** DK_GET_KEY_FILE -- retrieve a DK key from a text file (for testing) ** ** Parameters: ** dk -- DK handle ** selector -- selector to retrieve ** domain -- domain from which to retrieve ** buf -- buffer into which to write the result ** buflen -- bytes available at "buf" ** ** Return value: ** A DK_STAT_* constant. ** ** Notes: ** The file opened is defined by the library option DK_OPTS_QUERYINFO ** and must be set prior to use of this function. Failing to do ** so will cause this function to return DK_STAT_CANTVRFY every time. ** The file should contain lines of the form: ** ** ._domainkey. key-data ** ** Case matching on the left is case-sensitive, but libdkim already ** wraps the domain name to lowercase. */ static DK_STAT dk_get_key_file(DK *dk, char *selector, char *domain, u_char *buf, size_t buflen) { FILE *f; u_char *p; u_char *p2; char *path; char name[BUFRSZ + 1]; assert(dk != NULL); path = dk->dk_libhandle->dkl_queryinfo; if (path[0] == '\0') { dk_error(dk, "query file not defined"); return DK_STAT_CANTVRFY; } f = fopen(path, "r"); if (f == NULL) { dk_error(dk, "%s: fopen(): %s", path, strerror(errno)); return DK_STAT_CANTVRFY; } snprintf(name, sizeof name, "%s.%s.%s", selector, DK_DNSNAME, domain); memset(buf, '\0', sizeof buf); while (fgets(buf, BUFRSZ, f) != NULL) { p2 = NULL; for (p = buf; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; break; } else if (isascii(*p) && isspace(*p)) { *p = '\0'; p2 = p + 1; } else if (p2 != NULL) { break; } } if (strcasecmp(name, buf) == 0) { sm_strlcpy(buf, p2, buflen); fclose(f); return DK_STAT_OK; } } fclose(f); return DK_STAT_NOKEY; } /* ** DK_GET_KEY_DNS -- acquire from DNS the key that will be used to either ** generate or verify a signature ** ** Parameters: ** dk -- DK handle ** selector -- selector to retrieve ** domain -- domain from which to retrieve ** buf -- buffer into which to write the result ** buflen -- bytes available at "buf" ** ** Return value: ** A DK_STAT. */ static DK_STAT dk_get_key_dns(DK *dk, char *selector, char *domain, u_char *buf, size_t buflen) { bool key = FALSE; int status; int state; int qdcount; int ancount; #if USE_ARLIB int error; #endif /* USE_ARLIB */ int n = 0; int l; int type = -1; int class = -1; size_t anslen; #if USE_ARLIB AR_QUERY q; #endif /* USE_ARLIB */ unsigned char *p; unsigned char *r; unsigned char *cp; unsigned char *eob; unsigned char *eom; char qname[MAXHOSTNAMELEN + 1]; unsigned char ansbuf[MAXPACKET]; #if USE_ARLIB struct timeval timeout; #endif /* USE_ARLIB */ HEADER hdr; assert(dk != NULL); snprintf(qname, sizeof qname - 1, "%s.%s.%s", dk->dk_selector, DK_DNSNAME, dk->dk_domain); #if USE_ARLIB timeout.tv_sec = dk->dk_timeout; timeout.tv_usec = 0; if (DK_DEBUG('r')) { syslog(LOG_INFO, "thread %p ar_addquery(`%s')", pthread_self(), qname); } q = ar_addquery(dk->dk_libhandle->dkl_arlib, qname, C_IN, T_TXT, MAXCNAMEDEPTH, ansbuf, sizeof ansbuf, &error, dk->dk_timeout == 0 ? NULL : &timeout); if (q == NULL) return DK_STAT_INTERNAL; status = ar_waitreply(dk->dk_libhandle->dkl_arlib, q, NULL, NULL); (void) ar_cancelquery(dk->dk_libhandle->dkl_arlib, q); if (DK_DEBUG('r')) { syslog(LOG_INFO, "thread %p ar_cancelquery(`%s')", pthread_self(), qname); } #else /* USE_ARLIB */ status = res_query(qname, C_IN, T_TXT, ansbuf, sizeof ansbuf); #endif /* USE_ARLIB */ #if USE_ARLIB if (status == AR_STAT_ERROR || status == AR_STAT_EXPIRED) { if (DK_DEBUG('d') && dk->dk_id != NULL) { syslog(LOG_NOTICE, "%s: ar_waitreply(): %s", dk->dk_id, ar_strerror(error)); } dk_error(dk, "DNS error or timeout for `%s'", qname); return DK_STAT_CANTVRFY; } #else /* USE_ARLIB */ /* ** A -1 return from res_query could mean a bunch of things, ** not just NXDOMAIN. You can use h_errno to determine what ** -1 means. This is poorly documented. */ if (status == -1) { switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: dk_error(dk, "`%s' not found", qname); return DK_STAT_NOKEY; case TRY_AGAIN: case NO_RECOVERY: default: dk_error(dk, "DNS error or timeout for `%s'", qname); return DK_STAT_CANTVRFY; } } #endif /* USE_ARLIB */ /* set up pointers */ anslen = sizeof ansbuf; memcpy(&hdr, ansbuf, sizeof hdr); cp = (u_char *) &ansbuf + HFIXEDSZ; eom = (u_char *) &ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) &ansbuf, eom, cp, qname, sizeof qname); if ((n = dn_skipname(cp, eom)) < 0) { dk_error(dk, "key record corrupted"); return DK_STAT_INTERNAL; } cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return DK_STAT_INTERNAL; GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_TXT || class != C_IN) { dk_error(dk, "unexpected key reply"); return DK_STAT_INTERNAL; } /* if NXDOMAIN, return DK_STAT_NOKEY */ if (hdr.rcode == NXDOMAIN) { dk_error(dk, "`%s' not found", qname); return DK_STAT_NOKEY; } /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) { dk_error(dk, "DNS error or timeout for `%s'", qname); return DK_STAT_CANTVRFY; } /* if truncated, we can't do it */ if (hdr.tc) { dk_error(dk, "DNS reply for `%s' truncated", qname); return DK_STAT_INTERNAL; } /* ** Extract the data from the first answer. */ /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) &ansbuf, eom, cp, (RES_UNC_T) qname, sizeof qname)) < 0) { dk_error(dk, "key record corrupted"); return DK_STAT_INTERNAL; } /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { dk_error(dk, "key record corrupted"); return DK_STAT_INTERNAL; } GETSHORT(type, cp); GETSHORT(class, cp); /* skip the TTL */ cp += INT32SZ; /* get payload length */ if (cp + INT16SZ > eom) { dk_error(dk, "key record corrupted"); return DK_STAT_INTERNAL; } GETSHORT(n, cp); /* XXX -- maybe deal with a partial reply rather than require it all */ if (cp + n > eom) { dk_error(dk, "key record corrupted"); return DK_STAT_INTERNAL; } /* decode the TXT record */ eob = buf + buflen - 1; memset(buf, '\0', buflen); for (p = cp, l = 0, r = buf; p <= eom && n >= 0 && r <= eob; p++, n--, l--) { /* if appropriate, consume a length byte */ if (p < eom && n > 0 && l == 0) { l = *p + 1; } else { *r = *p; r++; } } return DK_STAT_OK; } /* ** DK_GET_KEY -- acquire the key that will be used to either ** generate or verify a signature ** ** Parameters: ** dk -- DK handle ** ** Return value: ** A DK_STAT. */ static DK_STAT dk_get_key(DK *dk) { bool key = FALSE; DK_STAT status; int state; size_t keyidx; int plen = 0; char *ssel; unsigned char *p; unsigned char *eom; unsigned char buf[BUFRSZ + 1]; char tag[MAXPARAMETER + 1]; char qname[MAXHOSTNAMELEN + 1]; char value[MAXPARAMETER + 1]; assert(dk != NULL); if (dk->dk_mode != DK_MODE_VERIFY) { FILE *f; size_t n; struct stat s; char fn[MAXPATHLEN + 1]; /* already got one? */ if (dk->dk_key != NULL) return DK_STAT_OK; ssel = dk_sterilize(dk->dk_selector); if (ssel == NULL) { dk_error(dk, "unsafe selector data"); return DK_STAT_SYNTAX; } memset(fn, '\0', sizeof fn); snprintf(fn, sizeof fn - 1, DK_PRIVATEKEY, dk->dk_selector == NULL ? DK_DEFAULT_SELECTOR : ssel); f = fopen(fn, "r"); if (f == NULL) { dk_error(dk, "%s: fopen(): %s", fn, strerror(errno)); return DK_STAT_INTERNAL; } if (fstat(fileno(f), &s) != 0) { dk_error(dk, "%s: fstat(): %s", fn, strerror(errno)); return DK_STAT_INTERNAL; } dk->dk_key = dk_malloc(dk->dk_libhandle, dk->dk_closure, (size_t) s.st_size); if (dk->dk_key == NULL) { dk_error(dk, "unable to allocate %d byte(s)", s.st_size); return DK_STAT_NORESOURCE; } dk->dk_keylen = s.st_size; n = fread(dk->dk_key, (unsigned int) s.st_size, 1, f); if (n != 1) { fclose(f); dk_error(dk, "%s: fread(): %s", fn, strerror(errno)); return DK_STAT_INTERNAL; } fclose(f); return DK_STAT_OK; } switch (dk->dk_querymethod) { case DK_QUERY_DNS: status = dk_get_key_dns(dk, dk->dk_selector, dk->dk_domain, buf, sizeof buf); if (status != DK_STAT_OK) return status; break; case DK_QUERY_FILE: status = dk_get_key_file(dk, dk->dk_selector, dk->dk_domain, buf, sizeof buf); if (status != DK_STAT_OK) return status; break; default: assert(0); } snprintf(qname, sizeof qname - 1, "%s.%s.%s", dk->dk_selector, DK_DNSNAME, dk->dk_domain); /* decode the tags, allocate memory, and copy */ eom = buf + strlen(buf); state = 0; keyidx = 0; for (p = buf; p <= eom; p++) { switch (state) { case 0: /* before tag */ if (isascii(*p) && isspace(*p)) continue; memset(tag, '\0', sizeof tag); plen = 0; state = 1; /* FALLTHROUGH */ case 1: /* in tag */ if (*p == '=') { state = 2; continue; } else if (isascii(*p) && isspace(*p)) { continue; } else if (plen < sizeof tag) { tag[plen++] = *p; continue; } /* FALLTHROUGH */ case 2: /* before value */ if (isascii(*p) && isspace(*p)) continue; memset(value, '\0', sizeof value); plen = 0; state = 3; key = (strcasecmp(tag, "p") == 0); if (dk->dk_b64 == NULL && key) { dk->dk_b64len = strlen(p + 1); dk->dk_b64 = dk_malloc(dk->dk_libhandle, dk->dk_closure, dk->dk_b64len); if (dk->dk_b64 == NULL) { dk_error(dk, "unable to allocate %d byte(s)", dk->dk_b64len); return DK_STAT_NORESOURCE; } } /* FALLTHROUGH */ case 3: /* in value */ if (*p == ';' || *p == '\0') { state = 4; /* FALLTHROUGH */ } else if (isascii(*p) && isspace(*p)) { continue; } else if (key && keyidx < dk->dk_b64len) { dk->dk_b64[keyidx] = *p; keyidx++; continue; } else if (!key && plen < sizeof value) { value[plen++] = *p; continue; } else { continue; } /* FALLTHROUGH */ case 4: /* after value */ if (strcasecmp(tag, "g") == 0) { dk->dk_gran = dk_strdup(dk->dk_libhandle, dk->dk_closure, value); } else if (strcasecmp(tag, "k") == 0) { /* key type */ if (strcasecmp(value, "rsa") != 0) { dk_error(dk, "unknown key type `%s' at `%s'", value, qname); return DK_STAT_CANTVRFY; } } else if (strcasecmp(tag, "t") == 0) { if (value[0] == 'y') dk->dk_testing = TRUE; } else if (strcasecmp(tag, "p") == 0) { /* signature; handled earlier */ dk->dk_b64len = keyidx; /* empty == revoked */ if (dk->dk_b64[0] == '\0') { dk->dk_revoked = TRUE; } else if (!dk_decode(dk, DK_DECODE_KEY)) { dk_error(dk, "can't decode key at `%s'", qname); return DK_STAT_CANTVRFY; } } else if (strcasecmp(tag, "n") == 0) { /* XXX -- comment */ } else { /* XXX -- unknown; ignore */ } state = 0; break; } } /* XXX -- verify valid and required values here instead of dk_eoh()? */ return DK_STAT_OK; } /* ** DK_PARAM_LOOKUP -- lookup the parameter's code ** ** Parameters: ** str -- string to evaluate ** ** Return value: ** Mnemonic code, or -1 on error. */ static int dk_param_lookup(str) char *str; { int c; assert(str != NULL); for (c = 0; params[c].str != NULL; c++) { if (strcasecmp(str, params[c].str) == 0) return params[c].code; } return -1; } /* ** DK_PROCESS_VALUE -- process the value that was found ** ** Parameters: ** dk -- DomainKeys handle ** pcode -- parameter whose value is being provided ** value -- the value ** ** Return value: ** 1 -- valid ** 0 -- invalid ** -1 -- error (malloc() failure in dk_decode()) */ static int dk_process_value(DK *dk, int pcode, char *value) { char *p; char *ctx; assert(dk != NULL); assert(value != NULL); switch (pcode) { case DK_PARAM_SIGNALG: if (value[0] == '\0') { dk->dk_signalg = DK_SIGN_DEFAULT; return 1; } else if (strcasecmp(value, "rsa-sha1") == 0) { dk->dk_signalg = DK_SIGN_RSASHA1; return 1; } return 0; case DK_PARAM_CANONALG: if (value[0] == '\0') { dk->dk_canonalg = DK_CANON_DEFAULT; return 1; } else if (strcasecmp(value, "simple") == 0) { dk->dk_canonalg = DK_CANON_SIMPLE; return 1; } else if (strcasecmp(value, "nofws") == 0) { dk->dk_canonalg = DK_CANON_NOFWS; return 1; } return 0; case DK_PARAM_QUERYMETHOD: if (value[0] == '\0') { /* we'll be generous and allow a default here */ dk->dk_querymethod = DK_QUERY_DEFAULT; return 1; } else if (strcasecmp(value, "dns") == 0) { dk->dk_querymethod = DK_QUERY_DNS; return 1; } return 0; case DK_PARAM_DOMAIN: if (strlen(value) > 0) { dk->dk_domain = dk_strdup(dk->dk_libhandle, dk->dk_closure, value); return 1; } else { /* domain has no default */ return 0; } case DK_PARAM_SELECTOR: if (strlen(value) > 0) { dk->dk_selector = dk_strdup(dk->dk_libhandle, dk->dk_closure, value); return 1; } else { /* selector has no default */ return 0; } case DK_PARAM_SIGNATURE: /* base64-decode the signature into dk_signature */ dk->dk_b64len = strlen(dk->dk_b64); if (!dk_decode(dk, DK_DECODE_SIGNATURE)) return -1; dk_mfree(dk->dk_libhandle, dk->dk_closure, dk->dk_b64); dk->dk_b64 = NULL; return 1; case DK_PARAM_HDRLIST: dk->dk_shdrlist = strdup(value); if (dk->dk_shdrlist == NULL) return -1; for (p = strtok_r(dk->dk_shdrlist, ":", &ctx); p != NULL && dk->dk_hdrlidx < MAXHDRCNT; p = strtok_r(NULL, ":", &ctx)) { while (isascii(*p) && isspace(*p)) p++; dk->dk_hdrlist[dk->dk_hdrlidx] = p; dk->dk_hdrlidx++; } return 1; default: return 0; } } /* ** DK_PROCESS_DKHEADER -- process a DomainKeys: header ** ** Parameters: ** dk -- DomainKeys handle ** hdr -- header contents ** ** Return value: ** -1 -- system error; check errno ** 0 -- success ** 1 -- parse error */ static int dk_process_dkheader(DK *dk, const char *hdr) { bool comment = FALSE; bool escaped = FALSE; bool quoting = FALSE; int state = 0; int status; int plen = 0; int pcode = 0; size_t hlen; const char *p; char param[MAXPARAMETER + 1]; char value[MAXPARAMETER + 1]; assert(dk != NULL); assert(hdr != NULL); hlen = strlen(hdr); for (p = hdr; *p != '\0'; p++) { if (!escaped) { if (*p == '\\') { escaped = TRUE; continue; } if (*p == '(') { comment = TRUE; continue; } else if (*p == ')') { comment = FALSE; continue; } if (*p == '"') quoting = !quoting; } if (comment) continue; if (escaped) escaped = FALSE; switch (state) { case 0: /* before parameter */ if (isascii(*p) && isspace(*p)) continue; state = 1; memset(param, '\0', sizeof param); plen = 0; /* FALLTHROUGH */ case 1: /* in parameter */ if (*p == '=') { state = 3; continue; } else if (!quoting && isascii(*p) && isspace(*p)) { state = 2; } else if (plen < MAXPARAMETER) { param[plen] = *p; plen++; continue; } /* FALLTHROUGH */ case 2: /* after parameter */ if (isascii(*p) && isspace(*p)) continue; else if (*p == '=') state = 3; else return 1; break; case 3: /* before value */ pcode = dk_param_lookup(param); if (pcode == -1) return 1; if (isascii(*p) && isspace(*p)) continue; state = 4; memset(value, '\0', sizeof value); plen = 0; if (pcode == DK_PARAM_SIGNATURE) { dk->dk_b64 = dk_malloc(dk->dk_libhandle, dk->dk_closure, hlen); if (dk->dk_b64 == NULL) return -1; memset(dk->dk_b64, '\0', hlen); } /* FALLTHROUGH */ case 4: /* in value */ if (!quoting && !escaped && *p == ';') { status = dk_process_value(dk, pcode, value); if (status == 0) return 1; else if (status == -1) return -1; if (*p == ';') state = 0; else state = 5; continue; } switch (pcode) { case DK_PARAM_SIGNALG: case DK_PARAM_DOMAIN: case DK_PARAM_CANONALG: case DK_PARAM_QUERYMETHOD: case DK_PARAM_SELECTOR: case DK_PARAM_HDRLIST: if (plen < MAXPARAMETER && (quoting || escaped || !(isascii(*p) && isspace(*p)))) { value[plen] = *p; plen++; } break; case DK_PARAM_SIGNATURE: dk->dk_b64[plen] = *p; plen++; break; default: return 1; } break; case 5: /* after value */ if (isascii(*p) && isspace(*p)) continue; switch (pcode) { case DK_PARAM_SIGNATURE: dk->dk_b64len = plen; break; default: break; } status = dk_process_value(dk, pcode, value); if (status == 0) return 1; else if (status == -1) return -1; if (*p == ';') state = 0; else return 1; break; default: /* shouldn't happen */ assert(0); } } if (state == 4) { status = dk_process_value(dk, pcode, value); if (status == 0) return 1; else if (status == -1) return -1; } /* XXX -- verify valid and required values here instead of dk_eoh()? */ return 0; } /* ** DK_HDRSIGNED -- see if this header is in the list of signed headers ** ** Parameters: ** dk -- DomainKeys handle ** hdr -- header being considered ** mark -- mark this header ("found") ** ** Return value: ** TRUE iff the header under evaluation was included in the signature */ static bool dk_hdrsigned(DK *dk, u_char *hdr, bool mark) { unsigned int c; unsigned char *colon; assert(dk != NULL); assert(hdr != NULL); colon = strchr(hdr, ':'); assert(colon != NULL); /* if verifying and no header list given, all headers were signed */ if (dk->dk_mode == DK_MODE_VERIFY && dk->dk_hdrlidx == 0) return TRUE; for (c = 0; c < dk->dk_hdrlidx; c++) { if (strncasecmp(dk->dk_hdrlist[c], hdr, colon - hdr) == 0 && strlen(dk->dk_hdrlist[c]) == colon - hdr) { if (mark) dk->dk_hdrmark[c] = TRUE; return TRUE; } } return FALSE; } /* ** DK_NEW -- allocate a new DomainKeys handle */ static DK * dk_new(DK_LIB *libhandle, const char *id, void *memclosure, dk_canon_t canon_alg, dk_alg_t sign_alg, DK_STAT *statp) { DK *newdk; /* allocate the handle */ newdk = dk_malloc(libhandle, memclosure, sizeof(struct dk)); if (newdk == NULL) { *statp = DK_STAT_NORESOURCE; return NULL; } /* populate defaults */ memset(newdk, '\0', sizeof(struct dk)); newdk->dk_id = id; newdk->dk_signalg = (sign_alg == -1 ? DK_SIGN_DEFAULT : sign_alg); newdk->dk_canonalg = (canon_alg == -1 ? DK_CANON_DEFAULT : canon_alg); newdk->dk_querymethod = DK_QUERY_UNKNOWN; newdk->dk_crlf = DK_CRLF_UNKNOWN; newdk->dk_mode = DK_MODE_UNKNOWN; newdk->dk_state = DK_STATE_INIT; newdk->dk_closure = memclosure; newdk->dk_libhandle = libhandle; newdk->dk_tmpdir = libhandle->dkl_tmpdir; newdk->dk_timeout = DEFTIMEOUT; if ((libhandle->dkl_flags & DK_LIBFLAGS_HDRLIST) != 0) newdk->dk_flags |= DK_FLAG_HDRLIST; *statp = DK_STAT_OK; return newdk; } /* ** DK_CANONINIT -- initialize canonicalization ** ** Parameters: ** dk -- DK handle */ static DK_STAT dk_canoninit(DK *dk) { struct dk_sha1 *sha1; int saveerr; assert(dk != NULL); #ifdef _FFR_HASH_BUFFERING dk->dk_hashbuf = dk_malloc(dk->dk_libhandle, dk->dk_closure, DK_HASHBUFSIZE); if (dk->dk_hashbuf == NULL) { dk_error(dk, "unable to allocate %d byte(s)", DK_HASHBUFSIZE); return DK_STAT_NORESOURCE; } dk->dk_hashbufsize = DK_HASHBUFSIZE; dk->dk_hashbuflen = 0; #endif /* _FFR_HASH_BUFFERING */ sha1 = dk_malloc(dk->dk_libhandle, dk->dk_closure, sizeof(struct dk_sha1)); if (sha1 == NULL) { dk_error(dk, "unable to allocate %d byte(s)", sizeof(struct dk_sha1)); return DK_STAT_NORESOURCE; } memset(sha1, '\0', sizeof(struct dk_sha1)); sha1->sha1_tmpfd = -1; dk->dk_signinfo = (void *) sha1; SHA1_Init(&sha1->sha1_sha1); if (DK_DEBUG('c') || (dk->dk_libhandle->dkl_flags & DK_LIBFLAGS_TMPFILES) != 0) { /* cache the stored stuff for later processing */ snprintf(sha1->sha1_tmppath, sizeof sha1->sha1_tmppath - 1, "%s/dk.%d.XXXXXX", dk->dk_tmpdir, getpid()); sha1->sha1_tmpfd = mkstemp(sha1->sha1_tmppath); saveerr = errno; if (sha1->sha1_tmpfd == -1) { /* looks like this is a bug on OpenBSD */ (void) unlink(sha1->sha1_tmppath); errno = saveerr; dk_error(dk, "unable to create temporary file at %s", sha1->sha1_tmppath); return DK_STAT_NORESOURCE; } sha1->sha1_tmpbio = BIO_new_fd(sha1->sha1_tmpfd, 1); if (!DK_DEBUG('c') && (dk->dk_libhandle->dkl_flags & DK_LIBFLAGS_KEEPFILES) == 0) (void) unlink(sha1->sha1_tmppath); } return DK_STAT_OK; } #ifdef _FFR_HASH_BUFFERING /* ** DK_CANONBUFFER -- buffer for dk_canon() ** ** Parameters: ** dk -- DK handle ** buf -- buffer containing canonicalized data ** buflen -- number of bytes to consume ** ** Return value: ** None. */ static void dk_canonbuffer(DK *dk, u_char *buf, size_t buflen) { assert(dk != NULL); /* NULL buffer or 0 length means flush */ if ((buf == NULL || buflen == 0) && dk->dk_hashbuflen > 0) { dk_canon(dk, dk->dk_hashbuf, dk->dk_hashbuflen); dk->dk_hashbuflen = 0; return; } /* not enough buffer space; write the buffer out */ if (dk->dk_hashbuflen + buflen > dk->dk_hashbufsize) { dk_canon(dk, dk->dk_hashbuf, dk->dk_hashbuflen); dk->dk_hashbuflen = 0; } /* ** Now, if the input is bigger than the buffer, write it too; ** otherwise cache it. */ if (buflen >= dk->dk_hashbufsize) { dk_canon(dk, buf, buflen); } else { memcpy(&dk->dk_hashbuf[dk->dk_hashbuflen], buf, buflen); dk->dk_hashbuflen += buflen; } } #endif /* _FFR_HASH_BUFFERING */ /* ** DK_CANON -- canonicalize some data ** ** Parameters: ** dk -- DK handle ** buf -- buffer containing data ** buflen -- number of bytes to consume ** ** Return value: ** None. */ static void dk_canon(DK *dk, unsigned char *buf, size_t buflen) { struct dk_sha1 *sha1; assert(dk != NULL); sha1 = (struct dk_sha1 *) dk->dk_signinfo; if (buf == NULL || buflen == 0) return; if (dk->dk_writesep) { if (sha1->sha1_tmpfd != -1) BIO_write(sha1->sha1_tmpbio, CRLF, 2); SHA1_Update(&sha1->sha1_sha1, CRLF, 2); dk->dk_writesep = FALSE; } if (sha1->sha1_tmpfd != -1) BIO_write(sha1->sha1_tmpbio, buf, buflen); SHA1_Update(&sha1->sha1_sha1, buf, buflen); } /* ** DK_VERROR -- log an error into a DK handle (varargs version) ** ** Parameters: ** dk -- DK context in which this is performed ** format -- format to apply ** va -- argument list ** ** Return value: ** None. */ static void dk_verror(DK *dk, const char *format, va_list va) { int flen; int saverr; char *newdk; assert(dk != NULL); assert(format != NULL); saverr = errno; if (dk->dk_error == NULL) { dk->dk_error = dk_malloc(dk->dk_libhandle, dk->dk_closure, DEFERRLEN); if (dk->dk_error == NULL) { errno = saverr; return; } dk->dk_errlen = DEFERRLEN; } for (;;) { flen = vsnprintf(dk->dk_error, dk->dk_errlen, format, va); /* compensate for broken vsnprintf() implementations */ if (flen == -1) flen = dk->dk_errlen * 2; if (flen >= dk->dk_errlen) { newdk = dk_malloc(dk->dk_libhandle, dk->dk_closure, flen + 1); if (newdk == NULL) { errno = saverr; return; } dk_mfree(dk->dk_libhandle, dk->dk_closure, dk->dk_error); dk->dk_error = newdk; dk->dk_errlen = flen + 1; } else { break; } } errno = saverr; } /* ** DK_ERROR -- log an error into a DK handle ** ** Parameters: ** dk -- DK context in which this is performed ** format -- format to apply ** ... -- arguments ** ** Return value: ** None. */ static void dk_error(DK *dk, const char *format, ...) { va_list va; assert(dk != NULL); assert(format != NULL); va_start(va, format); dk_verror(dk, format, va); va_end(va); } /* ** ===== PUBLIC SECTION */ /* ** DK_INIT -- initialize the DomainKeys system */ DK_LIB * dk_init(void *(*caller_mallocf)(void *closure, size_t nbytes), void (*caller_freef)(void *closure, void *p)) { DK_LIB *libhandle; char *path; /* initialize the resolver */ (void) res_init(); /* initialize OpenSSL algorithms */ #if 0 OpenSSL_add_all_algorithms(); #endif /* 0 */ /* copy the parameters */ libhandle = (DK_LIB *) malloc(sizeof(struct dk_lib)); if (libhandle == NULL) return NULL; memset(libhandle, '\0', sizeof(struct dk_lib)); libhandle->dkl_malloc = caller_mallocf; libhandle->dkl_free = caller_freef; libhandle->dkl_flags = DK_LIBFLAGS_DEFAULT; libhandle->dkl_querymethod = DK_QUERY_UNKNOWN; path = getenv("DK_TMPDIR"); if (path == NULL) path = DK_TMPDIR; sm_strlcpy(libhandle->dkl_tmpdir, path, sizeof libhandle->dkl_tmpdir); #if USE_ARLIB libhandle->dkl_arlib = ar_init(NULL, NULL, NULL, 0); if (libhandle->dkl_arlib == NULL) { free(libhandle); return NULL; } #else /* USE_ARLIB */ (void) res_init(); #endif /* USE_ARLIB */ return libhandle; } /* ** DK_CLOSE -- shut down a DK library package ** ** Parameters: ** lib -- library handle to shut down ** ** Return value: ** None. */ void dk_close(DK_LIB *lib) { assert(lib != NULL); #ifdef USE_ARLIB if (lib->dkl_arlib != NULL) (void) ar_shutdown(lib->dkl_arlib); #endif /* USE_ARLIB */ free((void *) lib); EVP_cleanup(); } /* ** DK_SIGN -- allocate a handle for use in a signature operation */ DK * dk_sign(DK_LIB *dklib, const char *id, void *memclosure, const dk_sigkey_t *secretkey, dk_canon_t canonalg, dk_alg_t signalg, DK_STAT *statp) { DK *newdk; assert(dklib != NULL); assert(canonalg == DK_CANON_SIMPLE || canonalg == DK_CANON_NOFWS); assert(signalg == DK_SIGN_RSASHA1); newdk = dk_new(dklib, id, memclosure, canonalg, signalg, statp); if (newdk != NULL) { newdk->dk_mode = DK_MODE_SIGN; if (secretkey != NULL) { newdk->dk_keylen = strlen((const char *) secretkey); newdk->dk_key = (unsigned char *) dk_malloc(dklib, memclosure, newdk->dk_keylen + 1); if (newdk->dk_key == NULL) { dk_free(newdk); return NULL; } memcpy(newdk->dk_key, secretkey, newdk->dk_keylen + 1); } } return newdk; } /* ** DK_VERIFY -- allocate a handle for use in a verification operation */ DK * dk_verify(DK_LIB *dklib, const char *id, void *memclosure, DK_STAT *statp) { DK *newdk; assert(dklib != NULL); newdk = dk_new(dklib, id, memclosure, DK_CANON_UNKNOWN, DK_SIGN_UNKNOWN, statp); if (newdk != NULL) newdk->dk_mode = DK_MODE_VERIFY; return newdk; } /* ** DK_GETERROR -- return any stored error string from within the DK ** context handle */ const char * dk_geterror(DK *dk) { assert(dk != NULL); return dk->dk_error; } /* ** DK_HEADER -- process a header */ DK_STAT dk_header(DK *dk, u_char *hdr, size_t len) { assert(dk != NULL); assert(hdr != NULL); assert(len > 0); /* verify state */ if (dk->dk_state > DK_STATE_HEADER) return DK_STAT_INTERNAL; dk->dk_state = DK_STATE_HEADER; /* ** If we're signing, or we found the DomainKeys: header before, ** this is a header of interest. Canonicalize and process. */ if (dk->dk_mode != DK_MODE_VERIFY || dk->dk_processing) { bool prevcr; bool skipit = FALSE; unsigned char *p; unsigned char *pend; char *q; char *qend; pend = hdr + len; qend = &dk->dk_hdrbuf[sizeof(dk->dk_hdrbuf)]; prevcr = FALSE; if (dk->dk_mode == DK_MODE_VERIFY) { /* is this header signed? */ if (!dk_hdrsigned(dk, hdr, TRUE)) skipit = TRUE; } else { /* XXX -- omit Received: ? */ if (!dk_hdrsigned(dk, hdr, FALSE) && dk->dk_hdrlidx < MAXHDRCNT) { dk->dk_hdrlist[dk->dk_hdrlidx] = &dk->dk_hdrbuf[dk->dk_hdrlen]; dk->dk_hdrlidx++; } } if (dk->dk_hdrsidx < MAXHDRCNT) { dk->dk_hdrset[dk->dk_hdrsidx] = &dk->dk_hdrbuf[dk->dk_hdrlen]; dk->dk_hdrsidx++; } for (p = hdr, q = &dk->dk_hdrbuf[dk->dk_hdrlen]; !skipit && p < pend && q < qend; p++) { if (*p == '\n' && dk->dk_canonalg != DK_CANON_NOFWS) { if (prevcr) { prevcr = FALSE; *q = '\n'; } else { *q = '\r'; if (q < qend) { q++; *q = '\n'; } } } else if (dk->dk_canonalg == DK_CANON_NOFWS) { if (*p == 0x20 || *p == 0x09 || *p == 0x0a || *p == 0x0D) continue; *q = *p; } else { *q = *p; } if (*p == '\r') prevcr = TRUE; q++; } if (!skipit && dk->dk_canonalg == DK_CANON_NOFWS) { if (q < qend) { *q = '\r'; q++; } if (q < qend) { *q = '\n'; q++; } } *q = '\0'; q++; dk->dk_hdrlen = q - dk->dk_hdrbuf; } /* ** Store the From: or Sender: value regardless of its position ** in case no DomainKey-Signature: header is found. */ if ((strncasecmp(hdr, "from:", 5) == 0 && dk->dk_uhdrn[0] == '\0') || strncasecmp(hdr, "sender:", 7) == 0) { int status; char *user; char *domain; u_char *colon; u_char tmphdr[MAXHEADER + 1]; sm_strlcpy(tmphdr, hdr, sizeof tmphdr); colon = (u_char *) strchr(tmphdr, ':'); status = rfc2822_mailbox_split(colon + 1, &user, &domain); if (status != 0 || user == NULL || domain == NULL) { dk_error(dk, "unable to parse sender `%s'", colon + 1); return DK_STAT_SYNTAX; } sm_strlcpy(dk->dk_uhdrn, tmphdr, MIN(sizeof dk->dk_uhdrn, (u_int) (colon - tmphdr) + 1)); dk_lowercase(dk->dk_uhdrn); snprintf(dk->dk_uhdrv, sizeof dk->dk_uhdrv, "%s@%s", user, domain); } /* ** If this is a DomainKey-Signature: header, cache it and note that ** the rest is of interest. */ if (strncasecmp(hdr, DK_SIGNHEADER, strlen(DK_SIGNHEADER)) == 0 && hdr[strlen(DK_SIGNHEADER)] == ':') { /* first DomainKey-Signature: header? */ if (!dk->dk_processing) { u_char *hval; hval = hdr + strlen(DK_SIGNHEADER) + 1; if (dk_process_dkheader(dk, hval) != 0) { dk_error(dk, "syntax error in signature"); return DK_STAT_SYNTAX; } dk->dk_processing = TRUE; } /* XXX -- OPTIMIZATION ** For signed messages, at this point we know under which ** domain and selector the message was signed. We could ** start the appropriate TXT query here. */ } return DK_STAT_OK; } /* ** DK_EOH -- note end of headers */ DK_STAT dk_eoh(DK *dk) { int saveerr; unsigned int c; unsigned int d; size_t hlen; char *colon; struct dk_sha1 *sha1; char *sender; char *from; char *hdr; unsigned char *p; int status; assert(dk != NULL); /* verify state */ if (dk->dk_state > DK_STATE_EOH) return DK_STAT_INTERNAL; dk->dk_state = DK_STATE_EOH; sender = NULL; from = NULL; for (c = 0; c < dk->dk_hdrsidx; c++) { if (strncasecmp(dk->dk_hdrset[c], "from:", 5) == 0) { if (from != NULL) { dk_error(dk, "multiple From: headers found"); return DK_STAT_SYNTAX; } from = dk->dk_hdrset[c]; } if (strncasecmp(dk->dk_hdrset[c], "sender:", 7) == 0) { if (sender != NULL) { dk_error(dk, "multiple Sender: headers found"); return DK_STAT_SYNTAX; } sender = dk->dk_hdrset[c]; } } hdr = NULL; if (sender == NULL) hdr = from; else hdr = sender; /* if verifying and no from/sender header was found, short-circuit */ if (hdr == NULL && dk->dk_mode == DK_MODE_VERIFY) { char *at; at = strchr(dk->dk_uhdrv, '@'); if (at == NULL || *(at + 1) == '\0') { dk_error(dk, "missing or empty domain name in sender"); return DK_STAT_SYNTAX; } /* clean up if dk->dk_domain already allocated */ if (dk->dk_domain == NULL) { dk_mfree(dk->dk_libhandle, dk->dk_closure, dk->dk_domain); } dk->dk_domain = dk_malloc(dk->dk_libhandle, dk->dk_closure, strlen(at + 1) + 1); if (dk->dk_domain == NULL) { dk_error(dk, "unable to allocate %d byte(s)", strlen(at + 1) + 1); return DK_STAT_NORESOURCE; } sm_strlcpy(dk->dk_domain, at + 1, strlen(at + 1) + 1); dk->dk_skipbody = TRUE; (void) dk_in_use(dk); if (dk->dk_signall || DK_DEBUG('s')) return DK_STAT_NOSIG; else return DK_STAT_OK; } /* if we found a signature but the sender doesn't match it, say so */ if (hdr != NULL) { size_t len; char *user; char *domain; colon = strchr(hdr, ':'); len = strlen(colon + 1) + 1; dk->dk_sender = dk_malloc(dk->dk_libhandle, dk->dk_closure, len); if (dk->dk_sender == NULL) return DK_STAT_INTERNAL; sm_strlcpy(dk->dk_frombuf, colon + 1, sizeof dk->dk_frombuf); status = rfc2822_mailbox_split(dk->dk_frombuf, &user, &domain); if (status != 0 || user == NULL || domain == NULL) { dk_error(dk, "unable to parse sender `%s'", colon + 1); return DK_STAT_SYNTAX; } snprintf(dk->dk_sender, len, "%s@%s", user, domain); /* verify domain/subdomain match */ if (dk->dk_mode == DK_MODE_VERIFY) { bool ok = FALSE; /* incorrect DomainKey-Signature: header? */ if (dk->dk_domain == NULL) { dk_error(dk, "can't determine signing domain"); return DK_STAT_CANTVRFY; } if (strcasecmp(domain, dk->dk_domain) != 0) { for (p = strchr(domain, '.'); p != NULL; p = strchr(p + 1, '.')) { if (strcasecmp(p + 1, dk->dk_domain) == 0) { ok = TRUE; break; } } } else { ok = TRUE; } if (!ok) { dk_error(dk, "signing domain and sending domain mismatch"); return DK_STAT_CANTVRFY; } } dk->dk_user = dk_strdup(dk->dk_libhandle, dk->dk_closure, user); if (dk->dk_domain == NULL) { dk->dk_domain = dk_strdup(dk->dk_libhandle, dk->dk_closure, domain); } } else { dk_error(dk, "no sender header found"); return DK_STAT_SYNTAX; } /* verify granularity */ if (dk->dk_gran != NULL && dk->dk_gran[0] != '\0') { if (strcmp(dk->dk_user, dk->dk_gran) != 0) { dk_error(dk, "key granularity mismatch"); return DK_STAT_CANTVRFY; } } status = dk_canoninit(dk); if (status != DK_STAT_OK) return status; /* dk_hdrlist -- set of headers to include */ /* dk_hdrset -- set of headers on input */ /* ** I would normally be embarrassed to use an O(N^2) ** algorithm, but this is a small data set. */ if (dk->dk_hdrlidx > 0 && (dk->dk_flags & DK_FLAG_HDRLIST) != 0) { /* reset sender/from buffer to use what was actually signed */ memset(dk->dk_uhdrn, '\0', sizeof dk->dk_uhdrn); memset(dk->dk_uhdrv, '\0', sizeof dk->dk_uhdrv); for (c = 0; c < dk->dk_hdrlidx; c++) { colon = strchr(dk->dk_hdrlist[c], ':'); if (colon == NULL) hlen = strlen(dk->dk_hdrlist[c]); else hlen = colon - dk->dk_hdrlist[c]; for (d = 0; d < dk->dk_hdrsidx; d++) { if (strncasecmp(dk->dk_hdrset[d], dk->dk_hdrlist[c], hlen) == 0 && dk->dk_hdrset[d][hlen] == ':') { dk_canon(dk, dk->dk_hdrset[d], strlen(dk->dk_hdrset[d])); colon = strchr(dk->dk_hdrset[d], ':'); /* extract correct sender/from data */ if ((strncasecmp(dk->dk_hdrlist[c], "from", hlen) == 0 && dk->dk_uhdrn[0] == '\0') || strncasecmp(dk->dk_hdrlist[c], "sender", hlen) == 0) { strncpy(dk->dk_uhdrn, dk->dk_hdrlist[c], hlen); if (colon != NULL) { sm_strlcpy(dk->dk_uhdrv, colon + 1, sizeof dk->dk_uhdrv); } } } } } if (dk->dk_uhdrv[0] != '\0') { int status; char *user; char *domain; u_char *at; char addr[MAXADDRESS + 1]; sm_strlcpy(addr, dk->dk_uhdrv, sizeof addr); status = rfc2822_mailbox_split(addr, &user, &domain); if (status != 0 || user == NULL || domain == NULL) { dk_error(dk, "unable to parse sender `%s'", addr); return DK_STAT_SYNTAX; } snprintf(dk->dk_uhdrv, sizeof dk->dk_uhdrv, "%s@%s", user, domain); at = strchr(dk->dk_uhdrv, '@'); dk_lowercase(at + 1); } } else { unsigned int c; for (c = 0; c < dk->dk_hdrsidx; c++) { dk_canon(dk, dk->dk_hdrset[c], strlen(dk->dk_hdrset[c])); } } /* ** The next call to dk_canon() that actually writes something ** should write an extra CRLF to separate the headers from the ** body. */ dk->dk_writesep = TRUE; /* ** If no DomainKeys: header was found, determine whether or not ** there should be one, and return something appropriate. */ if (!dk->dk_processing) { int status; if (dk->dk_domain == NULL) { char *at; at = strchr(dk->dk_sender, '@'); if (at == NULL || *(at + 1) == '\0') { dk_error(dk, "can't find sender domain in `%s'", dk->dk_sender); return DK_STAT_SYNTAX; } dk->dk_domain = dk_malloc(dk->dk_libhandle, dk->dk_closure, strlen(at + 1) + 1); if (dk->dk_domain == NULL) { dk_error(dk, "unable to allocate %d byte(s)", strlen(at + 1) + 1); return DK_STAT_NORESOURCE; } sm_strlcpy(dk->dk_domain, at + 1, strlen(at + 1) + 1); } if (dk->dk_selector == NULL && dk->dk_mode == DK_MODE_VERIFY) { (void) dk_in_use(dk); if (dk->dk_signall || DK_DEBUG('s')) return DK_STAT_NOSIG; else return DK_STAT_OK; } status = dk_get_key(dk); if (status == DK_STAT_INTERNAL) { return status; } else if (status != DK_STAT_OK) { if (dk->dk_mode == DK_MODE_VERIFY) { if (dk->dk_key != NULL || dk->dk_signall || DK_DEBUG('s')) return DK_STAT_NOSIG; else return DK_STAT_NOKEY; } else { if (dk->dk_key == NULL) return DK_STAT_NOKEY; } } } /* ** Apply signature defaults. */ if (dk->dk_processing) { if (dk->dk_libhandle->dkl_querymethod != DK_QUERY_UNKNOWN) dk->dk_querymethod = dk->dk_libhandle->dkl_querymethod; else if (dk->dk_querymethod == DK_QUERY_UNKNOWN) dk->dk_querymethod = DK_QUERY_DEFAULT; } /* ** If some of the supposedly-signed headers were absent, ** return an error. */ if (dk->dk_processing) { unsigned int c; for (c = 0; c < dk->dk_hdrlidx; c++) { if (!dk->dk_hdrmark[c]) return DK_STAT_BADSIG; } } /* ** Return DK_STAT_REVOKED if the key was revoked. */ if (dk->dk_revoked) return DK_STAT_REVOKED; /* ** Success! */ return DK_STAT_OK; } /* ** DK_BODY -- process a body chunk */ DK_STAT dk_body(DK *dk, u_char *buf, size_t len) { size_t lidx; size_t wlen; u_char *p; u_char *eob; u_char *wrote; unsigned char lbuf[BUFRSZ]; assert(dk != NULL); assert(buf != NULL); assert(len > 0); /* verify state */ if (dk->dk_state > DK_STATE_BODY) return DK_STAT_INTERNAL; dk->dk_state = DK_STATE_BODY; if (dk->dk_skipbody) return DK_STAT_OK; eob = buf + len - 1; wrote = buf; wlen = 0; lidx = 0; /* run it through the canonicalizing stuff */ switch (dk->dk_canonalg) { case DK_CANON_SIMPLE: for (p = buf; p <= eob; p++) { if (*p == '\n') { int c; /* adaptive */ if (dk->dk_crlf == DK_CRLF_UNKNOWN) { if (dk->dk_lastchar == '\r') dk->dk_crlf = DK_CRLF_CRLF; else dk->dk_crlf = DK_CRLF_LF; } if (dk->dk_crlf == DK_CRLF_CRLF && dk->dk_lastchar == '\r') { if (wlen == 1) { dk->dk_blanks++; wrote = p + 1; wlen = 0; } else { for (c = 0; c < dk->dk_blanks; c++) DK_CANON(dk, CRLF, 2); dk->dk_blanks = 0; DK_CANON(dk, wrote, wlen + 1); wlen = 0; wrote = p + 1; } dk->dk_lastchar = *p; continue; } else if (dk->dk_crlf == DK_CRLF_LF) { if (wlen == 0) { dk->dk_blanks++; wrote = p + 1; } else { for (c = 0; c < dk->dk_blanks; c++) DK_CANON(dk, CRLF, 2); dk->dk_blanks = 0; DK_CANON(dk, wrote, wlen); DK_CANON(dk, CRLF, 2); wlen = 0; wrote = p + 1; } dk->dk_lastchar = *p; continue; } } dk->dk_lastchar = *p; wlen++; } /* write what's left */ if (wlen > 0) DK_CANON(dk, wrote, wlen); break; case DK_CANON_NOFWS: for (p = buf; p <= eob; p++) { if (*p == '\n') { int c; /* adaptive */ if (dk->dk_crlf == DK_CRLF_UNKNOWN) { if (dk->dk_lastchar == '\r') dk->dk_crlf = DK_CRLF_CRLF; else dk->dk_crlf = DK_CRLF_LF; } if ((dk->dk_lastchar == '\r' && dk->dk_crlf == DK_CRLF_CRLF) || dk->dk_crlf == DK_CRLF_LF) { if (lidx == 0) { dk->dk_blanks++; } else { for (c = 0; c < dk->dk_blanks; c++) DK_CANON(dk, CRLF, 2); dk->dk_blanks = 0; DK_CANON(dk, lbuf, lidx); DK_CANON(dk, CRLF, 2); lidx = 0; } } } else if (!dk_isfws(*p)) { if (lidx == sizeof lbuf) { DK_CANON(dk, lbuf, lidx); lidx = 0; } lbuf[lidx] = *p; lidx++; } dk->dk_lastchar = *p; } if (lidx > 0) DK_CANON(dk, lbuf, lidx); break; default: DK_CANON(dk, buf, len); break; } return DK_STAT_OK; } /* ** DK_EOM -- note end of message */ DK_STAT dk_eom(DK *dk, DK_FLAGS *dkf) { int ret; BIO *key = NULL; struct dk_sha1 *sha1; unsigned char md[SHA_DIGEST_LENGTH]; assert(dk != NULL); /* verify state */ if (dk->dk_state >= DK_STATE_EOM) return DK_STAT_INTERNAL; dk->dk_state = DK_STATE_EOM; sha1 = (struct dk_sha1 *) dk->dk_signinfo; ret = DK_STAT_OK; /* if we're verifying, do the verification */ if (dk->dk_mode == DK_MODE_VERIFY) { int status; /* no sender header was found below the signature */ if (dk->dk_skipbody && dk->dk_processing) { dk_error(dk, "no sender header found below signature"); return DK_STAT_SYNTAX; } if (dk->dk_key == NULL) { if (dk->dk_selector == NULL) { (void) dk_in_use(dk); if (dk->dk_signall || DK_DEBUG('s')) return DK_STAT_NOSIG; else return DK_STAT_OK; } status = dk_get_key(dk); if (status != DK_STAT_OK) return status; } /* load the public key */ key = BIO_new_mem_buf(dk->dk_key, dk->dk_keylen); if (key == NULL) { dk_error(dk, "BIO_new_mem_buf() failed"); return DK_STAT_NORESOURCE; } sha1->sha1_pkey = d2i_PUBKEY_bio(key, NULL); if (sha1->sha1_pkey == NULL) { dk_error(dk, "d2i_PUBKEY_bio() failed"); BIO_free(key); return DK_STAT_NORESOURCE; } #ifdef _FFR_HASH_BUFFERING dk_canonbuffer(dk, NULL, 0); #endif /* _FFR_HASH_BUFFERING */ /* set up the RSA object */ sha1->sha1_rsa = EVP_PKEY_get1_RSA(sha1->sha1_pkey); if (sha1->sha1_rsa == NULL) { dk_error(dk, "EVP_PKEY_get1_RSA() failed"); BIO_free(key); return DK_STAT_NORESOURCE; } sha1->sha1_keysize = RSA_size(sha1->sha1_rsa); sha1->sha1_pad = RSA_PKCS1_PADDING; /* compute the SHA1 hash */ SHA1_Final(md, &sha1->sha1_sha1); /* verify the signature */ sha1->sha1_rsain = dk->dk_signature; sha1->sha1_rsainlen = dk->dk_signlen; status = RSA_verify(NID_sha1, md, SHA_DIGEST_LENGTH, sha1->sha1_rsain, sha1->sha1_rsainlen, sha1->sha1_rsa); if (status == 0) ret = DK_STAT_BADSIG; } /* return flags */ (void) dk_in_use(dk); if (dkf != NULL) { if (dk->dk_testing) *dkf |= DK_FLAG_TESTING; if (dk->dk_signall) *dkf |= DK_FLAG_SIGNSALL; } if (key != NULL) BIO_free(key); return ret; } /* ** DK_GETSIG -- compute the signature for a message */ DK_STAT dk_getsig(DK *dk, u_char *buf, size_t len) { int bits; int c; int char_count; int status; u_int l; size_t b64idx; size_t b64len; unsigned char *b64; BIO *key; struct dk_sha1 *sha1; unsigned char md[SHA_DIGEST_LENGTH]; assert(dk != NULL); assert(buf != NULL); assert(len > 0); /* verify state */ if (dk->dk_state != DK_STATE_EOM) { dk_error(dk, "dk_getsig() called out of sequence"); return DK_STAT_INTERNAL; } sha1 = (struct dk_sha1 *) dk->dk_signinfo; /* must be called only with a signing handle */ if (dk->dk_mode == DK_MODE_VERIFY) { dk_error(dk, "dk_getsig() called with verifying handle"); return DK_STAT_INTERNAL; } /* try to get the signature if it wasn't given */ if (dk->dk_key == NULL) { int status; status = dk_get_key(dk); if (status != DK_STAT_OK) return status; } #ifdef _FFR_HASH_BUFFERING dk_canonbuffer(dk, NULL, 0); #endif /* _FFR_HASH_BUFFERING */ /* load the private key */ key = BIO_new_mem_buf(dk->dk_key, dk->dk_keylen); if (key == NULL) { dk_error(dk, "BIO_new_mem_buf() failed"); return DK_STAT_NORESOURCE; } sha1->sha1_pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); if (sha1->sha1_pkey == NULL) { dk_error(dk, "PEM_read_bio_PrivateKey() failed"); BIO_free(key); return DK_STAT_NORESOURCE; } /* set up the RSA object */ sha1->sha1_rsa = EVP_PKEY_get1_RSA(sha1->sha1_pkey); if (sha1->sha1_rsa == NULL) { dk_error(dk, "EVP_PKEY_get1_RSA() failed"); BIO_free(key); return DK_STAT_NORESOURCE; } sha1->sha1_keysize = RSA_size(sha1->sha1_rsa); sha1->sha1_pad = RSA_PKCS1_PADDING; sha1->sha1_rsaout = dk_malloc(dk->dk_libhandle, dk->dk_closure, sha1->sha1_keysize); if (sha1->sha1_rsaout == NULL) { dk_error(dk, "unable to allocate %d byte(s)", sha1->sha1_keysize); BIO_free(key); return DK_STAT_NORESOURCE; } BIO_reset(sha1->sha1_tmpbio); /* compute the sha1 hash of the message */ SHA1_Final(md, &sha1->sha1_sha1); /* compute the signature on the hash */ sha1->sha1_rsainlen = SHA_DIGEST_LENGTH; sha1->sha1_rsain = md; status = RSA_sign(NID_sha1, sha1->sha1_rsain, sha1->sha1_rsainlen, sha1->sha1_rsaout, &l, sha1->sha1_rsa); if (status == 0 || l == 0) { BIO_free(key); dk_error(dk, "RSA_sign() returned %d, length %d", status, l); return DK_STAT_INTERNAL; } sha1->sha1_rsaoutlen = l; /* store the signature */ dk->dk_signature = sha1->sha1_rsaout; dk->dk_signlen = sha1->sha1_rsaoutlen; /* base64-encode the signature for validation */ b64len = sha1->sha1_rsaoutlen * 3 + 5; b64len += (b64len / 60); b64 = dk_malloc(dk->dk_libhandle, dk->dk_closure, b64len); if (b64 == NULL) { dk_error(dk, "unable to allocate %d byte(s)", b64len); BIO_free(key); return DK_STAT_NORESOURCE; } memset(b64, '\0', b64len); bits = 0; char_count = 0; b64idx = 0; for (c = 0; c < sha1->sha1_rsaoutlen; c++) { bits += sha1->sha1_rsaout[c]; char_count++; if (char_count == 3) { if (b64idx > b64len - 4) { BIO_free(key); dk_error(dk, "base64 encoding failed"); return DK_STAT_INTERNAL; } b64[b64idx++] = alphabet[bits >> 18]; b64[b64idx++] = alphabet[(bits >> 12) & 0x3f]; b64[b64idx++] = alphabet[(bits >> 6) & 0x3f]; b64[b64idx++] = alphabet[bits & 0x3f]; bits = 0; char_count = 0; } else { bits <<= 8; } } if (char_count != 0) { if (b64idx > b64len - 4) { BIO_free(key); dk_error(dk, "base64 encoding failed"); return DK_STAT_INTERNAL; } bits <<= 16 - (8 * char_count); b64[b64idx++] = alphabet[bits >> 18]; b64[b64idx++] = alphabet[(bits >> 12) & 0x3f]; if (char_count == 1) { b64[b64idx++] = '='; b64[b64idx++] = '='; } else { b64[b64idx++] = alphabet[(bits >> 6) & 0x3f]; b64[b64idx++] = '='; } } dk->dk_b64len = b64idx; dk->dk_b64 = b64; /* extract the signature */ strncpy(buf, dk->dk_b64, MIN(len, dk->dk_b64len)); BIO_free(key); return DK_STAT_OK; } /* ** DK_GETHDRS -- report which headers were included in calculation of ** the signature */ DK_STAT dk_gethdrs(DK *dk, int *hcnt, u_char *buf, size_t buflen) { int cnt = 0; unsigned int c; char *colon; char *end; assert(dk != NULL); assert(buf != NULL); assert(buflen > 0); /* verify state */ if (dk->dk_state != DK_STATE_EOM) return DK_STAT_INTERNAL; end = buf + strlen(buf); for (c = 0; c < dk->dk_hdrlidx; c++) { if (c != 0) { if (sm_strlcat(buf, ":", buflen) >= buflen) return DK_STAT_INTERNAL; end++; } if (sm_strlcat(buf, dk->dk_hdrlist[c], buflen) >= buflen) return DK_STAT_INTERNAL; colon = strchr(end, ':'); if (colon == NULL) return DK_STAT_INTERNAL; cnt++; *colon = '\0'; for (; *end != '\0'; end++) if (isascii(*end) && isupper(*end)) *end = tolower(*end); } *hcnt = cnt; return DK_STAT_OK; } /* ** DK_OPTIONS -- get or set a library option ** ** Parameters: ** lib -- DK library handle ** op -- operation to perform ** opt -- option to get/set ** ptr -- pointer to its old/new value ** len -- memory available at "ptr" ** ** Return value: ** A DK_STAT constant. */ DK_STAT dk_options(DK_LIB *lib, int op, dk_opts_t opt, void *ptr, size_t len) { assert(lib != NULL); assert(op == DK_OP_SETOPT || op == DK_OP_GETOPT); assert(len != 0); switch (opt) { case DK_OPTS_TMPDIR: if (ptr == NULL) return DK_STAT_INVALID; if (op == DK_OP_GETOPT) { sm_strlcpy((u_char *) ptr, lib->dkl_tmpdir, len); } else { sm_strlcpy(lib->dkl_tmpdir, (u_char *) ptr, sizeof lib->dkl_tmpdir); } return DK_STAT_OK; case DK_OPTS_FLAGS: if (ptr == NULL) return DK_STAT_INVALID; if (len != sizeof lib->dkl_flags) return DK_STAT_INVALID; if (op == DK_OP_GETOPT) { memcpy(ptr, &lib->dkl_flags, len); } else { memcpy(&lib->dkl_flags, ptr, len); } return DK_STAT_OK; case DK_OPTS_QUERYMETHOD: if (ptr == NULL) return DK_STAT_INVALID; if (len != sizeof lib->dkl_querymethod) return DK_STAT_INVALID; if (op == DK_OP_GETOPT) { memcpy(ptr, &lib->dkl_querymethod, len); } else { memcpy(&lib->dkl_querymethod, ptr, len); } return DK_STAT_OK; case DK_OPTS_QUERYINFO: if (ptr == NULL) return DK_STAT_INVALID; if (op == DK_OP_GETOPT) { sm_strlcpy(ptr, lib->dkl_queryinfo, len); } else { sm_strlcpy(lib->dkl_queryinfo, ptr, sizeof lib->dkl_queryinfo); } return DK_STAT_OK; default: return DK_STAT_INVALID; } /* to silence -Wall */ return DK_STAT_INTERNAL; } /* ** DK_REPORTINFO -- get report information */ DK_STAT dk_reportinfo(DK *dk, int *fd, char *addr, size_t alen) { struct dk_sha1 *sha1; assert(dk != NULL); /* verify state */ if (dk->dk_state != DK_STATE_EOM) return DK_STAT_INTERNAL; sha1 = (struct dk_sha1 *) dk->dk_signinfo; if (fd != NULL) { if (sha1 == NULL) *fd = -1; else *fd = sha1->sha1_tmpfd; } if (addr != NULL) sm_strlcpy(addr, dk->dk_reportaddr, alen); return DK_STAT_OK; } /* ** DK_GETIDENTITY -- retrieve apparent signer's identity */ DK_STAT dk_getidentity(DK *dk, char *hname, size_t hnamelen, char *hval, size_t hvallen) { assert(dk != NULL); if (dk->dk_state < DK_STATE_EOH) return DK_STAT_INTERNAL; if (hname != 0 && hnamelen > 0) sm_strlcpy(hname, dk->dk_uhdrn, hnamelen); if (hval != 0 && hvallen > 0) sm_strlcpy(hval, dk->dk_uhdrv, hvallen); return DK_STAT_OK; } /* ** DK_TIMEOUT -- set/get the current DNS timeout */ DK_STAT dk_timeout(DK *dk, int newt, int *old) { assert(dk != NULL); if (old != NULL) *old = dk->dk_timeout; if (newt != -1) dk->dk_timeout = newt; return DK_STAT_OK; } /* ** DK_FREE -- release resources associated with a DK handle */ DK_STAT dk_free(DK *dk) { struct dk_sha1 *sha1; assert(dk != NULL); sha1 = (struct dk_sha1 *) dk->dk_signinfo; #define CLOBBER(x) if ((x) != NULL) \ { \ dk_mfree(dk->dk_libhandle, dk->dk_closure, (x)); \ (x) = NULL; \ } #define BIO_CLOBBER(x) if ((x) != NULL) \ { \ BIO_free((x)); \ (x) = NULL; \ } #define RSA_CLOBBER(x) if ((x) != NULL) \ { \ RSA_free((x)); \ (x) = NULL; \ } #define EVP_CLOBBER(x) if ((x) != NULL) \ { \ EVP_PKEY_free((x)); \ (x) = NULL; \ } if (sha1 != NULL) { BIO_CLOBBER(sha1->sha1_tmpbio); EVP_CLOBBER(sha1->sha1_pkey); RSA_CLOBBER(sha1->sha1_rsa); CLOBBER(sha1->sha1_rsaout); CLOBBER(dk->dk_signinfo); } CLOBBER(dk->dk_sender); CLOBBER(dk->dk_domain); CLOBBER(dk->dk_user); CLOBBER(dk->dk_selector); if (dk->dk_flags & DK_FLAG_FREESIGNATURE) CLOBBER(dk->dk_signature); CLOBBER(dk->dk_b64); CLOBBER(dk->dk_key); CLOBBER(dk->dk_gran); #ifdef _FFR_HASH_BUFFERING CLOBBER(dk->dk_hashbuf); #endif /* _FFR_HASH_BUFFERING */ dk_mfree(dk->dk_libhandle, dk->dk_closure, dk); return DK_STAT_OK; } dk-milter-1.0.0.dfsg/libdk/README0000644000175000017500000000177210225542511016035 0ustar madhackmadhack$Id: README,v 1.23 2005/04/08 17:54:17 msk Exp $ DEBUG FEATURES ============== The DKDEBUG environment variable, if set, specifies debugging options to be applied by the library. Note that dk-filter uses the same variable name (for now) so there may be some overlap in the debug flags used. See dk-filter/README for details. The contents of DKDEBUG should be a string containing characters representing the required debug options as depicted in this list: c leave temporary files in /var/tmp; the files will contain canonicalized messages as they are fed to the signing or verifying operations d log failures reported by the ar_waitreply() function r log resolver function calls and completions at LOG_INFO s assume all domains assert "sign all" policies ENVIRONMENT VARIABLES ===================== In addition to what's described above, the following environment variables are checked and have some impact on libdk: DK_TMPDIR directory in which temporary files are created; default is /var/tmp dk-milter-1.0.0.dfsg/libdk/rfc2822.h0000644000175000017500000000064710057642376016433 0ustar madhackmadhack/* ** Copyright (c) 2004 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef _RFC2822_H_ #define _RFC2822_H_ #ifndef lint static char rfc2822_h_id[] = "@(#)$Id: rfc2822.h,v 1.1 2004/06/03 15:34:22 msk Exp $"; #endif /* !lint */ /* prototypes */ extern int rfc2822_mailbox_split __P((char *line, char **user_out, char **domain_out)); #endif /* ! _RFC2822_H_ */ dk-milter-1.0.0.dfsg/libdk/dk-private.h0000644000175000017500000000662710764452473017417 0ustar madhackmadhack/* ** Copyright (c) 2004, 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** $Id: dk-private.h,v 1.42 2008/03/08 08:58:35 msk Exp $ */ #ifndef _SMI_DK_PRIVATE_H_ #define _SMI_DK_PRIVATE_H_ #ifndef lint static char dk_private_h_id[] = "@(#)$Id: dk-private.h,v 1.42 2008/03/08 08:58:35 msk Exp $"; #endif /* !lint */ /* system */ #include /* libsm */ #include /* libdk */ #include /* OpenSSL */ #include #include /* ** DK -- DomainKeys context */ struct dk { unsigned char dk_lastchar; /* last body character */ bool dk_hdrmark[MAXHDRCNT]; /* header list marks */ bool dk_processing; /* processing (not skipping) */ bool dk_testing; /* test mode */ bool dk_revoked; /* revoked key? */ bool dk_signall; /* domain signs all mail */ bool dk_skipbody; /* skip body content */ bool dk_writesep; /* write separator CRLF? */ int dk_mode; /* operating mode */ int dk_crlf; /* CRLF mode used by input */ int dk_state; /* state */ unsigned int dk_hdrlidx; /* header list index */ unsigned int dk_hdrsidx; /* header set index */ unsigned int dk_blanks; /* buffered blank lines */ unsigned int dk_flags; /* flags */ unsigned int dk_signalg; /* signing algorithm */ unsigned int dk_canonalg; /* canonicalization algorithm */ unsigned int dk_querymethod; /* query method */ unsigned int dk_timeout; /* DNS timeout */ #ifdef _FFR_HASH_BUFFERING unsigned int dk_hashbufsize; /* hash buffer size */ unsigned int dk_hashbuflen; /* hash buffer current length */ #endif /* _FFR_HASH_BUFFERING */ size_t dk_keylen; /* length of the key */ size_t dk_signlen; /* length of the signature */ size_t dk_b64len; /* base64 data length */ size_t dk_hdrlen; /* dk_hdrbuf bytes in use */ size_t dk_errlen; /* length of error string */ const char * dk_id; /* ID string for logging */ const char * dk_tmpdir; /* where to write temp files */ char * dk_sender; /* sender user@domain */ char * dk_shdrlist; /* signed header list */ char * dk_gran; /* granularity */ char * dk_user; /* signing user */ char * dk_domain; /* signing domain */ char * dk_selector; /* selector in signing domain */ char * dk_error; /* error string */ unsigned char * dk_signature; /* signature data */ unsigned char * dk_b64; /* base64-encoded data */ unsigned char * dk_key; /* signing key */ #ifdef _FFR_HASH_BUFFERING unsigned char * dk_hashbuf; /* hash buffer */ #endif /* _FFR_HASH_BUFFERING */ void * dk_signinfo; /* signing info */ void * dk_closure; /* opaque memory info */ DK_LIB * dk_libhandle; /* library handle */ char * dk_hdrset[MAXHDRCNT]; /* pointers into dk_hdrbuf */ char * dk_hdrlist[MAXHDRCNT]; /* list of signed headers */ char dk_frombuf[MAXADDRESS]; /* copy of From: header */ char dk_uhdrn[MAXHEADER]; /* identity header name */ char dk_uhdrv[MAXADDRESS]; /* identity header value */ char dk_reportaddr[MAXADDRESS]; /* where to send reports */ char dk_hdrbuf[MAXHEADERS]; /* header buffer */ }; /* ** DK_SHA1 -- SHA1 signing information */ struct dk_sha1 { unsigned char sha1_pad; int sha1_tmpfd; size_t sha1_keysize; size_t sha1_rsainlen; size_t sha1_rsaoutlen; BIO * sha1_tmpbio; EVP_PKEY * sha1_pkey; RSA * sha1_rsa; unsigned char * sha1_rsain; unsigned char * sha1_rsaout; SHA_CTX sha1_sha1; char sha1_tmppath[MAXPATHLEN + 1]; }; #endif /* ! _SMI_DK_PRIVATE_H_ */ dk-milter-1.0.0.dfsg/libdk/util.c0000644000175000017500000000242010437625044016275 0ustar madhackmadhack/* ** Copyright (c) 2004, 2006 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char util_c_id[] = "@(#)$Id: util.c,v 1.16 2006/06/01 17:55:48 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libsm includes */ #include /* libdk includes */ #include #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* ** DK_STERILIZE -- sterilize a variable that's used as part of a path ** ** Parameters: ** str -- string to sterilize ** ** Return value: ** str if the string was OK, otherwise a pointer to a location in ** the string after which data is safe, or NULL if no such point ** could be determined. */ char * dk_sterilize(char *str) { char *p; char *ret; assert(str != NULL); ret = str; p = strrchr(str, '/'); if (p != NULL) ret = p + 1; return (*ret == '\0' ? NULL : ret); } /* ** DK_LOWERCASE -- convert a string to lowercase ** ** Parameters: ** str -- string to convert ** ** Return value: ** None. */ void dk_lowercase(char *str) { char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (isascii(*p) && isupper(*p)) *p = tolower(*p); } } dk-milter-1.0.0.dfsg/libdk/t-test04.c0000644000175000017500000000750210764775051016721 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_test04_c_id[] = "@(#)$Id: t-test04.c,v 1.1 2008/03/09 14:54:33 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libdk includes */ #include "dk.h" #include "t-testdata.h" #define SIGHEADER "a=rsa-sha1; c=nofws; d=example.com; s=test; h=from:to:date:subject:message-id; b=cvrt8mI1kxfzoUrryNTJbbfrd+f35lqjrNSUCS2Y54jZu9KxnVMR+Yk/MWJ2wET94koRvBPDhPsAENGk98iuGXyMjGQl2vAEp3EwRrCzvhkwRRiTwqGDuKwZGoCIM/BBqS8U1OsA9OricRhN+0cOoDK4lhQmCrIPWGcStTVwjb8=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DK_STAT status; DK *dk; DK_LIB *lib; dk_query_t qtype = DK_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** nofws rsa-sha1 verifying with h= tag\n"); /* instantiate the library */ lib = dk_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DK_LIBFLAGS_TMPFILES|DK_LIBFLAGS_KEEPFILES); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dk = dk_verify(lib, JOBID, NULL, &status); assert(dk != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DK_SIGNHEADER, SIGHEADER); status = dk_header(dk, hdr, strlen(hdr)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER01, strlen(HEADER01)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER02, strlen(HEADER02)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER03, strlen(HEADER03)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER04, strlen(HEADER04)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER05, strlen(HEADER05)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER06, strlen(HEADER06)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER07, strlen(HEADER07)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER08, strlen(HEADER08)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER09, strlen(HEADER09)); assert(status == DK_STAT_OK); status = dk_eoh(dk); assert(status == DK_STAT_OK); status = dk_body(dk, BODY00, strlen(BODY00)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01, strlen(BODY01)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01A, strlen(BODY01A)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01B, strlen(BODY01B)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01C, strlen(BODY01C)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01D, strlen(BODY01D)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01E, strlen(BODY01E)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY02, strlen(BODY02)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY04, strlen(BODY04)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY05, strlen(BODY05)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_eom(dk, NULL); assert(status == DK_STAT_OK); status = dk_free(dk); assert(status == DK_STAT_OK); dk_close(lib); return 0; } dk-milter-1.0.0.dfsg/libdk/t-testdata.h0000644000175000017500000001114510764724305017406 0ustar madhackmadhack/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_testdata_h[] = "@(#)$Id: t-testdata.h,v 1.1 2008/03/09 09:07:17 msk Exp $"; #endif /* !lint */ #define HEADER01 "Received: received data 0" #define HEADER02 "Received: received data 1" #define HEADER03 "Received: received data 2" #define HEADER04 "Received: received data 3 part 1\r\n\t data 3 part 2" #define HEADER04UNWRAP "Received: received data 3 part 1 data 3 part 2" #define HEADER05 "From: Murray S. Kucherawy " #define HEADER06 "To: Sendmail Test Address " #define HEADER07 "Date: Thu, 05 May 2005 11:59:09 -0700" #define HEADER07XLEADSP "Date: Thu, 05 May 2005 11:59:09 -0700" #define HEADER07NOLEADSP "Date:Thu, 05 May 2005 11:59:09 -0700" #define HEADER08 "Subject: DKIM test message" #define HEADER09 "Message-ID: <439094BF.5010709@example.com>" #define HEADER10 "Cc: user@example.com" #define BODY00 "This is a message body. Fun!\r\n" #define BODY01 "Here is a second line.\r\n" #define BODY01A "Here is a line" #define BODY01B " that is broken up across calls.\r" #define BODY01C "\n" #define BODY01D "Now we can try something interesting, like a\r\nmulti-line buffer. This should not be mangled.\r\n" #define BODY01E "And a line with a trailing space: \r\n" #define BODY02 "Next we'll try a blank.\r\n" #define BODY03 "\r\n" #define BODY04 "Next we'll try multiple blanks.\r\n" #define BODY05 "Finally we'll try multiple trailing blanks.\r\n" #define BODY06 "Surprise, more data!\r\n" #define NBODY00 "This is a message body. Fun!\n" #define NBODY01 "Here is a second line.\r" #define NBODY01A "Here is a line" #define NBODY01B " that is broken up across calls.\r" #define NBODY01C "\n" #define NBODY01D "Now we can try something interesting, like a\nmulti-line buffer. This should not be mangled.\r\n" #define NBODY01E "And a line with a trailing space: \n" #define NBODY02 "Next we'll try a blank.\r" #define NBODY03 "\r\n" #define NBODY04 "Next we'll try multiple blanks.\r\n" #define NBODY05 "Finally we'll try multiple trailing blanks.\r" #define THEADER00 "Received: from client1.football.example.com [192.0.2.1]\r\n" \ " by submitserver.example.com with SUBMISSION;\r\n" \ " Fri, 11 Jul 2003 21:01:54 -0700 (PDT)" #define THEADER01 "From: Joe SixPack " #define THEADER02 "To: Suzie Q " #define THEADER03 "Subject: Is dinner ready?" #define THEADER04 "Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)" #define THEADER05 "Message-ID: <20030712040037.46341.5F8J@football.example.com>" #define TBODY "Hi.\r\n" \ "\r\n" \ "We lost the game. Are you hungry yet?\r\n" \ "\r\n" \ "Joe.\r\n" #define KEY "-----BEGIN RSA PRIVATE KEY-----\n" \ "MIICXQIBAAKBgQC4GUGr+d/6SFNzVLYpphnRd0QPGKz2uWnV65RAxa1Pw352Bqiz\n" \ "qiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFgF0gu3UJbNnu3+cd8k/kiQj+q\n" \ "4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3Dyc079gSLtnSrgXb+gQIDAQAB\n" \ "AoGAemlI0opm1Kvs2T4VliH8/tvX5FXbBH8LEZQAUwVeFTB/UQlieXyCV39pIxZO\n" \ "0Sa50qm8YNL9rb5HTSZiHQFOwyAKNqS4m/7JCsbuH4gQkPgPF561BHNL9oKfYgJq\n" \ "9P4kEFfDTBoXKBMxwWtT7AKV8dYvCa3vYzPQ/1BnqQdw2zECQQDyscdgR9Ih59PQ\n" \ "b72ddibdsxS65uXS2vzYLe7SKl+4R5JgJzw0M6DTAnoYFf6JAsKGZM15PCC0E16t\n" \ "RRo47U9VAkEAwjEVrlQ0/8yPACbDggDJg/Zz/uRu1wK0zjqj4vKjleubaX4SEvj7\n" \ "r6xxZm9hC1pMJAC9y3bbkbgCRBjXfyY6fQJBANe5aq2MaZ41wTOPf45NjbKXEiAo\n" \ "SbUpboKCIbyyaa8V/2h0t7D3C0dE9l4efsguqdZoF7Rh2/f1F70QpYRgfJkCQQCH\n" \ "oRrAeGXP50JVW72fNgeJGH/pnghgOa6of0JpxwhENJuGMZxUDfxTtUA6yD3iXP3j\n" \ "A3WL/wbaHsfOYf9Y+g1NAkAGLhx67Ah+uBNK4Xvfz0YPGINX20m+CMsxAw7FOaNv\n" \ "IW2oWFfZCB4APkIis79Ql45AHpavwx5XodBMzZwJUvlL\n" \ "-----END RSA PRIVATE KEY-----\n" #define PUBLICKEY "k=rsa; t=y; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEY2 "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ" \ "KBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYt" \ "IxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v" \ "/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhi" \ "tdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB" #define GIBBERISH "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 !@#$%^&*()_+|-={}[];':,./<>?`~\r\n" #define CRLF "\r\n" #define LARGEBODYSIZE 65536 #define KEYFILE "/var/tmp/testkeys" #define JOBID "testing" #define SELECTOR "test" #define SELECTOR2 "brisbane" #define DOMAIN "example.com" #define DOMAIN2 "sendmail.com" #define REPLYADDRESS "postmaster@localhost" dk-milter-1.0.0.dfsg/libdk/t-test05.c0000644000175000017500000000750410764775060016724 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_test05_c_id[] = "@(#)$Id: t-test05.c,v 1.1 2008/03/09 14:54:40 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libdk includes */ #include "dk.h" #include "t-testdata.h" #define SIGHEADER "a=rsa-sha1; c=simple; d=example.com; s=test; h=from:to:date:subject:message-id; b=EtmLAYbPraB1+W58az0tQwQwPswCzpRu0/vYV8yXq3Czriqap8sBFl+uHSWqVXUFjVB9gog/DXIdbLaRFvw+Y8q1/sci4JRat6fn3ZatXBhmDqEFHEauggMb0Xv7V4WVZARXR3nF9Lvqas5pt/BExsazfTLDQPR9GU00seeT0xQ=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DK_STAT status; DK *dk; DK_LIB *lib; dk_query_t qtype = DK_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** simple rsa-sha1 verifying with h= tag\n"); /* instantiate the library */ lib = dk_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DK_LIBFLAGS_TMPFILES|DK_LIBFLAGS_KEEPFILES); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dk = dk_verify(lib, JOBID, NULL, &status); assert(dk != NULL); status = dk_header(dk, HEADER01, strlen(HEADER01)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER02, strlen(HEADER02)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER03, strlen(HEADER03)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER04, strlen(HEADER04)); assert(status == DK_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DK_SIGNHEADER, SIGHEADER); status = dk_header(dk, hdr, strlen(hdr)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER05, strlen(HEADER05)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER06, strlen(HEADER06)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER07, strlen(HEADER07)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER08, strlen(HEADER08)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER09, strlen(HEADER09)); assert(status == DK_STAT_OK); status = dk_eoh(dk); assert(status == DK_STAT_OK); status = dk_body(dk, BODY00, strlen(BODY00)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01, strlen(BODY01)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01A, strlen(BODY01A)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01B, strlen(BODY01B)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01C, strlen(BODY01C)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01D, strlen(BODY01D)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01E, strlen(BODY01E)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY02, strlen(BODY02)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY04, strlen(BODY04)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY05, strlen(BODY05)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_eom(dk, NULL); assert(status == DK_STAT_OK); status = dk_free(dk); assert(status == DK_STAT_OK); dk_close(lib); return 0; } dk-milter-1.0.0.dfsg/libdk/t-test00.c0000644000175000017500000000637610764775266016735 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_test00_c_id[] = "@(#)$Id: t-test00.c,v 1.2 2008/03/09 14:56:54 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libdk includes */ #include "dk.h" #include "t-testdata.h" #define SIG "cvrt8mI1kxfzoUrryNTJbbfrd+f35lqjrNSUCS2Y54jZu9KxnVMR+Yk/MWJ2wET94koRvBPDhPsAENGk98iuGXyMjGQl2vAEp3EwRrCzvhkwRRiTwqGDuKwZGoCIM/BBqS8U1OsA9OricRhN+0cOoDK4lhQmCrIPWGcStTVwjb8=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DK_STAT status; DK *dk; DK_LIB *lib; dk_sigkey_t *key; unsigned char sig[MAXHEADER + 1]; printf("*** nofws rsa-sha1 signing\n"); /* instantiate the library */ lib = dk_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DK_LIBFLAGS_TMPFILES|DK_LIBFLAGS_KEEPFILES); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = (dk_sigkey_t *) KEY; dk = dk_sign(lib, JOBID, NULL, key, DK_CANON_NOFWS, DK_SIGN_RSASHA1, &status); assert(dk != NULL); status = dk_header(dk, HEADER05, strlen(HEADER05)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER06, strlen(HEADER06)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER07, strlen(HEADER07)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER08, strlen(HEADER08)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER09, strlen(HEADER09)); assert(status == DK_STAT_OK); status = dk_eoh(dk); assert(status == DK_STAT_OK); status = dk_body(dk, BODY00, strlen(BODY00)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01, strlen(BODY01)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01A, strlen(BODY01A)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01B, strlen(BODY01B)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01C, strlen(BODY01C)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01D, strlen(BODY01D)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01E, strlen(BODY01E)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY02, strlen(BODY02)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY04, strlen(BODY04)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY05, strlen(BODY05)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_eom(dk, NULL); assert(status == DK_STAT_OK); memset(sig, '\0', sizeof sig); status = dk_getsig(dk, sig, sizeof sig); assert(status == DK_STAT_OK); assert(strcmp(SIG, sig) == 0); status = dk_free(dk); assert(status == DK_STAT_OK); dk_close(lib); return 0; } dk-milter-1.0.0.dfsg/libdk/util.h0000644000175000017500000000056110153461614016302 0ustar madhackmadhack/* ** Copyright (c) 2004 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef _UTIL_H_ #define _UTIL_H_ #ifndef lint static char util_h_id[] = "@(#)$Id: util.h,v 1.8 2004/12/02 00:36:28 msk Exp $"; #endif /* !lint */ /* prototypes */ extern void dk_lowercase __P((char *str)); extern char *dk_sterilize __P((char *str)); #endif /* ! _UTIL_H_ */ dk-milter-1.0.0.dfsg/libdk/rfc2822.c0000644000175000017500000002205710405344006016407 0ustar madhackmadhack/* ** Copyright (c) 2004, 2006 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char rfc2822_c_id[] = "@(#)$Id: rfc2822.c,v 1.2 2006/03/13 19:29:10 msk Exp $"; #endif /* !lint */ /* system inludes */ #include #include #include #include /* types */ typedef unsigned long cmap_elem_type; /* symbolic names */ #define RFC2822_OK 0 /* success */ #define RFC2822_ERR_PUNBALANCED 1 /* unbalanced parentheses */ #define RFC2822_ERR_QUNBALANCED 2 /* unbalanced quotes */ #define RFC2822_ERR_SUNBALANCED 3 /* unbalanced sq. brackets */ /* a bitmap for the "specials" character class */ #define CMAP_NBITS (sizeof(cmap_elem_type) * CHAR_BIT) #define CMAP_NELEMS ((1 + UCHAR_MAX) / CMAP_NBITS) #define CMAP_INDEX(i) ((unsigned char)(i) / CMAP_NBITS) #define CMAP_BIT(i) (1 << (unsigned char)(i) % CMAP_NBITS) #define CMAP_TST(ar, c) ((ar)[CMAP_INDEX(c)] & CMAP_BIT(c)) #define CMAP_SET(ar, c) ((ar)[CMAP_INDEX(c)] |= CMAP_BIT(c)) static unsigned char const SPECIALS[] = "<>@,;:\\\"/[]?="; #ifdef RFC2822_TEST /* ** UNESCAPE -- remove escape characters from a string ** ** Parameters: ** s -- the string to be unescaped ** ** Return value: ** s. */ static char * unescape(char *s) { char *w; char const *r, *p, *e; if (s == NULL) return NULL; r = w = s; e = s + strlen(s); while ((p = memchr(r, '\\', e - s)) != NULL) { if (p > s) { if (r != w) memmove(w, r, p - r); w += p - r; } if (p[1] == '\0') { r = p + 1; } else { *w++ = p[1]; r = p + 2; } } if (r > w) { if (e > r) { memmove(w, r, e - r); w += e - r; } *w = '\0'; } return s; } #endif /* RFC2822_TEST */ /* ** MATCHING_PAREN -- return the location past matching opposite parentheses ** ** Parameters: ** s -- start of string to be processed ** e -- end of string to be processed ** open_paren -- open parenthesis character ** close_paren -- close parenthesis character ** ** Return value: ** Location of the final close parenthesis character in the string. ** For example, given "xxx((yyyy)zz)aaaa", would return the location ** of the second ")". There may be more beyond that, but at that point ** everything is balanced. */ static char * matching_paren(char *s, char *e, int open_paren, int close_paren) { int paren = 1; for (; s < e; s++) { if (*s == close_paren) { if (--paren == 0) break; } else if (*s == open_paren) { paren++; } else if (*s == '\\') { if (s[1] != '\0') s++; } } return s; } /* ** RFC2822_FIRST_SPECIAL -- find the first RFC2822 "special" character ** ** Parameters: ** p -- input string ** e -- end of input string ** special_out -- pointer to the first special character found ** ** Return value: ** 0 on success, or an RFC2822_ERR_* on failure. */ static int rfc2822_first_special(char *p, char *e, char **special_out) { size_t i; cmap_elem_type is_special[CMAP_NELEMS] = { 0 }; char *at_ptr = NULL; /* set up special finder */ for (i = 0; SPECIALS[i] != '\0'; i++) CMAP_SET(is_special, SPECIALS[i]); for (; p < e && *p != '\0'; p++) { /* skip white space between tokens */ while (p < e && (*p == '(' || (isascii((unsigned char) *p) && isspace((unsigned char) *p)))) { if (*p != '(') { p++; } else { p = matching_paren(p + 1, e, '(', ')'); if (*p == '\0') return RFC2822_ERR_PUNBALANCED; else p++; } } if (*p == '\0') break; if (*p == '"') { p = matching_paren(p + 1, e, '\0', '"'); if (*p == '\0') return RFC2822_ERR_QUNBALANCED; } else if (*p == '[') { p = matching_paren(p + 1, e, '\0', ']'); if (*p == '\0') return RFC2822_ERR_SUNBALANCED; } else if (CMAP_TST(is_special, *p)) { if (*p == '<') { *special_out = p; return 0; } else if (*p == ':' || *p == ';' || *p == ',') { if (at_ptr != NULL) *special_out = at_ptr; else *special_out = p; return 0; } else if (*p == '@') { at_ptr = p; } } else { while (*p != '\0' && !CMAP_TST(is_special, *p) && (!isascii(*p) || !isspace((unsigned char) *p)) && *p != '(') p++; p--; } } *special_out = p; return 0; } /* ** RFC2822_TOKEN -- find the next token ** ** Parameters: ** s -- start of input string ** e -- end of input string ** type_out -- type of token (returned) ** start_out -- start of token (returned) ** end_out -- start of token (returned) ** uncommented_whitespace -- set to TRUE if uncommented whitespace is ** discovered (returned) ** ** Return value: ** 0 on success, or an RFC2822_ERR_* on failure. */ static int rfc2822_token(char *s, char *e, int *type_out, char **start_out, char **end_out, int *uncommented_whitespace) { char *p; int err = 0; size_t i; int token_type; cmap_elem_type is_special[CMAP_NELEMS] = { 0 }; char *token_start, *token_end; *start_out = NULL; *end_out = NULL; *type_out = 0; err = 0; /* set up special finder */ for (i = 0; SPECIALS[i] != '\0'; i++) CMAP_SET(is_special, SPECIALS[i]); p = s; /* skip white space between tokens */ while (p < e && (*p == '(' || (isascii((unsigned char) *p) && isspace((unsigned char) *p)))) { if (*p != '(') { *uncommented_whitespace = 1; p++; } else { p = matching_paren(p + 1, e, '(', ')'); if (*p == '\0') return RFC2822_ERR_PUNBALANCED; else p++; } } if (p >= e || *p == '\0') return 0; /* our new token starts here */ token_start = p; /* fill in the token contents and type */ if (*p == '"') { token_end = matching_paren(p + 1, e, '\0', '"'); token_type = '"'; if (*token_end != '\0') token_end++; else err = RFC2822_ERR_QUNBALANCED; } else if (*p == '[') { token_end = p = matching_paren(p + 1, e, '\0', ']'); token_type = '['; if (*token_end != '\0') token_end++; else err = RFC2822_ERR_SUNBALANCED; } else if (CMAP_TST(is_special, *p)) { token_end = p + 1; token_type = *p; } else { while (p < e && *p != '\0' && !CMAP_TST(is_special, *p) && (!isascii(*p) || !isspace((unsigned char) *p)) && *p != '(') p++; token_end = p; token_type = 'x'; } *start_out = token_start; *end_out = token_end; *type_out = token_type; return err; } /* ** RFC2822_MAILBOX_SPLIT -- extract the local-part and hostname from an ** RFC2822 header, e.g. "From:" ** ** Parameters: ** line -- input line ** user_out -- pointer to "local-part" (returned) ** domain_out -- pointer to hostname (returned) ** ** Return value: ** 0 on success, or an RFC2822_ERR_* on failure. ** ** Notes: ** Input string is modified. */ int rfc2822_mailbox_split(char *line, char **user_out, char **domain_out) { int type; int ws; int err; char *e, *special; char *tok_s, *tok_e; char *w; *user_out = NULL; *domain_out = NULL; err = 0; w = line; e = line + strlen(line); ws = 0; for (;;) { err = rfc2822_first_special(line, e, &special); if (err != 0) return err; /* given the construct we're looking at, do the right thing */ switch (*special) { case '<': /* display name

    */ line = special + 1; for (;;) { err = rfc2822_token(line, e, &type, &tok_s, &tok_e, &ws); if (err != 0) return err; if (type == '>' || type == '\0') { *w = '\0'; return 0; } else if (type == '@') { *w++ = '\0'; *domain_out = w; } else if (type == ',' || type == ':') { /* source route punctuation */ *user_out = NULL; *domain_out = NULL; } else { if (*user_out == NULL) *user_out = w; memcpy(w, tok_s, tok_e - tok_s); w += tok_e - tok_s; } line = tok_e; } return 0; case ';': case ':': case ',': /* skip a group name or result */ line = special + 1; break; default: /* (display name) addr(display name)ess */ ws = 0; for (;;) { err = rfc2822_token(line, e, &type, &tok_s, &tok_e, &ws); if (err != 0) return err; if (type == '\0' || type == ',' || type == ';') { *w = '\0'; break; } else if (type == '@') { *w++ = '\0'; *domain_out = w; ws = 0; } else { if (*user_out == NULL) *user_out = w; else if (type == 'x' && ws == 1) *w++ = ' '; memmove(w, tok_s, tok_e - tok_s); w += tok_e - tok_s; ws = 0; } line = tok_e; } return 0; } } return err; } #ifdef RFC2822_TEST int main(int argc, char **argv) { int err; char *domain, *user; if (argc != 2) { fprintf(stderr, "Usage: %s mailheader\n", argv[0]); exit(64); } err = rfc2822_mailbox_split(argv[1], &user, &domain); if (err) { printf("error %d\n", err); } else { printf("user: '%s'\ndomain: '%s'\n", user ? unescape(user) : "null", domain ? unescape(domain) : "null"); } return 0; } #endif /* RFC2822_TEST */ dk-milter-1.0.0.dfsg/libdk/t-test03.c0000644000175000017500000000742510764775312016724 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_test03_c_id[] = "@(#)$Id: t-test03.c,v 1.2 2008/03/09 14:57:14 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libdk includes */ #include "dk.h" #include "t-testdata.h" #define SIGHEADER "a=rsa-sha1; c=simple; d=example.com; s=test; b=EtmLAYbPraB1+W58az0tQwQwPswCzpRu0/vYV8yXq3Czriqap8sBFl+uHSWqVXUFjVB9gog/DXIdbLaRFvw+Y8q1/sci4JRat6fn3ZatXBhmDqEFHEauggMb0Xv7V4WVZARXR3nF9Lvqas5pt/BExsazfTLDQPR9GU00seeT0xQ=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DK_STAT status; DK *dk; DK_LIB *lib; dk_query_t qtype = DK_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** simple rsa-sha1 verifying\n"); /* instantiate the library */ lib = dk_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DK_LIBFLAGS_TMPFILES|DK_LIBFLAGS_KEEPFILES); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dk = dk_verify(lib, JOBID, NULL, &status); assert(dk != NULL); status = dk_header(dk, HEADER01, strlen(HEADER01)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER02, strlen(HEADER02)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER03, strlen(HEADER03)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER04, strlen(HEADER04)); assert(status == DK_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DK_SIGNHEADER, SIGHEADER); status = dk_header(dk, hdr, strlen(hdr)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER05, strlen(HEADER05)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER06, strlen(HEADER06)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER07, strlen(HEADER07)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER08, strlen(HEADER08)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER09, strlen(HEADER09)); assert(status == DK_STAT_OK); status = dk_eoh(dk); assert(status == DK_STAT_OK); status = dk_body(dk, BODY00, strlen(BODY00)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01, strlen(BODY01)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01A, strlen(BODY01A)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01B, strlen(BODY01B)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01C, strlen(BODY01C)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01D, strlen(BODY01D)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01E, strlen(BODY01E)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY02, strlen(BODY02)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY04, strlen(BODY04)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY05, strlen(BODY05)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_eom(dk, NULL); assert(status == DK_STAT_OK); status = dk_free(dk); assert(status == DK_STAT_OK); dk_close(lib); return 0; } dk-milter-1.0.0.dfsg/libdk/t-test02.c0000644000175000017500000000742310764775312016721 0ustar madhackmadhack/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_test02_c_id[] = "@(#)$Id: t-test02.c,v 1.2 2008/03/09 14:57:14 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include #include #include /* libdk includes */ #include "dk.h" #include "t-testdata.h" #define SIGHEADER "a=rsa-sha1; c=nofws; d=example.com; s=test; b=cvrt8mI1kxfzoUrryNTJbbfrd+f35lqjrNSUCS2Y54jZu9KxnVMR+Yk/MWJ2wET94koRvBPDhPsAENGk98iuGXyMjGQl2vAEp3EwRrCzvhkwRRiTwqGDuKwZGoCIM/BBqS8U1OsA9OricRhN+0cOoDK4lhQmCrIPWGcStTVwjb8=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DK_STAT status; DK *dk; DK_LIB *lib; dk_query_t qtype = DK_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** nofws rsa-sha1 verifying\n"); /* instantiate the library */ lib = dk_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DK_LIBFLAGS_TMPFILES|DK_LIBFLAGS_KEEPFILES); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dk_options(lib, DK_OP_SETOPT, DK_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dk = dk_verify(lib, JOBID, NULL, &status); assert(dk != NULL); status = dk_header(dk, HEADER01, strlen(HEADER01)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER02, strlen(HEADER02)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER03, strlen(HEADER03)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER04, strlen(HEADER04)); assert(status == DK_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DK_SIGNHEADER, SIGHEADER); status = dk_header(dk, hdr, strlen(hdr)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER05, strlen(HEADER05)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER06, strlen(HEADER06)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER07, strlen(HEADER07)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER08, strlen(HEADER08)); assert(status == DK_STAT_OK); status = dk_header(dk, HEADER09, strlen(HEADER09)); assert(status == DK_STAT_OK); status = dk_eoh(dk); assert(status == DK_STAT_OK); status = dk_body(dk, BODY00, strlen(BODY00)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01, strlen(BODY01)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01A, strlen(BODY01A)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01B, strlen(BODY01B)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01C, strlen(BODY01C)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01D, strlen(BODY01D)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY01E, strlen(BODY01E)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY02, strlen(BODY02)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY04, strlen(BODY04)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY05, strlen(BODY05)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_body(dk, BODY03, strlen(BODY03)); assert(status == DK_STAT_OK); status = dk_eom(dk, NULL); assert(status == DK_STAT_OK); status = dk_free(dk); assert(status == DK_STAT_OK); dk_close(lib); return 0; } dk-milter-1.0.0.dfsg/libdk/Build0000755000175000017500000000053010014765114016133 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1999, 2004 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: Build,v 1.2 2004/02/18 22:42:20 msk Exp $ exec sh ../devtools/bin/Build $* dk-milter-1.0.0.dfsg/libdk/docs/0000755000175000017500000000000010766324726016116 5ustar madhackmadhackdk-milter-1.0.0.dfsg/libdk/docs/rfc2822_mailbox_split.html0000644000175000017500000000410710057642571023016 0ustar madhackmadhack rfc2822_mailbox_split()

    rfc2822_mailbox_split()

    SYNOPSIS
    #include <dk.h>
    int rfc2822_mailbox_split(
    	char *line,
    	char **user_out,
    	char **domain_out
    );
    
    Parse an RFFC2822 header for a user and hostname.
    DESCRIPTION
    Called When At any time.
    ARGUMENTS
    ArgumentDescription
    line Input line, not including the name of the header.
    user_out Pointer to a variable of type (char *) which will be set to point to the "local-part" (user ID) found in the input.
    domain_out Pointer to a variable of type (char *) which will be set to point to the domain found in the input.
    RETURN VALUE 0 on success, other on failure. The failure codes are internal to the library for now.
    NOTES
    • line is modified.
    • This function is not part of the DomainKeys API specification. It is provided as a facility to implementors to reduce code duplication.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_geterror.html0000644000175000017500000000427610575626613021322 0ustar madhackmadhack dk_geterror()

    dk_geterror()

    SYNOPSIS
    #include <dk.h>
    
    const char * dk_geterror(
    	DK *dkim
    );
    
    Retrieve the last stored error message associated with a DK handle.
    DESCRIPTION
    Called When dk_geterror() can be called at any time after a handle is initialized with a call to dk_sign() or dk_verify().
    ARGUMENTS
    ArgumentDescription
    dkim Message-specific handle, returned by dk_sign or dk_verify.
    RETURN VALUES
    ValueDescription
    NULL No error message has been stored for this handle.
    otherwise A pointer to the last stored error string.
    NOTES
    • This function is a local addition to the formal API specification and is experimental only. It may not appear in other implementations.

    Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_lib.html0000644000175000017500000000220210052245104020200 0ustar madhackmadhack DK_LIB

    DK_LIB

    DESCRIPTION
    Purpose A DK_LIB handle is returned by a successful call to dk_init() and contains context information needed for a single instance of the libdk service to be used. It can be used by several threads at once.
    NOTES

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_sign.html0000644000175000017500000000527110052245104020403 0ustar madhackmadhack dk_sign()

    dk_sign()

    SYNOPSIS
    #include <dk.h>
    DK *dk_sign(
    	DK_LIB *libhandle,
    	const char *id,
    	void *memclosure,
    	const void *secretkey,
    	dk_canon_t canon_alg,
    	dk_alg_t sign_alg,
    	DK_STAT *statp
    );
    
    Create a new handle for signing a message.
    DESCRIPTION
    Called When dk_sign() is called when preparing to process a new message that will be signed later by a private key.
    ARGUMENTS
    ArgumentDescription
    libhandle DomainKeys library instance handle, returned by an earlier call to dk_init().
    id An opaque, printable string for identifying this message, suitable for use in logging or debug output.
    memclosure Opaque memory closure, passed directly to the caller-provided malloc() and/or free() replacement functions.
    secretkey The private key to be used when signing this message.
    canon_alg The canonicalization algorithm to use when preparing this message for signing.
    sign_alg The signing algorithm to use when generating the signature to be attached to this message.
    statp Pointer to a DK_STAT object which receives the completion status of this operation.
    NOTES
    • None.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_body.html0000644000175000017500000000360710052245104020401 0ustar madhackmadhack dk_body()

    dk_body()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_body(
    	DK *dk,
    	unsigned char *bodyp,
    	size_t len
    );
    
    Handle a piece of a message's body.
    DESCRIPTION
    Called When dk_body() is called zero or more times between dk_eoh() and dk_eom()
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign() or dk_verify()
    bodyp Pointer to the start of this block of body data.
    len The amount of data pointed to by bodyp.
    NOTES
    • bodyp points to a sequence of bytes. It is not expected to be a C string (a sequence of characters that is terminated by '\0').

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_header.html0000644000175000017500000000345310052245104020673 0ustar madhackmadhack dk_header()

    dk_header()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_header(
    	DK *dk,
    	char *headerf,
    	char *headerv
    );
    
    Handle a message header.
    DESCRIPTION
    Called When dk_header() is called zero or more times between dk_sign() or dk_verify() and dk_eoh(), once per message header.
    ARGUMENTS
    ArgumentDescription
    dk Per-message DK handle.
    headerf Header field name.
    headerv Header field value. The content of the header may include folded white space (i.e. multiple lines with following white space).
    NOTES
    • None.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_gethdrs.html0000644000175000017500000000441410077266212021113 0ustar madhackmadhack dk_gethdrs()

    dk_gethdrs()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_getsig(
    	DK *dk,
            unsigned char *buf,
            size_t len
    );
    
    Retrieve the list of headers that were included in the computation of this signature. They will be written to buf, separated by colons. This should be included in the header added to the message being signed.
    DESCRIPTION
    Called When dk_gethdrs() is called after dk_eom() when dk is a signing handle, i.e. one returned by an earlier call to dk_sign().
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign().
    buf A buffer into which the list of headers should be stored.
    len Number of bytes available at buf.
    NOTES
    • It is an error to call this function with a handle that was created using dk_verify().
    • This function is a local addition to the formal API specification and is experimental only. It may not appear in other implementations.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_alg_t.html0000644000175000017500000000257710052245104020537 0ustar madhackmadhack dk_alg_t

    dk_alg_t

    DESCRIPTION
    Purpose A dk_alg_t is a value from an enumerated list of the possible message signing algorithms available. It is passed as a parameter to dk_sign() when selecting a signing algorithm to be used to sign a message. It need not be passed to dk_verify() as that function will determine the signing algorithm for verification based on the signature on an arriving message.
    Possible Values
    • DK_SIGN_RSASHA1 -- use an RSA-signed SHA1 hash of the message's headers and body
    NOTES
    • None.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_eom.html0000644000175000017500000000353310052245104020222 0ustar madhackmadhack dk_eom()

    dk_eom()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_eom(
    	DK *dk,
            DK_FLAGS *flags
    );
    
    Denote end-of-message for a message.
    DESCRIPTION
    Called When dk_eom() is called after the entire body of the message has been passed to the API via zero or more calls to dk_body().
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign() or dk_verify()
    flags Pointer to a DK_FLAGS object which will be loaded with informational flags when this function returns.
    NOTES
    • None.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk.html0000644000175000017500000000251110052245104017355 0ustar madhackmadhack DK

    DK

    DESCRIPTION
    Purpose A DK handle is returned by successful calls to dk_sign() and dk_verify(), and passed to all of the message processing functions. It contains per-message context-specific information about the message. When processing of the message is complete, it must be destroyed using a call to dk_free().
    NOTES
    • More than one DK handle may exist at any given time. There is no memory shared between these handles, so two different handles may be concurrently accessed in separate threads.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_verify.html0000644000175000017500000000453410052245104020750 0ustar madhackmadhack dk_verify()

    dk_verify()

    SYNOPSIS
    #include <dk.h>
    DK *dk_verify(
    	DK_LIB *libhandle,
    	const char *id,
    	void *memclosure,
    	DK_STAT *statp
    );
    
    Create a new handle for verifying a (possibly) signed message.
    DESCRIPTION
    Called When dk_verify() is called when preparing to process a new message that may be signed already in order to be able to verify its contents against the signature.
    ARGUMENTS
    ArgumentDescription
    libhandle DomainKeys library instance handle, returned by an earlier call to dk_init().
    id An opaque, printable string for identifying this message, suitable for use in logging or debug output.
    memclosure Opaque memory closure, passed directly to the caller-provided malloc() and/or free() replacement functions.
    statp Pointer to a DK_STAT object which receives the completion status of this operation.
    NOTES
    • The handle returned by this function may not be used in a later call to dk_getsig().

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_free.html0000644000175000017500000000363410764722454020407 0ustar madhackmadhack dk_free()

    dk_free()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_free(
    	DK *dk
    );
    
    Release resources associated with a signing or verifying handle.
    DESCRIPTION
    Called When dk_free() must be passed a handle returned by dk_sign() or dk_verify()
    Effects Releases resources that were allocated and assigned to the handle dk when it was returned by dk_sign() or dk_verify(). The handle dk may not be reused.
    ARGUMENTS
    ArgumentDescription
    dk A DK handle returned by a previous call to dk_sign() or dk_verify().
    RETURN VALUES
    • DK_STAT_OK -- operation was successful
    NOTES None.

    Copyright (c) 2004, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_eoh.html0000644000175000017500000000345610052245104020221 0ustar madhackmadhack dk_eoh()

    dk_eoh()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_eoh(
    	DK *dk
    );
    
    Denote end-of-headers for a message.
    DESCRIPTION
    Called When dk_eoh() is called when the delimiter between the message's headers and its body is encountered.
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign() or dk_verify()
    NOTES
    • This function may return DK_STAT_NOSIG if no signature was present in the message headers. This is simply advisory; you must continue executing down to the dk_eom() call to determine whether or not a signature should have been present.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_timeout.html0000644000175000017500000000454510153433367021150 0ustar madhackmadhack dk_timeout()

    dk_timeout()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_timeout(
    	DK *dk,
            int new,
            int *old
    );
    
    Sets and/or retrieves the timeout used when waiting for DNS replies.
    DESCRIPTION
    Called When dk_timeout() can be called at any time after acquiring a transaction handle from either dk_sign() or dk_verify().
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign() or dk_verify.
    new The new timeout to use, in seconds. When first initialized, the handle contains a default of 5 seconds. A value of 0 means "wait forever".
    old An optional pointer to an int which will receive the current timeout. If this is not of interest, pass NULL.
    NOTES
    • This function only applies when using the asynchronous resolver package. When using the native resolver, no timeout facility is available.
    • This function is a local addition to the formal API specification and is experimental only. It may not appear in other implementations.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_close.html0000644000175000017500000000336310764722443020570 0ustar madhackmadhack dk_close()

    dk_close()

    SYNOPSIS
    #include <dk.h>
    void dk_close(
    	DK_LIB *lib
    );
    
    Release resources associated with a library instance.
    DESCRIPTION
    Called When dk_close() must be passed a handle returned by dk_init()
    Effects Releases resources that were allocated and assigned to the handle lib when it was returned by dk_init(). The handle lib may not be reused.
    ARGUMENTS
    ArgumentDescription
    lib A DK_LIB handle returned by a previous call to dk_init().
    RETURN VALUES None.
    NOTES None.

    Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_flags.html0000644000175000017500000000242010052245104020530 0ustar madhackmadhack DK_FLAGS

    DK_FLAGS

    DESCRIPTION
    Purpose A DK_FLAGS object is a set of flags (currently implemented as a bitmask within an int) which provide information returned by a call to dk_eom().
    Possible Bits
    • DK_FLAG_SIGNSALL -- the domain claims to sign all mail it sends
    • DK_FLAG_TESTING -- the domain claims to be using DomainKeys in a test-only mode, and verification results should not be considered authoritative
    NOTES
    • None.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_stat.html0000644000175000017500000000510710057371272020427 0ustar madhackmadhack DK_STAT

    DK_STAT

    DESCRIPTION
    Purpose A DK_STAT is a return value from libdk functions, either as a direct return value or a returned parameter.
    Possible Values
    • DK_STAT_OK -- successful completion
    • DK_STAT_BADSIG -- signature did not match headers and body
    • DK_STAT_NOSIG -- no signature present
    • DK_STAT_NOKEY -- no key available for verifying
    • DK_STAT_CANTVRFY -- can't get key for verifying
    • DK_STAT_SYNTAX -- message is not in valid syntax
    • DK_STAT_NORESOURCE -- resource unavailable
    • DK_STAT_INTERNAL -- internal error
    NOTES
    • DK_STAT_NOKEY is returned if the DNS query for a selector (public key) record returned with NXDOMAIN, i.e. the record does not exist; this should be considered a permanent failure.
    • DK_STAT_CANTVRFY is returned if the DNS query for a selector (public key) record timed out or suffered some other kind of transient failure; verification can be re-attempted later.
    • DK_STAT_SYNTAX is returned to indicate required data could not be extracted from the arriving message to be signed or verified, or if a selector (public key) record returned from a DNS query could not be parsed (e.g. corrupted, wrong format, etc.).
    • DK_STAT_NOSIG can be returned early, i.e. from dk_eoh(), if no signature was found on a message which is being verified. See that function's description for further details.
    • DK_STAT_INTERNAL can be returned on system error (e.g. malloc() failure), or if functions provided by this API are called in the incorrect order (e.g. dk_getsig() before dk_eom(), or dk_eoh() before dk_header(), etc.).

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/index.html0000644000175000017500000001171010764722465020113 0ustar madhackmadhack Sendmail DomainKeys Library

    Sendmail DomainKeys Library

    Introduction

    DomainKeys is a specification for signing messages at the domain level using simple crypto methods to prevent the falsification of sender domains. While the most obvious application of this is to defense against spam, other applications can make use of this capability.

    The specification of DomainKeys is contained in an Internet Draft from Yahoo!, Inc. More information can be found here.

    This API (libdk) allows an application to sign or verify messages according to the DomainKeys proposed standard. Also provided is an implementation of a filter, using Sendmail's milter package, that uses libdk to implement this facility.

    Data Types

    Data Type Description
    DK A signing/verifying context for a message.
    dk_alg_t A signature generation/verification method.
    dk_canon_t A canonicalization method.
    DK_FLAGS Flags; a union the following macros, representing flag bits:
    DK_LIB An instance of the libdk service.
    dk_query_t Query method.
    dk_sigkey_t Private key data.
    DK_STAT Return value/status.

    Functions

    Function Description
    Administration
    dk_close() Shut down an instance of the DomainKeys service.
    dk_init() Initialize an instance of the DomainKeys service.
    Signing
    dk_sign() Allocate a new DomainKeys handle for signing a message.
    dk_getsig() Generate and return a signature.
    dk_gethdrs() Retrieve a list of headers included in the computation of the signature.
    dk_getidentity() Retrieve sender identity information extracted from headers.
    Verifying
    dk_verify() Allocate a new DomainKeys handle for verifying a message.
    dk_reportinfo() Retrieve information required to generate a verification failure report. (EXPERIMENTAL)
    dkim_geterror() Retrieve the most recent internal error message associated with a DK handle.
    Processing
    dk_header() Process a header.
    dk_eoh() Identify end of headers.
    dk_body() Process a body chunk.
    dk_eom() Identify end of message.
    Utility
    dk_options() Get or set library options.
    dk_timeout() Get or set DNS timeout value.
    rfc2822_mailbox_split() Parse an RFC2822 header, e.g. From:, to get user and domain.
    Cleanup
    dk_free() Destroy a per-message handle of the DomainKeys service.

    An overview of the general use of this API is available here. dk-milter-1.0.0.dfsg/libdk/docs/dk_sigkey_t.html0000644000175000017500000000214610052245104021257 0ustar madhackmadhack dk_sigkey_t

    dk_sigkey_t

    DESCRIPTION
    Purpose A dk_sigkey_t points to the PEM-formatted private key to be used to sign messages. (For now, it is simply a pointer to a string of type unsigned char.)
    NOTES
    • The calling application should read the PEM file into memory and pass it in as this data type. Carriage return and newline characters (ASCII 13 and 10, respectively) should not be stripped.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_init.html0000644000175000017500000000516010052245104020403 0ustar madhackmadhack dk_init()

    dk_init()

    SYNOPSIS
    #include <dk.h>
    DK_LIB *dk_init(
    	void *(*mallocf)(void *closure, size_t nbytes),
    	void (*freef)(void *closure, void *p)
    );
    
    Create a new instantiation for the DomainKeys service, for use signing or verifying messages.
    DESCRIPTION
    Called When dk_init() is called when setting up the application. It is used when generating per-message handles for signing and verifying, and is used to declare optional alternate memory allocate and free functions.
    ARGUMENTS
    ArgumentDescription
    malloc Optional alternate memory allocation function. It must take two parameters, a void pointer which is the memory closure specified in calls to dk_sign() or dk_verify(), and one the number of bytes to be allocated. This allows memory allocations for a specific message to be made within the same closure.
    freef Optional alternate memory release function. It must take two parameters, a void pointer which is the memory closure specified in calls to dk_sign() or dk_verify(), and one the pointer to memory to be freed. This allows memory allocations for a specific message to be made within the same closure.
    NOTES

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_getsig.html0000644000175000017500000000372710052245104020731 0ustar madhackmadhack dk_getsig()

    dk_getsig()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_getsig(
    	DK *dk,
            unsigned char *buf,
            size_t len
    );
    
    Compute and retrieve the signature for a message.
    DESCRIPTION
    Called When dk_getsig() is called after dk_eom() when dk is a signing handle, i.e. one returned by an earlier call to dk_sign().
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign().
    buf A buffer into which the base64-encoded signature should be stored.
    len Number of bytes available at buf.
    NOTES
    • It is an error to call this function with a handle that was created using dk_verify().

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_canon_t.html0000644000175000017500000000310010106531701021052 0ustar madhackmadhack dk_canon_t

    dk_canon_t

    DESCRIPTION
    Purpose A dk_canon_t is a value from an enumerated list of the possible message canonicalization algorithms available. It is passed as a parameter to dk_sign() when selecting a canonicalization algorithm to be used when preparing a message body for signing. It need not be passed to dk_verify() as that function will determine the canonicalization algorithm for verification based on the signature on an arriving message.
    Possible Values
    • DK_CANON_NOFWS -- "nofws" canonicalization as specified in the DomainKeys specification
    • DK_CANON_SIMPLE -- "simple" canonicalization as specified in the DomainKeys specification
    NOTES
    • None.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/overview.html0000644000175000017500000001242510764722556020657 0ustar madhackmadhack Overview

    Overview

    To sign a message under DomainKeys, make the following calls:
    1. lib = dk_init();
      • initialize an instance of the library
      • this must be done once before any of the other calls are made
      • this needs to be called once when the application is started, but its result can be reused at the start of processing of each message
      • the remaining steps can use the same value of lib, even in multiple threads and over multiple messages
    2. dk = dk_sign(lib, ...);
      • initialize a handle set up for signing the message
      • at this point a canonicalization, signing algorithm and secret key are selected by the caller
    3. stat = dk_header(dk, ...);
      • pass a header to libdk
      • this should be done once for each header that should be included in computation of the signature (currently all of them)
    4. stat = dk_eoh(dk);
      • notify libdk that the end of this message's headers has been reached
    5. stat = dk_body(dk, ...);
      • pass to libdk a chunk of the body that should be included in computation of the signature (currently all of it)
      • repeat for each body chunk that arrives
    6. stat = dk_eom(dk, ...);
      • notify libdk that the end of this message has been reached
      • get back any informational flags of interest from libdk
    7. stat = dk_getsig(dk, ...);
      • compute the base64-encoded signature for the message
      • the signing algorithm was selected in the call to dk_sign() above
      • the data returned here coupled with the parameters to the dk_sign() call make up the content of the signature that needs to be prepended to the message according to the DomainKeys specification
    8. stat = dk_free(dk);
      • free resources related to this message
    9. stat = dk_close(dk);
      • free resources related to this library instance

    To verify a message under DomainKeys, make the following calls:
    1. lib = dk_init();
      • initialize an instance of the library
      • this must be done once before any of the other calls are made
      • this needs to be called once when the application is started, but its result can be reused at the start of processing of each message
      • the remaining steps can use the same value of lib, even in multiple threads and over multiple messages
    2. dk = dk_verify(lib, ...);
      • initialize a handle set up for verifying the message
      • the canonicalization and signing algorithms and public key were selected by the agent that signed the message, and so don't need to be provided here
    3. stat = dk_header(dk, ...);
      • pass a header to libdk
      • this should be done once for each header that should be included in computation of the digest to be verified (currently all of them)
    4. stat = dk_eoh(dk);
      • notify libdk that the end of this message's headers has been reached
    5. stat = dk_body(dk, ...);
      • pass to libdk a chunk of the body that should be included in computation of the digest to be verified (currently all of it)
    6. stat = dk_eom(dk, ...);
      • notify libdk that the end of this message has been reached
      • get back any informational flags of interest from libdk
      • see if stat is DK_STAT_OK (verification OK) or DK_STAT_BADSIG (verification failed)
    7. stat = dk_free(dk);
      • free resources related to this message
    8. stat = dk_close(dk);
      • free resources related to this library instance

    One application, having called dk_init() once, can call dk_sign() or dk_verify() more than once each, and furthermore can have more than one signing/verifying handle in existence at any given time. dk-milter-1.0.0.dfsg/libdk/docs/dk_query_t.html0000644000175000017500000000273610764721422021152 0ustar madhackmadhack dk_query_t

    dk_query_t

    DESCRIPTION
    Purpose A dk_query_t represents the type of query to be done when validating messages. Normally the query type is determined by the library when processing a signature header, but it is possible to force a particular query method using the dk_options() function.
    NOTES
    • The supported query types are:
      • DK_QUERY_DNS -- keys should be retrieved from the DNS as specified in RFC4870; this is the default
      • DK_QUERY_FILE -- keys should be retrieved from a text file; the text file is specified by using dk_options() to set the DK_OPTS_QUERYINFO library value

    Copyright (c) 2004, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_options.html0000644000175000017500000000775710764721405021166 0ustar madhackmadhack dk_options()

    dk_options()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_options(
    	DK *dk,
            int op,
            int opt,
            void *ptr,
    	size_t size
    );
    
    Sets or retrieves options to alter the behaviour of certain aspects of the library's operation.
    DESCRIPTION
    Called When dk_options() can be called at any time after acquiring a transaction handle from either dk_sign() or dk_verify(). However, the impact of certain options may not take effect after specific points in a transaction.
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign() or dk_verify.
    op Either DK_OP_SETOPT to set the value of the desired library option, or DK_OP_GETOPT to retrieve the current library option.
    opt A mnemonic symbol that indicates which library option is to be changed or retrieved. The list of valid options is below.
    ptr A pointer to a variable which contains the desired new value of the option to be changed, or which will receive the current value of the option specified.
    size The size in bytes of the variable referenced by ptr.
    NOTES
    • The supported options are:
      • DK_OPTS_FLAGS -- ptr points to an unsigned integer which is actually a mask of flag bits as defined below
      • DK_OPTS_QUERYINFO -- ptr points to a buffer no larger than MAXPATHLEN bytes which contains information used by special query methods; see dk_query_t for details
      • DK_OPTS_QUERYMETHOD -- ptr points to a dk_query_t containing the query method to be used for all verification operations
      • DK_OPTS_TMPDIR -- when used with DK_LIBFLAGS_TMPFILES, temporary files will be left on disk for analysis rather than cleaned up upon completion of the transaction
    • The supported flags are:
      • DK_LIBFLAGS_HDRLIST -- when signing, group like headers together during canonicalization so that there is no duplication in the header list ("h=") portion of the signature
      • DK_LIBFLAGS_KEEPFILES -- when used with DK_LIBFLAGS_TMPFILES, temporary files will be left on disk for analysis rather than cleaned up upon completion of the transaction
      • DK_LIBFLAGS_TMPFILES -- create temporary files on disk for debugging or reporting purposes

    Copyright (c) 2004, 2006, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/docs/dk_getidentity.html0000644000175000017500000000523010152704637022003 0ustar madhackmadhack dk_getidentity()

    dk_getidentity()

    SYNOPSIS
    #include <dk.h>
    DK_STAT dk_getidentity(
    	DK *dk,
            char *hname,
    	size_t hnamelen,
            char *hval,
            size_t hvallen
    );
    
    Retrieve the apparent signer's identity and/or the name of the header used to determine the identity.
    DESCRIPTION
    Called When dk_getidentity() is called after dk_eoh() to get the header that represents the signer's identity, and the decommented value of that header.
    ARGUMENTS
    ArgumentDescription
    dk Message-specific handle, returned by dk_sign() or dk_verify.
    hname A pointer to a character buffer into which should be written the name of the header from which the signer's identity was taken. Can be NULL if this information is not needed by the caller.
    hnamelen The number of bytes available at hname.
    hval A pointer to a character buffer into which should be written the value, with RFC2822 comments removed, of the header from which the signer's identity was taken. Can be NULL if this information is not needed by the caller.
    hvallen The number of bytes available at hval.
    NOTES
    • This function is a local addition to the formal API specification and is experimental only. It may not appear in other implementations.

    Copyright (c) 2004 Sendmail, Inc. and its suppliers. All rights reserved.
    By using this file, you agree to the terms and conditions set forth in the LICENSE.
    dk-milter-1.0.0.dfsg/libdk/t-cleanup.c0000644000175000017500000000100310764722641017210 0ustar madhackmadhack/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. */ #ifndef lint static char t_cleanup_c_id[] = "@(#)$Id: t-cleanup.c,v 1.1 2008/03/09 08:53:53 msk Exp $"; #endif /* !lint */ /* system includes */ #include #include /* libdkim includes */ #include "t-testdata.h" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { assert(unlink(KEYFILE) == 0); return 0; } dk-milter-1.0.0.dfsg/libdk/Makefile0000644000175000017500000000045710014506401016606 0ustar madhackmadhack# $Id: Makefile,v 1.1 2004/02/17 21:52:01 msk Exp $ SHELL= /bin/sh BUILD= ./Build OPTIONS= $(CONFIG) $(FLAGS) all: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ clean: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ install: FRC $(SHELL) $(BUILD) $(OPTIONS) $@ fresh: FRC $(SHELL) $(BUILD) $(OPTIONS) -c FRC: dk-milter-1.0.0.dfsg/Build0000755000175000017500000000051010057143764015054 0ustar madhackmadhack#!/bin/sh # Copyright (c) 1999 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set # forth in the LICENSE file which can be found at the top level of # the sendmail distribution. # # # $Id: Build,v 1.1 2004/06/01 18:16:20 msk Exp $ exec make OPTIONS="$*" dk-milter-1.0.0.dfsg/RELEASE_NOTES0000644000175000017500000004275110766324514016060 0ustar madhackmadhack DK-MILTER RELEASE NOTES $Id: RELEASE_NOTES,v 1.165 2008/03/13 22:23:08 msk Exp $ This listing shows the versions of the dk-milter package, the date of release, and a summary of the changes in that release. Bug and feature request (RFE) numbers that start with "SF" were logged via Sourceforge (http://www.sourceforge.net) trackers. Those not so labelled were logged internally at Sendmail, Inc. 1.0.0 2008/03/13 Use the current Authentication-Results: format (the -13 draft). Patch from S. Moonesamy of Eland Systems. Add improved mlfi_negotiate() function code, copied from dkim-milter, which does things like symbol requesting and more intelligent option negotiation. Patch from S. Moonesamy of Eland Systems. Add hash buffering, copied from libdkim. Patch from S. Moonesamy of Eland Systems. Fix bug #SF1736559: in_addr_t is not universal. Problem reported by Terry White. Fix bug #SF1763715: Fix string management in mlfi_eoh() with respect to mctx_domain, which could be left pointing to garbage when using domain wildcarding. Problem noted by Ronald Huizer. Activate _FFR_MULTIPLE_KEYS. LIBDK: Copy the library options structure from libdkim. LIBDK: Add dk_close(). LIBDK: Feature request #SF1872270: Rename parameters called "new" in dk.h so that C++ compilers don't complain. Requested by Paul Macintosh. LIBAR: Eliminate a possible race condition in ar_dispatcher(). LIBAR: Timeouts passed to select() can't be bigger than 10^8. Problem noted by S. Moonesamy of Eland Systems. LIBAR: Fix bug #SF1852618: Handle default case of no "nameserver" lines in /etc/resolv.conf. Problem noted by Mike Markley of Bank of America. LIBAR: Plug descriptor and memory leaks in ar_shutdown(). BUILD: Copy the unit test structure from libdkim and add a few basic unit tests. 0.6.0 2007/05/31 Fix bug #SF1728696: Repair message corruption occurring when a message body spams multiple milter writes. Reported by Eric Singer. Patch #SF1705006: Fix X-header malformation. LIBAR: Fix bug #SF1537457: Add proper support for IPv6 nameservers. Reported by Mark Martinec. BUILD: Copy the consolidated build system from the dkim-milter package. Activate the following FFRs: _FFR_LOG_SSL_ERRORS _FFR_QUARANTINE _FFR_REPORTINFO 0.5.0 2007/04/10 Copy several enhancements from the latest dkim-milter update: o Support for 8.14 (milter v2) and the leading space patch from dkim-milter. o Fixes/enhancements under POPAUTH. o Pass the correct length variable to RSA_sign() so that the value returned is sane on 64-bit platforms. o _FFR_ANTICIPATE_SENDMAIL_MUNGE o Feature request #SF1497801: _FFR_QUARANTINE Fix bug #SF1541450: Correct header selection in dk_hdrsigned(). Reported by Mark Martinec. LIBDK: Fix bug #SF1537918: Add dk_geterror() to retrieve additional diagnostic data from the API when a function call returns DK_STAT_INTERNAL or something else whose cause isn't readily apparent. Copied from libdkim. LIBAR: Block signals that should be caught and handled elsewhere, such as in libmilter. 0.4.2 2007/03/13 Fix bug #SF1509093, SF1611082: Set group ID as well as user ID when "-u" is used on the command line. Patch from Vincent Rivellino. Fix bug #SF1514447: Re-query for the job ID in mlfi_eom() to accomodate postfix's milter implementation. Copied from dkim-filter; requested by Jakob Schlyter. Fix bug #SF1541439: Fix mis-canonicalization of skipped headers in "nofws" mode. Reported by Mark Martinec. Fix bug #SF1541789: Stop spurious syntax errors on unsigned messages. Problem reported by S. Moonesamy of Eland Systems. 0.4.1 2006/06/14 LIBDK: Properly handle key and policy records that don't have whitespace after semicolons. LIBDK: In dk_eom(), return DK_STAT_SYNTAX if dk_skipbody is set. Failing to do so means a message with a signature header below which there is no sender header will report a bogus success status. Problem noted by Lennert Buytenhek. 0.4.0 2006/05/19 Remove spurious CRLFs injected into canonicalization when multiple body chunks arrive from the MTA. Patch from Suzuki Takahiko of Internet Initiative Japan, Inc. If _FFR_REPORTINFO is enabled, don't call dkf_report() if no DomainKeys context was ever created for a message. Simplify dk_sterilize() a little, and handle failures from it. Problem reported by Fredrik Pettai. RFC2822 doesn't require any recipient headers, so remove those checks inside _FFR_REQUIRED_HEADERS. Fix bug #SF1485119: Canonicalize in the correct order when not using "-H" on the command line. Problem noted by S. Moonesamy of Eland Systems. Activate _FFR_MACRO_LIST and _FFR_EXTERNAL_IGNORE_LIST. LIBDK: New flag DK_OPTS_HDRLIST for dk_options(). 0.3.4 2006/05/02 If _FFR_REPORTINFO is enabled, send reports on all failures, not just those which aren't in test mode. Ignore unknown tags in keys and policies, rather than returning an error. LIBDK: Return an error if the signing function returned success but also reported a zero-length signature. Reported by S. Moonesamy of Eland Systems. LIBAR: Add a timeout to the I/O wait so that retransmissions actually get done while waiting for activity. 0.3.3 2006/03/13 Fix test mode check at the end of mlfi_eom(), which was overriding any configuration settings from the command line. Reported by Arkadi Poliakevitch of Invidi Technologies. Copy the value of -C before parsing it so the output of "ps" doesn't get munged. Reported by Arkadi Poliakevitch of Invidi Technologies. Fix "-o", which wasn't actually working at all. Reported by Ben Lentz. Add _FFR_LOG_SSL_ERRORS which sends to syslog errors reported by the OpenSSL libraries. 0.3.2 2005/12/12 Patch a small but definite memory leak. Reported by Ray Krebs of eBay. 0.3.1 2005/12/02 Tolerate "b=" in signature headers at places other than the end of the signature (and, in fact, other things at the end of the signature). Reported by Jason Long. (Bug SF1234164) Don't reject or report about messages which fail verification when the sending domain advertises that it's in test mode. Patch from Adrian Havill. Fixes to POPAUTH compilation from S. Moonesamy of Eland Systems. Allow "-d" to specify a list from which domains should be read, and allow wildcarding in domain names. Requested by Ray Krebs of eBay. (Feature request SF1312453) Add "-o" command line option to allow certain headers to be omitted from signing operations. Suggested by Ben Lentz. (Feature request SF1314350) LIBAR: Fix a build issue introduced in the last release. 0.3.0 2005/04/28 Properly terminate pointer arrays built from command line arguments. Problem noted by Dick St. Peters of NetHeaven. Adjust position of optional domain name comment on output from gentxt.csh. Requested by Scott Grayban. (RFE SF1051288) Pass mail that has no From: header or Sender: header. Previously only the From: header was checked. Correctly report which header and value was used to do verification. Reported by S. Moonesamy of Eland Systems. (Bug SF1181850) Support for Sleepycat DB version 4. Based on a patch from Adrian D. Havill. Do a better job passing error information up from libar to the calling functions and logging it. To this end, add the DK_DEBUG "d" flag which causes libdk to log errors reported by libar. Activate _FFR_AUTH_RESULTS, to match the new DomainKeys draft. Activate _FFR_POPAUTH; now you compile with POPAUTH, and make sure the build can find the appropriate includes and libraries. This also adds the "-U" command line option to specify the location of the POP-before-SMTP database. LIBAR: Make a more concerted effort to report errors up to callers. 0.2.7 2005/03/11 Detect senders without domain names (e.g. "postmaster@") and reject them. LIBAR: Fix up some linked list shenanigans that could cause loops and other problems. 0.2.6 2005/02/11 Ignore spaces in wrapped "h=" sections of signature headers. 0.2.5 2005/02/07 Output long "h=" sections of signature headers in a more palatable way. (RFE SF1086264) Add new "-b" command line switch for limiting the filter to sign or verify only operations. (RFE SF1077832) 0.2.4 2004/12/08 Add new "-T" command line switch for controlling DNS timeouts when using the asynchronous resolver package. Fix policy record parsing so that values aren't skipped when they end at a NULL rather than a semi-colon. Discard "unknown-msgid" logging or header values, since it's actually the absence of the job ID being logged. (RFE SF1071960) Update the Authentication-Results: header content to match the current specification. (_FFR_AUTH_RESULTS) LIBDK: Improved handling of syntax errors and NULL-terminated values in zone records, and some size and NULL checks. Patch from shoon@dreamwiz.com. LIBDK: Only parse the first DomainKey-Signature: header found. Patch from shoon@dreamwiz.com. LIBDK: Return a "can't verify" error from dk_eoh() if the signer's domain could not be determined from the headers. Patch from shoon@dreamwiz.com. LIBDK: Add dk_options(), which is required to get _FFR_REPORTINFO working. LIBDK: Add dk_timeout() for new "-T" command line switch. Portability: Fixes for Solaris 10 (and earlier). Machine access courtesy of J.D. Bronson of Aurora Health Care Information Services. (Bug SF1068155) New FFR: REPORTINFO -- if a site policy contains a reporting address ("r=" parameter), optionally send reports about verification failures to that address 0.2.3 2004/10/22 Add optional command line argument to gentxt.csh to include a domain name comment on output. Requested by Scott Grayban. (RFE SF1051288) More strict command line argument parsing. Fix a linked list problem that would cause the filter to spin on startup. Reported by Scott Grayban. (_FFR_MULTIPLE_KEYS) Fixes to subdomain signing from Thorvald Natvig. (Patch SF1050425) LIBDK: Call res_init() in dk_init() if not using the asynchronous resolver. LIBDK: Don't include the CRLF separating the headers and the body unless the body contains at least one non-blank line. LIBDK: Add dk_reportinfo(). LIBAR: Add ar_setretry() and ar_setmaxretry(), and fail over to other available nameservers if that interval passes without an answer. (Bug SF1027541) New FFR: EXTERNAL_IGNORE_LIST -- optional list of hosts/networks which may send mail as one of our signing domains, but we know about it so don't log it (RFE SF1027562) 0.2.2 2004/09/11 Don't segfault when "-i" refers to an empty list. Don't run off the end of the macro list when creating/scanning it (_FFR_MACRO_LIST). Improve handling when res_query() returns -1 by checking h_errno. (Bug SF1026225) Automatically include braces around macro queries to make life easier when specifying macro lists (_FFR_MACRO_LIST). Minor build and documentation fixes. (Bugs SF1021948, SF1020931) LIBDK: Fix processing of unsigned messages, which were incorrectly logging syntax errors. LIBDK: Skip the body processing and hashing on unsigned messages. LIBDK: Cache the From:/Sender: even if unprotected so that unsigned messages can have their sender policies checked in dk_eoh(). 0.2.1 2004/09/01 Fix a cut-and-paste error that broke the build when REQUIRE_HEADERS is enabled. Reported by S. Moonesamy of Eland Systems. (Bug SF1016105) LIBDK: Report bad format when the selector or domain in a signature header is empty. Portability: Fixes for Solaris builds from Al Smith of aeschi.ch.eu.org. New FFRs: AUTH_RESULTS -- use the proposed Auth-Results: header instead of the original DomainKey-Status: header MACRO_LIST -- optional list of macros and values to be checked when making the sign vs. verify decision (RFE SF1015642) 0.2.0 2004/08/23 Support granularity, "nofws" canonicalization, revoked keys, and other changes as per the updated ("base-01") DomainKeys draft. Remove "blake", "sendmail" and "headerlist" canonicalizations. Fix a compile time bug in the inet6 code. From Graham Murray of Webywayone. When in autorestart mode, write the process ID of the parent, not the child, to the pid file. Don't segfault when sendmail is invoked with "-bs" mode, which causes mlfi_connect() to get a NULL "ip" parameter. Propagate termination signal to the child when in autorestart mode. Route the standard descriptors to /dev/null and call setsid() after the initial fork() in any mode. Zero out and deallocate the private key(s) before shutdown. Don't create temporary files any more, unless requested to do so for debugging. Add "-D" command line option to sign subdomains. New FFRs: FLUSH_HEADERS -- optionally delete existing DomainKey headers Activated FFRs: SIGN_SUBDOMAINS TEMP_FILES_OPTIONAL 0.1.17 2004/08/08 Allow IPv6 addresses for the "-i" option. Requested by Graham Murray of Webywayone. (RFE SF999896) New FFRs: REQUIRE_HEADERS -- require mandatory RFC2822 headers to sign or verify. Suggested by Jose Marcio Martins da Cruz of Ecole des Mines de Paris. (RFE SF999291) TEMP_FILES_OPTIONAL -- don't create temporary files unless requested by debugging options; instead, hand them directly to the hashing algorithm. (RFE SF991203) 0.1.16 2004/07/30 Skip body and EOM processing if at EOH we know for sure there will be no signing or verifying going on. (RFE SF991210) Print out active FFRs as part of -V output. Under "headerlist" canonicalization, if no header list was provided, assume all headers were included in the signature. Replace calls to inet_ntoa() with calls to a thread-safe version of that function. Since there is actually no default for the "q=" part of the signature header, always put a string there. New FFRs: POPAUTH -- authorize clients for signing based on a "popb4smtp" database. Patch provided by S. Moonesamy of Eland Systems. SELECT_CANONICALIZATION - select canonicalization via a special header. Proposed by Jim Fenton. (RFE SF996949) Portability: Fixes for Solaris 2.7. 0.1.15 2004/07/22 Copy the value of "-d" before parsing it, so that all of the domains being signed get logged, not just the first one. (Bug SF989735) Make the usage message more explicit about the fact that the values of "-a" and "-i" are files, not addresses. (Bug SF989737) Use {auth_type} instead of {auth_author} to determine whether or not a client authenticated. (Bug SF995333) Avoid a segmentation fault when "-s" is not specified. Consult the DK_TMPDIR environment variable for a preferred location for temporary files. (RFE SF991145) Signature header aesthetics. Suggested by Al Smith of aeschi.ch.eu.org. (RFE SF989240) Add "headerlist" canonicalization. LIBDK: It was possible for a BIO handle to be allocated and never freed through some code paths in dk_eom() and dk_getsig(). Problem noted by Kai Zhu. (Bug SF995376) 0.1.14 2004/07/07 Log command line arguments at startup. Fixes to debug mode. New FFRs: MULTIPLE_KEYS - supply multiple keys for signing (RFE SF974374) SIGN_SUBDOMAINS - sign subdomains as well as listed domains (RFE SF965524) 0.1.13 2004/06/19 When unable to determine the sender's domain, report "bad format" in the DomainKey-Status: header rather than temp-failing the message. (Bug SF975599) Portability: Fixes for Solaris 2.6 build from Al Smith of aeschi.ch.eu.org. 0.1.12 2004/06/16 Support for CNAME recursion. This required a change to the parameter list for ar_addquery(). (Bug SF972813) Set the DNS query timeout on calls to ar_addquery(), not on calls to ar_waitreply(). Take two -- Don't log "external host attempted to send as" for other than our signing domains. LIBAR: When reacting to timeouts in ar_waitreply(), be more correct about whether returning AR_STAT_NOREPLY or AR_STAT_EXPIRED. 0.1.11 2004/06/11 The package no longer needs to be unpacked in the middle of the sendmail Open Source distribution in order to be built. However, OpenSSL and libmilter are required and must be available. Don't log "external host attempted to send as" for other than our signing domains. Add "blake" canonicalization. LIBAR: Avoid memory allocation loops when res_mkquery() returns -1 for reasons other than the buffer being too small. Instead, if a 32K buffer isn't big enough, give up. 0.1.10 2004/06/04 Require a domain name match even if the message arrived on an approved submission port. Reported by S. Moonesamy of Eland Systems. (Bug SF966671) 0.1.9 2004/06/03 Add "-m" option to specify daemon submission ports whose mail should always be signed. Suggested by S. Moonesamy of Eland Systems. (RFE SF965525) LIBDK: Add a much better public RFC2822 header parsing function. (Bug SF965122) 0.1.8 2004/06/02 Rename "-c" (configure) option to "-C". Add new "-c" option to select the canonicalization method to use when signing messages. The DomainKeys-Signature: header selects the method to use when verifying. LIBDK: Return DK_STAT_INTERNAL if API functions are used out-of-order in the calling application. LIBDK: Detail added to documentation of DK_STAT. LIBDK: Tweaks to "sendmail" canonicalization. 0.1.7 2004/06/01 Only sign mail from "internal" hosts, i.e. the loopback address or any connection that authenticated; also add "-i" command line option, allowing definition of additional hosts or netblocks as "internal". Reported by S. Moonesamy of Eland Systems. 0.1.6 2004/05/31 Add "gentxt.csh" to automate generation of keys and DNS records. Portability: Fixes for Solaris and HP/UX. 0.1.5 2004/05/29 LIBAR: TCP mode error handling fixes. LIBDK: Handle error returns from ar_addquery(). 0.1.4 2004/05/28 Initial public open source release. dk-milter-1.0.0.dfsg/FEATURES0000644000175000017500000000324010627615270015232 0ustar madhackmadhack F E A T U R E S F O R F U T U R E R E L E A S E In the source code for this package may be one or more segments of code that are disabled, as they are slated for future release (FFR). These are generally unreleased features, or can be new algorithms for existing features. They are untested and currently unsupported, and generally formally become part of the released software in the next revision. There may or may not be documentation for them outside of this file. To enable an FFR in the source code, find the feature you want to use in the list below and arrange to enable that feature at build time by adding -D_FFR_ to the build. For example, to add the WIDGET feature, you would add -D_FFR_WIDGET to the build. You would do this by adding a line to Makefile.m4 that reads: APPENDDEF(`confENVDEF', `-D_FFR_WIDGET') Feature Name Description ANTICIPATE_SENDMAIL_MUNGE When canonicalizing headers, anticipate the minor rewrites the sendmail MTA is likely to do. (dk-filter) FLUSH_HEADERS Delete existing DK headers before delivery. (dk-filter) MULTIPLE_KEYS Adds a new command line option "-k", which changes interpretation of the "-s" to be a list of user@host patterns with matching filenames indicating which key to use to sign messages. (dk-filter) REQUIRED_HEADERS Optionally enforce minimum header requirements per RFC2822. (dk-filter) SELECT_CANONICALIZATION Optionally override the value of the "-c" command line flag by specifying a preferred canonicalization on a special header line. Intended mostly for testing, not production use. (dk-filter) $Revision: 1.18 $, Last updated $Date: 2007/05/31 18:58:00 $ dk-milter-1.0.0.dfsg/site.config.m4.dist0000644000175000017500000000726010765765407017526 0ustar madhackmadhackdnl Build options for dk-milter package dnl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dnl Any options you set here are applied to all subdirectories of this dnl build. Also, you may override or augment the defaults of any of the dnl values described in devtools/README by setting your preferred values dnl in this file. dnl Debug binary dnl dnl If you are encountering coredumps and want to be able to analyze them dnl using something like "gdb", enable this next line by deleting the "dnl" dnl at the front of it. dnl define(`confOPTIMIZE', `-g') dnl libar -- asynchronous resolver library dnl dnl If you want to use the asynchronous resolver library, enable this dnl next line by deleting the "dnl" at the front of it. dnl define(`bld_USE_ARLIB', `true') dnl dnl libar normally uses res_init() or res_ninit() to load the contents dnl of resolv.conf for its use. If neither of these work on your system dnl in multi-threaded programs (e.g. OpenBSD 3.7 and later), then you dnl may need to enable code that parses that file manually. This will dnl also be required if you've got any IPv6 addresses in /etc/resolv.conf. dnl In that case, enable this next line by deleting the "dnl" at the front dnl of it. dnl APPENDDEF(`conf_libar_ENVDEF', `-DAR_RES_MANUAL') dnl POPAUTH -- POP-before-SMTP authentication dnl dnl If you use any POP-before-SMTP authentication, dk-filter can dnl query that database to see if a client sending a message for signing dnl is legitimate, enable this next line by deleting the "dnl" at the dnl front of it. dnl APPENDDEF(`conf_dk_filter_ENVDEF', `-DPOPAUTH ') dnl BerkeleyDB -- Berkeley DB ("Sleepycat") database dnl dnl POPAUTH needs the Berkeley DB library. dnl dnl Sometimes this is built into your libc, but perhaps not, or perhaps dnl you have a newer version that you want to use. If that's the case, dnl edit the following lines as needed and enable the ones that apply dnl by deleting "dnl" from the front of them: dnl APPENDDEF(`confINCDIRS', `-I/usr/local/BerkeleyDB/include ') dnl APPENDDEF(`confLIBDIRS', `-L/usr/local/BerkeleyDB/lib ') dnl APPENDDEF(`confLIBS', `-ldb ') dnl OpenSSL -- cryptography library dnl dnl DK requires several algorithms provided by this library. If necessary, dnl enable these lines by deleting "dnl" from the front of them and edit dnl paths as needed. dnl APPENDDEF(`confINCDIRS', `-I/usr/local/ssl/include ') dnl APPENDDEF(`confLIBDIRS', `-L/usr/local/ssl/lib ') dnl Code For Future Release (FFRs): dnl dnl See the FEATURES file for descriptions of the features available dnl as options. Many of these are untested and/or undocumented, so use dnl at your own risk. To enable one, delete "dnl" from the front of its dnl line. dnl dnl APPENDDEF(`confENVDEF', `-D_FFR_ANTICIPATE_SENDMAIL_MUNGE ') dnl APPENDDEF(`confENVDEF', `-D_FFR_FLUSH_HEADERS ') dnl APPENDDEF(`confENVDEF', `-D_FFR_HASH_BUFFERING ') dnl APPENDDEF(`confENVDEF', `-D_FFR_REQUIRED_HEADERS ') dnl APPENDDEF(`confENVDEF', `-D_FFR_SELECT_CANONICALIZATION ') dnl libmilter -- Sendmail's milter library dnl dnl This must be in the search rules for your compile. If necessary, dnl adjust the paths below and enable the lines by deleting "dnl" from the dnl front of them. dnl APPENDDEF(`bld_dk_filter_INCDIRS', `-I/usr/local/sendmail/include') dnl APPENDDEF(`bld_dk_filter_LIBDIRS', `-L/usr/local/sendmail/lib') dnl smfi_addheader() -- older versions of libmilter dnl dnl If you run a version of libmilter too old to have the smfi_insheader() dnl primitive, you can enable this to have dk-filter use smfi_addheader() dnl instead. It will still work, but it breaks the DKIM specification. dnl To enable this, remove the "dnl" from the front of the line. dnl APPENDDEF(`conf_dk_filter_ENVDEF', `-DNO_SMFI_INSHEADER ') dk-milter-1.0.0.dfsg/Makefile0000644000175000017500000000152510057144503015526 0ustar madhackmadhack# $Id: Makefile.dist,v 1.1 2004/06/01 18:21:55 msk Exp $ SHELL= /bin/sh SUBDIRS= libar libdk dk-filter BUILD= ./Build OPTIONS= $(CONFIG) $(FLAGS) all: FRC @for x in $(SUBDIRS); \ do \ (cd $$x; echo Making $@ in:; pwd; \ $(SHELL) $(BUILD) $(OPTIONS)); \ done clean: FRC @for x in $(SUBDIRS); \ do \ (cd $$x; echo Making $@ in:; pwd; \ $(SHELL) $(BUILD) $(OPTIONS) $@); \ done install: FRC @for x in $(SUBDIRS); \ do \ (cd $$x; echo Making $@ in:; pwd; \ $(SHELL) $(BUILD) $(OPTIONS) $@); \ done install-docs: FRC @for x in $(SUBDIRS); \ do \ (cd $$x; echo Making $@ in:; pwd; \ $(SHELL) $(BUILD) $(OPTIONS) $@); \ done fresh: FRC @for x in $(SUBDIRS); \ do \ (cd $$x; echo Making $@ in:; pwd; \ $(SHELL) $(BUILD) $(OPTIONS) -c); \ done $(SUBDIRS): FRC @cd $@; pwd; \ $(SHELL) $(BUILD) $(OPTIONS) FRC: