]> git.ipfire.org Git - thirdparty/sarg.git/blob - log.c
Merge squidguard_log.c and squidguard_report.c into one file
[thirdparty/sarg.git] / log.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2011
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
30 #ifdef HAVE_GETOPT_H
31 #include <getopt.h>
32 #endif
33
34 #define REPORT_EVERY_X_LINES 5000
35 #define MAX_OPEN_USER_FILES 10
36
37 struct userfilestruct
38 {
39 struct userfilestruct *next;
40 struct userinfostruct *user;
41 FILE *file;
42 };
43
44 /*@null@*/static char *userfile=NULL;
45
46 numlist weekdays = { { 0, 1, 2, 3, 4, 5, 6 }, 7 };
47 numlist hours = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }, 24 };
48
49 static void getusers(const char *pwdfile, int debug);
50
51 int main(int argc,char *argv[])
52 {
53 enum isa_col_id {
54 ISACOL_Ip,
55 ISACOL_UserName,
56 ISACOL_Date,
57 ISACOL_Time,
58 ISACOL_TimeTaken,
59 ISACOL_Bytes,
60 ISACOL_Uri,
61 ISACOL_Status,
62 ISACOL_Last //last entry of the list !
63 };
64 enum InputLogFormat {
65 ILF_Unknown,
66 ILF_Squid,
67 ILF_Common,
68 ILF_Sarg,
69 ILF_Isa,
70 ILF_Last //last entry of the list !
71 };
72
73 FILE *fp_in = NULL, *fp_denied=NULL, *fp_authfail=NULL, *fp_log=NULL;
74
75 char sz_Download_Unsort[ 20000 ] ;
76 FILE * fp_Download_Unsort = NULL ;
77
78 extern int optind;
79 extern int optopt;
80 extern char *optarg;
81
82 char data[255];
83 char elap[255];
84 char ip[MAXLEN];
85 char tam[255];
86 char fun[MAXLEN];
87 char wuser[MAXLEN];
88 char smartfilter[MAXLEN];
89 char dia[128];
90 char mes[30];
91 char ano[30];
92 char hora[30];
93 char wtemp[MAXLEN];
94 char date[255];
95 char arq[255];
96 char arq_log[255];
97 int hm, hmf, hmr;
98 char hm_str[15];
99 char uagent[MAXLEN];
100 char hexclude[MAXLEN];
101 char csort[MAXLEN];
102 int cstatus;
103 char tbuf2[128];
104 char zip[20];
105 char *str;
106 char tmp3[MAXLEN];
107 char denied_unsort[MAXLEN];
108 char denied_sort[MAXLEN];
109 char authfail_unsort[MAXLEN];
110 char start_hour[128];
111 char end_hour[128];
112 char *linebuf;
113 const char *url;
114 char *full_url;
115 char *urly;
116 char user[MAX_USER_LEN];
117 char splitprefix[MAXLEN];
118 enum InputLogFormat ilf;
119 int ilf_count[ILF_Last];
120 int ch;
121 int x;
122 int errflg=0;
123 int puser=0;
124 bool fhost=false;
125 bool dns=false;
126 bool fuser=false;
127 int idata=0;
128 int mindate=0;
129 int maxdate=0;
130 int iarq=0;
131 int isa_ncols=0,isa_cols[ISACOL_Last];
132 int lastlog=-1;
133 bool from_stdin;
134 bool from_pipe;
135 int blen;
136 int maxopenfiles;
137 int nopen;
138 bool id_is_ip;
139 long totregsl=0;
140 long totregsg=0;
141 long totregsx=0;
142 bool totper=false;
143 long int max_elapsed=0;
144 long long int iyear, imonth, iday;
145 bool realt;
146 bool userip;
147 struct tm tt;
148 struct tm *t;
149 unsigned long recs1=0UL;
150 unsigned long recs2=0UL;
151 int OutputNonZero = REPORT_EVERY_X_LINES ;
152 bool download_flag=false;
153 char *download_url=NULL;
154 struct getwordstruct gwarea;
155 longline line;
156 time_t tnum;
157 struct stat logstat;
158 struct userinfostruct *uinfo;
159 struct userfilestruct *first_user_file, *ufile, *ufile1, *prev_ufile;
160 static int split=0;
161 static int convert=0;
162 static int output_css=0;
163 int option_index;
164 static struct option long_options[]=
165 {
166 {"convert",no_argument,&convert,1},
167 {"css",no_argument,&output_css,1},
168 {"lastlog",required_argument,NULL,2},
169 {"keeplogs",no_argument,NULL,3},
170 {"split",no_argument,&split,1},
171 {"splitprefix",required_argument,NULL,'P'},
172 {0,0,0,0}
173 };
174
175 #ifdef HAVE_LOCALE_H
176 setlocale(LC_TIME,"");
177 #endif
178
179 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
180 if (!setlocale (LC_ALL, "")) {
181 fprintf(stderr,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
182 exit(EXIT_FAILURE);
183 }
184 if (!bindtextdomain (PACKAGE_NAME, LOCALEDIR)) {
185 fprintf(stderr,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME,LOCALEDIR,strerror(errno));
186 exit(EXIT_FAILURE);
187 }
188 if (!textdomain (PACKAGE_NAME)) {
189 fprintf(stderr,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME,strerror(errno));
190 exit(EXIT_FAILURE);
191 }
192 #endif //ENABLE_NLS
193
194 BgImage[0]='\0';
195 LogoImage[0]='\0';
196 LogoText[0]='\0';
197 PasswdFile[0]='\0';
198 OutputEmail[0]='\0';
199 UserAgentLog[0]='\0';
200 ExcludeHosts[0]='\0';
201 ExcludeUsers[0]='\0';
202 ConfigFile[0]='\0';
203 code[0]='\0';
204 LastLog=0;
205 ReportType=0UL;
206 UserTabFile[0]='\0';
207 BlockIt[0]='\0';
208 ExternalCSSFile[0]='\0';
209 RedirectorLogFormat[0]='\0';
210 NRedirectorLogs=0;
211 for (ilf=0 ; ilf<ILF_Last ; ilf++) ilf_count[ilf]=0;
212
213 sprintf(ExcludeCodes,"%s/exclude_codes",SYSCONFDIR);
214 strcpy(GraphDaysBytesBarColor,"orange");
215 strcpy(BgColor,"#ffffff");
216 strcpy(TxColor,"#000000");
217 strcpy(TxBgColor,"lavender");
218 strcpy(TiColor,"darkblue");
219 strcpy(Width,"80");
220 strcpy(Height,"45");
221 strcpy(LogoTextColor,"#000000");
222 strcpy(HeaderColor,"darkblue");
223 strcpy(HeaderBgColor,"#dddddd");
224 strcpy(LogoTextColor,"#006699");
225 strcpy(FontSize,"9px");
226 strcpy(TempDir,"/tmp");
227 strcpy(OutputDir,"/var/www/html/squid-reports");
228 AnonymousOutputFiles=false;
229 Ip2Name=false;
230 strcpy(DateFormat,"u");
231 OverwriteReport=false;
232 RemoveTempFiles=true;
233 strcpy(ReplaceIndex,"index.html");
234 Index=INDEX_YES;
235 RecordsWithoutUser=RECORDWITHOUTUSER_IP;
236 UseComma=0;
237 strcpy(MailUtility,"mailx");
238 TopSitesNum=100;
239 TopUsersNum=0;
240 UserIp=0;
241 TopuserSort=TOPUSER_SORT_BYTES | TOPUSER_SORT_REVERSE;
242 UserSort=USER_SORT_BYTES | USER_SORT_REVERSE;
243 TopsitesSort=TOPSITE_SORT_CONNECT | TOPSITE_SORT_REVERSE;
244 LongUrl=0;
245 strcpy(FontFace,"Verdana,Tahoma,Arial");
246 datetimeby=DATETIME_BYTE;
247 strcpy(CharSet,"ISO-8859-1");
248 Privacy=0;
249 strcpy(PrivacyString,"***.***.***.***");
250 strcpy(PrivacyStringColor,"blue");
251 SuccessfulMsg=true;
252 TopUserFields=TOPUSERFIELDS_NUM | TOPUSERFIELDS_DATE_TIME | TOPUSERFIELDS_USERID | TOPUSERFIELDS_CONNECT |
253 TOPUSERFIELDS_BYTES | TOPUSERFIELDS_SETYB | TOPUSERFIELDS_IN_CACHE_OUT |
254 TOPUSERFIELDS_USED_TIME | TOPUSERFIELDS_MILISEC | TOPUSERFIELDS_PTIME |
255 TOPUSERFIELDS_TOTAL | TOPUSERFIELDS_AVERAGE;
256 UserReportFields=USERREPORTFIELDS_CONNECT | USERREPORTFIELDS_BYTES | USERREPORTFIELDS_SETYB |
257 USERREPORTFIELDS_IN_CACHE_OUT | USERREPORTFIELDS_USED_TIME | USERREPORTFIELDS_MILISEC |
258 USERREPORTFIELDS_PTIME | USERREPORTFIELDS_TOTAL | USERREPORTFIELDS_AVERAGE;
259 strcpy(DataFileDelimiter,";");
260 DataFileFields=DATA_FIELD_USER | DATA_FIELD_DATE | DATA_FIELD_TIME | DATA_FIELD_URL | DATA_FIELD_CONNECT |
261 DATA_FIELD_BYTES | DATA_FIELD_IN_CACHE | DATA_FIELD_OUT_CACHE | DATA_FIELD_ELAPSED;
262 ShowReadStatistics=true;
263 strcpy(IndexSortOrder,"D");
264 ShowSargInfo=true;
265 ShowSargLogo=true;
266 ParsedOutputLog[0]='\0';
267 strcpy(ParsedOutputLogCompress,"/bin/gzip -f");
268 DisplayedValues=DISPLAY_ABBREV;
269 strcpy(HeaderFontSize,"9px");
270 strcpy(TitleFontSize,"11px");
271 strcpy(AuthUserTemplateFile,"sarg_htaccess");
272 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");
273 Graphs=true;
274 #if defined(FONTDIR)
275 strcpy(GraphFont,FONTDIR"/DejaVuSans.ttf");
276 #else
277 GraphFont[0]='\0';
278 #endif
279 strcpy(Ulimit,"20000");
280 NtlmUserFormat=NTLMUSERFORMAT_DOMAINUSER;
281 IndexTree=INDEX_TREE_FILE;
282 IndexFields=INDEXFIELDS_DIRSIZE;
283 strcpy(RealtimeTypes,"GET,PUT,CONNECT");
284 RealtimeUnauthRec=REALTIME_UNAUTH_REC_SHOW;
285 RedirectorFilterOutDate=true;
286 DansguardianFilterOutDate=true;
287 DataFileUrl=DATAFILEURL_IP;
288 strcpy(MaxElapsed,"28800000");
289 BytesInSitesUsersReport=0;
290 UserAuthentication=0;
291 strcpy(LDAPHost,"127.0.0.1");
292 LDAPPort=389;
293 LDAPProtocolVersion=3;
294 LDAPBindDN[0]='\0';
295 LDAPBindPW[0]='\0';
296 LDAPBaseSearch[0]='\0';
297 strcpy(LDAPFilterSearch, "(uid=%s)");
298 strcpy(LDAPTargetAttr, "cn");
299 SortTableJs[0]='\0';
300
301 dia[0]='\0';
302 mes[0]='\0';
303 ano[0]='\0';
304 hora[0]='\0';
305 tmp[0]='\0';
306 tmp3[0]='\0';
307 wtemp[0]='\0';
308 us[0]='\0';
309 date[0]='\0';
310 df[0]='\0';
311 uagent[0]='\0';
312 hexclude[0]='\0';
313 addr[0]='\0';
314 hm=-1;
315 hmf=-1;
316 site[0]='\0';
317 outdir[0]='\0';
318 splitprefix[0]='\0';
319 elap[0]='\0';
320 email[0]='\0';
321 zip[0]='\0';
322 UserInvalidChar[0]='\0';
323 DataFile[0]='\0';
324 SquidGuardConf[0]='\0';
325 DansGuardianConf[0]='\0';
326 start_hour[0]='\0';
327 end_hour[0]='\0';
328 hm_str[0]='\0';
329 HostAliasFile[0]='\0';
330
331 denied_count=0;
332 download_count=0;
333 authfail_count=0;
334 dansguardian_count=0;
335 redirector_count=0;
336 useragent_count=0;
337 DeniedReportLimit=10;
338 AuthfailReportLimit=10;
339 DansGuardianReportLimit=10;
340 SquidGuardReportLimit=10;
341 DownloadReportLimit=50;
342 UserReportLimit=0;
343 debug=0;
344 debugz=0;
345 debugm=0;
346 iprel=false;
347 userip=false;
348 realt=false;
349 realtime_refresh=3;
350 realtime_access_log_lines=1000;
351 cost=0.01;
352 nocost=50000000;
353 ndownload=0;
354 squid24=false;
355 dfrom=0;
356 duntil=0;
357
358 bzero(IncludeUsers, sizeof(IncludeUsers));
359 bzero(ExcludeString, sizeof(ExcludeString));
360 first_user_file=NULL;
361 memset(&period,0,sizeof(period));
362
363 NAccessLog=0;
364 for(x=0; x<MAXLOGS; x++)
365 AccessLog[x][0]='\0';
366 AccessLogFromCmdLine=0;
367 RedirectorLogFromCmdLine=0;
368
369 strcpy(Title,_("Squid User Access Report"));
370
371 while((ch = getopt_long_only(argc, argv, "a:b:c:d:e:f:g:u:l:L:o:s:t:w:P:hijmnprvxyz",long_options,&option_index)) != -1){
372 switch(ch)
373 {
374 case 0:
375 break;
376 case 2:
377 lastlog=atoi(optarg);
378 break;
379 case 3:
380 lastlog=0;
381 break;
382 case 'a':
383 strcpy(addr,optarg);
384 break;
385 case 'b':
386 strcpy(uagent,optarg);
387 break;
388 case 'c':
389 strcpy(hexclude,optarg);
390 break;
391 case 'd':
392 strncpy(date,optarg,sizeof(date)-1);
393 date[sizeof(date)-1]='\0';
394 date_from(date, &dfrom, &duntil);
395 break;
396 case 'e':
397 strcpy(email,optarg);
398 break;
399 case 'f':
400 strcpy(ConfigFile,optarg);
401 break;
402 case 'g':
403 strcpy(df,optarg);
404 break;
405 case 'h':
406 usage(argv[0]);
407 exit(EXIT_SUCCESS);
408 case 'i':
409 iprel=true;
410 break;
411 case 'l':
412 if (NAccessLog>=MAXLOGS) {
413 debuga(_("Too many log files passed on command line with option -l.\n"));
414 exit(EXIT_FAILURE);
415 }
416 if (strlen(optarg)>=MAX_LOG_FILELEN) {
417 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg);
418 exit(EXIT_FAILURE);
419 }
420 strcpy(AccessLog[NAccessLog],optarg);
421 NAccessLog++;
422 AccessLogFromCmdLine++;
423 break;
424 case 'L':
425 if (NRedirectorLogs>MAX_REDIRECTOR_LOGS) {
426 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
427 exit(EXIT_FAILURE);
428 }
429 if (strlen(optarg)>=MAX_REDIRECTOR_FILELEN) {
430 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg);
431 exit(EXIT_FAILURE);
432 }
433 strcpy(RedirectorLogs[NRedirectorLogs],optarg);
434 NRedirectorLogs++;
435 RedirectorLogFromCmdLine++;
436 break;
437 case 'm':
438 debugm++;
439 break;
440 case 'n':
441 dns=true;
442 break;
443 case 'o':
444 strcpy(outdir,optarg);
445 break;
446 case 'p':
447 userip=true;
448 break;
449 case 'P':
450 strcpy(splitprefix,optarg);
451 break;
452 case 'r':
453 realt=true;
454 break;
455 case 's':
456 strcpy(site,optarg);
457 break;
458 case 't':
459 {
460 int h1,m1,h2,m2;
461
462 if(strstr(optarg,"-") == 0) {
463 if(sscanf(optarg,"%d:%d",&h1,&m1)!=2) {
464 debuga(_("Time period passed on the command line with option -t must be MM:SS\n"));
465 exit(EXIT_FAILURE);
466 }
467 hm=h1*100+m1;
468 hmf=hm;
469 snprintf(hm_str,sizeof(hm_str),"%02d:%02d",h1,m1);
470 } else {
471 if(sscanf(optarg,"%d:%d-%d:%d",&h1,&m1,&h2,&m2)!=4) {
472 debuga(_("Time range passed on the command line with option -t must be MM:SS-MM:SS\n"));
473 exit(EXIT_FAILURE);
474 }
475 hm=h1*100+m1;
476 hmf=h2*100+m2;
477 snprintf(hm_str,sizeof(hm_str),"%02d:%02d-%02d:%02d",h1,m1,h2,m2);
478 }
479 break;
480 }
481 case 'u':
482 strcpy(us,optarg);
483 break;
484 case 'v':
485 version();
486 break;
487 case 'w':
488 strcpy(tmp,optarg);
489 break;
490 case 'x':
491 debug++;
492 break;
493 case 'y':
494 langcode++;
495 break;
496 case 'z':
497 debugz++;
498 break;
499 case ':':
500 debuga(_("Option -%c requires an argument\n"),optopt);
501 exit(EXIT_FAILURE);
502 case '?':
503 usage(argv[0]);
504 exit(EXIT_FAILURE);
505 default:
506 abort();
507 }
508 }
509
510 if (errflg>0) {
511 usage(argv[0]);
512 exit(2);
513 }
514
515 if (optind<argc) {
516 for (iarq=optind ; iarq<argc ; iarq++) {
517 if (NAccessLog>=MAXLOGS) {
518 debuga(_("Too many log files passed on command line.\n"));
519 exit(EXIT_FAILURE);
520 }
521 if (strlen(argv[iarq])>=MAX_LOG_FILELEN) {
522 debuga(_("Log file name too long passed on command line: %s\n"),argv[iarq]);
523 exit(EXIT_FAILURE);
524 }
525 strcpy(AccessLog[NAccessLog],argv[iarq]);
526 NAccessLog++;
527 AccessLogFromCmdLine++;
528 }
529 }
530
531 if(debug) debuga(_("Init\n"));
532
533 if(ConfigFile[0] == '\0') snprintf(ConfigFile,sizeof(ConfigFile),"%s/sarg.conf",SYSCONFDIR);
534 if(access(ConfigFile, R_OK) != 0) {
535 debuga(_("Cannot open config file: %s - %s\n"),ConfigFile,strerror(errno));
536 exit(EXIT_FAILURE);
537 }
538
539 if(access(ConfigFile, R_OK) == 0)
540 getconf();
541
542 if(userip) UserIp=true;
543
544 if(dns) Ip2Name=true;
545
546 if (lastlog>=0) LastLog=lastlog;
547
548 if(outdir[0] == '\0') strcpy(outdir,OutputDir);
549 if(outdir[0] != '\0') strcat(outdir,"/");
550
551 if(realt) {
552 realtime();
553 exit(EXIT_SUCCESS);
554 }
555
556 if(IndexTree == INDEX_TREE_FILE)
557 strcpy(ImageFile,"../images");
558 else
559 strcpy(ImageFile,"../../../images");
560
561 dataonly=0;
562 if(DataFile[0] != '\0')
563 dataonly++;
564
565 if(df[0] == '\0') strcpy(df,DateFormat);
566 else strcpy(DateFormat,df);
567
568 if(df[0] == '\0') {
569 strcpy(df,"u");
570 strcpy(DateFormat,"u");
571 }
572 if (df[0]=='w')
573 IndexTree=INDEX_TREE_FILE;
574
575 if(NAccessLog == 0) {
576 strcpy(AccessLog[0],"/var/log/squid/access.log");
577 NAccessLog++;
578 }
579
580 if(output_css) {
581 css_content(stdout);
582 exit(EXIT_SUCCESS);
583 }
584 if(split) {
585 for (iarq=0 ; iarq<NAccessLog ; iarq++)
586 splitlog(AccessLog[iarq], df, dfrom, duntil, convert, splitprefix);
587 exit(EXIT_SUCCESS);
588 }
589 if(convert) {
590 for (iarq=0 ; iarq<NAccessLog ; iarq++)
591 convlog(AccessLog[iarq], df, dfrom, duntil);
592 exit(EXIT_SUCCESS);
593 }
594
595 load_excludecodes(ExcludeCodes);
596
597 if(access(PasswdFile, R_OK) == 0) {
598 getusers(PasswdFile,debug);
599 puser++;
600 }
601
602 if(hexclude[0] == '\0')
603 strcpy(hexclude,ExcludeHosts);
604 if(hexclude[0] != '\0') {
605 gethexclude(hexclude,debug);
606 fhost=true;
607 }
608
609 if(ReportType == 0) {
610 ReportType=REPORT_TYPE_TOPUSERS | REPORT_TYPE_TOPSITES | REPORT_TYPE_USERS_SITES |
611 REPORT_TYPE_SITES_USERS | REPORT_TYPE_DATE_TIME | REPORT_TYPE_DENIED |
612 REPORT_TYPE_AUTH_FAILURES | REPORT_TYPE_SITE_USER_TIME_DATE | REPORT_TYPE_DOWNLOADS;
613 }
614
615 if(access(ExcludeUsers, R_OK) == 0) {
616 getuexclude(ExcludeUsers,debug);
617 fuser=true;
618 }
619 if (HostAliasFile[0] != '\0')
620 read_hostalias(HostAliasFile);
621
622 indexonly=false;
623 if(fuser) {
624 if(is_indexonly())
625 indexonly=true;
626 }
627 if(strcmp(ExcludeUsers,"indexonly") == 0) indexonly=true;
628 if(Index == INDEX_ONLY) indexonly=true;
629
630 if(MaxElapsed[0] != '\0') max_elapsed=atol(MaxElapsed);
631
632 if(uagent[0] == '\0') strcpy(uagent,UserAgentLog);
633
634 if(tmp[0] == '\0') strcpy(tmp,TempDir);
635 else strcpy(TempDir,tmp);
636 /*
637 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
638 provided by the user.
639 */
640 strcat(tmp,"/sarg");
641
642 if (tmp[0]!='\0' && strncmp(outdir,tmp,strlen(tmp))==0) {
643 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir,tmp);
644 exit(EXIT_FAILURE);
645 }
646
647 if(email[0] == '\0' && OutputEmail[0] != '\0') strcpy(email,OutputEmail);
648
649 if(email[0] != '\0') {
650 my_mkdir(tmp);
651 strcpy(outdir,tmp);
652 strcat(outdir,"/");
653 }
654
655 if(access(tmp, R_OK) == 0) {
656 unlinkdir(tmp,1);
657 }
658 my_mkdir(tmp);
659 snprintf(denied_unsort,sizeof(denied_unsort),"%s/denied.log.unsort",tmp);
660 snprintf(denied_sort,sizeof(denied_sort),"%s/denied.log",tmp);
661 snprintf(authfail_unsort,sizeof(authfail_unsort),"%s/authfail.log.unsort",tmp);
662
663 if(debug) {
664 debuga(_("Parameters:\n"));
665 debuga(_(" Hostname or IP address (-a) = %s\n"),addr);
666 debuga(_(" Useragent log (-b) = %s\n"),uagent);
667 debuga(_(" Exclude file (-c) = %s\n"),hexclude);
668 debuga(_(" Date from-until (-d) = %s\n"),date);
669 debuga(_(" Email address to send reports (-e) = %s\n"),email);
670 debuga(_(" Config file (-f) = %s\n"),ConfigFile);
671 if(strcmp(df,"e") == 0)
672 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
673 if(strcmp(df,"u") == 0)
674 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
675 if(strcmp(df,"w") == 0)
676 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
677 debuga(_(" IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
678 for (iarq=0 ; iarq<NAccessLog ; iarq++)
679 debuga(_(" Input log (-l) = %s\n"),AccessLog[iarq]);
680 for (iarq=0 ; iarq<NRedirectorLogs ; iarq++)
681 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs[iarq]);
682 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
683 debuga(_(" Output dir (-o) = %s\n"),outdir);
684 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
685 debuga(_(" Accessed site (-s) = %s\n"),site);
686 debuga(_(" Time (-t) = %s\n"),hm_str);
687 debuga(_(" User (-u) = %s\n"),us);
688 debuga(_(" Temporary dir (-w) = %s\n"),tmp);
689 debuga(_(" Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
690 debuga(_(" Process messages (-z) = %s\n"),(debugz) ? _("Yes") : _("No"));
691 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog);
692 debuga("\n");
693 }
694
695 if(debugm) {
696 printf(_("Parameters:\n"));
697 printf(_(" Hostname or IP address (-a) = %s\n"),addr);
698 printf(_(" Useragent log (-b) = %s\n"),uagent);
699 printf(_(" Exclude file (-c) = %s\n"),hexclude);
700 printf(_(" Date from-until (-d) = %s\n"),date);
701 printf(_(" Email address to send reports (-e) = %s\n"),email);
702 printf(_(" Config file (-f) = %s\n"),ConfigFile);
703 if(strcmp(df,"e") == 0)
704 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
705 if(strcmp(df,"u") == 0)
706 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
707 if(strcmp(df,"w") == 0)
708 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
709 printf(_(" IP report (-i) = %s\n"),(iprel) ? _("Yes") : _("No"));
710 for (iarq=0 ; iarq<NAccessLog ; iarq++)
711 printf(_(" Input log (-l) = %s\n"),AccessLog[iarq]);
712 for (iarq=0 ; iarq<NRedirectorLogs ; iarq++)
713 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs[iarq]);
714 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name) ? _("Yes") : _("No"));
715 printf(_(" Output dir (-o) = %s\n"),outdir);
716 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp) ? _("Yes") : _("No"));
717 printf(_(" Accessed site (-s) = %s\n"),site);
718 printf(_(" Time (-t) = %s\n"),hm_str);
719 printf(_(" User (-u) = %s\n"),us);
720 printf(_(" Temporary dir (-w) = %s\n"),tmp);
721 printf(_(" Debug messages (-x) = %s\n"),(debug) ? _("Yes") : _("No"));
722 printf(_(" Process messages (-z) = %s\n"),(debugz) ? _("Yes") : _("No"));
723 printf(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog);
724 printf(_("sarg version: %s\n"),VERSION);
725 }
726
727 if(debug)
728 debuga(_("sarg version: %s\n"),VERSION);
729
730 #ifdef ENABLE_DOUBLE_CHECK_DATA
731 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
732 #endif
733
734 maxopenfiles=MAX_OPEN_USER_FILES;
735 #ifdef HAVE_RLIM_T
736 if (Ulimit[0] != '\0') {
737 struct rlimit rl;
738 long l1, l2;
739 int rc=0;
740
741 #if defined(RLIMIT_NOFILE)
742 getrlimit (RLIMIT_NOFILE, &rl);
743 #elif defined(RLIMIT_OFILE)
744 getrlimit (RLIMIT_OFILE, &rl);
745 #else
746 #warning "No rlimit resource for the number of open files"
747 #endif
748 l1 = rl.rlim_cur;
749 l2 = rl.rlim_max;
750
751 rl.rlim_cur = atol(Ulimit);
752 rl.rlim_max = atol(Ulimit);
753 #if defined(RLIMIT_NOFILE)
754 rc=setrlimit (RLIMIT_NOFILE, &rl);
755 #elif defined(RLIMIT_OFILE)
756 rc=setrlimit (RLIMIT_OFILE, &rl);
757 #else
758 #warning "No rlimit resource for the number of open files"
759 #endif
760 if(rc == -1) {
761 debuga(_("setrlimit error - %s\n"),strerror(errno));
762 }
763
764 if(debug)
765 debuga("Maximum file descriptor: cur=%ld max=%ld, changed to cur="RLIM_STRING" max="RLIM_STRING,l1,l2,rl.rlim_cur,rl.rlim_max);
766 }
767 #endif
768
769 init_usertab(UserTabFile);
770
771 if ((line=longline_create())==NULL) {
772 debuga(_("Not enough memory to read a log file\n"));
773 exit(EXIT_FAILURE);
774 }
775
776 snprintf(sz_Download_Unsort,sizeof(sz_Download_Unsort),"%s/download.unsort", tmp);
777
778 if(DataFile[0]=='\0') {
779 if((ReportType & REPORT_TYPE_DENIED) != 0) {
780 if((fp_denied=MY_FOPEN(denied_unsort,"w"))==NULL) {
781 debuga(_("(log) Cannot open file: %s - %s\n"),denied_unsort,strerror(errno));
782 exit(EXIT_FAILURE);
783 }
784 }
785
786 if((ReportType & REPORT_TYPE_DENIED) != 0 || (ReportType & REPORT_TYPE_AUTH_FAILURES) != 0) {
787 if((fp_authfail=MY_FOPEN(authfail_unsort,"w"))==NULL) {
788 debuga(_("(log) Cannot open file: %s - %s\n"),authfail_unsort,strerror(errno));
789 exit(EXIT_FAILURE);
790 }
791 }
792 }
793
794 for (iarq=0 ; iarq<NAccessLog ; iarq++) {
795 strcpy(arq,AccessLog[iarq]);
796
797 strcpy(arqtt,arq);
798
799 if(strcmp(arq,"-")==0) {
800 if(debug)
801 debuga(_("Reading access log file: from stdin\n"));
802 fp_in=stdin;
803 from_stdin=true;
804 } else {
805 if (date[0]!='\0') {
806 if (stat(arq,&logstat)!=0) {
807 debuga(_("Cannot get the modification time of input log file %s (%s). Processing it anyway\n"),arq,strerror(errno));
808 } else {
809 struct tm *logtime=localtime(&logstat.st_mtime);
810 if ((logtime->tm_year+1900)*10000+(logtime->tm_mon+1)*100+logtime->tm_mday<dfrom) {
811 debuga(_("Ignoring old log file %s\n"),arq);
812 continue;
813 }
814 }
815 }
816 fp_in=decomp(arq,&from_pipe);
817 if(fp_in==NULL) {
818 debuga(_("(log) Cannot open log file: %s - %s\n"),arq,strerror(errno));
819 exit(EXIT_FAILURE);
820 }
821 if(debug) debuga(_("Reading access log file: %s\n"),arq);
822 from_stdin=false;
823 }
824 ilf=ILF_Unknown;
825 download_flag=false;
826 // pre-read the file only if we have to show stats
827 if(ShowReadStatistics && !from_stdin && !from_pipe) {
828 size_t nread,i;
829 bool skipcr=false;
830 char tmp4[MAXLEN];
831
832 recs1=0UL;
833 recs2=0UL;
834
835 while ((nread=fread(tmp4,1,sizeof(tmp4),fp_in))>0) {
836 for (i=0 ; i<nread ; i++)
837 if (skipcr) {
838 if (tmp4[i]!='\n' && tmp4[i]!='\r') {
839 skipcr=false;
840 }
841 } else {
842 if (tmp4[i]=='\n' || tmp4[i]=='\r') {
843 skipcr=true;
844 recs1++;
845 }
846 }
847 }
848 rewind(fp_in);
849 printf(_("SARG: Records in file: %lu, reading: %3.2f%%"),recs1,(float) 0);
850 putchar('\r');
851 fflush( stdout ) ;
852 }
853
854 longline_reset(line);
855
856 while ((linebuf=longline_read(fp_in,line))!=NULL) {
857 blen=strlen(linebuf);
858
859 if (ilf==ILF_Unknown) {
860 if(strncmp(linebuf,"#Software: Mic",14) == 0) {
861 fixendofline(linebuf);
862 if (debug)
863 debuga(_("Log is from Microsoft ISA: %s\n"),linebuf);
864 ilf=ILF_Isa;
865 ilf_count[ilf]++;
866 continue;
867 }
868
869 if(strncmp(linebuf,"*** SARG Log ***",16) == 0) {
870 if (getperiod_fromsarglog(arqtt,&period)<0) {
871 debuga(_("The name of the file is invalid: %s\n"),arq);
872 exit(EXIT_FAILURE);
873 }
874 ilf=ILF_Sarg;
875 ilf_count[ilf]++;
876 continue;
877 }
878 }
879
880 if(!fp_log && ParsedOutputLog[0] && ilf!=ILF_Sarg) {
881 if(access(ParsedOutputLog,R_OK) != 0) {
882 my_mkdir(ParsedOutputLog);
883 }
884 sprintf(arq_log,"%s/sarg_temp.log",ParsedOutputLog);
885 if((fp_log=MY_FOPEN(arq_log,"w"))==NULL) {
886 debuga(_("(log) Cannot open log file: %s - %s\n"),arq_log,strerror(errno));
887 exit(EXIT_FAILURE);
888 }
889 fputs("*** SARG Log ***\n",fp_log);
890 }
891
892 recs2++;
893 if( ShowReadStatistics && !from_stdin && !from_pipe && --OutputNonZero<=0) {
894 double perc = recs2 * 100. / recs1 ;
895 printf(_("SARG: Records in file: %lu, reading: %3.2lf%%"),recs2,perc);
896 putchar('\r');
897 fflush (stdout);
898 OutputNonZero = REPORT_EVERY_X_LINES ;
899 }
900 if(blen < 58) continue;
901 if(strstr(linebuf,"HTTP/0.0") != 0) continue;
902 if(strstr(linebuf,"logfile turned over") != 0) continue;
903 if(linebuf[0] == ' ') continue;
904
905 // exclude_string
906 if(ExcludeString[0] != '\0') {
907 bool exstring=false;
908 getword_start(&gwarea,ExcludeString);
909 while(strchr(gwarea.current,':') != 0) {
910 if (getword_multisep(val1,sizeof(val1),&gwarea,':')<0) {
911 debuga(_("Maybe you have a broken record or garbage in your exclusion string\n"));
912 exit(EXIT_FAILURE);
913 }
914 if((str=(char *) strstr(linebuf,val1)) != (char *) NULL ) {
915 exstring=true;
916 break;
917 }
918 }
919 if(!exstring && (str=(char *) strstr(linebuf,gwarea.current)) != (char *) NULL )
920 exstring=true;
921 if(exstring) continue;
922 }
923
924 totregsl++;
925 if(debugm)
926 printf("BUF=%s\n",linebuf);
927
928 t=NULL;
929 if (ilf==ILF_Squid || ilf==ILF_Common || ilf==ILF_Unknown) {
930 getword_start(&gwarea,linebuf);
931 if (getword(data,sizeof(data),&gwarea,' ')<0) {
932 debuga(_("Maybe you have a broken time in your access.log file\n"));
933 exit(EXIT_FAILURE);
934 }
935 if((str=(char *) strchr(data, '.')) != (char *) NULL && (str=(char *) strchr(str+1, '.')) != (char *) NULL ) {
936 strcpy(ip,data);
937 strcpy(elap,"0");
938 if(squid24) {
939 if (getword(user,sizeof(user),&gwarea,' ')<0 || getword_skip(255,&gwarea,' ')<0) {
940 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
941 exit(EXIT_FAILURE);
942 }
943 } else {
944 if (getword_skip(255,&gwarea,' ')<0 || getword(user,sizeof(user),&gwarea,' ')<0) {
945 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
946 exit(EXIT_FAILURE);
947 }
948 }
949 if (getword(data,sizeof(data),&gwarea,']')<0 || getword_skip(MAXLEN,&gwarea,'"')<0 ||
950 getword(fun,sizeof(fun),&gwarea,' ')<0) {
951 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
952 exit(EXIT_FAILURE);
953 }
954 if (getword_ptr(linebuf,&full_url,&gwarea,' ')<0) {
955 debuga(_("Maybe you have a broken url in your %s file\n"),arq);
956 exit(EXIT_FAILURE);
957 }
958 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
959 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
960 exit(EXIT_FAILURE);
961 }
962 if (getword(code2,sizeof(code2),&gwarea,' ')<0) {
963 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
964 exit(EXIT_FAILURE);
965 }
966 if (getword(tam,sizeof(tam),&gwarea,' ')<0) {
967 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
968 exit(EXIT_FAILURE);
969 }
970 if((str=(char *) strchr(gwarea.current, ' ')) != (char *) NULL ) {
971 if (getword(code,sizeof(code),&gwarea,' ')<0) {
972 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
973 exit(EXIT_FAILURE);
974 }
975 } else {
976 if (getword(code,sizeof(code),&gwarea,'\0')<0) {
977 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
978 exit(EXIT_FAILURE);
979 }
980 }
981
982 if ((str = strchr(code, ':')) != NULL)
983 *str = '/';
984
985 if(strcmp(tam,"\0") == 0)
986 strcpy(tam,"0");
987
988 ilf=ILF_Common;
989 ilf_count[ilf]++;
990
991 getword_start(&gwarea,data+1);
992 if (getword_multisep(data,sizeof(data),&gwarea,':')<0){
993 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
994 exit(EXIT_FAILURE);
995 }
996 if (getword_multisep(hora,sizeof(hora),&gwarea,' ')<0){
997 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
998 exit(EXIT_FAILURE);
999 }
1000 getword_start(&gwarea,data);
1001 if (getword_atoll(&iday,&gwarea,'/')<0){
1002 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1003 exit(EXIT_FAILURE);
1004 }
1005 if (getword(mes,sizeof(mes),&gwarea,'/')<0){
1006 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1007 exit(EXIT_FAILURE);
1008 }
1009 if (getword_atoll(&iyear,&gwarea,'/')<0){
1010 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1011 exit(EXIT_FAILURE);
1012 }
1013
1014 imonth=month2num(mes)+1;
1015 idata=builddia(iday,imonth,iyear);
1016 computedate(iyear,imonth,iday,&tt);
1017 if (sscanf(hora,"%d:%d:%d",&tt.tm_hour,&tt.tm_min,&tt.tm_sec)!=3 || tt.tm_hour<0 || tt.tm_hour>=24 ||
1018 tt.tm_min<0 || tt.tm_min>=60 || tt.tm_sec<0 || tt.tm_sec>=60) {
1019 debuga(_("Invalid time found in %s\n"),arq);
1020 exit(EXIT_FAILURE);
1021 }
1022 t=&tt;
1023 }
1024
1025 if(ilf==ILF_Unknown || ilf==ILF_Squid) {
1026 if (getword(elap,sizeof(elap),&gwarea,' ')<0) {
1027 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq);
1028 exit(EXIT_FAILURE);
1029 }
1030 while(strcmp(elap,"") == 0 && gwarea.current[0] != '\0')
1031 if (getword(elap,sizeof(elap),&gwarea,' ')<0) {
1032 debuga(_("Maybe you have a broken elapsed time in your %s file\n"),arq);
1033 exit(EXIT_FAILURE);
1034 }
1035 if(strlen(elap) < 1) continue;
1036 if (getword(ip,sizeof(ip),&gwarea,' ')<0){
1037 debuga(_("Maybe you have a broken client IP address in your %s file\n"),arq);
1038 exit(EXIT_FAILURE);
1039 }
1040 if (getword(code,sizeof(code),&gwarea,' ')<0){
1041 debuga(_("Maybe you have a broken result code in your %s file\n"),arq);
1042 exit(EXIT_FAILURE);
1043 }
1044 if (getword(tam,sizeof(tam),&gwarea,' ')<0){
1045 debuga(_("Maybe you have a broken amount of data in your %s file\n"),arq);
1046 exit(EXIT_FAILURE);
1047 }
1048 if (getword(fun,sizeof(fun),&gwarea,' ')<0){
1049 debuga(_("Maybe you have a broken request method in your %s file\n"),arq);
1050 exit(EXIT_FAILURE);
1051 }
1052 if (getword_ptr(linebuf,&full_url,&gwarea,' ')<0){
1053 debuga(_("Maybe you have a broken url in your %s file\n"),arq);
1054 exit(EXIT_FAILURE);
1055 }
1056 if (getword(user,sizeof(user),&gwarea,' ')<0){
1057 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq);
1058 exit(EXIT_FAILURE);
1059 }
1060 ilf=ILF_Squid;
1061 ilf_count[ilf]++;
1062
1063 tnum=atoi(data);
1064 t=localtime(&tnum);
1065 if (t == NULL) {
1066 debuga(_("Cannot convert the timestamp from the squid log file\n"));
1067 exit(EXIT_FAILURE);
1068 }
1069
1070 strftime(tbuf2, sizeof(tbuf2), "%H%M", t);
1071
1072 idata=(t->tm_year+1900)*10000+(t->tm_mon+1)*100+t->tm_mday;
1073 }
1074 }
1075 if (ilf==ILF_Sarg) {
1076 getword_start(&gwarea,linebuf);
1077 if (getword(data,sizeof(data),&gwarea,'\t')<0){
1078 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1079 exit(EXIT_FAILURE);
1080 }
1081 if (getword(hora,sizeof(hora),&gwarea,'\t')<0) {
1082 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1083 exit(EXIT_FAILURE);
1084 }
1085 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
1086 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1087 exit(EXIT_FAILURE);
1088 }
1089 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
1090 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1091 exit(EXIT_FAILURE);
1092 }
1093 if (getword_ptr(linebuf,&full_url,&gwarea,'\t')<0){
1094 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1095 exit(EXIT_FAILURE);
1096 }
1097 if (getword(tam,sizeof(tam),&gwarea,'\t')<0){
1098 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1099 exit(EXIT_FAILURE);
1100 }
1101 if (getword(code,sizeof(code),&gwarea,'\t')<0){
1102 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1103 exit(EXIT_FAILURE);
1104 }
1105 if (getword(elap,sizeof(elap),&gwarea,'\t')<0){
1106 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1107 exit(EXIT_FAILURE);
1108 }
1109 if (getword(smartfilter,sizeof(smartfilter),&gwarea,'\0')<0){
1110 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1111 exit(EXIT_FAILURE);
1112 }
1113 getword_start(&gwarea,data);
1114 if (getword_atoll(&iday,&gwarea,'/')<0 || iday<1 || iday>31){
1115 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1116 exit(EXIT_FAILURE);
1117 }
1118 if (getword_atoll(&imonth,&gwarea,'/')<0 || imonth<1 || imonth>12){
1119 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1120 exit(EXIT_FAILURE);
1121 }
1122 if (getword_atoll(&iyear,&gwarea,'\0')<0){
1123 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1124 exit(EXIT_FAILURE);
1125 }
1126 idata=builddia(iday,imonth,iyear);
1127 computedate(iyear,imonth,iday,&tt);
1128 if (sscanf(hora,"%d:%d:%d",&tt.tm_hour,&tt.tm_min,&tt.tm_sec)!=3 || tt.tm_hour<0 || tt.tm_hour>=24 ||
1129 tt.tm_min<0 || tt.tm_min>=60 || tt.tm_sec<0 || tt.tm_sec>=60) {
1130 debuga(_("Invalid time found in %s\n"),arq);
1131 exit(EXIT_FAILURE);
1132 }
1133 t=&tt;
1134 }
1135 if (ilf==ILF_Isa) {
1136 if (linebuf[0] == '#') {
1137 int ncols,cols[ISACOL_Last];
1138
1139 fixendofline(linebuf);
1140 getword_start(&gwarea,linebuf);
1141 // remove the #Fields: column at the beginning of the line
1142 if (getword_skip(1000,&gwarea,' ')<0){
1143 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1144 exit(EXIT_FAILURE);
1145 }
1146 for (ncols=0 ; ncols<ISACOL_Last ; ncols++) cols[ncols]=-1;
1147 ncols=0;
1148 while(gwarea.current[0] != '\0') {
1149 if (getword(val1,sizeof(val1),&gwarea,'\t')<0){
1150 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1151 exit(EXIT_FAILURE);
1152 }
1153 if(strcmp(val1,"c-ip") == 0) cols[ISACOL_Ip]=ncols;
1154 if(strcmp(val1,"cs-username") == 0) cols[ISACOL_UserName]=ncols;
1155 if(strcmp(val1,"date") == 0) cols[ISACOL_Date]=ncols;
1156 if(strcmp(val1,"time") == 0) cols[ISACOL_Time]=ncols;
1157 if(strcmp(val1,"time-taken") == 0) cols[ISACOL_TimeTaken]=ncols;
1158 if(strcmp(val1,"sc-bytes") == 0) cols[ISACOL_Bytes]=ncols;
1159 if(strcmp(val1,"cs-uri") == 0) cols[ISACOL_Uri]=ncols;
1160 if(strcmp(val1,"sc-status") == 0) cols[ISACOL_Status]=ncols;
1161 ncols++;
1162 }
1163 if (cols[ISACOL_Ip]>=0) {
1164 isa_ncols=ncols;
1165 for (ncols=0 ; ncols<ISACOL_Last ; ncols++)
1166 isa_cols[ncols]=cols[ncols];
1167 }
1168 continue;
1169 }
1170 if (!isa_ncols) continue;
1171 getword_start(&gwarea,linebuf);
1172 for (x=0 ; x<isa_ncols ; x++) {
1173 if (getword_ptr(linebuf,&str,&gwarea,'\t')<0) {
1174 debuga(_("Maybe you have a broken record or garbage in your %s file\n"),arq);
1175 exit(EXIT_FAILURE);
1176 }
1177 if (x==isa_cols[ISACOL_Ip]) {
1178 if (strlen(str)>=sizeof(ip)) {
1179 debuga(_("Maybe you have a broken IP in your %s file\n"),arq);
1180 exit(EXIT_FAILURE);
1181 }
1182 strcpy(ip,str);
1183 } else if (x==isa_cols[ISACOL_UserName]) {
1184 if (strlen(str)>=sizeof(user)) {
1185 debuga(_("Maybe you have a broken user ID in your %s file\n"),arq);
1186 exit(EXIT_FAILURE);
1187 }
1188 strcpy(user,str);
1189 } else if (x==isa_cols[ISACOL_Date]) {
1190 if (strlen(str)>=sizeof(data)) {
1191 debuga(_("Maybe you have a broken date in your %s file\n"),arq);
1192 exit(EXIT_FAILURE);
1193 }
1194 strcpy(data,str);
1195 } else if (x==isa_cols[ISACOL_Time]) {
1196 if (strlen(str)>=sizeof(hora)) {
1197 debuga(_("Maybe you have a broken time in your %s file\n"),arq);
1198 exit(EXIT_FAILURE);
1199 }
1200 strcpy(hora,str);
1201 } else if (x==isa_cols[ISACOL_TimeTaken]) {
1202 if (strlen(str)>=sizeof(elap)) {
1203 debuga(_("Maybe you have a broken download duration in your %s file\n"),arq);
1204 exit(EXIT_FAILURE);
1205 }
1206 strcpy(elap,str);
1207 } else if (x==isa_cols[ISACOL_Bytes]) {
1208 if (strlen(str)>=sizeof(tam)) {
1209 debuga(_("Maybe you have a broken download size in your %s file\n"),arq);
1210 exit(EXIT_FAILURE);
1211 }
1212 strcpy(tam,str);
1213 } else if (x==isa_cols[ISACOL_Uri]) {
1214 full_url=str;
1215 } else if (x==isa_cols[ISACOL_Status]) {
1216 if (strlen(str)>=sizeof(code)) {
1217 debuga(_("Maybe you have a broken access code in your %s file\n"),arq);
1218 exit(EXIT_FAILURE);
1219 }
1220 strcpy(code,str);
1221 }
1222 }
1223
1224 if(strcmp(code,"401") == 0 || strcmp(code,"403") == 0 || strcmp(code,"407") == 0) {
1225 sprintf(val1,"DENIED/%s",code);
1226 strcpy(code,val1);
1227 }
1228 getword_start(&gwarea,data);
1229 if (getword_atoll(&iyear,&gwarea,'-')<0){
1230 debuga(_("Maybe you have a broken year in your %s file\n"),arq);
1231 exit(EXIT_FAILURE);
1232 }
1233 if (getword_atoll(&imonth,&gwarea,'-')<0){
1234 debuga(_("Maybe you have a broken month in your %s file\n"),arq);
1235 exit(EXIT_FAILURE);
1236 }
1237 if (getword_atoll(&iday,&gwarea,'\0')<0){
1238 debuga(_("Maybe you have a broken day in your %s file\n"),arq);
1239 exit(EXIT_FAILURE);
1240 }
1241
1242 idata=builddia(iday,imonth,iyear);
1243 computedate(iyear,imonth,iday,&tt);
1244 if (isa_cols[ISACOL_Time]>=0) {
1245 if (sscanf(hora,"%d:%d:%d",&tt.tm_hour,&tt.tm_min,&tt.tm_sec)!=3 || tt.tm_hour<0 || tt.tm_hour>=24 ||
1246 tt.tm_min<0 || tt.tm_min>=60 || tt.tm_sec<0 || tt.tm_sec>=60) {
1247 debuga(_("Invalid time found in %s\n"),arq);
1248 exit(EXIT_FAILURE);
1249 }
1250 }
1251 t=&tt;
1252 }
1253 if (t==NULL) {
1254 debuga(_("Unknown input log file format\n"));
1255 break;
1256 }
1257
1258 strftime(dia, sizeof(dia), "%d/%m/%Y", t);
1259 snprintf(hora,sizeof(hora),"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);
1260
1261 if(debugm)
1262 printf("DATE=%s IDATA=%d DFROM=%d DUNTIL=%d\n",date,idata,dfrom,duntil);
1263
1264 if(date[0] != '\0'){
1265 if(idata < dfrom || idata > duntil) continue;
1266 }
1267
1268 // Record only hours usage which is required
1269 if (t) {
1270 if( bsearch( &( t -> tm_wday ), weekdays.list, weekdays.len, sizeof( int ), compar ) == NULL )
1271 continue;
1272
1273 if( bsearch( &( t -> tm_hour ), hours.list, hours.len, sizeof( int ), compar ) == NULL )
1274 continue;
1275 }
1276
1277
1278 if(strlen(user) > MAX_USER_LEN) {
1279 if (debugm) printf(_("User ID too long: %s\n"),user);
1280 totregsx++;
1281 continue;
1282 }
1283
1284 // include_users
1285 if(IncludeUsers[0] != '\0') {
1286 sprintf(val1,":%s:",user);
1287 if((str=(char *) strstr(IncludeUsers,val1)) == (char *) NULL )
1288 continue;
1289 }
1290
1291 if(vercode(code)) {
1292 if (debugm) printf(_("Excluded code: %s\n"),code);
1293 totregsx++;
1294 continue;
1295 }
1296
1297 if(testvaliduserchar(user))
1298 continue;
1299
1300 #if 0
1301 if((str = strstr(user,"%20")) != NULL) {
1302 /*
1303 This is a patch introduced to solve bug #1624251 reported at sourceforge but
1304 the side effect is to truncate the name at the first space and merge the reports
1305 of people whose name is identical up to the first space.
1306
1307 The old code used to truncate the user name at the first % if a %20 was
1308 found anywhere in the string. That means the string could be truncated
1309 at the wrong place if another % occured before the %20. This new code should
1310 avoid that problem and only truncate at the space. There is no bug
1311 report indicating that anybody noticed this.
1312 */
1313 *str='\0';
1314 }
1315
1316 /*
1317 Code prior to 2.2.7 used to replace any %xx by a dot as long as a %5c was
1318 found in the user name.
1319 */
1320 while((str = strstr(user,"%5c")) != NULL) {
1321 *str='.';
1322 for (x=3 ; str[x] ; x++) str[x-2]=str[x];
1323 }
1324 #endif
1325
1326 urly=full_url;
1327
1328 if(ilf!=ILF_Sarg) {
1329 /*
1330 The full URL is not saved in sarg log. There is no point in testing the URL to detect
1331 a downloaded file.
1332 */
1333 download_flag=is_download_suffix(full_url);
1334 if (download_flag) {
1335 download_url=full_url;
1336 download_count++;
1337 }
1338 } else
1339 download_flag=false;
1340
1341 url=process_url(full_url,LongUrl);
1342 if (!url || url[0] == '\0') continue;
1343
1344 if(addr[0] != '\0'){
1345 if(strcmp(addr,ip)!=0) continue;
1346 }
1347 if(fhost) {
1348 if(!vhexclude(url)) {
1349 if (debugm) printf(_("Excluded site: %s\n"),url);
1350 totregsx++;
1351 continue;
1352 }
1353 }
1354
1355 if(hm >= 0 && hmf >= 0) {
1356 hmr=t->tm_hour*100+t->tm_min;
1357 if(hmr < hm || hmr > hmf) continue;
1358 }
1359
1360 if(site[0] != '\0'){
1361 if(strstr(url,site)==0) continue;
1362 }
1363
1364 if(UserIp) {
1365 strcpy(user,ip);
1366 id_is_ip=true;
1367 } else {
1368 id_is_ip=false;
1369 if(strcmp(user,"-") == 0 || strcmp(user," ") == 0 || strcmp(user,"") == 0) {
1370 if(RecordsWithoutUser == RECORDWITHOUTUSER_IP) {
1371 strcpy(user,ip);
1372 id_is_ip=true;
1373 }
1374 if(RecordsWithoutUser == RECORDWITHOUTUSER_IGNORE)
1375 continue;
1376 if(RecordsWithoutUser == RECORDWITHOUTUSER_EVERYBODY)
1377 strcpy(user,"everybody");
1378 } else {
1379 strlow(user);
1380 if(NtlmUserFormat == NTLMUSERFORMAT_USER) {
1381 if((str = strchr(user,'_')) != 0) {
1382 strcpy(warea,str+1);
1383 strcpy(user,warea);
1384 }
1385 if((str = strchr(user,'+')) != 0) {
1386 strcpy(warea,str+1);
1387 strcpy(user,warea);
1388 }
1389 }
1390 }
1391 }
1392
1393 if(us[0] != '\0'){
1394 if(strcmp(user,us)!=0) continue;
1395 }
1396
1397 if(puser) {
1398 sprintf(wuser,":%s:",user);
1399 if(strstr(userfile, wuser) == 0)
1400 continue;
1401 }
1402
1403 if(fuser) {
1404 if(!vuexclude(user)) {
1405 if (debugm) printf(_("Excluded user: %s\n"),user);
1406 totregsx++;
1407 continue;
1408 }
1409 }
1410
1411 if(strcmp(user,"-") ==0 || strcmp(user," ") ==0 || strcmp(user,"") ==0 || strcmp(user,":") ==0)
1412 continue;
1413
1414 if(max_elapsed) {
1415 if(atol(elap)>max_elapsed) {
1416 elap[0]='0';
1417 elap[1]='\0';
1418 }
1419 }
1420
1421 if((str=(char *) strstr(linebuf, "[SmartFilter:")) != (char *) NULL ) {
1422 fixendofline(str);
1423 sprintf(smartfilter,"\"%s\"",str+1);
1424 } else sprintf(smartfilter,"\"\"");
1425
1426 nopen=0;
1427 prev_ufile=NULL;
1428 for (ufile=first_user_file ; ufile && strcmp(user,ufile->user->id)!=0 ; ufile=ufile->next) {
1429 prev_ufile=ufile;
1430 if (ufile->file) nopen++;
1431 }
1432 if (!ufile) {
1433 ufile=malloc(sizeof(*ufile));
1434 if (!ufile) {
1435 debuga(_("Not enough memory to store the user %s\n"),user);
1436 exit(EXIT_FAILURE);
1437 }
1438 memset(ufile,0,sizeof(*ufile));
1439 ufile->next=first_user_file;
1440 first_user_file=ufile;
1441 uinfo=userinfo_create(user);
1442 ufile->user=uinfo;
1443 uinfo->id_is_ip=id_is_ip;
1444 } else {
1445 if (prev_ufile) {
1446 prev_ufile->next=ufile->next;
1447 ufile->next=first_user_file;
1448 first_user_file=ufile;
1449 }
1450 }
1451
1452 if (ufile->file==NULL) {
1453 if (nopen>=maxopenfiles) {
1454 x=0;
1455 for (ufile1=first_user_file ; ufile1 ; ufile1=ufile1->next) {
1456 if (ufile1->file!=NULL) {
1457 if (x>=maxopenfiles) {
1458 if (fclose(ufile1->file)==EOF) {
1459 debuga(_("Failed to close the log file of user %s - %s\n"),ufile1->user->id,strerror(errno));
1460 exit(EXIT_FAILURE);
1461 }
1462 ufile1->file=NULL;
1463 }
1464 x++;
1465 }
1466 }
1467 }
1468 if (snprintf (tmp3, sizeof(tmp3), "%s/%s.unsort", tmp, ufile->user->filename)>=sizeof(tmp3)) {
1469 debuga(_("Temporary user file name too long: %s/%s.unsort\n"), tmp, ufile->user->filename);
1470 exit(EXIT_FAILURE);
1471 }
1472 if ((ufile->file = MY_FOPEN (tmp3, "a")) == NULL) {
1473 debuga(_("(log) Cannot open temporary file: %s - %s\n"), tmp3, strerror(errno));
1474 exit (1);
1475 }
1476 }
1477
1478 /*if ( strcmp ( user , sz_Last_User ) != 0 ) {
1479 if ( fp_Write_User )
1480 fclose( fp_Write_User ) ;
1481 sprintf (tmp3, "%s/%s.unsort", tmp, user);
1482
1483 if ((fp_Write_User = MY_FOPEN (tmp3, "a")) == NULL) {
1484 fprintf (stderr, "%s: (log) %s: %s - %s\n", argv[0], _("Cannot open temporary file"), tmp3, strerror(errno));
1485 exit (1);
1486 }
1487 strcpy( sz_Last_User , user ) ;
1488 }*/
1489 if (fprintf(ufile->file, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",dia,hora,ip,url,tam,code,elap,smartfilter)<=0) {
1490 debuga(_("Write error in the log file of user %s\n"),user);
1491 exit(EXIT_FAILURE);
1492 }
1493
1494 if(fp_log && ilf!=ILF_Sarg)
1495 fprintf(fp_log, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,url,tam,code,elap,smartfilter);
1496
1497 totregsg++;
1498
1499 if(!dataonly && download_flag && download_url && strstr(code,"DENIED") == 0) {
1500 ndownload = 1;
1501
1502 if ( ! fp_Download_Unsort ) {
1503 if ((fp_Download_Unsort = MY_FOPEN ( sz_Download_Unsort, "a")) == NULL) {
1504 debuga(_("(log) Cannot open temporary file: %s - %s\n"),sz_Download_Unsort, strerror(errno));
1505 exit (1);
1506 }
1507 }
1508 fprintf(fp_Download_Unsort,"%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,download_url);
1509 }
1510
1511 if((ReportType & REPORT_TYPE_DENIED) != 0 || (ReportType & REPORT_TYPE_AUTH_FAILURES) != 0) {
1512 if(fp_denied && strstr(code,"DENIED/403") != 0) {
1513 fprintf(fp_denied, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
1514 denied_count++;
1515 }
1516 if(fp_authfail && (strstr(code,"DENIED/401") != 0 || strstr(code,"DENIED/407") != 0)) {
1517 fprintf(fp_authfail, "%s\t%s\t%s\t%s\t%s\n",dia,hora,user,ip,urly);
1518 authfail_count++;
1519 }
1520 }
1521
1522 if (ilf!=ILF_Sarg) {
1523 if(!totper || idata<mindate){
1524 mindate=idata;
1525 memcpy(&period.start,t,sizeof(*t));
1526 strcpy(start_hour,tbuf2);
1527 }
1528 if (!totper || idata>maxdate) {
1529 maxdate=idata;
1530 memcpy(&period.end,t,sizeof(*t));
1531 }
1532 totper=true;
1533 }
1534
1535 if(debugm){
1536 printf("IP=\t%s\n",ip);
1537 printf("USER=\t%s\n",user);
1538 printf("ELAP=\t%s\n",elap);
1539 printf("DATE=\t%s\n",dia);
1540 printf("TIME=\t%s\n",hora);
1541 printf("FUNC=\t%s\n",fun);
1542 printf("URL=\t%s\n",url);
1543 printf("CODE=\t%s\n",code);
1544 printf("LEN=\t%s\n",tam);
1545 }
1546 }
1547 if (!from_stdin) {
1548 if (from_pipe)
1549 pclose(fp_in);
1550 else {
1551 fclose(fp_in);
1552 if( ShowReadStatistics )
1553 printf(_("SARG: Records in file: %lu, reading: %3.2f%%\n"),recs1, (float) 100 );
1554 }
1555 }
1556 }
1557
1558 if (debug)
1559 debuga(_(" Records read: %ld, written: %ld, excluded: %ld\n"),totregsl,totregsg,totregsx);
1560
1561 longline_destroy(&line);
1562 if ( fp_Download_Unsort )
1563 fclose (fp_Download_Unsort);
1564
1565 for (ufile=first_user_file ; ufile ; ufile=ufile1) {
1566 ufile1=ufile->next;
1567 if (ufile->file!=NULL) fclose(ufile->file);
1568 free(ufile);
1569 }
1570
1571 free_download();
1572 free_excludecodes();
1573 free_exclude();
1574
1575 if(debug) {
1576 int totalcount=0;
1577
1578 for (ilf=0 ; ilf<ILF_Last ; ilf++) totalcount+=ilf_count[ilf];
1579
1580 if(ilf_count[ILF_Common]>0 && ilf_count[ILF_Squid]>0)
1581 debuga(_("Log with mixed records format (squid and common log)\n"));
1582
1583 if(ilf_count[ILF_Common]>0 && ilf_count[ILF_Squid]==0)
1584 debuga(_("Common log format\n"));
1585
1586 if(ilf_count[ILF_Common]==0 && ilf_count[ILF_Squid]>0)
1587 debuga(_("Squid log format\n"));
1588
1589 if(ilf_count[ILF_Sarg]>0)
1590 debuga(_("Sarg log format\n"));
1591
1592 if(totalcount==0 && totregsg)
1593 debuga(_("Log with invalid format\n"));
1594 }
1595
1596 if(!totregsg){
1597 debuga(_("No records found\n"));
1598 debuga(_("End\n"));
1599 if(fp_denied) fclose(fp_denied);
1600 if(fp_authfail) fclose(fp_authfail);
1601 userinfo_free();
1602 if(userfile) free(userfile);
1603 close_usertab();
1604 exit(EXIT_SUCCESS);
1605 }
1606
1607 if (date[0]!='\0') {
1608 char date0[30], date1[30];
1609
1610 strftime(date0,sizeof(date0),"%d/%m/%Y",&period.start);
1611 strftime(date1,sizeof(date1),"%d/%m/%Y",&period.end);
1612 debuga(_("Period covered by log files: %s-%s\n"),date0,date1);
1613 getperiod_fromrange(&period,dfrom,duntil);
1614 }
1615 if (getperiod_buildtext(&period)<0) {
1616 debuga(_("Failed to build the string representation of the date range\n"));
1617 exit(EXIT_FAILURE);
1618 }
1619
1620 if(debugz){
1621 debugaz("data",dia);
1622 debugaz("period",period.text);
1623 }
1624
1625 if(debug)
1626 debuga(_("Period: %s\n"),period.text);
1627
1628 if(fp_denied)
1629 fclose(fp_denied);
1630 if(fp_authfail)
1631 fclose(fp_authfail);
1632
1633 if(fp_log != NULL) {
1634 fclose(fp_log);
1635 strcpy(end_hour,tbuf2);
1636 strftime(val2,sizeof(val2),"%d%m%Y",&period.start);
1637 strftime(val1,sizeof(val1),"%d%m%Y",&period.end);
1638 sprintf(val4,"%s/sarg-%s_%s-%s_%s.log",ParsedOutputLog,val2,start_hour,val1,end_hour);
1639 if (rename(arq_log,val4)) {
1640 debuga(_("failed to rename %s to %s - %s\n"),arq_log,val4,strerror(errno));
1641 } else {
1642 strcpy(arq_log,val4);
1643
1644 if(strcmp(ParsedOutputLogCompress,"nocompress") != 0 && ParsedOutputLogCompress[0] != '\0') {
1645 /*
1646 No double quotes around ParsedOutputLogCompress because it may contain command line options. If double quotes are
1647 necessary around the command name, put them in the configuration file.
1648 */
1649 sprintf(val1,"%s \"%s\"",ParsedOutputLogCompress,arq_log);
1650 cstatus=system(val1);
1651 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
1652 debuga(_("command return status %d\n"),WEXITSTATUS(cstatus));
1653 debuga(_("command: %s\n"),val1);
1654 exit(EXIT_FAILURE);
1655 }
1656 }
1657 }
1658 if(debug)
1659 debuga(_("Sarg parsed log saved as %s\n"),arq_log);
1660 }
1661
1662 if(DataFile[0] == '\0' && (ReportType & REPORT_TYPE_DENIED) != 0) {
1663 if (snprintf(csort,sizeof(csort),"sort -T \"%s\" -t \"\t\" -k 3,3 -k 5,5 -o \"%s\" \"%s\"",tmp,denied_sort,denied_unsort)>=sizeof(csort)) {
1664 debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),denied_unsort,denied_sort);
1665 exit(EXIT_FAILURE);
1666 }
1667 cstatus=system(csort);
1668 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
1669 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
1670 debuga(_("sort command: %s\n"),csort);
1671 exit(EXIT_FAILURE);
1672 }
1673 if (unlink(denied_unsort)) {
1674 debuga(_("Cannot delete %s - %s\n"),denied_unsort,strerror(errno));
1675 exit(EXIT_FAILURE);
1676 }
1677 }
1678
1679 sort_users_log(tmp, debug);
1680
1681 if(DataFile[0] != '\0')
1682 data_file(tmp);
1683 else
1684 gerarel();
1685
1686 if((ReportType & REPORT_TYPE_DENIED) != 0) {
1687 unlink(denied_sort);
1688 }
1689
1690 if(strcmp(tmp,"/tmp") != 0) {
1691 unlinkdir(tmp,0);
1692 }
1693
1694 free_hostalias();
1695 userinfo_free();
1696 if(userfile)
1697 free(userfile);
1698 close_usertab();
1699
1700 if(debug)
1701 debuga(_("End\n"));
1702
1703 exit(EXIT_SUCCESS);
1704 }
1705
1706
1707 static void getusers(const char *pwdfile, int debug)
1708 {
1709 FILE *fp_usr;
1710 char buf[255];
1711 char *str;
1712 long int nreg=0;
1713
1714 if(debug)
1715 debuga(_("Loading password file from %s\n"),pwdfile);
1716
1717 if ((fp_usr = fopen(pwdfile, "r")) == NULL) {
1718 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile,strerror(errno));
1719 exit(EXIT_FAILURE);
1720 }
1721
1722 if (fseek(fp_usr, 0, SEEK_END)==-1) {
1723 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile,strerror(errno));
1724 exit(EXIT_FAILURE);
1725 }
1726 nreg = ftell(fp_usr);
1727 if (nreg<0) {
1728 debuga(_("Cannot get the size of file %s\n"),pwdfile);
1729 exit(EXIT_FAILURE);
1730 }
1731 nreg = nreg+5000;
1732 if (fseek(fp_usr, 0, SEEK_SET)==-1) {
1733 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile,strerror(errno));
1734 exit(EXIT_FAILURE);
1735 }
1736
1737 if((userfile=(char *) malloc(nreg))==NULL){
1738 debuga(_("malloc error (%ld)\n"),nreg);
1739 exit(EXIT_FAILURE);
1740 }
1741
1742 bzero(userfile,nreg);
1743 strcpy(userfile,":");
1744
1745 while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
1746 str=strchr(buf,':');
1747 if (!str) {
1748 debuga(_("You have an invalid user in your %s file\n"),pwdfile);
1749 exit(EXIT_FAILURE);
1750 }
1751 str[1]='\0';
1752 strcat(userfile,buf);
1753 }
1754
1755 fclose(fp_usr);
1756
1757 return;
1758 }