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

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1992 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1992, 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 copyright[] =
  15. "@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.n
  16. All rights reserved.n
  17.      Copyright (c) 1992 Eric P. Allman.  All rights reserved.n
  18.      Copyright (c) 1992, 1993n
  19. The Regents of the University of California.  All rights reserved.n";
  20. #endif /* ! lint */
  21. #ifndef lint
  22. static char id[] = "@(#)$Id: makemap.c,v 8.129 1999/11/23 08:42:54 gshapiro Exp $";
  23. #endif /* ! lint */
  24. #include <sys/types.h>
  25. #ifndef ISC_UNIX
  26. # include <sys/file.h>
  27. #endif /* ! ISC_UNIX */
  28. #include <ctype.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #ifdef EX_OK
  32. # undef EX_OK /* unistd.h may have another use for this */
  33. #endif /* EX_OK */
  34. #include <sysexits.h>
  35. #include <sendmail/sendmail.h>
  36. #include <sendmail/pathnames.h>
  37. #include <libsmdb/smdb.h>
  38. uid_t RealUid;
  39. gid_t RealGid;
  40. char *RealUserName;
  41. uid_t RunAsUid;
  42. uid_t RunAsGid;
  43. char *RunAsUserName;
  44. int Verbose = 2;
  45. bool DontInitGroups = FALSE;
  46. uid_t TrustedUid = 0;
  47. BITMAP256 DontBlameSendmail;
  48. #define BUFSIZE 1024
  49. #if _FFR_DELIM
  50. # define ISSEP(c) ((sep == '' && isascii(c) && isspace(c)) || (c) == sep)
  51. #else /* _FFR_DELIM */
  52. # define ISSEP(c) (isascii(c) && isspace(c))
  53. #endif /* _FFR_DELIM */
  54. static void
  55. usage(progname)
  56. char *progname;
  57. {
  58. fprintf(stderr,
  59. "Usage: %s [-N] [-c cachesize] [-d] [-f] [-l] [-o] [-r] [-s] "
  60. #if _FFR_DELIM
  61. "[-t  delimiter] "
  62. #endif /* _FFR_DELIM */
  63. "[-u] [-v] type mapnamen",
  64. progname);
  65. exit(EX_USAGE);
  66. }
  67. int
  68. main(argc, argv)
  69. int argc;
  70. char **argv;
  71. {
  72. char *progname;
  73. char *cfile;
  74. bool inclnull = FALSE;
  75. bool notrunc = FALSE;
  76. bool allowreplace = FALSE;
  77. bool allowempty = FALSE;
  78. bool verbose = FALSE;
  79. bool foldcase = TRUE;
  80. bool unmake = FALSE;
  81. #if _FFR_DELIM
  82. char sep = '';
  83. #endif /* _FFR_DELIM */
  84. int exitstat;
  85. int opt;
  86. char *typename = NULL;
  87. char *mapname = NULL;
  88. int lineno;
  89. int st;
  90. int mode;
  91. int smode;
  92. int putflags = 0;
  93. int sff = SFF_ROOTOK|SFF_REGONLY;
  94. struct passwd *pw;
  95. SMDB_DATABASE *database;
  96. SMDB_CURSOR *cursor;
  97. SMDB_DBENT db_key, db_val;
  98. SMDB_DBPARAMS params;
  99. SMDB_USER_INFO user_info;
  100. char ibuf[BUFSIZE];
  101. #if HASFCHOWN
  102. FILE *cfp;
  103. char buf[MAXLINE];
  104. #endif /* HASFCHOWN */
  105. static char rnamebuf[MAXNAME]; /* holds RealUserName */
  106. extern char *optarg;
  107. extern int optind;
  108. memset(&params, '', sizeof params);
  109. params.smdbp_cache_size = 1024 * 1024;
  110. progname = strrchr(argv[0], '/');
  111. if (progname != NULL)
  112. progname++;
  113. else
  114. progname = argv[0];
  115. cfile = _PATH_SENDMAILCF;
  116. clrbitmap(DontBlameSendmail);
  117. RunAsUid = RealUid = getuid();
  118. RunAsGid = RealGid = getgid();
  119. pw = getpwuid(RealUid);
  120. if (pw != NULL)
  121. (void) strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
  122. else
  123. snprintf(rnamebuf, sizeof rnamebuf,
  124. "Unknown UID %d", (int) RealUid);
  125. RunAsUserName = RealUserName = rnamebuf;
  126. user_info.smdbu_id = RunAsUid;
  127. user_info.smdbu_group_id = RunAsGid;
  128. (void) strlcpy(user_info.smdbu_name, RunAsUserName,
  129.        SMDB_MAX_USER_NAME_LEN);
  130. #define OPTIONS "C:Nc:t:deflorsuv"
  131. while ((opt = getopt(argc, argv, OPTIONS)) != EOF)
  132. {
  133. switch (opt)
  134. {
  135.   case 'C':
  136. cfile = optarg;
  137. break;
  138.   case 'N':
  139. inclnull = TRUE;
  140. break;
  141.   case 'c':
  142. params.smdbp_cache_size = atol(optarg);
  143. break;
  144.   case 'd':
  145. params.smdbp_allow_dup = TRUE;
  146. break;
  147.   case 'e':
  148. allowempty = TRUE;
  149. break;
  150.   case 'f':
  151. foldcase = FALSE;
  152. break;
  153.   case 'l':
  154. smdb_print_available_types();
  155. exit(EX_OK);
  156. break;
  157.   case 'o':
  158. notrunc = TRUE;
  159. break;
  160.   case 'r':
  161. allowreplace = TRUE;
  162. break;
  163.   case 's':
  164. setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
  165. setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
  166. setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
  167. setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
  168. break;
  169. #if _FFR_DELIM
  170.   case 't':
  171. if (optarg == NULL || *optarg == '')
  172. {
  173. fprintf(stderr, "Invalid separatorn");
  174. break;
  175. }
  176. sep = *optarg;
  177. break;
  178. #endif /* _FFR_DELIM */
  179.   case 'u':
  180. unmake = TRUE;
  181. break;
  182.   case 'v':
  183. verbose = TRUE;
  184. break;
  185.   default:
  186. usage(progname);
  187. /* NOTREACHED */
  188. }
  189. }
  190. if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
  191. sff |= SFF_NOSLINK;
  192. if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
  193. sff |= SFF_NOHLINK;
  194. if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
  195. sff |= SFF_NOWLINK;
  196. argc -= optind;
  197. argv += optind;
  198. if (argc != 2)
  199. {
  200. usage(progname);
  201. /* NOTREACHED */
  202. }
  203. else
  204. {
  205. typename = argv[0];
  206. mapname = argv[1];
  207. }
  208. #if HASFCHOWN
  209. /* Find TrustedUser value in sendmail.cf */
  210. if ((cfp = fopen(cfile, "r")) == NULL)
  211. {
  212. fprintf(stderr, "makemap: %s: %s", cfile, errstring(errno));
  213. exit(EX_NOINPUT);
  214. }
  215. while (fgets(buf, sizeof(buf), cfp) != NULL)
  216. {
  217. register char *b;
  218. if ((b = strchr(buf, 'n')) != NULL)
  219. *b = '';
  220. b = buf;
  221. switch (*b++)
  222. {
  223.   case 'O': /* option */
  224. if (strncasecmp(b, " TrustedUser", 12) == 0 &&
  225.     !(isascii(b[12]) && isalnum(b[12])))
  226. {
  227. b = strchr(b, '=');
  228. if (b == NULL)
  229. continue;
  230. while (isascii(*++b) && isspace(*b))
  231. continue;
  232. if (isascii(*b) && isdigit(*b))
  233. TrustedUid = atoi(b);
  234. else
  235. {
  236. TrustedUid = 0;
  237. pw = getpwnam(b);
  238. if (pw == NULL)
  239. fprintf(stderr,
  240. "TrustedUser: unknown user %sn", b);
  241. else
  242. TrustedUid = pw->pw_uid;
  243. }
  244. # ifdef UID_MAX
  245. if (TrustedUid > UID_MAX)
  246. {
  247. fprintf(stderr,
  248. "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
  249. (long) TrustedUid,
  250. (long) UID_MAX);
  251. TrustedUid = 0;
  252. }
  253. # endif /* UID_MAX */
  254. break;
  255. }
  256.   default:
  257. continue;
  258. }
  259. }
  260. (void) fclose(cfp);
  261. #endif /* HASFCHOWN */
  262. if (!params.smdbp_allow_dup && !allowreplace)
  263. putflags = SMDBF_NO_OVERWRITE;
  264. if (!notrunc)
  265. sff |= SFF_CREAT;
  266. if (unmake)
  267. {
  268. mode = O_RDONLY;
  269. smode = S_IRUSR;
  270. }
  271. else
  272. {
  273. mode = O_RDWR;
  274. if (!notrunc)
  275. mode |= O_CREAT|O_TRUNC;
  276. smode = S_IWUSR;
  277. }
  278. params.smdbp_num_elements = 4096;
  279. errno = smdb_open_database(&database, mapname, mode, smode, sff,
  280.    typename, &user_info, &params);
  281. if (errno != SMDBE_OK)
  282. {
  283. char *hint;
  284. if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
  285.     (hint = smdb_db_definition(typename)) != NULL)
  286. fprintf(stderr,
  287. "%s: Need to recompile with -D%s for %s supportn",
  288. progname, hint, typename);
  289. else
  290. fprintf(stderr,
  291. "%s: error opening type %s map %s: %sn",
  292. progname, typename, mapname, errstring(errno));
  293. exit(EX_CANTCREAT);
  294. }
  295. (void) database->smdb_sync(database, 0);
  296. if (geteuid() == 0 && TrustedUid != 0)
  297. {
  298. errno = database->smdb_set_owner(database, TrustedUid, -1);
  299. if (errno != SMDBE_OK)
  300. {
  301. fprintf(stderr,
  302. "WARNING: ownership change on %s failed %s",
  303. mapname, errstring(errno));
  304. }
  305. }
  306. /*
  307. **  Copy the data
  308. */
  309. exitstat = EX_OK;
  310. if (unmake)
  311. {
  312. bool stop;
  313. errno = database->smdb_cursor(database, &cursor, 0);
  314. if (errno != SMDBE_OK)
  315. {
  316. fprintf(stderr,
  317. "%s: cannot make cursor for type %s map %sn",
  318. progname, typename, mapname);
  319. exit(EX_SOFTWARE);
  320. }
  321. memset(&db_key, '', sizeof db_key);
  322. memset(&db_val, '', sizeof db_val);
  323. for (stop = FALSE, lineno = 0; !stop; lineno++)
  324. {
  325. errno = cursor->smdbc_get(cursor, &db_key, &db_val,
  326.   SMDB_CURSOR_GET_NEXT);
  327. if (errno != SMDBE_OK)
  328. {
  329. stop = TRUE;
  330. }
  331. if (!stop)
  332. printf("%.*st%.*sn",
  333.        (int) db_key.data.size,
  334.        (char *) db_key.data.data,
  335.        (int) db_val.data.size,
  336.        (char *)db_val.data.data);
  337. }
  338. (void) cursor->smdbc_close(cursor);
  339. }
  340. else
  341. {
  342. lineno = 0;
  343. while (fgets(ibuf, sizeof ibuf, stdin) != NULL)
  344. {
  345. register char *p;
  346. lineno++;
  347. /*
  348. **  Parse the line.
  349. */
  350. p = strchr(ibuf, 'n');
  351. if (p != NULL)
  352. *p = '';
  353. else if (!feof(stdin))
  354. {
  355. fprintf(stderr,
  356. "%s: %s: line %d: line too long (%ld bytes max)n",
  357. progname, mapname, lineno, (long) sizeof ibuf);
  358. exitstat = EX_DATAERR;
  359. continue;
  360. }
  361. if (ibuf[0] == '' || ibuf[0] == '#')
  362. continue;
  363. if (
  364. #if _FFR_DELIM
  365.     sep == '' &&
  366. #endif /* _FFR_DELIM */
  367.     isascii(ibuf[0]) && isspace(ibuf[0]))
  368. {
  369. fprintf(stderr,
  370. "%s: %s: line %d: syntax error (leading space)n",
  371. progname, mapname, lineno);
  372. exitstat = EX_DATAERR;
  373. continue;
  374. }
  375. memset(&db_key, '', sizeof db_key);
  376. memset(&db_val, '', sizeof db_val);
  377. db_key.data.data = ibuf;
  378. for (p = ibuf; *p != '' && !(ISSEP(*p)); p++)
  379. {
  380. if (foldcase && isascii(*p) && isupper(*p))
  381. *p = tolower(*p);
  382. }
  383. db_key.data.size = p - ibuf;
  384. if (inclnull)
  385. db_key.data.size++;
  386. if (*p != '')
  387. *p++ = '';
  388. while (ISSEP(*p))
  389. p++;
  390. if (!allowempty && *p == '')
  391. {
  392. fprintf(stderr,
  393. "%s: %s: line %d: no RHS for LHS %sn",
  394. progname, mapname, lineno,
  395. (char *) db_key.data.data);
  396. exitstat = EX_DATAERR;
  397. continue;
  398. }
  399. db_val.data.data = p;
  400. db_val.data.size = strlen(p);
  401. if (inclnull)
  402. db_val.data.size++;
  403. /*
  404. **  Do the database insert.
  405. */
  406. if (verbose)
  407. {
  408. printf("key=`%s', val=`%s'n",
  409.        (char *) db_key.data.data,
  410.        (char *) db_val.data.data);
  411. }
  412. errno = database->smdb_put(database, &db_key, &db_val,
  413.    putflags);
  414. switch (errno)
  415. {
  416.   case SMDBE_KEY_EXIST:
  417. st = 1;
  418. break;
  419.   case 0:
  420. st = 0;
  421. break;
  422.   default:
  423. st = -1;
  424. break;
  425. }
  426. if (st < 0)
  427. {
  428. fprintf(stderr,
  429. "%s: %s: line %d: key %s: put error: %sn",
  430. progname, mapname, lineno,
  431. (char *) db_key.data.data,
  432. errstring(errno));
  433. exitstat = EX_IOERR;
  434. }
  435. else if (st > 0)
  436. {
  437. fprintf(stderr,
  438. "%s: %s: line %d: key %s: duplicate keyn",
  439. progname, mapname,
  440. lineno, (char *) db_key.data.data);
  441. exitstat = EX_DATAERR;
  442. }
  443. }
  444. }
  445. /*
  446. **  Now close the database.
  447. */
  448. errno = database->smdb_close(database);
  449. if (errno != SMDBE_OK)
  450. {
  451. fprintf(stderr, "%s: close(%s): %sn",
  452. progname, mapname, errstring(errno));
  453. exitstat = EX_IOERR;
  454. }
  455. smdb_free_database(database);
  456. exit(exitstat);
  457. /* NOTREACHED */
  458. return exitstat;
  459. }
  460. /*VARARGS1*/
  461. void
  462. #ifdef __STDC__
  463. message(const char *msg, ...)
  464. #else /* __STDC__ */
  465. message(msg, va_alist)
  466. const char *msg;
  467. va_dcl
  468. #endif /* __STDC__ */
  469. {
  470. const char *m;
  471. VA_LOCAL_DECL
  472. m = msg;
  473. if (isascii(m[0]) && isdigit(m[0]) &&
  474.     isascii(m[1]) && isdigit(m[1]) &&
  475.     isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
  476. m += 4;
  477. VA_START(msg);
  478. (void) vfprintf(stderr, m, ap);
  479. VA_END;
  480. (void) fprintf(stderr, "n");
  481. }
  482. /*VARARGS1*/
  483. void
  484. #ifdef __STDC__
  485. syserr(const char *msg, ...)
  486. #else /* __STDC__ */
  487. syserr(msg, va_alist)
  488. const char *msg;
  489. va_dcl
  490. #endif /* __STDC__ */
  491. {
  492. const char *m;
  493. VA_LOCAL_DECL
  494. m = msg;
  495. if (isascii(m[0]) && isdigit(m[0]) &&
  496.     isascii(m[1]) && isdigit(m[1]) &&
  497.     isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
  498. m += 4;
  499. VA_START(msg);
  500. (void) vfprintf(stderr, m, ap);
  501. VA_END;
  502. (void) fprintf(stderr, "n");
  503. }