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