1c2aa98e2SPeter Wemm /* 206f25ae9SGregory Neil Shapiro * Copyright (c) 1998-2000 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 1506f25ae9SGregory Neil Shapiro static char id[] = "@(#)$Id: util.c,v 8.225.2.1.2.8 2000/07/03 18:28:56 geir 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 */ 212065a643dSPeter Wemm slen = strlen(string); 213065a643dSPeter Wemm if (length == 0 || slen < length) 214065a643dSPeter Wemm length = slen; 215065a643dSPeter Wemm 216065a643dSPeter Wemm while (*ptr != '\0') 217065a643dSPeter Wemm { 218065a643dSPeter Wemm if (backslash) 219065a643dSPeter Wemm { 220065a643dSPeter Wemm backslash = FALSE; 221065a643dSPeter Wemm goto increment; 222065a643dSPeter Wemm } 223065a643dSPeter Wemm 224065a643dSPeter Wemm if (*ptr == '\\') 225065a643dSPeter Wemm backslash = TRUE; 226065a643dSPeter Wemm else if (*ptr == '(') 227065a643dSPeter Wemm { 228065a643dSPeter Wemm if (!quoted) 229065a643dSPeter Wemm parencount++; 230065a643dSPeter Wemm } 231065a643dSPeter Wemm else if (*ptr == ')') 232065a643dSPeter Wemm { 233065a643dSPeter Wemm if (--parencount < 0) 234065a643dSPeter Wemm parencount = 0; 235065a643dSPeter Wemm } 236065a643dSPeter Wemm 237065a643dSPeter Wemm /* Inside a comment, quotes don't matter */ 238065a643dSPeter Wemm if (parencount <= 0 && *ptr == '"') 239065a643dSPeter Wemm quoted = !quoted; 240065a643dSPeter Wemm 241065a643dSPeter Wemm increment: 242065a643dSPeter Wemm /* Check for sufficient space for next character */ 24306f25ae9SGregory Neil Shapiro if (length - (ptr - string) <= (size_t) ((backslash ? 1 : 0) + 244065a643dSPeter Wemm parencount + 245065a643dSPeter Wemm (quoted ? 1 : 0))) 246065a643dSPeter Wemm { 247065a643dSPeter Wemm /* Not enough, backtrack */ 248065a643dSPeter Wemm if (*ptr == '\\') 249065a643dSPeter Wemm backslash = FALSE; 250065a643dSPeter Wemm else if (*ptr == '(' && !quoted) 251065a643dSPeter Wemm parencount--; 252065a643dSPeter Wemm else if (*ptr == '"' && parencount == 0) 253065a643dSPeter Wemm quoted = FALSE; 254065a643dSPeter Wemm break; 255065a643dSPeter Wemm } 256065a643dSPeter Wemm ptr++; 257065a643dSPeter Wemm } 258065a643dSPeter Wemm 259065a643dSPeter Wemm /* Rebalance */ 260065a643dSPeter Wemm while (parencount-- > 0) 261065a643dSPeter Wemm { 262065a643dSPeter Wemm if (*ptr != ')') 263065a643dSPeter Wemm { 264065a643dSPeter Wemm modified = TRUE; 265065a643dSPeter Wemm *ptr = ')'; 266065a643dSPeter Wemm } 267065a643dSPeter Wemm ptr++; 268065a643dSPeter Wemm } 269065a643dSPeter Wemm if (quoted) 270065a643dSPeter Wemm { 271065a643dSPeter Wemm if (*ptr != '"') 272065a643dSPeter Wemm { 273065a643dSPeter Wemm modified = TRUE; 274065a643dSPeter Wemm *ptr = '"'; 275065a643dSPeter Wemm } 276065a643dSPeter Wemm ptr++; 277065a643dSPeter Wemm } 278065a643dSPeter Wemm if (*ptr != '\0') 279065a643dSPeter Wemm { 280065a643dSPeter Wemm modified = TRUE; 281065a643dSPeter Wemm *ptr = '\0'; 282065a643dSPeter Wemm } 283065a643dSPeter Wemm return modified; 284065a643dSPeter Wemm } 285065a643dSPeter Wemm /* 286065a643dSPeter Wemm ** FIND_CHARACTER -- find an unquoted character in an RFC822 string 287065a643dSPeter Wemm ** 288065a643dSPeter Wemm ** Find an unquoted, non-commented character in an RFC822 289065a643dSPeter Wemm ** string and return a pointer to its location in the 290065a643dSPeter Wemm ** string. 291065a643dSPeter Wemm ** 292065a643dSPeter Wemm ** Parameters: 293065a643dSPeter Wemm ** string -- the string to search 294065a643dSPeter Wemm ** character -- the character to find 295065a643dSPeter Wemm ** 296065a643dSPeter Wemm ** Returns: 297065a643dSPeter Wemm ** pointer to the character, or 298065a643dSPeter Wemm ** a pointer to the end of the line if character is not found 299065a643dSPeter Wemm */ 300065a643dSPeter Wemm 301065a643dSPeter Wemm char * 302065a643dSPeter Wemm find_character(string, character) 303065a643dSPeter Wemm char *string; 30406f25ae9SGregory Neil Shapiro int character; 305065a643dSPeter Wemm { 306065a643dSPeter Wemm bool backslash = FALSE; 307065a643dSPeter Wemm bool quoted = FALSE; 308065a643dSPeter Wemm int parencount = 0; 309065a643dSPeter Wemm 310065a643dSPeter Wemm while (string != NULL && *string != '\0') 311065a643dSPeter Wemm { 312065a643dSPeter Wemm if (backslash) 313065a643dSPeter Wemm { 314065a643dSPeter Wemm backslash = FALSE; 315065a643dSPeter Wemm if (!quoted && character == '\\' && *string == '\\') 316065a643dSPeter Wemm break; 317065a643dSPeter Wemm string++; 318065a643dSPeter Wemm continue; 319065a643dSPeter Wemm } 320065a643dSPeter Wemm switch (*string) 321065a643dSPeter Wemm { 322065a643dSPeter Wemm case '\\': 323065a643dSPeter Wemm backslash = TRUE; 324065a643dSPeter Wemm break; 325065a643dSPeter Wemm 326065a643dSPeter Wemm case '(': 327065a643dSPeter Wemm if (!quoted) 328065a643dSPeter Wemm parencount++; 329065a643dSPeter Wemm break; 330065a643dSPeter Wemm 331065a643dSPeter Wemm case ')': 332065a643dSPeter Wemm if (--parencount < 0) 333065a643dSPeter Wemm parencount = 0; 334065a643dSPeter Wemm break; 335065a643dSPeter Wemm } 336065a643dSPeter Wemm 337065a643dSPeter Wemm /* Inside a comment, nothing matters */ 338065a643dSPeter Wemm if (parencount > 0) 339065a643dSPeter Wemm { 340065a643dSPeter Wemm string++; 341065a643dSPeter Wemm continue; 342065a643dSPeter Wemm } 343065a643dSPeter Wemm 344065a643dSPeter Wemm if (*string == '"') 345065a643dSPeter Wemm quoted = !quoted; 346065a643dSPeter Wemm else if (*string == character && !quoted) 347065a643dSPeter Wemm break; 348065a643dSPeter Wemm string++; 349065a643dSPeter Wemm } 350065a643dSPeter Wemm 351065a643dSPeter Wemm /* Return pointer to the character */ 352065a643dSPeter Wemm return string; 353065a643dSPeter Wemm } 354065a643dSPeter Wemm /* 355c2aa98e2SPeter Wemm ** XALLOC -- Allocate memory and bitch wildly on failure. 356c2aa98e2SPeter Wemm ** 357c2aa98e2SPeter Wemm ** THIS IS A CLUDGE. This should be made to give a proper 358c2aa98e2SPeter Wemm ** error -- but after all, what can we do? 359c2aa98e2SPeter Wemm ** 360c2aa98e2SPeter Wemm ** Parameters: 361c2aa98e2SPeter Wemm ** sz -- size of area to allocate. 362c2aa98e2SPeter Wemm ** 363c2aa98e2SPeter Wemm ** Returns: 364c2aa98e2SPeter Wemm ** pointer to data region. 365c2aa98e2SPeter Wemm ** 366c2aa98e2SPeter Wemm ** Side Effects: 367c2aa98e2SPeter Wemm ** Memory is allocated. 368c2aa98e2SPeter Wemm */ 369c2aa98e2SPeter Wemm 370c2aa98e2SPeter Wemm char * 371c2aa98e2SPeter Wemm xalloc(sz) 372c2aa98e2SPeter Wemm register int sz; 373c2aa98e2SPeter Wemm { 374c2aa98e2SPeter Wemm register char *p; 375c2aa98e2SPeter Wemm 376c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 377c2aa98e2SPeter Wemm if (sz <= 0) 378c2aa98e2SPeter Wemm sz = 1; 379c2aa98e2SPeter Wemm 380c2aa98e2SPeter Wemm p = malloc((unsigned) sz); 381c2aa98e2SPeter Wemm if (p == NULL) 382c2aa98e2SPeter Wemm { 383c2aa98e2SPeter Wemm syserr("!Out of memory!!"); 384c2aa98e2SPeter Wemm /* exit(EX_UNAVAILABLE); */ 385c2aa98e2SPeter Wemm } 38606f25ae9SGregory Neil Shapiro return p; 387c2aa98e2SPeter Wemm } 388c2aa98e2SPeter Wemm /* 389c2aa98e2SPeter Wemm ** COPYPLIST -- copy list of pointers. 390c2aa98e2SPeter Wemm ** 391c2aa98e2SPeter Wemm ** This routine is the equivalent of newstr for lists of 392c2aa98e2SPeter Wemm ** pointers. 393c2aa98e2SPeter Wemm ** 394c2aa98e2SPeter Wemm ** Parameters: 395c2aa98e2SPeter Wemm ** list -- list of pointers to copy. 396c2aa98e2SPeter Wemm ** Must be NULL terminated. 397c2aa98e2SPeter Wemm ** copycont -- if TRUE, copy the contents of the vector 398c2aa98e2SPeter Wemm ** (which must be a string) also. 399c2aa98e2SPeter Wemm ** 400c2aa98e2SPeter Wemm ** Returns: 401c2aa98e2SPeter Wemm ** a copy of 'list'. 402c2aa98e2SPeter Wemm ** 403c2aa98e2SPeter Wemm ** Side Effects: 404c2aa98e2SPeter Wemm ** none. 405c2aa98e2SPeter Wemm */ 406c2aa98e2SPeter Wemm 407c2aa98e2SPeter Wemm char ** 408c2aa98e2SPeter Wemm copyplist(list, copycont) 409c2aa98e2SPeter Wemm char **list; 410c2aa98e2SPeter Wemm bool copycont; 411c2aa98e2SPeter Wemm { 412c2aa98e2SPeter Wemm register char **vp; 413c2aa98e2SPeter Wemm register char **newvp; 414c2aa98e2SPeter Wemm 415c2aa98e2SPeter Wemm for (vp = list; *vp != NULL; vp++) 416c2aa98e2SPeter Wemm continue; 417c2aa98e2SPeter Wemm 418c2aa98e2SPeter Wemm vp++; 419c2aa98e2SPeter Wemm 420c2aa98e2SPeter Wemm newvp = (char **) xalloc((int) (vp - list) * sizeof *vp); 42106f25ae9SGregory Neil Shapiro memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); 422c2aa98e2SPeter Wemm 423c2aa98e2SPeter Wemm if (copycont) 424c2aa98e2SPeter Wemm { 425c2aa98e2SPeter Wemm for (vp = newvp; *vp != NULL; vp++) 426c2aa98e2SPeter Wemm *vp = newstr(*vp); 427c2aa98e2SPeter Wemm } 428c2aa98e2SPeter Wemm 42906f25ae9SGregory Neil Shapiro return newvp; 430c2aa98e2SPeter Wemm } 431c2aa98e2SPeter Wemm /* 432c2aa98e2SPeter Wemm ** COPYQUEUE -- copy address queue. 433c2aa98e2SPeter Wemm ** 434c2aa98e2SPeter Wemm ** This routine is the equivalent of newstr for address queues 43506f25ae9SGregory Neil Shapiro ** addresses marked as QS_IS_DEAD() aren't copied 436c2aa98e2SPeter Wemm ** 437c2aa98e2SPeter Wemm ** Parameters: 438c2aa98e2SPeter Wemm ** addr -- list of address structures to copy. 439c2aa98e2SPeter Wemm ** 440c2aa98e2SPeter Wemm ** Returns: 441c2aa98e2SPeter Wemm ** a copy of 'addr'. 442c2aa98e2SPeter Wemm ** 443c2aa98e2SPeter Wemm ** Side Effects: 444c2aa98e2SPeter Wemm ** none. 445c2aa98e2SPeter Wemm */ 446c2aa98e2SPeter Wemm 447c2aa98e2SPeter Wemm ADDRESS * 448c2aa98e2SPeter Wemm copyqueue(addr) 449c2aa98e2SPeter Wemm ADDRESS *addr; 450c2aa98e2SPeter Wemm { 451c2aa98e2SPeter Wemm register ADDRESS *newaddr; 452c2aa98e2SPeter Wemm ADDRESS *ret; 453c2aa98e2SPeter Wemm register ADDRESS **tail = &ret; 454c2aa98e2SPeter Wemm 455c2aa98e2SPeter Wemm while (addr != NULL) 456c2aa98e2SPeter Wemm { 45706f25ae9SGregory Neil Shapiro if (!QS_IS_DEAD(addr->q_state)) 458c2aa98e2SPeter Wemm { 45906f25ae9SGregory Neil Shapiro newaddr = (ADDRESS *) xalloc(sizeof *newaddr); 460c2aa98e2SPeter Wemm STRUCTCOPY(*addr, *newaddr); 461c2aa98e2SPeter Wemm *tail = newaddr; 462c2aa98e2SPeter Wemm tail = &newaddr->q_next; 463c2aa98e2SPeter Wemm } 464c2aa98e2SPeter Wemm addr = addr->q_next; 465c2aa98e2SPeter Wemm } 466c2aa98e2SPeter Wemm *tail = NULL; 467c2aa98e2SPeter Wemm 468c2aa98e2SPeter Wemm return ret; 469c2aa98e2SPeter Wemm } 470c2aa98e2SPeter Wemm /* 47106f25ae9SGregory Neil Shapiro ** LOG_SENDMAIL_PID -- record sendmail pid and command line. 47206f25ae9SGregory Neil Shapiro ** 47306f25ae9SGregory Neil Shapiro ** Parameters: 47406f25ae9SGregory Neil Shapiro ** e -- the current envelope. 47506f25ae9SGregory Neil Shapiro ** 47606f25ae9SGregory Neil Shapiro ** Returns: 47706f25ae9SGregory Neil Shapiro ** none. 47806f25ae9SGregory Neil Shapiro ** 47906f25ae9SGregory Neil Shapiro ** Side Effects: 48006f25ae9SGregory Neil Shapiro ** writes pidfile. 48106f25ae9SGregory Neil Shapiro */ 48206f25ae9SGregory Neil Shapiro 48306f25ae9SGregory Neil Shapiro void 48406f25ae9SGregory Neil Shapiro log_sendmail_pid(e) 48506f25ae9SGregory Neil Shapiro ENVELOPE *e; 48606f25ae9SGregory Neil Shapiro { 48706f25ae9SGregory Neil Shapiro long sff; 48806f25ae9SGregory Neil Shapiro FILE *pidf; 48906f25ae9SGregory Neil Shapiro char pidpath[MAXPATHLEN + 1]; 49006f25ae9SGregory Neil Shapiro 49106f25ae9SGregory Neil Shapiro /* write the pid to the log file for posterity */ 49206f25ae9SGregory Neil Shapiro sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 49306f25ae9SGregory Neil Shapiro if (TrustedUid != 0 && RealUid == TrustedUid) 49406f25ae9SGregory Neil Shapiro sff |= SFF_OPENASROOT; 49506f25ae9SGregory Neil Shapiro expand(PidFile, pidpath, sizeof pidpath, e); 49606f25ae9SGregory Neil Shapiro pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, 0644, sff); 49706f25ae9SGregory Neil Shapiro if (pidf == NULL) 49806f25ae9SGregory Neil Shapiro { 49906f25ae9SGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, "unable to write %s", pidpath); 50006f25ae9SGregory Neil Shapiro } 50106f25ae9SGregory Neil Shapiro else 50206f25ae9SGregory Neil Shapiro { 50306f25ae9SGregory Neil Shapiro extern char *CommandLineArgs; 50406f25ae9SGregory Neil Shapiro 50506f25ae9SGregory Neil Shapiro /* write the process id on line 1 */ 50606f25ae9SGregory Neil Shapiro fprintf(pidf, "%ld\n", (long) getpid()); 50706f25ae9SGregory Neil Shapiro 50806f25ae9SGregory Neil Shapiro /* line 2 contains all command line flags */ 50906f25ae9SGregory Neil Shapiro fprintf(pidf, "%s\n", CommandLineArgs); 51006f25ae9SGregory Neil Shapiro 51106f25ae9SGregory Neil Shapiro /* flush and close */ 51206f25ae9SGregory Neil Shapiro (void) fclose(pidf); 51306f25ae9SGregory Neil Shapiro } 51406f25ae9SGregory Neil Shapiro } 51506f25ae9SGregory Neil Shapiro /* 51606f25ae9SGregory Neil Shapiro ** SET_DELIVERY_MODE -- set and record the delivery mode 51706f25ae9SGregory Neil Shapiro ** 51806f25ae9SGregory Neil Shapiro ** Parameters: 51906f25ae9SGregory Neil Shapiro ** mode -- delivery mode 52006f25ae9SGregory Neil Shapiro ** e -- the current envelope. 52106f25ae9SGregory Neil Shapiro ** 52206f25ae9SGregory Neil Shapiro ** Returns: 52306f25ae9SGregory Neil Shapiro ** none. 52406f25ae9SGregory Neil Shapiro ** 52506f25ae9SGregory Neil Shapiro ** Side Effects: 52606f25ae9SGregory Neil Shapiro ** sets $&{deliveryMode} macro 52706f25ae9SGregory Neil Shapiro */ 52806f25ae9SGregory Neil Shapiro 52906f25ae9SGregory Neil Shapiro void 53006f25ae9SGregory Neil Shapiro set_delivery_mode(mode, e) 53106f25ae9SGregory Neil Shapiro int mode; 53206f25ae9SGregory Neil Shapiro ENVELOPE *e; 53306f25ae9SGregory Neil Shapiro { 53406f25ae9SGregory Neil Shapiro char buf[2]; 53506f25ae9SGregory Neil Shapiro 53606f25ae9SGregory Neil Shapiro e->e_sendmode = (char)mode; 53706f25ae9SGregory Neil Shapiro buf[0] = (char)mode; 53806f25ae9SGregory Neil Shapiro buf[1] = '\0'; 53906f25ae9SGregory Neil Shapiro define(macid("{deliveryMode}", NULL), newstr(buf), e); 54006f25ae9SGregory Neil Shapiro } 54106f25ae9SGregory Neil Shapiro /* 542c2aa98e2SPeter Wemm ** PRINTAV -- print argument vector. 543c2aa98e2SPeter Wemm ** 544c2aa98e2SPeter Wemm ** Parameters: 545c2aa98e2SPeter Wemm ** av -- argument vector. 546c2aa98e2SPeter Wemm ** 547c2aa98e2SPeter Wemm ** Returns: 548c2aa98e2SPeter Wemm ** none. 549c2aa98e2SPeter Wemm ** 550c2aa98e2SPeter Wemm ** Side Effects: 551c2aa98e2SPeter Wemm ** prints av. 552c2aa98e2SPeter Wemm */ 553c2aa98e2SPeter Wemm 554c2aa98e2SPeter Wemm void 555c2aa98e2SPeter Wemm printav(av) 556c2aa98e2SPeter Wemm register char **av; 557c2aa98e2SPeter Wemm { 558c2aa98e2SPeter Wemm while (*av != NULL) 559c2aa98e2SPeter Wemm { 560c2aa98e2SPeter Wemm if (tTd(0, 44)) 56106f25ae9SGregory Neil Shapiro dprintf("\n\t%08lx=", (u_long) *av); 562c2aa98e2SPeter Wemm else 563c2aa98e2SPeter Wemm (void) putchar(' '); 564c2aa98e2SPeter Wemm xputs(*av++); 565c2aa98e2SPeter Wemm } 566c2aa98e2SPeter Wemm (void) putchar('\n'); 567c2aa98e2SPeter Wemm } 568c2aa98e2SPeter Wemm /* 569c2aa98e2SPeter Wemm ** LOWER -- turn letter into lower case. 570c2aa98e2SPeter Wemm ** 571c2aa98e2SPeter Wemm ** Parameters: 572c2aa98e2SPeter Wemm ** c -- character to turn into lower case. 573c2aa98e2SPeter Wemm ** 574c2aa98e2SPeter Wemm ** Returns: 575c2aa98e2SPeter Wemm ** c, in lower case. 576c2aa98e2SPeter Wemm ** 577c2aa98e2SPeter Wemm ** Side Effects: 578c2aa98e2SPeter Wemm ** none. 579c2aa98e2SPeter Wemm */ 580c2aa98e2SPeter Wemm 581c2aa98e2SPeter Wemm char 582c2aa98e2SPeter Wemm lower(c) 58306f25ae9SGregory Neil Shapiro register int c; 584c2aa98e2SPeter Wemm { 585c2aa98e2SPeter Wemm return ((isascii(c) && isupper(c)) ? tolower(c) : c); 586c2aa98e2SPeter Wemm } 587c2aa98e2SPeter Wemm /* 588c2aa98e2SPeter Wemm ** XPUTS -- put string doing control escapes. 589c2aa98e2SPeter Wemm ** 590c2aa98e2SPeter Wemm ** Parameters: 591c2aa98e2SPeter Wemm ** s -- string to put. 592c2aa98e2SPeter Wemm ** 593c2aa98e2SPeter Wemm ** Returns: 594c2aa98e2SPeter Wemm ** none. 595c2aa98e2SPeter Wemm ** 596c2aa98e2SPeter Wemm ** Side Effects: 597c2aa98e2SPeter Wemm ** output to stdout 598c2aa98e2SPeter Wemm */ 599c2aa98e2SPeter Wemm 600c2aa98e2SPeter Wemm void 601c2aa98e2SPeter Wemm xputs(s) 602c2aa98e2SPeter Wemm register const char *s; 603c2aa98e2SPeter Wemm { 604c2aa98e2SPeter Wemm register int c; 605c2aa98e2SPeter Wemm register struct metamac *mp; 606c2aa98e2SPeter Wemm bool shiftout = FALSE; 607c2aa98e2SPeter Wemm extern struct metamac MetaMacros[]; 608c2aa98e2SPeter Wemm 609c2aa98e2SPeter Wemm if (s == NULL) 610c2aa98e2SPeter Wemm { 611c2aa98e2SPeter Wemm printf("%s<null>%s", TermEscape.te_rv_on, TermEscape.te_rv_off); 612c2aa98e2SPeter Wemm return; 613c2aa98e2SPeter Wemm } 614c2aa98e2SPeter Wemm while ((c = (*s++ & 0377)) != '\0') 615c2aa98e2SPeter Wemm { 616c2aa98e2SPeter Wemm if (shiftout) 617c2aa98e2SPeter Wemm { 618c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_off); 619c2aa98e2SPeter Wemm shiftout = FALSE; 620c2aa98e2SPeter Wemm } 621c2aa98e2SPeter Wemm if (!isascii(c)) 622c2aa98e2SPeter Wemm { 623c2aa98e2SPeter Wemm if (c == MATCHREPL) 624c2aa98e2SPeter Wemm { 625c2aa98e2SPeter Wemm printf("%s$", TermEscape.te_rv_on); 626c2aa98e2SPeter Wemm shiftout = TRUE; 627c2aa98e2SPeter Wemm if (*s == '\0') 628c2aa98e2SPeter Wemm continue; 629c2aa98e2SPeter Wemm c = *s++ & 0377; 630c2aa98e2SPeter Wemm goto printchar; 631c2aa98e2SPeter Wemm } 632c2aa98e2SPeter Wemm if (c == MACROEXPAND || c == MACRODEXPAND) 633c2aa98e2SPeter Wemm { 634c2aa98e2SPeter Wemm printf("%s$", TermEscape.te_rv_on); 635c2aa98e2SPeter Wemm if (c == MACRODEXPAND) 63606f25ae9SGregory Neil Shapiro (void) putchar('&'); 637c2aa98e2SPeter Wemm shiftout = TRUE; 638c2aa98e2SPeter Wemm if (*s == '\0') 639c2aa98e2SPeter Wemm continue; 640c2aa98e2SPeter Wemm if (strchr("=~&?", *s) != NULL) 64106f25ae9SGregory Neil Shapiro (void) putchar(*s++); 642c2aa98e2SPeter Wemm if (bitset(0200, *s)) 643c2aa98e2SPeter Wemm printf("{%s}", macname(*s++ & 0377)); 644c2aa98e2SPeter Wemm else 645c2aa98e2SPeter Wemm printf("%c", *s++); 646c2aa98e2SPeter Wemm continue; 647c2aa98e2SPeter Wemm } 648c2aa98e2SPeter Wemm for (mp = MetaMacros; mp->metaname != '\0'; mp++) 649c2aa98e2SPeter Wemm { 650c2aa98e2SPeter Wemm if ((mp->metaval & 0377) == c) 651c2aa98e2SPeter Wemm { 652c2aa98e2SPeter Wemm printf("%s$%c", 653c2aa98e2SPeter Wemm TermEscape.te_rv_on, 654c2aa98e2SPeter Wemm mp->metaname); 655c2aa98e2SPeter Wemm shiftout = TRUE; 656c2aa98e2SPeter Wemm break; 657c2aa98e2SPeter Wemm } 658c2aa98e2SPeter Wemm } 659c2aa98e2SPeter Wemm if (c == MATCHCLASS || c == MATCHNCLASS) 660c2aa98e2SPeter Wemm { 661c2aa98e2SPeter Wemm if (bitset(0200, *s)) 662c2aa98e2SPeter Wemm printf("{%s}", macname(*s++ & 0377)); 663c2aa98e2SPeter Wemm else if (*s != '\0') 664c2aa98e2SPeter Wemm printf("%c", *s++); 665c2aa98e2SPeter Wemm } 666c2aa98e2SPeter Wemm if (mp->metaname != '\0') 667c2aa98e2SPeter Wemm continue; 668c2aa98e2SPeter Wemm 669c2aa98e2SPeter Wemm /* unrecognized meta character */ 670c2aa98e2SPeter Wemm printf("%sM-", TermEscape.te_rv_on); 671c2aa98e2SPeter Wemm shiftout = TRUE; 672c2aa98e2SPeter Wemm c &= 0177; 673c2aa98e2SPeter Wemm } 674c2aa98e2SPeter Wemm printchar: 675c2aa98e2SPeter Wemm if (isprint(c)) 676c2aa98e2SPeter Wemm { 67706f25ae9SGregory Neil Shapiro (void) putchar(c); 678c2aa98e2SPeter Wemm continue; 679c2aa98e2SPeter Wemm } 680c2aa98e2SPeter Wemm 681c2aa98e2SPeter Wemm /* wasn't a meta-macro -- find another way to print it */ 682c2aa98e2SPeter Wemm switch (c) 683c2aa98e2SPeter Wemm { 684c2aa98e2SPeter Wemm case '\n': 685c2aa98e2SPeter Wemm c = 'n'; 686c2aa98e2SPeter Wemm break; 687c2aa98e2SPeter Wemm 688c2aa98e2SPeter Wemm case '\r': 689c2aa98e2SPeter Wemm c = 'r'; 690c2aa98e2SPeter Wemm break; 691c2aa98e2SPeter Wemm 692c2aa98e2SPeter Wemm case '\t': 693c2aa98e2SPeter Wemm c = 't'; 694c2aa98e2SPeter Wemm break; 695c2aa98e2SPeter Wemm } 696c2aa98e2SPeter Wemm if (!shiftout) 697c2aa98e2SPeter Wemm { 698c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_on); 699c2aa98e2SPeter Wemm shiftout = TRUE; 700c2aa98e2SPeter Wemm } 701c2aa98e2SPeter Wemm if (isprint(c)) 702c2aa98e2SPeter Wemm { 703c2aa98e2SPeter Wemm (void) putchar('\\'); 704c2aa98e2SPeter Wemm (void) putchar(c); 705c2aa98e2SPeter Wemm } 706c2aa98e2SPeter Wemm else 707c2aa98e2SPeter Wemm { 708c2aa98e2SPeter Wemm (void) putchar('^'); 709c2aa98e2SPeter Wemm (void) putchar(c ^ 0100); 710c2aa98e2SPeter Wemm } 711c2aa98e2SPeter Wemm } 712c2aa98e2SPeter Wemm if (shiftout) 713c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_off); 714c2aa98e2SPeter Wemm (void) fflush(stdout); 715c2aa98e2SPeter Wemm } 716c2aa98e2SPeter Wemm /* 717c2aa98e2SPeter Wemm ** MAKELOWER -- Translate a line into lower case 718c2aa98e2SPeter Wemm ** 719c2aa98e2SPeter Wemm ** Parameters: 720c2aa98e2SPeter Wemm ** p -- the string to translate. If NULL, return is 721c2aa98e2SPeter Wemm ** immediate. 722c2aa98e2SPeter Wemm ** 723c2aa98e2SPeter Wemm ** Returns: 724c2aa98e2SPeter Wemm ** none. 725c2aa98e2SPeter Wemm ** 726c2aa98e2SPeter Wemm ** Side Effects: 727c2aa98e2SPeter Wemm ** String pointed to by p is translated to lower case. 728c2aa98e2SPeter Wemm */ 729c2aa98e2SPeter Wemm 730c2aa98e2SPeter Wemm void 731c2aa98e2SPeter Wemm makelower(p) 732c2aa98e2SPeter Wemm register char *p; 733c2aa98e2SPeter Wemm { 734c2aa98e2SPeter Wemm register char c; 735c2aa98e2SPeter Wemm 736c2aa98e2SPeter Wemm if (p == NULL) 737c2aa98e2SPeter Wemm return; 738c2aa98e2SPeter Wemm for (; (c = *p) != '\0'; p++) 739c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 740c2aa98e2SPeter Wemm *p = tolower(c); 741c2aa98e2SPeter Wemm } 742c2aa98e2SPeter Wemm /* 743c2aa98e2SPeter Wemm ** BUILDFNAME -- build full name from gecos style entry. 744c2aa98e2SPeter Wemm ** 745c2aa98e2SPeter Wemm ** This routine interprets the strange entry that would appear 746c2aa98e2SPeter Wemm ** in the GECOS field of the password file. 747c2aa98e2SPeter Wemm ** 748c2aa98e2SPeter Wemm ** Parameters: 749c2aa98e2SPeter Wemm ** p -- name to build. 75006f25ae9SGregory Neil Shapiro ** user -- the login name of this user (for &). 751c2aa98e2SPeter Wemm ** buf -- place to put the result. 752c2aa98e2SPeter Wemm ** buflen -- length of buf. 753c2aa98e2SPeter Wemm ** 754c2aa98e2SPeter Wemm ** Returns: 755c2aa98e2SPeter Wemm ** none. 756c2aa98e2SPeter Wemm ** 757c2aa98e2SPeter Wemm ** Side Effects: 758c2aa98e2SPeter Wemm ** none. 759c2aa98e2SPeter Wemm */ 760c2aa98e2SPeter Wemm 761c2aa98e2SPeter Wemm void 76206f25ae9SGregory Neil Shapiro buildfname(gecos, user, buf, buflen) 763c2aa98e2SPeter Wemm register char *gecos; 76406f25ae9SGregory Neil Shapiro char *user; 765c2aa98e2SPeter Wemm char *buf; 766c2aa98e2SPeter Wemm int buflen; 767c2aa98e2SPeter Wemm { 768c2aa98e2SPeter Wemm register char *p; 769c2aa98e2SPeter Wemm register char *bp = buf; 770c2aa98e2SPeter Wemm 771c2aa98e2SPeter Wemm if (*gecos == '*') 772c2aa98e2SPeter Wemm gecos++; 773c2aa98e2SPeter Wemm 774c2aa98e2SPeter Wemm /* copy gecos, interpolating & to be full name */ 775c2aa98e2SPeter Wemm for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) 776c2aa98e2SPeter Wemm { 777c2aa98e2SPeter Wemm if (bp >= &buf[buflen - 1]) 778c2aa98e2SPeter Wemm { 779c2aa98e2SPeter Wemm /* buffer overflow -- just use login name */ 78006f25ae9SGregory Neil Shapiro snprintf(buf, buflen, "%s", user); 781c2aa98e2SPeter Wemm return; 782c2aa98e2SPeter Wemm } 783c2aa98e2SPeter Wemm if (*p == '&') 784c2aa98e2SPeter Wemm { 785c2aa98e2SPeter Wemm /* interpolate full name */ 78606f25ae9SGregory Neil Shapiro snprintf(bp, buflen - (bp - buf), "%s", user); 787c2aa98e2SPeter Wemm *bp = toupper(*bp); 788c2aa98e2SPeter Wemm bp += strlen(bp); 789c2aa98e2SPeter Wemm } 790c2aa98e2SPeter Wemm else 791c2aa98e2SPeter Wemm *bp++ = *p; 792c2aa98e2SPeter Wemm } 793c2aa98e2SPeter Wemm *bp = '\0'; 794c2aa98e2SPeter Wemm } 795c2aa98e2SPeter Wemm /* 796c2aa98e2SPeter Wemm ** FIXCRLF -- fix <CR><LF> in line. 797c2aa98e2SPeter Wemm ** 798c2aa98e2SPeter Wemm ** Looks for the <CR><LF> combination and turns it into the 799c2aa98e2SPeter Wemm ** UNIX canonical <NL> character. It only takes one line, 800c2aa98e2SPeter Wemm ** i.e., it is assumed that the first <NL> found is the end 801c2aa98e2SPeter Wemm ** of the line. 802c2aa98e2SPeter Wemm ** 803c2aa98e2SPeter Wemm ** Parameters: 804c2aa98e2SPeter Wemm ** line -- the line to fix. 805c2aa98e2SPeter Wemm ** stripnl -- if true, strip the newline also. 806c2aa98e2SPeter Wemm ** 807c2aa98e2SPeter Wemm ** Returns: 808c2aa98e2SPeter Wemm ** none. 809c2aa98e2SPeter Wemm ** 810c2aa98e2SPeter Wemm ** Side Effects: 811c2aa98e2SPeter Wemm ** line is changed in place. 812c2aa98e2SPeter Wemm */ 813c2aa98e2SPeter Wemm 814c2aa98e2SPeter Wemm void 815c2aa98e2SPeter Wemm fixcrlf(line, stripnl) 816c2aa98e2SPeter Wemm char *line; 817c2aa98e2SPeter Wemm bool stripnl; 818c2aa98e2SPeter Wemm { 819c2aa98e2SPeter Wemm register char *p; 820c2aa98e2SPeter Wemm 821c2aa98e2SPeter Wemm p = strchr(line, '\n'); 822c2aa98e2SPeter Wemm if (p == NULL) 823c2aa98e2SPeter Wemm return; 824c2aa98e2SPeter Wemm if (p > line && p[-1] == '\r') 825c2aa98e2SPeter Wemm p--; 826c2aa98e2SPeter Wemm if (!stripnl) 827c2aa98e2SPeter Wemm *p++ = '\n'; 828c2aa98e2SPeter Wemm *p = '\0'; 829c2aa98e2SPeter Wemm } 830c2aa98e2SPeter Wemm /* 831c2aa98e2SPeter Wemm ** PUTLINE -- put a line like fputs obeying SMTP conventions 832c2aa98e2SPeter Wemm ** 833c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 834c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 835c2aa98e2SPeter Wemm ** 836c2aa98e2SPeter Wemm ** Parameters: 837c2aa98e2SPeter Wemm ** l -- line to put. 838c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 839c2aa98e2SPeter Wemm ** 840c2aa98e2SPeter Wemm ** Returns: 841c2aa98e2SPeter Wemm ** none 842c2aa98e2SPeter Wemm ** 843c2aa98e2SPeter Wemm ** Side Effects: 844c2aa98e2SPeter Wemm ** output of l to fp. 845c2aa98e2SPeter Wemm */ 846c2aa98e2SPeter Wemm 847c2aa98e2SPeter Wemm void 848c2aa98e2SPeter Wemm putline(l, mci) 849c2aa98e2SPeter Wemm register char *l; 850c2aa98e2SPeter Wemm register MCI *mci; 851c2aa98e2SPeter Wemm { 852c2aa98e2SPeter Wemm putxline(l, strlen(l), mci, PXLF_MAPFROM); 853c2aa98e2SPeter Wemm } 854c2aa98e2SPeter Wemm /* 855c2aa98e2SPeter Wemm ** PUTXLINE -- putline with flags bits. 856c2aa98e2SPeter Wemm ** 857c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 858c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 859c2aa98e2SPeter Wemm ** 860c2aa98e2SPeter Wemm ** Parameters: 861c2aa98e2SPeter Wemm ** l -- line to put. 862c2aa98e2SPeter Wemm ** len -- the length of the line. 863c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 864c2aa98e2SPeter Wemm ** pxflags -- flag bits: 865c2aa98e2SPeter Wemm ** PXLF_MAPFROM -- map From_ to >From_. 866c2aa98e2SPeter Wemm ** PXLF_STRIP8BIT -- strip 8th bit. 867c2aa98e2SPeter Wemm ** PXLF_HEADER -- map bare newline in header to newline space. 868c2aa98e2SPeter Wemm ** 869c2aa98e2SPeter Wemm ** Returns: 870c2aa98e2SPeter Wemm ** none 871c2aa98e2SPeter Wemm ** 872c2aa98e2SPeter Wemm ** Side Effects: 873c2aa98e2SPeter Wemm ** output of l to fp. 874c2aa98e2SPeter Wemm */ 875c2aa98e2SPeter Wemm 876c2aa98e2SPeter Wemm void 877c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags) 878c2aa98e2SPeter Wemm register char *l; 879c2aa98e2SPeter Wemm size_t len; 880c2aa98e2SPeter Wemm register MCI *mci; 881c2aa98e2SPeter Wemm int pxflags; 882c2aa98e2SPeter Wemm { 88306f25ae9SGregory Neil Shapiro bool dead = FALSE; 884c2aa98e2SPeter Wemm register char *p, *end; 885c2aa98e2SPeter Wemm int slop = 0; 886c2aa98e2SPeter Wemm 887c2aa98e2SPeter Wemm /* strip out 0200 bits -- these can look like TELNET protocol */ 888c2aa98e2SPeter Wemm if (bitset(MCIF_7BIT, mci->mci_flags) || 889c2aa98e2SPeter Wemm bitset(PXLF_STRIP8BIT, pxflags)) 890c2aa98e2SPeter Wemm { 891c2aa98e2SPeter Wemm register char svchar; 892c2aa98e2SPeter Wemm 893c2aa98e2SPeter Wemm for (p = l; (svchar = *p) != '\0'; ++p) 894c2aa98e2SPeter Wemm if (bitset(0200, svchar)) 895c2aa98e2SPeter Wemm *p = svchar &~ 0200; 896c2aa98e2SPeter Wemm } 897c2aa98e2SPeter Wemm 898c2aa98e2SPeter Wemm end = l + len; 899c2aa98e2SPeter Wemm do 900c2aa98e2SPeter Wemm { 901c2aa98e2SPeter Wemm /* find the end of the line */ 902c2aa98e2SPeter Wemm p = memchr(l, '\n', end - l); 903c2aa98e2SPeter Wemm if (p == NULL) 904c2aa98e2SPeter Wemm p = end; 905c2aa98e2SPeter Wemm 906c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 907c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d >>> ", (int) getpid()); 908c2aa98e2SPeter Wemm 909c2aa98e2SPeter Wemm /* check for line overflow */ 910c2aa98e2SPeter Wemm while (mci->mci_mailer->m_linelimit > 0 && 911c2aa98e2SPeter Wemm (p - l + slop) > mci->mci_mailer->m_linelimit) 912c2aa98e2SPeter Wemm { 913c2aa98e2SPeter Wemm char *l_base = l; 914c2aa98e2SPeter Wemm register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 915c2aa98e2SPeter Wemm 916c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 917c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 918c2aa98e2SPeter Wemm { 91906f25ae9SGregory Neil Shapiro if (putc('.', mci->mci_out) == EOF) 92006f25ae9SGregory Neil Shapiro dead = TRUE; 921c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 922c2aa98e2SPeter Wemm (void) putc('.', TrafficLogFile); 923c2aa98e2SPeter Wemm } 924c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 925c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 926c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 927c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 928c2aa98e2SPeter Wemm { 92906f25ae9SGregory Neil Shapiro if (putc('>', mci->mci_out) == EOF) 93006f25ae9SGregory Neil Shapiro dead = TRUE; 931c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 932c2aa98e2SPeter Wemm (void) putc('>', TrafficLogFile); 933c2aa98e2SPeter Wemm } 93406f25ae9SGregory Neil Shapiro if (dead) 93506f25ae9SGregory Neil Shapiro break; 93606f25ae9SGregory Neil Shapiro 937c2aa98e2SPeter Wemm while (l < q) 938c2aa98e2SPeter Wemm { 93906f25ae9SGregory Neil Shapiro if (putc((unsigned char) *l++, mci->mci_out) == 94006f25ae9SGregory Neil Shapiro EOF) 94106f25ae9SGregory Neil Shapiro { 94206f25ae9SGregory Neil Shapiro dead = TRUE; 94306f25ae9SGregory Neil Shapiro break; 944c2aa98e2SPeter Wemm } 94506f25ae9SGregory Neil Shapiro 94606f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 94706f25ae9SGregory Neil Shapiro DataProgress = TRUE; 94806f25ae9SGregory Neil Shapiro } 94906f25ae9SGregory Neil Shapiro if (dead) 95006f25ae9SGregory Neil Shapiro break; 95106f25ae9SGregory Neil Shapiro 95206f25ae9SGregory Neil Shapiro if (putc('!', mci->mci_out) == EOF || 95306f25ae9SGregory Neil Shapiro fputs(mci->mci_mailer->m_eol, 95406f25ae9SGregory Neil Shapiro mci->mci_out) == EOF || 95506f25ae9SGregory Neil Shapiro putc(' ', mci->mci_out) == EOF) 95606f25ae9SGregory Neil Shapiro { 95706f25ae9SGregory Neil Shapiro dead = TRUE; 95806f25ae9SGregory Neil Shapiro break; 95906f25ae9SGregory Neil Shapiro } 96006f25ae9SGregory Neil Shapiro 96106f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 96206f25ae9SGregory Neil Shapiro DataProgress = TRUE; 96306f25ae9SGregory Neil Shapiro 964c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 965c2aa98e2SPeter Wemm { 966c2aa98e2SPeter Wemm for (l = l_base; l < q; l++) 96706f25ae9SGregory Neil Shapiro (void) putc((unsigned char)*l, 96806f25ae9SGregory Neil Shapiro TrafficLogFile); 969c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "!\n%05d >>> ", 970c2aa98e2SPeter Wemm (int) getpid()); 971c2aa98e2SPeter Wemm } 972c2aa98e2SPeter Wemm slop = 1; 973c2aa98e2SPeter Wemm } 974c2aa98e2SPeter Wemm 97506f25ae9SGregory Neil Shapiro if (dead) 97606f25ae9SGregory Neil Shapiro break; 97706f25ae9SGregory Neil Shapiro 978c2aa98e2SPeter Wemm /* output last part */ 979c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 980c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 981c2aa98e2SPeter Wemm { 98206f25ae9SGregory Neil Shapiro if (putc('.', mci->mci_out) == EOF) 98306f25ae9SGregory Neil Shapiro break; 984c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 985c2aa98e2SPeter Wemm (void) putc('.', TrafficLogFile); 986c2aa98e2SPeter Wemm } 987c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 988c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 989c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 990c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 991c2aa98e2SPeter Wemm { 99206f25ae9SGregory Neil Shapiro if (putc('>', mci->mci_out) == EOF) 99306f25ae9SGregory Neil Shapiro break; 994c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 995c2aa98e2SPeter Wemm (void) putc('>', TrafficLogFile); 996c2aa98e2SPeter Wemm } 997c2aa98e2SPeter Wemm for ( ; l < p; ++l) 998c2aa98e2SPeter Wemm { 999c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 100006f25ae9SGregory Neil Shapiro (void) putc((unsigned char)*l, TrafficLogFile); 100106f25ae9SGregory Neil Shapiro if (putc((unsigned char) *l, mci->mci_out) == EOF) 100206f25ae9SGregory Neil Shapiro { 100306f25ae9SGregory Neil Shapiro dead = TRUE; 100406f25ae9SGregory Neil Shapiro break; 1005c2aa98e2SPeter Wemm } 100606f25ae9SGregory Neil Shapiro 100706f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 100806f25ae9SGregory Neil Shapiro DataProgress = TRUE; 100906f25ae9SGregory Neil Shapiro } 101006f25ae9SGregory Neil Shapiro if (dead) 101106f25ae9SGregory Neil Shapiro break; 101206f25ae9SGregory Neil Shapiro 1013c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1014c2aa98e2SPeter Wemm (void) putc('\n', TrafficLogFile); 101506f25ae9SGregory Neil Shapiro if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) 101606f25ae9SGregory Neil Shapiro break; 1017c2aa98e2SPeter Wemm if (l < end && *l == '\n') 1018c2aa98e2SPeter Wemm { 1019c2aa98e2SPeter Wemm if (*++l != ' ' && *l != '\t' && *l != '\0' && 1020c2aa98e2SPeter Wemm bitset(PXLF_HEADER, pxflags)) 1021c2aa98e2SPeter Wemm { 102206f25ae9SGregory Neil Shapiro if (putc(' ', mci->mci_out) == EOF) 102306f25ae9SGregory Neil Shapiro break; 1024c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1025c2aa98e2SPeter Wemm (void) putc(' ', TrafficLogFile); 1026c2aa98e2SPeter Wemm } 1027c2aa98e2SPeter Wemm } 102806f25ae9SGregory Neil Shapiro 102906f25ae9SGregory Neil Shapiro /* record progress for DATA timeout */ 103006f25ae9SGregory Neil Shapiro DataProgress = TRUE; 1031c2aa98e2SPeter Wemm } while (l < end); 1032c2aa98e2SPeter Wemm } 1033c2aa98e2SPeter Wemm /* 1034c2aa98e2SPeter Wemm ** XUNLINK -- unlink a file, doing logging as appropriate. 1035c2aa98e2SPeter Wemm ** 1036c2aa98e2SPeter Wemm ** Parameters: 1037c2aa98e2SPeter Wemm ** f -- name of file to unlink. 1038c2aa98e2SPeter Wemm ** 1039c2aa98e2SPeter Wemm ** Returns: 1040c2aa98e2SPeter Wemm ** none. 1041c2aa98e2SPeter Wemm ** 1042c2aa98e2SPeter Wemm ** Side Effects: 1043c2aa98e2SPeter Wemm ** f is unlinked. 1044c2aa98e2SPeter Wemm */ 1045c2aa98e2SPeter Wemm 1046c2aa98e2SPeter Wemm void 1047c2aa98e2SPeter Wemm xunlink(f) 1048c2aa98e2SPeter Wemm char *f; 1049c2aa98e2SPeter Wemm { 1050c2aa98e2SPeter Wemm register int i; 1051c2aa98e2SPeter Wemm 1052c2aa98e2SPeter Wemm if (LogLevel > 98) 1053c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1054c2aa98e2SPeter Wemm "unlink %s", 1055c2aa98e2SPeter Wemm f); 1056c2aa98e2SPeter Wemm 1057c2aa98e2SPeter Wemm i = unlink(f); 1058c2aa98e2SPeter Wemm if (i < 0 && LogLevel > 97) 1059c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1060c2aa98e2SPeter Wemm "%s: unlink-fail %d", 1061c2aa98e2SPeter Wemm f, errno); 1062c2aa98e2SPeter Wemm } 1063c2aa98e2SPeter Wemm /* 1064c2aa98e2SPeter Wemm ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 1065c2aa98e2SPeter Wemm ** 1066c2aa98e2SPeter Wemm ** Parameters: 1067c2aa98e2SPeter Wemm ** buf -- place to put the input line. 1068c2aa98e2SPeter Wemm ** siz -- size of buf. 1069c2aa98e2SPeter Wemm ** fp -- file to read from. 1070c2aa98e2SPeter Wemm ** timeout -- the timeout before error occurs. 1071c2aa98e2SPeter Wemm ** during -- what we are trying to read (for error messages). 1072c2aa98e2SPeter Wemm ** 1073c2aa98e2SPeter Wemm ** Returns: 1074c2aa98e2SPeter Wemm ** NULL on error (including timeout). This will also leave 1075c2aa98e2SPeter Wemm ** buf containing a null string. 1076c2aa98e2SPeter Wemm ** buf otherwise. 1077c2aa98e2SPeter Wemm ** 1078c2aa98e2SPeter Wemm ** Side Effects: 1079c2aa98e2SPeter Wemm ** none. 1080c2aa98e2SPeter Wemm */ 1081c2aa98e2SPeter Wemm 108206f25ae9SGregory Neil Shapiro 1083c2aa98e2SPeter Wemm static jmp_buf CtxReadTimeout; 1084c2aa98e2SPeter Wemm 1085c2aa98e2SPeter Wemm char * 1086c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during) 1087c2aa98e2SPeter Wemm char *buf; 1088c2aa98e2SPeter Wemm int siz; 1089c2aa98e2SPeter Wemm FILE *fp; 1090c2aa98e2SPeter Wemm time_t timeout; 1091c2aa98e2SPeter Wemm char *during; 1092c2aa98e2SPeter Wemm { 1093c2aa98e2SPeter Wemm register EVENT *ev = NULL; 1094c2aa98e2SPeter Wemm register char *p; 10952e43090eSPeter Wemm int save_errno; 1096c2aa98e2SPeter Wemm 1097c2aa98e2SPeter Wemm if (fp == NULL) 1098c2aa98e2SPeter Wemm { 1099c2aa98e2SPeter Wemm buf[0] = '\0'; 1100c2aa98e2SPeter Wemm return NULL; 1101c2aa98e2SPeter Wemm } 1102c2aa98e2SPeter Wemm 1103c2aa98e2SPeter Wemm /* set the timeout */ 1104c2aa98e2SPeter Wemm if (timeout != 0) 1105c2aa98e2SPeter Wemm { 1106c2aa98e2SPeter Wemm if (setjmp(CtxReadTimeout) != 0) 1107c2aa98e2SPeter Wemm { 1108c2aa98e2SPeter Wemm if (LogLevel > 1) 1109c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 1110c2aa98e2SPeter Wemm "timeout waiting for input from %.100s during %s", 1111c2aa98e2SPeter Wemm CurHostName ? CurHostName : "local", 1112c2aa98e2SPeter Wemm during); 1113c2aa98e2SPeter Wemm buf[0] = '\0'; 1114c2aa98e2SPeter Wemm #if XDEBUG 1115c2aa98e2SPeter Wemm checkfd012(during); 111606f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1117c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1118c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n", 1119c2aa98e2SPeter Wemm (int) getpid()); 11202e43090eSPeter Wemm errno = 0; 112106f25ae9SGregory Neil Shapiro return NULL; 1122c2aa98e2SPeter Wemm } 1123c2aa98e2SPeter Wemm ev = setevent(timeout, readtimeout, 0); 1124c2aa98e2SPeter Wemm } 1125c2aa98e2SPeter Wemm 1126c2aa98e2SPeter Wemm /* try to read */ 1127c2aa98e2SPeter Wemm p = NULL; 11282e43090eSPeter Wemm errno = 0; 1129c2aa98e2SPeter Wemm while (!feof(fp) && !ferror(fp)) 1130c2aa98e2SPeter Wemm { 1131c2aa98e2SPeter Wemm errno = 0; 1132c2aa98e2SPeter Wemm p = fgets(buf, siz, fp); 1133c2aa98e2SPeter Wemm if (p != NULL || errno != EINTR) 1134c2aa98e2SPeter Wemm break; 1135c2aa98e2SPeter Wemm clearerr(fp); 1136c2aa98e2SPeter Wemm } 11372e43090eSPeter Wemm save_errno = errno; 1138c2aa98e2SPeter Wemm 1139c2aa98e2SPeter Wemm /* clear the event if it has not sprung */ 1140c2aa98e2SPeter Wemm clrevent(ev); 1141c2aa98e2SPeter Wemm 1142c2aa98e2SPeter Wemm /* clean up the books and exit */ 1143c2aa98e2SPeter Wemm LineNumber++; 1144c2aa98e2SPeter Wemm if (p == NULL) 1145c2aa98e2SPeter Wemm { 1146c2aa98e2SPeter Wemm buf[0] = '\0'; 1147c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1148c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< [EOF]\n", (int) getpid()); 11492e43090eSPeter Wemm errno = save_errno; 115006f25ae9SGregory Neil Shapiro return NULL; 1151c2aa98e2SPeter Wemm } 1152c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 1153c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< %s", (int) getpid(), buf); 1154c2aa98e2SPeter Wemm if (SevenBitInput) 1155c2aa98e2SPeter Wemm { 1156c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1157c2aa98e2SPeter Wemm *p &= ~0200; 1158c2aa98e2SPeter Wemm } 1159c2aa98e2SPeter Wemm else if (!HasEightBits) 1160c2aa98e2SPeter Wemm { 1161c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 1162c2aa98e2SPeter Wemm { 1163c2aa98e2SPeter Wemm if (bitset(0200, *p)) 1164c2aa98e2SPeter Wemm { 1165c2aa98e2SPeter Wemm HasEightBits = TRUE; 1166c2aa98e2SPeter Wemm break; 1167c2aa98e2SPeter Wemm } 1168c2aa98e2SPeter Wemm } 1169c2aa98e2SPeter Wemm } 117006f25ae9SGregory Neil Shapiro return buf; 1171c2aa98e2SPeter Wemm } 1172c2aa98e2SPeter Wemm 1173c2aa98e2SPeter Wemm /* ARGSUSED */ 1174c2aa98e2SPeter Wemm static void 1175c2aa98e2SPeter Wemm readtimeout(timeout) 1176c2aa98e2SPeter Wemm time_t timeout; 1177c2aa98e2SPeter Wemm { 1178c2aa98e2SPeter Wemm longjmp(CtxReadTimeout, 1); 1179c2aa98e2SPeter Wemm } 1180c2aa98e2SPeter Wemm /* 1181c2aa98e2SPeter Wemm ** FGETFOLDED -- like fgets, but know about folded lines. 1182c2aa98e2SPeter Wemm ** 1183c2aa98e2SPeter Wemm ** Parameters: 1184c2aa98e2SPeter Wemm ** buf -- place to put result. 1185c2aa98e2SPeter Wemm ** n -- bytes available. 1186c2aa98e2SPeter Wemm ** f -- file to read from. 1187c2aa98e2SPeter Wemm ** 1188c2aa98e2SPeter Wemm ** Returns: 1189c2aa98e2SPeter Wemm ** input line(s) on success, NULL on error or EOF. 1190c2aa98e2SPeter Wemm ** This will normally be buf -- unless the line is too 1191c2aa98e2SPeter Wemm ** long, when it will be xalloc()ed. 1192c2aa98e2SPeter Wemm ** 1193c2aa98e2SPeter Wemm ** Side Effects: 1194c2aa98e2SPeter Wemm ** buf gets lines from f, with continuation lines (lines 1195c2aa98e2SPeter Wemm ** with leading white space) appended. CRLF's are mapped 1196c2aa98e2SPeter Wemm ** into single newlines. Any trailing NL is stripped. 1197c2aa98e2SPeter Wemm */ 1198c2aa98e2SPeter Wemm 1199c2aa98e2SPeter Wemm char * 1200c2aa98e2SPeter Wemm fgetfolded(buf, n, f) 1201c2aa98e2SPeter Wemm char *buf; 1202c2aa98e2SPeter Wemm register int n; 1203c2aa98e2SPeter Wemm FILE *f; 1204c2aa98e2SPeter Wemm { 1205c2aa98e2SPeter Wemm register char *p = buf; 1206c2aa98e2SPeter Wemm char *bp = buf; 1207c2aa98e2SPeter Wemm register int i; 1208c2aa98e2SPeter Wemm 1209c2aa98e2SPeter Wemm n--; 1210c2aa98e2SPeter Wemm while ((i = getc(f)) != EOF) 1211c2aa98e2SPeter Wemm { 1212c2aa98e2SPeter Wemm if (i == '\r') 1213c2aa98e2SPeter Wemm { 1214c2aa98e2SPeter Wemm i = getc(f); 1215c2aa98e2SPeter Wemm if (i != '\n') 1216c2aa98e2SPeter Wemm { 1217c2aa98e2SPeter Wemm if (i != EOF) 1218c2aa98e2SPeter Wemm (void) ungetc(i, f); 1219c2aa98e2SPeter Wemm i = '\r'; 1220c2aa98e2SPeter Wemm } 1221c2aa98e2SPeter Wemm } 1222c2aa98e2SPeter Wemm if (--n <= 0) 1223c2aa98e2SPeter Wemm { 1224c2aa98e2SPeter Wemm /* allocate new space */ 1225c2aa98e2SPeter Wemm char *nbp; 1226c2aa98e2SPeter Wemm int nn; 1227c2aa98e2SPeter Wemm 1228c2aa98e2SPeter Wemm nn = (p - bp); 1229c2aa98e2SPeter Wemm if (nn < MEMCHUNKSIZE) 1230c2aa98e2SPeter Wemm nn *= 2; 1231c2aa98e2SPeter Wemm else 1232c2aa98e2SPeter Wemm nn += MEMCHUNKSIZE; 1233c2aa98e2SPeter Wemm nbp = xalloc(nn); 123406f25ae9SGregory Neil Shapiro memmove(nbp, bp, p - bp); 1235c2aa98e2SPeter Wemm p = &nbp[p - bp]; 1236c2aa98e2SPeter Wemm if (bp != buf) 1237c2aa98e2SPeter Wemm free(bp); 1238c2aa98e2SPeter Wemm bp = nbp; 1239c2aa98e2SPeter Wemm n = nn - (p - bp); 1240c2aa98e2SPeter Wemm } 1241c2aa98e2SPeter Wemm *p++ = i; 1242c2aa98e2SPeter Wemm if (i == '\n') 1243c2aa98e2SPeter Wemm { 1244c2aa98e2SPeter Wemm LineNumber++; 1245c2aa98e2SPeter Wemm i = getc(f); 1246c2aa98e2SPeter Wemm if (i != EOF) 1247c2aa98e2SPeter Wemm (void) ungetc(i, f); 1248c2aa98e2SPeter Wemm if (i != ' ' && i != '\t') 1249c2aa98e2SPeter Wemm break; 1250c2aa98e2SPeter Wemm } 1251c2aa98e2SPeter Wemm } 1252c2aa98e2SPeter Wemm if (p == bp) 125306f25ae9SGregory Neil Shapiro return NULL; 1254c2aa98e2SPeter Wemm if (p[-1] == '\n') 1255c2aa98e2SPeter Wemm p--; 1256c2aa98e2SPeter Wemm *p = '\0'; 125706f25ae9SGregory Neil Shapiro return bp; 1258c2aa98e2SPeter Wemm } 1259c2aa98e2SPeter Wemm /* 1260c2aa98e2SPeter Wemm ** CURTIME -- return current time. 1261c2aa98e2SPeter Wemm ** 1262c2aa98e2SPeter Wemm ** Parameters: 1263c2aa98e2SPeter Wemm ** none. 1264c2aa98e2SPeter Wemm ** 1265c2aa98e2SPeter Wemm ** Returns: 1266c2aa98e2SPeter Wemm ** the current time. 1267c2aa98e2SPeter Wemm ** 1268c2aa98e2SPeter Wemm ** Side Effects: 1269c2aa98e2SPeter Wemm ** none. 1270c2aa98e2SPeter Wemm */ 1271c2aa98e2SPeter Wemm 1272c2aa98e2SPeter Wemm time_t 1273c2aa98e2SPeter Wemm curtime() 1274c2aa98e2SPeter Wemm { 1275c2aa98e2SPeter Wemm auto time_t t; 1276c2aa98e2SPeter Wemm 1277c2aa98e2SPeter Wemm (void) time(&t); 127806f25ae9SGregory Neil Shapiro return t; 1279c2aa98e2SPeter Wemm } 1280c2aa98e2SPeter Wemm /* 1281c2aa98e2SPeter Wemm ** ATOBOOL -- convert a string representation to boolean. 1282c2aa98e2SPeter Wemm ** 1283c2aa98e2SPeter Wemm ** Defaults to "TRUE" 1284c2aa98e2SPeter Wemm ** 1285c2aa98e2SPeter Wemm ** Parameters: 1286c2aa98e2SPeter Wemm ** s -- string to convert. Takes "tTyY" as true, 1287c2aa98e2SPeter Wemm ** others as false. 1288c2aa98e2SPeter Wemm ** 1289c2aa98e2SPeter Wemm ** Returns: 1290c2aa98e2SPeter Wemm ** A boolean representation of the string. 1291c2aa98e2SPeter Wemm ** 1292c2aa98e2SPeter Wemm ** Side Effects: 1293c2aa98e2SPeter Wemm ** none. 1294c2aa98e2SPeter Wemm */ 1295c2aa98e2SPeter Wemm 1296c2aa98e2SPeter Wemm bool 1297c2aa98e2SPeter Wemm atobool(s) 1298c2aa98e2SPeter Wemm register char *s; 1299c2aa98e2SPeter Wemm { 1300c2aa98e2SPeter Wemm if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 130106f25ae9SGregory Neil Shapiro return TRUE; 130206f25ae9SGregory Neil Shapiro return FALSE; 1303c2aa98e2SPeter Wemm } 1304c2aa98e2SPeter Wemm /* 1305c2aa98e2SPeter Wemm ** ATOOCT -- convert a string representation to octal. 1306c2aa98e2SPeter Wemm ** 1307c2aa98e2SPeter Wemm ** Parameters: 1308c2aa98e2SPeter Wemm ** s -- string to convert. 1309c2aa98e2SPeter Wemm ** 1310c2aa98e2SPeter Wemm ** Returns: 1311c2aa98e2SPeter Wemm ** An integer representing the string interpreted as an 1312c2aa98e2SPeter Wemm ** octal number. 1313c2aa98e2SPeter Wemm ** 1314c2aa98e2SPeter Wemm ** Side Effects: 1315c2aa98e2SPeter Wemm ** none. 1316c2aa98e2SPeter Wemm */ 1317c2aa98e2SPeter Wemm 1318c2aa98e2SPeter Wemm int 1319c2aa98e2SPeter Wemm atooct(s) 1320c2aa98e2SPeter Wemm register char *s; 1321c2aa98e2SPeter Wemm { 1322c2aa98e2SPeter Wemm register int i = 0; 1323c2aa98e2SPeter Wemm 1324c2aa98e2SPeter Wemm while (*s >= '0' && *s <= '7') 1325c2aa98e2SPeter Wemm i = (i << 3) | (*s++ - '0'); 132606f25ae9SGregory Neil Shapiro return i; 1327c2aa98e2SPeter Wemm } 1328c2aa98e2SPeter Wemm /* 1329c2aa98e2SPeter Wemm ** BITINTERSECT -- tell if two bitmaps intersect 1330c2aa98e2SPeter Wemm ** 1331c2aa98e2SPeter Wemm ** Parameters: 1332c2aa98e2SPeter Wemm ** a, b -- the bitmaps in question 1333c2aa98e2SPeter Wemm ** 1334c2aa98e2SPeter Wemm ** Returns: 1335c2aa98e2SPeter Wemm ** TRUE if they have a non-null intersection 1336c2aa98e2SPeter Wemm ** FALSE otherwise 1337c2aa98e2SPeter Wemm ** 1338c2aa98e2SPeter Wemm ** Side Effects: 1339c2aa98e2SPeter Wemm ** none. 1340c2aa98e2SPeter Wemm */ 1341c2aa98e2SPeter Wemm 1342c2aa98e2SPeter Wemm bool 1343c2aa98e2SPeter Wemm bitintersect(a, b) 134406f25ae9SGregory Neil Shapiro BITMAP256 a; 134506f25ae9SGregory Neil Shapiro BITMAP256 b; 1346c2aa98e2SPeter Wemm { 1347c2aa98e2SPeter Wemm int i; 1348c2aa98e2SPeter Wemm 1349c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1350c2aa98e2SPeter Wemm if ((a[i] & b[i]) != 0) 135106f25ae9SGregory Neil Shapiro return TRUE; 135206f25ae9SGregory Neil Shapiro return FALSE; 1353c2aa98e2SPeter Wemm } 1354c2aa98e2SPeter Wemm /* 1355c2aa98e2SPeter Wemm ** BITZEROP -- tell if a bitmap is all zero 1356c2aa98e2SPeter Wemm ** 1357c2aa98e2SPeter Wemm ** Parameters: 1358c2aa98e2SPeter Wemm ** map -- the bit map to check 1359c2aa98e2SPeter Wemm ** 1360c2aa98e2SPeter Wemm ** Returns: 1361c2aa98e2SPeter Wemm ** TRUE if map is all zero. 1362c2aa98e2SPeter Wemm ** FALSE if there are any bits set in map. 1363c2aa98e2SPeter Wemm ** 1364c2aa98e2SPeter Wemm ** Side Effects: 1365c2aa98e2SPeter Wemm ** none. 1366c2aa98e2SPeter Wemm */ 1367c2aa98e2SPeter Wemm 1368c2aa98e2SPeter Wemm bool 1369c2aa98e2SPeter Wemm bitzerop(map) 137006f25ae9SGregory Neil Shapiro BITMAP256 map; 1371c2aa98e2SPeter Wemm { 1372c2aa98e2SPeter Wemm int i; 1373c2aa98e2SPeter Wemm 1374c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1375c2aa98e2SPeter Wemm if (map[i] != 0) 137606f25ae9SGregory Neil Shapiro return FALSE; 137706f25ae9SGregory Neil Shapiro return TRUE; 1378c2aa98e2SPeter Wemm } 1379c2aa98e2SPeter Wemm /* 1380c2aa98e2SPeter Wemm ** STRCONTAINEDIN -- tell if one string is contained in another 1381c2aa98e2SPeter Wemm ** 1382c2aa98e2SPeter Wemm ** Parameters: 1383c2aa98e2SPeter Wemm ** a -- possible substring. 1384c2aa98e2SPeter Wemm ** b -- possible superstring. 1385c2aa98e2SPeter Wemm ** 1386c2aa98e2SPeter Wemm ** Returns: 1387c2aa98e2SPeter Wemm ** TRUE if a is contained in b. 1388c2aa98e2SPeter Wemm ** FALSE otherwise. 1389c2aa98e2SPeter Wemm */ 1390c2aa98e2SPeter Wemm 1391c2aa98e2SPeter Wemm bool 1392c2aa98e2SPeter Wemm strcontainedin(a, b) 1393c2aa98e2SPeter Wemm register char *a; 1394c2aa98e2SPeter Wemm register char *b; 1395c2aa98e2SPeter Wemm { 1396c2aa98e2SPeter Wemm int la; 1397c2aa98e2SPeter Wemm int lb; 1398c2aa98e2SPeter Wemm int c; 1399c2aa98e2SPeter Wemm 1400c2aa98e2SPeter Wemm la = strlen(a); 1401c2aa98e2SPeter Wemm lb = strlen(b); 1402c2aa98e2SPeter Wemm c = *a; 1403c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 1404c2aa98e2SPeter Wemm c = tolower(c); 1405c2aa98e2SPeter Wemm for (; lb-- >= la; b++) 1406c2aa98e2SPeter Wemm { 1407c2aa98e2SPeter Wemm if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c) 1408c2aa98e2SPeter Wemm continue; 1409c2aa98e2SPeter Wemm if (strncasecmp(a, b, la) == 0) 1410c2aa98e2SPeter Wemm return TRUE; 1411c2aa98e2SPeter Wemm } 1412c2aa98e2SPeter Wemm return FALSE; 1413c2aa98e2SPeter Wemm } 1414c2aa98e2SPeter Wemm /* 1415c2aa98e2SPeter Wemm ** CHECKFD012 -- check low numbered file descriptors 1416c2aa98e2SPeter Wemm ** 1417c2aa98e2SPeter Wemm ** File descriptors 0, 1, and 2 should be open at all times. 1418c2aa98e2SPeter Wemm ** This routine verifies that, and fixes it if not true. 1419c2aa98e2SPeter Wemm ** 1420c2aa98e2SPeter Wemm ** Parameters: 1421c2aa98e2SPeter Wemm ** where -- a tag printed if the assertion failed 1422c2aa98e2SPeter Wemm ** 1423c2aa98e2SPeter Wemm ** Returns: 1424c2aa98e2SPeter Wemm ** none 1425c2aa98e2SPeter Wemm */ 1426c2aa98e2SPeter Wemm 1427c2aa98e2SPeter Wemm void 1428c2aa98e2SPeter Wemm checkfd012(where) 1429c2aa98e2SPeter Wemm char *where; 1430c2aa98e2SPeter Wemm { 1431c2aa98e2SPeter Wemm #if XDEBUG 1432c2aa98e2SPeter Wemm register int i; 1433c2aa98e2SPeter Wemm 1434c2aa98e2SPeter Wemm for (i = 0; i < 3; i++) 1435c2aa98e2SPeter Wemm fill_fd(i, where); 1436c2aa98e2SPeter Wemm #endif /* XDEBUG */ 1437c2aa98e2SPeter Wemm } 1438c2aa98e2SPeter Wemm /* 1439c2aa98e2SPeter Wemm ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1440c2aa98e2SPeter Wemm ** 1441c2aa98e2SPeter Wemm ** Parameters: 1442c2aa98e2SPeter Wemm ** fd -- file descriptor to check. 1443c2aa98e2SPeter Wemm ** where -- tag to print on failure. 1444c2aa98e2SPeter Wemm ** 1445c2aa98e2SPeter Wemm ** Returns: 1446c2aa98e2SPeter Wemm ** none. 1447c2aa98e2SPeter Wemm */ 1448c2aa98e2SPeter Wemm 1449c2aa98e2SPeter Wemm void 1450c2aa98e2SPeter Wemm checkfdopen(fd, where) 1451c2aa98e2SPeter Wemm int fd; 1452c2aa98e2SPeter Wemm char *where; 1453c2aa98e2SPeter Wemm { 1454c2aa98e2SPeter Wemm #if XDEBUG 1455c2aa98e2SPeter Wemm struct stat st; 1456c2aa98e2SPeter Wemm 1457c2aa98e2SPeter Wemm if (fstat(fd, &st) < 0 && errno == EBADF) 1458c2aa98e2SPeter Wemm { 1459c2aa98e2SPeter Wemm syserr("checkfdopen(%d): %s not open as expected!", fd, where); 1460c2aa98e2SPeter Wemm printopenfds(TRUE); 1461c2aa98e2SPeter Wemm } 146206f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1463c2aa98e2SPeter Wemm } 1464c2aa98e2SPeter Wemm /* 1465c2aa98e2SPeter Wemm ** CHECKFDS -- check for new or missing file descriptors 1466c2aa98e2SPeter Wemm ** 1467c2aa98e2SPeter Wemm ** Parameters: 1468c2aa98e2SPeter Wemm ** where -- tag for printing. If null, take a base line. 1469c2aa98e2SPeter Wemm ** 1470c2aa98e2SPeter Wemm ** Returns: 1471c2aa98e2SPeter Wemm ** none 1472c2aa98e2SPeter Wemm ** 1473c2aa98e2SPeter Wemm ** Side Effects: 1474c2aa98e2SPeter Wemm ** If where is set, shows changes since the last call. 1475c2aa98e2SPeter Wemm */ 1476c2aa98e2SPeter Wemm 1477c2aa98e2SPeter Wemm void 1478c2aa98e2SPeter Wemm checkfds(where) 1479c2aa98e2SPeter Wemm char *where; 1480c2aa98e2SPeter Wemm { 1481c2aa98e2SPeter Wemm int maxfd; 1482c2aa98e2SPeter Wemm register int fd; 1483c2aa98e2SPeter Wemm bool printhdr = TRUE; 1484c2aa98e2SPeter Wemm int save_errno = errno; 148506f25ae9SGregory Neil Shapiro static BITMAP256 baseline; 1486c2aa98e2SPeter Wemm extern int DtableSize; 1487c2aa98e2SPeter Wemm 1488c2aa98e2SPeter Wemm if (DtableSize > 256) 1489c2aa98e2SPeter Wemm maxfd = 256; 1490c2aa98e2SPeter Wemm else 1491c2aa98e2SPeter Wemm maxfd = DtableSize; 1492c2aa98e2SPeter Wemm if (where == NULL) 1493c2aa98e2SPeter Wemm clrbitmap(baseline); 1494c2aa98e2SPeter Wemm 1495c2aa98e2SPeter Wemm for (fd = 0; fd < maxfd; fd++) 1496c2aa98e2SPeter Wemm { 1497c2aa98e2SPeter Wemm struct stat stbuf; 1498c2aa98e2SPeter Wemm 1499c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 1500c2aa98e2SPeter Wemm { 1501c2aa98e2SPeter Wemm if (!bitnset(fd, baseline)) 1502c2aa98e2SPeter Wemm continue; 1503c2aa98e2SPeter Wemm clrbitn(fd, baseline); 1504c2aa98e2SPeter Wemm } 1505c2aa98e2SPeter Wemm else if (!bitnset(fd, baseline)) 1506c2aa98e2SPeter Wemm setbitn(fd, baseline); 1507c2aa98e2SPeter Wemm else 1508c2aa98e2SPeter Wemm continue; 1509c2aa98e2SPeter Wemm 1510c2aa98e2SPeter Wemm /* file state has changed */ 1511c2aa98e2SPeter Wemm if (where == NULL) 1512c2aa98e2SPeter Wemm continue; 1513c2aa98e2SPeter Wemm if (printhdr) 1514c2aa98e2SPeter Wemm { 1515c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1516c2aa98e2SPeter Wemm "%s: changed fds:", 1517c2aa98e2SPeter Wemm where); 1518c2aa98e2SPeter Wemm printhdr = FALSE; 1519c2aa98e2SPeter Wemm } 1520c2aa98e2SPeter Wemm dumpfd(fd, TRUE, TRUE); 1521c2aa98e2SPeter Wemm } 1522c2aa98e2SPeter Wemm errno = save_errno; 1523c2aa98e2SPeter Wemm } 1524c2aa98e2SPeter Wemm /* 1525c2aa98e2SPeter Wemm ** PRINTOPENFDS -- print the open file descriptors (for debugging) 1526c2aa98e2SPeter Wemm ** 1527c2aa98e2SPeter Wemm ** Parameters: 1528c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog; otherwise 1529c2aa98e2SPeter Wemm ** print for debugging. 1530c2aa98e2SPeter Wemm ** 1531c2aa98e2SPeter Wemm ** Returns: 1532c2aa98e2SPeter Wemm ** none. 1533c2aa98e2SPeter Wemm */ 1534c2aa98e2SPeter Wemm 153506f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 1536c2aa98e2SPeter Wemm # include <arpa/inet.h> 153706f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 1538c2aa98e2SPeter Wemm 1539c2aa98e2SPeter Wemm void 1540c2aa98e2SPeter Wemm printopenfds(logit) 1541c2aa98e2SPeter Wemm bool logit; 1542c2aa98e2SPeter Wemm { 1543c2aa98e2SPeter Wemm register int fd; 1544c2aa98e2SPeter Wemm extern int DtableSize; 1545c2aa98e2SPeter Wemm 1546c2aa98e2SPeter Wemm for (fd = 0; fd < DtableSize; fd++) 1547c2aa98e2SPeter Wemm dumpfd(fd, FALSE, logit); 1548c2aa98e2SPeter Wemm } 1549c2aa98e2SPeter Wemm /* 1550c2aa98e2SPeter Wemm ** DUMPFD -- dump a file descriptor 1551c2aa98e2SPeter Wemm ** 1552c2aa98e2SPeter Wemm ** Parameters: 1553c2aa98e2SPeter Wemm ** fd -- the file descriptor to dump. 1554c2aa98e2SPeter Wemm ** printclosed -- if set, print a notification even if 1555c2aa98e2SPeter Wemm ** it is closed; otherwise print nothing. 1556c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog instead of stdout. 1557c2aa98e2SPeter Wemm */ 1558c2aa98e2SPeter Wemm 1559c2aa98e2SPeter Wemm void 1560c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit) 1561c2aa98e2SPeter Wemm int fd; 1562c2aa98e2SPeter Wemm bool printclosed; 1563c2aa98e2SPeter Wemm bool logit; 1564c2aa98e2SPeter Wemm { 1565c2aa98e2SPeter Wemm register char *p; 1566c2aa98e2SPeter Wemm char *hp; 1567c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1568c2aa98e2SPeter Wemm SOCKADDR sa; 156906f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1570c2aa98e2SPeter Wemm auto SOCKADDR_LEN_T slen; 1571c2aa98e2SPeter Wemm int i; 1572c2aa98e2SPeter Wemm #if STAT64 > 0 1573c2aa98e2SPeter Wemm struct stat64 st; 157406f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1575c2aa98e2SPeter Wemm struct stat st; 157606f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1577c2aa98e2SPeter Wemm char buf[200]; 1578c2aa98e2SPeter Wemm 1579c2aa98e2SPeter Wemm p = buf; 1580c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 1581c2aa98e2SPeter Wemm p += strlen(p); 1582c2aa98e2SPeter Wemm 1583c2aa98e2SPeter Wemm if ( 1584c2aa98e2SPeter Wemm #if STAT64 > 0 1585c2aa98e2SPeter Wemm fstat64(fd, &st) 158606f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 1587c2aa98e2SPeter Wemm fstat(fd, &st) 158806f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 1589c2aa98e2SPeter Wemm < 0) 1590c2aa98e2SPeter Wemm { 1591c2aa98e2SPeter Wemm if (errno != EBADF) 1592c2aa98e2SPeter Wemm { 1593c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)", 1594c2aa98e2SPeter Wemm errstring(errno)); 1595c2aa98e2SPeter Wemm goto printit; 1596c2aa98e2SPeter Wemm } 1597c2aa98e2SPeter Wemm else if (printclosed) 1598c2aa98e2SPeter Wemm { 1599c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CLOSED"); 1600c2aa98e2SPeter Wemm goto printit; 1601c2aa98e2SPeter Wemm } 1602c2aa98e2SPeter Wemm return; 1603c2aa98e2SPeter Wemm } 1604c2aa98e2SPeter Wemm 1605c2aa98e2SPeter Wemm i = fcntl(fd, F_GETFL, NULL); 1606c2aa98e2SPeter Wemm if (i != -1) 1607c2aa98e2SPeter Wemm { 1608c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 1609c2aa98e2SPeter Wemm p += strlen(p); 1610c2aa98e2SPeter Wemm } 1611c2aa98e2SPeter Wemm 161206f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "mode=%o: ", (int) st.st_mode); 1613c2aa98e2SPeter Wemm p += strlen(p); 1614c2aa98e2SPeter Wemm switch (st.st_mode & S_IFMT) 1615c2aa98e2SPeter Wemm { 1616c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1617c2aa98e2SPeter Wemm case S_IFSOCK: 1618c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "SOCK "); 1619c2aa98e2SPeter Wemm p += strlen(p); 162006f25ae9SGregory Neil Shapiro memset(&sa, '\0', sizeof sa); 1621c2aa98e2SPeter Wemm slen = sizeof sa; 1622c2aa98e2SPeter Wemm if (getsockname(fd, &sa.sa, &slen) < 0) 162306f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "(%s)", 162406f25ae9SGregory Neil Shapiro errstring(errno)); 1625c2aa98e2SPeter Wemm else 1626c2aa98e2SPeter Wemm { 1627c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 162806f25ae9SGregory Neil Shapiro if (hp == NULL) 162906f25ae9SGregory Neil Shapiro { 163006f25ae9SGregory Neil Shapiro /* EMPTY */ 163106f25ae9SGregory Neil Shapiro /* do nothing */ 163206f25ae9SGregory Neil Shapiro } 163306f25ae9SGregory Neil Shapiro # if NETINET 163406f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 1635c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s/%d", 1636c2aa98e2SPeter Wemm hp, ntohs(sa.sin.sin_port)); 163706f25ae9SGregory Neil Shapiro # endif /* NETINET */ 163806f25ae9SGregory Neil Shapiro # if NETINET6 163906f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 164006f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "%s/%d", 164106f25ae9SGregory Neil Shapiro hp, ntohs(sa.sin6.sin6_port)); 164206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1643c2aa98e2SPeter Wemm else 1644c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s", hp); 1645c2aa98e2SPeter Wemm } 1646c2aa98e2SPeter Wemm p += strlen(p); 1647c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "->"); 1648c2aa98e2SPeter Wemm p += strlen(p); 1649c2aa98e2SPeter Wemm slen = sizeof sa; 1650c2aa98e2SPeter Wemm if (getpeername(fd, &sa.sa, &slen) < 0) 1651c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno)); 1652c2aa98e2SPeter Wemm else 1653c2aa98e2SPeter Wemm { 1654c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 165506f25ae9SGregory Neil Shapiro if (hp == NULL) 165606f25ae9SGregory Neil Shapiro { 165706f25ae9SGregory Neil Shapiro /* EMPTY */ 165806f25ae9SGregory Neil Shapiro /* do nothing */ 165906f25ae9SGregory Neil Shapiro } 166006f25ae9SGregory Neil Shapiro # if NETINET 166106f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET) 1662c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s/%d", 1663c2aa98e2SPeter Wemm hp, ntohs(sa.sin.sin_port)); 166406f25ae9SGregory Neil Shapiro # endif /* NETINET */ 166506f25ae9SGregory Neil Shapiro # if NETINET6 166606f25ae9SGregory Neil Shapiro else if (sa.sa.sa_family == AF_INET6) 166706f25ae9SGregory Neil Shapiro snprintf(p, SPACELEFT(buf, p), "%s/%d", 166806f25ae9SGregory Neil Shapiro hp, ntohs(sa.sin6.sin6_port)); 166906f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 1670c2aa98e2SPeter Wemm else 1671c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s", hp); 1672c2aa98e2SPeter Wemm } 1673c2aa98e2SPeter Wemm break; 167406f25ae9SGregory Neil Shapiro #endif /* S_IFSOCK */ 1675c2aa98e2SPeter Wemm 1676c2aa98e2SPeter Wemm case S_IFCHR: 1677c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CHR: "); 1678c2aa98e2SPeter Wemm p += strlen(p); 1679c2aa98e2SPeter Wemm goto defprint; 1680c2aa98e2SPeter Wemm 1681c2aa98e2SPeter Wemm case S_IFBLK: 1682c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "BLK: "); 1683c2aa98e2SPeter Wemm p += strlen(p); 1684c2aa98e2SPeter Wemm goto defprint; 1685c2aa98e2SPeter Wemm 1686c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 1687c2aa98e2SPeter Wemm case S_IFIFO: 1688c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "FIFO: "); 1689c2aa98e2SPeter Wemm p += strlen(p); 1690c2aa98e2SPeter Wemm goto defprint; 169106f25ae9SGregory Neil Shapiro #endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 1692c2aa98e2SPeter Wemm 1693c2aa98e2SPeter Wemm #ifdef S_IFDIR 1694c2aa98e2SPeter Wemm case S_IFDIR: 1695c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "DIR: "); 1696c2aa98e2SPeter Wemm p += strlen(p); 1697c2aa98e2SPeter Wemm goto defprint; 169806f25ae9SGregory Neil Shapiro #endif /* S_IFDIR */ 1699c2aa98e2SPeter Wemm 1700c2aa98e2SPeter Wemm #ifdef S_IFLNK 1701c2aa98e2SPeter Wemm case S_IFLNK: 1702c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "LNK: "); 1703c2aa98e2SPeter Wemm p += strlen(p); 1704c2aa98e2SPeter Wemm goto defprint; 170506f25ae9SGregory Neil Shapiro #endif /* S_IFLNK */ 1706c2aa98e2SPeter Wemm 1707c2aa98e2SPeter Wemm default: 1708c2aa98e2SPeter Wemm defprint: 170906f25ae9SGregory Neil Shapiro /*CONSTCOND*/ 1710c2aa98e2SPeter Wemm if (sizeof st.st_ino > sizeof (long)) 1711c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), 1712c2aa98e2SPeter Wemm "dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ", 1713c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 1714c2aa98e2SPeter Wemm quad_to_string(st.st_ino), 171506f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 171606f25ae9SGregory Neil Shapiro (int) st.st_gid); 1717c2aa98e2SPeter Wemm else 1718c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), 1719c2aa98e2SPeter Wemm "dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ", 1720c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 1721c2aa98e2SPeter Wemm (unsigned long) st.st_ino, 172206f25ae9SGregory Neil Shapiro (int) st.st_nlink, (int) st.st_uid, 172306f25ae9SGregory Neil Shapiro (int) st.st_gid); 172406f25ae9SGregory Neil Shapiro /*CONSTCOND*/ 1725c2aa98e2SPeter Wemm if (sizeof st.st_size > sizeof (long)) 1726c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "size=%s", 1727c2aa98e2SPeter Wemm quad_to_string(st.st_size)); 1728c2aa98e2SPeter Wemm else 1729c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "size=%lu", 1730c2aa98e2SPeter Wemm (unsigned long) st.st_size); 1731c2aa98e2SPeter Wemm break; 1732c2aa98e2SPeter Wemm } 1733c2aa98e2SPeter Wemm 1734c2aa98e2SPeter Wemm printit: 1735c2aa98e2SPeter Wemm if (logit) 1736c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 1737c2aa98e2SPeter Wemm "%.800s", buf); 1738c2aa98e2SPeter Wemm else 1739c2aa98e2SPeter Wemm printf("%s\n", buf); 1740c2aa98e2SPeter Wemm } 1741c2aa98e2SPeter Wemm /* 1742c2aa98e2SPeter Wemm ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1743c2aa98e2SPeter Wemm ** 1744c2aa98e2SPeter Wemm ** Parameters: 1745c2aa98e2SPeter Wemm ** host -- the host to shorten (stripped in place). 1746c2aa98e2SPeter Wemm ** 1747c2aa98e2SPeter Wemm ** Returns: 1748c2aa98e2SPeter Wemm ** none. 1749c2aa98e2SPeter Wemm */ 1750c2aa98e2SPeter Wemm 1751c2aa98e2SPeter Wemm void 1752c2aa98e2SPeter Wemm shorten_hostname(host) 1753c2aa98e2SPeter Wemm char host[]; 1754c2aa98e2SPeter Wemm { 1755c2aa98e2SPeter Wemm register char *p; 1756c2aa98e2SPeter Wemm char *mydom; 1757c2aa98e2SPeter Wemm int i; 1758c2aa98e2SPeter Wemm bool canon = FALSE; 1759c2aa98e2SPeter Wemm 1760c2aa98e2SPeter Wemm /* strip off final dot */ 1761c2aa98e2SPeter Wemm p = &host[strlen(host) - 1]; 1762c2aa98e2SPeter Wemm if (*p == '.') 1763c2aa98e2SPeter Wemm { 1764c2aa98e2SPeter Wemm *p = '\0'; 1765c2aa98e2SPeter Wemm canon = TRUE; 1766c2aa98e2SPeter Wemm } 1767c2aa98e2SPeter Wemm 1768c2aa98e2SPeter Wemm /* see if there is any domain at all -- if not, we are done */ 1769c2aa98e2SPeter Wemm p = strchr(host, '.'); 1770c2aa98e2SPeter Wemm if (p == NULL) 1771c2aa98e2SPeter Wemm return; 1772c2aa98e2SPeter Wemm 1773c2aa98e2SPeter Wemm /* yes, we have a domain -- see if it looks like us */ 1774c2aa98e2SPeter Wemm mydom = macvalue('m', CurEnv); 1775c2aa98e2SPeter Wemm if (mydom == NULL) 1776c2aa98e2SPeter Wemm mydom = ""; 1777c2aa98e2SPeter Wemm i = strlen(++p); 1778c2aa98e2SPeter Wemm if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 && 1779c2aa98e2SPeter Wemm (mydom[i] == '.' || mydom[i] == '\0')) 1780c2aa98e2SPeter Wemm *--p = '\0'; 1781c2aa98e2SPeter Wemm } 1782c2aa98e2SPeter Wemm /* 1783c2aa98e2SPeter Wemm ** PROG_OPEN -- open a program for reading 1784c2aa98e2SPeter Wemm ** 1785c2aa98e2SPeter Wemm ** Parameters: 1786c2aa98e2SPeter Wemm ** argv -- the argument list. 1787c2aa98e2SPeter Wemm ** pfd -- pointer to a place to store the file descriptor. 1788c2aa98e2SPeter Wemm ** e -- the current envelope. 1789c2aa98e2SPeter Wemm ** 1790c2aa98e2SPeter Wemm ** Returns: 1791c2aa98e2SPeter Wemm ** pid of the process -- -1 if it failed. 1792c2aa98e2SPeter Wemm */ 1793c2aa98e2SPeter Wemm 1794c2aa98e2SPeter Wemm int 1795c2aa98e2SPeter Wemm prog_open(argv, pfd, e) 1796c2aa98e2SPeter Wemm char **argv; 1797c2aa98e2SPeter Wemm int *pfd; 1798c2aa98e2SPeter Wemm ENVELOPE *e; 1799c2aa98e2SPeter Wemm { 1800c2aa98e2SPeter Wemm int pid; 1801c2aa98e2SPeter Wemm int i; 180206f25ae9SGregory Neil Shapiro int save_errno; 1803c2aa98e2SPeter Wemm int fdv[2]; 1804c2aa98e2SPeter Wemm char *p, *q; 1805c2aa98e2SPeter Wemm char buf[MAXLINE + 1]; 1806c2aa98e2SPeter Wemm extern int DtableSize; 1807c2aa98e2SPeter Wemm 1808c2aa98e2SPeter Wemm if (pipe(fdv) < 0) 1809c2aa98e2SPeter Wemm { 1810c2aa98e2SPeter Wemm syserr("%s: cannot create pipe for stdout", argv[0]); 1811c2aa98e2SPeter Wemm return -1; 1812c2aa98e2SPeter Wemm } 1813c2aa98e2SPeter Wemm pid = fork(); 1814c2aa98e2SPeter Wemm if (pid < 0) 1815c2aa98e2SPeter Wemm { 1816c2aa98e2SPeter Wemm syserr("%s: cannot fork", argv[0]); 181706f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 181806f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1819c2aa98e2SPeter Wemm return -1; 1820c2aa98e2SPeter Wemm } 1821c2aa98e2SPeter Wemm if (pid > 0) 1822c2aa98e2SPeter Wemm { 1823c2aa98e2SPeter Wemm /* parent */ 182406f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1825c2aa98e2SPeter Wemm *pfd = fdv[0]; 1826c2aa98e2SPeter Wemm return pid; 1827c2aa98e2SPeter Wemm } 1828c2aa98e2SPeter Wemm 1829c2aa98e2SPeter Wemm /* child -- close stdin */ 183006f25ae9SGregory Neil Shapiro (void) close(0); 1831c2aa98e2SPeter Wemm 1832c2aa98e2SPeter Wemm /* stdout goes back to parent */ 183306f25ae9SGregory Neil Shapiro (void) close(fdv[0]); 1834c2aa98e2SPeter Wemm if (dup2(fdv[1], 1) < 0) 1835c2aa98e2SPeter Wemm { 1836c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stdout", argv[0]); 1837c2aa98e2SPeter Wemm _exit(EX_OSERR); 1838c2aa98e2SPeter Wemm } 183906f25ae9SGregory Neil Shapiro (void) close(fdv[1]); 1840c2aa98e2SPeter Wemm 1841c2aa98e2SPeter Wemm /* stderr goes to transcript if available */ 1842c2aa98e2SPeter Wemm if (e->e_xfp != NULL) 1843c2aa98e2SPeter Wemm { 184406f25ae9SGregory Neil Shapiro int xfd; 184506f25ae9SGregory Neil Shapiro 184606f25ae9SGregory Neil Shapiro xfd = fileno(e->e_xfp); 184706f25ae9SGregory Neil Shapiro if (xfd >= 0 && dup2(xfd, 2) < 0) 1848c2aa98e2SPeter Wemm { 1849c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stderr", argv[0]); 1850c2aa98e2SPeter Wemm _exit(EX_OSERR); 1851c2aa98e2SPeter Wemm } 1852c2aa98e2SPeter Wemm } 1853c2aa98e2SPeter Wemm 1854c2aa98e2SPeter Wemm /* this process has no right to the queue file */ 1855c2aa98e2SPeter Wemm if (e->e_lockfp != NULL) 185606f25ae9SGregory Neil Shapiro (void) close(fileno(e->e_lockfp)); 185706f25ae9SGregory Neil Shapiro 185806f25ae9SGregory Neil Shapiro /* chroot to the program mailer directory, if defined */ 185906f25ae9SGregory Neil Shapiro if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) 186006f25ae9SGregory Neil Shapiro { 186106f25ae9SGregory Neil Shapiro expand(ProgMailer->m_rootdir, buf, sizeof buf, e); 186206f25ae9SGregory Neil Shapiro if (chroot(buf) < 0) 186306f25ae9SGregory Neil Shapiro { 186406f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chroot(%s)", buf); 186506f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 186606f25ae9SGregory Neil Shapiro } 186706f25ae9SGregory Neil Shapiro if (chdir("/") < 0) 186806f25ae9SGregory Neil Shapiro { 186906f25ae9SGregory Neil Shapiro syserr("prog_open: cannot chdir(/)"); 187006f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 187106f25ae9SGregory Neil Shapiro } 187206f25ae9SGregory Neil Shapiro } 1873c2aa98e2SPeter Wemm 1874c2aa98e2SPeter Wemm /* run as default user */ 1875c2aa98e2SPeter Wemm endpwent(); 1876c2aa98e2SPeter Wemm if (setgid(DefGid) < 0 && geteuid() == 0) 187706f25ae9SGregory Neil Shapiro { 1878c2aa98e2SPeter Wemm syserr("prog_open: setgid(%ld) failed", (long) DefGid); 187906f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 188006f25ae9SGregory Neil Shapiro } 1881c2aa98e2SPeter Wemm if (setuid(DefUid) < 0 && geteuid() == 0) 188206f25ae9SGregory Neil Shapiro { 1883c2aa98e2SPeter Wemm syserr("prog_open: setuid(%ld) failed", (long) DefUid); 188406f25ae9SGregory Neil Shapiro exit(EX_TEMPFAIL); 188506f25ae9SGregory Neil Shapiro } 1886c2aa98e2SPeter Wemm 1887c2aa98e2SPeter Wemm /* run in some directory */ 1888c2aa98e2SPeter Wemm if (ProgMailer != NULL) 1889c2aa98e2SPeter Wemm p = ProgMailer->m_execdir; 1890c2aa98e2SPeter Wemm else 1891c2aa98e2SPeter Wemm p = NULL; 1892c2aa98e2SPeter Wemm for (; p != NULL; p = q) 1893c2aa98e2SPeter Wemm { 1894c2aa98e2SPeter Wemm q = strchr(p, ':'); 1895c2aa98e2SPeter Wemm if (q != NULL) 1896c2aa98e2SPeter Wemm *q = '\0'; 1897c2aa98e2SPeter Wemm expand(p, buf, sizeof buf, e); 1898c2aa98e2SPeter Wemm if (q != NULL) 1899c2aa98e2SPeter Wemm *q++ = ':'; 1900c2aa98e2SPeter Wemm if (buf[0] != '\0' && chdir(buf) >= 0) 1901c2aa98e2SPeter Wemm break; 1902c2aa98e2SPeter Wemm } 1903c2aa98e2SPeter Wemm if (p == NULL) 1904c2aa98e2SPeter Wemm { 1905c2aa98e2SPeter Wemm /* backup directories */ 1906c2aa98e2SPeter Wemm if (chdir("/tmp") < 0) 1907c2aa98e2SPeter Wemm (void) chdir("/"); 1908c2aa98e2SPeter Wemm } 1909c2aa98e2SPeter Wemm 1910c2aa98e2SPeter Wemm /* arrange for all the files to be closed */ 1911c2aa98e2SPeter Wemm for (i = 3; i < DtableSize; i++) 1912c2aa98e2SPeter Wemm { 1913c2aa98e2SPeter Wemm register int j; 1914c2aa98e2SPeter Wemm 1915c2aa98e2SPeter Wemm if ((j = fcntl(i, F_GETFD, 0)) != -1) 191606f25ae9SGregory Neil Shapiro (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 1917c2aa98e2SPeter Wemm } 1918c2aa98e2SPeter Wemm 1919c2aa98e2SPeter Wemm /* now exec the process */ 192006f25ae9SGregory Neil Shapiro (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 1921c2aa98e2SPeter Wemm 1922c2aa98e2SPeter Wemm /* woops! failed */ 192306f25ae9SGregory Neil Shapiro save_errno = errno; 1924c2aa98e2SPeter Wemm syserr("%s: cannot exec", argv[0]); 192506f25ae9SGregory Neil Shapiro if (transienterror(save_errno)) 1926c2aa98e2SPeter Wemm _exit(EX_OSERR); 1927c2aa98e2SPeter Wemm _exit(EX_CONFIG); 1928c2aa98e2SPeter Wemm return -1; /* avoid compiler warning on IRIX */ 1929c2aa98e2SPeter Wemm } 1930c2aa98e2SPeter Wemm /* 1931c2aa98e2SPeter Wemm ** GET_COLUMN -- look up a Column in a line buffer 1932c2aa98e2SPeter Wemm ** 1933c2aa98e2SPeter Wemm ** Parameters: 1934c2aa98e2SPeter Wemm ** line -- the raw text line to search. 1935c2aa98e2SPeter Wemm ** col -- the column number to fetch. 1936c2aa98e2SPeter Wemm ** delim -- the delimiter between columns. If null, 1937c2aa98e2SPeter Wemm ** use white space. 1938c2aa98e2SPeter Wemm ** buf -- the output buffer. 1939c2aa98e2SPeter Wemm ** buflen -- the length of buf. 1940c2aa98e2SPeter Wemm ** 1941c2aa98e2SPeter Wemm ** Returns: 1942c2aa98e2SPeter Wemm ** buf if successful. 1943c2aa98e2SPeter Wemm ** NULL otherwise. 1944c2aa98e2SPeter Wemm */ 1945c2aa98e2SPeter Wemm 1946c2aa98e2SPeter Wemm char * 1947c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen) 1948c2aa98e2SPeter Wemm char line[]; 1949c2aa98e2SPeter Wemm int col; 195006f25ae9SGregory Neil Shapiro int delim; 1951c2aa98e2SPeter Wemm char buf[]; 1952c2aa98e2SPeter Wemm int buflen; 1953c2aa98e2SPeter Wemm { 1954c2aa98e2SPeter Wemm char *p; 1955c2aa98e2SPeter Wemm char *begin, *end; 1956c2aa98e2SPeter Wemm int i; 1957c2aa98e2SPeter Wemm char delimbuf[4]; 1958c2aa98e2SPeter Wemm 195906f25ae9SGregory Neil Shapiro if ((char)delim == '\0') 196006f25ae9SGregory Neil Shapiro (void) strlcpy(delimbuf, "\n\t ", sizeof delimbuf); 1961c2aa98e2SPeter Wemm else 1962c2aa98e2SPeter Wemm { 196306f25ae9SGregory Neil Shapiro delimbuf[0] = (char)delim; 1964c2aa98e2SPeter Wemm delimbuf[1] = '\0'; 1965c2aa98e2SPeter Wemm } 1966c2aa98e2SPeter Wemm 1967c2aa98e2SPeter Wemm p = line; 1968c2aa98e2SPeter Wemm if (*p == '\0') 1969c2aa98e2SPeter Wemm return NULL; /* line empty */ 197006f25ae9SGregory Neil Shapiro if (*p == (char)delim && col == 0) 1971c2aa98e2SPeter Wemm return NULL; /* first column empty */ 1972c2aa98e2SPeter Wemm 1973c2aa98e2SPeter Wemm begin = line; 1974c2aa98e2SPeter Wemm 197506f25ae9SGregory Neil Shapiro if (col == 0 && (char)delim == '\0') 1976c2aa98e2SPeter Wemm { 1977c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 1978c2aa98e2SPeter Wemm begin++; 1979c2aa98e2SPeter Wemm } 1980c2aa98e2SPeter Wemm 1981c2aa98e2SPeter Wemm for (i = 0; i < col; i++) 1982c2aa98e2SPeter Wemm { 1983c2aa98e2SPeter Wemm if ((begin = strpbrk(begin, delimbuf)) == NULL) 1984c2aa98e2SPeter Wemm return NULL; /* no such column */ 1985c2aa98e2SPeter Wemm begin++; 198606f25ae9SGregory Neil Shapiro if ((char)delim == '\0') 1987c2aa98e2SPeter Wemm { 1988c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 1989c2aa98e2SPeter Wemm begin++; 1990c2aa98e2SPeter Wemm } 1991c2aa98e2SPeter Wemm } 1992c2aa98e2SPeter Wemm 1993c2aa98e2SPeter Wemm end = strpbrk(begin, delimbuf); 1994c2aa98e2SPeter Wemm if (end == NULL) 1995c2aa98e2SPeter Wemm i = strlen(begin); 1996c2aa98e2SPeter Wemm else 1997c2aa98e2SPeter Wemm i = end - begin; 1998c2aa98e2SPeter Wemm if (i >= buflen) 1999c2aa98e2SPeter Wemm i = buflen - 1; 200006f25ae9SGregory Neil Shapiro (void) strlcpy(buf, begin, i + 1); 2001c2aa98e2SPeter Wemm return buf; 2002c2aa98e2SPeter Wemm } 2003c2aa98e2SPeter Wemm /* 2004c2aa98e2SPeter Wemm ** CLEANSTRCPY -- copy string keeping out bogus characters 2005c2aa98e2SPeter Wemm ** 2006c2aa98e2SPeter Wemm ** Parameters: 2007c2aa98e2SPeter Wemm ** t -- "to" string. 2008c2aa98e2SPeter Wemm ** f -- "from" string. 2009c2aa98e2SPeter Wemm ** l -- length of space available in "to" string. 2010c2aa98e2SPeter Wemm ** 2011c2aa98e2SPeter Wemm ** Returns: 2012c2aa98e2SPeter Wemm ** none. 2013c2aa98e2SPeter Wemm */ 2014c2aa98e2SPeter Wemm 2015c2aa98e2SPeter Wemm void 2016c2aa98e2SPeter Wemm cleanstrcpy(t, f, l) 2017c2aa98e2SPeter Wemm register char *t; 2018c2aa98e2SPeter Wemm register char *f; 2019c2aa98e2SPeter Wemm int l; 2020c2aa98e2SPeter Wemm { 2021c2aa98e2SPeter Wemm /* check for newlines and log if necessary */ 2022c2aa98e2SPeter Wemm (void) denlstring(f, TRUE, TRUE); 2023c2aa98e2SPeter Wemm 202406f25ae9SGregory Neil Shapiro if (l <= 0) 202506f25ae9SGregory Neil Shapiro syserr("!cleanstrcpy: length == 0"); 202606f25ae9SGregory Neil Shapiro 2027c2aa98e2SPeter Wemm l--; 2028c2aa98e2SPeter Wemm while (l > 0 && *f != '\0') 2029c2aa98e2SPeter Wemm { 2030c2aa98e2SPeter Wemm if (isascii(*f) && 2031c2aa98e2SPeter Wemm (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 2032c2aa98e2SPeter Wemm { 2033c2aa98e2SPeter Wemm l--; 2034c2aa98e2SPeter Wemm *t++ = *f; 2035c2aa98e2SPeter Wemm } 2036c2aa98e2SPeter Wemm f++; 2037c2aa98e2SPeter Wemm } 2038c2aa98e2SPeter Wemm *t = '\0'; 2039c2aa98e2SPeter Wemm } 204006f25ae9SGregory Neil Shapiro 2041c2aa98e2SPeter Wemm /* 2042c2aa98e2SPeter Wemm ** DENLSTRING -- convert newlines in a string to spaces 2043c2aa98e2SPeter Wemm ** 2044c2aa98e2SPeter Wemm ** Parameters: 2045c2aa98e2SPeter Wemm ** s -- the input string 2046c2aa98e2SPeter Wemm ** strict -- if set, don't permit continuation lines. 2047c2aa98e2SPeter Wemm ** logattacks -- if set, log attempted attacks. 2048c2aa98e2SPeter Wemm ** 2049c2aa98e2SPeter Wemm ** Returns: 2050c2aa98e2SPeter Wemm ** A pointer to a version of the string with newlines 2051c2aa98e2SPeter Wemm ** mapped to spaces. This should be copied. 2052c2aa98e2SPeter Wemm */ 2053c2aa98e2SPeter Wemm 2054c2aa98e2SPeter Wemm char * 2055c2aa98e2SPeter Wemm denlstring(s, strict, logattacks) 2056c2aa98e2SPeter Wemm char *s; 2057c2aa98e2SPeter Wemm bool strict; 2058c2aa98e2SPeter Wemm bool logattacks; 2059c2aa98e2SPeter Wemm { 2060c2aa98e2SPeter Wemm register char *p; 2061c2aa98e2SPeter Wemm int l; 2062c2aa98e2SPeter Wemm static char *bp = NULL; 2063c2aa98e2SPeter Wemm static int bl = 0; 2064c2aa98e2SPeter Wemm 2065c2aa98e2SPeter Wemm p = s; 2066c2aa98e2SPeter Wemm while ((p = strchr(p, '\n')) != NULL) 2067c2aa98e2SPeter Wemm if (strict || (*++p != ' ' && *p != '\t')) 2068c2aa98e2SPeter Wemm break; 2069c2aa98e2SPeter Wemm if (p == NULL) 2070c2aa98e2SPeter Wemm return s; 2071c2aa98e2SPeter Wemm 2072c2aa98e2SPeter Wemm l = strlen(s) + 1; 2073c2aa98e2SPeter Wemm if (bl < l) 2074c2aa98e2SPeter Wemm { 2075c2aa98e2SPeter Wemm /* allocate more space */ 2076c2aa98e2SPeter Wemm if (bp != NULL) 2077c2aa98e2SPeter Wemm free(bp); 2078c2aa98e2SPeter Wemm bp = xalloc(l); 2079c2aa98e2SPeter Wemm bl = l; 2080c2aa98e2SPeter Wemm } 208106f25ae9SGregory Neil Shapiro (void) strlcpy(bp, s, l); 2082c2aa98e2SPeter Wemm for (p = bp; (p = strchr(p, '\n')) != NULL; ) 2083c2aa98e2SPeter Wemm *p++ = ' '; 2084c2aa98e2SPeter Wemm 2085c2aa98e2SPeter Wemm if (logattacks) 2086c2aa98e2SPeter Wemm { 2087c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 2088c2aa98e2SPeter Wemm "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 2089c2aa98e2SPeter Wemm RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 2090c2aa98e2SPeter Wemm shortenstring(bp, MAXSHORTSTR)); 2091c2aa98e2SPeter Wemm } 2092c2aa98e2SPeter Wemm 2093c2aa98e2SPeter Wemm return bp; 2094c2aa98e2SPeter Wemm } 2095c2aa98e2SPeter Wemm /* 2096c2aa98e2SPeter Wemm ** PATH_IS_DIR -- check to see if file exists and is a directory. 2097c2aa98e2SPeter Wemm ** 2098c2aa98e2SPeter Wemm ** There are some additional checks for security violations in 2099c2aa98e2SPeter Wemm ** here. This routine is intended to be used for the host status 2100c2aa98e2SPeter Wemm ** support. 2101c2aa98e2SPeter Wemm ** 2102c2aa98e2SPeter Wemm ** Parameters: 2103c2aa98e2SPeter Wemm ** pathname -- pathname to check for directory-ness. 2104c2aa98e2SPeter Wemm ** createflag -- if set, create directory if needed. 2105c2aa98e2SPeter Wemm ** 2106c2aa98e2SPeter Wemm ** Returns: 2107c2aa98e2SPeter Wemm ** TRUE -- if the indicated pathname is a directory 2108c2aa98e2SPeter Wemm ** FALSE -- otherwise 2109c2aa98e2SPeter Wemm */ 2110c2aa98e2SPeter Wemm 2111c2aa98e2SPeter Wemm int 2112c2aa98e2SPeter Wemm path_is_dir(pathname, createflag) 2113c2aa98e2SPeter Wemm char *pathname; 2114c2aa98e2SPeter Wemm bool createflag; 2115c2aa98e2SPeter Wemm { 2116c2aa98e2SPeter Wemm struct stat statbuf; 2117c2aa98e2SPeter Wemm 2118c2aa98e2SPeter Wemm #if HASLSTAT 2119c2aa98e2SPeter Wemm if (lstat(pathname, &statbuf) < 0) 212006f25ae9SGregory Neil Shapiro #else /* HASLSTAT */ 2121c2aa98e2SPeter Wemm if (stat(pathname, &statbuf) < 0) 212206f25ae9SGregory Neil Shapiro #endif /* HASLSTAT */ 2123c2aa98e2SPeter Wemm { 2124c2aa98e2SPeter Wemm if (errno != ENOENT || !createflag) 2125c2aa98e2SPeter Wemm return FALSE; 2126c2aa98e2SPeter Wemm if (mkdir(pathname, 0755) < 0) 2127c2aa98e2SPeter Wemm return FALSE; 2128c2aa98e2SPeter Wemm return TRUE; 2129c2aa98e2SPeter Wemm } 2130c2aa98e2SPeter Wemm if (!S_ISDIR(statbuf.st_mode)) 2131c2aa98e2SPeter Wemm { 2132c2aa98e2SPeter Wemm errno = ENOTDIR; 2133c2aa98e2SPeter Wemm return FALSE; 2134c2aa98e2SPeter Wemm } 2135c2aa98e2SPeter Wemm 2136c2aa98e2SPeter Wemm /* security: don't allow writable directories */ 2137c2aa98e2SPeter Wemm if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 2138c2aa98e2SPeter Wemm { 2139c2aa98e2SPeter Wemm errno = EACCES; 2140c2aa98e2SPeter Wemm return FALSE; 2141c2aa98e2SPeter Wemm } 2142c2aa98e2SPeter Wemm 2143c2aa98e2SPeter Wemm return TRUE; 2144c2aa98e2SPeter Wemm } 2145c2aa98e2SPeter Wemm /* 2146c2aa98e2SPeter Wemm ** PROC_LIST_ADD -- add process id to list of our children 2147c2aa98e2SPeter Wemm ** 2148c2aa98e2SPeter Wemm ** Parameters: 2149c2aa98e2SPeter Wemm ** pid -- pid to add to list. 215006f25ae9SGregory Neil Shapiro ** task -- task of pid. 215106f25ae9SGregory Neil Shapiro ** type -- type of process. 2152c2aa98e2SPeter Wemm ** 2153c2aa98e2SPeter Wemm ** Returns: 2154c2aa98e2SPeter Wemm ** none 2155c2aa98e2SPeter Wemm */ 2156c2aa98e2SPeter Wemm 2157065a643dSPeter Wemm static struct procs *ProcListVec = NULL; 2158c2aa98e2SPeter Wemm static int ProcListSize = 0; 2159c2aa98e2SPeter Wemm 2160c2aa98e2SPeter Wemm void 216106f25ae9SGregory Neil Shapiro proc_list_add(pid, task, type) 2162c2aa98e2SPeter Wemm pid_t pid; 2163065a643dSPeter Wemm char *task; 216406f25ae9SGregory Neil Shapiro int type; 2165c2aa98e2SPeter Wemm { 2166c2aa98e2SPeter Wemm int i; 2167c2aa98e2SPeter Wemm 2168c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2169c2aa98e2SPeter Wemm { 2170065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2171c2aa98e2SPeter Wemm break; 2172c2aa98e2SPeter Wemm } 2173c2aa98e2SPeter Wemm if (i >= ProcListSize) 2174c2aa98e2SPeter Wemm { 2175c2aa98e2SPeter Wemm /* probe the existing vector to avoid growing infinitely */ 2176c2aa98e2SPeter Wemm proc_list_probe(); 2177c2aa98e2SPeter Wemm 2178c2aa98e2SPeter Wemm /* now scan again */ 2179c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2180c2aa98e2SPeter Wemm { 2181065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2182c2aa98e2SPeter Wemm break; 2183c2aa98e2SPeter Wemm } 2184c2aa98e2SPeter Wemm } 2185c2aa98e2SPeter Wemm if (i >= ProcListSize) 2186c2aa98e2SPeter Wemm { 2187c2aa98e2SPeter Wemm /* grow process list */ 2188065a643dSPeter Wemm struct procs *npv; 2189c2aa98e2SPeter Wemm 219006f25ae9SGregory Neil Shapiro npv = (struct procs *) xalloc((sizeof *npv) * 219106f25ae9SGregory Neil Shapiro (ProcListSize + PROC_LIST_SEG)); 2192c2aa98e2SPeter Wemm if (ProcListSize > 0) 2193c2aa98e2SPeter Wemm { 219406f25ae9SGregory Neil Shapiro memmove(npv, ProcListVec, 219506f25ae9SGregory Neil Shapiro ProcListSize * sizeof (struct procs)); 2196c2aa98e2SPeter Wemm free(ProcListVec); 2197c2aa98e2SPeter Wemm } 2198c2aa98e2SPeter Wemm for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 2199065a643dSPeter Wemm { 2200065a643dSPeter Wemm npv[i].proc_pid = NO_PID; 2201065a643dSPeter Wemm npv[i].proc_task = NULL; 220206f25ae9SGregory Neil Shapiro npv[i].proc_type = PROC_NONE; 2203065a643dSPeter Wemm } 2204c2aa98e2SPeter Wemm i = ProcListSize; 2205c2aa98e2SPeter Wemm ProcListSize += PROC_LIST_SEG; 2206c2aa98e2SPeter Wemm ProcListVec = npv; 2207c2aa98e2SPeter Wemm } 2208065a643dSPeter Wemm ProcListVec[i].proc_pid = pid; 220906f25ae9SGregory Neil Shapiro if (ProcListVec[i].proc_task != NULL) 221006f25ae9SGregory Neil Shapiro free(ProcListVec[i].proc_task); 2211065a643dSPeter Wemm ProcListVec[i].proc_task = newstr(task); 221206f25ae9SGregory Neil Shapiro ProcListVec[i].proc_type = type; 2213065a643dSPeter Wemm 2214065a643dSPeter Wemm /* if process adding itself, it's not a child */ 2215065a643dSPeter Wemm if (pid != getpid()) 2216c2aa98e2SPeter Wemm CurChildren++; 2217c2aa98e2SPeter Wemm } 2218c2aa98e2SPeter Wemm /* 2219065a643dSPeter Wemm ** PROC_LIST_SET -- set pid task in process list 2220065a643dSPeter Wemm ** 2221065a643dSPeter Wemm ** Parameters: 2222065a643dSPeter Wemm ** pid -- pid to set 2223065a643dSPeter Wemm ** task -- task of pid 2224065a643dSPeter Wemm ** 2225065a643dSPeter Wemm ** Returns: 2226065a643dSPeter Wemm ** none. 2227065a643dSPeter Wemm */ 2228065a643dSPeter Wemm 2229065a643dSPeter Wemm void 2230065a643dSPeter Wemm proc_list_set(pid, task) 2231065a643dSPeter Wemm pid_t pid; 2232065a643dSPeter Wemm char *task; 2233065a643dSPeter Wemm { 2234065a643dSPeter Wemm int i; 2235065a643dSPeter Wemm 2236065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2237065a643dSPeter Wemm { 2238065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2239065a643dSPeter Wemm { 2240065a643dSPeter Wemm if (ProcListVec[i].proc_task != NULL) 2241065a643dSPeter Wemm free(ProcListVec[i].proc_task); 2242065a643dSPeter Wemm ProcListVec[i].proc_task = newstr(task); 2243065a643dSPeter Wemm break; 2244065a643dSPeter Wemm } 2245065a643dSPeter Wemm } 2246065a643dSPeter Wemm } 2247065a643dSPeter Wemm /* 2248c2aa98e2SPeter Wemm ** PROC_LIST_DROP -- drop pid from process list 2249c2aa98e2SPeter Wemm ** 2250c2aa98e2SPeter Wemm ** Parameters: 2251c2aa98e2SPeter Wemm ** pid -- pid to drop 2252c2aa98e2SPeter Wemm ** 2253c2aa98e2SPeter Wemm ** Returns: 225406f25ae9SGregory Neil Shapiro ** type of process 2255c2aa98e2SPeter Wemm */ 2256c2aa98e2SPeter Wemm 225706f25ae9SGregory Neil Shapiro int 2258c2aa98e2SPeter Wemm proc_list_drop(pid) 2259c2aa98e2SPeter Wemm pid_t pid; 2260c2aa98e2SPeter Wemm { 2261c2aa98e2SPeter Wemm int i; 226206f25ae9SGregory Neil Shapiro int type = PROC_NONE; 2263c2aa98e2SPeter Wemm 2264c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 2265c2aa98e2SPeter Wemm { 2266065a643dSPeter Wemm if (ProcListVec[i].proc_pid == pid) 2267c2aa98e2SPeter Wemm { 2268065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 226906f25ae9SGregory Neil Shapiro type = ProcListVec[i].proc_type; 2270c2aa98e2SPeter Wemm break; 2271c2aa98e2SPeter Wemm } 2272c2aa98e2SPeter Wemm } 2273c2aa98e2SPeter Wemm if (CurChildren > 0) 2274c2aa98e2SPeter Wemm CurChildren--; 227506f25ae9SGregory Neil Shapiro 227606f25ae9SGregory Neil Shapiro 227706f25ae9SGregory Neil Shapiro return type; 2278c2aa98e2SPeter Wemm } 2279c2aa98e2SPeter Wemm /* 2280c2aa98e2SPeter Wemm ** PROC_LIST_CLEAR -- clear the process list 2281c2aa98e2SPeter Wemm ** 2282c2aa98e2SPeter Wemm ** Parameters: 2283c2aa98e2SPeter Wemm ** none. 2284c2aa98e2SPeter Wemm ** 2285c2aa98e2SPeter Wemm ** Returns: 2286c2aa98e2SPeter Wemm ** none. 2287c2aa98e2SPeter Wemm */ 2288c2aa98e2SPeter Wemm 2289c2aa98e2SPeter Wemm void 2290c2aa98e2SPeter Wemm proc_list_clear() 2291c2aa98e2SPeter Wemm { 2292c2aa98e2SPeter Wemm int i; 2293c2aa98e2SPeter Wemm 2294065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2295065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2296065a643dSPeter Wemm { 2297065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2298065a643dSPeter Wemm } 2299c2aa98e2SPeter Wemm CurChildren = 0; 2300c2aa98e2SPeter Wemm } 2301c2aa98e2SPeter Wemm /* 2302c2aa98e2SPeter Wemm ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 2303c2aa98e2SPeter Wemm ** 2304c2aa98e2SPeter Wemm ** Parameters: 2305c2aa98e2SPeter Wemm ** none 2306c2aa98e2SPeter Wemm ** 2307c2aa98e2SPeter Wemm ** Returns: 2308c2aa98e2SPeter Wemm ** none 2309c2aa98e2SPeter Wemm */ 2310c2aa98e2SPeter Wemm 2311c2aa98e2SPeter Wemm void 2312c2aa98e2SPeter Wemm proc_list_probe() 2313c2aa98e2SPeter Wemm { 2314c2aa98e2SPeter Wemm int i; 2315c2aa98e2SPeter Wemm 2316065a643dSPeter Wemm /* start from 1 since 0 is the daemon itself */ 2317065a643dSPeter Wemm for (i = 1; i < ProcListSize; i++) 2318c2aa98e2SPeter Wemm { 2319065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2320c2aa98e2SPeter Wemm continue; 2321065a643dSPeter Wemm if (kill(ProcListVec[i].proc_pid, 0) < 0) 2322c2aa98e2SPeter Wemm { 2323c2aa98e2SPeter Wemm if (LogLevel > 3) 2324c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 2325c2aa98e2SPeter Wemm "proc_list_probe: lost pid %d", 2326065a643dSPeter Wemm (int) ProcListVec[i].proc_pid); 2327065a643dSPeter Wemm ProcListVec[i].proc_pid = NO_PID; 2328c2aa98e2SPeter Wemm CurChildren--; 2329c2aa98e2SPeter Wemm } 2330c2aa98e2SPeter Wemm } 2331c2aa98e2SPeter Wemm if (CurChildren < 0) 2332c2aa98e2SPeter Wemm CurChildren = 0; 2333c2aa98e2SPeter Wemm } 2334c2aa98e2SPeter Wemm /* 2335065a643dSPeter Wemm ** PROC_LIST_DISPLAY -- display the process list 2336065a643dSPeter Wemm ** 2337065a643dSPeter Wemm ** Parameters: 2338065a643dSPeter Wemm ** out -- output file pointer 2339065a643dSPeter Wemm ** 2340065a643dSPeter Wemm ** Returns: 2341065a643dSPeter Wemm ** none. 2342065a643dSPeter Wemm */ 2343065a643dSPeter Wemm 2344065a643dSPeter Wemm void 2345065a643dSPeter Wemm proc_list_display(out) 2346065a643dSPeter Wemm FILE *out; 2347065a643dSPeter Wemm { 2348065a643dSPeter Wemm int i; 2349065a643dSPeter Wemm 2350065a643dSPeter Wemm for (i = 0; i < ProcListSize; i++) 2351065a643dSPeter Wemm { 2352065a643dSPeter Wemm if (ProcListVec[i].proc_pid == NO_PID) 2353065a643dSPeter Wemm continue; 2354065a643dSPeter Wemm 2355065a643dSPeter Wemm fprintf(out, "%d %s%s\n", (int) ProcListVec[i].proc_pid, 2356065a643dSPeter Wemm ProcListVec[i].proc_task != NULL ? 2357065a643dSPeter Wemm ProcListVec[i].proc_task : "(unknown)", 2358065a643dSPeter Wemm (OpMode == MD_SMTP || 2359065a643dSPeter Wemm OpMode == MD_DAEMON || 2360065a643dSPeter Wemm OpMode == MD_ARPAFTP) ? "\r" : ""); 2361065a643dSPeter Wemm } 2362065a643dSPeter Wemm } 2363065a643dSPeter Wemm /* 2364c2aa98e2SPeter Wemm ** SM_STRCASECMP -- 8-bit clean version of strcasecmp 2365c2aa98e2SPeter Wemm ** 2366c2aa98e2SPeter Wemm ** Thank you, vendors, for making this all necessary. 2367c2aa98e2SPeter Wemm */ 2368c2aa98e2SPeter Wemm 2369c2aa98e2SPeter Wemm /* 2370c2aa98e2SPeter Wemm * Copyright (c) 1987, 1993 2371c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 2372c2aa98e2SPeter Wemm * 2373c2aa98e2SPeter Wemm * Redistribution and use in source and binary forms, with or without 2374c2aa98e2SPeter Wemm * modification, are permitted provided that the following conditions 2375c2aa98e2SPeter Wemm * are met: 2376c2aa98e2SPeter Wemm * 1. Redistributions of source code must retain the above copyright 2377c2aa98e2SPeter Wemm * notice, this list of conditions and the following disclaimer. 2378c2aa98e2SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 2379c2aa98e2SPeter Wemm * notice, this list of conditions and the following disclaimer in the 2380c2aa98e2SPeter Wemm * documentation and/or other materials provided with the distribution. 2381c2aa98e2SPeter Wemm * 3. All advertising materials mentioning features or use of this software 2382c2aa98e2SPeter Wemm * must display the following acknowledgement: 2383c2aa98e2SPeter Wemm * This product includes software developed by the University of 2384c2aa98e2SPeter Wemm * California, Berkeley and its contributors. 2385c2aa98e2SPeter Wemm * 4. Neither the name of the University nor the names of its contributors 2386c2aa98e2SPeter Wemm * may be used to endorse or promote products derived from this software 2387c2aa98e2SPeter Wemm * without specific prior written permission. 2388c2aa98e2SPeter Wemm * 2389c2aa98e2SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2390c2aa98e2SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2391c2aa98e2SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2392c2aa98e2SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2393c2aa98e2SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2394c2aa98e2SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2395c2aa98e2SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2396c2aa98e2SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2397c2aa98e2SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2398c2aa98e2SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2399c2aa98e2SPeter Wemm * SUCH DAMAGE. 2400c2aa98e2SPeter Wemm */ 2401c2aa98e2SPeter Wemm 2402c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint) 2403c2aa98e2SPeter Wemm static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; 240406f25ae9SGregory Neil Shapiro #endif /* defined(LIBC_SCCS) && !defined(lint) */ 2405c2aa98e2SPeter Wemm 2406c2aa98e2SPeter Wemm /* 2407c2aa98e2SPeter Wemm * This array is designed for mapping upper and lower case letter 2408c2aa98e2SPeter Wemm * together for a case independent comparison. The mappings are 2409c2aa98e2SPeter Wemm * based upon ascii character sequences. 2410c2aa98e2SPeter Wemm */ 2411c2aa98e2SPeter Wemm static const u_char charmap[] = { 2412c2aa98e2SPeter Wemm 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 2413c2aa98e2SPeter Wemm 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 2414c2aa98e2SPeter Wemm 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 2415c2aa98e2SPeter Wemm 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 2416c2aa98e2SPeter Wemm 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 2417c2aa98e2SPeter Wemm 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 2418c2aa98e2SPeter Wemm 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 2419c2aa98e2SPeter Wemm 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 2420c2aa98e2SPeter Wemm 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 2421c2aa98e2SPeter Wemm 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 2422c2aa98e2SPeter Wemm 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 2423c2aa98e2SPeter Wemm 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, 2424c2aa98e2SPeter Wemm 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 2425c2aa98e2SPeter Wemm 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 2426c2aa98e2SPeter Wemm 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 2427c2aa98e2SPeter Wemm 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, 2428c2aa98e2SPeter Wemm 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 2429c2aa98e2SPeter Wemm 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 2430c2aa98e2SPeter Wemm 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 2431c2aa98e2SPeter Wemm 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 2432c2aa98e2SPeter Wemm 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 2433c2aa98e2SPeter Wemm 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 2434c2aa98e2SPeter Wemm 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 2435c2aa98e2SPeter Wemm 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 2436c2aa98e2SPeter Wemm 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 2437c2aa98e2SPeter Wemm 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 2438c2aa98e2SPeter Wemm 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 2439c2aa98e2SPeter Wemm 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 2440c2aa98e2SPeter Wemm 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 2441c2aa98e2SPeter Wemm 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 2442c2aa98e2SPeter Wemm 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 2443c2aa98e2SPeter Wemm 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, 2444c2aa98e2SPeter Wemm }; 2445c2aa98e2SPeter Wemm 2446c2aa98e2SPeter Wemm int 2447c2aa98e2SPeter Wemm sm_strcasecmp(s1, s2) 2448c2aa98e2SPeter Wemm const char *s1, *s2; 2449c2aa98e2SPeter Wemm { 2450c2aa98e2SPeter Wemm register const u_char *cm = charmap, 2451c2aa98e2SPeter Wemm *us1 = (const u_char *)s1, 2452c2aa98e2SPeter Wemm *us2 = (const u_char *)s2; 2453c2aa98e2SPeter Wemm 2454c2aa98e2SPeter Wemm while (cm[*us1] == cm[*us2++]) 2455c2aa98e2SPeter Wemm if (*us1++ == '\0') 245606f25ae9SGregory Neil Shapiro return 0; 2457c2aa98e2SPeter Wemm return (cm[*us1] - cm[*--us2]); 2458c2aa98e2SPeter Wemm } 2459c2aa98e2SPeter Wemm 2460c2aa98e2SPeter Wemm int 2461c2aa98e2SPeter Wemm sm_strncasecmp(s1, s2, n) 2462c2aa98e2SPeter Wemm const char *s1, *s2; 2463c2aa98e2SPeter Wemm register size_t n; 2464c2aa98e2SPeter Wemm { 2465c2aa98e2SPeter Wemm if (n != 0) { 2466c2aa98e2SPeter Wemm register const u_char *cm = charmap, 2467c2aa98e2SPeter Wemm *us1 = (const u_char *)s1, 2468c2aa98e2SPeter Wemm *us2 = (const u_char *)s2; 2469c2aa98e2SPeter Wemm 2470c2aa98e2SPeter Wemm do { 2471c2aa98e2SPeter Wemm if (cm[*us1] != cm[*us2++]) 2472c2aa98e2SPeter Wemm return (cm[*us1] - cm[*--us2]); 2473c2aa98e2SPeter Wemm if (*us1++ == '\0') 2474c2aa98e2SPeter Wemm break; 2475c2aa98e2SPeter Wemm } while (--n != 0); 2476c2aa98e2SPeter Wemm } 247706f25ae9SGregory Neil Shapiro return 0; 2478c2aa98e2SPeter Wemm } 2479