sendmail.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. --- sendmail/conf.c.orig Tue Oct 16 11:24:13 2001
  2. +++ sendmail/conf.c Wed Oct 17 18:49:33 2001
  3. @@ -470,6 +470,12 @@
  4. ndbm_map_lookup, ndbm_map_store);
  5. #endif /* NDBM */
  6. +#if MYSQLMAP
  7. + MAPDEF("mysql", NULL, MCF_ALIASOK | MCF_NOTPERSIST,
  8. + mysql_map_parseargs, mysql_map_open, mysql_map_close,
  9. + mysql_map_lookup, null_map_store);
  10. +#endif
  11. +
  12. #if NIS
  13. MAPDEF("nis", NULL, MCF_ALIASOK,
  14. map_parseargs, nis_map_open, null_map_close,
  15. @@ -5381,6 +5387,9 @@
  16. #if NDBM
  17. "NDBM",
  18. #endif /* NDBM */
  19. +#if MYSQLMAP
  20. + "MYSQL",
  21. +#endif /* MYSQLMAP */
  22. #if NETINET
  23. "NETINET",
  24. #endif /* NETINET */
  25. --- sendmail/map.c.orig Tue Oct 16 11:22:26 2001
  26. +++ sendmail/map.c Thu Oct 18 09:34:53 2001
  27. @@ -1822,12 +1822,443 @@
  28. }
  29. #endif /* NDBM */
  30. -/*
  31. -** NEWDB (Hash and BTree) Modules
  32. +
  33. +
  34. +/*
  35. +* MySQL map class for Sendmail 8.12.x
  36. +*
  37. +* (c) 2001 Igmar Palsenberg
  38. +* JDI Media Solutions
  39. +*
  40. +* MySQL can be obtained from http://www.mysql.com
  41. +*
  42. +* This version is subject to the Sendmail license. Sendmail Inc. is NOT
  43. +* responsible for this code, they don't have anything to do with it, and
  44. +* don't support it.
  45. +*
  46. +* USE AT YOUR OWN RISK. NO WARRANTY OF ANY KIND IS PROVIDED. PLEASE
  47. +* READ THE INSTRUCTIONS FOR USE OF THIS PATCH BEFORE CONTACTING THE
  48. +* AUTHOR OR SENDMAIL, INC. NO SUPPORT OF ANY KIND WILL BE PROVIDED
  49. +* BY SENDMAIL, INC. FOR THIS PATCH.
  50. +*
  51. +* Please use the sendmail_mysql@jdimedia.nl adress for questions, comments,
  52. +* remarks, etc, not my personal address.
  53. +*
  54. +* See http://projects.jdimedia.nl for a HOWTO on installing / using it.
  55. +*
  56. +*/
  57. +#ifdef MYSQLMAP
  58. +#include <mysql/mysql.h>
  59. +
  60. +struct mysql_conn {
  61. + char * host;
  62. + char * user;
  63. + char * passwd;
  64. + char * db;
  65. + int port;
  66. +};
  67. +
  68. +static char * parse_opt_arg(char * in, char * option, char ** value)
  69. +{
  70. + int len = strlen(in);
  71. + char * tmp;
  72. +
  73. + /* Skip whitespaces */
  74. + while ((*in == ' ') || (*in == '\t') && (*in != '\0'))
  75. + in++;
  76. + if (*in == '\0')
  77. + return NULL;
  78. +
  79. + while ((*in != '-') && (*in != '"'))
  80. + in++;
  81. +
  82. + /* " is an error in this case */
  83. + if (*in == '"')
  84. + return NULL;
  85. +
  86. + in++;
  87. + *option = *in;
  88. + in++;
  89. +
  90. + while ((*in == ' ') || (*in == '\t'))
  91. + in++;
  92. +
  93. + /* Not a " is an error */
  94. + if (*in != '"')
  95. + return NULL;
  96. + in++;
  97. +
  98. + tmp = (char *) sm_malloc(sizeof(char) * len);
  99. + *value = tmp;
  100. +
  101. + while (*in != '"')
  102. + *tmp++ = *in++;
  103. +
  104. + /* Null terminate */
  105. + *tmp = '\0';
  106. + in++;
  107. +
  108. + return in;
  109. +}
  110. +
  111. +static char * parse_delim_arg(char * in, char delim, char ** key, char ** value)
  112. +{
  113. + int len = strlen(in);
  114. + char * tmp;
  115. +
  116. + while ((*in == ' ') || (*in == '\t') && (*in != '\0'))
  117. + in++;
  118. + if (*in == '\0')
  119. + return NULL;
  120. +
  121. + /* Key */
  122. + tmp = (char *) sm_malloc(sizeof(char) * len);
  123. +
  124. + *key = tmp;
  125. +
  126. + while ((*in != delim) && (*in != '\0') && (*in != ' ') && (*in != '\t'))
  127. + *tmp++ = *in++;
  128. +
  129. + if ((*in != delim) ) {
  130. + free(*key);
  131. + return NULL;
  132. + }
  133. + *tmp = '\0';
  134. + in++;
  135. +
  136. + /* Value */
  137. + tmp = (char *) sm_malloc(sizeof(char) * len);
  138. + *value = tmp;
  139. +
  140. + while ((*in != '\0') && (*in != ' ') && (*in != '\t'))
  141. + *tmp++ = *in++;
  142. + *tmp = '\0';
  143. +
  144. + return in;
  145. +}
  146. +
  147. +
  148. +/*
  149. +* Parse MYSQL map definitions. I call it an ugly hack :)
  150. +*
  151. +* return false if failed, true if succeeded
  152. +*
  153. +* Copied from the sendmail generic map_parseargs() code
  154. */
  155. +bool
  156. +mysql_map_parseargs(map, args)
  157. + MAP * map;
  158. + char * args;
  159. +{
  160. + char *p = args;
  161. + char option;
  162. + char * value;
  163. -#if NEWDB
  164. + map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
  165. + map->map_spacesub = SpaceSub; /* default value */
  166. + while (p)
  167. + {
  168. + p = parse_opt_arg(p, &option, &value);
  169. + if (!p)
  170. + break;
  171. + switch (option)
  172. + {
  173. + case 'N': /* Append NULL byte to all keys */
  174. + map->map_mflags |= MF_INCLNULL;
  175. + map->map_mflags &= ~MF_TRY0NULL;
  176. + break;
  177. +
  178. + case 'O': /* Adaptive versus never add NULL */
  179. + map->map_mflags &= ~MF_TRY1NULL;
  180. + break;
  181. +
  182. + case 'o': /* Database file is optional */
  183. + map->map_mflags |= MF_OPTIONAL;
  184. + break;
  185. +
  186. + case 'f': /* Don't fold keys to lowercase */
  187. + map->map_mflags |= MF_NOFOLDCASE;
  188. + break;
  189. +
  190. + case 'm': /* Supress replacement on match */
  191. + map->map_mflags |= MF_MATCHONLY;
  192. + break;
  193. +
  194. + case 'A': /* Append values for duplicate keys */
  195. + map->map_mflags |= MF_APPEND;
  196. + break;
  197. +
  198. + case 'q': /* Don't strip quotes */
  199. + map->map_mflags |= MF_KEEPQUOTES;
  200. + break;
  201. +
  202. + case 'a': /* Append tag on successful match */
  203. + map->map_app = value;
  204. + value = NULL;
  205. + break;
  206. +
  207. + case 'T': /* No idea */
  208. + map->map_tapp = value;
  209. + value = NULL;
  210. + break;
  211. +
  212. + case 'k': /* No idea */
  213. + map->map_keycolnm = value;
  214. + value = NULL;
  215. + break;
  216. +
  217. + case 'v': /* Specify the value's column */
  218. + map->map_valcolnm = value;
  219. + value = NULL;
  220. + break;
  221. +
  222. + case 'z': /* Column delimiter */
  223. + if (value[0] != '\\')
  224. + map->map_coldelim = value[0];
  225. + else
  226. + {
  227. + switch (value[1])
  228. + {
  229. + case 'n':
  230. + map->map_coldelim = '\n';
  231. + break;
  232. +
  233. + case 't':
  234. + map->map_coldelim = '\t';
  235. + break;
  236. +
  237. + default:
  238. + map->map_coldelim = '\\';
  239. + }
  240. + }
  241. + break;
  242. +
  243. + case 't': /* No idea */
  244. + map->map_mflags |= MF_NODEFER;
  245. + break;
  246. +
  247. +
  248. + case 'S': /* No idea */
  249. + map->map_spacesub = value[0];
  250. + break;
  251. + case 'D': /* No idea, I need updated docs :( */
  252. + map->map_mflags |= MF_DEFER;
  253. + break;
  254. +
  255. + case 'c':
  256. + map->map_keycolnm = value;
  257. + value = NULL;
  258. + break;
  259. +
  260. + case 's':
  261. + map->map_valcolnm = value;
  262. + value = NULL;
  263. + break;
  264. +
  265. + default:
  266. + syserr("mysql_map_parse_args : illegal option %c map `%s'", *p, map->map_mname);
  267. + break;
  268. + }
  269. + if (value)
  270. + sm_free(value);
  271. + }
  272. + if (map->map_keycolnm == NULL) {
  273. + syserr("mysql_map_parse_args : no connect string for MySQL map `%s'", map->map_mname);
  274. + return false;
  275. + }
  276. +
  277. + if (map->map_valcolnm == NULL) {
  278. + syserr("mysql_map_parse_args : no select statement for MySQL map `%s'", map->map_mname);
  279. + return false;
  280. + }
  281. +
  282. + return true;
  283. +}
  284. +
  285. +static bool
  286. +mysql_map_parse_connect(char * cs, struct mysql_conn * conn, MAP * map)
  287. +{
  288. + char * p;
  289. + char * key, * value;
  290. + char * endptr;
  291. +
  292. + p = cs;
  293. +
  294. + memset(conn, '\0', sizeof(struct mysql_conn));
  295. +
  296. + while (p) {
  297. + p = parse_delim_arg(p, '=', &key, &value);
  298. + if (!p)
  299. + continue;
  300. + if (strcmp(key, "host") == 0) {
  301. + conn->host = value;
  302. + } else if (strcmp(key, "user") == 0) {
  303. + conn->user = value;
  304. + } else if (strcmp(key, "passwd") == 0) {
  305. + conn->passwd = value;
  306. + } else if (strcmp(key, "db") == 0) {
  307. + conn->db = value;
  308. + } else if (strcmp(key, "port") == 0) {
  309. + conn->port = (int) strtoul(value, &endptr, 10);
  310. + if (*endptr != '\0')
  311. + conn->port = 0;
  312. + sm_free(value);
  313. + } else {
  314. + syserr("mysql_map_parse_connect : illegal MySQL option %s map `%s'", key, map->map_mname);
  315. + }
  316. + sm_free(key);
  317. + }
  318. +
  319. + if ((conn->host == NULL) || (conn->user == NULL) || (conn->passwd == NULL))
  320. + return false;
  321. +
  322. + return true;
  323. +}
  324. +
  325. +static void mysql_map_free_conn(struct mysql_conn * conn)
  326. +{
  327. + if (conn->host)
  328. + sm_free(conn->host);
  329. + if (conn->user)
  330. + sm_free(conn->user);
  331. + if (conn->passwd)
  332. + sm_free(conn->passwd);
  333. + if (conn->db)
  334. + sm_free(conn->db);
  335. +}
  336. +
  337. +/*
  338. +* Open connection to the MySQL server
  339. +*
  340. +* returns true if all where OK, false if something went wrong
  341. +*
  342. +*/
  343. +bool
  344. +mysql_map_open(map, mode)
  345. + MAP * map;
  346. + int mode;
  347. +{
  348. + MYSQL * mysql;
  349. + struct mysql_conn conn;
  350. +
  351. + /* Make sure newaliases doesn't rebuild it */
  352. + mode &= O_ACCMODE;
  353. +
  354. + if (mode != O_RDONLY) {
  355. + errno = EPERM;
  356. + return false;
  357. + }
  358. +
  359. + mysql = mysql_init(NULL);
  360. +
  361. + if (mysql_map_parse_connect(map->map_keycolnm, &conn, map) == false) {
  362. + syserr("mysql_map_open : cannot parse map arguments %s for map `%s'", map->map_keycolnm, map->map_mname);
  363. + mysql_map_free_conn(&conn);
  364. + return false;
  365. + }
  366. +
  367. + if (!mysql_real_connect(mysql, conn.host, conn.user, conn.passwd, conn.db, conn.port, NULL, 0)) {
  368. + mysql_map_free_conn(&conn);
  369. + syserr("mysql_map_open : cannot open a MySQL connection for map `%s' : %s", map->map_mname, mysql_error(mysql));
  370. + return false;
  371. + }
  372. + mysql_map_free_conn(&conn);
  373. + map->map_db1 = (ARBPTR_T) mysql;
  374. + map->map_pid = getpid();
  375. +
  376. + return true;
  377. +}
  378. +
  379. +/*
  380. +* Close connection to the MYSQL database
  381. +*
  382. +*
  383. +*/
  384. +void
  385. +mysql_map_close(map)
  386. + MAP * map;
  387. +{
  388. + if (map->map_pid == getpid())
  389. + mysql_close(map->map_db1);
  390. +}
  391. +
  392. +/*
  393. +*
  394. +* Do a map look up.
  395. +*
  396. +* Returns value that comes with the key
  397. +*
  398. +*/
  399. +char *
  400. +mysql_map_lookup(map, name, av, statp)
  401. + MAP * map;
  402. + char * name;
  403. + char ** av;
  404. + int * statp;
  405. +{
  406. + MYSQL * mysql = (MYSQL *) map->map_db1;
  407. + MYSQL_RES * result;
  408. + MYSQL_ROW row;
  409. + char * query;
  410. + char * tmp;
  411. + int len;
  412. +
  413. + len = strlen(name) + strlen(map->map_valcolnm) + 5;
  414. + if (len > MAXNAME)
  415. + return NULL;
  416. +
  417. + tmp = (char *) sm_malloc(strlen(name) + 1);
  418. + strncpy(tmp, name, strlen(name) + 1);
  419. +
  420. + if (!bitset(MF_NOFOLDCASE, map->map_mflags))
  421. + makelower(tmp);
  422. +
  423. + query = (char *) sm_malloc(sizeof(char) * len);
  424. + /* Create query */
  425. + snprintf(query, len, map->map_valcolnm, tmp);
  426. +
  427. + sm_free(tmp);
  428. +
  429. + /* Query and retreive rows */
  430. + if (mysql_real_query(mysql, query, strlen(query))) {
  431. + syserr("mysql_map_lookup : query %s : %s", query, mysql_error(mysql));
  432. + sm_free(query);
  433. + return NULL;
  434. + }
  435. +
  436. + result = mysql_store_result(mysql);
  437. + if (result == NULL) {
  438. + syserr("mysql_map_lookup : store result : %s", mysql_error(mysql));
  439. + sm_free(query);
  440. + return NULL;
  441. + }
  442. +
  443. + /* 0 rows == no result */
  444. + if (mysql_num_rows(result) == 0) {
  445. + sm_free(query);
  446. + return NULL;
  447. + }
  448. +
  449. + row = mysql_fetch_row(result);
  450. + if (row[0] == NULL || strlen(row[0]) == 0) {
  451. + sm_free(query);
  452. + mysql_free_result(result);
  453. + return NULL;
  454. + }
  455. +
  456. + if (bitset(MF_MATCHONLY, map->map_mflags))
  457. + return map_rewrite(map, name, strlen(name), NULL);
  458. + else
  459. + return map_rewrite(map, row[0], strlen(row[0]), av);
  460. +}
  461. +#endif /* MYSQLMAP */
  462. +
  463. +
  464. +/*
  465. +** NEWDB (Hash and BTree) Modules
  466. +*/
  467. +#if NEWDB
  468. /*
  469. ** BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
  470. **
  471. --- include/sm/conf.h.orig 2004-02-11 13:58:36.443953000 +0100
  472. +++ include/sm/conf.h 2004-02-11 15:15:07.077087000 +0100
  473. @@ -446,7 +446,7 @@
  474. # define HASURANDOMDEV 1 /* /dev/[u]random added in S9 */
  475. # endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */
  476. # if SOLARIS >= 21000 || (SOLARIS < 10000 && SOLARIS >= 210)
  477. -# define HASUNSETENV 1 /* unsetenv() added in S10 */
  478. +# define HASUNSETENV 0 /* unsetenv() added in S10 but not yet available in our S10beta */
  479. # endif /* SOLARIS >= 21000 || (SOLARIS < 10000 && SOLARIS >= 210) */
  480. # ifndef HASGETUSERSHELL
  481. # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */