]> git.ipfire.org Git - thirdparty/sarg.git/blame - realtime.c
Replace the "getword loop" messages
[thirdparty/sarg.git] / realtime.c
CommitLineData
d5c1b1c1 1/*
d5c1b1c1 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
61d965f3 3 * 1998, 2012
d5c1b1c1
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
d5c1b1c1
GS
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27#include "include/conf.h"
5f3cfd1d 28#include "include/defs.h"
d5c1b1c1 29
120d768c
FM
30static int getdata(char*, FILE*);
31static void datashow(const char *);
32e71fa4
FM
32static void getlog(void);
33static void header(void);
d5c1b1c1 34
32e71fa4 35void realtime(void)
d5c1b1c1 36{
9bd92830 37 getlog();
d5c1b1c1
GS
38}
39
32e71fa4 40static void getlog(void)
d5c1b1c1 41{
9bd92830
FM
42 FILE *tmp, *fp;
43 char template1[255]="/var/tmp/sargtpl1.XXXXXX";
44 char template2[255]="/var/tmp/sargtpl2.XXXXXX";
45 char cmd[512];
46 char *buf;
d7cb0aec 47 int fd1,fd2;
9bd92830
FM
48 int cstatus;
49 longline line;
d6e703cc 50
9bd92830 51 init_usertab(UserTabFile);
d5c1b1c1 52
72a23a7a 53#ifdef HAVE_MKSTEMP
d7cb0aec
FM
54 fd2 = mkstemp(template2);
55 if (fd2 == -1) {
56 debuga(_("Cannot create a temporary file name to produce the report: %s\n"),strerror(errno));
57 exit(EXIT_FAILURE);
58 }
9bd92830 59 fd1 = mkstemp(template1);
72a23a7a 60#else
d7cb0aec
FM
61 buf = mktemp(template2);
62 if (buf[0]=='\0') {
63 debuga(_("Cannot create a temporary file name to produce the report: %s\n"),strerror(errno));
64 exit(EXIT_FAILURE);
65 }
66 fd2 = -1;
67 fd1 = open(mktemp(template1),O_RDWR);
72a23a7a 68#endif
d5c1b1c1 69
9bd92830
FM
70 if((fd1 == -1 ) || ((tmp = fdopen (fd1, "w+" )) == NULL) ) { /* failure, bail out */
71 debuga(_("(realtime) mkstemp error - %s\n"),strerror(errno));
72 exit(EXIT_FAILURE);
73 }
d5c1b1c1 74
9bd92830
FM
75 if ((line=longline_create())==NULL) {
76 debuga(_("Not enough memory to read the log file\n"));
77 exit(EXIT_FAILURE);
78 }
ac422f9b 79
9bd92830
FM
80 sprintf(cmd,"tail -%d \"%s\"",realtime_access_log_lines,AccessLog[0]);
81 fp = popen(cmd, "r");
82 if (!fp) {
83 debuga(_("Failed to get the %d trailing lines of %s: %s\n"),realtime_access_log_lines,AccessLog[0],strerror(errno));
84 debuga(_("tail command: %s\n"),cmd);
85 exit(EXIT_FAILURE);
86 }
87 while((buf=longline_read(fp,line)) != NULL )
88 if (getdata(buf,tmp)<0) {
89 debuga(_("Maybe a broken record or garbage was returned by %s\n"),cmd);
90 exit(EXIT_FAILURE);
91 }
92 pclose(fp);
93 fclose(tmp);
94 longline_destroy(&line);
d5c1b1c1 95
d7cb0aec
FM
96 if (fd2!=-1) close(fd2);//not safe at all but good enough for now.
97 if (snprintf(cmd,sizeof(cmd),"sort -t \"\t\" -r -n -k 1,1 -o \"%s\" \"%s\"",template2,template1)>=sizeof(cmd)) {
78eeb33f
FM
98 debuga(_("Sort command too long when sorting file \"%s\" to \"%s\"\n"),template1,template2);
99 exit(EXIT_FAILURE);
100 }
9bd92830
FM
101 cstatus=system(cmd);
102 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
103 debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
104 debuga(_("sort command: %s\n"),cmd);
105 exit(EXIT_FAILURE);
106 }
11767c6a
FM
107 if (!KeepTempLog && unlink(template1)) {
108 debuga(_("Cannot delete \"%s\": %s\n"),template1,strerror(errno));
08f9b029
FM
109 exit(EXIT_FAILURE);
110 }
9bd92830 111 datashow(template2);
d5c1b1c1
GS
112}
113
120d768c 114static int getdata(char *rec, FILE *ftmp)
d5c1b1c1 115{
d7cb0aec 116 int dat;
9bd92830
FM
117 char typ[128];
118 char warea[MAXLEN];
119 char user[MAX_USER_LEN];
9bd733aa 120 char ip[45];
9bd92830
FM
121 char *url;
122 struct getwordstruct gwarea;
d5c1b1c1 123
9bd92830 124 getword_start(&gwarea,rec);
d7cb0aec 125 if (getword_atoi(&dat,&gwarea,'.')<0) {
9bd92830
FM
126 debuga(_("The time stamp at column 1 is too long\n"));
127 return(-1);
128 }
d7cb0aec
FM
129 if (getword_skip(10,&gwarea,' ')<0) {
130 debuga(_("The time stamp decimal part at column 1 is too long\n"));
131 return(-1);
132 }
9bd92830
FM
133 if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
134 debuga(_("The connection duration at column 2 is too long\n"));
135 return(-1);
136 }
137 while(strcmp(warea,"") == 0 && gwarea.current[0] != '\0')
138 if (getword(warea,sizeof(warea),&gwarea,' ')<0) {
139 return(-1);
140 }
141 if (getword(ip,sizeof(ip),&gwarea,' ')<0) {
142 debuga(_("The IP address at column 3 is too long\n"));
143 return(-1);
144 }
145 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
146 debuga(_("The status at column 4 is too long\n"));
147 return(-1);
148 }
149 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
150 debuga(_("The size at column 5 is too long\n"));
151 return(-1);
152 }
153 if (getword(typ,sizeof(typ),&gwarea,' ')<0) {
154 debuga(_("The action at column 6 is too long\n"));
155 return(-1);
156 }
157 if(strncmp(typ,"CONNECT",7) == 0) {
158 if (getword_ptr(rec,&url,&gwarea,' ')<0) {
159 debuga(_("The URL at column 7 is too long\n"));
160 return(-1);
161 }
162 if (getword(user,sizeof(user),&gwarea,' ')<0) {
163 debuga(_("The user ID at column 8 is too long\n"));
164 return(-1);
165 }
166 }else {
167 if (getword_skip(MAXLEN,&gwarea,'/')<0) {
168 debuga(_("The URL at column 7 is too long\n"));
169 return(-1);
170 }
171 if (getword_skip(MAXLEN,&gwarea,'/')<0) {
172 debuga(_("The URL at column 7 is too long\n"));
173 return(-1);
174 }
175 if (getword_ptr(rec,&url,&gwarea,'/')<0) {
176 debuga(_("The URL at column 7 is too long\n"));
177 return(-1);
178 }
179 if (getword_skip(MAXLEN,&gwarea,' ')<0) {
180 debuga(_("The data at column 8 is too long\n"));
181 return(-1);
182 }
183 if (getword(user,sizeof(user),&gwarea,' ')<0) {
184 debuga(_("The user at column 9 is too long\n"));
185 return(-1);
186 }
187 }
d5c1b1c1 188
9bd92830
FM
189 if(strncmp(user,"-",1) == 0 && RealtimeUnauthRec==REALTIME_UNAUTH_REC_IGNORE)
190 return(0);
d5c1b1c1 191
d7cb0aec 192 fprintf(ftmp,"%d\t%s\t%s\t%s\t%s\n",dat,ip,user,url,typ);
9bd92830 193 return(0);
d5c1b1c1
GS
194}
195
120d768c 196static void datashow(const char *tmp)
d5c1b1c1 197{
9bd92830 198 FILE *fin;
d7cb0aec
FM
199 time_t tt;
200 struct tm *t;
201 char tbuf[128];
202 int dat;
9bd92830
FM
203 char *buf;
204 char *url;
205 char *ourl=NULL;
206 char ouser[MAX_USER_LEN]="";
207 char typ[128];
208 char user[MAX_USER_LEN];
209 char u2[MAX_USER_LEN];
9bd733aa 210 char ip[45];
9bd92830
FM
211 int url_len;
212 int ourl_size=0;
213 struct getwordstruct gwarea;
214 longline line;
d5c1b1c1 215
9bd92830
FM
216 if((fin=fopen(tmp,"r"))==NULL) {
217 debuga(_("(realtime) open error %s - %s\n"),tmp,strerror(errno));
218 exit(EXIT_FAILURE);
219 }
d5c1b1c1 220
9bd92830 221 header();
e5b2c6f0 222
9bd92830
FM
223 if ((line=longline_create())==NULL) {
224 debuga(_("Not enough memory to read the log file\n"));
225 exit(EXIT_FAILURE);
226 }
d5c1b1c1 227
9bd92830
FM
228 while((buf=longline_read(fin,line))!=NULL) {
229 fixendofline(buf);
230 getword_start(&gwarea,buf);
d7cb0aec
FM
231 if (getword_atoi(&dat,&gwarea,'\t')<0) {
232 debuga(_("Invalid time column in file %s\n"),tmp);
9bd92830
FM
233 exit(EXIT_FAILURE);
234 }
235 if (getword(ip,sizeof(ip),&gwarea,'\t')<0) {
d7cb0aec 236 debuga(_("Invalid IP address in file %s\n"),tmp);
9bd92830
FM
237 exit(EXIT_FAILURE);
238 }
239 if (getword(user,sizeof(user),&gwarea,'\t')<0) {
d7cb0aec 240 debuga(_("Invalid user name in file %s\n"),tmp);
9bd92830
FM
241 exit(EXIT_FAILURE);
242 }
d7cb0aec 243 if (strlen(user) < 1) continue;
9bd92830 244 if (getword_ptr(buf,&url,&gwarea,'\t')<0) {
d7cb0aec 245 debuga(_("Invalid URL in file %s\n"),tmp);
9bd92830
FM
246 exit(EXIT_FAILURE);
247 }
248 if (getword(typ,sizeof(typ),&gwarea,'\t')<0) {
d7cb0aec 249 debuga(_("Invalid access type in file %s\n"),tmp);
9bd92830
FM
250 exit(EXIT_FAILURE);
251 }
252 if(strstr(RealtimeTypes,typ) == 0)
253 continue;
d5c1b1c1 254
9bd92830
FM
255 if(strcmp(ouser,user) == 0 && ourl && strcmp(ourl,url) == 0)
256 continue;
d6e703cc 257
9bd92830
FM
258 if(UserIp)
259 strcpy(user,ip);
260 strcpy(u2,user);
261 if(Ip2Name)
262 ip2name(u2,sizeof(u2));
263 user_find(name, sizeof(name), u2);
e5b2c6f0 264
d7cb0aec
FM
265 tt=(time_t)dat;
266 t=localtime(&tt);
81a022d8 267 if (df=='u')
d7cb0aec 268 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M", t);
81a022d8 269 else if (df=='e')
d7cb0aec 270 strftime(tbuf, sizeof(tbuf), "%d-%m-%Y %H:%M", t);
bd43d81f 271
d7cb0aec 272 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);
9bd92830 273 strcpy(ouser,user);
d5c1b1c1 274
9bd92830
FM
275 url_len=strlen(url);
276 if (!ourl || url_len>=ourl_size) {
277 ourl_size=url_len+1;
278 ourl=realloc(ourl,ourl_size);
279 if (!ourl) {
280 debuga(_("Not enough memory to store the url\n"));
281 exit(EXIT_FAILURE);
282 }
283 }
284 strcpy(ourl,url);
285 }
286 longline_destroy(&line);
287 if (ourl) free(ourl);
dfb337be 288
9bd92830
FM
289 puts("</table>\n</div>\n</body>\n</html>\n");
290 fclose(fin);
11767c6a
FM
291 if (!KeepTempLog && unlink(tmp)) {
292 debuga(_("Cannot delete \"%s\": %s\n"),tmp,strerror(errno));
08f9b029
FM
293 exit(EXIT_FAILURE);
294 }
9bd92830 295 fflush(NULL);
d5c1b1c1
GS
296}
297
32e71fa4 298static void header(void)
d5c1b1c1 299{
9bd92830
FM
300 puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
301 puts(" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
302 puts("<html>\n");
303 puts("<head>\n");
304 if(realtime_refresh)
305 printf(" <meta http-equiv=refresh content=\"%d\" url=\"sarg-php/sarg-realtime.php\"; charset=\"%s\">\n",realtime_refresh,CharSet);
306 else
307 printf(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",CharSet);
308 css(stdout);
309 puts("</head>\n");
310 printf("<body style=\"font-family:%s;font-size:%s;background-color:%s;background-image:url(%s)\">\n",FontFace,TitleFontSize,BgColor,BgImage);
311 puts("<div align=\"center\"><table cellpadding=\"1\" cellspacing=\"1\">\n");
312 printf("<tr><th class=\"title_l\" colspan=\"10\">SARG %s</th></tr>\n",_("Realtime"));
313 printf("<tr><th class=\"text\" colspan=\"10\">%s: %d s</th></tr>\n",_("Auto refresh"),realtime_refresh);
314 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"));
d5c1b1c1 315}