2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /*******************************************************************************
27 ** $XConsortium: util.c /main/12 1996/11/21 19:44:40 drk $
29 ** RESTRICTED CONFIDENTIAL INFORMATION:
31 ** The information in this document is subject to special
32 ** restrictions in a confidential disclosure agreement between
33 ** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 ** document outside HP, IBM, Sun, USL, SCO, or Univel without
35 ** Sun's specific written approval. This document and all copies
36 ** and derivative works thereof must be returned or destroyed at
39 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
41 *******************************************************************************/
44 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
45 * (c) Copyright 1993, 1994 International Business Machines Corp. *
46 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
47 * (c) Copyright 1993, 1994 Novell, Inc. *
53 #include <EUSCompat.h>
60 #include <sys/utsname.h> /* SYS_NMLN */
61 #if defined(sun) || defined(USL) || defined(__uxp__)
62 #include <sys/systeminfo.h>
65 #endif /* sun || USL || __uxp__ */
66 #include <sys/param.h>
68 #if (defined(USL) || defined(__uxp__)) && !defined(DOM_NM_LN)
69 #define DOM_NM_LN BUFSIZ
72 #define X_INCLUDE_STRING_H
73 #define X_INCLUDE_TIME_H
74 #define XOS_USE_NO_LOCKING
78 #include <X11/Xos_r.h>
88 extern int _csa_tick_to_iso8601(time_t, char *);
89 extern int _csa_iso8601_to_tick(char *, time_t*);
91 extern FILE *popen(const char *, const char *);
92 extern int pclose(FILE *);
96 * Function: cm_def_printer
98 * Purpose: get the default printer name for SVR4
102 * Returns: char* (printer name)
111 char *printer_name=NULL;
114 tmp = (char*)getenv("LPDEST");
115 if (tmp != NULL && *tmp != NULL) {
116 printer_name = (char*)malloc(strlen(tmp)+1);
117 strcpy(printer_name, tmp);
121 /* This is really nasty. lpstat -d does *not* work on the AIX
122 machines. Just fall back to "lp" here */
125 _Xstrtokparams strtok_buf;
127 fp = (FILE *)popen("lpstat -d", "r");
128 fread(message, 256, 1, fp);
129 tmp = (char *)_XStrtok(message, ":", strtok_buf);
130 tmp = (char *)_XStrtok((char *)NULL, "\n", strtok_buf);
131 if (tmp != NULL && *tmp != NULL) {
132 printer_name = (char*)malloc(strlen(tmp)+1);
133 strcpy(printer_name, tmp);
136 printer_name = (char*)malloc(3);
137 strcpy(printer_name, "lp");
140 /* close the process connection */
143 printer_name = (char*)malloc(3);
144 strcpy(printer_name, "lp");
148 tmp = (char*)getenv("PRINTER");
149 if (tmp != NULL && *tmp != '\0') {
150 printer_name = (char*)malloc(strlen(tmp)+1);
151 strcpy(printer_name, tmp);
154 printer_name = (char*)malloc(3);
155 strcpy(printer_name, "lw");
161 /*--------------------------------------------------------------------------
162 * THE FOLLOWING STRING FUNCTION redefinitions are a HACK !
164 * The cm code should be changed so that
165 * a) the redefined functions use the same headers as in <string.h>
166 * b) no redefinition of these library function is necessary
168 * The cm definitions use different function headers than in <string.h>
169 * Prefixing the functions will get rid of the resulting compiler error.
170 * Now cm functions will use the cm_ string functions, but library functions,
171 * e.g. fprintf, will use strlen etc. which leads to core dumps.
172 * As part of the bootstrapping process, I am including the below redefinitions
173 * of the system functions. This should be fixed later.
175 *--------------------------------------------------------------------------*/
178 cm_strcpy(register char *s1, register char *s2)
180 if (s1==NULL || s2==NULL) return(NULL);
186 cm_strlen(register char *s)
190 if (s==NULL) return 0;
198 if (s1 == NULL) return NULL;
199 s2 = (char *) strdup(s1);
204 cm_strcat(char *s1, char *s2)
206 if (s1==NULL || s2==NULL) return(s1);
211 /* transform string patterns of \\ into \
212 \n into carriage returns and
221 if (s==NULL) return(NULL);
224 newstr= (char *) ckalloc((unsigned)i + 1);
226 for (j=0; j<i; j++) {
232 else if (s[j+1]=='\\') {
236 else if (s[j+1]=='\"') {
253 /* transform string patterns of \ into \\
254 carriage returns into \n, and
263 if (s==NULL) return(NULL);
266 newstr = (char *) ckalloc((unsigned)((2 * i) + 1));
268 for (j=0; j<i; j++) {
274 else if (s[j]=='\\') {
279 else if (s[j]=='\"') {
295 syserr(msg, a1, a2, a3)
298 /* Taken from Unix World, July 1989, p. 66 */
301 /* save the error number so fprintf doesn't step on it */
304 (void) fprintf(stderr, "cm: ");
305 /* print the actual message itself */
306 (void) fprintf(stderr, msg, a1, a2, a3);
309 /* print the error, if any */
311 if (saveerr < 0 || saveerr > sys_nerr)
312 (void) fprintf(stderr, ":Unknown error %d", saveerr);
314 (void) fprintf(stderr, ":%s", sys_errlist[saveerr]);
318 /* thow a newline on the end */
319 (void) fprintf(stderr, "\n");
321 /* exit with an error */
328 /* Wrapper around standard storage allocation, to localize errors.
329 Taken from Unix World, July 1989, p. 66 */
331 ckalloc(unsigned int size)
335 /* try to get the memory */
336 p = (char *)calloc(1, size);
338 /* if it worked, return the memory directly */
339 if (p != NULL) return(p);
341 /* try allocation again */
342 p = (char *)calloc(1, size);
344 /* see if it worked the second time */
345 if (p != NULL) return(p);
347 /* no recovery available */
348 syserr("ckalloc: cannot allocate %d bytes", size, 0, 0);
349 return((char *)NULL);
357 _Xctimeparams ctime_buf;
359 a = _XCtime(&t, ctime_buf);
360 (void) fprintf (stderr, "%ld %s\n", (long)t, a);
366 if (i1 > i2) return(i2);
367 if (i1 < i2) return(i1);
374 if (i1 > i2) return(i1);
375 if (i1 < i2) return(i2);
380 text_to_lines(char *s, int n)
383 Lines *prev_l = NULL, *l = NULL, *head= NULL;
388 if (s == NULL || n <= 0) return NULL;
390 string = cm_strdup(s);
392 * Here, look for \n, which is (in)famous character in IBM-932.
393 * Therefore, don't use strtok(). It is not i18n'ed.
395 for ( _p = string; *_p != '\0'; _p += clen ) {
396 clen = mblen( _p, MB_CUR_MAX );
401 if ( ( clen == 1 ) && ( *_p == '\n' ) ) {
409 if (line == NULL) break;
410 l = (Lines*)ckalloc(sizeof(Lines));
411 if (head == NULL) head = l;
412 if (prev_l != NULL) prev_l->next = l;
413 l->s = cm_strdup(line);
416 if ( ( *_p == '\0' ) || ( clen == -1 ) )
419 for ( ; *_p != '\0'; _p += clen ) {
420 clen = mblen( _p, MB_CUR_MAX );
425 if ( ( clen == 1 ) && ( *_p == '\n' ) ) {
439 destroy_lines(Lines *l)
444 free(l->s); l->s=NULL;
447 free((char *)p); p=NULL;
452 * Expand any escape characters in passed string
455 expand_esc_chars(char *string) {
459 while (from && *from) {
460 int len = mblen(from, MB_CUR_MAX);
462 if (len <= 0) break; /* invalid char */
463 if (len > 1) { /* move over multibyte char */
493 get_head(char *str, char sep)
495 static char buf[BUFSIZ];
502 while (*str && *str != sep)
508 return(cm_strdup(buf));
513 get_tail(char *str, char sep)
520 while (*str && *str != sep)
523 return(cm_strdup(++str));
532 static char *login = NULL;
536 name = (char*)cm_get_uname();
537 host = (char*)cm_get_local_host();
538 login = (char *) ckalloc (cm_strlen(name) + cm_strlen(host) + 2);
539 sprintf(login, "%s@%s", name, host);
547 static char *local_host;
549 if (local_host == NULL) {
550 #if defined(sun) || defined(USL) || defined(__uxp__)
551 local_host = (char *)ckalloc(MAXHOSTNAMELEN);
552 (void) sysinfo(SI_HOSTNAME, local_host, MAXHOSTNAMELEN);
554 local_host = (char *)ckalloc(MAXHOSTNAMELEN);
555 (void) gethostname(local_host, MAXHOSTNAMELEN);
556 #endif /* sun || USL || __uxp__ */
568 if ((pw = (struct passwd *)getpwuid(geteuid())) == NULL)
569 name = (char *) cm_strdup("nobody");
571 name = (char *) cm_strdup(pw->pw_name);
578 cm_get_local_domain()
580 static char *local_domain;
582 if (local_domain == NULL) {
583 local_domain = ckalloc(BUFSIZ);
584 #if defined(sun) || defined(USL) || defined(__uxp__)
585 sysinfo(SI_SRPC_DOMAIN, local_domain, DOM_NM_LN);
587 if(-1 == getdomainname(local_domain, BUFSIZ)) {
588 fprintf(stderr, "getdomainname() failed %d '%s'\n", errno, strerror(errno));
591 #endif /* sun || USL || __uxp__ */
593 return(local_domain);
596 /* partially qualified target */
598 cm_pqtarget(char *name)
600 char *host, *target=NULL;
602 host = (char*)strchr(name, '@');
604 host = (char*)cm_get_local_host();
605 target = (char *)ckalloc(cm_strlen(name) +
606 cm_strlen(host) + 2);
607 sprintf(target, "%s@%s", name, host);
610 target = (char *) cm_strdup(name);
615 * calendar_name@host[.domain] -> calendar_name
618 cm_target2name(char *target)
620 return(get_head(target, '@'));
624 * calendar_name@host[.domain] -> host[.domain]
627 cm_target2location(char *target)
629 return(get_tail(target, '@'));
633 * calendar_name@host[.domain] -> host
636 cm_target2host(char *target)
638 char *location, *host;
640 location = get_tail(target, '@');
641 if (location != NULL) {
642 host = get_head(location, '.');
649 * calendar_name@host[.domain] -> domain
652 cm_target2domain(char *target)
654 char *location, *domain;
656 location = get_tail(target, '@');
657 if (location != NULL) {
658 domain = get_tail(location, '.');
666 * str consists of components separated by token
667 * get and copy the first component into comp and
668 * strip it out of str, so str would point to the first
669 * token or the null terminator.
672 get_component(char **str, char *comp, char token)
683 while (ptr && *ptr != 0 && *ptr != token)
692 * head and tail points to the first and last character
693 * of a string which consists of components separated by token.
694 * get and copy the last component into comp and
695 * strip it out of the string, so tail would point to the last
696 * token or the head of the string.
699 get_last_component(char *head, char **tail, char *comp, char token)
710 while (cptr != head && *cptr != token)
718 while (ptr != (*tail + 1))
727 match_forward(char *str1, char *str2)
729 char com1[BUFSIZ], com2[BUFSIZ];
731 if (str1 == NULL || str2 == NULL)
735 get_component(&str1, com1, '.');
736 get_component(&str2, com2, '.');
748 if (strcasecmp(com1, com2) != 0)
751 /* take care of case: a.b a. */
752 if (strcmp(str2, ".") == 0
753 && (strcmp(str1, ".") != 0 || *str1 != '\0'))
764 } else if (strcmp(str2, ".") == 0 || *str2 == '\0')
772 match_backward(char *str1, char *str2)
776 char com1[BUFSIZ], com2[BUFSIZ];
778 if (str1 == NULL || str2 == NULL)
788 ptr1 = (len1 ? (str1 + len1 - 1) : str1);
789 ptr2 = (len2 ? (str2 + len2 - 1) : str2);
791 if (*ptr1 == '.' && ptr1 != str1)
794 if (*ptr2 == '.' && ptr2 != str2)
798 get_last_component(str1, &ptr1, com1, '.');
799 get_last_component(str2, &ptr2, com2, '.');
811 if (strcasecmp(com1, com2) != 0)
819 return (B_FALSE); /* bad format */
821 return (B_TRUE); /* done */
827 return (B_FALSE); /* bad format */
829 return (B_TRUE); /* done */
834 * Correct format assumed, i.e. str = label1[.label2 ...]
835 * Compare str2 against str1 which should be more fully qualified than str2
838 same_path(char *str1, char *str2)
844 if (str1 == NULL || str2 == NULL)
848 if (*str1 == '.' || *str2 == '.')
849 return (B_FALSE); /* bad format */
851 if (match_forward(str1, str2) == B_TRUE)
854 return (match_backward(str1, str2));
858 * compare user1 and user2
859 * user1 = user@host[.domain]
860 * user2 = any format in (user, user@host[.domain], user@domain)
863 same_user(char *user1, char *user2)
870 if (user1 == NULL || user2 == NULL)
873 /* compare user name */
874 str1 = get_head(user1, '@');
875 str2 = get_head(user2, '@');
877 if (str1 == NULL || str2 == NULL)
880 if (strcmp(str1, str2)) {
888 /* if only user name is specified, don't need to check domain */
889 str2 = strchr(user2, '@');
893 /* first assume user2=user@domain */
894 str1 = strchr(user1, '.');
896 if (same_path(cm_get_local_domain(), ++str2))
899 if (same_path(++str1, ++str2))
903 /* assume user2=user@host[.domain] */
905 str1 = strchr(user1, '@');
906 sprintf(buf, "%s.%s", ++str1, cm_get_local_domain());
909 str1 = strchr(user1, '@');
913 if (same_path(str1, str2))
920 * A blank line is one that consists of only \b, \t or \n.
927 if (ptr == NULL) return B_TRUE;
928 while (ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'))
937 embedded_blank(char *buf)
941 if (ptr == NULL) return B_TRUE;
942 while (ptr && *ptr) {
943 if ((*ptr == ' ') || (*ptr == '\t'))
952 get_data_version(CSA_session_handle session) {
955 CSA_attribute_reference names[1];
956 CSA_uint32 number_attrs_returned;
957 CSA_attribute *attrs_returned;
959 names[0] = CSA_X_DT_CAL_ATTR_DATA_VERSION;
962 if (csa_read_calendar_attributes(session,
965 &number_attrs_returned,
967 NULL) == CSA_SUCCESS) {
968 ver = attrs_returned[0].value->item.uint32_value;
969 csa_free(attrs_returned);
976 get_server_version(CSA_session_handle session) {
979 CSA_attribute_reference names[1];
980 CSA_uint32 number_attrs_returned;
981 CSA_attribute *attrs_returned;
983 names[0] = CSA_X_DT_CAL_ATTR_SERVER_VERSION;
985 if (csa_read_calendar_attributes(session,
988 &number_attrs_returned,
990 NULL) == CSA_SUCCESS) {
991 ver = attrs_returned[0].value->item.uint32_value;
992 csa_free(attrs_returned);
999 privacy_set(Dtcm_appointment *appt) {
1001 CSA_sint32 privacy = CSA_CLASS_PUBLIC;
1009 if (!appt->private->value)
1012 privacy = appt->private->value->item.sint32_value;
1018 showtime_set(Dtcm_appointment *appt) {
1020 CSA_sint32 showtime = 0;
1025 if (!appt->show_time)
1028 if (!appt->show_time->value)
1031 showtime = appt->show_time->value->item.sint32_value;
1037 ** Parse the date string and get the month, day, and year
1040 parse_date(OrderingType order, SeparatorType sep, char *datestr, char *m,
1043 char *first, *second, *third;
1044 char *tmp_date, *str = separator_str(sep);
1045 _Xstrtokparams strtok_buf;
1051 if (datestr == NULL)
1054 tmp_date = cm_strdup(datestr);
1055 first = _XStrtok(tmp_date, str, strtok_buf);
1057 ** Check to see if the date entered has legit separator
1059 if ( strcoll(first, datestr) == 0 ) {
1063 second = _XStrtok(NULL, str, strtok_buf);
1064 third = _XStrtok(NULL, str, strtok_buf);
1069 cm_strcpy(m, second);
1071 cm_strcpy(d, first);
1073 cm_strcpy(y, third);
1077 cm_strcpy(m, second);
1079 cm_strcpy(d, third);
1081 cm_strcpy(y, first);
1086 cm_strcpy(m, first);
1088 cm_strcpy(d, second);
1090 cm_strcpy(y, third);
1098 ** Reformat the date string into m/d/y format and write it into the buffer
1101 datestr2mdy(char *datestr, OrderingType order, SeparatorType sep, char *buf) {
1102 char m[3], d[3], y[5];
1105 if (datestr == NULL)
1108 if (order == ORDER_MDY && sep == SEPARATOR_SLASH)
1109 cm_strcpy(buf, datestr);
1111 if ( parse_date(order, sep, datestr, m, d, y) ) {
1112 sprintf(buf, "%s/%s/%s", m, d, y);
1122 ** Format the date according to display property and write it into buffer
1125 format_tick(Tick tick, OrderingType order, SeparatorType sep, char *buff) {
1126 char *str = separator_str(sep);
1128 _Xltimeparams localtime_buf;
1131 tm = _XLocaltime(&tick, localtime_buf);
1135 sprintf(buff, "%d%s%d%s%d", tm->tm_mday, str,
1136 tm->tm_mon+1, str, tm->tm_year+1900);
1139 sprintf(buff, "%d%s%d%s%d", tm->tm_year+1900, str,
1140 tm->tm_mon+1, str, tm->tm_mday);
1144 sprintf(buff, "%d%s%d%s%d", tm->tm_mon+1, str,
1145 tm->tm_mday, str, tm->tm_year+1900);
1151 format_time(Tick t, DisplayType dt, char *buffer) {
1158 } else if (dt == HOUR12) {
1159 am = adjust_hour(&hr);
1160 sprintf(buffer, "%2d:%02d%s",
1161 hr, minute(t), (am) ? "am" : "pm");
1163 sprintf(buffer, "%02d%02d", hr, minute(t));
1167 * The V5 back end uses arrays to pass attributes back and forth. However,
1168 * keeping hard coded references into those arrays (i.e. declaring the tick
1169 * value will always be into position 0 of the array, the what value in
1170 * position 3, etc.) is a bad idea and hard to maintain.
1172 * Thus these convenience functions will translate from an attribute array
1173 * received from the back end into defined structure which the front end can
1176 * IF YOU UPDATE THE STRUCTURES, MAKE SURE YOU UPDATE THESE COUNT CONSTANTS!!
1178 static const int APPT_ATTR_COUNT = 35;
1179 static const int RW_APPT_ATTR_COUNT = 15;
1180 static const int CAL_ATTR_COUNT = 12;
1181 static const int RW_CAL_ATTR_COUNT = 2;
1182 static const int DEF_V5_APPT_ATTR_COUNT = 22;
1183 static const int DEF_V4_APPT_ATTR_COUNT = 20;
1184 static const int DEF_V3_APPT_ATTR_COUNT = 17;
1185 static const int DEF_CAL_ATTR_COUNT = 6;
1186 static const int default_appt_attrs[] = {CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
1187 CSA_ENTRY_ATTR_LAST_UPDATE_I,
1188 CSA_ENTRY_ATTR_ORGANIZER_I,
1189 CSA_ENTRY_ATTR_START_DATE_I,
1190 CSA_ENTRY_ATTR_TYPE_I,
1191 CSA_ENTRY_ATTR_SUBTYPE_I,
1192 CSA_ENTRY_ATTR_CLASSIFICATION_I,
1193 CSA_ENTRY_ATTR_END_DATE_I,
1194 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
1195 CSA_ENTRY_ATTR_SUMMARY_I,
1196 CSA_ENTRY_ATTR_STATUS_I,
1197 CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
1198 CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
1199 CSA_ENTRY_ATTR_AUDIO_REMINDER_I,
1200 CSA_ENTRY_ATTR_FLASHING_REMINDER_I,
1201 CSA_ENTRY_ATTR_MAIL_REMINDER_I,
1202 CSA_ENTRY_ATTR_POPUP_REMINDER_I,
1203 CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
1204 CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
1205 CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I,
1206 CSA_ENTRY_ATTR_RECURRENCE_RULE_I,
1207 CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I
1209 static const int default_cal_attrs[] = {CSA_CAL_ATTR_ACCESS_LIST_I,
1210 CSA_CAL_ATTR_CALENDAR_NAME_I,
1211 CSA_CAL_ATTR_CALENDAR_SIZE_I,
1212 CSA_CAL_ATTR_NUMBER_ENTRIES_I,
1213 CSA_CAL_ATTR_TIME_ZONE_I,
1214 CSA_X_DT_CAL_ATTR_DATA_VERSION_I
1218 * NOTE that this loop is dependent on the first appointment attribute define
1219 * (DT_CM_ATTR_IDENTIFER_I) in the api - if that is changed and is no longer
1220 * the first appointment define, this needs to be changed.
1222 * NOTE that this function checks if the api indexes specified are read-only:
1223 * This assumes that if you need value space (and have set the need_value_space
1224 * flag to B_TRUE), you're setting attributes and since you can't set read-only
1225 * attributes, it will ignore read-only attributes if the need_value_space flag
1228 Dtcm_appointment *allocate_appt_struct (Allocation_reason reason, int version, ...) {
1229 int idx = 0, api_idx;
1231 CmDataList *api_ids = CmDataListCreate();
1232 Dtcm_appointment *appt;
1236 * The Dtcm_appointment wrapper array
1238 idx = sizeof(Dtcm_appointment);
1239 appt = (Dtcm_appointment *)ckalloc(idx);
1240 memset(appt, 0, idx);
1241 appt->reason = reason;
1242 appt->version = version;
1245 * Step through the variable argument list and build the list of
1246 * attributes we're looking for
1248 va_start(pvar, version);
1249 api_idx = va_arg(pvar, int);
1251 if ((reason == appt_read) || !entry_ident_index_ro(api_idx, version))
1252 CmDataListAdd(api_ids, (void *) (intptr_t) api_idx, 0);
1253 api_idx = va_arg(pvar, int);
1258 * No attributes specified, assume the caller wanted all of them
1260 if (api_ids->count <= 0) {
1262 if ((version == DATAVER2) || (version == DATAVER1))
1263 def_attr_count = DEF_V3_APPT_ATTR_COUNT;
1264 else if (version == DATAVER3)
1265 def_attr_count = DEF_V4_APPT_ATTR_COUNT;
1266 else if (version == DATAVER4)
1267 def_attr_count = DEF_V5_APPT_ATTR_COUNT;
1268 else if (version == DATAVER_ARCHIVE)
1269 def_attr_count = DEF_V5_APPT_ATTR_COUNT;
1271 for (idx = 0; idx < def_attr_count; idx++) {
1272 if ((reason == appt_write) && entry_ident_index_ro(default_appt_attrs[idx], version))
1274 CmDataListAdd(api_ids, (void *) (intptr_t) default_appt_attrs[idx], 0);
1279 * We've determined the number of attributes we're retrieving, so
1280 * allocate the name array, and the attribute array (if we are
1281 * going to be writing attributes).
1284 appt->num_names = api_ids->count;
1285 idx = sizeof(CSA_attribute_reference *) * appt->num_names;
1286 appt->names = (CSA_attribute_reference *)ckalloc(idx);
1287 memset(appt->names, 0, idx);
1289 appt->count = api_ids->count;
1290 if (reason == appt_write) {
1291 idx = sizeof(CSA_attribute) * appt->count;
1292 appt->attrs = (CSA_attribute *)ckalloc(idx);
1293 memset(appt->attrs, 0, idx);
1297 * Now loop through and set the names and initialize the attributes
1299 for (idx = 0; idx < appt->count; idx++) {
1300 api_idx = (int) (intptr_t) CmDataListGetData(api_ids, idx + 1);
1301 appt->names[idx] = strdup(_CSA_entry_attribute_names[api_idx]);
1302 if (reason == appt_write)
1303 initialize_entry_attr(api_idx, &appt->attrs[idx], reason, version);
1306 if (reason == appt_write)
1307 set_appt_links(appt);
1309 CmDataListDestroy(api_ids, 0);
1314 query_appt_struct(CSA_session_handle session,
1315 CSA_entry_handle entry_handle,
1316 Dtcm_appointment *appt) {
1318 CSA_return_code status;
1320 /* if there is old query material laying around, toss it */
1323 csa_free(appt->attrs);
1324 appt->filled = False;
1328 if ((status = csa_read_entry_attributes(session,
1334 NULL)) == CSA_SUCCESS) {
1335 set_appt_links(appt);
1336 appt->filled = True;
1344 * NOTE that this function checks if the api indexes specified are read-only:
1345 * This assumes that if you need value space (and have set the need_value_space
1346 * flag to B_TRUE), you're setting attributes and since you can't set read-only
1347 * attributes, it will ignore read-only attributes if the need_value_space flag
1351 allocate_cal_struct(Allocation_reason reason, int version, ...) {
1352 int idx = 0, api_idx;
1354 CmDataList *api_ids = CmDataListCreate();
1358 * The Dtcm_apopintment wrapper array
1360 idx = sizeof(Dtcm_calendar);
1361 cal = (Dtcm_calendar *)ckalloc(idx);
1362 memset(cal, 0, idx);
1363 cal->reason = reason;
1364 cal->version = version;
1367 * Step through the variable argument list and build the list of
1368 * attributes we're looking for
1370 va_start(pvar, version);
1371 api_idx = va_arg(pvar, int);
1373 if ((reason == appt_read) || !cal_ident_index_ro(api_idx, version))
1374 CmDataListAdd(api_ids, (void *) (intptr_t) api_idx, 0);
1375 api_idx = va_arg(pvar, int);
1380 * No attributes specified, assume the caller wanted all of them
1382 if (api_ids->count <= 0) {
1383 for (idx = 0; idx < DEF_CAL_ATTR_COUNT; idx++) {
1384 if ((reason == appt_write) && cal_ident_index_ro(default_cal_attrs[idx], version))
1386 CmDataListAdd(api_ids, (void *) (intptr_t) default_cal_attrs[idx], 0);
1391 * We've determined the number of attributes we're retrieving, so
1392 * allocate the name arrya, and the attribute array (if we are
1393 * going to be writing attributes).
1396 cal->num_names = api_ids->count;
1397 idx = sizeof(CSA_attribute_reference) * cal->num_names;
1398 cal->names = (CSA_attribute_reference *)ckalloc(idx);
1399 memset(cal->names, 0, idx);
1401 cal->count = api_ids->count;
1402 if (reason == appt_write) {
1403 idx = sizeof(CSA_attribute) * cal->count;
1404 cal->attrs = (CSA_attribute *)ckalloc(idx);
1405 memset(cal->attrs, 0, idx);
1409 * Now loop through and set the names and initialize the attributes
1411 for (idx = 0; idx < cal->count; idx++) {
1412 api_idx = (int) (intptr_t) CmDataListGetData(api_ids, idx + 1);
1413 cal->names[idx] = strdup(_CSA_calendar_attribute_names[api_idx]);
1414 if (reason == appt_write)
1415 initialize_cal_attr(api_idx, &cal->attrs[idx], reason, version);
1418 if (reason == appt_write)
1421 CmDataListDestroy(api_ids, 0);
1428 query_cal_struct(CSA_session_handle session,
1429 Dtcm_calendar *cal) {
1431 CSA_return_code status;
1433 /* if there is old query material laying around, toss it */
1436 csa_free(cal->attrs);
1437 cal->filled = False;
1440 if ((status = csa_read_calendar_attributes(session,
1445 NULL)) == CSA_SUCCESS) {
1454 scrub_cal_attr_list(Dtcm_calendar *cal) {
1458 for (i = 0; i < cal->count; i++) {
1459 if (cal->attrs[i].value->type == CSA_VALUE_REMINDER) {
1460 if ((cal->attrs[i].value->item.reminder_value->lead_time == NULL) ||
1461 (cal->attrs[i].value->item.reminder_value->lead_time[0] == '\0')) {
1462 free(cal->attrs[i].name);
1463 cal->attrs[i].name = NULL;
1466 else if ((cal->attrs[i].value->type == CSA_VALUE_ACCESS_LIST) && (cal->attrs[i].value->item.access_list_value == NULL)) {
1467 free(cal->attrs[i].name);
1468 cal->attrs[i].name = NULL;
1470 else if ((cal->attrs[i].value->type == CSA_VALUE_STRING) && (cal->attrs[i].value->item.string_value == NULL)) {
1471 free(cal->attrs[i].name);
1472 cal->attrs[i].name = NULL;
1474 else if ((cal->attrs[i].value->type == CSA_VALUE_DATE_TIME) && (cal->attrs[i].value->item.date_time_value == NULL)) {
1475 free(cal->attrs[i].name);
1476 cal->attrs[i].name = NULL;
1482 cal_ident_index_ro(int id, int version) {
1486 case CSA_CAL_ATTR_CALENDAR_NAME_I:
1487 case CSA_CAL_ATTR_CALENDAR_OWNER_I:
1488 case CSA_CAL_ATTR_CALENDAR_SIZE_I:
1489 case CSA_CAL_ATTR_CHARACTER_SET_I:
1490 case CSA_CAL_ATTR_NUMBER_ENTRIES_I:
1491 case CSA_CAL_ATTR_DATE_CREATED_I:
1492 case CSA_CAL_ATTR_PRODUCT_IDENTIFIER_I:
1493 case CSA_X_DT_CAL_ATTR_DATA_VERSION_I:
1494 case CSA_CAL_ATTR_TIME_ZONE_I:
1506 entry_ident_index_ro(int id, int version) {
1510 case CSA_ENTRY_ATTR_DATE_CREATED_I:
1511 case CSA_ENTRY_ATTR_LAST_UPDATE_I:
1512 case CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I:
1513 case CSA_ENTRY_ATTR_ORGANIZER_I:
1514 case CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I:
1515 case CSA_ENTRY_ATTR_SEQUENCE_NUMBER_I:
1518 case CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I:
1519 case CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I:
1520 case CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I:
1521 case CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I:
1522 case CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I:
1523 if (version >= DATAVER4)
1537 cal_ident_index_tag(int id) {
1541 case CSA_CAL_ATTR_CALENDAR_NAME_I:
1542 case CSA_CAL_ATTR_CHARACTER_SET_I:
1543 case CSA_CAL_ATTR_COUNTRY_I:
1544 case CSA_CAL_ATTR_PRODUCT_IDENTIFIER_I:
1545 case CSA_CAL_ATTR_TIME_ZONE_I:
1546 case CSA_CAL_ATTR_LANGUAGE_I:
1547 r_tag = CSA_VALUE_STRING;
1549 case CSA_CAL_ATTR_CALENDAR_OWNER_I:
1550 r_tag = CSA_VALUE_CALENDAR_USER;
1552 case CSA_CAL_ATTR_DATE_CREATED_I:
1553 r_tag = CSA_VALUE_DATE_TIME;
1555 case CSA_CAL_ATTR_CALENDAR_SIZE_I:
1556 case CSA_CAL_ATTR_NUMBER_ENTRIES_I:
1557 case CSA_X_DT_CAL_ATTR_DATA_VERSION_I:
1558 r_tag = CSA_VALUE_UINT32;
1560 case CSA_CAL_ATTR_ACCESS_LIST_I:
1561 r_tag = CSA_VALUE_ACCESS_LIST;
1563 case CSA_CAL_ATTR_WORK_SCHEDULE_I:
1565 r_tag = CSA_VALUE_OPAQUE_DATA;
1573 entry_ident_index_tag(int id) {
1577 case CSA_ENTRY_ATTR_DESCRIPTION_I:
1578 case CSA_ENTRY_ATTR_EXCEPTION_RULE_I:
1579 case CSA_ENTRY_ATTR_RECURRENCE_RULE_I:
1580 case CSA_ENTRY_ATTR_SUBTYPE_I:
1581 case CSA_ENTRY_ATTR_SUMMARY_I:
1582 r_tag = CSA_VALUE_STRING;
1584 case CSA_ENTRY_ATTR_DATE_COMPLETED_I:
1585 case CSA_ENTRY_ATTR_DATE_CREATED_I:
1586 case CSA_ENTRY_ATTR_DUE_DATE_I:
1587 case CSA_ENTRY_ATTR_END_DATE_I:
1588 case CSA_ENTRY_ATTR_LAST_UPDATE_I:
1589 case CSA_ENTRY_ATTR_START_DATE_I:
1590 case CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I:
1591 r_tag = CSA_VALUE_DATE_TIME;
1593 case CSA_ENTRY_ATTR_EXCEPTION_DATES_I:
1594 case CSA_ENTRY_ATTR_RECURRING_DATES_I:
1595 r_tag = CSA_VALUE_DATE_TIME_LIST;
1597 case CSA_ENTRY_ATTR_CLASSIFICATION_I:
1598 case CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I:
1599 case CSA_ENTRY_ATTR_PRIORITY_I:
1600 case CSA_ENTRY_ATTR_SEQUENCE_NUMBER_I:
1601 case CSA_ENTRY_ATTR_STATUS_I:
1602 case CSA_ENTRY_ATTR_TYPE_I:
1603 case CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I:
1604 case CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I:
1605 r_tag = CSA_VALUE_UINT32;
1607 case CSA_ENTRY_ATTR_TIME_TRANSPARENCY_I:
1608 case CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I:
1609 case CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I:
1610 case CSA_X_DT_ENTRY_ATTR_SHOWTIME_I:
1611 r_tag = CSA_VALUE_SINT32;
1613 case CSA_ENTRY_ATTR_AUDIO_REMINDER_I:
1614 case CSA_ENTRY_ATTR_FLASHING_REMINDER_I:
1615 case CSA_ENTRY_ATTR_MAIL_REMINDER_I:
1616 case CSA_ENTRY_ATTR_POPUP_REMINDER_I:
1617 r_tag = CSA_VALUE_REMINDER;
1619 case CSA_ENTRY_ATTR_ORGANIZER_I:
1620 case CSA_ENTRY_ATTR_SPONSOR_I:
1621 r_tag = CSA_VALUE_CALENDAR_USER;
1623 case CSA_ENTRY_ATTR_ATTENDEE_LIST_I:
1624 r_tag = CSA_VALUE_ATTENDEE_LIST;
1626 case CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I:
1628 r_tag = CSA_VALUE_OPAQUE_DATA;
1636 ident_name_ro(char *name, int version) {
1637 boolean_t r_ro = B_FALSE;
1639 if (strcmp(name, CSA_CAL_ATTR_CALENDAR_NAME) == 0 ||
1640 strcmp(name, CSA_CAL_ATTR_CALENDAR_OWNER) == 0 ||
1641 strcmp(name, CSA_CAL_ATTR_CALENDAR_SIZE) == 0 ||
1642 strcmp(name, CSA_CAL_ATTR_DATE_CREATED) == 0 ||
1643 strcmp(name, CSA_CAL_ATTR_PRODUCT_IDENTIFIER) == 0 ||
1644 strcmp(name, CSA_X_DT_CAL_ATTR_DATA_VERSION) == 0 ||
1645 strcmp(name, CSA_ENTRY_ATTR_SEQUENCE_NUMBER) == 0 ||
1646 strcmp(name, CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER) == 0 ||
1647 strcmp(name, CSA_ENTRY_ATTR_ORGANIZER) == 0 ||
1648 strcmp(name, CSA_ENTRY_ATTR_LAST_UPDATE) == 0 ||
1649 strcmp(name, CSA_ENTRY_ATTR_DATE_CREATED) == 0 ||
1650 strcmp(name, CSA_ENTRY_ATTR_NUMBER_RECURRENCES) == 0)
1653 if ((version >= DATAVER4) &&
1654 (strcmp(name, CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE) == 0 ||
1655 strcmp(name, CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES) == 0 ||
1656 strcmp(name, CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL) == 0 ||
1657 strcmp(name, CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM) == 0))
1664 initialize_cal_attr(int id, CSA_attribute *attrs, Allocation_reason reason, int version) {
1667 attrs->name = cm_strdup(_CSA_calendar_attribute_names[id]);
1668 if ((reason == appt_write) && !cal_ident_index_ro(id, version)) {
1669 size = sizeof(CSA_attribute_value);
1670 attrs->value = (CSA_attribute_value *)ckalloc(size);
1671 memset(attrs->value, 0, size);
1672 attrs->value->type = cal_ident_index_tag(id);
1673 if (attrs->value->type == CSA_VALUE_REMINDER)
1674 attrs->value->item.reminder_value = (CSA_reminder *) calloc(sizeof(CSA_reminder), 1);
1679 free_attr(CSA_attribute *attr) {
1689 if ((attr->value->type == CSA_VALUE_STRING) && attr->value->item.string_value != NULL)
1690 free(attr->value->item.string_value);
1691 else if ((attr->value->type == CSA_VALUE_DATE_TIME) && attr->value->item.date_time_value != NULL)
1692 free(attr->value->item.date_time_value);
1693 else if ((attr->value->type == CSA_VALUE_REMINDER) && attr->value->item.reminder_value != NULL) {
1694 if (attr->value->item.reminder_value->lead_time)
1695 free(attr->value->item.reminder_value->lead_time);
1696 if (attr->value->item.reminder_value->reminder_data.data)
1697 free(attr->value->item.reminder_value->reminder_data.data);
1699 free(attr->value->item.reminder_value);
1708 initialize_entry_attr(int id, CSA_attribute *attrs, Allocation_reason reason, int version) {
1711 attrs->name = cm_strdup(_CSA_entry_attribute_names[id]);
1712 if ((reason == appt_write) && !entry_ident_index_ro(id, version)) {
1713 size = sizeof(CSA_attribute_value);
1714 attrs->value = (CSA_attribute_value *)ckalloc(size);
1715 memset(attrs->value, 0, size);
1716 attrs->value->type = entry_ident_index_tag(id);
1717 if (attrs->value->type == CSA_VALUE_REMINDER)
1718 attrs->value->item.reminder_value = (CSA_reminder *) calloc(sizeof(CSA_reminder), 1);
1723 free_appt_struct(Dtcm_appointment **appt) {
1729 if ((*appt)->names) {
1730 for (i = 0; i < (*appt)->num_names; i++)
1731 if ((*appt)->names[i])
1732 free((*appt)->names[i]);
1734 free((*appt)->names);
1737 /* potential memory leak here. We must be careful, as results
1738 from querys should be thrown away with csa_free(), while
1739 structures we've set up to do update/write operations were
1740 allocated by the client, and need to be freed by that client. */
1742 if (((*appt)->reason == appt_read) && ((*appt)->filled == True))
1743 csa_free((*appt)->attrs);
1745 if ((*appt)->attrs) {
1746 for (i = 0; i < (*appt)->count; i++)
1747 free_attr(&((*appt)->attrs[i]));
1749 free((*appt)->attrs);
1757 free_cal_struct(Dtcm_calendar **cal) {
1763 if ((*cal)->names) {
1764 for (i = 0; i < (*cal)->num_names; i++)
1765 if ((*cal)->names[i])
1766 free((*cal)->names[i]);
1768 free((*cal)->names);
1771 /* potential memory leak here. We must be careful, as results
1772 from querys should be thrown away with csa_free(), while
1773 structures we've set up to do update/write operations were
1774 allocated by the client, and need to be freed by that client. */
1776 if (((*cal)->reason == appt_read) && ((*cal)->filled == True))
1777 csa_free((*cal)->attrs);
1779 if ((*cal)->attrs) {
1780 for (i = 0; i < (*cal)->count; i++)
1781 free_attr(&((*cal)->attrs[i]));
1782 free((*cal)->attrs);
1790 set_appt_links(Dtcm_appointment *appt) {
1794 appt->identifier = NULL;
1795 appt->modified_time = NULL;
1796 appt->author = NULL;
1797 appt->number_recurrence = NULL;
1800 appt->subtype = NULL;
1801 appt->private = NULL;
1802 appt->end_time = NULL;
1803 appt->show_time = NULL;
1806 appt->repeat_type = NULL;
1807 appt->repeat_times = NULL;
1808 appt->repeat_interval = NULL;
1809 appt->repeat_week_num = NULL;
1810 appt->recurrence_rule = NULL;
1815 appt->sequence_end_date = NULL;
1817 for (idx = 0; idx < appt->count; idx++) {
1818 idx_name = appt->attrs[idx].name;
1821 else if (strcmp(idx_name, CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER) == 0)
1822 appt->identifier = &appt->attrs[idx];
1823 else if (strcmp(idx_name, CSA_ENTRY_ATTR_LAST_UPDATE) == 0)
1824 appt->modified_time = &appt->attrs[idx];
1825 else if (strcmp(idx_name, CSA_ENTRY_ATTR_ORGANIZER) == 0)
1826 appt->author = &appt->attrs[idx];
1827 else if (strcmp(idx_name, CSA_ENTRY_ATTR_NUMBER_RECURRENCES) == 0)
1828 appt->number_recurrence = &appt->attrs[idx];
1829 else if (strcmp(idx_name, CSA_ENTRY_ATTR_START_DATE) == 0)
1830 appt->time = &appt->attrs[idx];
1831 else if (strcmp(idx_name, CSA_ENTRY_ATTR_TYPE) == 0)
1832 appt->type = &appt->attrs[idx];
1833 else if (strcmp(idx_name, CSA_ENTRY_ATTR_SUBTYPE) == 0)
1834 appt->subtype = &appt->attrs[idx];
1835 else if (strcmp(idx_name, CSA_ENTRY_ATTR_CLASSIFICATION) == 0)
1836 appt->private = &appt->attrs[idx];
1837 else if (strcmp(idx_name, CSA_ENTRY_ATTR_END_DATE) == 0)
1838 appt->end_time = &appt->attrs[idx];
1839 else if (strcmp(idx_name, CSA_X_DT_ENTRY_ATTR_SHOWTIME) == 0)
1840 appt->show_time = &appt->attrs[idx];
1841 else if (strcmp(idx_name, CSA_ENTRY_ATTR_SUMMARY) == 0)
1842 appt->what = &appt->attrs[idx];
1843 else if (strcmp(idx_name, CSA_ENTRY_ATTR_STATUS) == 0)
1844 appt->state = &appt->attrs[idx];
1845 else if (strcmp(idx_name, CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE) == 0)
1846 appt->repeat_type = &appt->attrs[idx];
1847 else if (strcmp(idx_name, CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES) == 0)
1848 appt->repeat_times = &appt->attrs[idx];
1849 else if (strcmp(idx_name, CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL) == 0)
1850 appt->repeat_interval = &appt->attrs[idx];
1851 else if (strcmp(idx_name, CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM) == 0)
1852 appt->repeat_week_num = &appt->attrs[idx];
1853 else if (strcmp(idx_name, CSA_ENTRY_ATTR_RECURRENCE_RULE) == 0)
1854 appt->recurrence_rule = &appt->attrs[idx];
1855 else if (strcmp(idx_name, CSA_ENTRY_ATTR_AUDIO_REMINDER) == 0)
1856 appt->beep = &appt->attrs[idx];
1857 else if (strcmp(idx_name, CSA_ENTRY_ATTR_FLASHING_REMINDER) == 0)
1858 appt->flash = &appt->attrs[idx];
1859 else if (strcmp(idx_name, CSA_ENTRY_ATTR_MAIL_REMINDER) == 0)
1860 appt->mail = &appt->attrs[idx];
1861 else if (strcmp(idx_name, CSA_ENTRY_ATTR_POPUP_REMINDER) == 0)
1862 appt->popup = &appt->attrs[idx];
1863 else if (strcmp(idx_name, CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE) == 0)
1864 appt->sequence_end_date = &appt->attrs[idx];
1869 set_cal_links(Dtcm_calendar *cal) {
1873 for (idx = 0; idx < cal->count; idx++) {
1874 idx_name = cal->attrs[idx].name;
1875 if (strcmp(idx_name, CSA_CAL_ATTR_CALENDAR_NAME) == 0)
1876 cal->cal_name = &cal->attrs[idx];
1877 else if (strcmp(idx_name, CSA_X_DT_CAL_ATTR_DATA_VERSION) == 0)
1878 cal->server_version = &cal->attrs[idx];
1879 else if (strcmp(idx_name, CSA_CAL_ATTR_NUMBER_ENTRIES) == 0)
1880 cal->num_entries = &cal->attrs[idx];
1881 else if (strcmp(idx_name, CSA_CAL_ATTR_CALENDAR_SIZE) == 0)
1882 cal->cal_size = &cal->attrs[idx];
1883 else if (strcmp(idx_name, CSA_CAL_ATTR_ACCESS_LIST) == 0)
1884 cal->access_list = &cal->attrs[idx];
1885 else if (strcmp(idx_name, CSA_CAL_ATTR_TIME_ZONE) == 0)
1886 cal->time_zone = &cal->attrs[idx];
1891 setup_range(CSA_attribute **attrs, CSA_enum **ops, int *count, time_t start,
1892 time_t stop, CSA_sint32 type, CSA_sint32 state, boolean_t use_state,
1896 CSA_attribute *attr_ptr;
1904 a_size = sizeof(CSA_attribute) * (*count);
1905 attr_ptr = (CSA_attribute *)ckalloc(a_size);
1906 memset(attr_ptr, 0, a_size);
1908 o_size = sizeof(CSA_enum) * (*count);
1909 op_ptr = (CSA_enum *)ckalloc(o_size);
1910 memset(op_ptr, 0, o_size);
1912 initialize_entry_attr(CSA_ENTRY_ATTR_START_DATE_I, &attr_ptr[0], appt_write, version);
1913 attr_ptr[0].value->item.string_value = malloc(BUFSIZ);
1914 _csa_tick_to_iso8601(start, attr_ptr[0].value->item.string_value);
1916 op_ptr[0] = CSA_MATCH_GREATER_THAN_OR_EQUAL_TO;
1918 initialize_entry_attr(CSA_ENTRY_ATTR_START_DATE_I, &attr_ptr[1], appt_write, version);
1919 attr_ptr[1].value->item.string_value = malloc(BUFSIZ);
1920 _csa_tick_to_iso8601(stop, attr_ptr[1].value->item.string_value);
1921 op_ptr[1] = CSA_MATCH_LESS_THAN_OR_EQUAL_TO;
1923 initialize_entry_attr(CSA_ENTRY_ATTR_TYPE_I, &attr_ptr[2], appt_write, version);
1924 attr_ptr[2].value->item.sint32_value = type;
1925 op_ptr[2] = CSA_MATCH_EQUAL_TO;
1928 initialize_entry_attr(CSA_ENTRY_ATTR_STATUS_I, &attr_ptr[3], appt_write, version);
1929 attr_ptr[3].value->item.sint32_value = state;
1930 op_ptr[3] = CSA_MATCH_EQUAL_TO;
1938 free_range(CSA_attribute **attrs, CSA_enum **ops, int count) {
1941 for (i = 0; i < count; i++) {
1942 free((*attrs)[i].name);
1943 if (((*attrs)[i].value->type == CSA_VALUE_STRING) ||
1944 ((*attrs)[i].value->type == CSA_VALUE_DATE_TIME))
1945 if ((*attrs)[i].value->item.string_value)
1946 free((*attrs)[i].value->item.string_value);
1948 free((*attrs)[i].value);
1951 /* This memory was allocated by the client, and must be freed
1963 * In Motif you can't associate user data with items in a list. To get around
1964 * this we have the following simple functions (CmDataList*) that maintain
1965 * a list of user data. We follow the intrinscs coding style to re-inforce
1966 * the relationship these routines have to the XmList* functions.
1970 * Create a list to store user data
1973 CmDataListCreate(void)
1976 return (CmDataList *)calloc(1, sizeof(CmDataList));
1983 CmDataListDestroy(CmDataList *list, int free_data)
1986 CmDataListDeleteAll(list, free_data);
1991 * Create node to hold data in list.
1994 CmDataItemCreate(void)
1997 return (CmDataItem *)calloc(1, sizeof(CmDataItem));
2001 * Add user data to list at specified position. Note that this
2002 * routine must be called for every item added to a list.
2003 * If the item has no user data, just pass NULL.
2005 * list List to add data to
2006 * data User data. NULL for no data.
2007 * position Where to insert data, starting with 1 for the
2008 * first item. 0 to append to end of list.
2012 * -1 Invalid position
2015 CmDataListAdd(CmDataList *list, void *data, int position)
2018 CmDataItem *item, *p;
2021 /* Create new node to hold data */
2022 item = CmDataItemCreate();
2025 /* Insert node into list at appropriate spot */
2026 if (list->head == NULL) {
2028 } else if (position == 0) {
2029 /* Special case. 0 means append to end */
2030 list->tail->next = item;
2031 } else if (position == 1) {
2032 item->next = list->head;
2035 for (n = 2, p = list->head; p != NULL && n < position;
2043 item->next = p->next;
2047 /* If new item is at the end of the list, update tail */
2048 if (item->next == NULL) {
2058 * Delete user data from a position in the list. If free_data is
2059 * True then this routine will call free(3C) on the user data, otherwise
2060 * the user data is returned so that the caller can dispose of it.
2061 * This routine should be called anytime you delete an item from a
2064 * list List to delete data from
2065 * position Location of item to delete. 0 for last item
2066 * free_data True if you want this routine to call free()
2067 * on the data for you. Otherwise this routine
2068 * will return the address of the data.
2071 * NULL No data found for item at the specified position
2072 * 1 Success (free_data was True)
2073 * other Address of data for item at the specified position.
2074 * (free_data was False)
2077 CmDataListDeletePos(CmDataList *list, int position, int free_data)
2081 CmDataItem *p, *item;
2084 /* Special case. 0 means delete last item */
2085 if (position == 0) {
2086 position = list->count;
2089 if (list->head == NULL) {
2091 } else if (position == 1) {
2093 list->head = item->next;
2094 if (list->tail == item) {
2095 list->tail = item->next;
2098 for (n = 2, p = list->head; p->next != NULL && n < position;
2102 if (p->next == NULL) {
2107 p->next = item->next;
2108 if (list->tail == item) {
2128 * Delete all nodes in the list.
2130 * list List to delete nodes from
2131 * free_data True if you want this routine to call free()
2132 * on the data for you.
2135 CmDataListDeleteAll(CmDataList *list, int free_data)
2138 CmDataItem *p, *tmp;
2142 if (free_data && p->data != NULL) {
2159 * Get data for the item at a particular position in a list.
2162 CmDataListGetData(CmDataList *list, int position)
2166 CmDataItem *p, *item;
2169 if (list->head == NULL) {
2171 } else if (position == 0) {
2172 data = list->tail->data;
2174 for (n = 1, p = list->head; p != NULL && n < position;
2188 * For dumping contents of list
2191 CmDataListDump(CmDataList *list)
2197 printf("***** %d items:\n", list->count);
2199 for (p = list->head, n = 1; p != NULL; p = p->next, n++) {
2200 printf("%3d: %s\n", n, p->data ? (char *)p->data : "<nil>");