X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=bindings%2Ftcl%2Ftclrrd.c;h=a98a2d7c2ac23f82847e8991a5287f4550f74d03;hp=11d25dfae86d276fe680725aa4863d83a9d10f15;hb=bb645ca129e84e78c78799310df6a4d3efe4b6dd;hpb=5fc7ff89bdbced9c593c566fea9840a269935dcd diff --git a/bindings/tcl/tclrrd.c b/bindings/tcl/tclrrd.c index 11d25df..a98a2d7 100644 --- a/bindings/tcl/tclrrd.c +++ b/bindings/tcl/tclrrd.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "../../src/rrd_tool.h" #include "../../src/rrd_format.h" @@ -27,8 +28,10 @@ # define CONST84 #endif -extern int Tclrrd_Init(Tcl_Interp *interp); -extern int Tclrrd_SafeInit(Tcl_Interp *interp); +extern int Tclrrd_Init( + Tcl_Interp *interp); +extern int Tclrrd_SafeInit( + Tcl_Interp *interp); /* @@ -37,147 +40,162 @@ extern int Tclrrd_SafeInit(Tcl_Interp *interp); * Hence, we need to do some preparation before * calling the rrd library functions. */ -static char ** getopt_init(int argc, CONST84 char *argv[]) +static char **getopt_init( + int argc, + CONST84 char *argv[]) { - char **argv2; - int i; - + char **argv2; + int i; + argv2 = calloc(argc, sizeof(char *)); for (i = 0; i < argc; i++) { - argv2[i] = strdup(argv[i]); + argv2[i] = strdup(argv[i]); } return argv2; } -static void getopt_cleanup(int argc, char **argv2) +static void getopt_cleanup( + int argc, + char **argv2) { - int i; - + int i; + for (i = 0; i < argc; i++) { - if (argv2[i] != NULL) { - free(argv2[i]); - } + if (argv2[i] != NULL) { + free(argv2[i]); + } } free(argv2); } -static void getopt_free_element(argv2, argn) - char *argv2[]; - int argn; +static void getopt_free_element( + char *argv2[], + int argn) { if (argv2[argn] != NULL) { - free(argv2[argn]); - argv2[argn] = NULL; + free(argv2[argn]); + argv2[argn] = NULL; } } -static void getopt_squieeze(argc, argv2) - int *argc; - char *argv2[]; +static void getopt_squieeze( + int *argc, + char *argv2[]) { - int i, null_i = 0, argc_tmp = *argc; + int i, null_i = 0, argc_tmp = *argc; for (i = 0; i < argc_tmp; i++) { - if (argv2[i] == NULL) { - (*argc)--; - } else { - argv2[null_i++] = argv2[i]; - } + if (argv2[i] == NULL) { + (*argc)--; + } else { + argv2[null_i++] = argv2[i]; + } } } /* Thread-safe version */ -static int -Rrd_Create(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Create( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - int argv_i; - char **argv2; - char *parsetime_error = NULL; - time_t last_up = time(NULL) - 10; - long int long_tmp; - unsigned long int pdp_step = 300; - struct rrd_time_value last_up_tv; + int argv_i; + char **argv2; + char *parsetime_error = NULL; + time_t last_up = time(NULL) - 10; + long int long_tmp; + unsigned long int pdp_step = 300; + rrd_time_value_t last_up_tv; argv2 = getopt_init(argc, argv); for (argv_i = 1; argv_i < argc; argv_i++) { - if (!strcmp(argv2[argv_i], "--start") || !strcmp(argv2[argv_i], "-b")) { - if (argv_i++>=argc) { - Tcl_AppendResult(interp, "RRD Error: option '", - argv2[argv_i - 1], "' needs an argument", (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - if ((parsetime_error = parsetime(argv2[argv_i], &last_up_tv))) { - Tcl_AppendResult(interp, "RRD Error: invalid time format: '", - argv2[argv_i], "'", (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - if (last_up_tv.type == RELATIVE_TO_END_TIME || - last_up_tv.type == RELATIVE_TO_START_TIME) { - Tcl_AppendResult(interp, "RRD Error: specifying time relative to the 'start' ", - "or 'end' makes no sense here", (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - last_up = mktime(&last_up_tv.tm) + last_up_tv.offset; - if (last_up < 3600*24*365*10) { - Tcl_AppendResult(interp, "RRD Error: the first entry to the RRD should be after 1980", - (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - getopt_free_element(argv2, argv_i - 1); - getopt_free_element(argv2, argv_i); - } else if (!strcmp(argv2[argv_i], "--step") || !strcmp(argv2[argv_i], "-s")) { - if (argv_i++>=argc) { - Tcl_AppendResult(interp, "RRD Error: option '", - argv2[argv_i - 1], "' needs an argument", (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - long_tmp = atol(argv2[argv_i]); - if (long_tmp < 1) { - Tcl_AppendResult(interp, "RRD Error: step size should be no less than one second", - (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - pdp_step = long_tmp; - getopt_free_element(argv2, argv_i - 1); - getopt_free_element(argv2, argv_i); - } else if (!strcmp(argv2[argv_i], "--")) { - getopt_free_element(argv2, argv_i); - break; - } else if (argv2[argv_i][0]=='-') { - Tcl_AppendResult(interp, "RRD Error: unknown option '", - argv2[argv_i], "'", (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } + if (!strcmp(argv2[argv_i], "--start") || !strcmp(argv2[argv_i], "-b")) { + if (argv_i++ >= argc) { + Tcl_AppendResult(interp, "RRD Error: option '", + argv2[argv_i - 1], "' needs an argument", + (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + if ((parsetime_error = rrd_parsetime(argv2[argv_i], &last_up_tv))) { + Tcl_AppendResult(interp, "RRD Error: invalid time format: '", + argv2[argv_i], "'", (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + if (last_up_tv.type == RELATIVE_TO_END_TIME || + last_up_tv.type == RELATIVE_TO_START_TIME) { + Tcl_AppendResult(interp, + "RRD Error: specifying time relative to the 'start' ", + "or 'end' makes no sense here", + (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + last_up = mktime(&last_up_tv.tm) +last_up_tv.offset; + if (last_up < 3600 * 24 * 365 * 10) { + Tcl_AppendResult(interp, + "RRD Error: the first entry to the RRD should be after 1980", + (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + getopt_free_element(argv2, argv_i - 1); + getopt_free_element(argv2, argv_i); + } else if (!strcmp(argv2[argv_i], "--step") + || !strcmp(argv2[argv_i], "-s")) { + if (argv_i++ >= argc) { + Tcl_AppendResult(interp, "RRD Error: option '", + argv2[argv_i - 1], "' needs an argument", + (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + long_tmp = atol(argv2[argv_i]); + if (long_tmp < 1) { + Tcl_AppendResult(interp, + "RRD Error: step size should be no less than one second", + (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + pdp_step = long_tmp; + getopt_free_element(argv2, argv_i - 1); + getopt_free_element(argv2, argv_i); + } else if (!strcmp(argv2[argv_i], "--")) { + getopt_free_element(argv2, argv_i); + break; + } else if (argv2[argv_i][0] == '-') { + Tcl_AppendResult(interp, "RRD Error: unknown option '", + argv2[argv_i], "'", (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } } getopt_squieeze(&argc, argv2); if (argc < 2) { - Tcl_AppendResult(interp, "RRD Error: needs rrd filename", - (char *) NULL); - getopt_cleanup(argc, argv2); - return TCL_ERROR; + Tcl_AppendResult(interp, "RRD Error: needs rrd filename", + (char *) NULL); + getopt_cleanup(argc, argv2); + return TCL_ERROR; } - rrd_create_r(argv2[1], pdp_step, last_up, argc - 2, argv2 + 2); + rrd_create_r(argv2[1], pdp_step, last_up, argc - 2, + (const char **)argv2 + 2); getopt_cleanup(argc, argv2); - + if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; @@ -186,13 +204,16 @@ Rrd_Create(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *ar /* Thread-safe version */ -static int -Rrd_Dump(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Dump( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { if (argc < 2) { - Tcl_AppendResult(interp, "RRD Error: needs rrd filename", - (char *) NULL); - return TCL_ERROR; + Tcl_AppendResult(interp, "RRD Error: needs rrd filename", + (char *) NULL); + return TCL_ERROR; } rrd_dump_r(argv[1], NULL); @@ -200,36 +221,63 @@ Rrd_Dump(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv /* NOTE: rrd_dump() writes to stdout. No interaction with TCL. */ if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; } +/* Thread-safe version */ +static int Rrd_Flushcached( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) +{ + if (argc < 2) { + Tcl_AppendResult(interp, "RRD Error: needs rrd filename", + (char *) NULL); + return TCL_ERROR; + } + + rrd_flushcached(argc, (char**)argv); + + if (rrd_test_error()) { + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); + rrd_clear_error(); + return TCL_ERROR; + } + + return TCL_OK; +} /* Thread-safe version */ -static int -Rrd_Last(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Last( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - time_t t; - + time_t t; + if (argc < 2) { - Tcl_AppendResult(interp, "RRD Error: needs rrd filename", - (char *) NULL); - return TCL_ERROR; + Tcl_AppendResult(interp, "RRD Error: needs rrd filename", + (char *) NULL); + return TCL_ERROR; } t = rrd_last_r(argv[1]); if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } Tcl_SetIntObj(Tcl_GetObjResult(interp), t); @@ -240,147 +288,166 @@ Rrd_Last(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv /* Thread-safe version */ -static int -Rrd_Update(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Update( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - int argv_i; - char **argv2, *template = NULL; - + int argv_i; + char **argv2, *template = NULL; + argv2 = getopt_init(argc, argv); for (argv_i = 1; argv_i < argc; argv_i++) { - if (!strcmp(argv2[argv_i], "--template") || !strcmp(argv2[argv_i], "-t")) { - if (argv_i++>=argc) { - Tcl_AppendResult(interp, "RRD Error: option '", - argv2[argv_i - 1], "' needs an argument", (char *) NULL); - if (template != NULL) { - free(template); - } - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } - if (template != NULL) { - free(template); - } - template = strdup(argv2[argv_i]); - getopt_free_element(argv2, argv_i - 1); - getopt_free_element(argv2, argv_i); - } else if (!strcmp(argv2[argv_i], "--")) { - getopt_free_element(argv2, argv_i); - break; - } else if (argv2[argv_i][0]=='-') { - Tcl_AppendResult(interp, "RRD Error: unknown option '", - argv2[argv_i], "'", (char *) NULL); - if (template != NULL) { - free(template); - } - getopt_cleanup(argc, argv2); - return TCL_ERROR; - } + if (!strcmp(argv2[argv_i], "--template") + || !strcmp(argv2[argv_i], "-t")) { + if (argv_i++ >= argc) { + Tcl_AppendResult(interp, "RRD Error: option '", + argv2[argv_i - 1], "' needs an argument", + (char *) NULL); + if (template != NULL) { + free(template); + } + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } + if (template != NULL) { + free(template); + } + template = strdup(argv2[argv_i]); + getopt_free_element(argv2, argv_i - 1); + getopt_free_element(argv2, argv_i); + } else if (!strcmp(argv2[argv_i], "--")) { + getopt_free_element(argv2, argv_i); + break; + } else if (argv2[argv_i][0] == '-') { + Tcl_AppendResult(interp, "RRD Error: unknown option '", + argv2[argv_i], "'", (char *) NULL); + if (template != NULL) { + free(template); + } + getopt_cleanup(argc, argv2); + return TCL_ERROR; + } } getopt_squieeze(&argc, argv2); if (argc < 2) { - Tcl_AppendResult(interp, "RRD Error: needs rrd filename", - (char *) NULL); - if (template != NULL) { - free(template); - } - getopt_cleanup(argc, argv2); - return TCL_ERROR; + Tcl_AppendResult(interp, "RRD Error: needs rrd filename", + (char *) NULL); + if (template != NULL) { + free(template); + } + getopt_cleanup(argc, argv2); + return TCL_ERROR; } - rrd_update_r(argv2[1], template, argc - 2, argv2 + 2); + rrd_update_r(argv2[1], template, argc - 2, (const char **)argv2 + 2); if (template != NULL) { - free(template); + free(template); } getopt_cleanup(argc, argv2); if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; } -static int -Rrd_Lastupdate(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Lastupdate( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - time_t last_update; - char **argv2; - char **ds_namv; - char **last_ds; - char s[30]; - Tcl_Obj *listPtr; - unsigned long ds_cnt, i; - - argv2 = getopt_init(argc, argv); - if (rrd_lastupdate(argc-1, argv2, &last_update, - &ds_cnt, &ds_namv, &last_ds) == 0) { - listPtr = Tcl_GetObjResult(interp); - for (i=0; iis< a Tcl fileID - */ - if (!(mode & TCL_WRITABLE)) { - Tcl_AppendResult(interp, "channel \"", argv[1], - "\" wasn't opened for writing", (char *) NULL); - return TCL_ERROR; - } - /* - * Must flush channel to make sure any buffered data is written before - * rrd_graph() writes to the stream - */ - if (Tcl_Flush(channel) != TCL_OK) { - Tcl_AppendResult(interp, "flush failed for \"", argv[1], "\": ", - strerror(Tcl_GetErrno()), (char *) NULL); - return TCL_ERROR; - } - if (Tcl_GetChannelHandle(channel, TCL_WRITABLE, &fd1) != TCL_OK) { - Tcl_AppendResult(interp, "cannot get file descriptor associated with \"", - argv[1], "\"", (char *) NULL); - return TCL_ERROR; - } - /* - * Must dup() file descriptor so we can fclose(stream), otherwise the fclose() - * would close Tcl's file descriptor - */ - if ((fd2 = dup((int)fd1)) == -1) { - Tcl_AppendResult(interp, "dup() failed for file descriptor associated with \"", - argv[1], "\": ", strerror(errno), (char *) NULL); - return TCL_ERROR; - } - /* - * rrd_graph() wants a FILE* - */ - if ((stream = fdopen(fd2, "wb")) == NULL) { - Tcl_AppendResult(interp, "fdopen() failed for file descriptor associated with \"", - argv[1], "\": ", strerror(errno), (char *) NULL); - close(fd2); /* plug potential file descriptor leak */ - return TCL_ERROR; - } - - save = argv[1]; - argv[1] = "-"; - argv2 = getopt_init(argc, argv); - argv[1] = save; + /* + * It >is< a Tcl fileID + */ + if (!(mode & TCL_WRITABLE)) { + Tcl_AppendResult(interp, "channel \"", argv[1], + "\" wasn't opened for writing", (char *) NULL); + return TCL_ERROR; + } + /* + * Must flush channel to make sure any buffered data is written before + * rrd_graph() writes to the stream + */ + if (Tcl_Flush(channel) != TCL_OK) { + Tcl_AppendResult(interp, "flush failed for \"", argv[1], "\": ", + strerror(Tcl_GetErrno()), (char *) NULL); + return TCL_ERROR; + } + if (Tcl_GetChannelHandle(channel, TCL_WRITABLE, &fd1) != TCL_OK) { + Tcl_AppendResult(interp, + "cannot get file descriptor associated with \"", + argv[1], "\"", (char *) NULL); + return TCL_ERROR; + } + /* + * Must dup() file descriptor so we can fclose(stream), otherwise the fclose() + * would close Tcl's file descriptor + */ + if ((fd2 = dup((int)fd1)) == -1) { + Tcl_AppendResult(interp, + "dup() failed for file descriptor associated with \"", + argv[1], "\": ", strerror(errno), (char *) NULL); + return TCL_ERROR; + } + /* + * rrd_graph() wants a FILE* + */ + if ((stream = fdopen(fd2, "wb")) == NULL) { + Tcl_AppendResult(interp, + "fdopen() failed for file descriptor associated with \"", + argv[1], "\": ", strerror(errno), (char *) NULL); + close(fd2); /* plug potential file descriptor leak */ + return TCL_ERROR; + } + + save = argv[1]; + argv[1] = "-"; + argv2 = getopt_init(argc, argv); + argv[1] = save; } else { - Tcl_ResetResult(interp); /* clear error from Tcl_GetChannel() */ - argv2 = getopt_init(argc, argv); + Tcl_ResetResult(interp); /* clear error from Tcl_GetChannel() */ + argv2 = getopt_init(argc, argv); } - rc = rrd_graph(argc, argv2, &calcpr, &xsize, &ysize, stream, &ymin, &ymax); + rc = rrd_graph(argc, argv2, &calcpr, &xsize, &ysize, stream, &ymin, + &ymax); getopt_cleanup(argc, argv2); if (stream != NULL) - fclose(stream); /* plug potential malloc & file descriptor leak */ + fclose(stream); /* plug potential malloc & file descriptor leak */ if (rc != -1) { sprintf(dimensions, "%d %d", xsize, ysize); Tcl_AppendResult(interp, dimensions, (char *) NULL); if (calcpr) { #if 0 - int i; - - for(i = 0; calcpr[i]; i++){ + int i; + + for (i = 0; calcpr[i]; i++) { printf("%s\n", calcpr[i]); free(calcpr[i]); - } + } #endif free(calcpr); } } if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; @@ -491,20 +565,23 @@ Rrd_Graph(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *arg -static int -Rrd_Tune(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Tune( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - char **argv2; - + char **argv2; + argv2 = getopt_init(argc, argv); rrd_tune(argc, argv2); getopt_cleanup(argc, argv2); if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; @@ -512,20 +589,23 @@ Rrd_Tune(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv -static int -Rrd_Resize(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Resize( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - char **argv2; - + char **argv2; + argv2 = getopt_init(argc, argv); rrd_resize(argc, argv2); getopt_cleanup(argc, argv2); if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; @@ -533,20 +613,23 @@ Rrd_Resize(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *ar -static int -Rrd_Restore(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) +static int Rrd_Restore( + ClientData __attribute__((unused)) clientData, + Tcl_Interp *interp, + int argc, + CONST84 char *argv[]) { - char **argv2; - + char **argv2; + argv2 = getopt_init(argc, argv); rrd_restore(argc, argv2); getopt_cleanup(argc, argv2); if (rrd_test_error()) { - Tcl_AppendResult(interp, "RRD Error: ", - rrd_get_error(), (char *) NULL); + Tcl_AppendResult(interp, "RRD Error: ", + rrd_get_error(), (char *) NULL); rrd_clear_error(); - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; @@ -559,39 +642,41 @@ Rrd_Restore(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *a */ typedef struct { - char *name; /* Name of the command. */ - Tcl_CmdProc *proc; /* Procedure for command. */ - int hide; /* Hide if safe interpreter */ + char *name; /* Name of the command. */ + Tcl_CmdProc *proc; /* Procedure for command. */ + int hide; /* Hide if safe interpreter */ } CmdInfo; static CmdInfo rrdCmds[] = { - { "Rrd::create", Rrd_Create, 1 }, /* Thread-safe version */ - { "Rrd::dump", Rrd_Dump, 0 }, /* Thread-safe version */ - { "Rrd::last", Rrd_Last, 0 }, /* Thread-safe version */ - { "Rrd::lastupdate", Rrd_Lastupdate, 0 }, /* Thread-safe version */ - { "Rrd::update", Rrd_Update, 1 }, /* Thread-safe version */ - { "Rrd::fetch", Rrd_Fetch, 0 }, - { "Rrd::graph", Rrd_Graph, 1 }, /* Due to RRD's API, a safe - interpreter cannot create - a graph since it writes to - a filename supplied by the - caller */ - { "Rrd::tune", Rrd_Tune, 1 }, - { "Rrd::resize", Rrd_Resize, 1 }, - { "Rrd::restore", Rrd_Restore, 1 }, - { (char *) NULL, (Tcl_CmdProc *) NULL, 0 } + {"Rrd::create", Rrd_Create, 1}, /* Thread-safe version */ + {"Rrd::dump", Rrd_Dump, 0}, /* Thread-safe version */ + {"Rrd::flushcached", Rrd_Flushcached, 0}, + {"Rrd::last", Rrd_Last, 0}, /* Thread-safe version */ + {"Rrd::lastupdate", Rrd_Lastupdate, 0}, /* Thread-safe version */ + {"Rrd::update", Rrd_Update, 1}, /* Thread-safe version */ + {"Rrd::fetch", Rrd_Fetch, 0}, + {"Rrd::graph", Rrd_Graph, 1}, /* Due to RRD's API, a safe + interpreter cannot create + a graph since it writes to + a filename supplied by the + caller */ + {"Rrd::tune", Rrd_Tune, 1}, + {"Rrd::resize", Rrd_Resize, 1}, + {"Rrd::restore", Rrd_Restore, 1}, + {(char *) NULL, (Tcl_CmdProc *) NULL, 0} }; -static int -init(Tcl_Interp *interp, int safe) -{ - CmdInfo *cmdInfoPtr; +static int init( + Tcl_Interp *interp, + int safe) +{ + CmdInfo *cmdInfoPtr; Tcl_CmdInfo info; - if ( Tcl_InitStubs(interp,TCL_VERSION,0) == NULL ) - return TCL_ERROR; + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) + return TCL_ERROR; if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) { return TCL_ERROR; @@ -604,65 +689,65 @@ init(Tcl_Interp *interp, int safe) Tcl_SetVar2(interp, "rrd", "version", VERSION, TCL_GLOBAL_ONLY); for (cmdInfoPtr = rrdCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) { - /* - * Check if the command already exists and return an error - * to ensure we detect name clashes while loading the Rrd - * extension. - */ - if (Tcl_GetCommandInfo(interp, cmdInfoPtr->name, &info)) { - Tcl_AppendResult(interp, "command \"", cmdInfoPtr->name, - "\" already exists", (char *) NULL); - return TCL_ERROR; - } - if (safe && cmdInfoPtr->hide) { + /* + * Check if the command already exists and return an error + * to ensure we detect name clashes while loading the Rrd + * extension. + */ + if (Tcl_GetCommandInfo(interp, cmdInfoPtr->name, &info)) { + Tcl_AppendResult(interp, "command \"", cmdInfoPtr->name, + "\" already exists", (char *) NULL); + return TCL_ERROR; + } + if (safe && cmdInfoPtr->hide) { #if 0 - /* - * Turns out the one cannot hide a command in a namespace - * due to a limitation of Tcl, one can only hide global - * commands. Thus, if we created the commands without - * the Rrd:: namespace in a safe interpreter, then the - * "unsafe" commands could be hidden -- which would allow - * an owning interpreter either un-hiding them or doing - * an "interp invokehidden". If the Rrd:: namespace is - * used, then it's still possible for the owning interpreter - * to fake out the missing commands: - * - * # Make all Rrd::* commands available in master interperter - * package require Rrd - * set safe [interp create -safe] - * # Make safe Rrd::* commands available in safe interperter - * interp invokehidden $safe -global load ./tclrrd1.2.11.so - * # Provide the safe interpreter with the missing commands - * $safe alias Rrd::update do_update $safe - * proc do_update {which_interp $args} { - * # Do some checking maybe... - * : - * return [eval Rrd::update $args] - * } - * - * Our solution for now is to just not create the "unsafe" - * commands in a safe interpreter. - */ - if (Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name) != TCL_OK) - return TCL_ERROR; + /* + * Turns out the one cannot hide a command in a namespace + * due to a limitation of Tcl, one can only hide global + * commands. Thus, if we created the commands without + * the Rrd:: namespace in a safe interpreter, then the + * "unsafe" commands could be hidden -- which would allow + * an owning interpreter either un-hiding them or doing + * an "interp invokehidden". If the Rrd:: namespace is + * used, then it's still possible for the owning interpreter + * to fake out the missing commands: + * + * # Make all Rrd::* commands available in master interperter + * package require Rrd + * set safe [interp create -safe] + * # Make safe Rrd::* commands available in safe interperter + * interp invokehidden $safe -global load ./tclrrd1.2.11.so + * # Provide the safe interpreter with the missing commands + * $safe alias Rrd::update do_update $safe + * proc do_update {which_interp $args} { + * # Do some checking maybe... + * : + * return [eval Rrd::update $args] + * } + * + * Our solution for now is to just not create the "unsafe" + * commands in a safe interpreter. + */ + if (Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name) != + TCL_OK) + return TCL_ERROR; #endif - } - else - Tcl_CreateCommand(interp, cmdInfoPtr->name, cmdInfoPtr->proc, - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + } else + Tcl_CreateCommand(interp, cmdInfoPtr->name, cmdInfoPtr->proc, + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); } if (Tcl_PkgProvide(interp, "Rrd", VERSION) != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } return TCL_OK; } -int -Tclrrd_Init(Tcl_Interp *interp) -{ - return init(interp, 0); +int Tclrrd_Init( + Tcl_Interp *interp) +{ + return init(interp, 0); } /* @@ -670,8 +755,8 @@ Tclrrd_Init(Tcl_Interp *interp) * Using rrdtool in a safe interpreter has very limited functionality. It's * tempting to just return TCL_ERROR and forget about it. */ -int -Tclrrd_SafeInit(Tcl_Interp *interp) -{ - return init(interp, 1); +int Tclrrd_SafeInit( + Tcl_Interp *interp) +{ + return init(interp, 1); }