libDtSearch: Coverity 86579
[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 libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: 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
390         DP(("table.c: _DtCm_table_lookup_range\n"));
391
392         if (cal == NULL || entries == NULL)
393                 return (CSA_E_INVALID_PARAMETER);
394
395         *entries = NULL;
396
397         old_range.key1 = start1;
398         old_range.key2 = start2;
399  
400         new_range.key1 = old_range.key1;
401         new_range.key2 = old_range.key2;
402         new_range.next = NULL;
403
404         conn = &cal->conn;
405         conn->retry = B_TRUE;
406
407         if (conn->use == udp_transport)
408                 if ((new_range.key1 + MAXDAY_LOOKUP_SECS) < old_range.key2)
409                         new_range.key2 = new_range.key1 + MAXDAY_LOOKUP_SECS;
410
411         do {
412                 switch(conn->ci->vers_out) {
413                         Table_Args_2 a2;
414                         Table_Args_3 a3;
415                         Table_Args_4 a4;
416                         Table_Res_2 *res2;
417                         Table_Res_3 *res3;
418                 case TABLEVERS_2:
419                         a2.target = cal->name;
420                         a2.args.tag = RANGE_2;
421                         a2.args.Args_2_u.range = _DtCm_range4_to_range2(&new_range);
422                         res2 = _DtCm_rtable_lookup_range_2(&a2, conn);
423                         res = _DtCm_tableres2_to_tableres4(res2);
424                         if (a2.args.Args_2_u.range != NULL)
425                                 free(a2.args.Args_2_u.range);
426                         if (res2 != NULL)
427                                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
428                         break;
429                 case TABLEVERS_3:
430                         a3.target = cal->name;
431                         a3.args.tag = RANGE_3;
432                         a3.args.Args_3_u.range = _DtCm_range4_to_range3(&new_range);
433                         a3.pid = getpid();
434                         res3 = _DtCm_rtable_lookup_range_3(&a3, conn);
435                         res = _DtCm_tableres3_to_tableres4(res3);
436                         if (a3.args.Args_3_u.range != NULL)
437                                 free(a3.args.Args_3_u.range);
438                         if (res3 != NULL)
439                                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
440                         break;
441                 case TABLEVERS_4:
442                         a4.target = cal->name;
443                         a4.args.tag = RANGE_4;
444                         a4.args.Args_4_u.range = &new_range;
445                         a4.pid = getpid();
446                         res = _DtCm_rtable_lookup_range_4(&a4, conn);
447                         break;
448                 default:
449                         stat = CSA_E_FAILURE;
450                         break;
451                 }
452
453                 if (res != NULL) {
454                         switch(res->status) {
455                         case access_ok_4:
456                         case access_failed_4:
457                                 tptr = _DtCm_copy_appt4(res->res.Table_Res_List_4_u.a);
458                                 if (stat == CSA_SUCCESS) {
459                                         if (conn->use == tcp_transport)
460                                                 appts = tptr;
461                                         else { /* udp transport */
462                                                 if (appts == NULL)
463                                                         appts = lptr = tptr;
464                                                 else {
465                                                         /* traverse from the last res ptr */
466                                                         for (rptr = lptr; rptr != NULL && 
467                                                                 rptr->next != NULL; rptr = rptr->next);
468                                                         if (tptr != NULL)
469                                                                 rptr->next = lptr = tptr;
470                                                         else
471                                                                 lptr = rptr;
472                                                 }
473                                         }
474                                 }
475                                 break;
476                         case access_other_4:
477                                 stat = CSA_E_INVALID_PARAMETER;
478                                 break;
479                         case access_notable_4:
480                                 stat = CSA_E_CALENDAR_NOT_EXIST;
481                                 break;
482                         default:
483                                 /* remote system error */
484                                 DP ((errfmt, "table_lookup_range", res->status));
485                                 stat = CSA_E_FAILURE;
486                                 break;
487                         }
488                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res); res = NULL;
489
490                         /* range must encompass interested ticks */
491                         new_range.key1 = new_range.key2-1;
492                         if ((new_range.key2 = 
493                                 (new_range.key1+MAXDAY_LOOKUP_SECS)) >
494                                         old_range.key2)
495                                 new_range.key2 = old_range.key2;
496                 } else { /* res == NULL */
497                         stat = (conn->stat == RPC_SUCCESS) ?
498                                 CSA_E_SERVICE_UNAVAILABLE :
499                                 _DtCm_clntstat_to_csastat(conn->stat);
500                 }
501         } while (stat == CSA_SUCCESS && new_range.key1 < old_range.key2 && 
502                 (new_range.key1+1) != old_range.key2);
503
504         if (stat == CSA_SUCCESS) {
505                 /*
506                  * if attrs are specified, return only those
507                  * appts that matches the values
508                  */
509                 if (id > 0 || num_attrs > 0 || !no_end_time_range)
510                         appts = _DtCm_match_appts(appts, id, no_end_time_range,
511                                 end1, end2, num_attrs, attrs, ops);
512
513                 stat = _DtCm_appt4_to_libentries(cal->name, appts, entries);
514                 _DtCm_free_appt4(appts);
515
516         } else if (appts != NULL) {
517                 /* this happens if udp is used and some rpc calls succeeded */
518                 _DtCm_free_appt4(appts);
519         }
520
521         return(stat);
522 }
523
524 /*
525  * This routine looks up events of a repeating sequence.
526  * The caller either specifies entry and elist_r or
527  * id and key. 
528  * If entry is specified, events are converted to cms_entry structures
529  * and returned in elist_r, otherwise; the caller is interested only
530  * in the key of the first entry which will be returned in the cms_key
531  * structure pointed to by key.
532  */
533 extern CSA_return_code
534 _DtCm_table_lookup_key_range(
535         Calendar        *cal,
536         _DtCm_libentry  *entry,
537         long            id,
538         time_t          start,
539         time_t          end,
540         cms_key         *key,
541         _DtCm_libentry  **elist_r)
542 {
543         CSA_return_code         stat = CSA_SUCCESS;
544         Table_Res_4             *res=NULL;
545         _DtCm_Connection        *conn;
546         Keyrange_4              keyrange;
547         Abb_Appt_4              *abbs;
548         _DtCm_libentry          *head, *prev, *eptr;
549  
550         DP(("table.c: _DtCm_table_lookup_key_range\n"));
551
552         if (cal == NULL || (entry == NULL && key == NULL) ||
553            (entry && elist_r == NULL))
554                 return (CSA_E_INVALID_PARAMETER);
555  
556         keyrange.next = NULL;
557         keyrange.key = (entry ? entry->e->key.id : id);
558         keyrange.tick1 = start;
559         keyrange.tick2 = end;
560
561         conn = &cal->conn;
562         conn->retry = B_TRUE;
563
564         switch(conn->ci->vers_out) {
565                 Table_Args_3 a3;
566                 Table_Args_4 a4;
567                 Table_Res_3 *res3;
568         case TABLEVERS_2:
569                 return (CSA_E_NOT_SUPPORTED);
570
571         case TABLEVERS_3:
572                 a3.target = cal->name;
573                 a3.args.tag = KEYRANGE_3;
574                 a3.args.Args_3_u.keyrange = _DtCm_keyrange4_to_keyrange3(&keyrange);
575                 a3.pid = getpid();
576                 res3 = _DtCm_rtable_abbreviated_lookup_key_range_3(&a3, conn);
577                 res = _DtCm_tableres3_to_tableres4(res3);
578                 if (a3.args.Args_3_u.keyrange != NULL)
579                         free(a3.args.Args_3_u.keyrange);
580                 if (res3 != NULL)
581                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
582                 break;
583         case TABLEVERS_4:
584                 a4.target = cal->name;
585                 a4.args.tag = KEYRANGE_4;
586                 a4.args.Args_4_u.keyrange = &keyrange;
587                 a4.pid = getpid();
588                 res = _DtCm_rtable_abbreviated_lookup_key_range_4(&a4, conn);
589                 break;
590         default:
591                 return (CSA_E_FAILURE);
592         }
593
594         if (res != NULL) {
595                 switch(res->status) {
596                 case access_ok_4:
597                 case access_failed_4:
598                         abbs = res->res.Table_Res_List_4_u.b;
599                         if (entry == NULL) {
600                                 /* caller is only interested in the first key */
601                                 if (abbs != NULL) {
602                                         key->id = abbs->appt_id.key;
603                                         key->time = abbs->appt_id.tick;
604                                 } else
605                                         key->id = 0;
606                                 break;
607                         }
608
609                         /* we just copy the time from the returned data */
610                         head = prev = NULL;
611                         while (abbs != NULL) {
612                                 if ((stat = _DtCm_make_libentry(entry->e,
613                                     &eptr)) != CSA_SUCCESS)
614                                         break;
615
616                                 /* change time to the time of the instance */
617                                 eptr->e->key.time = abbs->appt_id.tick;
618                                 _csa_tick_to_iso8601(eptr->e->key.time,
619                                         eptr->e->\
620                                         attrs[CSA_ENTRY_ATTR_START_DATE_I].\
621                                         value->item.string_value);
622
623                                 if (head == NULL)
624                                         head = eptr;
625                                 else {
626                                         prev->next = eptr;
627                                         eptr->prev = prev;
628                                 }
629
630                                 prev = eptr;
631                                 abbs = abbs->next;
632                         }
633                         if (stat == CSA_SUCCESS)
634                                 *elist_r = head;
635                         else if (head != NULL)
636                                 _DtCm_free_libentries(head);
637
638                         break;
639                 case access_other_4:
640                         stat = CSA_E_FAILURE;
641                         break;
642                 case access_notable_4:
643                         stat = CSA_E_CALENDAR_NOT_EXIST;
644                         break;
645                 default:
646                         /* remote system error */
647                         DP((errfmt, "_DtCm_table_lookup_key_range", res->status));
648                         stat = CSA_E_FAILURE;
649                         break;
650                 }
651                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
652         } else {
653                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
654                         _DtCm_clntstat_to_csastat(conn->stat);
655         }
656
657         return(stat);
658 }
659
660 extern CSA_return_code
661 _DtCm_table_insert(
662         Calendar *cal,
663         uint num_attrs,
664         CSA_attribute * attrs,
665         _DtCm_libentry **entry_r)
666 {
667         CSA_return_code stat = CSA_SUCCESS;
668         Table_Res_4     *res = NULL;
669         _DtCm_Connection        *conn;
670         Appt_4          *appt4;
671
672         DP(("table.c: _DtCm_table_insert\n"));
673
674         if (cal == NULL || num_attrs == 0 || attrs == NULL || entry_r == NULL)
675                 return (CSA_E_INVALID_PARAMETER);
676
677         if ((stat = _DtCm_attrs_to_appt4(num_attrs, attrs, &appt4)) != CSA_SUCCESS)
678                 return (stat);
679
680         /* if the backend's version is less than 4, then it
681          * does not support repeating event types beyond yearly
682          */
683         conn = &cal->conn;
684         if (conn->ci->vers_out < TABLEVERS_4 && appt4->period.period > yearly_4)        {
685                 _DtCm_free_appt4(appt4);
686                 return (CSA_E_NOT_SUPPORTED);
687         }
688
689         /* for old backend, insert one appt at a time
690          * in order to match appointments with the new id
691          */
692
693         conn->retry = B_FALSE;
694
695         switch(conn->ci->vers_out) {
696                 Table_Args_2 a2;
697                 Table_Args_3 a3;
698                 Table_Args_4 a4;
699                 Table_Res_2 *res2;
700                 Table_Res_3 *res3;
701         case TABLEVERS_2:
702                 a2.target = cal->name;
703                 a2.args.tag = APPT_2;
704                 a2.args.Args_2_u.appt = _DtCm_appt4_to_appt2(appt4);
705                 res2 = _DtCm_rtable_insert_2(&a2, conn);
706                 res = _DtCm_tableres2_to_tableres4(res2);
707                 if (a2.args.Args_2_u.appt != NULL)
708                         _DtCm_free_appt2(a2.args.Args_2_u.appt);
709                 if (res2 != NULL)
710                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
711                 break;
712         case TABLEVERS_3:
713                 a3.target = cal->name;
714                 a3.args.tag = APPT_3;
715                 a3.args.Args_3_u.appt = _DtCm_appt4_to_appt3(appt4);
716                 a3.pid = getpid();
717                 res3 = _DtCm_rtable_insert_3(&a3, conn);
718                 res = _DtCm_tableres3_to_tableres4(res3);
719                 if (a3.args.Args_3_u.appt != NULL)
720                         _DtCm_free_appt3(a3.args.Args_3_u.appt);
721                 if (res3 != NULL)
722                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
723                 break;
724         case TABLEVERS_4:
725                 a4.target = cal->name;
726                 a4.args.tag = APPT_4;
727                 a4.args.Args_4_u.appt = appt4;
728                 a4.pid = getpid();
729                 res = _DtCm_rtable_insert_4(&a4, conn);
730                 break;
731         default:
732                 stat = CSA_E_FAILURE;
733                 break;
734         }
735
736         if (res != NULL) {
737                 switch(res->status) {
738                 case access_ok_4:
739                         if (res->res.Table_Res_List_4_u.a) {
740                                 stat = _DtCm_appt4_to_libentries(cal->name,
741                                         res->res.Table_Res_List_4_u.a, entry_r);
742                         }
743                         break;
744                 case access_failed_4:
745                         stat = CSA_E_NO_AUTHORITY;
746                         break;
747                 case access_other_4:
748                         stat = CSA_E_INVALID_PARAMETER;
749                         break;
750                 case access_notable_4:
751                         stat = CSA_E_CALENDAR_NOT_EXIST;
752                         break;
753                 case access_partial_4:
754                 case access_incomplete_4:
755                         stat = CSA_E_FAILURE;
756                         break;
757                 default:
758                         /* remote system error */
759                         DP((errfmt, "table_insert_one", res->status));
760                         stat = CSA_E_FAILURE;
761                         break;
762                 }
763                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
764         } else {
765                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
766                         _DtCm_clntstat_to_csastat(conn->stat);
767         }
768
769         _DtCm_free_appt4(appt4);
770
771         return(stat);
772 }
773
774 extern CSA_return_code
775 _DtCm_table_update(
776         Calendar *cal,
777         _DtCm_libentry *oentry,
778         uint num_attrs,
779         CSA_attribute * attrs,
780         CSA_enum scope,
781         _DtCm_libentry **nentry)
782 {
783         CSA_return_code stat = CSA_SUCCESS;
784         Table_Res_4     *res = NULL;
785         _DtCm_Connection        *conn;
786         Id_4            key;
787         Options_4       opt;
788         Appt_4          *appt4;
789         _DtCm_libentry  *temp;
790
791         DP(("table.c: _DtCm_table_update_one\n"));
792
793         if (cal == NULL || oentry == NULL || nentry == NULL)
794                 return (CSA_E_INVALID_PARAMETER);
795
796         /* convert scope to option */
797         if ((stat = _DtCm_scope_to_options4(scope, &opt)) != CSA_SUCCESS)
798                 return (stat);
799
800         _csa_iso8601_to_tick(oentry->e->attrs[CSA_ENTRY_ATTR_START_DATE_I].\
801                 value->item.string_value, &key.tick);
802         key.key = oentry->e->key.id;
803
804         /* create new appt4 from old entry and new attribute values */
805         temp = oentry->next;
806         oentry->next = NULL;
807         stat = _DtCm_libentries_to_appt4(oentry, &appt4);
808         oentry->next = temp;
809
810         if (stat != CSA_SUCCESS)
811                 return (stat);
812
813         /* use do_all for old backends */
814         if (appt4->period.period == single_4)
815                 opt = do_all_4;
816
817         /* apply the new attribute values to the appointment */
818         if ((stat = _DtCm_attrs_to_apptdata(num_attrs, attrs, appt4))
819             != CSA_SUCCESS) {
820                 _DtCm_free_appt4(appt4);
821                 return (stat);
822         }
823
824
825         /* if the backend's version is less than 4, then it does
826          * not support repeating event types beyond yearly
827          * nor does it support do_forward
828          */
829         conn = &cal->conn;
830         if (conn->ci->vers_out < TABLEVERS_4 &&
831             (appt4->period.period > yearly_4 || scope >= CSA_SCOPE_FORWARD)) {
832                 _DtCm_free_appt4(appt4);
833                 return (CSA_E_NOT_SUPPORTED);
834         }
835
836         conn->retry = B_FALSE;
837         switch(conn->ci->vers_out) {
838                 Table_Args_2 a2;
839                 Table_Args_3 a3;
840                 Table_Args_4 a4;
841                 Table_Res_2 *res2;
842                 Table_Res_3 *res3;
843         case TABLEVERS_2:
844                 a2.target = cal->name;
845                 a2.args.tag = APPTID_2;
846                 a2.args.Args_2_u.apptid.oid = (Id_2 *)calloc(1, sizeof(Id_2));
847                 _DtCm_id4_to_id2(&key, a2.args.Args_2_u.apptid.oid);
848                 a2.args.Args_2_u.apptid.new_appt = _DtCm_appt4_to_appt2(appt4);
849
850                 if (opt == do_all_4)
851                     res2 = _DtCm_rtable_change_2(&a2, conn);
852                 else
853                     res2 = _DtCm_rtable_change_instance_2(&a2, conn);
854
855                 res = _DtCm_tableres2_to_tableres4(res2);
856                 free(a2.args.Args_2_u.apptid.oid);
857                 if (a2.args.Args_2_u.apptid.new_appt != NULL)
858                         _DtCm_free_appt2(a2.args.Args_2_u.apptid.new_appt);
859                 if (res2 != NULL)
860                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
861                 break;
862         case TABLEVERS_3:
863                 a3.target = cal->name;
864                 a3.args.tag = APPTID_3;
865                 a3.args.Args_3_u.apptid.oid = (Id_3 *)calloc(1, sizeof(Id_3));
866                 _DtCm_id4_to_id3(&key, a3.args.Args_3_u.apptid.oid);
867                 a3.args.Args_3_u.apptid.new_appt = _DtCm_appt4_to_appt3(appt4);
868                 a3.pid = getpid();
869
870                 if (opt == do_all_4)
871                     res3 = _DtCm_rtable_change_3(&a3, conn);
872                 else
873                     res3 = _DtCm_rtable_change_instance_3(&a3, conn);
874
875                 res = _DtCm_tableres3_to_tableres4(res3);
876                 free(a3.args.Args_3_u.apptid.oid);
877                 if (a3.args.Args_3_u.apptid.new_appt != NULL)
878                         _DtCm_free_appt3(a3.args.Args_3_u.apptid.new_appt);
879                 if (res3 != NULL)
880                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
881                 break;
882         case TABLEVERS_4:
883                 a4.target = cal->name;
884                 a4.args.tag = APPTID_4;
885                 a4.args.Args_4_u.apptid.oid = &key;
886                 a4.args.Args_4_u.apptid.new_appt = appt4;
887                 a4.args.Args_4_u.apptid.option = opt;
888                 a4.pid = getpid();
889                 res = _DtCm_rtable_change_4(&a4, conn);
890                 break;
891         default:
892                 stat = CSA_E_FAILURE;
893                 break;
894         }
895         _DtCm_free_appt4(appt4);
896
897         if (res != NULL) {
898                 switch(res->status) {
899                 case access_ok_4:
900                         if (res->res.Table_Res_List_4_u.a) {
901                                 stat = _DtCm_appt4_to_libentries(cal->name,
902                                         res->res.Table_Res_List_4_u.a, nentry);
903                         }
904                         break;
905                 case access_failed_4:
906                         stat = CSA_E_NO_AUTHORITY;
907                         break;
908                 case access_notable_4:
909                         stat = CSA_E_CALENDAR_NOT_EXIST;
910                         break;
911                 case access_other_4:
912                 case access_partial_4:
913                 case access_incomplete_4:
914                         stat = CSA_E_FAILURE;
915                         break;
916                 default:
917                         /* remote system error */
918                         DP((errfmt, "_DtCm_table_update", res->status));
919                         stat = CSA_E_FAILURE;
920                         break;
921                 }
922                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
923         } else {
924                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
925                         _DtCm_clntstat_to_csastat(conn->stat);
926         }
927
928         return(stat);
929 }
930
931 extern CSA_return_code
932 _DtCm_table_delete(
933         Calendar *cal,
934         _DtCm_libentry *entry,
935         CSA_enum scope)
936 {
937         CSA_return_code stat = CSA_SUCCESS;
938         Table_Res_4     *res = NULL;
939         _DtCm_Connection        *conn;
940         Uidopt_4        key;
941         cms_attribute   *rtype;
942
943         DP(("table.c: _DtCm_table_delete\n"));
944
945         if (cal == NULL || entry == NULL)
946                 return (CSA_E_INVALID_PARAMETER);
947
948         _csa_iso8601_to_tick(entry->e->attrs[CSA_ENTRY_ATTR_START_DATE_I].\
949                 value->item.string_value, &key.appt_id.tick);
950
951         /* if this is an one-time appt, make sure the scope is do_all */
952         rtype = &entry->e->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I];
953         if (rtype->value == NULL ||
954             rtype->value->item.sint32_value == CSA_X_DT_REPEAT_ONETIME)
955                 scope = CSA_SCOPE_ALL;
956
957         if ((stat = _DtCm_scope_to_options4(scope, &key.option)) != CSA_SUCCESS)
958                 return (stat);
959
960         key.appt_id.key         = entry->e->key.id;
961         key.next                = NULL;
962
963         conn = &cal->conn;
964         if ((key.option == do_forward_4) && (conn->ci->vers_out < TABLEVERS_4))
965                 return (CSA_E_NOT_SUPPORTED);
966
967         conn->retry = B_FALSE;
968
969         switch(conn->ci->vers_out) {
970                 Table_Args_2 a2;
971                 Table_Args_3 a3;
972                 Table_Args_4 a4;
973                 Table_Res_2 *res2;
974                 Table_Res_3 *res3;
975         case TABLEVERS_2:
976                 a2.target = cal->name;
977                 a2.args.tag = UID_2;
978                 a2.args.Args_2_u.key = _DtCm_uidopt4_to_uid2(&key);
979
980                 if (key.option == do_all_4)
981                     res2 = _DtCm_rtable_delete_2(&a2, conn);
982                 else
983                     res2 = _DtCm_rtable_delete_instance_2(&a2, conn);
984
985                 res = _DtCm_tableres2_to_tableres4(res2);
986                 if (a2.args.Args_2_u.key != NULL)
987                         free(a2.args.Args_2_u.key);
988                 if (res2 != NULL)
989                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
990                 break;
991         case TABLEVERS_3:
992                 a3.target = cal->name;
993                 a3.args.tag = UID_3;
994                 a3.args.Args_3_u.key = _DtCm_uidopt4_to_uid3(&key);
995                 a3.pid = getpid();
996
997                 if (key.option == do_all_4)
998                     res3 = _DtCm_rtable_delete_3(&a3, conn);
999                 else
1000                     res3 = _DtCm_rtable_delete_instance_3(&a3, conn);
1001
1002                 res = _DtCm_tableres3_to_tableres4(res3);
1003                 if (a3.args.Args_3_u.key != NULL)
1004                         free(a3.args.Args_3_u.key);
1005                 if (res3 != NULL)
1006                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
1007                 break;
1008         case TABLEVERS_4:
1009                 a4.target = cal->name;
1010                 a4.args.tag = UIDOPT_4;
1011                 a4.args.Args_4_u.uidopt = &key;
1012                 a4.pid = getpid();
1013                 res = _DtCm_rtable_delete_4(&a4, conn);
1014                 break;
1015         default:
1016                 stat = CSA_E_FAILURE;
1017                 break;
1018         }
1019
1020         if (res!=NULL) {
1021                 switch(res->status) {
1022                 case access_ok_4:
1023                         if (res->res.Table_Res_List_4_u.a == NULL)
1024                                 stat = CSA_X_DT_E_ENTRY_NOT_FOUND |
1025                                         CSA_E_INVALID_ENTRY_HANDLE;
1026                         break;
1027                 case access_failed_4:
1028                         stat = CSA_E_NO_AUTHORITY;
1029                         break;
1030                 case access_other_4:
1031                         stat = CSA_E_INVALID_PARAMETER;
1032                         break;
1033                 case access_notable_4:
1034                 case access_partial_4:
1035                 case access_incomplete_4:
1036                         stat = CSA_E_FAILURE;
1037                         break;
1038                 default:
1039                 /* remote system error */
1040                         DP((errfmt, "table_delete", res->status));
1041                         stat = CSA_E_FAILURE;
1042                         break;
1043                 }
1044                 xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
1045
1046         } else {
1047                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1048                         _DtCm_clntstat_to_csastat(conn->stat);
1049         }
1050
1051         return(stat);
1052 }
1053
1054 extern CSA_return_code 
1055 _DtCm_table_size(Calendar *cal, int *size)
1056 {
1057         int *res;
1058         CSA_return_code stat = CSA_SUCCESS;
1059         _DtCm_Connection        *conn;
1060
1061         DP(("table.c: _DtCm_table_size\n"));
1062
1063         if (cal == NULL || size == NULL)
1064                 return (CSA_E_INVALID_PARAMETER);
1065
1066         conn = &cal->conn;
1067         conn->retry = B_TRUE;
1068
1069         switch(conn->ci->vers_out) {
1070                 Table_Args_2 a2;
1071                 Table_Args_3 a3;
1072                 Table_Args_4 a4;
1073         case TABLEVERS_2:
1074                 a2.target = cal->name;
1075                 a2.args.tag = TICK_2;
1076                 a2.args.Args_2_u.tick = 0;
1077                 res = _DtCm_rtable_size_2(&a2, conn);
1078                 break;
1079         case TABLEVERS_3:
1080                 a3.target = cal->name;
1081                 a3.args.tag = TICK_3;
1082                 a3.args.Args_3_u.tick = 0;
1083                 a3.pid = getpid();
1084                 res = _DtCm_rtable_size_3(&a3, conn);
1085                 break;
1086         case TABLEVERS_4:
1087                 a4.target = cal->name;
1088                 a4.args.tag = TICK_4;
1089                 a4.args.Args_4_u.tick = 0;
1090                 a4.pid = getpid();
1091                 res = _DtCm_rtable_size_4(&a4, conn);
1092                 break;
1093         default:
1094                 stat = CSA_E_FAILURE;
1095                 break;
1096         }
1097
1098         if (res != NULL)
1099                 *size = *res;
1100         else {
1101                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1102                         _DtCm_clntstat_to_csastat(conn->stat);
1103         }
1104
1105         return (stat);
1106 }
1107
1108 extern CSA_return_code
1109 _DtCm_table_lookup_reminder(
1110         Calendar *cal,
1111         CSA_uint32 num_names,
1112         char **reminder_names,
1113         CSA_uint32 *num_rems,
1114         CSA_reminder_reference **rems)
1115 {
1116         CSA_return_code stat = CSA_SUCCESS;
1117         Table_Res_4     *res = NULL;
1118         _DtCm_Connection        *conn;
1119         Reminder_4      *rptr;
1120         time_t          tick;
1121
1122         DP(("table.c: _DtCm_table_lookup_reminder\n"));
1123
1124         if (cal == NULL || num_rems == 0 || rems == NULL)
1125                 return (CSA_E_INVALID_PARAMETER);
1126
1127         /*
1128          * Due to the implementation of existing backends which
1129          * will unmanage any reminders that happens before the
1130          * the given tick, the user specified tick is ignore and
1131          * we will pass in the current time.
1132          */
1133         tick = time(0);
1134
1135         conn = &cal->conn;
1136         conn->retry = B_TRUE;
1137
1138         switch(conn->ci->vers_out) {
1139                 Table_Args_2 a2;
1140                 Table_Args_3 a3;
1141                 Table_Args_4 a4;
1142                 Table_Res_2 *res2;
1143                 Table_Res_3 *res3;
1144         case TABLEVERS_2:
1145                 a2.target = cal->name;
1146                 a2.args.tag = TICK_2;
1147                 a2.args.Args_2_u.tick = tick;
1148                 res2 = _DtCm_rtable_lookup_next_reminder_2(&a2, conn);
1149                 res = _DtCm_tableres2_to_tableres4(res2);
1150                 if (res2 != NULL)
1151                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_2, (char*)res2);
1152                 break;
1153         case TABLEVERS_3:
1154                 a3.target = cal->name;
1155                 a3.args.tag = TICK_3;
1156                 a3.args.Args_3_u.tick = tick;
1157                 a3.pid = getpid();
1158                 res3 = _DtCm_rtable_lookup_next_reminder_3(&a3, conn);
1159                 res = _DtCm_tableres3_to_tableres4(res3);
1160                 if (res3 != NULL)
1161                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_3, (char*)res3);
1162                 break;
1163         case TABLEVERS_4:
1164                 a4.target = cal->name;
1165                 a4.args.tag = TICK_4;
1166                 a4.args.Args_4_u.tick = tick;
1167                 a4.pid = getpid();
1168                 res = _DtCm_rtable_lookup_next_reminder_4(&a4, conn);
1169                 break;
1170         default:
1171                 stat = CSA_E_FAILURE;
1172                 break;
1173         }
1174
1175         if (res != NULL) {
1176                 switch(res->status) {
1177                 case access_ok_4:
1178                         /*
1179                          * if reminder names are specified,
1180                          * return only those that match
1181                          */
1182                         rptr = _DtCm_copy_reminder4(res->res.Table_Res_List_4_u.r);
1183                         xdr_free((xdrproc_t)_DtCm_xdr_Table_Res_4, (char*)res);
1184
1185                         if (num_names > 0 && reminder_names != NULL) {
1186                                 rptr = _DtCm_match_reminders(rptr, num_names,
1187                                         reminder_names);
1188                         }
1189
1190                         stat = _DtCm_reminder4_to_csareminder(rptr, num_rems,
1191                                 rems);
1192
1193                         if (rptr != NULL)
1194                                 _DtCm_free_reminder4(rptr);
1195                         break;
1196                 case access_notable_4:
1197                         stat = CSA_E_CALENDAR_NOT_EXIST;
1198                         break;
1199                 case access_failed_4:
1200                 case access_other_4:
1201                         stat = CSA_E_FAILURE;
1202                         break;
1203                 default:
1204                         /* remote system error */
1205                         DP ((errfmt, "_DtCm_table_lookup_reminder", res->status));
1206                         stat = CSA_E_FAILURE;
1207                         break;
1208                 }
1209         } else {
1210                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1211                         _DtCm_clntstat_to_csastat(conn->stat);
1212         }
1213
1214         return(stat);
1215 }
1216
1217 extern CSA_return_code
1218 _DtCm_table_unregister_target(
1219         _DtCm_Connection *conn,
1220         char *calendar)
1221 {
1222         CSA_return_code stat;
1223         Registration_Status_4 res;
1224         boolean_t       nullreturned = B_FALSE;
1225
1226         DP(("table.c: _DtCm_table_unregister_target\n"));
1227
1228         switch(conn->ci->vers_out) {
1229                 Registration_2 r2;
1230                 Registration_3 r3;
1231                 Registration_4 r4;
1232                 Registration_Status_2 *stat2;
1233                 Registration_Status_3 *stat3;
1234                 Registration_Status_4 *stat4;
1235
1236         case TABLEVERS_2:
1237                 r2.target = calendar;
1238                 r2.prognum = _DtCm_transient;
1239                 r2.versnum = AGENTVERS;
1240                 r2.procnum = update_callback;
1241                 r2.next = NULL;
1242                 stat2 = _DtCm_deregister_callback_2(&r2, conn);
1243                 if (stat2 != NULL)
1244                         res = _DtCm_regstat2_to_regstat4(*stat2);
1245                 else
1246                         nullreturned = B_TRUE;
1247                 break;
1248
1249         case TABLEVERS_3:
1250                 r3.target = calendar;
1251                 r3.prognum = _DtCm_transient;
1252                 r3.versnum = AGENTVERS;
1253                 r3.procnum = update_callback;
1254                 r3.next = NULL;
1255                 r3.pid = getpid();
1256                 stat3 = _DtCm_deregister_callback_3(&r3, conn);
1257                 if (stat3 != NULL)
1258                         res = _DtCm_regstat3_to_regstat4(*stat3);
1259                 else
1260                         nullreturned = B_TRUE;
1261                 break;
1262
1263         case TABLEVERS_4:
1264                 r4.target = calendar;
1265                 r4.prognum = _DtCm_transient;
1266                 r4.versnum = AGENTVERS;
1267                 r4.procnum = update_callback;
1268                 r4.next = NULL;
1269                 r4.pid = getpid();
1270                 stat4 = _DtCm_deregister_callback_4(&r4, conn);
1271                 if (stat4 != NULL)
1272                         res = *stat4;
1273                 else
1274                         nullreturned = B_TRUE;
1275                 break;
1276         default:
1277                 stat = CSA_E_FAILURE;
1278         }
1279
1280         if (nullreturned) {
1281                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1282                         _DtCm_clntstat_to_csastat(conn->stat);
1283         } else {
1284                 switch (res) {
1285                 case deregistered_4:
1286                         stat = CSA_SUCCESS;
1287                         break; 
1288
1289                 case reg_notable_4:
1290                         stat = CSA_E_CALENDAR_NOT_EXIST;
1291                         break;
1292
1293                 default:
1294                         stat = CSA_E_FAILURE;
1295                         break;
1296                 }
1297         }
1298
1299         return (stat);
1300 }
1301
1302 extern CSA_return_code
1303 _DtCm_table_register_target(
1304         _DtCm_Connection *conn,
1305         char *calendar)
1306 {
1307         CSA_return_code stat;
1308         Registration_Status_4 res;
1309         boolean_t       nullreturned = B_FALSE;
1310
1311         DP(("table.c: _DtCm_table_register_target\n"));
1312
1313         switch(conn->ci->vers_out) {
1314                 Registration_2 r2;
1315                 Registration_3 r3;
1316                 Registration_4 r4;
1317                 Registration_Status_2 *stat2;
1318                 Registration_Status_3 *stat3;
1319                 Registration_Status_4 *stat4;
1320
1321         case TABLEVERS_2:
1322                 r2.target = calendar;
1323                 r2.prognum = _DtCm_transient;
1324                 r2.versnum = AGENTVERS;
1325                 r2.procnum = update_callback;
1326                 r2.next = NULL;
1327                 stat2 = _DtCm_register_callback_2(&r2, conn);
1328                 if (stat2 != NULL)
1329                         res = _DtCm_regstat2_to_regstat4(*stat2);
1330                 else
1331                         nullreturned = B_TRUE;
1332                 break;
1333
1334         case TABLEVERS_3:
1335                 r3.target = calendar;
1336                 r3.prognum = _DtCm_transient;
1337                 r3.versnum = AGENTVERS;
1338                 r3.procnum = update_callback;
1339                 r3.next = NULL;
1340                 r3.pid = getpid();
1341                 stat3 = _DtCm_register_callback_3(&r3, conn);
1342                 if (stat3 != NULL)
1343                         res = _DtCm_regstat3_to_regstat4(*stat3);
1344                 else
1345                         nullreturned = B_TRUE;
1346                 break;
1347
1348         case TABLEVERS_4:
1349                 r4.target = calendar;
1350                 r4.prognum = _DtCm_transient;
1351                 r4.versnum = AGENTVERS;
1352                 r4.procnum = update_callback;
1353                 r4.next = NULL;
1354                 r4.pid = getpid();
1355                 stat4 = _DtCm_register_callback_4(&r4, conn);
1356                 if (stat4 != NULL)
1357                         res = *stat4;
1358                 else
1359                         nullreturned = B_TRUE;
1360                 break;
1361         default:
1362                 stat = CSA_E_FAILURE;
1363         }
1364
1365         if (nullreturned) {
1366                 stat = (conn->stat == RPC_SUCCESS) ? CSA_E_SERVICE_UNAVAILABLE :
1367                         _DtCm_clntstat_to_csastat(conn->stat);
1368         } else {
1369                 switch (res) {
1370                 case registered_4:
1371                         stat = CSA_SUCCESS;
1372                         break;
1373
1374                 case reg_notable_4:
1375                         stat = CSA_E_CALENDAR_NOT_EXIST;
1376                         break;
1377
1378                 default:
1379                         stat = CSA_E_FAILURE;
1380                         break;
1381                 }
1382         }
1383         return (stat);
1384 }
1385
1386 /*****************************************************************************
1387  * static functions used within the file
1388  *****************************************************************************/
1389
1390 /*
1391  * Returns 1 if stat contains an invalid status
1392  */
1393 static CSA_return_code
1394 tablestat_to_dtcmstat(Table_Status_4 stat, CSA_return_code *dtcmstat)
1395 {
1396         switch (stat) {
1397                 case ok_4:
1398                         *dtcmstat = CSA_SUCCESS;
1399                         break;
1400                 case duplicate_4:
1401                         *dtcmstat = CSA_E_CALENDAR_EXISTS;
1402                         break;
1403                 case notable_4:
1404                         *dtcmstat = CSA_E_CALENDAR_NOT_EXIST;
1405                         break;
1406                 case denied_4:
1407                         *dtcmstat = CSA_E_NO_AUTHORITY;
1408                         break;
1409                 case badtable_4:
1410                 case other_4:
1411                         *dtcmstat = CSA_E_FAILURE;
1412                         break;
1413                 case tbl_not_owner_4:
1414                         *dtcmstat = CSA_E_NO_AUTHORITY;
1415                         break;
1416                 case tbl_exist_4:
1417                         *dtcmstat = CSA_E_CALENDAR_EXISTS;
1418                         break;
1419                 case tbl_notsupported_4:
1420                         *dtcmstat = CSA_E_NOT_SUPPORTED;
1421                         break;
1422                 default:
1423                         *dtcmstat = CSA_E_FAILURE;
1424                         return (CSA_E_FAILURE);
1425         }
1426
1427         return (CSA_SUCCESS);
1428 }
1429