agent.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: agent.c /main/2 1998/03/16 14:42:16 mgreess $ */
  24. /*
  25. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  26. * (c) Copyright 1993, 1994 International Business Machines Corp.
  27. * (c) Copyright 1993, 1994 Novell, Inc.
  28. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  29. */
  30. #include <EUSCompat.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <unistd.h>
  34. #include <signal.h>
  35. #include <rpc/rpc.h>
  36. #if !defined(__linux__) && !defined(CSRG_BASED)
  37. # include <poll.h>
  38. #endif
  39. #if defined(SunOS)
  40. #include <netconfig.h>
  41. #include <netdir.h>
  42. #else
  43. #include <sys/signal.h>
  44. #include <sys/socket.h>
  45. #include <sys/errno.h>
  46. #endif /* SunOS */
  47. #include <X11/Intrinsic.h>
  48. #include "agent.h"
  49. #include "cmcb.h"
  50. #include "entry.h"
  51. #include "debug.h"
  52. #include "iso8601.h"
  53. #include "free.h"
  54. #include "misc.h"
  55. /*
  56. * callback info
  57. * - contain update information from backend
  58. */
  59. typedef struct cb_info {
  60. int vers;
  61. char *cal;
  62. char *user;
  63. int reason;
  64. void *data;
  65. struct cb_info *next;
  66. } _CallbackInfo;
  67. static _CallbackInfo *cb_head = NULL, *cb_tail = NULL;
  68. u_long _DtCm_transient = 0;
  69. static u_long prognum = 0x40000000;
  70. static int mapped = 0;
  71. /******************************************************************************
  72. * forward declaration of static functions used within the file
  73. ******************************************************************************/
  74. #if defined(SunOS)
  75. static u_long gettransient (u_long version);
  76. #else
  77. static u_long gettransient (int proto, u_long vers, int *sockp);
  78. #endif
  79. static void _DtCm_handle_callback();
  80. static CSA_return_code _ConvertCallbackData(cmcb_update_callback_args *args,
  81. _CallbackInfo **cbi);
  82. static CSA_return_code _CopyAttributeNames(uint fnum, char **fnames,
  83. CSA_uint32 *tnum, char ***tnames);
  84. static boolean_t _ProcessV1Callback(_CallbackInfo *ptr);
  85. static boolean_t _ProcessV2Callback(_CallbackInfo *ptr);
  86. static void _FreeCallbackInfo(_CallbackInfo *ptr);
  87. /*****************************************************************************
  88. * extern functions used in the library
  89. *****************************************************************************/
  90. /*
  91. * Register rpc service for server callback
  92. */
  93. extern void
  94. _DtCm_init_agent(void)
  95. {
  96. int s = RPC_ANYSOCK;
  97. #if defined(SunOS) && SunOS < 55
  98. extern boolean_t rpc_reg(const u_long, const u_long, const u_long,
  99. const char *(*)(), const xdrproc_t, const xdrproc_t,
  100. const char *);
  101. #endif
  102. #if defined(SunOS)
  103. extern void (*sigset(int, void (*)(int)))(int);
  104. #else
  105. extern void (*sigset())();
  106. #endif
  107. /* locking candidate for MT-safe purpose */
  108. if (mapped == 1)
  109. return;
  110. DP(("libdtcm: _DtCm_init_agent\n"));
  111. #if defined(SunOS)
  112. (void)rpcb_unset(_DtCm_transient, AGENTVERS, NULL);
  113. if ((_DtCm_transient = gettransient((u_long)1)) == 0) {
  114. _DtCm_print_errmsg("Cannot get transient program number\n");
  115. _DtCm_print_errmsg("Callback cannot be enabled.\n");
  116. return;
  117. }
  118. /* register v1 callback */
  119. if (rpc_reg(_DtCm_transient, AGENTVERS, update_callback,
  120. (const char *(*)())_DtCm_update_callback_1, _DtCm_xdr_Table_Res_4,
  121. _DtCm_xdr_Update_Status, "udp") == -1) {
  122. _DtCm_print_errmsg("Cannot register v1 callback handler\n");
  123. _DtCm_print_errmsg("Callback cannot be enabled.\n");
  124. }
  125. /* register v2 callback */
  126. if (rpc_reg(_DtCm_transient, AGENTVERS_2, CMCB_UPDATE_CALLBACK,
  127. (const char *(*)())cmcb_update_callback_2_svc,
  128. xdr_cmcb_update_callback_args, xdr_void, "udp") == -1) {
  129. _DtCm_print_errmsg("Cannot register v2 callback handler\n");
  130. _DtCm_print_errmsg("Callback cannot be enabled.\n");
  131. }
  132. #else
  133. (void)pmap_unset(_DtCm_transient, AGENTVERS);
  134. if ((_DtCm_transient = gettransient(IPPROTO_UDP,(u_long)1, &s)) == 0) {
  135. _DtCm_print_errmsg("Cannot get transient program number\n");
  136. _DtCm_print_errmsg("Callback cannot be enabled.\n");
  137. return;
  138. }
  139. if (registerrpc(_DtCm_transient, AGENTVERS, update_callback,
  140. (char *(*)())_DtCm_update_callback_1, (xdrproc_t)_DtCm_xdr_Table_Res_4,
  141. (xdrproc_t)_DtCm_xdr_Update_Status) == -1) {
  142. _DtCm_print_errmsg("Cannot register v1 callback handler\n");
  143. _DtCm_print_errmsg("Callback cannot be enabled.\n");
  144. }
  145. if (registerrpc(_DtCm_transient, AGENTVERS_2, CMCB_UPDATE_CALLBACK,
  146. (char *(*)())cmcb_update_callback_2_svc,
  147. (xdrproc_t)xdr_cmcb_update_callback_args, (xdrproc_t)xdr_void) == -1) {
  148. _DtCm_print_errmsg("Cannot register v2 callback handler\n");
  149. _DtCm_print_errmsg("Callback cannot be enabled.\n");
  150. }
  151. #endif /* SunOS */
  152. /* locking candidate for MT-safe purpose */
  153. mapped = 1;
  154. }
  155. /*
  156. * Unregister with the rpc service.
  157. */
  158. extern void
  159. _DtCm_destroy_agent(void)
  160. {
  161. if (mapped == 0)
  162. return;
  163. DP(("libdtcm: _DtCm_destroy_agent\n"));
  164. #if defined(SunOS)
  165. (void) rpcb_unset(_DtCm_transient, AGENTVERS, NULL);
  166. (void) rpcb_unset(_DtCm_transient, AGENTVERS_2, NULL);
  167. #else
  168. (void) pmap_unset(_DtCm_transient, AGENTVERS);
  169. (void) pmap_unset(_DtCm_transient, AGENTVERS_2);
  170. #endif /* SunOS */
  171. /* locking candidate for MT-safe purpose */
  172. mapped = 0;
  173. }
  174. extern void
  175. _DtCm_process_updates(void)
  176. {
  177. #if defined(CSRG_BASED) || defined(__linux__)
  178. int i, nfd;
  179. fd_set rpc_bits;
  180. while (B_TRUE) {
  181. rpc_bits = svc_fdset;
  182. nfd = select(FD_SETSIZE, &rpc_bits, NULL, NULL, NULL);
  183. if (nfd <= 0)
  184. /* done */
  185. return;
  186. for (i = 0; i < FD_SETSIZE; i++) {
  187. if (FD_ISSET(i, &rpc_bits)) {
  188. svc_getreqset(&rpc_bits);
  189. break;
  190. }
  191. }
  192. }
  193. #else
  194. int i, j, nfd;
  195. fd_set rpc_bits;
  196. fd_mask fmask, *inbits;
  197. struct pollfd pfd[FD_SETSIZE];
  198. struct pollfd *p;
  199. int last;
  200. int do_rpc;
  201. while (B_TRUE) {
  202. rpc_bits = svc_fdset;
  203. /* convert to pollfd structure */
  204. inbits = rpc_bits.fds_bits;
  205. p = pfd;
  206. for (i = 0; i < FD_SETSIZE; i += NFDBITS) {
  207. fmask = *inbits;
  208. for (j = 0; fmask != 0 ; j++, fmask >>= 1) {
  209. if (fmask & 0x1) {
  210. p->fd = i + j;
  211. if (p->fd >= FD_SETSIZE)
  212. break;
  213. p->events = POLLIN;
  214. p++;
  215. }
  216. }
  217. inbits++;
  218. }
  219. /* poll and return right away */
  220. i = p - pfd;
  221. nfd = poll(pfd, i, 0);
  222. if (nfd <= 0)
  223. /* done */
  224. return;
  225. /* if set, handle rpc calls */
  226. /* convert back to fd_set structure */
  227. last = -1;
  228. do_rpc = 0;
  229. FD_ZERO(&rpc_bits);
  230. for (p = pfd; i-- > 0; p++) {
  231. j = p->fd / NFDBITS;
  232. if (j != last) {
  233. inbits = &rpc_bits.fds_bits[j];
  234. last = j;
  235. }
  236. if (p->revents & POLLIN) {
  237. *inbits |= (1 << (p->fd % NFDBITS));
  238. do_rpc = 1;
  239. }
  240. }
  241. if (do_rpc)
  242. svc_getreqset(&rpc_bits);
  243. }
  244. #endif /* CSRG_BASED || linux */
  245. }
  246. /*
  247. * The server calls this routine when an update event occurs;
  248. * It's job is to notify CM asynchronously that an
  249. * update has occurred. It has to do it this
  250. * way (i.e. raise a signal) because the client
  251. * can't make an rpc call until this procedure call has
  252. * returned to the server.
  253. */
  254. Update_Status *
  255. _DtCm_update_callback_1(Table_Res_4 *t, _DtCm_Connection *conn)
  256. {
  257. static Update_Status status = update_succeeded;
  258. _CallbackInfo *cbi;
  259. DP(("agent.c: _DtCm_update_callback_1()\n"));
  260. /*
  261. * no point to save data for version 4 and before
  262. * since the info from old backends does not contain
  263. * calendar info
  264. * so we just invoke all registered callback with no data
  265. */
  266. if (cbi = (_CallbackInfo *)calloc(1, sizeof(_CallbackInfo))) {
  267. cbi->vers = AGENTVERS;
  268. if (cb_tail == NULL)
  269. cb_head = cbi;
  270. else
  271. cb_tail->next = cbi;
  272. cb_tail = cbi;
  273. }
  274. /* handle callback from backend */
  275. _DtCm_handle_callback();
  276. return (&status);
  277. }
  278. /*
  279. * Handler for v2 callback protocol
  280. */
  281. void *
  282. cmcb_update_callback_2_svc(cmcb_update_callback_args *args, struct svc_req *d)
  283. {
  284. _CallbackInfo *cbi;
  285. DP(("agent.c: cmcb_update_callback_2_svc()\n"));
  286. if (args == NULL)
  287. return (NULL);
  288. if (_ConvertCallbackData(args, &cbi) == CSA_SUCCESS) {
  289. cbi->vers = AGENTVERS_2;
  290. if (cb_tail == NULL)
  291. cb_head = cbi;
  292. else
  293. cb_tail->next = cbi;
  294. cb_tail = cbi;
  295. /* handle callback from backend */
  296. _DtCm_handle_callback();
  297. }
  298. return (NULL);
  299. }
  300. /******************************************************************************
  301. * static functions used within in the file
  302. ******************************************************************************/
  303. /*
  304. * get transient program number for callbacks.
  305. */
  306. #if defined(SunOS)
  307. static u_long
  308. gettransient (u_long version)
  309. {
  310. int stat;
  311. struct nd_hostserv host = {HOST_SELF, "rpcbind"};
  312. struct nd_addrlist *addrp;
  313. struct netbuf *addr;
  314. struct netconfig *netconf;
  315. netconf = getnetconfigent("udp");
  316. if (!netconf) {
  317. DP(("(gettransient) getnetconfigent(udp) failed\n"));
  318. freenetconfigent(netconf);
  319. return 0;
  320. }
  321. stat = netdir_getbyname(netconf, &host, &addrp);
  322. if (stat) {
  323. DP(("(gettransient) netdir_getbyname failed\n"));
  324. netdir_free(addrp, ND_ADDRLIST);
  325. freenetconfigent(netconf);
  326. return 0;
  327. }
  328. if (addrp->n_cnt < 1) {
  329. DP(("(gettransient) netdir_getbyname - zero addresses\n"));
  330. netdir_free(addrp, ND_ADDRLIST);
  331. freenetconfigent(netconf);
  332. return 0;
  333. }
  334. addr = addrp->n_addrs;
  335. while (!rpcb_set(prognum++, version, netconf, addr))
  336. continue;
  337. netdir_free(addrp, ND_ADDRLIST);
  338. freenetconfigent(netconf);
  339. prognum--;
  340. return prognum;
  341. }
  342. #else /* SunOS */
  343. static u_long
  344. gettransient (int proto, u_long vers, int *sockp)
  345. {
  346. unsigned int len;
  347. int s, socktype;
  348. struct sockaddr_in addr;
  349. switch (proto) {
  350. case IPPROTO_UDP:
  351. socktype = SOCK_DGRAM;
  352. break;
  353. case IPPROTO_TCP:
  354. socktype = SOCK_STREAM;
  355. break;
  356. default:
  357. DP(("unknown protocol type\n"));
  358. return 0;
  359. }
  360. if (*sockp == RPC_ANYSOCK) {
  361. if ((s = socket(AF_INET, socktype, 0)) < 0) {
  362. perror("socket");
  363. return 0;
  364. }
  365. *sockp = s;
  366. } else
  367. s = *sockp;
  368. addr.sin_addr.s_addr = 0;
  369. addr.sin_family = AF_INET;
  370. addr.sin_port = 0;
  371. len = sizeof(addr);
  372. if (bind(s, (struct sockaddr *)&addr, len) != 0) {
  373. perror("bind");
  374. return 0;
  375. }
  376. if (getsockname(s, (struct sockaddr *)&addr, &len) < 0) {
  377. perror("getsockname");
  378. return 0;
  379. }
  380. while (!pmap_set(prognum++, vers, proto, ntohs(addr.sin_port)))
  381. continue;
  382. return (prognum-1);
  383. }
  384. #endif /* not SunOS */
  385. static void
  386. _DtCm_handle_callback(void)
  387. {
  388. _CallbackInfo *ptr, *prev;
  389. boolean_t keep = B_FALSE;
  390. DP(("agent.c: _DtCm_handle_callback()\n"));
  391. for (ptr = cb_head, prev = NULL; ptr != NULL; ) {
  392. /* we only handle version 1 and version 2 */
  393. if (ptr->vers == AGENTVERS)
  394. keep = _ProcessV1Callback(ptr);
  395. else
  396. keep = _ProcessV2Callback(ptr);
  397. if (!keep) {
  398. if (prev == NULL)
  399. cb_head = ptr->next;
  400. else
  401. prev->next = ptr->next;
  402. _FreeCallbackInfo(ptr);
  403. ptr = NULL; /* freed by _FreeCallbackInfo() */
  404. } else {
  405. prev = ptr;
  406. }
  407. if (ptr)
  408. ptr = ptr->next;
  409. }
  410. cb_tail = prev;
  411. }
  412. static CSA_return_code
  413. _ConvertCallbackData(cmcb_update_callback_args *args, _CallbackInfo **cbi)
  414. {
  415. _CallbackInfo *ncbi;
  416. CSA_calendar_user *user;
  417. CSA_logon_callback_data *ldata;
  418. CSA_calendar_deleted_callback_data *rdata;
  419. CSA_calendar_attr_update_callback_data *cdata;
  420. CSA_add_entry_callback_data *adata;
  421. CSA_delete_entry_callback_data *ddata;
  422. CSA_update_entry_callback_data *udata;
  423. char timebuf[BUFSIZ];
  424. if ((ncbi = (_CallbackInfo *)calloc(1, sizeof(_CallbackInfo))) == NULL)
  425. return (CSA_E_INSUFFICIENT_MEMORY);
  426. if (args->calendar && (ncbi->cal = strdup(args->calendar)) == NULL) {
  427. free(ncbi);
  428. return (CSA_E_INSUFFICIENT_MEMORY);
  429. }
  430. if (args->user && (ncbi->user = strdup(args->user)) == NULL) {
  431. _FreeCallbackInfo(ncbi);
  432. return (CSA_E_INSUFFICIENT_MEMORY);
  433. }
  434. if ((user = (CSA_calendar_user *)calloc(1, sizeof(CSA_calendar_user)))
  435. == NULL) {
  436. _FreeCallbackInfo(ncbi);
  437. return (CSA_E_INSUFFICIENT_MEMORY);
  438. } else
  439. user->user_name = ncbi->user;
  440. ncbi->reason = args->data.reason;
  441. switch (ncbi->reason) {
  442. case CSA_CB_CALENDAR_LOGON:
  443. if ((ldata = (CSA_logon_callback_data *)calloc(1,
  444. sizeof(CSA_logon_callback_data))) == NULL) {
  445. free(user);
  446. _FreeCallbackInfo(ncbi);
  447. return (CSA_E_INSUFFICIENT_MEMORY);
  448. }
  449. ldata->user = user;
  450. ncbi->data = (void *)ldata;
  451. break;
  452. case CSA_CB_CALENDAR_DELETED:
  453. if ((rdata = (CSA_calendar_deleted_callback_data *)calloc(1,
  454. sizeof(CSA_calendar_deleted_callback_data))) == NULL) {
  455. free(user);
  456. _FreeCallbackInfo(ncbi);
  457. return (CSA_E_INSUFFICIENT_MEMORY);
  458. }
  459. rdata->user = user;
  460. ncbi->data = (void *)rdata;
  461. break;
  462. case CSA_CB_CALENDAR_ATTRIBUTE_UPDATED:
  463. if ((cdata = (CSA_calendar_attr_update_callback_data *)
  464. calloc(1, sizeof(
  465. CSA_calendar_attr_update_callback_data))) == NULL) {
  466. free(user);
  467. _FreeCallbackInfo(ncbi);
  468. return (CSA_E_INSUFFICIENT_MEMORY);
  469. }
  470. cdata->user = user;
  471. ncbi->data = (void *)cdata;
  472. if (_CopyAttributeNames(args->data.data.cdata->num_names,
  473. args->data.data.cdata->names, &cdata->number_attributes,
  474. &cdata->attribute_names)) {
  475. _FreeCallbackInfo(ncbi);
  476. return (CSA_E_INSUFFICIENT_MEMORY);
  477. }
  478. break;
  479. case CSA_CB_ENTRY_ADDED:
  480. if ((adata = (CSA_add_entry_callback_data *)calloc(1,
  481. sizeof(CSA_add_entry_callback_data))) == NULL) {
  482. free(user);
  483. _FreeCallbackInfo(ncbi);
  484. return (CSA_E_INSUFFICIENT_MEMORY);
  485. }
  486. adata->user = user;
  487. ncbi->data = (void *)adata;
  488. if (args->data.data.adata->id && (adata->added_entry_id.data =
  489. (unsigned char *)strdup(args->data.data.adata->id))
  490. == NULL) {
  491. _FreeCallbackInfo(ncbi);
  492. return (CSA_E_INSUFFICIENT_MEMORY);
  493. } else
  494. adata->added_entry_id.size =
  495. strlen((char *)adata->added_entry_id.data);
  496. break;
  497. case CSA_CB_ENTRY_DELETED:
  498. if ((ddata = (CSA_delete_entry_callback_data *)calloc(1,
  499. sizeof(CSA_delete_entry_callback_data))) == NULL) {
  500. free(user);
  501. _FreeCallbackInfo(ncbi);
  502. return (CSA_E_INSUFFICIENT_MEMORY);
  503. }
  504. ddata->user = user;
  505. ncbi->data = (void *)ddata;
  506. if (args->data.data.ddata->id && (ddata->deleted_entry_id.data =
  507. (unsigned char *)strdup(args->data.data.ddata->id))
  508. == NULL) {
  509. _FreeCallbackInfo(ncbi);
  510. return (CSA_E_INSUFFICIENT_MEMORY);
  511. } else
  512. ddata->deleted_entry_id.size =
  513. strlen((char *)ddata->deleted_entry_id.data);
  514. _csa_tick_to_iso8601(args->data.data.ddata->time, timebuf);
  515. if ((ddata->date_and_time = strdup(timebuf)) == NULL) {
  516. _FreeCallbackInfo(ncbi);
  517. return (CSA_E_INSUFFICIENT_MEMORY);
  518. }
  519. ddata->scope = args->data.data.ddata->scope;
  520. break;
  521. case CSA_CB_ENTRY_UPDATED:
  522. if ((udata = (CSA_update_entry_callback_data *)calloc(1,
  523. sizeof(CSA_update_entry_callback_data))) == NULL) {
  524. free(user);
  525. _FreeCallbackInfo(ncbi);
  526. return (CSA_E_INSUFFICIENT_MEMORY);
  527. }
  528. udata->user = user;
  529. ncbi->data = (void *)udata;
  530. if (args->data.data.udata->newid && (udata->new_entry_id.data =
  531. (unsigned char *)strdup(args->data.data.udata->newid))
  532. == NULL) {
  533. _FreeCallbackInfo(ncbi);
  534. return (CSA_E_INSUFFICIENT_MEMORY);
  535. } else
  536. udata->new_entry_id.size =
  537. strlen((char *)udata->new_entry_id.data);
  538. if (args->data.data.udata->oldid && (udata->old_entry_id.data =
  539. (unsigned char *)strdup(args->data.data.udata->oldid))
  540. == NULL) {
  541. _FreeCallbackInfo(ncbi);
  542. return (CSA_E_INSUFFICIENT_MEMORY);
  543. } else
  544. udata->old_entry_id.size =
  545. strlen((char *)udata->old_entry_id.data);
  546. _csa_tick_to_iso8601(args->data.data.udata->time, timebuf);
  547. if ((udata->date_and_time = strdup(timebuf)) == NULL) {
  548. _FreeCallbackInfo(ncbi);
  549. return (CSA_E_INSUFFICIENT_MEMORY);
  550. }
  551. udata->scope = args->data.data.udata->scope;
  552. break;
  553. }
  554. *cbi = ncbi;
  555. return (CSA_SUCCESS);
  556. }
  557. static CSA_return_code
  558. _CopyAttributeNames(uint fnum, char **fnames, CSA_uint32 *tnum, char ***tnames)
  559. {
  560. int i;
  561. char **nnames;
  562. if (fnum == 0) {
  563. *tnum = 0;
  564. *tnames = NULL;
  565. return (CSA_SUCCESS);
  566. }
  567. if ((nnames = calloc(1, sizeof(char *) * fnum)) == NULL)
  568. return (CSA_E_INSUFFICIENT_MEMORY);
  569. for (i = 0; i < fnum; i++) {
  570. if ((nnames[i] = strdup(fnames[i])) == NULL)
  571. break;
  572. }
  573. if (i == fnum) {
  574. *tnum = i;
  575. *tnames = nnames;
  576. return (CSA_SUCCESS);
  577. } else {
  578. _DtCm_free_character_pointers(i, nnames);
  579. free(nnames);
  580. return (CSA_E_INSUFFICIENT_MEMORY);
  581. }
  582. }
  583. /*
  584. * pre callback protocol V2, there is no distinction
  585. * between different reasons, and no data passed. So
  586. * there's only one possible thing to do, and that's
  587. * run all the callbacks.
  588. */
  589. static boolean_t
  590. _ProcessV1Callback(_CallbackInfo *ptr)
  591. {
  592. Calendar *cal;
  593. _DtCmCallbackEntry *cb;
  594. boolean_t keep = B_FALSE;
  595. for (cal = _DtCm_active_cal_list; cal != NULL; cal = cal->next) {
  596. if (cal->rpc_version >= _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
  597. continue;
  598. if (cal->do_reasons &
  599. (CSA_CB_ENTRY_ADDED | CSA_CB_ENTRY_DELETED |
  600. CSA_CB_ENTRY_UPDATED))
  601. {
  602. /* only do dumb processing if it was a V4 server */
  603. for (cb = cal->cb_list; cb != NULL; cb = cb->next) {
  604. if (cal->do_reasons & cb->reason) {
  605. cb->handler((CSA_session_handle)cal,
  606. cal->do_reasons & cb->reason,
  607. (CSA_buffer) NULL,
  608. cb->client_data,
  609. (CSA_extension*) NULL);
  610. }
  611. }
  612. } else if (cal->all_reasons & (CSA_CB_ENTRY_ADDED |
  613. CSA_CB_ENTRY_DELETED | CSA_CB_ENTRY_UPDATED))
  614. keep = B_TRUE;
  615. }
  616. return (keep);
  617. }
  618. static boolean_t
  619. _ProcessV2Callback(_CallbackInfo *ptr)
  620. {
  621. Calendar *cal;
  622. _DtCmCallbackEntry *cb;
  623. boolean_t keep = B_FALSE;
  624. for (cal = _DtCm_active_cal_list; cal != NULL; cal = cal->next) {
  625. if (cal->rpc_version < _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION ||
  626. strcmp(ptr->cal, cal->name))
  627. continue;
  628. if (cal->do_reasons & ptr->reason) {
  629. /* only do dumb processing if it was a V4 server */
  630. for (cb = cal->cb_list; cb != NULL; cb = cb->next) {
  631. if (ptr->reason & cb->reason) {
  632. cb->handler((CSA_session_handle)cal,
  633. ptr->reason,
  634. (CSA_buffer)ptr->data,
  635. cb->client_data,
  636. (CSA_extension*) NULL);
  637. }
  638. }
  639. } else if (cal->all_reasons & ptr->reason)
  640. keep = B_TRUE;
  641. }
  642. return (keep);
  643. }
  644. static void
  645. _FreeCallbackInfo(_CallbackInfo *ptr)
  646. {
  647. CSA_logon_callback_data *ldata;
  648. CSA_calendar_deleted_callback_data *rdata;
  649. CSA_calendar_attr_update_callback_data *cdata;
  650. CSA_add_entry_callback_data *adata;
  651. CSA_delete_entry_callback_data *ddata;
  652. CSA_update_entry_callback_data *udata;
  653. if (ptr) {
  654. if (ptr->cal) free(ptr->cal);
  655. if (ptr->user) free(ptr->user);
  656. if (ptr->data) switch (ptr->reason) {
  657. case CSA_CB_CALENDAR_LOGON:
  658. ldata = ptr->data;
  659. if (ldata->user) free(ldata->user);
  660. free(ldata);
  661. break;
  662. case CSA_CB_CALENDAR_DELETED:
  663. rdata = ptr->data;
  664. if (rdata->user) free(rdata->user);
  665. free(rdata);
  666. break;
  667. case CSA_CB_CALENDAR_ATTRIBUTE_UPDATED:
  668. cdata = (CSA_calendar_attr_update_callback_data *)
  669. ptr->data;
  670. if (cdata->user) free(cdata->user);
  671. if (cdata->number_attributes > 0)
  672. _DtCm_free_character_pointers(
  673. cdata->number_attributes,
  674. cdata->attribute_names);
  675. free(cdata);
  676. break;
  677. case CSA_CB_ENTRY_ADDED:
  678. adata = (CSA_add_entry_callback_data *)ptr->data;
  679. if (adata->user) free(adata->user);
  680. if (adata->added_entry_id.data)
  681. free(adata->added_entry_id.data);
  682. free(adata);
  683. break;
  684. case CSA_CB_ENTRY_DELETED:
  685. ddata = (CSA_delete_entry_callback_data *)ptr->data;
  686. if (ddata->date_and_time) free(ddata->date_and_time);
  687. if (ddata->user) free(ddata->user);
  688. if (ddata->deleted_entry_id.data)
  689. free(ddata->deleted_entry_id.data);
  690. free(ddata);
  691. break;
  692. case CSA_CB_ENTRY_UPDATED:
  693. udata = (CSA_update_entry_callback_data *)ptr->data;
  694. if (udata->user) free(udata->user);
  695. if (udata->date_and_time) free(udata->date_and_time);
  696. if (udata->old_entry_id.data)
  697. free(udata->old_entry_id.data);
  698. if (udata->new_entry_id.data)
  699. free(udata->new_entry_id.data);
  700. free(udata);
  701. }
  702. free(ptr);
  703. }
  704. }