1 /*
2     webalizer - a web server log analysis program
3 
4     Copyright (C) 1997-2013  Bradford L. Barrett
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version, and provided that the above
10     copyright and permission notice is included with all distributed
11     copies of this or derived software.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 
22 */
23 
24 /*********************************************/
25 /* STANDARD INCLUDES                         */
26 /*********************************************/
27 
28 #include <time.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>                           /* normal stuff             */
33 #include <ctype.h>
34 #include <errno.h>
35 #include <sys/stat.h>
36 #include <sys/utsname.h>
37 
38 /* ensure sys/types */
39 #ifndef _SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
42 
43 /* need socket header? */
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>
46 #endif
47 
48 /* some systems need this */
49 #ifdef HAVE_MATH_H
50 #include <math.h>
51 #endif
52 
53 #include "webalizer.h"                        /* main header              */
54 #include "lang.h"
55 #include "hashtab.h"
56 #include "parser.h"
57 #include "preserve.h"
58 
59 struct hist_rec hist[HISTSIZE];              /* history structure array   */
60 
61 /*********************************************/
62 /* GET_HISTORY - load in history file        */
63 /*********************************************/
64 
get_history()65 void get_history()
66 {
67    int   i,n,numfields;
68    int   in_m,in_y;
69    int   mth, yr;
70    FILE  *hist_fp;
71    char  buffer[BUFSIZE];
72 
73    /* try to open history file */
74    hist_fp=fopen(hist_fname,"r");
75 
76    if (hist_fp)
77    {
78       if (verbose>1) printf("%s %s\n",msg_get_hist,hist_fname);
79       while ( fgets(buffer,BUFSIZE,hist_fp) != NULL )
80       {
81          if (buffer[0]=='#') { continue; } /* skip comments */
82 
83          /* get record month/year */
84          sscanf(buffer,"%d %d",&in_m,&in_y);
85 
86          /* check if valid numbers */
87          if ( (in_m<1 || in_m>12 || in_y<1970) )
88          {
89             if (verbose) fprintf(stderr,"%s (mth=%d)\n",msg_bad_hist,in_m);
90             continue;
91          }
92 
93          /* populate if first time through */
94          if (hist[HISTSIZE-1].year==0) populate_history(in_m, in_y);
95 
96          for (i=HISTSIZE-1;i>=0;i--)
97          {
98             if (in_m==hist[i].month && in_y==hist[i].year) break;
99             else
100             {
101                if ( (in_m>hist[i].month&&in_y==hist[i].year) ||
102                     (in_y>hist[i].year) )
103                {
104                   if (i>0)
105                   {
106                      n=(mth_idx(in_m,in_y)-mth_idx(hist[i].month,hist[i].year));
107                      while (n)
108                      {
109                         yr = hist[i].year;
110                         mth= hist[i].month+1;
111                         if (mth>12) { mth=1; yr++; }
112                         memcpy(&hist[0], &hist[1], sizeof(hist[0])*i);
113                         memset(&hist[i], 0, sizeof(struct hist_rec));
114                         hist[i].year=yr; hist[i].month=mth; n--;
115                     }
116                   }
117                   break;
118                }
119             }
120          }
121          if (i>=0)
122          {
123          /* month# year# requests files sites xfer firstday lastday */
124          numfields = sscanf(buffer,"%d %d %llu %llu %llu %lf %d %d %llu %llu",
125                        &hist[i].month,
126                        &hist[i].year,
127                        &hist[i].hit,
128                        &hist[i].files,
129                        &hist[i].site,
130                        &hist[i].xfer,
131                        &hist[i].fday,
132                        &hist[i].lday,
133                        &hist[i].page,
134                        &hist[i].visit);
135          }
136       }
137       fclose(hist_fp);
138    }
139    else if (verbose>1) printf("%s\n",msg_no_hist);
140 }
141 
142 /*********************************************/
143 /* PUT_HISTORY - write out history file      */
144 /*********************************************/
145 
put_history()146 void put_history()
147 {
148    int     i;
149    FILE    *hist_fp;
150    char    new_fname[MAXKVAL+4];
151    char    old_fname[MAXKVAL+4];
152    struct  stat hist_stat;
153    time_t  now;
154    char    timestamp[48];
155 
156    /* generate 'new' filename */
157    sprintf(new_fname, "%s.new", hist_fname);
158 
159    /* stat the file */
160    if ( !(lstat(new_fname, &hist_stat)) )
161    {
162       /* check if the file a symlink */
163       if ( S_ISLNK(hist_stat.st_mode) )
164       {
165          if (verbose)
166          fprintf(stderr,"%s %s (symlink)\n",msg_no_open,new_fname);
167          return;
168       }
169    }
170 
171    /* Generate our timestamp */
172    now=time(NULL);
173    strftime(timestamp,sizeof(timestamp),"%d/%b/%Y %H:%M:%S",localtime(&now));
174 
175    /* Open file for writing */
176    hist_fp = fopen(new_fname,"w");
177    if (hist_fp)
178    {
179       if (verbose>1) printf("%s\n",msg_put_hist);
180 
181       /* write header */
182       fprintf(hist_fp,"# Webalizer V%s-%s History Data - %s (%d month)\n",
183               version, editlvl, timestamp, HISTSIZE);
184 
185       for (i=HISTSIZE-1;i>=0;i--)
186       {
187          fprintf(hist_fp,"%d %d %llu %llu %llu %.0f %d %d %llu %llu\n",
188                          hist[i].month,
189                          hist[i].year,
190                          hist[i].hit,
191                          hist[i].files,
192                          hist[i].site,
193                          hist[i].xfer,
194                          hist[i].fday,
195                          hist[i].lday,
196                          hist[i].page,
197                          hist[i].visit);
198       }
199       /* Done, close file */
200       fclose(hist_fp);
201 
202       /* if time-warp error detected, save old */
203       if (hist_gap)
204       {
205          sprintf(old_fname, "%s.sav", hist_fname);
206          if ((rename(hist_fname,old_fname)==-1)&&(errno!=ENOENT)&&verbose)
207             fprintf(stderr,"Failed renaming %s to %s: %s\n",
208                hist_fname,old_fname,strerror(errno));
209       }
210 
211       /* now rename the 'new' file to real name */
212       if ((rename(new_fname,hist_fname) == -1) && verbose)
213          fprintf(stderr,"Failed renaming %s to %s\n",new_fname,hist_fname);
214    }
215    else
216       if (verbose)
217       fprintf(stderr,"%s %s\n",msg_hist_err,new_fname);
218 }
219 
220 /*********************************************/
221 /* POPULATE_HISTORY - populate with dates    */
222 /*********************************************/
223 
populate_history(int month,int year)224 void populate_history(int month, int year)
225 {
226    int   i;
227    int   mth=month;
228    int   yr =year;
229 
230    if (hist[HISTSIZE-1].year==0)
231    {
232       for (i=HISTSIZE-1;i>=0;i--)
233       {
234          hist[i].year=yr; hist[i].month=mth--;
235          if (mth==0) { yr--; mth=12; }
236       }
237    }
238 }
239 
240 /*********************************************/
241 /* UPDATE_HISTORY - update with cur totals   */
242 /*********************************************/
243 
update_history()244 void update_history()
245 {
246    int   i,n;
247    int   mth,yr;
248 
249    /* populate if first time through */
250    if (hist[HISTSIZE-1].year==0) populate_history(cur_month,cur_year);
251 
252    /* we need to figure out where to put in history */
253    for (i=HISTSIZE-1;i>=0;i--)
254    {
255       if (cur_month==hist[i].month && cur_year==hist[i].year) break;
256       else
257       {
258          if ((cur_month>hist[i].month&&cur_year==hist[i].year) ||
259              (cur_year>hist[i].year))
260          {
261             if (i>0)
262             {
263                n=(mth_idx(cur_month,cur_year) -
264                   mth_idx(hist[i].month,hist[i].year));
265 
266                if (n>2)
267                {
268                   if (verbose)
269                      fprintf(stderr,"Warning! %d month gap detected! "   \
270                              "(%d/%d to %d/%d)\n", n, hist[i].month,
271                              hist[i].year, cur_month, cur_year);
272                   if (n>11) hist_gap=1;  /* year or more? */
273                }
274 
275                while (n)
276                {
277                   yr = hist[i].year;
278                   mth= hist[i].month+1;
279                   if (mth>12) { mth=1; yr++; }
280                   memcpy(&hist[0],&hist[1],sizeof(hist[0])*i);
281                   memset(&hist[i], 0, sizeof(struct hist_rec));
282                   hist[i].year=yr; hist[i].month=mth; n--;
283                }
284             }
285             break;
286          }
287       }
288    }
289    if (i>=0)
290    {
291       hist[i].month = cur_month;
292       hist[i].year  = cur_year;
293       hist[i].hit   = t_hit;
294       hist[i].files = t_file;
295       hist[i].page  = t_page;
296       hist[i].visit = t_visit;
297       hist[i].site  = t_site;
298       hist[i].xfer  = t_xfer/1024;
299       hist[i].fday  = f_day;
300       hist[i].lday  = l_day;
301    }
302 }
303 
304 /*********************************************/
305 /* SAVE_STATE - save internal data structs   */
306 /*********************************************/
307 
save_state()308 int save_state()
309 {
310    HNODEPTR hptr;
311    UNODEPTR uptr;
312    RNODEPTR rptr;
313    ANODEPTR aptr;
314    SNODEPTR sptr;
315    INODEPTR iptr;
316 
317    FILE *fp;
318    int  i;
319    struct stat state_stat;
320 
321    char buffer[BUFSIZE];
322    char new_fname[MAXKVAL+4];
323 
324    /* generate 'new' filename */
325    sprintf(new_fname, "%s.new", state_fname);
326 
327    /* stat the file */
328    if ( !(lstat(new_fname, &state_stat)) )
329    {
330       /* check if the file a symlink */
331       if ( S_ISLNK(state_stat.st_mode) )
332       {
333          if (verbose)
334          fprintf(stderr,"%s %s (symlink)\n",msg_no_open,new_fname);
335          return(EBADF);
336       }
337    }
338 
339    /* Open file for writing */
340    fp=fopen(new_fname,"w");
341    if (fp==NULL) return 1;
342 
343    /* Saving current run data... */
344    if (verbose>1)
345    {
346       sprintf(buffer,"%02d/%02d/%04d %02d:%02d:%02d",
347        cur_month,cur_day,cur_year,cur_hour,cur_min,cur_sec);
348       printf("%s [%s]\n",msg_put_data,buffer);
349    }
350 
351    /* first, save the easy stuff */
352    /* Header record */
353    snprintf(buffer,sizeof(buffer),
354      "# Webalizer V%s-%s Incremental Data - %02d/%02d/%04d %02d:%02d:%02d\n",
355       version,editlvl,cur_month,cur_day,cur_year,cur_hour,cur_min,cur_sec);
356    if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
357 
358    /* Current date/time          */
359    sprintf(buffer,"%d %d %d %d %d %d\n",
360         cur_year, cur_month, cur_day, cur_hour, cur_min, cur_sec);
361    if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
362 
363    /* Monthly totals for sites, urls, etc... */
364    sprintf(buffer,"%llu %llu %llu %llu %llu %llu %.0f %llu %llu %llu\n",
365         t_hit, t_file, t_site, t_url,
366         t_ref, t_agent, t_xfer, t_page, t_visit, t_user);
367    if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
368 
369    /* Daily totals for sites, urls, etc... */
370    sprintf(buffer,"%llu %llu %llu %d %d\n",
371         dt_site, ht_hit, mh_hit, f_day, l_day);
372    if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
373 
374    /* Monthly (by day) total array */
375    for (i=0;i<31;i++)
376    {
377       sprintf(buffer,"%llu %llu %.0f %llu %llu %llu\n",
378         tm_hit[i],tm_file[i],tm_xfer[i],tm_site[i],tm_page[i],tm_visit[i]);
379       if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
380    }
381 
382    /* Daily (by hour) total array */
383    for (i=0;i<24;i++)
384    {
385       sprintf(buffer,"%llu %llu %.0f %llu\n",
386         th_hit[i],th_file[i],th_xfer[i],th_page[i]);
387       if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
388    }
389 
390    /* Response codes */
391    for (i=0;i<TOTAL_RC;i++)
392    {
393       sprintf(buffer,"%llu\n",response[i].count);
394       if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
395    }
396 
397    /* now we need to save our linked lists */
398    /* URL list */
399    if (fputs("# -urls- \n",fp)==EOF) return 1;  /* error exit */
400    for (i=0;i<MAXHASH;i++)
401    {
402       uptr=um_htab[i];
403       while (uptr!=NULL)
404       {
405          snprintf(buffer,sizeof(buffer),"%s\n%d %llu %llu %.0f %llu %llu\n",
406                   uptr->string, uptr->flag, uptr->count, uptr->files,
407                   uptr->xfer, uptr->entry, uptr->exit);
408          if (fputs(buffer,fp)==EOF) return 1;
409          uptr=uptr->next;
410       }
411    }
412    if (fputs("# End Of Table - urls\n",fp)==EOF) return 1;  /* error exit */
413 
414    /* daily hostname list */
415    if (fputs("# -sites- (monthly)\n",fp)==EOF) return 1;  /* error exit */
416 
417    for (i=0;i<MAXHASH;i++)
418    {
419       hptr=sm_htab[i];
420       while (hptr!=NULL)
421       {
422          snprintf(buffer,sizeof(buffer),"%s\n%d %llu %llu %.0f %llu %llu\n%s\n",
423                   hptr->string, hptr->flag, hptr->count, hptr->files,
424                   hptr->xfer, hptr->visit, hptr->tstamp,
425                   (hptr->lasturl==blank_str)?"-":hptr->lasturl);
426          if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
427          hptr=hptr->next;
428       }
429    }
430    if (fputs("# End Of Table - sites (monthly)\n",fp)==EOF) return 1;
431 
432    /* hourly hostname list */
433    if (fputs("# -sites- (daily)\n",fp)==EOF) return 1;  /* error exit */
434    for (i=0;i<MAXHASH;i++)
435    {
436       hptr=sd_htab[i];
437       while (hptr!=NULL)
438       {
439          snprintf(buffer,sizeof(buffer),"%s\n%d %llu %llu %.0f %llu %llu\n%s\n",
440                   hptr->string, hptr->flag, hptr->count, hptr->files,
441                   hptr->xfer, hptr->visit, hptr->tstamp,
442                   (hptr->lasturl==blank_str)?"-":hptr->lasturl);
443          if (fputs(buffer,fp)==EOF) return 1;
444          hptr=hptr->next;
445       }
446    }
447    if (fputs("# End Of Table - sites (daily)\n",fp)==EOF) return 1;
448 
449    /* Referrer list */
450    if (fputs("# -referrers- \n",fp)==EOF) return 1;  /* error exit */
451    if (t_ref != 0)
452    {
453       for (i=0;i<MAXHASH;i++)
454       {
455          rptr=rm_htab[i];
456          while (rptr!=NULL)
457          {
458             snprintf(buffer,sizeof(buffer),"%s\n%d %llu\n",
459                      rptr->string, rptr->flag, rptr->count);
460             if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
461             rptr=rptr->next;
462          }
463       }
464    }
465    if (fputs("# End Of Table - referrers\n",fp)==EOF) return 1;
466 
467    /* User agent list */
468    if (fputs("# -agents- \n",fp)==EOF) return 1;  /* error exit */
469    if (t_agent != 0)
470    {
471       for (i=0;i<MAXHASH;i++)
472       {
473          aptr=am_htab[i];
474          while (aptr!=NULL)
475          {
476             snprintf(buffer,sizeof(buffer),"%s\n%d %llu\n",
477                      aptr->string, aptr->flag, aptr->count);
478             if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
479             aptr=aptr->next;
480          }
481       }
482    }
483    if (fputs("# End Of Table - agents\n",fp)==EOF) return 1;
484 
485    /* Search String list */
486    if (fputs("# -search strings- \n",fp)==EOF) return 1;  /* error exit */
487    for (i=0;i<MAXHASH;i++)
488    {
489       sptr=sr_htab[i];
490       while (sptr!=NULL)
491       {
492          snprintf(buffer,sizeof(buffer),"%s\n%llu\n",
493                   sptr->string,sptr->count);
494          if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
495          sptr=sptr->next;
496       }
497    }
498    if (fputs("# End Of Table - search strings\n",fp)==EOF) return 1;
499 
500    /* username list */
501    if (fputs("# -usernames- \n",fp)==EOF) return 1;  /* error exit */
502 
503    for (i=0;i<MAXHASH;i++)
504    {
505       iptr=im_htab[i];
506       while (iptr!=NULL)
507       {
508          snprintf(buffer,sizeof(buffer),"%s\n%d %llu %llu %.0f %llu %llu\n",
509                   iptr->string, iptr->flag, iptr->count, iptr->files,
510               iptr->xfer, iptr->visit, iptr->tstamp);
511          if (fputs(buffer,fp)==EOF) return 1;  /* error exit */
512          iptr=iptr->next;
513       }
514    }
515    if (fputs("# End Of Table - usernames\n",fp)==EOF) return 1;
516 
517    /* Done, close file */
518    fclose(fp);
519 
520    /* now rename the 'new' file to real name */
521    if ((rename(new_fname,state_fname) == -1) && verbose)
522    {
523       fprintf(stderr,"Failed renaming %s to %s\n",new_fname,state_fname);
524       return 1;         /* Failed, return with error code                */
525    }
526    return 0;            /* successful, return with good return code      */
527 }
528 
529 /*********************************************/
530 /* RESTORE_STATE - reload internal run data  */
531 /*********************************************/
532 
restore_state()533 int restore_state()
534 {
535    FILE *fp;
536    int  i;
537    struct hnode t_hnode;         /* Temporary hash nodes */
538    struct unode t_unode;
539    struct rnode t_rnode;
540    struct anode t_anode;
541    struct snode t_snode;
542    struct inode t_inode;
543 
544    char         buffer[BUFSIZE];
545    char         tmp_buf[BUFSIZE];
546 
547    u_int64_t    ul_bogus=0;
548 
549    /* if ignoring, just return */
550    if (ignore_state) return 0;
551 
552    /* try to open state file */
553    fp=fopen(state_fname,"r");
554    if (fp==NULL)
555    {
556       /* Previous run data not found... */
557       if (verbose>1) printf("%s\n",msg_no_data);
558       return 0;   /* return with ok code */
559    }
560 
561    /* Reading previous run data... */
562    if (verbose>1) printf("%s %s\n",msg_get_data,state_fname);
563 
564    /* get easy stuff */
565    sprintf(tmp_buf,"# Webalizer V%s    ",version);
566    if ((fgets(buffer,BUFSIZE,fp)) != NULL)                 /* Header record */
567    {
568       if (strncmp(buffer,tmp_buf,16))
569       {
570          /* Kludge to allow 2.01 files also */
571          sprintf(tmp_buf,"# Webalizer V2.01-1");
572          if (strncmp(buffer,tmp_buf,19)) return 99; /* bad magic? */
573       }
574    }
575    else return 1;   /* error exit */
576 
577    /* Get current timestamp */
578    if ((fgets(buffer,BUFSIZE,fp)) != NULL)
579    {
580       sscanf(buffer,"%d %d %d %d %d %d",
581        &cur_year, &cur_month, &cur_day,
582        &cur_hour, &cur_min, &cur_sec);
583    } else return 2;  /* error exit */
584 
585    /* calculate current timestamp (seconds since epoch) */
586    cur_tstamp=((jdate(cur_day,cur_month,cur_year)-epoch)*86400)+
587                      (cur_hour*3600)+(cur_min*60)+cur_sec;
588 
589    /* Get monthly totals */
590    if ((fgets(buffer,BUFSIZE,fp)) != NULL)
591    {
592       sscanf(buffer,"%llu %llu %llu %llu %llu %llu %lf %llu %llu %llu",
593        &t_hit, &t_file, &t_site, &t_url,
594        &t_ref, &t_agent, &t_xfer, &t_page, &t_visit, &t_user);
595    } else return 3;  /* error exit */
596 
597    /* Get daily totals */
598    if ((fgets(buffer,BUFSIZE,fp)) != NULL)
599    {
600       sscanf(buffer,"%llu %llu %llu %d %d",
601        &dt_site, &ht_hit, &mh_hit, &f_day, &l_day);
602    } else return 4;  /* error exit */
603 
604    /* get daily totals */
605    for (i=0;i<31;i++)
606    {
607       if ((fgets(buffer,BUFSIZE,fp)) != NULL)
608       {
609          sscanf(buffer,"%llu %llu %lf %llu %llu %llu",
610           &tm_hit[i],&tm_file[i],&tm_xfer[i],&tm_site[i],&tm_page[i],
611           &tm_visit[i]);
612       } else return 5;  /* error exit */
613    }
614 
615    /* get hourly totals */
616    for (i=0;i<24;i++)
617    {
618       if ((fgets(buffer,BUFSIZE,fp)) != NULL)
619       {
620          sscanf(buffer,"%llu %llu %lf %llu",
621           &th_hit[i],&th_file[i],&th_xfer[i],&th_page[i]);
622       } else return 6;  /* error exit */
623    }
624 
625    /* get response code totals */
626    for (i=0;i<TOTAL_RC;i++)
627    {
628       if ((fgets(buffer,BUFSIZE,fp)) != NULL)
629          sscanf(buffer,"%llu",&response[i].count);
630       else return 7;  /* error exit */
631    }
632 
633    /* Kludge for V2.01-06 TOTAL_RC off by one bug */
634    if (!strncmp(buffer,"# -urls- ",9)) response[TOTAL_RC-1].count=0;
635    else
636    {
637       /* now do hash tables */
638 
639       /* url table */
640       if ((fgets(buffer,BUFSIZE,fp)) != NULL)            /* Table header */
641       { if (strncmp(buffer,"# -urls- ",9)) return 10; }  /* (url)        */
642       else return 10;   /* error exit */
643    }
644 
645    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
646    {
647       if (!strncmp(buffer,"# End Of Table ",15)) break;
648       strncpy(tmp_buf,buffer,MAXURLH);
649       tmp_buf[strlen(tmp_buf)-1]=0;
650 
651       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 10;  /* error exit */
652       if (!isdigit((unsigned char)buffer[0])) return 10;  /* error exit */
653 
654       /* load temporary node data */
655       sscanf(buffer,"%d %llu %llu %lf %llu %llu",
656          &t_unode.flag,&t_unode.count,
657          &t_unode.files, &t_unode.xfer,
658          &t_unode.entry, &t_unode.exit);
659 
660       /* Good record, insert into hash table */
661       if (put_unode(tmp_buf,t_unode.flag,t_unode.count,
662          t_unode.xfer,&ul_bogus,t_unode.entry,t_unode.exit,um_htab))
663       {
664          if (verbose)
665          /* Error adding URL node, skipping ... */
666          fprintf(stderr,"%s %s\n", msg_nomem_u, t_unode.string);
667       }
668    }
669 
670    /* monthly sites table */
671    if ((fgets(buffer,BUFSIZE,fp)) != NULL)               /* Table header */
672    { if (strncmp(buffer,"# -sites- ",10)) return 8; }    /* (monthly)    */
673    else return 8;   /* error exit */
674 
675    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
676    {
677       /* Check for end of table */
678       if (!strncmp(buffer,"# End Of Table ",15)) break;
679       strncpy(tmp_buf,buffer,MAXHOST);
680       tmp_buf[strlen(buffer)-1]=0;
681 
682       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 8;  /* error exit */
683       if (!isdigit((unsigned char)buffer[0])) return 8;  /* error exit */
684 
685       /* load temporary node data */
686       sscanf(buffer,"%d %llu %llu %lf %llu %llu",
687          &t_hnode.flag,&t_hnode.count,
688          &t_hnode.files, &t_hnode.xfer,
689          &t_hnode.visit, &t_hnode.tstamp);
690 
691       /* get last url */
692       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 8;  /* error exit */
693       if (buffer[0]=='-') t_hnode.lasturl=blank_str;
694       else
695       {
696          buffer[strlen(buffer)-1]=0;
697          t_hnode.lasturl=find_url(buffer);
698       }
699 
700       /* Good record, insert into hash table */
701       if (put_hnode(tmp_buf,t_hnode.flag,
702          t_hnode.count,t_hnode.files,t_hnode.xfer,&ul_bogus,
703          t_hnode.visit+1,t_hnode.tstamp,t_hnode.lasturl,sm_htab))
704       {
705          /* Error adding host node (monthly), skipping .... */
706          if (verbose) fprintf(stderr,"%s %s\n",msg_nomem_mh, t_hnode.string);
707       }
708    }
709 
710    /* Daily sites table */
711    if ((fgets(buffer,BUFSIZE,fp)) != NULL)               /* Table header */
712    { if (strncmp(buffer,"# -sites- ",10)) return 9; }    /* (daily)      */
713    else return 9;   /* error exit */
714 
715    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
716    {
717       /* Check for end of table */
718       if (!strncmp(buffer,"# End Of Table ",15)) break;
719       strncpy(tmp_buf,buffer,MAXHOST);
720       tmp_buf[strlen(buffer)-1]=0;
721 
722       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 9;  /* error exit */
723       if (!isdigit((unsigned char)buffer[0])) return 9;  /* error exit */
724 
725       /* load temporary node data */
726       sscanf(buffer,"%d %llu %llu %lf %llu %llu",
727           &t_hnode.flag,&t_hnode.count,
728           &t_hnode.files, &t_hnode.xfer,
729           &t_hnode.visit, &t_hnode.tstamp);
730 
731       /* get last url */
732       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 9;  /* error exit */
733       if (buffer[0]=='-') t_hnode.lasturl=blank_str;
734       else
735       {
736          buffer[strlen(buffer)-1]=0;
737          t_hnode.lasturl=find_url(buffer);
738       }
739 
740       /* Good record, insert into hash table */
741       if (put_hnode(tmp_buf,t_hnode.flag,
742          t_hnode.count,t_hnode.files,t_hnode.xfer,&ul_bogus,
743          t_hnode.visit+1,t_hnode.tstamp,t_hnode.lasturl,sd_htab))
744       {
745          /* Error adding host node (daily), skipping .... */
746          if (verbose) fprintf(stderr,"%s %s\n",msg_nomem_dh, t_hnode.string);
747       }
748    }
749 
750    /* Referrers table */
751    if ((fgets(buffer,BUFSIZE,fp)) != NULL)               /* Table header */
752    { if (strncmp(buffer,"# -referrers- ",14)) return 11; } /* (referrers)*/
753    else return 11;   /* error exit */
754 
755    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
756    {
757       if (!strncmp(buffer,"# End Of Table ",15)) break;
758       strncpy(tmp_buf,buffer,MAXREFH);
759       tmp_buf[strlen(buffer)-1]=0;
760 
761       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 11;  /* error exit */
762       if (!isdigit((unsigned char)buffer[0])) return 11;  /* error exit */
763 
764       /* load temporary node data */
765       sscanf(buffer,"%d %llu",&t_rnode.flag,&t_rnode.count);
766 
767       /* insert node */
768       if (put_rnode(tmp_buf,t_rnode.flag,
769          t_rnode.count, &ul_bogus, rm_htab))
770       {
771          if (verbose) fprintf(stderr,"%s %s\n", msg_nomem_r, log_rec.refer);
772       }
773    }
774 
775    /* Agents table */
776    if ((fgets(buffer,BUFSIZE,fp)) != NULL)               /* Table header */
777    { if (strncmp(buffer,"# -agents- ",11)) return 12; } /* (agents)*/
778    else return 12;   /* error exit */
779 
780    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
781    {
782       if (!strncmp(buffer,"# End Of Table ",15)) break;
783       strncpy(tmp_buf,buffer,MAXAGENT);
784       tmp_buf[strlen(buffer)-1]=0;
785 
786       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 12;  /* error exit */
787       if (!isdigit((unsigned char)buffer[0])) return 12;  /* error exit */
788 
789       /* load temporary node data */
790       sscanf(buffer,"%d %llu",&t_anode.flag,&t_anode.count);
791 
792       /* insert node */
793       if (put_anode(tmp_buf,t_anode.flag,t_anode.count,
794          &ul_bogus,am_htab))
795       {
796          if (verbose) fprintf(stderr,"%s %s\n", msg_nomem_a, log_rec.agent);
797       }
798    }
799 
800    /* Search Strings table */
801    if ((fgets(buffer,BUFSIZE,fp)) != NULL)               /* Table header */
802    { if (strncmp(buffer,"# -search string",16)) return 13; }  /* (search)*/
803    else return 13;   /* error exit */
804 
805    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
806    {
807       if (!strncmp(buffer,"# End Of Table ",15)) break;
808       strncpy(tmp_buf,buffer,MAXSRCH);
809       tmp_buf[strlen(buffer)-1]=0;
810 
811       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 13;  /* error exit */
812       if (!isdigit((unsigned char)buffer[0])) return 13;  /* error exit */
813 
814       /* load temporary node data */
815       sscanf(buffer,"%llu",&t_snode.count);
816 
817       /* insert node */
818       if (put_snode(tmp_buf,t_snode.count,sr_htab))
819       {
820          if (verbose) fprintf(stderr,"%s %s\n", msg_nomem_sc, t_snode.string);
821       }
822    }
823 
824    /* usernames table */
825    if ((fgets(buffer,BUFSIZE,fp)) != NULL)               /* Table header */
826    { if (strncmp(buffer,"# -usernames- ",10)) return 14; }
827    else return 14;   /* error exit */
828 
829    while ((fgets(buffer,BUFSIZE,fp)) != NULL)
830    {
831       /* Check for end of table */
832       if (!strncmp(buffer,"# End Of Table ",15)) break;
833       strncpy(tmp_buf,buffer,MAXIDENT);
834       tmp_buf[strlen(buffer)-1]=0;
835 
836       if ((fgets(buffer,BUFSIZE,fp)) == NULL) return 14;  /* error exit */
837       if (!isdigit((unsigned char)buffer[0])) return 14;  /* error exit */
838 
839       /* load temporary node data */
840       sscanf(buffer,"%d %llu %llu %lf %llu %llu",
841          &t_inode.flag,&t_inode.count,
842          &t_inode.files, &t_inode.xfer,
843          &t_inode.visit, &t_inode.tstamp);
844 
845       /* Good record, insert into hash table */
846       if (put_inode(tmp_buf,t_inode.flag,
847          t_inode.count,t_inode.files,t_inode.xfer,&ul_bogus,
848          t_inode.visit+1,t_inode.tstamp,im_htab))
849       {
850          if (verbose)
851          /* Error adding username node, skipping .... */
852          fprintf(stderr,"%s %s\n",msg_nomem_i, t_inode.string);
853       }
854    }
855 
856    fclose(fp);
857    check_dup = 1;              /* enable duplicate checking */
858    return 0;                   /* return with ok code       */
859 }
860