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*57977Seric static char sccsid[] = "@(#)conf.c 6.14 (Berkeley) 02/14/93"; 1133728Sbostic #endif /* not lint */ 1222698Sdist 1314881Seric # include <sys/ioctl.h> 1436928Sbostic # include <pwd.h> 153309Seric # include "sendmail.h" 1640980Sbostic # include "pathnames.h" 17404Seric 18294Seric /* 193309Seric ** CONF.C -- Sendmail Configuration Tables. 20294Seric ** 21294Seric ** Defines the configuration of this installation. 22294Seric ** 231388Seric ** Configuration Variables: 242897Seric ** HdrInfo -- a table describing well-known header fields. 252897Seric ** Each entry has the field name and some flags, 264147Seric ** which are described in sendmail.h. 274093Seric ** 284093Seric ** Notes: 294093Seric ** I have tried to put almost all the reasonable 304093Seric ** configuration information into the configuration 314093Seric ** file read at runtime. My intent is that anything 324093Seric ** here is a function of the version of UNIX you 334093Seric ** are running, or is really static -- for example 344093Seric ** the headers are a superset of widely used 354093Seric ** protocols. If you find yourself playing with 364093Seric ** this file too much, you may be making a mistake! 37294Seric */ 38294Seric 39294Seric 40294Seric 41294Seric 424437Seric /* 432897Seric ** Header info table 443057Seric ** Final (null) entry contains the flags used for any other field. 454147Seric ** 464147Seric ** Not all of these are actually handled specially by sendmail 474147Seric ** at this time. They are included as placeholders, to let 484147Seric ** you know that "someday" I intend to have sendmail do 494147Seric ** something with them. 502897Seric */ 512897Seric 522897Seric struct hdrinfo HdrInfo[] = 532897Seric { 548060Seric /* originator fields, most to least significant */ 5511417Seric "resent-sender", H_FROM|H_RESENT, 5611417Seric "resent-from", H_FROM|H_RESENT, 5725686Seric "resent-reply-to", H_FROM|H_RESENT, 589055Seric "sender", H_FROM, 599055Seric "from", H_FROM, 6025686Seric "reply-to", H_FROM, 619055Seric "full-name", H_ACHECK, 6257359Seric "return-receipt-to", H_FROM /* |H_RECEIPTTO */, 6357359Seric "errors-to", H_FROM|H_ERRORSTO, 648060Seric /* destination fields */ 659055Seric "to", H_RCPT, 6611417Seric "resent-to", H_RCPT|H_RESENT, 679055Seric "cc", H_RCPT, 6811417Seric "resent-cc", H_RCPT|H_RESENT, 699055Seric "bcc", H_RCPT|H_ACHECK, 7011417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 7156215Seric "apparently-to", H_RCPT, 728060Seric /* message identification and control */ 7311417Seric "message-id", 0, 7411417Seric "resent-message-id", H_RESENT, 759055Seric "message", H_EOH, 769055Seric "text", H_EOH, 7711417Seric /* date fields */ 7811417Seric "date", 0, 7911417Seric "resent-date", H_RESENT, 808060Seric /* trace fields */ 819055Seric "received", H_TRACE|H_FORCE, 829055Seric "via", H_TRACE|H_FORCE, 839055Seric "mail-from", H_TRACE|H_FORCE, 848060Seric 859055Seric NULL, 0, 862897Seric }; 874166Seric 884166Seric 894166Seric /* 904166Seric ** ARPANET error message numbers. 914166Seric */ 924166Seric 937956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 947956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 957956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 96*57977Seric char Arpa_Usrerr[] = "501"; /* some (fatal) user error */ 974282Seric 984282Seric 994282Seric 1004282Seric /* 1014282Seric ** Location of system files/databases/etc. 1024282Seric */ 1034282Seric 10440980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 10540980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 1069039Seric 1079064Seric 1089064Seric 1099039Seric /* 11024943Seric ** Miscellaneous stuff. 1119039Seric */ 1129039Seric 11324943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 11424943Seric /* 11524943Seric ** SETDEFAULTS -- set default values 11624943Seric ** 11724943Seric ** Because of the way freezing is done, these must be initialized 11824943Seric ** using direct code. 11924943Seric ** 12024943Seric ** Parameters: 12124943Seric ** none. 12224943Seric ** 12324943Seric ** Returns: 12424943Seric ** none. 12524943Seric ** 12624943Seric ** Side Effects: 12724943Seric ** Initializes a bunch of global variables to their 12824943Seric ** default values. 12924943Seric */ 13024943Seric 13124943Seric setdefaults() 13224943Seric { 13357438Seric SpaceSub = ' '; /* option B */ 13457438Seric QueueLA = 8; /* option x */ 13557438Seric RefuseLA = 12; /* option X */ 13657438Seric WkRecipFact = 30000L; /* option y */ 13757438Seric WkClassFact = 1800L; /* option z */ 13857438Seric WkTimeFact = 90000L; /* option Z */ 13957438Seric QueueFactor = WkRecipFact * 20; /* option q */ 14057142Seric FileMode = (getuid() != geteuid()) ? 0644 : 0600; 14157438Seric /* option F */ 14257438Seric DefUid = 1; /* option u */ 14357438Seric DefGid = 1; /* option g */ 14457438Seric CheckpointInterval = 10; /* option C */ 14557438Seric MaxHopCount = 25; /* option h */ 14657438Seric SendMode = SM_FORK; /* option d */ 14757438Seric ErrorMode = EM_PRINT; /* option e */ 14857438Seric EightBit = FALSE; /* option 8 */ 14957438Seric MaxMciCache = 1; /* option k */ 15057438Seric MciCacheTimeout = 300; /* option K */ 15157438Seric LogLevel = 9; /* option L */ 15257438Seric ReadTimeout = 2 * 60 * 60; /* option r */ 15357438Seric TimeOut = 3 * 24 * 60 * 60; /* option T */ 15440973Sbostic setdefuser(); 15553654Seric setupmaps(); 15657402Seric setupmailers(); 15724943Seric } 158294Seric 15940973Sbostic 1604326Seric /* 16140973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 16240973Sbostic */ 16340973Sbostic 16440973Sbostic setdefuser() 16540973Sbostic { 16640973Sbostic struct passwd *defpwent; 16757386Seric static char defuserbuf[40]; 16840973Sbostic 16957386Seric DefUser = defuserbuf; 17040973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 17157386Seric strcpy(defuserbuf, defpwent->pw_name); 17240973Sbostic else 17357386Seric strcpy(defuserbuf, "nobody"); 17440973Sbostic } 17553654Seric /* 17653654Seric ** SETUPMAPS -- set up map classes 17753654Seric ** 17853654Seric ** Since these are compiled in, they cannot be in the config file. 17953654Seric ** 18053654Seric */ 18140973Sbostic 18253654Seric setupmaps() 18353654Seric { 18453654Seric register STAB *s; 18556836Seric extern bool host_map_init(); 18653654Seric extern char *maphostname(); 18740973Sbostic 18853654Seric /* set up host name lookup map */ 18953654Seric s = stab("host", ST_MAPCLASS, ST_ENTER); 19056836Seric s->s_mapclass.map_init = host_map_init; 19153654Seric s->s_mapclass.map_lookup = maphostname; 19253654Seric 19353654Seric /* 19453654Seric ** Set up other map classes. 19553654Seric */ 19653654Seric 19753654Seric # ifdef DBM_MAP 19853654Seric /* dbm file access */ 19953654Seric { 20056836Seric extern bool dbm_map_init(); 20153654Seric extern char *dbm_map_lookup(); 20253654Seric 20353654Seric s = stab("dbm", ST_MAPCLASS, ST_ENTER); 20453654Seric s->s_mapclass.map_init = dbm_map_init; 20553654Seric s->s_mapclass.map_lookup = dbm_map_lookup; 20653654Seric } 20753654Seric # endif 20853654Seric 20953654Seric # ifdef BTREE_MAP 21053654Seric /* new database file access -- btree files */ 21153654Seric { 21256823Seric extern bool bt_map_init(); 21356823Seric extern char *db_map_lookup(); 21453654Seric 21553654Seric s = stab("btree", ST_MAPCLASS, ST_ENTER); 21653654Seric s->s_mapclass.map_init = bt_map_init; 21756823Seric s->s_mapclass.map_lookup = db_map_lookup; 21853654Seric } 21953654Seric # endif 22053654Seric 22153654Seric # ifdef HASH_MAP 22253654Seric /* new database file access -- hash files */ 22353654Seric { 22456823Seric extern bool hash_map_init(); 22556823Seric extern char *db_map_lookup(); 22653654Seric 22753654Seric s = stab("hash", ST_MAPCLASS, ST_ENTER); 22853654Seric s->s_mapclass.map_init = hash_map_init; 22956823Seric s->s_mapclass.map_lookup = db_map_lookup; 23053654Seric } 23153654Seric # endif 23253654Seric 23357208Seric # ifdef NIS_MAP 23457208Seric /* NIS map access */ 23557208Seric { 23657208Seric extern bool nis_map_init(); 23757208Seric extern char *nis_map_lookup(); 23857208Seric 23957208Seric s = stab("nis", ST_MAPCLASS, ST_ENTER); 24057208Seric s->s_mapclass.map_init = nis_map_init; 24157208Seric s->s_mapclass.map_lookup = nis_map_lookup; 24257208Seric } 24357208Seric # endif 24457208Seric 24553654Seric # ifdef USERDB_MAP 24653654Seric /* user database */ 24753654Seric { 24856836Seric extern bool udb_map_init(); 24953654Seric extern char *udb_map_lookup(); 25053654Seric 25153654Seric s = stab("udb", ST_MAPCLASS, ST_ENTER); 25253654Seric s->s_mapclass.map_init = udb_map_init; 25353654Seric s->s_mapclass.map_lookup = udb_map_lookup; 25453654Seric } 25553654Seric # endif 25653654Seric } 25753654Seric /* 25856836Seric ** HOST_MAP_INIT -- initialize host class structures 25956836Seric */ 26056836Seric 26156836Seric bool 26256836Seric host_map_init(map, mapname, args) 26356836Seric MAP *map; 26456836Seric char *mapname; 26556836Seric char *args; 26656836Seric { 26756836Seric register char *p = args; 26856836Seric 26956836Seric for (;;) 27056836Seric { 27156836Seric while (isspace(*p)) 27256836Seric p++; 27356836Seric if (*p != '-') 27456836Seric break; 27556836Seric switch (*++p) 27656836Seric { 27756836Seric case 'a': 27856836Seric map->map_app = ++p; 27956836Seric break; 28056836Seric } 28156836Seric while (*p != '\0' && !isspace(*p)) 28256836Seric p++; 28356836Seric if (*p != '\0') 28456836Seric *p++ = '\0'; 28556836Seric } 28656836Seric if (map->map_app != NULL) 28756836Seric map->map_app = newstr(map->map_app); 28856836Seric return TRUE; 28956836Seric } 29057402Seric /* 29157402Seric ** SETUPMAILERS -- initialize default mailers 29257402Seric */ 29356836Seric 29457402Seric setupmailers() 29557402Seric { 29657402Seric char buf[100]; 29757402Seric 29857403Seric strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); 29957403Seric makemailer(buf); 30057403Seric 30157402Seric strcpy(buf, "*file*, P=/dev/null, F=lsDEu, A=FILE"); 30257402Seric makemailer(buf); 30357402Seric 30457402Seric strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 30557402Seric makemailer(buf); 30657402Seric } 30756836Seric /* 3084326Seric ** GETRUID -- get real user id (V7) 3094326Seric */ 3104326Seric 3114326Seric getruid() 3124326Seric { 3139274Seric if (OpMode == MD_DAEMON) 3144536Seric return (RealUid); 3154536Seric else 3164536Seric return (getuid()); 3174326Seric } 3184326Seric 3194326Seric 3204326Seric /* 3214326Seric ** GETRGID -- get real group id (V7). 3224326Seric */ 3234326Seric 3244326Seric getrgid() 3254326Seric { 3269274Seric if (OpMode == MD_DAEMON) 3274536Seric return (RealGid); 3284536Seric else 3294536Seric return (getgid()); 3304326Seric } 33153654Seric /* 3329369Seric ** USERNAME -- return the user id of the logged in user. 3339369Seric ** 3349369Seric ** Parameters: 3359369Seric ** none. 3369369Seric ** 3379369Seric ** Returns: 3389369Seric ** The login name of the logged in user. 3399369Seric ** 3409369Seric ** Side Effects: 3419369Seric ** none. 3429369Seric ** 3439369Seric ** Notes: 3449369Seric ** The return value is statically allocated. 3459369Seric */ 3469369Seric 3479369Seric char * 3489369Seric username() 3499369Seric { 35017469Seric static char *myname = NULL; 3519369Seric extern char *getlogin(); 35219904Smiriam register struct passwd *pw; 3539369Seric 35417469Seric /* cache the result */ 35517469Seric if (myname == NULL) 35617469Seric { 35717469Seric myname = getlogin(); 35817469Seric if (myname == NULL || myname[0] == '\0') 35917469Seric { 36017469Seric 36117469Seric pw = getpwuid(getruid()); 36217469Seric if (pw != NULL) 36340993Sbostic myname = newstr(pw->pw_name); 36417469Seric } 36519904Smiriam else 36619904Smiriam { 36719873Smiriam 36840993Sbostic myname = newstr(myname); 36940993Sbostic if ((pw = getpwnam(myname)) == NULL || 37040993Sbostic getuid() != pw->pw_uid) 37119904Smiriam { 37219873Smiriam pw = getpwuid(getuid()); 37324945Seric if (pw != NULL) 37440993Sbostic myname = newstr(pw->pw_name); 37519873Smiriam } 37619873Smiriam } 37717469Seric if (myname == NULL || myname[0] == '\0') 37817469Seric { 37917469Seric syserr("Who are you?"); 38017469Seric myname = "postmaster"; 38117469Seric } 38217469Seric } 38317469Seric 38417469Seric return (myname); 3859369Seric } 3869369Seric /* 3874190Seric ** TTYPATH -- Get the path of the user's tty 388294Seric ** 389294Seric ** Returns the pathname of the user's tty. Returns NULL if 390294Seric ** the user is not logged in or if s/he has write permission 391294Seric ** denied. 392294Seric ** 393294Seric ** Parameters: 394294Seric ** none 395294Seric ** 396294Seric ** Returns: 397294Seric ** pathname of the user's tty. 398294Seric ** NULL if not logged in or write permission denied. 399294Seric ** 400294Seric ** Side Effects: 401294Seric ** none. 402294Seric ** 403294Seric ** WARNING: 404294Seric ** Return value is in a local buffer. 405294Seric ** 406294Seric ** Called By: 407294Seric ** savemail 408294Seric */ 409294Seric 410294Seric # include <sys/stat.h> 411294Seric 412294Seric char * 413294Seric ttypath() 414294Seric { 415294Seric struct stat stbuf; 416294Seric register char *pathn; 417294Seric extern char *ttyname(); 4184081Seric extern char *getlogin(); 419294Seric 420294Seric /* compute the pathname of the controlling tty */ 4219369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4229369Seric (pathn = ttyname(0)) == NULL) 423294Seric { 424294Seric errno = 0; 425294Seric return (NULL); 426294Seric } 427294Seric 428294Seric /* see if we have write permission */ 4292967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 430294Seric { 431294Seric errno = 0; 432294Seric return (NULL); 433294Seric } 434294Seric 435294Seric /* see if the user is logged in */ 436294Seric if (getlogin() == NULL) 437294Seric return (NULL); 438294Seric 439294Seric /* looks good */ 440294Seric return (pathn); 441294Seric } 4422967Seric /* 4432967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4442967Seric ** 4452967Seric ** This routine can be supplied on a per-installation basis 4462967Seric ** to determine whether a person is allowed to send a message. 4472967Seric ** This allows restriction of certain types of internet 4482967Seric ** forwarding or registration of users. 4492967Seric ** 4502967Seric ** If the hosts are found to be incompatible, an error 45157454Seric ** message should be given using "usrerr" and 0 should 4522967Seric ** be returned. 4532967Seric ** 4544288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4554288Seric ** function; this should be done on huge messages. 4564288Seric ** 4572967Seric ** Parameters: 4582967Seric ** to -- the person being sent to. 4592967Seric ** 4602967Seric ** Returns: 46157459Seric ** an exit status 4622967Seric ** 4632967Seric ** Side Effects: 4642967Seric ** none (unless you include the usrerr stuff) 4652967Seric */ 4662967Seric 46755012Seric checkcompat(to, e) 4682967Seric register ADDRESS *to; 46955012Seric register ENVELOPE *e; 4702967Seric { 47112133Seric # ifdef lint 47212133Seric if (to == NULL) 47312133Seric to++; 47412133Seric # endif lint 47510698Seric # ifdef EXAMPLE_CODE 47610698Seric /* this code is intended as an example only */ 4774437Seric register STAB *s; 4784437Seric 4794437Seric s = stab("arpa", ST_MAILER, ST_FIND); 48055012Seric if (s != NULL && e->e_from.q_mailer != LocalMailer && 4819369Seric to->q_mailer == s->s_mailer) 4824437Seric { 4834437Seric usrerr("No ARPA mail through this machine: see your system administration"); 48410698Seric /* NoReturn = TRUE; to supress return copy */ 48557459Seric return (EX_UNAVAILABLE); 4864437Seric } 48756795Seric # endif /* EXAMPLE_CODE */ 48857459Seric return (EX_OK); 4892967Seric } 4909369Seric /* 4919369Seric ** HOLDSIGS -- arrange to hold all signals 4929369Seric ** 4939369Seric ** Parameters: 4949369Seric ** none. 4959369Seric ** 4969369Seric ** Returns: 4979369Seric ** none. 4989369Seric ** 4999369Seric ** Side Effects: 5009369Seric ** Arranges that signals are held. 5019369Seric */ 5029369Seric 5039369Seric holdsigs() 5049369Seric { 5059369Seric } 5069369Seric /* 5079369Seric ** RLSESIGS -- arrange to release all signals 5089369Seric ** 5099369Seric ** This undoes the effect of holdsigs. 5109369Seric ** 5119369Seric ** Parameters: 5129369Seric ** none. 5139369Seric ** 5149369Seric ** Returns: 5159369Seric ** none. 5169369Seric ** 5179369Seric ** Side Effects: 5189369Seric ** Arranges that signals are released. 5199369Seric */ 5209369Seric 5219369Seric rlsesigs() 5229369Seric { 5239369Seric } 52414872Seric /* 52514872Seric ** GETLA -- get the current load average 52614872Seric ** 52714881Seric ** This code stolen from la.c. 52814881Seric ** 52914872Seric ** Parameters: 53014872Seric ** none. 53114872Seric ** 53214872Seric ** Returns: 53314872Seric ** The current load average as an integer. 53414872Seric ** 53514872Seric ** Side Effects: 53614872Seric ** none. 53714872Seric */ 53814872Seric 53951920Seric /* try to guess what style of load average we have */ 54051920Seric #define LA_ZERO 1 /* always return load average as zero */ 54151920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 54251920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 54351920Seric #define LA_SUBR 4 /* call getloadavg */ 54414872Seric 54551920Seric #ifndef LA_TYPE 54651920Seric # if defined(sun) 54751920Seric # define LA_TYPE LA_INT 54851920Seric # endif 549*57977Seric # if defined(mips) || defined(__alpha) 550*57977Seric /* Ultrix or OSF/1 or RISC/os */ 55151920Seric # define LA_TYPE LA_INT 55251920Seric # define LA_AVENRUN "avenrun" 55351920Seric # endif 55451920Seric # if defined(hpux) 55551920Seric # define LA_TYPE LA_FLOAT 55651920Seric # endif 55751920Seric 55851920Seric # ifndef LA_TYPE 55957736Seric # if defined(SYSTEM5) 56057736Seric # define LA_TYPE LA_INT 56157736Seric # define LA_AVENRUN "avenrun" 56257736Seric # else 56357736Seric # if defined(BSD) 56457736Seric # define LA_TYPE LA_SUBR 56557736Seric # else 56657736Seric # define LA_TYPE LA_ZERO 56757736Seric # endif 56857736Seric # endif 56951920Seric # endif 57051920Seric #endif 57151920Seric 57251920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 57351920Seric 57414872Seric #include <nlist.h> 57551920Seric #include <fcntl.h> 57614872Seric 57751920Seric #ifndef LA_AVENRUN 57851920Seric #define LA_AVENRUN "_avenrun" 57951920Seric #endif 58051920Seric 58151920Seric /* _PATH_UNIX should be defined in <paths.h> */ 58251920Seric #ifndef _PATH_UNIX 58351920Seric # if defined(hpux) 58451920Seric # define _PATH_UNIX "/hp-ux" 58551920Seric # endif 58651920Seric # if defined(mips) && !defined(ultrix) 58751920Seric /* powerful RISC/os */ 58851920Seric # define _PATH_UNIX "/unix" 58951920Seric # endif 59057736Seric # if defined(SYSTEM5) 591*57977Seric # ifndef _PATH_UNIX 592*57977Seric # define _PATH_UNIX "/unix" 593*57977Seric # endif 59457736Seric # endif 59551920Seric # ifndef _PATH_UNIX 59651920Seric # define _PATH_UNIX "/vmunix" 59751920Seric # endif 59851920Seric #endif 59951920Seric 60014872Seric struct nlist Nl[] = 60114872Seric { 60251920Seric { LA_AVENRUN }, 60314872Seric #define X_AVENRUN 0 60414872Seric { 0 }, 60514872Seric }; 60614872Seric 60757736Seric #if defined(unixpc) 60857736Seric # define FSHIFT 5 60957736Seric #endif 61057736Seric 611*57977Seric #if defined(__alpha) 612*57977Seric # define FSHIFT 10 613*57977Seric #endif 614*57977Seric 61551920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 61651920Seric # define FSHIFT 8 61757736Seric #endif 61857736Seric #if (LA_TYPE == LA_INT) && !defined(FSCALE) 61951920Seric # define FSCALE (1 << FSHIFT) 62051920Seric #endif 62140930Srick 62214872Seric getla() 62314872Seric { 62414872Seric static int kmem = -1; 62551920Seric #if LA_TYPE == LA_INT 62624943Seric long avenrun[3]; 62751920Seric #else 62851920Seric double avenrun[3]; 62951920Seric #endif 63025615Seric extern off_t lseek(); 63157736Seric extern char *errstring(); 63257736Seric extern int errno; 63314872Seric 63414872Seric if (kmem < 0) 63514872Seric { 63624945Seric kmem = open("/dev/kmem", 0, 0); 63714872Seric if (kmem < 0) 63857736Seric { 63957736Seric if (tTd(3, 1)) 64057736Seric printf("getla: open(/dev/kmem): %s\n", 64157736Seric errstring(errno)); 64214872Seric return (-1); 64357736Seric } 64451920Seric (void) fcntl(kmem, F_SETFD, 1); 64557736Seric if (nlist(_PATH_UNIX, Nl) < 0) 64657736Seric { 64757736Seric if (tTd(3, 1)) 64857736Seric printf("getla: nlist(%s): %s\n", _PATH_UNIX, 64957736Seric errstring(errno)); 65014872Seric return (-1); 65157736Seric } 65214872Seric } 65357736Seric if (tTd(3, 20)) 65457736Seric printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); 65524945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 65623118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 65719967Seric { 65819967Seric /* thank you Ian */ 65957736Seric if (tTd(3, 1)) 66057736Seric printf("getla: lseek or read: %s\n", errstring(errno)); 66119967Seric return (-1); 66219967Seric } 66351920Seric #if LA_TYPE == LA_INT 66457736Seric if (tTd(3, 5)) 66557736Seric { 66657736Seric printf("getla: avenrun = %d", avenrun[0]); 66757736Seric if (tTd(3, 15)) 66857736Seric printf(", %d, %d", avenrun[1], avenrun[2]); 66957736Seric printf("\n"); 67057736Seric } 67157736Seric if (tTd(3, 1)) 67257736Seric printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 67324943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 67451920Seric #else 67557736Seric if (tTd(3, 5)) 67657736Seric { 67757736Seric printf("getla: avenrun = %g", avenrun[0]); 67857736Seric if (tTd(3, 15)) 67957736Seric printf(", %g, %g", avenrun[1], avenrun[2]); 68057736Seric printf("\n"); 68157736Seric } 68257736Seric if (tTd(3, 1)) 68357736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 68451920Seric return ((int) (avenrun[0] + 0.5)); 68551920Seric #endif 68614872Seric } 68714872Seric 68851773Seric #else 68951920Seric #if LA_TYPE == LA_SUBR 69051773Seric 69151773Seric getla() 69251773Seric { 69351920Seric double avenrun[3]; 69451920Seric 69551920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 69657736Seric { 69757736Seric if (tTd(3, 1)) 69857736Seric perror("getla: getloadavg failed:"); 69951920Seric return (-1); 70057736Seric } 70157736Seric if (tTd(3, 1)) 70257736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 70351920Seric return ((int) (avenrun[0] + 0.5)); 70451773Seric } 70551773Seric 70651773Seric #else 70751773Seric 70851773Seric getla() 70951773Seric { 71057736Seric if (tTd(3, 1)) 71157736Seric printf("getla: ZERO\n"); 71251920Seric return (0); 71351773Seric } 71451773Seric 71551773Seric #endif 71651773Seric #endif 71724943Seric /* 71824943Seric ** SHOULDQUEUE -- should this message be queued or sent? 71924943Seric ** 72024943Seric ** Compares the message cost to the load average to decide. 72124943Seric ** 72224943Seric ** Parameters: 72324943Seric ** pri -- the priority of the message in question. 72457438Seric ** ctime -- the message creation time. 72524943Seric ** 72624943Seric ** Returns: 72724943Seric ** TRUE -- if this message should be queued up for the 72824943Seric ** time being. 72924943Seric ** FALSE -- if the load is low enough to send this message. 73024943Seric ** 73124943Seric ** Side Effects: 73224943Seric ** none. 73324943Seric */ 73424943Seric 73524943Seric bool 73657438Seric shouldqueue(pri, ctime) 73724943Seric long pri; 73857438Seric time_t ctime; 73924943Seric { 74051920Seric if (CurrentLA < QueueLA) 74124943Seric return (FALSE); 74251920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 74324943Seric } 74424943Seric /* 74553037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 74653037Seric ** 74753037Seric ** Parameters: 74853037Seric ** none. 74953037Seric ** 75053037Seric ** Returns: 75153037Seric ** TRUE if incoming SMTP connections should be refused 75253037Seric ** (for now). 75353037Seric ** FALSE if we should accept new work. 75453037Seric ** 75553037Seric ** Side Effects: 75653037Seric ** none. 75753037Seric */ 75853037Seric 75953037Seric bool 76053037Seric refuseconnections() 76153037Seric { 76253037Seric /* this is probably too simplistic */ 76353037Seric return (CurrentLA > RefuseLA); 76453037Seric } 76553037Seric /* 76624943Seric ** SETPROCTITLE -- set process title for ps 76724943Seric ** 76824943Seric ** Parameters: 76924943Seric ** fmt -- a printf style format string. 77024943Seric ** a, b, c -- possible parameters to fmt. 77124943Seric ** 77224943Seric ** Returns: 77324943Seric ** none. 77424943Seric ** 77524943Seric ** Side Effects: 77624943Seric ** Clobbers argv of our main procedure so ps(1) will 77724943Seric ** display the title. 77824943Seric */ 77924943Seric 78024943Seric /*VARARGS1*/ 78157642Seric #ifdef __STDC__ 78257642Seric setproctitle(char *fmt, ...) 78357642Seric #else 78457642Seric setproctitle(fmt, va_alist) 78524943Seric char *fmt; 78657642Seric va_dcl 78757642Seric #endif 78824943Seric { 78924943Seric # ifdef SETPROCTITLE 79024943Seric register char *p; 79125049Seric register int i; 79256852Seric char buf[MAXLINE]; 79356852Seric VA_LOCAL_DECL 79424943Seric extern char **Argv; 79524943Seric extern char *LastArgv; 79624943Seric 79754996Seric p = buf; 79824943Seric 79954996Seric /* print sendmail: heading for grep */ 80054996Seric (void) strcpy(p, "sendmail: "); 80154996Seric p += strlen(p); 80224943Seric 80354996Seric /* print the argument string */ 80456852Seric VA_START(fmt); 80556852Seric (void) vsprintf(p, fmt, ap); 80656852Seric VA_END; 80754996Seric 80825049Seric i = strlen(buf); 80954996Seric if (i > LastArgv - Argv[0] - 2) 81025049Seric { 81154996Seric i = LastArgv - Argv[0] - 2; 81225049Seric buf[i] = '\0'; 81325049Seric } 81454996Seric (void) strcpy(Argv[0], buf); 81554997Seric p = &Argv[0][i]; 81624943Seric while (p < LastArgv) 81724943Seric *p++ = ' '; 81856795Seric # endif /* SETPROCTITLE */ 81924943Seric } 82025698Seric /* 82125698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 82225698Seric ** 82325698Seric ** Parameters: 82425698Seric ** none. 82525698Seric ** 82625698Seric ** Returns: 82725698Seric ** none. 82825698Seric ** 82925698Seric ** Side Effects: 83025698Seric ** Picks up extant zombies. 83125698Seric */ 83225698Seric 83325698Seric # include <sys/wait.h> 83425698Seric 83546928Sbostic void 83625698Seric reapchild() 83725698Seric { 83825698Seric # ifdef WNOHANG 83925698Seric union wait status; 84025698Seric 84146928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 84225698Seric continue; 84356795Seric # else /* WNOHANG */ 84425698Seric auto int status; 84525698Seric 84646928Sbostic while (wait((int *)&status) > 0) 84725698Seric continue; 84856795Seric # endif /* WNOHANG */ 84925698Seric } 85055418Seric /* 85155418Seric ** UNSETENV -- remove a variable from the environment 85255418Seric ** 85355418Seric ** Not needed on newer systems. 85455418Seric ** 85555418Seric ** Parameters: 85655418Seric ** name -- the string name of the environment variable to be 85755418Seric ** deleted from the current environment. 85855418Seric ** 85955418Seric ** Returns: 86055418Seric ** none. 86155418Seric ** 86255418Seric ** Globals: 86355418Seric ** environ -- a pointer to the current environment. 86455418Seric ** 86555418Seric ** Side Effects: 86655418Seric ** Modifies environ. 86755418Seric */ 86855418Seric 86955418Seric #ifdef UNSETENV 87055418Seric 87155418Seric void 87255418Seric unsetenv(name) 87355418Seric char *name; 87455418Seric { 87555418Seric extern char **environ; 87655418Seric register char **pp; 87755418Seric int len = strlen(name); 87855418Seric 87955418Seric for (pp = environ; *pp != NULL; pp++) 88055418Seric { 88155418Seric if (strncmp(name, *pp, len) == 0 && 88255418Seric ((*pp)[len] == '=' || (*pp)[len] == '\0')) 88355418Seric break; 88455418Seric } 88555418Seric 88655418Seric for (; *pp != NULL; pp++) 88755418Seric *pp = pp[1]; 88855418Seric } 88955418Seric 89055418Seric #endif /* UNSETENV */ 89156215Seric /* 89256215Seric ** GETDTABLESIZE -- return number of file descriptors 89356215Seric ** 89456215Seric ** Only on non-BSD systems 89556215Seric ** 89656215Seric ** Parameters: 89756215Seric ** none 89856215Seric ** 89956215Seric ** Returns: 90056215Seric ** size of file descriptor table 90156215Seric ** 90256215Seric ** Side Effects: 90356215Seric ** none 90456215Seric */ 90556215Seric 90656215Seric #ifdef SYSTEM5 90756215Seric 90856215Seric int 90956215Seric getdtablesize() 91056215Seric { 91156215Seric return NOFILE; 91256215Seric } 91356215Seric 91456215Seric #endif 91557631Seric /* 91657631Seric ** UNAME -- get the UUCP name of this system. 91757631Seric */ 91857631Seric 91957943Seric #ifndef HASUNAME 92057631Seric 92157631Seric int 92257631Seric uname(name) 92357631Seric struct utsname *name; 92457631Seric { 92557631Seric FILE *file; 92657631Seric char *n; 92757631Seric 92857631Seric name->nodename[0] = '\0'; 92957631Seric 93057661Seric /* try /etc/whoami -- one line with the node name */ 93157631Seric if ((file = fopen("/etc/whoami", "r")) != NULL) 93257631Seric { 93357661Seric (void) fgets(name->nodename, NODE_LENGTH + 1, file); 93457631Seric (void) fclose(file); 93557661Seric n = strchr(name->nodename, '\n'); 93657631Seric if (n != NULL) 93757631Seric *n = '\0'; 93857631Seric if (name->nodename[0] != '\0') 93957631Seric return (0); 94057631Seric } 94157631Seric 94257661Seric /* try /usr/include/whoami.h -- has a #define somewhere */ 94357631Seric if ((file = fopen("/usr/include/whoami.h", "r")) != NULL) 94457631Seric { 94557631Seric char buf[MAXLINE]; 94657631Seric 94757631Seric while (fgets(buf, MAXLINE, file) != NULL) 94857631Seric if (sscanf(buf, "#define sysname \"%*[^\"]\"", 94957631Seric NODE_LENGTH, name->nodename) > 0) 95057631Seric break; 95157631Seric (void) fclose(file); 95257631Seric if (name->nodename[0] != '\0') 95357631Seric return (0); 95457631Seric } 95557631Seric 95657631Seric #ifdef TRUST_POPEN 95757631Seric /* 95857631Seric ** Popen is known to have security holes. 95957631Seric */ 96057631Seric 96157661Seric /* try uuname -l to return local name */ 96257631Seric if ((file = popen("uuname -l", "r")) != NULL) 96357631Seric { 96457661Seric (void) fgets(name, NODE_LENGTH + 1, file); 96557631Seric (void) pclose(file); 96657661Seric n = strchr(name, '\n'); 96757631Seric if (n != NULL) 96857631Seric *n = '\0'; 96957661Seric if (name->nodename[0] != '\0') 97057631Seric return (0); 97157631Seric } 97257631Seric #endif 97357631Seric 97457631Seric return (-1); 97557631Seric } 97657943Seric #endif /* HASUNAME */ 977