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*25008Seric static char SccsId[] = "@(#)conf.c 5.8 (Berkeley) 09/21/85"; 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, 699055Seric "sender", H_FROM, 709055Seric "from", H_FROM, 719055Seric "full-name", H_ACHECK, 729055Seric "return-receipt-to", H_FROM, 739055Seric "errors-to", H_FROM, 748060Seric /* destination fields */ 759055Seric "to", H_RCPT, 7611417Seric "resent-to", H_RCPT|H_RESENT, 779055Seric "cc", H_RCPT, 7811417Seric "resent-cc", H_RCPT|H_RESENT, 799055Seric "bcc", H_RCPT|H_ACHECK, 8011417Seric "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 818060Seric /* message identification and control */ 8211417Seric "message-id", 0, 8311417Seric "resent-message-id", H_RESENT, 849055Seric "message", H_EOH, 859055Seric "text", H_EOH, 8611417Seric /* date fields */ 8711417Seric "date", 0, 8811417Seric "resent-date", H_RESENT, 898060Seric /* trace fields */ 909055Seric "received", H_TRACE|H_FORCE, 919055Seric "via", H_TRACE|H_FORCE, 929055Seric "mail-from", H_TRACE|H_FORCE, 938060Seric 949055Seric NULL, 0, 952897Seric }; 964166Seric 974166Seric 984166Seric /* 994166Seric ** ARPANET error message numbers. 1004166Seric */ 1014166Seric 1027956Seric char Arpa_Info[] = "050"; /* arbitrary info */ 1037956Seric char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 1047956Seric char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 1057956Seric char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 1064282Seric 1074282Seric 1084282Seric 1094282Seric /* 1104282Seric ** Location of system files/databases/etc. 1114282Seric */ 1124282Seric 1134282Seric char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ 1149064Seric char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ 1159039Seric 1169064Seric 1179064Seric 1189039Seric /* 11924943Seric ** Miscellaneous stuff. 1209039Seric */ 1219039Seric 12224943Seric int DtableSize = 50; /* max open files; reset in 4.2bsd */ 12324943Seric /* 12424943Seric ** SETDEFAULTS -- set default values 12524943Seric ** 12624943Seric ** Because of the way freezing is done, these must be initialized 12724943Seric ** using direct code. 12824943Seric ** 12924943Seric ** Parameters: 13024943Seric ** none. 13124943Seric ** 13224943Seric ** Returns: 13324943Seric ** none. 13424943Seric ** 13524943Seric ** Side Effects: 13624943Seric ** Initializes a bunch of global variables to their 13724943Seric ** default values. 13824943Seric */ 13924943Seric 14024943Seric setdefaults() 14124943Seric { 14224943Seric QueueLA = 8; 14324943Seric QueueFactor = 10000; 14424943Seric RefuseLA = 12; 14524943Seric SpaceSub = ' '; 14624981Seric WkRecipFact = 1000; 14724981Seric WkClassFact = 1800; 148*25008Seric WkTimeFact = 600; 14924981Seric FileMode = 0644; 15024981Seric DefUid = 1; 15124981Seric DefGid = 1; 15224943Seric } 153294Seric 154294Seric # ifdef V6 155294Seric /* 1564190Seric ** TTYNAME -- return name of terminal. 157294Seric ** 158294Seric ** Parameters: 1594190Seric ** fd -- file descriptor to check. 160294Seric ** 161294Seric ** Returns: 1624190Seric ** pointer to full path of tty. 1634190Seric ** NULL if no tty. 164294Seric ** 165294Seric ** Side Effects: 166294Seric ** none. 167294Seric */ 168294Seric 169294Seric char * 1704190Seric ttyname(fd) 1714190Seric int fd; 172294Seric { 1734190Seric register char tn; 174294Seric static char pathn[] = "/dev/ttyx"; 175294Seric 176294Seric /* compute the pathname of the controlling tty */ 1774190Seric if ((tn = ttyn(fd)) == NULL) 178294Seric { 179294Seric errno = 0; 180294Seric return (NULL); 181294Seric } 1824190Seric pathn[8] = tn; 183294Seric return (pathn); 184294Seric } 185294Seric /* 186294Seric ** FDOPEN -- Open a stdio file given an open file descriptor. 187294Seric ** 188294Seric ** This is included here because it is standard in v7, but we 189294Seric ** need it in v6. 190294Seric ** 191294Seric ** Algorithm: 192294Seric ** Open /dev/null to create a descriptor. 193294Seric ** Close that descriptor. 194294Seric ** Copy the existing fd into the descriptor. 195294Seric ** 196294Seric ** Parameters: 197294Seric ** fd -- the open file descriptor. 198294Seric ** type -- "r", "w", or whatever. 199294Seric ** 200294Seric ** Returns: 201294Seric ** The file descriptor it creates. 202294Seric ** 203294Seric ** Side Effects: 204294Seric ** none 205294Seric ** 206294Seric ** Called By: 207294Seric ** deliver 208294Seric ** 209294Seric ** Notes: 210294Seric ** The mode of fd must match "type". 211294Seric */ 212294Seric 213294Seric FILE * 214294Seric fdopen(fd, type) 215294Seric int fd; 216294Seric char *type; 217294Seric { 218294Seric register FILE *f; 219294Seric 220294Seric f = fopen("/dev/null", type); 2214081Seric (void) close(fileno(f)); 222294Seric fileno(f) = fd; 223294Seric return (f); 224294Seric } 225294Seric /* 226294Seric ** INDEX -- Return pointer to character in string 227294Seric ** 228294Seric ** For V7 compatibility. 229294Seric ** 230294Seric ** Parameters: 231294Seric ** s -- a string to scan. 232294Seric ** c -- a character to look for. 233294Seric ** 234294Seric ** Returns: 235294Seric ** If c is in s, returns the address of the first 236294Seric ** instance of c in s. 237294Seric ** NULL if c is not in s. 238294Seric ** 239294Seric ** Side Effects: 240294Seric ** none. 241294Seric */ 242294Seric 2434437Seric char * 244294Seric index(s, c) 245294Seric register char *s; 246294Seric register char c; 247294Seric { 248294Seric while (*s != '\0') 249294Seric { 250294Seric if (*s++ == c) 251294Seric return (--s); 252294Seric } 253294Seric return (NULL); 254294Seric } 2554326Seric /* 2564326Seric ** UMASK -- fake the umask system call. 2574326Seric ** 2584326Seric ** Since V6 always acts like the umask is zero, we will just 2594326Seric ** assume the same thing. 2604326Seric */ 2614326Seric 2624326Seric /*ARGSUSED*/ 2634326Seric umask(nmask) 2644326Seric { 2654326Seric return (0); 2664326Seric } 2674326Seric 2684326Seric 2694326Seric /* 2704326Seric ** GETRUID -- get real user id. 2714326Seric */ 2724326Seric 2734326Seric getruid() 2744326Seric { 2754326Seric return (getuid() & 0377); 2764326Seric } 2774326Seric 2784326Seric 2794326Seric /* 2804326Seric ** GETRGID -- get real group id. 2814326Seric */ 2824326Seric 2834326Seric getrgid() 2844326Seric { 2854326Seric return (getgid() & 0377); 2864326Seric } 2874326Seric 2884326Seric 2894326Seric /* 2904326Seric ** GETEUID -- get effective user id. 2914326Seric */ 2924326Seric 2934326Seric geteuid() 2944326Seric { 2954326Seric return ((getuid() >> 8) & 0377); 2964326Seric } 2974326Seric 2984326Seric 2994326Seric /* 3004326Seric ** GETEGID -- get effective group id. 3014326Seric */ 3024326Seric 3034326Seric getegid() 3044326Seric { 3054326Seric return ((getgid() >> 8) & 0377); 3064326Seric } 3074326Seric 308294Seric # endif V6 3094326Seric 3104326Seric # ifndef V6 3114326Seric 3124326Seric /* 3134326Seric ** GETRUID -- get real user id (V7) 3144326Seric */ 3154326Seric 3164326Seric getruid() 3174326Seric { 3189274Seric if (OpMode == MD_DAEMON) 3194536Seric return (RealUid); 3204536Seric else 3214536Seric return (getuid()); 3224326Seric } 3234326Seric 3244326Seric 3254326Seric /* 3264326Seric ** GETRGID -- get real group id (V7). 3274326Seric */ 3284326Seric 3294326Seric getrgid() 3304326Seric { 3319274Seric if (OpMode == MD_DAEMON) 3324536Seric return (RealGid); 3334536Seric else 3344536Seric return (getgid()); 3354326Seric } 3364326Seric 3374326Seric # endif V6 3384190Seric /* 3399369Seric ** USERNAME -- return the user id of the logged in user. 3409369Seric ** 3419369Seric ** Parameters: 3429369Seric ** none. 3439369Seric ** 3449369Seric ** Returns: 3459369Seric ** The login name of the logged in user. 3469369Seric ** 3479369Seric ** Side Effects: 3489369Seric ** none. 3499369Seric ** 3509369Seric ** Notes: 3519369Seric ** The return value is statically allocated. 3529369Seric */ 3539369Seric 3549369Seric char * 3559369Seric username() 3569369Seric { 35717469Seric static char *myname = NULL; 3589369Seric extern char *getlogin(); 35919904Smiriam register struct passwd *pw; 36019904Smiriam extern struct passwd *getpwuid(); 3619369Seric 36217469Seric /* cache the result */ 36317469Seric if (myname == NULL) 36417469Seric { 36517469Seric myname = getlogin(); 36617469Seric if (myname == NULL || myname[0] == '\0') 36717469Seric { 36817469Seric 36917469Seric pw = getpwuid(getruid()); 37017469Seric if (pw != NULL) 37117469Seric myname = pw->pw_name; 37217469Seric } 37319904Smiriam else 37419904Smiriam { 37519873Smiriam 37619873Smiriam pw = getpwnam(myname); 37719904Smiriam if(getuid() != pw->pw_uid) 37819904Smiriam { 37919873Smiriam pw = getpwuid(getuid()); 38024945Seric if (pw != NULL) 38124945Seric myname = pw->pw_name; 38219873Smiriam } 38319873Smiriam } 38417469Seric if (myname == NULL || myname[0] == '\0') 38517469Seric { 38617469Seric syserr("Who are you?"); 38717469Seric myname = "postmaster"; 38817469Seric } 38917469Seric } 39017469Seric 39117469Seric return (myname); 3929369Seric } 3939369Seric /* 3944190Seric ** TTYPATH -- Get the path of the user's tty 395294Seric ** 396294Seric ** Returns the pathname of the user's tty. Returns NULL if 397294Seric ** the user is not logged in or if s/he has write permission 398294Seric ** denied. 399294Seric ** 400294Seric ** Parameters: 401294Seric ** none 402294Seric ** 403294Seric ** Returns: 404294Seric ** pathname of the user's tty. 405294Seric ** NULL if not logged in or write permission denied. 406294Seric ** 407294Seric ** Side Effects: 408294Seric ** none. 409294Seric ** 410294Seric ** WARNING: 411294Seric ** Return value is in a local buffer. 412294Seric ** 413294Seric ** Called By: 414294Seric ** savemail 415294Seric */ 416294Seric 417294Seric # include <sys/stat.h> 418294Seric 419294Seric char * 420294Seric ttypath() 421294Seric { 422294Seric struct stat stbuf; 423294Seric register char *pathn; 424294Seric extern char *ttyname(); 4254081Seric extern char *getlogin(); 426294Seric 427294Seric /* compute the pathname of the controlling tty */ 4289369Seric if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 4299369Seric (pathn = ttyname(0)) == NULL) 430294Seric { 431294Seric errno = 0; 432294Seric return (NULL); 433294Seric } 434294Seric 435294Seric /* see if we have write permission */ 4362967Seric if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 437294Seric { 438294Seric errno = 0; 439294Seric return (NULL); 440294Seric } 441294Seric 442294Seric /* see if the user is logged in */ 443294Seric if (getlogin() == NULL) 444294Seric return (NULL); 445294Seric 446294Seric /* looks good */ 447294Seric return (pathn); 448294Seric } 4492967Seric /* 4502967Seric ** CHECKCOMPAT -- check for From and To person compatible. 4512967Seric ** 4522967Seric ** This routine can be supplied on a per-installation basis 4532967Seric ** to determine whether a person is allowed to send a message. 4542967Seric ** This allows restriction of certain types of internet 4552967Seric ** forwarding or registration of users. 4562967Seric ** 4572967Seric ** If the hosts are found to be incompatible, an error 4582967Seric ** message should be given using "usrerr" and FALSE should 4592967Seric ** be returned. 4602967Seric ** 4614288Seric ** 'NoReturn' can be set to suppress the return-to-sender 4624288Seric ** function; this should be done on huge messages. 4634288Seric ** 4642967Seric ** Parameters: 4652967Seric ** to -- the person being sent to. 4662967Seric ** 4672967Seric ** Returns: 4682967Seric ** TRUE -- ok to send. 4692967Seric ** FALSE -- not ok. 4702967Seric ** 4712967Seric ** Side Effects: 4722967Seric ** none (unless you include the usrerr stuff) 4732967Seric */ 4742967Seric 4752967Seric bool 4762967Seric checkcompat(to) 4772967Seric register ADDRESS *to; 4782967Seric { 47912133Seric # ifdef lint 48012133Seric if (to == NULL) 48112133Seric to++; 48212133Seric # endif lint 48310698Seric # ifdef EXAMPLE_CODE 48410698Seric /* this code is intended as an example only */ 4854437Seric register STAB *s; 4864437Seric 4874437Seric s = stab("arpa", ST_MAILER, ST_FIND); 4889369Seric if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 4899369Seric to->q_mailer == s->s_mailer) 4904437Seric { 4914437Seric usrerr("No ARPA mail through this machine: see your system administration"); 49210698Seric /* NoReturn = TRUE; to supress return copy */ 4934437Seric return (FALSE); 4944437Seric } 49510698Seric # endif EXAMPLE_CODE 4962967Seric return (TRUE); 4972967Seric } 4989369Seric /* 4999369Seric ** HOLDSIGS -- arrange to hold all signals 5009369Seric ** 5019369Seric ** Parameters: 5029369Seric ** none. 5039369Seric ** 5049369Seric ** Returns: 5059369Seric ** none. 5069369Seric ** 5079369Seric ** Side Effects: 5089369Seric ** Arranges that signals are held. 5099369Seric */ 5109369Seric 5119369Seric holdsigs() 5129369Seric { 5139369Seric } 5149369Seric /* 5159369Seric ** RLSESIGS -- arrange to release all signals 5169369Seric ** 5179369Seric ** This undoes the effect of holdsigs. 5189369Seric ** 5199369Seric ** Parameters: 5209369Seric ** none. 5219369Seric ** 5229369Seric ** Returns: 5239369Seric ** none. 5249369Seric ** 5259369Seric ** Side Effects: 5269369Seric ** Arranges that signals are released. 5279369Seric */ 5289369Seric 5299369Seric rlsesigs() 5309369Seric { 5319369Seric } 53214872Seric /* 53314872Seric ** GETLA -- get the current load average 53414872Seric ** 53514881Seric ** This code stolen from la.c. 53614881Seric ** 53714872Seric ** Parameters: 53814872Seric ** none. 53914872Seric ** 54014872Seric ** Returns: 54114872Seric ** The current load average as an integer. 54214872Seric ** 54314872Seric ** Side Effects: 54414872Seric ** none. 54514872Seric */ 54614872Seric 54714872Seric #ifdef VMUNIX 54814872Seric 54914872Seric #include <nlist.h> 55014872Seric 55114872Seric struct nlist Nl[] = 55214872Seric { 55314872Seric { "_avenrun" }, 55414872Seric #define X_AVENRUN 0 55514872Seric { 0 }, 55614872Seric }; 55714872Seric 55814872Seric getla() 55914872Seric { 56014872Seric static int kmem = -1; 56124943Seric # ifdef sun 56224943Seric long avenrun[3]; 56324943Seric # else 56414872Seric double avenrun[3]; 56524943Seric # endif 56614872Seric 56714872Seric if (kmem < 0) 56814872Seric { 56924945Seric kmem = open("/dev/kmem", 0, 0); 57014872Seric if (kmem < 0) 57114872Seric return (-1); 57223118Seric (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); 57314872Seric nlist("/vmunix", Nl); 57414872Seric if (Nl[0].n_type == 0) 57514872Seric return (-1); 57614872Seric } 57724945Seric if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 57823118Seric read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 57919967Seric { 58019967Seric /* thank you Ian */ 58119967Seric return (-1); 58219967Seric } 58324943Seric # ifdef sun 58424943Seric return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 58524943Seric # else 58614872Seric return ((int) (avenrun[0] + 0.5)); 58724943Seric # endif 58814872Seric } 58914872Seric 59014872Seric #else VMUNIX 59114872Seric 59214872Seric getla() 59314872Seric { 59414872Seric return (0); 59514872Seric } 59614872Seric 59714872Seric #endif VMUNIX 59824943Seric /* 59924943Seric ** SHOULDQUEUE -- should this message be queued or sent? 60024943Seric ** 60124943Seric ** Compares the message cost to the load average to decide. 60224943Seric ** 60324943Seric ** Parameters: 60424943Seric ** pri -- the priority of the message in question. 60524943Seric ** 60624943Seric ** Returns: 60724943Seric ** TRUE -- if this message should be queued up for the 60824943Seric ** time being. 60924943Seric ** FALSE -- if the load is low enough to send this message. 61024943Seric ** 61124943Seric ** Side Effects: 61224943Seric ** none. 61324943Seric */ 61424943Seric 61524943Seric bool 61624943Seric shouldqueue(pri) 61724943Seric long pri; 61824943Seric { 61924943Seric int la; 62024943Seric 62124943Seric la = getla(); 62224943Seric if (la < QueueLA) 62324943Seric return (FALSE); 62424943Seric return (pri > (QueueFactor / (la - QueueLA + 1))); 62524943Seric } 62624943Seric /* 62724943Seric ** SETPROCTITLE -- set process title for ps 62824943Seric ** 62924943Seric ** Parameters: 63024943Seric ** fmt -- a printf style format string. 63124943Seric ** a, b, c -- possible parameters to fmt. 63224943Seric ** 63324943Seric ** Returns: 63424943Seric ** none. 63524943Seric ** 63624943Seric ** Side Effects: 63724943Seric ** Clobbers argv of our main procedure so ps(1) will 63824943Seric ** display the title. 63924943Seric */ 64024943Seric 64124943Seric /*VARARGS1*/ 64224943Seric setproctitle(fmt, a, b, c) 64324943Seric char *fmt; 64424943Seric { 64524943Seric # ifdef SETPROCTITLE 64624943Seric register char *p; 64724943Seric extern char **Argv; 64824943Seric extern char *LastArgv; 64924943Seric 65024943Seric p = Argv[0]; 65124943Seric 65224943Seric /* make ps print "(sendmail)" */ 65324943Seric *p++ = '-'; 65424943Seric 65524943Seric (void) sprintf(p, fmt, a, b, c); 65624943Seric p += strlen(p); 65724943Seric 65824943Seric /* avoid confusing ps */ 65924943Seric while (p < LastArgv) 66024943Seric *p++ = ' '; 66124943Seric # endif SETPROCTITLE 66224943Seric } 663