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 libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: callback.c /main/5 1996/10/03 10:40:51 drk $ */
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>
50 * forward declaration of static functions used within the file
52 static _DtCmsRegistrationInfo * _DtCmsDoCallback(
53 _DtCmsRegistrationInfo *rlist,
60 /*****************************************************************************
62 *****************************************************************************/
64 extern _DtCmsRegistrationInfo *
65 _DtCmsMakeRegistrationInfo(
73 _DtCmsRegistrationInfo *rinfo;
75 if ((rinfo = (_DtCmsRegistrationInfo *)calloc(1,
76 sizeof(_DtCmsRegistrationInfo))) == NULL)
79 if ((rinfo->client = strdup(client)) == NULL) {
85 rinfo->prognum = prognum;
86 rinfo->versnum = versnum;
87 rinfo->procnum = procnum;
94 _DtCmsFreeRegistrationInfo(_DtCmsRegistrationInfo *rinfo)
96 if (rinfo==NULL) return;
97 if (rinfo->client != NULL)
103 * this routine is for v4, so type is not checked
105 extern _DtCmsRegistrationInfo *
106 _DtCmsGetRegistration(
107 _DtCmsRegistrationInfo **_rlist,
114 _DtCmsRegistrationInfo *rlist = *_rlist,
119 for (prev = ptr = rlist; ptr != NULL; ) {
120 if ((strcmp(ptr->client, client)==0) &&
121 (ptr->prognum == prognum) &&
122 (ptr->versnum == versnum) &&
123 (ptr->procnum == procnum))
125 if (ptr->pid == pid) {
129 /* ptr points to a stale record
130 * remove it from the linked list
131 * and update ptr and prev appropriately
133 if (ptr == prev) { /* top of list */
135 _DtCmsFreeRegistrationInfo(ptr);
138 prev->next = ptr->next;
141 _DtCmsFreeRegistrationInfo(tmp_ptr);
155 * Go through the registration list and ping each client.
156 * Deregister clients that do not respond.
158 extern _DtCmsRegistrationInfo *
159 _DtCmsCheckRegistrationList(_DtCmsRegistrationInfo *rlist)
161 int nclients=0, ndereg=0;
162 char *sourcehost=NULL;
163 _DtCmsRegistrationInfo *p_next;
164 _DtCmsRegistrationInfo *p_prev;
165 _DtCmsRegistrationInfo *head;
166 struct timeval timeout_tv;
168 boolean_t advance = B_TRUE;
170 timeout_tv.tv_sec = 10;
171 timeout_tv.tv_usec = 0;
173 /* loop through the registration list */
175 head = p_prev = rlist;
176 while (rlist != NULL) {
178 p_next = rlist->next;
182 "%s: pinging %s on prog: %ld, vers: %ld, proc: %ld\n",
183 pgname, rlist->client, rlist->prognum, rlist->versnum,
187 sourcehost = _DtCmsTarget2Location(rlist->client);
188 cl = clnt_create(sourcehost, rlist->prognum, rlist->versnum,
192 clnt_control(cl, CLSET_TIMEOUT, (char *)&timeout_tv);
193 timeout_tv.tv_sec = 5;
194 clnt_control(cl, CLSET_RETRY_TIMEOUT,
198 /* no client or client not responding */
199 if (cl == NULL || clnt_call(cl, 0, (xdrproc_t)xdr_void, (char *)NULL,
200 (xdrproc_t)xdr_void, (char *)NULL, timeout_tv) != RPC_SUCCESS)
203 clnt_pcreateerror(sourcehost);
204 fprintf(stderr, "%s: %s deregistered, pid %d\n",
205 pgname, rlist->client, rlist->pid);
208 if (rlist == p_prev) { /* top of list */
213 p_prev->next = p_next;
216 /* deregister client */
217 _DtCmsFreeRegistrationInfo(rlist);
238 fprintf(stderr, "%s: number of clients before cleanup = %d\n",
240 fprintf(stderr, "%s: number of clients deregistered = %d\n",
247 extern _DtCmsRegistrationInfo *
248 _DtCmsDoV1CbForV4Data(
249 _DtCmsRegistrationInfo *rlist,
260 appt1.appt_id.tick = key1->time;
261 appt1.appt_id.key = key1->id;
264 appt2.appt_id.tick = key2->time;
265 appt2.appt_id.key = key2->id;
271 return (_DtCmsDoV1Callback(rlist, source, pid, &appt1));
275 * this routine takes care of callbacks to clients using v1 of the callback
278 extern _DtCmsRegistrationInfo *
280 _DtCmsRegistrationInfo *rlist,
285 Uid_4 *k, *ids = NULL;
287 int nclients=0, ncallbacks=0;
288 char *sourcehost=NULL;
289 _DtCmsRegistrationInfo *ptr;
290 _DtCmsRegistrationInfo *prev;
291 struct timeval timeout_tv;
293 boolean_t advance = B_TRUE;
298 /* Callback with appointment ids only for security reason. */
301 if ((k = (Uid_4 *)malloc(sizeof(Uid_4))) == NULL) {
302 _DtCm_free_keyentry4(ids);
306 k->appt_id = a->appt_id;
312 res.status = access_ok_4;
314 res.res.Table_Res_List_4_u.i = ids;
316 rlist = _DtCmsDoCallback(rlist, 0, source, pid, AGENTVERS, (void *)&res);
319 _DtCm_free_keyentry4(ids);
325 _DtCmsListRegistration(_DtCmsRegistrationInfo *rlist, char *cal)
329 fprintf(stderr, "registration list of calendar %s\n", cal);
330 while(rlist != NULL) {
332 fprintf(stderr, "\t%s (pid %d)\n", rlist->client, rlist->pid);
335 fprintf(stderr, "\tnumber of registered clients = %d\n", n);
338 extern _DtCmsRegistrationInfo *
339 _DtCmsRemoveRegistration(
340 _DtCmsRegistrationInfo *rlist,
341 _DtCmsRegistrationInfo *rinfo)
343 _DtCmsRegistrationInfo *ptr, *prev;
346 for (ptr = prev = rlist; ptr != NULL; prev = ptr, ptr = ptr->next) {
351 prev->next = ptr->next;
353 _DtCmsFreeRegistrationInfo(ptr);
361 extern _DtCmsRegistrationInfo *
362 _DtCmsDoOpenCalCallback(
363 _DtCmsRegistrationInfo *rlist,
368 cmcb_update_callback_args args;
369 char calendar[BUFSIZ];
374 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
375 args.calendar = calendar;
377 args.data.reason = CSA_CB_CALENDAR_LOGON;
379 return (_DtCmsDoCallback(rlist, CSA_CB_CALENDAR_LOGON, user, pid,
380 AGENTVERS_2, (void *)&args));
384 extern _DtCmsRegistrationInfo *
385 _DtCmsDoRemoveCalCallback(
386 _DtCmsRegistrationInfo *rlist,
391 cmcb_update_callback_args args;
392 char calendar[BUFSIZ];
397 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
398 args.calendar = calendar;
400 args.data.reason = CSA_CB_CALENDAR_DELETED;
402 return (_DtCmsDoCallback(rlist, CSA_CB_CALENDAR_DELETED, user, pid,
403 AGENTVERS_2, (void *)&args));
406 extern _DtCmsRegistrationInfo *
407 _DtCmsDoUpdateCalAttrsCallback(
408 _DtCmsRegistrationInfo *rlist,
412 cms_attribute *attrs,
415 cmcb_update_callback_args args;
416 cmcb_cal_attr_data cdata;
417 _DtCmsRegistrationInfo *res;
419 char calendar[BUFSIZ];
425 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
427 /* set up update info */
429 (cdata.names = (char **)calloc(1, sizeof(char *)*num_attrs)))
431 for (i = 0; i < num_attrs; i++)
432 cdata.names[i] = attrs[i].name.name;
438 args.calendar = calendar;
440 args.data.reason = CSA_CB_CALENDAR_ATTRIBUTE_UPDATED;
441 args.data.data.cdata = &cdata;
443 res = _DtCmsDoCallback(rlist, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED, user,
444 pid, AGENTVERS_2, (void *)&args);
446 if (num_attrs > 0) free(cdata.names);
451 extern _DtCmsRegistrationInfo *
452 _DtCmsDoInsertEntryCallback(
453 _DtCmsRegistrationInfo *rlist,
459 cmcb_update_callback_args args;
460 cmcb_add_entry_data adata;
462 char calendar[BUFSIZ];
467 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
469 /* set up update info */
470 sprintf(buf, "%ld", id);
472 args.calendar = calendar;
474 args.data.reason = CSA_CB_ENTRY_ADDED;
475 args.data.data.adata = &adata;
477 return (_DtCmsDoCallback(rlist, CSA_CB_ENTRY_ADDED, source, pid,
478 AGENTVERS_2, (void *)&args));
481 extern _DtCmsRegistrationInfo *
482 _DtCmsDoDeleteEntryCallback(
483 _DtCmsRegistrationInfo *rlist,
491 cmcb_update_callback_args args;
492 cmcb_delete_entry_data ddata;
494 char calendar[BUFSIZ];
499 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
501 /* set up update info */
502 sprintf(buf, "%ld", id);
506 args.calendar = calendar;
508 args.data.reason = CSA_CB_ENTRY_DELETED;
509 args.data.data.ddata = &ddata;
511 return (_DtCmsDoCallback(rlist, CSA_CB_ENTRY_DELETED, source, pid,
512 AGENTVERS_2, (void *)&args));
515 extern _DtCmsRegistrationInfo *
516 _DtCmsDoUpdateEntryCallback(
517 _DtCmsRegistrationInfo *rlist,
526 cmcb_update_callback_args args;
527 cmcb_update_entry_data udata;
528 char nbuf[80], obuf[80];
529 char calendar[BUFSIZ];
534 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
536 /* set up update info */
537 sprintf(obuf, "%ld", oldid);
540 sprintf(nbuf, "%ld", newid);
546 args.calendar = calendar;
548 args.data.reason = CSA_CB_ENTRY_UPDATED;
549 args.data.data.udata = &udata;
551 return (_DtCmsDoCallback(rlist, CSA_CB_ENTRY_UPDATED, source, pid,
552 AGENTVERS_2, (void *)&args));
556 * this routine takes care of callbacks to clients using either
557 * v1 or v2 of the callback protocol.
559 static _DtCmsRegistrationInfo *
561 _DtCmsRegistrationInfo *rlist,
568 int nclients=0, ncallbacks=0;
569 char *sourcehost=NULL;
570 _DtCmsRegistrationInfo *ptr;
571 _DtCmsRegistrationInfo *prev;
572 struct timeval timeout_tv;
574 boolean_t advance = B_TRUE;
577 * loop through the registration list looking for parties
578 * interested in this transaction.
581 for (ptr = prev = rlist; ptr != NULL; ) {
583 /* The caller will get the results of the rpc call.
584 * If he's registered on the callback list, don't call him -
585 * UNLESS the process id of his client differs from the
586 * original ticket. However, if the pid is a VOIDPID (-1),
587 * a version 2 client has registered and there's no way
588 * of telling which instance of the client it is. So,
589 * to be safe (avoid deadlock) we won't callback version
590 * 2 clients registered on version 3 daemons if their
591 * registration name entry matches the caller's. [Nanno]
594 if (version != ptr->versnum ||
595 (type && !(type & ptr->types)) ||
596 ((strcmp(source, ptr->client) == 0) &&
597 ((pid == ptr->pid) || (pid == -1 ) || (ptr->pid == -1)))) {
604 sourcehost = _DtCmsTarget2Location(ptr->client);
607 "%s: calling back %s on prog: %ld, vers: %ld, proc: %ld\n",
608 pgname, ptr->client, ptr->prognum, ptr->versnum,
611 cl = clnt_create(sourcehost, ptr->prognum, ptr->versnum, "udp");
613 /* deregister client if fails to create handle */
616 clnt_pcreateerror(sourcehost);
619 if (ptr == rlist) { /* top of list */
624 prev->next = ptr->next;
627 /* deregister client */
628 _DtCmsFreeRegistrationInfo(ptr);
633 /* Set timeout to zero so that the call
634 * returns right away.
636 timeout_tv.tv_sec = 0;
637 timeout_tv.tv_usec = 0;
640 /* for non-sun systems, clnt_call won't
641 * return right away unless timeout is set
642 * to zero using clnt_control(), (rpc bug?)
644 clnt_control(cl, CLSET_TIMEOUT,
645 (char *)&timeout_tv);
647 if (version == AGENTVERS) {
648 (void)clnt_call(cl, ptr->procnum,
649 (xdrproc_t)_DtCm_xdr_Table_Res_4, (char *)args,
650 (xdrproc_t)xdr_void, (char *)0, timeout_tv);
651 } else if (version == AGENTVERS_2) {
652 (void)clnt_call(cl, ptr->procnum,
653 (xdrproc_t)xdr_cmcb_update_callback_args,
654 (char *)args, (xdrproc_t)xdr_void, (char *)0,
674 fprintf(stderr, "%s: number of registered clients = %d\n",
676 fprintf(stderr, "%s: number of clients called back= %d\n",