Don't declare 'Chunk' as both public and private, that's just daft.
[oweals/cde.git] / cde / lib / csa / rpccalls.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 librararies 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: rpccalls.c /main/1 1996/04/21 19:24:20 drk $ */
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 /*****************************************************************************
32  * interface to cm rpc calls
33  * - this files make calls to v5 backend
34  * - calls to v4 and before are implemented in table.c
35  *****************************************************************************/
36
37 #include <EUSCompat.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <netdb.h>              /* define MAXHOSTNAMELEN */
42 #include <sys/utsname.h>        /* SYS_NMLN */
43 #include <unistd.h>
44 #ifdef SunOS
45 #include <sys/systeminfo.h>
46 #endif
47 #include "debug.h"
48 #include "rtable4.h" 
49 #include "cm.h"
50 #include "attr.h"
51 #include "connection.h"
52 #include "convert5-4.h"
53 #include "convert4-5.h"
54 #include "rpccalls.h"
55 #include "table.h"
56 #include "agent.h"
57 #include "cmcb.h"
58 #include "cmsdata.h"
59 #include "iso8601.h"
60 #include "misc.h"
61 #include "updateattrs.h"
62 #include "free.h"
63 #include "lutil.h"
64 #include "laccess.h"
65 #include "match.h"
66
67 extern u_long   _DtCm_transient;
68
69 static char *nullstr = "";
70
71 /*****************************************************************************
72  * forward declaration of static functions
73  *****************************************************************************/
74 static CSA_return_code csa2cmsattrs(CSA_uint32 num_attrs, CSA_attribute *csaattrs,
75                                         CSA_enum *ops, CSA_uint32 *newnum,
76                                         cms_attribute **newattrs, CSA_enum **newops);
77 static void free_cmsattrs(CSA_uint32 num_attrs, cms_attribute *attrs);
78 static CSA_return_code csa2cmsnames(CSA_uint32 num_names, char **reminder_names,
79                                         CSA_uint32 *newnum, cms_attr_name **newnames);
80 static CSA_return_code _GetV4UserAccess(Calendar *cal, cms_access_entry *alist);
81
82 /*****************************************************************************
83  * extern functions used in the library
84  *****************************************************************************/
85
86 extern CSA_return_code
87 _DtCm_rpc_open_calendar(Calendar *cal)
88 {
89         _DtCm_Client_Info       *ci=NULL;
90         CSA_return_code stat;
91
92         DP(("rpccalls.c: _DtCm_rpc_open_calendar\n"));
93
94         if (cal == NULL)
95                 return (CSA_E_INVALID_PARAMETER);
96
97         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
98             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
99                 return (stat);
100         }
101         cal->conn.ci = ci;
102         cal->conn.retry = B_TRUE;
103
104         if (ci->vers_out == TABLEVERS) {
105                 cms_open_args   arg;
106                 cms_open_res    *res;
107
108                 arg.cal = cal->name;
109                 arg.pid = getpid();
110
111                 res = cms_open_calendar_5(&arg, &cal->conn);
112
113                 if (res != NULL) {
114                         if ((stat = res->stat) == CSA_SUCCESS) {
115                                 cal->rpc_version = res->svr_vers;
116                                 cal->file_version = res->file_vers;
117                                 cal->access = res->user_access;
118                         }
119
120                         xdr_free((xdrproc_t)xdr_cms_open_res, (char *)res);
121                 } else {
122                         stat = (cal->conn.stat == RPC_SUCCESS) ?
123                                 CSA_E_SERVICE_UNAVAILABLE :
124                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
125                 }
126         } else {
127                 _DtCm_libentry          *entries;
128                 cms_access_entry        *alist;
129
130                 cal->rpc_version = ci->vers_out;
131                 cal->file_version = ci->vers_out - 1;
132  
133                 /*
134                  * call lookup_range to check the existence of
135                  * the calendar
136                  */
137                 if ((stat = _DtCm_table_lookup_range(cal, 0, 0, B_TRUE, 0, 0,
138                     0, 0, NULL, NULL, &entries)) == CSA_SUCCESS) {
139                         if (entries) _DtCm_free_libentries(entries);
140
141                         if ((stat = _DtCm_table_get_access(cal, &alist))
142                             == CSA_SUCCESS) {
143                                 stat = _GetV4UserAccess(cal, alist);
144                                 _DtCm_free_cms_access_entry(alist);
145                         }
146                 }
147         }
148         return (stat);
149 }
150
151 extern CSA_return_code
152 _DtCm_rpc_create_calendar(
153         Calendar *cal,
154         CSA_uint32 num_attrs,
155         CSA_attribute * attrs)
156 {
157         _DtCm_Client_Info       *ci=NULL;
158         CSA_return_code stat = CSA_SUCCESS;
159
160         DP(("rpccalls.c: _DtCm_rpc_create_calendar\n"));
161
162         if (cal == NULL)
163                 return (CSA_E_INVALID_PARAMETER);
164
165         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
166             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
167                 return (stat);
168         }
169         cal->conn.ci = ci;
170         cal->conn.retry = B_FALSE;
171
172         if (ci->vers_out == TABLEVERS) {
173                 cms_create_args args;
174                 CSA_return_code *res;
175                 CSA_uint32      num_cmsattrs;
176                 cms_attribute   *cmsattrs;
177
178                 if ((stat = csa2cmsattrs(num_attrs, attrs, NULL, &num_cmsattrs,
179                     &cmsattrs, NULL)) != CSA_SUCCESS)
180                         return (stat);
181
182                 args.cal        = cal->name;
183                 args.char_set   = nullstr;
184                 args.pid        = getpid();
185                 args.num_attrs  = num_cmsattrs;
186                 args.attrs      = cmsattrs;
187
188                 res = cms_create_calendar_5(&args, &cal->conn);
189
190                 if (num_cmsattrs) free_cmsattrs(num_cmsattrs, cmsattrs);
191
192                 if (res != NULL) {
193                         stat = *res;
194                 } else {
195                         stat = (cal->conn.stat == RPC_SUCCESS) ?
196                                 CSA_E_SERVICE_UNAVAILABLE :
197                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
198                 }
199         } else if (ci->vers_out == TABLEVERS_4) {
200
201                 if ((stat = _DtCm_table_create(cal))
202                     == CSA_SUCCESS && num_attrs > 0) {
203
204                         int     i;
205
206                         /*
207                          * for old backends, the only settable
208                          * calendar attribute is access list
209                          */
210                         for (i = num_attrs - 1; i >= 0; i--) {
211                                 if (attrs[i].name)
212                                         break;
213                         }
214                         if (attrs[i].value == NULL)
215                                 stat = _DtCm_table_set_access(cal, NULL);
216                         else
217                                 stat = _DtCm_table_set_access(cal,
218                                         attrs[i].value->item.access_list_value);
219                 }
220
221         } else if (ci->vers_out < TABLEVERS_4) {
222                 _DtCm_libentry          *entries;
223                 char                    *ptr, *owner;
224                 boolean_t               isuser;
225
226                 /* check to make sure user is not creating a calendar
227                  * using another user's name
228                  */
229                 if (ptr = strchr(cal->name, '@')) *ptr = NULL;
230                 if (_DtCmIsUserName(cal->name) == B_TRUE) {
231
232                         if ((owner = _DtCmGetUserName()) == NULL)
233                                 stat = CSA_E_FAILURE;
234
235                         if (strcmp(cal->name, owner))
236                                 stat = CSA_E_NO_AUTHORITY;
237                 } else
238                         stat = CSA_E_INVALID_PARAMETER;
239                 if (ptr) *ptr = '@';
240
241                 /*
242                  * for v2 and v3 servers, calling a lookup routine has
243                  * the side effect of having a calendar created
244                  * the calendar
245                  */
246                 if (stat == CSA_SUCCESS &&
247                     (stat = _DtCm_table_lookup_range(cal, 0, 0, B_TRUE, 0, 0,
248                     0, 0, NULL, NULL, &entries)) == CSA_SUCCESS) {
249                         if (entries) _DtCm_free_libentries(entries);
250                 }
251         }
252         return (stat);
253 }
254
255 extern CSA_return_code
256 _DtCm_rpc_delete_calendar(Calendar *cal)
257 {
258         CSA_return_code         stat;
259         _DtCm_Client_Info       *ci;
260
261         DP(("rpccalls.c: _DtCm_rpc_delete_calendar\n"));
262
263         if (cal == NULL)
264                 return (CSA_E_INVALID_PARAMETER);
265
266         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
267             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
268                 return (stat);
269         }
270
271         cal->conn.ci = ci;
272         cal->conn.retry = B_FALSE;
273
274         if (ci->vers_out == TABLEVERS) {
275                 cms_remove_args arg;
276                 CSA_return_code *res;
277
278                 arg.cal = cal->name;
279                 arg.pid = getpid();
280
281                 res = cms_remove_calendar_5(&arg, &cal->conn);
282
283                 if (res != NULL) {
284                         stat = *res;
285                 } else {
286                         stat = (cal->conn.stat == RPC_SUCCESS) ?
287                                 CSA_E_SERVICE_UNAVAILABLE :
288                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
289                 }
290         } else
291                 stat = CSA_E_NOT_SUPPORTED;
292
293         return (stat);
294 }
295
296 extern CSA_return_code
297 _DtCm_rpc_register_client(Calendar *cal, unsigned long update_type)
298 {
299         CSA_return_code stat;
300         _DtCm_Client_Info *ci = NULL;
301
302         DP(("rpccalls.c: _DtCm_rpc_register_client\n"));
303
304         if (cal == NULL)
305                 return (CSA_E_INVALID_PARAMETER);
306
307         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
308             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
309                 return (stat);
310         }
311
312         cal->conn.ci = ci;
313         cal->conn.retry = B_TRUE;
314
315         return (_DtCm_do_registration(&cal->conn, cal->name, update_type));
316 }
317
318 extern CSA_return_code
319 _DtCm_rpc_unregister_client(Calendar *cal, unsigned long update_type)
320 {
321         CSA_return_code stat;
322         _DtCm_Client_Info *ci = NULL;
323
324         DP(("rpccalls.c: _DtCm_rpc_unregister_client\n"));
325
326         if (cal == NULL)
327                 return (CSA_E_INVALID_PARAMETER);
328
329         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
330             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
331                 return (stat);
332         }
333
334         cal->conn.ci = ci;
335         cal->conn.retry = B_TRUE;
336
337         return (_DtCm_do_unregistration(&cal->conn, cal->name, update_type));
338 }
339
340 extern CSA_return_code
341 _DtCm_rpc_lookup_reminder(
342         Calendar *cal,
343         time_t tick,
344         CSA_uint32 num_names,
345         char **reminder_names,
346         CSA_uint32 *num_rems,
347         CSA_reminder_reference **rems)
348 {
349         _DtCm_Client_Info       *ci=NULL;
350         CSA_return_code stat = CSA_SUCCESS;
351
352         DP(("rpccalls.c: _DtCm_rpc_lookup_reminder\n"));
353
354         if (cal == NULL || num_rems == 0 || rems == NULL)
355                 return (CSA_E_INVALID_PARAMETER);
356
357         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
358             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
359                 return (stat);
360         }
361         cal->conn.ci = ci;
362         cal->conn.retry = B_TRUE;
363
364         if (ci->vers_out == TABLEVERS) {
365                 cms_reminder_args       args;
366                 cms_reminder_res        *res;
367                 CSA_uint32      num_cmsnames;
368                 cms_attr_name   *cmsnames;
369
370                 if ((stat = csa2cmsnames(num_names, reminder_names,
371                     &num_cmsnames, &cmsnames)) != CSA_SUCCESS)
372                         return (stat);
373
374                 args.cal        = cal->name;
375                 args.tick       = tick;
376                 args.num_names  = num_cmsnames;
377                 args.names      = cmsnames;
378
379                 res = cms_lookup_reminder_5(&args, &cal->conn);
380
381                 if (cmsnames)
382                         free(cmsnames);
383
384                 if (res != NULL) {
385                         if ((stat = res->stat) == CSA_SUCCESS)
386                                 stat = _DtCm_cms2csa_reminder_ref(res->rems,
387                                         num_rems, rems);
388                 } else {
389                         stat = (cal->conn.stat == RPC_SUCCESS) ?
390                                 CSA_E_SERVICE_UNAVAILABLE :
391                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
392                 }
393         } else {
394  
395                 stat = _DtCm_table_lookup_reminder(cal, num_names,
396                         reminder_names, num_rems, rems);
397         }
398
399         return(stat);
400 }
401
402 /*
403  * Lookup calendar entries.
404  * If it's an old server, will try to match the attributes in the library;
405  * but if attrlist contains attributes not supported by the old backend,
406  * will just return CSA_E_UNSUPPORTED_ATTRIBUTE.
407  */
408 extern CSA_return_code
409 _DtCm_rpc_lookup_entries(
410         Calendar *cal,
411         CSA_uint32 num_attrs,
412         CSA_attribute * attrs,
413         CSA_enum *ops,
414         _DtCm_libentry **elist_r)
415 {
416         _DtCm_Client_Info       *ci=NULL;
417         CSA_return_code stat = CSA_SUCCESS;
418
419         DP(("rpccalls.c: _DtCm_rpc_lookup_entries\n"));
420
421         if (cal == NULL)
422                 return (CSA_E_INVALID_PARAMETER);
423
424         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
425             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
426                 return (stat);
427         }
428         cal->conn.ci = ci;
429         cal->conn.retry = B_TRUE;
430
431         *elist_r = NULL;
432
433         if (ci->vers_out == TABLEVERS) {
434                 cms_lookup_entries_args args;
435                 cms_entries_res         *res;
436                 CSA_uint32              num_cmsattrs;
437                 cms_attribute           *cmsattrs;
438                 CSA_enum                *newops;
439
440                 if ((stat = csa2cmsattrs(num_attrs, attrs, ops, &num_cmsattrs,
441                     &cmsattrs, &newops)) != CSA_SUCCESS)
442                         return (stat);
443
444                 args.cal = cal->name;
445                 args.char_set = nullstr;
446                 args.num_attrs = num_cmsattrs;
447                 args.attrs = cmsattrs;
448                 args.ops = newops;
449
450                 res = cms_lookup_entries_5(&args, &cal->conn);
451
452                 free_cmsattrs(num_cmsattrs, cmsattrs);
453                 if (newops) free(newops);
454
455                 if (res != NULL) {
456                         if ((stat = res->stat) == CSA_SUCCESS) {
457                                 stat = _DtCmCmsentriesToLibentries(
458                                         &cal->entry_tbl, res->entries, elist_r);
459                         }
460
461                         xdr_free((xdrproc_t)xdr_cms_entries_res, (char *)res);
462                 } else {
463                         stat = (cal->conn.stat == RPC_SUCCESS) ?
464                                 CSA_E_SERVICE_UNAVAILABLE :
465                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
466                 }
467         } else {
468                 time_t          start1, start2, end1, end2;
469                 long            id;
470                 boolean_t       no_start_time_range;
471                 boolean_t       no_end_time_range;
472                 boolean_t       no_match;
473                 CSA_uint32      hnum;
474                 cms_attribute   *hattrs;
475                 CSA_enum        *hops;
476                 cms_key         key;
477                 _DtCm_libentry  *entry;
478  
479                 /* hash the matching criteria */
480                 if ((stat = _DtCmHashCriteria(cal->entry_tbl, num_attrs, attrs,
481                     NULL, ops, &no_match, &no_start_time_range,
482                     &no_end_time_range, &start1, &start2, &end1, &end2, &id,
483                     &hnum, &hattrs, &hops)) == CSA_E_INVALID_ATTRIBUTE)
484                 {
485                         return (CSA_SUCCESS);
486                 } else if (stat != CSA_SUCCESS || no_match == B_TRUE) {
487                         return (stat);
488                 }
489
490                 if (id > 0 && no_start_time_range && no_end_time_range) {
491                         /* get the key for the first event */
492                         key.id = 0;
493                         if ((stat = _DtCm_table_lookup_key_range(cal, NULL, id,
494                             _DtCM_BOT, _DtCM_EOT, &key, NULL)) == CSA_SUCCESS &&
495                             key.id > 0) {
496
497                                 /* get the detail */
498                                 if ((stat = _DtCm_make_libentry(NULL, &entry))
499                                     == CSA_SUCCESS) {
500                                         entry->e->key = key;
501
502                                         if ((stat = _DtCm_table_lookup(cal,
503                                             entry)) == CSA_SUCCESS)
504                                                 *elist_r = entry;
505                                         else
506                                                 _DtCm_free_libentries(entry);
507                                 }
508                         }
509                 } else {
510                         stat = _DtCm_table_lookup_range(cal, start1, start2,
511                                 no_end_time_range, end1, end2,
512                                 id, hnum, hattrs, hops, elist_r);
513                 }
514
515                 _DtCmFreeHashedArrays(hnum, hattrs, hops);
516         }
517
518         return(stat);
519 }
520
521 extern CSA_return_code
522 _DtCm_rpc_enumerate_sequence(
523         Calendar *cal,
524         _DtCm_libentry *entry,
525         time_t start,
526         time_t end,
527         _DtCm_libentry **elist_r)
528 {
529         _DtCm_Client_Info       *ci=NULL;
530         CSA_return_code stat = CSA_SUCCESS;
531         int             i;
532
533         DP(("rpccalls.c: _DtCm_rpc_enumerate_sequence\n"));
534
535         if (cal == NULL)
536                 return (CSA_E_INVALID_PARAMETER);
537
538         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
539             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
540                 return (stat);
541         }
542         cal->conn.ci = ci;
543         cal->conn.retry = B_TRUE;
544
545         *elist_r = NULL;
546
547         if (ci->vers_out == TABLEVERS) {
548                 cms_enumerate_args      args;
549                 cms_entries_res         *res;
550
551                 args.cal = cal->name;
552                 args.id = entry->e->key.id;
553                 args.start = start;
554                 args.end = end;
555
556                 res = cms_enumerate_sequence_5(&args, &cal->conn);
557
558                 if (res != NULL) {
559                         if ((stat = res->stat) == CSA_SUCCESS) {
560                                 stat = _DtCmCmsentriesToLibentries(
561                                         &cal->entry_tbl, res->entries, elist_r);
562                         }
563
564                         xdr_free((xdrproc_t)xdr_cms_entries_res, (char *)res);
565                 } else {
566                         stat = (cal->conn.stat == RPC_SUCCESS) ?
567                                 CSA_E_SERVICE_UNAVAILABLE :
568                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
569                 }
570
571         } else {
572  
573                 stat = _DtCm_table_lookup_key_range(cal, entry, 0, start, end,
574                         NULL, elist_r);
575         }
576
577         return(stat);
578 }
579
580 extern CSA_return_code
581 _DtCm_rpc_lookup_entry_by_id(Calendar *cal, _DtCm_libentry *entry)
582 {
583         _DtCm_Client_Info       *ci=NULL;
584         CSA_return_code stat = CSA_SUCCESS;
585         int             i;
586
587         DP(("rpccalls.c: _DtCm_rpc_lookup_entry_by_id\n"));
588
589         if (cal == NULL)
590                 return (CSA_E_INVALID_PARAMETER);
591
592         if ((stat = _DtCm_create_tcp_client(cal->location,
593             (cal->file_version < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION ?
594             TABLEVERS_4 : TABLEVERS), _DtCM_LONG_TIMEOUT, &ci))
595             != CSA_SUCCESS) {
596                 return (stat);
597         }
598         cal->conn.ci = ci;
599         cal->conn.retry = B_TRUE;
600
601         if (ci->vers_out == TABLEVERS) {
602                 cms_get_entry_attr_args args;
603                 cms_get_entry_attr_res  *res;
604
605                 /*
606                  * the entry reference id is filled in already
607                  * otherwise, we would not be in this routine
608                  */
609                 args.cal = cal->name;
610                 args.num_keys = 1;
611                 args.keys = &entry->e->key;
612                 args.num_names = 0;
613                 args.names = NULL;
614
615                 res = cms_get_entry_attr_5(&args, &cal->conn);
616
617                 if (res != NULL) {
618                         if (res->entries) {
619                                 if ((stat = res->entries->stat) == CSA_SUCCESS)
620                                 {
621                                         if ((stat = _DtCmUpdateAttributes(
622                                             res->entries->num_attrs,
623                                             res->entries->attrs,
624                                             &entry->e->num_attrs,
625                                             &entry->e->attrs,
626                                             &cal->entry_tbl, B_FALSE,
627                                             NULL, B_TRUE)) == CSA_SUCCESS)
628                                         {
629                                                 entry->filled = B_TRUE;
630                                         }
631                                 }
632                         } else
633                                 stat = res->stat;
634                 } else {
635                         stat = (cal->conn.stat == RPC_SUCCESS) ?
636                                 CSA_E_SERVICE_UNAVAILABLE :
637                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
638                 }
639
640                 if (res) xdr_free((xdrproc_t)xdr_cms_get_entry_attr_res, (char *)res);
641         } else {
642  
643                 stat = _DtCm_table_lookup(cal, entry);
644         }
645
646         return(stat);
647 }
648
649 extern CSA_return_code
650 _DtCm_rpc_get_cal_attrs(Calendar *cal, int index, CSA_uint32 num_names, char **names)
651 {
652         _DtCm_Client_Info       *ci;
653         CSA_return_code         stat = CSA_SUCCESS;
654         cms_attribute_value     val;
655
656         DP(("rpccalls.c: _DtCm_rpc_get_cal_attrs\n"));
657
658         if (cal == NULL)
659                 return (CSA_E_INVALID_PARAMETER);
660
661         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
662             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
663                 return (stat);
664         }
665
666         cal->conn.ci = ci;
667         cal->conn.retry = B_TRUE;
668
669         if (ci->vers_out == TABLEVERS) {
670                 cms_get_cal_attr_args   arg;
671                 cms_get_cal_attr_res    *res;
672                 CSA_uint32              num_cmsnames;
673                 cms_attr_name           *cmsnames;
674
675                 if ((stat = csa2cmsnames(num_names, names,
676                     &num_cmsnames, &cmsnames)) != CSA_SUCCESS)
677                         return (stat);
678
679                 arg.cal = cal->name;
680                 arg.num_names = num_cmsnames;
681                 arg.names = cmsnames;
682
683                 res = cms_get_calendar_attr_5(&arg, &cal->conn);
684
685                 if (res != NULL) {
686                         if ((stat = res->stat) == CSA_SUCCESS) {
687                                 if ((stat = _DtCmUpdateAttributes(
688                                     res->num_attrs, res->attrs, &cal->num_attrs,
689                                     &cal->attrs, &cal->cal_tbl, B_TRUE, NULL,
690                                     B_TRUE)) == CSA_SUCCESS)
691                                         cal->got_attrs = B_TRUE;
692                         }
693
694                         xdr_free((xdrproc_t)xdr_cms_get_cal_attr_res, (char *)res);
695                 } else {
696                         stat = (cal->conn.stat == RPC_SUCCESS) ?
697                                 CSA_E_SERVICE_UNAVAILABLE :
698                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
699                 }
700         } else {
701
702                 switch (index) {
703                 case CSA_CAL_ATTR_ACCESS_LIST_I:
704                         if ((stat = _DtCm_table_get_access(cal,
705                             &val.item.access_list_value)) == CSA_SUCCESS) {
706                                 val.type = CSA_VALUE_ACCESS_LIST;
707                                 stat = _DtCmUpdateAccessListAttrVal(&val,
708                                         &cal->attrs\
709                                         [CSA_CAL_ATTR_ACCESS_LIST_I].value);
710                                 _DtCm_free_cms_access_entry(val.item.\
711                                         access_list_value);
712                         }
713                         break;
714
715                 case CSA_CAL_ATTR_NUMBER_ENTRIES_I:
716                         if ((stat = _DtCm_table_size(cal,
717                             (int*)&val.item.uint32_value)) == CSA_SUCCESS) {
718                                 val.type = CSA_VALUE_UINT32;
719                                 stat = _DtCmUpdateSint32AttrVal(&val,
720                                         &cal->attrs\
721                                         [CSA_CAL_ATTR_NUMBER_ENTRIES_I].value);
722                         }
723                         break;
724
725                 }
726         }
727         return(stat);
728 }
729
730 extern CSA_return_code
731 _DtCm_rpc_set_cal_attrs(Calendar *cal, CSA_uint32 num_attrs, CSA_attribute * attrs)
732 {
733         _DtCm_Client_Info       *ci;
734         CSA_return_code stat = CSA_SUCCESS;
735         int             i;
736
737         DP(("rpccalls.c: _DtCm_rpc_set_cal_attrs\n"));
738
739         if (cal == NULL || attrs == NULL)
740                 return (CSA_E_INVALID_PARAMETER);
741
742         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
743             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS)
744         {
745                 return (stat);
746         }
747
748         cal->conn.ci = ci;
749         cal->conn.retry = B_FALSE;
750
751         if (ci->vers_out == TABLEVERS) {
752                 CSA_return_code         *res;
753                 cms_set_cal_attr_args   args;
754                 CSA_uint32      num_cmsattrs;
755                 cms_attribute   *cmsattrs;
756
757                 if ((stat = csa2cmsattrs(num_attrs, attrs, NULL, &num_cmsattrs,
758                     &cmsattrs, NULL)) != CSA_SUCCESS)
759                         return (stat);
760
761                 if (num_cmsattrs == 0)
762                         return (CSA_E_INVALID_PARAMETER);
763
764                 args.cal = cal->name;
765                 args.pid = getpid();
766                 args.num_attrs = num_cmsattrs;
767                 args.attrs = cmsattrs;
768
769                 res = cms_set_calendar_attr_5(&args, &cal->conn);
770
771                 free_cmsattrs(num_cmsattrs, cmsattrs);
772
773                 if (res != NULL) {
774                         stat = *res;
775                         if (stat == CSA_SUCCESS) {
776                                 _DtCm_free_cms_attribute_values(cal->num_attrs,
777                                         cal->attrs);
778                         }
779                 } else {
780                         stat = (cal->conn.stat == RPC_SUCCESS) ?
781                                 CSA_E_SERVICE_UNAVAILABLE :
782                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
783                 }
784
785         } else {
786                 int     i;
787
788                 /*
789                  * CSA_CAL_ATTR_ACCESS_LIST is the only settable attribute
790                  */
791                 for (i = num_attrs - 1; i >= 0; i--) {
792                         if (attrs[i].name)
793                                 break;
794                 }
795                 if (attrs[i].value == NULL)
796                         stat = _DtCm_table_set_access(cal, NULL);
797                 else
798                         stat = _DtCm_table_set_access(cal,
799                                 attrs[i].value->item.access_list_value);
800         }
801
802         return (stat);
803 }
804
805 extern CSA_return_code
806 _DtCm_rpc_insert_entry(
807         Calendar *cal,
808         CSA_uint32 num_attrs,
809         CSA_attribute * attrs,
810         _DtCm_libentry **entry_r)
811 {
812         _DtCm_Client_Info       *ci = NULL;
813         CSA_return_code         stat = CSA_SUCCESS;
814
815         DP(("rpccalls.c: _DtCm_rpc_insert_entry;\n"));
816
817         if (cal == NULL || num_attrs == 0 || attrs == NULL || entry_r == NULL)
818                 return (CSA_E_INVALID_PARAMETER);
819
820         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
821             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS)
822         {
823                 return (stat);
824         }
825         cal->conn.ci = ci;
826         cal->conn.retry = B_FALSE;
827
828         if (ci->vers_out == TABLEVERS) {
829                 cms_entry_res   *res;
830                 cms_insert_args args;
831                 CSA_uint32      num_cmsattrs;
832                 cms_attribute   *cmsattrs;
833
834                 if ((stat = csa2cmsattrs(num_attrs, attrs, NULL, &num_cmsattrs,
835                     &cmsattrs, NULL)) != CSA_SUCCESS)
836                         return (stat);
837
838                 if (num_cmsattrs == 0)
839                         return (CSA_E_INVALID_PARAMETER);
840
841                 args.cal = cal->name;
842                 args.pid = getpid();
843                 args.num_attrs = num_cmsattrs;
844                 args.attrs = cmsattrs;
845
846                 res = cms_insert_entry_5(&args, &cal->conn);
847
848                 free_cmsattrs(num_cmsattrs, cmsattrs);
849
850                 if (res != NULL) {
851                         if ((stat = res->stat) == CSA_SUCCESS) {
852                                 stat = _DtCmCmsentriesToLibentries(
853                                         &cal->entry_tbl, res->entry, entry_r);
854                         }
855
856                         xdr_free((xdrproc_t)xdr_cms_entry_res, (char *)res);
857                 } else {
858                         stat = (cal->conn.stat == RPC_SUCCESS) ?
859                                 CSA_E_SERVICE_UNAVAILABLE :
860                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
861                 }
862
863         } else {
864  
865                 stat = _DtCm_table_insert(cal, num_attrs, attrs, entry_r);
866         }
867
868         return(stat);
869 }
870
871 extern CSA_return_code
872 _DtCm_rpc_update_entry(
873         Calendar *cal,
874         _DtCm_libentry *oentry,
875         CSA_uint32 num_attrs,
876         CSA_attribute * attrs,
877         CSA_enum scope,
878         _DtCm_libentry **nentry)
879 {
880         _DtCm_Client_Info       *ci = NULL;
881         CSA_return_code stat = CSA_SUCCESS;
882         _DtCm_libentry  *hptr = NULL, *tptr, *cptr;
883         int i;
884
885         DP(("rpccalls.c: _DtCm_rpc_update_entry\n"));
886
887         if (cal == NULL || oentry == NULL)
888                 return (CSA_E_INVALID_PARAMETER);
889
890         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
891             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS)
892         {
893                 return (stat);
894         }
895         cal->conn.ci = ci;
896         cal->conn.retry = B_FALSE;
897
898         if (ci->vers_out == TABLEVERS) {
899                 cms_entry_res   *res;
900                 cms_update_args args;
901                 CSA_uint32      num_cmsattrs;
902                 cms_attribute   *cmsattrs;
903
904                 if ((stat = csa2cmsattrs(num_attrs, attrs, NULL, &num_cmsattrs,
905                     &cmsattrs, NULL)) != CSA_SUCCESS)
906                         return (stat);
907
908                 if (num_cmsattrs == 0)
909                         return (CSA_E_INVALID_PARAMETER);
910
911                 args.cal = cal->name;
912                 args.pid = getpid();
913                 args.entry = oentry->e->key;
914                 args.scope = scope;
915                 args.num_attrs = num_cmsattrs;
916                 args.attrs = cmsattrs;
917
918                 res = cms_update_entry_5(&args, &cal->conn);
919
920                 free_cmsattrs(num_cmsattrs, cmsattrs);
921
922                 if (res != NULL) {
923                         if ((stat = res->stat) == CSA_SUCCESS) {
924                                 stat = _DtCmCmsentriesToLibentries(
925                                         &cal->entry_tbl, res->entry, nentry);
926                         }
927
928                         xdr_free((xdrproc_t)xdr_cms_entry_res, (char *)res);
929                 } else {
930                         stat = (cal->conn.stat == RPC_SUCCESS) ?
931                                 CSA_E_SERVICE_UNAVAILABLE :
932                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
933                 }
934
935         } else {
936  
937                 stat = _DtCm_table_update(cal, oentry, num_attrs, attrs,
938                                 scope, nentry);
939         }
940
941         return(stat);
942
943 }
944
945 extern CSA_return_code
946 _DtCm_rpc_delete_entry(
947         Calendar *cal,
948         _DtCm_libentry *entry,
949         CSA_enum scope)
950 {
951         _DtCm_Client_Info       *ci = NULL;
952         CSA_return_code stat = CSA_SUCCESS;
953
954         DP(("rpccalls.c: _DtCm_rpc_delete_entry\n"));
955
956         if (cal == NULL || entry == NULL)
957                 return (CSA_E_INVALID_PARAMETER);
958
959         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
960             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS)
961         {
962                 return (stat);
963         }
964         cal->conn.ci = ci;
965         cal->conn.retry = B_FALSE;
966
967         if (ci->vers_out == TABLEVERS) {
968                 CSA_return_code *res;
969                 cms_delete_args args;
970
971                 args.cal = cal->name;
972                 args.pid = getpid();
973                 args.entry = entry->e->key;
974                 args.scope = scope;
975
976                 res = cms_delete_entry_5(&args, &cal->conn);
977
978                 if (res != NULL) {
979                         stat = *res;
980                 } else {
981                         stat = (cal->conn.stat == RPC_SUCCESS) ?
982                                 CSA_E_SERVICE_UNAVAILABLE :
983                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
984                 }
985
986         } else {
987  
988                 stat = _DtCm_table_delete(cal, entry, scope);
989         }
990
991         return(stat);
992 }
993
994 extern CSA_return_code
995 _DtCm_rpc_list_calendar_attributes(
996         Calendar        *cal,
997         CSA_uint32      *number_names,
998         char            ***names_r)
999 {
1000         _DtCm_Client_Info       *ci = NULL;
1001         CSA_return_code stat = CSA_SUCCESS;
1002
1003         DP(("rpccalls.c: _DtCm_rpc_list_calendar_attributes\n"));
1004
1005         if (cal == NULL)
1006                 return (CSA_E_INVALID_PARAMETER);
1007
1008         if ((stat = _DtCm_create_tcp_client(cal->location, TABLEVERS,
1009             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
1010                 return (stat);
1011         }
1012         cal->conn.ci = ci;
1013         cal->conn.retry = B_TRUE;
1014
1015         if (ci->vers_out == TABLEVERS) {
1016                 cms_enumerate_calendar_attr_res *res;
1017                 char                            **names;
1018                 int                             i;
1019
1020                 *number_names = 0;
1021                 *names_r = NULL;
1022
1023                 res = cms_enumerate_calendar_attr_5(&cal->name, &cal->conn);
1024
1025                 if (res != NULL) {
1026                         if ((stat = res->stat) == CSA_SUCCESS && res->num_names)
1027                         {
1028                                 if (names = _DtCm_alloc_character_pointers(
1029                                     res->num_names)) {
1030                                         for (i = 0; i < res->num_names; i++) {
1031                                                 if ((names[i] = strdup(
1032                                                     res->names[i].name))
1033                                                     == NULL) {
1034                                                         _DtCm_free(names);
1035                                                         return (CSA_E_INSUFFICIENT_MEMORY);
1036                                                 }
1037                                         }
1038                                         *number_names = res->num_names;
1039                                         *names_r = names;
1040                                 }
1041                         }
1042                 } else {
1043                         stat = (cal->conn.stat == RPC_SUCCESS) ?
1044                                 CSA_E_SERVICE_UNAVAILABLE :
1045                                 _DtCm_clntstat_to_csastat(cal->conn.stat);
1046                 }
1047
1048         } else {
1049  
1050                 stat = CSA_E_NOT_SUPPORTED;
1051         }
1052
1053         return(stat);
1054 }
1055
1056 extern CSA_return_code
1057 _DtCm_rpc_list_calendars(
1058         char                    *location,
1059         CSA_uint32              *number_names,
1060         CSA_calendar_user       **names_r)
1061 {
1062         _DtCm_Client_Info       *ci = NULL;
1063         CSA_return_code stat = CSA_SUCCESS;
1064         _DtCm_Connection        conn;
1065
1066         DP(("rpccalls.c: _DtCm_rpc_list_calendars\n"));
1067
1068         if ((stat = _DtCm_create_tcp_client(location, TABLEVERS,
1069             _DtCM_LONG_TIMEOUT, &ci)) != CSA_SUCCESS) {
1070                 return (stat);
1071         }
1072         conn.ci = ci;
1073         conn.retry = B_TRUE;
1074
1075         if (ci->vers_out == TABLEVERS) {
1076                 cms_list_calendars_res  *res;
1077                 CSA_calendar_user       *names;
1078                 int                     i;
1079
1080                 *number_names = 0;
1081                 *names_r = NULL;
1082
1083                 res = cms_list_calendars_5(NULL, &conn);
1084
1085                 if (res != NULL) {
1086                         if ((stat = res->stat) == CSA_SUCCESS && res->num_names)
1087                         {
1088                                 if (names = _DtCm_alloc_calendar_users(
1089                                     res->num_names)) {
1090                                         for (i = 0; i < res->num_names; i++) {
1091                                                 if ((names[i].calendar_address =
1092                                                     strdup(res->names[i]))
1093                                                     == NULL) {
1094                                                         _DtCm_free(names);
1095                                                         return (CSA_E_INSUFFICIENT_MEMORY);
1096                                                 }
1097                                         }
1098                                         *number_names = res->num_names;
1099                                         *names_r = names;
1100                                 }
1101                         }
1102                 } else {
1103                         stat = (conn.stat == RPC_SUCCESS) ?
1104                                 CSA_E_SERVICE_UNAVAILABLE :
1105                                 _DtCm_clntstat_to_csastat(conn.stat);
1106                 }
1107
1108         } else {
1109  
1110                 stat = CSA_E_NOT_SUPPORTED;
1111         }
1112
1113         return(stat);
1114 }
1115
1116 extern CSA_return_code
1117 _DtCm_do_unregistration(
1118         _DtCm_Connection *conn,
1119         char *cal,
1120         unsigned long update_type)
1121 {
1122         CSA_return_code stat;
1123
1124         if (conn->ci->vers_out == TABLEVERS) {
1125                 cms_register_args args;
1126                 CSA_return_code *res;
1127
1128                 args.cal = cal;
1129                 args.update_type = update_type;
1130                 args.prognum = _DtCm_transient;
1131                 args.versnum = AGENTVERS_2;
1132                 args.procnum = update_callback;
1133                 args.pid = getpid();
1134
1135                 res = cms_unregister_5(&args, conn);
1136
1137                 if (res != NULL) {
1138                         stat = *res;
1139                 } else {
1140                         stat = (conn->stat == RPC_SUCCESS) ?
1141                                 CSA_E_SERVICE_UNAVAILABLE :
1142                                 _DtCm_clntstat_to_csastat(conn->stat);
1143                 }
1144         } else {
1145                 stat = _DtCm_table_unregister_target(conn, cal);
1146         }
1147
1148         if (stat == CSA_SUCCESS)
1149                 _DtCm_remove_registration(conn->ci, cal);
1150
1151         return (stat);
1152 }
1153
1154 extern CSA_return_code
1155 _DtCm_do_registration(
1156         _DtCm_Connection *conn,
1157         char *cal,
1158         unsigned long update_type)
1159 {
1160         CSA_return_code stat;
1161
1162         if (conn->ci->vers_out == TABLEVERS) {
1163                 cms_register_args args;
1164                 CSA_return_code *res;
1165
1166                 args.cal = cal;
1167                 args.update_type = update_type;
1168                 args.prognum = _DtCm_transient;
1169                 args.versnum = AGENTVERS_2;
1170                 args.procnum = update_callback;
1171                 args.pid = getpid();
1172
1173                 res = cms_register_5(&args, conn);
1174
1175                 if (res != NULL)
1176                         stat = *res;
1177                 else {
1178                         stat = (conn->stat == RPC_SUCCESS) ?
1179                                 CSA_E_SERVICE_UNAVAILABLE :
1180                                 _DtCm_clntstat_to_csastat(conn->stat);
1181                 }
1182         } else {
1183
1184                 stat = _DtCm_table_register_target(conn, cal);
1185         }
1186
1187         if (stat == CSA_SUCCESS) {
1188                 if ((stat = _DtCm_add_registration(conn->ci, cal, update_type))
1189                     != CSA_SUCCESS) {
1190                         (void) _DtCm_do_unregistration(conn, cal, update_type);
1191                 }
1192         }
1193
1194         return (stat);
1195 }
1196
1197 /*****************************************************************************
1198  * static functions used within the file
1199  *****************************************************************************/
1200
1201 /*
1202  * Newnum is initialized to 0 and newattrs to NULL when num_attrs == 0
1203  */
1204 static CSA_return_code
1205 csa2cmsattrs(
1206         CSA_uint32      num_attrs,
1207         CSA_attribute   *csaattrs,
1208         CSA_enum        *ops,
1209         CSA_uint32      *newnum,
1210         cms_attribute   **newattrs,
1211         CSA_enum        **newops)
1212 {
1213         CSA_return_code stat = CSA_SUCCESS;
1214         cms_attribute   *cmsattrs;
1215         CSA_enum        *ops_r;
1216         CSA_reminder    *rptr1, *rptr2;
1217         int             i,j;
1218
1219         *newnum = 0;
1220         *newattrs = NULL;
1221         if (newops) *newops = NULL;
1222
1223         if (num_attrs == 0)
1224                 return CSA_SUCCESS;
1225
1226         if ((cmsattrs = calloc(1, sizeof(cms_attribute)*num_attrs)) == NULL)
1227                 return (CSA_E_INSUFFICIENT_MEMORY);
1228
1229         if (newops && (ops_r = malloc(sizeof(CSA_enum)*num_attrs)) == NULL) {
1230                 free(cmsattrs);
1231                 return (CSA_E_INSUFFICIENT_MEMORY);
1232         }
1233
1234         for (i = 0, j = 0; i < num_attrs && stat == CSA_SUCCESS; i++) {
1235                 if (csaattrs[i].name == NULL)
1236                         continue;
1237
1238                 if (newops)
1239                         ops_r[j] = (ops ? ops[i] : CSA_MATCH_EQUAL_TO);
1240
1241                 cmsattrs[j].name.name = csaattrs[i].name;
1242                 if (csaattrs[i].value == NULL) {
1243                         j++;
1244                         continue;
1245                 }
1246
1247                 if ((cmsattrs[j].value = (cms_attribute_value *)malloc(
1248                     sizeof(cms_attribute_value))) == NULL) {
1249                         stat = CSA_E_INSUFFICIENT_MEMORY;
1250                         break;
1251                 }
1252
1253                 cmsattrs[j].value->type = csaattrs[i].value->type;
1254
1255                 switch (csaattrs[i].value->type) {
1256                 case CSA_VALUE_ACCESS_LIST:
1257                         stat = _DtCm_csa2cms_access_list(
1258                                 csaattrs[i].value->item.access_list_value,
1259                                 &cmsattrs[j].value->item.access_list_value);
1260                         break;
1261                 case CSA_VALUE_CALENDAR_USER:
1262                         if (csaattrs[i].value->item.calendar_user_value &&
1263                             csaattrs[i].value->item.calendar_user_value->\
1264                             user_name)
1265                         {
1266                                 cmsattrs[j].value->item.calendar_user_value =
1267                                         csaattrs[i].value->item.\
1268                                         calendar_user_value->user_name;
1269                         } else {
1270                                 cmsattrs[j].value->item.calendar_user_value =
1271                                         nullstr;
1272                         }
1273                         break;
1274                 case CSA_VALUE_STRING:
1275                 case CSA_VALUE_DATE_TIME:
1276                 case CSA_VALUE_DATE_TIME_RANGE:
1277                 case CSA_VALUE_TIME_DURATION:
1278                         if (csaattrs[i].value->item.string_value) {
1279                                 cmsattrs[j].value->item.string_value =
1280                                         csaattrs[i].value->item.string_value;
1281                         } else {
1282                                 cmsattrs[j].value->item.string_value = nullstr;
1283                         }
1284                         break;
1285                 case CSA_VALUE_REMINDER:
1286                         if ((rptr1 = csaattrs[i].value->item.reminder_value) &&
1287                             (rptr2 = (CSA_reminder *)malloc(sizeof(CSA_reminder))))
1288                         {
1289                                 rptr2->lead_time = rptr1->lead_time ?
1290                                                     rptr1->lead_time : nullstr;
1291                                 rptr2->snooze_time = rptr1->snooze_time ?
1292                                                      rptr1->snooze_time:nullstr;
1293                                 rptr2->repeat_count = rptr1->repeat_count;
1294                                 rptr2->reminder_data = rptr1->reminder_data;
1295                                 cmsattrs[j].value->item.reminder_value = rptr2;
1296                         } else if (rptr1 && rptr2 == NULL)
1297                                 stat = CSA_E_INSUFFICIENT_MEMORY;
1298                         break;
1299                 default:
1300                         /* all other value types uses the same type
1301                          * of data, so we just copy the value/address of
1302                          * of the data
1303                          */
1304                         cmsattrs[j].value->item.sint32_value =
1305                                 csaattrs[i].value->item.sint32_value;
1306                 }
1307                 j++;
1308         }
1309
1310         if (stat != CSA_SUCCESS) {
1311
1312                 free_cmsattrs(num_attrs, cmsattrs);
1313                 if (newops) free(ops_r);
1314
1315         } else if (j > 0) {
1316                 *newnum = j;
1317                 *newattrs = cmsattrs;
1318                 if (newops) *newops = ops_r;
1319         } else {
1320                 free(cmsattrs);
1321                 if (newops) free(ops_r);
1322         }
1323
1324         return (stat);
1325 }
1326
1327 static void
1328 free_cmsattrs(CSA_uint32 num_attrs, cms_attribute *attrs)
1329 {
1330         int i;
1331
1332         for (i = 0; i < num_attrs; i++) {
1333                 if (attrs[i].value == NULL)
1334                         continue;
1335
1336                 switch (attrs[i].value->type) {
1337                 case CSA_VALUE_ACCESS_LIST:
1338                         _DtCm_free_cms_access_entry(
1339                                 attrs[i].value->item.access_list_value);
1340                         break;
1341                 case CSA_VALUE_REMINDER:
1342                         if (attrs[i].value->item.reminder_value)
1343                                 free(attrs[i].value->item.reminder_value);
1344                         break;
1345                 }
1346
1347                 free(attrs[i].value);
1348         }
1349         free (attrs);
1350 }
1351
1352 /*
1353  * Newnum is initialized to 0 and newattrs to NULL when num_attrs == 0
1354  */
1355 static CSA_return_code
1356 csa2cmsnames(
1357         CSA_uint32      num_names,
1358         char            **reminder_names,
1359         CSA_uint32      *newnum,
1360         cms_attr_name   **newnames)
1361 {
1362         cms_attr_name   *cmsnames;
1363         int             i,j;
1364
1365         *newnum = 0;
1366         *newnames = NULL;
1367
1368         if (num_names == 0)
1369                 return (CSA_SUCCESS);
1370
1371         if ((cmsnames = calloc(1, sizeof(cms_attr_name)*num_names)) == NULL)
1372                 return (CSA_E_INSUFFICIENT_MEMORY);
1373
1374         for (i = 0, j = 0; i < num_names; i++) {
1375                 if (reminder_names[i] == NULL)
1376                         continue;
1377                 else {
1378                         cmsnames[j].name = reminder_names[i];
1379                         j++;
1380                 }
1381         }
1382
1383         if (j > 0) {
1384                 *newnum = j;
1385                 *newnames = cmsnames;
1386         } else
1387                 free(cmsnames);
1388
1389         return (CSA_SUCCESS);
1390 }
1391
1392 /*
1393  * It is an old server and so we need to determine whether the user
1394  * is the calendar owner ourselves.
1395  * If the calendar name is the same as a user name, then that user
1396  * is the owner, and we just need to make sure the calendar is located
1397  * in the same domain as ours.  If the calendar is located in another
1398  * domain and since we can't do cross domain authentication yet, to be save
1399  * we assume that the user is not the owner.
1400  * If the calendar name is not a user name, we need to make an rpc call
1401  * (table_set_access) to test whether the user is the owner.
1402  */
1403 static CSA_return_code
1404 _GetV4UserAccess(Calendar *cal, cms_access_entry *alist)
1405 {
1406         CSA_return_code stat = CSA_SUCCESS;
1407         char    *user = _DtCmGetUserName();
1408         char    *localhost = _DtCmGetHostAtDomain();
1409         char    buf[BUFSIZ];
1410         char    *ptr, *dom;
1411         int     worldaccess = 0, useraccess = 0;
1412         boolean_t isowner = B_FALSE;
1413
1414         /* first check if user is owner */
1415         if (ptr = strchr(cal->name, '@')) *ptr = NULL;
1416
1417         if (_DtCmIsUserName(cal->name) == B_TRUE) {
1418                 if (strcmp(user, cal->name) == 0) {
1419                         /* check whether calendar location is in
1420                          * the same domain
1421                          */
1422                         if (dom = strchr(cal->location, '.')) dom++;
1423                         if (dom == NULL || _DtCmIsSamePath(
1424                             _DtCmGetLocalDomain(NULL), dom) == B_TRUE)
1425                                 isowner = B_TRUE;
1426                 }
1427         } else {
1428                 CSA_access_rights       *csalist;
1429
1430                 /* need to test whether the user is the owner */
1431                 if ((stat = _DtCm_cms2csa_access_list(alist, &csalist))
1432                     == CSA_SUCCESS) {
1433
1434                         stat = _DtCm_table_set_access(cal, csalist);
1435                         _DtCm_free_csa_access_list(csalist);
1436
1437                         if (stat == CSA_SUCCESS)
1438                                 isowner = B_TRUE;
1439                         else if (stat == CSA_E_NO_AUTHORITY) {
1440                                 isowner = B_FALSE;
1441                                 stat = CSA_SUCCESS;
1442                         }
1443                 }
1444         }
1445         if (ptr) *ptr = '@';
1446         if (stat != CSA_SUCCESS)
1447                 return (stat);
1448
1449         if (isowner) {
1450                 cal->access = CSA_OWNER_RIGHTS;
1451                 return (CSA_SUCCESS);
1452         }
1453
1454         sprintf(buf, "%s@%s", user, localhost);
1455         for (; alist != NULL; alist = alist->next) {
1456                 if (strcasecmp(alist->user, "world") == 0)
1457                         worldaccess = alist->rights;
1458                 else if (_DtCmIsSameUser(buf, alist->user)) {
1459                         useraccess = alist->rights;
1460                         break;
1461                 }
1462         }
1463
1464         cal->access = useraccess | worldaccess;
1465         return (CSA_SUCCESS);
1466 }
1467