Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / programs / dtcm / server / cmsfunc.c
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 /* $XConsortium: cmsfunc.c /main/4 1995/11/09 12:42:12 rswiston $ */
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
31 #include <EUSCompat.h>
32 #include <stdio.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <time.h>
38 #include <sys/resource.h>
39 #include <rpc/rpc.h>
40 #include <dirent.h>
41 #include "csa.h"
42 #include "cm.h"
43 #include "rtable4.h"
44 #include "attr.h"
45 #include "access.h"
46 #include "cmscalendar.h"
47 #include "updateattrs.h"
48 #include "cmsdata.h"
49 #include "cmsentry.h"
50 #include "match.h"
51 #include "rpcextras.h"
52 #include "v5ops.h"
53 #include "v4ops.h"
54 #include "iso8601.h"
55 #include "log.h"
56 #include "lutil.h"
57 #include "cm_tbl.i"
58 #include "callback.h"
59 #include "insert.h"
60 #include "update.h"
61 #include "delete.h"
62 #include "lookup.h"
63 #include "misc.h"
64 #include "convert4-5.h"
65 #include "convert5-4.h"
66 #include "appt4.h"
67 #include "cmsconvert.h"
68
69 extern int debug;
70
71 /******************************************************************************
72  * forward declaration of static functions used within the file
73  ******************************************************************************/
74
75 static CSA_return_code _DtCmsCreateCallog(char *user, cms_create_args *args,
76                                         _DtCmsCalendar **cal);
77 static CSA_return_code _ListCalendarNames(uint *num_names, char ***names);
78 static void * _grow_char_array(void *ptr, uint oldcount, uint newcount);
79 static void _free_char_array(uint num_elem, char **ptr);
80 static CSA_return_code _DtCmsGetOldCalAttrNames(_DtCmsCalendar *cal,
81                                 uint *num_names_r, cms_attr_name **names_r);
82
83 /*****************************************************************************
84  * extern functions used in the library
85  *****************************************************************************/
86
87 extern void *
88 cms_ping_5_svc(void *args, struct svc_req *svcrq)
89 {
90         if (debug)
91                 fprintf(stderr, "cms_ping_5_svc called\n");
92
93         return(NULL); /* for RPC reply */
94 }
95
96
97 extern cms_list_calendars_res *
98 cms_list_calendars_5_svc(void *dummy, struct svc_req *svcrq)
99 {
100         static cms_list_calendars_res   res;
101
102         if (debug)
103                 fprintf(stderr, "cms_list_calendars_5_svc called\n");
104
105         if (res.num_names > 0) {
106                 _free_char_array(res.num_names, res.names);
107                 res.num_names = 0;
108         }
109
110         res.stat = _ListCalendarNames(&res.num_names, &res.names);
111
112         return (&res);
113 }
114
115 extern  cms_open_res *
116 cms_open_calendar_5_svc(cms_open_args *args, struct svc_req *svcrq)
117 {
118         static cms_open_res     res;
119         static char             sversion[80];
120         _DtCmsCalendar          *cal;
121         char                    *user;
122
123         if (debug)
124                 fprintf(stderr, "cms_open_calendar_5_svc called\n");
125
126         if (res.num_attrs > 0) {
127                 _DtCm_free_cms_attributes(res.num_attrs, res.attrs);
128                 free(res.attrs);
129                 res.num_attrs = 0;
130         }
131
132         /* check parameter */
133         if (args->cal == NULL) {
134                 res.stat = CSA_E_INVALID_PARAMETER;
135                 return (&res);
136         }
137
138         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
139             &res.user_access, &cal)) == CSA_SUCCESS) {
140
141                 res.svr_vers = TABLEVERS;
142
143                 if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
144
145                         res.file_vers = cal->fversion;
146
147                 } else {
148                         /* old format data */
149                         res.file_vers = _DtCM_FIRST_EXTENSIBLE_DATA_VERSION - 1;
150                 }
151
152                 /* return attribute names */
153                 res.stat = _DtCmsGetAllCalAttrs(cal, &res.num_attrs,
154                                         &res.attrs, B_FALSE);
155         }
156
157         if (res.stat == CSA_SUCCESS) {
158                 /* do callbacks */
159                 cal->rlist = _DtCmsDoOpenCalCallback(cal->rlist,
160                                 cal->calendar, user, args->pid);
161         }
162
163
164         return (&res);
165 }
166
167 extern  CSA_return_code *
168 cms_create_calendar_5_svc(cms_create_args *args, struct svc_req *svcrq)
169 {
170         static CSA_return_code  res;
171         _DtCmsCalendar          *cal;
172         char                    *user;
173
174         if (debug)
175                 fprintf(stderr, "cms_create_calendar_5_svc called\n");
176
177         /* check parameter */
178         if (args->cal == NULL) {
179                 res = CSA_E_INVALID_PARAMETER;
180                 return (&res);
181         }
182
183         /* need to check whether we know about the sender,
184          * if not, fail the request
185          */
186         if ((res = _DtCmsGetClientInfo(svcrq, &user)) != CSA_SUCCESS) {
187                 return (&res);
188         }
189
190         if ((res = _DtCm_check_cal_cms_attributes(_DtCMS_VERSION4,
191             args->num_attrs, args->attrs, user, args->cal, B_TRUE, B_TRUE,
192             B_FALSE)) != CSA_SUCCESS)
193                 return (&res);
194
195         if ((res = _DtCmsGetCalendarByName(args->cal, B_FALSE, &cal))
196             == CSA_SUCCESS && cal != NULL) {
197
198                 res = CSA_E_CALENDAR_EXISTS;
199
200         } else {
201
202                 /* create callog file for new calendar */
203                 res = _DtCmsCreateCallog(user, args, &cal);
204         }
205
206         return (&res);
207 }
208
209 extern  CSA_return_code *
210 cms_remove_calendar_5_svc(cms_remove_args *args, struct svc_req *svcrq)
211 {
212         static CSA_return_code  res;
213         _DtCmsCalendar          *cal;
214         char                    *user;
215         uint                    access;
216
217         if (debug)
218                 fprintf(stderr, "cms_remove_calendar_5_svc called\n");
219
220         if ((res = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
221             &access, &cal)) != CSA_SUCCESS)
222                 return (&res);
223
224         if (!(access & CSA_OWNER_RIGHTS)) {
225
226                 res = CSA_E_NO_AUTHORITY;
227
228         } else {
229
230                 /* move callog.name file to calrm.name */
231                 res = _DtCmsRemoveLog(cal->calendar, user);
232
233                 if (res != CSA_SUCCESS)
234                         return (&res);
235
236                 /* do callbacks */
237                 cal->rlist = _DtCmsDoRemoveCalCallback(cal->rlist,
238                                 cal->calendar, user, args->pid);
239
240                 /* free up internal structures */
241                 _DtCmsFreeCalendar(cal);
242         } 
243
244         return (&res);
245 }
246
247 extern  CSA_return_code *
248 cms_register_5_svc(cms_register_args *args, struct svc_req *svcrq)
249 {
250         static CSA_return_code  res;
251         char                    *user;
252         _DtCmsCalendar          *cal;
253         _DtCmsRegistrationInfo  *rinfo;
254
255         if (debug)
256                 fprintf(stderr, "cms_register_5_svc called\n");
257
258         if (args->cal == NULL ||
259             args->update_type >= (CSA_CB_ENTRY_UPDATED << 1)) {
260                 res = CSA_E_INVALID_PARAMETER;
261                 return (&res);
262         }
263
264         if ((res = _DtCmsGetClientInfo(svcrq, &user)) != CSA_SUCCESS)
265                 return (&res);
266
267         if ((res = _DtCmsGetCalendarByName(args->cal, B_TRUE, &cal))
268             != CSA_SUCCESS)
269                 return (&res);
270
271         if ((rinfo = _DtCmsGetRegistration(&(cal->rlist), user, args->prognum,
272             args->versnum, args->procnum, args->pid)) == NULL) {
273                 /* this client has not registered */
274
275                 if ((rinfo = _DtCmsMakeRegistrationInfo(user,
276                     args->update_type, args->prognum, args->versnum,
277                     args->procnum, args->pid)) == NULL) {
278                         res = CSA_E_INSUFFICIENT_MEMORY;
279                         return (&res);
280                 }
281
282                 /* put in the calendar's registration list */
283                 rinfo->next = cal->rlist;
284                 cal->rlist = rinfo;
285         } else {
286                 if (debug) {
287                         fprintf(stderr, "%s registered on %s, old types = %d\n",
288                                 user, args->cal, rinfo->types);
289                 }
290
291                 /* add new type to the registration */
292                 rinfo->types = rinfo->types | args->update_type;
293         }
294
295         if (debug) {
296                 fprintf(stderr, "%s registered on %s, types = %d\n",
297                         user, args->cal, rinfo->types);
298         }
299
300         res = CSA_SUCCESS;
301         return (&res);
302 }
303
304 extern  CSA_return_code *
305 cms_unregister_5_svc(cms_register_args *args, struct svc_req *svcrq)
306 {
307         static CSA_return_code  res;
308         char                    *user;
309         _DtCmsCalendar          *cal;
310         _DtCmsRegistrationInfo  *rinfo;
311
312         if (debug)
313                 fprintf(stderr, "cms_unregister_5_svc called\n");
314
315         if (args->cal == NULL ||
316             args->update_type >= (CSA_CB_ENTRY_UPDATED << 1)) {
317                 res = CSA_E_INVALID_PARAMETER;
318                 return (&res);
319         }
320
321         if ((res = _DtCmsGetClientInfo(svcrq, &user)) != CSA_SUCCESS)
322                 return (&res);
323
324         if ((res = _DtCmsGetCalendarByName(args->cal, B_FALSE, &cal))
325             != CSA_SUCCESS)
326                 return (&res);
327
328         if (cal == NULL || (rinfo = _DtCmsGetRegistration(&(cal->rlist), user,
329             args->prognum, args->versnum, args->procnum, args->pid)) == NULL) {
330                 res = CSA_E_CALLBACK_NOT_REGISTERED;
331                 return (&res);
332         }
333
334         /* update registration info */
335         if (debug) {
336                 fprintf(stderr, "%s registered on %s, old types = %d\n",
337                         user, args->cal, rinfo->types);
338         }
339
340         /* registered bits are cleared, unregistered bits are ignored */
341         rinfo->types = (rinfo->types | args->update_type) ^ args->update_type;
342
343         if (debug) {
344                 fprintf(stderr, "%s unregistered types %d on %s, new types = %d\n",
345                         user, args->update_type, args->cal, rinfo->types);
346         }
347
348         if (rinfo->types == 0) {
349                 cal->rlist = _DtCmsRemoveRegistration(cal->rlist, rinfo);
350         }
351
352         res = CSA_SUCCESS;
353         return (&res);
354 }
355
356 extern  cms_enumerate_calendar_attr_res *
357 cms_enumerate_calendar_attr_5_svc(buffer *args, struct svc_req *svcrq)
358 {
359         static cms_enumerate_calendar_attr_res  res;
360         _DtCmsCalendar          *cal;
361         char                    *user;
362         uint                    access;
363
364
365         if (debug)
366                 fprintf(stderr, "cms_enumerate_calendar_attr_5_svc called\n");
367
368         if (res.num_names > 0) {
369                 _DtCmsFreeCmsAttrNames(res.num_names, res.names);
370                 res.num_names = 0;
371         }
372
373         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, *args, &user,
374             &access, &cal)) != CSA_SUCCESS)
375                 return (&res);
376
377         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
378                 if (!_DTCMS_HAS_VIEW_CALENDAR_ATTR_ACCESS(access)) {
379                         res.stat = CSA_E_NO_AUTHORITY;
380                         return (&res);
381                 }
382
383                 res.stat = _DtCmsGetCalAttrNames(cal, &res.num_names,
384                                 &res.names);
385         } else {
386                 res.stat = _DtCmsGetOldCalAttrNames(cal, &res.num_names,
387                                 &res.names);
388         }
389
390         return (&res);
391 }
392
393 extern  cms_get_cal_attr_res *
394 cms_get_calendar_attr_5_svc(cms_get_cal_attr_args *args, struct svc_req *svcrq)
395 {
396         static cms_get_cal_attr_res     res;
397         _DtCmsCalendar          *cal;
398         char                    *user;
399         uint                    access;
400
401         if (debug)
402                 fprintf(stderr, "cms_get_calendar_attr_5_svc called\n");
403
404         if (res.num_attrs > 0) {
405                 _DtCm_free_cms_attributes(res.num_attrs, res.attrs);
406                 free(res.attrs);
407                 res.num_attrs = 0;
408         }
409
410         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
411             &access, &cal)) != CSA_SUCCESS)
412                 return (&res);
413
414         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
415             !_DTCMS_HAS_VIEW_CALENDAR_ATTR_ACCESS(access)) {
416                 res.stat = CSA_E_NO_AUTHORITY;
417                 return (&res);
418         }
419
420         if (args->num_names > 0)
421                 res.stat = _DtCmsGetCalAttrsByName(cal, args->num_names,
422                                 args->names, &res.num_attrs, &res.attrs);
423         else
424                 res.stat = _DtCmsGetAllCalAttrs(cal, &res.num_attrs,
425                                 &res.attrs, B_TRUE);
426
427         return (&res);
428 }
429
430 extern  CSA_return_code *
431 cms_set_calendar_attr_5_svc(cms_set_cal_attr_args *args, struct svc_req *svcrq)
432 {
433         static CSA_return_code  res;
434         _DtCmsCalendar          *cal;
435         char                    *user;
436         uint                    access;
437
438         if (debug)
439                 fprintf(stderr, "cms_set_calendar_attr_5_svc called\n");
440
441         if ((res = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
442             &access, &cal)) != CSA_SUCCESS)
443                 return (&res);
444
445         if ((cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
446             !(access & CSA_OWNER_RIGHTS)) ||
447             (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
448             !(access & (CSA_OWNER_RIGHTS | CSA_INSERT_CALENDAR_ATTRIBUTES |
449             CSA_CHANGE_CALENDAR_ATTRIBUTES)))) {
450                 res = CSA_E_NO_AUTHORITY;
451                 return (&res);
452         }
453
454         /* check argument */
455         if (args->cal == NULL || args->num_attrs == 0) {
456                 res = CSA_E_INVALID_PARAMETER;
457                 return (&res);
458         }
459
460         /* check validity of attribute values */
461         if ((res = _DtCm_check_cal_cms_attributes(
462             (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ?
463             cal->fversion : _DtCM_FIRST_EXTENSIBLE_DATA_VERSION - 1),
464             args->num_attrs, args->attrs, NULL, NULL, B_TRUE, B_FALSE, B_TRUE))
465             != CSA_SUCCESS)
466                 return (&res);
467
468         if (cal->fversion >=_DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
469                 if ((res = _DtCmsUpdateCalAttributesAndLog(cal, args->num_attrs,
470                     args->attrs, access)) != CSA_SUCCESS)
471                 {
472                         return (&res);
473                 }
474         } else {
475                 int             i;
476                 Access_Entry_4  *v4list = NULL;
477
478                 /* for old format file, the only settable calendar attribute
479                  * is access list
480                  */
481                 for (i = args->num_attrs - 1; i >= 0; i--) {
482                         if (args->attrs[i].name.name)
483                                 break;
484                 }
485
486                 if (args->attrs[i].value == NULL ||
487                     args->attrs[i].value->item.access_list_value == NULL) {
488                         res = _DtCmsSetV4AccessListAndLog(cal, NULL);
489                 } else {
490                         if ((res = _DtCmsCmsAccessToV4Access(
491                             args->attrs[i].value->item.access_list_value,
492                             &v4list)) == CSA_SUCCESS)
493                         {
494                                 res = _DtCmsSetV4AccessListAndLog(cal, v4list);
495                         }
496                         free(v4list);
497                 }
498
499                 if (res != CSA_SUCCESS)
500                         return (&res);
501         }
502
503         /* do callback */
504         cal->rlist = _DtCmsDoUpdateCalAttrsCallback(cal->rlist, cal->calendar,
505                         user, args->num_attrs, args->attrs, args->pid);
506
507         /* reply */
508         res = CSA_SUCCESS;
509
510         return (&res);
511 }
512
513 extern  cms_archive_res *
514 cms_archive_5_svc(cms_archive_args *args, struct svc_req *svcrq)
515 {
516         static cms_archive_res res;
517
518         if (debug)
519                 fprintf(stderr, "cms_archive_5_svc called\n");
520
521         res.stat = CSA_E_NOT_SUPPORTED;
522         return (&res);
523 }
524
525 extern  CSA_return_code *
526 cms_restore_5_svc(cms_restore_args *args, struct svc_req *svcrq)
527 {
528         static CSA_return_code res;
529
530         if (debug)
531                 fprintf(stderr, "cms_restore_5_svc called\n");
532
533         res = CSA_E_NOT_SUPPORTED;
534         return (&res);
535 }
536
537 extern  cms_reminder_res *
538 cms_lookup_reminder_5_svc(cms_reminder_args *args, struct svc_req *svcrq)
539 {
540         static cms_reminder_res res;
541         _DtCmsCalendar          *cal;
542         char                    *user;
543         uint                    access;
544
545         if (debug)
546                 fprintf(stderr, "cms_lookup_reminder_5_svc called\n");
547
548         if (res.rems != NULL) {
549                 _DtCmsFreeReminderRef(res.rems);
550                 res.rems = NULL;
551         }
552
553         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
554             &access, &cal)) != CSA_SUCCESS)
555                 return (&res);
556
557         if ((access & CSA_OWNER_RIGHTS) == 0) {
558                 res.stat = CSA_E_NO_AUTHORITY;
559                 return (&res);
560         }
561
562         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
563                 res.stat = _DtCmsLookupReminder(cal->remq, args->tick,
564                                 args->num_names, args->names, &res.rems);
565         } else {
566                 Reminder_4      *v4rem;
567                 _DtCmsEntryId   *ids;
568
569                 if ((res.stat = _DtCmsGetV4Reminders(cal, time(0), &v4rem,
570                     &ids)) == CSA_SUCCESS) {
571                         res.stat = _DtCmsV4ReminderToReminderRef(cal->calendar,
572                                         v4rem, ids, &res.rems);
573                         _DtCm_free_reminder4(v4rem);
574                         _DtCmsFreeEntryIds(ids);
575                 }
576         }
577
578         return (&res);
579 }
580
581 extern  cms_entries_res *
582 cms_lookup_entries_5_svc(cms_lookup_entries_args *args, struct svc_req *svcrq)
583 {
584         static cms_entries_res  res;
585         _DtCmsCalendar          *cal;
586         char                    *user;
587         uint                    access;
588         time_t                  start1, start2, end1, end2;
589         long                    id = 0;
590         boolean_t               no_match;
591         boolean_t               no_start_time_range, no_end_time_range;
592         CSA_uint32              hnum;
593         cms_attribute           *hattrs;
594         CSA_enum                *hops;
595
596         if (debug)
597                 fprintf(stderr, "cms_lookup_entries_5_svc called\n");
598
599         if (res.entries) {
600                 _DtCm_free_cms_entries(res.entries);
601                 res.entries = NULL;
602         }
603
604         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
605             &access, &cal)) != CSA_SUCCESS)
606                 return (&res);
607
608         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
609             !_DTCMS_HAS_VIEW_ACCESS(access)) {
610                 res.stat = CSA_E_NO_AUTHORITY;
611                 return (&res);
612         }
613
614         /* check operator */
615         if ((res.stat = _DtCm_check_operator(args->num_attrs, NULL,
616             args->attrs, args->ops)) != CSA_SUCCESS)
617                 return (&res);
618
619         /* get time range */
620         if ((res.stat = _DtCmHashCriteria(
621             cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ?
622             _DtCm_entry_name_tbl : cal->entry_tbl, args->num_attrs,
623             NULL, args->attrs, args->ops, &no_match, &no_start_time_range,
624             &no_end_time_range, &start1, &start2, &end1, &end2, &id,
625             &hnum, &hattrs, &hops)) == CSA_E_INVALID_ATTRIBUTE) {
626
627                 /* attribute not defined in this calendar specified,
628                  * return NULL list
629                  */
630                 res.stat = CSA_SUCCESS;
631                 return (&res);
632
633         } else if (res.stat != CSA_SUCCESS || no_match == B_TRUE)
634                 return (&res);
635
636         /* do lookup */
637         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
638                 if (id > 0)
639                         res.stat = _DtCmsLookupEntriesById(cal, user, access,
640                                         no_start_time_range, no_end_time_range,
641                                         start1, start2, end1, end2, id, hnum,
642                                         hattrs, hops, &res.entries);
643                 else
644                         res.stat = _DtCmsLookupEntries(cal, user, access,
645                                         start1, start2, no_end_time_range,
646                                         end1, end2, hnum, hattrs, hops,
647                                         &res.entries);
648         } else {
649                 Range_4 prange;
650                 Appt_4  *appt = NULL;;
651
652                 if (id > 0) {
653                         res.stat = _DtCmsLookupKeyrangeV4(cal, user, access,
654                                         no_start_time_range, no_end_time_range,
655                                         start1, start2, end1, end2, id,
656                                         _DtCm_match_one_appt, hnum, hattrs,
657                                         hops, &appt, NULL);
658                 } else {
659                         prange.key1 = start1;
660                         prange.key2 = start2;
661                         prange.next = NULL;
662                         res.stat = _DtCmsLookupRangeV4(cal, user, access,
663                                         &prange, no_end_time_range, end1, end2,
664                                         _DtCm_match_one_appt, hnum,
665                                         hattrs, hops, &appt, NULL);
666                 }
667
668                 if (res.stat == CSA_SUCCESS && appt) {
669                         res.stat = _DtCmsAppt4ToCmsentriesForClient(args->cal,
670                                         appt, &res.entries);
671                         _DtCm_free_appt4(appt);
672                 }
673         }
674
675         _DtCmFreeHashedArrays(hnum, hattrs, hops);
676
677         return (&res);
678 }
679
680 extern  cms_entries_res *
681 cms_enumerate_sequence_5_svc(cms_enumerate_args *args, struct svc_req *svcrq)
682 {
683         static cms_entries_res  res;
684         _DtCmsCalendar          *cal;
685         char                    *user;
686         uint                    access;
687
688         if (debug)
689                 fprintf(stderr, "cms_enumerate_sequence_5_svc called\n");
690
691         if (res.entries) {
692                 _DtCm_free_cms_entries(res.entries);
693                 res.entries = NULL;
694         }
695
696         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
697             &access, &cal)) != CSA_SUCCESS)
698                 return (&res);
699
700         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
701             !_DTCMS_HAS_VIEW_ACCESS(access)) {
702                 res.stat = CSA_E_NO_AUTHORITY;
703                 return (&res);
704         }
705
706         /* do lookup */
707         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
708                 res.stat = _DtCmsEnumerateSequenceById(cal, user, access,
709                                 B_FALSE, B_TRUE, args->start, args->end,
710                                 0, 0, args->id, 0, NULL, NULL, &res.entries);
711         } else {
712                 Range_4 prange;
713                 Appt_4 *appt = NULL;
714                 res.stat = _DtCmsLookupKeyrangeV4(cal, user, access,
715                                 B_FALSE, B_TRUE, args->start, args->end,
716                                 0, 0, args->id, NULL, 0, NULL, NULL, &appt,
717                                 NULL);
718
719                 if (res.stat == CSA_SUCCESS && appt) {
720                         res.stat = _DtCmsAppt4ToCmsentriesForClient(args->cal,
721                                         appt, &res.entries);
722                         _DtCm_free_appt4(appt);
723                 }
724         }
725
726         return (&res);
727 }
728
729 extern  cms_get_entry_attr_res *
730 cms_get_entry_attr_5_svc(cms_get_entry_attr_args *args, struct svc_req *svcrq)
731 {
732         static cms_get_entry_attr_res   res;
733         _DtCmsCalendar          *cal;
734         char                    *user;
735         uint                    access;
736
737         if (debug)
738                 fprintf(stderr, "cms_get_entry_attr_5_svc called\n");
739
740         if (res.entries) {
741                 _DtCmsFreeEntryAttrResItem(res.entries);
742                 res.entries = NULL;
743         }
744
745         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
746             &access, &cal)) != CSA_SUCCESS)
747                 return (&res);
748
749         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
750             !_DTCMS_HAS_VIEW_ACCESS(access)) {
751                 res.stat = CSA_E_NO_AUTHORITY;
752                 return (&res);
753         }
754
755         /* check operator */
756         if (args->num_keys == 0) {
757                 res.stat = CSA_E_INVALID_PARAMETER;
758                 return (&res);
759         }
760
761         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
762                 res.stat = _DtCmsLookupEntriesByKey(cal, user, access,
763                         args->num_keys, args->keys, args->num_names,
764                         args->names, &res.entries);
765         } else {
766                 res.stat = CSA_E_NOT_SUPPORTED;
767         }
768
769         return (&res);
770 }
771
772 extern  cms_entry_res *
773 cms_insert_entry_5_svc(cms_insert_args *args, struct svc_req *svcrq)
774 {
775         static cms_entry_res    res;
776         _DtCmsCalendar          *cal;
777         cms_entry               *entry;
778         cms_key                 key;
779         char                    *user;
780         uint                    access, needaccess;
781         Appt_4                  *appt;
782
783         if (debug)
784                 fprintf(stderr, "cms_insert_entry_5_svc called\n");
785
786         if (res.entry != NULL) {
787                 res.entry->num_attrs--;
788                 _DtCm_free_cms_entry(res.entry);
789                 res.entry = NULL;
790         }
791
792         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
793             &access, &cal)) != CSA_SUCCESS)
794                 return (&res);
795
796         if ((cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
797             !_DTCMS_HAS_INSERT_ACCESS(access)) ||
798             (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
799             !_DTCMS_HAS_V4_WRITE_ACCESS(access))) {
800                 res.stat = CSA_E_NO_AUTHORITY;
801                 return (&res);
802         }
803
804         /* check argument */
805         if (args->cal == NULL || args->num_attrs == 0) {
806                 res.stat = CSA_E_INVALID_PARAMETER;
807                 return (&res);
808         }
809
810         /* check validity of attribute values */
811         if ((res.stat = _DtCm_check_entry_cms_attributes(
812             (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ?
813             cal->fversion : _DtCM_FIRST_EXTENSIBLE_DATA_VERSION - 1),
814             args->num_attrs, args->attrs, CSA_CB_ENTRY_ADDED, B_TRUE))
815             != CSA_SUCCESS)
816                 return (&res);
817
818         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
819                 if ((res.stat = _DtCmsMakeHashedEntry(cal, args->num_attrs,
820                     args->attrs, &entry)) != CSA_SUCCESS)
821                         return (&res);
822
823                 if ((res.stat = _DtCmsCheckInitialAttributes(entry))
824                     != CSA_SUCCESS) {
825                         _DtCm_free_cms_entry(entry);
826                         return (&res);
827                 }
828
829                 /* check access rights */
830                 needaccess = _DtCmsClassToInsertAccess(entry);
831                 if ((access & (CSA_OWNER_RIGHTS | needaccess)) == 0) {
832                         _DtCm_free_cms_entry(entry);
833                         res.stat = CSA_E_NO_AUTHORITY;
834                         return (&res);
835                 }
836
837                 /* set organizer */
838                 if ((res.stat = _DtCm_set_string_attrval(user,
839                     &entry->attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value,
840                     CSA_VALUE_CALENDAR_USER)) != CSA_SUCCESS) {
841                         _DtCm_free_cms_entry(entry);
842                         return (&res);
843                 }
844
845                 /* insert entry and log it */
846                 if ((res.stat = _DtCmsInsertEntryAndLog(cal, entry))
847                     != CSA_SUCCESS) {
848                         _DtCm_free_cms_entry(entry);
849                         return (&res);
850                 }
851
852                 key = entry->key;
853         } else {
854                 if ((appt = _DtCm_make_appt4(B_TRUE)) == NULL) {
855                         res.stat = CSA_E_INSUFFICIENT_MEMORY;
856                         return (&res);
857                 }
858  
859                 if ((res.stat = _DtCmsAttrsToAppt4(args->num_attrs,
860                     args->attrs, appt, B_TRUE)) != CSA_SUCCESS) {
861                         _DtCm_free_appt4(appt);
862                         return (&res);
863                 }
864
865                 if (appt->author) free(appt->author);
866                 if ((appt->author = strdup(user)) == NULL) {
867                         _DtCm_free_appt4(appt);
868                         return (&res);
869                 }
870
871                 /*
872                  * calculate the correct start day,
873                  */
874                 _DtCms_adjust_appt_startdate(appt);
875
876                 if ((res.stat = _DtCmsInsertApptAndLog(cal, appt))
877                     != CSA_SUCCESS) {
878                         _DtCm_free_appt4(appt);
879                         return (&res);
880                 }
881
882                 key.id = appt->appt_id.key;
883                 key.time = appt->appt_id.tick;
884         }
885
886         if (res.stat == CSA_SUCCESS)
887                 cal->modified = B_TRUE;
888         else
889                 return (&res);
890
891         /* do callback */
892         cal->rlist = _DtCmsDoV1CbForV4Data(cal->rlist, user, args->pid,
893                         &key, NULL);
894
895         cal->rlist = _DtCmsDoInsertEntryCallback(cal->rlist, cal->calendar,
896                         user, key.id, args->pid);
897
898         /* reply */
899         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ||
900             (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
901             (res.stat = _DtCmsAppt4ToCmsentriesForClient(cal->calendar, appt,
902             &entry)) == CSA_SUCCESS)) {
903
904                 res.stat = _DtCmsGetCmsEntryForClient(entry, &res.entry, B_FALSE);
905
906                 _DtCm_free_cms_entry(entry);
907         }
908
909         return (&res);
910 }
911
912 extern  cms_entry_res *
913 cms_update_entry_5_svc(cms_update_args *args, struct svc_req *svcrq)
914 {
915         static cms_entry_res    res;
916         _DtCmsCalendar          *cal;
917         cms_entry               *newentry;
918         caddr_t                 event;
919         char                    *user;
920         uint                    access, needaccess;
921         Appt_4                  *appt = NULL;
922
923         if (debug)
924                 fprintf(stderr, "cms_update_entry_5_svc called\n");
925
926         if (res.entry != NULL) {
927                 res.entry->num_attrs--;
928                 _DtCm_free_cms_entry(res.entry);
929                 res.entry = NULL;
930         }
931
932         if ((res.stat = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
933             &access, &cal)) != CSA_SUCCESS)
934                 return (&res);
935
936         if ((cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
937             !_DTCMS_HAS_CHANGE_ACCESS(access)) ||
938             (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
939             !_DTCMS_HAS_V4_WRITE_ACCESS(access))) {
940                 res.stat = CSA_E_NO_AUTHORITY;
941                 return (&res);
942         }
943
944         /* check argument */
945         if (args->cal == NULL || args->entry.id <= 0 || args->num_attrs == 0) {
946                 res.stat = CSA_E_INVALID_PARAMETER;
947                 return (&res);
948         }
949
950         if (args->scope < CSA_SCOPE_ALL || args->scope > CSA_SCOPE_FORWARD) {
951                 res.stat = CSA_E_INVALID_ENUM;
952                 return (&res);
953         }
954
955         /* check validity of attribute values */
956         if ((res.stat = _DtCm_check_entry_cms_attributes(
957             (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ?
958             cal->fversion : _DtCM_FIRST_EXTENSIBLE_DATA_VERSION - 1),
959             args->num_attrs, args->attrs, CSA_CB_ENTRY_UPDATED, B_TRUE))
960             != CSA_SUCCESS)
961                 return (&res);
962
963         /* get event from one-time event tree */
964         event = (caddr_t)rb_lookup(cal->tree, (caddr_t)&args->entry);
965
966         /* update entry and log it */
967         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
968                 if (event != NULL || args->scope == CSA_SCOPE_ALL) {
969                         res.stat = _DtCmsUpdateEntry(cal, user, access,
970                                         &args->entry, args->num_attrs,
971                                         args->attrs, NULL, &newentry);
972                 } else {
973                         res.stat = _DtCmsUpdateInstances(cal, user, access,
974                                         &args->entry, args->scope,
975                                         args->num_attrs, args->attrs, NULL,
976                                         &newentry);
977                 }
978         } else {
979                 Options_4       opt;
980
981                 if (event != NULL || args->scope == CSA_SCOPE_ALL)
982                         opt = do_all_4;
983                 else
984                         opt = (args->scope == CSA_SCOPE_ONE) ?
985                                 do_one_4 : do_forward_4;
986
987                 if (event == NULL && (event = hc_lookup(cal->list,
988                     (caddr_t)&args->entry)) == NULL) {
989
990                         res.stat = CSA_X_DT_E_ENTRY_NOT_FOUND;
991
992                 } else if ((appt = _DtCm_copy_one_appt4((Appt_4 *)event))
993                     == NULL) {
994
995                         res.stat = CSA_E_INSUFFICIENT_MEMORY; 
996
997                 } else {
998                         /* get rid of exceptions */
999                         _DtCm_free_excpt4(appt->exception);
1000                         appt->exception = NULL;
1001
1002                         if ((res.stat = _DtCmsAttrsToAppt4(args->num_attrs,
1003                             args->attrs, appt, B_TRUE)) == CSA_SUCCESS) {
1004
1005                                 if (opt == do_all_4)
1006                                         res.stat = _DtCmsChangeAll(cal, user,
1007                                                 access, (Id_4 *)&args->entry,
1008                                                 appt, NULL);
1009                                 else
1010                                         res.stat = _DtCmsChangeSome(cal, user,
1011                                                 access, (Id_4 *)&args->entry,
1012                                                 appt, opt, NULL);
1013
1014                         }
1015                 }
1016         }
1017
1018         if (res.stat == CSA_SUCCESS)
1019                 cal->modified = B_TRUE;
1020         else {
1021                 free(appt);
1022                 return (&res);
1023         }
1024
1025         /* do callback */
1026         cal->rlist = _DtCmsDoV1CbForV4Data(cal->rlist, user, args->pid,
1027                         &args->entry,
1028                         (appt ? (cms_key *)&appt->appt_id : &newentry->key));
1029
1030         cal->rlist = _DtCmsDoUpdateEntryCallback(cal->rlist, cal->calendar,
1031                         user, (appt ? appt->appt_id.key : newentry->key.id),
1032                         args->entry.id, args->scope, args->entry.time,
1033                         args->pid);
1034
1035         free(appt);
1036
1037         /* reply */
1038         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ||
1039             (cal->fversion < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1040             (res.stat = _DtCmsAppt4ToCmsentriesForClient(cal->calendar, appt,
1041             &newentry)) == CSA_SUCCESS)) {
1042
1043                 res.stat = _DtCmsGetCmsEntryForClient(newentry, &res.entry, B_FALSE);
1044
1045                 _DtCm_free_cms_entry(newentry);
1046         }
1047
1048         return (&res);
1049 }
1050
1051 extern  CSA_return_code *
1052 cms_delete_entry_5_svc(cms_delete_args *args, struct svc_req *svcrq)
1053 {
1054         static CSA_return_code  res;
1055         _DtCmsCalendar          *cal;
1056         caddr_t                 event;
1057         char                    *user;
1058         uint                    access, needaccess;
1059
1060         if (debug)
1061                 fprintf(stderr, "cms_delete_entry_5_svc called\n");
1062
1063         if ((res = _DtCmsV5LoadAndCheckAccess(svcrq, args->cal, &user,
1064             &access, &cal)) != CSA_SUCCESS)
1065                 return (&res);
1066
1067         /* for v3 data, authority check is done in the routines doing the
1068          * deletion since we may need to check the organizer
1069          */
1070         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1071             !_DTCMS_HAS_CHANGE_ACCESS(access)) {
1072                 res = CSA_E_NO_AUTHORITY;
1073                 return (&res);
1074         }
1075
1076         /* check argument */
1077         if (args->cal == NULL || args->entry.id <= 0) {
1078                 res = CSA_E_INVALID_PARAMETER;
1079                 return (&res);
1080         }
1081
1082         if (args->scope < CSA_SCOPE_ALL || args->scope > CSA_SCOPE_FORWARD) {
1083                 res = CSA_E_INVALID_ENUM;
1084                 return (&res);
1085         }
1086
1087
1088         /* get event from one-time event tree */
1089         event = (caddr_t)rb_lookup(cal->tree, (caddr_t)&args->entry);
1090
1091         /* delete entry and log it */
1092         if (cal->fversion >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1093                 if (event != NULL || args->scope == CSA_SCOPE_ALL) {
1094                         res = _DtCmsDeleteEntryAndLog(cal, user, access,
1095                                 &args->entry, NULL);
1096                 } else {
1097                         res = _DtCmsDeleteInstancesAndLog(cal, user, access,
1098                                 &args->entry, args->scope, NULL, NULL);
1099                 }
1100         } else {
1101                 if (event != NULL || args->scope == CSA_SCOPE_ALL) {
1102                         res = _DtCmsDeleteApptAndLog(cal, user, access,
1103                                 (Id_4 *)&args->entry, NULL);
1104                 } else {
1105                         res = _DtCmsDeleteApptInstancesAndLog(cal, user, access,
1106                                 (Id_4 *)&args->entry,
1107                                 ((args->scope == CSA_SCOPE_ONE) ? do_one_4 :
1108                                 do_forward_4), NULL, NULL);
1109                 }
1110         }
1111
1112         if (res == CSA_SUCCESS)
1113                 cal->modified = B_TRUE;
1114         else
1115                 return (&res);
1116
1117         /* do callback */
1118         cal->rlist = _DtCmsDoV1CbForV4Data(cal->rlist, user, args->pid,
1119                         &args->entry, NULL);
1120
1121         cal->rlist = _DtCmsDoDeleteEntryCallback(cal->rlist, cal->calendar,
1122                         user, args->entry.id, args->scope, args->entry.time,
1123                         args->pid);
1124
1125
1126         return (&res);
1127 }
1128
1129 void initfunctable(program_handle ph)
1130 {
1131         ph->program_num = TABLEPROG;
1132         ph->prog[TABLEVERS].vers = &tableprog_5_table[0];
1133         ph->prog[TABLEVERS].nproc = sizeof(tableprog_5_table)/sizeof(tableprog_5_table[0]);
1134 }
1135
1136 /*****************************************************************************
1137  * static functions used within the file
1138  *****************************************************************************/
1139
1140 static CSA_return_code
1141 _DtCmsCreateCallog(char *user, cms_create_args *args, _DtCmsCalendar **newcal)
1142 {
1143         CSA_return_code stat;
1144         _DtCmsCalendar  *cal;
1145         int             i, index;
1146         char            datestr[80];
1147         char            *calname;
1148         char            *log;
1149         char            *username;
1150         cms_attribute_value val;
1151         cms_access_entry aentry;
1152         int             nidx = 0, oidx = 0;
1153         char            *name, *owner;
1154
1155         /*
1156          * if calendar name is a user name, make sure that
1157          * it's the same as the sender.
1158          */
1159         calname = _DtCmGetPrefix(args->cal, '@');
1160         username = _DtCmGetPrefix(user, '@');
1161
1162         if (_DtCmIsUserName(calname) && strcmp(calname, username)) {
1163                 free(calname);
1164                 free(username);
1165                 return (CSA_E_NO_AUTHORITY);
1166         }
1167         log = _DtCmsGetLogFN(calname);
1168         free(calname);
1169         free(username);
1170
1171         /* create internal calendar data structure */
1172         if ((cal = _DtCmsMakeCalendar(user, args->cal)) == NULL) {
1173                 free(log);
1174                 return (CSA_E_INSUFFICIENT_MEMORY);
1175         }
1176
1177         /* fill in information */
1178         _csa_tick_to_iso8601(time(0), datestr);
1179
1180         if ((stat = _DtCm_set_string_attrval(datestr,
1181             &cal->attrs[CSA_CAL_ATTR_DATE_CREATED_I].value,
1182             CSA_VALUE_DATE_TIME)) != CSA_SUCCESS) {
1183                 _DtCmsFreeCalendar(cal);
1184                 free(log);
1185                 return (stat);
1186         }
1187
1188         /* initialize access list to be "WORLD", VIEW_PUBLIC */
1189         aentry.user = WORLD;
1190         aentry.rights = CSA_VIEW_PUBLIC_ENTRIES;
1191         aentry.next = NULL;
1192         val.item.access_list_value = &aentry;
1193         val.type = CSA_VALUE_ACCESS_LIST;
1194
1195         if ((stat = _DtCmUpdateAccessListAttrVal(&val,
1196             &cal->attrs[CSA_CAL_ATTR_ACCESS_LIST_I].value)) != CSA_SUCCESS) {
1197                 _DtCmsFreeCalendar(cal);
1198                 free(log);
1199                 return (stat);
1200         }
1201
1202         /* set product identifier */
1203         if ((stat = _DtCm_set_string_attrval(_DtCM_PRODUCT_IDENTIFIER,
1204             &cal->attrs[CSA_CAL_ATTR_PRODUCT_IDENTIFIER_I].value,
1205             CSA_VALUE_STRING)) != CSA_SUCCESS) {
1206                 _DtCmsFreeCalendar(cal);
1207                 free(log);
1208                 return (stat);
1209         }
1210
1211         /* set CSA version */
1212         if ((stat = _DtCm_set_string_attrval(_DtCM_SPEC_VERSION_SUPPORTED,
1213             &cal->attrs[CSA_CAL_ATTR_VERSION_I].value, CSA_VALUE_STRING))
1214             != CSA_SUCCESS) {
1215                 _DtCmsFreeCalendar(cal);
1216                 free(log);
1217                 return (stat);
1218         }
1219
1220         /* we don't use the values specified by client */
1221         for (i = 0; i < args->num_attrs; i++) {
1222                 if (strcmp(args->attrs[i].name.name,
1223                     CSA_CAL_ATTR_CALENDAR_NAME) == 0) {
1224                         nidx = i;
1225                         name = args->attrs[i].name.name;
1226                         args->attrs[i].name.name = NULL;
1227                 } else if (strcmp(args->attrs[i].name.name,
1228                     CSA_CAL_ATTR_CALENDAR_OWNER) == 0) {
1229                         oidx = i;
1230                         owner = args->attrs[i].name.name;
1231                         args->attrs[i].name.name = NULL;
1232                 }
1233         }
1234
1235         /* initialize calendar attribute with info provided by caller */
1236         if ((stat = _DtCmUpdateAttributes(args->num_attrs, args->attrs,
1237             &cal->num_attrs, &cal->attrs, &cal->cal_tbl, B_TRUE,
1238             NULL, B_FALSE)) != CSA_SUCCESS) {
1239                 _DtCmsFreeCalendar(cal);
1240                 free(log);
1241                 return (stat);
1242         }
1243
1244         if (nidx) args->attrs[nidx].name.name = name;
1245         if (oidx) args->attrs[oidx].name.name = owner;
1246
1247         /* use passed in char set if client does not supply one */
1248         if (cal->attrs[CSA_CAL_ATTR_CHARACTER_SET_I].value == NULL &&
1249              args->char_set && *args->char_set != '\0') {
1250                 if ((stat = _DtCm_set_string_attrval(args->char_set,
1251                     &cal->attrs[CSA_CAL_ATTR_CHARACTER_SET_I].value,
1252                     CSA_VALUE_STRING)) != CSA_SUCCESS) {
1253                         _DtCmsFreeCalendar(cal);
1254                         free(log);
1255                         return (stat);
1256                 }
1257         }
1258
1259         /* create file */
1260         if ((stat = _DtCmsCreateLogV2(user, log)) != CSA_SUCCESS) {
1261                 _DtCmsFreeCalendar(cal);
1262                 free(log);
1263                 return (stat);
1264         }
1265
1266         /* dump file */
1267         if ((stat = _DtCmsAppendCalAttrsByFN(log, cal->num_attrs, cal->attrs))
1268             != CSA_SUCCESS) {
1269                 free(log);
1270                 unlink(log);
1271                 _DtCmsFreeCalendar(cal);
1272                 return (stat);
1273         }
1274         free(log);
1275
1276         _DtCmsPutInCalList(cal);
1277
1278         *newcal = cal;
1279
1280         return (stat);
1281 }
1282
1283 #define _NAME_INCREMENT 10
1284
1285 static CSA_return_code
1286 _ListCalendarNames(uint *num_names, char ***names)
1287 {
1288         uint    num = 0, count = 0;
1289         char    **names_r = NULL;
1290         DIR     *dirp;
1291         struct  dirent *dp;
1292
1293         if ((dirp = opendir(".")) == NULL)
1294                 return (CSA_E_FAILURE);
1295
1296 #ifdef SunOS
1297         if ((dp = (struct dirent *)malloc(sizeof(struct dirent) + FILENAME_MAX))
1298             == NULL) {
1299                 closedir(dirp);
1300                 return (CSA_E_INSUFFICIENT_MEMORY);
1301         }
1302
1303         while (dp = readdir_r(dirp, dp)) {
1304 #else
1305         while (dp = readdir(dirp)) {
1306 #endif
1307                 if (strncmp(dp->d_name, "callog.", strlen("callog.")) == 0) {
1308                         if (count == num) {
1309                                 count += _NAME_INCREMENT;
1310                                 if ((names_r = (char **)_grow_char_array(
1311                                     names_r, sizeof(char *) * count,
1312                                     sizeof(char *) * (count + _NAME_INCREMENT)))
1313                                     == NULL) {
1314                                         if (num > 0) {
1315                                                 _free_char_array(
1316                                                         num, names_r);
1317                                         }
1318                                         closedir(dirp);
1319                                         return (CSA_E_INSUFFICIENT_MEMORY);
1320                                 }
1321                         }
1322                         if ((names_r[num++] = strdup(dp->d_name)) == NULL) {
1323                                 _free_char_array(num, names_r);
1324                                 closedir(dirp);
1325                                 return (CSA_E_INSUFFICIENT_MEMORY);
1326                         }
1327                 }
1328         }
1329
1330         closedir(dirp);
1331
1332         if (num > 0) {
1333                 *num_names = num;
1334                 *names = names_r;
1335         } else if (count > 0)
1336                 free(names_r);
1337
1338         return (CSA_SUCCESS);
1339 }
1340
1341 static void *
1342 _grow_char_array(void *ptr, uint oldcount, uint newcount)
1343 {
1344         void *nptr;
1345
1346         if (nptr = realloc(ptr, newcount)) {
1347                 memset((void *)((char *)nptr + oldcount), 0,
1348                         newcount - oldcount);
1349                 return (nptr);
1350         } else
1351                 return (NULL);
1352 }
1353
1354 static void
1355 _free_char_array(uint num_elem, char **ptr)
1356 {
1357         int i;
1358
1359         if (num_elem == 0)
1360                 return;
1361
1362         for (i = 0; i < num_elem; i++) {
1363                 if (ptr[i])
1364                         free(ptr[i]);
1365                 else
1366                         break;
1367         }
1368
1369         free(ptr);
1370 }
1371
1372 /*
1373  * This routine assumes that the attributes are hashed already
1374  */
1375 static CSA_return_code
1376 _DtCmsGetOldCalAttrNames(
1377         _DtCmsCalendar  *cal,
1378         uint            *num_names_r,
1379         cms_attr_name   **names_r)
1380 {
1381         CSA_return_code stat = CSA_SUCCESS;
1382         cms_attr_name   *names;
1383         uint            i, j;
1384
1385         if ((names = (cms_attr_name *)calloc(1,
1386             sizeof(cms_attr_name)*_DtCM_OLD_CAL_ATTR_SIZE)) == NULL)
1387                 return (CSA_E_INSUFFICIENT_MEMORY);
1388
1389         for (i = 1, j = 0; i <= _DtCM_DEFINED_CAL_ATTR_SIZE; i++) {
1390                 if ((_CSA_cal_attr_info[i].fst_vers > 0 &&
1391                     _CSA_cal_attr_info[i].fst_vers <= cal->fversion)
1392                     || i == CSA_CAL_ATTR_CALENDAR_SIZE_I) {
1393                         if ((names[j].name =
1394                             strdup(_CSA_calendar_attribute_names[i])) == NULL)
1395                         {
1396                                 _DtCmsFreeCmsAttrNames(j, names);
1397                                 return (CSA_E_INSUFFICIENT_MEMORY);
1398                         } else {
1399                                 names[j].num = i;
1400                                 j++;
1401                         }
1402                 }
1403         }
1404
1405         *num_names_r = j;
1406         *names_r = names;
1407
1408         return (CSA_SUCCESS);
1409 }
1410