1c2aa98e2SPeter Wemm /* 2323f6dcbSGregory Neil Shapiro * Copyright (c) 1998-2003 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 16323f6dcbSGregory Neil Shapiro SM_RCSID("@(#)$Id: util.c,v 8.363.2.10 2003/10/15 17:19:14 ca 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 } 7013bd1963SGregory Neil Shapiro 7113bd1963SGregory Neil Shapiro #if _FFR_STRIPBACKSL 7213bd1963SGregory Neil Shapiro /* 7313bd1963SGregory Neil Shapiro ** STRIPBACKSLASH -- Strip leading backslash from a string. 7413bd1963SGregory Neil Shapiro ** 7513bd1963SGregory Neil Shapiro ** This is done in place. 7613bd1963SGregory Neil Shapiro ** 7713bd1963SGregory Neil Shapiro ** Parameters: 7813bd1963SGregory Neil Shapiro ** s -- the string to strip. 7913bd1963SGregory Neil Shapiro ** 8013bd1963SGregory Neil Shapiro ** Returns: 8113bd1963SGregory Neil Shapiro ** none. 8213bd1963SGregory Neil Shapiro */ 8313bd1963SGregory Neil Shapiro 8413bd1963SGregory Neil Shapiro void 8513bd1963SGregory Neil Shapiro stripbackslash(s) 8613bd1963SGregory Neil Shapiro char *s; 8713bd1963SGregory Neil Shapiro { 8813bd1963SGregory Neil Shapiro char *p, *q, c; 8913bd1963SGregory Neil Shapiro 9013bd1963SGregory Neil Shapiro if (s == NULL || *s == '\0') 9113bd1963SGregory Neil Shapiro return; 9213bd1963SGregory Neil Shapiro p = q = s; 9313bd1963SGregory Neil Shapiro while (*p == '\\' && (p[1] == '\\' || (isascii(p[1]) && isalnum(p[1])))) 9413bd1963SGregory Neil Shapiro p++; 9513bd1963SGregory Neil Shapiro do 9613bd1963SGregory Neil Shapiro { 9713bd1963SGregory Neil Shapiro c = *q++ = *p++; 9813bd1963SGregory Neil Shapiro } while (c != '\0'); 9913bd1963SGregory Neil Shapiro } 10013bd1963SGregory Neil Shapiro #endif /* _FFR_STRIPBACKSL */ 10113bd1963SGregory Neil Shapiro 10240266059SGregory Neil Shapiro /* 103c2aa98e2SPeter Wemm ** RFC822_STRING -- Checks string for proper RFC822 string quoting. 104c2aa98e2SPeter Wemm ** 105c2aa98e2SPeter Wemm ** Runs through a string and verifies RFC822 special characters 106c2aa98e2SPeter Wemm ** are only found inside comments, quoted strings, or backslash 107c2aa98e2SPeter Wemm ** escaped. Also verified balanced quotes and parenthesis. 108c2aa98e2SPeter Wemm ** 109c2aa98e2SPeter Wemm ** Parameters: 110c2aa98e2SPeter Wemm ** s -- the string to modify. 111c2aa98e2SPeter Wemm ** 112c2aa98e2SPeter Wemm ** Returns: 11340266059SGregory Neil Shapiro ** true iff the string is RFC822 compliant, false otherwise. 114c2aa98e2SPeter Wemm */ 115c2aa98e2SPeter Wemm 116c2aa98e2SPeter Wemm bool 117c2aa98e2SPeter Wemm rfc822_string(s) 118c2aa98e2SPeter Wemm char *s; 119c2aa98e2SPeter Wemm { 12040266059SGregory Neil Shapiro bool quoted = false; 121c2aa98e2SPeter Wemm int commentlev = 0; 122c2aa98e2SPeter Wemm char *c = s; 123c2aa98e2SPeter Wemm 124c2aa98e2SPeter Wemm if (s == NULL) 12540266059SGregory Neil Shapiro return false; 126c2aa98e2SPeter Wemm 127c2aa98e2SPeter Wemm while (*c != '\0') 128c2aa98e2SPeter Wemm { 129c2aa98e2SPeter Wemm /* escaped character */ 130c2aa98e2SPeter Wemm if (*c == '\\') 131c2aa98e2SPeter Wemm { 132c2aa98e2SPeter Wemm c++; 133c2aa98e2SPeter Wemm if (*c == '\0') 13440266059SGregory Neil Shapiro return false; 135c2aa98e2SPeter Wemm } 136c2aa98e2SPeter Wemm else if (commentlev == 0 && *c == '"') 137c2aa98e2SPeter Wemm quoted = !quoted; 138c2aa98e2SPeter Wemm else if (!quoted) 139c2aa98e2SPeter Wemm { 140c2aa98e2SPeter Wemm if (*c == ')') 141c2aa98e2SPeter Wemm { 142c2aa98e2SPeter Wemm /* unbalanced ')' */ 143c2aa98e2SPeter Wemm if (commentlev == 0) 14440266059SGregory Neil Shapiro return false; 145c2aa98e2SPeter Wemm else 146c2aa98e2SPeter Wemm commentlev--; 147c2aa98e2SPeter Wemm } 148c2aa98e2SPeter Wemm else if (*c == '(') 149c2aa98e2SPeter Wemm commentlev++; 150c2aa98e2SPeter Wemm else if (commentlev == 0 && 151c2aa98e2SPeter Wemm strchr(MustQuoteChars, *c) != NULL) 15240266059SGregory Neil Shapiro return false; 153c2aa98e2SPeter Wemm } 154c2aa98e2SPeter Wemm c++; 155c2aa98e2SPeter Wemm } 15640266059SGregory Neil Shapiro 157c2aa98e2SPeter Wemm /* unbalanced '"' or '(' */ 15840266059SGregory Neil Shapiro return !quoted && commentlev == 0; 159c2aa98e2SPeter Wemm } 16040266059SGregory Neil Shapiro /* 161065a643dSPeter Wemm ** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string 162065a643dSPeter Wemm ** 16306f25ae9SGregory Neil Shapiro ** Arbitrarily shorten (in place) an RFC822 string and rebalance 164065a643dSPeter Wemm ** comments and quotes. 165065a643dSPeter Wemm ** 166065a643dSPeter Wemm ** Parameters: 167065a643dSPeter Wemm ** string -- the string to shorten 168065a643dSPeter Wemm ** length -- the maximum size, 0 if no maximum 169065a643dSPeter Wemm ** 170065a643dSPeter Wemm ** Returns: 17140266059SGregory Neil Shapiro ** true if string is changed, false otherwise 172065a643dSPeter Wemm ** 173065a643dSPeter Wemm ** Side Effects: 174065a643dSPeter Wemm ** Changes string in place, possibly resulting 175065a643dSPeter Wemm ** in a shorter string. 176065a643dSPeter Wemm */ 177065a643dSPeter Wemm 178065a643dSPeter Wemm bool 179065a643dSPeter Wemm shorten_rfc822_string(string, length) 180065a643dSPeter Wemm char *string; 181065a643dSPeter Wemm size_t length; 182065a643dSPeter Wemm { 18340266059SGregory Neil Shapiro bool backslash = false; 18440266059SGregory Neil Shapiro bool modified = false; 18540266059SGregory Neil Shapiro bool quoted = false; 186065a643dSPeter Wemm size_t slen; 187065a643dSPeter Wemm int parencount = 0; 188065a643dSPeter Wemm char *ptr = string; 189065a643dSPeter Wemm 190065a643dSPeter Wemm /* 191065a643dSPeter Wemm ** If have to rebalance an already short enough string, 192065a643dSPeter Wemm ** need to do it within allocated space. 193065a643dSPeter Wemm */ 194193538b7SGregory Neil Shapiro 195065a643dSPeter Wemm slen = strlen(string); 196065a643dSPeter Wemm if (length == 0 || slen < length) 197065a643dSPeter Wemm length = slen; 198065a643dSPeter Wemm 199065a643dSPeter Wemm while (*ptr != '\0') 200065a643dSPeter Wemm { 201065a643dSPeter Wemm if (backslash) 202065a643dSPeter Wemm { 20340266059SGregory Neil Shapiro backslash = false; 204065a643dSPeter Wemm goto increment; 205065a643dSPeter Wemm } 206065a643dSPeter Wemm 207065a643dSPeter Wemm if (*ptr == '\\') 20840266059SGregory Neil Shapiro backslash = true; 209065a643dSPeter Wemm else if (*ptr == '(') 210065a643dSPeter Wemm { 211065a643dSPeter Wemm if (!quoted) 212065a643dSPeter Wemm parencount++; 213065a643dSPeter Wemm } 214065a643dSPeter Wemm else if (*ptr == ')') 215065a643dSPeter Wemm { 216065a643dSPeter Wemm if (--parencount < 0) 217065a643dSPeter Wemm parencount = 0; 218065a643dSPeter Wemm } 219065a643dSPeter Wemm 220065a643dSPeter Wemm /* Inside a comment, quotes don't matter */ 221065a643dSPeter Wemm if (parencount <= 0 && *ptr == '"') 222065a643dSPeter Wemm quoted = !quoted; 223065a643dSPeter Wemm 224065a643dSPeter Wemm increment: 225065a643dSPeter Wemm /* Check for sufficient space for next character */ 22606f25ae9SGregory Neil Shapiro if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) + 227065a643dSPeter Wemm parencount + 228065a643dSPeter Wemm (quoted ? 1 : 0))) 229065a643dSPeter Wemm { 230065a643dSPeter Wemm /* Not enough, backtrack */ 231065a643dSPeter Wemm if (*ptr == '\\') 23240266059SGregory Neil Shapiro backslash = false; 233065a643dSPeter Wemm else if (*ptr == '(' && !quoted) 234065a643dSPeter Wemm parencount--; 235065a643dSPeter Wemm else if (*ptr == '"' && parencount == 0) 23640266059SGregory Neil Shapiro quoted = false; 237065a643dSPeter Wemm break; 238065a643dSPeter Wemm } 239065a643dSPeter Wemm ptr++; 240065a643dSPeter Wemm } 241065a643dSPeter Wemm 242065a643dSPeter Wemm /* Rebalance */ 243065a643dSPeter Wemm while (parencount-- > 0) 244065a643dSPeter Wemm { 245065a643dSPeter Wemm if (*ptr != ')') 246065a643dSPeter Wemm { 24740266059SGregory Neil Shapiro modified = true; 248065a643dSPeter Wemm *ptr = ')'; 249065a643dSPeter Wemm } 250065a643dSPeter Wemm ptr++; 251065a643dSPeter Wemm } 252065a643dSPeter Wemm if (quoted) 253065a643dSPeter Wemm { 254065a643dSPeter Wemm if (*ptr != '"') 255065a643dSPeter Wemm { 25640266059SGregory Neil Shapiro modified = true; 257065a643dSPeter Wemm *ptr = '"'; 258065a643dSPeter Wemm } 259065a643dSPeter Wemm ptr++; 260065a643dSPeter Wemm } 261065a643dSPeter Wemm if (*ptr != '\0') 262065a643dSPeter Wemm { 26340266059SGregory Neil Shapiro modified = true; 264065a643dSPeter Wemm *ptr = '\0'; 265065a643dSPeter Wemm } 266065a643dSPeter Wemm return modified; 267065a643dSPeter Wemm } 26840266059SGregory Neil Shapiro /* 269065a643dSPeter Wemm ** FIND_CHARACTER -- find an unquoted character in an RFC822 string 270065a643dSPeter Wemm ** 271065a643dSPeter Wemm ** Find an unquoted, non-commented character in an RFC822 272065a643dSPeter Wemm ** string and return a pointer to its location in the 273065a643dSPeter Wemm ** string. 274065a643dSPeter Wemm ** 275065a643dSPeter Wemm ** Parameters: 276065a643dSPeter Wemm ** string -- the string to search 277065a643dSPeter Wemm ** character -- the character to find 278065a643dSPeter Wemm ** 279065a643dSPeter Wemm ** Returns: 280065a643dSPeter Wemm ** pointer to the character, or 281065a643dSPeter Wemm ** a pointer to the end of the line if character is not found 282065a643dSPeter Wemm */ 283065a643dSPeter Wemm 284065a643dSPeter Wemm char * 285065a643dSPeter Wemm find_character(string, character) 286065a643dSPeter Wemm char *string; 28706f25ae9SGregory Neil Shapiro int character; 288065a643dSPeter Wemm { 28940266059SGregory Neil Shapiro bool backslash = false; 29040266059SGregory Neil Shapiro bool quoted = false; 291065a643dSPeter Wemm int parencount = 0; 292065a643dSPeter Wemm 293065a643dSPeter Wemm while (string != NULL && *string != '\0') 294065a643dSPeter Wemm { 295065a643dSPeter Wemm if (backslash) 296065a643dSPeter Wemm { 29740266059SGregory Neil Shapiro backslash = false; 298065a643dSPeter Wemm if (!quoted && character == '\\' && *string == '\\') 299065a643dSPeter Wemm break; 300065a643dSPeter Wemm string++; 301065a643dSPeter Wemm continue; 302065a643dSPeter Wemm } 303065a643dSPeter Wemm switch (*string) 304065a643dSPeter Wemm { 305065a643dSPeter Wemm case '\\': 30640266059SGregory Neil Shapiro backslash = true; 307065a643dSPeter Wemm break; 308065a643dSPeter Wemm 309065a643dSPeter Wemm case '(': 310065a643dSPeter Wemm if (!quoted) 311065a643dSPeter Wemm parencount++; 312065a643dSPeter Wemm break; 313065a643dSPeter Wemm 314065a643dSPeter Wemm case ')': 315065a643dSPeter Wemm if (--parencount < 0) 316065a643dSPeter Wemm parencount = 0; 317065a643dSPeter Wemm break; 318065a643dSPeter Wemm } 319065a643dSPeter Wemm 320065a643dSPeter Wemm /* Inside a comment, nothing matters */ 321065a643dSPeter Wemm if (parencount > 0) 322065a643dSPeter Wemm { 323065a643dSPeter Wemm string++; 324065a643dSPeter Wemm continue; 325065a643dSPeter Wemm } 326065a643dSPeter Wemm 327065a643dSPeter Wemm if (*string == '"') 328065a643dSPeter Wemm quoted = !quoted; 329065a643dSPeter Wemm else if (*string == character && !quoted) 330065a643dSPeter Wemm break; 331065a643dSPeter Wemm string++; 332065a643dSPeter Wemm } 333065a643dSPeter Wemm 334065a643dSPeter Wemm /* Return pointer to the character */ 335065a643dSPeter Wemm return string; 336065a643dSPeter Wemm } 33740266059SGregory Neil Shapiro 33840266059SGregory Neil Shapiro /* 33940266059SGregory Neil Shapiro ** CHECK_BODYTYPE -- check bodytype parameter 340c2aa98e2SPeter Wemm ** 34140266059SGregory Neil Shapiro ** Parameters: 34240266059SGregory Neil Shapiro ** bodytype -- bodytype parameter 34340266059SGregory Neil Shapiro ** 34440266059SGregory Neil Shapiro ** Returns: 34540266059SGregory Neil Shapiro ** BODYTYPE_* according to parameter 34640266059SGregory Neil Shapiro ** 34740266059SGregory Neil Shapiro */ 34840266059SGregory Neil Shapiro 34940266059SGregory Neil Shapiro int 35040266059SGregory Neil Shapiro check_bodytype(bodytype) 35140266059SGregory Neil Shapiro char *bodytype; 35240266059SGregory Neil Shapiro { 35340266059SGregory Neil Shapiro /* check body type for legality */ 35440266059SGregory Neil Shapiro if (bodytype == NULL) 35540266059SGregory Neil Shapiro return BODYTYPE_NONE; 35640266059SGregory Neil Shapiro if (sm_strcasecmp(bodytype, "7BIT") == 0) 35740266059SGregory Neil Shapiro return BODYTYPE_7BIT; 35840266059SGregory Neil Shapiro if (sm_strcasecmp(bodytype, "8BITMIME") == 0) 35940266059SGregory Neil Shapiro return BODYTYPE_8BITMIME; 36040266059SGregory Neil Shapiro return BODYTYPE_ILLEGAL; 36140266059SGregory Neil Shapiro } 36240266059SGregory Neil Shapiro 36340266059SGregory Neil Shapiro #if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI 36440266059SGregory Neil Shapiro /* 36540266059SGregory Neil Shapiro ** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..." 36640266059SGregory Neil Shapiro ** 36740266059SGregory Neil Shapiro ** Parameters: 36840266059SGregory Neil Shapiro ** str -- string to truncate 36940266059SGregory Neil Shapiro ** len -- maximum length (including '\0') (0 for unlimited) 37040266059SGregory Neil Shapiro ** delim -- delimiter character 37140266059SGregory Neil Shapiro ** 37240266059SGregory Neil Shapiro ** Returns: 37340266059SGregory Neil Shapiro ** None. 37440266059SGregory Neil Shapiro */ 37540266059SGregory Neil Shapiro 37640266059SGregory Neil Shapiro void 37740266059SGregory Neil Shapiro truncate_at_delim(str, len, delim) 37840266059SGregory Neil Shapiro char *str; 37940266059SGregory Neil Shapiro size_t len; 38040266059SGregory Neil Shapiro int delim; 38140266059SGregory Neil Shapiro { 38240266059SGregory Neil Shapiro char *p; 38340266059SGregory Neil Shapiro 38440266059SGregory Neil Shapiro if (str == NULL || len == 0 || strlen(str) < len) 38540266059SGregory Neil Shapiro return; 38640266059SGregory Neil Shapiro 38740266059SGregory Neil Shapiro *(str + len - 1) = '\0'; 38840266059SGregory Neil Shapiro while ((p = strrchr(str, delim)) != NULL) 38940266059SGregory Neil Shapiro { 39040266059SGregory Neil Shapiro *p = '\0'; 39140266059SGregory Neil Shapiro if (p - str + 4 < len) 39240266059SGregory Neil Shapiro { 393a7ec597cSGregory Neil Shapiro *p++ = (char) delim; 39440266059SGregory Neil Shapiro *p = '\0'; 39540266059SGregory Neil Shapiro (void) sm_strlcat(str, "...", len); 39640266059SGregory Neil Shapiro return; 39740266059SGregory Neil Shapiro } 39840266059SGregory Neil Shapiro } 39940266059SGregory Neil Shapiro 40040266059SGregory Neil Shapiro /* Couldn't find a place to append "..." */ 40140266059SGregory Neil Shapiro if (len > 3) 40240266059SGregory Neil Shapiro (void) sm_strlcpy(str, "...", len); 40340266059SGregory Neil Shapiro else 40440266059SGregory Neil Shapiro str[0] = '\0'; 40540266059SGregory Neil Shapiro } 40640266059SGregory Neil Shapiro #endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */ 40740266059SGregory Neil Shapiro /* 40840266059SGregory Neil Shapiro ** XALLOC -- Allocate memory, raise an exception on error 409c2aa98e2SPeter Wemm ** 410c2aa98e2SPeter Wemm ** Parameters: 411c2aa98e2SPeter Wemm ** sz -- size of area to allocate. 412c2aa98e2SPeter Wemm ** 413c2aa98e2SPeter Wemm ** Returns: 414c2aa98e2SPeter Wemm ** pointer to data region. 415c2aa98e2SPeter Wemm ** 41640266059SGregory Neil Shapiro ** Exceptions: 41740266059SGregory Neil Shapiro ** SmHeapOutOfMemory (F:sm.heap) -- cannot allocate memory 41840266059SGregory Neil Shapiro ** 419c2aa98e2SPeter Wemm ** Side Effects: 420c2aa98e2SPeter Wemm ** Memory is allocated. 421c2aa98e2SPeter Wemm */ 422c2aa98e2SPeter Wemm 423c2aa98e2SPeter Wemm char * 42440266059SGregory Neil Shapiro #if SM_HEAP_CHECK 42540266059SGregory Neil Shapiro xalloc_tagged(sz, file, line) 42640266059SGregory Neil Shapiro register int sz; 42740266059SGregory Neil Shapiro char *file; 42840266059SGregory Neil Shapiro int line; 42940266059SGregory Neil Shapiro #else /* SM_HEAP_CHECK */ 430c2aa98e2SPeter Wemm xalloc(sz) 431c2aa98e2SPeter Wemm register int sz; 43240266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */ 433c2aa98e2SPeter Wemm { 434c2aa98e2SPeter Wemm register char *p; 435c2aa98e2SPeter Wemm 436c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 437c2aa98e2SPeter Wemm if (sz <= 0) 438c2aa98e2SPeter Wemm sz = 1; 439c2aa98e2SPeter Wemm 44040266059SGregory Neil Shapiro /* scaffolding for testing error handling code */ 44140266059SGregory Neil Shapiro sm_xtrap_raise_x(&SmHeapOutOfMemory); 44240266059SGregory Neil Shapiro 44340266059SGregory Neil Shapiro p = sm_malloc_tagged((unsigned) sz, file, line, sm_heap_group()); 444c2aa98e2SPeter Wemm if (p == NULL) 445c2aa98e2SPeter Wemm { 44640266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory); 447c2aa98e2SPeter Wemm } 44806f25ae9SGregory Neil Shapiro return p; 449c2aa98e2SPeter Wemm } 45040266059SGregory Neil Shapiro /* 451c2aa98e2SPeter Wemm ** COPYPLIST -- copy list of pointers. 452c2aa98e2SPeter Wemm ** 45340266059SGregory Neil Shapiro ** This routine is the equivalent of strdup for lists of 454c2aa98e2SPeter Wemm ** pointers. 455c2aa98e2SPeter Wemm ** 456c2aa98e2SPeter Wemm ** Parameters: 457c2aa98e2SPeter Wemm ** list -- list of pointers to copy. 458c2aa98e2SPeter Wemm ** Must be NULL terminated. 45940266059SGregory Neil Shapiro ** copycont -- if true, copy the contents of the vector 460c2aa98e2SPeter Wemm ** (which must be a string) also. 46140266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate storage, 46240266059SGregory Neil Shapiro ** or NULL 463c2aa98e2SPeter Wemm ** 464c2aa98e2SPeter Wemm ** Returns: 465c2aa98e2SPeter Wemm ** a copy of 'list'. 466c2aa98e2SPeter Wemm */ 467c2aa98e2SPeter Wemm 468c2aa98e2SPeter Wemm char ** 46940266059SGregory Neil Shapiro copyplist(list, copycont, rpool) 470c2aa98e2SPeter Wemm char **list; 471c2aa98e2SPeter Wemm bool copycont; 47240266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 473c2aa98e2SPeter Wemm { 474c2aa98e2SPeter Wemm register char **vp; 475c2aa98e2SPeter Wemm register char **newvp; 476c2aa98e2SPeter Wemm 477c2aa98e2SPeter Wemm for (vp = list; *vp != NULL; vp++) 478c2aa98e2SPeter Wemm continue; 479c2aa98e2SPeter Wemm 480c2aa98e2SPeter Wemm vp++; 481c2aa98e2SPeter Wemm 48240266059SGregory Neil Shapiro newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof *vp); 48306f25ae9SGregory Neil Shapiro memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); 484c2aa98e2SPeter Wemm 485c2aa98e2SPeter Wemm if (copycont) 486c2aa98e2SPeter Wemm { 487c2aa98e2SPeter Wemm for (vp = newvp; *vp != NULL; vp++) 48840266059SGregory Neil Shapiro *vp = sm_rpool_strdup_x(rpool, *vp); 489c2aa98e2SPeter Wemm } 490c2aa98e2SPeter Wemm 49106f25ae9SGregory Neil Shapiro return newvp; 492c2aa98e2SPeter Wemm } 49340266059SGregory Neil Shapiro /* 494c2aa98e2SPeter Wemm ** COPYQUEUE -- copy address queue. 495c2aa98e2SPeter Wemm ** 49640266059SGregory Neil Shapiro ** This routine is the equivalent of strdup for address queues; 49706f25ae9SGregory Neil Shapiro ** addresses marked as QS_IS_DEAD() aren't copied 498c2aa98e2SPeter Wemm ** 499c2aa98e2SPeter Wemm ** Parameters: 500c2aa98e2SPeter Wemm ** addr -- list of address structures to copy. 50140266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate storage 502c2aa98e2SPeter Wemm ** 503c2aa98e2SPeter Wemm ** Returns: 504c2aa98e2SPeter Wemm ** a copy of 'addr'. 505c2aa98e2SPeter Wemm */ 506c2aa98e2SPeter Wemm 507c2aa98e2SPeter Wemm ADDRESS * 50840266059SGregory Neil Shapiro copyqueue(addr, rpool) 509c2aa98e2SPeter Wemm ADDRESS *addr; 51040266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 511c2aa98e2SPeter Wemm { 512c2aa98e2SPeter Wemm register ADDRESS *newaddr; 513c2aa98e2SPeter Wemm ADDRESS *ret; 514c2aa98e2SPeter Wemm register ADDRESS **tail = &ret; 515c2aa98e2SPeter Wemm 516c2aa98e2SPeter Wemm while (addr != NULL) 517c2aa98e2SPeter Wemm { 51806f25ae9SGregory Neil Shapiro if (!QS_IS_DEAD(addr->q_state)) 519c2aa98e2SPeter Wemm { 52040266059SGregory Neil Shapiro newaddr = (ADDRESS *) sm_rpool_malloc_x(rpool, 52140266059SGregory Neil Shapiro sizeof *newaddr); 522c2aa98e2SPeter Wemm STRUCTCOPY(*addr, *newaddr); 523c2aa98e2SPeter Wemm *tail = newaddr; 524c2aa98e2SPeter Wemm tail = &newaddr->q_next; 525c2aa98e2SPeter Wemm } 526c2aa98e2SPeter Wemm addr = addr->q_next; 527c2aa98e2SPeter Wemm } 528c2aa98e2SPeter Wemm *tail = NULL; 529c2aa98e2SPeter Wemm 530c2aa98e2SPeter Wemm return ret; 531c2aa98e2SPeter Wemm } 53240266059SGregory Neil Shapiro /* 53306f25ae9SGregory Neil Shapiro ** LOG_SENDMAIL_PID -- record sendmail pid and command line. 53406f25ae9SGregory Neil Shapiro ** 53506f25ae9SGregory Neil Shapiro ** Parameters: 53606f25ae9SGregory Neil Shapiro ** e -- the current envelope. 53706f25ae9SGregory Neil Shapiro ** 53806f25ae9SGregory Neil Shapiro ** Returns: 53906f25ae9SGregory Neil Shapiro ** none. 54006f25ae9SGregory Neil Shapiro ** 54106f25ae9SGregory Neil Shapiro ** Side Effects: 54240266059SGregory Neil Shapiro ** writes pidfile, logs command line. 54306f25ae9SGregory Neil Shapiro */ 54406f25ae9SGregory Neil Shapiro 54506f25ae9SGregory Neil Shapiro void 54606f25ae9SGregory Neil Shapiro log_sendmail_pid(e) 54706f25ae9SGregory Neil Shapiro ENVELOPE *e; 54806f25ae9SGregory Neil Shapiro { 54906f25ae9SGregory Neil Shapiro long sff; 55040266059SGregory Neil Shapiro SM_FILE_T *pidf; 55194c01205SGregory Neil Shapiro char pidpath[MAXPATHLEN]; 55240266059SGregory Neil Shapiro extern char *CommandLineArgs; 55306f25ae9SGregory Neil Shapiro 55406f25ae9SGregory Neil Shapiro /* write the pid to the log file for posterity */ 55506f25ae9SGregory Neil Shapiro sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 55606f25ae9SGregory Neil Shapiro if (TrustedUid != 0 && RealUid == TrustedUid) 55706f25ae9SGregory Neil Shapiro sff |= SFF_OPENASROOT; 55806f25ae9SGregory Neil Shapiro expand(PidFile, pidpath, sizeof pidpath, e); 55994c01205SGregory Neil Shapiro pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff); 56006f25ae9SGregory Neil Shapiro if (pidf == NULL) 56106f25ae9SGregory Neil Shapiro { 562602a2b1bSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s", 56340266059SGregory Neil Shapiro pidpath, sm_errstring(errno)); 56406f25ae9SGregory Neil Shapiro } 56506f25ae9SGregory Neil Shapiro else 56606f25ae9SGregory Neil Shapiro { 5678774250cSGregory Neil Shapiro pid_t pid; 56806f25ae9SGregory Neil Shapiro 5698774250cSGregory Neil Shapiro pid = getpid(); 570193538b7SGregory Neil Shapiro 57106f25ae9SGregory Neil Shapiro /* write the process id on line 1 */ 57240266059SGregory Neil Shapiro (void) sm_io_fprintf(pidf, SM_TIME_DEFAULT, "%ld\n", 57340266059SGregory Neil Shapiro (long) pid); 57406f25ae9SGregory Neil Shapiro 57506f25ae9SGregory Neil Shapiro /* line 2 contains all command line flags */ 57640266059SGregory Neil Shapiro (void) sm_io_fprintf(pidf, SM_TIME_DEFAULT, "%s\n", 57740266059SGregory Neil Shapiro CommandLineArgs); 57806f25ae9SGregory Neil Shapiro 57906f25ae9SGregory Neil Shapiro /* flush and close */ 58040266059SGregory Neil Shapiro (void) sm_io_close(pidf, SM_TIME_DEFAULT); 58106f25ae9SGregory Neil Shapiro } 58240266059SGregory Neil Shapiro if (LogLevel > 9) 58340266059SGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID, "started as: %s", CommandLineArgs); 58406f25ae9SGregory Neil Shapiro } 58540266059SGregory Neil Shapiro /* 58606f25ae9SGregory Neil Shapiro ** SET_DELIVERY_MODE -- set and record the delivery mode 58706f25ae9SGregory Neil Shapiro ** 58806f25ae9SGregory Neil Shapiro ** Parameters: 58906f25ae9SGregory Neil Shapiro ** mode -- delivery mode 59006f25ae9SGregory Neil Shapiro ** e -- the current envelope. 59106f25ae9SGregory Neil Shapiro ** 59206f25ae9SGregory Neil Shapiro ** Returns: 59306f25ae9SGregory Neil Shapiro ** none. 59406f25ae9SGregory Neil Shapiro ** 59506f25ae9SGregory Neil Shapiro ** Side Effects: 59640266059SGregory Neil Shapiro ** sets {deliveryMode} macro 59706f25ae9SGregory Neil Shapiro */ 59806f25ae9SGregory Neil Shapiro 59906f25ae9SGregory Neil Shapiro void 60006f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e) 60106f25ae9SGregory Neil Shapiro int mode; 60206f25ae9SGregory Neil Shapiro ENVELOPE *e; 60306f25ae9SGregory Neil Shapiro { 60406f25ae9SGregory Neil Shapiro char buf[2]; 60506f25ae9SGregory Neil Shapiro 60606f25ae9SGregory Neil Shapiro e->e_sendmode = (char) mode; 60706f25ae9SGregory Neil Shapiro buf[0] = (char) mode; 60806f25ae9SGregory Neil Shapiro buf[1] = '\0'; 60940266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, macid("{deliveryMode}"), buf); 61006f25ae9SGregory Neil Shapiro } 61140266059SGregory Neil Shapiro /* 61240266059SGregory Neil Shapiro ** SET_OP_MODE -- set and record the op mode 61340266059SGregory Neil Shapiro ** 61440266059SGregory Neil Shapiro ** Parameters: 61540266059SGregory Neil Shapiro ** mode -- op mode 61640266059SGregory Neil Shapiro ** e -- the current envelope. 61740266059SGregory Neil Shapiro ** 61840266059SGregory Neil Shapiro ** Returns: 61940266059SGregory Neil Shapiro ** none. 62040266059SGregory Neil Shapiro ** 62140266059SGregory Neil Shapiro ** Side Effects: 62240266059SGregory Neil Shapiro ** sets {opMode} macro 62340266059SGregory Neil Shapiro */ 62440266059SGregory Neil Shapiro 62540266059SGregory Neil Shapiro void 62640266059SGregory Neil Shapiro set_op_mode(mode) 62740266059SGregory Neil Shapiro int mode; 62840266059SGregory Neil Shapiro { 62940266059SGregory Neil Shapiro char buf[2]; 63040266059SGregory Neil Shapiro extern ENVELOPE BlankEnvelope; 63140266059SGregory Neil Shapiro 63240266059SGregory Neil Shapiro OpMode = (char) mode; 63340266059SGregory Neil Shapiro buf[0] = (char) mode; 63440266059SGregory Neil Shapiro buf[1] = '\0'; 63540266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, MID_OPMODE, buf); 63640266059SGregory Neil Shapiro } 63740266059SGregory Neil Shapiro /* 638c2aa98e2SPeter Wemm ** PRINTAV -- print argument vector. 639c2aa98e2SPeter Wemm ** 640c2aa98e2SPeter Wemm ** Parameters: 641c2aa98e2SPeter Wemm ** av -- argument vector. 642c2aa98e2SPeter Wemm ** 643c2aa98e2SPeter Wemm ** Returns: 644c2aa98e2SPeter Wemm ** none. 645c2aa98e2SPeter Wemm ** 646c2aa98e2SPeter Wemm ** Side Effects: 647c2aa98e2SPeter Wemm ** prints av. 648c2aa98e2SPeter Wemm */ 649c2aa98e2SPeter Wemm 650c2aa98e2SPeter Wemm void 651c2aa98e2SPeter Wemm printav(av) 652c2aa98e2SPeter Wemm register char **av; 653c2aa98e2SPeter Wemm { 654c2aa98e2SPeter Wemm while (*av != NULL) 655c2aa98e2SPeter Wemm { 656c2aa98e2SPeter Wemm if (tTd(0, 44)) 65740266059SGregory Neil Shapiro sm_dprintf("\n\t%08lx=", (unsigned long) *av); 658c2aa98e2SPeter Wemm else 65940266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, ' '); 660c2aa98e2SPeter Wemm xputs(*av++); 661c2aa98e2SPeter Wemm } 66240266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '\n'); 663c2aa98e2SPeter Wemm } 66440266059SGregory Neil Shapiro /* 665c2aa98e2SPeter Wemm ** XPUTS -- put string doing control escapes. 666c2aa98e2SPeter Wemm ** 667c2aa98e2SPeter Wemm ** Parameters: 668c2aa98e2SPeter Wemm ** s -- string to put. 669c2aa98e2SPeter Wemm ** 670c2aa98e2SPeter Wemm ** Returns: 671c2aa98e2SPeter Wemm ** none. 672c2aa98e2SPeter Wemm ** 673c2aa98e2SPeter Wemm ** Side Effects: 674c2aa98e2SPeter Wemm ** output to stdout 675c2aa98e2SPeter Wemm */ 676c2aa98e2SPeter Wemm 677c2aa98e2SPeter Wemm void 678c2aa98e2SPeter Wemm xputs(s) 679c2aa98e2SPeter Wemm register const char *s; 680c2aa98e2SPeter Wemm { 681c2aa98e2SPeter Wemm register int c; 682c2aa98e2SPeter Wemm register struct metamac *mp; 68340266059SGregory Neil Shapiro bool shiftout = false; 684c2aa98e2SPeter Wemm extern struct metamac MetaMacros[]; 68540266059SGregory Neil Shapiro static SM_DEBUG_T DebugANSI = SM_DEBUG_INITIALIZER("ANSI", 68640266059SGregory Neil Shapiro "@(#)$Debug: ANSI - enable reverse video in debug output $"); 68740266059SGregory Neil Shapiro 68840266059SGregory Neil Shapiro /* 68940266059SGregory Neil Shapiro ** TermEscape is set here, rather than in main(), 69040266059SGregory Neil Shapiro ** because ANSI mode can be turned on or off at any time 69140266059SGregory Neil Shapiro ** if we are in -bt rule testing mode. 69240266059SGregory Neil Shapiro */ 69340266059SGregory Neil Shapiro 69440266059SGregory Neil Shapiro if (sm_debug_unknown(&DebugANSI)) 69540266059SGregory Neil Shapiro { 69640266059SGregory Neil Shapiro if (sm_debug_active(&DebugANSI, 1)) 69740266059SGregory Neil Shapiro { 69840266059SGregory Neil Shapiro TermEscape.te_rv_on = "\033[7m"; 69940266059SGregory Neil Shapiro TermEscape.te_rv_off = "\033[0m"; 70040266059SGregory Neil Shapiro } 70140266059SGregory Neil Shapiro else 70240266059SGregory Neil Shapiro { 70340266059SGregory Neil Shapiro TermEscape.te_rv_on = ""; 70440266059SGregory Neil Shapiro TermEscape.te_rv_off = ""; 70540266059SGregory Neil Shapiro } 70640266059SGregory Neil Shapiro } 707c2aa98e2SPeter Wemm 708c2aa98e2SPeter Wemm if (s == NULL) 709c2aa98e2SPeter Wemm { 71040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s<null>%s", 71140266059SGregory Neil Shapiro TermEscape.te_rv_on, TermEscape.te_rv_off); 712c2aa98e2SPeter Wemm return; 713c2aa98e2SPeter Wemm } 714c2aa98e2SPeter Wemm while ((c = (*s++ & 0377)) != '\0') 715c2aa98e2SPeter Wemm { 716c2aa98e2SPeter Wemm if (shiftout) 717c2aa98e2SPeter Wemm { 71840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 71940266059SGregory Neil Shapiro TermEscape.te_rv_off); 72040266059SGregory Neil Shapiro shiftout = false; 721c2aa98e2SPeter Wemm } 722c2aa98e2SPeter Wemm if (!isascii(c)) 723c2aa98e2SPeter Wemm { 724c2aa98e2SPeter Wemm if (c == MATCHREPL) 725c2aa98e2SPeter Wemm { 72640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 72740266059SGregory Neil Shapiro "%s$", 72840266059SGregory Neil Shapiro TermEscape.te_rv_on); 72940266059SGregory Neil Shapiro shiftout = true; 730c2aa98e2SPeter Wemm if (*s == '\0') 731c2aa98e2SPeter Wemm continue; 732c2aa98e2SPeter Wemm c = *s++ & 0377; 733c2aa98e2SPeter Wemm goto printchar; 734c2aa98e2SPeter Wemm } 735c2aa98e2SPeter Wemm if (c == MACROEXPAND || c == MACRODEXPAND) 736c2aa98e2SPeter Wemm { 73740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 73840266059SGregory Neil Shapiro "%s$", 73940266059SGregory Neil Shapiro TermEscape.te_rv_on); 740c2aa98e2SPeter Wemm if (c == MACRODEXPAND) 74140266059SGregory Neil Shapiro (void) sm_io_putc(smioout, 74240266059SGregory Neil Shapiro SM_TIME_DEFAULT, '&'); 74340266059SGregory Neil Shapiro shiftout = true; 744c2aa98e2SPeter Wemm if (*s == '\0') 745c2aa98e2SPeter Wemm continue; 746c2aa98e2SPeter Wemm if (strchr("=~&?", *s) != NULL) 74740266059SGregory Neil Shapiro (void) sm_io_putc(smioout, 74840266059SGregory Neil Shapiro SM_TIME_DEFAULT, 74940266059SGregory Neil Shapiro *s++); 750c2aa98e2SPeter Wemm if (bitset(0200, *s)) 75140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 75240266059SGregory Neil Shapiro SM_TIME_DEFAULT, 75340266059SGregory Neil Shapiro "{%s}", 75440266059SGregory Neil Shapiro macname(bitidx(*s++))); 755c2aa98e2SPeter Wemm else 75640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 75740266059SGregory Neil Shapiro SM_TIME_DEFAULT, 75840266059SGregory Neil Shapiro "%c", 75940266059SGregory Neil Shapiro *s++); 760c2aa98e2SPeter Wemm continue; 761c2aa98e2SPeter Wemm } 762c2aa98e2SPeter Wemm for (mp = MetaMacros; mp->metaname != '\0'; mp++) 763c2aa98e2SPeter Wemm { 76440266059SGregory Neil Shapiro if (bitidx(mp->metaval) == c) 765c2aa98e2SPeter Wemm { 76640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 76740266059SGregory Neil Shapiro SM_TIME_DEFAULT, 76840266059SGregory Neil Shapiro "%s$%c", 769c2aa98e2SPeter Wemm TermEscape.te_rv_on, 770c2aa98e2SPeter Wemm mp->metaname); 77140266059SGregory Neil Shapiro shiftout = true; 772c2aa98e2SPeter Wemm break; 773c2aa98e2SPeter Wemm } 774c2aa98e2SPeter Wemm } 775c2aa98e2SPeter Wemm if (c == MATCHCLASS || c == MATCHNCLASS) 776c2aa98e2SPeter Wemm { 777c2aa98e2SPeter Wemm if (bitset(0200, *s)) 77840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 77940266059SGregory Neil Shapiro SM_TIME_DEFAULT, 78040266059SGregory Neil Shapiro "{%s}", 78140266059SGregory Neil Shapiro macname(bitidx(*s++))); 782c2aa98e2SPeter Wemm else if (*s != '\0') 78340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 78440266059SGregory Neil Shapiro SM_TIME_DEFAULT, 78540266059SGregory Neil Shapiro "%c", 78640266059SGregory Neil Shapiro *s++); 787c2aa98e2SPeter Wemm } 788c2aa98e2SPeter Wemm if (mp->metaname != '\0') 789c2aa98e2SPeter Wemm continue; 790c2aa98e2SPeter Wemm 791c2aa98e2SPeter Wemm /* unrecognized meta character */ 79240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%sM-", 79340266059SGregory Neil Shapiro TermEscape.te_rv_on); 79440266059SGregory Neil Shapiro shiftout = true; 795c2aa98e2SPeter Wemm c &= 0177; 796c2aa98e2SPeter Wemm } 797c2aa98e2SPeter Wemm printchar: 798c2aa98e2SPeter Wemm if (isprint(c)) 799c2aa98e2SPeter Wemm { 80040266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 801c2aa98e2SPeter Wemm continue; 802c2aa98e2SPeter Wemm } 803c2aa98e2SPeter Wemm 804c2aa98e2SPeter Wemm /* wasn't a meta-macro -- find another way to print it */ 805c2aa98e2SPeter Wemm switch (c) 806c2aa98e2SPeter Wemm { 807c2aa98e2SPeter Wemm case '\n': 808c2aa98e2SPeter Wemm c = 'n'; 809c2aa98e2SPeter Wemm break; 810c2aa98e2SPeter Wemm 811c2aa98e2SPeter Wemm case '\r': 812c2aa98e2SPeter Wemm c = 'r'; 813c2aa98e2SPeter Wemm break; 814c2aa98e2SPeter Wemm 815c2aa98e2SPeter Wemm case '\t': 816c2aa98e2SPeter Wemm c = 't'; 817c2aa98e2SPeter Wemm break; 818c2aa98e2SPeter Wemm } 819c2aa98e2SPeter Wemm if (!shiftout) 820c2aa98e2SPeter Wemm { 82140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 82240266059SGregory Neil Shapiro TermEscape.te_rv_on); 82340266059SGregory Neil Shapiro shiftout = true; 824c2aa98e2SPeter Wemm } 825c2aa98e2SPeter Wemm if (isprint(c)) 826c2aa98e2SPeter Wemm { 82740266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '\\'); 82840266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c); 829c2aa98e2SPeter Wemm } 830c2aa98e2SPeter Wemm else 831c2aa98e2SPeter Wemm { 83240266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, '^'); 83340266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, c ^ 0100); 834c2aa98e2SPeter Wemm } 835c2aa98e2SPeter Wemm } 836c2aa98e2SPeter Wemm if (shiftout) 83740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s", 83840266059SGregory Neil Shapiro TermEscape.te_rv_off); 83940266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 840c2aa98e2SPeter Wemm } 84140266059SGregory Neil Shapiro /* 842c2aa98e2SPeter Wemm ** MAKELOWER -- Translate a line into lower case 843c2aa98e2SPeter Wemm ** 844c2aa98e2SPeter Wemm ** Parameters: 845c2aa98e2SPeter Wemm ** p -- the string to translate. If NULL, return is 846c2aa98e2SPeter Wemm ** immediate. 847c2aa98e2SPeter Wemm ** 848c2aa98e2SPeter Wemm ** Returns: 849c2aa98e2SPeter Wemm ** none. 850c2aa98e2SPeter Wemm ** 851c2aa98e2SPeter Wemm ** Side Effects: 852c2aa98e2SPeter Wemm ** String pointed to by p is translated to lower case. 853c2aa98e2SPeter Wemm */ 854c2aa98e2SPeter Wemm 855c2aa98e2SPeter Wemm void 856c2aa98e2SPeter Wemm makelower(p) 857c2aa98e2SPeter Wemm register char *p; 858c2aa98e2SPeter Wemm { 859c2aa98e2SPeter Wemm register char c; 860c2aa98e2SPeter Wemm 861c2aa98e2SPeter Wemm if (p == NULL) 862c2aa98e2SPeter Wemm return; 863c2aa98e2SPeter Wemm for (; (c = *p) != '\0'; p++) 864c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 865c2aa98e2SPeter Wemm *p = tolower(c); 866c2aa98e2SPeter Wemm } 86740266059SGregory Neil Shapiro /* 868c2aa98e2SPeter Wemm ** FIXCRLF -- fix <CR><LF> in line. 869c2aa98e2SPeter Wemm ** 870c2aa98e2SPeter Wemm ** Looks for the <CR><LF> combination and turns it into the 871c2aa98e2SPeter Wemm ** UNIX canonical <NL> character. It only takes one line, 872c2aa98e2SPeter Wemm ** i.e., it is assumed that the first <NL> found is the end 873c2aa98e2SPeter Wemm ** of the line. 874c2aa98e2SPeter Wemm ** 875c2aa98e2SPeter Wemm ** Parameters: 876c2aa98e2SPeter Wemm ** line -- the line to fix. 877c2aa98e2SPeter Wemm ** stripnl -- if true, strip the newline also. 878c2aa98e2SPeter Wemm ** 879c2aa98e2SPeter Wemm ** Returns: 880c2aa98e2SPeter Wemm ** none. 881c2aa98e2SPeter Wemm ** 882c2aa98e2SPeter Wemm ** Side Effects: 883c2aa98e2SPeter Wemm ** line is changed in place. 884c2aa98e2SPeter Wemm */ 885c2aa98e2SPeter Wemm 886c2aa98e2SPeter Wemm void 887c2aa98e2SPeter Wemm fixcrlf(line, stripnl) 888c2aa98e2SPeter Wemm char *line; 889c2aa98e2SPeter Wemm bool stripnl; 890c2aa98e2SPeter Wemm { 891c2aa98e2SPeter Wemm register char *p; 892c2aa98e2SPeter Wemm 893c2aa98e2SPeter Wemm p = strchr(line, '\n'); 894c2aa98e2SPeter Wemm if (p == NULL) 895c2aa98e2SPeter Wemm return; 896c2aa98e2SPeter Wemm if (p > line && p[-1] == '\r') 897c2aa98e2SPeter Wemm p--; 898c2aa98e2SPeter Wemm if (!stripnl) 899c2aa98e2SPeter Wemm *p++ = '\n'; 900c2aa98e2SPeter Wemm *p = '\0'; 901c2aa98e2SPeter Wemm } 90240266059SGregory Neil Shapiro /* 903c2aa98e2SPeter Wemm ** PUTLINE -- put a line like fputs obeying SMTP conventions 904c2aa98e2SPeter Wemm ** 905c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 906c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 907c2aa98e2SPeter Wemm ** 908c2aa98e2SPeter Wemm ** Parameters: 909c2aa98e2SPeter Wemm ** l -- line to put. 910c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 911c2aa98e2SPeter Wemm ** 912c2aa98e2SPeter Wemm ** Returns: 913c2aa98e2SPeter Wemm ** none 914c2aa98e2SPeter Wemm ** 915c2aa98e2SPeter Wemm ** Side Effects: 91640266059SGregory Neil Shapiro ** output of l to mci->mci_out. 917c2aa98e2SPeter Wemm */ 918c2aa98e2SPeter Wemm 919c2aa98e2SPeter Wemm void 920c2aa98e2SPeter Wemm putline(l, mci) 921c2aa98e2SPeter Wemm register char *l; 922c2aa98e2SPeter Wemm register MCI *mci; 923c2aa98e2SPeter Wemm { 924c2aa98e2SPeter Wemm putxline(l, strlen(l), mci, PXLF_MAPFROM); 925c2aa98e2SPeter Wemm } 92640266059SGregory Neil Shapiro /* 927c2aa98e2SPeter Wemm ** PUTXLINE -- putline with flags bits. 928c2aa98e2SPeter Wemm ** 929c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 930c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 931c2aa98e2SPeter Wemm ** 932c2aa98e2SPeter Wemm ** Parameters: 933c2aa98e2SPeter Wemm ** l -- line to put. 934c2aa98e2SPeter Wemm ** len -- the length of the line. 935c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 936c2aa98e2SPeter Wemm ** pxflags -- flag bits: 937c2aa98e2SPeter Wemm ** PXLF_MAPFROM -- map From_ to >From_. 938c2aa98e2SPeter Wemm ** PXLF_STRIP8BIT -- strip 8th bit. 939c2aa98e2SPeter Wemm ** PXLF_HEADER -- map bare newline in header to newline space. 940605302a5SGregory Neil Shapiro ** PXLF_NOADDEOL -- don't add an EOL if one wasn't present. 941c2aa98e2SPeter Wemm ** 942c2aa98e2SPeter Wemm ** Returns: 943c2aa98e2SPeter Wemm ** none 944c2aa98e2SPeter Wemm ** 945c2aa98e2SPeter Wemm ** Side Effects: 94640266059SGregory Neil Shapiro ** output of l to mci->mci_out. 947c2aa98e2SPeter Wemm */ 948c2aa98e2SPeter Wemm 949c2aa98e2SPeter Wemm void 950c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags) 951c2aa98e2SPeter Wemm register char *l; 952c2aa98e2SPeter Wemm size_t len; 953c2aa98e2SPeter Wemm register MCI *mci; 954c2aa98e2SPeter Wemm int pxflags; 955c2aa98e2SPeter Wemm { 95640266059SGregory Neil Shapiro bool dead = false; 957c2aa98e2SPeter Wemm register char *p, *end; 958c2aa98e2SPeter Wemm int slop = 0; 959c2aa98e2SPeter Wemm 960c2aa98e2SPeter Wemm /* strip out 0200 bits -- these can look like TELNET protocol */ 961c2aa98e2SPeter Wemm if (bitset(MCIF_7BIT, mci->mci_flags) || 962c2aa98e2SPeter Wemm bitset(PXLF_STRIP8BIT, pxflags)) 963c2aa98e2SPeter Wemm { 964c2aa98e2SPeter Wemm register char svchar; 965c2aa98e2SPeter Wemm 966c2aa98e2SPeter Wemm for (p = l; (svchar = *p) != '\0'; ++p) 967c2aa98e2SPeter Wemm if (bitset(0200, svchar)) 968c2aa98e2SPeter Wemm *p = svchar &~ 0200; 969c2aa98e2SPeter Wemm } 970c2aa98e2SPeter Wemm 971c2aa98e2SPeter Wemm end = l + len; 972c2aa98e2SPeter Wemm do 973c2aa98e2SPeter Wemm { 974605302a5SGregory Neil Shapiro bool noeol = false; 975605302a5SGregory Neil Shapiro 976c2aa98e2SPeter Wemm /* find the end of the line */ 977c2aa98e2SPeter Wemm p = memchr(l, '\n', end - l); 978c2aa98e2SPeter Wemm if (p == NULL) 979605302a5SGregory Neil Shapiro { 980c2aa98e2SPeter Wemm p = end; 981605302a5SGregory Neil Shapiro noeol = true; 982605302a5SGregory Neil Shapiro } 983c2aa98e2SPeter Wemm 984c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 98540266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 98640266059SGregory Neil Shapiro "%05d >>> ", (int) CurrentPid); 987c2aa98e2SPeter Wemm 988c2aa98e2SPeter Wemm /* check for line overflow */ 989c2aa98e2SPeter Wemm while (mci->mci_mailer->m_linelimit > 0 && 990c2aa98e2SPeter Wemm (p - l + slop) > mci->mci_mailer->m_linelimit) 991c2aa98e2SPeter Wemm { 992c2aa98e2SPeter Wemm char *l_base = l; 993c2aa98e2SPeter Wemm register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 994c2aa98e2SPeter Wemm 995c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 996c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 997c2aa98e2SPeter Wemm { 99840266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 99940266059SGregory Neil Shapiro '.') == SM_IO_EOF) 100040266059SGregory Neil Shapiro dead = true; 1001193538b7SGregory Neil Shapiro else 1002193538b7SGregory Neil Shapiro { 1003193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 100440266059SGregory Neil Shapiro DataProgress = true; 1005193538b7SGregory Neil Shapiro } 1006c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 100740266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 100840266059SGregory Neil Shapiro SM_TIME_DEFAULT, '.'); 1009c2aa98e2SPeter Wemm } 1010c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1011c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1012c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1013c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1014c2aa98e2SPeter Wemm { 101540266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 101640266059SGregory Neil Shapiro '>') == SM_IO_EOF) 101740266059SGregory Neil Shapiro dead = true; 1018193538b7SGregory Neil Shapiro else 1019193538b7SGregory Neil Shapiro { 1020193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 102140266059SGregory Neil Shapiro DataProgress = true; 1022193538b7SGregory Neil Shapiro } 1023c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 102440266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 102540266059SGregory Neil Shapiro SM_TIME_DEFAULT, 102640266059SGregory Neil Shapiro '>'); 1027c2aa98e2SPeter Wemm } 102806f25ae9SGregory Neil Shapiro if (dead) 102906f25ae9SGregory Neil Shapiro break; 103006f25ae9SGregory Neil Shapiro 1031c2aa98e2SPeter Wemm while (l < q) 1032c2aa98e2SPeter Wemm { 103340266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 103440266059SGregory Neil Shapiro (unsigned char) *l++) == SM_IO_EOF) 103506f25ae9SGregory Neil Shapiro { 103640266059SGregory Neil Shapiro dead = true; 103706f25ae9SGregory Neil Shapiro break; 1038c2aa98e2SPeter Wemm } 1039193538b7SGregory Neil Shapiro else 1040193538b7SGregory Neil Shapiro { 104106f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 104240266059SGregory Neil Shapiro DataProgress = true; 104306f25ae9SGregory Neil Shapiro } 1044193538b7SGregory Neil Shapiro } 104506f25ae9SGregory Neil Shapiro if (dead) 104606f25ae9SGregory Neil Shapiro break; 104706f25ae9SGregory Neil Shapiro 104840266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '!') == 104940266059SGregory Neil Shapiro SM_IO_EOF || 105040266059SGregory Neil Shapiro sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 105140266059SGregory Neil Shapiro mci->mci_mailer->m_eol) == 105240266059SGregory Neil Shapiro SM_IO_EOF || 105340266059SGregory Neil Shapiro sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, ' ') == 105440266059SGregory Neil Shapiro SM_IO_EOF) 105506f25ae9SGregory Neil Shapiro { 105640266059SGregory Neil Shapiro dead = true; 105706f25ae9SGregory Neil Shapiro break; 105806f25ae9SGregory Neil Shapiro } 1059193538b7SGregory Neil Shapiro else 1060193538b7SGregory Neil Shapiro { 106106f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 106240266059SGregory Neil Shapiro DataProgress = true; 1063193538b7SGregory Neil Shapiro } 1064c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1065c2aa98e2SPeter Wemm { 1066c2aa98e2SPeter Wemm for (l = l_base; l < q; l++) 106740266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 106840266059SGregory Neil Shapiro SM_TIME_DEFAULT, 106940266059SGregory Neil Shapiro (unsigned char)*l); 107040266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, 107140266059SGregory Neil Shapiro SM_TIME_DEFAULT, 107240266059SGregory Neil Shapiro "!\n%05d >>> ", 107340266059SGregory Neil Shapiro (int) CurrentPid); 1074c2aa98e2SPeter Wemm } 1075c2aa98e2SPeter Wemm slop = 1; 1076c2aa98e2SPeter Wemm } 1077c2aa98e2SPeter Wemm 107806f25ae9SGregory Neil Shapiro if (dead) 107906f25ae9SGregory Neil Shapiro break; 108006f25ae9SGregory Neil Shapiro 1081c2aa98e2SPeter Wemm /* output last part */ 1082c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 1083c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 1084c2aa98e2SPeter Wemm { 108540266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '.') == 108640266059SGregory Neil Shapiro SM_IO_EOF) 108706f25ae9SGregory Neil Shapiro break; 1088193538b7SGregory Neil Shapiro else 1089193538b7SGregory Neil Shapiro { 1090193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 109140266059SGregory Neil Shapiro DataProgress = true; 1092193538b7SGregory Neil Shapiro } 1093c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 109440266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 109540266059SGregory Neil Shapiro SM_TIME_DEFAULT, '.'); 1096c2aa98e2SPeter Wemm } 1097c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1098c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1099c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1100c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1101c2aa98e2SPeter Wemm { 110240266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '>') == 110340266059SGregory Neil Shapiro SM_IO_EOF) 110406f25ae9SGregory Neil Shapiro break; 1105193538b7SGregory Neil Shapiro else 1106193538b7SGregory Neil Shapiro { 1107193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 110840266059SGregory Neil Shapiro DataProgress = true; 1109193538b7SGregory Neil Shapiro } 1110c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 111140266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 111240266059SGregory Neil Shapiro SM_TIME_DEFAULT, '>'); 1113c2aa98e2SPeter Wemm } 1114c2aa98e2SPeter Wemm for ( ; l < p; ++l) 1115c2aa98e2SPeter Wemm { 1116c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 111740266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 111840266059SGregory Neil Shapiro SM_TIME_DEFAULT, 111940266059SGregory Neil Shapiro (unsigned char)*l); 112040266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 112140266059SGregory Neil Shapiro (unsigned char) *l) == SM_IO_EOF) 112206f25ae9SGregory Neil Shapiro { 112340266059SGregory Neil Shapiro dead = true; 112406f25ae9SGregory Neil Shapiro break; 1125c2aa98e2SPeter Wemm } 1126193538b7SGregory Neil Shapiro else 1127193538b7SGregory Neil Shapiro { 112806f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 112940266059SGregory Neil Shapiro DataProgress = true; 113006f25ae9SGregory Neil Shapiro } 1131193538b7SGregory Neil Shapiro } 113206f25ae9SGregory Neil Shapiro if (dead) 113306f25ae9SGregory Neil Shapiro break; 113406f25ae9SGregory Neil Shapiro 1135c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 113640266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, SM_TIME_DEFAULT, 113740266059SGregory Neil Shapiro '\n'); 1138605302a5SGregory Neil Shapiro if ((!bitset(PXLF_NOADDEOL, pxflags) || !noeol) && 1139605302a5SGregory Neil Shapiro sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 114040266059SGregory Neil Shapiro mci->mci_mailer->m_eol) == SM_IO_EOF) 114106f25ae9SGregory Neil Shapiro break; 1142193538b7SGregory Neil Shapiro else 1143193538b7SGregory Neil Shapiro { 1144193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 114540266059SGregory Neil Shapiro DataProgress = true; 1146193538b7SGregory Neil Shapiro } 1147c2aa98e2SPeter Wemm if (l < end && *l == '\n') 1148c2aa98e2SPeter Wemm { 1149c2aa98e2SPeter Wemm if (*++l != ' ' && *l != '\t' && *l != '\0' && 1150c2aa98e2SPeter Wemm bitset(PXLF_HEADER, pxflags)) 1151c2aa98e2SPeter Wemm { 115240266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 115340266059SGregory Neil Shapiro ' ') == SM_IO_EOF) 115406f25ae9SGregory Neil Shapiro break; 1155193538b7SGregory Neil Shapiro else 1156193538b7SGregory Neil Shapiro { 1157193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 115840266059SGregory Neil Shapiro DataProgress = true; 1159193538b7SGregory Neil Shapiro } 116040266059SGregory Neil Shapiro 1161c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 116240266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 116340266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' '); 1164c2aa98e2SPeter Wemm } 1165c2aa98e2SPeter Wemm } 116640266059SGregory Neil Shapiro 116740266059SGregory Neil Shapiro /* record progress for DATA timeout */ 116840266059SGregory Neil Shapiro DataProgress = true; 1169c2aa98e2SPeter Wemm } while (l < end); 1170c2aa98e2SPeter Wemm } 117140266059SGregory Neil Shapiro /* 1172c2aa98e2SPeter Wemm ** XUNLINK -- unlink a file, doing logging as appropriate. 1173c2aa98e2SPeter Wemm ** 1174c2aa98e2SPeter Wemm ** Parameters: 1175c2aa98e2SPeter Wemm ** f -- name of file to unlink. 1176c2aa98e2SPeter Wemm ** 1177c2aa98e2SPeter Wemm ** Returns: 117840266059SGregory Neil Shapiro ** return value of unlink() 1179c2aa98e2SPeter Wemm ** 1180c2aa98e2SPeter Wemm ** Side Effects: 1181c2aa98e2SPeter Wemm ** f is unlinked. 1182c2aa98e2SPeter Wemm */ 1183c2aa98e2SPeter Wemm 118440266059SGregory Neil Shapiro int 1185c2aa98e2SPeter Wemm xunlink(f) 1186c2aa98e2SPeter Wemm char *f; 1187c2aa98e2SPeter Wemm { 1188c2aa98e2SPeter Wemm register int i; 118940266059SGregory Neil Shapiro int save_errno; 1190c2aa98e2SPeter Wemm 1191c2aa98e2SPeter Wemm if (LogLevel > 98) 119240266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "unlink %s", f); 1193c2aa98e2SPeter Wemm 1194c2aa98e2SPeter Wemm i = unlink(f); 119540266059SGregory Neil Shapiro save_errno = errno; 1196c2aa98e2SPeter Wemm if (i < 0 && LogLevel > 97) 119740266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s: unlink-fail %d", 1198c2aa98e2SPeter Wemm f, errno); 119940266059SGregory Neil Shapiro if (i >= 0) 120040266059SGregory Neil Shapiro SYNC_DIR(f, false); 120140266059SGregory Neil Shapiro errno = save_errno; 120240266059SGregory Neil Shapiro return i; 1203c2aa98e2SPeter Wemm } 120440266059SGregory Neil Shapiro /* 1205c2aa98e2SPeter Wemm ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 1206c2aa98e2SPeter Wemm ** 1207c2aa98e2SPeter Wemm ** Parameters: 1208c2aa98e2SPeter Wemm ** buf -- place to put the input line. 1209c2aa98e2SPeter Wemm ** siz -- size of buf. 1210c2aa98e2SPeter Wemm ** fp -- file to read from. 1211c2aa98e2SPeter Wemm ** timeout -- the timeout before error occurs. 1212c2aa98e2SPeter Wemm ** during -- what we are trying to read (for error messages). 1213c2aa98e2SPeter Wemm ** 1214c2aa98e2SPeter Wemm ** Returns: 121540266059SGregory Neil Shapiro ** NULL on error (including timeout). This may also leave 1216c2aa98e2SPeter Wemm ** buf containing a null string. 1217c2aa98e2SPeter Wemm ** buf otherwise. 1218c2aa98e2SPeter Wemm */ 1219c2aa98e2SPeter Wemm 122006f25ae9SGregory Neil Shapiro 1221c2aa98e2SPeter Wemm char * 1222c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during) 1223c2aa98e2SPeter Wemm char *buf; 1224c2aa98e2SPeter Wemm int siz; 122540266059SGregory Neil Shapiro SM_FILE_T *fp; 1226c2aa98e2SPeter Wemm time_t timeout; 1227c2aa98e2SPeter Wemm char *during; 1228c2aa98e2SPeter Wemm { 1229c2aa98e2SPeter Wemm register char *p; 12302e43090eSPeter Wemm int save_errno; 123140266059SGregory Neil Shapiro int io_timeout; 123240266059SGregory Neil Shapiro 123340266059SGregory Neil Shapiro SM_REQUIRE(siz > 0); 123440266059SGregory Neil Shapiro SM_REQUIRE(buf != NULL); 1235c2aa98e2SPeter Wemm 1236c2aa98e2SPeter Wemm if (fp == NULL) 1237c2aa98e2SPeter Wemm { 1238c2aa98e2SPeter Wemm buf[0] = '\0'; 123940266059SGregory Neil Shapiro errno = EBADF; 1240c2aa98e2SPeter Wemm return NULL; 1241c2aa98e2SPeter Wemm } 1242c2aa98e2SPeter Wemm 124340266059SGregory Neil Shapiro /* try to read */ 124440266059SGregory Neil Shapiro p = NULL; 124540266059SGregory Neil Shapiro errno = 0; 124640266059SGregory Neil Shapiro 124740266059SGregory Neil Shapiro /* convert the timeout to sm_io notation */ 124840266059SGregory Neil Shapiro io_timeout = (timeout <= 0) ? SM_TIME_DEFAULT : timeout * 1000; 124940266059SGregory Neil Shapiro while (!sm_io_eof(fp) && !sm_io_error(fp)) 1250c2aa98e2SPeter Wemm { 125140266059SGregory Neil Shapiro errno = 0; 125240266059SGregory Neil Shapiro p = sm_io_fgets(fp, io_timeout, buf, siz); 125340266059SGregory Neil Shapiro if (p == NULL && errno == EAGAIN) 1254c2aa98e2SPeter Wemm { 125540266059SGregory Neil Shapiro /* The sm_io_fgets() call timedout */ 1256c2aa98e2SPeter Wemm if (LogLevel > 1) 1257c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 1258c2aa98e2SPeter Wemm "timeout waiting for input from %.100s during %s", 125940266059SGregory Neil Shapiro CURHOSTNAME, 1260c2aa98e2SPeter Wemm during); 1261c2aa98e2SPeter Wemm buf[0] = '\0'; 1262c2aa98e2SPeter Wemm #if XDEBUG 1263c2aa98e2SPeter Wemm checkfd012(during); 126406f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1265c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 126640266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, 126740266059SGregory Neil Shapiro SM_TIME_DEFAULT, 126840266059SGregory Neil Shapiro "%05d <<< [TIMEOUT]\n", 126940266059SGregory Neil Shapiro (int) CurrentPid); 127040266059SGregory Neil Shapiro errno = ETIMEDOUT; 127106f25ae9SGregory Neil Shapiro return NULL; 1272c2aa98e2SPeter Wemm } 1273c2aa98e2SPeter Wemm if (p != NULL || errno != EINTR) 1274c2aa98e2SPeter Wemm break; 127540266059SGregory Neil Shapiro (void) sm_io_clearerr(fp); 1276c2aa98e2SPeter Wemm } 12772e43090eSPeter Wemm save_errno = errno; 1278c2aa98e2SPeter Wemm 1279c2aa98e2SPeter Wemm /* clean up the books and exit */ 1280c2aa98e2SPeter Wemm LineNumber++; 1281c2aa98e2SPeter Wemm if (p == NULL) 1282c2aa98e2SPeter Wemm { 1283c2aa98e2SPeter Wemm buf[0] = '\0'; 1284c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 128540266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 128640266059SGregory Neil Shapiro "%05d <<< [EOF]\n", 128740266059SGregory Neil Shapiro (int) CurrentPid); 12882e43090eSPeter Wemm errno = save_errno; 128906f25ae9SGregory Neil Shapiro return NULL; 1290c2aa98e2SPeter Wemm } 1291c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 129240266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 129340266059SGregory Neil Shapiro "%05d <<< %s", (int) CurrentPid, buf); 1294c2aa98e2SPeter Wemm if (SevenBitInput) 1295c2aa98e2SPeter Wemm { 1296c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1297c2aa98e2SPeter Wemm *p &= ~0200; 1298c2aa98e2SPeter Wemm } 1299c2aa98e2SPeter Wemm else if (!HasEightBits) 1300c2aa98e2SPeter Wemm { 1301c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1302c2aa98e2SPeter Wemm { 1303c2aa98e2SPeter Wemm if (bitset(0200, *p)) 1304c2aa98e2SPeter Wemm { 130540266059SGregory Neil Shapiro HasEightBits = true; 1306c2aa98e2SPeter Wemm break; 1307c2aa98e2SPeter Wemm } 1308c2aa98e2SPeter Wemm } 1309c2aa98e2SPeter Wemm } 131006f25ae9SGregory Neil Shapiro return buf; 1311c2aa98e2SPeter Wemm } 13128774250cSGregory Neil Shapiro /* 131340266059SGregory Neil Shapiro ** FGETFOLDED -- like fgets, but knows about folded lines. 1314c2aa98e2SPeter Wemm ** 1315c2aa98e2SPeter Wemm ** Parameters: 1316c2aa98e2SPeter Wemm ** buf -- place to put result. 1317c2aa98e2SPeter Wemm ** n -- bytes available. 1318c2aa98e2SPeter Wemm ** f -- file to read from. 1319c2aa98e2SPeter Wemm ** 1320c2aa98e2SPeter Wemm ** Returns: 132140266059SGregory Neil Shapiro ** input line(s) on success, NULL on error or SM_IO_EOF. 1322c2aa98e2SPeter Wemm ** This will normally be buf -- unless the line is too 132340266059SGregory Neil Shapiro ** long, when it will be sm_malloc_x()ed. 1324c2aa98e2SPeter Wemm ** 1325c2aa98e2SPeter Wemm ** Side Effects: 1326c2aa98e2SPeter Wemm ** buf gets lines from f, with continuation lines (lines 1327c2aa98e2SPeter Wemm ** with leading white space) appended. CRLF's are mapped 1328c2aa98e2SPeter Wemm ** into single newlines. Any trailing NL is stripped. 1329c2aa98e2SPeter Wemm */ 1330c2aa98e2SPeter Wemm 1331c2aa98e2SPeter Wemm char * 1332c2aa98e2SPeter Wemm fgetfolded(buf, n, f) 1333c2aa98e2SPeter Wemm char *buf; 1334c2aa98e2SPeter Wemm register int n; 133540266059SGregory Neil Shapiro SM_FILE_T *f; 1336c2aa98e2SPeter Wemm { 1337c2aa98e2SPeter Wemm register char *p = buf; 1338c2aa98e2SPeter Wemm char *bp = buf; 1339c2aa98e2SPeter Wemm register int i; 1340c2aa98e2SPeter Wemm 134140266059SGregory Neil Shapiro SM_REQUIRE(n > 0); 134240266059SGregory Neil Shapiro SM_REQUIRE(buf != NULL); 134340266059SGregory Neil Shapiro if (f == NULL) 134440266059SGregory Neil Shapiro { 134540266059SGregory Neil Shapiro buf[0] = '\0'; 134640266059SGregory Neil Shapiro errno = EBADF; 134740266059SGregory Neil Shapiro return NULL; 134840266059SGregory Neil Shapiro } 134940266059SGregory Neil Shapiro 1350c2aa98e2SPeter Wemm n--; 135140266059SGregory Neil Shapiro while ((i = sm_io_getc(f, SM_TIME_DEFAULT)) != SM_IO_EOF) 1352c2aa98e2SPeter Wemm { 1353c2aa98e2SPeter Wemm if (i == '\r') 1354c2aa98e2SPeter Wemm { 135540266059SGregory Neil Shapiro i = sm_io_getc(f, SM_TIME_DEFAULT); 1356c2aa98e2SPeter Wemm if (i != '\n') 1357c2aa98e2SPeter Wemm { 135840266059SGregory Neil Shapiro if (i != SM_IO_EOF) 135940266059SGregory Neil Shapiro (void) sm_io_ungetc(f, SM_TIME_DEFAULT, 136040266059SGregory Neil Shapiro i); 1361c2aa98e2SPeter Wemm i = '\r'; 1362c2aa98e2SPeter Wemm } 1363c2aa98e2SPeter Wemm } 1364c2aa98e2SPeter Wemm if (--n <= 0) 1365c2aa98e2SPeter Wemm { 1366c2aa98e2SPeter Wemm /* allocate new space */ 1367c2aa98e2SPeter Wemm char *nbp; 1368c2aa98e2SPeter Wemm int nn; 1369c2aa98e2SPeter Wemm 1370c2aa98e2SPeter Wemm nn = (p - bp); 1371c2aa98e2SPeter Wemm if (nn < MEMCHUNKSIZE) 1372c2aa98e2SPeter Wemm nn *= 2; 1373c2aa98e2SPeter Wemm else 1374c2aa98e2SPeter Wemm nn += MEMCHUNKSIZE; 137540266059SGregory Neil Shapiro nbp = sm_malloc_x(nn); 137606f25ae9SGregory Neil Shapiro memmove(nbp, bp, p - bp); 1377c2aa98e2SPeter Wemm p = &nbp[p - bp]; 1378c2aa98e2SPeter Wemm if (bp != buf) 13798774250cSGregory Neil Shapiro sm_free(bp); 1380c2aa98e2SPeter Wemm bp = nbp; 1381c2aa98e2SPeter Wemm n = nn - (p - bp); 1382c2aa98e2SPeter Wemm } 1383c2aa98e2SPeter Wemm *p++ = i; 1384c2aa98e2SPeter Wemm if (i == '\n') 1385c2aa98e2SPeter Wemm { 1386c2aa98e2SPeter Wemm LineNumber++; 138740266059SGregory Neil Shapiro i = sm_io_getc(f, SM_TIME_DEFAULT); 138840266059SGregory Neil Shapiro if (i != SM_IO_EOF) 138940266059SGregory Neil Shapiro (void) sm_io_ungetc(f, SM_TIME_DEFAULT, i); 1390c2aa98e2SPeter Wemm if (i != ' ' && i != '\t') 1391c2aa98e2SPeter Wemm break; 1392c2aa98e2SPeter Wemm } 1393c2aa98e2SPeter Wemm } 1394c2aa98e2SPeter Wemm if (p == bp) 139506f25ae9SGregory Neil Shapiro return NULL; 1396c2aa98e2SPeter Wemm if (p[-1] == '\n') 1397c2aa98e2SPeter Wemm p--; 1398c2aa98e2SPeter Wemm *p = '\0'; 139906f25ae9SGregory Neil Shapiro return bp; 1400c2aa98e2SPeter Wemm } 140140266059SGregory Neil Shapiro /* 1402c2aa98e2SPeter Wemm ** CURTIME -- return current time. 1403c2aa98e2SPeter Wemm ** 1404c2aa98e2SPeter Wemm ** Parameters: 1405c2aa98e2SPeter Wemm ** none. 1406c2aa98e2SPeter Wemm ** 1407c2aa98e2SPeter Wemm ** Returns: 1408c2aa98e2SPeter Wemm ** the current time. 1409c2aa98e2SPeter Wemm */ 1410c2aa98e2SPeter Wemm 1411c2aa98e2SPeter Wemm time_t 1412c2aa98e2SPeter Wemm curtime() 1413c2aa98e2SPeter Wemm { 1414c2aa98e2SPeter Wemm auto time_t t; 1415c2aa98e2SPeter Wemm 1416c2aa98e2SPeter Wemm (void) time(&t); 141706f25ae9SGregory Neil Shapiro return t; 1418c2aa98e2SPeter Wemm } 141940266059SGregory Neil Shapiro /* 1420c2aa98e2SPeter Wemm ** ATOBOOL -- convert a string representation to boolean. 1421c2aa98e2SPeter Wemm ** 142240266059SGregory Neil Shapiro ** Defaults to false 1423c2aa98e2SPeter Wemm ** 1424c2aa98e2SPeter Wemm ** Parameters: 142540266059SGregory Neil Shapiro ** s -- string to convert. Takes "tTyY", empty, and NULL as true, 1426c2aa98e2SPeter Wemm ** others as false. 1427c2aa98e2SPeter Wemm ** 1428c2aa98e2SPeter Wemm ** Returns: 1429c2aa98e2SPeter Wemm ** A boolean representation of the string. 1430c2aa98e2SPeter Wemm */ 1431c2aa98e2SPeter Wemm 1432c2aa98e2SPeter Wemm bool 1433c2aa98e2SPeter Wemm atobool(s) 1434c2aa98e2SPeter Wemm register char *s; 1435c2aa98e2SPeter Wemm { 1436c2aa98e2SPeter Wemm if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 143740266059SGregory Neil Shapiro return true; 143840266059SGregory Neil Shapiro return false; 1439c2aa98e2SPeter Wemm } 144040266059SGregory Neil Shapiro /* 1441c2aa98e2SPeter Wemm ** ATOOCT -- convert a string representation to octal. 1442c2aa98e2SPeter Wemm ** 1443c2aa98e2SPeter Wemm ** Parameters: 1444c2aa98e2SPeter Wemm ** s -- string to convert. 1445c2aa98e2SPeter Wemm ** 1446c2aa98e2SPeter Wemm ** Returns: 1447c2aa98e2SPeter Wemm ** An integer representing the string interpreted as an 1448c2aa98e2SPeter Wemm ** octal number. 1449c2aa98e2SPeter Wemm */ 1450c2aa98e2SPeter Wemm 1451c2aa98e2SPeter Wemm int 1452c2aa98e2SPeter Wemm atooct(s) 1453c2aa98e2SPeter Wemm register char *s; 1454c2aa98e2SPeter Wemm { 1455c2aa98e2SPeter Wemm register int i = 0; 1456c2aa98e2SPeter Wemm 1457c2aa98e2SPeter Wemm while (*s >= '0' && *s <= '7') 1458c2aa98e2SPeter Wemm i = (i << 3) | (*s++ - '0'); 145906f25ae9SGregory Neil Shapiro return i; 1460c2aa98e2SPeter Wemm } 146140266059SGregory Neil Shapiro /* 1462c2aa98e2SPeter Wemm ** BITINTERSECT -- tell if two bitmaps intersect 1463c2aa98e2SPeter Wemm ** 1464c2aa98e2SPeter Wemm ** Parameters: 1465c2aa98e2SPeter Wemm ** a, b -- the bitmaps in question 1466c2aa98e2SPeter Wemm ** 1467c2aa98e2SPeter Wemm ** Returns: 146840266059SGregory Neil Shapiro ** true if they have a non-null intersection 146940266059SGregory Neil Shapiro ** false otherwise 1470c2aa98e2SPeter Wemm */ 1471c2aa98e2SPeter Wemm 1472c2aa98e2SPeter Wemm bool 1473c2aa98e2SPeter Wemm bitintersect(a, b) 147406f25ae9SGregory Neil Shapiro BITMAP256 a; 147506f25ae9SGregory Neil Shapiro BITMAP256 b; 1476c2aa98e2SPeter Wemm { 1477c2aa98e2SPeter Wemm int i; 1478c2aa98e2SPeter Wemm 1479c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1480193538b7SGregory Neil Shapiro { 1481c2aa98e2SPeter Wemm if ((a[i] & b[i]) != 0) 148240266059SGregory Neil Shapiro return true; 1483193538b7SGregory Neil Shapiro } 148440266059SGregory Neil Shapiro return false; 1485c2aa98e2SPeter Wemm } 148640266059SGregory Neil Shapiro /* 1487c2aa98e2SPeter Wemm ** BITZEROP -- tell if a bitmap is all zero 1488c2aa98e2SPeter Wemm ** 1489c2aa98e2SPeter Wemm ** Parameters: 1490c2aa98e2SPeter Wemm ** map -- the bit map to check 1491c2aa98e2SPeter Wemm ** 1492c2aa98e2SPeter Wemm ** Returns: 149340266059SGregory Neil Shapiro ** true if map is all zero. 149440266059SGregory Neil Shapiro ** false if there are any bits set in map. 1495c2aa98e2SPeter Wemm */ 1496c2aa98e2SPeter Wemm 1497c2aa98e2SPeter Wemm bool 1498c2aa98e2SPeter Wemm bitzerop(map) 149906f25ae9SGregory Neil Shapiro BITMAP256 map; 1500c2aa98e2SPeter Wemm { 1501c2aa98e2SPeter Wemm int i; 1502c2aa98e2SPeter Wemm 1503c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1504193538b7SGregory Neil Shapiro { 1505c2aa98e2SPeter Wemm if (map[i] != 0) 150640266059SGregory Neil Shapiro return false; 1507193538b7SGregory Neil Shapiro } 150840266059SGregory Neil Shapiro return true; 1509c2aa98e2SPeter Wemm } 151040266059SGregory Neil Shapiro /* 1511c2aa98e2SPeter Wemm ** STRCONTAINEDIN -- tell if one string is contained in another 1512c2aa98e2SPeter Wemm ** 1513c2aa98e2SPeter Wemm ** Parameters: 151440266059SGregory Neil Shapiro ** icase -- ignore case? 1515c2aa98e2SPeter Wemm ** a -- possible substring. 1516c2aa98e2SPeter Wemm ** b -- possible superstring. 1517c2aa98e2SPeter Wemm ** 1518c2aa98e2SPeter Wemm ** Returns: 151940266059SGregory Neil Shapiro ** true if a is contained in b (case insensitive). 152040266059SGregory Neil Shapiro ** false otherwise. 1521c2aa98e2SPeter Wemm */ 1522c2aa98e2SPeter Wemm 1523c2aa98e2SPeter Wemm bool 152440266059SGregory Neil Shapiro strcontainedin(icase, a, b) 152540266059SGregory Neil Shapiro bool icase; 1526c2aa98e2SPeter Wemm register char *a; 1527c2aa98e2SPeter Wemm register char *b; 1528c2aa98e2SPeter Wemm { 1529c2aa98e2SPeter Wemm int la; 1530c2aa98e2SPeter Wemm int lb; 1531c2aa98e2SPeter Wemm int c; 1532c2aa98e2SPeter Wemm 1533c2aa98e2SPeter Wemm la = strlen(a); 1534c2aa98e2SPeter Wemm lb = strlen(b); 1535c2aa98e2SPeter Wemm c = *a; 153640266059SGregory Neil Shapiro if (icase && isascii(c) && isupper(c)) 1537c2aa98e2SPeter Wemm c = tolower(c); 1538c2aa98e2SPeter Wemm for (; lb-- >= la; b++) 1539c2aa98e2SPeter Wemm { 154040266059SGregory Neil Shapiro if (icase) 154140266059SGregory Neil Shapiro { 154240266059SGregory Neil Shapiro if (*b != c && 154340266059SGregory Neil Shapiro isascii(*b) && isupper(*b) && tolower(*b) != c) 1544c2aa98e2SPeter Wemm continue; 154540266059SGregory Neil Shapiro if (sm_strncasecmp(a, b, la) == 0) 154640266059SGregory Neil Shapiro return true; 1547c2aa98e2SPeter Wemm } 154840266059SGregory Neil Shapiro else 154940266059SGregory Neil Shapiro { 155040266059SGregory Neil Shapiro if (*b != c) 155140266059SGregory Neil Shapiro continue; 155240266059SGregory Neil Shapiro if (strncmp(a, b, la) == 0) 155340266059SGregory Neil Shapiro return true; 1554c2aa98e2SPeter Wemm } 155540266059SGregory Neil Shapiro } 155640266059SGregory Neil Shapiro return false; 155740266059SGregory Neil Shapiro } 155840266059SGregory Neil Shapiro /* 1559c2aa98e2SPeter Wemm ** CHECKFD012 -- check low numbered file descriptors 1560c2aa98e2SPeter Wemm ** 1561c2aa98e2SPeter Wemm ** File descriptors 0, 1, and 2 should be open at all times. 1562c2aa98e2SPeter Wemm ** This routine verifies that, and fixes it if not true. 1563c2aa98e2SPeter Wemm ** 1564c2aa98e2SPeter Wemm ** Parameters: 1565c2aa98e2SPeter Wemm ** where -- a tag printed if the assertion failed 1566c2aa98e2SPeter Wemm ** 1567c2aa98e2SPeter Wemm ** Returns: 1568c2aa98e2SPeter Wemm ** none 1569c2aa98e2SPeter Wemm */ 1570c2aa98e2SPeter Wemm 1571c2aa98e2SPeter Wemm void 1572c2aa98e2SPeter Wemm checkfd012(where) 1573c2aa98e2SPeter Wemm char *where; 1574c2aa98e2SPeter Wemm { 1575c2aa98e2SPeter Wemm #if XDEBUG 1576c2aa98e2SPeter Wemm register int i; 1577c2aa98e2SPeter Wemm 1578c2aa98e2SPeter Wemm for (i = 0; i < 3; i++) 1579c2aa98e2SPeter Wemm fill_fd(i, where); 1580c2aa98e2SPeter Wemm #endif /* XDEBUG */ 1581c2aa98e2SPeter Wemm } 158240266059SGregory Neil Shapiro /* 1583c2aa98e2SPeter Wemm ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1584c2aa98e2SPeter Wemm ** 1585c2aa98e2SPeter Wemm ** Parameters: 1586c2aa98e2SPeter Wemm ** fd -- file descriptor to check. 1587c2aa98e2SPeter Wemm ** where -- tag to print on failure. 1588c2aa98e2SPeter Wemm ** 1589c2aa98e2SPeter Wemm ** Returns: 1590c2aa98e2SPeter Wemm ** none. 1591c2aa98e2SPeter Wemm */ 1592c2aa98e2SPeter Wemm 1593c2aa98e2SPeter Wemm void 1594c2aa98e2SPeter Wemm checkfdopen(fd, where) 1595c2aa98e2SPeter Wemm int fd; 1596c2aa98e2SPeter Wemm char *where; 1597c2aa98e2SPeter Wemm { 1598c2aa98e2SPeter Wemm #if XDEBUG 1599c2aa98e2SPeter Wemm struct stat st; 1600c2aa98e2SPeter Wemm 1601c2aa98e2SPeter Wemm if (fstat(fd, &st) < 0 && errno == EBADF) 1602c2aa98e2SPeter Wemm { 1603c2aa98e2SPeter Wemm syserr("checkfdopen(%d): %s not open as expected!", fd, where); 160440266059SGregory Neil Shapiro printopenfds(true); 1605c2aa98e2SPeter Wemm } 160606f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1607c2aa98e2SPeter Wemm } 160840266059SGregory Neil Shapiro /* 1609c2aa98e2SPeter Wemm ** CHECKFDS -- check for new or missing file descriptors 1610c2aa98e2SPeter Wemm ** 1611c2aa98e2SPeter Wemm ** Parameters: 1612c2aa98e2SPeter Wemm ** where -- tag for printing. If null, take a base line. 1613c2aa98e2SPeter Wemm ** 1614c2aa98e2SPeter Wemm ** Returns: 1615c2aa98e2SPeter Wemm ** none 1616c2aa98e2SPeter Wemm ** 1617c2aa98e2SPeter Wemm ** Side Effects: 1618c2aa98e2SPeter Wemm ** If where is set, shows changes since the last call. 1619c2aa98e2SPeter Wemm */ 1620c2aa98e2SPeter Wemm 1621c2aa98e2SPeter Wemm void 1622c2aa98e2SPeter Wemm checkfds(where) 1623c2aa98e2SPeter Wemm char *where; 1624c2aa98e2SPeter Wemm { 1625c2aa98e2SPeter Wemm int maxfd; 1626c2aa98e2SPeter Wemm register int fd; 162740266059SGregory Neil Shapiro bool printhdr = true; 1628c2aa98e2SPeter Wemm int save_errno = errno; 162906f25ae9SGregory Neil Shapiro static BITMAP256 baseline; 1630c2aa98e2SPeter Wemm extern int DtableSize; 1631c2aa98e2SPeter Wemm 1632193538b7SGregory Neil Shapiro if (DtableSize > BITMAPBITS) 1633193538b7SGregory Neil Shapiro maxfd = BITMAPBITS; 1634c2aa98e2SPeter Wemm else 1635c2aa98e2SPeter Wemm maxfd = DtableSize; 1636c2aa98e2SPeter Wemm if (where == NULL) 1637c2aa98e2SPeter Wemm clrbitmap(baseline); 1638c2aa98e2SPeter Wemm 1639c2aa98e2SPeter Wemm for (fd = 0; fd < maxfd; fd++) 1640c2aa98e2SPeter Wemm { 1641c2aa98e2SPeter Wemm struct stat stbuf; 1642c2aa98e2SPeter Wemm 1643c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 1644c2aa98e2SPeter Wemm { 1645c2aa98e2SPeter Wemm if (!bitnset(fd, baseline)) 1646c2aa98e2SPeter Wemm continue; 1647c2aa98e2SPeter Wemm clrbitn(fd, baseline); 1648c2aa98e2SPeter Wemm } 1649c2aa98e2SPeter Wemm else if (!bitnset(fd, baseline)) 1650c2aa98e2SPeter Wemm setbitn(fd, baseline); 1651c2aa98e2SPeter Wemm else 1652c2aa98e2SPeter Wemm continue; 1653c2aa98e2SPeter Wemm 1654c2aa98e2SPeter Wemm /* file state has changed */ 1655c2aa98e2SPeter Wemm if (where == NULL) 1656c2aa98e2SPeter Wemm continue; 1657c2aa98e2SPeter Wemm if (printhdr) 1658c2aa98e2SPeter Wemm { 1659c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1660c2aa98e2SPeter Wemm "%s: changed fds:", 1661c2aa98e2SPeter Wemm where); 166240266059SGregory Neil Shapiro printhdr = false; 1663c2aa98e2SPeter Wemm } 166440266059SGregory Neil Shapiro dumpfd(fd, true, true); 1665c2aa98e2SPeter Wemm } 1666c2aa98e2SPeter Wemm errno = save_errno; 1667c2aa98e2SPeter Wemm } 166840266059SGregory Neil Shapiro /* 1669c2aa98e2SPeter Wemm ** PRINTOPENFDS -- print the open file descriptors (for debugging) 1670c2aa98e2SPeter Wemm ** 1671c2aa98e2SPeter Wemm ** Parameters: 1672c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog; otherwise 1673c2aa98e2SPeter Wemm ** print for debugging. 1674c2aa98e2SPeter Wemm ** 1675c2aa98e2SPeter Wemm ** Returns: 1676c2aa98e2SPeter Wemm ** none. 1677c2aa98e2SPeter Wemm */ 1678c2aa98e2SPeter Wemm 167906f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 1680c2aa98e2SPeter Wemm # include <arpa/inet.h> 168106f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 1682c2aa98e2SPeter Wemm 1683c2aa98e2SPeter Wemm void 1684c2aa98e2SPeter Wemm printopenfds(logit) 1685c2aa98e2SPeter Wemm bool logit; 1686c2aa98e2SPeter Wemm { 1687c2aa98e2SPeter Wemm register int fd; 1688c2aa98e2SPeter Wemm extern int DtableSize; 1689c2aa98e2SPeter Wemm 1690c2aa98e2SPeter Wemm for (fd = 0; fd < DtableSize; fd++) 169140266059SGregory Neil Shapiro dumpfd(fd, false, logit); 1692c2aa98e2SPeter Wemm } 169340266059SGregory Neil Shapiro /* 1694c2aa98e2SPeter Wemm ** DUMPFD -- dump a file descriptor 1695c2aa98e2SPeter Wemm ** 1696c2aa98e2SPeter Wemm ** Parameters: 1697c2aa98e2SPeter Wemm ** fd -- the file descriptor to dump. 1698c2aa98e2SPeter Wemm ** printclosed -- if set, print a notification even if 1699c2aa98e2SPeter Wemm ** it is closed; otherwise print nothing. 1700c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog instead of stdout. 170140266059SGregory Neil Shapiro ** 170240266059SGregory Neil Shapiro ** Returns: 170340266059SGregory Neil Shapiro ** none. 1704c2aa98e2SPeter Wemm */ 1705c2aa98e2SPeter Wemm 1706c2aa98e2SPeter Wemm void 1707c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit) 1708c2aa98e2SPeter Wemm int fd; 1709c2aa98e2SPeter Wemm bool printclosed; 1710c2aa98e2SPeter Wemm bool logit; 1711c2aa98e2SPeter Wemm { 1712c2aa98e2SPeter Wemm register char *p; 1713c2aa98e2SPeter Wemm char *hp; 1714c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1715c2aa98e2SPeter Wemm SOCKADDR sa; 171606f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1717c2aa98e2SPeter Wemm auto SOCKADDR_LEN_T slen; 1718c2aa98e2SPeter Wemm int i; 1719c2aa98e2SPeter Wemm #if STAT64 > 0 1720c2aa98e2SPeter Wemm struct stat64 st; 172106f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1722c2aa98e2SPeter Wemm struct stat st; 172306f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1724c2aa98e2SPeter Wemm char buf[200]; 1725c2aa98e2SPeter Wemm 1726c2aa98e2SPeter Wemm p = buf; 172740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 1728c2aa98e2SPeter Wemm p += strlen(p); 1729c2aa98e2SPeter Wemm 1730c2aa98e2SPeter Wemm if ( 1731c2aa98e2SPeter Wemm #if STAT64 > 0 1732c2aa98e2SPeter Wemm fstat64(fd, &st) 173306f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1734c2aa98e2SPeter Wemm fstat(fd, &st) 173506f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1736c2aa98e2SPeter Wemm < 0) 1737c2aa98e2SPeter Wemm { 1738c2aa98e2SPeter Wemm if (errno != EBADF) 1739c2aa98e2SPeter Wemm { 174040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 174140266059SGregory Neil Shapiro "CANNOT STAT (%s)", 174240266059SGregory Neil Shapiro sm_errstring(errno)); 1743c2aa98e2SPeter Wemm goto printit; 1744c2aa98e2SPeter Wemm } 1745c2aa98e2SPeter Wemm else if (printclosed) 1746c2aa98e2SPeter Wemm { 174740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "CLOSED"); 1748c2aa98e2SPeter Wemm goto printit; 1749c2aa98e2SPeter Wemm } 1750c2aa98e2SPeter Wemm return; 1751c2aa98e2SPeter Wemm } 1752c2aa98e2SPeter Wemm 1753605302a5SGregory Neil Shapiro i = fcntl(fd, F_GETFL, 0); 1754c2aa98e2SPeter Wemm if (i != -1) 1755c2aa98e2SPeter Wemm { 175640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 1757c2aa98e2SPeter Wemm p += strlen(p); 1758c2aa98e2SPeter Wemm } 1759c2aa98e2SPeter Wemm 176040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "mode=%o: ", 176140266059SGregory Neil Shapiro (int) st.st_mode); 1762c2aa98e2SPeter Wemm p += strlen(p); 1763c2aa98e2SPeter Wemm switch (st.st_mode & S_IFMT) 1764c2aa98e2SPeter Wemm { 1765c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1766c2aa98e2SPeter Wemm case S_IFSOCK: 176740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "SOCK "); 1768c2aa98e2SPeter Wemm p += strlen(p); 176906f25ae9SGregory Neil Shapiro memset(&sa, '\0', sizeof sa); 1770c2aa98e2SPeter Wemm slen = sizeof sa; 1771c2aa98e2SPeter Wemm if (getsockname(fd, &sa.sa, &slen) < 0) 177240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 177340266059SGregory Neil Shapiro sm_errstring(errno)); 1774c2aa98e2SPeter Wemm else 1775c2aa98e2SPeter Wemm { 1776c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 177706f25ae9SGregory Neil Shapiro if (hp == NULL) 177806f25ae9SGregory Neil Shapiro { 177906f25ae9SGregory Neil Shapiro /* EMPTY */ 178006f25ae9SGregory Neil Shapiro /* do nothing */ 178106f25ae9SGregory Neil Shapiro } 178206f25ae9SGregory Neil Shapiro # if NETINET 178306f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 178440266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 178540266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin.sin_port)); 178606f25ae9SGregory Neil Shapiro # endif /* NETINET */ 178706f25ae9SGregory Neil Shapiro # if NETINET6 178806f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 178940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 179040266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 179106f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1792c2aa98e2SPeter Wemm else 179340266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 179440266059SGregory Neil Shapiro "%s", hp); 1795c2aa98e2SPeter Wemm } 1796c2aa98e2SPeter Wemm p += strlen(p); 179740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "->"); 1798c2aa98e2SPeter Wemm p += strlen(p); 1799c2aa98e2SPeter Wemm slen = sizeof sa; 1800c2aa98e2SPeter Wemm if (getpeername(fd, &sa.sa, &slen) < 0) 180140266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 180240266059SGregory Neil Shapiro sm_errstring(errno)); 1803c2aa98e2SPeter Wemm else 1804c2aa98e2SPeter Wemm { 1805c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 180606f25ae9SGregory Neil Shapiro if (hp == NULL) 180706f25ae9SGregory Neil Shapiro { 180806f25ae9SGregory Neil Shapiro /* EMPTY */ 180906f25ae9SGregory Neil Shapiro /* do nothing */ 181006f25ae9SGregory Neil Shapiro } 181106f25ae9SGregory Neil Shapiro # if NETINET 181206f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 181340266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 181440266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin.sin_port)); 181506f25ae9SGregory Neil Shapiro # endif /* NETINET */ 181606f25ae9SGregory Neil Shapiro # if NETINET6 181706f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 181840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 181940266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 182006f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1821c2aa98e2SPeter Wemm else 182240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 182340266059SGregory Neil Shapiro "%s", hp); 1824c2aa98e2SPeter Wemm } 1825c2aa98e2SPeter Wemm break; 182606f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1827c2aa98e2SPeter Wemm 1828c2aa98e2SPeter Wemm case S_IFCHR: 182940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "CHR: "); 1830c2aa98e2SPeter Wemm p += strlen(p); 1831c2aa98e2SPeter Wemm goto defprint; 1832c2aa98e2SPeter Wemm 183340266059SGregory Neil Shapiro #ifdef S_IFBLK 1834c2aa98e2SPeter Wemm case S_IFBLK: 183540266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "BLK: "); 1836c2aa98e2SPeter Wemm p += strlen(p); 1837c2aa98e2SPeter Wemm goto defprint; 183840266059SGregory Neil Shapiro #endif /* S_IFBLK */ 1839c2aa98e2SPeter Wemm 1840c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 1841c2aa98e2SPeter Wemm case S_IFIFO: 184240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "FIFO: "); 1843c2aa98e2SPeter Wemm p += strlen(p); 1844c2aa98e2SPeter Wemm goto defprint; 184506f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 1846c2aa98e2SPeter Wemm 1847c2aa98e2SPeter Wemm #ifdef S_IFDIR 1848c2aa98e2SPeter Wemm case S_IFDIR: 184940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "DIR: "); 1850c2aa98e2SPeter Wemm p += strlen(p); 1851c2aa98e2SPeter Wemm goto defprint; 185206f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */ 1853c2aa98e2SPeter Wemm 1854c2aa98e2SPeter Wemm #ifdef S_IFLNK 1855c2aa98e2SPeter Wemm case S_IFLNK: 185640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "LNK: "); 1857c2aa98e2SPeter Wemm p += strlen(p); 1858c2aa98e2SPeter Wemm goto defprint; 185906f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */ 1860c2aa98e2SPeter Wemm 1861c2aa98e2SPeter Wemm default: 1862c2aa98e2SPeter Wemm defprint: 186340266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 186440266059SGregory Neil Shapiro "dev=%d/%d, ino=%llu, nlink=%d, u/gid=%d/%d, ", 1865c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 186640266059SGregory Neil Shapiro (ULONGLONG_T) st.st_ino, 186706f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 186806f25ae9SGregory Neil Shapiro (int) st.st_gid); 186940266059SGregory Neil Shapiro p += strlen(p); 187040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "size=%llu", 187140266059SGregory Neil Shapiro (ULONGLONG_T) st.st_size); 1872c2aa98e2SPeter Wemm break; 1873c2aa98e2SPeter Wemm } 1874c2aa98e2SPeter Wemm 1875c2aa98e2SPeter Wemm printit: 1876c2aa98e2SPeter Wemm if (logit) 1877c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 1878c2aa98e2SPeter Wemm "%.800s", buf); 1879c2aa98e2SPeter Wemm else 188040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "%s\n", buf); 1881c2aa98e2SPeter Wemm } 188240266059SGregory Neil Shapiro /* 1883c2aa98e2SPeter Wemm ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1884c2aa98e2SPeter Wemm ** 1885c2aa98e2SPeter Wemm ** Parameters: 1886c2aa98e2SPeter Wemm ** host -- the host to shorten (stripped in place). 1887c2aa98e2SPeter Wemm ** 1888c2aa98e2SPeter Wemm ** Returns: 188940266059SGregory Neil Shapiro ** place where string was truncated, NULL if not truncated. 1890c2aa98e2SPeter Wemm */ 1891c2aa98e2SPeter Wemm 1892602a2b1bSGregory Neil Shapiro char * 1893c2aa98e2SPeter Wemm shorten_hostname(host) 1894c2aa98e2SPeter Wemm char host[]; 1895c2aa98e2SPeter Wemm { 1896c2aa98e2SPeter Wemm register char *p; 1897c2aa98e2SPeter Wemm char *mydom; 1898c2aa98e2SPeter Wemm int i; 189940266059SGregory Neil Shapiro bool canon = false; 1900c2aa98e2SPeter Wemm 1901c2aa98e2SPeter Wemm /* strip off final dot */ 190240266059SGregory Neil Shapiro i = strlen(host); 190340266059SGregory Neil Shapiro p = &host[(i == 0) ? 0 : i - 1]; 1904c2aa98e2SPeter Wemm if (*p == '.') 1905c2aa98e2SPeter Wemm { 1906c2aa98e2SPeter Wemm *p = '\0'; 190740266059SGregory Neil Shapiro canon = true; 1908c2aa98e2SPeter Wemm } 1909c2aa98e2SPeter Wemm 1910c2aa98e2SPeter Wemm /* see if there is any domain at all -- if not, we are done */ 1911c2aa98e2SPeter Wemm p = strchr(host, '.'); 1912c2aa98e2SPeter Wemm if (p == NULL) 1913602a2b1bSGregory Neil Shapiro return NULL; 1914c2aa98e2SPeter Wemm 1915c2aa98e2SPeter Wemm /* yes, we have a domain -- see if it looks like us */ 1916c2aa98e2SPeter Wemm mydom = macvalue('m', CurEnv); 1917c2aa98e2SPeter Wemm if (mydom == NULL) 1918c2aa98e2SPeter Wemm mydom = ""; 1919c2aa98e2SPeter Wemm i = strlen(++p); 192040266059SGregory Neil Shapiro if ((canon ? sm_strcasecmp(p, mydom) 192140266059SGregory Neil Shapiro : sm_strncasecmp(p, mydom, i)) == 0 && 1922c2aa98e2SPeter Wemm (mydom[i] == '.' || mydom[i] == '\0')) 1923602a2b1bSGregory Neil Shapiro { 1924c2aa98e2SPeter Wemm *--p = '\0'; 1925602a2b1bSGregory Neil Shapiro return p; 1926602a2b1bSGregory Neil Shapiro } 1927602a2b1bSGregory Neil Shapiro return NULL; 1928c2aa98e2SPeter Wemm } 192940266059SGregory Neil Shapiro /* 1930c2aa98e2SPeter Wemm ** PROG_OPEN -- open a program for reading 1931c2aa98e2SPeter Wemm ** 1932c2aa98e2SPeter Wemm ** Parameters: 1933c2aa98e2SPeter Wemm ** argv -- the argument list. 1934c2aa98e2SPeter Wemm ** pfd -- pointer to a place to store the file descriptor. 1935c2aa98e2SPeter Wemm ** e -- the current envelope. 1936c2aa98e2SPeter Wemm ** 1937c2aa98e2SPeter Wemm ** Returns: 1938c2aa98e2SPeter Wemm ** pid of the process -- -1 if it failed. 1939c2aa98e2SPeter Wemm */ 1940c2aa98e2SPeter Wemm 19418774250cSGregory Neil Shapiro pid_t 1942c2aa98e2SPeter Wemm prog_open(argv, pfd, e) 1943c2aa98e2SPeter Wemm char **argv; 1944c2aa98e2SPeter Wemm int *pfd; 1945c2aa98e2SPeter Wemm ENVELOPE *e; 1946c2aa98e2SPeter Wemm { 19478774250cSGregory Neil Shapiro pid_t pid; 1948c2aa98e2SPeter Wemm int i; 194906f25ae9SGregory Neil Shapiro int save_errno; 195040266059SGregory Neil Shapiro int sff; 195140266059SGregory Neil Shapiro int ret; 1952c2aa98e2SPeter Wemm int fdv[2]; 1953c2aa98e2SPeter Wemm char *p, *q; 195494c01205SGregory Neil Shapiro char buf[MAXPATHLEN]; 1955c2aa98e2SPeter Wemm extern int DtableSize; 1956c2aa98e2SPeter Wemm 1957c2aa98e2SPeter Wemm if (pipe(fdv) < 0) 1958c2aa98e2SPeter Wemm { 1959c2aa98e2SPeter Wemm syserr("%s: cannot create pipe for stdout", argv[0]); 1960c2aa98e2SPeter Wemm return -1; 1961c2aa98e2SPeter Wemm } 1962c2aa98e2SPeter Wemm pid = fork(); 1963c2aa98e2SPeter Wemm if (pid < 0) 1964c2aa98e2SPeter Wemm { 1965c2aa98e2SPeter Wemm syserr("%s: cannot fork", argv[0]); 196606f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 196706f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1968c2aa98e2SPeter Wemm return -1; 1969c2aa98e2SPeter Wemm } 1970c2aa98e2SPeter Wemm if (pid > 0) 1971c2aa98e2SPeter Wemm { 1972c2aa98e2SPeter Wemm /* parent */ 197306f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1974c2aa98e2SPeter Wemm *pfd = fdv[0]; 1975c2aa98e2SPeter Wemm return pid; 1976c2aa98e2SPeter Wemm } 1977c2aa98e2SPeter Wemm 19788774250cSGregory Neil Shapiro /* Reset global flags */ 19798774250cSGregory Neil Shapiro RestartRequest = NULL; 198040266059SGregory Neil Shapiro RestartWorkGroup = false; 19818774250cSGregory Neil Shapiro ShutdownRequest = NULL; 19828774250cSGregory Neil Shapiro PendingSignal = 0; 198340266059SGregory Neil Shapiro CurrentPid = getpid(); 198440266059SGregory Neil Shapiro 198540266059SGregory Neil Shapiro /* 198640266059SGregory Neil Shapiro ** Initialize exception stack and default exception 198740266059SGregory Neil Shapiro ** handler for child process. 198840266059SGregory Neil Shapiro */ 198940266059SGregory Neil Shapiro 199040266059SGregory Neil Shapiro sm_exc_newthread(fatal_error); 199140266059SGregory Neil Shapiro 199240266059SGregory Neil Shapiro /* child -- close stdin */ 199340266059SGregory Neil Shapiro (void) close(0); 19948774250cSGregory Neil Shapiro 1995c2aa98e2SPeter Wemm /* stdout goes back to parent */ 199606f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 1997c2aa98e2SPeter Wemm if (dup2(fdv[1], 1) < 0) 1998c2aa98e2SPeter Wemm { 1999c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stdout", argv[0]); 2000c2aa98e2SPeter Wemm _exit(EX_OSERR); 2001c2aa98e2SPeter Wemm } 200206f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 2003c2aa98e2SPeter Wemm 2004c2aa98e2SPeter Wemm /* stderr goes to transcript if available */ 2005c2aa98e2SPeter Wemm if (e->e_xfp != NULL) 2006c2aa98e2SPeter Wemm { 200706f25ae9SGregory Neil Shapiro int xfd; 200806f25ae9SGregory Neil Shapiro 200940266059SGregory Neil Shapiro xfd = sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL); 201006f25ae9SGregory Neil Shapiro if (xfd >= 0 && dup2(xfd, 2) < 0) 2011c2aa98e2SPeter Wemm { 2012c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stderr", argv[0]); 2013c2aa98e2SPeter Wemm _exit(EX_OSERR); 2014c2aa98e2SPeter Wemm } 2015c2aa98e2SPeter Wemm } 2016c2aa98e2SPeter Wemm 2017c2aa98e2SPeter Wemm /* this process has no right to the queue file */ 2018c2aa98e2SPeter Wemm if (e->e_lockfp != NULL) 201940266059SGregory Neil Shapiro (void) close(sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL)); 202006f25ae9SGregory Neil Shapiro 202106f25ae9SGregory Neil Shapiro /* chroot to the program mailer directory, if defined */ 202206f25ae9SGregory Neil Shapiro if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) 202306f25ae9SGregory Neil Shapiro { 202406f25ae9SGregory Neil Shapiro expand(ProgMailer->m_rootdir, buf, sizeof buf, e); 202506f25ae9SGregory Neil Shapiro if (chroot(buf) < 0) 202606f25ae9SGregory Neil Shapiro { 202706f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chroot(%s)", buf); 202806f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 202906f25ae9SGregory Neil Shapiro } 203006f25ae9SGregory Neil Shapiro if (chdir("/") < 0) 203106f25ae9SGregory Neil Shapiro { 203206f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chdir(/)"); 203306f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 203406f25ae9SGregory Neil Shapiro } 203506f25ae9SGregory Neil Shapiro } 2036c2aa98e2SPeter Wemm 2037c2aa98e2SPeter Wemm /* run as default user */ 2038c2aa98e2SPeter Wemm endpwent(); 203940266059SGregory Neil Shapiro sm_mbdb_terminate(); 2040c2aa98e2SPeter Wemm if (setgid(DefGid) < 0 && geteuid() == 0) 204106f25ae9SGregory Neil Shapiro { 2042c2aa98e2SPeter Wemm syserr("prog_open: setgid(%ld) failed", (long) DefGid); 204306f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 204406f25ae9SGregory Neil Shapiro } 2045c2aa98e2SPeter Wemm if (setuid(DefUid) < 0 && geteuid() == 0) 204606f25ae9SGregory Neil Shapiro { 2047c2aa98e2SPeter Wemm syserr("prog_open: setuid(%ld) failed", (long) DefUid); 204806f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 204906f25ae9SGregory Neil Shapiro } 2050c2aa98e2SPeter Wemm 2051c2aa98e2SPeter Wemm /* run in some directory */ 2052c2aa98e2SPeter Wemm if (ProgMailer != NULL) 2053c2aa98e2SPeter Wemm p = ProgMailer->m_execdir; 2054c2aa98e2SPeter Wemm else 2055c2aa98e2SPeter Wemm p = NULL; 2056c2aa98e2SPeter Wemm for (; p != NULL; p = q) 2057c2aa98e2SPeter Wemm { 2058c2aa98e2SPeter Wemm q = strchr(p, ':'); 2059c2aa98e2SPeter Wemm if (q != NULL) 2060c2aa98e2SPeter Wemm *q = '\0'; 2061c2aa98e2SPeter Wemm expand(p, buf, sizeof buf, e); 2062c2aa98e2SPeter Wemm if (q != NULL) 2063c2aa98e2SPeter Wemm *q++ = ':'; 2064c2aa98e2SPeter Wemm if (buf[0] != '\0' && chdir(buf) >= 0) 2065c2aa98e2SPeter Wemm break; 2066c2aa98e2SPeter Wemm } 2067c2aa98e2SPeter Wemm if (p == NULL) 2068c2aa98e2SPeter Wemm { 2069c2aa98e2SPeter Wemm /* backup directories */ 2070c2aa98e2SPeter Wemm if (chdir("/tmp") < 0) 2071c2aa98e2SPeter Wemm (void) chdir("/"); 2072c2aa98e2SPeter Wemm } 2073c2aa98e2SPeter Wemm 207440266059SGregory Neil Shapiro /* Check safety of program to be run */ 207540266059SGregory Neil Shapiro sff = SFF_ROOTOK|SFF_EXECOK; 207640266059SGregory Neil Shapiro if (!bitnset(DBS_RUNWRITABLEPROGRAM, DontBlameSendmail)) 207740266059SGregory Neil Shapiro sff |= SFF_NOGWFILES|SFF_NOWWFILES; 207840266059SGregory Neil Shapiro if (bitnset(DBS_RUNPROGRAMINUNSAFEDIRPATH, DontBlameSendmail)) 207940266059SGregory Neil Shapiro sff |= SFF_NOPATHCHECK; 208040266059SGregory Neil Shapiro else 208140266059SGregory Neil Shapiro sff |= SFF_SAFEDIRPATH; 208240266059SGregory Neil Shapiro ret = safefile(argv[0], DefUid, DefGid, DefUser, sff, 0, NULL); 208340266059SGregory Neil Shapiro if (ret != 0) 208440266059SGregory Neil Shapiro sm_syslog(LOG_INFO, e->e_id, 208540266059SGregory Neil Shapiro "Warning: prog_open: program %s unsafe: %s", 208640266059SGregory Neil Shapiro argv[0], sm_errstring(ret)); 208740266059SGregory Neil Shapiro 2088c2aa98e2SPeter Wemm /* arrange for all the files to be closed */ 2089c2aa98e2SPeter Wemm for (i = 3; i < DtableSize; i++) 2090c2aa98e2SPeter Wemm { 2091c2aa98e2SPeter Wemm register int j; 2092c2aa98e2SPeter Wemm 2093c2aa98e2SPeter Wemm if ((j = fcntl(i, F_GETFD, 0)) != -1) 209406f25ae9SGregory Neil Shapiro (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 2095c2aa98e2SPeter Wemm } 2096c2aa98e2SPeter Wemm 2097c2aa98e2SPeter Wemm /* now exec the process */ 209806f25ae9SGregory Neil Shapiro (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 2099c2aa98e2SPeter Wemm 2100c2aa98e2SPeter Wemm /* woops! failed */ 210106f25ae9SGregory Neil Shapiro save_errno = errno; 2102c2aa98e2SPeter Wemm syserr("%s: cannot exec", argv[0]); 210306f25ae9SGregory Neil Shapiro if (transienterror(save_errno)) 2104c2aa98e2SPeter Wemm _exit(EX_OSERR); 2105c2aa98e2SPeter Wemm _exit(EX_CONFIG); 2106c2aa98e2SPeter Wemm return -1; /* avoid compiler warning on IRIX */ 2107c2aa98e2SPeter Wemm } 210840266059SGregory Neil Shapiro /* 2109c2aa98e2SPeter Wemm ** GET_COLUMN -- look up a Column in a line buffer 2110c2aa98e2SPeter Wemm ** 2111c2aa98e2SPeter Wemm ** Parameters: 2112c2aa98e2SPeter Wemm ** line -- the raw text line to search. 2113c2aa98e2SPeter Wemm ** col -- the column number to fetch. 2114c2aa98e2SPeter Wemm ** delim -- the delimiter between columns. If null, 2115c2aa98e2SPeter Wemm ** use white space. 2116c2aa98e2SPeter Wemm ** buf -- the output buffer. 2117c2aa98e2SPeter Wemm ** buflen -- the length of buf. 2118c2aa98e2SPeter Wemm ** 2119c2aa98e2SPeter Wemm ** Returns: 2120c2aa98e2SPeter Wemm ** buf if successful. 2121c2aa98e2SPeter Wemm ** NULL otherwise. 2122c2aa98e2SPeter Wemm */ 2123c2aa98e2SPeter Wemm 2124c2aa98e2SPeter Wemm char * 2125c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen) 2126c2aa98e2SPeter Wemm char line[]; 2127c2aa98e2SPeter Wemm int col; 212806f25ae9SGregory Neil Shapiro int delim; 2129c2aa98e2SPeter Wemm char buf[]; 2130c2aa98e2SPeter Wemm int buflen; 2131c2aa98e2SPeter Wemm { 2132c2aa98e2SPeter Wemm char *p; 2133c2aa98e2SPeter Wemm char *begin, *end; 2134c2aa98e2SPeter Wemm int i; 2135c2aa98e2SPeter Wemm char delimbuf[4]; 2136c2aa98e2SPeter Wemm 213706f25ae9SGregory Neil Shapiro if ((char) delim == '\0') 213840266059SGregory Neil Shapiro (void) sm_strlcpy(delimbuf, "\n\t ", sizeof delimbuf); 2139c2aa98e2SPeter Wemm else 2140c2aa98e2SPeter Wemm { 214106f25ae9SGregory Neil Shapiro delimbuf[0] = (char) delim; 2142c2aa98e2SPeter Wemm delimbuf[1] = '\0'; 2143c2aa98e2SPeter Wemm } 2144c2aa98e2SPeter Wemm 2145c2aa98e2SPeter Wemm p = line; 2146c2aa98e2SPeter Wemm if (*p == '\0') 2147c2aa98e2SPeter Wemm return NULL; /* line empty */ 214806f25ae9SGregory Neil Shapiro if (*p == (char) delim && col == 0) 2149c2aa98e2SPeter Wemm return NULL; /* first column empty */ 2150c2aa98e2SPeter Wemm 2151c2aa98e2SPeter Wemm begin = line; 2152c2aa98e2SPeter Wemm 215306f25ae9SGregory Neil Shapiro if (col == 0 && (char) delim == '\0') 2154c2aa98e2SPeter Wemm { 2155c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2156c2aa98e2SPeter Wemm begin++; 2157c2aa98e2SPeter Wemm } 2158c2aa98e2SPeter Wemm 2159c2aa98e2SPeter Wemm for (i = 0; i < col; i++) 2160c2aa98e2SPeter Wemm { 2161c2aa98e2SPeter Wemm if ((begin = strpbrk(begin, delimbuf)) == NULL) 2162c2aa98e2SPeter Wemm return NULL; /* no such column */ 2163c2aa98e2SPeter Wemm begin++; 216406f25ae9SGregory Neil Shapiro if ((char) delim == '\0') 2165c2aa98e2SPeter Wemm { 2166c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2167c2aa98e2SPeter Wemm begin++; 2168c2aa98e2SPeter Wemm } 2169c2aa98e2SPeter Wemm } 2170c2aa98e2SPeter Wemm 2171c2aa98e2SPeter Wemm end = strpbrk(begin, delimbuf); 2172c2aa98e2SPeter Wemm if (end == NULL) 2173c2aa98e2SPeter Wemm i = strlen(begin); 2174c2aa98e2SPeter Wemm else 2175c2aa98e2SPeter Wemm i = end - begin; 2176c2aa98e2SPeter Wemm if (i >= buflen) 2177c2aa98e2SPeter Wemm i = buflen - 1; 217840266059SGregory Neil Shapiro (void) sm_strlcpy(buf, begin, i + 1); 2179c2aa98e2SPeter Wemm return buf; 2180c2aa98e2SPeter Wemm } 218140266059SGregory Neil Shapiro /* 2182c2aa98e2SPeter Wemm ** CLEANSTRCPY -- copy string keeping out bogus characters 2183c2aa98e2SPeter Wemm ** 2184c2aa98e2SPeter Wemm ** Parameters: 2185c2aa98e2SPeter Wemm ** t -- "to" string. 2186c2aa98e2SPeter Wemm ** f -- "from" string. 2187c2aa98e2SPeter Wemm ** l -- length of space available in "to" string. 2188c2aa98e2SPeter Wemm ** 2189c2aa98e2SPeter Wemm ** Returns: 2190c2aa98e2SPeter Wemm ** none. 2191c2aa98e2SPeter Wemm */ 2192c2aa98e2SPeter Wemm 2193c2aa98e2SPeter Wemm void 2194c2aa98e2SPeter Wemm cleanstrcpy(t, f, l) 2195c2aa98e2SPeter Wemm register char *t; 2196c2aa98e2SPeter Wemm register char *f; 2197c2aa98e2SPeter Wemm int l; 2198c2aa98e2SPeter Wemm { 2199c2aa98e2SPeter Wemm /* check for newlines and log if necessary */ 220040266059SGregory Neil Shapiro (void) denlstring(f, true, true); 2201c2aa98e2SPeter Wemm 220206f25ae9SGregory Neil Shapiro if (l <= 0) 220306f25ae9SGregory Neil Shapiro syserr("!cleanstrcpy: length == 0"); 220406f25ae9SGregory Neil Shapiro 2205c2aa98e2SPeter Wemm l--; 2206c2aa98e2SPeter Wemm while (l > 0 && *f != '\0') 2207c2aa98e2SPeter Wemm { 2208c2aa98e2SPeter Wemm if (isascii(*f) && 2209c2aa98e2SPeter Wemm (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 2210c2aa98e2SPeter Wemm { 2211c2aa98e2SPeter Wemm l--; 2212c2aa98e2SPeter Wemm *t++ = *f; 2213c2aa98e2SPeter Wemm } 2214c2aa98e2SPeter Wemm f++; 2215c2aa98e2SPeter Wemm } 2216c2aa98e2SPeter Wemm *t = '\0'; 2217c2aa98e2SPeter Wemm } 221840266059SGregory Neil Shapiro /* 2219c2aa98e2SPeter Wemm ** DENLSTRING -- convert newlines in a string to spaces 2220c2aa98e2SPeter Wemm ** 2221c2aa98e2SPeter Wemm ** Parameters: 2222c2aa98e2SPeter Wemm ** s -- the input string 2223c2aa98e2SPeter Wemm ** strict -- if set, don't permit continuation lines. 2224c2aa98e2SPeter Wemm ** logattacks -- if set, log attempted attacks. 2225c2aa98e2SPeter Wemm ** 2226c2aa98e2SPeter Wemm ** Returns: 2227c2aa98e2SPeter Wemm ** A pointer to a version of the string with newlines 2228c2aa98e2SPeter Wemm ** mapped to spaces. This should be copied. 2229c2aa98e2SPeter Wemm */ 2230c2aa98e2SPeter Wemm 2231c2aa98e2SPeter Wemm char * 2232c2aa98e2SPeter Wemm denlstring(s, strict, logattacks) 2233c2aa98e2SPeter Wemm char *s; 2234c2aa98e2SPeter Wemm bool strict; 2235c2aa98e2SPeter Wemm bool logattacks; 2236c2aa98e2SPeter Wemm { 2237c2aa98e2SPeter Wemm register char *p; 2238c2aa98e2SPeter Wemm int l; 2239c2aa98e2SPeter Wemm static char *bp = NULL; 2240c2aa98e2SPeter Wemm static int bl = 0; 2241c2aa98e2SPeter Wemm 2242c2aa98e2SPeter Wemm p = s; 2243c2aa98e2SPeter Wemm while ((p = strchr(p, '\n')) != NULL) 2244c2aa98e2SPeter Wemm if (strict || (*++p != ' ' && *p != '\t')) 2245c2aa98e2SPeter Wemm break; 2246c2aa98e2SPeter Wemm if (p == NULL) 2247c2aa98e2SPeter Wemm return s; 2248c2aa98e2SPeter Wemm 2249c2aa98e2SPeter Wemm l = strlen(s) + 1; 2250c2aa98e2SPeter Wemm if (bl < l) 2251c2aa98e2SPeter Wemm { 2252c2aa98e2SPeter Wemm /* allocate more space */ 225340266059SGregory Neil Shapiro char *nbp = sm_pmalloc_x(l); 225440266059SGregory Neil Shapiro 2255c2aa98e2SPeter Wemm if (bp != NULL) 22568774250cSGregory Neil Shapiro sm_free(bp); 225740266059SGregory Neil Shapiro bp = nbp; 2258c2aa98e2SPeter Wemm bl = l; 2259c2aa98e2SPeter Wemm } 226040266059SGregory Neil Shapiro (void) sm_strlcpy(bp, s, l); 2261c2aa98e2SPeter Wemm for (p = bp; (p = strchr(p, '\n')) != NULL; ) 2262c2aa98e2SPeter Wemm *p++ = ' '; 2263c2aa98e2SPeter Wemm 2264c2aa98e2SPeter Wemm if (logattacks) 2265c2aa98e2SPeter Wemm { 2266c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 2267c2aa98e2SPeter Wemm "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 2268c2aa98e2SPeter Wemm RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 2269c2aa98e2SPeter Wemm shortenstring(bp, MAXSHORTSTR)); 2270c2aa98e2SPeter Wemm } 2271c2aa98e2SPeter Wemm 2272c2aa98e2SPeter Wemm return bp; 2273c2aa98e2SPeter Wemm } 2274739ac4d4SGregory Neil Shapiro 2275739ac4d4SGregory Neil Shapiro /* 2276739ac4d4SGregory Neil Shapiro ** STRREPLNONPRT -- replace "unprintable" characters in a string with subst 2277739ac4d4SGregory Neil Shapiro ** 2278739ac4d4SGregory Neil Shapiro ** Parameters: 2279739ac4d4SGregory Neil Shapiro ** s -- string to manipulate (in place) 2280739ac4d4SGregory Neil Shapiro ** subst -- character to use as replacement 2281739ac4d4SGregory Neil Shapiro ** 2282739ac4d4SGregory Neil Shapiro ** Returns: 2283739ac4d4SGregory Neil Shapiro ** true iff string did not contain "unprintable" characters 2284739ac4d4SGregory Neil Shapiro */ 2285739ac4d4SGregory Neil Shapiro 2286739ac4d4SGregory Neil Shapiro bool 2287739ac4d4SGregory Neil Shapiro strreplnonprt(s, c) 2288739ac4d4SGregory Neil Shapiro char *s; 2289739ac4d4SGregory Neil Shapiro int c; 2290739ac4d4SGregory Neil Shapiro { 2291739ac4d4SGregory Neil Shapiro bool ok; 2292739ac4d4SGregory Neil Shapiro 2293739ac4d4SGregory Neil Shapiro ok = true; 2294739ac4d4SGregory Neil Shapiro if (s == NULL) 2295739ac4d4SGregory Neil Shapiro return ok; 2296739ac4d4SGregory Neil Shapiro while (*s != '\0') 2297739ac4d4SGregory Neil Shapiro { 2298739ac4d4SGregory Neil Shapiro if (!(isascii(*s) && isprint(*s))) 2299739ac4d4SGregory Neil Shapiro { 2300739ac4d4SGregory Neil Shapiro *s = c; 2301739ac4d4SGregory Neil Shapiro ok = false; 2302739ac4d4SGregory Neil Shapiro } 2303739ac4d4SGregory Neil Shapiro ++s; 2304739ac4d4SGregory Neil Shapiro } 2305739ac4d4SGregory Neil Shapiro return ok; 2306739ac4d4SGregory Neil Shapiro } 2307739ac4d4SGregory Neil Shapiro 230840266059SGregory Neil Shapiro /* 230940266059SGregory Neil Shapiro ** STR2PRT -- convert "unprintable" characters in a string to \oct 231040266059SGregory Neil Shapiro ** 231140266059SGregory Neil Shapiro ** Parameters: 231240266059SGregory Neil Shapiro ** s -- string to convert 231340266059SGregory Neil Shapiro ** 231440266059SGregory Neil Shapiro ** Returns: 231540266059SGregory Neil Shapiro ** converted string. 231640266059SGregory Neil Shapiro ** This is a static local buffer, string must be copied 231740266059SGregory Neil Shapiro ** before this function is called again! 231840266059SGregory Neil Shapiro */ 231940266059SGregory Neil Shapiro 232040266059SGregory Neil Shapiro char * 232140266059SGregory Neil Shapiro str2prt(s) 232240266059SGregory Neil Shapiro char *s; 232340266059SGregory Neil Shapiro { 232440266059SGregory Neil Shapiro int l; 232540266059SGregory Neil Shapiro char c, *h; 232640266059SGregory Neil Shapiro bool ok; 232740266059SGregory Neil Shapiro static int len = 0; 232840266059SGregory Neil Shapiro static char *buf = NULL; 232940266059SGregory Neil Shapiro 233040266059SGregory Neil Shapiro if (s == NULL) 233140266059SGregory Neil Shapiro return NULL; 233240266059SGregory Neil Shapiro ok = true; 233340266059SGregory Neil Shapiro for (h = s, l = 1; *h != '\0'; h++, l++) 233440266059SGregory Neil Shapiro { 233540266059SGregory Neil Shapiro if (*h == '\\') 233640266059SGregory Neil Shapiro { 233740266059SGregory Neil Shapiro ++l; 233840266059SGregory Neil Shapiro ok = false; 233940266059SGregory Neil Shapiro } 234040266059SGregory Neil Shapiro else if (!(isascii(*h) && isprint(*h))) 234140266059SGregory Neil Shapiro { 234240266059SGregory Neil Shapiro l += 3; 234340266059SGregory Neil Shapiro ok = false; 234440266059SGregory Neil Shapiro } 234540266059SGregory Neil Shapiro } 234640266059SGregory Neil Shapiro if (ok) 234740266059SGregory Neil Shapiro return s; 234840266059SGregory Neil Shapiro if (l > len) 234940266059SGregory Neil Shapiro { 235040266059SGregory Neil Shapiro char *nbuf = sm_pmalloc_x(l); 235140266059SGregory Neil Shapiro 235240266059SGregory Neil Shapiro if (buf != NULL) 235340266059SGregory Neil Shapiro sm_free(buf); 235440266059SGregory Neil Shapiro len = l; 235540266059SGregory Neil Shapiro buf = nbuf; 235640266059SGregory Neil Shapiro } 235740266059SGregory Neil Shapiro for (h = buf; *s != '\0' && l > 0; s++, l--) 235840266059SGregory Neil Shapiro { 235940266059SGregory Neil Shapiro c = *s; 236040266059SGregory Neil Shapiro if (isascii(c) && isprint(c) && c != '\\') 236140266059SGregory Neil Shapiro { 236240266059SGregory Neil Shapiro *h++ = c; 236340266059SGregory Neil Shapiro } 236440266059SGregory Neil Shapiro else 236540266059SGregory Neil Shapiro { 236640266059SGregory Neil Shapiro *h++ = '\\'; 236740266059SGregory Neil Shapiro --l; 236840266059SGregory Neil Shapiro switch (c) 236940266059SGregory Neil Shapiro { 237040266059SGregory Neil Shapiro case '\\': 237140266059SGregory Neil Shapiro *h++ = '\\'; 237240266059SGregory Neil Shapiro break; 237340266059SGregory Neil Shapiro case '\t': 237440266059SGregory Neil Shapiro *h++ = 't'; 237540266059SGregory Neil Shapiro break; 237640266059SGregory Neil Shapiro case '\n': 237740266059SGregory Neil Shapiro *h++ = 'n'; 237840266059SGregory Neil Shapiro break; 237940266059SGregory Neil Shapiro case '\r': 238040266059SGregory Neil Shapiro *h++ = 'r'; 238140266059SGregory Neil Shapiro break; 238240266059SGregory Neil Shapiro default: 2383323f6dcbSGregory Neil Shapiro (void) sm_snprintf(h, l, "%03o", 2384323f6dcbSGregory Neil Shapiro (unsigned int)((unsigned char) c)); 238540266059SGregory Neil Shapiro 238640266059SGregory Neil Shapiro /* 238740266059SGregory Neil Shapiro ** XXX since l is unsigned this may 238840266059SGregory Neil Shapiro ** wrap around if the calculation is screwed 238940266059SGregory Neil Shapiro ** up... 239040266059SGregory Neil Shapiro */ 239140266059SGregory Neil Shapiro 239240266059SGregory Neil Shapiro l -= 2; 239340266059SGregory Neil Shapiro h += 3; 239440266059SGregory Neil Shapiro break; 239540266059SGregory Neil Shapiro } 239640266059SGregory Neil Shapiro } 239740266059SGregory Neil Shapiro } 239840266059SGregory Neil Shapiro *h = '\0'; 239940266059SGregory Neil Shapiro buf[len - 1] = '\0'; 240040266059SGregory Neil Shapiro return buf; 240140266059SGregory Neil Shapiro } 240240266059SGregory Neil Shapiro /* 2403c2aa98e2SPeter Wemm ** PATH_IS_DIR -- check to see if file exists and is a directory. 2404c2aa98e2SPeter Wemm ** 2405c2aa98e2SPeter Wemm ** There are some additional checks for security violations in 2406c2aa98e2SPeter Wemm ** here. This routine is intended to be used for the host status 2407c2aa98e2SPeter Wemm ** support. 2408c2aa98e2SPeter Wemm ** 2409c2aa98e2SPeter Wemm ** Parameters: 2410c2aa98e2SPeter Wemm ** pathname -- pathname to check for directory-ness. 2411c2aa98e2SPeter Wemm ** createflag -- if set, create directory if needed. 2412c2aa98e2SPeter Wemm ** 2413c2aa98e2SPeter Wemm ** Returns: 241440266059SGregory Neil Shapiro ** true -- if the indicated pathname is a directory 241540266059SGregory Neil Shapiro ** false -- otherwise 2416c2aa98e2SPeter Wemm */ 2417c2aa98e2SPeter Wemm 2418a7ec597cSGregory Neil Shapiro bool 2419c2aa98e2SPeter Wemm path_is_dir(pathname, createflag) 2420c2aa98e2SPeter Wemm char *pathname; 2421c2aa98e2SPeter Wemm bool createflag; 2422c2aa98e2SPeter Wemm { 2423c2aa98e2SPeter Wemm struct stat statbuf; 2424c2aa98e2SPeter Wemm 2425c2aa98e2SPeter Wemm #if HASLSTAT 2426c2aa98e2SPeter Wemm if (lstat(pathname, &statbuf) < 0) 242706f25ae9SGregory Neil Shapiro #else /* HASLSTAT */ 2428c2aa98e2SPeter Wemm if (stat(pathname, &statbuf) < 0) 242906f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */ 2430c2aa98e2SPeter Wemm { 2431c2aa98e2SPeter Wemm if (errno != ENOENT || !createflag) 243240266059SGregory Neil Shapiro return false; 2433c2aa98e2SPeter Wemm if (mkdir(pathname, 0755) < 0) 243440266059SGregory Neil Shapiro return false; 243540266059SGregory Neil Shapiro return true; 2436c2aa98e2SPeter Wemm } 2437c2aa98e2SPeter Wemm if (!S_ISDIR(statbuf.st_mode)) 2438c2aa98e2SPeter Wemm { 2439c2aa98e2SPeter Wemm errno = ENOTDIR; 244040266059SGregory Neil Shapiro return false; 2441c2aa98e2SPeter Wemm } 2442c2aa98e2SPeter Wemm 2443c2aa98e2SPeter Wemm /* security: don't allow writable directories */ 2444c2aa98e2SPeter Wemm if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 2445c2aa98e2SPeter Wemm { 2446c2aa98e2SPeter Wemm errno = EACCES; 244740266059SGregory Neil Shapiro return false; 2448c2aa98e2SPeter Wemm } 244940266059SGregory Neil Shapiro return true; 2450c2aa98e2SPeter Wemm } 245140266059SGregory Neil Shapiro /* 2452c2aa98e2SPeter Wemm ** PROC_LIST_ADD -- add process id to list of our children 2453c2aa98e2SPeter Wemm ** 2454c2aa98e2SPeter Wemm ** Parameters: 2455c2aa98e2SPeter Wemm ** pid -- pid to add to list. 245606f25ae9SGregory Neil Shapiro ** task -- task of pid. 245706f25ae9SGregory Neil Shapiro ** type -- type of process. 245840266059SGregory Neil Shapiro ** count -- number of processes. 245940266059SGregory Neil Shapiro ** other -- other information for this type. 2460c2aa98e2SPeter Wemm ** 2461c2aa98e2SPeter Wemm ** Returns: 2462c2aa98e2SPeter Wemm ** none 246340266059SGregory Neil Shapiro ** 246440266059SGregory Neil Shapiro ** Side Effects: 246540266059SGregory Neil Shapiro ** May increase CurChildren. May grow ProcList. 2466c2aa98e2SPeter Wemm */ 2467c2aa98e2SPeter Wemm 246840266059SGregory Neil Shapiro typedef struct procs PROCS_T; 246940266059SGregory Neil Shapiro 247040266059SGregory Neil Shapiro struct procs 247140266059SGregory Neil Shapiro { 247240266059SGregory Neil Shapiro pid_t proc_pid; 247340266059SGregory Neil Shapiro char *proc_task; 247440266059SGregory Neil Shapiro int proc_type; 247540266059SGregory Neil Shapiro int proc_count; 247640266059SGregory Neil Shapiro int proc_other; 247740266059SGregory Neil Shapiro }; 247840266059SGregory Neil Shapiro 247940266059SGregory Neil Shapiro static PROCS_T *volatile ProcListVec = NULL; 2480c2aa98e2SPeter Wemm static int ProcListSize = 0; 2481c2aa98e2SPeter Wemm 2482c2aa98e2SPeter Wemm void 248340266059SGregory Neil Shapiro proc_list_add(pid, task, type, count, other) 2484c2aa98e2SPeter Wemm pid_t pid; 2485065a643dSPeter Wemm char *task; 248606f25ae9SGregory Neil Shapiro int type; 248740266059SGregory Neil Shapiro int count; 248840266059SGregory Neil Shapiro int other; 2489c2aa98e2SPeter Wemm { 2490c2aa98e2SPeter Wemm int i; 2491c2aa98e2SPeter Wemm 2492c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2493c2aa98e2SPeter Wemm { 2494065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2495c2aa98e2SPeter Wemm break; 2496c2aa98e2SPeter Wemm } 2497c2aa98e2SPeter Wemm if (i >= ProcListSize) 2498c2aa98e2SPeter Wemm { 2499c2aa98e2SPeter Wemm /* probe the existing vector to avoid growing infinitely */ 2500c2aa98e2SPeter Wemm proc_list_probe(); 2501c2aa98e2SPeter Wemm 2502c2aa98e2SPeter Wemm /* now scan again */ 2503c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2504c2aa98e2SPeter Wemm { 2505065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2506c2aa98e2SPeter Wemm break; 2507c2aa98e2SPeter Wemm } 2508c2aa98e2SPeter Wemm } 2509c2aa98e2SPeter Wemm if (i >= ProcListSize) 2510c2aa98e2SPeter Wemm { 2511c2aa98e2SPeter Wemm /* grow process list */ 251240266059SGregory Neil Shapiro PROCS_T *npv; 2513c2aa98e2SPeter Wemm 251440266059SGregory Neil Shapiro SM_ASSERT(ProcListSize < INT_MAX - PROC_LIST_SEG); 251540266059SGregory Neil Shapiro npv = (PROCS_T *) sm_pmalloc_x((sizeof *npv) * 251606f25ae9SGregory Neil Shapiro (ProcListSize + PROC_LIST_SEG)); 2517c2aa98e2SPeter Wemm if (ProcListSize > 0) 2518c2aa98e2SPeter Wemm { 251906f25ae9SGregory Neil Shapiro memmove(npv, ProcListVec, 252040266059SGregory Neil Shapiro ProcListSize * sizeof (PROCS_T)); 25218774250cSGregory Neil Shapiro sm_free(ProcListVec); 2522c2aa98e2SPeter Wemm } 252340266059SGregory Neil Shapiro 252440266059SGregory Neil Shapiro /* XXX just use memset() to initialize this part? */ 2525c2aa98e2SPeter Wemm for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 2526065a643dSPeter Wemm { 2527065a643dSPeter Wemm npv[i].proc_pid = NO_PID; 2528065a643dSPeter Wemm npv[i].proc_task = NULL; 252906f25ae9SGregory Neil Shapiro npv[i].proc_type = PROC_NONE; 2530065a643dSPeter Wemm } 2531c2aa98e2SPeter Wemm i = ProcListSize; 2532c2aa98e2SPeter Wemm ProcListSize += PROC_LIST_SEG; 2533c2aa98e2SPeter Wemm ProcListVec = npv; 2534c2aa98e2SPeter Wemm } 2535065a643dSPeter Wemm ProcListVec[i].proc_pid = pid; 253640266059SGregory Neil Shapiro PSTRSET(ProcListVec[i].proc_task, task); 253706f25ae9SGregory Neil Shapiro ProcListVec[i].proc_type = type; 253840266059SGregory Neil Shapiro ProcListVec[i].proc_count = count; 253940266059SGregory Neil Shapiro ProcListVec[i].proc_other = other; 2540065a643dSPeter Wemm 2541065a643dSPeter Wemm /* if process adding itself, it's not a child */ 254240266059SGregory Neil Shapiro if (pid != CurrentPid) 254340266059SGregory Neil Shapiro { 254440266059SGregory Neil Shapiro SM_ASSERT(CurChildren < INT_MAX); 2545c2aa98e2SPeter Wemm CurChildren++; 2546c2aa98e2SPeter Wemm } 254740266059SGregory Neil Shapiro } 254840266059SGregory Neil Shapiro /* 2549065a643dSPeter Wemm ** PROC_LIST_SET -- set pid task in process list 2550065a643dSPeter Wemm ** 2551065a643dSPeter Wemm ** Parameters: 2552065a643dSPeter Wemm ** pid -- pid to set 2553065a643dSPeter Wemm ** task -- task of pid 2554065a643dSPeter Wemm ** 2555065a643dSPeter Wemm ** Returns: 2556065a643dSPeter Wemm ** none. 2557065a643dSPeter Wemm */ 2558065a643dSPeter Wemm 2559065a643dSPeter Wemm void 2560065a643dSPeter Wemm proc_list_set(pid, task) 2561065a643dSPeter Wemm pid_t pid; 2562065a643dSPeter Wemm char *task; 2563065a643dSPeter Wemm { 2564065a643dSPeter Wemm int i; 2565065a643dSPeter Wemm 2566065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2567065a643dSPeter Wemm { 2568065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2569065a643dSPeter Wemm { 257040266059SGregory Neil Shapiro PSTRSET(ProcListVec[i].proc_task, task); 2571065a643dSPeter Wemm break; 2572065a643dSPeter Wemm } 2573065a643dSPeter Wemm } 2574065a643dSPeter Wemm } 257540266059SGregory Neil Shapiro /* 2576c2aa98e2SPeter Wemm ** PROC_LIST_DROP -- drop pid from process list 2577c2aa98e2SPeter Wemm ** 2578c2aa98e2SPeter Wemm ** Parameters: 2579c2aa98e2SPeter Wemm ** pid -- pid to drop 258040266059SGregory Neil Shapiro ** st -- process status 258140266059SGregory Neil Shapiro ** other -- storage for proc_other (return). 2582c2aa98e2SPeter Wemm ** 2583c2aa98e2SPeter Wemm ** Returns: 258440266059SGregory Neil Shapiro ** none. 258540266059SGregory Neil Shapiro ** 258640266059SGregory Neil Shapiro ** Side Effects: 258740266059SGregory Neil Shapiro ** May decrease CurChildren, CurRunners, or 258840266059SGregory Neil Shapiro ** set RestartRequest or ShutdownRequest. 25898774250cSGregory Neil Shapiro ** 25908774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 25918774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 25928774250cSGregory Neil Shapiro ** DOING. 2593c2aa98e2SPeter Wemm */ 2594c2aa98e2SPeter Wemm 259540266059SGregory Neil Shapiro void 259640266059SGregory Neil Shapiro proc_list_drop(pid, st, other) 2597c2aa98e2SPeter Wemm pid_t pid; 259840266059SGregory Neil Shapiro int st; 259940266059SGregory Neil Shapiro int *other; 2600c2aa98e2SPeter Wemm { 2601c2aa98e2SPeter Wemm int i; 260206f25ae9SGregory Neil Shapiro int type = PROC_NONE; 2603c2aa98e2SPeter Wemm 2604c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2605c2aa98e2SPeter Wemm { 2606065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2607c2aa98e2SPeter Wemm { 2608065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 260906f25ae9SGregory Neil Shapiro type = ProcListVec[i].proc_type; 261040266059SGregory Neil Shapiro if (other != NULL) 261140266059SGregory Neil Shapiro *other = ProcListVec[i].proc_other; 2612c2aa98e2SPeter Wemm break; 2613c2aa98e2SPeter Wemm } 2614c2aa98e2SPeter Wemm } 2615c2aa98e2SPeter Wemm if (CurChildren > 0) 2616c2aa98e2SPeter Wemm CurChildren--; 261706f25ae9SGregory Neil Shapiro 261806f25ae9SGregory Neil Shapiro 261940266059SGregory Neil Shapiro if (type == PROC_CONTROL && WIFEXITED(st)) 262040266059SGregory Neil Shapiro { 262140266059SGregory Neil Shapiro /* if so, see if we need to restart or shutdown */ 262240266059SGregory Neil Shapiro if (WEXITSTATUS(st) == EX_RESTART) 262340266059SGregory Neil Shapiro RestartRequest = "control socket"; 262440266059SGregory Neil Shapiro else if (WEXITSTATUS(st) == EX_SHUTDOWN) 262540266059SGregory Neil Shapiro ShutdownRequest = "control socket"; 2626c2aa98e2SPeter Wemm } 262740266059SGregory Neil Shapiro else if (type == PROC_QUEUE_CHILD && !WIFSTOPPED(st) && 262840266059SGregory Neil Shapiro ProcListVec[i].proc_other > -1) 262940266059SGregory Neil Shapiro { 263040266059SGregory Neil Shapiro /* restart this persistent runner */ 263140266059SGregory Neil Shapiro mark_work_group_restart(ProcListVec[i].proc_other, st); 263240266059SGregory Neil Shapiro } 263340266059SGregory Neil Shapiro else if (type == PROC_QUEUE) 263440266059SGregory Neil Shapiro CurRunners -= ProcListVec[i].proc_count; 263540266059SGregory Neil Shapiro } 263640266059SGregory Neil Shapiro /* 2637c2aa98e2SPeter Wemm ** PROC_LIST_CLEAR -- clear the process list 2638c2aa98e2SPeter Wemm ** 2639c2aa98e2SPeter Wemm ** Parameters: 2640c2aa98e2SPeter Wemm ** none. 2641c2aa98e2SPeter Wemm ** 2642c2aa98e2SPeter Wemm ** Returns: 2643c2aa98e2SPeter Wemm ** none. 264440266059SGregory Neil Shapiro ** 264540266059SGregory Neil Shapiro ** Side Effects: 264640266059SGregory Neil Shapiro ** Sets CurChildren to zero. 2647c2aa98e2SPeter Wemm */ 2648c2aa98e2SPeter Wemm 2649c2aa98e2SPeter Wemm void 2650c2aa98e2SPeter Wemm proc_list_clear() 2651c2aa98e2SPeter Wemm { 2652c2aa98e2SPeter Wemm int i; 2653c2aa98e2SPeter Wemm 2654065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2655065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2656065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2657c2aa98e2SPeter Wemm CurChildren = 0; 2658c2aa98e2SPeter Wemm } 265940266059SGregory Neil Shapiro /* 2660c2aa98e2SPeter Wemm ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 2661c2aa98e2SPeter Wemm ** 2662c2aa98e2SPeter Wemm ** Parameters: 2663c2aa98e2SPeter Wemm ** none 2664c2aa98e2SPeter Wemm ** 2665c2aa98e2SPeter Wemm ** Returns: 2666c2aa98e2SPeter Wemm ** none 266740266059SGregory Neil Shapiro ** 266840266059SGregory Neil Shapiro ** Side Effects: 266940266059SGregory Neil Shapiro ** May decrease CurChildren. 2670c2aa98e2SPeter Wemm */ 2671c2aa98e2SPeter Wemm 2672c2aa98e2SPeter Wemm void 2673c2aa98e2SPeter Wemm proc_list_probe() 2674c2aa98e2SPeter Wemm { 2675c2aa98e2SPeter Wemm int i; 2676c2aa98e2SPeter Wemm 2677065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2678065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2679c2aa98e2SPeter Wemm { 2680065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2681c2aa98e2SPeter Wemm continue; 2682065a643dSPeter Wemm if (kill(ProcListVec[i].proc_pid, 0) < 0) 2683c2aa98e2SPeter Wemm { 2684c2aa98e2SPeter Wemm if (LogLevel > 3) 2685c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 2686c2aa98e2SPeter Wemm "proc_list_probe: lost pid %d", 2687065a643dSPeter Wemm (int) ProcListVec[i].proc_pid); 2688065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 268940266059SGregory Neil Shapiro SM_FREE_CLR(ProcListVec[i].proc_task); 2690c2aa98e2SPeter Wemm CurChildren--; 2691c2aa98e2SPeter Wemm } 2692c2aa98e2SPeter Wemm } 2693c2aa98e2SPeter Wemm if (CurChildren < 0) 2694c2aa98e2SPeter Wemm CurChildren = 0; 2695c2aa98e2SPeter Wemm } 269640266059SGregory Neil Shapiro 269740266059SGregory Neil Shapiro /* 2698065a643dSPeter Wemm ** PROC_LIST_DISPLAY -- display the process list 2699065a643dSPeter Wemm ** 2700065a643dSPeter Wemm ** Parameters: 2701065a643dSPeter Wemm ** out -- output file pointer 270240266059SGregory Neil Shapiro ** prefix -- string to output in front of each line. 2703065a643dSPeter Wemm ** 2704065a643dSPeter Wemm ** Returns: 2705065a643dSPeter Wemm ** none. 2706065a643dSPeter Wemm */ 2707065a643dSPeter Wemm 2708065a643dSPeter Wemm void 270940266059SGregory Neil Shapiro proc_list_display(out, prefix) 271040266059SGregory Neil Shapiro SM_FILE_T *out; 271140266059SGregory Neil Shapiro char *prefix; 2712065a643dSPeter Wemm { 2713065a643dSPeter Wemm int i; 2714065a643dSPeter Wemm 2715065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2716065a643dSPeter Wemm { 2717065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2718065a643dSPeter Wemm continue; 2719065a643dSPeter Wemm 272040266059SGregory Neil Shapiro (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "%s%d %s%s\n", 272140266059SGregory Neil Shapiro prefix, 272240266059SGregory Neil Shapiro (int) ProcListVec[i].proc_pid, 2723065a643dSPeter Wemm ProcListVec[i].proc_task != NULL ? 2724065a643dSPeter Wemm ProcListVec[i].proc_task : "(unknown)", 2725065a643dSPeter Wemm (OpMode == MD_SMTP || 2726065a643dSPeter Wemm OpMode == MD_DAEMON || 2727065a643dSPeter Wemm OpMode == MD_ARPAFTP) ? "\r" : ""); 2728065a643dSPeter Wemm } 2729065a643dSPeter Wemm } 273040266059SGregory Neil Shapiro 273140266059SGregory Neil Shapiro /* 273240266059SGregory Neil Shapiro ** PROC_LIST_SIGNAL -- send a signal to a type of process in the list 273313058a91SGregory Neil Shapiro ** 273413058a91SGregory Neil Shapiro ** Parameters: 273540266059SGregory Neil Shapiro ** type -- type of process to signal 273640266059SGregory Neil Shapiro ** signal -- the type of signal to send 273713058a91SGregory Neil Shapiro ** 273840266059SGregory Neil Shapiro ** Results: 273940266059SGregory Neil Shapiro ** none. 2740c2aa98e2SPeter Wemm ** 274140266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 274240266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 274340266059SGregory Neil Shapiro ** DOING. 2744c2aa98e2SPeter Wemm */ 2745c2aa98e2SPeter Wemm 274640266059SGregory Neil Shapiro void 274740266059SGregory Neil Shapiro proc_list_signal(type, signal) 274840266059SGregory Neil Shapiro int type; 274940266059SGregory Neil Shapiro int signal; 2750c2aa98e2SPeter Wemm { 275140266059SGregory Neil Shapiro int chldwasblocked; 275240266059SGregory Neil Shapiro int alrmwasblocked; 275340266059SGregory Neil Shapiro int i; 275440266059SGregory Neil Shapiro pid_t mypid = getpid(); 2755c2aa98e2SPeter Wemm 275640266059SGregory Neil Shapiro /* block these signals so that we may signal cleanly */ 275740266059SGregory Neil Shapiro chldwasblocked = sm_blocksignal(SIGCHLD); 275840266059SGregory Neil Shapiro alrmwasblocked = sm_blocksignal(SIGALRM); 275940266059SGregory Neil Shapiro 276040266059SGregory Neil Shapiro /* Find all processes of type and send signal */ 276140266059SGregory Neil Shapiro for (i = 0; i < ProcListSize; i++) 276240266059SGregory Neil Shapiro { 276340266059SGregory Neil Shapiro if (ProcListVec[i].proc_pid == NO_PID || 276440266059SGregory Neil Shapiro ProcListVec[i].proc_pid == mypid) 276540266059SGregory Neil Shapiro continue; 276640266059SGregory Neil Shapiro if (ProcListVec[i].proc_type != type) 276740266059SGregory Neil Shapiro continue; 276840266059SGregory Neil Shapiro (void) kill(ProcListVec[i].proc_pid, signal); 2769c2aa98e2SPeter Wemm } 2770c2aa98e2SPeter Wemm 277140266059SGregory Neil Shapiro /* restore the signals */ 277240266059SGregory Neil Shapiro if (alrmwasblocked == 0) 277340266059SGregory Neil Shapiro (void) sm_releasesignal(SIGALRM); 277440266059SGregory Neil Shapiro if (chldwasblocked == 0) 277540266059SGregory Neil Shapiro (void) sm_releasesignal(SIGCHLD); 2776c2aa98e2SPeter Wemm } 2777