replaced time_value with rrd_time_value as MacOS X introduced a struct of that name...
[rrdtool.git] / src / rrd_cgi.c
index 0c4f6de..b49f5f5 100644 (file)
@@ -56,6 +56,9 @@ char* includefile(long, char **);
 /* for how long is the output of the cgi valid ? */
 char* rrdgoodfor(long, char **);
 
+/* format at-time specified times using strftime */
+char* printstrftime(long, char**);
+
 /** http protocol needs special format, and GMT time **/
 char *http_time(time_t *);
 
@@ -128,9 +131,9 @@ int main(int argc, char *argv[]) {
       server_url = getenv("SERVER_URL");
   }
 
-  if (optind != argc-1) { 
-     fprintf(stderr, "ERROR: expected a filename\n");
-     exit(1);
+  if ( (optind != argc-2 && strstr(getenv("SERVER_SOFTWARE"),"Apache/2") != NULL) && optind != argc-1) {
+    fprintf(stderr, "ERROR: expected a filename\n");
+    exit(1);
   } else {
      length  = readfile(argv[optind], &buffer, 1);
   }
@@ -158,6 +161,7 @@ int main(int argc, char *argv[]) {
       i += parse(&buffer,i,"<RRD::INCLUDE",includefile);
       i += parse(&buffer,i,"<RRD::TIME::LAST",printtimelast);
       i += parse(&buffer,i,"<RRD::TIME::NOW",printtimenow);
+      i += parse(&buffer,i,"<RRD::TIME::STRFTIME",printstrftime);
   }
 
   /* pass 3 */
@@ -234,6 +238,62 @@ char* rrdgoodfor(long argc, char **args){
   return stralloc("");
 }
 
+/* Format start or end times using strftime.  We always need both the
+ * start and end times, because, either might be relative to the other.
+ * */
+#define MAX_STRFTIME_SIZE 256
+char* printstrftime(long argc, char **args){
+       struct  rrd_time_value start_tv, end_tv;
+       char    *parsetime_error = NULL;
+       char    formatted[MAX_STRFTIME_SIZE];
+       struct tm *the_tm;
+       time_t  start_tmp, end_tmp;
+
+       /* Make sure that we were given the right number of args */
+       if( argc != 4) {
+               rrd_set_error( "wrong number of args %d", argc);
+               return (char *) -1;
+       }
+
+       /* Init start and end time */
+       parsetime("end-24h", &start_tv);
+       parsetime("now", &end_tv);
+
+       /* Parse the start and end times we were given */
+       if( (parsetime_error = parsetime( args[1], &start_tv))) {
+               rrd_set_error( "start time: %s", parsetime_error);
+               return (char *) -1;
+       }
+       if( (parsetime_error = parsetime( args[2], &end_tv))) {
+               rrd_set_error( "end time: %s", parsetime_error);
+               return (char *) -1;
+       }
+       if( proc_start_end( &start_tv, &end_tv, &start_tmp, &end_tmp) == -1) {
+               return (char *) -1;
+       }
+
+       /* Do we do the start or end */
+       if( strcasecmp( args[0], "START") == 0) {
+               the_tm = localtime( &start_tmp);
+       }
+       else if( strcasecmp( args[0], "END") == 0) {
+               the_tm = localtime( &end_tmp);
+       }
+       else {
+               rrd_set_error( "start/end not found in '%s'", args[0]);
+               return (char *) -1;
+       }
+
+       /* now format it */
+       if( strftime( formatted, MAX_STRFTIME_SIZE, args[3], the_tm)) {
+               return( stralloc( formatted));
+       }
+       else {
+               rrd_set_error( "strftime failed");
+               return (char *) -1;
+       }
+}
+
 char* includefile(long argc, char **args){
   char *buffer;
   if (argc >= 1) {
@@ -253,6 +313,7 @@ char* includefile(long argc, char **args){
   }
 }
 
+static
 char* rrdstrip(char *buf){
   char *start;
   if (buf == NULL) return NULL;
@@ -412,7 +473,7 @@ char* printtimelast(long argc, char **args) {
       rrd_clear_error();
       return err;
     }
-    tm_last = *localtime(&last);
+    localtime_r(&last, &tm_last);
     strftime(buf,254,args[1],&tm_last);
     return buf;
   }
@@ -431,7 +492,7 @@ char* printtimenow(long argc, char **args) {
     if (buf == NULL){  
        return stralloc("[ERROR: allocating strftime buffer]");
     };
-    tm_now = *localtime(&now);
+    localtime_r(&now, &tm_now);
     strftime(buf,254,args[0],&tm_now);
     return buf;
   }
@@ -442,6 +503,7 @@ char* printtimenow(long argc, char **args) {
 }
 
 /* scan aLine until an unescaped '>' arives */
+static
 char* scanargs(char *aLine, long *argc, char ***args)
 {
   char        *getP, *putP;
@@ -459,7 +521,7 @@ char* scanargs(char *aLine, long *argc, char ***args)
   getP = aLine;
   putP = aLine;
   while (*getP && !( !Quote  && (braket == 0) && ((*getP) == '>'))){
-    if (*getP < ' ') *getP = ' '; /*remove all special chars*/
+    if ((unsigned)*getP < ' ') *getP = ' '; /*remove all special chars*/
     switch (*getP) {
     case ' ': 
       if (Quote){
@@ -576,10 +638,10 @@ int parse(char **buf, long i, char *tag,
 
 char *
 http_time(time_t *now) {
-        struct tm *tmptime;
+        struct tm tmptime;
         static char buf[60];
 
-        tmptime=gmtime(now);
-        strftime(buf,sizeof(buf),"%a, %d %b %Y %H:%M:%S GMT",tmptime);
+        gmtime_r(now, &tmptime);
+        strftime(buf,sizeof(buf),"%a, %d %b %Y %H:%M:%S GMT", &tmptime);
         return(buf);
 }