122698Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642825Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822698Sdist 922698Sdist #ifndef lint 10*58151Seric static char sccsid[] = "@(#)conf.c 6.25 (Berkeley) 02/23/93"; 1133728Sbostic #endif /* not lint */ 1222698Sdist 1314881Seric # include <sys/ioctl.h> 1458082Seric # include <sys/param.h> 1536928Sbostic # include <pwd.h> 163309Seric # include "sendmail.h" 1740980Sbostic # include "pathnames.h" 18404Seric 19294Seric /* 203309Seric ** CONF.C -- Sendmail Configuration Tables. 21294Seric ** 22294Seric ** Defines the configuration of this installation. 23294Seric ** 241388Seric ** Configuration Variables: 252897Seric ** HdrInfo -- a table describing well-known header fields. 262897Seric ** Each entry has the field name and some flags, 274147Seric ** which are described in sendmail.h. 284093Seric ** 294093Seric ** Notes: 304093Seric ** I have tried to put almost all the reasonable 314093Seric ** configuration information into the configuration 324093Seric ** file read at runtime. My intent is that anything 334093Seric ** here is a function of the version of UNIX you 344093Seric ** are running, or is really static -- for example 354093Seric ** the headers are a superset of widely used 364093Seric ** protocols. If you find yourself playing with 374093Seric ** this file too much, you may be making a mistake! 38294Seric */ 39294Seric 40294Seric 41294Seric 42294Seric 434437Seric /* 442897Seric ** Header info table 453057Seric ** Final (null) entry contains the flags used for any other field. 464147Seric ** 474147Seric ** Not all of these are actually handled specially by sendmail 484147Seric ** at this time. They are included as placeholders, to let 494147Seric ** you know that "someday" I intend to have sendmail do 504147Seric ** something with them. 512897Seric */ 522897Seric 532897Seric struct hdrinfo HdrInfo[] = 542897Seric { 558060Seric /* originator fields, most to least significant */ 5611417Seric "resent-sender", H_FROM|H_RESENT, 5711417Seric "resent-from", H_FROM|H_RESENT, 5825686Seric "resent-reply-to", H_FROM|H_RESENT, 599055Seric "sender", H_FROM, 609055Seric "from", H_FROM, 6125686Seric "reply-to", H_FROM, 629055Seric "full-name", H_ACHECK, 6357359Seric "return-receipt-to", H_FROM /* |H_RECEIPTTO */, 6457359Seric "errors-to", H_FROM|H_ERRORSTO, 658060Seric /* destination fields */ 669055Seric "to", H_RCPT, 6711417Seric "resent-to", H_RCPT|H_RESENT, 689055Seric "cc", H_RCPT, 6911417Seric "resent-cc", H_RCPT|H_RESENT, 709055Seric "bcc", H_RCPT|H_ACHECK, 7111417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 7256215Seric "apparently-to", H_RCPT, 738060Seric /* message identification and control */ 7411417Seric "message-id", 0, 7511417Seric "resent-message-id", H_RESENT, 769055Seric "message", H_EOH, 779055Seric "text", H_EOH, 7811417Seric /* date fields */ 7911417Seric "date", 0, 8011417Seric "resent-date", H_RESENT, 818060Seric /* trace fields */ 829055Seric "received", H_TRACE|H_FORCE, 839055Seric "via", H_TRACE|H_FORCE, 849055Seric "mail-from", H_TRACE|H_FORCE, 858060Seric 869055Seric NULL, 0, 872897Seric }; 884166Seric 894166Seric 904166Seric 914282Seric /* 924282Seric ** Location of system files/databases/etc. 934282Seric */ 944282Seric 9540980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 9640980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 9758082Seric char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */ 989039Seric 999064Seric 1009064Seric 1019039Seric /* 10258082Seric ** Privacy values 10358082Seric */ 10458082Seric 10558082Seric struct prival PrivacyValues[] = 10658082Seric { 10758082Seric "public", PRIV_PUBLIC, 10858082Seric "needmailhelo", PRIV_NEEDMAILHELO, 10958114Seric "needexpnhelo", PRIV_NEEDEXPNHELO, 11058082Seric "needvrfyhelo", PRIV_NEEDVRFYHELO, 11158082Seric "noexpn", PRIV_NOEXPN, 11258082Seric "novrfy", PRIV_NOVRFY, 11358082Seric "goaway", PRIV_GOAWAY, 11458082Seric NULL, PRIV_PUBLIC, 11558082Seric }; 11658082Seric 11758082Seric 11858082Seric 11958082Seric /* 12024943Seric ** Miscellaneous stuff. 1219039Seric */ 1229039Seric 12324943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 12424943Seric /* 12524943Seric ** SETDEFAULTS -- set default values 12624943Seric ** 12724943Seric ** Because of the way freezing is done, these must be initialized 12824943Seric ** using direct code. 12924943Seric ** 13024943Seric ** Parameters: 13124943Seric ** none. 13224943Seric ** 13324943Seric ** Returns: 13424943Seric ** none. 13524943Seric ** 13624943Seric ** Side Effects: 13724943Seric ** Initializes a bunch of global variables to their 13824943Seric ** default values. 13924943Seric */ 14024943Seric 14124943Seric setdefaults() 14224943Seric { 14357438Seric SpaceSub = ' '; /* option B */ 14457438Seric QueueLA = 8; /* option x */ 14557438Seric RefuseLA = 12; /* option X */ 14657438Seric WkRecipFact = 30000L; /* option y */ 14757438Seric WkClassFact = 1800L; /* option z */ 14857438Seric WkTimeFact = 90000L; /* option Z */ 14957438Seric QueueFactor = WkRecipFact * 20; /* option q */ 15057142Seric FileMode = (getuid() != geteuid()) ? 0644 : 0600; 15157438Seric /* option F */ 15257438Seric DefUid = 1; /* option u */ 15357438Seric DefGid = 1; /* option g */ 15457438Seric CheckpointInterval = 10; /* option C */ 15557438Seric MaxHopCount = 25; /* option h */ 15657438Seric SendMode = SM_FORK; /* option d */ 15757438Seric ErrorMode = EM_PRINT; /* option e */ 15857438Seric EightBit = FALSE; /* option 8 */ 15957438Seric MaxMciCache = 1; /* option k */ 16057438Seric MciCacheTimeout = 300; /* option K */ 16157438Seric LogLevel = 9; /* option L */ 16258112Seric settimeouts(NULL); /* option r */ 16358112Seric TimeOut = 5 * 24 * 60 * 60; /* option T */ 16440973Sbostic setdefuser(); 16553654Seric setupmaps(); 16657402Seric setupmailers(); 16724943Seric } 168294Seric 16940973Sbostic 1704326Seric /* 17140973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 17240973Sbostic */ 17340973Sbostic 17440973Sbostic setdefuser() 17540973Sbostic { 17640973Sbostic struct passwd *defpwent; 17757386Seric static char defuserbuf[40]; 17840973Sbostic 17957386Seric DefUser = defuserbuf; 18040973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 18157386Seric strcpy(defuserbuf, defpwent->pw_name); 18240973Sbostic else 18357386Seric strcpy(defuserbuf, "nobody"); 18440973Sbostic } 18553654Seric /* 18653654Seric ** SETUPMAPS -- set up map classes 18753654Seric ** 18853654Seric ** Since these are compiled in, they cannot be in the config file. 18953654Seric ** 19053654Seric */ 19140973Sbostic 19253654Seric setupmaps() 19353654Seric { 19453654Seric register STAB *s; 19556836Seric extern bool host_map_init(); 19653654Seric extern char *maphostname(); 19740973Sbostic 19853654Seric /* set up host name lookup map */ 19953654Seric s = stab("host", ST_MAPCLASS, ST_ENTER); 20056836Seric s->s_mapclass.map_init = host_map_init; 20153654Seric s->s_mapclass.map_lookup = maphostname; 20253654Seric 20353654Seric /* 20453654Seric ** Set up other map classes. 20553654Seric */ 20653654Seric 20753654Seric # ifdef DBM_MAP 20853654Seric /* dbm file access */ 20953654Seric { 21056836Seric extern bool dbm_map_init(); 21153654Seric extern char *dbm_map_lookup(); 21253654Seric 21353654Seric s = stab("dbm", ST_MAPCLASS, ST_ENTER); 21453654Seric s->s_mapclass.map_init = dbm_map_init; 21553654Seric s->s_mapclass.map_lookup = dbm_map_lookup; 21653654Seric } 21753654Seric # endif 21853654Seric 21953654Seric # ifdef BTREE_MAP 22053654Seric /* new database file access -- btree files */ 22153654Seric { 22256823Seric extern bool bt_map_init(); 22356823Seric extern char *db_map_lookup(); 22453654Seric 22553654Seric s = stab("btree", ST_MAPCLASS, ST_ENTER); 22653654Seric s->s_mapclass.map_init = bt_map_init; 22756823Seric s->s_mapclass.map_lookup = db_map_lookup; 22853654Seric } 22953654Seric # endif 23053654Seric 23153654Seric # ifdef HASH_MAP 23253654Seric /* new database file access -- hash files */ 23353654Seric { 23456823Seric extern bool hash_map_init(); 23556823Seric extern char *db_map_lookup(); 23653654Seric 23753654Seric s = stab("hash", ST_MAPCLASS, ST_ENTER); 23853654Seric s->s_mapclass.map_init = hash_map_init; 23956823Seric s->s_mapclass.map_lookup = db_map_lookup; 24053654Seric } 24153654Seric # endif 24253654Seric 24357208Seric # ifdef NIS_MAP 24457208Seric /* NIS map access */ 24557208Seric { 24657208Seric extern bool nis_map_init(); 24757208Seric extern char *nis_map_lookup(); 24857208Seric 24957208Seric s = stab("nis", ST_MAPCLASS, ST_ENTER); 25057208Seric s->s_mapclass.map_init = nis_map_init; 25157208Seric s->s_mapclass.map_lookup = nis_map_lookup; 25257208Seric } 25357208Seric # endif 25457208Seric 25553654Seric # ifdef USERDB_MAP 25653654Seric /* user database */ 25753654Seric { 25856836Seric extern bool udb_map_init(); 25953654Seric extern char *udb_map_lookup(); 26053654Seric 26153654Seric s = stab("udb", ST_MAPCLASS, ST_ENTER); 26253654Seric s->s_mapclass.map_init = udb_map_init; 26353654Seric s->s_mapclass.map_lookup = udb_map_lookup; 26453654Seric } 26553654Seric # endif 26653654Seric } 26753654Seric /* 26856836Seric ** HOST_MAP_INIT -- initialize host class structures 26956836Seric */ 27056836Seric 27156836Seric bool 27256836Seric host_map_init(map, mapname, args) 27356836Seric MAP *map; 27456836Seric char *mapname; 27556836Seric char *args; 27656836Seric { 27756836Seric register char *p = args; 27856836Seric 27956836Seric for (;;) 28056836Seric { 28158050Seric while (isascii(*p) && isspace(*p)) 28256836Seric p++; 28356836Seric if (*p != '-') 28456836Seric break; 28556836Seric switch (*++p) 28656836Seric { 28756836Seric case 'a': 28856836Seric map->map_app = ++p; 28956836Seric break; 29056836Seric } 29158050Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 29256836Seric p++; 29356836Seric if (*p != '\0') 29456836Seric *p++ = '\0'; 29556836Seric } 29656836Seric if (map->map_app != NULL) 29756836Seric map->map_app = newstr(map->map_app); 29856836Seric return TRUE; 29956836Seric } 30057402Seric /* 30157402Seric ** SETUPMAILERS -- initialize default mailers 30257402Seric */ 30356836Seric 30457402Seric setupmailers() 30557402Seric { 30657402Seric char buf[100]; 30757402Seric 30857403Seric strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); 30957403Seric makemailer(buf); 31057403Seric 31157402Seric strcpy(buf, "*file*, P=/dev/null, F=lsDEu, A=FILE"); 31257402Seric makemailer(buf); 31357402Seric 31457402Seric strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 31557402Seric makemailer(buf); 31657402Seric } 31756836Seric /* 3184326Seric ** GETRUID -- get real user id (V7) 3194326Seric */ 3204326Seric 3214326Seric getruid() 3224326Seric { 3239274Seric if (OpMode == MD_DAEMON) 3244536Seric return (RealUid); 3254536Seric else 3264536Seric return (getuid()); 3274326Seric } 3284326Seric 3294326Seric 3304326Seric /* 3314326Seric ** GETRGID -- get real group id (V7). 3324326Seric */ 3334326Seric 3344326Seric getrgid() 3354326Seric { 3369274Seric if (OpMode == MD_DAEMON) 3374536Seric return (RealGid); 3384536Seric else 3394536Seric return (getgid()); 3404326Seric } 34153654Seric /* 3429369Seric ** USERNAME -- return the user id of the logged in user. 3439369Seric ** 3449369Seric ** Parameters: 3459369Seric ** none. 3469369Seric ** 3479369Seric ** Returns: 3489369Seric ** The login name of the logged in user. 3499369Seric ** 3509369Seric ** Side Effects: 3519369Seric ** none. 3529369Seric ** 3539369Seric ** Notes: 3549369Seric ** The return value is statically allocated. 3559369Seric */ 3569369Seric 3579369Seric char * 3589369Seric username() 3599369Seric { 36017469Seric static char *myname = NULL; 3619369Seric extern char *getlogin(); 36219904Smiriam register struct passwd *pw; 3639369Seric 36417469Seric /* cache the result */ 36517469Seric if (myname == NULL) 36617469Seric { 36717469Seric myname = getlogin(); 36817469Seric if (myname == NULL || myname[0] == '\0') 36917469Seric { 37017469Seric 37117469Seric pw = getpwuid(getruid()); 37217469Seric if (pw != NULL) 37340993Sbostic myname = newstr(pw->pw_name); 37417469Seric } 37519904Smiriam else 37619904Smiriam { 37719873Smiriam 37840993Sbostic myname = newstr(myname); 37940993Sbostic if ((pw = getpwnam(myname)) == NULL || 38040993Sbostic getuid() != pw->pw_uid) 38119904Smiriam { 38219873Smiriam pw = getpwuid(getuid()); 38324945Seric if (pw != NULL) 38440993Sbostic myname = newstr(pw->pw_name); 38519873Smiriam } 38619873Smiriam } 38717469Seric if (myname == NULL || myname[0] == '\0') 38817469Seric { 389*58151Seric syserr("554 Who are you?"); 39017469Seric myname = "postmaster"; 39117469Seric } 39217469Seric } 39317469Seric 39417469Seric return (myname); 3959369Seric } 3969369Seric /* 3974190Seric ** TTYPATH -- Get the path of the user's tty 398294Seric ** 399294Seric ** Returns the pathname of the user's tty. Returns NULL if 400294Seric ** the user is not logged in or if s/he has write permission 401294Seric ** denied. 402294Seric ** 403294Seric ** Parameters: 404294Seric ** none 405294Seric ** 406294Seric ** Returns: 407294Seric ** pathname of the user's tty. 408294Seric ** NULL if not logged in or write permission denied. 409294Seric ** 410294Seric ** Side Effects: 411294Seric ** none. 412294Seric ** 413294Seric ** WARNING: 414294Seric ** Return value is in a local buffer. 415294Seric ** 416294Seric ** Called By: 417294Seric ** savemail 418294Seric */ 419294Seric 420294Seric # include <sys/stat.h> 421294Seric 422294Seric char * 423294Seric ttypath() 424294Seric { 425294Seric struct stat stbuf; 426294Seric register char *pathn; 427294Seric extern char *ttyname(); 4284081Seric extern char *getlogin(); 429294Seric 430294Seric /* compute the pathname of the controlling tty */ 4319369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4329369Seric (pathn = ttyname(0)) == NULL) 433294Seric { 434294Seric errno = 0; 435294Seric return (NULL); 436294Seric } 437294Seric 438294Seric /* see if we have write permission */ 4392967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 440294Seric { 441294Seric errno = 0; 442294Seric return (NULL); 443294Seric } 444294Seric 445294Seric /* see if the user is logged in */ 446294Seric if (getlogin() == NULL) 447294Seric return (NULL); 448294Seric 449294Seric /* looks good */ 450294Seric return (pathn); 451294Seric } 4522967Seric /* 4532967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4542967Seric ** 4552967Seric ** This routine can be supplied on a per-installation basis 4562967Seric ** to determine whether a person is allowed to send a message. 4572967Seric ** This allows restriction of certain types of internet 4582967Seric ** forwarding or registration of users. 4592967Seric ** 4602967Seric ** If the hosts are found to be incompatible, an error 46157454Seric ** message should be given using "usrerr" and 0 should 4622967Seric ** be returned. 4632967Seric ** 4644288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4654288Seric ** function; this should be done on huge messages. 4664288Seric ** 4672967Seric ** Parameters: 4682967Seric ** to -- the person being sent to. 4692967Seric ** 4702967Seric ** Returns: 47157459Seric ** an exit status 4722967Seric ** 4732967Seric ** Side Effects: 4742967Seric ** none (unless you include the usrerr stuff) 4752967Seric */ 4762967Seric 47755012Seric checkcompat(to, e) 4782967Seric register ADDRESS *to; 47955012Seric register ENVELOPE *e; 4802967Seric { 48112133Seric # ifdef lint 48212133Seric if (to == NULL) 48312133Seric to++; 48412133Seric # endif lint 48510698Seric # ifdef EXAMPLE_CODE 48610698Seric /* this code is intended as an example only */ 4874437Seric register STAB *s; 4884437Seric 4894437Seric s = stab("arpa", ST_MAILER, ST_FIND); 49055012Seric if (s != NULL && e->e_from.q_mailer != LocalMailer && 4919369Seric to->q_mailer == s->s_mailer) 4924437Seric { 493*58151Seric usrerr("553 No ARPA mail through this machine: see your system administration"); 49410698Seric /* NoReturn = TRUE; to supress return copy */ 49557459Seric return (EX_UNAVAILABLE); 4964437Seric } 49756795Seric # endif /* EXAMPLE_CODE */ 49857459Seric return (EX_OK); 4992967Seric } 5009369Seric /* 5019369Seric ** HOLDSIGS -- arrange to hold all signals 5029369Seric ** 5039369Seric ** Parameters: 5049369Seric ** none. 5059369Seric ** 5069369Seric ** Returns: 5079369Seric ** none. 5089369Seric ** 5099369Seric ** Side Effects: 5109369Seric ** Arranges that signals are held. 5119369Seric */ 5129369Seric 5139369Seric holdsigs() 5149369Seric { 5159369Seric } 5169369Seric /* 5179369Seric ** RLSESIGS -- arrange to release all signals 5189369Seric ** 5199369Seric ** This undoes the effect of holdsigs. 5209369Seric ** 5219369Seric ** Parameters: 5229369Seric ** none. 5239369Seric ** 5249369Seric ** Returns: 5259369Seric ** none. 5269369Seric ** 5279369Seric ** Side Effects: 5289369Seric ** Arranges that signals are released. 5299369Seric */ 5309369Seric 5319369Seric rlsesigs() 5329369Seric { 5339369Seric } 53414872Seric /* 53514872Seric ** GETLA -- get the current load average 53614872Seric ** 53714881Seric ** This code stolen from la.c. 53814881Seric ** 53914872Seric ** Parameters: 54014872Seric ** none. 54114872Seric ** 54214872Seric ** Returns: 54314872Seric ** The current load average as an integer. 54414872Seric ** 54514872Seric ** Side Effects: 54614872Seric ** none. 54714872Seric */ 54814872Seric 54951920Seric /* try to guess what style of load average we have */ 55051920Seric #define LA_ZERO 1 /* always return load average as zero */ 55151920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 55251920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 55351920Seric #define LA_SUBR 4 /* call getloadavg */ 55414872Seric 55551920Seric #ifndef LA_TYPE 55651920Seric # if defined(sun) 55751920Seric # define LA_TYPE LA_INT 55851920Seric # endif 55957977Seric # if defined(mips) || defined(__alpha) 56057977Seric /* Ultrix or OSF/1 or RISC/os */ 56151920Seric # define LA_TYPE LA_INT 56251920Seric # define LA_AVENRUN "avenrun" 56351920Seric # endif 56451920Seric # if defined(hpux) 56551920Seric # define LA_TYPE LA_FLOAT 56651920Seric # endif 56751920Seric 56851920Seric # ifndef LA_TYPE 56957736Seric # if defined(SYSTEM5) 57057736Seric # define LA_TYPE LA_INT 57157736Seric # define LA_AVENRUN "avenrun" 57257736Seric # else 57357736Seric # if defined(BSD) 57457736Seric # define LA_TYPE LA_SUBR 57557736Seric # else 57657736Seric # define LA_TYPE LA_ZERO 57757736Seric # endif 57857736Seric # endif 57951920Seric # endif 58051920Seric #endif 58151920Seric 58251920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 58351920Seric 58414872Seric #include <nlist.h> 58551920Seric #include <fcntl.h> 58614872Seric 58751920Seric #ifndef LA_AVENRUN 58851920Seric #define LA_AVENRUN "_avenrun" 58951920Seric #endif 59051920Seric 59151920Seric /* _PATH_UNIX should be defined in <paths.h> */ 59251920Seric #ifndef _PATH_UNIX 59351920Seric # if defined(hpux) 59451920Seric # define _PATH_UNIX "/hp-ux" 59551920Seric # endif 59651920Seric # if defined(mips) && !defined(ultrix) 59751920Seric /* powerful RISC/os */ 59851920Seric # define _PATH_UNIX "/unix" 59951920Seric # endif 60057736Seric # if defined(SYSTEM5) 60157977Seric # ifndef _PATH_UNIX 60257977Seric # define _PATH_UNIX "/unix" 60357977Seric # endif 60457736Seric # endif 60551920Seric # ifndef _PATH_UNIX 60651920Seric # define _PATH_UNIX "/vmunix" 60751920Seric # endif 60851920Seric #endif 60951920Seric 61014872Seric struct nlist Nl[] = 61114872Seric { 61251920Seric { LA_AVENRUN }, 61314872Seric #define X_AVENRUN 0 61414872Seric { 0 }, 61514872Seric }; 61614872Seric 61757736Seric #if defined(unixpc) 61857736Seric # define FSHIFT 5 61957736Seric #endif 62057736Seric 62157977Seric #if defined(__alpha) 62257977Seric # define FSHIFT 10 62357977Seric #endif 62457977Seric 62551920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 62651920Seric # define FSHIFT 8 62757736Seric #endif 62857736Seric #if (LA_TYPE == LA_INT) && !defined(FSCALE) 62951920Seric # define FSCALE (1 << FSHIFT) 63051920Seric #endif 63140930Srick 63214872Seric getla() 63314872Seric { 63414872Seric static int kmem = -1; 63551920Seric #if LA_TYPE == LA_INT 63624943Seric long avenrun[3]; 63751920Seric #else 63851920Seric double avenrun[3]; 63951920Seric #endif 64025615Seric extern off_t lseek(); 64157736Seric extern char *errstring(); 64257736Seric extern int errno; 64314872Seric 64414872Seric if (kmem < 0) 64514872Seric { 64624945Seric kmem = open("/dev/kmem", 0, 0); 64714872Seric if (kmem < 0) 64857736Seric { 64957736Seric if (tTd(3, 1)) 65057736Seric printf("getla: open(/dev/kmem): %s\n", 65157736Seric errstring(errno)); 65214872Seric return (-1); 65357736Seric } 65451920Seric (void) fcntl(kmem, F_SETFD, 1); 65557736Seric if (nlist(_PATH_UNIX, Nl) < 0) 65657736Seric { 65757736Seric if (tTd(3, 1)) 65857736Seric printf("getla: nlist(%s): %s\n", _PATH_UNIX, 65957736Seric errstring(errno)); 66014872Seric return (-1); 66157736Seric } 66214872Seric } 66357736Seric if (tTd(3, 20)) 66457736Seric printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); 66524945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 66623118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 66719967Seric { 66819967Seric /* thank you Ian */ 66957736Seric if (tTd(3, 1)) 67057736Seric printf("getla: lseek or read: %s\n", errstring(errno)); 67119967Seric return (-1); 67219967Seric } 67351920Seric #if LA_TYPE == LA_INT 67457736Seric if (tTd(3, 5)) 67557736Seric { 67657736Seric printf("getla: avenrun = %d", avenrun[0]); 67757736Seric if (tTd(3, 15)) 67857736Seric printf(", %d, %d", avenrun[1], avenrun[2]); 67957736Seric printf("\n"); 68057736Seric } 68157736Seric if (tTd(3, 1)) 68257736Seric printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 68324943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 68451920Seric #else 68557736Seric if (tTd(3, 5)) 68657736Seric { 68757736Seric printf("getla: avenrun = %g", avenrun[0]); 68857736Seric if (tTd(3, 15)) 68957736Seric printf(", %g, %g", avenrun[1], avenrun[2]); 69057736Seric printf("\n"); 69157736Seric } 69257736Seric if (tTd(3, 1)) 69357736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 69451920Seric return ((int) (avenrun[0] + 0.5)); 69551920Seric #endif 69614872Seric } 69714872Seric 69851773Seric #else 69951920Seric #if LA_TYPE == LA_SUBR 70051773Seric 70151773Seric getla() 70251773Seric { 70351920Seric double avenrun[3]; 70451920Seric 70551920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 70657736Seric { 70757736Seric if (tTd(3, 1)) 70857736Seric perror("getla: getloadavg failed:"); 70951920Seric return (-1); 71057736Seric } 71157736Seric if (tTd(3, 1)) 71257736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 71351920Seric return ((int) (avenrun[0] + 0.5)); 71451773Seric } 71551773Seric 71651773Seric #else 71751773Seric 71851773Seric getla() 71951773Seric { 72057736Seric if (tTd(3, 1)) 72157736Seric printf("getla: ZERO\n"); 72251920Seric return (0); 72351773Seric } 72451773Seric 72551773Seric #endif 72651773Seric #endif 72724943Seric /* 72824943Seric ** SHOULDQUEUE -- should this message be queued or sent? 72924943Seric ** 73024943Seric ** Compares the message cost to the load average to decide. 73124943Seric ** 73224943Seric ** Parameters: 73324943Seric ** pri -- the priority of the message in question. 73457438Seric ** ctime -- the message creation time. 73524943Seric ** 73624943Seric ** Returns: 73724943Seric ** TRUE -- if this message should be queued up for the 73824943Seric ** time being. 73924943Seric ** FALSE -- if the load is low enough to send this message. 74024943Seric ** 74124943Seric ** Side Effects: 74224943Seric ** none. 74324943Seric */ 74424943Seric 74524943Seric bool 74657438Seric shouldqueue(pri, ctime) 74724943Seric long pri; 74857438Seric time_t ctime; 74924943Seric { 75051920Seric if (CurrentLA < QueueLA) 75124943Seric return (FALSE); 75258132Seric if (CurrentLA >= RefuseLA) 75358132Seric return (TRUE); 75451920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 75524943Seric } 75624943Seric /* 75753037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 75853037Seric ** 75953037Seric ** Parameters: 76053037Seric ** none. 76153037Seric ** 76253037Seric ** Returns: 76353037Seric ** TRUE if incoming SMTP connections should be refused 76453037Seric ** (for now). 76553037Seric ** FALSE if we should accept new work. 76653037Seric ** 76753037Seric ** Side Effects: 76853037Seric ** none. 76953037Seric */ 77053037Seric 77153037Seric bool 77253037Seric refuseconnections() 77353037Seric { 77453037Seric /* this is probably too simplistic */ 77558132Seric return (CurrentLA >= RefuseLA); 77653037Seric } 77753037Seric /* 77824943Seric ** SETPROCTITLE -- set process title for ps 77924943Seric ** 78024943Seric ** Parameters: 78124943Seric ** fmt -- a printf style format string. 78224943Seric ** a, b, c -- possible parameters to fmt. 78324943Seric ** 78424943Seric ** Returns: 78524943Seric ** none. 78624943Seric ** 78724943Seric ** Side Effects: 78824943Seric ** Clobbers argv of our main procedure so ps(1) will 78924943Seric ** display the title. 79024943Seric */ 79124943Seric 79224943Seric /*VARARGS1*/ 79357642Seric #ifdef __STDC__ 79457642Seric setproctitle(char *fmt, ...) 79557642Seric #else 79657642Seric setproctitle(fmt, va_alist) 79724943Seric char *fmt; 79857642Seric va_dcl 79957642Seric #endif 80024943Seric { 80124943Seric # ifdef SETPROCTITLE 80224943Seric register char *p; 80325049Seric register int i; 80456852Seric char buf[MAXLINE]; 80556852Seric VA_LOCAL_DECL 80624943Seric extern char **Argv; 80724943Seric extern char *LastArgv; 80824943Seric 80954996Seric p = buf; 81024943Seric 81154996Seric /* print sendmail: heading for grep */ 81254996Seric (void) strcpy(p, "sendmail: "); 81354996Seric p += strlen(p); 81424943Seric 81554996Seric /* print the argument string */ 81656852Seric VA_START(fmt); 81756852Seric (void) vsprintf(p, fmt, ap); 81856852Seric VA_END; 81954996Seric 82025049Seric i = strlen(buf); 82154996Seric if (i > LastArgv - Argv[0] - 2) 82225049Seric { 82354996Seric i = LastArgv - Argv[0] - 2; 82425049Seric buf[i] = '\0'; 82525049Seric } 82654996Seric (void) strcpy(Argv[0], buf); 82754997Seric p = &Argv[0][i]; 82824943Seric while (p < LastArgv) 82924943Seric *p++ = ' '; 83056795Seric # endif /* SETPROCTITLE */ 83124943Seric } 83225698Seric /* 83325698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 83425698Seric ** 83525698Seric ** Parameters: 83625698Seric ** none. 83725698Seric ** 83825698Seric ** Returns: 83925698Seric ** none. 84025698Seric ** 84125698Seric ** Side Effects: 84225698Seric ** Picks up extant zombies. 84325698Seric */ 84425698Seric 84525698Seric # include <sys/wait.h> 84625698Seric 84746928Sbostic void 84825698Seric reapchild() 84925698Seric { 85025698Seric # ifdef WNOHANG 85125698Seric union wait status; 85225698Seric 85346928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 85425698Seric continue; 85556795Seric # else /* WNOHANG */ 85625698Seric auto int status; 85725698Seric 85846928Sbostic while (wait((int *)&status) > 0) 85925698Seric continue; 86056795Seric # endif /* WNOHANG */ 86158061Seric # ifdef SYSTEM5 86258061Seric (void) signal(SIGCHLD, reapchild); 86358061Seric # endif 86425698Seric } 86555418Seric /* 86655418Seric ** UNSETENV -- remove a variable from the environment 86755418Seric ** 86855418Seric ** Not needed on newer systems. 86955418Seric ** 87055418Seric ** Parameters: 87155418Seric ** name -- the string name of the environment variable to be 87255418Seric ** deleted from the current environment. 87355418Seric ** 87455418Seric ** Returns: 87555418Seric ** none. 87655418Seric ** 87755418Seric ** Globals: 87855418Seric ** environ -- a pointer to the current environment. 87955418Seric ** 88055418Seric ** Side Effects: 88155418Seric ** Modifies environ. 88255418Seric */ 88355418Seric 88455418Seric #ifdef UNSETENV 88555418Seric 88655418Seric void 88755418Seric unsetenv(name) 88855418Seric char *name; 88955418Seric { 89055418Seric extern char **environ; 89155418Seric register char **pp; 89255418Seric int len = strlen(name); 89355418Seric 89455418Seric for (pp = environ; *pp != NULL; pp++) 89555418Seric { 89655418Seric if (strncmp(name, *pp, len) == 0 && 89755418Seric ((*pp)[len] == '=' || (*pp)[len] == '\0')) 89855418Seric break; 89955418Seric } 90055418Seric 90155418Seric for (; *pp != NULL; pp++) 90255418Seric *pp = pp[1]; 90355418Seric } 90455418Seric 90555418Seric #endif /* UNSETENV */ 90656215Seric /* 90756215Seric ** GETDTABLESIZE -- return number of file descriptors 90856215Seric ** 90956215Seric ** Only on non-BSD systems 91056215Seric ** 91156215Seric ** Parameters: 91256215Seric ** none 91356215Seric ** 91456215Seric ** Returns: 91556215Seric ** size of file descriptor table 91656215Seric ** 91756215Seric ** Side Effects: 91856215Seric ** none 91956215Seric */ 92056215Seric 92156215Seric #ifdef SYSTEM5 92256215Seric 92356215Seric int 92456215Seric getdtablesize() 92556215Seric { 92656215Seric return NOFILE; 92756215Seric } 92856215Seric 92956215Seric #endif 93057631Seric /* 93157631Seric ** UNAME -- get the UUCP name of this system. 93257631Seric */ 93357631Seric 93457943Seric #ifndef HASUNAME 93557631Seric 93657631Seric int 93757631Seric uname(name) 93857631Seric struct utsname *name; 93957631Seric { 94057631Seric FILE *file; 94157631Seric char *n; 94257631Seric 94357631Seric name->nodename[0] = '\0'; 94457631Seric 94557661Seric /* try /etc/whoami -- one line with the node name */ 94657631Seric if ((file = fopen("/etc/whoami", "r")) != NULL) 94757631Seric { 94857661Seric (void) fgets(name->nodename, NODE_LENGTH + 1, file); 94957631Seric (void) fclose(file); 95057661Seric n = strchr(name->nodename, '\n'); 95157631Seric if (n != NULL) 95257631Seric *n = '\0'; 95357631Seric if (name->nodename[0] != '\0') 95457631Seric return (0); 95557631Seric } 95657631Seric 95757661Seric /* try /usr/include/whoami.h -- has a #define somewhere */ 95857631Seric if ((file = fopen("/usr/include/whoami.h", "r")) != NULL) 95957631Seric { 96057631Seric char buf[MAXLINE]; 96157631Seric 96257631Seric while (fgets(buf, MAXLINE, file) != NULL) 96357631Seric if (sscanf(buf, "#define sysname \"%*[^\"]\"", 96457631Seric NODE_LENGTH, name->nodename) > 0) 96557631Seric break; 96657631Seric (void) fclose(file); 96757631Seric if (name->nodename[0] != '\0') 96857631Seric return (0); 96957631Seric } 97057631Seric 97157631Seric #ifdef TRUST_POPEN 97257631Seric /* 97357631Seric ** Popen is known to have security holes. 97457631Seric */ 97557631Seric 97657661Seric /* try uuname -l to return local name */ 97757631Seric if ((file = popen("uuname -l", "r")) != NULL) 97857631Seric { 97957661Seric (void) fgets(name, NODE_LENGTH + 1, file); 98057631Seric (void) pclose(file); 98157661Seric n = strchr(name, '\n'); 98257631Seric if (n != NULL) 98357631Seric *n = '\0'; 98457661Seric if (name->nodename[0] != '\0') 98557631Seric return (0); 98657631Seric } 98757631Seric #endif 98857631Seric 98957631Seric return (-1); 99057631Seric } 99157943Seric #endif /* HASUNAME */ 99258068Seric /* 99358068Seric ** INITGROUPS -- initialize groups 99458068Seric ** 99558068Seric ** Stub implementation for System V style systems 99658068Seric */ 99758068Seric 99858068Seric #ifndef HASINITGROUPS 99958068Seric # if !defined(SYSTEM5) || defined(hpux) 100058068Seric # define HASINITGROUPS 100158068Seric # endif 100258068Seric #endif 100358068Seric 100458068Seric #ifndef HASINITGROUPS 100558068Seric 100658068Seric initgroups(name, basegid) 100758068Seric char *name; 100858068Seric int basegid; 100958068Seric { 101058068Seric return 0; 101158068Seric } 101258068Seric 101358068Seric #endif 101458082Seric /* 101558082Seric ** ENOUGHSPACE -- check to see if there is enough free space on the queue fs 101658082Seric ** 101758082Seric ** Only implemented if you have statfs. 101858082Seric ** 101958082Seric ** Parameters: 102058082Seric ** none. 102158082Seric ** 102258082Seric ** Returns: 102358082Seric ** TRUE if there is enough space. 102458082Seric ** FALSE otherwise. 102558082Seric */ 102658082Seric 102758082Seric #ifndef HASSTATFS 102858082Seric # if defined(BSD4_4) || defined(__osf__) 102958082Seric # define HASSTATFS 103058082Seric # endif 103158082Seric #endif 103258082Seric 103358082Seric #ifdef HASSTATFS 103458133Seric # if defined(sgi) || defined(apollo) 103558133Seric # include <sys/statfs.h> 103658133Seric # else 103758133Seric # if defined(sun) || defined(hpux) 103858133Seric # include <sys/vfs.h> 103958133Seric # else 104058133Seric # include <sys/mount.h> 104158133Seric # endif 104258133Seric # endif 104358082Seric #endif 104458082Seric 104558082Seric bool 104658082Seric enoughspace() 104758082Seric { 104858082Seric #ifdef HASSTATFS 104958133Seric # if defined(ultrix) 105058133Seric struct fs_data fs; 105158133Seric # define f_bavail fd_bfreen 105258133Seric # else 105358082Seric struct statfs fs; 105458133Seric # endif 105558082Seric extern int errno; 105658082Seric extern char *errstring(); 105758082Seric 105858133Seric if (MinBlocksFree <= 0) 105958082Seric { 106058082Seric if (tTd(4, 80)) 106158133Seric printf("enoughspace: no threshold\n"); 106258133Seric return TRUE; 106358133Seric } 106458133Seric # if defined(sgi) || defined(apollo) 106558133Seric if (statfs(QueueDir, &fs, sizeof fs, 0) == 0) 106658133Seric # else 106758133Seric # if defined(ultrix) 106858133Seric if (statfs(QueueDir, &fs) > 0) 106958133Seric # else 107058133Seric if (statfs(QueueDir, &fs) == 0) 107158133Seric # endif 107258133Seric # endif 107358133Seric { 107458133Seric if (tTd(4, 80)) 107558115Seric printf("enoughspace: bavail=%ld, min=%ld\n", 107658115Seric fs.f_bavail, MinBlocksFree); 107758115Seric if (fs.f_bavail < MinBlocksFree) 107858090Seric { 107958090Seric #ifdef LOG 108058090Seric if (LogLevel > 0) 108158090Seric syslog(LOG_ALERT, "%s: low on space (have %ld, need %ld)", 108258115Seric QueueDir, fs.f_bavail, MinBlocksFree); 108358090Seric #endif 108458082Seric return FALSE; 108558090Seric } 108658082Seric } 108758082Seric else if (tTd(4, 80)) 108858082Seric printf("enoughspace: min=%ld: %s\n", 108958082Seric MinBlocksFree, errstring(errno)); 109058082Seric #endif 109158082Seric return TRUE; 109258082Seric } 1093