X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_cgi.c;h=a0c9b3b27d4f86d7e6f118da303024c004b6a08f;hp=844f9ac6ebe5b310db2c5253b9a1246fbe647373;hb=4e8787fdbff3ddd4044e19cf37b9e3a54b5ef0cb;hpb=82336d4b8f2f2227e733cf3078378ed87fd6e79c diff --git a/src/rrd_cgi.c b/src/rrd_cgi.c index 844f9ac..a0c9b3b 100644 --- a/src/rrd_cgi.c +++ b/src/rrd_cgi.c @@ -1,5 +1,5 @@ /***************************************************************************** - * RRDtool 1.2.99907080300 Copyright by Tobi Oetiker, 1997-2007 + * RRDtool 1.4.3 Copyright by Tobi Oetiker, 1997-2010 ***************************************************************************** * rrd_cgi.c RRD Web Page Generator *****************************************************************************/ @@ -9,6 +9,11 @@ #include #endif +#ifdef WIN32 + #define strcasecmp stricmp + #define strcasencmp strnicmp +#endif + #define MEMBLK 1024 /*#define DEBUG_PARSER #define DEBUG_VARS*/ @@ -374,6 +379,7 @@ static void calfree( if (calcpr) { free(calcpr); } + calcpr = NULL; } } @@ -381,14 +387,67 @@ static void calfree( char *stralloc( const char *str) { - char *nstr; - if (!str) { return NULL; } - nstr = malloc((strlen(str) + 1)); - strcpy(nstr, str); - return (nstr); + return strdup(str); +} + +static int readfile( + const char *file_name, + char **buffer, + int skipfirst) +{ + long writecnt = 0, totalcnt = MEMBLK; + long offset = 0; + FILE *input = NULL; + char c; + + if ((strcmp("-", file_name) == 0)) { + input = stdin; + } else { + if ((input = fopen(file_name, "rb")) == NULL) { + rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno)); + return (-1); + } + } + if (skipfirst) { + do { + c = getc(input); + offset++; + } while (c != '\n' && !feof(input)); + } + if (strcmp("-", file_name)) { + fseek(input, 0, SEEK_END); + /* have extra space for detecting EOF without realloc */ + totalcnt = (ftell(input) + 1) / sizeof(char) - offset; + if (totalcnt < MEMBLK) + totalcnt = MEMBLK; /* sanitize */ + fseek(input, offset * sizeof(char), SEEK_SET); + } + if (((*buffer) = (char *) malloc((totalcnt + 4) * sizeof(char))) == NULL) { + perror("Allocate Buffer:"); + exit(1); + }; + do { + writecnt += + fread((*buffer) + writecnt, 1, + (totalcnt - writecnt) * sizeof(char), input); + if (writecnt >= totalcnt) { + totalcnt += MEMBLK; + if (((*buffer) = + rrd_realloc((*buffer), + (totalcnt + 4) * sizeof(char))) == NULL) { + perror("Realloc Buffer:"); + exit(1); + }; + } + } while (!feof(input)); + (*buffer)[writecnt] = '\0'; + if (strcmp("-", file_name) != 0) { + fclose(input); + }; + return writecnt; } int main( @@ -532,12 +591,13 @@ char *rrdsetenv( const char **args) { if (argc >= 2) { - char *xyz = malloc((strlen(args[0]) + strlen(args[1]) + 2)); + const size_t len = strlen(args[0]) + strlen(args[1]) + 2; + char *xyz = malloc(len); if (xyz == NULL) { return stralloc("[ERROR: allocating setenv buffer]"); }; - sprintf(xyz, "%s=%s", args[0], args[1]); + snprintf(xyz, len, "%s=%s", args[0], args[1]); if (putenv(xyz) == -1) { free(xyz); return stralloc("[ERROR: failed to do putenv]"); @@ -666,7 +726,7 @@ char *printstrftime( long argc, const char **args) { - struct rrd_time_value start_tv, end_tv; + rrd_time_value_t start_tv, end_tv; char *parsetime_error = NULL; char formatted[MAX_STRFTIME_SIZE]; struct tm *the_tm; @@ -679,19 +739,19 @@ char *printstrftime( } /* Init start and end time */ - parsetime("end-24h", &start_tv); - parsetime("now", &end_tv); + rrd_parsetime("end-24h", &start_tv); + rrd_parsetime("now", &end_tv); /* Parse the start and end times we were given */ - if ((parsetime_error = parsetime(args[1], &start_tv))) { + if ((parsetime_error = rrd_parsetime(args[1], &start_tv))) { rrd_set_error("start time: %s", parsetime_error); return stralloc(""); } - if ((parsetime_error = parsetime(args[2], &end_tv))) { + if ((parsetime_error = rrd_parsetime(args[2], &end_tv))) { rrd_set_error("end time: %s", parsetime_error); return stralloc(""); } - if (proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { + if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { return stralloc(""); } @@ -725,9 +785,10 @@ char *includefile( readfile(filename, &buffer, 0); if (rrd_test_error()) { - char *err = malloc((strlen(rrd_get_error()) + DS_NAM_SIZE)); + const size_t len = strlen(rrd_get_error()) + DS_NAM_SIZE; + char *err = malloc(len); - sprintf(err, "[ERROR: %s]", rrd_get_error()); + snprintf(err, len, "[ERROR: %s]", rrd_get_error()); rrd_clear_error(); return err; } else { @@ -891,12 +952,10 @@ char *drawgraph( return stralloc(calcpr[0]); } else { if (rrd_test_error()) { - char *err = - malloc((strlen(rrd_get_error()) + - DS_NAM_SIZE) * sizeof(char)); - sprintf(err, "[ERROR: %s]", rrd_get_error()); + const size_t len = strlen(rrd_get_error()) + DS_NAM_SIZE; + char *err = malloc(len); + snprintf(err, len, "[ERROR: %s]", rrd_get_error()); rrd_clear_error(); - calfree(); return err; } } @@ -931,12 +990,14 @@ char *printtimelast( if (buf == NULL) { return stralloc("[ERROR: allocating strftime buffer]"); }; - last = rrd_last(argc + 1, (char **) args - 1); + /* not raising argc in step with args - 1 since the last argument + will be used below for strftime */ + + last = rrd_last(argc, (char **) args - 1); if (rrd_test_error()) { - char *err = - malloc((strlen(rrd_get_error()) + - DS_NAM_SIZE) * sizeof(char)); - sprintf(err, "[ERROR: %s]", rrd_get_error()); + const size_t len = strlen(rrd_get_error()) + DS_NAM_SIZE; + char *err = malloc(len); + snprintf(err, len, "[ERROR: %s]", rrd_get_error()); rrd_clear_error(); return err; } @@ -944,10 +1005,7 @@ char *printtimelast( strftime(buf, 254, args[1], &tm_last); return buf; } - if (argc < 2) { - return stralloc("[ERROR: too few arguments for RRD::TIME::LAST]"); - } - return stralloc("[ERROR: not enough arguments for RRD::TIME::LAST]"); + return stralloc("[ERROR: expected ]"); } char *printtimenow( @@ -996,7 +1054,7 @@ char *scanargs( int curarg_contains_rrd_directives; /* local array of arguments while parsing */ - int argc = 0; + int argc = 1; char **argv; #ifdef DEBUG_PARSER @@ -1012,6 +1070,7 @@ char *scanargs( if (!argv) { return NULL; } + argv[0] = "rrdcgi"; /* skip leading blanks */ while (isspace((int) *line)) { @@ -1115,7 +1174,7 @@ char *scanargs( argv[argc - 1] = rrd_expand_vars(stralloc(argv[argc - 1])); } #ifdef DEBUG_PARSER - if (argc > 0) { + if (argc > 1) { int n; printf("<-- arguments found [%d]\n", argc); @@ -1129,8 +1188,17 @@ char *scanargs( #endif /* update caller's notion of the argument array and it's size */ - *arguments = argv; - *argument_count = argc; + + /* note this is a bit of a hack since the rrd_cgi code used to just put + its arguments into a normal array starting at 0 ... since the rrd_* + commands expect and argc/argv array we used to just shift everything + by -1 ... this in turn exploded when a rrd_* function tried to print + argv[0] ... hence we are now doing everything in argv style but hand + over seemingly the old array ... but doing argv-1 will actually end + up in a 'good' place now. */ + + *arguments = argv+1; + *argument_count = argc-1; if (Quote) { return NULL; @@ -1184,13 +1252,8 @@ int parse( if (end) { /* got arguments, call function for 'tag' with arguments */ val = func(argc, (const char **) args); - free(args); + free(args-1); } else { - /* unable to parse arguments, undo 0-termination by scanargs */ - for (; argc > 0; argc--) { - *((args[argc - 1]) - 1) = ' '; - } - /* next call, try parsing at current offset +1 */ end = (*buf) + i + 1; @@ -1321,6 +1384,7 @@ s_var **rrdcgiReadVariables( s_var **result; int i, k, len; char tmp[101]; + size_t tmplen; cp = getenv("REQUEST_METHOD"); ip = getenv("CONTENT_LENGTH"); @@ -1330,15 +1394,15 @@ s_var **rrdcgiReadVariables( length = atoi(ip); if ((line = (char *) malloc(length + 2)) == NULL) return NULL; - fgets(line, length + 1, stdin); + if (fgets(line, length + 1, stdin) == NULL) + return NULL; } else return NULL; } else if (cp && !strcmp(cp, "GET")) { esp = getenv("QUERY_STRING"); if (esp && strlen(esp)) { - if ((line = (char *) malloc(strlen(esp) + 2)) == NULL) + if ((line = strdup(esp)) == NULL) return NULL; - sprintf(line, "%s", esp); } else return NULL; } else { @@ -1346,22 +1410,18 @@ s_var **rrdcgiReadVariables( printf("(offline mode: enter name=value pairs on standard input)\n"); memset(tmp, 0, sizeof(tmp)); while ((cp = fgets(tmp, 100, stdin)) != NULL) { - if (strlen(tmp)) { - if (tmp[strlen(tmp) - 1] == '\n') - tmp[strlen(tmp) - 1] = '&'; - if (length) { - length += strlen(tmp); - len = (length + 1) * sizeof(char); + if ((tmplen = strlen(tmp)) != 0) { + if (tmp[tmplen - 1] == '\n') + tmp[tmplen - 1] = '&'; + length += tmplen; + len = (length + 1) * sizeof(char); + if ((unsigned) length > tmplen) { if ((line = (char *) realloc(line, len)) == NULL) return NULL; - strcat(line, tmp); + strncat(line, tmp, tmplen); } else { - length = strlen(tmp); - len = (length + 1) * sizeof(char); - if ((line = (char *) malloc(len)) == NULL) + if ((line = strdup(tmp)) == NULL) return NULL; - memset(line, 0, len); - strcpy(line, tmp); } } memset(tmp, 0, sizeof(tmp)); @@ -1430,8 +1490,8 @@ s_var **rrdcgiReadVariables( /* try to find out if there's already such a variable */ for (k = 0; k < i && (strncmp(result[k]->name, cp, esp - cp) - || !(strlen(result[k]->name) == (size_t)(esp - cp))); - k++); + || !(strlen(result[k]->name) == + (size_t) (esp - cp))); k++); if (k == i) { /* No such variable yet */ if ((result[i] = (s_var *) malloc(sizeof(s_var))) == NULL) @@ -1459,14 +1519,10 @@ s_var **rrdcgiReadVariables( i++; } else { /* There is already such a name, suppose a mutiple field */ cp = ++esp; - len = - (strlen(result[k]->value) + (ip - esp) + - 2) * sizeof(char); - if ((sptr = (char *) malloc(len)) == NULL) + len = strlen(result[k]->value) + (ip - esp) + 2; + if ((sptr = (char *) calloc(len, sizeof(char))) == NULL) return NULL; - memset(sptr, 0, len); - sprintf(sptr, "%s\n", result[k]->value); - strncat(sptr, cp, ip - esp); + snprintf(sptr, len, "%s\n%s", result[k]->value, cp); free(result[k]->value); result[k]->value = rrdcgiDecodeString(sptr); }