1c2aa98e2SPeter Wemm /* 2602a2b1bSGregory Neil Shapiro * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 14c2aa98e2SPeter Wemm #ifndef lint 1513058a91SGregory Neil Shapiro static char id[] = "@(#)$Id: util.c,v 8.225.2.1.2.26 2001/06/01 08:23:25 gshapiro Exp $"; 1606f25ae9SGregory Neil Shapiro #endif /* ! lint */ 17c2aa98e2SPeter Wemm 1806f25ae9SGregory Neil Shapiro #include <sendmail.h> 19c2aa98e2SPeter Wemm #include <sysexits.h> 2006f25ae9SGregory Neil Shapiro 2106f25ae9SGregory Neil Shapiro 2206f25ae9SGregory Neil Shapiro static void readtimeout __P((time_t)); 2306f25ae9SGregory Neil Shapiro 24c2aa98e2SPeter Wemm /* 25c2aa98e2SPeter Wemm ** STRIPQUOTES -- Strip quotes & quote bits from a string. 26c2aa98e2SPeter Wemm ** 27c2aa98e2SPeter Wemm ** Runs through a string and strips off unquoted quote 28c2aa98e2SPeter Wemm ** characters and quote bits. This is done in place. 29c2aa98e2SPeter Wemm ** 30c2aa98e2SPeter Wemm ** Parameters: 31c2aa98e2SPeter Wemm ** s -- the string to strip. 32c2aa98e2SPeter Wemm ** 33c2aa98e2SPeter Wemm ** Returns: 34c2aa98e2SPeter Wemm ** none. 35c2aa98e2SPeter Wemm ** 36c2aa98e2SPeter Wemm ** Side Effects: 37c2aa98e2SPeter Wemm ** none. 38c2aa98e2SPeter Wemm */ 39c2aa98e2SPeter Wemm 40c2aa98e2SPeter Wemm void 41c2aa98e2SPeter Wemm stripquotes(s) 42c2aa98e2SPeter Wemm char *s; 43c2aa98e2SPeter Wemm { 44c2aa98e2SPeter Wemm register char *p; 45c2aa98e2SPeter Wemm register char *q; 46c2aa98e2SPeter Wemm register char c; 47c2aa98e2SPeter Wemm 48c2aa98e2SPeter Wemm if (s == NULL) 49c2aa98e2SPeter Wemm return; 50c2aa98e2SPeter Wemm 51c2aa98e2SPeter Wemm p = q = s; 52c2aa98e2SPeter Wemm do 53c2aa98e2SPeter Wemm { 54c2aa98e2SPeter Wemm c = *p++; 55c2aa98e2SPeter Wemm if (c == '\\') 56c2aa98e2SPeter Wemm c = *p++; 57c2aa98e2SPeter Wemm else if (c == '"') 58c2aa98e2SPeter Wemm continue; 59c2aa98e2SPeter Wemm *q++ = c; 60c2aa98e2SPeter Wemm } while (c != '\0'); 61c2aa98e2SPeter Wemm } 62c2aa98e2SPeter Wemm /* 63c2aa98e2SPeter Wemm ** ADDQUOTES -- Adds quotes & quote bits to a string. 64c2aa98e2SPeter Wemm ** 65c2aa98e2SPeter Wemm ** Runs through a string and adds characters and quote bits. 66c2aa98e2SPeter Wemm ** 67c2aa98e2SPeter Wemm ** Parameters: 68c2aa98e2SPeter Wemm ** s -- the string to modify. 69c2aa98e2SPeter Wemm ** 70c2aa98e2SPeter Wemm ** Returns: 71c2aa98e2SPeter Wemm ** pointer to quoted string. 72c2aa98e2SPeter Wemm ** 73c2aa98e2SPeter Wemm ** Side Effects: 74c2aa98e2SPeter Wemm ** none. 75c2aa98e2SPeter Wemm ** 76c2aa98e2SPeter Wemm */ 77c2aa98e2SPeter Wemm 78c2aa98e2SPeter Wemm char * 79c2aa98e2SPeter Wemm addquotes(s) 80c2aa98e2SPeter Wemm char *s; 81c2aa98e2SPeter Wemm { 82c2aa98e2SPeter Wemm int len = 0; 83c2aa98e2SPeter Wemm char c; 84c2aa98e2SPeter Wemm char *p = s, *q, *r; 85c2aa98e2SPeter Wemm 86c2aa98e2SPeter Wemm if (s == NULL) 87c2aa98e2SPeter Wemm return NULL; 88c2aa98e2SPeter Wemm 89c2aa98e2SPeter Wemm /* Find length of quoted string */ 90c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 91c2aa98e2SPeter Wemm { 92c2aa98e2SPeter Wemm len++; 93c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 94c2aa98e2SPeter Wemm len++; 95c2aa98e2SPeter Wemm } 96c2aa98e2SPeter Wemm 97c2aa98e2SPeter Wemm q = r = xalloc(len + 3); 98c2aa98e2SPeter Wemm p = s; 99c2aa98e2SPeter Wemm 100c2aa98e2SPeter Wemm /* add leading quote */ 101c2aa98e2SPeter Wemm *q++ = '"'; 102c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 103c2aa98e2SPeter Wemm { 104c2aa98e2SPeter Wemm /* quote \ or " */ 105c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 106c2aa98e2SPeter Wemm *q++ = '\\'; 107c2aa98e2SPeter Wemm *q++ = c; 108c2aa98e2SPeter Wemm } 109c2aa98e2SPeter Wemm *q++ = '"'; 110c2aa98e2SPeter Wemm *q = '\0'; 111c2aa98e2SPeter Wemm return r; 112c2aa98e2SPeter Wemm } 113c2aa98e2SPeter Wemm /* 114c2aa98e2SPeter Wemm ** RFC822_STRING -- Checks string for proper RFC822 string quoting. 115c2aa98e2SPeter Wemm ** 116c2aa98e2SPeter Wemm ** Runs through a string and verifies RFC822 special characters 117c2aa98e2SPeter Wemm ** are only found inside comments, quoted strings, or backslash 118c2aa98e2SPeter Wemm ** escaped. Also verified balanced quotes and parenthesis. 119c2aa98e2SPeter Wemm ** 120c2aa98e2SPeter Wemm ** Parameters: 121c2aa98e2SPeter Wemm ** s -- the string to modify. 122c2aa98e2SPeter Wemm ** 123c2aa98e2SPeter Wemm ** Returns: 124c2aa98e2SPeter Wemm ** TRUE -- if the string is RFC822 compliant. 125c2aa98e2SPeter Wemm ** FALSE -- if the string is not RFC822 compliant. 126c2aa98e2SPeter Wemm ** 127c2aa98e2SPeter Wemm ** Side Effects: 128c2aa98e2SPeter Wemm ** none. 129c2aa98e2SPeter Wemm ** 130c2aa98e2SPeter Wemm */ 131c2aa98e2SPeter Wemm 132c2aa98e2SPeter Wemm bool 133c2aa98e2SPeter Wemm rfc822_string(s) 134c2aa98e2SPeter Wemm char *s; 135c2aa98e2SPeter Wemm { 136c2aa98e2SPeter Wemm bool quoted = FALSE; 137c2aa98e2SPeter Wemm int commentlev = 0; 138c2aa98e2SPeter Wemm char *c = s; 139c2aa98e2SPeter Wemm 140c2aa98e2SPeter Wemm if (s == NULL) 141c2aa98e2SPeter Wemm return FALSE; 142c2aa98e2SPeter Wemm 143c2aa98e2SPeter Wemm while (*c != '\0') 144c2aa98e2SPeter Wemm { 145c2aa98e2SPeter Wemm /* escaped character */ 146c2aa98e2SPeter Wemm if (*c == '\\') 147c2aa98e2SPeter Wemm { 148c2aa98e2SPeter Wemm c++; 149c2aa98e2SPeter Wemm if (*c == '\0') 150c2aa98e2SPeter Wemm return FALSE; 151c2aa98e2SPeter Wemm } 152c2aa98e2SPeter Wemm else if (commentlev == 0 && *c == '"') 153c2aa98e2SPeter Wemm quoted = !quoted; 154c2aa98e2SPeter Wemm else if (!quoted) 155c2aa98e2SPeter Wemm { 156c2aa98e2SPeter Wemm if (*c == ')') 157c2aa98e2SPeter Wemm { 158c2aa98e2SPeter Wemm /* unbalanced ')' */ 159c2aa98e2SPeter Wemm if (commentlev == 0) 160c2aa98e2SPeter Wemm return FALSE; 161c2aa98e2SPeter Wemm else 162c2aa98e2SPeter Wemm commentlev--; 163c2aa98e2SPeter Wemm } 164c2aa98e2SPeter Wemm else if (*c == '(') 165c2aa98e2SPeter Wemm commentlev++; 166c2aa98e2SPeter Wemm else if (commentlev == 0 && 167c2aa98e2SPeter Wemm strchr(MustQuoteChars, *c) != NULL) 168c2aa98e2SPeter Wemm return FALSE; 169c2aa98e2SPeter Wemm } 170c2aa98e2SPeter Wemm c++; 171c2aa98e2SPeter Wemm } 172c2aa98e2SPeter Wemm /* unbalanced '"' or '(' */ 173c2aa98e2SPeter Wemm if (quoted || commentlev != 0) 174c2aa98e2SPeter Wemm return FALSE; 175c2aa98e2SPeter Wemm else 176c2aa98e2SPeter Wemm return TRUE; 177c2aa98e2SPeter Wemm } 178c2aa98e2SPeter Wemm /* 179065a643dSPeter Wemm ** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string 180065a643dSPeter Wemm ** 18106f25ae9SGregory Neil Shapiro ** Arbitrarily shorten (in place) an RFC822 string and rebalance 182065a643dSPeter Wemm ** comments and quotes. 183065a643dSPeter Wemm ** 184065a643dSPeter Wemm ** Parameters: 185065a643dSPeter Wemm ** string -- the string to shorten 186065a643dSPeter Wemm ** length -- the maximum size, 0 if no maximum 187065a643dSPeter Wemm ** 188065a643dSPeter Wemm ** Returns: 189065a643dSPeter Wemm ** TRUE if string is changed, FALSE otherwise 190065a643dSPeter Wemm ** 191065a643dSPeter Wemm ** Side Effects: 192065a643dSPeter Wemm ** Changes string in place, possibly resulting 193065a643dSPeter Wemm ** in a shorter string. 194065a643dSPeter Wemm */ 195065a643dSPeter Wemm 196065a643dSPeter Wemm bool 197065a643dSPeter Wemm shorten_rfc822_string(string, length) 198065a643dSPeter Wemm char *string; 199065a643dSPeter Wemm size_t length; 200065a643dSPeter Wemm { 201065a643dSPeter Wemm bool backslash = FALSE; 202065a643dSPeter Wemm bool modified = FALSE; 203065a643dSPeter Wemm bool quoted = FALSE; 204065a643dSPeter Wemm size_t slen; 205065a643dSPeter Wemm int parencount = 0; 206065a643dSPeter Wemm char *ptr = string; 207065a643dSPeter Wemm 208065a643dSPeter Wemm /* 209065a643dSPeter Wemm ** If have to rebalance an already short enough string, 210065a643dSPeter Wemm ** need to do it within allocated space. 211065a643dSPeter Wemm */ 212193538b7SGregory Neil Shapiro 213065a643dSPeter Wemm slen = strlen(string); 214065a643dSPeter Wemm if (length == 0 || slen < length) 215065a643dSPeter Wemm length = slen; 216065a643dSPeter Wemm 217065a643dSPeter Wemm while (*ptr != '\0') 218065a643dSPeter Wemm { 219065a643dSPeter Wemm if (backslash) 220065a643dSPeter Wemm { 221065a643dSPeter Wemm backslash = FALSE; 222065a643dSPeter Wemm goto increment; 223065a643dSPeter Wemm } 224065a643dSPeter Wemm 225065a643dSPeter Wemm if (*ptr == '\\') 226065a643dSPeter Wemm backslash = TRUE; 227065a643dSPeter Wemm else if (*ptr == '(') 228065a643dSPeter Wemm { 229065a643dSPeter Wemm if (!quoted) 230065a643dSPeter Wemm parencount++; 231065a643dSPeter Wemm } 232065a643dSPeter Wemm else if (*ptr == ')') 233065a643dSPeter Wemm { 234065a643dSPeter Wemm if (--parencount < 0) 235065a643dSPeter Wemm parencount = 0; 236065a643dSPeter Wemm } 237065a643dSPeter Wemm 238065a643dSPeter Wemm /* Inside a comment, quotes don't matter */ 239065a643dSPeter Wemm if (parencount <= 0 && *ptr == '"') 240065a643dSPeter Wemm quoted = !quoted; 241065a643dSPeter Wemm 242065a643dSPeter Wemm increment: 243065a643dSPeter Wemm /* Check for sufficient space for next character */ 24406f25ae9SGregory Neil Shapiro if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) + 245065a643dSPeter Wemm parencount + 246065a643dSPeter Wemm (quoted ? 1 : 0))) 247065a643dSPeter Wemm { 248065a643dSPeter Wemm /* Not enough, backtrack */ 249065a643dSPeter Wemm if (*ptr == '\\') 250065a643dSPeter Wemm backslash = FALSE; 251065a643dSPeter Wemm else if (*ptr == '(' && !quoted) 252065a643dSPeter Wemm parencount--; 253065a643dSPeter Wemm else if (*ptr == '"' && parencount == 0) 254065a643dSPeter Wemm quoted = FALSE; 255065a643dSPeter Wemm break; 256065a643dSPeter Wemm } 257065a643dSPeter Wemm ptr++; 258065a643dSPeter Wemm } 259065a643dSPeter Wemm 260065a643dSPeter Wemm /* Rebalance */ 261065a643dSPeter Wemm while (parencount-- > 0) 262065a643dSPeter Wemm { 263065a643dSPeter Wemm if (*ptr != ')') 264065a643dSPeter Wemm { 265065a643dSPeter Wemm modified = TRUE; 266065a643dSPeter Wemm *ptr = ')'; 267065a643dSPeter Wemm } 268065a643dSPeter Wemm ptr++; 269065a643dSPeter Wemm } 270065a643dSPeter Wemm if (quoted) 271065a643dSPeter Wemm { 272065a643dSPeter Wemm if (*ptr != '"') 273065a643dSPeter Wemm { 274065a643dSPeter Wemm modified = TRUE; 275065a643dSPeter Wemm *ptr = '"'; 276065a643dSPeter Wemm } 277065a643dSPeter Wemm ptr++; 278065a643dSPeter Wemm } 279065a643dSPeter Wemm if (*ptr != '\0') 280065a643dSPeter Wemm { 281065a643dSPeter Wemm modified = TRUE; 282065a643dSPeter Wemm *ptr = '\0'; 283065a643dSPeter Wemm } 284065a643dSPeter Wemm return modified; 285065a643dSPeter Wemm } 286065a643dSPeter Wemm /* 287065a643dSPeter Wemm ** FIND_CHARACTER -- find an unquoted character in an RFC822 string 288065a643dSPeter Wemm ** 289065a643dSPeter Wemm ** Find an unquoted, non-commented character in an RFC822 290065a643dSPeter Wemm ** string and return a pointer to its location in the 291065a643dSPeter Wemm ** string. 292065a643dSPeter Wemm ** 293065a643dSPeter Wemm ** Parameters: 294065a643dSPeter Wemm ** string -- the string to search 295065a643dSPeter Wemm ** character -- the character to find 296065a643dSPeter Wemm ** 297065a643dSPeter Wemm ** Returns: 298065a643dSPeter Wemm ** pointer to the character, or 299065a643dSPeter Wemm ** a pointer to the end of the line if character is not found 300065a643dSPeter Wemm */ 301065a643dSPeter Wemm 302065a643dSPeter Wemm char * 303065a643dSPeter Wemm find_character(string, character) 304065a643dSPeter Wemm char *string; 30506f25ae9SGregory Neil Shapiro int character; 306065a643dSPeter Wemm { 307065a643dSPeter Wemm bool backslash = FALSE; 308065a643dSPeter Wemm bool quoted = FALSE; 309065a643dSPeter Wemm int parencount = 0; 310065a643dSPeter Wemm 311065a643dSPeter Wemm while (string != NULL && *string != '\0') 312065a643dSPeter Wemm { 313065a643dSPeter Wemm if (backslash) 314065a643dSPeter Wemm { 315065a643dSPeter Wemm backslash = FALSE; 316065a643dSPeter Wemm if (!quoted && character == '\\' && *string == '\\') 317065a643dSPeter Wemm break; 318065a643dSPeter Wemm string++; 319065a643dSPeter Wemm continue; 320065a643dSPeter Wemm } 321065a643dSPeter Wemm switch (*string) 322065a643dSPeter Wemm { 323065a643dSPeter Wemm case '\\': 324065a643dSPeter Wemm backslash = TRUE; 325065a643dSPeter Wemm break; 326065a643dSPeter Wemm 327065a643dSPeter Wemm case '(': 328065a643dSPeter Wemm if (!quoted) 329065a643dSPeter Wemm parencount++; 330065a643dSPeter Wemm break; 331065a643dSPeter Wemm 332065a643dSPeter Wemm case ')': 333065a643dSPeter Wemm if (--parencount < 0) 334065a643dSPeter Wemm parencount = 0; 335065a643dSPeter Wemm break; 336065a643dSPeter Wemm } 337065a643dSPeter Wemm 338065a643dSPeter Wemm /* Inside a comment, nothing matters */ 339065a643dSPeter Wemm if (parencount > 0) 340065a643dSPeter Wemm { 341065a643dSPeter Wemm string++; 342065a643dSPeter Wemm continue; 343065a643dSPeter Wemm } 344065a643dSPeter Wemm 345065a643dSPeter Wemm if (*string == '"') 346065a643dSPeter Wemm quoted = !quoted; 347065a643dSPeter Wemm else if (*string == character && !quoted) 348065a643dSPeter Wemm break; 349065a643dSPeter Wemm string++; 350065a643dSPeter Wemm } 351065a643dSPeter Wemm 352065a643dSPeter Wemm /* Return pointer to the character */ 353065a643dSPeter Wemm return string; 354065a643dSPeter Wemm } 355065a643dSPeter Wemm /* 356c2aa98e2SPeter Wemm ** XALLOC -- Allocate memory and bitch wildly on failure. 357c2aa98e2SPeter Wemm ** 358c2aa98e2SPeter Wemm ** THIS IS A CLUDGE. This should be made to give a proper 359c2aa98e2SPeter Wemm ** error -- but after all, what can we do? 360c2aa98e2SPeter Wemm ** 361c2aa98e2SPeter Wemm ** Parameters: 362c2aa98e2SPeter Wemm ** sz -- size of area to allocate. 363c2aa98e2SPeter Wemm ** 364c2aa98e2SPeter Wemm ** Returns: 365c2aa98e2SPeter Wemm ** pointer to data region. 366c2aa98e2SPeter Wemm ** 367c2aa98e2SPeter Wemm ** Side Effects: 368c2aa98e2SPeter Wemm ** Memory is allocated. 369c2aa98e2SPeter Wemm */ 370c2aa98e2SPeter Wemm 371c2aa98e2SPeter Wemm char * 372c2aa98e2SPeter Wemm xalloc(sz) 373c2aa98e2SPeter Wemm register int sz; 374c2aa98e2SPeter Wemm { 375c2aa98e2SPeter Wemm register char *p; 376c2aa98e2SPeter Wemm 377c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 378c2aa98e2SPeter Wemm if (sz <= 0) 379c2aa98e2SPeter Wemm sz = 1; 380c2aa98e2SPeter Wemm 3818774250cSGregory Neil Shapiro ENTER_CRITICAL(); 382c2aa98e2SPeter Wemm p = malloc((unsigned) sz); 3838774250cSGregory Neil Shapiro LEAVE_CRITICAL(); 384c2aa98e2SPeter Wemm if (p == NULL) 385c2aa98e2SPeter Wemm { 386c2aa98e2SPeter Wemm syserr("!Out of memory!!"); 3878774250cSGregory Neil Shapiro 3888774250cSGregory Neil Shapiro /* NOTREACHED */ 3898774250cSGregory Neil Shapiro exit(EX_UNAVAILABLE); 390c2aa98e2SPeter Wemm } 39106f25ae9SGregory Neil Shapiro return p; 392c2aa98e2SPeter Wemm } 393c2aa98e2SPeter Wemm /* 3948774250cSGregory Neil Shapiro ** XREALLOC -- Reallocate memory and bitch wildly on failure. 3958774250cSGregory Neil Shapiro ** 3968774250cSGregory Neil Shapiro ** THIS IS A CLUDGE. This should be made to give a proper 3978774250cSGregory Neil Shapiro ** error -- but after all, what can we do? 3988774250cSGregory Neil Shapiro ** 3998774250cSGregory Neil Shapiro ** Parameters: 4008774250cSGregory Neil Shapiro ** ptr -- original area. 4018774250cSGregory Neil Shapiro ** sz -- size of new area to allocate. 4028774250cSGregory Neil Shapiro ** 4038774250cSGregory Neil Shapiro ** Returns: 4048774250cSGregory Neil Shapiro ** pointer to data region. 4058774250cSGregory Neil Shapiro ** 4068774250cSGregory Neil Shapiro ** Side Effects: 4078774250cSGregory Neil Shapiro ** Memory is allocated. 4088774250cSGregory Neil Shapiro */ 4098774250cSGregory Neil Shapiro 4108774250cSGregory Neil Shapiro char * 4118774250cSGregory Neil Shapiro xrealloc(ptr, sz) 4128774250cSGregory Neil Shapiro void *ptr; 4138774250cSGregory Neil Shapiro size_t sz; 4148774250cSGregory Neil Shapiro { 4158774250cSGregory Neil Shapiro register char *p; 4168774250cSGregory Neil Shapiro 4178774250cSGregory Neil Shapiro /* some systems can't handle size zero mallocs */ 4188774250cSGregory Neil Shapiro if (sz <= 0) 4198774250cSGregory Neil Shapiro sz = 1; 4208774250cSGregory Neil Shapiro 4218774250cSGregory Neil Shapiro ENTER_CRITICAL(); 4228774250cSGregory Neil Shapiro p = realloc(ptr, (unsigned) sz); 4238774250cSGregory Neil Shapiro LEAVE_CRITICAL(); 4248774250cSGregory Neil Shapiro if (p == NULL) 4258774250cSGregory Neil Shapiro { 4268774250cSGregory Neil Shapiro syserr("!Out of memory!!"); 4278774250cSGregory Neil Shapiro 4288774250cSGregory Neil Shapiro /* NOTREACHED */ 4298774250cSGregory Neil Shapiro exit(EX_UNAVAILABLE); 4308774250cSGregory Neil Shapiro } 4318774250cSGregory Neil Shapiro return p; 4328774250cSGregory Neil Shapiro } 4338774250cSGregory Neil Shapiro /* 4348774250cSGregory Neil Shapiro ** XCALLOC -- Allocate memory and bitch wildly on failure. 4358774250cSGregory Neil Shapiro ** 4368774250cSGregory Neil Shapiro ** THIS IS A CLUDGE. This should be made to give a proper 4378774250cSGregory Neil Shapiro ** error -- but after all, what can we do? 4388774250cSGregory Neil Shapiro ** 4398774250cSGregory Neil Shapiro ** Parameters: 4408774250cSGregory Neil Shapiro ** num -- number of items to allocate 4418774250cSGregory Neil Shapiro ** sz -- size of new area to allocate. 4428774250cSGregory Neil Shapiro ** 4438774250cSGregory Neil Shapiro ** Returns: 4448774250cSGregory Neil Shapiro ** pointer to data region. 4458774250cSGregory Neil Shapiro ** 4468774250cSGregory Neil Shapiro ** Side Effects: 4478774250cSGregory Neil Shapiro ** Memory is allocated. 4488774250cSGregory Neil Shapiro */ 4498774250cSGregory Neil Shapiro 4508774250cSGregory Neil Shapiro char * 4518774250cSGregory Neil Shapiro xcalloc(num, sz) 4528774250cSGregory Neil Shapiro size_t num; 4538774250cSGregory Neil Shapiro size_t sz; 4548774250cSGregory Neil Shapiro { 4558774250cSGregory Neil Shapiro register char *p; 4568774250cSGregory Neil Shapiro 4578774250cSGregory Neil Shapiro /* some systems can't handle size zero mallocs */ 4588774250cSGregory Neil Shapiro if (num <= 0) 4598774250cSGregory Neil Shapiro num = 1; 4608774250cSGregory Neil Shapiro if (sz <= 0) 4618774250cSGregory Neil Shapiro sz = 1; 4628774250cSGregory Neil Shapiro 4638774250cSGregory Neil Shapiro ENTER_CRITICAL(); 4648774250cSGregory Neil Shapiro p = calloc((unsigned) num, (unsigned) sz); 4658774250cSGregory Neil Shapiro LEAVE_CRITICAL(); 4668774250cSGregory Neil Shapiro if (p == NULL) 4678774250cSGregory Neil Shapiro { 4688774250cSGregory Neil Shapiro syserr("!Out of memory!!"); 4698774250cSGregory Neil Shapiro 4708774250cSGregory Neil Shapiro /* NOTREACHED */ 4718774250cSGregory Neil Shapiro exit(EX_UNAVAILABLE); 4728774250cSGregory Neil Shapiro } 4738774250cSGregory Neil Shapiro return p; 4748774250cSGregory Neil Shapiro } 4758774250cSGregory Neil Shapiro /* 4768774250cSGregory Neil Shapiro ** SM_FREE -- Free memory safely. 4778774250cSGregory Neil Shapiro ** 4788774250cSGregory Neil Shapiro ** Parameters: 4798774250cSGregory Neil Shapiro ** ptr -- area to free 4808774250cSGregory Neil Shapiro ** 4818774250cSGregory Neil Shapiro ** Returns: 4828774250cSGregory Neil Shapiro ** none. 4838774250cSGregory Neil Shapiro ** 4848774250cSGregory Neil Shapiro ** Side Effects: 4858774250cSGregory Neil Shapiro ** Memory is freed. 4868774250cSGregory Neil Shapiro */ 4878774250cSGregory Neil Shapiro 4888774250cSGregory Neil Shapiro void 4898774250cSGregory Neil Shapiro sm_free(ptr) 4908774250cSGregory Neil Shapiro void *ptr; 4918774250cSGregory Neil Shapiro { 4928774250cSGregory Neil Shapiro ENTER_CRITICAL(); 4938774250cSGregory Neil Shapiro free(ptr); 4948774250cSGregory Neil Shapiro LEAVE_CRITICAL(); 4958774250cSGregory Neil Shapiro } 4968774250cSGregory Neil Shapiro /* 497c2aa98e2SPeter Wemm ** COPYPLIST -- copy list of pointers. 498c2aa98e2SPeter Wemm ** 499c2aa98e2SPeter Wemm ** This routine is the equivalent of newstr for lists of 500c2aa98e2SPeter Wemm ** pointers. 501c2aa98e2SPeter Wemm ** 502c2aa98e2SPeter Wemm ** Parameters: 503c2aa98e2SPeter Wemm ** list -- list of pointers to copy. 504c2aa98e2SPeter Wemm ** Must be NULL terminated. 505c2aa98e2SPeter Wemm ** copycont -- if TRUE, copy the contents of the vector 506c2aa98e2SPeter Wemm ** (which must be a string) also. 507c2aa98e2SPeter Wemm ** 508c2aa98e2SPeter Wemm ** Returns: 509c2aa98e2SPeter Wemm ** a copy of 'list'. 510c2aa98e2SPeter Wemm ** 511c2aa98e2SPeter Wemm ** Side Effects: 512c2aa98e2SPeter Wemm ** none. 513c2aa98e2SPeter Wemm */ 514c2aa98e2SPeter Wemm 515c2aa98e2SPeter Wemm char ** 516c2aa98e2SPeter Wemm copyplist(list, copycont) 517c2aa98e2SPeter Wemm char **list; 518c2aa98e2SPeter Wemm bool copycont; 519c2aa98e2SPeter Wemm { 520c2aa98e2SPeter Wemm register char **vp; 521c2aa98e2SPeter Wemm register char **newvp; 522c2aa98e2SPeter Wemm 523c2aa98e2SPeter Wemm for (vp = list; *vp != NULL; vp++) 524c2aa98e2SPeter Wemm continue; 525c2aa98e2SPeter Wemm 526c2aa98e2SPeter Wemm vp++; 527c2aa98e2SPeter Wemm 528c2aa98e2SPeter Wemm newvp = (char **) xalloc((int) (vp - list) * sizeof *vp); 52906f25ae9SGregory Neil Shapiro memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); 530c2aa98e2SPeter Wemm 531c2aa98e2SPeter Wemm if (copycont) 532c2aa98e2SPeter Wemm { 533c2aa98e2SPeter Wemm for (vp = newvp; *vp != NULL; vp++) 534c2aa98e2SPeter Wemm *vp = newstr(*vp); 535c2aa98e2SPeter Wemm } 536c2aa98e2SPeter Wemm 53706f25ae9SGregory Neil Shapiro return newvp; 538c2aa98e2SPeter Wemm } 539c2aa98e2SPeter Wemm /* 540c2aa98e2SPeter Wemm ** COPYQUEUE -- copy address queue. 541c2aa98e2SPeter Wemm ** 542c2aa98e2SPeter Wemm ** This routine is the equivalent of newstr for address queues 54306f25ae9SGregory Neil Shapiro ** addresses marked as QS_IS_DEAD() aren't copied 544c2aa98e2SPeter Wemm ** 545c2aa98e2SPeter Wemm ** Parameters: 546c2aa98e2SPeter Wemm ** addr -- list of address structures to copy. 547c2aa98e2SPeter Wemm ** 548c2aa98e2SPeter Wemm ** Returns: 549c2aa98e2SPeter Wemm ** a copy of 'addr'. 550c2aa98e2SPeter Wemm ** 551c2aa98e2SPeter Wemm ** Side Effects: 552c2aa98e2SPeter Wemm ** none. 553c2aa98e2SPeter Wemm */ 554c2aa98e2SPeter Wemm 555c2aa98e2SPeter Wemm ADDRESS * 556c2aa98e2SPeter Wemm copyqueue(addr) 557c2aa98e2SPeter Wemm ADDRESS *addr; 558c2aa98e2SPeter Wemm { 559c2aa98e2SPeter Wemm register ADDRESS *newaddr; 560c2aa98e2SPeter Wemm ADDRESS *ret; 561c2aa98e2SPeter Wemm register ADDRESS **tail = &ret; 562c2aa98e2SPeter Wemm 563c2aa98e2SPeter Wemm while (addr != NULL) 564c2aa98e2SPeter Wemm { 56506f25ae9SGregory Neil Shapiro if (!QS_IS_DEAD(addr->q_state)) 566c2aa98e2SPeter Wemm { 56706f25ae9SGregory Neil Shapiro newaddr = (ADDRESS *) xalloc(sizeof *newaddr); 568c2aa98e2SPeter Wemm STRUCTCOPY(*addr, *newaddr); 569c2aa98e2SPeter Wemm *tail = newaddr; 570c2aa98e2SPeter Wemm tail = &newaddr->q_next; 571c2aa98e2SPeter Wemm } 572c2aa98e2SPeter Wemm addr = addr->q_next; 573c2aa98e2SPeter Wemm } 574c2aa98e2SPeter Wemm *tail = NULL; 575c2aa98e2SPeter Wemm 576c2aa98e2SPeter Wemm return ret; 577c2aa98e2SPeter Wemm } 578c2aa98e2SPeter Wemm /* 57906f25ae9SGregory Neil Shapiro ** LOG_SENDMAIL_PID -- record sendmail pid and command line. 58006f25ae9SGregory Neil Shapiro ** 58106f25ae9SGregory Neil Shapiro ** Parameters: 58206f25ae9SGregory Neil Shapiro ** e -- the current envelope. 58306f25ae9SGregory Neil Shapiro ** 58406f25ae9SGregory Neil Shapiro ** Returns: 58506f25ae9SGregory Neil Shapiro ** none. 58606f25ae9SGregory Neil Shapiro ** 58706f25ae9SGregory Neil Shapiro ** Side Effects: 58806f25ae9SGregory Neil Shapiro ** writes pidfile. 58906f25ae9SGregory Neil Shapiro */ 59006f25ae9SGregory Neil Shapiro 59106f25ae9SGregory Neil Shapiro void 59206f25ae9SGregory Neil Shapiro log_sendmail_pid(e) 59306f25ae9SGregory Neil Shapiro ENVELOPE *e; 59406f25ae9SGregory Neil Shapiro { 59506f25ae9SGregory Neil Shapiro long sff; 59606f25ae9SGregory Neil Shapiro FILE *pidf; 59706f25ae9SGregory Neil Shapiro char pidpath[MAXPATHLEN + 1]; 59806f25ae9SGregory Neil Shapiro 59906f25ae9SGregory Neil Shapiro /* write the pid to the log file for posterity */ 60006f25ae9SGregory Neil Shapiro sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 60106f25ae9SGregory Neil Shapiro if (TrustedUid != 0 && RealUid == TrustedUid) 60206f25ae9SGregory Neil Shapiro sff |= SFF_OPENASROOT; 60306f25ae9SGregory Neil Shapiro expand(PidFile, pidpath, sizeof pidpath, e); 60406f25ae9SGregory Neil Shapiro pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, 0644, sff); 60506f25ae9SGregory Neil Shapiro if (pidf == NULL) 60606f25ae9SGregory Neil Shapiro { 607602a2b1bSGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, "unable to write %s: %s", 608602a2b1bSGregory Neil Shapiro pidpath, errstring(errno)); 60906f25ae9SGregory Neil Shapiro } 61006f25ae9SGregory Neil Shapiro else 61106f25ae9SGregory Neil Shapiro { 6128774250cSGregory Neil Shapiro pid_t pid; 61306f25ae9SGregory Neil Shapiro extern char *CommandLineArgs; 61406f25ae9SGregory Neil Shapiro 6158774250cSGregory Neil Shapiro pid = getpid(); 616193538b7SGregory Neil Shapiro 61706f25ae9SGregory Neil Shapiro /* write the process id on line 1 */ 6188774250cSGregory Neil Shapiro fprintf(pidf, "%ld\n", (long) pid); 61906f25ae9SGregory Neil Shapiro 62006f25ae9SGregory Neil Shapiro /* line 2 contains all command line flags */ 62106f25ae9SGregory Neil Shapiro fprintf(pidf, "%s\n", CommandLineArgs); 62206f25ae9SGregory Neil Shapiro 62306f25ae9SGregory Neil Shapiro /* flush and close */ 62406f25ae9SGregory Neil Shapiro (void) fclose(pidf); 62506f25ae9SGregory Neil Shapiro } 62606f25ae9SGregory Neil Shapiro } 62706f25ae9SGregory Neil Shapiro /* 62806f25ae9SGregory Neil Shapiro ** SET_DELIVERY_MODE -- set and record the delivery mode 62906f25ae9SGregory Neil Shapiro ** 63006f25ae9SGregory Neil Shapiro ** Parameters: 63106f25ae9SGregory Neil Shapiro ** mode -- delivery mode 63206f25ae9SGregory Neil Shapiro ** e -- the current envelope. 63306f25ae9SGregory Neil Shapiro ** 63406f25ae9SGregory Neil Shapiro ** Returns: 63506f25ae9SGregory Neil Shapiro ** none. 63606f25ae9SGregory Neil Shapiro ** 63706f25ae9SGregory Neil Shapiro ** Side Effects: 63806f25ae9SGregory Neil Shapiro ** sets $&{deliveryMode} macro 63906f25ae9SGregory Neil Shapiro */ 64006f25ae9SGregory Neil Shapiro 64106f25ae9SGregory Neil Shapiro void 64206f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e) 64306f25ae9SGregory Neil Shapiro int mode; 64406f25ae9SGregory Neil Shapiro ENVELOPE *e; 64506f25ae9SGregory Neil Shapiro { 64606f25ae9SGregory Neil Shapiro char buf[2]; 64706f25ae9SGregory Neil Shapiro 64806f25ae9SGregory Neil Shapiro e->e_sendmode = (char)mode; 64906f25ae9SGregory Neil Shapiro buf[0] = (char)mode; 65006f25ae9SGregory Neil Shapiro buf[1] = '\0'; 65106f25ae9SGregory Neil Shapiro define(macid("{deliveryMode}", NULL), newstr(buf), e); 65206f25ae9SGregory Neil Shapiro } 65306f25ae9SGregory Neil Shapiro /* 654c2aa98e2SPeter Wemm ** PRINTAV -- print argument vector. 655c2aa98e2SPeter Wemm ** 656c2aa98e2SPeter Wemm ** Parameters: 657c2aa98e2SPeter Wemm ** av -- argument vector. 658c2aa98e2SPeter Wemm ** 659c2aa98e2SPeter Wemm ** Returns: 660c2aa98e2SPeter Wemm ** none. 661c2aa98e2SPeter Wemm ** 662c2aa98e2SPeter Wemm ** Side Effects: 663c2aa98e2SPeter Wemm ** prints av. 664c2aa98e2SPeter Wemm */ 665c2aa98e2SPeter Wemm 666c2aa98e2SPeter Wemm void 667c2aa98e2SPeter Wemm printav(av) 668c2aa98e2SPeter Wemm register char **av; 669c2aa98e2SPeter Wemm { 670c2aa98e2SPeter Wemm while (*av != NULL) 671c2aa98e2SPeter Wemm { 672c2aa98e2SPeter Wemm if (tTd(0, 44)) 67306f25ae9SGregory Neil Shapiro dprintf("\n\t%08lx=", (u_long) *av); 674c2aa98e2SPeter Wemm else 675c2aa98e2SPeter Wemm (void) putchar(' '); 676c2aa98e2SPeter Wemm xputs(*av++); 677c2aa98e2SPeter Wemm } 678c2aa98e2SPeter Wemm (void) putchar('\n'); 679c2aa98e2SPeter Wemm } 680c2aa98e2SPeter Wemm /* 681c2aa98e2SPeter Wemm ** LOWER -- turn letter into lower case. 682c2aa98e2SPeter Wemm ** 683c2aa98e2SPeter Wemm ** Parameters: 684c2aa98e2SPeter Wemm ** c -- character to turn into lower case. 685c2aa98e2SPeter Wemm ** 686c2aa98e2SPeter Wemm ** Returns: 687c2aa98e2SPeter Wemm ** c, in lower case. 688c2aa98e2SPeter Wemm ** 689c2aa98e2SPeter Wemm ** Side Effects: 690c2aa98e2SPeter Wemm ** none. 691c2aa98e2SPeter Wemm */ 692c2aa98e2SPeter Wemm 693c2aa98e2SPeter Wemm char 694c2aa98e2SPeter Wemm lower(c) 69506f25ae9SGregory Neil Shapiro register int c; 696c2aa98e2SPeter Wemm { 697c2aa98e2SPeter Wemm return ((isascii(c) && isupper(c)) ? tolower(c) : c); 698c2aa98e2SPeter Wemm } 699c2aa98e2SPeter Wemm /* 700c2aa98e2SPeter Wemm ** XPUTS -- put string doing control escapes. 701c2aa98e2SPeter Wemm ** 702c2aa98e2SPeter Wemm ** Parameters: 703c2aa98e2SPeter Wemm ** s -- string to put. 704c2aa98e2SPeter Wemm ** 705c2aa98e2SPeter Wemm ** Returns: 706c2aa98e2SPeter Wemm ** none. 707c2aa98e2SPeter Wemm ** 708c2aa98e2SPeter Wemm ** Side Effects: 709c2aa98e2SPeter Wemm ** output to stdout 710c2aa98e2SPeter Wemm */ 711c2aa98e2SPeter Wemm 712c2aa98e2SPeter Wemm void 713c2aa98e2SPeter Wemm xputs(s) 714c2aa98e2SPeter Wemm register const char *s; 715c2aa98e2SPeter Wemm { 716c2aa98e2SPeter Wemm register int c; 717c2aa98e2SPeter Wemm register struct metamac *mp; 718c2aa98e2SPeter Wemm bool shiftout = FALSE; 719c2aa98e2SPeter Wemm extern struct metamac MetaMacros[]; 720c2aa98e2SPeter Wemm 721c2aa98e2SPeter Wemm if (s == NULL) 722c2aa98e2SPeter Wemm { 723c2aa98e2SPeter Wemm printf("%s<null>%s", TermEscape.te_rv_on, TermEscape.te_rv_off); 724c2aa98e2SPeter Wemm return; 725c2aa98e2SPeter Wemm } 726c2aa98e2SPeter Wemm while ((c = (*s++ & 0377)) != '\0') 727c2aa98e2SPeter Wemm { 728c2aa98e2SPeter Wemm if (shiftout) 729c2aa98e2SPeter Wemm { 730c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_off); 731c2aa98e2SPeter Wemm shiftout = FALSE; 732c2aa98e2SPeter Wemm } 733c2aa98e2SPeter Wemm if (!isascii(c)) 734c2aa98e2SPeter Wemm { 735c2aa98e2SPeter Wemm if (c == MATCHREPL) 736c2aa98e2SPeter Wemm { 737c2aa98e2SPeter Wemm printf("%s$", TermEscape.te_rv_on); 738c2aa98e2SPeter Wemm shiftout = TRUE; 739c2aa98e2SPeter Wemm if (*s == '\0') 740c2aa98e2SPeter Wemm continue; 741c2aa98e2SPeter Wemm c = *s++ & 0377; 742c2aa98e2SPeter Wemm goto printchar; 743c2aa98e2SPeter Wemm } 744c2aa98e2SPeter Wemm if (c == MACROEXPAND || c == MACRODEXPAND) 745c2aa98e2SPeter Wemm { 746c2aa98e2SPeter Wemm printf("%s$", TermEscape.te_rv_on); 747c2aa98e2SPeter Wemm if (c == MACRODEXPAND) 74806f25ae9SGregory Neil Shapiro (void) putchar('&'); 749c2aa98e2SPeter Wemm shiftout = TRUE; 750c2aa98e2SPeter Wemm if (*s == '\0') 751c2aa98e2SPeter Wemm continue; 752c2aa98e2SPeter Wemm if (strchr("=~&?", *s) != NULL) 75306f25ae9SGregory Neil Shapiro (void) putchar(*s++); 754c2aa98e2SPeter Wemm if (bitset(0200, *s)) 755193538b7SGregory Neil Shapiro printf("{%s}", macname(bitidx(*s++))); 756c2aa98e2SPeter Wemm else 757c2aa98e2SPeter Wemm printf("%c", *s++); 758c2aa98e2SPeter Wemm continue; 759c2aa98e2SPeter Wemm } 760c2aa98e2SPeter Wemm for (mp = MetaMacros; mp->metaname != '\0'; mp++) 761c2aa98e2SPeter Wemm { 762c2aa98e2SPeter Wemm if ((mp->metaval & 0377) == c) 763c2aa98e2SPeter Wemm { 764c2aa98e2SPeter Wemm printf("%s$%c", 765c2aa98e2SPeter Wemm TermEscape.te_rv_on, 766c2aa98e2SPeter Wemm mp->metaname); 767c2aa98e2SPeter Wemm shiftout = TRUE; 768c2aa98e2SPeter Wemm break; 769c2aa98e2SPeter Wemm } 770c2aa98e2SPeter Wemm } 771c2aa98e2SPeter Wemm if (c == MATCHCLASS || c == MATCHNCLASS) 772c2aa98e2SPeter Wemm { 773c2aa98e2SPeter Wemm if (bitset(0200, *s)) 774c2aa98e2SPeter Wemm printf("{%s}", macname(*s++ & 0377)); 775c2aa98e2SPeter Wemm else if (*s != '\0') 776c2aa98e2SPeter Wemm printf("%c", *s++); 777c2aa98e2SPeter Wemm } 778c2aa98e2SPeter Wemm if (mp->metaname != '\0') 779c2aa98e2SPeter Wemm continue; 780c2aa98e2SPeter Wemm 781c2aa98e2SPeter Wemm /* unrecognized meta character */ 782c2aa98e2SPeter Wemm printf("%sM-", TermEscape.te_rv_on); 783c2aa98e2SPeter Wemm shiftout = TRUE; 784c2aa98e2SPeter Wemm c &= 0177; 785c2aa98e2SPeter Wemm } 786c2aa98e2SPeter Wemm printchar: 787c2aa98e2SPeter Wemm if (isprint(c)) 788c2aa98e2SPeter Wemm { 78906f25ae9SGregory Neil Shapiro (void) putchar(c); 790c2aa98e2SPeter Wemm continue; 791c2aa98e2SPeter Wemm } 792c2aa98e2SPeter Wemm 793c2aa98e2SPeter Wemm /* wasn't a meta-macro -- find another way to print it */ 794c2aa98e2SPeter Wemm switch (c) 795c2aa98e2SPeter Wemm { 796c2aa98e2SPeter Wemm case '\n': 797c2aa98e2SPeter Wemm c = 'n'; 798c2aa98e2SPeter Wemm break; 799c2aa98e2SPeter Wemm 800c2aa98e2SPeter Wemm case '\r': 801c2aa98e2SPeter Wemm c = 'r'; 802c2aa98e2SPeter Wemm break; 803c2aa98e2SPeter Wemm 804c2aa98e2SPeter Wemm case '\t': 805c2aa98e2SPeter Wemm c = 't'; 806c2aa98e2SPeter Wemm break; 807c2aa98e2SPeter Wemm } 808c2aa98e2SPeter Wemm if (!shiftout) 809c2aa98e2SPeter Wemm { 810c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_on); 811c2aa98e2SPeter Wemm shiftout = TRUE; 812c2aa98e2SPeter Wemm } 813c2aa98e2SPeter Wemm if (isprint(c)) 814c2aa98e2SPeter Wemm { 815c2aa98e2SPeter Wemm (void) putchar('\\'); 816c2aa98e2SPeter Wemm (void) putchar(c); 817c2aa98e2SPeter Wemm } 818c2aa98e2SPeter Wemm else 819c2aa98e2SPeter Wemm { 820c2aa98e2SPeter Wemm (void) putchar('^'); 821c2aa98e2SPeter Wemm (void) putchar(c ^ 0100); 822c2aa98e2SPeter Wemm } 823c2aa98e2SPeter Wemm } 824c2aa98e2SPeter Wemm if (shiftout) 825c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_off); 826c2aa98e2SPeter Wemm (void) fflush(stdout); 827c2aa98e2SPeter Wemm } 828c2aa98e2SPeter Wemm /* 829c2aa98e2SPeter Wemm ** MAKELOWER -- Translate a line into lower case 830c2aa98e2SPeter Wemm ** 831c2aa98e2SPeter Wemm ** Parameters: 832c2aa98e2SPeter Wemm ** p -- the string to translate. If NULL, return is 833c2aa98e2SPeter Wemm ** immediate. 834c2aa98e2SPeter Wemm ** 835c2aa98e2SPeter Wemm ** Returns: 836c2aa98e2SPeter Wemm ** none. 837c2aa98e2SPeter Wemm ** 838c2aa98e2SPeter Wemm ** Side Effects: 839c2aa98e2SPeter Wemm ** String pointed to by p is translated to lower case. 840c2aa98e2SPeter Wemm */ 841c2aa98e2SPeter Wemm 842c2aa98e2SPeter Wemm void 843c2aa98e2SPeter Wemm makelower(p) 844c2aa98e2SPeter Wemm register char *p; 845c2aa98e2SPeter Wemm { 846c2aa98e2SPeter Wemm register char c; 847c2aa98e2SPeter Wemm 848c2aa98e2SPeter Wemm if (p == NULL) 849c2aa98e2SPeter Wemm return; 850c2aa98e2SPeter Wemm for (; (c = *p) != '\0'; p++) 851c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 852c2aa98e2SPeter Wemm *p = tolower(c); 853c2aa98e2SPeter Wemm } 854c2aa98e2SPeter Wemm /* 855c2aa98e2SPeter Wemm ** BUILDFNAME -- build full name from gecos style entry. 856c2aa98e2SPeter Wemm ** 857c2aa98e2SPeter Wemm ** This routine interprets the strange entry that would appear 858c2aa98e2SPeter Wemm ** in the GECOS field of the password file. 859c2aa98e2SPeter Wemm ** 860c2aa98e2SPeter Wemm ** Parameters: 861c2aa98e2SPeter Wemm ** p -- name to build. 86206f25ae9SGregory Neil Shapiro ** user -- the login name of this user (for &). 863c2aa98e2SPeter Wemm ** buf -- place to put the result. 864c2aa98e2SPeter Wemm ** buflen -- length of buf. 865c2aa98e2SPeter Wemm ** 866c2aa98e2SPeter Wemm ** Returns: 867c2aa98e2SPeter Wemm ** none. 868c2aa98e2SPeter Wemm ** 869c2aa98e2SPeter Wemm ** Side Effects: 870c2aa98e2SPeter Wemm ** none. 871c2aa98e2SPeter Wemm */ 872c2aa98e2SPeter Wemm 873c2aa98e2SPeter Wemm void 87406f25ae9SGregory Neil Shapiro buildfname(gecos, user, buf, buflen) 875c2aa98e2SPeter Wemm register char *gecos; 87606f25ae9SGregory Neil Shapiro char *user; 877c2aa98e2SPeter Wemm char *buf; 878c2aa98e2SPeter Wemm int buflen; 879c2aa98e2SPeter Wemm { 880c2aa98e2SPeter Wemm register char *p; 881c2aa98e2SPeter Wemm register char *bp = buf; 882c2aa98e2SPeter Wemm 883c2aa98e2SPeter Wemm if (*gecos == '*') 884c2aa98e2SPeter Wemm gecos++; 885c2aa98e2SPeter Wemm 886c2aa98e2SPeter Wemm /* copy gecos, interpolating & to be full name */ 887c2aa98e2SPeter Wemm for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) 888c2aa98e2SPeter Wemm { 889c2aa98e2SPeter Wemm if (bp >= &buf[buflen - 1]) 890c2aa98e2SPeter Wemm { 891c2aa98e2SPeter Wemm /* buffer overflow -- just use login name */ 89206f25ae9SGregory Neil Shapiro snprintf(buf, buflen, "%s", user); 893c2aa98e2SPeter Wemm return; 894c2aa98e2SPeter Wemm } 895c2aa98e2SPeter Wemm if (*p == '&') 896c2aa98e2SPeter Wemm { 897c2aa98e2SPeter Wemm /* interpolate full name */ 89806f25ae9SGregory Neil Shapiro snprintf(bp, buflen - (bp - buf), "%s", user); 899c2aa98e2SPeter Wemm *bp = toupper(*bp); 900c2aa98e2SPeter Wemm bp += strlen(bp); 901c2aa98e2SPeter Wemm } 902c2aa98e2SPeter Wemm else 903c2aa98e2SPeter Wemm *bp++ = *p; 904c2aa98e2SPeter Wemm } 905c2aa98e2SPeter Wemm *bp = '\0'; 906c2aa98e2SPeter Wemm } 907c2aa98e2SPeter Wemm /* 908c2aa98e2SPeter Wemm ** FIXCRLF -- fix <CR><LF> in line. 909c2aa98e2SPeter Wemm ** 910c2aa98e2SPeter Wemm ** Looks for the <CR><LF> combination and turns it into the 911c2aa98e2SPeter Wemm ** UNIX canonical <NL> character. It only takes one line, 912c2aa98e2SPeter Wemm ** i.e., it is assumed that the first <NL> found is the end 913c2aa98e2SPeter Wemm ** of the line. 914c2aa98e2SPeter Wemm ** 915c2aa98e2SPeter Wemm ** Parameters: 916c2aa98e2SPeter Wemm ** line -- the line to fix. 917c2aa98e2SPeter Wemm ** stripnl -- if true, strip the newline also. 918c2aa98e2SPeter Wemm ** 919c2aa98e2SPeter Wemm ** Returns: 920c2aa98e2SPeter Wemm ** none. 921c2aa98e2SPeter Wemm ** 922c2aa98e2SPeter Wemm ** Side Effects: 923c2aa98e2SPeter Wemm ** line is changed in place. 924c2aa98e2SPeter Wemm */ 925c2aa98e2SPeter Wemm 926c2aa98e2SPeter Wemm void 927c2aa98e2SPeter Wemm fixcrlf(line, stripnl) 928c2aa98e2SPeter Wemm char *line; 929c2aa98e2SPeter Wemm bool stripnl; 930c2aa98e2SPeter Wemm { 931c2aa98e2SPeter Wemm register char *p; 932c2aa98e2SPeter Wemm 933c2aa98e2SPeter Wemm p = strchr(line, '\n'); 934c2aa98e2SPeter Wemm if (p == NULL) 935c2aa98e2SPeter Wemm return; 936c2aa98e2SPeter Wemm if (p > line && p[-1] == '\r') 937c2aa98e2SPeter Wemm p--; 938c2aa98e2SPeter Wemm if (!stripnl) 939c2aa98e2SPeter Wemm *p++ = '\n'; 940c2aa98e2SPeter Wemm *p = '\0'; 941c2aa98e2SPeter Wemm } 942c2aa98e2SPeter Wemm /* 943c2aa98e2SPeter Wemm ** PUTLINE -- put a line like fputs obeying SMTP conventions 944c2aa98e2SPeter Wemm ** 945c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 946c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 947c2aa98e2SPeter Wemm ** 948c2aa98e2SPeter Wemm ** Parameters: 949c2aa98e2SPeter Wemm ** l -- line to put. 950c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 951c2aa98e2SPeter Wemm ** 952c2aa98e2SPeter Wemm ** Returns: 953c2aa98e2SPeter Wemm ** none 954c2aa98e2SPeter Wemm ** 955c2aa98e2SPeter Wemm ** Side Effects: 956c2aa98e2SPeter Wemm ** output of l to fp. 957c2aa98e2SPeter Wemm */ 958c2aa98e2SPeter Wemm 959c2aa98e2SPeter Wemm void 960c2aa98e2SPeter Wemm putline(l, mci) 961c2aa98e2SPeter Wemm register char *l; 962c2aa98e2SPeter Wemm register MCI *mci; 963c2aa98e2SPeter Wemm { 964c2aa98e2SPeter Wemm putxline(l, strlen(l), mci, PXLF_MAPFROM); 965c2aa98e2SPeter Wemm } 966c2aa98e2SPeter Wemm /* 967c2aa98e2SPeter Wemm ** PUTXLINE -- putline with flags bits. 968c2aa98e2SPeter Wemm ** 969c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 970c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 971c2aa98e2SPeter Wemm ** 972c2aa98e2SPeter Wemm ** Parameters: 973c2aa98e2SPeter Wemm ** l -- line to put. 974c2aa98e2SPeter Wemm ** len -- the length of the line. 975c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 976c2aa98e2SPeter Wemm ** pxflags -- flag bits: 977c2aa98e2SPeter Wemm ** PXLF_MAPFROM -- map From_ to >From_. 978c2aa98e2SPeter Wemm ** PXLF_STRIP8BIT -- strip 8th bit. 979c2aa98e2SPeter Wemm ** PXLF_HEADER -- map bare newline in header to newline space. 980c2aa98e2SPeter Wemm ** 981c2aa98e2SPeter Wemm ** Returns: 982c2aa98e2SPeter Wemm ** none 983c2aa98e2SPeter Wemm ** 984c2aa98e2SPeter Wemm ** Side Effects: 985c2aa98e2SPeter Wemm ** output of l to fp. 986c2aa98e2SPeter Wemm */ 987c2aa98e2SPeter Wemm 988c2aa98e2SPeter Wemm void 989c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags) 990c2aa98e2SPeter Wemm register char *l; 991c2aa98e2SPeter Wemm size_t len; 992c2aa98e2SPeter Wemm register MCI *mci; 993c2aa98e2SPeter Wemm int pxflags; 994c2aa98e2SPeter Wemm { 99506f25ae9SGregory Neil Shapiro bool dead = FALSE; 996c2aa98e2SPeter Wemm register char *p, *end; 997c2aa98e2SPeter Wemm int slop = 0; 998c2aa98e2SPeter Wemm 999c2aa98e2SPeter Wemm /* strip out 0200 bits -- these can look like TELNET protocol */ 1000c2aa98e2SPeter Wemm if (bitset(MCIF_7BIT, mci->mci_flags) || 1001c2aa98e2SPeter Wemm bitset(PXLF_STRIP8BIT, pxflags)) 1002c2aa98e2SPeter Wemm { 1003c2aa98e2SPeter Wemm register char svchar; 1004c2aa98e2SPeter Wemm 1005c2aa98e2SPeter Wemm for (p = l; (svchar = *p) != '\0'; ++p) 1006c2aa98e2SPeter Wemm if (bitset(0200, svchar)) 1007c2aa98e2SPeter Wemm *p = svchar &~ 0200; 1008c2aa98e2SPeter Wemm } 1009c2aa98e2SPeter Wemm 1010c2aa98e2SPeter Wemm end = l + len; 1011c2aa98e2SPeter Wemm do 1012c2aa98e2SPeter Wemm { 1013c2aa98e2SPeter Wemm /* find the end of the line */ 1014c2aa98e2SPeter Wemm p = memchr(l, '\n', end - l); 1015c2aa98e2SPeter Wemm if (p == NULL) 1016c2aa98e2SPeter Wemm p = end; 1017c2aa98e2SPeter Wemm 1018c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1019c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d >>> ", (int) getpid()); 1020c2aa98e2SPeter Wemm 1021c2aa98e2SPeter Wemm /* check for line overflow */ 1022c2aa98e2SPeter Wemm while (mci->mci_mailer->m_linelimit > 0 && 1023c2aa98e2SPeter Wemm (p - l + slop) > mci->mci_mailer->m_linelimit) 1024c2aa98e2SPeter Wemm { 1025c2aa98e2SPeter Wemm char *l_base = l; 1026c2aa98e2SPeter Wemm register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 1027c2aa98e2SPeter Wemm 1028c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 1029c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 1030c2aa98e2SPeter Wemm { 103106f25ae9SGregory Neil Shapiro if (putc('.', mci->mci_out) == EOF) 103206f25ae9SGregory Neil Shapiro dead = TRUE; 1033193538b7SGregory Neil Shapiro else 1034193538b7SGregory Neil Shapiro { 1035193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 1036193538b7SGregory Neil Shapiro DataProgress = TRUE; 1037193538b7SGregory Neil Shapiro } 1038c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1039c2aa98e2SPeter Wemm (void) putc('.', TrafficLogFile); 1040c2aa98e2SPeter Wemm } 1041c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1042c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1043c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1044c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1045c2aa98e2SPeter Wemm { 104606f25ae9SGregory Neil Shapiro if (putc('>', mci->mci_out) == EOF) 104706f25ae9SGregory Neil Shapiro dead = TRUE; 1048193538b7SGregory Neil Shapiro else 1049193538b7SGregory Neil Shapiro { 1050193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 1051193538b7SGregory Neil Shapiro DataProgress = TRUE; 1052193538b7SGregory Neil Shapiro } 1053c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1054c2aa98e2SPeter Wemm (void) putc('>', TrafficLogFile); 1055c2aa98e2SPeter Wemm } 105606f25ae9SGregory Neil Shapiro if (dead) 105706f25ae9SGregory Neil Shapiro break; 105806f25ae9SGregory Neil Shapiro 1059c2aa98e2SPeter Wemm while (l < q) 1060c2aa98e2SPeter Wemm { 106106f25ae9SGregory Neil Shapiro if (putc((unsigned char) *l++, mci->mci_out) == 106206f25ae9SGregory Neil Shapiro EOF) 106306f25ae9SGregory Neil Shapiro { 106406f25ae9SGregory Neil Shapiro dead = TRUE; 106506f25ae9SGregory Neil Shapiro break; 1066c2aa98e2SPeter Wemm } 1067193538b7SGregory Neil Shapiro else 1068193538b7SGregory Neil Shapiro { 106906f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 107006f25ae9SGregory Neil Shapiro DataProgress = TRUE; 107106f25ae9SGregory Neil Shapiro } 1072193538b7SGregory Neil Shapiro } 107306f25ae9SGregory Neil Shapiro if (dead) 107406f25ae9SGregory Neil Shapiro break; 107506f25ae9SGregory Neil Shapiro 107606f25ae9SGregory Neil Shapiro if (putc('!', mci->mci_out) == EOF || 107706f25ae9SGregory Neil Shapiro fputs(mci->mci_mailer->m_eol, 107806f25ae9SGregory Neil Shapiro mci->mci_out) == EOF || 107906f25ae9SGregory Neil Shapiro putc(' ', mci->mci_out) == EOF) 108006f25ae9SGregory Neil Shapiro { 108106f25ae9SGregory Neil Shapiro dead = TRUE; 108206f25ae9SGregory Neil Shapiro break; 108306f25ae9SGregory Neil Shapiro } 1084193538b7SGregory Neil Shapiro else 1085193538b7SGregory Neil Shapiro { 108606f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 108706f25ae9SGregory Neil Shapiro DataProgress = TRUE; 1088193538b7SGregory Neil Shapiro } 1089c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1090c2aa98e2SPeter Wemm { 1091c2aa98e2SPeter Wemm for (l = l_base; l < q; l++) 109206f25ae9SGregory Neil Shapiro (void) putc((unsigned char)*l, 109306f25ae9SGregory Neil Shapiro TrafficLogFile); 1094c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "!\n%05d >>> ", 1095c2aa98e2SPeter Wemm (int) getpid()); 1096c2aa98e2SPeter Wemm } 1097c2aa98e2SPeter Wemm slop = 1; 1098c2aa98e2SPeter Wemm } 1099c2aa98e2SPeter Wemm 110006f25ae9SGregory Neil Shapiro if (dead) 110106f25ae9SGregory Neil Shapiro break; 110206f25ae9SGregory Neil Shapiro 1103c2aa98e2SPeter Wemm /* output last part */ 1104c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 1105c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 1106c2aa98e2SPeter Wemm { 110706f25ae9SGregory Neil Shapiro if (putc('.', mci->mci_out) == EOF) 110806f25ae9SGregory Neil Shapiro break; 1109193538b7SGregory Neil Shapiro else 1110193538b7SGregory Neil Shapiro { 1111193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 1112193538b7SGregory Neil Shapiro DataProgress = TRUE; 1113193538b7SGregory Neil Shapiro } 1114c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1115c2aa98e2SPeter Wemm (void) putc('.', TrafficLogFile); 1116c2aa98e2SPeter Wemm } 1117c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 1118c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 1119c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 1120c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 1121c2aa98e2SPeter Wemm { 112206f25ae9SGregory Neil Shapiro if (putc('>', mci->mci_out) == EOF) 112306f25ae9SGregory Neil Shapiro break; 1124193538b7SGregory Neil Shapiro else 1125193538b7SGregory Neil Shapiro { 1126193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 1127193538b7SGregory Neil Shapiro DataProgress = TRUE; 1128193538b7SGregory Neil Shapiro } 1129c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1130c2aa98e2SPeter Wemm (void) putc('>', TrafficLogFile); 1131c2aa98e2SPeter Wemm } 1132c2aa98e2SPeter Wemm for ( ; l < p; ++l) 1133c2aa98e2SPeter Wemm { 1134c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 113506f25ae9SGregory Neil Shapiro (void) putc((unsigned char)*l, TrafficLogFile); 113606f25ae9SGregory Neil Shapiro if (putc((unsigned char) *l, mci->mci_out) == EOF) 113706f25ae9SGregory Neil Shapiro { 113806f25ae9SGregory Neil Shapiro dead = TRUE; 113906f25ae9SGregory Neil Shapiro break; 1140c2aa98e2SPeter Wemm } 1141193538b7SGregory Neil Shapiro else 1142193538b7SGregory Neil Shapiro { 114306f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 114406f25ae9SGregory Neil Shapiro DataProgress = TRUE; 114506f25ae9SGregory Neil Shapiro } 1146193538b7SGregory Neil Shapiro } 114706f25ae9SGregory Neil Shapiro if (dead) 114806f25ae9SGregory Neil Shapiro break; 114906f25ae9SGregory Neil Shapiro 1150c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1151c2aa98e2SPeter Wemm (void) putc('\n', TrafficLogFile); 115206f25ae9SGregory Neil Shapiro if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) 115306f25ae9SGregory Neil Shapiro break; 1154193538b7SGregory Neil Shapiro else 1155193538b7SGregory Neil Shapiro { 1156193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 1157193538b7SGregory Neil Shapiro DataProgress = TRUE; 1158193538b7SGregory Neil Shapiro } 1159c2aa98e2SPeter Wemm if (l < end && *l == '\n') 1160c2aa98e2SPeter Wemm { 1161c2aa98e2SPeter Wemm if (*++l != ' ' && *l != '\t' && *l != '\0' && 1162c2aa98e2SPeter Wemm bitset(PXLF_HEADER, pxflags)) 1163c2aa98e2SPeter Wemm { 116406f25ae9SGregory Neil Shapiro if (putc(' ', mci->mci_out) == EOF) 116506f25ae9SGregory Neil Shapiro break; 1166193538b7SGregory Neil Shapiro else 1167193538b7SGregory Neil Shapiro { 1168193538b7SGregory Neil Shapiro /* record progress for DATA timeout */ 1169193538b7SGregory Neil Shapiro DataProgress = TRUE; 1170193538b7SGregory Neil Shapiro } 1171c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1172c2aa98e2SPeter Wemm (void) putc(' ', TrafficLogFile); 1173c2aa98e2SPeter Wemm } 1174c2aa98e2SPeter Wemm } 1175c2aa98e2SPeter Wemm } while (l < end); 1176c2aa98e2SPeter Wemm } 1177c2aa98e2SPeter Wemm /* 1178c2aa98e2SPeter Wemm ** XUNLINK -- unlink a file, doing logging as appropriate. 1179c2aa98e2SPeter Wemm ** 1180c2aa98e2SPeter Wemm ** Parameters: 1181c2aa98e2SPeter Wemm ** f -- name of file to unlink. 1182c2aa98e2SPeter Wemm ** 1183c2aa98e2SPeter Wemm ** Returns: 1184c2aa98e2SPeter Wemm ** none. 1185c2aa98e2SPeter Wemm ** 1186c2aa98e2SPeter Wemm ** Side Effects: 1187c2aa98e2SPeter Wemm ** f is unlinked. 1188c2aa98e2SPeter Wemm */ 1189c2aa98e2SPeter Wemm 1190c2aa98e2SPeter Wemm void 1191c2aa98e2SPeter Wemm xunlink(f) 1192c2aa98e2SPeter Wemm char *f; 1193c2aa98e2SPeter Wemm { 1194c2aa98e2SPeter Wemm register int i; 1195c2aa98e2SPeter Wemm 1196c2aa98e2SPeter Wemm if (LogLevel > 98) 1197c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1198c2aa98e2SPeter Wemm "unlink %s", 1199c2aa98e2SPeter Wemm f); 1200c2aa98e2SPeter Wemm 1201c2aa98e2SPeter Wemm i = unlink(f); 1202c2aa98e2SPeter Wemm if (i < 0 && LogLevel > 97) 1203c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1204c2aa98e2SPeter Wemm "%s: unlink-fail %d", 1205c2aa98e2SPeter Wemm f, errno); 1206c2aa98e2SPeter Wemm } 1207c2aa98e2SPeter Wemm /* 1208c2aa98e2SPeter Wemm ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 1209c2aa98e2SPeter Wemm ** 1210c2aa98e2SPeter Wemm ** Parameters: 1211c2aa98e2SPeter Wemm ** buf -- place to put the input line. 1212c2aa98e2SPeter Wemm ** siz -- size of buf. 1213c2aa98e2SPeter Wemm ** fp -- file to read from. 1214c2aa98e2SPeter Wemm ** timeout -- the timeout before error occurs. 1215c2aa98e2SPeter Wemm ** during -- what we are trying to read (for error messages). 1216c2aa98e2SPeter Wemm ** 1217c2aa98e2SPeter Wemm ** Returns: 1218c2aa98e2SPeter Wemm ** NULL on error (including timeout). This will also leave 1219c2aa98e2SPeter Wemm ** buf containing a null string. 1220c2aa98e2SPeter Wemm ** buf otherwise. 1221c2aa98e2SPeter Wemm ** 1222c2aa98e2SPeter Wemm ** Side Effects: 1223c2aa98e2SPeter Wemm ** none. 1224c2aa98e2SPeter Wemm */ 1225c2aa98e2SPeter Wemm 122606f25ae9SGregory Neil Shapiro 1227c2aa98e2SPeter Wemm static jmp_buf CtxReadTimeout; 1228c2aa98e2SPeter Wemm 1229c2aa98e2SPeter Wemm char * 1230c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during) 1231c2aa98e2SPeter Wemm char *buf; 1232c2aa98e2SPeter Wemm int siz; 1233c2aa98e2SPeter Wemm FILE *fp; 1234c2aa98e2SPeter Wemm time_t timeout; 1235c2aa98e2SPeter Wemm char *during; 1236c2aa98e2SPeter Wemm { 1237c2aa98e2SPeter Wemm register EVENT *ev = NULL; 1238c2aa98e2SPeter Wemm register char *p; 12392e43090eSPeter Wemm int save_errno; 1240c2aa98e2SPeter Wemm 1241c2aa98e2SPeter Wemm if (fp == NULL) 1242c2aa98e2SPeter Wemm { 1243c2aa98e2SPeter Wemm buf[0] = '\0'; 1244c2aa98e2SPeter Wemm return NULL; 1245c2aa98e2SPeter Wemm } 1246c2aa98e2SPeter Wemm 1247c2aa98e2SPeter Wemm /* set the timeout */ 1248c2aa98e2SPeter Wemm if (timeout != 0) 1249c2aa98e2SPeter Wemm { 1250c2aa98e2SPeter Wemm if (setjmp(CtxReadTimeout) != 0) 1251c2aa98e2SPeter Wemm { 1252c2aa98e2SPeter Wemm if (LogLevel > 1) 1253c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 1254c2aa98e2SPeter Wemm "timeout waiting for input from %.100s during %s", 1255c2aa98e2SPeter Wemm CurHostName ? CurHostName : "local", 1256c2aa98e2SPeter Wemm during); 1257c2aa98e2SPeter Wemm buf[0] = '\0'; 1258c2aa98e2SPeter Wemm #if XDEBUG 1259c2aa98e2SPeter Wemm checkfd012(during); 126006f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1261c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1262c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n", 1263c2aa98e2SPeter Wemm (int) getpid()); 12642e43090eSPeter Wemm errno = 0; 126506f25ae9SGregory Neil Shapiro return NULL; 1266c2aa98e2SPeter Wemm } 1267c2aa98e2SPeter Wemm ev = setevent(timeout, readtimeout, 0); 1268c2aa98e2SPeter Wemm } 1269c2aa98e2SPeter Wemm 1270c2aa98e2SPeter Wemm /* try to read */ 1271c2aa98e2SPeter Wemm p = NULL; 12722e43090eSPeter Wemm errno = 0; 1273c2aa98e2SPeter Wemm while (!feof(fp) && !ferror(fp)) 1274c2aa98e2SPeter Wemm { 1275c2aa98e2SPeter Wemm errno = 0; 1276c2aa98e2SPeter Wemm p = fgets(buf, siz, fp); 1277c2aa98e2SPeter Wemm if (p != NULL || errno != EINTR) 1278c2aa98e2SPeter Wemm break; 1279c2aa98e2SPeter Wemm clearerr(fp); 1280c2aa98e2SPeter Wemm } 12812e43090eSPeter Wemm save_errno = errno; 1282c2aa98e2SPeter Wemm 1283c2aa98e2SPeter Wemm /* clear the event if it has not sprung */ 1284c2aa98e2SPeter Wemm clrevent(ev); 1285c2aa98e2SPeter Wemm 1286c2aa98e2SPeter Wemm /* clean up the books and exit */ 1287c2aa98e2SPeter Wemm LineNumber++; 1288c2aa98e2SPeter Wemm if (p == NULL) 1289c2aa98e2SPeter Wemm { 1290c2aa98e2SPeter Wemm buf[0] = '\0'; 1291c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1292c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< [EOF]\n", (int) getpid()); 12932e43090eSPeter Wemm errno = save_errno; 129406f25ae9SGregory Neil Shapiro return NULL; 1295c2aa98e2SPeter Wemm } 1296c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1297c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< %s", (int) getpid(), buf); 1298c2aa98e2SPeter Wemm if (SevenBitInput) 1299c2aa98e2SPeter Wemm { 1300c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1301c2aa98e2SPeter Wemm *p &= ~0200; 1302c2aa98e2SPeter Wemm } 1303c2aa98e2SPeter Wemm else if (!HasEightBits) 1304c2aa98e2SPeter Wemm { 1305c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1306c2aa98e2SPeter Wemm { 1307c2aa98e2SPeter Wemm if (bitset(0200, *p)) 1308c2aa98e2SPeter Wemm { 1309c2aa98e2SPeter Wemm HasEightBits = TRUE; 1310c2aa98e2SPeter Wemm break; 1311c2aa98e2SPeter Wemm } 1312c2aa98e2SPeter Wemm } 1313c2aa98e2SPeter Wemm } 131406f25ae9SGregory Neil Shapiro return buf; 1315c2aa98e2SPeter Wemm } 1316c2aa98e2SPeter Wemm 1317c2aa98e2SPeter Wemm /* ARGSUSED */ 1318c2aa98e2SPeter Wemm static void 1319c2aa98e2SPeter Wemm readtimeout(timeout) 1320c2aa98e2SPeter Wemm time_t timeout; 1321c2aa98e2SPeter Wemm { 13228774250cSGregory Neil Shapiro /* 13238774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 13248774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 13258774250cSGregory Neil Shapiro ** DOING. 13268774250cSGregory Neil Shapiro */ 13278774250cSGregory Neil Shapiro 13288774250cSGregory Neil Shapiro errno = ETIMEDOUT; 1329c2aa98e2SPeter Wemm longjmp(CtxReadTimeout, 1); 1330c2aa98e2SPeter Wemm } 1331c2aa98e2SPeter Wemm /* 1332c2aa98e2SPeter Wemm ** FGETFOLDED -- like fgets, but know about folded lines. 1333c2aa98e2SPeter Wemm ** 1334c2aa98e2SPeter Wemm ** Parameters: 1335c2aa98e2SPeter Wemm ** buf -- place to put result. 1336c2aa98e2SPeter Wemm ** n -- bytes available. 1337c2aa98e2SPeter Wemm ** f -- file to read from. 1338c2aa98e2SPeter Wemm ** 1339c2aa98e2SPeter Wemm ** Returns: 1340c2aa98e2SPeter Wemm ** input line(s) on success, NULL on error or EOF. 1341c2aa98e2SPeter Wemm ** This will normally be buf -- unless the line is too 1342c2aa98e2SPeter Wemm ** long, when it will be xalloc()ed. 1343c2aa98e2SPeter Wemm ** 1344c2aa98e2SPeter Wemm ** Side Effects: 1345c2aa98e2SPeter Wemm ** buf gets lines from f, with continuation lines (lines 1346c2aa98e2SPeter Wemm ** with leading white space) appended. CRLF's are mapped 1347c2aa98e2SPeter Wemm ** into single newlines. Any trailing NL is stripped. 1348c2aa98e2SPeter Wemm */ 1349c2aa98e2SPeter Wemm 1350c2aa98e2SPeter Wemm char * 1351c2aa98e2SPeter Wemm fgetfolded(buf, n, f) 1352c2aa98e2SPeter Wemm char *buf; 1353c2aa98e2SPeter Wemm register int n; 1354c2aa98e2SPeter Wemm FILE *f; 1355c2aa98e2SPeter Wemm { 1356c2aa98e2SPeter Wemm register char *p = buf; 1357c2aa98e2SPeter Wemm char *bp = buf; 1358c2aa98e2SPeter Wemm register int i; 1359c2aa98e2SPeter Wemm 1360c2aa98e2SPeter Wemm n--; 1361c2aa98e2SPeter Wemm while ((i = getc(f)) != EOF) 1362c2aa98e2SPeter Wemm { 1363c2aa98e2SPeter Wemm if (i == '\r') 1364c2aa98e2SPeter Wemm { 1365c2aa98e2SPeter Wemm i = getc(f); 1366c2aa98e2SPeter Wemm if (i != '\n') 1367c2aa98e2SPeter Wemm { 1368c2aa98e2SPeter Wemm if (i != EOF) 1369c2aa98e2SPeter Wemm (void) ungetc(i, f); 1370c2aa98e2SPeter Wemm i = '\r'; 1371c2aa98e2SPeter Wemm } 1372c2aa98e2SPeter Wemm } 1373c2aa98e2SPeter Wemm if (--n <= 0) 1374c2aa98e2SPeter Wemm { 1375c2aa98e2SPeter Wemm /* allocate new space */ 1376c2aa98e2SPeter Wemm char *nbp; 1377c2aa98e2SPeter Wemm int nn; 1378c2aa98e2SPeter Wemm 1379c2aa98e2SPeter Wemm nn = (p - bp); 1380c2aa98e2SPeter Wemm if (nn < MEMCHUNKSIZE) 1381c2aa98e2SPeter Wemm nn *= 2; 1382c2aa98e2SPeter Wemm else 1383c2aa98e2SPeter Wemm nn += MEMCHUNKSIZE; 1384c2aa98e2SPeter Wemm nbp = xalloc(nn); 138506f25ae9SGregory Neil Shapiro memmove(nbp, bp, p - bp); 1386c2aa98e2SPeter Wemm p = &nbp[p - bp]; 1387c2aa98e2SPeter Wemm if (bp != buf) 13888774250cSGregory Neil Shapiro sm_free(bp); 1389c2aa98e2SPeter Wemm bp = nbp; 1390c2aa98e2SPeter Wemm n = nn - (p - bp); 1391c2aa98e2SPeter Wemm } 1392c2aa98e2SPeter Wemm *p++ = i; 1393c2aa98e2SPeter Wemm if (i == '\n') 1394c2aa98e2SPeter Wemm { 1395c2aa98e2SPeter Wemm LineNumber++; 1396c2aa98e2SPeter Wemm i = getc(f); 1397c2aa98e2SPeter Wemm if (i != EOF) 1398c2aa98e2SPeter Wemm (void) ungetc(i, f); 1399c2aa98e2SPeter Wemm if (i != ' ' && i != '\t') 1400c2aa98e2SPeter Wemm break; 1401c2aa98e2SPeter Wemm } 1402c2aa98e2SPeter Wemm } 1403c2aa98e2SPeter Wemm if (p == bp) 140406f25ae9SGregory Neil Shapiro return NULL; 1405c2aa98e2SPeter Wemm if (p[-1] == '\n') 1406c2aa98e2SPeter Wemm p--; 1407c2aa98e2SPeter Wemm *p = '\0'; 140806f25ae9SGregory Neil Shapiro return bp; 1409c2aa98e2SPeter Wemm } 1410c2aa98e2SPeter Wemm /* 1411c2aa98e2SPeter Wemm ** CURTIME -- return current time. 1412c2aa98e2SPeter Wemm ** 1413c2aa98e2SPeter Wemm ** Parameters: 1414c2aa98e2SPeter Wemm ** none. 1415c2aa98e2SPeter Wemm ** 1416c2aa98e2SPeter Wemm ** Returns: 1417c2aa98e2SPeter Wemm ** the current time. 1418c2aa98e2SPeter Wemm ** 1419c2aa98e2SPeter Wemm ** Side Effects: 1420c2aa98e2SPeter Wemm ** none. 1421c2aa98e2SPeter Wemm */ 1422c2aa98e2SPeter Wemm 1423c2aa98e2SPeter Wemm time_t 1424c2aa98e2SPeter Wemm curtime() 1425c2aa98e2SPeter Wemm { 1426c2aa98e2SPeter Wemm auto time_t t; 1427c2aa98e2SPeter Wemm 1428c2aa98e2SPeter Wemm (void) time(&t); 142906f25ae9SGregory Neil Shapiro return t; 1430c2aa98e2SPeter Wemm } 1431c2aa98e2SPeter Wemm /* 1432c2aa98e2SPeter Wemm ** ATOBOOL -- convert a string representation to boolean. 1433c2aa98e2SPeter Wemm ** 1434c2aa98e2SPeter Wemm ** Defaults to "TRUE" 1435c2aa98e2SPeter Wemm ** 1436c2aa98e2SPeter Wemm ** Parameters: 1437c2aa98e2SPeter Wemm ** s -- string to convert. Takes "tTyY" as true, 1438c2aa98e2SPeter Wemm ** others as false. 1439c2aa98e2SPeter Wemm ** 1440c2aa98e2SPeter Wemm ** Returns: 1441c2aa98e2SPeter Wemm ** A boolean representation of the string. 1442c2aa98e2SPeter Wemm ** 1443c2aa98e2SPeter Wemm ** Side Effects: 1444c2aa98e2SPeter Wemm ** none. 1445c2aa98e2SPeter Wemm */ 1446c2aa98e2SPeter Wemm 1447c2aa98e2SPeter Wemm bool 1448c2aa98e2SPeter Wemm atobool(s) 1449c2aa98e2SPeter Wemm register char *s; 1450c2aa98e2SPeter Wemm { 1451c2aa98e2SPeter Wemm if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 145206f25ae9SGregory Neil Shapiro return TRUE; 145306f25ae9SGregory Neil Shapiro return FALSE; 1454c2aa98e2SPeter Wemm } 1455c2aa98e2SPeter Wemm /* 1456c2aa98e2SPeter Wemm ** ATOOCT -- convert a string representation to octal. 1457c2aa98e2SPeter Wemm ** 1458c2aa98e2SPeter Wemm ** Parameters: 1459c2aa98e2SPeter Wemm ** s -- string to convert. 1460c2aa98e2SPeter Wemm ** 1461c2aa98e2SPeter Wemm ** Returns: 1462c2aa98e2SPeter Wemm ** An integer representing the string interpreted as an 1463c2aa98e2SPeter Wemm ** octal number. 1464c2aa98e2SPeter Wemm ** 1465c2aa98e2SPeter Wemm ** Side Effects: 1466c2aa98e2SPeter Wemm ** none. 1467c2aa98e2SPeter Wemm */ 1468c2aa98e2SPeter Wemm 1469c2aa98e2SPeter Wemm int 1470c2aa98e2SPeter Wemm atooct(s) 1471c2aa98e2SPeter Wemm register char *s; 1472c2aa98e2SPeter Wemm { 1473c2aa98e2SPeter Wemm register int i = 0; 1474c2aa98e2SPeter Wemm 1475c2aa98e2SPeter Wemm while (*s >= '0' && *s <= '7') 1476c2aa98e2SPeter Wemm i = (i << 3) | (*s++ - '0'); 147706f25ae9SGregory Neil Shapiro return i; 1478c2aa98e2SPeter Wemm } 1479c2aa98e2SPeter Wemm /* 1480c2aa98e2SPeter Wemm ** BITINTERSECT -- tell if two bitmaps intersect 1481c2aa98e2SPeter Wemm ** 1482c2aa98e2SPeter Wemm ** Parameters: 1483c2aa98e2SPeter Wemm ** a, b -- the bitmaps in question 1484c2aa98e2SPeter Wemm ** 1485c2aa98e2SPeter Wemm ** Returns: 1486c2aa98e2SPeter Wemm ** TRUE if they have a non-null intersection 1487c2aa98e2SPeter Wemm ** FALSE otherwise 1488c2aa98e2SPeter Wemm ** 1489c2aa98e2SPeter Wemm ** Side Effects: 1490c2aa98e2SPeter Wemm ** none. 1491c2aa98e2SPeter Wemm */ 1492c2aa98e2SPeter Wemm 1493c2aa98e2SPeter Wemm bool 1494c2aa98e2SPeter Wemm bitintersect(a, b) 149506f25ae9SGregory Neil Shapiro BITMAP256 a; 149606f25ae9SGregory Neil Shapiro BITMAP256 b; 1497c2aa98e2SPeter Wemm { 1498c2aa98e2SPeter Wemm int i; 1499c2aa98e2SPeter Wemm 1500c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1501193538b7SGregory Neil Shapiro { 1502c2aa98e2SPeter Wemm if ((a[i] & b[i]) != 0) 150306f25ae9SGregory Neil Shapiro return TRUE; 1504193538b7SGregory Neil Shapiro } 150506f25ae9SGregory Neil Shapiro return FALSE; 1506c2aa98e2SPeter Wemm } 1507c2aa98e2SPeter Wemm /* 1508c2aa98e2SPeter Wemm ** BITZEROP -- tell if a bitmap is all zero 1509c2aa98e2SPeter Wemm ** 1510c2aa98e2SPeter Wemm ** Parameters: 1511c2aa98e2SPeter Wemm ** map -- the bit map to check 1512c2aa98e2SPeter Wemm ** 1513c2aa98e2SPeter Wemm ** Returns: 1514c2aa98e2SPeter Wemm ** TRUE if map is all zero. 1515c2aa98e2SPeter Wemm ** FALSE if there are any bits set in map. 1516c2aa98e2SPeter Wemm ** 1517c2aa98e2SPeter Wemm ** Side Effects: 1518c2aa98e2SPeter Wemm ** none. 1519c2aa98e2SPeter Wemm */ 1520c2aa98e2SPeter Wemm 1521c2aa98e2SPeter Wemm bool 1522c2aa98e2SPeter Wemm bitzerop(map) 152306f25ae9SGregory Neil Shapiro BITMAP256 map; 1524c2aa98e2SPeter Wemm { 1525c2aa98e2SPeter Wemm int i; 1526c2aa98e2SPeter Wemm 1527c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1528193538b7SGregory Neil Shapiro { 1529c2aa98e2SPeter Wemm if (map[i] != 0) 153006f25ae9SGregory Neil Shapiro return FALSE; 1531193538b7SGregory Neil Shapiro } 153206f25ae9SGregory Neil Shapiro return TRUE; 1533c2aa98e2SPeter Wemm } 1534c2aa98e2SPeter Wemm /* 1535c2aa98e2SPeter Wemm ** STRCONTAINEDIN -- tell if one string is contained in another 1536c2aa98e2SPeter Wemm ** 1537c2aa98e2SPeter Wemm ** Parameters: 1538c2aa98e2SPeter Wemm ** a -- possible substring. 1539c2aa98e2SPeter Wemm ** b -- possible superstring. 1540c2aa98e2SPeter Wemm ** 1541c2aa98e2SPeter Wemm ** Returns: 1542c2aa98e2SPeter Wemm ** TRUE if a is contained in b. 1543c2aa98e2SPeter Wemm ** FALSE otherwise. 1544c2aa98e2SPeter Wemm */ 1545c2aa98e2SPeter Wemm 1546c2aa98e2SPeter Wemm bool 1547c2aa98e2SPeter Wemm strcontainedin(a, b) 1548c2aa98e2SPeter Wemm register char *a; 1549c2aa98e2SPeter Wemm register char *b; 1550c2aa98e2SPeter Wemm { 1551c2aa98e2SPeter Wemm int la; 1552c2aa98e2SPeter Wemm int lb; 1553c2aa98e2SPeter Wemm int c; 1554c2aa98e2SPeter Wemm 1555c2aa98e2SPeter Wemm la = strlen(a); 1556c2aa98e2SPeter Wemm lb = strlen(b); 1557c2aa98e2SPeter Wemm c = *a; 1558c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 1559c2aa98e2SPeter Wemm c = tolower(c); 1560c2aa98e2SPeter Wemm for (; lb-- >= la; b++) 1561c2aa98e2SPeter Wemm { 1562c2aa98e2SPeter Wemm if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c) 1563c2aa98e2SPeter Wemm continue; 1564c2aa98e2SPeter Wemm if (strncasecmp(a, b, la) == 0) 1565c2aa98e2SPeter Wemm return TRUE; 1566c2aa98e2SPeter Wemm } 1567c2aa98e2SPeter Wemm return FALSE; 1568c2aa98e2SPeter Wemm } 1569c2aa98e2SPeter Wemm /* 1570c2aa98e2SPeter Wemm ** CHECKFD012 -- check low numbered file descriptors 1571c2aa98e2SPeter Wemm ** 1572c2aa98e2SPeter Wemm ** File descriptors 0, 1, and 2 should be open at all times. 1573c2aa98e2SPeter Wemm ** This routine verifies that, and fixes it if not true. 1574c2aa98e2SPeter Wemm ** 1575c2aa98e2SPeter Wemm ** Parameters: 1576c2aa98e2SPeter Wemm ** where -- a tag printed if the assertion failed 1577c2aa98e2SPeter Wemm ** 1578c2aa98e2SPeter Wemm ** Returns: 1579c2aa98e2SPeter Wemm ** none 1580c2aa98e2SPeter Wemm */ 1581c2aa98e2SPeter Wemm 1582c2aa98e2SPeter Wemm void 1583c2aa98e2SPeter Wemm checkfd012(where) 1584c2aa98e2SPeter Wemm char *where; 1585c2aa98e2SPeter Wemm { 1586c2aa98e2SPeter Wemm #if XDEBUG 1587c2aa98e2SPeter Wemm register int i; 1588c2aa98e2SPeter Wemm 1589c2aa98e2SPeter Wemm for (i = 0; i < 3; i++) 1590c2aa98e2SPeter Wemm fill_fd(i, where); 1591c2aa98e2SPeter Wemm #endif /* XDEBUG */ 1592c2aa98e2SPeter Wemm } 1593c2aa98e2SPeter Wemm /* 1594c2aa98e2SPeter Wemm ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1595c2aa98e2SPeter Wemm ** 1596c2aa98e2SPeter Wemm ** Parameters: 1597c2aa98e2SPeter Wemm ** fd -- file descriptor to check. 1598c2aa98e2SPeter Wemm ** where -- tag to print on failure. 1599c2aa98e2SPeter Wemm ** 1600c2aa98e2SPeter Wemm ** Returns: 1601c2aa98e2SPeter Wemm ** none. 1602c2aa98e2SPeter Wemm */ 1603c2aa98e2SPeter Wemm 1604c2aa98e2SPeter Wemm void 1605c2aa98e2SPeter Wemm checkfdopen(fd, where) 1606c2aa98e2SPeter Wemm int fd; 1607c2aa98e2SPeter Wemm char *where; 1608c2aa98e2SPeter Wemm { 1609c2aa98e2SPeter Wemm #if XDEBUG 1610c2aa98e2SPeter Wemm struct stat st; 1611c2aa98e2SPeter Wemm 1612c2aa98e2SPeter Wemm if (fstat(fd, &st) < 0 && errno == EBADF) 1613c2aa98e2SPeter Wemm { 1614c2aa98e2SPeter Wemm syserr("checkfdopen(%d): %s not open as expected!", fd, where); 1615c2aa98e2SPeter Wemm printopenfds(TRUE); 1616c2aa98e2SPeter Wemm } 161706f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1618c2aa98e2SPeter Wemm } 1619c2aa98e2SPeter Wemm /* 1620c2aa98e2SPeter Wemm ** CHECKFDS -- check for new or missing file descriptors 1621c2aa98e2SPeter Wemm ** 1622c2aa98e2SPeter Wemm ** Parameters: 1623c2aa98e2SPeter Wemm ** where -- tag for printing. If null, take a base line. 1624c2aa98e2SPeter Wemm ** 1625c2aa98e2SPeter Wemm ** Returns: 1626c2aa98e2SPeter Wemm ** none 1627c2aa98e2SPeter Wemm ** 1628c2aa98e2SPeter Wemm ** Side Effects: 1629c2aa98e2SPeter Wemm ** If where is set, shows changes since the last call. 1630c2aa98e2SPeter Wemm */ 1631c2aa98e2SPeter Wemm 1632c2aa98e2SPeter Wemm void 1633c2aa98e2SPeter Wemm checkfds(where) 1634c2aa98e2SPeter Wemm char *where; 1635c2aa98e2SPeter Wemm { 1636c2aa98e2SPeter Wemm int maxfd; 1637c2aa98e2SPeter Wemm register int fd; 1638c2aa98e2SPeter Wemm bool printhdr = TRUE; 1639c2aa98e2SPeter Wemm int save_errno = errno; 164006f25ae9SGregory Neil Shapiro static BITMAP256 baseline; 1641c2aa98e2SPeter Wemm extern int DtableSize; 1642c2aa98e2SPeter Wemm 1643193538b7SGregory Neil Shapiro if (DtableSize > BITMAPBITS) 1644193538b7SGregory Neil Shapiro maxfd = BITMAPBITS; 1645c2aa98e2SPeter Wemm else 1646c2aa98e2SPeter Wemm maxfd = DtableSize; 1647c2aa98e2SPeter Wemm if (where == NULL) 1648c2aa98e2SPeter Wemm clrbitmap(baseline); 1649c2aa98e2SPeter Wemm 1650c2aa98e2SPeter Wemm for (fd = 0; fd < maxfd; fd++) 1651c2aa98e2SPeter Wemm { 1652c2aa98e2SPeter Wemm struct stat stbuf; 1653c2aa98e2SPeter Wemm 1654c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 1655c2aa98e2SPeter Wemm { 1656c2aa98e2SPeter Wemm if (!bitnset(fd, baseline)) 1657c2aa98e2SPeter Wemm continue; 1658c2aa98e2SPeter Wemm clrbitn(fd, baseline); 1659c2aa98e2SPeter Wemm } 1660c2aa98e2SPeter Wemm else if (!bitnset(fd, baseline)) 1661c2aa98e2SPeter Wemm setbitn(fd, baseline); 1662c2aa98e2SPeter Wemm else 1663c2aa98e2SPeter Wemm continue; 1664c2aa98e2SPeter Wemm 1665c2aa98e2SPeter Wemm /* file state has changed */ 1666c2aa98e2SPeter Wemm if (where == NULL) 1667c2aa98e2SPeter Wemm continue; 1668c2aa98e2SPeter Wemm if (printhdr) 1669c2aa98e2SPeter Wemm { 1670c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1671c2aa98e2SPeter Wemm "%s: changed fds:", 1672c2aa98e2SPeter Wemm where); 1673c2aa98e2SPeter Wemm printhdr = FALSE; 1674c2aa98e2SPeter Wemm } 1675c2aa98e2SPeter Wemm dumpfd(fd, TRUE, TRUE); 1676c2aa98e2SPeter Wemm } 1677c2aa98e2SPeter Wemm errno = save_errno; 1678c2aa98e2SPeter Wemm } 1679c2aa98e2SPeter Wemm /* 1680c2aa98e2SPeter Wemm ** PRINTOPENFDS -- print the open file descriptors (for debugging) 1681c2aa98e2SPeter Wemm ** 1682c2aa98e2SPeter Wemm ** Parameters: 1683c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog; otherwise 1684c2aa98e2SPeter Wemm ** print for debugging. 1685c2aa98e2SPeter Wemm ** 1686c2aa98e2SPeter Wemm ** Returns: 1687c2aa98e2SPeter Wemm ** none. 1688c2aa98e2SPeter Wemm */ 1689c2aa98e2SPeter Wemm 169006f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 1691c2aa98e2SPeter Wemm # include <arpa/inet.h> 169206f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 1693c2aa98e2SPeter Wemm 1694c2aa98e2SPeter Wemm void 1695c2aa98e2SPeter Wemm printopenfds(logit) 1696c2aa98e2SPeter Wemm bool logit; 1697c2aa98e2SPeter Wemm { 1698c2aa98e2SPeter Wemm register int fd; 1699c2aa98e2SPeter Wemm extern int DtableSize; 1700c2aa98e2SPeter Wemm 1701c2aa98e2SPeter Wemm for (fd = 0; fd < DtableSize; fd++) 1702c2aa98e2SPeter Wemm dumpfd(fd, FALSE, logit); 1703c2aa98e2SPeter Wemm } 1704c2aa98e2SPeter Wemm /* 1705c2aa98e2SPeter Wemm ** DUMPFD -- dump a file descriptor 1706c2aa98e2SPeter Wemm ** 1707c2aa98e2SPeter Wemm ** Parameters: 1708c2aa98e2SPeter Wemm ** fd -- the file descriptor to dump. 1709c2aa98e2SPeter Wemm ** printclosed -- if set, print a notification even if 1710c2aa98e2SPeter Wemm ** it is closed; otherwise print nothing. 1711c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog instead of stdout. 1712c2aa98e2SPeter Wemm */ 1713c2aa98e2SPeter Wemm 1714c2aa98e2SPeter Wemm void 1715c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit) 1716c2aa98e2SPeter Wemm int fd; 1717c2aa98e2SPeter Wemm bool printclosed; 1718c2aa98e2SPeter Wemm bool logit; 1719c2aa98e2SPeter Wemm { 1720c2aa98e2SPeter Wemm register char *p; 1721c2aa98e2SPeter Wemm char *hp; 1722c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1723c2aa98e2SPeter Wemm SOCKADDR sa; 172406f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1725c2aa98e2SPeter Wemm auto SOCKADDR_LEN_T slen; 1726c2aa98e2SPeter Wemm int i; 1727c2aa98e2SPeter Wemm #if STAT64 > 0 1728c2aa98e2SPeter Wemm struct stat64 st; 172906f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1730c2aa98e2SPeter Wemm struct stat st; 173106f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1732c2aa98e2SPeter Wemm char buf[200]; 1733c2aa98e2SPeter Wemm 1734c2aa98e2SPeter Wemm p = buf; 1735c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 1736c2aa98e2SPeter Wemm p += strlen(p); 1737c2aa98e2SPeter Wemm 1738c2aa98e2SPeter Wemm if ( 1739c2aa98e2SPeter Wemm #if STAT64 > 0 1740c2aa98e2SPeter Wemm fstat64(fd, &st) 174106f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1742c2aa98e2SPeter Wemm fstat(fd, &st) 174306f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1744c2aa98e2SPeter Wemm < 0) 1745c2aa98e2SPeter Wemm { 1746c2aa98e2SPeter Wemm if (errno != EBADF) 1747c2aa98e2SPeter Wemm { 1748c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)", 1749c2aa98e2SPeter Wemm errstring(errno)); 1750c2aa98e2SPeter Wemm goto printit; 1751c2aa98e2SPeter Wemm } 1752c2aa98e2SPeter Wemm else if (printclosed) 1753c2aa98e2SPeter Wemm { 1754c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CLOSED"); 1755c2aa98e2SPeter Wemm goto printit; 1756c2aa98e2SPeter Wemm } 1757c2aa98e2SPeter Wemm return; 1758c2aa98e2SPeter Wemm } 1759c2aa98e2SPeter Wemm 1760c2aa98e2SPeter Wemm i = fcntl(fd, F_GETFL, NULL); 1761c2aa98e2SPeter Wemm if (i != -1) 1762c2aa98e2SPeter Wemm { 1763c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 1764c2aa98e2SPeter Wemm p += strlen(p); 1765c2aa98e2SPeter Wemm } 1766c2aa98e2SPeter Wemm 176706f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "mode=%o: ", (int) st.st_mode); 1768c2aa98e2SPeter Wemm p += strlen(p); 1769c2aa98e2SPeter Wemm switch (st.st_mode & S_IFMT) 1770c2aa98e2SPeter Wemm { 1771c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1772c2aa98e2SPeter Wemm case S_IFSOCK: 1773c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "SOCK "); 1774c2aa98e2SPeter Wemm p += strlen(p); 177506f25ae9SGregory Neil Shapiro memset(&sa, '\0', sizeof sa); 1776c2aa98e2SPeter Wemm slen = sizeof sa; 1777c2aa98e2SPeter Wemm if (getsockname(fd, &sa.sa, &slen) < 0) 177806f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "(%s)", 177906f25ae9SGregory Neil Shapiro errstring(errno)); 1780c2aa98e2SPeter Wemm else 1781c2aa98e2SPeter Wemm { 1782c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 178306f25ae9SGregory Neil Shapiro if (hp == NULL) 178406f25ae9SGregory Neil Shapiro { 178506f25ae9SGregory Neil Shapiro /* EMPTY */ 178606f25ae9SGregory Neil Shapiro /* do nothing */ 178706f25ae9SGregory Neil Shapiro } 178806f25ae9SGregory Neil Shapiro # if NETINET 178906f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 1790c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s/%d", 1791c2aa98e2SPeter Wemm hp, ntohs(sa.sin.sin_port)); 179206f25ae9SGregory Neil Shapiro # endif /* NETINET */ 179306f25ae9SGregory Neil Shapiro # if NETINET6 179406f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 179506f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "%s/%d", 179606f25ae9SGregory Neil Shapiro hp, ntohs(sa.sin6.sin6_port)); 179706f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1798c2aa98e2SPeter Wemm else 1799c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s", hp); 1800c2aa98e2SPeter Wemm } 1801c2aa98e2SPeter Wemm p += strlen(p); 1802c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "->"); 1803c2aa98e2SPeter Wemm p += strlen(p); 1804c2aa98e2SPeter Wemm slen = sizeof sa; 1805c2aa98e2SPeter Wemm if (getpeername(fd, &sa.sa, &slen) < 0) 1806c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno)); 1807c2aa98e2SPeter Wemm else 1808c2aa98e2SPeter Wemm { 1809c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 181006f25ae9SGregory Neil Shapiro if (hp == NULL) 181106f25ae9SGregory Neil Shapiro { 181206f25ae9SGregory Neil Shapiro /* EMPTY */ 181306f25ae9SGregory Neil Shapiro /* do nothing */ 181406f25ae9SGregory Neil Shapiro } 181506f25ae9SGregory Neil Shapiro # if NETINET 181606f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 1817c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s/%d", 1818c2aa98e2SPeter Wemm hp, ntohs(sa.sin.sin_port)); 181906f25ae9SGregory Neil Shapiro # endif /* NETINET */ 182006f25ae9SGregory Neil Shapiro # if NETINET6 182106f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 182206f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "%s/%d", 182306f25ae9SGregory Neil Shapiro hp, ntohs(sa.sin6.sin6_port)); 182406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1825c2aa98e2SPeter Wemm else 1826c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s", hp); 1827c2aa98e2SPeter Wemm } 1828c2aa98e2SPeter Wemm break; 182906f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1830c2aa98e2SPeter Wemm 1831c2aa98e2SPeter Wemm case S_IFCHR: 1832c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CHR: "); 1833c2aa98e2SPeter Wemm p += strlen(p); 1834c2aa98e2SPeter Wemm goto defprint; 1835c2aa98e2SPeter Wemm 1836c2aa98e2SPeter Wemm case S_IFBLK: 1837c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "BLK: "); 1838c2aa98e2SPeter Wemm p += strlen(p); 1839c2aa98e2SPeter Wemm goto defprint; 1840c2aa98e2SPeter Wemm 1841c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 1842c2aa98e2SPeter Wemm case S_IFIFO: 1843c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "FIFO: "); 1844c2aa98e2SPeter Wemm p += strlen(p); 1845c2aa98e2SPeter Wemm goto defprint; 184606f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 1847c2aa98e2SPeter Wemm 1848c2aa98e2SPeter Wemm #ifdef S_IFDIR 1849c2aa98e2SPeter Wemm case S_IFDIR: 1850c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "DIR: "); 1851c2aa98e2SPeter Wemm p += strlen(p); 1852c2aa98e2SPeter Wemm goto defprint; 185306f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */ 1854c2aa98e2SPeter Wemm 1855c2aa98e2SPeter Wemm #ifdef S_IFLNK 1856c2aa98e2SPeter Wemm case S_IFLNK: 1857c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "LNK: "); 1858c2aa98e2SPeter Wemm p += strlen(p); 1859c2aa98e2SPeter Wemm goto defprint; 186006f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */ 1861c2aa98e2SPeter Wemm 1862c2aa98e2SPeter Wemm default: 1863c2aa98e2SPeter Wemm defprint: 186406f25ae9SGregory Neil Shapiro /*CONSTCOND*/ 1865c2aa98e2SPeter Wemm if (sizeof st.st_ino > sizeof (long)) 1866c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), 1867c2aa98e2SPeter Wemm "dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ", 1868c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 1869c2aa98e2SPeter Wemm quad_to_string(st.st_ino), 187006f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 187106f25ae9SGregory Neil Shapiro (int) st.st_gid); 1872c2aa98e2SPeter Wemm else 1873c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), 1874c2aa98e2SPeter Wemm "dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ", 1875c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 1876c2aa98e2SPeter Wemm (unsigned long) st.st_ino, 187706f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 187806f25ae9SGregory Neil Shapiro (int) st.st_gid); 187906f25ae9SGregory Neil Shapiro /*CONSTCOND*/ 1880c2aa98e2SPeter Wemm if (sizeof st.st_size > sizeof (long)) 1881c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "size=%s", 1882c2aa98e2SPeter Wemm quad_to_string(st.st_size)); 1883c2aa98e2SPeter Wemm else 1884c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "size=%lu", 1885c2aa98e2SPeter Wemm (unsigned long) st.st_size); 1886c2aa98e2SPeter Wemm break; 1887c2aa98e2SPeter Wemm } 1888c2aa98e2SPeter Wemm 1889c2aa98e2SPeter Wemm printit: 1890c2aa98e2SPeter Wemm if (logit) 1891c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 1892c2aa98e2SPeter Wemm "%.800s", buf); 1893c2aa98e2SPeter Wemm else 1894c2aa98e2SPeter Wemm printf("%s\n", buf); 1895c2aa98e2SPeter Wemm } 1896c2aa98e2SPeter Wemm /* 1897c2aa98e2SPeter Wemm ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1898c2aa98e2SPeter Wemm ** 1899c2aa98e2SPeter Wemm ** Parameters: 1900c2aa98e2SPeter Wemm ** host -- the host to shorten (stripped in place). 1901c2aa98e2SPeter Wemm ** 1902c2aa98e2SPeter Wemm ** Returns: 1903602a2b1bSGregory Neil Shapiro ** place where string was trunacted, NULL if not truncated. 1904c2aa98e2SPeter Wemm */ 1905c2aa98e2SPeter Wemm 1906602a2b1bSGregory Neil Shapiro char * 1907c2aa98e2SPeter Wemm shorten_hostname(host) 1908c2aa98e2SPeter Wemm char host[]; 1909c2aa98e2SPeter Wemm { 1910c2aa98e2SPeter Wemm register char *p; 1911c2aa98e2SPeter Wemm char *mydom; 1912c2aa98e2SPeter Wemm int i; 1913c2aa98e2SPeter Wemm bool canon = FALSE; 1914c2aa98e2SPeter Wemm 1915c2aa98e2SPeter Wemm /* strip off final dot */ 1916c2aa98e2SPeter Wemm p = &host[strlen(host) - 1]; 1917c2aa98e2SPeter Wemm if (*p == '.') 1918c2aa98e2SPeter Wemm { 1919c2aa98e2SPeter Wemm *p = '\0'; 1920c2aa98e2SPeter Wemm canon = TRUE; 1921c2aa98e2SPeter Wemm } 1922c2aa98e2SPeter Wemm 1923c2aa98e2SPeter Wemm /* see if there is any domain at all -- if not, we are done */ 1924c2aa98e2SPeter Wemm p = strchr(host, '.'); 1925c2aa98e2SPeter Wemm if (p == NULL) 1926602a2b1bSGregory Neil Shapiro return NULL; 1927c2aa98e2SPeter Wemm 1928c2aa98e2SPeter Wemm /* yes, we have a domain -- see if it looks like us */ 1929c2aa98e2SPeter Wemm mydom = macvalue('m', CurEnv); 1930c2aa98e2SPeter Wemm if (mydom == NULL) 1931c2aa98e2SPeter Wemm mydom = ""; 1932c2aa98e2SPeter Wemm i = strlen(++p); 1933c2aa98e2SPeter Wemm if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 && 1934c2aa98e2SPeter Wemm (mydom[i] == '.' || mydom[i] == '\0')) 1935602a2b1bSGregory Neil Shapiro { 1936c2aa98e2SPeter Wemm *--p = '\0'; 1937602a2b1bSGregory Neil Shapiro return p; 1938602a2b1bSGregory Neil Shapiro } 1939602a2b1bSGregory Neil Shapiro return NULL; 1940c2aa98e2SPeter Wemm } 1941c2aa98e2SPeter Wemm /* 1942c2aa98e2SPeter Wemm ** PROG_OPEN -- open a program for reading 1943c2aa98e2SPeter Wemm ** 1944c2aa98e2SPeter Wemm ** Parameters: 1945c2aa98e2SPeter Wemm ** argv -- the argument list. 1946c2aa98e2SPeter Wemm ** pfd -- pointer to a place to store the file descriptor. 1947c2aa98e2SPeter Wemm ** e -- the current envelope. 1948c2aa98e2SPeter Wemm ** 1949c2aa98e2SPeter Wemm ** Returns: 1950c2aa98e2SPeter Wemm ** pid of the process -- -1 if it failed. 1951c2aa98e2SPeter Wemm */ 1952c2aa98e2SPeter Wemm 19538774250cSGregory Neil Shapiro pid_t 1954c2aa98e2SPeter Wemm prog_open(argv, pfd, e) 1955c2aa98e2SPeter Wemm char **argv; 1956c2aa98e2SPeter Wemm int *pfd; 1957c2aa98e2SPeter Wemm ENVELOPE *e; 1958c2aa98e2SPeter Wemm { 19598774250cSGregory Neil Shapiro pid_t pid; 1960c2aa98e2SPeter Wemm int i; 196106f25ae9SGregory Neil Shapiro int save_errno; 1962c2aa98e2SPeter Wemm int fdv[2]; 1963c2aa98e2SPeter Wemm char *p, *q; 1964c2aa98e2SPeter Wemm char buf[MAXLINE + 1]; 1965c2aa98e2SPeter Wemm extern int DtableSize; 1966c2aa98e2SPeter Wemm 1967c2aa98e2SPeter Wemm if (pipe(fdv) < 0) 1968c2aa98e2SPeter Wemm { 1969c2aa98e2SPeter Wemm syserr("%s: cannot create pipe for stdout", argv[0]); 1970c2aa98e2SPeter Wemm return -1; 1971c2aa98e2SPeter Wemm } 1972c2aa98e2SPeter Wemm pid = fork(); 1973c2aa98e2SPeter Wemm if (pid < 0) 1974c2aa98e2SPeter Wemm { 1975c2aa98e2SPeter Wemm syserr("%s: cannot fork", argv[0]); 197606f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 197706f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1978c2aa98e2SPeter Wemm return -1; 1979c2aa98e2SPeter Wemm } 1980c2aa98e2SPeter Wemm if (pid > 0) 1981c2aa98e2SPeter Wemm { 1982c2aa98e2SPeter Wemm /* parent */ 198306f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1984c2aa98e2SPeter Wemm *pfd = fdv[0]; 1985c2aa98e2SPeter Wemm return pid; 1986c2aa98e2SPeter Wemm } 1987c2aa98e2SPeter Wemm 1988c2aa98e2SPeter Wemm /* child -- close stdin */ 198906f25ae9SGregory Neil Shapiro (void) close(0); 1990c2aa98e2SPeter Wemm 19918774250cSGregory Neil Shapiro /* Reset global flags */ 19928774250cSGregory Neil Shapiro RestartRequest = NULL; 19938774250cSGregory Neil Shapiro ShutdownRequest = NULL; 19948774250cSGregory Neil Shapiro PendingSignal = 0; 19958774250cSGregory Neil Shapiro 1996c2aa98e2SPeter Wemm /* stdout goes back to parent */ 199706f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 1998c2aa98e2SPeter Wemm if (dup2(fdv[1], 1) < 0) 1999c2aa98e2SPeter Wemm { 2000c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stdout", argv[0]); 2001c2aa98e2SPeter Wemm _exit(EX_OSERR); 2002c2aa98e2SPeter Wemm } 200306f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 2004c2aa98e2SPeter Wemm 2005c2aa98e2SPeter Wemm /* stderr goes to transcript if available */ 2006c2aa98e2SPeter Wemm if (e->e_xfp != NULL) 2007c2aa98e2SPeter Wemm { 200806f25ae9SGregory Neil Shapiro int xfd; 200906f25ae9SGregory Neil Shapiro 201006f25ae9SGregory Neil Shapiro xfd = fileno(e->e_xfp); 201106f25ae9SGregory Neil Shapiro if (xfd >= 0 && dup2(xfd, 2) < 0) 2012c2aa98e2SPeter Wemm { 2013c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stderr", argv[0]); 2014c2aa98e2SPeter Wemm _exit(EX_OSERR); 2015c2aa98e2SPeter Wemm } 2016c2aa98e2SPeter Wemm } 2017c2aa98e2SPeter Wemm 2018c2aa98e2SPeter Wemm /* this process has no right to the queue file */ 2019c2aa98e2SPeter Wemm if (e->e_lockfp != NULL) 202006f25ae9SGregory Neil Shapiro (void) close(fileno(e->e_lockfp)); 202106f25ae9SGregory Neil Shapiro 202206f25ae9SGregory Neil Shapiro /* chroot to the program mailer directory, if defined */ 202306f25ae9SGregory Neil Shapiro if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) 202406f25ae9SGregory Neil Shapiro { 202506f25ae9SGregory Neil Shapiro expand(ProgMailer->m_rootdir, buf, sizeof buf, e); 202606f25ae9SGregory Neil Shapiro if (chroot(buf) < 0) 202706f25ae9SGregory Neil Shapiro { 202806f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chroot(%s)", buf); 202906f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 203006f25ae9SGregory Neil Shapiro } 203106f25ae9SGregory Neil Shapiro if (chdir("/") < 0) 203206f25ae9SGregory Neil Shapiro { 203306f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chdir(/)"); 203406f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 203506f25ae9SGregory Neil Shapiro } 203606f25ae9SGregory Neil Shapiro } 2037c2aa98e2SPeter Wemm 2038c2aa98e2SPeter Wemm /* run as default user */ 2039c2aa98e2SPeter Wemm endpwent(); 2040c2aa98e2SPeter Wemm if (setgid(DefGid) < 0 && geteuid() == 0) 204106f25ae9SGregory Neil Shapiro { 2042c2aa98e2SPeter Wemm syserr("prog_open: setgid(%ld) failed", (long) DefGid); 204306f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 204406f25ae9SGregory Neil Shapiro } 2045c2aa98e2SPeter Wemm if (setuid(DefUid) < 0 && geteuid() == 0) 204606f25ae9SGregory Neil Shapiro { 2047c2aa98e2SPeter Wemm syserr("prog_open: setuid(%ld) failed", (long) DefUid); 204806f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 204906f25ae9SGregory Neil Shapiro } 2050c2aa98e2SPeter Wemm 2051c2aa98e2SPeter Wemm /* run in some directory */ 2052c2aa98e2SPeter Wemm if (ProgMailer != NULL) 2053c2aa98e2SPeter Wemm p = ProgMailer->m_execdir; 2054c2aa98e2SPeter Wemm else 2055c2aa98e2SPeter Wemm p = NULL; 2056c2aa98e2SPeter Wemm for (; p != NULL; p = q) 2057c2aa98e2SPeter Wemm { 2058c2aa98e2SPeter Wemm q = strchr(p, ':'); 2059c2aa98e2SPeter Wemm if (q != NULL) 2060c2aa98e2SPeter Wemm *q = '\0'; 2061c2aa98e2SPeter Wemm expand(p, buf, sizeof buf, e); 2062c2aa98e2SPeter Wemm if (q != NULL) 2063c2aa98e2SPeter Wemm *q++ = ':'; 2064c2aa98e2SPeter Wemm if (buf[0] != '\0' && chdir(buf) >= 0) 2065c2aa98e2SPeter Wemm break; 2066c2aa98e2SPeter Wemm } 2067c2aa98e2SPeter Wemm if (p == NULL) 2068c2aa98e2SPeter Wemm { 2069c2aa98e2SPeter Wemm /* backup directories */ 2070c2aa98e2SPeter Wemm if (chdir("/tmp") < 0) 2071c2aa98e2SPeter Wemm (void) chdir("/"); 2072c2aa98e2SPeter Wemm } 2073c2aa98e2SPeter Wemm 2074c2aa98e2SPeter Wemm /* arrange for all the files to be closed */ 2075c2aa98e2SPeter Wemm for (i = 3; i < DtableSize; i++) 2076c2aa98e2SPeter Wemm { 2077c2aa98e2SPeter Wemm register int j; 2078c2aa98e2SPeter Wemm 2079c2aa98e2SPeter Wemm if ((j = fcntl(i, F_GETFD, 0)) != -1) 208006f25ae9SGregory Neil Shapiro (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 2081c2aa98e2SPeter Wemm } 2082c2aa98e2SPeter Wemm 2083c2aa98e2SPeter Wemm /* now exec the process */ 208406f25ae9SGregory Neil Shapiro (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 2085c2aa98e2SPeter Wemm 2086c2aa98e2SPeter Wemm /* woops! failed */ 208706f25ae9SGregory Neil Shapiro save_errno = errno; 2088c2aa98e2SPeter Wemm syserr("%s: cannot exec", argv[0]); 208906f25ae9SGregory Neil Shapiro if (transienterror(save_errno)) 2090c2aa98e2SPeter Wemm _exit(EX_OSERR); 2091c2aa98e2SPeter Wemm _exit(EX_CONFIG); 2092c2aa98e2SPeter Wemm return -1; /* avoid compiler warning on IRIX */ 2093c2aa98e2SPeter Wemm } 2094c2aa98e2SPeter Wemm /* 2095c2aa98e2SPeter Wemm ** GET_COLUMN -- look up a Column in a line buffer 2096c2aa98e2SPeter Wemm ** 2097c2aa98e2SPeter Wemm ** Parameters: 2098c2aa98e2SPeter Wemm ** line -- the raw text line to search. 2099c2aa98e2SPeter Wemm ** col -- the column number to fetch. 2100c2aa98e2SPeter Wemm ** delim -- the delimiter between columns. If null, 2101c2aa98e2SPeter Wemm ** use white space. 2102c2aa98e2SPeter Wemm ** buf -- the output buffer. 2103c2aa98e2SPeter Wemm ** buflen -- the length of buf. 2104c2aa98e2SPeter Wemm ** 2105c2aa98e2SPeter Wemm ** Returns: 2106c2aa98e2SPeter Wemm ** buf if successful. 2107c2aa98e2SPeter Wemm ** NULL otherwise. 2108c2aa98e2SPeter Wemm */ 2109c2aa98e2SPeter Wemm 2110c2aa98e2SPeter Wemm char * 2111c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen) 2112c2aa98e2SPeter Wemm char line[]; 2113c2aa98e2SPeter Wemm int col; 211406f25ae9SGregory Neil Shapiro int delim; 2115c2aa98e2SPeter Wemm char buf[]; 2116c2aa98e2SPeter Wemm int buflen; 2117c2aa98e2SPeter Wemm { 2118c2aa98e2SPeter Wemm char *p; 2119c2aa98e2SPeter Wemm char *begin, *end; 2120c2aa98e2SPeter Wemm int i; 2121c2aa98e2SPeter Wemm char delimbuf[4]; 2122c2aa98e2SPeter Wemm 212306f25ae9SGregory Neil Shapiro if ((char)delim == '\0') 212406f25ae9SGregory Neil Shapiro (void) strlcpy(delimbuf, "\n\t ", sizeof delimbuf); 2125c2aa98e2SPeter Wemm else 2126c2aa98e2SPeter Wemm { 212706f25ae9SGregory Neil Shapiro delimbuf[0] = (char)delim; 2128c2aa98e2SPeter Wemm delimbuf[1] = '\0'; 2129c2aa98e2SPeter Wemm } 2130c2aa98e2SPeter Wemm 2131c2aa98e2SPeter Wemm p = line; 2132c2aa98e2SPeter Wemm if (*p == '\0') 2133c2aa98e2SPeter Wemm return NULL; /* line empty */ 213406f25ae9SGregory Neil Shapiro if (*p == (char)delim && col == 0) 2135c2aa98e2SPeter Wemm return NULL; /* first column empty */ 2136c2aa98e2SPeter Wemm 2137c2aa98e2SPeter Wemm begin = line; 2138c2aa98e2SPeter Wemm 213906f25ae9SGregory Neil Shapiro if (col == 0 && (char)delim == '\0') 2140c2aa98e2SPeter Wemm { 2141c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2142c2aa98e2SPeter Wemm begin++; 2143c2aa98e2SPeter Wemm } 2144c2aa98e2SPeter Wemm 2145c2aa98e2SPeter Wemm for (i = 0; i < col; i++) 2146c2aa98e2SPeter Wemm { 2147c2aa98e2SPeter Wemm if ((begin = strpbrk(begin, delimbuf)) == NULL) 2148c2aa98e2SPeter Wemm return NULL; /* no such column */ 2149c2aa98e2SPeter Wemm begin++; 215006f25ae9SGregory Neil Shapiro if ((char)delim == '\0') 2151c2aa98e2SPeter Wemm { 2152c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 2153c2aa98e2SPeter Wemm begin++; 2154c2aa98e2SPeter Wemm } 2155c2aa98e2SPeter Wemm } 2156c2aa98e2SPeter Wemm 2157c2aa98e2SPeter Wemm end = strpbrk(begin, delimbuf); 2158c2aa98e2SPeter Wemm if (end == NULL) 2159c2aa98e2SPeter Wemm i = strlen(begin); 2160c2aa98e2SPeter Wemm else 2161c2aa98e2SPeter Wemm i = end - begin; 2162c2aa98e2SPeter Wemm if (i >= buflen) 2163c2aa98e2SPeter Wemm i = buflen - 1; 216406f25ae9SGregory Neil Shapiro (void) strlcpy(buf, begin, i + 1); 2165c2aa98e2SPeter Wemm return buf; 2166c2aa98e2SPeter Wemm } 2167c2aa98e2SPeter Wemm /* 2168c2aa98e2SPeter Wemm ** CLEANSTRCPY -- copy string keeping out bogus characters 2169c2aa98e2SPeter Wemm ** 2170c2aa98e2SPeter Wemm ** Parameters: 2171c2aa98e2SPeter Wemm ** t -- "to" string. 2172c2aa98e2SPeter Wemm ** f -- "from" string. 2173c2aa98e2SPeter Wemm ** l -- length of space available in "to" string. 2174c2aa98e2SPeter Wemm ** 2175c2aa98e2SPeter Wemm ** Returns: 2176c2aa98e2SPeter Wemm ** none. 2177c2aa98e2SPeter Wemm */ 2178c2aa98e2SPeter Wemm 2179c2aa98e2SPeter Wemm void 2180c2aa98e2SPeter Wemm cleanstrcpy(t, f, l) 2181c2aa98e2SPeter Wemm register char *t; 2182c2aa98e2SPeter Wemm register char *f; 2183c2aa98e2SPeter Wemm int l; 2184c2aa98e2SPeter Wemm { 2185c2aa98e2SPeter Wemm /* check for newlines and log if necessary */ 2186c2aa98e2SPeter Wemm (void) denlstring(f, TRUE, TRUE); 2187c2aa98e2SPeter Wemm 218806f25ae9SGregory Neil Shapiro if (l <= 0) 218906f25ae9SGregory Neil Shapiro syserr("!cleanstrcpy: length == 0"); 219006f25ae9SGregory Neil Shapiro 2191c2aa98e2SPeter Wemm l--; 2192c2aa98e2SPeter Wemm while (l > 0 && *f != '\0') 2193c2aa98e2SPeter Wemm { 2194c2aa98e2SPeter Wemm if (isascii(*f) && 2195c2aa98e2SPeter Wemm (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 2196c2aa98e2SPeter Wemm { 2197c2aa98e2SPeter Wemm l--; 2198c2aa98e2SPeter Wemm *t++ = *f; 2199c2aa98e2SPeter Wemm } 2200c2aa98e2SPeter Wemm f++; 2201c2aa98e2SPeter Wemm } 2202c2aa98e2SPeter Wemm *t = '\0'; 2203c2aa98e2SPeter Wemm } 220406f25ae9SGregory Neil Shapiro 2205c2aa98e2SPeter Wemm /* 2206c2aa98e2SPeter Wemm ** DENLSTRING -- convert newlines in a string to spaces 2207c2aa98e2SPeter Wemm ** 2208c2aa98e2SPeter Wemm ** Parameters: 2209c2aa98e2SPeter Wemm ** s -- the input string 2210c2aa98e2SPeter Wemm ** strict -- if set, don't permit continuation lines. 2211c2aa98e2SPeter Wemm ** logattacks -- if set, log attempted attacks. 2212c2aa98e2SPeter Wemm ** 2213c2aa98e2SPeter Wemm ** Returns: 2214c2aa98e2SPeter Wemm ** A pointer to a version of the string with newlines 2215c2aa98e2SPeter Wemm ** mapped to spaces. This should be copied. 2216c2aa98e2SPeter Wemm */ 2217c2aa98e2SPeter Wemm 2218c2aa98e2SPeter Wemm char * 2219c2aa98e2SPeter Wemm denlstring(s, strict, logattacks) 2220c2aa98e2SPeter Wemm char *s; 2221c2aa98e2SPeter Wemm bool strict; 2222c2aa98e2SPeter Wemm bool logattacks; 2223c2aa98e2SPeter Wemm { 2224c2aa98e2SPeter Wemm register char *p; 2225c2aa98e2SPeter Wemm int l; 2226c2aa98e2SPeter Wemm static char *bp = NULL; 2227c2aa98e2SPeter Wemm static int bl = 0; 2228c2aa98e2SPeter Wemm 2229c2aa98e2SPeter Wemm p = s; 2230c2aa98e2SPeter Wemm while ((p = strchr(p, '\n')) != NULL) 2231c2aa98e2SPeter Wemm if (strict || (*++p != ' ' && *p != '\t')) 2232c2aa98e2SPeter Wemm break; 2233c2aa98e2SPeter Wemm if (p == NULL) 2234c2aa98e2SPeter Wemm return s; 2235c2aa98e2SPeter Wemm 2236c2aa98e2SPeter Wemm l = strlen(s) + 1; 2237c2aa98e2SPeter Wemm if (bl < l) 2238c2aa98e2SPeter Wemm { 2239c2aa98e2SPeter Wemm /* allocate more space */ 2240c2aa98e2SPeter Wemm if (bp != NULL) 22418774250cSGregory Neil Shapiro sm_free(bp); 2242c2aa98e2SPeter Wemm bp = xalloc(l); 2243c2aa98e2SPeter Wemm bl = l; 2244c2aa98e2SPeter Wemm } 224506f25ae9SGregory Neil Shapiro (void) strlcpy(bp, s, l); 2246c2aa98e2SPeter Wemm for (p = bp; (p = strchr(p, '\n')) != NULL; ) 2247c2aa98e2SPeter Wemm *p++ = ' '; 2248c2aa98e2SPeter Wemm 2249c2aa98e2SPeter Wemm if (logattacks) 2250c2aa98e2SPeter Wemm { 2251c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 2252c2aa98e2SPeter Wemm "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 2253c2aa98e2SPeter Wemm RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 2254c2aa98e2SPeter Wemm shortenstring(bp, MAXSHORTSTR)); 2255c2aa98e2SPeter Wemm } 2256c2aa98e2SPeter Wemm 2257c2aa98e2SPeter Wemm return bp; 2258c2aa98e2SPeter Wemm } 2259c2aa98e2SPeter Wemm /* 2260c2aa98e2SPeter Wemm ** PATH_IS_DIR -- check to see if file exists and is a directory. 2261c2aa98e2SPeter Wemm ** 2262c2aa98e2SPeter Wemm ** There are some additional checks for security violations in 2263c2aa98e2SPeter Wemm ** here. This routine is intended to be used for the host status 2264c2aa98e2SPeter Wemm ** support. 2265c2aa98e2SPeter Wemm ** 2266c2aa98e2SPeter Wemm ** Parameters: 2267c2aa98e2SPeter Wemm ** pathname -- pathname to check for directory-ness. 2268c2aa98e2SPeter Wemm ** createflag -- if set, create directory if needed. 2269c2aa98e2SPeter Wemm ** 2270c2aa98e2SPeter Wemm ** Returns: 2271c2aa98e2SPeter Wemm ** TRUE -- if the indicated pathname is a directory 2272c2aa98e2SPeter Wemm ** FALSE -- otherwise 2273c2aa98e2SPeter Wemm */ 2274c2aa98e2SPeter Wemm 2275c2aa98e2SPeter Wemm int 2276c2aa98e2SPeter Wemm path_is_dir(pathname, createflag) 2277c2aa98e2SPeter Wemm char *pathname; 2278c2aa98e2SPeter Wemm bool createflag; 2279c2aa98e2SPeter Wemm { 2280c2aa98e2SPeter Wemm struct stat statbuf; 2281c2aa98e2SPeter Wemm 2282c2aa98e2SPeter Wemm #if HASLSTAT 2283c2aa98e2SPeter Wemm if (lstat(pathname, &statbuf) < 0) 228406f25ae9SGregory Neil Shapiro #else /* HASLSTAT */ 2285c2aa98e2SPeter Wemm if (stat(pathname, &statbuf) < 0) 228606f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */ 2287c2aa98e2SPeter Wemm { 2288c2aa98e2SPeter Wemm if (errno != ENOENT || !createflag) 2289c2aa98e2SPeter Wemm return FALSE; 2290c2aa98e2SPeter Wemm if (mkdir(pathname, 0755) < 0) 2291c2aa98e2SPeter Wemm return FALSE; 2292c2aa98e2SPeter Wemm return TRUE; 2293c2aa98e2SPeter Wemm } 2294c2aa98e2SPeter Wemm if (!S_ISDIR(statbuf.st_mode)) 2295c2aa98e2SPeter Wemm { 2296c2aa98e2SPeter Wemm errno = ENOTDIR; 2297c2aa98e2SPeter Wemm return FALSE; 2298c2aa98e2SPeter Wemm } 2299c2aa98e2SPeter Wemm 2300c2aa98e2SPeter Wemm /* security: don't allow writable directories */ 2301c2aa98e2SPeter Wemm if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 2302c2aa98e2SPeter Wemm { 2303c2aa98e2SPeter Wemm errno = EACCES; 2304c2aa98e2SPeter Wemm return FALSE; 2305c2aa98e2SPeter Wemm } 2306c2aa98e2SPeter Wemm 2307c2aa98e2SPeter Wemm return TRUE; 2308c2aa98e2SPeter Wemm } 2309c2aa98e2SPeter Wemm /* 2310c2aa98e2SPeter Wemm ** PROC_LIST_ADD -- add process id to list of our children 2311c2aa98e2SPeter Wemm ** 2312c2aa98e2SPeter Wemm ** Parameters: 2313c2aa98e2SPeter Wemm ** pid -- pid to add to list. 231406f25ae9SGregory Neil Shapiro ** task -- task of pid. 231506f25ae9SGregory Neil Shapiro ** type -- type of process. 2316c2aa98e2SPeter Wemm ** 2317c2aa98e2SPeter Wemm ** Returns: 2318c2aa98e2SPeter Wemm ** none 2319c2aa98e2SPeter Wemm */ 2320c2aa98e2SPeter Wemm 23218774250cSGregory Neil Shapiro static struct procs *volatile ProcListVec = NULL; 2322c2aa98e2SPeter Wemm static int ProcListSize = 0; 2323c2aa98e2SPeter Wemm 2324c2aa98e2SPeter Wemm void 232506f25ae9SGregory Neil Shapiro proc_list_add(pid, task, type) 2326c2aa98e2SPeter Wemm pid_t pid; 2327065a643dSPeter Wemm char *task; 232806f25ae9SGregory Neil Shapiro int type; 2329c2aa98e2SPeter Wemm { 2330c2aa98e2SPeter Wemm int i; 2331c2aa98e2SPeter Wemm 2332c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2333c2aa98e2SPeter Wemm { 2334065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2335c2aa98e2SPeter Wemm break; 2336c2aa98e2SPeter Wemm } 2337c2aa98e2SPeter Wemm if (i >= ProcListSize) 2338c2aa98e2SPeter Wemm { 2339c2aa98e2SPeter Wemm /* probe the existing vector to avoid growing infinitely */ 2340c2aa98e2SPeter Wemm proc_list_probe(); 2341c2aa98e2SPeter Wemm 2342c2aa98e2SPeter Wemm /* now scan again */ 2343c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2344c2aa98e2SPeter Wemm { 2345065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2346c2aa98e2SPeter Wemm break; 2347c2aa98e2SPeter Wemm } 2348c2aa98e2SPeter Wemm } 2349c2aa98e2SPeter Wemm if (i >= ProcListSize) 2350c2aa98e2SPeter Wemm { 2351c2aa98e2SPeter Wemm /* grow process list */ 2352065a643dSPeter Wemm struct procs *npv; 2353c2aa98e2SPeter Wemm 235406f25ae9SGregory Neil Shapiro npv = (struct procs *) xalloc((sizeof *npv) * 235506f25ae9SGregory Neil Shapiro (ProcListSize + PROC_LIST_SEG)); 2356c2aa98e2SPeter Wemm if (ProcListSize > 0) 2357c2aa98e2SPeter Wemm { 235806f25ae9SGregory Neil Shapiro memmove(npv, ProcListVec, 235906f25ae9SGregory Neil Shapiro ProcListSize * sizeof (struct procs)); 23608774250cSGregory Neil Shapiro sm_free(ProcListVec); 2361c2aa98e2SPeter Wemm } 2362c2aa98e2SPeter Wemm for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 2363065a643dSPeter Wemm { 2364065a643dSPeter Wemm npv[i].proc_pid = NO_PID; 2365065a643dSPeter Wemm npv[i].proc_task = NULL; 236606f25ae9SGregory Neil Shapiro npv[i].proc_type = PROC_NONE; 2367065a643dSPeter Wemm } 2368c2aa98e2SPeter Wemm i = ProcListSize; 2369c2aa98e2SPeter Wemm ProcListSize += PROC_LIST_SEG; 2370c2aa98e2SPeter Wemm ProcListVec = npv; 2371c2aa98e2SPeter Wemm } 2372065a643dSPeter Wemm ProcListVec[i].proc_pid = pid; 237306f25ae9SGregory Neil Shapiro if (ProcListVec[i].proc_task != NULL) 23748774250cSGregory Neil Shapiro sm_free(ProcListVec[i].proc_task); 2375065a643dSPeter Wemm ProcListVec[i].proc_task = newstr(task); 237606f25ae9SGregory Neil Shapiro ProcListVec[i].proc_type = type; 2377065a643dSPeter Wemm 2378065a643dSPeter Wemm /* if process adding itself, it's not a child */ 2379065a643dSPeter Wemm if (pid != getpid()) 2380c2aa98e2SPeter Wemm CurChildren++; 2381c2aa98e2SPeter Wemm } 2382c2aa98e2SPeter Wemm /* 2383065a643dSPeter Wemm ** PROC_LIST_SET -- set pid task in process list 2384065a643dSPeter Wemm ** 2385065a643dSPeter Wemm ** Parameters: 2386065a643dSPeter Wemm ** pid -- pid to set 2387065a643dSPeter Wemm ** task -- task of pid 2388065a643dSPeter Wemm ** 2389065a643dSPeter Wemm ** Returns: 2390065a643dSPeter Wemm ** none. 2391065a643dSPeter Wemm */ 2392065a643dSPeter Wemm 2393065a643dSPeter Wemm void 2394065a643dSPeter Wemm proc_list_set(pid, task) 2395065a643dSPeter Wemm pid_t pid; 2396065a643dSPeter Wemm char *task; 2397065a643dSPeter Wemm { 2398065a643dSPeter Wemm int i; 2399065a643dSPeter Wemm 2400065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2401065a643dSPeter Wemm { 2402065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2403065a643dSPeter Wemm { 2404065a643dSPeter Wemm if (ProcListVec[i].proc_task != NULL) 24058774250cSGregory Neil Shapiro sm_free(ProcListVec[i].proc_task); 2406065a643dSPeter Wemm ProcListVec[i].proc_task = newstr(task); 2407065a643dSPeter Wemm break; 2408065a643dSPeter Wemm } 2409065a643dSPeter Wemm } 2410065a643dSPeter Wemm } 2411065a643dSPeter Wemm /* 2412c2aa98e2SPeter Wemm ** PROC_LIST_DROP -- drop pid from process list 2413c2aa98e2SPeter Wemm ** 2414c2aa98e2SPeter Wemm ** Parameters: 2415c2aa98e2SPeter Wemm ** pid -- pid to drop 2416c2aa98e2SPeter Wemm ** 2417c2aa98e2SPeter Wemm ** Returns: 241806f25ae9SGregory Neil Shapiro ** type of process 24198774250cSGregory Neil Shapiro ** 24208774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 24218774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 24228774250cSGregory Neil Shapiro ** DOING. 2423c2aa98e2SPeter Wemm */ 2424c2aa98e2SPeter Wemm 242506f25ae9SGregory Neil Shapiro int 2426c2aa98e2SPeter Wemm proc_list_drop(pid) 2427c2aa98e2SPeter Wemm pid_t pid; 2428c2aa98e2SPeter Wemm { 2429c2aa98e2SPeter Wemm int i; 243006f25ae9SGregory Neil Shapiro int type = PROC_NONE; 2431c2aa98e2SPeter Wemm 2432c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2433c2aa98e2SPeter Wemm { 2434065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2435c2aa98e2SPeter Wemm { 2436065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 243706f25ae9SGregory Neil Shapiro type = ProcListVec[i].proc_type; 2438c2aa98e2SPeter Wemm break; 2439c2aa98e2SPeter Wemm } 2440c2aa98e2SPeter Wemm } 2441c2aa98e2SPeter Wemm if (CurChildren > 0) 2442c2aa98e2SPeter Wemm CurChildren--; 244306f25ae9SGregory Neil Shapiro 244406f25ae9SGregory Neil Shapiro 244506f25ae9SGregory Neil Shapiro return type; 2446c2aa98e2SPeter Wemm } 2447c2aa98e2SPeter Wemm /* 2448c2aa98e2SPeter Wemm ** PROC_LIST_CLEAR -- clear the process list 2449c2aa98e2SPeter Wemm ** 2450c2aa98e2SPeter Wemm ** Parameters: 2451c2aa98e2SPeter Wemm ** none. 2452c2aa98e2SPeter Wemm ** 2453c2aa98e2SPeter Wemm ** Returns: 2454c2aa98e2SPeter Wemm ** none. 2455c2aa98e2SPeter Wemm */ 2456c2aa98e2SPeter Wemm 2457c2aa98e2SPeter Wemm void 2458c2aa98e2SPeter Wemm proc_list_clear() 2459c2aa98e2SPeter Wemm { 2460c2aa98e2SPeter Wemm int i; 2461c2aa98e2SPeter Wemm 2462065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2463065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2464065a643dSPeter Wemm { 2465065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2466065a643dSPeter Wemm } 2467c2aa98e2SPeter Wemm CurChildren = 0; 2468c2aa98e2SPeter Wemm } 2469c2aa98e2SPeter Wemm /* 2470c2aa98e2SPeter Wemm ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 2471c2aa98e2SPeter Wemm ** 2472c2aa98e2SPeter Wemm ** Parameters: 2473c2aa98e2SPeter Wemm ** none 2474c2aa98e2SPeter Wemm ** 2475c2aa98e2SPeter Wemm ** Returns: 2476c2aa98e2SPeter Wemm ** none 2477c2aa98e2SPeter Wemm */ 2478c2aa98e2SPeter Wemm 2479c2aa98e2SPeter Wemm void 2480c2aa98e2SPeter Wemm proc_list_probe() 2481c2aa98e2SPeter Wemm { 2482c2aa98e2SPeter Wemm int i; 2483c2aa98e2SPeter Wemm 2484065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2485065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2486c2aa98e2SPeter Wemm { 2487065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2488c2aa98e2SPeter Wemm continue; 2489065a643dSPeter Wemm if (kill(ProcListVec[i].proc_pid, 0) < 0) 2490c2aa98e2SPeter Wemm { 2491c2aa98e2SPeter Wemm if (LogLevel > 3) 2492c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 2493c2aa98e2SPeter Wemm "proc_list_probe: lost pid %d", 2494065a643dSPeter Wemm (int) ProcListVec[i].proc_pid); 2495065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2496c2aa98e2SPeter Wemm CurChildren--; 2497c2aa98e2SPeter Wemm } 2498c2aa98e2SPeter Wemm } 2499c2aa98e2SPeter Wemm if (CurChildren < 0) 2500c2aa98e2SPeter Wemm CurChildren = 0; 2501c2aa98e2SPeter Wemm } 2502c2aa98e2SPeter Wemm /* 2503065a643dSPeter Wemm ** PROC_LIST_DISPLAY -- display the process list 2504065a643dSPeter Wemm ** 2505065a643dSPeter Wemm ** Parameters: 2506065a643dSPeter Wemm ** out -- output file pointer 2507065a643dSPeter Wemm ** 2508065a643dSPeter Wemm ** Returns: 2509065a643dSPeter Wemm ** none. 2510065a643dSPeter Wemm */ 2511065a643dSPeter Wemm 2512065a643dSPeter Wemm void 2513065a643dSPeter Wemm proc_list_display(out) 2514065a643dSPeter Wemm FILE *out; 2515065a643dSPeter Wemm { 2516065a643dSPeter Wemm int i; 2517065a643dSPeter Wemm 2518065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2519065a643dSPeter Wemm { 2520065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2521065a643dSPeter Wemm continue; 2522065a643dSPeter Wemm 2523065a643dSPeter Wemm fprintf(out, "%d %s%s\n", (int) ProcListVec[i].proc_pid, 2524065a643dSPeter Wemm ProcListVec[i].proc_task != NULL ? 2525065a643dSPeter Wemm ProcListVec[i].proc_task : "(unknown)", 2526065a643dSPeter Wemm (OpMode == MD_SMTP || 2527065a643dSPeter Wemm OpMode == MD_DAEMON || 2528065a643dSPeter Wemm OpMode == MD_ARPAFTP) ? "\r" : ""); 2529065a643dSPeter Wemm } 2530065a643dSPeter Wemm } 2531065a643dSPeter Wemm /* 253213058a91SGregory Neil Shapiro ** SAFEFOPEN -- do a file open with extra checking 253313058a91SGregory Neil Shapiro ** 253413058a91SGregory Neil Shapiro ** Parameters: 253513058a91SGregory Neil Shapiro ** fn -- the file name to open. 253613058a91SGregory Neil Shapiro ** omode -- the open-style mode flags. 253713058a91SGregory Neil Shapiro ** cmode -- the create-style mode flags. 253813058a91SGregory Neil Shapiro ** sff -- safefile flags. 253913058a91SGregory Neil Shapiro ** 254013058a91SGregory Neil Shapiro ** Returns: 254113058a91SGregory Neil Shapiro ** Same as fopen. 254213058a91SGregory Neil Shapiro */ 254313058a91SGregory Neil Shapiro 254413058a91SGregory Neil Shapiro FILE * 254513058a91SGregory Neil Shapiro safefopen(fn, omode, cmode, sff) 254613058a91SGregory Neil Shapiro char *fn; 254713058a91SGregory Neil Shapiro int omode; 254813058a91SGregory Neil Shapiro int cmode; 254913058a91SGregory Neil Shapiro long sff; 255013058a91SGregory Neil Shapiro { 255113058a91SGregory Neil Shapiro int fd; 255213058a91SGregory Neil Shapiro int save_errno; 255313058a91SGregory Neil Shapiro FILE *fp; 255413058a91SGregory Neil Shapiro char *fmode; 255513058a91SGregory Neil Shapiro 255613058a91SGregory Neil Shapiro switch (omode & O_ACCMODE) 255713058a91SGregory Neil Shapiro { 255813058a91SGregory Neil Shapiro case O_RDONLY: 255913058a91SGregory Neil Shapiro fmode = "r"; 256013058a91SGregory Neil Shapiro break; 256113058a91SGregory Neil Shapiro 256213058a91SGregory Neil Shapiro case O_WRONLY: 256313058a91SGregory Neil Shapiro if (bitset(O_APPEND, omode)) 256413058a91SGregory Neil Shapiro fmode = "a"; 256513058a91SGregory Neil Shapiro else 256613058a91SGregory Neil Shapiro fmode = "w"; 256713058a91SGregory Neil Shapiro break; 256813058a91SGregory Neil Shapiro 256913058a91SGregory Neil Shapiro case O_RDWR: 257013058a91SGregory Neil Shapiro if (bitset(O_TRUNC, omode)) 257113058a91SGregory Neil Shapiro fmode = "w+"; 257213058a91SGregory Neil Shapiro else if (bitset(O_APPEND, omode)) 257313058a91SGregory Neil Shapiro fmode = "a+"; 257413058a91SGregory Neil Shapiro else 257513058a91SGregory Neil Shapiro fmode = "r+"; 257613058a91SGregory Neil Shapiro break; 257713058a91SGregory Neil Shapiro 257813058a91SGregory Neil Shapiro default: 257913058a91SGregory Neil Shapiro syserr("554 5.3.5 safefopen: unknown omode %o", omode); 258013058a91SGregory Neil Shapiro fmode = "x"; 258113058a91SGregory Neil Shapiro } 258213058a91SGregory Neil Shapiro fd = safeopen(fn, omode, cmode, sff); 258313058a91SGregory Neil Shapiro if (fd < 0) 258413058a91SGregory Neil Shapiro { 258513058a91SGregory Neil Shapiro save_errno = errno; 258613058a91SGregory Neil Shapiro if (tTd(44, 10)) 258713058a91SGregory Neil Shapiro dprintf("safefopen: safeopen failed: %s\n", 258813058a91SGregory Neil Shapiro errstring(errno)); 258913058a91SGregory Neil Shapiro errno = save_errno; 259013058a91SGregory Neil Shapiro return NULL; 259113058a91SGregory Neil Shapiro } 259213058a91SGregory Neil Shapiro fp = fdopen(fd, fmode); 259313058a91SGregory Neil Shapiro if (fp != NULL) 259413058a91SGregory Neil Shapiro return fp; 259513058a91SGregory Neil Shapiro 259613058a91SGregory Neil Shapiro save_errno = errno; 259713058a91SGregory Neil Shapiro if (tTd(44, 10)) 259813058a91SGregory Neil Shapiro { 259913058a91SGregory Neil Shapiro dprintf("safefopen: fdopen(%s, %s) failed: omode=%x, sff=%lx, err=%s\n", 260013058a91SGregory Neil Shapiro fn, fmode, omode, sff, errstring(errno)); 260113058a91SGregory Neil Shapiro } 260213058a91SGregory Neil Shapiro (void) close(fd); 260313058a91SGregory Neil Shapiro errno = save_errno; 260413058a91SGregory Neil Shapiro return NULL; 260513058a91SGregory Neil Shapiro } 260613058a91SGregory Neil Shapiro /* 2607c2aa98e2SPeter Wemm ** SM_STRCASECMP -- 8-bit clean version of strcasecmp 2608c2aa98e2SPeter Wemm ** 2609c2aa98e2SPeter Wemm ** Thank you, vendors, for making this all necessary. 2610c2aa98e2SPeter Wemm */ 2611c2aa98e2SPeter Wemm 2612c2aa98e2SPeter Wemm /* 2613c2aa98e2SPeter Wemm * Copyright (c) 1987, 1993 2614c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 2615c2aa98e2SPeter Wemm * 2616c2aa98e2SPeter Wemm * Redistribution and use in source and binary forms, with or without 2617c2aa98e2SPeter Wemm * modification, are permitted provided that the following conditions 2618c2aa98e2SPeter Wemm * are met: 2619c2aa98e2SPeter Wemm * 1. Redistributions of source code must retain the above copyright 2620c2aa98e2SPeter Wemm * notice, this list of conditions and the following disclaimer. 2621c2aa98e2SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 2622c2aa98e2SPeter Wemm * notice, this list of conditions and the following disclaimer in the 2623c2aa98e2SPeter Wemm * documentation and/or other materials provided with the distribution. 2624c2aa98e2SPeter Wemm * 3. All advertising materials mentioning features or use of this software 2625c2aa98e2SPeter Wemm * must display the following acknowledgement: 2626c2aa98e2SPeter Wemm * This product includes software developed by the University of 2627c2aa98e2SPeter Wemm * California, Berkeley and its contributors. 2628c2aa98e2SPeter Wemm * 4. Neither the name of the University nor the names of its contributors 2629c2aa98e2SPeter Wemm * may be used to endorse or promote products derived from this software 2630c2aa98e2SPeter Wemm * without specific prior written permission. 2631c2aa98e2SPeter Wemm * 2632c2aa98e2SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2633c2aa98e2SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2634c2aa98e2SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2635c2aa98e2SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2636c2aa98e2SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2637c2aa98e2SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2638c2aa98e2SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2639c2aa98e2SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2640c2aa98e2SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2641c2aa98e2SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2642c2aa98e2SPeter Wemm * SUCH DAMAGE. 2643c2aa98e2SPeter Wemm */ 2644c2aa98e2SPeter Wemm 2645c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint) 2646c2aa98e2SPeter Wemm static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; 264706f25ae9SGregory Neil Shapiro #endif /* defined(LIBC_SCCS) && !defined(lint) */ 2648c2aa98e2SPeter Wemm 2649c2aa98e2SPeter Wemm /* 2650c2aa98e2SPeter Wemm * This array is designed for mapping upper and lower case letter 2651c2aa98e2SPeter Wemm * together for a case independent comparison. The mappings are 2652c2aa98e2SPeter Wemm * based upon ascii character sequences. 2653c2aa98e2SPeter Wemm */ 2654c2aa98e2SPeter Wemm static const u_char charmap[] = { 2655c2aa98e2SPeter Wemm 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 2656c2aa98e2SPeter Wemm 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 2657c2aa98e2SPeter Wemm 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 2658c2aa98e2SPeter Wemm 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 2659c2aa98e2SPeter Wemm 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 2660c2aa98e2SPeter Wemm 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 2661c2aa98e2SPeter Wemm 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 2662c2aa98e2SPeter Wemm 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 2663c2aa98e2SPeter Wemm 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 2664c2aa98e2SPeter Wemm 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 2665c2aa98e2SPeter Wemm 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 2666c2aa98e2SPeter Wemm 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, 2667c2aa98e2SPeter Wemm 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 2668c2aa98e2SPeter Wemm 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 2669c2aa98e2SPeter Wemm 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 2670c2aa98e2SPeter Wemm 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, 2671c2aa98e2SPeter Wemm 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 2672c2aa98e2SPeter Wemm 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 2673c2aa98e2SPeter Wemm 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 2674c2aa98e2SPeter Wemm 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 2675c2aa98e2SPeter Wemm 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 2676c2aa98e2SPeter Wemm 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 2677c2aa98e2SPeter Wemm 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 2678c2aa98e2SPeter Wemm 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 2679c2aa98e2SPeter Wemm 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 2680c2aa98e2SPeter Wemm 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 2681c2aa98e2SPeter Wemm 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 2682c2aa98e2SPeter Wemm 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 2683c2aa98e2SPeter Wemm 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 2684c2aa98e2SPeter Wemm 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 2685c2aa98e2SPeter Wemm 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 2686c2aa98e2SPeter Wemm 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, 2687c2aa98e2SPeter Wemm }; 2688c2aa98e2SPeter Wemm 2689c2aa98e2SPeter Wemm int 2690c2aa98e2SPeter Wemm sm_strcasecmp(s1, s2) 2691c2aa98e2SPeter Wemm const char *s1, *s2; 2692c2aa98e2SPeter Wemm { 2693c2aa98e2SPeter Wemm register const u_char *cm = charmap, 2694c2aa98e2SPeter Wemm *us1 = (const u_char *)s1, 2695c2aa98e2SPeter Wemm *us2 = (const u_char *)s2; 2696c2aa98e2SPeter Wemm 2697c2aa98e2SPeter Wemm while (cm[*us1] == cm[*us2++]) 2698c2aa98e2SPeter Wemm if (*us1++ == '\0') 269906f25ae9SGregory Neil Shapiro return 0; 2700c2aa98e2SPeter Wemm return (cm[*us1] - cm[*--us2]); 2701c2aa98e2SPeter Wemm } 2702c2aa98e2SPeter Wemm 2703c2aa98e2SPeter Wemm int 2704c2aa98e2SPeter Wemm sm_strncasecmp(s1, s2, n) 2705c2aa98e2SPeter Wemm const char *s1, *s2; 2706c2aa98e2SPeter Wemm register size_t n; 2707c2aa98e2SPeter Wemm { 2708c2aa98e2SPeter Wemm if (n != 0) { 2709c2aa98e2SPeter Wemm register const u_char *cm = charmap, 2710c2aa98e2SPeter Wemm *us1 = (const u_char *)s1, 2711c2aa98e2SPeter Wemm *us2 = (const u_char *)s2; 2712c2aa98e2SPeter Wemm 2713c2aa98e2SPeter Wemm do { 2714c2aa98e2SPeter Wemm if (cm[*us1] != cm[*us2++]) 2715c2aa98e2SPeter Wemm return (cm[*us1] - cm[*--us2]); 2716c2aa98e2SPeter Wemm if (*us1++ == '\0') 2717c2aa98e2SPeter Wemm break; 2718c2aa98e2SPeter Wemm } while (--n != 0); 2719c2aa98e2SPeter Wemm } 272006f25ae9SGregory Neil Shapiro return 0; 2721c2aa98e2SPeter Wemm } 2722