1 /* $XConsortium: callback.c /main/5 1996/10/03 10:40:51 drk $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Novell, Inc.
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
28 * forward declaration of static functions used within the file
30 static _DtCmsRegistrationInfo * _DtCmsDoCallback(
31 _DtCmsRegistrationInfo *rlist,
38 /*****************************************************************************
40 *****************************************************************************/
42 extern _DtCmsRegistrationInfo *
43 _DtCmsMakeRegistrationInfo(
51 _DtCmsRegistrationInfo *rinfo;
53 if ((rinfo = (_DtCmsRegistrationInfo *)calloc(1,
54 sizeof(_DtCmsRegistrationInfo))) == NULL)
57 if ((rinfo->client = strdup(client)) == NULL) {
63 rinfo->prognum = prognum;
64 rinfo->versnum = versnum;
65 rinfo->procnum = procnum;
72 _DtCmsFreeRegistrationInfo(_DtCmsRegistrationInfo *rinfo)
74 if (rinfo==NULL) return;
75 if (rinfo->client != NULL)
81 * this routine is for v4, so type is not checked
83 extern _DtCmsRegistrationInfo *
84 _DtCmsGetRegistration(
85 _DtCmsRegistrationInfo **_rlist,
92 _DtCmsRegistrationInfo *rlist = *_rlist,
97 for (prev = ptr = rlist; ptr != NULL; ) {
98 if ((strcmp(ptr->client, client)==0) &&
99 (ptr->prognum == prognum) &&
100 (ptr->versnum == versnum) &&
101 (ptr->procnum == procnum))
103 if (ptr->pid == pid) {
107 /* ptr points to a stale record
108 * remove it from the linked list
109 * and update ptr and prev appropriately
111 if (ptr == prev) { /* top of list */
113 _DtCmsFreeRegistrationInfo(ptr);
116 prev->next = ptr->next;
119 _DtCmsFreeRegistrationInfo(tmp_ptr);
133 * Go through the registration list and ping each client.
134 * Deregister clients that do not respond.
136 extern _DtCmsRegistrationInfo *
137 _DtCmsCheckRegistrationList(_DtCmsRegistrationInfo *rlist)
139 int nclients=0, ndereg=0;
140 char *sourcehost=NULL;
141 _DtCmsRegistrationInfo *p_next;
142 _DtCmsRegistrationInfo *p_prev;
143 _DtCmsRegistrationInfo *head;
144 struct timeval timeout_tv;
146 boolean_t advance = B_TRUE;
148 timeout_tv.tv_sec = 10;
149 timeout_tv.tv_usec = 0;
151 /* loop through the registration list */
153 head = p_prev = rlist;
154 while (rlist != NULL) {
156 p_next = rlist->next;
160 "%s: pinging %s on prog: %ld, vers: %ld, proc: %ld\n",
161 pgname, rlist->client, rlist->prognum, rlist->versnum,
165 sourcehost = _DtCmsTarget2Location(rlist->client);
166 cl = clnt_create(sourcehost, rlist->prognum, rlist->versnum,
170 clnt_control(cl, CLSET_TIMEOUT, (char *)&timeout_tv);
171 timeout_tv.tv_sec = 5;
172 clnt_control(cl, CLSET_RETRY_TIMEOUT,
176 /* no client or client not responding */
177 if (cl == NULL || clnt_call(cl, 0, (xdrproc_t)xdr_void, (char *)NULL,
178 (xdrproc_t)xdr_void, (char *)NULL, timeout_tv) != RPC_SUCCESS)
181 clnt_pcreateerror(sourcehost);
182 fprintf(stderr, "%s: %s deregistered, pid %d\n",
183 pgname, rlist->client, rlist->pid);
186 if (rlist == p_prev) { /* top of list */
191 p_prev->next = p_next;
194 /* deregister client */
195 _DtCmsFreeRegistrationInfo(rlist);
216 fprintf(stderr, "%s: number of clients before cleanup = %d\n",
218 fprintf(stderr, "%s: number of clients deregistered = %d\n",
225 extern _DtCmsRegistrationInfo *
226 _DtCmsDoV1CbForV4Data(
227 _DtCmsRegistrationInfo *rlist,
238 appt1.appt_id.tick = key1->time;
239 appt1.appt_id.key = key1->id;
242 appt2.appt_id.tick = key2->time;
243 appt2.appt_id.key = key2->id;
249 return (_DtCmsDoV1Callback(rlist, source, pid, &appt1));
253 * this routine takes care of callbacks to clients using v1 of the callback
256 extern _DtCmsRegistrationInfo *
258 _DtCmsRegistrationInfo *rlist,
263 Uid_4 *k, *ids = NULL;
265 int nclients=0, ncallbacks=0;
266 char *sourcehost=NULL;
267 _DtCmsRegistrationInfo *ptr;
268 _DtCmsRegistrationInfo *prev;
269 struct timeval timeout_tv;
271 boolean_t advance = B_TRUE;
276 /* Callback with appointment ids only for security reason. */
279 if ((k = (Uid_4 *)malloc(sizeof(Uid_4))) == NULL) {
280 _DtCm_free_keyentry4(ids);
284 k->appt_id = a->appt_id;
290 res.status = access_ok_4;
292 res.res.Table_Res_List_4_u.i = ids;
294 rlist = _DtCmsDoCallback(rlist, 0, source, pid, AGENTVERS, (void *)&res);
297 _DtCm_free_keyentry4(ids);
303 _DtCmsListRegistration(_DtCmsRegistrationInfo *rlist, char *cal)
307 fprintf(stderr, "registration list of calendar %s\n", cal);
308 while(rlist != NULL) {
310 fprintf(stderr, "\t%s (pid %d)\n", rlist->client, rlist->pid);
313 fprintf(stderr, "\tnumber of registered clients = %d\n", n);
316 extern _DtCmsRegistrationInfo *
317 _DtCmsRemoveRegistration(
318 _DtCmsRegistrationInfo *rlist,
319 _DtCmsRegistrationInfo *rinfo)
321 _DtCmsRegistrationInfo *ptr, *prev;
324 for (ptr = prev = rlist; ptr != NULL; prev = ptr, ptr = ptr->next) {
329 prev->next = ptr->next;
331 _DtCmsFreeRegistrationInfo(ptr);
339 extern _DtCmsRegistrationInfo *
340 _DtCmsDoOpenCalCallback(
341 _DtCmsRegistrationInfo *rlist,
346 cmcb_update_callback_args args;
347 char calendar[BUFSIZ];
352 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
353 args.calendar = calendar;
355 args.data.reason = CSA_CB_CALENDAR_LOGON;
357 return (_DtCmsDoCallback(rlist, CSA_CB_CALENDAR_LOGON, user, pid,
358 AGENTVERS_2, (void *)&args));
362 extern _DtCmsRegistrationInfo *
363 _DtCmsDoRemoveCalCallback(
364 _DtCmsRegistrationInfo *rlist,
369 cmcb_update_callback_args args;
370 char calendar[BUFSIZ];
375 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
376 args.calendar = calendar;
378 args.data.reason = CSA_CB_CALENDAR_DELETED;
380 return (_DtCmsDoCallback(rlist, CSA_CB_CALENDAR_DELETED, user, pid,
381 AGENTVERS_2, (void *)&args));
384 extern _DtCmsRegistrationInfo *
385 _DtCmsDoUpdateCalAttrsCallback(
386 _DtCmsRegistrationInfo *rlist,
390 cms_attribute *attrs,
393 cmcb_update_callback_args args;
394 cmcb_cal_attr_data cdata;
395 _DtCmsRegistrationInfo *res;
397 char calendar[BUFSIZ];
403 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
405 /* set up update info */
407 (cdata.names = (char **)calloc(1, sizeof(char *)*num_attrs)))
409 for (i = 0; i < num_attrs; i++)
410 cdata.names[i] = attrs[i].name.name;
416 args.calendar = calendar;
418 args.data.reason = CSA_CB_CALENDAR_ATTRIBUTE_UPDATED;
419 args.data.data.cdata = &cdata;
421 res = _DtCmsDoCallback(rlist, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED, user,
422 pid, AGENTVERS_2, (void *)&args);
424 if (num_attrs > 0) free(cdata.names);
429 extern _DtCmsRegistrationInfo *
430 _DtCmsDoInsertEntryCallback(
431 _DtCmsRegistrationInfo *rlist,
437 cmcb_update_callback_args args;
438 cmcb_add_entry_data adata;
440 char calendar[BUFSIZ];
445 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
447 /* set up update info */
448 sprintf(buf, "%ld", id);
450 args.calendar = calendar;
452 args.data.reason = CSA_CB_ENTRY_ADDED;
453 args.data.data.adata = &adata;
455 return (_DtCmsDoCallback(rlist, CSA_CB_ENTRY_ADDED, source, pid,
456 AGENTVERS_2, (void *)&args));
459 extern _DtCmsRegistrationInfo *
460 _DtCmsDoDeleteEntryCallback(
461 _DtCmsRegistrationInfo *rlist,
469 cmcb_update_callback_args args;
470 cmcb_delete_entry_data ddata;
472 char calendar[BUFSIZ];
477 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
479 /* set up update info */
480 sprintf(buf, "%ld", id);
484 args.calendar = calendar;
486 args.data.reason = CSA_CB_ENTRY_DELETED;
487 args.data.data.ddata = &ddata;
489 return (_DtCmsDoCallback(rlist, CSA_CB_ENTRY_DELETED, source, pid,
490 AGENTVERS_2, (void *)&args));
493 extern _DtCmsRegistrationInfo *
494 _DtCmsDoUpdateEntryCallback(
495 _DtCmsRegistrationInfo *rlist,
504 cmcb_update_callback_args args;
505 cmcb_update_entry_data udata;
506 char nbuf[80], obuf[80];
507 char calendar[BUFSIZ];
512 sprintf(calendar, "%s@%s", cal, _DtCmGetLocalHost());
514 /* set up update info */
515 sprintf(obuf, "%ld", oldid);
518 sprintf(nbuf, "%ld", newid);
524 args.calendar = calendar;
526 args.data.reason = CSA_CB_ENTRY_UPDATED;
527 args.data.data.udata = &udata;
529 return (_DtCmsDoCallback(rlist, CSA_CB_ENTRY_UPDATED, source, pid,
530 AGENTVERS_2, (void *)&args));
534 * this routine takes care of callbacks to clients using either
535 * v1 or v2 of the callback protocol.
537 static _DtCmsRegistrationInfo *
539 _DtCmsRegistrationInfo *rlist,
546 int nclients=0, ncallbacks=0;
547 char *sourcehost=NULL;
548 _DtCmsRegistrationInfo *ptr;
549 _DtCmsRegistrationInfo *prev;
550 struct timeval timeout_tv;
552 boolean_t advance = B_TRUE;
555 * loop through the registration list looking for parties
556 * interested in this transaction.
559 for (ptr = prev = rlist; ptr != NULL; ) {
561 /* The caller will get the results of the rpc call.
562 * If he's registered on the callback list, don't call him -
563 * UNLESS the process id of his client differs from the
564 * original ticket. However, if the pid is a VOIDPID (-1),
565 * a version 2 client has registered and there's no way
566 * of telling which instance of the client it is. So,
567 * to be safe (avoid deadlock) we won't callback version
568 * 2 clients registered on version 3 daemons if their
569 * registration name entry matches the caller's. [Nanno]
572 if (version != ptr->versnum ||
573 (type && !(type & ptr->types)) ||
574 ((strcmp(source, ptr->client) == 0) &&
575 ((pid == ptr->pid) || (pid == -1 ) || (ptr->pid == -1)))) {
582 sourcehost = _DtCmsTarget2Location(ptr->client);
585 "%s: calling back %s on prog: %ld, vers: %ld, proc: %ld\n",
586 pgname, ptr->client, ptr->prognum, ptr->versnum,
589 cl = clnt_create(sourcehost, ptr->prognum, ptr->versnum, "udp");
591 /* deregister client if fails to create handle */
594 clnt_pcreateerror(sourcehost);
597 if (ptr == rlist) { /* top of list */
602 prev->next = ptr->next;
605 /* deregister client */
606 _DtCmsFreeRegistrationInfo(ptr);
611 /* Set timeout to zero so that the call
612 * returns right away.
614 timeout_tv.tv_sec = 0;
615 timeout_tv.tv_usec = 0;
618 /* for non-sun systems, clnt_call won't
619 * return right away unless timeout is set
620 * to zero using clnt_control(), (rpc bug?)
622 clnt_control(cl, CLSET_TIMEOUT,
623 (char *)&timeout_tv);
625 if (version == AGENTVERS) {
626 (void)clnt_call(cl, ptr->procnum,
627 (xdrproc_t)_DtCm_xdr_Table_Res_4, (char *)args,
628 (xdrproc_t)xdr_void, (char *)0, timeout_tv);
629 } else if (version == AGENTVERS_2) {
630 (void)clnt_call(cl, ptr->procnum,
631 (xdrproc_t)xdr_cmcb_update_callback_args,
632 (char *)args, (xdrproc_t)xdr_void, (char *)0,
652 fprintf(stderr, "%s: number of registered clients = %d\n",
654 fprintf(stderr, "%s: number of clients called back= %d\n",