1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)conf.c 6.23 (Berkeley) 02/21/93"; 11 #endif /* not lint */ 12 13 # include <sys/ioctl.h> 14 # include <sys/param.h> 15 # include <pwd.h> 16 # include "sendmail.h" 17 # include "pathnames.h" 18 19 /* 20 ** CONF.C -- Sendmail Configuration Tables. 21 ** 22 ** Defines the configuration of this installation. 23 ** 24 ** Configuration Variables: 25 ** HdrInfo -- a table describing well-known header fields. 26 ** Each entry has the field name and some flags, 27 ** which are described in sendmail.h. 28 ** 29 ** Notes: 30 ** I have tried to put almost all the reasonable 31 ** configuration information into the configuration 32 ** file read at runtime. My intent is that anything 33 ** here is a function of the version of UNIX you 34 ** are running, or is really static -- for example 35 ** the headers are a superset of widely used 36 ** protocols. If you find yourself playing with 37 ** this file too much, you may be making a mistake! 38 */ 39 40 41 42 43 /* 44 ** Header info table 45 ** Final (null) entry contains the flags used for any other field. 46 ** 47 ** Not all of these are actually handled specially by sendmail 48 ** at this time. They are included as placeholders, to let 49 ** you know that "someday" I intend to have sendmail do 50 ** something with them. 51 */ 52 53 struct hdrinfo HdrInfo[] = 54 { 55 /* originator fields, most to least significant */ 56 "resent-sender", H_FROM|H_RESENT, 57 "resent-from", H_FROM|H_RESENT, 58 "resent-reply-to", H_FROM|H_RESENT, 59 "sender", H_FROM, 60 "from", H_FROM, 61 "reply-to", H_FROM, 62 "full-name", H_ACHECK, 63 "return-receipt-to", H_FROM /* |H_RECEIPTTO */, 64 "errors-to", H_FROM|H_ERRORSTO, 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_ACHECK, 71 "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 72 "apparently-to", H_RCPT, 73 /* message identification and control */ 74 "message-id", 0, 75 "resent-message-id", H_RESENT, 76 "message", H_EOH, 77 "text", H_EOH, 78 /* date fields */ 79 "date", 0, 80 "resent-date", H_RESENT, 81 /* trace fields */ 82 "received", H_TRACE|H_FORCE, 83 "via", H_TRACE|H_FORCE, 84 "mail-from", H_TRACE|H_FORCE, 85 86 NULL, 0, 87 }; 88 89 90 /* 91 ** ARPANET error message numbers. 92 */ 93 94 char Arpa_Info[] = "050"; /* arbitrary info */ 95 char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 96 char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 97 char Arpa_Usrerr[] = "501"; /* some (fatal) user error */ 98 99 100 101 /* 102 ** Location of system files/databases/etc. 103 */ 104 105 char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 106 char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 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 "goaway", PRIV_GOAWAY, 124 NULL, PRIV_PUBLIC, 125 }; 126 127 128 129 /* 130 ** Miscellaneous stuff. 131 */ 132 133 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 134 /* 135 ** SETDEFAULTS -- set default values 136 ** 137 ** Because of the way freezing is done, these must be initialized 138 ** using direct code. 139 ** 140 ** Parameters: 141 ** none. 142 ** 143 ** Returns: 144 ** none. 145 ** 146 ** Side Effects: 147 ** Initializes a bunch of global variables to their 148 ** default values. 149 */ 150 151 setdefaults() 152 { 153 SpaceSub = ' '; /* option B */ 154 QueueLA = 8; /* option x */ 155 RefuseLA = 12; /* option X */ 156 WkRecipFact = 30000L; /* option y */ 157 WkClassFact = 1800L; /* option z */ 158 WkTimeFact = 90000L; /* option Z */ 159 QueueFactor = WkRecipFact * 20; /* option q */ 160 FileMode = (getuid() != geteuid()) ? 0644 : 0600; 161 /* option F */ 162 DefUid = 1; /* option u */ 163 DefGid = 1; /* option g */ 164 CheckpointInterval = 10; /* option C */ 165 MaxHopCount = 25; /* option h */ 166 SendMode = SM_FORK; /* option d */ 167 ErrorMode = EM_PRINT; /* option e */ 168 EightBit = FALSE; /* option 8 */ 169 MaxMciCache = 1; /* option k */ 170 MciCacheTimeout = 300; /* option K */ 171 LogLevel = 9; /* option L */ 172 settimeouts(NULL); /* option r */ 173 TimeOut = 5 * 24 * 60 * 60; /* option T */ 174 setdefuser(); 175 setupmaps(); 176 setupmailers(); 177 } 178 179 180 /* 181 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 182 */ 183 184 setdefuser() 185 { 186 struct passwd *defpwent; 187 static char defuserbuf[40]; 188 189 DefUser = defuserbuf; 190 if ((defpwent = getpwuid(DefUid)) != NULL) 191 strcpy(defuserbuf, defpwent->pw_name); 192 else 193 strcpy(defuserbuf, "nobody"); 194 } 195 /* 196 ** SETUPMAPS -- set up map classes 197 ** 198 ** Since these are compiled in, they cannot be in the config file. 199 ** 200 */ 201 202 setupmaps() 203 { 204 register STAB *s; 205 extern bool host_map_init(); 206 extern char *maphostname(); 207 208 /* set up host name lookup map */ 209 s = stab("host", ST_MAPCLASS, ST_ENTER); 210 s->s_mapclass.map_init = host_map_init; 211 s->s_mapclass.map_lookup = maphostname; 212 213 /* 214 ** Set up other map classes. 215 */ 216 217 # ifdef DBM_MAP 218 /* dbm file access */ 219 { 220 extern bool dbm_map_init(); 221 extern char *dbm_map_lookup(); 222 223 s = stab("dbm", ST_MAPCLASS, ST_ENTER); 224 s->s_mapclass.map_init = dbm_map_init; 225 s->s_mapclass.map_lookup = dbm_map_lookup; 226 } 227 # endif 228 229 # ifdef BTREE_MAP 230 /* new database file access -- btree files */ 231 { 232 extern bool bt_map_init(); 233 extern char *db_map_lookup(); 234 235 s = stab("btree", ST_MAPCLASS, ST_ENTER); 236 s->s_mapclass.map_init = bt_map_init; 237 s->s_mapclass.map_lookup = db_map_lookup; 238 } 239 # endif 240 241 # ifdef HASH_MAP 242 /* new database file access -- hash files */ 243 { 244 extern bool hash_map_init(); 245 extern char *db_map_lookup(); 246 247 s = stab("hash", ST_MAPCLASS, ST_ENTER); 248 s->s_mapclass.map_init = hash_map_init; 249 s->s_mapclass.map_lookup = db_map_lookup; 250 } 251 # endif 252 253 # ifdef NIS_MAP 254 /* NIS map access */ 255 { 256 extern bool nis_map_init(); 257 extern char *nis_map_lookup(); 258 259 s = stab("nis", ST_MAPCLASS, ST_ENTER); 260 s->s_mapclass.map_init = nis_map_init; 261 s->s_mapclass.map_lookup = nis_map_lookup; 262 } 263 # endif 264 265 # ifdef USERDB_MAP 266 /* user database */ 267 { 268 extern bool udb_map_init(); 269 extern char *udb_map_lookup(); 270 271 s = stab("udb", ST_MAPCLASS, ST_ENTER); 272 s->s_mapclass.map_init = udb_map_init; 273 s->s_mapclass.map_lookup = udb_map_lookup; 274 } 275 # endif 276 } 277 /* 278 ** HOST_MAP_INIT -- initialize host class structures 279 */ 280 281 bool 282 host_map_init(map, mapname, args) 283 MAP *map; 284 char *mapname; 285 char *args; 286 { 287 register char *p = args; 288 289 for (;;) 290 { 291 while (isascii(*p) && isspace(*p)) 292 p++; 293 if (*p != '-') 294 break; 295 switch (*++p) 296 { 297 case 'a': 298 map->map_app = ++p; 299 break; 300 } 301 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 302 p++; 303 if (*p != '\0') 304 *p++ = '\0'; 305 } 306 if (map->map_app != NULL) 307 map->map_app = newstr(map->map_app); 308 return TRUE; 309 } 310 /* 311 ** SETUPMAILERS -- initialize default mailers 312 */ 313 314 setupmailers() 315 { 316 char buf[100]; 317 318 strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); 319 makemailer(buf); 320 321 strcpy(buf, "*file*, P=/dev/null, F=lsDEu, A=FILE"); 322 makemailer(buf); 323 324 strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 325 makemailer(buf); 326 } 327 /* 328 ** GETRUID -- get real user id (V7) 329 */ 330 331 getruid() 332 { 333 if (OpMode == MD_DAEMON) 334 return (RealUid); 335 else 336 return (getuid()); 337 } 338 339 340 /* 341 ** GETRGID -- get real group id (V7). 342 */ 343 344 getrgid() 345 { 346 if (OpMode == MD_DAEMON) 347 return (RealGid); 348 else 349 return (getgid()); 350 } 351 /* 352 ** USERNAME -- return the user id of the logged in user. 353 ** 354 ** Parameters: 355 ** none. 356 ** 357 ** Returns: 358 ** The login name of the logged in user. 359 ** 360 ** Side Effects: 361 ** none. 362 ** 363 ** Notes: 364 ** The return value is statically allocated. 365 */ 366 367 char * 368 username() 369 { 370 static char *myname = NULL; 371 extern char *getlogin(); 372 register struct passwd *pw; 373 374 /* cache the result */ 375 if (myname == NULL) 376 { 377 myname = getlogin(); 378 if (myname == NULL || myname[0] == '\0') 379 { 380 381 pw = getpwuid(getruid()); 382 if (pw != NULL) 383 myname = newstr(pw->pw_name); 384 } 385 else 386 { 387 388 myname = newstr(myname); 389 if ((pw = getpwnam(myname)) == NULL || 390 getuid() != pw->pw_uid) 391 { 392 pw = getpwuid(getuid()); 393 if (pw != NULL) 394 myname = newstr(pw->pw_name); 395 } 396 } 397 if (myname == NULL || myname[0] == '\0') 398 { 399 syserr("Who are you?"); 400 myname = "postmaster"; 401 } 402 } 403 404 return (myname); 405 } 406 /* 407 ** TTYPATH -- Get the path of the user's tty 408 ** 409 ** Returns the pathname of the user's tty. Returns NULL if 410 ** the user is not logged in or if s/he has write permission 411 ** denied. 412 ** 413 ** Parameters: 414 ** none 415 ** 416 ** Returns: 417 ** pathname of the user's tty. 418 ** NULL if not logged in or write permission denied. 419 ** 420 ** Side Effects: 421 ** none. 422 ** 423 ** WARNING: 424 ** Return value is in a local buffer. 425 ** 426 ** Called By: 427 ** savemail 428 */ 429 430 # include <sys/stat.h> 431 432 char * 433 ttypath() 434 { 435 struct stat stbuf; 436 register char *pathn; 437 extern char *ttyname(); 438 extern char *getlogin(); 439 440 /* compute the pathname of the controlling tty */ 441 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 442 (pathn = ttyname(0)) == NULL) 443 { 444 errno = 0; 445 return (NULL); 446 } 447 448 /* see if we have write permission */ 449 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 450 { 451 errno = 0; 452 return (NULL); 453 } 454 455 /* see if the user is logged in */ 456 if (getlogin() == NULL) 457 return (NULL); 458 459 /* looks good */ 460 return (pathn); 461 } 462 /* 463 ** CHECKCOMPAT -- check for From and To person compatible. 464 ** 465 ** This routine can be supplied on a per-installation basis 466 ** to determine whether a person is allowed to send a message. 467 ** This allows restriction of certain types of internet 468 ** forwarding or registration of users. 469 ** 470 ** If the hosts are found to be incompatible, an error 471 ** message should be given using "usrerr" and 0 should 472 ** be returned. 473 ** 474 ** 'NoReturn' can be set to suppress the return-to-sender 475 ** function; this should be done on huge messages. 476 ** 477 ** Parameters: 478 ** to -- the person being sent to. 479 ** 480 ** Returns: 481 ** an exit status 482 ** 483 ** Side Effects: 484 ** none (unless you include the usrerr stuff) 485 */ 486 487 checkcompat(to, e) 488 register ADDRESS *to; 489 register ENVELOPE *e; 490 { 491 # ifdef lint 492 if (to == NULL) 493 to++; 494 # endif lint 495 # ifdef EXAMPLE_CODE 496 /* this code is intended as an example only */ 497 register STAB *s; 498 499 s = stab("arpa", ST_MAILER, ST_FIND); 500 if (s != NULL && e->e_from.q_mailer != LocalMailer && 501 to->q_mailer == s->s_mailer) 502 { 503 usrerr("No ARPA mail through this machine: see your system administration"); 504 /* NoReturn = TRUE; to supress return copy */ 505 return (EX_UNAVAILABLE); 506 } 507 # endif /* EXAMPLE_CODE */ 508 return (EX_OK); 509 } 510 /* 511 ** HOLDSIGS -- arrange to hold all signals 512 ** 513 ** Parameters: 514 ** none. 515 ** 516 ** Returns: 517 ** none. 518 ** 519 ** Side Effects: 520 ** Arranges that signals are held. 521 */ 522 523 holdsigs() 524 { 525 } 526 /* 527 ** RLSESIGS -- arrange to release all signals 528 ** 529 ** This undoes the effect of holdsigs. 530 ** 531 ** Parameters: 532 ** none. 533 ** 534 ** Returns: 535 ** none. 536 ** 537 ** Side Effects: 538 ** Arranges that signals are released. 539 */ 540 541 rlsesigs() 542 { 543 } 544 /* 545 ** GETLA -- get the current load average 546 ** 547 ** This code stolen from la.c. 548 ** 549 ** Parameters: 550 ** none. 551 ** 552 ** Returns: 553 ** The current load average as an integer. 554 ** 555 ** Side Effects: 556 ** none. 557 */ 558 559 /* try to guess what style of load average we have */ 560 #define LA_ZERO 1 /* always return load average as zero */ 561 #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 562 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 563 #define LA_SUBR 4 /* call getloadavg */ 564 565 #ifndef LA_TYPE 566 # if defined(sun) 567 # define LA_TYPE LA_INT 568 # endif 569 # if defined(mips) || defined(__alpha) 570 /* Ultrix or OSF/1 or RISC/os */ 571 # define LA_TYPE LA_INT 572 # define LA_AVENRUN "avenrun" 573 # endif 574 # if defined(hpux) 575 # define LA_TYPE LA_FLOAT 576 # endif 577 578 # ifndef LA_TYPE 579 # if defined(SYSTEM5) 580 # define LA_TYPE LA_INT 581 # define LA_AVENRUN "avenrun" 582 # else 583 # if defined(BSD) 584 # define LA_TYPE LA_SUBR 585 # else 586 # define LA_TYPE LA_ZERO 587 # endif 588 # endif 589 # endif 590 #endif 591 592 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 593 594 #include <nlist.h> 595 #include <fcntl.h> 596 597 #ifndef LA_AVENRUN 598 #define LA_AVENRUN "_avenrun" 599 #endif 600 601 /* _PATH_UNIX should be defined in <paths.h> */ 602 #ifndef _PATH_UNIX 603 # if defined(hpux) 604 # define _PATH_UNIX "/hp-ux" 605 # endif 606 # if defined(mips) && !defined(ultrix) 607 /* powerful RISC/os */ 608 # define _PATH_UNIX "/unix" 609 # endif 610 # if defined(SYSTEM5) 611 # ifndef _PATH_UNIX 612 # define _PATH_UNIX "/unix" 613 # endif 614 # endif 615 # ifndef _PATH_UNIX 616 # define _PATH_UNIX "/vmunix" 617 # endif 618 #endif 619 620 struct nlist Nl[] = 621 { 622 { LA_AVENRUN }, 623 #define X_AVENRUN 0 624 { 0 }, 625 }; 626 627 #if defined(unixpc) 628 # define FSHIFT 5 629 #endif 630 631 #if defined(__alpha) 632 # define FSHIFT 10 633 #endif 634 635 #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 636 # define FSHIFT 8 637 #endif 638 #if (LA_TYPE == LA_INT) && !defined(FSCALE) 639 # define FSCALE (1 << FSHIFT) 640 #endif 641 642 getla() 643 { 644 static int kmem = -1; 645 #if LA_TYPE == LA_INT 646 long avenrun[3]; 647 #else 648 double avenrun[3]; 649 #endif 650 extern off_t lseek(); 651 extern char *errstring(); 652 extern int errno; 653 654 if (kmem < 0) 655 { 656 kmem = open("/dev/kmem", 0, 0); 657 if (kmem < 0) 658 { 659 if (tTd(3, 1)) 660 printf("getla: open(/dev/kmem): %s\n", 661 errstring(errno)); 662 return (-1); 663 } 664 (void) fcntl(kmem, F_SETFD, 1); 665 if (nlist(_PATH_UNIX, Nl) < 0) 666 { 667 if (tTd(3, 1)) 668 printf("getla: nlist(%s): %s\n", _PATH_UNIX, 669 errstring(errno)); 670 return (-1); 671 } 672 } 673 if (tTd(3, 20)) 674 printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); 675 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 676 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 677 { 678 /* thank you Ian */ 679 if (tTd(3, 1)) 680 printf("getla: lseek or read: %s\n", errstring(errno)); 681 return (-1); 682 } 683 #if LA_TYPE == LA_INT 684 if (tTd(3, 5)) 685 { 686 printf("getla: avenrun = %d", avenrun[0]); 687 if (tTd(3, 15)) 688 printf(", %d, %d", avenrun[1], avenrun[2]); 689 printf("\n"); 690 } 691 if (tTd(3, 1)) 692 printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 693 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 694 #else 695 if (tTd(3, 5)) 696 { 697 printf("getla: avenrun = %g", avenrun[0]); 698 if (tTd(3, 15)) 699 printf(", %g, %g", avenrun[1], avenrun[2]); 700 printf("\n"); 701 } 702 if (tTd(3, 1)) 703 printf("getla: %d\n", (int) (avenrun[0] +0.5)); 704 return ((int) (avenrun[0] + 0.5)); 705 #endif 706 } 707 708 #else 709 #if LA_TYPE == LA_SUBR 710 711 getla() 712 { 713 double avenrun[3]; 714 715 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 716 { 717 if (tTd(3, 1)) 718 perror("getla: getloadavg failed:"); 719 return (-1); 720 } 721 if (tTd(3, 1)) 722 printf("getla: %d\n", (int) (avenrun[0] +0.5)); 723 return ((int) (avenrun[0] + 0.5)); 724 } 725 726 #else 727 728 getla() 729 { 730 if (tTd(3, 1)) 731 printf("getla: ZERO\n"); 732 return (0); 733 } 734 735 #endif 736 #endif 737 /* 738 ** SHOULDQUEUE -- should this message be queued or sent? 739 ** 740 ** Compares the message cost to the load average to decide. 741 ** 742 ** Parameters: 743 ** pri -- the priority of the message in question. 744 ** ctime -- the message creation time. 745 ** 746 ** Returns: 747 ** TRUE -- if this message should be queued up for the 748 ** time being. 749 ** FALSE -- if the load is low enough to send this message. 750 ** 751 ** Side Effects: 752 ** none. 753 */ 754 755 bool 756 shouldqueue(pri, ctime) 757 long pri; 758 time_t ctime; 759 { 760 if (CurrentLA < QueueLA) 761 return (FALSE); 762 if (CurrentLA >= RefuseLA) 763 return (TRUE); 764 return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 765 } 766 /* 767 ** REFUSECONNECTIONS -- decide if connections should be refused 768 ** 769 ** Parameters: 770 ** none. 771 ** 772 ** Returns: 773 ** TRUE if incoming SMTP connections should be refused 774 ** (for now). 775 ** FALSE if we should accept new work. 776 ** 777 ** Side Effects: 778 ** none. 779 */ 780 781 bool 782 refuseconnections() 783 { 784 /* this is probably too simplistic */ 785 return (CurrentLA >= RefuseLA); 786 } 787 /* 788 ** SETPROCTITLE -- set process title for ps 789 ** 790 ** Parameters: 791 ** fmt -- a printf style format string. 792 ** a, b, c -- possible parameters to fmt. 793 ** 794 ** Returns: 795 ** none. 796 ** 797 ** Side Effects: 798 ** Clobbers argv of our main procedure so ps(1) will 799 ** display the title. 800 */ 801 802 /*VARARGS1*/ 803 #ifdef __STDC__ 804 setproctitle(char *fmt, ...) 805 #else 806 setproctitle(fmt, va_alist) 807 char *fmt; 808 va_dcl 809 #endif 810 { 811 # ifdef SETPROCTITLE 812 register char *p; 813 register int i; 814 char buf[MAXLINE]; 815 VA_LOCAL_DECL 816 extern char **Argv; 817 extern char *LastArgv; 818 819 p = buf; 820 821 /* print sendmail: heading for grep */ 822 (void) strcpy(p, "sendmail: "); 823 p += strlen(p); 824 825 /* print the argument string */ 826 VA_START(fmt); 827 (void) vsprintf(p, fmt, ap); 828 VA_END; 829 830 i = strlen(buf); 831 if (i > LastArgv - Argv[0] - 2) 832 { 833 i = LastArgv - Argv[0] - 2; 834 buf[i] = '\0'; 835 } 836 (void) strcpy(Argv[0], buf); 837 p = &Argv[0][i]; 838 while (p < LastArgv) 839 *p++ = ' '; 840 # endif /* SETPROCTITLE */ 841 } 842 /* 843 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 844 ** 845 ** Parameters: 846 ** none. 847 ** 848 ** Returns: 849 ** none. 850 ** 851 ** Side Effects: 852 ** Picks up extant zombies. 853 */ 854 855 # include <sys/wait.h> 856 857 void 858 reapchild() 859 { 860 # ifdef WNOHANG 861 union wait status; 862 863 while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 864 continue; 865 # else /* WNOHANG */ 866 auto int status; 867 868 while (wait((int *)&status) > 0) 869 continue; 870 # endif /* WNOHANG */ 871 # ifdef SYSTEM5 872 (void) signal(SIGCHLD, reapchild); 873 # endif 874 } 875 /* 876 ** UNSETENV -- remove a variable from the environment 877 ** 878 ** Not needed on newer systems. 879 ** 880 ** Parameters: 881 ** name -- the string name of the environment variable to be 882 ** deleted from the current environment. 883 ** 884 ** Returns: 885 ** none. 886 ** 887 ** Globals: 888 ** environ -- a pointer to the current environment. 889 ** 890 ** Side Effects: 891 ** Modifies environ. 892 */ 893 894 #ifdef UNSETENV 895 896 void 897 unsetenv(name) 898 char *name; 899 { 900 extern char **environ; 901 register char **pp; 902 int len = strlen(name); 903 904 for (pp = environ; *pp != NULL; pp++) 905 { 906 if (strncmp(name, *pp, len) == 0 && 907 ((*pp)[len] == '=' || (*pp)[len] == '\0')) 908 break; 909 } 910 911 for (; *pp != NULL; pp++) 912 *pp = pp[1]; 913 } 914 915 #endif /* UNSETENV */ 916 /* 917 ** GETDTABLESIZE -- return number of file descriptors 918 ** 919 ** Only on non-BSD systems 920 ** 921 ** Parameters: 922 ** none 923 ** 924 ** Returns: 925 ** size of file descriptor table 926 ** 927 ** Side Effects: 928 ** none 929 */ 930 931 #ifdef SYSTEM5 932 933 int 934 getdtablesize() 935 { 936 return NOFILE; 937 } 938 939 #endif 940 /* 941 ** UNAME -- get the UUCP name of this system. 942 */ 943 944 #ifndef HASUNAME 945 946 int 947 uname(name) 948 struct utsname *name; 949 { 950 FILE *file; 951 char *n; 952 953 name->nodename[0] = '\0'; 954 955 /* try /etc/whoami -- one line with the node name */ 956 if ((file = fopen("/etc/whoami", "r")) != NULL) 957 { 958 (void) fgets(name->nodename, NODE_LENGTH + 1, file); 959 (void) fclose(file); 960 n = strchr(name->nodename, '\n'); 961 if (n != NULL) 962 *n = '\0'; 963 if (name->nodename[0] != '\0') 964 return (0); 965 } 966 967 /* try /usr/include/whoami.h -- has a #define somewhere */ 968 if ((file = fopen("/usr/include/whoami.h", "r")) != NULL) 969 { 970 char buf[MAXLINE]; 971 972 while (fgets(buf, MAXLINE, file) != NULL) 973 if (sscanf(buf, "#define sysname \"%*[^\"]\"", 974 NODE_LENGTH, name->nodename) > 0) 975 break; 976 (void) fclose(file); 977 if (name->nodename[0] != '\0') 978 return (0); 979 } 980 981 #ifdef TRUST_POPEN 982 /* 983 ** Popen is known to have security holes. 984 */ 985 986 /* try uuname -l to return local name */ 987 if ((file = popen("uuname -l", "r")) != NULL) 988 { 989 (void) fgets(name, NODE_LENGTH + 1, file); 990 (void) pclose(file); 991 n = strchr(name, '\n'); 992 if (n != NULL) 993 *n = '\0'; 994 if (name->nodename[0] != '\0') 995 return (0); 996 } 997 #endif 998 999 return (-1); 1000 } 1001 #endif /* HASUNAME */ 1002 /* 1003 ** INITGROUPS -- initialize groups 1004 ** 1005 ** Stub implementation for System V style systems 1006 */ 1007 1008 #ifndef HASINITGROUPS 1009 # if !defined(SYSTEM5) || defined(hpux) 1010 # define HASINITGROUPS 1011 # endif 1012 #endif 1013 1014 #ifndef HASINITGROUPS 1015 1016 initgroups(name, basegid) 1017 char *name; 1018 int basegid; 1019 { 1020 return 0; 1021 } 1022 1023 #endif 1024 /* 1025 ** ENOUGHSPACE -- check to see if there is enough free space on the queue fs 1026 ** 1027 ** Only implemented if you have statfs. 1028 ** 1029 ** Parameters: 1030 ** none. 1031 ** 1032 ** Returns: 1033 ** TRUE if there is enough space. 1034 ** FALSE otherwise. 1035 */ 1036 1037 #ifndef HASSTATFS 1038 # if defined(BSD4_4) || defined(__osf__) 1039 # define HASSTATFS 1040 # endif 1041 #endif 1042 1043 #ifdef HASSTATFS 1044 #include <sys/mount.h> 1045 #endif 1046 1047 bool 1048 enoughspace() 1049 { 1050 #ifdef HASSTATFS 1051 struct statfs fs; 1052 extern int errno; 1053 extern char *errstring(); 1054 1055 if (MinBlocksFree > 0 && statfs(QueueDir, &fs) >= 0) 1056 { 1057 if (tTd(4, 80)) 1058 printf("enoughspace: bavail=%ld, min=%ld\n", 1059 fs.f_bavail, MinBlocksFree); 1060 if (fs.f_bavail < MinBlocksFree) 1061 { 1062 #ifdef LOG 1063 if (LogLevel > 0) 1064 syslog(LOG_ALERT, "%s: low on space (have %ld, need %ld)", 1065 QueueDir, fs.f_bavail, MinBlocksFree); 1066 #endif 1067 return FALSE; 1068 } 1069 } 1070 else if (tTd(4, 80)) 1071 printf("enoughspace: min=%ld: %s\n", 1072 MinBlocksFree, errstring(errno)); 1073 #endif 1074 return TRUE; 1075 } 1076