Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtcm / server / rerule.c
1 /* $XConsortium: rerule.c /main/4 1995/11/09 12:50:23 rswiston $ */
2 /*
3  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
4  *  (c) Copyright 1993, 1994 International Business Machines Corp.
5  *  (c) Copyright 1993, 1994 Novell, Inc.
6  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
7  */
8
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <time.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "rerule.h"
15
16 typedef enum {
17         NUM_NUM         = 0,    /* Used in NumsToBuf to tell the proc what  */
18         NUM_DAY,                /* type of list we are handing it.          */
19         NUM_WEEK
20 } NumType;
21
22 static void NumsToBuf(unsigned int *, unsigned int, NumType, char *,
23                         unsigned int);
24 static void WeekNumberToString(WeekNumber, char *);
25 static void WeekDayToString(WeekDay, char *);
26 static void ConvertDaily(RepeatEvent *, char *, unsigned int);
27 static void ConvertWeekly(RepeatEvent *, char *, unsigned int);
28 static void ConvertMonthly(RepeatEvent *, char *, unsigned int);
29 static void ConvertYearly(RepeatEvent *, char *, unsigned int);
30
31 #define RE_DAILY(re) (re->re_data.re_daily)
32 #define RE_WEEKLY(re) (re->re_data.re_weekly)
33 #define RE_MONTHLY(re) (re->re_data.re_monthly)
34 #define RE_YEARLY(re) (re->re_data.re_yearly)
35
36 char *
37 ReToString(
38         RepeatEvent *re)
39 {
40         char    *cmd_buf = NULL;
41         char    *cmd_buf_tmp = NULL;
42         int      cmd_buf_size = 0;
43         int      subcommand_size = 0;
44         char     subcommand[1024];  /* XXX: fixed size */
45
46         if (!re) return (char *)NULL;
47
48         while (re) {
49                 switch (re->re_type) {
50
51                 case RT_MINUTE:
52                         sprintf(subcommand, "M%d #%d",
53                                         re->re_interval, re->re_duration);
54                         break;
55                 case RT_DAILY:
56                         ConvertDaily(re, subcommand, 1024);
57                         break;
58                 case RT_WEEKLY:
59                         ConvertWeekly(re, subcommand, 1024);
60                         break;
61                 case RT_MONTHLY_POSITION:
62                 case RT_MONTHLY_DAY:
63                         ConvertMonthly(re, subcommand, 1024);
64                         break;
65                 case RT_YEARLY_MONTH:
66                 case RT_YEARLY_DAY:
67                         ConvertYearly(re, subcommand, 1024);
68                         break;
69                 }
70
71                 cmd_buf_tmp = cmd_buf;
72
73                 if (cmd_buf) cmd_buf_size = strlen(cmd_buf);
74                 if (subcommand) subcommand_size = strlen(subcommand);
75
76                 cmd_buf = (char *)calloc(1, cmd_buf_size + subcommand_size + 2);
77
78                 if (cmd_buf_tmp)
79                         strcat (cmd_buf, cmd_buf_tmp);
80                         
81                 if (subcommand) {
82                         if (cmd_buf_tmp)
83                                 strcat (cmd_buf, " ");
84                         strcat (cmd_buf, subcommand);
85                 }
86
87                 memset (subcommand, NULL, 1024);
88
89                 re = re->re_next;
90         }
91
92         return cmd_buf;
93 }
94
95 /*
96  * Takes an array of numbers, converts them back into their string
97  * type (e.g. SU 1W etc) and puts them into a string buffer with end
98  * marks as necessary, seperated by spaces.
99  */
100 static void
101 NumsToBuf(
102         unsigned int    *array,
103         unsigned int     array_size,
104         NumType          type,
105         char            *buffer,
106         unsigned int     buf_size)
107 {
108         int      i,
109                  size = 0; 
110         char     tmp_buf[32],
111                  tmp_buf2[32];
112
113         for (i = 0; i < array_size; i++) {
114                 if (type == NUM_NUM)
115                         sprintf(tmp_buf2, " %d", RE_MASK_STOP(array[i]));
116                 else if (type == NUM_DAY)
117                         WeekDayToString(RE_MASK_STOP(array[i]), tmp_buf2);
118                 else if (type == NUM_WEEK)
119                         WeekNumberToString(RE_MASK_STOP(array[i]), tmp_buf2);
120                         
121                         /* Add end mark if needed */
122                 if (RE_STOP_IS_SET(array[i])) {
123                         sprintf(tmp_buf, "%s$", tmp_buf2);
124                         strcat (buffer, tmp_buf);
125                         size += strlen(tmp_buf);
126                 } else {
127                         strcat (buffer, tmp_buf2);
128                         size += strlen(tmp_buf2);
129                 }
130
131                         /* Make sure the size of our buffer does not overflow */
132                 if (size > buf_size) {
133                         printf ("Error: Internal buffer size exceeded\n");
134                         return;
135                 }
136         }
137 }
138
139 static void
140 WeekDayToString(
141         WeekDay          day,
142         char            *buffer)
143 {
144         switch (RE_MASK_STOP(day)) {
145         case WD_SUN:
146                 sprintf (buffer, " SU");
147                 break;
148         case WD_MON:
149                 sprintf (buffer, " MO");
150                 break;
151         case WD_TUE:
152                 sprintf (buffer, " TU");
153                 break;
154         case WD_WED:
155                 sprintf (buffer, " WE");
156                 break;
157         case WD_THU:
158                 sprintf (buffer, " TH");
159                 break;
160         case WD_FRI:
161                 sprintf (buffer, " FR");
162                 break;
163         case WD_SAT:
164                 sprintf (buffer, " SA");
165                 break;
166         }
167
168         if (RE_STOP_IS_SET(day))
169                 strcat (buffer, "$");
170 }
171
172 static void
173 WeekNumberToString(
174         WeekNumber       week,
175         char            *buffer)
176 {
177         switch (RE_MASK_STOP(week)) {
178         case WK_F1:
179                 sprintf (buffer, " 1+");
180                 break;
181         case WK_F2:
182                 sprintf (buffer, " 2+");
183                 break;
184         case WK_F3:
185                 sprintf (buffer, " 3+");
186                 break;
187         case WK_F4:
188                 sprintf (buffer, " 4+");
189                 break;
190         case WK_F5:
191                 sprintf (buffer, " 5+");
192                 break;
193         case WK_L1:
194                 sprintf (buffer, " 1-");
195                 break;
196         case WK_L2:
197                 sprintf (buffer, " 2-");
198                 break;
199         case WK_L3:
200                 sprintf (buffer, " 3-");
201                 break;
202         case WK_L4:
203                 sprintf (buffer, " 4-");
204                 break;
205         case WK_L5:
206                 sprintf (buffer, " 5-");
207                 break;
208         }
209
210         if (RE_STOP_IS_SET(week))
211                 strcat (buffer, "$");
212 }
213
214 static void
215 ConvertDaily(
216         RepeatEvent     *re,
217         char            *subcommand,
218         unsigned int     buf_size)
219 {
220         char            tmp_buf[32];
221         unsigned int    size = 0,
222                         num_time,
223                         i;
224
225         num_time = RE_DAILY(re)->dd_ntime;
226
227         sprintf(subcommand, "D%d", re->re_interval);
228         size += strlen(subcommand);
229
230         NumsToBuf((unsigned int *)RE_DAILY(re)->dd_time, num_time, NUM_NUM,
231                   subcommand, buf_size - size);
232
233                 /* Tack on the duration information */
234         sprintf(tmp_buf, " #%d", re->re_duration);
235
236         size += strlen(tmp_buf);
237         if (size > buf_size) {
238                 printf ("Error: Internal buffer size exceeded\n");
239                 return;
240         }
241         strcat (subcommand, tmp_buf);
242 }
243
244 static void
245 ConvertWeekly(
246         RepeatEvent     *re,
247         char            *subcommand,
248         unsigned int     subcommand_size)
249 {
250         char     tmp_buf[32];
251         int      size = 0,
252                  num_items,
253                  i;
254
255         num_items = RE_WEEKLY(re)->wd_ndaytime;
256
257         sprintf(subcommand, "W%d", re->re_interval);
258         size += strlen(subcommand);
259
260                 /* walk through Day/time data (e.g. TU 1200 Th 2000)    */
261         for (i = 0; i < num_items; i++) {
262
263                         /* The day: MO TU TH etc. */
264                 WeekDayToString(RE_WEEKLY(re)->wd_daytime[i].dt_day, tmp_buf);
265                 size += strlen(tmp_buf);
266
267                         /* Make sure the size of our buffer does not overflow */
268                 if (size > subcommand_size) {
269                         printf ("Error: Internal buffer size exceeded\n");
270                         return;
271                 }
272
273                 strcat (subcommand, tmp_buf);
274
275                         /* The hours: 1000 1400 etc. */
276                 NumsToBuf((unsigned int *)RE_WEEKLY(re)->wd_daytime[i].dt_time,
277                           RE_WEEKLY(re)->wd_daytime[i].dt_ntime, NUM_NUM,
278                           subcommand, subcommand_size - size);
279
280                 size = strlen(subcommand);
281         }
282                 /* Tack on the duration information */
283         sprintf(tmp_buf, " #%d", re->re_duration);
284
285         size += strlen(tmp_buf);
286         if (size > subcommand_size) {
287                 printf ("Error: Internal buffer size exceeded\n");
288                 return;
289         }
290         strcat (subcommand, tmp_buf);
291 }
292
293 static void
294 ConvertMonthly(
295         RepeatEvent     *re,
296         char            *subcommand,
297         unsigned int     subcommand_size)
298 {
299         char     tmp_buf[32];
300         int      size = 0,
301                  num_items,
302                  i;
303
304         num_items = RE_MONTHLY(re)->md_nitems;
305
306         if (re->re_type == RT_MONTHLY_POSITION)
307                 sprintf(subcommand, "MP%d", re->re_interval);
308         else
309                 sprintf(subcommand, "MD%d", re->re_interval);
310
311         size += strlen(subcommand);
312
313         if (re->re_type == RT_MONTHLY_POSITION) {
314
315                 /* walk through Day/time data (e.g. TU 1200 Th 2000)    */
316             for (i = 0; i < num_items; i++) {
317
318                         /* The week: 1+ 3- etc. */
319                 NumsToBuf(
320                          (unsigned int*)RE_MONTHLY(re)->md_weektime[i].wdt_week,
321                           RE_MONTHLY(re)->md_weektime[i].wdt_nweek, NUM_WEEK,
322                           subcommand, subcommand_size - size);
323
324                 size = strlen(subcommand);
325
326                         /* Make sure the size of our buffer does not overflow */
327                 if (size > subcommand_size) {
328                         printf ("Error: Internal buffer size exceeded\n");
329                         return;
330                 }
331
332                         /* The day: SU MO TU etc. */
333                 NumsToBuf(
334                          (unsigned int *)RE_MONTHLY(re)->md_weektime[i].wdt_day,
335                           RE_MONTHLY(re)->md_weektime[i].wdt_nday, NUM_DAY,
336                           subcommand, subcommand_size - size);
337
338                 size = strlen(subcommand);
339
340                         /* Make sure the size of our buffer does not overflow */
341                 if (size > subcommand_size) {
342                         printf ("Error: Internal buffer size exceeded\n");
343                         return;
344                 }
345
346                         /* The hours: 1000 1400 etc. */
347                 NumsToBuf(
348                          (unsigned int *)
349                                 RE_MONTHLY(re)->md_weektime[i].wdt_time,
350                           RE_MONTHLY(re)->md_weektime[i].wdt_ntime, NUM_NUM,
351                           subcommand, subcommand_size - size);
352
353                 size = strlen(subcommand);
354             }
355         } else {  /* RT_MONTHLY_DAY */
356                         /* The days: 1 15 31 etc. */
357                 NumsToBuf((unsigned int *)RE_MONTHLY(re)->md_days,
358                           num_items, NUM_NUM, subcommand,
359                           subcommand_size - size);
360         }
361                 /* Tack on the duration information */
362         sprintf(tmp_buf, " #%d", re->re_duration);
363
364         size += strlen(tmp_buf);
365         if (size > subcommand_size) {
366                 printf ("Error: Internal buffer size exceeded\n");
367                 return;
368         }
369         strcat (subcommand, tmp_buf);
370 }
371
372 static void
373 ConvertYearly(
374         RepeatEvent     *re,
375         char            *subcommand,
376         unsigned int     subcommand_size)
377 {
378         char     tmp_buf[32];
379         int      size = 0,
380                  num_items,
381                  i;
382
383         num_items = RE_YEARLY(re)->yd_nitems;
384
385         if (re->re_type == RT_YEARLY_MONTH)
386                 sprintf(subcommand, "YM%d", re->re_interval);
387         else
388                 sprintf(subcommand, "YD%d", re->re_interval);
389
390         size += strlen(subcommand);
391
392                 /* An array of days or months */
393         NumsToBuf(RE_YEARLY(re)->yd_items,
394                   RE_YEARLY(re)->yd_nitems, NUM_NUM,
395                   subcommand, subcommand_size - size);
396
397                 /* Tack on the duration information */
398         sprintf(tmp_buf, " #%d", re->re_duration);
399
400         size += strlen(tmp_buf);
401         if (size > subcommand_size) {
402                 printf ("Error: Internal buffer size exceeded\n");
403                 return;
404         }
405         strcat (subcommand, tmp_buf);
406 }