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