/****************************************************************/ /* */ /* rdlog2.c (see readme.html for program explanation */ /* */ /* author : Philippe Simonet, sip00@vg.swissptt.ch */ /* */ /* change log : */ /* */ /* v. 1.00 : initial update (SIP) (02.12.97 */ /* */ /* */ /* */ /************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include "gd.h" #include "gdfonts.h" #define FALSE 0 #define TRUE 1 #define TEXT 1 #define RECT 2 #define POLY 3 #define COLOR 4 #define COLORDEF 5 #define LINK 6 #define COMPOUND 7 #define ENDCOMPOUND 8 #define GIFAREA 9 #define URL 10 #define IN 11 #define OUT 12 #define INOUT 13 #define UNKNOWN 99 #ifndef max #define max(a,b) ((a)>(b))?(a):(b) #endif #ifndef min #define min(a,b) ((a)<(b))?(a):(b) #endif int colorratetable[256]; int colortable[256] = { 0x000000, /* 0 BLACK */ 0xff0000, /* 1 BLUE */ 0x00ff00, /* 2 GREEN*/ 0xffff00, /* 3 CYAN */ 0x0000ff, /* 4 RED */ 0xff00ff, /* 5 MAGENTA */ 0x00ffff, /* 6 YELLOW */ 0xffffff, /* 7 WHITE */ 0x900000, /* 8 Blue4 */ 0xb00000, /* 9 Blue3 */ 0xd00000, /* 10 Blue2 */ 0xffce87, /* 11 LtBlue */ 0x009000, /* 12 Green4 */ 0x00b000, /* 13 Green3 */ 0x00d000, /* 14 Green2 */ 0x909000, /* 15 Cyan4 */ 0xb0b000, /* 16 Cyan3 */ 0xd0d000, /* 17 Cyan2 */ 0x000090, /* 18 Red4 */ 0x0000b0, /* 19 Red3 */ 0x0000d0, /* 20 Red2 */ 0x900090, /* 21 Magenta4 */ 0xb000b0, /* 22 Magenta3 */ 0xd000d0, /* 23 Magenta2 */ 0x003080, /* 24 Brown4 */ 0x0040a0, /* 25 Brown3 */ 0x0060c0, /* 26 Brown2 */ 0x8080ff, /* 27 Pink4 */ 0xa0a0ff, /* 28 Pink3 */ 0xc0c0ff, /* 29 Pink2 */ 0xe0e0ff, /* 30 Pink */ 0x00d7ff /* 31 gold */ }; /************************************************************************/ /* each of these entry contain the description of a graphical object */ struct sentry { int type; /* text, line, link, poly */ int depth; /* order in which it appears */ char * str; /* log file name, url, text */ int maxrate; /* max xfer rate */ int rate; /* max xfer rate */ int orientation; /* text orientation, ... */ int color; /* color */ int fillcolor; /* color */ int colorindex; /* color index */ int npoints; /* fig size */ int * coords; /* coordinates list */ struct sentry * next; /* next entry */ }; int xsize, ysize, rounds, xoffset, yoffset; struct sentry * pfirstentry, *pcurrententry, *pareaentry; /************************************************************************/ /* analyze command-line options */ static int optind = 0; /* Global argv index. */ static char *scan = NULL; /* Private scan pointer. */ static int scale = 15; int getopt1( int argc, char *argv[], char *optstring, char ** optarg ) { int c; /* return value */ char *place; char *index(); *optarg = NULL; /* check argument validity */ if (scan == NULL || *scan == '\0') { if (optind == 0) optind++; if (optind >= argc) return EOF; place = argv[optind]; if (place[0] != '-' || place[1] == '\0') return EOF; optind++; if (place[1] == '-' && place[2] == '\0') return EOF; scan = place+1; } c = *scan++; /* get option character */ place = strchr(optstring, c); if (place == NULL || c == ':') return '?'; /* set optarg if needed */ if (*++place == ':') { if (*scan != '\0') { *optarg = scan; scan = NULL; } else { *optarg = argv[optind], optind++; } } return c; } /************************************************************************/ /* computes a traffic in % by reading 'rounds' lines in a MRTG log file */ /* currently, it takes the maximum of the In or OUT traffic. */ void read_entry ( struct sentry * pentry) { FILE * logf; int i, j=0, k=0; logf = fopen ( pentry->str, "r" ); if ( pentry->maxrate == 0 ) { fprintf ( stderr, "Max rate for %s is null.\n", pentry->str ); return; } if ( logf != NULL ) { fscanf(logf, "%*d %d %d", &j, &k); /* get first line */ for ( i = 0; i < rounds; i ++ ) { /* computes mean */ fscanf(logf, "%*d %d %d %*d %*d", &j, &k); /* get line */ /*printf(" - [%d %d]\n", j, k);*/ switch (pentry->orientation) { case IN: pentry->rate += j; break; case OUT: pentry->rate += k; break; default: if ( j > k ) pentry->rate += j; else pentry->rate += k; break; } } /* computes the rate 0-9 */ pentry->rate = pentry->rate / rounds; /*printf ( "%s : %u, %u.\n", pentry->str, (pentry->maxrate*100)/pentry->maxrate, (pentry->rate*10)/pentry->maxrate );*/ pentry->rate = (pentry->rate * 10) / pentry->maxrate; if ( pentry->rate > 9 ) pentry->rate = 9; if ( pentry->rate < 0 ) pentry->rate = 0; fclose ( logf ); } else { fprintf ( stderr, "Cannot open file %s.\n", pentry->str ); }; } /************************************************************************/ /* in case of trouble ... */ void print_error ( void ) { fprintf ( stderr, "Read mrtg configuration files and convert them in gif format.\n" ); fprintf ( stderr, "Use :\n" ); fprintf ( stderr, " rdlog -i cfile -o gfile [-m mapfile] -r rounds\n" ); fprintf ( stderr, " ifile : input fig file name,\n" ); fprintf ( stderr, " gfile : output gif file (will be overwritten),\n" ); fprintf ( stderr, " mapfile : output map file (optional, will be overwritten),\n" ); fprintf ( stderr, " rounds : number of 5 min intervals to take.\n" ); } /************************************************************************/ /* free an 'entry' variable */ void free_entry (struct sentry * pentry) { if ( pentry!= NULL ) { if ( pentry->str != NULL ) free(pentry->str); pentry->str = NULL; if ( pentry->coords != NULL ) free(pentry->coords); pentry->coords = NULL; free(pentry); } } /************************************************************************/ /* print an entry for debug purpose */ void print_entry (struct sentry * pentry) { printf ( "Entry : " ); if ( pentry->str != NULL ) printf ( "str '%s' ", pentry->str ); printf ( ".\n type %i, maxrate %i, orientation %i, npoints %i, color %i, depth %i.\n", pentry->type,pentry->maxrate,pentry->orientation,pentry->npoints,pentry->color,pentry->depth ); } /************************************************************************/ int new_entry( void ) { struct sentry * pentry; if ( ( pentry = malloc ( sizeof (struct sentry) )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); return ( FALSE ); } if ( pfirstentry == NULL ) { pfirstentry = pentry; } else { pcurrententry->next = pentry; } pentry->type = UNKNOWN; pentry->str = NULL; pentry->maxrate = 0; pentry->rate = 0; pentry->orientation = 0; pentry->color = 0; pentry->fillcolor = 0; pentry->depth = 0; pentry->colorindex = 0; pentry->npoints = 0; pentry->coords = NULL; pentry->next = NULL; pcurrententry = pentry; return ( TRUE ); } /************************************************************************/ #define r(color) ((color&0x0000ff)>>0) #define g(color) ((color&0x00ff00)>>8) #define b(color) ((color&0xff0000)>>16) #define rgb(color) ((color&0x0000ff)>>0),((color&0x00ff00)>>8),((color&0xff0000)>>16) /************************************************************************/ /* build a color or find the nearest color in the color table */ int find_color ( gdImagePtr graph, int color ) { int i_col; if ( (i_col = gdImageColorExact(graph,r(color), g(color), b(color))) == -1 ) { if ( (i_col = gdImageColorAllocate(graph,r(color), g(color), b(color))) == -1 ) { i_col = gdImageColorClosest(graph,r(color), g(color), b(color)); } } return (i_col); } /************************************************************************/ /* draw the gif file, based on the tentry desciption */ void draw_gif ( FILE * gif ) { #define c_blank 245,245,245 /* base colors */ #define c_light 194,194,194 #define c_dark 100,100,100 #define c_black 0,0,0 #define c_white 255,255,0 gdImagePtr graph; int i_light,i_dark,i_blank, i_black, i_white; int bkcolor; graph = gdImageCreate(xsize, ysize); /* the first color allocated will be the background color. */ bkcolor = colortable[pareaentry->fillcolor]; i_blank = gdImageColorAllocate(graph,rgb(bkcolor)); i_light = gdImageColorAllocate(graph,c_light); i_dark = gdImageColorAllocate(graph,c_dark); gdImageInterlace(graph, 1); i_black = gdImageColorAllocate(graph,c_black); i_white = gdImageColorAllocate(graph,c_white); /* draw the image border */ gdImageLine(graph,0,0,xsize-1,0,i_light); gdImageLine(graph,1,1,xsize-2,1,i_light); gdImageLine(graph,0,0,0,ysize-1,i_light); gdImageLine(graph,1,1,1,ysize-2,i_light); gdImageLine(graph,xsize-1,0,xsize-1,ysize-1,i_dark); gdImageLine(graph,0,ysize-1,xsize-1,ysize-1,i_dark); gdImageLine(graph,xsize-2,1,xsize-2,ysize-2,i_dark); gdImageLine(graph,1,ysize-2,xsize-2,ysize-2,i_dark); { /* date the graph */ struct tm *newtime; time_t aclock; time( &aclock ); /* Get time in seconds */ newtime = localtime( &aclock ); /* Convert time to struct */ /* tm form */ gdImageString(graph, gdFontSmall,3,3,asctime( newtime ),i_dark); }; while ( 1 ) { int i_col, i_col2, depth; struct sentry * pentry; /* find smallest depth */ pentry = pfirstentry; depth = -1; while ( pentry != NULL ) { if (pentry->depth > depth) { depth = pentry->depth; pcurrententry = pentry; } pentry = pentry->next; } if ( depth == -1 ) break; pcurrententry->depth = -1; /* draw this fig */ switch ( pcurrententry->type) { case RECT: i_col = find_color(graph, colortable[pcurrententry->color]); if ( pcurrententry->fillcolor != -1 ) { i_col2 = find_color(graph, colortable[pcurrententry->fillcolor]); gdImageFilledRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col2); } gdImageRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col); break; case TEXT: i_col = find_color(graph, colortable[pcurrententry->color]); if (pcurrententry->orientation == 0) { gdImageString(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); } else { gdImageStringUp(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); } break; case POLY: case LINK: { int x = pcurrententry->coords[0]; int y = pcurrententry->coords[1]; int x2, y2, j, k; gdImagePtr brush_2pix; if (pcurrententry->type == POLY) { i_col = find_color(graph, colortable[pcurrententry->color]); } else { brush_2pix = gdImageCreate(2,2); gdImageColorAllocate( brush_2pix, r(colortable[colorratetable[pcurrententry->rate]]), g(colortable[colorratetable[pcurrententry->rate]]), b(colortable[colorratetable[pcurrententry->rate]]) ); gdImageSetBrush(graph, brush_2pix); i_col = gdBrushed; } k = 2; for ( j = 1; j < pcurrententry->npoints; j ++ ) { x2 = pcurrententry->coords[k++]; y2 = pcurrententry->coords[k++]; gdImageLine(graph, x, y, x2, y2,i_col); x = x2; y = y2; }; if (pcurrententry->type == LINK) { gdImageDestroy(brush_2pix); }; } break; default: break; } pcurrententry = pcurrententry->next; } gdImageGif(graph, gif); gdImageDestroy(graph); } struct sfigrec { int type; char text[500]; int colorindex; int depth; int color; int fillcolor; int angle; int coords[500]; int npoints; }; /************************************************************************/ int getfig ( FILE * config, struct sfigrec * fig ) { char buf[1000], str[1000], *s; int i, n, type, color, colorindex, depth, pen_style, font, flags, x, y; int style, thickness, pen_color, fill_color, fill_style, join_style, cap_style, radius, fa, ba, npts; float tx_size, angle, style_val; fig->type = UNKNOWN; if ( fgets (buf, 1000, config ) == NULL ) { return ( TRUE ); } switch ( buf[0] ) { case '0': /* color ref */ n = sscanf(buf, "%*d %d #%06x", &colorindex, &color ); /*printf ( "colordef : %d, %d.\n", colorindex, color );*/ fig->type = COLORDEF; fig->color = ((color & 0xff0000)>>16) | (color & 0x00ff00) | ((color & 0x0000ff)<<16); fig->colorindex = colorindex; break; case '2': /* polyline */ n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%f%d%d%d%d%d%d", &type, &style, &thickness, &pen_color, &fill_color, &depth, &pen_style, &fill_style, &style_val, &join_style, &cap_style, &radius, &fa, &ba, &npts); /*puts ( buf );*/ /*printf ("type %d, style %d, thickness %d, pen_color %d, fill_color %d, depth %d, pen_style %d, fill_style %d, style_val %f, join_style %d, cap_style %d, radius %d, fa %d, ba %d, npts %d ", type, style, thickness, pen_color, fill_color, depth, pen_style, fill_style, style_val, join_style, cap_style, radius, fa, ba, npts);*/ fig->depth = depth; fig->color = pen_color; fig->npoints = npts; for ( i = 0; i < npts; i ++ ) { fscanf(config, "%d%d", &x, &y); fig->coords[i*2] = x; fig->coords[i*2+1] = y; /*printf ( "[%d %d] ", x, y );*/ } fig->type = POLY; if ( type == 2 ) { /* rectangle */ fig->type = RECT; if ( fill_style == -1 ) { fig->fillcolor = -1; } else { fig->fillcolor = fill_color; } x = min(fig->coords[0],fig->coords[4]); y = min(fig->coords[1],fig->coords[5]); fig->coords[2] = max(fig->coords[0],fig->coords[4]); fig->coords[3] = max(fig->coords[1],fig->coords[5]); fig->coords[0] = x; fig->coords[1] = y; fig->npoints = 2; } /*printf ( ".\n" );*/ break; case '4': /* text */ n = sscanf(buf, "%*d%d%d%d%d%d%f%f%d%*f%*f%d%d %[^\n]", &type, &color, &depth, &pen_style, &font, &tx_size, &angle, &flags, &x, &y, str); s = strstr ( str, "\\001" ); if ( s != NULL ) s[0] = 0; /*printf ( "text : type %d, color %d, depth %d, pen_style %d, font %d, ty_size %f, angle %f, flags %d, x %d, y %d, s [%s].\n", type, color, depth, pen_style, font, tx_size, angle, flags, x, y, str );*/ fig->type = TEXT; strcpy (fig->text, str); fig->depth = depth; fig->color = color; if ( angle < 1) { fig->angle = 0; fig->coords[0] = x; fig->coords[1] = y-150; } else { fig->angle = 1; fig->coords[0] = x-150; fig->coords[1] = y; } fig->npoints = 1; break; case '6': /* compound */ fig->type = COMPOUND; /*printf ( "compound.\n" );*/ break; case '-': /* compound end */ fig->type = ENDCOMPOUND; /*printf ( "end of compound.\n" );*/ break; default: break; } return ( FALSE ); } /************************************************************************/ void main ( int argc, char * argv[] ) { FILE *config = NULL, *gif = NULL, *map = NULL; char *sconfig = NULL, *sgif = NULL, *smap = NULL; char *optarg; int i; /* globals */ xsize = 100, ysize = 100; rounds = 6; do { /***************************************************************/ /* 0 : read program arguments */ while ( ( i = getopt1( argc, argv, "o:i:r:m:", &optarg ) ) != EOF ) { switch ( i ) { case 'i': sconfig = optarg; break; case 'o': sgif = optarg; break; case 'm': smap = optarg; break; case 'r': rounds = atoi (optarg); if ( rounds < 1 ) { print_error(); exit (0); }; break; case '?': print_error(); exit (0); break; default: break; } } if ( sconfig == NULL || sgif == NULL ) { print_error(); break; } /***************************************************************/ /* 1 : OPEN FILES */ config = fopen ( sconfig, "r" ); if ( config == NULL ) { fprintf ( stderr, "Error opening %s.\n", sconfig ); break; } gif = fopen ( sgif, "wb" ); if ( gif == NULL ) { fprintf ( stderr, "Error opening %s.\n", sgif ); fclose ( config ); break; } if ( smap != NULL ) { map = fopen ( smap, "w" ); if ( map == NULL ) { fprintf ( stderr, "Error opening %s.\n", sgif ); fclose ( config ); fclose ( gif ); break; } fprintf ( map, " <map name=\"map1\">\n" ); } /***************************************************************/ /* 2 : SCAN CONFIG FILE */ pcurrententry = NULL; pfirstentry = NULL; pareaentry = NULL; for ( i = 0; i < 256; i++ ) { colorratetable[i] = 0; } for ( i = 32; i < 256; i++ ) { colortable[i] = 0; } while ( TRUE ) { struct sfigrec figrec; /********************************************/ /* get one fig record */ if ( getfig ( config, &figrec ) == TRUE ) break; switch (figrec.type) { case COLORDEF: if ( figrec.colorindex < 256 ) colortable[figrec.colorindex] = figrec.color; /*printf ( "color table[%i] : %i.\n", figrec.colorindex, colortable[figrec.colorindex] );*/ break; case TEXT: if ( new_entry() == FALSE ) break; pcurrententry->type = UNKNOWN; pcurrententry->color = figrec.color; pcurrententry->depth = figrec.depth; if ( strncmp("color:", figrec.text, 6 ) == 0 ) { /* special 'color:' text */ i = atoi ( figrec.text+6 ); if ( i < 256 ) colorratetable[i] = figrec.color; /*printf ( "color rate[%i] : %i.\n", i, colorratetable[i] );*/ break; } if ( (pcurrententry->str = malloc ( strlen(figrec.text) + 1 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } if ( (pcurrententry->coords = (int *)malloc(figrec.npoints * (sizeof (int)) * 2 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->type = TEXT; pcurrententry->npoints = figrec.npoints; pcurrententry->orientation = figrec.angle; strcpy (pcurrententry->str,figrec.text); memcpy (pcurrententry->coords,figrec.coords,figrec.npoints * (sizeof (int)) * 2); break; case POLY: case RECT: if ( new_entry() == FALSE ) break; pcurrententry->type = UNKNOWN; pcurrententry->depth = figrec.depth; pcurrententry->color = figrec.color; pcurrententry->fillcolor = figrec.fillcolor; if ( (pcurrententry->coords = (int *)malloc(figrec.npoints * (sizeof (int)) * 2 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); continue; } pcurrententry->type = figrec.type; pcurrententry->npoints = figrec.npoints; memcpy (pcurrententry->coords,figrec.coords,figrec.npoints * (sizeof (int)) * 2); break; case COMPOUND: /* compound must be links ... */ if ( new_entry() == FALSE ) break; do { if ( getfig ( config, &figrec ) == TRUE ) break; if ( figrec.type == ENDCOMPOUND ) break; if ( figrec.type == TEXT ) { /*printf (" txt %s.\n", figrec.text );*/ if ( strncmp("gifarea", figrec.text, 7 ) == 0 ) { pcurrententry->type = GIFAREA; pareaentry = pcurrententry; /*printf ( " gifarea : [%i / %i] ", pcurrententry->coords[0], pcurrententry->coords[1]); printf ( " [%i / %i].\n", pcurrententry->coords[2], pcurrententry->coords[3]);*/ } else if ( strncmp("url:", figrec.text, 4 ) == 0 ) { if ( (pcurrententry->str = malloc ( strlen(figrec.text) + 1 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->type = URL; strcpy (pcurrententry->str,figrec.text+4); /*printf (" url %s.\n", pcurrententry->str );*/ } else if ( strncmp("log:", figrec.text, 4 ) == 0 ) { char * s = figrec.text + 4; if ( s[0] == '>' ) { pcurrententry->orientation = OUT; s++; } else if ( s[0] == '<' ) { pcurrententry->orientation = IN; s++; } else { pcurrententry->orientation = INOUT; } if ( (pcurrententry->str = malloc ( strlen(s) + 1 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->type = LINK; strcpy (pcurrententry->str,s); /*printf (" str %s.\n", pcurrententry->str );*/ } else if ( strncmp("speed:", figrec.text, 6 ) == 0 ) { pcurrententry->maxrate = atoi ( figrec.text+6 ); /*printf (" max rate : %i.\n", pcurrententry->maxrate );*/ } } if ( (figrec.type == POLY) || (figrec.type == RECT) ) { pcurrententry->color = figrec.color; /* default color */ pcurrententry->depth = figrec.depth; pcurrententry->fillcolor = figrec.fillcolor; if ( (pcurrententry->coords = (int *)malloc(figrec.npoints * (sizeof (int)) * 2 )) == NULL ) { fprintf ( stderr, "Error : memory allocation failure.\n" ); break; } pcurrententry->npoints = figrec.npoints; memcpy (pcurrententry->coords,figrec.coords,figrec.npoints * (sizeof (int)) * 2); } } while ( 1 ); if ( pcurrententry->type==LINK && pcurrententry->coords != NULL ) { read_entry ( pcurrententry ); /*printf (" link : log : %s.log, max rate : %i.\n", pcurrententry->str, pcurrententry->maxrate );*/ } break; case ENDCOMPOUND: case UNKNOWN: default: break; } } /***************************************************************/ /* checks */ if ( pareaentry == NULL ) { fprintf ( stderr, "Error : no gif area specified.\n"); break; } xsize = (pareaentry->coords[2] - pareaentry->coords[0]); ysize = (pareaentry->coords[3] - pareaentry->coords[1]); xoffset = pareaentry->coords[0]; yoffset = pareaentry->coords[1]; /*printf ( "size : %i %i.\n", xsize, ysize ); printf ( "offset : %i %i.\n", xoffset, yoffset );*/ /***************************************************************/ /* do translations */ pcurrententry = pfirstentry; while ( pcurrententry != NULL ) { for (i = 0; i < pcurrententry->npoints; i ++) { pcurrententry->coords[i*2] -= xoffset; pcurrententry->coords[i*2+1] -= yoffset; pcurrententry->coords[i*2] /= scale; pcurrententry->coords[i*2+1] /= scale; } if ( smap != NULL ) { if ( pcurrententry->type==URL && pcurrententry->coords != NULL ) { fprintf ( map, " <area href=%s alt=\"%s\" shape=rect coords=\"%i,%i,%i,%i\">\n", pcurrententry->str,pcurrententry->str, pcurrententry->coords[0],pcurrententry->coords[1], pcurrententry->coords[2],pcurrententry->coords[3] ); } } pcurrententry = pcurrententry->next; } xsize /= scale; ysize /=scale; /***************************************************************/ /* 3 : draw gif file */ draw_gif ( gif ); /***************************************************************/ /* 4 : clean-up all */ { struct sentry * pentry; pcurrententry = pfirstentry; do { pentry = pcurrententry->next; free_entry(pcurrententry); pcurrententry = pentry; } while ( pentry != NULL ); } fclose ( gif ); fclose ( config ); if ( smap != NULL ) { /*<area href=lk311.html alt="lk311.html" shape=rect coords="240,12,270,24">*/ fprintf ( map, " </map>\n" ); fclose ( map ); } break; } while ( TRUE ); }