+ *legend_v = legend_list;
+ free(ref_list);
+ return 0;
+
+}
+
+/* helper function for buffer handling */
+typedef struct stringbuffer_t {
+ size_t allocated;
+ size_t len;
+ unsigned char* data;
+ FILE *file;
+} stringbuffer_t;
+int addToBuffer(stringbuffer_t *,char*,size_t);
+
+int rrd_graph_xport(image_desc_t *);
+int rrd_xport_format_xml(stringbuffer_t *,image_desc_t*,time_t, time_t, unsigned long, unsigned long, char**, rrd_value_t*);
+int rrd_xport_format_json(stringbuffer_t *,image_desc_t*,time_t, time_t, unsigned long, unsigned long, char**, rrd_value_t*);
+int rrd_xport_format_sv(char,stringbuffer_t *,image_desc_t*,time_t, time_t, unsigned long, unsigned long, char**, rrd_value_t*);
+
+int rrd_graph_xport(image_desc_t *im) {
+ /* prepare the data for processing */
+ unsigned long col_cnt=0;
+ time_t start=im->start;
+ time_t end=im->end;
+ unsigned long step=im->step;
+ char **legend_v=NULL;
+ rrd_value_t *data=NULL;
+ /* initialize buffer */
+ stringbuffer_t buffer={0,0,NULL,NULL};
+ /* if we write a file, then open it */
+ if (strlen(im->graphfile)) {
+ buffer.file=fopen(im->graphfile,"w");
+ }
+
+ /* do the data processing */
+ if (rrd_xport_fn(im,&start,&end,&step,&col_cnt,&legend_v,&data,1)) { return -1;}
+
+ /* fill in some data */
+ rrd_infoval_t info;
+ info.u_cnt = im->start;
+ grinfo_push(im, sprintf_alloc("graph_start"), RD_I_CNT, info);
+ info.u_cnt = im->end;
+ grinfo_push(im, sprintf_alloc("graph_end"), RD_I_CNT, info);
+ info.u_cnt = im->step;
+ grinfo_push(im, sprintf_alloc("graph_step"), RD_I_CNT, info);
+
+ /* set locale */
+ char *old_locale = setlocale(LC_NUMERIC,NULL);
+ setlocale(LC_NUMERIC, "C");
+
+ /* format it for output */
+ int r=0;
+ switch(im->imgformat) {
+ case IF_XML:
+ r=rrd_xport_format_xml(&buffer,im, start, end, step, col_cnt, legend_v, data);
+ break;
+ case IF_JSON:
+ r=rrd_xport_format_json(&buffer,im, start, end, step, col_cnt, legend_v, data);
+ break;
+ case IF_CSV:
+ r=rrd_xport_format_sv(',',&buffer,im, start, end, step, col_cnt, legend_v, data);
+ break;
+ case IF_TSV:
+ r=rrd_xport_format_sv('\t',&buffer,im, start, end, step, col_cnt, legend_v, data);
+ break;
+ case IF_SSV:
+ r=rrd_xport_format_sv(';',&buffer,im, start, end, step, col_cnt, legend_v, data);
+ break;
+ default:
+ break;
+ }
+ /* restore locale */
+ setlocale(LC_NUMERIC, old_locale);
+ /* handle errors */
+ if (r) {
+ /* free legend */
+ for (unsigned long j = 0; j < col_cnt; j++) {
+ free(legend_v[j]);