Subversion Repositories wimsdev

Rev

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