Back to index

wims  3.65+svn20090927
log.c
Go to the documentation of this file.
00001 /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
00002  *
00003  *  This program is free software; you can redistribute it and/or modify
00004  *  it under the terms of the GNU General Public License as published by
00005  *  the Free Software Foundation; either version 2 of the License, or
00006  *  (at your option) any later version.
00007  *
00008  *  This program is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *  GNU General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU General Public License
00014  *  along with this program; if not, write to the Free Software
00015  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00016  */
00017        /* Routines to write log files. */
00018 
00019 char logbuf[4*(MAX_LINELEN+1)];
00020 char *logp=logbuf;
00021 
00022 void write_logfile(char *fname, char *str)
00023 {
00024     char *p;
00025     if((p=strchr(str,'\n'))!=NULL) *p=0;
00026     snprintf(logp,sizeof(logbuf)-(logp-logbuf),"%s %s\n",fname,str);
00027     logp+=strlen(logp);
00028 }
00029 
00030 void flushlog(void)
00031 {
00032     int n, fd;
00033     n=logp-logbuf; logp=logbuf;
00034     if(n<=0) return;
00035     fd=open(temp_log,O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR);
00036     if(fd==-1) return;
00037     write(fd,logbuf,n); close(fd);
00038 }
00039 
00040        /* Write module log file. */
00041 void module_log(void)
00042 {
00043        /* log string is limited to 100 characters. */
00044     char *logstr, *ip, *sess, lbuf[100], *p;
00045     
00046     if(robot_access || !modlog || strstr(session_prefix,"_check")!=NULL) return;
00047     logstr=getvar("wims_module_log");
00048     if(logstr==NULL || *logstr==0) return;
00049     ip=remote_addr; 
00050     if(mode==mode_default) sess=getvar("wims_session");
00051     else sess="popup";
00052     if(ip==NULL || sess==NULL) return;
00053     mystrncpy(lbuf,logstr,sizeof(lbuf));
00054     p=strchr(sess,'_'); if(p==NULL) p=sess+strlen(sess);
00055     if(p<sess+4) p=sess; else p=p-4;
00056     snprintf(tmplbuf,sizeof(tmplbuf),"%s %.6s %s\11%s",
00057             nowstr, p, ip, lbuf);
00058     p=getvar(ro_name[ro_module]);
00059     if(p==NULL || *p==0) return;
00060     write_logfile(mkfname(NULL,"%s/%s",module_dir,p),tmplbuf);
00061 }
00062 
00063        /* log http referers */
00064 void referer_log(void)
00065 {
00066     char *c,*s,*ip,*r,*h,refstr[256];
00067 
00068     if(robot_access) return;
00069     c=getvar(ro_name[ro_cmd]);
00070     if(c==NULL) c="";
00071     if(mode==mode_default) s=getvar("wims_session"); else s="popup";
00072     if(s==NULL) s="----";
00073     else if(!new_session && strcmp(c,"intro")!=0) return;
00074     if(strlen(s)<4) s="----";
00075     if(strchr(s,'_')!=NULL) return;
00076     ip=remote_addr; if(*ip==0) return;
00077     r=getenv("HTTP_REFERER");
00078     if(r==NULL || *r==0) r="??";
00079        /* skip some useless referers */
00080     else {
00081        if(strstr(r,cgi_name)!=NULL) return;
00082        if(strstr(r,"file:")!=NULL || strchr(r,'.')==NULL) r="??";
00083        if(strstr(r,"http")==NULL && strchr(r,'.')==NULL && 
00084           strstr(r,"bookmark")!=NULL) r="??bookmark";
00085     }
00086     if(strncmp(r,"http://",strlen("http://"))==0) r+=strlen("http://");
00087        /* Take references from the same site or not? No. */
00088     h=getenv("HTTP_HOST");
00089     if(h!=NULL && *h!=0 && strncmp(r,h,strlen(h))==0) return;
00090        /* stop before '#' */
00091     mystrncpy(refstr,r,sizeof(refstr));
00092     r=strchr(refstr,'#'); if(r!=NULL) *r=0;
00093     for(r=refstr;r<refstr+strlen(refstr);r++) {
00094        if(*r=='%' && *(r+1)=='7' && *(r+2)=='E') {
00095            *r='~'; strcpy(r+1,r+3);
00096        }
00097     }
00098     snprintf(tmplbuf,sizeof(tmplbuf),"%s %s %s\11%s",
00099             nowstr,s+strlen(s)-4,ip,refstr);
00100     write_logfile("referer.log",tmplbuf);
00101 }
00102 
00103        /* Log new creation of sessions. For server counting use. */
00104 void session_log(char *c)
00105 {
00106     int i;
00107     char *ip, *p, *agent, *s, *sess;
00108     
00109     ip=remote_addr; if(*ip==0) return;
00110     if(mode==mode_default) {
00111        sess=getvar("wims_session"); 
00112        if(sess==NULL) return;
00113        if(strchr(sess,'_')!=NULL) return;
00114     }
00115     else sess="popup";
00116     p=getenv("REMOTE_HOST"); if(p==NULL) p="";
00117     i=strlen(p); if(i>40) p+=i-40;
00118     agent=getenv("HTTP_USER_AGENT"); if(agent==NULL) agent="";
00119     s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
00120     if(s<sess+4) s=sess; else s=s-4;
00121       /* limit agent name to 40 chars */
00122     snprintf(tmplbuf,sizeof(tmplbuf),"%s %s %s\11%s\11%.40s",
00123             nowstr, s, ip, p, agent);
00124     write_logfile("session.log",tmplbuf);
00125 }
00126 
00127        /* Log user information. */
00128 void user_log(char *c)
00129 {
00130     char fname[MAX_FNAME+1], logbuf[MAX_LINELEN+1], cbuf[256], sbuf[32], shbuf[32];
00131     char *user, *classe, *sh, *sess, *exo, *cc, *ip, *allow, *pend;
00132     char *ex;
00133     double sc,Sc;
00134     int i, scorelog;
00135     
00136     if(robot_access || strstr("session_prefix","_check")!=NULL) return;
00137     user=getvar("wims_user"); classe=getvar("wims_class");
00138     sc=0;
00139     if(isexam) {
00140        if(user==NULL || classe==NULL || *user==0 || *classe==0) return;
00141        sh=getvar("worksheet"); if(sh==NULL) return;
00142        mystrncpy(shbuf,sh,sizeof(shbuf));
00143        exo=strchr(shbuf,'.'); if(exo==NULL) return;
00144        *exo++=0; sh=shbuf;
00145        if(mode==mode_default) sess=getvar("wims_session");
00146        else sess="popup";
00147        if(sess==NULL) return;
00148        mystrncpy(sbuf,sess,sizeof(sbuf));
00149        sess=strchr(sbuf,'_'); if(sess==NULL) return;
00150        *sess=0; sess=sbuf; ex="E";
00151        accessfile(logbuf,"r","%s/.E%s",class_dir,sh);
00152        if(strchr(logbuf,'#')!=NULL || strcmp(user,"supervisor")==0) simuxam=1;
00153        else {
00154            accessfile(logbuf,"r","%s/%s/examsimu.%d", session_dir,sess,sh);
00155            if(strstr(logbuf,"yes")!=NULL) user_error("expired_exam");
00156        }
00157        mkfname(examlogd,"%s/examlog/%s/%s",class_dir,user,sess);
00158        mkfname(examlogf,"%s/%s.%s",examlogd,sh,exo);
00159     }
00160     else {
00161        sh=getvar("wims_sheet");
00162        if(sh==NULL || *sh==0) return;
00163        exo=getvar("wims_exo"); if(exo==NULL) return;
00164        sess=getvar("wims_session");
00165        if(sess==NULL) return;
00166        ex="";
00167     
00168     }
00169     if(strcmp(c,"new")!=0 && strcmp(c,"renew")!=0
00170        && strcmp(c,"rafale")!=0
00171        && strcmp(c,"hint")!=0 && parm_restore==0) {
00172        char *s;
00173        s=getvar("module_score");
00174        if(s==NULL || *s==0) return;
00175        sc=atof(s); if(!finite(sc)) {sc=0; return;}
00176        snprintf(cbuf,sizeof(cbuf),"score %s",s);
00177        cc=cbuf;
00178     }
00179     else cc=c;
00180     if(classe==NULL || *classe==0) i=1;
00181     else i=getscorestatus(classe,atoi(sh));
00182     pend=getvar("wims_scoring"); if(pend==NULL) pend="";
00183     if((i==0 || !exodepOK || strcmp(pend,"pending")!=0) && strcmp(cc,"rafale")!=0)
00184       allow=" noscore";
00185     else allow="";
00186     ip=remote_addr; if(*ip==0) ip="-"; scorelog=0;
00187     if(user==NULL || *user==0) {
00188        classe="0"; allow="";
00189        mkfname(fname,"../sessions/%s/.score",sess);
00190     }
00191     else {
00192        char *pp;
00193        if(classe==NULL || *classe==0) return;
00194        pp=getvar("wims_scorereg");
00195        if((allow[0]==0 || (pp!=NULL && strcmp(pp,"suspend")==0)) && *ex!='E') 
00196          scorelog=1;
00197        else
00198          mkfname(fname,"classes/%s/noscore/%s",classe,user);
00199     }
00200     if(isexam && user!=NULL && *user!=0) {
00201        allow=exam_sheetexo;
00202        snprintf(logbuf,sizeof(logbuf),":%s %2s %s       %s%s\n",
00203                nowstr,exo,cc,ip,allow);
00204        accessfile(logbuf,"a","%s/%s/examscore.%s", session_dir,sess,sh);
00205        Sc=currexamscore(atoi(sh));
00206        accessfile(logbuf,"r","%s/.E%s",class_dir,sh);
00207        if(simuxam==0) {            /* not simulation */
00208            if(sc>0) {
00209               snprintf(logbuf,sizeof(logbuf),
00210                       "%s %.2f -1 %u %s %s\n",
00211                       sh,Sc,(unsigned int) nowtime,ip,sess);
00212               accessfile(logbuf,"a","%s/score/%s.exam",
00213                         class_dir,user);
00214            }
00215        }
00216        else snprintf(exam_sheetexo+strlen(exam_sheetexo),
00217                     sizeof(exam_sheetexo)-strlen(exam_sheetexo),
00218                     "       S");
00219     }
00220     snprintf(logbuf,sizeof(logbuf),"%s%s %s %2s %2s %s         %s%s",
00221             ex,nowstr,sess,sh,exo,cc,ip,allow);
00222     if(scorelog) {
00223        snprintf(tmplbuf,sizeof(tmplbuf),"-c%s -u%s scorelog %s",
00224                classe,user,logbuf);
00225        _daemoncmd(tmplbuf);
00226     }
00227     else write_logfile(fname,logbuf);
00228 }
00229 
00230        /* Log class information. */
00231 void class_log(char *cl, char *l, char *ip)
00232 {
00233     char logbuf[1024];
00234     
00235     if(robot_access) return;
00236     snprintf(logbuf,sizeof(logbuf),"%s %s        %s",
00237             nowstr,ip,l);
00238     write_logfile(mkfname(NULL,"classes/%s/.log",cl),logbuf);
00239 }
00240 
00241        /* Log accesses to modules. For server counting use. */
00242 void access_log(char *c)
00243 {
00244     int i;
00245     char *ip, *p, *sess, *s, *agent, *u, *cl;
00246     time_t logtime;
00247     char ag[128], tm[64];
00248     
00249     ip=remote_addr; 
00250     if(*ip==0) ip="????????";
00251     if(mode==mode_default) sess=getvar("wims_session");
00252     else sess="popup";
00253     if(sess==NULL) sess="----------";
00254     p=getvar(ro_name[ro_module]);
00255     if(p==NULL || *p==0) p="-";
00256       /* limit module name to 40 chars */
00257     i=strlen(p); if(i>40) p+=i-40;
00258     if(robot_access) {
00259        agent=getenv("HTTP_USER_AGENT"); if(agent==NULL) agent="-";
00260        snprintf(ag,sizeof(ag)," %s",agent);
00261     }
00262     else {
00263        u=getvar("wims_user");
00264        if(u!=NULL && *u!=0) snprintf(ag,sizeof(ag)," %s,%s",u,getvar("wims_class"));
00265        else ag[0]=0;
00266     }
00267     s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
00268     if(s<sess+4) s=sess; else s=s-4;
00269     tm[0]=0; logtime=time(0); if(logtime>nowtime+2) {
00270        snprintf(tm,sizeof(tm)," (%lus)", logtime-nowtime);
00271     }
00272     snprintf(tmplbuf,sizeof(tmplbuf),"%s %.6s %s\11%s\11%s%s%s",
00273             nowstr, s, ip, c, p, tm, ag);
00274     write_logfile("access.log",tmplbuf);
00275     user_log(c);
00276     cl=getvar("wims_class");
00277     if(cl!=NULL && *cl!=0) {
00278        char *l;
00279        l=getvar("wims_class_log");
00280        if(l!=NULL && *l!=0) class_log(cl, l, ip);
00281     }
00282 }
00283 
00284        /* Log of mails. */
00285 void mail_log(char *c)
00286 {
00287     int i;
00288     char *ip, *p, *sess, *s, *cl;
00289     
00290     ip=remote_addr; 
00291     if(*ip==0) ip="????????";
00292     if(mode==mode_default) sess=getvar("wims_session");
00293     else sess="popup";
00294     if(sess==NULL) sess="----------";
00295     p=getvar(ro_name[ro_module]);
00296     if(p==NULL || *p==0) p="-";
00297       /* limit module name to 40 chars */
00298     i=strlen(p); if(i>40) p+=i-40;
00299     s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
00300     if(s<sess+4) s=sess; else s=s-4;
00301     cl=getvar("wims_class"); if(cl==NULL) cl="";
00302     snprintf(tmplbuf,sizeof(tmplbuf),"%s %.6s %s\11%s\11%s\11%s",
00303             nowstr, s, ip, c, cl, p);
00304     write_logfile("mail.log",tmplbuf);
00305 }
00306 
00307        /* log posted data */
00308 void post_log(void)
00309 {
00310     char *h, *l, logstr[2*MAX_LINELEN+2];
00311 
00312     h=remote_addr;
00313     if(mpboundary[0]!=0) l="multipart/form-data"; else l=stdinbuf;
00314     snprintf(logstr,sizeof(logstr),"%s %s %s",
00315            nowstr, h, l);
00316     write_logfile("post.log",logstr);
00317 }
00318 
00319        /* It is this routine which is called by main(). */
00320 void write_logs(void)
00321 {
00322     char *p;
00323     p=getvar(ro_name[ro_cmd]); if(p==NULL || *p==0) p="no_cmd";
00324     access_log(p); if(strstr(session_prefix,"_check")!=NULL) return;
00325     module_log(); referer_log();
00326     if(new_session) session_log(p);
00327 }
00328 
00329 void user_error_log(char msg[])
00330 {
00331     char *s, *m, *c, *h, *q, *r, *sess, logstr[512];
00332     if(mode==mode_default) sess=getvar("wims_session");
00333     else sess="popup";
00334     if(sess==NULL) sess="----------";
00335     m=getvar(ro_name[ro_module]);if(m==NULL) m="";
00336     c=getvar(ro_name[ro_cmd]);if(c==NULL) c="";
00337     h=remote_addr;
00338     q=getenv("QUERY_STRING");if(q==NULL) q="";
00339     r=getenv("HTTP_REFERER");
00340     if(r==NULL || strstr(r,cgi_name)!=NULL) r="";
00341     s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
00342     if(s<sess+4) s=sess; else s=s-4;
00343     snprintf(logstr,sizeof(logstr),"%s %.5s %s %s, module=%s cmd=%s: %s %s",
00344            nowstr, s, h, msg, m, c, r, q);
00345     write_logfile("user_error.log",logstr);
00346     if(user_error_nolog) return;
00347     access_log("user_error");referer_log();
00348 }
00349 
00350 void module_error_log(char msg[])
00351 {
00352     char *s, *m, *c, logstr[256];
00353     if(strstr(msg,"debug")!=NULL || strstr(msg,"timeup")!=NULL) return;
00354     if(strstr(m_file.name,"sessions/")!=NULL) return;
00355     s=getvar(ro_name[ro_module]);
00356     if(s!=NULL) {
00357        if(strncmp(s,"classes/",strlen("classes/"))==0 ||
00358           strncmp(s,"devel/",strlen("devel/"))==0) return;
00359     }
00360     s=getvar("wims_session"); if(s==NULL) s="    ";
00361     m=getvar(ro_name[ro_module]);if(m==NULL) m="";
00362     c=getvar(ro_name[ro_cmd]);if(c==NULL) c="";
00363     snprintf(logstr,sizeof(logstr),"%s %.10s %s in %s/%s, line %d",
00364            nowstr, s+2, msg, m, m_file.name, m_file.l+1);
00365     write_logfile("module_error.log",logstr);
00366     access_log("module_error");
00367 }
00368 
00369        /* Refused users due to threshold excess */
00370 void refuse_log(int th)
00371 {
00372     char *load, *h;
00373     
00374     load=getvar("wims_server_load"); if(load==NULL) load="??";
00375     h=remote_addr;
00376     snprintf(tmplbuf,sizeof(tmplbuf),"%s %s\11%d:%s",
00377             nowstr, h, th, load);
00378     write_logfile("refuse.log",tmplbuf);
00379 }
00380 
00381 #define logdpid "../tmp/log/wimslogd.pid"
00382 #define newlogd "../tmp/log/wimslogd.new"
00383 
00384 void bringuplogd(void)
00385 {
00386     char *arg[]={"../bin/wimslogd",NULL};
00387     struct stat st;
00388     pid_t pid;
00389 
00390        /* need to update wimslogd? */
00391     if(stat(newlogd,&st)==0) {
00392        if((S_IXUSR&st.st_mode)!=0 && st.st_size>40000 && st.st_size<200000)
00393          call_ssh("mv %s %s",newlogd,arg[0]);
00394        else call_ssh("rm -f %s",newlogd);
00395     }
00396     pid=fork(); if(pid) return;    /* parent */
00397        /* double fork to escape sysmask orphan. */
00398     pid=fork(); if(pid) {   /* secondary parent */
00399        snprintf(tmplbuf,sizeof(tmplbuf),"%u",pid);
00400        mkdirs("../tmp/log");
00401        chmod("../tmp/log",S_IRUSR|S_IWUSR|S_IXUSR);
00402        accessfile(tmplbuf,"w",logdpid);
00403        exit(0);
00404     }
00405     setreuid(geteuid(),geteuid());setregid(getegid(),getegid());
00406     snprintf(tmplbuf,sizeof(tmplbuf),"%u %u %u %u %u %u %d %d %d",
00407             idle_time,idle_time2,idle_time3,
00408             OLD_LOG_FILES,GEN_LOG_LIMIT,
00409             MODULE_LOG_LIMIT,backup_hour,site_accounting,
00410             examlog_limit);
00411     
00412     setenv("wimslogd",tmplbuf,1);
00413     execve(arg[0],arg,environ);
00414     fprintf(stderr,"Unable to execute wimslogd: %s\n",strerror(errno));
00415     exit(1);
00416 }
00417 
00418 void checklogd(void)
00419 {
00420     int i,t;
00421     char *p1, *p2, *p, buf[MAX_LINELEN+1];
00422     sun.sun_family=PF_UNIX;
00423     snprintf(sun.sun_path,sizeof(sun.sun_path),"%s",ksockfile);
00424     p=getenv("REMOTE_ADDR"); if(p==NULL) p="";
00425     snprintf(buf+sizeof(int),sizeof(buf)-sizeof(int),"ping %s",p);
00426     t=kerneld(buf,sizeof(buf)); if(t<0) {
00427        bringuplogd();
00428        for(i=0; i<10 && t<0; i++) {
00429            msleep(100);
00430            snprintf(buf+sizeof(int),sizeof(buf)-sizeof(int),"ping %s",p);
00431            t=kerneld(buf,sizeof(buf));
00432        }
00433     }
00434     if(t<0) internal_error("Unable to bring up wimslogd.");
00435     p1=find_word_start(buf+sizeof(int)); p2=find_word_end(p1);
00436     if(*p2) *p2++=0;
00437     if(strcmp(p1,"OK")!=0) internal_error("wimslogd error.");
00438     if(*p2=='1') hostcquota=1; else hostcquota=0;
00439     p1=find_word_start(find_word_end(p2));
00440     p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1);
00441     mystrncpy(loadavg,p1,sizeof(loadavg));
00442     p2=find_word_start(p2);
00443     p1=find_word_end(p2); if(*p1) *p1++=0;
00444     
00445     p=getenv("SERVER_ADDR");
00446     if(*p2!=0 && memcmp(p,"10.",3)==0) p=p2;
00447     if(p!=NULL) {
00448        i=strlen(cookieheader);
00449        snprintf(cookieheader+i, sizeof(cookieheader)-i,"%s/",p);
00450     }
00451     p=getenv("HTTP_COOKIE"); cookiegot[0]=0;
00452     if(p!=NULL && (p2=strstr(p,cookieheader))!=NULL) {
00453        mystrncpy(cookiegot,find_word_start(p+strlen(cookieheader)),sizeof(cookiegot));
00454        *find_word_end(cookiegot)=0;
00455     }
00456 }
00457