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*58789Seric static char sccsid[] = "@(#)conf.c 6.41 (Berkeley) 03/23/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, 668060Seric /* destination fields */ 679055Seric "to", H_RCPT, 6811417Seric "resent-to", H_RCPT|H_RESENT, 699055Seric "cc", H_RCPT, 7011417Seric "resent-cc", H_RCPT|H_RESENT, 719055Seric "bcc", H_RCPT|H_ACHECK, 7211417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 7356215Seric "apparently-to", H_RCPT, 748060Seric /* message identification and control */ 7511417Seric "message-id", 0, 7611417Seric "resent-message-id", H_RESENT, 779055Seric "message", H_EOH, 789055Seric "text", H_EOH, 7911417Seric /* date fields */ 8011417Seric "date", 0, 8111417Seric "resent-date", H_RESENT, 828060Seric /* trace fields */ 839055Seric "received", H_TRACE|H_FORCE, 849055Seric "via", H_TRACE|H_FORCE, 859055Seric "mail-from", H_TRACE|H_FORCE, 868060Seric 879055Seric NULL, 0, 882897Seric }; 894166Seric 904166Seric 914166Seric 924282Seric /* 934282Seric ** Location of system files/databases/etc. 944282Seric */ 954282Seric 9640980Sbostic char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 9740980Sbostic char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 9858082Seric char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */ 999039Seric 1009064Seric 1019064Seric 1029039Seric /* 10358082Seric ** Privacy values 10458082Seric */ 10558082Seric 10658082Seric struct prival PrivacyValues[] = 10758082Seric { 10858082Seric "public", PRIV_PUBLIC, 10958082Seric "needmailhelo", PRIV_NEEDMAILHELO, 11058114Seric "needexpnhelo", PRIV_NEEDEXPNHELO, 11158082Seric "needvrfyhelo", PRIV_NEEDVRFYHELO, 11258082Seric "noexpn", PRIV_NOEXPN, 11358082Seric "novrfy", PRIV_NOVRFY, 11458249Seric "restrictmailq", PRIV_RESTRMAILQ, 115*58789Seric "authwarnings", PRIV_AUTHWARNINGS, 11658082Seric "goaway", PRIV_GOAWAY, 117*58789Seric NULL, 0, 11858082Seric }; 11958082Seric 12058082Seric 12158082Seric 12258082Seric /* 12324943Seric ** Miscellaneous stuff. 1249039Seric */ 1259039Seric 12624943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 12724943Seric /* 12824943Seric ** SETDEFAULTS -- set default values 12924943Seric ** 13024943Seric ** Because of the way freezing is done, these must be initialized 13124943Seric ** using direct code. 13224943Seric ** 13324943Seric ** Parameters: 13458734Seric ** e -- the default envelope. 13524943Seric ** 13624943Seric ** Returns: 13724943Seric ** none. 13824943Seric ** 13924943Seric ** Side Effects: 14024943Seric ** Initializes a bunch of global variables to their 14124943Seric ** default values. 14224943Seric */ 14324943Seric 14458737Seric #define DAYS * 24 * 60 * 60 14558737Seric 14658734Seric setdefaults(e) 14758734Seric register ENVELOPE *e; 14824943Seric { 14957438Seric SpaceSub = ' '; /* option B */ 15057438Seric QueueLA = 8; /* option x */ 15157438Seric RefuseLA = 12; /* option X */ 15257438Seric WkRecipFact = 30000L; /* option y */ 15357438Seric WkClassFact = 1800L; /* option z */ 15457438Seric WkTimeFact = 90000L; /* option Z */ 15557438Seric QueueFactor = WkRecipFact * 20; /* option q */ 15657142Seric FileMode = (getuid() != geteuid()) ? 0644 : 0600; 15757438Seric /* option F */ 15857438Seric DefUid = 1; /* option u */ 15957438Seric DefGid = 1; /* option g */ 16057438Seric CheckpointInterval = 10; /* option C */ 16157438Seric MaxHopCount = 25; /* option h */ 16258734Seric e->e_sendmode = SM_FORK; /* option d */ 16358734Seric e->e_errormode = EM_PRINT; /* option e */ 16457438Seric EightBit = FALSE; /* option 8 */ 16557438Seric MaxMciCache = 1; /* option k */ 16657438Seric MciCacheTimeout = 300; /* option K */ 16757438Seric LogLevel = 9; /* option L */ 16858112Seric settimeouts(NULL); /* option r */ 16958737Seric TimeOuts.to_q_return = 5 DAYS; /* option T */ 17058737Seric TimeOuts.to_q_warning = 0; /* option T */ 171*58789Seric PrivacyFlags = PRIV_AUTHWARNINGS; /* option p */ 17240973Sbostic setdefuser(); 17353654Seric setupmaps(); 17457402Seric setupmailers(); 17524943Seric } 176294Seric 17740973Sbostic 1784326Seric /* 17940973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 18040973Sbostic */ 18140973Sbostic 18240973Sbostic setdefuser() 18340973Sbostic { 18440973Sbostic struct passwd *defpwent; 18557386Seric static char defuserbuf[40]; 18640973Sbostic 18757386Seric DefUser = defuserbuf; 18840973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 18957386Seric strcpy(defuserbuf, defpwent->pw_name); 19040973Sbostic else 19157386Seric strcpy(defuserbuf, "nobody"); 19240973Sbostic } 19353654Seric /* 19453654Seric ** SETUPMAPS -- set up map classes 19553654Seric ** 19653654Seric ** Since these are compiled in, they cannot be in the config file. 19753654Seric ** 19853654Seric */ 19940973Sbostic 20053654Seric setupmaps() 20153654Seric { 20253654Seric register STAB *s; 20356836Seric extern bool host_map_init(); 20453654Seric extern char *maphostname(); 20540973Sbostic 20653654Seric /* set up host name lookup map */ 20753654Seric s = stab("host", ST_MAPCLASS, ST_ENTER); 20856836Seric s->s_mapclass.map_init = host_map_init; 20953654Seric s->s_mapclass.map_lookup = maphostname; 21053654Seric 21153654Seric /* 21253654Seric ** Set up other map classes. 21353654Seric */ 21453654Seric 21553654Seric # ifdef DBM_MAP 21653654Seric /* dbm file access */ 21753654Seric { 21856836Seric extern bool dbm_map_init(); 21953654Seric extern char *dbm_map_lookup(); 22053654Seric 22153654Seric s = stab("dbm", ST_MAPCLASS, ST_ENTER); 22253654Seric s->s_mapclass.map_init = dbm_map_init; 22353654Seric s->s_mapclass.map_lookup = dbm_map_lookup; 22453654Seric } 22553654Seric # endif 22653654Seric 22753654Seric # ifdef BTREE_MAP 22853654Seric /* new database file access -- btree files */ 22953654Seric { 23056823Seric extern bool bt_map_init(); 23156823Seric extern char *db_map_lookup(); 23253654Seric 23353654Seric s = stab("btree", ST_MAPCLASS, ST_ENTER); 23453654Seric s->s_mapclass.map_init = bt_map_init; 23556823Seric s->s_mapclass.map_lookup = db_map_lookup; 23653654Seric } 23753654Seric # endif 23853654Seric 23953654Seric # ifdef HASH_MAP 24053654Seric /* new database file access -- hash files */ 24153654Seric { 24256823Seric extern bool hash_map_init(); 24356823Seric extern char *db_map_lookup(); 24453654Seric 24553654Seric s = stab("hash", ST_MAPCLASS, ST_ENTER); 24653654Seric s->s_mapclass.map_init = hash_map_init; 24756823Seric s->s_mapclass.map_lookup = db_map_lookup; 24853654Seric } 24953654Seric # endif 25053654Seric 25157208Seric # ifdef NIS_MAP 25257208Seric /* NIS map access */ 25357208Seric { 25457208Seric extern bool nis_map_init(); 25557208Seric extern char *nis_map_lookup(); 25657208Seric 25757208Seric s = stab("nis", ST_MAPCLASS, ST_ENTER); 25857208Seric s->s_mapclass.map_init = nis_map_init; 25957208Seric s->s_mapclass.map_lookup = nis_map_lookup; 26057208Seric } 26157208Seric # endif 26257208Seric 26353654Seric # ifdef USERDB_MAP 26453654Seric /* user database */ 26553654Seric { 26656836Seric extern bool udb_map_init(); 26753654Seric extern char *udb_map_lookup(); 26853654Seric 26953654Seric s = stab("udb", ST_MAPCLASS, ST_ENTER); 27053654Seric s->s_mapclass.map_init = udb_map_init; 27153654Seric s->s_mapclass.map_lookup = udb_map_lookup; 27253654Seric } 27353654Seric # endif 27453654Seric } 27553654Seric /* 27656836Seric ** HOST_MAP_INIT -- initialize host class structures 27756836Seric */ 27856836Seric 27956836Seric bool 28056836Seric host_map_init(map, mapname, args) 28156836Seric MAP *map; 28256836Seric char *mapname; 28356836Seric char *args; 28456836Seric { 28556836Seric register char *p = args; 28656836Seric 28756836Seric for (;;) 28856836Seric { 28958050Seric while (isascii(*p) && isspace(*p)) 29056836Seric p++; 29156836Seric if (*p != '-') 29256836Seric break; 29356836Seric switch (*++p) 29456836Seric { 29556836Seric case 'a': 29656836Seric map->map_app = ++p; 29756836Seric break; 29856836Seric } 29958050Seric while (*p != '\0' && !(isascii(*p) && isspace(*p))) 30056836Seric p++; 30156836Seric if (*p != '\0') 30256836Seric *p++ = '\0'; 30356836Seric } 30456836Seric if (map->map_app != NULL) 30556836Seric map->map_app = newstr(map->map_app); 30656836Seric return TRUE; 30756836Seric } 30857402Seric /* 30957402Seric ** SETUPMAILERS -- initialize default mailers 31057402Seric */ 31156836Seric 31257402Seric setupmailers() 31357402Seric { 31457402Seric char buf[100]; 31557402Seric 31657403Seric strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); 31757403Seric makemailer(buf); 31857403Seric 31957402Seric strcpy(buf, "*file*, P=/dev/null, F=lsDEu, A=FILE"); 32057402Seric makemailer(buf); 32157402Seric 32257402Seric strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 32357402Seric makemailer(buf); 32457402Seric } 32556836Seric /* 3264326Seric ** GETRUID -- get real user id (V7) 3274326Seric */ 3284326Seric 3294326Seric getruid() 3304326Seric { 3319274Seric if (OpMode == MD_DAEMON) 3324536Seric return (RealUid); 3334536Seric else 3344536Seric return (getuid()); 3354326Seric } 3364326Seric 3374326Seric 3384326Seric /* 3394326Seric ** GETRGID -- get real group id (V7). 3404326Seric */ 3414326Seric 3424326Seric getrgid() 3434326Seric { 3449274Seric if (OpMode == MD_DAEMON) 3454536Seric return (RealGid); 3464536Seric else 3474536Seric return (getgid()); 3484326Seric } 34953654Seric /* 3509369Seric ** USERNAME -- return the user id of the logged in user. 3519369Seric ** 3529369Seric ** Parameters: 3539369Seric ** none. 3549369Seric ** 3559369Seric ** Returns: 3569369Seric ** The login name of the logged in user. 3579369Seric ** 3589369Seric ** Side Effects: 3599369Seric ** none. 3609369Seric ** 3619369Seric ** Notes: 3629369Seric ** The return value is statically allocated. 3639369Seric */ 3649369Seric 3659369Seric char * 3669369Seric username() 3679369Seric { 36817469Seric static char *myname = NULL; 3699369Seric extern char *getlogin(); 37019904Smiriam register struct passwd *pw; 3719369Seric 37217469Seric /* cache the result */ 37317469Seric if (myname == NULL) 37417469Seric { 37517469Seric myname = getlogin(); 37617469Seric if (myname == NULL || myname[0] == '\0') 37717469Seric { 37817469Seric pw = getpwuid(getruid()); 37917469Seric if (pw != NULL) 38040993Sbostic myname = newstr(pw->pw_name); 38117469Seric } 38219904Smiriam else 38319904Smiriam { 38458736Seric uid_t uid = getuid(); 38519873Smiriam 38640993Sbostic myname = newstr(myname); 38740993Sbostic if ((pw = getpwnam(myname)) == NULL || 38858736Seric (uid != 0 && uid != pw->pw_uid)) 38919904Smiriam { 39058736Seric pw = getpwuid(uid); 39124945Seric if (pw != NULL) 39240993Sbostic myname = newstr(pw->pw_name); 39319873Smiriam } 39419873Smiriam } 39517469Seric if (myname == NULL || myname[0] == '\0') 39617469Seric { 39758151Seric syserr("554 Who are you?"); 39817469Seric myname = "postmaster"; 39917469Seric } 40017469Seric } 40117469Seric 40217469Seric return (myname); 4039369Seric } 4049369Seric /* 4054190Seric ** TTYPATH -- Get the path of the user's tty 406294Seric ** 407294Seric ** Returns the pathname of the user's tty. Returns NULL if 408294Seric ** the user is not logged in or if s/he has write permission 409294Seric ** denied. 410294Seric ** 411294Seric ** Parameters: 412294Seric ** none 413294Seric ** 414294Seric ** Returns: 415294Seric ** pathname of the user's tty. 416294Seric ** NULL if not logged in or write permission denied. 417294Seric ** 418294Seric ** Side Effects: 419294Seric ** none. 420294Seric ** 421294Seric ** WARNING: 422294Seric ** Return value is in a local buffer. 423294Seric ** 424294Seric ** Called By: 425294Seric ** savemail 426294Seric */ 427294Seric 428294Seric # include <sys/stat.h> 429294Seric 430294Seric char * 431294Seric ttypath() 432294Seric { 433294Seric struct stat stbuf; 434294Seric register char *pathn; 435294Seric extern char *ttyname(); 4364081Seric extern char *getlogin(); 437294Seric 438294Seric /* compute the pathname of the controlling tty */ 4399369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4409369Seric (pathn = ttyname(0)) == NULL) 441294Seric { 442294Seric errno = 0; 443294Seric return (NULL); 444294Seric } 445294Seric 446294Seric /* see if we have write permission */ 4472967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 448294Seric { 449294Seric errno = 0; 450294Seric return (NULL); 451294Seric } 452294Seric 453294Seric /* see if the user is logged in */ 454294Seric if (getlogin() == NULL) 455294Seric return (NULL); 456294Seric 457294Seric /* looks good */ 458294Seric return (pathn); 459294Seric } 4602967Seric /* 4612967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4622967Seric ** 4632967Seric ** This routine can be supplied on a per-installation basis 4642967Seric ** to determine whether a person is allowed to send a message. 4652967Seric ** This allows restriction of certain types of internet 4662967Seric ** forwarding or registration of users. 4672967Seric ** 4682967Seric ** If the hosts are found to be incompatible, an error 46957454Seric ** message should be given using "usrerr" and 0 should 4702967Seric ** be returned. 4712967Seric ** 4724288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4734288Seric ** function; this should be done on huge messages. 4744288Seric ** 4752967Seric ** Parameters: 4762967Seric ** to -- the person being sent to. 4772967Seric ** 4782967Seric ** Returns: 47957459Seric ** an exit status 4802967Seric ** 4812967Seric ** Side Effects: 4822967Seric ** none (unless you include the usrerr stuff) 4832967Seric */ 4842967Seric 48555012Seric checkcompat(to, e) 4862967Seric register ADDRESS *to; 48755012Seric register ENVELOPE *e; 4882967Seric { 48912133Seric # ifdef lint 49012133Seric if (to == NULL) 49112133Seric to++; 49212133Seric # endif lint 49310698Seric # ifdef EXAMPLE_CODE 49410698Seric /* this code is intended as an example only */ 4954437Seric register STAB *s; 4964437Seric 4974437Seric s = stab("arpa", ST_MAILER, ST_FIND); 49855012Seric if (s != NULL && e->e_from.q_mailer != LocalMailer && 4999369Seric to->q_mailer == s->s_mailer) 5004437Seric { 50158151Seric usrerr("553 No ARPA mail through this machine: see your system administration"); 50210698Seric /* NoReturn = TRUE; to supress return copy */ 50357459Seric return (EX_UNAVAILABLE); 5044437Seric } 50556795Seric # endif /* EXAMPLE_CODE */ 50657459Seric return (EX_OK); 5072967Seric } 5089369Seric /* 5099369Seric ** HOLDSIGS -- arrange to hold all signals 5109369Seric ** 5119369Seric ** Parameters: 5129369Seric ** none. 5139369Seric ** 5149369Seric ** Returns: 5159369Seric ** none. 5169369Seric ** 5179369Seric ** Side Effects: 5189369Seric ** Arranges that signals are held. 5199369Seric */ 5209369Seric 5219369Seric holdsigs() 5229369Seric { 5239369Seric } 5249369Seric /* 5259369Seric ** RLSESIGS -- arrange to release all signals 5269369Seric ** 5279369Seric ** This undoes the effect of holdsigs. 5289369Seric ** 5299369Seric ** Parameters: 5309369Seric ** none. 5319369Seric ** 5329369Seric ** Returns: 5339369Seric ** none. 5349369Seric ** 5359369Seric ** Side Effects: 5369369Seric ** Arranges that signals are released. 5379369Seric */ 5389369Seric 5399369Seric rlsesigs() 5409369Seric { 5419369Seric } 54214872Seric /* 54314872Seric ** GETLA -- get the current load average 54414872Seric ** 54514881Seric ** This code stolen from la.c. 54614881Seric ** 54714872Seric ** Parameters: 54814872Seric ** none. 54914872Seric ** 55014872Seric ** Returns: 55114872Seric ** The current load average as an integer. 55214872Seric ** 55314872Seric ** Side Effects: 55414872Seric ** none. 55514872Seric */ 55614872Seric 55751920Seric /* try to guess what style of load average we have */ 55851920Seric #define LA_ZERO 1 /* always return load average as zero */ 55951920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 56051920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 56151920Seric #define LA_SUBR 4 /* call getloadavg */ 56214872Seric 56351920Seric #ifndef LA_TYPE 56451920Seric # if defined(sun) 56551920Seric # define LA_TYPE LA_INT 56651920Seric # endif 56757977Seric # if defined(mips) || defined(__alpha) 56857977Seric /* Ultrix or OSF/1 or RISC/os */ 56951920Seric # define LA_TYPE LA_INT 57051920Seric # define LA_AVENRUN "avenrun" 57151920Seric # endif 57251920Seric # if defined(hpux) 57351920Seric # define LA_TYPE LA_FLOAT 57451920Seric # endif 57551920Seric 57651920Seric # ifndef LA_TYPE 57757736Seric # if defined(SYSTEM5) 57857736Seric # define LA_TYPE LA_INT 57957736Seric # define LA_AVENRUN "avenrun" 58057736Seric # else 58157736Seric # if defined(BSD) 58257736Seric # define LA_TYPE LA_SUBR 58357736Seric # else 58457736Seric # define LA_TYPE LA_ZERO 58557736Seric # endif 58657736Seric # endif 58751920Seric # endif 58851920Seric #endif 58951920Seric 59051920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 59151920Seric 59214872Seric #include <nlist.h> 59314872Seric 59451920Seric #ifndef LA_AVENRUN 59551920Seric #define LA_AVENRUN "_avenrun" 59651920Seric #endif 59751920Seric 59851920Seric /* _PATH_UNIX should be defined in <paths.h> */ 59951920Seric #ifndef _PATH_UNIX 60051920Seric # if defined(hpux) 60151920Seric # define _PATH_UNIX "/hp-ux" 60251920Seric # endif 60351920Seric # if defined(mips) && !defined(ultrix) 60451920Seric /* powerful RISC/os */ 60551920Seric # define _PATH_UNIX "/unix" 60651920Seric # endif 60757736Seric # if defined(SYSTEM5) 60857977Seric # ifndef _PATH_UNIX 60957977Seric # define _PATH_UNIX "/unix" 61057977Seric # endif 61157736Seric # endif 61251920Seric # ifndef _PATH_UNIX 61351920Seric # define _PATH_UNIX "/vmunix" 61451920Seric # endif 61551920Seric #endif 61651920Seric 61714872Seric struct nlist Nl[] = 61814872Seric { 61951920Seric { LA_AVENRUN }, 62014872Seric #define X_AVENRUN 0 62114872Seric { 0 }, 62214872Seric }; 62314872Seric 62457736Seric #if defined(unixpc) 62557736Seric # define FSHIFT 5 62657736Seric #endif 62757736Seric 62857977Seric #if defined(__alpha) 62957977Seric # define FSHIFT 10 63057977Seric #endif 63157977Seric 63251920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 63351920Seric # define FSHIFT 8 63457736Seric #endif 63557736Seric #if (LA_TYPE == LA_INT) && !defined(FSCALE) 63651920Seric # define FSCALE (1 << FSHIFT) 63751920Seric #endif 63840930Srick 63914872Seric getla() 64014872Seric { 64114872Seric static int kmem = -1; 64251920Seric #if LA_TYPE == LA_INT 64324943Seric long avenrun[3]; 64451920Seric #else 64551920Seric double avenrun[3]; 64651920Seric #endif 64725615Seric extern off_t lseek(); 64857736Seric extern char *errstring(); 64957736Seric extern int errno; 65014872Seric 65114872Seric if (kmem < 0) 65214872Seric { 65324945Seric kmem = open("/dev/kmem", 0, 0); 65414872Seric if (kmem < 0) 65557736Seric { 65657736Seric if (tTd(3, 1)) 65757736Seric printf("getla: open(/dev/kmem): %s\n", 65857736Seric errstring(errno)); 65914872Seric return (-1); 66057736Seric } 66151920Seric (void) fcntl(kmem, F_SETFD, 1); 66257736Seric if (nlist(_PATH_UNIX, Nl) < 0) 66357736Seric { 66457736Seric if (tTd(3, 1)) 66557736Seric printf("getla: nlist(%s): %s\n", _PATH_UNIX, 66657736Seric errstring(errno)); 66714872Seric return (-1); 66857736Seric } 66914872Seric } 67057736Seric if (tTd(3, 20)) 67157736Seric printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); 67224945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 67323118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 67419967Seric { 67519967Seric /* thank you Ian */ 67657736Seric if (tTd(3, 1)) 67757736Seric printf("getla: lseek or read: %s\n", errstring(errno)); 67819967Seric return (-1); 67919967Seric } 68051920Seric #if LA_TYPE == LA_INT 68157736Seric if (tTd(3, 5)) 68257736Seric { 68357736Seric printf("getla: avenrun = %d", avenrun[0]); 68457736Seric if (tTd(3, 15)) 68557736Seric printf(", %d, %d", avenrun[1], avenrun[2]); 68657736Seric printf("\n"); 68757736Seric } 68857736Seric if (tTd(3, 1)) 68957736Seric printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 69024943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 69151920Seric #else 69257736Seric if (tTd(3, 5)) 69357736Seric { 69457736Seric printf("getla: avenrun = %g", avenrun[0]); 69557736Seric if (tTd(3, 15)) 69657736Seric printf(", %g, %g", avenrun[1], avenrun[2]); 69757736Seric printf("\n"); 69857736Seric } 69957736Seric if (tTd(3, 1)) 70057736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 70151920Seric return ((int) (avenrun[0] + 0.5)); 70251920Seric #endif 70314872Seric } 70414872Seric 70551773Seric #else 70651920Seric #if LA_TYPE == LA_SUBR 70751773Seric 70851773Seric getla() 70951773Seric { 71051920Seric double avenrun[3]; 71151920Seric 71251920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 71357736Seric { 71457736Seric if (tTd(3, 1)) 71557736Seric perror("getla: getloadavg failed:"); 71651920Seric return (-1); 71757736Seric } 71857736Seric if (tTd(3, 1)) 71957736Seric printf("getla: %d\n", (int) (avenrun[0] +0.5)); 72051920Seric return ((int) (avenrun[0] + 0.5)); 72151773Seric } 72251773Seric 72351773Seric #else 72451773Seric 72551773Seric getla() 72651773Seric { 72757736Seric if (tTd(3, 1)) 72857736Seric printf("getla: ZERO\n"); 72951920Seric return (0); 73051773Seric } 73151773Seric 73251773Seric #endif 73351773Seric #endif 73424943Seric /* 73524943Seric ** SHOULDQUEUE -- should this message be queued or sent? 73624943Seric ** 73724943Seric ** Compares the message cost to the load average to decide. 73824943Seric ** 73924943Seric ** Parameters: 74024943Seric ** pri -- the priority of the message in question. 74157438Seric ** ctime -- the message creation time. 74224943Seric ** 74324943Seric ** Returns: 74424943Seric ** TRUE -- if this message should be queued up for the 74524943Seric ** time being. 74624943Seric ** FALSE -- if the load is low enough to send this message. 74724943Seric ** 74824943Seric ** Side Effects: 74924943Seric ** none. 75024943Seric */ 75124943Seric 75224943Seric bool 75357438Seric shouldqueue(pri, ctime) 75424943Seric long pri; 75557438Seric time_t ctime; 75624943Seric { 75751920Seric if (CurrentLA < QueueLA) 75824943Seric return (FALSE); 75958132Seric if (CurrentLA >= RefuseLA) 76058132Seric return (TRUE); 76151920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 76224943Seric } 76324943Seric /* 76453037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 76553037Seric ** 76653037Seric ** Parameters: 76753037Seric ** none. 76853037Seric ** 76953037Seric ** Returns: 77053037Seric ** TRUE if incoming SMTP connections should be refused 77153037Seric ** (for now). 77253037Seric ** FALSE if we should accept new work. 77353037Seric ** 77453037Seric ** Side Effects: 77553037Seric ** none. 77653037Seric */ 77753037Seric 77853037Seric bool 77953037Seric refuseconnections() 78053037Seric { 78153037Seric /* this is probably too simplistic */ 78258132Seric return (CurrentLA >= RefuseLA); 78353037Seric } 78453037Seric /* 78524943Seric ** SETPROCTITLE -- set process title for ps 78624943Seric ** 78724943Seric ** Parameters: 78858674Seric ** fmt -- a printf style format string. 78958674Seric ** a, b, c -- possible parameters to fmt. 79024943Seric ** 79124943Seric ** Returns: 79224943Seric ** none. 79324943Seric ** 79424943Seric ** Side Effects: 79524943Seric ** Clobbers argv of our main procedure so ps(1) will 79624943Seric ** display the title. 79724943Seric */ 79824943Seric 79958689Seric #ifdef SETPROCTITLE 80058689Seric # ifdef __hpux 80158689Seric # include <sys/pstat.h> 80258689Seric # endif 80358689Seric #endif 80458689Seric 80524943Seric /*VARARGS1*/ 80657642Seric #ifdef __STDC__ 80757642Seric setproctitle(char *fmt, ...) 80857642Seric #else 80957642Seric setproctitle(fmt, va_alist) 81024943Seric char *fmt; 81157642Seric va_dcl 81257642Seric #endif 81324943Seric { 81424943Seric # ifdef SETPROCTITLE 81524943Seric register char *p; 81625049Seric register int i; 81758674Seric char buf[MAXLINE]; 81856852Seric VA_LOCAL_DECL 81958689Seric # ifdef __hpux 82058689Seric union pstun pst; 82158689Seric # endif 82224943Seric extern char **Argv; 82324943Seric extern char *LastArgv; 82424943Seric 82558674Seric p = buf; 82624943Seric 82758674Seric /* print sendmail: heading for grep */ 82858674Seric (void) strcpy(p, "sendmail: "); 82958674Seric p += strlen(p); 83024943Seric 83158674Seric /* print the argument string */ 83258674Seric VA_START(fmt); 83358674Seric (void) vsprintf(p, fmt, ap); 83456852Seric VA_END; 83554996Seric 83658674Seric i = strlen(buf); 83758689Seric 83858689Seric # ifdef __hpux 83958689Seric pst.pst_command = buf; 84058689Seric pstat(PSTAT_SETCMD, pst, i, 0, 0); 84158689Seric # else 84258689Seric 84354996Seric if (i > LastArgv - Argv[0] - 2) 84425049Seric { 84554996Seric i = LastArgv - Argv[0] - 2; 84658674Seric buf[i] = '\0'; 84725049Seric } 84858674Seric (void) strcpy(Argv[0], buf); 84954997Seric p = &Argv[0][i]; 85024943Seric while (p < LastArgv) 85124943Seric *p++ = ' '; 85258689Seric # endif 85356795Seric # endif /* SETPROCTITLE */ 85424943Seric } 85525698Seric /* 85625698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 85725698Seric ** 85825698Seric ** Parameters: 85925698Seric ** none. 86025698Seric ** 86125698Seric ** Returns: 86225698Seric ** none. 86325698Seric ** 86425698Seric ** Side Effects: 86525698Seric ** Picks up extant zombies. 86625698Seric */ 86725698Seric 86825698Seric # include <sys/wait.h> 86925698Seric 87046928Sbostic void 87125698Seric reapchild() 87225698Seric { 87325698Seric # ifdef WNOHANG 87425698Seric union wait status; 87525698Seric 87646928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 87725698Seric continue; 87856795Seric # else /* WNOHANG */ 87925698Seric auto int status; 88025698Seric 88146928Sbostic while (wait((int *)&status) > 0) 88225698Seric continue; 88356795Seric # endif /* WNOHANG */ 88458061Seric # ifdef SYSTEM5 88558061Seric (void) signal(SIGCHLD, reapchild); 88658061Seric # endif 88725698Seric } 88855418Seric /* 88955418Seric ** UNSETENV -- remove a variable from the environment 89055418Seric ** 89155418Seric ** Not needed on newer systems. 89255418Seric ** 89355418Seric ** Parameters: 89455418Seric ** name -- the string name of the environment variable to be 89555418Seric ** deleted from the current environment. 89655418Seric ** 89755418Seric ** Returns: 89855418Seric ** none. 89955418Seric ** 90055418Seric ** Globals: 90155418Seric ** environ -- a pointer to the current environment. 90255418Seric ** 90355418Seric ** Side Effects: 90455418Seric ** Modifies environ. 90555418Seric */ 90655418Seric 90755418Seric #ifdef UNSETENV 90855418Seric 90955418Seric void 91055418Seric unsetenv(name) 91155418Seric char *name; 91255418Seric { 91355418Seric extern char **environ; 91455418Seric register char **pp; 91555418Seric int len = strlen(name); 91655418Seric 91755418Seric for (pp = environ; *pp != NULL; pp++) 91855418Seric { 91955418Seric if (strncmp(name, *pp, len) == 0 && 92055418Seric ((*pp)[len] == '=' || (*pp)[len] == '\0')) 92155418Seric break; 92255418Seric } 92355418Seric 92455418Seric for (; *pp != NULL; pp++) 92555418Seric *pp = pp[1]; 92655418Seric } 92755418Seric 92855418Seric #endif /* UNSETENV */ 92956215Seric /* 93056215Seric ** GETDTABLESIZE -- return number of file descriptors 93156215Seric ** 93256215Seric ** Only on non-BSD systems 93356215Seric ** 93456215Seric ** Parameters: 93556215Seric ** none 93656215Seric ** 93756215Seric ** Returns: 93856215Seric ** size of file descriptor table 93956215Seric ** 94056215Seric ** Side Effects: 94156215Seric ** none 94256215Seric */ 94356215Seric 94456215Seric #ifdef SYSTEM5 94556215Seric 94656215Seric int 94756215Seric getdtablesize() 94856215Seric { 94958689Seric # ifdef _SC_OPEN_MAX 95058689Seric return sysconf(_SC_OPEN_MAX); 95158689Seric # else 95256215Seric return NOFILE; 95358689Seric # endif 95456215Seric } 95556215Seric 95656215Seric #endif 95757631Seric /* 95857631Seric ** UNAME -- get the UUCP name of this system. 95957631Seric */ 96057631Seric 96157943Seric #ifndef HASUNAME 96257631Seric 96357631Seric int 96457631Seric uname(name) 96557631Seric struct utsname *name; 96657631Seric { 96757631Seric FILE *file; 96857631Seric char *n; 96957631Seric 97057631Seric name->nodename[0] = '\0'; 97157631Seric 97257661Seric /* try /etc/whoami -- one line with the node name */ 97357631Seric if ((file = fopen("/etc/whoami", "r")) != NULL) 97457631Seric { 97557661Seric (void) fgets(name->nodename, NODE_LENGTH + 1, file); 97657631Seric (void) fclose(file); 97757661Seric n = strchr(name->nodename, '\n'); 97857631Seric if (n != NULL) 97957631Seric *n = '\0'; 98057631Seric if (name->nodename[0] != '\0') 98157631Seric return (0); 98257631Seric } 98357631Seric 98457661Seric /* try /usr/include/whoami.h -- has a #define somewhere */ 98557631Seric if ((file = fopen("/usr/include/whoami.h", "r")) != NULL) 98657631Seric { 98757631Seric char buf[MAXLINE]; 98857631Seric 98957631Seric while (fgets(buf, MAXLINE, file) != NULL) 99057631Seric if (sscanf(buf, "#define sysname \"%*[^\"]\"", 99157631Seric NODE_LENGTH, name->nodename) > 0) 99257631Seric break; 99357631Seric (void) fclose(file); 99457631Seric if (name->nodename[0] != '\0') 99557631Seric return (0); 99657631Seric } 99757631Seric 99857631Seric #ifdef TRUST_POPEN 99957631Seric /* 100057631Seric ** Popen is known to have security holes. 100157631Seric */ 100257631Seric 100357661Seric /* try uuname -l to return local name */ 100457631Seric if ((file = popen("uuname -l", "r")) != NULL) 100557631Seric { 100657661Seric (void) fgets(name, NODE_LENGTH + 1, file); 100757631Seric (void) pclose(file); 100857661Seric n = strchr(name, '\n'); 100957631Seric if (n != NULL) 101057631Seric *n = '\0'; 101157661Seric if (name->nodename[0] != '\0') 101257631Seric return (0); 101357631Seric } 101457631Seric #endif 101557631Seric 101657631Seric return (-1); 101757631Seric } 101857943Seric #endif /* HASUNAME */ 101958068Seric /* 102058068Seric ** INITGROUPS -- initialize groups 102158068Seric ** 102258068Seric ** Stub implementation for System V style systems 102358068Seric */ 102458068Seric 102558068Seric #ifndef HASINITGROUPS 102658068Seric # if !defined(SYSTEM5) || defined(hpux) 102758068Seric # define HASINITGROUPS 102858068Seric # endif 102958068Seric #endif 103058068Seric 103158068Seric #ifndef HASINITGROUPS 103258068Seric 103358068Seric initgroups(name, basegid) 103458068Seric char *name; 103558068Seric int basegid; 103658068Seric { 103758068Seric return 0; 103858068Seric } 103958068Seric 104058068Seric #endif 104158082Seric /* 104258082Seric ** ENOUGHSPACE -- check to see if there is enough free space on the queue fs 104358082Seric ** 104458082Seric ** Only implemented if you have statfs. 104558082Seric ** 104658082Seric ** Parameters: 104758333Seric ** msize -- the size to check against. If zero, we don't yet 104858333Seric ** know how big the message will be, so just check for 104958333Seric ** a "reasonable" amount. 105058082Seric ** 105158082Seric ** Returns: 105258082Seric ** TRUE if there is enough space. 105358082Seric ** FALSE otherwise. 105458082Seric */ 105558082Seric 105658082Seric #ifndef HASSTATFS 105758082Seric # if defined(BSD4_4) || defined(__osf__) 105858082Seric # define HASSTATFS 105958082Seric # endif 106058082Seric #endif 106158082Seric 106258082Seric #ifdef HASSTATFS 106358157Seric # undef HASUSTAT 106458157Seric #endif 106558157Seric 106658157Seric #if defined(HASUSTAT) 106758157Seric # include <sys/stat.h> 106858157Seric # include <ustat.h> 106958157Seric #endif 107058157Seric 107158157Seric #ifdef HASSTATFS 107258133Seric # if defined(sgi) || defined(apollo) 107358133Seric # include <sys/statfs.h> 107458133Seric # else 107558133Seric # if defined(sun) || defined(hpux) 107658133Seric # include <sys/vfs.h> 107758133Seric # else 107858157Seric # include <sys/mount.h> 107958133Seric # endif 108058133Seric # endif 108158082Seric #endif 108258082Seric 108358082Seric bool 108458333Seric enoughspace(msize) 108558333Seric long msize; 108658082Seric { 108758160Seric #if defined(HASSTATFS) || defined(HASUSTAT) 108858157Seric # if defined(HASUSTAT) 108958153Seric struct ustat fs; 109058153Seric struct stat statbuf; 109158366Seric # define FSBLOCKSIZE DEV_BSIZE 109258157Seric # define f_bavail f_tfree 109358157Seric # else 109458157Seric # if defined(ultrix) 109558157Seric struct fs_data fs; 109658157Seric # define f_bavail fd_bfreen 109758366Seric # define FSBLOCKSIZE fs.fd_bsize 109858153Seric # else 109958082Seric struct statfs fs; 110058366Seric # define FSBLOCKSIZE fs.f_bsize 110158153Seric # endif 110258133Seric # endif 110358333Seric long blocksneeded; 110458082Seric extern int errno; 110558082Seric extern char *errstring(); 110658082Seric 110758333Seric if (MinBlocksFree <= 0 && msize <= 0) 110858082Seric { 110958082Seric if (tTd(4, 80)) 111058133Seric printf("enoughspace: no threshold\n"); 111158133Seric return TRUE; 111258133Seric } 111358333Seric 111458157Seric # if defined(HASUSTAT) 111558157Seric if (stat(QueueDir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) 111658157Seric # else 111758157Seric # if defined(sgi) || defined(apollo) 111858133Seric if (statfs(QueueDir, &fs, sizeof fs, 0) == 0) 111958157Seric # else 112058157Seric # if defined(ultrix) 112158133Seric if (statfs(QueueDir, &fs) > 0) 112258153Seric # else 112358133Seric if (statfs(QueueDir, &fs) == 0) 112458153Seric # endif 112558133Seric # endif 112658133Seric # endif 112758133Seric { 112858133Seric if (tTd(4, 80)) 112958333Seric printf("enoughspace: bavail=%ld, need=%ld\n", 113058333Seric fs.f_bavail, msize); 113158333Seric 113258333Seric /* convert msize to block count */ 113358366Seric msize = msize / FSBLOCKSIZE + 1; 113458333Seric if (MinBlocksFree >= 0) 113558333Seric msize += MinBlocksFree; 113658333Seric 113758333Seric if (fs.f_bavail < msize) 113858090Seric { 113958090Seric #ifdef LOG 114058090Seric if (LogLevel > 0) 114158090Seric syslog(LOG_ALERT, "%s: low on space (have %ld, need %ld)", 114258333Seric QueueDir, fs.f_bavail, msize); 114358090Seric #endif 114458082Seric return FALSE; 114558090Seric } 114658082Seric } 114758082Seric else if (tTd(4, 80)) 114858333Seric printf("enoughspace failure: min=%ld, need=%ld: %s\n", 114958333Seric MinBlocksFree, msize, errstring(errno)); 115058082Seric #endif 115158082Seric return TRUE; 115258082Seric } 115358542Seric /* 115458542Seric ** TRANSIENTERROR -- tell if an error code indicates a transient failure 115558542Seric ** 115658542Seric ** This looks at an errno value and tells if this is likely to 115758542Seric ** go away if retried later. 115858542Seric ** 115958542Seric ** Parameters: 116058542Seric ** err -- the errno code to classify. 116158542Seric ** 116258542Seric ** Returns: 116358542Seric ** TRUE if this is probably transient. 116458542Seric ** FALSE otherwise. 116558542Seric */ 116658542Seric 116758542Seric bool 116858542Seric transienterror(err) 116958542Seric int err; 117058542Seric { 117158542Seric switch (err) 117258542Seric { 117358542Seric case EIO: /* I/O error */ 117458542Seric case ENXIO: /* Device not configured */ 117558542Seric case EAGAIN: /* Resource temporarily unavailable */ 117658542Seric case ENOMEM: /* Cannot allocate memory */ 117758542Seric case ENODEV: /* Operation not supported by device */ 117858542Seric case ENFILE: /* Too many open files in system */ 117958542Seric case EMFILE: /* Too many open files */ 118058542Seric case ENOSPC: /* No space left on device */ 118158542Seric #ifdef ETIMEDOUT 118258542Seric case ETIMEDOUT: /* Connection timed out */ 118358542Seric #endif 118458542Seric #ifdef ESTALE 118558542Seric case ESTALE: /* Stale NFS file handle */ 118658542Seric #endif 118758542Seric #ifdef ENETDOWN 118858542Seric case ENETDOWN: /* Network is down */ 118958542Seric #endif 119058542Seric #ifdef ENETUNREACH 119158542Seric case ENETUNREACH: /* Network is unreachable */ 119258542Seric #endif 119358542Seric #ifdef ENETRESET 119458542Seric case ENETRESET: /* Network dropped connection on reset */ 119558542Seric #endif 119658542Seric #ifdef ECONNABORTED 119758542Seric case ECONNABORTED: /* Software caused connection abort */ 119858542Seric #endif 119958542Seric #ifdef ECONNRESET 120058542Seric case ECONNRESET: /* Connection reset by peer */ 120158542Seric #endif 120258542Seric #ifdef ENOBUFS 120358542Seric case ENOBUFS: /* No buffer space available */ 120458542Seric #endif 120558542Seric #ifdef ESHUTDOWN 120658542Seric case ESHUTDOWN: /* Can't send after socket shutdown */ 120758542Seric #endif 120858542Seric #ifdef ECONNREFUSED 120958542Seric case ECONNREFUSED: /* Connection refused */ 121058542Seric #endif 121158542Seric #ifdef EHOSTDOWN 121258542Seric case EHOSTDOWN: /* Host is down */ 121358542Seric #endif 121458542Seric #ifdef EHOSTUNREACH 121558542Seric case EHOSTUNREACH: /* No route to host */ 121658542Seric #endif 121758542Seric #ifdef EDQUOT 121858542Seric case EDQUOT: /* Disc quota exceeded */ 121958542Seric #endif 122058542Seric #ifdef EPROCLIM 122158542Seric case EPROCLIM: /* Too many processes */ 122258542Seric #endif 122358542Seric #ifdef EUSERS 122458542Seric case EUSERS: /* Too many users */ 122558542Seric #endif 122658542Seric #ifdef EDEADLK 122758542Seric case EDEADLK: /* Resource deadlock avoided */ 122858542Seric #endif 122958542Seric #ifdef EISCONN 123058542Seric case EISCONN: /* Socket already connected */ 123158542Seric #endif 123258542Seric #ifdef EINPROGRESS 123358542Seric case EINPROGRESS: /* Operation now in progress */ 123458542Seric #endif 123558542Seric #ifdef EALREADY 123658542Seric case EALREADY: /* Operation already in progress */ 123758542Seric #endif 123858542Seric #ifdef EADDRINUSE 123958542Seric case EADDRINUSE: /* Address already in use */ 124058542Seric #endif 124158542Seric #ifdef EADDRNOTAVAIL 124258542Seric case EADDRNOTAVAIL: /* Can't assign requested address */ 124358542Seric #endif 124458542Seric #ifdef ENOSR 124558542Seric case ENOSR: /* Out of streams resources */ 124658542Seric #endif 124758542Seric return TRUE; 124858542Seric } 124958542Seric 125058542Seric /* nope, must be permanent */ 125158542Seric return FALSE; 125258542Seric } 125358689Seric /* 125458689Seric ** LOCKFILE -- lock a file using flock or (shudder) lockf 125558689Seric ** 125658689Seric ** Parameters: 125758689Seric ** fd -- the file descriptor of the file. 125858689Seric ** filename -- the file name (for error messages). 125958689Seric ** type -- type of the lock. Bits can be: 126058689Seric ** LOCK_EX -- exclusive lock. 126158689Seric ** LOCK_NB -- non-blocking. 126258689Seric ** 126358689Seric ** Returns: 126458689Seric ** TRUE if the lock was acquired. 126558689Seric ** FALSE otherwise. 126658689Seric */ 126758689Seric 126858689Seric bool 126958689Seric lockfile(fd, filename, type) 127058689Seric int fd; 127158689Seric char *filename; 127258689Seric int type; 127358689Seric { 127458689Seric # ifdef LOCKF 127558689Seric int action; 127658689Seric struct flock lfd; 127758689Seric 127858701Seric if (bitset(LOCK_EX, type)) 127958689Seric lfd.l_type = F_WRLCK; 128058689Seric else 128158689Seric lfd.l_type = F_RDLCK; 128258689Seric 128358689Seric if (bitset(LOCK_NB, type)) 128458689Seric action = F_SETLK; 128558689Seric else 128658689Seric action = F_SETLKW; 128758689Seric 128858689Seric lfd.l_whence = lfd.l_start = lfd.l_len = 0; 128958689Seric 129058689Seric if (fcntl(fd, action, &lfd) >= 0) 129158689Seric return TRUE; 129258689Seric 129358689Seric if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN)) 129458689Seric syserr("cannot lockf(%s)", filename); 129558689Seric # else 129658689Seric if (flock(fd, type) >= 0) 129758689Seric return TRUE; 129858689Seric 129958689Seric if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK) 130058689Seric syserr("cannot flock(%s)", filename); 130158689Seric # endif 130258689Seric return FALSE; 130358689Seric } 1304