Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / csa / calendar.c
1 /* $XConsortium: calendar.c /main/1 1996/04/21 19:21:47 drk $ */
2 /*
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.
7  */
8
9 /*****************************************************************************
10  * Functions that manage the calendar data structures.
11  *****************************************************************************/
12
13 #include <EUSCompat.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <pwd.h>
18 #include "calendar.h"
19 #include "entry.h"
20 #include "cmsdata.h"
21 #include "agent_p.h"
22 #include "rpccalls.h"
23 #include "debug.h"
24 #include "attr.h"
25 #include "xtclient.h"
26 #include "misc.h"
27 #include "free.h"
28 #include "nametbl.h"
29 #include "lutil.h"
30
31 /* linked list of calendar structure representing opened calendars */
32 Calendar *_DtCm_active_cal_list = NULL;
33
34 /******************************************************************************
35  * forward declaration of static functions used within the file
36  ******************************************************************************/
37 static CSA_return_code _get_owner_from_old_cal(Calendar *cal, char *buf);
38 static CSA_return_code _get_calendar_owner(Calendar *cal, uint num_names,
39                                         char **names, CSA_attribute *attr);
40 static CSA_return_code _get_calendar_name(Calendar *cal, CSA_attribute *attr);
41 static CSA_return_code _get_product_identifier(Calendar *cal,
42                                                 CSA_attribute *attr);
43 static CSA_return_code _get_version_supported(Calendar *cal,
44                                                 CSA_attribute *attr);
45 static CSA_return_code _get_server_version(Calendar *cal, CSA_attribute *attr);
46 static CSA_return_code _get_data_version(Calendar *cal, CSA_attribute *attr);
47 static CSA_return_code _get_access_list(Calendar *cal, uint num_names,
48                                         char ** names, CSA_attribute *attr);
49 static CSA_return_code _get_number_entries(Calendar *cal, uint num_names,
50                                         char ** names, CSA_attribute *attr);
51
52 /*****************************************************************************
53  * extern functions used in the library
54  *****************************************************************************/
55
56 /*
57  * Allocate a calendar structure and initialize it with
58  * the location, and name of the calendar.
59  */
60 extern Calendar *
61 _DtCm_new_Calendar(const char *calendar)
62 {
63         Calendar        *cal;
64         int i;
65
66         _DtCm_init_hash();
67
68         if ((cal = (Calendar *)malloc(sizeof(Calendar))) == NULL)
69                 return(NULL);
70
71         memset((void *)cal, NULL, sizeof(Calendar));
72
73         if ((cal->name = strdup(calendar)) == NULL) {
74                 free(cal);
75                 return(NULL);
76         }
77
78         cal->location = strchr(cal->name, '@');
79         cal->location++;
80
81         /* set up attribute array */
82         if ((cal->attrs = (cms_attribute *)calloc(1,
83             sizeof(cms_attribute) * (_DtCm_cal_name_tbl->size + 1))) == NULL) {
84                 free(cal->name);
85                 free(cal);
86                 return(NULL);
87         }
88
89         for (i = 1; i <= _DtCm_cal_name_tbl->size; i++) {
90                 if ((cal->attrs[i].name.name =
91                     strdup(_DtCm_cal_name_tbl->names[i])) == NULL) {
92                         /* clean up */
93                         cal->num_attrs = i - 1;
94                         _DtCm_free_Calendar(cal);
95                         return(NULL);
96                 } else
97                         cal->attrs[i].name.num = i;
98         }
99         cal->num_attrs = _DtCm_cal_name_tbl->size;
100
101         if (_DtCm_active_cal_list == NULL) {
102                 _DtCm_active_cal_list = cal;
103                 cal->next = NULL;
104                 cal->prev = NULL;
105         }
106         else {
107                 cal->next = _DtCm_active_cal_list;
108                 _DtCm_active_cal_list->prev = cal;
109                 _DtCm_active_cal_list = cal;
110         }
111
112         cal->cal_tbl = _DtCm_cal_name_tbl;
113         cal->entry_tbl = _DtCm_entry_name_tbl;
114
115         cal->handle = (void *)cal;
116
117         return(cal);
118 }
119
120 /*
121  * After freeing up memory pointed to by cal,
122  * put it in the free list.
123  */
124 extern void
125 _DtCm_free_Calendar(Calendar *cal)
126 {
127         _DtCmCallbackEntry      *cb, *ptr;
128
129         /* remove from active list */
130         if (_DtCm_active_cal_list == cal)
131                 _DtCm_active_cal_list = cal->next;
132
133         if (cal->prev != NULL)
134                 cal->prev->next = cal->next;
135
136         if (cal->next != NULL)
137                 cal->next->prev = cal->prev;
138
139         /* free up resources used by it */
140         if (cal->name) free(cal->name);
141         if (cal->ehead) _DtCm_free_libentries((_DtCm_libentry *)cal->ehead);
142
143         if (cal->cal_tbl != _DtCm_cal_name_tbl)
144                 _DtCm_free_name_table(cal->cal_tbl);
145
146         if (cal->entry_tbl != _DtCm_entry_name_tbl)
147                 _DtCm_free_name_table(cal->entry_tbl);
148
149         cb = cal->cb_list;
150         while (cb) {
151                 ptr = cb->next;
152                 free(cb);
153                 cb = ptr;
154         }
155
156         /*
157          * no need to free attribute values now
158          * since the values are passed to client
159          * directly.
160          * need to free attribute values if they
161          * are cached later
162          */
163         _DtCm_free_cms_attribute_values(cal->num_attrs, cal->attrs);
164         free(cal->attrs);
165
166         memset((void *)cal, '\0', sizeof(Calendar));
167
168         /* if no calendar is open, destroy rpc mapping */
169         if (_DtCm_active_cal_list == NULL)
170                 _DtCm_destroy_agent();
171 }
172
173 /*
174  * Given the calendar handle, return the internal calendar data structure.
175  */
176 extern Calendar *
177 _DtCm_get_Calendar(CSA_session_handle calhandle)
178 {
179         Calendar *cal = (Calendar *)calhandle;
180
181         if (cal == NULL || cal->handle != (void *)cal)
182                 return (NULL);
183         else
184                 return ((Calendar *)calhandle);
185 }
186
187 /*
188  * Add linked list of entry data structures to the calendar.
189  */
190 extern uint
191 _DtCm_add_to_entry_list(Calendar *cal, caddr_t elist)
192 {
193         int i;
194         _DtCm_libentry *entries = (_DtCm_libentry *)elist;
195
196         if (entries == NULL)
197                 return (0);
198
199         if (cal->ehead == NULL)
200                 cal->ehead = elist;
201         else {
202                 ((_DtCm_libentry *)cal->etail)->next = entries;
203                 entries->prev = (_DtCm_libentry *)cal->etail;
204         }
205
206         /* find tail of given entry list */
207         i = 1;
208         entries->cal = cal;
209         while (entries->next != NULL) {
210                 i++;
211                 entries->next->cal = cal;
212                 entries = entries->next;
213         }
214
215         cal->etail = (caddr_t)entries;
216
217 #ifdef CM_DEBUG
218         _DtCm_count_entry_in_list(cal->ehead);
219 #endif
220
221         return (i);
222 }
223
224 extern void
225 _DtCm_remove_from_entry_list(
226         Calendar *cal,
227         caddr_t head,
228         caddr_t tail)
229 {
230         _DtCm_libentry *ehead = (_DtCm_libentry *)head;
231         _DtCm_libentry *etail = (_DtCm_libentry *)tail;
232
233         if (ehead == NULL || tail == NULL)
234                 return;
235
236         if (ehead == (_DtCm_libentry *)cal->ehead)
237                 cal->ehead = (caddr_t)etail->next;
238
239         if (etail == (_DtCm_libentry *)cal->etail)
240                 cal->etail = (caddr_t)ehead->prev;
241
242         /* remove from list */
243         if (ehead->prev != NULL)
244                 ehead->prev->next = etail->next;
245
246         if (etail->next != NULL)
247                 etail->next->prev = ehead->prev;
248
249         etail->next = ehead->prev = NULL;
250
251 #ifdef CM_DEBUG
252         _DtCm_count_entry_in_list(cal->ehead);
253 #endif
254 }
255
256 extern void
257 _DtCm_reset_cal_attrs(Calendar *cal)
258 {
259         cal->got_attrs = B_FALSE;
260 }
261
262 /*
263  * Assume good parameters.  Caller should check before calling this.
264  */
265 extern CSA_return_code
266 _DtCm_list_old_cal_attr_names(
267         Calendar *cal,
268         CSA_uint32 *num_names_r,
269         char **names_r[])
270 {
271         CSA_return_code stat;
272         char            **names, buf[BUFSIZ];
273         int             i, j;
274
275         if ((names = _DtCm_alloc_character_pointers(_DtCM_OLD_CAL_ATTR_SIZE))
276             == NULL)
277                 return (CSA_E_INSUFFICIENT_MEMORY);
278
279         /* find out whether we know the owner of the calendar */
280         if ((stat = _get_owner_from_old_cal(cal, buf)) != CSA_SUCCESS)
281                 return (stat);
282
283         for (i = 1, j = 0; i <= _DtCM_DEFINED_CAL_ATTR_SIZE; i++) {
284                 if (_CSA_cal_attr_info[i].fst_vers > 0 &&
285                     _CSA_cal_attr_info[i].fst_vers <= cal->file_version) {
286                         if (i == CSA_CAL_ATTR_CALENDAR_OWNER_I && *buf == NULL)
287                                 continue;
288
289                         if ((names[j] =
290                             strdup(_CSA_calendar_attribute_names[i])) == NULL)
291                         {
292                                 _DtCm_free(names);
293                                 return (CSA_E_INSUFFICIENT_MEMORY);
294                         } else
295                                 j++;
296                 }
297         }
298
299         *names_r = names;
300         *num_names_r = j;
301
302         return (CSA_SUCCESS);
303 }
304
305 extern CSA_return_code
306 _DtCm_get_all_cal_attrs(
307         Calendar *cal,
308         CSA_uint32 *num_attrs,
309         CSA_attribute **attrs)
310 {
311         CSA_return_code stat;
312         int             i, j;
313         CSA_attribute   *attrs_r;
314
315         if (num_attrs == NULL || attrs == NULL)
316                 return (CSA_E_INVALID_PARAMETER);
317
318         if (cal->rpc_version >= _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION) {
319                 if ((stat = _DtCm_rpc_get_cal_attrs(cal, 0, 0, NULL))
320                     != CSA_SUCCESS)
321                         return (stat);
322
323                 if ((attrs_r = _DtCm_alloc_attributes(cal->num_attrs)) == NULL)
324                         return (CSA_E_INSUFFICIENT_MEMORY);
325
326                 /* get attributes */
327                 for (i = 1, j = 0; i <= cal->num_attrs; i++) {
328                         if (cal->attrs[i].value != NULL) {
329
330                                 if ((stat = _DtCm_cms2csa_attribute(
331                                     cal->attrs[i], &attrs_r[j])) != CSA_SUCCESS)
332                                 {
333                                         _DtCm_free(attrs_r);
334                                         return (stat);
335                                 } else
336                                         j++;
337                         }
338                 }
339
340                 *num_attrs = j;
341                 *attrs = attrs_r;
342
343                 return (CSA_SUCCESS);
344         } else
345                 return (_DtCm_get_cal_attrs_by_name(cal,
346                         _DtCM_DEFINED_CAL_ATTR_SIZE + 1,
347                         _CSA_calendar_attribute_names, num_attrs, attrs));
348 }
349
350 /*
351  * If it's not found, the attribute value is set to NULL.
352  */
353 extern CSA_return_code
354 _DtCm_get_cal_attrs_by_name(
355         Calendar *cal,
356         CSA_uint32      num_names,
357         CSA_attribute_reference *names,
358         CSA_uint32      *num_attrs,
359         CSA_attribute **attrs)
360 {
361         CSA_return_code stat = CSA_SUCCESS;
362         CSA_attribute *attrs_r;
363         int i, j, index;
364
365         if (num_attrs == 0 || attrs == NULL)
366                 return (CSA_E_INVALID_PARAMETER);
367
368
369         if ((attrs_r = _DtCm_alloc_attributes(num_names)) == NULL)
370                 return (CSA_E_INSUFFICIENT_MEMORY);
371
372         for (i = 0, j = 0; i < num_names; i++) {
373                 if (names[i] == NULL)
374                         continue;
375
376                 index = _DtCm_get_index_from_table(cal->cal_tbl, names[i]);
377
378                 switch (index) {
379                 case CSA_X_DT_CAL_ATTR_SERVER_VERSION_I:
380
381                         stat = _get_server_version(cal, &attrs_r[j]);
382                         break;
383
384                 case CSA_X_DT_CAL_ATTR_DATA_VERSION_I:
385
386                         stat = _get_data_version(cal, &attrs_r[j]);
387                         break;
388
389                 case CSA_CAL_ATTR_ACCESS_LIST_I:
390
391                         stat = _get_access_list(cal, num_names, names,
392                                 &attrs_r[j]);
393                         break;
394
395                 case CSA_CAL_ATTR_NUMBER_ENTRIES_I:
396
397                         stat = _get_number_entries(cal, num_names,
398                                 names, &attrs_r[j]);
399                         break;
400
401                 case CSA_CAL_ATTR_CALENDAR_NAME_I:
402
403                         stat = _get_calendar_name(cal, &attrs_r[j]);
404                         break;
405
406                 case CSA_CAL_ATTR_CALENDAR_OWNER_I:
407
408                         stat = _get_calendar_owner(cal, num_names, names,
409                                 &attrs_r[j]);
410                         break;
411
412                 case CSA_CAL_ATTR_PRODUCT_IDENTIFIER_I:
413
414                         stat = _get_product_identifier(cal, &attrs_r[j]);
415                         break;
416
417                 case CSA_CAL_ATTR_VERSION_I:
418
419                         stat = _get_version_supported(cal, &attrs_r[j]);
420                         break;
421
422                 default:
423                         if (cal->rpc_version >=
424                             _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
425                         {
426                                 if (cal->file_version <
427                                     _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
428                                     index == -1)
429                                         break;
430
431                                 if (cal->got_attrs == B_FALSE &&
432                                     (stat = _DtCm_rpc_get_cal_attrs(cal, 0,
433                                     num_names, names)) == CSA_SUCCESS) {
434                                         /* there might by new attributes */
435                                         if (index == -1 &&
436                                             (index = _DtCm_get_index_from_table(
437                                             cal->cal_tbl, names[i])) == -1)
438                                                 break;
439                                 }
440
441                                 if (stat == CSA_SUCCESS &&
442                                     cal->attrs[index].value)
443                                         stat = _DtCm_cms2csa_attribute(
444                                                 cal->attrs[index], &attrs_r[j]);
445                         }
446                         break;
447                 }
448
449                 if (stat == CSA_SUCCESS) {
450                         if (attrs_r[j].value != NULL)
451                                 j++;
452                 } else {
453                         _DtCm_free(attrs_r);
454                         return (stat);
455                 }
456         }
457
458         *num_attrs = j;
459
460         if (j > 0) {
461                 *attrs = attrs_r;
462         } else {
463                 *attrs = NULL;
464                 _DtCm_free(attrs_r);
465         }
466
467         return (CSA_SUCCESS);
468 }
469
470 /*
471  * Debugging function - count the number of entries in the list and print it out
472  */
473 extern void
474 _DtCm_count_entry_in_list(caddr_t elist)
475 {
476         int i;
477         _DtCm_libentry *list;
478
479         for (i = 0, list = (_DtCm_libentry *)elist;
480             list != NULL;
481             i++, list = list->next)
482                 ;
483
484         fprintf(stderr, "number of entries = %d\n", i);
485 }
486
487 /******************************************************************************
488  * static functions used within in the file
489  ******************************************************************************/
490
491 /*
492  * owner should point to a buffer big enough to hold the owner name
493  * We test whether the calendar name is a user name, if so, the
494  * owner will be the same as the calendar name.
495  * Otherwise, we don't know the owner.
496  */
497 static CSA_return_code
498 _get_owner_from_old_cal(Calendar *cal, char *owner)
499 {
500         char            *calname;
501
502         if ((calname = _DtCmGetPrefix(cal->name, '@')) == NULL)
503                 return (CSA_E_INSUFFICIENT_MEMORY);
504
505         if (_DtCmIsUserName(calname) == B_TRUE)
506                 strcpy(owner, calname);
507         else
508                 *owner = NULL;
509
510         free(calname);
511         return (CSA_SUCCESS);
512 }
513
514 static CSA_return_code
515 _get_calendar_owner(
516         Calendar        *cal,
517         uint            num_names,
518         char            **names,
519         CSA_attribute   *attr)
520 {
521         CSA_return_code         stat;
522         CSA_attribute_value     *val;
523         char                    *owner, buf[BUFSIZ];
524
525         if (cal->rpc_version >= _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION) {
526                 if (cal->got_attrs == B_FALSE) {
527                         if ((stat = _DtCm_rpc_get_cal_attrs(cal, 0, num_names,
528                             names)) != CSA_SUCCESS)
529                                 return (stat);
530                 }
531                 owner = cal->attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].value->\
532                         item.string_value;
533         } else {
534                 if ((stat = _get_owner_from_old_cal(cal, buf)) != CSA_SUCCESS)
535                         return (stat);
536                 else if (*buf == NULL)
537                         return (CSA_SUCCESS);
538                 else
539                         owner = buf;
540         }
541
542         if (attr->name = strdup(CSA_CAL_ATTR_CALENDAR_OWNER)) {
543                 if ((val = (CSA_attribute_value *)calloc(1,
544                     sizeof(CSA_attribute_value))) == NULL) {
545                         free(attr->name);
546                         return (CSA_E_INSUFFICIENT_MEMORY);
547                 }
548
549                 val->type = CSA_VALUE_CALENDAR_USER;
550
551                 if ((val->item.calendar_user_value = (CSA_calendar_user *)
552                     calloc(1, sizeof(CSA_calendar_user))) == NULL) {
553                         free(val);
554                         free(attr->name);
555                         return (CSA_E_INSUFFICIENT_MEMORY);
556                 }
557
558                 if (val->item.calendar_user_value->user_name = strdup(owner)) {
559                         attr->value = val;
560                         return (CSA_SUCCESS);
561                 } else {
562                         free(val->item.calendar_user_value);
563                         free(val);
564                         free(attr->name);
565                         return (CSA_E_INSUFFICIENT_MEMORY);
566                 }
567         } else
568                 return (CSA_E_INSUFFICIENT_MEMORY);
569 }
570
571 static CSA_return_code
572 _get_calendar_name(Calendar *cal, CSA_attribute *attr)
573 {
574         if (attr->name = strdup(CSA_CAL_ATTR_CALENDAR_NAME))
575                 return (_DtCm_set_csa_string_attrval(cal->name, &attr->value,
576                         CSA_VALUE_STRING));
577         else
578                 return (CSA_E_INSUFFICIENT_MEMORY);
579 }
580
581 static CSA_return_code
582 _get_product_identifier(Calendar *cal, CSA_attribute *attr)
583 {
584         if (attr->name = strdup(CSA_CAL_ATTR_PRODUCT_IDENTIFIER))
585                 return (_DtCm_set_csa_string_attrval(_DtCM_PRODUCT_IDENTIFIER,
586                         &attr->value, CSA_VALUE_STRING));
587         else
588                 return (CSA_E_INSUFFICIENT_MEMORY);
589 }
590
591 static CSA_return_code
592 _get_version_supported(Calendar *cal, CSA_attribute *attr)
593 {
594         char buf[10];
595
596         if (attr->name = strdup(CSA_CAL_ATTR_VERSION))
597                 return (_DtCm_set_csa_string_attrval(
598                         _DtCM_SPEC_VERSION_SUPPORTED, &attr->value,
599                         CSA_VALUE_STRING));
600         else
601                 return (CSA_E_INSUFFICIENT_MEMORY);
602 }
603
604 static CSA_return_code
605 _get_server_version(Calendar *cal, CSA_attribute *attr)
606 {
607         if (attr->name = strdup(CSA_X_DT_CAL_ATTR_SERVER_VERSION))
608                 return (_DtCm_set_csa_uint32_attrval(cal->rpc_version,
609                         &attr->value));
610         else
611                 return (CSA_E_INSUFFICIENT_MEMORY);
612 }
613
614 static CSA_return_code
615 _get_data_version(Calendar *cal, CSA_attribute *attr)
616 {
617         if (attr->name = strdup(CSA_X_DT_CAL_ATTR_DATA_VERSION))
618                 return (_DtCm_set_csa_uint32_attrval(cal->file_version,
619                         &attr->value));
620         else
621                 return (CSA_E_INSUFFICIENT_MEMORY);
622 }
623
624 static CSA_return_code
625 _get_access_list(
626         Calendar        *cal,
627         uint            num_names,
628         char            **names,
629         CSA_attribute   *attr)
630 {
631         CSA_return_code stat = CSA_SUCCESS;
632
633         if (cal->rpc_version < _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
634                 stat = _DtCm_rpc_get_cal_attrs(cal, CSA_CAL_ATTR_ACCESS_LIST_I,
635                         0, NULL);
636         else if (cal->got_attrs == B_FALSE)
637                 stat = _DtCm_rpc_get_cal_attrs(cal, 0, num_names, names);
638
639         if (stat == CSA_SUCCESS)
640                 stat = _DtCm_cms2csa_attribute(
641                         cal->attrs[CSA_CAL_ATTR_ACCESS_LIST_I], attr);
642
643         return (stat);
644 }
645
646 static CSA_return_code
647 _get_number_entries(
648         Calendar        *cal,
649         uint            num_names,
650         char            **names,
651         CSA_attribute   *attr)
652 {
653         CSA_return_code stat = CSA_SUCCESS;
654
655         if (cal->rpc_version < _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
656                 stat = _DtCm_rpc_get_cal_attrs(cal,
657                         CSA_CAL_ATTR_NUMBER_ENTRIES_I, 0, NULL);
658         else if (cal->got_attrs == B_FALSE)
659                 stat = _DtCm_rpc_get_cal_attrs(cal, 0, num_names, names);
660
661         if (stat == CSA_SUCCESS)
662                 stat = _DtCm_cms2csa_attribute(
663                         cal->attrs[CSA_CAL_ATTR_NUMBER_ENTRIES_I], attr);
664
665         return (stat);
666 }
667