2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
6 * please look at http://sarg.sourceforge.net/donations.php
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
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.
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.
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.
27 #include "include/conf.h"
28 #include "include/defs.h"
29 #include "include/readlog.h"
35 //! The log file filtering.
36 struct ReadLogDataStruct ReadFilter
;
38 //! The list of the system users.
39 /*@null@*/char *userfile
=NULL
;
41 static void getusers(const char *pwdfile
, int debug
);
43 int main(int argc
,char *argv
[])
51 char hexclude
[MAXLEN
];
52 char splitprefix
[MAXLEN
];
64 static int output_css
=0;
66 static struct option long_options
[]=
68 {"convert",no_argument
,&convert
,1},
69 {"css",no_argument
,&output_css
,1},
70 {"help",no_argument
,NULL
,'h'},
71 {"lastlog",required_argument
,NULL
,2},
72 {"keeplogs",no_argument
,NULL
,3},
73 {"split",no_argument
,&split
,1},
74 {"splitprefix",required_argument
,NULL
,'P'},
79 setlocale(LC_TIME
,"");
82 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H)
83 if (!setlocale (LC_ALL
, "")) {
84 fprintf(stderr
,"SARG: Cannot set the locale LC_ALL to the environment variable\n");
87 if (!bindtextdomain (PACKAGE_NAME
, LOCALEDIR
)) {
88 fprintf(stderr
,"SARG: Cannot bind to text domain %s in directory %s (%s)\n",PACKAGE_NAME
,LOCALEDIR
,strerror(errno
));
91 if (!textdomain (PACKAGE_NAME
)) {
92 fprintf(stderr
,"SARG: Cannot set gettext domain for %s PACKAGE_NAME (%s)\n",PACKAGE_NAME
,strerror(errno
));
102 UserAgentLog
[0]='\0';
103 ExcludeHosts
[0]='\0';
104 ExcludeUsers
[0]='\0';
111 ExternalCSSFile
[0]='\0';
112 RedirectorLogFormat
[0]='\0';
115 snprintf(ExcludeCodes
,sizeof(ExcludeCodes
),"%s/exclude_codes",SYSCONFDIR
);
116 strcpy(GraphDaysBytesBarColor
,"orange");
117 strcpy(BgColor
,"#ffffff");
118 strcpy(TxColor
,"#000000");
119 strcpy(TxBgColor
,"lavender");
120 strcpy(TiColor
,"darkblue");
123 strcpy(LogoTextColor
,"#000000");
124 strcpy(HeaderColor
,"darkblue");
125 strcpy(HeaderBgColor
,"#dddddd");
126 strcpy(LogoTextColor
,"#006699");
127 strcpy(FontSize
,"9px");
128 strcpy(TempDir
,"/tmp");
129 strcpy(OutputDir
,"/var/www/html/squid-reports");
130 AnonymousOutputFiles
=false;
133 OverwriteReport
=false;
134 RemoveTempFiles
=true;
135 strcpy(ReplaceIndex
,"index.html");
137 RecordsWithoutUser
=RECORDWITHOUTUSER_IP
;
139 strcpy(MailUtility
,"mailx");
143 TopuserSort
=TOPUSER_SORT_BYTES
| TOPUSER_SORT_REVERSE
;
144 UserSort
=USER_SORT_BYTES
| USER_SORT_REVERSE
;
145 TopsitesSort
=TOPSITE_SORT_CONNECT
| TOPSITE_SORT_REVERSE
;
147 strcpy(FontFace
,"Verdana,Tahoma,Arial");
148 datetimeby
=DATETIME_BYTE
;
149 strcpy(CharSet
,"ISO-8859-1");
151 strcpy(PrivacyString
,"***.***.***.***");
152 strcpy(PrivacyStringColor
,"blue");
154 TopUserFields
=TOPUSERFIELDS_NUM
| TOPUSERFIELDS_DATE_TIME
| TOPUSERFIELDS_USERID
| TOPUSERFIELDS_CONNECT
|
155 TOPUSERFIELDS_BYTES
| TOPUSERFIELDS_SETYB
| TOPUSERFIELDS_IN_CACHE_OUT
|
156 TOPUSERFIELDS_USED_TIME
| TOPUSERFIELDS_MILISEC
| TOPUSERFIELDS_PTIME
|
157 TOPUSERFIELDS_TOTAL
| TOPUSERFIELDS_AVERAGE
;
158 UserReportFields
=USERREPORTFIELDS_CONNECT
| USERREPORTFIELDS_BYTES
| USERREPORTFIELDS_SETYB
|
159 USERREPORTFIELDS_IN_CACHE_OUT
| USERREPORTFIELDS_USED_TIME
| USERREPORTFIELDS_MILISEC
|
160 USERREPORTFIELDS_PTIME
| USERREPORTFIELDS_TOTAL
| USERREPORTFIELDS_AVERAGE
;
161 strcpy(DataFileDelimiter
,";");
162 DataFileFields
=DATA_FIELD_USER
| DATA_FIELD_DATE
| DATA_FIELD_TIME
| DATA_FIELD_URL
| DATA_FIELD_CONNECT
|
163 DATA_FIELD_BYTES
| DATA_FIELD_IN_CACHE
| DATA_FIELD_OUT_CACHE
| DATA_FIELD_ELAPSED
;
164 ShowReadStatistics
=true;
165 ShowReadPercent
=false;
166 strcpy(IndexSortOrder
,"D");
169 ParsedOutputLog
[0]='\0';
170 strcpy(ParsedOutputLogCompress
,"/bin/gzip -f");
171 DisplayedValues
=DISPLAY_ABBREV
;
172 strcpy(HeaderFontSize
,"9px");
173 strcpy(TitleFontSize
,"11px");
174 strcpy(AuthUserTemplateFile
,"sarg_htaccess");
175 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");
178 strcpy(GraphFont
,FONTDIR
"/DejaVuSans.ttf");
182 strcpy(Ulimit
,"20000");
183 NtlmUserFormat
=NTLMUSERFORMAT_DOMAINUSER
;
184 IndexTree
=INDEX_TREE_FILE
;
185 IndexFields
=INDEXFIELDS_DIRSIZE
;
186 strcpy(RealtimeTypes
,"GET,PUT,CONNECT");
187 RealtimeUnauthRec
=REALTIME_UNAUTH_REC_SHOW
;
188 RedirectorFilterOutDate
=true;
189 DansguardianFilterOutDate
=true;
190 DataFileUrl
=DATAFILEURL_IP
;
191 strcpy(MaxElapsed
,"28800000");
192 BytesInSitesUsersReport
=0;
193 UserAuthentication
=0;
194 strcpy(LDAPHost
,"127.0.0.1");
196 LDAPProtocolVersion
=3;
199 LDAPBaseSearch
[0]='\0';
200 strcpy(LDAPFilterSearch
, "(uid=%s)");
201 strcpy(LDAPTargetAttr
, "cn");
206 ReadFilter
.DateRange
[0]='\0';
211 ReadFilter
.StartTime
=-1;
212 ReadFilter
.EndTime
=-1;
217 UserInvalidChar
[0]='\0';
219 SquidGuardConf
[0]='\0';
220 DansGuardianConf
[0]='\0';
222 HostAliasFile
[0]='\0';
225 dansguardian_count
=0;
228 DeniedReportLimit
=10;
229 AuthfailReportLimit
=10;
230 DansGuardianReportLimit
=10;
231 SquidGuardReportLimit
=10;
232 DownloadReportLimit
=50;
241 realtime_access_log_lines
=1000;
250 bzero(IncludeUsers
, sizeof(IncludeUsers
));
251 bzero(ExcludeString
, sizeof(ExcludeString
));
252 memset(&period
,0,sizeof(period
));
255 for(x
=0; x
<MAXLOGS
; x
++)
256 AccessLog
[x
][0]='\0';
257 AccessLogFromCmdLine
=0;
258 RedirectorLogFromCmdLine
=0;
260 strcpy(Title
,_("Squid User Access Report"));
262 while((ch
= getopt_long_only(argc
, argv
, "a:b:c:d:e:f:g:hikl:L:mno:P:prs:t:u:vw:xyz",long_options
,&option_index
)) != -1){
268 lastlog
=atoi(optarg
);
274 safe_strcpy(addr
,optarg
,sizeof(addr
));
276 case 'b': //unused option
277 safe_strcpy(uagent
,optarg
,sizeof(uagent
));
280 safe_strcpy(hexclude
,optarg
,sizeof(hexclude
));
283 safe_strcpy(ReadFilter
.DateRange
,optarg
,sizeof(ReadFilter
.DateRange
));
284 date_from(ReadFilter
.DateRange
, &dfrom
, &duntil
);
287 safe_strcpy(email
,optarg
,sizeof(email
));
290 safe_strcpy(ConfigFile
,optarg
,sizeof(ConfigFile
));
305 if (NAccessLog
>=MAXLOGS
) {
306 debuga(_("Too many log files passed on command line with option -l.\n"));
309 if (strlen(optarg
)>=MAX_LOG_FILELEN
) {
310 debuga(_("Log file name too long passed on command line with option -l: %s\n"),optarg
);
313 strcpy(AccessLog
[NAccessLog
],optarg
);
315 AccessLogFromCmdLine
++;
318 if (NRedirectorLogs
>MAX_REDIRECTOR_LOGS
) {
319 debuga(_("Too many redirector logs passed on command line with option -L.\n"));
322 if (strlen(optarg
)>=MAX_REDIRECTOR_FILELEN
) {
323 debuga(_("Redirector log file name too long passed on command line with opton -L: %s\n"),optarg
);
326 strcpy(RedirectorLogs
[NRedirectorLogs
],optarg
);
328 RedirectorLogFromCmdLine
++;
337 safe_strcpy(outdir
,optarg
,sizeof(outdir
));
343 safe_strcpy(splitprefix
,optarg
,sizeof(splitprefix
));
349 safe_strcpy(site
,optarg
,sizeof(site
));
355 if(strstr(optarg
,"-") == 0) {
356 if(sscanf(optarg
,"%d:%d",&h1
,&m1
)!=2) {
357 debuga(_("Time period passed on the command line with option -t must be HH:MM\n"));
360 ReadFilter
.StartTime
=h1
*100+m1
;
361 ReadFilter
.EndTime
=ReadFilter
.StartTime
;
362 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d",h1
,m1
);
364 if(sscanf(optarg
,"%d:%d-%d:%d",&h1
,&m1
,&h2
,&m2
)!=4) {
365 debuga(_("Time range passed on the command line with option -t must be HH:MM-HH:MM\n"));
368 ReadFilter
.StartTime
=h1
*100+m1
;
369 ReadFilter
.EndTime
=h2
*100+m2
;
370 snprintf(hm_str
,sizeof(hm_str
),"%02d:%02d-%02d:%02d",h1
,m1
,h2
,m2
);
375 safe_strcpy(us
,optarg
,sizeof(us
));
381 safe_strcpy(tmp
,optarg
,sizeof(tmp
));
386 case 'y': //unused option
393 debuga(_("Option -%c requires an argument\n"),optopt
);
409 for (iarq
=optind
; iarq
<argc
; iarq
++) {
410 if (NAccessLog
>=MAXLOGS
) {
411 debuga(_("Too many log files passed on command line.\n"));
414 if (strlen(argv
[iarq
])>=MAX_LOG_FILELEN
) {
415 debuga(_("Log file name too long passed on command line: %s\n"),argv
[iarq
]);
418 strcpy(AccessLog
[NAccessLog
],argv
[iarq
]);
420 AccessLogFromCmdLine
++;
424 if(debug
) debuga(_("Init\n"));
426 if(ConfigFile
[0] == '\0') snprintf(ConfigFile
,sizeof(ConfigFile
),"%s/sarg.conf",SYSCONFDIR
);
427 if(access(ConfigFile
, R_OK
) != 0) {
428 debuga(_("Cannot open config file: %s - %s\n"),ConfigFile
,strerror(errno
));
432 if(access(ConfigFile
, R_OK
) == 0)
435 if(userip
) UserIp
=true;
437 if(dns
) ip2name_forcedns();
439 if (lastlog
>=0) LastLog
=lastlog
;
441 if(outdir
[0] == '\0') strcpy(outdir
,OutputDir
);
442 if(outdir
[0] != '\0') strcat(outdir
,"/");
449 if(IndexTree
== INDEX_TREE_FILE
)
450 strcpy(ImageFile
,"../images");
452 strcpy(ImageFile
,"../../../images");
455 if(DataFile
[0] != '\0')
458 if (df
=='\0') df
=DateFormat
;
459 if (df
=='\0') df
='u';
461 IndexTree
=INDEX_TREE_FILE
;
463 if(NAccessLog
== 0) {
464 strcpy(AccessLog
[0],"/var/log/squid/access.log");
473 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
474 splitlog(AccessLog
[iarq
], df
, dfrom
, duntil
, convert
, splitprefix
);
478 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
479 convlog(AccessLog
[iarq
], df
, dfrom
, duntil
);
483 load_excludecodes(ExcludeCodes
);
485 if(access(PasswdFile
, R_OK
) == 0) {
486 getusers(PasswdFile
,debug
);
487 ReadFilter
.SysUsers
=true;
489 ReadFilter
.SysUsers
=false;
492 if(hexclude
[0] == '\0')
493 strcpy(hexclude
,ExcludeHosts
);
494 if(hexclude
[0] != '\0') {
495 gethexclude(hexclude
,debug
);
496 ReadFilter
.HostFilter
=true;
498 ReadFilter
.HostFilter
=false;
501 if(ReportType
== 0) {
502 ReportType
=REPORT_TYPE_TOPUSERS
| REPORT_TYPE_TOPSITES
| REPORT_TYPE_USERS_SITES
|
503 REPORT_TYPE_SITES_USERS
| REPORT_TYPE_DATE_TIME
| REPORT_TYPE_DENIED
|
504 REPORT_TYPE_AUTH_FAILURES
| REPORT_TYPE_SITE_USER_TIME_DATE
| REPORT_TYPE_DOWNLOADS
;
507 if(access(ExcludeUsers
, R_OK
) == 0) {
508 getuexclude(ExcludeUsers
,debug
);
509 ReadFilter
.UserFilter
=true;
511 ReadFilter
.UserFilter
=false;
513 if (HostAliasFile
[0] != '\0')
514 read_hostalias(HostAliasFile
);
517 if(ReadFilter
.UserFilter
) {
521 if(strcmp(ExcludeUsers
,"indexonly") == 0) indexonly
=true;
522 if(Index
== INDEX_ONLY
) indexonly
=true;
524 if(MaxElapsed
[0] != '\0')
525 ReadFilter
.max_elapsed
=atol(MaxElapsed
);
527 ReadFilter
.max_elapsed
=0;
529 if(uagent
[0] == '\0') strcpy(uagent
,UserAgentLog
);
531 if(tmp
[0] == '\0') strcpy(tmp
,TempDir
);
532 else strcpy(TempDir
,tmp
);
534 For historical reasons, the temporary directory is the subdirectory "sarg" of the path
535 provided by the user.
539 if (tmp
[0]!='\0' && strncmp(outdir
,tmp
,strlen(tmp
))==0) {
540 debuga(_("The output directory \"%s\" must be outside of the temporary directory \"%s\"\n"),outdir
,tmp
);
544 if(email
[0] == '\0' && OutputEmail
[0] != '\0') strcpy(email
,OutputEmail
);
546 if(email
[0] != '\0') {
552 if(access(tmp
, R_OK
) == 0) {
553 if (debug
) debuga(_("Deleting temporary directory \"%s\"\n"),tmp
);
559 debuga(_("Parameters:\n"));
560 debuga(_(" Hostname or IP address (-a) = %s\n"),addr
);
561 debuga(_(" Useragent log (-b) = %s\n"),uagent
);
562 debuga(_(" Exclude file (-c) = %s\n"),hexclude
);
563 debuga(_(" Date from-until (-d) = %s\n"),ReadFilter
.DateRange
);
564 debuga(_(" Email address to send reports (-e) = %s\n"),email
);
565 debuga(_(" Config file (-f) = %s\n"),ConfigFile
);
567 debuga(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
569 debuga(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
571 debuga(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
572 debuga(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
573 debuga(_(" Keep temporary files (-k) = %s\n"),(KeepTempLog
) ? _("Yes") : _("No"));
574 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
575 debuga(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
576 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
577 debuga(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
578 debuga(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
579 debuga(_(" Output dir (-o) = %s\n"),outdir
);
580 debuga(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
581 debuga(_(" Accessed site (-s) = %s\n"),site
);
582 debuga(_(" Time (-t) = %s\n"),hm_str
);
583 debuga(_(" User (-u) = %s\n"),us
);
584 debuga(_(" Temporary dir (-w) = %s\n"),tmp
);
585 debuga(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
586 debuga(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
587 debuga(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
592 printf(_("Parameters:\n"));
593 printf(_(" Hostname or IP address (-a) = %s\n"),addr
);
594 printf(_(" Useragent log (-b) = %s\n"),uagent
);
595 printf(_(" Exclude file (-c) = %s\n"),hexclude
);
596 printf(_(" Date from-until (-d) = %s\n"),ReadFilter
.DateRange
);
597 printf(_(" Email address to send reports (-e) = %s\n"),email
);
598 printf(_(" Config file (-f) = %s\n"),ConfigFile
);
600 printf(_(" Date format (-g) = Europe (dd/mm/yyyy)\n"));
602 printf(_(" Date format (-g) = USA (mm/dd/yyyy)\n"));
604 printf(_(" Date format (-g) = Sites & Users (yyyy/ww)\n"));
605 printf(_(" IP report (-i) = %s\n"),(iprel
) ? _("Yes") : _("No"));
606 printf(_(" Keep temporary files (-k) = %s\n"),(KeepTempLog
) ? _("Yes") : _("No"));
607 for (iarq
=0 ; iarq
<NAccessLog
; iarq
++)
608 printf(_(" Input log (-l) = %s\n"),AccessLog
[iarq
]);
609 for (iarq
=0 ; iarq
<NRedirectorLogs
; iarq
++)
610 printf(_(" Redirector log (-L) = %s\n"),RedirectorLogs
[iarq
]);
611 printf(_(" Resolve IP Address (-n) = %s\n"),(Ip2Name
) ? _("Yes") : _("No"));
612 printf(_(" Output dir (-o) = %s\n"),outdir
);
613 printf(_("Use Ip Address instead of userid (-p) = %s\n"),(UserIp
) ? _("Yes") : _("No"));
614 printf(_(" Accessed site (-s) = %s\n"),site
);
615 printf(_(" Time (-t) = %s\n"),hm_str
);
616 printf(_(" User (-u) = %s\n"),us
);
617 printf(_(" Temporary dir (-w) = %s\n"),tmp
);
618 printf(_(" Debug messages (-x) = %s\n"),(debug
) ? _("Yes") : _("No"));
619 printf(_(" Process messages (-z) = %s\n"),(debugz
) ? _("Yes") : _("No"));
620 printf(_(" Previous reports to keep (--lastlog) = %d\n"),LastLog
);
621 printf(_("sarg version: %s\n"),VERSION
);
625 debuga(_("sarg version: %s\n"),VERSION
);
627 #ifdef ENABLE_DOUBLE_CHECK_DATA
628 debuga(_("Sarg compiled to report warnings if the output is inconsistent\n"));
632 if (Ulimit
[0] != '\0') {
637 #if defined(RLIMIT_NOFILE)
638 getrlimit (RLIMIT_NOFILE
, &rl
);
639 #elif defined(RLIMIT_OFILE)
640 getrlimit (RLIMIT_OFILE
, &rl
);
642 #warning "No rlimit resource for the number of open files"
647 rl
.rlim_cur
= atol(Ulimit
);
648 rl
.rlim_max
= atol(Ulimit
);
649 #if defined(RLIMIT_NOFILE)
650 rc
=setrlimit (RLIMIT_NOFILE
, &rl
);
651 #elif defined(RLIMIT_OFILE)
652 rc
=setrlimit (RLIMIT_OFILE
, &rl
);
654 #warning "No rlimit resource for the number of open files"
657 debuga(_("setrlimit error - %s\n"),strerror(errno
));
661 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
);
665 init_usertab(UserTabFile
);
667 LogStatus
=ReadLogFile(&ReadFilter
);
674 debuga(_("No records found\n"));
677 if(userfile
) free(userfile
);
682 if (ReadFilter
.DateRange
[0]!='\0') {
683 char date0
[30], date1
[30];
685 strftime(date0
,sizeof(date0
),"%d/%m/%Y",&period
.start
);
686 strftime(date1
,sizeof(date1
),"%d/%m/%Y",&period
.end
);
687 debuga(_("Period covered by log files: %s-%s\n"),date0
,date1
);
688 getperiod_fromrange(&period
,dfrom
,duntil
);
690 if (getperiod_buildtext(&period
)<0) {
691 debuga(_("Failed to build the string representation of the date range\n"));
696 debuga(_("Period: %s\n"),period
.text
);
698 if(DataFile
[0] != '\0')
707 if(!KeepTempLog
&& strcmp(tmp
,"/tmp") != 0) {
725 static void getusers(const char *pwdfile
, int debug
)
733 debuga(_("Loading password file from %s\n"),pwdfile
);
735 if ((fp_usr
= fopen(pwdfile
, "r")) == NULL
) {
736 debuga(_("(getusers) Cannot open file %s - %s\n"),pwdfile
,strerror(errno
));
740 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
741 debuga(_("Failed to move till the end of the users file %s: %s\n"),pwdfile
,strerror(errno
));
744 nreg
= ftell(fp_usr
);
746 debuga(_("Cannot get the size of file %s\n"),pwdfile
);
750 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
751 debuga(_("Failed to rewind the users file %s: %s\n"),pwdfile
,strerror(errno
));
755 if((userfile
=(char *) malloc(nreg
))==NULL
){
756 debuga(_("malloc error (%ld)\n"),nreg
);
760 bzero(userfile
,nreg
);
761 strcpy(userfile
,":");
763 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
766 debuga(_("You have an invalid user in your %s file\n"),pwdfile
);
770 strcat(userfile
,buf
);