Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / csa / table.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: table.c /main/1 1996/04/21 19:24:46 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 #include <EUSCompat.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include "entry.h"
38 #include "appt4.h"
39 #include "attr.h"
40 #include "rtable2.h"
41 #include "rtable3.h"
42 #include "rtable4.h" 
43 #include "convert4-2.h"
44 #include "convert2-4.h"
45 #include "convert4-3.h"
46 #include "convert3-4.h"
47 #include "convert4-5.h"
48 #include "convert5-4.h"
49 #include "connection.h"
50 #include "debug.h"
51 #include "misc.h"
52 #include "agent.h"
53 #include "nametbl.h"
54 #include "match.h"
55 #include "iso8601.h"
56
57 extern u_long   _DtCm_transient;
58
59 #define MAXDAY_LOOKUP           15
60 #define MAXDAY_LOOKUP_SECS      ((DAYSEC*MAXDAY_LOOKUP)+1)
61
62 static char *errfmt = "cm: %s() unexpected return status %d.\n";
63
64 /*****************************************************************************
65  * forward declaration of static functions
66  *****************************************************************************/
67 static CSA_return_code tablestat_to_dtcmstat(
68                         Table_Status_4 stat,
69                         CSA_return_code *dtcmstat);
70
71 /*****************************************************************************
72  * extern functions used in the library
73  *****************************************************************************/
74
75 extern CSA_return_code
76 _DtCm_table_create(Calendar *cal)
77 {
78         CSA_return_code stat;
79         Table_Status_4  *res = NULL;
80         _DtCm_Connection        *conn;
81
82         DP(("table.c: _DtCm_table_create\n"));
83
84         if (cal == NULL)
85                 return (CSA_E_INVALID_PARAMETER);
86
87         conn = &cal->conn;
88         conn->retry = B_TRUE;
89
90         switch(conn->ci->vers_out) {
91                 Table_Op_Args_4 a4;
92         case TABLEVERS_2:
93         case TABLEVERS_3:
94                 return(CSA_E_NOT_SUPPORTED);
95         case TABLEVERS_4:
96                 a4.target = cal->name;
97                 a4.new_target = calloc(1, 1);
98                 res = _DtCm_rtable_create_4(&a4, conn);
99                 free(a4.new_target);
100                 break;
101         default:
102                 return(CSA_E_FAILURE);
103         }
104         if (res != NULL) {
105                 if (tablestat_to_dtcmstat(*res, &stat) != CSA_SUCCESS)
106                         DP((errfmt, "table.c:", "_DtCm_table_create", *res));
107         } else {
108                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
109                         _DtCm_clntstat_to_csastat(conn->stat);
110         }
111
112         return(stat);
113 }
114
115 extern CSA_return_code
116 _DtCm_table_get_access(Calendar *cal, cms_access_entry **alist)
117 {
118         CSA_return_code stat = CSA_SUCCESS;
119         Access_Args_4   *res = NULL;
120         _DtCm_Connection        *conn;
121
122         DP(("table.c: _DtCm_table_get_access\n"));
123
124         if (cal == NULL || alist == NULL)
125                 return (CSA_E_INVALID_PARAMETER);
126
127         *alist = NULL;
128
129         conn = &cal->conn;
130
131         switch(conn->ci->vers_out) {
132                 Access_Args_2 a2;
133                 Access_Args_3 a3;
134                 Access_Args_4 a4;
135                 Access_Args_2 *res2;
136                 Access_Args_3 *res3;
137         case TABLEVERS_2:
138                 a2.target = cal->name;
139                 a2.access_list = NULL;
140                 res2 = _DtCm_rtable_get_access_2(&a2,  conn);
141                 res = _DtCm_accargs2_to_accargs4(res2);
142                 if (res2 != NULL)
143                          xdr_free((xdrproc_t)_DtCm_xdr_Access_Args_2, (char*)res2);
144                 break;
145         case TABLEVERS_3:
146                 a3.target = cal->name;
147                 a3.access_list = NULL;
148                 res3 = _DtCm_rtable_get_access_3(&a3,  conn);
149                 res = _DtCm_accargs3_to_accargs4(res3);
150                 if (res3 != NULL)
151                          xdr_free((xdrproc_t)_DtCm_xdr_Access_Args_3, (char*)res3);
152                 break;
153         case TABLEVERS_4:
154                 a4.target = cal->name;
155                 a4.access_list = NULL;
156                 res = _DtCm_rtable_get_access_4(&a4, conn);
157                 break;
158         default:
159                 stat = CSA_E_FAILURE;
160                 break;
161         }
162
163         if (res != NULL) {
164                 stat = _DtCm_accessentry4_to_cmsaccesslist(res->access_list, alist);
165                 xdr_free ((xdrproc_t)_DtCm_xdr_Access_Args_4, (char*)res);
166         } else {
167                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
168                         _DtCm_clntstat_to_csastat(conn->stat);
169         }
170
171         return(stat);
172 }
173
174 extern CSA_return_code
175 _DtCm_table_set_access(Calendar *cal, CSA_access_list alist)
176 {
177         CSA_return_code stat = CSA_SUCCESS;
178         Access_Status_4 s = access_other_4;
179         Access_Status_4 *res;
180         _DtCm_Connection        *conn;
181         boolean_t       nullreturned = B_FALSE;
182         Access_Entry_4  *alist4;
183
184         DP(("table.c: _DtCm_table_set_access\n"));
185
186         if (cal == NULL)
187                 return (CSA_E_INVALID_PARAMETER);
188
189         if ((stat = _DtCm_csaaccesslist_toaccessentry4(alist, &alist4))
190             != CSA_SUCCESS)
191                 return (stat);
192
193         conn = &cal->conn;
194         conn->retry = B_FALSE;
195
196         switch(conn->ci->vers_out) {
197                 Access_Args_2 a2;
198                 Access_Args_3 a3;
199                 Access_Args_4 a4;
200                 Access_Status_2 *s2;
201                 Access_Status_3 *s3;
202         case TABLEVERS_2:
203                 a2.target = cal->name;
204                 a2.access_list = _DtCm_acclist4_to_acclist2(alist4);
205                 s2 = _DtCm_rtable_set_access_2(&a2,  conn);
206                 if (s2 != NULL)
207                         s =  _DtCm_accstat2_to_accstat4(*s2);
208                 else
209                         nullreturned = B_TRUE;
210                 if (a2.access_list != NULL)
211                         _DtCm_free_access_list4((Access_Entry_4 *)a2.access_list);
212                 break;
213         case TABLEVERS_3:
214                 a3.target = cal->name;
215                 a3.access_list = _DtCm_acclist4_to_acclist3(alist4);
216                 s3 = _DtCm_rtable_set_access_3(&a3,  conn);
217                 if (s3 != NULL)
218                         s =  _DtCm_accstat3_to_accstat4(*s3);
219                 else
220                         nullreturned = B_TRUE;
221                 if (a3.access_list != NULL)
222                         _DtCm_free_access_list4((Access_Entry_4 *)a3.access_list);
223                 break;
224         case TABLEVERS_4:
225                 a4.target = cal->name;
226                 a4.access_list = alist4;
227                 res = _DtCm_rtable_set_access_4(&a4, conn);
228                 if (res != NULL)
229                         s = *res;
230                 else
231                         nullreturned = B_TRUE;
232                 break;
233         default:
234                 stat = CSA_E_FAILURE;
235                 break;
236         }
237
238         if (alist4 != NULL)
239                 _DtCm_free_access_list4(alist4);
240
241         if (nullreturned) {
242                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
243                         _DtCm_clntstat_to_csastat(conn->stat);
244         } else {
245                 switch(s) {
246                 case access_ok_4:
247                         stat = CSA_SUCCESS;
248                         break;
249                 case access_failed_4:
250                         stat = CSA_E_NO_AUTHORITY;
251                         break;
252                 case access_notable_4:
253                         stat = CSA_E_CALENDAR_NOT_EXIST;
254                         break;
255                 default:
256                         DP((errfmt, "table_set_access", s));
257                         stat = CSA_E_FAILURE;
258                         break;
259                 }
260         }
261
262         return(stat);
263 }
264
265 extern CSA_return_code
266 _DtCm_table_lookup(Calendar *cal, _DtCm_libentry *entry)
267 {
268         CSA_return_code stat = CSA_SUCCESS;
269         Table_Res_4     *res = NULL;
270         _DtCm_Connection        *conn;
271         Uid_4           key;
272         Appt_4          *appt;
273
274         DP(("table.c: call to _DtCm_table_lookup\n"));
275
276         if ((cal == NULL) || entry == NULL)
277                 return (CSA_E_INVALID_PARAMETER);
278
279         key.appt_id.tick = entry->e->key.time;
280         key.appt_id.key = entry->e->key.id;
281         key.next = NULL;
282
283         conn = &cal->conn;
284         conn->retry = B_TRUE;
285
286         switch(conn->ci->vers_out) {
287                 Table_Args_2 a2;
288                 Table_Args_3 a3;
289                 Table_Args_4 a4;
290                 Table_Res_2 *res2;
291                 Table_Res_3 *res3;
292         case TABLEVERS_2:
293                 a2.target = cal->name;
294                 a2.args.tag = UID_2;
295                 a2.args.Args_2_u.key = _DtCm_uid4_to_uid2(&key);
296                 res2 = _DtCm_rtable_lookup_2(&a2, conn);
297                 res = _DtCm_tableres2_to_tableres4(res2);
298                 if (a2.args.Args_2_u.key != NULL)
299                         free(a2.args.Args_2_u.key);
300                 if (res2 != NULL)
301                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
302                 break;
303         case TABLEVERS_3:
304                 a3.target = cal->name;
305                 a3.args.tag = UID_3;
306                 a3.args.Args_3_u.key = _DtCm_uid4_to_uid3(&key);
307                 a3.pid = getpid();
308                 res3 = _DtCm_rtable_lookup_3(&a3, conn);
309                 res = _DtCm_tableres3_to_tableres4(res3);
310                 if (a3.args.Args_3_u.key != NULL)
311                         free(a3.args.Args_3_u.key);
312                 if (res3 != NULL)
313                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
314                 break;
315         case TABLEVERS_4:
316                 a4.target = cal->name;
317                 a4.args.tag = UID_4;
318                 a4.args.Args_4_u.key = &key;
319                 a4.pid = getpid();
320                 res = _DtCm_rtable_lookup_4(&a4, conn);
321                 break;
322         default:
323                 stat = CSA_E_FAILURE;
324                 break;
325         }
326
327         if (res != NULL) {
328                 switch(res->status) {
329                 case access_ok_4:
330                 case access_failed_4:
331                         if ((appt = res->res.Table_Res_List_4_u.a) == NULL)
332                                 stat = CSA_X_DT_E_ENTRY_NOT_FOUND |
333                                         CSA_E_INVALID_ENTRY_HANDLE;
334                         else {
335                                 if (stat == CSA_SUCCESS) {
336                                         if (entry->filled == B_TRUE)
337                                                 _DtCm_free_cms_attribute_values(
338                                                     entry->e->num_attrs,
339                                                     entry->e->attrs);
340                                         if ((stat = _DtCm_appt4_to_attrs(
341                                             cal->name, appt,
342                                             entry->e->num_attrs,
343                                             entry->e->attrs, B_FALSE))
344                                             == CSA_SUCCESS)
345                                                 entry->filled = B_TRUE;
346                                 }
347                         }
348                         break;
349                 case access_other_4:
350                         stat = CSA_E_FAILURE;
351                         break;
352                 case access_notable_4:
353                         stat = CSA_E_CALENDAR_NOT_EXIST;
354                         break;
355                 default:
356                         /* remote system error */
357                         DP((errfmt, "_DtCm_table_lookup", res->status));
358                         stat = CSA_E_FAILURE;
359                         break;
360                 }
361                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
362         } else {
363                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
364                         _DtCm_clntstat_to_csastat(conn->stat);
365         }
366
367         return(stat);
368 }
369
370 extern CSA_return_code
371 _DtCm_table_lookup_range(
372         Calendar        *cal,
373         long            start1,
374         long            start2,
375         boolean_t       no_end_time_range,
376         long            end1,
377         long            end2,
378         long            id,
379         uint            num_attrs,
380         cms_attribute   *attrs,
381         CSA_enum        *ops,
382         _DtCm_libentry  **entries)
383 {
384         CSA_return_code stat = CSA_SUCCESS;
385         Table_Res_4     *res = NULL;
386         _DtCm_Connection        *conn;
387         Range_4         new_range, old_range;
388         Appt_4          *appts = NULL, *lptr = NULL, *tptr = NULL, *rptr = NULL;
389         boolean_t       need_matching = B_FALSE;
390         time_t          tick;
391
392         DP(("table.c: _DtCm_table_lookup_range\n"));
393
394         if (cal == NULL || entries == NULL)
395                 return (CSA_E_INVALID_PARAMETER);
396
397         *entries = NULL;
398
399         old_range.key1 = start1;
400         old_range.key2 = start2;
401  
402         new_range.key1 = old_range.key1;
403         new_range.key2 = old_range.key2;
404         new_range.next = NULL;
405
406         conn = &cal->conn;
407         conn->retry = B_TRUE;
408
409         if (conn->use == udp_transport)
410                 if ((new_range.key1 + MAXDAY_LOOKUP_SECS) < old_range.key2)
411                         new_range.key2 = new_range.key1 + MAXDAY_LOOKUP_SECS;
412
413         do {
414                 switch(conn->ci->vers_out) {
415                         Table_Args_2 a2;
416                         Table_Args_3 a3;
417                         Table_Args_4 a4;
418                         Table_Res_2 *res2;
419                         Table_Res_3 *res3;
420                 case TABLEVERS_2:
421                         a2.target = cal->name;
422                         a2.args.tag = RANGE_2;
423                         a2.args.Args_2_u.range = _DtCm_range4_to_range2(&new_range);
424                         res2 = _DtCm_rtable_lookup_range_2(&a2, conn);
425                         res = _DtCm_tableres2_to_tableres4(res2);
426                         if (a2.args.Args_2_u.range != NULL)
427                                 free(a2.args.Args_2_u.range);
428                         if (res2 != NULL)
429                                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
430                         break;
431                 case TABLEVERS_3:
432                         a3.target = cal->name;
433                         a3.args.tag = RANGE_3;
434                         a3.args.Args_3_u.range = _DtCm_range4_to_range3(&new_range);
435                         a3.pid = getpid();
436                         res3 = _DtCm_rtable_lookup_range_3(&a3, conn);
437                         res = _DtCm_tableres3_to_tableres4(res3);
438                         if (a3.args.Args_3_u.range != NULL)
439                                 free(a3.args.Args_3_u.range);
440                         if (res3 != NULL)
441                                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
442                         break;
443                 case TABLEVERS_4:
444                         a4.target = cal->name;
445                         a4.args.tag = RANGE_4;
446                         a4.args.Args_4_u.range = &new_range;
447                         a4.pid = getpid();
448                         res = _DtCm_rtable_lookup_range_4(&a4, conn);
449                         break;
450                 default:
451                         stat = CSA_E_FAILURE;
452                         break;
453                 }
454
455                 if (res != NULL) {
456                         switch(res->status) {
457                         case access_ok_4:
458                         case access_failed_4:
459                                 tptr = _DtCm_copy_appt4(res->res.Table_Res_List_4_u.a);
460                                 if (stat == CSA_SUCCESS) {
461                                         if (conn->use == tcp_transport)
462                                                 appts = tptr;
463                                         else { /* udp transport */
464                                                 if (appts == NULL)
465                                                         appts = lptr = tptr;
466                                                 else {
467                                                         /* traverse from the last res ptr */
468                                                         for (rptr = lptr; rptr != NULL && 
469                                                                 rptr->next != NULL; rptr = rptr->next);
470                                                         if (tptr != NULL)
471                                                                 rptr->next = lptr = tptr;
472                                                         else
473                                                                 lptr = rptr;
474                                                 }
475                                         }
476                                 }
477                                 break;
478                         case access_other_4:
479                                 stat = CSA_E_INVALID_PARAMETER;
480                                 break;
481                         case access_notable_4:
482                                 stat = CSA_E_CALENDAR_NOT_EXIST;
483                                 break;
484                         default:
485                                 /* remote system error */
486                                 DP ((errfmt, "table_lookup_range", res->status));
487                                 stat = CSA_E_FAILURE;
488                                 break;
489                         }
490                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res); res = NULL;
491
492                         /* range must encompass interested ticks */
493                         new_range.key1 = new_range.key2-1;
494                         if ((new_range.key2 = 
495                                 (new_range.key1+MAXDAY_LOOKUP_SECS)) >
496                                         old_range.key2)
497                                 new_range.key2 = old_range.key2;
498                 } else { /* res == NULL */
499                         stat = (conn->stat == RPC_SUCCESS) ?
500                                 CSA_E_SERVICE_UNAVAILABLE :
501                                 _DtCm_clntstat_to_csastat(conn->stat);
502                 }
503         } while (stat == CSA_SUCCESS && new_range.key1 < old_range.key2 && 
504                 (new_range.key1+1) != old_range.key2);
505
506         if (stat == CSA_SUCCESS) {
507                 /*
508                  * if attrs are specified, return only those
509                  * appts that matches the values
510                  */
511                 if (id > 0 || num_attrs > 0 || !no_end_time_range)
512                         appts = _DtCm_match_appts(appts, id, no_end_time_range,
513                                 end1, end2, num_attrs, attrs, ops);
514
515                 stat = _DtCm_appt4_to_libentries(cal->name, appts, entries);
516                 _DtCm_free_appt4(appts);
517
518         } else if (appts != NULL) {
519                 /* this happens if udp is used and some rpc calls succeeded */
520                 _DtCm_free_appt4(appts);
521         }
522
523         return(stat);
524 }
525
526 /*
527  * This routine looks up events of a repeating sequence.
528  * The caller either specifies entry and elist_r or
529  * id and key. 
530  * If entry is specified, events are converted to cms_entry structures
531  * and returned in elist_r, otherwise; the caller is interested only
532  * in the key of the first entry which will be returned in the cms_key
533  * structure pointed to by key.
534  */
535 extern CSA_return_code
536 _DtCm_table_lookup_key_range(
537         Calendar        *cal,
538         _DtCm_libentry  *entry,
539         long            id,
540         time_t          start,
541         time_t          end,
542         cms_key         *key,
543         _DtCm_libentry  **elist_r)
544 {
545         CSA_return_code         stat = CSA_SUCCESS;
546         Table_Res_4             *res=NULL;
547         _DtCm_Connection        *conn;
548         Keyrange_4              keyrange;
549         Abb_Appt_4              *abbs;
550         _DtCm_libentry          *head, *prev, *eptr;
551  
552         DP(("table.c: _DtCm_table_lookup_key_range\n"));
553
554         if (cal == NULL || (entry == NULL && key == NULL) ||
555            (entry && elist_r == NULL))
556                 return (CSA_E_INVALID_PARAMETER);
557  
558         keyrange.next = NULL;
559         keyrange.key = (entry ? entry->e->key.id : id);
560         keyrange.tick1 = start;
561         keyrange.tick2 = end;
562
563         conn = &cal->conn;
564         conn->retry = B_TRUE;
565
566         switch(conn->ci->vers_out) {
567                 Table_Args_3 a3;
568                 Table_Args_4 a4;
569                 Table_Res_3 *res3;
570         case TABLEVERS_2:
571                 return (CSA_E_NOT_SUPPORTED);
572
573         case TABLEVERS_3:
574                 a3.target = cal->name;
575                 a3.args.tag = KEYRANGE_3;
576                 a3.args.Args_3_u.keyrange = _DtCm_keyrange4_to_keyrange3(&keyrange);
577                 a3.pid = getpid();
578                 res3 = _DtCm_rtable_abbreviated_lookup_key_range_3(&a3, conn);
579                 res = _DtCm_tableres3_to_tableres4(res3);
580                 if (a3.args.Args_3_u.keyrange != NULL)
581                         free(a3.args.Args_3_u.keyrange);
582                 if (res3 != NULL)
583                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
584                 break;
585         case TABLEVERS_4:
586                 a4.target = cal->name;
587                 a4.args.tag = KEYRANGE_4;
588                 a4.args.Args_4_u.keyrange = &keyrange;
589                 a4.pid = getpid();
590                 res = _DtCm_rtable_abbreviated_lookup_key_range_4(&a4, conn);
591                 break;
592         default:
593                 return (CSA_E_FAILURE);
594         }
595
596         if (res != NULL) {
597                 switch(res->status) {
598                 case access_ok_4:
599                 case access_failed_4:
600                         abbs = res->res.Table_Res_List_4_u.b;
601                         if (entry == NULL) {
602                                 /* caller is only interested in the first key */
603                                 if (abbs != NULL) {
604                                         key->id = abbs->appt_id.key;
605                                         key->time = abbs->appt_id.tick;
606                                 } else
607                                         key->id = 0;
608                                 break;
609                         }
610
611                         /* we just copy the time from the returned data */
612                         head = prev = NULL;
613                         while (abbs != NULL) {
614                                 if ((stat = _DtCm_make_libentry(entry->e,
615                                     &eptr)) != CSA_SUCCESS)
616                                         break;
617
618                                 /* change time to the time of the instance */
619                                 eptr->e->key.time = abbs->appt_id.tick;
620                                 _csa_tick_to_iso8601(eptr->e->key.time,
621                                         eptr->e->\
622                                         attrs[CSA_ENTRY_ATTR_START_DATE_I].\
623                                         value->item.string_value);
624
625                                 if (head == NULL)
626                                         head = eptr;
627                                 else {
628                                         prev->next = eptr;
629                                         eptr->prev = prev;
630                                 }
631
632                                 prev = eptr;
633                                 abbs = abbs->next;
634                         }
635                         if (stat == CSA_SUCCESS)
636                                 *elist_r = head;
637                         else if (head != NULL)
638                                 _DtCm_free_libentries(head);
639
640                         break;
641                 case access_other_4:
642                         stat = CSA_E_FAILURE;
643                         break;
644                 case access_notable_4:
645                         stat = CSA_E_CALENDAR_NOT_EXIST;
646                         break;
647                 default:
648                         /* remote system error */
649                         DP((errfmt, "_DtCm_table_lookup_key_range", res->status));
650                         stat = CSA_E_FAILURE;
651                         break;
652                 }
653                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
654         } else {
655                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
656                         _DtCm_clntstat_to_csastat(conn->stat);
657         }
658
659         return(stat);
660 }
661
662 extern CSA_return_code
663 _DtCm_table_insert(
664         Calendar *cal,
665         uint num_attrs,
666         CSA_attribute * attrs,
667         _DtCm_libentry **entry_r)
668 {
669         CSA_return_code stat = CSA_SUCCESS;
670         Table_Res_4     *res = NULL;
671         _DtCm_Connection        *conn;
672         Appt_4          *appt4;
673         int             id, i, j;
674
675         DP(("table.c: _DtCm_table_insert\n"));
676
677         if (cal == NULL || num_attrs == 0 || attrs == NULL || entry_r == NULL)
678                 return (CSA_E_INVALID_PARAMETER);
679
680         if ((stat = _DtCm_attrs_to_appt4(num_attrs, attrs, &appt4)) != CSA_SUCCESS)
681                 return (stat);
682
683         /* if the backend's version is less than 4, then it
684          * does not support repeating event types beyond yearly
685          */
686         conn = &cal->conn;
687         if (conn->ci->vers_out < TABLEVERS_4 && appt4->period.period > yearly_4)        {
688                 _DtCm_free_appt4(appt4);
689                 return (CSA_E_NOT_SUPPORTED);
690         }
691
692         /* for old backend, insert one appt at a time
693          * in order to match appointments with the new id
694          */
695
696         conn->retry = B_FALSE;
697
698         switch(conn->ci->vers_out) {
699                 Table_Args_2 a2;
700                 Table_Args_3 a3;
701                 Table_Args_4 a4;
702                 Table_Res_2 *res2;
703                 Table_Res_3 *res3;
704         case TABLEVERS_2:
705                 a2.target = cal->name;
706                 a2.args.tag = APPT_2;
707                 a2.args.Args_2_u.appt = _DtCm_appt4_to_appt2(appt4);
708                 res2 = _DtCm_rtable_insert_2(&a2, conn);
709                 res = _DtCm_tableres2_to_tableres4(res2);
710                 if (a2.args.Args_2_u.appt != NULL)
711                         _DtCm_free_appt2(a2.args.Args_2_u.appt);
712                 if (res2 != NULL)
713                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
714                 break;
715         case TABLEVERS_3:
716                 a3.target = cal->name;
717                 a3.args.tag = APPT_3;
718                 a3.args.Args_3_u.appt = _DtCm_appt4_to_appt3(appt4);
719                 a3.pid = getpid();
720                 res3 = _DtCm_rtable_insert_3(&a3, conn);
721                 res = _DtCm_tableres3_to_tableres4(res3);
722                 if (a3.args.Args_3_u.appt != NULL)
723                         _DtCm_free_appt3(a3.args.Args_3_u.appt);
724                 if (res3 != NULL)
725                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
726                 break;
727         case TABLEVERS_4:
728                 a4.target = cal->name;
729                 a4.args.tag = APPT_4;
730                 a4.args.Args_4_u.appt = appt4;
731                 a4.pid = getpid();
732                 res = _DtCm_rtable_insert_4(&a4, conn);
733                 break;
734         default:
735                 stat = CSA_E_FAILURE;
736                 break;
737         }
738
739         if (res != NULL) {
740                 switch(res->status) {
741                 case access_ok_4:
742                         if (res->res.Table_Res_List_4_u.a) {
743                                 stat = _DtCm_appt4_to_libentries(cal->name,
744                                         res->res.Table_Res_List_4_u.a, entry_r);
745                         }
746                         break;
747                 case access_failed_4:
748                         stat = CSA_E_NO_AUTHORITY;
749                         break;
750                 case access_other_4:
751                         stat = CSA_E_INVALID_PARAMETER;
752                         break;
753                 case access_notable_4:
754                         stat = CSA_E_CALENDAR_NOT_EXIST;
755                         break;
756                 case access_partial_4:
757                 case access_incomplete_4:
758                         stat = CSA_E_FAILURE;
759                         break;
760                 default:
761                         /* remote system error */
762                         DP((errfmt, "table_insert_one", res->status));
763                         stat = CSA_E_FAILURE;
764                         break;
765                 }
766                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
767         } else {
768                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
769                         _DtCm_clntstat_to_csastat(conn->stat);
770         }
771
772         _DtCm_free_appt4(appt4);
773
774         return(stat);
775 }
776
777 extern CSA_return_code
778 _DtCm_table_update(
779         Calendar *cal,
780         _DtCm_libentry *oentry,
781         uint num_attrs,
782         CSA_attribute * attrs,
783         CSA_enum scope,
784         _DtCm_libentry **nentry)
785 {
786         CSA_return_code stat = CSA_SUCCESS;
787         Table_Res_4     *res = NULL;
788         _DtCm_Connection        *conn;
789         Id_4            key;
790         Options_4       opt;
791         Appt_4          *appt4;
792         int             id, i, j;
793         _DtCm_libentry  *temp;
794
795         DP(("table.c: _DtCm_table_update_one\n"));
796
797         if (cal == NULL || oentry == NULL || nentry == NULL)
798                 return (CSA_E_INVALID_PARAMETER);
799
800         /* convert scope to option */
801         if ((stat = _DtCm_scope_to_options4(scope, &opt)) != CSA_SUCCESS)
802                 return (stat);
803
804         _csa_iso8601_to_tick(oentry->e->attrs[CSA_ENTRY_ATTR_START_DATE_I].\
805                 value->item.string_value, &key.tick);
806         key.key = oentry->e->key.id;
807
808         /* create new appt4 from old entry and new attribute values */
809         temp = oentry->next;
810         oentry->next = NULL;
811         stat = _DtCm_libentries_to_appt4(oentry, &appt4);
812         oentry->next = temp;
813
814         if (stat != CSA_SUCCESS)
815                 return (stat);
816
817         /* use do_all for old backends */
818         if (appt4->period.period == single_4)
819                 opt = do_all_4;
820
821         /* apply the new attribute values to the appointment */
822         if ((stat = _DtCm_attrs_to_apptdata(num_attrs, attrs, appt4))
823             != CSA_SUCCESS) {
824                 _DtCm_free_appt4(appt4);
825                 return (stat);
826         }
827
828
829         /* if the backend's version is less than 4, then it does
830          * not support repeating event types beyond yearly
831          * nor does it support do_forward
832          */
833         conn = &cal->conn;
834         if (conn->ci->vers_out < TABLEVERS_4 &&
835             (appt4->period.period > yearly_4 || scope >= CSA_SCOPE_FORWARD)) {
836                 _DtCm_free_appt4(appt4);
837                 return (CSA_E_NOT_SUPPORTED);
838         }
839
840         conn->retry = B_FALSE;
841         switch(conn->ci->vers_out) {
842                 Table_Args_2 a2;
843                 Table_Args_3 a3;
844                 Table_Args_4 a4;
845                 Table_Res_2 *res2;
846                 Table_Res_3 *res3;
847         case TABLEVERS_2:
848                 a2.target = cal->name;
849                 a2.args.tag = APPTID_2;
850                 a2.args.Args_2_u.apptid.oid = (Id_2 *)calloc(1, sizeof(Id_2));
851                 _DtCm_id4_to_id2(&key, a2.args.Args_2_u.apptid.oid);
852                 a2.args.Args_2_u.apptid.new_appt = _DtCm_appt4_to_appt2(appt4);
853
854                 if (opt == do_all_4)
855                     res2 = _DtCm_rtable_change_2(&a2, conn);
856                 else
857                     res2 = _DtCm_rtable_change_instance_2(&a2, conn);
858
859                 res = _DtCm_tableres2_to_tableres4(res2);
860                 free(a2.args.Args_2_u.apptid.oid);
861                 if (a2.args.Args_2_u.apptid.new_appt != NULL)
862                         _DtCm_free_appt2(a2.args.Args_2_u.apptid.new_appt);
863                 if (res2 != NULL)
864                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
865                 break;
866         case TABLEVERS_3:
867                 a3.target = cal->name;
868                 a3.args.tag = APPTID_3;
869                 a3.args.Args_3_u.apptid.oid = (Id_3 *)calloc(1, sizeof(Id_3));
870                 _DtCm_id4_to_id3(&key, a3.args.Args_3_u.apptid.oid);
871                 a3.args.Args_3_u.apptid.new_appt = _DtCm_appt4_to_appt3(appt4);
872                 a3.pid = getpid();
873
874                 if (opt == do_all_4)
875                     res3 = _DtCm_rtable_change_3(&a3, conn);
876                 else
877                     res3 = _DtCm_rtable_change_instance_3(&a3, conn);
878
879                 res = _DtCm_tableres3_to_tableres4(res3);
880                 free(a3.args.Args_3_u.apptid.oid);
881                 if (a3.args.Args_3_u.apptid.new_appt != NULL)
882                         _DtCm_free_appt3(a3.args.Args_3_u.apptid.new_appt);
883                 if (res3 != NULL)
884                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
885                 break;
886         case TABLEVERS_4:
887                 a4.target = cal->name;
888                 a4.args.tag = APPTID_4;
889                 a4.args.Args_4_u.apptid.oid = &key;
890                 a4.args.Args_4_u.apptid.new_appt = appt4;
891                 a4.args.Args_4_u.apptid.option = opt;
892                 a4.pid = getpid();
893                 res = _DtCm_rtable_change_4(&a4, conn);
894                 break;
895         default:
896                 stat = CSA_E_FAILURE;
897                 break;
898         }
899         _DtCm_free_appt4(appt4);
900
901         if (res != NULL) {
902                 switch(res->status) {
903                 case access_ok_4:
904                         if (res->res.Table_Res_List_4_u.a) {
905                                 stat = _DtCm_appt4_to_libentries(cal->name,
906                                         res->res.Table_Res_List_4_u.a, nentry);
907                         }
908                         break;
909                 case access_failed_4:
910                         stat = CSA_E_NO_AUTHORITY;
911                         break;
912                 case access_notable_4:
913                         stat = CSA_E_CALENDAR_NOT_EXIST;
914                         break;
915                 case access_other_4:
916                 case access_partial_4:
917                 case access_incomplete_4:
918                         stat = CSA_E_FAILURE;
919                         break;
920                 default:
921                         /* remote system error */
922                         DP((errfmt, "_DtCm_table_update", res->status));
923                         stat = CSA_E_FAILURE;
924                         break;
925                 }
926                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
927         } else {
928                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
929                         _DtCm_clntstat_to_csastat(conn->stat);
930         }
931
932         return(stat);
933 }
934
935 extern CSA_return_code
936 _DtCm_table_delete(
937         Calendar *cal,
938         _DtCm_libentry *entry,
939         CSA_enum scope)
940 {
941         CSA_return_code stat = CSA_SUCCESS;
942         Table_Res_4     *res = NULL;
943         _DtCm_Connection        *conn;
944         Uidopt_4        key;
945         int             id, i, j;
946         cms_attribute   *rtype;
947
948         DP(("table.c: _DtCm_table_delete\n"));
949
950         if (cal == NULL || entry == NULL)
951                 return (CSA_E_INVALID_PARAMETER);
952
953         _csa_iso8601_to_tick(entry->e->attrs[CSA_ENTRY_ATTR_START_DATE_I].\
954                 value->item.string_value, &key.appt_id.tick);
955
956         /* if this is an one-time appt, make sure the scope is do_all */
957         rtype = &entry->e->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I];
958         if (rtype->value == NULL ||
959             rtype->value->item.sint32_value == CSA_X_DT_REPEAT_ONETIME)
960                 scope = CSA_SCOPE_ALL;
961
962         if ((stat = _DtCm_scope_to_options4(scope, &key.option)) != CSA_SUCCESS)
963                 return (stat);
964
965         key.appt_id.key         = entry->e->key.id;
966         key.next                = NULL;
967
968         conn = &cal->conn;
969         if ((key.option == do_forward_4) && (conn->ci->vers_out < TABLEVERS_4))
970                 return (CSA_E_NOT_SUPPORTED);
971
972         conn->retry = B_FALSE;
973
974         switch(conn->ci->vers_out) {
975                 Table_Args_2 a2;
976                 Table_Args_3 a3;
977                 Table_Args_4 a4;
978                 Table_Res_2 *res2;
979                 Table_Res_3 *res3;
980         case TABLEVERS_2:
981                 a2.target = cal->name;
982                 a2.args.tag = UID_2;
983                 a2.args.Args_2_u.key = _DtCm_uidopt4_to_uid2(&key);
984
985                 if (key.option == do_all_4)
986                     res2 = _DtCm_rtable_delete_2(&a2, conn);
987                 else
988                     res2 = _DtCm_rtable_delete_instance_2(&a2, conn);
989
990                 res = _DtCm_tableres2_to_tableres4(res2);
991                 if (a2.args.Args_2_u.key != NULL)
992                         free(a2.args.Args_2_u.key);
993                 if (res2 != NULL)
994                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
995                 break;
996         case TABLEVERS_3:
997                 a3.target = cal->name;
998                 a3.args.tag = UID_3;
999                 a3.args.Args_3_u.key = _DtCm_uidopt4_to_uid3(&key);
1000                 a3.pid = getpid();
1001
1002                 if (key.option == do_all_4)
1003                     res3 = _DtCm_rtable_delete_3(&a3, conn);
1004                 else
1005                     res3 = _DtCm_rtable_delete_instance_3(&a3, conn);
1006
1007                 res = _DtCm_tableres3_to_tableres4(res3);
1008                 if (a3.args.Args_3_u.key != NULL)
1009                         free(a3.args.Args_3_u.key);
1010                 if (res3 != NULL)
1011                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
1012                 break;
1013         case TABLEVERS_4:
1014                 a4.target = cal->name;
1015                 a4.args.tag = UIDOPT_4;
1016                 a4.args.Args_4_u.uidopt = &key;
1017                 a4.pid = getpid();
1018                 res = _DtCm_rtable_delete_4(&a4, conn);
1019                 break;
1020         default:
1021                 stat = CSA_E_FAILURE;
1022                 break;
1023         }
1024
1025         if (res!=NULL) {
1026                 switch(res->status) {
1027                 case access_ok_4:
1028                         if (res->res.Table_Res_List_4_u.a == NULL)
1029                                 stat = CSA_X_DT_E_ENTRY_NOT_FOUND |
1030                                         CSA_E_INVALID_ENTRY_HANDLE;
1031                         break;
1032                 case access_failed_4:
1033                         stat = CSA_E_NO_AUTHORITY;
1034                         break;
1035                 case access_other_4:
1036                         stat = CSA_E_INVALID_PARAMETER;
1037                         break;
1038                 case access_notable_4:
1039                 case access_partial_4:
1040                 case access_incomplete_4:
1041                         stat = CSA_E_FAILURE;
1042                         break;
1043                 default:
1044                 /* remote system error */
1045                         DP((errfmt, "table_delete", res->status));
1046                         stat = CSA_E_FAILURE;
1047                         break;
1048                 }
1049                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
1050
1051         } else {
1052                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1053                         _DtCm_clntstat_to_csastat(conn->stat);
1054         }
1055
1056         return(stat);
1057 }
1058
1059 extern CSA_return_code 
1060 _DtCm_table_size(Calendar *cal, int *size)
1061 {
1062         int *res;
1063         CSA_return_code stat = CSA_SUCCESS;
1064         _DtCm_Connection        *conn;
1065
1066         DP(("table.c: _DtCm_table_size\n"));
1067
1068         if (cal == NULL || size == NULL)
1069                 return (CSA_E_INVALID_PARAMETER);
1070
1071         conn = &cal->conn;
1072         conn->retry = B_TRUE;
1073
1074         switch(conn->ci->vers_out) {
1075                 Table_Args_2 a2;
1076                 Table_Args_3 a3;
1077                 Table_Args_4 a4;
1078         case TABLEVERS_2:
1079                 a2.target = cal->name;
1080                 a2.args.tag = TICK_2;
1081                 a2.args.Args_2_u.tick = 0;
1082                 res = _DtCm_rtable_size_2(&a2, conn);
1083                 break;
1084         case TABLEVERS_3:
1085                 a3.target = cal->name;
1086                 a3.args.tag = TICK_3;
1087                 a3.args.Args_3_u.tick = 0;
1088                 a3.pid = getpid();
1089                 res = _DtCm_rtable_size_3(&a3, conn);
1090                 break;
1091         case TABLEVERS_4:
1092                 a4.target = cal->name;
1093                 a4.args.tag = TICK_4;
1094                 a4.args.Args_4_u.tick = 0;
1095                 a4.pid = getpid();
1096                 res = _DtCm_rtable_size_4(&a4, conn);
1097                 break;
1098         default:
1099                 stat = CSA_E_FAILURE;
1100                 break;
1101         }
1102
1103         if (res != NULL)
1104                 *size = *res;
1105         else {
1106                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1107                         _DtCm_clntstat_to_csastat(conn->stat);
1108         }
1109
1110         return (stat);
1111 }
1112
1113 extern CSA_return_code
1114 _DtCm_table_lookup_reminder(
1115         Calendar *cal,
1116         CSA_uint32 num_names,
1117         char **reminder_names,
1118         CSA_uint32 *num_rems,
1119         CSA_reminder_reference **rems)
1120 {
1121         CSA_return_code stat = CSA_SUCCESS;
1122         Table_Res_4     *res = NULL;
1123         _DtCm_Connection        *conn;
1124         Reminder_4      *rptr;
1125         time_t          tick;
1126
1127         DP(("table.c: _DtCm_table_lookup_reminder\n"));
1128
1129         if (cal == NULL || num_rems == 0 || rems == NULL)
1130                 return (CSA_E_INVALID_PARAMETER);
1131
1132         /*
1133          * Due to the implementation of existing backends which
1134          * will unmanage any reminders that happens before the
1135          * the given tick, the user specified tick is ignore and
1136          * we will pass in the current time.
1137          */
1138         tick = time(0);
1139
1140         conn = &cal->conn;
1141         conn->retry = B_TRUE;
1142
1143         switch(conn->ci->vers_out) {
1144                 Table_Args_2 a2;
1145                 Table_Args_3 a3;
1146                 Table_Args_4 a4;
1147                 Table_Res_2 *res2;
1148                 Table_Res_3 *res3;
1149         case TABLEVERS_2:
1150                 a2.target = cal->name;
1151                 a2.args.tag = TICK_2;
1152                 a2.args.Args_2_u.tick = tick;
1153                 res2 = _DtCm_rtable_lookup_next_reminder_2(&a2, conn);
1154                 res = _DtCm_tableres2_to_tableres4(res2);
1155                 if (res2 != NULL)
1156                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
1157                 break;
1158         case TABLEVERS_3:
1159                 a3.target = cal->name;
1160                 a3.args.tag = TICK_3;
1161                 a3.args.Args_3_u.tick = tick;
1162                 a3.pid = getpid();
1163                 res3 = _DtCm_rtable_lookup_next_reminder_3(&a3, conn);
1164                 res = _DtCm_tableres3_to_tableres4(res3);
1165                 if (res3 != NULL)
1166                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
1167                 break;
1168         case TABLEVERS_4:
1169                 a4.target = cal->name;
1170                 a4.args.tag = TICK_4;
1171                 a4.args.Args_4_u.tick = tick;
1172                 a4.pid = getpid();
1173                 res = _DtCm_rtable_lookup_next_reminder_4(&a4, conn);
1174                 break;
1175         default:
1176                 stat = CSA_E_FAILURE;
1177                 break;
1178         }
1179
1180         if (res != NULL) {
1181                 switch(res->status) {
1182                 case access_ok_4:
1183                         /*
1184                          * if reminder names are specified,
1185                          * return only those that match
1186                          */
1187                         rptr = _DtCm_copy_reminder4(res->res.Table_Res_List_4_u.r);
1188                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
1189
1190                         if (num_names > 0 && reminder_names != NULL) {
1191                                 rptr = _DtCm_match_reminders(rptr, num_names,
1192                                         reminder_names);
1193                         }
1194
1195                         stat = _DtCm_reminder4_to_csareminder(rptr, num_rems,
1196                                 rems);
1197
1198                         if (rptr != NULL)
1199                                 _DtCm_free_reminder4(rptr);
1200                         break;
1201                 case access_notable_4:
1202                         stat = CSA_E_CALENDAR_NOT_EXIST;
1203                         break;
1204                 case access_failed_4:
1205                 case access_other_4:
1206                         stat = CSA_E_FAILURE;
1207                         break;
1208                 default:
1209                         /* remote system error */
1210                         DP ((errfmt, "_DtCm_table_lookup_reminder", res->status));
1211                         stat = CSA_E_FAILURE;
1212                         break;
1213                 }
1214         } else {
1215                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1216                         _DtCm_clntstat_to_csastat(conn->stat);
1217         }
1218
1219         return(stat);
1220 }
1221
1222 extern CSA_return_code
1223 _DtCm_table_unregister_target(
1224         _DtCm_Connection *conn,
1225         char *calendar)
1226 {
1227         CSA_return_code stat;
1228         Registration_Status_4 res;
1229         boolean_t       nullreturned = B_FALSE;
1230
1231         DP(("table.c: _DtCm_table_unregister_target\n"));
1232
1233         switch(conn->ci->vers_out) {
1234                 Registration_2 r2;
1235                 Registration_3 r3;
1236                 Registration_4 r4;
1237                 Registration_Status_2 *stat2;
1238                 Registration_Status_3 *stat3;
1239                 Registration_Status_4 *stat4;
1240
1241         case TABLEVERS_2:
1242                 r2.target = calendar;
1243                 r2.prognum = _DtCm_transient;
1244                 r2.versnum = AGENTVERS;
1245                 r2.procnum = update_callback;
1246                 r2.next = NULL;
1247                 stat2 = _DtCm_deregister_callback_2(&r2, conn);
1248                 if (stat2 != NULL)
1249                         res = _DtCm_regstat2_to_regstat4(*stat2);
1250                 else
1251                         nullreturned = B_TRUE;
1252                 break;
1253
1254         case TABLEVERS_3:
1255                 r3.target = calendar;
1256                 r3.prognum = _DtCm_transient;
1257                 r3.versnum = AGENTVERS;
1258                 r3.procnum = update_callback;
1259                 r3.next = NULL;
1260                 r3.pid = getpid();
1261                 stat3 = _DtCm_deregister_callback_3(&r3, conn);
1262                 if (stat3 != NULL)
1263                         res = _DtCm_regstat3_to_regstat4(*stat3);
1264                 else
1265                         nullreturned = B_TRUE;
1266                 break;
1267
1268         case TABLEVERS_4:
1269                 r4.target = calendar;
1270                 r4.prognum = _DtCm_transient;
1271                 r4.versnum = AGENTVERS;
1272                 r4.procnum = update_callback;
1273                 r4.next = NULL;
1274                 r4.pid = getpid();
1275                 stat4 = _DtCm_deregister_callback_4(&r4, conn);
1276                 if (stat4 != NULL)
1277                         res = *stat4;
1278                 else
1279                         nullreturned = B_TRUE;
1280                 break;
1281         default:
1282                 stat = CSA_E_FAILURE;
1283         }
1284
1285         if (nullreturned) {
1286                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1287                         _DtCm_clntstat_to_csastat(conn->stat);
1288         } else {
1289                 switch (res) {
1290                 case deregistered_4:
1291                         stat = CSA_SUCCESS;
1292                         break; 
1293
1294                 case reg_notable_4:
1295                         stat = CSA_E_CALENDAR_NOT_EXIST;
1296                         break;
1297
1298                 default:
1299                         stat = CSA_E_FAILURE;
1300                         break;
1301                 }
1302         }
1303
1304         return (stat);
1305 }
1306
1307 extern CSA_return_code
1308 _DtCm_table_register_target(
1309         _DtCm_Connection *conn,
1310         char *calendar)
1311 {
1312         CSA_return_code stat;
1313         Registration_Status_4 res;
1314         boolean_t       nullreturned = B_FALSE;
1315
1316         DP(("table.c: _DtCm_table_register_target\n"));
1317
1318         switch(conn->ci->vers_out) {
1319                 Registration_2 r2;
1320                 Registration_3 r3;
1321                 Registration_4 r4;
1322                 Registration_Status_2 *stat2;
1323                 Registration_Status_3 *stat3;
1324                 Registration_Status_4 *stat4;
1325
1326         case TABLEVERS_2:
1327                 r2.target = calendar;
1328                 r2.prognum = _DtCm_transient;
1329                 r2.versnum = AGENTVERS;
1330                 r2.procnum = update_callback;
1331                 r2.next = NULL;
1332                 stat2 = _DtCm_register_callback_2(&r2, conn);
1333                 if (stat2 != NULL)
1334                         res = _DtCm_regstat2_to_regstat4(*stat2);
1335                 else
1336                         nullreturned = B_TRUE;
1337                 break;
1338
1339         case TABLEVERS_3:
1340                 r3.target = calendar;
1341                 r3.prognum = _DtCm_transient;
1342                 r3.versnum = AGENTVERS;
1343                 r3.procnum = update_callback;
1344                 r3.next = NULL;
1345                 r3.pid = getpid();
1346                 stat3 = _DtCm_register_callback_3(&r3, conn);
1347                 if (stat3 != NULL)
1348                         res = _DtCm_regstat3_to_regstat4(*stat3);
1349                 else
1350                         nullreturned = B_TRUE;
1351                 break;
1352
1353         case TABLEVERS_4:
1354                 r4.target = calendar;
1355                 r4.prognum = _DtCm_transient;
1356                 r4.versnum = AGENTVERS;
1357                 r4.procnum = update_callback;
1358                 r4.next = NULL;
1359                 r4.pid = getpid();
1360                 stat4 = _DtCm_register_callback_4(&r4, conn);
1361                 if (stat4 != NULL)
1362                         res = *stat4;
1363                 else
1364                         nullreturned = B_TRUE;
1365                 break;
1366         default:
1367                 stat = CSA_E_FAILURE;
1368         }
1369
1370         if (nullreturned) {
1371                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1372                         _DtCm_clntstat_to_csastat(conn->stat);
1373         } else {
1374                 switch (res) {
1375                 case registered_4:
1376                         stat = CSA_SUCCESS;
1377                         break;
1378
1379                 case reg_notable_4:
1380                         stat = CSA_E_CALENDAR_NOT_EXIST;
1381                         break;
1382
1383                 default:
1384                         stat = CSA_E_FAILURE;
1385                         break;
1386                 }
1387         }
1388         return (stat);
1389 }
1390
1391 /*****************************************************************************
1392  * static functions used within the file
1393  *****************************************************************************/
1394
1395 /*
1396  * Returns 1 if stat contains an invalid status
1397  */
1398 static CSA_return_code
1399 tablestat_to_dtcmstat(Table_Status_4 stat, CSA_return_code *dtcmstat)
1400 {
1401         switch (stat) {
1402                 case ok_4:
1403                         *dtcmstat = CSA_SUCCESS;
1404                         break;
1405                 case duplicate_4:
1406                         *dtcmstat = CSA_E_CALENDAR_EXISTS;
1407                         break;
1408                 case notable_4:
1409                         *dtcmstat = CSA_E_CALENDAR_NOT_EXIST;
1410                         break;
1411                 case denied_4:
1412                         *dtcmstat = CSA_E_NO_AUTHORITY;
1413                         break;
1414                 case badtable_4:
1415                 case other_4:
1416                         *dtcmstat = CSA_E_FAILURE;
1417                         break;
1418                 case tbl_not_owner_4:
1419                         *dtcmstat = CSA_E_NO_AUTHORITY;
1420                         break;
1421                 case tbl_exist_4:
1422                         *dtcmstat = CSA_E_CALENDAR_EXISTS;
1423                         break;
1424                 case tbl_notsupported_4:
1425                         *dtcmstat = CSA_E_NOT_SUPPORTED;
1426                         break;
1427                 default:
1428                         *dtcmstat = CSA_E_FAILURE;
1429                         return (CSA_E_FAILURE);
1430         }
1431
1432         return (CSA_SUCCESS);
1433 }
1434