Subversion Repositories wimsdev

Rev

Rev 2792 | Rev 7673 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18.         /* Low-level variable management routines. */
  19.  
  20. #define VARBUF_LEN      (256*1024)
  21. #define VARBUF_NUM      16
  22. #define VARNAME_LEN     32768
  23. #define VARNUM_LIMIT    4096
  24. #define vb_internal     1
  25. #define vb_ro           2
  26. #define vb_dirty        4
  27. #define vb_noexport     8
  28. #define vb_hacked       16
  29.  
  30. char *_varbuf[VARBUF_NUM];      /* main variable value buffer */
  31. char *_varptr;
  32. int _varbufcurr;
  33. char *_varnamebuf, *_varnameptr; /* variable name buffer */
  34.  
  35.         /* wims_ variables that should be exported */
  36. char *exportvars[]={
  37.       "class",
  38.       "deposit",
  39.       "home",
  40.       "inssub",
  41.       "sesdir",
  42.       "session",
  43.       "site_languages",
  44.       "supervisor",
  45.       "supervisormail",
  46.       "tmp_debug",
  47.       "user",
  48.       "version",
  49. };
  50. #define exportvarcnt (sizeof(exportvars)/sizeof(exportvars[0]))
  51.  
  52. struct vartab {
  53.     char *name, *val;
  54.     unsigned short int vlen;
  55.     char tag,lvl;
  56. } fastvartab[128], mainvartab[VARNUM_LIMIT];
  57.  
  58. /* int vlenmin[]={0,1,20,45,    100,200,400,800,        1500,3000,6000}; */
  59. int vlenmax[]={1,32,64,128,     256,512,1024,2048,      4096,8192,MAX_LINELEN+1};
  60. int freelim[]={1,500,500,300,   200,150,100,80,         60,50,30};
  61. #define lvlno (sizeof(vlenmax)/sizeof(vlenmax[0]))
  62. #define freevtot (1+500+500+300 +200+150+100+80        +60+50+30)
  63.  
  64. int freevars[lvlno], freevstart[lvlno];
  65. int freevcnt=0,bufvcnt=0;
  66. char *freevbuf[freevtot];
  67. int mainvarcnt=0;
  68. void add_hack(char *name);
  69.  
  70. void get_var_privileges(void)
  71. {
  72.     int sav=untrust;
  73.     untrust=0;
  74.     var_readable=getvar("wims_readable");
  75.     var_writable=getvar("wims_writable");
  76.     var_nr=getvar("wims_nr");
  77.     var_nw=getvar("wims_nw");
  78.     var_pfx=getvar("wims_prefix");
  79.     untrust=sav;
  80. }
  81.  
  82.         /* Returns 1 if rights OK. Else 0. */
  83. int var_checkright(char *name, char *allow, char *deny, char *prefix)
  84. {
  85.     if(strcmp(name,"wims_read_parm")==0) return 1;
  86.     if(allow!=NULL && allow[0]!=0 && wordchr(allow,name)!=NULL) return 1;
  87.     if(deny!=NULL && deny[0]!=0 && wordchr(deny,name)!=NULL) return 0;
  88.     if(prefix!=NULL && prefix[0]!=0) {
  89.         char *p, buf[MAX_NAMELEN+1];
  90.         for(p=name; *p!=0 && *p!='_'; p++);
  91.         if(*p!='_' || p-name>=MAX_NAMELEN) return 0;
  92.         memmove(buf,name,p-name); buf[p-name]=0;
  93.         if(wordchr(prefix,buf)==NULL) return 0;
  94.     }
  95.     return 1;
  96. }
  97.  
  98.         /* initialisation */
  99. void var_init(void)
  100. {
  101.     int i,j;
  102.     memset(freevars,0,sizeof(freevars));
  103.     _varbufcurr=0;
  104.     _varbuf[0]=xmalloc(VARBUF_LEN);
  105.     _varnamebuf=xmalloc(VARNAME_LEN);
  106.     _varptr=_varbuf[0]; _varnameptr=_varnamebuf;
  107.     for(i=j=0;i<lvlno;i++) {freevstart[i]=j; j+=freelim[i];}
  108.     if(j!=freevtot) internal_error("var.c: wrong count freevtot!");
  109. }
  110.  
  111. void exportall(void)
  112. {
  113.     int i, j, tag; char buf[MAX_NAMELEN+17];
  114.     char *p, *p1, *p2;
  115.     char *noexpword[1024];
  116.     int noexplen[1024];
  117.     int noexpcnt;
  118.    
  119.     noexpcnt=0;
  120.     p=getvar("wims_noexport"); if(p==NULL) p="";
  121.     for(p1=find_word_start(p),noexpcnt=0;
  122.         *p1 && noexpcnt<1024;
  123.         p1=find_word_start(p2)) {
  124.         p2=find_word_end(p1);
  125.         noexpword[noexpcnt]=p1; noexplen[noexpcnt]=p2-p1;
  126.         noexpcnt++;
  127.     }
  128.     for(i=0;i<mainvarcnt;i++) {
  129.         tag=mainvartab[i].tag;
  130.         if((tag&vb_dirty)==0 || (tag&vb_noexport)!=0) continue;
  131.         p=mainvartab[i].name;
  132.         for(j=0;j<noexpcnt;j++) if(strncmp(p,noexpword[j],noexplen[j])==0) {
  133.             mainvartab[i].tag|=vb_noexport;
  134.             goto lend;
  135.         }
  136.         if(mainvartab[i].tag&vb_hacked) {
  137.             add_hack(p); mainvartab[i].tag&=~vb_hacked;
  138.         }
  139.         snprintf(buf,sizeof(buf),"%s%s",var_prefix,p);
  140.         setenv(buf,mainvartab[i].val,1);
  141.         mainvartab[i].tag&=~vb_dirty;
  142. lend:   ;
  143.     }
  144. }
  145.  
  146. char *vaskbuf(int lvl)
  147. {
  148.     char *p;
  149.     if(lvl>=lvlno) {    /* should never occur */
  150.         module_error("Internal_variable_length_overflow"); return NULL;
  151.     }
  152.     if(freevars[lvl]>0) {
  153.         freevars[lvl]--; freevcnt--;
  154.         return freevbuf[freevstart[lvl]+freevars[lvl]];
  155.     }
  156.     if(_varptr+vlenmax[lvl]>=_varbuf[_varbufcurr]+VARBUF_LEN) {
  157.         if(_varbufcurr>=VARBUF_NUM) {
  158.             module_error("variable_buffer_overflow"); return NULL;
  159.         }
  160.         _varbufcurr++; _varptr=_varbuf[_varbufcurr]=xmalloc(VARBUF_LEN);
  161.     }
  162.     bufvcnt++;
  163.     p=_varptr; _varptr+=vlenmax[lvl]; return p;
  164. }
  165.  
  166.         /* returns 1 if free succeeded. */
  167. int vfreebuf(int lvl, char *p)
  168. {
  169.     if(p>=_varptr) return 0;
  170.     if(p+vlenmax[lvl]==_varptr) {_varptr=p; bufvcnt--;return 1;}
  171.     if(lvl<=0 || lvl>=lvlno || freevars[lvl]>=freelim[lvl]) return 0;
  172.     freevcnt++;
  173.     freevbuf[freevstart[lvl]+freevars[lvl]]=p; freevars[lvl]++; return 1;
  174. }
  175.  
  176. int _char_int(char *vn)
  177. {
  178.     int t; char v;
  179.     v=vn[0]; if(vn[1]) t=64; else t=0;
  180.     if(v>='0' && v<='9') return v-'0'+t;
  181.     else {
  182.         if(v>='A' && v<='Z') return v-'A'+10+t;
  183.         else {
  184.             if(v>='a' && v<='z') return v-'a'+10+26+t;
  185.             else return -1;
  186.         }
  187.     }
  188. }
  189.  
  190. int var_ins(char *name,int inspoint)
  191. {
  192.     int i, nlen, tag;
  193.     if(mainvarcnt>=VARNUM_LIMIT) {
  194.         module_error("too_many_variable_names"); return -1;
  195.     }
  196.     for(nlen=0;nlen<=MAX_NAMELEN && (myisalnum(name[nlen]) || name[nlen]=='_');nlen++);
  197.     if(nlen<=1 || nlen>MAX_NAMELEN || name[nlen]!=0) return -1;
  198.     if(_varnameptr+nlen+1>_varnamebuf+VARNAME_LEN) {
  199.         module_error("variable_name_buffer_overflow"); return -1;
  200.     }
  201.     tag=0;
  202.     if(search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),name)>=0)
  203.       tag|=vb_ro;
  204.     if(nlen<=2 || strncmp(name,mathfont_prefix,strlen(mathfont_prefix))==0 ||
  205.        name[nlen-1]=='_')
  206.       tag|=vb_noexport;
  207.     if(var_noexport) tag|=vb_noexport;
  208.     if(name[0]=='w' && strncmp(name,wims_prefix,wpflen)==0) {
  209.         if(search_list(exportvars,exportvarcnt,sizeof(exportvars[0]),name+wpflen)<0)
  210.           tag|=vb_noexport;
  211.         if(strncmp(name+wpflen,"priv_",strlen("priv_"))==0 ||
  212.            search_list(internal_name,INTERNAL_NAME_NO,sizeof(internal_name[0]),name+wpflen)>=0)
  213.           tag|=vb_internal;
  214.     }
  215.     i=inspoint; if(i>mainvarcnt) i=mainvarcnt; if(i<0) i=0;
  216.     memmove(mainvartab+i+1,mainvartab+i,(mainvarcnt-i)*sizeof(mainvartab[0]));
  217.     mainvarcnt++; nlen++;
  218.     memmove(_varnameptr,name,nlen);
  219.     mainvartab[i].name=_varnameptr; _varnameptr+=nlen;
  220.     mainvartab[i].val=NULL; mainvartab[i].vlen=0;
  221.     mainvartab[i].tag=tag;
  222.     mainvartab[i].lvl=0; return i;
  223. }
  224.  
  225. char *fast_getvar(char *vname)
  226. {
  227.     int n;
  228.  
  229.     n=_char_int(vname); if(n<0) return "";
  230.     if(fastvartab[n].tag&vb_hacked) {
  231.         add_hack(vname); fastvartab[n].tag&=~vb_hacked;
  232.     }
  233.     getvar_len=fastvartab[n].vlen;
  234.     return fastvartab[n].val;
  235. }
  236.  
  237. int _setvar_(struct vartab *vtb, char *vval)
  238. {
  239.     int l,lvl;
  240.     char *p;
  241.     if(vval) l=strlen(vval); else l=0;
  242.     if(l>MAX_LINELEN) return 1;
  243.     lvl=vtb->lvl;
  244.     if(l==0) {
  245.         if(lvl>0) {
  246.             vfreebuf(lvl,vtb->val); vtb->tag|=vb_dirty;
  247.             if(var_hacking) vtb->tag|=vb_hacked; else vtb->tag&=~vb_hacked;
  248.             vtb->lvl=0; vtb->vlen=0;
  249.         }
  250.         if(vval) vtb->val=""; else vtb->val=NULL;
  251.         return 0;
  252.     }
  253.     if(l>=vlenmax[lvl]) {
  254.         vfreebuf(lvl,vtb->val);
  255.         do lvl++; while(l>=vlenmax[lvl]);
  256.         vtb->lvl=lvl;
  257.         vtb->val=p=vaskbuf(lvl);
  258.     }
  259.     else p=vtb->val;
  260.     vtb->vlen=l; vtb->tag|=vb_dirty;
  261.     if(var_hacking) vtb->tag|=vb_hacked; else vtb->tag&=~vb_hacked;
  262.     memmove(p,vval,++l); return 0;
  263. }
  264.  
  265. int fast_setvar(char *vname, char *vval)
  266. {
  267.     int n;
  268.    
  269.     n=_char_int(vname); if(n<0) return 1;
  270.     return _setvar_(fastvartab+n,vval);
  271. }
  272.  
  273.         /* internal constant */
  274. int setvar_force=0;
  275.  
  276.         /* Set a user variable. Now it no longer uses environment.
  277.          * Returns 0 if OK. */
  278. int setvar(char *vname, char *vvalue)
  279. {
  280.     int i,overwrite,tag;
  281.    
  282.     if(vname[0]==0) return 1;
  283.     if((vname[1]==0 || (vname[1]=='_' && vname[2]==0)))
  284.       return fast_setvar(vname,vvalue);
  285.     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
  286.     if(i<0) i=var_ins(vname,~i);
  287.     if(i<0) return 1;   /* error */
  288.     overwrite=1; tag=mainvartab[i].tag;
  289.     if(setvar_force==0 && confset==0) {
  290.                 /* user file has no right to modify wims variables. */
  291.         if((untrust&6)!=0) {
  292.             if(var_checkright(vname,var_writable,var_nw,var_pfx)==0)
  293.               return 1;
  294.             if(strncmp(vname,wims_prefix,wpflen)==0 &&
  295.                strcmp(vname,"wims_read_parm")!=0) return 1;
  296.         }
  297.         if((tag&vb_ro)!=0) overwrite=0;
  298.         else if((tag&vb_internal)!=0 && !trusted_module()) return 1;
  299.     }
  300.     if(!overwrite && mainvartab[i].val!=NULL) return 1;
  301.     _setvar_(mainvartab+i,vvalue);
  302.     if(vname[0]=='w') {
  303.         if(strcmp(vname,"wims_print_precision")==0) {
  304.             int a=atoi(vvalue);
  305.             if(a>0 && a<100) print_precision=a;
  306.         }
  307.         if(strcmp(vname,"wims_backslash_insmath")==0) {
  308.             if(strcasecmp(vvalue,"yes")==0) backslash_insmath=1;
  309.             else backslash_insmath=0;
  310.         }
  311.     }
  312.     return 0;
  313. }
  314.  
  315. int force_setvar(char *vname,char *vvalue)
  316. {
  317.     int i;
  318.     setvar_force=1; i=setvar(vname,vvalue); setvar_force=0; return i;
  319. }
  320.  
  321. void unsetvar(char *vname)
  322. {
  323.     int i;
  324.     if(vname[0]!=0 && (vname[1]==0 || (vname[1]=='_' && vname[2]==0))) {
  325.         fast_setvar(vname,NULL); return;
  326.     }
  327.     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
  328.     if(i>=0) _setvar_(mainvartab+i,NULL);
  329. }
  330.  
  331. #include "mathfonts.c"
  332.  
  333.         /* Get a variable's value. */
  334. char *_getvar(char *vname)
  335. {
  336.     char *val;
  337.     int i;
  338.  
  339.     if((untrust&4)!=0 || vname[0]==0) return "";        /* called from !readdef */
  340.     if(vname[1]==0 || (vname[1]=='_' && vname[2]==0)) return fast_getvar(vname);
  341.     if((untrust&6)!=0) {
  342.         if(var_checkright(vname,var_readable,var_nr,var_pfx)==0)
  343.           return "";
  344.     }
  345.     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname);
  346.     if(i<0) val=NULL; else {
  347.         if(mainvartab[i].tag&vb_hacked) {
  348.             add_hack(vname); mainvartab[i].tag&=~vb_hacked;
  349.         }
  350.         val=mainvartab[i].val; getvar_len=mainvartab[i].vlen;
  351.     }
  352.     if(vname[0]=='w' && strcmp(vname,"wims_incremental")==0) {
  353.         static char buf[32];
  354.         if(val==NULL) i=0;
  355.         else i=atoi(val)+1;
  356.         mystrncpy(buf,int2str(i),sizeof(buf));
  357.         force_setvar(vname,buf); getvar_len=strlen(buf); val=buf;
  358.     }
  359.     return val;
  360. }
  361.  
  362. char *getvar(char *vname)
  363. {
  364.     char *val;
  365.     getvar_len=0; val=_getvar(vname);
  366.     if(val==NULL && memcmp(vname,mathfont_prefix,strlen(mathfont_prefix))==0) {
  367.         val=mathfont(vname);
  368.         if(val) getvar_len=strlen(val); else getvar_len=0;
  369.     }
  370.     return val;
  371. }
  372.  
  373.         /* Search variables with numeric subscripts, from beg to end.
  374.          * Store result to pbuf. Returns number of variables found. */
  375. int varsuite(char *stem, int beg, int end, char *pbuf[], int pbuflen)
  376. {
  377.     int i,t,l,v;
  378.     i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),stem);
  379.     if(i<0) i=~i;
  380.     for(t=0,l=strlen(stem);i<mainvarcnt && t<pbuflen;i++){
  381.         if(strncmp(mainvartab[i].name,stem,l)!=0) break;
  382.         v=atoi(mainvartab[i].name+l); if(v<beg || v>end) continue;
  383.         if(mainvartab[i].val==NULL || mainvartab[i].val[0]==0) continue;
  384.         pbuf[t++]=mainvartab[i].name;
  385.     }
  386.     return t;
  387. }
  388.  
  389.         /* output debug information */
  390. void debug_output(void)
  391. {
  392.     long int endmtime2, time1;
  393.     struct timeval tv;
  394.     struct rusage us;
  395.  
  396.     if(noout || robot_access || strcasecmp(tmp_debug,"yes")!=0 ||
  397.        checkhost(manager_site)<1) return;
  398.     if(instex_cnt>0) instex_flush();
  399.     if(gettimeofday(&tv,NULL)) endmtime2=0;
  400.     else endmtime2=((tv.tv_sec%1000)*1000000+tv.tv_usec);
  401.     endmtime2=(endmtime2-startmtime2)/100;
  402.     time1=0;
  403.     if(getrusage(RUSAGE_SELF,&us)==0) {
  404.         time1+=us.ru_utime.tv_sec*1000+us.ru_utime.tv_usec/1000;
  405.         time1+=us.ru_stime.tv_sec*1000+us.ru_stime.tv_usec/1000;
  406.     }
  407.     if(getrusage(RUSAGE_CHILDREN,&us)==0) {
  408.         time1+=us.ru_utime.tv_sec*1000+us.ru_utime.tv_usec/1000;
  409.         time1+=us.ru_stime.tv_sec*1000+us.ru_stime.tv_usec/1000;
  410.     }
  411.     snprintf(tmplbuf,sizeof(tmplbuf),"%d,%d,%d,%.4f,%.2f,%d,%d,%d",
  412.              (int)(_varptr-_varbuf[_varbufcurr])+_varbufcurr*VARBUF_LEN,
  413.              bufvcnt-freevcnt,freevcnt,
  414.              (double) endmtime2/10000, (double) time1/1000,
  415.              mcachecnt,mfilecnt,execnt);
  416.     setvar("wims_debug_info",tmplbuf);
  417.     lastout_file=-1; phtml_put_base("debug.phtml",0);
  418. }
  419.  
  420.         /* Add to list of hacked variables */
  421. void add_hack(char *name)
  422. {
  423.     char buf[MAX_LINELEN+1];
  424.     char *p;
  425.     p=getvar("wims_hacked_variables"); if(p==NULL) buf[0]=0;
  426.     else snprintf(buf,sizeof(buf),"%s",p);
  427.     p=buf+strlen(buf);
  428.     if(p-buf >= sizeof(buf)-strlen(name)-4) return; /* too long */
  429.     if(p>buf) snprintf(p,sizeof(buf)-(p-buf),", %s",name);
  430.     else snprintf(buf,sizeof(buf),"%s",name);
  431.     setvar("wims_hacked_variables",buf);
  432. }
  433.  
  434.