1c2aa98e2SPeter Wemm /* 2c2aa98e2SPeter Wemm * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 5c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 6c2aa98e2SPeter Wemm * 7c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 8c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 9c2aa98e2SPeter Wemm * the sendmail distribution. 10c2aa98e2SPeter Wemm * 11c2aa98e2SPeter Wemm */ 12c2aa98e2SPeter Wemm 13c2aa98e2SPeter Wemm #ifndef lint 14c2aa98e2SPeter Wemm static char sccsid[] = "@(#)util.c 8.159 (Berkeley) 7/1/98"; 15c2aa98e2SPeter Wemm #endif /* not lint */ 16c2aa98e2SPeter Wemm 17c2aa98e2SPeter Wemm # include "sendmail.h" 18c2aa98e2SPeter Wemm # include <sysexits.h> 19c2aa98e2SPeter Wemm /* 20c2aa98e2SPeter Wemm ** STRIPQUOTES -- Strip quotes & quote bits from a string. 21c2aa98e2SPeter Wemm ** 22c2aa98e2SPeter Wemm ** Runs through a string and strips off unquoted quote 23c2aa98e2SPeter Wemm ** characters and quote bits. This is done in place. 24c2aa98e2SPeter Wemm ** 25c2aa98e2SPeter Wemm ** Parameters: 26c2aa98e2SPeter Wemm ** s -- the string to strip. 27c2aa98e2SPeter Wemm ** 28c2aa98e2SPeter Wemm ** Returns: 29c2aa98e2SPeter Wemm ** none. 30c2aa98e2SPeter Wemm ** 31c2aa98e2SPeter Wemm ** Side Effects: 32c2aa98e2SPeter Wemm ** none. 33c2aa98e2SPeter Wemm ** 34c2aa98e2SPeter Wemm ** Called By: 35c2aa98e2SPeter Wemm ** deliver 36c2aa98e2SPeter Wemm */ 37c2aa98e2SPeter Wemm 38c2aa98e2SPeter Wemm void 39c2aa98e2SPeter Wemm stripquotes(s) 40c2aa98e2SPeter Wemm char *s; 41c2aa98e2SPeter Wemm { 42c2aa98e2SPeter Wemm register char *p; 43c2aa98e2SPeter Wemm register char *q; 44c2aa98e2SPeter Wemm register char c; 45c2aa98e2SPeter Wemm 46c2aa98e2SPeter Wemm if (s == NULL) 47c2aa98e2SPeter Wemm return; 48c2aa98e2SPeter Wemm 49c2aa98e2SPeter Wemm p = q = s; 50c2aa98e2SPeter Wemm do 51c2aa98e2SPeter Wemm { 52c2aa98e2SPeter Wemm c = *p++; 53c2aa98e2SPeter Wemm if (c == '\\') 54c2aa98e2SPeter Wemm c = *p++; 55c2aa98e2SPeter Wemm else if (c == '"') 56c2aa98e2SPeter Wemm continue; 57c2aa98e2SPeter Wemm *q++ = c; 58c2aa98e2SPeter Wemm } while (c != '\0'); 59c2aa98e2SPeter Wemm } 60c2aa98e2SPeter Wemm /* 61c2aa98e2SPeter Wemm ** ADDQUOTES -- Adds quotes & quote bits to a string. 62c2aa98e2SPeter Wemm ** 63c2aa98e2SPeter Wemm ** Runs through a string and adds characters and quote bits. 64c2aa98e2SPeter Wemm ** 65c2aa98e2SPeter Wemm ** Parameters: 66c2aa98e2SPeter Wemm ** s -- the string to modify. 67c2aa98e2SPeter Wemm ** 68c2aa98e2SPeter Wemm ** Returns: 69c2aa98e2SPeter Wemm ** pointer to quoted string. 70c2aa98e2SPeter Wemm ** 71c2aa98e2SPeter Wemm ** Side Effects: 72c2aa98e2SPeter Wemm ** none. 73c2aa98e2SPeter Wemm ** 74c2aa98e2SPeter Wemm */ 75c2aa98e2SPeter Wemm 76c2aa98e2SPeter Wemm char * 77c2aa98e2SPeter Wemm addquotes(s) 78c2aa98e2SPeter Wemm char *s; 79c2aa98e2SPeter Wemm { 80c2aa98e2SPeter Wemm int len = 0; 81c2aa98e2SPeter Wemm char c; 82c2aa98e2SPeter Wemm char *p = s, *q, *r; 83c2aa98e2SPeter Wemm 84c2aa98e2SPeter Wemm if (s == NULL) 85c2aa98e2SPeter Wemm return NULL; 86c2aa98e2SPeter Wemm 87c2aa98e2SPeter Wemm /* Find length of quoted string */ 88c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 89c2aa98e2SPeter Wemm { 90c2aa98e2SPeter Wemm len++; 91c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 92c2aa98e2SPeter Wemm len++; 93c2aa98e2SPeter Wemm } 94c2aa98e2SPeter Wemm 95c2aa98e2SPeter Wemm q = r = xalloc(len + 3); 96c2aa98e2SPeter Wemm p = s; 97c2aa98e2SPeter Wemm 98c2aa98e2SPeter Wemm /* add leading quote */ 99c2aa98e2SPeter Wemm *q++ = '"'; 100c2aa98e2SPeter Wemm while ((c = *p++) != '\0') 101c2aa98e2SPeter Wemm { 102c2aa98e2SPeter Wemm /* quote \ or " */ 103c2aa98e2SPeter Wemm if (c == '\\' || c == '"') 104c2aa98e2SPeter Wemm *q++ = '\\'; 105c2aa98e2SPeter Wemm *q++ = c; 106c2aa98e2SPeter Wemm } 107c2aa98e2SPeter Wemm *q++ = '"'; 108c2aa98e2SPeter Wemm *q = '\0'; 109c2aa98e2SPeter Wemm return r; 110c2aa98e2SPeter Wemm } 111c2aa98e2SPeter Wemm /* 112c2aa98e2SPeter Wemm ** RFC822_STRING -- Checks string for proper RFC822 string quoting. 113c2aa98e2SPeter Wemm ** 114c2aa98e2SPeter Wemm ** Runs through a string and verifies RFC822 special characters 115c2aa98e2SPeter Wemm ** are only found inside comments, quoted strings, or backslash 116c2aa98e2SPeter Wemm ** escaped. Also verified balanced quotes and parenthesis. 117c2aa98e2SPeter Wemm ** 118c2aa98e2SPeter Wemm ** Parameters: 119c2aa98e2SPeter Wemm ** s -- the string to modify. 120c2aa98e2SPeter Wemm ** 121c2aa98e2SPeter Wemm ** Returns: 122c2aa98e2SPeter Wemm ** TRUE -- if the string is RFC822 compliant. 123c2aa98e2SPeter Wemm ** FALSE -- if the string is not RFC822 compliant. 124c2aa98e2SPeter Wemm ** 125c2aa98e2SPeter Wemm ** Side Effects: 126c2aa98e2SPeter Wemm ** none. 127c2aa98e2SPeter Wemm ** 128c2aa98e2SPeter Wemm */ 129c2aa98e2SPeter Wemm 130c2aa98e2SPeter Wemm bool 131c2aa98e2SPeter Wemm rfc822_string(s) 132c2aa98e2SPeter Wemm char *s; 133c2aa98e2SPeter Wemm { 134c2aa98e2SPeter Wemm bool quoted = FALSE; 135c2aa98e2SPeter Wemm int commentlev = 0; 136c2aa98e2SPeter Wemm char *c = s; 137c2aa98e2SPeter Wemm 138c2aa98e2SPeter Wemm if (s == NULL) 139c2aa98e2SPeter Wemm return FALSE; 140c2aa98e2SPeter Wemm 141c2aa98e2SPeter Wemm while (*c != '\0') 142c2aa98e2SPeter Wemm { 143c2aa98e2SPeter Wemm /* escaped character */ 144c2aa98e2SPeter Wemm if (*c == '\\') 145c2aa98e2SPeter Wemm { 146c2aa98e2SPeter Wemm c++; 147c2aa98e2SPeter Wemm if (*c == '\0') 148c2aa98e2SPeter Wemm return FALSE; 149c2aa98e2SPeter Wemm } 150c2aa98e2SPeter Wemm else if (commentlev == 0 && *c == '"') 151c2aa98e2SPeter Wemm quoted = !quoted; 152c2aa98e2SPeter Wemm else if (!quoted) 153c2aa98e2SPeter Wemm { 154c2aa98e2SPeter Wemm if (*c == ')') 155c2aa98e2SPeter Wemm { 156c2aa98e2SPeter Wemm /* unbalanced ')' */ 157c2aa98e2SPeter Wemm if (commentlev == 0) 158c2aa98e2SPeter Wemm return FALSE; 159c2aa98e2SPeter Wemm else 160c2aa98e2SPeter Wemm commentlev--; 161c2aa98e2SPeter Wemm } 162c2aa98e2SPeter Wemm else if (*c == '(') 163c2aa98e2SPeter Wemm commentlev++; 164c2aa98e2SPeter Wemm else if (commentlev == 0 && 165c2aa98e2SPeter Wemm strchr(MustQuoteChars, *c) != NULL) 166c2aa98e2SPeter Wemm return FALSE; 167c2aa98e2SPeter Wemm } 168c2aa98e2SPeter Wemm c++; 169c2aa98e2SPeter Wemm } 170c2aa98e2SPeter Wemm /* unbalanced '"' or '(' */ 171c2aa98e2SPeter Wemm if (quoted || commentlev != 0) 172c2aa98e2SPeter Wemm return FALSE; 173c2aa98e2SPeter Wemm else 174c2aa98e2SPeter Wemm return TRUE; 175c2aa98e2SPeter Wemm } 176c2aa98e2SPeter Wemm /* 177c2aa98e2SPeter Wemm ** XALLOC -- Allocate memory and bitch wildly on failure. 178c2aa98e2SPeter Wemm ** 179c2aa98e2SPeter Wemm ** THIS IS A CLUDGE. This should be made to give a proper 180c2aa98e2SPeter Wemm ** error -- but after all, what can we do? 181c2aa98e2SPeter Wemm ** 182c2aa98e2SPeter Wemm ** Parameters: 183c2aa98e2SPeter Wemm ** sz -- size of area to allocate. 184c2aa98e2SPeter Wemm ** 185c2aa98e2SPeter Wemm ** Returns: 186c2aa98e2SPeter Wemm ** pointer to data region. 187c2aa98e2SPeter Wemm ** 188c2aa98e2SPeter Wemm ** Side Effects: 189c2aa98e2SPeter Wemm ** Memory is allocated. 190c2aa98e2SPeter Wemm */ 191c2aa98e2SPeter Wemm 192c2aa98e2SPeter Wemm char * 193c2aa98e2SPeter Wemm xalloc(sz) 194c2aa98e2SPeter Wemm register int sz; 195c2aa98e2SPeter Wemm { 196c2aa98e2SPeter Wemm register char *p; 197c2aa98e2SPeter Wemm 198c2aa98e2SPeter Wemm /* some systems can't handle size zero mallocs */ 199c2aa98e2SPeter Wemm if (sz <= 0) 200c2aa98e2SPeter Wemm sz = 1; 201c2aa98e2SPeter Wemm 202c2aa98e2SPeter Wemm p = malloc((unsigned) sz); 203c2aa98e2SPeter Wemm if (p == NULL) 204c2aa98e2SPeter Wemm { 205c2aa98e2SPeter Wemm syserr("!Out of memory!!"); 206c2aa98e2SPeter Wemm /* exit(EX_UNAVAILABLE); */ 207c2aa98e2SPeter Wemm } 208c2aa98e2SPeter Wemm return (p); 209c2aa98e2SPeter Wemm } 210c2aa98e2SPeter Wemm /* 211c2aa98e2SPeter Wemm ** COPYPLIST -- copy list of pointers. 212c2aa98e2SPeter Wemm ** 213c2aa98e2SPeter Wemm ** This routine is the equivalent of newstr for lists of 214c2aa98e2SPeter Wemm ** pointers. 215c2aa98e2SPeter Wemm ** 216c2aa98e2SPeter Wemm ** Parameters: 217c2aa98e2SPeter Wemm ** list -- list of pointers to copy. 218c2aa98e2SPeter Wemm ** Must be NULL terminated. 219c2aa98e2SPeter Wemm ** copycont -- if TRUE, copy the contents of the vector 220c2aa98e2SPeter Wemm ** (which must be a string) also. 221c2aa98e2SPeter Wemm ** 222c2aa98e2SPeter Wemm ** Returns: 223c2aa98e2SPeter Wemm ** a copy of 'list'. 224c2aa98e2SPeter Wemm ** 225c2aa98e2SPeter Wemm ** Side Effects: 226c2aa98e2SPeter Wemm ** none. 227c2aa98e2SPeter Wemm */ 228c2aa98e2SPeter Wemm 229c2aa98e2SPeter Wemm char ** 230c2aa98e2SPeter Wemm copyplist(list, copycont) 231c2aa98e2SPeter Wemm char **list; 232c2aa98e2SPeter Wemm bool copycont; 233c2aa98e2SPeter Wemm { 234c2aa98e2SPeter Wemm register char **vp; 235c2aa98e2SPeter Wemm register char **newvp; 236c2aa98e2SPeter Wemm 237c2aa98e2SPeter Wemm for (vp = list; *vp != NULL; vp++) 238c2aa98e2SPeter Wemm continue; 239c2aa98e2SPeter Wemm 240c2aa98e2SPeter Wemm vp++; 241c2aa98e2SPeter Wemm 242c2aa98e2SPeter Wemm newvp = (char **) xalloc((int) (vp - list) * sizeof *vp); 243c2aa98e2SPeter Wemm bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp); 244c2aa98e2SPeter Wemm 245c2aa98e2SPeter Wemm if (copycont) 246c2aa98e2SPeter Wemm { 247c2aa98e2SPeter Wemm for (vp = newvp; *vp != NULL; vp++) 248c2aa98e2SPeter Wemm *vp = newstr(*vp); 249c2aa98e2SPeter Wemm } 250c2aa98e2SPeter Wemm 251c2aa98e2SPeter Wemm return (newvp); 252c2aa98e2SPeter Wemm } 253c2aa98e2SPeter Wemm /* 254c2aa98e2SPeter Wemm ** COPYQUEUE -- copy address queue. 255c2aa98e2SPeter Wemm ** 256c2aa98e2SPeter Wemm ** This routine is the equivalent of newstr for address queues 257c2aa98e2SPeter Wemm ** addresses marked with QDONTSEND aren't copied 258c2aa98e2SPeter Wemm ** 259c2aa98e2SPeter Wemm ** Parameters: 260c2aa98e2SPeter Wemm ** addr -- list of address structures to copy. 261c2aa98e2SPeter Wemm ** 262c2aa98e2SPeter Wemm ** Returns: 263c2aa98e2SPeter Wemm ** a copy of 'addr'. 264c2aa98e2SPeter Wemm ** 265c2aa98e2SPeter Wemm ** Side Effects: 266c2aa98e2SPeter Wemm ** none. 267c2aa98e2SPeter Wemm */ 268c2aa98e2SPeter Wemm 269c2aa98e2SPeter Wemm ADDRESS * 270c2aa98e2SPeter Wemm copyqueue(addr) 271c2aa98e2SPeter Wemm ADDRESS *addr; 272c2aa98e2SPeter Wemm { 273c2aa98e2SPeter Wemm register ADDRESS *newaddr; 274c2aa98e2SPeter Wemm ADDRESS *ret; 275c2aa98e2SPeter Wemm register ADDRESS **tail = &ret; 276c2aa98e2SPeter Wemm 277c2aa98e2SPeter Wemm while (addr != NULL) 278c2aa98e2SPeter Wemm { 279c2aa98e2SPeter Wemm if (!bitset(QDONTSEND, addr->q_flags)) 280c2aa98e2SPeter Wemm { 281c2aa98e2SPeter Wemm newaddr = (ADDRESS *) xalloc(sizeof(ADDRESS)); 282c2aa98e2SPeter Wemm STRUCTCOPY(*addr, *newaddr); 283c2aa98e2SPeter Wemm *tail = newaddr; 284c2aa98e2SPeter Wemm tail = &newaddr->q_next; 285c2aa98e2SPeter Wemm } 286c2aa98e2SPeter Wemm addr = addr->q_next; 287c2aa98e2SPeter Wemm } 288c2aa98e2SPeter Wemm *tail = NULL; 289c2aa98e2SPeter Wemm 290c2aa98e2SPeter Wemm return ret; 291c2aa98e2SPeter Wemm } 292c2aa98e2SPeter Wemm /* 293c2aa98e2SPeter Wemm ** PRINTAV -- print argument vector. 294c2aa98e2SPeter Wemm ** 295c2aa98e2SPeter Wemm ** Parameters: 296c2aa98e2SPeter Wemm ** av -- argument vector. 297c2aa98e2SPeter Wemm ** 298c2aa98e2SPeter Wemm ** Returns: 299c2aa98e2SPeter Wemm ** none. 300c2aa98e2SPeter Wemm ** 301c2aa98e2SPeter Wemm ** Side Effects: 302c2aa98e2SPeter Wemm ** prints av. 303c2aa98e2SPeter Wemm */ 304c2aa98e2SPeter Wemm 305c2aa98e2SPeter Wemm void 306c2aa98e2SPeter Wemm printav(av) 307c2aa98e2SPeter Wemm register char **av; 308c2aa98e2SPeter Wemm { 309c2aa98e2SPeter Wemm while (*av != NULL) 310c2aa98e2SPeter Wemm { 311c2aa98e2SPeter Wemm if (tTd(0, 44)) 312c2aa98e2SPeter Wemm printf("\n\t%08lx=", (u_long) *av); 313c2aa98e2SPeter Wemm else 314c2aa98e2SPeter Wemm (void) putchar(' '); 315c2aa98e2SPeter Wemm xputs(*av++); 316c2aa98e2SPeter Wemm } 317c2aa98e2SPeter Wemm (void) putchar('\n'); 318c2aa98e2SPeter Wemm } 319c2aa98e2SPeter Wemm /* 320c2aa98e2SPeter Wemm ** LOWER -- turn letter into lower case. 321c2aa98e2SPeter Wemm ** 322c2aa98e2SPeter Wemm ** Parameters: 323c2aa98e2SPeter Wemm ** c -- character to turn into lower case. 324c2aa98e2SPeter Wemm ** 325c2aa98e2SPeter Wemm ** Returns: 326c2aa98e2SPeter Wemm ** c, in lower case. 327c2aa98e2SPeter Wemm ** 328c2aa98e2SPeter Wemm ** Side Effects: 329c2aa98e2SPeter Wemm ** none. 330c2aa98e2SPeter Wemm */ 331c2aa98e2SPeter Wemm 332c2aa98e2SPeter Wemm char 333c2aa98e2SPeter Wemm lower(c) 334c2aa98e2SPeter Wemm register char c; 335c2aa98e2SPeter Wemm { 336c2aa98e2SPeter Wemm return((isascii(c) && isupper(c)) ? tolower(c) : c); 337c2aa98e2SPeter Wemm } 338c2aa98e2SPeter Wemm /* 339c2aa98e2SPeter Wemm ** XPUTS -- put string doing control escapes. 340c2aa98e2SPeter Wemm ** 341c2aa98e2SPeter Wemm ** Parameters: 342c2aa98e2SPeter Wemm ** s -- string to put. 343c2aa98e2SPeter Wemm ** 344c2aa98e2SPeter Wemm ** Returns: 345c2aa98e2SPeter Wemm ** none. 346c2aa98e2SPeter Wemm ** 347c2aa98e2SPeter Wemm ** Side Effects: 348c2aa98e2SPeter Wemm ** output to stdout 349c2aa98e2SPeter Wemm */ 350c2aa98e2SPeter Wemm 351c2aa98e2SPeter Wemm void 352c2aa98e2SPeter Wemm xputs(s) 353c2aa98e2SPeter Wemm register const char *s; 354c2aa98e2SPeter Wemm { 355c2aa98e2SPeter Wemm register int c; 356c2aa98e2SPeter Wemm register struct metamac *mp; 357c2aa98e2SPeter Wemm bool shiftout = FALSE; 358c2aa98e2SPeter Wemm extern struct metamac MetaMacros[]; 359c2aa98e2SPeter Wemm 360c2aa98e2SPeter Wemm if (s == NULL) 361c2aa98e2SPeter Wemm { 362c2aa98e2SPeter Wemm printf("%s<null>%s", TermEscape.te_rv_on, TermEscape.te_rv_off); 363c2aa98e2SPeter Wemm return; 364c2aa98e2SPeter Wemm } 365c2aa98e2SPeter Wemm while ((c = (*s++ & 0377)) != '\0') 366c2aa98e2SPeter Wemm { 367c2aa98e2SPeter Wemm if (shiftout) 368c2aa98e2SPeter Wemm { 369c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_off); 370c2aa98e2SPeter Wemm shiftout = FALSE; 371c2aa98e2SPeter Wemm } 372c2aa98e2SPeter Wemm if (!isascii(c)) 373c2aa98e2SPeter Wemm { 374c2aa98e2SPeter Wemm if (c == MATCHREPL) 375c2aa98e2SPeter Wemm { 376c2aa98e2SPeter Wemm printf("%s$", TermEscape.te_rv_on); 377c2aa98e2SPeter Wemm shiftout = TRUE; 378c2aa98e2SPeter Wemm if (*s == '\0') 379c2aa98e2SPeter Wemm continue; 380c2aa98e2SPeter Wemm c = *s++ & 0377; 381c2aa98e2SPeter Wemm goto printchar; 382c2aa98e2SPeter Wemm } 383c2aa98e2SPeter Wemm if (c == MACROEXPAND || c == MACRODEXPAND) 384c2aa98e2SPeter Wemm { 385c2aa98e2SPeter Wemm printf("%s$", TermEscape.te_rv_on); 386c2aa98e2SPeter Wemm if (c == MACRODEXPAND) 387c2aa98e2SPeter Wemm putchar('&'); 388c2aa98e2SPeter Wemm shiftout = TRUE; 389c2aa98e2SPeter Wemm if (*s == '\0') 390c2aa98e2SPeter Wemm continue; 391c2aa98e2SPeter Wemm if (strchr("=~&?", *s) != NULL) 392c2aa98e2SPeter Wemm putchar(*s++); 393c2aa98e2SPeter Wemm if (bitset(0200, *s)) 394c2aa98e2SPeter Wemm printf("{%s}", macname(*s++ & 0377)); 395c2aa98e2SPeter Wemm else 396c2aa98e2SPeter Wemm printf("%c", *s++); 397c2aa98e2SPeter Wemm continue; 398c2aa98e2SPeter Wemm } 399c2aa98e2SPeter Wemm for (mp = MetaMacros; mp->metaname != '\0'; mp++) 400c2aa98e2SPeter Wemm { 401c2aa98e2SPeter Wemm if ((mp->metaval & 0377) == c) 402c2aa98e2SPeter Wemm { 403c2aa98e2SPeter Wemm printf("%s$%c", 404c2aa98e2SPeter Wemm TermEscape.te_rv_on, 405c2aa98e2SPeter Wemm mp->metaname); 406c2aa98e2SPeter Wemm shiftout = TRUE; 407c2aa98e2SPeter Wemm break; 408c2aa98e2SPeter Wemm } 409c2aa98e2SPeter Wemm } 410c2aa98e2SPeter Wemm if (c == MATCHCLASS || c == MATCHNCLASS) 411c2aa98e2SPeter Wemm { 412c2aa98e2SPeter Wemm if (bitset(0200, *s)) 413c2aa98e2SPeter Wemm printf("{%s}", macname(*s++ & 0377)); 414c2aa98e2SPeter Wemm else if (*s != '\0') 415c2aa98e2SPeter Wemm printf("%c", *s++); 416c2aa98e2SPeter Wemm } 417c2aa98e2SPeter Wemm if (mp->metaname != '\0') 418c2aa98e2SPeter Wemm continue; 419c2aa98e2SPeter Wemm 420c2aa98e2SPeter Wemm /* unrecognized meta character */ 421c2aa98e2SPeter Wemm printf("%sM-", TermEscape.te_rv_on); 422c2aa98e2SPeter Wemm shiftout = TRUE; 423c2aa98e2SPeter Wemm c &= 0177; 424c2aa98e2SPeter Wemm } 425c2aa98e2SPeter Wemm printchar: 426c2aa98e2SPeter Wemm if (isprint(c)) 427c2aa98e2SPeter Wemm { 428c2aa98e2SPeter Wemm putchar(c); 429c2aa98e2SPeter Wemm continue; 430c2aa98e2SPeter Wemm } 431c2aa98e2SPeter Wemm 432c2aa98e2SPeter Wemm /* wasn't a meta-macro -- find another way to print it */ 433c2aa98e2SPeter Wemm switch (c) 434c2aa98e2SPeter Wemm { 435c2aa98e2SPeter Wemm case '\n': 436c2aa98e2SPeter Wemm c = 'n'; 437c2aa98e2SPeter Wemm break; 438c2aa98e2SPeter Wemm 439c2aa98e2SPeter Wemm case '\r': 440c2aa98e2SPeter Wemm c = 'r'; 441c2aa98e2SPeter Wemm break; 442c2aa98e2SPeter Wemm 443c2aa98e2SPeter Wemm case '\t': 444c2aa98e2SPeter Wemm c = 't'; 445c2aa98e2SPeter Wemm break; 446c2aa98e2SPeter Wemm } 447c2aa98e2SPeter Wemm if (!shiftout) 448c2aa98e2SPeter Wemm { 449c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_on); 450c2aa98e2SPeter Wemm shiftout = TRUE; 451c2aa98e2SPeter Wemm } 452c2aa98e2SPeter Wemm if (isprint(c)) 453c2aa98e2SPeter Wemm { 454c2aa98e2SPeter Wemm (void) putchar('\\'); 455c2aa98e2SPeter Wemm (void) putchar(c); 456c2aa98e2SPeter Wemm } 457c2aa98e2SPeter Wemm else 458c2aa98e2SPeter Wemm { 459c2aa98e2SPeter Wemm (void) putchar('^'); 460c2aa98e2SPeter Wemm (void) putchar(c ^ 0100); 461c2aa98e2SPeter Wemm } 462c2aa98e2SPeter Wemm } 463c2aa98e2SPeter Wemm if (shiftout) 464c2aa98e2SPeter Wemm printf("%s", TermEscape.te_rv_off); 465c2aa98e2SPeter Wemm (void) fflush(stdout); 466c2aa98e2SPeter Wemm } 467c2aa98e2SPeter Wemm /* 468c2aa98e2SPeter Wemm ** MAKELOWER -- Translate a line into lower case 469c2aa98e2SPeter Wemm ** 470c2aa98e2SPeter Wemm ** Parameters: 471c2aa98e2SPeter Wemm ** p -- the string to translate. If NULL, return is 472c2aa98e2SPeter Wemm ** immediate. 473c2aa98e2SPeter Wemm ** 474c2aa98e2SPeter Wemm ** Returns: 475c2aa98e2SPeter Wemm ** none. 476c2aa98e2SPeter Wemm ** 477c2aa98e2SPeter Wemm ** Side Effects: 478c2aa98e2SPeter Wemm ** String pointed to by p is translated to lower case. 479c2aa98e2SPeter Wemm ** 480c2aa98e2SPeter Wemm ** Called By: 481c2aa98e2SPeter Wemm ** parse 482c2aa98e2SPeter Wemm */ 483c2aa98e2SPeter Wemm 484c2aa98e2SPeter Wemm void 485c2aa98e2SPeter Wemm makelower(p) 486c2aa98e2SPeter Wemm register char *p; 487c2aa98e2SPeter Wemm { 488c2aa98e2SPeter Wemm register char c; 489c2aa98e2SPeter Wemm 490c2aa98e2SPeter Wemm if (p == NULL) 491c2aa98e2SPeter Wemm return; 492c2aa98e2SPeter Wemm for (; (c = *p) != '\0'; p++) 493c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 494c2aa98e2SPeter Wemm *p = tolower(c); 495c2aa98e2SPeter Wemm } 496c2aa98e2SPeter Wemm /* 497c2aa98e2SPeter Wemm ** BUILDFNAME -- build full name from gecos style entry. 498c2aa98e2SPeter Wemm ** 499c2aa98e2SPeter Wemm ** This routine interprets the strange entry that would appear 500c2aa98e2SPeter Wemm ** in the GECOS field of the password file. 501c2aa98e2SPeter Wemm ** 502c2aa98e2SPeter Wemm ** Parameters: 503c2aa98e2SPeter Wemm ** p -- name to build. 504c2aa98e2SPeter Wemm ** login -- the login name of this user (for &). 505c2aa98e2SPeter Wemm ** buf -- place to put the result. 506c2aa98e2SPeter Wemm ** buflen -- length of buf. 507c2aa98e2SPeter Wemm ** 508c2aa98e2SPeter Wemm ** Returns: 509c2aa98e2SPeter Wemm ** none. 510c2aa98e2SPeter Wemm ** 511c2aa98e2SPeter Wemm ** Side Effects: 512c2aa98e2SPeter Wemm ** none. 513c2aa98e2SPeter Wemm */ 514c2aa98e2SPeter Wemm 515c2aa98e2SPeter Wemm void 516c2aa98e2SPeter Wemm buildfname(gecos, login, buf, buflen) 517c2aa98e2SPeter Wemm register char *gecos; 518c2aa98e2SPeter Wemm char *login; 519c2aa98e2SPeter Wemm char *buf; 520c2aa98e2SPeter Wemm int buflen; 521c2aa98e2SPeter Wemm { 522c2aa98e2SPeter Wemm register char *p; 523c2aa98e2SPeter Wemm register char *bp = buf; 524c2aa98e2SPeter Wemm 525c2aa98e2SPeter Wemm if (*gecos == '*') 526c2aa98e2SPeter Wemm gecos++; 527c2aa98e2SPeter Wemm 528c2aa98e2SPeter Wemm /* copy gecos, interpolating & to be full name */ 529c2aa98e2SPeter Wemm for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) 530c2aa98e2SPeter Wemm { 531c2aa98e2SPeter Wemm if (bp >= &buf[buflen - 1]) 532c2aa98e2SPeter Wemm { 533c2aa98e2SPeter Wemm /* buffer overflow -- just use login name */ 534c2aa98e2SPeter Wemm snprintf(buf, buflen, "%s", login); 535c2aa98e2SPeter Wemm return; 536c2aa98e2SPeter Wemm } 537c2aa98e2SPeter Wemm if (*p == '&') 538c2aa98e2SPeter Wemm { 539c2aa98e2SPeter Wemm /* interpolate full name */ 540c2aa98e2SPeter Wemm snprintf(bp, buflen - (bp - buf), "%s", login); 541c2aa98e2SPeter Wemm *bp = toupper(*bp); 542c2aa98e2SPeter Wemm bp += strlen(bp); 543c2aa98e2SPeter Wemm } 544c2aa98e2SPeter Wemm else 545c2aa98e2SPeter Wemm *bp++ = *p; 546c2aa98e2SPeter Wemm } 547c2aa98e2SPeter Wemm *bp = '\0'; 548c2aa98e2SPeter Wemm } 549c2aa98e2SPeter Wemm /* 550c2aa98e2SPeter Wemm ** FIXCRLF -- fix <CR><LF> in line. 551c2aa98e2SPeter Wemm ** 552c2aa98e2SPeter Wemm ** Looks for the <CR><LF> combination and turns it into the 553c2aa98e2SPeter Wemm ** UNIX canonical <NL> character. It only takes one line, 554c2aa98e2SPeter Wemm ** i.e., it is assumed that the first <NL> found is the end 555c2aa98e2SPeter Wemm ** of the line. 556c2aa98e2SPeter Wemm ** 557c2aa98e2SPeter Wemm ** Parameters: 558c2aa98e2SPeter Wemm ** line -- the line to fix. 559c2aa98e2SPeter Wemm ** stripnl -- if true, strip the newline also. 560c2aa98e2SPeter Wemm ** 561c2aa98e2SPeter Wemm ** Returns: 562c2aa98e2SPeter Wemm ** none. 563c2aa98e2SPeter Wemm ** 564c2aa98e2SPeter Wemm ** Side Effects: 565c2aa98e2SPeter Wemm ** line is changed in place. 566c2aa98e2SPeter Wemm */ 567c2aa98e2SPeter Wemm 568c2aa98e2SPeter Wemm void 569c2aa98e2SPeter Wemm fixcrlf(line, stripnl) 570c2aa98e2SPeter Wemm char *line; 571c2aa98e2SPeter Wemm bool stripnl; 572c2aa98e2SPeter Wemm { 573c2aa98e2SPeter Wemm register char *p; 574c2aa98e2SPeter Wemm 575c2aa98e2SPeter Wemm p = strchr(line, '\n'); 576c2aa98e2SPeter Wemm if (p == NULL) 577c2aa98e2SPeter Wemm return; 578c2aa98e2SPeter Wemm if (p > line && p[-1] == '\r') 579c2aa98e2SPeter Wemm p--; 580c2aa98e2SPeter Wemm if (!stripnl) 581c2aa98e2SPeter Wemm *p++ = '\n'; 582c2aa98e2SPeter Wemm *p = '\0'; 583c2aa98e2SPeter Wemm } 584c2aa98e2SPeter Wemm /* 585c2aa98e2SPeter Wemm ** PUTLINE -- put a line like fputs obeying SMTP conventions 586c2aa98e2SPeter Wemm ** 587c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 588c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 589c2aa98e2SPeter Wemm ** 590c2aa98e2SPeter Wemm ** Parameters: 591c2aa98e2SPeter Wemm ** l -- line to put. 592c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 593c2aa98e2SPeter Wemm ** 594c2aa98e2SPeter Wemm ** Returns: 595c2aa98e2SPeter Wemm ** none 596c2aa98e2SPeter Wemm ** 597c2aa98e2SPeter Wemm ** Side Effects: 598c2aa98e2SPeter Wemm ** output of l to fp. 599c2aa98e2SPeter Wemm */ 600c2aa98e2SPeter Wemm 601c2aa98e2SPeter Wemm void 602c2aa98e2SPeter Wemm putline(l, mci) 603c2aa98e2SPeter Wemm register char *l; 604c2aa98e2SPeter Wemm register MCI *mci; 605c2aa98e2SPeter Wemm { 606c2aa98e2SPeter Wemm putxline(l, strlen(l), mci, PXLF_MAPFROM); 607c2aa98e2SPeter Wemm } 608c2aa98e2SPeter Wemm /* 609c2aa98e2SPeter Wemm ** PUTXLINE -- putline with flags bits. 610c2aa98e2SPeter Wemm ** 611c2aa98e2SPeter Wemm ** This routine always guarantees outputing a newline (or CRLF, 612c2aa98e2SPeter Wemm ** as appropriate) at the end of the string. 613c2aa98e2SPeter Wemm ** 614c2aa98e2SPeter Wemm ** Parameters: 615c2aa98e2SPeter Wemm ** l -- line to put. 616c2aa98e2SPeter Wemm ** len -- the length of the line. 617c2aa98e2SPeter Wemm ** mci -- the mailer connection information. 618c2aa98e2SPeter Wemm ** pxflags -- flag bits: 619c2aa98e2SPeter Wemm ** PXLF_MAPFROM -- map From_ to >From_. 620c2aa98e2SPeter Wemm ** PXLF_STRIP8BIT -- strip 8th bit. 621c2aa98e2SPeter Wemm ** PXLF_HEADER -- map bare newline in header to newline space. 622c2aa98e2SPeter Wemm ** 623c2aa98e2SPeter Wemm ** Returns: 624c2aa98e2SPeter Wemm ** none 625c2aa98e2SPeter Wemm ** 626c2aa98e2SPeter Wemm ** Side Effects: 627c2aa98e2SPeter Wemm ** output of l to fp. 628c2aa98e2SPeter Wemm */ 629c2aa98e2SPeter Wemm 630c2aa98e2SPeter Wemm void 631c2aa98e2SPeter Wemm putxline(l, len, mci, pxflags) 632c2aa98e2SPeter Wemm register char *l; 633c2aa98e2SPeter Wemm size_t len; 634c2aa98e2SPeter Wemm register MCI *mci; 635c2aa98e2SPeter Wemm int pxflags; 636c2aa98e2SPeter Wemm { 637c2aa98e2SPeter Wemm register char *p, *end; 638c2aa98e2SPeter Wemm int slop = 0; 639c2aa98e2SPeter Wemm size_t eol_len = strlen(mci->mci_mailer->m_eol); 640c2aa98e2SPeter Wemm 641c2aa98e2SPeter Wemm /* strip out 0200 bits -- these can look like TELNET protocol */ 642c2aa98e2SPeter Wemm if (bitset(MCIF_7BIT, mci->mci_flags) || 643c2aa98e2SPeter Wemm bitset(PXLF_STRIP8BIT, pxflags)) 644c2aa98e2SPeter Wemm { 645c2aa98e2SPeter Wemm register char svchar; 646c2aa98e2SPeter Wemm 647c2aa98e2SPeter Wemm for (p = l; (svchar = *p) != '\0'; ++p) 648c2aa98e2SPeter Wemm if (bitset(0200, svchar)) 649c2aa98e2SPeter Wemm *p = svchar &~ 0200; 650c2aa98e2SPeter Wemm } 651c2aa98e2SPeter Wemm 652c2aa98e2SPeter Wemm end = l + len; 653c2aa98e2SPeter Wemm do 654c2aa98e2SPeter Wemm { 655c2aa98e2SPeter Wemm /* find the end of the line */ 656c2aa98e2SPeter Wemm p = memchr(l, '\n', end - l); 657c2aa98e2SPeter Wemm if (p == NULL) 658c2aa98e2SPeter Wemm p = end; 659c2aa98e2SPeter Wemm 660c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 661c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d >>> ", (int) getpid()); 662c2aa98e2SPeter Wemm 663c2aa98e2SPeter Wemm /* check for line overflow */ 664c2aa98e2SPeter Wemm while (mci->mci_mailer->m_linelimit > 0 && 665c2aa98e2SPeter Wemm (p - l + slop) > mci->mci_mailer->m_linelimit) 666c2aa98e2SPeter Wemm { 667c2aa98e2SPeter Wemm char *l_base = l; 668c2aa98e2SPeter Wemm register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; 669c2aa98e2SPeter Wemm 670c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 671c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 672c2aa98e2SPeter Wemm { 673c2aa98e2SPeter Wemm (void) putc('.', mci->mci_out); 674c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 675c2aa98e2SPeter Wemm mci->mci_contentlen++; 676c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 677c2aa98e2SPeter Wemm (void) putc('.', TrafficLogFile); 678c2aa98e2SPeter Wemm } 679c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 680c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 681c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 682c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 683c2aa98e2SPeter Wemm { 684c2aa98e2SPeter Wemm (void) putc('>', mci->mci_out); 685c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 686c2aa98e2SPeter Wemm mci->mci_contentlen++; 687c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 688c2aa98e2SPeter Wemm (void) putc('>', TrafficLogFile); 689c2aa98e2SPeter Wemm } 690c2aa98e2SPeter Wemm while (l < q) 691c2aa98e2SPeter Wemm { 692c2aa98e2SPeter Wemm (void) putc(*l++, mci->mci_out); 693c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 694c2aa98e2SPeter Wemm mci->mci_contentlen++; 695c2aa98e2SPeter Wemm } 696c2aa98e2SPeter Wemm (void) putc('!', mci->mci_out); 697c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 698c2aa98e2SPeter Wemm mci->mci_contentlen++; 699c2aa98e2SPeter Wemm fputs(mci->mci_mailer->m_eol, mci->mci_out); 700c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 701c2aa98e2SPeter Wemm mci->mci_contentlen += eol_len; 702c2aa98e2SPeter Wemm (void) putc(' ', mci->mci_out); 703c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 704c2aa98e2SPeter Wemm mci->mci_contentlen++; 705c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 706c2aa98e2SPeter Wemm { 707c2aa98e2SPeter Wemm for (l = l_base; l < q; l++) 708c2aa98e2SPeter Wemm (void) putc(*l, TrafficLogFile); 709c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "!\n%05d >>> ", 710c2aa98e2SPeter Wemm (int) getpid()); 711c2aa98e2SPeter Wemm } 712c2aa98e2SPeter Wemm slop = 1; 713c2aa98e2SPeter Wemm } 714c2aa98e2SPeter Wemm 715c2aa98e2SPeter Wemm /* output last part */ 716c2aa98e2SPeter Wemm if (l[0] == '.' && slop == 0 && 717c2aa98e2SPeter Wemm bitnset(M_XDOT, mci->mci_mailer->m_flags)) 718c2aa98e2SPeter Wemm { 719c2aa98e2SPeter Wemm (void) putc('.', mci->mci_out); 720c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 721c2aa98e2SPeter Wemm mci->mci_contentlen++; 722c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 723c2aa98e2SPeter Wemm (void) putc('.', TrafficLogFile); 724c2aa98e2SPeter Wemm } 725c2aa98e2SPeter Wemm else if (l[0] == 'F' && slop == 0 && 726c2aa98e2SPeter Wemm bitset(PXLF_MAPFROM, pxflags) && 727c2aa98e2SPeter Wemm strncmp(l, "From ", 5) == 0 && 728c2aa98e2SPeter Wemm bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) 729c2aa98e2SPeter Wemm { 730c2aa98e2SPeter Wemm (void) putc('>', mci->mci_out); 731c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 732c2aa98e2SPeter Wemm mci->mci_contentlen++; 733c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 734c2aa98e2SPeter Wemm (void) putc('>', TrafficLogFile); 735c2aa98e2SPeter Wemm } 736c2aa98e2SPeter Wemm for ( ; l < p; ++l) 737c2aa98e2SPeter Wemm { 738c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 739c2aa98e2SPeter Wemm (void) putc(*l, TrafficLogFile); 740c2aa98e2SPeter Wemm (void) putc(*l, mci->mci_out); 741c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 742c2aa98e2SPeter Wemm mci->mci_contentlen++; 743c2aa98e2SPeter Wemm } 744c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 745c2aa98e2SPeter Wemm (void) putc('\n', TrafficLogFile); 746c2aa98e2SPeter Wemm fputs(mci->mci_mailer->m_eol, mci->mci_out); 747c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 748c2aa98e2SPeter Wemm mci->mci_contentlen += eol_len; 749c2aa98e2SPeter Wemm if (l < end && *l == '\n') 750c2aa98e2SPeter Wemm { 751c2aa98e2SPeter Wemm if (*++l != ' ' && *l != '\t' && *l != '\0' && 752c2aa98e2SPeter Wemm bitset(PXLF_HEADER, pxflags)) 753c2aa98e2SPeter Wemm { 754c2aa98e2SPeter Wemm (void) putc(' ', mci->mci_out); 755c2aa98e2SPeter Wemm if (!bitset(MCIF_INHEADER, mci->mci_flags)) 756c2aa98e2SPeter Wemm mci->mci_contentlen++; 757c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 758c2aa98e2SPeter Wemm (void) putc(' ', TrafficLogFile); 759c2aa98e2SPeter Wemm } 760c2aa98e2SPeter Wemm } 761c2aa98e2SPeter Wemm } while (l < end); 762c2aa98e2SPeter Wemm } 763c2aa98e2SPeter Wemm /* 764c2aa98e2SPeter Wemm ** XUNLINK -- unlink a file, doing logging as appropriate. 765c2aa98e2SPeter Wemm ** 766c2aa98e2SPeter Wemm ** Parameters: 767c2aa98e2SPeter Wemm ** f -- name of file to unlink. 768c2aa98e2SPeter Wemm ** 769c2aa98e2SPeter Wemm ** Returns: 770c2aa98e2SPeter Wemm ** none. 771c2aa98e2SPeter Wemm ** 772c2aa98e2SPeter Wemm ** Side Effects: 773c2aa98e2SPeter Wemm ** f is unlinked. 774c2aa98e2SPeter Wemm */ 775c2aa98e2SPeter Wemm 776c2aa98e2SPeter Wemm void 777c2aa98e2SPeter Wemm xunlink(f) 778c2aa98e2SPeter Wemm char *f; 779c2aa98e2SPeter Wemm { 780c2aa98e2SPeter Wemm register int i; 781c2aa98e2SPeter Wemm 782c2aa98e2SPeter Wemm if (LogLevel > 98) 783c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 784c2aa98e2SPeter Wemm "unlink %s", 785c2aa98e2SPeter Wemm f); 786c2aa98e2SPeter Wemm 787c2aa98e2SPeter Wemm i = unlink(f); 788c2aa98e2SPeter Wemm if (i < 0 && LogLevel > 97) 789c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 790c2aa98e2SPeter Wemm "%s: unlink-fail %d", 791c2aa98e2SPeter Wemm f, errno); 792c2aa98e2SPeter Wemm } 793c2aa98e2SPeter Wemm /* 794c2aa98e2SPeter Wemm ** XFCLOSE -- close a file, doing logging as appropriate. 795c2aa98e2SPeter Wemm ** 796c2aa98e2SPeter Wemm ** Parameters: 797c2aa98e2SPeter Wemm ** fp -- file pointer for the file to close 798c2aa98e2SPeter Wemm ** a, b -- miscellaneous crud to print for debugging 799c2aa98e2SPeter Wemm ** 800c2aa98e2SPeter Wemm ** Returns: 801c2aa98e2SPeter Wemm ** none. 802c2aa98e2SPeter Wemm ** 803c2aa98e2SPeter Wemm ** Side Effects: 804c2aa98e2SPeter Wemm ** fp is closed. 805c2aa98e2SPeter Wemm */ 806c2aa98e2SPeter Wemm 807c2aa98e2SPeter Wemm void 808c2aa98e2SPeter Wemm xfclose(fp, a, b) 809c2aa98e2SPeter Wemm FILE *fp; 810c2aa98e2SPeter Wemm char *a, *b; 811c2aa98e2SPeter Wemm { 812c2aa98e2SPeter Wemm if (tTd(53, 99)) 813c2aa98e2SPeter Wemm printf("xfclose(%lx) %s %s\n", (u_long) fp, a, b); 814c2aa98e2SPeter Wemm #if XDEBUG 815c2aa98e2SPeter Wemm if (fileno(fp) == 1) 816c2aa98e2SPeter Wemm syserr("xfclose(%s %s): fd = 1", a, b); 817c2aa98e2SPeter Wemm #endif 818c2aa98e2SPeter Wemm if (fclose(fp) < 0 && tTd(53, 99)) 819c2aa98e2SPeter Wemm printf("xfclose FAILURE: %s\n", errstring(errno)); 820c2aa98e2SPeter Wemm } 821c2aa98e2SPeter Wemm /* 822c2aa98e2SPeter Wemm ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 823c2aa98e2SPeter Wemm ** 824c2aa98e2SPeter Wemm ** Parameters: 825c2aa98e2SPeter Wemm ** buf -- place to put the input line. 826c2aa98e2SPeter Wemm ** siz -- size of buf. 827c2aa98e2SPeter Wemm ** fp -- file to read from. 828c2aa98e2SPeter Wemm ** timeout -- the timeout before error occurs. 829c2aa98e2SPeter Wemm ** during -- what we are trying to read (for error messages). 830c2aa98e2SPeter Wemm ** 831c2aa98e2SPeter Wemm ** Returns: 832c2aa98e2SPeter Wemm ** NULL on error (including timeout). This will also leave 833c2aa98e2SPeter Wemm ** buf containing a null string. 834c2aa98e2SPeter Wemm ** buf otherwise. 835c2aa98e2SPeter Wemm ** 836c2aa98e2SPeter Wemm ** Side Effects: 837c2aa98e2SPeter Wemm ** none. 838c2aa98e2SPeter Wemm */ 839c2aa98e2SPeter Wemm 840c2aa98e2SPeter Wemm static jmp_buf CtxReadTimeout; 841c2aa98e2SPeter Wemm static void readtimeout __P((time_t)); 842c2aa98e2SPeter Wemm 843c2aa98e2SPeter Wemm char * 844c2aa98e2SPeter Wemm sfgets(buf, siz, fp, timeout, during) 845c2aa98e2SPeter Wemm char *buf; 846c2aa98e2SPeter Wemm int siz; 847c2aa98e2SPeter Wemm FILE *fp; 848c2aa98e2SPeter Wemm time_t timeout; 849c2aa98e2SPeter Wemm char *during; 850c2aa98e2SPeter Wemm { 851c2aa98e2SPeter Wemm register EVENT *ev = NULL; 852c2aa98e2SPeter Wemm register char *p; 853c2aa98e2SPeter Wemm 854c2aa98e2SPeter Wemm if (fp == NULL) 855c2aa98e2SPeter Wemm { 856c2aa98e2SPeter Wemm buf[0] = '\0'; 857c2aa98e2SPeter Wemm return NULL; 858c2aa98e2SPeter Wemm } 859c2aa98e2SPeter Wemm 860c2aa98e2SPeter Wemm /* set the timeout */ 861c2aa98e2SPeter Wemm if (timeout != 0) 862c2aa98e2SPeter Wemm { 863c2aa98e2SPeter Wemm if (setjmp(CtxReadTimeout) != 0) 864c2aa98e2SPeter Wemm { 865c2aa98e2SPeter Wemm if (LogLevel > 1) 866c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 867c2aa98e2SPeter Wemm "timeout waiting for input from %.100s during %s", 868c2aa98e2SPeter Wemm CurHostName ? CurHostName : "local", 869c2aa98e2SPeter Wemm during); 870c2aa98e2SPeter Wemm errno = 0; 871c2aa98e2SPeter Wemm buf[0] = '\0'; 872c2aa98e2SPeter Wemm #if XDEBUG 873c2aa98e2SPeter Wemm checkfd012(during); 874c2aa98e2SPeter Wemm #endif 875c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 876c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n", 877c2aa98e2SPeter Wemm (int) getpid()); 878c2aa98e2SPeter Wemm return (NULL); 879c2aa98e2SPeter Wemm } 880c2aa98e2SPeter Wemm ev = setevent(timeout, readtimeout, 0); 881c2aa98e2SPeter Wemm } 882c2aa98e2SPeter Wemm 883c2aa98e2SPeter Wemm /* try to read */ 884c2aa98e2SPeter Wemm p = NULL; 885c2aa98e2SPeter Wemm while (!feof(fp) && !ferror(fp)) 886c2aa98e2SPeter Wemm { 887c2aa98e2SPeter Wemm errno = 0; 888c2aa98e2SPeter Wemm p = fgets(buf, siz, fp); 889c2aa98e2SPeter Wemm if (p != NULL || errno != EINTR) 890c2aa98e2SPeter Wemm break; 891c2aa98e2SPeter Wemm clearerr(fp); 892c2aa98e2SPeter Wemm } 893c2aa98e2SPeter Wemm 894c2aa98e2SPeter Wemm /* clear the event if it has not sprung */ 895c2aa98e2SPeter Wemm clrevent(ev); 896c2aa98e2SPeter Wemm 897c2aa98e2SPeter Wemm /* clean up the books and exit */ 898c2aa98e2SPeter Wemm LineNumber++; 899c2aa98e2SPeter Wemm if (p == NULL) 900c2aa98e2SPeter Wemm { 901c2aa98e2SPeter Wemm buf[0] = '\0'; 902c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 903c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< [EOF]\n", (int) getpid()); 904c2aa98e2SPeter Wemm return (NULL); 905c2aa98e2SPeter Wemm } 906c2aa98e2SPeter Wemm if (TrafficLogFile != NULL) 907c2aa98e2SPeter Wemm fprintf(TrafficLogFile, "%05d <<< %s", (int) getpid(), buf); 908c2aa98e2SPeter Wemm if (SevenBitInput) 909c2aa98e2SPeter Wemm { 910c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 911c2aa98e2SPeter Wemm *p &= ~0200; 912c2aa98e2SPeter Wemm } 913c2aa98e2SPeter Wemm else if (!HasEightBits) 914c2aa98e2SPeter Wemm { 915c2aa98e2SPeter Wemm for (p = buf; *p != '\0'; p++) 916c2aa98e2SPeter Wemm { 917c2aa98e2SPeter Wemm if (bitset(0200, *p)) 918c2aa98e2SPeter Wemm { 919c2aa98e2SPeter Wemm HasEightBits = TRUE; 920c2aa98e2SPeter Wemm break; 921c2aa98e2SPeter Wemm } 922c2aa98e2SPeter Wemm } 923c2aa98e2SPeter Wemm } 924c2aa98e2SPeter Wemm return (buf); 925c2aa98e2SPeter Wemm } 926c2aa98e2SPeter Wemm 927c2aa98e2SPeter Wemm /* ARGSUSED */ 928c2aa98e2SPeter Wemm static void 929c2aa98e2SPeter Wemm readtimeout(timeout) 930c2aa98e2SPeter Wemm time_t timeout; 931c2aa98e2SPeter Wemm { 932c2aa98e2SPeter Wemm longjmp(CtxReadTimeout, 1); 933c2aa98e2SPeter Wemm } 934c2aa98e2SPeter Wemm /* 935c2aa98e2SPeter Wemm ** FGETFOLDED -- like fgets, but know about folded lines. 936c2aa98e2SPeter Wemm ** 937c2aa98e2SPeter Wemm ** Parameters: 938c2aa98e2SPeter Wemm ** buf -- place to put result. 939c2aa98e2SPeter Wemm ** n -- bytes available. 940c2aa98e2SPeter Wemm ** f -- file to read from. 941c2aa98e2SPeter Wemm ** 942c2aa98e2SPeter Wemm ** Returns: 943c2aa98e2SPeter Wemm ** input line(s) on success, NULL on error or EOF. 944c2aa98e2SPeter Wemm ** This will normally be buf -- unless the line is too 945c2aa98e2SPeter Wemm ** long, when it will be xalloc()ed. 946c2aa98e2SPeter Wemm ** 947c2aa98e2SPeter Wemm ** Side Effects: 948c2aa98e2SPeter Wemm ** buf gets lines from f, with continuation lines (lines 949c2aa98e2SPeter Wemm ** with leading white space) appended. CRLF's are mapped 950c2aa98e2SPeter Wemm ** into single newlines. Any trailing NL is stripped. 951c2aa98e2SPeter Wemm */ 952c2aa98e2SPeter Wemm 953c2aa98e2SPeter Wemm char * 954c2aa98e2SPeter Wemm fgetfolded(buf, n, f) 955c2aa98e2SPeter Wemm char *buf; 956c2aa98e2SPeter Wemm register int n; 957c2aa98e2SPeter Wemm FILE *f; 958c2aa98e2SPeter Wemm { 959c2aa98e2SPeter Wemm register char *p = buf; 960c2aa98e2SPeter Wemm char *bp = buf; 961c2aa98e2SPeter Wemm register int i; 962c2aa98e2SPeter Wemm 963c2aa98e2SPeter Wemm n--; 964c2aa98e2SPeter Wemm while ((i = getc(f)) != EOF) 965c2aa98e2SPeter Wemm { 966c2aa98e2SPeter Wemm if (i == '\r') 967c2aa98e2SPeter Wemm { 968c2aa98e2SPeter Wemm i = getc(f); 969c2aa98e2SPeter Wemm if (i != '\n') 970c2aa98e2SPeter Wemm { 971c2aa98e2SPeter Wemm if (i != EOF) 972c2aa98e2SPeter Wemm (void) ungetc(i, f); 973c2aa98e2SPeter Wemm i = '\r'; 974c2aa98e2SPeter Wemm } 975c2aa98e2SPeter Wemm } 976c2aa98e2SPeter Wemm if (--n <= 0) 977c2aa98e2SPeter Wemm { 978c2aa98e2SPeter Wemm /* allocate new space */ 979c2aa98e2SPeter Wemm char *nbp; 980c2aa98e2SPeter Wemm int nn; 981c2aa98e2SPeter Wemm 982c2aa98e2SPeter Wemm nn = (p - bp); 983c2aa98e2SPeter Wemm if (nn < MEMCHUNKSIZE) 984c2aa98e2SPeter Wemm nn *= 2; 985c2aa98e2SPeter Wemm else 986c2aa98e2SPeter Wemm nn += MEMCHUNKSIZE; 987c2aa98e2SPeter Wemm nbp = xalloc(nn); 988c2aa98e2SPeter Wemm bcopy(bp, nbp, p - bp); 989c2aa98e2SPeter Wemm p = &nbp[p - bp]; 990c2aa98e2SPeter Wemm if (bp != buf) 991c2aa98e2SPeter Wemm free(bp); 992c2aa98e2SPeter Wemm bp = nbp; 993c2aa98e2SPeter Wemm n = nn - (p - bp); 994c2aa98e2SPeter Wemm } 995c2aa98e2SPeter Wemm *p++ = i; 996c2aa98e2SPeter Wemm if (i == '\n') 997c2aa98e2SPeter Wemm { 998c2aa98e2SPeter Wemm LineNumber++; 999c2aa98e2SPeter Wemm i = getc(f); 1000c2aa98e2SPeter Wemm if (i != EOF) 1001c2aa98e2SPeter Wemm (void) ungetc(i, f); 1002c2aa98e2SPeter Wemm if (i != ' ' && i != '\t') 1003c2aa98e2SPeter Wemm break; 1004c2aa98e2SPeter Wemm } 1005c2aa98e2SPeter Wemm } 1006c2aa98e2SPeter Wemm if (p == bp) 1007c2aa98e2SPeter Wemm return (NULL); 1008c2aa98e2SPeter Wemm if (p[-1] == '\n') 1009c2aa98e2SPeter Wemm p--; 1010c2aa98e2SPeter Wemm *p = '\0'; 1011c2aa98e2SPeter Wemm return (bp); 1012c2aa98e2SPeter Wemm } 1013c2aa98e2SPeter Wemm /* 1014c2aa98e2SPeter Wemm ** CURTIME -- return current time. 1015c2aa98e2SPeter Wemm ** 1016c2aa98e2SPeter Wemm ** Parameters: 1017c2aa98e2SPeter Wemm ** none. 1018c2aa98e2SPeter Wemm ** 1019c2aa98e2SPeter Wemm ** Returns: 1020c2aa98e2SPeter Wemm ** the current time. 1021c2aa98e2SPeter Wemm ** 1022c2aa98e2SPeter Wemm ** Side Effects: 1023c2aa98e2SPeter Wemm ** none. 1024c2aa98e2SPeter Wemm */ 1025c2aa98e2SPeter Wemm 1026c2aa98e2SPeter Wemm time_t 1027c2aa98e2SPeter Wemm curtime() 1028c2aa98e2SPeter Wemm { 1029c2aa98e2SPeter Wemm auto time_t t; 1030c2aa98e2SPeter Wemm 1031c2aa98e2SPeter Wemm (void) time(&t); 1032c2aa98e2SPeter Wemm return (t); 1033c2aa98e2SPeter Wemm } 1034c2aa98e2SPeter Wemm /* 1035c2aa98e2SPeter Wemm ** ATOBOOL -- convert a string representation to boolean. 1036c2aa98e2SPeter Wemm ** 1037c2aa98e2SPeter Wemm ** Defaults to "TRUE" 1038c2aa98e2SPeter Wemm ** 1039c2aa98e2SPeter Wemm ** Parameters: 1040c2aa98e2SPeter Wemm ** s -- string to convert. Takes "tTyY" as true, 1041c2aa98e2SPeter Wemm ** others as false. 1042c2aa98e2SPeter Wemm ** 1043c2aa98e2SPeter Wemm ** Returns: 1044c2aa98e2SPeter Wemm ** A boolean representation of the string. 1045c2aa98e2SPeter Wemm ** 1046c2aa98e2SPeter Wemm ** Side Effects: 1047c2aa98e2SPeter Wemm ** none. 1048c2aa98e2SPeter Wemm */ 1049c2aa98e2SPeter Wemm 1050c2aa98e2SPeter Wemm bool 1051c2aa98e2SPeter Wemm atobool(s) 1052c2aa98e2SPeter Wemm register char *s; 1053c2aa98e2SPeter Wemm { 1054c2aa98e2SPeter Wemm if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL) 1055c2aa98e2SPeter Wemm return (TRUE); 1056c2aa98e2SPeter Wemm return (FALSE); 1057c2aa98e2SPeter Wemm } 1058c2aa98e2SPeter Wemm /* 1059c2aa98e2SPeter Wemm ** ATOOCT -- convert a string representation to octal. 1060c2aa98e2SPeter Wemm ** 1061c2aa98e2SPeter Wemm ** Parameters: 1062c2aa98e2SPeter Wemm ** s -- string to convert. 1063c2aa98e2SPeter Wemm ** 1064c2aa98e2SPeter Wemm ** Returns: 1065c2aa98e2SPeter Wemm ** An integer representing the string interpreted as an 1066c2aa98e2SPeter Wemm ** octal number. 1067c2aa98e2SPeter Wemm ** 1068c2aa98e2SPeter Wemm ** Side Effects: 1069c2aa98e2SPeter Wemm ** none. 1070c2aa98e2SPeter Wemm */ 1071c2aa98e2SPeter Wemm 1072c2aa98e2SPeter Wemm int 1073c2aa98e2SPeter Wemm atooct(s) 1074c2aa98e2SPeter Wemm register char *s; 1075c2aa98e2SPeter Wemm { 1076c2aa98e2SPeter Wemm register int i = 0; 1077c2aa98e2SPeter Wemm 1078c2aa98e2SPeter Wemm while (*s >= '0' && *s <= '7') 1079c2aa98e2SPeter Wemm i = (i << 3) | (*s++ - '0'); 1080c2aa98e2SPeter Wemm return (i); 1081c2aa98e2SPeter Wemm } 1082c2aa98e2SPeter Wemm /* 1083c2aa98e2SPeter Wemm ** BITINTERSECT -- tell if two bitmaps intersect 1084c2aa98e2SPeter Wemm ** 1085c2aa98e2SPeter Wemm ** Parameters: 1086c2aa98e2SPeter Wemm ** a, b -- the bitmaps in question 1087c2aa98e2SPeter Wemm ** 1088c2aa98e2SPeter Wemm ** Returns: 1089c2aa98e2SPeter Wemm ** TRUE if they have a non-null intersection 1090c2aa98e2SPeter Wemm ** FALSE otherwise 1091c2aa98e2SPeter Wemm ** 1092c2aa98e2SPeter Wemm ** Side Effects: 1093c2aa98e2SPeter Wemm ** none. 1094c2aa98e2SPeter Wemm */ 1095c2aa98e2SPeter Wemm 1096c2aa98e2SPeter Wemm bool 1097c2aa98e2SPeter Wemm bitintersect(a, b) 1098c2aa98e2SPeter Wemm BITMAP a; 1099c2aa98e2SPeter Wemm BITMAP b; 1100c2aa98e2SPeter Wemm { 1101c2aa98e2SPeter Wemm int i; 1102c2aa98e2SPeter Wemm 1103c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1104c2aa98e2SPeter Wemm if ((a[i] & b[i]) != 0) 1105c2aa98e2SPeter Wemm return (TRUE); 1106c2aa98e2SPeter Wemm return (FALSE); 1107c2aa98e2SPeter Wemm } 1108c2aa98e2SPeter Wemm /* 1109c2aa98e2SPeter Wemm ** BITZEROP -- tell if a bitmap is all zero 1110c2aa98e2SPeter Wemm ** 1111c2aa98e2SPeter Wemm ** Parameters: 1112c2aa98e2SPeter Wemm ** map -- the bit map to check 1113c2aa98e2SPeter Wemm ** 1114c2aa98e2SPeter Wemm ** Returns: 1115c2aa98e2SPeter Wemm ** TRUE if map is all zero. 1116c2aa98e2SPeter Wemm ** FALSE if there are any bits set in map. 1117c2aa98e2SPeter Wemm ** 1118c2aa98e2SPeter Wemm ** Side Effects: 1119c2aa98e2SPeter Wemm ** none. 1120c2aa98e2SPeter Wemm */ 1121c2aa98e2SPeter Wemm 1122c2aa98e2SPeter Wemm bool 1123c2aa98e2SPeter Wemm bitzerop(map) 1124c2aa98e2SPeter Wemm BITMAP map; 1125c2aa98e2SPeter Wemm { 1126c2aa98e2SPeter Wemm int i; 1127c2aa98e2SPeter Wemm 1128c2aa98e2SPeter Wemm for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) 1129c2aa98e2SPeter Wemm if (map[i] != 0) 1130c2aa98e2SPeter Wemm return (FALSE); 1131c2aa98e2SPeter Wemm return (TRUE); 1132c2aa98e2SPeter Wemm } 1133c2aa98e2SPeter Wemm /* 1134c2aa98e2SPeter Wemm ** STRCONTAINEDIN -- tell if one string is contained in another 1135c2aa98e2SPeter Wemm ** 1136c2aa98e2SPeter Wemm ** Parameters: 1137c2aa98e2SPeter Wemm ** a -- possible substring. 1138c2aa98e2SPeter Wemm ** b -- possible superstring. 1139c2aa98e2SPeter Wemm ** 1140c2aa98e2SPeter Wemm ** Returns: 1141c2aa98e2SPeter Wemm ** TRUE if a is contained in b. 1142c2aa98e2SPeter Wemm ** FALSE otherwise. 1143c2aa98e2SPeter Wemm */ 1144c2aa98e2SPeter Wemm 1145c2aa98e2SPeter Wemm bool 1146c2aa98e2SPeter Wemm strcontainedin(a, b) 1147c2aa98e2SPeter Wemm register char *a; 1148c2aa98e2SPeter Wemm register char *b; 1149c2aa98e2SPeter Wemm { 1150c2aa98e2SPeter Wemm int la; 1151c2aa98e2SPeter Wemm int lb; 1152c2aa98e2SPeter Wemm int c; 1153c2aa98e2SPeter Wemm 1154c2aa98e2SPeter Wemm la = strlen(a); 1155c2aa98e2SPeter Wemm lb = strlen(b); 1156c2aa98e2SPeter Wemm c = *a; 1157c2aa98e2SPeter Wemm if (isascii(c) && isupper(c)) 1158c2aa98e2SPeter Wemm c = tolower(c); 1159c2aa98e2SPeter Wemm for (; lb-- >= la; b++) 1160c2aa98e2SPeter Wemm { 1161c2aa98e2SPeter Wemm if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c) 1162c2aa98e2SPeter Wemm continue; 1163c2aa98e2SPeter Wemm if (strncasecmp(a, b, la) == 0) 1164c2aa98e2SPeter Wemm return TRUE; 1165c2aa98e2SPeter Wemm } 1166c2aa98e2SPeter Wemm return FALSE; 1167c2aa98e2SPeter Wemm } 1168c2aa98e2SPeter Wemm /* 1169c2aa98e2SPeter Wemm ** CHECKFD012 -- check low numbered file descriptors 1170c2aa98e2SPeter Wemm ** 1171c2aa98e2SPeter Wemm ** File descriptors 0, 1, and 2 should be open at all times. 1172c2aa98e2SPeter Wemm ** This routine verifies that, and fixes it if not true. 1173c2aa98e2SPeter Wemm ** 1174c2aa98e2SPeter Wemm ** Parameters: 1175c2aa98e2SPeter Wemm ** where -- a tag printed if the assertion failed 1176c2aa98e2SPeter Wemm ** 1177c2aa98e2SPeter Wemm ** Returns: 1178c2aa98e2SPeter Wemm ** none 1179c2aa98e2SPeter Wemm */ 1180c2aa98e2SPeter Wemm 1181c2aa98e2SPeter Wemm void 1182c2aa98e2SPeter Wemm checkfd012(where) 1183c2aa98e2SPeter Wemm char *where; 1184c2aa98e2SPeter Wemm { 1185c2aa98e2SPeter Wemm #if XDEBUG 1186c2aa98e2SPeter Wemm register int i; 1187c2aa98e2SPeter Wemm 1188c2aa98e2SPeter Wemm for (i = 0; i < 3; i++) 1189c2aa98e2SPeter Wemm fill_fd(i, where); 1190c2aa98e2SPeter Wemm #endif /* XDEBUG */ 1191c2aa98e2SPeter Wemm } 1192c2aa98e2SPeter Wemm /* 1193c2aa98e2SPeter Wemm ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1194c2aa98e2SPeter Wemm ** 1195c2aa98e2SPeter Wemm ** Parameters: 1196c2aa98e2SPeter Wemm ** fd -- file descriptor to check. 1197c2aa98e2SPeter Wemm ** where -- tag to print on failure. 1198c2aa98e2SPeter Wemm ** 1199c2aa98e2SPeter Wemm ** Returns: 1200c2aa98e2SPeter Wemm ** none. 1201c2aa98e2SPeter Wemm */ 1202c2aa98e2SPeter Wemm 1203c2aa98e2SPeter Wemm void 1204c2aa98e2SPeter Wemm checkfdopen(fd, where) 1205c2aa98e2SPeter Wemm int fd; 1206c2aa98e2SPeter Wemm char *where; 1207c2aa98e2SPeter Wemm { 1208c2aa98e2SPeter Wemm #if XDEBUG 1209c2aa98e2SPeter Wemm struct stat st; 1210c2aa98e2SPeter Wemm 1211c2aa98e2SPeter Wemm if (fstat(fd, &st) < 0 && errno == EBADF) 1212c2aa98e2SPeter Wemm { 1213c2aa98e2SPeter Wemm syserr("checkfdopen(%d): %s not open as expected!", fd, where); 1214c2aa98e2SPeter Wemm printopenfds(TRUE); 1215c2aa98e2SPeter Wemm } 1216c2aa98e2SPeter Wemm #endif 1217c2aa98e2SPeter Wemm } 1218c2aa98e2SPeter Wemm /* 1219c2aa98e2SPeter Wemm ** CHECKFDS -- check for new or missing file descriptors 1220c2aa98e2SPeter Wemm ** 1221c2aa98e2SPeter Wemm ** Parameters: 1222c2aa98e2SPeter Wemm ** where -- tag for printing. If null, take a base line. 1223c2aa98e2SPeter Wemm ** 1224c2aa98e2SPeter Wemm ** Returns: 1225c2aa98e2SPeter Wemm ** none 1226c2aa98e2SPeter Wemm ** 1227c2aa98e2SPeter Wemm ** Side Effects: 1228c2aa98e2SPeter Wemm ** If where is set, shows changes since the last call. 1229c2aa98e2SPeter Wemm */ 1230c2aa98e2SPeter Wemm 1231c2aa98e2SPeter Wemm void 1232c2aa98e2SPeter Wemm checkfds(where) 1233c2aa98e2SPeter Wemm char *where; 1234c2aa98e2SPeter Wemm { 1235c2aa98e2SPeter Wemm int maxfd; 1236c2aa98e2SPeter Wemm register int fd; 1237c2aa98e2SPeter Wemm bool printhdr = TRUE; 1238c2aa98e2SPeter Wemm int save_errno = errno; 1239c2aa98e2SPeter Wemm static BITMAP baseline; 1240c2aa98e2SPeter Wemm extern int DtableSize; 1241c2aa98e2SPeter Wemm 1242c2aa98e2SPeter Wemm if (DtableSize > 256) 1243c2aa98e2SPeter Wemm maxfd = 256; 1244c2aa98e2SPeter Wemm else 1245c2aa98e2SPeter Wemm maxfd = DtableSize; 1246c2aa98e2SPeter Wemm if (where == NULL) 1247c2aa98e2SPeter Wemm clrbitmap(baseline); 1248c2aa98e2SPeter Wemm 1249c2aa98e2SPeter Wemm for (fd = 0; fd < maxfd; fd++) 1250c2aa98e2SPeter Wemm { 1251c2aa98e2SPeter Wemm struct stat stbuf; 1252c2aa98e2SPeter Wemm 1253c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) 1254c2aa98e2SPeter Wemm { 1255c2aa98e2SPeter Wemm if (!bitnset(fd, baseline)) 1256c2aa98e2SPeter Wemm continue; 1257c2aa98e2SPeter Wemm clrbitn(fd, baseline); 1258c2aa98e2SPeter Wemm } 1259c2aa98e2SPeter Wemm else if (!bitnset(fd, baseline)) 1260c2aa98e2SPeter Wemm setbitn(fd, baseline); 1261c2aa98e2SPeter Wemm else 1262c2aa98e2SPeter Wemm continue; 1263c2aa98e2SPeter Wemm 1264c2aa98e2SPeter Wemm /* file state has changed */ 1265c2aa98e2SPeter Wemm if (where == NULL) 1266c2aa98e2SPeter Wemm continue; 1267c2aa98e2SPeter Wemm if (printhdr) 1268c2aa98e2SPeter Wemm { 1269c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1270c2aa98e2SPeter Wemm "%s: changed fds:", 1271c2aa98e2SPeter Wemm where); 1272c2aa98e2SPeter Wemm printhdr = FALSE; 1273c2aa98e2SPeter Wemm } 1274c2aa98e2SPeter Wemm dumpfd(fd, TRUE, TRUE); 1275c2aa98e2SPeter Wemm } 1276c2aa98e2SPeter Wemm errno = save_errno; 1277c2aa98e2SPeter Wemm } 1278c2aa98e2SPeter Wemm /* 1279c2aa98e2SPeter Wemm ** PRINTOPENFDS -- print the open file descriptors (for debugging) 1280c2aa98e2SPeter Wemm ** 1281c2aa98e2SPeter Wemm ** Parameters: 1282c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog; otherwise 1283c2aa98e2SPeter Wemm ** print for debugging. 1284c2aa98e2SPeter Wemm ** 1285c2aa98e2SPeter Wemm ** Returns: 1286c2aa98e2SPeter Wemm ** none. 1287c2aa98e2SPeter Wemm */ 1288c2aa98e2SPeter Wemm 1289c2aa98e2SPeter Wemm #include <arpa/inet.h> 1290c2aa98e2SPeter Wemm 1291c2aa98e2SPeter Wemm void 1292c2aa98e2SPeter Wemm printopenfds(logit) 1293c2aa98e2SPeter Wemm bool logit; 1294c2aa98e2SPeter Wemm { 1295c2aa98e2SPeter Wemm register int fd; 1296c2aa98e2SPeter Wemm extern int DtableSize; 1297c2aa98e2SPeter Wemm 1298c2aa98e2SPeter Wemm for (fd = 0; fd < DtableSize; fd++) 1299c2aa98e2SPeter Wemm dumpfd(fd, FALSE, logit); 1300c2aa98e2SPeter Wemm } 1301c2aa98e2SPeter Wemm /* 1302c2aa98e2SPeter Wemm ** DUMPFD -- dump a file descriptor 1303c2aa98e2SPeter Wemm ** 1304c2aa98e2SPeter Wemm ** Parameters: 1305c2aa98e2SPeter Wemm ** fd -- the file descriptor to dump. 1306c2aa98e2SPeter Wemm ** printclosed -- if set, print a notification even if 1307c2aa98e2SPeter Wemm ** it is closed; otherwise print nothing. 1308c2aa98e2SPeter Wemm ** logit -- if set, send output to syslog instead of stdout. 1309c2aa98e2SPeter Wemm */ 1310c2aa98e2SPeter Wemm 1311c2aa98e2SPeter Wemm void 1312c2aa98e2SPeter Wemm dumpfd(fd, printclosed, logit) 1313c2aa98e2SPeter Wemm int fd; 1314c2aa98e2SPeter Wemm bool printclosed; 1315c2aa98e2SPeter Wemm bool logit; 1316c2aa98e2SPeter Wemm { 1317c2aa98e2SPeter Wemm register char *p; 1318c2aa98e2SPeter Wemm char *hp; 1319c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1320c2aa98e2SPeter Wemm SOCKADDR sa; 1321c2aa98e2SPeter Wemm #endif 1322c2aa98e2SPeter Wemm auto SOCKADDR_LEN_T slen; 1323c2aa98e2SPeter Wemm int i; 1324c2aa98e2SPeter Wemm #if STAT64 > 0 1325c2aa98e2SPeter Wemm struct stat64 st; 1326c2aa98e2SPeter Wemm #else 1327c2aa98e2SPeter Wemm struct stat st; 1328c2aa98e2SPeter Wemm #endif 1329c2aa98e2SPeter Wemm char buf[200]; 1330c2aa98e2SPeter Wemm 1331c2aa98e2SPeter Wemm p = buf; 1332c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); 1333c2aa98e2SPeter Wemm p += strlen(p); 1334c2aa98e2SPeter Wemm 1335c2aa98e2SPeter Wemm if ( 1336c2aa98e2SPeter Wemm #if STAT64 > 0 1337c2aa98e2SPeter Wemm fstat64(fd, &st) 1338c2aa98e2SPeter Wemm #else 1339c2aa98e2SPeter Wemm fstat(fd, &st) 1340c2aa98e2SPeter Wemm #endif 1341c2aa98e2SPeter Wemm < 0) 1342c2aa98e2SPeter Wemm { 1343c2aa98e2SPeter Wemm if (errno != EBADF) 1344c2aa98e2SPeter Wemm { 1345c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)", 1346c2aa98e2SPeter Wemm errstring(errno)); 1347c2aa98e2SPeter Wemm goto printit; 1348c2aa98e2SPeter Wemm } 1349c2aa98e2SPeter Wemm else if (printclosed) 1350c2aa98e2SPeter Wemm { 1351c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CLOSED"); 1352c2aa98e2SPeter Wemm goto printit; 1353c2aa98e2SPeter Wemm } 1354c2aa98e2SPeter Wemm return; 1355c2aa98e2SPeter Wemm } 1356c2aa98e2SPeter Wemm 1357c2aa98e2SPeter Wemm i = fcntl(fd, F_GETFL, NULL); 1358c2aa98e2SPeter Wemm if (i != -1) 1359c2aa98e2SPeter Wemm { 1360c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); 1361c2aa98e2SPeter Wemm p += strlen(p); 1362c2aa98e2SPeter Wemm } 1363c2aa98e2SPeter Wemm 1364c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "mode=%o: ", st.st_mode); 1365c2aa98e2SPeter Wemm p += strlen(p); 1366c2aa98e2SPeter Wemm switch (st.st_mode & S_IFMT) 1367c2aa98e2SPeter Wemm { 1368c2aa98e2SPeter Wemm #ifdef S_IFSOCK 1369c2aa98e2SPeter Wemm case S_IFSOCK: 1370c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "SOCK "); 1371c2aa98e2SPeter Wemm p += strlen(p); 1372c2aa98e2SPeter Wemm slen = sizeof sa; 1373c2aa98e2SPeter Wemm if (getsockname(fd, &sa.sa, &slen) < 0) 1374c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno)); 1375c2aa98e2SPeter Wemm else 1376c2aa98e2SPeter Wemm { 1377c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 1378c2aa98e2SPeter Wemm if (sa.sa.sa_family == AF_INET) 1379c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s/%d", 1380c2aa98e2SPeter Wemm hp, ntohs(sa.sin.sin_port)); 1381c2aa98e2SPeter Wemm else 1382c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s", hp); 1383c2aa98e2SPeter Wemm } 1384c2aa98e2SPeter Wemm p += strlen(p); 1385c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "->"); 1386c2aa98e2SPeter Wemm p += strlen(p); 1387c2aa98e2SPeter Wemm slen = sizeof sa; 1388c2aa98e2SPeter Wemm if (getpeername(fd, &sa.sa, &slen) < 0) 1389c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno)); 1390c2aa98e2SPeter Wemm else 1391c2aa98e2SPeter Wemm { 1392c2aa98e2SPeter Wemm hp = hostnamebyanyaddr(&sa); 1393c2aa98e2SPeter Wemm if (sa.sa.sa_family == AF_INET) 1394c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s/%d", 1395c2aa98e2SPeter Wemm hp, ntohs(sa.sin.sin_port)); 1396c2aa98e2SPeter Wemm else 1397c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "%s", hp); 1398c2aa98e2SPeter Wemm } 1399c2aa98e2SPeter Wemm break; 1400c2aa98e2SPeter Wemm #endif 1401c2aa98e2SPeter Wemm 1402c2aa98e2SPeter Wemm case S_IFCHR: 1403c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "CHR: "); 1404c2aa98e2SPeter Wemm p += strlen(p); 1405c2aa98e2SPeter Wemm goto defprint; 1406c2aa98e2SPeter Wemm 1407c2aa98e2SPeter Wemm case S_IFBLK: 1408c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "BLK: "); 1409c2aa98e2SPeter Wemm p += strlen(p); 1410c2aa98e2SPeter Wemm goto defprint; 1411c2aa98e2SPeter Wemm 1412c2aa98e2SPeter Wemm #if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) 1413c2aa98e2SPeter Wemm case S_IFIFO: 1414c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "FIFO: "); 1415c2aa98e2SPeter Wemm p += strlen(p); 1416c2aa98e2SPeter Wemm goto defprint; 1417c2aa98e2SPeter Wemm #endif 1418c2aa98e2SPeter Wemm 1419c2aa98e2SPeter Wemm #ifdef S_IFDIR 1420c2aa98e2SPeter Wemm case S_IFDIR: 1421c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "DIR: "); 1422c2aa98e2SPeter Wemm p += strlen(p); 1423c2aa98e2SPeter Wemm goto defprint; 1424c2aa98e2SPeter Wemm #endif 1425c2aa98e2SPeter Wemm 1426c2aa98e2SPeter Wemm #ifdef S_IFLNK 1427c2aa98e2SPeter Wemm case S_IFLNK: 1428c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "LNK: "); 1429c2aa98e2SPeter Wemm p += strlen(p); 1430c2aa98e2SPeter Wemm goto defprint; 1431c2aa98e2SPeter Wemm #endif 1432c2aa98e2SPeter Wemm 1433c2aa98e2SPeter Wemm default: 1434c2aa98e2SPeter Wemm defprint: 1435c2aa98e2SPeter Wemm if (sizeof st.st_ino > sizeof (long)) 1436c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), 1437c2aa98e2SPeter Wemm "dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ", 1438c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 1439c2aa98e2SPeter Wemm quad_to_string(st.st_ino), 1440c2aa98e2SPeter Wemm st.st_nlink, st.st_uid, st.st_gid); 1441c2aa98e2SPeter Wemm else 1442c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), 1443c2aa98e2SPeter Wemm "dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ", 1444c2aa98e2SPeter Wemm major(st.st_dev), minor(st.st_dev), 1445c2aa98e2SPeter Wemm (unsigned long) st.st_ino, 1446c2aa98e2SPeter Wemm st.st_nlink, st.st_uid, st.st_gid); 1447c2aa98e2SPeter Wemm if (sizeof st.st_size > sizeof (long)) 1448c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "size=%s", 1449c2aa98e2SPeter Wemm quad_to_string(st.st_size)); 1450c2aa98e2SPeter Wemm else 1451c2aa98e2SPeter Wemm snprintf(p, SPACELEFT(buf, p), "size=%lu", 1452c2aa98e2SPeter Wemm (unsigned long) st.st_size); 1453c2aa98e2SPeter Wemm break; 1454c2aa98e2SPeter Wemm } 1455c2aa98e2SPeter Wemm 1456c2aa98e2SPeter Wemm printit: 1457c2aa98e2SPeter Wemm if (logit) 1458c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, 1459c2aa98e2SPeter Wemm "%.800s", buf); 1460c2aa98e2SPeter Wemm else 1461c2aa98e2SPeter Wemm printf("%s\n", buf); 1462c2aa98e2SPeter Wemm } 1463c2aa98e2SPeter Wemm /* 1464c2aa98e2SPeter Wemm ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1465c2aa98e2SPeter Wemm ** 1466c2aa98e2SPeter Wemm ** Parameters: 1467c2aa98e2SPeter Wemm ** host -- the host to shorten (stripped in place). 1468c2aa98e2SPeter Wemm ** 1469c2aa98e2SPeter Wemm ** Returns: 1470c2aa98e2SPeter Wemm ** none. 1471c2aa98e2SPeter Wemm */ 1472c2aa98e2SPeter Wemm 1473c2aa98e2SPeter Wemm void 1474c2aa98e2SPeter Wemm shorten_hostname(host) 1475c2aa98e2SPeter Wemm char host[]; 1476c2aa98e2SPeter Wemm { 1477c2aa98e2SPeter Wemm register char *p; 1478c2aa98e2SPeter Wemm char *mydom; 1479c2aa98e2SPeter Wemm int i; 1480c2aa98e2SPeter Wemm bool canon = FALSE; 1481c2aa98e2SPeter Wemm 1482c2aa98e2SPeter Wemm /* strip off final dot */ 1483c2aa98e2SPeter Wemm p = &host[strlen(host) - 1]; 1484c2aa98e2SPeter Wemm if (*p == '.') 1485c2aa98e2SPeter Wemm { 1486c2aa98e2SPeter Wemm *p = '\0'; 1487c2aa98e2SPeter Wemm canon = TRUE; 1488c2aa98e2SPeter Wemm } 1489c2aa98e2SPeter Wemm 1490c2aa98e2SPeter Wemm /* see if there is any domain at all -- if not, we are done */ 1491c2aa98e2SPeter Wemm p = strchr(host, '.'); 1492c2aa98e2SPeter Wemm if (p == NULL) 1493c2aa98e2SPeter Wemm return; 1494c2aa98e2SPeter Wemm 1495c2aa98e2SPeter Wemm /* yes, we have a domain -- see if it looks like us */ 1496c2aa98e2SPeter Wemm mydom = macvalue('m', CurEnv); 1497c2aa98e2SPeter Wemm if (mydom == NULL) 1498c2aa98e2SPeter Wemm mydom = ""; 1499c2aa98e2SPeter Wemm i = strlen(++p); 1500c2aa98e2SPeter Wemm if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 && 1501c2aa98e2SPeter Wemm (mydom[i] == '.' || mydom[i] == '\0')) 1502c2aa98e2SPeter Wemm *--p = '\0'; 1503c2aa98e2SPeter Wemm } 1504c2aa98e2SPeter Wemm /* 1505c2aa98e2SPeter Wemm ** PROG_OPEN -- open a program for reading 1506c2aa98e2SPeter Wemm ** 1507c2aa98e2SPeter Wemm ** Parameters: 1508c2aa98e2SPeter Wemm ** argv -- the argument list. 1509c2aa98e2SPeter Wemm ** pfd -- pointer to a place to store the file descriptor. 1510c2aa98e2SPeter Wemm ** e -- the current envelope. 1511c2aa98e2SPeter Wemm ** 1512c2aa98e2SPeter Wemm ** Returns: 1513c2aa98e2SPeter Wemm ** pid of the process -- -1 if it failed. 1514c2aa98e2SPeter Wemm */ 1515c2aa98e2SPeter Wemm 1516c2aa98e2SPeter Wemm int 1517c2aa98e2SPeter Wemm prog_open(argv, pfd, e) 1518c2aa98e2SPeter Wemm char **argv; 1519c2aa98e2SPeter Wemm int *pfd; 1520c2aa98e2SPeter Wemm ENVELOPE *e; 1521c2aa98e2SPeter Wemm { 1522c2aa98e2SPeter Wemm int pid; 1523c2aa98e2SPeter Wemm int i; 1524c2aa98e2SPeter Wemm int saveerrno; 1525c2aa98e2SPeter Wemm int fdv[2]; 1526c2aa98e2SPeter Wemm char *p, *q; 1527c2aa98e2SPeter Wemm char buf[MAXLINE + 1]; 1528c2aa98e2SPeter Wemm extern int DtableSize; 1529c2aa98e2SPeter Wemm 1530c2aa98e2SPeter Wemm if (pipe(fdv) < 0) 1531c2aa98e2SPeter Wemm { 1532c2aa98e2SPeter Wemm syserr("%s: cannot create pipe for stdout", argv[0]); 1533c2aa98e2SPeter Wemm return -1; 1534c2aa98e2SPeter Wemm } 1535c2aa98e2SPeter Wemm pid = fork(); 1536c2aa98e2SPeter Wemm if (pid < 0) 1537c2aa98e2SPeter Wemm { 1538c2aa98e2SPeter Wemm syserr("%s: cannot fork", argv[0]); 1539c2aa98e2SPeter Wemm close(fdv[0]); 1540c2aa98e2SPeter Wemm close(fdv[1]); 1541c2aa98e2SPeter Wemm return -1; 1542c2aa98e2SPeter Wemm } 1543c2aa98e2SPeter Wemm if (pid > 0) 1544c2aa98e2SPeter Wemm { 1545c2aa98e2SPeter Wemm /* parent */ 1546c2aa98e2SPeter Wemm close(fdv[1]); 1547c2aa98e2SPeter Wemm *pfd = fdv[0]; 1548c2aa98e2SPeter Wemm return pid; 1549c2aa98e2SPeter Wemm } 1550c2aa98e2SPeter Wemm 1551c2aa98e2SPeter Wemm /* child -- close stdin */ 1552c2aa98e2SPeter Wemm close(0); 1553c2aa98e2SPeter Wemm 1554c2aa98e2SPeter Wemm /* stdout goes back to parent */ 1555c2aa98e2SPeter Wemm close(fdv[0]); 1556c2aa98e2SPeter Wemm if (dup2(fdv[1], 1) < 0) 1557c2aa98e2SPeter Wemm { 1558c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stdout", argv[0]); 1559c2aa98e2SPeter Wemm _exit(EX_OSERR); 1560c2aa98e2SPeter Wemm } 1561c2aa98e2SPeter Wemm close(fdv[1]); 1562c2aa98e2SPeter Wemm 1563c2aa98e2SPeter Wemm /* stderr goes to transcript if available */ 1564c2aa98e2SPeter Wemm if (e->e_xfp != NULL) 1565c2aa98e2SPeter Wemm { 1566c2aa98e2SPeter Wemm if (dup2(fileno(e->e_xfp), 2) < 0) 1567c2aa98e2SPeter Wemm { 1568c2aa98e2SPeter Wemm syserr("%s: cannot dup2 for stderr", argv[0]); 1569c2aa98e2SPeter Wemm _exit(EX_OSERR); 1570c2aa98e2SPeter Wemm } 1571c2aa98e2SPeter Wemm } 1572c2aa98e2SPeter Wemm 1573c2aa98e2SPeter Wemm /* this process has no right to the queue file */ 1574c2aa98e2SPeter Wemm if (e->e_lockfp != NULL) 1575c2aa98e2SPeter Wemm close(fileno(e->e_lockfp)); 1576c2aa98e2SPeter Wemm 1577c2aa98e2SPeter Wemm /* run as default user */ 1578c2aa98e2SPeter Wemm endpwent(); 1579c2aa98e2SPeter Wemm if (setgid(DefGid) < 0 && geteuid() == 0) 1580c2aa98e2SPeter Wemm syserr("prog_open: setgid(%ld) failed", (long) DefGid); 1581c2aa98e2SPeter Wemm if (setuid(DefUid) < 0 && geteuid() == 0) 1582c2aa98e2SPeter Wemm syserr("prog_open: setuid(%ld) failed", (long) DefUid); 1583c2aa98e2SPeter Wemm 1584c2aa98e2SPeter Wemm /* run in some directory */ 1585c2aa98e2SPeter Wemm if (ProgMailer != NULL) 1586c2aa98e2SPeter Wemm p = ProgMailer->m_execdir; 1587c2aa98e2SPeter Wemm else 1588c2aa98e2SPeter Wemm p = NULL; 1589c2aa98e2SPeter Wemm for (; p != NULL; p = q) 1590c2aa98e2SPeter Wemm { 1591c2aa98e2SPeter Wemm q = strchr(p, ':'); 1592c2aa98e2SPeter Wemm if (q != NULL) 1593c2aa98e2SPeter Wemm *q = '\0'; 1594c2aa98e2SPeter Wemm expand(p, buf, sizeof buf, e); 1595c2aa98e2SPeter Wemm if (q != NULL) 1596c2aa98e2SPeter Wemm *q++ = ':'; 1597c2aa98e2SPeter Wemm if (buf[0] != '\0' && chdir(buf) >= 0) 1598c2aa98e2SPeter Wemm break; 1599c2aa98e2SPeter Wemm } 1600c2aa98e2SPeter Wemm if (p == NULL) 1601c2aa98e2SPeter Wemm { 1602c2aa98e2SPeter Wemm /* backup directories */ 1603c2aa98e2SPeter Wemm if (chdir("/tmp") < 0) 1604c2aa98e2SPeter Wemm (void) chdir("/"); 1605c2aa98e2SPeter Wemm } 1606c2aa98e2SPeter Wemm 1607c2aa98e2SPeter Wemm /* arrange for all the files to be closed */ 1608c2aa98e2SPeter Wemm for (i = 3; i < DtableSize; i++) 1609c2aa98e2SPeter Wemm { 1610c2aa98e2SPeter Wemm register int j; 1611c2aa98e2SPeter Wemm 1612c2aa98e2SPeter Wemm if ((j = fcntl(i, F_GETFD, 0)) != -1) 1613c2aa98e2SPeter Wemm (void) fcntl(i, F_SETFD, j | 1); 1614c2aa98e2SPeter Wemm } 1615c2aa98e2SPeter Wemm 1616c2aa98e2SPeter Wemm /* now exec the process */ 1617c2aa98e2SPeter Wemm execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); 1618c2aa98e2SPeter Wemm 1619c2aa98e2SPeter Wemm /* woops! failed */ 1620c2aa98e2SPeter Wemm saveerrno = errno; 1621c2aa98e2SPeter Wemm syserr("%s: cannot exec", argv[0]); 1622c2aa98e2SPeter Wemm if (transienterror(saveerrno)) 1623c2aa98e2SPeter Wemm _exit(EX_OSERR); 1624c2aa98e2SPeter Wemm _exit(EX_CONFIG); 1625c2aa98e2SPeter Wemm return -1; /* avoid compiler warning on IRIX */ 1626c2aa98e2SPeter Wemm } 1627c2aa98e2SPeter Wemm /* 1628c2aa98e2SPeter Wemm ** GET_COLUMN -- look up a Column in a line buffer 1629c2aa98e2SPeter Wemm ** 1630c2aa98e2SPeter Wemm ** Parameters: 1631c2aa98e2SPeter Wemm ** line -- the raw text line to search. 1632c2aa98e2SPeter Wemm ** col -- the column number to fetch. 1633c2aa98e2SPeter Wemm ** delim -- the delimiter between columns. If null, 1634c2aa98e2SPeter Wemm ** use white space. 1635c2aa98e2SPeter Wemm ** buf -- the output buffer. 1636c2aa98e2SPeter Wemm ** buflen -- the length of buf. 1637c2aa98e2SPeter Wemm ** 1638c2aa98e2SPeter Wemm ** Returns: 1639c2aa98e2SPeter Wemm ** buf if successful. 1640c2aa98e2SPeter Wemm ** NULL otherwise. 1641c2aa98e2SPeter Wemm */ 1642c2aa98e2SPeter Wemm 1643c2aa98e2SPeter Wemm char * 1644c2aa98e2SPeter Wemm get_column(line, col, delim, buf, buflen) 1645c2aa98e2SPeter Wemm char line[]; 1646c2aa98e2SPeter Wemm int col; 1647c2aa98e2SPeter Wemm char delim; 1648c2aa98e2SPeter Wemm char buf[]; 1649c2aa98e2SPeter Wemm int buflen; 1650c2aa98e2SPeter Wemm { 1651c2aa98e2SPeter Wemm char *p; 1652c2aa98e2SPeter Wemm char *begin, *end; 1653c2aa98e2SPeter Wemm int i; 1654c2aa98e2SPeter Wemm char delimbuf[4]; 1655c2aa98e2SPeter Wemm 1656c2aa98e2SPeter Wemm if (delim == '\0') 1657c2aa98e2SPeter Wemm strcpy(delimbuf, "\n\t "); 1658c2aa98e2SPeter Wemm else 1659c2aa98e2SPeter Wemm { 1660c2aa98e2SPeter Wemm delimbuf[0] = delim; 1661c2aa98e2SPeter Wemm delimbuf[1] = '\0'; 1662c2aa98e2SPeter Wemm } 1663c2aa98e2SPeter Wemm 1664c2aa98e2SPeter Wemm p = line; 1665c2aa98e2SPeter Wemm if (*p == '\0') 1666c2aa98e2SPeter Wemm return NULL; /* line empty */ 1667c2aa98e2SPeter Wemm if (*p == delim && col == 0) 1668c2aa98e2SPeter Wemm return NULL; /* first column empty */ 1669c2aa98e2SPeter Wemm 1670c2aa98e2SPeter Wemm begin = line; 1671c2aa98e2SPeter Wemm 1672c2aa98e2SPeter Wemm if (col == 0 && delim == '\0') 1673c2aa98e2SPeter Wemm { 1674c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 1675c2aa98e2SPeter Wemm begin++; 1676c2aa98e2SPeter Wemm } 1677c2aa98e2SPeter Wemm 1678c2aa98e2SPeter Wemm for (i = 0; i < col; i++) 1679c2aa98e2SPeter Wemm { 1680c2aa98e2SPeter Wemm if ((begin = strpbrk(begin, delimbuf)) == NULL) 1681c2aa98e2SPeter Wemm return NULL; /* no such column */ 1682c2aa98e2SPeter Wemm begin++; 1683c2aa98e2SPeter Wemm if (delim == '\0') 1684c2aa98e2SPeter Wemm { 1685c2aa98e2SPeter Wemm while (*begin != '\0' && isascii(*begin) && isspace(*begin)) 1686c2aa98e2SPeter Wemm begin++; 1687c2aa98e2SPeter Wemm } 1688c2aa98e2SPeter Wemm } 1689c2aa98e2SPeter Wemm 1690c2aa98e2SPeter Wemm end = strpbrk(begin, delimbuf); 1691c2aa98e2SPeter Wemm if (end == NULL) 1692c2aa98e2SPeter Wemm i = strlen(begin); 1693c2aa98e2SPeter Wemm else 1694c2aa98e2SPeter Wemm i = end - begin; 1695c2aa98e2SPeter Wemm if (i >= buflen) 1696c2aa98e2SPeter Wemm i = buflen - 1; 1697c2aa98e2SPeter Wemm strncpy(buf, begin, i); 1698c2aa98e2SPeter Wemm buf[i] = '\0'; 1699c2aa98e2SPeter Wemm return buf; 1700c2aa98e2SPeter Wemm } 1701c2aa98e2SPeter Wemm /* 1702c2aa98e2SPeter Wemm ** CLEANSTRCPY -- copy string keeping out bogus characters 1703c2aa98e2SPeter Wemm ** 1704c2aa98e2SPeter Wemm ** Parameters: 1705c2aa98e2SPeter Wemm ** t -- "to" string. 1706c2aa98e2SPeter Wemm ** f -- "from" string. 1707c2aa98e2SPeter Wemm ** l -- length of space available in "to" string. 1708c2aa98e2SPeter Wemm ** 1709c2aa98e2SPeter Wemm ** Returns: 1710c2aa98e2SPeter Wemm ** none. 1711c2aa98e2SPeter Wemm */ 1712c2aa98e2SPeter Wemm 1713c2aa98e2SPeter Wemm void 1714c2aa98e2SPeter Wemm cleanstrcpy(t, f, l) 1715c2aa98e2SPeter Wemm register char *t; 1716c2aa98e2SPeter Wemm register char *f; 1717c2aa98e2SPeter Wemm int l; 1718c2aa98e2SPeter Wemm { 1719c2aa98e2SPeter Wemm /* check for newlines and log if necessary */ 1720c2aa98e2SPeter Wemm (void) denlstring(f, TRUE, TRUE); 1721c2aa98e2SPeter Wemm 1722c2aa98e2SPeter Wemm l--; 1723c2aa98e2SPeter Wemm while (l > 0 && *f != '\0') 1724c2aa98e2SPeter Wemm { 1725c2aa98e2SPeter Wemm if (isascii(*f) && 1726c2aa98e2SPeter Wemm (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL)) 1727c2aa98e2SPeter Wemm { 1728c2aa98e2SPeter Wemm l--; 1729c2aa98e2SPeter Wemm *t++ = *f; 1730c2aa98e2SPeter Wemm } 1731c2aa98e2SPeter Wemm f++; 1732c2aa98e2SPeter Wemm } 1733c2aa98e2SPeter Wemm *t = '\0'; 1734c2aa98e2SPeter Wemm } 1735c2aa98e2SPeter Wemm /* 1736c2aa98e2SPeter Wemm ** DENLSTRING -- convert newlines in a string to spaces 1737c2aa98e2SPeter Wemm ** 1738c2aa98e2SPeter Wemm ** Parameters: 1739c2aa98e2SPeter Wemm ** s -- the input string 1740c2aa98e2SPeter Wemm ** strict -- if set, don't permit continuation lines. 1741c2aa98e2SPeter Wemm ** logattacks -- if set, log attempted attacks. 1742c2aa98e2SPeter Wemm ** 1743c2aa98e2SPeter Wemm ** Returns: 1744c2aa98e2SPeter Wemm ** A pointer to a version of the string with newlines 1745c2aa98e2SPeter Wemm ** mapped to spaces. This should be copied. 1746c2aa98e2SPeter Wemm */ 1747c2aa98e2SPeter Wemm 1748c2aa98e2SPeter Wemm char * 1749c2aa98e2SPeter Wemm denlstring(s, strict, logattacks) 1750c2aa98e2SPeter Wemm char *s; 1751c2aa98e2SPeter Wemm bool strict; 1752c2aa98e2SPeter Wemm bool logattacks; 1753c2aa98e2SPeter Wemm { 1754c2aa98e2SPeter Wemm register char *p; 1755c2aa98e2SPeter Wemm int l; 1756c2aa98e2SPeter Wemm static char *bp = NULL; 1757c2aa98e2SPeter Wemm static int bl = 0; 1758c2aa98e2SPeter Wemm 1759c2aa98e2SPeter Wemm p = s; 1760c2aa98e2SPeter Wemm while ((p = strchr(p, '\n')) != NULL) 1761c2aa98e2SPeter Wemm if (strict || (*++p != ' ' && *p != '\t')) 1762c2aa98e2SPeter Wemm break; 1763c2aa98e2SPeter Wemm if (p == NULL) 1764c2aa98e2SPeter Wemm return s; 1765c2aa98e2SPeter Wemm 1766c2aa98e2SPeter Wemm l = strlen(s) + 1; 1767c2aa98e2SPeter Wemm if (bl < l) 1768c2aa98e2SPeter Wemm { 1769c2aa98e2SPeter Wemm /* allocate more space */ 1770c2aa98e2SPeter Wemm if (bp != NULL) 1771c2aa98e2SPeter Wemm free(bp); 1772c2aa98e2SPeter Wemm bp = xalloc(l); 1773c2aa98e2SPeter Wemm bl = l; 1774c2aa98e2SPeter Wemm } 1775c2aa98e2SPeter Wemm strcpy(bp, s); 1776c2aa98e2SPeter Wemm for (p = bp; (p = strchr(p, '\n')) != NULL; ) 1777c2aa98e2SPeter Wemm *p++ = ' '; 1778c2aa98e2SPeter Wemm 1779c2aa98e2SPeter Wemm if (logattacks) 1780c2aa98e2SPeter Wemm { 1781c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, CurEnv->e_id, 1782c2aa98e2SPeter Wemm "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", 1783c2aa98e2SPeter Wemm RealHostName == NULL ? "[UNKNOWN]" : RealHostName, 1784c2aa98e2SPeter Wemm shortenstring(bp, MAXSHORTSTR)); 1785c2aa98e2SPeter Wemm } 1786c2aa98e2SPeter Wemm 1787c2aa98e2SPeter Wemm return bp; 1788c2aa98e2SPeter Wemm } 1789c2aa98e2SPeter Wemm /* 1790c2aa98e2SPeter Wemm ** PATH_IS_DIR -- check to see if file exists and is a directory. 1791c2aa98e2SPeter Wemm ** 1792c2aa98e2SPeter Wemm ** There are some additional checks for security violations in 1793c2aa98e2SPeter Wemm ** here. This routine is intended to be used for the host status 1794c2aa98e2SPeter Wemm ** support. 1795c2aa98e2SPeter Wemm ** 1796c2aa98e2SPeter Wemm ** Parameters: 1797c2aa98e2SPeter Wemm ** pathname -- pathname to check for directory-ness. 1798c2aa98e2SPeter Wemm ** createflag -- if set, create directory if needed. 1799c2aa98e2SPeter Wemm ** 1800c2aa98e2SPeter Wemm ** Returns: 1801c2aa98e2SPeter Wemm ** TRUE -- if the indicated pathname is a directory 1802c2aa98e2SPeter Wemm ** FALSE -- otherwise 1803c2aa98e2SPeter Wemm */ 1804c2aa98e2SPeter Wemm 1805c2aa98e2SPeter Wemm int 1806c2aa98e2SPeter Wemm path_is_dir(pathname, createflag) 1807c2aa98e2SPeter Wemm char *pathname; 1808c2aa98e2SPeter Wemm bool createflag; 1809c2aa98e2SPeter Wemm { 1810c2aa98e2SPeter Wemm struct stat statbuf; 1811c2aa98e2SPeter Wemm 1812c2aa98e2SPeter Wemm #if HASLSTAT 1813c2aa98e2SPeter Wemm if (lstat(pathname, &statbuf) < 0) 1814c2aa98e2SPeter Wemm #else 1815c2aa98e2SPeter Wemm if (stat(pathname, &statbuf) < 0) 1816c2aa98e2SPeter Wemm #endif 1817c2aa98e2SPeter Wemm { 1818c2aa98e2SPeter Wemm if (errno != ENOENT || !createflag) 1819c2aa98e2SPeter Wemm return FALSE; 1820c2aa98e2SPeter Wemm if (mkdir(pathname, 0755) < 0) 1821c2aa98e2SPeter Wemm return FALSE; 1822c2aa98e2SPeter Wemm return TRUE; 1823c2aa98e2SPeter Wemm } 1824c2aa98e2SPeter Wemm if (!S_ISDIR(statbuf.st_mode)) 1825c2aa98e2SPeter Wemm { 1826c2aa98e2SPeter Wemm errno = ENOTDIR; 1827c2aa98e2SPeter Wemm return FALSE; 1828c2aa98e2SPeter Wemm } 1829c2aa98e2SPeter Wemm 1830c2aa98e2SPeter Wemm /* security: don't allow writable directories */ 1831c2aa98e2SPeter Wemm if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) 1832c2aa98e2SPeter Wemm { 1833c2aa98e2SPeter Wemm errno = EACCES; 1834c2aa98e2SPeter Wemm return FALSE; 1835c2aa98e2SPeter Wemm } 1836c2aa98e2SPeter Wemm 1837c2aa98e2SPeter Wemm return TRUE; 1838c2aa98e2SPeter Wemm } 1839c2aa98e2SPeter Wemm /* 1840c2aa98e2SPeter Wemm ** PROC_LIST_ADD -- add process id to list of our children 1841c2aa98e2SPeter Wemm ** 1842c2aa98e2SPeter Wemm ** Parameters: 1843c2aa98e2SPeter Wemm ** pid -- pid to add to list. 1844c2aa98e2SPeter Wemm ** 1845c2aa98e2SPeter Wemm ** Returns: 1846c2aa98e2SPeter Wemm ** none 1847c2aa98e2SPeter Wemm */ 1848c2aa98e2SPeter Wemm 1849c2aa98e2SPeter Wemm static pid_t *ProcListVec = NULL; 1850c2aa98e2SPeter Wemm static int ProcListSize = 0; 1851c2aa98e2SPeter Wemm 1852c2aa98e2SPeter Wemm #define NO_PID ((pid_t) 0) 1853c2aa98e2SPeter Wemm #ifndef PROC_LIST_SEG 1854c2aa98e2SPeter Wemm # define PROC_LIST_SEG 32 /* number of pids to alloc at a time */ 1855c2aa98e2SPeter Wemm #endif 1856c2aa98e2SPeter Wemm 1857c2aa98e2SPeter Wemm void 1858c2aa98e2SPeter Wemm proc_list_add(pid) 1859c2aa98e2SPeter Wemm pid_t pid; 1860c2aa98e2SPeter Wemm { 1861c2aa98e2SPeter Wemm int i; 1862c2aa98e2SPeter Wemm extern void proc_list_probe __P((void)); 1863c2aa98e2SPeter Wemm 1864c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 1865c2aa98e2SPeter Wemm { 1866c2aa98e2SPeter Wemm if (ProcListVec[i] == NO_PID) 1867c2aa98e2SPeter Wemm break; 1868c2aa98e2SPeter Wemm } 1869c2aa98e2SPeter Wemm if (i >= ProcListSize) 1870c2aa98e2SPeter Wemm { 1871c2aa98e2SPeter Wemm /* probe the existing vector to avoid growing infinitely */ 1872c2aa98e2SPeter Wemm proc_list_probe(); 1873c2aa98e2SPeter Wemm 1874c2aa98e2SPeter Wemm /* now scan again */ 1875c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 1876c2aa98e2SPeter Wemm { 1877c2aa98e2SPeter Wemm if (ProcListVec[i] == NO_PID) 1878c2aa98e2SPeter Wemm break; 1879c2aa98e2SPeter Wemm } 1880c2aa98e2SPeter Wemm } 1881c2aa98e2SPeter Wemm if (i >= ProcListSize) 1882c2aa98e2SPeter Wemm { 1883c2aa98e2SPeter Wemm /* grow process list */ 1884c2aa98e2SPeter Wemm pid_t *npv; 1885c2aa98e2SPeter Wemm 1886c2aa98e2SPeter Wemm npv = (pid_t *) xalloc(sizeof (pid_t) * (ProcListSize + PROC_LIST_SEG)); 1887c2aa98e2SPeter Wemm if (ProcListSize > 0) 1888c2aa98e2SPeter Wemm { 1889c2aa98e2SPeter Wemm bcopy(ProcListVec, npv, ProcListSize * sizeof (pid_t)); 1890c2aa98e2SPeter Wemm free(ProcListVec); 1891c2aa98e2SPeter Wemm } 1892c2aa98e2SPeter Wemm for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) 1893c2aa98e2SPeter Wemm npv[i] = NO_PID; 1894c2aa98e2SPeter Wemm i = ProcListSize; 1895c2aa98e2SPeter Wemm ProcListSize += PROC_LIST_SEG; 1896c2aa98e2SPeter Wemm ProcListVec = npv; 1897c2aa98e2SPeter Wemm } 1898c2aa98e2SPeter Wemm ProcListVec[i] = pid; 1899c2aa98e2SPeter Wemm CurChildren++; 1900c2aa98e2SPeter Wemm } 1901c2aa98e2SPeter Wemm /* 1902c2aa98e2SPeter Wemm ** PROC_LIST_DROP -- drop pid from process list 1903c2aa98e2SPeter Wemm ** 1904c2aa98e2SPeter Wemm ** Parameters: 1905c2aa98e2SPeter Wemm ** pid -- pid to drop 1906c2aa98e2SPeter Wemm ** 1907c2aa98e2SPeter Wemm ** Returns: 1908c2aa98e2SPeter Wemm ** none. 1909c2aa98e2SPeter Wemm */ 1910c2aa98e2SPeter Wemm 1911c2aa98e2SPeter Wemm void 1912c2aa98e2SPeter Wemm proc_list_drop(pid) 1913c2aa98e2SPeter Wemm pid_t pid; 1914c2aa98e2SPeter Wemm { 1915c2aa98e2SPeter Wemm int i; 1916c2aa98e2SPeter Wemm 1917c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 1918c2aa98e2SPeter Wemm { 1919c2aa98e2SPeter Wemm if (ProcListVec[i] == pid) 1920c2aa98e2SPeter Wemm { 1921c2aa98e2SPeter Wemm ProcListVec[i] = NO_PID; 1922c2aa98e2SPeter Wemm break; 1923c2aa98e2SPeter Wemm } 1924c2aa98e2SPeter Wemm } 1925c2aa98e2SPeter Wemm if (CurChildren > 0) 1926c2aa98e2SPeter Wemm CurChildren--; 1927c2aa98e2SPeter Wemm } 1928c2aa98e2SPeter Wemm /* 1929c2aa98e2SPeter Wemm ** PROC_LIST_CLEAR -- clear the process list 1930c2aa98e2SPeter Wemm ** 1931c2aa98e2SPeter Wemm ** Parameters: 1932c2aa98e2SPeter Wemm ** none. 1933c2aa98e2SPeter Wemm ** 1934c2aa98e2SPeter Wemm ** Returns: 1935c2aa98e2SPeter Wemm ** none. 1936c2aa98e2SPeter Wemm */ 1937c2aa98e2SPeter Wemm 1938c2aa98e2SPeter Wemm void 1939c2aa98e2SPeter Wemm proc_list_clear() 1940c2aa98e2SPeter Wemm { 1941c2aa98e2SPeter Wemm int i; 1942c2aa98e2SPeter Wemm 1943c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 1944c2aa98e2SPeter Wemm ProcListVec[i] = NO_PID; 1945c2aa98e2SPeter Wemm CurChildren = 0; 1946c2aa98e2SPeter Wemm } 1947c2aa98e2SPeter Wemm /* 1948c2aa98e2SPeter Wemm ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 1949c2aa98e2SPeter Wemm ** 1950c2aa98e2SPeter Wemm ** Parameters: 1951c2aa98e2SPeter Wemm ** none 1952c2aa98e2SPeter Wemm ** 1953c2aa98e2SPeter Wemm ** Returns: 1954c2aa98e2SPeter Wemm ** none 1955c2aa98e2SPeter Wemm */ 1956c2aa98e2SPeter Wemm 1957c2aa98e2SPeter Wemm void 1958c2aa98e2SPeter Wemm proc_list_probe() 1959c2aa98e2SPeter Wemm { 1960c2aa98e2SPeter Wemm int i; 1961c2aa98e2SPeter Wemm 1962c2aa98e2SPeter Wemm for (i = 0; i < ProcListSize; i++) 1963c2aa98e2SPeter Wemm { 1964c2aa98e2SPeter Wemm if (ProcListVec[i] == NO_PID) 1965c2aa98e2SPeter Wemm continue; 1966c2aa98e2SPeter Wemm if (kill(ProcListVec[i], 0) < 0) 1967c2aa98e2SPeter Wemm { 1968c2aa98e2SPeter Wemm if (LogLevel > 3) 1969c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 1970c2aa98e2SPeter Wemm "proc_list_probe: lost pid %d", 1971c2aa98e2SPeter Wemm ProcListVec[i]); 1972c2aa98e2SPeter Wemm ProcListVec[i] = NO_PID; 1973c2aa98e2SPeter Wemm CurChildren--; 1974c2aa98e2SPeter Wemm } 1975c2aa98e2SPeter Wemm } 1976c2aa98e2SPeter Wemm if (CurChildren < 0) 1977c2aa98e2SPeter Wemm CurChildren = 0; 1978c2aa98e2SPeter Wemm } 1979c2aa98e2SPeter Wemm /* 1980c2aa98e2SPeter Wemm ** SM_STRCASECMP -- 8-bit clean version of strcasecmp 1981c2aa98e2SPeter Wemm ** 1982c2aa98e2SPeter Wemm ** Thank you, vendors, for making this all necessary. 1983c2aa98e2SPeter Wemm */ 1984c2aa98e2SPeter Wemm 1985c2aa98e2SPeter Wemm /* 1986c2aa98e2SPeter Wemm * Copyright (c) 1987, 1993 1987c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 1988c2aa98e2SPeter Wemm * 1989c2aa98e2SPeter Wemm * Redistribution and use in source and binary forms, with or without 1990c2aa98e2SPeter Wemm * modification, are permitted provided that the following conditions 1991c2aa98e2SPeter Wemm * are met: 1992c2aa98e2SPeter Wemm * 1. Redistributions of source code must retain the above copyright 1993c2aa98e2SPeter Wemm * notice, this list of conditions and the following disclaimer. 1994c2aa98e2SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 1995c2aa98e2SPeter Wemm * notice, this list of conditions and the following disclaimer in the 1996c2aa98e2SPeter Wemm * documentation and/or other materials provided with the distribution. 1997c2aa98e2SPeter Wemm * 3. All advertising materials mentioning features or use of this software 1998c2aa98e2SPeter Wemm * must display the following acknowledgement: 1999c2aa98e2SPeter Wemm * This product includes software developed by the University of 2000c2aa98e2SPeter Wemm * California, Berkeley and its contributors. 2001c2aa98e2SPeter Wemm * 4. Neither the name of the University nor the names of its contributors 2002c2aa98e2SPeter Wemm * may be used to endorse or promote products derived from this software 2003c2aa98e2SPeter Wemm * without specific prior written permission. 2004c2aa98e2SPeter Wemm * 2005c2aa98e2SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2006c2aa98e2SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2007c2aa98e2SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2008c2aa98e2SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2009c2aa98e2SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2010c2aa98e2SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2011c2aa98e2SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2012c2aa98e2SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2013c2aa98e2SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2014c2aa98e2SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2015c2aa98e2SPeter Wemm * SUCH DAMAGE. 2016c2aa98e2SPeter Wemm */ 2017c2aa98e2SPeter Wemm 2018c2aa98e2SPeter Wemm #if defined(LIBC_SCCS) && !defined(lint) 2019c2aa98e2SPeter Wemm static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; 2020c2aa98e2SPeter Wemm #endif /* LIBC_SCCS and not lint */ 2021c2aa98e2SPeter Wemm 2022c2aa98e2SPeter Wemm /* 2023c2aa98e2SPeter Wemm * This array is designed for mapping upper and lower case letter 2024c2aa98e2SPeter Wemm * together for a case independent comparison. The mappings are 2025c2aa98e2SPeter Wemm * based upon ascii character sequences. 2026c2aa98e2SPeter Wemm */ 2027c2aa98e2SPeter Wemm static const u_char charmap[] = { 2028c2aa98e2SPeter Wemm 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 2029c2aa98e2SPeter Wemm 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 2030c2aa98e2SPeter Wemm 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 2031c2aa98e2SPeter Wemm 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 2032c2aa98e2SPeter Wemm 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 2033c2aa98e2SPeter Wemm 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 2034c2aa98e2SPeter Wemm 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 2035c2aa98e2SPeter Wemm 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 2036c2aa98e2SPeter Wemm 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 2037c2aa98e2SPeter Wemm 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 2038c2aa98e2SPeter Wemm 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 2039c2aa98e2SPeter Wemm 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, 2040c2aa98e2SPeter Wemm 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 2041c2aa98e2SPeter Wemm 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 2042c2aa98e2SPeter Wemm 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 2043c2aa98e2SPeter Wemm 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, 2044c2aa98e2SPeter Wemm 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 2045c2aa98e2SPeter Wemm 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 2046c2aa98e2SPeter Wemm 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 2047c2aa98e2SPeter Wemm 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 2048c2aa98e2SPeter Wemm 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 2049c2aa98e2SPeter Wemm 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 2050c2aa98e2SPeter Wemm 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 2051c2aa98e2SPeter Wemm 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 2052c2aa98e2SPeter Wemm 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 2053c2aa98e2SPeter Wemm 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 2054c2aa98e2SPeter Wemm 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 2055c2aa98e2SPeter Wemm 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 2056c2aa98e2SPeter Wemm 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 2057c2aa98e2SPeter Wemm 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 2058c2aa98e2SPeter Wemm 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 2059c2aa98e2SPeter Wemm 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, 2060c2aa98e2SPeter Wemm }; 2061c2aa98e2SPeter Wemm 2062c2aa98e2SPeter Wemm int 2063c2aa98e2SPeter Wemm sm_strcasecmp(s1, s2) 2064c2aa98e2SPeter Wemm const char *s1, *s2; 2065c2aa98e2SPeter Wemm { 2066c2aa98e2SPeter Wemm register const u_char *cm = charmap, 2067c2aa98e2SPeter Wemm *us1 = (const u_char *)s1, 2068c2aa98e2SPeter Wemm *us2 = (const u_char *)s2; 2069c2aa98e2SPeter Wemm 2070c2aa98e2SPeter Wemm while (cm[*us1] == cm[*us2++]) 2071c2aa98e2SPeter Wemm if (*us1++ == '\0') 2072c2aa98e2SPeter Wemm return (0); 2073c2aa98e2SPeter Wemm return (cm[*us1] - cm[*--us2]); 2074c2aa98e2SPeter Wemm } 2075c2aa98e2SPeter Wemm 2076c2aa98e2SPeter Wemm int 2077c2aa98e2SPeter Wemm sm_strncasecmp(s1, s2, n) 2078c2aa98e2SPeter Wemm const char *s1, *s2; 2079c2aa98e2SPeter Wemm register size_t n; 2080c2aa98e2SPeter Wemm { 2081c2aa98e2SPeter Wemm if (n != 0) { 2082c2aa98e2SPeter Wemm register const u_char *cm = charmap, 2083c2aa98e2SPeter Wemm *us1 = (const u_char *)s1, 2084c2aa98e2SPeter Wemm *us2 = (const u_char *)s2; 2085c2aa98e2SPeter Wemm 2086c2aa98e2SPeter Wemm do { 2087c2aa98e2SPeter Wemm if (cm[*us1] != cm[*us2++]) 2088c2aa98e2SPeter Wemm return (cm[*us1] - cm[*--us2]); 2089c2aa98e2SPeter Wemm if (*us1++ == '\0') 2090c2aa98e2SPeter Wemm break; 2091c2aa98e2SPeter Wemm } while (--n != 0); 2092c2aa98e2SPeter Wemm } 2093c2aa98e2SPeter Wemm return (0); 2094c2aa98e2SPeter Wemm } 2095