summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: edb1cd4)
raw | patch | inline | side by side (parent: edb1cd4)
author | oetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa> | |
Fri, 7 Oct 2005 07:48:52 +0000 (07:48 +0000) | ||
committer | oetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa> | |
Fri, 7 Oct 2005 07:48:52 +0000 (07:48 +0000) |
git-svn-id: svn://svn.oetiker.ch/rrdtool/branches/1.2/program@696 a5681a0c-68f1-0310-ab6d-d61299d08faa
CONTRIBUTORS | patch | blob | history | |
bindings/tcl/Makefile.am | patch | blob | history | |
bindings/tcl/tclrrd.c | patch | blob | history | |
configure.ac | patch | blob | history |
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 9eb60f12bc7d702abd888e8f6c6f1552bc2a2e77..71566c6fe141630a3d13495c606dd7c23c0c06bb 100644 (file)
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
Christophe VG <Christophe.VanGinneken with ubizen.com>
Christophe Van Ginneken <Christophe.VanGinneken with ubizen.com> (--no-legend)
Dan Dunn <dandunn with computer.org>
+Dave Bodenstab <dave@bodenstab.org> AT style time in update, tclfixes
David Grimes <dgrimes with navisite.com> SQRT/SORT/REV/SHIFT/TREND
David L. Barker <dave with ncomtech.com> xport function bug fixes
Frank Strauss <strauss with escape.de> TCL bindings
index 9931975f718a50f0f241ebda7f1109f984b6b024..7b2393102aa84ad363c0f1cbdc6aa11f9ae2821f 100644 (file)
--- a/bindings/tcl/Makefile.am
+++ b/bindings/tcl/Makefile.am
TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
TCL_LD_SEARCH_FLAGS = @TCL_LD_SEARCH_FLAGS@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
CLEANFILES = tclrrd.o tclrrd.so
SRC_DIR = $(top_srcdir)/src
-AM_CPPFLAGS = -I$(TCL_PREFIX)/include -I$(SRC_DIR)
+AM_CPPFLAGS = -I$(TCL_PREFIX)/include -I$(SRC_DIR) -DUSE_TCL_STUBS
LIBDIRS = -L$(top_builddir)/src/.libs -L$(top_builddir)/src -L$(libdir)
LIB_RUNTIME_DIR = $(libdir)
pkglib_SCRIPTS = ifOctets.tcl
$(TCL_RRD_LIB): tclrrd.o
- $(TCL_SHLIB_LD) $(TCL_LD_SEARCH_FLAGS) $(LIBDIRS) $< -o $@ -lrrd -lm
+ $(TCL_SHLIB_LD) $(TCL_LD_SEARCH_FLAGS) $(LIBDIRS) $< -o $@ -lrrd -lm $(TCL_STUB_LIB_SPEC) $(LIBS)
tclrrd.o: tclrrd.c
$(CC) $(AM_CFLAGS) $(CFLAGS) $(TCL_SHLIB_CFLAGS) $(AM_CPPFLAGS) -c $< -DVERSION=\"$(VERSION)\"
diff --git a/bindings/tcl/tclrrd.c b/bindings/tcl/tclrrd.c
index ad8a8a3aac9dcd2d7501ede87b7d0f6d571cd4ad..43836478d7bce20829b8c62926912363e1160302 100644 (file)
--- a/bindings/tcl/tclrrd.c
+++ b/bindings/tcl/tclrrd.c
#include <rrd_tool.h>
#include <rrd_format.h>
-extern int Tclrrd_Init(Tcl_Interp *interp, int safe);
-
-extern int __getopt_initialized;
+extern int Tclrrd_Init(Tcl_Interp *interp);
+extern int Tclrrd_SafeInit(Tcl_Interp *interp);
/*
* Hence, we need to do some preparation before
* calling the rrd library functions.
*/
-static char ** getopt_init(argc, argv)
- int argc;
- char *argv[];
+static char ** getopt_init(int argc, CONST84 char *argv[])
{
char **argv2;
int i;
return argv2;
}
-static void getopt_cleanup(argc, argv2)
- int argc;
- char *argv2[];
+static void getopt_cleanup(int argc, char **argv2)
{
int i;
static int
-Rrd_Create(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Create(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **argv2;
static int
-Rrd_Dump(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Dump(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **argv2;
argv2 = getopt_init(argc, argv);
rrd_dump(argc, argv2);
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
/* NOTE: rrd_dump() writes to stdout. No interaction with TCL. */
static int
-Rrd_Last(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Last(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
time_t t;
char **argv2;
argv2 = getopt_init(argc, argv);
t = rrd_last(argc, argv2);
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
static int
-Rrd_Update(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Update(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **argv2;
argv2 = getopt_init(argc, argv);
rrd_update(argc, argv2);
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
Tcl_AppendResult(interp, "RRD Error: ",
static int
-Rrd_Fetch(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Fetch(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
time_t start, end, j;
unsigned long step, ds_cnt, i, ii;
free(ds_namv);
free(data);
}
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
Tcl_AppendResult(interp, "RRD Error: ",
static int
-Rrd_Graph(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Graph(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **calcpr;
int xsize, ysize;
double ymin, ymax;
- Tcl_Obj *listPtr;
+ char dimensions[50];
char **argv2;
calcpr = NULL;
argv2 = getopt_init(argc, argv);
if (rrd_graph(argc, argv2, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) != -1 ) {
- listPtr = Tcl_GetObjResult(interp);
- Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(xsize));
- Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(ysize));
+ sprintf(dimensions, "%d %d", xsize, ysize);
+ Tcl_AppendResult(interp, dimensions, (char *) NULL);
if (calcpr) {
#if 0
int i;
free(calcpr);
}
}
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
Tcl_AppendResult(interp, "RRD Error: ",
static int
-Rrd_Tune(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Tune(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **argv2;
argv2 = getopt_init(argc, argv);
rrd_tune(argc, argv2);
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
Tcl_AppendResult(interp, "RRD Error: ",
static int
-Rrd_Resize(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Resize(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **argv2;
argv2 = getopt_init(argc, argv);
rrd_resize(argc, argv2);
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
Tcl_AppendResult(interp, "RRD Error: ",
static int
-Rrd_Restore(clientData, interp, argc, argv)
- ClientData clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
+Rrd_Restore(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
char **argv2;
argv2 = getopt_init(argc, argv);
rrd_restore(argc, argv2);
- getopt_cleanup(argv, argv2);
+ getopt_cleanup(argc, argv2);
if (rrd_test_error()) {
Tcl_AppendResult(interp, "RRD Error: ",
typedef struct {
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 },
- { "Rrd::dump", Rrd_Dump },
- { "Rrd::last", Rrd_Last },
- { "Rrd::update", Rrd_Update },
- { "Rrd::fetch", Rrd_Fetch },
- { "Rrd::graph", Rrd_Graph },
- { "Rrd::tune", Rrd_Tune },
- { "Rrd::resize", Rrd_Resize },
- { "Rrd::restore", Rrd_Restore },
- { (char *) NULL, (Tcl_CmdProc *) NULL }
+ { "Rrd::create", Rrd_Create, 1 },
+ { "Rrd::dump", Rrd_Dump, 0 },
+ { "Rrd::last", Rrd_Last, 0 },
+ { "Rrd::update", Rrd_Update, 1 },
+ { "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 }
};
-int
-Tclrrd_Init(interp, safe)
- Tcl_Interp *interp;
- int safe;
+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_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) {
return TCL_ERROR;
}
+ /*
+ * Why a global array? In keeping with the Rrd:: namespace, why
+ * not simply create a normal variable Rrd::version and set it?
+ */
Tcl_SetVar2(interp, "rrd", "version", VERSION, TCL_GLOBAL_ONLY);
for (cmdInfoPtr = rrdCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
"\" already exists", (char *) NULL);
return TCL_ERROR;
}
- Tcl_CreateCommand(interp, cmdInfoPtr->name, cmdInfoPtr->proc,
+ 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;
+#endif
+ }
+ else
+ Tcl_CreateCommand(interp, cmdInfoPtr->name, cmdInfoPtr->proc,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
}
return TCL_OK;
}
+
+int
+Tclrrd_Init(Tcl_Interp *interp)
+{
+ return init(interp, 0);
+}
+
+/*
+ * See the comments above and note how few commands are considered "safe"...
+ * 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);
+}
diff --git a/configure.ac b/configure.ac
index d40d930dbe0a408181ff6043c8dcde7f92d1e80f..cb3caa8dd80873292dfff589a79e0973e36ecb39 100644 (file)
--- a/configure.ac
+++ b/configure.ac
AC_SUBST(TCL_SHLIB_SUFFIX)
AC_SUBST(TCL_PACKAGE_PATH)
AC_SUBST(TCL_LD_SEARCH_FLAGS)
+AC_SUBST(TCL_STUB_LIB_SPEC)
AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_PACKAGE_DIR)