1: /* 2: ** Sendmail 3: ** Copyright (c) 1983 Eric P. Allman 4: ** Berkeley, California 5: ** 6: ** Copyright (c) 1983 Regents of the University of California. 7: ** All rights reserved. The Berkeley software License Agreement 8: ** specifies the terms and conditions for redistribution. 9: */ 10: 11: #if !defined(lint) && !defined(NOSCCS) 12: static char SccsId[] = "@(#)conf.c 5.14.6 (2.11BSD GTE) 1997/10/2"; 13: #endif 14: 15: #include <pwd.h> 16: #include <sys/ioctl.h> 17: #include "sendmail.h" 18: 19: /* 20: ** CONF.C -- Sendmail Configuration Tables. 21: ** 22: ** Defines the configuration of this installation. 23: ** 24: ** Compilation Flags: 25: ** VMUNIX -- running on a Berkeley UNIX system. 26: ** 27: ** Configuration Variables: 28: ** HdrInfo -- a table describing well-known header fields. 29: ** Each entry has the field name and some flags, 30: ** which are described in sendmail.h. 31: ** 32: ** Notes: 33: ** I have tried to put almost all the reasonable 34: ** configuration information into the configuration 35: ** file read at runtime. My intent is that anything 36: ** here is a function of the version of UNIX you 37: ** are running, or is really static -- for example 38: ** the headers are a superset of widely used 39: ** protocols. If you find yourself playing with 40: ** this file too much, you may be making a mistake! 41: */ 42: 43: 44: 45: 46: /* 47: ** Header info table 48: ** Final (null) entry contains the flags used for any other field. 49: ** 50: ** Not all of these are actually handled specially by sendmail 51: ** at this time. They are included as placeholders, to let 52: ** you know that "someday" I intend to have sendmail do 53: ** something with them. 54: */ 55: 56: struct hdrinfo HdrInfo[] = 57: { 58: /* originator fields, most to least significant */ 59: "resent-sender", H_FROM|H_RESENT, 60: "resent-from", H_FROM|H_RESENT, 61: "resent-reply-to", H_FROM|H_RESENT, 62: "sender", H_FROM, 63: "from", H_FROM, 64: "reply-to", H_FROM, 65: "full-name", H_ACHECK, 66: "return-receipt-to", H_FROM, 67: "errors-to", H_FROM, 68: /* destination fields */ 69: "to", H_RCPT, 70: "resent-to", H_RCPT|H_RESENT, 71: "cc", H_RCPT, 72: "resent-cc", H_RCPT|H_RESENT, 73: "bcc", H_RCPT|H_ACHECK, 74: "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 75: /* message identification and control */ 76: "message-id", 0, 77: "resent-message-id", H_RESENT, 78: "message", H_EOH, 79: "text", H_EOH, 80: /* date fields */ 81: "date", 0, 82: "resent-date", H_RESENT, 83: /* trace fields */ 84: "received", H_TRACE|H_FORCE, 85: "via", H_TRACE|H_FORCE, 86: "mail-from", H_TRACE|H_FORCE, 87: 88: NULL, 0, 89: }; 90: 91: 92: /* 93: ** ARPANET error message numbers. 94: */ 95: 96: char *Arpa_Info = "050"; /* arbitrary info */ 97: char *Arpa_TSyserr = "451"; /* some (transient) system error */ 98: char *Arpa_PSyserr = "554"; /* some (permanent) system error */ 99: char *Arpa_Usrerr = "554"; /* some (fatal) user error */ 100: 101: 102: 103: /* 104: ** Location of system files/databases/etc. 105: */ 106: 107: char *ConfFile = "/etc/sendmail.cf"; /* runtime configuration */ 108: char *FreezeFile = "/etc/sendmail.fc"; /* frozen version of above */ 109: 110: 111: 112: /* 113: ** Miscellaneous stuff. 114: */ 115: 116: int DtableSize = 50; /* max open files; reset in 4.2bsd */ 117: /* 118: ** SETDEFAULTS -- set default values 119: ** 120: ** Because of the way freezing is done, these must be initialized 121: ** using direct code. 122: ** 123: ** Parameters: 124: ** none. 125: ** 126: ** Returns: 127: ** none. 128: ** 129: ** Side Effects: 130: ** Initializes a bunch of global variables to their 131: ** default values. 132: */ 133: 134: setdefaults() 135: { 136: QueueLA = 8; 137: QueueFactor = 10000; 138: RefuseLA = 12; 139: SpaceSub = ' '; 140: WkRecipFact = 1000; 141: WkClassFact = 1800; 142: WkTimeFact = 9000; 143: FileMode = 0644; 144: DefUid = 1; 145: DefGid = 1; 146: } 147: 148: /* 149: ** GETRUID -- get real user id (V7) 150: */ 151: 152: getruid() 153: { 154: if (OpMode == MD_DAEMON) 155: return (RealUid); 156: else 157: return (getuid()); 158: } 159: 160: 161: /* 162: ** GETRGID -- get real group id (V7). 163: */ 164: 165: getrgid() 166: { 167: if (OpMode == MD_DAEMON) 168: return (RealGid); 169: else 170: return (getgid()); 171: } 172: 173: /* 174: ** USERNAME -- return the user id of the logged in user. 175: ** 176: ** Parameters: 177: ** none. 178: ** 179: ** Returns: 180: ** The login name of the logged in user. 181: ** 182: ** Side Effects: 183: ** none. 184: ** 185: ** Notes: 186: ** The return value is statically allocated. 187: */ 188: 189: char * 190: username() 191: { 192: static char *myname = NULL; 193: register struct passwd *pw; 194: 195: /* cache the result */ 196: if (myname == NULL) 197: { 198: myname = getlogin(); 199: if (myname == NULL || myname[0] == '\0') 200: { 201: 202: pw = getpwuid(getruid()); 203: if (pw != NULL) 204: myname = newstr(pw->pw_name); 205: } 206: else 207: { 208: 209: pw = getpwnam(myname); 210: if(getuid() != pw->pw_uid) 211: { 212: pw = getpwuid(getuid()); 213: if (pw != NULL) 214: myname = newstr(pw->pw_name); 215: } 216: } 217: if (myname == NULL || myname[0] == '\0') 218: { 219: syserr("Who are you?"); 220: myname = "postmaster"; 221: } 222: } 223: 224: return (myname); 225: } 226: /* 227: ** TTYPATH -- Get the path of the user's tty 228: ** 229: ** Returns the pathname of the user's tty. Returns NULL if 230: ** the user is not logged in or if s/he has write permission 231: ** denied. 232: ** 233: ** Parameters: 234: ** none 235: ** 236: ** Returns: 237: ** pathname of the user's tty. 238: ** NULL if not logged in or write permission denied. 239: ** 240: ** Side Effects: 241: ** none. 242: ** 243: ** WARNING: 244: ** Return value is in a local buffer. 245: ** 246: ** Called By: 247: ** savemail 248: */ 249: 250: # include <sys/stat.h> 251: 252: char * 253: ttypath() 254: { 255: struct stat stbuf; 256: register char *pathn; 257: 258: /* compute the pathname of the controlling tty */ 259: if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 260: (pathn = ttyname(0)) == NULL) 261: { 262: errno = 0; 263: return (NULL); 264: } 265: 266: /* see if we have write permission */ 267: if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 268: { 269: errno = 0; 270: return (NULL); 271: } 272: 273: /* see if the user is logged in */ 274: if (getlogin() == NULL) 275: return (NULL); 276: 277: /* looks good */ 278: return (pathn); 279: } 280: /* 281: ** CHECKCOMPAT -- check for From and To person compatible. 282: ** 283: ** This routine can be supplied on a per-installation basis 284: ** to determine whether a person is allowed to send a message. 285: ** This allows restriction of certain types of internet 286: ** forwarding or registration of users. 287: ** 288: ** If the hosts are found to be incompatible, an error 289: ** message should be given using "usrerr" and FALSE should 290: ** be returned. 291: ** 292: ** 'NoReturn' can be set to suppress the return-to-sender 293: ** function; this should be done on huge messages. 294: ** 295: ** Parameters: 296: ** to -- the person being sent to. 297: ** 298: ** Returns: 299: ** TRUE -- ok to send. 300: ** FALSE -- not ok. 301: ** 302: ** Side Effects: 303: ** none (unless you include the usrerr stuff) 304: */ 305: 306: bool 307: checkcompat(to) 308: register ADDRESS *to; 309: { 310: # ifdef lint 311: if (to == NULL) 312: to++; 313: # endif lint 314: # ifdef EXAMPLE_CODE 315: /* this code is intended as an example only */ 316: register STAB *s; 317: 318: s = stab("arpa", ST_MAILER, ST_FIND); 319: if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && 320: to->q_mailer == s->s_mailer) 321: { 322: usrerr("No ARPA mail through this machine: see your system administration"); 323: /* NoReturn = TRUE; to supress return copy */ 324: return (FALSE); 325: } 326: # endif EXAMPLE_CODE 327: return (TRUE); 328: } 329: /* 330: ** GETLA -- get the current load average 331: ** 332: ** This code stolen from la.c. 333: ** 334: ** Parameters: 335: ** none. 336: ** 337: ** Returns: 338: ** The current load average as an integer. 339: ** 340: ** Side Effects: 341: ** none. 342: */ 343: 344: getla() 345: { 346: double avenrun; 347: 348: getloadavg(&avenrun, 1); 349: return(avenrun); 350: } 351: /* 352: ** SHOULDQUEUE -- should this message be queued or sent? 353: ** 354: ** Compares the message cost to the load average to decide. 355: ** 356: ** Parameters: 357: ** pri -- the priority of the message in question. 358: ** 359: ** Returns: 360: ** TRUE -- if this message should be queued up for the 361: ** time being. 362: ** FALSE -- if the load is low enough to send this message. 363: ** 364: ** Side Effects: 365: ** none. 366: */ 367: 368: bool 369: shouldqueue(pri) 370: long pri; 371: { 372: int la; 373: 374: la = getla(); 375: if (la < QueueLA) 376: return (FALSE); 377: return (pri > (QueueFactor / (la - QueueLA + 1))); 378: } 379: /* 380: ** SETPROCTITLE -- set process title for ps 381: ** 382: ** Parameters: 383: ** fmt -- a printf style format string. 384: ** a, b, c -- possible parameters to fmt. 385: ** 386: ** Returns: 387: ** none. 388: ** 389: ** Side Effects: 390: ** Clobbers argv of our main procedure so ps(1) will 391: ** display the title. 392: */ 393: 394: /*VARARGS1*/ 395: setproctitle(fmt, a, b, c) 396: char *fmt; 397: { 398: # ifdef SETPROCTITLE 399: register char *p; 400: register int i; 401: extern char **Argv; 402: extern char *LastArgv; 403: char buf[MAXLINE]; 404: 405: (void) sprintf(buf, fmt, a, b, c); 406: 407: /* make ps print "(sendmail)" */ 408: p = Argv[0]; 409: *p++ = '-'; 410: 411: i = strlen(buf); 412: if (i > LastArgv - p - 2) 413: { 414: i = LastArgv - p - 2; 415: buf[i] = '\0'; 416: } 417: (void) strcpy(p, buf); 418: p += i; 419: while (p < LastArgv) 420: *p++ = ' '; 421: # endif SETPROCTITLE 422: } 423: /* 424: ** REAPCHILD -- pick up the body of my child, lest it become a zombie 425: ** 426: ** Parameters: 427: ** none. 428: ** 429: ** Returns: 430: ** none. 431: ** 432: ** Side Effects: 433: ** Picks up extant zombies. 434: */ 435: 436: # ifdef VMUNIX 437: # include <sys/wait.h> 438: # endif VMUNIX 439: 440: reapchild() 441: { 442: # ifdef WNOHANG 443: union wait status; 444: 445: while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) 446: continue; 447: # else WNOHANG 448: auto int status; 449: 450: while (wait(&status) > 0) 451: continue; 452: # endif WNOHANG 453: }