void rrd_graph_script(int argc, char *argv[], image_desc_t *im, int optno) { int i; for (i=optind+optno;i<argc;i++) { graph_desc_t *gdp; unsigned int eaten=0; if (gdes_alloc(im)) return; /* the error string is already set */ gdp = &im->gdes[im->gdes_c-1]; #ifdef DEBUG gdp->debug = 1; #endif if (rrd_parse_find_gf(argv[i],&eaten,gdp)) return; switch (gdp->gf) { case GF_SHIFT: /* vname:value */ if (rrd_parse_shift(argv[i],&eaten,gdp,im)) return; break; case GF_XPORT: if (rrd_parse_xport(argv[i],&eaten,gdp,im)) return; break; case GF_PRINT: /* vname:CF:format -or- vname:format */ case GF_GPRINT: /* vname:CF:format -or- vname:format */ if (rrd_parse_print(argv[i],&eaten,gdp,im)) return; break; case GF_COMMENT: /* text */ if (rrd_parse_legend(argv[i],&eaten,gdp)) return; break; case GF_STACK: /* vname-or-value[#color[:legend]] */ #ifdef WITH_PIECHART case GF_PART: /* value[#color[:legend]] */ #endif case GF_VRULE: /* value#color[:legend] */ case GF_HRULE: /* value#color[:legend] */ case GF_LINE: /* vname-or-value[#color[:legend]][:STACK] */ case GF_AREA: /* vname-or-value[#color[:legend]][:STACK] */ case GF_TICK: /* vname#color[:num[:legend]] */ if (rrd_parse_PVHLAST(argv[i],&eaten,gdp,im)) return; break; /* data acquisition */ case GF_DEF: /* vname=x:DS:CF:[:step=#][:start=#][:end=#] */ if (rrd_parse_def(argv[i],&eaten,gdp,im)) return; break; case GF_CDEF: /* vname=rpn-expression */ if (rrd_parse_cdef(argv[i],&eaten,gdp,im)) return; break; case GF_VDEF: /* vname=rpn-expression */ if (rrd_parse_vdef(argv[i],&eaten,gdp,im)) return; break; } if (gdp->debug) { dprintf("used %i out of %i chars\n",eaten,strlen(argv[i])); dprintf("parsed line: '%s'\n",argv[i]); dprintf("remaining: '%s'\n",&argv[i][eaten]); if (eaten >= strlen(argv[i])) dprintf("Command finished successfully\n"); } if (eaten < strlen(argv[i])) { rrd_set_error("Garbage '%s' after command:\n%s", &argv[i][eaten],argv[i]); return; } } }
static graph_desc_t* newGraphDescription(image_desc_t *const im,enum gf_en gf,parsedargs_t* pa,uint64_t bits) { /* check that none of the other bitfield marker is set */ if ((bits&PARSE_FIELD1)&&((bits&(PARSE_FIELD2|PARSE_FIELD3|PARSE_FIELD4)))) { rrd_set_error("newGraphDescription: bad bitfield1 value %08llx",bits);return NULL; } /* the normal handler that adds to img */ if ((!(bits & PARSE_RETRY)) && (gdes_alloc(im))) { return NULL; } /* set gdp */ graph_desc_t *gdp= &im->gdes[im->gdes_c - 1]; /* set some generic things */ gdp->gf=gf; { char *t,*x; long debug=0; if ((t=getKeyValueArgument("debug",1,pa)) && ((getLong(t,&debug,&x,10)))) { rrd_set_error("Bad debug value: %s",t); return NULL; } gdp->debug=debug; } /* and the "flagged" parser implementation * * first the fields with legacy positional args */ #define bitscmp(v) ((bits&v)==v) char* vname=NULL; if (bitscmp(PARSE_VNAME)) { vname=getKeyValueArgument("vname",1,pa); dprintfparsed("got vname: %s\n",vname);} char *rrd=NULL; if (bitscmp(PARSE_RRD)) { rrd=getKeyValueArgument("rrd",1,pa); dprintfparsed("got rrd: %s\n",rrd);} char *ds=NULL; if (bitscmp(PARSE_DS)) { ds=getKeyValueArgument("ds",1,pa); dprintfparsed("got ds: %s\n",ds);} char *cf=NULL; if (bitscmp(PARSE_CF)) { cf=getKeyValueArgument("cf",1,pa); dprintfparsed("got cf: %s\n",cf);} char *color=NULL; if (bitscmp(PARSE_COLOR)) { color=getKeyValueArgument("color",1,pa); dprintfparsed("got color: %s\n",color);} char *color2=NULL; if (bitscmp(PARSE_COLOR2)) { color2=getKeyValueArgument("color2",1,pa); dprintfparsed("got color2: %s\n",color2);} char *rpn=NULL; if (bitscmp(PARSE_RPN)) { rpn=getKeyValueArgument("rpn",1,pa); dprintfparsed("got rpn: %s\n",rpn);} char *legend=NULL; if (bitscmp(PARSE_LEGEND)) { legend=getKeyValueArgument("legend",1,pa); dprintfparsed("got legend: \"%s\"\n",legend);} char *fraction=NULL; if (bitscmp(PARSE_FRACTION)) { fraction=getKeyValueArgument("fraction",1,pa); dprintfparsed("got fraction: %s\n",fraction);} /* * here the ones without delayed assigns (which are for positional parsers) */ if (bitscmp(PARSE_FORMAT)) { char *format=getKeyValueArgument("format",1,pa); if(format) { strncpy(gdp->format,format,FMT_LEG_LEN); dprintfparsed("got format: %s\n",format); } } if (bitscmp(PARSE_STRFTIMEVFMT)) { char *strft=getKeyValueArgument("strftime",1,pa); char *frmtr=getKeyValueArgument("vformatter",1,pa); gdp->strftm=(strft)?1:0; if (frmtr != NULL) { if (strcmp(frmtr,"timestamp") == 0) { gdp->vformatter = VALUE_FORMATTER_TIMESTAMP; } else if (strcmp(frmtr,"duration") == 0) { gdp->vformatter = VALUE_FORMATTER_DURATION; } else { rrd_set_error("Unsupported vformatter: %s", frmtr); return NULL; } } dprintfparsed("got strftime: %s\n",strft); } if (bitscmp(PARSE_STACK)) { char *stack=getKeyValueArgument("stack",1,pa); gdp->stack=(stack)?1:0; dprintfparsed("got stack: %s\n",stack); } if (bitscmp(PARSE_SKIPSCALE)) { char *skipscale=getKeyValueArgument("skipscale",1,pa); gdp->skipscale =(skipscale)?1:0; dprintfparsed("got skipscale: %s\n",skipscale); } if (bitscmp(PARSE_REDUCE)) { char *reduce=getKeyValueArgument("reduce",1,pa); if (reduce) { gdp->cf_reduce=cf_conv(reduce); gdp->cf_reduce_set=1; dprintfparsed("got reduce: %s (%i)\n",reduce,gdp->cf_reduce); if (((int)gdp->cf_reduce)==-1) { rrd_set_error("bad reduce CF: %s",reduce); return NULL; } } } if (bitscmp(PARSE_DAEMON)) { char *daemon=getKeyValueArgument("daemon",1,pa); if (daemon) { strncpy(gdp->daemon,daemon,strlen(daemon)); dprintfparsed("got daemon: %s\n", gdp->daemon); } } if (bitscmp(PARSE_XAXIS)) { long xaxis=0; char *t,*x; if ((t=getKeyValueArgument("xaxis",1,pa)) && ((getLong(t,&xaxis,&x,10))||(xaxis<1)||(xaxis>MAX_AXIS))) { rrd_set_error("Bad xaxis value: %s",t); return NULL; } dprintfparsed("got xaxis: %s (%li)\n",t,xaxis); gdp->xaxisidx=xaxis; } if (bitscmp(PARSE_YAXIS)) { long yaxis=0; char *t,*x; if ((t=getKeyValueArgument("yaxis",1,pa)) && ((getLong(t,&yaxis,&x,10))||(yaxis<1)||(yaxis>MAX_AXIS))) { rrd_set_error("Bad yaxis value: %s",t); return NULL; } dprintfparsed("got yaxis: %s (%li)\n",t,yaxis); gdp->yaxisidx=yaxis; } if (bitscmp(PARSE_LINEWIDTH)) { double linewidth = 1; char *t,*x; if ((t=getKeyValueArgument("linewidth",1,pa))&&(*t!=0)) { if ((getDouble(t,&linewidth,&x))||(linewidth<=0)) { rrd_set_error("Bad line width: %s",t); return NULL; } } dprintfparsed("got linewidth: %s (%g)\n",t,linewidth); gdp->linewidth=linewidth; } if (bitscmp(PARSE_GRADHEIGHT)) { double gradheight=0; char *t,*x; if ((t=getKeyValueArgument("gradheight",1,pa))&&(*t!=0)) { if (getDouble(t,&gradheight,&x)) { rrd_set_error("Bad gradheight: %s",t); return NULL; } dprintfparsed("got gradheight: %s (%g)\n",t,gradheight); gdp->gradheight=gradheight; } } if (bitscmp(PARSE_STEP)) { long step=0; char *t,*x; if ((t=getKeyValueArgument("step",1,pa)) && ((getLong(t,&step,&x,10))||(step<1))) { rrd_set_error("Bad step value: %s",t); return NULL; } dprintfparsed("got step: %s (%li)\n",t,step); gdp->step=step; } if ((bitscmp(PARSE_START)||bitscmp(PARSE_END))) { /* these should get done together to use the start/end code correctly*/ char* parsetime_error; /* first start */ char* start; rrd_time_value_t start_tv; start_tv.type = ABSOLUTE_TIME; start_tv.offset = 0; localtime_r(&gdp->start, &start_tv.tm); if (bitscmp(PARSE_START)) { start=getKeyValueArgument("start",1,pa); if ((start)&&(parsetime_error = rrd_parsetime(start, &start_tv))) { rrd_set_error("start time: %s", parsetime_error);return NULL; } dprintfparsed("got start: %s\n",start); } else { start = NULL; } /* now end */ char* end; rrd_time_value_t end_tv; end_tv.type = ABSOLUTE_TIME; end_tv.offset = 0; localtime_r(&gdp->end, &end_tv.tm); if (bitscmp(PARSE_END)) { end=getKeyValueArgument("end",1,pa); if ((end)&&(parsetime_error = rrd_parsetime(end, &end_tv))) { rrd_set_error("end time: %s", parsetime_error); return NULL; } dprintfparsed("got end: %s\n",end); } else { end = NULL; } /* and now put the pieces together (relative times like start=end-2days) */ time_t start_tmp = 0, end_tmp = 0; if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { return NULL; } dprintfparsed("got start %s translated to: %lld\n",start,(long long int)start_tmp); dprintfparsed("got end %s translated to: %lld\n",end,(long long int)end_tmp); /* check some ranges */ if (start_tmp < 3600 * 24 * 365 * 10) { rrd_set_error("the first entry to fetch should be " "after 1980 (%ld)", start_tmp); return NULL; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return NULL; } /* and finally set it irrespectively of if it has been set or not * it may have been a relative time and if you just set it partially * then that is wrong... */ gdp->start = start_tmp; gdp->start_orig = start_tmp; gdp->end = end_tmp; gdp->end_orig = end_tmp; } if (bitscmp(PARSE_DASHES)) { char* dashes=getKeyValueArgument("dashes",1,pa); /* if we got dashes */ if (dashes) { gdp->dash = 1; gdp->offset = 0; /* count the , in dashes */ int cnt=0;for(char*t=dashes;(*t)&&(t=strchr(t,','));t++,cnt++) {;} dprintfparsed("Got dashes argument: %s with %i comma\n",dashes,cnt); /* now handle */ gdp->ndash = cnt+1; gdp->p_dashes = (double *) malloc(sizeof(double)*(gdp->ndash+1)); /* now loop dashes */ for(int i=0;i<gdp->ndash;i++) { char *x; int f=getDouble(dashes,&gdp->p_dashes[i],&x); if(f<0) { rrd_set_error("Could not parse number: %s",dashes); return NULL; } /* we should have this most of the time */ dprintfparsed("Processed %s to %g at index %i\n",dashes,gdp->p_dashes[i],i); if (f>0) { if (*x!=',') { rrd_set_error("expected a ',' at : %s",x); return NULL;} dashes=x+1; } if ((f==0)&&(i!=gdp->ndash-1)) { rrd_set_error("unexpected end at : %s",dashes); return NULL;} } } char* dashoffset=getKeyValueArgument("dash-offset",1,pa); if (dashoffset) { char* x; if (getDouble(dashoffset,&gdp->offset,&x)) { rrd_set_error("Could not parse dash-offset: %s",dashoffset); return NULL; } } } /* here now the positional(=legacy) parsers which are EXCLUSIVE - SO ELSE IF !!! * we also only parse the extra here and assign just further down * TODO maybe we can generalize this a bit more... */ if (bitscmp(PARSE_VNAMERRDDSCF)) { if ((!vname)||(!rrd)) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional vname and rrd: %s - %s\n",first->key,first->value); if (!vname) {vname=first->key;} if (!rrd) {rrd=first->value; } } /* and now look for datasource */ if (!ds) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of DS in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional ds: %s - \n",first->value); ds=first->value; } /* and for CF */ if (!cf) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of CF in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional cf: %s - \n",first->value); cf=first->value; } } else if (bitscmp(PARSE_VNAMECOLORLEGEND)) { /* vname */ if (!vname) { keyvalue_t* first=getFirstUnusedArgument(1,pa); if (first) { vname=first->value; } else { rrd_set_error("No positional VNAME"); return NULL; } } /* fraction added into the parsing mix for TICK */ if ((bitscmp(PARSE_VNAMECOLORFRACTIONLEGEND))&&(!fraction)) { keyvalue_t* first=getFirstUnusedArgument(1,pa); if (first) { fraction=first->value; } else { rrd_set_error("No positional FRACTION"); return NULL; } } /* legend (it's optional if no other arguments follow)*/ if (!legend) { keyvalue_t* first=getFirstUnusedArgument(1,pa); if (first) { legend=first->keyvalue; dprintfparsed("got positional legend: %s - \n",legend); } } } else if (bitscmp(PARSE_VNAMERPN)) { if ((!vname)||(!rpn)) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional vname and rpn: %s - %s\n",first->key,first->value); if (!vname) {vname=first->key;} if (!rpn) {rpn=first->value; } } } else if (bitscmp(PARSE_VNAMEREFPOS)) { if ((!vname)) { /* get the first unused argument */ keyvalue_t* first=getFirstUnusedArgument(1,pa); if (!first) { rrd_set_error("No argument for definition of vdef/rrd in %s",pa->arg_orig); return NULL; } dprintfparsed("got positional vname and rrd: %s - %s\n",first->key,first->value); if (!vname) {vname=first->value;} } } /* and set some of those late assignments to accommodate the legacy parser*/ /* first split vname into color */ if (vname) { /* check for color */ char *h1=strchr(vname,'#'); char* h2=NULL; if (h1) { *h1=0;h1++; dprintfparsed("got positional color: %s - \n",h1); h2=strchr(h1,'#'); if (h2) { *h2=0;h2++; dprintfparsed("got positional color2: %s - \n",h2); } } if (bitscmp(PARSE_COLOR) && (! color) && (h1)) { color=h1;} if (bitscmp(PARSE_COLOR2) && (! color2) && (h2)) { color2=h2;} } /* check if we are reusing the vname */ if (vname) { int idx=find_var(im, vname); dprintfparsed("got positional index %i for %s - \n",idx,vname); /* some handling */ if (bitscmp(PARSE_VNAMEDEF)) { if (idx>=0) { rrd_set_error("trying to reuse vname %s",vname); return NULL; } } else if (bitscmp(PARSE_VNAMEREF)) { gdp->vidx=idx; if (idx < 0){ if (bitscmp(PARSE_VNAMEREFNUM)) { double val; char *x; int f=getDouble(vname,&val,&x); if (f) { rrd_set_error("%s is not a vname nor a number",vname); return NULL; } if (gf==GF_VRULE){ gdp->xrule=val; } else { gdp->yrule=val; } } else { rrd_set_error("vname %s not found",vname); return NULL; } } } } /* and assign it */ if (vname) { strncpy(gdp->vname,vname,MAX_VNAME_LEN); gdp->vname[MAX_VNAME_LEN] = '\0'; } if (rrd) { strncpy(gdp->rrd,rrd, 1023); gdp->rrd[1023] = '\0'; } if (ds) { strncpy(gdp->ds_nam,ds,DS_NAM_SIZE - 1); gdp->ds_nam[DS_NAM_SIZE - 1] = '\0'; } if (cf) { gdp->cf=cf_conv(cf); if (((int)gdp->cf)==-1) { rrd_set_error("bad CF: %s",cf); return NULL; } } else { if (bitscmp(PARSE_CF)) { gdp->cf = (enum cf_en) -1; }} if ((color)&&(parse_color(color,&(gdp->col)))) { return NULL; } if ((color2)&&(parse_color(color2,&(gdp->col2)))) { return NULL; } if (rpn) {gdp->rpn=rpn;} if ((legend)&&(*legend!=0)) { /* and copy it into place */ strncpy(gdp->legend,legend,FMT_LEG_LEN); } if (fraction) { if (strcmp(fraction,"vname")==0) { /* check that vname is really a DEF|CDEF */ if (im->gdes[gdp->vidx].gf != GF_DEF && im->gdes[gdp->vidx].gf != GF_CDEF) { rrd_set_error("variable '%s' not DEF nor CDEF when using dynamic fractions", gdp->vname); return NULL; } /* add as flag to use (c)?def */ gdp->cf=CF_LAST; gdp->yrule=0.5; } else { /* parse number */ double val; char *x; int f=getDouble(fraction,&val,&x); if (f) { rrd_set_error("error parsing number %s",vname); return NULL; } gdp->yrule=val; } } /* remember the index for faster varfind */ char *key = gdes_fetch_key((*gdp)); if (gdp->gf == GF_DEF && !g_hash_table_lookup_extended(im->rrd_map,key,NULL,NULL)){ dprintfhash("ins key %s - %ld\n",key,im->gdes_c-1); g_hash_table_insert(im->gdef_map,g_strdup(key),GINT_TO_POINTER(im->gdes_c-1)); } free(key); if (gdp->gf == GF_DEF || gdp->gf == GF_VDEF || gdp->gf == GF_CDEF){ dprintfhash("ins vname %s - %ld\n",gdp->vname,im->gdes_c-1); g_hash_table_insert(im->gdef_map,g_strdup(gdp->vname),GINT_TO_POINTER(im->gdes_c-1)); } return gdp; }
/* mostly rrd_graph(), just pushed a bit here and stretched a bit there */ int rrd_xport(int argc, char **argv, int *xsize, time_t *start, time_t *end, /* which time frame do you want ? * will be changed to represent reality */ unsigned long *step, /* which stepsize do you want? * will be changed to represent reality */ unsigned long *col_cnt, /* number of data columns in the result */ char ***legend_v, /* legend entries */ rrd_value_t **data) /* two dimensional array containing the data */ { image_desc_t im; int i; long long_tmp; time_t start_tmp=0,end_tmp=0; char symname[100]; long scancount; struct rrd_time_value start_tv, end_tv; char *parsetime_error = NULL; parsetime("end-24h", &start_tv); parsetime("now", &end_tv); /* use the default values from rrd_graph.c */ im.xlab_user.minsec = -1; im.xgif=0; im.ygif=0; im.xsize = 400; im.ysize = 100; im.step = 0; im.ylegend[0] = '\0'; im.title[0] = '\0'; im.minval = DNAN; im.maxval = DNAN; im.interlaced = 0; im.unitsexponent= 9999; im.unitslength= 9; im.extra_flags= 0; im.rigid = 0; im.imginfo = NULL; im.lazy = 0; im.logarithmic = 0; im.ygridstep = DNAN; im.draw_x_grid = 1; im.draw_y_grid = 1; im.base = 1000; im.prt_c = 0; im.gdes_c = 0; im.gdes = NULL; im.imgformat = IF_GIF; /* we default to GIF output */ while (1) { static struct option long_options[] = { {"start", required_argument, 0, 's'}, {"end", required_argument, 0, 'e'}, {"maxrows", required_argument, 0, 'm'}, {"step", required_argument, 0, 261}, {0,0,0,0} }; int option_index = 0; int opt; opt = getopt_long(argc, argv, "s:e:m:", long_options, &option_index); if (opt == EOF) break; switch(opt) { case 261: im.step = atoi(optarg); break; case 's': if ((parsetime_error = parsetime(optarg, &start_tv))) { rrd_set_error( "start time: %s", parsetime_error ); return -1; } break; case 'e': if ((parsetime_error = parsetime(optarg, &end_tv))) { rrd_set_error( "end time: %s", parsetime_error ); return -1; } break; case 'm': long_tmp = atol(optarg); if (long_tmp < 10) { rrd_set_error("maxrows below 10 rows"); return -1; } im.xsize = long_tmp; break; case '?': if (optopt != 0) rrd_set_error("unknown option '%c'", optopt); else rrd_set_error("unknown option '%s'",argv[optind-1]); return -1; } } /* if (optind >= argc) { rrd_set_error("missing filename"); return -1; } */ if (proc_start_end(&start_tv,&end_tv,&start_tmp,&end_tmp) == -1) { return -1; } if (start_tmp < 3600*24*365*10) { rrd_set_error("the first entry to fetch should be after 1980 (%ld)",start_tmp); return -1; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return -1; } im.start = start_tmp; im.end = end_tmp; for(i=optind; i<argc; i++) { int argstart=0; int strstart=0; char varname[30],*rpnex; gdes_alloc(&im); if(sscanf(argv[i],"%10[A-Z0-9]:%n",symname,&argstart)==1) { if((im.gdes[im.gdes_c-1].gf=gf_conv(symname))==-1) { im_free(&im); rrd_set_error("unknown function '%s'",symname); return -1; } } else { rrd_set_error("can't parse '%s'",argv[i]); im_free(&im); return -1; } switch(im.gdes[im.gdes_c-1].gf) { case GF_CDEF: if((rpnex = malloc(strlen(&argv[i][argstart])*sizeof(char)))==NULL) { rrd_set_error("malloc for CDEF"); return -1; } if(sscanf( &argv[i][argstart], DEF_NAM_FMT "=%[^: ]", im.gdes[im.gdes_c-1].vname, rpnex) != 2) { im_free(&im); free(rpnex); rrd_set_error("can't parse CDEF '%s'",&argv[i][argstart]); return -1; } /* checking for duplicate DEF CDEFS */ if(find_var(&im,im.gdes[im.gdes_c-1].vname) != -1) { im_free(&im); rrd_set_error("duplicate variable '%s'", im.gdes[im.gdes_c-1].vname); return -1; } if((im.gdes[im.gdes_c-1].rpnp = str2rpn(&im,rpnex))== NULL) { rrd_set_error("invalid rpn expression '%s'", rpnex); im_free(&im); return -1; } free(rpnex); break; case GF_DEF: if (sscanf( &argv[i][argstart], DEF_NAM_FMT "=%n", im.gdes[im.gdes_c-1].vname, &strstart)== 1 && strstart) { /* is the = did not match %n returns 0 */ if(sscanf(&argv[i][argstart +strstart +scan_for_col(&argv[i][argstart+strstart], MAXPATH,im.gdes[im.gdes_c-1].rrd)], ":" DS_NAM_FMT ":" CF_NAM_FMT, im.gdes[im.gdes_c-1].ds_nam, symname) != 2) { im_free(&im); rrd_set_error("can't parse DEF '%s' -2",&argv[i][argstart]); return -1; } } else { im_free(&im); rrd_set_error("can't parse DEF '%s'",&argv[i][argstart]); return -1; } /* checking for duplicate DEF CDEFS */ if (find_var(&im,im.gdes[im.gdes_c-1].vname) != -1) { im_free(&im); rrd_set_error("duplicate variable '%s'", im.gdes[im.gdes_c-1].vname); return -1; } if((im.gdes[im.gdes_c-1].cf=cf_conv(symname))==-1) { im_free(&im); rrd_set_error("unknown cf '%s'",symname); return -1; } break; case GF_XPORT: if((scancount=sscanf( &argv[i][argstart], "%29[^:]:%n", varname, &strstart))>=1) { if(strstart <= 0) { im.gdes[im.gdes_c-1].legend[0] = '\0'; } else { scan_for_col(&argv[i][argstart+strstart],FMT_LEG_LEN,im.gdes[im.gdes_c-1].legend); } if((im.gdes[im.gdes_c-1].vidx=find_var(&im,varname))==-1) { im_free(&im); rrd_set_error("unknown variable '%s'",varname); return -1; } } else { im_free(&im); rrd_set_error("can't parse '%s'",&argv[i][argstart]); return -1; } break; default: break; } } if (im.gdes_c == 0) { rrd_set_error("can't make a graph without contents"); im_free(&im); return(-1); } if (rrd_xport_fn(&im, start, end, step, col_cnt, legend_v, data) == -1) { im_free(&im); return -1; } im_free(&im); return 0; }