1 /* 2 * Copyright (c) 1983, 1995 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)conf.c 8.169 (Berkeley) 05/17/95"; 11 #endif /* not lint */ 12 13 # include "sendmail.h" 14 # include "pathnames.h" 15 # include <sys/ioctl.h> 16 # include <sys/param.h> 17 18 /* 19 ** CONF.C -- Sendmail Configuration Tables. 20 ** 21 ** Defines the configuration of this installation. 22 ** 23 ** Configuration Variables: 24 ** HdrInfo -- a table describing well-known header fields. 25 ** Each entry has the field name and some flags, 26 ** which are described in sendmail.h. 27 ** 28 ** Notes: 29 ** I have tried to put almost all the reasonable 30 ** configuration information into the configuration 31 ** file read at runtime. My intent is that anything 32 ** here is a function of the version of UNIX you 33 ** are running, or is really static -- for example 34 ** the headers are a superset of widely used 35 ** protocols. If you find yourself playing with 36 ** this file too much, you may be making a mistake! 37 */ 38 39 40 41 42 /* 43 ** Header info table 44 ** Final (null) entry contains the flags used for any other field. 45 ** 46 ** Not all of these are actually handled specially by sendmail 47 ** at this time. They are included as placeholders, to let 48 ** you know that "someday" I intend to have sendmail do 49 ** something with them. 50 */ 51 52 struct hdrinfo HdrInfo[] = 53 { 54 /* originator fields, most to least significant */ 55 "resent-sender", H_FROM|H_RESENT, 56 "resent-from", H_FROM|H_RESENT, 57 "resent-reply-to", H_FROM|H_RESENT, 58 "sender", H_FROM, 59 "from", H_FROM, 60 "reply-to", H_FROM, 61 "full-name", H_ACHECK, 62 "return-receipt-to", H_FROM|H_RECEIPTTO, 63 "errors-to", H_FROM|H_ERRORSTO, 64 65 /* destination fields */ 66 "to", H_RCPT, 67 "resent-to", H_RCPT|H_RESENT, 68 "cc", H_RCPT, 69 "resent-cc", H_RCPT|H_RESENT, 70 "bcc", H_RCPT|H_STRIPVAL, 71 "resent-bcc", H_RCPT|H_STRIPVAL|H_RESENT, 72 "apparently-to", H_RCPT, 73 74 /* message identification and control */ 75 "message-id", 0, 76 "resent-message-id", H_RESENT, 77 "message", H_EOH, 78 "text", H_EOH, 79 80 /* date fields */ 81 "date", 0, 82 "resent-date", H_RESENT, 83 84 /* trace fields */ 85 "received", H_TRACE|H_FORCE, 86 "x400-received", H_TRACE|H_FORCE, 87 "via", H_TRACE|H_FORCE, 88 "mail-from", H_TRACE|H_FORCE, 89 90 /* miscellaneous fields */ 91 "comments", H_FORCE, 92 "return-path", H_FORCE|H_ACHECK, 93 "content-transfer-encoding", H_CTE, 94 "content-type", H_CTYPE, 95 "content-length", H_ACHECK, 96 97 NULL, 0, 98 }; 99 100 101 102 /* 103 ** Location of system files/databases/etc. 104 */ 105 106 char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */ 107 108 109 110 /* 111 ** Privacy values 112 */ 113 114 struct prival PrivacyValues[] = 115 { 116 "public", PRIV_PUBLIC, 117 "needmailhelo", PRIV_NEEDMAILHELO, 118 "needexpnhelo", PRIV_NEEDEXPNHELO, 119 "needvrfyhelo", PRIV_NEEDVRFYHELO, 120 "noexpn", PRIV_NOEXPN, 121 "novrfy", PRIV_NOVRFY, 122 "restrictmailq", PRIV_RESTRICTMAILQ, 123 "restrictqrun", PRIV_RESTRICTQRUN, 124 "authwarnings", PRIV_AUTHWARNINGS, 125 "noreceipts", PRIV_NORECEIPTS, 126 "goaway", PRIV_GOAWAY, 127 NULL, 0, 128 }; 129 130 131 132 /* 133 ** Miscellaneous stuff. 134 */ 135 136 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 137 /* 138 ** SETDEFAULTS -- set default values 139 ** 140 ** Because of the way freezing is done, these must be initialized 141 ** using direct code. 142 ** 143 ** Parameters: 144 ** e -- the default envelope. 145 ** 146 ** Returns: 147 ** none. 148 ** 149 ** Side Effects: 150 ** Initializes a bunch of global variables to their 151 ** default values. 152 */ 153 154 #define DAYS * 24 * 60 * 60 155 156 void 157 setdefaults(e) 158 register ENVELOPE *e; 159 { 160 int i; 161 extern void inittimeouts(); 162 extern void setdefuser(); 163 extern void setupmaps(); 164 extern void setupmailers(); 165 166 SpaceSub = ' '; /* option B */ 167 QueueLA = 8; /* option x */ 168 RefuseLA = 12; /* option X */ 169 WkRecipFact = 30000L; /* option y */ 170 WkClassFact = 1800L; /* option z */ 171 WkTimeFact = 90000L; /* option Z */ 172 QueueFactor = WkRecipFact * 20; /* option q */ 173 FileMode = (RealUid != geteuid()) ? 0644 : 0600; 174 /* option F */ 175 DefUid = 1; /* option u */ 176 DefGid = 1; /* option g */ 177 CheckpointInterval = 10; /* option C */ 178 MaxHopCount = 25; /* option h */ 179 e->e_sendmode = SM_FORK; /* option d */ 180 e->e_errormode = EM_PRINT; /* option e */ 181 SevenBitInput = FALSE; /* option 7 */ 182 MaxMciCache = 1; /* option k */ 183 MciCacheTimeout = 300; /* option K */ 184 LogLevel = 9; /* option L */ 185 inittimeouts(NULL); /* option r */ 186 PrivacyFlags = 0; /* option p */ 187 #if MIME8TO7 188 MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */ 189 #else 190 MimeMode = MM_PASS8BIT; 191 #endif 192 for (i = 0; i < MAXTOCLASS; i++) 193 { 194 TimeOuts.to_q_return[i] = 5 DAYS; /* option T */ 195 TimeOuts.to_q_warning[i] = 0; /* option T */ 196 } 197 ServiceSwitchFile = "/etc/service.switch"; 198 HostsFile = _PATH_HOSTS; 199 setdefuser(); 200 setupmaps(); 201 setupmailers(); 202 } 203 204 205 /* 206 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 207 */ 208 209 void 210 setdefuser() 211 { 212 struct passwd *defpwent; 213 static char defuserbuf[40]; 214 215 DefUser = defuserbuf; 216 if ((defpwent = sm_getpwuid(DefUid)) != NULL) 217 strcpy(defuserbuf, defpwent->pw_name); 218 else 219 strcpy(defuserbuf, "nobody"); 220 } 221 /* 222 ** HOST_MAP_INIT -- initialize host class structures 223 */ 224 225 bool host_map_init __P((MAP *map, char *args)); 226 227 bool 228 host_map_init(map, args) 229 MAP *map; 230 char *args; 231 { 232 register char *p = args; 233 234 for (;;) 235 { 236 while (isascii(*p) && isspace(*p)) 237 p++; 238 if (*p != '-') 239 break; 240 switch (*++p) 241 { 242 case 'a': 243 map->map_app = ++p; 244 break; 245 } 246 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 247 p++; 248 if (*p != '\0') 249 *p++ = '\0'; 250 } 251 if (map->map_app != NULL) 252 map->map_app = newstr(map->map_app); 253 return TRUE; 254 } 255 /* 256 ** SETUPMAILERS -- initialize default mailers 257 */ 258 259 void 260 setupmailers() 261 { 262 char buf[100]; 263 extern void makemailer(); 264 265 strcpy(buf, "prog, P=/bin/sh, F=lsoD, T=X-Unix, A=sh -c $u"); 266 makemailer(buf); 267 268 strcpy(buf, "*file*, P=[FILE], F=lsDFMPEou, T=X-Unix, A=FILE"); 269 makemailer(buf); 270 271 strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 272 makemailer(buf); 273 } 274 /* 275 ** SETUPMAPS -- set up map classes 276 */ 277 278 #define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \ 279 { \ 280 extern bool parse __P((MAP *, char *)); \ 281 extern bool open __P((MAP *, int)); \ 282 extern void close __P((MAP *)); \ 283 extern char *lookup __P((MAP *, char *, char **, int *)); \ 284 extern void store __P((MAP *, char *, char *)); \ 285 s = stab(name, ST_MAPCLASS, ST_ENTER); \ 286 s->s_mapclass.map_cname = name; \ 287 s->s_mapclass.map_ext = ext; \ 288 s->s_mapclass.map_cflags = flags; \ 289 s->s_mapclass.map_parse = parse; \ 290 s->s_mapclass.map_open = open; \ 291 s->s_mapclass.map_close = close; \ 292 s->s_mapclass.map_lookup = lookup; \ 293 s->s_mapclass.map_store = store; \ 294 } 295 296 void 297 setupmaps() 298 { 299 register STAB *s; 300 301 #ifdef NEWDB 302 MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 303 map_parseargs, hash_map_open, db_map_close, 304 db_map_lookup, db_map_store); 305 306 MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 307 map_parseargs, bt_map_open, db_map_close, 308 db_map_lookup, db_map_store); 309 #endif 310 311 #ifdef NDBM 312 MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE, 313 map_parseargs, ndbm_map_open, ndbm_map_close, 314 ndbm_map_lookup, ndbm_map_store); 315 #endif 316 317 #ifdef NIS 318 MAPDEF("nis", NULL, MCF_ALIASOK, 319 map_parseargs, nis_map_open, null_map_close, 320 nis_map_lookup, null_map_store); 321 #endif 322 323 #ifdef NISPLUS 324 MAPDEF("nisplus", NULL, MCF_ALIASOK, 325 map_parseargs, nisplus_map_open, null_map_close, 326 nisplus_map_lookup, null_map_store); 327 #endif 328 329 #ifdef HESIOD 330 MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY, 331 map_parseargs, null_map_open, null_map_close, 332 hes_map_lookup, null_map_store); 333 #endif 334 335 #ifdef NETINFO 336 MAPDEF("netinfo", NULL, MCF_ALIASOK, 337 map_parseargs, ni_map_open, null_map_close, 338 ni_map_lookup, null_map_store); 339 #endif 340 341 #if 0 342 MAPDEF("dns", NULL, 0, 343 dns_map_init, null_map_open, null_map_close, 344 dns_map_lookup, null_map_store); 345 #endif 346 347 #if NAMED_BIND 348 /* best MX DNS lookup */ 349 MAPDEF("bestmx", NULL, MCF_OPTFILE, 350 map_parseargs, null_map_open, null_map_close, 351 bestmx_map_lookup, null_map_store); 352 #endif 353 354 MAPDEF("host", NULL, 0, 355 host_map_init, null_map_open, null_map_close, 356 host_map_lookup, null_map_store); 357 358 MAPDEF("text", NULL, MCF_ALIASOK, 359 map_parseargs, text_map_open, null_map_close, 360 text_map_lookup, null_map_store); 361 362 MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY, 363 map_parseargs, stab_map_open, null_map_close, 364 stab_map_lookup, stab_map_store); 365 366 MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE, 367 map_parseargs, impl_map_open, impl_map_close, 368 impl_map_lookup, impl_map_store); 369 370 /* access to system passwd file */ 371 MAPDEF("user", NULL, MCF_OPTFILE, 372 map_parseargs, user_map_open, null_map_close, 373 user_map_lookup, null_map_store); 374 375 /* dequote map */ 376 MAPDEF("dequote", NULL, 0, 377 dequote_init, null_map_open, null_map_close, 378 dequote_map, null_map_store); 379 380 #ifdef USERDB 381 /* user database */ 382 MAPDEF("userdb", ".db", 0, 383 map_parseargs, null_map_open, null_map_close, 384 udb_map_lookup, null_map_store); 385 #endif 386 387 /* arbitrary programs */ 388 MAPDEF("program", NULL, MCF_ALIASOK, 389 map_parseargs, null_map_open, null_map_close, 390 prog_map_lookup, null_map_store); 391 392 /* sequenced maps */ 393 MAPDEF("sequence", NULL, MCF_ALIASOK, 394 seq_map_parse, null_map_open, null_map_close, 395 seq_map_lookup, seq_map_store); 396 397 /* switched interface to sequenced maps */ 398 MAPDEF("switch", NULL, MCF_ALIASOK, 399 map_parseargs, switch_map_open, null_map_close, 400 seq_map_lookup, seq_map_store); 401 } 402 403 #undef MAPDEF 404 /* 405 ** INITHOSTMAPS -- initial host-dependent maps 406 ** 407 ** This should act as an interface to any local service switch 408 ** provided by the host operating system. 409 ** 410 ** Parameters: 411 ** none 412 ** 413 ** Returns: 414 ** none 415 ** 416 ** Side Effects: 417 ** Should define maps "host" and "users" as necessary 418 ** for this OS. If they are not defined, they will get 419 ** a default value later. It should check to make sure 420 ** they are not defined first, since it's possible that 421 ** the config file has provided an override. 422 */ 423 424 void 425 inithostmaps() 426 { 427 register int i; 428 int nmaps; 429 char *maptype[MAXMAPSTACK]; 430 short mapreturn[MAXMAPACTIONS]; 431 char buf[MAXLINE]; 432 433 /* 434 ** Set up default hosts maps. 435 */ 436 437 #if 0 438 nmaps = switch_map_find("hosts", maptype, mapreturn); 439 for (i = 0; i < nmaps; i++) 440 { 441 if (strcmp(maptype[i], "files") == 0 && 442 stab("hosts.files", ST_MAP, ST_FIND) == NULL) 443 { 444 strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts"); 445 makemapentry(buf); 446 } 447 #if NAMED_BIND 448 else if (strcmp(maptype[i], "dns") == 0 && 449 stab("hosts.dns", ST_MAP, ST_FIND) == NULL) 450 { 451 strcpy(buf, "hosts.dns dns A"); 452 makemapentry(buf); 453 } 454 #endif 455 #ifdef NISPLUS 456 else if (strcmp(maptype[i], "nisplus") == 0 && 457 stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL) 458 { 459 strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir"); 460 makemapentry(buf); 461 } 462 #endif 463 #ifdef NIS 464 else if (strcmp(maptype[i], "nis") == 0 && 465 stab("hosts.nis", ST_MAP, ST_FIND) == NULL) 466 { 467 strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname"); 468 makemapentry(buf); 469 } 470 #endif 471 } 472 #endif 473 474 /* 475 ** Make sure we have a host map. 476 */ 477 478 if (stab("host", ST_MAP, ST_FIND) == NULL) 479 { 480 /* user didn't initialize: set up host map */ 481 strcpy(buf, "host host"); 482 #if NAMED_BIND 483 if (ConfigLevel >= 2) 484 strcat(buf, " -a."); 485 #endif 486 makemapentry(buf); 487 } 488 489 /* 490 ** Set up default aliases maps 491 */ 492 493 nmaps = switch_map_find("aliases", maptype, mapreturn); 494 for (i = 0; i < nmaps; i++) 495 { 496 if (strcmp(maptype[i], "files") == 0 && 497 stab("aliases.files", ST_MAP, ST_FIND) == NULL) 498 { 499 strcpy(buf, "aliases.files implicit /etc/aliases"); 500 makemapentry(buf); 501 } 502 #ifdef NISPLUS 503 else if (strcmp(maptype[i], "nisplus") == 0 && 504 stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL) 505 { 506 strcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion -d mail_aliases.org_dir"); 507 makemapentry(buf); 508 } 509 #endif 510 #ifdef NIS 511 else if (strcmp(maptype[i], "nis") == 0 && 512 stab("aliases.nis", ST_MAP, ST_FIND) == NULL) 513 { 514 strcpy(buf, "aliases.nis nis -d mail.aliases"); 515 makemapentry(buf); 516 } 517 #endif 518 } 519 if (stab("aliases", ST_MAP, ST_FIND) == NULL) 520 { 521 strcpy(buf, "aliases switch aliases"); 522 makemapentry(buf); 523 } 524 strcpy(buf, "switch:aliases"); 525 setalias(buf); 526 527 #if 0 /* "user" map class is a better choice */ 528 /* 529 ** Set up default users maps. 530 */ 531 532 nmaps = switch_map_find("passwd", maptype, mapreturn); 533 for (i = 0; i < nmaps; i++) 534 { 535 if (strcmp(maptype[i], "files") == 0 && 536 stab("users.files", ST_MAP, ST_FIND) == NULL) 537 { 538 strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd"); 539 makemapentry(buf); 540 } 541 #ifdef NISPLUS 542 else if (strcmp(maptype[i], "nisplus") == 0 && 543 stab("users.nisplus", ST_MAP, ST_FIND) == NULL) 544 { 545 strcpy(buf, "users.nisplus nisplus -m -kname -vhome -d passwd.org_dir"); 546 makemapentry(buf); 547 } 548 #endif 549 #ifdef NIS 550 else if (strcmp(maptype[i], "nis") == 0 && 551 stab("users.nis", ST_MAP, ST_FIND) == NULL) 552 { 553 strcpy(buf, "users.nis nis -m -d passwd.byname"); 554 makemapentry(buf); 555 } 556 #endif 557 #ifdef HESIOD 558 else if (strcmp(maptype[i], "hesiod") == 0) && 559 stab("users.hesiod", ST_MAP, ST_FIND) == NULL) 560 { 561 strcpy(buf, "users.hesiod hesiod"); 562 makemapentry(buf); 563 } 564 #endif 565 } 566 if (stab("users", ST_MAP, ST_FIND) == NULL) 567 { 568 strcpy(buf, "users switch -m passwd"); 569 makemapentry(buf); 570 } 571 #endif 572 } 573 /* 574 ** SWITCH_MAP_FIND -- find the list of types associated with a map 575 ** 576 ** This is the system-dependent interface to the service switch. 577 ** 578 ** Parameters: 579 ** service -- the name of the service of interest. 580 ** maptype -- an out-array of strings containing the types 581 ** of access to use for this service. There can 582 ** be at most MAXMAPSTACK types for a single service. 583 ** mapreturn -- an out-array of return information bitmaps 584 ** for the map. 585 ** 586 ** Returns: 587 ** The number of map types filled in, or -1 for failure. 588 */ 589 590 #ifdef SOLARIS 591 # include <nsswitch.h> 592 #endif 593 594 #if defined(ultrix) || defined(__osf__) 595 # include <sys/svcinfo.h> 596 #endif 597 598 int 599 switch_map_find(service, maptype, mapreturn) 600 char *service; 601 char *maptype[MAXMAPSTACK]; 602 short mapreturn[MAXMAPACTIONS]; 603 { 604 register FILE *fp; 605 int svcno; 606 static char buf[MAXLINE]; 607 608 #ifdef SOLARIS 609 struct __nsw_switchconfig *nsw_conf; 610 enum __nsw_parse_err pserr; 611 struct __nsw_lookup *lk; 612 int nsw_rc; 613 static struct __nsw_lookup lkp0 = 614 { "files", {1, 0, 0, 0}, NULL, NULL }; 615 static struct __nsw_switchconfig lkp_default = 616 { 0, "sendmail", 3, &lkp0 }; 617 618 if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL) 619 lk = lkp_default.lookups; 620 else 621 lk = nsw_conf->lookups; 622 svcno = 0; 623 while (lk != NULL) 624 { 625 maptype[svcno] = lk->service_name; 626 if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN) 627 mapreturn[MA_NOTFOUND] |= 1 << svcno; 628 if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN) 629 mapreturn[MA_TRYAGAIN] |= 1 << svcno; 630 if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN) 631 mapreturn[MA_TRYAGAIN] |= 1 << svcno; 632 svcno++; 633 lk = lk->next; 634 } 635 return svcno; 636 #endif 637 638 #if defined(ultrix) || defined(__osf__) 639 struct svcinfo *svcinfo; 640 int svc; 641 642 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 643 mapreturn[svcno] = 0; 644 645 svcinfo = getsvc(); 646 if (svcinfo == NULL) 647 goto punt; 648 if (strcmp(service, "hosts") == 0) 649 svc = SVC_HOSTS; 650 else if (strcmp(service, "aliases") == 0) 651 svc = SVC_ALIASES; 652 else if (strcmp(service, "passwd") == 0) 653 svc = SVC_PASSWD; 654 else 655 return -1; 656 for (svcno = 0; svcno < SVC_PATHSIZE; svcno++) 657 { 658 switch (svcinfo->svcpath[svc][svcno]) 659 { 660 case SVC_LOCAL: 661 maptype[svcno] = "files"; 662 break; 663 664 case SVC_YP: 665 maptype[svcno] = "nis"; 666 break; 667 668 case SVC_BIND: 669 maptype[svcno] = "dns"; 670 break; 671 672 #ifdef SVC_HESIOD 673 case SVC_HESIOD: 674 maptype[svcno] = "hesiod"; 675 break; 676 #endif 677 678 case SVC_LAST: 679 return svcno; 680 } 681 } 682 return svcno; 683 #endif 684 685 #if !defined(SOLARIS) && !defined(ultrix) && !defined(__osf__) 686 /* 687 ** Fall-back mechanism. 688 */ 689 690 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 691 mapreturn[svcno] = 0; 692 693 svcno = 0; 694 fp = fopen(ServiceSwitchFile, "r"); 695 if (fp != NULL) 696 { 697 while (fgets(buf, sizeof buf, fp) != NULL) 698 { 699 register char *p; 700 701 p = strpbrk(buf, "#\n"); 702 if (p != NULL) 703 *p = '\0'; 704 p = strpbrk(buf, " \t"); 705 if (p != NULL) 706 *p++ = '\0'; 707 if (strcmp(buf, service) != 0) 708 continue; 709 710 /* got the right service -- extract data */ 711 do 712 { 713 while (isspace(*p)) 714 p++; 715 if (*p == '\0') 716 break; 717 maptype[svcno++] = p; 718 p = strpbrk(p, " \t"); 719 if (p != NULL) 720 *p++ = '\0'; 721 } while (p != NULL); 722 break; 723 } 724 fclose(fp); 725 return svcno; 726 } 727 #endif 728 729 /* if the service file doesn't work, use an absolute fallback */ 730 punt: 731 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 732 mapreturn[svcno] = 0; 733 svcno = 0; 734 if (strcmp(service, "aliases") == 0) 735 { 736 maptype[svcno++] = "files"; 737 #ifdef AUTO_NIS_ALIASES 738 # ifdef NISPLUS 739 maptype[svcno++] = "nisplus"; 740 # endif 741 # ifdef NIS 742 maptype[svcno++] = "nis"; 743 # endif 744 #endif 745 return svcno; 746 } 747 if (strcmp(service, "hosts") == 0) 748 { 749 # if NAMED_BIND 750 maptype[svcno++] = "dns"; 751 # else 752 # if defined(sun) && !defined(BSD) && !defined(SOLARIS) 753 /* SunOS */ 754 maptype[svcno++] = "nis"; 755 # endif 756 # endif 757 maptype[svcno++] = "files"; 758 return svcno; 759 } 760 return -1; 761 } 762 /* 763 ** USERNAME -- return the user id of the logged in user. 764 ** 765 ** Parameters: 766 ** none. 767 ** 768 ** Returns: 769 ** The login name of the logged in user. 770 ** 771 ** Side Effects: 772 ** none. 773 ** 774 ** Notes: 775 ** The return value is statically allocated. 776 */ 777 778 char * 779 username() 780 { 781 static char *myname = NULL; 782 extern char *getlogin(); 783 register struct passwd *pw; 784 785 /* cache the result */ 786 if (myname == NULL) 787 { 788 myname = getlogin(); 789 if (myname == NULL || myname[0] == '\0') 790 { 791 pw = sm_getpwuid(RealUid); 792 if (pw != NULL) 793 myname = newstr(pw->pw_name); 794 } 795 else 796 { 797 uid_t uid = RealUid; 798 799 myname = newstr(myname); 800 if ((pw = sm_getpwnam(myname)) == NULL || 801 (uid != 0 && uid != pw->pw_uid)) 802 { 803 pw = sm_getpwuid(uid); 804 if (pw != NULL) 805 myname = newstr(pw->pw_name); 806 } 807 } 808 if (myname == NULL || myname[0] == '\0') 809 { 810 syserr("554 Who are you?"); 811 myname = "postmaster"; 812 } 813 } 814 815 return (myname); 816 } 817 /* 818 ** TTYPATH -- Get the path of the user's tty 819 ** 820 ** Returns the pathname of the user's tty. Returns NULL if 821 ** the user is not logged in or if s/he has write permission 822 ** denied. 823 ** 824 ** Parameters: 825 ** none 826 ** 827 ** Returns: 828 ** pathname of the user's tty. 829 ** NULL if not logged in or write permission denied. 830 ** 831 ** Side Effects: 832 ** none. 833 ** 834 ** WARNING: 835 ** Return value is in a local buffer. 836 ** 837 ** Called By: 838 ** savemail 839 */ 840 841 char * 842 ttypath() 843 { 844 struct stat stbuf; 845 register char *pathn; 846 extern char *ttyname(); 847 extern char *getlogin(); 848 849 /* compute the pathname of the controlling tty */ 850 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 851 (pathn = ttyname(0)) == NULL) 852 { 853 errno = 0; 854 return (NULL); 855 } 856 857 /* see if we have write permission */ 858 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 859 { 860 errno = 0; 861 return (NULL); 862 } 863 864 /* see if the user is logged in */ 865 if (getlogin() == NULL) 866 return (NULL); 867 868 /* looks good */ 869 return (pathn); 870 } 871 /* 872 ** CHECKCOMPAT -- check for From and To person compatible. 873 ** 874 ** This routine can be supplied on a per-installation basis 875 ** to determine whether a person is allowed to send a message. 876 ** This allows restriction of certain types of internet 877 ** forwarding or registration of users. 878 ** 879 ** If the hosts are found to be incompatible, an error 880 ** message should be given using "usrerr" and an EX_ code 881 ** should be returned. You can also set to->q_status to 882 ** a DSN-style status code. 883 ** 884 ** EF_NO_BODY_RETN can be set in e->e_flags to suppress the 885 ** body during the return-to-sender function; this should be done 886 ** on huge messages. This bit may already be set by the ESMTP 887 ** protocol. 888 ** 889 ** Parameters: 890 ** to -- the person being sent to. 891 ** 892 ** Returns: 893 ** an exit status 894 ** 895 ** Side Effects: 896 ** none (unless you include the usrerr stuff) 897 */ 898 899 int 900 checkcompat(to, e) 901 register ADDRESS *to; 902 register ENVELOPE *e; 903 { 904 # ifdef lint 905 if (to == NULL) 906 to++; 907 # endif /* lint */ 908 909 if (tTd(49, 1)) 910 printf("checkcompat(to=%s, from=%s)\n", 911 to->q_paddr, e->e_from.q_paddr); 912 913 # ifdef EXAMPLE_CODE 914 /* this code is intended as an example only */ 915 register STAB *s; 916 917 s = stab("arpa", ST_MAILER, ST_FIND); 918 if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 && 919 to->q_mailer == s->s_mailer) 920 { 921 usrerr("553 No ARPA mail through this machine: see your system administration"); 922 /* e->e_flags |= EF_NO_BODY_RETN; to supress body on return */ 923 to->q_status = "5.7.1"; 924 return (EX_UNAVAILABLE); 925 } 926 # endif /* EXAMPLE_CODE */ 927 return (EX_OK); 928 } 929 /* 930 ** SETSIGNAL -- set a signal handler 931 ** 932 ** This is essentially old BSD "signal(3)". 933 */ 934 935 sigfunc_t 936 setsignal(sig, handler) 937 int sig; 938 sigfunc_t handler; 939 { 940 #if defined(SYS5SIGNALS) || defined(BSD4_3) || defined(_AUX_SOURCE) 941 return signal(sig, handler); 942 #else 943 struct sigaction n, o; 944 945 bzero(&n, sizeof n); 946 n.sa_handler = handler; 947 # ifdef SA_RESTART 948 n.sa_flags = SA_RESTART; 949 # endif 950 if (sigaction(sig, &n, &o) < 0) 951 return SIG_ERR; 952 return o.sa_handler; 953 #endif 954 } 955 /* 956 ** HOLDSIGS -- arrange to hold all signals 957 ** 958 ** Parameters: 959 ** none. 960 ** 961 ** Returns: 962 ** none. 963 ** 964 ** Side Effects: 965 ** Arranges that signals are held. 966 */ 967 968 void 969 holdsigs() 970 { 971 } 972 /* 973 ** RLSESIGS -- arrange to release all signals 974 ** 975 ** This undoes the effect of holdsigs. 976 ** 977 ** Parameters: 978 ** none. 979 ** 980 ** Returns: 981 ** none. 982 ** 983 ** Side Effects: 984 ** Arranges that signals are released. 985 */ 986 987 void 988 rlsesigs() 989 { 990 } 991 /* 992 ** INIT_MD -- do machine dependent initializations 993 ** 994 ** Systems that have global modes that should be set should do 995 ** them here rather than in main. 996 */ 997 998 #ifdef _AUX_SOURCE 999 # include <compat.h> 1000 #endif 1001 1002 void 1003 init_md(argc, argv) 1004 int argc; 1005 char **argv; 1006 { 1007 #ifdef _AUX_SOURCE 1008 setcompat(getcompat() | COMPAT_BSDPROT); 1009 #endif 1010 1011 #ifdef VENDOR_DEFAULT 1012 VendorCode = VENDOR_DEFAULT; 1013 #else 1014 VendorCode = VENDOR_BERKELEY; 1015 #endif 1016 } 1017 /* 1018 ** INIT_VENDOR_MACROS -- vendor-dependent macro initializations 1019 ** 1020 ** Called once, on startup. 1021 ** 1022 ** Parameters: 1023 ** e -- the global envelope. 1024 ** 1025 ** Returns: 1026 ** none. 1027 ** 1028 ** Side Effects: 1029 ** vendor-dependent. 1030 */ 1031 1032 void 1033 init_vendor_macros(e) 1034 register ENVELOPE *e; 1035 { 1036 } 1037 /* 1038 ** GETLA -- get the current load average 1039 ** 1040 ** This code stolen from la.c. 1041 ** 1042 ** Parameters: 1043 ** none. 1044 ** 1045 ** Returns: 1046 ** The current load average as an integer. 1047 ** 1048 ** Side Effects: 1049 ** none. 1050 */ 1051 1052 /* try to guess what style of load average we have */ 1053 #define LA_ZERO 1 /* always return load average as zero */ 1054 #define LA_INT 2 /* read kmem for avenrun; interpret as long */ 1055 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 1056 #define LA_SUBR 4 /* call getloadavg */ 1057 #define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */ 1058 #define LA_SHORT 6 /* read kmem for avenrun; interpret as short */ 1059 #define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */ 1060 #define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */ 1061 #define LA_DGUX 9 /* special DGUX implementation */ 1062 #define LA_HPUX 10 /* special HPUX implementation */ 1063 1064 /* do guesses based on general OS type */ 1065 #ifndef LA_TYPE 1066 # define LA_TYPE LA_ZERO 1067 #endif 1068 1069 #ifndef FSHIFT 1070 # if defined(unixpc) 1071 # define FSHIFT 5 1072 # endif 1073 1074 # if defined(__alpha) || defined(IRIX) 1075 # define FSHIFT 10 1076 # endif 1077 1078 # if defined(_AIX3) 1079 # define FSHIFT 16 1080 # endif 1081 #endif 1082 1083 #ifndef FSHIFT 1084 # define FSHIFT 8 1085 #endif 1086 1087 #ifndef FSCALE 1088 # define FSCALE (1 << FSHIFT) 1089 #endif 1090 1091 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) 1092 1093 #include <nlist.h> 1094 1095 #ifdef IRIX64 1096 # define nlist nlist64 1097 #endif 1098 1099 #ifndef LA_AVENRUN 1100 # ifdef SYSTEM5 1101 # define LA_AVENRUN "avenrun" 1102 # else 1103 # define LA_AVENRUN "_avenrun" 1104 # endif 1105 #endif 1106 1107 /* _PATH_UNIX should be defined in <paths.h> */ 1108 #ifndef _PATH_UNIX 1109 # if defined(SYSTEM5) 1110 # define _PATH_UNIX "/unix" 1111 # else 1112 # define _PATH_UNIX "/vmunix" 1113 # endif 1114 #endif 1115 1116 struct nlist Nl[] = 1117 { 1118 { LA_AVENRUN }, 1119 #define X_AVENRUN 0 1120 { 0 }, 1121 }; 1122 1123 getla() 1124 { 1125 static int kmem = -1; 1126 #if LA_TYPE == LA_INT 1127 long avenrun[3]; 1128 #else 1129 # if LA_TYPE == LA_SHORT 1130 short avenrun[3]; 1131 # else 1132 double avenrun[3]; 1133 # endif 1134 #endif 1135 extern int errno; 1136 extern off_t lseek(); 1137 1138 if (kmem < 0) 1139 { 1140 kmem = open("/dev/kmem", 0, 0); 1141 if (kmem < 0) 1142 { 1143 if (tTd(3, 1)) 1144 printf("getla: open(/dev/kmem): %s\n", 1145 errstring(errno)); 1146 return (-1); 1147 } 1148 (void) fcntl(kmem, F_SETFD, 1); 1149 1150 #ifdef _AIX3 1151 if (knlist(Nl, 1, sizeof Nl[0]) < 0) 1152 #else 1153 if (nlist(_PATH_UNIX, Nl) < 0) 1154 #endif 1155 { 1156 if (tTd(3, 1)) 1157 printf("getla: nlist(%s): %s\n", _PATH_UNIX, 1158 errstring(errno)); 1159 return (-1); 1160 } 1161 if (Nl[X_AVENRUN].n_value == 0) 1162 { 1163 if (tTd(3, 1)) 1164 printf("getla: nlist(%s, %s) ==> 0\n", 1165 _PATH_UNIX, LA_AVENRUN); 1166 return (-1); 1167 } 1168 #ifdef NAMELISTMASK 1169 Nl[X_AVENRUN].n_value &= NAMELISTMASK; 1170 #endif 1171 } 1172 if (tTd(3, 20)) 1173 printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); 1174 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 || 1175 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 1176 { 1177 /* thank you Ian */ 1178 if (tTd(3, 1)) 1179 printf("getla: lseek or read: %s\n", errstring(errno)); 1180 return (-1); 1181 } 1182 # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) 1183 if (tTd(3, 5)) 1184 { 1185 printf("getla: avenrun = %d", avenrun[0]); 1186 if (tTd(3, 15)) 1187 printf(", %d, %d", avenrun[1], avenrun[2]); 1188 printf("\n"); 1189 } 1190 if (tTd(3, 1)) 1191 printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1192 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1193 # else /* LA_TYPE == LA_FLOAT */ 1194 if (tTd(3, 5)) 1195 { 1196 printf("getla: avenrun = %g", avenrun[0]); 1197 if (tTd(3, 15)) 1198 printf(", %g, %g", avenrun[1], avenrun[2]); 1199 printf("\n"); 1200 } 1201 if (tTd(3, 1)) 1202 printf("getla: %d\n", (int) (avenrun[0] +0.5)); 1203 return ((int) (avenrun[0] + 0.5)); 1204 # endif 1205 } 1206 1207 #endif /* LA_TYPE == LA_INT or LA_SHORT or LA_FLOAT */ 1208 1209 #if LA_TYPE == LA_READKSYM 1210 1211 # include <sys/ksym.h> 1212 1213 getla() 1214 { 1215 static int kmem = -1; 1216 long avenrun[3]; 1217 extern int errno; 1218 struct mioc_rksym mirk; 1219 1220 if (kmem < 0) 1221 { 1222 kmem = open("/dev/kmem", 0, 0); 1223 if (kmem < 0) 1224 { 1225 if (tTd(3, 1)) 1226 printf("getla: open(/dev/kmem): %s\n", 1227 errstring(errno)); 1228 return (-1); 1229 } 1230 (void) fcntl(kmem, F_SETFD, 1); 1231 } 1232 mirk.mirk_symname = LA_AVENRUN; 1233 mirk.mirk_buf = avenrun; 1234 mirk.mirk_buflen = sizeof(avenrun); 1235 if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0) 1236 { 1237 if (tTd(3, 1)) 1238 printf("getla: ioctl(MIOC_READKSYM) failed: %s\n", 1239 errstring(errno)); 1240 return -1; 1241 } 1242 if (tTd(3, 5)) 1243 { 1244 printf("getla: avenrun = %d", avenrun[0]); 1245 if (tTd(3, 15)) 1246 printf(", %d, %d", avenrun[1], avenrun[2]); 1247 printf("\n"); 1248 } 1249 if (tTd(3, 1)) 1250 printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1251 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1252 } 1253 1254 #endif /* LA_TYPE == LA_READKSYM */ 1255 1256 #if LA_TYPE == LA_DGUX 1257 1258 # include <sys/dg_sys_info.h> 1259 1260 int 1261 getla() 1262 { 1263 struct dg_sys_info_load_info load_info; 1264 1265 dg_sys_info((long *)&load_info, 1266 DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); 1267 1268 if (tTd(3, 1)) 1269 printf("getla: %d\n", (int) (load_info.one_minute + 0.5)); 1270 1271 return((int) (load_info.one_minute + 0.5)); 1272 } 1273 1274 #endif /* LA_TYPE == LA_DGUX */ 1275 1276 #if LA_TYPE == LA_HPUX 1277 1278 struct pst_dynamic; 1279 1280 # include <sys/param.h> 1281 # include <sys/pstat.h> 1282 1283 int 1284 getla() 1285 { 1286 struct pst_dynamic pstd; 1287 1288 if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic), 1289 (size_t) 1, 0) == -1) 1290 return 0; 1291 1292 if (tTd(3, 1)) 1293 printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); 1294 1295 return (int) (pstd.psd_avg_1_min + 0.5); 1296 } 1297 1298 #endif /* LA_TYPE == LA_HPUX */ 1299 1300 #if LA_TYPE == LA_SUBR 1301 1302 int 1303 getla() 1304 { 1305 double avenrun[3]; 1306 1307 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 1308 { 1309 if (tTd(3, 1)) 1310 perror("getla: getloadavg failed:"); 1311 return (-1); 1312 } 1313 if (tTd(3, 1)) 1314 printf("getla: %d\n", (int) (avenrun[0] +0.5)); 1315 return ((int) (avenrun[0] + 0.5)); 1316 } 1317 1318 #endif /* LA_TYPE == LA_SUBR */ 1319 1320 #if LA_TYPE == LA_MACH 1321 1322 /* 1323 ** This has been tested on NEXTSTEP release 2.1/3.X. 1324 */ 1325 1326 #if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 1327 # include <mach/mach.h> 1328 #else 1329 # include <mach.h> 1330 #endif 1331 1332 getla() 1333 { 1334 processor_set_t default_set; 1335 kern_return_t error; 1336 unsigned int info_count; 1337 struct processor_set_basic_info info; 1338 host_t host; 1339 1340 error = processor_set_default(host_self(), &default_set); 1341 if (error != KERN_SUCCESS) 1342 return -1; 1343 info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 1344 if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, 1345 &host, (processor_set_info_t)&info, 1346 &info_count) != KERN_SUCCESS) 1347 { 1348 return -1; 1349 } 1350 return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE; 1351 } 1352 1353 #endif /* LA_TYPE == LA_MACH */ 1354 1355 #if LA_TYPE == LA_PROCSTR 1356 1357 /* 1358 ** Read /proc/loadavg for the load average. This is assumed to be 1359 ** in a format like "0.15 0.12 0.06". 1360 ** 1361 ** Initially intended for Linux. This has been in the kernel 1362 ** since at least 0.99.15. 1363 */ 1364 1365 # ifndef _PATH_LOADAVG 1366 # define _PATH_LOADAVG "/proc/loadavg" 1367 # endif 1368 1369 int 1370 getla() 1371 { 1372 double avenrun; 1373 register int result; 1374 FILE *fp; 1375 1376 fp = fopen(_PATH_LOADAVG, "r"); 1377 if (fp == NULL) 1378 { 1379 if (tTd(3, 1)) 1380 printf("getla: fopen(%s): %s\n", 1381 _PATH_LOADAVG, errstring(errno)); 1382 return -1; 1383 } 1384 result = fscanf(fp, "%lf", &avenrun); 1385 fclose(fp); 1386 if (result != 1) 1387 { 1388 if (tTd(3, 1)) 1389 printf("getla: fscanf() = %d: %s\n", 1390 result, errstring(errno)); 1391 return -1; 1392 } 1393 1394 if (tTd(3, 1)) 1395 printf("getla(): %.2f\n", avenrun); 1396 1397 return ((int) (avenrun + 0.5)); 1398 } 1399 1400 #endif /* LA_TYPE == LA_PROCSTR */ 1401 1402 #if LA_TYPE == LA_ZERO 1403 1404 getla() 1405 { 1406 if (tTd(3, 1)) 1407 printf("getla: ZERO\n"); 1408 return (0); 1409 } 1410 1411 #endif /* LA_TYPE == LA_ZERO */ 1412 1413 1414 /* 1415 * Copyright 1989 Massachusetts Institute of Technology 1416 * 1417 * Permission to use, copy, modify, distribute, and sell this software and its 1418 * documentation for any purpose is hereby granted without fee, provided that 1419 * the above copyright notice appear in all copies and that both that 1420 * copyright notice and this permission notice appear in supporting 1421 * documentation, and that the name of M.I.T. not be used in advertising or 1422 * publicity pertaining to distribution of the software without specific, 1423 * written prior permission. M.I.T. makes no representations about the 1424 * suitability of this software for any purpose. It is provided "as is" 1425 * without express or implied warranty. 1426 * 1427 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1428 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. 1429 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1430 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1431 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1432 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1433 * 1434 * Authors: Many and varied... 1435 */ 1436 1437 /* Non Apollo stuff removed by Don Lewis 11/15/93 */ 1438 #ifndef lint 1439 static char rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; 1440 #endif /* !lint */ 1441 1442 #ifdef apollo 1443 # undef volatile 1444 # include <apollo/base.h> 1445 1446 /* ARGSUSED */ 1447 int getloadavg( call_data ) 1448 caddr_t call_data; /* pointer to (double) return value */ 1449 { 1450 double *avenrun = (double *) call_data; 1451 int i; 1452 status_$t st; 1453 long loadav[3]; 1454 proc1_$get_loadav(loadav, &st); 1455 *avenrun = loadav[0] / (double) (1 << 16); 1456 return(0); 1457 } 1458 # endif /* apollo */ 1459 /* 1460 ** SHOULDQUEUE -- should this message be queued or sent? 1461 ** 1462 ** Compares the message cost to the load average to decide. 1463 ** 1464 ** Parameters: 1465 ** pri -- the priority of the message in question. 1466 ** ctime -- the message creation time. 1467 ** 1468 ** Returns: 1469 ** TRUE -- if this message should be queued up for the 1470 ** time being. 1471 ** FALSE -- if the load is low enough to send this message. 1472 ** 1473 ** Side Effects: 1474 ** none. 1475 */ 1476 1477 bool 1478 shouldqueue(pri, ctime) 1479 long pri; 1480 time_t ctime; 1481 { 1482 bool rval; 1483 1484 if (tTd(3, 30)) 1485 printf("shouldqueue: CurrentLA=%d, pri=%d: ", CurrentLA, pri); 1486 if (CurrentLA < QueueLA) 1487 { 1488 if (tTd(3, 30)) 1489 printf("FALSE (CurrentLA < QueueLA)\n"); 1490 return (FALSE); 1491 } 1492 if (CurrentLA >= RefuseLA) 1493 { 1494 if (tTd(3, 30)) 1495 printf("TRUE (CurrentLA >= RefuseLA)\n"); 1496 return (TRUE); 1497 } 1498 rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); 1499 if (tTd(3, 30)) 1500 printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE"); 1501 return rval; 1502 } 1503 /* 1504 ** REFUSECONNECTIONS -- decide if connections should be refused 1505 ** 1506 ** Parameters: 1507 ** none. 1508 ** 1509 ** Returns: 1510 ** TRUE if incoming SMTP connections should be refused 1511 ** (for now). 1512 ** FALSE if we should accept new work. 1513 ** 1514 ** Side Effects: 1515 ** none. 1516 */ 1517 1518 bool 1519 refuseconnections() 1520 { 1521 extern bool enoughspace(); 1522 1523 #ifdef XLA 1524 if (!xla_smtp_ok()) 1525 return TRUE; 1526 #endif 1527 1528 /* this is probably too simplistic */ 1529 return CurrentLA >= RefuseLA || !enoughspace(MinBlocksFree + 1); 1530 } 1531 /* 1532 ** SETPROCTITLE -- set process title for ps 1533 ** 1534 ** Parameters: 1535 ** fmt -- a printf style format string. 1536 ** a, b, c -- possible parameters to fmt. 1537 ** 1538 ** Returns: 1539 ** none. 1540 ** 1541 ** Side Effects: 1542 ** Clobbers argv of our main procedure so ps(1) will 1543 ** display the title. 1544 */ 1545 1546 #define SPT_NONE 0 /* don't use it at all */ 1547 #define SPT_REUSEARGV 1 /* cover argv with title information */ 1548 #define SPT_BUILTIN 2 /* use libc builtin */ 1549 #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ 1550 #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ 1551 #define SPT_WRITEUDOT 5 /* write u. area in kmem */ 1552 1553 #ifndef SPT_TYPE 1554 # define SPT_TYPE SPT_REUSEARGV 1555 #endif 1556 1557 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN 1558 1559 # if SPT_TYPE == SPT_PSTAT 1560 # include <sys/pstat.h> 1561 # endif 1562 # if SPT_TYPE == SPT_PSSTRINGS 1563 # include <machine/vmparam.h> 1564 # include <sys/exec.h> 1565 # ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ 1566 # undef SPT_TYPE 1567 # define SPT_TYPE SPT_REUSEARGV 1568 # else 1569 # ifndef NKPDE /* FreeBSD 2.0 */ 1570 # define NKPDE 63 1571 typedef unsigned int *pt_entry_t; 1572 # endif 1573 # endif 1574 # endif 1575 1576 # if SPT_TYPE == SPT_PSSTRINGS 1577 # define SETPROC_STATIC static 1578 # else 1579 # define SETPROC_STATIC 1580 # endif 1581 1582 # ifndef SPT_PADCHAR 1583 # define SPT_PADCHAR ' ' 1584 # endif 1585 1586 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ 1587 1588 #if SPT_TYPE != SPT_BUILTIN 1589 1590 /*VARARGS1*/ 1591 void 1592 # ifdef __STDC__ 1593 setproctitle(char *fmt, ...) 1594 # else 1595 setproctitle(fmt, va_alist) 1596 char *fmt; 1597 va_dcl 1598 # endif 1599 { 1600 # if SPT_TYPE != SPT_NONE 1601 register char *p; 1602 register int i; 1603 SETPROC_STATIC char buf[MAXLINE]; 1604 VA_LOCAL_DECL 1605 # if SPT_TYPE == SPT_PSTAT 1606 union pstun pst; 1607 # endif 1608 extern char **Argv; 1609 extern char *LastArgv; 1610 1611 p = buf; 1612 1613 /* print sendmail: heading for grep */ 1614 (void) strcpy(p, "sendmail: "); 1615 p += strlen(p); 1616 1617 /* print the argument string */ 1618 VA_START(fmt); 1619 (void) vsprintf(p, fmt, ap); 1620 VA_END; 1621 1622 i = strlen(buf); 1623 1624 # if SPT_TYPE == SPT_PSTAT 1625 pst.pst_command = buf; 1626 pstat(PSTAT_SETCMD, pst, i, 0, 0); 1627 # else 1628 # if SPT_TYPE == SPT_PSSTRINGS 1629 PS_STRINGS->ps_nargvstr = 1; 1630 PS_STRINGS->ps_argvstr = buf; 1631 # else 1632 if (i > LastArgv - Argv[0] - 2) 1633 { 1634 i = LastArgv - Argv[0] - 2; 1635 buf[i] = '\0'; 1636 } 1637 (void) strcpy(Argv[0], buf); 1638 p = &Argv[0][i]; 1639 while (p < LastArgv) 1640 *p++ = SPT_PADCHAR; 1641 Argv[1] = NULL; 1642 # endif /* SPT_TYPE == SPT_PSSTRINGS */ 1643 # endif /* SPT_TYPE == SPT_PSTAT */ 1644 # endif /* SPT_TYPE != SPT_NONE */ 1645 } 1646 1647 #endif /* SPT_TYPE != SPT_BUILTIN */ 1648 /* 1649 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 1650 ** 1651 ** Parameters: 1652 ** sig -- the signal that got us here (unused). 1653 ** 1654 ** Returns: 1655 ** none. 1656 ** 1657 ** Side Effects: 1658 ** Picks up extant zombies. 1659 */ 1660 1661 void 1662 reapchild(sig) 1663 int sig; 1664 { 1665 int olderrno = errno; 1666 # ifdef HASWAITPID 1667 auto int status; 1668 int count; 1669 int pid; 1670 1671 count = 0; 1672 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 1673 { 1674 if (count++ > 1000) 1675 { 1676 #ifdef LOG 1677 syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x", 1678 pid, status); 1679 #endif 1680 break; 1681 } 1682 } 1683 # else 1684 # ifdef WNOHANG 1685 union wait status; 1686 1687 while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 1688 continue; 1689 # else /* WNOHANG */ 1690 auto int status; 1691 1692 while (wait(&status) > 0) 1693 continue; 1694 # endif /* WNOHANG */ 1695 # endif 1696 # ifdef SYS5SIGNALS 1697 (void) setsignal(SIGCHLD, reapchild); 1698 # endif 1699 errno = olderrno; 1700 } 1701 /* 1702 ** UNSETENV -- remove a variable from the environment 1703 ** 1704 ** Not needed on newer systems. 1705 ** 1706 ** Parameters: 1707 ** name -- the string name of the environment variable to be 1708 ** deleted from the current environment. 1709 ** 1710 ** Returns: 1711 ** none. 1712 ** 1713 ** Globals: 1714 ** environ -- a pointer to the current environment. 1715 ** 1716 ** Side Effects: 1717 ** Modifies environ. 1718 */ 1719 1720 #ifndef HASUNSETENV 1721 1722 void 1723 unsetenv(name) 1724 char *name; 1725 { 1726 extern char **environ; 1727 register char **pp; 1728 int len = strlen(name); 1729 1730 for (pp = environ; *pp != NULL; pp++) 1731 { 1732 if (strncmp(name, *pp, len) == 0 && 1733 ((*pp)[len] == '=' || (*pp)[len] == '\0')) 1734 break; 1735 } 1736 1737 for (; *pp != NULL; pp++) 1738 *pp = pp[1]; 1739 } 1740 1741 #endif 1742 /* 1743 ** GETDTABLESIZE -- return number of file descriptors 1744 ** 1745 ** Only on non-BSD systems 1746 ** 1747 ** Parameters: 1748 ** none 1749 ** 1750 ** Returns: 1751 ** size of file descriptor table 1752 ** 1753 ** Side Effects: 1754 ** none 1755 */ 1756 1757 #ifdef SOLARIS 1758 # include <sys/resource.h> 1759 #endif 1760 1761 int 1762 getdtsize() 1763 { 1764 #ifdef RLIMIT_NOFILE 1765 struct rlimit rl; 1766 1767 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) 1768 return rl.rlim_cur; 1769 #endif 1770 1771 # ifdef HASGETDTABLESIZE 1772 return getdtablesize(); 1773 # else 1774 # ifdef _SC_OPEN_MAX 1775 return sysconf(_SC_OPEN_MAX); 1776 # else 1777 return NOFILE; 1778 # endif 1779 # endif 1780 } 1781 /* 1782 ** UNAME -- get the UUCP name of this system. 1783 */ 1784 1785 #ifndef HASUNAME 1786 1787 int 1788 uname(name) 1789 struct utsname *name; 1790 { 1791 FILE *file; 1792 char *n; 1793 1794 name->nodename[0] = '\0'; 1795 1796 /* try /etc/whoami -- one line with the node name */ 1797 if ((file = fopen("/etc/whoami", "r")) != NULL) 1798 { 1799 (void) fgets(name->nodename, NODE_LENGTH + 1, file); 1800 (void) fclose(file); 1801 n = strchr(name->nodename, '\n'); 1802 if (n != NULL) 1803 *n = '\0'; 1804 if (name->nodename[0] != '\0') 1805 return (0); 1806 } 1807 1808 /* try /usr/include/whoami.h -- has a #define somewhere */ 1809 if ((file = fopen("/usr/include/whoami.h", "r")) != NULL) 1810 { 1811 char buf[MAXLINE]; 1812 1813 while (fgets(buf, MAXLINE, file) != NULL) 1814 if (sscanf(buf, "#define sysname \"%*[^\"]\"", 1815 NODE_LENGTH, name->nodename) > 0) 1816 break; 1817 (void) fclose(file); 1818 if (name->nodename[0] != '\0') 1819 return (0); 1820 } 1821 1822 #ifdef TRUST_POPEN 1823 /* 1824 ** Popen is known to have security holes. 1825 */ 1826 1827 /* try uuname -l to return local name */ 1828 if ((file = popen("uuname -l", "r")) != NULL) 1829 { 1830 (void) fgets(name, NODE_LENGTH + 1, file); 1831 (void) pclose(file); 1832 n = strchr(name, '\n'); 1833 if (n != NULL) 1834 *n = '\0'; 1835 if (name->nodename[0] != '\0') 1836 return (0); 1837 } 1838 #endif 1839 1840 return (-1); 1841 } 1842 #endif /* HASUNAME */ 1843 /* 1844 ** INITGROUPS -- initialize groups 1845 ** 1846 ** Stub implementation for System V style systems 1847 */ 1848 1849 #ifndef HASINITGROUPS 1850 1851 initgroups(name, basegid) 1852 char *name; 1853 int basegid; 1854 { 1855 return 0; 1856 } 1857 1858 #endif 1859 /* 1860 ** SETSID -- set session id (for non-POSIX systems) 1861 */ 1862 1863 #ifndef HASSETSID 1864 1865 pid_t 1866 setsid __P ((void)) 1867 { 1868 #ifdef TIOCNOTTY 1869 int fd; 1870 1871 fd = open("/dev/tty", O_RDWR, 0); 1872 if (fd >= 0) 1873 { 1874 (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0); 1875 (void) close(fd); 1876 } 1877 #endif /* TIOCNOTTY */ 1878 # ifdef SYS5SETPGRP 1879 return setpgrp(); 1880 # else 1881 return setpgid(0, getpid()); 1882 # endif 1883 } 1884 1885 #endif 1886 /* 1887 ** FSYNC -- dummy fsync 1888 */ 1889 1890 #ifdef NEEDFSYNC 1891 1892 fsync(fd) 1893 int fd; 1894 { 1895 # ifdef O_SYNC 1896 return fcntl(fd, F_SETFL, O_SYNC); 1897 # else 1898 /* nothing we can do */ 1899 return 0; 1900 # endif 1901 } 1902 1903 #endif 1904 /* 1905 ** DGUX_INET_ADDR -- inet_addr for DG/UX 1906 ** 1907 ** Data General DG/UX version of inet_addr returns a struct in_addr 1908 ** instead of a long. This patches things. Only needed on versions 1909 ** prior to 5.4.3. 1910 */ 1911 1912 #ifdef DGUX_5_4_2 1913 1914 #undef inet_addr 1915 1916 long 1917 dgux_inet_addr(host) 1918 char *host; 1919 { 1920 struct in_addr haddr; 1921 1922 haddr = inet_addr(host); 1923 return haddr.s_addr; 1924 } 1925 1926 #endif 1927 /* 1928 ** GETOPT -- for old systems or systems with bogus implementations 1929 */ 1930 1931 #ifdef NEEDGETOPT 1932 1933 /* 1934 * Copyright (c) 1985 Regents of the University of California. 1935 * All rights reserved. The Berkeley software License Agreement 1936 * specifies the terms and conditions for redistribution. 1937 */ 1938 1939 1940 /* 1941 ** this version hacked to add `atend' flag to allow state machine 1942 ** to reset if invoked by the program to scan args for a 2nd time 1943 */ 1944 1945 #if defined(LIBC_SCCS) && !defined(lint) 1946 static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86"; 1947 #endif /* LIBC_SCCS and not lint */ 1948 1949 #include <stdio.h> 1950 1951 /* 1952 * get option letter from argument vector 1953 */ 1954 #ifdef _CONVEX_SOURCE 1955 extern int optind, opterr, optopt; 1956 extern char *optarg; 1957 #else 1958 int opterr = 1; /* if error message should be printed */ 1959 int optind = 1; /* index into parent argv vector */ 1960 int optopt = 0; /* character checked for validity */ 1961 char *optarg = NULL; /* argument associated with option */ 1962 #endif 1963 1964 #define BADCH (int)'?' 1965 #define EMSG "" 1966 #define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \ 1967 fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);} 1968 1969 getopt(nargc,nargv,ostr) 1970 int nargc; 1971 char *const *nargv; 1972 const char *ostr; 1973 { 1974 static char *place = EMSG; /* option letter processing */ 1975 static char atend = 0; 1976 register char *oli; /* option letter list index */ 1977 1978 if (atend) { 1979 atend = 0; 1980 place = EMSG; 1981 } 1982 if(!*place) { /* update scanning pointer */ 1983 if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) { 1984 atend++; 1985 return(EOF); 1986 } 1987 if (*place == '-') { /* found "--" */ 1988 ++optind; 1989 atend++; 1990 return(EOF); 1991 } 1992 } /* option letter okay? */ 1993 if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) { 1994 if (!*place) ++optind; 1995 tell(": illegal option -- "); 1996 } 1997 if (*++oli != ':') { /* don't need argument */ 1998 optarg = NULL; 1999 if (!*place) ++optind; 2000 } 2001 else { /* need an argument */ 2002 if (*place) optarg = place; /* no white space */ 2003 else if (nargc <= ++optind) { /* no arg */ 2004 place = EMSG; 2005 tell(": option requires an argument -- "); 2006 } 2007 else optarg = nargv[optind]; /* white space */ 2008 place = EMSG; 2009 ++optind; 2010 } 2011 return(optopt); /* dump back option letter */ 2012 } 2013 2014 #endif 2015 /* 2016 ** VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version 2017 */ 2018 2019 #ifdef NEEDVPRINTF 2020 2021 #define MAXARG 16 2022 2023 vfprintf(fp, fmt, ap) 2024 FILE * fp; 2025 char * fmt; 2026 char ** ap; 2027 { 2028 char * bp[MAXARG]; 2029 int i = 0; 2030 2031 while (*ap && i < MAXARG) 2032 bp[i++] = *ap++; 2033 fprintf(fp, fmt, bp[0], bp[1], bp[2], bp[3], 2034 bp[4], bp[5], bp[6], bp[7], 2035 bp[8], bp[9], bp[10], bp[11], 2036 bp[12], bp[13], bp[14], bp[15]); 2037 } 2038 2039 vsprintf(s, fmt, ap) 2040 char * s; 2041 char * fmt; 2042 char ** ap; 2043 { 2044 char * bp[MAXARG]; 2045 int i = 0; 2046 2047 while (*ap && i < MAXARG) 2048 bp[i++] = *ap++; 2049 sprintf(s, fmt, bp[0], bp[1], bp[2], bp[3], 2050 bp[4], bp[5], bp[6], bp[7], 2051 bp[8], bp[9], bp[10], bp[11], 2052 bp[12], bp[13], bp[14], bp[15]); 2053 } 2054 2055 #endif 2056 /* 2057 ** USERSHELLOK -- tell if a user's shell is ok for unrestricted use 2058 ** 2059 ** Parameters: 2060 ** shell -- the user's shell from /etc/passwd 2061 ** 2062 ** Returns: 2063 ** TRUE -- if it is ok to use this for unrestricted access. 2064 ** FALSE -- if the shell is restricted. 2065 */ 2066 2067 #if !HASGETUSERSHELL 2068 2069 # ifndef _PATH_SHELLS 2070 # define _PATH_SHELLS "/etc/shells" 2071 # endif 2072 2073 char *DefaultUserShells[] = 2074 { 2075 "/bin/sh", /* standard shell */ 2076 "/usr/bin/sh", 2077 "/bin/csh", /* C shell */ 2078 "/usr/bin/csh", 2079 #ifdef __hpux 2080 # ifdef V4FS 2081 "/usr/bin/rsh", /* restricted Bourne shell */ 2082 "/usr/bin/ksh", /* Korn shell */ 2083 "/usr/bin/rksh", /* restricted Korn shell */ 2084 "/usr/bin/pam", 2085 "/usr/bin/keysh", /* key shell (extended Korn shell) */ 2086 "/usr/bin/posix/sh", 2087 # else 2088 "/bin/rsh", /* restricted Bourne shell */ 2089 "/bin/ksh", /* Korn shell */ 2090 "/bin/rksh", /* restricted Korn shell */ 2091 "/bin/pam", 2092 "/usr/bin/keysh", /* key shell (extended Korn shell) */ 2093 "/bin/posix/sh", 2094 # endif 2095 #endif 2096 #ifdef _AIX3 2097 "/bin/ksh", /* Korn shell */ 2098 "/usr/bin/ksh", 2099 "/bin/tsh", /* trusted shell */ 2100 "/usr/bin/tsh", 2101 "/bin/bsh", /* Bourne shell */ 2102 "/usr/bin/bsh", 2103 #endif 2104 NULL 2105 }; 2106 2107 #endif 2108 2109 #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/" 2110 2111 bool 2112 usershellok(shell) 2113 char *shell; 2114 { 2115 #if HASGETUSERSHELL 2116 register char *p; 2117 extern char *getusershell(); 2118 2119 if (shell == NULL || shell[0] == '\0' || ConfigLevel <= 1) 2120 return TRUE; 2121 2122 setusershell(); 2123 while ((p = getusershell()) != NULL) 2124 if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0) 2125 break; 2126 endusershell(); 2127 return p != NULL; 2128 #else 2129 register FILE *shellf; 2130 char buf[MAXLINE]; 2131 2132 if (shell == NULL || shell[0] == '\0') 2133 return TRUE; 2134 2135 shellf = fopen(_PATH_SHELLS, "r"); 2136 if (shellf == NULL) 2137 { 2138 /* no /etc/shells; see if it is one of the std shells */ 2139 char **d; 2140 2141 for (d = DefaultUserShells; *d != NULL; d++) 2142 { 2143 if (strcmp(shell, *d) == 0) 2144 return TRUE; 2145 } 2146 return FALSE; 2147 } 2148 2149 while (fgets(buf, sizeof buf, shellf) != NULL) 2150 { 2151 register char *p, *q; 2152 2153 p = buf; 2154 while (*p != '\0' && *p != '#' && *p != '/') 2155 p++; 2156 if (*p == '#' || *p == '\0') 2157 continue; 2158 q = p; 2159 while (*p != '\0' && *p != '#' && !isspace(*p)) 2160 p++; 2161 *p = '\0'; 2162 if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0) 2163 { 2164 fclose(shellf); 2165 return TRUE; 2166 } 2167 } 2168 fclose(shellf); 2169 return FALSE; 2170 #endif 2171 } 2172 /* 2173 ** FREESPACE -- see how much free space is on the queue filesystem 2174 ** 2175 ** Only implemented if you have statfs. 2176 ** 2177 ** Parameters: 2178 ** dir -- the directory in question. 2179 ** bsize -- a variable into which the filesystem 2180 ** block size is stored. 2181 ** 2182 ** Returns: 2183 ** The number of bytes free on the queue filesystem. 2184 ** -1 if the statfs call fails. 2185 ** 2186 ** Side effects: 2187 ** Puts the filesystem block size into bsize. 2188 */ 2189 2190 /* statfs types */ 2191 #define SFS_NONE 0 /* no statfs implementation */ 2192 #define SFS_USTAT 1 /* use ustat */ 2193 #define SFS_4ARGS 2 /* use four-argument statfs call */ 2194 #define SFS_VFS 3 /* use <sys/vfs.h> implementation */ 2195 #define SFS_MOUNT 4 /* use <sys/mount.h> implementation */ 2196 #define SFS_STATFS 5 /* use <sys/statfs.h> implementation */ 2197 #define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */ 2198 2199 #ifndef SFS_TYPE 2200 # define SFS_TYPE SFS_NONE 2201 #endif 2202 2203 #if SFS_TYPE == SFS_USTAT 2204 # include <ustat.h> 2205 #endif 2206 #if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS 2207 # include <sys/statfs.h> 2208 #endif 2209 #if SFS_TYPE == SFS_VFS 2210 # include <sys/vfs.h> 2211 #endif 2212 #if SFS_TYPE == SFS_MOUNT 2213 # include <sys/mount.h> 2214 #endif 2215 #if SFS_TYPE == SFS_STATVFS 2216 # include <sys/statvfs.h> 2217 #endif 2218 2219 long 2220 freespace(dir, bsize) 2221 char *dir; 2222 long *bsize; 2223 { 2224 #if SFS_TYPE != SFS_NONE 2225 # if SFS_TYPE == SFS_USTAT 2226 struct ustat fs; 2227 struct stat statbuf; 2228 # define FSBLOCKSIZE DEV_BSIZE 2229 # define SFS_BAVAIL f_tfree 2230 # else 2231 # if defined(ultrix) 2232 struct fs_data fs; 2233 # define SFS_BAVAIL fd_bfreen 2234 # define FSBLOCKSIZE 1024L 2235 # else 2236 # if SFS_TYPE == SFS_STATVFS 2237 struct statvfs fs; 2238 # define FSBLOCKSIZE fs.f_frsize 2239 # else 2240 struct statfs fs; 2241 # define FSBLOCKSIZE fs.f_bsize 2242 # endif 2243 # endif 2244 # endif 2245 # ifndef SFS_BAVAIL 2246 # define SFS_BAVAIL f_bavail 2247 # endif 2248 2249 # if SFS_TYPE == SFS_USTAT 2250 if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) 2251 # else 2252 # if SFS_TYPE == SFS_4ARGS 2253 if (statfs(dir, &fs, sizeof fs, 0) == 0) 2254 # else 2255 # if SFS_TYPE == SFS_STATVFS 2256 if (statvfs(dir, &fs) == 0) 2257 # else 2258 # if defined(ultrix) 2259 if (statfs(dir, &fs) > 0) 2260 # else 2261 if (statfs(dir, &fs) == 0) 2262 # endif 2263 # endif 2264 # endif 2265 # endif 2266 { 2267 if (bsize != NULL) 2268 *bsize = FSBLOCKSIZE; 2269 return (fs.SFS_BAVAIL); 2270 } 2271 #endif 2272 return (-1); 2273 } 2274 /* 2275 ** ENOUGHSPACE -- check to see if there is enough free space on the queue fs 2276 ** 2277 ** Only implemented if you have statfs. 2278 ** 2279 ** Parameters: 2280 ** msize -- the size to check against. If zero, we don't yet 2281 ** know how big the message will be, so just check for 2282 ** a "reasonable" amount. 2283 ** 2284 ** Returns: 2285 ** TRUE if there is enough space. 2286 ** FALSE otherwise. 2287 */ 2288 2289 bool 2290 enoughspace(msize) 2291 long msize; 2292 { 2293 long bfree, bsize; 2294 2295 if (MinBlocksFree <= 0 && msize <= 0) 2296 { 2297 if (tTd(4, 80)) 2298 printf("enoughspace: no threshold\n"); 2299 return TRUE; 2300 } 2301 2302 if ((bfree = freespace(QueueDir, &bsize)) >= 0) 2303 { 2304 if (tTd(4, 80)) 2305 printf("enoughspace: bavail=%ld, need=%ld\n", 2306 bfree, msize); 2307 2308 /* convert msize to block count */ 2309 msize = msize / bsize + 1; 2310 if (MinBlocksFree >= 0) 2311 msize += MinBlocksFree; 2312 2313 if (bfree < msize) 2314 { 2315 #ifdef LOG 2316 if (LogLevel > 0) 2317 syslog(LOG_ALERT, 2318 "%s: low on space (have %ld, %s needs %ld in %s)", 2319 CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id, 2320 bfree, 2321 CurHostName == NULL ? "SMTP-DAEMON" : CurHostName, 2322 msize, QueueDir); 2323 #endif 2324 return FALSE; 2325 } 2326 } 2327 else if (tTd(4, 80)) 2328 printf("enoughspace failure: min=%ld, need=%ld: %s\n", 2329 MinBlocksFree, msize, errstring(errno)); 2330 return TRUE; 2331 } 2332 /* 2333 ** TRANSIENTERROR -- tell if an error code indicates a transient failure 2334 ** 2335 ** This looks at an errno value and tells if this is likely to 2336 ** go away if retried later. 2337 ** 2338 ** Parameters: 2339 ** err -- the errno code to classify. 2340 ** 2341 ** Returns: 2342 ** TRUE if this is probably transient. 2343 ** FALSE otherwise. 2344 */ 2345 2346 bool 2347 transienterror(err) 2348 int err; 2349 { 2350 switch (err) 2351 { 2352 case EIO: /* I/O error */ 2353 case ENXIO: /* Device not configured */ 2354 case EAGAIN: /* Resource temporarily unavailable */ 2355 case ENOMEM: /* Cannot allocate memory */ 2356 case ENODEV: /* Operation not supported by device */ 2357 case ENFILE: /* Too many open files in system */ 2358 case EMFILE: /* Too many open files */ 2359 case ENOSPC: /* No space left on device */ 2360 #ifdef ETIMEDOUT 2361 case ETIMEDOUT: /* Connection timed out */ 2362 #endif 2363 #ifdef ESTALE 2364 case ESTALE: /* Stale NFS file handle */ 2365 #endif 2366 #ifdef ENETDOWN 2367 case ENETDOWN: /* Network is down */ 2368 #endif 2369 #ifdef ENETUNREACH 2370 case ENETUNREACH: /* Network is unreachable */ 2371 #endif 2372 #ifdef ENETRESET 2373 case ENETRESET: /* Network dropped connection on reset */ 2374 #endif 2375 #ifdef ECONNABORTED 2376 case ECONNABORTED: /* Software caused connection abort */ 2377 #endif 2378 #ifdef ECONNRESET 2379 case ECONNRESET: /* Connection reset by peer */ 2380 #endif 2381 #ifdef ENOBUFS 2382 case ENOBUFS: /* No buffer space available */ 2383 #endif 2384 #ifdef ESHUTDOWN 2385 case ESHUTDOWN: /* Can't send after socket shutdown */ 2386 #endif 2387 #ifdef ECONNREFUSED 2388 case ECONNREFUSED: /* Connection refused */ 2389 #endif 2390 #ifdef EHOSTDOWN 2391 case EHOSTDOWN: /* Host is down */ 2392 #endif 2393 #ifdef EHOSTUNREACH 2394 case EHOSTUNREACH: /* No route to host */ 2395 #endif 2396 #ifdef EDQUOT 2397 case EDQUOT: /* Disc quota exceeded */ 2398 #endif 2399 #ifdef EPROCLIM 2400 case EPROCLIM: /* Too many processes */ 2401 #endif 2402 #ifdef EUSERS 2403 case EUSERS: /* Too many users */ 2404 #endif 2405 #ifdef EDEADLK 2406 case EDEADLK: /* Resource deadlock avoided */ 2407 #endif 2408 #ifdef EISCONN 2409 case EISCONN: /* Socket already connected */ 2410 #endif 2411 #ifdef EINPROGRESS 2412 case EINPROGRESS: /* Operation now in progress */ 2413 #endif 2414 #ifdef EALREADY 2415 case EALREADY: /* Operation already in progress */ 2416 #endif 2417 #ifdef EADDRINUSE 2418 case EADDRINUSE: /* Address already in use */ 2419 #endif 2420 #ifdef EADDRNOTAVAIL 2421 case EADDRNOTAVAIL: /* Can't assign requested address */ 2422 #endif 2423 #ifdef ETXTBSY 2424 case ETXTBSY: /* (Apollo) file locked */ 2425 #endif 2426 #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) 2427 case ENOSR: /* Out of streams resources */ 2428 #endif 2429 return TRUE; 2430 } 2431 2432 /* nope, must be permanent */ 2433 return FALSE; 2434 } 2435 /* 2436 ** LOCKFILE -- lock a file using flock or (shudder) fcntl locking 2437 ** 2438 ** Parameters: 2439 ** fd -- the file descriptor of the file. 2440 ** filename -- the file name (for error messages). 2441 ** ext -- the filename extension. 2442 ** type -- type of the lock. Bits can be: 2443 ** LOCK_EX -- exclusive lock. 2444 ** LOCK_NB -- non-blocking. 2445 ** 2446 ** Returns: 2447 ** TRUE if the lock was acquired. 2448 ** FALSE otherwise. 2449 */ 2450 2451 bool 2452 lockfile(fd, filename, ext, type) 2453 int fd; 2454 char *filename; 2455 char *ext; 2456 int type; 2457 { 2458 # if !HASFLOCK 2459 int action; 2460 struct flock lfd; 2461 2462 if (ext == NULL) 2463 ext = ""; 2464 2465 bzero(&lfd, sizeof lfd); 2466 if (bitset(LOCK_UN, type)) 2467 lfd.l_type = F_UNLCK; 2468 else if (bitset(LOCK_EX, type)) 2469 lfd.l_type = F_WRLCK; 2470 else 2471 lfd.l_type = F_RDLCK; 2472 2473 if (bitset(LOCK_NB, type)) 2474 action = F_SETLK; 2475 else 2476 action = F_SETLKW; 2477 2478 if (tTd(55, 60)) 2479 printf("lockfile(%s%s, action=%d, type=%d): ", 2480 filename, ext, action, lfd.l_type); 2481 2482 if (fcntl(fd, action, &lfd) >= 0) 2483 { 2484 if (tTd(55, 60)) 2485 printf("SUCCESS\n"); 2486 return TRUE; 2487 } 2488 2489 if (tTd(55, 60)) 2490 printf("(%s) ", errstring(errno)); 2491 2492 /* 2493 ** On SunOS, if you are testing using -oQ/tmp/mqueue or 2494 ** -oA/tmp/aliases or anything like that, and /tmp is mounted 2495 ** as type "tmp" (that is, served from swap space), the 2496 ** previous fcntl will fail with "Invalid argument" errors. 2497 ** Since this is fairly common during testing, we will assume 2498 ** that this indicates that the lock is successfully grabbed. 2499 */ 2500 2501 if (errno == EINVAL) 2502 { 2503 if (tTd(55, 60)) 2504 printf("SUCCESS\n"); 2505 return TRUE; 2506 } 2507 2508 if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN)) 2509 { 2510 int omode = -1; 2511 # ifdef F_GETFL 2512 int oerrno = errno; 2513 2514 (void) fcntl(fd, F_GETFL, &omode); 2515 errno = oerrno; 2516 # endif 2517 syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", 2518 filename, ext, fd, type, omode, geteuid()); 2519 } 2520 # else 2521 if (ext == NULL) 2522 ext = ""; 2523 2524 if (tTd(55, 60)) 2525 printf("lockfile(%s%s, type=%o): ", filename, ext, type); 2526 2527 if (flock(fd, type) >= 0) 2528 { 2529 if (tTd(55, 60)) 2530 printf("SUCCESS\n"); 2531 return TRUE; 2532 } 2533 2534 if (tTd(55, 60)) 2535 printf("(%s) ", errstring(errno)); 2536 2537 if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK) 2538 { 2539 int omode = -1; 2540 # ifdef F_GETFL 2541 int oerrno = errno; 2542 2543 (void) fcntl(fd, F_GETFL, &omode); 2544 errno = oerrno; 2545 # endif 2546 syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", 2547 filename, ext, fd, type, omode, geteuid()); 2548 } 2549 # endif 2550 if (tTd(55, 60)) 2551 printf("FAIL\n"); 2552 return FALSE; 2553 } 2554 /* 2555 ** CHOWNSAFE -- tell if chown is "safe" (executable only by root) 2556 ** 2557 ** Parameters: 2558 ** fd -- the file descriptor to check. 2559 ** 2560 ** Returns: 2561 ** TRUE -- if only root can chown the file to an arbitrary 2562 ** user. 2563 ** FALSE -- if an arbitrary user can give away a file. 2564 */ 2565 2566 bool 2567 chownsafe(fd) 2568 int fd; 2569 { 2570 #ifdef __hpux 2571 char *s; 2572 int tfd; 2573 uid_t o_uid, o_euid; 2574 gid_t o_gid, o_egid; 2575 bool rval; 2576 struct stat stbuf; 2577 2578 o_uid = getuid(); 2579 o_euid = geteuid(); 2580 o_gid = getgid(); 2581 o_egid = getegid(); 2582 fstat(fd, &stbuf); 2583 setresuid(stbuf.st_uid, stbuf.st_uid, -1); 2584 setresgid(stbuf.st_gid, stbuf.st_gid, -1); 2585 s = tmpnam(NULL); 2586 tfd = open(s, O_RDONLY|O_CREAT, 0600); 2587 rval = fchown(tfd, DefUid, DefGid) != 0; 2588 close(tfd); 2589 unlink(s); 2590 setreuid(o_uid, o_euid); 2591 setresgid(o_gid, o_egid, -1); 2592 return rval; 2593 #else 2594 # ifdef _POSIX_CHOWN_RESTRICTED 2595 # if _POSIX_CHOWN_RESTRICTED == -1 2596 return FALSE; 2597 # else 2598 return TRUE; 2599 # endif 2600 # else 2601 # ifdef _PC_CHOWN_RESTRICTED 2602 int rval; 2603 2604 /* 2605 ** Some systems (e.g., SunOS) seem to have the call and the 2606 ** #define _PC_CHOWN_RESTRICTED, but don't actually implement 2607 ** the call. This heuristic checks for that. 2608 */ 2609 2610 errno = 0; 2611 rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); 2612 if (errno == 0) 2613 return rval > 0; 2614 # endif 2615 # ifdef BSD 2616 return TRUE; 2617 # else 2618 return FALSE; 2619 # endif 2620 # endif 2621 #endif 2622 } 2623 /* 2624 ** RESETLIMITS -- reset system controlled resource limits 2625 ** 2626 ** This is to avoid denial-of-service attacks 2627 ** 2628 ** Parameters: 2629 ** none 2630 ** 2631 ** Returns: 2632 ** none 2633 */ 2634 2635 #if HASSETRLIMIT 2636 # include <sys/resource.h> 2637 #endif 2638 2639 void 2640 resetlimits() 2641 { 2642 #if HASSETRLIMIT 2643 struct rlimit lim; 2644 2645 lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; 2646 (void) setrlimit(RLIMIT_CPU, &lim); 2647 (void) setrlimit(RLIMIT_FSIZE, &lim); 2648 #else 2649 # if HASULIMIT 2650 (void) ulimit(2, 0x3fffff); 2651 # endif 2652 #endif 2653 } 2654 /* 2655 ** GETCFNAME -- return the name of the .cf file. 2656 ** 2657 ** Some systems (e.g., NeXT) determine this dynamically. 2658 */ 2659 2660 char * 2661 getcfname() 2662 { 2663 int i; 2664 static char cbuf[200]; 2665 2666 if (ConfFile != NULL) 2667 return ConfFile; 2668 #ifdef NETINFO 2669 { 2670 extern char *ni_propval(); 2671 char *cflocation; 2672 2673 cflocation = ni_propval("/locations", NULL, "sendmail", 2674 "sendmail.cf", '\0'); 2675 if (cflocation != NULL) 2676 return cflocation; 2677 } 2678 #endif 2679 2680 #ifdef TRY_VERSIONED_CF_NAME 2681 /* 2682 ** Try sendmail.8.6.12.cf, then sendmail.8.6.cf, then 2683 ** sendmail.8.cf, and finally sendmail.cf. 2684 ** 2685 ** I suppose it should really try a search path here -- 2686 ** e.g., /etc/sendmail.cf, /etc/mail/sendmail.cf, 2687 ** /usr/lib/sendmail.cf, and so forth. 2688 */ 2689 2690 strcpy(cbuf, _PATH_SENDMAILCF); 2691 i = strlen(cbuf); 2692 if (strcmp(&cbuf[i - 3], ".cf") == 0) 2693 { 2694 char *p; 2695 extern char Version[]; 2696 2697 strcpy(&cbuf[i - 2], Version); 2698 p = strchr(&cbuf[i - 2], '/'); 2699 if (p != NULL) 2700 *p = '\0'; 2701 p = &cbuf[strlen(cbuf)]; 2702 do 2703 { 2704 int fd; 2705 2706 strcpy(p, ".cf"); 2707 if ((fd = open(cbuf, O_RDONLY, 0)) >= 0) 2708 { 2709 close(fd); 2710 return cbuf; 2711 } 2712 *p = '\0'; 2713 } while ((p = strrchr(&cbuf[i - 2], '.')) != NULL); 2714 } 2715 #endif 2716 return _PATH_SENDMAILCF; 2717 } 2718 /* 2719 ** SETVENDOR -- process vendor code from V configuration line 2720 ** 2721 ** Parameters: 2722 ** vendor -- string representation of vendor. 2723 ** 2724 ** Returns: 2725 ** TRUE -- if ok. 2726 ** FALSE -- if vendor code could not be processed. 2727 ** 2728 ** Side Effects: 2729 ** It is reasonable to set mode flags here to tweak 2730 ** processing in other parts of the code if necessary. 2731 ** For example, if you are a vendor that uses $%y to 2732 ** indicate YP lookups, you could enable that here. 2733 */ 2734 2735 bool 2736 setvendor(vendor) 2737 char *vendor; 2738 { 2739 if (strcasecmp(vendor, "Berkeley") == 0) 2740 { 2741 VendorCode = VENDOR_BERKELEY; 2742 return TRUE; 2743 } 2744 2745 /* add vendor extensions here */ 2746 2747 #ifdef SUN_EXTENSIONS 2748 if (strcasecmp(vendor, "Sun") == 0) 2749 { 2750 VendorCode = VENDOR_SUN; 2751 return TRUE; 2752 } 2753 #endif 2754 2755 return FALSE; 2756 } 2757 /* 2758 ** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults 2759 ** 2760 ** Vendor_pre_defaults is called before reading the configuration 2761 ** file; vendor_post_defaults is called immediately after. 2762 ** 2763 ** Parameters: 2764 ** e -- the global environment to initialize. 2765 ** 2766 ** Returns: 2767 ** none. 2768 */ 2769 2770 void 2771 vendor_pre_defaults(e) 2772 ENVELOPE *e; 2773 { 2774 } 2775 2776 2777 void 2778 vendor_post_defaults(e) 2779 ENVELOPE *e; 2780 { 2781 } 2782 /* 2783 ** STRTOL -- convert string to long integer 2784 ** 2785 ** For systems that don't have it in the C library. 2786 ** 2787 ** This is taken verbatim from the 4.4-Lite C library. 2788 */ 2789 2790 #ifdef NEEDSTRTOL 2791 2792 #if defined(LIBC_SCCS) && !defined(lint) 2793 static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; 2794 #endif /* LIBC_SCCS and not lint */ 2795 2796 #include <limits.h> 2797 2798 /* 2799 * Convert a string to a long integer. 2800 * 2801 * Ignores `locale' stuff. Assumes that the upper and lower case 2802 * alphabets and digits are each contiguous. 2803 */ 2804 2805 long 2806 strtol(nptr, endptr, base) 2807 const char *nptr; 2808 char **endptr; 2809 register int base; 2810 { 2811 register const char *s = nptr; 2812 register unsigned long acc; 2813 register int c; 2814 register unsigned long cutoff; 2815 register int neg = 0, any, cutlim; 2816 2817 /* 2818 * Skip white space and pick up leading +/- sign if any. 2819 * If base is 0, allow 0x for hex and 0 for octal, else 2820 * assume decimal; if base is already 16, allow 0x. 2821 */ 2822 do { 2823 c = *s++; 2824 } while (isspace(c)); 2825 if (c == '-') { 2826 neg = 1; 2827 c = *s++; 2828 } else if (c == '+') 2829 c = *s++; 2830 if ((base == 0 || base == 16) && 2831 c == '0' && (*s == 'x' || *s == 'X')) { 2832 c = s[1]; 2833 s += 2; 2834 base = 16; 2835 } 2836 if (base == 0) 2837 base = c == '0' ? 8 : 10; 2838 2839 /* 2840 * Compute the cutoff value between legal numbers and illegal 2841 * numbers. That is the largest legal value, divided by the 2842 * base. An input number that is greater than this value, if 2843 * followed by a legal input character, is too big. One that 2844 * is equal to this value may be valid or not; the limit 2845 * between valid and invalid numbers is then based on the last 2846 * digit. For instance, if the range for longs is 2847 * [-2147483648..2147483647] and the input base is 10, 2848 * cutoff will be set to 214748364 and cutlim to either 2849 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 2850 * a value > 214748364, or equal but the next digit is > 7 (or 8), 2851 * the number is too big, and we will return a range error. 2852 * 2853 * Set any if any `digits' consumed; make it negative to indicate 2854 * overflow. 2855 */ 2856 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 2857 cutlim = cutoff % (unsigned long)base; 2858 cutoff /= (unsigned long)base; 2859 for (acc = 0, any = 0;; c = *s++) { 2860 if (isdigit(c)) 2861 c -= '0'; 2862 else if (isalpha(c)) 2863 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 2864 else 2865 break; 2866 if (c >= base) 2867 break; 2868 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 2869 any = -1; 2870 else { 2871 any = 1; 2872 acc *= base; 2873 acc += c; 2874 } 2875 } 2876 if (any < 0) { 2877 acc = neg ? LONG_MIN : LONG_MAX; 2878 errno = ERANGE; 2879 } else if (neg) 2880 acc = -acc; 2881 if (endptr != 0) 2882 *endptr = (char *)(any ? s - 1 : nptr); 2883 return (acc); 2884 } 2885 2886 #endif 2887 /* 2888 ** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX 2889 ** 2890 ** Some operating systems have wierd problems with the gethostbyXXX 2891 ** routines. For example, Solaris versions at least through 2.3 2892 ** don't properly deliver a canonical h_name field. This tries to 2893 ** work around these problems. 2894 */ 2895 2896 struct hostent * 2897 sm_gethostbyname(name) 2898 char *name; 2899 { 2900 #if defined(SOLARIS) && SOLARIS < 204 2901 extern int h_errno; 2902 2903 # if SOLARIS == 203 2904 static struct hostent hp; 2905 static char buf[1000]; 2906 extern struct hostent *_switch_gethostbyname_r(); 2907 2908 return _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); 2909 # else 2910 extern struct hostent *__switch_gethostbyname(); 2911 2912 return __switch_gethostbyname(name); 2913 # endif 2914 #else 2915 return gethostbyname(name); 2916 #endif 2917 } 2918 2919 struct hostent * 2920 sm_gethostbyaddr(addr, len, type) 2921 char *addr; 2922 int len; 2923 int type; 2924 { 2925 #if defined(SOLARIS) && SOLARIS < 204 2926 extern int h_errno; 2927 2928 # if SOLARIS == 203 2929 static struct hostent hp; 2930 static char buf[1000]; 2931 extern struct hostent *_switch_gethostbyaddr_r(); 2932 2933 return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno); 2934 # else 2935 extern struct hostent *__switch_gethostbyaddr(); 2936 2937 return __switch_gethostbyaddr(addr, len, type); 2938 # endif 2939 #else 2940 return gethostbyaddr(addr, len, type); 2941 #endif 2942 } 2943 /* 2944 ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid 2945 */ 2946 2947 struct passwd * 2948 sm_getpwnam(user) 2949 char *user; 2950 { 2951 return getpwnam(user); 2952 } 2953 2954 struct passwd * 2955 sm_getpwuid(uid) 2956 uid_t uid; 2957 { 2958 return getpwuid(uid); 2959 } 2960 /* 2961 ** LOAD_IF_NAMES -- load interface-specific names into $=w 2962 ** 2963 ** Parameters: 2964 ** none. 2965 ** 2966 ** Returns: 2967 ** none. 2968 ** 2969 ** Side Effects: 2970 ** Loads $=w with the names of all the interfaces. 2971 */ 2972 2973 #ifdef SIOCGIFCONF 2974 # include <netdb.h> 2975 # include <arpa/inet.h> 2976 # include <net/if.h> 2977 #endif 2978 2979 void 2980 load_if_names() 2981 { 2982 #ifdef SIOCGIFCONF 2983 int s; 2984 int i; 2985 struct ifconf ifc; 2986 char interfacebuf[1024]; 2987 2988 s = socket(AF_INET, SOCK_DGRAM, 0); 2989 if (s == -1) 2990 return; 2991 2992 /* get the list of known IP address from the kernel */ 2993 ifc.ifc_buf = interfacebuf; 2994 ifc.ifc_len = sizeof interfacebuf; 2995 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 2996 { 2997 if (tTd(0, 4)) 2998 printf("SIOGIFCONF failed: %s\n", errstring(errno)); 2999 close(s); 3000 return; 3001 } 3002 close(s); 3003 3004 /* scan the list of IP address */ 3005 if (tTd(0, 4)) 3006 printf("scanning for interface specific names, ifc_len=%d\n", 3007 ifc.ifc_len); 3008 3009 for (i = 0; i < ifc.ifc_len; ) 3010 { 3011 struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; 3012 struct sockaddr *sa = &ifr->ifr_addr; 3013 struct in_addr ia; 3014 struct hostent *hp; 3015 char ip_addr[256]; 3016 extern char *inet_ntoa(); 3017 extern struct hostent *gethostbyaddr(); 3018 3019 #ifdef BSD4_4_SOCKADDR 3020 if (sa->sa_len > sizeof ifr->ifr_addr) 3021 i += sizeof ifr->ifr_name + sa->sa_len; 3022 else 3023 #endif 3024 i += sizeof *ifr; 3025 3026 if (tTd(0, 20)) 3027 printf("%s\n", anynet_ntoa((SOCKADDR *) sa)); 3028 3029 if (ifr->ifr_addr.sa_family != AF_INET) 3030 continue; 3031 3032 /* extract IP address from the list*/ 3033 ia = (((struct sockaddr_in *) sa)->sin_addr); 3034 3035 /* save IP address in text from */ 3036 (void) sprintf(ip_addr, "[%s]", 3037 inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 3038 if (!wordinclass(ip_addr, 'w')) 3039 { 3040 setclass('w', ip_addr); 3041 if (tTd(0, 4)) 3042 printf("\ta.k.a.: %s\n", ip_addr); 3043 } 3044 3045 /* skip "loopback" interface "lo" */ 3046 if (strcmp("lo0", ifr->ifr_name) == 0) 3047 continue; 3048 3049 /* lookup name with IP address */ 3050 hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET); 3051 if (hp == NULL) 3052 { 3053 syslog(LOG_CRIT, "gethostbyaddr() failed for %s\n", 3054 inet_ntoa(ia)); 3055 continue; 3056 } 3057 3058 /* save its cname */ 3059 if (!wordinclass(hp->h_name, 'w')) 3060 { 3061 setclass('w', hp->h_name); 3062 if (tTd(0, 4)) 3063 printf("\ta.k.a.: %s\n", hp->h_name); 3064 } 3065 3066 /* save all it aliases name */ 3067 while (*hp->h_aliases) 3068 { 3069 if (!wordinclass(*hp->h_aliases, 'w')) 3070 { 3071 setclass('w', *hp->h_aliases); 3072 if (tTd(0, 4)) 3073 printf("\ta.k.a.: %s\n", *hp->h_aliases); 3074 } 3075 hp->h_aliases++; 3076 } 3077 } 3078 #endif 3079 } 3080 /* 3081 ** NI_PROPVAL -- netinfo property value lookup routine 3082 ** 3083 ** Parameters: 3084 ** keydir -- the Netinfo directory name in which to search 3085 ** for the key. 3086 ** keyprop -- the name of the property in which to find the 3087 ** property we are interested. Defaults to "name". 3088 ** keyval -- the value for which we are really searching. 3089 ** valprop -- the property name for the value in which we 3090 ** are interested. 3091 ** sepchar -- if non-nil, this can be multiple-valued, and 3092 ** we should return a string separated by this 3093 ** character. 3094 ** 3095 ** Returns: 3096 ** NULL -- if: 3097 ** 1. the directory is not found 3098 ** 2. the property name is not found 3099 ** 3. the property contains multiple values 3100 ** 4. some error occured 3101 ** else -- the location of the config file. 3102 ** 3103 ** Example: 3104 ** To search for an alias value, use: 3105 ** ni_propval("/aliases", "name", aliasname, "members", ',') 3106 ** 3107 ** Notes: 3108 ** Caller should free the return value of ni_proval 3109 */ 3110 3111 #ifdef NETINFO 3112 3113 # include <netinfo/ni.h> 3114 3115 # define LOCAL_NETINFO_DOMAIN "." 3116 # define PARENT_NETINFO_DOMAIN ".." 3117 # define MAX_NI_LEVELS 256 3118 3119 char * 3120 ni_propval(keydir, keyprop, keyval, valprop, sepchar) 3121 char *keydir; 3122 char *keyprop; 3123 char *keyval; 3124 char *valprop; 3125 char sepchar; 3126 { 3127 char *propval = NULL; 3128 int i; 3129 int j, alen; 3130 void *ni = NULL; 3131 void *lastni = NULL; 3132 ni_status nis; 3133 ni_id nid; 3134 ni_namelist ninl; 3135 register char *p; 3136 char keybuf[1024]; 3137 3138 /* 3139 ** Create the full key from the two parts. 3140 ** 3141 ** Note that directory can end with, e.g., "name=" to specify 3142 ** an alternate search property. 3143 */ 3144 3145 i = strlen(keydir) + strlen(keyval) + 2; 3146 if (keyprop != NULL) 3147 i += strlen(keyprop) + 1; 3148 if (i > sizeof keybuf) 3149 return NULL; 3150 strcpy(keybuf, keydir); 3151 strcat(keybuf, "/"); 3152 if (keyprop != NULL) 3153 { 3154 strcat(keybuf, keyprop); 3155 strcat(keybuf, "="); 3156 } 3157 strcat(keybuf, keyval); 3158 3159 /* 3160 ** If the passed directory and property name are found 3161 ** in one of netinfo domains we need to search (starting 3162 ** from the local domain moving all the way back to the 3163 ** root domain) set propval to the property's value 3164 ** and return it. 3165 */ 3166 3167 for (i = 0; i < MAX_NI_LEVELS; ++i) 3168 { 3169 if (i == 0) 3170 { 3171 nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 3172 } 3173 else 3174 { 3175 if (lastni != NULL) 3176 ni_free(lastni); 3177 lastni = ni; 3178 nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 3179 } 3180 3181 /* 3182 ** Don't bother if we didn't get a handle on a 3183 ** proper domain. This is not necessarily an error. 3184 ** We would get a positive ni_status if, for instance 3185 ** we never found the directory or property and tried 3186 ** to open the parent of the root domain! 3187 */ 3188 3189 if (nis != 0) 3190 break; 3191 3192 /* 3193 ** Find the path to the server information. 3194 */ 3195 3196 if (ni_pathsearch(ni, &nid, keybuf) != 0) 3197 continue; 3198 3199 /* 3200 ** Find associated value information. 3201 */ 3202 3203 if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 3204 continue; 3205 3206 /* 3207 ** See if we have an acceptable number of values. 3208 */ 3209 3210 if (ninl.ni_namelist_len <= 0) 3211 continue; 3212 3213 if (sepchar == '\0' && ninl.ni_namelist_len > 1) 3214 { 3215 ni_namelist_free(&ninl); 3216 continue; 3217 } 3218 3219 /* 3220 ** Calculate number of bytes needed and build result 3221 */ 3222 3223 alen = 1; 3224 for (j = 0; j < ninl.ni_namelist_len; j++) 3225 alen += strlen(ninl.ni_namelist_val[j]) + 1; 3226 propval = p = xalloc(alen); 3227 for (j = 0; j < ninl.ni_namelist_len; j++) 3228 { 3229 strcpy(p, ninl.ni_namelist_val[j]); 3230 p += strlen(p); 3231 *p++ = sepchar; 3232 } 3233 *--p = '\0'; 3234 3235 ni_namelist_free(&ninl); 3236 } 3237 3238 /* 3239 ** Clean up. 3240 */ 3241 3242 if (ni != NULL) 3243 ni_free(ni); 3244 if (lastni != NULL && ni != lastni) 3245 ni_free(lastni); 3246 3247 return propval; 3248 } 3249 3250 #endif /* NETINFO */ 3251 /* 3252 ** HARD_SYSLOG -- call syslog repeatedly until it works 3253 ** 3254 ** Needed on HP-UX, which apparently doesn't guarantee that 3255 ** syslog succeeds during interrupt handlers. 3256 */ 3257 3258 #ifdef __hpux 3259 3260 # define MAXSYSLOGTRIES 100 3261 # undef syslog 3262 3263 # ifdef __STDC__ 3264 hard_syslog(int pri, char *msg, ...) 3265 # else 3266 hard_syslog(pri, msg, va_alist) 3267 int pri; 3268 char *msg; 3269 va_dcl 3270 # endif 3271 { 3272 int i; 3273 char buf[SYSLOG_BUFSIZE * 2]; 3274 VA_LOCAL_DECL; 3275 3276 VA_START(msg); 3277 vsprintf(buf, msg, ap); 3278 VA_END; 3279 3280 for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; ) 3281 continue; 3282 } 3283 3284 #endif 3285 /* 3286 ** LOCAL_HOSTNAME_LENGTH 3287 ** 3288 ** This is required to get sendmail to compile against BIND 4.9.x 3289 ** on Ultrix. 3290 */ 3291 3292 #if defined(ultrix) && NAMED_BIND 3293 3294 # include <resolv.h> 3295 # if __RES >= 19931104 3296 3297 int 3298 local_hostname_length(hostname) 3299 char *hostname; 3300 { 3301 int len_host, len_domain; 3302 3303 if (!*_res.defdname) 3304 res_init(); 3305 len_host = strlen(hostname); 3306 len_domain = strlen(_res.defdname); 3307 if (len_host > len_domain && 3308 (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) && 3309 hostname[len_host - len_domain - 1] == '.') 3310 return len_host - len_domain - 1; 3311 else 3312 return 0; 3313 } 3314 3315 # endif 3316 #endif 3317 /* 3318 ** Compile-Time options 3319 */ 3320 3321 char *CompileOptions[] = 3322 { 3323 #if HESIOD 3324 "HESIOD", 3325 #endif 3326 #if LOG 3327 "LOG", 3328 #endif 3329 #if MATCHGECOS 3330 "MATCHGECOS", 3331 #endif 3332 #if NAMED_BIND 3333 "NAMED_BIND", 3334 #endif 3335 #if NDBM 3336 "NDBM", 3337 #endif 3338 #if NETINET 3339 "NETINET", 3340 #endif 3341 #if NETINFO 3342 "NETINFO", 3343 #endif 3344 #if NETISO 3345 "NETISO", 3346 #endif 3347 #if NETNS 3348 "NETNS", 3349 #endif 3350 #if NETUNIX 3351 "NETUNIX", 3352 #endif 3353 #if NETX25 3354 "NETX25", 3355 #endif 3356 #if NEWDB 3357 "NEWDB", 3358 #endif 3359 #if NIS 3360 "NIS", 3361 #endif 3362 #if NISPLUS 3363 "NISPLUS", 3364 #endif 3365 #if SCANF 3366 "SCANF", 3367 #endif 3368 #if SUID_ROOT_FILES_OK 3369 "SUID_ROOT_FILES_OK", 3370 #endif 3371 #if USERDB 3372 "USERDB", 3373 #endif 3374 #if XDEBUG 3375 "XDEBUG", 3376 #endif 3377 #if XLA 3378 "XLA", 3379 #endif 3380 NULL 3381 }; 3382