2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: agent.c /main/2 1998/03/16 14:42:16 mgreess $ */
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.
31 #include <EUSCompat.h>
38 # include <sys/poll.h>
42 #if defined(SunOS) || defined(USL) || defined(__uxp__)
43 #include <netconfig.h>
46 #include <sys/signal.h>
47 #include <sys/socket.h>
48 #include <sys/errno.h>
49 #endif /* SunOS || USL || __uxp__ */
50 #include <X11/Intrinsic.h>
62 * - contain update information from backend
64 typedef struct cb_info {
73 static _CallbackInfo *cb_head = NULL, *cb_tail = NULL;
75 u_long _DtCm_transient = 0;
77 static u_long prognum = 0x40000000;
78 static int mapped = 0;
80 /******************************************************************************
81 * forward declaration of static functions used within the file
82 ******************************************************************************/
83 #if defined(SunOS) || defined(USL) || defined(__uxp__)
84 static u_long gettransient (u_long version);
86 static u_long gettransient (int proto, u_long vers, int *sockp);
88 static void _DtCm_handle_callback();
89 static CSA_return_code _ConvertCallbackData(cmcb_update_callback_args *args,
91 static CSA_return_code _CopyAttributeNames(uint fnum, char **fnames,
92 CSA_uint32 *tnum, char ***tnames);
93 static boolean_t _ProcessV1Callback(_CallbackInfo *ptr);
94 static boolean_t _ProcessV2Callback(_CallbackInfo *ptr);
95 static void _FreeCallbackInfo(_CallbackInfo *ptr);
97 /*****************************************************************************
98 * extern functions used in the library
99 *****************************************************************************/
102 * Register rpc service for server callback
110 #if defined(SunOS) && SunOS < 55 || defined(USL) || defined(__uxp__)
111 extern boolean_t rpc_reg(const u_long, const u_long, const u_long,
112 const char *(*)(), const xdrproc_t, const xdrproc_t,
116 #if defined(SunOS) || defined(USL)|| defined(__uxp__)
117 extern void (*sigset(int, void (*)(int)))(int);
119 extern void (*sigset())();
122 /* locking candidate for MT-safe purpose */
126 DP(("libdtcm: _DtCm_init_agent\n"));
128 #if defined(SunOS) || defined(USL) || defined(__uxp__)
129 (void)rpcb_unset(_DtCm_transient, AGENTVERS, NULL);
130 if ((_DtCm_transient = gettransient((u_long)1)) == 0) {
131 _DtCm_print_errmsg("Cannot get transient program number\n");
132 _DtCm_print_errmsg("Callback cannot be enabled.\n");
136 /* register v1 callback */
137 if (rpc_reg(_DtCm_transient, AGENTVERS, update_callback,
138 (const char *(*)())_DtCm_update_callback_1, _DtCm_xdr_Table_Res_4,
139 _DtCm_xdr_Update_Status, "udp") == -1) {
140 _DtCm_print_errmsg("Cannot register v1 callback handler\n");
141 _DtCm_print_errmsg("Callback cannot be enabled.\n");
144 /* register v2 callback */
145 if (rpc_reg(_DtCm_transient, AGENTVERS_2, CMCB_UPDATE_CALLBACK,
146 (const char *(*)())cmcb_update_callback_2_svc,
147 xdr_cmcb_update_callback_args, xdr_void, "udp") == -1) {
148 _DtCm_print_errmsg("Cannot register v2 callback handler\n");
149 _DtCm_print_errmsg("Callback cannot be enabled.\n");
153 (void)pmap_unset(_DtCm_transient, AGENTVERS);
154 if ((_DtCm_transient = gettransient(IPPROTO_UDP,(u_long)1, &s)) == 0) {
155 _DtCm_print_errmsg("Cannot get transient program number\n");
156 _DtCm_print_errmsg("Callback cannot be enabled.\n");
160 if (registerrpc(_DtCm_transient, AGENTVERS, update_callback,
161 (char *(*)())_DtCm_update_callback_1, _DtCm_xdr_Table_Res_4,
162 _DtCm_xdr_Update_Status) == -1) {
163 _DtCm_print_errmsg("Cannot register v1 callback handler\n");
164 _DtCm_print_errmsg("Callback cannot be enabled.\n");
167 if (registerrpc(_DtCm_transient, AGENTVERS_2, CMCB_UPDATE_CALLBACK,
168 (char *(*)())cmcb_update_callback_2_svc,
169 xdr_cmcb_update_callback_args, xdr_void) == -1) {
170 _DtCm_print_errmsg("Cannot register v2 callback handler\n");
171 _DtCm_print_errmsg("Callback cannot be enabled.\n");
174 #endif /* SunOS || USL || __uxp__ */
176 /* locking candidate for MT-safe purpose */
181 * Unregister with the rpc service.
184 _DtCm_destroy_agent()
189 DP(("libdtcm: _DtCm_destroy_agent\n"));
191 #if defined(SunOS) || defined(USL) || defined(__uxp__)
192 (void) rpcb_unset(_DtCm_transient, AGENTVERS, NULL);
193 (void) rpcb_unset(_DtCm_transient, AGENTVERS_2, NULL);
195 (void) pmap_unset(_DtCm_transient, AGENTVERS);
196 (void) pmap_unset(_DtCm_transient, AGENTVERS_2);
197 #endif /* SunOS || USL || __uxp__ */
199 /* locking candidate for MT-safe purpose */
204 _DtCm_process_updates()
208 fd_mask fmask, *inbits;
209 struct pollfd pfd[FD_SETSIZE];
215 rpc_bits = svc_fdset;
217 /* convert to pollfd structure */
218 inbits = rpc_bits.fds_bits;
220 for (i = 0; i < FD_SETSIZE; i += NFDBITS) {
222 for (j = 0; fmask != 0 ; j++, fmask >>= 1) {
225 if (p->fd >= FD_SETSIZE)
234 /* poll and return right away */
237 nfd = poll(pfd, i, 0);
243 /* if set, handle rpc calls */
245 /* convert back to fd_set structure */
249 for (p = pfd; i-- > 0; p++) {
252 inbits = &rpc_bits.fds_bits[j];
255 if (p->revents & POLLIN) {
256 *inbits |= (1 << (p->fd % NFDBITS));
262 svc_getreqset(&rpc_bits);
267 * The server calls this routine when an update event occurs;
268 * It's job is to notify CM asynchronously that an
269 * update has occurred. It has to do it this
270 * way (i.e. raise a signal) because the client
271 * can't make an rpc call until this procedure call has
272 * returned to the server.
276 _DtCm_update_callback_1(Table_Res_4 *t, void *dummy)
278 static Update_Status status = update_succeeded;
281 DP(("agent.c: _DtCm_update_callback_1()\n"));
284 * no point to save data for version 4 and before
285 * since the info from old backends does not contain
287 * so we just invoke all registered callback with no data
289 if (cbi = (_CallbackInfo *)calloc(1, sizeof(_CallbackInfo))) {
290 cbi->vers = AGENTVERS;
300 /* handle callback from backend */
301 _DtCm_handle_callback();
307 * Handler for v2 callback protocol
310 cmcb_update_callback_2_svc(cmcb_update_callback_args *args, struct svc_req *d)
314 DP(("agent.c: cmcb_update_callback_2_svc()\n"));
319 if (_ConvertCallbackData(args, &cbi) == CSA_SUCCESS) {
320 cbi->vers = AGENTVERS_2;
329 /* handle callback from backend */
330 _DtCm_handle_callback();
336 /******************************************************************************
337 * static functions used within in the file
338 ******************************************************************************/
341 * get transient program number for callbacks.
343 #if defined(SunOS) || defined(USL) || defined(__uxp__)
345 gettransient (u_long version)
348 struct nd_hostserv host = {HOST_SELF, "rpcbind"};
349 struct nd_addrlist *addrp;
352 struct netconfig *netconf;
354 netconf = getnetconfigent("udp");
356 DP(("(gettransient) getnetconfigent(udp) failed\n"));
357 freenetconfigent(netconf);
361 stat = netdir_getbyname(netconf, &host, &addrp);
363 DP(("(gettransient) netdir_getbyname failed\n"));
364 netdir_free(addrp, ND_ADDRLIST);
365 freenetconfigent(netconf);
369 if (addrp->n_cnt < 1) {
370 DP(("(gettransient) netdir_getbyname - zero addresses\n"));
371 netdir_free(addrp, ND_ADDRLIST);
372 freenetconfigent(netconf);
376 addr = addrp->n_addrs;
378 while (!rpcb_set(prognum++, version, netconf, addr))
380 netdir_free(addrp, ND_ADDRLIST);
381 freenetconfigent(netconf);
387 #else /* SunOS || USL || __uxp__ */
390 gettransient (int proto, u_long vers, int *sockp)
392 int s, len, socktype;
393 struct sockaddr_in addr;
397 socktype = SOCK_DGRAM;
400 socktype = SOCK_STREAM;
403 DP(("unknown protocol type\n"));
407 if (*sockp == RPC_ANYSOCK) {
408 if ((s = socket(AF_INET, socktype, 0)) < 0) {
416 addr.sin_addr.s_addr = 0;
417 addr.sin_family = AF_INET;
421 if (bind(s, (struct sockaddr *)&addr, len) != 0) {
426 if (getsockname(s, (struct sockaddr *)&addr, &len) < 0) {
427 perror("getsockname");
431 while (!pmap_set(prognum++, vers, proto, ntohs(addr.sin_port)))
437 #endif /* not SunOS || USL || __uxp__ */
440 _DtCm_handle_callback()
442 _CallbackInfo *ptr, *prev;
444 _DtCmCallbackEntry *cb;
445 boolean_t keep = B_FALSE;
447 DP(("agent.c: _DtCm_handle_callback()\n"));
449 for (ptr = cb_head, prev = NULL; ptr != NULL; ) {
450 /* we only handle version 1 and version 2 */
451 if (ptr->vers == AGENTVERS)
452 keep = _ProcessV1Callback(ptr);
454 keep = _ProcessV2Callback(ptr);
460 prev->next = ptr->next;
462 _FreeCallbackInfo(ptr);
472 static CSA_return_code
473 _ConvertCallbackData(cmcb_update_callback_args *args, _CallbackInfo **cbi)
476 CSA_calendar_user *user;
477 CSA_logon_callback_data *ldata;
478 CSA_calendar_deleted_callback_data *rdata;
479 CSA_calendar_attr_update_callback_data *cdata;
480 CSA_add_entry_callback_data *adata;
481 CSA_delete_entry_callback_data *ddata;
482 CSA_update_entry_callback_data *udata;
483 char timebuf[BUFSIZ];
485 if ((ncbi = (_CallbackInfo *)calloc(1, sizeof(_CallbackInfo))) == NULL)
486 return (CSA_E_INSUFFICIENT_MEMORY);
488 if (args->calendar && (ncbi->cal = strdup(args->calendar)) == NULL) {
490 return (CSA_E_INSUFFICIENT_MEMORY);
493 if (args->user && (ncbi->user = strdup(args->user)) == NULL) {
494 _FreeCallbackInfo(ncbi);
495 return (CSA_E_INSUFFICIENT_MEMORY);
498 if ((user = (CSA_calendar_user *)calloc(1, sizeof(CSA_calendar_user)))
500 _FreeCallbackInfo(ncbi);
501 return (CSA_E_INSUFFICIENT_MEMORY);
503 user->user_name = ncbi->user;
505 ncbi->reason = args->data.reason;
506 switch (ncbi->reason) {
507 case CSA_CB_CALENDAR_LOGON:
508 if ((ldata = (CSA_logon_callback_data *)calloc(1,
509 sizeof(CSA_logon_callback_data))) == NULL) {
511 _FreeCallbackInfo(ncbi);
512 return (CSA_E_INSUFFICIENT_MEMORY);
515 ncbi->data = (void *)ldata;
518 case CSA_CB_CALENDAR_DELETED:
519 if ((rdata = (CSA_calendar_deleted_callback_data *)calloc(1,
520 sizeof(CSA_calendar_deleted_callback_data))) == NULL) {
522 _FreeCallbackInfo(ncbi);
523 return (CSA_E_INSUFFICIENT_MEMORY);
526 ncbi->data = (void *)rdata;
529 case CSA_CB_CALENDAR_ATTRIBUTE_UPDATED:
530 if ((cdata = (CSA_calendar_attr_update_callback_data *)
532 CSA_calendar_attr_update_callback_data))) == NULL) {
534 _FreeCallbackInfo(ncbi);
535 return (CSA_E_INSUFFICIENT_MEMORY);
538 ncbi->data = (void *)cdata;
540 if (_CopyAttributeNames(args->data.data.cdata->num_names,
541 args->data.data.cdata->names, &cdata->number_attributes,
542 &cdata->attribute_names)) {
543 _FreeCallbackInfo(ncbi);
544 return (CSA_E_INSUFFICIENT_MEMORY);
549 case CSA_CB_ENTRY_ADDED:
550 if ((adata = (CSA_add_entry_callback_data *)calloc(1,
551 sizeof(CSA_add_entry_callback_data))) == NULL) {
553 _FreeCallbackInfo(ncbi);
554 return (CSA_E_INSUFFICIENT_MEMORY);
557 ncbi->data = (void *)adata;
559 if (args->data.data.adata->id && (adata->added_entry_id.data =
560 (unsigned char *)strdup(args->data.data.adata->id))
562 _FreeCallbackInfo(ncbi);
563 return (CSA_E_INSUFFICIENT_MEMORY);
565 adata->added_entry_id.size =
566 strlen((char *)adata->added_entry_id.data);
570 case CSA_CB_ENTRY_DELETED:
571 if ((ddata = (CSA_delete_entry_callback_data *)calloc(1,
572 sizeof(CSA_delete_entry_callback_data))) == NULL) {
574 _FreeCallbackInfo(ncbi);
575 return (CSA_E_INSUFFICIENT_MEMORY);
578 ncbi->data = (void *)ddata;
580 if (args->data.data.ddata->id && (ddata->deleted_entry_id.data =
581 (unsigned char *)strdup(args->data.data.ddata->id))
583 _FreeCallbackInfo(ncbi);
584 return (CSA_E_INSUFFICIENT_MEMORY);
586 ddata->deleted_entry_id.size =
587 strlen((char *)ddata->deleted_entry_id.data);
589 _csa_tick_to_iso8601(args->data.data.ddata->time, timebuf);
590 if ((ddata->date_and_time = strdup(timebuf)) == NULL) {
591 _FreeCallbackInfo(ncbi);
592 return (CSA_E_INSUFFICIENT_MEMORY);
595 ddata->scope = args->data.data.ddata->scope;
598 case CSA_CB_ENTRY_UPDATED:
599 if ((udata = (CSA_update_entry_callback_data *)calloc(1,
600 sizeof(CSA_update_entry_callback_data))) == NULL) {
602 _FreeCallbackInfo(ncbi);
603 return (CSA_E_INSUFFICIENT_MEMORY);
606 ncbi->data = (void *)udata;
608 if (args->data.data.udata->newid && (udata->new_entry_id.data =
609 (unsigned char *)strdup(args->data.data.udata->newid))
611 _FreeCallbackInfo(ncbi);
612 return (CSA_E_INSUFFICIENT_MEMORY);
614 udata->new_entry_id.size =
615 strlen((char *)udata->new_entry_id.data);
617 if (args->data.data.udata->oldid && (udata->old_entry_id.data =
618 (unsigned char *)strdup(args->data.data.udata->oldid))
620 _FreeCallbackInfo(ncbi);
621 return (CSA_E_INSUFFICIENT_MEMORY);
623 udata->old_entry_id.size =
624 strlen((char *)udata->old_entry_id.data);
626 _csa_tick_to_iso8601(args->data.data.udata->time, timebuf);
627 if ((udata->date_and_time = strdup(timebuf)) == NULL) {
628 _FreeCallbackInfo(ncbi);
629 return (CSA_E_INSUFFICIENT_MEMORY);
632 udata->scope = args->data.data.udata->scope;
637 return (CSA_SUCCESS);
640 static CSA_return_code
641 _CopyAttributeNames(uint fnum, char **fnames, CSA_uint32 *tnum, char ***tnames)
649 return (CSA_SUCCESS);
652 if ((nnames = calloc(1, sizeof(char *) * fnum)) == NULL)
653 return (CSA_E_INSUFFICIENT_MEMORY);
655 for (i = 0; i < fnum; i++) {
656 if ((nnames[i] = strdup(fnames[i])) == NULL)
663 return (CSA_SUCCESS);
665 _DtCm_free_character_pointers(i, nnames);
667 return (CSA_E_INSUFFICIENT_MEMORY);
672 * pre callback protocol V2, there is no distinction
673 * between different reasons, and no data passed. So
674 * there's only one possible thing to do, and that's
675 * run all the callbacks.
678 _ProcessV1Callback(_CallbackInfo *ptr)
681 _DtCmCallbackEntry *cb;
682 boolean_t keep = B_FALSE;
684 for (cal = _DtCm_active_cal_list; cal != NULL; cal = cal->next) {
685 if (cal->rpc_version >= _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
688 if (cal->do_reasons &
689 (CSA_CB_ENTRY_ADDED | CSA_CB_ENTRY_DELETED |
690 CSA_CB_ENTRY_UPDATED))
692 /* only do dumb processing if it was a V4 server */
693 for (cb = cal->cb_list; cb != NULL; cb = cb->next) {
694 if (cal->do_reasons & cb->reason) {
695 cb->handler((CSA_session_handle)cal,
696 cal->do_reasons & cb->reason,
699 (CSA_extension*) NULL);
702 } else if (cal->all_reasons & (CSA_CB_ENTRY_ADDED |
703 CSA_CB_ENTRY_DELETED | CSA_CB_ENTRY_UPDATED))
711 _ProcessV2Callback(_CallbackInfo *ptr)
714 _DtCmCallbackEntry *cb;
715 boolean_t keep = B_FALSE;
717 for (cal = _DtCm_active_cal_list; cal != NULL; cal = cal->next) {
718 if (cal->rpc_version < _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION ||
719 strcmp(ptr->cal, cal->name))
722 if (cal->do_reasons & ptr->reason) {
724 /* only do dumb processing if it was a V4 server */
725 for (cb = cal->cb_list; cb != NULL; cb = cb->next) {
726 if (ptr->reason & cb->reason) {
727 cb->handler((CSA_session_handle)cal,
729 (CSA_buffer)ptr->data,
731 (CSA_extension*) NULL);
734 } else if (cal->all_reasons & ptr->reason)
742 _FreeCallbackInfo(_CallbackInfo *ptr)
744 CSA_logon_callback_data *ldata;
745 CSA_calendar_deleted_callback_data *rdata;
746 CSA_calendar_attr_update_callback_data *cdata;
747 CSA_add_entry_callback_data *adata;
748 CSA_delete_entry_callback_data *ddata;
749 CSA_update_entry_callback_data *udata;
752 if (ptr->cal) free(ptr->cal);
753 if (ptr->user) free(ptr->user);
755 if (ptr->data) switch (ptr->reason) {
756 case CSA_CB_CALENDAR_LOGON:
758 if (ldata->user) free(ldata->user);
761 case CSA_CB_CALENDAR_DELETED:
763 if (rdata->user) free(rdata->user);
766 case CSA_CB_CALENDAR_ATTRIBUTE_UPDATED:
767 cdata = (CSA_calendar_attr_update_callback_data *)
769 if (cdata->user) free(cdata->user);
770 if (cdata->number_attributes > 0)
771 _DtCm_free_character_pointers(
772 cdata->number_attributes,
773 cdata->attribute_names);
776 case CSA_CB_ENTRY_ADDED:
777 adata = (CSA_add_entry_callback_data *)ptr->data;
778 if (adata->user) free(adata->user);
779 if (adata->added_entry_id.data)
780 free(adata->added_entry_id.data);
783 case CSA_CB_ENTRY_DELETED:
784 ddata = (CSA_delete_entry_callback_data *)ptr->data;
785 if (ddata->date_and_time) free(ddata->date_and_time);
786 if (ddata->user) free(ddata->user);
787 if (ddata->deleted_entry_id.data)
788 free(ddata->deleted_entry_id.data);
791 case CSA_CB_ENTRY_UPDATED:
792 udata = (CSA_update_entry_callback_data *)ptr->data;
793 if (udata->user) free(udata->user);
794 if (udata->date_and_time) free(udata->date_and_time);
795 if (udata->old_entry_id.data)
796 free(udata->old_entry_id.data);
797 if (udata->new_entry_id.data)
798 free(udata->new_entry_id.data);