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