122698Sdist /* 222698Sdist ** Sendmail 322698Sdist ** Copyright (c) 1983 Eric P. Allman 422698Sdist ** Berkeley, California 522698Sdist ** 622698Sdist ** Copyright (c) 1983 Regents of the University of California. 722698Sdist ** All rights reserved. The Berkeley software License Agreement 822698Sdist ** specifies the terms and conditions for redistribution. 922698Sdist */ 1022698Sdist 1122698Sdist #ifndef lint 12*25686Seric static char SccsId[] = "@(#)conf.c 5.12 (Berkeley) 01/05/86"; 1322698Sdist #endif not lint 1422698Sdist 15294Seric # include <pwd.h> 1614881Seric # include <sys/ioctl.h> 1724943Seric # ifdef sun 1824943Seric # include <sys/param.h> 1924943Seric # endif sun 203309Seric # include "sendmail.h" 21404Seric 22294Seric /* 233309Seric ** CONF.C -- Sendmail Configuration Tables. 24294Seric ** 25294Seric ** Defines the configuration of this installation. 26294Seric ** 271388Seric ** Compilation Flags: 281388Seric ** V6 -- running on a version 6 system. This determines 291388Seric ** whether to define certain routines between 301388Seric ** the two systems. If you are running a funny 311388Seric ** system, e.g., V6 with long tty names, this 321388Seric ** should be checked carefully. 3314872Seric ** VMUNIX -- running on a Berkeley UNIX system. 34294Seric ** 351388Seric ** Configuration Variables: 362897Seric ** HdrInfo -- a table describing well-known header fields. 372897Seric ** Each entry has the field name and some flags, 384147Seric ** which are described in sendmail.h. 394093Seric ** 404093Seric ** Notes: 414093Seric ** I have tried to put almost all the reasonable 424093Seric ** configuration information into the configuration 434093Seric ** file read at runtime. My intent is that anything 444093Seric ** here is a function of the version of UNIX you 454093Seric ** are running, or is really static -- for example 464093Seric ** the headers are a superset of widely used 474093Seric ** protocols. If you find yourself playing with 484093Seric ** this file too much, you may be making a mistake! 49294Seric */ 50294Seric 51294Seric 52294Seric 53294Seric 544437Seric /* 552897Seric ** Header info table 563057Seric ** Final (null) entry contains the flags used for any other field. 574147Seric ** 584147Seric ** Not all of these are actually handled specially by sendmail 594147Seric ** at this time. They are included as placeholders, to let 604147Seric ** you know that "someday" I intend to have sendmail do 614147Seric ** something with them. 622897Seric */ 632897Seric 642897Seric struct hdrinfo HdrInfo[] = 652897Seric { 668060Seric /* originator fields, most to least significant */ 6711417Seric "resent-sender", H_FROM|H_RESENT, 6811417Seric "resent-from", H_FROM|H_RESENT, 69*25686Seric "resent-reply-to", H_FROM|H_RESENT, 709055Seric "sender", H_FROM, 719055Seric "from", H_FROM, 72*25686Seric "reply-to", H_FROM, 739055Seric "full-name", H_ACHECK, 749055Seric "return-receipt-to", H_FROM, 759055Seric "errors-to", H_FROM, 768060Seric /* destination fields */ 779055Seric "to", H_RCPT, 7811417Seric "resent-to", H_RCPT|H_RESENT, 799055Seric "cc", H_RCPT, 8011417Seric "resent-cc", H_RCPT|H_RESENT, 819055Seric "bcc", H_RCPT|H_ACHECK, 8211417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 838060Seric /* message identification and control */ 8411417Seric "message-id", 0, 8511417Seric "resent-message-id", H_RESENT, 869055Seric "message", H_EOH, 879055Seric "text", H_EOH, 8811417Seric /* date fields */ 8911417Seric "date", 0, 9011417Seric "resent-date", H_RESENT, 918060Seric /* trace fields */ 929055Seric "received", H_TRACE|H_FORCE, 939055Seric "via", H_TRACE|H_FORCE, 949055Seric "mail-from", H_TRACE|H_FORCE, 958060Seric 969055Seric NULL, 0, 972897Seric }; 984166Seric 994166Seric 1004166Seric /* 1014166Seric ** ARPANET error message numbers. 1024166Seric */ 1034166Seric 1047956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 1057956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 1067956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 1077956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 1084282Seric 1094282Seric 1104282Seric 1114282Seric /* 1124282Seric ** Location of system files/databases/etc. 1134282Seric */ 1144282Seric 1154282Seric char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ 1169064Seric char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ 1179039Seric 1189064Seric 1199064Seric 1209039Seric /* 12124943Seric ** Miscellaneous stuff. 1229039Seric */ 1239039Seric 12424943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 12524943Seric /* 12624943Seric ** SETDEFAULTS -- set default values 12724943Seric ** 12824943Seric ** Because of the way freezing is done, these must be initialized 12924943Seric ** using direct code. 13024943Seric ** 13124943Seric ** Parameters: 13224943Seric ** none. 13324943Seric ** 13424943Seric ** Returns: 13524943Seric ** none. 13624943Seric ** 13724943Seric ** Side Effects: 13824943Seric ** Initializes a bunch of global variables to their 13924943Seric ** default values. 14024943Seric */ 14124943Seric 14224943Seric setdefaults() 14324943Seric { 14424943Seric QueueLA = 8; 14524943Seric QueueFactor = 10000; 14624943Seric RefuseLA = 12; 14724943Seric SpaceSub = ' '; 14824981Seric WkRecipFact = 1000; 14924981Seric WkClassFact = 1800; 15025008Seric WkTimeFact = 600; 15124981Seric FileMode = 0644; 15224981Seric DefUid = 1; 15324981Seric DefGid = 1; 15424943Seric } 155294Seric 156294Seric # ifdef V6 157294Seric /* 1584190Seric ** TTYNAME -- return name of terminal. 159294Seric ** 160294Seric ** Parameters: 1614190Seric ** fd -- file descriptor to check. 162294Seric ** 163294Seric ** Returns: 1644190Seric ** pointer to full path of tty. 1654190Seric ** NULL if no tty. 166294Seric ** 167294Seric ** Side Effects: 168294Seric ** none. 169294Seric */ 170294Seric 171294Seric char * 1724190Seric ttyname(fd) 1734190Seric int fd; 174294Seric { 1754190Seric register char tn; 176294Seric static char pathn[] = "/dev/ttyx"; 177294Seric 178294Seric /* compute the pathname of the controlling tty */ 1794190Seric if ((tn = ttyn(fd)) == NULL) 180294Seric { 181294Seric errno = 0; 182294Seric return (NULL); 183294Seric } 1844190Seric pathn[8] = tn; 185294Seric return (pathn); 186294Seric } 187294Seric /* 188294Seric ** FDOPEN -- Open a stdio file given an open file descriptor. 189294Seric ** 190294Seric ** This is included here because it is standard in v7, but we 191294Seric ** need it in v6. 192294Seric ** 193294Seric ** Algorithm: 194294Seric ** Open /dev/null to create a descriptor. 195294Seric ** Close that descriptor. 196294Seric ** Copy the existing fd into the descriptor. 197294Seric ** 198294Seric ** Parameters: 199294Seric ** fd -- the open file descriptor. 200294Seric ** type -- "r", "w", or whatever. 201294Seric ** 202294Seric ** Returns: 203294Seric ** The file descriptor it creates. 204294Seric ** 205294Seric ** Side Effects: 206294Seric ** none 207294Seric ** 208294Seric ** Called By: 209294Seric ** deliver 210294Seric ** 211294Seric ** Notes: 212294Seric ** The mode of fd must match "type". 213294Seric */ 214294Seric 215294Seric FILE * 216294Seric fdopen(fd, type) 217294Seric int fd; 218294Seric char *type; 219294Seric { 220294Seric register FILE *f; 221294Seric 222294Seric f = fopen("/dev/null", type); 2234081Seric (void) close(fileno(f)); 224294Seric fileno(f) = fd; 225294Seric return (f); 226294Seric } 227294Seric /* 228294Seric ** INDEX -- Return pointer to character in string 229294Seric ** 230294Seric ** For V7 compatibility. 231294Seric ** 232294Seric ** Parameters: 233294Seric ** s -- a string to scan. 234294Seric ** c -- a character to look for. 235294Seric ** 236294Seric ** Returns: 237294Seric ** If c is in s, returns the address of the first 238294Seric ** instance of c in s. 239294Seric ** NULL if c is not in s. 240294Seric ** 241294Seric ** Side Effects: 242294Seric ** none. 243294Seric */ 244294Seric 2454437Seric char * 246294Seric index(s, c) 247294Seric register char *s; 248294Seric register char c; 249294Seric { 250294Seric while (*s != '\0') 251294Seric { 252294Seric if (*s++ == c) 253294Seric return (--s); 254294Seric } 255294Seric return (NULL); 256294Seric } 2574326Seric /* 2584326Seric ** UMASK -- fake the umask system call. 2594326Seric ** 2604326Seric ** Since V6 always acts like the umask is zero, we will just 2614326Seric ** assume the same thing. 2624326Seric */ 2634326Seric 2644326Seric /*ARGSUSED*/ 2654326Seric umask(nmask) 2664326Seric { 2674326Seric return (0); 2684326Seric } 2694326Seric 2704326Seric 2714326Seric /* 2724326Seric ** GETRUID -- get real user id. 2734326Seric */ 2744326Seric 2754326Seric getruid() 2764326Seric { 2774326Seric return (getuid() & 0377); 2784326Seric } 2794326Seric 2804326Seric 2814326Seric /* 2824326Seric ** GETRGID -- get real group id. 2834326Seric */ 2844326Seric 2854326Seric getrgid() 2864326Seric { 2874326Seric return (getgid() & 0377); 2884326Seric } 2894326Seric 2904326Seric 2914326Seric /* 2924326Seric ** GETEUID -- get effective user id. 2934326Seric */ 2944326Seric 2954326Seric geteuid() 2964326Seric { 2974326Seric return ((getuid() >> 8) & 0377); 2984326Seric } 2994326Seric 3004326Seric 3014326Seric /* 3024326Seric ** GETEGID -- get effective group id. 3034326Seric */ 3044326Seric 3054326Seric getegid() 3064326Seric { 3074326Seric return ((getgid() >> 8) & 0377); 3084326Seric } 3094326Seric 310294Seric # endif V6 3114326Seric 3124326Seric # ifndef V6 3134326Seric 3144326Seric /* 3154326Seric ** GETRUID -- get real user id (V7) 3164326Seric */ 3174326Seric 3184326Seric getruid() 3194326Seric { 3209274Seric if (OpMode == MD_DAEMON) 3214536Seric return (RealUid); 3224536Seric else 3234536Seric return (getuid()); 3244326Seric } 3254326Seric 3264326Seric 3274326Seric /* 3284326Seric ** GETRGID -- get real group id (V7). 3294326Seric */ 3304326Seric 3314326Seric getrgid() 3324326Seric { 3339274Seric if (OpMode == MD_DAEMON) 3344536Seric return (RealGid); 3354536Seric else 3364536Seric return (getgid()); 3374326Seric } 3384326Seric 3394326Seric # endif V6 3404190Seric /* 3419369Seric ** USERNAME -- return the user id of the logged in user. 3429369Seric ** 3439369Seric ** Parameters: 3449369Seric ** none. 3459369Seric ** 3469369Seric ** Returns: 3479369Seric ** The login name of the logged in user. 3489369Seric ** 3499369Seric ** Side Effects: 3509369Seric ** none. 3519369Seric ** 3529369Seric ** Notes: 3539369Seric ** The return value is statically allocated. 3549369Seric */ 3559369Seric 3569369Seric char * 3579369Seric username() 3589369Seric { 35917469Seric static char *myname = NULL; 3609369Seric extern char *getlogin(); 36119904Smiriam register struct passwd *pw; 36219904Smiriam extern struct passwd *getpwuid(); 3639369Seric 36417469Seric /* cache the result */ 36517469Seric if (myname == NULL) 36617469Seric { 36717469Seric myname = getlogin(); 36817469Seric if (myname == NULL || myname[0] == '\0') 36917469Seric { 37017469Seric 37117469Seric pw = getpwuid(getruid()); 37217469Seric if (pw != NULL) 37317469Seric myname = pw->pw_name; 37417469Seric } 37519904Smiriam else 37619904Smiriam { 37719873Smiriam 37819873Smiriam pw = getpwnam(myname); 37919904Smiriam if(getuid() != pw->pw_uid) 38019904Smiriam { 38119873Smiriam pw = getpwuid(getuid()); 38224945Seric if (pw != NULL) 38324945Seric myname = pw->pw_name; 38419873Smiriam } 38519873Smiriam } 38617469Seric if (myname == NULL || myname[0] == '\0') 38717469Seric { 38817469Seric syserr("Who are you?"); 38917469Seric myname = "postmaster"; 39017469Seric } 39117469Seric } 39217469Seric 39317469Seric return (myname); 3949369Seric } 3959369Seric /* 3964190Seric ** TTYPATH -- Get the path of the user's tty 397294Seric ** 398294Seric ** Returns the pathname of the user's tty. Returns NULL if 399294Seric ** the user is not logged in or if s/he has write permission 400294Seric ** denied. 401294Seric ** 402294Seric ** Parameters: 403294Seric ** none 404294Seric ** 405294Seric ** Returns: 406294Seric ** pathname of the user's tty. 407294Seric ** NULL if not logged in or write permission denied. 408294Seric ** 409294Seric ** Side Effects: 410294Seric ** none. 411294Seric ** 412294Seric ** WARNING: 413294Seric ** Return value is in a local buffer. 414294Seric ** 415294Seric ** Called By: 416294Seric ** savemail 417294Seric */ 418294Seric 419294Seric # include <sys/stat.h> 420294Seric 421294Seric char * 422294Seric ttypath() 423294Seric { 424294Seric struct stat stbuf; 425294Seric register char *pathn; 426294Seric extern char *ttyname(); 4274081Seric extern char *getlogin(); 428294Seric 429294Seric /* compute the pathname of the controlling tty */ 4309369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4319369Seric (pathn = ttyname(0)) == NULL) 432294Seric { 433294Seric errno = 0; 434294Seric return (NULL); 435294Seric } 436294Seric 437294Seric /* see if we have write permission */ 4382967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 439294Seric { 440294Seric errno = 0; 441294Seric return (NULL); 442294Seric } 443294Seric 444294Seric /* see if the user is logged in */ 445294Seric if (getlogin() == NULL) 446294Seric return (NULL); 447294Seric 448294Seric /* looks good */ 449294Seric return (pathn); 450294Seric } 4512967Seric /* 4522967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4532967Seric ** 4542967Seric ** This routine can be supplied on a per-installation basis 4552967Seric ** to determine whether a person is allowed to send a message. 4562967Seric ** This allows restriction of certain types of internet 4572967Seric ** forwarding or registration of users. 4582967Seric ** 4592967Seric ** If the hosts are found to be incompatible, an error 4602967Seric ** message should be given using "usrerr" and FALSE should 4612967Seric ** be returned. 4622967Seric ** 4634288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4644288Seric ** function; this should be done on huge messages. 4654288Seric ** 4662967Seric ** Parameters: 4672967Seric ** to -- the person being sent to. 4682967Seric ** 4692967Seric ** Returns: 4702967Seric ** TRUE -- ok to send. 4712967Seric ** FALSE -- not ok. 4722967Seric ** 4732967Seric ** Side Effects: 4742967Seric ** none (unless you include the usrerr stuff) 4752967Seric */ 4762967Seric 4772967Seric bool 4782967Seric checkcompat(to) 4792967Seric register ADDRESS *to; 4802967Seric { 48112133Seric # ifdef lint 48212133Seric if (to == NULL) 48312133Seric to++; 48412133Seric # endif lint 48510698Seric # ifdef EXAMPLE_CODE 48610698Seric /* this code is intended as an example only */ 4874437Seric register STAB *s; 4884437Seric 4894437Seric s = stab("arpa", ST_MAILER, ST_FIND); 4909369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 4919369Seric to->q_mailer == s->s_mailer) 4924437Seric { 4934437Seric usrerr("No ARPA mail through this machine: see your system administration"); 49410698Seric /* NoReturn = TRUE; to supress return copy */ 4954437Seric return (FALSE); 4964437Seric } 49710698Seric # endif EXAMPLE_CODE 4982967Seric return (TRUE); 4992967Seric } 5009369Seric /* 5019369Seric ** HOLDSIGS -- arrange to hold all signals 5029369Seric ** 5039369Seric ** Parameters: 5049369Seric ** none. 5059369Seric ** 5069369Seric ** Returns: 5079369Seric ** none. 5089369Seric ** 5099369Seric ** Side Effects: 5109369Seric ** Arranges that signals are held. 5119369Seric */ 5129369Seric 5139369Seric holdsigs() 5149369Seric { 5159369Seric } 5169369Seric /* 5179369Seric ** RLSESIGS -- arrange to release all signals 5189369Seric ** 5199369Seric ** This undoes the effect of holdsigs. 5209369Seric ** 5219369Seric ** Parameters: 5229369Seric ** none. 5239369Seric ** 5249369Seric ** Returns: 5259369Seric ** none. 5269369Seric ** 5279369Seric ** Side Effects: 5289369Seric ** Arranges that signals are released. 5299369Seric */ 5309369Seric 5319369Seric rlsesigs() 5329369Seric { 5339369Seric } 53414872Seric /* 53514872Seric ** GETLA -- get the current load average 53614872Seric ** 53714881Seric ** This code stolen from la.c. 53814881Seric ** 53914872Seric ** Parameters: 54014872Seric ** none. 54114872Seric ** 54214872Seric ** Returns: 54314872Seric ** The current load average as an integer. 54414872Seric ** 54514872Seric ** Side Effects: 54614872Seric ** none. 54714872Seric */ 54814872Seric 54914872Seric #ifdef VMUNIX 55014872Seric 55114872Seric #include <nlist.h> 55214872Seric 55314872Seric struct nlist Nl[] = 55414872Seric { 55514872Seric { "_avenrun" }, 55614872Seric #define X_AVENRUN 0 55714872Seric { 0 }, 55814872Seric }; 55914872Seric 56014872Seric getla() 56114872Seric { 56214872Seric static int kmem = -1; 56324943Seric # ifdef sun 56424943Seric long avenrun[3]; 56524943Seric # else 56614872Seric double avenrun[3]; 56724943Seric # endif 56825615Seric extern off_t lseek(); 56914872Seric 57014872Seric if (kmem < 0) 57114872Seric { 57224945Seric kmem = open("/dev/kmem", 0, 0); 57314872Seric if (kmem < 0) 57414872Seric return (-1); 57523118Seric (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 57614872Seric nlist("/vmunix", Nl); 57714872Seric if (Nl[0].n_type == 0) 57814872Seric return (-1); 57914872Seric } 58024945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 58123118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 58219967Seric { 58319967Seric /* thank you Ian */ 58419967Seric return (-1); 58519967Seric } 58624943Seric # ifdef sun 58724943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 58824943Seric # else 58914872Seric return ((int) (avenrun[0] + 0.5)); 59024943Seric # endif 59114872Seric } 59214872Seric 59314872Seric #else VMUNIX 59414872Seric 59514872Seric getla() 59614872Seric { 59714872Seric return (0); 59814872Seric } 59914872Seric 60014872Seric #endif VMUNIX 60124943Seric /* 60224943Seric ** SHOULDQUEUE -- should this message be queued or sent? 60324943Seric ** 60424943Seric ** Compares the message cost to the load average to decide. 60524943Seric ** 60624943Seric ** Parameters: 60724943Seric ** pri -- the priority of the message in question. 60824943Seric ** 60924943Seric ** Returns: 61024943Seric ** TRUE -- if this message should be queued up for the 61124943Seric ** time being. 61224943Seric ** FALSE -- if the load is low enough to send this message. 61324943Seric ** 61424943Seric ** Side Effects: 61524943Seric ** none. 61624943Seric */ 61724943Seric 61824943Seric bool 61924943Seric shouldqueue(pri) 62024943Seric long pri; 62124943Seric { 62224943Seric int la; 62324943Seric 62424943Seric la = getla(); 62524943Seric if (la < QueueLA) 62624943Seric return (FALSE); 62724943Seric return (pri > (QueueFactor / (la - QueueLA + 1))); 62824943Seric } 62924943Seric /* 63024943Seric ** SETPROCTITLE -- set process title for ps 63124943Seric ** 63224943Seric ** Parameters: 63324943Seric ** fmt -- a printf style format string. 63424943Seric ** a, b, c -- possible parameters to fmt. 63524943Seric ** 63624943Seric ** Returns: 63724943Seric ** none. 63824943Seric ** 63924943Seric ** Side Effects: 64024943Seric ** Clobbers argv of our main procedure so ps(1) will 64124943Seric ** display the title. 64224943Seric */ 64324943Seric 64424943Seric /*VARARGS1*/ 64524943Seric setproctitle(fmt, a, b, c) 64624943Seric char *fmt; 64724943Seric { 64824943Seric # ifdef SETPROCTITLE 64924943Seric register char *p; 65025049Seric register int i; 65124943Seric extern char **Argv; 65224943Seric extern char *LastArgv; 65325049Seric char buf[MAXLINE]; 65424943Seric 65525049Seric (void) sprintf(buf, fmt, a, b, c); 65624943Seric 65724943Seric /* make ps print "(sendmail)" */ 65825049Seric p = Argv[0]; 65924943Seric *p++ = '-'; 66024943Seric 66125049Seric i = strlen(buf); 66225049Seric if (i > LastArgv - p - 2) 66325049Seric { 66425049Seric i = LastArgv - p - 2; 66525049Seric buf[i] = '\0'; 66625049Seric } 66725049Seric (void) strcpy(p, buf); 66825049Seric p += i; 66924943Seric while (p < LastArgv) 67024943Seric *p++ = ' '; 67124943Seric # endif SETPROCTITLE 67224943Seric } 673