agent.c 20 KB

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