ktime: Don't leak token list
[openafs.git] / src / util / ktime.c
index eba0260..b331b19 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
+#include <afs/opr.h>
 
-#include <sys/types.h>
-#include <stdio.h>
-#include <time.h>
 #include <ctype.h>
-#ifdef AFS_NT40_ENV
-#include <malloc.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-#include <stdlib.h>
-#include "afsutil.h"
 
+#include <afs/opr.h>
+#include "afsutil.h"
 #include "ktime.h"
 
 /* some date parsing routines */
@@ -50,20 +37,17 @@ static char *day[] = {
 };
 
 /* free token list returned by parseLine */
-#ifdef undef
-static
-LocalFreeTokens(alist)
-     register struct token *alist;
+static void
+LocalFreeTokens(struct token *alist)
 {
-    register struct token *nlist;
+    struct token *nlist;
     for (; alist; alist = nlist) {
        nlist = alist->next;
        free(alist->key);
        free(alist);
     }
-    return 0;
+    return;
 }
-#endif
 
 static int
 space(int x)
@@ -78,11 +62,11 @@ static int
 LocalParseLine(char *aline, struct token **alist)
 {
     char tbuffer[256];
-    register char *tptr = NULL;
+    char *tptr = NULL;
     int inToken;
     struct token *first, *last;
-    register struct token *ttok;
-    register int tc;
+    struct token *ttok;
+    int tc;
 
     inToken = 0;               /* not copying token chars at start */
     first = NULL;
@@ -93,9 +77,9 @@ LocalParseLine(char *aline, struct token **alist)
            if (inToken) {
                inToken = 0;    /* end of this token */
                *tptr++ = 0;
-               ttok = (struct token *)malloc(sizeof(struct token));
+               ttok = malloc(sizeof(struct token));
                ttok->next = NULL;
-               ttok->key = (char *)malloc(strlen(tbuffer) + 1);
+               ttok->key = malloc(strlen(tbuffer) + 1);
                strcpy(ttok->key, tbuffer);
                if (last) {
                    last->next = ttok;
@@ -164,8 +148,9 @@ char *
 ktime_DateOf(afs_int32 atime)
 {
     static char tbuffer[30];
-    register char *tp;
-    tp = ctime((time_t *) & atime);
+    char *tp;
+    time_t t = atime;
+    tp = ctime(&t);
     if (tp) {
        strcpy(tbuffer, tp);
        tbuffer[24] = 0;        /* get rid of new line */
@@ -185,12 +170,12 @@ ktime_DateOf(afs_int32 atime)
  */
 
 static int
-ParseTime(register struct ktime *ak, register char *astr)
+ParseTime(struct ktime *ak, char *astr)
 {
     int field;
     afs_int32 temp;
-    register char *tp;
-    register int tc;
+    char *tp;
+    int tc;
 
     field = 0;                 /* 0=hour, 1=min, 2=sec */
     temp = 0;
@@ -224,7 +209,7 @@ ParseTime(register struct ktime *ak, register char *astr)
 }
 
 afs_int32
-ktime_Str2int32(register char *astr)
+ktime_Str2int32(char *astr)
 {
     struct ktime tk;
 
@@ -249,10 +234,10 @@ ktime_Str2int32(register char *astr)
 
 /* -1 means error, 0 means now, otherwise returns time of next event */
 int
-ktime_ParsePeriodic(char *adate, register struct ktime *ak)
+ktime_ParsePeriodic(char *adate, struct ktime *ak)
 {
     struct token *tt;
-    register afs_int32 code;
+    afs_int32 code;
     struct ptemp *tp;
 
     memset(ak, 0, sizeof(*ak));
@@ -263,11 +248,11 @@ ktime_ParsePeriodic(char *adate, register struct ktime *ak)
        /* look at each token */
        if (strcmp(tt->key, "now") == 0) {
            ak->mask |= KTIME_NOW;
-           return 0;
+           goto out;
        }
        if (strcmp(tt->key, "never") == 0) {
            ak->mask |= KTIME_NEVER;
-           return 0;
+           goto out;
        }
        if (strcmp(tt->key, "at") == 0)
            continue;
@@ -276,14 +261,17 @@ ktime_ParsePeriodic(char *adate, register struct ktime *ak)
        if (isdigit(tt->key[0])) {
            /* parse a time */
            code = ParseTime(ak, tt->key);
-           if (code)
-               return -1;
+           if (code) {
+               code = -1;
+               goto out;
+           }
            continue;
        }
        /* otherwise use keyword table */
        for (tp = ptkeys;; tp++) {
            if (tp->key == NULL) {
-               return -1;
+               code = -1;
+               goto out;
            }
            if (strcmp(tp->key, tt->key) == 0)
                break;
@@ -298,23 +286,31 @@ ktime_ParsePeriodic(char *adate, register struct ktime *ak)
            /* am or pm token */
            if ((tp->value & 0xff) == 1) {
                /* pm */
-               if (!(ak->mask & KTIME_HOUR))
-                   return -1;
-               if (ak->hour < 12)
+               if (!(ak->mask & KTIME_HOUR)) {
+                   code = -1;
+                   goto out;
+               }
+               if (ak->hour < 12) {
                    ak->hour += 12;
                /* 12 is 12 PM */
-               else if (ak->hour != 12)
-                   return -1;
+               } else if (ak->hour != 12) {
+                   code = -1;
+                   goto out;
+               }
            } else {
                /* am is almost a noop, except that we map 12:01 am to 0:01 */
-               if (ak->hour > 12)
-                   return -1;
+               if (ak->hour > 12) {
+                   code = -1;
+                   goto out;
+               }
                if (ak->hour == 12)
                    ak->hour = 0;
            }
        }
     }
-    return 0;
+out:
+    LocalFreeTokens(tt);
+    return code;
 }
 
 /* ktime_DisplayString
@@ -326,7 +322,7 @@ ktime_ParsePeriodic(char *adate, register struct ktime *ak)
  *     0 - astring contains ktime string.
  */
 int
-ktime_DisplayString(struct ktime *aparm, register char *astring)
+ktime_DisplayString(struct ktime *aparm, char *astring)
 {
     char tempString[50];
 
@@ -390,8 +386,8 @@ ktime_next(struct ktime * aktime, afs_int32 afrom)
     if (tmask & KTIME_NOW)
        return 0;
 
-    /* Use probe to fill in members of *tsp. Add 23 hours each iteration until 
-     * time_next is correct. Only add 23 hrs to avoid skipping spring 
+    /* Use probe to fill in members of *tsp. Add 23 hours each iteration until
+     * time_next is correct. Only add 23 hrs to avoid skipping spring
      * daylight savings time day */
     for (probe = start;; probe += (23 * 3600)) {
        tsp = localtime(&probe);        /* find out what UTC time "probe" is */
@@ -421,9 +417,9 @@ ktime_next(struct ktime * aktime, afs_int32 afrom)
 /* compare date in both formats, and return as in strcmp */
 #ifdef undef
 static int
-KTimeCmp(register struct ktime *aktime, register struct tm *atm)
+KTimeCmp(struct ktime *aktime, struct tm *atm)
 {
-    register afs_int32 tmask;
+    afs_int32 tmask;
 
     /* don't compare day of the week, since we can't tell the
      * order in a cyclical set.  Caller must check for equality, if
@@ -453,7 +449,7 @@ KTimeCmp(register struct ktime *aktime, register struct tm *atm)
 
 /* compare date in both formats, and return as in strcmp */
 static int
-KDateCmp(register struct ktime_date *akdate, register struct tm *atm)
+KDateCmp(struct ktime_date *akdate, struct tm *atm)
 {
     if (akdate->year > atm->tm_year)
        return 1;
@@ -516,6 +512,7 @@ ktime_ParseDate(char *adate, struct ktime_date *akdate)
     if (akdate->mask)
        return 0;
 
+    /* Old ambiguous mm/dd/yy hh:mm:ss format */
 
     code =
        sscanf(adate, "%d / %d / %d %d : %d : %d%1s", &month, &day2, &year,
@@ -527,13 +524,28 @@ ktime_ParseDate(char *adate, struct ktime_date *akdate)
                   &hour, &min, &c[0]);
        if (code != 5) {
            hour = min = 0;
-           code = sscanf(adate, "%d / %d / %d%1s", &month, &day2, &year, &c[0]);
+           code =
+               sscanf(adate, "%d / %d / %d%1s", &month, &day2, &year, &c[0]);
            if (code != 3) {
-               return -1;
+               code = -1;
            }
        }
     }
 
+    /* New ISO 8601 (subset) format */
+
+    if (code < 0) {
+       hour = min = sec = 0;
+       code =
+           sscanf(adate, "%d-%d-%d %d:%d:%d%1s", &year, &month, &day2,
+                  &hour, &min, &sec, c);
+       if (code != 3 && code != 5 && code != 6)
+           code = -1;
+    }
+
+    if (code < 0)
+       return code;
+
     if ((year < 0) || (month < 1) || (month > 12) || (day2 < 1) || (day2 > 31) ||      /* more or less */
        (hour < 0) || (hour > 23) || (min < 0) || (min > 59) || (sec < 0)
        || (sec > 59))
@@ -574,23 +586,28 @@ afs_int32
 ktime_DateToInt32(char *adate, afs_int32 * aint32)
 {
     struct ktime_date tdate;
-    register afs_int32 code;
+    afs_int32 code;
+    unsigned long l;
+    char c[2];
 
-    /* parse the date into a ktime_date structure */
-    code = ktime_ParseDate(adate, &tdate);
-    if (code)
-       return code;            /* failed to parse */
+    if (sscanf(adate, "%lu%1s", &l, c) == 1 && l > 200000000)
+       *aint32 = l;
+    else {
+       /* parse the date into a ktime_date structure */
+       code = ktime_ParseDate(adate, &tdate);
+       if (code)
+           return code;                /* failed to parse */
+       *aint32 = ktime_InterpretDate(&tdate);  /* interpret as seconds since 1970 */
+    }
 
-    code = ktime_InterpretDate(&tdate);        /* interpret as seconds since 1970 */
-    *aint32 = code;            /* return it */
-    return 0;                  /* and declare no errors */
+    return 0;
 }
 
 /* get useful error message to print about date input format */
 char *
 ktime_GetDateUsage(void)
 {
-    return "date format is 'mm/dd/yy [hh:mm]', using a 24 hour clock";
+    return "date format is '(yyyy-mm-dd | mm/dd/yy) [hh:mm]', using a 24 hour clock";
 }
 
 
@@ -606,10 +623,10 @@ ktime_GetDateUsage(void)
 afs_int32
 ktime_InterpretDate(struct ktime_date * akdate)
 {
-    register afs_uint32 tresult;
-    register afs_uint32 tbit;
+    afs_uint32 tresult;
+    afs_uint32 tbit;
     time_t temp;
-    register struct tm *tsp;
+    struct tm *tsp;
 
     if (akdate->mask & KTIMEDATE_NOW)
        return time(0);