conf.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:125k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #ifndef lint
  14. static char id[] = "@(#)$Id: conf.c,v 8.623 1999/12/06 21:48:49 ca Exp $";
  15. #endif /* ! lint */
  16. #include <sendmail.h>
  17. #include <sendmail/pathnames.h>
  18. #include <sys/ioctl.h>
  19. #include <sys/param.h>
  20. #include <limits.h>
  21. #if NETINET || NETINET6
  22. # include <arpa/inet.h>
  23. #endif /* NETINET || NETINET6 */
  24. #if HASULIMIT && defined(HPUX11)
  25. # include <ulimit.h>
  26. #endif /* HASULIMIT && defined(HPUX11) */
  27. static void setupmaps __P((void));
  28. static void setupmailers __P((void));
  29. static int get_num_procs_online __P((void));
  30. /*
  31. **  CONF.C -- Sendmail Configuration Tables.
  32. **
  33. ** Defines the configuration of this installation.
  34. **
  35. ** Configuration Variables:
  36. ** HdrInfo -- a table describing well-known header fields.
  37. ** Each entry has the field name and some flags,
  38. ** which are described in sendmail.h.
  39. **
  40. ** Notes:
  41. ** I have tried to put almost all the reasonable
  42. ** configuration information into the configuration
  43. ** file read at runtime.  My intent is that anything
  44. ** here is a function of the version of UNIX you
  45. ** are running, or is really static -- for example
  46. ** the headers are a superset of widely used
  47. ** protocols.  If you find yourself playing with
  48. ** this file too much, you may be making a mistake!
  49. */
  50. /*
  51. **  Header info table
  52. ** Final (null) entry contains the flags used for any other field.
  53. **
  54. ** Not all of these are actually handled specially by sendmail
  55. ** at this time.  They are included as placeholders, to let
  56. ** you know that "someday" I intend to have sendmail do
  57. ** something with them.
  58. */
  59. struct hdrinfo HdrInfo[] =
  60. {
  61. /* originator fields, most to least significant */
  62. { "resent-sender", H_FROM|H_RESENT, NULL },
  63. { "resent-from", H_FROM|H_RESENT, NULL },
  64. { "resent-reply-to", H_FROM|H_RESENT, NULL },
  65. { "sender", H_FROM, NULL },
  66. { "from", H_FROM, NULL },
  67. { "reply-to", H_FROM, NULL },
  68. { "errors-to", H_FROM|H_ERRORSTO, NULL },
  69. { "full-name", H_ACHECK, NULL },
  70. { "return-receipt-to", H_RECEIPTTO, NULL },
  71. /* destination fields */
  72. { "to", H_RCPT, NULL },
  73. { "resent-to", H_RCPT|H_RESENT, NULL },
  74. { "cc", H_RCPT, NULL },
  75. { "resent-cc", H_RCPT|H_RESENT, NULL },
  76. { "bcc", H_RCPT|H_BCC, NULL },
  77. { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL },
  78. { "apparently-to", H_RCPT, NULL },
  79. /* message identification and control */
  80. { "message-id", 0, NULL },
  81. { "resent-message-id", H_RESENT, NULL },
  82. { "message", H_EOH, NULL },
  83. { "text", H_EOH, NULL },
  84. /* date fields */
  85. { "date", 0, NULL },
  86. { "resent-date", H_RESENT, NULL },
  87. /* trace fields */
  88. { "received", H_TRACE|H_FORCE, NULL },
  89. { "x400-received", H_TRACE|H_FORCE, NULL },
  90. { "via", H_TRACE|H_FORCE, NULL },
  91. { "mail-from", H_TRACE|H_FORCE, NULL },
  92. /* miscellaneous fields */
  93. { "comments", H_FORCE|H_ENCODABLE, NULL },
  94. { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL },
  95. { "content-transfer-encoding", H_CTE, NULL },
  96. { "content-type", H_CTYPE, NULL },
  97. { "content-length", H_ACHECK, NULL },
  98. { "subject", H_ENCODABLE, NULL },
  99. { NULL, 0, NULL }
  100. };
  101. /*
  102. **  Privacy values
  103. */
  104. struct prival PrivacyValues[] =
  105. {
  106. { "public", PRIV_PUBLIC },
  107. { "needmailhelo", PRIV_NEEDMAILHELO },
  108. { "needexpnhelo", PRIV_NEEDEXPNHELO },
  109. { "needvrfyhelo", PRIV_NEEDVRFYHELO },
  110. { "noexpn", PRIV_NOEXPN },
  111. { "novrfy", PRIV_NOVRFY },
  112. { "restrictmailq", PRIV_RESTRICTMAILQ },
  113. { "restrictqrun", PRIV_RESTRICTQRUN },
  114. { "noetrn", PRIV_NOETRN },
  115. { "noverb", PRIV_NOVERB },
  116. { "authwarnings", PRIV_AUTHWARNINGS },
  117. { "noreceipts", PRIV_NORECEIPTS },
  118. { "nobodyreturn", PRIV_NOBODYRETN },
  119. { "goaway", PRIV_GOAWAY },
  120. { NULL, 0 }
  121. };
  122. /*
  123. **  DontBlameSendmail values
  124. */
  125. struct dbsval DontBlameSendmailValues[] =
  126. {
  127. { "safe", DBS_SAFE },
  128. { "assumesafechown", DBS_ASSUMESAFECHOWN },
  129. { "groupwritabledirpathsafe", DBS_GROUPWRITABLEDIRPATHSAFE },
  130. { "groupwritableforwardfilesafe",
  131. DBS_GROUPWRITABLEFORWARDFILESAFE },
  132. { "groupwritableincludefilesafe",
  133. DBS_GROUPWRITABLEINCLUDEFILESAFE },
  134. { "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE },
  135. { "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE },
  136. { "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH },
  137. { "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH },
  138. { "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH },
  139. { "linkedaliasfileinwritabledir",
  140. DBS_LINKEDALIASFILEINWRITABLEDIR },
  141. { "linkedclassfileinwritabledir",
  142. DBS_LINKEDCLASSFILEINWRITABLEDIR },
  143. { "linkedforwardfileinwritabledir",
  144. DBS_LINKEDFORWARDFILEINWRITABLEDIR },
  145. { "linkedincludefileinwritabledir",
  146. DBS_LINKEDINCLUDEFILEINWRITABLEDIR },
  147. { "linkedmapinwritabledir", DBS_LINKEDMAPINWRITABLEDIR },
  148. { "linkedserviceswitchfileinwritabledir",
  149. DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR },
  150. { "filedeliverytohardlink", DBS_FILEDELIVERYTOHARDLINK },
  151. { "filedeliverytosymlink", DBS_FILEDELIVERYTOSYMLINK },
  152. { "writemaptohardlink", DBS_WRITEMAPTOHARDLINK },
  153. { "writemaptosymlink", DBS_WRITEMAPTOSYMLINK },
  154. { "writestatstohardlink", DBS_WRITESTATSTOHARDLINK },
  155. { "writestatstosymlink", DBS_WRITESTATSTOSYMLINK },
  156. { "forwardfileingroupwritabledirpath",
  157. DBS_FORWARDFILEINGROUPWRITABLEDIRPATH },
  158. { "includefileingroupwritabledirpath",
  159. DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH },
  160. { "classfileinunsafedirpath", DBS_CLASSFILEINUNSAFEDIRPATH },
  161. { "errorheaderinunsafedirpath", DBS_ERRORHEADERINUNSAFEDIRPATH },
  162. { "helpfileinunsafedirpath", DBS_HELPFILEINUNSAFEDIRPATH },
  163. { "forwardfileinunsafedirpathsafe",
  164. DBS_FORWARDFILEINUNSAFEDIRPATHSAFE },
  165. { "includefileinunsafedirpathsafe",
  166. DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE },
  167. { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH },
  168. { "runwritableprogram", DBS_RUNWRITABLEPROGRAM },
  169. { "nonrootsafeaddr", DBS_NONROOTSAFEADDR },
  170. { "truststickybit", DBS_TRUSTSTICKYBIT },
  171. { "dontwarnforwardfileinunsafedirpath",
  172. DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH },
  173. { NULL, 0 }
  174. };
  175. /*
  176. **  Miscellaneous stuff.
  177. */
  178. int DtableSize = 50; /* max open files; reset in 4.2bsd */
  179. /*
  180. **  SETDEFAULTS -- set default values
  181. **
  182. ** Because of the way freezing is done, these must be initialized
  183. ** using direct code.
  184. **
  185. ** Parameters:
  186. ** e -- the default envelope.
  187. **
  188. ** Returns:
  189. ** none.
  190. **
  191. ** Side Effects:
  192. ** Initializes a bunch of global variables to their
  193. ** default values.
  194. */
  195. #define MINUTES * 60
  196. #define HOURS * 60 MINUTES
  197. #define DAYS * 24 HOURS
  198. #ifndef MAXRULERECURSION
  199. # define MAXRULERECURSION 50 /* max ruleset recursion depth */
  200. #endif /* ! MAXRULERECURSION */
  201. void
  202. setdefaults(e)
  203. register ENVELOPE *e;
  204. {
  205. int i;
  206. int numprocs;
  207. struct passwd *pw;
  208. numprocs = get_num_procs_online();
  209. SpaceSub = ' '; /* option B */
  210. QueueLA = 8 * numprocs; /* option x */
  211. RefuseLA = 12 * numprocs; /* option X */
  212. WkRecipFact = 30000L; /* option y */
  213. WkClassFact = 1800L; /* option z */
  214. WkTimeFact = 90000L; /* option Z */
  215. QueueFactor = WkRecipFact * 20; /* option q */
  216. FileMode = (RealUid != geteuid()) ? 0644 : 0600;
  217. /* option F */
  218. if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) ||
  219.     ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) ||
  220.     ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0))
  221. {
  222. DefUid = pw->pw_uid; /* option u */
  223. DefGid = pw->pw_gid; /* option g */
  224. DefUser = newstr(pw->pw_name);
  225. }
  226. else
  227. {
  228. DefUid = 1; /* option u */
  229. DefGid = 1; /* option g */
  230. setdefuser();
  231. }
  232. TrustedUid = 0;
  233. if (tTd(37, 4))
  234. dprintf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%dn",
  235. DefUser != NULL ? DefUser : "<1:1>",
  236. (int) DefUid, (int) DefGid);
  237. CheckpointInterval = 10; /* option C */
  238. MaxHopCount = 25; /* option h */
  239. set_delivery_mode(SM_FORK, e); /* option d */
  240. e->e_errormode = EM_PRINT; /* option e */
  241. e->e_queuedir = NOQDIR;
  242. e->e_ctime = curtime();
  243. SevenBitInput = FALSE; /* option 7 */
  244. MaxMciCache = 1; /* option k */
  245. MciCacheTimeout = 5 MINUTES; /* option K */
  246. LogLevel = 9; /* option L */
  247. inittimeouts(NULL, FALSE); /* option r */
  248. PrivacyFlags = PRIV_PUBLIC; /* option p */
  249. MeToo = TRUE; /* option m */
  250. SendMIMEErrors = TRUE; /* option f */
  251. SuperSafe = TRUE; /* option s */
  252. clrbitmap(DontBlameSendmail); /* DontBlameSendmail option */
  253. #if MIME8TO7
  254. MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */
  255. #else /* MIME8TO7 */
  256. MimeMode = MM_PASS8BIT;
  257. #endif /* MIME8TO7 */
  258. for (i = 0; i < MAXTOCLASS; i++)
  259. {
  260. TimeOuts.to_q_return[i] = 5 DAYS; /* option T */
  261. TimeOuts.to_q_warning[i] = 0; /* option T */
  262. }
  263. ServiceSwitchFile = "/etc/mail/service.switch";
  264. ServiceCacheMaxAge = (time_t) 10;
  265. HostsFile = _PATH_HOSTS;
  266. PidFile = newstr(_PATH_SENDMAILPID);
  267. MustQuoteChars = "@,;:\()[].'";
  268. MciInfoTimeout = 30 MINUTES;
  269. MaxRuleRecursion = MAXRULERECURSION;
  270. MaxAliasRecursion = 10;
  271. MaxMacroRecursion = 10;
  272. ColonOkInAddr = TRUE;
  273. DontLockReadFiles = TRUE;
  274. DoubleBounceAddr = "postmaster";
  275. MaxHeadersLength = MAXHDRSLEN;
  276. MaxForwardEntries = 0;
  277. #if SASL
  278. AuthMechanisms = newstr(AUTH_MECHANISMS);
  279. #endif /* SASL */
  280. #ifdef HESIOD_INIT
  281. HesiodContext = NULL;
  282. #endif /* HESIOD_INIT */
  283. #if NETINET6
  284. InetMode = AF_INET6;
  285. #else /* NETINET6 */
  286. InetMode = AF_INET;
  287. #endif /* NETINET6 */
  288. ControlSocketName = NULL;
  289. memset(&ConnectOnlyTo, '', sizeof ConnectOnlyTo);
  290. DataFileBufferSize = 4096;
  291. XscriptFileBufferSize = 4096;
  292. for (i = 0; i < MAXRWSETS; i++)
  293. RuleSetNames[i] = NULL;
  294. setupmaps();
  295. setupmailers();
  296. setupheaders();
  297. }
  298. /*
  299. **  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
  300. */
  301. void
  302. setdefuser()
  303. {
  304. struct passwd *defpwent;
  305. static char defuserbuf[40];
  306. DefUser = defuserbuf;
  307. defpwent = sm_getpwuid(DefUid);
  308. snprintf(defuserbuf, sizeof defuserbuf, "%s",
  309. defpwent == NULL ? "nobody" : defpwent->pw_name);
  310. if (tTd(37, 4))
  311. dprintf("setdefuser: DefUid=%d, DefUser=%sn",
  312.        (int) DefUid, DefUser);
  313. }
  314. /*
  315. **  SETUPMAILERS -- initialize default mailers
  316. */
  317. static void
  318. setupmailers()
  319. {
  320. char buf[100];
  321. (void) strlcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c 201u",
  322. sizeof buf);
  323. makemailer(buf);
  324. (void) strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE 201u",
  325. sizeof buf);
  326. makemailer(buf);
  327. (void) strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE 201u",
  328. sizeof buf);
  329. makemailer(buf);
  330. initerrmailers();
  331. }
  332. /*
  333. **  SETUPMAPS -- set up map classes
  334. */
  335. #define MAPDEF(name, ext, flags, parse, open, close, lookup, store) 
  336. extern bool parse __P((MAP *, char *)); 
  337. extern bool open __P((MAP *, int)); 
  338. extern void close __P((MAP *)); 
  339. extern char *lookup __P((MAP *, char *, char **, int *)); 
  340. extern void store __P((MAP *, char *, char *)); 
  341. s = stab(name, ST_MAPCLASS, ST_ENTER); 
  342. s->s_mapclass.map_cname = name; 
  343. s->s_mapclass.map_ext = ext; 
  344. s->s_mapclass.map_cflags = flags; 
  345. s->s_mapclass.map_parse = parse; 
  346. s->s_mapclass.map_open = open; 
  347. s->s_mapclass.map_close = close; 
  348. s->s_mapclass.map_lookup = lookup; 
  349. s->s_mapclass.map_store = store; 
  350. }
  351. static void
  352. setupmaps()
  353. {
  354. register STAB *s;
  355. #ifdef NEWDB
  356. MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
  357. map_parseargs, hash_map_open, db_map_close,
  358. db_map_lookup, db_map_store);
  359. MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
  360. map_parseargs, bt_map_open, db_map_close,
  361. db_map_lookup, db_map_store);
  362. #endif /* NEWDB */
  363. #ifdef NDBM
  364. MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
  365. map_parseargs, ndbm_map_open, ndbm_map_close,
  366. ndbm_map_lookup, ndbm_map_store);
  367. #endif /* NDBM */
  368. #ifdef NIS
  369. MAPDEF("nis", NULL, MCF_ALIASOK,
  370. map_parseargs, nis_map_open, null_map_close,
  371. nis_map_lookup, null_map_store);
  372. #endif /* NIS */
  373. #ifdef NISPLUS
  374. MAPDEF("nisplus", NULL, MCF_ALIASOK,
  375. map_parseargs, nisplus_map_open, null_map_close,
  376. nisplus_map_lookup, null_map_store);
  377. #endif /* NISPLUS */
  378. #ifdef LDAPMAP
  379. MAPDEF("ldap", NULL, MCF_ALIASOK,
  380. ldapmap_parseargs, ldapmap_open, ldapmap_close,
  381. ldapmap_lookup, null_map_store);
  382. /* Deprecated */
  383. MAPDEF("ldapx", NULL, MCF_ALIASOK,
  384. ldapx_map_parseargs, ldapmap_open, ldapmap_close,
  385. ldapmap_lookup, null_map_store);
  386. #endif /* LDAPMAP */
  387. #ifdef PH_MAP
  388. MAPDEF("ph", NULL, 0,
  389. ph_map_parseargs, ph_map_open, ph_map_close,
  390. ph_map_lookup, null_map_store);
  391. #endif /* PH_MAP */
  392. #if MAP_NSD
  393. /* IRIX 6.5 nsd support */
  394. MAPDEF("nsd", NULL, MCF_ALIASOK,
  395.        map_parseargs, null_map_open, null_map_close,
  396.        nsd_map_lookup, null_map_store);
  397. #endif /* MAP_NSD */
  398. #ifdef HESIOD
  399. MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY,
  400. map_parseargs, hes_map_open, null_map_close,
  401. hes_map_lookup, null_map_store);
  402. #endif /* HESIOD */
  403. #if NETINFO
  404. MAPDEF("netinfo", NULL, MCF_ALIASOK,
  405. map_parseargs, ni_map_open, null_map_close,
  406. ni_map_lookup, null_map_store);
  407. #endif /* NETINFO */
  408. #if 0
  409. MAPDEF("dns", NULL, 0,
  410. dns_map_init, null_map_open, null_map_close,
  411. dns_map_lookup, null_map_store);
  412. #endif /* 0 */
  413. #if NAMED_BIND
  414. /* best MX DNS lookup */
  415. MAPDEF("bestmx", NULL, MCF_OPTFILE,
  416. map_parseargs, null_map_open, null_map_close,
  417. bestmx_map_lookup, null_map_store);
  418. #endif /* NAMED_BIND */
  419. MAPDEF("host", NULL, 0,
  420. host_map_init, null_map_open, null_map_close,
  421. host_map_lookup, null_map_store);
  422. MAPDEF("text", NULL, MCF_ALIASOK,
  423. map_parseargs, text_map_open, null_map_close,
  424. text_map_lookup, null_map_store);
  425. MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
  426. map_parseargs, stab_map_open, null_map_close,
  427. stab_map_lookup, stab_map_store);
  428. MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE,
  429. map_parseargs, impl_map_open, impl_map_close,
  430. impl_map_lookup, impl_map_store);
  431. /* access to system passwd file */
  432. MAPDEF("user", NULL, MCF_OPTFILE,
  433. map_parseargs, user_map_open, null_map_close,
  434. user_map_lookup, null_map_store);
  435. /* dequote map */
  436. MAPDEF("dequote", NULL, 0,
  437. dequote_init, null_map_open, null_map_close,
  438. dequote_map, null_map_store);
  439. #ifdef MAP_REGEX
  440. MAPDEF("regex", NULL, 0,
  441. regex_map_init, null_map_open, null_map_close,
  442. regex_map_lookup, null_map_store);
  443. #endif /* MAP_REGEX */
  444. #if USERDB
  445. /* user database */
  446. MAPDEF("userdb", ".db", 0,
  447. map_parseargs, null_map_open, null_map_close,
  448. udb_map_lookup, null_map_store);
  449. #endif /* USERDB */
  450. /* arbitrary programs */
  451. MAPDEF("program", NULL, MCF_ALIASOK,
  452. map_parseargs, null_map_open, null_map_close,
  453. prog_map_lookup, null_map_store);
  454. /* sequenced maps */
  455. MAPDEF("sequence", NULL, MCF_ALIASOK,
  456. seq_map_parse, null_map_open, null_map_close,
  457. seq_map_lookup, seq_map_store);
  458. /* switched interface to sequenced maps */
  459. MAPDEF("switch", NULL, MCF_ALIASOK,
  460. map_parseargs, switch_map_open, null_map_close,
  461. seq_map_lookup, seq_map_store);
  462. /* null map lookup -- really for internal use only */
  463. MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
  464. map_parseargs, null_map_open, null_map_close,
  465. null_map_lookup, null_map_store);
  466. /* syslog map -- logs information to syslog */
  467. MAPDEF("syslog", NULL, 0,
  468. syslog_map_parseargs, null_map_open, null_map_close,
  469. syslog_map_lookup, null_map_store);
  470. /* macro storage map -- rulesets can set macros */
  471. MAPDEF("macro", NULL, 0,
  472. dequote_init, null_map_open, null_map_close,
  473. macro_map_lookup, null_map_store);
  474. /* arithmetic map -- add/subtract/compare */
  475. MAPDEF("arith", NULL, 0,
  476. dequote_init, null_map_open, null_map_close,
  477. arith_map_lookup, null_map_store);
  478. if (tTd(38, 2))
  479. {
  480. /* bogus map -- always return tempfail */
  481. MAPDEF("bogus", NULL, MCF_ALIASOK|MCF_OPTFILE,
  482.        map_parseargs, null_map_open, null_map_close,
  483.        bogus_map_lookup, null_map_store);
  484. }
  485. }
  486. #undef MAPDEF
  487. /*
  488. **  INITHOSTMAPS -- initial host-dependent maps
  489. **
  490. ** This should act as an interface to any local service switch
  491. ** provided by the host operating system.
  492. **
  493. ** Parameters:
  494. ** none
  495. **
  496. ** Returns:
  497. ** none
  498. **
  499. ** Side Effects:
  500. ** Should define maps "host" and "users" as necessary
  501. ** for this OS.  If they are not defined, they will get
  502. ** a default value later.  It should check to make sure
  503. ** they are not defined first, since it's possible that
  504. ** the config file has provided an override.
  505. */
  506. void
  507. inithostmaps()
  508. {
  509. register int i;
  510. int nmaps;
  511. char *maptype[MAXMAPSTACK];
  512. short mapreturn[MAXMAPACTIONS];
  513. char buf[MAXLINE];
  514. /*
  515. **  Set up default hosts maps.
  516. */
  517. #if 0
  518. nmaps = switch_map_find("hosts", maptype, mapreturn);
  519. for (i = 0; i < nmaps; i++)
  520. {
  521. if (strcmp(maptype[i], "files") == 0 &&
  522.     stab("hosts.files", ST_MAP, ST_FIND) == NULL)
  523. {
  524. (void) strlcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts",
  525. sizeof buf);
  526. (void) makemapentry(buf);
  527. }
  528. # if NAMED_BIND
  529. else if (strcmp(maptype[i], "dns") == 0 &&
  530.     stab("hosts.dns", ST_MAP, ST_FIND) == NULL)
  531. {
  532. (void) strlcpy(buf, "hosts.dns dns A", sizeof buf);
  533. (void) makemapentry(buf);
  534. }
  535. # endif /* NAMED_BIND */
  536. # ifdef NISPLUS
  537. else if (strcmp(maptype[i], "nisplus") == 0 &&
  538.     stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL)
  539. {
  540. (void) strlcpy(buf, "hosts.nisplus nisplus -k name -v address hosts.org_dir",
  541. sizeof buf);
  542. (void) makemapentry(buf);
  543. }
  544. # endif /* NISPLUS */
  545. # ifdef NIS
  546. else if (strcmp(maptype[i], "nis") == 0 &&
  547.     stab("hosts.nis", ST_MAP, ST_FIND) == NULL)
  548. {
  549. (void) strlcpy(buf, "hosts.nis nis -k 0 -v 1 hosts.byname",
  550. sizeof buf);
  551. (void) makemapentry(buf);
  552. }
  553. # endif /* NIS */
  554. # if NETINFO
  555. else if (strcmp(maptype[i], "netinfo") == 0) &&
  556.     stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL)
  557. {
  558. (void) strlcpy(buf, "hosts.netinfo netinfo -v name /machines",
  559. sizeof buf);
  560. (void) makemapentry(buf);
  561. }
  562. # endif /* NETINFO */
  563. }
  564. #endif /* 0 */
  565. /*
  566. **  Make sure we have a host map.
  567. */
  568. if (stab("host", ST_MAP, ST_FIND) == NULL)
  569. {
  570. /* user didn't initialize: set up host map */
  571. (void) strlcpy(buf, "host host", sizeof buf);
  572. #if NAMED_BIND
  573. if (ConfigLevel >= 2)
  574. (void) strlcat(buf, " -a. -D", sizeof buf);
  575. #endif /* NAMED_BIND */
  576. (void) makemapentry(buf);
  577. }
  578. /*
  579. **  Set up default aliases maps
  580. */
  581. nmaps = switch_map_find("aliases", maptype, mapreturn);
  582. for (i = 0; i < nmaps; i++)
  583. {
  584. if (strcmp(maptype[i], "files") == 0 &&
  585.     stab("aliases.files", ST_MAP, ST_FIND) == NULL)
  586. {
  587. (void) strlcpy(buf, "aliases.files null", sizeof buf);
  588. (void) makemapentry(buf);
  589. }
  590. #ifdef NISPLUS
  591. else if (strcmp(maptype[i], "nisplus") == 0 &&
  592.     stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
  593. {
  594. (void) strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir",
  595. sizeof buf);
  596. (void) makemapentry(buf);
  597. }
  598. #endif /* NISPLUS */
  599. #ifdef NIS
  600. else if (strcmp(maptype[i], "nis") == 0 &&
  601.     stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
  602. {
  603. (void) strlcpy(buf, "aliases.nis nis mail.aliases",
  604. sizeof buf);
  605. (void) makemapentry(buf);
  606. }
  607. #endif /* NIS */
  608. #if NETINFO
  609. else if (strcmp(maptype[i], "netinfo") == 0 &&
  610.     stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
  611. {
  612. (void) strlcpy(buf, "aliases.netinfo netinfo -z, /aliases",
  613. sizeof buf);
  614. (void) makemapentry(buf);
  615. }
  616. #endif /* NETINFO */
  617. #ifdef HESIOD
  618. else if (strcmp(maptype[i], "hesiod") == 0 &&
  619.     stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
  620. {
  621. (void) strlcpy(buf, "aliases.hesiod hesiod aliases",
  622. sizeof buf);
  623. (void) makemapentry(buf);
  624. }
  625. #endif /* HESIOD */
  626. }
  627. if (stab("aliases", ST_MAP, ST_FIND) == NULL)
  628. {
  629. (void) strlcpy(buf, "aliases switch aliases", sizeof buf);
  630. (void) makemapentry(buf);
  631. }
  632. #if 0 /* "user" map class is a better choice */
  633. /*
  634. **  Set up default users maps.
  635. */
  636. nmaps = switch_map_find("passwd", maptype, mapreturn);
  637. for (i = 0; i < nmaps; i++)
  638. {
  639. if (strcmp(maptype[i], "files") == 0 &&
  640.     stab("users.files", ST_MAP, ST_FIND) == NULL)
  641. {
  642. (void) strlcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd",
  643. sizeof buf);
  644. (void) makemapentry(buf);
  645. }
  646. # ifdef NISPLUS
  647. else if (strcmp(maptype[i], "nisplus") == 0 &&
  648.     stab("users.nisplus", ST_MAP, ST_FIND) == NULL)
  649. {
  650. (void) strlcpy(buf, "users.nisplus nisplus -m -kname -vhome passwd.org_dir",
  651. sizeof buf);
  652. (void) makemapentry(buf);
  653. }
  654. # endif /* NISPLUS */
  655. # ifdef NIS
  656. else if (strcmp(maptype[i], "nis") == 0 &&
  657.     stab("users.nis", ST_MAP, ST_FIND) == NULL)
  658. {
  659. (void) strlcpy(buf, "users.nis nis -m passwd.byname",
  660. sizeof buf);
  661. (void) makemapentry(buf);
  662. }
  663. # endif /* NIS */
  664. # ifdef HESIOD
  665. else if (strcmp(maptype[i], "hesiod") == 0) &&
  666.     stab("users.hesiod", ST_MAP, ST_FIND) == NULL)
  667. {
  668. (void) strlcpy(buf, "users.hesiod hesiod", sizeof buf);
  669. (void) makemapentry(buf);
  670. }
  671. # endif /* HESIOD */
  672. }
  673. if (stab("users", ST_MAP, ST_FIND) == NULL)
  674. {
  675. (void) strlcpy(buf, "users switch -m passwd", sizeof buf);
  676. (void) makemapentry(buf);
  677. }
  678. #endif /* 0 */
  679. }
  680. /*
  681. **  SWITCH_MAP_FIND -- find the list of types associated with a map
  682. **
  683. ** This is the system-dependent interface to the service switch.
  684. **
  685. ** Parameters:
  686. ** service -- the name of the service of interest.
  687. ** maptype -- an out-array of strings containing the types
  688. ** of access to use for this service.  There can
  689. ** be at most MAXMAPSTACK types for a single service.
  690. ** mapreturn -- an out-array of return information bitmaps
  691. ** for the map.
  692. **
  693. ** Returns:
  694. ** The number of map types filled in, or -1 for failure.
  695. **
  696. ** Side effects:
  697. ** Preserves errno so nothing in the routine clobbers it.
  698. */
  699. #if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
  700. # define _USE_SUN_NSSWITCH_
  701. #endif /* defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) */
  702. #ifdef _USE_SUN_NSSWITCH_
  703. # include <nsswitch.h>
  704. #endif /* _USE_SUN_NSSWITCH_ */
  705. #if defined(ultrix) || (defined(__osf__) && defined(__alpha))
  706. # define _USE_DEC_SVC_CONF_
  707. #endif /* defined(ultrix) || (defined(__osf__) && defined(__alpha)) */
  708. #ifdef _USE_DEC_SVC_CONF_
  709. # include <sys/svcinfo.h>
  710. #endif /* _USE_DEC_SVC_CONF_ */
  711. int
  712. switch_map_find(service, maptype, mapreturn)
  713. char *service;
  714. char *maptype[MAXMAPSTACK];
  715. short mapreturn[MAXMAPACTIONS];
  716. {
  717. int svcno;
  718. int save_errno = errno;
  719. #ifdef _USE_SUN_NSSWITCH_
  720. struct __nsw_switchconfig *nsw_conf;
  721. enum __nsw_parse_err pserr;
  722. struct __nsw_lookup *lk;
  723. static struct __nsw_lookup lkp0 =
  724. { "files", {1, 0, 0, 0}, NULL, NULL };
  725. static struct __nsw_switchconfig lkp_default =
  726. { 0, "sendmail", 3, &lkp0 };
  727. for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
  728. mapreturn[svcno] = 0;
  729. if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
  730. lk = lkp_default.lookups;
  731. else
  732. lk = nsw_conf->lookups;
  733. svcno = 0;
  734. while (lk != NULL)
  735. {
  736. maptype[svcno] = lk->service_name;
  737. if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
  738. mapreturn[MA_NOTFOUND] |= 1 << svcno;
  739. if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
  740. mapreturn[MA_TRYAGAIN] |= 1 << svcno;
  741. if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
  742. mapreturn[MA_TRYAGAIN] |= 1 << svcno;
  743. svcno++;
  744. lk = lk->next;
  745. }
  746. errno = save_errno;
  747. return svcno;
  748. #endif /* _USE_SUN_NSSWITCH_ */
  749. #ifdef _USE_DEC_SVC_CONF_
  750. struct svcinfo *svcinfo;
  751. int svc;
  752. for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
  753. mapreturn[svcno] = 0;
  754. svcinfo = getsvc();
  755. if (svcinfo == NULL)
  756. goto punt;
  757. if (strcmp(service, "hosts") == 0)
  758. svc = SVC_HOSTS;
  759. else if (strcmp(service, "aliases") == 0)
  760. svc = SVC_ALIASES;
  761. else if (strcmp(service, "passwd") == 0)
  762. svc = SVC_PASSWD;
  763. else
  764. {
  765. errno = save_errno;
  766. return -1;
  767. }
  768. for (svcno = 0; svcno < SVC_PATHSIZE; svcno++)
  769. {
  770. switch (svcinfo->svcpath[svc][svcno])
  771. {
  772.   case SVC_LOCAL:
  773. maptype[svcno] = "files";
  774. break;
  775.   case SVC_YP:
  776. maptype[svcno] = "nis";
  777. break;
  778.   case SVC_BIND:
  779. maptype[svcno] = "dns";
  780. break;
  781. # ifdef SVC_HESIOD
  782.   case SVC_HESIOD:
  783. maptype[svcno] = "hesiod";
  784. break;
  785. # endif /* SVC_HESIOD */
  786.   case SVC_LAST:
  787. errno = save_errno;
  788. return svcno;
  789. }
  790. }
  791. errno = save_errno;
  792. return svcno;
  793. #endif /* _USE_DEC_SVC_CONF_ */
  794. #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
  795. /*
  796. **  Fall-back mechanism.
  797. */
  798. STAB *st;
  799. time_t now = curtime();
  800. for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
  801. mapreturn[svcno] = 0;
  802. if ((now - ServiceCacheTime) > (time_t) ServiceCacheMaxAge)
  803. {
  804. /* (re)read service switch */
  805. register FILE *fp;
  806. long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK;
  807. if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR,
  808.     DontBlameSendmail))
  809. sff |= SFF_NOWLINK;
  810. if (ConfigFileRead)
  811. ServiceCacheTime = now;
  812. fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff);
  813. if (fp != NULL)
  814. {
  815. char buf[MAXLINE];
  816. while (fgets(buf, sizeof buf, fp) != NULL)
  817. {
  818. register char *p;
  819. p = strpbrk(buf, "#n");
  820. if (p != NULL)
  821. *p = '';
  822. p = strpbrk(buf, " t");
  823. if (p != NULL)
  824. *p++ = '';
  825. if (buf[0] == '')
  826. continue;
  827. if (p == NULL)
  828. {
  829. sm_syslog(LOG_ERR, NOQID,
  830.   "Bad line on %.100s: %.100s",
  831.   ServiceSwitchFile,
  832.   buf);
  833. continue;
  834. }
  835. while (isspace(*p))
  836. p++;
  837. if (*p == '')
  838. continue;
  839. /*
  840. **  Find/allocate space for this service entry.
  841. ** Space for all of the service strings
  842. ** are allocated at once.  This means
  843. ** that we only have to free the first
  844. ** one to free all of them.
  845. */
  846. st = stab(buf, ST_SERVICE, ST_ENTER);
  847. if (st->s_service[0] != NULL)
  848. free((void *) st->s_service[0]);
  849. p = newstr(p);
  850. for (svcno = 0; svcno < MAXMAPSTACK; )
  851. {
  852. if (*p == '')
  853. break;
  854. st->s_service[svcno++] = p;
  855. p = strpbrk(p, " t");
  856. if (p == NULL)
  857. break;
  858. *p++ = '';
  859. while (isspace(*p))
  860. p++;
  861. }
  862. if (svcno < MAXMAPSTACK)
  863. st->s_service[svcno] = NULL;
  864. }
  865. (void) fclose(fp);
  866. }
  867. }
  868. /* look up entry in cache */
  869. st = stab(service, ST_SERVICE, ST_FIND);
  870. if (st != NULL && st->s_service[0] != NULL)
  871. {
  872. /* extract data */
  873. svcno = 0;
  874. while (svcno < MAXMAPSTACK)
  875. {
  876. maptype[svcno] = st->s_service[svcno];
  877. if (maptype[svcno++] == NULL)
  878. break;
  879. }
  880. errno = save_errno;
  881. return --svcno;
  882. }
  883. #endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */
  884. #if !defined(_USE_SUN_NSSWITCH_)
  885. /* if the service file doesn't work, use an absolute fallback */
  886. # ifdef _USE_DEC_SVC_CONF_
  887.   punt:
  888. # endif /* _USE_DEC_SVC_CONF_ */
  889. for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
  890. mapreturn[svcno] = 0;
  891. svcno = 0;
  892. if (strcmp(service, "aliases") == 0)
  893. {
  894. maptype[svcno++] = "files";
  895. # if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO)
  896. maptype[svcno++] = "netinfo";
  897. # endif /* defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) */
  898. # ifdef AUTO_NIS_ALIASES
  899. #  ifdef NISPLUS
  900. maptype[svcno++] = "nisplus";
  901. #  endif /* NISPLUS */
  902. #  ifdef NIS
  903. maptype[svcno++] = "nis";
  904. #  endif /* NIS */
  905. # endif /* AUTO_NIS_ALIASES */
  906. errno = save_errno;
  907. return svcno;
  908. }
  909. if (strcmp(service, "hosts") == 0)
  910. {
  911. # if NAMED_BIND
  912. maptype[svcno++] = "dns";
  913. # else /* NAMED_BIND */
  914. #  if defined(sun) && !defined(BSD)
  915. /* SunOS */
  916. maptype[svcno++] = "nis";
  917. #  endif /* defined(sun) && !defined(BSD) */
  918. # endif /* NAMED_BIND */
  919. # if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO)
  920. maptype[svcno++] = "netinfo";
  921. # endif /* defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) */
  922. maptype[svcno++] = "files";
  923. errno = save_errno;
  924. return svcno;
  925. }
  926. errno = save_errno;
  927. return -1;
  928. #endif /* !defined(_USE_SUN_NSSWITCH_) */
  929. }
  930. /*
  931. **  USERNAME -- return the user id of the logged in user.
  932. **
  933. ** Parameters:
  934. ** none.
  935. **
  936. ** Returns:
  937. ** The login name of the logged in user.
  938. **
  939. ** Side Effects:
  940. ** none.
  941. **
  942. ** Notes:
  943. ** The return value is statically allocated.
  944. */
  945. char *
  946. username()
  947. {
  948. static char *myname = NULL;
  949. extern char *getlogin();
  950. register struct passwd *pw;
  951. /* cache the result */
  952. if (myname == NULL)
  953. {
  954. myname = getlogin();
  955. if (myname == NULL || myname[0] == '')
  956. {
  957. pw = sm_getpwuid(RealUid);
  958. if (pw != NULL)
  959. myname = newstr(pw->pw_name);
  960. }
  961. else
  962. {
  963. uid_t uid = RealUid;
  964. myname = newstr(myname);
  965. if ((pw = sm_getpwnam(myname)) == NULL ||
  966.       (uid != 0 && uid != pw->pw_uid))
  967. {
  968. pw = sm_getpwuid(uid);
  969. if (pw != NULL)
  970. myname = newstr(pw->pw_name);
  971. }
  972. }
  973. if (myname == NULL || myname[0] == '')
  974. {
  975. syserr("554 5.3.0 Who are you?");
  976. myname = "postmaster";
  977. }
  978. }
  979. return myname;
  980. }
  981. /*
  982. **  TTYPATH -- Get the path of the user's tty
  983. **
  984. ** Returns the pathname of the user's tty.  Returns NULL if
  985. ** the user is not logged in or if s/he has write permission
  986. ** denied.
  987. **
  988. ** Parameters:
  989. ** none
  990. **
  991. ** Returns:
  992. ** pathname of the user's tty.
  993. ** NULL if not logged in or write permission denied.
  994. **
  995. ** Side Effects:
  996. ** none.
  997. **
  998. ** WARNING:
  999. ** Return value is in a local buffer.
  1000. **
  1001. ** Called By:
  1002. ** savemail
  1003. */
  1004. char *
  1005. ttypath()
  1006. {
  1007. struct stat stbuf;
  1008. register char *pathn;
  1009. extern char *ttyname();
  1010. extern char *getlogin();
  1011. /* compute the pathname of the controlling tty */
  1012. if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
  1013.     (pathn = ttyname(0)) == NULL)
  1014. {
  1015. errno = 0;
  1016. return NULL;
  1017. }
  1018. /* see if we have write permission */
  1019. if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode))
  1020. {
  1021. errno = 0;
  1022. return NULL;
  1023. }
  1024. /* see if the user is logged in */
  1025. if (getlogin() == NULL)
  1026. return NULL;
  1027. /* looks good */
  1028. return pathn;
  1029. }
  1030. /*
  1031. **  CHECKCOMPAT -- check for From and To person compatible.
  1032. **
  1033. ** This routine can be supplied on a per-installation basis
  1034. ** to determine whether a person is allowed to send a message.
  1035. ** This allows restriction of certain types of internet
  1036. ** forwarding or registration of users.
  1037. **
  1038. ** If the hosts are found to be incompatible, an error
  1039. ** message should be given using "usrerr" and an EX_ code
  1040. ** should be returned.  You can also set to->q_status to
  1041. ** a DSN-style status code.
  1042. **
  1043. ** EF_NO_BODY_RETN can be set in e->e_flags to suppress the
  1044. ** body during the return-to-sender function; this should be done
  1045. ** on huge messages.  This bit may already be set by the ESMTP
  1046. ** protocol.
  1047. **
  1048. ** Parameters:
  1049. ** to -- the person being sent to.
  1050. **
  1051. ** Returns:
  1052. ** an exit status
  1053. **
  1054. ** Side Effects:
  1055. ** none (unless you include the usrerr stuff)
  1056. */
  1057. int
  1058. checkcompat(to, e)
  1059. register ADDRESS *to;
  1060. register ENVELOPE *e;
  1061. {
  1062. if (tTd(49, 1))
  1063. dprintf("checkcompat(to=%s, from=%s)n",
  1064. to->q_paddr, e->e_from.q_paddr);
  1065. #ifdef EXAMPLE_CODE
  1066. /* this code is intended as an example only */
  1067. register STAB *s;
  1068. s = stab("arpa", ST_MAILER, ST_FIND);
  1069. if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
  1070.     to->q_mailer == s->s_mailer)
  1071. {
  1072. usrerr("553 No ARPA mail through this machine: see your system administration");
  1073. /* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */
  1074. to->q_status = "5.7.1";
  1075. return EX_UNAVAILABLE;
  1076. }
  1077. #endif /* EXAMPLE_CODE */
  1078. return EX_OK;
  1079. }
  1080. /*
  1081. **  SETSIGNAL -- set a signal handler
  1082. **
  1083. ** This is essentially old BSD "signal(3)".
  1084. */
  1085. sigfunc_t
  1086. setsignal(sig, handler)
  1087. int sig;
  1088. sigfunc_t handler;
  1089. {
  1090. /*
  1091. **  First, try for modern signal calls
  1092. **  and restartable syscalls
  1093. */
  1094. #ifdef SA_RESTART
  1095. struct sigaction n, o;
  1096. memset(&n, '', sizeof n);
  1097. # if USE_SA_SIGACTION
  1098. n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler;
  1099. n.sa_flags = SA_RESTART|SA_SIGINFO;
  1100. # else /* USE_SA_SIGACTION */
  1101. n.sa_handler = handler;
  1102. n.sa_flags = SA_RESTART;
  1103. # endif /* USE_SA_SIGACTION */
  1104. if (sigaction(sig, &n, &o) < 0)
  1105. return SIG_ERR;
  1106. return o.sa_handler;
  1107. #else /* SA_RESTART */
  1108. /*
  1109. **  Else check for SYS5SIGNALS or
  1110. **  BSD4_3 signals
  1111. */
  1112. # if defined(SYS5SIGNALS) || defined(BSD4_3)
  1113. #  ifdef BSD4_3
  1114. return signal(sig, handler);
  1115. #  else /* BSD4_3 */
  1116. return sigset(sig, handler);
  1117. #  endif /* BSD4_3 */
  1118. # else /* defined(SYS5SIGNALS) || defined(BSD4_3) */
  1119. /*
  1120. **  Finally, if nothing else is available,
  1121. **  go for a default
  1122. */
  1123. struct sigaction n, o;
  1124. memset(&n, '', sizeof n);
  1125. n.sa_handler = handler;
  1126. if (sigaction(sig, &n, &o) < 0)
  1127. return SIG_ERR;
  1128. return o.sa_handler;
  1129. # endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */
  1130. #endif /* SA_RESTART */
  1131. }
  1132. /*
  1133. **  BLOCKSIGNAL -- hold a signal to prevent delivery
  1134. **
  1135. ** Parameters:
  1136. ** sig -- the signal to block.
  1137. **
  1138. ** Returns:
  1139. ** 1 signal was previously blocked
  1140. ** 0 signal was not previously blocked
  1141. ** -1 on failure.
  1142. */
  1143. int
  1144. blocksignal(sig)
  1145. int sig;
  1146. {
  1147. #ifdef BSD4_3
  1148. # ifndef sigmask
  1149. #  define sigmask(s) (1 << ((s) - 1))
  1150. # endif /* ! sigmask */
  1151. return (sigblock(sigmask(sig)) & sigmask(sig)) != 0;
  1152. #else /* BSD4_3 */
  1153. # ifdef ALTOS_SYSTEM_V
  1154. sigfunc_t handler;
  1155. handler = sigset(sig, SIG_HOLD);
  1156. if (handler == SIG_ERR)
  1157. return -1;
  1158. else
  1159. return handler == SIG_HOLD;
  1160. # else /* ALTOS_SYSTEM_V */
  1161. sigset_t sset, oset;
  1162. (void) sigemptyset(&sset);
  1163. (void) sigaddset(&sset, sig);
  1164. if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0)
  1165. return -1;
  1166. else
  1167. return sigismember(&oset, sig);
  1168. # endif /* ALTOS_SYSTEM_V */
  1169. #endif /* BSD4_3 */
  1170. }
  1171. /*
  1172. **  RELEASESIGNAL -- release a held signal
  1173. **
  1174. ** Parameters:
  1175. ** sig -- the signal to release.
  1176. **
  1177. ** Returns:
  1178. ** 1 signal was previously blocked
  1179. ** 0 signal was not previously blocked
  1180. ** -1 on failure.
  1181. */
  1182. int
  1183. releasesignal(sig)
  1184. int sig;
  1185. {
  1186. #ifdef BSD4_3
  1187. return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0;
  1188. #else /* BSD4_3 */
  1189. # ifdef ALTOS_SYSTEM_V
  1190. sigfunc_t handler;
  1191. handler = sigset(sig, SIG_HOLD);
  1192. if (sigrelse(sig) < 0)
  1193. return -1;
  1194. else
  1195. return handler == SIG_HOLD;
  1196. # else /* ALTOS_SYSTEM_V */
  1197. sigset_t sset, oset;
  1198. (void) sigemptyset(&sset);
  1199. (void) sigaddset(&sset, sig);
  1200. if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0)
  1201. return -1;
  1202. else
  1203. return sigismember(&oset, sig);
  1204. # endif /* ALTOS_SYSTEM_V */
  1205. #endif /* BSD4_3 */
  1206. }
  1207. /*
  1208. **  HOLDSIGS -- arrange to hold all signals
  1209. **
  1210. ** Parameters:
  1211. ** none.
  1212. **
  1213. ** Returns:
  1214. ** none.
  1215. **
  1216. ** Side Effects:
  1217. ** Arranges that signals are held.
  1218. */
  1219. void
  1220. holdsigs()
  1221. {
  1222. }
  1223. /*
  1224. **  RLSESIGS -- arrange to release all signals
  1225. **
  1226. ** This undoes the effect of holdsigs.
  1227. **
  1228. ** Parameters:
  1229. ** none.
  1230. **
  1231. ** Returns:
  1232. ** none.
  1233. **
  1234. ** Side Effects:
  1235. ** Arranges that signals are released.
  1236. */
  1237. void
  1238. rlsesigs()
  1239. {
  1240. }
  1241. /*
  1242. **  INIT_MD -- do machine dependent initializations
  1243. **
  1244. ** Systems that have global modes that should be set should do
  1245. ** them here rather than in main.
  1246. */
  1247. #ifdef _AUX_SOURCE
  1248. # include <compat.h>
  1249. #endif /* _AUX_SOURCE */
  1250. #if SHARE_V1
  1251. # include <shares.h>
  1252. #endif /* SHARE_V1 */
  1253. void
  1254. init_md(argc, argv)
  1255. int argc;
  1256. char **argv;
  1257. {
  1258. #ifdef _AUX_SOURCE
  1259. setcompat(getcompat() | COMPAT_BSDPROT);
  1260. #endif /* _AUX_SOURCE */
  1261. #ifdef SUN_EXTENSIONS
  1262. init_md_sun();
  1263. #endif /* SUN_EXTENSIONS */
  1264. #if _CONVEX_SOURCE
  1265. /* keep gethostby*() from stripping the local domain name */
  1266. set_domain_trim_off();
  1267. #endif /* _CONVEX_SOURCE */
  1268. #ifdef __QNX__
  1269. /*
  1270. **  Due to QNX's network distributed nature, you can target a tcpip
  1271. **  stack on a different node in the qnx network; this patch lets
  1272. **  this feature work.  The __sock_locate() must be done before the
  1273. **  environment is clear.
  1274. */
  1275. __sock_locate();
  1276. #endif /* __QNX__ */
  1277. #if SECUREWARE || defined(_SCO_unix_)
  1278. set_auth_parameters(argc, argv);
  1279. # ifdef _SCO_unix_
  1280. /*
  1281. **  This is required for highest security levels (the kernel
  1282. **  won't let it call set*uid() or run setuid binaries without
  1283. **  it).  It may be necessary on other SECUREWARE systems.
  1284. */
  1285. if (getluid() == -1)
  1286. setluid(0);
  1287. # endif /* _SCO_unix_ */
  1288. #endif /* SECUREWARE || defined(_SCO_unix_) */
  1289. #ifdef VENDOR_DEFAULT
  1290. VendorCode = VENDOR_DEFAULT;
  1291. #else /* VENDOR_DEFAULT */
  1292. VendorCode = VENDOR_BERKELEY;
  1293. #endif /* VENDOR_DEFAULT */
  1294. }
  1295. /*
  1296. **  INIT_VENDOR_MACROS -- vendor-dependent macro initializations
  1297. **
  1298. ** Called once, on startup.
  1299. **
  1300. ** Parameters:
  1301. ** e -- the global envelope.
  1302. **
  1303. ** Returns:
  1304. ** none.
  1305. **
  1306. ** Side Effects:
  1307. ** vendor-dependent.
  1308. */
  1309. void
  1310. init_vendor_macros(e)
  1311. register ENVELOPE *e;
  1312. {
  1313. }
  1314. /*
  1315. **  GETLA -- get the current load average
  1316. **
  1317. ** This code stolen from la.c.
  1318. **
  1319. ** Parameters:
  1320. ** none.
  1321. **
  1322. ** Returns:
  1323. ** The current load average as an integer.
  1324. **
  1325. ** Side Effects:
  1326. ** none.
  1327. */
  1328. /* try to guess what style of load average we have */
  1329. #define LA_ZERO 1 /* always return load average as zero */
  1330. #define LA_INT 2 /* read kmem for avenrun; interpret as long */
  1331. #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */
  1332. #define LA_SUBR 4 /* call getloadavg */
  1333. #define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */
  1334. #define LA_SHORT 6 /* read kmem for avenrun; interpret as short */
  1335. #define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */
  1336. #define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */
  1337. #define LA_DGUX 9 /* special DGUX implementation */
  1338. #define LA_HPUX 10 /* special HPUX implementation */
  1339. #define LA_IRIX6 11 /* special IRIX 6.2 implementation */
  1340. #define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */
  1341. #define LA_DEVSHORT 13 /* read short from a device */
  1342. #define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */
  1343. /* do guesses based on general OS type */
  1344. #ifndef LA_TYPE
  1345. # define LA_TYPE LA_ZERO
  1346. #endif /* ! LA_TYPE */
  1347. #ifndef FSHIFT
  1348. # if defined(unixpc)
  1349. #  define FSHIFT 5
  1350. # endif /* defined(unixpc) */
  1351. # if defined(__alpha) || defined(IRIX)
  1352. #  define FSHIFT 10
  1353. # endif /* defined(__alpha) || defined(IRIX) */
  1354. #endif /* ! FSHIFT */
  1355. #ifndef FSHIFT
  1356. # define FSHIFT 8
  1357. #endif /* ! FSHIFT */
  1358. #ifndef FSCALE
  1359. # define FSCALE (1 << FSHIFT)
  1360. #endif /* ! FSCALE */
  1361. #ifndef LA_AVENRUN
  1362. # ifdef SYSTEM5
  1363. #  define LA_AVENRUN "avenrun"
  1364. # else /* SYSTEM5 */
  1365. #  define LA_AVENRUN "_avenrun"
  1366. # endif /* SYSTEM5 */
  1367. #endif /* ! LA_AVENRUN */
  1368. /* _PATH_KMEM should be defined in <paths.h> */
  1369. #ifndef _PATH_KMEM
  1370. # define _PATH_KMEM "/dev/kmem"
  1371. #endif /* ! _PATH_KMEM */
  1372. #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT)
  1373. # include <nlist.h>
  1374. /* _PATH_UNIX should be defined in <paths.h> */
  1375. # ifndef _PATH_UNIX
  1376. #  if defined(SYSTEM5)
  1377. #   define _PATH_UNIX "/unix"
  1378. #  else /* defined(SYSTEM5) */
  1379. #   define _PATH_UNIX "/vmunix"
  1380. #  endif /* defined(SYSTEM5) */
  1381. # endif /* ! _PATH_UNIX */
  1382. # ifdef _AUX_SOURCE
  1383. struct nlist Nl[2];
  1384. # else /* _AUX_SOURCE */
  1385. struct nlist Nl[] =
  1386. {
  1387. { LA_AVENRUN },
  1388. { 0 },
  1389. };
  1390. # endif /* _AUX_SOURCE */
  1391. # define X_AVENRUN 0
  1392. static int
  1393. getla()
  1394. {
  1395. static int kmem = -1;
  1396. # if LA_TYPE == LA_INT
  1397. long avenrun[3];
  1398. # else /* LA_TYPE == LA_INT */
  1399. #  if LA_TYPE == LA_SHORT
  1400. short avenrun[3];
  1401. #  else /* LA_TYPE == LA_SHORT */
  1402. double avenrun[3];
  1403. #  endif /* LA_TYPE == LA_SHORT */
  1404. # endif /* LA_TYPE == LA_INT */
  1405. extern int errno;
  1406. extern off_t lseek();
  1407. if (kmem < 0)
  1408. {
  1409. # ifdef _AUX_SOURCE
  1410. (void) strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN,
  1411.        sizeof Nl[X_AVENRUN].n_name);
  1412. Nl[1].n_name[0] = '';
  1413. # endif /* _AUX_SOURCE */
  1414. # if defined(_AIX3) || defined(_AIX4)
  1415. if (knlist(Nl, 1, sizeof Nl[0]) < 0)
  1416. # else /* defined(_AIX3) || defined(_AIX4) */
  1417. if (nlist(_PATH_UNIX, Nl) < 0)
  1418. # endif /* defined(_AIX3) || defined(_AIX4) */
  1419. {
  1420. if (tTd(3, 1))
  1421. dprintf("getla: nlist(%s): %sn", _PATH_UNIX,
  1422. errstring(errno));
  1423. return -1;
  1424. }
  1425. if (Nl[X_AVENRUN].n_value == 0)
  1426. {
  1427. if (tTd(3, 1))
  1428. dprintf("getla: nlist(%s, %s) ==> 0n",
  1429. _PATH_UNIX, LA_AVENRUN);
  1430. return -1;
  1431. }
  1432. # ifdef NAMELISTMASK
  1433. Nl[X_AVENRUN].n_value &= NAMELISTMASK;
  1434. # endif /* NAMELISTMASK */
  1435. kmem = open(_PATH_KMEM, 0, 0);
  1436. if (kmem < 0)
  1437. {
  1438. if (tTd(3, 1))
  1439. dprintf("getla: open(/dev/kmem): %sn",
  1440. errstring(errno));
  1441. return -1;
  1442. }
  1443. (void) fcntl(kmem, F_SETFD, FD_CLOEXEC);
  1444. }
  1445. if (tTd(3, 20))
  1446. dprintf("getla: symbol address = %#lxn",
  1447. (u_long) Nl[X_AVENRUN].n_value);
  1448. if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 ||
  1449.     read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
  1450. {
  1451. /* thank you Ian */
  1452. if (tTd(3, 1))
  1453. dprintf("getla: lseek or read: %sn",
  1454. errstring(errno));
  1455. return -1;
  1456. }
  1457. # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
  1458. if (tTd(3, 5))
  1459. {
  1460. #  if LA_TYPE == LA_SHORT
  1461. dprintf("getla: avenrun = %d", avenrun[0]);
  1462. if (tTd(3, 15))
  1463. dprintf(", %d, %d", avenrun[1], avenrun[2]);
  1464. #  else /* LA_TYPE == LA_SHORT */
  1465. dprintf("getla: avenrun = %ld", avenrun[0]);
  1466. if (tTd(3, 15))
  1467. dprintf(", %ld, %ld", avenrun[1], avenrun[2]);
  1468. #  endif /* LA_TYPE == LA_SHORT */
  1469. dprintf("n");
  1470. }
  1471. if (tTd(3, 1))
  1472. dprintf("getla: %dn",
  1473. (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
  1474. return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
  1475. # else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */
  1476. if (tTd(3, 5))
  1477. {
  1478. dprintf("getla: avenrun = %g", avenrun[0]);
  1479. if (tTd(3, 15))
  1480. dprintf(", %g, %g", avenrun[1], avenrun[2]);
  1481. dprintf("n");
  1482. }
  1483. if (tTd(3, 1))
  1484. dprintf("getla: %dn", (int) (avenrun[0] +0.5));
  1485. return ((int) (avenrun[0] + 0.5));
  1486. # endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */
  1487. }
  1488. #endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) */
  1489. #if LA_TYPE == LA_READKSYM
  1490. # include <sys/ksym.h>
  1491. static int
  1492. getla()
  1493. {
  1494. static int kmem = -1;
  1495. long avenrun[3];
  1496. extern int errno;
  1497. struct mioc_rksym mirk;
  1498. if (kmem < 0)
  1499. {
  1500. kmem = open("/dev/kmem", 0, 0);
  1501. if (kmem < 0)
  1502. {
  1503. if (tTd(3, 1))
  1504. dprintf("getla: open(/dev/kmem): %sn",
  1505. errstring(errno));
  1506. return -1;
  1507. }
  1508. (void) fcntl(kmem, F_SETFD, FD_CLOEXEC);
  1509. }
  1510. mirk.mirk_symname = LA_AVENRUN;
  1511. mirk.mirk_buf = avenrun;
  1512. mirk.mirk_buflen = sizeof(avenrun);
  1513. if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
  1514. {
  1515. if (tTd(3, 1))
  1516. dprintf("getla: ioctl(MIOC_READKSYM) failed: %sn",
  1517. errstring(errno));
  1518. return -1;
  1519. }
  1520. if (tTd(3, 5))
  1521. {
  1522. dprintf("getla: avenrun = %d", avenrun[0]);
  1523. if (tTd(3, 15))
  1524. dprintf(", %d, %d", avenrun[1], avenrun[2]);
  1525. dprintf("n");
  1526. }
  1527. if (tTd(3, 1))
  1528. dprintf("getla: %dn",
  1529. (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
  1530. return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
  1531. }
  1532. #endif /* LA_TYPE == LA_READKSYM */
  1533. #if LA_TYPE == LA_DGUX
  1534. # include <sys/dg_sys_info.h>
  1535. static int
  1536. getla()
  1537. {
  1538. struct dg_sys_info_load_info load_info;
  1539. dg_sys_info((long *)&load_info,
  1540. DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
  1541. if (tTd(3, 1))
  1542. dprintf("getla: %dn", (int) (load_info.one_minute + 0.5));
  1543. return ((int) (load_info.one_minute + 0.5));
  1544. }
  1545. #endif /* LA_TYPE == LA_DGUX */
  1546. #if LA_TYPE == LA_HPUX
  1547. /* forward declarations to keep gcc from complaining */
  1548. struct pst_dynamic;
  1549. struct pst_status;
  1550. struct pst_static;
  1551. struct pst_vminfo;
  1552. struct pst_diskinfo;
  1553. struct pst_processor;
  1554. struct pst_lv;
  1555. struct pst_swapinfo;
  1556. # include <sys/param.h>
  1557. # include <sys/pstat.h>
  1558. static int
  1559. getla()
  1560. {
  1561. struct pst_dynamic pstd;
  1562. if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
  1563.      (size_t) 1, 0) == -1)
  1564. return 0;
  1565. if (tTd(3, 1))
  1566. dprintf("getla: %dn", (int) (pstd.psd_avg_1_min + 0.5));
  1567. return (int) (pstd.psd_avg_1_min + 0.5);
  1568. }
  1569. #endif /* LA_TYPE == LA_HPUX */
  1570. #if LA_TYPE == LA_SUBR
  1571. static int
  1572. getla()
  1573. {
  1574. double avenrun[3];
  1575. if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
  1576. {
  1577. if (tTd(3, 1))
  1578. dprintf("getla: getloadavg failed: %s",
  1579. errstring(errno));
  1580. return -1;
  1581. }
  1582. if (tTd(3, 1))
  1583. dprintf("getla: %dn", (int) (avenrun[0] +0.5));
  1584. return ((int) (avenrun[0] + 0.5));
  1585. }
  1586. #endif /* LA_TYPE == LA_SUBR */
  1587. #if LA_TYPE == LA_MACH
  1588. /*
  1589. **  This has been tested on NEXTSTEP release 2.1/3.X.
  1590. */
  1591. # if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
  1592. #  include <mach/mach.h>
  1593. # else /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */
  1594. #  include <mach.h>
  1595. # endif /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */
  1596. static int
  1597. getla()
  1598. {
  1599. processor_set_t default_set;
  1600. kern_return_t error;
  1601. unsigned int info_count;
  1602. struct processor_set_basic_info info;
  1603. host_t host;
  1604. error = processor_set_default(host_self(), &default_set);
  1605. if (error != KERN_SUCCESS)
  1606. {
  1607. if (tTd(3, 1))
  1608. dprintf("getla: processor_set_default failed: %s",
  1609. errstring(errno));
  1610. return -1;
  1611. }
  1612. info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
  1613. if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
  1614.        &host, (processor_set_info_t)&info,
  1615.        &info_count) != KERN_SUCCESS)
  1616. {
  1617. if (tTd(3, 1))
  1618. dprintf("getla: processor_set_info failed: %s",
  1619. errstring(errno));
  1620. return -1;
  1621. }
  1622. if (tTd(3, 1))
  1623. dprintf("getla: %dn",
  1624. (int) ((info.load_average + (LOAD_SCALE / 2)) /
  1625.        LOAD_SCALE));
  1626. return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
  1627. }
  1628. #endif /* LA_TYPE == LA_MACH */
  1629. #if LA_TYPE == LA_PROCSTR
  1630. /*
  1631. **  Read /proc/loadavg for the load average.  This is assumed to be
  1632. **  in a format like "0.15 0.12 0.06".
  1633. **
  1634. ** Initially intended for Linux.  This has been in the kernel
  1635. ** since at least 0.99.15.
  1636. */
  1637. # ifndef _PATH_LOADAVG
  1638. #  define _PATH_LOADAVG "/proc/loadavg"
  1639. # endif /* ! _PATH_LOADAVG */
  1640. static int
  1641. getla()
  1642. {
  1643. double avenrun;
  1644. register int result;
  1645. FILE *fp;
  1646. fp = fopen(_PATH_LOADAVG, "r");
  1647. if (fp == NULL)
  1648. {
  1649. if (tTd(3, 1))
  1650. dprintf("getla: fopen(%s): %sn",
  1651. _PATH_LOADAVG, errstring(errno));
  1652. return -1;
  1653. }
  1654. result = fscanf(fp, "%lf", &avenrun);
  1655. (void) fclose(fp);
  1656. if (result != 1)
  1657. {
  1658. if (tTd(3, 1))
  1659. dprintf("getla: fscanf() = %d: %sn",
  1660. result, errstring(errno));
  1661. return -1;
  1662. }
  1663. if (tTd(3, 1))
  1664. dprintf("getla(): %.2fn", avenrun);
  1665. return ((int) (avenrun + 0.5));
  1666. }
  1667. #endif /* LA_TYPE == LA_PROCSTR */
  1668. #if LA_TYPE == LA_IRIX6
  1669. # include <sys/sysmp.h>
  1670. int getla(void)
  1671. {
  1672. static int kmem = -1;
  1673. int avenrun[3];
  1674. if (kmem < 0)
  1675. {
  1676. kmem = open(_PATH_KMEM, 0, 0);
  1677. if (kmem < 0)
  1678. {
  1679. if (tTd(3, 1))
  1680. dprintf("getla: open(%s): %sn", _PATH_KMEM,
  1681. errstring(errno));
  1682. return -1;
  1683. }
  1684. (void) fcntl(kmem, F_SETFD, FD_CLOEXEC);
  1685. }
  1686. if (lseek(kmem, (sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff), SEEK_SET) == -1 ||
  1687.     read(kmem, (char *)avenrun, sizeof(avenrun)) < sizeof(avenrun))
  1688. {
  1689. if (tTd(3, 1))
  1690. dprintf("getla: lseek or read: %sn",
  1691. errstring(errno));
  1692. return -1;
  1693. }
  1694. if (tTd(3, 5))
  1695. {
  1696. dprintf("getla: avenrun = %ld", (long int) avenrun[0]);
  1697. if (tTd(3, 15))
  1698. dprintf(", %ld, %ld",
  1699. (long int) avenrun[1], (long int) avenrun[2]);
  1700. dprintf("n");
  1701. }
  1702. if (tTd(3, 1))
  1703. dprintf("getla: %dn",
  1704. (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
  1705. return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
  1706. }
  1707. #endif /* LA_TYPE == LA_IRIX6 */
  1708. #if LA_TYPE == LA_KSTAT
  1709. # include <kstat.h>
  1710. static int
  1711. getla()
  1712. {
  1713. static kstat_ctl_t *kc = NULL;
  1714. static kstat_t *ksp = NULL;
  1715. kstat_named_t *ksn;
  1716. int la;
  1717. if (kc == NULL) /* if not initialized before */
  1718. kc = kstat_open();
  1719. if (kc == NULL)
  1720. {
  1721. if (tTd(3, 1))
  1722. dprintf("getla: kstat_open(): %sn",
  1723. errstring(errno));
  1724. return -1;
  1725. }
  1726. if (ksp == NULL)
  1727. ksp = kstat_lookup(kc, "unix", 0, "system_misc");
  1728. if (ksp == NULL)
  1729. {
  1730. if (tTd(3, 1))
  1731. dprintf("getla: kstat_lookup(): %sn",
  1732. errstring(errno));
  1733. return -1;
  1734. }
  1735. if (kstat_read(kc, ksp, NULL) < 0)
  1736. {
  1737. if (tTd(3, 1))
  1738. dprintf("getla: kstat_read(): %sn",
  1739. errstring(errno));
  1740. return -1;
  1741. }
  1742. ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
  1743. la = ((double)ksn->value.ul + FSCALE/2) / FSCALE;
  1744. /* kstat_close(kc); /o do not close for fast access */
  1745. return la;
  1746. }
  1747. #endif /* LA_TYPE == LA_KSTAT */
  1748. #if LA_TYPE == LA_DEVSHORT
  1749. /*
  1750. **  Read /dev/table/avenrun for the load average.  This should contain
  1751. **  three shorts for the 1, 5, and 15 minute loads.  We only read the
  1752. **  first, since that's all we care about.
  1753. **
  1754. ** Intended for SCO OpenServer 5.
  1755. */
  1756. # ifndef _PATH_AVENRUN
  1757. #  define _PATH_AVENRUN "/dev/table/avenrun"
  1758. # endif /* ! _PATH_AVENRUN */
  1759. static int
  1760. getla()
  1761. {
  1762. static int afd = -1;
  1763. short avenrun;
  1764. int loadav;
  1765. int r;
  1766. errno = EBADF;
  1767. if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
  1768. {
  1769. if (errno != EBADF)
  1770. return -1;
  1771. afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
  1772. if (afd < 0)
  1773. {
  1774. sm_syslog(LOG_ERR, NOQID,
  1775. "can't open %s: %m",
  1776. _PATH_AVENRUN);
  1777. return -1;
  1778. }
  1779. }
  1780. r = read(afd, &avenrun, sizeof avenrun);
  1781. if (tTd(3, 5))
  1782. dprintf("getla: avenrun = %dn", avenrun);
  1783. loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
  1784. if (tTd(3, 1))
  1785. dprintf("getla: %dn", loadav);
  1786. return loadav;
  1787. }
  1788. #endif /* LA_TYPE == LA_DEVSHORT */
  1789. #if LA_TYPE == LA_ALPHAOSF
  1790. struct rtentry;
  1791. struct mbuf;
  1792. # include <sys/table.h>
  1793. int getla()
  1794. {
  1795. int ave = 0;
  1796. struct tbl_loadavg tab;
  1797. if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1)
  1798. {
  1799. if (tTd(3, 1))
  1800. dprintf("getla: table %sn", errstring(errno));
  1801. return -1;
  1802. }
  1803. if (tTd(3, 1))
  1804. dprintf("getla: scale = %dn", tab.tl_lscale);
  1805. if (tab.tl_lscale)
  1806. ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) /
  1807.        tab.tl_lscale);
  1808. else
  1809. ave = (int) (tab.tl_avenrun.d[2] + 0.5);
  1810. if (tTd(3, 1))
  1811. dprintf("getla: %dn", ave);
  1812. return ave;
  1813. }
  1814. #endif /* LA_TYPE == LA_ALPHAOSF */
  1815. #if LA_TYPE == LA_ZERO
  1816. static int
  1817. getla()
  1818. {
  1819. if (tTd(3, 1))
  1820. dprintf("getla: ZEROn");
  1821. return 0;
  1822. }
  1823. #endif /* LA_TYPE == LA_ZERO */
  1824. /*
  1825.  * Copyright 1989 Massachusetts Institute of Technology
  1826.  *
  1827.  * Permission to use, copy, modify, distribute, and sell this software and its
  1828.  * documentation for any purpose is hereby granted without fee, provided that
  1829.  * the above copyright notice appear in all copies and that both that
  1830.  * copyright notice and this permission notice appear in supporting
  1831.  * documentation, and that the name of M.I.T. not be used in advertising or
  1832.  * publicity pertaining to distribution of the software without specific,
  1833.  * written prior permission.  M.I.T. makes no representations about the
  1834.  * suitability of this software for any purpose.  It is provided "as is"
  1835.  * without express or implied warranty.
  1836.  *
  1837.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  1838.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  1839.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  1840.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  1841.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  1842.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1843.  *
  1844.  * Authors:  Many and varied...
  1845.  */
  1846. /* Non Apollo stuff removed by Don Lewis 11/15/93 */
  1847. #ifndef lint
  1848. static char  rcsid[] = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
  1849. #endif /* ! lint */
  1850. #ifdef apollo
  1851. # undef volatile
  1852. # include <apollo/base.h>
  1853. /* ARGSUSED */
  1854. int getloadavg( call_data )
  1855.      caddr_t call_data; /* pointer to (double) return value */
  1856. {
  1857.      double *avenrun = (double *) call_data;
  1858.      int i;
  1859.      status_$t      st;
  1860.      long loadav[3];
  1861.      proc1_$get_loadav(loadav, &st);
  1862.      *avenrun = loadav[0] / (double) (1 << 16);
  1863.      return 0;
  1864. }
  1865. #endif /* apollo */
  1866. /*
  1867. **  SM_GETLA -- get the current load average and set macro
  1868. **
  1869. ** Parameters:
  1870. ** e -- the envelope for the load average macro.
  1871. **
  1872. ** Returns:
  1873. ** The current load average as an integer.
  1874. **
  1875. ** Side Effects:
  1876. ** Sets the load average macro ({load_avg}) if
  1877. ** envelope e is not NULL.
  1878. */
  1879. int
  1880. sm_getla(e)
  1881. ENVELOPE *e;
  1882. {
  1883. register int la;
  1884. la = getla();
  1885. if (e != NULL)
  1886. {
  1887. char labuf[8];
  1888. snprintf(labuf, sizeof labuf, "%d", CurrentLA);
  1889. define(macid("{load_avg}", NULL), newstr(labuf), e);
  1890. }
  1891. return la;
  1892. }
  1893. /*
  1894. **  SHOULDQUEUE -- should this message be queued or sent?
  1895. **
  1896. ** Compares the message cost to the load average to decide.
  1897. **
  1898. ** Parameters:
  1899. ** pri -- the priority of the message in question.
  1900. ** ct -- the message creation time.
  1901. **
  1902. ** Returns:
  1903. ** TRUE -- if this message should be queued up for the
  1904. ** time being.
  1905. ** FALSE -- if the load is low enough to send this message.
  1906. **
  1907. ** Side Effects:
  1908. ** none.
  1909. */
  1910. /* ARGSUSED1 */
  1911. bool
  1912. shouldqueue(pri, ct)
  1913. long pri;
  1914. time_t ct;
  1915. {
  1916. bool rval;
  1917. if (tTd(3, 30))
  1918. dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ",
  1919. CurrentLA, pri);
  1920. if (CurrentLA < QueueLA)
  1921. {
  1922. if (tTd(3, 30))
  1923. dprintf("FALSE (CurrentLA < QueueLA)n");
  1924. return FALSE;
  1925. }
  1926. #if 0 /* this code is reported to cause oscillation around RefuseLA */
  1927. if (CurrentLA >= RefuseLA && QueueLA < RefuseLA)
  1928. {
  1929. if (tTd(3, 30))
  1930. dprintf("TRUE (CurrentLA >= RefuseLA)n");
  1931. return TRUE;
  1932. }
  1933. #endif /* 0 */
  1934. rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
  1935. if (tTd(3, 30))
  1936. dprintf("%s (by calculation)n", rval ? "TRUE" : "FALSE");
  1937. return rval;
  1938. }
  1939. /*
  1940. **  REFUSECONNECTIONS -- decide if connections should be refused
  1941. **
  1942. ** Parameters:
  1943. ** name -- daemon name (for error messages only)
  1944. ** e -- the current envelope.
  1945. ** d -- number of daemon
  1946. **
  1947. ** Returns:
  1948. ** TRUE if incoming SMTP connections should be refused
  1949. ** (for now).
  1950. ** FALSE if we should accept new work.
  1951. **
  1952. ** Side Effects:
  1953. ** Sets process title when it is rejecting connections.
  1954. */
  1955. bool
  1956. refuseconnections(name, e, d)
  1957. char *name;
  1958. ENVELOPE *e;
  1959. int d;
  1960. {
  1961. time_t now;
  1962. static time_t lastconn[MAXDAEMONS];
  1963. static int conncnt[MAXDAEMONS];
  1964. #ifdef XLA
  1965. if (!xla_smtp_ok())
  1966. return TRUE;
  1967. #endif /* XLA */
  1968. now = curtime();
  1969. if (now != lastconn[d])
  1970. {
  1971. lastconn[d] = now;
  1972. conncnt[d] = 0;
  1973. }
  1974. else if (conncnt[d]++ > ConnRateThrottle && ConnRateThrottle > 0)
  1975. {
  1976. /* sleep to flatten out connection load */
  1977. sm_setproctitle(TRUE, e, "deferring connections on daemon %s: %d per second",
  1978. name, ConnRateThrottle);
  1979. if (LogLevel >= 9)
  1980. sm_syslog(LOG_INFO, NOQID,
  1981. "deferring connections on daemon %s: %d per second",
  1982. name, ConnRateThrottle);
  1983. (void) sleep(1);
  1984. }
  1985. CurrentLA = getla();
  1986. if (RefuseLA > 0 && CurrentLA >= RefuseLA)
  1987. {
  1988. sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: load average: %d",
  1989. name, CurrentLA);
  1990. if (LogLevel >= 9)
  1991. sm_syslog(LOG_INFO, NOQID,
  1992. "rejecting connections on daemon %s: load average: %d",
  1993. name, CurrentLA);
  1994. return TRUE;
  1995. }
  1996. if (MaxChildren > 0 && CurChildren >= MaxChildren)
  1997. {
  1998. proc_list_probe();
  1999. if (CurChildren >= MaxChildren)
  2000. {
  2001. sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: %d children, max %d",
  2002. name, CurChildren, MaxChildren);
  2003. if (LogLevel >= 9)
  2004. sm_syslog(LOG_INFO, NOQID,
  2005. "rejecting connections on daemon %s: %d children, max %d",
  2006. name, CurChildren, MaxChildren);
  2007. return TRUE;
  2008. }
  2009. }
  2010. return FALSE;
  2011. }
  2012. /*
  2013. **  SETPROCTITLE -- set process title for ps
  2014. **
  2015. ** Parameters:
  2016. ** fmt -- a printf style format string.
  2017. ** a, b, c -- possible parameters to fmt.
  2018. **
  2019. ** Returns:
  2020. ** none.
  2021. **
  2022. ** Side Effects:
  2023. ** Clobbers argv of our main procedure so ps(1) will
  2024. ** display the title.
  2025. */
  2026. #define SPT_NONE 0 /* don't use it at all */
  2027. #define SPT_REUSEARGV 1 /* cover argv with title information */
  2028. #define SPT_BUILTIN 2 /* use libc builtin */
  2029. #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
  2030. #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
  2031. #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
  2032. #define SPT_SCO 6 /* write kernel u. area */
  2033. #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
  2034. #ifndef SPT_TYPE
  2035. # define SPT_TYPE SPT_REUSEARGV
  2036. #endif /* ! SPT_TYPE */
  2037. #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
  2038. # if SPT_TYPE == SPT_PSTAT
  2039. #  include <sys/pstat.h>
  2040. # endif /* SPT_TYPE == SPT_PSTAT */
  2041. # if SPT_TYPE == SPT_PSSTRINGS
  2042. #  include <machine/vmparam.h>
  2043. #  include <sys/exec.h>
  2044. #  ifndef PS_STRINGS /* hmmmm....  apparently not available after all */
  2045. #   undef SPT_TYPE
  2046. #   define SPT_TYPE SPT_REUSEARGV
  2047. #  else /* ! PS_STRINGS */
  2048. #   ifndef NKPDE /* FreeBSD 2.0 */
  2049. #    define NKPDE 63
  2050. typedef unsigned int *pt_entry_t;
  2051. #   endif /* ! NKPDE */
  2052. #  endif /* ! PS_STRINGS */
  2053. # endif /* SPT_TYPE == SPT_PSSTRINGS */
  2054. # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
  2055. #  define SETPROC_STATIC static
  2056. # else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
  2057. #  define SETPROC_STATIC
  2058. # endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
  2059. # if SPT_TYPE == SPT_SYSMIPS
  2060. #  include <sys/sysmips.h>
  2061. #  include <sys/sysnews.h>
  2062. # endif /* SPT_TYPE == SPT_SYSMIPS */
  2063. # if SPT_TYPE == SPT_SCO
  2064. #  include <sys/immu.h>
  2065. #  include <sys/dir.h>
  2066. #  include <sys/user.h>
  2067. #  include <sys/fs/s5param.h>
  2068. #  if PSARGSZ > MAXLINE
  2069. #   define SPT_BUFSIZE PSARGSZ
  2070. #  endif /* PSARGSZ > MAXLINE */
  2071. # endif /* SPT_TYPE == SPT_SCO */
  2072. # ifndef SPT_PADCHAR
  2073. #  define SPT_PADCHAR ' '
  2074. # endif /* ! SPT_PADCHAR */
  2075. #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
  2076. #ifndef SPT_BUFSIZE
  2077. # define SPT_BUFSIZE MAXLINE
  2078. #endif /* ! SPT_BUFSIZE */
  2079. /*
  2080. **  Pointers for setproctitle.
  2081. ** This allows "ps" listings to give more useful information.
  2082. */
  2083. static char **Argv = NULL; /* pointer to argument vector */
  2084. static char *LastArgv = NULL; /* end of argv */
  2085. #if SPT_TYPE != SPT_BUILTIN
  2086. static void setproctitle __P((const char *, ...));
  2087. #endif /* SPT_TYPE != SPT_BUILTIN */
  2088. void
  2089. initsetproctitle(argc, argv, envp)
  2090. int argc;
  2091. char **argv;
  2092. char **envp;
  2093. {
  2094. register int i, envpsize = 0;
  2095. extern char **environ;
  2096. /*
  2097. **  Move the environment so setproctitle can use the space at
  2098. **  the top of memory.
  2099. */
  2100. for (i = 0; envp[i] != NULL; i++)
  2101. envpsize += strlen(envp[i]) + 1;
  2102. environ = (char **) xalloc(sizeof (char *) * (i + 1));
  2103. for (i = 0; envp[i] != NULL; i++)
  2104. environ[i] = newstr(envp[i]);
  2105. environ[i] = NULL;
  2106. /*
  2107. **  Save start and extent of argv for setproctitle.
  2108. */
  2109. Argv = argv;
  2110. /*
  2111. **  Determine how much space we can use for setproctitle.
  2112. **  Use all contiguous argv and envp pointers starting at argv[0]
  2113. */
  2114. for (i = 0; i < argc; i++)
  2115. {
  2116. if (i == 0 || LastArgv + 1 == argv[i])
  2117. LastArgv = argv[i] + strlen(argv[i]);
  2118. }
  2119. for (i = 0; envp[i] != NULL; i++)
  2120. {
  2121. if (LastArgv + 1 == envp[i])
  2122. LastArgv = envp[i] + strlen(envp[i]);
  2123. }
  2124. }
  2125. #if SPT_TYPE != SPT_BUILTIN
  2126. /*VARARGS1*/
  2127. static void
  2128. # ifdef __STDC__
  2129. setproctitle(const char *fmt, ...)
  2130. # else /* __STDC__ */
  2131. setproctitle(fmt, va_alist)
  2132. const char *fmt;
  2133. va_dcl
  2134. # endif /* __STDC__ */
  2135. {
  2136. # if SPT_TYPE != SPT_NONE
  2137. register int i;
  2138. register char *p;
  2139. SETPROC_STATIC char buf[SPT_BUFSIZE];
  2140. VA_LOCAL_DECL
  2141. #  if SPT_TYPE == SPT_PSTAT
  2142. union pstun pst;
  2143. #  endif /* SPT_TYPE == SPT_PSTAT */
  2144. #  if SPT_TYPE == SPT_SCO
  2145. off_t seek_off;
  2146. static int kmem = -1;
  2147. static int kmempid = -1;
  2148. struct user u;
  2149. #  endif /* SPT_TYPE == SPT_SCO */
  2150. p = buf;
  2151. /* print sendmail: heading for grep */
  2152. (void) strlcpy(p, "sendmail: ", SPACELEFT(buf, p));
  2153. p += strlen(p);
  2154. /* print the argument string */
  2155. VA_START(fmt);
  2156. (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
  2157. VA_END;
  2158. i = strlen(buf);
  2159. #  if SPT_TYPE == SPT_PSTAT
  2160. pst.pst_command = buf;
  2161. pstat(PSTAT_SETCMD, pst, i, 0, 0);
  2162. #  endif /* SPT_TYPE == SPT_PSTAT */
  2163. #  if SPT_TYPE == SPT_PSSTRINGS
  2164. PS_STRINGS->ps_nargvstr = 1;
  2165. PS_STRINGS->ps_argvstr = buf;
  2166. #  endif /* SPT_TYPE == SPT_PSSTRINGS */
  2167. #  if SPT_TYPE == SPT_SYSMIPS
  2168. sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
  2169. #  endif /* SPT_TYPE == SPT_SYSMIPS */
  2170. #  if SPT_TYPE == SPT_SCO
  2171. if (kmem < 0 || kmempid != getpid())
  2172. {
  2173. if (kmem >= 0)
  2174. close(kmem);
  2175. kmem = open(_PATH_KMEM, O_RDWR, 0);
  2176. if (kmem < 0)
  2177. return;
  2178. (void) fcntl(kmem, F_SETFD, FD_CLOEXEC);
  2179. kmempid = getpid();
  2180. }
  2181. buf[PSARGSZ - 1] = '';
  2182. seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
  2183. if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
  2184. (void) write(kmem, buf, PSARGSZ);
  2185. #  endif /* SPT_TYPE == SPT_SCO */
  2186. #  if SPT_TYPE == SPT_REUSEARGV
  2187. if (i > LastArgv - Argv[0] - 2)
  2188. {
  2189. i = LastArgv - Argv[0] - 2;
  2190. buf[i] = '';
  2191. }
  2192. (void) strlcpy(Argv[0], buf, i + 1);
  2193. p = &Argv[0][i];
  2194. while (p < LastArgv)
  2195. *p++ = SPT_PADCHAR;
  2196. Argv[1] = NULL;
  2197. #  endif /* SPT_TYPE == SPT_REUSEARGV */
  2198. #  if SPT_TYPE == SPT_CHANGEARGV
  2199. Argv[0] = buf;
  2200. Argv[1] = 0;
  2201. #  endif /* SPT_TYPE == SPT_CHANGEARGV */
  2202. # endif /* SPT_TYPE != SPT_NONE */
  2203. }
  2204. #endif /* SPT_TYPE != SPT_BUILTIN */
  2205. /*
  2206. **  SM_SETPROCTITLE -- set process task and set process title for ps
  2207. **
  2208. ** Possibly set process status and call setproctitle() to
  2209. ** change the ps display.
  2210. **
  2211. ** Parameters:
  2212. ** status -- whether or not to store as process status
  2213. ** e -- the current envelope.
  2214. ** fmt -- a printf style format string.
  2215. ** a, b, c -- possible parameters to fmt.
  2216. **
  2217. ** Returns:
  2218. ** none.
  2219. */
  2220. /*VARARGS2*/
  2221. void
  2222. #ifdef __STDC__
  2223. sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...)
  2224. #else /* __STDC__ */
  2225. sm_setproctitle(status, e, fmt, va_alist)
  2226. bool status;
  2227. ENVELOPE *e;
  2228. const char *fmt;
  2229. va_dcl
  2230. #endif /* __STDC__ */
  2231. {
  2232. char buf[SPT_BUFSIZE];
  2233. VA_LOCAL_DECL
  2234. /* print the argument string */
  2235. VA_START(fmt);
  2236. (void) vsnprintf(buf, sizeof buf, fmt, ap);
  2237. VA_END;
  2238. if (status)
  2239. proc_list_set(getpid(), buf);
  2240. if (ProcTitlePrefix != NULL)
  2241. {
  2242. char prefix[SPT_BUFSIZE];
  2243. expand(ProcTitlePrefix, prefix, sizeof prefix, e);
  2244. setproctitle("%s: %s", prefix, buf);
  2245. }
  2246. else
  2247. setproctitle("%s", buf);
  2248. }
  2249. /*
  2250. **  WAITFOR -- wait for a particular process id.
  2251. **
  2252. ** Parameters:
  2253. ** pid -- process id to wait for.
  2254. **
  2255. ** Returns:
  2256. ** status of pid.
  2257. ** -1 if pid never shows up.
  2258. **
  2259. ** Side Effects:
  2260. ** none.
  2261. */
  2262. int
  2263. waitfor(pid)
  2264. pid_t pid;
  2265. {
  2266. #ifdef WAITUNION
  2267. union wait st;
  2268. #else /* WAITUNION */
  2269. auto int st;
  2270. #endif /* WAITUNION */
  2271. pid_t i;
  2272. #if defined(ISC_UNIX) || defined(_SCO_unix_)
  2273. int savesig;
  2274. #endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
  2275. do
  2276. {
  2277. errno = 0;
  2278. #if defined(ISC_UNIX) || defined(_SCO_unix_)
  2279. savesig = releasesignal(SIGCHLD);
  2280. #endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
  2281. i = wait(&st);
  2282. #if defined(ISC_UNIX) || defined(_SCO_unix_)
  2283. if (savesig > 0)
  2284. blocksignal(SIGCHLD);
  2285. #endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
  2286. if (i > 0)
  2287. (void) proc_list_drop(i);
  2288. } while ((i >= 0 || errno == EINTR) && i != pid);
  2289. if (i < 0)
  2290. return -1;
  2291. #ifdef WAITUNION
  2292. return st.w_status;
  2293. #else /* WAITUNION */
  2294. return st;
  2295. #endif /* WAITUNION */
  2296. }
  2297. /*
  2298. **  REAPCHILD -- pick up the body of my child, lest it become a zombie
  2299. **
  2300. ** Parameters:
  2301. ** sig -- the signal that got us here (unused).
  2302. **
  2303. ** Returns:
  2304. ** none.
  2305. **
  2306. ** Side Effects:
  2307. ** Picks up extant zombies.
  2308. ** Control socket exits may restart/shutdown daemon.
  2309. */
  2310. /* ARGSUSED0 */
  2311. SIGFUNC_DECL
  2312. reapchild(sig)
  2313. int sig;
  2314. {
  2315. int save_errno = errno;
  2316. pid_t pid;
  2317. #if HASWAITPID
  2318. auto int status;
  2319. int count;
  2320. count = 0;
  2321. while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
  2322. {
  2323. if (count++ > 1000)
  2324. {
  2325. if (LogLevel > 0)
  2326. sm_syslog(LOG_ALERT, NOQID,
  2327. "reapchild: waitpid loop: pid=%d, status=%x",
  2328. pid, status);
  2329. break;
  2330. }
  2331. #else /* HASWAITPID */
  2332. # ifdef WNOHANG
  2333. union wait status;
  2334. while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
  2335. {
  2336. # else /* WNOHANG */
  2337. auto int status;
  2338. /*
  2339. **  Catch one zombie -- we will be re-invoked (we hope) if there
  2340. **  are more.  Unreliable signals probably break this, but this
  2341. **  is the "old system" situation -- waitpid or wait3 are to be
  2342. **  strongly preferred.
  2343. */
  2344. if ((pid = wait(&status)) > 0)
  2345. {
  2346. # endif /* WNOHANG */
  2347. #endif /* HASWAITPID */
  2348. /* Drop PID and check if it was a control socket child */
  2349. if (proc_list_drop(pid) == PROC_CONTROL &&
  2350.     WIFEXITED(status))
  2351. {
  2352. /* if so, see if we need to restart or shutdown */
  2353. if (WEXITSTATUS(status) == EX_RESTART)
  2354. {
  2355. /* emulate a SIGHUP restart */
  2356. sighup(0);
  2357. /* NOTREACHED */
  2358. }
  2359. else if (WEXITSTATUS(status) == EX_SHUTDOWN)
  2360. {
  2361. /* emulate a SIGTERM shutdown */
  2362. intsig(0);
  2363. /* NOTREACHED */
  2364. }
  2365. }
  2366. }
  2367. #ifdef SYS5SIGNALS
  2368. (void) setsignal(SIGCHLD, reapchild);
  2369. #endif /* SYS5SIGNALS */
  2370. errno = save_errno;
  2371. return SIGFUNC_RETURN;
  2372. }
  2373. /*
  2374. **  PUTENV -- emulation of putenv() in terms of setenv()
  2375. **
  2376. ** Not needed on Posix-compliant systems.
  2377. ** This doesn't have full Posix semantics, but it's good enough
  2378. ** for sendmail.
  2379. **
  2380. ** Parameter:
  2381. ** env -- the environment to put.
  2382. **
  2383. ** Returns:
  2384. ** none.
  2385. */
  2386. #if NEEDPUTENV
  2387. # if NEEDPUTENV == 2 /* no setenv(3) call available */
  2388. int
  2389. putenv(str)
  2390. char *str;
  2391. {
  2392. char **current;
  2393. int matchlen, envlen = 0;
  2394. char *tmp;
  2395. char **newenv;
  2396. static bool first = TRUE;
  2397. extern char **environ;
  2398. /*
  2399.  * find out how much of str to match when searching
  2400.  * for a string to replace.
  2401.  */
  2402. if ((tmp = strchr(str, '=')) == NULL || tmp == str)
  2403. matchlen = strlen(str);
  2404. else
  2405. matchlen = (int) (tmp - str);
  2406. ++matchlen;
  2407. /*
  2408.  * Search for an existing string in the environment and find the
  2409.  * length of environ.  If found, replace and exit.
  2410.  */
  2411. for (current = environ; *current; current++)
  2412. {
  2413. ++envlen;
  2414. if (strncmp(str, *current, matchlen) == 0)
  2415. {
  2416. /* found it, now insert the new version */
  2417. *current = (char *)str;
  2418. return 0;
  2419. }
  2420. }
  2421. /*
  2422.  * There wasn't already a slot so add space for a new slot.
  2423.  * If this is our first time through, use malloc(), else realloc().
  2424.  */
  2425. if (first)
  2426. {
  2427. newenv = (char **) malloc(sizeof(char *) * (envlen + 2));
  2428. if (newenv == NULL)
  2429. return -1;
  2430. first = FALSE;
  2431. (void) memcpy(newenv, environ, sizeof(char *) * envlen);
  2432. }
  2433. else
  2434. {
  2435. newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2));
  2436. if (newenv == NULL)
  2437. return -1;
  2438. }
  2439. /* actually add in the new entry */
  2440. environ = newenv;
  2441. environ[envlen] = (char *)str;
  2442. environ[envlen + 1] = NULL;
  2443. return 0;
  2444. }
  2445. # else /* NEEDPUTENV == 2 */
  2446. int
  2447. putenv(env)
  2448. char *env;
  2449. {
  2450. char *p;
  2451. int l;
  2452. char nbuf[100];
  2453. p = strchr(env, '=');
  2454. if (p == NULL)
  2455. return 0;
  2456. l = p - env;
  2457. if (l > sizeof nbuf - 1)
  2458. l = sizeof nbuf - 1;
  2459. memmove(nbuf, env, l);
  2460. nbuf[l] = '';
  2461. return setenv(nbuf, ++p, 1);
  2462. }
  2463. # endif /* NEEDPUTENV == 2 */
  2464. #endif /* NEEDPUTENV */
  2465. /*
  2466. **  UNSETENV -- remove a variable from the environment
  2467. **
  2468. ** Not needed on newer systems.
  2469. **
  2470. ** Parameters:
  2471. ** name -- the string name of the environment variable to be
  2472. ** deleted from the current environment.
  2473. **
  2474. ** Returns:
  2475. ** none.
  2476. **
  2477. ** Globals:
  2478. ** environ -- a pointer to the current environment.
  2479. **
  2480. ** Side Effects:
  2481. ** Modifies environ.
  2482. */
  2483. #if !HASUNSETENV
  2484. void
  2485. unsetenv(name)
  2486. char *name;
  2487. {
  2488. extern char **environ;
  2489. register char **pp;
  2490. int len = strlen(name);
  2491. for (pp = environ; *pp != NULL; pp++)
  2492. {
  2493. if (strncmp(name, *pp, len) == 0 &&
  2494.     ((*pp)[len] == '=' || (*pp)[len] == ''))
  2495. break;
  2496. }
  2497. for (; *pp != NULL; pp++)
  2498. *pp = pp[1];
  2499. }
  2500. #endif /* !HASUNSETENV */
  2501. /*
  2502. **  GETDTABLESIZE -- return number of file descriptors
  2503. **
  2504. ** Only on non-BSD systems
  2505. **
  2506. ** Parameters:
  2507. ** none
  2508. **
  2509. ** Returns:
  2510. ** size of file descriptor table
  2511. **
  2512. ** Side Effects:
  2513. ** none
  2514. */
  2515. #ifdef SOLARIS
  2516. # include <sys/resource.h>
  2517. #endif /* SOLARIS */
  2518. int
  2519. getdtsize()
  2520. {
  2521. #ifdef RLIMIT_NOFILE
  2522. struct rlimit rl;
  2523. if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
  2524. return rl.rlim_cur;
  2525. #endif /* RLIMIT_NOFILE */
  2526. #if HASGETDTABLESIZE
  2527. return getdtablesize();
  2528. #else /* HASGETDTABLESIZE */
  2529. # ifdef _SC_OPEN_MAX
  2530. return sysconf(_SC_OPEN_MAX);
  2531. # else /* _SC_OPEN_MAX */
  2532. return NOFILE;
  2533. # endif /* _SC_OPEN_MAX */
  2534. #endif /* HASGETDTABLESIZE */
  2535. }
  2536. /*
  2537. **  UNAME -- get the UUCP name of this system.
  2538. */
  2539. #if !HASUNAME
  2540. int
  2541. uname(name)
  2542. struct utsname *name;
  2543. {
  2544. FILE *file;
  2545. char *n;
  2546. name->nodename[0] = '';
  2547. /* try /etc/whoami -- one line with the node name */
  2548. if ((file = fopen("/etc/whoami", "r")) != NULL)
  2549. {
  2550. (void) fgets(name->nodename, NODE_LENGTH + 1, file);
  2551. (void) fclose(file);
  2552. n = strchr(name->nodename, 'n');
  2553. if (n != NULL)
  2554. *n = '';
  2555. if (name->nodename[0] != '')
  2556. return 0;
  2557. }
  2558. /* try /usr/include/whoami.h -- has a #define somewhere */
  2559. if ((file = fopen("/usr/include/whoami.h", "r")) != NULL)
  2560. {
  2561. char buf[MAXLINE];
  2562. while (fgets(buf, MAXLINE, file) != NULL)
  2563. if (sscanf(buf, "#define sysname "%*[^"]"",
  2564. NODE_LENGTH, name->nodename) > 0)
  2565. break;
  2566. (void) fclose(file);
  2567. if (name->nodename[0] != '')
  2568. return 0;
  2569. }
  2570. # if 0
  2571. /*
  2572. **  Popen is known to have security holes.
  2573. */
  2574. /* try uuname -l to return local name */
  2575. if ((file = popen("uuname -l", "r")) != NULL)
  2576. {
  2577. (void) fgets(name, NODE_LENGTH + 1, file);
  2578. (void) pclose(file);
  2579. n = strchr(name, 'n');
  2580. if (n != NULL)
  2581. *n = '';
  2582. if (name->nodename[0] != '')
  2583. return 0;
  2584. }
  2585. # endif /* 0 */
  2586. return -1;
  2587. }
  2588. #endif /* !HASUNAME */
  2589. /*
  2590. **  INITGROUPS -- initialize groups
  2591. **
  2592. ** Stub implementation for System V style systems
  2593. */
  2594. #if !HASINITGROUPS
  2595. initgroups(name, basegid)
  2596. char *name;
  2597. int basegid;
  2598. {
  2599. return 0;
  2600. }
  2601. #endif /* !HASINITGROUPS */
  2602. /*
  2603. **  SETGROUPS -- set group list
  2604. **
  2605. ** Stub implementation for systems that don't have group lists
  2606. */
  2607. #ifndef NGROUPS_MAX
  2608. int
  2609. setgroups(ngroups, grouplist)
  2610. int ngroups;
  2611. GIDSET_T grouplist[];
  2612. {
  2613. return 0;
  2614. }
  2615. #endif /* ! NGROUPS_MAX */
  2616. /*
  2617. **  SETSID -- set session id (for non-POSIX systems)
  2618. */
  2619. #if !HASSETSID
  2620. pid_t
  2621. setsid __P ((void))
  2622. {
  2623. # ifdef TIOCNOTTY
  2624. int fd;
  2625. fd = open("/dev/tty", O_RDWR, 0);
  2626. if (fd >= 0)
  2627. {
  2628. (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
  2629. (void) close(fd);
  2630. }
  2631. # endif /* TIOCNOTTY */
  2632. # ifdef SYS5SETPGRP
  2633. return setpgrp();
  2634. # else /* SYS5SETPGRP */
  2635. return setpgid(0, getpid());
  2636. # endif /* SYS5SETPGRP */
  2637. }
  2638. #endif /* !HASSETSID */
  2639. /*
  2640. **  FSYNC -- dummy fsync
  2641. */
  2642. #if NEEDFSYNC
  2643. fsync(fd)
  2644. int fd;
  2645. {
  2646. # ifdef O_SYNC
  2647. return fcntl(fd, F_SETFL, O_SYNC);
  2648. # else /* O_SYNC */
  2649. /* nothing we can do */
  2650. return 0;
  2651. # endif /* O_SYNC */
  2652. }
  2653. #endif /* NEEDFSYNC */
  2654. /*
  2655. **  DGUX_INET_ADDR -- inet_addr for DG/UX
  2656. **
  2657. ** Data General DG/UX version of inet_addr returns a struct in_addr
  2658. ** instead of a long.  This patches things.  Only needed on versions
  2659. ** prior to 5.4.3.
  2660. */
  2661. #ifdef DGUX_5_4_2
  2662. # undef inet_addr
  2663. long
  2664. dgux_inet_addr(host)
  2665. char *host;
  2666. {
  2667. struct in_addr haddr;
  2668. haddr = inet_addr(host);
  2669. return haddr.s_addr;
  2670. }
  2671. #endif /* DGUX_5_4_2 */
  2672. /*
  2673. **  GETOPT -- for old systems or systems with bogus implementations
  2674. */
  2675. #if NEEDGETOPT
  2676. /*
  2677.  * Copyright (c) 1985 Regents of the University of California.
  2678.  * All rights reserved.  The Berkeley software License Agreement
  2679.  * specifies the terms and conditions for redistribution.
  2680.  */
  2681. /*
  2682. **  this version hacked to add `atend' flag to allow state machine
  2683. **  to reset if invoked by the program to scan args for a 2nd time
  2684. */
  2685. # if defined(LIBC_SCCS) && !defined(lint)
  2686. static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86";
  2687. # endif /* defined(LIBC_SCCS) && !defined(lint) */
  2688. /*
  2689.  * get option letter from argument vector
  2690.  */
  2691. # ifdef _CONVEX_SOURCE
  2692. extern int optind, opterr, optopt;
  2693. extern char *optarg;
  2694. # else /* _CONVEX_SOURCE */
  2695. int opterr = 1; /* if error message should be printed */
  2696. int optind = 1; /* index into parent argv vector */
  2697. int optopt = 0; /* character checked for validity */
  2698. char *optarg = NULL; /* argument associated with option */
  2699. # endif /* _CONVEX_SOURCE */
  2700. # define BADCH (int)'?'
  2701. # define EMSG ""
  2702. # define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); 
  2703. fputc(optopt,stderr);fputc('n',stderr);return(BADCH);}
  2704. int
  2705. getopt(nargc,nargv,ostr)
  2706. int nargc;
  2707. char *const *nargv;
  2708. const char *ostr;
  2709. {
  2710. static char *place = EMSG; /* option letter processing */
  2711. static char atend = 0;
  2712. register char *oli = NULL; /* option letter list index */
  2713. if (atend) {
  2714. atend = 0;
  2715. place = EMSG;
  2716. }
  2717. if(!*place) { /* update scanning pointer */
  2718. if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
  2719. atend++;
  2720. return -1;
  2721. }
  2722. if (*place == '-') { /* found "--" */
  2723. ++optind;
  2724. atend++;
  2725. return -1;
  2726. }
  2727. } /* option letter okay? */
  2728. if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
  2729. if (!*place) ++optind;
  2730. tell(": illegal option -- ");
  2731. }
  2732. if (oli && *++oli != ':') { /* don't need argument */
  2733. optarg = NULL;
  2734. if (!*place) ++optind;
  2735. }
  2736. else { /* need an argument */
  2737. if (*place) optarg = place; /* no white space */
  2738. else if (nargc <= ++optind) { /* no arg */
  2739. place = EMSG;
  2740. tell(": option requires an argument -- ");
  2741. }
  2742. else optarg = nargv[optind]; /* white space */
  2743. place = EMSG;
  2744. ++optind;
  2745. }
  2746. return(optopt); /* dump back option letter */
  2747. }
  2748. #endif /* NEEDGETOPT */
  2749. /*
  2750. **  VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version
  2751. */
  2752. #if NEEDVPRINTF
  2753. # define MAXARG 16
  2754. vfprintf(fp, fmt, ap)
  2755. FILE *fp;
  2756. char *fmt;
  2757. char **ap;
  2758. {
  2759. char *bp[MAXARG];
  2760. int i = 0;
  2761. while (*ap && i < MAXARG)
  2762. bp[i++] = *ap++;
  2763. fprintf(fp, fmt, bp[0], bp[1], bp[2], bp[3],
  2764.  bp[4], bp[5], bp[6], bp[7],
  2765.  bp[8], bp[9], bp[10], bp[11],
  2766.  bp[12], bp[13], bp[14], bp[15]);
  2767. }
  2768. vsprintf(s, fmt, ap)
  2769. char *s;
  2770. char *fmt;
  2771. char **ap;
  2772. {
  2773. char *bp[MAXARG];
  2774. int i = 0;
  2775. while (*ap && i < MAXARG)
  2776. bp[i++] = *ap++;
  2777. sprintf(s, fmt, bp[0], bp[1], bp[2], bp[3],
  2778. bp[4], bp[5], bp[6], bp[7],
  2779. bp[8], bp[9], bp[10], bp[11],
  2780. bp[12], bp[13], bp[14], bp[15]);
  2781. }
  2782. #endif /* NEEDVPRINTF */
  2783. /*
  2784. **  USERSHELLOK -- tell if a user's shell is ok for unrestricted use
  2785. **
  2786. ** Parameters:
  2787. ** user -- the name of the user we are checking.
  2788. ** shell -- the user's shell from /etc/passwd
  2789. **
  2790. ** Returns:
  2791. ** TRUE -- if it is ok to use this for unrestricted access.
  2792. ** FALSE -- if the shell is restricted.
  2793. */
  2794. #if !HASGETUSERSHELL
  2795. # ifndef _PATH_SHELLS
  2796. #  define _PATH_SHELLS "/etc/shells"
  2797. # endif /* ! _PATH_SHELLS */
  2798. # if defined(_AIX3) || defined(_AIX4)
  2799. #  include <userconf.h>
  2800. #  if _AIX4 >= 40200
  2801. #   include <userpw.h>
  2802. #  endif /* _AIX4 >= 40200 */
  2803. #  include <usersec.h>
  2804. # endif /* defined(_AIX3) || defined(_AIX4) */
  2805. static char *DefaultUserShells[] =
  2806. {
  2807. "/bin/sh", /* standard shell */
  2808. "/usr/bin/sh",
  2809. "/bin/csh", /* C shell */
  2810. "/usr/bin/csh",
  2811. # ifdef __hpux
  2812. #  ifdef V4FS
  2813. "/usr/bin/rsh", /* restricted Bourne shell */
  2814. "/usr/bin/ksh", /* Korn shell */
  2815. "/usr/bin/rksh", /* restricted Korn shell */
  2816. "/usr/bin/pam",
  2817. "/usr/bin/keysh", /* key shell (extended Korn shell) */
  2818. "/usr/bin/posix/sh",
  2819. #  else /* V4FS */
  2820. "/bin/rsh", /* restricted Bourne shell */
  2821. "/bin/ksh", /* Korn shell */
  2822. "/bin/rksh", /* restricted Korn shell */
  2823. "/bin/pam",
  2824. "/usr/bin/keysh", /* key shell (extended Korn shell) */
  2825. "/bin/posix/sh",
  2826. #  endif /* V4FS */
  2827. # endif /* __hpux */
  2828. # if defined(_AIX3) || defined(_AIX4)
  2829. "/bin/ksh", /* Korn shell */
  2830. "/usr/bin/ksh",
  2831. "/bin/tsh", /* trusted shell */
  2832. "/usr/bin/tsh",
  2833. "/bin/bsh", /* Bourne shell */
  2834. "/usr/bin/bsh",
  2835. # endif /* defined(_AIX3) || defined(_AIX4) */
  2836. # if defined(__svr4__) || defined(__svr5__)
  2837. "/bin/ksh", /* Korn shell */
  2838. "/usr/bin/ksh",
  2839. # endif /* defined(__svr4__) || defined(__svr5__) */
  2840. # ifdef sgi
  2841. "/sbin/sh", /* SGI's shells really live in /sbin */
  2842. "/sbin/csh",
  2843. "/bin/ksh", /* Korn shell */
  2844. "/sbin/ksh",
  2845. "/usr/bin/ksh",
  2846. "/bin/tcsh", /* Extended csh */
  2847. "/usr/bin/tcsh",
  2848. # endif /* sgi */
  2849. NULL
  2850. };
  2851. #endif /* !HASGETUSERSHELL */
  2852. #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
  2853. bool
  2854. usershellok(user, shell)
  2855. char *user;
  2856. char *shell;
  2857. {
  2858. #if HASGETUSERSHELL
  2859. register char *p;
  2860. extern char *getusershell();
  2861. if (shell == NULL || shell[0] == '' || wordinclass(user, 't') ||
  2862.     ConfigLevel <= 1)
  2863. return TRUE;
  2864. setusershell();
  2865. while ((p = getusershell()) != NULL)
  2866. if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
  2867. break;
  2868. endusershell();
  2869. return p != NULL;
  2870. #else /* HASGETUSERSHELL */
  2871. # if USEGETCONFATTR
  2872. auto char *v;
  2873. # endif /* USEGETCONFATTR */
  2874. register FILE *shellf;
  2875. char buf[MAXLINE];
  2876. if (shell == NULL || shell[0] == '' || wordinclass(user, 't') ||
  2877.     ConfigLevel <= 1)
  2878. return TRUE;
  2879. # if USEGETCONFATTR
  2880. /*
  2881. **  Naturally IBM has a "better" idea.....
  2882. **
  2883. ** What a crock.  This interface isn't documented, it is
  2884. ** considered part of the security library (-ls), and it
  2885. ** only works if you are running as root (since the list
  2886. ** of valid shells is obviously a source of great concern).
  2887. ** I recommend that you do NOT define USEGETCONFATTR,
  2888. ** especially since you are going to have to set up an
  2889. ** /etc/shells anyhow to handle the cases where getconfattr
  2890. ** fails.
  2891. */
  2892. if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
  2893. {
  2894. while (*v != '')
  2895. {
  2896. if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
  2897. return TRUE;
  2898. v += strlen(v) + 1;
  2899. }
  2900. return FALSE;
  2901. }
  2902. # endif /* USEGETCONFATTR */
  2903. shellf = fopen(_PATH_SHELLS, "r");
  2904. if (shellf == NULL)
  2905. {
  2906. /* no /etc/shells; see if it is one of the std shells */
  2907. char **d;
  2908. if (errno != ENOENT && LogLevel > 3)
  2909. sm_syslog(LOG_ERR, NOQID,
  2910.   "usershellok: cannot open %s: %s",
  2911.   _PATH_SHELLS, errstring(errno));
  2912. for (d = DefaultUserShells; *d != NULL; d++)
  2913. {
  2914. if (strcmp(shell, *d) == 0)
  2915. return TRUE;
  2916. }
  2917. return FALSE;
  2918. }
  2919. while (fgets(buf, sizeof buf, shellf) != NULL)
  2920. {
  2921. register char *p, *q;
  2922. p = buf;
  2923. while (*p != '' && *p != '#' && *p != '/')
  2924. p++;
  2925. if (*p == '#' || *p == '')
  2926. continue;
  2927. q = p;
  2928. while (*p != '' && *p != '#' && !(isascii(*p) && isspace(*p)))
  2929. p++;
  2930. *p = '';
  2931. if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
  2932. {
  2933. (void) fclose(shellf);
  2934. return TRUE;
  2935. }
  2936. }
  2937. (void) fclose(shellf);
  2938. return FALSE;
  2939. #endif /* HASGETUSERSHELL */
  2940. }
  2941. /*
  2942. **  FREEDISKSPACE -- see how much free space is on the queue filesystem
  2943. **
  2944. ** Only implemented if you have statfs.
  2945. **
  2946. ** Parameters:
  2947. ** dir -- the directory in question.
  2948. ** bsize -- a variable into which the filesystem
  2949. ** block size is stored.
  2950. **
  2951. ** Returns:
  2952. ** The number of bytes free on the queue filesystem.
  2953. ** -1 if the statfs call fails.
  2954. **
  2955. ** Side effects:
  2956. ** Puts the filesystem block size into bsize.
  2957. */
  2958. /* statfs types */
  2959. #define SFS_NONE 0 /* no statfs implementation */
  2960. #define SFS_USTAT 1 /* use ustat */
  2961. #define SFS_4ARGS 2 /* use four-argument statfs call */
  2962. #define SFS_VFS 3 /* use <sys/vfs.h> implementation */
  2963. #define SFS_MOUNT 4 /* use <sys/mount.h> implementation */
  2964. #define SFS_STATFS 5 /* use <sys/statfs.h> implementation */
  2965. #define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */
  2966. #ifndef SFS_TYPE
  2967. # define SFS_TYPE SFS_NONE
  2968. #endif /* ! SFS_TYPE */
  2969. #if SFS_TYPE == SFS_USTAT
  2970. # include <ustat.h>
  2971. #endif /* SFS_TYPE == SFS_USTAT */
  2972. #if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
  2973. # include <sys/statfs.h>
  2974. #endif /* SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS */
  2975. #if SFS_TYPE == SFS_VFS
  2976. # include <sys/vfs.h>
  2977. #endif /* SFS_TYPE == SFS_VFS */
  2978. #if SFS_TYPE == SFS_MOUNT
  2979. # include <sys/mount.h>
  2980. #endif /* SFS_TYPE == SFS_MOUNT */
  2981. #if SFS_TYPE == SFS_STATVFS
  2982. # include <sys/statvfs.h>
  2983. #endif /* SFS_TYPE == SFS_STATVFS */
  2984. long
  2985. freediskspace(dir, bsize)
  2986. char *dir;
  2987. long *bsize;
  2988. {
  2989. #if SFS_TYPE != SFS_NONE
  2990. # if SFS_TYPE == SFS_USTAT
  2991. struct ustat fs;
  2992. struct stat statbuf;
  2993. #  define FSBLOCKSIZE DEV_BSIZE
  2994. #  define SFS_BAVAIL f_tfree
  2995. # else /* SFS_TYPE == SFS_USTAT */
  2996. #  if defined(ultrix)
  2997. struct fs_data fs;
  2998. #   define SFS_BAVAIL fd_bfreen
  2999. #   define FSBLOCKSIZE 1024L
  3000. #  else /* defined(ultrix) */
  3001. #   if SFS_TYPE == SFS_STATVFS
  3002. struct statvfs fs;
  3003. #    define FSBLOCKSIZE fs.f_frsize
  3004. #   else /* SFS_TYPE == SFS_STATVFS */
  3005. struct statfs fs;
  3006. #    define FSBLOCKSIZE fs.f_bsize
  3007. #   endif /* SFS_TYPE == SFS_STATVFS */
  3008. #  endif /* defined(ultrix) */
  3009. # endif /* SFS_TYPE == SFS_USTAT */
  3010. # ifndef SFS_BAVAIL
  3011. #  define SFS_BAVAIL f_bavail
  3012. # endif /* ! SFS_BAVAIL */
  3013. # if SFS_TYPE == SFS_USTAT
  3014. if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
  3015. # else /* SFS_TYPE == SFS_USTAT */
  3016. #  if SFS_TYPE == SFS_4ARGS
  3017. if (statfs(dir, &fs, sizeof fs, 0) == 0)
  3018. #  else /* SFS_TYPE == SFS_4ARGS */
  3019. #   if SFS_TYPE == SFS_STATVFS
  3020. if (statvfs(dir, &fs) == 0)
  3021. #   else /* SFS_TYPE == SFS_STATVFS */
  3022. #    if defined(ultrix)
  3023. if (statfs(dir, &fs) > 0)
  3024. #    else /* defined(ultrix) */
  3025. if (statfs(dir, &fs) == 0)
  3026. #    endif /* defined(ultrix) */
  3027. #   endif /* SFS_TYPE == SFS_STATVFS */
  3028. #  endif /* SFS_TYPE == SFS_4ARGS */
  3029. # endif /* SFS_TYPE == SFS_USTAT */
  3030. {
  3031. if (bsize != NULL)
  3032. *bsize = FSBLOCKSIZE;
  3033. if (fs.SFS_BAVAIL <= 0)
  3034. return 0;
  3035. else if (fs.SFS_BAVAIL > LONG_MAX)
  3036. return LONG_MAX;
  3037. else
  3038. return (long) fs.SFS_BAVAIL;
  3039. }
  3040. #endif /* SFS_TYPE != SFS_NONE */
  3041. return -1;
  3042. }
  3043. /*
  3044. **  ENOUGHDISKSPACE -- is there enough free space on the queue fs?
  3045. **
  3046. ** Only implemented if you have statfs.
  3047. **
  3048. ** Parameters:
  3049. ** msize -- the size to check against.  If zero, we don't yet
  3050. ** know how big the message will be, so just check for
  3051. ** a "reasonable" amount.
  3052. ** log -- log message?
  3053. **
  3054. ** Returns:
  3055. ** TRUE if there is enough space.
  3056. ** FALSE otherwise.
  3057. */
  3058. bool
  3059. enoughdiskspace(msize, log)
  3060. long msize;
  3061. bool log;
  3062. {
  3063. long bfree, bsize;
  3064. if (MinBlocksFree <= 0 && msize <= 0)
  3065. {
  3066. if (tTd(4, 80))
  3067. dprintf("enoughdiskspace: no thresholdn");
  3068. return TRUE;
  3069. }
  3070. if ((bfree = freediskspace(QueueDir, &bsize)) >= 0)
  3071. {
  3072. if (tTd(4, 80))
  3073. dprintf("enoughdiskspace: bavail=%ld, need=%ldn",
  3074. bfree, msize);
  3075. /* convert msize to block count */
  3076. msize = msize / bsize + 1;
  3077. if (MinBlocksFree >= 0)
  3078. msize += MinBlocksFree;
  3079. if (bfree < msize)
  3080. {
  3081. if (log && LogLevel > 0)
  3082. sm_syslog(LOG_ALERT, CurEnv->e_id,
  3083. "low on space (have %ld, %s needs %ld in %s)",
  3084. bfree,
  3085. CurHostName == NULL ? "SMTP-DAEMON" : CurHostName,
  3086. msize, QueueDir);
  3087. return FALSE;
  3088. }
  3089. }
  3090. else if (tTd(4, 80))
  3091. dprintf("enoughdiskspace failure: min=%ld, need=%ld: %sn",
  3092. MinBlocksFree, msize, errstring(errno));
  3093. return TRUE;
  3094. }
  3095. /*
  3096. **  TRANSIENTERROR -- tell if an error code indicates a transient failure
  3097. **
  3098. ** This looks at an errno value and tells if this is likely to
  3099. ** go away if retried later.
  3100. **
  3101. ** Parameters:
  3102. ** err -- the errno code to classify.
  3103. **
  3104. ** Returns:
  3105. ** TRUE if this is probably transient.
  3106. ** FALSE otherwise.
  3107. */
  3108. bool
  3109. transienterror(err)
  3110. int err;
  3111. {
  3112. switch (err)
  3113. {
  3114.   case EIO: /* I/O error */
  3115.   case ENXIO: /* Device not configured */
  3116.   case EAGAIN: /* Resource temporarily unavailable */
  3117.   case ENOMEM: /* Cannot allocate memory */
  3118.   case ENODEV: /* Operation not supported by device */
  3119.   case ENFILE: /* Too many open files in system */
  3120.   case EMFILE: /* Too many open files */
  3121.   case ENOSPC: /* No space left on device */
  3122. #ifdef ETIMEDOUT
  3123.   case ETIMEDOUT: /* Connection timed out */
  3124. #endif /* ETIMEDOUT */
  3125. #ifdef ESTALE
  3126.   case ESTALE: /* Stale NFS file handle */
  3127. #endif /* ESTALE */
  3128. #ifdef ENETDOWN
  3129.   case ENETDOWN: /* Network is down */
  3130. #endif /* ENETDOWN */
  3131. #ifdef ENETUNREACH
  3132.   case ENETUNREACH: /* Network is unreachable */
  3133. #endif /* ENETUNREACH */
  3134. #ifdef ENETRESET
  3135.   case ENETRESET: /* Network dropped connection on reset */
  3136. #endif /* ENETRESET */
  3137. #ifdef ECONNABORTED
  3138.   case ECONNABORTED: /* Software caused connection abort */
  3139. #endif /* ECONNABORTED */
  3140. #ifdef ECONNRESET
  3141.   case ECONNRESET: /* Connection reset by peer */
  3142. #endif /* ECONNRESET */
  3143. #ifdef ENOBUFS
  3144.   case ENOBUFS: /* No buffer space available */
  3145. #endif /* ENOBUFS */
  3146. #ifdef ESHUTDOWN
  3147.   case ESHUTDOWN: /* Can't send after socket shutdown */
  3148. #endif /* ESHUTDOWN */
  3149. #ifdef ECONNREFUSED
  3150.   case ECONNREFUSED: /* Connection refused */
  3151. #endif /* ECONNREFUSED */
  3152. #ifdef EHOSTDOWN
  3153.   case EHOSTDOWN: /* Host is down */
  3154. #endif /* EHOSTDOWN */
  3155. #ifdef EHOSTUNREACH
  3156.   case EHOSTUNREACH: /* No route to host */
  3157. #endif /* EHOSTUNREACH */
  3158. #ifdef EDQUOT
  3159.   case EDQUOT: /* Disc quota exceeded */
  3160. #endif /* EDQUOT */
  3161. #ifdef EPROCLIM
  3162.   case EPROCLIM: /* Too many processes */
  3163. #endif /* EPROCLIM */
  3164. #ifdef EUSERS
  3165.   case EUSERS: /* Too many users */
  3166. #endif /* EUSERS */
  3167. #ifdef EDEADLK
  3168.   case EDEADLK: /* Resource deadlock avoided */
  3169. #endif /* EDEADLK */
  3170. #ifdef EISCONN
  3171.   case EISCONN: /* Socket already connected */
  3172. #endif /* EISCONN */
  3173. #ifdef EINPROGRESS
  3174.   case EINPROGRESS: /* Operation now in progress */
  3175. #endif /* EINPROGRESS */
  3176. #ifdef EALREADY
  3177.   case EALREADY: /* Operation already in progress */
  3178. #endif /* EALREADY */
  3179. #ifdef EADDRINUSE
  3180.   case EADDRINUSE: /* Address already in use */
  3181. #endif /* EADDRINUSE */
  3182. #ifdef EADDRNOTAVAIL
  3183.   case EADDRNOTAVAIL: /* Can't assign requested address */
  3184. #endif /* EADDRNOTAVAIL */
  3185. #ifdef ETXTBSY
  3186.   case ETXTBSY: /* (Apollo) file locked */
  3187. #endif /* ETXTBSY */
  3188. #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
  3189.   case ENOSR: /* Out of streams resources */
  3190. #endif /* defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) */
  3191. #ifdef ENOLCK
  3192.   case ENOLCK: /* No locks available */
  3193. #endif /* ENOLCK */
  3194.   case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */
  3195. return TRUE;
  3196. }
  3197. /* nope, must be permanent */
  3198. return FALSE;
  3199. }
  3200. /*
  3201. **  LOCKFILE -- lock a file using flock or (shudder) fcntl locking
  3202. **
  3203. ** Parameters:
  3204. ** fd -- the file descriptor of the file.
  3205. ** filename -- the file name (for error messages).
  3206. ** ext -- the filename extension.
  3207. ** type -- type of the lock.  Bits can be:
  3208. ** LOCK_EX -- exclusive lock.
  3209. ** LOCK_NB -- non-blocking.
  3210. **
  3211. ** Returns:
  3212. ** TRUE if the lock was acquired.
  3213. ** FALSE otherwise.
  3214. */
  3215. bool
  3216. lockfile(fd, filename, ext, type)
  3217. int fd;
  3218. char *filename;
  3219. char *ext;
  3220. int type;
  3221. {
  3222. int i;
  3223. int save_errno;
  3224. #if !HASFLOCK
  3225. int action;
  3226. struct flock lfd;
  3227. if (ext == NULL)
  3228. ext = "";
  3229. memset(&lfd, '', sizeof lfd);
  3230. if (bitset(LOCK_UN, type))
  3231. lfd.l_type = F_UNLCK;
  3232. else if (bitset(LOCK_EX, type))
  3233. lfd.l_type = F_WRLCK;
  3234. else
  3235. lfd.l_type = F_RDLCK;
  3236. if (bitset(LOCK_NB, type))
  3237. action = F_SETLK;
  3238. else
  3239. action = F_SETLKW;
  3240. if (tTd(55, 60))
  3241. dprintf("lockfile(%s%s, action=%d, type=%d): ",
  3242. filename, ext, action, lfd.l_type);
  3243. while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
  3244. continue;
  3245. if (i >= 0)
  3246. {
  3247. if (tTd(55, 60))
  3248. dprintf("SUCCESSn");
  3249. return TRUE;
  3250. }
  3251. save_errno = errno;
  3252. if (tTd(55, 60))
  3253. dprintf("(%s) ", errstring(save_errno));
  3254. /*
  3255. **  On SunOS, if you are testing using -oQ/tmp/mqueue or
  3256. **  -oA/tmp/aliases or anything like that, and /tmp is mounted
  3257. **  as type "tmp" (that is, served from swap space), the
  3258. **  previous fcntl will fail with "Invalid argument" errors.
  3259. **  Since this is fairly common during testing, we will assume
  3260. **  that this indicates that the lock is successfully grabbed.
  3261. */
  3262. if (save_errno == EINVAL)
  3263. {
  3264. if (tTd(55, 60))
  3265. dprintf("SUCCESSn");
  3266. return TRUE;
  3267. }
  3268. if (!bitset(LOCK_NB, type) ||
  3269.     (save_errno != EACCES && save_errno != EAGAIN))
  3270. {
  3271. int omode = -1;
  3272. # ifdef F_GETFL
  3273. (void) fcntl(fd, F_GETFL, &omode);
  3274. errno = save_errno;
  3275. # endif /* F_GETFL */
  3276. syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
  3277. filename, ext, fd, type, omode, geteuid());
  3278. dumpfd(fd, TRUE, TRUE);
  3279. }
  3280. #else /* !HASFLOCK */
  3281. if (ext == NULL)
  3282. ext = "";
  3283. if (tTd(55, 60))
  3284. dprintf("lockfile(%s%s, type=%o): ", filename, ext, type);
  3285. while ((i = flock(fd, type)) < 0 && errno == EINTR)
  3286. continue;
  3287. if (i >= 0)
  3288. {
  3289. if (tTd(55, 60))
  3290. dprintf("SUCCESSn");
  3291. return TRUE;
  3292. }
  3293. save_errno = errno;
  3294. if (tTd(55, 60))
  3295. dprintf("(%s) ", errstring(save_errno));
  3296. if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK)
  3297. {
  3298. int omode = -1;
  3299. # ifdef F_GETFL
  3300. (void) fcntl(fd, F_GETFL, &omode);
  3301. errno = save_errno;
  3302. # endif /* F_GETFL */
  3303. syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
  3304. filename, ext, fd, type, omode, geteuid());
  3305. dumpfd(fd, TRUE, TRUE);
  3306. }
  3307. #endif /* !HASFLOCK */
  3308. if (tTd(55, 60))
  3309. dprintf("FAILn");
  3310. errno = save_errno;
  3311. return FALSE;
  3312. }
  3313. /*
  3314. **  CHOWNSAFE -- tell if chown is "safe" (executable only by root)
  3315. **
  3316. ** Unfortunately, given that we can't predict other systems on which
  3317. ** a remote mounted (NFS) filesystem will be mounted, the answer is
  3318. ** almost always that this is unsafe.
  3319. **
  3320. ** Note also that many operating systems have non-compliant
  3321. ** implementations of the _POSIX_CHOWN_RESTRICTED variable and the
  3322. ** fpathconf() routine.  According to IEEE 1003.1-1990, if
  3323. ** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
  3324. ** no non-root process can give away the file.  However, vendors
  3325. ** don't take NFS into account, so a comfortable value of
  3326. ** _POSIX_CHOWN_RESTRICTED tells us nothing.
  3327. **
  3328. ** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
  3329. ** even on files where chown is not restricted.  Many systems get
  3330. ** this wrong on NFS-based filesystems (that is, they say that chown
  3331. ** is restricted [safe] on NFS filesystems where it may not be, since
  3332. ** other systems can access the same filesystem and do file giveaway;
  3333. ** only the NFS server knows for sure!)  Hence, it is important to
  3334. ** get the value of SAFENFSPATHCONF correct -- it should be defined
  3335. ** _only_ after testing (see test/t_pathconf.c) a system on an unsafe
  3336. ** NFS-based filesystem to ensure that you can get meaningful results.
  3337. ** If in doubt, assume unsafe!
  3338. **
  3339. ** You may also need to tweak IS_SAFE_CHOWN -- it should be a
  3340. ** condition indicating whether the return from pathconf indicates
  3341. ** that chown is safe (typically either > 0 or >= 0 -- there isn't
  3342. ** even any agreement about whether a zero return means that a file
  3343. ** is or is not safe).  It defaults to "> 0".
  3344. **
  3345. ** If the parent directory is safe (writable only by owner back
  3346. ** to the root) then we can relax slightly and trust fpathconf
  3347. ** in more circumstances.  This is really a crock -- if this is an
  3348. ** NFS mounted filesystem then we really know nothing about the
  3349. ** underlying implementation.  However, most systems pessimize and
  3350. ** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
  3351. ** we interpret as unsafe, as we should.  Thus, this heuristic gets
  3352. ** us into a possible problem only on systems that have a broken
  3353. ** pathconf implementation and which are also poorly configured
  3354. ** (have :include: files in group- or world-writable directories).
  3355. **
  3356. ** Parameters:
  3357. ** fd -- the file descriptor to check.
  3358. ** safedir -- set if the parent directory is safe.
  3359. **
  3360. ** Returns:
  3361. ** TRUE -- if the chown(2) operation is "safe" -- that is,
  3362. ** only root can chown the file to an arbitrary user.
  3363. ** FALSE -- if an arbitrary user can give away a file.
  3364. */
  3365. #ifndef IS_SAFE_CHOWN
  3366. # define IS_SAFE_CHOWN > 0
  3367. #endif /* ! IS_SAFE_CHOWN */
  3368. bool
  3369. chownsafe(fd, safedir)
  3370. int fd;
  3371. bool safedir;
  3372. {
  3373. #if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && 
  3374.     (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H))
  3375. int rval;
  3376. /* give the system administrator a chance to override */
  3377. if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail))
  3378. return TRUE;
  3379. /*
  3380. **  Some systems (e.g., SunOS) seem to have the call and the
  3381. **  #define _PC_CHOWN_RESTRICTED, but don't actually implement
  3382. **  the call.  This heuristic checks for that.
  3383. */
  3384. errno = 0;
  3385. rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
  3386. # if SAFENFSPATHCONF
  3387. return errno == 0 && rval IS_SAFE_CHOWN;
  3388. # else /* SAFENFSPATHCONF */
  3389. return safedir && errno == 0 && rval IS_SAFE_CHOWN;
  3390. # endif /* SAFENFSPATHCONF */
  3391. #else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) &&  */
  3392. return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail);
  3393. #endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) &&  */
  3394. }
  3395. /*
  3396. **  RESETLIMITS -- reset system controlled resource limits
  3397. **
  3398. ** This is to avoid denial-of-service attacks
  3399. **
  3400. ** Parameters:
  3401. ** none
  3402. **
  3403. ** Returns:
  3404. ** none
  3405. */
  3406. #if HASSETRLIMIT
  3407. # ifdef RLIMIT_NEEDS_SYS_TIME_H
  3408. #  include <sys/time.h>
  3409. # endif /* RLIMIT_NEEDS_SYS_TIME_H */
  3410. # include <sys/resource.h>
  3411. #endif /* HASSETRLIMIT */
  3412. #ifndef FD_SETSIZE
  3413. # define FD_SETSIZE 256
  3414. #endif /* ! FD_SETSIZE */
  3415. void
  3416. resetlimits()
  3417. {
  3418. #if HASSETRLIMIT
  3419. struct rlimit lim;
  3420. lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
  3421. (void) setrlimit(RLIMIT_CPU, &lim);
  3422. (void) setrlimit(RLIMIT_FSIZE, &lim);
  3423. # ifdef RLIMIT_NOFILE
  3424. lim.rlim_cur = lim.rlim_max = FD_SETSIZE;
  3425. (void) setrlimit(RLIMIT_NOFILE, &lim);
  3426. # endif /* RLIMIT_NOFILE */
  3427. #else /* HASSETRLIMIT */
  3428. # if HASULIMIT
  3429. (void) ulimit(2, 0x3fffff);
  3430. (void) ulimit(4, FD_SETSIZE);
  3431. # endif /* HASULIMIT */
  3432. #endif /* HASSETRLIMIT */
  3433. errno = 0;
  3434. }
  3435. /*
  3436. **  GETCFNAME -- return the name of the .cf file.
  3437. **
  3438. ** Some systems (e.g., NeXT) determine this dynamically.
  3439. */
  3440. char *
  3441. getcfname()
  3442. {
  3443. if (ConfFile != NULL)
  3444. return ConfFile;
  3445. #if NETINFO
  3446. {
  3447. char *cflocation;
  3448. cflocation = ni_propval("/locations", NULL, "sendmail",
  3449. "sendmail.cf", '');
  3450. if (cflocation != NULL)
  3451. return cflocation;
  3452. }
  3453. #endif /* NETINFO */
  3454. return _PATH_SENDMAILCF;
  3455. }
  3456. /*
  3457. **  SETVENDOR -- process vendor code from V configuration line
  3458. **
  3459. ** Parameters:
  3460. ** vendor -- string representation of vendor.
  3461. **
  3462. ** Returns:
  3463. ** TRUE -- if ok.
  3464. ** FALSE -- if vendor code could not be processed.
  3465. **
  3466. ** Side Effects:
  3467. ** It is reasonable to set mode flags here to tweak
  3468. ** processing in other parts of the code if necessary.
  3469. ** For example, if you are a vendor that uses $%y to
  3470. ** indicate YP lookups, you could enable that here.
  3471. */
  3472. bool
  3473. setvendor(vendor)
  3474. char *vendor;
  3475. {
  3476. if (strcasecmp(vendor, "Berkeley") == 0)
  3477. {
  3478. VendorCode = VENDOR_BERKELEY;
  3479. return TRUE;
  3480. }
  3481. /* add vendor extensions here */
  3482. #ifdef SUN_EXTENSIONS
  3483. if (strcasecmp(vendor, "Sun") == 0)
  3484. {
  3485. VendorCode = VENDOR_SUN;
  3486. return TRUE;
  3487. }
  3488. #endif /* SUN_EXTENSIONS */
  3489. #if defined(VENDOR_NAME) && defined(VENDOR_CODE)
  3490. if (strcasecmp(vendor, VENDOR_NAME) == 0)
  3491. {
  3492. VendorCode = VENDOR_CODE;
  3493. return TRUE;
  3494. }
  3495. #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
  3496. return FALSE;
  3497. }
  3498. /*
  3499. **  GETVENDOR -- return vendor name based on vendor code
  3500. **
  3501. ** Parameters:
  3502. ** vendorcode -- numeric representation of vendor.
  3503. **
  3504. ** Returns:
  3505. ** string containing vendor name.
  3506. */
  3507. char *
  3508. getvendor(vendorcode)
  3509. int vendorcode;
  3510. {
  3511. #if defined(VENDOR_NAME) && defined(VENDOR_CODE)
  3512. /*
  3513. **  Can't have the same switch case twice so need to
  3514. **  handle VENDOR_CODE outside of switch.  It might
  3515. **  match one of the existing VENDOR_* codes.
  3516. */
  3517. if (vendorcode == VENDOR_CODE)
  3518. return VENDOR_NAME;
  3519. #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
  3520. switch (vendorcode)
  3521. {
  3522. case VENDOR_BERKELEY:
  3523. return "Berkeley";
  3524. case VENDOR_SUN:
  3525. return "Sun";
  3526. case VENDOR_HP:
  3527. return "HP";
  3528. case VENDOR_IBM:
  3529. return "IBM";
  3530. case VENDOR_SENDMAIL:
  3531. return "Sendmail";
  3532. default:
  3533. return "Unknown";
  3534. }
  3535. }
  3536. /*
  3537. **  VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
  3538. **
  3539. ** Vendor_pre_defaults is called before reading the configuration
  3540. ** file; vendor_post_defaults is called immediately after.
  3541. **
  3542. ** Parameters:
  3543. ** e -- the global environment to initialize.
  3544. **
  3545. ** Returns:
  3546. ** none.
  3547. */
  3548. #if SHARE_V1
  3549. int DefShareUid; /* default share uid to run as -- unused??? */
  3550. #endif /* SHARE_V1 */
  3551. void
  3552. vendor_pre_defaults(e)
  3553. ENVELOPE *e;
  3554. {
  3555. #if SHARE_V1
  3556. /* OTHERUID is defined in shares.h, do not be alarmed */
  3557. DefShareUid = OTHERUID;
  3558. #endif /* SHARE_V1 */
  3559. #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
  3560. sun_pre_defaults(e);
  3561. #endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */
  3562. #ifdef apollo
  3563. /*
  3564. **  stupid domain/os can't even open
  3565. **  /etc/mail/sendmail.cf without this
  3566. */
  3567. setuserenv("ISP", NULL);
  3568. setuserenv("SYSTYPE", NULL);
  3569. #endif /* apollo */
  3570. }
  3571. void
  3572. vendor_post_defaults(e)
  3573. ENVELOPE *e;
  3574. {
  3575. #ifdef __QNX__
  3576. char *p;
  3577. /* Makes sure the SOCK environment variable remains */
  3578. if (p = getextenv("SOCK"))
  3579. setuserenv("SOCK", p);
  3580. #endif /* __QNX__ */
  3581. #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
  3582. sun_post_defaults(e);
  3583. #endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */
  3584. }
  3585. /*
  3586. **  VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
  3587. */
  3588. void
  3589. vendor_daemon_setup(e)
  3590. ENVELOPE *e;
  3591. {
  3592. #if HASSETLOGIN
  3593. (void) setlogin(RunAsUserName);
  3594. #endif /* HASSETLOGIN */
  3595. #if SECUREWARE
  3596. if (getluid() != -1)
  3597. {
  3598. usrerr("Daemon cannot have LUID");
  3599. finis(FALSE, EX_USAGE);
  3600. }
  3601. #endif /* SECUREWARE */
  3602. }
  3603. /*
  3604. **  VENDOR_SET_UID -- do setup for setting a user id
  3605. **
  3606. ** This is called when we are still root.
  3607. **
  3608. ** Parameters:
  3609. ** uid -- the uid we are about to become.
  3610. **
  3611. ** Returns:
  3612. ** none.
  3613. */
  3614. void
  3615. vendor_set_uid(uid)
  3616. UID_T uid;
  3617. {
  3618. /*
  3619. **  We need to setup the share groups (lnodes)
  3620. **  and add auditing information (luid's)
  3621. **  before we loose our ``root''ness.
  3622. */
  3623. #if SHARE_V1
  3624. if (setupshares(uid, syserr) != 0)
  3625. syserr("Unable to set up shares");
  3626. #endif /* SHARE_V1 */
  3627. #if SECUREWARE
  3628. (void) setup_secure(uid);
  3629. #endif /* SECUREWARE */
  3630. }
  3631. /*
  3632. **  VALIDATE_CONNECTION -- check connection for rationality
  3633. **
  3634. ** If the connection is rejected, this routine should log an
  3635. ** appropriate message -- but should never issue any SMTP protocol.
  3636. **
  3637. ** Parameters:
  3638. ** sap -- a pointer to a SOCKADDR naming the peer.
  3639. ** hostname -- the name corresponding to sap.
  3640. ** e -- the current envelope.
  3641. **
  3642. ** Returns:
  3643. ** error message from rejection.
  3644. ** NULL if not rejected.
  3645. */
  3646. #if TCPWRAPPERS
  3647. # include <tcpd.h>
  3648. /* tcpwrappers does no logging, but you still have to declare these -- ugh */
  3649. int allow_severity = LOG_INFO;
  3650. int deny_severity = LOG_NOTICE;
  3651. #endif /* TCPWRAPPERS */
  3652. #if DAEMON
  3653. char *
  3654. validate_connection(sap, hostname, e)
  3655. SOCKADDR *sap;
  3656. char *hostname;
  3657. ENVELOPE *e;
  3658. {
  3659. # if TCPWRAPPERS
  3660. char *host;
  3661. # endif /* TCPWRAPPERS */
  3662. if (tTd(48, 3))
  3663. dprintf("validate_connection(%s, %s)n",
  3664. hostname, anynet_ntoa(sap));
  3665. if (rscheck("check_relay", hostname, anynet_ntoa(sap), e, TRUE, TRUE)
  3666.     != EX_OK)
  3667. {
  3668. static char reject[BUFSIZ*2];
  3669. extern char MsgBuf[];
  3670. if (tTd(48, 4))
  3671. dprintf("  ... validate_connection: BAD (rscheck)n");
  3672. if (strlen(MsgBuf) > 5)
  3673. {
  3674. if (ISSMTPCODE(MsgBuf))
  3675. {
  3676. int off;
  3677. if ((off = isenhsc(MsgBuf + 4, ' ')) > 0)
  3678. off += 5;
  3679. else
  3680. off = 4;
  3681. (void) strlcpy(reject, &MsgBuf[off],
  3682.        sizeof reject);
  3683. }
  3684. else
  3685. (void) strlcpy(reject, MsgBuf, sizeof reject);
  3686. }
  3687. else
  3688. (void) strlcpy(reject, "Access denied", sizeof reject);
  3689. return reject;
  3690. }
  3691. # if TCPWRAPPERS
  3692. if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']')
  3693. host = "unknown";
  3694. else
  3695. host = hostname;
  3696. if (!hosts_ctl("sendmail", host, anynet_ntoa(sap), STRING_UNKNOWN))
  3697. {
  3698. if (tTd(48, 4))
  3699. dprintf("  ... validate_connection: BAD (tcpwrappers)n");
  3700. if (LogLevel >= 4)
  3701. sm_syslog(LOG_NOTICE, e->e_id,
  3702. "tcpwrappers (%s, %s) rejection",
  3703. host, anynet_ntoa(sap));
  3704. return "Access denied";
  3705. }
  3706. # endif /* TCPWRAPPERS */
  3707. if (tTd(48, 4))
  3708. dprintf("  ... validate_connection: OKn");
  3709. return NULL;
  3710. }
  3711. #endif /* DAEMON */
  3712. /*
  3713. **  STRTOL -- convert string to long integer
  3714. **
  3715. ** For systems that don't have it in the C library.
  3716. **
  3717. ** This is taken verbatim from the 4.4-Lite C library.
  3718. */
  3719. #if NEEDSTRTOL
  3720. # if defined(LIBC_SCCS) && !defined(lint)
  3721. static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
  3722. # endif /* defined(LIBC_SCCS) && !defined(lint) */
  3723. /*
  3724.  * Convert a string to a long integer.
  3725.  *
  3726.  * Ignores `locale' stuff.  Assumes that the upper and lower case
  3727.  * alphabets and digits are each contiguous.
  3728.  */
  3729. long
  3730. strtol(nptr, endptr, base)
  3731. const char *nptr;
  3732. char **endptr;
  3733. register int base;
  3734. {
  3735. register const char *s = nptr;
  3736. register unsigned long acc;
  3737. register int c;
  3738. register unsigned long cutoff;
  3739. register int neg = 0, any, cutlim;
  3740. /*
  3741.  * Skip white space and pick up leading +/- sign if any.
  3742.  * If base is 0, allow 0x for hex and 0 for octal, else
  3743.  * assume decimal; if base is already 16, allow 0x.
  3744.  */
  3745. do {
  3746. c = *s++;
  3747. } while (isspace(c));
  3748. if (c == '-') {
  3749. neg = 1;
  3750. c = *s++;
  3751. } else if (c == '+')
  3752. c = *s++;
  3753. if ((base == 0 || base == 16) &&
  3754.     c == '0' && (*s == 'x' || *s == 'X')) {
  3755. c = s[1];
  3756. s += 2;
  3757. base = 16;
  3758. }
  3759. if (base == 0)
  3760. base = c == '0' ? 8 : 10;
  3761. /*
  3762.  * Compute the cutoff value between legal numbers and illegal
  3763.  * numbers.  That is the largest legal value, divided by the
  3764.  * base.  An input number that is greater than this value, if
  3765.  * followed by a legal input character, is too big.  One that
  3766.  * is equal to this value may be valid or not; the limit
  3767.  * between valid and invalid numbers is then based on the last
  3768.  * digit.  For instance, if the range for longs is
  3769.  * [-2147483648..2147483647] and the input base is 10,
  3770.  * cutoff will be set to 214748364 and cutlim to either
  3771.  * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
  3772.  * a value > 214748364, or equal but the next digit is > 7 (or 8),
  3773.  * the number is too big, and we will return a range error.
  3774.  *
  3775.  * Set any if any `digits' consumed; make it negative to indicate
  3776.  * overflow.
  3777.  */
  3778. cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
  3779. cutlim = cutoff % (unsigned long)base;
  3780. cutoff /= (unsigned long)base;
  3781. for (acc = 0, any = 0;; c = *s++) {
  3782. if (isdigit(c))
  3783. c -= '0';
  3784. else if (isalpha(c))
  3785. c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  3786. else
  3787. break;
  3788. if (c >= base)
  3789. break;
  3790. if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
  3791. any = -1;
  3792. else {
  3793. any = 1;
  3794. acc *= base;
  3795. acc += c;
  3796. }
  3797. }
  3798. if (any < 0) {
  3799. acc = neg ? LONG_MIN : LONG_MAX;
  3800. errno = ERANGE;
  3801. } else if (neg)
  3802. acc = -acc;
  3803. if (endptr != 0)
  3804. *endptr = (char *)(any ? s - 1 : nptr);
  3805. return acc;
  3806. }
  3807. #endif /* NEEDSTRTOL */
  3808. /*
  3809. **  STRSTR -- find first substring in string
  3810. **
  3811. ** Parameters:
  3812. ** big -- the big (full) string.
  3813. ** little -- the little (sub) string.
  3814. **
  3815. ** Returns:
  3816. ** A pointer to the first instance of little in big.
  3817. ** big if little is the null string.
  3818. ** NULL if little is not contained in big.
  3819. */
  3820. #if NEEDSTRSTR
  3821. char *
  3822. strstr(big, little)
  3823. char *big;
  3824. char *little;
  3825. {
  3826. register char *p = big;
  3827. int l;
  3828. if (*little == '')
  3829. return big;
  3830. l = strlen(little);
  3831. while ((p = strchr(p, *little)) != NULL)
  3832. {
  3833. if (strncmp(p, little, l) == 0)
  3834. return p;
  3835. p++;
  3836. }
  3837. return NULL;
  3838. }
  3839. #endif /* NEEDSTRSTR */
  3840. /*
  3841. **  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
  3842. **
  3843. ** Some operating systems have wierd problems with the gethostbyXXX
  3844. ** routines.  For example, Solaris versions at least through 2.3
  3845. ** don't properly deliver a canonical h_name field.  This tries to
  3846. ** work around these problems.
  3847. **
  3848. ** Support IPv6 as well as IPv4.
  3849. */
  3850. #if NETINET6 && NEEDSGETIPNODE && __RES < 19990909
  3851. # ifndef AI_V4MAPPED
  3852. #  define AI_V4MAPPED 0 /* dummy */
  3853. # endif /* ! AI_V4MAPPED */
  3854. # ifndef AI_ALL
  3855. #  define AI_ALL 0 /* dummy */
  3856. # endif /* ! AI_ALL */
  3857. static struct hostent *
  3858. getipnodebyname(name, family, flags, err)
  3859. char *name;
  3860. int family;
  3861. int flags;
  3862. int *err;
  3863. {
  3864. bool resv6 = TRUE;
  3865. struct hostent *h;
  3866. if (family == AF_INET6)
  3867. {
  3868. /* From RFC2133, section 6.1 */
  3869. resv6 = bitset(RES_USE_INET6, _res.options);
  3870. _res.options |= RES_USE_INET6;
  3871. }
  3872. h_errno = 0;
  3873. h = gethostbyname(name);
  3874. *err = h_errno;
  3875. if (family == AF_INET6 && !resv6)
  3876. _res.options &= ~RES_USE_INET6;
  3877. return h;
  3878. }
  3879. static struct hostent *
  3880. getipnodebyaddr(addr, len, family, err)
  3881. char *addr;
  3882. int len;
  3883. int family;
  3884. int *err;
  3885. {
  3886. struct hostent *h;
  3887. h_errno = 0;
  3888. h = gethostbyaddr(addr, len, family);
  3889. *err = h_errno;
  3890. return h;
  3891. }
  3892. #endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */
  3893. struct hostent *
  3894. sm_gethostbyname(name, family)
  3895. char *name;
  3896. int family;
  3897. {
  3898. struct hostent *h = NULL;
  3899. #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
  3900. # if SOLARIS == 20300 || SOLARIS == 203
  3901. static struct hostent hp;
  3902. static char buf[1000];
  3903. extern struct hostent *_switch_gethostbyname_r();
  3904. if (tTd(61, 10))
  3905. dprintf("_switch_gethostbyname_r(%s)... ", name);
  3906. h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
  3907. # else /* SOLARIS == 20300 || SOLARIS == 203 */
  3908. extern struct hostent *__switch_gethostbyname();
  3909. if (tTd(61, 10))
  3910. dprintf("__switch_gethostbyname(%s)... ", name);
  3911. h = __switch_gethostbyname(name);
  3912. # endif /* SOLARIS == 20300 || SOLARIS == 203 */
  3913. #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
  3914. int nmaps;
  3915. # if NETINET6
  3916. int err;
  3917. # endif /* NETINET6 */
  3918. int save_errno;
  3919. char *maptype[MAXMAPSTACK];
  3920. short mapreturn[MAXMAPACTIONS];
  3921. char hbuf[MAXNAME];
  3922. if (tTd(61, 10))
  3923. dprintf("sm_gethostbyname(%s, %d)... ", name, family);
  3924. # if NETINET6
  3925. h = getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err);
  3926. h_errno = err;
  3927. # else /* NETINET6 */
  3928. h = gethostbyname(name);
  3929. # endif /* NETINET6 */
  3930. save_errno = errno;
  3931. if (h == NULL)
  3932. {
  3933. if (tTd(61, 10))
  3934. dprintf("failuren");
  3935. nmaps = switch_map_find("hosts", maptype, mapreturn);
  3936. while (--nmaps >= 0)
  3937. if (strcmp(maptype[nmaps], "nis") == 0 ||
  3938.     strcmp(maptype[nmaps], "files") == 0)
  3939. break;
  3940. if (nmaps >= 0)
  3941. {
  3942. /* try short name */
  3943. if (strlen(name) > (SIZE_T) sizeof hbuf - 1)
  3944. {
  3945. errno = save_errno;
  3946. return NULL;
  3947. }
  3948. (void) strlcpy(hbuf, name, sizeof hbuf);
  3949. shorten_hostname(hbuf);
  3950. /* if it hasn't been shortened, there's no point */
  3951. if (strcmp(hbuf, name) != 0)
  3952. {
  3953. if (tTd(61, 10))
  3954. dprintf("sm_gethostbyname(%s, %d)... ",
  3955.        hbuf, family);
  3956. # if NETINET6
  3957. h = getipnodebyname(hbuf, family,
  3958.     AI_V4MAPPED|AI_ALL,
  3959.     &err);
  3960. h_errno = err;
  3961. save_errno = errno;
  3962. # else /* NETINET6 */
  3963. h = gethostbyname(hbuf);
  3964. save_errno = errno;
  3965. # endif /* NETINET6 */
  3966. }
  3967. }
  3968. }
  3969. #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
  3970. if (tTd(61, 10))
  3971. {
  3972. if (h == NULL)
  3973. dprintf("failuren");
  3974. else
  3975. {
  3976. dprintf("%sn", h->h_name);
  3977. if (tTd(61, 11))
  3978. {
  3979. #if NETINET6
  3980. struct in6_addr ia6;
  3981. char buf6[INET6_ADDRSTRLEN];
  3982. #else /* NETINET6 */
  3983. struct in_addr ia;
  3984. #endif /* NETINET6 */
  3985. int i;
  3986. if (h->h_aliases != NULL)
  3987. for (i = 0; h->h_aliases[i] != NULL;
  3988.      i++)
  3989. dprintf("talias: %sn",
  3990. h->h_aliases[i]);
  3991. for (i = 0; h->h_addr_list[i] != NULL; i++)
  3992. {
  3993. char *addr;
  3994. #if NETINET6
  3995. memmove(&ia6, h->h_addr_list[i],
  3996. IN6ADDRSZ);
  3997. addr = anynet_ntop(&ia6,
  3998.    buf6, sizeof buf6);
  3999. #else /* NETINET6 */
  4000. memmove(&ia, h->h_addr_list[i],
  4001. INADDRSZ);
  4002. addr = (char *) inet_ntoa(ia);
  4003. #endif /* NETINET6 */
  4004. if (addr != NULL)
  4005. dprintf("taddr: %sn", addr);
  4006. }
  4007. }
  4008. }
  4009. }
  4010. errno = save_errno;
  4011. return h;
  4012. }
  4013. struct hostent *
  4014. sm_gethostbyaddr(addr, len, type)
  4015. char *addr;
  4016. int len;
  4017. int type;
  4018. {
  4019. struct hostent *hp;
  4020. #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
  4021. # if SOLARIS == 20300 || SOLARIS == 203
  4022. static struct hostent he;
  4023. static char buf[1000];
  4024. extern struct hostent *_switch_gethostbyaddr_r();
  4025. hp = _switch_gethostbyaddr_r(addr, len, type, &he, buf, sizeof(buf), &h_errno);
  4026. # else /* SOLARIS == 20300 || SOLARIS == 203 */
  4027. extern struct hostent *__switch_gethostbyaddr();
  4028. hp = __switch_gethostbyaddr(addr, len, type);
  4029. # endif /* SOLARIS == 20300 || SOLARIS == 203 */
  4030. #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
  4031. # if NETINET6
  4032. int err;
  4033. # endif /* NETINET6 */
  4034. # if NETINET6
  4035. hp = getipnodebyaddr(addr, len, type, &err);
  4036. h_errno = err;
  4037. # else /* NETINET6 */
  4038. hp = gethostbyaddr(addr, len, type);
  4039. # endif /* NETINET6 */
  4040. return hp;
  4041. #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
  4042. }
  4043. /*
  4044. **  SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
  4045. */
  4046. struct passwd *
  4047. sm_getpwnam(user)
  4048. char *user;
  4049. {
  4050. # ifdef _AIX4
  4051. extern struct passwd *_getpwnam_shadow(const char *, const int);
  4052. return _getpwnam_shadow(user, 0);
  4053. # else /* _AIX4 */
  4054. return getpwnam(user);
  4055. # endif /* _AIX4 */
  4056. }
  4057. struct passwd *
  4058. sm_getpwuid(uid)
  4059. UID_T uid;
  4060. {
  4061. # if defined(_AIX4) && 0
  4062. extern struct passwd *_getpwuid_shadow(const int, const int);
  4063. return _getpwuid_shadow(uid,0);
  4064. # else /* defined(_AIX4) && 0 */
  4065. return getpwuid(uid);
  4066. # endif /* defined(_AIX4) && 0 */
  4067. }
  4068. /*
  4069. **  SECUREWARE_SETUP_SECURE -- Convex SecureWare setup
  4070. **
  4071. ** Set up the trusted computing environment for C2 level security
  4072. ** under SecureWare.
  4073. **
  4074. ** Parameters:
  4075. ** uid -- uid of the user to initialize in the TCB
  4076. **
  4077. ** Returns:
  4078. ** none
  4079. **
  4080. ** Side Effects:
  4081. ** Initialized the user in the trusted computing base
  4082. */
  4083. #if SECUREWARE
  4084. # include <sys/security.h>
  4085. # include <prot.h>
  4086. void
  4087. secureware_setup_secure(uid)
  4088. UID_T uid;
  4089. {
  4090. int rc;
  4091. if (getluid() != -1)
  4092. return;
  4093. if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN)
  4094. {
  4095. switch (rc)
  4096. {
  4097.   case SSI_NO_PRPW_ENTRY:
  4098. syserr("No protected passwd entry, uid = %d", uid);
  4099. break;
  4100.   case SSI_LOCKED:
  4101. syserr("Account has been disabled, uid = %d", uid);
  4102. break;
  4103.   case SSI_RETIRED:
  4104. syserr("Account has been retired, uid = %d", uid);
  4105. break;
  4106.   case SSI_BAD_SET_LUID:
  4107. syserr("Could not set LUID, uid = %d", uid);
  4108. break;
  4109.   case SSI_BAD_SET_PRIVS:
  4110. syserr("Could not set kernel privs, uid = %d", uid);
  4111.   default:
  4112. syserr("Unknown return code (%d) from set_secure_info(%d)",
  4113. rc, uid);
  4114. break;
  4115. }
  4116. finis(FALSE, EX_NOPERM);
  4117. }
  4118. }
  4119. #endif /* SECUREWARE */
  4120. /*
  4121. **  ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address
  4122. **
  4123. ** Add hostnames to class 'w' based on the IP address read from
  4124. ** the network interface.
  4125. **
  4126. ** Parameters:
  4127. ** sa -- a pointer to a SOCKADDR containing the address
  4128. **
  4129. ** Returns:
  4130. ** 0 if successful, -1 if host lookup fails.
  4131. */
  4132. #if (NETINET6 && defined(SIOCGLIFCONF)) || 
  4133.     (!NETINET6 && defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN)
  4134. static int
  4135. add_hostnames(sa)
  4136. SOCKADDR *sa;
  4137. {
  4138. struct hostent *hp;
  4139. char **ha;
  4140. char hnb[MAXHOSTNAMELEN];
  4141. /* lookup name with IP address */
  4142. switch (sa->sa.sa_family)
  4143. {
  4144. #if NETINET
  4145. case AF_INET:
  4146. hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr,
  4147. sizeof(sa->sin.sin_addr), sa->sa.sa_family);
  4148. break;
  4149. #endif /* NETINET */
  4150. #if NETINET6
  4151. case AF_INET6:
  4152. hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr,
  4153. sizeof(sa->sin6.sin6_addr), sa->sa.sa_family);
  4154. break;
  4155. #endif /* NETINET6 */
  4156. default:
  4157. /* Give warning about unsupported family */
  4158. if (LogLevel > 3)
  4159. sm_syslog(LOG_WARNING, NOQID,
  4160.   "Unsupported address family %d: %.100s",
  4161.   sa->sa.sa_family, anynet_ntoa(sa));
  4162. return -1;
  4163. }
  4164. if (hp == NULL)
  4165. {
  4166. int save_errno = errno;
  4167. if (LogLevel > 3 &&
  4168. #if NETINET6
  4169.     !(sa->sa.sa_family == AF_INET6 &&
  4170.       IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) &&
  4171. #endif /* NETINET6 */
  4172.     TRUE)
  4173. sm_syslog(LOG_WARNING, NOQID,
  4174. "gethostbyaddr(%.100s) failed: %dn",
  4175. anynet_ntoa(sa),
  4176. #if NAMED_BIND
  4177. h_errno
  4178. #else /* NAMED_BIND */
  4179. -1
  4180. #endif /* NAMED_BIND */
  4181. );
  4182. errno = save_errno;
  4183. return -1;
  4184. }
  4185. /* save its cname */
  4186. if (!wordinclass((char *) hp->h_name, 'w'))
  4187. {
  4188. setclass('w', (char *) hp->h_name);
  4189. if (tTd(0, 4))
  4190. dprintf("ta.k.a.: %sn", hp->h_name);
  4191. if (snprintf(hnb, sizeof hnb, "[%s]", hp->h_name) < sizeof hnb
  4192.     && !wordinclass((char *) hnb, 'w'))
  4193. setclass('w', hnb);
  4194. }
  4195. else
  4196. {
  4197. if (tTd(0, 43))
  4198. dprintf("ta.k.a.: %s (already in $=w)n", hp->h_name);
  4199. }
  4200. /* save all it aliases name */
  4201. for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
  4202. {
  4203. if (!wordinclass(*ha, 'w'))
  4204. {
  4205. setclass('w', *ha);
  4206. if (tTd(0, 4))
  4207. dprintf("ta.k.a.: %sn", *ha);
  4208. if (snprintf(hnb, sizeof hnb,
  4209.      "[%s]", *ha) < sizeof hnb &&
  4210.     !wordinclass((char *) hnb, 'w'))
  4211. setclass('w', hnb);
  4212. }
  4213. else
  4214. {
  4215. if (tTd(0, 43))
  4216. dprintf("ta.k.a.: %s (already in $=w)n",
  4217. *ha);
  4218. }
  4219. }
  4220. return 0;
  4221. }
  4222. #endif /* (NETINET6 && defined(SIOCGLIFCONF)) || 
  4223.   (!NETINET6 && defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN) */
  4224. /*
  4225. **  LOAD_IF_NAMES -- load interface-specific names into $=w
  4226. **
  4227. ** Parameters:
  4228. ** none.
  4229. **
  4230. ** Returns:
  4231. ** none.
  4232. **
  4233. ** Side Effects:
  4234. ** Loads $=w with the names of all the interfaces.
  4235. */
  4236. #if !NETINET
  4237. # define SIOCGIFCONF_IS_BROKEN 1 /* XXX */
  4238. #endif /* !NETINET */
  4239. #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
  4240. struct rtentry;
  4241. struct mbuf;
  4242. # ifndef SUNOS403
  4243. #  include <sys/time.h>
  4244. # endif /* ! SUNOS403 */
  4245. # if (_AIX4 >= 40300) && !defined(_NET_IF_H)
  4246. #  undef __P
  4247. # endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */
  4248. # include <net/if.h>
  4249. #endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
  4250. void
  4251. load_if_names()
  4252. {
  4253. #if NETINET6
  4254. # ifdef SIOCGLIFCONF
  4255. int s;
  4256. int i;
  4257. struct lifconf lifc;
  4258. struct lifnum lifn;
  4259. int numifs;
  4260. s = socket(AF_INET6, SOCK_DGRAM, 0);
  4261. if (s == -1)
  4262. return;
  4263. /* get the list of known IP address from the kernel */
  4264. #  ifdef SIOCGLIFNUM
  4265. lifn.lifn_family = AF_UNSPEC;
  4266. lifn.lifn_flags = 0;
  4267. if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0)
  4268. {
  4269. /* can't get number of interfaces -- fall back */
  4270. if (tTd(0, 4))
  4271. dprintf("SIOCGLIFNUM failed: %sn", errstring(errno));
  4272. numifs = -1;
  4273. }
  4274. else
  4275. {
  4276. numifs = lifn.lifn_count;
  4277. if (tTd(0, 42))
  4278. dprintf("system has %d interfacesn", numifs);
  4279. }
  4280. if (numifs < 0)
  4281. #  endif /* SIOCGLIFNUM */
  4282. numifs = MAXINTERFACES;
  4283. if (numifs <= 0)
  4284. {
  4285. close(s);
  4286. return;
  4287. }
  4288. lifc.lifc_len = numifs * sizeof (struct lifreq);
  4289. lifc.lifc_buf = xalloc(lifc.lifc_len);
  4290. lifc.lifc_family = AF_UNSPEC;
  4291. lifc.lifc_flags = 0;
  4292. if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0)
  4293. {
  4294. if (tTd(0, 4))
  4295. dprintf("SIOCGLIFCONF failed: %sn", errstring(errno));
  4296. close(s);
  4297. return;
  4298. }
  4299. /* scan the list of IP address */
  4300. if (tTd(0, 40))
  4301. dprintf("scanning for interface specific names, lifc_len=%dn",
  4302. lifc.lifc_len);
  4303. for (i = 0; i < lifc.lifc_len; )
  4304. {
  4305. struct lifreq *ifr = (struct lifreq *)&lifc.lifc_buf[i];
  4306. SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr;
  4307. char *addr;
  4308. struct in6_addr ia6;
  4309. struct in_addr ia;
  4310. #  ifdef SIOCGLIFFLAGS
  4311. struct lifreq ifrf;
  4312. #  endif /* SIOCGLIFFLAGS */
  4313. char ip_addr[256];
  4314. char buf6[INET6_ADDRSTRLEN];
  4315. int af = ifr->lifr_addr.ss_family;
  4316. /*
  4317. **  We must close and recreate the socket each time
  4318. **  since we don't know what type of socket it is now
  4319. **  (each status function may change it).
  4320. */
  4321. (void) close(s);
  4322. s = socket(af, SOCK_DGRAM, 0);
  4323. if (s == -1)
  4324. return;
  4325. /*
  4326. **  If we don't have a complete ifr structure,
  4327. **  don't try to use it.
  4328. */
  4329. if ((lifc.lifc_len - i) < sizeof *ifr)
  4330. break;
  4331. #  ifdef BSD4_4_SOCKADDR
  4332. if (sa->sa.sa_len > sizeof ifr->lifr_addr)
  4333. i += sizeof ifr->lifr_name + sa->sa.sa_len;
  4334. else
  4335. #  endif /* BSD4_4_SOCKADDR */
  4336. i += sizeof *ifr;
  4337. if (tTd(0, 20))
  4338. dprintf("%sn", anynet_ntoa(sa));
  4339. if (af != AF_INET && af != AF_INET6)
  4340. continue;
  4341. #  ifdef SIOCGLIFFLAGS
  4342. memset(&ifrf, '', sizeof(struct lifreq));
  4343. (void) strlcpy(ifrf.lifr_name, ifr->lifr_name,
  4344.        sizeof(ifrf.lifr_name));
  4345. if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0)
  4346. {
  4347. if (tTd(0, 4))
  4348. dprintf("SIOCGLIFFLAGS failed: %sn",
  4349. errstring(errno));
  4350. continue;
  4351. }
  4352. else if (tTd(0, 41))
  4353. dprintf("tflags: %lxn",
  4354. (unsigned long)ifrf.lifr_flags);
  4355. if (!bitset(IFF_UP, ifrf.lifr_flags))
  4356. continue;
  4357. #  endif /* SIOCGLIFFLAGS */
  4358. ip_addr[0] = '';
  4359. /* extract IP address from the list*/
  4360. switch (af)
  4361. {
  4362.   case AF_INET6:
  4363. ia6 = sa->sin6.sin6_addr;
  4364. if (ia6.s6_addr == in6addr_any.s6_addr)
  4365. {
  4366. addr = anynet_ntop(&ia6, buf6, sizeof buf6);
  4367. message("WARNING: interface %s is UP with %s address",
  4368. ifr->lifr_name,
  4369. addr == NULL ? "(NULL)" : addr);
  4370. continue;
  4371. }
  4372. /* save IP address in text from */
  4373. addr = anynet_ntop(&ia6, buf6, sizeof buf6);
  4374. if (addr != NULL)
  4375. (void) snprintf(ip_addr, sizeof ip_addr,
  4376. "[%.*s]",
  4377. sizeof ip_addr - 3, addr);
  4378. break;
  4379.   case AF_INET:
  4380. ia = sa->sin.sin_addr;
  4381. if (ia.s_addr == INADDR_ANY ||
  4382.     ia.s_addr == INADDR_NONE)
  4383. {
  4384. message("WARNING: interface %s is UP with %s address",
  4385. ifr->lifr_name, inet_ntoa(ia));
  4386. continue;
  4387. }
  4388. /* save IP address in text from */
  4389. (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]",
  4390. sizeof ip_addr - 3, inet_ntoa(ia));
  4391. break;
  4392. }
  4393. if (*ip_addr == '')
  4394. continue;
  4395. if (!wordinclass(ip_addr, 'w'))
  4396. {
  4397. setclass('w', ip_addr);
  4398. if (tTd(0, 4))
  4399. dprintf("ta.k.a.: %sn", ip_addr);
  4400. }
  4401. #  ifdef SIOCGLIFFLAGS
  4402. /* skip "loopback" interface "lo" */
  4403. if (bitset(IFF_LOOPBACK, ifrf.lifr_flags))
  4404. continue;
  4405. #  endif /* SIOCGLIFFLAGS */
  4406. (void) add_hostnames(sa);
  4407. }
  4408. free(lifc.lifc_buf);
  4409. close(s);
  4410. # endif /* SIOCGLIFCONF */
  4411. #else /* NETINET6 */
  4412. # if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
  4413. int s;
  4414. int i;
  4415. struct ifconf ifc;
  4416. int numifs;
  4417. s = socket(AF_INET, SOCK_DGRAM, 0);
  4418. if (s == -1)
  4419. return;
  4420. /* get the list of known IP address from the kernel */
  4421. #  if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN
  4422. if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
  4423. {
  4424. /* can't get number of interfaces -- fall back */
  4425. if (tTd(0, 4))
  4426. dprintf("SIOCGIFNUM failed: %sn", errstring(errno));
  4427. numifs = -1;
  4428. }
  4429. else if (tTd(0, 42))
  4430. dprintf("system has %d interfacesn", numifs);
  4431. if (numifs < 0)
  4432. #  endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */
  4433. numifs = MAXINTERFACES;
  4434. if (numifs <= 0)
  4435. {
  4436. (void) close(s);
  4437. return;
  4438. }
  4439. ifc.ifc_len = numifs * sizeof (struct ifreq);
  4440. ifc.ifc_buf = xalloc(ifc.ifc_len);
  4441. if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
  4442. {
  4443. if (tTd(0, 4))
  4444. dprintf("SIOCGIFCONF failed: %sn", errstring(errno));
  4445. (void) close(s);
  4446. return;
  4447. }
  4448. /* scan the list of IP address */
  4449. if (tTd(0, 40))
  4450. dprintf("scanning for interface specific names, ifc_len=%dn",
  4451. ifc.ifc_len);
  4452. for (i = 0; i < ifc.ifc_len; )
  4453. {
  4454. struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
  4455. SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr;
  4456. struct in_addr ia;
  4457. #  ifdef SIOCGIFFLAGS
  4458. struct ifreq ifrf;
  4459. #  endif /* SIOCGIFFLAGS */
  4460. char ip_addr[256];
  4461. /*
  4462. **  If we don't have a complete ifr structure,
  4463. **  don't try to use it.
  4464. */
  4465. if ((ifc.ifc_len - i) < sizeof *ifr)
  4466. break;
  4467. #  ifdef BSD4_4_SOCKADDR
  4468. if (sa->sa.sa_len > sizeof ifr->ifr_addr)
  4469. i += sizeof ifr->ifr_name + sa->sa.sa_len;
  4470. else
  4471. #  endif /* BSD4_4_SOCKADDR */
  4472. i += sizeof *ifr;
  4473. if (tTd(0, 20))
  4474. dprintf("%sn", anynet_ntoa(sa));
  4475. if (ifr->ifr_addr.sa_family != AF_INET)
  4476. continue;
  4477. #  ifdef SIOCGIFFLAGS
  4478. memset(&ifrf, '', sizeof(struct ifreq));
  4479. (void) strlcpy(ifrf.ifr_name, ifr->ifr_name,
  4480.        sizeof(ifrf.ifr_name));
  4481. (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
  4482. if (tTd(0, 41))
  4483. dprintf("tflags: %lxn", ifrf.ifr_flags);
  4484. #   define IFRFREF ifrf
  4485. #  else /* SIOCGIFFLAGS */
  4486. #   define IFRFREF (*ifr)
  4487. #  endif /* SIOCGIFFLAGS */
  4488. if (!bitset(IFF_UP, IFRFREF.ifr_flags))
  4489. continue;
  4490. /* extract IP address from the list*/
  4491. ia = sa->sin.sin_addr;
  4492. if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE)
  4493. {
  4494. message("WARNING: interface %s is UP with %s address",
  4495. ifr->ifr_name, inet_ntoa(ia));
  4496. continue;
  4497. }
  4498. /* save IP address in text from */
  4499. (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]",
  4500. (int) sizeof ip_addr - 3, inet_ntoa(ia));
  4501. if (!wordinclass(ip_addr, 'w'))
  4502. {
  4503. setclass('w', ip_addr);
  4504. if (tTd(0, 4))
  4505. dprintf("ta.k.a.: %sn", ip_addr);
  4506. }
  4507. /* skip "loopback" interface "lo" */
  4508. if (bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
  4509. continue;
  4510. (void) add_hostnames(sa);
  4511. }
  4512. free(ifc.ifc_buf);
  4513. (void) close(s);
  4514. #  undef IFRFREF
  4515. # endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
  4516. #endif /* NETINET6 */
  4517. }
  4518. /*
  4519. **  ISLOOPBACK -- is socket address in the loopback net?
  4520. **
  4521. ** Parameters:
  4522. ** sa -- socket address.
  4523. **
  4524. ** Returns:
  4525. ** TRUE -- is socket address in the loopback net?
  4526. ** FALSE -- otherwise
  4527. **
  4528. */
  4529. bool
  4530. isloopback(sa)
  4531. SOCKADDR sa;
  4532. {
  4533. #if NETINET6
  4534. if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr))
  4535. return TRUE;
  4536. #else /* NETINET6 */
  4537. /* XXX how to correctly extract IN_LOOPBACKNET part? */
  4538. if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET)
  4539.      >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
  4540. return TRUE;
  4541. #endif /* NETINET6 */
  4542. return FALSE;
  4543. }
  4544. /*
  4545. **  GET_NUM_PROCS_ONLINE -- return the number of processors currently online
  4546. **
  4547. ** Parameters:
  4548. ** none.
  4549. **
  4550. ** Returns:
  4551. ** The number of processors online.
  4552. */
  4553. static int
  4554. get_num_procs_online()
  4555. {
  4556. int nproc = 0;
  4557. #ifdef _SC_NPROCESSORS_ONLN
  4558. nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
  4559. #endif /* _SC_NPROCESSORS_ONLN */
  4560. if (nproc <= 0)
  4561. nproc = 1;
  4562. return nproc;
  4563. }
  4564. /*
  4565. **  SEED_RANDOM -- seed the random number generator
  4566. **
  4567. ** Parameters:
  4568. ** none
  4569. **
  4570. ** Returns:
  4571. ** none
  4572. */
  4573. void
  4574. seed_random()
  4575. {
  4576. #if HASSRANDOMDEV
  4577. srandomdev();
  4578. #else /* HASSRANDOMDEV */
  4579. long seed;
  4580. struct timeval t;
  4581. if (gettimeofday(&t, NULL) < 0)
  4582. seed = (long) getpid();
  4583. else
  4584. seed = t.tv_sec + t.tv_usec;
  4585. # if HASRANDOM
  4586. (void) srandom(seed);
  4587. # else /* HASRANDOM */
  4588. (void) srand((unsigned int) seed);
  4589. # endif /* HASRANDOM */
  4590. #endif /* HASSRANDOMDEV */
  4591. }
  4592. /*
  4593. **  SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
  4594. **
  4595. ** Parameters:
  4596. ** level -- syslog level
  4597. ** id -- envelope ID or NULL (NOQUEUE)
  4598. ** fmt -- format string
  4599. ** arg... -- arguments as implied by fmt.
  4600. **
  4601. ** Returns:
  4602. ** none
  4603. */
  4604. /* VARARGS3 */
  4605. void
  4606. #ifdef __STDC__
  4607. sm_syslog(int level, const char *id, const char *fmt, ...)
  4608. #else /* __STDC__ */
  4609. sm_syslog(level, id, fmt, va_alist)
  4610. int level;
  4611. const char *id;
  4612. const char *fmt;
  4613. va_dcl
  4614. #endif /* __STDC__ */
  4615. {
  4616. static char *buf = NULL;
  4617. static size_t bufsize;
  4618. char *begin, *end;
  4619. int seq = 1;
  4620. int idlen;
  4621. char buf0[MAXLINE];
  4622. extern int SnprfOverflow;
  4623. extern int SyslogErrno;
  4624. extern char *DoprEnd;
  4625. VA_LOCAL_DECL
  4626. SyslogErrno = errno;
  4627. if (id == NULL)
  4628. id = "NOQUEUE";
  4629. else if (strcmp(id, NOQID) == 0)
  4630. id = "";
  4631. idlen = strlen(id);
  4632. if (buf == NULL)
  4633. {
  4634. buf = buf0;
  4635. bufsize = sizeof buf0;
  4636. }
  4637. for (;;)
  4638. {
  4639. /* do a virtual vsnprintf into buf */
  4640. VA_START(fmt);
  4641. buf[0] = 0;
  4642. DoprEnd = buf + bufsize - 1;
  4643. SnprfOverflow = 0;
  4644. sm_dopr(buf, fmt, ap);
  4645. *DoprEnd = '';
  4646. VA_END;
  4647. /* end of virtual vsnprintf */
  4648. if (SnprfOverflow == 0)
  4649. break;
  4650. /* String too small, redo with correct size */
  4651. bufsize += SnprfOverflow + 1;
  4652. if (buf != buf0)
  4653. free(buf);
  4654. buf = xalloc(bufsize * sizeof (char));
  4655. }
  4656. if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE)
  4657. {
  4658. #if LOG
  4659. if (*id == '')
  4660. syslog(level, "%s", buf);
  4661. else
  4662. syslog(level, "%s: %s", id, buf);
  4663. #else /* LOG */
  4664. /*XXX should do something more sensible */
  4665. if (*id == '')
  4666. fprintf(stderr, "%sn", buf);
  4667. else
  4668. fprintf(stderr, "%s: %sn", id, buf);
  4669. #endif /* LOG */
  4670. if (buf == buf0)
  4671. buf = NULL;
  4672. return;
  4673. }
  4674. begin = buf;
  4675. while (*begin != '' &&
  4676.        (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE)
  4677. {
  4678. char save;
  4679. if (seq == 999)
  4680. {
  4681. /* Too many messages */
  4682. break;
  4683. }
  4684. end = begin + SYSLOG_BUFSIZE - idlen - 12;
  4685. while (end > begin)
  4686. {
  4687. /* Break on comma or space */
  4688. if (*end == ',' || *end == ' ')
  4689. {
  4690. end++;   /* Include separator */
  4691. break;
  4692. }
  4693. end--;
  4694. }
  4695. /* No separator, break midstring... */
  4696. if (end == begin)
  4697. end = begin + SYSLOG_BUFSIZE - idlen - 12;
  4698. save = *end;
  4699. *end = 0;
  4700. #if LOG
  4701. syslog(level, "%s[%d]: %s ...", id, seq++, begin);
  4702. #else /* LOG */
  4703. fprintf(stderr, "%s[%d]: %s ...n", id, seq++, begin);
  4704. #endif /* LOG */
  4705. *end = save;
  4706. begin = end;
  4707. }
  4708. if (seq == 999)
  4709. #if LOG
  4710. syslog(level, "%s[%d]: log terminated, too many parts",
  4711. id, seq);
  4712. #else /* LOG */
  4713. fprintf(stderr, "%s[%d]: log terminated, too many partsn",
  4714. id, seq);
  4715. #endif /* LOG */
  4716. else if (*begin != '')
  4717. #if LOG
  4718. syslog(level, "%s[%d]: %s", id, seq, begin);
  4719. #else /* LOG */
  4720. fprintf(stderr, "%s[%d]: %sn", id, seq, begin);
  4721. #endif /* LOG */
  4722. if (buf == buf0)
  4723. buf = NULL;
  4724. }
  4725. /*
  4726. **  HARD_SYSLOG -- call syslog repeatedly until it works
  4727. **
  4728. ** Needed on HP-UX, which apparently doesn't guarantee that
  4729. ** syslog succeeds during interrupt handlers.
  4730. */
  4731. #if defined(__hpux) && !defined(HPUX11)
  4732. # define MAXSYSLOGTRIES 100
  4733. # undef syslog
  4734. # ifdef V4FS
  4735. #  define XCNST const
  4736. #  define CAST (const char *)
  4737. # else /* V4FS */
  4738. #  define XCNST
  4739. #  define CAST
  4740. # endif /* V4FS */
  4741. void
  4742. # ifdef __STDC__
  4743. hard_syslog(int pri, XCNST char *msg, ...)
  4744. # else /* __STDC__ */
  4745. hard_syslog(pri, msg, va_alist)
  4746. int pri;
  4747. XCNST char *msg;
  4748. va_dcl
  4749. # endif /* __STDC__ */
  4750. {
  4751. int i;
  4752. char buf[SYSLOG_BUFSIZE];
  4753. VA_LOCAL_DECL;
  4754. VA_START(msg);
  4755. vsnprintf(buf, sizeof buf, msg, ap);
  4756. VA_END;
  4757. for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
  4758. continue;
  4759. }
  4760. # undef CAST
  4761. #endif /* defined(__hpux) && !defined(HPUX11) */
  4762. /*
  4763. **  LOCAL_HOSTNAME_LENGTH
  4764. **
  4765. ** This is required to get sendmail to compile against BIND 4.9.x
  4766. ** on Ultrix.
  4767. */
  4768. #if defined(ultrix) && NAMED_BIND
  4769. # if __RES >= 19931104 && __RES < 19950621
  4770. int
  4771. local_hostname_length(hostname)
  4772. char *hostname;
  4773. {
  4774. int len_host, len_domain;
  4775. if (!*_res.defdname)
  4776. res_init();
  4777. len_host = strlen(hostname);
  4778. len_domain = strlen(_res.defdname);
  4779. if (len_host > len_domain &&
  4780.     (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) &&
  4781.     hostname[len_host - len_domain - 1] == '.')
  4782. return len_host - len_domain - 1;
  4783. else
  4784. return 0;
  4785. }
  4786. # endif /* __RES >= 19931104 && __RES < 19950621 */
  4787. #endif /* defined(ultrix) && NAMED_BIND */
  4788. /*
  4789. **  Compile-Time options
  4790. */
  4791. char *CompileOptions[] =
  4792. {
  4793. #ifdef HESIOD
  4794. "HESIOD",
  4795. #endif /* HESIOD */
  4796. #if HES_GETMAILHOST
  4797. "HES_GETMAILHOST",
  4798. #endif /* HES_GETMAILHOST */
  4799. #ifdef LDAPMAP
  4800. "LDAPMAP",
  4801. #endif /* LDAPMAP */
  4802. #ifdef MAP_NSD
  4803. "MAP_NSD",
  4804. #endif /* MAP_NSD */
  4805. #ifdef MAP_REGEX
  4806. "MAP_REGEX",
  4807. #endif /* MAP_REGEX */
  4808. #if LOG
  4809. "LOG",
  4810. #endif /* LOG */
  4811. #if MATCHGECOS
  4812. "MATCHGECOS",
  4813. #endif /* MATCHGECOS */
  4814. #if MIME7TO8
  4815. "MIME7TO8",
  4816. #endif /* MIME7TO8 */
  4817. #if MIME8TO7
  4818. "MIME8TO7",
  4819. #endif /* MIME8TO7 */
  4820. #if NAMED_BIND
  4821. "NAMED_BIND",
  4822. #endif /* NAMED_BIND */
  4823. #ifdef NDBM
  4824. "NDBM",
  4825. #endif /* NDBM */
  4826. #if NETINET
  4827. "NETINET",
  4828. #endif /* NETINET */
  4829. #if NETINET6
  4830. "NETINET6",
  4831. #endif /* NETINET6 */
  4832. #if NETINFO
  4833. "NETINFO",
  4834. #endif /* NETINFO */
  4835. #if NETISO
  4836. "NETISO",
  4837. #endif /* NETISO */
  4838. #if NETNS
  4839. "NETNS",
  4840. #endif /* NETNS */
  4841. #if NETUNIX
  4842. "NETUNIX",
  4843. #endif /* NETUNIX */
  4844. #if NETX25
  4845. "NETX25",
  4846. #endif /* NETX25 */
  4847. #ifdef NEWDB
  4848. "NEWDB",
  4849. #endif /* NEWDB */
  4850. #ifdef NIS
  4851. "NIS",
  4852. #endif /* NIS */
  4853. #ifdef NISPLUS
  4854. "NISPLUS",
  4855. #endif /* NISPLUS */
  4856. #ifdef PH_MAP
  4857. "PH_MAP",
  4858. #endif /* PH_MAP */
  4859. #if QUEUE
  4860. "QUEUE",
  4861. #endif /* QUEUE */
  4862. #if SASL
  4863. "SASL",
  4864. #endif /* SASL */
  4865. #if SCANF
  4866. "SCANF",
  4867. #endif /* SCANF */
  4868. #if SMTP
  4869. "SMTP",
  4870. #endif /* SMTP */
  4871. #if SMTPDEBUG
  4872. "SMTPDEBUG",
  4873. #endif /* SMTPDEBUG */
  4874. #ifdef SUID_ROOT_FILES_OK
  4875. "SUID_ROOT_FILES_OK",
  4876. #endif /* SUID_ROOT_FILES_OK */
  4877. #if TCPWRAPPERS
  4878. "TCPWRAPPERS",
  4879. #endif /* TCPWRAPPERS */
  4880. #if USERDB
  4881. "USERDB",
  4882. #endif /* USERDB */
  4883. #if XDEBUG
  4884. "XDEBUG",
  4885. #endif /* XDEBUG */
  4886. #ifdef XLA
  4887. "XLA",
  4888. #endif /* XLA */
  4889. NULL
  4890. };
  4891. /*
  4892. **  OS compile options.
  4893. */
  4894. char *OsCompileOptions[] =
  4895. {
  4896. #if BOGUS_O_EXCL
  4897. "BOGUS_O_EXCL",
  4898. #endif /* BOGUS_O_EXCL */
  4899. #if FAST_PID_RECYCLE
  4900. "FAST_PID_RECYCLE",
  4901. #endif /* FAST_PID_RECYCLE */
  4902. #if HASFCHOWN
  4903. "HASFCHOWN",
  4904. #endif /* HASFCHOWN */
  4905. #if HASFCHMOD
  4906. "HASFCHMOD",
  4907. #endif /* HASFCHMOD */
  4908. #if HASFLOCK
  4909. "HASFLOCK",
  4910. #endif /* HASFLOCK */
  4911. #if HASGETDTABLESIZE
  4912. "HASGETDTABLESIZE",
  4913. #endif /* HASGETDTABLESIZE */
  4914. #if HASGETUSERSHELL
  4915. "HASGETUSERSHELL",
  4916. #endif /* HASGETUSERSHELL */
  4917. #if HASINITGROUPS
  4918. "HASINITGROUPS",
  4919. #endif /* HASINITGROUPS */
  4920. #if HASLSTAT
  4921. "HASLSTAT",
  4922. #endif /* HASLSTAT */
  4923. #if HASRANDOM
  4924. "HASRANDOM",
  4925. #endif /* HASRANDOM */
  4926. #if HASSETLOGIN
  4927. "HASSETLOGIN",
  4928. #endif /* HASSETLOGIN */
  4929. #if HASSETREUID
  4930. "HASSETREUID",
  4931. #endif /* HASSETREUID */
  4932. #if HASSETRLIMIT
  4933. "HASSETRLIMIT",
  4934. #endif /* HASSETRLIMIT */
  4935. #if HASSETSID
  4936. "HASSETSID",
  4937. #endif /* HASSETSID */
  4938. #if HASSETUSERCONTEXT
  4939. "HASSETUSERCONTEXT",
  4940. #endif /* HASSETUSERCONTEXT */
  4941. #if HASSETVBUF
  4942. "HASSETVBUF",
  4943. #endif /* HASSETVBUF */
  4944. #if HASSNPRINTF
  4945. "HASSNPRINTF",
  4946. #endif /* HASSNPRINTF */
  4947. #if HAS_ST_GEN
  4948. "HAS_ST_GEN",
  4949. #endif /* HAS_ST_GEN */
  4950. #if HASSRANDOMDEV
  4951. "HASSRANDOMDEV",
  4952. #endif /* HASSRANDOMDEV */
  4953. #if HASSTRERROR
  4954. "HASSTRERROR",
  4955. #endif /* HASSTRERROR */
  4956. #if HASULIMIT
  4957. "HASULIMIT",
  4958. #endif /* HASULIMIT */
  4959. #if HASUNAME
  4960. "HASUNAME",
  4961. #endif /* HASUNAME */
  4962. #if HASUNSETENV
  4963. "HASUNSETENV",
  4964. #endif /* HASUNSETENV */
  4965. #if HASWAITPID
  4966. "HASWAITPID",
  4967. #endif /* HASWAITPID */
  4968. #if IDENTPROTO
  4969. "IDENTPROTO",
  4970. #endif /* IDENTPROTO */
  4971. #if IP_SRCROUTE
  4972. "IP_SRCROUTE",
  4973. #endif /* IP_SRCROUTE */
  4974. #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
  4975. "LOCK_ON_OPEN",
  4976. #endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */
  4977. #if NEEDFSYNC
  4978. "NEEDFSYNC",
  4979. #endif /* NEEDFSYNC */
  4980. #if NOFTRUNCATE
  4981. "NOFTRUNCATE",
  4982. #endif /* NOFTRUNCATE */
  4983. #if RLIMIT_NEEDS_SYS_TIME_H
  4984. "RLIMIT_NEEDS_SYS_TIME_H",
  4985. #endif /* RLIMIT_NEEDS_SYS_TIME_H */
  4986. #if SAFENFSPATHCONF
  4987. "SAFENFSPATHCONF",
  4988. #endif /* SAFENFSPATHCONF */
  4989. #if SECUREWARE
  4990. "SECUREWARE",
  4991. #endif /* SECUREWARE */
  4992. #if SHARE_V1
  4993. "SHARE_V1",
  4994. #endif /* SHARE_V1 */
  4995. #if SIOCGIFCONF_IS_BROKEN
  4996. "SIOCGIFCONF_IS_BROKEN",
  4997. #endif /* SIOCGIFCONF_IS_BROKEN */
  4998. #if SIOCGIFNUM_IS_BROKEN
  4999. "SIOCGIFNUM_IS_BROKEN",
  5000. #endif /* SIOCGIFNUM_IS_BROKEN */
  5001. #if SYS5SETPGRP
  5002. "SYS5SETPGRP",
  5003. #endif /* SYS5SETPGRP */
  5004. #if SYSTEM5
  5005. "SYSTEM5",
  5006. #endif /* SYSTEM5 */
  5007. #if USE_SA_SIGACTION
  5008. "USE_SA_SIGACTION",
  5009. #endif /* USE_SA_SIGACTION */
  5010. #if USE_SIGLONGJMP
  5011. "USE_SIGLONGJMP",
  5012. #endif /* USE_SIGLONGJMP */
  5013. #if USESETEUID
  5014. "USESETEUID",
  5015. #endif /* USESETEUID */
  5016. NULL
  5017. };