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*57142Seric static char sccsid[] = "@(#)conf.c 5.47 (Berkeley) 12/16/92"; 1133728Sbostic #endif /* not lint */ 1222698Sdist 1314881Seric # include <sys/ioctl.h> 1424943Seric # include <sys/param.h> 1536928Sbostic # include <pwd.h> 163309Seric # include "sendmail.h" 1740980Sbostic # include "pathnames.h" 18404Seric 19294Seric /* 203309Seric ** CONF.C -- Sendmail Configuration Tables. 21294Seric ** 22294Seric ** Defines the configuration of this installation. 23294Seric ** 241388Seric ** Configuration Variables: 252897Seric ** HdrInfo -- a table describing well-known header fields. 262897Seric ** Each entry has the field name and some flags, 274147Seric ** which are described in sendmail.h. 284093Seric ** 294093Seric ** Notes: 304093Seric ** I have tried to put almost all the reasonable 314093Seric ** configuration information into the configuration 324093Seric ** file read at runtime. My intent is that anything 334093Seric ** here is a function of the version of UNIX you 344093Seric ** are running, or is really static -- for example 354093Seric ** the headers are a superset of widely used 364093Seric ** protocols. If you find yourself playing with 374093Seric ** this file too much, you may be making a mistake! 38294Seric */ 39294Seric 40294Seric 41294Seric 42294Seric 434437Seric /* 442897Seric ** Header info table 453057Seric ** Final (null) entry contains the flags used for any other field. 464147Seric ** 474147Seric ** Not all of these are actually handled specially by sendmail 484147Seric ** at this time. They are included as placeholders, to let 494147Seric ** you know that "someday" I intend to have sendmail do 504147Seric ** something with them. 512897Seric */ 522897Seric 532897Seric struct hdrinfo HdrInfo[] = 542897Seric { 558060Seric /* originator fields, most to least significant */ 5611417Seric "resent-sender", H_FROM|H_RESENT, 5711417Seric "resent-from", H_FROM|H_RESENT, 5825686Seric "resent-reply-to", H_FROM|H_RESENT, 599055Seric "sender", H_FROM, 609055Seric "from", H_FROM, 6125686Seric "reply-to", H_FROM, 629055Seric "full-name", H_ACHECK, 639055Seric "return-receipt-to", H_FROM, 649055Seric "errors-to", H_FROM, 658060Seric /* destination fields */ 669055Seric "to", H_RCPT, 6711417Seric "resent-to", H_RCPT|H_RESENT, 689055Seric "cc", H_RCPT, 6911417Seric "resent-cc", H_RCPT|H_RESENT, 709055Seric "bcc", H_RCPT|H_ACHECK, 7111417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 7256215Seric "apparently-to", H_RCPT, 738060Seric /* message identification and control */ 7411417Seric "message-id", 0, 7511417Seric "resent-message-id", H_RESENT, 769055Seric "message", H_EOH, 779055Seric "text", H_EOH, 7811417Seric /* date fields */ 7911417Seric "date", 0, 8011417Seric "resent-date", H_RESENT, 818060Seric /* trace fields */ 829055Seric "received", H_TRACE|H_FORCE, 839055Seric "via", H_TRACE|H_FORCE, 849055Seric "mail-from", H_TRACE|H_FORCE, 858060Seric 869055Seric NULL, 0, 872897Seric }; 884166Seric 894166Seric 904166Seric /* 914166Seric ** ARPANET error message numbers. 924166Seric */ 934166Seric 947956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 957956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 967956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 977956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 984282Seric 994282Seric 1004282Seric 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 */ 1079039Seric 1089064Seric 1099064Seric 1109039Seric /* 11124943Seric ** Miscellaneous stuff. 1129039Seric */ 1139039Seric 11424943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 11524943Seric /* 11624943Seric ** SETDEFAULTS -- set default values 11724943Seric ** 11824943Seric ** Because of the way freezing is done, these must be initialized 11924943Seric ** using direct code. 12024943Seric ** 12124943Seric ** Parameters: 12224943Seric ** none. 12324943Seric ** 12424943Seric ** Returns: 12524943Seric ** none. 12624943Seric ** 12724943Seric ** Side Effects: 12824943Seric ** Initializes a bunch of global variables to their 12924943Seric ** default values. 13024943Seric */ 13124943Seric 13224943Seric setdefaults() 13324943Seric { 13424943Seric QueueLA = 8; 13524943Seric QueueFactor = 10000; 13624943Seric RefuseLA = 12; 13724943Seric SpaceSub = ' '; 13824981Seric WkRecipFact = 1000; 13924981Seric WkClassFact = 1800; 14025812Seric WkTimeFact = 9000; 141*57142Seric FileMode = (getuid() != geteuid()) ? 0644 : 0600; 14224981Seric DefUid = 1; 14324981Seric DefGid = 1; 14447284Seric CheckpointInterval = 10; 145*57142Seric MaxHopCount = 17; 14652105Seric SendMode = SM_FORK; 14752105Seric ErrorMode = EM_PRINT; 14852106Seric EightBit = FALSE; 14954967Seric MaxMciCache = 1; 15054967Seric MciCacheTimeout = 300; 15140973Sbostic setdefuser(); 15253654Seric setupmaps(); 15324943Seric } 154294Seric 15540973Sbostic 1564326Seric /* 15740973Sbostic ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 15840973Sbostic */ 15940973Sbostic 16040973Sbostic setdefuser() 16140973Sbostic { 16240973Sbostic struct passwd *defpwent; 16340973Sbostic 16440973Sbostic if (DefUser != NULL) 16540973Sbostic free(DefUser); 16640973Sbostic if ((defpwent = getpwuid(DefUid)) != NULL) 16740973Sbostic DefUser = newstr(defpwent->pw_name); 16840973Sbostic else 16940973Sbostic DefUser = newstr("nobody"); 17040973Sbostic } 17153654Seric /* 17253654Seric ** SETUPMAPS -- set up map classes 17353654Seric ** 17453654Seric ** Since these are compiled in, they cannot be in the config file. 17553654Seric ** 17653654Seric */ 17740973Sbostic 17853654Seric setupmaps() 17953654Seric { 18053654Seric register STAB *s; 18156836Seric extern bool host_map_init(); 18253654Seric extern char *maphostname(); 18340973Sbostic 18453654Seric /* set up host name lookup map */ 18553654Seric s = stab("host", ST_MAPCLASS, ST_ENTER); 18656836Seric s->s_mapclass.map_init = host_map_init; 18753654Seric s->s_mapclass.map_lookup = maphostname; 18853654Seric 18953654Seric /* 19053654Seric ** Set up other map classes. 19153654Seric */ 19253654Seric 19353654Seric # ifdef DBM_MAP 19453654Seric /* dbm file access */ 19553654Seric { 19656836Seric extern bool dbm_map_init(); 19753654Seric extern char *dbm_map_lookup(); 19853654Seric 19953654Seric s = stab("dbm", ST_MAPCLASS, ST_ENTER); 20053654Seric s->s_mapclass.map_init = dbm_map_init; 20153654Seric s->s_mapclass.map_lookup = dbm_map_lookup; 20253654Seric } 20353654Seric # endif 20453654Seric 20553654Seric # ifdef BTREE_MAP 20653654Seric /* new database file access -- btree files */ 20753654Seric { 20856823Seric extern bool bt_map_init(); 20956823Seric extern char *db_map_lookup(); 21053654Seric 21153654Seric s = stab("btree", ST_MAPCLASS, ST_ENTER); 21253654Seric s->s_mapclass.map_init = bt_map_init; 21356823Seric s->s_mapclass.map_lookup = db_map_lookup; 21453654Seric } 21553654Seric # endif 21653654Seric 21753654Seric # ifdef HASH_MAP 21853654Seric /* new database file access -- hash files */ 21953654Seric { 22056823Seric extern bool hash_map_init(); 22156823Seric extern char *db_map_lookup(); 22253654Seric 22353654Seric s = stab("hash", ST_MAPCLASS, ST_ENTER); 22453654Seric s->s_mapclass.map_init = hash_map_init; 22556823Seric s->s_mapclass.map_lookup = db_map_lookup; 22653654Seric } 22753654Seric # endif 22853654Seric 22953654Seric # ifdef USERDB_MAP 23053654Seric /* user database */ 23153654Seric { 23256836Seric extern bool udb_map_init(); 23353654Seric extern char *udb_map_lookup(); 23453654Seric 23553654Seric s = stab("udb", ST_MAPCLASS, ST_ENTER); 23653654Seric s->s_mapclass.map_init = udb_map_init; 23753654Seric s->s_mapclass.map_lookup = udb_map_lookup; 23853654Seric } 23953654Seric # endif 24053654Seric } 24153654Seric /* 24256836Seric ** HOST_MAP_INIT -- initialize host class structures 24356836Seric */ 24456836Seric 24556836Seric bool 24656836Seric host_map_init(map, mapname, args) 24756836Seric MAP *map; 24856836Seric char *mapname; 24956836Seric char *args; 25056836Seric { 25156836Seric register char *p = args; 25256836Seric 25356836Seric for (;;) 25456836Seric { 25556836Seric while (isspace(*p)) 25656836Seric p++; 25756836Seric if (*p != '-') 25856836Seric break; 25956836Seric switch (*++p) 26056836Seric { 26156836Seric case 'a': 26256836Seric map->map_app = ++p; 26356836Seric break; 26456836Seric } 26556836Seric while (*p != '\0' && !isspace(*p)) 26656836Seric p++; 26756836Seric if (*p != '\0') 26856836Seric *p++ = '\0'; 26956836Seric } 27056836Seric if (map->map_app != NULL) 27156836Seric map->map_app = newstr(map->map_app); 27256836Seric return TRUE; 27356836Seric } 27456836Seric 27556836Seric /* 2764326Seric ** GETRUID -- get real user id (V7) 2774326Seric */ 2784326Seric 2794326Seric getruid() 2804326Seric { 2819274Seric if (OpMode == MD_DAEMON) 2824536Seric return (RealUid); 2834536Seric else 2844536Seric return (getuid()); 2854326Seric } 2864326Seric 2874326Seric 2884326Seric /* 2894326Seric ** GETRGID -- get real group id (V7). 2904326Seric */ 2914326Seric 2924326Seric getrgid() 2934326Seric { 2949274Seric if (OpMode == MD_DAEMON) 2954536Seric return (RealGid); 2964536Seric else 2974536Seric return (getgid()); 2984326Seric } 29953654Seric /* 3009369Seric ** USERNAME -- return the user id of the logged in user. 3019369Seric ** 3029369Seric ** Parameters: 3039369Seric ** none. 3049369Seric ** 3059369Seric ** Returns: 3069369Seric ** The login name of the logged in user. 3079369Seric ** 3089369Seric ** Side Effects: 3099369Seric ** none. 3109369Seric ** 3119369Seric ** Notes: 3129369Seric ** The return value is statically allocated. 3139369Seric */ 3149369Seric 3159369Seric char * 3169369Seric username() 3179369Seric { 31817469Seric static char *myname = NULL; 3199369Seric extern char *getlogin(); 32019904Smiriam register struct passwd *pw; 3219369Seric 32217469Seric /* cache the result */ 32317469Seric if (myname == NULL) 32417469Seric { 32517469Seric myname = getlogin(); 32617469Seric if (myname == NULL || myname[0] == '\0') 32717469Seric { 32817469Seric 32917469Seric pw = getpwuid(getruid()); 33017469Seric if (pw != NULL) 33140993Sbostic myname = newstr(pw->pw_name); 33217469Seric } 33319904Smiriam else 33419904Smiriam { 33519873Smiriam 33640993Sbostic myname = newstr(myname); 33740993Sbostic if ((pw = getpwnam(myname)) == NULL || 33840993Sbostic getuid() != pw->pw_uid) 33919904Smiriam { 34019873Smiriam pw = getpwuid(getuid()); 34124945Seric if (pw != NULL) 34240993Sbostic myname = newstr(pw->pw_name); 34319873Smiriam } 34419873Smiriam } 34517469Seric if (myname == NULL || myname[0] == '\0') 34617469Seric { 34717469Seric syserr("Who are you?"); 34817469Seric myname = "postmaster"; 34917469Seric } 35017469Seric } 35117469Seric 35217469Seric return (myname); 3539369Seric } 3549369Seric /* 3554190Seric ** TTYPATH -- Get the path of the user's tty 356294Seric ** 357294Seric ** Returns the pathname of the user's tty. Returns NULL if 358294Seric ** the user is not logged in or if s/he has write permission 359294Seric ** denied. 360294Seric ** 361294Seric ** Parameters: 362294Seric ** none 363294Seric ** 364294Seric ** Returns: 365294Seric ** pathname of the user's tty. 366294Seric ** NULL if not logged in or write permission denied. 367294Seric ** 368294Seric ** Side Effects: 369294Seric ** none. 370294Seric ** 371294Seric ** WARNING: 372294Seric ** Return value is in a local buffer. 373294Seric ** 374294Seric ** Called By: 375294Seric ** savemail 376294Seric */ 377294Seric 378294Seric # include <sys/stat.h> 379294Seric 380294Seric char * 381294Seric ttypath() 382294Seric { 383294Seric struct stat stbuf; 384294Seric register char *pathn; 385294Seric extern char *ttyname(); 3864081Seric extern char *getlogin(); 387294Seric 388294Seric /* compute the pathname of the controlling tty */ 3899369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 3909369Seric (pathn = ttyname(0)) == NULL) 391294Seric { 392294Seric errno = 0; 393294Seric return (NULL); 394294Seric } 395294Seric 396294Seric /* see if we have write permission */ 3972967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 398294Seric { 399294Seric errno = 0; 400294Seric return (NULL); 401294Seric } 402294Seric 403294Seric /* see if the user is logged in */ 404294Seric if (getlogin() == NULL) 405294Seric return (NULL); 406294Seric 407294Seric /* looks good */ 408294Seric return (pathn); 409294Seric } 4102967Seric /* 4112967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4122967Seric ** 4132967Seric ** This routine can be supplied on a per-installation basis 4142967Seric ** to determine whether a person is allowed to send a message. 4152967Seric ** This allows restriction of certain types of internet 4162967Seric ** forwarding or registration of users. 4172967Seric ** 4182967Seric ** If the hosts are found to be incompatible, an error 4192967Seric ** message should be given using "usrerr" and FALSE should 4202967Seric ** be returned. 4212967Seric ** 4224288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4234288Seric ** function; this should be done on huge messages. 4244288Seric ** 4252967Seric ** Parameters: 4262967Seric ** to -- the person being sent to. 4272967Seric ** 4282967Seric ** Returns: 4292967Seric ** TRUE -- ok to send. 4302967Seric ** FALSE -- not ok. 4312967Seric ** 4322967Seric ** Side Effects: 4332967Seric ** none (unless you include the usrerr stuff) 4342967Seric */ 4352967Seric 4362967Seric bool 43755012Seric checkcompat(to, e) 4382967Seric register ADDRESS *to; 43955012Seric register ENVELOPE *e; 4402967Seric { 44112133Seric # ifdef lint 44212133Seric if (to == NULL) 44312133Seric to++; 44412133Seric # endif lint 44510698Seric # ifdef EXAMPLE_CODE 44610698Seric /* this code is intended as an example only */ 4474437Seric register STAB *s; 4484437Seric 4494437Seric s = stab("arpa", ST_MAILER, ST_FIND); 45055012Seric if (s != NULL && e->e_from.q_mailer != LocalMailer && 4519369Seric to->q_mailer == s->s_mailer) 4524437Seric { 4534437Seric usrerr("No ARPA mail through this machine: see your system administration"); 45410698Seric /* NoReturn = TRUE; to supress return copy */ 4554437Seric return (FALSE); 4564437Seric } 45756795Seric # endif /* EXAMPLE_CODE */ 4582967Seric return (TRUE); 4592967Seric } 4609369Seric /* 4619369Seric ** HOLDSIGS -- arrange to hold all signals 4629369Seric ** 4639369Seric ** Parameters: 4649369Seric ** none. 4659369Seric ** 4669369Seric ** Returns: 4679369Seric ** none. 4689369Seric ** 4699369Seric ** Side Effects: 4709369Seric ** Arranges that signals are held. 4719369Seric */ 4729369Seric 4739369Seric holdsigs() 4749369Seric { 4759369Seric } 4769369Seric /* 4779369Seric ** RLSESIGS -- arrange to release all signals 4789369Seric ** 4799369Seric ** This undoes the effect of holdsigs. 4809369Seric ** 4819369Seric ** Parameters: 4829369Seric ** none. 4839369Seric ** 4849369Seric ** Returns: 4859369Seric ** none. 4869369Seric ** 4879369Seric ** Side Effects: 4889369Seric ** Arranges that signals are released. 4899369Seric */ 4909369Seric 4919369Seric rlsesigs() 4929369Seric { 4939369Seric } 49414872Seric /* 49514872Seric ** GETLA -- get the current load average 49614872Seric ** 49714881Seric ** This code stolen from la.c. 49814881Seric ** 49914872Seric ** Parameters: 50014872Seric ** none. 50114872Seric ** 50214872Seric ** Returns: 50314872Seric ** The current load average as an integer. 50414872Seric ** 50514872Seric ** Side Effects: 50614872Seric ** none. 50714872Seric */ 50814872Seric 50951920Seric /* try to guess what style of load average we have */ 51051920Seric #define LA_ZERO 1 /* always return load average as zero */ 51151920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 51251920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 51351920Seric #define LA_SUBR 4 /* call getloadavg */ 51414872Seric 51551920Seric #ifndef LA_TYPE 51651920Seric # if defined(sun) 51751920Seric # define LA_TYPE LA_INT 51851920Seric # endif 51951920Seric # if defined(mips) 52051920Seric /* Ultrix or RISC/os */ 52151920Seric # define LA_TYPE LA_INT 52251920Seric # define LA_AVENRUN "avenrun" 52351920Seric # endif 52451920Seric # if defined(hpux) 52551920Seric # define LA_TYPE LA_FLOAT 52651920Seric # endif 52751920Seric # if defined(BSD) 52851920Seric # define LA_TYPE LA_SUBR 52951920Seric # endif 53051920Seric 53151920Seric # ifndef LA_TYPE 53251920Seric # define LA_TYPE LA_ZERO 53351920Seric # endif 53451920Seric #endif 53551920Seric 53651920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 53751920Seric 53814872Seric #include <nlist.h> 53951920Seric #include <fcntl.h> 54014872Seric 54151920Seric #ifndef LA_AVENRUN 54251920Seric #define LA_AVENRUN "_avenrun" 54351920Seric #endif 54451920Seric 54551920Seric /* _PATH_UNIX should be defined in <paths.h> */ 54651920Seric #ifndef _PATH_UNIX 54751920Seric # if defined(hpux) 54851920Seric # define _PATH_UNIX "/hp-ux" 54951920Seric # endif 55051920Seric # if defined(mips) && !defined(ultrix) 55151920Seric /* powerful RISC/os */ 55251920Seric # define _PATH_UNIX "/unix" 55351920Seric # endif 55451920Seric # ifndef _PATH_UNIX 55551920Seric # define _PATH_UNIX "/vmunix" 55651920Seric # endif 55751920Seric #endif 55851920Seric 55914872Seric struct nlist Nl[] = 56014872Seric { 56151920Seric { LA_AVENRUN }, 56214872Seric #define X_AVENRUN 0 56314872Seric { 0 }, 56414872Seric }; 56514872Seric 56651920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 56751920Seric # define FSHIFT 8 56851920Seric # define FSCALE (1 << FSHIFT) 56951920Seric #endif 57040930Srick 57114872Seric getla() 57214872Seric { 57314872Seric static int kmem = -1; 57451920Seric #if LA_TYPE == LA_INT 57524943Seric long avenrun[3]; 57651920Seric #else 57751920Seric double avenrun[3]; 57851920Seric #endif 57925615Seric extern off_t lseek(); 58014872Seric 58114872Seric if (kmem < 0) 58214872Seric { 58324945Seric kmem = open("/dev/kmem", 0, 0); 58414872Seric if (kmem < 0) 58514872Seric return (-1); 58651920Seric (void) fcntl(kmem, F_SETFD, 1); 58751920Seric nlist(_PATH_UNIX, Nl); 58814872Seric if (Nl[0].n_type == 0) 58914872Seric return (-1); 59014872Seric } 59124945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 59223118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 59319967Seric { 59419967Seric /* thank you Ian */ 59519967Seric return (-1); 59619967Seric } 59751920Seric #if LA_TYPE == LA_INT 59824943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 59951920Seric #else 60051920Seric return ((int) (avenrun[0] + 0.5)); 60151920Seric #endif 60214872Seric } 60314872Seric 60451773Seric #else 60551920Seric #if LA_TYPE == LA_SUBR 60651773Seric 60751773Seric getla() 60851773Seric { 60951920Seric double avenrun[3]; 61051920Seric 61151920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 61251920Seric return (-1); 61351920Seric return ((int) (avenrun[0] + 0.5)); 61451773Seric } 61551773Seric 61651773Seric #else 61751773Seric 61851773Seric getla() 61951773Seric { 62051920Seric return (0); 62151773Seric } 62251773Seric 62351773Seric #endif 62451773Seric #endif 62524943Seric /* 62624943Seric ** SHOULDQUEUE -- should this message be queued or sent? 62724943Seric ** 62824943Seric ** Compares the message cost to the load average to decide. 62924943Seric ** 63024943Seric ** Parameters: 63124943Seric ** pri -- the priority of the message in question. 63224943Seric ** 63324943Seric ** Returns: 63424943Seric ** TRUE -- if this message should be queued up for the 63524943Seric ** time being. 63624943Seric ** FALSE -- if the load is low enough to send this message. 63724943Seric ** 63824943Seric ** Side Effects: 63924943Seric ** none. 64024943Seric */ 64124943Seric 64224943Seric bool 64324943Seric shouldqueue(pri) 64424943Seric long pri; 64524943Seric { 64651920Seric if (CurrentLA < QueueLA) 64724943Seric return (FALSE); 64851920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 64924943Seric } 65024943Seric /* 65153037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 65253037Seric ** 65353037Seric ** Parameters: 65453037Seric ** none. 65553037Seric ** 65653037Seric ** Returns: 65753037Seric ** TRUE if incoming SMTP connections should be refused 65853037Seric ** (for now). 65953037Seric ** FALSE if we should accept new work. 66053037Seric ** 66153037Seric ** Side Effects: 66253037Seric ** none. 66353037Seric */ 66453037Seric 66553037Seric bool 66653037Seric refuseconnections() 66753037Seric { 66853037Seric /* this is probably too simplistic */ 66953037Seric return (CurrentLA > RefuseLA); 67053037Seric } 67153037Seric /* 67224943Seric ** SETPROCTITLE -- set process title for ps 67324943Seric ** 67424943Seric ** Parameters: 67524943Seric ** fmt -- a printf style format string. 67624943Seric ** a, b, c -- possible parameters to fmt. 67724943Seric ** 67824943Seric ** Returns: 67924943Seric ** none. 68024943Seric ** 68124943Seric ** Side Effects: 68224943Seric ** Clobbers argv of our main procedure so ps(1) will 68324943Seric ** display the title. 68424943Seric */ 68524943Seric 68624943Seric /*VARARGS1*/ 68756852Seric setproctitle(fmt VA_ARG_FORMAL) 68824943Seric char *fmt; 68956852Seric VA_ARG_DECL 69024943Seric { 69124943Seric # ifdef SETPROCTITLE 69224943Seric register char *p; 69325049Seric register int i; 69456852Seric char buf[MAXLINE]; 69556852Seric VA_LOCAL_DECL 69624943Seric extern char **Argv; 69724943Seric extern char *LastArgv; 69824943Seric 69954996Seric p = buf; 70024943Seric 70154996Seric /* print sendmail: heading for grep */ 70254996Seric (void) strcpy(p, "sendmail: "); 70354996Seric p += strlen(p); 70424943Seric 70554996Seric /* print the argument string */ 70656852Seric VA_START(fmt); 70756852Seric (void) vsprintf(p, fmt, ap); 70856852Seric VA_END; 70954996Seric 71025049Seric i = strlen(buf); 71154996Seric if (i > LastArgv - Argv[0] - 2) 71225049Seric { 71354996Seric i = LastArgv - Argv[0] - 2; 71425049Seric buf[i] = '\0'; 71525049Seric } 71654996Seric (void) strcpy(Argv[0], buf); 71754997Seric p = &Argv[0][i]; 71824943Seric while (p < LastArgv) 71924943Seric *p++ = ' '; 72056795Seric # endif /* SETPROCTITLE */ 72124943Seric } 72225698Seric /* 72325698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 72425698Seric ** 72525698Seric ** Parameters: 72625698Seric ** none. 72725698Seric ** 72825698Seric ** Returns: 72925698Seric ** none. 73025698Seric ** 73125698Seric ** Side Effects: 73225698Seric ** Picks up extant zombies. 73325698Seric */ 73425698Seric 73525698Seric # include <sys/wait.h> 73625698Seric 73746928Sbostic void 73825698Seric reapchild() 73925698Seric { 74025698Seric # ifdef WNOHANG 74125698Seric union wait status; 74225698Seric 74346928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 74425698Seric continue; 74556795Seric # else /* WNOHANG */ 74625698Seric auto int status; 74725698Seric 74846928Sbostic while (wait((int *)&status) > 0) 74925698Seric continue; 75056795Seric # endif /* WNOHANG */ 75125698Seric } 75255418Seric /* 75355418Seric ** UNSETENV -- remove a variable from the environment 75455418Seric ** 75555418Seric ** Not needed on newer systems. 75655418Seric ** 75755418Seric ** Parameters: 75855418Seric ** name -- the string name of the environment variable to be 75955418Seric ** deleted from the current environment. 76055418Seric ** 76155418Seric ** Returns: 76255418Seric ** none. 76355418Seric ** 76455418Seric ** Globals: 76555418Seric ** environ -- a pointer to the current environment. 76655418Seric ** 76755418Seric ** Side Effects: 76855418Seric ** Modifies environ. 76955418Seric */ 77055418Seric 77155418Seric #ifdef UNSETENV 77255418Seric 77355418Seric void 77455418Seric unsetenv(name) 77555418Seric char *name; 77655418Seric { 77755418Seric extern char **environ; 77855418Seric register char **pp; 77955418Seric int len = strlen(name); 78055418Seric 78155418Seric for (pp = environ; *pp != NULL; pp++) 78255418Seric { 78355418Seric if (strncmp(name, *pp, len) == 0 && 78455418Seric ((*pp)[len] == '=' || (*pp)[len] == '\0')) 78555418Seric break; 78655418Seric } 78755418Seric 78855418Seric for (; *pp != NULL; pp++) 78955418Seric *pp = pp[1]; 79055418Seric } 79155418Seric 79255418Seric #endif /* UNSETENV */ 79356215Seric /* 79456215Seric ** GETDTABLESIZE -- return number of file descriptors 79556215Seric ** 79656215Seric ** Only on non-BSD systems 79756215Seric ** 79856215Seric ** Parameters: 79956215Seric ** none 80056215Seric ** 80156215Seric ** Returns: 80256215Seric ** size of file descriptor table 80356215Seric ** 80456215Seric ** Side Effects: 80556215Seric ** none 80656215Seric */ 80756215Seric 80856215Seric #ifdef SYSTEM5 80956215Seric 81056215Seric int 81156215Seric getdtablesize() 81256215Seric { 81356215Seric return NOFILE; 81456215Seric } 81556215Seric 81656215Seric #endif 817