1c2aa98e2SPeter Wemm /* 24e4196cbSGregory Neil Shapiro * Copyright (c) 1998-2006 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 16af9557fdSGregory Neil Shapiro SM_RCSID("@(#)$Id: util.c,v 8.394 2006/05/03 23:55:29 ca Exp $") 1740266059SGregory Neil Shapiro 18c2aa98e2SPeter Wemm #include <sysexits.h> 1940266059SGregory Neil Shapiro #include <sm/xtrap.h> 2006f25ae9SGregory Neil Shapiro 2140266059SGregory Neil Shapiro /* 22e92d3f3fSGregory Neil Shapiro ** NEWSTR -- Create a copy of a C string 23e92d3f3fSGregory Neil Shapiro ** 24e92d3f3fSGregory Neil Shapiro ** Parameters: 25e92d3f3fSGregory Neil Shapiro ** s -- the string to copy. 26e92d3f3fSGregory Neil Shapiro ** 27e92d3f3fSGregory Neil Shapiro ** Returns: 28e92d3f3fSGregory Neil Shapiro ** pointer to newly allocated string. 29e92d3f3fSGregory Neil Shapiro */ 30e92d3f3fSGregory Neil Shapiro 31e92d3f3fSGregory Neil Shapiro char * 32e92d3f3fSGregory Neil Shapiro newstr(s) 33e92d3f3fSGregory Neil Shapiro const char *s; 34e92d3f3fSGregory Neil Shapiro { 35e92d3f3fSGregory Neil Shapiro size_t l; 36e92d3f3fSGregory Neil Shapiro char *n; 37e92d3f3fSGregory Neil Shapiro 38e92d3f3fSGregory Neil Shapiro l = strlen(s); 39e92d3f3fSGregory Neil Shapiro SM_ASSERT(l + 1 > l); 40e92d3f3fSGregory Neil Shapiro n = xalloc(l + 1); 41e92d3f3fSGregory Neil Shapiro sm_strlcpy(n, s, l + 1); 42e92d3f3fSGregory Neil Shapiro return n; 43e92d3f3fSGregory Neil Shapiro } 44e92d3f3fSGregory Neil Shapiro 45e92d3f3fSGregory Neil Shapiro /* 46c2aa98e2SPeter Wemm ** ADDQUOTES -- Adds quotes & quote bits to a string. 47c2aa98e2SPeter Wemm ** 4840266059SGregory Neil Shapiro ** Runs through a string and adds backslashes and quote bits. 49c2aa98e2SPeter Wemm ** 50c2aa98e2SPeter Wemm ** Parameters: 51c2aa98e2SPeter Wemm ** s -- the string to modify. 5240266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate result 53c2aa98e2SPeter Wemm ** 54c2aa98e2SPeter Wemm ** Returns: 55c2aa98e2SPeter Wemm ** pointer to quoted string. 56c2aa98e2SPeter Wemm */ 57c2aa98e2SPeter Wemm 58c2aa98e2SPeter Wemm char * 5940266059SGregory Neil Shapiro addquotes(s, rpool) 60c2aa98e2SPeter Wemm char *s; 6140266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 62c2aa98e2SPeter Wemm { 63c2aa98e2SPeter Wemm int len = 0; 64c2aa98e2SPeter Wemm char c; 65c2aa98e2SPeter Wemm char *p = s, *q, *r; 66c2aa98e2SPeter Wemm 67c2aa98e2SPeter Wemm if (s == NULL) 68c2aa98e2SPeter Wemm return NULL; 69c2aa98e2SPeter Wemm 70c2aa98e2SPeter Wemm /* Find length of quoted string */ 71c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 72c2aa98e2SPeter Wemm { 73c2aa98e2SPeter Wemm len++; 74c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 75c2aa98e2SPeter Wemm len++; 76c2aa98e2SPeter Wemm } 77c2aa98e2SPeter Wemm 7840266059SGregory Neil Shapiro q = r = sm_rpool_malloc_x(rpool, len + 3); 79c2aa98e2SPeter Wemm p = s; 80c2aa98e2SPeter Wemm 81c2aa98e2SPeter Wemm /* add leading quote */ 82c2aa98e2SPeter Wemm *q++ = '"'; 83c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 84c2aa98e2SPeter Wemm { 85c2aa98e2SPeter Wemm /* quote \ or " */ 86c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 87c2aa98e2SPeter Wemm *q++ = '\\'; 88c2aa98e2SPeter Wemm *q++ = c; 89c2aa98e2SPeter Wemm } 90c2aa98e2SPeter Wemm *q++ = '"'; 91c2aa98e2SPeter Wemm *q = '\0'; 92c2aa98e2SPeter Wemm return r; 93c2aa98e2SPeter Wemm } 9413bd1963SGregory Neil Shapiro 9513bd1963SGregory Neil Shapiro /* 96b6bacd31SGregory Neil Shapiro ** STRIPBACKSLASH -- Strip all leading backslashes from a string, provided 97b6bacd31SGregory Neil Shapiro ** the following character is alpha-numerical. 9813bd1963SGregory Neil Shapiro ** 9913bd1963SGregory Neil Shapiro ** This is done in place. 10013bd1963SGregory Neil Shapiro ** 10113bd1963SGregory Neil Shapiro ** Parameters: 10213bd1963SGregory Neil Shapiro ** s -- the string to strip. 10313bd1963SGregory Neil Shapiro ** 10413bd1963SGregory Neil Shapiro ** Returns: 10513bd1963SGregory Neil Shapiro ** none. 10613bd1963SGregory Neil Shapiro */ 10713bd1963SGregory Neil Shapiro 10813bd1963SGregory Neil Shapiro void 10913bd1963SGregory Neil Shapiro stripbackslash(s) 11013bd1963SGregory Neil Shapiro char *s; 11113bd1963SGregory Neil Shapiro { 11213bd1963SGregory Neil Shapiro char *p, *q, c; 11313bd1963SGregory Neil Shapiro 11413bd1963SGregory Neil Shapiro if (s == NULL || *s == '\0') 11513bd1963SGregory Neil Shapiro return; 11613bd1963SGregory Neil Shapiro p = q = s; 11713bd1963SGregory Neil Shapiro while (*p == '\\' && (p[1] == '\\' || (isascii(p[1]) && isalnum(p[1])))) 11813bd1963SGregory Neil Shapiro p++; 11913bd1963SGregory Neil Shapiro do 12013bd1963SGregory Neil Shapiro { 12113bd1963SGregory Neil Shapiro c = *q++ = *p++; 12213bd1963SGregory Neil Shapiro } while (c != '\0'); 12313bd1963SGregory Neil Shapiro } 12413bd1963SGregory Neil Shapiro 12540266059SGregory Neil Shapiro /* 126c2aa98e2SPeter Wemm ** RFC822_STRING -- Checks string for proper RFC822 string quoting. 127c2aa98e2SPeter Wemm ** 128c2aa98e2SPeter Wemm ** Runs through a string and verifies RFC822 special characters 129c2aa98e2SPeter Wemm ** are only found inside comments, quoted strings, or backslash 130c2aa98e2SPeter Wemm ** escaped. Also verified balanced quotes and parenthesis. 131c2aa98e2SPeter Wemm ** 132c2aa98e2SPeter Wemm ** Parameters: 133c2aa98e2SPeter Wemm ** s -- the string to modify. 134c2aa98e2SPeter Wemm ** 135c2aa98e2SPeter Wemm ** Returns: 13640266059SGregory Neil Shapiro ** true iff the string is RFC822 compliant, false otherwise. 137c2aa98e2SPeter Wemm */ 138c2aa98e2SPeter Wemm 139c2aa98e2SPeter Wemm bool 140c2aa98e2SPeter Wemm rfc822_string(s) 141c2aa98e2SPeter Wemm char *s; 142c2aa98e2SPeter Wemm { 14340266059SGregory Neil Shapiro bool quoted = false; 144c2aa98e2SPeter Wemm int commentlev = 0; 145c2aa98e2SPeter Wemm char *c = s; 146c2aa98e2SPeter Wemm 147c2aa98e2SPeter Wemm if (s == NULL) 14840266059SGregory Neil Shapiro return false; 149c2aa98e2SPeter Wemm 150c2aa98e2SPeter Wemm while (*c != '\0') 151c2aa98e2SPeter Wemm { 152c2aa98e2SPeter Wemm /* escaped character */ 153c2aa98e2SPeter Wemm if (*c == '\\') 154c2aa98e2SPeter Wemm { 155c2aa98e2SPeter Wemm c++; 156c2aa98e2SPeter Wemm if (*c == '\0') 15740266059SGregory Neil Shapiro return false; 158c2aa98e2SPeter Wemm } 159c2aa98e2SPeter Wemm else if (commentlev == 0 && *c == '"') 160c2aa98e2SPeter Wemm quoted = !quoted; 161c2aa98e2SPeter Wemm else if (!quoted) 162c2aa98e2SPeter Wemm { 163c2aa98e2SPeter Wemm if (*c == ')') 164c2aa98e2SPeter Wemm { 165c2aa98e2SPeter Wemm /* unbalanced ')' */ 166c2aa98e2SPeter Wemm if (commentlev == 0) 16740266059SGregory Neil Shapiro return false; 168c2aa98e2SPeter Wemm else 169c2aa98e2SPeter Wemm commentlev--; 170c2aa98e2SPeter Wemm } 171c2aa98e2SPeter Wemm else if (*c == '(') 172c2aa98e2SPeter Wemm commentlev++; 173c2aa98e2SPeter Wemm else if (commentlev == 0 && 174c2aa98e2SPeter Wemm strchr(MustQuoteChars, *c) != NULL) 17540266059SGregory Neil Shapiro return false; 176c2aa98e2SPeter Wemm } 177c2aa98e2SPeter Wemm c++; 178c2aa98e2SPeter Wemm } 17940266059SGregory Neil Shapiro 180c2aa98e2SPeter Wemm /* unbalanced '"' or '(' */ 18140266059SGregory Neil Shapiro return !quoted && commentlev == 0; 182c2aa98e2SPeter Wemm } 18340266059SGregory Neil Shapiro /* 184065a643dSPeter Wemm ** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string 185065a643dSPeter Wemm ** 18606f25ae9SGregory Neil Shapiro ** Arbitrarily shorten (in place) an RFC822 string and rebalance 187065a643dSPeter Wemm ** comments and quotes. 188065a643dSPeter Wemm ** 189065a643dSPeter Wemm ** Parameters: 190065a643dSPeter Wemm ** string -- the string to shorten 191065a643dSPeter Wemm ** length -- the maximum size, 0 if no maximum 192065a643dSPeter Wemm ** 193065a643dSPeter Wemm ** Returns: 19440266059SGregory Neil Shapiro ** true if string is changed, false otherwise 195065a643dSPeter Wemm ** 196065a643dSPeter Wemm ** Side Effects: 197065a643dSPeter Wemm ** Changes string in place, possibly resulting 198065a643dSPeter Wemm ** in a shorter string. 199065a643dSPeter Wemm */ 200065a643dSPeter Wemm 201065a643dSPeter Wemm bool 202065a643dSPeter Wemm shorten_rfc822_string(string, length) 203065a643dSPeter Wemm char *string; 204065a643dSPeter Wemm size_t length; 205065a643dSPeter Wemm { 20640266059SGregory Neil Shapiro bool backslash = false; 20740266059SGregory Neil Shapiro bool modified = false; 20840266059SGregory Neil Shapiro bool quoted = false; 209065a643dSPeter Wemm size_t slen; 210065a643dSPeter Wemm int parencount = 0; 211065a643dSPeter Wemm char *ptr = string; 212065a643dSPeter Wemm 213065a643dSPeter Wemm /* 214065a643dSPeter Wemm ** If have to rebalance an already short enough string, 215065a643dSPeter Wemm ** need to do it within allocated space. 216065a643dSPeter Wemm */ 217193538b7SGregory Neil Shapiro 218065a643dSPeter Wemm slen = strlen(string); 219065a643dSPeter Wemm if (length == 0 || slen < length) 220065a643dSPeter Wemm length = slen; 221065a643dSPeter Wemm 222065a643dSPeter Wemm while (*ptr != '\0') 223065a643dSPeter Wemm { 224065a643dSPeter Wemm if (backslash) 225065a643dSPeter Wemm { 22640266059SGregory Neil Shapiro backslash = false; 227065a643dSPeter Wemm goto increment; 228065a643dSPeter Wemm } 229065a643dSPeter Wemm 230065a643dSPeter Wemm if (*ptr == '\\') 23140266059SGregory Neil Shapiro backslash = true; 232065a643dSPeter Wemm else if (*ptr == '(') 233065a643dSPeter Wemm { 234065a643dSPeter Wemm if (!quoted) 235065a643dSPeter Wemm parencount++; 236065a643dSPeter Wemm } 237065a643dSPeter Wemm else if (*ptr == ')') 238065a643dSPeter Wemm { 239065a643dSPeter Wemm if (--parencount < 0) 240065a643dSPeter Wemm parencount = 0; 241065a643dSPeter Wemm } 242065a643dSPeter Wemm 243065a643dSPeter Wemm /* Inside a comment, quotes don't matter */ 244065a643dSPeter Wemm if (parencount <= 0 && *ptr == '"') 245065a643dSPeter Wemm quoted = !quoted; 246065a643dSPeter Wemm 247065a643dSPeter Wemm increment: 248065a643dSPeter Wemm /* Check for sufficient space for next character */ 24906f25ae9SGregory Neil Shapiro if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) + 250065a643dSPeter Wemm parencount + 251065a643dSPeter Wemm (quoted ? 1 : 0))) 252065a643dSPeter Wemm { 253065a643dSPeter Wemm /* Not enough, backtrack */ 254065a643dSPeter Wemm if (*ptr == '\\') 25540266059SGregory Neil Shapiro backslash = false; 256065a643dSPeter Wemm else if (*ptr == '(' && !quoted) 257065a643dSPeter Wemm parencount--; 258065a643dSPeter Wemm else if (*ptr == '"' && parencount == 0) 25940266059SGregory Neil Shapiro quoted = false; 260065a643dSPeter Wemm break; 261065a643dSPeter Wemm } 262065a643dSPeter Wemm ptr++; 263065a643dSPeter Wemm } 264065a643dSPeter Wemm 265065a643dSPeter Wemm /* Rebalance */ 266065a643dSPeter Wemm while (parencount-- > 0) 267065a643dSPeter Wemm { 268065a643dSPeter Wemm if (*ptr != ')') 269065a643dSPeter Wemm { 27040266059SGregory Neil Shapiro modified = true; 271065a643dSPeter Wemm *ptr = ')'; 272065a643dSPeter Wemm } 273065a643dSPeter Wemm ptr++; 274065a643dSPeter Wemm } 275065a643dSPeter Wemm if (quoted) 276065a643dSPeter Wemm { 277065a643dSPeter Wemm if (*ptr != '"') 278065a643dSPeter Wemm { 27940266059SGregory Neil Shapiro modified = true; 280065a643dSPeter Wemm *ptr = '"'; 281065a643dSPeter Wemm } 282065a643dSPeter Wemm ptr++; 283065a643dSPeter Wemm } 284065a643dSPeter Wemm if (*ptr != '\0') 285065a643dSPeter Wemm { 28640266059SGregory Neil Shapiro modified = true; 287065a643dSPeter Wemm *ptr = '\0'; 288065a643dSPeter Wemm } 289065a643dSPeter Wemm return modified; 290065a643dSPeter Wemm } 29140266059SGregory Neil Shapiro /* 292065a643dSPeter Wemm ** FIND_CHARACTER -- find an unquoted character in an RFC822 string 293065a643dSPeter Wemm ** 294065a643dSPeter Wemm ** Find an unquoted, non-commented character in an RFC822 295065a643dSPeter Wemm ** string and return a pointer to its location in the 296065a643dSPeter Wemm ** string. 297065a643dSPeter Wemm ** 298065a643dSPeter Wemm ** Parameters: 299065a643dSPeter Wemm ** string -- the string to search 300065a643dSPeter Wemm ** character -- the character to find 301065a643dSPeter Wemm ** 302065a643dSPeter Wemm ** Returns: 303065a643dSPeter Wemm ** pointer to the character, or 304065a643dSPeter Wemm ** a pointer to the end of the line if character is not found 305065a643dSPeter Wemm */ 306065a643dSPeter Wemm 307065a643dSPeter Wemm char * 308065a643dSPeter Wemm find_character(string, character) 309065a643dSPeter Wemm char *string; 31006f25ae9SGregory Neil Shapiro int character; 311065a643dSPeter Wemm { 31240266059SGregory Neil Shapiro bool backslash = false; 31340266059SGregory Neil Shapiro bool quoted = false; 314065a643dSPeter Wemm int parencount = 0; 315065a643dSPeter Wemm 316065a643dSPeter Wemm while (string != NULL && *string != '\0') 317065a643dSPeter Wemm { 318065a643dSPeter Wemm if (backslash) 319065a643dSPeter Wemm { 32040266059SGregory Neil Shapiro backslash = false; 321065a643dSPeter Wemm if (!quoted && character == '\\' && *string == '\\') 322065a643dSPeter Wemm break; 323065a643dSPeter Wemm string++; 324065a643dSPeter Wemm continue; 325065a643dSPeter Wemm } 326065a643dSPeter Wemm switch (*string) 327065a643dSPeter Wemm { 328065a643dSPeter Wemm case '\\': 32940266059SGregory Neil Shapiro backslash = true; 330065a643dSPeter Wemm break; 331065a643dSPeter Wemm 332065a643dSPeter Wemm case '(': 333065a643dSPeter Wemm if (!quoted) 334065a643dSPeter Wemm parencount++; 335065a643dSPeter Wemm break; 336065a643dSPeter Wemm 337065a643dSPeter Wemm case ')': 338065a643dSPeter Wemm if (--parencount < 0) 339065a643dSPeter Wemm parencount = 0; 340065a643dSPeter Wemm break; 341065a643dSPeter Wemm } 342065a643dSPeter Wemm 343065a643dSPeter Wemm /* Inside a comment, nothing matters */ 344065a643dSPeter Wemm if (parencount > 0) 345065a643dSPeter Wemm { 346065a643dSPeter Wemm string++; 347065a643dSPeter Wemm continue; 348065a643dSPeter Wemm } 349065a643dSPeter Wemm 350065a643dSPeter Wemm if (*string == '"') 351065a643dSPeter Wemm quoted = !quoted; 352065a643dSPeter Wemm else if (*string == character && !quoted) 353065a643dSPeter Wemm break; 354065a643dSPeter Wemm string++; 355065a643dSPeter Wemm } 356065a643dSPeter Wemm 357065a643dSPeter Wemm /* Return pointer to the character */ 358065a643dSPeter Wemm return string; 359065a643dSPeter Wemm } 36040266059SGregory Neil Shapiro 36140266059SGregory Neil Shapiro /* 36240266059SGregory Neil Shapiro ** CHECK_BODYTYPE -- check bodytype parameter 363c2aa98e2SPeter Wemm ** 36440266059SGregory Neil Shapiro ** Parameters: 36540266059SGregory Neil Shapiro ** bodytype -- bodytype parameter 36640266059SGregory Neil Shapiro ** 36740266059SGregory Neil Shapiro ** Returns: 36840266059SGregory Neil Shapiro ** BODYTYPE_* according to parameter 36940266059SGregory Neil Shapiro ** 37040266059SGregory Neil Shapiro */ 37140266059SGregory Neil Shapiro 37240266059SGregory Neil Shapiro int 37340266059SGregory Neil Shapiro check_bodytype(bodytype) 37440266059SGregory Neil Shapiro char *bodytype; 37540266059SGregory Neil Shapiro { 37640266059SGregory Neil Shapiro /* check body type for legality */ 37740266059SGregory Neil Shapiro if (bodytype == NULL) 37840266059SGregory Neil Shapiro return BODYTYPE_NONE; 37940266059SGregory Neil Shapiro if (sm_strcasecmp(bodytype, "7BIT") == 0) 38040266059SGregory Neil Shapiro return BODYTYPE_7BIT; 38140266059SGregory Neil Shapiro if (sm_strcasecmp(bodytype, "8BITMIME") == 0) 38240266059SGregory Neil Shapiro return BODYTYPE_8BITMIME; 38340266059SGregory Neil Shapiro return BODYTYPE_ILLEGAL; 38440266059SGregory Neil Shapiro } 38540266059SGregory Neil Shapiro 38640266059SGregory Neil Shapiro #if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI 38740266059SGregory Neil Shapiro /* 38840266059SGregory Neil Shapiro ** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..." 38940266059SGregory Neil Shapiro ** 39040266059SGregory Neil Shapiro ** Parameters: 39140266059SGregory Neil Shapiro ** str -- string to truncate 39240266059SGregory Neil Shapiro ** len -- maximum length (including '\0') (0 for unlimited) 39340266059SGregory Neil Shapiro ** delim -- delimiter character 39440266059SGregory Neil Shapiro ** 39540266059SGregory Neil Shapiro ** Returns: 39640266059SGregory Neil Shapiro ** None. 39740266059SGregory Neil Shapiro */ 39840266059SGregory Neil Shapiro 39940266059SGregory Neil Shapiro void 40040266059SGregory Neil Shapiro truncate_at_delim(str, len, delim) 40140266059SGregory Neil Shapiro char *str; 40240266059SGregory Neil Shapiro size_t len; 40340266059SGregory Neil Shapiro int delim; 40440266059SGregory Neil Shapiro { 40540266059SGregory Neil Shapiro char *p; 40640266059SGregory Neil Shapiro 40740266059SGregory Neil Shapiro if (str == NULL || len == 0 || strlen(str) < len) 40840266059SGregory Neil Shapiro return; 40940266059SGregory Neil Shapiro 41040266059SGregory Neil Shapiro *(str + len - 1) = '\0'; 41140266059SGregory Neil Shapiro while ((p = strrchr(str, delim)) != NULL) 41240266059SGregory Neil Shapiro { 41340266059SGregory Neil Shapiro *p = '\0'; 41440266059SGregory Neil Shapiro if (p - str + 4 < len) 41540266059SGregory Neil Shapiro { 416a7ec597cSGregory Neil Shapiro *p++ = (char) delim; 41740266059SGregory Neil Shapiro *p = '\0'; 41840266059SGregory Neil Shapiro (void) sm_strlcat(str, "...", len); 41940266059SGregory Neil Shapiro return; 42040266059SGregory Neil Shapiro } 42140266059SGregory Neil Shapiro } 42240266059SGregory Neil Shapiro 42340266059SGregory Neil Shapiro /* Couldn't find a place to append "..." */ 42440266059SGregory Neil Shapiro if (len > 3) 42540266059SGregory Neil Shapiro (void) sm_strlcpy(str, "...", len); 42640266059SGregory Neil Shapiro else 42740266059SGregory Neil Shapiro str[0] = '\0'; 42840266059SGregory Neil Shapiro } 42940266059SGregory Neil Shapiro #endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */ 43040266059SGregory Neil Shapiro /* 43140266059SGregory Neil Shapiro ** XALLOC -- Allocate memory, raise an exception on error 432c2aa98e2SPeter Wemm ** 433c2aa98e2SPeter Wemm ** Parameters: 434c2aa98e2SPeter Wemm ** sz -- size of area to allocate. 435c2aa98e2SPeter Wemm ** 436c2aa98e2SPeter Wemm ** Returns: 437c2aa98e2SPeter Wemm ** pointer to data region. 438c2aa98e2SPeter Wemm ** 43940266059SGregory Neil Shapiro ** Exceptions: 44040266059SGregory Neil Shapiro ** SmHeapOutOfMemory (F:sm.heap) -- cannot allocate memory 44140266059SGregory Neil Shapiro ** 442c2aa98e2SPeter Wemm ** Side Effects: 443c2aa98e2SPeter Wemm ** Memory is allocated. 444c2aa98e2SPeter Wemm */ 445c2aa98e2SPeter Wemm 446c2aa98e2SPeter Wemm char * 44740266059SGregory Neil Shapiro #if SM_HEAP_CHECK 44840266059SGregory Neil Shapiro xalloc_tagged(sz, file, line) 44940266059SGregory Neil Shapiro register int sz; 45040266059SGregory Neil Shapiro char *file; 45140266059SGregory Neil Shapiro int line; 45240266059SGregory Neil Shapiro #else /* SM_HEAP_CHECK */ 453c2aa98e2SPeter Wemm xalloc(sz) 454c2aa98e2SPeter Wemm register int sz; 45540266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */ 456c2aa98e2SPeter Wemm { 457c2aa98e2SPeter Wemm register char *p; 458c2aa98e2SPeter Wemm 4594e4196cbSGregory Neil Shapiro SM_REQUIRE(sz >= 0); 4604e4196cbSGregory Neil Shapiro 461c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 462c2aa98e2SPeter Wemm if (sz <= 0) 463c2aa98e2SPeter Wemm sz = 1; 464c2aa98e2SPeter Wemm 46540266059SGregory Neil Shapiro /* scaffolding for testing error handling code */ 46640266059SGregory Neil Shapiro sm_xtrap_raise_x(&SmHeapOutOfMemory); 46740266059SGregory Neil Shapiro 46840266059SGregory Neil Shapiro p = sm_malloc_tagged((unsigned) sz, file, line, sm_heap_group()); 469c2aa98e2SPeter Wemm if (p == NULL) 470c2aa98e2SPeter Wemm { 47140266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory); 472c2aa98e2SPeter Wemm } 47306f25ae9SGregory Neil Shapiro return p; 474c2aa98e2SPeter Wemm } 47540266059SGregory Neil Shapiro /* 476c2aa98e2SPeter Wemm ** COPYPLIST -- copy list of pointers. 477c2aa98e2SPeter Wemm ** 47840266059SGregory Neil Shapiro ** This routine is the equivalent of strdup for lists of 479c2aa98e2SPeter Wemm ** pointers. 480c2aa98e2SPeter Wemm ** 481c2aa98e2SPeter Wemm ** Parameters: 482c2aa98e2SPeter Wemm ** list -- list of pointers to copy. 483c2aa98e2SPeter Wemm ** Must be NULL terminated. 48440266059SGregory Neil Shapiro ** copycont -- if true, copy the contents of the vector 485c2aa98e2SPeter Wemm ** (which must be a string) also. 48640266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate storage, 48740266059SGregory Neil Shapiro ** or NULL 488c2aa98e2SPeter Wemm ** 489c2aa98e2SPeter Wemm ** Returns: 490c2aa98e2SPeter Wemm ** a copy of 'list'. 491c2aa98e2SPeter Wemm */ 492c2aa98e2SPeter Wemm 493c2aa98e2SPeter Wemm char ** 49440266059SGregory Neil Shapiro copyplist(list, copycont, rpool) 495c2aa98e2SPeter Wemm char **list; 496c2aa98e2SPeter Wemm bool copycont; 49740266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 498c2aa98e2SPeter Wemm { 499c2aa98e2SPeter Wemm register char **vp; 500c2aa98e2SPeter Wemm register char **newvp; 501c2aa98e2SPeter Wemm 502c2aa98e2SPeter Wemm for (vp = list; *vp != NULL; vp++) 503c2aa98e2SPeter Wemm continue; 504c2aa98e2SPeter Wemm 505c2aa98e2SPeter Wemm vp++; 506c2aa98e2SPeter Wemm 50740266059SGregory Neil Shapiro newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof *vp); 50806f25ae9SGregory Neil Shapiro memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); 509c2aa98e2SPeter Wemm 510c2aa98e2SPeter Wemm if (copycont) 511c2aa98e2SPeter Wemm { 512c2aa98e2SPeter Wemm for (vp = newvp; *vp != NULL; vp++) 51340266059SGregory Neil Shapiro *vp = sm_rpool_strdup_x(rpool, *vp); 514c2aa98e2SPeter Wemm } 515c2aa98e2SPeter Wemm 51606f25ae9SGregory Neil Shapiro return newvp; 517c2aa98e2SPeter Wemm } 51840266059SGregory Neil Shapiro /* 519c2aa98e2SPeter Wemm ** COPYQUEUE -- copy address queue. 520c2aa98e2SPeter Wemm ** 52140266059SGregory Neil Shapiro ** This routine is the equivalent of strdup for address queues; 52206f25ae9SGregory Neil Shapiro ** addresses marked as QS_IS_DEAD() aren't copied 523c2aa98e2SPeter Wemm ** 524c2aa98e2SPeter Wemm ** Parameters: 525c2aa98e2SPeter Wemm ** addr -- list of address structures to copy. 52640266059SGregory Neil Shapiro ** rpool -- resource pool from which to allocate storage 527c2aa98e2SPeter Wemm ** 528c2aa98e2SPeter Wemm ** Returns: 529c2aa98e2SPeter Wemm ** a copy of 'addr'. 530c2aa98e2SPeter Wemm */ 531c2aa98e2SPeter Wemm 532c2aa98e2SPeter Wemm ADDRESS * 53340266059SGregory Neil Shapiro copyqueue(addr, rpool) 534c2aa98e2SPeter Wemm ADDRESS *addr; 53540266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 536c2aa98e2SPeter Wemm { 537c2aa98e2SPeter Wemm register ADDRESS *newaddr; 538c2aa98e2SPeter Wemm ADDRESS *ret; 539c2aa98e2SPeter Wemm register ADDRESS **tail = &ret; 540c2aa98e2SPeter Wemm 541c2aa98e2SPeter Wemm while (addr != NULL) 542c2aa98e2SPeter Wemm { 54306f25ae9SGregory Neil Shapiro if (!QS_IS_DEAD(addr->q_state)) 544c2aa98e2SPeter Wemm { 54540266059SGregory Neil Shapiro newaddr = (ADDRESS *) sm_rpool_malloc_x(rpool, 54640266059SGregory Neil Shapiro sizeof *newaddr); 547c2aa98e2SPeter Wemm STRUCTCOPY(*addr, *newaddr); 548c2aa98e2SPeter Wemm *tail = newaddr; 549c2aa98e2SPeter Wemm tail = &newaddr->q_next; 550c2aa98e2SPeter Wemm } 551c2aa98e2SPeter Wemm addr = addr->q_next; 552c2aa98e2SPeter Wemm } 553c2aa98e2SPeter Wemm *tail = NULL; 554c2aa98e2SPeter Wemm 555c2aa98e2SPeter Wemm return ret; 556c2aa98e2SPeter Wemm } 55740266059SGregory Neil Shapiro /* 55806f25ae9SGregory Neil Shapiro ** LOG_SENDMAIL_PID -- record sendmail pid and command line. 55906f25ae9SGregory Neil Shapiro ** 56006f25ae9SGregory Neil Shapiro ** Parameters: 56106f25ae9SGregory Neil Shapiro ** e -- the current envelope. 56206f25ae9SGregory Neil Shapiro ** 56306f25ae9SGregory Neil Shapiro ** Returns: 56406f25ae9SGregory Neil Shapiro ** none. 56506f25ae9SGregory Neil Shapiro ** 56606f25ae9SGregory Neil Shapiro ** Side Effects: 56740266059SGregory Neil Shapiro ** writes pidfile, logs command line. 568e92d3f3fSGregory Neil Shapiro ** keeps file open and locked to prevent overwrite of active file 56906f25ae9SGregory Neil Shapiro */ 57006f25ae9SGregory Neil Shapiro 571e92d3f3fSGregory Neil Shapiro static SM_FILE_T *Pidf = NULL; 572e92d3f3fSGregory Neil Shapiro 57306f25ae9SGregory Neil Shapiro void 57406f25ae9SGregory Neil Shapiro log_sendmail_pid(e) 57506f25ae9SGregory Neil Shapiro ENVELOPE *e; 57606f25ae9SGregory Neil Shapiro { 57706f25ae9SGregory Neil Shapiro long sff; 57894c01205SGregory Neil Shapiro char pidpath[MAXPATHLEN]; 57940266059SGregory Neil Shapiro extern char *CommandLineArgs; 58006f25ae9SGregory Neil Shapiro 58106f25ae9SGregory Neil Shapiro /* write the pid to the log file for posterity */ 582e92d3f3fSGregory Neil Shapiro sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT|SFF_NBLOCK; 58306f25ae9SGregory Neil Shapiro if (TrustedUid != 0 && RealUid == TrustedUid) 58406f25ae9SGregory Neil Shapiro sff |= SFF_OPENASROOT; 58506f25ae9SGregory Neil Shapiro expand(PidFile, pidpath, sizeof pidpath, e); 586e92d3f3fSGregory Neil Shapiro Pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff); 587e92d3f3fSGregory Neil Shapiro if (Pidf == NULL) 58806f25ae9SGregory Neil Shapiro { 589e92d3f3fSGregory Neil Shapiro if (errno == EWOULDBLOCK) 590e92d3f3fSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, 591e92d3f3fSGregory Neil Shapiro "unable to write pid to %s: file in use by another process", 592e92d3f3fSGregory Neil Shapiro pidpath); 593e92d3f3fSGregory Neil Shapiro else 594e92d3f3fSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, 595e92d3f3fSGregory Neil Shapiro "unable to write pid to %s: %s", 59640266059SGregory Neil Shapiro pidpath, sm_errstring(errno)); 59706f25ae9SGregory Neil Shapiro } 59806f25ae9SGregory Neil Shapiro else 59906f25ae9SGregory Neil Shapiro { 600e92d3f3fSGregory Neil Shapiro PidFilePid = getpid(); 601193538b7SGregory Neil Shapiro 60206f25ae9SGregory Neil Shapiro /* write the process id on line 1 */ 603e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(Pidf, SM_TIME_DEFAULT, "%ld\n", 604e92d3f3fSGregory Neil Shapiro (long) PidFilePid); 60506f25ae9SGregory Neil Shapiro 60606f25ae9SGregory Neil Shapiro /* line 2 contains all command line flags */ 607e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(Pidf, SM_TIME_DEFAULT, "%s\n", 60840266059SGregory Neil Shapiro CommandLineArgs); 60906f25ae9SGregory Neil Shapiro 610e92d3f3fSGregory Neil Shapiro /* flush */ 611e92d3f3fSGregory Neil Shapiro (void) sm_io_flush(Pidf, SM_TIME_DEFAULT); 612e92d3f3fSGregory Neil Shapiro 613e92d3f3fSGregory Neil Shapiro /* 614e92d3f3fSGregory Neil Shapiro ** Leave pid file open until process ends 615e92d3f3fSGregory Neil Shapiro ** so it's not overwritten by another 616e92d3f3fSGregory Neil Shapiro ** process. 617e92d3f3fSGregory Neil Shapiro */ 61806f25ae9SGregory Neil Shapiro } 61940266059SGregory Neil Shapiro if (LogLevel > 9) 62040266059SGregory Neil Shapiro sm_syslog(LOG_INFO, NOQID, "started as: %s", CommandLineArgs); 62106f25ae9SGregory Neil Shapiro } 622e92d3f3fSGregory Neil Shapiro 623e92d3f3fSGregory Neil Shapiro /* 624e92d3f3fSGregory Neil Shapiro ** CLOSE_SENDMAIL_PID -- close sendmail pid file 625e92d3f3fSGregory Neil Shapiro ** 626e92d3f3fSGregory Neil Shapiro ** Parameters: 627e92d3f3fSGregory Neil Shapiro ** none. 628e92d3f3fSGregory Neil Shapiro ** 629e92d3f3fSGregory Neil Shapiro ** Returns: 630e92d3f3fSGregory Neil Shapiro ** none. 631e92d3f3fSGregory Neil Shapiro */ 632e92d3f3fSGregory Neil Shapiro 633e92d3f3fSGregory Neil Shapiro void 634e92d3f3fSGregory Neil Shapiro close_sendmail_pid() 635e92d3f3fSGregory Neil Shapiro { 636e92d3f3fSGregory Neil Shapiro if (Pidf == NULL) 637e92d3f3fSGregory Neil Shapiro return; 638e92d3f3fSGregory Neil Shapiro 639e92d3f3fSGregory Neil Shapiro (void) sm_io_close(Pidf, SM_TIME_DEFAULT); 640e92d3f3fSGregory Neil Shapiro Pidf = NULL; 641e92d3f3fSGregory Neil Shapiro } 642e92d3f3fSGregory Neil Shapiro 64340266059SGregory Neil Shapiro /* 64406f25ae9SGregory Neil Shapiro ** SET_DELIVERY_MODE -- set and record the delivery mode 64506f25ae9SGregory Neil Shapiro ** 64606f25ae9SGregory Neil Shapiro ** Parameters: 64706f25ae9SGregory Neil Shapiro ** mode -- delivery mode 64806f25ae9SGregory Neil Shapiro ** e -- the current envelope. 64906f25ae9SGregory Neil Shapiro ** 65006f25ae9SGregory Neil Shapiro ** Returns: 65106f25ae9SGregory Neil Shapiro ** none. 65206f25ae9SGregory Neil Shapiro ** 65306f25ae9SGregory Neil Shapiro ** Side Effects: 65440266059SGregory Neil Shapiro ** sets {deliveryMode} macro 65506f25ae9SGregory Neil Shapiro */ 65606f25ae9SGregory Neil Shapiro 65706f25ae9SGregory Neil Shapiro void 65806f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e) 65906f25ae9SGregory Neil Shapiro int mode; 66006f25ae9SGregory Neil Shapiro ENVELOPE *e; 66106f25ae9SGregory Neil Shapiro { 66206f25ae9SGregory Neil Shapiro char buf[2]; 66306f25ae9SGregory Neil Shapiro 66406f25ae9SGregory Neil Shapiro e->e_sendmode = (char) mode; 66506f25ae9SGregory Neil Shapiro buf[0] = (char) mode; 66606f25ae9SGregory Neil Shapiro buf[1] = '\0'; 66740266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, macid("{deliveryMode}"), buf); 66806f25ae9SGregory Neil Shapiro } 66940266059SGregory Neil Shapiro /* 67040266059SGregory Neil Shapiro ** SET_OP_MODE -- set and record the op mode 67140266059SGregory Neil Shapiro ** 67240266059SGregory Neil Shapiro ** Parameters: 67340266059SGregory Neil Shapiro ** mode -- op mode 67440266059SGregory Neil Shapiro ** e -- the current envelope. 67540266059SGregory Neil Shapiro ** 67640266059SGregory Neil Shapiro ** Returns: 67740266059SGregory Neil Shapiro ** none. 67840266059SGregory Neil Shapiro ** 67940266059SGregory Neil Shapiro ** Side Effects: 68040266059SGregory Neil Shapiro ** sets {opMode} macro 68140266059SGregory Neil Shapiro */ 68240266059SGregory Neil Shapiro 68340266059SGregory Neil Shapiro void 68440266059SGregory Neil Shapiro set_op_mode(mode) 68540266059SGregory Neil Shapiro int mode; 68640266059SGregory Neil Shapiro { 68740266059SGregory Neil Shapiro char buf[2]; 68840266059SGregory Neil Shapiro extern ENVELOPE BlankEnvelope; 68940266059SGregory Neil Shapiro 69040266059SGregory Neil Shapiro OpMode = (char) mode; 69140266059SGregory Neil Shapiro buf[0] = (char) mode; 69240266059SGregory Neil Shapiro buf[1] = '\0'; 69340266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, MID_OPMODE, buf); 69440266059SGregory Neil Shapiro } 69540266059SGregory Neil Shapiro /* 696c2aa98e2SPeter Wemm ** PRINTAV -- print argument vector. 697c2aa98e2SPeter Wemm ** 698c2aa98e2SPeter Wemm ** Parameters: 699e92d3f3fSGregory Neil Shapiro ** fp -- output file pointer. 700c2aa98e2SPeter Wemm ** av -- argument vector. 701c2aa98e2SPeter Wemm ** 702c2aa98e2SPeter Wemm ** Returns: 703c2aa98e2SPeter Wemm ** none. 704c2aa98e2SPeter Wemm ** 705c2aa98e2SPeter Wemm ** Side Effects: 706c2aa98e2SPeter Wemm ** prints av. 707c2aa98e2SPeter Wemm */ 708c2aa98e2SPeter Wemm 709c2aa98e2SPeter Wemm void 710e92d3f3fSGregory Neil Shapiro printav(fp, av) 711e92d3f3fSGregory Neil Shapiro SM_FILE_T *fp; 712c2aa98e2SPeter Wemm register char **av; 713c2aa98e2SPeter Wemm { 714c2aa98e2SPeter Wemm while (*av != NULL) 715c2aa98e2SPeter Wemm { 716c2aa98e2SPeter Wemm if (tTd(0, 44)) 71740266059SGregory Neil Shapiro sm_dprintf("\n\t%08lx=", (unsigned long) *av); 718c2aa98e2SPeter Wemm else 719e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, ' '); 720e92d3f3fSGregory Neil Shapiro xputs(fp, *av++); 721c2aa98e2SPeter Wemm } 722e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\n'); 723c2aa98e2SPeter Wemm } 72440266059SGregory Neil Shapiro /* 725c2aa98e2SPeter Wemm ** XPUTS -- put string doing control escapes. 726c2aa98e2SPeter Wemm ** 727c2aa98e2SPeter Wemm ** Parameters: 728e92d3f3fSGregory Neil Shapiro ** fp -- output file pointer. 729c2aa98e2SPeter Wemm ** s -- string to put. 730c2aa98e2SPeter Wemm ** 731c2aa98e2SPeter Wemm ** Returns: 732c2aa98e2SPeter Wemm ** none. 733c2aa98e2SPeter Wemm ** 734c2aa98e2SPeter Wemm ** Side Effects: 735c2aa98e2SPeter Wemm ** output to stdout 736c2aa98e2SPeter Wemm */ 737c2aa98e2SPeter Wemm 738c2aa98e2SPeter Wemm void 739e92d3f3fSGregory Neil Shapiro xputs(fp, s) 740e92d3f3fSGregory Neil Shapiro SM_FILE_T *fp; 741c2aa98e2SPeter Wemm register const char *s; 742c2aa98e2SPeter Wemm { 743c2aa98e2SPeter Wemm register int c; 744c2aa98e2SPeter Wemm register struct metamac *mp; 74540266059SGregory Neil Shapiro bool shiftout = false; 746c2aa98e2SPeter Wemm extern struct metamac MetaMacros[]; 74740266059SGregory Neil Shapiro static SM_DEBUG_T DebugANSI = SM_DEBUG_INITIALIZER("ANSI", 74840266059SGregory Neil Shapiro "@(#)$Debug: ANSI - enable reverse video in debug output $"); 74940266059SGregory Neil Shapiro 75040266059SGregory Neil Shapiro /* 75140266059SGregory Neil Shapiro ** TermEscape is set here, rather than in main(), 75240266059SGregory Neil Shapiro ** because ANSI mode can be turned on or off at any time 75340266059SGregory Neil Shapiro ** if we are in -bt rule testing mode. 75440266059SGregory Neil Shapiro */ 75540266059SGregory Neil Shapiro 75640266059SGregory Neil Shapiro if (sm_debug_unknown(&DebugANSI)) 75740266059SGregory Neil Shapiro { 75840266059SGregory Neil Shapiro if (sm_debug_active(&DebugANSI, 1)) 75940266059SGregory Neil Shapiro { 76040266059SGregory Neil Shapiro TermEscape.te_rv_on = "\033[7m"; 76140266059SGregory Neil Shapiro TermEscape.te_rv_off = "\033[0m"; 76240266059SGregory Neil Shapiro } 76340266059SGregory Neil Shapiro else 76440266059SGregory Neil Shapiro { 76540266059SGregory Neil Shapiro TermEscape.te_rv_on = ""; 76640266059SGregory Neil Shapiro TermEscape.te_rv_off = ""; 76740266059SGregory Neil Shapiro } 76840266059SGregory Neil Shapiro } 769c2aa98e2SPeter Wemm 770c2aa98e2SPeter Wemm if (s == NULL) 771c2aa98e2SPeter Wemm { 772e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s<null>%s", 77340266059SGregory Neil Shapiro TermEscape.te_rv_on, TermEscape.te_rv_off); 774c2aa98e2SPeter Wemm return; 775c2aa98e2SPeter Wemm } 776c2aa98e2SPeter Wemm while ((c = (*s++ & 0377)) != '\0') 777c2aa98e2SPeter Wemm { 778c2aa98e2SPeter Wemm if (shiftout) 779c2aa98e2SPeter Wemm { 780e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", 78140266059SGregory Neil Shapiro TermEscape.te_rv_off); 78240266059SGregory Neil Shapiro shiftout = false; 783c2aa98e2SPeter Wemm } 784c2aa98e2SPeter Wemm if (!isascii(c)) 785c2aa98e2SPeter Wemm { 786c2aa98e2SPeter Wemm if (c == MATCHREPL) 787c2aa98e2SPeter Wemm { 788e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 78940266059SGregory Neil Shapiro "%s$", 79040266059SGregory Neil Shapiro TermEscape.te_rv_on); 79140266059SGregory Neil Shapiro shiftout = true; 792c2aa98e2SPeter Wemm if (*s == '\0') 793c2aa98e2SPeter Wemm continue; 794c2aa98e2SPeter Wemm c = *s++ & 0377; 795c2aa98e2SPeter Wemm goto printchar; 796c2aa98e2SPeter Wemm } 797c2aa98e2SPeter Wemm if (c == MACROEXPAND || c == MACRODEXPAND) 798c2aa98e2SPeter Wemm { 799e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 80040266059SGregory Neil Shapiro "%s$", 80140266059SGregory Neil Shapiro TermEscape.te_rv_on); 802c2aa98e2SPeter Wemm if (c == MACRODEXPAND) 803e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, 80440266059SGregory Neil Shapiro SM_TIME_DEFAULT, '&'); 80540266059SGregory Neil Shapiro shiftout = true; 806c2aa98e2SPeter Wemm if (*s == '\0') 807c2aa98e2SPeter Wemm continue; 808c2aa98e2SPeter Wemm if (strchr("=~&?", *s) != NULL) 809e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, 81040266059SGregory Neil Shapiro SM_TIME_DEFAULT, 81140266059SGregory Neil Shapiro *s++); 812c2aa98e2SPeter Wemm if (bitset(0200, *s)) 813e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, 81440266059SGregory Neil Shapiro SM_TIME_DEFAULT, 81540266059SGregory Neil Shapiro "{%s}", 81640266059SGregory Neil Shapiro macname(bitidx(*s++))); 817c2aa98e2SPeter Wemm else 818e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, 81940266059SGregory Neil Shapiro SM_TIME_DEFAULT, 82040266059SGregory Neil Shapiro "%c", 82140266059SGregory Neil Shapiro *s++); 822c2aa98e2SPeter Wemm continue; 823c2aa98e2SPeter Wemm } 824c2aa98e2SPeter Wemm for (mp = MetaMacros; mp->metaname != '\0'; mp++) 825c2aa98e2SPeter Wemm { 82640266059SGregory Neil Shapiro if (bitidx(mp->metaval) == c) 827c2aa98e2SPeter Wemm { 828e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, 82940266059SGregory Neil Shapiro SM_TIME_DEFAULT, 83040266059SGregory Neil Shapiro "%s$%c", 831c2aa98e2SPeter Wemm TermEscape.te_rv_on, 832c2aa98e2SPeter Wemm mp->metaname); 83340266059SGregory Neil Shapiro shiftout = true; 834c2aa98e2SPeter Wemm break; 835c2aa98e2SPeter Wemm } 836c2aa98e2SPeter Wemm } 837c2aa98e2SPeter Wemm if (c == MATCHCLASS || c == MATCHNCLASS) 838c2aa98e2SPeter Wemm { 839c2aa98e2SPeter Wemm if (bitset(0200, *s)) 840e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, 84140266059SGregory Neil Shapiro SM_TIME_DEFAULT, 84240266059SGregory Neil Shapiro "{%s}", 84340266059SGregory Neil Shapiro macname(bitidx(*s++))); 844c2aa98e2SPeter Wemm else if (*s != '\0') 845e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, 84640266059SGregory Neil Shapiro SM_TIME_DEFAULT, 84740266059SGregory Neil Shapiro "%c", 84840266059SGregory Neil Shapiro *s++); 849c2aa98e2SPeter Wemm } 850c2aa98e2SPeter Wemm if (mp->metaname != '\0') 851c2aa98e2SPeter Wemm continue; 852c2aa98e2SPeter Wemm 853c2aa98e2SPeter Wemm /* unrecognized meta character */ 854e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%sM-", 85540266059SGregory Neil Shapiro TermEscape.te_rv_on); 85640266059SGregory Neil Shapiro shiftout = true; 857c2aa98e2SPeter Wemm c &= 0177; 858c2aa98e2SPeter Wemm } 859c2aa98e2SPeter Wemm printchar: 860c2aa98e2SPeter Wemm if (isprint(c)) 861c2aa98e2SPeter Wemm { 862e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, c); 863c2aa98e2SPeter Wemm continue; 864c2aa98e2SPeter Wemm } 865c2aa98e2SPeter Wemm 866c2aa98e2SPeter Wemm /* wasn't a meta-macro -- find another way to print it */ 867c2aa98e2SPeter Wemm switch (c) 868c2aa98e2SPeter Wemm { 869c2aa98e2SPeter Wemm case '\n': 870c2aa98e2SPeter Wemm c = 'n'; 871c2aa98e2SPeter Wemm break; 872c2aa98e2SPeter Wemm 873c2aa98e2SPeter Wemm case '\r': 874c2aa98e2SPeter Wemm c = 'r'; 875c2aa98e2SPeter Wemm break; 876c2aa98e2SPeter Wemm 877c2aa98e2SPeter Wemm case '\t': 878c2aa98e2SPeter Wemm c = 't'; 879c2aa98e2SPeter Wemm break; 880c2aa98e2SPeter Wemm } 881c2aa98e2SPeter Wemm if (!shiftout) 882c2aa98e2SPeter Wemm { 883e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", 88440266059SGregory Neil Shapiro TermEscape.te_rv_on); 88540266059SGregory Neil Shapiro shiftout = true; 886c2aa98e2SPeter Wemm } 887c2aa98e2SPeter Wemm if (isprint(c)) 888c2aa98e2SPeter Wemm { 889e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\\'); 890e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, c); 891c2aa98e2SPeter Wemm } 892c2aa98e2SPeter Wemm else 893c2aa98e2SPeter Wemm { 894e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, '^'); 895e92d3f3fSGregory Neil Shapiro (void) sm_io_putc(fp, SM_TIME_DEFAULT, c ^ 0100); 896c2aa98e2SPeter Wemm } 897c2aa98e2SPeter Wemm } 898c2aa98e2SPeter Wemm if (shiftout) 899e92d3f3fSGregory Neil Shapiro (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", 90040266059SGregory Neil Shapiro TermEscape.te_rv_off); 901e92d3f3fSGregory Neil Shapiro (void) sm_io_flush(fp, SM_TIME_DEFAULT); 902c2aa98e2SPeter Wemm } 90340266059SGregory Neil Shapiro /* 904c2aa98e2SPeter Wemm ** MAKELOWER -- Translate a line into lower case 905c2aa98e2SPeter Wemm ** 906c2aa98e2SPeter Wemm ** Parameters: 907c2aa98e2SPeter Wemm ** p -- the string to translate. If NULL, return is 908c2aa98e2SPeter Wemm ** immediate. 909c2aa98e2SPeter Wemm ** 910c2aa98e2SPeter Wemm ** Returns: 911c2aa98e2SPeter Wemm ** none. 912c2aa98e2SPeter Wemm ** 913c2aa98e2SPeter Wemm ** Side Effects: 914c2aa98e2SPeter Wemm ** String pointed to by p is translated to lower case. 915c2aa98e2SPeter Wemm */ 916c2aa98e2SPeter Wemm 917c2aa98e2SPeter Wemm void 918c2aa98e2SPeter Wemm makelower(p) 919c2aa98e2SPeter Wemm register char *p; 920c2aa98e2SPeter Wemm { 921c2aa98e2SPeter Wemm register char c; 922c2aa98e2SPeter Wemm 923c2aa98e2SPeter Wemm if (p == NULL) 924c2aa98e2SPeter Wemm return; 925c2aa98e2SPeter Wemm for (; (c = *p) != '\0'; p++) 926c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 927c2aa98e2SPeter Wemm *p = tolower(c); 928c2aa98e2SPeter Wemm } 92940266059SGregory Neil Shapiro /* 930c2aa98e2SPeter Wemm ** FIXCRLF -- fix <CR><LF> in line. 931c2aa98e2SPeter Wemm ** 932c2aa98e2SPeter Wemm ** Looks for the <CR><LF> combination and turns it into the 933c2aa98e2SPeter Wemm ** UNIX canonical <NL> character. It only takes one line, 934c2aa98e2SPeter Wemm ** i.e., it is assumed that the first <NL> found is the end 935c2aa98e2SPeter Wemm ** of the line. 936c2aa98e2SPeter Wemm ** 937c2aa98e2SPeter Wemm ** Parameters: 938c2aa98e2SPeter Wemm ** line -- the line to fix. 939c2aa98e2SPeter Wemm ** stripnl -- if true, strip the newline also. 940c2aa98e2SPeter Wemm ** 941c2aa98e2SPeter Wemm ** Returns: 942c2aa98e2SPeter Wemm ** none. 943c2aa98e2SPeter Wemm ** 944c2aa98e2SPeter Wemm ** Side Effects: 945c2aa98e2SPeter Wemm ** line is changed in place. 946c2aa98e2SPeter Wemm */ 947c2aa98e2SPeter Wemm 948c2aa98e2SPeter Wemm void 949c2aa98e2SPeter Wemm fixcrlf(line, stripnl) 950c2aa98e2SPeter Wemm char *line; 951c2aa98e2SPeter Wemm bool stripnl; 952c2aa98e2SPeter Wemm { 953c2aa98e2SPeter Wemm register char *p; 954c2aa98e2SPeter Wemm 955c2aa98e2SPeter Wemm p = strchr(line, '\n'); 956c2aa98e2SPeter Wemm if (p == NULL) 957c2aa98e2SPeter Wemm return; 958c2aa98e2SPeter Wemm if (p > line && p[-1] == '\r') 959c2aa98e2SPeter Wemm p--; 960c2aa98e2SPeter Wemm if (!stripnl) 961c2aa98e2SPeter Wemm *p++ = '\n'; 962c2aa98e2SPeter Wemm *p = '\0'; 963c2aa98e2SPeter Wemm } 96440266059SGregory Neil Shapiro /* 965c2aa98e2SPeter Wemm ** PUTLINE -- put a line like fputs obeying SMTP conventions 966c2aa98e2SPeter Wemm ** 967c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 968c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 969c2aa98e2SPeter Wemm ** 970c2aa98e2SPeter Wemm ** Parameters: 971c2aa98e2SPeter Wemm ** l -- line to put. 972c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 973c2aa98e2SPeter Wemm ** 974c2aa98e2SPeter Wemm ** Returns: 9754e4196cbSGregory Neil Shapiro ** true iff line was written successfully 976c2aa98e2SPeter Wemm ** 977c2aa98e2SPeter Wemm ** Side Effects: 97840266059SGregory Neil Shapiro ** output of l to mci->mci_out. 979c2aa98e2SPeter Wemm */ 980c2aa98e2SPeter Wemm 9814e4196cbSGregory Neil Shapiro bool 982c2aa98e2SPeter Wemm putline(l, mci) 983c2aa98e2SPeter Wemm register char *l; 984c2aa98e2SPeter Wemm register MCI *mci; 985c2aa98e2SPeter Wemm { 9864e4196cbSGregory Neil Shapiro return putxline(l, strlen(l), mci, PXLF_MAPFROM); 987c2aa98e2SPeter Wemm } 98840266059SGregory Neil Shapiro /* 989c2aa98e2SPeter Wemm ** PUTXLINE -- putline with flags bits. 990c2aa98e2SPeter Wemm ** 991c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 992c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 993c2aa98e2SPeter Wemm ** 994c2aa98e2SPeter Wemm ** Parameters: 995c2aa98e2SPeter Wemm ** l -- line to put. 996c2aa98e2SPeter Wemm ** len -- the length of the line. 997c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 998c2aa98e2SPeter Wemm ** pxflags -- flag bits: 999c2aa98e2SPeter Wemm ** PXLF_MAPFROM -- map From_ to >From_. 1000c2aa98e2SPeter Wemm ** PXLF_STRIP8BIT -- strip 8th bit. 1001c2aa98e2SPeter Wemm ** PXLF_HEADER -- map bare newline in header to newline space. 1002605302a5SGregory Neil Shapiro ** PXLF_NOADDEOL -- don't add an EOL if one wasn't present. 1003c2aa98e2SPeter Wemm ** 1004c2aa98e2SPeter Wemm ** Returns: 10054e4196cbSGregory Neil Shapiro ** true iff line was written successfully 1006c2aa98e2SPeter Wemm ** 1007c2aa98e2SPeter Wemm ** Side Effects: 100840266059SGregory Neil Shapiro ** output of l to mci->mci_out. 1009c2aa98e2SPeter Wemm */ 1010c2aa98e2SPeter Wemm 10114e4196cbSGregory Neil Shapiro bool 1012c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags) 1013c2aa98e2SPeter Wemm register char *l; 1014c2aa98e2SPeter Wemm size_t len; 1015c2aa98e2SPeter Wemm register MCI *mci; 1016c2aa98e2SPeter Wemm int pxflags; 1017c2aa98e2SPeter Wemm { 101840266059SGregory Neil Shapiro bool dead = false; 1019c2aa98e2SPeter Wemm register char *p, *end; 1020c2aa98e2SPeter Wemm int slop = 0; 1021c2aa98e2SPeter Wemm 1022c2aa98e2SPeter Wemm /* strip out 0200 bits -- these can look like TELNET protocol */ 1023c2aa98e2SPeter Wemm if (bitset(MCIF_7BIT, mci->mci_flags) || 1024c2aa98e2SPeter Wemm bitset(PXLF_STRIP8BIT, pxflags)) 1025c2aa98e2SPeter Wemm { 1026c2aa98e2SPeter Wemm register char svchar; 1027c2aa98e2SPeter Wemm 1028c2aa98e2SPeter Wemm for (p = l; (svchar = *p) != '\0'; ++p) 1029c2aa98e2SPeter Wemm if (bitset(0200, svchar)) 1030c2aa98e2SPeter Wemm *p = svchar &~ 0200; 1031c2aa98e2SPeter Wemm } 1032c2aa98e2SPeter Wemm 1033c2aa98e2SPeter Wemm end = l + len; 1034c2aa98e2SPeter Wemm do 1035c2aa98e2SPeter Wemm { 1036605302a5SGregory Neil Shapiro bool noeol = false; 1037605302a5SGregory Neil Shapiro 1038c2aa98e2SPeter Wemm /* find the end of the line */ 1039c2aa98e2SPeter Wemm p = memchr(l, '\n', end - l); 1040c2aa98e2SPeter Wemm if (p == NULL) 1041605302a5SGregory Neil Shapiro { 1042c2aa98e2SPeter Wemm p = end; 1043605302a5SGregory Neil Shapiro noeol = true; 1044605302a5SGregory Neil Shapiro } 1045c2aa98e2SPeter Wemm 1046c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 104740266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 104840266059SGregory Neil Shapiro "%05d >>> ", (int) CurrentPid); 1049c2aa98e2SPeter Wemm 1050c2aa98e2SPeter Wemm /* check for line overflow */ 1051c2aa98e2SPeter Wemm while (mci->mci_mailer->m_linelimit > 0 && 1052c2aa98e2SPeter Wemm (p - l + slop) > mci->mci_mailer->m_linelimit) 1053c2aa98e2SPeter Wemm { 1054c2aa98e2SPeter Wemm char *l_base = l; 1055c2aa98e2SPeter Wemm register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 1056c2aa98e2SPeter Wemm 1057c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 1058c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 1059c2aa98e2SPeter Wemm { 106040266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 106140266059SGregory Neil Shapiro '.') == SM_IO_EOF) 106240266059SGregory Neil Shapiro dead = true; 1063c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 106440266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 106540266059SGregory Neil Shapiro SM_TIME_DEFAULT, '.'); 1066c2aa98e2SPeter Wemm } 1067c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1068c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1069c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1070c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1071c2aa98e2SPeter Wemm { 107240266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 107340266059SGregory Neil Shapiro '>') == SM_IO_EOF) 107440266059SGregory Neil Shapiro dead = true; 1075c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 107640266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 107740266059SGregory Neil Shapiro SM_TIME_DEFAULT, 107840266059SGregory Neil Shapiro '>'); 1079c2aa98e2SPeter Wemm } 108006f25ae9SGregory Neil Shapiro if (dead) 108106f25ae9SGregory Neil Shapiro break; 108206f25ae9SGregory Neil Shapiro 1083c2aa98e2SPeter Wemm while (l < q) 1084c2aa98e2SPeter Wemm { 108540266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 108640266059SGregory Neil Shapiro (unsigned char) *l++) == SM_IO_EOF) 108706f25ae9SGregory Neil Shapiro { 108840266059SGregory Neil Shapiro dead = true; 108906f25ae9SGregory Neil Shapiro break; 1090c2aa98e2SPeter Wemm } 1091193538b7SGregory Neil Shapiro } 109206f25ae9SGregory Neil Shapiro if (dead) 109306f25ae9SGregory Neil Shapiro break; 109406f25ae9SGregory Neil Shapiro 109540266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '!') == 109640266059SGregory Neil Shapiro SM_IO_EOF || 109740266059SGregory Neil Shapiro sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 109840266059SGregory Neil Shapiro mci->mci_mailer->m_eol) == 109940266059SGregory Neil Shapiro SM_IO_EOF || 110040266059SGregory Neil Shapiro sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, ' ') == 110140266059SGregory Neil Shapiro SM_IO_EOF) 110206f25ae9SGregory Neil Shapiro { 110340266059SGregory Neil Shapiro dead = true; 110406f25ae9SGregory Neil Shapiro break; 110506f25ae9SGregory Neil Shapiro } 1106c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1107c2aa98e2SPeter Wemm { 1108c2aa98e2SPeter Wemm for (l = l_base; l < q; l++) 110940266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 111040266059SGregory Neil Shapiro SM_TIME_DEFAULT, 111140266059SGregory Neil Shapiro (unsigned char)*l); 111240266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, 111340266059SGregory Neil Shapiro SM_TIME_DEFAULT, 111440266059SGregory Neil Shapiro "!\n%05d >>> ", 111540266059SGregory Neil Shapiro (int) CurrentPid); 1116c2aa98e2SPeter Wemm } 1117c2aa98e2SPeter Wemm slop = 1; 1118c2aa98e2SPeter Wemm } 1119c2aa98e2SPeter Wemm 112006f25ae9SGregory Neil Shapiro if (dead) 112106f25ae9SGregory Neil Shapiro break; 112206f25ae9SGregory Neil Shapiro 1123c2aa98e2SPeter Wemm /* output last part */ 1124c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 1125c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 1126c2aa98e2SPeter Wemm { 112740266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '.') == 112840266059SGregory Neil Shapiro SM_IO_EOF) 1129193538b7SGregory Neil Shapiro { 11304e4196cbSGregory Neil Shapiro dead = true; 11314e4196cbSGregory Neil Shapiro break; 1132193538b7SGregory Neil Shapiro } 1133c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 113440266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 113540266059SGregory Neil Shapiro SM_TIME_DEFAULT, '.'); 1136c2aa98e2SPeter Wemm } 1137c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1138c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1139c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1140c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1141c2aa98e2SPeter Wemm { 114240266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '>') == 114340266059SGregory Neil Shapiro SM_IO_EOF) 1144193538b7SGregory Neil Shapiro { 11454e4196cbSGregory Neil Shapiro dead = true; 11464e4196cbSGregory Neil Shapiro break; 1147193538b7SGregory Neil Shapiro } 1148c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 114940266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 115040266059SGregory Neil Shapiro SM_TIME_DEFAULT, '>'); 1151c2aa98e2SPeter Wemm } 1152c2aa98e2SPeter Wemm for ( ; l < p; ++l) 1153c2aa98e2SPeter Wemm { 1154c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 115540266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 115640266059SGregory Neil Shapiro SM_TIME_DEFAULT, 115740266059SGregory Neil Shapiro (unsigned char)*l); 115840266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 115940266059SGregory Neil Shapiro (unsigned char) *l) == SM_IO_EOF) 116006f25ae9SGregory Neil Shapiro { 116140266059SGregory Neil Shapiro dead = true; 116206f25ae9SGregory Neil Shapiro break; 1163c2aa98e2SPeter Wemm } 1164193538b7SGregory Neil Shapiro } 116506f25ae9SGregory Neil Shapiro if (dead) 116606f25ae9SGregory Neil Shapiro break; 116706f25ae9SGregory Neil Shapiro 1168c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 116940266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, SM_TIME_DEFAULT, 117040266059SGregory Neil Shapiro '\n'); 1171605302a5SGregory Neil Shapiro if ((!bitset(PXLF_NOADDEOL, pxflags) || !noeol) && 1172605302a5SGregory Neil Shapiro sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 117340266059SGregory Neil Shapiro mci->mci_mailer->m_eol) == SM_IO_EOF) 1174193538b7SGregory Neil Shapiro { 11754e4196cbSGregory Neil Shapiro dead = true; 11764e4196cbSGregory Neil Shapiro break; 1177193538b7SGregory Neil Shapiro } 1178c2aa98e2SPeter Wemm if (l < end && *l == '\n') 1179c2aa98e2SPeter Wemm { 1180c2aa98e2SPeter Wemm if (*++l != ' ' && *l != '\t' && *l != '\0' && 1181c2aa98e2SPeter Wemm bitset(PXLF_HEADER, pxflags)) 1182c2aa98e2SPeter Wemm { 118340266059SGregory Neil Shapiro if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 118440266059SGregory Neil Shapiro ' ') == SM_IO_EOF) 1185193538b7SGregory Neil Shapiro { 11864e4196cbSGregory Neil Shapiro dead = true; 11874e4196cbSGregory Neil Shapiro break; 1188193538b7SGregory Neil Shapiro } 118940266059SGregory Neil Shapiro 1190c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 119140266059SGregory Neil Shapiro (void) sm_io_putc(TrafficLogFile, 119240266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' '); 1193c2aa98e2SPeter Wemm } 1194c2aa98e2SPeter Wemm } 119540266059SGregory Neil Shapiro 1196c2aa98e2SPeter Wemm } while (l < end); 11974e4196cbSGregory Neil Shapiro return !dead; 1198c2aa98e2SPeter Wemm } 11994e4196cbSGregory Neil Shapiro 120040266059SGregory Neil Shapiro /* 1201c2aa98e2SPeter Wemm ** XUNLINK -- unlink a file, doing logging as appropriate. 1202c2aa98e2SPeter Wemm ** 1203c2aa98e2SPeter Wemm ** Parameters: 1204c2aa98e2SPeter Wemm ** f -- name of file to unlink. 1205c2aa98e2SPeter Wemm ** 1206c2aa98e2SPeter Wemm ** Returns: 120740266059SGregory Neil Shapiro ** return value of unlink() 1208c2aa98e2SPeter Wemm ** 1209c2aa98e2SPeter Wemm ** Side Effects: 1210c2aa98e2SPeter Wemm ** f is unlinked. 1211c2aa98e2SPeter Wemm */ 1212c2aa98e2SPeter Wemm 121340266059SGregory Neil Shapiro int 1214c2aa98e2SPeter Wemm xunlink(f) 1215c2aa98e2SPeter Wemm char *f; 1216c2aa98e2SPeter Wemm { 1217c2aa98e2SPeter Wemm register int i; 121840266059SGregory Neil Shapiro int save_errno; 1219c2aa98e2SPeter Wemm 1220c2aa98e2SPeter Wemm if (LogLevel > 98) 122140266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "unlink %s", f); 1222c2aa98e2SPeter Wemm 1223c2aa98e2SPeter Wemm i = unlink(f); 122440266059SGregory Neil Shapiro save_errno = errno; 1225c2aa98e2SPeter Wemm if (i < 0 && LogLevel > 97) 122640266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s: unlink-fail %d", 1227c2aa98e2SPeter Wemm f, errno); 122840266059SGregory Neil Shapiro if (i >= 0) 122940266059SGregory Neil Shapiro SYNC_DIR(f, false); 123040266059SGregory Neil Shapiro errno = save_errno; 123140266059SGregory Neil Shapiro return i; 1232c2aa98e2SPeter Wemm } 123340266059SGregory Neil Shapiro /* 1234c2aa98e2SPeter Wemm ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 1235c2aa98e2SPeter Wemm ** 1236c2aa98e2SPeter Wemm ** Parameters: 1237c2aa98e2SPeter Wemm ** buf -- place to put the input line. 1238c2aa98e2SPeter Wemm ** siz -- size of buf. 1239c2aa98e2SPeter Wemm ** fp -- file to read from. 1240c2aa98e2SPeter Wemm ** timeout -- the timeout before error occurs. 1241c2aa98e2SPeter Wemm ** during -- what we are trying to read (for error messages). 1242c2aa98e2SPeter Wemm ** 1243c2aa98e2SPeter Wemm ** Returns: 124440266059SGregory Neil Shapiro ** NULL on error (including timeout). This may also leave 1245c2aa98e2SPeter Wemm ** buf containing a null string. 1246c2aa98e2SPeter Wemm ** buf otherwise. 1247c2aa98e2SPeter Wemm */ 1248c2aa98e2SPeter Wemm 124906f25ae9SGregory Neil Shapiro 1250c2aa98e2SPeter Wemm char * 1251c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during) 1252c2aa98e2SPeter Wemm char *buf; 1253c2aa98e2SPeter Wemm int siz; 125440266059SGregory Neil Shapiro SM_FILE_T *fp; 1255c2aa98e2SPeter Wemm time_t timeout; 1256c2aa98e2SPeter Wemm char *during; 1257c2aa98e2SPeter Wemm { 1258c2aa98e2SPeter Wemm register char *p; 12592e43090eSPeter Wemm int save_errno; 126040266059SGregory Neil Shapiro int io_timeout; 126140266059SGregory Neil Shapiro 126240266059SGregory Neil Shapiro SM_REQUIRE(siz > 0); 126340266059SGregory Neil Shapiro SM_REQUIRE(buf != NULL); 1264c2aa98e2SPeter Wemm 1265c2aa98e2SPeter Wemm if (fp == NULL) 1266c2aa98e2SPeter Wemm { 1267c2aa98e2SPeter Wemm buf[0] = '\0'; 126840266059SGregory Neil Shapiro errno = EBADF; 1269c2aa98e2SPeter Wemm return NULL; 1270c2aa98e2SPeter Wemm } 1271c2aa98e2SPeter Wemm 127240266059SGregory Neil Shapiro /* try to read */ 127340266059SGregory Neil Shapiro p = NULL; 127440266059SGregory Neil Shapiro errno = 0; 127540266059SGregory Neil Shapiro 127640266059SGregory Neil Shapiro /* convert the timeout to sm_io notation */ 127740266059SGregory Neil Shapiro io_timeout = (timeout <= 0) ? SM_TIME_DEFAULT : timeout * 1000; 127840266059SGregory Neil Shapiro while (!sm_io_eof(fp) && !sm_io_error(fp)) 1279c2aa98e2SPeter Wemm { 128040266059SGregory Neil Shapiro errno = 0; 128140266059SGregory Neil Shapiro p = sm_io_fgets(fp, io_timeout, buf, siz); 128240266059SGregory Neil Shapiro if (p == NULL && errno == EAGAIN) 1283c2aa98e2SPeter Wemm { 128440266059SGregory Neil Shapiro /* The sm_io_fgets() call timedout */ 1285c2aa98e2SPeter Wemm if (LogLevel > 1) 1286c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 1287c2aa98e2SPeter Wemm "timeout waiting for input from %.100s during %s", 128840266059SGregory Neil Shapiro CURHOSTNAME, 1289c2aa98e2SPeter Wemm during); 1290c2aa98e2SPeter Wemm buf[0] = '\0'; 1291c2aa98e2SPeter Wemm #if XDEBUG 1292c2aa98e2SPeter Wemm checkfd012(during); 129306f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1294c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 129540266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, 129640266059SGregory Neil Shapiro SM_TIME_DEFAULT, 129740266059SGregory Neil Shapiro "%05d <<< [TIMEOUT]\n", 129840266059SGregory Neil Shapiro (int) CurrentPid); 129940266059SGregory Neil Shapiro errno = ETIMEDOUT; 130006f25ae9SGregory Neil Shapiro return NULL; 1301c2aa98e2SPeter Wemm } 1302c2aa98e2SPeter Wemm if (p != NULL || errno != EINTR) 1303c2aa98e2SPeter Wemm break; 130440266059SGregory Neil Shapiro (void) sm_io_clearerr(fp); 1305c2aa98e2SPeter Wemm } 13062e43090eSPeter Wemm save_errno = errno; 1307c2aa98e2SPeter Wemm 1308c2aa98e2SPeter Wemm /* clean up the books and exit */ 1309c2aa98e2SPeter Wemm LineNumber++; 1310c2aa98e2SPeter Wemm if (p == NULL) 1311c2aa98e2SPeter Wemm { 1312c2aa98e2SPeter Wemm buf[0] = '\0'; 1313c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 131440266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 131540266059SGregory Neil Shapiro "%05d <<< [EOF]\n", 131640266059SGregory Neil Shapiro (int) CurrentPid); 13172e43090eSPeter Wemm errno = save_errno; 131806f25ae9SGregory Neil Shapiro return NULL; 1319c2aa98e2SPeter Wemm } 1320c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 132140266059SGregory Neil Shapiro (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 132240266059SGregory Neil Shapiro "%05d <<< %s", (int) CurrentPid, buf); 1323c2aa98e2SPeter Wemm if (SevenBitInput) 1324c2aa98e2SPeter Wemm { 1325c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1326c2aa98e2SPeter Wemm *p &= ~0200; 1327c2aa98e2SPeter Wemm } 1328c2aa98e2SPeter Wemm else if (!HasEightBits) 1329c2aa98e2SPeter Wemm { 1330c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1331c2aa98e2SPeter Wemm { 1332c2aa98e2SPeter Wemm if (bitset(0200, *p)) 1333c2aa98e2SPeter Wemm { 133440266059SGregory Neil Shapiro HasEightBits = true; 1335c2aa98e2SPeter Wemm break; 1336c2aa98e2SPeter Wemm } 1337c2aa98e2SPeter Wemm } 1338c2aa98e2SPeter Wemm } 133906f25ae9SGregory Neil Shapiro return buf; 1340c2aa98e2SPeter Wemm } 13418774250cSGregory Neil Shapiro /* 134240266059SGregory Neil Shapiro ** FGETFOLDED -- like fgets, but knows about folded lines. 1343c2aa98e2SPeter Wemm ** 1344c2aa98e2SPeter Wemm ** Parameters: 1345c2aa98e2SPeter Wemm ** buf -- place to put result. 1346c2aa98e2SPeter Wemm ** n -- bytes available. 1347c2aa98e2SPeter Wemm ** f -- file to read from. 1348c2aa98e2SPeter Wemm ** 1349c2aa98e2SPeter Wemm ** Returns: 135040266059SGregory Neil Shapiro ** input line(s) on success, NULL on error or SM_IO_EOF. 1351c2aa98e2SPeter Wemm ** This will normally be buf -- unless the line is too 135240266059SGregory Neil Shapiro ** long, when it will be sm_malloc_x()ed. 1353c2aa98e2SPeter Wemm ** 1354c2aa98e2SPeter Wemm ** Side Effects: 1355c2aa98e2SPeter Wemm ** buf gets lines from f, with continuation lines (lines 1356c2aa98e2SPeter Wemm ** with leading white space) appended. CRLF's are mapped 1357c2aa98e2SPeter Wemm ** into single newlines. Any trailing NL is stripped. 1358c2aa98e2SPeter Wemm */ 1359c2aa98e2SPeter Wemm 1360c2aa98e2SPeter Wemm char * 1361c2aa98e2SPeter Wemm fgetfolded(buf, n, f) 1362c2aa98e2SPeter Wemm char *buf; 1363c2aa98e2SPeter Wemm register int n; 136440266059SGregory Neil Shapiro SM_FILE_T *f; 1365c2aa98e2SPeter Wemm { 1366c2aa98e2SPeter Wemm register char *p = buf; 1367c2aa98e2SPeter Wemm char *bp = buf; 1368c2aa98e2SPeter Wemm register int i; 1369c2aa98e2SPeter Wemm 137040266059SGregory Neil Shapiro SM_REQUIRE(n > 0); 137140266059SGregory Neil Shapiro SM_REQUIRE(buf != NULL); 137240266059SGregory Neil Shapiro if (f == NULL) 137340266059SGregory Neil Shapiro { 137440266059SGregory Neil Shapiro buf[0] = '\0'; 137540266059SGregory Neil Shapiro errno = EBADF; 137640266059SGregory Neil Shapiro return NULL; 137740266059SGregory Neil Shapiro } 137840266059SGregory Neil Shapiro 1379c2aa98e2SPeter Wemm n--; 138040266059SGregory Neil Shapiro while ((i = sm_io_getc(f, SM_TIME_DEFAULT)) != SM_IO_EOF) 1381c2aa98e2SPeter Wemm { 1382c2aa98e2SPeter Wemm if (i == '\r') 1383c2aa98e2SPeter Wemm { 138440266059SGregory Neil Shapiro i = sm_io_getc(f, SM_TIME_DEFAULT); 1385c2aa98e2SPeter Wemm if (i != '\n') 1386c2aa98e2SPeter Wemm { 138740266059SGregory Neil Shapiro if (i != SM_IO_EOF) 138840266059SGregory Neil Shapiro (void) sm_io_ungetc(f, SM_TIME_DEFAULT, 138940266059SGregory Neil Shapiro i); 1390c2aa98e2SPeter Wemm i = '\r'; 1391c2aa98e2SPeter Wemm } 1392c2aa98e2SPeter Wemm } 1393c2aa98e2SPeter Wemm if (--n <= 0) 1394c2aa98e2SPeter Wemm { 1395c2aa98e2SPeter Wemm /* allocate new space */ 1396c2aa98e2SPeter Wemm char *nbp; 1397c2aa98e2SPeter Wemm int nn; 1398c2aa98e2SPeter Wemm 1399c2aa98e2SPeter Wemm nn = (p - bp); 1400c2aa98e2SPeter Wemm if (nn < MEMCHUNKSIZE) 1401c2aa98e2SPeter Wemm nn *= 2; 1402c2aa98e2SPeter Wemm else 1403c2aa98e2SPeter Wemm nn += MEMCHUNKSIZE; 140440266059SGregory Neil Shapiro nbp = sm_malloc_x(nn); 140506f25ae9SGregory Neil Shapiro memmove(nbp, bp, p - bp); 1406c2aa98e2SPeter Wemm p = &nbp[p - bp]; 1407c2aa98e2SPeter Wemm if (bp != buf) 14088774250cSGregory Neil Shapiro sm_free(bp); 1409c2aa98e2SPeter Wemm bp = nbp; 1410c2aa98e2SPeter Wemm n = nn - (p - bp); 1411c2aa98e2SPeter Wemm } 1412c2aa98e2SPeter Wemm *p++ = i; 1413c2aa98e2SPeter Wemm if (i == '\n') 1414c2aa98e2SPeter Wemm { 1415c2aa98e2SPeter Wemm LineNumber++; 141640266059SGregory Neil Shapiro i = sm_io_getc(f, SM_TIME_DEFAULT); 141740266059SGregory Neil Shapiro if (i != SM_IO_EOF) 141840266059SGregory Neil Shapiro (void) sm_io_ungetc(f, SM_TIME_DEFAULT, i); 1419c2aa98e2SPeter Wemm if (i != ' ' && i != '\t') 1420c2aa98e2SPeter Wemm break; 1421c2aa98e2SPeter Wemm } 1422c2aa98e2SPeter Wemm } 1423c2aa98e2SPeter Wemm if (p == bp) 142406f25ae9SGregory Neil Shapiro return NULL; 1425c2aa98e2SPeter Wemm if (p[-1] == '\n') 1426c2aa98e2SPeter Wemm p--; 1427c2aa98e2SPeter Wemm *p = '\0'; 142806f25ae9SGregory Neil Shapiro return bp; 1429c2aa98e2SPeter Wemm } 143040266059SGregory Neil Shapiro /* 1431c2aa98e2SPeter Wemm ** CURTIME -- return current time. 1432c2aa98e2SPeter Wemm ** 1433c2aa98e2SPeter Wemm ** Parameters: 1434c2aa98e2SPeter Wemm ** none. 1435c2aa98e2SPeter Wemm ** 1436c2aa98e2SPeter Wemm ** Returns: 1437c2aa98e2SPeter Wemm ** the current time. 1438c2aa98e2SPeter Wemm */ 1439c2aa98e2SPeter Wemm 1440c2aa98e2SPeter Wemm time_t 1441c2aa98e2SPeter Wemm curtime() 1442c2aa98e2SPeter Wemm { 1443c2aa98e2SPeter Wemm auto time_t t; 1444c2aa98e2SPeter Wemm 1445c2aa98e2SPeter Wemm (void) time(&t); 144606f25ae9SGregory Neil Shapiro return t; 1447c2aa98e2SPeter Wemm } 144840266059SGregory Neil Shapiro /* 1449c2aa98e2SPeter Wemm ** ATOBOOL -- convert a string representation to boolean. 1450c2aa98e2SPeter Wemm ** 145140266059SGregory Neil Shapiro ** Defaults to false 1452c2aa98e2SPeter Wemm ** 1453c2aa98e2SPeter Wemm ** Parameters: 145440266059SGregory Neil Shapiro ** s -- string to convert. Takes "tTyY", empty, and NULL as true, 1455c2aa98e2SPeter Wemm ** others as false. 1456c2aa98e2SPeter Wemm ** 1457c2aa98e2SPeter Wemm ** Returns: 1458c2aa98e2SPeter Wemm ** A boolean representation of the string. 1459c2aa98e2SPeter Wemm */ 1460c2aa98e2SPeter Wemm 1461c2aa98e2SPeter Wemm bool 1462c2aa98e2SPeter Wemm atobool(s) 1463c2aa98e2SPeter Wemm register char *s; 1464c2aa98e2SPeter Wemm { 1465c2aa98e2SPeter Wemm if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 146640266059SGregory Neil Shapiro return true; 146740266059SGregory Neil Shapiro return false; 1468c2aa98e2SPeter Wemm } 146940266059SGregory Neil Shapiro /* 1470c2aa98e2SPeter Wemm ** ATOOCT -- convert a string representation to octal. 1471c2aa98e2SPeter Wemm ** 1472c2aa98e2SPeter Wemm ** Parameters: 1473c2aa98e2SPeter Wemm ** s -- string to convert. 1474c2aa98e2SPeter Wemm ** 1475c2aa98e2SPeter Wemm ** Returns: 1476c2aa98e2SPeter Wemm ** An integer representing the string interpreted as an 1477c2aa98e2SPeter Wemm ** octal number. 1478c2aa98e2SPeter Wemm */ 1479c2aa98e2SPeter Wemm 1480c2aa98e2SPeter Wemm int 1481c2aa98e2SPeter Wemm atooct(s) 1482c2aa98e2SPeter Wemm register char *s; 1483c2aa98e2SPeter Wemm { 1484c2aa98e2SPeter Wemm register int i = 0; 1485c2aa98e2SPeter Wemm 1486c2aa98e2SPeter Wemm while (*s >= '0' && *s <= '7') 1487c2aa98e2SPeter Wemm i = (i << 3) | (*s++ - '0'); 148806f25ae9SGregory Neil Shapiro return i; 1489c2aa98e2SPeter Wemm } 149040266059SGregory Neil Shapiro /* 1491c2aa98e2SPeter Wemm ** BITINTERSECT -- tell if two bitmaps intersect 1492c2aa98e2SPeter Wemm ** 1493c2aa98e2SPeter Wemm ** Parameters: 1494c2aa98e2SPeter Wemm ** a, b -- the bitmaps in question 1495c2aa98e2SPeter Wemm ** 1496c2aa98e2SPeter Wemm ** Returns: 149740266059SGregory Neil Shapiro ** true if they have a non-null intersection 149840266059SGregory Neil Shapiro ** false otherwise 1499c2aa98e2SPeter Wemm */ 1500c2aa98e2SPeter Wemm 1501c2aa98e2SPeter Wemm bool 1502c2aa98e2SPeter Wemm bitintersect(a, b) 150306f25ae9SGregory Neil Shapiro BITMAP256 a; 150406f25ae9SGregory Neil Shapiro BITMAP256 b; 1505c2aa98e2SPeter Wemm { 1506c2aa98e2SPeter Wemm int i; 1507c2aa98e2SPeter Wemm 1508c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1509193538b7SGregory Neil Shapiro { 1510c2aa98e2SPeter Wemm if ((a[i] & b[i]) != 0) 151140266059SGregory Neil Shapiro return true; 1512193538b7SGregory Neil Shapiro } 151340266059SGregory Neil Shapiro return false; 1514c2aa98e2SPeter Wemm } 151540266059SGregory Neil Shapiro /* 1516c2aa98e2SPeter Wemm ** BITZEROP -- tell if a bitmap is all zero 1517c2aa98e2SPeter Wemm ** 1518c2aa98e2SPeter Wemm ** Parameters: 1519c2aa98e2SPeter Wemm ** map -- the bit map to check 1520c2aa98e2SPeter Wemm ** 1521c2aa98e2SPeter Wemm ** Returns: 152240266059SGregory Neil Shapiro ** true if map is all zero. 152340266059SGregory Neil Shapiro ** false if there are any bits set in map. 1524c2aa98e2SPeter Wemm */ 1525c2aa98e2SPeter Wemm 1526c2aa98e2SPeter Wemm bool 1527c2aa98e2SPeter Wemm bitzerop(map) 152806f25ae9SGregory Neil Shapiro BITMAP256 map; 1529c2aa98e2SPeter Wemm { 1530c2aa98e2SPeter Wemm int i; 1531c2aa98e2SPeter Wemm 1532c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1533193538b7SGregory Neil Shapiro { 1534c2aa98e2SPeter Wemm if (map[i] != 0) 153540266059SGregory Neil Shapiro return false; 1536193538b7SGregory Neil Shapiro } 153740266059SGregory Neil Shapiro return true; 1538c2aa98e2SPeter Wemm } 153940266059SGregory Neil Shapiro /* 1540c2aa98e2SPeter Wemm ** STRCONTAINEDIN -- tell if one string is contained in another 1541c2aa98e2SPeter Wemm ** 1542c2aa98e2SPeter Wemm ** Parameters: 154340266059SGregory Neil Shapiro ** icase -- ignore case? 1544c2aa98e2SPeter Wemm ** a -- possible substring. 1545c2aa98e2SPeter Wemm ** b -- possible superstring. 1546c2aa98e2SPeter Wemm ** 1547c2aa98e2SPeter Wemm ** Returns: 154840266059SGregory Neil Shapiro ** true if a is contained in b (case insensitive). 154940266059SGregory Neil Shapiro ** false otherwise. 1550c2aa98e2SPeter Wemm */ 1551c2aa98e2SPeter Wemm 1552c2aa98e2SPeter Wemm bool 155340266059SGregory Neil Shapiro strcontainedin(icase, a, b) 155440266059SGregory Neil Shapiro bool icase; 1555c2aa98e2SPeter Wemm register char *a; 1556c2aa98e2SPeter Wemm register char *b; 1557c2aa98e2SPeter Wemm { 1558c2aa98e2SPeter Wemm int la; 1559c2aa98e2SPeter Wemm int lb; 1560c2aa98e2SPeter Wemm int c; 1561c2aa98e2SPeter Wemm 1562c2aa98e2SPeter Wemm la = strlen(a); 1563c2aa98e2SPeter Wemm lb = strlen(b); 1564c2aa98e2SPeter Wemm c = *a; 156540266059SGregory Neil Shapiro if (icase && isascii(c) && isupper(c)) 1566c2aa98e2SPeter Wemm c = tolower(c); 1567c2aa98e2SPeter Wemm for (; lb-- >= la; b++) 1568c2aa98e2SPeter Wemm { 156940266059SGregory Neil Shapiro if (icase) 157040266059SGregory Neil Shapiro { 157140266059SGregory Neil Shapiro if (*b != c && 157240266059SGregory Neil Shapiro isascii(*b) && isupper(*b) && tolower(*b) != c) 1573c2aa98e2SPeter Wemm continue; 157440266059SGregory Neil Shapiro if (sm_strncasecmp(a, b, la) == 0) 157540266059SGregory Neil Shapiro return true; 1576c2aa98e2SPeter Wemm } 157740266059SGregory Neil Shapiro else 157840266059SGregory Neil Shapiro { 157940266059SGregory Neil Shapiro if (*b != c) 158040266059SGregory Neil Shapiro continue; 158140266059SGregory Neil Shapiro if (strncmp(a, b, la) == 0) 158240266059SGregory Neil Shapiro return true; 1583c2aa98e2SPeter Wemm } 158440266059SGregory Neil Shapiro } 158540266059SGregory Neil Shapiro return false; 158640266059SGregory Neil Shapiro } 158740266059SGregory Neil Shapiro /* 1588c2aa98e2SPeter Wemm ** CHECKFD012 -- check low numbered file descriptors 1589c2aa98e2SPeter Wemm ** 1590c2aa98e2SPeter Wemm ** File descriptors 0, 1, and 2 should be open at all times. 1591c2aa98e2SPeter Wemm ** This routine verifies that, and fixes it if not true. 1592c2aa98e2SPeter Wemm ** 1593c2aa98e2SPeter Wemm ** Parameters: 1594c2aa98e2SPeter Wemm ** where -- a tag printed if the assertion failed 1595c2aa98e2SPeter Wemm ** 1596c2aa98e2SPeter Wemm ** Returns: 1597c2aa98e2SPeter Wemm ** none 1598c2aa98e2SPeter Wemm */ 1599c2aa98e2SPeter Wemm 1600c2aa98e2SPeter Wemm void 1601c2aa98e2SPeter Wemm checkfd012(where) 1602c2aa98e2SPeter Wemm char *where; 1603c2aa98e2SPeter Wemm { 1604c2aa98e2SPeter Wemm #if XDEBUG 1605c2aa98e2SPeter Wemm register int i; 1606c2aa98e2SPeter Wemm 1607c2aa98e2SPeter Wemm for (i = 0; i < 3; i++) 1608c2aa98e2SPeter Wemm fill_fd(i, where); 1609c2aa98e2SPeter Wemm #endif /* XDEBUG */ 1610c2aa98e2SPeter Wemm } 161140266059SGregory Neil Shapiro /* 1612c2aa98e2SPeter Wemm ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1613c2aa98e2SPeter Wemm ** 1614c2aa98e2SPeter Wemm ** Parameters: 1615c2aa98e2SPeter Wemm ** fd -- file descriptor to check. 1616c2aa98e2SPeter Wemm ** where -- tag to print on failure. 1617c2aa98e2SPeter Wemm ** 1618c2aa98e2SPeter Wemm ** Returns: 1619c2aa98e2SPeter Wemm ** none. 1620c2aa98e2SPeter Wemm */ 1621c2aa98e2SPeter Wemm 1622c2aa98e2SPeter Wemm void 1623c2aa98e2SPeter Wemm checkfdopen(fd, where) 1624c2aa98e2SPeter Wemm int fd; 1625c2aa98e2SPeter Wemm char *where; 1626c2aa98e2SPeter Wemm { 1627c2aa98e2SPeter Wemm #if XDEBUG 1628c2aa98e2SPeter Wemm struct stat st; 1629c2aa98e2SPeter Wemm 1630c2aa98e2SPeter Wemm if (fstat(fd, &st) < 0 && errno == EBADF) 1631c2aa98e2SPeter Wemm { 1632c2aa98e2SPeter Wemm syserr("checkfdopen(%d): %s not open as expected!", fd, where); 163340266059SGregory Neil Shapiro printopenfds(true); 1634c2aa98e2SPeter Wemm } 163506f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1636c2aa98e2SPeter Wemm } 163740266059SGregory Neil Shapiro /* 1638c2aa98e2SPeter Wemm ** CHECKFDS -- check for new or missing file descriptors 1639c2aa98e2SPeter Wemm ** 1640c2aa98e2SPeter Wemm ** Parameters: 1641c2aa98e2SPeter Wemm ** where -- tag for printing. If null, take a base line. 1642c2aa98e2SPeter Wemm ** 1643c2aa98e2SPeter Wemm ** Returns: 1644c2aa98e2SPeter Wemm ** none 1645c2aa98e2SPeter Wemm ** 1646c2aa98e2SPeter Wemm ** Side Effects: 1647c2aa98e2SPeter Wemm ** If where is set, shows changes since the last call. 1648c2aa98e2SPeter Wemm */ 1649c2aa98e2SPeter Wemm 1650c2aa98e2SPeter Wemm void 1651c2aa98e2SPeter Wemm checkfds(where) 1652c2aa98e2SPeter Wemm char *where; 1653c2aa98e2SPeter Wemm { 1654c2aa98e2SPeter Wemm int maxfd; 1655c2aa98e2SPeter Wemm register int fd; 165640266059SGregory Neil Shapiro bool printhdr = true; 1657c2aa98e2SPeter Wemm int save_errno = errno; 165806f25ae9SGregory Neil Shapiro static BITMAP256 baseline; 1659c2aa98e2SPeter Wemm extern int DtableSize; 1660c2aa98e2SPeter Wemm 1661193538b7SGregory Neil Shapiro if (DtableSize > BITMAPBITS) 1662193538b7SGregory Neil Shapiro maxfd = BITMAPBITS; 1663c2aa98e2SPeter Wemm else 1664c2aa98e2SPeter Wemm maxfd = DtableSize; 1665c2aa98e2SPeter Wemm if (where == NULL) 1666c2aa98e2SPeter Wemm clrbitmap(baseline); 1667c2aa98e2SPeter Wemm 1668c2aa98e2SPeter Wemm for (fd = 0; fd < maxfd; fd++) 1669c2aa98e2SPeter Wemm { 1670c2aa98e2SPeter Wemm struct stat stbuf; 1671c2aa98e2SPeter Wemm 1672c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 1673c2aa98e2SPeter Wemm { 1674c2aa98e2SPeter Wemm if (!bitnset(fd, baseline)) 1675c2aa98e2SPeter Wemm continue; 1676c2aa98e2SPeter Wemm clrbitn(fd, baseline); 1677c2aa98e2SPeter Wemm } 1678c2aa98e2SPeter Wemm else if (!bitnset(fd, baseline)) 1679c2aa98e2SPeter Wemm setbitn(fd, baseline); 1680c2aa98e2SPeter Wemm else 1681c2aa98e2SPeter Wemm continue; 1682c2aa98e2SPeter Wemm 1683c2aa98e2SPeter Wemm /* file state has changed */ 1684c2aa98e2SPeter Wemm if (where == NULL) 1685c2aa98e2SPeter Wemm continue; 1686c2aa98e2SPeter Wemm if (printhdr) 1687c2aa98e2SPeter Wemm { 1688c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1689c2aa98e2SPeter Wemm "%s: changed fds:", 1690c2aa98e2SPeter Wemm where); 169140266059SGregory Neil Shapiro printhdr = false; 1692c2aa98e2SPeter Wemm } 169340266059SGregory Neil Shapiro dumpfd(fd, true, true); 1694c2aa98e2SPeter Wemm } 1695c2aa98e2SPeter Wemm errno = save_errno; 1696c2aa98e2SPeter Wemm } 169740266059SGregory Neil Shapiro /* 1698c2aa98e2SPeter Wemm ** PRINTOPENFDS -- print the open file descriptors (for debugging) 1699c2aa98e2SPeter Wemm ** 1700c2aa98e2SPeter Wemm ** Parameters: 1701c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog; otherwise 1702c2aa98e2SPeter Wemm ** print for debugging. 1703c2aa98e2SPeter Wemm ** 1704c2aa98e2SPeter Wemm ** Returns: 1705c2aa98e2SPeter Wemm ** none. 1706c2aa98e2SPeter Wemm */ 1707c2aa98e2SPeter Wemm 170806f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 1709c2aa98e2SPeter Wemm # include <arpa/inet.h> 171006f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 1711c2aa98e2SPeter Wemm 1712c2aa98e2SPeter Wemm void 1713c2aa98e2SPeter Wemm printopenfds(logit) 1714c2aa98e2SPeter Wemm bool logit; 1715c2aa98e2SPeter Wemm { 1716c2aa98e2SPeter Wemm register int fd; 1717c2aa98e2SPeter Wemm extern int DtableSize; 1718c2aa98e2SPeter Wemm 1719c2aa98e2SPeter Wemm for (fd = 0; fd < DtableSize; fd++) 172040266059SGregory Neil Shapiro dumpfd(fd, false, logit); 1721c2aa98e2SPeter Wemm } 172240266059SGregory Neil Shapiro /* 1723c2aa98e2SPeter Wemm ** DUMPFD -- dump a file descriptor 1724c2aa98e2SPeter Wemm ** 1725c2aa98e2SPeter Wemm ** Parameters: 1726c2aa98e2SPeter Wemm ** fd -- the file descriptor to dump. 1727c2aa98e2SPeter Wemm ** printclosed -- if set, print a notification even if 1728c2aa98e2SPeter Wemm ** it is closed; otherwise print nothing. 1729e92d3f3fSGregory Neil Shapiro ** logit -- if set, use sm_syslog instead of sm_dprintf() 173040266059SGregory Neil Shapiro ** 173140266059SGregory Neil Shapiro ** Returns: 173240266059SGregory Neil Shapiro ** none. 1733c2aa98e2SPeter Wemm */ 1734c2aa98e2SPeter Wemm 1735c2aa98e2SPeter Wemm void 1736c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit) 1737c2aa98e2SPeter Wemm int fd; 1738c2aa98e2SPeter Wemm bool printclosed; 1739c2aa98e2SPeter Wemm bool logit; 1740c2aa98e2SPeter Wemm { 1741c2aa98e2SPeter Wemm register char *p; 1742c2aa98e2SPeter Wemm char *hp; 1743c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1744c2aa98e2SPeter Wemm SOCKADDR sa; 174506f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1746c2aa98e2SPeter Wemm auto SOCKADDR_LEN_T slen; 1747c2aa98e2SPeter Wemm int i; 1748c2aa98e2SPeter Wemm #if STAT64 > 0 1749c2aa98e2SPeter Wemm struct stat64 st; 175006f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1751c2aa98e2SPeter Wemm struct stat st; 175206f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1753c2aa98e2SPeter Wemm char buf[200]; 1754c2aa98e2SPeter Wemm 1755c2aa98e2SPeter Wemm p = buf; 175640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 1757c2aa98e2SPeter Wemm p += strlen(p); 1758c2aa98e2SPeter Wemm 1759c2aa98e2SPeter Wemm if ( 1760c2aa98e2SPeter Wemm #if STAT64 > 0 1761c2aa98e2SPeter Wemm fstat64(fd, &st) 176206f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1763c2aa98e2SPeter Wemm fstat(fd, &st) 176406f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1765c2aa98e2SPeter Wemm < 0) 1766c2aa98e2SPeter Wemm { 1767c2aa98e2SPeter Wemm if (errno != EBADF) 1768c2aa98e2SPeter Wemm { 176940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 177040266059SGregory Neil Shapiro "CANNOT STAT (%s)", 177140266059SGregory Neil Shapiro sm_errstring(errno)); 1772c2aa98e2SPeter Wemm goto printit; 1773c2aa98e2SPeter Wemm } 1774c2aa98e2SPeter Wemm else if (printclosed) 1775c2aa98e2SPeter Wemm { 177640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "CLOSED"); 1777c2aa98e2SPeter Wemm goto printit; 1778c2aa98e2SPeter Wemm } 1779c2aa98e2SPeter Wemm return; 1780c2aa98e2SPeter Wemm } 1781c2aa98e2SPeter Wemm 1782605302a5SGregory Neil Shapiro i = fcntl(fd, F_GETFL, 0); 1783c2aa98e2SPeter Wemm if (i != -1) 1784c2aa98e2SPeter Wemm { 178540266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 1786c2aa98e2SPeter Wemm p += strlen(p); 1787c2aa98e2SPeter Wemm } 1788c2aa98e2SPeter Wemm 178940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "mode=%o: ", 179040266059SGregory Neil Shapiro (int) st.st_mode); 1791c2aa98e2SPeter Wemm p += strlen(p); 1792c2aa98e2SPeter Wemm switch (st.st_mode & S_IFMT) 1793c2aa98e2SPeter Wemm { 1794c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1795c2aa98e2SPeter Wemm case S_IFSOCK: 179640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "SOCK "); 1797c2aa98e2SPeter Wemm p += strlen(p); 179806f25ae9SGregory Neil Shapiro memset(&sa, '\0', sizeof sa); 1799c2aa98e2SPeter Wemm slen = sizeof sa; 1800c2aa98e2SPeter Wemm if (getsockname(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 p += strlen(p); 182640266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "->"); 1827c2aa98e2SPeter Wemm p += strlen(p); 1828c2aa98e2SPeter Wemm slen = sizeof sa; 1829c2aa98e2SPeter Wemm if (getpeername(fd, &sa.sa, &slen) < 0) 183040266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 183140266059SGregory Neil Shapiro sm_errstring(errno)); 1832c2aa98e2SPeter Wemm else 1833c2aa98e2SPeter Wemm { 1834c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 183506f25ae9SGregory Neil Shapiro if (hp == NULL) 183606f25ae9SGregory Neil Shapiro { 183706f25ae9SGregory Neil Shapiro /* EMPTY */ 183806f25ae9SGregory Neil Shapiro /* do nothing */ 183906f25ae9SGregory Neil Shapiro } 184006f25ae9SGregory Neil Shapiro # if NETINET 184106f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 184240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 184340266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin.sin_port)); 184406f25ae9SGregory Neil Shapiro # endif /* NETINET */ 184506f25ae9SGregory Neil Shapiro # if NETINET6 184606f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 184740266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 184840266059SGregory Neil Shapiro "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 184906f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1850c2aa98e2SPeter Wemm else 185140266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 185240266059SGregory Neil Shapiro "%s", hp); 1853c2aa98e2SPeter Wemm } 1854c2aa98e2SPeter Wemm break; 185506f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1856c2aa98e2SPeter Wemm 1857c2aa98e2SPeter Wemm case S_IFCHR: 185840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "CHR: "); 1859c2aa98e2SPeter Wemm p += strlen(p); 1860c2aa98e2SPeter Wemm goto defprint; 1861c2aa98e2SPeter Wemm 186240266059SGregory Neil Shapiro #ifdef S_IFBLK 1863c2aa98e2SPeter Wemm case S_IFBLK: 186440266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "BLK: "); 1865c2aa98e2SPeter Wemm p += strlen(p); 1866c2aa98e2SPeter Wemm goto defprint; 186740266059SGregory Neil Shapiro #endif /* S_IFBLK */ 1868c2aa98e2SPeter Wemm 1869c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 1870c2aa98e2SPeter Wemm case S_IFIFO: 187140266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "FIFO: "); 1872c2aa98e2SPeter Wemm p += strlen(p); 1873c2aa98e2SPeter Wemm goto defprint; 187406f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 1875c2aa98e2SPeter Wemm 1876c2aa98e2SPeter Wemm #ifdef S_IFDIR 1877c2aa98e2SPeter Wemm case S_IFDIR: 187840266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "DIR: "); 1879c2aa98e2SPeter Wemm p += strlen(p); 1880c2aa98e2SPeter Wemm goto defprint; 188106f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */ 1882c2aa98e2SPeter Wemm 1883c2aa98e2SPeter Wemm #ifdef S_IFLNK 1884c2aa98e2SPeter Wemm case S_IFLNK: 188540266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "LNK: "); 1886c2aa98e2SPeter Wemm p += strlen(p); 1887c2aa98e2SPeter Wemm goto defprint; 188806f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */ 1889c2aa98e2SPeter Wemm 1890c2aa98e2SPeter Wemm default: 1891c2aa98e2SPeter Wemm defprint: 189240266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), 189340266059SGregory Neil Shapiro "dev=%d/%d, ino=%llu, nlink=%d, u/gid=%d/%d, ", 1894c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 189540266059SGregory Neil Shapiro (ULONGLONG_T) st.st_ino, 189606f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 189706f25ae9SGregory Neil Shapiro (int) st.st_gid); 189840266059SGregory Neil Shapiro p += strlen(p); 189940266059SGregory Neil Shapiro (void) sm_snprintf(p, SPACELEFT(buf, p), "size=%llu", 190040266059SGregory Neil Shapiro (ULONGLONG_T) st.st_size); 1901c2aa98e2SPeter Wemm break; 1902c2aa98e2SPeter Wemm } 1903c2aa98e2SPeter Wemm 1904c2aa98e2SPeter Wemm printit: 1905c2aa98e2SPeter Wemm if (logit) 1906c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 1907c2aa98e2SPeter Wemm "%.800s", buf); 1908c2aa98e2SPeter Wemm else 1909e92d3f3fSGregory Neil Shapiro sm_dprintf("%s\n", buf); 1910c2aa98e2SPeter Wemm } 191140266059SGregory Neil Shapiro /* 1912c2aa98e2SPeter Wemm ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1913c2aa98e2SPeter Wemm ** 1914c2aa98e2SPeter Wemm ** Parameters: 1915c2aa98e2SPeter Wemm ** host -- the host to shorten (stripped in place). 1916c2aa98e2SPeter Wemm ** 1917c2aa98e2SPeter Wemm ** Returns: 191840266059SGregory Neil Shapiro ** place where string was truncated, NULL if not truncated. 1919c2aa98e2SPeter Wemm */ 1920c2aa98e2SPeter Wemm 1921602a2b1bSGregory Neil Shapiro char * 1922c2aa98e2SPeter Wemm shorten_hostname(host) 1923c2aa98e2SPeter Wemm char host[]; 1924c2aa98e2SPeter Wemm { 1925c2aa98e2SPeter Wemm register char *p; 1926c2aa98e2SPeter Wemm char *mydom; 1927c2aa98e2SPeter Wemm int i; 192840266059SGregory Neil Shapiro bool canon = false; 1929c2aa98e2SPeter Wemm 1930c2aa98e2SPeter Wemm /* strip off final dot */ 193140266059SGregory Neil Shapiro i = strlen(host); 193240266059SGregory Neil Shapiro p = &host[(i == 0) ? 0 : i - 1]; 1933c2aa98e2SPeter Wemm if (*p == '.') 1934c2aa98e2SPeter Wemm { 1935c2aa98e2SPeter Wemm *p = '\0'; 193640266059SGregory Neil Shapiro canon = true; 1937c2aa98e2SPeter Wemm } 1938c2aa98e2SPeter Wemm 1939c2aa98e2SPeter Wemm /* see if there is any domain at all -- if not, we are done */ 1940c2aa98e2SPeter Wemm p = strchr(host, '.'); 1941c2aa98e2SPeter Wemm if (p == NULL) 1942602a2b1bSGregory Neil Shapiro return NULL; 1943c2aa98e2SPeter Wemm 1944c2aa98e2SPeter Wemm /* yes, we have a domain -- see if it looks like us */ 1945c2aa98e2SPeter Wemm mydom = macvalue('m', CurEnv); 1946c2aa98e2SPeter Wemm if (mydom == NULL) 1947c2aa98e2SPeter Wemm mydom = ""; 1948c2aa98e2SPeter Wemm i = strlen(++p); 194940266059SGregory Neil Shapiro if ((canon ? sm_strcasecmp(p, mydom) 195040266059SGregory Neil Shapiro : sm_strncasecmp(p, mydom, i)) == 0 && 1951c2aa98e2SPeter Wemm (mydom[i] == '.' || mydom[i] == '\0')) 1952602a2b1bSGregory Neil Shapiro { 1953c2aa98e2SPeter Wemm *--p = '\0'; 1954602a2b1bSGregory Neil Shapiro return p; 1955602a2b1bSGregory Neil Shapiro } 1956602a2b1bSGregory Neil Shapiro return NULL; 1957c2aa98e2SPeter Wemm } 195840266059SGregory Neil Shapiro /* 1959c2aa98e2SPeter Wemm ** PROG_OPEN -- open a program for reading 1960c2aa98e2SPeter Wemm ** 1961c2aa98e2SPeter Wemm ** Parameters: 1962c2aa98e2SPeter Wemm ** argv -- the argument list. 1963c2aa98e2SPeter Wemm ** pfd -- pointer to a place to store the file descriptor. 1964c2aa98e2SPeter Wemm ** e -- the current envelope. 1965c2aa98e2SPeter Wemm ** 1966c2aa98e2SPeter Wemm ** Returns: 1967c2aa98e2SPeter Wemm ** pid of the process -- -1 if it failed. 1968c2aa98e2SPeter Wemm */ 1969c2aa98e2SPeter Wemm 19708774250cSGregory Neil Shapiro pid_t 1971c2aa98e2SPeter Wemm prog_open(argv, pfd, e) 1972c2aa98e2SPeter Wemm char **argv; 1973c2aa98e2SPeter Wemm int *pfd; 1974c2aa98e2SPeter Wemm ENVELOPE *e; 1975c2aa98e2SPeter Wemm { 19768774250cSGregory Neil Shapiro pid_t pid; 197706f25ae9SGregory Neil Shapiro int save_errno; 197840266059SGregory Neil Shapiro int sff; 197940266059SGregory Neil Shapiro int ret; 1980c2aa98e2SPeter Wemm int fdv[2]; 1981c2aa98e2SPeter Wemm char *p, *q; 198294c01205SGregory Neil Shapiro char buf[MAXPATHLEN]; 1983c2aa98e2SPeter Wemm extern int DtableSize; 1984c2aa98e2SPeter Wemm 1985c2aa98e2SPeter Wemm if (pipe(fdv) < 0) 1986c2aa98e2SPeter Wemm { 1987c2aa98e2SPeter Wemm syserr("%s: cannot create pipe for stdout", argv[0]); 1988c2aa98e2SPeter Wemm return -1; 1989c2aa98e2SPeter Wemm } 1990c2aa98e2SPeter Wemm pid = fork(); 1991c2aa98e2SPeter Wemm if (pid < 0) 1992c2aa98e2SPeter Wemm { 1993c2aa98e2SPeter Wemm syserr("%s: cannot fork", argv[0]); 199406f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 199506f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1996c2aa98e2SPeter Wemm return -1; 1997c2aa98e2SPeter Wemm } 1998c2aa98e2SPeter Wemm if (pid > 0) 1999c2aa98e2SPeter Wemm { 2000c2aa98e2SPeter Wemm /* parent */ 200106f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 2002c2aa98e2SPeter Wemm *pfd = fdv[0]; 2003c2aa98e2SPeter Wemm return pid; 2004c2aa98e2SPeter Wemm } 2005c2aa98e2SPeter Wemm 20068774250cSGregory Neil Shapiro /* Reset global flags */ 20078774250cSGregory Neil Shapiro RestartRequest = NULL; 200840266059SGregory Neil Shapiro RestartWorkGroup = false; 20098774250cSGregory Neil Shapiro ShutdownRequest = NULL; 20108774250cSGregory Neil Shapiro PendingSignal = 0; 201140266059SGregory Neil Shapiro CurrentPid = getpid(); 201240266059SGregory Neil Shapiro 201340266059SGregory Neil Shapiro /* 201440266059SGregory Neil Shapiro ** Initialize exception stack and default exception 201540266059SGregory Neil Shapiro ** handler for child process. 201640266059SGregory Neil Shapiro */ 201740266059SGregory Neil Shapiro 201840266059SGregory Neil Shapiro sm_exc_newthread(fatal_error); 201940266059SGregory Neil Shapiro 202040266059SGregory Neil Shapiro /* child -- close stdin */ 202140266059SGregory Neil Shapiro (void) close(0); 20228774250cSGregory Neil Shapiro 2023c2aa98e2SPeter Wemm /* stdout goes back to parent */ 202406f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 2025c2aa98e2SPeter Wemm if (dup2(fdv[1], 1) < 0) 2026c2aa98e2SPeter Wemm { 2027c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stdout", argv[0]); 2028c2aa98e2SPeter Wemm _exit(EX_OSERR); 2029c2aa98e2SPeter Wemm } 203006f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 2031c2aa98e2SPeter Wemm 2032c2aa98e2SPeter Wemm /* stderr goes to transcript if available */ 2033c2aa98e2SPeter Wemm if (e->e_xfp != NULL) 2034c2aa98e2SPeter Wemm { 203506f25ae9SGregory Neil Shapiro int xfd; 203606f25ae9SGregory Neil Shapiro 203740266059SGregory Neil Shapiro xfd = sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL); 203806f25ae9SGregory Neil Shapiro if (xfd >= 0 && dup2(xfd, 2) < 0) 2039c2aa98e2SPeter Wemm { 2040c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stderr", argv[0]); 2041c2aa98e2SPeter Wemm _exit(EX_OSERR); 2042c2aa98e2SPeter Wemm } 2043c2aa98e2SPeter Wemm } 2044c2aa98e2SPeter Wemm 2045c2aa98e2SPeter Wemm /* this process has no right to the queue file */ 2046c2aa98e2SPeter Wemm if (e->e_lockfp != NULL) 2047af9557fdSGregory Neil Shapiro { 2048af9557fdSGregory Neil Shapiro int fd; 2049af9557fdSGregory Neil Shapiro 2050af9557fdSGregory Neil Shapiro fd = sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL); 2051af9557fdSGregory Neil Shapiro if (fd >= 0) 2052af9557fdSGregory Neil Shapiro (void) close(fd); 2053af9557fdSGregory Neil Shapiro else 2054af9557fdSGregory Neil Shapiro syserr("%s: lockfp does not have a fd", argv[0]); 2055af9557fdSGregory Neil Shapiro } 205606f25ae9SGregory Neil Shapiro 205706f25ae9SGregory Neil Shapiro /* chroot to the program mailer directory, if defined */ 205806f25ae9SGregory Neil Shapiro if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) 205906f25ae9SGregory Neil Shapiro { 206006f25ae9SGregory Neil Shapiro expand(ProgMailer->m_rootdir, buf, sizeof buf, e); 206106f25ae9SGregory Neil Shapiro if (chroot(buf) < 0) 206206f25ae9SGregory Neil Shapiro { 206306f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chroot(%s)", buf); 206406f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 206506f25ae9SGregory Neil Shapiro } 206606f25ae9SGregory Neil Shapiro if (chdir("/") < 0) 206706f25ae9SGregory Neil Shapiro { 206806f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chdir(/)"); 206906f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 207006f25ae9SGregory Neil Shapiro } 207106f25ae9SGregory Neil Shapiro } 2072c2aa98e2SPeter Wemm 2073c2aa98e2SPeter Wemm /* run as default user */ 2074c2aa98e2SPeter Wemm endpwent(); 207540266059SGregory Neil Shapiro sm_mbdb_terminate(); 20764e4196cbSGregory Neil Shapiro #if _FFR_MEMSTAT 20774e4196cbSGregory Neil Shapiro (void) sm_memstat_close(); 20784e4196cbSGregory Neil Shapiro #endif /* _FFR_MEMSTAT */ 2079c2aa98e2SPeter Wemm if (setgid(DefGid) < 0 && geteuid() == 0) 208006f25ae9SGregory Neil Shapiro { 2081c2aa98e2SPeter Wemm syserr("prog_open: setgid(%ld) failed", (long) DefGid); 208206f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 208306f25ae9SGregory Neil Shapiro } 2084c2aa98e2SPeter Wemm if (setuid(DefUid) < 0 && geteuid() == 0) 208506f25ae9SGregory Neil Shapiro { 2086c2aa98e2SPeter Wemm syserr("prog_open: setuid(%ld) failed", (long) DefUid); 208706f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 208806f25ae9SGregory Neil Shapiro } 2089c2aa98e2SPeter Wemm 2090c2aa98e2SPeter Wemm /* run in some directory */ 2091c2aa98e2SPeter Wemm if (ProgMailer != NULL) 2092c2aa98e2SPeter Wemm p = ProgMailer->m_execdir; 2093c2aa98e2SPeter Wemm else 2094c2aa98e2SPeter Wemm p = NULL; 2095c2aa98e2SPeter Wemm for (; p != NULL; p = q) 2096c2aa98e2SPeter Wemm { 2097c2aa98e2SPeter Wemm q = strchr(p, ':'); 2098c2aa98e2SPeter Wemm if (q != NULL) 2099c2aa98e2SPeter Wemm *q = '\0'; 2100c2aa98e2SPeter Wemm expand(p, buf, sizeof buf, e); 2101c2aa98e2SPeter Wemm if (q != NULL) 2102c2aa98e2SPeter Wemm *q++ = ':'; 2103c2aa98e2SPeter Wemm if (buf[0] != '\0' && chdir(buf) >= 0) 2104c2aa98e2SPeter Wemm break; 2105c2aa98e2SPeter Wemm } 2106c2aa98e2SPeter Wemm if (p == NULL) 2107c2aa98e2SPeter Wemm { 2108c2aa98e2SPeter Wemm /* backup directories */ 2109c2aa98e2SPeter Wemm if (chdir("/tmp") < 0) 2110c2aa98e2SPeter Wemm (void) chdir("/"); 2111c2aa98e2SPeter Wemm } 2112c2aa98e2SPeter Wemm 211340266059SGregory Neil Shapiro /* Check safety of program to be run */ 211440266059SGregory Neil Shapiro sff = SFF_ROOTOK|SFF_EXECOK; 211540266059SGregory Neil Shapiro if (!bitnset(DBS_RUNWRITABLEPROGRAM, DontBlameSendmail)) 211640266059SGregory Neil Shapiro sff |= SFF_NOGWFILES|SFF_NOWWFILES; 211740266059SGregory Neil Shapiro if (bitnset(DBS_RUNPROGRAMINUNSAFEDIRPATH, DontBlameSendmail)) 211840266059SGregory Neil Shapiro sff |= SFF_NOPATHCHECK; 211940266059SGregory Neil Shapiro else 212040266059SGregory Neil Shapiro sff |= SFF_SAFEDIRPATH; 212140266059SGregory Neil Shapiro ret = safefile(argv[0], DefUid, DefGid, DefUser, sff, 0, NULL); 212240266059SGregory Neil Shapiro if (ret != 0) 212340266059SGregory Neil Shapiro sm_syslog(LOG_INFO, e->e_id, 212440266059SGregory Neil Shapiro "Warning: prog_open: program %s unsafe: %s", 212540266059SGregory Neil Shapiro argv[0], sm_errstring(ret)); 212640266059SGregory Neil Shapiro 2127c2aa98e2SPeter Wemm /* arrange for all the files to be closed */ 2128e92d3f3fSGregory Neil Shapiro sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 2129c2aa98e2SPeter Wemm 2130c2aa98e2SPeter Wemm /* now exec the process */ 213106f25ae9SGregory Neil Shapiro (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 2132c2aa98e2SPeter Wemm 2133c2aa98e2SPeter Wemm /* woops! failed */ 213406f25ae9SGregory Neil Shapiro save_errno = errno; 2135c2aa98e2SPeter Wemm syserr("%s: cannot exec", argv[0]); 213606f25ae9SGregory Neil Shapiro if (transienterror(save_errno)) 2137c2aa98e2SPeter Wemm _exit(EX_OSERR); 2138c2aa98e2SPeter Wemm _exit(EX_CONFIG); 2139c2aa98e2SPeter Wemm return -1; /* avoid compiler warning on IRIX */ 2140c2aa98e2SPeter Wemm } 214140266059SGregory Neil Shapiro /* 2142c2aa98e2SPeter Wemm ** GET_COLUMN -- look up a Column in a line buffer 2143c2aa98e2SPeter Wemm ** 2144c2aa98e2SPeter Wemm ** Parameters: 2145c2aa98e2SPeter Wemm ** line -- the raw text line to search. 2146c2aa98e2SPeter Wemm ** col -- the column number to fetch. 2147c2aa98e2SPeter Wemm ** delim -- the delimiter between columns. If null, 2148c2aa98e2SPeter Wemm ** use white space. 2149c2aa98e2SPeter Wemm ** buf -- the output buffer. 2150c2aa98e2SPeter Wemm ** buflen -- the length of buf. 2151c2aa98e2SPeter Wemm ** 2152c2aa98e2SPeter Wemm ** Returns: 2153c2aa98e2SPeter Wemm ** buf if successful. 2154c2aa98e2SPeter Wemm ** NULL otherwise. 2155c2aa98e2SPeter Wemm */ 2156c2aa98e2SPeter Wemm 2157c2aa98e2SPeter Wemm char * 2158c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen) 2159c2aa98e2SPeter Wemm char line[]; 2160c2aa98e2SPeter Wemm int col; 216106f25ae9SGregory Neil Shapiro int delim; 2162c2aa98e2SPeter Wemm char buf[]; 2163c2aa98e2SPeter Wemm int buflen; 2164c2aa98e2SPeter Wemm { 2165c2aa98e2SPeter Wemm char *p; 2166c2aa98e2SPeter Wemm char *begin, *end; 2167c2aa98e2SPeter Wemm int i; 2168c2aa98e2SPeter Wemm char delimbuf[4]; 2169c2aa98e2SPeter Wemm 217006f25ae9SGregory Neil Shapiro if ((char) delim == '\0') 217140266059SGregory Neil Shapiro (void) sm_strlcpy(delimbuf, "\n\t ", sizeof delimbuf); 2172c2aa98e2SPeter Wemm else 2173c2aa98e2SPeter Wemm { 217406f25ae9SGregory Neil Shapiro delimbuf[0] = (char) delim; 2175c2aa98e2SPeter Wemm delimbuf[1] = '\0'; 2176c2aa98e2SPeter Wemm } 2177c2aa98e2SPeter Wemm 2178c2aa98e2SPeter Wemm p = line; 2179c2aa98e2SPeter Wemm if (*p == '\0') 2180c2aa98e2SPeter Wemm return NULL; /* line empty */ 218106f25ae9SGregory Neil Shapiro if (*p == (char) delim && col == 0) 2182c2aa98e2SPeter Wemm return NULL; /* first column empty */ 2183c2aa98e2SPeter Wemm 2184c2aa98e2SPeter Wemm begin = line; 2185c2aa98e2SPeter Wemm 218606f25ae9SGregory Neil Shapiro if (col == 0 && (char) delim == '\0') 2187c2aa98e2SPeter Wemm { 2188c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2189c2aa98e2SPeter Wemm begin++; 2190c2aa98e2SPeter Wemm } 2191c2aa98e2SPeter Wemm 2192c2aa98e2SPeter Wemm for (i = 0; i < col; i++) 2193c2aa98e2SPeter Wemm { 2194c2aa98e2SPeter Wemm if ((begin = strpbrk(begin, delimbuf)) == NULL) 2195c2aa98e2SPeter Wemm return NULL; /* no such column */ 2196c2aa98e2SPeter Wemm begin++; 219706f25ae9SGregory Neil Shapiro if ((char) delim == '\0') 2198c2aa98e2SPeter Wemm { 2199c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2200c2aa98e2SPeter Wemm begin++; 2201c2aa98e2SPeter Wemm } 2202c2aa98e2SPeter Wemm } 2203c2aa98e2SPeter Wemm 2204c2aa98e2SPeter Wemm end = strpbrk(begin, delimbuf); 2205c2aa98e2SPeter Wemm if (end == NULL) 2206c2aa98e2SPeter Wemm i = strlen(begin); 2207c2aa98e2SPeter Wemm else 2208c2aa98e2SPeter Wemm i = end - begin; 2209c2aa98e2SPeter Wemm if (i >= buflen) 2210c2aa98e2SPeter Wemm i = buflen - 1; 221140266059SGregory Neil Shapiro (void) sm_strlcpy(buf, begin, i + 1); 2212c2aa98e2SPeter Wemm return buf; 2213c2aa98e2SPeter Wemm } 221440266059SGregory Neil Shapiro /* 2215c2aa98e2SPeter Wemm ** CLEANSTRCPY -- copy string keeping out bogus characters 2216c2aa98e2SPeter Wemm ** 2217c2aa98e2SPeter Wemm ** Parameters: 2218c2aa98e2SPeter Wemm ** t -- "to" string. 2219c2aa98e2SPeter Wemm ** f -- "from" string. 2220c2aa98e2SPeter Wemm ** l -- length of space available in "to" string. 2221c2aa98e2SPeter Wemm ** 2222c2aa98e2SPeter Wemm ** Returns: 2223c2aa98e2SPeter Wemm ** none. 2224c2aa98e2SPeter Wemm */ 2225c2aa98e2SPeter Wemm 2226c2aa98e2SPeter Wemm void 2227c2aa98e2SPeter Wemm cleanstrcpy(t, f, l) 2228c2aa98e2SPeter Wemm register char *t; 2229c2aa98e2SPeter Wemm register char *f; 2230c2aa98e2SPeter Wemm int l; 2231c2aa98e2SPeter Wemm { 2232c2aa98e2SPeter Wemm /* check for newlines and log if necessary */ 223340266059SGregory Neil Shapiro (void) denlstring(f, true, true); 2234c2aa98e2SPeter Wemm 223506f25ae9SGregory Neil Shapiro if (l <= 0) 223606f25ae9SGregory Neil Shapiro syserr("!cleanstrcpy: length == 0"); 223706f25ae9SGregory Neil Shapiro 2238c2aa98e2SPeter Wemm l--; 2239c2aa98e2SPeter Wemm while (l > 0 && *f != '\0') 2240c2aa98e2SPeter Wemm { 2241c2aa98e2SPeter Wemm if (isascii(*f) && 2242c2aa98e2SPeter Wemm (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 2243c2aa98e2SPeter Wemm { 2244c2aa98e2SPeter Wemm l--; 2245c2aa98e2SPeter Wemm *t++ = *f; 2246c2aa98e2SPeter Wemm } 2247c2aa98e2SPeter Wemm f++; 2248c2aa98e2SPeter Wemm } 2249c2aa98e2SPeter Wemm *t = '\0'; 2250c2aa98e2SPeter Wemm } 225140266059SGregory Neil Shapiro /* 2252c2aa98e2SPeter Wemm ** DENLSTRING -- convert newlines in a string to spaces 2253c2aa98e2SPeter Wemm ** 2254c2aa98e2SPeter Wemm ** Parameters: 2255c2aa98e2SPeter Wemm ** s -- the input string 2256c2aa98e2SPeter Wemm ** strict -- if set, don't permit continuation lines. 2257c2aa98e2SPeter Wemm ** logattacks -- if set, log attempted attacks. 2258c2aa98e2SPeter Wemm ** 2259c2aa98e2SPeter Wemm ** Returns: 2260c2aa98e2SPeter Wemm ** A pointer to a version of the string with newlines 2261c2aa98e2SPeter Wemm ** mapped to spaces. This should be copied. 2262c2aa98e2SPeter Wemm */ 2263c2aa98e2SPeter Wemm 2264c2aa98e2SPeter Wemm char * 2265c2aa98e2SPeter Wemm denlstring(s, strict, logattacks) 2266c2aa98e2SPeter Wemm char *s; 2267c2aa98e2SPeter Wemm bool strict; 2268c2aa98e2SPeter Wemm bool logattacks; 2269c2aa98e2SPeter Wemm { 2270c2aa98e2SPeter Wemm register char *p; 2271c2aa98e2SPeter Wemm int l; 2272c2aa98e2SPeter Wemm static char *bp = NULL; 2273c2aa98e2SPeter Wemm static int bl = 0; 2274c2aa98e2SPeter Wemm 2275c2aa98e2SPeter Wemm p = s; 2276c2aa98e2SPeter Wemm while ((p = strchr(p, '\n')) != NULL) 2277c2aa98e2SPeter Wemm if (strict || (*++p != ' ' && *p != '\t')) 2278c2aa98e2SPeter Wemm break; 2279c2aa98e2SPeter Wemm if (p == NULL) 2280c2aa98e2SPeter Wemm return s; 2281c2aa98e2SPeter Wemm 2282c2aa98e2SPeter Wemm l = strlen(s) + 1; 2283c2aa98e2SPeter Wemm if (bl < l) 2284c2aa98e2SPeter Wemm { 2285c2aa98e2SPeter Wemm /* allocate more space */ 228640266059SGregory Neil Shapiro char *nbp = sm_pmalloc_x(l); 228740266059SGregory Neil Shapiro 2288c2aa98e2SPeter Wemm if (bp != NULL) 22898774250cSGregory Neil Shapiro sm_free(bp); 229040266059SGregory Neil Shapiro bp = nbp; 2291c2aa98e2SPeter Wemm bl = l; 2292c2aa98e2SPeter Wemm } 229340266059SGregory Neil Shapiro (void) sm_strlcpy(bp, s, l); 2294c2aa98e2SPeter Wemm for (p = bp; (p = strchr(p, '\n')) != NULL; ) 2295c2aa98e2SPeter Wemm *p++ = ' '; 2296c2aa98e2SPeter Wemm 2297c2aa98e2SPeter Wemm if (logattacks) 2298c2aa98e2SPeter Wemm { 2299c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 2300c2aa98e2SPeter Wemm "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 2301c2aa98e2SPeter Wemm RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 2302c2aa98e2SPeter Wemm shortenstring(bp, MAXSHORTSTR)); 2303c2aa98e2SPeter Wemm } 2304c2aa98e2SPeter Wemm 2305c2aa98e2SPeter Wemm return bp; 2306c2aa98e2SPeter Wemm } 2307739ac4d4SGregory Neil Shapiro 2308739ac4d4SGregory Neil Shapiro /* 2309739ac4d4SGregory Neil Shapiro ** STRREPLNONPRT -- replace "unprintable" characters in a string with subst 2310739ac4d4SGregory Neil Shapiro ** 2311739ac4d4SGregory Neil Shapiro ** Parameters: 2312739ac4d4SGregory Neil Shapiro ** s -- string to manipulate (in place) 2313739ac4d4SGregory Neil Shapiro ** subst -- character to use as replacement 2314739ac4d4SGregory Neil Shapiro ** 2315739ac4d4SGregory Neil Shapiro ** Returns: 2316739ac4d4SGregory Neil Shapiro ** true iff string did not contain "unprintable" characters 2317739ac4d4SGregory Neil Shapiro */ 2318739ac4d4SGregory Neil Shapiro 2319739ac4d4SGregory Neil Shapiro bool 2320739ac4d4SGregory Neil Shapiro strreplnonprt(s, c) 2321739ac4d4SGregory Neil Shapiro char *s; 2322739ac4d4SGregory Neil Shapiro int c; 2323739ac4d4SGregory Neil Shapiro { 2324739ac4d4SGregory Neil Shapiro bool ok; 2325739ac4d4SGregory Neil Shapiro 2326739ac4d4SGregory Neil Shapiro ok = true; 2327739ac4d4SGregory Neil Shapiro if (s == NULL) 2328739ac4d4SGregory Neil Shapiro return ok; 2329739ac4d4SGregory Neil Shapiro while (*s != '\0') 2330739ac4d4SGregory Neil Shapiro { 2331739ac4d4SGregory Neil Shapiro if (!(isascii(*s) && isprint(*s))) 2332739ac4d4SGregory Neil Shapiro { 2333739ac4d4SGregory Neil Shapiro *s = c; 2334739ac4d4SGregory Neil Shapiro ok = false; 2335739ac4d4SGregory Neil Shapiro } 2336739ac4d4SGregory Neil Shapiro ++s; 2337739ac4d4SGregory Neil Shapiro } 2338739ac4d4SGregory Neil Shapiro return ok; 2339739ac4d4SGregory Neil Shapiro } 2340739ac4d4SGregory Neil Shapiro 234140266059SGregory Neil Shapiro /* 234240266059SGregory Neil Shapiro ** STR2PRT -- convert "unprintable" characters in a string to \oct 234340266059SGregory Neil Shapiro ** 234440266059SGregory Neil Shapiro ** Parameters: 234540266059SGregory Neil Shapiro ** s -- string to convert 234640266059SGregory Neil Shapiro ** 234740266059SGregory Neil Shapiro ** Returns: 234840266059SGregory Neil Shapiro ** converted string. 234940266059SGregory Neil Shapiro ** This is a static local buffer, string must be copied 235040266059SGregory Neil Shapiro ** before this function is called again! 235140266059SGregory Neil Shapiro */ 235240266059SGregory Neil Shapiro 235340266059SGregory Neil Shapiro char * 235440266059SGregory Neil Shapiro str2prt(s) 235540266059SGregory Neil Shapiro char *s; 235640266059SGregory Neil Shapiro { 235740266059SGregory Neil Shapiro int l; 235840266059SGregory Neil Shapiro char c, *h; 235940266059SGregory Neil Shapiro bool ok; 236040266059SGregory Neil Shapiro static int len = 0; 236140266059SGregory Neil Shapiro static char *buf = NULL; 236240266059SGregory Neil Shapiro 236340266059SGregory Neil Shapiro if (s == NULL) 236440266059SGregory Neil Shapiro return NULL; 236540266059SGregory Neil Shapiro ok = true; 236640266059SGregory Neil Shapiro for (h = s, l = 1; *h != '\0'; h++, l++) 236740266059SGregory Neil Shapiro { 236840266059SGregory Neil Shapiro if (*h == '\\') 236940266059SGregory Neil Shapiro { 237040266059SGregory Neil Shapiro ++l; 237140266059SGregory Neil Shapiro ok = false; 237240266059SGregory Neil Shapiro } 237340266059SGregory Neil Shapiro else if (!(isascii(*h) && isprint(*h))) 237440266059SGregory Neil Shapiro { 237540266059SGregory Neil Shapiro l += 3; 237640266059SGregory Neil Shapiro ok = false; 237740266059SGregory Neil Shapiro } 237840266059SGregory Neil Shapiro } 237940266059SGregory Neil Shapiro if (ok) 238040266059SGregory Neil Shapiro return s; 238140266059SGregory Neil Shapiro if (l > len) 238240266059SGregory Neil Shapiro { 238340266059SGregory Neil Shapiro char *nbuf = sm_pmalloc_x(l); 238440266059SGregory Neil Shapiro 238540266059SGregory Neil Shapiro if (buf != NULL) 238640266059SGregory Neil Shapiro sm_free(buf); 238740266059SGregory Neil Shapiro len = l; 238840266059SGregory Neil Shapiro buf = nbuf; 238940266059SGregory Neil Shapiro } 239040266059SGregory Neil Shapiro for (h = buf; *s != '\0' && l > 0; s++, l--) 239140266059SGregory Neil Shapiro { 239240266059SGregory Neil Shapiro c = *s; 239340266059SGregory Neil Shapiro if (isascii(c) && isprint(c) && c != '\\') 239440266059SGregory Neil Shapiro { 239540266059SGregory Neil Shapiro *h++ = c; 239640266059SGregory Neil Shapiro } 239740266059SGregory Neil Shapiro else 239840266059SGregory Neil Shapiro { 239940266059SGregory Neil Shapiro *h++ = '\\'; 240040266059SGregory Neil Shapiro --l; 240140266059SGregory Neil Shapiro switch (c) 240240266059SGregory Neil Shapiro { 240340266059SGregory Neil Shapiro case '\\': 240440266059SGregory Neil Shapiro *h++ = '\\'; 240540266059SGregory Neil Shapiro break; 240640266059SGregory Neil Shapiro case '\t': 240740266059SGregory Neil Shapiro *h++ = 't'; 240840266059SGregory Neil Shapiro break; 240940266059SGregory Neil Shapiro case '\n': 241040266059SGregory Neil Shapiro *h++ = 'n'; 241140266059SGregory Neil Shapiro break; 241240266059SGregory Neil Shapiro case '\r': 241340266059SGregory Neil Shapiro *h++ = 'r'; 241440266059SGregory Neil Shapiro break; 241540266059SGregory Neil Shapiro default: 24164e4196cbSGregory Neil Shapiro SM_ASSERT(l >= 2); 2417323f6dcbSGregory Neil Shapiro (void) sm_snprintf(h, l, "%03o", 2418323f6dcbSGregory Neil Shapiro (unsigned int)((unsigned char) c)); 241940266059SGregory Neil Shapiro 242040266059SGregory Neil Shapiro /* 242140266059SGregory Neil Shapiro ** XXX since l is unsigned this may 242240266059SGregory Neil Shapiro ** wrap around if the calculation is screwed 242340266059SGregory Neil Shapiro ** up... 242440266059SGregory Neil Shapiro */ 242540266059SGregory Neil Shapiro 242640266059SGregory Neil Shapiro l -= 2; 242740266059SGregory Neil Shapiro h += 3; 242840266059SGregory Neil Shapiro break; 242940266059SGregory Neil Shapiro } 243040266059SGregory Neil Shapiro } 243140266059SGregory Neil Shapiro } 243240266059SGregory Neil Shapiro *h = '\0'; 243340266059SGregory Neil Shapiro buf[len - 1] = '\0'; 243440266059SGregory Neil Shapiro return buf; 243540266059SGregory Neil Shapiro } 243640266059SGregory Neil Shapiro /* 2437c2aa98e2SPeter Wemm ** PATH_IS_DIR -- check to see if file exists and is a directory. 2438c2aa98e2SPeter Wemm ** 2439c2aa98e2SPeter Wemm ** There are some additional checks for security violations in 2440c2aa98e2SPeter Wemm ** here. This routine is intended to be used for the host status 2441c2aa98e2SPeter Wemm ** support. 2442c2aa98e2SPeter Wemm ** 2443c2aa98e2SPeter Wemm ** Parameters: 2444c2aa98e2SPeter Wemm ** pathname -- pathname to check for directory-ness. 2445c2aa98e2SPeter Wemm ** createflag -- if set, create directory if needed. 2446c2aa98e2SPeter Wemm ** 2447c2aa98e2SPeter Wemm ** Returns: 244840266059SGregory Neil Shapiro ** true -- if the indicated pathname is a directory 244940266059SGregory Neil Shapiro ** false -- otherwise 2450c2aa98e2SPeter Wemm */ 2451c2aa98e2SPeter Wemm 2452a7ec597cSGregory Neil Shapiro bool 2453c2aa98e2SPeter Wemm path_is_dir(pathname, createflag) 2454c2aa98e2SPeter Wemm char *pathname; 2455c2aa98e2SPeter Wemm bool createflag; 2456c2aa98e2SPeter Wemm { 2457c2aa98e2SPeter Wemm struct stat statbuf; 2458c2aa98e2SPeter Wemm 2459c2aa98e2SPeter Wemm #if HASLSTAT 2460c2aa98e2SPeter Wemm if (lstat(pathname, &statbuf) < 0) 246106f25ae9SGregory Neil Shapiro #else /* HASLSTAT */ 2462c2aa98e2SPeter Wemm if (stat(pathname, &statbuf) < 0) 246306f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */ 2464c2aa98e2SPeter Wemm { 2465c2aa98e2SPeter Wemm if (errno != ENOENT || !createflag) 246640266059SGregory Neil Shapiro return false; 2467c2aa98e2SPeter Wemm if (mkdir(pathname, 0755) < 0) 246840266059SGregory Neil Shapiro return false; 246940266059SGregory Neil Shapiro return true; 2470c2aa98e2SPeter Wemm } 2471c2aa98e2SPeter Wemm if (!S_ISDIR(statbuf.st_mode)) 2472c2aa98e2SPeter Wemm { 2473c2aa98e2SPeter Wemm errno = ENOTDIR; 247440266059SGregory Neil Shapiro return false; 2475c2aa98e2SPeter Wemm } 2476c2aa98e2SPeter Wemm 2477c2aa98e2SPeter Wemm /* security: don't allow writable directories */ 2478c2aa98e2SPeter Wemm if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 2479c2aa98e2SPeter Wemm { 2480c2aa98e2SPeter Wemm errno = EACCES; 248140266059SGregory Neil Shapiro return false; 2482c2aa98e2SPeter Wemm } 248340266059SGregory Neil Shapiro return true; 2484c2aa98e2SPeter Wemm } 248540266059SGregory Neil Shapiro /* 2486c2aa98e2SPeter Wemm ** PROC_LIST_ADD -- add process id to list of our children 2487c2aa98e2SPeter Wemm ** 2488c2aa98e2SPeter Wemm ** Parameters: 2489c2aa98e2SPeter Wemm ** pid -- pid to add to list. 249006f25ae9SGregory Neil Shapiro ** task -- task of pid. 249106f25ae9SGregory Neil Shapiro ** type -- type of process. 249240266059SGregory Neil Shapiro ** count -- number of processes. 249340266059SGregory Neil Shapiro ** other -- other information for this type. 2494c2aa98e2SPeter Wemm ** 2495c2aa98e2SPeter Wemm ** Returns: 2496c2aa98e2SPeter Wemm ** none 249740266059SGregory Neil Shapiro ** 249840266059SGregory Neil Shapiro ** Side Effects: 249940266059SGregory Neil Shapiro ** May increase CurChildren. May grow ProcList. 2500c2aa98e2SPeter Wemm */ 2501c2aa98e2SPeter Wemm 250240266059SGregory Neil Shapiro typedef struct procs PROCS_T; 250340266059SGregory Neil Shapiro 250440266059SGregory Neil Shapiro struct procs 250540266059SGregory Neil Shapiro { 250640266059SGregory Neil Shapiro pid_t proc_pid; 250740266059SGregory Neil Shapiro char *proc_task; 250840266059SGregory Neil Shapiro int proc_type; 250940266059SGregory Neil Shapiro int proc_count; 251040266059SGregory Neil Shapiro int proc_other; 2511e92d3f3fSGregory Neil Shapiro SOCKADDR proc_hostaddr; 251240266059SGregory Neil Shapiro }; 251340266059SGregory Neil Shapiro 251440266059SGregory Neil Shapiro static PROCS_T *volatile ProcListVec = NULL; 2515c2aa98e2SPeter Wemm static int ProcListSize = 0; 2516c2aa98e2SPeter Wemm 2517c2aa98e2SPeter Wemm void 2518e92d3f3fSGregory Neil Shapiro proc_list_add(pid, task, type, count, other, hostaddr) 2519c2aa98e2SPeter Wemm pid_t pid; 2520065a643dSPeter Wemm char *task; 252106f25ae9SGregory Neil Shapiro int type; 252240266059SGregory Neil Shapiro int count; 252340266059SGregory Neil Shapiro int other; 2524e92d3f3fSGregory Neil Shapiro SOCKADDR *hostaddr; 2525c2aa98e2SPeter Wemm { 2526c2aa98e2SPeter Wemm int i; 2527c2aa98e2SPeter Wemm 2528c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2529c2aa98e2SPeter Wemm { 2530065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2531c2aa98e2SPeter Wemm break; 2532c2aa98e2SPeter Wemm } 2533c2aa98e2SPeter Wemm if (i >= ProcListSize) 2534c2aa98e2SPeter Wemm { 2535c2aa98e2SPeter Wemm /* probe the existing vector to avoid growing infinitely */ 2536c2aa98e2SPeter Wemm proc_list_probe(); 2537c2aa98e2SPeter Wemm 2538c2aa98e2SPeter Wemm /* now scan again */ 2539c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2540c2aa98e2SPeter Wemm { 2541065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2542c2aa98e2SPeter Wemm break; 2543c2aa98e2SPeter Wemm } 2544c2aa98e2SPeter Wemm } 2545c2aa98e2SPeter Wemm if (i >= ProcListSize) 2546c2aa98e2SPeter Wemm { 2547c2aa98e2SPeter Wemm /* grow process list */ 254840266059SGregory Neil Shapiro PROCS_T *npv; 2549c2aa98e2SPeter Wemm 255040266059SGregory Neil Shapiro SM_ASSERT(ProcListSize < INT_MAX - PROC_LIST_SEG); 255140266059SGregory Neil Shapiro npv = (PROCS_T *) sm_pmalloc_x((sizeof *npv) * 255206f25ae9SGregory Neil Shapiro (ProcListSize + PROC_LIST_SEG)); 2553c2aa98e2SPeter Wemm if (ProcListSize > 0) 2554c2aa98e2SPeter Wemm { 255506f25ae9SGregory Neil Shapiro memmove(npv, ProcListVec, 255640266059SGregory Neil Shapiro ProcListSize * sizeof (PROCS_T)); 25578774250cSGregory Neil Shapiro sm_free(ProcListVec); 2558c2aa98e2SPeter Wemm } 255940266059SGregory Neil Shapiro 256040266059SGregory Neil Shapiro /* XXX just use memset() to initialize this part? */ 2561c2aa98e2SPeter Wemm for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 2562065a643dSPeter Wemm { 2563065a643dSPeter Wemm npv[i].proc_pid = NO_PID; 2564065a643dSPeter Wemm npv[i].proc_task = NULL; 256506f25ae9SGregory Neil Shapiro npv[i].proc_type = PROC_NONE; 2566065a643dSPeter Wemm } 2567c2aa98e2SPeter Wemm i = ProcListSize; 2568c2aa98e2SPeter Wemm ProcListSize += PROC_LIST_SEG; 2569c2aa98e2SPeter Wemm ProcListVec = npv; 2570c2aa98e2SPeter Wemm } 2571065a643dSPeter Wemm ProcListVec[i].proc_pid = pid; 257240266059SGregory Neil Shapiro PSTRSET(ProcListVec[i].proc_task, task); 257306f25ae9SGregory Neil Shapiro ProcListVec[i].proc_type = type; 257440266059SGregory Neil Shapiro ProcListVec[i].proc_count = count; 257540266059SGregory Neil Shapiro ProcListVec[i].proc_other = other; 2576e92d3f3fSGregory Neil Shapiro if (hostaddr != NULL) 2577e92d3f3fSGregory Neil Shapiro ProcListVec[i].proc_hostaddr = *hostaddr; 2578e92d3f3fSGregory Neil Shapiro else 2579e92d3f3fSGregory Neil Shapiro memset(&ProcListVec[i].proc_hostaddr, 0, 2580e92d3f3fSGregory Neil Shapiro sizeof(ProcListVec[i].proc_hostaddr)); 2581065a643dSPeter Wemm 2582065a643dSPeter Wemm /* if process adding itself, it's not a child */ 258340266059SGregory Neil Shapiro if (pid != CurrentPid) 258440266059SGregory Neil Shapiro { 258540266059SGregory Neil Shapiro SM_ASSERT(CurChildren < INT_MAX); 2586c2aa98e2SPeter Wemm CurChildren++; 2587c2aa98e2SPeter Wemm } 258840266059SGregory Neil Shapiro } 258940266059SGregory Neil Shapiro /* 2590065a643dSPeter Wemm ** PROC_LIST_SET -- set pid task in process list 2591065a643dSPeter Wemm ** 2592065a643dSPeter Wemm ** Parameters: 2593065a643dSPeter Wemm ** pid -- pid to set 2594065a643dSPeter Wemm ** task -- task of pid 2595065a643dSPeter Wemm ** 2596065a643dSPeter Wemm ** Returns: 2597065a643dSPeter Wemm ** none. 2598065a643dSPeter Wemm */ 2599065a643dSPeter Wemm 2600065a643dSPeter Wemm void 2601065a643dSPeter Wemm proc_list_set(pid, task) 2602065a643dSPeter Wemm pid_t pid; 2603065a643dSPeter Wemm char *task; 2604065a643dSPeter Wemm { 2605065a643dSPeter Wemm int i; 2606065a643dSPeter Wemm 2607065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2608065a643dSPeter Wemm { 2609065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2610065a643dSPeter Wemm { 261140266059SGregory Neil Shapiro PSTRSET(ProcListVec[i].proc_task, task); 2612065a643dSPeter Wemm break; 2613065a643dSPeter Wemm } 2614065a643dSPeter Wemm } 2615065a643dSPeter Wemm } 261640266059SGregory Neil Shapiro /* 2617c2aa98e2SPeter Wemm ** PROC_LIST_DROP -- drop pid from process list 2618c2aa98e2SPeter Wemm ** 2619c2aa98e2SPeter Wemm ** Parameters: 2620c2aa98e2SPeter Wemm ** pid -- pid to drop 262140266059SGregory Neil Shapiro ** st -- process status 262240266059SGregory Neil Shapiro ** other -- storage for proc_other (return). 2623c2aa98e2SPeter Wemm ** 2624c2aa98e2SPeter Wemm ** Returns: 262540266059SGregory Neil Shapiro ** none. 262640266059SGregory Neil Shapiro ** 262740266059SGregory Neil Shapiro ** Side Effects: 262840266059SGregory Neil Shapiro ** May decrease CurChildren, CurRunners, or 262940266059SGregory Neil Shapiro ** set RestartRequest or ShutdownRequest. 26308774250cSGregory Neil Shapiro ** 26318774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 26328774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 26338774250cSGregory Neil Shapiro ** DOING. 2634c2aa98e2SPeter Wemm */ 2635c2aa98e2SPeter Wemm 263640266059SGregory Neil Shapiro void 263740266059SGregory Neil Shapiro proc_list_drop(pid, st, other) 2638c2aa98e2SPeter Wemm pid_t pid; 263940266059SGregory Neil Shapiro int st; 264040266059SGregory Neil Shapiro int *other; 2641c2aa98e2SPeter Wemm { 2642c2aa98e2SPeter Wemm int i; 264306f25ae9SGregory Neil Shapiro int type = PROC_NONE; 2644c2aa98e2SPeter Wemm 2645c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2646c2aa98e2SPeter Wemm { 2647065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2648c2aa98e2SPeter Wemm { 2649065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 265006f25ae9SGregory Neil Shapiro type = ProcListVec[i].proc_type; 265140266059SGregory Neil Shapiro if (other != NULL) 265240266059SGregory Neil Shapiro *other = ProcListVec[i].proc_other; 26534e4196cbSGregory Neil Shapiro if (CurChildren > 0) 26544e4196cbSGregory Neil Shapiro CurChildren--; 2655c2aa98e2SPeter Wemm break; 2656c2aa98e2SPeter Wemm } 2657c2aa98e2SPeter Wemm } 265806f25ae9SGregory Neil Shapiro 265906f25ae9SGregory Neil Shapiro 266040266059SGregory Neil Shapiro if (type == PROC_CONTROL && WIFEXITED(st)) 266140266059SGregory Neil Shapiro { 266240266059SGregory Neil Shapiro /* if so, see if we need to restart or shutdown */ 266340266059SGregory Neil Shapiro if (WEXITSTATUS(st) == EX_RESTART) 266440266059SGregory Neil Shapiro RestartRequest = "control socket"; 266540266059SGregory Neil Shapiro else if (WEXITSTATUS(st) == EX_SHUTDOWN) 266640266059SGregory Neil Shapiro ShutdownRequest = "control socket"; 2667c2aa98e2SPeter Wemm } 266840266059SGregory Neil Shapiro else if (type == PROC_QUEUE_CHILD && !WIFSTOPPED(st) && 266940266059SGregory Neil Shapiro ProcListVec[i].proc_other > -1) 267040266059SGregory Neil Shapiro { 267140266059SGregory Neil Shapiro /* restart this persistent runner */ 267240266059SGregory Neil Shapiro mark_work_group_restart(ProcListVec[i].proc_other, st); 267340266059SGregory Neil Shapiro } 267440266059SGregory Neil Shapiro else if (type == PROC_QUEUE) 267540266059SGregory Neil Shapiro CurRunners -= ProcListVec[i].proc_count; 267640266059SGregory Neil Shapiro } 267740266059SGregory Neil Shapiro /* 2678c2aa98e2SPeter Wemm ** PROC_LIST_CLEAR -- clear the process list 2679c2aa98e2SPeter Wemm ** 2680c2aa98e2SPeter Wemm ** Parameters: 2681c2aa98e2SPeter Wemm ** none. 2682c2aa98e2SPeter Wemm ** 2683c2aa98e2SPeter Wemm ** Returns: 2684c2aa98e2SPeter Wemm ** none. 268540266059SGregory Neil Shapiro ** 268640266059SGregory Neil Shapiro ** Side Effects: 268740266059SGregory Neil Shapiro ** Sets CurChildren to zero. 2688c2aa98e2SPeter Wemm */ 2689c2aa98e2SPeter Wemm 2690c2aa98e2SPeter Wemm void 2691c2aa98e2SPeter Wemm proc_list_clear() 2692c2aa98e2SPeter Wemm { 2693c2aa98e2SPeter Wemm int i; 2694c2aa98e2SPeter Wemm 2695065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2696065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2697065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2698c2aa98e2SPeter Wemm CurChildren = 0; 2699c2aa98e2SPeter Wemm } 270040266059SGregory Neil Shapiro /* 2701c2aa98e2SPeter Wemm ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 2702c2aa98e2SPeter Wemm ** 2703c2aa98e2SPeter Wemm ** Parameters: 2704c2aa98e2SPeter Wemm ** none 2705c2aa98e2SPeter Wemm ** 2706c2aa98e2SPeter Wemm ** Returns: 2707c2aa98e2SPeter Wemm ** none 270840266059SGregory Neil Shapiro ** 270940266059SGregory Neil Shapiro ** Side Effects: 271040266059SGregory Neil Shapiro ** May decrease CurChildren. 2711c2aa98e2SPeter Wemm */ 2712c2aa98e2SPeter Wemm 2713c2aa98e2SPeter Wemm void 2714c2aa98e2SPeter Wemm proc_list_probe() 2715c2aa98e2SPeter Wemm { 27164e4196cbSGregory Neil Shapiro int i, children; 27174e4196cbSGregory Neil Shapiro int chldwasblocked; 27184e4196cbSGregory Neil Shapiro pid_t pid; 27194e4196cbSGregory Neil Shapiro 27204e4196cbSGregory Neil Shapiro children = 0; 27214e4196cbSGregory Neil Shapiro chldwasblocked = sm_blocksignal(SIGCHLD); 2722c2aa98e2SPeter Wemm 2723065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2724065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2725c2aa98e2SPeter Wemm { 27264e4196cbSGregory Neil Shapiro pid = ProcListVec[i].proc_pid; 27274e4196cbSGregory Neil Shapiro if (pid == NO_PID || pid == CurrentPid) 2728c2aa98e2SPeter Wemm continue; 27294e4196cbSGregory Neil Shapiro if (kill(pid, 0) < 0) 2730c2aa98e2SPeter Wemm { 2731c2aa98e2SPeter Wemm if (LogLevel > 3) 2732c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 2733c2aa98e2SPeter Wemm "proc_list_probe: lost pid %d", 2734065a643dSPeter Wemm (int) ProcListVec[i].proc_pid); 2735065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 273640266059SGregory Neil Shapiro SM_FREE_CLR(ProcListVec[i].proc_task); 2737c2aa98e2SPeter Wemm CurChildren--; 2738c2aa98e2SPeter Wemm } 27394e4196cbSGregory Neil Shapiro else 27404e4196cbSGregory Neil Shapiro { 27414e4196cbSGregory Neil Shapiro ++children; 27424e4196cbSGregory Neil Shapiro } 2743c2aa98e2SPeter Wemm } 2744c2aa98e2SPeter Wemm if (CurChildren < 0) 2745c2aa98e2SPeter Wemm CurChildren = 0; 27464e4196cbSGregory Neil Shapiro if (chldwasblocked == 0) 27474e4196cbSGregory Neil Shapiro (void) sm_releasesignal(SIGCHLD); 2748af9557fdSGregory Neil Shapiro if (LogLevel > 10 && children != CurChildren && CurrentPid == DaemonPid) 27494e4196cbSGregory Neil Shapiro { 27504e4196cbSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, 27514e4196cbSGregory Neil Shapiro "proc_list_probe: found %d children, expected %d", 27524e4196cbSGregory Neil Shapiro children, CurChildren); 27534e4196cbSGregory Neil Shapiro } 2754c2aa98e2SPeter Wemm } 275540266059SGregory Neil Shapiro 275640266059SGregory Neil Shapiro /* 2757065a643dSPeter Wemm ** PROC_LIST_DISPLAY -- display the process list 2758065a643dSPeter Wemm ** 2759065a643dSPeter Wemm ** Parameters: 2760065a643dSPeter Wemm ** out -- output file pointer 276140266059SGregory Neil Shapiro ** prefix -- string to output in front of each line. 2762065a643dSPeter Wemm ** 2763065a643dSPeter Wemm ** Returns: 2764065a643dSPeter Wemm ** none. 2765065a643dSPeter Wemm */ 2766065a643dSPeter Wemm 2767065a643dSPeter Wemm void 276840266059SGregory Neil Shapiro proc_list_display(out, prefix) 276940266059SGregory Neil Shapiro SM_FILE_T *out; 277040266059SGregory Neil Shapiro char *prefix; 2771065a643dSPeter Wemm { 2772065a643dSPeter Wemm int i; 2773065a643dSPeter Wemm 2774065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2775065a643dSPeter Wemm { 2776065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2777065a643dSPeter Wemm continue; 2778065a643dSPeter Wemm 277940266059SGregory Neil Shapiro (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "%s%d %s%s\n", 278040266059SGregory Neil Shapiro prefix, 278140266059SGregory Neil Shapiro (int) ProcListVec[i].proc_pid, 2782065a643dSPeter Wemm ProcListVec[i].proc_task != NULL ? 2783065a643dSPeter Wemm ProcListVec[i].proc_task : "(unknown)", 2784065a643dSPeter Wemm (OpMode == MD_SMTP || 2785065a643dSPeter Wemm OpMode == MD_DAEMON || 2786065a643dSPeter Wemm OpMode == MD_ARPAFTP) ? "\r" : ""); 2787065a643dSPeter Wemm } 2788065a643dSPeter Wemm } 278940266059SGregory Neil Shapiro 279040266059SGregory Neil Shapiro /* 279140266059SGregory Neil Shapiro ** PROC_LIST_SIGNAL -- send a signal to a type of process in the list 279213058a91SGregory Neil Shapiro ** 279313058a91SGregory Neil Shapiro ** Parameters: 279440266059SGregory Neil Shapiro ** type -- type of process to signal 279540266059SGregory Neil Shapiro ** signal -- the type of signal to send 279613058a91SGregory Neil Shapiro ** 279740266059SGregory Neil Shapiro ** Results: 279840266059SGregory Neil Shapiro ** none. 2799c2aa98e2SPeter Wemm ** 280040266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 280140266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 280240266059SGregory Neil Shapiro ** DOING. 2803c2aa98e2SPeter Wemm */ 2804c2aa98e2SPeter Wemm 280540266059SGregory Neil Shapiro void 280640266059SGregory Neil Shapiro proc_list_signal(type, signal) 280740266059SGregory Neil Shapiro int type; 280840266059SGregory Neil Shapiro int signal; 2809c2aa98e2SPeter Wemm { 281040266059SGregory Neil Shapiro int chldwasblocked; 281140266059SGregory Neil Shapiro int alrmwasblocked; 281240266059SGregory Neil Shapiro int i; 281340266059SGregory Neil Shapiro pid_t mypid = getpid(); 2814c2aa98e2SPeter Wemm 281540266059SGregory Neil Shapiro /* block these signals so that we may signal cleanly */ 281640266059SGregory Neil Shapiro chldwasblocked = sm_blocksignal(SIGCHLD); 281740266059SGregory Neil Shapiro alrmwasblocked = sm_blocksignal(SIGALRM); 281840266059SGregory Neil Shapiro 281940266059SGregory Neil Shapiro /* Find all processes of type and send signal */ 282040266059SGregory Neil Shapiro for (i = 0; i < ProcListSize; i++) 282140266059SGregory Neil Shapiro { 282240266059SGregory Neil Shapiro if (ProcListVec[i].proc_pid == NO_PID || 282340266059SGregory Neil Shapiro ProcListVec[i].proc_pid == mypid) 282440266059SGregory Neil Shapiro continue; 282540266059SGregory Neil Shapiro if (ProcListVec[i].proc_type != type) 282640266059SGregory Neil Shapiro continue; 282740266059SGregory Neil Shapiro (void) kill(ProcListVec[i].proc_pid, signal); 2828c2aa98e2SPeter Wemm } 2829c2aa98e2SPeter Wemm 283040266059SGregory Neil Shapiro /* restore the signals */ 283140266059SGregory Neil Shapiro if (alrmwasblocked == 0) 283240266059SGregory Neil Shapiro (void) sm_releasesignal(SIGALRM); 283340266059SGregory Neil Shapiro if (chldwasblocked == 0) 283440266059SGregory Neil Shapiro (void) sm_releasesignal(SIGCHLD); 2835c2aa98e2SPeter Wemm } 2836e92d3f3fSGregory Neil Shapiro 2837e92d3f3fSGregory Neil Shapiro /* 2838e92d3f3fSGregory Neil Shapiro ** COUNT_OPEN_CONNECTIONS 2839e92d3f3fSGregory Neil Shapiro ** 2840e92d3f3fSGregory Neil Shapiro ** Parameters: 2841e92d3f3fSGregory Neil Shapiro ** hostaddr - ClientAddress 2842e92d3f3fSGregory Neil Shapiro ** 2843e92d3f3fSGregory Neil Shapiro ** Returns: 2844e92d3f3fSGregory Neil Shapiro ** the number of open connections for this client 2845e92d3f3fSGregory Neil Shapiro ** 2846e92d3f3fSGregory Neil Shapiro */ 2847e92d3f3fSGregory Neil Shapiro 2848e92d3f3fSGregory Neil Shapiro int 2849e92d3f3fSGregory Neil Shapiro count_open_connections(hostaddr) 2850e92d3f3fSGregory Neil Shapiro SOCKADDR *hostaddr; 2851e92d3f3fSGregory Neil Shapiro { 2852e92d3f3fSGregory Neil Shapiro int i, n; 2853e92d3f3fSGregory Neil Shapiro 2854e92d3f3fSGregory Neil Shapiro if (hostaddr == NULL) 2855e92d3f3fSGregory Neil Shapiro return 0; 2856e92d3f3fSGregory Neil Shapiro n = 0; 2857e92d3f3fSGregory Neil Shapiro for (i = 0; i < ProcListSize; i++) 2858e92d3f3fSGregory Neil Shapiro { 2859e92d3f3fSGregory Neil Shapiro if (ProcListVec[i].proc_pid == NO_PID) 2860e92d3f3fSGregory Neil Shapiro continue; 2861e92d3f3fSGregory Neil Shapiro if (hostaddr->sa.sa_family != 2862e92d3f3fSGregory Neil Shapiro ProcListVec[i].proc_hostaddr.sa.sa_family) 2863e92d3f3fSGregory Neil Shapiro continue; 2864e92d3f3fSGregory Neil Shapiro #if NETINET 2865e92d3f3fSGregory Neil Shapiro if (hostaddr->sa.sa_family == AF_INET && 2866e92d3f3fSGregory Neil Shapiro (hostaddr->sin.sin_addr.s_addr == 2867e92d3f3fSGregory Neil Shapiro ProcListVec[i].proc_hostaddr.sin.sin_addr.s_addr)) 2868e92d3f3fSGregory Neil Shapiro n++; 2869e92d3f3fSGregory Neil Shapiro #endif /* NETINET */ 2870e92d3f3fSGregory Neil Shapiro #if NETINET6 2871e92d3f3fSGregory Neil Shapiro if (hostaddr->sa.sa_family == AF_INET6 && 2872e92d3f3fSGregory Neil Shapiro IN6_ARE_ADDR_EQUAL(&(hostaddr->sin6.sin6_addr), 2873e92d3f3fSGregory Neil Shapiro &(ProcListVec[i].proc_hostaddr.sin6.sin6_addr))) 2874e92d3f3fSGregory Neil Shapiro n++; 2875e92d3f3fSGregory Neil Shapiro #endif /* NETINET6 */ 2876e92d3f3fSGregory Neil Shapiro } 2877e92d3f3fSGregory Neil Shapiro return n; 2878e92d3f3fSGregory Neil Shapiro } 2879