17c478bd9Sstevel@tonic-gate /* 2*445f2479Sjbeck * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. 37c478bd9Sstevel@tonic-gate * All rights reserved. 47c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 57c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1993 67c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 97c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 107c478bd9Sstevel@tonic-gate * the sendmail distribution. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate */ 137c478bd9Sstevel@tonic-gate 147c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate #include <sendmail.h> 177c478bd9Sstevel@tonic-gate 18*445f2479Sjbeck SM_RCSID("@(#)$Id: util.c,v 8.392 2006/03/09 19:49:35 ca Exp $") 197c478bd9Sstevel@tonic-gate 207c478bd9Sstevel@tonic-gate #include <sysexits.h> 217c478bd9Sstevel@tonic-gate #include <sm/xtrap.h> 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate ** NEWSTR -- Create a copy of a C string 257c478bd9Sstevel@tonic-gate ** 267c478bd9Sstevel@tonic-gate ** Parameters: 277c478bd9Sstevel@tonic-gate ** s -- the string to copy. 287c478bd9Sstevel@tonic-gate ** 297c478bd9Sstevel@tonic-gate ** Returns: 307c478bd9Sstevel@tonic-gate ** pointer to newly allocated string. 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate char * 347c478bd9Sstevel@tonic-gate newstr(s) 357c478bd9Sstevel@tonic-gate const char *s; 367c478bd9Sstevel@tonic-gate { 377c478bd9Sstevel@tonic-gate size_t l; 387c478bd9Sstevel@tonic-gate char *n; 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate l = strlen(s); 417c478bd9Sstevel@tonic-gate SM_ASSERT(l + 1 > l); 427c478bd9Sstevel@tonic-gate n = xalloc(l + 1); 437c478bd9Sstevel@tonic-gate sm_strlcpy(n, s, l + 1); 447c478bd9Sstevel@tonic-gate return n; 457c478bd9Sstevel@tonic-gate } 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate ** ADDQUOTES -- Adds quotes & quote bits to a string. 497c478bd9Sstevel@tonic-gate ** 507c478bd9Sstevel@tonic-gate ** Runs through a string and adds backslashes and quote bits. 517c478bd9Sstevel@tonic-gate ** 527c478bd9Sstevel@tonic-gate ** Parameters: 537c478bd9Sstevel@tonic-gate ** s -- the string to modify. 547c478bd9Sstevel@tonic-gate ** rpool -- resource pool from which to allocate result 557c478bd9Sstevel@tonic-gate ** 567c478bd9Sstevel@tonic-gate ** Returns: 577c478bd9Sstevel@tonic-gate ** pointer to quoted string. 587c478bd9Sstevel@tonic-gate */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate char * 617c478bd9Sstevel@tonic-gate addquotes(s, rpool) 627c478bd9Sstevel@tonic-gate char *s; 637c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 647c478bd9Sstevel@tonic-gate { 657c478bd9Sstevel@tonic-gate int len = 0; 667c478bd9Sstevel@tonic-gate char c; 677c478bd9Sstevel@tonic-gate char *p = s, *q, *r; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if (s == NULL) 707c478bd9Sstevel@tonic-gate return NULL; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* Find length of quoted string */ 737c478bd9Sstevel@tonic-gate while ((c = *p++) != '\0') 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate len++; 767c478bd9Sstevel@tonic-gate if (c == '\\' || c == '"') 777c478bd9Sstevel@tonic-gate len++; 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate q = r = sm_rpool_malloc_x(rpool, len + 3); 817c478bd9Sstevel@tonic-gate p = s; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* add leading quote */ 847c478bd9Sstevel@tonic-gate *q++ = '"'; 857c478bd9Sstevel@tonic-gate while ((c = *p++) != '\0') 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate /* quote \ or " */ 887c478bd9Sstevel@tonic-gate if (c == '\\' || c == '"') 897c478bd9Sstevel@tonic-gate *q++ = '\\'; 907c478bd9Sstevel@tonic-gate *q++ = c; 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate *q++ = '"'; 937c478bd9Sstevel@tonic-gate *q = '\0'; 947c478bd9Sstevel@tonic-gate return r; 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate ** STRIPBACKSLASH -- Strip all leading backslashes from a string, provided 997c478bd9Sstevel@tonic-gate ** the following character is alpha-numerical. 1007c478bd9Sstevel@tonic-gate ** 1017c478bd9Sstevel@tonic-gate ** This is done in place. 1027c478bd9Sstevel@tonic-gate ** 1037c478bd9Sstevel@tonic-gate ** Parameters: 1047c478bd9Sstevel@tonic-gate ** s -- the string to strip. 1057c478bd9Sstevel@tonic-gate ** 1067c478bd9Sstevel@tonic-gate ** Returns: 1077c478bd9Sstevel@tonic-gate ** none. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate void 1117c478bd9Sstevel@tonic-gate stripbackslash(s) 1127c478bd9Sstevel@tonic-gate char *s; 1137c478bd9Sstevel@tonic-gate { 1147c478bd9Sstevel@tonic-gate char *p, *q, c; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate if (s == NULL || *s == '\0') 1177c478bd9Sstevel@tonic-gate return; 1187c478bd9Sstevel@tonic-gate p = q = s; 1197c478bd9Sstevel@tonic-gate while (*p == '\\' && (p[1] == '\\' || (isascii(p[1]) && isalnum(p[1])))) 1207c478bd9Sstevel@tonic-gate p++; 1217c478bd9Sstevel@tonic-gate do 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate c = *q++ = *p++; 1247c478bd9Sstevel@tonic-gate } while (c != '\0'); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate ** RFC822_STRING -- Checks string for proper RFC822 string quoting. 1297c478bd9Sstevel@tonic-gate ** 1307c478bd9Sstevel@tonic-gate ** Runs through a string and verifies RFC822 special characters 1317c478bd9Sstevel@tonic-gate ** are only found inside comments, quoted strings, or backslash 1327c478bd9Sstevel@tonic-gate ** escaped. Also verified balanced quotes and parenthesis. 1337c478bd9Sstevel@tonic-gate ** 1347c478bd9Sstevel@tonic-gate ** Parameters: 1357c478bd9Sstevel@tonic-gate ** s -- the string to modify. 1367c478bd9Sstevel@tonic-gate ** 1377c478bd9Sstevel@tonic-gate ** Returns: 1387c478bd9Sstevel@tonic-gate ** true iff the string is RFC822 compliant, false otherwise. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate bool 1427c478bd9Sstevel@tonic-gate rfc822_string(s) 1437c478bd9Sstevel@tonic-gate char *s; 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate bool quoted = false; 1467c478bd9Sstevel@tonic-gate int commentlev = 0; 1477c478bd9Sstevel@tonic-gate char *c = s; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if (s == NULL) 1507c478bd9Sstevel@tonic-gate return false; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate while (*c != '\0') 1537c478bd9Sstevel@tonic-gate { 1547c478bd9Sstevel@tonic-gate /* escaped character */ 1557c478bd9Sstevel@tonic-gate if (*c == '\\') 1567c478bd9Sstevel@tonic-gate { 1577c478bd9Sstevel@tonic-gate c++; 1587c478bd9Sstevel@tonic-gate if (*c == '\0') 1597c478bd9Sstevel@tonic-gate return false; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate else if (commentlev == 0 && *c == '"') 1627c478bd9Sstevel@tonic-gate quoted = !quoted; 1637c478bd9Sstevel@tonic-gate else if (!quoted) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate if (*c == ')') 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate /* unbalanced ')' */ 1687c478bd9Sstevel@tonic-gate if (commentlev == 0) 1697c478bd9Sstevel@tonic-gate return false; 1707c478bd9Sstevel@tonic-gate else 1717c478bd9Sstevel@tonic-gate commentlev--; 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate else if (*c == '(') 1747c478bd9Sstevel@tonic-gate commentlev++; 1757c478bd9Sstevel@tonic-gate else if (commentlev == 0 && 1767c478bd9Sstevel@tonic-gate strchr(MustQuoteChars, *c) != NULL) 1777c478bd9Sstevel@tonic-gate return false; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate c++; 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* unbalanced '"' or '(' */ 1837c478bd9Sstevel@tonic-gate return !quoted && commentlev == 0; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate ** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string 1877c478bd9Sstevel@tonic-gate ** 1887c478bd9Sstevel@tonic-gate ** Arbitrarily shorten (in place) an RFC822 string and rebalance 1897c478bd9Sstevel@tonic-gate ** comments and quotes. 1907c478bd9Sstevel@tonic-gate ** 1917c478bd9Sstevel@tonic-gate ** Parameters: 1927c478bd9Sstevel@tonic-gate ** string -- the string to shorten 1937c478bd9Sstevel@tonic-gate ** length -- the maximum size, 0 if no maximum 1947c478bd9Sstevel@tonic-gate ** 1957c478bd9Sstevel@tonic-gate ** Returns: 1967c478bd9Sstevel@tonic-gate ** true if string is changed, false otherwise 1977c478bd9Sstevel@tonic-gate ** 1987c478bd9Sstevel@tonic-gate ** Side Effects: 1997c478bd9Sstevel@tonic-gate ** Changes string in place, possibly resulting 2007c478bd9Sstevel@tonic-gate ** in a shorter string. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate bool 2047c478bd9Sstevel@tonic-gate shorten_rfc822_string(string, length) 2057c478bd9Sstevel@tonic-gate char *string; 2067c478bd9Sstevel@tonic-gate size_t length; 2077c478bd9Sstevel@tonic-gate { 2087c478bd9Sstevel@tonic-gate bool backslash = false; 2097c478bd9Sstevel@tonic-gate bool modified = false; 2107c478bd9Sstevel@tonic-gate bool quoted = false; 2117c478bd9Sstevel@tonic-gate size_t slen; 2127c478bd9Sstevel@tonic-gate int parencount = 0; 2137c478bd9Sstevel@tonic-gate char *ptr = string; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate ** If have to rebalance an already short enough string, 2177c478bd9Sstevel@tonic-gate ** need to do it within allocated space. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate slen = strlen(string); 2217c478bd9Sstevel@tonic-gate if (length == 0 || slen < length) 2227c478bd9Sstevel@tonic-gate length = slen; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate while (*ptr != '\0') 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate if (backslash) 2277c478bd9Sstevel@tonic-gate { 2287c478bd9Sstevel@tonic-gate backslash = false; 2297c478bd9Sstevel@tonic-gate goto increment; 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if (*ptr == '\\') 2337c478bd9Sstevel@tonic-gate backslash = true; 2347c478bd9Sstevel@tonic-gate else if (*ptr == '(') 2357c478bd9Sstevel@tonic-gate { 2367c478bd9Sstevel@tonic-gate if (!quoted) 2377c478bd9Sstevel@tonic-gate parencount++; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate else if (*ptr == ')') 2407c478bd9Sstevel@tonic-gate { 2417c478bd9Sstevel@tonic-gate if (--parencount < 0) 2427c478bd9Sstevel@tonic-gate parencount = 0; 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* Inside a comment, quotes don't matter */ 2467c478bd9Sstevel@tonic-gate if (parencount <= 0 && *ptr == '"') 2477c478bd9Sstevel@tonic-gate quoted = !quoted; 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate increment: 2507c478bd9Sstevel@tonic-gate /* Check for sufficient space for next character */ 2517c478bd9Sstevel@tonic-gate if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) + 2527c478bd9Sstevel@tonic-gate parencount + 2537c478bd9Sstevel@tonic-gate (quoted ? 1 : 0))) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate /* Not enough, backtrack */ 2567c478bd9Sstevel@tonic-gate if (*ptr == '\\') 2577c478bd9Sstevel@tonic-gate backslash = false; 2587c478bd9Sstevel@tonic-gate else if (*ptr == '(' && !quoted) 2597c478bd9Sstevel@tonic-gate parencount--; 2607c478bd9Sstevel@tonic-gate else if (*ptr == '"' && parencount == 0) 2617c478bd9Sstevel@tonic-gate quoted = false; 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate ptr++; 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* Rebalance */ 2687c478bd9Sstevel@tonic-gate while (parencount-- > 0) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate if (*ptr != ')') 2717c478bd9Sstevel@tonic-gate { 2727c478bd9Sstevel@tonic-gate modified = true; 2737c478bd9Sstevel@tonic-gate *ptr = ')'; 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate ptr++; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate if (quoted) 2787c478bd9Sstevel@tonic-gate { 2797c478bd9Sstevel@tonic-gate if (*ptr != '"') 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate modified = true; 2827c478bd9Sstevel@tonic-gate *ptr = '"'; 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate ptr++; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate if (*ptr != '\0') 2877c478bd9Sstevel@tonic-gate { 2887c478bd9Sstevel@tonic-gate modified = true; 2897c478bd9Sstevel@tonic-gate *ptr = '\0'; 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate return modified; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate ** FIND_CHARACTER -- find an unquoted character in an RFC822 string 2957c478bd9Sstevel@tonic-gate ** 2967c478bd9Sstevel@tonic-gate ** Find an unquoted, non-commented character in an RFC822 2977c478bd9Sstevel@tonic-gate ** string and return a pointer to its location in the 2987c478bd9Sstevel@tonic-gate ** string. 2997c478bd9Sstevel@tonic-gate ** 3007c478bd9Sstevel@tonic-gate ** Parameters: 3017c478bd9Sstevel@tonic-gate ** string -- the string to search 3027c478bd9Sstevel@tonic-gate ** character -- the character to find 3037c478bd9Sstevel@tonic-gate ** 3047c478bd9Sstevel@tonic-gate ** Returns: 3057c478bd9Sstevel@tonic-gate ** pointer to the character, or 3067c478bd9Sstevel@tonic-gate ** a pointer to the end of the line if character is not found 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate char * 3107c478bd9Sstevel@tonic-gate find_character(string, character) 3117c478bd9Sstevel@tonic-gate char *string; 3127c478bd9Sstevel@tonic-gate int character; 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate bool backslash = false; 3157c478bd9Sstevel@tonic-gate bool quoted = false; 3167c478bd9Sstevel@tonic-gate int parencount = 0; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate while (string != NULL && *string != '\0') 3197c478bd9Sstevel@tonic-gate { 3207c478bd9Sstevel@tonic-gate if (backslash) 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate backslash = false; 3237c478bd9Sstevel@tonic-gate if (!quoted && character == '\\' && *string == '\\') 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate string++; 3267c478bd9Sstevel@tonic-gate continue; 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate switch (*string) 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate case '\\': 3317c478bd9Sstevel@tonic-gate backslash = true; 3327c478bd9Sstevel@tonic-gate break; 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate case '(': 3357c478bd9Sstevel@tonic-gate if (!quoted) 3367c478bd9Sstevel@tonic-gate parencount++; 3377c478bd9Sstevel@tonic-gate break; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate case ')': 3407c478bd9Sstevel@tonic-gate if (--parencount < 0) 3417c478bd9Sstevel@tonic-gate parencount = 0; 3427c478bd9Sstevel@tonic-gate break; 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* Inside a comment, nothing matters */ 3467c478bd9Sstevel@tonic-gate if (parencount > 0) 3477c478bd9Sstevel@tonic-gate { 3487c478bd9Sstevel@tonic-gate string++; 3497c478bd9Sstevel@tonic-gate continue; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate if (*string == '"') 3537c478bd9Sstevel@tonic-gate quoted = !quoted; 3547c478bd9Sstevel@tonic-gate else if (*string == character && !quoted) 3557c478bd9Sstevel@tonic-gate break; 3567c478bd9Sstevel@tonic-gate string++; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* Return pointer to the character */ 3607c478bd9Sstevel@tonic-gate return string; 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate ** CHECK_BODYTYPE -- check bodytype parameter 3657c478bd9Sstevel@tonic-gate ** 3667c478bd9Sstevel@tonic-gate ** Parameters: 3677c478bd9Sstevel@tonic-gate ** bodytype -- bodytype parameter 3687c478bd9Sstevel@tonic-gate ** 3697c478bd9Sstevel@tonic-gate ** Returns: 3707c478bd9Sstevel@tonic-gate ** BODYTYPE_* according to parameter 3717c478bd9Sstevel@tonic-gate ** 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate int 3757c478bd9Sstevel@tonic-gate check_bodytype(bodytype) 3767c478bd9Sstevel@tonic-gate char *bodytype; 3777c478bd9Sstevel@tonic-gate { 3787c478bd9Sstevel@tonic-gate /* check body type for legality */ 3797c478bd9Sstevel@tonic-gate if (bodytype == NULL) 3807c478bd9Sstevel@tonic-gate return BODYTYPE_NONE; 3817c478bd9Sstevel@tonic-gate if (sm_strcasecmp(bodytype, "7BIT") == 0) 3827c478bd9Sstevel@tonic-gate return BODYTYPE_7BIT; 3837c478bd9Sstevel@tonic-gate if (sm_strcasecmp(bodytype, "8BITMIME") == 0) 3847c478bd9Sstevel@tonic-gate return BODYTYPE_8BITMIME; 3857c478bd9Sstevel@tonic-gate return BODYTYPE_ILLEGAL; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate #if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate ** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..." 3917c478bd9Sstevel@tonic-gate ** 3927c478bd9Sstevel@tonic-gate ** Parameters: 3937c478bd9Sstevel@tonic-gate ** str -- string to truncate 3947c478bd9Sstevel@tonic-gate ** len -- maximum length (including '\0') (0 for unlimited) 3957c478bd9Sstevel@tonic-gate ** delim -- delimiter character 3967c478bd9Sstevel@tonic-gate ** 3977c478bd9Sstevel@tonic-gate ** Returns: 3987c478bd9Sstevel@tonic-gate ** None. 3997c478bd9Sstevel@tonic-gate */ 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate void 4027c478bd9Sstevel@tonic-gate truncate_at_delim(str, len, delim) 4037c478bd9Sstevel@tonic-gate char *str; 4047c478bd9Sstevel@tonic-gate size_t len; 4057c478bd9Sstevel@tonic-gate int delim; 4067c478bd9Sstevel@tonic-gate { 4077c478bd9Sstevel@tonic-gate char *p; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if (str == NULL || len == 0 || strlen(str) < len) 4107c478bd9Sstevel@tonic-gate return; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate *(str + len - 1) = '\0'; 4137c478bd9Sstevel@tonic-gate while ((p = strrchr(str, delim)) != NULL) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate *p = '\0'; 4167c478bd9Sstevel@tonic-gate if (p - str + 4 < len) 4177c478bd9Sstevel@tonic-gate { 4187c478bd9Sstevel@tonic-gate *p++ = (char) delim; 4197c478bd9Sstevel@tonic-gate *p = '\0'; 4207c478bd9Sstevel@tonic-gate (void) sm_strlcat(str, "...", len); 4217c478bd9Sstevel@tonic-gate return; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* Couldn't find a place to append "..." */ 4267c478bd9Sstevel@tonic-gate if (len > 3) 4277c478bd9Sstevel@tonic-gate (void) sm_strlcpy(str, "...", len); 4287c478bd9Sstevel@tonic-gate else 4297c478bd9Sstevel@tonic-gate str[0] = '\0'; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate #endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */ 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate ** XALLOC -- Allocate memory, raise an exception on error 4347c478bd9Sstevel@tonic-gate ** 4357c478bd9Sstevel@tonic-gate ** Parameters: 4367c478bd9Sstevel@tonic-gate ** sz -- size of area to allocate. 4377c478bd9Sstevel@tonic-gate ** 4387c478bd9Sstevel@tonic-gate ** Returns: 4397c478bd9Sstevel@tonic-gate ** pointer to data region. 4407c478bd9Sstevel@tonic-gate ** 4417c478bd9Sstevel@tonic-gate ** Exceptions: 4427c478bd9Sstevel@tonic-gate ** SmHeapOutOfMemory (F:sm.heap) -- cannot allocate memory 4437c478bd9Sstevel@tonic-gate ** 4447c478bd9Sstevel@tonic-gate ** Side Effects: 4457c478bd9Sstevel@tonic-gate ** Memory is allocated. 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate char * 4497c478bd9Sstevel@tonic-gate #if SM_HEAP_CHECK 4507c478bd9Sstevel@tonic-gate xalloc_tagged(sz, file, line) 4517c478bd9Sstevel@tonic-gate register int sz; 4527c478bd9Sstevel@tonic-gate char *file; 4537c478bd9Sstevel@tonic-gate int line; 4547c478bd9Sstevel@tonic-gate #else /* SM_HEAP_CHECK */ 4557c478bd9Sstevel@tonic-gate xalloc(sz) 4567c478bd9Sstevel@tonic-gate register int sz; 4577c478bd9Sstevel@tonic-gate #endif /* SM_HEAP_CHECK */ 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate register char *p; 4607c478bd9Sstevel@tonic-gate 461*445f2479Sjbeck SM_REQUIRE(sz >= 0); 462*445f2479Sjbeck 4637c478bd9Sstevel@tonic-gate /* some systems can't handle size zero mallocs */ 4647c478bd9Sstevel@tonic-gate if (sz <= 0) 4657c478bd9Sstevel@tonic-gate sz = 1; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate /* scaffolding for testing error handling code */ 4687c478bd9Sstevel@tonic-gate sm_xtrap_raise_x(&SmHeapOutOfMemory); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate p = sm_malloc_tagged((unsigned) sz, file, line, sm_heap_group()); 4717c478bd9Sstevel@tonic-gate if (p == NULL) 4727c478bd9Sstevel@tonic-gate { 4737c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate return p; 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate ** COPYPLIST -- copy list of pointers. 4797c478bd9Sstevel@tonic-gate ** 4807c478bd9Sstevel@tonic-gate ** This routine is the equivalent of strdup for lists of 4817c478bd9Sstevel@tonic-gate ** pointers. 4827c478bd9Sstevel@tonic-gate ** 4837c478bd9Sstevel@tonic-gate ** Parameters: 4847c478bd9Sstevel@tonic-gate ** list -- list of pointers to copy. 4857c478bd9Sstevel@tonic-gate ** Must be NULL terminated. 4867c478bd9Sstevel@tonic-gate ** copycont -- if true, copy the contents of the vector 4877c478bd9Sstevel@tonic-gate ** (which must be a string) also. 4887c478bd9Sstevel@tonic-gate ** rpool -- resource pool from which to allocate storage, 4897c478bd9Sstevel@tonic-gate ** or NULL 4907c478bd9Sstevel@tonic-gate ** 4917c478bd9Sstevel@tonic-gate ** Returns: 4927c478bd9Sstevel@tonic-gate ** a copy of 'list'. 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate char ** 4967c478bd9Sstevel@tonic-gate copyplist(list, copycont, rpool) 4977c478bd9Sstevel@tonic-gate char **list; 4987c478bd9Sstevel@tonic-gate bool copycont; 4997c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 5007c478bd9Sstevel@tonic-gate { 5017c478bd9Sstevel@tonic-gate register char **vp; 5027c478bd9Sstevel@tonic-gate register char **newvp; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate for (vp = list; *vp != NULL; vp++) 5057c478bd9Sstevel@tonic-gate continue; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate vp++; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof *vp); 5107c478bd9Sstevel@tonic-gate memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (copycont) 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate for (vp = newvp; *vp != NULL; vp++) 5157c478bd9Sstevel@tonic-gate *vp = sm_rpool_strdup_x(rpool, *vp); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate return newvp; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate /* 5217c478bd9Sstevel@tonic-gate ** COPYQUEUE -- copy address queue. 5227c478bd9Sstevel@tonic-gate ** 5237c478bd9Sstevel@tonic-gate ** This routine is the equivalent of strdup for address queues; 5247c478bd9Sstevel@tonic-gate ** addresses marked as QS_IS_DEAD() aren't copied 5257c478bd9Sstevel@tonic-gate ** 5267c478bd9Sstevel@tonic-gate ** Parameters: 5277c478bd9Sstevel@tonic-gate ** addr -- list of address structures to copy. 5287c478bd9Sstevel@tonic-gate ** rpool -- resource pool from which to allocate storage 5297c478bd9Sstevel@tonic-gate ** 5307c478bd9Sstevel@tonic-gate ** Returns: 5317c478bd9Sstevel@tonic-gate ** a copy of 'addr'. 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate ADDRESS * 5357c478bd9Sstevel@tonic-gate copyqueue(addr, rpool) 5367c478bd9Sstevel@tonic-gate ADDRESS *addr; 5377c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool; 5387c478bd9Sstevel@tonic-gate { 5397c478bd9Sstevel@tonic-gate register ADDRESS *newaddr; 5407c478bd9Sstevel@tonic-gate ADDRESS *ret; 5417c478bd9Sstevel@tonic-gate register ADDRESS **tail = &ret; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate while (addr != NULL) 5447c478bd9Sstevel@tonic-gate { 5457c478bd9Sstevel@tonic-gate if (!QS_IS_DEAD(addr->q_state)) 5467c478bd9Sstevel@tonic-gate { 5477c478bd9Sstevel@tonic-gate newaddr = (ADDRESS *) sm_rpool_malloc_x(rpool, 5487c478bd9Sstevel@tonic-gate sizeof *newaddr); 5497c478bd9Sstevel@tonic-gate STRUCTCOPY(*addr, *newaddr); 5507c478bd9Sstevel@tonic-gate *tail = newaddr; 5517c478bd9Sstevel@tonic-gate tail = &newaddr->q_next; 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate addr = addr->q_next; 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate *tail = NULL; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate return ret; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate ** LOG_SENDMAIL_PID -- record sendmail pid and command line. 5617c478bd9Sstevel@tonic-gate ** 5627c478bd9Sstevel@tonic-gate ** Parameters: 5637c478bd9Sstevel@tonic-gate ** e -- the current envelope. 5647c478bd9Sstevel@tonic-gate ** 5657c478bd9Sstevel@tonic-gate ** Returns: 5667c478bd9Sstevel@tonic-gate ** none. 5677c478bd9Sstevel@tonic-gate ** 5687c478bd9Sstevel@tonic-gate ** Side Effects: 5697c478bd9Sstevel@tonic-gate ** writes pidfile, logs command line. 5707c478bd9Sstevel@tonic-gate ** keeps file open and locked to prevent overwrite of active file 5717c478bd9Sstevel@tonic-gate */ 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate static SM_FILE_T *Pidf = NULL; 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate void 5767c478bd9Sstevel@tonic-gate log_sendmail_pid(e) 5777c478bd9Sstevel@tonic-gate ENVELOPE *e; 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate long sff; 5807c478bd9Sstevel@tonic-gate char pidpath[MAXPATHLEN]; 5817c478bd9Sstevel@tonic-gate extern char *CommandLineArgs; 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* write the pid to the log file for posterity */ 5847c478bd9Sstevel@tonic-gate sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT|SFF_NBLOCK; 5857c478bd9Sstevel@tonic-gate if (TrustedUid != 0 && RealUid == TrustedUid) 5867c478bd9Sstevel@tonic-gate sff |= SFF_OPENASROOT; 5877c478bd9Sstevel@tonic-gate expand(PidFile, pidpath, sizeof pidpath, e); 5887c478bd9Sstevel@tonic-gate Pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff); 5897c478bd9Sstevel@tonic-gate if (Pidf == NULL) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate if (errno == EWOULDBLOCK) 5927c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 5937c478bd9Sstevel@tonic-gate "unable to write pid to %s: file in use by another process", 5947c478bd9Sstevel@tonic-gate pidpath); 5957c478bd9Sstevel@tonic-gate else 5967c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 5977c478bd9Sstevel@tonic-gate "unable to write pid to %s: %s", 5987c478bd9Sstevel@tonic-gate pidpath, sm_errstring(errno)); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate else 6017c478bd9Sstevel@tonic-gate { 6027c478bd9Sstevel@tonic-gate PidFilePid = getpid(); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* write the process id on line 1 */ 6057c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(Pidf, SM_TIME_DEFAULT, "%ld\n", 6067c478bd9Sstevel@tonic-gate (long) PidFilePid); 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* line 2 contains all command line flags */ 6097c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(Pidf, SM_TIME_DEFAULT, "%s\n", 6107c478bd9Sstevel@tonic-gate CommandLineArgs); 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate /* flush */ 6137c478bd9Sstevel@tonic-gate (void) sm_io_flush(Pidf, SM_TIME_DEFAULT); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate ** Leave pid file open until process ends 6177c478bd9Sstevel@tonic-gate ** so it's not overwritten by another 6187c478bd9Sstevel@tonic-gate ** process. 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate if (LogLevel > 9) 6227c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, "started as: %s", CommandLineArgs); 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate /* 6267c478bd9Sstevel@tonic-gate ** CLOSE_SENDMAIL_PID -- close sendmail pid file 6277c478bd9Sstevel@tonic-gate ** 6287c478bd9Sstevel@tonic-gate ** Parameters: 6297c478bd9Sstevel@tonic-gate ** none. 6307c478bd9Sstevel@tonic-gate ** 6317c478bd9Sstevel@tonic-gate ** Returns: 6327c478bd9Sstevel@tonic-gate ** none. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate void 6367c478bd9Sstevel@tonic-gate close_sendmail_pid() 6377c478bd9Sstevel@tonic-gate { 6387c478bd9Sstevel@tonic-gate if (Pidf == NULL) 6397c478bd9Sstevel@tonic-gate return; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate (void) sm_io_close(Pidf, SM_TIME_DEFAULT); 6427c478bd9Sstevel@tonic-gate Pidf = NULL; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate ** SET_DELIVERY_MODE -- set and record the delivery mode 6477c478bd9Sstevel@tonic-gate ** 6487c478bd9Sstevel@tonic-gate ** Parameters: 6497c478bd9Sstevel@tonic-gate ** mode -- delivery mode 6507c478bd9Sstevel@tonic-gate ** e -- the current envelope. 6517c478bd9Sstevel@tonic-gate ** 6527c478bd9Sstevel@tonic-gate ** Returns: 6537c478bd9Sstevel@tonic-gate ** none. 6547c478bd9Sstevel@tonic-gate ** 6557c478bd9Sstevel@tonic-gate ** Side Effects: 6567c478bd9Sstevel@tonic-gate ** sets {deliveryMode} macro 6577c478bd9Sstevel@tonic-gate */ 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate void 6607c478bd9Sstevel@tonic-gate set_delivery_mode(mode, e) 6617c478bd9Sstevel@tonic-gate int mode; 6627c478bd9Sstevel@tonic-gate ENVELOPE *e; 6637c478bd9Sstevel@tonic-gate { 6647c478bd9Sstevel@tonic-gate char buf[2]; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate e->e_sendmode = (char) mode; 6677c478bd9Sstevel@tonic-gate buf[0] = (char) mode; 6687c478bd9Sstevel@tonic-gate buf[1] = '\0'; 6697c478bd9Sstevel@tonic-gate macdefine(&e->e_macro, A_TEMP, macid("{deliveryMode}"), buf); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate ** SET_OP_MODE -- set and record the op mode 6737c478bd9Sstevel@tonic-gate ** 6747c478bd9Sstevel@tonic-gate ** Parameters: 6757c478bd9Sstevel@tonic-gate ** mode -- op mode 6767c478bd9Sstevel@tonic-gate ** e -- the current envelope. 6777c478bd9Sstevel@tonic-gate ** 6787c478bd9Sstevel@tonic-gate ** Returns: 6797c478bd9Sstevel@tonic-gate ** none. 6807c478bd9Sstevel@tonic-gate ** 6817c478bd9Sstevel@tonic-gate ** Side Effects: 6827c478bd9Sstevel@tonic-gate ** sets {opMode} macro 6837c478bd9Sstevel@tonic-gate */ 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate void 6867c478bd9Sstevel@tonic-gate set_op_mode(mode) 6877c478bd9Sstevel@tonic-gate int mode; 6887c478bd9Sstevel@tonic-gate { 6897c478bd9Sstevel@tonic-gate char buf[2]; 6907c478bd9Sstevel@tonic-gate extern ENVELOPE BlankEnvelope; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate OpMode = (char) mode; 6937c478bd9Sstevel@tonic-gate buf[0] = (char) mode; 6947c478bd9Sstevel@tonic-gate buf[1] = '\0'; 6957c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, MID_OPMODE, buf); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate /* 6987c478bd9Sstevel@tonic-gate ** PRINTAV -- print argument vector. 6997c478bd9Sstevel@tonic-gate ** 7007c478bd9Sstevel@tonic-gate ** Parameters: 7017c478bd9Sstevel@tonic-gate ** fp -- output file pointer. 7027c478bd9Sstevel@tonic-gate ** av -- argument vector. 7037c478bd9Sstevel@tonic-gate ** 7047c478bd9Sstevel@tonic-gate ** Returns: 7057c478bd9Sstevel@tonic-gate ** none. 7067c478bd9Sstevel@tonic-gate ** 7077c478bd9Sstevel@tonic-gate ** Side Effects: 7087c478bd9Sstevel@tonic-gate ** prints av. 7097c478bd9Sstevel@tonic-gate */ 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate void 7127c478bd9Sstevel@tonic-gate printav(fp, av) 7137c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 7147c478bd9Sstevel@tonic-gate register char **av; 7157c478bd9Sstevel@tonic-gate { 7167c478bd9Sstevel@tonic-gate while (*av != NULL) 7177c478bd9Sstevel@tonic-gate { 7187c478bd9Sstevel@tonic-gate if (tTd(0, 44)) 7197c478bd9Sstevel@tonic-gate sm_dprintf("\n\t%08lx=", (unsigned long) *av); 7207c478bd9Sstevel@tonic-gate else 7217c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, ' '); 7227c478bd9Sstevel@tonic-gate xputs(fp, *av++); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\n'); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate /* 7277c478bd9Sstevel@tonic-gate ** XPUTS -- put string doing control escapes. 7287c478bd9Sstevel@tonic-gate ** 7297c478bd9Sstevel@tonic-gate ** Parameters: 7307c478bd9Sstevel@tonic-gate ** fp -- output file pointer. 7317c478bd9Sstevel@tonic-gate ** s -- string to put. 7327c478bd9Sstevel@tonic-gate ** 7337c478bd9Sstevel@tonic-gate ** Returns: 7347c478bd9Sstevel@tonic-gate ** none. 7357c478bd9Sstevel@tonic-gate ** 7367c478bd9Sstevel@tonic-gate ** Side Effects: 7377c478bd9Sstevel@tonic-gate ** output to stdout 7387c478bd9Sstevel@tonic-gate */ 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate void 7417c478bd9Sstevel@tonic-gate xputs(fp, s) 7427c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 7437c478bd9Sstevel@tonic-gate register const char *s; 7447c478bd9Sstevel@tonic-gate { 7457c478bd9Sstevel@tonic-gate register int c; 7467c478bd9Sstevel@tonic-gate register struct metamac *mp; 7477c478bd9Sstevel@tonic-gate bool shiftout = false; 7487c478bd9Sstevel@tonic-gate extern struct metamac MetaMacros[]; 7497c478bd9Sstevel@tonic-gate static SM_DEBUG_T DebugANSI = SM_DEBUG_INITIALIZER("ANSI", 7507c478bd9Sstevel@tonic-gate "@(#)$Debug: ANSI - enable reverse video in debug output $"); 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate ** TermEscape is set here, rather than in main(), 7547c478bd9Sstevel@tonic-gate ** because ANSI mode can be turned on or off at any time 7557c478bd9Sstevel@tonic-gate ** if we are in -bt rule testing mode. 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (sm_debug_unknown(&DebugANSI)) 7597c478bd9Sstevel@tonic-gate { 7607c478bd9Sstevel@tonic-gate if (sm_debug_active(&DebugANSI, 1)) 7617c478bd9Sstevel@tonic-gate { 7627c478bd9Sstevel@tonic-gate TermEscape.te_rv_on = "\033[7m"; 7637c478bd9Sstevel@tonic-gate TermEscape.te_rv_off = "\033[0m"; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate else 7667c478bd9Sstevel@tonic-gate { 7677c478bd9Sstevel@tonic-gate TermEscape.te_rv_on = ""; 7687c478bd9Sstevel@tonic-gate TermEscape.te_rv_off = ""; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate if (s == NULL) 7737c478bd9Sstevel@tonic-gate { 7747c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s<null>%s", 7757c478bd9Sstevel@tonic-gate TermEscape.te_rv_on, TermEscape.te_rv_off); 7767c478bd9Sstevel@tonic-gate return; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate while ((c = (*s++ & 0377)) != '\0') 7797c478bd9Sstevel@tonic-gate { 7807c478bd9Sstevel@tonic-gate if (shiftout) 7817c478bd9Sstevel@tonic-gate { 7827c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", 7837c478bd9Sstevel@tonic-gate TermEscape.te_rv_off); 7847c478bd9Sstevel@tonic-gate shiftout = false; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate if (!isascii(c)) 7877c478bd9Sstevel@tonic-gate { 7887c478bd9Sstevel@tonic-gate if (c == MATCHREPL) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 7917c478bd9Sstevel@tonic-gate "%s$", 7927c478bd9Sstevel@tonic-gate TermEscape.te_rv_on); 7937c478bd9Sstevel@tonic-gate shiftout = true; 7947c478bd9Sstevel@tonic-gate if (*s == '\0') 7957c478bd9Sstevel@tonic-gate continue; 7967c478bd9Sstevel@tonic-gate c = *s++ & 0377; 7977c478bd9Sstevel@tonic-gate goto printchar; 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate if (c == MACROEXPAND || c == MACRODEXPAND) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, 8027c478bd9Sstevel@tonic-gate "%s$", 8037c478bd9Sstevel@tonic-gate TermEscape.te_rv_on); 8047c478bd9Sstevel@tonic-gate if (c == MACRODEXPAND) 8057c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, 8067c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, '&'); 8077c478bd9Sstevel@tonic-gate shiftout = true; 8087c478bd9Sstevel@tonic-gate if (*s == '\0') 8097c478bd9Sstevel@tonic-gate continue; 8107c478bd9Sstevel@tonic-gate if (strchr("=~&?", *s) != NULL) 8117c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, 8127c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8137c478bd9Sstevel@tonic-gate *s++); 8147c478bd9Sstevel@tonic-gate if (bitset(0200, *s)) 8157c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, 8167c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8177c478bd9Sstevel@tonic-gate "{%s}", 8187c478bd9Sstevel@tonic-gate macname(bitidx(*s++))); 8197c478bd9Sstevel@tonic-gate else 8207c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, 8217c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8227c478bd9Sstevel@tonic-gate "%c", 8237c478bd9Sstevel@tonic-gate *s++); 8247c478bd9Sstevel@tonic-gate continue; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate for (mp = MetaMacros; mp->metaname != '\0'; mp++) 8277c478bd9Sstevel@tonic-gate { 8287c478bd9Sstevel@tonic-gate if (bitidx(mp->metaval) == c) 8297c478bd9Sstevel@tonic-gate { 8307c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, 8317c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8327c478bd9Sstevel@tonic-gate "%s$%c", 8337c478bd9Sstevel@tonic-gate TermEscape.te_rv_on, 8347c478bd9Sstevel@tonic-gate mp->metaname); 8357c478bd9Sstevel@tonic-gate shiftout = true; 8367c478bd9Sstevel@tonic-gate break; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate if (c == MATCHCLASS || c == MATCHNCLASS) 8407c478bd9Sstevel@tonic-gate { 8417c478bd9Sstevel@tonic-gate if (bitset(0200, *s)) 8427c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, 8437c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8447c478bd9Sstevel@tonic-gate "{%s}", 8457c478bd9Sstevel@tonic-gate macname(bitidx(*s++))); 8467c478bd9Sstevel@tonic-gate else if (*s != '\0') 8477c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, 8487c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8497c478bd9Sstevel@tonic-gate "%c", 8507c478bd9Sstevel@tonic-gate *s++); 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate if (mp->metaname != '\0') 8537c478bd9Sstevel@tonic-gate continue; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate /* unrecognized meta character */ 8567c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%sM-", 8577c478bd9Sstevel@tonic-gate TermEscape.te_rv_on); 8587c478bd9Sstevel@tonic-gate shiftout = true; 8597c478bd9Sstevel@tonic-gate c &= 0177; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate printchar: 8627c478bd9Sstevel@tonic-gate if (isprint(c)) 8637c478bd9Sstevel@tonic-gate { 8647c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, c); 8657c478bd9Sstevel@tonic-gate continue; 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate /* wasn't a meta-macro -- find another way to print it */ 8697c478bd9Sstevel@tonic-gate switch (c) 8707c478bd9Sstevel@tonic-gate { 8717c478bd9Sstevel@tonic-gate case '\n': 8727c478bd9Sstevel@tonic-gate c = 'n'; 8737c478bd9Sstevel@tonic-gate break; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate case '\r': 8767c478bd9Sstevel@tonic-gate c = 'r'; 8777c478bd9Sstevel@tonic-gate break; 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate case '\t': 8807c478bd9Sstevel@tonic-gate c = 't'; 8817c478bd9Sstevel@tonic-gate break; 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate if (!shiftout) 8847c478bd9Sstevel@tonic-gate { 8857c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", 8867c478bd9Sstevel@tonic-gate TermEscape.te_rv_on); 8877c478bd9Sstevel@tonic-gate shiftout = true; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate if (isprint(c)) 8907c478bd9Sstevel@tonic-gate { 8917c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\\'); 8927c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, c); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate else 8957c478bd9Sstevel@tonic-gate { 8967c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, '^'); 8977c478bd9Sstevel@tonic-gate (void) sm_io_putc(fp, SM_TIME_DEFAULT, c ^ 0100); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate if (shiftout) 9017c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", 9027c478bd9Sstevel@tonic-gate TermEscape.te_rv_off); 9037c478bd9Sstevel@tonic-gate (void) sm_io_flush(fp, SM_TIME_DEFAULT); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate /* 9067c478bd9Sstevel@tonic-gate ** MAKELOWER -- Translate a line into lower case 9077c478bd9Sstevel@tonic-gate ** 9087c478bd9Sstevel@tonic-gate ** Parameters: 9097c478bd9Sstevel@tonic-gate ** p -- the string to translate. If NULL, return is 9107c478bd9Sstevel@tonic-gate ** immediate. 9117c478bd9Sstevel@tonic-gate ** 9127c478bd9Sstevel@tonic-gate ** Returns: 9137c478bd9Sstevel@tonic-gate ** none. 9147c478bd9Sstevel@tonic-gate ** 9157c478bd9Sstevel@tonic-gate ** Side Effects: 9167c478bd9Sstevel@tonic-gate ** String pointed to by p is translated to lower case. 9177c478bd9Sstevel@tonic-gate */ 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate void 9207c478bd9Sstevel@tonic-gate makelower(p) 9217c478bd9Sstevel@tonic-gate register char *p; 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate register char c; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (p == NULL) 9267c478bd9Sstevel@tonic-gate return; 9277c478bd9Sstevel@tonic-gate for (; (c = *p) != '\0'; p++) 9287c478bd9Sstevel@tonic-gate if (isascii(c) && isupper(c)) 9297c478bd9Sstevel@tonic-gate *p = tolower(c); 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate /* 9327c478bd9Sstevel@tonic-gate ** FIXCRLF -- fix <CR><LF> in line. 9337c478bd9Sstevel@tonic-gate ** 9347c478bd9Sstevel@tonic-gate ** Looks for the <CR><LF> combination and turns it into the 9357c478bd9Sstevel@tonic-gate ** UNIX canonical <NL> character. It only takes one line, 9367c478bd9Sstevel@tonic-gate ** i.e., it is assumed that the first <NL> found is the end 9377c478bd9Sstevel@tonic-gate ** of the line. 9387c478bd9Sstevel@tonic-gate ** 9397c478bd9Sstevel@tonic-gate ** Parameters: 9407c478bd9Sstevel@tonic-gate ** line -- the line to fix. 9417c478bd9Sstevel@tonic-gate ** stripnl -- if true, strip the newline also. 9427c478bd9Sstevel@tonic-gate ** 9437c478bd9Sstevel@tonic-gate ** Returns: 9447c478bd9Sstevel@tonic-gate ** none. 9457c478bd9Sstevel@tonic-gate ** 9467c478bd9Sstevel@tonic-gate ** Side Effects: 9477c478bd9Sstevel@tonic-gate ** line is changed in place. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate void 9517c478bd9Sstevel@tonic-gate fixcrlf(line, stripnl) 9527c478bd9Sstevel@tonic-gate char *line; 9537c478bd9Sstevel@tonic-gate bool stripnl; 9547c478bd9Sstevel@tonic-gate { 9557c478bd9Sstevel@tonic-gate register char *p; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate p = strchr(line, '\n'); 9587c478bd9Sstevel@tonic-gate if (p == NULL) 9597c478bd9Sstevel@tonic-gate return; 9607c478bd9Sstevel@tonic-gate if (p > line && p[-1] == '\r') 9617c478bd9Sstevel@tonic-gate p--; 9627c478bd9Sstevel@tonic-gate if (!stripnl) 9637c478bd9Sstevel@tonic-gate *p++ = '\n'; 9647c478bd9Sstevel@tonic-gate *p = '\0'; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate /* 9677c478bd9Sstevel@tonic-gate ** PUTLINE -- put a line like fputs obeying SMTP conventions 9687c478bd9Sstevel@tonic-gate ** 9697c478bd9Sstevel@tonic-gate ** This routine always guarantees outputing a newline (or CRLF, 9707c478bd9Sstevel@tonic-gate ** as appropriate) at the end of the string. 9717c478bd9Sstevel@tonic-gate ** 9727c478bd9Sstevel@tonic-gate ** Parameters: 9737c478bd9Sstevel@tonic-gate ** l -- line to put. 9747c478bd9Sstevel@tonic-gate ** mci -- the mailer connection information. 9757c478bd9Sstevel@tonic-gate ** 9767c478bd9Sstevel@tonic-gate ** Returns: 977*445f2479Sjbeck ** true iff line was written successfully 9787c478bd9Sstevel@tonic-gate ** 9797c478bd9Sstevel@tonic-gate ** Side Effects: 9807c478bd9Sstevel@tonic-gate ** output of l to mci->mci_out. 9817c478bd9Sstevel@tonic-gate */ 9827c478bd9Sstevel@tonic-gate 983*445f2479Sjbeck bool 9847c478bd9Sstevel@tonic-gate putline(l, mci) 9857c478bd9Sstevel@tonic-gate register char *l; 9867c478bd9Sstevel@tonic-gate register MCI *mci; 9877c478bd9Sstevel@tonic-gate { 988*445f2479Sjbeck return putxline(l, strlen(l), mci, PXLF_MAPFROM); 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate /* 9917c478bd9Sstevel@tonic-gate ** PUTXLINE -- putline with flags bits. 9927c478bd9Sstevel@tonic-gate ** 9937c478bd9Sstevel@tonic-gate ** This routine always guarantees outputing a newline (or CRLF, 9947c478bd9Sstevel@tonic-gate ** as appropriate) at the end of the string. 9957c478bd9Sstevel@tonic-gate ** 9967c478bd9Sstevel@tonic-gate ** Parameters: 9977c478bd9Sstevel@tonic-gate ** l -- line to put. 9987c478bd9Sstevel@tonic-gate ** len -- the length of the line. 9997c478bd9Sstevel@tonic-gate ** mci -- the mailer connection information. 10007c478bd9Sstevel@tonic-gate ** pxflags -- flag bits: 10017c478bd9Sstevel@tonic-gate ** PXLF_MAPFROM -- map From_ to >From_. 10027c478bd9Sstevel@tonic-gate ** PXLF_STRIP8BIT -- strip 8th bit. 10037c478bd9Sstevel@tonic-gate ** PXLF_HEADER -- map bare newline in header to newline space. 10047c478bd9Sstevel@tonic-gate ** PXLF_NOADDEOL -- don't add an EOL if one wasn't present. 10057c478bd9Sstevel@tonic-gate ** 10067c478bd9Sstevel@tonic-gate ** Returns: 1007*445f2479Sjbeck ** true iff line was written successfully 10087c478bd9Sstevel@tonic-gate ** 10097c478bd9Sstevel@tonic-gate ** Side Effects: 10107c478bd9Sstevel@tonic-gate ** output of l to mci->mci_out. 10117c478bd9Sstevel@tonic-gate */ 10127c478bd9Sstevel@tonic-gate 1013*445f2479Sjbeck bool 10147c478bd9Sstevel@tonic-gate putxline(l, len, mci, pxflags) 10157c478bd9Sstevel@tonic-gate register char *l; 10167c478bd9Sstevel@tonic-gate size_t len; 10177c478bd9Sstevel@tonic-gate register MCI *mci; 10187c478bd9Sstevel@tonic-gate int pxflags; 10197c478bd9Sstevel@tonic-gate { 10207c478bd9Sstevel@tonic-gate bool dead = false; 10217c478bd9Sstevel@tonic-gate register char *p, *end; 10227c478bd9Sstevel@tonic-gate int slop = 0; 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate /* strip out 0200 bits -- these can look like TELNET protocol */ 10257c478bd9Sstevel@tonic-gate if (bitset(MCIF_7BIT, mci->mci_flags) || 10267c478bd9Sstevel@tonic-gate bitset(PXLF_STRIP8BIT, pxflags)) 10277c478bd9Sstevel@tonic-gate { 10287c478bd9Sstevel@tonic-gate register char svchar; 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate for (p = l; (svchar = *p) != '\0'; ++p) 10317c478bd9Sstevel@tonic-gate if (bitset(0200, svchar)) 10327c478bd9Sstevel@tonic-gate *p = svchar &~ 0200; 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate end = l + len; 10367c478bd9Sstevel@tonic-gate do 10377c478bd9Sstevel@tonic-gate { 10387c478bd9Sstevel@tonic-gate bool noeol = false; 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* find the end of the line */ 10417c478bd9Sstevel@tonic-gate p = memchr(l, '\n', end - l); 10427c478bd9Sstevel@tonic-gate if (p == NULL) 10437c478bd9Sstevel@tonic-gate { 10447c478bd9Sstevel@tonic-gate p = end; 10457c478bd9Sstevel@tonic-gate noeol = true; 10467c478bd9Sstevel@tonic-gate } 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 10497c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 10507c478bd9Sstevel@tonic-gate "%05d >>> ", (int) CurrentPid); 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate /* check for line overflow */ 10537c478bd9Sstevel@tonic-gate while (mci->mci_mailer->m_linelimit > 0 && 10547c478bd9Sstevel@tonic-gate (p - l + slop) > mci->mci_mailer->m_linelimit) 10557c478bd9Sstevel@tonic-gate { 10567c478bd9Sstevel@tonic-gate char *l_base = l; 10577c478bd9Sstevel@tonic-gate register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate if (l[0] == '.' && slop == 0 && 10607c478bd9Sstevel@tonic-gate bitnset(M_XDOT, mci->mci_mailer->m_flags)) 10617c478bd9Sstevel@tonic-gate { 10627c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 10637c478bd9Sstevel@tonic-gate '.') == SM_IO_EOF) 10647c478bd9Sstevel@tonic-gate dead = true; 10657c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 10667c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 10677c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, '.'); 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate else if (l[0] == 'F' && slop == 0 && 10707c478bd9Sstevel@tonic-gate bitset(PXLF_MAPFROM, pxflags) && 10717c478bd9Sstevel@tonic-gate strncmp(l, "From ", 5) == 0 && 10727c478bd9Sstevel@tonic-gate bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 10737c478bd9Sstevel@tonic-gate { 10747c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 10757c478bd9Sstevel@tonic-gate '>') == SM_IO_EOF) 10767c478bd9Sstevel@tonic-gate dead = true; 10777c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 10787c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 10797c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 10807c478bd9Sstevel@tonic-gate '>'); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate if (dead) 10837c478bd9Sstevel@tonic-gate break; 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate while (l < q) 10867c478bd9Sstevel@tonic-gate { 10877c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 1088*445f2479Sjbeck (unsigned char) *l++) == SM_IO_EOF) 10897c478bd9Sstevel@tonic-gate { 10907c478bd9Sstevel@tonic-gate dead = true; 10917c478bd9Sstevel@tonic-gate break; 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate if (dead) 10957c478bd9Sstevel@tonic-gate break; 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '!') == 10987c478bd9Sstevel@tonic-gate SM_IO_EOF || 10997c478bd9Sstevel@tonic-gate sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 11007c478bd9Sstevel@tonic-gate mci->mci_mailer->m_eol) == 11017c478bd9Sstevel@tonic-gate SM_IO_EOF || 11027c478bd9Sstevel@tonic-gate sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, ' ') == 11037c478bd9Sstevel@tonic-gate SM_IO_EOF) 11047c478bd9Sstevel@tonic-gate { 11057c478bd9Sstevel@tonic-gate dead = true; 11067c478bd9Sstevel@tonic-gate break; 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 11097c478bd9Sstevel@tonic-gate { 11107c478bd9Sstevel@tonic-gate for (l = l_base; l < q; l++) 11117c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 11127c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 11137c478bd9Sstevel@tonic-gate (unsigned char)*l); 11147c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(TrafficLogFile, 11157c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 11167c478bd9Sstevel@tonic-gate "!\n%05d >>> ", 11177c478bd9Sstevel@tonic-gate (int) CurrentPid); 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate slop = 1; 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate if (dead) 11237c478bd9Sstevel@tonic-gate break; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate /* output last part */ 11267c478bd9Sstevel@tonic-gate if (l[0] == '.' && slop == 0 && 11277c478bd9Sstevel@tonic-gate bitnset(M_XDOT, mci->mci_mailer->m_flags)) 11287c478bd9Sstevel@tonic-gate { 11297c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '.') == 11307c478bd9Sstevel@tonic-gate SM_IO_EOF) 11317c478bd9Sstevel@tonic-gate { 1132*445f2479Sjbeck dead = true; 1133*445f2479Sjbeck break; 11347c478bd9Sstevel@tonic-gate } 11357c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 11367c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 11377c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, '.'); 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate else if (l[0] == 'F' && slop == 0 && 11407c478bd9Sstevel@tonic-gate bitset(PXLF_MAPFROM, pxflags) && 11417c478bd9Sstevel@tonic-gate strncmp(l, "From ", 5) == 0 && 11427c478bd9Sstevel@tonic-gate bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 11437c478bd9Sstevel@tonic-gate { 11447c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '>') == 11457c478bd9Sstevel@tonic-gate SM_IO_EOF) 11467c478bd9Sstevel@tonic-gate { 1147*445f2479Sjbeck dead = true; 1148*445f2479Sjbeck break; 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 11517c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 11527c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, '>'); 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate for ( ; l < p; ++l) 11557c478bd9Sstevel@tonic-gate { 11567c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 11577c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 11587c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 11597c478bd9Sstevel@tonic-gate (unsigned char)*l); 11607c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 11617c478bd9Sstevel@tonic-gate (unsigned char) *l) == SM_IO_EOF) 11627c478bd9Sstevel@tonic-gate { 11637c478bd9Sstevel@tonic-gate dead = true; 11647c478bd9Sstevel@tonic-gate break; 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate if (dead) 11687c478bd9Sstevel@tonic-gate break; 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 11717c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, SM_TIME_DEFAULT, 11727c478bd9Sstevel@tonic-gate '\n'); 11737c478bd9Sstevel@tonic-gate if ((!bitset(PXLF_NOADDEOL, pxflags) || !noeol) && 11747c478bd9Sstevel@tonic-gate sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, 11757c478bd9Sstevel@tonic-gate mci->mci_mailer->m_eol) == SM_IO_EOF) 11767c478bd9Sstevel@tonic-gate { 1177*445f2479Sjbeck dead = true; 1178*445f2479Sjbeck break; 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate if (l < end && *l == '\n') 11817c478bd9Sstevel@tonic-gate { 11827c478bd9Sstevel@tonic-gate if (*++l != ' ' && *l != '\t' && *l != '\0' && 11837c478bd9Sstevel@tonic-gate bitset(PXLF_HEADER, pxflags)) 11847c478bd9Sstevel@tonic-gate { 11857c478bd9Sstevel@tonic-gate if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, 11867c478bd9Sstevel@tonic-gate ' ') == SM_IO_EOF) 11877c478bd9Sstevel@tonic-gate { 1188*445f2479Sjbeck dead = true; 1189*445f2479Sjbeck break; 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 11937c478bd9Sstevel@tonic-gate (void) sm_io_putc(TrafficLogFile, 11947c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, ' '); 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate } while (l < end); 1199*445f2479Sjbeck return !dead; 12007c478bd9Sstevel@tonic-gate } 1201*445f2479Sjbeck 12027c478bd9Sstevel@tonic-gate /* 12037c478bd9Sstevel@tonic-gate ** XUNLINK -- unlink a file, doing logging as appropriate. 12047c478bd9Sstevel@tonic-gate ** 12057c478bd9Sstevel@tonic-gate ** Parameters: 12067c478bd9Sstevel@tonic-gate ** f -- name of file to unlink. 12077c478bd9Sstevel@tonic-gate ** 12087c478bd9Sstevel@tonic-gate ** Returns: 12097c478bd9Sstevel@tonic-gate ** return value of unlink() 12107c478bd9Sstevel@tonic-gate ** 12117c478bd9Sstevel@tonic-gate ** Side Effects: 12127c478bd9Sstevel@tonic-gate ** f is unlinked. 12137c478bd9Sstevel@tonic-gate */ 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate int 12167c478bd9Sstevel@tonic-gate xunlink(f) 12177c478bd9Sstevel@tonic-gate char *f; 12187c478bd9Sstevel@tonic-gate { 12197c478bd9Sstevel@tonic-gate register int i; 12207c478bd9Sstevel@tonic-gate int save_errno; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if (LogLevel > 98) 12237c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "unlink %s", f); 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate i = unlink(f); 12267c478bd9Sstevel@tonic-gate save_errno = errno; 12277c478bd9Sstevel@tonic-gate if (i < 0 && LogLevel > 97) 12287c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s: unlink-fail %d", 12297c478bd9Sstevel@tonic-gate f, errno); 12307c478bd9Sstevel@tonic-gate if (i >= 0) 12317c478bd9Sstevel@tonic-gate SYNC_DIR(f, false); 12327c478bd9Sstevel@tonic-gate errno = save_errno; 12337c478bd9Sstevel@tonic-gate return i; 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate /* 12367c478bd9Sstevel@tonic-gate ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 12377c478bd9Sstevel@tonic-gate ** 12387c478bd9Sstevel@tonic-gate ** Parameters: 12397c478bd9Sstevel@tonic-gate ** buf -- place to put the input line. 12407c478bd9Sstevel@tonic-gate ** siz -- size of buf. 12417c478bd9Sstevel@tonic-gate ** fp -- file to read from. 12427c478bd9Sstevel@tonic-gate ** timeout -- the timeout before error occurs. 12437c478bd9Sstevel@tonic-gate ** during -- what we are trying to read (for error messages). 12447c478bd9Sstevel@tonic-gate ** 12457c478bd9Sstevel@tonic-gate ** Returns: 12467c478bd9Sstevel@tonic-gate ** NULL on error (including timeout). This may also leave 12477c478bd9Sstevel@tonic-gate ** buf containing a null string. 12487c478bd9Sstevel@tonic-gate ** buf otherwise. 12497c478bd9Sstevel@tonic-gate */ 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate char * 12537c478bd9Sstevel@tonic-gate sfgets(buf, siz, fp, timeout, during) 12547c478bd9Sstevel@tonic-gate char *buf; 12557c478bd9Sstevel@tonic-gate int siz; 12567c478bd9Sstevel@tonic-gate SM_FILE_T *fp; 12577c478bd9Sstevel@tonic-gate time_t timeout; 12587c478bd9Sstevel@tonic-gate char *during; 12597c478bd9Sstevel@tonic-gate { 12607c478bd9Sstevel@tonic-gate register char *p; 12617c478bd9Sstevel@tonic-gate int save_errno; 12627c478bd9Sstevel@tonic-gate int io_timeout; 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate SM_REQUIRE(siz > 0); 12657c478bd9Sstevel@tonic-gate SM_REQUIRE(buf != NULL); 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate if (fp == NULL) 12687c478bd9Sstevel@tonic-gate { 12697c478bd9Sstevel@tonic-gate buf[0] = '\0'; 12707c478bd9Sstevel@tonic-gate errno = EBADF; 12717c478bd9Sstevel@tonic-gate return NULL; 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate /* try to read */ 12757c478bd9Sstevel@tonic-gate p = NULL; 12767c478bd9Sstevel@tonic-gate errno = 0; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* convert the timeout to sm_io notation */ 12797c478bd9Sstevel@tonic-gate io_timeout = (timeout <= 0) ? SM_TIME_DEFAULT : timeout * 1000; 12807c478bd9Sstevel@tonic-gate while (!sm_io_eof(fp) && !sm_io_error(fp)) 12817c478bd9Sstevel@tonic-gate { 12827c478bd9Sstevel@tonic-gate errno = 0; 12837c478bd9Sstevel@tonic-gate p = sm_io_fgets(fp, io_timeout, buf, siz); 12847c478bd9Sstevel@tonic-gate if (p == NULL && errno == EAGAIN) 12857c478bd9Sstevel@tonic-gate { 12867c478bd9Sstevel@tonic-gate /* The sm_io_fgets() call timedout */ 12877c478bd9Sstevel@tonic-gate if (LogLevel > 1) 12887c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 12897c478bd9Sstevel@tonic-gate "timeout waiting for input from %.100s during %s", 12907c478bd9Sstevel@tonic-gate CURHOSTNAME, 12917c478bd9Sstevel@tonic-gate during); 12927c478bd9Sstevel@tonic-gate buf[0] = '\0'; 12937c478bd9Sstevel@tonic-gate #if XDEBUG 12947c478bd9Sstevel@tonic-gate checkfd012(during); 12957c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 12967c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 12977c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(TrafficLogFile, 12987c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 12997c478bd9Sstevel@tonic-gate "%05d <<< [TIMEOUT]\n", 13007c478bd9Sstevel@tonic-gate (int) CurrentPid); 13017c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 13027c478bd9Sstevel@tonic-gate return NULL; 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate if (p != NULL || errno != EINTR) 13057c478bd9Sstevel@tonic-gate break; 13067c478bd9Sstevel@tonic-gate (void) sm_io_clearerr(fp); 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate save_errno = errno; 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate /* clean up the books and exit */ 13117c478bd9Sstevel@tonic-gate LineNumber++; 13127c478bd9Sstevel@tonic-gate if (p == NULL) 13137c478bd9Sstevel@tonic-gate { 13147c478bd9Sstevel@tonic-gate buf[0] = '\0'; 13157c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 13167c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 13177c478bd9Sstevel@tonic-gate "%05d <<< [EOF]\n", 13187c478bd9Sstevel@tonic-gate (int) CurrentPid); 13197c478bd9Sstevel@tonic-gate errno = save_errno; 13207c478bd9Sstevel@tonic-gate return NULL; 13217c478bd9Sstevel@tonic-gate } 13227c478bd9Sstevel@tonic-gate if (TrafficLogFile != NULL) 13237c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 13247c478bd9Sstevel@tonic-gate "%05d <<< %s", (int) CurrentPid, buf); 13257c478bd9Sstevel@tonic-gate if (SevenBitInput) 13267c478bd9Sstevel@tonic-gate { 13277c478bd9Sstevel@tonic-gate for (p = buf; *p != '\0'; p++) 13287c478bd9Sstevel@tonic-gate *p &= ~0200; 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate else if (!HasEightBits) 13317c478bd9Sstevel@tonic-gate { 13327c478bd9Sstevel@tonic-gate for (p = buf; *p != '\0'; p++) 13337c478bd9Sstevel@tonic-gate { 13347c478bd9Sstevel@tonic-gate if (bitset(0200, *p)) 13357c478bd9Sstevel@tonic-gate { 13367c478bd9Sstevel@tonic-gate HasEightBits = true; 13377c478bd9Sstevel@tonic-gate break; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate return buf; 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate /* 13447c478bd9Sstevel@tonic-gate ** FGETFOLDED -- like fgets, but knows about folded lines. 13457c478bd9Sstevel@tonic-gate ** 13467c478bd9Sstevel@tonic-gate ** Parameters: 13477c478bd9Sstevel@tonic-gate ** buf -- place to put result. 13487c478bd9Sstevel@tonic-gate ** n -- bytes available. 13497c478bd9Sstevel@tonic-gate ** f -- file to read from. 13507c478bd9Sstevel@tonic-gate ** 13517c478bd9Sstevel@tonic-gate ** Returns: 13527c478bd9Sstevel@tonic-gate ** input line(s) on success, NULL on error or SM_IO_EOF. 13537c478bd9Sstevel@tonic-gate ** This will normally be buf -- unless the line is too 13547c478bd9Sstevel@tonic-gate ** long, when it will be sm_malloc_x()ed. 13557c478bd9Sstevel@tonic-gate ** 13567c478bd9Sstevel@tonic-gate ** Side Effects: 13577c478bd9Sstevel@tonic-gate ** buf gets lines from f, with continuation lines (lines 13587c478bd9Sstevel@tonic-gate ** with leading white space) appended. CRLF's are mapped 13597c478bd9Sstevel@tonic-gate ** into single newlines. Any trailing NL is stripped. 13607c478bd9Sstevel@tonic-gate */ 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate char * 13637c478bd9Sstevel@tonic-gate fgetfolded(buf, n, f) 13647c478bd9Sstevel@tonic-gate char *buf; 13657c478bd9Sstevel@tonic-gate register int n; 13667c478bd9Sstevel@tonic-gate SM_FILE_T *f; 13677c478bd9Sstevel@tonic-gate { 13687c478bd9Sstevel@tonic-gate register char *p = buf; 13697c478bd9Sstevel@tonic-gate char *bp = buf; 13707c478bd9Sstevel@tonic-gate register int i; 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate SM_REQUIRE(n > 0); 13737c478bd9Sstevel@tonic-gate SM_REQUIRE(buf != NULL); 13747c478bd9Sstevel@tonic-gate if (f == NULL) 13757c478bd9Sstevel@tonic-gate { 13767c478bd9Sstevel@tonic-gate buf[0] = '\0'; 13777c478bd9Sstevel@tonic-gate errno = EBADF; 13787c478bd9Sstevel@tonic-gate return NULL; 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate n--; 13827c478bd9Sstevel@tonic-gate while ((i = sm_io_getc(f, SM_TIME_DEFAULT)) != SM_IO_EOF) 13837c478bd9Sstevel@tonic-gate { 13847c478bd9Sstevel@tonic-gate if (i == '\r') 13857c478bd9Sstevel@tonic-gate { 13867c478bd9Sstevel@tonic-gate i = sm_io_getc(f, SM_TIME_DEFAULT); 13877c478bd9Sstevel@tonic-gate if (i != '\n') 13887c478bd9Sstevel@tonic-gate { 13897c478bd9Sstevel@tonic-gate if (i != SM_IO_EOF) 13907c478bd9Sstevel@tonic-gate (void) sm_io_ungetc(f, SM_TIME_DEFAULT, 13917c478bd9Sstevel@tonic-gate i); 13927c478bd9Sstevel@tonic-gate i = '\r'; 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate if (--n <= 0) 13967c478bd9Sstevel@tonic-gate { 13977c478bd9Sstevel@tonic-gate /* allocate new space */ 13987c478bd9Sstevel@tonic-gate char *nbp; 13997c478bd9Sstevel@tonic-gate int nn; 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate nn = (p - bp); 14027c478bd9Sstevel@tonic-gate if (nn < MEMCHUNKSIZE) 14037c478bd9Sstevel@tonic-gate nn *= 2; 14047c478bd9Sstevel@tonic-gate else 14057c478bd9Sstevel@tonic-gate nn += MEMCHUNKSIZE; 14067c478bd9Sstevel@tonic-gate nbp = sm_malloc_x(nn); 14077c478bd9Sstevel@tonic-gate memmove(nbp, bp, p - bp); 14087c478bd9Sstevel@tonic-gate p = &nbp[p - bp]; 14097c478bd9Sstevel@tonic-gate if (bp != buf) 14107c478bd9Sstevel@tonic-gate sm_free(bp); 14117c478bd9Sstevel@tonic-gate bp = nbp; 14127c478bd9Sstevel@tonic-gate n = nn - (p - bp); 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate *p++ = i; 14157c478bd9Sstevel@tonic-gate if (i == '\n') 14167c478bd9Sstevel@tonic-gate { 14177c478bd9Sstevel@tonic-gate LineNumber++; 14187c478bd9Sstevel@tonic-gate i = sm_io_getc(f, SM_TIME_DEFAULT); 14197c478bd9Sstevel@tonic-gate if (i != SM_IO_EOF) 14207c478bd9Sstevel@tonic-gate (void) sm_io_ungetc(f, SM_TIME_DEFAULT, i); 14217c478bd9Sstevel@tonic-gate if (i != ' ' && i != '\t') 14227c478bd9Sstevel@tonic-gate break; 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate if (p == bp) 14267c478bd9Sstevel@tonic-gate return NULL; 14277c478bd9Sstevel@tonic-gate if (p[-1] == '\n') 14287c478bd9Sstevel@tonic-gate p--; 14297c478bd9Sstevel@tonic-gate *p = '\0'; 14307c478bd9Sstevel@tonic-gate return bp; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate /* 14337c478bd9Sstevel@tonic-gate ** CURTIME -- return current time. 14347c478bd9Sstevel@tonic-gate ** 14357c478bd9Sstevel@tonic-gate ** Parameters: 14367c478bd9Sstevel@tonic-gate ** none. 14377c478bd9Sstevel@tonic-gate ** 14387c478bd9Sstevel@tonic-gate ** Returns: 14397c478bd9Sstevel@tonic-gate ** the current time. 14407c478bd9Sstevel@tonic-gate */ 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate time_t 14437c478bd9Sstevel@tonic-gate curtime() 14447c478bd9Sstevel@tonic-gate { 14457c478bd9Sstevel@tonic-gate auto time_t t; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate (void) time(&t); 14487c478bd9Sstevel@tonic-gate return t; 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate /* 14517c478bd9Sstevel@tonic-gate ** ATOBOOL -- convert a string representation to boolean. 14527c478bd9Sstevel@tonic-gate ** 14537c478bd9Sstevel@tonic-gate ** Defaults to false 14547c478bd9Sstevel@tonic-gate ** 14557c478bd9Sstevel@tonic-gate ** Parameters: 14567c478bd9Sstevel@tonic-gate ** s -- string to convert. Takes "tTyY", empty, and NULL as true, 14577c478bd9Sstevel@tonic-gate ** others as false. 14587c478bd9Sstevel@tonic-gate ** 14597c478bd9Sstevel@tonic-gate ** Returns: 14607c478bd9Sstevel@tonic-gate ** A boolean representation of the string. 14617c478bd9Sstevel@tonic-gate */ 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate bool 14647c478bd9Sstevel@tonic-gate atobool(s) 14657c478bd9Sstevel@tonic-gate register char *s; 14667c478bd9Sstevel@tonic-gate { 14677c478bd9Sstevel@tonic-gate if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 14687c478bd9Sstevel@tonic-gate return true; 14697c478bd9Sstevel@tonic-gate return false; 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate /* 14727c478bd9Sstevel@tonic-gate ** ATOOCT -- convert a string representation to octal. 14737c478bd9Sstevel@tonic-gate ** 14747c478bd9Sstevel@tonic-gate ** Parameters: 14757c478bd9Sstevel@tonic-gate ** s -- string to convert. 14767c478bd9Sstevel@tonic-gate ** 14777c478bd9Sstevel@tonic-gate ** Returns: 14787c478bd9Sstevel@tonic-gate ** An integer representing the string interpreted as an 14797c478bd9Sstevel@tonic-gate ** octal number. 14807c478bd9Sstevel@tonic-gate */ 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate int 14837c478bd9Sstevel@tonic-gate atooct(s) 14847c478bd9Sstevel@tonic-gate register char *s; 14857c478bd9Sstevel@tonic-gate { 14867c478bd9Sstevel@tonic-gate register int i = 0; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate while (*s >= '0' && *s <= '7') 14897c478bd9Sstevel@tonic-gate i = (i << 3) | (*s++ - '0'); 14907c478bd9Sstevel@tonic-gate return i; 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate /* 14937c478bd9Sstevel@tonic-gate ** BITINTERSECT -- tell if two bitmaps intersect 14947c478bd9Sstevel@tonic-gate ** 14957c478bd9Sstevel@tonic-gate ** Parameters: 14967c478bd9Sstevel@tonic-gate ** a, b -- the bitmaps in question 14977c478bd9Sstevel@tonic-gate ** 14987c478bd9Sstevel@tonic-gate ** Returns: 14997c478bd9Sstevel@tonic-gate ** true if they have a non-null intersection 15007c478bd9Sstevel@tonic-gate ** false otherwise 15017c478bd9Sstevel@tonic-gate */ 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate bool 15047c478bd9Sstevel@tonic-gate bitintersect(a, b) 15057c478bd9Sstevel@tonic-gate BITMAP256 a; 15067c478bd9Sstevel@tonic-gate BITMAP256 b; 15077c478bd9Sstevel@tonic-gate { 15087c478bd9Sstevel@tonic-gate int i; 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 15117c478bd9Sstevel@tonic-gate { 15127c478bd9Sstevel@tonic-gate if ((a[i] & b[i]) != 0) 15137c478bd9Sstevel@tonic-gate return true; 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate return false; 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate /* 15187c478bd9Sstevel@tonic-gate ** BITZEROP -- tell if a bitmap is all zero 15197c478bd9Sstevel@tonic-gate ** 15207c478bd9Sstevel@tonic-gate ** Parameters: 15217c478bd9Sstevel@tonic-gate ** map -- the bit map to check 15227c478bd9Sstevel@tonic-gate ** 15237c478bd9Sstevel@tonic-gate ** Returns: 15247c478bd9Sstevel@tonic-gate ** true if map is all zero. 15257c478bd9Sstevel@tonic-gate ** false if there are any bits set in map. 15267c478bd9Sstevel@tonic-gate */ 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate bool 15297c478bd9Sstevel@tonic-gate bitzerop(map) 15307c478bd9Sstevel@tonic-gate BITMAP256 map; 15317c478bd9Sstevel@tonic-gate { 15327c478bd9Sstevel@tonic-gate int i; 15337c478bd9Sstevel@tonic-gate 15347c478bd9Sstevel@tonic-gate for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 15357c478bd9Sstevel@tonic-gate { 15367c478bd9Sstevel@tonic-gate if (map[i] != 0) 15377c478bd9Sstevel@tonic-gate return false; 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate return true; 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate /* 15427c478bd9Sstevel@tonic-gate ** STRCONTAINEDIN -- tell if one string is contained in another 15437c478bd9Sstevel@tonic-gate ** 15447c478bd9Sstevel@tonic-gate ** Parameters: 15457c478bd9Sstevel@tonic-gate ** icase -- ignore case? 15467c478bd9Sstevel@tonic-gate ** a -- possible substring. 15477c478bd9Sstevel@tonic-gate ** b -- possible superstring. 15487c478bd9Sstevel@tonic-gate ** 15497c478bd9Sstevel@tonic-gate ** Returns: 15507c478bd9Sstevel@tonic-gate ** true if a is contained in b (case insensitive). 15517c478bd9Sstevel@tonic-gate ** false otherwise. 15527c478bd9Sstevel@tonic-gate */ 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate bool 15557c478bd9Sstevel@tonic-gate strcontainedin(icase, a, b) 15567c478bd9Sstevel@tonic-gate bool icase; 15577c478bd9Sstevel@tonic-gate register char *a; 15587c478bd9Sstevel@tonic-gate register char *b; 15597c478bd9Sstevel@tonic-gate { 15607c478bd9Sstevel@tonic-gate int la; 15617c478bd9Sstevel@tonic-gate int lb; 15627c478bd9Sstevel@tonic-gate int c; 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate la = strlen(a); 15657c478bd9Sstevel@tonic-gate lb = strlen(b); 15667c478bd9Sstevel@tonic-gate c = *a; 15677c478bd9Sstevel@tonic-gate if (icase && isascii(c) && isupper(c)) 15687c478bd9Sstevel@tonic-gate c = tolower(c); 15697c478bd9Sstevel@tonic-gate for (; lb-- >= la; b++) 15707c478bd9Sstevel@tonic-gate { 15717c478bd9Sstevel@tonic-gate if (icase) 15727c478bd9Sstevel@tonic-gate { 15737c478bd9Sstevel@tonic-gate if (*b != c && 15747c478bd9Sstevel@tonic-gate isascii(*b) && isupper(*b) && tolower(*b) != c) 15757c478bd9Sstevel@tonic-gate continue; 15767c478bd9Sstevel@tonic-gate if (sm_strncasecmp(a, b, la) == 0) 15777c478bd9Sstevel@tonic-gate return true; 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate else 15807c478bd9Sstevel@tonic-gate { 15817c478bd9Sstevel@tonic-gate if (*b != c) 15827c478bd9Sstevel@tonic-gate continue; 15837c478bd9Sstevel@tonic-gate if (strncmp(a, b, la) == 0) 15847c478bd9Sstevel@tonic-gate return true; 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate return false; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate /* 15907c478bd9Sstevel@tonic-gate ** CHECKFD012 -- check low numbered file descriptors 15917c478bd9Sstevel@tonic-gate ** 15927c478bd9Sstevel@tonic-gate ** File descriptors 0, 1, and 2 should be open at all times. 15937c478bd9Sstevel@tonic-gate ** This routine verifies that, and fixes it if not true. 15947c478bd9Sstevel@tonic-gate ** 15957c478bd9Sstevel@tonic-gate ** Parameters: 15967c478bd9Sstevel@tonic-gate ** where -- a tag printed if the assertion failed 15977c478bd9Sstevel@tonic-gate ** 15987c478bd9Sstevel@tonic-gate ** Returns: 15997c478bd9Sstevel@tonic-gate ** none 16007c478bd9Sstevel@tonic-gate */ 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate void 16037c478bd9Sstevel@tonic-gate checkfd012(where) 16047c478bd9Sstevel@tonic-gate char *where; 16057c478bd9Sstevel@tonic-gate { 16067c478bd9Sstevel@tonic-gate #if XDEBUG 16077c478bd9Sstevel@tonic-gate register int i; 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate for (i = 0; i < 3; i++) 16107c478bd9Sstevel@tonic-gate fill_fd(i, where); 16117c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate /* 16147c478bd9Sstevel@tonic-gate ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 16157c478bd9Sstevel@tonic-gate ** 16167c478bd9Sstevel@tonic-gate ** Parameters: 16177c478bd9Sstevel@tonic-gate ** fd -- file descriptor to check. 16187c478bd9Sstevel@tonic-gate ** where -- tag to print on failure. 16197c478bd9Sstevel@tonic-gate ** 16207c478bd9Sstevel@tonic-gate ** Returns: 16217c478bd9Sstevel@tonic-gate ** none. 16227c478bd9Sstevel@tonic-gate */ 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate void 16257c478bd9Sstevel@tonic-gate checkfdopen(fd, where) 16267c478bd9Sstevel@tonic-gate int fd; 16277c478bd9Sstevel@tonic-gate char *where; 16287c478bd9Sstevel@tonic-gate { 16297c478bd9Sstevel@tonic-gate #if XDEBUG 16307c478bd9Sstevel@tonic-gate struct stat st; 16317c478bd9Sstevel@tonic-gate 16327c478bd9Sstevel@tonic-gate if (fstat(fd, &st) < 0 && errno == EBADF) 16337c478bd9Sstevel@tonic-gate { 16347c478bd9Sstevel@tonic-gate syserr("checkfdopen(%d): %s not open as expected!", fd, where); 16357c478bd9Sstevel@tonic-gate printopenfds(true); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate /* 16407c478bd9Sstevel@tonic-gate ** CHECKFDS -- check for new or missing file descriptors 16417c478bd9Sstevel@tonic-gate ** 16427c478bd9Sstevel@tonic-gate ** Parameters: 16437c478bd9Sstevel@tonic-gate ** where -- tag for printing. If null, take a base line. 16447c478bd9Sstevel@tonic-gate ** 16457c478bd9Sstevel@tonic-gate ** Returns: 16467c478bd9Sstevel@tonic-gate ** none 16477c478bd9Sstevel@tonic-gate ** 16487c478bd9Sstevel@tonic-gate ** Side Effects: 16497c478bd9Sstevel@tonic-gate ** If where is set, shows changes since the last call. 16507c478bd9Sstevel@tonic-gate */ 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate void 16537c478bd9Sstevel@tonic-gate checkfds(where) 16547c478bd9Sstevel@tonic-gate char *where; 16557c478bd9Sstevel@tonic-gate { 16567c478bd9Sstevel@tonic-gate int maxfd; 16577c478bd9Sstevel@tonic-gate register int fd; 16587c478bd9Sstevel@tonic-gate bool printhdr = true; 16597c478bd9Sstevel@tonic-gate int save_errno = errno; 16607c478bd9Sstevel@tonic-gate static BITMAP256 baseline; 16617c478bd9Sstevel@tonic-gate extern int DtableSize; 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate if (DtableSize > BITMAPBITS) 16647c478bd9Sstevel@tonic-gate maxfd = BITMAPBITS; 16657c478bd9Sstevel@tonic-gate else 16667c478bd9Sstevel@tonic-gate maxfd = DtableSize; 16677c478bd9Sstevel@tonic-gate if (where == NULL) 16687c478bd9Sstevel@tonic-gate clrbitmap(baseline); 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate for (fd = 0; fd < maxfd; fd++) 16717c478bd9Sstevel@tonic-gate { 16727c478bd9Sstevel@tonic-gate struct stat stbuf; 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 16757c478bd9Sstevel@tonic-gate { 16767c478bd9Sstevel@tonic-gate if (!bitnset(fd, baseline)) 16777c478bd9Sstevel@tonic-gate continue; 16787c478bd9Sstevel@tonic-gate clrbitn(fd, baseline); 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate else if (!bitnset(fd, baseline)) 16817c478bd9Sstevel@tonic-gate setbitn(fd, baseline); 16827c478bd9Sstevel@tonic-gate else 16837c478bd9Sstevel@tonic-gate continue; 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate /* file state has changed */ 16867c478bd9Sstevel@tonic-gate if (where == NULL) 16877c478bd9Sstevel@tonic-gate continue; 16887c478bd9Sstevel@tonic-gate if (printhdr) 16897c478bd9Sstevel@tonic-gate { 16907c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, 16917c478bd9Sstevel@tonic-gate "%s: changed fds:", 16927c478bd9Sstevel@tonic-gate where); 16937c478bd9Sstevel@tonic-gate printhdr = false; 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate dumpfd(fd, true, true); 16967c478bd9Sstevel@tonic-gate } 16977c478bd9Sstevel@tonic-gate errno = save_errno; 16987c478bd9Sstevel@tonic-gate } 16997c478bd9Sstevel@tonic-gate /* 17007c478bd9Sstevel@tonic-gate ** PRINTOPENFDS -- print the open file descriptors (for debugging) 17017c478bd9Sstevel@tonic-gate ** 17027c478bd9Sstevel@tonic-gate ** Parameters: 17037c478bd9Sstevel@tonic-gate ** logit -- if set, send output to syslog; otherwise 17047c478bd9Sstevel@tonic-gate ** print for debugging. 17057c478bd9Sstevel@tonic-gate ** 17067c478bd9Sstevel@tonic-gate ** Returns: 17077c478bd9Sstevel@tonic-gate ** none. 17087c478bd9Sstevel@tonic-gate */ 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate #if NETINET || NETINET6 17117c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 17127c478bd9Sstevel@tonic-gate #endif /* NETINET || NETINET6 */ 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate void 17157c478bd9Sstevel@tonic-gate printopenfds(logit) 17167c478bd9Sstevel@tonic-gate bool logit; 17177c478bd9Sstevel@tonic-gate { 17187c478bd9Sstevel@tonic-gate register int fd; 17197c478bd9Sstevel@tonic-gate extern int DtableSize; 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate for (fd = 0; fd < DtableSize; fd++) 17227c478bd9Sstevel@tonic-gate dumpfd(fd, false, logit); 17237c478bd9Sstevel@tonic-gate } 17247c478bd9Sstevel@tonic-gate /* 17257c478bd9Sstevel@tonic-gate ** DUMPFD -- dump a file descriptor 17267c478bd9Sstevel@tonic-gate ** 17277c478bd9Sstevel@tonic-gate ** Parameters: 17287c478bd9Sstevel@tonic-gate ** fd -- the file descriptor to dump. 17297c478bd9Sstevel@tonic-gate ** printclosed -- if set, print a notification even if 17307c478bd9Sstevel@tonic-gate ** it is closed; otherwise print nothing. 17317c478bd9Sstevel@tonic-gate ** logit -- if set, use sm_syslog instead of sm_dprintf() 17327c478bd9Sstevel@tonic-gate ** 17337c478bd9Sstevel@tonic-gate ** Returns: 17347c478bd9Sstevel@tonic-gate ** none. 17357c478bd9Sstevel@tonic-gate */ 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate void 17387c478bd9Sstevel@tonic-gate dumpfd(fd, printclosed, logit) 17397c478bd9Sstevel@tonic-gate int fd; 17407c478bd9Sstevel@tonic-gate bool printclosed; 17417c478bd9Sstevel@tonic-gate bool logit; 17427c478bd9Sstevel@tonic-gate { 17437c478bd9Sstevel@tonic-gate register char *p; 17447c478bd9Sstevel@tonic-gate char *hp; 17457c478bd9Sstevel@tonic-gate #ifdef S_IFSOCK 17467c478bd9Sstevel@tonic-gate SOCKADDR sa; 17477c478bd9Sstevel@tonic-gate #endif /* S_IFSOCK */ 17487c478bd9Sstevel@tonic-gate auto SOCKADDR_LEN_T slen; 17497c478bd9Sstevel@tonic-gate int i; 17507c478bd9Sstevel@tonic-gate #if STAT64 > 0 17517c478bd9Sstevel@tonic-gate struct stat64 st; 17527c478bd9Sstevel@tonic-gate #else /* STAT64 > 0 */ 17537c478bd9Sstevel@tonic-gate struct stat st; 17547c478bd9Sstevel@tonic-gate #endif /* STAT64 > 0 */ 17557c478bd9Sstevel@tonic-gate char buf[200]; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate p = buf; 17587c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 17597c478bd9Sstevel@tonic-gate p += strlen(p); 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate if ( 17627c478bd9Sstevel@tonic-gate #if STAT64 > 0 17637c478bd9Sstevel@tonic-gate fstat64(fd, &st) 17647c478bd9Sstevel@tonic-gate #else /* STAT64 > 0 */ 17657c478bd9Sstevel@tonic-gate fstat(fd, &st) 17667c478bd9Sstevel@tonic-gate #endif /* STAT64 > 0 */ 17677c478bd9Sstevel@tonic-gate < 0) 17687c478bd9Sstevel@tonic-gate { 17697c478bd9Sstevel@tonic-gate if (errno != EBADF) 17707c478bd9Sstevel@tonic-gate { 17717c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 17727c478bd9Sstevel@tonic-gate "CANNOT STAT (%s)", 17737c478bd9Sstevel@tonic-gate sm_errstring(errno)); 17747c478bd9Sstevel@tonic-gate goto printit; 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate else if (printclosed) 17777c478bd9Sstevel@tonic-gate { 17787c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "CLOSED"); 17797c478bd9Sstevel@tonic-gate goto printit; 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate return; 17827c478bd9Sstevel@tonic-gate } 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate i = fcntl(fd, F_GETFL, 0); 17857c478bd9Sstevel@tonic-gate if (i != -1) 17867c478bd9Sstevel@tonic-gate { 17877c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 17887c478bd9Sstevel@tonic-gate p += strlen(p); 17897c478bd9Sstevel@tonic-gate } 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "mode=%o: ", 17927c478bd9Sstevel@tonic-gate (int) st.st_mode); 17937c478bd9Sstevel@tonic-gate p += strlen(p); 17947c478bd9Sstevel@tonic-gate switch (st.st_mode & S_IFMT) 17957c478bd9Sstevel@tonic-gate { 17967c478bd9Sstevel@tonic-gate #ifdef S_IFSOCK 17977c478bd9Sstevel@tonic-gate case S_IFSOCK: 17987c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "SOCK "); 17997c478bd9Sstevel@tonic-gate p += strlen(p); 18007c478bd9Sstevel@tonic-gate memset(&sa, '\0', sizeof sa); 18017c478bd9Sstevel@tonic-gate slen = sizeof sa; 18027c478bd9Sstevel@tonic-gate if (getsockname(fd, &sa.sa, &slen) < 0) 18037c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 18047c478bd9Sstevel@tonic-gate sm_errstring(errno)); 18057c478bd9Sstevel@tonic-gate else 18067c478bd9Sstevel@tonic-gate { 18077c478bd9Sstevel@tonic-gate hp = hostnamebyanyaddr(&sa); 18087c478bd9Sstevel@tonic-gate if (hp == NULL) 18097c478bd9Sstevel@tonic-gate { 18107c478bd9Sstevel@tonic-gate /* EMPTY */ 18117c478bd9Sstevel@tonic-gate /* do nothing */ 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate # if NETINET 18147c478bd9Sstevel@tonic-gate else if (sa.sa.sa_family == AF_INET) 18157c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18167c478bd9Sstevel@tonic-gate "%s/%d", hp, ntohs(sa.sin.sin_port)); 18177c478bd9Sstevel@tonic-gate # endif /* NETINET */ 18187c478bd9Sstevel@tonic-gate # if NETINET6 18197c478bd9Sstevel@tonic-gate else if (sa.sa.sa_family == AF_INET6) 18207c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18217c478bd9Sstevel@tonic-gate "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 18227c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 18237c478bd9Sstevel@tonic-gate else 18247c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18257c478bd9Sstevel@tonic-gate "%s", hp); 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate p += strlen(p); 18287c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "->"); 18297c478bd9Sstevel@tonic-gate p += strlen(p); 18307c478bd9Sstevel@tonic-gate slen = sizeof sa; 18317c478bd9Sstevel@tonic-gate if (getpeername(fd, &sa.sa, &slen) < 0) 18327c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", 18337c478bd9Sstevel@tonic-gate sm_errstring(errno)); 18347c478bd9Sstevel@tonic-gate else 18357c478bd9Sstevel@tonic-gate { 18367c478bd9Sstevel@tonic-gate hp = hostnamebyanyaddr(&sa); 18377c478bd9Sstevel@tonic-gate if (hp == NULL) 18387c478bd9Sstevel@tonic-gate { 18397c478bd9Sstevel@tonic-gate /* EMPTY */ 18407c478bd9Sstevel@tonic-gate /* do nothing */ 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate # if NETINET 18437c478bd9Sstevel@tonic-gate else if (sa.sa.sa_family == AF_INET) 18447c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18457c478bd9Sstevel@tonic-gate "%s/%d", hp, ntohs(sa.sin.sin_port)); 18467c478bd9Sstevel@tonic-gate # endif /* NETINET */ 18477c478bd9Sstevel@tonic-gate # if NETINET6 18487c478bd9Sstevel@tonic-gate else if (sa.sa.sa_family == AF_INET6) 18497c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18507c478bd9Sstevel@tonic-gate "%s/%d", hp, ntohs(sa.sin6.sin6_port)); 18517c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 18527c478bd9Sstevel@tonic-gate else 18537c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18547c478bd9Sstevel@tonic-gate "%s", hp); 18557c478bd9Sstevel@tonic-gate } 18567c478bd9Sstevel@tonic-gate break; 18577c478bd9Sstevel@tonic-gate #endif /* S_IFSOCK */ 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate case S_IFCHR: 18607c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "CHR: "); 18617c478bd9Sstevel@tonic-gate p += strlen(p); 18627c478bd9Sstevel@tonic-gate goto defprint; 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate #ifdef S_IFBLK 18657c478bd9Sstevel@tonic-gate case S_IFBLK: 18667c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "BLK: "); 18677c478bd9Sstevel@tonic-gate p += strlen(p); 18687c478bd9Sstevel@tonic-gate goto defprint; 18697c478bd9Sstevel@tonic-gate #endif /* S_IFBLK */ 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 18727c478bd9Sstevel@tonic-gate case S_IFIFO: 18737c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "FIFO: "); 18747c478bd9Sstevel@tonic-gate p += strlen(p); 18757c478bd9Sstevel@tonic-gate goto defprint; 18767c478bd9Sstevel@tonic-gate #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate #ifdef S_IFDIR 18797c478bd9Sstevel@tonic-gate case S_IFDIR: 18807c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "DIR: "); 18817c478bd9Sstevel@tonic-gate p += strlen(p); 18827c478bd9Sstevel@tonic-gate goto defprint; 18837c478bd9Sstevel@tonic-gate #endif /* S_IFDIR */ 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate #ifdef S_IFLNK 18867c478bd9Sstevel@tonic-gate case S_IFLNK: 18877c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "LNK: "); 18887c478bd9Sstevel@tonic-gate p += strlen(p); 18897c478bd9Sstevel@tonic-gate goto defprint; 18907c478bd9Sstevel@tonic-gate #endif /* S_IFLNK */ 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate default: 18937c478bd9Sstevel@tonic-gate defprint: 18947c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), 18957c478bd9Sstevel@tonic-gate "dev=%d/%d, ino=%llu, nlink=%d, u/gid=%d/%d, ", 18967c478bd9Sstevel@tonic-gate major(st.st_dev), minor(st.st_dev), 18977c478bd9Sstevel@tonic-gate (ULONGLONG_T) st.st_ino, 18987c478bd9Sstevel@tonic-gate (int) st.st_nlink, (int) st.st_uid, 18997c478bd9Sstevel@tonic-gate (int) st.st_gid); 19007c478bd9Sstevel@tonic-gate p += strlen(p); 19017c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(buf, p), "size=%llu", 19027c478bd9Sstevel@tonic-gate (ULONGLONG_T) st.st_size); 19037c478bd9Sstevel@tonic-gate break; 19047c478bd9Sstevel@tonic-gate } 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate printit: 19077c478bd9Sstevel@tonic-gate if (logit) 19087c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 19097c478bd9Sstevel@tonic-gate "%.800s", buf); 19107c478bd9Sstevel@tonic-gate else 19117c478bd9Sstevel@tonic-gate sm_dprintf("%s\n", buf); 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate /* 19147c478bd9Sstevel@tonic-gate ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 19157c478bd9Sstevel@tonic-gate ** 19167c478bd9Sstevel@tonic-gate ** Parameters: 19177c478bd9Sstevel@tonic-gate ** host -- the host to shorten (stripped in place). 19187c478bd9Sstevel@tonic-gate ** 19197c478bd9Sstevel@tonic-gate ** Returns: 19207c478bd9Sstevel@tonic-gate ** place where string was truncated, NULL if not truncated. 19217c478bd9Sstevel@tonic-gate */ 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate char * 19247c478bd9Sstevel@tonic-gate shorten_hostname(host) 19257c478bd9Sstevel@tonic-gate char host[]; 19267c478bd9Sstevel@tonic-gate { 19277c478bd9Sstevel@tonic-gate register char *p; 19287c478bd9Sstevel@tonic-gate char *mydom; 19297c478bd9Sstevel@tonic-gate int i; 19307c478bd9Sstevel@tonic-gate bool canon = false; 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate /* strip off final dot */ 19337c478bd9Sstevel@tonic-gate i = strlen(host); 19347c478bd9Sstevel@tonic-gate p = &host[(i == 0) ? 0 : i - 1]; 19357c478bd9Sstevel@tonic-gate if (*p == '.') 19367c478bd9Sstevel@tonic-gate { 19377c478bd9Sstevel@tonic-gate *p = '\0'; 19387c478bd9Sstevel@tonic-gate canon = true; 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate /* see if there is any domain at all -- if not, we are done */ 19427c478bd9Sstevel@tonic-gate p = strchr(host, '.'); 19437c478bd9Sstevel@tonic-gate if (p == NULL) 19447c478bd9Sstevel@tonic-gate return NULL; 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate /* yes, we have a domain -- see if it looks like us */ 19477c478bd9Sstevel@tonic-gate mydom = macvalue('m', CurEnv); 19487c478bd9Sstevel@tonic-gate if (mydom == NULL) 19497c478bd9Sstevel@tonic-gate mydom = ""; 19507c478bd9Sstevel@tonic-gate i = strlen(++p); 19517c478bd9Sstevel@tonic-gate if ((canon ? sm_strcasecmp(p, mydom) 19527c478bd9Sstevel@tonic-gate : sm_strncasecmp(p, mydom, i)) == 0 && 19537c478bd9Sstevel@tonic-gate (mydom[i] == '.' || mydom[i] == '\0')) 19547c478bd9Sstevel@tonic-gate { 19557c478bd9Sstevel@tonic-gate *--p = '\0'; 19567c478bd9Sstevel@tonic-gate return p; 19577c478bd9Sstevel@tonic-gate } 19587c478bd9Sstevel@tonic-gate return NULL; 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate /* 19617c478bd9Sstevel@tonic-gate ** PROG_OPEN -- open a program for reading 19627c478bd9Sstevel@tonic-gate ** 19637c478bd9Sstevel@tonic-gate ** Parameters: 19647c478bd9Sstevel@tonic-gate ** argv -- the argument list. 19657c478bd9Sstevel@tonic-gate ** pfd -- pointer to a place to store the file descriptor. 19667c478bd9Sstevel@tonic-gate ** e -- the current envelope. 19677c478bd9Sstevel@tonic-gate ** 19687c478bd9Sstevel@tonic-gate ** Returns: 19697c478bd9Sstevel@tonic-gate ** pid of the process -- -1 if it failed. 19707c478bd9Sstevel@tonic-gate */ 19717c478bd9Sstevel@tonic-gate 19727c478bd9Sstevel@tonic-gate pid_t 19737c478bd9Sstevel@tonic-gate prog_open(argv, pfd, e) 19747c478bd9Sstevel@tonic-gate char **argv; 19757c478bd9Sstevel@tonic-gate int *pfd; 19767c478bd9Sstevel@tonic-gate ENVELOPE *e; 19777c478bd9Sstevel@tonic-gate { 19787c478bd9Sstevel@tonic-gate pid_t pid; 19797c478bd9Sstevel@tonic-gate int save_errno; 19807c478bd9Sstevel@tonic-gate int sff; 19817c478bd9Sstevel@tonic-gate int ret; 19827c478bd9Sstevel@tonic-gate int fdv[2]; 19837c478bd9Sstevel@tonic-gate char *p, *q; 19847c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 19857c478bd9Sstevel@tonic-gate extern int DtableSize; 19867c478bd9Sstevel@tonic-gate 19877c478bd9Sstevel@tonic-gate if (pipe(fdv) < 0) 19887c478bd9Sstevel@tonic-gate { 19897c478bd9Sstevel@tonic-gate syserr("%s: cannot create pipe for stdout", argv[0]); 19907c478bd9Sstevel@tonic-gate return -1; 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate pid = fork(); 19937c478bd9Sstevel@tonic-gate if (pid < 0) 19947c478bd9Sstevel@tonic-gate { 19957c478bd9Sstevel@tonic-gate syserr("%s: cannot fork", argv[0]); 19967c478bd9Sstevel@tonic-gate (void) close(fdv[0]); 19977c478bd9Sstevel@tonic-gate (void) close(fdv[1]); 19987c478bd9Sstevel@tonic-gate return -1; 19997c478bd9Sstevel@tonic-gate } 20007c478bd9Sstevel@tonic-gate if (pid > 0) 20017c478bd9Sstevel@tonic-gate { 20027c478bd9Sstevel@tonic-gate /* parent */ 20037c478bd9Sstevel@tonic-gate (void) close(fdv[1]); 20047c478bd9Sstevel@tonic-gate *pfd = fdv[0]; 20057c478bd9Sstevel@tonic-gate return pid; 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate /* Reset global flags */ 20097c478bd9Sstevel@tonic-gate RestartRequest = NULL; 20107c478bd9Sstevel@tonic-gate RestartWorkGroup = false; 20117c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 20127c478bd9Sstevel@tonic-gate PendingSignal = 0; 20137c478bd9Sstevel@tonic-gate CurrentPid = getpid(); 20147c478bd9Sstevel@tonic-gate 20157c478bd9Sstevel@tonic-gate /* 20167c478bd9Sstevel@tonic-gate ** Initialize exception stack and default exception 20177c478bd9Sstevel@tonic-gate ** handler for child process. 20187c478bd9Sstevel@tonic-gate */ 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate sm_exc_newthread(fatal_error); 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate /* child -- close stdin */ 20237c478bd9Sstevel@tonic-gate (void) close(0); 20247c478bd9Sstevel@tonic-gate 20257c478bd9Sstevel@tonic-gate /* stdout goes back to parent */ 20267c478bd9Sstevel@tonic-gate (void) close(fdv[0]); 20277c478bd9Sstevel@tonic-gate if (dup2(fdv[1], 1) < 0) 20287c478bd9Sstevel@tonic-gate { 20297c478bd9Sstevel@tonic-gate syserr("%s: cannot dup2 for stdout", argv[0]); 20307c478bd9Sstevel@tonic-gate _exit(EX_OSERR); 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate (void) close(fdv[1]); 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate /* stderr goes to transcript if available */ 20357c478bd9Sstevel@tonic-gate if (e->e_xfp != NULL) 20367c478bd9Sstevel@tonic-gate { 20377c478bd9Sstevel@tonic-gate int xfd; 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate xfd = sm_io_getinfo(e->e_xfp, SM_IO_WHAT_FD, NULL); 20407c478bd9Sstevel@tonic-gate if (xfd >= 0 && dup2(xfd, 2) < 0) 20417c478bd9Sstevel@tonic-gate { 20427c478bd9Sstevel@tonic-gate syserr("%s: cannot dup2 for stderr", argv[0]); 20437c478bd9Sstevel@tonic-gate _exit(EX_OSERR); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate } 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate /* this process has no right to the queue file */ 20487c478bd9Sstevel@tonic-gate if (e->e_lockfp != NULL) 20497c478bd9Sstevel@tonic-gate (void) close(sm_io_getinfo(e->e_lockfp, SM_IO_WHAT_FD, NULL)); 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate /* chroot to the program mailer directory, if defined */ 20527c478bd9Sstevel@tonic-gate if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) 20537c478bd9Sstevel@tonic-gate { 20547c478bd9Sstevel@tonic-gate expand(ProgMailer->m_rootdir, buf, sizeof buf, e); 20557c478bd9Sstevel@tonic-gate if (chroot(buf) < 0) 20567c478bd9Sstevel@tonic-gate { 20577c478bd9Sstevel@tonic-gate syserr("prog_open: cannot chroot(%s)", buf); 20587c478bd9Sstevel@tonic-gate exit(EX_TEMPFAIL); 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate if (chdir("/") < 0) 20617c478bd9Sstevel@tonic-gate { 20627c478bd9Sstevel@tonic-gate syserr("prog_open: cannot chdir(/)"); 20637c478bd9Sstevel@tonic-gate exit(EX_TEMPFAIL); 20647c478bd9Sstevel@tonic-gate } 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate /* run as default user */ 20687c478bd9Sstevel@tonic-gate endpwent(); 20697c478bd9Sstevel@tonic-gate sm_mbdb_terminate(); 2070*445f2479Sjbeck #if _FFR_MEMSTAT 2071*445f2479Sjbeck (void) sm_memstat_close(); 2072*445f2479Sjbeck #endif /* _FFR_MEMSTAT */ 20737c478bd9Sstevel@tonic-gate if (setgid(DefGid) < 0 && geteuid() == 0) 20747c478bd9Sstevel@tonic-gate { 20757c478bd9Sstevel@tonic-gate syserr("prog_open: setgid(%ld) failed", (long) DefGid); 20767c478bd9Sstevel@tonic-gate exit(EX_TEMPFAIL); 20777c478bd9Sstevel@tonic-gate } 20787c478bd9Sstevel@tonic-gate if (setuid(DefUid) < 0 && geteuid() == 0) 20797c478bd9Sstevel@tonic-gate { 20807c478bd9Sstevel@tonic-gate syserr("prog_open: setuid(%ld) failed", (long) DefUid); 20817c478bd9Sstevel@tonic-gate exit(EX_TEMPFAIL); 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate /* run in some directory */ 20857c478bd9Sstevel@tonic-gate if (ProgMailer != NULL) 20867c478bd9Sstevel@tonic-gate p = ProgMailer->m_execdir; 20877c478bd9Sstevel@tonic-gate else 20887c478bd9Sstevel@tonic-gate p = NULL; 20897c478bd9Sstevel@tonic-gate for (; p != NULL; p = q) 20907c478bd9Sstevel@tonic-gate { 20917c478bd9Sstevel@tonic-gate q = strchr(p, ':'); 20927c478bd9Sstevel@tonic-gate if (q != NULL) 20937c478bd9Sstevel@tonic-gate *q = '\0'; 20947c478bd9Sstevel@tonic-gate expand(p, buf, sizeof buf, e); 20957c478bd9Sstevel@tonic-gate if (q != NULL) 20967c478bd9Sstevel@tonic-gate *q++ = ':'; 20977c478bd9Sstevel@tonic-gate if (buf[0] != '\0' && chdir(buf) >= 0) 20987c478bd9Sstevel@tonic-gate break; 20997c478bd9Sstevel@tonic-gate } 21007c478bd9Sstevel@tonic-gate if (p == NULL) 21017c478bd9Sstevel@tonic-gate { 21027c478bd9Sstevel@tonic-gate /* backup directories */ 21037c478bd9Sstevel@tonic-gate if (chdir("/tmp") < 0) 21047c478bd9Sstevel@tonic-gate (void) chdir("/"); 21057c478bd9Sstevel@tonic-gate } 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate /* Check safety of program to be run */ 21087c478bd9Sstevel@tonic-gate sff = SFF_ROOTOK|SFF_EXECOK; 21097c478bd9Sstevel@tonic-gate if (!bitnset(DBS_RUNWRITABLEPROGRAM, DontBlameSendmail)) 21107c478bd9Sstevel@tonic-gate sff |= SFF_NOGWFILES|SFF_NOWWFILES; 21117c478bd9Sstevel@tonic-gate if (bitnset(DBS_RUNPROGRAMINUNSAFEDIRPATH, DontBlameSendmail)) 21127c478bd9Sstevel@tonic-gate sff |= SFF_NOPATHCHECK; 21137c478bd9Sstevel@tonic-gate else 21147c478bd9Sstevel@tonic-gate sff |= SFF_SAFEDIRPATH; 21157c478bd9Sstevel@tonic-gate ret = safefile(argv[0], DefUid, DefGid, DefUser, sff, 0, NULL); 21167c478bd9Sstevel@tonic-gate if (ret != 0) 21177c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 21187c478bd9Sstevel@tonic-gate "Warning: prog_open: program %s unsafe: %s", 21197c478bd9Sstevel@tonic-gate argv[0], sm_errstring(ret)); 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate /* arrange for all the files to be closed */ 21227c478bd9Sstevel@tonic-gate sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate /* now exec the process */ 21257c478bd9Sstevel@tonic-gate (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 21267c478bd9Sstevel@tonic-gate 21277c478bd9Sstevel@tonic-gate /* woops! failed */ 21287c478bd9Sstevel@tonic-gate save_errno = errno; 21297c478bd9Sstevel@tonic-gate syserr("%s: cannot exec", argv[0]); 21307c478bd9Sstevel@tonic-gate if (transienterror(save_errno)) 21317c478bd9Sstevel@tonic-gate _exit(EX_OSERR); 21327c478bd9Sstevel@tonic-gate _exit(EX_CONFIG); 21337c478bd9Sstevel@tonic-gate return -1; /* avoid compiler warning on IRIX */ 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate /* 21367c478bd9Sstevel@tonic-gate ** GET_COLUMN -- look up a Column in a line buffer 21377c478bd9Sstevel@tonic-gate ** 21387c478bd9Sstevel@tonic-gate ** Parameters: 21397c478bd9Sstevel@tonic-gate ** line -- the raw text line to search. 21407c478bd9Sstevel@tonic-gate ** col -- the column number to fetch. 21417c478bd9Sstevel@tonic-gate ** delim -- the delimiter between columns. If null, 21427c478bd9Sstevel@tonic-gate ** use white space. 21437c478bd9Sstevel@tonic-gate ** buf -- the output buffer. 21447c478bd9Sstevel@tonic-gate ** buflen -- the length of buf. 21457c478bd9Sstevel@tonic-gate ** 21467c478bd9Sstevel@tonic-gate ** Returns: 21477c478bd9Sstevel@tonic-gate ** buf if successful. 21487c478bd9Sstevel@tonic-gate ** NULL otherwise. 21497c478bd9Sstevel@tonic-gate */ 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate char * 21527c478bd9Sstevel@tonic-gate get_column(line, col, delim, buf, buflen) 21537c478bd9Sstevel@tonic-gate char line[]; 21547c478bd9Sstevel@tonic-gate int col; 21557c478bd9Sstevel@tonic-gate int delim; 21567c478bd9Sstevel@tonic-gate char buf[]; 21577c478bd9Sstevel@tonic-gate int buflen; 21587c478bd9Sstevel@tonic-gate { 21597c478bd9Sstevel@tonic-gate char *p; 21607c478bd9Sstevel@tonic-gate char *begin, *end; 21617c478bd9Sstevel@tonic-gate int i; 21627c478bd9Sstevel@tonic-gate char delimbuf[4]; 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate if ((char) delim == '\0') 21657c478bd9Sstevel@tonic-gate (void) sm_strlcpy(delimbuf, "\n\t ", sizeof delimbuf); 21667c478bd9Sstevel@tonic-gate else 21677c478bd9Sstevel@tonic-gate { 21687c478bd9Sstevel@tonic-gate delimbuf[0] = (char) delim; 21697c478bd9Sstevel@tonic-gate delimbuf[1] = '\0'; 21707c478bd9Sstevel@tonic-gate } 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate p = line; 21737c478bd9Sstevel@tonic-gate if (*p == '\0') 21747c478bd9Sstevel@tonic-gate return NULL; /* line empty */ 21757c478bd9Sstevel@tonic-gate if (*p == (char) delim && col == 0) 21767c478bd9Sstevel@tonic-gate return NULL; /* first column empty */ 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate begin = line; 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate if (col == 0 && (char) delim == '\0') 21817c478bd9Sstevel@tonic-gate { 21827c478bd9Sstevel@tonic-gate while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 21837c478bd9Sstevel@tonic-gate begin++; 21847c478bd9Sstevel@tonic-gate } 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate for (i = 0; i < col; i++) 21877c478bd9Sstevel@tonic-gate { 21887c478bd9Sstevel@tonic-gate if ((begin = strpbrk(begin, delimbuf)) == NULL) 21897c478bd9Sstevel@tonic-gate return NULL; /* no such column */ 21907c478bd9Sstevel@tonic-gate begin++; 21917c478bd9Sstevel@tonic-gate if ((char) delim == '\0') 21927c478bd9Sstevel@tonic-gate { 21937c478bd9Sstevel@tonic-gate while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 21947c478bd9Sstevel@tonic-gate begin++; 21957c478bd9Sstevel@tonic-gate } 21967c478bd9Sstevel@tonic-gate } 21977c478bd9Sstevel@tonic-gate 21987c478bd9Sstevel@tonic-gate end = strpbrk(begin, delimbuf); 21997c478bd9Sstevel@tonic-gate if (end == NULL) 22007c478bd9Sstevel@tonic-gate i = strlen(begin); 22017c478bd9Sstevel@tonic-gate else 22027c478bd9Sstevel@tonic-gate i = end - begin; 22037c478bd9Sstevel@tonic-gate if (i >= buflen) 22047c478bd9Sstevel@tonic-gate i = buflen - 1; 22057c478bd9Sstevel@tonic-gate (void) sm_strlcpy(buf, begin, i + 1); 22067c478bd9Sstevel@tonic-gate return buf; 22077c478bd9Sstevel@tonic-gate } 22087c478bd9Sstevel@tonic-gate /* 22097c478bd9Sstevel@tonic-gate ** CLEANSTRCPY -- copy string keeping out bogus characters 22107c478bd9Sstevel@tonic-gate ** 22117c478bd9Sstevel@tonic-gate ** Parameters: 22127c478bd9Sstevel@tonic-gate ** t -- "to" string. 22137c478bd9Sstevel@tonic-gate ** f -- "from" string. 22147c478bd9Sstevel@tonic-gate ** l -- length of space available in "to" string. 22157c478bd9Sstevel@tonic-gate ** 22167c478bd9Sstevel@tonic-gate ** Returns: 22177c478bd9Sstevel@tonic-gate ** none. 22187c478bd9Sstevel@tonic-gate */ 22197c478bd9Sstevel@tonic-gate 22207c478bd9Sstevel@tonic-gate void 22217c478bd9Sstevel@tonic-gate cleanstrcpy(t, f, l) 22227c478bd9Sstevel@tonic-gate register char *t; 22237c478bd9Sstevel@tonic-gate register char *f; 22247c478bd9Sstevel@tonic-gate int l; 22257c478bd9Sstevel@tonic-gate { 22267c478bd9Sstevel@tonic-gate /* check for newlines and log if necessary */ 22277c478bd9Sstevel@tonic-gate (void) denlstring(f, true, true); 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate if (l <= 0) 22307c478bd9Sstevel@tonic-gate syserr("!cleanstrcpy: length == 0"); 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate l--; 22337c478bd9Sstevel@tonic-gate while (l > 0 && *f != '\0') 22347c478bd9Sstevel@tonic-gate { 22357c478bd9Sstevel@tonic-gate if (isascii(*f) && 22367c478bd9Sstevel@tonic-gate (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 22377c478bd9Sstevel@tonic-gate { 22387c478bd9Sstevel@tonic-gate l--; 22397c478bd9Sstevel@tonic-gate *t++ = *f; 22407c478bd9Sstevel@tonic-gate } 22417c478bd9Sstevel@tonic-gate f++; 22427c478bd9Sstevel@tonic-gate } 22437c478bd9Sstevel@tonic-gate *t = '\0'; 22447c478bd9Sstevel@tonic-gate } 22457c478bd9Sstevel@tonic-gate /* 22467c478bd9Sstevel@tonic-gate ** DENLSTRING -- convert newlines in a string to spaces 22477c478bd9Sstevel@tonic-gate ** 22487c478bd9Sstevel@tonic-gate ** Parameters: 22497c478bd9Sstevel@tonic-gate ** s -- the input string 22507c478bd9Sstevel@tonic-gate ** strict -- if set, don't permit continuation lines. 22517c478bd9Sstevel@tonic-gate ** logattacks -- if set, log attempted attacks. 22527c478bd9Sstevel@tonic-gate ** 22537c478bd9Sstevel@tonic-gate ** Returns: 22547c478bd9Sstevel@tonic-gate ** A pointer to a version of the string with newlines 22557c478bd9Sstevel@tonic-gate ** mapped to spaces. This should be copied. 22567c478bd9Sstevel@tonic-gate */ 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate char * 22597c478bd9Sstevel@tonic-gate denlstring(s, strict, logattacks) 22607c478bd9Sstevel@tonic-gate char *s; 22617c478bd9Sstevel@tonic-gate bool strict; 22627c478bd9Sstevel@tonic-gate bool logattacks; 22637c478bd9Sstevel@tonic-gate { 22647c478bd9Sstevel@tonic-gate register char *p; 22657c478bd9Sstevel@tonic-gate int l; 22667c478bd9Sstevel@tonic-gate static char *bp = NULL; 22677c478bd9Sstevel@tonic-gate static int bl = 0; 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate p = s; 22707c478bd9Sstevel@tonic-gate while ((p = strchr(p, '\n')) != NULL) 22717c478bd9Sstevel@tonic-gate if (strict || (*++p != ' ' && *p != '\t')) 22727c478bd9Sstevel@tonic-gate break; 22737c478bd9Sstevel@tonic-gate if (p == NULL) 22747c478bd9Sstevel@tonic-gate return s; 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate l = strlen(s) + 1; 22777c478bd9Sstevel@tonic-gate if (bl < l) 22787c478bd9Sstevel@tonic-gate { 22797c478bd9Sstevel@tonic-gate /* allocate more space */ 22807c478bd9Sstevel@tonic-gate char *nbp = sm_pmalloc_x(l); 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate if (bp != NULL) 22837c478bd9Sstevel@tonic-gate sm_free(bp); 22847c478bd9Sstevel@tonic-gate bp = nbp; 22857c478bd9Sstevel@tonic-gate bl = l; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate (void) sm_strlcpy(bp, s, l); 22887c478bd9Sstevel@tonic-gate for (p = bp; (p = strchr(p, '\n')) != NULL; ) 22897c478bd9Sstevel@tonic-gate *p++ = ' '; 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate if (logattacks) 22927c478bd9Sstevel@tonic-gate { 22937c478bd9Sstevel@tonic-gate sm_syslog(LOG_NOTICE, CurEnv->e_id, 22947c478bd9Sstevel@tonic-gate "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 22957c478bd9Sstevel@tonic-gate RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 22967c478bd9Sstevel@tonic-gate shortenstring(bp, MAXSHORTSTR)); 22977c478bd9Sstevel@tonic-gate } 22987c478bd9Sstevel@tonic-gate 22997c478bd9Sstevel@tonic-gate return bp; 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate /* 23037c478bd9Sstevel@tonic-gate ** STRREPLNONPRT -- replace "unprintable" characters in a string with subst 23047c478bd9Sstevel@tonic-gate ** 23057c478bd9Sstevel@tonic-gate ** Parameters: 23067c478bd9Sstevel@tonic-gate ** s -- string to manipulate (in place) 23077c478bd9Sstevel@tonic-gate ** subst -- character to use as replacement 23087c478bd9Sstevel@tonic-gate ** 23097c478bd9Sstevel@tonic-gate ** Returns: 23107c478bd9Sstevel@tonic-gate ** true iff string did not contain "unprintable" characters 23117c478bd9Sstevel@tonic-gate */ 23127c478bd9Sstevel@tonic-gate 23137c478bd9Sstevel@tonic-gate bool 23147c478bd9Sstevel@tonic-gate strreplnonprt(s, c) 23157c478bd9Sstevel@tonic-gate char *s; 23167c478bd9Sstevel@tonic-gate int c; 23177c478bd9Sstevel@tonic-gate { 23187c478bd9Sstevel@tonic-gate bool ok; 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate ok = true; 23217c478bd9Sstevel@tonic-gate if (s == NULL) 23227c478bd9Sstevel@tonic-gate return ok; 23237c478bd9Sstevel@tonic-gate while (*s != '\0') 23247c478bd9Sstevel@tonic-gate { 23257c478bd9Sstevel@tonic-gate if (!(isascii(*s) && isprint(*s))) 23267c478bd9Sstevel@tonic-gate { 23277c478bd9Sstevel@tonic-gate *s = c; 23287c478bd9Sstevel@tonic-gate ok = false; 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate ++s; 23317c478bd9Sstevel@tonic-gate } 23327c478bd9Sstevel@tonic-gate return ok; 23337c478bd9Sstevel@tonic-gate } 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate /* 23367c478bd9Sstevel@tonic-gate ** STR2PRT -- convert "unprintable" characters in a string to \oct 23377c478bd9Sstevel@tonic-gate ** 23387c478bd9Sstevel@tonic-gate ** Parameters: 23397c478bd9Sstevel@tonic-gate ** s -- string to convert 23407c478bd9Sstevel@tonic-gate ** 23417c478bd9Sstevel@tonic-gate ** Returns: 23427c478bd9Sstevel@tonic-gate ** converted string. 23437c478bd9Sstevel@tonic-gate ** This is a static local buffer, string must be copied 23447c478bd9Sstevel@tonic-gate ** before this function is called again! 23457c478bd9Sstevel@tonic-gate */ 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate char * 23487c478bd9Sstevel@tonic-gate str2prt(s) 23497c478bd9Sstevel@tonic-gate char *s; 23507c478bd9Sstevel@tonic-gate { 23517c478bd9Sstevel@tonic-gate int l; 23527c478bd9Sstevel@tonic-gate char c, *h; 23537c478bd9Sstevel@tonic-gate bool ok; 23547c478bd9Sstevel@tonic-gate static int len = 0; 23557c478bd9Sstevel@tonic-gate static char *buf = NULL; 23567c478bd9Sstevel@tonic-gate 23577c478bd9Sstevel@tonic-gate if (s == NULL) 23587c478bd9Sstevel@tonic-gate return NULL; 23597c478bd9Sstevel@tonic-gate ok = true; 23607c478bd9Sstevel@tonic-gate for (h = s, l = 1; *h != '\0'; h++, l++) 23617c478bd9Sstevel@tonic-gate { 23627c478bd9Sstevel@tonic-gate if (*h == '\\') 23637c478bd9Sstevel@tonic-gate { 23647c478bd9Sstevel@tonic-gate ++l; 23657c478bd9Sstevel@tonic-gate ok = false; 23667c478bd9Sstevel@tonic-gate } 23677c478bd9Sstevel@tonic-gate else if (!(isascii(*h) && isprint(*h))) 23687c478bd9Sstevel@tonic-gate { 23697c478bd9Sstevel@tonic-gate l += 3; 23707c478bd9Sstevel@tonic-gate ok = false; 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate } 23737c478bd9Sstevel@tonic-gate if (ok) 23747c478bd9Sstevel@tonic-gate return s; 23757c478bd9Sstevel@tonic-gate if (l > len) 23767c478bd9Sstevel@tonic-gate { 23777c478bd9Sstevel@tonic-gate char *nbuf = sm_pmalloc_x(l); 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate if (buf != NULL) 23807c478bd9Sstevel@tonic-gate sm_free(buf); 23817c478bd9Sstevel@tonic-gate len = l; 23827c478bd9Sstevel@tonic-gate buf = nbuf; 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate for (h = buf; *s != '\0' && l > 0; s++, l--) 23857c478bd9Sstevel@tonic-gate { 23867c478bd9Sstevel@tonic-gate c = *s; 23877c478bd9Sstevel@tonic-gate if (isascii(c) && isprint(c) && c != '\\') 23887c478bd9Sstevel@tonic-gate { 23897c478bd9Sstevel@tonic-gate *h++ = c; 23907c478bd9Sstevel@tonic-gate } 23917c478bd9Sstevel@tonic-gate else 23927c478bd9Sstevel@tonic-gate { 23937c478bd9Sstevel@tonic-gate *h++ = '\\'; 23947c478bd9Sstevel@tonic-gate --l; 23957c478bd9Sstevel@tonic-gate switch (c) 23967c478bd9Sstevel@tonic-gate { 23977c478bd9Sstevel@tonic-gate case '\\': 23987c478bd9Sstevel@tonic-gate *h++ = '\\'; 23997c478bd9Sstevel@tonic-gate break; 24007c478bd9Sstevel@tonic-gate case '\t': 24017c478bd9Sstevel@tonic-gate *h++ = 't'; 24027c478bd9Sstevel@tonic-gate break; 24037c478bd9Sstevel@tonic-gate case '\n': 24047c478bd9Sstevel@tonic-gate *h++ = 'n'; 24057c478bd9Sstevel@tonic-gate break; 24067c478bd9Sstevel@tonic-gate case '\r': 24077c478bd9Sstevel@tonic-gate *h++ = 'r'; 24087c478bd9Sstevel@tonic-gate break; 24097c478bd9Sstevel@tonic-gate default: 2410*445f2479Sjbeck SM_ASSERT(l >= 2); 24117c478bd9Sstevel@tonic-gate (void) sm_snprintf(h, l, "%03o", 24127c478bd9Sstevel@tonic-gate (unsigned int)((unsigned char) c)); 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate /* 24157c478bd9Sstevel@tonic-gate ** XXX since l is unsigned this may 24167c478bd9Sstevel@tonic-gate ** wrap around if the calculation is screwed 24177c478bd9Sstevel@tonic-gate ** up... 24187c478bd9Sstevel@tonic-gate */ 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate l -= 2; 24217c478bd9Sstevel@tonic-gate h += 3; 24227c478bd9Sstevel@tonic-gate break; 24237c478bd9Sstevel@tonic-gate } 24247c478bd9Sstevel@tonic-gate } 24257c478bd9Sstevel@tonic-gate } 24267c478bd9Sstevel@tonic-gate *h = '\0'; 24277c478bd9Sstevel@tonic-gate buf[len - 1] = '\0'; 24287c478bd9Sstevel@tonic-gate return buf; 24297c478bd9Sstevel@tonic-gate } 24307c478bd9Sstevel@tonic-gate /* 24317c478bd9Sstevel@tonic-gate ** PATH_IS_DIR -- check to see if file exists and is a directory. 24327c478bd9Sstevel@tonic-gate ** 24337c478bd9Sstevel@tonic-gate ** There are some additional checks for security violations in 24347c478bd9Sstevel@tonic-gate ** here. This routine is intended to be used for the host status 24357c478bd9Sstevel@tonic-gate ** support. 24367c478bd9Sstevel@tonic-gate ** 24377c478bd9Sstevel@tonic-gate ** Parameters: 24387c478bd9Sstevel@tonic-gate ** pathname -- pathname to check for directory-ness. 24397c478bd9Sstevel@tonic-gate ** createflag -- if set, create directory if needed. 24407c478bd9Sstevel@tonic-gate ** 24417c478bd9Sstevel@tonic-gate ** Returns: 24427c478bd9Sstevel@tonic-gate ** true -- if the indicated pathname is a directory 24437c478bd9Sstevel@tonic-gate ** false -- otherwise 24447c478bd9Sstevel@tonic-gate */ 24457c478bd9Sstevel@tonic-gate 24467c478bd9Sstevel@tonic-gate bool 24477c478bd9Sstevel@tonic-gate path_is_dir(pathname, createflag) 24487c478bd9Sstevel@tonic-gate char *pathname; 24497c478bd9Sstevel@tonic-gate bool createflag; 24507c478bd9Sstevel@tonic-gate { 24517c478bd9Sstevel@tonic-gate struct stat statbuf; 24527c478bd9Sstevel@tonic-gate 24537c478bd9Sstevel@tonic-gate #if HASLSTAT 24547c478bd9Sstevel@tonic-gate if (lstat(pathname, &statbuf) < 0) 24557c478bd9Sstevel@tonic-gate #else /* HASLSTAT */ 24567c478bd9Sstevel@tonic-gate if (stat(pathname, &statbuf) < 0) 24577c478bd9Sstevel@tonic-gate #endif /* HASLSTAT */ 24587c478bd9Sstevel@tonic-gate { 24597c478bd9Sstevel@tonic-gate if (errno != ENOENT || !createflag) 24607c478bd9Sstevel@tonic-gate return false; 24617c478bd9Sstevel@tonic-gate if (mkdir(pathname, 0755) < 0) 24627c478bd9Sstevel@tonic-gate return false; 24637c478bd9Sstevel@tonic-gate return true; 24647c478bd9Sstevel@tonic-gate } 24657c478bd9Sstevel@tonic-gate if (!S_ISDIR(statbuf.st_mode)) 24667c478bd9Sstevel@tonic-gate { 24677c478bd9Sstevel@tonic-gate errno = ENOTDIR; 24687c478bd9Sstevel@tonic-gate return false; 24697c478bd9Sstevel@tonic-gate } 24707c478bd9Sstevel@tonic-gate 24717c478bd9Sstevel@tonic-gate /* security: don't allow writable directories */ 24727c478bd9Sstevel@tonic-gate if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 24737c478bd9Sstevel@tonic-gate { 24747c478bd9Sstevel@tonic-gate errno = EACCES; 24757c478bd9Sstevel@tonic-gate return false; 24767c478bd9Sstevel@tonic-gate } 24777c478bd9Sstevel@tonic-gate return true; 24787c478bd9Sstevel@tonic-gate } 24797c478bd9Sstevel@tonic-gate /* 24807c478bd9Sstevel@tonic-gate ** PROC_LIST_ADD -- add process id to list of our children 24817c478bd9Sstevel@tonic-gate ** 24827c478bd9Sstevel@tonic-gate ** Parameters: 24837c478bd9Sstevel@tonic-gate ** pid -- pid to add to list. 24847c478bd9Sstevel@tonic-gate ** task -- task of pid. 24857c478bd9Sstevel@tonic-gate ** type -- type of process. 24867c478bd9Sstevel@tonic-gate ** count -- number of processes. 24877c478bd9Sstevel@tonic-gate ** other -- other information for this type. 24887c478bd9Sstevel@tonic-gate ** 24897c478bd9Sstevel@tonic-gate ** Returns: 24907c478bd9Sstevel@tonic-gate ** none 24917c478bd9Sstevel@tonic-gate ** 24927c478bd9Sstevel@tonic-gate ** Side Effects: 24937c478bd9Sstevel@tonic-gate ** May increase CurChildren. May grow ProcList. 24947c478bd9Sstevel@tonic-gate */ 24957c478bd9Sstevel@tonic-gate 24967c478bd9Sstevel@tonic-gate typedef struct procs PROCS_T; 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate struct procs 24997c478bd9Sstevel@tonic-gate { 25007c478bd9Sstevel@tonic-gate pid_t proc_pid; 25017c478bd9Sstevel@tonic-gate char *proc_task; 25027c478bd9Sstevel@tonic-gate int proc_type; 25037c478bd9Sstevel@tonic-gate int proc_count; 25047c478bd9Sstevel@tonic-gate int proc_other; 25057c478bd9Sstevel@tonic-gate SOCKADDR proc_hostaddr; 25067c478bd9Sstevel@tonic-gate }; 25077c478bd9Sstevel@tonic-gate 25087c478bd9Sstevel@tonic-gate static PROCS_T *volatile ProcListVec = NULL; 25097c478bd9Sstevel@tonic-gate static int ProcListSize = 0; 25107c478bd9Sstevel@tonic-gate 25117c478bd9Sstevel@tonic-gate void 25127c478bd9Sstevel@tonic-gate proc_list_add(pid, task, type, count, other, hostaddr) 25137c478bd9Sstevel@tonic-gate pid_t pid; 25147c478bd9Sstevel@tonic-gate char *task; 25157c478bd9Sstevel@tonic-gate int type; 25167c478bd9Sstevel@tonic-gate int count; 25177c478bd9Sstevel@tonic-gate int other; 25187c478bd9Sstevel@tonic-gate SOCKADDR *hostaddr; 25197c478bd9Sstevel@tonic-gate { 25207c478bd9Sstevel@tonic-gate int i; 25217c478bd9Sstevel@tonic-gate 25227c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 25237c478bd9Sstevel@tonic-gate { 25247c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == NO_PID) 25257c478bd9Sstevel@tonic-gate break; 25267c478bd9Sstevel@tonic-gate } 25277c478bd9Sstevel@tonic-gate if (i >= ProcListSize) 25287c478bd9Sstevel@tonic-gate { 25297c478bd9Sstevel@tonic-gate /* probe the existing vector to avoid growing infinitely */ 25307c478bd9Sstevel@tonic-gate proc_list_probe(); 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate /* now scan again */ 25337c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 25347c478bd9Sstevel@tonic-gate { 25357c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == NO_PID) 25367c478bd9Sstevel@tonic-gate break; 25377c478bd9Sstevel@tonic-gate } 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate if (i >= ProcListSize) 25407c478bd9Sstevel@tonic-gate { 25417c478bd9Sstevel@tonic-gate /* grow process list */ 25427c478bd9Sstevel@tonic-gate PROCS_T *npv; 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate SM_ASSERT(ProcListSize < INT_MAX - PROC_LIST_SEG); 25457c478bd9Sstevel@tonic-gate npv = (PROCS_T *) sm_pmalloc_x((sizeof *npv) * 25467c478bd9Sstevel@tonic-gate (ProcListSize + PROC_LIST_SEG)); 25477c478bd9Sstevel@tonic-gate if (ProcListSize > 0) 25487c478bd9Sstevel@tonic-gate { 25497c478bd9Sstevel@tonic-gate memmove(npv, ProcListVec, 25507c478bd9Sstevel@tonic-gate ProcListSize * sizeof (PROCS_T)); 25517c478bd9Sstevel@tonic-gate sm_free(ProcListVec); 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate /* XXX just use memset() to initialize this part? */ 25557c478bd9Sstevel@tonic-gate for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 25567c478bd9Sstevel@tonic-gate { 25577c478bd9Sstevel@tonic-gate npv[i].proc_pid = NO_PID; 25587c478bd9Sstevel@tonic-gate npv[i].proc_task = NULL; 25597c478bd9Sstevel@tonic-gate npv[i].proc_type = PROC_NONE; 25607c478bd9Sstevel@tonic-gate } 25617c478bd9Sstevel@tonic-gate i = ProcListSize; 25627c478bd9Sstevel@tonic-gate ProcListSize += PROC_LIST_SEG; 25637c478bd9Sstevel@tonic-gate ProcListVec = npv; 25647c478bd9Sstevel@tonic-gate } 25657c478bd9Sstevel@tonic-gate ProcListVec[i].proc_pid = pid; 25667c478bd9Sstevel@tonic-gate PSTRSET(ProcListVec[i].proc_task, task); 25677c478bd9Sstevel@tonic-gate ProcListVec[i].proc_type = type; 25687c478bd9Sstevel@tonic-gate ProcListVec[i].proc_count = count; 25697c478bd9Sstevel@tonic-gate ProcListVec[i].proc_other = other; 25707c478bd9Sstevel@tonic-gate if (hostaddr != NULL) 25717c478bd9Sstevel@tonic-gate ProcListVec[i].proc_hostaddr = *hostaddr; 25727c478bd9Sstevel@tonic-gate else 25737c478bd9Sstevel@tonic-gate memset(&ProcListVec[i].proc_hostaddr, 0, 25747c478bd9Sstevel@tonic-gate sizeof(ProcListVec[i].proc_hostaddr)); 25757c478bd9Sstevel@tonic-gate 25767c478bd9Sstevel@tonic-gate /* if process adding itself, it's not a child */ 25777c478bd9Sstevel@tonic-gate if (pid != CurrentPid) 25787c478bd9Sstevel@tonic-gate { 25797c478bd9Sstevel@tonic-gate SM_ASSERT(CurChildren < INT_MAX); 25807c478bd9Sstevel@tonic-gate CurChildren++; 25817c478bd9Sstevel@tonic-gate } 25827c478bd9Sstevel@tonic-gate } 25837c478bd9Sstevel@tonic-gate /* 25847c478bd9Sstevel@tonic-gate ** PROC_LIST_SET -- set pid task in process list 25857c478bd9Sstevel@tonic-gate ** 25867c478bd9Sstevel@tonic-gate ** Parameters: 25877c478bd9Sstevel@tonic-gate ** pid -- pid to set 25887c478bd9Sstevel@tonic-gate ** task -- task of pid 25897c478bd9Sstevel@tonic-gate ** 25907c478bd9Sstevel@tonic-gate ** Returns: 25917c478bd9Sstevel@tonic-gate ** none. 25927c478bd9Sstevel@tonic-gate */ 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate void 25957c478bd9Sstevel@tonic-gate proc_list_set(pid, task) 25967c478bd9Sstevel@tonic-gate pid_t pid; 25977c478bd9Sstevel@tonic-gate char *task; 25987c478bd9Sstevel@tonic-gate { 25997c478bd9Sstevel@tonic-gate int i; 26007c478bd9Sstevel@tonic-gate 26017c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 26027c478bd9Sstevel@tonic-gate { 26037c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == pid) 26047c478bd9Sstevel@tonic-gate { 26057c478bd9Sstevel@tonic-gate PSTRSET(ProcListVec[i].proc_task, task); 26067c478bd9Sstevel@tonic-gate break; 26077c478bd9Sstevel@tonic-gate } 26087c478bd9Sstevel@tonic-gate } 26097c478bd9Sstevel@tonic-gate } 26107c478bd9Sstevel@tonic-gate /* 26117c478bd9Sstevel@tonic-gate ** PROC_LIST_DROP -- drop pid from process list 26127c478bd9Sstevel@tonic-gate ** 26137c478bd9Sstevel@tonic-gate ** Parameters: 26147c478bd9Sstevel@tonic-gate ** pid -- pid to drop 26157c478bd9Sstevel@tonic-gate ** st -- process status 26167c478bd9Sstevel@tonic-gate ** other -- storage for proc_other (return). 26177c478bd9Sstevel@tonic-gate ** 26187c478bd9Sstevel@tonic-gate ** Returns: 26197c478bd9Sstevel@tonic-gate ** none. 26207c478bd9Sstevel@tonic-gate ** 26217c478bd9Sstevel@tonic-gate ** Side Effects: 26227c478bd9Sstevel@tonic-gate ** May decrease CurChildren, CurRunners, or 26237c478bd9Sstevel@tonic-gate ** set RestartRequest or ShutdownRequest. 26247c478bd9Sstevel@tonic-gate ** 26257c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 26267c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 26277c478bd9Sstevel@tonic-gate ** DOING. 26287c478bd9Sstevel@tonic-gate */ 26297c478bd9Sstevel@tonic-gate 26307c478bd9Sstevel@tonic-gate void 26317c478bd9Sstevel@tonic-gate proc_list_drop(pid, st, other) 26327c478bd9Sstevel@tonic-gate pid_t pid; 26337c478bd9Sstevel@tonic-gate int st; 26347c478bd9Sstevel@tonic-gate int *other; 26357c478bd9Sstevel@tonic-gate { 26367c478bd9Sstevel@tonic-gate int i; 26377c478bd9Sstevel@tonic-gate int type = PROC_NONE; 26387c478bd9Sstevel@tonic-gate 26397c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 26407c478bd9Sstevel@tonic-gate { 26417c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == pid) 26427c478bd9Sstevel@tonic-gate { 26437c478bd9Sstevel@tonic-gate ProcListVec[i].proc_pid = NO_PID; 26447c478bd9Sstevel@tonic-gate type = ProcListVec[i].proc_type; 26457c478bd9Sstevel@tonic-gate if (other != NULL) 26467c478bd9Sstevel@tonic-gate *other = ProcListVec[i].proc_other; 2647*445f2479Sjbeck if (CurChildren > 0) 2648*445f2479Sjbeck CurChildren--; 26497c478bd9Sstevel@tonic-gate break; 26507c478bd9Sstevel@tonic-gate } 26517c478bd9Sstevel@tonic-gate } 26527c478bd9Sstevel@tonic-gate 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate if (type == PROC_CONTROL && WIFEXITED(st)) 26557c478bd9Sstevel@tonic-gate { 26567c478bd9Sstevel@tonic-gate /* if so, see if we need to restart or shutdown */ 26577c478bd9Sstevel@tonic-gate if (WEXITSTATUS(st) == EX_RESTART) 26587c478bd9Sstevel@tonic-gate RestartRequest = "control socket"; 26597c478bd9Sstevel@tonic-gate else if (WEXITSTATUS(st) == EX_SHUTDOWN) 26607c478bd9Sstevel@tonic-gate ShutdownRequest = "control socket"; 26617c478bd9Sstevel@tonic-gate } 26627c478bd9Sstevel@tonic-gate else if (type == PROC_QUEUE_CHILD && !WIFSTOPPED(st) && 26637c478bd9Sstevel@tonic-gate ProcListVec[i].proc_other > -1) 26647c478bd9Sstevel@tonic-gate { 26657c478bd9Sstevel@tonic-gate /* restart this persistent runner */ 26667c478bd9Sstevel@tonic-gate mark_work_group_restart(ProcListVec[i].proc_other, st); 26677c478bd9Sstevel@tonic-gate } 26687c478bd9Sstevel@tonic-gate else if (type == PROC_QUEUE) 26697c478bd9Sstevel@tonic-gate CurRunners -= ProcListVec[i].proc_count; 26707c478bd9Sstevel@tonic-gate } 26717c478bd9Sstevel@tonic-gate /* 26727c478bd9Sstevel@tonic-gate ** PROC_LIST_CLEAR -- clear the process list 26737c478bd9Sstevel@tonic-gate ** 26747c478bd9Sstevel@tonic-gate ** Parameters: 26757c478bd9Sstevel@tonic-gate ** none. 26767c478bd9Sstevel@tonic-gate ** 26777c478bd9Sstevel@tonic-gate ** Returns: 26787c478bd9Sstevel@tonic-gate ** none. 26797c478bd9Sstevel@tonic-gate ** 26807c478bd9Sstevel@tonic-gate ** Side Effects: 26817c478bd9Sstevel@tonic-gate ** Sets CurChildren to zero. 26827c478bd9Sstevel@tonic-gate */ 26837c478bd9Sstevel@tonic-gate 26847c478bd9Sstevel@tonic-gate void 26857c478bd9Sstevel@tonic-gate proc_list_clear() 26867c478bd9Sstevel@tonic-gate { 26877c478bd9Sstevel@tonic-gate int i; 26887c478bd9Sstevel@tonic-gate 26897c478bd9Sstevel@tonic-gate /* start from 1 since 0 is the daemon itself */ 26907c478bd9Sstevel@tonic-gate for (i = 1; i < ProcListSize; i++) 26917c478bd9Sstevel@tonic-gate ProcListVec[i].proc_pid = NO_PID; 26927c478bd9Sstevel@tonic-gate CurChildren = 0; 26937c478bd9Sstevel@tonic-gate } 26947c478bd9Sstevel@tonic-gate /* 26957c478bd9Sstevel@tonic-gate ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 26967c478bd9Sstevel@tonic-gate ** 26977c478bd9Sstevel@tonic-gate ** Parameters: 26987c478bd9Sstevel@tonic-gate ** none 26997c478bd9Sstevel@tonic-gate ** 27007c478bd9Sstevel@tonic-gate ** Returns: 27017c478bd9Sstevel@tonic-gate ** none 27027c478bd9Sstevel@tonic-gate ** 27037c478bd9Sstevel@tonic-gate ** Side Effects: 27047c478bd9Sstevel@tonic-gate ** May decrease CurChildren. 27057c478bd9Sstevel@tonic-gate */ 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate void 27087c478bd9Sstevel@tonic-gate proc_list_probe() 27097c478bd9Sstevel@tonic-gate { 2710*445f2479Sjbeck int i, children; 2711*445f2479Sjbeck int chldwasblocked; 2712*445f2479Sjbeck pid_t pid; 2713*445f2479Sjbeck 2714*445f2479Sjbeck children = 0; 2715*445f2479Sjbeck chldwasblocked = sm_blocksignal(SIGCHLD); 27167c478bd9Sstevel@tonic-gate 27177c478bd9Sstevel@tonic-gate /* start from 1 since 0 is the daemon itself */ 27187c478bd9Sstevel@tonic-gate for (i = 1; i < ProcListSize; i++) 27197c478bd9Sstevel@tonic-gate { 2720*445f2479Sjbeck pid = ProcListVec[i].proc_pid; 2721*445f2479Sjbeck if (pid == NO_PID || pid == CurrentPid) 27227c478bd9Sstevel@tonic-gate continue; 2723*445f2479Sjbeck if (kill(pid, 0) < 0) 27247c478bd9Sstevel@tonic-gate { 27257c478bd9Sstevel@tonic-gate if (LogLevel > 3) 27267c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, 27277c478bd9Sstevel@tonic-gate "proc_list_probe: lost pid %d", 27287c478bd9Sstevel@tonic-gate (int) ProcListVec[i].proc_pid); 27297c478bd9Sstevel@tonic-gate ProcListVec[i].proc_pid = NO_PID; 27307c478bd9Sstevel@tonic-gate SM_FREE_CLR(ProcListVec[i].proc_task); 27317c478bd9Sstevel@tonic-gate CurChildren--; 27327c478bd9Sstevel@tonic-gate } 2733*445f2479Sjbeck else 2734*445f2479Sjbeck { 2735*445f2479Sjbeck ++children; 2736*445f2479Sjbeck } 27377c478bd9Sstevel@tonic-gate } 27387c478bd9Sstevel@tonic-gate if (CurChildren < 0) 27397c478bd9Sstevel@tonic-gate CurChildren = 0; 2740*445f2479Sjbeck if (chldwasblocked == 0) 2741*445f2479Sjbeck (void) sm_releasesignal(SIGCHLD); 2742*445f2479Sjbeck if (LogLevel > 10 && children != CurChildren) 2743*445f2479Sjbeck { 2744*445f2479Sjbeck sm_syslog(LOG_ERR, NOQID, 2745*445f2479Sjbeck "proc_list_probe: found %d children, expected %d", 2746*445f2479Sjbeck children, CurChildren); 2747*445f2479Sjbeck } 27487c478bd9Sstevel@tonic-gate } 27497c478bd9Sstevel@tonic-gate 27507c478bd9Sstevel@tonic-gate /* 27517c478bd9Sstevel@tonic-gate ** PROC_LIST_DISPLAY -- display the process list 27527c478bd9Sstevel@tonic-gate ** 27537c478bd9Sstevel@tonic-gate ** Parameters: 27547c478bd9Sstevel@tonic-gate ** out -- output file pointer 27557c478bd9Sstevel@tonic-gate ** prefix -- string to output in front of each line. 27567c478bd9Sstevel@tonic-gate ** 27577c478bd9Sstevel@tonic-gate ** Returns: 27587c478bd9Sstevel@tonic-gate ** none. 27597c478bd9Sstevel@tonic-gate */ 27607c478bd9Sstevel@tonic-gate 27617c478bd9Sstevel@tonic-gate void 27627c478bd9Sstevel@tonic-gate proc_list_display(out, prefix) 27637c478bd9Sstevel@tonic-gate SM_FILE_T *out; 27647c478bd9Sstevel@tonic-gate char *prefix; 27657c478bd9Sstevel@tonic-gate { 27667c478bd9Sstevel@tonic-gate int i; 27677c478bd9Sstevel@tonic-gate 27687c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 27697c478bd9Sstevel@tonic-gate { 27707c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == NO_PID) 27717c478bd9Sstevel@tonic-gate continue; 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(out, SM_TIME_DEFAULT, "%s%d %s%s\n", 27747c478bd9Sstevel@tonic-gate prefix, 27757c478bd9Sstevel@tonic-gate (int) ProcListVec[i].proc_pid, 27767c478bd9Sstevel@tonic-gate ProcListVec[i].proc_task != NULL ? 27777c478bd9Sstevel@tonic-gate ProcListVec[i].proc_task : "(unknown)", 27787c478bd9Sstevel@tonic-gate (OpMode == MD_SMTP || 27797c478bd9Sstevel@tonic-gate OpMode == MD_DAEMON || 27807c478bd9Sstevel@tonic-gate OpMode == MD_ARPAFTP) ? "\r" : ""); 27817c478bd9Sstevel@tonic-gate } 27827c478bd9Sstevel@tonic-gate } 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate /* 27857c478bd9Sstevel@tonic-gate ** PROC_LIST_SIGNAL -- send a signal to a type of process in the list 27867c478bd9Sstevel@tonic-gate ** 27877c478bd9Sstevel@tonic-gate ** Parameters: 27887c478bd9Sstevel@tonic-gate ** type -- type of process to signal 27897c478bd9Sstevel@tonic-gate ** signal -- the type of signal to send 27907c478bd9Sstevel@tonic-gate ** 27917c478bd9Sstevel@tonic-gate ** Results: 27927c478bd9Sstevel@tonic-gate ** none. 27937c478bd9Sstevel@tonic-gate ** 27947c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 27957c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 27967c478bd9Sstevel@tonic-gate ** DOING. 27977c478bd9Sstevel@tonic-gate */ 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate void 28007c478bd9Sstevel@tonic-gate proc_list_signal(type, signal) 28017c478bd9Sstevel@tonic-gate int type; 28027c478bd9Sstevel@tonic-gate int signal; 28037c478bd9Sstevel@tonic-gate { 28047c478bd9Sstevel@tonic-gate int chldwasblocked; 28057c478bd9Sstevel@tonic-gate int alrmwasblocked; 28067c478bd9Sstevel@tonic-gate int i; 28077c478bd9Sstevel@tonic-gate pid_t mypid = getpid(); 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate /* block these signals so that we may signal cleanly */ 28107c478bd9Sstevel@tonic-gate chldwasblocked = sm_blocksignal(SIGCHLD); 28117c478bd9Sstevel@tonic-gate alrmwasblocked = sm_blocksignal(SIGALRM); 28127c478bd9Sstevel@tonic-gate 28137c478bd9Sstevel@tonic-gate /* Find all processes of type and send signal */ 28147c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 28157c478bd9Sstevel@tonic-gate { 28167c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == NO_PID || 28177c478bd9Sstevel@tonic-gate ProcListVec[i].proc_pid == mypid) 28187c478bd9Sstevel@tonic-gate continue; 28197c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_type != type) 28207c478bd9Sstevel@tonic-gate continue; 28217c478bd9Sstevel@tonic-gate (void) kill(ProcListVec[i].proc_pid, signal); 28227c478bd9Sstevel@tonic-gate } 28237c478bd9Sstevel@tonic-gate 28247c478bd9Sstevel@tonic-gate /* restore the signals */ 28257c478bd9Sstevel@tonic-gate if (alrmwasblocked == 0) 28267c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGALRM); 28277c478bd9Sstevel@tonic-gate if (chldwasblocked == 0) 28287c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 28297c478bd9Sstevel@tonic-gate } 28307c478bd9Sstevel@tonic-gate 28317c478bd9Sstevel@tonic-gate /* 28327c478bd9Sstevel@tonic-gate ** COUNT_OPEN_CONNECTIONS 28337c478bd9Sstevel@tonic-gate ** 28347c478bd9Sstevel@tonic-gate ** Parameters: 28357c478bd9Sstevel@tonic-gate ** hostaddr - ClientAddress 28367c478bd9Sstevel@tonic-gate ** 28377c478bd9Sstevel@tonic-gate ** Returns: 28387c478bd9Sstevel@tonic-gate ** the number of open connections for this client 28397c478bd9Sstevel@tonic-gate ** 28407c478bd9Sstevel@tonic-gate */ 28417c478bd9Sstevel@tonic-gate 28427c478bd9Sstevel@tonic-gate int 28437c478bd9Sstevel@tonic-gate count_open_connections(hostaddr) 28447c478bd9Sstevel@tonic-gate SOCKADDR *hostaddr; 28457c478bd9Sstevel@tonic-gate { 28467c478bd9Sstevel@tonic-gate int i, n; 28477c478bd9Sstevel@tonic-gate 28487c478bd9Sstevel@tonic-gate if (hostaddr == NULL) 28497c478bd9Sstevel@tonic-gate return 0; 28507c478bd9Sstevel@tonic-gate n = 0; 28517c478bd9Sstevel@tonic-gate for (i = 0; i < ProcListSize; i++) 28527c478bd9Sstevel@tonic-gate { 28537c478bd9Sstevel@tonic-gate if (ProcListVec[i].proc_pid == NO_PID) 28547c478bd9Sstevel@tonic-gate continue; 28557c478bd9Sstevel@tonic-gate if (hostaddr->sa.sa_family != 28567c478bd9Sstevel@tonic-gate ProcListVec[i].proc_hostaddr.sa.sa_family) 28577c478bd9Sstevel@tonic-gate continue; 28587c478bd9Sstevel@tonic-gate #if NETINET 28597c478bd9Sstevel@tonic-gate if (hostaddr->sa.sa_family == AF_INET && 28607c478bd9Sstevel@tonic-gate (hostaddr->sin.sin_addr.s_addr == 28617c478bd9Sstevel@tonic-gate ProcListVec[i].proc_hostaddr.sin.sin_addr.s_addr)) 28627c478bd9Sstevel@tonic-gate n++; 28637c478bd9Sstevel@tonic-gate #endif /* NETINET */ 28647c478bd9Sstevel@tonic-gate #if NETINET6 28657c478bd9Sstevel@tonic-gate if (hostaddr->sa.sa_family == AF_INET6 && 28667c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&(hostaddr->sin6.sin6_addr), 28677c478bd9Sstevel@tonic-gate &(ProcListVec[i].proc_hostaddr.sin6.sin6_addr))) 28687c478bd9Sstevel@tonic-gate n++; 28697c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 28707c478bd9Sstevel@tonic-gate } 28717c478bd9Sstevel@tonic-gate return n; 28727c478bd9Sstevel@tonic-gate } 2873