]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - realtime.c
A temporary file could be left in place by sarg
[thirdparty/sarg.git] / realtime.c
index 4ab6b47874a106c0d229f2a01ed9cdee08eeb33a..a2d7c7f2eb8d914783614583dc54de4e331a54ce 100755 (executable)
@@ -1,10 +1,11 @@
 /*
- * AUTHOR: Pedro Lineu Orso                      orso@penguintech.com.br
- *                                                            1998, 2005
  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
+ *                                                            1998, 2012
  *
  * SARG donations:
  *      please look at http://sarg.sourceforge.net/donations.php
+ * Support:
+ *     http://sourceforge.net/projects/sarg/forums/forum/363374
  * ---------------------------------------------------------------------
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -31,224 +32,284 @@ static void datashow(const char *);
 static void getlog(void);
 static void header(void);
 
-char dat[128];
-char tim[128];
-char typ[128];
-char ouser[MAXLEN]="";
-char ourl[MAXLEN]="";
-
 void realtime(void)
 {
-
-   getlog();
-
+       getlog();
 }
 
 static void getlog(void)
 {
-   FILE *tmp, *fp;
-   char template1[255]="/var/tmp/sargtpl1.XXXXXX";
-   char template2[255]="/var/tmp/sargtpl2.XXXXXX";
-   char cmd[512];
-   char buf[MAXLEN];
-   int  fd1,fd2;
-   int cstatus;
-
-   read_usertab(UserTabFile);
-
-   fd1 = mkstemp(template1);
-   fd2 = mkstemp(template2);
-
-   if((fd1 == -1 ) || ((tmp = fdopen (fd1, "w+" )) == NULL)  ) {    /* failure, bail out */
-       fprintf(stderr, "SARG: (realtime) mkstemp error - %s\n",strerror(errno));
-       exit(1);
-   }
-
-   sprintf(cmd,"tail -%d %s",realtime_access_log_lines,AccessLog[0]);
-   fp = popen(cmd, "r");
-   while(fgets(buf,sizeof(buf),fp) != NULL )
-      if (getdata(buf,tmp)<0) {
-         fprintf(stderr,"SARG: Maybe a broken record or garbage was returned by %s.\n",cmd);
-         exit(1);
-      }
-   pclose(fp);
-   fclose(tmp);
-
-   sprintf(cmd,"sort -r -k 1,1 -k 2,2 -o \"%s\" \"%s\"",template2,template1);
-   cstatus=system(cmd);
-   if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
-      fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus));
-      fprintf(stderr, "SARG: sort command: %s\n",cmd);
-      exit(1);
-   }
-   unlink(template1);
-   datashow(template2);
+       FILE *tmp, *fp;
+       char template1[255]="/var/tmp/sargtpl1.XXXXXX";
+       char template2[255]="/var/tmp/sargtpl2.XXXXXX";
+       char cmd[512];
+       char *buf;
+       int  fd1,fd2;
+       int cstatus;
+       longline line;
+
+       init_usertab(UserTabFile);
+
+#ifdef HAVE_MKSTEMP
+       fd2 = mkstemp(template2);
+       if (fd2 == -1) {
+               debuga(_("Cannot create a temporary file name to produce the report: %s\n"),strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       fd1 = mkstemp(template1);
+#else
+       buf = mktemp(template2);
+       if (buf[0]=='\0') {
+               debuga(_("Cannot create a temporary file name to produce the report: %s\n"),strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       fd2 = -1;
+       fd1 = open(mktemp(template1),O_RDWR);
+#endif
+
+       if((fd1 == -1 ) || ((tmp = fdopen (fd1, "w+" )) == NULL)  ) {    /* failure, bail out */
+               debuga(_("(realtime) mkstemp error - %s\n"),strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       if ((line=longline_create())==NULL) {
+               debuga(_("Not enough memory to read the log file\n"));
+               exit(EXIT_FAILURE);
+       }
+
+       sprintf(cmd,"tail -%d \"%s\"",realtime_access_log_lines,AccessLog[0]);
+       fp = popen(cmd, "r");
+       if (!fp) {
+               debuga(_("Failed to get the %d trailing lines of %s: %s\n"),realtime_access_log_lines,AccessLog[0],strerror(errno));
+               debuga(_("tail command: %s\n"),cmd);
+               exit(EXIT_FAILURE);
+       }
+       while((buf=longline_read(fp,line)) != NULL )
+               if (getdata(buf,tmp)<0) {
+                       debuga(_("Maybe a broken record or garbage was returned by %s\n"),cmd);
+                       exit(EXIT_FAILURE);
+               }
+       pclose(fp);
+       fclose(tmp);
+       longline_destroy(&line);
+
+       if (fd2!=-1) close(fd2);//not safe at all but good enough for now.
+       if (snprintf(cmd,sizeof(cmd),"sort -t \"\t\" -r -n -k 1,1 -o \"%s\" \"%s\"",template2,template1)>=sizeof(cmd)) {
+               debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),template1,template2);
+               exit(EXIT_FAILURE);
+       }
+       cstatus=system(cmd);
+       if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
+               debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
+               debuga(_("sort command: %s\n"),cmd);
+               exit(EXIT_FAILURE);
+       }
+       if (unlink(template1)) {
+               debuga(_("Cannot delete %s - %s\n"),template1,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       datashow(template2);
 }
 
 static int getdata(char *rec, FILE *ftmp)
 {
-   time_t tt;
-   struct tm *t;
-   char tbuf[128];
-   char warea[MAXLEN];
-   struct getwordstruct gwarea;
-
-   getword_start(&gwarea,rec);
-   if (getword(dat,sizeof(dat),&gwarea,' ')<0) {
-      fprintf(stderr,"SARG: The time stamp at column 1 is too long.\n");
-      return(-1);
-   }
-   if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
-      fprintf(stderr,"SARG: The connection duration at column 2 is too long.\n");
-      return(-1);
-   }
-   while(strcmp(warea,"") == 0 && gwarea.current[0] != '\0')
-      if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
-         return(-1);
-      }
-   if (getword(ip,sizeof(ip),&gwarea,' ')<0) {
-      fprintf(stderr,"SARG: The IP address at column 3 is too long.\n");
-      return(-1);
-   }
-   if (getword_skip(MAXLEN,&gwarea,' ')<0) {
-      fprintf(stderr,"SARG: The status at column 4 is too long.\n");
-      return(-1);
-   }
-   if (getword_skip(MAXLEN,&gwarea,' ')<0) {
-      fprintf(stderr,"SARG: The size at column 5 is too long.\n");
-      return(-1);
-   }
-   if (getword(typ,sizeof(typ),&gwarea,' ')<0) {
-      fprintf(stderr,"SARG: The action at column 6 is too long.\n");
-      return(-1);
-   }
-   if(strncmp(typ,"CONNECT",7) == 0) {
-      if (getword(url,sizeof(url),&gwarea,' ')<0) {
-         return(-1);
-      }
-      if (getword(user,sizeof(user),&gwarea,' ')<0) {
-         return(-1);
-      }
-   }else {
-      if (getword_skip(MAXLEN,&gwarea,'/')<0) {
-         fprintf(stderr,"SARG: The URL at column 7 is too long.\n");
-         return(-1);
-      }
-      if (getword_skip(MAXLEN,&gwarea,'/')<0) {
-         fprintf(stderr,"SARG: The URL at column 7 is too long.\n");
-         return(-1);
-      }
-      if (getword(url,sizeof(url),&gwarea,'/')<0) {
-         fprintf(stderr,"SARG: The URL at column 7 is too long.\n");
-         return(-1);
-      }
-      if (getword_skip(MAXLEN,&gwarea,' ')<0) {
-         fprintf(stderr,"SARG: The data at column 8 is too long.\n");
-         return(-1);
-      }
-      if (getword(user,sizeof(user),&gwarea,' ')<0) {
-         fprintf(stderr,"SARG: The user at column 9 is too long.\n");
-         return(-1);
-      }
-   }
-
-   if(strncmp(user,"-",1) == 0 && strcmp(RealtimeUnauthRec,"ignore") == 0)
-      return(0);
-
-   tt=atoi(dat);
-   t=localtime(&tt);
-   if(strncmp(DateFormat,"u",1) == 0)
-      strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M", t);
-   else if(strncmp(DateFormat,"e",1) == 0)
-      strftime(tbuf, sizeof(tbuf), "%d-%m-%Y %H:%M", t);
-
-   fprintf(ftmp,"%s\t%s\t%s\t%s\t%s\n",tbuf,ip,user,url,typ);
-   return(0);
+       int dat;
+       char typ[128];
+       char warea[MAXLEN];
+       char user[MAX_USER_LEN];
+       char ip[45];
+       char *url;
+       struct getwordstruct gwarea;
+
+       getword_start(&gwarea,rec);
+       if (getword_atoi(&dat,&gwarea,'.')<0) {
+               debuga(_("The time stamp at column 1 is too long\n"));
+               return(-1);
+       }
+       if (getword_skip(10,&gwarea,' ')<0) {
+               debuga(_("The time stamp decimal part at column 1 is too long\n"));
+               return(-1);
+       }
+       if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
+               debuga(_("The connection duration at column 2 is too long\n"));
+               return(-1);
+       }
+       while(strcmp(warea,"") == 0 && gwarea.current[0] != '\0')
+               if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
+                       return(-1);
+               }
+       if (getword(ip,sizeof(ip),&gwarea,' ')<0) {
+               debuga(_("The IP address at column 3 is too long\n"));
+               return(-1);
+       }
+       if (getword_skip(MAXLEN,&gwarea,' ')<0) {
+               debuga(_("The status at column 4 is too long\n"));
+               return(-1);
+       }
+       if (getword_skip(MAXLEN,&gwarea,' ')<0) {
+               debuga(_("The size at column 5 is too long\n"));
+               return(-1);
+       }
+       if (getword(typ,sizeof(typ),&gwarea,' ')<0) {
+               debuga(_("The action at column 6 is too long\n"));
+               return(-1);
+       }
+       if(strncmp(typ,"CONNECT",7) == 0) {
+               if (getword_ptr(rec,&url,&gwarea,' ')<0) {
+                       debuga(_("The URL at column 7 is too long\n"));
+                       return(-1);
+               }
+               if (getword(user,sizeof(user),&gwarea,' ')<0) {
+                       debuga(_("The user ID at column 8 is too long\n"));
+                       return(-1);
+               }
+       }else {
+               if (getword_skip(MAXLEN,&gwarea,'/')<0) {
+                       debuga(_("The URL at column 7 is too long\n"));
+                       return(-1);
+               }
+               if (getword_skip(MAXLEN,&gwarea,'/')<0) {
+                       debuga(_("The URL at column 7 is too long\n"));
+                       return(-1);
+               }
+               if (getword_ptr(rec,&url,&gwarea,'/')<0) {
+                       debuga(_("The URL at column 7 is too long\n"));
+                       return(-1);
+               }
+               if (getword_skip(MAXLEN,&gwarea,' ')<0) {
+                       debuga(_("The data at column 8 is too long\n"));
+                       return(-1);
+               }
+               if (getword(user,sizeof(user),&gwarea,' ')<0) {
+                       debuga(_("The user at column 9 is too long\n"));
+                       return(-1);
+               }
+       }
+
+       if(strncmp(user,"-",1) == 0 && RealtimeUnauthRec==REALTIME_UNAUTH_REC_IGNORE)
+               return(0);
+
+       fprintf(ftmp,"%d\t%s\t%s\t%s\t%s\n",dat,ip,user,url,typ);
+       return(0);
 }
 
 static void datashow(const char *tmp)
 {
-   FILE *fin;
-   char buf[MAXLEN];
-   struct getwordstruct gwarea;
-
-   if((fin=fopen(tmp,"r"))==NULL) {
-      fprintf(stderr, "SARG: (realtime) open error %s - %s\n",tmp,strerror(errno));
-      exit(1);
-   }
-
-   header();
-
-   while(fgets(buf, sizeof(buf), fin)) {
-      fixendofline(buf);
-      getword_start(&gwarea,buf);
-      if (getword(dat,sizeof(dat),&gwarea,'\t')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp);
-         exit(1);
-      }
-      if (getword(tim,sizeof(tim),&gwarea,'\t')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp);
-         exit(1);
-      }
-      if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp);
-         exit(1);
-      }
-      if (getword(user,sizeof(user),&gwarea,'\t')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp);
-         exit(1);
-      }
-      if(strlen(dat) < 3 || strlen(user) < 1) continue;
-      if (getword(url,sizeof(url),&gwarea,'\t')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp);
-         exit(1);
-      }
-      if (getword(typ,sizeof(typ),&gwarea,'\t')<0) {
-         printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp);
-         exit(1);
-      }
-      if(strstr(RealtimeTypes,typ) == 0)
-         continue;
-
-      if(strcmp(ouser,user) == 0 && strcmp(ourl,url) == 0)
-         continue;
-
-      strcpy(u2,user);
-      if(Ip2Name)
-         ip2name(u2,sizeof(u2));
-      get_usertab_name(u2,name,sizeof(name));
-
-      if(dotinuser && strchr(name,'_')) {
-         subs(name,sizeof(name),"_",".");
-      }
-
-      printf("<tr><td class=\"data\">%s %s</td><td class=\"data3\">%s</td><td class=\"data3\">%s</td><td class=\"data3\">%s</td><td class=\"data2\"><a href=\"http://%s\">%s</td></tr>\n",dat,tim,ip,name,typ,url,url);
-      strcpy(ouser,user);
-      strcpy(ourl,url);
-   }
-
-   puts("</table>\n</div>\n</body>\n</html>\n");
-   fclose(fin);
-   unlink(tmp);
-   fflush(NULL);
+       FILE *fin;
+       time_t tt;
+       struct tm *t;
+       char tbuf[128];
+       int dat;
+       char *buf;
+       char *url;
+       char *ourl=NULL;
+       char ouser[MAX_USER_LEN]="";
+       char typ[128];
+       char user[MAX_USER_LEN];
+       char u2[MAX_USER_LEN];
+       char ip[45];
+       int url_len;
+       int ourl_size=0;
+       struct getwordstruct gwarea;
+       longline line;
+
+       if((fin=fopen(tmp,"r"))==NULL) {
+               debuga(_("(realtime) open error %s - %s\n"),tmp,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       header();
+
+       if ((line=longline_create())==NULL) {
+               debuga(_("Not enough memory to read the log file\n"));
+               exit(EXIT_FAILURE);
+       }
+
+       while((buf=longline_read(fin,line))!=NULL) {
+               fixendofline(buf);
+               getword_start(&gwarea,buf);
+               if (getword_atoi(&dat,&gwarea,'\t')<0) {
+                       debuga(_("Invalid time column in file %s\n"),tmp);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
+                       debuga(_("Invalid IP address in file %s\n"),tmp);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword(user,sizeof(user),&gwarea,'\t')<0) {
+                       debuga(_("Invalid user name in file %s\n"),tmp);
+                       exit(EXIT_FAILURE);
+               }
+               if (strlen(user) < 1) continue;
+               if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
+                       debuga(_("Invalid URL in file %s\n"),tmp);
+                       exit(EXIT_FAILURE);
+               }
+               if (getword(typ,sizeof(typ),&gwarea,'\t')<0) {
+                       debuga(_("Invalid access type in file %s\n"),tmp);
+                       exit(EXIT_FAILURE);
+               }
+               if(strstr(RealtimeTypes,typ) == 0)
+                       continue;
+
+               if(strcmp(ouser,user) == 0 && ourl && strcmp(ourl,url) == 0)
+                       continue;
+
+               if(UserIp)
+                       strcpy(user,ip);
+               strcpy(u2,user);
+               if(Ip2Name)
+                       ip2name(u2,sizeof(u2));
+               user_find(name, sizeof(name), u2);
+
+               tt=(time_t)dat;
+               t=localtime(&tt);
+               if(DateFormat[0]=='u')
+                       strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M", t);
+               else if(DateFormat[0]=='e')
+                       strftime(tbuf, sizeof(tbuf), "%d-%m-%Y %H:%M", t);
+               
+               printf("<tr><td class=\"data\">%s</td><td class=\"data3\">%s</td><td class=\"data3\">%s</td><td class=\"data3\">%s</td><td class=\"data2\"><a href=\"http://%s\">%s</td></tr>\n",tbuf,ip,name,typ,url,url);
+               strcpy(ouser,user);
+
+               url_len=strlen(url);
+               if (!ourl || url_len>=ourl_size) {
+                       ourl_size=url_len+1;
+                       ourl=realloc(ourl,ourl_size);
+                       if (!ourl) {
+                               debuga(_("Not enough memory to store the url\n"));
+                               exit(EXIT_FAILURE);
+                       }
+               }
+               strcpy(ourl,url);
+       }
+       longline_destroy(&line);
+       if (ourl) free(ourl);
 
+       puts("</table>\n</div>\n</body>\n</html>\n");
+       fclose(fin);
+       if (unlink(tmp)) {
+               debuga(_("Cannot delete %s - %s\n"),tmp,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       fflush(NULL);
 }
 
 static void header(void)
 {
-   puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
-   puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
-   puts("<html>\n");
-   puts("<head>\n");
-   if(realtime_refresh)
-      printf("  <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh,CharSet);
-   else
-      printf("  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
-   css(stdout);
-   puts("</head>\n");
-   printf(buf,"<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
-   puts("<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"1\">\n");
-   printf("<tr><th class=\"title2\" colspan=\"10\">SARG %s</th></tr>\n",text[134]);
-   printf("<tr><th class=\"text\" colspan=\"10\">%s: %d s</th></tr>\n",text[136],realtime_refresh);
-   printf("<tr><th class=\"header3\">%s</th><th class=\"header3\">%s</th><th class=\"header3\">%s</th><th class=\"header3\">%s</th><th class=\"header\">%s</th></tr>\n",text[110],text[111],text[98],text[135],text[91]);
+       puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
+       puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
+       puts("<html>\n");
+       puts("<head>\n");
+       if(realtime_refresh)
+               printf("  <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh,CharSet);
+       else
+               printf("  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
+       css(stdout);
+       puts("</head>\n");
+       printf("<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
+       puts("<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"1\">\n");
+       printf("<tr><th class=\"title_l\" colspan=\"10\">SARG %s</th></tr>\n",_("Realtime"));
+       printf("<tr><th class=\"text\" colspan=\"10\">%s: %d s</th></tr>\n",_("Auto refresh"),realtime_refresh);
+       printf("<tr><th class=\"header_c\">%s</th><th class=\"header_c\">%s</th><th class=\"header_c\">%s</th><th class=\"header_c\">%s</th><th class=\"header_l\">%s</th></tr>\n",_("DATE/TIME"),_("IP/NAME"),_("USERID"),_("TYPE"),_("ACCESSED SITE"));
 }