changeset 636:42ae383499c5

Add date -r, make -u work even when /etc/localtime set, and lots of cleanup/refactoring.
author Rob Landley <rob@landley.net>
date Sat, 21 Jul 2012 18:37:26 -0500
parents cffb9b7f1c60
children 9aeea680acc7
files toys/date.c
diffstat 1 files changed, 51 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/toys/date.c	Sat Jul 21 00:29:27 2012 -0500
+++ b/toys/date.c	Sat Jul 21 18:37:26 2012 -0500
@@ -12,77 +12,80 @@
 	bool "date"
 	default y
 	help
-          usage: date [-u] [+format] | mmddhhmm[[cc]yy]
+	  usage: date [-u] [-r file] [+format] | mmddhhmm[[cc]yy]
 
 	  Set/get the current date/time
 */
 
 #include "toys.h"
 
-/* Convert a string of decimal numbers to their integer equivalent */
-static int fromdec(const char *buf, int len)
-{
-    int result = 0;
-    while (len--) result=result * 10 + (*buf++ - '0');
-    return result;
-}
+DEFINE_GLOBALS(
+    char *file;
+)
+
+#define TT this.date
+
+#define FLAG_u 1
+#define FLAG_r 2
 
 void date_main(void)
 {
     const char *format_string = "%a %b %e %H:%M:%S %Z %Y";
+    time_t now = time(NULL);
+    struct tm tm;
 
-    /* Check if we should be displaying the date */
+    if (TT.file) {
+        struct stat st;
+
+        xstat(TT.file, &st);
+        now = st.st_mtim.tv_sec;
+    }
+    ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm);
+
+    // Display the date?
     if (!toys.optargs[0] || toys.optargs[0][0] == '+') {
-        time_t now = time(NULL);
-        struct tm *tm;
+        if (toys.optargs[0]) format_string = toys.optargs[0]+1;
+        if (!strftime(toybuf, sizeof(toybuf), format_string, &tm))
+            perror_msg("bad format `%s'", format_string);
 
-        if (toys.optargs[0]) format_string = toys.optargs[0]+1;
-        if (toys.optflags) tm = gmtime(&now);
-        else tm = localtime(&now);
-        if (!tm) perror_msg("Unable to retrieve current time");
-        if (!strftime(toybuf, sizeof(toybuf), format_string, tm))
-            perror_msg("bad format `%s'", format_string);
         puts(toybuf);
+
+    // Set the date
     } else {
-        int len = strlen(toys.optargs[0]);
-        struct tm tm;
         struct timeval tv;
+        char *s = *toys.optargs;
+        int len = strlen(s);
 
-        if (len < 8 || len > 12 || len & 1)
-            error_msg("bad date `%s'", toys.optargs[0]);
+        if (len < 8 || len > 12 || (len & 1)) error_msg("bad date `%s'", s);
+
+        // Date format: mmddhhmm[[cc]yy]
         memset(&tm, 0, sizeof(tm));
-        /* Date format: mmddhhmm[[cc]yy] */
-        tm.tm_mon = fromdec(toys.optargs[0], 2) - 1;
-        tm.tm_mday = fromdec(&toys.optargs[0][2], 2);
-        tm.tm_hour = fromdec(&toys.optargs[0][4], 2);
-        tm.tm_min = fromdec(&toys.optargs[0][6], 2);
-        if (len == 12) tm.tm_year = fromdec(&toys.optargs[0][8], 4) - 1900;
-        else if (len == 10) {
-            tm.tm_year = fromdec(&toys.optargs[0][8], 2);
+        len = sscanf(s, "%2u%2u%2u%2u", &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
+               &tm.tm_min);
+        tm.tm_mon--;
+
+        // If year specified, overwrite one we fetched earlier
+        if (len > 8) {
+            sscanf(s, "%u", &tm.tm_year);
+            if (len == 12) tm.tm_year -= 1900;
             /* 69-99 = 1969-1999, 0 - 68 = 2000-2068 */
-            if (tm.tm_year < 69) tm.tm_year += 100;
-        } else {
-            /* Year not specified, so retrieve current year */
-            time_t now = time(NULL);
-            struct tm *now_tm = localtime(&now);
-            if (!now_tm) perror_msg("Unable to retrieve current time");
-            tm.tm_year = now_tm->tm_year;
+            else if (tm.tm_year < 69) tm.tm_year += 100;
         }
-        if (!toys.optflags) tv.tv_sec = mktime(&tm);
-        else {
-            /* Get the UTC version of a struct tm */
-            char *tz = NULL;
-            tz = getenv("TZ");
-            setenv("TZ", "", 1);
+
+        if (toys.optflags & FLAG_u) {
+            // Get the UTC version of a struct tm
+            char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0;
+            setenv("TZ", "UTC", 1);
             tzset();
             tv.tv_sec = mktime(&tm);
-            if (tz) setenv("TZ", tz, 1);
-            else unsetenv("TZ");
-            tzset();
-        }
+            if (CFG_TOYBOX_FREE) {
+                if (tz) setenv("TZ", tz, 1);
+                else unsetenv("TZ");
+                tzset();
+            }
+        } else tv.tv_sec = mktime(&tm);
 
-        if (tv.tv_sec == (time_t)-1)
-            error_msg("bad `%s'", toys.optargs[0]);
+        if (tv.tv_sec == (time_t)-1) error_msg("bad `%s'", toys.optargs[0]);
         tv.tv_usec = 0;
         if (!strftime(toybuf, sizeof(toybuf), format_string, &tm))
             perror_msg("bad format `%s'", format_string);