122698Sdist /* 2*33728Sbostic * Copyright (c) 1988 Regents of the University of California. 3*33728Sbostic * All rights reserved. 4*33728Sbostic * 5*33728Sbostic * Redistribution and use in source and binary forms are permitted 6*33728Sbostic * provided that this notice is preserved and that due credit is given 7*33728Sbostic * to the University of California at Berkeley. The name of the University 8*33728Sbostic * may not be used to endorse or promote products derived from this 9*33728Sbostic * software without specific prior written permission. This software 10*33728Sbostic * is provided ``as is'' without express or implied warranty. 11*33728Sbostic * 12*33728Sbostic * Sendmail 13*33728Sbostic * Copyright (c) 1983 Eric P. Allman 14*33728Sbostic * Berkeley, California 15*33728Sbostic */ 1622698Sdist 1722698Sdist #ifndef lint 18*33728Sbostic static char sccsid[] = "@(#)conf.c 5.15 (Berkeley) 03/13/88"; 19*33728Sbostic #endif /* not lint */ 2022698Sdist 21294Seric # include <pwd.h> 2214881Seric # include <sys/ioctl.h> 2324943Seric # ifdef sun 2424943Seric # include <sys/param.h> 2524943Seric # endif sun 263309Seric # include "sendmail.h" 27404Seric 28294Seric /* 293309Seric ** CONF.C -- Sendmail Configuration Tables. 30294Seric ** 31294Seric ** Defines the configuration of this installation. 32294Seric ** 331388Seric ** Compilation Flags: 341388Seric ** V6 -- running on a version 6 system. This determines 351388Seric ** whether to define certain routines between 361388Seric ** the two systems. If you are running a funny 371388Seric ** system, e.g., V6 with long tty names, this 381388Seric ** should be checked carefully. 3914872Seric ** VMUNIX -- running on a Berkeley UNIX system. 40294Seric ** 411388Seric ** Configuration Variables: 422897Seric ** HdrInfo -- a table describing well-known header fields. 432897Seric ** Each entry has the field name and some flags, 444147Seric ** which are described in sendmail.h. 454093Seric ** 464093Seric ** Notes: 474093Seric ** I have tried to put almost all the reasonable 484093Seric ** configuration information into the configuration 494093Seric ** file read at runtime. My intent is that anything 504093Seric ** here is a function of the version of UNIX you 514093Seric ** are running, or is really static -- for example 524093Seric ** the headers are a superset of widely used 534093Seric ** protocols. If you find yourself playing with 544093Seric ** this file too much, you may be making a mistake! 55294Seric */ 56294Seric 57294Seric 58294Seric 59294Seric 604437Seric /* 612897Seric ** Header info table 623057Seric ** Final (null) entry contains the flags used for any other field. 634147Seric ** 644147Seric ** Not all of these are actually handled specially by sendmail 654147Seric ** at this time. They are included as placeholders, to let 664147Seric ** you know that "someday" I intend to have sendmail do 674147Seric ** something with them. 682897Seric */ 692897Seric 702897Seric struct hdrinfo HdrInfo[] = 712897Seric { 728060Seric /* originator fields, most to least significant */ 7311417Seric "resent-sender", H_FROM|H_RESENT, 7411417Seric "resent-from", H_FROM|H_RESENT, 7525686Seric "resent-reply-to", H_FROM|H_RESENT, 769055Seric "sender", H_FROM, 779055Seric "from", H_FROM, 7825686Seric "reply-to", H_FROM, 799055Seric "full-name", H_ACHECK, 809055Seric "return-receipt-to", H_FROM, 819055Seric "errors-to", H_FROM, 828060Seric /* destination fields */ 839055Seric "to", H_RCPT, 8411417Seric "resent-to", H_RCPT|H_RESENT, 859055Seric "cc", H_RCPT, 8611417Seric "resent-cc", H_RCPT|H_RESENT, 879055Seric "bcc", H_RCPT|H_ACHECK, 8811417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 898060Seric /* message identification and control */ 9011417Seric "message-id", 0, 9111417Seric "resent-message-id", H_RESENT, 929055Seric "message", H_EOH, 939055Seric "text", H_EOH, 9411417Seric /* date fields */ 9511417Seric "date", 0, 9611417Seric "resent-date", H_RESENT, 978060Seric /* trace fields */ 989055Seric "received", H_TRACE|H_FORCE, 999055Seric "via", H_TRACE|H_FORCE, 1009055Seric "mail-from", H_TRACE|H_FORCE, 1018060Seric 1029055Seric NULL, 0, 1032897Seric }; 1044166Seric 1054166Seric 1064166Seric /* 1074166Seric ** ARPANET error message numbers. 1084166Seric */ 1094166Seric 1107956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 1117956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 1127956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 1137956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 1144282Seric 1154282Seric 1164282Seric 1174282Seric /* 1184282Seric ** Location of system files/databases/etc. 1194282Seric */ 1204282Seric 1214282Seric char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ 1229064Seric char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ 1239039Seric 1249064Seric 1259064Seric 1269039Seric /* 12724943Seric ** Miscellaneous stuff. 1289039Seric */ 1299039Seric 13024943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 13124943Seric /* 13224943Seric ** SETDEFAULTS -- set default values 13324943Seric ** 13424943Seric ** Because of the way freezing is done, these must be initialized 13524943Seric ** using direct code. 13624943Seric ** 13724943Seric ** Parameters: 13824943Seric ** none. 13924943Seric ** 14024943Seric ** Returns: 14124943Seric ** none. 14224943Seric ** 14324943Seric ** Side Effects: 14424943Seric ** Initializes a bunch of global variables to their 14524943Seric ** default values. 14624943Seric */ 14724943Seric 14824943Seric setdefaults() 14924943Seric { 15024943Seric QueueLA = 8; 15124943Seric QueueFactor = 10000; 15224943Seric RefuseLA = 12; 15324943Seric SpaceSub = ' '; 15424981Seric WkRecipFact = 1000; 15524981Seric WkClassFact = 1800; 15625812Seric WkTimeFact = 9000; 15724981Seric FileMode = 0644; 15824981Seric DefUid = 1; 15924981Seric DefGid = 1; 16024943Seric } 161294Seric 162294Seric # ifdef V6 163294Seric /* 1644190Seric ** TTYNAME -- return name of terminal. 165294Seric ** 166294Seric ** Parameters: 1674190Seric ** fd -- file descriptor to check. 168294Seric ** 169294Seric ** Returns: 1704190Seric ** pointer to full path of tty. 1714190Seric ** NULL if no tty. 172294Seric ** 173294Seric ** Side Effects: 174294Seric ** none. 175294Seric */ 176294Seric 177294Seric char * 1784190Seric ttyname(fd) 1794190Seric int fd; 180294Seric { 1814190Seric register char tn; 182294Seric static char pathn[] = "/dev/ttyx"; 183294Seric 184294Seric /* compute the pathname of the controlling tty */ 1854190Seric if ((tn = ttyn(fd)) == NULL) 186294Seric { 187294Seric errno = 0; 188294Seric return (NULL); 189294Seric } 1904190Seric pathn[8] = tn; 191294Seric return (pathn); 192294Seric } 193294Seric /* 194294Seric ** FDOPEN -- Open a stdio file given an open file descriptor. 195294Seric ** 196294Seric ** This is included here because it is standard in v7, but we 197294Seric ** need it in v6. 198294Seric ** 199294Seric ** Algorithm: 200294Seric ** Open /dev/null to create a descriptor. 201294Seric ** Close that descriptor. 202294Seric ** Copy the existing fd into the descriptor. 203294Seric ** 204294Seric ** Parameters: 205294Seric ** fd -- the open file descriptor. 206294Seric ** type -- "r", "w", or whatever. 207294Seric ** 208294Seric ** Returns: 209294Seric ** The file descriptor it creates. 210294Seric ** 211294Seric ** Side Effects: 212294Seric ** none 213294Seric ** 214294Seric ** Called By: 215294Seric ** deliver 216294Seric ** 217294Seric ** Notes: 218294Seric ** The mode of fd must match "type". 219294Seric */ 220294Seric 221294Seric FILE * 222294Seric fdopen(fd, type) 223294Seric int fd; 224294Seric char *type; 225294Seric { 226294Seric register FILE *f; 227294Seric 228294Seric f = fopen("/dev/null", type); 2294081Seric (void) close(fileno(f)); 230294Seric fileno(f) = fd; 231294Seric return (f); 232294Seric } 233294Seric /* 234294Seric ** INDEX -- Return pointer to character in string 235294Seric ** 236294Seric ** For V7 compatibility. 237294Seric ** 238294Seric ** Parameters: 239294Seric ** s -- a string to scan. 240294Seric ** c -- a character to look for. 241294Seric ** 242294Seric ** Returns: 243294Seric ** If c is in s, returns the address of the first 244294Seric ** instance of c in s. 245294Seric ** NULL if c is not in s. 246294Seric ** 247294Seric ** Side Effects: 248294Seric ** none. 249294Seric */ 250294Seric 2514437Seric char * 252294Seric index(s, c) 253294Seric register char *s; 254294Seric register char c; 255294Seric { 256294Seric while (*s != '\0') 257294Seric { 258294Seric if (*s++ == c) 259294Seric return (--s); 260294Seric } 261294Seric return (NULL); 262294Seric } 2634326Seric /* 2644326Seric ** UMASK -- fake the umask system call. 2654326Seric ** 2664326Seric ** Since V6 always acts like the umask is zero, we will just 2674326Seric ** assume the same thing. 2684326Seric */ 2694326Seric 2704326Seric /*ARGSUSED*/ 2714326Seric umask(nmask) 2724326Seric { 2734326Seric return (0); 2744326Seric } 2754326Seric 2764326Seric 2774326Seric /* 2784326Seric ** GETRUID -- get real user id. 2794326Seric */ 2804326Seric 2814326Seric getruid() 2824326Seric { 2834326Seric return (getuid() & 0377); 2844326Seric } 2854326Seric 2864326Seric 2874326Seric /* 2884326Seric ** GETRGID -- get real group id. 2894326Seric */ 2904326Seric 2914326Seric getrgid() 2924326Seric { 2934326Seric return (getgid() & 0377); 2944326Seric } 2954326Seric 2964326Seric 2974326Seric /* 2984326Seric ** GETEUID -- get effective user id. 2994326Seric */ 3004326Seric 3014326Seric geteuid() 3024326Seric { 3034326Seric return ((getuid() >> 8) & 0377); 3044326Seric } 3054326Seric 3064326Seric 3074326Seric /* 3084326Seric ** GETEGID -- get effective group id. 3094326Seric */ 3104326Seric 3114326Seric getegid() 3124326Seric { 3134326Seric return ((getgid() >> 8) & 0377); 3144326Seric } 3154326Seric 316294Seric # endif V6 3174326Seric 3184326Seric # ifndef V6 3194326Seric 3204326Seric /* 3214326Seric ** GETRUID -- get real user id (V7) 3224326Seric */ 3234326Seric 3244326Seric getruid() 3254326Seric { 3269274Seric if (OpMode == MD_DAEMON) 3274536Seric return (RealUid); 3284536Seric else 3294536Seric return (getuid()); 3304326Seric } 3314326Seric 3324326Seric 3334326Seric /* 3344326Seric ** GETRGID -- get real group id (V7). 3354326Seric */ 3364326Seric 3374326Seric getrgid() 3384326Seric { 3399274Seric if (OpMode == MD_DAEMON) 3404536Seric return (RealGid); 3414536Seric else 3424536Seric return (getgid()); 3434326Seric } 3444326Seric 3454326Seric # endif V6 3464190Seric /* 3479369Seric ** USERNAME -- return the user id of the logged in user. 3489369Seric ** 3499369Seric ** Parameters: 3509369Seric ** none. 3519369Seric ** 3529369Seric ** Returns: 3539369Seric ** The login name of the logged in user. 3549369Seric ** 3559369Seric ** Side Effects: 3569369Seric ** none. 3579369Seric ** 3589369Seric ** Notes: 3599369Seric ** The return value is statically allocated. 3609369Seric */ 3619369Seric 3629369Seric char * 3639369Seric username() 3649369Seric { 36517469Seric static char *myname = NULL; 3669369Seric extern char *getlogin(); 36719904Smiriam register struct passwd *pw; 36819904Smiriam extern struct passwd *getpwuid(); 3699369Seric 37017469Seric /* cache the result */ 37117469Seric if (myname == NULL) 37217469Seric { 37317469Seric myname = getlogin(); 37417469Seric if (myname == NULL || myname[0] == '\0') 37517469Seric { 37617469Seric 37717469Seric pw = getpwuid(getruid()); 37817469Seric if (pw != NULL) 37917469Seric myname = pw->pw_name; 38017469Seric } 38119904Smiriam else 38219904Smiriam { 38319873Smiriam 38419873Smiriam pw = getpwnam(myname); 38519904Smiriam if(getuid() != pw->pw_uid) 38619904Smiriam { 38719873Smiriam pw = getpwuid(getuid()); 38824945Seric if (pw != NULL) 38924945Seric myname = pw->pw_name; 39019873Smiriam } 39119873Smiriam } 39217469Seric if (myname == NULL || myname[0] == '\0') 39317469Seric { 39417469Seric syserr("Who are you?"); 39517469Seric myname = "postmaster"; 39617469Seric } 39717469Seric } 39817469Seric 39917469Seric return (myname); 4009369Seric } 4019369Seric /* 4024190Seric ** TTYPATH -- Get the path of the user's tty 403294Seric ** 404294Seric ** Returns the pathname of the user's tty. Returns NULL if 405294Seric ** the user is not logged in or if s/he has write permission 406294Seric ** denied. 407294Seric ** 408294Seric ** Parameters: 409294Seric ** none 410294Seric ** 411294Seric ** Returns: 412294Seric ** pathname of the user's tty. 413294Seric ** NULL if not logged in or write permission denied. 414294Seric ** 415294Seric ** Side Effects: 416294Seric ** none. 417294Seric ** 418294Seric ** WARNING: 419294Seric ** Return value is in a local buffer. 420294Seric ** 421294Seric ** Called By: 422294Seric ** savemail 423294Seric */ 424294Seric 425294Seric # include <sys/stat.h> 426294Seric 427294Seric char * 428294Seric ttypath() 429294Seric { 430294Seric struct stat stbuf; 431294Seric register char *pathn; 432294Seric extern char *ttyname(); 4334081Seric extern char *getlogin(); 434294Seric 435294Seric /* compute the pathname of the controlling tty */ 4369369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4379369Seric (pathn = ttyname(0)) == NULL) 438294Seric { 439294Seric errno = 0; 440294Seric return (NULL); 441294Seric } 442294Seric 443294Seric /* see if we have write permission */ 4442967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 445294Seric { 446294Seric errno = 0; 447294Seric return (NULL); 448294Seric } 449294Seric 450294Seric /* see if the user is logged in */ 451294Seric if (getlogin() == NULL) 452294Seric return (NULL); 453294Seric 454294Seric /* looks good */ 455294Seric return (pathn); 456294Seric } 4572967Seric /* 4582967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4592967Seric ** 4602967Seric ** This routine can be supplied on a per-installation basis 4612967Seric ** to determine whether a person is allowed to send a message. 4622967Seric ** This allows restriction of certain types of internet 4632967Seric ** forwarding or registration of users. 4642967Seric ** 4652967Seric ** If the hosts are found to be incompatible, an error 4662967Seric ** message should be given using "usrerr" and FALSE should 4672967Seric ** be returned. 4682967Seric ** 4694288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4704288Seric ** function; this should be done on huge messages. 4714288Seric ** 4722967Seric ** Parameters: 4732967Seric ** to -- the person being sent to. 4742967Seric ** 4752967Seric ** Returns: 4762967Seric ** TRUE -- ok to send. 4772967Seric ** FALSE -- not ok. 4782967Seric ** 4792967Seric ** Side Effects: 4802967Seric ** none (unless you include the usrerr stuff) 4812967Seric */ 4822967Seric 4832967Seric bool 4842967Seric checkcompat(to) 4852967Seric register ADDRESS *to; 4862967Seric { 48712133Seric # ifdef lint 48812133Seric if (to == NULL) 48912133Seric to++; 49012133Seric # endif lint 49110698Seric # ifdef EXAMPLE_CODE 49210698Seric /* this code is intended as an example only */ 4934437Seric register STAB *s; 4944437Seric 4954437Seric s = stab("arpa", ST_MAILER, ST_FIND); 4969369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 4979369Seric to->q_mailer == s->s_mailer) 4984437Seric { 4994437Seric usrerr("No ARPA mail through this machine: see your system administration"); 50010698Seric /* NoReturn = TRUE; to supress return copy */ 5014437Seric return (FALSE); 5024437Seric } 50310698Seric # endif EXAMPLE_CODE 5042967Seric return (TRUE); 5052967Seric } 5069369Seric /* 5079369Seric ** HOLDSIGS -- arrange to hold all signals 5089369Seric ** 5099369Seric ** Parameters: 5109369Seric ** none. 5119369Seric ** 5129369Seric ** Returns: 5139369Seric ** none. 5149369Seric ** 5159369Seric ** Side Effects: 5169369Seric ** Arranges that signals are held. 5179369Seric */ 5189369Seric 5199369Seric holdsigs() 5209369Seric { 5219369Seric } 5229369Seric /* 5239369Seric ** RLSESIGS -- arrange to release all signals 5249369Seric ** 5259369Seric ** This undoes the effect of holdsigs. 5269369Seric ** 5279369Seric ** Parameters: 5289369Seric ** none. 5299369Seric ** 5309369Seric ** Returns: 5319369Seric ** none. 5329369Seric ** 5339369Seric ** Side Effects: 5349369Seric ** Arranges that signals are released. 5359369Seric */ 5369369Seric 5379369Seric rlsesigs() 5389369Seric { 5399369Seric } 54014872Seric /* 54114872Seric ** GETLA -- get the current load average 54214872Seric ** 54314881Seric ** This code stolen from la.c. 54414881Seric ** 54514872Seric ** Parameters: 54614872Seric ** none. 54714872Seric ** 54814872Seric ** Returns: 54914872Seric ** The current load average as an integer. 55014872Seric ** 55114872Seric ** Side Effects: 55214872Seric ** none. 55314872Seric */ 55414872Seric 55514872Seric #ifdef VMUNIX 55614872Seric 55714872Seric #include <nlist.h> 55814872Seric 55914872Seric struct nlist Nl[] = 56014872Seric { 56114872Seric { "_avenrun" }, 56214872Seric #define X_AVENRUN 0 56314872Seric { 0 }, 56414872Seric }; 56514872Seric 56614872Seric getla() 56714872Seric { 56814872Seric static int kmem = -1; 56924943Seric # ifdef sun 57024943Seric long avenrun[3]; 57124943Seric # else 57214872Seric double avenrun[3]; 57324943Seric # endif 57425615Seric extern off_t lseek(); 57514872Seric 57614872Seric if (kmem < 0) 57714872Seric { 57824945Seric kmem = open("/dev/kmem", 0, 0); 57914872Seric if (kmem < 0) 58014872Seric return (-1); 58123118Seric (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 58214872Seric nlist("/vmunix", Nl); 58314872Seric if (Nl[0].n_type == 0) 58414872Seric return (-1); 58514872Seric } 58624945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 58723118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 58819967Seric { 58919967Seric /* thank you Ian */ 59019967Seric return (-1); 59119967Seric } 59224943Seric # ifdef sun 59324943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 59424943Seric # else 59514872Seric return ((int) (avenrun[0] + 0.5)); 59624943Seric # endif 59714872Seric } 59814872Seric 59914872Seric #else VMUNIX 60014872Seric 60114872Seric getla() 60214872Seric { 60314872Seric return (0); 60414872Seric } 60514872Seric 60614872Seric #endif VMUNIX 60724943Seric /* 60824943Seric ** SHOULDQUEUE -- should this message be queued or sent? 60924943Seric ** 61024943Seric ** Compares the message cost to the load average to decide. 61124943Seric ** 61224943Seric ** Parameters: 61324943Seric ** pri -- the priority of the message in question. 61424943Seric ** 61524943Seric ** Returns: 61624943Seric ** TRUE -- if this message should be queued up for the 61724943Seric ** time being. 61824943Seric ** FALSE -- if the load is low enough to send this message. 61924943Seric ** 62024943Seric ** Side Effects: 62124943Seric ** none. 62224943Seric */ 62324943Seric 62424943Seric bool 62524943Seric shouldqueue(pri) 62624943Seric long pri; 62724943Seric { 62824943Seric int la; 62924943Seric 63024943Seric la = getla(); 63124943Seric if (la < QueueLA) 63224943Seric return (FALSE); 63324943Seric return (pri > (QueueFactor / (la - QueueLA + 1))); 63424943Seric } 63524943Seric /* 63624943Seric ** SETPROCTITLE -- set process title for ps 63724943Seric ** 63824943Seric ** Parameters: 63924943Seric ** fmt -- a printf style format string. 64024943Seric ** a, b, c -- possible parameters to fmt. 64124943Seric ** 64224943Seric ** Returns: 64324943Seric ** none. 64424943Seric ** 64524943Seric ** Side Effects: 64624943Seric ** Clobbers argv of our main procedure so ps(1) will 64724943Seric ** display the title. 64824943Seric */ 64924943Seric 65024943Seric /*VARARGS1*/ 65124943Seric setproctitle(fmt, a, b, c) 65224943Seric char *fmt; 65324943Seric { 65424943Seric # ifdef SETPROCTITLE 65524943Seric register char *p; 65625049Seric register int i; 65724943Seric extern char **Argv; 65824943Seric extern char *LastArgv; 65925049Seric char buf[MAXLINE]; 66024943Seric 66125049Seric (void) sprintf(buf, fmt, a, b, c); 66224943Seric 66324943Seric /* make ps print "(sendmail)" */ 66425049Seric p = Argv[0]; 66524943Seric *p++ = '-'; 66624943Seric 66725049Seric i = strlen(buf); 66825049Seric if (i > LastArgv - p - 2) 66925049Seric { 67025049Seric i = LastArgv - p - 2; 67125049Seric buf[i] = '\0'; 67225049Seric } 67325049Seric (void) strcpy(p, buf); 67425049Seric p += i; 67524943Seric while (p < LastArgv) 67624943Seric *p++ = ' '; 67724943Seric # endif SETPROCTITLE 67824943Seric } 67925698Seric /* 68025698Seric ** REAPCHILD -- pick up the body of my child, lest it become a zombie 68125698Seric ** 68225698Seric ** Parameters: 68325698Seric ** none. 68425698Seric ** 68525698Seric ** Returns: 68625698Seric ** none. 68725698Seric ** 68825698Seric ** Side Effects: 68925698Seric ** Picks up extant zombies. 69025698Seric */ 69125698Seric 69225698Seric # ifdef VMUNIX 69325698Seric # include <sys/wait.h> 69425698Seric # endif VMUNIX 69525698Seric 69625698Seric reapchild() 69725698Seric { 69825698Seric # ifdef WNOHANG 69925698Seric union wait status; 70025698Seric 70125698Seric while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 70225698Seric continue; 70325698Seric # else WNOHANG 70425698Seric auto int status; 70525698Seric 70625698Seric while (wait(&status) > 0) 70725698Seric continue; 70825698Seric # endif WNOHANG 70925698Seric } 710