]> git.ipfire.org Git - thirdparty/sarg.git/blob - util.c
Pre-parse variables Index and IndexTree
[thirdparty/sarg.git] / util.c
1 /*
2 * AUTHOR: Pedro Lineu Orso pedro.orso@gmail.com
3 * 1998, 2010
4 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
5 *
6 * SARG donations:
7 * please look at http://sarg.sourceforge.net/donations.php
8 * ---------------------------------------------------------------------
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
23 *
24 */
25
26 // #define LEGACY_MY_ATOLL
27 // #define LEGACY_TESTVALIDUSERCHAR
28
29 #include "include/conf.h"
30 #include "include/defs.h"
31
32 #if defined(HAVE_BACKTRACE)
33 #define USE_GETWORD_BACKTRACE 1
34 #else
35 #define USE_GETWORD_BACKTRACE 0
36 #endif
37
38 static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
39
40 //! The list of the HTTP codes to exclude from the report.
41 static char *excludecode=NULL;
42
43 /*void fgetword(char *word, char *line, int stop)
44 {
45 //VARIANT N1
46 int x;
47
48 for (x=0; line[x] && (line[x] != stop); x++) word[x] = line[x];
49 word[x] = '\0';
50
51 //VARIANT N2
52 char *tchar;
53 int difflen;
54
55 tchar = strchr(line, stop);
56 if (tchar == NULL) strcpy(word, line);
57 else
58 {
59 difflen = tchar - line;
60 strncpy(word, line, difflen);
61 word[difflen] = '\0';
62 }
63 }*/
64
65 #if USE_GETWORD_BACKTRACE
66 static void getword_backtrace(void)
67 {
68 void *buffer[5];
69 int i, n;
70 char **calls;
71
72 n=backtrace(buffer,sizeof(buffer)/sizeof(buffer[0]));
73 if (n<=0) return;
74 calls=backtrace_symbols(buffer,n);
75 if (calls) {
76 fprintf(stderr,"SARG: getword backtrace:\n");
77 for (i=0 ; i<n ; i++) {
78 fprintf(stderr,"SARG: %d:%s\n",i+1,calls[i]);
79 }
80 free(calls);
81 }
82 }
83 #endif //USE_GETWORD_BACKTRACE
84
85 void getword_start(struct getwordstruct *gwarea, const char *line)
86 {
87 gwarea->beginning=line;
88 gwarea->current=line;
89 }
90
91 void getword_restart(struct getwordstruct *gwarea)
92 {
93 gwarea->current=gwarea->beginning;
94 }
95
96 int getword(char *word, int limit, struct getwordstruct *gwarea, int stop)
97 {
98 int x;
99
100 for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) {
101 if(x>=limit) {
102 printf("SARG: getword loop detected after %d bytes.\n",x);
103 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
104 printf("SARG: Record=\"%s\"\n",gwarea->current);
105 printf("SARG: searching for \'x%x\'\n",stop);
106 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
107 word[(limit>0) ? limit-1 : 0]='\0';
108 #if USE_GETWORD_BACKTRACE
109 getword_backtrace();
110 #endif
111 return(-1);
112 }
113 word[x] = gwarea->current[x];
114 }
115
116 word[x] = '\0';
117 if (gwarea->current[x]) ++x;
118 gwarea->current+=x;
119 return(0);
120 }
121
122 int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, int stop)
123 {
124 int x;
125
126 for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) {
127 if(x>=limit) {
128 printf("SARG: getword_multisep loop detected.\n");
129 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
130 printf("SARG: Record=\"%s\"\n",gwarea->current);
131 printf("SARG: searching for \'x%x\'\n",stop);
132 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
133 if (limit>0) word[limit-1]='\0';
134 #if USE_GETWORD_BACKTRACE
135 getword_backtrace();
136 #endif
137 //exit(1);
138 return(-1);
139 }
140 word[x] = gwarea->current[x];
141 }
142
143 word[x] = '\0';
144 while (gwarea->current[x] && gwarea->current[x]==stop) ++x;
145 gwarea->current+=x;
146 return(0);
147 }
148
149 int getword_skip(int limit, struct getwordstruct *gwarea, int stop)
150 {
151 int x;
152
153 for(x=0;(gwarea->current[x] && (gwarea->current[x] != stop ));x++) {
154 if(x>=limit) {
155 printf("SARG: getword_skip loop detected after %d bytes.\n",x);
156 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
157 printf("SARG: Record=\"%s\"\n",gwarea->current);
158 printf("SARG: searching for \'x%x\'\n",stop);
159 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
160 #if USE_GETWORD_BACKTRACE
161 getword_backtrace();
162 #endif
163 return(-1);
164 }
165 }
166
167 if (gwarea->current[x]) ++x;
168 gwarea->current+=x;
169 return(0);
170 }
171
172 int getword_atoll(long long int *number, struct getwordstruct *gwarea, int stop)
173 {
174 int x;
175 int sign=+1;
176
177 if (gwarea->current[0] == '-') {
178 gwarea->current++;
179 sign=-1;
180 } else if (gwarea->current[0] == '+') {
181 gwarea->current++;
182 }
183 *number=0LL;
184 for(x=0;isdigit(gwarea->current[x]);x++) {
185 *number=(*number * 10) + gwarea->current[x]-'0';
186 }
187 if(gwarea->current[x] && gwarea->current[x]!=stop) {
188 printf("SARG: getword_atoll loop detected after %d bytes.\n",x);
189 printf("SARG: Line=\"%s\"\n",gwarea->beginning);
190 printf("SARG: Record=\"%s\"\n",gwarea->current);
191 printf("SARG: searching for \'x%x\'\n",stop);
192 //printf("SARG: Maybe you have a broken record or garbage in your access.log file.\n");
193 #if USE_GETWORD_BACKTRACE
194 getword_backtrace();
195 #endif
196 return(-1);
197 }
198 *number*=sign;
199
200 if (gwarea->current[x]) ++x;
201 gwarea->current+=x;
202 return(0);
203 }
204
205
206 #define MAXLLL 30 //!< Maximum number of digits in long long (a guess).
207 long long int my_atoll (const char *nptr)
208 {
209 long long int returnval=0LL;
210 int max_digits = MAXLLL ;
211
212 // Soak up all the white space
213 while (isspace( *nptr )) {
214 nptr++;
215 }
216
217 //For each character left to right
218 //change the character to a single digit
219 //multiply what we had before by 10 and add the new digit
220
221 while (--max_digits && isdigit( *nptr ))
222 {
223 returnval = ( returnval * 10 ) + ( *nptr++ - '0' ) ;
224 }
225
226 return returnval;
227 }
228
229 int is_absolute(const char *path)
230 {
231 if (*path=='/') return(1);
232 #ifdef WINDOWS
233 if (isalpha(path[0]) && path[1]==':') return(1);
234 #endif
235 return(0);
236 }
237
238 void my_mkdir(const char *name)
239 {
240 char w0[MAXLEN];
241 int i;
242 int chars;
243
244 if(!is_absolute(name)) {
245 fprintf(stderr,"SARG: Invalid path (%s). Please, use absolute paths only.\n",name);
246 fprintf(stderr,"SARG: process aborted.\n");
247 exit(1);
248 }
249
250 chars=0;
251 for (i=0 ; name[i] ; i++) {
252 if (i>=sizeof(w0)) {
253 fprintf(stderr,"SARG: directory name too long %s\n",name);
254 exit(1);
255 }
256 if (chars>0 && name[i] == '/') {
257 w0[i] = '\0';
258 if(access(w0, R_OK) != 0) {
259 if(mkdir(w0,0755)) {
260 fprintf(stderr,"SARG: mkdir %s %s\n",w0,strerror(errno));
261 fprintf(stderr,"SARG: process aborted.\n");
262 exit(1);
263 }
264 }
265 }
266 if (name[i] != '/') chars++;
267 w0[i] = name[i];
268 }
269
270 if(access(name, R_OK) != 0) {
271 if(mkdir(name,0755)) {
272 fprintf(stderr,"SARG: mkdir %s %s\n",name,strerror(errno));
273 fprintf(stderr,"SARG: process aborted.\n");
274 exit(1);
275 }
276 }
277 }
278
279
280 void my_lltoa(unsigned long long int n, char s[], int len)
281 {
282 int i;
283 int slen = 0;
284 int j;
285 char c;
286
287 do {
288 s[slen++] = (n % 10) + '0';
289 } while ((n /= 10) > 0);
290 s[slen] = '\0';
291
292 for (i = 0, j = slen-1; i<j; i++, j--) {
293 c = s[i];
294 s[i] = s[j];
295 s[j] = c;
296 }
297
298 if(len>slen) {
299 i=len-slen;
300 for(j=slen; j>=0; j--)
301 s[j+i]=s[j];
302 for(j=0 ; j<i ; j++)
303 s[j]='0';
304 }
305 }
306
307
308 void builddia(char *dia, const char *mes, const char *ano, const char *df, char *wdata)
309 {
310 char ndia[11];
311 int nmes;
312
313 if(strlen(dia) < 1) return;
314
315 for(nmes=0; nmes<12; nmes++) {
316 if(strcmp(mtab1[nmes],mes) == 0) {
317 break;
318 }
319 }
320 nmes++;
321
322 snprintf(wdata,9,"%s%02d%s",ano,nmes,dia);
323
324 if(df[0]!='u')
325 snprintf(ndia,sizeof(ndia),"%s/%02d/%s",dia,nmes,ano);
326 else
327 snprintf(ndia,sizeof(ndia),"%02d/%s/%s",nmes,dia,ano);
328
329 strcpy(dia,ndia);
330
331 }
332
333
334 void buildymd(const char *dia, const char *mes, const char *ano, char *wdata)
335 {
336 int nmes;
337
338 for(nmes=0; nmes<12; nmes++) {
339 if(strcmp(mtab1[nmes],mes) == 0)
340 break;
341 }
342
343 sprintf(wdata,"%04d%02d%02d",atoi(ano),nmes+1,atoi(dia));
344
345 }
346
347
348 void conv_month(char *month)
349 {
350 int x;
351
352 for(x=0; x<12 && strcmp(mtab1[x],month)!=0; x++);
353 sprintf(month,"%02d",x+1);
354 }
355
356
357 void conv_month_name(char *month)
358 {
359 int x;
360
361 x=atoi(month);
362 if (x>=1 && x<=12)
363 strcpy(month,mtab1[x-1]);
364 }
365
366
367 void name_month(char *month,int month_len)
368 {
369 int x, z=atoi(month)-1;
370 char m[255];
371 char w[20];
372 struct getwordstruct gwarea;
373
374 strcpy(m,text[133]);
375 getword_start(&gwarea,m);
376
377 for(x=0; x<z; x++)
378 if (getword_multisep(w,sizeof(w),&gwarea,',')<0) {
379 printf("SARG: Maybe you have a broken record or garbage in the names of the months.\n");
380 exit(1);
381 }
382 if (getword_multisep(month,month_len,&gwarea,',')<0) {
383 printf("SARG: Maybe you have a broken record or garbage in the name of the months.\n");
384 exit(1);
385 }
386 }
387
388
389 void fixper(char *tbuf, char *period, const char *duntil)
390 {
391 char warea[50];
392 char dia[5], mes[5], ano[5];
393 int x;
394
395 strncpy(dia,duntil+6,2);
396 dia[2]='\0';
397 strncpy(mes,duntil+4,2);
398 mes[2]='\0';
399 strncpy(ano,duntil,4);
400 ano[4]='\0';
401
402 x=atoi(mes);
403 if (x>=1 && x<=12)
404 strcpy(mes,mtab1[x-1]);
405
406 if(strcmp(df,"e") == 0)
407 sprintf(warea,"%s%s%s",dia,mes,ano);
408 else if(strcmp(df,"u") == 0)
409 sprintf(warea,"%s%s%s",ano,mes,dia);
410 else
411 warea[0]='\0';
412
413 strcat(period,warea);
414 }
415
416
417 void debuga(const char *msg,...)
418 {
419 va_list ap;
420
421 fputs("SARG: ",stderr);
422 va_start(ap,msg);
423 vfprintf(stderr,msg,ap);
424 va_end(ap);
425 fputc('\n',stderr);
426 }
427
428
429 void debugaz(const char *head, const char *msg)
430 {
431 fprintf(stderr, "SARG: (util) %s=%s\n",head, msg);
432
433 }
434
435
436 void fixip(char *ip)
437 {
438 int i;
439 char sep='_';
440 char search=0;
441 int nrepl=0;
442
443 for (i=0; ip[i]; i++) {
444 if (ip[i]=='.') {
445 search='.';
446 sep='_';
447 break;
448 }
449 if (ip[i]=='_') {
450 search='_';
451 sep='.';
452 break;
453 }
454 }
455 for (; ip[i]; i++) {
456 if (ip[i]==search) {
457 ip[i]=sep;
458 nrepl++;
459 if (nrepl>=3) break;
460 }
461 }
462 }
463
464
465 char *fixnum(long long int value, int n)
466 {
467 #define MAXLEN_FIXNUM 1024
468 char num[MAXLEN_FIXNUM]="";
469 char buf[MAXLEN_FIXNUM * 2];
470 char *pbuf;
471 static char ret[MAXLEN_FIXNUM * 2];
472 char *pret;
473 register int i, j, k;
474 int numlen;
475 static char abbrev[30];
476
477 my_lltoa(value, num, 0);
478
479 if(strcmp(DisplayedValues,"abbreviation") == 0) {
480 numlen = strlen(num);
481 if(numlen <= 3)
482 sprintf(abbrev,"%s",num);
483 if(numlen == 4 || numlen == 7 || numlen == 10 || numlen == 13) {
484 snprintf(abbrev,2,"%s",num);
485 strncat(abbrev,".",1);
486 strncat(abbrev,num+1,2);
487 if(!n) return(abbrev);
488 if(numlen == 4)
489 strncat(abbrev,"K",1);
490 else if(numlen == 7)
491 strncat(abbrev,"M",1);
492 else if(numlen == 10)
493 strncat(abbrev,"G",1);
494 else if(numlen == 13)
495 strncat(abbrev,"T",1);
496 }
497 if(numlen == 5 || numlen == 8 || numlen == 11 || numlen == 14) {
498 snprintf(abbrev,3,"%s",num);
499 strncat(abbrev,".",1);
500 strncat(abbrev,num+2,2);
501 if(!n) return(abbrev);
502 if(numlen == 5)
503 strncat(abbrev,"K",1);
504 else if(numlen == 8)
505 strncat(abbrev,"M",1);
506 else if(numlen == 11)
507 strncat(abbrev,"G",1);
508 else if(numlen == 14)
509 strncat(abbrev,"T",1);
510 }
511 if(numlen == 6 || numlen == 9 || numlen == 12 || numlen == 15) {
512 snprintf(abbrev,4,"%s",num);
513 strncat(abbrev,".",1);
514 strncat(abbrev,num+3,2);
515 if(!n) return(abbrev);
516 if(numlen == 6)
517 strncat(abbrev,"K",1);
518 else if(numlen == 9)
519 strncat(abbrev,"M",1);
520 else if(numlen == 12)
521 strncat(abbrev,"G",1);
522 else if(numlen == 15)
523 strncat(abbrev,"T",1);
524 }
525
526 return(abbrev);
527 }
528
529 bzero(buf, MAXLEN_FIXNUM*2);
530
531 pbuf = buf;
532 pret = ret;
533 k = 0;
534
535 for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
536 if ( k == 2 && i != 0 ) {
537 k = 0;
538 pbuf[j++] = num[i];
539 pbuf[j++] = (UseComma) ? ',' : '.';
540 continue;
541 }
542 pbuf[j] = num[i];
543 j++;
544 k++;
545 }
546
547 pret[0]='\0';
548
549 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
550 pret[j] = pbuf[i];
551
552 pret[j] = '\0';
553
554 return pret;
555 }
556
557
558 char *fixnum2(long long int value, int n)
559 {
560 #define MAXLEN_FIXNUM2 1024
561 char num[MAXLEN_FIXNUM2];
562 char buf[MAXLEN_FIXNUM2 * 2];
563 char *pbuf;
564 static char ret[MAXLEN_FIXNUM2 * 2];
565 char *pret;
566 register int i, j, k;
567
568 my_lltoa(value, num, 0);
569 bzero(buf, MAXLEN_FIXNUM2*2);
570
571 pbuf = buf;
572 pret = ret;
573 k = 0;
574
575 for ( i = strlen(num) - 1, j = 0 ; i > -1; i--) {
576 if ( k == 2 && i != 0 ) {
577 k = 0;
578 pbuf[j++] = num[i];
579 pbuf[j++] = (UseComma) ? ',' : '.';
580 continue;
581 }
582 pbuf[j] = num[i];
583 j++;
584 k++;
585 }
586
587 pret[0]='\0';
588
589 for ( i = strlen(pbuf) - 1, j = 0 ; i > -1; i--, j++)
590 pret[j] = pbuf[i];
591
592 pret[j] = '\0';
593
594 return pret;
595 }
596
597
598
599 void buildhref(char * href)
600 {
601 char whref[MAXLEN];
602
603 if(strcmp(href,"./") == 0){
604 href[0]='\0';
605 strcat(href,"<a href='");
606 return;
607 }
608
609 href[strlen(href)-1]='\0';
610 sprintf(whref,"%s",strrchr(href,'/'));
611
612 strcpy(href,"<a href='");
613 strcat(href,whref);
614 strcat(href,"/");
615
616 return;
617
618 }
619
620
621 char *buildtime(long long int elap)
622 {
623
624 int num = elap / 1000;
625 int hor = 0;
626 int min = 0;
627 int sec = 0;
628 static char buf[12];
629
630 buf[0]='\0';
631
632 hor=num / 3600;
633 min=(num % 3600) / 60;
634 sec=num % 60;
635 sprintf(buf,"%02d:%02d:%02d",hor,min,sec);
636
637 return(buf);
638
639 }
640
641
642 void obtdate(const char *dirname, const char *name, char *data)
643 {
644
645 FILE *fp_in;
646 char wdir[MAXLEN];
647
648 sprintf(wdir,"%s%s/sarg-date",dirname,name);
649 if ((fp_in = fopen(wdir, "rt")) == 0) {
650 sprintf(wdir,"%s%s/date",dirname,name);
651 if ((fp_in = fopen(wdir, "rt")) == 0) {
652 data[0]='\0';
653 return;
654 }
655 }
656
657 if (!fgets(data,80,fp_in)) {
658 fprintf(stderr,"Failed to read the date in %s\n",wdir);
659 exit(1);
660 }
661 fclose(fp_in);
662 fixendofline(data);
663
664 return;
665
666 }
667
668
669 void formatdate(char *date,int date_size,int year,int month,int day,int hour,int minute,int second,int dst)
670 {
671 struct tm ltm;
672 time_t unixtime;
673 struct tm *fulltm;
674
675 memset(&ltm,0,sizeof(ltm));
676 if (year>=1900) ltm.tm_year=year-1900;
677 if (month>=1 && month<=12) ltm.tm_mon=month-1;
678 if (day>=1 && day<=31) ltm.tm_mday=day;
679 if (hour>=0 && hour<24) ltm.tm_hour=hour;
680 if (minute>=0 && minute<60) ltm.tm_min=minute;
681 if (second>=0 && second<60) ltm.tm_sec=second;
682 ltm.tm_isdst=dst;
683 unixtime=mktime(&ltm); //fill the missing entries
684 fulltm=localtime(&unixtime);
685 //strftime(date,date_size,"%a %b %d %H:%M:%S %Z %Y",fulltm);
686 strftime(date,date_size,"%c",fulltm);
687 }
688
689
690 void obtuser(const char *dirname, const char *name, char *tuser)
691 {
692
693 FILE *fp_in;
694 char wdir[MAXLEN];
695
696 sprintf(wdir,"%s%s/sarg-users",dirname,name);
697 if((fp_in=fopen(wdir,"r"))==NULL) {
698 sprintf(wdir,"%s%s/users",dirname,name);
699 if((fp_in=fopen(wdir,"r"))==NULL) {
700 tuser[0]='\0';
701 return;
702 }
703 }
704
705 if (!fgets(tuser,20,fp_in)) {
706 fprintf(stderr,"Failed to read the user in %s\n",wdir);
707 exit(1);
708 }
709 fclose(fp_in);
710 fixendofline(tuser);
711
712 return;
713
714 }
715
716
717 void obttotal(const char *dirname, const char *name, char *tbytes, const char *tuser, char *media)
718 {
719 FILE *fp_in;
720 char buf[MAXLEN];
721 char wdir[MAXLEN];
722 char warea[MAXLEN];
723 char sep;
724 long long int med=0;
725 long long int wtuser=0;
726 long long int twork=0;
727 struct getwordstruct gwarea;
728
729 twork=0;
730 tbytes[0]='\0';
731 media[0]='\0';
732
733 sprintf(wdir,"%s%s/sarg-general",dirname,name);
734 if ((fp_in = fopen(wdir, "r")) == 0) {
735 sprintf(wdir,"%s%s/general",dirname,name);
736 if ((fp_in = fopen(wdir, "r")) == 0) {
737 return;
738 }
739 }
740
741 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
742 if (strncmp(buf,"TOTAL\t",6) == 0)
743 sep='\t'; //new file
744 else if (strncmp(buf,"TOTAL ",6) == 0)
745 sep=' '; //old file
746 else
747 continue;
748 getword_start(&gwarea,buf);
749 if (getword(warea,sizeof(warea),&gwarea,sep)<0) {
750 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wdir);
751 exit(1);
752 }
753 if(strcmp(warea,"TOTAL") != 0)
754 continue;
755 if (getword_skip(MAXLEN,&gwarea,sep)<0) {
756 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wdir);
757 exit(1);
758 }
759 if (getword_atoll(&twork,&gwarea,sep)<0) {
760 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",wdir);
761 exit(1);
762 }
763 strcpy(tbytes,fixnum(twork,1));
764 break;
765 }
766 fclose(fp_in);
767
768 wtuser=my_atoll(tuser);
769 if(wtuser <= 0) {
770 strcpy(media,"0");
771 return;
772 }
773
774 med=twork / wtuser;
775 strcpy(media,fixnum(med,1));
776
777 return;
778 }
779
780
781 void gperiod(const char *dirname, const char *period)
782 {
783
784 FILE *fp_ou;
785 char wdirname[MAXLEN];
786
787 strcpy(wdirname,dirname);
788 strcat(wdirname,"/sarg-period");
789
790 if((fp_ou=fopen(wdirname,"w"))==NULL){
791 fprintf(stderr, "SARG: (report) %s: %s\n",text[45],wdirname);
792 exit(1);
793 }
794
795 fputs(period,fp_ou);
796 fclose(fp_ou);
797
798 if(debug)
799 debuga("%s",(char *)text[50]);
800
801 return;
802
803 }
804
805 static void copy_images(void)
806 {
807 FILE *img_in, *img_ou;
808 char images[512];
809 char imgdir[MAXLEN];
810 char srcfile[MAXLEN];
811 char dstfile[MAXLEN];
812 DIR *dirp;
813 struct dirent *direntp;
814 char buffer[MAXLEN];
815 size_t nread;
816 struct stat info;
817
818 if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) {
819 fprintf(stderr,"SARG: Cannot copy images to target directory %simages\n",outdir);
820 exit(1);
821 }
822 if (access(images,R_OK)!=0) {
823 mkdir(images,0755);
824 }
825
826 strcpy(imgdir,IMAGEDIR);
827 dirp = opendir(imgdir);
828 if(dirp==NULL) {
829 fprintf(stderr, "SARG: (util) %s %s: %s\n","Can't open directory", imgdir,strerror(errno));
830 return;
831 }
832 while ((direntp = readdir( dirp )) != NULL ){
833 if(direntp->d_name[0]=='.')
834 continue;
835 sprintf(srcfile,"%s/%s",imgdir,direntp->d_name);
836 if (stat(srcfile,&info)) {
837 fprintf(stderr,"SARG: Cannot stat \"%s\" - %s\n",srcfile,strerror(errno));
838 continue;
839 }
840 if (S_ISREG(info.st_mode)) {
841 sprintf(dstfile,"%s/%s",images,direntp->d_name);
842 img_in = fopen(srcfile, "rb");
843 if(img_in!=NULL) {
844 img_ou = fopen(dstfile, "wb");
845 if(img_ou!=NULL) {
846 while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) {
847 if (fwrite(buffer,1,nread,img_ou)!=nread) {
848 fprintf(stderr,"SARG: Failed to copy image %s to %s\n",srcfile,dstfile);
849 break;
850 }
851 }
852 fclose(img_ou);
853 } else
854 fprintf(stderr,"SARG: (util): %s %s: %s\n", text[45]?text[45]:"Can't open/create file", dstfile, strerror(errno));
855 fclose(img_in);
856 } else
857 fprintf(stderr,"SARG: (util): %s %s: %s\n", text[45]?text[45]:"Can't open file", srcfile, strerror(errno));
858 }
859 }
860 (void) closedir(dirp);
861
862 return;
863 }
864
865 void vrfydir(const char *per1, const char *addr, const char *site, const char *us, const char *form)
866 {
867 FILE *fp_ou;
868 int num=1, count=0;
869 char wdir[MAXLEN];
870 char per2[MAXLEN];
871 char dirname2[MAXLEN];
872 char y1[5], y2[5];
873 char d1[3], d2[3];
874 char m1[8], m2[8];
875 time_t curtime;
876 struct tm *loctm;
877
878 if(IndexTree == INDEX_TREE_DATE) {
879 bzero(y1,sizeof(y1));
880 bzero(y2,sizeof(y2));
881 bzero(d1,sizeof(d1));
882 bzero(d2,sizeof(d2));
883 bzero(m1,sizeof(m1));
884 bzero(m2,sizeof(m2));
885 if(strncmp(df,"u",1) == 0) {
886 strncpy(y1,period,4);
887 strncpy(y2,period+10,4);
888 strncpy(m1,period+4,3);
889 strncpy(m2,period+14,3);
890 strncpy(d1,period+7,2);
891 strncpy(d2,period+17,2);
892 } else if(strncmp(df,"e",1) == 0) {
893 strncpy(d1,period+0,2);
894 strncpy(d2,period+10,2);
895 strncpy(m1,period+2,3);
896 strncpy(m2,period+12,3);
897 strncpy(y1,period+5,4);
898 strncpy(y2,period+15,4);
899 }
900 conv_month(m1);
901 conv_month(m2);
902
903 sprintf(wdir,"%s%s",outdir,y1);
904 if(strcmp(y1,y2) != 0) {
905 strcat(wdir,"-");
906 strcat(wdir,y2);
907 }
908 if(access(wdir, R_OK) != 0)
909 my_mkdir(wdir);
910
911 strcat(wdir,"/");
912 strcat(wdir,m1);
913 if(strcmp(m1,m2) != 0) {
914 strcat(wdir,"-");
915 strcat(wdir,m2);
916 }
917 if(access(wdir, R_OK) != 0)
918 my_mkdir(wdir);
919
920 strcat(wdir,"/");
921 strcat(wdir,d1);
922 if(strcmp(d1,d2) != 0) {
923 strcat(wdir,"-");
924 strcat(wdir,d2);
925 }
926 } else {
927 sprintf(wdir, "%s%s", outdir, per1);
928 }
929
930 if(us[0] != '\0') {
931 strcat(wdir,"-");
932 strcat(wdir,us);
933 }
934 if(addr[0] != '\0') {
935 strcat(wdir,"-");
936 strcat(wdir,addr);
937 }
938 if(site[0] != '\0') {
939 strcat(wdir,"-");
940 strcat(wdir,site);
941 }
942
943 strcpy(dirname,wdir);
944
945 if(IndexTree != INDEX_TREE_DATE) {
946 if(!OverwriteReport) {
947 while(num) {
948 if(access(wdir,R_OK) == 0) {
949 sprintf(wdir,"%s.%d",dirname,num);
950 sprintf(per2,"%s.%d",per1,num);
951 num++;
952 count++;
953 } else
954 break;
955 }
956
957 if(count > 0) {
958 if(debug)
959 fprintf(stderr, "SARG: %s: %s %s %s\n",text[51],dirname,text[52],wdir);
960 rename(dirname,wdir);
961 }
962 } else {
963 if(access(dirname,R_OK) == 0) {
964 unlinkdir(dirname,1);
965 }
966 }
967 my_mkdir(dirname);
968 } else {
969 strcpy(dirname2,wdir);
970 if(!OverwriteReport) {
971 while(num) {
972 if(access(wdir,R_OK) == 0) {
973 sprintf(wdir,"%s.%d",dirname2,num);
974 sprintf(per2,"%s.%d",per1,num);
975 num++;
976 count++;
977 } else
978 break;
979 }
980
981 if(count > 0) {
982 if(debug)
983 fprintf(stderr, "SARG: %s: %s %s %s\n",text[51],dirname2,text[52],wdir);
984 rename(dirname2,wdir);
985 strcpy(dirname2,wdir);
986 }
987 } else {
988 if(access(wdir,R_OK) == 0) {
989 unlinkdir(wdir,1);
990 }
991 }
992
993 if(access(wdir, R_OK) != 0)
994 my_mkdir(wdir);
995 }
996
997 strcpy(dirname2,wdir);
998
999 sprintf(wdir,"%s/sarg-date",dirname);
1000 if ((fp_ou = fopen(wdir, "wt")) == 0) {
1001 fprintf(stderr, "SARG: cannot open %s for writing\n",wdir);
1002 perror("SARG:");
1003 exit(1);
1004 }
1005 time(&curtime);
1006 //strftime(wdir,sizeof(wdir),"%a %b %d %H:%M:%S %Z %Y",localtime(&curtime));
1007 loctm=localtime(&curtime);
1008 strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm);
1009 fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst);
1010 fclose(fp_ou);
1011
1012 copy_images();
1013 }
1014
1015 void strip_latin(char *line)
1016 {
1017 int i,j;
1018 int skip;
1019
1020 j=0;
1021 skip=0;
1022 for (i=0;line[i];i++){
1023 if (skip){
1024 if (line[i]==';') skip=0;
1025 } else {
1026 if (line[i]=='&')
1027 skip=1;
1028 else
1029 line[j++]=line[i];
1030 }
1031 }
1032 line[j]='\0';
1033 return;
1034
1035 }
1036
1037 void zdate(char *ftime,int ftimesize, const char *DateFormat)
1038 {
1039
1040 time_t t;
1041 struct tm *local;
1042
1043 t = time(NULL);
1044 local = localtime(&t);
1045 if(strcmp(DateFormat,"u") == 0)
1046 strftime(ftime, ftimesize, "%b/%d/%Y %H:%M", local);
1047 if(strcmp(DateFormat,"e") == 0)
1048 strftime(ftime, ftimesize, "%d/%b/%Y-%H:%M", local);
1049 if(strcmp(DateFormat,"w") == 0)
1050 strftime(ftime, ftimesize, "%V-%H-%M", local);
1051 return;
1052 }
1053
1054
1055 char *fixtime(long int elap)
1056 {
1057
1058 int num = elap / 1000;
1059 int hor = 0;
1060 int min = 0;
1061 int sec = 0;
1062 static char buf[12];
1063
1064 if(strcmp(datetimeby,"bytes") == 0) {
1065 strcpy(buf,fixnum(elap,1));
1066 return buf;
1067 }
1068
1069 if(num<1) {
1070 sprintf(buf,"00:00:%02ld",elap);
1071 return buf;
1072 }
1073
1074 hor=num / 3600;
1075 min=(num % 3600) / 60;
1076 sec=num % 60;
1077
1078 if(hor==0 && min==0 && sec==0)
1079 strcpy(buf,"0");
1080 else
1081 sprintf(buf,"%01d:%02d:%02d",hor,min,sec);
1082
1083 return buf;
1084
1085 }
1086
1087
1088 void date_from(char *date, char *dfrom, char *duntil)
1089 {
1090
1091 int diaf;
1092 int mesf;
1093 int anof;
1094 int diau;
1095 int mesu;
1096 int anou;
1097 char wdate[50];
1098
1099 strncpy(wdate,date,sizeof(wdate)-1);
1100 wdate[sizeof(wdate)-1]='\0';
1101 if(strchr(wdate,'-') == NULL) {
1102 if (strlen(wdate)*2+1>=sizeof(wdate)) {
1103 fprintf(stderr,"SARG: Invalid date range passed as argument.\n");
1104 exit(1);
1105 }
1106 strcat(wdate,"-");
1107 strcat(wdate,date);
1108 strcpy(date,wdate);
1109 }
1110
1111 if (sscanf(wdate,"%d/%d/%d-%d/%d/%d",&diaf,&mesf,&anof,&diau,&mesu,&anou)!=6) {
1112 fprintf(stderr,"SARG: The date range passed as argument is not formated as dd/mm/yyyy-dd/mm/yyyy.\n");
1113 exit(1);
1114 }
1115
1116 sprintf(dfrom,"%04d%02d%02d",anof,mesf,diaf);
1117 sprintf(duntil,"%04d%02d%02d",anou,mesu,diau);
1118 return;
1119 }
1120
1121
1122 char *strlow(char *string)
1123 {
1124 char *s;
1125
1126 if (string)
1127 {
1128 for (s = string; *s; ++s)
1129 *s = tolower(*s);
1130 }
1131
1132 return string;
1133 }
1134
1135
1136
1137
1138 char *strup(char *string)
1139 {
1140 char *s;
1141
1142 if (string)
1143 {
1144 for (s = string; *s; ++s)
1145 *s = toupper(*s);
1146 }
1147
1148 return string;
1149 }
1150
1151
1152 void subs(char *str, int size, char *from, char *to)
1153 {
1154 char *tmp;
1155 int i;
1156 int ss, st, sf;
1157 int len;
1158 int shift;
1159
1160 tmp = strstr(str, from);
1161 if(tmp == NULL)
1162 return;
1163
1164 ss = strlen(str);
1165 sf = strlen(from);
1166 st = strlen(to);
1167 shift=st-sf;
1168
1169 if (shift>0) {
1170 if (ss+shift>=size){
1171 fprintf(stderr,"SARG: Cannot replace %s by %s in %s and fit within %d bytes\n",from,to,str,size);
1172 exit(1);
1173 }
1174 for (i=strlen(tmp) ; i>=sf ; i--)
1175 tmp[i+shift]=tmp[i];
1176 } else if (shift<0) {
1177 len=strlen(tmp);
1178 for (i=sf ; i<=len ; i++)
1179 tmp[i+shift]=tmp[i];
1180 }
1181 memcpy(tmp, to, st);
1182 return;
1183 }
1184
1185
1186 void removetmp(const char *outdir)
1187 {
1188
1189 FILE *fp_in;
1190 char warea[256];
1191
1192 if(!RemoveTempFiles)
1193 return;
1194
1195 if(debug) {
1196 debuga("%s: sarg-general, sarg-period",text[82]);
1197 }
1198 if (snprintf(warea,sizeof(warea),"%s/sarg-general",outdir)>=sizeof(warea)) {
1199 fprintf(stderr, "SARG: (removetmp) directory too long to remove: %s/sarg-period\n",outdir);
1200 exit(1);
1201 }
1202 if((fp_in=fopen(warea,"r"))==NULL){
1203 fprintf(stderr, "===SARG: (removetmp) %s: %s\n",text[45],warea);
1204 exit(1);
1205 }
1206 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
1207 if(strncmp(buf,"TOTAL",5) == 0)
1208 break;
1209 }
1210 fclose(fp_in);
1211 if((fp_in=fopen(warea,"w"))==NULL){
1212 fprintf(stderr, "SARG: (removetmp) %s: %s\n",text[45],warea);
1213 exit(1);
1214 }
1215 fputs(buf,fp_in);
1216 fclose(fp_in);
1217 if (snprintf(warea,sizeof(warea),"%s/sarg-period",outdir)>=sizeof(warea)) {
1218 fprintf(stderr, "SARG: (removetmp) directory too long to remove: %s/sarg-period\n",outdir);
1219 exit(1);
1220 }
1221 unlink(warea);
1222
1223 return;
1224 }
1225
1226 void load_excludecodes(const char *ExcludeCodes)
1227 {
1228
1229 FILE *fp_in;
1230 char data[80];
1231 int i;
1232
1233 if(ExcludeCodes[0] == '\0')
1234 return;
1235
1236 if((excludecode=(char *) malloc(1024))==NULL) {
1237 fprintf(stderr, "SARG: %s (1024):\n",text[59]);
1238 exit(1);
1239 }
1240 bzero(excludecode,1024);
1241
1242 if((fp_in=fopen(ExcludeCodes,"r"))==NULL) {
1243 fprintf(stderr, "SARG: (util) Cannot open file: %s (exclude_codes)\n",ExcludeCodes);
1244 exit(1);
1245 }
1246
1247 while(fgets(data,sizeof(data),fp_in)!=NULL) {
1248 for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]=0;
1249 if (i<0) continue;
1250 strcat(excludecode,data);
1251 strcat(excludecode,";");
1252 }
1253
1254 fclose(fp_in);
1255 return;
1256
1257 }
1258
1259 void free_excludecodes(void)
1260 {
1261 if (excludecode) {
1262 free(excludecode);
1263 excludecode=NULL;
1264 }
1265 }
1266
1267 int vercode(const char *code)
1268 {
1269 char *cod;
1270 int clen;
1271
1272 if (excludecode && excludecode[0]!=0) {
1273 clen=strlen(code);
1274 for (cod=excludecode ; cod ; cod=strchr(cod+1,';')) {
1275 if (strncmp(code,cod,clen)==0 && cod[clen]==';')
1276 return 1;
1277 }
1278 }
1279 return 0;
1280 }
1281
1282 void fixnone(char *str)
1283 {
1284 int i;
1285
1286 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--);
1287 if(i==3 && strncmp(str,"none",4) == 0)
1288 str[0]='\0';
1289
1290 return;
1291 }
1292
1293 void fixendofline(char *str)
1294 {
1295 int i;
1296
1297 for (i=strlen(str)-1 ; i>=0 && (unsigned char)str[i]<=' ' ; i--) str[i]=0;
1298 }
1299
1300 #ifdef LEGACY_TESTVALIDUSERCHAR
1301 int testvaliduserchar(const char *user)
1302 {
1303
1304 int x=0;
1305 int y=0;
1306
1307 for (y=0; y<strlen(UserInvalidChar); y++) {
1308 for (x=0; x<strlen(user); x++) {
1309 if(user[x] == UserInvalidChar[y])
1310 return 1;
1311 }
1312 }
1313 return 0;
1314 }
1315 #else
1316 int testvaliduserchar(const char *user)
1317 {
1318
1319 char * p_UserInvalidChar = UserInvalidChar ;
1320 const char * p_user ;
1321
1322 while( *p_UserInvalidChar ) {
1323 p_user = user ;
1324 while ( *p_user ) {
1325 if( *p_UserInvalidChar == *p_user )
1326 return 1;
1327 p_user++ ;
1328 }
1329 p_UserInvalidChar++ ;
1330 }
1331 return 0;
1332 }
1333 #endif
1334
1335 int compar( const void *a, const void *b )
1336 { if( *(int *)a > *(int *)b ) return 1;
1337 if( *(int *)a < *(int *)b ) return -1;
1338 return 0;
1339 }
1340
1341 int getnumlist( char *buf, numlist *list, const int len, const int maxvalue )
1342 {
1343 int i, j, d, flag, r1, r2;
1344 char *pbuf, **bp, *strbufs[ 24 ];
1345
1346 bp = strbufs;
1347 strtok( buf, " \t" );
1348 for( *bp = strtok( NULL, "," ), list->len = 0; *bp; *bp = strtok( NULL, "," ) ) {
1349 if( ++bp >= &strbufs[ 24 ] )
1350 break;
1351 list->len++;
1352 }
1353 if( ! list->len )
1354 return -1;
1355 d = 0;
1356 for( i = 0; i < list->len; i++ ) {
1357 if( strchr( strbufs[ i ], '-' ) != 0 ) {
1358 pbuf = strbufs[ i ];
1359 strtok( pbuf, "-" );
1360 pbuf = strtok( NULL, "\0" );
1361 r1 = atoi( strbufs[ i ] );
1362 if( ( r2 = atoi( pbuf ) ) >= maxvalue || r1 >= r2 )
1363 return -1;
1364 if( i + d + ( r2 - r1 ) + 1 <= len ) {
1365 for( j = r1; j <= r2; j++ )
1366 list->list[ i + d++ ] = j;
1367 d--;
1368 }
1369 }
1370 else
1371 if( ( list->list[ i + d ] = atoi( strbufs[ i ] ) ) >= maxvalue )
1372 return 1;
1373 }
1374 list->len += d;
1375 qsort( list->list, list->len, sizeof( int ), compar );
1376 do {
1377 flag = 0;
1378 for( i = 0; i < list->len - 1; i++ )
1379 if( list->list[ i ] == list->list[ i + 1 ] ) {
1380 for( j = i + 1; j < list->len; j++ )
1381 list->list[ j - 1 ] = list->list[ j ];
1382 list->len--;
1383 flag = 1;
1384 break;
1385 }
1386 } while( flag );
1387 return 0;
1388 }
1389
1390
1391 char *get_size(const char *path, const char *file)
1392 {
1393 FILE *fp;
1394 static char response[255];
1395 char cmd[255];
1396 char *ptr;
1397
1398 if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) {
1399 printf("SARG: Cannot get disk space because the path %s%s is too long.\n",path,file);
1400 exit(1);
1401 }
1402 fp = popen(cmd, "r");
1403 if (!fgets(response, sizeof(response), fp)) {
1404 fprintf(stderr,"SARG: Cannot get disk size with command %s",cmd);
1405 exit(1);
1406 }
1407 ptr=strchr(response,'\t');
1408 if (ptr==NULL) {
1409 fprintf(stderr,"SARG: The command %s failed.\n",cmd);
1410 exit(1);
1411 }
1412 pclose(fp);
1413 *ptr='\0';
1414
1415 return (response);
1416 }
1417
1418 void show_info(FILE *fp_ou)
1419 {
1420 char ftime[127];
1421
1422 if(!ShowSargInfo) return;
1423 zdate(ftime, sizeof(ftime), DateFormat);
1424 fprintf(fp_ou,"<div align=\"center\"><table><tr><td><br><br></td><td class=\"info\">%s <a href='%s'><font class=\"info\">%s-%s</font></a> %s %s</td></tr></table></div>\n",text[108],URL,PGM,VERSION,text[109],ftime);
1425 }
1426
1427 void show_sarg(FILE *fp_ou, const char *ind)
1428 {
1429 if(ShowSargLogo) fprintf(fp_ou,"<div align=\"center\"><table class=\"logo\">\n<tr><th><a href=\"http://sarg.sourceforge.net\"><img src=\"%s/images/sarg.png\" title=\"SARG, Squid Analysis Report Generator. Logo by Osamu Matsuzaki\" alt=\"Sarg\"></a>&nbsp;Squid Analysis Report Generator</th></tr>\n<tr><th class=\"title\">&nbsp</th></tr>\n</table></div>\n",ind);
1430 }
1431
1432 void write_logo_image(FILE *fp_ou)
1433 {
1434 if(LogoImage[0]!='\0')
1435 fprintf(fp_ou, "<div align=\"center\"><table class=\"logo\">\n<tr><th><img src=\"%s\" width=\"%s\" height=\"%s\" alt=\"Logo\">&nbsp;%s</th></tr>\n<tr><td height=\"5\"></td></tr>\n</table>\n</div>\n",LogoImage,Width,Height,LogoText);
1436 }
1437
1438 void write_html_header(FILE *fp_ou, const char * ind)
1439 {
1440 fprintf(fp_ou, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
1441 css(fp_ou);
1442 fprintf(fp_ou,"</head>\n<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
1443 write_logo_image(fp_ou);
1444 show_sarg(fp_ou, ind);
1445 fprintf(fp_ou,"<div align=\"center\"><table cellpadding=\"0\" cellspacing=\"0\">\n<tr><th class=\"title\">%s</th></tr>\n</table></div>\n<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",Title);
1446 }
1447
1448 void output_html_string(FILE *fp_ou,const char *str)
1449 {
1450
1451 while (*str) {
1452 switch (*str) {
1453 case '&':
1454 fputs("&amp;",fp_ou);
1455 break;
1456 case '<':
1457 fputs("&lt;",fp_ou);
1458 break;
1459 case '>':
1460 fputs("&gt;",fp_ou);
1461 break;
1462 case '"':
1463 fputs("&quot;",fp_ou);
1464 break;
1465 case '\'':
1466 fputs("&#39;",fp_ou);
1467 break;
1468 default:
1469 fputc(*str,fp_ou);
1470 }
1471 str++;
1472 }
1473 }
1474
1475 void baddata(void)
1476 {
1477 char dir[1024];
1478
1479 printf("SARG: ------------------------------------------------------------------------------\n");
1480 printf("SARG: MALICIUS CODE DETECTED.\n");
1481 printf("SARG: I think someone is trying to execute arbitrary code in your system using sarg.\n");
1482 printf("SARG: please review your access.log and/or your useragent.log file.\n");
1483 printf("SARG: process stoped. No actions taken.\n");
1484 printf("SARG: ------------------------------------------------------------------------------\n");
1485
1486 if (snprintf(dir,sizeof(dir),"%s/sarg",tmp)>=sizeof(dir)) {
1487 fprintf(stderr,"SARG: temporary directory too long: %s/sarg\n",tmp);
1488 exit(1);
1489 }
1490 unlinkdir(dir,0);
1491 unlinkdir(dirname,0);
1492
1493 exit(1);
1494 }
1495
1496
1497 void url_module(const char *url, char *w2)
1498 {
1499 int x, y;
1500 char w[255];
1501
1502 y=0;
1503 for(x=strlen(url)-1; x>=0; x--) {
1504 if(url[x] == '/' || y>=sizeof(w)-1) break;
1505 w[y++]=url[x];
1506 }
1507 if (x<0) {
1508 w2[0]='\0';
1509 return;
1510 }
1511
1512 x=0;
1513 for(y=y-1; y>=0; y--) {
1514 w2[x++]=w[y];
1515 }
1516 w2[x]='\0';
1517 }
1518
1519
1520 void write_html_trailer(FILE *fp_ou)
1521 {
1522 char ftime[128];
1523
1524 fputs("</table></div>\n",fp_ou);
1525 zdate(ftime, sizeof(ftime), DateFormat);
1526 show_info(fp_ou);
1527 fputs("</body>\n</html>\n",fp_ou);
1528 }
1529
1530 void version(void)
1531 {
1532 printf("SARG Version: %s\n",VERSION);
1533 exit(0);
1534 }
1535
1536 char *get_param_value(const char *param,char *line)
1537 {
1538 int plen;
1539
1540 while (*line==' ' || *line=='\t') line++;
1541 plen=strlen(param);
1542 if (strncasecmp(line,param,plen)) return(NULL);
1543 if (line[plen]!=' ' && line[plen]!='\t') return(NULL);
1544 line+=plen;
1545 while (*line==' ' || *line=='\t') line++;
1546 return(line);
1547 }
1548
1549 void unlinkdir(const char *dir,int contentonly)
1550 {
1551 struct stat st;
1552 DIR *dirp;
1553 struct dirent *direntp;
1554 char dname[MAXLEN];
1555 int err;
1556
1557 dirp=opendir(dir);
1558 if (!dirp) return;
1559 while ((direntp = readdir(dirp)) != NULL) {
1560 if (direntp->d_name[0] == '.' && (direntp->d_name[1] == '\0' ||
1561 (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0')))
1562 continue;
1563 if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) {
1564 fprintf(stderr,"SARG: directory name to delete too long: %s/%s\n",dir,direntp->d_name);
1565 exit(1);
1566 }
1567 #ifdef HAVE_LSTAT
1568 err=lstat(dname,&st);
1569 #else
1570 err=stat(dname,&st);
1571 #endif
1572 if (err) {
1573 fprintf(stderr,"SARG: cannot stat %s\n",dname);
1574 exit(1);
1575 }
1576 if (S_ISREG(st.st_mode)) {
1577 if (unlink(dname)) {
1578 fprintf(stderr,"SARG: cannot delete %s - %s\n",dname,strerror(errno));
1579 exit(1);
1580 }
1581 } else if (S_ISDIR(st.st_mode)) {
1582 unlinkdir(dname,0);
1583 } else {
1584 fprintf(stderr,"SARG: unknown path type %s\n",dname);
1585 }
1586 }
1587 closedir(dirp);
1588
1589 if (!contentonly) {
1590 if (rmdir(dir)) {
1591 fprintf(stderr,"SARG: cannot delete %s - %s\n",dir,strerror(errno));
1592 exit(1);
1593 }
1594 }
1595 }