Rev 5335 | Rev 8155 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 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 | |||
7673 | bpr | 18 | /* Low-level variable management routines. */ |
10 | reyssat | 19 | |
7673 | bpr | 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 |
||
10 | reyssat | 29 | |
7673 | bpr | 30 | char *_varbuf[VARBUF_NUM]; /* main variable value buffer */ |
10 | reyssat | 31 | char *_varptr; |
32 | int _varbufcurr; |
||
33 | char *_varnamebuf, *_varnameptr; /* variable name buffer */ |
||
34 | |||
7673 | bpr | 35 | /* wims_ variables that should be exported */ |
10 | reyssat | 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 | |||
7673 | bpr | 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}; |
||
10 | reyssat | 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 | |||
7673 | bpr | 82 | /* Returns 1 if rights OK. Else 0. */ |
10 | reyssat | 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) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 94 | } |
95 | return 1; |
||
96 | } |
||
97 | |||
7673 | bpr | 98 | /* initialisation */ |
10 | reyssat | 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; |
||
7673 | bpr | 118 | |
10 | reyssat | 119 | noexpcnt=0; |
120 | p=getvar("wims_noexport"); if(p==NULL) p=""; |
||
121 | for(p1=find_word_start(p),noexpcnt=0; |
||
7673 | bpr | 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++; |
||
10 | reyssat | 127 | } |
128 | for(i=0;i<mainvarcnt;i++) { |
||
7673 | bpr | 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: ; |
||
10 | reyssat | 143 | } |
144 | } |
||
145 | |||
146 | char *vaskbuf(int lvl) |
||
147 | { |
||
148 | char *p; |
||
7673 | bpr | 149 | if(lvl>=lvlno) { /* should never occur */ |
150 | module_error("Internal_variable_length_overflow"); return NULL; |
||
10 | reyssat | 151 | } |
152 | if(freevars[lvl]>0) { |
||
7673 | bpr | 153 | freevars[lvl]--; freevcnt--; |
154 | return freevbuf[freevstart[lvl]+freevars[lvl]]; |
||
10 | reyssat | 155 | } |
156 | if(_varptr+vlenmax[lvl]>=_varbuf[_varbufcurr]+VARBUF_LEN) { |
||
7673 | bpr | 157 | if(_varbufcurr>=VARBUF_NUM) { |
158 | module_error("variable_buffer_overflow"); return NULL; |
||
159 | } |
||
160 | _varbufcurr++; _varptr=_varbuf[_varbufcurr]=xmalloc(VARBUF_LEN); |
||
10 | reyssat | 161 | } |
162 | bufvcnt++; |
||
163 | p=_varptr; _varptr+=vlenmax[lvl]; return p; |
||
164 | } |
||
165 | |||
7673 | bpr | 166 | /* returns 1 if free succeeded. */ |
10 | reyssat | 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 { |
||
7673 | bpr | 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 | } |
||
10 | reyssat | 187 | } |
188 | } |
||
189 | |||
190 | int var_ins(char *name,int inspoint) |
||
191 | { |
||
192 | int i, nlen, tag; |
||
193 | if(mainvarcnt>=VARNUM_LIMIT) { |
||
7673 | bpr | 194 | module_error("too_many_variable_names"); return -1; |
10 | reyssat | 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) { |
||
7673 | bpr | 199 | module_error("variable_name_buffer_overflow"); return -1; |
10 | reyssat | 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) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 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) { |
||
7673 | bpr | 231 | add_hack(vname); fastvartab[n].tag&=~vb_hacked; |
10 | reyssat | 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) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 252 | } |
253 | if(l>=vlenmax[lvl]) { |
||
7673 | bpr | 254 | vfreebuf(lvl,vtb->val); |
255 | do lvl++; while(l>=vlenmax[lvl]); |
||
256 | vtb->lvl=lvl; |
||
257 | vtb->val=p=vaskbuf(lvl); |
||
10 | reyssat | 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; |
||
7673 | bpr | 268 | |
10 | reyssat | 269 | n=_char_int(vname); if(n<0) return 1; |
270 | return _setvar_(fastvartab+n,vval); |
||
271 | } |
||
272 | |||
7673 | bpr | 273 | /* internal constant */ |
10 | reyssat | 274 | int setvar_force=0; |
275 | |||
7673 | bpr | 276 | /* Set a user variable. Now it no longer uses environment. |
277 | * Returns 0 if OK. */ |
||
10 | reyssat | 278 | int setvar(char *vname, char *vvalue) |
279 | { |
||
280 | int i,overwrite,tag; |
||
7673 | bpr | 281 | |
10 | reyssat | 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); |
||
7673 | bpr | 287 | if(i<0) return 1; /* error */ |
10 | reyssat | 288 | overwrite=1; tag=mainvartab[i].tag; |
289 | if(setvar_force==0 && confset==0) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 299 | } |
300 | if(!overwrite && mainvartab[i].val!=NULL) return 1; |
||
301 | _setvar_(mainvartab+i,vvalue); |
||
302 | if(vname[0]=='w') { |
||
7673 | bpr | 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 | } |
||
10 | reyssat | 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))) { |
||
7673 | bpr | 325 | fast_setvar(vname,NULL); return; |
10 | reyssat | 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 | |||
7673 | bpr | 333 | /* Get a variable's value. */ |
10 | reyssat | 334 | char *_getvar(char *vname) |
335 | { |
||
336 | char *val; |
||
337 | int i; |
||
338 | |||
7673 | bpr | 339 | if((untrust&4)!=0 || vname[0]==0) return ""; /* called from !readdef */ |
10 | reyssat | 340 | if(vname[1]==0 || (vname[1]=='_' && vname[2]==0)) return fast_getvar(vname); |
341 | if((untrust&6)!=0) { |
||
7673 | bpr | 342 | if(var_checkright(vname,var_readable,var_nr,var_pfx)==0) |
343 | return ""; |
||
10 | reyssat | 344 | } |
345 | i=search_list(mainvartab,mainvarcnt,sizeof(mainvartab[0]),vname); |
||
346 | if(i<0) val=NULL; else { |
||
7673 | bpr | 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; |
||
10 | reyssat | 351 | } |
352 | if(vname[0]=='w' && strcmp(vname,"wims_incremental")==0) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 358 | } |
359 | return val; |
||
360 | } |
||
361 | |||
362 | char *getvar(char *vname) |
||
363 | { |
||
364 | char *val; |
||
365 | getvar_len=0; val=_getvar(vname); |
||
5335 | bpr | 366 | if(val==NULL && memcmp(vname,mathfont_prefix,strlen(mathfont_prefix))==0) {// mathfont_prefix m_ is add |
7673 | bpr | 367 | val=mathfont(vname); |
368 | if(val) getvar_len=strlen(val); else getvar_len=0; |
||
10 | reyssat | 369 | } |
370 | return val; |
||
371 | } |
||
372 | |||
7673 | bpr | 373 | /* Search variables with numeric subscripts, from beg to end. |
374 | * Store result to pbuf. Returns number of variables found. */ |
||
10 | reyssat | 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++){ |
||
7673 | bpr | 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; |
||
10 | reyssat | 385 | } |
386 | return t; |
||
387 | } |
||
388 | |||
7673 | bpr | 389 | /* output debug information */ |
10 | reyssat | 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) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 406 | } |
407 | if(getrusage(RUSAGE_CHILDREN,&us)==0) { |
||
7673 | bpr | 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; |
||
10 | reyssat | 410 | } |
411 | snprintf(tmplbuf,sizeof(tmplbuf),"%d,%d,%d,%.4f,%.2f,%d,%d,%d", |
||
7673 | bpr | 412 | (int)(_varptr-_varbuf[_varbufcurr])+_varbufcurr*VARBUF_LEN, |
413 | bufvcnt-freevcnt,freevcnt, |
||
414 | (double) endmtime2/10000, (double) time1/1000, |
||
415 | mcachecnt,mfilecnt,execnt); |
||
10 | reyssat | 416 | setvar("wims_debug_info",tmplbuf); |
417 | lastout_file=-1; phtml_put_base("debug.phtml",0); |
||
418 | } |
||
419 | |||
7673 | bpr | 420 | /* Add to list of hacked variables */ |
10 | reyssat | 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 |