make tcl compile again ... don't know if it will work though
[rrdtool.git] / bindings / tcl / tclrrd.c
1 /*
2  * tclrrd.c -- A TCL interpreter extension to access the RRD library.
3  *
4  * Copyright (c) 1999,2000 Frank Strauss, Technical University of Braunschweig.
5  *
6  * See the file "COPYING" for information on usage and redistribution
7  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
8  *
9  * $Id$
10  */
11
12
13
14 #include <time.h>
15 #include <tcl.h>
16 #include <rrd_tool.h>
17 #include <rrd_format.h>
18
19
20
21 extern int __getopt_initialized;
22
23
24 /*
25  * some rrd_XXX() functions might modify the argv strings passed to it.
26  * Hence, we need to do some preparation before
27  * calling the rrd library functions.
28  */
29 static char ** getopt_init(argc, argv)
30     int argc;
31     char *argv[];
32 {
33     char **argv2;
34     int i;
35     
36     argv2 = calloc(argc, sizeof(char *));
37     for (i = 0; i < argc; i++) {
38         argv2[i] = strdup(argv[i]);
39     }
40     return argv2;
41 }
42
43 static void getopt_cleanup(argc, argv2)
44     int argc;
45     char *argv2[];
46 {
47     int i;
48     
49     for (i = 0; i < argc; i++) {
50         free(argv2[i]);
51     }
52     free(argv2);
53 }
54
55
56
57 static int
58 Rrd_Create(clientData, interp, argc, argv)
59     ClientData clientData;
60     Tcl_Interp *interp;
61     int argc;
62     char *argv[];
63 {
64     char **argv2;
65
66     argv2 = getopt_init(argc, argv);
67     rrd_create(argc, argv2);
68     getopt_cleanup(argc, argv2);
69     
70     if (rrd_test_error()) {
71         Tcl_AppendResult(interp, "RRD Error: ",
72                          rrd_get_error(), (char *) NULL);
73         rrd_clear_error();
74         return TCL_ERROR;
75     }
76
77     return TCL_OK;
78 }
79
80
81
82 static int
83 Rrd_Dump(clientData, interp, argc, argv)
84     ClientData clientData;
85     Tcl_Interp *interp;
86     int argc;
87     char *argv[];
88 {
89     char **argv2;
90     
91     argv2 = getopt_init(argc, argv);
92     rrd_dump(argc, argv2);
93     getopt_cleanup(argv, argv2);
94
95     /* NOTE: rrd_dump() writes to stdout. No interaction with TCL. */
96
97     if (rrd_test_error()) {
98         Tcl_AppendResult(interp, "RRD Error: ",
99                          rrd_get_error(), (char *) NULL);
100         rrd_clear_error();
101         return TCL_ERROR;
102     }
103
104     return TCL_OK;
105 }
106
107
108
109 static int
110 Rrd_Last(clientData, interp, argc, argv)
111     ClientData clientData;
112     Tcl_Interp *interp;
113     int argc;
114     char *argv[];
115 {
116     time_t t;
117     char **argv2;
118     
119     argv2 = getopt_init(argc, argv);
120     t = rrd_last(argc, argv2);
121     getopt_cleanup(argv, argv2);
122
123
124     if (rrd_test_error()) {
125         Tcl_AppendResult(interp, "RRD Error: ",
126                          rrd_get_error(), (char *) NULL);
127         rrd_clear_error();
128         return TCL_ERROR;
129     }
130
131     Tcl_SetIntObj(Tcl_GetObjResult(interp), t);
132
133     return TCL_OK;
134 }
135
136
137
138 static int
139 Rrd_Update(clientData, interp, argc, argv)
140     ClientData clientData;
141     Tcl_Interp *interp;
142     int argc;
143     char *argv[];
144 {
145     char **argv2;
146     
147     argv2 = getopt_init(argc, argv);
148     rrd_update(argc, argv2);
149     getopt_cleanup(argv, argv2);
150
151     if (rrd_test_error()) {
152         Tcl_AppendResult(interp, "RRD Error: ",
153                          rrd_get_error(), (char *) NULL);
154         rrd_clear_error();
155         return TCL_ERROR;
156     }
157
158     return TCL_OK;
159 }
160
161
162
163 static int
164 Rrd_Fetch(clientData, interp, argc, argv)
165     ClientData clientData;
166     Tcl_Interp *interp;
167     int argc;
168     char *argv[];
169 {
170     time_t start, end;
171     unsigned long step, ds_cnt, i, ii;
172     rrd_value_t *data, *datai;
173     char **ds_namv;
174     Tcl_Obj *listPtr;
175     char s[30];
176     char **argv2;
177     
178     argv2 = getopt_init(argc, argv);
179     if (rrd_fetch(argc, argv2, &start, &end, &step,
180                   &ds_cnt, &ds_namv, &data) != -1) {
181         datai = data;
182         listPtr = Tcl_GetObjResult(interp);
183         for (i = start; i <= end; i += step) {
184             for (ii = 0; ii < ds_cnt; ii++) {
185                 sprintf(s, "%.2f", *(datai++));
186                 Tcl_ListObjAppendElement(interp, listPtr,
187                                          Tcl_NewStringObj(s, -1));
188             }
189         }
190         for (i=0; i<ds_cnt; i++) free(ds_namv[i]);
191         free(ds_namv);
192         free(data);
193     }
194     getopt_cleanup(argv, argv2);
195
196     if (rrd_test_error()) {
197         Tcl_AppendResult(interp, "RRD Error: ",
198                          rrd_get_error(), (char *) NULL);
199         rrd_clear_error();
200         return TCL_ERROR;
201     }
202
203     return TCL_OK;
204 }
205
206
207
208 static int
209 Rrd_Graph(clientData, interp, argc, argv)
210     ClientData clientData;
211     Tcl_Interp *interp;
212     int argc;
213     char *argv[];
214 {
215     char **calcpr;
216     int xsize, ysize;
217     double ymin, ymax;
218     Tcl_Obj *listPtr;
219     char **argv2;
220     
221     calcpr = NULL;
222
223     argv2 = getopt_init(argc, argv);
224     if (rrd_graph(argc, argv2, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) != -1 ) {
225         listPtr = Tcl_GetObjResult(interp);
226         Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(xsize));
227         Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(ysize));
228         if (calcpr) {
229 #if 0
230             int i;
231             
232             for(i = 0; calcpr[i]; i++){
233                 printf("%s\n", calcpr[i]);
234                 free(calcpr[i]);
235             } 
236 #endif
237             free(calcpr);
238         }
239     }
240     getopt_cleanup(argv, argv2);
241
242     if (rrd_test_error()) {
243         Tcl_AppendResult(interp, "RRD Error: ",
244                          rrd_get_error(), (char *) NULL);
245         rrd_clear_error();
246         return TCL_ERROR;
247     }
248
249     return TCL_OK;
250 }
251
252
253
254 static int
255 Rrd_Tune(clientData, interp, argc, argv)
256     ClientData clientData;
257     Tcl_Interp *interp;
258     int argc;
259     char *argv[];
260 {
261     char **argv2;
262     
263     argv2 = getopt_init(argc, argv);
264     rrd_tune(argc, argv2);
265     getopt_cleanup(argv, argv2);
266
267     if (rrd_test_error()) {
268         Tcl_AppendResult(interp, "RRD Error: ",
269                          rrd_get_error(), (char *) NULL);
270         rrd_clear_error();
271         return TCL_ERROR;
272     }
273
274     return TCL_OK;
275 }
276
277
278
279 static int
280 Rrd_Resize(clientData, interp, argc, argv)
281     ClientData clientData;
282     Tcl_Interp *interp;
283     int argc;
284     char *argv[];
285 {
286     char **argv2;
287     
288     argv2 = getopt_init(argc, argv);
289     rrd_resize(argc, argv2);
290     getopt_cleanup(argv, argv2);
291
292     if (rrd_test_error()) {
293         Tcl_AppendResult(interp, "RRD Error: ",
294                          rrd_get_error(), (char *) NULL);
295         rrd_clear_error();
296         return TCL_ERROR;
297     }
298
299     return TCL_OK;
300 }
301
302
303
304 static int
305 Rrd_Restore(clientData, interp, argc, argv)
306     ClientData clientData;
307     Tcl_Interp *interp;
308     int argc;
309     char *argv[];
310 {
311     char **argv2;
312     
313     argv2 = getopt_init(argc, argv);
314     rrd_restore(argc, argv2);
315     getopt_cleanup(argv, argv2);
316
317     if (rrd_test_error()) {
318         Tcl_AppendResult(interp, "RRD Error: ",
319                          rrd_get_error(), (char *) NULL);
320         rrd_clear_error();
321         return TCL_ERROR;
322     }
323
324     return TCL_OK;
325 }
326
327
328
329 /*
330  * The following structure defines the commands in the Rrd extension.
331  */
332
333 typedef struct {
334     char *name;                 /* Name of the command. */
335     Tcl_CmdProc *proc;          /* Procedure for command. */
336 } CmdInfo;
337
338 static CmdInfo rrdCmds[] = {
339     { "Rrd::create",    Rrd_Create              },
340     { "Rrd::dump",      Rrd_Dump                },
341     { "Rrd::last",      Rrd_Last                },
342     { "Rrd::update",    Rrd_Update              },
343     { "Rrd::fetch",     Rrd_Fetch               },
344     { "Rrd::graph",     Rrd_Graph               },
345     { "Rrd::tune",      Rrd_Tune                },
346     { "Rrd::resize",    Rrd_Resize              },
347     { "Rrd::restore",   Rrd_Restore             },
348     { (char *) NULL,    (Tcl_CmdProc *) NULL    }
349 };
350
351
352
353 int
354 Tclrrd_Init(interp, safe)
355     Tcl_Interp *interp;
356     int safe;
357
358     CmdInfo *cmdInfoPtr;
359     Tcl_CmdInfo info;
360
361     if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) {
362         return TCL_ERROR;
363     }
364
365     Tcl_SetVar2(interp, "rrd", "version", VERSION, TCL_GLOBAL_ONLY);
366
367     for (cmdInfoPtr = rrdCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
368         /*
369          * Check if the command already exists and return an error
370          * to ensure we detect name clashes while loading the Rrd
371          * extension.
372          */
373         if (Tcl_GetCommandInfo(interp, cmdInfoPtr->name, &info)) {
374             Tcl_AppendResult(interp, "command \"", cmdInfoPtr->name,
375                              "\" already exists", (char *) NULL);
376             return TCL_ERROR;
377         }
378         Tcl_CreateCommand(interp, cmdInfoPtr->name, cmdInfoPtr->proc,
379                           (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
380     }
381
382     if (Tcl_PkgProvide(interp, "Rrd", VERSION) != TCL_OK) {
383         return TCL_ERROR;
384     }
385
386     return TCL_OK;
387 }