Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtcm / server / log.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: log.c /main/8 1996/11/21 19:45:13 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 <errno.h>
36 #include <pwd.h>
37 #include <unistd.h>
38 #include <sys/stat.h>
39 #include <sys/file.h>
40 #define XOS_USE_NO_LOCKING
41 #define X_INCLUDE_TIME_H
42 #include <X11/Xos_r.h>
43 #include "cm.h"
44 #include "rtable4.h"
45 #include "log.h"
46 #include "iso8601.h"
47
48 extern uid_t    daemon_uid;
49 extern gid_t    daemon_gid;
50 extern char     *pgname;
51 extern int      debug;
52 static char     *spool_dir = _DtCMS_DEFAULT_DIR;
53
54 char *tag_string[] = {
55         "0:boolean",
56         "1:enum",
57         "2:flags",
58         "3:sint32",
59         "4:uint32",
60         "5:string",
61         "6:user",
62         "7:date_time",
63         "8:date_time_range",
64         "9:time_duration",
65         "10:access_list",
66         "11:attendees",
67         "12:date_time_list",
68         "13:reminder",
69         "14:opaque_data",
70         NULL
71 };
72
73 /*
74  * forward declaration of functions used within this file
75  */
76 static char * cr_to_str(char *s, int size);
77 static void periodtostr(Interval_4 i, char *q);
78 static void privacytostr(Privacy_Level_4 p, char *q);
79 static void apptstatustostr(Appt_Status_4 p, char *q);
80 static void apptstatustostr(Appt_Status_4 p, char *q);
81 static void tagstostr(Event_Type_4 p, char *q);
82 static char * get_fname (char *dir, char *fname, char *who);
83 static CSA_return_code append_log(int f, char *buf);
84 static CSA_return_code create_log(char *owner, char *file, int version);
85 static char *attrs_to_attrliststr(int len, cms_attribute *attrs,
86                                 boolean_t write_hash, boolean_t entryattrs);
87 static char *grow_n_concat(char *base, char *newstr, int newcount);
88 static char *get_access_list_string(cms_access_entry *list);
89 static char *get_date_time_list_string(CSA_date_time_list list);
90
91
92 /*
93  * extern functions
94  */
95
96 extern char *
97 _DtCmsGetLogFN(char *who)
98 {
99         return (get_fname (spool_dir, _DtCMS_DEFAULT_LOG, who));
100 }
101  
102 extern char *
103 _DtCmsGetBakFN(char *who)
104 {
105         return (get_fname (spool_dir, _DtCMS_DEFAULT_BAK, who));
106 }
107  
108 extern char *
109 _DtCmsGetTmpFN(char *who)
110 {
111         return (get_fname (spool_dir, _DtCMS_DEFAULT_TMP, who));
112 }
113
114 extern char *
115 _DtCmsGetDelFN(char *who)
116 {
117         return (get_fname (spool_dir, _DtCMS_DEFAULT_DEL, who));
118 }
119
120 extern CSA_return_code
121 _DtCmsCreateLogV1(char *owner, char *file)
122 {
123         return (create_log(owner, file, _DtCMS_VERSION1));
124 }
125
126
127 extern CSA_return_code
128 _DtCmsAppendHTableByFN(char *file, uint size, char **names, int *types)
129 {
130         int     f;
131         CSA_return_code stat;
132
133         if ((f = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0) {
134                 perror(pgname);
135                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
136         }
137
138         stat = _DtCmsAppendHTableByFD(f, size, names, types);
139
140         close(f);
141         return (stat);
142 }
143
144 /*
145  * the first element of the arrays is not used
146  */
147 extern CSA_return_code
148 _DtCmsAppendHTableByFD(int fd, uint size, char **names, int *types)
149 {
150         CSA_return_code stat;
151         char    *tptr, *buf, tmpbuf[BUFSIZ/4];
152         int     i, tcount, count = 15;  /* strlen("(entrytable )\n") + 1 */
153
154         if ((buf = malloc(BUFSIZ)) == NULL) return (CSA_E_INSUFFICIENT_MEMORY);
155         tcount = BUFSIZ;
156         strcpy(buf, "(entrytable ");
157
158         for (i = 1; i <= size; i++) {
159                 sprintf(tmpbuf, "(%d \"%s\" \"%s\")\n", i, names[i],
160                         tag_string[types[i]]);
161
162                 count += strlen(tmpbuf);
163                 if (tcount < count) {
164                         if ((tptr = grow_n_concat(buf, tmpbuf, tcount + BUFSIZ))
165                             == NULL) {
166                                 free(buf);
167                                 return (CSA_E_INSUFFICIENT_MEMORY);
168                         }
169                         buf = tptr;
170                         tcount += BUFSIZ;
171                 } else
172                         strcat(buf, tmpbuf);
173         }
174
175         strcat(buf, ")\n");
176
177         stat = append_log(fd, buf);
178
179         free(buf);
180         return (stat);
181 }
182
183 extern CSA_return_code
184 _DtCmsAppendEntryByFN(char *file, cms_entry *entry, _DtCmsLogOps op)
185 {
186         int     f;
187         CSA_return_code stat;
188
189         if ((f = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0) {
190                 perror(pgname);
191                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
192         }
193
194         stat = _DtCmsAppendEntryByFD(f, entry, op);
195
196         close(f);
197         return (stat);
198 }
199
200 extern CSA_return_code
201 _DtCmsAppendEntryByFD(int f, cms_entry *entry, _DtCmsLogOps op)
202 {
203         CSA_return_code stat;
204         int     count;
205         char    *cptr, *tptr, *buf;
206         char    isotime[25];
207
208         if ((buf = malloc(100)) == NULL) return (CSA_E_INSUFFICIENT_MEMORY);
209
210         _csa_tick_to_iso8601(entry->key.time, isotime);
211         sprintf(buf, "(%s \"%s\" key: %ld%s",
212                 (op == _DtCmsLogAdd ? "add" : "remove"),
213                 isotime, entry->key.id,
214                 (op == _DtCmsLogAdd ? "\nhashedattributes: (" : ""));
215         count = strlen(buf) + 4;
216
217         if (op == _DtCmsLogAdd && entry->num_attrs > 0) {
218                 if ((cptr = attrs_to_attrliststr(entry->num_attrs,
219                     entry->attrs, B_TRUE, B_TRUE)) == NULL) {
220                         free(buf);
221                         return (CSA_E_INSUFFICIENT_MEMORY);
222                 }
223                 count += strlen(cptr);
224                 if ((tptr = grow_n_concat(buf, cptr, count)) == NULL) {
225                         free(cptr);
226                         free(buf);
227                         return (CSA_E_INSUFFICIENT_MEMORY);
228                 }
229                 free(cptr);
230                 buf = tptr;
231         }
232
233         /* closing for attr list and closing for entry */
234         if (op == _DtCmsLogAdd)
235                 strcat(buf, "))\n");
236         else
237                 strcat(buf, ")\n");
238
239         stat = append_log(f, buf);
240
241         free(buf);
242         return (stat);
243 }
244
245 extern CSA_return_code
246 _DtCmsAppendCalAttrsByFN(char *file, int size, cms_attribute * attrs)
247 {
248         int     f;
249         CSA_return_code stat;
250
251         if (file == NULL || size <= 0)
252                 return (CSA_E_INVALID_PARAMETER);
253
254         if ((f = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0) {
255                 perror(pgname);
256                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
257         }
258
259         stat = _DtCmsAppendCalAttrsByFD(f, size, attrs);
260
261         close(f);
262         return (stat);
263 }
264
265 extern CSA_return_code
266 _DtCmsAppendCalAttrsByFD(int f, int size, cms_attribute * attrs)
267 {
268         CSA_return_code stat;
269         char    *buf, *attrstr;
270         char    *prefix = "(calendarattributes ";
271         char    *subfix = ")\n";
272         int     count;
273
274         if ((attrstr = attrs_to_attrliststr(size, attrs, B_FALSE, B_FALSE))
275             == NULL)
276                 return (CSA_E_INSUFFICIENT_MEMORY);
277
278         count = strlen(prefix) + strlen(attrstr) + strlen(subfix) + 1;
279         if ((buf = malloc(count)) == NULL) {
280                 free(attrstr);
281                 return (CSA_E_INSUFFICIENT_MEMORY);
282         }
283         sprintf(buf, "%s%s%s", prefix, attrstr, subfix);
284
285         stat = append_log(f, buf);
286
287         free(attrstr);
288         free(buf);
289         return (stat);
290 }
291
292 extern CSA_return_code
293 _DtCmsAppendAppt4ByFN(char *file, Appt_4 *appt, _DtCmsLogOps op)
294 {
295         int     f;
296         CSA_return_code stat;
297
298         if ((f = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0) {
299                 perror(pgname);
300                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
301         }
302
303         stat = _DtCmsAppendAppt4ByFD(f, appt, op);
304
305         close(f);
306         return (stat);
307 }
308
309 extern CSA_return_code
310 _DtCmsAppendAppt4ByFD(int f, Appt_4 *appt, _DtCmsLogOps op)
311 {
312         char *cptr;
313         char tmpbuf[BUFSIZ];
314         char buf[BUFSIZ*3], buf2[BUFSIZ*2]; /* 1 BUFSIZ for what fields, 
315                                                1 BUFSIZ for mailto field,
316                                                and 1 BUFSIZ for the rest */
317
318         cptr = ctime (&appt->appt_id.tick);
319         cptr[24] = NULL;                /* strip off CR */
320
321         buf[0] = NULL;
322         switch (op) {
323         case _DtCmsLogAdd:
324                 sprintf(buf, "(add \"%s\" key: %ld ", cptr, appt->appt_id.key);
325                 if (appt->what) {
326                         cptr = cr_to_str(appt->what, strlen(appt->what));
327                         if (cptr != NULL) {
328                                 sprintf(buf2, "what: \"%s\" ", cptr);
329                                 strcat(buf, buf2);
330                                 free(cptr);
331                         } else {
332                                 return (CSA_E_INSUFFICIENT_MEMORY);
333                         }
334                 }
335                 if (appt->client_data) {
336                         sprintf(buf2, "details: \"%s\" ", appt->client_data);
337                         strcat(buf, buf2);
338                 }
339                 if (appt->duration) {
340                         sprintf(buf2, "duration: %d ", appt->duration);
341                         strcat(buf, buf2);
342                 }
343
344                 periodtostr (appt->period.period, tmpbuf);
345                 sprintf(buf2, "period: %s ", tmpbuf);
346                 strcat(buf, buf2);
347
348                 if (appt->period.nth != 0) {
349                         sprintf (buf2, "nth: %d ", appt->period.nth);
350                         strcat(buf, buf2);
351                 }
352                 if (appt->period.enddate != 0) {
353                         cptr = ctime (&(appt->period.enddate));
354                         cptr[24] = NULL; /* strip off CR */
355                         sprintf(buf2, "enddate: \"%s\" ", cptr);
356                         strcat(buf, buf2);
357                 }
358
359                 sprintf(buf2, "ntimes: %d ", appt->ntimes);
360                 strcat(buf, buf2);
361
362                 if (appt->exception != NULL) {
363                         struct Except_4 *e = appt->exception;
364                         strcat(buf, "exceptions: (");
365                         while(e != NULL) {
366                                 sprintf(buf2, "%d ", e->ordinal);
367                                 strcat(buf, buf2);
368                                 e = e->next;
369                         }
370                         strcat(buf, ") ");
371                 }
372
373                 if (appt->author != NULL) {
374                         sprintf(buf2, "author: \"%s\" ", appt->author);
375                         strcat(buf, buf2);
376                 }
377                 if (appt->attr != NULL) {
378                         struct Attribute_4 *item = appt->attr;
379                         strcat(buf, "attributes: (");
380                         while(item != NULL) {
381                                 sprintf(buf2, "(\"%s\",\"%s\",\"%s\")",
382                                         item->attr, item->value,
383                                         item->clientdata);
384                                 strcat(buf, buf2);
385                                 item = item->next;
386                         }
387                         strcat(buf, ") ");
388                 }
389                 if (appt->tag != NULL) {
390                         struct Tag_4 *item = appt->tag;
391                         strcat(buf, "tags: (");
392                         while(item != NULL) {
393                                 tagstostr(item->tag, tmpbuf);
394                                 sprintf(buf2, "(%s , %d)", tmpbuf,
395                                         item->showtime);
396                                 strcat(buf, buf2);
397                                 item = item->next;
398                         }
399                         strcat(buf, ") ");
400                 }
401
402                 apptstatustostr(appt->appt_status, tmpbuf);
403                 sprintf(buf2, "apptstat: %s ", tmpbuf);
404                 strcat(buf, buf2);
405
406                 privacytostr(appt->privacy, tmpbuf);
407                 sprintf(buf2, "privacy: %s )\n", tmpbuf);
408                 strcat(buf, buf2);
409
410                 break;    
411
412         case _DtCmsLogRemove:
413                 sprintf(buf, "(remove \"%s\" key: %ld)\n", cptr,
414                         appt->appt_id.key);
415                 break;
416         }
417
418         return (append_log(f, buf));
419 }
420
421 extern CSA_return_code
422 _DtCmsAppendAccessByFN(char *file, int type, Access_Entry_4 *p)
423 {
424         int     f;
425         CSA_return_code stat;
426
427         if ((f = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0) {
428                 perror(pgname);
429                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
430         }
431
432         stat = _DtCmsAppendAccessByFD(f, type, p);
433
434         close(f);
435         return (stat);
436 }
437
438 extern CSA_return_code
439 _DtCmsAppendAccessByFD(int f, int type, Access_Entry_4 *p)
440 {
441         CSA_return_code stat;
442         int     count = 12; /* (access  )\n */
443         char    *p_type;
444         char    *buf;
445
446         if (type == access_read_4)
447                 p_type = "read";
448         else if (type == access_write_4)
449                 p_type = "write";
450         else if (type == access_delete_4)
451                 p_type = "delete";
452         else if (type == access_exec_4)
453                 p_type = "exec";
454         else
455                 return (CSA_E_INVALID_PARAMETER);
456
457         count = count + strlen(p_type);
458         if ((buf = malloc(count)) == NULL)
459                 return (CSA_E_INSUFFICIENT_MEMORY);
460
461         sprintf(buf, "(access %s ", p_type);
462
463         while(p != NULL) {
464                 if (p->who != NULL) {
465                         count = count + strlen(p->who) + 3;
466                         if ((buf = realloc(buf, count)) == NULL)
467                                 return (CSA_E_INSUFFICIENT_MEMORY);
468                         else {
469                                 strcat(buf, "\"");
470                                 strcat(buf, p->who);
471                                 strcat(buf, "\" ");
472                         }
473                 }
474                 p = p->next;
475         }
476         strcat(buf, ")\n");
477
478         stat = append_log(f, buf);
479
480         free(buf);
481         return(stat);
482 }
483
484 extern boolean_t
485 _DtCmsPrintAppt4(caddr_t data)
486 {
487         Appt_4 *appt = (Appt_4 *)data;
488         char *tmstr;
489         char buf[BUFSIZ];
490
491         fprintf(stderr, "*** V4 appointement: ***\n\n");
492
493         tmstr = ctime (&appt->appt_id.tick);
494         tmstr[24] = NULL;               /* strip off CR */
495
496         if (fprintf(stderr, "(add \"%s\" ", tmstr)==EOF) {
497                 return (B_TRUE);
498         }
499         if (fprintf(stderr, "key: %ld ", appt->appt_id.key)==EOF) {
500                 return (B_TRUE);
501         }
502         if (appt->what) {
503                 tmstr = cr_to_str(appt->what, strlen(appt->what));
504                 if (fprintf(stderr, "what: \"%s\" ", tmstr) == EOF) {
505                         free(tmstr);
506                         return (1);
507                 } else
508                         free(tmstr);
509         }
510         if (appt->client_data) {
511                 if (fprintf(stderr, "details: \"%s\" ", appt->client_data)
512                     == EOF)
513                         return (B_TRUE);
514         }
515         if (appt->duration) {
516                 if (fprintf(stderr, "duration: %d ", appt->duration) == EOF)
517                         return (B_TRUE);
518         }
519
520         buf[0]=NULL;  
521         periodtostr (appt->period.period, buf);
522         if (fprintf(stderr, "period: %s ", buf) == EOF)
523                 return (B_TRUE);
524
525         if (appt->period.nth != 0) {
526                 if (fprintf (stderr, "nth: %d ", appt->period.nth) == EOF)
527                         return (B_TRUE);
528         }
529         if (appt->period.enddate != 0) {
530                 tmstr = ctime (&(appt->period.enddate));
531                 tmstr[24] = NULL; /* strip off CR */
532                 if (fprintf(stderr, "enddate: \"%s\" ", tmstr) == EOF)
533                         return (B_TRUE);
534         }
535
536         if (fprintf(stderr, "ntimes: %d ", appt->ntimes) == EOF)
537                 return (B_TRUE);
538
539         if (appt->exception != NULL) {
540                 struct Except_4 *e = appt->exception;
541                 if (fprintf(stderr, "exceptions: (") == EOF)
542                         return (B_TRUE);
543                 while(e != NULL) {
544                         if (fprintf(stderr, "%d ", e->ordinal) == EOF)
545                                 return (B_TRUE);
546                         e = e->next;
547                 }
548                 if (fprintf(stderr, ") ") == EOF)
549                         return (B_TRUE);
550         }
551         if (appt->author != NULL) {
552                 if (fprintf(stderr, "author: \"%s\" ", appt->author) == EOF)
553                         return (B_TRUE);
554         }
555         if (appt->attr != NULL) {
556                 struct Attribute_4 *item = appt->attr;
557                 if (fprintf(stderr, "attributes: (") == EOF)
558                         return (B_TRUE);
559                 while(item != NULL) {
560                         if (fprintf(stderr, "(\"%s\",\"%s\",\"%s\")",
561                             item->attr, item->value, item->clientdata) == EOF)
562                                 return (B_TRUE);
563                         item = item->next;
564                 }
565                 if (fprintf(stderr, ") ") == EOF)
566                         return (B_TRUE);
567         }
568         if (appt->tag != NULL) {
569                 struct Tag_4 *item = appt->tag;
570                 if (fprintf(stderr, "tags: (") == EOF)
571                         return (B_TRUE);
572                 while(item != NULL) {
573                         buf[0]=NULL;
574                         tagstostr(item->tag, buf);
575                         if (fprintf(stderr, "(%s , %d)", buf, item->showtime)
576                             == EOF)
577                                 return (B_TRUE);
578                         item = item->next;
579                 }
580                 if (fprintf(stderr, ") ") == EOF)
581                         return (B_TRUE);
582         }
583
584
585         buf[0]=NULL;
586         apptstatustostr(appt->appt_status, buf);
587         if (fprintf(stderr, "apptstat: %s ", buf) == EOF)
588                 return (B_TRUE);
589
590         buf[0]=NULL;
591         privacytostr(appt->privacy, buf);
592         if (fprintf(stderr, "privacy: %s )\n", buf) == EOF)
593                 return (B_TRUE);
594
595         return (B_FALSE);
596 }
597
598 extern void
599 _DtCmsPrintExceptions(int len, int *exceptions)
600 {
601         int i;
602
603         fprintf(stderr, "\nexception part:\n");
604         fprintf(stderr, "number of exception = %d\n", len);
605         fprintf(stderr, "exceptions:");
606         for (i = 0; i < len; i++) {
607                 fprintf(stderr, " %d", exceptions[i]);
608         }
609         fprintf(stderr, "\n");
610 }
611
612 extern CSA_return_code
613 _DtCmsCreateLogV2(char *owner, char *file)
614 {
615         return (create_log(owner, file, _DtCMS_VERSION4));
616 }
617
618 extern CSA_return_code
619 _DtCmsGetFileSize(char *calendar, int *size)
620 {
621         char            *log;
622         struct stat     info;
623
624         if ((log = _DtCmsGetLogFN(calendar)) == NULL)
625                 return (CSA_E_INSUFFICIENT_MEMORY);
626
627         if (stat(log, &info) != 0) {
628                 free(log);
629                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
630         } else {
631                 *size = info.st_size;
632                 free(log);
633                 return (CSA_SUCCESS);
634         }
635 }
636
637 extern void
638 _DtCmsTruncateFile(char *calendar, int size)
639 {
640         char    *log;
641         int     f;
642
643         if ((log = _DtCmsGetLogFN(calendar)) == NULL)
644                 return;
645
646         /* truncate log file to specified size */
647         if ((f = open(log, O_RDWR | O_APPEND | O_SYNC)) >= 0)
648                 ftruncate(f, size);
649
650         free(log);
651 }
652
653 extern CSA_return_code
654 _DtCmsRemoveLog(char *calendar, char *user)
655 {
656         CSA_return_code stat = CSA_SUCCESS;
657         char            *log, *dlog;
658
659         if ((log = _DtCmsGetLogFN(calendar)) == NULL)
660                 return (CSA_E_INSUFFICIENT_MEMORY);
661
662         if ((dlog = _DtCmsGetDelFN(calendar)) == NULL) {
663                 free(log);
664                 return (CSA_E_INSUFFICIENT_MEMORY);
665         }
666
667         if (rename(log, dlog) < 0)
668                 stat = CSA_X_DT_E_BACKING_STORE_PROBLEM;
669
670         free(log);
671         free(dlog);
672
673         return (stat);
674 }
675
676 extern CSA_return_code
677 _DtCmsWriteVersionString(char *file, int version)
678 {
679         struct  tm *tm;
680         time_t  tmval;
681         char    *tmstr;
682         int     fd, len;
683         char    buf[BUFSIZ];
684         CSA_return_code stat = CSA_SUCCESS;
685         _Xltimeparams   localtime_buf;
686         _Xatimeparams   asctime_buf;
687
688         tmval = time((time_t *) 0);
689         tm = _XLocaltime(&tmval, localtime_buf);
690         tmstr  = _XAsctime(tm, asctime_buf);
691         tmstr[24] = NULL;               /* strip off CR */
692
693         if ((fd = open(file, O_WRONLY|O_TRUNC|O_SYNC)) < 0) {
694                 if (debug)
695                         fprintf(stderr, "%s: failed to open %s in %s\n",
696                                 pgname, file, _DtCmsWriteVersionString);
697                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
698         }
699
700         sprintf(buf, "Version: %d\n**** start of log on %s ****\n\n",
701                 version, tmstr);
702
703         len = strlen(buf);
704         if (write(fd, buf, len) != len) {
705                 perror(pgname);
706                 stat = CSA_X_DT_E_BACKING_STORE_PROBLEM;
707         }
708         close(fd);
709
710         return (stat);
711 }
712
713 /*
714  * if everything works fine, return 0; otherwise, return -1
715  */
716 extern int
717 _DtCmsSetFileMode(
718         char *file,
719         uid_t uid,
720         gid_t gid,
721         mode_t mode,
722         boolean_t changeeuid,
723         boolean_t printerr)
724 {
725         int     error;
726         char    buff[BUFSIZ];
727
728         if (changeeuid == B_TRUE) {
729 #ifndef AIX
730 #ifdef HPUX
731                 setuid (0);
732 #else
733                 seteuid (0);
734 #endif
735 #endif
736         }
737
738         if (chmod (file, mode) < 0) {
739                 if (printerr == B_TRUE) {
740                         error = errno;
741                         sprintf (buff, "%s: chmod %s to %lo failed.\n%s: System error",
742                                 pgname, file, (long)mode, pgname);
743                         errno = error;
744                         perror (buff);
745                 }
746                 return(-1);
747         }
748
749         if (chown (file, uid, gid) < 0) {
750                 if (printerr == B_TRUE) {
751                         error = errno;
752                         sprintf (buff, "%s: chown %s to (uid=%ld,gid=%ld) failed.\n%s%s",
753                                 pgname, file, (long)uid, (long)gid, pgname, ": System error");
754                         errno = error;
755                         perror (buff);
756                 }
757                 return(-1);
758         }
759
760 #ifndef AIX
761 #ifdef HPUX
762         if (changeeuid == B_TRUE && setuid (daemon_uid) < 0)
763 #else
764         if (changeeuid == B_TRUE && seteuid (daemon_uid) < 0)
765 #endif
766         {
767                 if (printerr == B_TRUE) {
768                         error = errno;
769                         sprintf (buff, "%s: Can't switch process uid back to daemon.\n%s%s",
770                                 pgname, pgname, ": System error");
771                         errno = error;
772                         perror (buff);
773                 }
774         }
775 #endif /* AIX */
776
777         return(0);
778 }
779
780 static void
781 periodtostr(Interval_4 i, char *q)
782 {
783         if (q==NULL) return;
784         q[0]=NULL;
785         switch (i) {
786                 case single_4:
787                         strcpy (q, "single");
788                         break;
789                 case daily_4:
790                         strcpy (q, "daily");
791                         break;
792                 case weekly_4:
793                         strcpy (q, "weekly");
794                         break;
795                 case biweekly_4:
796                         strcpy (q, "biweekly");
797                         break;
798                 case monthly_4:
799                         strcpy (q, "monthly");
800                         break;
801                 case yearly_4:
802                         strcpy (q, "yearly");
803                         break;
804                 case nthWeekday_4:
805                         strcpy (q, "nthWeekday");
806                         break;
807                 case everyNthDay_4:
808                         strcpy (q, "everyNthDay");
809                         break;
810                 case everyNthWeek_4:
811                         strcpy (q, "everyNthWeek");
812                         break;
813                 case everyNthMonth_4:
814                         strcpy (q, "everyNthMonth");
815                         break;
816                 case monThruFri_4:
817                         strcpy (q, "monThruFri");
818                         break;
819                 case monWedFri_4:
820                         strcpy (q, "monWedFri");
821                         break;
822                 case tueThur_4:
823                         strcpy (q, "tueThur");
824                         break;
825                 case daysOfWeek_4:
826                         strcpy (q, "daysOfWeek");
827                         break;
828                 default:
829                         strcpy (q, "single");
830                         break;
831         }
832 }
833
834 static void
835 privacytostr(Privacy_Level_4 p, char *q)
836 {
837         if (q==NULL) return;
838         q[0]=NULL;
839         switch(p) {
840         case public_4:
841                 strcpy(q, "public");
842                 break;
843         case private_4:
844                 strcpy(q, "private");
845                 break;
846         case semiprivate_4:
847                 strcpy(q, "semiprivate");
848                 break;
849         default:
850                 strcpy(q, "public");
851                 break;
852         }
853 }
854
855 static void
856 apptstatustostr(Appt_Status_4 p, char *q)
857 {
858         if (q==NULL) return;
859         q[0]=NULL;
860         switch(p) {
861         case active_4:
862                 strcpy(q, "active");
863                 break;
864         case pendingAdd_4:
865                 strcpy(q, "pendingAdd");
866                 break;
867         case pendingDelete_4:
868                 strcpy(q, "pendingDelete");
869                 break;
870         case committed_4:
871                 strcpy(q, "committed");
872                 break;
873         case cancelled_4:
874                 strcpy(q, "cancelled");
875                 break;
876         case completed_4:
877                 strcpy(q, "completed");
878                 break;
879         default:
880                 strcpy(q, "active");
881                 break;
882         }
883 }
884
885 static void
886 tagstostr(Event_Type_4 p, char *q)
887 {
888         if (q==NULL) return;
889         q[0]=NULL;
890         switch(p) {
891         case appointment_4:
892                 strcpy(q, "appointment");
893                 break;
894         case reminder_4:
895                 strcpy(q, "reminder");
896                 break;
897         case otherTag_4:
898                 strcpy(q, "otherTag");
899                 break;
900         case holiday_4:
901                 strcpy(q, "holiday");
902                 break;
903         case toDo_4:
904                 strcpy(q, "toDo");
905                 break;
906         default:
907                 strcpy(q, "appointment");
908                 break;
909         }
910 }
911
912 static char *
913 get_fname (char *dir, char *fname, char *who)
914 {
915         char *buf;
916
917         buf = (char *)malloc(strlen(dir) + strlen(fname) + strlen(who) + 3);
918         if (buf != NULL)
919                 sprintf (buf, "%s/%s.%s", dir, fname, who);
920         return (buf);
921 }
922
923 static CSA_return_code
924 create_log(char *owner, char *file, int version)
925 {
926         uid_t   uid;
927         struct  passwd *pw;
928         int     fd;
929         char    *ptr;
930         CSA_return_code stat;
931
932         ptr = strchr(owner, '@');
933         if (ptr) *ptr = NULL;
934         pw = getpwnam (owner);
935         if (ptr) *ptr = '@';
936         if (pw == NULL)
937                 return(CSA_E_FAILURE);
938         else
939                 uid = pw->pw_uid;
940
941         /* Read by owner and Read/Write by group (gid must be daemon) */
942         fd = open(file, O_WRONLY|O_CREAT|O_EXCL, _DtCMS_DEFAULT_MODE);
943         if (fd < 0) {
944                 if (debug)
945                         fprintf(stderr, "%s: can't create %s\n", pgname, file);
946
947                 if (errno == EEXIST)
948                         return(CSA_E_CALENDAR_EXISTS);
949                 else
950                         return(CSA_X_DT_E_BACKING_STORE_PROBLEM);
951         }
952
953         if (_DtCmsSetFileMode(file, uid, daemon_gid, _DtCMS_DEFAULT_MODE,
954             B_TRUE, B_TRUE) < 0) {
955                 close(fd);
956                 unlink(file);
957                 return(CSA_X_DT_E_BACKING_STORE_PROBLEM);
958         }
959         close(fd);
960
961         if ((stat = _DtCmsWriteVersionString(file, version)) != CSA_SUCCESS) {
962                 unlink(file);
963         }
964
965         return (stat);
966 }
967
968 static CSA_return_code
969 append_log(int f, char *buf)
970 {
971         CSA_return_code status;
972         struct stat finfo;
973         int file_size = 0, nbytes_written = 0, nbytes_towrite = 0;
974
975         if (buf == NULL)
976                 return (CSA_E_INVALID_PARAMETER);
977
978         if (fstat(f, &finfo) < 0) {
979                 perror(pgname);
980                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
981         } else
982                 file_size = finfo.st_size;
983
984         nbytes_towrite = strlen(buf);
985         nbytes_written = write(f, buf, nbytes_towrite);
986         if (nbytes_written != nbytes_towrite) {
987                 if (errno == ENOSPC)
988                         status = CSA_E_DISK_FULL;
989                 else
990                         status = CSA_X_DT_E_BACKING_STORE_PROBLEM;
991
992                 perror(pgname);
993                 ftruncate(f, file_size);
994                 return (status);        
995         }
996
997         return(CSA_SUCCESS);
998 }
999
1000 static char *
1001 grow_n_concat(char *base, char *newstr, int newcount)
1002 {
1003         char *ptr;
1004
1005         if ((ptr = realloc(base, newcount)) == NULL)
1006                 return (NULL);
1007
1008         if (base)
1009                 strcat(ptr, newstr);
1010         else
1011                 strcpy(ptr, newstr);
1012
1013         return (ptr);
1014 }
1015
1016 /*
1017  * format of attributes:
1018  * CSA_VALUE_BOOLEAN:           ("name","type","number")
1019  * CSA_VALUE_ENUMERATED:        ("name","type","number")
1020  * CSA_VALUE_FLAGS:             ("name","type","number")
1021  * CSA_VALUE_SINT32:            ("name","type","number")
1022  * CSA_VALUE_UINT32:            ("name","type","number")
1023  * CSA_VALUE_STRING:            ("name","type","string")
1024  * CSA_VALUE_ACCESS_LIST:       ("name","type","user:rights [user:rights]")
1025  * CSA_VALUE_CALENDAR_USER:     ("name","type","string")
1026  * CSA_VALUE_DATE_TIME:         ("name","type","datetime")
1027  * CSA_VALUE_DATE_TIME_RANGE:   ("name","type","datetimerange")
1028  * CSA_VALUE_TIME_DURATION:     ("name","type","timeduration")
1029  * CSA_VALUE_DATE_TIME_LIST:    ("name","type","datetime [datetime]")
1030  * CSA_VALUE_REMINDER:          ("name","type","string:number:string") or
1031  *                              ("name","type","string:string:number:number:string")
1032  * CSA_VALUE_OPAQUE_DATA:       ("name","type","number:string")
1033  *
1034  * format of attributes (when only hashed number is written):
1035  * CSA_VALUE_BOOLEAN:           (hash_number "number")
1036  * CSA_VALUE_ENUMERATED:        (hash_number "number")
1037  * CSA_VALUE_FLAGS:             (hash_number "number")
1038  * CSA_VALUE_SINT32:            (hash_number "number")
1039  * CSA_VALUE_UINT32:            (hash_number "number")
1040  * CSA_VALUE_STRING:            (hash_number "string")
1041  * CSA_VALUE_ACCESS_LIST:       (hash_number "user:rights [user:rights]")
1042  * CSA_VALUE_CALENDAR_USER:     (hash_number "string")
1043  * CSA_VALUE_DATE_TIME:         (hash_number "datetime")
1044  * CSA_VALUE_DATE_TIME_RANGE:   (hash_number "datetimerange")
1045  * CSA_VALUE_TIME_DURATION:     (hash_number "timeduration")
1046  * CSA_VALUE_DATE_TIME_LIST:    (hash_number "datetime [datetime]")
1047  * CSA_VALUE_REMINDER:          (hash_number "string:number:string") or
1048  *                              (hash_number "string:string:number:number:string")
1049  * CSA_VALUE_OPAQUE_DATA:       (hash_number "number:string")
1050  *
1051  * Note: element 0 of the array is not used
1052  */
1053 static char *
1054 attrs_to_attrliststr(
1055         int             num_attr,
1056         cms_attribute   *attrs,
1057         boolean_t       write_hash,
1058         boolean_t       entryattrs)
1059 {
1060         int     i, count, tcount;
1061         char    *ptr, *buf = NULL;
1062         char    tmpbuf[BUFSIZ/2], tmpbuf2[BUFSIZ/2], *body;
1063         CSA_opaque_data *opq;
1064
1065         if ((buf = malloc(BUFSIZ+1)) == NULL) return (NULL);
1066         tcount = BUFSIZ;
1067
1068         for (i = 1, count = 0, *buf = NULL; i <= num_attr; i++) {
1069
1070                 if (attrs[i].value == NULL || (entryattrs &&
1071                     (i == CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I ||
1072                     i == CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I ||
1073                     i == CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I ||
1074                     i == CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I ||
1075                     i == CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I ||
1076                     i == CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I)))
1077                         continue;
1078
1079                 if (write_hash)
1080                         /* open_bracket hash_number open quote for value */
1081                         sprintf(tmpbuf, "(%d \"", attrs[i].name.num);
1082                 else
1083                         /* open bracket name, type, open quote for value */
1084                         sprintf(tmpbuf, "(\"%s\",\"%s\",\"", attrs[i].name.name,
1085                                 tag_string[attrs[i].value->type]);
1086
1087                 /* value string */
1088                 body = NULL;
1089                 *tmpbuf2 = NULL;
1090                 switch (attrs[i].value->type) {
1091                 case CSA_VALUE_ENUMERATED:
1092                 case CSA_VALUE_SINT32:
1093                         sprintf(tmpbuf2, "%ld",
1094                                 attrs[i].value->item.sint32_value);
1095                         break;
1096
1097                 case CSA_VALUE_BOOLEAN:
1098                 case CSA_VALUE_FLAGS:
1099                 case CSA_VALUE_UINT32:
1100                         sprintf(tmpbuf2, "%lu",
1101                                 attrs[i].value->item.uint32_value);
1102                         break;
1103
1104                 case CSA_VALUE_STRING:
1105                 case CSA_VALUE_DATE_TIME:
1106                 case CSA_VALUE_DATE_TIME_RANGE:
1107                 case CSA_VALUE_TIME_DURATION:
1108                 case CSA_VALUE_CALENDAR_USER:
1109                         if (attrs[i].value->item.string_value) {
1110                                 if ((ptr = cr_to_str(attrs[i].value->\
1111                                     item.string_value,
1112                                     strlen(attrs[i].value->item.string_value)))
1113                                     == NULL) {
1114                                         free(buf);
1115                                         return (NULL);
1116                                 }
1117                         } else
1118                                 ptr = NULL;
1119
1120                         body = ptr;
1121                         break;
1122
1123                 case CSA_VALUE_REMINDER:
1124                         opq = &attrs[i].value->item.reminder_value->\
1125                                 reminder_data;
1126                         if (attrs[i].value->item.reminder_value->repeat_count
1127                             > 1)
1128                         {
1129                             sprintf(tmpbuf2, "%s:%s:%lu:%lu:",
1130                                 attrs[i].value->item.reminder_value->lead_time,
1131                                 (attrs[i].value->item.reminder_value->snooze_time ?
1132                                 attrs[i].value->item.reminder_value->snooze_time:""),
1133                                 attrs[i].value->item.reminder_value->repeat_count,
1134                                 opq->size);
1135                         } else {
1136                             sprintf(tmpbuf2, "%s:%lu:",
1137                                 attrs[i].value->item.reminder_value->lead_time,
1138                                 opq->size);
1139                         }
1140
1141                         if (opq->size > 0) {
1142                                 if ((ptr = cr_to_str((char *)opq->data,
1143                                     opq->size)) == NULL) {
1144                                         free(buf);
1145                                         return (NULL);
1146                                 }
1147                         } else
1148                                 ptr = NULL;
1149                         body = ptr;
1150
1151                         break;
1152
1153                 case CSA_VALUE_OPAQUE_DATA:
1154                         opq = attrs[i].value->item.opaque_data_value;
1155                         sprintf(tmpbuf2, "%lu:", opq->size);
1156
1157                         if (opq->size > 0) {
1158                                 if ((ptr = cr_to_str((char *)opq->data,
1159                                     opq->size)) == NULL) {
1160                                         free(buf);
1161                                         return (NULL);
1162                                 }
1163                         } else
1164                                 ptr = NULL;
1165                         body = ptr;
1166                         break;
1167
1168                 case CSA_VALUE_ACCESS_LIST:
1169                         if (attrs[i].value->item.access_list_value) {
1170                                 if ((ptr = get_access_list_string(
1171                                     attrs[i].value->item.access_list_value))
1172                                     == NULL) {
1173                                         free(buf);
1174                                         return (NULL);
1175                                 }
1176                         } else
1177                                 ptr = NULL;
1178                         body = ptr;
1179                         break;
1180
1181                 case CSA_VALUE_DATE_TIME_LIST:
1182                         if (attrs[i].value->item.date_time_list_value) {
1183                                 if ((ptr = get_date_time_list_string(
1184                                     attrs[i].value->item.date_time_list_value))
1185                                     == NULL) {
1186                                         free(buf);
1187                                         return (NULL);
1188                                 }
1189                         } else
1190                                 ptr = NULL;
1191                         body = ptr;
1192                         break;
1193                 }
1194
1195                 count += strlen(tmpbuf) + strlen(tmpbuf2) +
1196                                 (body ? strlen(body) : 0) + 3; /* closing */
1197                 if (tcount < count) {
1198                         if ((ptr = realloc(buf, tcount+BUFSIZ)) == NULL) {
1199                                 if (body) free(body);
1200                                 free(buf);
1201                                 return NULL;
1202                         }
1203                         buf = ptr;
1204                         tcount += BUFSIZ;
1205                 }
1206                 strcat(buf, tmpbuf);
1207                 if (*tmpbuf2 != NULL) strcat(buf, tmpbuf2);
1208                 if (body) strcat(buf, body);
1209                 strcat(buf, "\")\n");
1210                 if (body) free(body);
1211         }
1212
1213         return (buf);
1214 }
1215
1216 static char *
1217 get_access_list_string(cms_access_entry *list)
1218 {
1219         char *ptr = NULL, *tptr, buf[BUFSIZ/4];
1220         int count, tcount;
1221
1222         /* do the first one */
1223         if ((ptr = malloc(BUFSIZ+1)) == NULL) return (NULL);
1224         tcount = BUFSIZ;
1225         sprintf(ptr, "%s:%u", list->user, list->rights);
1226         count = strlen(ptr);
1227
1228         while (list->next) {
1229                 list = list->next;
1230                 sprintf(buf, " %s:%u", list->user, list->rights);
1231
1232                 count += strlen(buf);
1233                 if (tcount < count) {
1234                         if ((tptr = grow_n_concat(ptr, buf, tcount+BUFSIZ))
1235                             == NULL) {
1236                                 free(ptr);
1237                                 return (NULL);
1238                         }
1239                         ptr = tptr;
1240                         tcount += BUFSIZ;
1241                 } else
1242                         strcat(ptr, buf);
1243         }
1244         return (ptr);
1245 }
1246
1247 static char *
1248 cr_to_str(char *s, int size)
1249 {
1250         int j, k;
1251         char *newstr;
1252
1253         if (s==NULL)
1254                 return(NULL);
1255
1256         if ((newstr = (char *) calloc(1, (unsigned)((2 * size) + 2))) == NULL)
1257                 return (NULL);
1258         k = 0;
1259         for (j=0; j<size; j++) {
1260                 if (s[j]=='\n') {
1261                         newstr[k] = '\\';
1262                         newstr[k+1] = 'n';
1263                         k+=2;
1264                 }
1265                 else if (s[j]=='\\') {
1266                         newstr[k] = '\\';
1267                         newstr[k+1] = '\\';
1268                         k+=2;
1269                 }
1270                 else if (s[j]=='\"') {
1271                         newstr[k] = '\\';
1272                         newstr[k+1] = '\"';
1273                         k+=2;
1274                 }
1275                 else {
1276                         newstr[k] = s[j];
1277                         k++;
1278                 }
1279         }
1280         newstr[k] = NULL;
1281         return(newstr);
1282 }
1283
1284 static char *
1285 get_date_time_list_string(CSA_date_time_list list)
1286 {
1287         char *ptr = NULL, *tptr, buf[80];
1288         int count, datestrlen, tcount;
1289
1290         /* do the first one */
1291         sprintf(buf, "%s", list->date_time);
1292         if ((ptr = strdup(buf)) == NULL)
1293                 return (NULL);
1294
1295         if ((ptr = malloc(BUFSIZ+1)) == NULL) return (NULL);
1296         tcount = BUFSIZ;
1297         strcpy(ptr, list->date_time);
1298         count = strlen(ptr);
1299
1300         datestrlen = count + 1;
1301         while (list->next) {
1302                 list = list->next;
1303                 sprintf(buf, " %s", list->date_time);
1304
1305                 count += datestrlen;
1306                 if (tcount < count) {
1307                         if ((tptr = grow_n_concat(ptr, buf, tcount+BUFSIZ))
1308                             == NULL) {
1309                                 free(ptr);
1310                                 return (NULL);
1311                         }
1312                         ptr = tptr;
1313                         tcount += BUFSIZ;
1314                 } else
1315                         strcat(ptr, buf);
1316         }
1317         return (ptr);
1318 }
1319