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 /* $XConsortium: rtable4.c /main/5 1996/10/02 17:31: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.
32 * version 4 of calendar manager rpc protocol functions.
35 #include <EUSCompat.h>
44 #include <sys/param.h>
46 #include <sys/signal.h>
54 #include <sys/socket.h>
65 #include "cmscalendar.h"
72 #include "rpcextras.h"
73 #include "rtable4_tbl.i"
77 #include "convert5-4.h"
78 #include "convert4-5.h"
79 #include "cmsconvert.h"
89 /*****************************************************************************
90 * forward declaration of static functions used within the file
91 *****************************************************************************/
93 static Appt_4 * rtable_lookup_internal(_DtCmsCalendar *cal, char **p_src,
96 static Access_Status_4 csastat2accessstat(CSA_return_code stat);
98 static Registration_Status_4 csastat2regstat(CSA_return_code stat);
100 static Table_Status_4 csastat2tablestat(CSA_return_code stat);
102 static Table_Res_4 * table_lookup_next(Table_Args_4 *args,
103 struct svc_req *svcrq, caddr_t (* rb_func)(),
104 Appt_4 *(* rp_func)());
106 static Appt_4 * repeater_next_smaller(List_node *p_lnode, Id_4 *key);
108 static Appt_4 * repeater_next_larger(List_node *p_lnode, Id_4 *key);
110 /*****************************************************************************
111 * extern functions used in the library
112 *****************************************************************************/
115 * supports both data format
118 _DtCm_rtable_lookup_4_svc (Table_Args_4 *args, struct svc_req *svcrq)
120 static Table_Res_4 res;
121 CSA_return_code stat;
134 fprintf(stderr, "_DtCm_rtable_lookup_4_svc called\n");
136 if (res.res.Table_Res_List_4_u.a)
137 _DtCm_free_appt4(res.res.Table_Res_List_4_u.a);
139 res.status = access_other_4;
141 res.res.Table_Res_List_4_u.a = NULL;
142 if ((p_keys = args->args.Args_4_u.key) == NULL)
145 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
146 &access, &cal)) == CSA_SUCCESS) {
147 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
148 if (_DTCMS_HAS_V4_BROWSE_ACCESS(access))
149 res.status = access_ok_4;
151 res.status = access_failed_4;
152 } else if (!_DTCMS_HAS_VIEW_ACCESS(access)) {
153 res.status = access_failed_4;
156 res.status = access_ok_4;
158 res.status = csastat2accessstat(stat);
162 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
163 while (p_keys != NULL) {
164 cmskey.time = p_keys->appt_id.tick;
165 cmskey.id = p_keys->appt_id.key;
167 if ((stat = _DtCmsGetEntryAttrByKey(cal, user, access,
168 cmskey, 0, NULL, &entries, NULL))
171 if ((stat = _DtCmsCmsentriesToAppt4ForClient(
172 entries, &p_appt)) == CSA_SUCCESS) {
173 /* link to appt list */
174 h = _AddApptInOrder(h, p_appt);
176 _DtCm_free_cms_entries(entries);
179 if (stat != CSA_SUCCESS) {
180 res.status = csastat2accessstat(stat);
187 p_keys = p_keys->next;
190 res.res.Table_Res_List_4_u.a = h;
194 /* do lookup on old format calendar */
195 while (p_keys != NULL)
197 key = &p_keys->appt_id;
201 "_DtCm_rtable_lookup_4_svc at (key %ld)%s\n",
202 key->key, ctime(&key->tick));
205 p_appt = (Appt_4 *)rb_lookup(APPT_TREE(cal), (caddr_t)key);
206 if (p_appt == NULL) {
207 if ((p_appt = (Appt_4 *)hc_lookup(REPT_LIST(cal),
208 (caddr_t)key)) != NULL) {
209 if (!_DtCms_in_repeater(key, p_appt, B_FALSE))
214 if (p_appt != NULL) {
215 if (p_appt->appt_id.tick != key->tick) {
216 tmptick = p_appt->appt_id.tick;
217 p_appt->appt_id.tick = key->tick;
220 stat = _AddToLinkedAppts(p_appt, user, access,
223 if (tmptick) p_appt->appt_id.tick = tmptick;
225 if (stat != CSA_SUCCESS) {
230 res.status = csastat2accessstat(stat);
235 p_keys = p_keys->next;
238 res.res.Table_Res_List_4_u.a = h;
243 * supports old data format only
246 _DtCm_rtable_lookup_next_larger_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
251 fprintf(stderr, "_DtCm_rtable_lookup_next_larger_4_svc called\n");
253 res = table_lookup_next(args, svcrq, rb_lookup_next_larger,
254 repeater_next_larger);
259 * supports old data format only
262 _DtCm_rtable_lookup_next_smaller_4_svc(
264 struct svc_req *svcrq)
269 fprintf(stderr, "_DtCm_rtable_lookup_next_smaller_4_svc called\n");
271 res = table_lookup_next(args, svcrq, rb_lookup_next_smaller,
272 repeater_next_smaller);
277 * supports both data format
280 _DtCm_rtable_lookup_range_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
282 static Table_Res_4 res;
283 CSA_return_code stat;
289 fprintf(stderr, "_DtCm_rtable_lookup_range_4_svc called\n");
291 if (res.res.Table_Res_List_4_u.a)
292 _DtCm_free_appt4(res.res.Table_Res_List_4_u.a);
295 res.res.Table_Res_List_4_u.a = NULL;
297 res.status = access_other_4;
298 if (args->args.Args_4_u.range == NULL)
301 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
302 &access, &cal)) == CSA_SUCCESS) {
303 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
304 if (_DTCMS_HAS_V4_BROWSE_ACCESS(access))
305 res.status = access_ok_4;
307 res.status = access_failed_4;
310 res.status = csastat2accessstat(stat);
314 stat = _DtCmsLookupRangeV4(cal, user, access, args->args.Args_4_u.range,
315 B_TRUE, 0, 0, NULL, 0, NULL, NULL,
316 &res.res.Table_Res_List_4_u.a, NULL);
318 res.status = csastat2accessstat(stat);
323 * supports both data format
326 _DtCm_rtable_abbreviated_lookup_range_4_svc(
328 struct svc_req *svcrq)
330 static Table_Res_4 res;
331 CSA_return_code stat;
338 "_DtCm_rtable_abbreviated_lookup_range_4_svc called\n");
340 if (res.res.Table_Res_List_4_u.b)
341 _DtCm_free_abbrev_appt4(res.res.Table_Res_List_4_u.b);
344 res.res.Table_Res_List_4_u.b = NULL;
346 res.status = access_other_4;
347 if (args->args.Args_4_u.range == NULL)
350 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
351 &access, &cal)) == CSA_SUCCESS) {
352 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
353 if (_DTCMS_HAS_V4_BROWSE_ACCESS(access))
354 res.status = access_ok_4;
356 res.status = access_failed_4;
359 res.status = csastat2accessstat(stat);
363 stat = _DtCmsLookupRangeV4(cal, user, access, args->args.Args_4_u.range,
364 B_TRUE, 0, 0, NULL, 0, NULL, NULL, NULL,
365 &res.res.Table_Res_List_4_u.b);
367 res.status = csastat2accessstat(stat);
372 _DtCm_rtable_insert_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
374 static Table_Res_4 res;
376 CSA_return_code stat;
380 Appt_4 *ap, *appt, *prev=NULL, *a;
384 fprintf(stderr, "_DtCm_rtable_insert_4_svc called\n");
386 /* clean out left over */
387 if (res.res.Table_Res_List_4_u.a != NULL)
388 _DtCm_free_appt4(res.res.Table_Res_List_4_u.a);
390 res.status = access_other_4;
392 res.res.Table_Res_List_4_u.a = NULL;
394 /* check arguments */
395 if (args->target == NULL)
397 if ((ap = args->args.Args_4_u.appt) == NULL)
400 /* do some sanity checks before inserting : check appt data */
401 for (appt = args->args.Args_4_u.appt; appt != NULL; appt = appt->next)
403 /* ntimes should be 0 or positive */
404 if (appt->ntimes < 0 ||
405 (appt->period.period > single_4 && appt->ntimes == 0))
408 /* period beyond daysOfWeek is not supported */
409 if (appt->period.period > daysOfWeek_4) {
410 res.status = access_notsupported_4;
414 /* if weekmask of daysOfWeek appt is set incorrectly, return */
415 if (appt->period.period == daysOfWeek_4 &&
416 (appt->period.nth == 0 || appt->period.nth > 127))
420 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
421 &access, &cal)) == CSA_SUCCESS) {
422 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
423 if (!_DTCMS_HAS_V4_WRITE_ACCESS(access)) {
424 res.status = access_failed_4;
427 } else if (!_DTCMS_HAS_INSERT_ACCESS(access)) {
428 res.status = access_failed_4;
431 res.status = access_ok_4;
433 res.status = csastat2accessstat(stat);
437 /* make copy of the appointments */
438 /* this copy is used in the result and will be freed
439 * when this routine is called again
441 if ((appt = _DtCm_copy_appt4(args->args.Args_4_u.appt)) == NULL) {
447 while (appt != NULL) {
450 * we used to calculate the correct start day,
451 * but we should return an error instead
453 _DtCms_adjust_appt_startdate(appt);
455 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
456 /* convert to attributes */
457 if (_DtCmsAppt4ToCmsentry(args->target, appt, &entry,
461 /* null out readonly attributes */
462 _DtCm_free_cms_attribute_value(entry->attrs\
463 [CSA_ENTRY_ATTR_ORGANIZER_I].value);
464 entry->attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value = NULL;
465 _DtCm_free_cms_attribute_value(entry->attrs\
466 [CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].value);
467 entry->attrs[CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].\
470 if (_DtCmsCheckInitialAttributes(entry)) {
471 _DtCm_free_cms_entry(entry);
476 if (_DtCm_set_string_attrval(user, &entry->attrs\
477 [CSA_ENTRY_ATTR_ORGANIZER_I].value,
478 CSA_VALUE_CALENDAR_USER) != CSA_SUCCESS) {
479 _DtCm_free_cms_entry(entry);
483 /* insert entry and log it */
484 if (_DtCmsInsertEntryAndLog(cal, entry)) {
485 _DtCm_free_cms_entry(entry);
489 appt->appt_id.key = entry->key.id;
490 _DtCm_free_cms_entry(entry);
493 if ((a = _DtCm_copy_one_appt4(appt)) == NULL)
496 /* We don't trust the author field; we set our own. */
498 if ((a->author = strdup(user)) == NULL) {
503 /* Note, the key in appt will be set if its value is 0. */
504 if ((stat = _DtCmsInsertApptAndLog(cal, a)) != CSA_SUCCESS) {
505 res.status = csastat2accessstat(stat);
509 /* get the new key */
510 appt->appt_id.key = a->appt_id.key;
517 cal->modified = B_TRUE;
520 cal->rlist = _DtCmsDoV1Callback(cal->rlist, user, args->pid, ap);
522 for (appt = ap; appt != NULL; appt = appt->next) {
523 cal->rlist = _DtCmsDoInsertEntryCallback(cal->rlist,
524 cal->calendar, user, appt->appt_id.key,
528 res.status = access_ok_4;
529 res.res.Table_Res_List_4_u.a = ap;
535 cal->modified = B_TRUE;
536 /* some appts were inserted successfully */
537 res.status = access_partial_4;
539 res.res.Table_Res_List_4_u.a = ap;
542 cal->rlist = _DtCmsDoV1Callback(cal->rlist, user, args->pid,
544 for (appt = ap; appt != NULL; appt = appt->next) {
545 cal->rlist = _DtCmsDoInsertEntryCallback(cal->rlist,
547 appt->appt_id.key, args->pid);
551 /* first appt in bunch that failed */
552 res.status = csastat2accessstat(stat);
554 _DtCm_free_appt4(appt);
560 _DtCm_rtable_delete_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
562 static Table_Res_4 res;
564 CSA_return_code stat;
575 fprintf(stderr, "_DtCm_rtable_delete_4_svc called\n");
577 /* clean out left over */
578 if (res.res.Table_Res_List_4_u.a)
579 _DtCm_free_appt4(res.res.Table_Res_List_4_u.a);
581 res.status = access_other_4;
583 res.res.Table_Res_List_4_u.a = NULL;
585 /* check arguments */
586 if (args->target == NULL)
588 if ((p_keys = args->args.Args_4_u.uidopt) == NULL)
591 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
592 &access, &cal)) == CSA_SUCCESS) {
593 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
594 !_DTCMS_HAS_CHANGE_ACCESS(access)) {
595 res.status = access_failed_4;
599 res.status = csastat2accessstat(stat);
604 while (p_keys != NULL) {
607 fprintf (stderr, "Delete: (key %ld)%s\n",
609 ctime(&p_keys->appt_id.tick));
612 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
613 key.time = p_keys->appt_id.tick;
614 key.id = p_keys->appt_id.key;
616 if (p_keys->option == do_all_4)
617 stat = _DtCmsDeleteEntryAndLog(cal, user,
618 access, &key, &entry);
620 stat = _DtCmsDeleteInstancesAndLog(cal, user,
622 (p_keys->option == CSA_SCOPE_ONE ?
623 CSA_SCOPE_ONE : CSA_SCOPE_FORWARD),
626 if (stat == CSA_SUCCESS)
627 stat = _DtCm_cms_entry_to_appt4(entry, &a);
629 _DtCm_free_cms_entry(entry);
633 /* single or all in a repeating series */
634 if (p_keys->option == do_all_4)
635 stat = _DtCmsDeleteApptAndLog(cal, user,
636 access, &p_keys->appt_id, &a);
638 stat = _DtCmsDeleteApptInstancesAndLog(cal,
639 user, access, &p_keys->appt_id,
640 p_keys->option, NULL, &a);
644 if (stat == CSA_SUCCESS) {
645 if (p_keys->option != do_all_4)
646 APPT_TICK(a) = p_keys->appt_id.tick;
651 } else if (stat == CSA_X_DT_E_ENTRY_NOT_FOUND)
654 p_keys = p_keys->next;
658 cal->modified = B_TRUE;
661 cal->rlist = _DtCmsDoV1Callback(cal->rlist, user, args->pid, h);
662 for (a = h, p_keys = args->args.Args_4_u.uidopt;
663 a != NULL; a = a->next) {
664 while (a->appt_id.key != p_keys->appt_id.key)
665 p_keys = p_keys->next;
667 cal->rlist = _DtCmsDoDeleteEntryCallback(cal->rlist,
668 cal->calendar, user, a->appt_id.key,
670 (p_keys->option == do_all_4 ?
671 a->appt_id.tick : p_keys->appt_id.tick),
678 res.status = csastat2accessstat(stat);
680 res.status = (nf < n) ? access_failed_4 : access_ok_4;
682 res.status = access_partial_4;
684 res.status = access_ok_4;
686 res.res.Table_Res_List_4_u.a = h;
692 _DtCm_rtable_delete_instance_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
694 static Table_Res_4 res;
697 fprintf(stderr, "_DtCm_rtable_delete_instance_4_svc called\n");
699 res.status = access_notsupported_4;
701 res.res.Table_Res_List_4_u.a = NULL;
707 _DtCm_rtable_change_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
709 static Table_Res_4 res;
711 CSA_return_code stat;
718 cms_entry *entry, *oldentry, *newentry = NULL;
722 fprintf(stderr, "_DtCm_rtable_change_4_svc called\n");
724 /* clean out left over */
725 res.status = access_other_4;
727 res.res.Table_Res_List_4_u.a = NULL;
729 /* check arguments */
730 if (args->target == NULL)
732 if ((p_key = args->args.Args_4_u.apptid.oid) == NULL)
734 if ((newa = args->args.Args_4_u.apptid.new_appt) == NULL)
737 /* ntimes should be 0 or positive */
738 if (newa->ntimes < 0 ||
739 (newa->period.period > single_4 && newa->ntimes == 0))
742 /* period beyond daysOfWeek is not supported */
743 if (newa->period.period > daysOfWeek_4) {
744 res.status = access_notsupported_4;
748 /* if weekmask of daysOfWeek appt is not set correctly, return */
749 if (newa->period.period == daysOfWeek_4 &&
750 (newa->period.nth == 0 || newa->period.nth > 127))
753 option = args->args.Args_4_u.apptid.option;
754 if (option < do_all_4 || option > do_forward_4)
757 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
758 &access, &cal)) == CSA_SUCCESS) {
759 if ((cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
760 !_DTCMS_HAS_CHANGE_ACCESS(access)) ||
761 (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
762 !_DTCMS_HAS_V4_WRITE_ACCESS(access))) {
764 res.status = access_failed_4;
768 res.status = csastat2accessstat(stat);
772 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
773 /* convert to attributes */
774 if ((stat = _DtCmsAppt4ToCmsentry(args->target, newa, &entry,
775 B_TRUE)) == CSA_SUCCESS) {
777 key.time = p_key->tick;
780 /* null out readonly attributes */
781 _DtCm_free_cms_attributes(1,
782 &entry->attrs[CSA_ENTRY_ATTR_ORGANIZER_I]);
783 _DtCm_free_cms_attributes(1, &entry->attrs\
784 [CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I]);
785 _DtCm_free_cms_attributes(1,
786 &entry->attrs[CSA_ENTRY_ATTR_TYPE_I]);
789 if (option == do_all_4)
790 stat = _DtCmsUpdateEntry(cal, user, access,
791 &key, entry->num_attrs,
792 &entry->attrs[1], &oldentry, NULL);
794 stat = _DtCmsUpdateInstances(cal, user,
795 access, &key, (option == do_one_4 ?
796 CSA_SCOPE_ONE : CSA_SCOPE_FORWARD),
797 entry->num_attrs, &entry->attrs[1],
798 &oldentry, &newentry);
800 _DtCm_free_cms_entry(entry);
804 if (option == do_all_4)
805 stat = _DtCmsChangeAll(cal, user, access, p_key, newa,
808 stat = _DtCmsChangeSome(cal, user, access,p_key, newa,
812 if (stat == CSA_SUCCESS) {
813 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
814 tmpappt.appt_id.tick = oldentry->key.time;
815 tmpappt.appt_id.key = oldentry->key.id;
817 _DtCm_free_cms_entry(oldentry);
819 newa->appt_id.key = newentry->key.id;
820 _DtCm_free_cms_entry(newentry);
824 /* If the date/time is changed, we do a callback
825 * with the old and new appointments. Otherwise,
826 * we only do callback with the new appointmnt.
828 if (APPT_TICK(newa) == APPT_TICK(olda)) {
829 cal->rlist = _DtCmsDoV1Callback(cal->rlist, user,
833 cal->rlist = _DtCmsDoV1Callback(cal->rlist, user,
838 cal->rlist = _DtCmsDoUpdateEntryCallback(cal->rlist,
840 (newa->appt_id.key == olda->appt_id.key ?
841 0 : newa->appt_id.key),
842 olda->appt_id.key, option, (option == do_all_4 ?
843 olda->appt_id.tick : p_key->tick),
846 cal->modified = B_TRUE;
848 /* Return the new appointment. */
849 res.res.Table_Res_List_4_u.a = newa;
850 res.status = access_ok_4;
852 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION)
853 _DtCm_free_appt4(olda);
855 res.status = csastat2accessstat(stat);
861 _DtCm_rtable_change_instance_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
863 static Table_Res_4 res;
866 fprintf(stderr, "_DtCm_rtable_change_instance_4_svc called\n");
868 res.status = access_notsupported_4;
870 res.res.Table_Res_List_4_u.a = NULL;
876 _DtCm_rtable_lookup_next_reminder_4_svc(
878 struct svc_req *svcrq)
880 static Table_Res_4 res;
881 CSA_return_code stat;
885 Reminder_4 *p_reminder;
891 cms_reminder_ref *rems;
894 fprintf(stderr, "_DtCm_rtable_lookup_next_reminder_4_svc called\n");
896 /* clean up left over */
897 if (res.res.Table_Res_List_4_u.r)
898 _DtCm_free_reminder4(res.res.Table_Res_List_4_u.r);
900 res.status = access_other_4;
902 res.res.Table_Res_List_4_u.r = NULL;
904 if (args->target == NULL)
907 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
908 &access, &cal)) == CSA_SUCCESS) {
909 /* only user with owner rights can lookup reminders */
910 if (!(access & CSA_OWNER_RIGHTS)) {
912 res.status = access_failed_4;
916 res.status = csastat2accessstat(stat);
920 tick = args->args.Args_4_u.tick;
923 fprintf(stderr, "Next reminder after %s", ctime(&tick));
925 if (cal->fversion > 1) {
926 if ((stat = _DtCmsLookupReminder(cal->remq, tick, 0, NULL,
927 &rems)) == CSA_SUCCESS) {
928 stat = _DtCmsReminderRefToReminder(rems,
929 &res.res.Table_Res_List_4_u.r);
930 _DtCmsFreeReminderRef(rems);
934 stat = _DtCmsGetV4Reminders(cal, tick,
935 &res.res.Table_Res_List_4_u.r, NULL);
938 res.status = csastat2accessstat(stat);
942 extern Table_Status_4 *
943 _DtCm_rtable_check_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
945 static Table_Status_4 s;
946 CSA_return_code stat;
951 fprintf(stderr, "_DtCm_rtable_check_4_svc called\n");
953 if ((stat = _DtCmsGetCalendarByName(args->target, B_TRUE, &cal))
956 s = csastat2tablestat(stat);
960 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
961 s = tbl_notsupported_4;
964 rbstat = rb_check_tree (cal->tree);
966 rbstat = hc_check_list (cal->list);
977 extern Table_Status_4 *
978 _DtCm_rtable_flush_table_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
980 static Table_Status_4 s;
982 CSA_return_code stat;
996 fprintf (stderr, "rtable_flush_table\n");
998 if ((stat = _DtCmsGetCalendarByName(args->target, B_TRUE, &cal))
1000 s = csastat2tablestat(stat);
1004 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1005 s = tbl_notsupported_4;
1011 fprintf(stderr, "%s: before flush.. rbsize= %d\n", pgname,
1012 rb_size(APPT_TREE(cal))+hc_size(REPT_LIST(cal)));
1015 /* Flushing the single appointment tree. */
1017 key.tick = args->args.Args_4_u.tick;
1018 while (p_appt = (Appt_4 *) rb_lookup_next_larger(APPT_TREE(cal),
1020 p_node = rb_delete (APPT_TREE(cal),
1021 (caddr_t)&(p_appt->appt_id));
1025 _DtCm_free_appt4 ((Appt_4 *) p_node->data);
1030 /* Flushing the repeating appointment list */
1032 key.tick = args->args.Args_4_u.tick;
1033 p_lnode = cal->list->root;
1034 while (p_lnode != NULL)
1036 p_next = hc_lookup_next (p_lnode);
1037 p_appt = (Appt_4*)p_lnode->data;
1038 if (APPT_TICK(p_appt) > key.tick)
1041 _DtCm_free_appt4 (p_appt);
1042 (void) hc_delete_node (REPT_LIST(cal), p_lnode);
1050 fprintf (stderr, "%s: entries deleted= %d\n", pgname, n);
1051 fprintf (stderr, "%s: after flush.. rbsize= %d\n", pgname,
1052 rb_size(APPT_TREE(cal))+hc_size(REPT_LIST(cal)));
1059 _DtCm_rtable_size_4_svc(Table_Args_4 *args, struct svc_req *svcrq)
1061 /* must be static! */
1063 CSA_return_code stat;
1064 _DtCmsCalendar *cal;
1067 fprintf(stderr, "_DtCm_rtable_size_4_svc called\n");
1070 if ((stat = _DtCmsGetCalendarByName(args->target, B_TRUE, &cal))
1074 size = rb_size (APPT_TREE(cal)) + hc_size (REPT_LIST(cal));
1079 extern Registration_Status_4 *
1080 _DtCm_register_callback_4_svc(Registration_4 *r, struct svc_req *svcrq)
1082 static Registration_Status_4 regstat;
1083 CSA_return_code stat;
1085 _DtCmsCalendar *cal = NULL;
1086 _DtCmsRegistrationInfo *copy=NULL;
1089 fprintf(stderr, "_DtCm_register_callback_4_svc called\n");
1092 if (r->target == NULL) {
1097 if ((stat = _DtCmsGetClientInfo(svcrq, &source)) != CSA_SUCCESS) {
1098 regstat = csastat2regstat(stat);
1102 /* check if the target exists */
1103 if ((stat = _DtCmsGetCalendarByName(r->target, B_TRUE, &cal))
1105 regstat = csastat2regstat(stat);
1109 /* Check for duplicate registrations */
1110 if (_DtCmsGetRegistration(&(cal->rlist), source, r->prognum, r->versnum,
1111 r->procnum, r->pid) == NULL) {
1112 /* not registered */
1114 /* Make a copy of the callback info. */
1116 if ((copy = _DtCmsMakeRegistrationInfo(source, 0, r->prognum,
1117 r->versnum, r->procnum, r->pid)) == NULL) {
1122 /* Store it away so that it can later be called. */
1123 copy->next = cal->rlist;
1127 fprintf(stderr, "%s requested registration on %s. registered pid= %d\n",
1128 source, r->target, r->pid);
1129 _DtCmsListRegistration(cal->rlist,
1132 regstat = registered_4;
1135 /* already registered */
1136 regstat = registered_4;
1141 /* de-register an rpc callback proc from the client */
1142 extern Registration_Status_4 *
1143 _DtCm_deregister_callback_4_svc(Registration_4 *r, struct svc_req *svcrq)
1145 static Registration_Status_4 regstat;
1146 CSA_return_code stat;
1147 _DtCmsCalendar *cal;
1149 _DtCmsRegistrationInfo *p = NULL, *q = NULL;
1152 fprintf(stderr, "_DtCm_deregister_callback_4_svc called\n");
1154 if (r->target == NULL) {
1159 if ((stat = _DtCmsGetClientInfo(svcrq, &source)) != CSA_SUCCESS) {
1160 regstat = csastat2regstat(stat);
1164 if ((stat = _DtCmsGetCalendarByName(r->target, B_FALSE, &cal))
1166 regstat = csastat2regstat(stat);
1179 * 1) if the name of the caller requesting deregistration
1180 * is the same as the original caller who requested
1181 * requested registration, and
1182 * 2) if the (transient) program, version, & procnum match
1183 * the original registration, and
1184 * 3) if the process id of the client matches the
1185 * orignal registration
1187 * ... only then is it ok to decommission the ticket.
1191 if ((strcmp(p->client, source)==0) &&
1192 (p->prognum==r->prognum) &&
1193 (p->versnum==r->versnum) &&
1194 (p->procnum==r->procnum) &&
1195 (p->pid==r->pid)) { /* a match */
1197 fprintf(stderr, "%s requested deregistration on %s. registered pid= %d\n", source, r->target, r->pid);
1200 cal->rlist = p->next;
1203 _DtCmsFreeRegistrationInfo(p);
1205 _DtCmsListRegistration(cal->rlist,
1208 regstat = deregistered_4;
1220 extern Access_Status_4 *
1221 _DtCm_rtable_set_access_4_svc(Access_Args_4 *args, struct svc_req *svcrq)
1223 /* must be static! */
1224 static Access_Status_4 s;
1225 CSA_return_code stat;
1228 _DtCmsCalendar *cal = NULL;
1231 fprintf(stderr, "_DtCm_rtable_set_access_4_svc called\n");
1235 if (args->target == NULL)
1238 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
1239 &access, &cal)) == CSA_SUCCESS) {
1240 /* only user with owner rights can lookup reminders */
1241 if ((cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1242 !(access&(CSA_OWNER_RIGHTS|CSA_CHANGE_CALENDAR_ATTRIBUTES)))
1243 || (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1244 !(access & CSA_OWNER_RIGHTS))) {
1246 s = access_failed_4;
1250 s = csastat2accessstat(stat);
1254 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1256 cms_attribute_value attrval;
1257 cms_access_entry *alist;
1259 if (args->access_list && (alist =
1260 _DtCmsConvertV4AccessList(args->access_list)) == NULL) {
1261 s = csastat2accessstat(CSA_E_INSUFFICIENT_MEMORY);
1265 attr.name.name = CSA_CAL_ATTR_ACCESS_LIST;
1267 attr.value = &attrval;
1268 attrval.type = CSA_VALUE_ACCESS_LIST;
1269 attrval.item.access_list_value = alist;
1271 stat = _DtCmsUpdateCalAttributesAndLog(cal, 1, &attr, access);
1273 stat = _DtCmsSetV4AccessListAndLog(cal, args->access_list);
1276 if ((s = csastat2accessstat(stat)) == access_ok_4) {
1280 attr.name.name = CSA_CAL_ATTR_ACCESS_LIST;
1281 cal->rlist = _DtCmsDoUpdateCalAttrsCallback(cal->rlist,
1282 cal->calendar, user, 1, &attr, -1);
1288 extern Access_Args_4 *
1289 _DtCm_rtable_get_access_4_svc(Access_Args_4 *args, struct svc_req *svcrq)
1291 static Access_Args_4 res;
1292 CSA_return_code stat;
1293 _DtCmsCalendar *cal;
1294 char *target, *user;
1296 boolean_t useronly = B_FALSE;
1297 cms_access_entry aentry;
1300 fprintf(stderr, "_DtCm_rtable_get_access_4_svc called\n");
1302 if (res.target != NULL)
1304 if (res.access_list)
1305 _DtCm_free_access_list4(res.access_list);
1308 res.access_list = (Access_Entry_4 *) NULL;
1310 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
1311 &access, &cal)) == CSA_SUCCESS) {
1312 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1313 !_DTCMS_HAS_VIEW_CALENDAR_ATTR_ACCESS(access)) {
1320 if (cal->fversion > 1) {
1323 aentry.rights = access;
1325 res.access_list = _DtCmsConvertV5AccessList(&aentry,
1328 res.access_list = _DtCmsConvertV5AccessList(
1329 cal->attrs[CSA_CAL_ATTR_ACCESS_LIST_I].\
1330 value->item.access_list_value, B_TRUE);
1333 res.access_list = _DtCmsCalendarAccessList(cal);
1335 _DtCmsShowAccessList (res.access_list);
1338 res.target = strdup(args->target);
1343 extern Table_Res_4 *
1344 _DtCm_rtable_abbreviated_lookup_key_range_4_svc(
1346 struct svc_req *svcrq)
1348 static Table_Res_4 res;
1349 CSA_return_code stat;
1350 _DtCmsCalendar *cal;
1353 Keyrange_4 *p_range;
1354 Abb_Appt_4 *abbr_r = NULL;
1358 "_DtCm_rtable_abbreviated_lookup_key_range_4_svc called\n");
1360 if (res.res.Table_Res_List_4_u.b)
1361 _DtCm_free_abbrev_appt4(res.res.Table_Res_List_4_u.b);
1364 res.res.Table_Res_List_4_u.b = NULL;
1366 res.status = access_other_4;
1367 if ((p_range = args->args.Args_4_u.keyrange) == NULL)
1370 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
1371 &access, &cal)) == CSA_SUCCESS) {
1372 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1373 if (_DTCMS_HAS_V4_BROWSE_ACCESS(access))
1374 res.status = access_ok_4;
1376 res.status = access_failed_4;
1379 res.status = csastat2accessstat(stat);
1383 while (p_range != NULL)
1386 if ((stat = _DtCmsLookupKeyrangeV4(cal, user, access,
1387 B_FALSE, B_TRUE, p_range->tick1, p_range->tick2, 0, 0,
1388 p_range->key, NULL, 0, NULL, NULL, NULL, &abbr_r))
1393 p_range = p_range->next;
1396 if (stat == CSA_SUCCESS)
1397 res.res.Table_Res_List_4_u.b = abbr_r;
1399 _DtCm_free_abbrev_appt4(abbr_r);
1401 res.status = csastat2accessstat(stat);
1406 _DtCm_rtable_gmtoff_4_svc(void *args, struct svc_req *svcrq)
1409 extern long timezone;
1412 fprintf(stderr, "_DtCm_rtable_gmtoff_4_svc called\n");
1418 extern Table_Status_4 *
1419 _DtCm_rtable_create_4_svc(Table_Op_Args_4 *args, struct svc_req *svcrq)
1421 static Table_Status_4 res;
1422 CSA_return_code stat;
1423 _DtCmsCalendar *cal;
1428 char *id, *user, *domain;
1429 Access_Entry_4 aentry;
1432 fprintf(stderr, "_DtCm_rtable_create_4_svc called\n");
1435 if ((stat = _DtCmsGetClientInfo(svcrq, &source)) != CSA_SUCCESS) {
1436 res = csastat2tablestat(stat);
1440 /* check domain if domain info is available */
1441 /* only user in the local domain can create file */
1442 if (ptr = strchr(source, '.')) {
1444 fprintf(stderr, "rpc.cmsd: %s %s(target) and %s(sender)\n",
1445 "check domains, comparing",
1446 args->target, source);
1448 if ((domain = _DtCmsTarget2Domain(args->target)) != NULL) {
1450 if (!_DtCmIsSamePath(domain, ++ptr)) {
1458 if ((calname = _DtCmsTarget2Name(args->target)) == NULL)
1461 /* if the file is loaded in memory, the file already exists */
1462 if ((stat = _DtCmsGetCalendarByName(calname, B_FALSE, &cal))
1463 == CSA_SUCCESS && cal != NULL) {
1470 * If identifier of the calendar name is a user name,
1471 * make sure it's the same as sender.
1472 * format of calendar name assumed: identifier.name
1474 if ((id = _DtCmGetPrefix(calname, '.')) == NULL) {
1478 if ((user = _DtCmGetPrefix(source, '@')) == NULL) {
1484 if (getpwnam(id) && strcmp(user, id)) {
1493 if ((log = _DtCmsGetLogFN(calname)) == NULL)
1499 fprintf(stderr, "new file = '%s'\n", log);
1501 if ((stat = _DtCmsCreateLogV1(user, log)) == CSA_E_CALENDAR_EXISTS)
1503 else if (stat != CSA_SUCCESS)
1508 /* initialize the access list to be "WORLD", access_read_4 */
1511 aentry.access_type = access_read_4;
1512 if ((stat = _DtCmsAppendAccessByFN(log, access_read_4, &aentry))
1523 extern Table_Status_4 *
1524 _DtCm_rtable_remove_4_svc(Table_Op_Args_4 *args, struct svc_req *svcrq)
1526 static Table_Status_4 res;
1528 res = tbl_notsupported_4;
1532 extern Table_Status_4 *
1533 _DtCm_rtable_rename_4_svc(Table_Op_Args_4 *args, struct svc_req *svcrq)
1535 static Table_Status_4 res;
1537 res = tbl_notsupported_4;
1542 _DtCm_rtable_ping_4_svc(void *args, struct svc_req *svcrq)
1547 fprintf(stderr, "_DtCm_rtable_ping_4_svc called\n");
1549 return((void *)&dummy); /* for RPC reply */
1553 initrtable4(program_handle ph)
1555 ph->program_num = TABLEPROG;
1556 ph->prog[TABLEVERS_4].vers = &tableprog_4_table[0];
1557 ph->prog[TABLEVERS_4].nproc = sizeof(tableprog_4_table)/sizeof(tableprog_4_table[0]);
1560 /******************************************************************************
1561 * static functions used within the file
1562 ******************************************************************************/
1565 append_exception_list(Appt_4 *p_appt, int ordinal)
1567 Exception_4 p_excpt;
1571 if ((p_excpt = (Exception_4)calloc(1, sizeof(*p_excpt))) == NULL)
1573 p_excpt->ordinal = ordinal;
1575 p_ex = p_appt->exception;
1576 while (p_ex != NULL)
1578 /* Exception list is in descending order for faster access */
1579 if (ordinal > p_ex->ordinal)
1586 p_excpt->next = p_appt->exception;
1587 p_appt->exception = p_excpt;
1591 p_excpt->next = p_prev->next;
1592 p_prev->next = p_excpt;
1599 rtable_lookup_internal(_DtCmsCalendar *cal, char **p_src, Id_4 *key)
1602 Privacy_Level_4 p_level;
1604 /* Check if it hits a single appointment */
1605 p_appt = (Appt_4 *)rb_lookup(APPT_TREE(cal), (caddr_t)key);
1607 if (p_appt != NULL) {
1608 switch (_DtCmCheckPrivacyLevel(p_src, p_appt)) {
1610 p_appt = _DtCm_copy_one_appt4(p_appt);
1613 p_appt = _DtCm_copy_semiprivate_appt4(p_appt);
1621 /* Check if it hits an event in any repeating appointment */
1622 p_appt = (Appt_4 *) hc_lookup (REPT_LIST(cal), (caddr_t)key);
1624 if (p_appt != NULL) {
1625 if ((p_level = _DtCmCheckPrivacyLevel(p_src, p_appt)) != private_4)
1627 if (_DtCms_in_repeater (key, p_appt, B_FALSE)) {
1628 if (p_level == public_4)
1629 p_appt = _DtCm_copy_one_appt4(p_appt);
1631 p_appt = _DtCm_copy_semiprivate_appt4(p_appt);
1632 APPT_TICK(p_appt) = key->tick;
1642 repeater_next_larger(List_node *p_lnode, Id_4 *key)
1647 Appt_4 *p_save = NULL;
1648 Id_4 id, next_larger_id;
1652 next_larger_id.tick = MAXINT;
1653 next_larger_id.key = MAXINT;
1654 while (p_lnode != NULL)
1656 p_appt = (Appt_4*)p_lnode->data;
1658 /* check last tick: if it's before the lookup range, skip it */
1659 if (p_lnode->lasttick == 0)
1660 p_lnode->lasttick = _DtCms_last_tick_v4(APPT_TICK(p_appt),
1661 p_appt->period, p_appt->ntimes);
1663 if ((p_lnode->lasttick < key->tick) ||
1664 (p_lnode->lasttick == key->tick &&
1665 APPT_KEY(p_appt) <= key->key)) {
1666 p_lnode = hc_lookup_next(p_lnode);
1670 period = p_appt->period;
1671 ntimes = _DtCms_get_ninstance_v4(p_appt);
1672 id.tick = _DtCms_closest_tick_v4(key->tick, APPT_TICK(p_appt),
1675 id.key = APPT_KEY(p_appt);
1676 while (++ord <= ntimes)
1678 if ((id.tick < key->tick) || (id.tick == key->tick &&
1679 id.key <= key->key))
1680 id.tick = _DtCms_next_tick_v4 (id.tick, period);
1681 else if (!_DtCms_marked_4_cancellation (p_appt, ord)) {
1682 if ((id.tick < next_larger_id.tick) ||
1683 (id.tick == next_larger_id.tick &&
1684 id.key < next_larger_id.key))
1686 next_larger_id = id;
1691 id.tick = _DtCms_next_tick_v4(id.tick, period);
1693 p_lnode = hc_lookup_next (p_lnode);
1699 APPT_TICK(&appt) = next_larger_id.tick;
1707 repeater_next_smaller(List_node *p_lnode, Id_4 *key)
1712 Appt_4 *p_save = NULL;
1713 Id_4 id, next_smaller_id;
1717 next_smaller_id.tick = 0;
1718 next_smaller_id.key = 0;
1719 while (p_lnode != NULL)
1721 p_appt = (Appt_4*)p_lnode->data;
1723 ntimes = _DtCms_get_ninstance_v4(p_appt);
1724 period = p_appt->period;
1725 id.tick = APPT_TICK(p_appt);
1726 id.key = APPT_KEY(p_appt);
1728 /* Very inefficient loop because it has to check if each
1729 * instance is cancelled. If there is a function to calculate
1730 * last tick, this loop can be rewritten in an efficient way.
1732 while ((++ord <= ntimes) && (id.tick <= key->tick))
1734 if (id.tick == key->tick && id.key >= key->key)
1735 /* this will get us out of the loop */
1736 /* faster than continue. */
1737 id.tick = _DtCms_next_tick_v4 (id.tick, period);
1739 if (!_DtCms_marked_4_cancellation (p_appt, ord)) {
1740 if ((id.tick > next_smaller_id.tick) ||
1741 (id.tick == next_smaller_id.tick &&
1742 id.key > next_smaller_id.key))
1744 next_smaller_id = id;
1748 id.tick = _DtCms_next_tick_v4 (id.tick, period);
1752 p_lnode = hc_lookup_next (p_lnode);
1758 APPT_TICK(&appt) = next_smaller_id.tick;
1765 static Table_Res_4 *
1768 struct svc_req *svcrq,
1769 caddr_t (* rb_func)(),
1770 Appt_4 *(* rp_func)())
1772 static Table_Res_4 res;
1773 CSA_return_code stat;
1774 Privacy_Level_4 p_level;
1776 _DtCmsCalendar *cal;
1782 if (res.res.Table_Res_List_4_u.a)
1783 _DtCm_free_appt4(res.res.Table_Res_List_4_u.a);
1785 res.status = access_other_4;
1787 res.res.Table_Res_List_4_u.a = NULL;
1789 switch (args->args.tag) {
1791 key.tick = args->args.Args_4_u.tick;
1795 key = args->args.Args_4_u.key->appt_id;
1801 if ((stat = _DtCmsV4LoadAndCheckAccess(svcrq, args->target, &user,
1802 &access, &cal)) == CSA_SUCCESS) {
1803 if (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1804 if (_DTCMS_HAS_V4_BROWSE_ACCESS(access))
1805 res.status = access_ok_4;
1807 res.status = access_failed_4;
1810 res.status = csastat2accessstat(stat);
1814 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1815 res.status = access_notsupported_4;
1819 p_appt = (Appt_4 *) (*rb_func) (APPT_TREE(cal), &key);
1820 p_appt1 = (*rp_func) (REPT_LIST(cal)->root, &key);
1822 if (p_appt1 != NULL) {
1823 if (rb_func == rb_lookup_next_larger) {
1824 if ((p_appt==NULL) ||
1825 (APPT_TICK(p_appt) > APPT_TICK(p_appt1)) ||
1826 ((APPT_TICK(p_appt) == APPT_TICK(p_appt1)) &&
1827 (APPT_KEY(p_appt) > APPT_KEY(p_appt1)))) {
1831 if ((p_appt==NULL) ||
1832 (APPT_TICK(p_appt) < APPT_TICK(p_appt1)) ||
1833 ((APPT_TICK(p_appt) == APPT_TICK(p_appt1)) &&
1834 (APPT_KEY(p_appt) < APPT_KEY(p_appt1)))) {
1840 if (p_appt != NULL) {
1841 switch (_GetAccessLevel(user, access, p_appt)) {
1843 p_appt = _DtCm_copy_one_appt4(p_appt);
1846 p_appt = _DtCm_copy_semiprivate_appt4(p_appt);
1854 res.res.Table_Res_List_4_u.a = p_appt;
1858 static Access_Status_4
1859 csastat2accessstat(CSA_return_code stat)
1863 return (access_ok_4);
1864 case CSA_E_CALENDAR_EXISTS:
1865 return (access_exists_4);
1866 case CSA_E_CALENDAR_NOT_EXIST:
1867 return (access_notable_4);
1868 case CSA_E_INSUFFICIENT_MEMORY:
1869 case CSA_E_NO_AUTHORITY:
1870 return (access_failed_4);
1871 case CSA_X_DT_E_BACKING_STORE_PROBLEM:
1872 case CSA_E_DISK_FULL:
1873 return (access_incomplete_4);
1874 case CSA_E_NOT_SUPPORTED:
1875 return (access_notsupported_4);
1876 case CSA_E_INVALID_PARAMETER:
1878 case CSA_X_DT_E_ENTRY_NOT_FOUND:
1880 return (access_other_4);
1884 static Table_Status_4
1885 csastat2tablestat(CSA_return_code stat)
1890 case CSA_E_CALENDAR_EXISTS:
1891 return (tbl_exist_4);
1892 case CSA_E_CALENDAR_NOT_EXIST:
1894 case CSA_E_NOT_SUPPORTED:
1895 return (tbl_notsupported_4);
1897 case CSA_E_INSUFFICIENT_MEMORY:
1898 case CSA_E_INVALID_PARAMETER:
1904 static Registration_Status_4
1905 csastat2regstat(CSA_return_code stat)
1908 case CSA_E_CALENDAR_NOT_EXIST:
1909 return(reg_notable_4);