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