/****************************************************************/ /* */ /* distrib.c (see readme.html for program explanation) */ /* */ /* author : Philippe Simonet, Philippe.Simonet@swiisstelecom.com*/ /* */ /* change log : */ /* */ /* v. 1.00 : initial update (SIP) (23.06.97) */ /* */ /* */ /* */ /************************************************************************/ #include #include #include #include #include #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 distcount; int xsize, ysize, rounds, rate; int dist[1000][2]; /************************************************************************/ /* 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; } /************************************************************************/ void computes_distrib ( FILE * fi, int length, int nb, unsigned int maxbytes ) { int i,j; unsigned long time, in, out, maxin, maxout; for ( i = 0; i < length; i ++ ) { in = 0; out = 0; /* compute mean on 'nb' items */ for (j = 0; j < nb; j ++ ) { unsigned long wi, wo; if (fscanf(fi,"%lu %lu %lu %lu %lu\n",&time,&wi,&wo,&maxin, &maxout) != 5) { printf ( "config file error !!!\n" ); } else { in += wi; out += wo; } } in /= nb; out /= nb; if ( in >= maxbytes ) in = maxbytes-1; if ( out >= maxbytes ) out = maxbytes-1; dist[(( in*distcount)/maxbytes)][0] ++; dist[((out*distcount)/maxbytes)][1] ++; } }; /************************************************************************/ /* in case of trouble ... */ void print_error ( void ) { fprintf ( stderr, "Read mrtg log files and build distribution graphs.\n" ); fprintf ( stderr, "Version 1.1, 27.06.97.\n" ); fprintf ( stderr, "Use : case 1 : (1 distr. log file)\n" ); fprintf ( stderr, " distrib -i logfile -o gfile -w width -h height -t type -r rate -d count\n" ); fprintf ( stderr, " ifile : input log file name,\n" ); fprintf ( stderr, " gfile : output gif file (will be overwritten),\n" ); fprintf ( stderr, " count : histogram count,\n" ); fprintf ( stderr, " rate : line rate,\n" ); fprintf ( stderr, " type : length of measurement (d/w/m/y).\n" ); fprintf ( stderr, "Use : case 2 : (distr. from distrib. file)\n" ); fprintf ( stderr, " distrib -i distrib -o gfile -w width -h height -t x -r top -d count\n" ); fprintf ( stderr, " ifile : input distribution summary file name,\n" ); fprintf ( stderr, " gfile : output gif file (will be overwritten),\n" ); fprintf ( stderr, " top : how may top n,\n" ); fprintf ( stderr, " count : histogram count,\n" ); fprintf ( stderr, " type : 'x'.\n" ); } /************************************************************************/ #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 */ void draw_distrib_gif ( FILE * score, 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 #define c_blue 0,0,255 #define c_red 255,0,0 #define c_green 0,255,0 gdImagePtr graph; int i_light,i_dark,i_blank, i_black, i_white, i_blue, i_red, i_green; int color[4000][2]; graph = gdImageCreate(xsize, ysize); /* the first color allocated will be the background color. */ i_blank = gdImageColorAllocate(graph,c_blank); 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); i_red = gdImageColorAllocate(graph,c_red); i_green = gdImageColorAllocate(graph,c_green); i_blue = gdImageColorAllocate(graph,c_blue); { int i; for (i = 0; i <= distcount; i++ ) { color[distcount - i - 1][0] = gdImageColorAllocate(graph, (255*i)/distcount, 255, (255*i)/distcount); } for (i = 0; i <= distcount; i++ ) { color[distcount - i - 1][1] = gdImageColorAllocate(graph, (255*i)/distcount, (255*i)/distcount, 255); } } /* 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,gdFontSmall->w,3,asctime( newtime ),i_dark); }; /*i_col = find_color(graph, colortable[pcurrententry->color]); gdImageFilledRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col2); } gdImageString(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImageStringUp(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImagePtr brush_2pix; 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; gdImageLine(graph, x, y, x2, y2,i_col); gdImageDestroy(brush_2pix);*/ /* draw axes and graphs */ { int w = gdFontSmall->w, h = gdFontSmall->h, i, j, k, incrx, incry; char str[4000]; int nbaxesx = (rate + 1); int nbaxesy = 6; int textx = 7; int texty = 15; incry = (ysize-(h*2)-(w*texty))/(nbaxesy-1); incrx = (xsize-(w*(textx+2)))/(nbaxesx-1); j = 100; for ( i = h*2; i <= ((h*2) + (incry * (nbaxesy-1))) ; i+= incry ) { gdImageLine(graph,w*textx,i,w*textx + (incrx*(nbaxesx-1)),i,i_black); /* horizontal */ sprintf ( str, "%3u%%", j ); j-= 100/(nbaxesy-1); gdImageString(graph, gdFontSmall,w,i-h/2,str,i_black ); } j = 0; for ( i = w*7; i <= ((w*7) + (incrx * (nbaxesx-1))) ; i+= incrx ) { /*gdImageLine(graph,i,h*2,i,h*2 + (incry*(AXESY-1)),i_black);*/ /* vertical */ /*sprintf ( str, "%3u%%", j ); j+= (100/(AXESX-1)); gdImageStringUp(graph, gdFontSmall, i - w/2, ysize - h, str, i_black );*/ } for ( i = 0; i < rate; i ++ ) { char *name,*ptr; int tin=0, tout=0; int x1, x2, y1, y2, mrgx; if ( fscanf ( score, "%s", str ) == EOF ) break; /*printf ( "%s\n", str );*/ name = str; if ((ptr = strtok( str, ":")) == NULL) continue; /*printf ( "%s:", name );*/ for ( j = 0; j < distcount; j++ ) { dist[j][0] = dist[j][0] = 0; if ((ptr = strtok( NULL, "/,")) == NULL) continue; dist[j][0] = atoi(ptr); tin += dist[j][0]; if ((ptr = strtok( NULL, "/,")) == NULL) continue; dist[j][1] = atoi(ptr); tout += dist[j][1]; /*printf ( "%u/%u,",dist[j][0],dist[j][1] );*/ } /*printf ( "\n" );*/ /* draw label and graphs */ mrgx = incrx/5; x1 = (w*textx) + (i*incrx) + (incrx/2) - (h/2); y1 = ysize-h; gdImageStringUp( graph, gdFontSmall, x1, y1, str, i_black ); for (k = 0; k < 2; k ++ ) { y1 = ysize-((texty-4) * w); if ( k == 0 ) { x1 = (w*textx) + (i*incrx) + mrgx; x2 = x1 + (incrx/3); gdImageStringUp( graph, gdFontSmall, x1, y1, "in", i_black ); } else { x2 = (w*textx) + ((i+1)*incrx) - mrgx; x1 = x2 - (incrx/3); gdImageStringUp( graph, gdFontSmall, x1, y1, "out", i_black ); } y2 = h*2 + (incry*(nbaxesy-1)); for ( j = distcount-1; j >=0 ; j-- ) { y1 = y2 - (((ysize-(h*2)-(w*texty) - 2) * dist[j][k]) / tin); if (j == 0) { /* 'correct' cumulative error */ y1 = h*2; } gdImageFilledRectangle(graph, x1, y1, x2, y2,color[j][k]); gdImageRectangle(graph, x1, y1, x2, y2,i_black); y2 = y1; } } /* int x1, x2, y1, y2, mrgx; mrgx = incrx/5; x1 = (w*7) + (i*incrx) + mrgx; x2 = x1 + (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][0]) / rounds); gdImageFilledRectangle(graph, x1, y1, x2, y2,i_green); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); x2 = (w*7) + ((i+1)*incrx) - mrgx; x1 = x2 - (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][1]) / rounds); gdImageFilledRectangle(graph, x1, y1, x2, y2,i_blue); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); */ } } gdImageGif(graph, gif); gdImageDestroy(graph); } /************************************************************************/ /* 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 #define c_blue 0,0,255 #define c_red 255,0,0 #define c_green 0,255,0 gdImagePtr graph; int i_light,i_dark,i_blank, i_black, i_white, i_blue, i_red, i_green; graph = gdImageCreate(xsize, ysize); /* the first color allocated will be the background color. */ i_blank = gdImageColorAllocate(graph,c_blank); 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); i_red = gdImageColorAllocate(graph,c_red); i_green = gdImageColorAllocate(graph,c_green); i_blue = gdImageColorAllocate(graph,c_blue); /* 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,gdFontSmall->w,3,asctime( newtime ),i_dark); }; /*i_col = find_color(graph, colortable[pcurrententry->color]); gdImageFilledRectangle(graph, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->coords[2], pcurrententry->coords[3],i_col2); } gdImageString(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImageStringUp(graph, gdFontSmall, pcurrententry->coords[0], pcurrententry->coords[1], pcurrententry->str, i_col ); gdImagePtr brush_2pix; 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; gdImageLine(graph, x, y, x2, y2,i_col); gdImageDestroy(brush_2pix);*/ /* draw axes and graphs */ { int w = gdFontSmall->w, h = gdFontSmall->h, i, j, incrx, incry, maxio; char str[20]; #define AXESX (distcount + 1) #define AXESY 6 maxio = 0; for ( i = 0; i < distcount; i ++ ) { if (maxio < dist[i][0]) maxio = dist[i][0]; if (maxio < dist[i][1]) maxio = dist[i][1]; } incry = (ysize-(h*2)-(w*7))/(AXESY-1); incrx = (xsize-(w*9))/(AXESX-1); j = 100; for ( i = h*2; i <= ((h*2) + (incry * (AXESY-1))) ; i+= incry ) { gdImageLine(graph,w*7,i,w*7 + (incrx*(AXESX-1)),i,i_black); /* horizontal */ sprintf ( str, "%3u%%", j ); j-= 100/(AXESY-1); gdImageString(graph, gdFontSmall,w,i-h/2,str,i_black ); } j = 0; for ( i = w*7; i <= ((w*7) + (incrx * (AXESX-1))) ; i+= incrx ) { gdImageLine(graph,i,h*2,i,h*2 + (incry*(AXESY-1)),i_black); /* vertical */ sprintf ( str, "%3u%%", j ); j+= (100/(AXESX-1)); gdImageStringUp(graph, gdFontSmall, i - w/2, ysize - h, str, i_black ); } for ( i = 0; i < distcount; i ++ ) { int x1, x2, y1, y2, mrgx; mrgx = incrx/5; x1 = (w*7) + (i*incrx) + mrgx; x2 = x1 + (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][0]) / rounds); /* printf ( "x1 %u, y1 %u, x2 %u, y2 %u.\n", x1, y1, x2, y2 );*/ gdImageFilledRectangle(graph, x1, y1, x2, y2,i_green); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); x2 = (w*7) + ((i+1)*incrx) - mrgx; x1 = x2 - (incrx/3); y2 = h*2 + (incry*(AXESY-1)) - 2; y1 = y2 - (((ysize-(h*2)-(w*7) - 2) * dist[i][1]) / rounds); /* printf ( "x1 %u, y1 %u, x2 %u, y2 %u.\n", x1, y1, x2, y2 );*/ gdImageFilledRectangle(graph, x1, y1, x2, y2,i_blue); gdImageRectangle(graph, x1, y1, x2, y2,i_dark); } } gdImageGif(graph, gif); gdImageDestroy(graph); } /************************************************************************/ void main ( int argc, char * argv[] ) { FILE *config = NULL, *gif = NULL; char *sconfig = NULL, *sgif = NULL; char *optarg; char type; int i; /* globals */ xsize = 400, ysize = 150; type = 'd'; rate = 1250000; distcount = 10; do { /***************************************************************/ /* 0 : read program arguments */ while ( ( i = getopt1( argc, argv, "o:i:t:w:h:r:d:", &optarg ) ) != EOF ) { switch ( i ) { case 'i': sconfig = optarg; break; case 'o': sgif = optarg; break; case 'w': if ( optarg != NULL ) { xsize = atoi (optarg); } break; case 'r': if ( optarg != NULL ) { rate = atoi (optarg); } break; case 'd': if ( optarg != NULL ) { distcount = atoi (optarg); } break; case 'h': if ( optarg != NULL ) { ysize = atoi (optarg); } break; case 't': if ( optarg != NULL ) type = optarg[0]; if (type != 'd' && type != 'm' && type != 'w' && type != 'y' && type != 'x' ) { print_error(); exit (0); } break; case '?': print_error(); exit (0); break; default: break; } } if ( sgif == NULL || sconfig == NULL ) { print_error(); break; } /***************************************************************/ /* 1 : OPEN FILES */ gif = fopen ( sgif, "wb" ); if ( gif == NULL ) { fprintf ( stderr, "Error opening %s.\n", sgif ); fclose ( config ); break; } config = fopen ( sconfig, "r" ); if ( config == NULL ) { fprintf ( stderr, "Error opening %s.\n", sconfig ); break; } if ( type != 'x' ) { /***************************************************************/ for ( i = 0; i < distcount; i ++ ) { dist[i][0] = 0; dist[i][1] = 0; } { /* read first line ... */ unsigned long time, in, out; fscanf ( config, "%lu %lu %lu\n", &time, &in, &out ); /* read first line */ } switch ( type ) { case 'd': computes_distrib ( config, 288, 1, rate ); rounds = 288; /* 288 * 5' = 24 hours */ break; case 'w': computes_distrib ( config, 100, 6, rate ); /* 600 * 5', with mean on 6 (30')*/ computes_distrib ( config, 236, 1, rate ); rounds = 336; /* 336 * 30' = 7 days */ break; case 'm': computes_distrib ( config, 25, 24, rate ); /* 600 * 5', with mean on 24 (2hours) */ computes_distrib ( config, 150, 4, rate ); /* 600 *30', with mean on 4 */ computes_distrib ( config, 185, 1, rate ); rounds = 360; /* 260 * 2 hours = 30 days */ break; case 'y': computes_distrib ( config, 2,300, rate ); /* 600 * 5', with mean on 300 ~= 1 day */ computes_distrib ( config, 12, 50, rate ); /* 600 *30', with mean on 50 ~= 1 day */ computes_distrib ( config, 50, 12, rate ); /* 600 * 2h, with mean on 12 */ computes_distrib ( config, 300, 1, rate ); rounds = 364; break; } for ( i = 0; i < distcount; i ++ ) { printf ( "%u:%u,%u.\n", i, dist[i][0],dist[i][1] ); } /***************************************************************/ draw_gif ( gif ); /***************************************************************/ fclose ( gif ); fclose ( config ); break; } else { draw_distrib_gif ( config, gif ); fclose ( config ); fclose ( gif ); break; } } while ( TRUE ); }