#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define COPYRIGHT "1998,2013" #ifdef PLATFORM_AMIGA char *ver="$VER: CrashStats "VERSION" ("__COMMODORE_DATE__")"; #endif #define STATS_IDENTIFIER "CST3" static size_t ptrsize = sizeof(void *); struct DiskAreaStats { char Tagname[80]; struct Node4D Aka; char Group; char fill_to_make_even; /* Just ignore this one */ uint32_t TotalTexts; uint16_t Last8Days[8]; uint32_t Dupes; time_t FirstTime; time_t LastTime; }; struct DiskNodeStats { struct Node4D Node; uint32_t GotNetmails; uint32_t GotNetmailBytes; uint32_t SentNetmails; uint32_t SentNetmailBytes; uint32_t GotEchomails; uint32_t GotEchomailBytes; uint32_t SentEchomails; uint32_t SentEchomailBytes; uint32_t Dupes; time_t FirstTime; }; struct StatsNode { struct StatsNode *Next; char Tagname[80]; uint32_t Average; uint32_t Total; uint32_t Dupes; time_t FirstTime; time_t LastTime; uint16_t Last8Days[8]; }; struct NodeStatsNode { struct NodeStatsNode *Next; struct Node4D Node; uint32_t GotNetmails; uint32_t GotNetmailBytes; uint32_t SentNetmails; uint32_t SentNetmailBytes; uint32_t GotEchomails; uint32_t GotEchomailBytes; uint32_t SentEchomails; uint32_t SentEchomailBytes; uint32_t Dupes; uint32_t Days; time_t FirstTime; }; #define ARG_FILE 0 #define ARG_SORT 1 #define ARG_LAST7 2 #define ARG_NOAREAS 3 #define ARG_NONODES 4 #define ARG_GROUP 5 struct argument args[] = { { ARGTYPE_STRING, "FILE", ARGFLAG_AUTO | ARGFLAG_MANDATORY, NULL }, { ARGTYPE_STRING, "SORT", 0, NULL }, { ARGTYPE_BOOL, "LAST7", 0, NULL }, { ARGTYPE_BOOL, "NOAREAS", 0, NULL }, { ARGTYPE_BOOL, "NONODES", 0, NULL }, { ARGTYPE_STRING, "GROUP", 0, NULL }, { ARGTYPE_END, NULL, 0, 0 } }; bool diskfull; int CompareAlpha(const void *a1,const void *a2) { struct StatsNode **s1,**s2; s1=(struct StatsNode **)a1; s2=(struct StatsNode **)a2; return(stricmp((*s1)->Tagname,(*s2)->Tagname)); } int CompareTotal(const void *a1,const void *a2) { struct StatsNode **s1,**s2; s1=(struct StatsNode **)a1; s2=(struct StatsNode **)a2; if((*s1)->Total < (*s2)->Total) return(1); if((*s1)->Total > (*s2)->Total) return(-1); return(0); } int CompareDupes(const void *a1,const void *a2) { struct StatsNode **s1,**s2; s1=(struct StatsNode **)a1; s2=(struct StatsNode **)a2; if((*s1)->Dupes < (*s2)->Dupes) return(1); if((*s1)->Dupes > (*s2)->Dupes) return(-1); return(0); } int CompareMsgsDay(const void *a1,const void *a2) { struct StatsNode **s1,**s2; s1=(struct StatsNode **)a1; s2=(struct StatsNode **)a2; if((*s1)->Average < (*s2)->Average) return(1); if((*s1)->Average > (*s2)->Average) return(-1); return(0); } int CompareFirstTime(const void *a1,const void *a2) { struct StatsNode **s1,**s2; s1=(struct StatsNode **)a1; s2=(struct StatsNode **)a2; if((*s1)->FirstTime < (*s2)->FirstTime) return(1); if((*s1)->FirstTime > (*s2)->FirstTime) return(-1); return(0); } int CompareLastTime(const void *a1,const void *a2) { struct StatsNode **s1,**s2; s1=(struct StatsNode **)a1; s2=(struct StatsNode **)a2; if((*s1)->LastTime < (*s2)->LastTime) return(1); if((*s1)->LastTime > (*s2)->LastTime) return(-1); return(0); } bool Sort(struct jbList *list,char sortmode) { uint32_t nc; struct StatsNode *sn,**buf,**work; nc=0; for(sn=(struct StatsNode *)list->First;sn;sn=sn->Next) nc++; if(nc==0) return(TRUE); /* Nothing to sort */ if(!(buf=(struct StatsNode **)osAlloc(nc*sizeof(struct StatsNode *)))) return(FALSE); work=buf; for(sn=(struct StatsNode *)list->First;sn;sn=sn->Next) *work++=sn; switch(sortmode) { case 'a': qsort(buf,nc,ptrsize,CompareAlpha); break; case 't': qsort(buf,nc,ptrsize,CompareTotal); break; case 'm': qsort(buf,nc,ptrsize,CompareMsgsDay); break; case 'd': qsort(buf,nc,ptrsize,CompareFirstTime); break; case 'l': qsort(buf,nc,ptrsize,CompareLastTime); break; case 'u': qsort(buf,nc,ptrsize,CompareDupes); break; } jbNewList(list); for(work=buf;nc--;) jbAddNode(list,(struct jbNode *)*work++); osFree(buf); return(TRUE); } int CompareNodes(const void *a1,const void *a2) { struct NodeStatsNode **s1,**s2; s1=(struct NodeStatsNode **)a1; s2=(struct NodeStatsNode **)a2; return(Compare4D(&(*s1)->Node,&(*s2)->Node)); } bool SortNodes(struct jbList *list) { struct NodeStatsNode *sn,**buf,**work; uint32_t nc; nc=0; for(sn=(struct NodeStatsNode *)list->First;sn;sn=sn->Next) nc++; if(nc==0) return(TRUE); /* Nothing to sort */ if(!(buf=(struct NodeStatsNode **)osAlloc(nc*sizeof(struct NodeStatsNode *)))) return(FALSE); work=buf; for(sn=(struct NodeStatsNode *)list->First;sn;sn=sn->Next) *work++=sn; qsort(buf,nc,ptrsize,CompareNodes); jbNewList(list); for(work=buf;nc--;) jbAddNode(list,(struct jbNode *)*work++); osFree(buf); return(TRUE); } char *unit(uint32_t i) { static char buf[40]; if ((i>10000000)||(i<-10000000)) sprintf(buf,"%d MB",i/(1024*1024)); else if ((i>10000)||(i<-10000)) sprintf(buf,"%d KB",i/1024); else sprintf(buf,"%d bytes",i); return buf; } bool CheckFlags(char group,char *node) { int c; for(c=0;c 7) days=7; sum=0; for(c=1;c 1 && (strcmp(argv[1],"?")==0 || strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0 || strcmp(argv[1],"help")==0 || strcmp(argv[1],"/h")==0 || strcmp(argv[1],"/?")==0 )) { printargs(args); osEnd(); exit(OS_EXIT_OK); } if(!parseargs(args,argc,argv)) { osEnd(); exit(OS_EXIT_ERROR); } sortmode='a'; if(args[ARG_SORT].data) sortmode=tolower(((char *)args[ARG_SORT].data)[0]); if(!strchr("amtdlu",sortmode)) { printf("Unknown sort mode %c\n",sortmode); osEnd(); exit(OS_EXIT_ERROR); } if(args[ARG_NOAREAS].data && args[ARG_NONODES].data) { printf("Nothing to do\n"); osEnd(); exit(OS_EXIT_ERROR); } printf("CrashStats "VERSION" © " COPYRIGHT " Johan Billing & Robert James Clay\n"); if(!(fh=osOpen(args[ARG_FILE].data,MODE_OLDFILE))) { uint32_t err=osError(); printf("Error opening %s\n",(char *)args[ARG_FILE].data); printf("Error: %s\n",osErrorMsg(err)); osEnd(); exit(OS_EXIT_ERROR); } osRead(fh,buf,4); buf[4]=0; if(strcmp(buf,STATS_IDENTIFIER)!=0) { printf("Unknown format of stats file\n"); osClose(fh); osEnd(); exit(OS_EXIT_ERROR); } osRead(fh,&DayStatsWritten,sizeof(uint32_t)); total=0; totaldupes=0; firsttime=0; areas=0; for(c=0;c<8;c++) total8days[c]=0; jbNewList(&StatsList); jbNewList(&NodesList); osRead(fh,&num,sizeof(uint32_t)); c=0; if(!args[ARG_NOAREAS].data) { while(cTagname,dastat.Tagname); sn->Dupes=dastat.Dupes; sn->Total=dastat.TotalTexts; sn->FirstTime=dastat.FirstTime; sn->LastTime=dastat.LastTime; memcpy(&sn->Last8Days[0],&dastat.Last8Days[0],8*sizeof(uint16_t)); sn->Average=CalculateAverage(&dastat.Last8Days[0],dastat.TotalTexts,DayStatsWritten,sn->FirstTime / (24*60*60)); } if(dastat.FirstTime!=0) if(firsttime==0 || firsttime > dastat.FirstTime) firsttime=dastat.FirstTime; c++; } } else { while(cNode,&dnstat.Node); nsn->GotNetmails=dnstat.GotNetmails; nsn->GotNetmailBytes=dnstat.GotNetmailBytes; nsn->SentNetmails=dnstat.SentNetmails; nsn->SentNetmailBytes=dnstat.SentNetmailBytes; nsn->GotEchomails=dnstat.GotEchomails; nsn->GotEchomailBytes=dnstat.GotEchomailBytes; nsn->SentEchomails=dnstat.SentEchomails; nsn->SentEchomailBytes=dnstat.SentEchomailBytes; nsn->Dupes=dnstat.Dupes; nsn->Days=DayStatsWritten-dnstat.FirstTime % (24*60*60); if(nsn->Days==0) nsn->Days=1; nsn->FirstTime=dnstat.FirstTime; if(dnstat.FirstTime!=0) if(firsttime==0 || firsttime > dnstat.FirstTime) firsttime=dnstat.FirstTime; c++; } } else { while(ctm_mday,monthnames[tp->tm_mon],tp->tm_year%100); tp=localtime(&t); sprintf(date2,"%02d-%s-%02d",tp->tm_mday,monthnames[tp->tm_mon],tp->tm_year%100); printf("\nStatistics from %s to %s\n",date,date2); if(!ctrlc && !args[ARG_NOAREAS].data) { Sort(&StatsList,'a'); Sort(&StatsList,sortmode); printf("\n"); if(args[ARG_LAST7].data) { printf("Area "); for(c=1;c<8;c++) { t=(DayStatsWritten-c)*24*60*60; tp=localtime(&t); printf(" %02d",tp->tm_mday); } printf(" Total\n============================================================================\n"); if(!ctrlc) { for(sn=(struct StatsNode *)StatsList.First;sn && !ctrlc;sn=sn->Next) { tot=0; for(c=1;c<8;c++) tot+=sn->Last8Days[c]; printf("%-33.33s %4d %4d %4d %4d %4d %4d %4d : %5d\n", sn->Tagname, sn->Last8Days[1], sn->Last8Days[2], sn->Last8Days[3], sn->Last8Days[4], sn->Last8Days[5], sn->Last8Days[6], sn->Last8Days[7], tot); for(c=1;c<8;c++) total8days[c]+=sn->Last8Days[c]; areas++; } if(!ctrlc) { tot=0; for(c=1;c<8;c++) tot+=total8days[c]; printf("=============================================================================\n"); sprintf(buf,"Totally in all %u areas",areas); printf("%-33.33s %4d %4d %4d %4d %4d %4d %4d : %5d\n", buf, total8days[1], total8days[2], total8days[3], total8days[4], total8days[5], total8days[6], total8days[7], tot); } } } else { printf("Area First Last Msgs Msgs/day Dupes\n"); printf("============================================================================\n"); if(!ctrlc) { for(sn=(struct StatsNode *)StatsList.First;sn && !ctrlc;sn=sn->Next) { if(sn->LastTime==0) { strcpy(date2,""); } else { tp=localtime(&sn->LastTime); sprintf(date2,"%02d-%s-%02d",tp->tm_mday,monthnames[tp->tm_mon],tp->tm_year%100); } if(sn->FirstTime==0) { strcpy(date,""); } else { tp=localtime(&sn->FirstTime); sprintf(date,"%02d-%s-%02d",tp->tm_mday,monthnames[tp->tm_mon],tp->tm_year%100); } for(c=0;c<8;c++) total8days[c]+=sn->Last8Days[c]; total+=sn->Total; totaldupes+=sn->Dupes; areas++; printf("%-29.30s %-9.9s %-9.9s %7d %7d %7d\n",sn->Tagname,date,date2,sn->Total,sn->Average,sn->Dupes); } } if(!ctrlc) { printf("============================================================================\n"); sprintf(buf,"Totally in all %u areas",areas); printf("%-42s %7d %7d %7d\n", buf, total, CalculateAverage(&total8days[0],total,DayStatsWritten,firsttime / (24*60*60)), totaldupes); } } } if(!ctrlc && !args[ARG_NONODES].data) { SortNodes(&NodesList); printf("\n"); printf("Nodes statistics\n"); printf("================\n"); for(nsn=(struct NodeStatsNode *)NodesList.First;nsn && !ctrlc;nsn=nsn->Next) { if(nsn->FirstTime==0) { strcpy(date,""); } else { tp=localtime(&nsn->FirstTime); sprintf(date,"%0d-%s-%0d",tp->tm_mday,monthnames[tp->tm_mon],tp->tm_year%100); } sprintf(buf,"%u:%u/%u.%u",nsn->Node.Zone,nsn->Node.Net,nsn->Node.Node,nsn->Node.Point); printf("%-30.40s Statistics since: %s\n\n",buf,date); printf(" Sent netmails: %u/%s\n",nsn->SentNetmails,unit(nsn->SentNetmailBytes)); printf(" Received netmails: %u/%s\n",nsn->GotNetmails,unit(nsn->GotNetmailBytes)); printf(" Sent echomails: %u/%s\n",nsn->SentEchomails,unit(nsn->SentEchomailBytes)); printf(" Received echomails: %u/%s\n",nsn->GotEchomails,unit(nsn->GotEchomailBytes)); printf(" Dupes: %u\n",nsn->Dupes); printf("\n"); } } if(ctrlc) { printf("*** Break\n"); } else { printf("\n"); } jbFreeList(&StatsList); jbFreeList(&NodesList); osEnd(); exit(OS_EXIT_OK); }