1c2aa98e2SPeter Wemm /* 2602a2b1bSGregory Neil Shapiro * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 1406f25ae9SGregory Neil Shapiro #include <sendmail.h> 1540266059SGregory Neil Shapiro 1640266059SGregory Neil Shapiro SM_RCSID("@(#)$Id: util.c,v 8.357 2001/11/28 19:19:27 gshapiro Exp $") 1740266059SGregory Neil Shapiro 18c2aa98e2SPeter Wemm #include <sysexits.h> 1940266059SGregory Neil Shapiro #include <sm/xtrap.h> 2006f25ae9SGregory Neil Shapiro 2140266059SGregory Neil Shapiro /* 22c2aa98e2SPeter Wemm ** ADDQUOTES -- Adds quotes & quote bits to a string. 23c2aa98e2SPeter Wemm ** 2440266059SGregory Neil Shapiro ** Runs through a string and adds backslashes and quote bits. 25c2aa98e2SPeter Wemm ** 26c2aa98e2SPeter Wemm ** Parameters: 27c2aa98e2SPeter Wemm ** s -- the string to modify. 2840266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate result 29c2aa98e2SPeter Wemm ** 30c2aa98e2SPeter Wemm ** Returns: 31c2aa98e2SPeter Wemm ** pointer to quoted string. 32c2aa98e2SPeter Wemm */ 33c2aa98e2SPeter Wemm 34c2aa98e2SPeter Wemm char * 3540266059SGregory Neil Shapiro addquotes(s, rpool) 36c2aa98e2SPeter Wemm char *s; 3740266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 38c2aa98e2SPeter Wemm { 39c2aa98e2SPeter Wemm int len = 0; 40c2aa98e2SPeter Wemm char c; 41c2aa98e2SPeter Wemm char *p = s, *q, *r; 42c2aa98e2SPeter Wemm 43c2aa98e2SPeter Wemm if (s == NULL) 44c2aa98e2SPeter Wemm return NULL; 45c2aa98e2SPeter Wemm 46c2aa98e2SPeter Wemm /* Find length of quoted string */ 47c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 48c2aa98e2SPeter Wemm { 49c2aa98e2SPeter Wemm len++; 50c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 51c2aa98e2SPeter Wemm len++; 52c2aa98e2SPeter Wemm } 53c2aa98e2SPeter Wemm 5440266059SGregory Neil Shapiro q = r = sm_rpool_malloc_x(rpool, len + 3); 55c2aa98e2SPeter Wemm p = s; 56c2aa98e2SPeter Wemm 57c2aa98e2SPeter Wemm /* add leading quote */ 58c2aa98e2SPeter Wemm *q++ = '"'; 59c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 60c2aa98e2SPeter Wemm { 61c2aa98e2SPeter Wemm /* quote \ or " */ 62c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 63c2aa98e2SPeter Wemm *q++ = '\\'; 64c2aa98e2SPeter Wemm *q++ = c; 65c2aa98e2SPeter Wemm } 66c2aa98e2SPeter Wemm *q++ = '"'; 67c2aa98e2SPeter Wemm *q = '\0'; 68c2aa98e2SPeter Wemm return r; 69c2aa98e2SPeter Wemm } 7040266059SGregory Neil Shapiro /* 71c2aa98e2SPeter Wemm ** RFC822_STRING -- Checks string for proper RFC822 string quoting. 72c2aa98e2SPeter Wemm ** 73c2aa98e2SPeter Wemm ** Runs through a string and verifies RFC822 special characters 74c2aa98e2SPeter Wemm ** are only found inside comments, quoted strings, or backslash 75c2aa98e2SPeter Wemm ** escaped. Also verified balanced quotes and parenthesis. 76c2aa98e2SPeter Wemm ** 77c2aa98e2SPeter Wemm ** Parameters: 78c2aa98e2SPeter Wemm ** s -- the string to modify. 79c2aa98e2SPeter Wemm ** 80c2aa98e2SPeter Wemm ** Returns: 8140266059SGregory Neil Shapiro ** true iff the string is RFC822 compliant, false otherwise. 82c2aa98e2SPeter Wemm */ 83c2aa98e2SPeter Wemm 84c2aa98e2SPeter Wemm bool 85c2aa98e2SPeter Wemm rfc822_string(s) 86c2aa98e2SPeter Wemm char *s; 87c2aa98e2SPeter Wemm { 8840266059SGregory Neil Shapiro bool quoted = false; 89c2aa98e2SPeter Wemm int commentlev = 0; 90c2aa98e2SPeter Wemm char *c = s; 91c2aa98e2SPeter Wemm 92c2aa98e2SPeter Wemm if (s == NULL) 9340266059SGregory Neil Shapiro return false; 94c2aa98e2SPeter Wemm 95c2aa98e2SPeter Wemm while (*c != '\0') 96c2aa98e2SPeter Wemm { 97c2aa98e2SPeter Wemm /* escaped character */ 98c2aa98e2SPeter Wemm if (*c == '\\') 99c2aa98e2SPeter Wemm { 100c2aa98e2SPeter Wemm c++; 101c2aa98e2SPeter Wemm if (*c == '\0') 10240266059SGregory Neil Shapiro return false; 103c2aa98e2SPeter Wemm } 104c2aa98e2SPeter Wemm else if (commentlev == 0 && *c == '"') 105c2aa98e2SPeter Wemm quoted = !quoted; 106c2aa98e2SPeter Wemm else if (!quoted) 107c2aa98e2SPeter Wemm { 108c2aa98e2SPeter Wemm if (*c == ')') 109c2aa98e2SPeter Wemm { 110c2aa98e2SPeter Wemm /* unbalanced ')' */ 111c2aa98e2SPeter Wemm if (commentlev == 0) 11240266059SGregory Neil Shapiro return false; 113c2aa98e2SPeter Wemm else 114c2aa98e2SPeter Wemm commentlev--; 115c2aa98e2SPeter Wemm } 116c2aa98e2SPeter Wemm else if (*c == '(') 117c2aa98e2SPeter Wemm commentlev++; 118c2aa98e2SPeter Wemm else if (commentlev == 0 && 119c2aa98e2SPeter Wemm strchr(MustQuoteChars, *c) != NULL) 12040266059SGregory Neil Shapiro return false; 121c2aa98e2SPeter Wemm } 122c2aa98e2SPeter Wemm c++; 123c2aa98e2SPeter Wemm } 12440266059SGregory Neil Shapiro 125c2aa98e2SPeter Wemm /* unbalanced '"' or '(' */ 12640266059SGregory Neil Shapiro return !quoted && commentlev == 0; 127c2aa98e2SPeter Wemm } 12840266059SGregory Neil Shapiro /* 129065a643dSPeter Wemm ** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string 130065a643dSPeter Wemm ** 13106f25ae9SGregory Neil Shapiro ** Arbitrarily shorten (in place) an RFC822 string and rebalance 132065a643dSPeter Wemm ** comments and quotes. 133065a643dSPeter Wemm ** 134065a643dSPeter Wemm ** Parameters: 135065a643dSPeter Wemm ** string -- the string to shorten 136065a643dSPeter Wemm ** length -- the maximum size, 0 if no maximum 137065a643dSPeter Wemm ** 138065a643dSPeter Wemm ** Returns: 13940266059SGregory Neil Shapiro ** true if string is changed, false otherwise 140065a643dSPeter Wemm ** 141065a643dSPeter Wemm ** Side Effects: 142065a643dSPeter Wemm ** Changes string in place, possibly resulting 143065a643dSPeter Wemm ** in a shorter string. 144065a643dSPeter Wemm */ 145065a643dSPeter Wemm 146065a643dSPeter Wemm bool 147065a643dSPeter Wemm shorten_rfc822_string(string, length) 148065a643dSPeter Wemm char *string; 149065a643dSPeter Wemm size_t length; 150065a643dSPeter Wemm { 15140266059SGregory Neil Shapiro bool backslash = false; 15240266059SGregory Neil Shapiro bool modified = false; 15340266059SGregory Neil Shapiro bool quoted = false; 154065a643dSPeter Wemm size_t slen; 155065a643dSPeter Wemm int parencount = 0; 156065a643dSPeter Wemm char *ptr = string; 157065a643dSPeter Wemm 158065a643dSPeter Wemm /* 159065a643dSPeter Wemm ** If have to rebalance an already short enough string, 160065a643dSPeter Wemm ** need to do it within allocated space. 161065a643dSPeter Wemm */ 162193538b7SGregory Neil Shapiro 163065a643dSPeter Wemm slen = strlen(string); 164065a643dSPeter Wemm if (length == 0 || slen < length) 165065a643dSPeter Wemm length = slen; 166065a643dSPeter Wemm 167065a643dSPeter Wemm while (*ptr != '\0') 168065a643dSPeter Wemm { 169065a643dSPeter Wemm if (backslash) 170065a643dSPeter Wemm { 17140266059SGregory Neil Shapiro backslash = false; 172065a643dSPeter Wemm goto increment; 173065a643dSPeter Wemm } 174065a643dSPeter Wemm 175065a643dSPeter Wemm if (*ptr == '\\') 17640266059SGregory Neil Shapiro backslash = true; 177065a643dSPeter Wemm else if (*ptr == '(') 178065a643dSPeter Wemm { 179065a643dSPeter Wemm if (!quoted) 180065a643dSPeter Wemm parencount++; 181065a643dSPeter Wemm } 182065a643dSPeter Wemm else if (*ptr == ')') 183065a643dSPeter Wemm { 184065a643dSPeter Wemm if (--parencount < 0) 185065a643dSPeter Wemm parencount = 0; 186065a643dSPeter Wemm } 187065a643dSPeter Wemm 188065a643dSPeter Wemm /* Inside a comment, quotes don't matter */ 189065a643dSPeter Wemm if (parencount <= 0 && *ptr == '"') 190065a643dSPeter Wemm quoted = !quoted; 191065a643dSPeter Wemm 192065a643dSPeter Wemm increment: 193065a643dSPeter Wemm /* Check for sufficient space for next character */ 19406f25ae9SGregory Neil Shapiro if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) + 195065a643dSPeter Wemm parencount + 196065a643dSPeter Wemm (quoted ? 1 : 0))) 197065a643dSPeter Wemm { 198065a643dSPeter Wemm /* Not enough, backtrack */ 199065a643dSPeter Wemm if (*ptr == '\\') 20040266059SGregory Neil Shapiro backslash = false; 201065a643dSPeter Wemm else if (*ptr == '(' && !quoted) 202065a643dSPeter Wemm parencount--; 203065a643dSPeter Wemm else if (*ptr == '"' && parencount == 0) 20440266059SGregory Neil Shapiro quoted = false; 205065a643dSPeter Wemm break; 206065a643dSPeter Wemm } 207065a643dSPeter Wemm ptr++; 208065a643dSPeter Wemm } 209065a643dSPeter Wemm 210065a643dSPeter Wemm /* Rebalance */ 211065a643dSPeter Wemm while (parencount-- > 0) 212065a643dSPeter Wemm { 213065a643dSPeter Wemm if (*ptr != ')') 214065a643dSPeter Wemm { 21540266059SGregory Neil Shapiro modified = true; 216065a643dSPeter Wemm *ptr = ')'; 217065a643dSPeter Wemm } 218065a643dSPeter Wemm ptr++; 219065a643dSPeter Wemm } 220065a643dSPeter Wemm if (quoted) 221065a643dSPeter Wemm { 222065a643dSPeter Wemm if (*ptr != '"') 223065a643dSPeter Wemm { 22440266059SGregory Neil Shapiro modified = true; 225065a643dSPeter Wemm *ptr = '"'; 226065a643dSPeter Wemm } 227065a643dSPeter Wemm ptr++; 228065a643dSPeter Wemm } 229065a643dSPeter Wemm if (*ptr != '\0') 230065a643dSPeter Wemm { 23140266059SGregory Neil Shapiro modified = true; 232065a643dSPeter Wemm *ptr = '\0'; 233065a643dSPeter Wemm } 234065a643dSPeter Wemm return modified; 235065a643dSPeter Wemm } 23640266059SGregory Neil Shapiro /* 237065a643dSPeter Wemm ** FIND_CHARACTER -- find an unquoted character in an RFC822 string 238065a643dSPeter Wemm ** 239065a643dSPeter Wemm ** Find an unquoted, non-commented character in an RFC822 240065a643dSPeter Wemm ** string and return a pointer to its location in the 241065a643dSPeter Wemm ** string. 242065a643dSPeter Wemm ** 243065a643dSPeter Wemm ** Parameters: 244065a643dSPeter Wemm ** string -- the string to search 245065a643dSPeter Wemm ** character -- the character to find 246065a643dSPeter Wemm ** 247065a643dSPeter Wemm ** Returns: 248065a643dSPeter Wemm ** pointer to the character, or 249065a643dSPeter Wemm ** a pointer to the end of the line if character is not found 250065a643dSPeter Wemm */ 251065a643dSPeter Wemm 252065a643dSPeter Wemm char * 253065a643dSPeter Wemm find_character(string, character) 254065a643dSPeter Wemm char *string; 25506f25ae9SGregory Neil Shapiro int character; 256065a643dSPeter Wemm { 25740266059SGregory Neil Shapiro bool backslash = false; 25840266059SGregory Neil Shapiro bool quoted = false; 259065a643dSPeter Wemm int parencount = 0; 260065a643dSPeter Wemm 261065a643dSPeter Wemm while (string != NULL && *string != '\0') 262065a643dSPeter Wemm { 263065a643dSPeter Wemm if (backslash) 264065a643dSPeter Wemm { 26540266059SGregory Neil Shapiro backslash = false; 266065a643dSPeter Wemm if (!quoted && character == '\\' && *string == '\\') 267065a643dSPeter Wemm break; 268065a643dSPeter Wemm string++; 269065a643dSPeter Wemm continue; 270065a643dSPeter Wemm } 271065a643dSPeter Wemm switch (*string) 272065a643dSPeter Wemm { 273065a643dSPeter Wemm case '\\': 27440266059SGregory Neil Shapiro backslash = true; 275065a643dSPeter Wemm break; 276065a643dSPeter Wemm 277065a643dSPeter Wemm case '(': 278065a643dSPeter Wemm if (!quoted) 279065a643dSPeter Wemm parencount++; 280065a643dSPeter Wemm break; 281065a643dSPeter Wemm 282065a643dSPeter Wemm case ')': 283065a643dSPeter Wemm if (--parencount < 0) 284065a643dSPeter Wemm parencount = 0; 285065a643dSPeter Wemm break; 286065a643dSPeter Wemm } 287065a643dSPeter Wemm 288065a643dSPeter Wemm /* Inside a comment, nothing matters */ 289065a643dSPeter Wemm if (parencount > 0) 290065a643dSPeter Wemm { 291065a643dSPeter Wemm string++; 292065a643dSPeter Wemm continue; 293065a643dSPeter Wemm } 294065a643dSPeter Wemm 295065a643dSPeter Wemm if (*string == '"') 296065a643dSPeter Wemm quoted = !quoted; 297065a643dSPeter Wemm else if (*string == character && !quoted) 298065a643dSPeter Wemm break; 299065a643dSPeter Wemm string++; 300065a643dSPeter Wemm } 301065a643dSPeter Wemm 302065a643dSPeter Wemm /* Return pointer to the character */ 303065a643dSPeter Wemm return string; 304065a643dSPeter Wemm } 30540266059SGregory Neil Shapiro 30640266059SGregory Neil Shapiro /* 30740266059SGregory Neil Shapiro ** CHECK_BODYTYPE -- check bodytype parameter 308c2aa98e2SPeter Wemm ** 30940266059SGregory Neil Shapiro ** Parameters: 31040266059SGregory Neil Shapiro ** bodytype -- bodytype parameter 31140266059SGregory Neil Shapiro ** 31240266059SGregory Neil Shapiro ** Returns: 31340266059SGregory Neil Shapiro ** BODYTYPE_* according to parameter 31440266059SGregory Neil Shapiro ** 31540266059SGregory Neil Shapiro */ 31640266059SGregory Neil Shapiro 31740266059SGregory Neil Shapiro int 31840266059SGregory Neil Shapiro check_bodytype(bodytype) 31940266059SGregory Neil Shapiro char *bodytype; 32040266059SGregory Neil Shapiro { 32140266059SGregory Neil Shapiro /* check body type for legality */ 32240266059SGregory Neil Shapiro if (bodytype == NULL) 32340266059SGregory Neil Shapiro return BODYTYPE_NONE; 32440266059SGregory Neil Shapiro if (sm_strcasecmp(bodytype, "7BIT") == 0) 32540266059SGregory Neil Shapiro return BODYTYPE_7BIT; 32640266059SGregory Neil Shapiro if (sm_strcasecmp(bodytype, "8BITMIME") == 0) 32740266059SGregory Neil Shapiro return BODYTYPE_8BITMIME; 32840266059SGregory Neil Shapiro return BODYTYPE_ILLEGAL; 32940266059SGregory Neil Shapiro } 33040266059SGregory Neil Shapiro 33140266059SGregory Neil Shapiro #if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI 33240266059SGregory Neil Shapiro /* 33340266059SGregory Neil Shapiro ** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..." 33440266059SGregory Neil Shapiro ** 33540266059SGregory Neil Shapiro ** Parameters: 33640266059SGregory Neil Shapiro ** str -- string to truncate 33740266059SGregory Neil Shapiro ** len -- maximum length (including '\0') (0 for unlimited) 33840266059SGregory Neil Shapiro ** delim -- delimiter character 33940266059SGregory Neil Shapiro ** 34040266059SGregory Neil Shapiro ** Returns: 34140266059SGregory Neil Shapiro ** None. 34240266059SGregory Neil Shapiro */ 34340266059SGregory Neil Shapiro 34440266059SGregory Neil Shapiro void 34540266059SGregory Neil Shapiro truncate_at_delim(str, len, delim) 34640266059SGregory Neil Shapiro char *str; 34740266059SGregory Neil Shapiro size_t len; 34840266059SGregory Neil Shapiro int delim; 34940266059SGregory Neil Shapiro { 35040266059SGregory Neil Shapiro char *p; 35140266059SGregory Neil Shapiro 35240266059SGregory Neil Shapiro if (str == NULL || len == 0 || strlen(str) < len) 35340266059SGregory Neil Shapiro return; 35440266059SGregory Neil Shapiro 35540266059SGregory Neil Shapiro *(str + len - 1) = '\0'; 35640266059SGregory Neil Shapiro while ((p = strrchr(str, delim)) != NULL) 35740266059SGregory Neil Shapiro { 35840266059SGregory Neil Shapiro *p = '\0'; 35940266059SGregory Neil Shapiro if (p - str + 4 < len) 36040266059SGregory Neil Shapiro { 36140266059SGregory Neil Shapiro *p++ = ':'; 36240266059SGregory Neil Shapiro *p = '\0'; 36340266059SGregory Neil Shapiro (void) sm_strlcat(str, "...", len); 36440266059SGregory Neil Shapiro return; 36540266059SGregory Neil Shapiro } 36640266059SGregory Neil Shapiro } 36740266059SGregory Neil Shapiro 36840266059SGregory Neil Shapiro /* Couldn't find a place to append "..." */ 36940266059SGregory Neil Shapiro if (len > 3) 37040266059SGregory Neil Shapiro (void) sm_strlcpy(str, "...", len); 37140266059SGregory Neil Shapiro else 37240266059SGregory Neil Shapiro str[0] = '\0'; 37340266059SGregory Neil Shapiro } 37440266059SGregory Neil Shapiro #endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */ 37540266059SGregory Neil Shapiro /* 37640266059SGregory Neil Shapiro ** XALLOC -- Allocate memory, raise an exception on error 377c2aa98e2SPeter Wemm ** 378c2aa98e2SPeter Wemm ** Parameters: 379c2aa98e2SPeter Wemm ** sz -- size of area to allocate. 380c2aa98e2SPeter Wemm ** 381c2aa98e2SPeter Wemm ** Returns: 382c2aa98e2SPeter Wemm ** pointer to data region. 383c2aa98e2SPeter Wemm ** 38440266059SGregory Neil Shapiro ** Exceptions: 38540266059SGregory Neil Shapiro ** SmHeapOutOfMemory (F:sm.heap) -- cannot allocate memory 38640266059SGregory Neil Shapiro ** 387c2aa98e2SPeter Wemm ** Side Effects: 388c2aa98e2SPeter Wemm ** Memory is allocated. 389c2aa98e2SPeter Wemm */ 390c2aa98e2SPeter Wemm 391c2aa98e2SPeter Wemm char * 39240266059SGregory Neil Shapiro #if SM_HEAP_CHECK 39340266059SGregory Neil Shapiro xalloc_tagged(sz, file, line) 39440266059SGregory Neil Shapiro register int sz; 39540266059SGregory Neil Shapiro char *file; 39640266059SGregory Neil Shapiro int line; 39740266059SGregory Neil Shapiro #else /* SM_HEAP_CHECK */ 398c2aa98e2SPeter Wemm xalloc(sz) 399c2aa98e2SPeter Wemm register int sz; 40040266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */ 401c2aa98e2SPeter Wemm { 402c2aa98e2SPeter Wemm register char *p; 403c2aa98e2SPeter Wemm 404c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 405c2aa98e2SPeter Wemm if (sz <= 0) 406c2aa98e2SPeter Wemm sz = 1; 407c2aa98e2SPeter Wemm 40840266059SGregory Neil Shapiro /* scaffolding for testing error handling code */ 40940266059SGregory Neil Shapiro sm_xtrap_raise_x(&SmHeapOutOfMemory); 41040266059SGregory Neil Shapiro 41140266059SGregory Neil Shapiro p = sm_malloc_tagged((unsigned) sz, file, line, sm_heap_group()); 412c2aa98e2SPeter Wemm if (p == NULL) 413c2aa98e2SPeter Wemm { 41440266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory); 415c2aa98e2SPeter Wemm } 41606f25ae9SGregory Neil Shapiro return p; 417c2aa98e2SPeter Wemm } 41840266059SGregory Neil Shapiro /* 419c2aa98e2SPeter Wemm ** COPYPLIST -- copy list of pointers. 420c2aa98e2SPeter Wemm ** 42140266059SGregory Neil Shapiro ** This routine is the equivalent of strdup for lists of 422c2aa98e2SPeter Wemm ** pointers. 423c2aa98e2SPeter Wemm ** 424c2aa98e2SPeter Wemm ** Parameters: 425c2aa98e2SPeter Wemm ** list -- list of pointers to copy. 426c2aa98e2SPeter Wemm ** Must be NULL terminated. 42740266059SGregory Neil Shapiro ** copycont -- if true, copy the contents of the vector 428c2aa98e2SPeter Wemm ** (which must be a string) also. 42940266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate storage, 43040266059SGregory Neil Shapiro ** or NULL 431c2aa98e2SPeter Wemm ** 432c2aa98e2SPeter Wemm ** Returns: 433c2aa98e2SPeter Wemm ** a copy of 'list'. 434c2aa98e2SPeter Wemm */ 435c2aa98e2SPeter Wemm 436c2aa98e2SPeter Wemm char ** 43740266059SGregory Neil Shapiro copyplist(list, copycont, rpool) 438c2aa98e2SPeter Wemm char **list; 439c2aa98e2SPeter Wemm bool copycont; 44040266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 441c2aa98e2SPeter Wemm { 442c2aa98e2SPeter Wemm register char **vp; 443c2aa98e2SPeter Wemm register char **newvp; 444c2aa98e2SPeter Wemm 445c2aa98e2SPeter Wemm for (vp = list; *vp != NULL; vp++) 446c2aa98e2SPeter Wemm continue; 447c2aa98e2SPeter Wemm 448c2aa98e2SPeter Wemm vp++; 449c2aa98e2SPeter Wemm 45040266059SGregory Neil Shapiro newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof *vp); 45106f25ae9SGregory Neil Shapiro memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); 452c2aa98e2SPeter Wemm 453c2aa98e2SPeter Wemm if (copycont) 454c2aa98e2SPeter Wemm { 455c2aa98e2SPeter Wemm for (vp = newvp; *vp != NULL; vp++) 45640266059SGregory Neil Shapiro *vp = sm_rpool_strdup_x(rpool, *vp); 457c2aa98e2SPeter Wemm } 458c2aa98e2SPeter Wemm 45906f25ae9SGregory Neil Shapiro return newvp; 460c2aa98e2SPeter Wemm } 46140266059SGregory Neil Shapiro /* 462c2aa98e2SPeter Wemm ** COPYQUEUE -- copy address queue. 463c2aa98e2SPeter Wemm ** 46440266059SGregory Neil Shapiro ** This routine is the equivalent of strdup for address queues; 46506f25ae9SGregory Neil Shapiro ** addresses marked as QS_IS_DEAD() aren't copied 466c2aa98e2SPeter Wemm ** 467c2aa98e2SPeter Wemm ** Parameters: 468c2aa98e2SPeter Wemm ** addr -- list of address structures to copy. 46940266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate storage 470c2aa98e2SPeter Wemm ** 471c2aa98e2SPeter Wemm ** Returns: 472c2aa98e2SPeter Wemm ** a copy of 'addr'. 473c2aa98e2SPeter Wemm */ 474c2aa98e2SPeter Wemm 475c2aa98e2SPeter Wemm ADDRESS * 47640266059SGregory Neil Shapiro copyqueue(addr, rpool) 477c2aa98e2SPeter Wemm ADDRESS *addr; 47840266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 479c2aa98e2SPeter Wemm { 480c2aa98e2SPeter Wemm register ADDRESS *newaddr; 481c2aa98e2SPeter Wemm ADDRESS *ret; 482c2aa98e2SPeter Wemm register ADDRESS **tail = &ret; 483c2aa98e2SPeter Wemm 484c2aa98e2SPeter Wemm while (addr != NULL) 485c2aa98e2SPeter Wemm { 48606f25ae9SGregory Neil Shapiro if (!QS_IS_DEAD(addr->q_state)) 487c2aa98e2SPeter Wemm { 48840266059SGregory Neil Shapiro newaddr = (ADDRESS *) sm_rpool_malloc_x(rpool, 48940266059SGregory Neil Shapiro sizeof *newaddr); 490c2aa98e2SPeter Wemm STRUCTCOPY(*addr, *newaddr); 491c2aa98e2SPeter Wemm *tail = newaddr; 492c2aa98e2SPeter Wemm tail = &newaddr->q_next; 493c2aa98e2SPeter Wemm } 494c2aa98e2SPeter Wemm addr = addr->q_next; 495c2aa98e2SPeter Wemm } 496c2aa98e2SPeter Wemm *tail = NULL; 497c2aa98e2SPeter Wemm 498c2aa98e2SPeter Wemm return ret; 499c2aa98e2SPeter Wemm } 50040266059SGregory Neil Shapiro /* 50106f25ae9SGregory Neil Shapiro ** LOG_SENDMAIL_PID -- record sendmail pid and command line. 50206f25ae9SGregory Neil Shapiro ** 50306f25ae9SGregory Neil Shapiro ** Parameters: 50406f25ae9SGregory Neil Shapiro ** e -- the current envelope. 50506f25ae9SGregory Neil Shapiro ** 50606f25ae9SGregory Neil Shapiro ** Returns: 50706f25ae9SGregory Neil Shapiro ** none. 50806f25ae9SGregory Neil Shapiro ** 50906f25ae9SGregory Neil Shapiro ** Side Effects: 51040266059SGregory Neil Shapiro ** writes pidfile, logs command line. 51106f25ae9SGregory Neil Shapiro */ 51206f25ae9SGregory Neil Shapiro 51306f25ae9SGregory Neil Shapiro void 51406f25ae9SGregory Neil Shapiro log_sendmail_pid(e) 51506f25ae9SGregory Neil Shapiro ENVELOPE *e; 51606f25ae9SGregory Neil Shapiro { 51706f25ae9SGregory Neil Shapiro long sff; 51840266059SGregory Neil Shapiro SM_FILE_T *pidf; 51906f25ae9SGregory Neil Shapiro char pidpath[MAXPATHLEN + 1]; 52040266059SGregory Neil Shapiro extern char *CommandLineArgs; 52106f25ae9SGregory Neil Shapiro 52206f25ae9SGregory Neil Shapiro /* write the pid to the log file for posterity */ 52306f25ae9SGregory Neil Shapiro sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 52406f25ae9SGregory Neil Shapiro if (TrustedUid != 0 && RealUid == TrustedUid) 52506f25ae9SGregory Neil Shapiro sff |= SFF_OPENASROOT; 52606f25ae9SGregory Neil Shapiro expand(PidFile, pidpath, sizeof pidpath, e); 52706f25ae9SGregory Neil Shapiro pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, 0644, sff); 52806f25ae9SGregory Neil Shapiro if (pidf == NULL) 52906f25ae9SGregory Neil Shapiro { 530602a2b1bSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s", 53140266059SGregory Neil Shapiro pidpath, sm_errstring(errno)); 53206f25ae9SGregory Neil Shapiro } 53306f25ae9SGregory Neil Shapiro else 53406f25ae9SGregory Neil Shapiro { 5358774250cSGregory Neil Shapiro pid_t pid; 53606f25ae9SGregory Neil Shapiro 5378774250cSGregory Neil Shapiro pid = getpid(); 538193538b7SGregory Neil Shapiro 53906f25ae9SGregory Neil Shapiro /* write the process id on line 1 */ 54040266059SGregory Neil Shapiro (void) sm_io_fprintf(pidf, SM_TIME_DEFAULT, "%ld\n", 54140266059SGregory Neil Shapiro (long) pid); 54206f25ae9SGregory Neil Shapiro 54306f25ae9SGregory Neil Shapiro /* line 2 contains all command line flags */ 54440266059SGregory Neil Shapiro (void) sm_io_fprintf(pidf, SM_TIME_DEFAULT, "%s\n", 54540266059SGregory Neil Shapiro CommandLineArgs); 54606f25ae9SGregory Neil Shapiro 54706f25ae9SGregory Neil Shapiro /* flush and close */ 54840266059SGregory Neil Shapiro (void) sm_io_close(pidf, SM_TIME_DEFAULT); 54906f25ae9SGregory Neil Shapiro } 55040266059SGregory Neil Shapiro if (LogLevel > 9) 55140266059SGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID, "started as: %s", CommandLineArgs); 55206f25ae9SGregory Neil Shapiro } 55340266059SGregory Neil Shapiro /* 55406f25ae9SGregory Neil Shapiro ** SET_DELIVERY_MODE -- set and record the delivery mode 55506f25ae9SGregory Neil Shapiro ** 55606f25ae9SGregory Neil Shapiro ** Parameters: 55706f25ae9SGregory Neil Shapiro ** mode -- delivery mode 55806f25ae9SGregory Neil Shapiro ** e -- the current envelope. 55906f25ae9SGregory Neil Shapiro ** 56006f25ae9SGregory Neil Shapiro ** Returns: 56106f25ae9SGregory Neil Shapiro ** none. 56206f25ae9SGregory Neil Shapiro ** 56306f25ae9SGregory Neil Shapiro ** Side Effects: 56440266059SGregory Neil Shapiro ** sets {deliveryMode} macro 56506f25ae9SGregory Neil Shapiro */ 56606f25ae9SGregory Neil Shapiro 56706f25ae9SGregory Neil Shapiro void 56806f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e) 56906f25ae9SGregory Neil Shapiro int mode; 57006f25ae9SGregory Neil Shapiro ENVELOPE *e; 57106f25ae9SGregory Neil Shapiro { 57206f25ae9SGregory Neil Shapiro char buf[2]; 57306f25ae9SGregory Neil Shapiro 57406f25ae9SGregory Neil Shapiro e->e_sendmode = (char) mode; 57506f25ae9SGregory Neil Shapiro buf[0] = (char) mode; 57606f25ae9SGregory Neil Shapiro buf[1] = '\0'; 57740266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, macid("{deliveryMode}"), buf); 57806f25ae9SGregory Neil Shapiro } 57940266059SGregory Neil Shapiro /* 58040266059SGregory Neil Shapiro ** SET_OP_MODE -- set and record the op mode 58140266059SGregory Neil Shapiro ** 58240266059SGregory Neil Shapiro ** Parameters: 58340266059SGregory Neil Shapiro ** mode -- op mode 58440266059SGregory Neil Shapiro ** e -- the current envelope. 58540266059SGregory Neil Shapiro ** 58640266059SGregory Neil Shapiro ** Returns: 58740266059SGregory Neil Shapiro ** none. 58840266059SGregory Neil Shapiro ** 58940266059SGregory Neil Shapiro ** Side Effects: 59040266059SGregory Neil Shapiro ** sets {opMode} macro 59140266059SGregory Neil Shapiro */ 59240266059SGregory Neil Shapiro 59340266059SGregory Neil Shapiro void 59440266059SGregory Neil Shapiro set_op_mode(mode) 59540266059SGregory Neil Shapiro int mode; 59640266059SGregory Neil Shapiro { 59740266059SGregory Neil Shapiro char buf[2]; 59840266059SGregory Neil Shapiro extern ENVELOPE BlankEnvelope; 59940266059SGregory Neil Shapiro 60040266059SGregory Neil Shapiro OpMode = (char) mode; 60140266059SGregory Neil Shapiro buf[0] = (char) mode; 60240266059SGregory Neil Shapiro buf[1] = '\0'; 60340266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, MID_OPMODE, buf); 60440266059SGregory Neil Shapiro } 60540266059SGregory Neil Shapiro /* 606c2aa98e2SPeter Wemm ** PRINTAV -- print argument vector. 607c2aa98e2SPeter Wemm ** 608c2aa98e2SPeter Wemm ** Parameters: 609c2aa98e2SPeter Wemm ** av -- argument vector. 610c2aa98e2SPeter Wemm ** 611c2aa98e2SPeter Wemm ** Returns: 612c2aa98e2SPeter Wemm ** none. 613c2aa98e2SPeter Wemm ** 614c2aa98e2SPeter Wemm ** Side Effects: 615c2aa98e2SPeter Wemm ** prints av. 616c2aa98e2SPeter Wemm */ 617c2aa98e2SPeter Wemm 618c2aa98e2SPeter Wemm void 619c2aa98e2SPeter Wemm printav(av) 620c2aa98e2SPeter Wemm register char **av; 621c2aa98e2SPeter Wemm { 622c2aa98e2SPeter Wemm while (*av != NULL) 623c2aa98e2SPeter Wemm { 624c2aa98e2SPeter Wemm if (tTd(0, 44)) 62540266059SGregory Neil Shapiro sm_dprintf("\n\t%08lx=", (unsigned long) *av); 626c2aa98e2SPeter Wemm else 62740266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, ' '); 628c2aa98e2SPeter Wemm xputs(*av++); 629c2aa98e2SPeter Wemm } 63040266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '\n'); 631c2aa98e2SPeter Wemm } 63240266059SGregory Neil Shapiro /* 633c2aa98e2SPeter Wemm ** XPUTS -- put string doing control escapes. 634c2aa98e2SPeter Wemm ** 635c2aa98e2SPeter Wemm ** Parameters: 636c2aa98e2SPeter Wemm ** s -- string to put. 637c2aa98e2SPeter Wemm ** 638c2aa98e2SPeter Wemm ** Returns: 639c2aa98e2SPeter Wemm ** none. 640c2aa98e2SPeter Wemm ** 641c2aa98e2SPeter Wemm ** Side Effects: 642c2aa98e2SPeter Wemm ** output to stdout 643c2aa98e2SPeter Wemm */ 644c2aa98e2SPeter Wemm 645c2aa98e2SPeter Wemm void 646c2aa98e2SPeter Wemm xputs(s) 647c2aa98e2SPeter Wemm register const char *s; 648c2aa98e2SPeter Wemm { 649c2aa98e2SPeter Wemm register int c; 650c2aa98e2SPeter Wemm register struct metamac *mp; 65140266059SGregory Neil Shapiro bool shiftout = false; 652c2aa98e2SPeter Wemm extern struct metamac MetaMacros[]; 65340266059SGregory Neil Shapiro static SM_DEBUG_T DebugANSI = SM_DEBUG_INITIALIZER("ANSI", 65440266059SGregory Neil Shapiro "@(#)$Debug: ANSI - enable reverse video in debug output $"); 65540266059SGregory Neil Shapiro 65640266059SGregory Neil Shapiro /* 65740266059SGregory Neil Shapiro ** TermEscape is set here, rather than in main(), 65840266059SGregory Neil Shapiro ** because ANSI mode can be turned on or off at any time 65940266059SGregory Neil Shapiro ** if we are in -bt rule testing mode. 66040266059SGregory Neil Shapiro */ 66140266059SGregory Neil Shapiro 66240266059SGregory Neil Shapiro if (sm_debug_unknown(&DebugANSI)) 66340266059SGregory Neil Shapiro { 66440266059SGregory Neil Shapiro if (sm_debug_active(&DebugANSI, 1)) 66540266059SGregory Neil Shapiro { 66640266059SGregory Neil Shapiro TermEscape.te_rv_on = "\033[7m"; 66740266059SGregory Neil Shapiro TermEscape.te_rv_off = "\033[0m"; 66840266059SGregory Neil Shapiro } 66940266059SGregory Neil Shapiro else 67040266059SGregory Neil Shapiro { 67140266059SGregory Neil Shapiro TermEscape.te_rv_on = ""; 67240266059SGregory Neil Shapiro TermEscape.te_rv_off = ""; 67340266059SGregory Neil Shapiro } 67440266059SGregory Neil Shapiro } 675c2aa98e2SPeter Wemm 676c2aa98e2SPeter Wemm if (s == NULL) 677c2aa98e2SPeter Wemm { 67840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s<null>%s", 67940266059SGregory Neil Shapiro TermEscape.te_rv_on, TermEscape.te_rv_off); 680c2aa98e2SPeter Wemm return; 681c2aa98e2SPeter Wemm } 682c2aa98e2SPeter Wemm while ((c = (*s++ & 0377)) != '\0') 683c2aa98e2SPeter Wemm { 684c2aa98e2SPeter Wemm if (shiftout) 685c2aa98e2SPeter Wemm { 68640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 68740266059SGregory Neil Shapiro TermEscape.te_rv_off); 68840266059SGregory Neil Shapiro shiftout = false; 689c2aa98e2SPeter Wemm } 690c2aa98e2SPeter Wemm if (!isascii(c)) 691c2aa98e2SPeter Wemm { 692c2aa98e2SPeter Wemm if (c == MATCHREPL) 693c2aa98e2SPeter Wemm { 69440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 69540266059SGregory Neil Shapiro "%s$", 69640266059SGregory Neil Shapiro TermEscape.te_rv_on); 69740266059SGregory Neil Shapiro shiftout = true; 698c2aa98e2SPeter Wemm if (*s == '\0') 699c2aa98e2SPeter Wemm continue; 700c2aa98e2SPeter Wemm c = *s++ & 0377; 701c2aa98e2SPeter Wemm goto printchar; 702c2aa98e2SPeter Wemm } 703c2aa98e2SPeter Wemm if (c == MACROEXPAND || c == MACRODEXPAND) 704c2aa98e2SPeter Wemm { 70540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 70640266059SGregory Neil Shapiro "%s$", 70740266059SGregory Neil Shapiro TermEscape.te_rv_on); 708c2aa98e2SPeter Wemm if (c == MACRODEXPAND) 70940266059SGregory Neil Shapiro (void) sm_io_putc(smioout, 71040266059SGregory Neil Shapiro SM_TIME_DEFAULT, '&'); 71140266059SGregory Neil Shapiro shiftout = true; 712c2aa98e2SPeter Wemm if (*s == '\0') 713c2aa98e2SPeter Wemm continue; 714c2aa98e2SPeter Wemm if (strchr("=~&?", *s) != NULL) 71540266059SGregory Neil Shapiro (void) sm_io_putc(smioout, 71640266059SGregory Neil Shapiro SM_TIME_DEFAULT, 71740266059SGregory Neil Shapiro *s++); 718c2aa98e2SPeter Wemm if (bitset(0200, *s)) 71940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 72040266059SGregory Neil Shapiro SM_TIME_DEFAULT, 72140266059SGregory Neil Shapiro "{%s}", 72240266059SGregory Neil Shapiro macname(bitidx(*s++))); 723c2aa98e2SPeter Wemm else 72440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 72540266059SGregory Neil Shapiro SM_TIME_DEFAULT, 72640266059SGregory Neil Shapiro "%c", 72740266059SGregory Neil Shapiro *s++); 728c2aa98e2SPeter Wemm continue; 729c2aa98e2SPeter Wemm } 730c2aa98e2SPeter Wemm for (mp = MetaMacros; mp->metaname != '\0'; mp++) 731c2aa98e2SPeter Wemm { 73240266059SGregory Neil Shapiro if (bitidx(mp->metaval) == c) 733c2aa98e2SPeter Wemm { 73440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 73540266059SGregory Neil Shapiro SM_TIME_DEFAULT, 73640266059SGregory Neil Shapiro "%s$%c", 737c2aa98e2SPeter Wemm TermEscape.te_rv_on, 738c2aa98e2SPeter Wemm mp->metaname); 73940266059SGregory Neil Shapiro shiftout = true; 740c2aa98e2SPeter Wemm break; 741c2aa98e2SPeter Wemm } 742c2aa98e2SPeter Wemm } 743c2aa98e2SPeter Wemm if (c == MATCHCLASS || c == MATCHNCLASS) 744c2aa98e2SPeter Wemm { 745c2aa98e2SPeter Wemm if (bitset(0200, *s)) 74640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 74740266059SGregory Neil Shapiro SM_TIME_DEFAULT, 74840266059SGregory Neil Shapiro "{%s}", 74940266059SGregory Neil Shapiro macname(bitidx(*s++))); 750c2aa98e2SPeter Wemm else if (*s != '\0') 75140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 75240266059SGregory Neil Shapiro SM_TIME_DEFAULT, 75340266059SGregory Neil Shapiro "%c", 75440266059SGregory Neil Shapiro *s++); 755c2aa98e2SPeter Wemm } 756c2aa98e2SPeter Wemm if (mp->metaname != '\0') 757c2aa98e2SPeter Wemm continue; 758c2aa98e2SPeter Wemm 759c2aa98e2SPeter Wemm /* unrecognized meta character */ 76040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%sM-", 76140266059SGregory Neil Shapiro TermEscape.te_rv_on); 76240266059SGregory Neil Shapiro shiftout = true; 763c2aa98e2SPeter Wemm c &= 0177; 764c2aa98e2SPeter Wemm } 765c2aa98e2SPeter Wemm printchar: 766c2aa98e2SPeter Wemm if (isprint(c)) 767c2aa98e2SPeter Wemm { 76840266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 769c2aa98e2SPeter Wemm continue; 770c2aa98e2SPeter Wemm } 771c2aa98e2SPeter Wemm 772c2aa98e2SPeter Wemm /* wasn't a meta-macro -- find another way to print it */ 773c2aa98e2SPeter Wemm switch (c) 774c2aa98e2SPeter Wemm { 775c2aa98e2SPeter Wemm case '\n': 776c2aa98e2SPeter Wemm c = 'n'; 777c2aa98e2SPeter Wemm break; 778c2aa98e2SPeter Wemm 779c2aa98e2SPeter Wemm case '\r': 780c2aa98e2SPeter Wemm c = 'r'; 781c2aa98e2SPeter Wemm break; 782c2aa98e2SPeter Wemm 783c2aa98e2SPeter Wemm case '\t': 784c2aa98e2SPeter Wemm c = 't'; 785c2aa98e2SPeter Wemm break; 786c2aa98e2SPeter Wemm } 787c2aa98e2SPeter Wemm if (!shiftout) 788c2aa98e2SPeter Wemm { 78940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 79040266059SGregory Neil Shapiro TermEscape.te_rv_on); 79140266059SGregory Neil Shapiro shiftout = true; 792c2aa98e2SPeter Wemm } 793c2aa98e2SPeter Wemm if (isprint(c)) 794c2aa98e2SPeter Wemm { 79540266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '\\'); 79640266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 797c2aa98e2SPeter Wemm } 798c2aa98e2SPeter Wemm else 799c2aa98e2SPeter Wemm { 80040266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '^'); 80140266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c ^ 0100); 802c2aa98e2SPeter Wemm } 803c2aa98e2SPeter Wemm } 804c2aa98e2SPeter Wemm if (shiftout) 80540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 80640266059SGregory Neil Shapiro TermEscape.te_rv_off); 80740266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 808c2aa98e2SPeter Wemm } 80940266059SGregory Neil Shapiro /* 810c2aa98e2SPeter Wemm ** MAKELOWER -- Translate a line into lower case 811c2aa98e2SPeter Wemm ** 812c2aa98e2SPeter Wemm ** Parameters: 813c2aa98e2SPeter Wemm ** p -- the string to translate. If NULL, return is 814c2aa98e2SPeter Wemm ** immediate. 815c2aa98e2SPeter Wemm ** 816c2aa98e2SPeter Wemm ** Returns: 817c2aa98e2SPeter Wemm ** none. 818c2aa98e2SPeter Wemm ** 819c2aa98e2SPeter Wemm ** Side Effects: 820c2aa98e2SPeter Wemm ** String pointed to by p is translated to lower case. 821c2aa98e2SPeter Wemm */ 822c2aa98e2SPeter Wemm 823c2aa98e2SPeter Wemm void 824c2aa98e2SPeter Wemm makelower(p) 825c2aa98e2SPeter Wemm register char *p; 826c2aa98e2SPeter Wemm { 827c2aa98e2SPeter Wemm register char c; 828c2aa98e2SPeter Wemm 829c2aa98e2SPeter Wemm if (p == NULL) 830c2aa98e2SPeter Wemm return; 831c2aa98e2SPeter Wemm for (; (c = *p) != '\0'; p++) 832c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 833c2aa98e2SPeter Wemm *p = tolower(c); 834c2aa98e2SPeter Wemm } 83540266059SGregory Neil Shapiro /* 836c2aa98e2SPeter Wemm ** FIXCRLF -- fix <CR><LF> in line. 837c2aa98e2SPeter Wemm ** 838c2aa98e2SPeter Wemm ** Looks for the <CR><LF> combination and turns it into the 839c2aa98e2SPeter Wemm ** UNIX canonical <NL> character. It only takes one line, 840c2aa98e2SPeter Wemm ** i.e., it is assumed that the first <NL> found is the end 841c2aa98e2SPeter Wemm ** of the line. 842c2aa98e2SPeter Wemm ** 843c2aa98e2SPeter Wemm ** Parameters: 844c2aa98e2SPeter Wemm ** line -- the line to fix. 845c2aa98e2SPeter Wemm ** stripnl -- if true, strip the newline also. 846c2aa98e2SPeter Wemm ** 847c2aa98e2SPeter Wemm ** Returns: 848c2aa98e2SPeter Wemm ** none. 849c2aa98e2SPeter Wemm ** 850c2aa98e2SPeter Wemm ** Side Effects: 851c2aa98e2SPeter Wemm ** line is changed in place. 852c2aa98e2SPeter Wemm */ 853c2aa98e2SPeter Wemm 854c2aa98e2SPeter Wemm void 855c2aa98e2SPeter Wemm fixcrlf(line, stripnl) 856c2aa98e2SPeter Wemm char *line; 857c2aa98e2SPeter Wemm bool stripnl; 858c2aa98e2SPeter Wemm { 859c2aa98e2SPeter Wemm register char *p; 860c2aa98e2SPeter Wemm 861c2aa98e2SPeter Wemm p = strchr(line, '\n'); 862c2aa98e2SPeter Wemm if (p == NULL) 863c2aa98e2SPeter Wemm return; 864c2aa98e2SPeter Wemm if (p > line && p[-1] == '\r') 865c2aa98e2SPeter Wemm p--; 866c2aa98e2SPeter Wemm if (!stripnl) 867c2aa98e2SPeter Wemm *p++ = '\n'; 868c2aa98e2SPeter Wemm *p = '\0'; 869c2aa98e2SPeter Wemm } 87040266059SGregory Neil Shapiro /* 871c2aa98e2SPeter Wemm ** PUTLINE -- put a line like fputs obeying SMTP conventions 872c2aa98e2SPeter Wemm ** 873c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 874c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 875c2aa98e2SPeter Wemm ** 876c2aa98e2SPeter Wemm ** Parameters: 877c2aa98e2SPeter Wemm ** l -- line to put. 878c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 879c2aa98e2SPeter Wemm ** 880c2aa98e2SPeter Wemm ** Returns: 881c2aa98e2SPeter Wemm ** none 882c2aa98e2SPeter Wemm ** 883c2aa98e2SPeter Wemm ** Side Effects: 88440266059SGregory Neil Shapiro ** output of l to mci->mci_out. 885c2aa98e2SPeter Wemm */ 886c2aa98e2SPeter Wemm 887c2aa98e2SPeter Wemm void 888c2aa98e2SPeter Wemm putline(l, mci) 889c2aa98e2SPeter Wemm register char *l; 890c2aa98e2SPeter Wemm register MCI *mci; 891c2aa98e2SPeter Wemm { 892c2aa98e2SPeter Wemm putxline(l, strlen(l), mci, PXLF_MAPFROM); 893c2aa98e2SPeter Wemm } 89440266059SGregory Neil Shapiro /* 895c2aa98e2SPeter Wemm ** PUTXLINE -- putline with flags bits. 896c2aa98e2SPeter Wemm ** 897c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 898c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 899c2aa98e2SPeter Wemm ** 900c2aa98e2SPeter Wemm ** Parameters: 901c2aa98e2SPeter Wemm ** l -- line to put. 902c2aa98e2SPeter Wemm ** len -- the length of the line. 903c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 904c2aa98e2SPeter Wemm ** pxflags -- flag bits: 905c2aa98e2SPeter Wemm ** PXLF_MAPFROM -- map From_ to >From_. 906c2aa98e2SPeter Wemm ** PXLF_STRIP8BIT -- strip 8th bit. 907c2aa98e2SPeter Wemm ** PXLF_HEADER -- map bare newline in header to newline space. 908c2aa98e2SPeter Wemm ** 909c2aa98e2SPeter Wemm ** Returns: 910c2aa98e2SPeter Wemm ** none 911c2aa98e2SPeter Wemm ** 912c2aa98e2SPeter Wemm ** Side Effects: 91340266059SGregory Neil Shapiro ** output of l to mci->mci_out. 914c2aa98e2SPeter Wemm */ 915c2aa98e2SPeter Wemm 916c2aa98e2SPeter Wemm void 917c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags) 918c2aa98e2SPeter Wemm register char *l; 919c2aa98e2SPeter Wemm size_t len; 920c2aa98e2SPeter Wemm register MCI *mci; 921c2aa98e2SPeter Wemm int pxflags; 922c2aa98e2SPeter Wemm { 92340266059SGregory Neil Shapiro bool dead = false; 924c2aa98e2SPeter Wemm register char *p, *end; 925c2aa98e2SPeter Wemm int slop = 0; 926c2aa98e2SPeter Wemm 927c2aa98e2SPeter Wemm /* strip out 0200 bits -- these can look like TELNET protocol */ 928c2aa98e2SPeter Wemm if (bitset(MCIF_7BIT, mci->mci_flags) || 929c2aa98e2SPeter Wemm bitset(PXLF_STRIP8BIT, pxflags)) 930c2aa98e2SPeter Wemm { 931c2aa98e2SPeter Wemm register char svchar; 932c2aa98e2SPeter Wemm 933c2aa98e2SPeter Wemm for (p = l; (svchar = *p) != '\0'; ++p) 934c2aa98e2SPeter Wemm if (bitset(0200, svchar)) 935c2aa98e2SPeter Wemm *p = svchar &~ 0200; 936c2aa98e2SPeter Wemm } 937c2aa98e2SPeter Wemm 938c2aa98e2SPeter Wemm end = l + len; 939c2aa98e2SPeter Wemm do 940c2aa98e2SPeter Wemm { 941c2aa98e2SPeter Wemm /* find the end of the line */ 942c2aa98e2SPeter Wemm p = memchr(l, '\n', end - l); 943c2aa98e2SPeter Wemm if (p == NULL) 944c2aa98e2SPeter Wemm p = end; 945c2aa98e2SPeter Wemm 946c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 94740266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 94840266059SGregory Neil Shapiro "%05d >>> ", (int) CurrentPid); 949c2aa98e2SPeter Wemm 950c2aa98e2SPeter Wemm /* check for line overflow */ 951c2aa98e2SPeter Wemm while (mci->mci_mailer->m_linelimit > 0 && 952c2aa98e2SPeter Wemm (p - l + slop) > mci->mci_mailer->m_linelimit) 953c2aa98e2SPeter Wemm { 954c2aa98e2SPeter Wemm char *l_base = l; 955c2aa98e2SPeter Wemm register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 956c2aa98e2SPeter Wemm 957c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 958c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 959c2aa98e2SPeter Wemm { 96040266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 96140266059SGregory Neil Shapiro '.') == SM_IO_EOF) 96240266059SGregory Neil Shapiro dead = true; 963193538b7SGregory Neil Shapiro else 964193538b7SGregory Neil Shapiro { 965193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 96640266059SGregory Neil Shapiro DataProgress = true; 967193538b7SGregory Neil Shapiro } 968c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 96940266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 97040266059SGregory Neil Shapiro SM_TIME_DEFAULT, '.'); 971c2aa98e2SPeter Wemm } 972c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 973c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 974c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 975c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 976c2aa98e2SPeter Wemm { 97740266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 97840266059SGregory Neil Shapiro '>') == SM_IO_EOF) 97940266059SGregory Neil Shapiro dead = true; 980193538b7SGregory Neil Shapiro else 981193538b7SGregory Neil Shapiro { 982193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 98340266059SGregory Neil Shapiro DataProgress = true; 984193538b7SGregory Neil Shapiro } 985c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 98640266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 98740266059SGregory Neil Shapiro SM_TIME_DEFAULT, 98840266059SGregory Neil Shapiro '>'); 989c2aa98e2SPeter Wemm } 99006f25ae9SGregory Neil Shapiro if (dead) 99106f25ae9SGregory Neil Shapiro break; 99206f25ae9SGregory Neil Shapiro 993c2aa98e2SPeter Wemm while (l < q) 994c2aa98e2SPeter Wemm { 99540266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 99640266059SGregory Neil Shapiro (unsigned char) *l++) == SM_IO_EOF) 99706f25ae9SGregory Neil Shapiro { 99840266059SGregory Neil Shapiro dead = true; 99906f25ae9SGregory Neil Shapiro break; 1000c2aa98e2SPeter Wemm } 1001193538b7SGregory Neil Shapiro else 1002193538b7SGregory Neil Shapiro { 100306f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 100440266059SGregory Neil Shapiro DataProgress = true; 100506f25ae9SGregory Neil Shapiro } 1006193538b7SGregory Neil Shapiro } 100706f25ae9SGregory Neil Shapiro if (dead) 100806f25ae9SGregory Neil Shapiro break; 100906f25ae9SGregory Neil Shapiro 101040266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '!') == 101140266059SGregory Neil Shapiro SM_IO_EOF || 101240266059SGregory Neil Shapiro sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 101340266059SGregory Neil Shapiro mci->mci_mailer->m_eol) == 101440266059SGregory Neil Shapiro SM_IO_EOF || 101540266059SGregory Neil Shapiro sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, ' ') == 101640266059SGregory Neil Shapiro SM_IO_EOF) 101706f25ae9SGregory Neil Shapiro { 101840266059SGregory Neil Shapiro dead = true; 101906f25ae9SGregory Neil Shapiro break; 102006f25ae9SGregory Neil Shapiro } 1021193538b7SGregory Neil Shapiro else 1022193538b7SGregory Neil Shapiro { 102306f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 102440266059SGregory Neil Shapiro DataProgress = true; 1025193538b7SGregory Neil Shapiro } 1026c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1027c2aa98e2SPeter Wemm { 1028c2aa98e2SPeter Wemm for (l = l_base; l < q; l++) 102940266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 103040266059SGregory Neil Shapiro SM_TIME_DEFAULT, 103140266059SGregory Neil Shapiro (unsigned char)*l); 103240266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, 103340266059SGregory Neil Shapiro SM_TIME_DEFAULT, 103440266059SGregory Neil Shapiro "!\n%05d >>> ", 103540266059SGregory Neil Shapiro (int) CurrentPid); 1036c2aa98e2SPeter Wemm } 1037c2aa98e2SPeter Wemm slop = 1; 1038c2aa98e2SPeter Wemm } 1039c2aa98e2SPeter Wemm 104006f25ae9SGregory Neil Shapiro if (dead) 104106f25ae9SGregory Neil Shapiro break; 104206f25ae9SGregory Neil Shapiro 1043c2aa98e2SPeter Wemm /* output last part */ 1044c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 1045c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 1046c2aa98e2SPeter Wemm { 104740266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '.') == 104840266059SGregory Neil Shapiro SM_IO_EOF) 104906f25ae9SGregory Neil Shapiro break; 1050193538b7SGregory Neil Shapiro else 1051193538b7SGregory Neil Shapiro { 1052193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 105340266059SGregory Neil Shapiro DataProgress = true; 1054193538b7SGregory Neil Shapiro } 1055c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 105640266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 105740266059SGregory Neil Shapiro SM_TIME_DEFAULT, '.'); 1058c2aa98e2SPeter Wemm } 1059c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1060c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1061c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1062c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1063c2aa98e2SPeter Wemm { 106440266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '>') == 106540266059SGregory Neil Shapiro SM_IO_EOF) 106606f25ae9SGregory Neil Shapiro break; 1067193538b7SGregory Neil Shapiro else 1068193538b7SGregory Neil Shapiro { 1069193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 107040266059SGregory Neil Shapiro DataProgress = true; 1071193538b7SGregory Neil Shapiro } 1072c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 107340266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 107440266059SGregory Neil Shapiro SM_TIME_DEFAULT, '>'); 1075c2aa98e2SPeter Wemm } 1076c2aa98e2SPeter Wemm for ( ; l < p; ++l) 1077c2aa98e2SPeter Wemm { 1078c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 107940266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 108040266059SGregory Neil Shapiro SM_TIME_DEFAULT, 108140266059SGregory Neil Shapiro (unsigned char)*l); 108240266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 108340266059SGregory Neil Shapiro (unsigned char) *l) == SM_IO_EOF) 108406f25ae9SGregory Neil Shapiro { 108540266059SGregory Neil Shapiro dead = true; 108606f25ae9SGregory Neil Shapiro break; 1087c2aa98e2SPeter Wemm } 1088193538b7SGregory Neil Shapiro else 1089193538b7SGregory Neil Shapiro { 109006f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 109140266059SGregory Neil Shapiro DataProgress = true; 109206f25ae9SGregory Neil Shapiro } 1093193538b7SGregory Neil Shapiro } 109406f25ae9SGregory Neil Shapiro if (dead) 109506f25ae9SGregory Neil Shapiro break; 109606f25ae9SGregory Neil Shapiro 1097c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 109840266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, SM_TIME_DEFAULT, 109940266059SGregory Neil Shapiro '\n'); 110040266059SGregory Neil Shapiro if (sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 110140266059SGregory Neil Shapiro mci->mci_mailer->m_eol) == SM_IO_EOF) 110206f25ae9SGregory Neil Shapiro break; 1103193538b7SGregory Neil Shapiro else 1104193538b7SGregory Neil Shapiro { 1105193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 110640266059SGregory Neil Shapiro DataProgress = true; 1107193538b7SGregory Neil Shapiro } 1108c2aa98e2SPeter Wemm if (l < end && *l == '\n') 1109c2aa98e2SPeter Wemm { 1110c2aa98e2SPeter Wemm if (*++l != ' ' && *l != '\t' && *l != '\0' && 1111c2aa98e2SPeter Wemm bitset(PXLF_HEADER, pxflags)) 1112c2aa98e2SPeter Wemm { 111340266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 111440266059SGregory Neil Shapiro ' ') == SM_IO_EOF) 111506f25ae9SGregory Neil Shapiro break; 1116193538b7SGregory Neil Shapiro else 1117193538b7SGregory Neil Shapiro { 1118193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 111940266059SGregory Neil Shapiro DataProgress = true; 1120193538b7SGregory Neil Shapiro } 112140266059SGregory Neil Shapiro 1122c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 112340266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 112440266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' '); 1125c2aa98e2SPeter Wemm } 1126c2aa98e2SPeter Wemm } 112740266059SGregory Neil Shapiro 112840266059SGregory Neil Shapiro /* record progress for DATA timeout */ 112940266059SGregory Neil Shapiro DataProgress = true; 1130c2aa98e2SPeter Wemm } while (l < end); 1131c2aa98e2SPeter Wemm } 113240266059SGregory Neil Shapiro /* 1133c2aa98e2SPeter Wemm ** XUNLINK -- unlink a file, doing logging as appropriate. 1134c2aa98e2SPeter Wemm ** 1135c2aa98e2SPeter Wemm ** Parameters: 1136c2aa98e2SPeter Wemm ** f -- name of file to unlink. 1137c2aa98e2SPeter Wemm ** 1138c2aa98e2SPeter Wemm ** Returns: 113940266059SGregory Neil Shapiro ** return value of unlink() 1140c2aa98e2SPeter Wemm ** 1141c2aa98e2SPeter Wemm ** Side Effects: 1142c2aa98e2SPeter Wemm ** f is unlinked. 1143c2aa98e2SPeter Wemm */ 1144c2aa98e2SPeter Wemm 114540266059SGregory Neil Shapiro int 1146c2aa98e2SPeter Wemm xunlink(f) 1147c2aa98e2SPeter Wemm char *f; 1148c2aa98e2SPeter Wemm { 1149c2aa98e2SPeter Wemm register int i; 115040266059SGregory Neil Shapiro int save_errno; 1151c2aa98e2SPeter Wemm 1152c2aa98e2SPeter Wemm if (LogLevel > 98) 115340266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "unlink %s", f); 1154c2aa98e2SPeter Wemm 1155c2aa98e2SPeter Wemm i = unlink(f); 115640266059SGregory Neil Shapiro save_errno = errno; 1157c2aa98e2SPeter Wemm if (i < 0 && LogLevel > 97) 115840266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s: unlink-fail %d", 1159c2aa98e2SPeter Wemm f, errno); 116040266059SGregory Neil Shapiro if (i >= 0) 116140266059SGregory Neil Shapiro SYNC_DIR(f, false); 116240266059SGregory Neil Shapiro errno = save_errno; 116340266059SGregory Neil Shapiro return i; 1164c2aa98e2SPeter Wemm } 116540266059SGregory Neil Shapiro /* 1166c2aa98e2SPeter Wemm ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 1167c2aa98e2SPeter Wemm ** 1168c2aa98e2SPeter Wemm ** Parameters: 1169c2aa98e2SPeter Wemm ** buf -- place to put the input line. 1170c2aa98e2SPeter Wemm ** siz -- size of buf. 1171c2aa98e2SPeter Wemm ** fp -- file to read from. 1172c2aa98e2SPeter Wemm ** timeout -- the timeout before error occurs. 1173c2aa98e2SPeter Wemm ** during -- what we are trying to read (for error messages). 1174c2aa98e2SPeter Wemm ** 1175c2aa98e2SPeter Wemm ** Returns: 117640266059SGregory Neil Shapiro ** NULL on error (including timeout). This may also leave 1177c2aa98e2SPeter Wemm ** buf containing a null string. 1178c2aa98e2SPeter Wemm ** buf otherwise. 1179c2aa98e2SPeter Wemm */ 1180c2aa98e2SPeter Wemm 118106f25ae9SGregory Neil Shapiro 1182c2aa98e2SPeter Wemm char * 1183c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during) 1184c2aa98e2SPeter Wemm char *buf; 1185c2aa98e2SPeter Wemm int siz; 118640266059SGregory Neil Shapiro SM_FILE_T *fp; 1187c2aa98e2SPeter Wemm time_t timeout; 1188c2aa98e2SPeter Wemm char *during; 1189c2aa98e2SPeter Wemm { 1190c2aa98e2SPeter Wemm register char *p; 11912e43090eSPeter Wemm int save_errno; 119240266059SGregory Neil Shapiro int io_timeout; 119340266059SGregory Neil Shapiro 119440266059SGregory Neil Shapiro SM_REQUIRE(siz > 0); 119540266059SGregory Neil Shapiro SM_REQUIRE(buf != NULL); 1196c2aa98e2SPeter Wemm 1197c2aa98e2SPeter Wemm if (fp == NULL) 1198c2aa98e2SPeter Wemm { 1199c2aa98e2SPeter Wemm buf[0] = '\0'; 120040266059SGregory Neil Shapiro errno = EBADF; 1201c2aa98e2SPeter Wemm return NULL; 1202c2aa98e2SPeter Wemm } 1203c2aa98e2SPeter Wemm 120440266059SGregory Neil Shapiro /* try to read */ 120540266059SGregory Neil Shapiro p = NULL; 120640266059SGregory Neil Shapiro errno = 0; 120740266059SGregory Neil Shapiro 120840266059SGregory Neil Shapiro /* convert the timeout to sm_io notation */ 120940266059SGregory Neil Shapiro io_timeout = (timeout <= 0) ? SM_TIME_DEFAULT : timeout * 1000; 121040266059SGregory Neil Shapiro while (!sm_io_eof(fp) && !sm_io_error(fp)) 1211c2aa98e2SPeter Wemm { 121240266059SGregory Neil Shapiro errno = 0; 121340266059SGregory Neil Shapiro p = sm_io_fgets(fp, io_timeout, buf, siz); 121440266059SGregory Neil Shapiro if (p == NULL && errno == EAGAIN) 1215c2aa98e2SPeter Wemm { 121640266059SGregory Neil Shapiro /* The sm_io_fgets() call timedout */ 1217c2aa98e2SPeter Wemm if (LogLevel > 1) 1218c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 1219c2aa98e2SPeter Wemm "timeout waiting for input from %.100s during %s", 122040266059SGregory Neil Shapiro CURHOSTNAME, 1221c2aa98e2SPeter Wemm during); 1222c2aa98e2SPeter Wemm buf[0] = '\0'; 1223c2aa98e2SPeter Wemm #if XDEBUG 1224c2aa98e2SPeter Wemm checkfd012(during); 122506f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1226c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 122740266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, 122840266059SGregory Neil Shapiro SM_TIME_DEFAULT, 122940266059SGregory Neil Shapiro "%05d <<< [TIMEOUT]\n", 123040266059SGregory Neil Shapiro (int) CurrentPid); 123140266059SGregory Neil Shapiro errno = ETIMEDOUT; 123206f25ae9SGregory Neil Shapiro return NULL; 1233c2aa98e2SPeter Wemm } 1234c2aa98e2SPeter Wemm if (p != NULL || errno != EINTR) 1235c2aa98e2SPeter Wemm break; 123640266059SGregory Neil Shapiro (void) sm_io_clearerr(fp); 1237c2aa98e2SPeter Wemm } 12382e43090eSPeter Wemm save_errno = errno; 1239c2aa98e2SPeter Wemm 1240c2aa98e2SPeter Wemm /* clean up the books and exit */ 1241c2aa98e2SPeter Wemm LineNumber++; 1242c2aa98e2SPeter Wemm if (p == NULL) 1243c2aa98e2SPeter Wemm { 1244c2aa98e2SPeter Wemm buf[0] = '\0'; 1245c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 124640266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 124740266059SGregory Neil Shapiro "%05d <<< [EOF]\n", 124840266059SGregory Neil Shapiro (int) CurrentPid); 12492e43090eSPeter Wemm errno = save_errno; 125006f25ae9SGregory Neil Shapiro return NULL; 1251c2aa98e2SPeter Wemm } 1252c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 125340266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 125440266059SGregory Neil Shapiro "%05d <<< %s", (int) CurrentPid, buf); 1255c2aa98e2SPeter Wemm if (SevenBitInput) 1256c2aa98e2SPeter Wemm { 1257c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1258c2aa98e2SPeter Wemm *p &= ~0200; 1259c2aa98e2SPeter Wemm } 1260c2aa98e2SPeter Wemm else if (!HasEightBits) 1261c2aa98e2SPeter Wemm { 1262c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1263c2aa98e2SPeter Wemm { 1264c2aa98e2SPeter Wemm if (bitset(0200, *p)) 1265c2aa98e2SPeter Wemm { 126640266059SGregory Neil Shapiro HasEightBits = true; 1267c2aa98e2SPeter Wemm break; 1268c2aa98e2SPeter Wemm } 1269c2aa98e2SPeter Wemm } 1270c2aa98e2SPeter Wemm } 127106f25ae9SGregory Neil Shapiro return buf; 1272c2aa98e2SPeter Wemm } 12738774250cSGregory Neil Shapiro /* 127440266059SGregory Neil Shapiro ** FGETFOLDED -- like fgets, but knows about folded lines. 1275c2aa98e2SPeter Wemm ** 1276c2aa98e2SPeter Wemm ** Parameters: 1277c2aa98e2SPeter Wemm ** buf -- place to put result. 1278c2aa98e2SPeter Wemm ** n -- bytes available. 1279c2aa98e2SPeter Wemm ** f -- file to read from. 1280c2aa98e2SPeter Wemm ** 1281c2aa98e2SPeter Wemm ** Returns: 128240266059SGregory Neil Shapiro ** input line(s) on success, NULL on error or SM_IO_EOF. 1283c2aa98e2SPeter Wemm ** This will normally be buf -- unless the line is too 128440266059SGregory Neil Shapiro ** long, when it will be sm_malloc_x()ed. 1285c2aa98e2SPeter Wemm ** 1286c2aa98e2SPeter Wemm ** Side Effects: 1287c2aa98e2SPeter Wemm ** buf gets lines from f, with continuation lines (lines 1288c2aa98e2SPeter Wemm ** with leading white space) appended. CRLF's are mapped 1289c2aa98e2SPeter Wemm ** into single newlines. Any trailing NL is stripped. 1290c2aa98e2SPeter Wemm */ 1291c2aa98e2SPeter Wemm 1292c2aa98e2SPeter Wemm char * 1293c2aa98e2SPeter Wemm fgetfolded(buf, n, f) 1294c2aa98e2SPeter Wemm char *buf; 1295c2aa98e2SPeter Wemm register int n; 129640266059SGregory Neil Shapiro SM_FILE_T *f; 1297c2aa98e2SPeter Wemm { 1298c2aa98e2SPeter Wemm register char *p = buf; 1299c2aa98e2SPeter Wemm char *bp = buf; 1300c2aa98e2SPeter Wemm register int i; 1301c2aa98e2SPeter Wemm 130240266059SGregory Neil Shapiro SM_REQUIRE(n > 0); 130340266059SGregory Neil Shapiro SM_REQUIRE(buf != NULL); 130440266059SGregory Neil Shapiro if (f == NULL) 130540266059SGregory Neil Shapiro { 130640266059SGregory Neil Shapiro buf[0] = '\0'; 130740266059SGregory Neil Shapiro errno = EBADF; 130840266059SGregory Neil Shapiro return NULL; 130940266059SGregory Neil Shapiro } 131040266059SGregory Neil Shapiro 1311c2aa98e2SPeter Wemm n--; 131240266059SGregory Neil Shapiro while ((i = sm_io_getc(f, SM_TIME_DEFAULT)) != SM_IO_EOF) 1313c2aa98e2SPeter Wemm { 1314c2aa98e2SPeter Wemm if (i == '\r') 1315c2aa98e2SPeter Wemm { 131640266059SGregory Neil Shapiro i = sm_io_getc(f, SM_TIME_DEFAULT); 1317c2aa98e2SPeter Wemm if (i != '\n') 1318c2aa98e2SPeter Wemm { 131940266059SGregory Neil Shapiro if (i != SM_IO_EOF) 132040266059SGregory Neil Shapiro (void) sm_io_ungetc(f, SM_TIME_DEFAULT, 132140266059SGregory Neil Shapiro i); 1322c2aa98e2SPeter Wemm i = '\r'; 1323c2aa98e2SPeter Wemm } 1324c2aa98e2SPeter Wemm } 1325c2aa98e2SPeter Wemm if (--n <= 0) 1326c2aa98e2SPeter Wemm { 1327c2aa98e2SPeter Wemm /* allocate new space */ 1328c2aa98e2SPeter Wemm char *nbp; 1329c2aa98e2SPeter Wemm int nn; 1330c2aa98e2SPeter Wemm 1331c2aa98e2SPeter Wemm nn = (p - bp); 1332c2aa98e2SPeter Wemm if (nn < MEMCHUNKSIZE) 1333c2aa98e2SPeter Wemm nn *= 2; 1334c2aa98e2SPeter Wemm else 1335c2aa98e2SPeter Wemm nn += MEMCHUNKSIZE; 133640266059SGregory Neil Shapiro nbp = sm_malloc_x(nn); 133706f25ae9SGregory Neil Shapiro memmove(nbp, bp, p - bp); 1338c2aa98e2SPeter Wemm p = &nbp[p - bp]; 1339c2aa98e2SPeter Wemm if (bp != buf) 13408774250cSGregory Neil Shapiro sm_free(bp); 1341c2aa98e2SPeter Wemm bp = nbp; 1342c2aa98e2SPeter Wemm n = nn - (p - bp); 1343c2aa98e2SPeter Wemm } 1344c2aa98e2SPeter Wemm *p++ = i; 1345c2aa98e2SPeter Wemm if (i == '\n') 1346c2aa98e2SPeter Wemm { 1347c2aa98e2SPeter Wemm LineNumber++; 134840266059SGregory Neil Shapiro i = sm_io_getc(f, SM_TIME_DEFAULT); 134940266059SGregory Neil Shapiro if (i != SM_IO_EOF) 135040266059SGregory Neil Shapiro (void) sm_io_ungetc(f, SM_TIME_DEFAULT, i); 1351c2aa98e2SPeter Wemm if (i != ' ' && i != '\t') 1352c2aa98e2SPeter Wemm break; 1353c2aa98e2SPeter Wemm } 1354c2aa98e2SPeter Wemm } 1355c2aa98e2SPeter Wemm if (p == bp) 135606f25ae9SGregory Neil Shapiro return NULL; 1357c2aa98e2SPeter Wemm if (p[-1] == '\n') 1358c2aa98e2SPeter Wemm p--; 1359c2aa98e2SPeter Wemm *p = '\0'; 136006f25ae9SGregory Neil Shapiro return bp; 1361c2aa98e2SPeter Wemm } 136240266059SGregory Neil Shapiro /* 1363c2aa98e2SPeter Wemm ** CURTIME -- return current time. 1364c2aa98e2SPeter Wemm ** 1365c2aa98e2SPeter Wemm ** Parameters: 1366c2aa98e2SPeter Wemm ** none. 1367c2aa98e2SPeter Wemm ** 1368c2aa98e2SPeter Wemm ** Returns: 1369c2aa98e2SPeter Wemm ** the current time. 1370c2aa98e2SPeter Wemm */ 1371c2aa98e2SPeter Wemm 1372c2aa98e2SPeter Wemm time_t 1373c2aa98e2SPeter Wemm curtime() 1374c2aa98e2SPeter Wemm { 1375c2aa98e2SPeter Wemm auto time_t t; 1376c2aa98e2SPeter Wemm 1377c2aa98e2SPeter Wemm (void) time(&t); 137806f25ae9SGregory Neil Shapiro return t; 1379c2aa98e2SPeter Wemm } 138040266059SGregory Neil Shapiro /* 1381c2aa98e2SPeter Wemm ** ATOBOOL -- convert a string representation to boolean. 1382c2aa98e2SPeter Wemm ** 138340266059SGregory Neil Shapiro ** Defaults to false 1384c2aa98e2SPeter Wemm ** 1385c2aa98e2SPeter Wemm ** Parameters: 138640266059SGregory Neil Shapiro ** s -- string to convert. Takes "tTyY", empty, and NULL as true, 1387c2aa98e2SPeter Wemm ** others as false. 1388c2aa98e2SPeter Wemm ** 1389c2aa98e2SPeter Wemm ** Returns: 1390c2aa98e2SPeter Wemm ** A boolean representation of the string. 1391c2aa98e2SPeter Wemm */ 1392c2aa98e2SPeter Wemm 1393c2aa98e2SPeter Wemm bool 1394c2aa98e2SPeter Wemm atobool(s) 1395c2aa98e2SPeter Wemm register char *s; 1396c2aa98e2SPeter Wemm { 1397c2aa98e2SPeter Wemm if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 139840266059SGregory Neil Shapiro return true; 139940266059SGregory Neil Shapiro return false; 1400c2aa98e2SPeter Wemm } 140140266059SGregory Neil Shapiro /* 1402c2aa98e2SPeter Wemm ** ATOOCT -- convert a string representation to octal. 1403c2aa98e2SPeter Wemm ** 1404c2aa98e2SPeter Wemm ** Parameters: 1405c2aa98e2SPeter Wemm ** s -- string to convert. 1406c2aa98e2SPeter Wemm ** 1407c2aa98e2SPeter Wemm ** Returns: 1408c2aa98e2SPeter Wemm ** An integer representing the string interpreted as an 1409c2aa98e2SPeter Wemm ** octal number. 1410c2aa98e2SPeter Wemm */ 1411c2aa98e2SPeter Wemm 1412c2aa98e2SPeter Wemm int 1413c2aa98e2SPeter Wemm atooct(s) 1414c2aa98e2SPeter Wemm register char *s; 1415c2aa98e2SPeter Wemm { 1416c2aa98e2SPeter Wemm register int i = 0; 1417c2aa98e2SPeter Wemm 1418c2aa98e2SPeter Wemm while (*s >= '0' && *s <= '7') 1419c2aa98e2SPeter Wemm i = (i << 3) | (*s++ - '0'); 142006f25ae9SGregory Neil Shapiro return i; 1421c2aa98e2SPeter Wemm } 142240266059SGregory Neil Shapiro /* 1423c2aa98e2SPeter Wemm ** BITINTERSECT -- tell if two bitmaps intersect 1424c2aa98e2SPeter Wemm ** 1425c2aa98e2SPeter Wemm ** Parameters: 1426c2aa98e2SPeter Wemm ** a, b -- the bitmaps in question 1427c2aa98e2SPeter Wemm ** 1428c2aa98e2SPeter Wemm ** Returns: 142940266059SGregory Neil Shapiro ** true if they have a non-null intersection 143040266059SGregory Neil Shapiro ** false otherwise 1431c2aa98e2SPeter Wemm */ 1432c2aa98e2SPeter Wemm 1433c2aa98e2SPeter Wemm bool 1434c2aa98e2SPeter Wemm bitintersect(a, b) 143506f25ae9SGregory Neil Shapiro BITMAP256 a; 143606f25ae9SGregory Neil Shapiro BITMAP256 b; 1437c2aa98e2SPeter Wemm { 1438c2aa98e2SPeter Wemm int i; 1439c2aa98e2SPeter Wemm 1440c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1441193538b7SGregory Neil Shapiro { 1442c2aa98e2SPeter Wemm if ((a[i] & b[i]) != 0) 144340266059SGregory Neil Shapiro return true; 1444193538b7SGregory Neil Shapiro } 144540266059SGregory Neil Shapiro return false; 1446c2aa98e2SPeter Wemm } 144740266059SGregory Neil Shapiro /* 1448c2aa98e2SPeter Wemm ** BITZEROP -- tell if a bitmap is all zero 1449c2aa98e2SPeter Wemm ** 1450c2aa98e2SPeter Wemm ** Parameters: 1451c2aa98e2SPeter Wemm ** map -- the bit map to check 1452c2aa98e2SPeter Wemm ** 1453c2aa98e2SPeter Wemm ** Returns: 145440266059SGregory Neil Shapiro ** true if map is all zero. 145540266059SGregory Neil Shapiro ** false if there are any bits set in map. 1456c2aa98e2SPeter Wemm */ 1457c2aa98e2SPeter Wemm 1458c2aa98e2SPeter Wemm bool 1459c2aa98e2SPeter Wemm bitzerop(map) 146006f25ae9SGregory Neil Shapiro BITMAP256 map; 1461c2aa98e2SPeter Wemm { 1462c2aa98e2SPeter Wemm int i; 1463c2aa98e2SPeter Wemm 1464c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1465193538b7SGregory Neil Shapiro { 1466c2aa98e2SPeter Wemm if (map[i] != 0) 146740266059SGregory Neil Shapiro return false; 1468193538b7SGregory Neil Shapiro } 146940266059SGregory Neil Shapiro return true; 1470c2aa98e2SPeter Wemm } 147140266059SGregory Neil Shapiro /* 1472c2aa98e2SPeter Wemm ** STRCONTAINEDIN -- tell if one string is contained in another 1473c2aa98e2SPeter Wemm ** 1474c2aa98e2SPeter Wemm ** Parameters: 147540266059SGregory Neil Shapiro ** icase -- ignore case? 1476c2aa98e2SPeter Wemm ** a -- possible substring. 1477c2aa98e2SPeter Wemm ** b -- possible superstring. 1478c2aa98e2SPeter Wemm ** 1479c2aa98e2SPeter Wemm ** Returns: 148040266059SGregory Neil Shapiro ** true if a is contained in b (case insensitive). 148140266059SGregory Neil Shapiro ** false otherwise. 1482c2aa98e2SPeter Wemm */ 1483c2aa98e2SPeter Wemm 1484c2aa98e2SPeter Wemm bool 148540266059SGregory Neil Shapiro strcontainedin(icase, a, b) 148640266059SGregory Neil Shapiro bool icase; 1487c2aa98e2SPeter Wemm register char *a; 1488c2aa98e2SPeter Wemm register char *b; 1489c2aa98e2SPeter Wemm { 1490c2aa98e2SPeter Wemm int la; 1491c2aa98e2SPeter Wemm int lb; 1492c2aa98e2SPeter Wemm int c; 1493c2aa98e2SPeter Wemm 1494c2aa98e2SPeter Wemm la = strlen(a); 1495c2aa98e2SPeter Wemm lb = strlen(b); 1496c2aa98e2SPeter Wemm c = *a; 149740266059SGregory Neil Shapiro if (icase && isascii(c) && isupper(c)) 1498c2aa98e2SPeter Wemm c = tolower(c); 1499c2aa98e2SPeter Wemm for (; lb-- >= la; b++) 1500c2aa98e2SPeter Wemm { 150140266059SGregory Neil Shapiro if (icase) 150240266059SGregory Neil Shapiro { 150340266059SGregory Neil Shapiro if (*b != c && 150440266059SGregory Neil Shapiro isascii(*b) && isupper(*b) && tolower(*b) != c) 1505c2aa98e2SPeter Wemm continue; 150640266059SGregory Neil Shapiro if (sm_strncasecmp(a, b, la) == 0) 150740266059SGregory Neil Shapiro return true; 1508c2aa98e2SPeter Wemm } 150940266059SGregory Neil Shapiro else 151040266059SGregory Neil Shapiro { 151140266059SGregory Neil Shapiro if (*b != c) 151240266059SGregory Neil Shapiro continue; 151340266059SGregory Neil Shapiro if (strncmp(a, b, la) == 0) 151440266059SGregory Neil Shapiro return true; 1515c2aa98e2SPeter Wemm } 151640266059SGregory Neil Shapiro } 151740266059SGregory Neil Shapiro return false; 151840266059SGregory Neil Shapiro } 151940266059SGregory Neil Shapiro /* 1520c2aa98e2SPeter Wemm ** CHECKFD012 -- check low numbered file descriptors 1521c2aa98e2SPeter Wemm ** 1522c2aa98e2SPeter Wemm ** File descriptors 0, 1, and 2 should be open at all times. 1523c2aa98e2SPeter Wemm ** This routine verifies that, and fixes it if not true. 1524c2aa98e2SPeter Wemm ** 1525c2aa98e2SPeter Wemm ** Parameters: 1526c2aa98e2SPeter Wemm ** where -- a tag printed if the assertion failed 1527c2aa98e2SPeter Wemm ** 1528c2aa98e2SPeter Wemm ** Returns: 1529c2aa98e2SPeter Wemm ** none 1530c2aa98e2SPeter Wemm */ 1531c2aa98e2SPeter Wemm 1532c2aa98e2SPeter Wemm void 1533c2aa98e2SPeter Wemm checkfd012(where) 1534c2aa98e2SPeter Wemm char *where; 1535c2aa98e2SPeter Wemm { 1536c2aa98e2SPeter Wemm #if XDEBUG 1537c2aa98e2SPeter Wemm register int i; 1538c2aa98e2SPeter Wemm 1539c2aa98e2SPeter Wemm for (i = 0; i < 3; i++) 1540c2aa98e2SPeter Wemm fill_fd(i, where); 1541c2aa98e2SPeter Wemm #endif /* XDEBUG */ 1542c2aa98e2SPeter Wemm } 154340266059SGregory Neil Shapiro /* 1544c2aa98e2SPeter Wemm ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1545c2aa98e2SPeter Wemm ** 1546c2aa98e2SPeter Wemm ** Parameters: 1547c2aa98e2SPeter Wemm ** fd -- file descriptor to check. 1548c2aa98e2SPeter Wemm ** where -- tag to print on failure. 1549c2aa98e2SPeter Wemm ** 1550c2aa98e2SPeter Wemm ** Returns: 1551c2aa98e2SPeter Wemm ** none. 1552c2aa98e2SPeter Wemm */ 1553c2aa98e2SPeter Wemm 1554c2aa98e2SPeter Wemm void 1555c2aa98e2SPeter Wemm checkfdopen(fd, where) 1556c2aa98e2SPeter Wemm int fd; 1557c2aa98e2SPeter Wemm char *where; 1558c2aa98e2SPeter Wemm { 1559c2aa98e2SPeter Wemm #if XDEBUG 1560c2aa98e2SPeter Wemm struct stat st; 1561c2aa98e2SPeter Wemm 1562c2aa98e2SPeter Wemm if (fstat(fd, &st) < 0 && errno == EBADF) 1563c2aa98e2SPeter Wemm { 1564c2aa98e2SPeter Wemm syserr("checkfdopen(%d): %s not open as expected!", fd, where); 156540266059SGregory Neil Shapiro printopenfds(true); 1566c2aa98e2SPeter Wemm } 156706f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1568c2aa98e2SPeter Wemm } 156940266059SGregory Neil Shapiro /* 1570c2aa98e2SPeter Wemm ** CHECKFDS -- check for new or missing file descriptors 1571c2aa98e2SPeter Wemm ** 1572c2aa98e2SPeter Wemm ** Parameters: 1573c2aa98e2SPeter Wemm ** where -- tag for printing. If null, take a base line. 1574c2aa98e2SPeter Wemm ** 1575c2aa98e2SPeter Wemm ** Returns: 1576c2aa98e2SPeter Wemm ** none 1577c2aa98e2SPeter Wemm ** 1578c2aa98e2SPeter Wemm ** Side Effects: 1579c2aa98e2SPeter Wemm ** If where is set, shows changes since the last call. 1580c2aa98e2SPeter Wemm */ 1581c2aa98e2SPeter Wemm 1582c2aa98e2SPeter Wemm void 1583c2aa98e2SPeter Wemm checkfds(where) 1584c2aa98e2SPeter Wemm char *where; 1585c2aa98e2SPeter Wemm { 1586c2aa98e2SPeter Wemm int maxfd; 1587c2aa98e2SPeter Wemm register int fd; 158840266059SGregory Neil Shapiro bool printhdr = true; 1589c2aa98e2SPeter Wemm int save_errno = errno; 159006f25ae9SGregory Neil Shapiro static BITMAP256 baseline; 1591c2aa98e2SPeter Wemm extern int DtableSize; 1592c2aa98e2SPeter Wemm 1593193538b7SGregory Neil Shapiro if (DtableSize > BITMAPBITS) 1594193538b7SGregory Neil Shapiro maxfd = BITMAPBITS; 1595c2aa98e2SPeter Wemm else 1596c2aa98e2SPeter Wemm maxfd = DtableSize; 1597c2aa98e2SPeter Wemm if (where == NULL) 1598c2aa98e2SPeter Wemm clrbitmap(baseline); 1599c2aa98e2SPeter Wemm 1600c2aa98e2SPeter Wemm for (fd = 0; fd < maxfd; fd++) 1601c2aa98e2SPeter Wemm { 1602c2aa98e2SPeter Wemm struct stat stbuf; 1603c2aa98e2SPeter Wemm 1604c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 1605c2aa98e2SPeter Wemm { 1606c2aa98e2SPeter Wemm if (!bitnset(fd, baseline)) 1607c2aa98e2SPeter Wemm continue; 1608c2aa98e2SPeter Wemm clrbitn(fd, baseline); 1609c2aa98e2SPeter Wemm } 1610c2aa98e2SPeter Wemm else if (!bitnset(fd, baseline)) 1611c2aa98e2SPeter Wemm setbitn(fd, baseline); 1612c2aa98e2SPeter Wemm else 1613c2aa98e2SPeter Wemm continue; 1614c2aa98e2SPeter Wemm 1615c2aa98e2SPeter Wemm /* file state has changed */ 1616c2aa98e2SPeter Wemm if (where == NULL) 1617c2aa98e2SPeter Wemm continue; 1618c2aa98e2SPeter Wemm if (printhdr) 1619c2aa98e2SPeter Wemm { 1620c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1621c2aa98e2SPeter Wemm "%s: changed fds:", 1622c2aa98e2SPeter Wemm where); 162340266059SGregory Neil Shapiro printhdr = false; 1624c2aa98e2SPeter Wemm } 162540266059SGregory Neil Shapiro dumpfd(fd, true, true); 1626c2aa98e2SPeter Wemm } 1627c2aa98e2SPeter Wemm errno = save_errno; 1628c2aa98e2SPeter Wemm } 162940266059SGregory Neil Shapiro /* 1630c2aa98e2SPeter Wemm ** PRINTOPENFDS -- print the open file descriptors (for debugging) 1631c2aa98e2SPeter Wemm ** 1632c2aa98e2SPeter Wemm ** Parameters: 1633c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog; otherwise 1634c2aa98e2SPeter Wemm ** print for debugging. 1635c2aa98e2SPeter Wemm ** 1636c2aa98e2SPeter Wemm ** Returns: 1637c2aa98e2SPeter Wemm ** none. 1638c2aa98e2SPeter Wemm */ 1639c2aa98e2SPeter Wemm 164006f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 1641c2aa98e2SPeter Wemm # include <arpa/inet.h> 164206f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 1643c2aa98e2SPeter Wemm 1644c2aa98e2SPeter Wemm void 1645c2aa98e2SPeter Wemm printopenfds(logit) 1646c2aa98e2SPeter Wemm bool logit; 1647c2aa98e2SPeter Wemm { 1648c2aa98e2SPeter Wemm register int fd; 1649c2aa98e2SPeter Wemm extern int DtableSize; 1650c2aa98e2SPeter Wemm 1651c2aa98e2SPeter Wemm for (fd = 0; fd < DtableSize; fd++) 165240266059SGregory Neil Shapiro dumpfd(fd, false, logit); 1653c2aa98e2SPeter Wemm } 165440266059SGregory Neil Shapiro /* 1655c2aa98e2SPeter Wemm ** DUMPFD -- dump a file descriptor 1656c2aa98e2SPeter Wemm ** 1657c2aa98e2SPeter Wemm ** Parameters: 1658c2aa98e2SPeter Wemm ** fd -- the file descriptor to dump. 1659c2aa98e2SPeter Wemm ** printclosed -- if set, print a notification even if 1660c2aa98e2SPeter Wemm ** it is closed; otherwise print nothing. 1661c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog instead of stdout. 166240266059SGregory Neil Shapiro ** 166340266059SGregory Neil Shapiro ** Returns: 166440266059SGregory Neil Shapiro ** none. 1665c2aa98e2SPeter Wemm */ 1666c2aa98e2SPeter Wemm 1667c2aa98e2SPeter Wemm void 1668c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit) 1669c2aa98e2SPeter Wemm int fd; 1670c2aa98e2SPeter Wemm bool printclosed; 1671c2aa98e2SPeter Wemm bool logit; 1672c2aa98e2SPeter Wemm { 1673c2aa98e2SPeter Wemm register char *p; 1674c2aa98e2SPeter Wemm char *hp; 1675c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1676c2aa98e2SPeter Wemm SOCKADDR sa; 167706f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1678c2aa98e2SPeter Wemm auto SOCKADDR_LEN_T slen; 1679c2aa98e2SPeter Wemm int i; 1680c2aa98e2SPeter Wemm #if STAT64 > 0 1681c2aa98e2SPeter Wemm struct stat64 st; 168206f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1683c2aa98e2SPeter Wemm struct stat st; 168406f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1685c2aa98e2SPeter Wemm char buf[200]; 1686c2aa98e2SPeter Wemm 1687c2aa98e2SPeter Wemm p = buf; 168840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 1689c2aa98e2SPeter Wemm p += strlen(p); 1690c2aa98e2SPeter Wemm 1691c2aa98e2SPeter Wemm if ( 1692c2aa98e2SPeter Wemm #if STAT64 > 0 1693c2aa98e2SPeter Wemm fstat64(fd, &st) 169406f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1695c2aa98e2SPeter Wemm fstat(fd, &st) 169606f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1697c2aa98e2SPeter Wemm < 0) 1698c2aa98e2SPeter Wemm { 1699c2aa98e2SPeter Wemm if (errno != EBADF) 1700c2aa98e2SPeter Wemm { 170140266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 170240266059SGregory Neil Shapiro "CANNOT STAT (%s)", 170340266059SGregory Neil Shapiro sm_errstring(errno)); 1704c2aa98e2SPeter Wemm goto printit; 1705c2aa98e2SPeter Wemm } 1706c2aa98e2SPeter Wemm else if (printclosed) 1707c2aa98e2SPeter Wemm { 170840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "CLOSED"); 1709c2aa98e2SPeter Wemm goto printit; 1710c2aa98e2SPeter Wemm } 1711c2aa98e2SPeter Wemm return; 1712c2aa98e2SPeter Wemm } 1713c2aa98e2SPeter Wemm 1714c2aa98e2SPeter Wemm i = fcntl(fd, F_GETFL, NULL); 1715c2aa98e2SPeter Wemm if (i != -1) 1716c2aa98e2SPeter Wemm { 171740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 1718c2aa98e2SPeter Wemm p += strlen(p); 1719c2aa98e2SPeter Wemm } 1720c2aa98e2SPeter Wemm 172140266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "mode=%o: ", 172240266059SGregory Neil Shapiro (int) st.st_mode); 1723c2aa98e2SPeter Wemm p += strlen(p); 1724c2aa98e2SPeter Wemm switch (st.st_mode & S_IFMT) 1725c2aa98e2SPeter Wemm { 1726c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1727c2aa98e2SPeter Wemm case S_IFSOCK: 172840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "SOCK "); 1729c2aa98e2SPeter Wemm p += strlen(p); 173006f25ae9SGregory Neil Shapiro memset(&sa, '\0', sizeof sa); 1731c2aa98e2SPeter Wemm slen = sizeof sa; 1732c2aa98e2SPeter Wemm if (getsockname(fd, &sa.sa, &slen) < 0) 173340266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 173440266059SGregory Neil Shapiro sm_errstring(errno)); 1735c2aa98e2SPeter Wemm else 1736c2aa98e2SPeter Wemm { 1737c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 173806f25ae9SGregory Neil Shapiro if (hp == NULL) 173906f25ae9SGregory Neil Shapiro { 174006f25ae9SGregory Neil Shapiro /* EMPTY */ 174106f25ae9SGregory Neil Shapiro /* do nothing */ 174206f25ae9SGregory Neil Shapiro } 174306f25ae9SGregory Neil Shapiro # if NETINET 174406f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 174540266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 174640266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin.sin_port)); 174706f25ae9SGregory Neil Shapiro # endif /* NETINET */ 174806f25ae9SGregory Neil Shapiro # if NETINET6 174906f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 175040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 175140266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 175206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1753c2aa98e2SPeter Wemm else 175440266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 175540266059SGregory Neil Shapiro "%s", hp); 1756c2aa98e2SPeter Wemm } 1757c2aa98e2SPeter Wemm p += strlen(p); 175840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "->"); 1759c2aa98e2SPeter Wemm p += strlen(p); 1760c2aa98e2SPeter Wemm slen = sizeof sa; 1761c2aa98e2SPeter Wemm if (getpeername(fd, &sa.sa, &slen) < 0) 176240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 176340266059SGregory Neil Shapiro sm_errstring(errno)); 1764c2aa98e2SPeter Wemm else 1765c2aa98e2SPeter Wemm { 1766c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 176706f25ae9SGregory Neil Shapiro if (hp == NULL) 176806f25ae9SGregory Neil Shapiro { 176906f25ae9SGregory Neil Shapiro /* EMPTY */ 177006f25ae9SGregory Neil Shapiro /* do nothing */ 177106f25ae9SGregory Neil Shapiro } 177206f25ae9SGregory Neil Shapiro # if NETINET 177306f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 177440266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 177540266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin.sin_port)); 177606f25ae9SGregory Neil Shapiro # endif /* NETINET */ 177706f25ae9SGregory Neil Shapiro # if NETINET6 177806f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 177940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 178040266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 178106f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1782c2aa98e2SPeter Wemm else 178340266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 178440266059SGregory Neil Shapiro "%s", hp); 1785c2aa98e2SPeter Wemm } 1786c2aa98e2SPeter Wemm break; 178706f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1788c2aa98e2SPeter Wemm 1789c2aa98e2SPeter Wemm case S_IFCHR: 179040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "CHR: "); 1791c2aa98e2SPeter Wemm p += strlen(p); 1792c2aa98e2SPeter Wemm goto defprint; 1793c2aa98e2SPeter Wemm 179440266059SGregory Neil Shapiro #ifdef S_IFBLK 1795c2aa98e2SPeter Wemm case S_IFBLK: 179640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "BLK: "); 1797c2aa98e2SPeter Wemm p += strlen(p); 1798c2aa98e2SPeter Wemm goto defprint; 179940266059SGregory Neil Shapiro #endif /* S_IFBLK */ 1800c2aa98e2SPeter Wemm 1801c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 1802c2aa98e2SPeter Wemm case S_IFIFO: 180340266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "FIFO: "); 1804c2aa98e2SPeter Wemm p += strlen(p); 1805c2aa98e2SPeter Wemm goto defprint; 180606f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 1807c2aa98e2SPeter Wemm 1808c2aa98e2SPeter Wemm #ifdef S_IFDIR 1809c2aa98e2SPeter Wemm case S_IFDIR: 181040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "DIR: "); 1811c2aa98e2SPeter Wemm p += strlen(p); 1812c2aa98e2SPeter Wemm goto defprint; 181306f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */ 1814c2aa98e2SPeter Wemm 1815c2aa98e2SPeter Wemm #ifdef S_IFLNK 1816c2aa98e2SPeter Wemm case S_IFLNK: 181740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "LNK: "); 1818c2aa98e2SPeter Wemm p += strlen(p); 1819c2aa98e2SPeter Wemm goto defprint; 182006f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */ 1821c2aa98e2SPeter Wemm 1822c2aa98e2SPeter Wemm default: 1823c2aa98e2SPeter Wemm defprint: 182440266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 182540266059SGregory Neil Shapiro "dev=%d/%d, ino=%llu, nlink=%d, u/gid=%d/%d, ", 1826c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 182740266059SGregory Neil Shapiro (ULONGLONG_T) st.st_ino, 182806f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 182906f25ae9SGregory Neil Shapiro (int) st.st_gid); 183040266059SGregory Neil Shapiro p += strlen(p); 183140266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "size=%llu", 183240266059SGregory Neil Shapiro (ULONGLONG_T) st.st_size); 1833c2aa98e2SPeter Wemm break; 1834c2aa98e2SPeter Wemm } 1835c2aa98e2SPeter Wemm 1836c2aa98e2SPeter Wemm printit: 1837c2aa98e2SPeter Wemm if (logit) 1838c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 1839c2aa98e2SPeter Wemm "%.800s", buf); 1840c2aa98e2SPeter Wemm else 184140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s\n", buf); 1842c2aa98e2SPeter Wemm } 184340266059SGregory Neil Shapiro /* 1844c2aa98e2SPeter Wemm ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1845c2aa98e2SPeter Wemm ** 1846c2aa98e2SPeter Wemm ** Parameters: 1847c2aa98e2SPeter Wemm ** host -- the host to shorten (stripped in place). 1848c2aa98e2SPeter Wemm ** 1849c2aa98e2SPeter Wemm ** Returns: 185040266059SGregory Neil Shapiro ** place where string was truncated, NULL if not truncated. 1851c2aa98e2SPeter Wemm */ 1852c2aa98e2SPeter Wemm 1853602a2b1bSGregory Neil Shapiro char * 1854c2aa98e2SPeter Wemm shorten_hostname(host) 1855c2aa98e2SPeter Wemm char host[]; 1856c2aa98e2SPeter Wemm { 1857c2aa98e2SPeter Wemm register char *p; 1858c2aa98e2SPeter Wemm char *mydom; 1859c2aa98e2SPeter Wemm int i; 186040266059SGregory Neil Shapiro bool canon = false; 1861c2aa98e2SPeter Wemm 1862c2aa98e2SPeter Wemm /* strip off final dot */ 186340266059SGregory Neil Shapiro i = strlen(host); 186440266059SGregory Neil Shapiro p = &host[(i == 0) ? 0 : i - 1]; 1865c2aa98e2SPeter Wemm if (*p == '.') 1866c2aa98e2SPeter Wemm { 1867c2aa98e2SPeter Wemm *p = '\0'; 186840266059SGregory Neil Shapiro canon = true; 1869c2aa98e2SPeter Wemm } 1870c2aa98e2SPeter Wemm 1871c2aa98e2SPeter Wemm /* see if there is any domain at all -- if not, we are done */ 1872c2aa98e2SPeter Wemm p = strchr(host, '.'); 1873c2aa98e2SPeter Wemm if (p == NULL) 1874602a2b1bSGregory Neil Shapiro return NULL; 1875c2aa98e2SPeter Wemm 1876c2aa98e2SPeter Wemm /* yes, we have a domain -- see if it looks like us */ 1877c2aa98e2SPeter Wemm mydom = macvalue('m', CurEnv); 1878c2aa98e2SPeter Wemm if (mydom == NULL) 1879c2aa98e2SPeter Wemm mydom = ""; 1880c2aa98e2SPeter Wemm i = strlen(++p); 188140266059SGregory Neil Shapiro if ((canon ? sm_strcasecmp(p, mydom) 188240266059SGregory Neil Shapiro : sm_strncasecmp(p, mydom, i)) == 0 && 1883c2aa98e2SPeter Wemm (mydom[i] == '.' || mydom[i] == '\0')) 1884602a2b1bSGregory Neil Shapiro { 1885c2aa98e2SPeter Wemm *--p = '\0'; 1886602a2b1bSGregory Neil Shapiro return p; 1887602a2b1bSGregory Neil Shapiro } 1888602a2b1bSGregory Neil Shapiro return NULL; 1889c2aa98e2SPeter Wemm } 189040266059SGregory Neil Shapiro /* 1891c2aa98e2SPeter Wemm ** PROG_OPEN -- open a program for reading 1892c2aa98e2SPeter Wemm ** 1893c2aa98e2SPeter Wemm ** Parameters: 1894c2aa98e2SPeter Wemm ** argv -- the argument list. 1895c2aa98e2SPeter Wemm ** pfd -- pointer to a place to store the file descriptor. 1896c2aa98e2SPeter Wemm ** e -- the current envelope. 1897c2aa98e2SPeter Wemm ** 1898c2aa98e2SPeter Wemm ** Returns: 1899c2aa98e2SPeter Wemm ** pid of the process -- -1 if it failed. 1900c2aa98e2SPeter Wemm */ 1901c2aa98e2SPeter Wemm 19028774250cSGregory Neil Shapiro pid_t 1903c2aa98e2SPeter Wemm prog_open(argv, pfd, e) 1904c2aa98e2SPeter Wemm char **argv; 1905c2aa98e2SPeter Wemm int *pfd; 1906c2aa98e2SPeter Wemm ENVELOPE *e; 1907c2aa98e2SPeter Wemm { 19088774250cSGregory Neil Shapiro pid_t pid; 1909c2aa98e2SPeter Wemm int i; 191006f25ae9SGregory Neil Shapiro int save_errno; 191140266059SGregory Neil Shapiro int sff; 191240266059SGregory Neil Shapiro int ret; 1913c2aa98e2SPeter Wemm int fdv[2]; 1914c2aa98e2SPeter Wemm char *p, *q; 1915c2aa98e2SPeter Wemm char buf[MAXLINE + 1]; 1916c2aa98e2SPeter Wemm extern int DtableSize; 1917c2aa98e2SPeter Wemm 1918c2aa98e2SPeter Wemm if (pipe(fdv) < 0) 1919c2aa98e2SPeter Wemm { 1920c2aa98e2SPeter Wemm syserr("%s: cannot create pipe for stdout", argv[0]); 1921c2aa98e2SPeter Wemm return -1; 1922c2aa98e2SPeter Wemm } 1923c2aa98e2SPeter Wemm pid = fork(); 1924c2aa98e2SPeter Wemm if (pid < 0) 1925c2aa98e2SPeter Wemm { 1926c2aa98e2SPeter Wemm syserr("%s: cannot fork", argv[0]); 192706f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 192806f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1929c2aa98e2SPeter Wemm return -1; 1930c2aa98e2SPeter Wemm } 1931c2aa98e2SPeter Wemm if (pid > 0) 1932c2aa98e2SPeter Wemm { 1933c2aa98e2SPeter Wemm /* parent */ 193406f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1935c2aa98e2SPeter Wemm *pfd = fdv[0]; 1936c2aa98e2SPeter Wemm return pid; 1937c2aa98e2SPeter Wemm } 1938c2aa98e2SPeter Wemm 19398774250cSGregory Neil Shapiro /* Reset global flags */ 19408774250cSGregory Neil Shapiro RestartRequest = NULL; 194140266059SGregory Neil Shapiro RestartWorkGroup = false; 19428774250cSGregory Neil Shapiro ShutdownRequest = NULL; 19438774250cSGregory Neil Shapiro PendingSignal = 0; 194440266059SGregory Neil Shapiro CurrentPid = getpid(); 194540266059SGregory Neil Shapiro 194640266059SGregory Neil Shapiro /* 194740266059SGregory Neil Shapiro ** Initialize exception stack and default exception 194840266059SGregory Neil Shapiro ** handler for child process. 194940266059SGregory Neil Shapiro */ 195040266059SGregory Neil Shapiro 195140266059SGregory Neil Shapiro sm_exc_newthread(fatal_error); 195240266059SGregory Neil Shapiro 195340266059SGregory Neil Shapiro /* child -- close stdin */ 195440266059SGregory Neil Shapiro (void) close(0); 19558774250cSGregory Neil Shapiro 1956c2aa98e2SPeter Wemm /* stdout goes back to parent */ 195706f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 1958c2aa98e2SPeter Wemm if (dup2(fdv[1], 1) < 0) 1959c2aa98e2SPeter Wemm { 1960c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stdout", argv[0]); 1961c2aa98e2SPeter Wemm _exit(EX_OSERR); 1962c2aa98e2SPeter Wemm } 196306f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1964c2aa98e2SPeter Wemm 1965c2aa98e2SPeter Wemm /* stderr goes to transcript if available */ 1966c2aa98e2SPeter Wemm if (e->e_xfp != NULL) 1967c2aa98e2SPeter Wemm { 196806f25ae9SGregory Neil Shapiro int xfd; 196906f25ae9SGregory Neil Shapiro 197040266059SGregory Neil Shapiro xfd = sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL); 197106f25ae9SGregory Neil Shapiro if (xfd >= 0 && dup2(xfd, 2) < 0) 1972c2aa98e2SPeter Wemm { 1973c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stderr", argv[0]); 1974c2aa98e2SPeter Wemm _exit(EX_OSERR); 1975c2aa98e2SPeter Wemm } 1976c2aa98e2SPeter Wemm } 1977c2aa98e2SPeter Wemm 1978c2aa98e2SPeter Wemm /* this process has no right to the queue file */ 1979c2aa98e2SPeter Wemm if (e->e_lockfp != NULL) 198040266059SGregory Neil Shapiro (void) close(sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL)); 198106f25ae9SGregory Neil Shapiro 198206f25ae9SGregory Neil Shapiro /* chroot to the program mailer directory, if defined */ 198306f25ae9SGregory Neil Shapiro if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) 198406f25ae9SGregory Neil Shapiro { 198506f25ae9SGregory Neil Shapiro expand(ProgMailer->m_rootdir, buf, sizeof buf, e); 198606f25ae9SGregory Neil Shapiro if (chroot(buf) < 0) 198706f25ae9SGregory Neil Shapiro { 198806f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chroot(%s)", buf); 198906f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 199006f25ae9SGregory Neil Shapiro } 199106f25ae9SGregory Neil Shapiro if (chdir("/") < 0) 199206f25ae9SGregory Neil Shapiro { 199306f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chdir(/)"); 199406f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 199506f25ae9SGregory Neil Shapiro } 199606f25ae9SGregory Neil Shapiro } 1997c2aa98e2SPeter Wemm 1998c2aa98e2SPeter Wemm /* run as default user */ 1999c2aa98e2SPeter Wemm endpwent(); 200040266059SGregory Neil Shapiro sm_mbdb_terminate(); 2001c2aa98e2SPeter Wemm if (setgid(DefGid) < 0 && geteuid() == 0) 200206f25ae9SGregory Neil Shapiro { 2003c2aa98e2SPeter Wemm syserr("prog_open: setgid(%ld) failed", (long) DefGid); 200406f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 200506f25ae9SGregory Neil Shapiro } 2006c2aa98e2SPeter Wemm if (setuid(DefUid) < 0 && geteuid() == 0) 200706f25ae9SGregory Neil Shapiro { 2008c2aa98e2SPeter Wemm syserr("prog_open: setuid(%ld) failed", (long) DefUid); 200906f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 201006f25ae9SGregory Neil Shapiro } 2011c2aa98e2SPeter Wemm 2012c2aa98e2SPeter Wemm /* run in some directory */ 2013c2aa98e2SPeter Wemm if (ProgMailer != NULL) 2014c2aa98e2SPeter Wemm p = ProgMailer->m_execdir; 2015c2aa98e2SPeter Wemm else 2016c2aa98e2SPeter Wemm p = NULL; 2017c2aa98e2SPeter Wemm for (; p != NULL; p = q) 2018c2aa98e2SPeter Wemm { 2019c2aa98e2SPeter Wemm q = strchr(p, ':'); 2020c2aa98e2SPeter Wemm if (q != NULL) 2021c2aa98e2SPeter Wemm *q = '\0'; 2022c2aa98e2SPeter Wemm expand(p, buf, sizeof buf, e); 2023c2aa98e2SPeter Wemm if (q != NULL) 2024c2aa98e2SPeter Wemm *q++ = ':'; 2025c2aa98e2SPeter Wemm if (buf[0] != '\0' && chdir(buf) >= 0) 2026c2aa98e2SPeter Wemm break; 2027c2aa98e2SPeter Wemm } 2028c2aa98e2SPeter Wemm if (p == NULL) 2029c2aa98e2SPeter Wemm { 2030c2aa98e2SPeter Wemm /* backup directories */ 2031c2aa98e2SPeter Wemm if (chdir("/tmp") < 0) 2032c2aa98e2SPeter Wemm (void) chdir("/"); 2033c2aa98e2SPeter Wemm } 2034c2aa98e2SPeter Wemm 203540266059SGregory Neil Shapiro /* Check safety of program to be run */ 203640266059SGregory Neil Shapiro sff = SFF_ROOTOK|SFF_EXECOK; 203740266059SGregory Neil Shapiro if (!bitnset(DBS_RUNWRITABLEPROGRAM, DontBlameSendmail)) 203840266059SGregory Neil Shapiro sff |= SFF_NOGWFILES|SFF_NOWWFILES; 203940266059SGregory Neil Shapiro if (bitnset(DBS_RUNPROGRAMINUNSAFEDIRPATH, DontBlameSendmail)) 204040266059SGregory Neil Shapiro sff |= SFF_NOPATHCHECK; 204140266059SGregory Neil Shapiro else 204240266059SGregory Neil Shapiro sff |= SFF_SAFEDIRPATH; 204340266059SGregory Neil Shapiro ret = safefile(argv[0], DefUid, DefGid, DefUser, sff, 0, NULL); 204440266059SGregory Neil Shapiro if (ret != 0) 204540266059SGregory Neil Shapiro sm_syslog(LOG_INFO, e->e_id, 204640266059SGregory Neil Shapiro "Warning: prog_open: program %s unsafe: %s", 204740266059SGregory Neil Shapiro argv[0], sm_errstring(ret)); 204840266059SGregory Neil Shapiro 2049c2aa98e2SPeter Wemm /* arrange for all the files to be closed */ 2050c2aa98e2SPeter Wemm for (i = 3; i < DtableSize; i++) 2051c2aa98e2SPeter Wemm { 2052c2aa98e2SPeter Wemm register int j; 2053c2aa98e2SPeter Wemm 2054c2aa98e2SPeter Wemm if ((j = fcntl(i, F_GETFD, 0)) != -1) 205506f25ae9SGregory Neil Shapiro (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 2056c2aa98e2SPeter Wemm } 2057c2aa98e2SPeter Wemm 2058c2aa98e2SPeter Wemm /* now exec the process */ 205906f25ae9SGregory Neil Shapiro (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 2060c2aa98e2SPeter Wemm 2061c2aa98e2SPeter Wemm /* woops! failed */ 206206f25ae9SGregory Neil Shapiro save_errno = errno; 2063c2aa98e2SPeter Wemm syserr("%s: cannot exec", argv[0]); 206406f25ae9SGregory Neil Shapiro if (transienterror(save_errno)) 2065c2aa98e2SPeter Wemm _exit(EX_OSERR); 2066c2aa98e2SPeter Wemm _exit(EX_CONFIG); 2067c2aa98e2SPeter Wemm return -1; /* avoid compiler warning on IRIX */ 2068c2aa98e2SPeter Wemm } 206940266059SGregory Neil Shapiro /* 2070c2aa98e2SPeter Wemm ** GET_COLUMN -- look up a Column in a line buffer 2071c2aa98e2SPeter Wemm ** 2072c2aa98e2SPeter Wemm ** Parameters: 2073c2aa98e2SPeter Wemm ** line -- the raw text line to search. 2074c2aa98e2SPeter Wemm ** col -- the column number to fetch. 2075c2aa98e2SPeter Wemm ** delim -- the delimiter between columns. If null, 2076c2aa98e2SPeter Wemm ** use white space. 2077c2aa98e2SPeter Wemm ** buf -- the output buffer. 2078c2aa98e2SPeter Wemm ** buflen -- the length of buf. 2079c2aa98e2SPeter Wemm ** 2080c2aa98e2SPeter Wemm ** Returns: 2081c2aa98e2SPeter Wemm ** buf if successful. 2082c2aa98e2SPeter Wemm ** NULL otherwise. 2083c2aa98e2SPeter Wemm */ 2084c2aa98e2SPeter Wemm 2085c2aa98e2SPeter Wemm char * 2086c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen) 2087c2aa98e2SPeter Wemm char line[]; 2088c2aa98e2SPeter Wemm int col; 208906f25ae9SGregory Neil Shapiro int delim; 2090c2aa98e2SPeter Wemm char buf[]; 2091c2aa98e2SPeter Wemm int buflen; 2092c2aa98e2SPeter Wemm { 2093c2aa98e2SPeter Wemm char *p; 2094c2aa98e2SPeter Wemm char *begin, *end; 2095c2aa98e2SPeter Wemm int i; 2096c2aa98e2SPeter Wemm char delimbuf[4]; 2097c2aa98e2SPeter Wemm 209806f25ae9SGregory Neil Shapiro if ((char) delim == '\0') 209940266059SGregory Neil Shapiro (void) sm_strlcpy(delimbuf, "\n\t ", sizeof delimbuf); 2100c2aa98e2SPeter Wemm else 2101c2aa98e2SPeter Wemm { 210206f25ae9SGregory Neil Shapiro delimbuf[0] = (char) delim; 2103c2aa98e2SPeter Wemm delimbuf[1] = '\0'; 2104c2aa98e2SPeter Wemm } 2105c2aa98e2SPeter Wemm 2106c2aa98e2SPeter Wemm p = line; 2107c2aa98e2SPeter Wemm if (*p == '\0') 2108c2aa98e2SPeter Wemm return NULL; /* line empty */ 210906f25ae9SGregory Neil Shapiro if (*p == (char) delim && col == 0) 2110c2aa98e2SPeter Wemm return NULL; /* first column empty */ 2111c2aa98e2SPeter Wemm 2112c2aa98e2SPeter Wemm begin = line; 2113c2aa98e2SPeter Wemm 211406f25ae9SGregory Neil Shapiro if (col == 0 && (char) delim == '\0') 2115c2aa98e2SPeter Wemm { 2116c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2117c2aa98e2SPeter Wemm begin++; 2118c2aa98e2SPeter Wemm } 2119c2aa98e2SPeter Wemm 2120c2aa98e2SPeter Wemm for (i = 0; i < col; i++) 2121c2aa98e2SPeter Wemm { 2122c2aa98e2SPeter Wemm if ((begin = strpbrk(begin, delimbuf)) == NULL) 2123c2aa98e2SPeter Wemm return NULL; /* no such column */ 2124c2aa98e2SPeter Wemm begin++; 212506f25ae9SGregory Neil Shapiro if ((char) delim == '\0') 2126c2aa98e2SPeter Wemm { 2127c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2128c2aa98e2SPeter Wemm begin++; 2129c2aa98e2SPeter Wemm } 2130c2aa98e2SPeter Wemm } 2131c2aa98e2SPeter Wemm 2132c2aa98e2SPeter Wemm end = strpbrk(begin, delimbuf); 2133c2aa98e2SPeter Wemm if (end == NULL) 2134c2aa98e2SPeter Wemm i = strlen(begin); 2135c2aa98e2SPeter Wemm else 2136c2aa98e2SPeter Wemm i = end - begin; 2137c2aa98e2SPeter Wemm if (i >= buflen) 2138c2aa98e2SPeter Wemm i = buflen - 1; 213940266059SGregory Neil Shapiro (void) sm_strlcpy(buf, begin, i + 1); 2140c2aa98e2SPeter Wemm return buf; 2141c2aa98e2SPeter Wemm } 214240266059SGregory Neil Shapiro /* 2143c2aa98e2SPeter Wemm ** CLEANSTRCPY -- copy string keeping out bogus characters 2144c2aa98e2SPeter Wemm ** 2145c2aa98e2SPeter Wemm ** Parameters: 2146c2aa98e2SPeter Wemm ** t -- "to" string. 2147c2aa98e2SPeter Wemm ** f -- "from" string. 2148c2aa98e2SPeter Wemm ** l -- length of space available in "to" string. 2149c2aa98e2SPeter Wemm ** 2150c2aa98e2SPeter Wemm ** Returns: 2151c2aa98e2SPeter Wemm ** none. 2152c2aa98e2SPeter Wemm */ 2153c2aa98e2SPeter Wemm 2154c2aa98e2SPeter Wemm void 2155c2aa98e2SPeter Wemm cleanstrcpy(t, f, l) 2156c2aa98e2SPeter Wemm register char *t; 2157c2aa98e2SPeter Wemm register char *f; 2158c2aa98e2SPeter Wemm int l; 2159c2aa98e2SPeter Wemm { 2160c2aa98e2SPeter Wemm /* check for newlines and log if necessary */ 216140266059SGregory Neil Shapiro (void) denlstring(f, true, true); 2162c2aa98e2SPeter Wemm 216306f25ae9SGregory Neil Shapiro if (l <= 0) 216406f25ae9SGregory Neil Shapiro syserr("!cleanstrcpy: length == 0"); 216506f25ae9SGregory Neil Shapiro 2166c2aa98e2SPeter Wemm l--; 2167c2aa98e2SPeter Wemm while (l > 0 && *f != '\0') 2168c2aa98e2SPeter Wemm { 2169c2aa98e2SPeter Wemm if (isascii(*f) && 2170c2aa98e2SPeter Wemm (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 2171c2aa98e2SPeter Wemm { 2172c2aa98e2SPeter Wemm l--; 2173c2aa98e2SPeter Wemm *t++ = *f; 2174c2aa98e2SPeter Wemm } 2175c2aa98e2SPeter Wemm f++; 2176c2aa98e2SPeter Wemm } 2177c2aa98e2SPeter Wemm *t = '\0'; 2178c2aa98e2SPeter Wemm } 217940266059SGregory Neil Shapiro /* 2180c2aa98e2SPeter Wemm ** DENLSTRING -- convert newlines in a string to spaces 2181c2aa98e2SPeter Wemm ** 2182c2aa98e2SPeter Wemm ** Parameters: 2183c2aa98e2SPeter Wemm ** s -- the input string 2184c2aa98e2SPeter Wemm ** strict -- if set, don't permit continuation lines. 2185c2aa98e2SPeter Wemm ** logattacks -- if set, log attempted attacks. 2186c2aa98e2SPeter Wemm ** 2187c2aa98e2SPeter Wemm ** Returns: 2188c2aa98e2SPeter Wemm ** A pointer to a version of the string with newlines 2189c2aa98e2SPeter Wemm ** mapped to spaces. This should be copied. 2190c2aa98e2SPeter Wemm */ 2191c2aa98e2SPeter Wemm 2192c2aa98e2SPeter Wemm char * 2193c2aa98e2SPeter Wemm denlstring(s, strict, logattacks) 2194c2aa98e2SPeter Wemm char *s; 2195c2aa98e2SPeter Wemm bool strict; 2196c2aa98e2SPeter Wemm bool logattacks; 2197c2aa98e2SPeter Wemm { 2198c2aa98e2SPeter Wemm register char *p; 2199c2aa98e2SPeter Wemm int l; 2200c2aa98e2SPeter Wemm static char *bp = NULL; 2201c2aa98e2SPeter Wemm static int bl = 0; 2202c2aa98e2SPeter Wemm 2203c2aa98e2SPeter Wemm p = s; 2204c2aa98e2SPeter Wemm while ((p = strchr(p, '\n')) != NULL) 2205c2aa98e2SPeter Wemm if (strict || (*++p != ' ' && *p != '\t')) 2206c2aa98e2SPeter Wemm break; 2207c2aa98e2SPeter Wemm if (p == NULL) 2208c2aa98e2SPeter Wemm return s; 2209c2aa98e2SPeter Wemm 2210c2aa98e2SPeter Wemm l = strlen(s) + 1; 2211c2aa98e2SPeter Wemm if (bl < l) 2212c2aa98e2SPeter Wemm { 2213c2aa98e2SPeter Wemm /* allocate more space */ 221440266059SGregory Neil Shapiro char *nbp = sm_pmalloc_x(l); 221540266059SGregory Neil Shapiro 2216c2aa98e2SPeter Wemm if (bp != NULL) 22178774250cSGregory Neil Shapiro sm_free(bp); 221840266059SGregory Neil Shapiro bp = nbp; 2219c2aa98e2SPeter Wemm bl = l; 2220c2aa98e2SPeter Wemm } 222140266059SGregory Neil Shapiro (void) sm_strlcpy(bp, s, l); 2222c2aa98e2SPeter Wemm for (p = bp; (p = strchr(p, '\n')) != NULL; ) 2223c2aa98e2SPeter Wemm *p++ = ' '; 2224c2aa98e2SPeter Wemm 2225c2aa98e2SPeter Wemm if (logattacks) 2226c2aa98e2SPeter Wemm { 2227c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 2228c2aa98e2SPeter Wemm "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 2229c2aa98e2SPeter Wemm RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 2230c2aa98e2SPeter Wemm shortenstring(bp, MAXSHORTSTR)); 2231c2aa98e2SPeter Wemm } 2232c2aa98e2SPeter Wemm 2233c2aa98e2SPeter Wemm return bp; 2234c2aa98e2SPeter Wemm } 223540266059SGregory Neil Shapiro /* 223640266059SGregory Neil Shapiro ** STR2PRT -- convert "unprintable" characters in a string to \oct 223740266059SGregory Neil Shapiro ** 223840266059SGregory Neil Shapiro ** Parameters: 223940266059SGregory Neil Shapiro ** s -- string to convert 224040266059SGregory Neil Shapiro ** 224140266059SGregory Neil Shapiro ** Returns: 224240266059SGregory Neil Shapiro ** converted string. 224340266059SGregory Neil Shapiro ** This is a static local buffer, string must be copied 224440266059SGregory Neil Shapiro ** before this function is called again! 224540266059SGregory Neil Shapiro */ 224640266059SGregory Neil Shapiro 224740266059SGregory Neil Shapiro char * 224840266059SGregory Neil Shapiro str2prt(s) 224940266059SGregory Neil Shapiro char *s; 225040266059SGregory Neil Shapiro { 225140266059SGregory Neil Shapiro int l; 225240266059SGregory Neil Shapiro char c, *h; 225340266059SGregory Neil Shapiro bool ok; 225440266059SGregory Neil Shapiro static int len = 0; 225540266059SGregory Neil Shapiro static char *buf = NULL; 225640266059SGregory Neil Shapiro 225740266059SGregory Neil Shapiro if (s == NULL) 225840266059SGregory Neil Shapiro return NULL; 225940266059SGregory Neil Shapiro ok = true; 226040266059SGregory Neil Shapiro for (h = s, l = 1; *h != '\0'; h++, l++) 226140266059SGregory Neil Shapiro { 226240266059SGregory Neil Shapiro if (*h == '\\') 226340266059SGregory Neil Shapiro { 226440266059SGregory Neil Shapiro ++l; 226540266059SGregory Neil Shapiro ok = false; 226640266059SGregory Neil Shapiro } 226740266059SGregory Neil Shapiro else if (!(isascii(*h) && isprint(*h))) 226840266059SGregory Neil Shapiro { 226940266059SGregory Neil Shapiro l += 3; 227040266059SGregory Neil Shapiro ok = false; 227140266059SGregory Neil Shapiro } 227240266059SGregory Neil Shapiro } 227340266059SGregory Neil Shapiro if (ok) 227440266059SGregory Neil Shapiro return s; 227540266059SGregory Neil Shapiro if (l > len) 227640266059SGregory Neil Shapiro { 227740266059SGregory Neil Shapiro char *nbuf = sm_pmalloc_x(l); 227840266059SGregory Neil Shapiro 227940266059SGregory Neil Shapiro if (buf != NULL) 228040266059SGregory Neil Shapiro sm_free(buf); 228140266059SGregory Neil Shapiro len = l; 228240266059SGregory Neil Shapiro buf = nbuf; 228340266059SGregory Neil Shapiro } 228440266059SGregory Neil Shapiro for (h = buf; *s != '\0' && l > 0; s++, l--) 228540266059SGregory Neil Shapiro { 228640266059SGregory Neil Shapiro c = *s; 228740266059SGregory Neil Shapiro if (isascii(c) && isprint(c) && c != '\\') 228840266059SGregory Neil Shapiro { 228940266059SGregory Neil Shapiro *h++ = c; 229040266059SGregory Neil Shapiro } 229140266059SGregory Neil Shapiro else 229240266059SGregory Neil Shapiro { 229340266059SGregory Neil Shapiro *h++ = '\\'; 229440266059SGregory Neil Shapiro --l; 229540266059SGregory Neil Shapiro switch (c) 229640266059SGregory Neil Shapiro { 229740266059SGregory Neil Shapiro case '\\': 229840266059SGregory Neil Shapiro *h++ = '\\'; 229940266059SGregory Neil Shapiro break; 230040266059SGregory Neil Shapiro case '\t': 230140266059SGregory Neil Shapiro *h++ = 't'; 230240266059SGregory Neil Shapiro break; 230340266059SGregory Neil Shapiro case '\n': 230440266059SGregory Neil Shapiro *h++ = 'n'; 230540266059SGregory Neil Shapiro break; 230640266059SGregory Neil Shapiro case '\r': 230740266059SGregory Neil Shapiro *h++ = 'r'; 230840266059SGregory Neil Shapiro break; 230940266059SGregory Neil Shapiro default: 231040266059SGregory Neil Shapiro (void) sm_snprintf(h, l, "%03o", (int) c); 231140266059SGregory Neil Shapiro 231240266059SGregory Neil Shapiro /* 231340266059SGregory Neil Shapiro ** XXX since l is unsigned this may 231440266059SGregory Neil Shapiro ** wrap around if the calculation is screwed 231540266059SGregory Neil Shapiro ** up... 231640266059SGregory Neil Shapiro */ 231740266059SGregory Neil Shapiro 231840266059SGregory Neil Shapiro l -= 2; 231940266059SGregory Neil Shapiro h += 3; 232040266059SGregory Neil Shapiro break; 232140266059SGregory Neil Shapiro } 232240266059SGregory Neil Shapiro } 232340266059SGregory Neil Shapiro } 232440266059SGregory Neil Shapiro *h = '\0'; 232540266059SGregory Neil Shapiro buf[len - 1] = '\0'; 232640266059SGregory Neil Shapiro return buf; 232740266059SGregory Neil Shapiro } 232840266059SGregory Neil Shapiro /* 2329c2aa98e2SPeter Wemm ** PATH_IS_DIR -- check to see if file exists and is a directory. 2330c2aa98e2SPeter Wemm ** 2331c2aa98e2SPeter Wemm ** There are some additional checks for security violations in 2332c2aa98e2SPeter Wemm ** here. This routine is intended to be used for the host status 2333c2aa98e2SPeter Wemm ** support. 2334c2aa98e2SPeter Wemm ** 2335c2aa98e2SPeter Wemm ** Parameters: 2336c2aa98e2SPeter Wemm ** pathname -- pathname to check for directory-ness. 2337c2aa98e2SPeter Wemm ** createflag -- if set, create directory if needed. 2338c2aa98e2SPeter Wemm ** 2339c2aa98e2SPeter Wemm ** Returns: 234040266059SGregory Neil Shapiro ** true -- if the indicated pathname is a directory 234140266059SGregory Neil Shapiro ** false -- otherwise 2342c2aa98e2SPeter Wemm */ 2343c2aa98e2SPeter Wemm 2344c2aa98e2SPeter Wemm int 2345c2aa98e2SPeter Wemm path_is_dir(pathname, createflag) 2346c2aa98e2SPeter Wemm char *pathname; 2347c2aa98e2SPeter Wemm bool createflag; 2348c2aa98e2SPeter Wemm { 2349c2aa98e2SPeter Wemm struct stat statbuf; 2350c2aa98e2SPeter Wemm 2351c2aa98e2SPeter Wemm #if HASLSTAT 2352c2aa98e2SPeter Wemm if (lstat(pathname, &statbuf) < 0) 235306f25ae9SGregory Neil Shapiro #else /* HASLSTAT */ 2354c2aa98e2SPeter Wemm if (stat(pathname, &statbuf) < 0) 235506f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */ 2356c2aa98e2SPeter Wemm { 2357c2aa98e2SPeter Wemm if (errno != ENOENT || !createflag) 235840266059SGregory Neil Shapiro return false; 2359c2aa98e2SPeter Wemm if (mkdir(pathname, 0755) < 0) 236040266059SGregory Neil Shapiro return false; 236140266059SGregory Neil Shapiro return true; 2362c2aa98e2SPeter Wemm } 2363c2aa98e2SPeter Wemm if (!S_ISDIR(statbuf.st_mode)) 2364c2aa98e2SPeter Wemm { 2365c2aa98e2SPeter Wemm errno = ENOTDIR; 236640266059SGregory Neil Shapiro return false; 2367c2aa98e2SPeter Wemm } 2368c2aa98e2SPeter Wemm 2369c2aa98e2SPeter Wemm /* security: don't allow writable directories */ 2370c2aa98e2SPeter Wemm if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 2371c2aa98e2SPeter Wemm { 2372c2aa98e2SPeter Wemm errno = EACCES; 237340266059SGregory Neil Shapiro return false; 2374c2aa98e2SPeter Wemm } 237540266059SGregory Neil Shapiro return true; 2376c2aa98e2SPeter Wemm } 237740266059SGregory Neil Shapiro /* 2378c2aa98e2SPeter Wemm ** PROC_LIST_ADD -- add process id to list of our children 2379c2aa98e2SPeter Wemm ** 2380c2aa98e2SPeter Wemm ** Parameters: 2381c2aa98e2SPeter Wemm ** pid -- pid to add to list. 238206f25ae9SGregory Neil Shapiro ** task -- task of pid. 238306f25ae9SGregory Neil Shapiro ** type -- type of process. 238440266059SGregory Neil Shapiro ** count -- number of processes. 238540266059SGregory Neil Shapiro ** other -- other information for this type. 2386c2aa98e2SPeter Wemm ** 2387c2aa98e2SPeter Wemm ** Returns: 2388c2aa98e2SPeter Wemm ** none 238940266059SGregory Neil Shapiro ** 239040266059SGregory Neil Shapiro ** Side Effects: 239140266059SGregory Neil Shapiro ** May increase CurChildren. May grow ProcList. 2392c2aa98e2SPeter Wemm */ 2393c2aa98e2SPeter Wemm 239440266059SGregory Neil Shapiro typedef struct procs PROCS_T; 239540266059SGregory Neil Shapiro 239640266059SGregory Neil Shapiro struct procs 239740266059SGregory Neil Shapiro { 239840266059SGregory Neil Shapiro pid_t proc_pid; 239940266059SGregory Neil Shapiro char *proc_task; 240040266059SGregory Neil Shapiro int proc_type; 240140266059SGregory Neil Shapiro int proc_count; 240240266059SGregory Neil Shapiro int proc_other; 240340266059SGregory Neil Shapiro }; 240440266059SGregory Neil Shapiro 240540266059SGregory Neil Shapiro static PROCS_T *volatile ProcListVec = NULL; 2406c2aa98e2SPeter Wemm static int ProcListSize = 0; 2407c2aa98e2SPeter Wemm 2408c2aa98e2SPeter Wemm void 240940266059SGregory Neil Shapiro proc_list_add(pid, task, type, count, other) 2410c2aa98e2SPeter Wemm pid_t pid; 2411065a643dSPeter Wemm char *task; 241206f25ae9SGregory Neil Shapiro int type; 241340266059SGregory Neil Shapiro int count; 241440266059SGregory Neil Shapiro int other; 2415c2aa98e2SPeter Wemm { 2416c2aa98e2SPeter Wemm int i; 2417c2aa98e2SPeter Wemm 2418c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2419c2aa98e2SPeter Wemm { 2420065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2421c2aa98e2SPeter Wemm break; 2422c2aa98e2SPeter Wemm } 2423c2aa98e2SPeter Wemm if (i >= ProcListSize) 2424c2aa98e2SPeter Wemm { 2425c2aa98e2SPeter Wemm /* probe the existing vector to avoid growing infinitely */ 2426c2aa98e2SPeter Wemm proc_list_probe(); 2427c2aa98e2SPeter Wemm 2428c2aa98e2SPeter Wemm /* now scan again */ 2429c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2430c2aa98e2SPeter Wemm { 2431065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2432c2aa98e2SPeter Wemm break; 2433c2aa98e2SPeter Wemm } 2434c2aa98e2SPeter Wemm } 2435c2aa98e2SPeter Wemm if (i >= ProcListSize) 2436c2aa98e2SPeter Wemm { 2437c2aa98e2SPeter Wemm /* grow process list */ 243840266059SGregory Neil Shapiro PROCS_T *npv; 2439c2aa98e2SPeter Wemm 244040266059SGregory Neil Shapiro SM_ASSERT(ProcListSize < INT_MAX - PROC_LIST_SEG); 244140266059SGregory Neil Shapiro npv = (PROCS_T *) sm_pmalloc_x((sizeof *npv) * 244206f25ae9SGregory Neil Shapiro (ProcListSize + PROC_LIST_SEG)); 2443c2aa98e2SPeter Wemm if (ProcListSize > 0) 2444c2aa98e2SPeter Wemm { 244506f25ae9SGregory Neil Shapiro memmove(npv, ProcListVec, 244640266059SGregory Neil Shapiro ProcListSize * sizeof (PROCS_T)); 24478774250cSGregory Neil Shapiro sm_free(ProcListVec); 2448c2aa98e2SPeter Wemm } 244940266059SGregory Neil Shapiro 245040266059SGregory Neil Shapiro /* XXX just use memset() to initialize this part? */ 2451c2aa98e2SPeter Wemm for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 2452065a643dSPeter Wemm { 2453065a643dSPeter Wemm npv[i].proc_pid = NO_PID; 2454065a643dSPeter Wemm npv[i].proc_task = NULL; 245506f25ae9SGregory Neil Shapiro npv[i].proc_type = PROC_NONE; 2456065a643dSPeter Wemm } 2457c2aa98e2SPeter Wemm i = ProcListSize; 2458c2aa98e2SPeter Wemm ProcListSize += PROC_LIST_SEG; 2459c2aa98e2SPeter Wemm ProcListVec = npv; 2460c2aa98e2SPeter Wemm } 2461065a643dSPeter Wemm ProcListVec[i].proc_pid = pid; 246240266059SGregory Neil Shapiro PSTRSET(ProcListVec[i].proc_task, task); 246306f25ae9SGregory Neil Shapiro ProcListVec[i].proc_type = type; 246440266059SGregory Neil Shapiro ProcListVec[i].proc_count = count; 246540266059SGregory Neil Shapiro ProcListVec[i].proc_other = other; 2466065a643dSPeter Wemm 2467065a643dSPeter Wemm /* if process adding itself, it's not a child */ 246840266059SGregory Neil Shapiro if (pid != CurrentPid) 246940266059SGregory Neil Shapiro { 247040266059SGregory Neil Shapiro SM_ASSERT(CurChildren < INT_MAX); 2471c2aa98e2SPeter Wemm CurChildren++; 2472c2aa98e2SPeter Wemm } 247340266059SGregory Neil Shapiro } 247440266059SGregory Neil Shapiro /* 2475065a643dSPeter Wemm ** PROC_LIST_SET -- set pid task in process list 2476065a643dSPeter Wemm ** 2477065a643dSPeter Wemm ** Parameters: 2478065a643dSPeter Wemm ** pid -- pid to set 2479065a643dSPeter Wemm ** task -- task of pid 2480065a643dSPeter Wemm ** 2481065a643dSPeter Wemm ** Returns: 2482065a643dSPeter Wemm ** none. 2483065a643dSPeter Wemm */ 2484065a643dSPeter Wemm 2485065a643dSPeter Wemm void 2486065a643dSPeter Wemm proc_list_set(pid, task) 2487065a643dSPeter Wemm pid_t pid; 2488065a643dSPeter Wemm char *task; 2489065a643dSPeter Wemm { 2490065a643dSPeter Wemm int i; 2491065a643dSPeter Wemm 2492065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2493065a643dSPeter Wemm { 2494065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2495065a643dSPeter Wemm { 249640266059SGregory Neil Shapiro PSTRSET(ProcListVec[i].proc_task, task); 2497065a643dSPeter Wemm break; 2498065a643dSPeter Wemm } 2499065a643dSPeter Wemm } 2500065a643dSPeter Wemm } 250140266059SGregory Neil Shapiro /* 2502c2aa98e2SPeter Wemm ** PROC_LIST_DROP -- drop pid from process list 2503c2aa98e2SPeter Wemm ** 2504c2aa98e2SPeter Wemm ** Parameters: 2505c2aa98e2SPeter Wemm ** pid -- pid to drop 250640266059SGregory Neil Shapiro ** st -- process status 250740266059SGregory Neil Shapiro ** other -- storage for proc_other (return). 2508c2aa98e2SPeter Wemm ** 2509c2aa98e2SPeter Wemm ** Returns: 251040266059SGregory Neil Shapiro ** none. 251140266059SGregory Neil Shapiro ** 251240266059SGregory Neil Shapiro ** Side Effects: 251340266059SGregory Neil Shapiro ** May decrease CurChildren, CurRunners, or 251440266059SGregory Neil Shapiro ** set RestartRequest or ShutdownRequest. 25158774250cSGregory Neil Shapiro ** 25168774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 25178774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 25188774250cSGregory Neil Shapiro ** DOING. 2519c2aa98e2SPeter Wemm */ 2520c2aa98e2SPeter Wemm 252140266059SGregory Neil Shapiro void 252240266059SGregory Neil Shapiro proc_list_drop(pid, st, other) 2523c2aa98e2SPeter Wemm pid_t pid; 252440266059SGregory Neil Shapiro int st; 252540266059SGregory Neil Shapiro int *other; 2526c2aa98e2SPeter Wemm { 2527c2aa98e2SPeter Wemm int i; 252806f25ae9SGregory Neil Shapiro int type = PROC_NONE; 2529c2aa98e2SPeter Wemm 2530c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2531c2aa98e2SPeter Wemm { 2532065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2533c2aa98e2SPeter Wemm { 2534065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 253506f25ae9SGregory Neil Shapiro type = ProcListVec[i].proc_type; 253640266059SGregory Neil Shapiro if (other != NULL) 253740266059SGregory Neil Shapiro *other = ProcListVec[i].proc_other; 2538c2aa98e2SPeter Wemm break; 2539c2aa98e2SPeter Wemm } 2540c2aa98e2SPeter Wemm } 2541c2aa98e2SPeter Wemm if (CurChildren > 0) 2542c2aa98e2SPeter Wemm CurChildren--; 254306f25ae9SGregory Neil Shapiro 254406f25ae9SGregory Neil Shapiro 254540266059SGregory Neil Shapiro if (type == PROC_CONTROL && WIFEXITED(st)) 254640266059SGregory Neil Shapiro { 254740266059SGregory Neil Shapiro /* if so, see if we need to restart or shutdown */ 254840266059SGregory Neil Shapiro if (WEXITSTATUS(st) == EX_RESTART) 254940266059SGregory Neil Shapiro RestartRequest = "control socket"; 255040266059SGregory Neil Shapiro else if (WEXITSTATUS(st) == EX_SHUTDOWN) 255140266059SGregory Neil Shapiro ShutdownRequest = "control socket"; 2552c2aa98e2SPeter Wemm } 255340266059SGregory Neil Shapiro else if (type == PROC_QUEUE_CHILD && !WIFSTOPPED(st) && 255440266059SGregory Neil Shapiro ProcListVec[i].proc_other > -1) 255540266059SGregory Neil Shapiro { 255640266059SGregory Neil Shapiro /* restart this persistent runner */ 255740266059SGregory Neil Shapiro mark_work_group_restart(ProcListVec[i].proc_other, st); 255840266059SGregory Neil Shapiro } 255940266059SGregory Neil Shapiro else if (type == PROC_QUEUE) 256040266059SGregory Neil Shapiro CurRunners -= ProcListVec[i].proc_count; 256140266059SGregory Neil Shapiro } 256240266059SGregory Neil Shapiro /* 2563c2aa98e2SPeter Wemm ** PROC_LIST_CLEAR -- clear the process list 2564c2aa98e2SPeter Wemm ** 2565c2aa98e2SPeter Wemm ** Parameters: 2566c2aa98e2SPeter Wemm ** none. 2567c2aa98e2SPeter Wemm ** 2568c2aa98e2SPeter Wemm ** Returns: 2569c2aa98e2SPeter Wemm ** none. 257040266059SGregory Neil Shapiro ** 257140266059SGregory Neil Shapiro ** Side Effects: 257240266059SGregory Neil Shapiro ** Sets CurChildren to zero. 2573c2aa98e2SPeter Wemm */ 2574c2aa98e2SPeter Wemm 2575c2aa98e2SPeter Wemm void 2576c2aa98e2SPeter Wemm proc_list_clear() 2577c2aa98e2SPeter Wemm { 2578c2aa98e2SPeter Wemm int i; 2579c2aa98e2SPeter Wemm 2580065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2581065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2582065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2583c2aa98e2SPeter Wemm CurChildren = 0; 2584c2aa98e2SPeter Wemm } 258540266059SGregory Neil Shapiro /* 2586c2aa98e2SPeter Wemm ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 2587c2aa98e2SPeter Wemm ** 2588c2aa98e2SPeter Wemm ** Parameters: 2589c2aa98e2SPeter Wemm ** none 2590c2aa98e2SPeter Wemm ** 2591c2aa98e2SPeter Wemm ** Returns: 2592c2aa98e2SPeter Wemm ** none 259340266059SGregory Neil Shapiro ** 259440266059SGregory Neil Shapiro ** Side Effects: 259540266059SGregory Neil Shapiro ** May decrease CurChildren. 2596c2aa98e2SPeter Wemm */ 2597c2aa98e2SPeter Wemm 2598c2aa98e2SPeter Wemm void 2599c2aa98e2SPeter Wemm proc_list_probe() 2600c2aa98e2SPeter Wemm { 2601c2aa98e2SPeter Wemm int i; 2602c2aa98e2SPeter Wemm 2603065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2604065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2605c2aa98e2SPeter Wemm { 2606065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2607c2aa98e2SPeter Wemm continue; 2608065a643dSPeter Wemm if (kill(ProcListVec[i].proc_pid, 0) < 0) 2609c2aa98e2SPeter Wemm { 2610c2aa98e2SPeter Wemm if (LogLevel > 3) 2611c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 2612c2aa98e2SPeter Wemm "proc_list_probe: lost pid %d", 2613065a643dSPeter Wemm (int) ProcListVec[i].proc_pid); 2614065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 261540266059SGregory Neil Shapiro SM_FREE_CLR(ProcListVec[i].proc_task); 2616c2aa98e2SPeter Wemm CurChildren--; 2617c2aa98e2SPeter Wemm } 2618c2aa98e2SPeter Wemm } 2619c2aa98e2SPeter Wemm if (CurChildren < 0) 2620c2aa98e2SPeter Wemm CurChildren = 0; 2621c2aa98e2SPeter Wemm } 262240266059SGregory Neil Shapiro 262340266059SGregory Neil Shapiro /* 2624065a643dSPeter Wemm ** PROC_LIST_DISPLAY -- display the process list 2625065a643dSPeter Wemm ** 2626065a643dSPeter Wemm ** Parameters: 2627065a643dSPeter Wemm ** out -- output file pointer 262840266059SGregory Neil Shapiro ** prefix -- string to output in front of each line. 2629065a643dSPeter Wemm ** 2630065a643dSPeter Wemm ** Returns: 2631065a643dSPeter Wemm ** none. 2632065a643dSPeter Wemm */ 2633065a643dSPeter Wemm 2634065a643dSPeter Wemm void 263540266059SGregory Neil Shapiro proc_list_display(out, prefix) 263640266059SGregory Neil Shapiro SM_FILE_T *out; 263740266059SGregory Neil Shapiro char *prefix; 2638065a643dSPeter Wemm { 2639065a643dSPeter Wemm int i; 2640065a643dSPeter Wemm 2641065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2642065a643dSPeter Wemm { 2643065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2644065a643dSPeter Wemm continue; 2645065a643dSPeter Wemm 264640266059SGregory Neil Shapiro (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "%s%d %s%s\n", 264740266059SGregory Neil Shapiro prefix, 264840266059SGregory Neil Shapiro (int) ProcListVec[i].proc_pid, 2649065a643dSPeter Wemm ProcListVec[i].proc_task != NULL ? 2650065a643dSPeter Wemm ProcListVec[i].proc_task : "(unknown)", 2651065a643dSPeter Wemm (OpMode == MD_SMTP || 2652065a643dSPeter Wemm OpMode == MD_DAEMON || 2653065a643dSPeter Wemm OpMode == MD_ARPAFTP) ? "\r" : ""); 2654065a643dSPeter Wemm } 2655065a643dSPeter Wemm } 265640266059SGregory Neil Shapiro 265740266059SGregory Neil Shapiro /* 265840266059SGregory Neil Shapiro ** PROC_LIST_SIGNAL -- send a signal to a type of process in the list 265913058a91SGregory Neil Shapiro ** 266013058a91SGregory Neil Shapiro ** Parameters: 266140266059SGregory Neil Shapiro ** type -- type of process to signal 266240266059SGregory Neil Shapiro ** signal -- the type of signal to send 266313058a91SGregory Neil Shapiro ** 266440266059SGregory Neil Shapiro ** Results: 266540266059SGregory Neil Shapiro ** none. 2666c2aa98e2SPeter Wemm ** 266740266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 266840266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 266940266059SGregory Neil Shapiro ** DOING. 2670c2aa98e2SPeter Wemm */ 2671c2aa98e2SPeter Wemm 267240266059SGregory Neil Shapiro void 267340266059SGregory Neil Shapiro proc_list_signal(type, signal) 267440266059SGregory Neil Shapiro int type; 267540266059SGregory Neil Shapiro int signal; 2676c2aa98e2SPeter Wemm { 267740266059SGregory Neil Shapiro int chldwasblocked; 267840266059SGregory Neil Shapiro int alrmwasblocked; 267940266059SGregory Neil Shapiro int i; 268040266059SGregory Neil Shapiro pid_t mypid = getpid(); 2681c2aa98e2SPeter Wemm 268240266059SGregory Neil Shapiro /* block these signals so that we may signal cleanly */ 268340266059SGregory Neil Shapiro chldwasblocked = sm_blocksignal(SIGCHLD); 268440266059SGregory Neil Shapiro alrmwasblocked = sm_blocksignal(SIGALRM); 268540266059SGregory Neil Shapiro 268640266059SGregory Neil Shapiro /* Find all processes of type and send signal */ 268740266059SGregory Neil Shapiro for (i = 0; i < ProcListSize; i++) 268840266059SGregory Neil Shapiro { 268940266059SGregory Neil Shapiro if (ProcListVec[i].proc_pid == NO_PID || 269040266059SGregory Neil Shapiro ProcListVec[i].proc_pid == mypid) 269140266059SGregory Neil Shapiro continue; 269240266059SGregory Neil Shapiro if (ProcListVec[i].proc_type != type) 269340266059SGregory Neil Shapiro continue; 269440266059SGregory Neil Shapiro (void) kill(ProcListVec[i].proc_pid, signal); 2695c2aa98e2SPeter Wemm } 2696c2aa98e2SPeter Wemm 269740266059SGregory Neil Shapiro /* restore the signals */ 269840266059SGregory Neil Shapiro if (alrmwasblocked == 0) 269940266059SGregory Neil Shapiro (void) sm_releasesignal(SIGALRM); 270040266059SGregory Neil Shapiro if (chldwasblocked == 0) 270140266059SGregory Neil Shapiro (void) sm_releasesignal(SIGCHLD); 2702c2aa98e2SPeter Wemm } 2703