From: Frederic Marchal Date: Sun, 19 Jul 2015 12:55:31 +0000 (+0200) Subject: Split the top user report generation X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a3a7e14357f5c64d2f738869f2560f71124b5c1b;p=thirdparty%2Fsarg.git Split the top user report generation Use one function to prepare the top user list and another to generate the html report. It is the first step to merge the html and email reports. --- diff --git a/include/conf.h b/include/conf.h index 44d5384..875804c 100644 --- a/include/conf.h +++ b/include/conf.h @@ -500,7 +500,6 @@ int realtime_access_log_lines; int rc; int ntopsites; int nrepday; -int ntopuser; bool squid24; //! \c True to keep the temporary files for inspection. bool KeepTempLog; diff --git a/topuser.c b/topuser.c index 42a5f49..19bd2bc 100644 --- a/topuser.c +++ b/topuser.c @@ -28,6 +28,22 @@ #include "include/defs.h" #include "include/filelist.h" +struct TopUserStatistics +{ + long long int ttnbytes; + long long int ttnacc; + long long int ttnelap; + long long int ttnincache; + long long int ttnoucache; + int totuser; +}; + +struct SortInfoStruct +{ + const char *sort_field; + const char *sort_order; +}; + extern struct globalstatstruct globstat; extern bool smartfilter; extern FileListObject UserAgentLog; @@ -56,14 +72,17 @@ static void set_total_users(int totuser) globstat.totuser=totuser; } -void topuser(void) +/*! + * Generate a HTML report with the users downloading the most. + * + * \param ListFile Name of the file with the sorted list of users. + * \param Statis Statistics about the data collected from the log file. + * \param SortInfo Strings explaining how the list was sorted. + */ +static void TopUser_HtmlReport(const char *ListFile,struct TopUserStatistics *Statis,struct SortInfoStruct *SortInfo) { - FileObject *fp_in = NULL; FileObject *fp_top1 = NULL; - FILE *fp_top2 = NULL, *fp_top3 = NULL; - long long int ttnbytes=0, ttnacc=0, tnacc=0; - long long int tnbytes=0, ttnelap=0, tnelap=0; - long long int tnincache=0, tnoucache=0, ttnincache=0, ttnoucache=0; + FILE *fp_top3 = NULL; long long int nbytes; long long int nacc; long long int elap, incac, oucac; @@ -71,158 +90,23 @@ void topuser(void) double perc2=0.00; double inperc=0.00, ouperc=0.00; int posicao=0; - char olduser[MAX_USER_LEN], csort[MAXLEN]; - char wger[MAXLEN], top1[MAXLEN], top2[MAXLEN], top3[MAXLEN]; + char top3[MAXLEN]; char user[MAX_USER_LEN]; - const char *sfield="-n -k 2,2"; - const char *order; - const char *sort_field; - const char *sort_order; char title[80]; char *warea; - int totuser=0; - int topcount=0; - int cstatus; + bool ntopuser=false; + int topcount=0; struct getwordstruct gwarea; longline line; - struct generalitemstruct item; struct userinfostruct *uinfo; - if (debugz>=LogLevel_Process) - debuga(__FILE__,__LINE__,_("Creating top users report...\n")); - ntopuser = 0; - snprintf(wger,sizeof(wger),"%s/sarg-general",outdirname); - if((fp_in=FileObject_Open(wger))==NULL) { - debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wger,FileObject_GetLastOpenError()); - exit(EXIT_FAILURE); - } - - snprintf(top2,sizeof(top2),"%s/top.tmp",outdirname); - if((fp_top2=fopen(top2,"w"))==NULL) { - debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top2,strerror(errno)); - exit(EXIT_FAILURE); - } - - olduser[0]='\0'; - totuser=0; - - if ((line=longline_create())==NULL) { - debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wger); - exit(EXIT_FAILURE); - } - - while((warea=longline_read(fp_in,line))!=NULL) { - ger_read(warea,&item,wger); - if(item.total) continue; - if(strcmp(olduser,item.user) != 0) { - totuser++; - - if (olduser[0] != '\0') { - /* - This complicated printf is due to Microsoft's inability to comply with any standard. Msvcrt is unable - to print a long long int unless it is exactly 64-bits long. - */ - fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap,(uint64_t)tnincache,(uint64_t)tnoucache); - - ttnbytes+=tnbytes; - ttnacc+=tnacc; - ttnelap+=tnelap; - ttnincache+=tnincache; - ttnoucache+=tnoucache; - } - strcpy(olduser,item.user); - tnbytes=0; - tnacc=0; - tnelap=0; - tnincache=0; - tnoucache=0; - } - - tnbytes+=item.nbytes; - tnacc+=item.nacc; - tnelap+=item.nelap; - tnincache+=item.incache; - tnoucache+=item.oucache; - } - if (FileObject_Close(fp_in)) { - debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wger,FileObject_GetLastCloseError()); - exit(EXIT_FAILURE); - } - longline_destroy(&line); - - if (olduser[0] != '\0') { - /* - This complicated printf is due to Microsoft's inability to comply with any standard. Msvcrt is unable - to print a long long int unless it is exactly 64-bits long. - */ - fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap,(uint64_t)tnincache,(uint64_t)tnoucache); - - ttnbytes+=tnbytes; - ttnacc+=tnacc; - ttnelap+=tnelap; - ttnincache+=tnincache; - ttnoucache+=tnoucache; - } - if (fclose(fp_top2)==EOF) { - debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top2,strerror(errno)); - exit(EXIT_FAILURE); - } - -#ifdef ENABLE_DOUBLE_CHECK_DATA - if (ttnacc!=globstat.nacc || ttnbytes!=globstat.nbytes || ttnelap!=globstat.elap || - ttnincache!=globstat.incache || ttnoucache!=globstat.oucache) { - debuga(__FILE__,__LINE__,_("Total statistics mismatch when reading \"%s\" to produce the top users\n"),wger); - exit(EXIT_FAILURE); - } -#endif - - set_total_users(totuser); - - if((TopuserSort & TOPUSER_SORT_USER) != 0) { - sfield="-k 1,1"; - sort_field=_("user"); - } else if((TopuserSort & TOPUSER_SORT_CONNECT) != 0) { - sfield="-n -k 3,3"; - sort_field=_("connect"); - } else if((TopuserSort & TOPUSER_SORT_TIME) != 0) { - sfield="-n -k 4,4"; - sort_field=pgettext("duration","time"); - } else { - sort_field=_("bytes"); - } - - if((TopuserSort & TOPUSER_SORT_REVERSE) == 0) { - order=""; - sort_order=_("normal"); - } else { - order="-r"; - sort_order=_("reverse"); - } - - snprintf(top1,sizeof(top1),"%s/top",outdirname); - if (snprintf(csort,sizeof(csort),"sort -T \"%s\" -t \"\t\" %s %s -o \"%s\" \"%s\"", tmp, order, sfield, top1, top2)>=sizeof(csort)) { - debuga(__FILE__,__LINE__,_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),top2,top1); - exit(EXIT_FAILURE); - } - cstatus=system(csort); - if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) { - debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus)); - debuga(__FILE__,__LINE__,_("sort command: %s\n"),csort); - exit(EXIT_FAILURE); - } - - if((fp_top1=FileObject_Open(top1))==NULL) { - debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top1,FileObject_GetLastOpenError()); - exit(EXIT_FAILURE); - } - - if (!KeepTempLog && unlink(top2)) { - debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),top2,strerror(errno)); + if ((fp_top1=FileObject_Open(ListFile))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ListFile,FileObject_GetLastOpenError()); exit(EXIT_FAILURE); } snprintf(top3,sizeof(top3),"%s/"INDEX_HTML_FILE,outdirname); - if((fp_top3=fopen(top3,"w"))==NULL) { + if ((fp_top3=fopen(top3,"w"))==NULL) { debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top3,strerror(errno)); exit(EXIT_FAILURE); } @@ -234,7 +118,7 @@ void topuser(void) fputs("\n",fp_top3); if ((ReportType & REPORT_TYPE_TOPUSERS) != 0) { fputs("",fp_top3); - fprintf(fp_top3,_("Sort: %s, %s"),sort_field,sort_order); + fprintf(fp_top3,_("Sort: %s, %s"),SortInfo->sort_field,SortInfo->sort_order); fputs("\n",fp_top3); fprintf(fp_top3,"%s\n",_("Top users")); } else { @@ -310,49 +194,45 @@ void topuser(void) greport_prepare(); - ntopuser = 0; - if ((line=longline_create())==NULL) { - debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } - while((warea=longline_read(fp_top1,line))!=NULL) { + while ((warea=longline_read(fp_top1,line))!=NULL) { getword_start(&gwarea,warea); if (getword(user,sizeof(user),&gwarea,'\t')<0) { - debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } if (getword_atoll(&nbytes,&gwarea,'\t')<0) { - debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } if (getword_atoll(&nacc,&gwarea,'\t')<0) { - debuga(__FILE__,__LINE__,_("Invalid number of accesses in file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Invalid number of accesses in file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } if (getword_atoll(&elap,&gwarea,'\t')<0) { - debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Invalid elapsed time in file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } if (getword_atoll(&incac,&gwarea,'\t')<0) { - debuga(__FILE__,__LINE__,_("Invalid in-cache size in file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Invalid in-cache size in file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } if (getword_atoll(&oucac,&gwarea,'\n')<0) { - debuga(__FILE__,__LINE__,_("Invalid out-of-cache size in file \"%s\"\n"),top1); + debuga(__FILE__,__LINE__,_("Invalid out-of-cache size in file \"%s\"\n"),ListFile); exit(EXIT_FAILURE); } - if(nacc < 1) + if (nacc < 1) continue; - ntopuser = 1; - if(TopUsersNum > 0 && topcount >= TopUsersNum) break; - tnbytes=nbytes; - tnelap=elap; + ntopuser=true; + if (TopUsersNum>0 && topcount>=TopUsersNum) break; uinfo=userinfo_find_from_id(user); if (!uinfo) { - debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,top1); + debuga(__FILE__,__LINE__,_("Unknown user ID %s in file \"%s\"\n"),user,ListFile); exit(EXIT_FAILURE); } uinfo->topuser=1; @@ -394,16 +274,16 @@ void topuser(void) } if((TopUserFields & TOPUSERFIELDS_BYTES) != 0) { fputs("%s",fixnum(tnbytes,1)); + if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)nbytes); + fprintf(fp_top3,">%s",fixnum(nbytes,1)); } if((TopUserFields & TOPUSERFIELDS_SETYB) != 0) { - perc=(ttnbytes) ? tnbytes * 100. / ttnbytes : 0.; + perc=(Statis->ttnbytes) ? nbytes * 100. / Statis->ttnbytes : 0.; fprintf(fp_top3,"%3.2lf%%",perc); } if((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0) { - inperc=(tnbytes) ? incac * 100. / tnbytes : 0.; - ouperc=(tnbytes) ? oucac * 100. / tnbytes : 0.; + inperc=(nbytes) ? incac * 100. / nbytes : 0.; + ouperc=(nbytes) ? oucac * 100. / nbytes : 0.; fprintf(fp_top3,"%3.2lf%%%3.2lf%%",inperc,ouperc); #ifdef ENABLE_DOUBLE_CHECK_DATA if ((inperc!=0. || ouperc!=0.) && fabs(inperc+ouperc-100.)>=0.01) { @@ -413,16 +293,16 @@ void topuser(void) } if((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0) { fputs("%s",buildtime(tnelap)); + if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)elap); + fprintf(fp_top3,">%s",buildtime(elap)); } if((TopUserFields & TOPUSERFIELDS_MILISEC) != 0) { fputs("%s",fixnum2(tnelap,1)); + if (SortTableJs[0]) fprintf(fp_top3," sorttable_customkey=\"%"PRId64"\"",(int64_t)elap); + fprintf(fp_top3,">%s",fixnum2(elap,1)); } if((TopUserFields & TOPUSERFIELDS_PTIME) != 0) { - perc2=(ttnelap) ? elap * 100. / ttnelap : 0.; + perc2=(Statis->ttnelap) ? elap * 100. / Statis->ttnelap : 0.; fprintf(fp_top3,"%3.2lf%%",perc2); } @@ -431,16 +311,16 @@ void topuser(void) topcount++; } if (FileObject_Close(fp_top1)) { - debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),top1,FileObject_GetLastCloseError()); + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ListFile,FileObject_GetLastCloseError()); exit(EXIT_FAILURE); } - if (!KeepTempLog && unlink(top1)) { - debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),top1,strerror(errno)); + if (!KeepTempLog && unlink(ListFile)) { + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),ListFile,strerror(errno)); exit(EXIT_FAILURE); } longline_destroy(&line); - if((TopUserFields & TOPUSERFIELDS_TOTAL) != 0) { + if ((TopUserFields & TOPUSERFIELDS_TOTAL) != 0) { fputs("",fp_top3); if((TopUserFields & TOPUSERFIELDS_NUM) != 0) fputs("",fp_top3); @@ -452,15 +332,15 @@ void topuser(void) fprintf(fp_top3,"%s",_("TOTAL")); if((TopUserFields & TOPUSERFIELDS_CONNECT) != 0) - fprintf(fp_top3,"%s",fixnum(ttnacc,1)); + fprintf(fp_top3,"%s",fixnum(Statis->ttnacc,1)); if((TopUserFields & TOPUSERFIELDS_BYTES) != 0) - fprintf(fp_top3,"%15s",fixnum(ttnbytes,1)); + fprintf(fp_top3,"%15s",fixnum(Statis->ttnbytes,1)); if((TopUserFields & TOPUSERFIELDS_SETYB) != 0) fputs("",fp_top3); if((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0) { - inperc=(ttnbytes) ? ttnincache * 100. / ttnbytes : 0.; - ouperc=(ttnbytes) ? ttnoucache *100. / ttnbytes : 0.; + inperc=(Statis->ttnbytes) ? Statis->ttnincache * 100. / Statis->ttnbytes : 0.; + ouperc=(Statis->ttnbytes) ? Statis->ttnoucache *100. / Statis->ttnbytes : 0.; fprintf(fp_top3,"%3.2lf%%%3.2lf%%",inperc,ouperc); #ifdef ENABLE_DOUBLE_CHECK_DATA if (fabs(inperc+ouperc-100.)>=0.01) { @@ -469,15 +349,15 @@ void topuser(void) #endif } if((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0) - fprintf(fp_top3,"%s",buildtime(ttnelap)); + fprintf(fp_top3,"%s",buildtime(Statis->ttnelap)); if((TopUserFields & TOPUSERFIELDS_MILISEC) != 0) - fprintf(fp_top3,"%s",fixnum2(ttnelap,1)); + fprintf(fp_top3,"%s",fixnum2(Statis->ttnelap,1)); fputs("\n",fp_top3); } greport_cleanup(); - if(ntopuser && (TopUserFields & TOPUSERFIELDS_AVERAGE) != 0) { + if (ntopuser && (TopUserFields & TOPUSERFIELDS_AVERAGE) != 0) { fputs("",fp_top3); if((TopUserFields & TOPUSERFIELDS_NUM) != 0) fputs("",fp_top3); @@ -489,19 +369,19 @@ void topuser(void) fprintf(fp_top3,"%s",_("AVERAGE")); if((TopUserFields & TOPUSERFIELDS_CONNECT) != 0) - fprintf(fp_top3,"%s",fixnum(ttnacc/totuser,1)); + fprintf(fp_top3,"%s",fixnum(Statis->ttnacc/Statis->totuser,1)); if((TopUserFields & TOPUSERFIELDS_BYTES) != 0) { - tnbytes=(totuser) ? ttnbytes / totuser : 0; - fprintf(fp_top3,"%15s",fixnum(tnbytes,1)); + nbytes=(Statis->totuser) ? Statis->ttnbytes / Statis->totuser : 0; + fprintf(fp_top3,"%15s",fixnum(nbytes,1)); } if((TopUserFields & TOPUSERFIELDS_SETYB) != 0) fputs("",fp_top3); if((TopUserFields & TOPUSERFIELDS_IN_CACHE_OUT) != 0) fputs("",fp_top3); if((TopUserFields & TOPUSERFIELDS_USED_TIME) != 0) - fprintf(fp_top3,"%s",buildtime(ttnelap/totuser)); + fprintf(fp_top3,"%s",buildtime(Statis->ttnelap/Statis->totuser)); if((TopUserFields & TOPUSERFIELDS_MILISEC) != 0) - fprintf(fp_top3,"%s",fixnum2(ttnelap/totuser,1)); + fprintf(fp_top3,"%s",fixnum2(Statis->ttnelap/Statis->totuser,1)); fputs("\n",fp_top3); } @@ -511,6 +391,159 @@ void topuser(void) debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top3,strerror(errno)); exit(EXIT_FAILURE); } +} + +/*! + * Produce a report with the user downloading the most data. + */ +void topuser(void) +{ + FileObject *fp_in = NULL; + FILE *fp_top2; + char wger[MAXLEN]; + char top1[MAXLEN]; + char top2[MAXLEN]; + longline line; + long long int tnacc=0; + long long int tnbytes=0, tnelap=0; + long long int tnincache=0, tnoucache=0; + char *warea; + struct generalitemstruct item; + char olduser[MAX_USER_LEN], csort[MAXLEN]; + const char *sfield="-n -k 2,2"; + const char *order; + int cstatus; + struct TopUserStatistics Statis; + struct SortInfoStruct SortInfo; + + if (debugz>=LogLevel_Process) + debuga(__FILE__,__LINE__,_("Creating top users report...\n")); + + memset(&Statis,0,sizeof(Statis)); + + snprintf(wger,sizeof(wger),"%s/sarg-general",outdirname); + if ((fp_in=FileObject_Open(wger))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wger,FileObject_GetLastOpenError()); + exit(EXIT_FAILURE); + } + + snprintf(top2,sizeof(top2),"%s/top.tmp",outdirname); + if ((fp_top2=fopen(top2,"w"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),top2,strerror(errno)); + exit(EXIT_FAILURE); + } + + olduser[0]='\0'; + + if ((line=longline_create())==NULL) { + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wger); + exit(EXIT_FAILURE); + } + + while ((warea=longline_read(fp_in,line))!=NULL) { + ger_read(warea,&item,wger); + if (item.total) continue; + if (strcmp(olduser,item.user) != 0) { + Statis.totuser++; + + if (olduser[0] != '\0') { + /* + This complicated printf is due to Microsoft's inability to comply with any standard. Msvcrt is unable + to print a long long int unless it is exactly 64-bits long. + */ + fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap,(uint64_t)tnincache,(uint64_t)tnoucache); + + Statis.ttnbytes+=tnbytes; + Statis.ttnacc+=tnacc; + Statis.ttnelap+=tnelap; + Statis.ttnincache+=tnincache; + Statis.ttnoucache+=tnoucache; + } + safe_strcpy(olduser,item.user,sizeof(olduser)); + tnbytes=0; + tnacc=0; + tnelap=0; + tnincache=0; + tnoucache=0; + } + + tnbytes+=item.nbytes; + tnacc+=item.nacc; + tnelap+=item.nelap; + tnincache+=item.incache; + tnoucache+=item.oucache; + } + if (FileObject_Close(fp_in)) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wger,FileObject_GetLastCloseError()); + exit(EXIT_FAILURE); + } + longline_destroy(&line); + + if (olduser[0] != '\0') { + /* + This complicated printf is due to Microsoft's inability to comply with any standard. Msvcrt is unable + to print a long long int unless it is exactly 64-bits long. + */ + fprintf(fp_top2,"%s\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\t%"PRIu64"\n",olduser,(uint64_t)tnbytes,(uint64_t)tnacc,(uint64_t)tnelap,(uint64_t)tnincache,(uint64_t)tnoucache); + + Statis.ttnbytes+=tnbytes; + Statis.ttnacc+=tnacc; + Statis.ttnelap+=tnelap; + Statis.ttnincache+=tnincache; + Statis.ttnoucache+=tnoucache; + } + if (fclose(fp_top2)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),top2,strerror(errno)); + exit(EXIT_FAILURE); + } + +#ifdef ENABLE_DOUBLE_CHECK_DATA + if (Statis.ttnacc!=globstat.nacc || Statis.ttnbytes!=globstat.nbytes || Statis.ttnelap!=globstat.elap || + Statis.ttnincache!=globstat.incache || Statis.ttnoucache!=globstat.oucache) { + debuga(__FILE__,__LINE__,_("Total statistics mismatch when reading \"%s\" to produce the top users\n"),wger); + exit(EXIT_FAILURE); + } +#endif + + set_total_users(Statis.totuser); + + if((TopuserSort & TOPUSER_SORT_USER) != 0) { + sfield="-k 1,1"; + SortInfo.sort_field=_("user"); + } else if((TopuserSort & TOPUSER_SORT_CONNECT) != 0) { + sfield="-n -k 3,3"; + SortInfo.sort_field=_("connect"); + } else if((TopuserSort & TOPUSER_SORT_TIME) != 0) { + sfield="-n -k 4,4"; + SortInfo.sort_field=pgettext("duration","time"); + } else { + SortInfo.sort_field=_("bytes"); + } + + if((TopuserSort & TOPUSER_SORT_REVERSE) == 0) { + order=""; + SortInfo.sort_order=_("normal"); + } else { + order="-r"; + SortInfo.sort_order=_("reverse"); + } + + snprintf(top1,sizeof(top1),"%s/top",outdirname); + if (snprintf(csort,sizeof(csort),"sort -T \"%s\" -t \"\t\" %s %s -o \"%s\" \"%s\"", tmp, order, sfield, top1, top2)>=sizeof(csort)) { + debuga(__FILE__,__LINE__,_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),top2,top1); + exit(EXIT_FAILURE); + } + cstatus=system(csort); + if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) { + debuga(__FILE__,__LINE__,_("sort command return status %d\n"),WEXITSTATUS(cstatus)); + debuga(__FILE__,__LINE__,_("sort command: %s\n"),csort); + exit(EXIT_FAILURE); + } + + if (!KeepTempLog && unlink(top2)) { + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),top2,strerror(errno)); + exit(EXIT_FAILURE); + } - return; + TopUser_HtmlReport(top1,&Statis,&SortInfo); }