"Fossies" - the Fresh Open Source Software Archive

Member "sarg-2.4.0/log.c" (24 Dec 2019, 24430 Bytes) of package /linux/privat/sarg-2.4.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "log.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.11_vs_2.4.0.

    1 /*
    2  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
    3  *                                                            1998, 2015
    4  *
    5  * SARG donations:
    6  *      please look at http://sarg.sourceforge.net/donations.php
    7  * Support:
    8  *     http://sourceforge.net/projects/sarg/forums/forum/363374
    9  * ---------------------------------------------------------------------
   10  *
   11  *  This program is free software; you can redistribute it and/or modify
   12  *  it under the terms of the GNU General Public License as published by
   13  *  the Free Software Foundation; either version 2 of the License, or
   14  *  (at your option) any later version.
   15  *
   16  *  This program is distributed in the hope that it will be useful,
   17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19  *  GNU General Public License for more details.
   20  *
   21  *  You should have received a copy of the GNU General Public License
   22  *  along with this program; if not, write to the Free Software
   23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   24  *
   25  */
   26 
   27 #include "include/conf.h"
   28 #include "include/defs.h"
   29 #include "include/readlog.h"
   30 #include "include/filelist.h"
   31 
   32 #ifdef HAVE_GETOPT_H
   33 #include <getopt.h>
   34 #endif
   35 
   36 //! The log file filtering.
   37 struct ReadLogDataStruct ReadFilter;
   38 
   39 //! The list of the system users.
   40 /*@null@*/char *userfile=NULL;
   41 
   42 //! List of the input log files to process.
   43 FileListObject AccessLog=NULL;
   44 //! Selected locale set through the environment variable.
   45 char *CurrentLocale=NULL;
   46 //! Set to \c true if a useragent log is provided on the command line.
   47 bool UserAgentFromCmdLine=false;
   48 
   49 extern FileListObject UserAgentLog;
   50 
   51 static void getusers(const char *pwdfile, int debug);
   52 static void CleanTemporaryDir();
   53 
   54 int main(int argc,char *argv[])
   55 {
   56     extern int optind;
   57     extern int optopt;
   58     extern char *optarg;
   59 
   60     char hm_str[15];
   61     char hexclude[MAXLEN];
   62     char splitprefix[MAXLEN];
   63     int  ch;
   64     int  errflg=0;
   65     bool  dns=false;
   66     int  iarq=0;
   67     int lastlog=-1;
   68     int LogStatus;
   69     bool realt;
   70     bool userip;
   71     time_t start_time;
   72     time_t end_time;
   73     time_t read_start_time;
   74     time_t read_end_time;
   75     time_t process_start_time;
   76     time_t process_end_time;
   77     double read_elapsed;
   78     double process_elapsed;
   79     FileListIterator FIter;
   80     static int split=0;
   81     static int convert=0;
   82     static int output_css=0;
   83     static int show_statis=0;
   84     static int show_version=0;
   85     int option_index;
   86     static struct option long_options[]=
   87     {
   88         {"convert",no_argument,&convert,1},
   89         {"css",no_argument,&output_css,1},
   90         {"help",no_argument,NULL,'h'},
   91         {"lastlog",required_argument,NULL,2},
   92         {"keeplogs",no_argument,NULL,3},
   93         {"split",no_argument,&split,1},
   94         {"splitprefix",required_argument,NULL,'P'},
   95         {"statistics",no_argument,&show_statis,1},
   96         {"version",no_argument,&show_version,'V'},
   97         {0,0,0,0}
   98     };
   99 
  100     start_time=time(NULL);
  101 
  102 #ifdef HAVE_LOCALE_H
  103     setlocale(LC_TIME,"");
  104 #endif
  105 
  106 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
  107     CurrentLocale=setlocale (LC_ALL, "");
  108     if (!CurrentLocale) {
  109         fprintf(stderr,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
  110         exit(EXIT_FAILURE);
  111     }
  112     if (!bindtextdomain (PACKAGE_NAME, LOCALEDIR)) {
  113         fprintf(stderr,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME,LOCALEDIR,strerror(errno));
  114         exit(EXIT_FAILURE);
  115     }
  116     if (!textdomain (PACKAGE_NAME)) {
  117         fprintf(stderr,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME,strerror(errno));
  118         exit(EXIT_FAILURE);
  119     }
  120 #endif //ENABLE_NLS
  121 
  122     BgImage[0]='\0';
  123     LogoImage[0]='\0';
  124     LogoText[0]='\0';
  125     PasswdFile[0]='\0';
  126     OutputEmail[0]='\0';
  127     ExcludeHosts[0]='\0';
  128     ExcludeUsers[0]='\0';
  129     ConfigFile[0]='\0';
  130     code[0]='\0';
  131     LastLog=0;
  132     ReportType=0UL;
  133     UserTabFile[0]='\0';
  134     BlockIt[0]='\0';
  135     ExternalCSSFile[0]='\0';
  136     RedirectorLogFormat[0]='\0';
  137     NRedirectorLogs=0;
  138 
  139     snprintf(ExcludeCodes,sizeof(ExcludeCodes),"%s/exclude_codes",SYSCONFDIR);
  140     strcpy(GraphDaysBytesBarColor,"orange");
  141     strcpy(BgColor,"#ffffff");
  142     strcpy(TxColor,"#000000");
  143     strcpy(TxBgColor,"lavender");
  144     strcpy(TiColor,"darkblue");
  145     strcpy(Width,"80");
  146     strcpy(Height,"45");
  147     strcpy(LogoTextColor,"#000000");
  148     strcpy(HeaderColor,"darkblue");
  149     strcpy(HeaderBgColor,"#dddddd");
  150     strcpy(LogoTextColor,"#006699");
  151     strcpy(FontSize,"9px");
  152     strcpy(TempDir,"/tmp");
  153     TempDirPath[0] = '\0';
  154     strcpy(OutputDir,"/var/www/html/squid-reports");
  155     AnonymousOutputFiles=false;
  156     Ip2Name=false;
  157     DateFormat='u';
  158     OverwriteReport=false;
  159     RemoveTempFiles=true;
  160     strcpy(ReplaceIndex,INDEX_HTML_FILE);
  161     Index=INDEX_YES;
  162     RecordsWithoutUser=RECORDWITHOUTUSER_IP;
  163     UseComma=0;
  164     strcpy(MailUtility,"mailx");
  165     TopSitesNum=100;
  166     TopUsersNum=0;
  167     UserIp=0;
  168     TopuserSort=TOPUSER_SORT_BYTES | TOPUSER_SORT_REVERSE;
  169     UserSort=USER_SORT_BYTES | USER_SORT_REVERSE;
  170     TopsitesSort=TOPSITE_SORT_CONNECT | TOPSITE_SORT_REVERSE;
  171     LongUrl=0;
  172     strcpy(FontFace,"Verdana,Tahoma,Arial");
  173     datetimeby=DATETIME_BYTE;
  174     strcpy(CharSet,"ISO-8859-1");
  175     Privacy=0;
  176     strcpy(PrivacyString,"***.***.***.***");
  177     strcpy(PrivacyStringColor,"blue");
  178     SuccessfulMsg=true;
  179     TopUserFields=TOPUSERFIELDS_NUM | TOPUSERFIELDS_DATE_TIME | TOPUSERFIELDS_USERID | TOPUSERFIELDS_CONNECT |
  180           TOPUSERFIELDS_BYTES | TOPUSERFIELDS_SETYB | TOPUSERFIELDS_IN_CACHE_OUT |
  181           TOPUSERFIELDS_USED_TIME | TOPUSERFIELDS_MILISEC | TOPUSERFIELDS_PTIME |
  182           TOPUSERFIELDS_TOTAL | TOPUSERFIELDS_AVERAGE;
  183     UserReportFields=USERREPORTFIELDS_CONNECT | USERREPORTFIELDS_BYTES | USERREPORTFIELDS_SETYB |
  184           USERREPORTFIELDS_IN_CACHE_OUT | USERREPORTFIELDS_USED_TIME | USERREPORTFIELDS_MILISEC |
  185           USERREPORTFIELDS_PTIME | USERREPORTFIELDS_TOTAL | USERREPORTFIELDS_AVERAGE;
  186     strcpy(DataFileDelimiter,";");
  187     DataFileFields=DATA_FIELD_USER | DATA_FIELD_DATE | DATA_FIELD_TIME | DATA_FIELD_URL | DATA_FIELD_CONNECT |
  188           DATA_FIELD_BYTES | DATA_FIELD_IN_CACHE | DATA_FIELD_OUT_CACHE | DATA_FIELD_ELAPSED;
  189     ShowReadStatistics=true;
  190     ShowReadPercent=false;
  191     strcpy(IndexSortOrder,"D");
  192     ShowSargInfo=true;
  193     ShowSargLogo=true;
  194     ParsedOutputLog[0]='\0';
  195     strcpy(ParsedOutputLogCompress,"/bin/gzip -f");
  196     DisplayedValues=DISPLAY_ABBREV;
  197     strcpy(HeaderFontSize,"9px");
  198     strcpy(TitleFontSize,"11px");
  199     strcpy(AuthUserTemplateFile,"sarg_htaccess");
  200     set_download_suffix("7z,ace,arj,avi,bat,bin,bz2,bzip,cab,com,cpio,dll,doc,dot,exe,gz,iso,lha,lzh,mdb,mov,mp3,mpeg,mpg,mso,nrg,ogg,ppt,rar,rtf,shs,src,sys,tar,tgz,vcd,vob,wma,wmv,zip");
  201     Graphs=true;
  202 #if defined(FONTDIR)
  203     strcpy(GraphFont,FONTDIR"/DejaVuSans.ttf");
  204 #else
  205     GraphFont[0]='\0';
  206 #endif
  207     strcpy(Ulimit,"20000");
  208     NtlmUserFormat=NTLMUSERFORMAT_DOMAINUSER;
  209     IndexTree=INDEX_TREE_FILE;
  210     IndexFields=INDEXFIELDS_DIRSIZE;
  211     strcpy(RealtimeTypes,"GET,PUT,CONNECT,POST");
  212     RealtimeUnauthRec=REALTIME_UNAUTH_REC_SHOW;
  213     RedirectorFilterOutDate=true;
  214     DansguardianFilterOutDate=true;
  215     DataFileUrl=DATAFILEURL_IP;
  216     strcpy(MaxElapsed,"28800000");
  217     BytesInSitesUsersReport=0;
  218     UserAuthentication=0;
  219     strcpy(LDAPHost,"127.0.0.1");
  220     LDAPPort=389;
  221     LDAPProtocolVersion=3;
  222     LDAPBindDN[0]='\0';
  223     LDAPBindPW[0]='\0';
  224     LDAPBaseSearch[0]='\0';
  225     strcpy(LDAPFilterSearch, "(uid=%s)");
  226     strcpy(LDAPTargetAttr, "cn");
  227     LDAPNativeCharset[0]='\0';
  228     SortTableJs[0]='\0';
  229 
  230     tmp[0]='\0';
  231     us[0]='\0';
  232     ReadFilter.DateRange[0]='\0';
  233     df='\0';
  234     hexclude[0]='\0';
  235     addr[0]='\0';
  236     ReadFilter.StartTime=-1;
  237     ReadFilter.EndTime=-1;
  238     site[0]='\0';
  239     outdir[0]='\0';
  240     splitprefix[0]='\0';
  241     email[0]='\0';
  242     UserInvalidChar[0]='\0';
  243     DataFile[0]='\0';
  244     SquidGuardConf[0]='\0';
  245     DansGuardianConf[0]='\0';
  246     hm_str[0]='\0';
  247     HostAliasFile[0]='\0';
  248     UserAliasFile[0]='\0';
  249 
  250     dansguardian_count=0;
  251     redirector_count=0;
  252     useragent_count=0;
  253     DeniedReportLimit=10;
  254     SiteUsersReportLimit=0;
  255     AuthfailReportLimit=10;
  256     DansGuardianReportLimit=10;
  257     SquidGuardReportLimit=10;
  258     DownloadReportLimit=50;
  259     UserReportLimit=0;
  260     debug=0;
  261     debugz=0;
  262     iprel=false;
  263     userip=false;
  264     realt=false;
  265     realtime_refresh=3;
  266     realtime_access_log_lines=1000;
  267     cost=0.01;
  268     nocost=50000000;
  269     squid24=false;
  270     ReadFilter.StartDate=0;
  271     ReadFilter.EndDate=0;
  272     KeepTempLog=false;
  273     NumLogSuccessiveErrors=3;
  274     NumLogTotalErrors=50;
  275     lines_read=0UL;
  276     records_kept=0UL;
  277     nusers=0UL;
  278 
  279     memset(IncludeUsers,0,sizeof(IncludeUsers));
  280     memset(ExcludeString,0,sizeof(ExcludeString));
  281     memset(&period,0,sizeof(period));
  282 
  283     AccessLogFromCmdLine=0;
  284     RedirectorLogFromCmdLine=0;
  285 
  286     strcpy(Title,_("Squid User Access Report"));
  287 
  288     while((ch = getopt_long(argc, argv, "a:b:c:d:e:f:g:hikl:L:no:P:prs:t:u:Vw:xyz",long_options,&option_index)) != -1){
  289         switch(ch)
  290         {
  291             case 0:
  292                 break;
  293             case 2:
  294                 lastlog=atoi(optarg);
  295                 break;
  296             case 3:
  297                 lastlog=0;
  298                 break;
  299             case 'a':
  300                 safe_strcpy(addr,optarg,sizeof(addr));
  301                 break;
  302             case 'b': //unused option
  303                 UserAgentFromCmdLine=true;
  304                 if (!UserAgentLog)
  305                     UserAgentLog=FileList_Create();
  306                 if (!FileList_AddFile(UserAgentLog,optarg)) {
  307                     debuga(__FILE__,__LINE__,_("Not enough memory to store a user agent file name\n"));
  308                     exit(EXIT_FAILURE);
  309                 }
  310                 break;
  311             case 'c':
  312                 safe_strcpy(hexclude,optarg,sizeof(hexclude));
  313                 break;
  314             case 'd':
  315                 safe_strcpy(ReadFilter.DateRange,optarg,sizeof(ReadFilter.DateRange));
  316                 date_from(&ReadFilter);
  317                 break;
  318             case 'e':
  319                 safe_strcpy(email,optarg,sizeof(email));
  320                 break;
  321             case 'f':
  322                 safe_strcpy(ConfigFile,optarg,sizeof(ConfigFile));
  323                 break;
  324             case 'g':
  325                 df=*optarg;
  326                 break;
  327             case 'h':
  328                 usage(argv[0]);
  329                 exit(EXIT_SUCCESS);
  330             case 'i':
  331                 iprel=true;
  332                 break;
  333             case 'k':
  334                 KeepTempLog=true;
  335                 break;
  336             case 'l':
  337                 if (!AccessLog)
  338                     AccessLog=FileList_Create();
  339                 if (!FileList_AddFile(AccessLog,optarg)) {
  340                     debuga(__FILE__,__LINE__,_("Not enough memory to store the input log file names\n"));
  341                     exit(EXIT_FAILURE);
  342                 }
  343                 AccessLogFromCmdLine++;
  344                 break;
  345             case 'L':
  346                 if (NRedirectorLogs>MAX_REDIRECTOR_LOGS) {
  347                     debuga(__FILE__,__LINE__,_("Too many redirector logs passed on command line with option -L.\n"));
  348                     exit(EXIT_FAILURE);
  349                 }
  350                 if (strlen(optarg)>=MAX_REDIRECTOR_FILELEN) {
  351                     debuga(__FILE__,__LINE__,_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg);
  352                     exit(EXIT_FAILURE);
  353                 }
  354                 strcpy(RedirectorLogs[NRedirectorLogs],optarg);
  355                 NRedirectorLogs++;
  356                 RedirectorLogFromCmdLine++;
  357                 break;
  358             case 'n':
  359                 dns=true;
  360                 break;
  361             case 'o':
  362                 safe_strcpy(outdir,optarg,sizeof(outdir));
  363                 break;
  364             case 'p':
  365                 userip=true;
  366                 break;
  367             case 'P':
  368                 safe_strcpy(splitprefix,optarg,sizeof(splitprefix));
  369                 break;
  370             case 'r':
  371                 realt=true;
  372                 break;
  373             case 's':
  374                 safe_strcpy(site,optarg,sizeof(site));
  375                 break;
  376             case 't':
  377             {
  378                 int h1,m1,h2,m2;
  379 
  380                 if (strstr(optarg,"-") == 0) {
  381                     if (sscanf(optarg,"%d:%d",&h1,&m1)!=2) {
  382                         debuga(__FILE__,__LINE__,_("Time period passed on the command line with option -t must be HH:MM\n"));
  383                         exit(EXIT_FAILURE);
  384                     }
  385                     ReadFilter.StartTime=h1*100+m1;
  386                     ReadFilter.EndTime=ReadFilter.StartTime+1;
  387                     snprintf(hm_str,sizeof(hm_str),"%02d:%02d",h1,m1);
  388                 } else {
  389                     if (sscanf(optarg,"%d:%d-%d:%d",&h1,&m1,&h2,&m2)!=4) {
  390                         debuga(__FILE__,__LINE__,_("Time range passed on the command line with option -t must be HH:MM-HH:MM\n"));
  391                         exit(EXIT_FAILURE);
  392                     }
  393                     ReadFilter.StartTime=h1*100+m1;
  394                     ReadFilter.EndTime=h2*100+m2;
  395                     snprintf(hm_str,sizeof(hm_str),"%02d:%02d-%02d:%02d",h1,m1,h2,m2);
  396                 }
  397                 break;
  398             }
  399             case 'u':
  400                 safe_strcpy(us,optarg,sizeof(us));
  401                 break;
  402             case 'V':
  403                 show_version=1;
  404                 break;
  405             case 'w':
  406                 safe_strcpy(tmp,optarg,sizeof(tmp));
  407                 break;
  408             case 'x':
  409                 debug++;
  410                 break;
  411             case 'y': //unused option
  412                 langcode++;
  413                 break;
  414             case 'z':
  415                 debugz++;
  416                 break;
  417             case ':':
  418                 debuga(__FILE__,__LINE__,_("Option -%c requires an argument\n"),optopt);
  419                 exit(EXIT_FAILURE);
  420             case '?':
  421                 usage(argv[0]);
  422                 exit(EXIT_FAILURE);
  423             default:
  424                 abort();
  425         }
  426     }
  427 
  428     if (errflg>0) {
  429         usage(argv[0]);
  430         exit(2);
  431     }
  432     if (show_version) {
  433         version();
  434     }
  435 
  436     if (output_css) {
  437         css_content(stdout);
  438         exit(EXIT_SUCCESS);
  439     }
  440 
  441     if (optind<argc) {
  442         if (!AccessLog)
  443             AccessLog=FileList_Create();
  444         for (iarq=optind ; iarq<argc ; iarq++) {
  445             if (!FileList_AddFile(AccessLog,argv[iarq])) {
  446                 debuga(__FILE__,__LINE__,_("Not enough memory to store the input log file names\n"));
  447                 exit(EXIT_FAILURE);
  448             }
  449             AccessLogFromCmdLine++;
  450         }
  451     }
  452 
  453     if (debug) debuga(__FILE__,__LINE__,_("Init\n"));
  454 
  455     if (ConfigFile[0] == '\0') snprintf(ConfigFile,sizeof(ConfigFile),"%s/sarg.conf",SYSCONFDIR);
  456     if (access(ConfigFile, R_OK) != 0) {
  457         debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ConfigFile,strerror(errno));
  458         exit(EXIT_FAILURE);
  459     }
  460 
  461     if (access(ConfigFile, R_OK) == 0)
  462         getconf(ConfigFile);
  463 
  464     if (userip) UserIp=true;
  465 
  466     if (dns) ip2name_forcedns();
  467 
  468     if (lastlog>=0) LastLog=lastlog;
  469 
  470     if (outdir[0] == '\0') strcpy(outdir,OutputDir);
  471     if (outdir[0] != '\0') strcat(outdir,"/");
  472 
  473     if (IndexTree == INDEX_TREE_FILE)
  474         strcpy(ImageFile,"../images");
  475     else
  476         strcpy(ImageFile,"../../../images");
  477 
  478     dataonly=(DataFile[0] != '\0');
  479 
  480     if (df=='\0') df=DateFormat;
  481     if (df=='\0') df='u';
  482     if (df=='w')
  483         IndexTree=INDEX_TREE_FILE;
  484 
  485     if (AccessLog==NULL) {
  486         AccessLog=FileList_Create();
  487         if (!FileList_AddFile(AccessLog,"/var/log/squid/access.log")) {
  488             debuga(__FILE__,__LINE__,_("Not enough memory to store the input log file names\n"));
  489             exit(EXIT_FAILURE);
  490         }
  491     }
  492 
  493     if (realt) {
  494         realtime();
  495         exit(EXIT_SUCCESS);
  496     }
  497     if (split) {
  498         const char *file;
  499 
  500         FIter=FileListIter_Open(AccessLog);
  501         while ((file=FileListIter_Next(FIter))!=NULL)
  502             splitlog(file, df, &ReadFilter, convert, splitprefix);
  503         FileListIter_Close(FIter);
  504         exit(EXIT_SUCCESS);
  505     }
  506     if (convert) {
  507         const char *file;
  508 
  509         FIter=FileListIter_Open(AccessLog);
  510         while ((file=FileListIter_Next(FIter))!=NULL)
  511             convlog(file, df, &ReadFilter);
  512         FileListIter_Close(FIter);
  513         exit(EXIT_SUCCESS);
  514     }
  515 
  516     load_excludecodes(ExcludeCodes);
  517 
  518     if (access(PasswdFile, R_OK) == 0) {
  519         getusers(PasswdFile,debug);
  520         ReadFilter.SysUsers=true;
  521     } else {
  522         ReadFilter.SysUsers=false;
  523     }
  524 
  525     if (hexclude[0] == '\0')
  526         strcpy(hexclude,ExcludeHosts);
  527     if (hexclude[0] != '\0') {
  528         gethexclude(hexclude,debug);
  529         ReadFilter.HostFilter=true;
  530     } else {
  531         ReadFilter.HostFilter=false;
  532     }
  533 
  534     if (ReportType == 0) {
  535         ReportType=REPORT_TYPE_TOPUSERS | REPORT_TYPE_TOPSITES | REPORT_TYPE_USERS_SITES |
  536                    REPORT_TYPE_SITES_USERS | REPORT_TYPE_DATE_TIME | REPORT_TYPE_DENIED |
  537                    REPORT_TYPE_AUTH_FAILURES | REPORT_TYPE_SITE_USER_TIME_DATE |
  538                    REPORT_TYPE_DOWNLOADS | REPORT_TYPE_USERAGENT;
  539     }
  540     if (!FileList_IsEmpty(UserAgentLog))
  541         ReportType|=REPORT_TYPE_USERAGENT;
  542 
  543     if (access(ExcludeUsers, R_OK) == 0) {
  544         getuexclude(ExcludeUsers,debug);
  545         ReadFilter.UserFilter=true;
  546     } else {
  547         ReadFilter.UserFilter=false;
  548     }
  549     if (HostAliasFile[0] != '\0')
  550         read_hostalias(HostAliasFile);
  551     if (UserAliasFile[0] != '\0')
  552         read_useralias(UserAliasFile);
  553 
  554     indexonly=false;
  555     if (ReadFilter.UserFilter) {
  556         if (is_indexonly())
  557             indexonly=true;
  558     }
  559     if (strcmp(ExcludeUsers,"indexonly") == 0) indexonly=true;
  560     if (Index == INDEX_ONLY) indexonly=true;
  561 
  562     if (MaxElapsed[0] != '\0')
  563         ReadFilter.max_elapsed=atol(MaxElapsed);
  564     else
  565         ReadFilter.max_elapsed=0;
  566 
  567     if (tmp[0] == '\0') strcpy(tmp,TempDir);
  568     else strcpy(TempDir,tmp);
  569     /*
  570     For historical reasons, the temporary directory used to be subdirectory "sarg" of the path
  571     provided by the user. The full temporary directory was the predictable name /tmp/sarg. It is unsafe
  572     to use a predictable name in the world writable /tmp as malicious users might use that knowledge
  573     to lure sarg into some kind of nasty activity it was not designed for.
  574     The default is now to use a random name safely created by the system but it is still possible to
  575     use a known fixed path set with a parameter in sarg.conf.
  576     */
  577     if (TempDirPath[0]) {
  578         append_to_path(tmp, sizeof(tmp), TempDirPath);
  579     } else {
  580         append_to_path(tmp, sizeof(tmp), "sargXXXXXX");
  581         if (mkdtemp(tmp) == NULL) {
  582             debuga(__FILE__,__LINE__,_("Failed to get a unique temporary directory name based on template \"%s\": %s\n"), tmp, strerror(errno));
  583             exit(EXIT_FAILURE);
  584         }
  585     }
  586 
  587     if (tmp[0]!='\0' && strncmp(outdir,tmp,strlen(tmp))==0) {
  588         debuga(__FILE__,__LINE__,_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir,tmp);
  589         exit(EXIT_FAILURE);
  590     }
  591     atexit(CleanTemporaryDir);
  592 
  593     if (email[0] == '\0' && OutputEmail[0] != '\0') strcpy(email,OutputEmail);
  594 
  595     if (email[0] != '\0') {
  596         my_mkdir(tmp);
  597         strcpy(outdir,tmp);
  598         strcat(outdir,"/");
  599     }
  600 
  601     makeTmpDir(tmp);
  602 
  603     if (debug) {
  604         const char *file;
  605 
  606         debuga(__FILE__,__LINE__,_("Parameters:\n"));
  607         debuga(__FILE__,__LINE__,_("          Hostname or IP address (-a) = %s\n"),addr);
  608         FIter=FileListIter_Open(UserAgentLog);
  609         while ((file=FileListIter_NextWithMask(FIter))!=NULL)
  610             debuga(__FILE__,__LINE__,_("                   Useragent log (-b) = %s\n"),file);
  611         FileListIter_Close(FIter);
  612         debuga(__FILE__,__LINE__,_("                    Exclude file (-c) = %s\n"),hexclude);
  613         debuga(__FILE__,__LINE__,_("                 Date from-until (-d) = %s\n"),ReadFilter.DateRange);
  614         debuga(__FILE__,__LINE__,_("   Email address to send reports (-e) = %s\n"),email);
  615         debuga(__FILE__,__LINE__,_("                     Config file (-f) = %s\n"),ConfigFile);
  616         if (df=='e')
  617             debuga(__FILE__,__LINE__,_("                     Date format (-g) = Europe (dd/mm/yyyy)\n"));
  618         else if (df=='u')
  619             debuga(__FILE__,__LINE__,_("                     Date format (-g) = USA (mm/dd/yyyy)\n"));
  620         else if (df=='w')
  621             debuga(__FILE__,__LINE__,_("                     Date format (-g) = Sites & Users (yyyy/ww)\n"));
  622         debuga(__FILE__,__LINE__,_("                       IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
  623         debuga(__FILE__,__LINE__,_("            Keep temporary files (-k) = %s\n"),(KeepTempLog) ? _("Yes") : _("No"));
  624         FIter=FileListIter_Open(AccessLog);
  625         while ((file=FileListIter_NextWithMask(FIter))!=NULL)
  626             debuga(__FILE__,__LINE__,_("                       Input log (-l) = %s\n"),file);
  627         FileListIter_Close(FIter);
  628         for (iarq=0 ; iarq<NRedirectorLogs ; iarq++)
  629             debuga(__FILE__,__LINE__,_("                  Redirector log (-L) = %s\n"),RedirectorLogs[iarq]);
  630         debuga(__FILE__,__LINE__,_("              Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
  631         debuga(__FILE__,__LINE__,_("                      Output dir (-o) = %s\n"),outdir);
  632         debuga(__FILE__,__LINE__,_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
  633         debuga(__FILE__,__LINE__,_("                   Accessed site (-s) = %s\n"),site);
  634         debuga(__FILE__,__LINE__,_("                            Time (-t) = %s\n"),hm_str);
  635         debuga(__FILE__,__LINE__,_("                            User (-u) = %s\n"),us);
  636         debuga(__FILE__,__LINE__,_("                   Temporary dir (-w) = %s\n"),tmp);
  637         debuga(__FILE__,__LINE__,_("                  Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
  638         debuga(__FILE__,__LINE__,_("                Process messages (-z) = %d\n"),debugz);
  639         debuga(__FILE__,__LINE__,_(" Previous reports to keep (--lastlog) = %d\n"),LastLog);
  640         debuga(__FILE__,__LINE__,"\n");
  641     }
  642 
  643     if (debug)
  644         debuga(__FILE__,__LINE__,_("sarg version: %s\n"),VERSION);
  645 
  646 #ifdef ENABLE_DOUBLE_CHECK_DATA
  647     debuga(__FILE__,__LINE__,_("Sarg compiled to report warnings if the output is inconsistent\n"));
  648 #endif
  649 
  650 #ifdef HAVE_RLIM_T
  651     if (Ulimit[0] != '\0') {
  652         struct rlimit rl;
  653         long l1, l2;
  654         int rc=0;
  655 
  656 #if defined(RLIMIT_NOFILE)
  657         getrlimit (RLIMIT_NOFILE, &rl);
  658 #elif defined(RLIMIT_OFILE)
  659         getrlimit (RLIMIT_OFILE, &rl);
  660 #else
  661 #warning "No rlimit resource for the number of open files"
  662 #endif
  663         l1 = rl.rlim_cur;
  664         l2 = rl.rlim_max;
  665 
  666         rl.rlim_cur = atol(Ulimit);
  667         rl.rlim_max = atol(Ulimit);
  668 #if defined(RLIMIT_NOFILE)
  669         rc=setrlimit (RLIMIT_NOFILE, &rl);
  670 #elif defined(RLIMIT_OFILE)
  671         rc=setrlimit (RLIMIT_OFILE, &rl);
  672 #else
  673 #warning "No rlimit resource for the number of open files"
  674 #endif
  675         if (rc == -1) {
  676             debuga(_("setrlimit error: %s\n"),strerror(errno));
  677         }
  678 
  679         if (debug)
  680             debuga("Maximum file descriptor: cur=%ld max=%ld, changed to cur="RLIM_STRING" max="RLIM_STRING"\n",l1,l2,rl.rlim_cur,rl.rlim_max);
  681     }
  682 #endif
  683 
  684     read_start_time=time(NULL);
  685     LogStatus=ReadLogFile(&ReadFilter);
  686     read_end_time=time(NULL);
  687     read_elapsed=(double)read_end_time-(double)read_start_time;
  688 
  689     FileList_Destroy(&AccessLog);
  690     free_download();
  691     free_excludecodes();
  692     free_exclude();
  693 
  694     if (debug) {
  695         char date0[30], date1[30];
  696         struct tm Start,End;
  697 
  698         if (GetLogPeriod(&Start,&End)) {
  699             strftime(date0,sizeof(date0),"%x",&Start);
  700             strftime(date1,sizeof(date1),"%x",&End);
  701             // TRANSLATORS: The %s are the start and end dates in locale format.
  702             debuga(__FILE__,__LINE__,_("Period covered by log files: %s-%s\n"),date0,date1);
  703         }
  704     }
  705 
  706     if (!LogStatus){
  707         debuga(__FILE__,__LINE__,_("No records found\n"));
  708         debuga(__FILE__,__LINE__,_("End\n"));
  709         userinfo_free();
  710         if (userfile) free(userfile);
  711         close_usertab();
  712         exit(EXIT_SUCCESS);
  713     }
  714 
  715     if (debug) {
  716         char date0[30], date1[30];
  717 
  718         strftime(date0,sizeof(date0),"%x",&period.start);
  719         strftime(date1,sizeof(date1),"%x",&period.end);
  720         // TRANSLATORS: The %s are the start and end dates in locale format.
  721         debuga(__FILE__,__LINE__,_("Period extracted from log files: %s-%s\n"),date0,date1);
  722     }
  723     if (ReadFilter.DateRange[0] != '\0') {
  724         getperiod_fromrange(&period,&ReadFilter);
  725     }
  726     if (getperiod_buildtext(&period)<0) {
  727         debuga(__FILE__,__LINE__,_("Failed to build the string representation of the date range\n"));
  728         exit(EXIT_FAILURE);
  729     }
  730 
  731     process_start_time=time(NULL);
  732     if (DataFile[0] != '\0')
  733         data_file(tmp);
  734     else
  735         gerarel(&ReadFilter);
  736     process_end_time=time(NULL);
  737     process_elapsed=(double)process_end_time-(double)process_start_time;
  738 
  739     denied_cleanup();
  740     authfail_cleanup();
  741     download_cleanup();
  742     CleanTemporaryDir();
  743 
  744     ip2name_cleanup();
  745     free_hostalias();
  746     free_useralias();
  747     userinfo_free();
  748     if (userfile)
  749         free(userfile);
  750     close_usertab();
  751     FileList_Destroy(&UserAgentLog);
  752 
  753     end_time=time(NULL);
  754 
  755     if (show_statis) {
  756         double elapsed=(double)end_time-(double)start_time;
  757         debuga(__FILE__,__LINE__,_("Total execution time: %.0lf seconds\n"),elapsed);
  758         if (read_elapsed>0.) {
  759             debuga(__FILE__,__LINE__,_("Lines read: %lu lines in %.0lf seconds (%.0lf lines/s)\n"),lines_read,read_elapsed,(double)lines_read/read_elapsed);
  760         }
  761         if (process_elapsed>0.) {
  762             debuga(__FILE__,__LINE__,_("Processed records: %lu records in %.0lf seconds (%.0lf records/s)\n"),records_kept,process_elapsed,(double)records_kept/process_elapsed);
  763             debuga(__FILE__,__LINE__,_("Users: %lu users in %.0lf seconds (%.0lf users/s)\n"),nusers,process_elapsed,(double)nusers/process_elapsed);
  764         }
  765     }
  766 
  767     if (debug)
  768         debuga(__FILE__,__LINE__,_("End\n"));
  769 
  770     exit(EXIT_SUCCESS);
  771 }
  772 
  773 static void getusers(const char *pwdfile, int debug)
  774 {
  775     FILE *fp_usr;
  776     char buf[255];
  777     char *str;
  778     long int nreg=0;
  779 
  780     if (debug)
  781         debuga(__FILE__,__LINE__,_("Loading password file \"%s\"\n"),pwdfile);
  782 
  783     if ((fp_usr = fopen(pwdfile, "r")) == NULL) {
  784         debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),pwdfile,strerror(errno));
  785         exit(EXIT_FAILURE);
  786     }
  787 
  788     if (fseek(fp_usr, 0, SEEK_END)==-1) {
  789         debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),pwdfile,strerror(errno));
  790         exit(EXIT_FAILURE);
  791     }
  792     nreg = ftell(fp_usr);
  793     if (nreg<0) {
  794         debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),pwdfile);
  795         exit(EXIT_FAILURE);
  796     }
  797     nreg = nreg+5000;
  798     if (fseek(fp_usr, 0, SEEK_SET)==-1) {
  799         debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),pwdfile,strerror(errno));
  800         exit(EXIT_FAILURE);
  801     }
  802 
  803     if ((userfile=(char *) malloc(nreg))==NULL){
  804         debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),nreg);
  805         exit(EXIT_FAILURE);
  806     }
  807 
  808     memset(userfile,0,nreg);
  809     strcpy(userfile,":");
  810 
  811     while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
  812         str=strchr(buf,':');
  813         if (!str) {
  814             debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),pwdfile);
  815             exit(EXIT_FAILURE);
  816         }
  817         str[1]='\0';
  818         strcat(userfile,buf);
  819     }
  820 
  821     if (fclose(fp_usr)==EOF) {
  822         debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),pwdfile,strerror(errno));
  823         exit(EXIT_FAILURE);
  824     }
  825 
  826     return;
  827 }
  828 
  829 static void CleanTemporaryDir()
  830 {
  831     if (!KeepTempLog && strcmp(tmp,"/tmp") != 0) {
  832         unlinkdir(tmp,0);
  833     }
  834 }