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*56823Seric static char sccsid[] = "@(#)conf.c 5.44 (Berkeley) 11/15/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; 14124981Seric FileMode = 0644; 14224981Seric DefUid = 1; 14324981Seric DefGid = 1; 14447284Seric CheckpointInterval = 10; 14551305Seric MaxHopCount = MAXHOP; 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; 18153654Seric MAPCLASS *hostmapclass; 18253654Seric extern char *maphostname(); 18340973Sbostic 18453654Seric /* set up host name lookup map */ 18553654Seric s = stab("host", ST_MAPCLASS, ST_ENTER); 18653654Seric s->s_mapclass.map_init = NULL; 18753654Seric s->s_mapclass.map_lookup = maphostname; 18853654Seric hostmapclass = &s->s_mapclass; 18953654Seric 19053654Seric s = stab("host", ST_MAP, ST_ENTER); 19153654Seric s->s_map.map_class = hostmapclass; 19253654Seric s->s_map.map_flags = MF_VALID; 19353654Seric 19453654Seric /* 19553654Seric ** Set up other map classes. 19653654Seric */ 19753654Seric 19853654Seric # ifdef DBM_MAP 19953654Seric /* dbm file access */ 20053654Seric { 20153654Seric extern void dbm_map_init(); 20253654Seric extern char *dbm_map_lookup(); 20353654Seric 20453654Seric s = stab("dbm", ST_MAPCLASS, ST_ENTER); 20553654Seric s->s_mapclass.map_init = dbm_map_init; 20653654Seric s->s_mapclass.map_lookup = dbm_map_lookup; 20753654Seric } 20853654Seric # endif 20953654Seric 21053654Seric # ifdef BTREE_MAP 21153654Seric /* new database file access -- btree files */ 21253654Seric { 213*56823Seric extern bool bt_map_init(); 214*56823Seric extern char *db_map_lookup(); 21553654Seric 21653654Seric s = stab("btree", ST_MAPCLASS, ST_ENTER); 21753654Seric s->s_mapclass.map_init = bt_map_init; 218*56823Seric s->s_mapclass.map_lookup = db_map_lookup; 21953654Seric } 22053654Seric # endif 22153654Seric 22253654Seric # ifdef HASH_MAP 22353654Seric /* new database file access -- hash files */ 22453654Seric { 225*56823Seric extern bool hash_map_init(); 226*56823Seric extern char *db_map_lookup(); 22753654Seric 22853654Seric s = stab("hash", ST_MAPCLASS, ST_ENTER); 22953654Seric s->s_mapclass.map_init = hash_map_init; 230*56823Seric s->s_mapclass.map_lookup = db_map_lookup; 23153654Seric } 23253654Seric # endif 23353654Seric 23453654Seric # ifdef USERDB_MAP 23553654Seric /* user database */ 23653654Seric { 23753654Seric extern void udb_map_init(); 23853654Seric extern char *udb_map_lookup(); 23953654Seric 24053654Seric s = stab("udb", ST_MAPCLASS, ST_ENTER); 24153654Seric s->s_mapclass.map_init = udb_map_init; 24253654Seric s->s_mapclass.map_lookup = udb_map_lookup; 24353654Seric } 24453654Seric # endif 24553654Seric } 24653654Seric /* 2474326Seric ** GETRUID -- get real user id (V7) 2484326Seric */ 2494326Seric 2504326Seric getruid() 2514326Seric { 2529274Seric if (OpMode == MD_DAEMON) 2534536Seric return (RealUid); 2544536Seric else 2554536Seric return (getuid()); 2564326Seric } 2574326Seric 2584326Seric 2594326Seric /* 2604326Seric ** GETRGID -- get real group id (V7). 2614326Seric */ 2624326Seric 2634326Seric getrgid() 2644326Seric { 2659274Seric if (OpMode == MD_DAEMON) 2664536Seric return (RealGid); 2674536Seric else 2684536Seric return (getgid()); 2694326Seric } 27053654Seric /* 2719369Seric ** USERNAME -- return the user id of the logged in user. 2729369Seric ** 2739369Seric ** Parameters: 2749369Seric ** none. 2759369Seric ** 2769369Seric ** Returns: 2779369Seric ** The login name of the logged in user. 2789369Seric ** 2799369Seric ** Side Effects: 2809369Seric ** none. 2819369Seric ** 2829369Seric ** Notes: 2839369Seric ** The return value is statically allocated. 2849369Seric */ 2859369Seric 2869369Seric char * 2879369Seric username() 2889369Seric { 28917469Seric static char *myname = NULL; 2909369Seric extern char *getlogin(); 29119904Smiriam register struct passwd *pw; 2929369Seric 29317469Seric /* cache the result */ 29417469Seric if (myname == NULL) 29517469Seric { 29617469Seric myname = getlogin(); 29717469Seric if (myname == NULL || myname[0] == '\0') 29817469Seric { 29917469Seric 30017469Seric pw = getpwuid(getruid()); 30117469Seric if (pw != NULL) 30240993Sbostic myname = newstr(pw->pw_name); 30317469Seric } 30419904Smiriam else 30519904Smiriam { 30619873Smiriam 30740993Sbostic myname = newstr(myname); 30840993Sbostic if ((pw = getpwnam(myname)) == NULL || 30940993Sbostic getuid() != pw->pw_uid) 31019904Smiriam { 31119873Smiriam pw = getpwuid(getuid()); 31224945Seric if (pw != NULL) 31340993Sbostic myname = newstr(pw->pw_name); 31419873Smiriam } 31519873Smiriam } 31617469Seric if (myname == NULL || myname[0] == '\0') 31717469Seric { 31817469Seric syserr("Who are you?"); 31917469Seric myname = "postmaster"; 32017469Seric } 32117469Seric } 32217469Seric 32317469Seric return (myname); 3249369Seric } 3259369Seric /* 3264190Seric ** TTYPATH -- Get the path of the user's tty 327294Seric ** 328294Seric ** Returns the pathname of the user's tty. Returns NULL if 329294Seric ** the user is not logged in or if s/he has write permission 330294Seric ** denied. 331294Seric ** 332294Seric ** Parameters: 333294Seric ** none 334294Seric ** 335294Seric ** Returns: 336294Seric ** pathname of the user's tty. 337294Seric ** NULL if not logged in or write permission denied. 338294Seric ** 339294Seric ** Side Effects: 340294Seric ** none. 341294Seric ** 342294Seric ** WARNING: 343294Seric ** Return value is in a local buffer. 344294Seric ** 345294Seric ** Called By: 346294Seric ** savemail 347294Seric */ 348294Seric 349294Seric # include <sys/stat.h> 350294Seric 351294Seric char * 352294Seric ttypath() 353294Seric { 354294Seric struct stat stbuf; 355294Seric register char *pathn; 356294Seric extern char *ttyname(); 3574081Seric extern char *getlogin(); 358294Seric 359294Seric /* compute the pathname of the controlling tty */ 3609369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 3619369Seric (pathn = ttyname(0)) == NULL) 362294Seric { 363294Seric errno = 0; 364294Seric return (NULL); 365294Seric } 366294Seric 367294Seric /* see if we have write permission */ 3682967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 369294Seric { 370294Seric errno = 0; 371294Seric return (NULL); 372294Seric } 373294Seric 374294Seric /* see if the user is logged in */ 375294Seric if (getlogin() == NULL) 376294Seric return (NULL); 377294Seric 378294Seric /* looks good */ 379294Seric return (pathn); 380294Seric } 3812967Seric /* 3822967Seric ** CHECKCOMPAT -- check for From and To person compatible. 3832967Seric ** 3842967Seric ** This routine can be supplied on a per-installation basis 3852967Seric ** to determine whether a person is allowed to send a message. 3862967Seric ** This allows restriction of certain types of internet 3872967Seric ** forwarding or registration of users. 3882967Seric ** 3892967Seric ** If the hosts are found to be incompatible, an error 3902967Seric ** message should be given using "usrerr" and FALSE should 3912967Seric ** be returned. 3922967Seric ** 3934288Seric ** 'NoReturn' can be set to suppress the return-to-sender 3944288Seric ** function; this should be done on huge messages. 3954288Seric ** 3962967Seric ** Parameters: 3972967Seric ** to -- the person being sent to. 3982967Seric ** 3992967Seric ** Returns: 4002967Seric ** TRUE -- ok to send. 4012967Seric ** FALSE -- not ok. 4022967Seric ** 4032967Seric ** Side Effects: 4042967Seric ** none (unless you include the usrerr stuff) 4052967Seric */ 4062967Seric 4072967Seric bool 40855012Seric checkcompat(to, e) 4092967Seric register ADDRESS *to; 41055012Seric register ENVELOPE *e; 4112967Seric { 41212133Seric # ifdef lint 41312133Seric if (to == NULL) 41412133Seric to++; 41512133Seric # endif lint 41610698Seric # ifdef EXAMPLE_CODE 41710698Seric /* this code is intended as an example only */ 4184437Seric register STAB *s; 4194437Seric 4204437Seric s = stab("arpa", ST_MAILER, ST_FIND); 42155012Seric if (s != NULL && e->e_from.q_mailer != LocalMailer && 4229369Seric to->q_mailer == s->s_mailer) 4234437Seric { 4244437Seric usrerr("No ARPA mail through this machine: see your system administration"); 42510698Seric /* NoReturn = TRUE; to supress return copy */ 4264437Seric return (FALSE); 4274437Seric } 42856795Seric # endif /* EXAMPLE_CODE */ 4292967Seric return (TRUE); 4302967Seric } 4319369Seric /* 4329369Seric ** HOLDSIGS -- arrange to hold all signals 4339369Seric ** 4349369Seric ** Parameters: 4359369Seric ** none. 4369369Seric ** 4379369Seric ** Returns: 4389369Seric ** none. 4399369Seric ** 4409369Seric ** Side Effects: 4419369Seric ** Arranges that signals are held. 4429369Seric */ 4439369Seric 4449369Seric holdsigs() 4459369Seric { 4469369Seric } 4479369Seric /* 4489369Seric ** RLSESIGS -- arrange to release all signals 4499369Seric ** 4509369Seric ** This undoes the effect of holdsigs. 4519369Seric ** 4529369Seric ** Parameters: 4539369Seric ** none. 4549369Seric ** 4559369Seric ** Returns: 4569369Seric ** none. 4579369Seric ** 4589369Seric ** Side Effects: 4599369Seric ** Arranges that signals are released. 4609369Seric */ 4619369Seric 4629369Seric rlsesigs() 4639369Seric { 4649369Seric } 46514872Seric /* 46614872Seric ** GETLA -- get the current load average 46714872Seric ** 46814881Seric ** This code stolen from la.c. 46914881Seric ** 47014872Seric ** Parameters: 47114872Seric ** none. 47214872Seric ** 47314872Seric ** Returns: 47414872Seric ** The current load average as an integer. 47514872Seric ** 47614872Seric ** Side Effects: 47714872Seric ** none. 47814872Seric */ 47914872Seric 48051920Seric /* try to guess what style of load average we have */ 48151920Seric #define LA_ZERO 1 /* always return load average as zero */ 48251920Seric #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 48351920Seric #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 48451920Seric #define LA_SUBR 4 /* call getloadavg */ 48514872Seric 48651920Seric #ifndef LA_TYPE 48751920Seric # if defined(sun) 48851920Seric # define LA_TYPE LA_INT 48951920Seric # endif 49051920Seric # if defined(mips) 49151920Seric /* Ultrix or RISC/os */ 49251920Seric # define LA_TYPE LA_INT 49351920Seric # define LA_AVENRUN "avenrun" 49451920Seric # endif 49551920Seric # if defined(hpux) 49651920Seric # define LA_TYPE LA_FLOAT 49751920Seric # endif 49851920Seric # if defined(BSD) 49951920Seric # define LA_TYPE LA_SUBR 50051920Seric # endif 50151920Seric 50251920Seric # ifndef LA_TYPE 50351920Seric # define LA_TYPE LA_ZERO 50451920Seric # endif 50551920Seric #endif 50651920Seric 50751920Seric #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 50851920Seric 50914872Seric #include <nlist.h> 51051920Seric #include <fcntl.h> 51114872Seric 51251920Seric #ifndef LA_AVENRUN 51351920Seric #define LA_AVENRUN "_avenrun" 51451920Seric #endif 51551920Seric 51651920Seric /* _PATH_UNIX should be defined in <paths.h> */ 51751920Seric #ifndef _PATH_UNIX 51851920Seric # if defined(hpux) 51951920Seric # define _PATH_UNIX "/hp-ux" 52051920Seric # endif 52151920Seric # if defined(mips) && !defined(ultrix) 52251920Seric /* powerful RISC/os */ 52351920Seric # define _PATH_UNIX "/unix" 52451920Seric # endif 52551920Seric # ifndef _PATH_UNIX 52651920Seric # define _PATH_UNIX "/vmunix" 52751920Seric # endif 52851920Seric #endif 52951920Seric 53014872Seric struct nlist Nl[] = 53114872Seric { 53251920Seric { LA_AVENRUN }, 53314872Seric #define X_AVENRUN 0 53414872Seric { 0 }, 53514872Seric }; 53614872Seric 53751920Seric #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 53851920Seric # define FSHIFT 8 53951920Seric # define FSCALE (1 << FSHIFT) 54051920Seric #endif 54140930Srick 54214872Seric getla() 54314872Seric { 54414872Seric static int kmem = -1; 54551920Seric #if LA_TYPE == LA_INT 54624943Seric long avenrun[3]; 54751920Seric #else 54851920Seric double avenrun[3]; 54951920Seric #endif 55025615Seric extern off_t lseek(); 55114872Seric 55214872Seric if (kmem < 0) 55314872Seric { 55424945Seric kmem = open("/dev/kmem", 0, 0); 55514872Seric if (kmem < 0) 55614872Seric return (-1); 55751920Seric (void) fcntl(kmem, F_SETFD, 1); 55851920Seric nlist(_PATH_UNIX, Nl); 55914872Seric if (Nl[0].n_type == 0) 56014872Seric return (-1); 56114872Seric } 56224945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 56323118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 56419967Seric { 56519967Seric /* thank you Ian */ 56619967Seric return (-1); 56719967Seric } 56851920Seric #if LA_TYPE == LA_INT 56924943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 57051920Seric #else 57151920Seric return ((int) (avenrun[0] + 0.5)); 57251920Seric #endif 57314872Seric } 57414872Seric 57551773Seric #else 57651920Seric #if LA_TYPE == LA_SUBR 57751773Seric 57851773Seric getla() 57951773Seric { 58051920Seric double avenrun[3]; 58151920Seric 58251920Seric if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 58351920Seric return (-1); 58451920Seric return ((int) (avenrun[0] + 0.5)); 58551773Seric } 58651773Seric 58751773Seric #else 58851773Seric 58951773Seric getla() 59051773Seric { 59151920Seric return (0); 59251773Seric } 59351773Seric 59451773Seric #endif 59551773Seric #endif 59624943Seric /* 59724943Seric ** SHOULDQUEUE -- should this message be queued or sent? 59824943Seric ** 59924943Seric ** Compares the message cost to the load average to decide. 60024943Seric ** 60124943Seric ** Parameters: 60224943Seric ** pri -- the priority of the message in question. 60324943Seric ** 60424943Seric ** Returns: 60524943Seric ** TRUE -- if this message should be queued up for the 60624943Seric ** time being. 60724943Seric ** FALSE -- if the load is low enough to send this message. 60824943Seric ** 60924943Seric ** Side Effects: 61024943Seric ** none. 61124943Seric */ 61224943Seric 61324943Seric bool 61424943Seric shouldqueue(pri) 61524943Seric long pri; 61624943Seric { 61751920Seric if (CurrentLA < QueueLA) 61824943Seric return (FALSE); 61951920Seric return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 62024943Seric } 62124943Seric /* 62253037Seric ** REFUSECONNECTIONS -- decide if connections should be refused 62353037Seric ** 62453037Seric ** Parameters: 62553037Seric ** none. 62653037Seric ** 62753037Seric ** Returns: 62853037Seric ** TRUE if incoming SMTP connections should be refused 62953037Seric ** (for now). 63053037Seric ** FALSE if we should accept new work. 63153037Seric ** 63253037Seric ** Side Effects: 63353037Seric ** none. 63453037Seric */ 63553037Seric 63653037Seric bool 63753037Seric refuseconnections() 63853037Seric { 63953037Seric /* this is probably too simplistic */ 64053037Seric return (CurrentLA > RefuseLA); 64153037Seric } 64253037Seric /* 64324943Seric ** SETPROCTITLE -- set process title for ps 64424943Seric ** 64524943Seric ** Parameters: 64624943Seric ** fmt -- a printf style format string. 64724943Seric ** a, b, c -- possible parameters to fmt. 64824943Seric ** 64924943Seric ** Returns: 65024943Seric ** none. 65124943Seric ** 65224943Seric ** Side Effects: 65324943Seric ** Clobbers argv of our main procedure so ps(1) will 65424943Seric ** display the title. 65524943Seric */ 65624943Seric 65724943Seric /*VARARGS1*/ 65824943Seric setproctitle(fmt, a, b, c) 65924943Seric char *fmt; 66024943Seric { 66124943Seric # ifdef SETPROCTITLE 66224943Seric register char *p; 66325049Seric register int i; 66424943Seric extern char **Argv; 66524943Seric extern char *LastArgv; 66625049Seric char buf[MAXLINE]; 66724943Seric 66854996Seric p = buf; 66924943Seric 67054996Seric /* print sendmail: heading for grep */ 67154996Seric (void) strcpy(p, "sendmail: "); 67254996Seric p += strlen(p); 67324943Seric 67454996Seric /* print the argument string */ 67554996Seric (void) sprintf(p, fmt, a, b, c); 67654996Seric 67725049Seric i = strlen(buf); 67854996Seric if (i > LastArgv - Argv[0] - 2) 67925049Seric { 68054996Seric i = LastArgv - Argv[0] - 2; 68125049Seric buf[i] = '\0'; 68225049Seric } 68354996Seric (void) strcpy(Argv[0], buf); 68454997Seric p = &Argv[0][i]; 68524943Seric while (p < LastArgv) 68624943Seric *p++ = ' '; 68756795Seric # endif /* SETPROCTITLE */ 68824943Seric } 68925698Seric /* 69025698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 69125698Seric ** 69225698Seric ** Parameters: 69325698Seric ** none. 69425698Seric ** 69525698Seric ** Returns: 69625698Seric ** none. 69725698Seric ** 69825698Seric ** Side Effects: 69925698Seric ** Picks up extant zombies. 70025698Seric */ 70125698Seric 70225698Seric # include <sys/wait.h> 70325698Seric 70446928Sbostic void 70525698Seric reapchild() 70625698Seric { 70725698Seric # ifdef WNOHANG 70825698Seric union wait status; 70925698Seric 71046928Sbostic while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 71125698Seric continue; 71256795Seric # else /* WNOHANG */ 71325698Seric auto int status; 71425698Seric 71546928Sbostic while (wait((int *)&status) > 0) 71625698Seric continue; 71756795Seric # endif /* WNOHANG */ 71825698Seric } 71955418Seric /* 72055418Seric ** UNSETENV -- remove a variable from the environment 72155418Seric ** 72255418Seric ** Not needed on newer systems. 72355418Seric ** 72455418Seric ** Parameters: 72555418Seric ** name -- the string name of the environment variable to be 72655418Seric ** deleted from the current environment. 72755418Seric ** 72855418Seric ** Returns: 72955418Seric ** none. 73055418Seric ** 73155418Seric ** Globals: 73255418Seric ** environ -- a pointer to the current environment. 73355418Seric ** 73455418Seric ** Side Effects: 73555418Seric ** Modifies environ. 73655418Seric */ 73755418Seric 73855418Seric #ifdef UNSETENV 73955418Seric 74055418Seric void 74155418Seric unsetenv(name) 74255418Seric char *name; 74355418Seric { 74455418Seric extern char **environ; 74555418Seric register char **pp; 74655418Seric int len = strlen(name); 74755418Seric 74855418Seric for (pp = environ; *pp != NULL; pp++) 74955418Seric { 75055418Seric if (strncmp(name, *pp, len) == 0 && 75155418Seric ((*pp)[len] == '=' || (*pp)[len] == '\0')) 75255418Seric break; 75355418Seric } 75455418Seric 75555418Seric for (; *pp != NULL; pp++) 75655418Seric *pp = pp[1]; 75755418Seric } 75855418Seric 75955418Seric #endif /* UNSETENV */ 76056215Seric /* 76156215Seric ** GETDTABLESIZE -- return number of file descriptors 76256215Seric ** 76356215Seric ** Only on non-BSD systems 76456215Seric ** 76556215Seric ** Parameters: 76656215Seric ** none 76756215Seric ** 76856215Seric ** Returns: 76956215Seric ** size of file descriptor table 77056215Seric ** 77156215Seric ** Side Effects: 77256215Seric ** none 77356215Seric */ 77456215Seric 77556215Seric #ifdef SYSTEM5 77656215Seric 77756215Seric int 77856215Seric getdtablesize() 77956215Seric { 78056215Seric return NOFILE; 78156215Seric } 78256215Seric 78356215Seric #endif 784