Back to index

wims  3.65+svn20090927
var.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 
00018        /* Low-level variable management routines. */
00019 
00020 #define VARBUF_LEN   (256*1024)
00021 #define VARBUF_NUM   16
00022 #define VARNAME_LEN  32768
00023 #define VARNUM_LIMIT 2048
00024 #define vb_internal  1
00025 #define vb_ro        2
00026 #define vb_dirty     4
00027 #define vb_noexport  8
00028 #define vb_hacked    16
00029 
00030 char *_varbuf[VARBUF_NUM];  /* main variable value buffer */
00031 char *_varptr;
00032 int _varbufcurr;
00033 char *_varnamebuf, *_varnameptr; /* variable name buffer */
00034 
00035        /* wims_ variables that should be exported */
00036 char *exportvars[]={
00037       "class",
00038       "deposit",
00039       "home",
00040       "inssub",
00041       "sesdir",
00042       "session",
00043       "site_languages",
00044       "supervisor",
00045       "supervisormail",
00046       "tmp_debug",
00047       "user",
00048       "version",
00049 };
00050 #define exportvarcnt (sizeof(exportvars)/sizeof(exportvars[0]))
00051 
00052 struct vartab {
00053     char *name, *val;
00054     unsigned short int vlen;
00055     char tag,lvl;
00056 } fastvartab[128], mainvartab[VARNUM_LIMIT];
00057 
00058 /* int vlenmin[]={0,1,20,45,       100,200,400,800,     1500,3000,6000}; */
00059 int vlenmax[]={1,32,64,128, 256,512,1024,2048,   4096,8192,MAX_LINELEN+1};
00060 int freelim[]={1,500,500,300,      200,150,100,80,             60,50,30};
00061 #define lvlno (sizeof(vlenmax)/sizeof(vlenmax[0]))
00062 #define freevtot (1+500+500+300 +200+150+100+80        +60+50+30)
00063 
00064 int freevars[lvlno], freevstart[lvlno];
00065 int freevcnt=0,bufvcnt=0;
00066 char *freevbuf[freevtot];
00067 int mainvarcnt=0;
00068 void add_hack(char *name);
00069 
00070 void get_var_privileges(void)
00071 {
00072     int sav=untrust;
00073     untrust=0;
00074     var_readable=getvar("wims_readable");
00075     var_writable=getvar("wims_writable");
00076     var_nr=getvar("wims_nr");
00077     var_nw=getvar("wims_nw");
00078     var_pfx=getvar("wims_prefix");
00079     untrust=sav;
00080 }
00081 
00082        /* Returns 1 if rights OK. Else 0. */
00083 int var_checkright(char *name, char *allow, char *deny, char *prefix)
00084 {
00085     if(strcmp(name,"wims_read_parm")==0) return 1;
00086     if(allow!=NULL && allow[0]!=0 && wordchr(allow,name)!=NULL) return 1;
00087     if(deny!=NULL && deny[0]!=0 && wordchr(deny,name)!=NULL) return 0;
00088     if(prefix!=NULL && prefix[0]!=0) {
00089        char *p, buf[MAX_NAMELEN+1];
00090        for(p=name; *p!=0 && *p!='_'; p++);
00091        if(*p!='_' || p-name>=MAX_NAMELEN) return 0;
00092        memmove(buf,name,p-name); buf[p-name]=0;
00093        if(wordchr(prefix,buf)==NULL) return 0;
00094     }
00095     return 1;
00096 }
00097 
00098        /* initialisation */
00099 void var_init(void)
00100 {
00101     int i,j;
00102     memset(freevars,0,sizeof(freevars));
00103     _varbufcurr=0;
00104     _varbuf[0]=xmalloc(VARBUF_LEN);
00105     _varnamebuf=xmalloc(VARNAME_LEN);
00106     _varptr=_varbuf[0]; _varnameptr=_varnamebuf;
00107     for(i=j=0;i<lvlno;i++) {freevstart[i]=j; j+=freelim[i];}
00108     if(j!=freevtot) internal_error("var.c: wrong count freevtot!");
00109 }
00110 
00111 void exportall(void)
00112 {
00113     int i, j, tag; char buf[MAX_NAMELEN+17];
00114     char *p, *p1, *p2;
00115     char *noexpword[1024];
00116     int noexplen[1024];
00117     int noexpcnt;
00118     
00119     noexpcnt=0;
00120     p=getvar("wims_noexport"); if(p==NULL) p="";
00121     for(p1=find_word_start(p),noexpcnt=0;
00122        *p1 && noexpcnt<1024;
00123        p1=find_word_start(p2)) {
00124        p2=find_word_end(p1);
00125        noexpword[noexpcnt]=p1; noexplen[noexpcnt]=p2-p1;
00126        noexpcnt++;
00127     }
00128     for(i=0;i<mainvarcnt;i++) {
00129        tag=mainvartab[i].tag;
00130        if((tag&vb_dirty)==0 || (tag&vb_noexport)!=0) continue;
00131        p=mainvartab[i].name;
00132        for(j=0;j<noexpcnt;j++) if(strncmp(p,noexpword[j],noexplen[j])==0) {
00133            mainvartab[i].tag|=vb_noexport;
00134            goto lend;
00135        }
00136        if(mainvartab[i].tag&vb_hacked) {
00137            add_hack(p); mainvartab[i].tag&=~vb_hacked;
00138        }
00139        snprintf(buf,sizeof(buf),"%s%s",var_prefix,p);
00140        setenv(buf,mainvartab[i].val,1);
00141        mainvartab[i].tag&=~vb_dirty;
00142 lend:  ;
00143     }
00144 }
00145 
00146 char *vaskbuf(int lvl)
00147 {
00148     char *p;
00149     if(lvl>=lvlno) { /* should never occur */
00150        module_error("Internal_variable_length_overflow"); return NULL;
00151     }
00152     if(freevars[lvl]>0) {
00153        freevars[lvl]--; freevcnt--;
00154        return freevbuf[freevstart[lvl]+freevars[lvl]];
00155     }
00156     if(_varptr+vlenmax[lvl]>=_varbuf[_varbufcurr]+VARBUF_LEN) {
00157        if(_varbufcurr>=VARBUF_NUM) {
00158            module_error("variable_buffer_overflow"); return NULL;
00159        }
00160        _varbufcurr++; _varptr=_varbuf[_varbufcurr]=xmalloc(VARBUF_LEN);
00161     }
00162     bufvcnt++;
00163     p=_varptr; _varptr+=vlenmax[lvl]; return p;
00164 }
00165 
00166        /* returns 1 if free succeeded. */
00167 int vfreebuf(int lvl, char *p)
00168 {
00169     if(p>=_varptr) return 0;
00170     if(p+vlenmax[lvl]==_varptr) {_varptr=p; bufvcnt--;return 1;}
00171     if(lvl<=0 || lvl>=lvlno || freevars[lvl]>=freelim[lvl]) return 0;
00172     freevcnt++;
00173     freevbuf[freevstart[lvl]+freevars[lvl]]=p; freevars[lvl]++; return 1;
00174 }
00175 
00176 int _char_int(char *vn)
00177 {
00178     int t; char v;
00179     v=vn[0]; if(vn[1]) t=64; else t=0;
00180     if(v>='0' && v<='9') return v-'0'+t;
00181     else {
00182        if(v>='A' && v<='Z') return v-'A'+10+t;
00183        else {
00184            if(v>='a' && v<='z') return v-'a'+10+26+t;
00185            else return -1;
00186        }
00187     }
00188 }
00189 
00190 int var_ins(char *name,int inspoint)
00191 {
00192     int i, nlen, tag;
00193     if(mainvarcnt>=VARNUM_LIMIT) {
00194        module_error("too_many_variable_names"); return -1;
00195     }
00196     for(nlen=0;nlen<=MAX_NAMELEN && (myisalnum(name[nlen]) || name[nlen]=='_');nlen++);
00197     if(nlen<=1 || nlen>MAX_NAMELEN || name[nlen]!=0) return -1;
00198     if(_varnameptr+nlen+1>_varnamebuf+VARNAME_LEN) {
00199        module_error("variable_name_buffer_overflow"); return -1;
00200     }
00201     tag=0;
00202     if(search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),name)>=0)
00203       tag|=vb_ro;
00204     if(nlen<=2 || strncmp(name,mathfont_prefix,strlen(mathfont_prefix))==0 ||
00205        name[nlen-1]=='_')
00206       tag|=vb_noexport;
00207     if(var_noexport) tag|=vb_noexport;
00208     if(name[0]=='w' && strncmp(name,wims_prefix,wpflen)==0) {
00209        if(search_list(exportvars,exportvarcnt,sizeof(exportvars[0]),name+wpflen)<0)
00210          tag|=vb_noexport;
00211        if(strncmp(name+wpflen,"priv_",strlen("priv_"))==0 || 
00212           search_list(internal_name,INTERNAL_NAME_NO,sizeof(internal_name[0]),name+wpflen)>=0)
00213          tag|=vb_internal;
00214     }
00215     i=inspoint; if(i>mainvarcnt) i=mainvarcnt; if(i<0) i=0;
00216     memmove(mainvartab+i+1,mainvartab+i,(mainvarcnt-i)*sizeof(mainvartab[0]));
00217     mainvarcnt++; nlen++;
00218     memmove(_varnameptr,name,nlen);
00219     mainvartab[i].name=_varnameptr; _varnameptr+=nlen;
00220     mainvartab[i].val=NULL; mainvartab[i].vlen=0;
00221     mainvartab[i].tag=tag;
00222     mainvartab[i].lvl=0; return i;
00223 }
00224 
00225 char *fast_getvar(char *vname)
00226 {
00227     int n;
00228 
00229     n=_char_int(vname); if(n<0) return "";
00230     if(fastvartab[n].tag&vb_hacked) {
00231        add_hack(vname); fastvartab[n].tag&=~vb_hacked;
00232     }
00233     getvar_len=fastvartab[n].vlen;
00234     return fastvartab[n].val;
00235 }
00236 
00237 int _setvar_(struct vartab *vtb, char *vval)
00238 {
00239     int l,lvl;
00240     char *p;
00241     if(vval) l=strlen(vval); else l=0;
00242     if(l>MAX_LINELEN) return 1;
00243     lvl=vtb->lvl;
00244     if(l==0) {
00245        if(lvl>0) {
00246            vfreebuf(lvl,vtb->val); vtb->tag|=vb_dirty;
00247            if(var_hacking) vtb->tag|=vb_hacked; else vtb->tag&=~vb_hacked;
00248            vtb->lvl=0; vtb->vlen=0;
00249        }
00250        if(vval) vtb->val=""; else vtb->val=NULL;
00251        return 0;
00252     }
00253     if(l>=vlenmax[lvl]) {
00254        vfreebuf(lvl,vtb->val);
00255        do lvl++; while(l>=vlenmax[lvl]);
00256        vtb->lvl=lvl;
00257        vtb->val=p=vaskbuf(lvl);
00258     }
00259     else p=vtb->val;
00260     vtb->vlen=l; vtb->tag|=vb_dirty;
00261     if(var_hacking) vtb->tag|=vb_hacked; else vtb->tag&=~vb_hacked;
00262     memmove(p,vval,++l); return 0;
00263 }
00264 
00265 int fast_setvar(char *vname, char *vval)
00266 {
00267     int n;
00268     
00269     n=_char_int(vname); if(n<0) return 1;
00270     return _setvar_(fastvartab+n,vval);
00271 }
00272 
00273        /* internal constant */
00274 int setvar_force=0;
00275 
00276        /* Set a user variable. Now it no longer uses environment.
00277         * Returns 0 if OK. */
00278 int setvar(char *vname, char *vvalue)
00279 {
00280     int i,overwrite,tag;
00281     
00282     if(vname[0]==0) return 1;
00283     if((vname[1]==0 || (vname[1]=='_' && vname[2]==0)))
00284       return fast_setvar(vname,vvalue);
00285     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
00286     if(i<0) i=var_ins(vname,~i);
00287     if(i<0) return 1;       /* error */
00288     overwrite=1; tag=mainvartab[i].tag;
00289     if(setvar_force==0 && confset==0) {
00290               /* user file has no right to modify wims variables. */
00291        if((untrust&6)!=0) {
00292            if(var_checkright(vname,var_writable,var_nw,var_pfx)==0)
00293              return 1;
00294            if(strncmp(vname,wims_prefix,wpflen)==0 &&
00295               strcmp(vname,"wims_read_parm")!=0) return 1;
00296        }
00297        if((tag&vb_ro)!=0) overwrite=0;
00298        else if((tag&vb_internal)!=0 && !trusted_module()) return 1;
00299     }
00300     if(!overwrite && mainvartab[i].val!=NULL) return 1;
00301     _setvar_(mainvartab+i,vvalue);
00302     if(vname[0]=='w') {
00303        if(strcmp(vname,"wims_print_precision")==0) {
00304            int a=atoi(vvalue);
00305            if(a>0 && a<100) print_precision=a;
00306        }
00307        if(strcmp(vname,"wims_backslash_insmath")==0) {
00308            if(strcasecmp(vvalue,"yes")==0) backslash_insmath=1;
00309            else backslash_insmath=0;
00310        }
00311     }
00312     return 0;
00313 }
00314 
00315 int force_setvar(char *vname,char *vvalue)
00316 {
00317     int i;
00318     setvar_force=1; i=setvar(vname,vvalue); setvar_force=0; return i;
00319 }
00320 
00321 void unsetvar(char *vname)
00322 {
00323     int i;
00324     if(vname[0]!=0 && (vname[1]==0 || (vname[1]=='_' && vname[2]==0))) {
00325        fast_setvar(vname,NULL); return;
00326     }
00327     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
00328     if(i>=0) _setvar_(mainvartab+i,NULL);
00329 }
00330 
00331 #include "mathfonts.c"
00332 
00333        /* Get a variable's value. */
00334 char *_getvar(char *vname)
00335 {
00336     char *val;
00337     int i;
00338 
00339     if((untrust&4)!=0 || vname[0]==0) return ""; /* called from !readdef */
00340     if(vname[1]==0 || (vname[1]=='_' && vname[2]==0)) return fast_getvar(vname);
00341     if((untrust&6)!=0) {
00342        if(var_checkright(vname,var_readable,var_nr,var_pfx)==0)
00343          return "";
00344     }
00345     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
00346     if(i<0) val=NULL; else {
00347        if(mainvartab[i].tag&vb_hacked) {
00348            add_hack(vname); mainvartab[i].tag&=~vb_hacked;
00349        }
00350        val=mainvartab[i].val; getvar_len=mainvartab[i].vlen;
00351     }
00352     if(vname[0]=='w' && strcmp(vname,"wims_incremental")==0) {
00353        static char buf[32];
00354        if(val==NULL) i=0;
00355        else i=atoi(val)+1;
00356        mystrncpy(buf,int2str(i),sizeof(buf));
00357        force_setvar(vname,buf); getvar_len=strlen(buf); val=buf;
00358     }
00359     return val;
00360 }
00361 
00362 char *getvar(char *vname)
00363 {
00364     char *val;
00365     getvar_len=0; val=_getvar(vname);
00366     if(val==NULL && memcmp(vname,mathfont_prefix,strlen(mathfont_prefix))==0) {
00367        val=mathfont(vname);
00368        if(val) getvar_len=strlen(val); else getvar_len=0;
00369     }
00370     return val;
00371 }
00372 
00373        /* Search variables with numeric subscripts, from beg to end.
00374         * Store result to pbuf. Returns number of variables found. */
00375 int varsuite(char *stem, int beg, int end, char *pbuf[], int pbuflen)
00376 {
00377     int i,t,l,v;
00378     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),stem);
00379     if(i<0) i=~i;
00380     for(t=0,l=strlen(stem);i<mainvarcnt && t<pbuflen;i++){
00381        if(strncmp(mainvartab[i].name,stem,l)!=0) break;
00382        v=atoi(mainvartab[i].name+l); if(v<beg || v>end) continue;
00383        if(mainvartab[i].val==NULL || mainvartab[i].val[0]==0) continue;
00384        pbuf[t++]=mainvartab[i].name;
00385     }
00386     return t;
00387 }
00388 
00389        /* output debug information */
00390 void debug_output(void)
00391 {
00392     long int endmtime2, time1;
00393     struct timeval tv;
00394     struct rusage us;
00395 
00396     if(noout || robot_access || strcasecmp(tmp_debug,"yes")!=0 ||
00397        checkhost(manager_site)<1) return;
00398     if(instex_cnt>0) instex_flush();
00399     if(gettimeofday(&tv,NULL)) endmtime2=0;
00400     else endmtime2=((tv.tv_sec%1000)*1000000+tv.tv_usec);
00401     endmtime2=(endmtime2-startmtime2)/100;
00402     time1=0;
00403     if(getrusage(RUSAGE_SELF,&us)==0) {
00404        time1+=us.ru_utime.tv_sec*1000+us.ru_utime.tv_usec/1000;
00405        time1+=us.ru_stime.tv_sec*1000+us.ru_stime.tv_usec/1000;
00406     }
00407     if(getrusage(RUSAGE_CHILDREN,&us)==0) {
00408        time1+=us.ru_utime.tv_sec*1000+us.ru_utime.tv_usec/1000;
00409        time1+=us.ru_stime.tv_sec*1000+us.ru_stime.tv_usec/1000;
00410     }
00411     snprintf(tmplbuf,sizeof(tmplbuf),"%d,%d,%d,%.4f,%.2f,%d,%d,%d",
00412             _varptr-_varbuf[_varbufcurr]+_varbufcurr*VARBUF_LEN,
00413             bufvcnt-freevcnt,freevcnt,
00414             (double) endmtime2/10000, (double) time1/1000,
00415             mcachecnt,mfilecnt,execnt);
00416     setvar("wims_debug_info",tmplbuf);
00417     lastout_file=-1; phtml_put_base("debug.phtml",0);
00418 }
00419 
00420        /* Add to list of hacked variables */
00421 void add_hack(char *name)
00422 {
00423     char buf[MAX_LINELEN+1];
00424     char *p;
00425     p=getvar("wims_hacked_variables"); if(p==NULL) buf[0]=0;
00426     else snprintf(buf,sizeof(buf),"%s",p);
00427     p=buf+strlen(buf);
00428     if(p-buf >= sizeof(buf)-strlen(name)-4) return; /* too long */
00429     if(p>buf) snprintf(p,sizeof(buf)-(p-buf),", %s",name);
00430     else snprintf(buf,sizeof(buf),"%s",name);
00431     setvar("wims_hacked_variables",buf);
00432 }
00433