]> diplodocus.org Git - nmh/blobdiff - uip/mhical.c
lock_file.c: close(2) file descriptor on failure, avoiding leak.
[nmh] / uip / mhical.c
index eb26c388412ccfeb6752416fe191d6fac9792b3c..d62fce95d7049b4e37f17611cd913cdb46e28370 100644 (file)
@@ -1,5 +1,4 @@
-/*
- * mhical.c -- operate on an iCalendar request
+/* mhical.c -- operate on an iCalendar request
  *
  * This code is Copyright (c) 2014, by the authors of nmh.
  * See the COPYRIGHT file in the root directory of the nmh
@@ -30,7 +29,7 @@ static void convert_common (contentline *, act);
 static void dump_unfolded (FILE *, contentline *);
 static void output (FILE *, contentline *, int);
 static void display (FILE *, contentline *, char *);
-static const char *identity (const contentline *);
+static const char *identity (const contentline *) PURE;
 static char *format_params (char *, param_list *);
 static char *fold (char *, int);
 
@@ -57,6 +56,7 @@ DEFINE_SWITCH_ARRAY(MHICAL, switches);
 #undef X
 
 vevent vevents = { NULL, NULL, NULL};
+int parser_status = 0;
 
 int
 main (int argc, char *argv[]) {
@@ -76,7 +76,7 @@ main (int argc, char *argv[]) {
 
     icaldebug = 0;  /* Global provided by bison (with name-prefix "ical"). */
 
-    if (nmh_init(argv[0], 1)) { return 1; }
+    if (nmh_init(argv[0], 2)) { return 1; }
 
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
@@ -140,12 +140,12 @@ main (int argc, char *argv[]) {
             case INFILESW:
                 if (! (cp = *argp++) || (*cp == '-' && cp[1]))
                     adios (NULL, "missing argument to %s", argp[-2]);
-                infile = *cp == '-'  ?  add (cp, NULL)  :  path (cp, TFILE);
+                infile = *cp == '-'  ?  mh_xstrdup(cp)  :  path (cp, TFILE);
                 continue;
             case OUTFILESW:
                 if (! (cp = *argp++) || (*cp == '-' && cp[1]))
                     adios (NULL, "missing argument to %s", argp[-2]);
-                outfile = *cp == '-'  ?  add (cp, NULL)  :  path (cp, TFILE);
+                outfile = *cp == '-'  ?  mh_xstrdup(cp)  :  path (cp, TFILE);
                 continue;
 
             case CONTENTTYPESW:
@@ -237,7 +237,7 @@ main (int argc, char *argv[]) {
         free (outfile);
     }
 
-    return 0;
+    return parser_status;
 }
 
 /*
@@ -332,10 +332,10 @@ convert_to_reply (contentline *clines, act action) {
             (node = find_contentline (clines, "BEGIN", "VEVENT"))) {
             contentline *new_node = add_contentline (node, "ATTENDEE");
 
-            add_param_name (new_node, strdup ("PARTSTAT"));
-            add_param_value (new_node, strdup (partstat));
-            add_param_name (new_node, strdup ("CN"));
-            add_param_value (new_node, strdup (getfullname ()));
+            add_param_name (new_node, mh_xstrdup ("PARTSTAT"));
+            add_param_value (new_node, mh_xstrdup (partstat));
+            add_param_name (new_node, mh_xstrdup ("CN"));
+            add_param_value (new_node, mh_xstrdup (getfullname ()));
             new_node->value = concat ("MAILTO:", getlocalmbox (), NULL);
         }
     }
@@ -369,7 +369,7 @@ convert_to_cancellation (contentline *clines) {
     if ((node = find_contentline (clines, "STATUS", 0))  &&
         ! strcasecmp (node->value, "CONFIRMED")) {
         free (node->value);
-        node->value = strdup ("CANCELLED");
+        node->value = mh_xstrdup ("CANCELLED");
     }
 
     if ((node = find_contentline (clines, "SEQUENCE", 0))) {
@@ -378,7 +378,7 @@ convert_to_cancellation (contentline *clines) {
 
         (void) snprintf (buf, sizeof buf, "%d", sequence + 1);
         free (node->value);
-        node->value = strdup (buf);
+        node->value = mh_xstrdup (buf);
     }
 }
 
@@ -389,24 +389,25 @@ convert_common (contentline *clines, act action) {
 
     if ((node = find_contentline (clines, "METHOD", 0))) {
         free (node->value);
-        node->value = strdup (action == ACT_CANCEL  ?  "CANCEL"  :  "REPLY");
+        node->value = mh_xstrdup (action == ACT_CANCEL  ?  "CANCEL"  :  "REPLY");
     }
 
     if ((node = find_contentline (clines, "PRODID", 0))) {
         free (node->value);
-        node->value = strdup ("nmh mhical v0.1");
+        node->value = mh_xstrdup ("nmh mhical v0.1");
     }
 
     if ((node = find_contentline (clines, "VERSION", 0))) {
         if (! node->value) {
-            admonish (NULL, "Version property is missing value, assume 2.0");
-            node->value = strdup ("2.0");
+            inform("Version property is missing value, assume 2.0, continuing...");
+            node->value = mh_xstrdup ("2.0");
         }
 
         if (strcmp (node->value, "2.0")) {
-            admonish (NULL, "supports the Version 2.0 specified by RFC 5545 "
-                            "but iCalendar object has Version %s", node->value);
-            node->value = strdup ("2.0");
+            inform("supports the Version 2.0 specified by RFC 5545 "
+               "but iCalendar object has Version %s, continuing...",
+               node->value);
+            node->value = mh_xstrdup ("2.0");
         }
     }
 
@@ -458,12 +459,12 @@ convert_common (contentline *clines, act action) {
 
             if (strftime (buf, sizeof buf, "%Y%m%dT%H%M%SZ", &now_tm)) {
                 free (node->value);
-                node->value = strdup (buf);
+                node->value = mh_xstrdup (buf);
             } else {
-                admonish (NULL, "strftime unable to format current time");
+                inform("strftime unable to format current time, continuing...");
             }
         } else {
-            admonish (NULL, "gmtime_r failed on current time");
+            inform("gmtime_r failed on current time, continuing...");
         }
     }
 
@@ -523,7 +524,7 @@ output (FILE *file, contentline *clines, int contenttype) {
             char *line = NULL;
             size_t len;
 
-            line = strdup (node->name);
+            line = mh_xstrdup (node->name);
             line = format_params (line, node->params);
 
             len = strlen (line);
@@ -534,11 +535,10 @@ output (FILE *file, contentline *clines, int contenttype) {
             line = fold (add (node->value, line),
                          clines->cr_before_lf == CR_BEFORE_LF);
 
-            if (clines->cr_before_lf == LF_ONLY) {
-                fprintf (file, "%s\n", line);
-            } else {
-                fprintf (file, "%s\r\n", line);
-            }
+            fputs(line, file);
+            if (clines->cr_before_lf != LF_ONLY)
+                putc('\r', file);
+            putc('\n', file);
             free (line);
         }
     }
@@ -576,20 +576,20 @@ display (FILE *file, contentline *clines, char *nfs) {
 
     if ((c = fmt_findcomp ("method"))) {
         if ((node = find_contentline (clines, "METHOD", 0))  &&  node->value) {
-            c->c_text = strdup (node->value);
+            c->c_text = mh_xstrdup (node->value);
         }
     }
 
     if ((c = fmt_findcomp ("organizer"))) {
         if ((node = find_contentline (clines, "ORGANIZER", 0))  &&
             node->value) {
-            c->c_text = strdup (identity (node));
+            c->c_text = mh_xstrdup (identity (node));
         }
     }
 
     if ((c = fmt_findcomp ("summary"))) {
         if ((node = find_contentline (clines, "SUMMARY", 0))  &&  node->value) {
-            c->c_text = strdup (node->value);
+            c->c_text = mh_xstrdup (node->value);
         }
     }
 
@@ -601,7 +601,7 @@ display (FILE *file, contentline *clines, char *nfs) {
             if (node->name  &&  node->value  &&  ! in_valarm  &&
                 ! strcasecmp ("DESCRIPTION", node->name)  &&
                 strcasecmp (node->value, "\\n\\n")) {
-                c->c_text = strdup (node->value);
+                c->c_text = mh_xstrdup (node->value);
             } else if (in_valarm) {
                 if (! strcasecmp ("END", node->name)  &&
                     ! strcasecmp ("VALARM", node->value)) {
@@ -619,7 +619,7 @@ display (FILE *file, contentline *clines, char *nfs) {
     if ((c = fmt_findcomp ("location"))) {
         if ((node = find_contentline (clines, "LOCATION", 0))  &&
             node->value) {
-            c->c_text = strdup (node->value);
+            c->c_text = mh_xstrdup (node->value);
         }
     }
 
@@ -642,7 +642,7 @@ display (FILE *file, contentline *clines, char *nfs) {
                 } else if (! strcasecmp ("DTSTART", node->name)) {
                     /* Got it:  DTSTART outside of a VTIMEZONE section. */
                     char *datetime = format_datetime (timezones, node);
-                    c->c_text = datetime ? datetime : node->value;
+                    c->c_text = datetime ? datetime : mh_xstrdup(node->value);
                 }
             }
         }
@@ -651,7 +651,26 @@ display (FILE *file, contentline *clines, char *nfs) {
     if ((c = fmt_findcomp ("dtend"))) {
         if ((node = find_contentline (clines, "DTEND", 0))  &&  node->value) {
             char *datetime = format_datetime (timezones, node);
-            c->c_text = datetime ? datetime : node->value;
+            c->c_text = datetime ? datetime : strdup(node->value);
+        } else if ((node = find_contentline (clines, "DTSTART", 0))  &&
+                   node->value) {
+            /* There is no DTEND.  If there's a DTSTART, use it.  If it
+               doesn't have a time, assume that the event is for the
+               entire day and append 23:59:59 to it so that it signifies
+               the end of the day.  And assume local timezone. */
+            if (strchr(node->value, 'T')) {
+                char * datetime = format_datetime (timezones, node);
+                c->c_text = datetime ? datetime : strdup(node->value);
+            } else {
+                char *datetime;
+                contentline node_copy;
+
+                node_copy = *node;
+                node_copy.value = concat(node_copy.value, "T235959", NULL);
+                datetime = format_datetime (timezones, &node_copy);
+                c->c_text = datetime ? datetime : strdup(node_copy.value);
+                free(node_copy.value);
+            }
         }
     }
 
@@ -694,7 +713,7 @@ display (FILE *file, contentline *clines, char *nfs) {
     }
 
     /* Don't call on the END:VCALENDAR line. */
-    if (clines->next) {
+    if (clines  &&  clines->next) {
       (void) fmt_scan (fmt, buffer, INT_MAX, dat, NULL);
       fputs (charstring_buffer (buffer), file);
       fmt_free (fmt, 1);
@@ -790,7 +809,7 @@ fold (char *line, int uses_cr) {
 #endif
 
         charstring_push_back_chars (folded_line, cp, char_len, 1);
-        remaining -= char_len > 0 ? char_len : 1;
+        remaining -= max(char_len, 1);
 
         /* remaining must be > 0 to pass the loop condition above, so
            if it's not > 1, it is == 1. */
@@ -805,7 +824,7 @@ fold (char *line, int uses_cr) {
             }
         }
 
-        cp += char_len > 0 ? char_len : 1;
+        cp += max(char_len, 1);
     }
 
     free (line);