122698Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 362522Sbostic * Copyright (c) 1988, 1993 462522Sbostic * The Regents of the University of California. All rights reserved. 533728Sbostic * 642825Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822698Sdist 922698Sdist #ifndef lint 10*63834Seric static char sccsid[] = "@(#)conf.c 8.4 (Berkeley) 07/16/93"; 1133728Sbostic #endif /* not lint */ 1222698Sdist 1314881Seric # include <sys/ioctl.h> 1458082Seric # include <sys/param.h> 1558153Seric # include <signal.h> 1636928Sbostic # include <pwd.h> 173309Seric # include "sendmail.h" 1840980Sbostic # include "pathnames.h" 19404Seric 20294Seric /* 213309Seric ** CONF.C -- Sendmail Configuration Tables. 22294Seric ** 23294Seric ** Defines the configuration of this installation. 24294Seric ** 251388Seric ** Configuration Variables: 262897Seric ** HdrInfo -- a table describing well-known header fields. 272897Seric ** Each entry has the field name and some flags, 284147Seric ** which are described in sendmail.h. 294093Seric ** 304093Seric ** Notes: 314093Seric ** I have tried to put almost all the reasonable 324093Seric ** configuration information into the configuration 334093Seric ** file read at runtime. My intent is that anything 344093Seric ** here is a function of the version of UNIX you 354093Seric ** are running, or is really static -- for example 364093Seric ** the headers are a superset of widely used 374093Seric ** protocols. If you find yourself playing with 384093Seric ** this file too much, you may be making a mistake! 39294Seric */ 40294Seric 41294Seric 42294Seric 43294Seric 444437Seric /* 452897Seric ** Header info table 463057Seric ** Final (null) entry contains the flags used for any other field. 474147Seric ** 484147Seric ** Not all of these are actually handled specially by sendmail 494147Seric ** at this time. They are included as placeholders, to let 504147Seric ** you know that "someday" I intend to have sendmail do 514147Seric ** something with them. 522897Seric */ 532897Seric 542897Seric struct hdrinfo HdrInfo[] = 552897Seric { 568060Seric /* originator fields, most to least significant */ 5711417Seric "resent-sender", H_FROM|H_RESENT, 5811417Seric "resent-from", H_FROM|H_RESENT, 5925686Seric "resent-reply-to", H_FROM|H_RESENT, 609055Seric "sender", H_FROM, 619055Seric "from", H_FROM, 6225686Seric "reply-to", H_FROM, 639055Seric "full-name", H_ACHECK, 6457359Seric "return-receipt-to", H_FROM /* |H_RECEIPTTO */, 6557359Seric "errors-to", H_FROM|H_ERRORSTO, 6658796Seric 678060Seric /* destination fields */ 689055Seric "to", H_RCPT, 6911417Seric "resent-to", H_RCPT|H_RESENT, 709055Seric "cc", H_RCPT, 7111417Seric "resent-cc", H_RCPT|H_RESENT, 729055Seric "bcc", H_RCPT|H_ACHECK, 7311417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 7456215Seric "apparently-to", H_RCPT, 7558796Seric 768060Seric /* message identification and control */ 7711417Seric "message-id", 0, 7811417Seric "resent-message-id", H_RESENT, 799055Seric "message", H_EOH, 809055Seric "text", H_EOH, 8158796Seric 8211417Seric /* date fields */ 8311417Seric "date", 0, 8411417Seric "resent-date", H_RESENT, 8558796Seric 868060Seric /* trace fields */ 879055Seric "received", H_TRACE|H_FORCE, 8859318Seric "x400-received", H_TRACE|H_FORCE, 899055Seric "via", H_TRACE|H_FORCE, 909055Seric "mail-from", H_TRACE|H_FORCE, 918060Seric 9258796Seric /* miscellaneous fields */ 9358796Seric "comments", H_FORCE, 9463753Seric "return-path", H_FORCE|H_ACHECK, 9558796Seric 969055Seric NULL, 0, 972897Seric }; 984166Seric 994166Seric 1004166Seric 1014282Seric /* 1024282Seric ** Location of system files/databases/etc. 1034282Seric */ 1044282Seric 10540980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 10640980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 10758082Seric char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */ 1089039Seric 1099064Seric 1109064Seric 1119039Seric /* 11258082Seric ** Privacy values 11358082Seric */ 11458082Seric 11558082Seric struct prival PrivacyValues[] = 11658082Seric { 11758082Seric "public", PRIV_PUBLIC, 11858082Seric "needmailhelo", PRIV_NEEDMAILHELO, 11958114Seric "needexpnhelo", PRIV_NEEDEXPNHELO, 12058082Seric "needvrfyhelo", PRIV_NEEDVRFYHELO, 12158082Seric "noexpn", PRIV_NOEXPN, 12258082Seric "novrfy", PRIV_NOVRFY, 12358249Seric "restrictmailq", PRIV_RESTRMAILQ, 12458789Seric "authwarnings", PRIV_AUTHWARNINGS, 12558082Seric "goaway", PRIV_GOAWAY, 12658789Seric NULL, 0, 12758082Seric }; 12858082Seric 12958082Seric 13058082Seric 13158082Seric /* 13224943Seric ** Miscellaneous stuff. 1339039Seric */ 1349039Seric 13524943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 13624943Seric /* 13724943Seric ** SETDEFAULTS -- set default values 13824943Seric ** 13924943Seric ** Because of the way freezing is done, these must be initialized 14024943Seric ** using direct code. 14124943Seric ** 14224943Seric ** Parameters: 14358734Seric ** e -- the default envelope. 14424943Seric ** 14524943Seric ** Returns: 14624943Seric ** none. 14724943Seric ** 14824943Seric ** Side Effects: 14924943Seric ** Initializes a bunch of global variables to their 15024943Seric ** default values. 15124943Seric */ 15224943Seric 15358737Seric #define DAYS * 24 * 60 * 60 15458737Seric 15558734Seric setdefaults(e) 15658734Seric register ENVELOPE *e; 15724943Seric { 15857438Seric SpaceSub = ' '; /* option B */ 15957438Seric QueueLA = 8; /* option x */ 16057438Seric RefuseLA = 12; /* option X */ 16157438Seric WkRecipFact = 30000L; /* option y */ 16257438Seric WkClassFact = 1800L; /* option z */ 16357438Seric WkTimeFact = 90000L; /* option Z */ 16457438Seric QueueFactor = WkRecipFact * 20; /* option q */ 16563787Seric FileMode = (RealUid != geteuid()) ? 0644 : 0600; 16657438Seric /* option F */ 16757438Seric DefUid = 1; /* option u */ 16857438Seric DefGid = 1; /* option g */ 16957438Seric CheckpointInterval = 10; /* option C */ 17057438Seric MaxHopCount = 25; /* option h */ 17158734Seric e->e_sendmode = SM_FORK; /* option d */ 17258734Seric e->e_errormode = EM_PRINT; /* option e */ 17359709Seric SevenBit = FALSE; /* option 7 */ 17457438Seric MaxMciCache = 1; /* option k */ 17557438Seric MciCacheTimeout = 300; /* option K */ 17657438Seric LogLevel = 9; /* option L */ 17758112Seric settimeouts(NULL); /* option r */ 17858737Seric TimeOuts.to_q_return = 5 DAYS; /* option T */ 17958737Seric TimeOuts.to_q_warning = 0; /* option T */ 18058853Seric PrivacyFlags = 0; /* option p */ 18140973Sbostic setdefuser(); 18253654Seric setupmaps(); 18357402Seric setupmailers(); 18424943Seric } 185294Seric 18640973Sbostic 1874326Seric /* 18840973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 18940973Sbostic */ 19040973Sbostic 19140973Sbostic setdefuser() 19240973Sbostic { 19340973Sbostic struct passwd *defpwent; 19457386Seric static char defuserbuf[40]; 19540973Sbostic 19657386Seric DefUser = defuserbuf; 19740973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 19857386Seric strcpy(defuserbuf, defpwent->pw_name); 19940973Sbostic else 20057386Seric strcpy(defuserbuf, "nobody"); 20140973Sbostic } 20253654Seric /* 20356836Seric ** HOST_MAP_INIT -- initialize host class structures 20456836Seric */ 20556836Seric 20656836Seric bool 20760219Seric host_map_init(map, args) 20856836Seric MAP *map; 20956836Seric char *args; 21056836Seric { 21156836Seric register char *p = args; 21256836Seric 21356836Seric for (;;) 21456836Seric { 21558050Seric while (isascii(*p) && isspace(*p)) 21656836Seric p++; 21756836Seric if (*p != '-') 21856836Seric break; 21956836Seric switch (*++p) 22056836Seric { 22156836Seric case 'a': 22256836Seric map->map_app = ++p; 22356836Seric break; 22456836Seric } 22558050Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 22656836Seric p++; 22756836Seric if (*p != '\0') 22856836Seric *p++ = '\0'; 22956836Seric } 23056836Seric if (map->map_app != NULL) 23156836Seric map->map_app = newstr(map->map_app); 23256836Seric return TRUE; 23356836Seric } 23457402Seric /* 23557402Seric ** SETUPMAILERS -- initialize default mailers 23657402Seric */ 23756836Seric 23857402Seric setupmailers() 23957402Seric { 24057402Seric char buf[100]; 24157402Seric 24257403Seric strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); 24357403Seric makemailer(buf); 24457403Seric 24559883Seric strcpy(buf, "*file*, P=/dev/null, F=lsDFMPEu, A=FILE"); 24657402Seric makemailer(buf); 24757402Seric 24857402Seric strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 24957402Seric makemailer(buf); 25057402Seric } 25156836Seric /* 25260207Seric ** SETUPMAPS -- set up map classes 25360207Seric */ 25460207Seric 25560207Seric #define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \ 25660207Seric { \ 25760207Seric extern bool parse __P((MAP *, char *)); \ 25860207Seric extern bool open __P((MAP *, int)); \ 25960207Seric extern void close __P((MAP *)); \ 26060207Seric extern char *lookup __P((MAP *, char *, char **, int *)); \ 26160207Seric extern void store __P((MAP *, char *, char *)); \ 26260207Seric s = stab(name, ST_MAPCLASS, ST_ENTER); \ 26360207Seric s->s_mapclass.map_cname = name; \ 26460207Seric s->s_mapclass.map_ext = ext; \ 26560207Seric s->s_mapclass.map_cflags = flags; \ 26660207Seric s->s_mapclass.map_parse = parse; \ 26760207Seric s->s_mapclass.map_open = open; \ 26860207Seric s->s_mapclass.map_close = close; \ 26960207Seric s->s_mapclass.map_lookup = lookup; \ 27060207Seric s->s_mapclass.map_store = store; \ 27160207Seric } 27260207Seric 27360207Seric setupmaps() 27460207Seric { 27560207Seric register STAB *s; 27660207Seric 27760207Seric #ifdef NEWDB 27860207Seric MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 27960207Seric map_parseargs, hash_map_open, db_map_close, 28060207Seric db_map_lookup, db_map_store); 28160207Seric MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 28260207Seric map_parseargs, bt_map_open, db_map_close, 28360207Seric db_map_lookup, db_map_store); 28460207Seric #endif 28560207Seric 28660207Seric #ifdef NDBM 28760207Seric MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE, 28860207Seric map_parseargs, ndbm_map_open, ndbm_map_close, 28960207Seric ndbm_map_lookup, ndbm_map_store); 29060207Seric #endif 29160207Seric 29260207Seric #ifdef NIS 29360207Seric MAPDEF("nis", NULL, MCF_ALIASOK, 29460207Seric map_parseargs, nis_map_open, nis_map_close, 29560207Seric nis_map_lookup, nis_map_store); 29660207Seric #endif 29760207Seric 29860207Seric MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY, 29960207Seric map_parseargs, stab_map_open, stab_map_close, 30060207Seric stab_map_lookup, stab_map_store); 30160207Seric 30260207Seric MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE, 30360207Seric map_parseargs, impl_map_open, impl_map_close, 30460207Seric impl_map_lookup, impl_map_store); 30560207Seric 30660207Seric /* host DNS lookup */ 30760207Seric MAPDEF("host", NULL, 0, 30860207Seric host_map_init, null_map_open, null_map_close, 30960207Seric host_map_lookup, null_map_store); 31060207Seric 31160207Seric /* dequote map */ 31260207Seric MAPDEF("dequote", NULL, 0, 31360207Seric dequote_init, null_map_open, null_map_close, 31460207Seric dequote_map, null_map_store); 31560207Seric 31660207Seric #if 0 31760207Seric # ifdef USERDB 31860207Seric /* user database */ 31960207Seric MAPDEF("udb", ".db", 0, 32060207Seric udb_map_parse, null_map_open, null_map_close, 32160207Seric udb_map_lookup, null_map_store); 32260207Seric # endif 32360207Seric #endif 32460207Seric } 32560207Seric 32660207Seric #undef MAPDEF 32760207Seric /* 3289369Seric ** USERNAME -- return the user id of the logged in user. 3299369Seric ** 3309369Seric ** Parameters: 3319369Seric ** none. 3329369Seric ** 3339369Seric ** Returns: 3349369Seric ** The login name of the logged in user. 3359369Seric ** 3369369Seric ** Side Effects: 3379369Seric ** none. 3389369Seric ** 3399369Seric ** Notes: 3409369Seric ** The return value is statically allocated. 3419369Seric */ 3429369Seric 3439369Seric char * 3449369Seric username() 3459369Seric { 34617469Seric static char *myname = NULL; 3479369Seric extern char *getlogin(); 34819904Smiriam register struct passwd *pw; 3499369Seric 35017469Seric /* cache the result */ 35117469Seric if (myname == NULL) 35217469Seric { 35317469Seric myname = getlogin(); 35417469Seric if (myname == NULL || myname[0] == '\0') 35517469Seric { 35663787Seric pw = getpwuid(RealUid); 35717469Seric if (pw != NULL) 35840993Sbostic myname = newstr(pw->pw_name); 35917469Seric } 36019904Smiriam else 36119904Smiriam { 36263787Seric uid_t uid = RealUid; 36319873Smiriam 36440993Sbostic myname = newstr(myname); 36540993Sbostic if ((pw = getpwnam(myname)) == NULL || 36658736Seric (uid != 0 && uid != pw->pw_uid)) 36719904Smiriam { 36858736Seric pw = getpwuid(uid); 36924945Seric if (pw != NULL) 37040993Sbostic myname = newstr(pw->pw_name); 37119873Smiriam } 37219873Smiriam } 37317469Seric if (myname == NULL || myname[0] == '\0') 37417469Seric { 37558151Seric syserr("554 Who are you?"); 37617469Seric myname = "postmaster"; 37717469Seric } 37817469Seric } 37917469Seric 38017469Seric return (myname); 3819369Seric } 3829369Seric /* 3834190Seric ** TTYPATH -- Get the path of the user's tty 384294Seric ** 385294Seric ** Returns the pathname of the user's tty. Returns NULL if 386294Seric ** the user is not logged in or if s/he has write permission 387294Seric ** denied. 388294Seric ** 389294Seric ** Parameters: 390294Seric ** none 391294Seric ** 392294Seric ** Returns: 393294Seric ** pathname of the user's tty. 394294Seric ** NULL if not logged in or write permission denied. 395294Seric ** 396294Seric ** Side Effects: 397294Seric ** none. 398294Seric ** 399294Seric ** WARNING: 400294Seric ** Return value is in a local buffer. 401294Seric ** 402294Seric ** Called By: 403294Seric ** savemail 404294Seric */ 405294Seric 406294Seric char * 407294Seric ttypath() 408294Seric { 409294Seric struct stat stbuf; 410294Seric register char *pathn; 411294Seric extern char *ttyname(); 4124081Seric extern char *getlogin(); 413294Seric 414294Seric /* compute the pathname of the controlling tty */ 4159369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4169369Seric (pathn = ttyname(0)) == NULL) 417294Seric { 418294Seric errno = 0; 419294Seric return (NULL); 420294Seric } 421294Seric 422294Seric /* see if we have write permission */ 4232967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 424294Seric { 425294Seric errno = 0; 426294Seric return (NULL); 427294Seric } 428294Seric 429294Seric /* see if the user is logged in */ 430294Seric if (getlogin() == NULL) 431294Seric return (NULL); 432294Seric 433294Seric /* looks good */ 434294Seric return (pathn); 435294Seric } 4362967Seric /* 4372967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4382967Seric ** 4392967Seric ** This routine can be supplied on a per-installation basis 4402967Seric ** to determine whether a person is allowed to send a message. 4412967Seric ** This allows restriction of certain types of internet 4422967Seric ** forwarding or registration of users. 4432967Seric ** 4442967Seric ** If the hosts are found to be incompatible, an error 44557454Seric ** message should be given using "usrerr" and 0 should 4462967Seric ** be returned. 4472967Seric ** 4484288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4494288Seric ** function; this should be done on huge messages. 4504288Seric ** 4512967Seric ** Parameters: 4522967Seric ** to -- the person being sent to. 4532967Seric ** 4542967Seric ** Returns: 45557459Seric ** an exit status 4562967Seric ** 4572967Seric ** Side Effects: 4582967Seric ** none (unless you include the usrerr stuff) 4592967Seric */ 4602967Seric 46155012Seric checkcompat(to, e) 4622967Seric register ADDRESS *to; 46355012Seric register ENVELOPE *e; 4642967Seric { 46512133Seric # ifdef lint 46612133Seric if (to == NULL) 46712133Seric to++; 468*63834Seric # endif /* lint */ 46910698Seric # ifdef EXAMPLE_CODE 47010698Seric /* this code is intended as an example only */ 4714437Seric register STAB *s; 4724437Seric 4734437Seric s = stab("arpa", ST_MAILER, ST_FIND); 47455012Seric if (s != NULL && e->e_from.q_mailer != LocalMailer && 4759369Seric to->q_mailer == s->s_mailer) 4764437Seric { 47758151Seric usrerr("553 No ARPA mail through this machine: see your system administration"); 47810698Seric /* NoReturn = TRUE; to supress return copy */ 47957459Seric return (EX_UNAVAILABLE); 4804437Seric } 48156795Seric # endif /* EXAMPLE_CODE */ 48257459Seric return (EX_OK); 4832967Seric } 4849369Seric /* 4859369Seric ** HOLDSIGS -- arrange to hold all signals 4869369Seric ** 4879369Seric ** Parameters: 4889369Seric ** none. 4899369Seric ** 4909369Seric ** Returns: 4919369Seric ** none. 4929369Seric ** 4939369Seric ** Side Effects: 4949369Seric ** Arranges that signals are held. 4959369Seric */ 4969369Seric 4979369Seric holdsigs() 4989369Seric { 4999369Seric } 5009369Seric /* 5019369Seric ** RLSESIGS -- arrange to release all signals 5029369Seric ** 5039369Seric ** This undoes the effect of holdsigs. 5049369Seric ** 5059369Seric ** Parameters: 5069369Seric ** none. 5079369Seric ** 5089369Seric ** Returns: 5099369Seric ** none. 5109369Seric ** 5119369Seric ** Side Effects: 5129369Seric ** Arranges that signals are released. 5139369Seric */ 5149369Seric 5159369Seric rlsesigs() 5169369Seric { 5179369Seric } 51814872Seric /* 51914872Seric ** GETLA -- get the current load average 52014872Seric ** 52114881Seric ** This code stolen from la.c. 52214881Seric ** 52314872Seric ** Parameters: 52414872Seric ** none. 52514872Seric ** 52614872Seric ** Returns: 52714872Seric ** The current load average as an integer. 52814872Seric ** 52914872Seric ** Side Effects: 53014872Seric ** none. 53114872Seric */ 53214872Seric 53351920Seric /* try to guess what style of load average we have */ 53451920Seric #define LA_ZERO 1 /* always return load average as zero */ 53551920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 53651920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 53751920Seric #define LA_SUBR 4 /* call getloadavg */ 53814872Seric 53951920Seric #ifndef LA_TYPE 54060160Seric # if defined(sun) && !defined(BSD) 54151920Seric # define LA_TYPE LA_INT 54251920Seric # endif 54357977Seric # if defined(mips) || defined(__alpha) 54457977Seric /* Ultrix or OSF/1 or RISC/os */ 54551920Seric # define LA_TYPE LA_INT 54651920Seric # define LA_AVENRUN "avenrun" 54751920Seric # endif 54859430Seric # if defined(__hpux) 54951920Seric # define LA_TYPE LA_FLOAT 55059253Seric # define LA_AVENRUN "avenrun" 55151920Seric # endif 55263753Seric # if defined(__NeXT__) 55363753Seric # define LA_TYPE LA_ZERO 55463753Seric # endif 55551920Seric 55660219Seric /* now do the guesses based on general OS type */ 55751920Seric # ifndef LA_TYPE 55857736Seric # if defined(SYSTEM5) 55957736Seric # define LA_TYPE LA_INT 56057736Seric # define LA_AVENRUN "avenrun" 56157736Seric # else 56257736Seric # if defined(BSD) 56357736Seric # define LA_TYPE LA_SUBR 56457736Seric # else 56557736Seric # define LA_TYPE LA_ZERO 56657736Seric # endif 56757736Seric # endif 56851920Seric # endif 56951920Seric #endif 57051920Seric 57151920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 57251920Seric 57314872Seric #include <nlist.h> 57414872Seric 57551920Seric #ifndef LA_AVENRUN 57651920Seric #define LA_AVENRUN "_avenrun" 57751920Seric #endif 57851920Seric 57951920Seric /* _PATH_UNIX should be defined in <paths.h> */ 58051920Seric #ifndef _PATH_UNIX 58159430Seric # if defined(__hpux) 58251920Seric # define _PATH_UNIX "/hp-ux" 58351920Seric # endif 58451920Seric # if defined(mips) && !defined(ultrix) 58551920Seric /* powerful RISC/os */ 58651920Seric # define _PATH_UNIX "/unix" 58751920Seric # endif 58863753Seric # if defined(Solaris2) 58963753Seric /* Solaris 2 */ 59063753Seric # define _PATH_UNIX "/kernel/unix" 59163753Seric # endif 59257736Seric # if defined(SYSTEM5) 59357977Seric # ifndef _PATH_UNIX 59457977Seric # define _PATH_UNIX "/unix" 59557977Seric # endif 59657736Seric # endif 59751920Seric # ifndef _PATH_UNIX 59851920Seric # define _PATH_UNIX "/vmunix" 59951920Seric # endif 60051920Seric #endif 60151920Seric 60214872Seric struct nlist Nl[] = 60314872Seric { 60451920Seric { LA_AVENRUN }, 60514872Seric #define X_AVENRUN 0 60614872Seric { 0 }, 60714872Seric }; 60814872Seric 60960583Seric #ifndef FSHIFT 61060583Seric # if defined(unixpc) 61160583Seric # define FSHIFT 5 61260583Seric # endif 61357736Seric 61460583Seric # if defined(__alpha) 61560583Seric # define FSHIFT 10 61660583Seric # endif 61757977Seric 61860583Seric # if (LA_TYPE == LA_INT) 61951920Seric # define FSHIFT 8 62060583Seric # endif 62157736Seric #endif 62260583Seric 62357736Seric #if (LA_TYPE == LA_INT) && !defined(FSCALE) 62451920Seric # define FSCALE (1 << FSHIFT) 62551920Seric #endif 62640930Srick 62714872Seric getla() 62814872Seric { 62914872Seric static int kmem = -1; 63051920Seric #if LA_TYPE == LA_INT 63124943Seric long avenrun[3]; 63251920Seric #else 63351920Seric double avenrun[3]; 63451920Seric #endif 63525615Seric extern off_t lseek(); 63657736Seric extern int errno; 63714872Seric 63814872Seric if (kmem < 0) 63914872Seric { 64024945Seric kmem = open("/dev/kmem", 0, 0); 64114872Seric if (kmem < 0) 64257736Seric { 64357736Seric if (tTd(3, 1)) 64457736Seric printf("getla: open(/dev/kmem): %s\n", 64557736Seric errstring(errno)); 64614872Seric return (-1); 64757736Seric } 64851920Seric (void) fcntl(kmem, F_SETFD, 1); 64957736Seric if (nlist(_PATH_UNIX, Nl) < 0) 65057736Seric { 65157736Seric if (tTd(3, 1)) 65257736Seric printf("getla: nlist(%s): %s\n", _PATH_UNIX, 65357736Seric errstring(errno)); 65414872Seric return (-1); 65557736Seric } 65659253Seric if (Nl[X_AVENRUN].n_value == 0) 65759253Seric { 65859253Seric if (tTd(3, 1)) 65959253Seric printf("getla: nlist(%s, %s) ==> 0\n", 66059253Seric _PATH_UNIX, LA_AVENRUN); 66159253Seric return (-1); 66259253Seric } 66314872Seric } 66457736Seric if (tTd(3, 20)) 66557736Seric printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); 66624945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 66723118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 66819967Seric { 66919967Seric /* thank you Ian */ 67057736Seric if (tTd(3, 1)) 67157736Seric printf("getla: lseek or read: %s\n", errstring(errno)); 67219967Seric return (-1); 67319967Seric } 67451920Seric #if LA_TYPE == LA_INT 67557736Seric if (tTd(3, 5)) 67657736Seric { 67757736Seric printf("getla: avenrun = %d", avenrun[0]); 67857736Seric if (tTd(3, 15)) 67957736Seric printf(", %d, %d", avenrun[1], avenrun[2]); 68057736Seric printf("\n"); 68157736Seric } 68257736Seric if (tTd(3, 1)) 68357736Seric printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 68424943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 68551920Seric #else 68657736Seric if (tTd(3, 5)) 68757736Seric { 68857736Seric printf("getla: avenrun = %g", avenrun[0]); 68957736Seric if (tTd(3, 15)) 69057736Seric printf(", %g, %g", avenrun[1], avenrun[2]); 69157736Seric printf("\n"); 69257736Seric } 69357736Seric if (tTd(3, 1)) 69457736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 69551920Seric return ((int) (avenrun[0] + 0.5)); 69651920Seric #endif 69714872Seric } 69814872Seric 69951773Seric #else 70051920Seric #if LA_TYPE == LA_SUBR 70151773Seric 70251773Seric getla() 70351773Seric { 70451920Seric double avenrun[3]; 70551920Seric 70651920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 70757736Seric { 70857736Seric if (tTd(3, 1)) 70957736Seric perror("getla: getloadavg failed:"); 71051920Seric return (-1); 71157736Seric } 71257736Seric if (tTd(3, 1)) 71357736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 71451920Seric return ((int) (avenrun[0] + 0.5)); 71551773Seric } 71651773Seric 71751773Seric #else 71851773Seric 71951773Seric getla() 72051773Seric { 72157736Seric if (tTd(3, 1)) 72257736Seric printf("getla: ZERO\n"); 72351920Seric return (0); 72451773Seric } 72551773Seric 72651773Seric #endif 72751773Seric #endif 72824943Seric /* 72924943Seric ** SHOULDQUEUE -- should this message be queued or sent? 73024943Seric ** 73124943Seric ** Compares the message cost to the load average to decide. 73224943Seric ** 73324943Seric ** Parameters: 73424943Seric ** pri -- the priority of the message in question. 73557438Seric ** ctime -- the message creation time. 73624943Seric ** 73724943Seric ** Returns: 73824943Seric ** TRUE -- if this message should be queued up for the 73924943Seric ** time being. 74024943Seric ** FALSE -- if the load is low enough to send this message. 74124943Seric ** 74224943Seric ** Side Effects: 74324943Seric ** none. 74424943Seric */ 74524943Seric 74624943Seric bool 74757438Seric shouldqueue(pri, ctime) 74824943Seric long pri; 74957438Seric time_t ctime; 75024943Seric { 75151920Seric if (CurrentLA < QueueLA) 75224943Seric return (FALSE); 75358132Seric if (CurrentLA >= RefuseLA) 75458132Seric return (TRUE); 75551920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 75624943Seric } 75724943Seric /* 75853037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 75953037Seric ** 76053037Seric ** Parameters: 76153037Seric ** none. 76253037Seric ** 76353037Seric ** Returns: 76453037Seric ** TRUE if incoming SMTP connections should be refused 76553037Seric ** (for now). 76653037Seric ** FALSE if we should accept new work. 76753037Seric ** 76853037Seric ** Side Effects: 76953037Seric ** none. 77053037Seric */ 77153037Seric 77253037Seric bool 77353037Seric refuseconnections() 77453037Seric { 77559156Seric #ifdef XLA 77659156Seric if (!xla_smtp_ok()) 77759156Seric return TRUE; 77859156Seric #endif 77959156Seric 78053037Seric /* this is probably too simplistic */ 78158132Seric return (CurrentLA >= RefuseLA); 78253037Seric } 78353037Seric /* 78424943Seric ** SETPROCTITLE -- set process title for ps 78524943Seric ** 78624943Seric ** Parameters: 78758674Seric ** fmt -- a printf style format string. 78858674Seric ** a, b, c -- possible parameters to fmt. 78924943Seric ** 79024943Seric ** Returns: 79124943Seric ** none. 79224943Seric ** 79324943Seric ** Side Effects: 79424943Seric ** Clobbers argv of our main procedure so ps(1) will 79524943Seric ** display the title. 79624943Seric */ 79724943Seric 79858689Seric #ifdef SETPROCTITLE 79958689Seric # ifdef __hpux 80058689Seric # include <sys/pstat.h> 80158689Seric # endif 80259732Seric # ifdef BSD4_4 80359732Seric # include <machine/vmparam.h> 80459732Seric # include <sys/exec.h> 80559992Seric # ifdef PS_STRINGS 80659992Seric # define SETPROC_STATIC static 80759992Seric # endif 80859732Seric # endif 80959732Seric # ifndef SETPROC_STATIC 81059732Seric # define SETPROC_STATIC 81159732Seric # endif 81258689Seric #endif 81358689Seric 81424943Seric /*VARARGS1*/ 81557642Seric #ifdef __STDC__ 81657642Seric setproctitle(char *fmt, ...) 81757642Seric #else 81857642Seric setproctitle(fmt, va_alist) 81924943Seric char *fmt; 82057642Seric va_dcl 82157642Seric #endif 82224943Seric { 82324943Seric # ifdef SETPROCTITLE 82424943Seric register char *p; 82525049Seric register int i; 82659732Seric SETPROC_STATIC char buf[MAXLINE]; 82756852Seric VA_LOCAL_DECL 82858689Seric # ifdef __hpux 82958689Seric union pstun pst; 83058689Seric # endif 83124943Seric extern char **Argv; 83224943Seric extern char *LastArgv; 83324943Seric 83458674Seric p = buf; 83524943Seric 83658674Seric /* print sendmail: heading for grep */ 83758674Seric (void) strcpy(p, "sendmail: "); 83858674Seric p += strlen(p); 83924943Seric 84058674Seric /* print the argument string */ 84158674Seric VA_START(fmt); 84258674Seric (void) vsprintf(p, fmt, ap); 84356852Seric VA_END; 84454996Seric 84558674Seric i = strlen(buf); 84658689Seric 84758689Seric # ifdef __hpux 84858689Seric pst.pst_command = buf; 84958689Seric pstat(PSTAT_SETCMD, pst, i, 0, 0); 85058689Seric # else 85159992Seric # ifdef PS_STRINGS 85259732Seric PS_STRINGS->ps_nargvstr = 1; 85359732Seric PS_STRINGS->ps_argvstr = buf; 85459732Seric # else 85554996Seric if (i > LastArgv - Argv[0] - 2) 85625049Seric { 85754996Seric i = LastArgv - Argv[0] - 2; 85858674Seric buf[i] = '\0'; 85925049Seric } 86058674Seric (void) strcpy(Argv[0], buf); 86154997Seric p = &Argv[0][i]; 86224943Seric while (p < LastArgv) 86324943Seric *p++ = ' '; 86459732Seric # endif 86558689Seric # endif 86656795Seric # endif /* SETPROCTITLE */ 86724943Seric } 86825698Seric /* 86925698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 87025698Seric ** 87125698Seric ** Parameters: 87225698Seric ** none. 87325698Seric ** 87425698Seric ** Returns: 87525698Seric ** none. 87625698Seric ** 87725698Seric ** Side Effects: 87825698Seric ** Picks up extant zombies. 87925698Seric */ 88025698Seric 88125698Seric # include <sys/wait.h> 88225698Seric 88346928Sbostic void 88425698Seric reapchild() 88525698Seric { 88663753Seric # if defined(WIFEXITED) && !defined(__NeXT__) 88760219Seric auto int status; 88860560Seric int count; 88960560Seric int pid; 89060219Seric 89160560Seric count = 0; 89260560Seric while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 89360560Seric { 89460560Seric if (count++ > 1000) 89560560Seric { 89660560Seric syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x", 89760560Seric pid, status); 89860560Seric break; 89960560Seric } 90060560Seric } 90160219Seric # else 90225698Seric # ifdef WNOHANG 90325698Seric union wait status; 90425698Seric 90563753Seric while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 90625698Seric continue; 90756795Seric # else /* WNOHANG */ 90825698Seric auto int status; 90925698Seric 91060219Seric while (wait(&status) > 0) 91125698Seric continue; 91256795Seric # endif /* WNOHANG */ 91360219Seric # endif 91458061Seric # ifdef SYSTEM5 91558061Seric (void) signal(SIGCHLD, reapchild); 91658061Seric # endif 91725698Seric } 91855418Seric /* 91955418Seric ** UNSETENV -- remove a variable from the environment 92055418Seric ** 92155418Seric ** Not needed on newer systems. 92255418Seric ** 92355418Seric ** Parameters: 92455418Seric ** name -- the string name of the environment variable to be 92555418Seric ** deleted from the current environment. 92655418Seric ** 92755418Seric ** Returns: 92855418Seric ** none. 92955418Seric ** 93055418Seric ** Globals: 93155418Seric ** environ -- a pointer to the current environment. 93255418Seric ** 93355418Seric ** Side Effects: 93455418Seric ** Modifies environ. 93555418Seric */ 93655418Seric 93755418Seric #ifdef UNSETENV 93855418Seric 93955418Seric void 94055418Seric unsetenv(name) 94155418Seric char *name; 94255418Seric { 94355418Seric extern char **environ; 94455418Seric register char **pp; 94555418Seric int len = strlen(name); 94655418Seric 94755418Seric for (pp = environ; *pp != NULL; pp++) 94855418Seric { 94955418Seric if (strncmp(name, *pp, len) == 0 && 95055418Seric ((*pp)[len] == '=' || (*pp)[len] == '\0')) 95155418Seric break; 95255418Seric } 95355418Seric 95455418Seric for (; *pp != NULL; pp++) 95555418Seric *pp = pp[1]; 95655418Seric } 95755418Seric 95855418Seric #endif /* UNSETENV */ 95956215Seric /* 96056215Seric ** GETDTABLESIZE -- return number of file descriptors 96156215Seric ** 96256215Seric ** Only on non-BSD systems 96356215Seric ** 96456215Seric ** Parameters: 96556215Seric ** none 96656215Seric ** 96756215Seric ** Returns: 96856215Seric ** size of file descriptor table 96956215Seric ** 97056215Seric ** Side Effects: 97156215Seric ** none 97256215Seric */ 97356215Seric 97463787Seric #ifdef SOLARIS 97563787Seric # include <sys/resource.h> 97663787Seric #endif 97756215Seric 97856215Seric int 97963787Seric getdtsize() 98056215Seric { 98163787Seric #ifdef RLIMIT_NOFILE 98263787Seric struct rlimit rl; 98363787Seric 98463787Seric if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) 98563787Seric return rl.rlim_cur; 98663787Seric #endif 98763787Seric 98858689Seric # ifdef _SC_OPEN_MAX 98958689Seric return sysconf(_SC_OPEN_MAX); 99058689Seric # else 99163787Seric # ifdef HASGETDTABLESIZE 99263787Seric return getdtablesize(); 99363787Seric # else 99456215Seric return NOFILE; 99563787Seric # endif 99658689Seric # endif 99756215Seric } 99857631Seric /* 99957631Seric ** UNAME -- get the UUCP name of this system. 100057631Seric */ 100157631Seric 100257943Seric #ifndef HASUNAME 100357631Seric 100457631Seric int 100557631Seric uname(name) 100657631Seric struct utsname *name; 100757631Seric { 100857631Seric FILE *file; 100957631Seric char *n; 101057631Seric 101157631Seric name->nodename[0] = '\0'; 101257631Seric 101357661Seric /* try /etc/whoami -- one line with the node name */ 101457631Seric if ((file = fopen("/etc/whoami", "r")) != NULL) 101557631Seric { 101657661Seric (void) fgets(name->nodename, NODE_LENGTH + 1, file); 101757631Seric (void) fclose(file); 101857661Seric n = strchr(name->nodename, '\n'); 101957631Seric if (n != NULL) 102057631Seric *n = '\0'; 102157631Seric if (name->nodename[0] != '\0') 102257631Seric return (0); 102357631Seric } 102457631Seric 102557661Seric /* try /usr/include/whoami.h -- has a #define somewhere */ 102657631Seric if ((file = fopen("/usr/include/whoami.h", "r")) != NULL) 102757631Seric { 102857631Seric char buf[MAXLINE]; 102957631Seric 103057631Seric while (fgets(buf, MAXLINE, file) != NULL) 103157631Seric if (sscanf(buf, "#define sysname \"%*[^\"]\"", 103257631Seric NODE_LENGTH, name->nodename) > 0) 103357631Seric break; 103457631Seric (void) fclose(file); 103557631Seric if (name->nodename[0] != '\0') 103657631Seric return (0); 103757631Seric } 103857631Seric 103957631Seric #ifdef TRUST_POPEN 104057631Seric /* 104157631Seric ** Popen is known to have security holes. 104257631Seric */ 104357631Seric 104457661Seric /* try uuname -l to return local name */ 104557631Seric if ((file = popen("uuname -l", "r")) != NULL) 104657631Seric { 104757661Seric (void) fgets(name, NODE_LENGTH + 1, file); 104857631Seric (void) pclose(file); 104957661Seric n = strchr(name, '\n'); 105057631Seric if (n != NULL) 105157631Seric *n = '\0'; 105257661Seric if (name->nodename[0] != '\0') 105357631Seric return (0); 105457631Seric } 105557631Seric #endif 105657631Seric 105757631Seric return (-1); 105857631Seric } 105957943Seric #endif /* HASUNAME */ 106058068Seric /* 106158068Seric ** INITGROUPS -- initialize groups 106258068Seric ** 106358068Seric ** Stub implementation for System V style systems 106458068Seric */ 106558068Seric 106658068Seric #ifndef HASINITGROUPS 106759430Seric # if !defined(SYSTEM5) || defined(__hpux) 106858068Seric # define HASINITGROUPS 106958068Seric # endif 107058068Seric #endif 107158068Seric 107258068Seric #ifndef HASINITGROUPS 107358068Seric 107458068Seric initgroups(name, basegid) 107558068Seric char *name; 107658068Seric int basegid; 107758068Seric { 107858068Seric return 0; 107958068Seric } 108058068Seric 108158068Seric #endif 108258082Seric /* 108359289Seric ** SETSID -- set session id (for non-POSIX systems) 108459289Seric */ 108559289Seric 108659289Seric #ifndef HASSETSID 108759289Seric 108863753Seric pid_t 108963753Seric setsid __P ((void)) 109059289Seric { 109159289Seric # ifdef SYSTEM5 109263753Seric return setpgrp(); 109363753Seric # else 109463753Seric return 0; 109559289Seric # endif 109659289Seric } 109759289Seric 109859289Seric #endif 109959289Seric /* 110058082Seric ** ENOUGHSPACE -- check to see if there is enough free space on the queue fs 110158082Seric ** 110258082Seric ** Only implemented if you have statfs. 110358082Seric ** 110458082Seric ** Parameters: 110558333Seric ** msize -- the size to check against. If zero, we don't yet 110658333Seric ** know how big the message will be, so just check for 110758333Seric ** a "reasonable" amount. 110858082Seric ** 110958082Seric ** Returns: 111058082Seric ** TRUE if there is enough space. 111158082Seric ** FALSE otherwise. 111258082Seric */ 111358082Seric 111458082Seric #ifndef HASSTATFS 111558082Seric # if defined(BSD4_4) || defined(__osf__) 111658082Seric # define HASSTATFS 111758082Seric # endif 111858082Seric #endif 111958082Seric 112058082Seric #ifdef HASSTATFS 112158157Seric # undef HASUSTAT 112258157Seric #endif 112358157Seric 112458157Seric #if defined(HASUSTAT) 112558157Seric # include <ustat.h> 112658157Seric #endif 112758157Seric 112858157Seric #ifdef HASSTATFS 112958133Seric # if defined(sgi) || defined(apollo) 113058133Seric # include <sys/statfs.h> 113158133Seric # else 113260160Seric # if (defined(sun) && !defined(BSD)) || defined(__hpux) 113358133Seric # include <sys/vfs.h> 113458133Seric # else 113558157Seric # include <sys/mount.h> 113658133Seric # endif 113758133Seric # endif 113858082Seric #endif 113958082Seric 114058082Seric bool 114158333Seric enoughspace(msize) 114258333Seric long msize; 114358082Seric { 114458160Seric #if defined(HASSTATFS) || defined(HASUSTAT) 114558157Seric # if defined(HASUSTAT) 114658153Seric struct ustat fs; 114758153Seric struct stat statbuf; 114858366Seric # define FSBLOCKSIZE DEV_BSIZE 114958157Seric # define f_bavail f_tfree 115058157Seric # else 115158157Seric # if defined(ultrix) 115258157Seric struct fs_data fs; 115358157Seric # define f_bavail fd_bfreen 115458366Seric # define FSBLOCKSIZE fs.fd_bsize 115558153Seric # else 115658082Seric struct statfs fs; 115758366Seric # define FSBLOCKSIZE fs.f_bsize 115858153Seric # endif 115958133Seric # endif 116058082Seric extern int errno; 116158082Seric 116258333Seric if (MinBlocksFree <= 0 && msize <= 0) 116358082Seric { 116458082Seric if (tTd(4, 80)) 116558133Seric printf("enoughspace: no threshold\n"); 116658133Seric return TRUE; 116758133Seric } 116858333Seric 116958157Seric # if defined(HASUSTAT) 117058157Seric if (stat(QueueDir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) 117158157Seric # else 117258157Seric # if defined(sgi) || defined(apollo) 117358133Seric if (statfs(QueueDir, &fs, sizeof fs, 0) == 0) 117458157Seric # else 117558157Seric # if defined(ultrix) 117658133Seric if (statfs(QueueDir, &fs) > 0) 117758153Seric # else 117858133Seric if (statfs(QueueDir, &fs) == 0) 117958153Seric # endif 118058133Seric # endif 118158133Seric # endif 118258133Seric { 118358133Seric if (tTd(4, 80)) 118458333Seric printf("enoughspace: bavail=%ld, need=%ld\n", 118558333Seric fs.f_bavail, msize); 118658333Seric 118758333Seric /* convert msize to block count */ 118858366Seric msize = msize / FSBLOCKSIZE + 1; 118958333Seric if (MinBlocksFree >= 0) 119058333Seric msize += MinBlocksFree; 119158333Seric 119258333Seric if (fs.f_bavail < msize) 119358090Seric { 119458090Seric #ifdef LOG 119558090Seric if (LogLevel > 0) 119658090Seric syslog(LOG_ALERT, "%s: low on space (have %ld, need %ld)", 119758333Seric QueueDir, fs.f_bavail, msize); 119858090Seric #endif 119958082Seric return FALSE; 120058090Seric } 120158082Seric } 120258082Seric else if (tTd(4, 80)) 120358333Seric printf("enoughspace failure: min=%ld, need=%ld: %s\n", 120458333Seric MinBlocksFree, msize, errstring(errno)); 120558082Seric #endif 120658082Seric return TRUE; 120758082Seric } 120858542Seric /* 120958542Seric ** TRANSIENTERROR -- tell if an error code indicates a transient failure 121058542Seric ** 121158542Seric ** This looks at an errno value and tells if this is likely to 121258542Seric ** go away if retried later. 121358542Seric ** 121458542Seric ** Parameters: 121558542Seric ** err -- the errno code to classify. 121658542Seric ** 121758542Seric ** Returns: 121858542Seric ** TRUE if this is probably transient. 121958542Seric ** FALSE otherwise. 122058542Seric */ 122158542Seric 122258542Seric bool 122358542Seric transienterror(err) 122458542Seric int err; 122558542Seric { 122658542Seric switch (err) 122758542Seric { 122858542Seric case EIO: /* I/O error */ 122958542Seric case ENXIO: /* Device not configured */ 123058542Seric case EAGAIN: /* Resource temporarily unavailable */ 123158542Seric case ENOMEM: /* Cannot allocate memory */ 123258542Seric case ENODEV: /* Operation not supported by device */ 123358542Seric case ENFILE: /* Too many open files in system */ 123458542Seric case EMFILE: /* Too many open files */ 123558542Seric case ENOSPC: /* No space left on device */ 123658542Seric #ifdef ETIMEDOUT 123758542Seric case ETIMEDOUT: /* Connection timed out */ 123858542Seric #endif 123958542Seric #ifdef ESTALE 124058542Seric case ESTALE: /* Stale NFS file handle */ 124158542Seric #endif 124258542Seric #ifdef ENETDOWN 124358542Seric case ENETDOWN: /* Network is down */ 124458542Seric #endif 124558542Seric #ifdef ENETUNREACH 124658542Seric case ENETUNREACH: /* Network is unreachable */ 124758542Seric #endif 124858542Seric #ifdef ENETRESET 124958542Seric case ENETRESET: /* Network dropped connection on reset */ 125058542Seric #endif 125158542Seric #ifdef ECONNABORTED 125258542Seric case ECONNABORTED: /* Software caused connection abort */ 125358542Seric #endif 125458542Seric #ifdef ECONNRESET 125558542Seric case ECONNRESET: /* Connection reset by peer */ 125658542Seric #endif 125758542Seric #ifdef ENOBUFS 125858542Seric case ENOBUFS: /* No buffer space available */ 125958542Seric #endif 126058542Seric #ifdef ESHUTDOWN 126158542Seric case ESHUTDOWN: /* Can't send after socket shutdown */ 126258542Seric #endif 126358542Seric #ifdef ECONNREFUSED 126458542Seric case ECONNREFUSED: /* Connection refused */ 126558542Seric #endif 126658542Seric #ifdef EHOSTDOWN 126758542Seric case EHOSTDOWN: /* Host is down */ 126858542Seric #endif 126958542Seric #ifdef EHOSTUNREACH 127058542Seric case EHOSTUNREACH: /* No route to host */ 127158542Seric #endif 127258542Seric #ifdef EDQUOT 127358542Seric case EDQUOT: /* Disc quota exceeded */ 127458542Seric #endif 127558542Seric #ifdef EPROCLIM 127658542Seric case EPROCLIM: /* Too many processes */ 127758542Seric #endif 127858542Seric #ifdef EUSERS 127958542Seric case EUSERS: /* Too many users */ 128058542Seric #endif 128158542Seric #ifdef EDEADLK 128258542Seric case EDEADLK: /* Resource deadlock avoided */ 128358542Seric #endif 128458542Seric #ifdef EISCONN 128558542Seric case EISCONN: /* Socket already connected */ 128658542Seric #endif 128758542Seric #ifdef EINPROGRESS 128858542Seric case EINPROGRESS: /* Operation now in progress */ 128958542Seric #endif 129058542Seric #ifdef EALREADY 129158542Seric case EALREADY: /* Operation already in progress */ 129258542Seric #endif 129358542Seric #ifdef EADDRINUSE 129458542Seric case EADDRINUSE: /* Address already in use */ 129558542Seric #endif 129658542Seric #ifdef EADDRNOTAVAIL 129758542Seric case EADDRNOTAVAIL: /* Can't assign requested address */ 129858542Seric #endif 1299*63834Seric #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) 130058542Seric case ENOSR: /* Out of streams resources */ 130158542Seric #endif 130258542Seric return TRUE; 130358542Seric } 130458542Seric 130558542Seric /* nope, must be permanent */ 130658542Seric return FALSE; 130758542Seric } 130858689Seric /* 130958689Seric ** LOCKFILE -- lock a file using flock or (shudder) lockf 131058689Seric ** 131158689Seric ** Parameters: 131258689Seric ** fd -- the file descriptor of the file. 131358689Seric ** filename -- the file name (for error messages). 131458689Seric ** type -- type of the lock. Bits can be: 131558689Seric ** LOCK_EX -- exclusive lock. 131658689Seric ** LOCK_NB -- non-blocking. 131758689Seric ** 131858689Seric ** Returns: 131958689Seric ** TRUE if the lock was acquired. 132058689Seric ** FALSE otherwise. 132158689Seric */ 132258689Seric 132358689Seric bool 132458689Seric lockfile(fd, filename, type) 132558689Seric int fd; 132658689Seric char *filename; 132758689Seric int type; 132858689Seric { 132958689Seric # ifdef LOCKF 133058689Seric int action; 133158689Seric struct flock lfd; 133258689Seric 133359447Seric if (bitset(LOCK_UN, type)) 133459447Seric lfd.l_type = F_UNLCK; 133559447Seric else if (bitset(LOCK_EX, type)) 133658689Seric lfd.l_type = F_WRLCK; 133758689Seric else 133858689Seric lfd.l_type = F_RDLCK; 133958689Seric 134058689Seric if (bitset(LOCK_NB, type)) 134158689Seric action = F_SETLK; 134258689Seric else 134358689Seric action = F_SETLKW; 134458689Seric 134558689Seric lfd.l_whence = lfd.l_start = lfd.l_len = 0; 134658689Seric 134758689Seric if (fcntl(fd, action, &lfd) >= 0) 134858689Seric return TRUE; 134958689Seric 135058689Seric if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN)) 135159447Seric syserr("cannot lockf(%s, %o)", filename, type); 135258689Seric # else 135358689Seric if (flock(fd, type) >= 0) 135458689Seric return TRUE; 135558689Seric 135658689Seric if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK) 135759447Seric syserr("cannot flock(%s, %o)", filename, type); 135858689Seric # endif 135958689Seric return FALSE; 136058689Seric } 1361