Rev 11125 | Rev 13011 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 11125 | Rev 12242 | ||
---|---|---|---|
Line 62... | Line 62... | ||
62 | void delete_pid(void); |
62 | void delete_pid(void); |
63 | 63 | ||
64 | /* Internal use only */ |
64 | /* Internal use only */ |
65 | void _debug(char *s,...) |
65 | void _debug(char *s,...) |
66 | { |
66 | { |
67 |
|
67 | va_list vp; |
68 |
|
68 | char buf[MAX_LINELEN+1]; |
69 | 69 | ||
70 |
|
70 | va_start(vp,s); |
71 |
|
71 | vsnprintf(buf,sizeof(buf),s,vp); |
72 |
|
72 | va_end(vp); |
73 |
|
73 | setvar("debug",buf); module_error("debug"); |
74 |
|
74 | exit(1); |
75 | } |
75 | } |
76 | 76 | ||
77 | 77 | ||
78 | /* HTTP response header for non-processed CGI interface */ |
78 | /* HTTP response header for non-processed CGI interface */ |
79 | void nph_header(int code) |
79 | void nph_header(int code) |
80 | { |
80 | { |
81 |
|
81 | char *cstr; |
82 |
|
82 | switch(code) { |
83 |
|
83 | case 200: cstr="OK"; break; |
84 |
|
84 | case 301: cstr="Moved Permanently"; break; |
85 |
|
85 | case 302: cstr="Moved Temporarily"; break; |
86 |
|
86 | case 420: cstr="WIMS Nested Error"; break; |
87 |
|
87 | case 450: cstr="WIMS User Error"; break; |
88 |
|
88 | case 500: cstr="WIMS Internal Error"; break; |
89 |
|
89 | case 550: cstr="WIMS Module Error"; break; |
90 |
|
90 | default: cstr="ERROR"; break; |
91 |
|
91 | } |
92 |
|
92 | if(httpd_type!=httpd_wims) printf("Status: %d %s\r\n",code,cstr); |
93 |
|
93 | else { |
94 |
|
94 | char *p, tbuf[256]; |
95 |
|
95 | mystrncpy(tbuf,ctime(&nowtime),sizeof(tbuf)); |
96 |
|
96 | for(p=tbuf+strlen(tbuf);p>=tbuf && (*(p-1)=='\n' || *(p-1)=='\r'); p--); |
97 |
|
97 | *p=0; |
98 |
|
98 | printf("HTTP/1.0 %d %s\r\n\ |
99 | Date: %s\r\n\ |
99 | Date: %s\r\n\ |
100 | Connection: close\r\n\ |
100 | Connection: close\r\n\ |
101 | ",code,cstr,tbuf); |
101 | ",code,cstr,tbuf); |
102 |
|
102 | } |
103 | } |
103 | } |
104 | 104 | ||
105 | void flushoutput(void) |
105 | void flushoutput(void) |
106 | { |
106 | { |
107 |
|
107 | int l2; |
108 |
|
108 | if(outptr<=outbuf) return; |
109 |
|
109 | l2=outptr-outbuf; |
110 |
|
110 | if(lastout_file!=-1) (void)write(lastout_file,outbuf,l2); |
111 |
|
111 | else fwrite(outbuf,l2,1,stdout); |
112 |
|
112 | outptr=outbuf; |
113 | } |
113 | } |
114 | 114 | ||
115 | void internal_warn(char msg[]) |
115 | void internal_warn(char msg[]) |
116 | { |
116 | { |
117 |
|
117 | char buf[1024]; |
118 |
|
118 | fprintf(stderr,"wims: %s\n%s\n",msg,strerror(errno)); |
119 |
|
119 | snprintf(buf,sizeof(buf),"%s: %s\n",nowstr,msg); |
120 |
|
120 | accessfile(buf,"a","%s/internal_error.log",log_dir); |
121 | } |
121 | } |
122 | 122 | ||
123 | /* Internal error: panic and forget about requester. */ |
123 | /* Internal error: panic and forget about requester. */ |
124 | void internal_error(char msg[]) |
124 | void internal_error(char msg[]) |
125 | { |
125 | { |
126 |
|
126 | if(error_status<2) { |
127 |
|
127 | nph_header(500); |
128 |
|
128 | printf("Cache-Control: no-cache\nPragma: no-cache\r\n\ |
129 | Content-type: text/plain\r\n\r\n\r\n\ |
129 | Content-type: text/plain\r\n\r\n\r\n\ |
130 | WIMS panick! %s\n%s\n",msg,strerror(errno)); |
130 | WIMS panick! %s\n%s\n",msg,strerror(errno)); |
131 | error_status=2; internal_warn(msg); |
131 | error_status=2; internal_warn(msg); |
132 |
|
132 | } |
133 |
|
133 | delete_pid(); exit(1); |
134 | } |
134 | } |
135 | 135 | ||
136 | void tex_nospace(char *p) |
136 | void tex_nospace(char *p) |
137 | { |
137 | { |
138 |
|
138 | char *p1, *p2; |
139 |
|
139 | char buf[MAX_LINELEN+1]; |
140 |
|
140 | for(p1=buf,p2=p;*p2 && p1-buf<MAX_LINELEN-4;p2++) { |
141 |
|
141 | if(!isspace(*p2)) {*p1++=*p2;continue;} |
142 |
|
142 | while(isspace(*p2)) p2++; |
143 |
|
143 | if(*(p1-1)=='\\' || |
144 |
|
144 | (p1>buf && myisalnum(*(p1-1)) && myisalnum(*p2))) |
145 |
|
145 | *p1++=' '; |
146 |
|
146 | *p1++=*p2; |
147 |
|
147 | } |
148 |
|
148 | *p1++=0; memmove(p,buf,p1-buf); |
149 | } |
149 | } |
150 | 150 | ||
151 | void nametoolong(char *p) |
151 | void nametoolong(char *p) |
152 | { |
152 | { |
153 |
|
153 | char buf[MAX_FNAME+17]; |
154 |
|
154 | snprintf(buf,sizeof(buf),"%s...",p); |
155 |
|
155 | force_setvar("wims_error_data",buf); |
156 |
|
156 | module_error("file_name_too_long"); |
157 | } |
157 | } |
158 | 158 | ||
159 | off_t ftest_size; |
159 | off_t ftest_size; |
160 | 160 | ||
161 | /* A simple front-end of stat(). */ |
161 | /* A simple front-end of stat(). */ |
162 | int ftest(char *fname) |
162 | int ftest(char *fname) |
163 | { |
163 | { |
164 |
|
164 | if(strcmp(fname,lastftest)==0) return lastftype; |
165 | /* if(fname[0]=='/' || fname[0]=='.') fprintf(stderr,"ftest: %s\n",fname); */ |
165 | /* if(fname[0]=='/' || fname[0]=='.') fprintf(stderr,"ftest: %s\n",fname); */ |
166 |
|
166 | mystrncpy(lastftest,fname,sizeof(lastftest)); |
167 |
|
167 | if(stat(fname,&ftst)) return lastftype=-1; |
168 |
|
168 | ftest_size=ftst.st_size; |
169 |
|
169 | if(S_ISREG(ftst.st_mode)) { |
170 |
|
170 | if((ftst.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))!=0) return lastftype=is_exec; |
171 |
|
171 | else return lastftype=is_file; |
172 |
|
172 | } |
173 |
|
173 | if(S_ISDIR(ftst.st_mode)) return lastftype=is_dir; |
174 |
|
174 | if(S_ISFIFO(ftst.st_mode)) return lastftype=is_fifo; |
175 |
|
175 | if(S_ISSOCK(ftst.st_mode)) return lastftype=is_socket; |
176 |
|
176 | return lastftype=is_unknown; |
177 | } |
177 | } |
178 | 178 | ||
179 | char fnbuf[MAX_FNAME+1]; |
179 | char fnbuf[MAX_FNAME+1]; |
180 | 180 | ||
181 | /* make a filename and check length */ |
181 | /* make a filename and check length */ |
182 | char *mkfname(char buf[], char *s,...) |
182 | char *mkfname(char buf[], char *s,...) |
183 | { |
183 | { |
184 |
|
184 | va_list vp; |
185 |
|
185 | char *p; |
186 | 186 | ||
187 |
|
187 | if(buf==NULL) p=fnbuf; else p=buf; |
188 |
|
188 | va_start(vp,s); |
189 |
|
189 | vsnprintf(p,MAX_FNAME,s,vp); |
190 |
|
190 | va_end(vp); |
191 |
|
191 | if(strlen(p)>=MAX_FNAME-1) nametoolong(p); |
192 |
|
192 | return p; |
193 | } |
193 | } |
194 | 194 | ||
195 | void sysmask_trigger(char *s) |
195 | void sysmask_trigger(char *s) |
196 | { |
196 | { |
197 |
|
197 | char buf[MAX_FNAME+1]; |
198 |
|
198 | struct stat st; |
199 |
|
199 | mkfname(buf,"%s/%s",sysmask_trigger_dir,s); |
200 |
|
200 | stat(buf,&st); |
201 | } |
201 | } |
202 | 202 | ||
203 | /* read-in a file into buffer. Use open() and read(). |
203 | /* read-in a file into buffer. Use open() and read(). |
204 | * Return buffer address which will be malloc'ed if buf=NULL. */ |
204 | * Return buffer address which will be malloc'ed if buf=NULL. */ |
205 | char *readfile(char *fname, char buf[], long int buflen) |
205 | char *readfile(char *fname, char buf[], long int buflen) |
206 | { |
206 | { |
207 |
|
207 | int fd, t, st; |
208 |
|
208 | long int l, lc; |
209 |
|
209 | char *bf; |
210 |
|
210 | t=0; if(buf) buf[0]=0; |
211 |
|
211 | st=ftest(fname); if(st!=is_file) { |
212 |
|
212 | if(st==is_exec) { /* refuse to open executable file */ |
213 |
|
213 | setvar("executable",fname); module_error("executable"); |
214 | } |
- | |
215 | return NULL; |
- | |
216 | } |
214 | } |
- | 215 | return NULL; |
|
- | 216 | } |
|
217 |
|
217 | l=ftst.st_size; if(l<0) return NULL; |
218 |
|
218 | if(l>=buflen) { |
219 |
|
219 | if(buflen<MAX_LINELEN) l=buflen-1; |
220 |
|
220 | else { |
221 |
|
221 | if(strncmp(fname,"modules/",strlen("modules/"))==0) { |
222 |
|
222 | setvar(error_data_string,fname); module_error("file_too_long"); |
223 | } |
- | |
224 | else user_error("cmd_output_too_long"); |
- | |
225 | } |
223 | } |
- | 224 | else user_error("cmd_output_too_long"); |
|
226 | } |
225 | } |
- | 226 | } |
|
227 |
|
227 | fd=open(fname,O_RDONLY); if(fd==-1) return NULL; |
228 |
|
228 | if(buf==NULL) bf=xmalloc(l+8); else {bf=buf;if(l==0) {t=1; l=buflen-1;}} |
229 |
|
229 | lc=read(fd,bf,l); close(fd); |
230 |
|
230 | if(lc<0 || lc>l || (lc!=l && t==0)){ |
231 |
|
231 | if(buf==NULL) free(bf); else buf[0]=0; return NULL; |
- | 232 | } |
|
232 |
|
233 | bf[lc]=0; _tolinux(bf); return bf; |
233 | } |
234 | } |
234 | 235 | ||
235 | /* Get a line in a stored working file. |
236 | /* Get a line in a stored working file. |
236 | * Buffer length is always MAX_LINELEN. */ |
237 | * Buffer length is always MAX_LINELEN. */ |
237 | int wgetline(char buf[], size_t buflen, WORKING_FILE *f) |
238 | int wgetline(char buf[], size_t buflen, WORKING_FILE *f) |
238 | { |
239 | { |
239 |
|
240 | int i,j; unsigned int n; |
240 |
|
241 | i=f->linepointer; buf[0]=0; |
241 |
|
242 | if(i>=f->linecnt || f->textbuf==NULL) return EOF; |
242 |
|
243 | n=f->lines[i].llen; |
243 |
|
244 | if(n>=buflen) n=buflen-1; |
244 |
|
245 | if(n>0) memmove(buf,f->lines[i].address,n); |
245 |
|
246 | buf[n]=0; |
246 |
|
247 | for(j=i+1;j<f->linecnt && f->lines[j].isstart==0;j++); |
247 |
|
248 | f->l=i; f->linepointer=j; |
248 |
|
249 | if(j>=f->linecnt && n==0) return EOF; else return n; |
249 | } |
250 | } |
250 | 251 | ||
251 | int get_cached_file(char *name) |
252 | int get_cached_file(char *name) |
252 | { |
253 | { |
253 |
|
254 | int i,l,flag; |
254 |
|
255 | l=strlen(name); if(l>=127) return -1; |
255 |
|
256 | if(strncmp(module_prefix,module_dir,strlen(module_dir))!=0) flag=8; else flag=0; |
256 |
|
257 | for(i=0;i<mcachecnt;i++) { |
257 |
|
258 | if(flag==mcache[i].nocache && strcmp(name,mcache[i].name)==0) { |
258 |
|
259 | memmove(&m_file,mcache+i,sizeof(WORKING_FILE)); |
259 |
|
260 | m_file.nocache|=4; |
260 |
|
261 | return i; |
261 | } |
- | |
262 | } |
262 | } |
- | 263 | } |
|
263 |
|
264 | return -1; |
264 | } |
265 | } |
265 | 266 | ||
266 | /* Open a work file. Returns 0 if OK. */ |
267 | /* Open a work file. Returns 0 if OK. */ |
267 | int open_working_file(WORKING_FILE *f, char *fname) |
268 | int open_working_file(WORKING_FILE *f, char *fname) |
268 | { |
269 | { |
269 |
|
270 | char *p, *q; |
270 |
|
271 | void *vp; |
271 |
|
272 | int i,j,k,laststart,lc[LINE_LIMIT]; |
272 | 273 | ||
273 |
|
274 | f->linecnt=f->linepointer=0; |
274 |
|
275 | f->for_idx=f->nocache=0; |
275 |
|
276 | f->l=-1; f->lines=NULL; |
276 |
|
277 | strncpy(f->filepath,fname,MAX_FNAME+1); |
277 |
|
278 | f->textbuf=readfile(fname,NULL,WORKFILE_LIMIT); |
278 |
|
279 | if(f->textbuf==NULL) return -1; |
279 |
|
280 | p=f->textbuf; if(*p) { |
280 |
|
281 | for(i=0,p--; i<LINE_LIMIT-1 && p!=NULL;p=strchr(p,'\n')) { |
281 |
|
282 | if(i>0) *p=0; |
282 |
|
283 | lc[i++]=(++p-f->textbuf); |
- | 284 | } |
|
- | 285 | } |
|
- | 286 | else i=0; |
|
- | 287 | if(i>=LINE_LIMIT-1) module_error("file_too_long"); |
|
- | 288 | lc[i]=lc[i-1]+strlen(f->textbuf+lc[i-1])+1; |
|
- | 289 | f->textbuf[lc[i]]=0; |
|
- | 290 | f->linecnt=i; laststart=0; |
|
- | 291 | f->for_stack=xmalloc(MAX_FOR_LEVEL*sizeof(FOR_STACK)+(i+1)*sizeof(LINE_STRUCT)); |
|
- | 292 | vp=f->for_stack+MAX_FOR_LEVEL; f->lines=vp; |
|
- | 293 | for(j=0;j<i;j++) { |
|
- | 294 | f->lines[j].address=p=(f->textbuf)+lc[j]; |
|
- | 295 | f->lines[j].llen=lc[j+1]-lc[j]-1; |
|
- | 296 | (f->lines[j]).execcode=(f->lines[j]).varcode=-1; |
|
- | 297 | if(j==0) goto normal; |
|
- | 298 | q=f->lines[laststart].address+f->lines[laststart].llen-1; |
|
- | 299 | if(q>=f->textbuf && *q=='\\') { |
|
- | 300 | f->lines[laststart].llen+=f->lines[j].llen; *q='\n'; |
|
- | 301 | f->lines[j].isstart=f->lines[j].llen=0; |
|
- | 302 | memmove(q+1,p,lc[j+1]-lc[j]); |
|
- | 303 | } |
|
- | 304 | else { |
|
- | 305 | normal: for(q=p;myislspace(*q);q++); |
|
- | 306 | f->lines[j].isstart=1; laststart=j; k=0; |
|
- | 307 | switch(*q) { |
|
- | 308 | /* isstart: bit 1 = start. |
|
- | 309 | * bit 2 = exec |
|
- | 310 | * bit 3 (4) = label |
|
- | 311 | * bit 4 (8) = hard comment (!!) |
|
- | 312 | * bit 5 (16) = soft comment (#) */ |
|
- | 313 | case exec_prefix_char: { |
|
- | 314 | if(myisalpha(q[1])) f->lines[j].isstart=3; |
|
- | 315 | else f->lines[j].isstart=9; |
|
- | 316 | k=1; break; |
|
- | 317 | } |
|
- | 318 | case label_prefix_char: {f->lines[j].isstart=5; k=1; break;} |
|
- | 319 | case comment_prefix_char: {f->lines[j].isstart=17; break;} |
|
- | 320 | default: {f->lines[j].isstart=1; break;} |
|
283 | } |
321 | } |
- | 322 | if(k && q>p) {f->lines[j].address=q;f->lines[j].llen-=q-p;} |
|
284 | } |
323 | } |
285 | else i=0; |
- | |
286 | if(i>=LINE_LIMIT-1) module_error("file_too_long"); |
- | |
287 | lc[i]=lc[i-1]+strlen(f->textbuf+lc[i-1])+1; |
- | |
288 | f->textbuf[lc[i]]=0; |
- | |
289 | f->linecnt=i; laststart=0; |
- | |
290 | f->for_stack=xmalloc(MAX_FOR_LEVEL*sizeof(FOR_STACK)+(i+1)*sizeof(LINE_STRUCT)); |
- | |
291 | vp=f->for_stack+MAX_FOR_LEVEL; f->lines=vp; |
- | |
292 | for(j=0;j<i;j++) { |
- | |
293 | f->lines[j].address=p=(f->textbuf)+lc[j]; |
- | |
294 | f->lines[j].llen=lc[j+1]-lc[j]-1; |
- | |
295 | (f->lines[j]).execcode=(f->lines[j]).varcode=-1; |
- | |
296 | if(j==0) goto normal; |
- | |
297 | q=f->lines[laststart].address+f->lines[laststart].llen-1; |
- | |
298 | if(q>=f->textbuf && *q=='\\') { |
- | |
299 | f->lines[laststart].llen+=f->lines[j].llen; *q='\n'; |
- | |
300 | f->lines[j].isstart=f->lines[j].llen=0; |
- | |
301 | memmove(q+1,p,lc[j+1]-lc[j]); |
- | |
302 | } |
- | |
303 | else { |
- | |
304 | normal: for(q=p;myislspace(*q);q++); |
- | |
305 | f->lines[j].isstart=1; laststart=j; k=0; |
- | |
306 | switch(*q) { |
- | |
307 | /* isstart: bit 1 = start. |
- | |
308 | * bit 2 = exec |
- | |
309 | * bit 3 (4) = label |
- | |
310 | * bit 4 (8) = hard comment (!!) |
- | |
311 | * bit 5 (16) = soft comment (#) */ |
- | |
312 | case exec_prefix_char: { |
- | |
313 | if(myisalpha(q[1])) f->lines[j].isstart=3; |
- | |
314 | else f->lines[j].isstart=9; |
- | |
315 | k=1; break; |
- | |
316 | } |
- | |
317 | case label_prefix_char: {f->lines[j].isstart=5; k=1; break;} |
- | |
318 | case comment_prefix_char: {f->lines[j].isstart=17; break;} |
- | |
319 | default: {f->lines[j].isstart=1; break;} |
- | |
320 | } |
- | |
321 | if(k && q>p) {f->lines[j].address=q;f->lines[j].llen-=q-p;} |
- | |
322 | } |
- | |
323 |
|
324 | } |
324 |
|
325 | f->lines[i].isstart=1; f->lines[i].llen=0; |
325 |
|
326 | f->lines[i].address=(f->textbuf)+lc[i]; |
326 |
|
327 | mfilecnt++; return 0; |
327 | } |
328 | } |
328 | 329 | ||
329 | /* close an earlier opened working file */ |
330 | /* close an earlier opened working file */ |
330 | void close_working_file(WORKING_FILE *f, int cache) |
331 | void close_working_file(WORKING_FILE *f, int cache) |
331 | { |
332 | { |
332 |
|
333 | f->linepointer=f->l=0; |
333 |
|
334 | if(cache && untrust==0 && mcachecnt<MAX_MCACHE && (f->nocache&7)==0) { |
334 |
|
335 | memmove(mcache+mcachecnt,f,sizeof(WORKING_FILE)); |
335 |
|
336 | mcachecnt++; |
336 |
|
337 | } |
337 |
|
338 | else if((f->nocache&4)==0) { |
338 |
|
339 | if(f->for_stack!=NULL) free(f->for_stack); |
339 |
|
340 | if(f->textbuf!=NULL) free(f->textbuf); |
340 |
|
341 | } |
341 |
|
342 | f->for_stack=NULL; f->textbuf=NULL; f->linecnt=0; |
342 | } |
343 | } |
343 | 344 | ||
344 | void free_mcache(void) |
345 | void free_mcache(void) |
345 | { |
346 | { |
346 |
|
347 | int i; |
347 |
|
348 | untrust=0; |
348 |
|
349 | for(i=mcachecnt-1;i>=0;i--) close_working_file(mcache+i,0); |
349 |
|
350 | mcachecnt=0; |
350 | } |
351 | } |
351 | 352 | ||
352 | void cleantmpdir(void); |
353 | void cleantmpdir(void); |
353 | void user_error_log(char msg[]); |
354 | void user_error_log(char msg[]); |
354 | 355 | ||
355 | void nested_error(char msg[]) |
356 | void nested_error(char msg[]) |
356 | { |
357 | { |
357 |
|
358 | fprintf(stderr,"\nNested error! %s\n",msg); |
358 |
|
359 | nph_header(420); |
359 |
|
360 | printf("\r\n\r\nWIMS error processing aborted on nested error.\r\n\r\n%s\r\n",msg); |
360 |
|
361 | delete_pid(); exit(1); |
361 | } |
362 | } |
362 | 363 | ||
363 | /* Send an error message to requester and exit. |
364 | /* Send an error message to requester and exit. |
364 | * This is for user errors, language-sensitive. |
365 | * This is for user errors, language-sensitive. |
365 | */ |
366 | */ |
366 | void user_error(char msg[]) |
367 | void user_error(char msg[]) |
367 | { |
368 | { |
368 |
|
369 | char erfname[MAX_FNAME+1]; |
369 | 370 | ||
370 |
|
371 | if(error_status) nested_error(msg); |
371 |
|
372 | error_status=1; |
372 |
|
373 | mkfname(erfname,"%s.%s",user_error_msg_file,lang); |
373 |
|
374 | if(ftest(erfname)!=is_file) internal_error("user_error(): error message file not found.\n\ |
374 | Bad installation."); |
375 | Bad installation."); |
375 |
|
376 | force_setvar("wims_user_error",msg); |
376 |
|
377 | if(strcmp(msg,"threshold")!=0) user_error_log(msg); |
377 |
|
378 | memmove(module_prefix,".",2); |
378 |
|
379 | if(lastout_file!=-1 && outputing) { |
379 |
|
380 | flushoutput(); close(lastout_file); lastout_file=-1; |
380 |
|
381 | } |
381 |
|
382 | nph_header(450); |
382 |
|
383 | phtml_put_base(erfname,0); |
383 |
|
384 | if(strcmp(msg,"double_click")!=0) delete_pid(); |
384 |
|
385 | else { |
385 |
|
386 | cleantmpdir(); flushlog(); |
386 |
|
387 | } |
387 |
|
388 | flushoutput(); exit(0); |
388 | } |
389 | } |
389 | 390 | ||
390 | void module_error_log(char msg[]); |
391 | void module_error_log(char msg[]); |
391 | 392 | ||
392 | /* Messages for module errors. English only. |
393 | /* Messages for module errors. English only. |
393 | * This is really rudimentary for the time being. |
394 | * This is really rudimentary for the time being. |
394 | */ |
395 | */ |
395 | void module_error(char msg[]) |
396 | void module_error(char msg[]) |
396 | { |
397 | { |
397 |
|
398 | int send=0; |
398 |
|
399 | char *p; |
399 |
|
400 | WORKING_FILE mf; |
400 | 401 | ||
401 |
|
402 | if(error_status) nested_error(msg); |
402 |
|
403 | error_status=1; untrust=0; |
403 |
|
404 | module_error_log(msg); |
404 |
|
405 | nph_header(550); |
405 |
|
406 | printf("Server: %s %s (%s)\r\n", SHORTSWNAME,wims_version,LONGSWNAME); |
406 |
|
407 | p=getvar("wims_main_font"); |
407 |
|
408 | if(p!=NULL && *p!=0) printf("Content-type: text/plain; charset=%s\r\n\r\n",p); |
408 |
|
409 | else printf("Content-type: text/plain\r\n\r\n"); |
409 |
|
410 | p=getvar(ro_name[ro_module]); if(p==NULL) p="???"; |
410 |
|
411 | printf("ERROR.\n\nwims has detected an error in the module '%s'.",p); |
411 |
|
412 | if(m_file.l>=0) printf("\n\nIn file '%s', line %d:", m_file.name,m_file.l+1); |
412 | m_file.name,m_file.l+1); |
- | |
413 |
|
413 | printf(" %s.\n\n",msg); |
414 |
|
414 | if(open_working_file(&mf,mkfname(NULL,"%s.%s",module_error_msg_file,lang))!=0) |
415 |
|
415 | internal_error("module_error(): error message file not found."); |
416 |
|
416 | while(wgetline(tmplbuf,MAX_LINELEN,&mf)!=EOF) { |
417 |
|
417 | if(tmplbuf[0]!=tag_prefix_char) { |
418 |
|
418 | if(send) {substit(tmplbuf); puts(tmplbuf);} |
419 |
|
419 | continue; |
420 | } |
- | |
421 | strip_trailing_spaces(tmplbuf); |
- | |
422 | if(tmplbuf[1]==0 || strcmp(msg,tmplbuf+1)==0) send=1; |
- | |
423 | else send=0; |
- | |
424 | } |
420 | } |
- | 421 | strip_trailing_spaces(tmplbuf); |
|
- | 422 | if(tmplbuf[1]==0 || strcmp(msg,tmplbuf+1)==0) send=1; |
|
- | 423 | else send=0; |
|
- | 424 | } |
|
425 |
|
425 | close_working_file(&mf,0); |
426 |
|
426 | outptr=outbuf; delete_pid(); exit(1); |
427 | } |
427 | } |
428 | 428 | ||
429 | /* Output kernel routine */ |
429 | /* Output kernel routine */ |
430 | void _output_(char *s) |
430 | void _output_(char *s) |
431 | { |
431 | { |
432 |
|
432 | int l,l2; |
433 |
|
433 | l=strlen(s); output_length+=l; |
434 |
|
434 | if(output_length>=OUTPUT_LENGTH_LIMIT) { |
435 |
|
435 | module_error("output_too_long"); return; |
436 |
|
436 | } |
437 |
|
437 | l2=sizeof(outbuf)-(outptr-outbuf); |
438 |
|
438 | put: if(l<=l2) { |
439 |
|
439 | memmove(outptr,s,l); outptr+=l; return; |
440 |
|
440 | } |
441 |
|
441 | memmove(outptr,s,l2); s+=l2; l-=l2; |
442 |
|
442 | if(lastout_file!=-1) (void)write(lastout_file,outbuf,sizeof(outbuf)); |
443 |
|
443 | else fwrite(outbuf,sizeof(outbuf),1,stdout); |
444 |
|
444 | outptr=outbuf; l2=sizeof(outbuf); goto put; |
445 | } |
445 | } |
446 | 446 | ||
447 | /* Output with no var. */ |
447 | /* Output with no var. */ |
448 | void output0(char buf[]) |
448 | void output0(char buf[]) |
449 | { |
449 | { |
450 |
|
450 | char *p1, *p2, *ps; |
451 |
|
451 | int dynsave; |
452 |
|
452 | if(backslash_insmath) { |
453 |
|
453 | ps=buf; dynsave=instex_usedynamic; |
454 |
|
454 | for(p1=strstr(buf,"\\("); p1; p1=strstr(p2,"\\(")) { |
455 |
|
455 | p2=find_matching(p1+2,')'); |
456 |
|
456 | if(p2==NULL) break; |
457 |
|
457 | if(p1>buf && *(p1-1)=='\\') continue; |
458 |
|
458 | *p1=0; if(*(p2-1)=='\\') *(p2-1)=0; *p2++=0; _output_(ps); ps=p2; |
459 |
|
459 | instex_usedynamic=1; insmath(p1+2); |
460 |
|
460 | } |
461 |
|
461 | if(*ps) _output_(ps); |
462 |
|
462 | instex_usedynamic=dynsave; |
463 |
|
463 | } |
464 |
|
464 | else _output_(buf); |
465 | } |
465 | } |
466 | 466 | ||
467 | /* Output routine */ |
467 | /* Output routine */ |
468 | void output(char *s,...) |
468 | void output(char *s,...) |
469 | { |
469 | { |
470 |
|
470 | va_list vp; |
471 |
|
471 | char buf[4*MAX_LINELEN+1]; |
472 | 472 | ||
473 |
|
473 | va_start(vp,s); |
474 |
|
474 | vsnprintf(buf,sizeof(buf),s,vp); |
475 |
|
475 | va_end(vp); |
476 |
|
476 | output0(buf); |
477 | } |
477 | } |
478 | 478 | ||
479 | /* read in tmpf in tmp directory, and places in p. |
479 | /* read in tmpf in tmp directory, and places in p. |
480 | * Maximal length: MAX_LINELEN. |
480 | * Maximal length: MAX_LINELEN. |
481 | */ |
481 | */ |
482 | void read_tmp_file(char *p, const char *fname) |
482 | void read_tmp_file(char *p, const char *fname) |
483 | { |
483 | { |
484 |
|
484 | char *name, *pp; |
485 |
|
485 | name=mkfname(NULL,"%s/%s",tmp_dir,fname); |
486 |
|
486 | if(!exec_is_module || !outputing || !direct_exec |
487 |
|
487 | || strcmp(fname,"exec.out")!=0) { |
488 |
|
488 | readfile(name,p,MAX_LINELEN); |
489 |
|
489 | pp=getvar("wims_exec_dollar_double"); |
490 |
|
490 | if(pp && strcmp(pp,"yes")==0) { |
491 |
|
491 | for(pp=strchr(p,'$'); pp; pp=strchr(pp+2,'$')) |
492 |
|
492 | string_modify(p,pp,pp+1,"$$"); |
493 |
|
493 | } |
494 |
|
494 | } |
495 |
|
495 | else { |
496 |
|
496 | char *s; |
497 |
|
497 | s=readfile(name,NULL,OUTPUT_LENGTH_LIMIT); |
498 |
|
498 | if(s==NULL) {*p=0; return;} |
499 |
|
499 | if(memcmp(s,"Error: ", strlen("Error: "))==0) mystrncpy(p,s,MAX_LINELEN); |
500 |
|
500 | output_length+=strlen(s); |
501 |
|
501 | if(output_length>=OUTPUT_LENGTH_LIMIT) module_error("output_too_long"); |
502 |
|
502 | else _output_(s); |
503 |
|
503 | free(s); *p=0; |
504 |
|
504 | chmod(name,S_IRUSR|S_IWUSR); |
505 |
|
505 | } |
506 | } |
506 | } |
507 | 507 | ||
508 | /* verify whether the module is trusted. |
508 | /* verify whether the module is trusted. |
509 | * Returns 1 if yes, 0 if no. -1 for error. |
509 | * Returns 1 if yes, 0 if no. -1 for error. |
510 | */ |
510 | */ |
511 | int trusted_module(void) |
511 | int trusted_module(void) |
512 | { |
512 | { |
513 |
|
513 | char *modname, *w, buf[MAX_LINELEN+1]; |
514 |
|
514 | int i,n; |
515 |
|
515 | static int _trusted=-1; /* avoid repeated computations */ |
516 | 516 | ||
517 |
|
517 | if(untrust&255) return 0; |
518 |
|
518 | if(_trusted>=0) return _trusted; |
519 |
|
519 | modname=getvar(ro_name[ro_module]); |
520 |
|
520 | if(modname==NULL || *modname==0) return 0; |
521 |
|
521 | if(memcmp(modname,"adm/",strlen("adm/"))==0 || |
522 |
|
522 | memcmp(modname,"classes/",strlen("classes/"))==0 || |
523 |
|
523 | strcmp(modname,home_module)==0 || |
524 |
|
524 | memcmp(modname,"help/",strlen("help/"))==0) { |
525 |
|
525 | tr: |
526 |
|
526 | if(memcmp(modname,"classes/",strlen("classes/"))==0) |
527 |
|
527 | is_class_module=1; |
528 |
|
528 | setenv("trusted_module","yes",1); |
529 |
|
529 | return _trusted=1; |
530 |
|
530 | } |
531 |
|
531 | n=wordnum(trusted_modules); |
- | 532 | for(i=0;i<n;i++) { |
|
532 |
|
533 | w=fnd_word(trusted_modules,i+1,buf); |
533 |
|
534 | if(strcmp(w,modname)==0) goto tr; |
534 |
|
535 | } |
535 |
|
536 | return _trusted=0; |
536 | } |
537 | } |
537 | 538 | ||
538 | /* file should be in the module directory, but |
539 | /* file should be in the module directory, but |
539 | * it may also be somewhere else. |
540 | * it may also be somewhere else. |
540 | * buf[] requires MAX_FNAME+1 length. |
541 | * buf[] requires MAX_FNAME+1 length. |
541 | * Returns 0 if found. |
542 | * Returns 0 if found. |
542 | */ |
543 | */ |
543 | int find_module_file(char *fname, char buf[], int mode) |
544 | int find_module_file(char *fname, char buf[], int mode) |
544 | { |
545 | { |
545 |
|
546 | char *p, dtest[32]; |
546 | 547 | ||
547 |
|
548 | fname=find_word_start(fname); |
548 |
|
549 | if(*fname==0) return -1; |
549 | /* Name checking: no directory backtracing. */ |
550 | /* Name checking: no directory backtracing. */ |
550 |
|
551 | if(strstr(fname,parent_dir_string)!=NULL) { |
551 |
|
552 | setvar(error_data_string,fname); module_error("illegal_fname"); |
- | 553 | return -1; |
|
- | 554 | } |
|
- | 555 | p=strchr(fname,'/'); if(p==NULL || p>fname+10) goto openit; |
|
- | 556 | memmove(dtest,fname,p-fname); dtest[p-fname]=0; |
|
- | 557 | if(strcmp(dtest,"datamodule")==0) { |
|
- | 558 | mkfname(buf,"modules/data%s",p); goto lastopen; |
|
- | 559 | } |
|
- | 560 | if(strcmp(dtest,"wimshome")==0 && trusted_module()) { |
|
- | 561 | mkfname(buf,"%s%s",getvar("wims_home"),p); goto lastopen; |
|
- | 562 | } |
|
- | 563 | if(strcmp(dtest,"writable")==0) { |
|
- | 564 | if(strncmp(p+1,"TEMP_",5)==0 && strchr(p+1,'/')==NULL) { |
|
- | 565 | mkfname(buf,"%s/%s",tmp_dir,p+1); |
|
- | 566 | } |
|
- | 567 | else { |
|
- | 568 | mkfname(buf,"w/%s/%s",module_prefix,p+1); |
|
- | 569 | } |
|
- | 570 | untrust|=4; |
|
- | 571 | } |
|
- | 572 | else { |
|
- | 573 | openit: mkfname(buf,"%s/%s",module_prefix,fname); |
|
- | 574 | } |
|
- | 575 | if(mode) return 0; |
|
- | 576 | if(ftest(buf)!=is_file) { |
|
- | 577 | if(lastftype==is_exec) { |
|
- | 578 | isexec: |
|
- | 579 | setvar("executable",fname); module_error("executable"); |
|
552 | return -1; |
580 | return -1; |
553 | } |
581 | } |
554 | p=strchr(fname,'/'); if(p==NULL || p>fname+10) goto openit; |
- | |
555 | memmove(dtest,fname,p-fname); dtest[p-fname]=0; |
- | |
556 | if( |
582 | if(strncmp(fname,"adm/",4)==0 && |
557 | mkfname(buf,"modules/data%s",p); goto lastopen; |
- | |
558 | } |
- | |
559 |
|
583 | (!trusted_module() || is_class_module)) return -1; |
560 | mkfname(buf,"%s%s",getvar("wims_home"),p); goto lastopen; |
- | |
561 | } |
- | |
562 | if(strcmp(dtest,"writable")==0) { |
- | |
563 | if(strncmp(p+1,"TEMP_",5)==0 && strchr(p+1,'/')==NULL) { |
- | |
564 |
|
584 | mkfname(buf,"scripts/%s",fname); |
565 | } |
- | |
566 | else { |
- | |
567 | mkfname(buf,"w/%s/%s",module_prefix,p+1); |
- | |
568 | } |
- | |
569 | untrust|=4; |
- | |
570 | } |
- | |
571 |
|
585 | lastopen: |
572 | openit: mkfname(buf,"%s/%s",module_prefix,fname); |
- | |
573 | } |
- | |
574 | if(mode) return 0; |
586 | if(mode) return 0; |
575 | if(ftest(buf)!=is_file) { |
587 | if(ftest(buf)!=is_file) { |
576 | if(lastftype==is_exec) { |
- | |
577 | isexec: |
- | |
578 | setvar("executable",fname); module_error("executable"); |
- | |
579 | return -1; |
- | |
580 | } |
- | |
581 | if(strncmp(fname,"adm/",4)==0 && |
- | |
582 | (!trusted_module() || is_class_module)) return -1; |
- | |
583 | mkfname(buf,"scripts/%s",fname); |
- | |
584 | lastopen: |
- | |
585 | if(mode) return 0; |
- | |
586 | if(ftest(buf)!=is_file) { |
- | |
587 |
|
588 | if(lastftype==is_exec) goto isexec; |
588 |
|
589 | else return -1; |
589 | } |
- | |
590 | } |
590 | } |
- | 591 | } |
|
591 |
|
592 | return 0; |
592 | } |
593 | } |
593 | 594 | ||
594 | /* check whether a file is user-submitted |
595 | /* check whether a file is user-submitted |
595 | * This is deprecated because of the wimshome/ method. |
596 | * This is deprecated because of the wimshome/ method. |
596 | */ |
597 | */ |
Line 603... | Line 604... | ||
603 | } |
604 | } |
604 | */ |
605 | */ |
605 | 606 | ||
606 | /* returns 1 if violation */ |
607 | /* returns 1 if violation */ |
607 | int datafile_check(char *name) { |
608 | int datafile_check(char *name) { |
608 |
|
609 | if((untrust&255)==0) return 0; |
609 |
|
610 | if(strncmp(name,"data/",strlen("data/"))==0) return 0; |
610 |
|
611 | if(strncmp(name,"authors/",strlen("authors/"))==0) return 0; |
611 |
|
612 | if(strncmp(name,"datamodule/",strlen("datamodule/"))==0) return 0; |
612 |
|
613 | return 1; |
613 | } |
614 | } |
614 | 615 | ||
615 | /* returns 0 if success */ |
616 | /* returns 0 if success */ |
616 | void readdatafile(char *name) |
617 | void readdatafile(char *name) |
617 | { |
618 | { |
618 |
|
619 | char *pp; |
619 |
|
620 | if(strcmp(name,lastdatafile)==0) return; |
620 |
|
621 | lastdata[0]=0; readfile(name,lastdata,WORKFILE_LIMIT); |
621 |
|
622 | mystrncpy(lastdatafile,name,sizeof(lastdatafile)); |
622 |
|
623 | datacache[0]=lastdata; nextdatacache=1; |
623 |
|
624 | if(lastdata[0]==tag_string[1]) { |
624 |
|
625 | datacache[1]=lastdata; nextdatacache++; |
625 |
|
626 | } |
626 |
|
627 | pp=strstr(lastdata,tag_string); |
627 |
|
628 | if(pp) datacache[nextdatacache]=pp; |
628 |
|
629 | else datacache[nextdatacache]=lastdata+strlen(lastdata); |
629 | } |
630 | } |
630 | 631 | ||
631 | char *_nextdata(char *p) |
632 | char *_nextdata(char *p) |
632 | { |
633 | { |
633 |
|
634 | char *pp; |
634 |
|
635 | if(!*p) return p; |
635 |
|
636 | pp=strstr(p,tag_string); |
636 |
|
637 | if(pp) return pp; |
637 |
|
638 | else return p+strlen(p); |
638 | } |
639 | } |
639 | 640 | ||
640 | /* datafile structure: number of records. |
641 | /* datafile structure: number of records. |
641 | * tag=1 if direct access |
642 | * tag=1 if direct access |
642 | */ |
643 | */ |
643 | unsigned int datafile_recordnum(char *p) |
644 | unsigned int datafile_recordnum(char *p) |
644 | { |
645 | { |
645 |
|
646 | char nbuf[MAX_LINELEN+1], *pp; |
646 |
|
647 | int i, t, ret; |
647 | 648 | ||
648 |
|
649 | t=untrust; ret=0; |
649 |
|
650 | if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf)); |
650 |
|
651 | else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret; |
651 |
|
652 | readdatafile(nbuf); |
652 |
|
653 | for(i=nextdatacache, pp=datacache[i]; *pp;) { |
- | 654 | pp=_nextdata(pp+1); i++; |
|
- | 655 | if(i<DATAFIELD_LIMIT) { |
|
- | 656 | datacache[i]=pp; nextdatacache=i; |
|
- | 657 | } |
|
- | 658 | } |
|
- | 659 | ret=i-1; |
|
- | 660 | ret: |
|
- | 661 | untrust=t; |
|
- | 662 | return ret; |
|
- | 663 | } |
|
- | 664 | ||
- | 665 | /* datafile structure: find record n, starting from 1 */ |
|
- | 666 | char *datafile_fnd_record(char *p, int n, char bf[]) |
|
- | 667 | { |
|
- | 668 | char nbuf[MAX_LINELEN+1], *pp, *p2; |
|
- | 669 | int i, t; |
|
- | 670 | ||
- | 671 | bf[0]=0; t=untrust; |
|
- | 672 | if(n<0) goto ret; |
|
- | 673 | if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf)); |
|
- | 674 | else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret; |
|
- | 675 | readdatafile(nbuf); if(*lastdata==0) goto ret; |
|
- | 676 | if(n>nextdatacache) { |
|
- | 677 | for(i=nextdatacache, pp=datacache[i]; i<n && *pp;) { |
|
653 | pp=_nextdata(pp+1); i++; |
678 | pp=_nextdata(pp+1); i++; |
654 | if(i<DATAFIELD_LIMIT) { |
679 | if(i<DATAFIELD_LIMIT) { |
655 |
|
680 | datacache[i]=pp; nextdatacache=i; |
656 | } |
681 | } |
657 | } |
682 | } |
658 | ret=i-1; |
- | |
659 | ret: |
- | |
660 | untrust=t; |
- | |
661 | return ret; |
- | |
662 | } |
- | |
663 | - | ||
664 | /* datafile structure: find record n, starting from 1 */ |
- | |
665 | char *datafile_fnd_record(char *p, int n, char bf[]) |
- | |
666 | { |
- | |
667 | char nbuf[MAX_LINELEN+1], *pp, *p2; |
- | |
668 | int i, t; |
- | |
669 | - | ||
670 | bf[0]=0; t=untrust; |
- | |
671 | if(n<0) goto ret; |
- | |
672 | if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf)); |
- | |
673 | else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret; |
- | |
674 | readdatafile(nbuf); if(*lastdata==0) goto ret; |
- | |
675 | if(n>nextdatacache) { |
- | |
676 | for(i=nextdatacache, pp=datacache[i]; i<n && *pp;) { |
- | |
677 | pp=_nextdata(pp+1); i++; |
- | |
678 | if(i<DATAFIELD_LIMIT) { |
- | |
679 | datacache[i]=pp; nextdatacache=i; |
- | |
680 | } |
- | |
681 | } |
- | |
682 |
|
683 | } |
683 |
|
684 | else pp=datacache[n]; |
684 |
|
685 | if(!*pp) goto ret; |
685 |
|
686 | if(n>1 || (n==1 && *pp!=tag_string[1])) pp+=strlen(tag_string); |
686 |
|
687 | else if(n==1) pp+=strlen(tag_string)-1; |
687 |
|
688 | if(n<nextdatacache) p2=datacache[n+1]; |
688 |
|
689 | else { |
689 |
|
690 | p2=strstr(pp,tag_string); if(p2==NULL) p2=pp+strlen(pp); |
690 |
|
691 | if(n<DATAFIELD_LIMIT-1 && n==nextdatacache) { |
691 | nextdatacache++; datacache[nextdatacache]=p2; |
692 | nextdatacache++; datacache[nextdatacache]=p2; |
692 | } |
- | |
693 | } |
693 | } |
- | 694 | } |
|
694 |
|
695 | if(p2-pp>=MAX_LINELEN) p2=pp+MAX_LINELEN-1; |
695 |
|
696 | if(p2<pp) p2=pp; |
696 |
|
697 | memmove(bf,pp,p2-pp); bf[p2-pp]=0; |
697 |
|
698 | ret: |
698 |
|
699 | untrust=t; return bf; |
699 | } |
700 | } |
700 | 701 | ||
701 | char hex2char(char c1, char c2) |
702 | char hex2char(char c1, char c2) |
702 | { |
703 | { |
703 |
|
704 | char tbuf[16]; |
704 |
|
705 | if(c1<'0' || c1>'f' || c2<'0' || c2>'f') { |
705 | invl: |
706 | invl: |
706 |
|
707 | snprintf(tbuf,sizeof(tbuf),"%%%c%c",c1,c2); |
707 |
|
708 | setvar(error_data_string,tbuf); |
708 |
|
709 | user_error("invalid_char_in_query_string"); |
709 |
|
710 | } |
710 |
|
711 | c1=toupper(c1);c2=toupper(c2); |
711 |
|
712 | if(c1>'9' && c1<'A') goto invl; |
712 |
|
713 | if(c2>'9' && c2<'A') goto invl; |
713 |
|
714 | if(c1>'F' || c2>'F') goto invl; |
714 |
|
715 | if(c1>='A') c1=c1-'A'+'9'+1; |
715 |
|
716 | if(c2>='A') c2=c2-'A'+'9'+1; |
716 |
|
717 | return (c1-'0')*16+c2-'0'; |
717 | } |
718 | } |
718 | 719 | ||
719 | /* Converts back http escaped chars, slight. Does not check buffer length. |
720 | /* Converts back http escaped chars, slight. Does not check buffer length. |
720 | * Returns converted string length. |
721 | * Returns converted string length. |
721 | */ |
722 | */ |
722 | int _http2env(char outs[], char ins[]) |
723 | int _http2env(char outs[], char ins[]) |
723 | { |
724 | { |
724 |
|
725 | int j,k,l; |
725 |
|
726 | l=strlen(ins); |
726 |
|
727 | for(j=k=0;j<l && !isspace(ins[j]);j++,k++) { |
727 |
|
728 | if(isspace(ins[j])) { /* skip space characters in query string */ |
728 |
|
729 | k--;continue; |
729 |
|
730 | } |
730 |
|
731 | if(ins[j]=='%') { |
731 | /* skip Carriage-Return. */ |
732 | /* skip Carriage-Return. */ |
732 |
|
733 | if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) { |
733 |
|
734 | j+=2; k--; continue; |
734 |
|
735 | } |
735 |
|
736 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
736 |
|
737 | j+=2; continue; |
737 |
|
738 | } |
738 |
|
739 | outs[k]=ins[j]; |
739 |
|
740 | } |
740 |
|
741 | outs[k]=0; |
741 |
|
742 | return k; |
742 | } |
743 | } |
743 | 744 | ||
744 | /* Converts back http escaped chars. Does not check buffer length. |
745 | /* Converts back http escaped chars. Does not check buffer length. |
745 | * Returns converted string length. |
746 | * Returns converted string length. |
746 | */ |
747 | */ |
747 | int http2env(char outs[], char ins[]) |
748 | int http2env(char outs[], char ins[]) |
748 | { |
749 | { |
749 |
|
750 | int j,k,l; |
750 |
|
751 | l=strlen(ins); |
751 |
|
752 | for(j=k=0;j<l && !isspace(ins[j]);j++,k++) { |
752 |
|
753 | if(isspace(ins[j])) { /* skip space characters in query string */ |
753 |
|
754 | k--;continue; |
754 |
|
755 | } |
755 |
|
756 | if(ins[j]=='%') { |
756 | /* skip Carriage-Return. */ |
757 | /* skip Carriage-Return. */ |
757 |
|
758 | if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) { |
758 |
|
759 | j+=2; k--; continue; |
759 | } |
- | |
760 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
- | |
761 | j+=2; continue; |
- | |
762 | } |
760 | } |
763 | if(ins[j]=='+') { |
- | |
764 | outs[k]=' '; continue; |
- | |
765 | } |
- | |
766 |
|
761 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
767 |
|
762 | j+=2; continue; |
768 | } |
- | |
769 | outs[k]=ins[j]; |
- | |
770 | } |
763 | } |
- | 764 | if(ins[j]=='+') { |
|
- | 765 | outs[k]=' '; continue; |
|
- | 766 | } |
|
- | 767 | if(ins[j]=='?' || ins[j]=='&') { |
|
- | 768 | outs[k]=0; continue; |
|
- | 769 | } |
|
- | 770 | outs[k]=ins[j]; |
|
- | 771 | } |
|
771 |
|
772 | outs[k]=0; |
772 |
|
773 | return k; |
773 | } |
774 | } |
774 | 775 | ||
775 | /* translate a string to http querystring style. |
776 | /* translate a string to http querystring style. |
776 | * '&' is not translated. |
777 | * '&' is not translated. |
777 | * Buffer p must be at least MAX_LINELEN. |
778 | * Buffer p must be at least MAX_LINELEN. |
778 | */ |
779 | */ |
779 | void tohttpquery(char *p) |
780 | void tohttpquery(char *p) |
780 | { |
781 | { |
781 |
|
782 | char trlist[]=" ()[]{}+-*^|/\"\'!:;,<>\n"; |
782 |
|
783 | char *pp; |
783 |
|
784 | for(pp=p;*pp;pp++) { |
784 |
|
785 | if(*pp==' ') { |
785 |
|
786 | *pp='+'; continue; |
786 |
|
787 | } |
787 |
|
788 | if(strchr(trlist,*pp)==NULL) continue; |
788 |
|
789 | if(*pp=='+' && pp>p && *(pp-1)=='&') continue; |
789 |
|
790 | if(pp>p && *(pp-1)=='\\') { |
790 |
|
791 | ovlstrcpy(pp-1,pp);pp--;continue; |
791 |
|
792 | } |
792 |
|
793 | if(*pp=='\n') { |
793 |
|
794 | string_modify(p,pp,pp+1,"%%0D%%0A");pp+=5; |
794 |
|
795 | } |
795 |
|
796 | else { |
796 |
|
797 | string_modify(p,pp,pp+1,"%%%02X",*pp);pp+=2; |
797 | } |
- | |
798 | } |
798 | } |
- | 799 | } |
|
799 | } |
800 | } |
800 | 801 | ||
801 | /* substitute backslash parameters. Internal use only. */ |
802 | /* substitute backslash parameters. Internal use only. */ |
802 | void slashsubst(char *p) |
803 | void slashsubst(char *p) |
803 | { |
804 | { |
804 |
|
805 | char *p1, *p2, *pt, *pp, namebuf[128]; |
805 |
|
806 | int n; |
806 | 807 | ||
807 |
|
808 | n=strlen(mathfont_prefix); memmove(namebuf,mathfont_prefix,n+1); |
808 |
|
809 | for(p1=strchr(p,'\\'); p1!=NULL; p1=strchr(p1,'\\')) { |
809 |
|
810 | p1++; for(p2=p1; myisalnum(*p2) || *p2=='_'; p2++); |
810 |
|
811 | if(p2<=p1 || p2>p1+100) continue; |
811 |
|
812 | memmove(namebuf+n,p1,p2-p1); namebuf[p2-p1+n]=0; |
812 |
|
813 | pt=_getvar(namebuf); if(pt==NULL) continue; |
813 |
|
814 | if(*p2=='[' && (pp=find_matching(p2+1,']'))!=NULL) { |
814 |
|
815 | string_modify(p,pp+1,pp+1,")"); |
815 |
|
816 | string_modify(p,p1-1,p1,"$(%s",mathfont_prefix); |
816 | } |
- | |
817 | else string_modify(p,p1-1,p1,"$%s",mathfont_prefix); |
- | |
818 | } |
817 | } |
- | 818 | else string_modify(p,p1-1,p1,"$%s",mathfont_prefix); |
|
- | 819 | } |
|
819 | } |
820 | } |
820 | 821 | ||
821 | /* two alarm handlers. */ |
822 | /* two alarm handlers. */ |
822 | void alarm1(int s) |
823 | void alarm1(int s) |
823 | { |
824 | { |
824 |
|
825 | if(killpid>0 && kill(killpid,SIGKILL)) module_error("timeup"); |
825 |
|
826 | killpid=0; |
826 | } |
827 | } |
827 | 828 | ||
828 | void alarm2(int s) |
829 | void alarm2(int s) |
829 | { |
830 | { |
830 |
|
831 | cleantmpdir(); |
831 |
|
832 | alarm1(s); module_error("timeup"); |
832 | } |
833 | } |
833 | 834 | ||
834 | void finalalarm(void) |
835 | void finalalarm(void) |
835 | { |
836 | { |
836 |
|
837 | time_t curr; |
837 |
|
838 | curr=time(0); |
838 |
|
839 | if(curr>=limtime) alarm2(SIGALRM); |
839 |
|
840 | errno=0; |
840 |
|
841 | if(signal(SIGALRM,alarm2)==SIG_ERR) |
841 |
|
842 | internal_error(strerror(errno)); |
842 |
|
843 | alarm(limtime-curr+1); |
843 | } |
844 | } |
844 | 845 | ||
845 | void initalarm(void) |
846 | void initalarm(void) |
846 | { |
847 | { |
847 |
|
848 | limtimex=nowtime+4*rlimit_cpu/3; |
848 |
|
849 | limtime=limtimex+2; finalalarm(); |
849 | } |
850 | } |
850 | 851 | ||
851 | void forkalarm(void) |
852 | void forkalarm(void) |
852 | { |
853 | { |
853 |
|
854 | time_t curr; |
854 |
|
855 | curr=time(0); |
855 |
|
856 | if(curr>=limtimex) {alarm1(SIGALRM); return;} |
856 |
|
857 | if(signal(SIGALRM,alarm1)==SIG_ERR) |
857 |
|
858 | internal_error(strerror(errno)); |
858 |
|
859 | alarm(limtimex-curr+1); |
859 | } |
860 | } |
860 | 861 | ||
861 | /* create pid tag */ |
862 | /* create pid tag */ |
862 | void create_pid(void) |
863 | void create_pid(void) |
863 | { |
864 | { |
864 |
|
865 | char buf[MAX_FNAME+1], pbuf[256], obuf[MAX_FNAME+1]; |
865 |
|
866 | struct stat dst; |
866 |
|
867 | struct utimbuf ub; |
867 | 868 | ||
868 |
|
869 | if(robot_access || *session_prefix==0) return; |
869 |
|
870 | if(cmd_type==cmd_getframe) return; |
870 |
|
871 | mkfname(buf,"%s/.pid",s2_prefix); |
871 | /* another process running? */ |
872 | /* another process running? */ |
872 |
|
873 | if(readfile(buf,pbuf,sizeof(pbuf))!=NULL) { |
873 |
|
874 | mkfname(obuf,"/proc/%s",pbuf); |
874 |
|
875 | if(stat(obuf,&dst)==0) user_error("double_click"); |
875 |
|
876 | } |
876 |
|
877 | snprintf(pidbuf,sizeof(pidbuf),"%u",getpid()); |
877 |
|
878 | accessfile(pidbuf,"w","%s",buf); |
878 | /* Touch session time */ |
879 | /* Touch session time */ |
879 |
|
880 | if(strstr(session_prefix,"sessions/")==NULL) return; |
880 |
|
881 | ub.actime=ub.modtime=nowtime; |
881 |
|
882 | utime(session_prefix,&ub); |
882 |
|
883 | if(strchr(session_prefix,'_')!=NULL) { /* touch parent too */ |
883 |
|
884 | char sbuf[MAX_FNAME+1], *p; |
884 |
|
885 | mystrncpy(sbuf,session_prefix,sizeof(sbuf)); |
885 |
|
886 | p=strchr(sbuf,'_'); if(p!=NULL) *p=0; |
886 |
|
887 | utime(sbuf,&ub); |
887 |
|
888 | } |
888 | } |
889 | } |
889 | 890 | ||
890 | struct mxtab mxtab[MAX_MULTIEXEC]; |
891 | struct mxtab mxtab[MAX_MULTIEXEC]; |
891 | int mxno=0; |
892 | int mxno=0; |
892 | 893 | ||
893 | int execredirected(char *cmdf, char *inf, char *outf, char *errf, char *arg[]) |
894 | int execredirected(char *cmdf, char *inf, char *outf, char *errf, char *arg[]) |
894 | { |
895 | { |
895 |
|
896 | pid_t pid; |
896 |
|
897 | int status, t; |
897 | 898 | ||
898 |
|
899 | if(robot_access) return 0; |
899 |
|
900 | if(time(0)>=limtimex) { |
900 |
|
901 | if(errf!=NULL) |
901 |
|
902 | accessfile("No time left to execute subprograms.\n","w","%s",errf); |
902 |
|
903 | return -100; |
903 |
|
904 | } |
904 |
|
905 | lastdatafile[0]=lastftest[0]=0; |
905 |
|
906 | fflush(NULL); /* flush all output streams before forking |
906 |
|
907 | * otherwise they will be doubled |
907 |
|
908 | */ |
908 |
|
909 | pid=fork(); if(pid==-1) return -1; |
909 |
|
910 | if(!pid) { /* child */ |
910 |
|
911 | char buf[MAX_LINELEN+1]; int k; |
911 |
|
912 | (void)nice(10); /* lower priority for children */ |
912 |
|
913 | if(is_multiexec) { |
913 |
|
914 | dup2(mxtab[multiexec_index].pipe_stdin[0],0); |
914 |
|
915 | dup2(mxtab[multiexec_index].pipe_stdout[1],1); |
915 |
|
916 | dup2(mxtab[multiexec_index].pipe_stderr[1],2); |
916 |
|
917 | } |
917 |
|
918 | else { |
918 |
|
919 | if(inf!=NULL) (void)freopen(inf,"r",stdin); |
919 |
|
920 | if(outf!=NULL) (void)freopen(outf,"w",stdout); |
920 |
|
921 | if(errf!=NULL) (void)freopen(errf,"w",stderr); |
921 |
|
922 | } |
922 | /* This is to patch LinuxPPC uid wrapping |
923 | /* This is to patch LinuxPPC uid wrapping |
923 | * for scripts */ |
924 | * for scripts */ |
924 |
|
925 | t=0; if(strchr(cmdf,'/')) { |
925 |
|
926 | int tf; |
926 |
|
927 | char tbuf[16]; |
927 |
|
928 | tf=open(cmdf,O_RDONLY); (void)read(tf,tbuf,8); close(tf); |
928 |
|
929 | if(memcmp(tbuf+1,"ELF",3)!=0) t=1; |
929 |
|
930 | } |
930 |
|
931 | if(wrapexec==-1) { |
931 |
|
932 | setreuid(getuid(),getuid());setregid(getgid(),getgid()); |
932 |
|
933 | } |
933 |
|
934 | if(wrapexec==1 || (t==1 && wrapexec==0)) { |
934 |
|
935 | setreuid(geteuid(),geteuid());setregid(getegid(),getegid()); |
935 |
|
936 | } |
936 |
|
937 | errno=0; |
937 |
|
938 | if(strchr(cmdf,'/')) execve(cmdf,arg,environ); |
938 |
|
939 | else execvp(cmdf,arg); |
939 |
|
940 | snprintf(buf,sizeof(buf),"Failed to execute"); |
940 |
|
941 | for(k=0;arg[k];k++) { |
941 | t=strlen(buf); |
- | |
942 | snprintf(buf+t,sizeof(buf)-t," %s",arg[k]); |
- | |
943 | } |
- | |
944 | t=strlen(buf); |
942 | t=strlen(buf); |
945 | snprintf(buf+t,sizeof(buf)-t," |
943 | snprintf(buf+t,sizeof(buf)-t," %s",arg[k]); |
946 | accessfile(buf,"a","%s/exec.fail",tmp_dir); |
- | |
947 | exit(127); |
- | |
948 | } |
944 | } |
- | 945 | t=strlen(buf); |
|
- | 946 | snprintf(buf+t,sizeof(buf)-t,"\n %s\n",strerror(errno)); |
|
- | 947 | accessfile(buf,"a","%s/exec.fail",tmp_dir); |
|
- | 948 | exit(127); |
|
- | 949 | } |
|
949 |
|
950 | else { /* parent */ |
950 |
|
951 | wrapexec=0; status=0; |
951 |
|
952 | if(exec_wait && !is_multiexec) { |
952 |
|
953 | killpid=pid; forkalarm(); |
953 |
|
954 | waitpid(pid,&status,0); killpid=0; finalalarm(); |
954 | } |
- | |
955 | return WEXITSTATUS(status); |
- | |
956 | } |
955 | } |
- | 956 | return WEXITSTATUS(status); |
|
- | 957 | } |
|
957 | } |
958 | } |
958 | 959 | ||
959 | /* preparation for resident execution. |
960 | /* preparation for resident execution. |
960 | * Returns 1 if already up, otherwise 0. |
961 | * Returns 1 if already up, otherwise 0. |
961 | */ |
962 | */ |
962 | int multiexec(char *cmd, char **abuf) |
963 | int multiexec(char *cmd, char **abuf) |
963 | { |
964 | { |
964 |
|
965 | char *p; |
965 |
|
966 | int i; |
966 | 967 | ||
967 |
|
968 | if(robot_access) return 0; |
968 |
|
969 | if(strstr(tmp_dir,"sessions/")==NULL) return 0; |
969 |
|
970 | if(strstr(tmp_debug,"yes")!=NULL && checkhost(manager_site)>=1) |
970 |
|
971 | setenv("multiexec_debug","yes",1); |
971 |
|
972 | p=getvar("wims_multiexec"); |
972 |
|
973 | if(p==NULL || wordchr(p,cmd)==NULL) return 0; /* not allowed */ |
973 |
|
974 | if(!multiexec_random[0]) { |
974 |
|
975 | snprintf(multiexec_random, sizeof(multiexec_random), |
975 |
|
976 | "%lX%lX%lX%lX%lX%lX%lX%lX", |
976 |
|
977 | random(),random(),random(),random(), |
977 |
|
978 | random(),random(),random(),random()); |
978 |
|
979 | setenv("multiexec_random",multiexec_random,1); |
979 |
|
980 | } |
980 |
|
981 | for(i=0;i<mxno && strcmp(cmd,mxtab[i].cmd)!=0; i++); |
981 |
|
982 | multiexec_index=i; |
982 |
|
983 | if(i==mxno) { |
983 |
|
984 | if(mxno>=MAX_MULTIEXEC) return 0; |
984 |
|
985 | if(pipe(mxtab[i].pipe_stdin)<0) return 0; |
985 |
|
986 | if(pipe(mxtab[i].pipe_stdout)<0) return 0; |
986 |
|
987 | if(pipe(mxtab[i].pipe_stderr)<0) return 0; |
987 |
|
988 | mystrncpy(mxtab[i].cmd,cmd,sizeof(mxtab[i].cmd)); |
988 |
|
989 | mxno++; is_multiexec=1; |
989 |
|
990 | exportall(); setenv("wims_exec_parm",multiexec_random,1); |
990 |
|
991 | execredirected(abuf[0],NULL,NULL,NULL,abuf); |
991 |
|
992 | } |
992 |
|
993 | is_multiexec=0; |
993 |
|
994 | return 1; |
994 | } |
995 | } |
995 | 996 | ||
996 | /* my system(), but with variable parms |
997 | /* my system(), but with variable parms |
997 | * More secure than system(), and direct fork. |
998 | * More secure than system(), and direct fork. |
998 | */ |
999 | */ |
999 | int call_ssh(char *s,...) |
1000 | int call_ssh(char *s,...) |
1000 | { |
1001 | { |
1001 |
|
1002 | va_list vp; |
1002 |
|
1003 | char buf[MAX_LINELEN+1]; |
1003 |
|
1004 | char *arg[1024]; |
1004 |
|
1005 | char *inf=NULL, *outf=NULL, *errf=NULL; |
1005 |
|
1006 | char *cmdf, *p, *p2; |
1006 |
|
1007 | int i, d; |
1007 | 1008 | ||
1008 |
|
1009 | if(robot_access) return 0; |
1009 |
|
1010 | va_start(vp,s); |
1010 |
|
1011 | vsnprintf(buf,sizeof(buf),s,vp); |
1011 |
|
1012 | va_end(vp); |
1012 |
|
1013 | p=find_word_start(buf); if(*p==0) return 0; |
1013 |
|
1014 | cmdf=p; |
1014 |
|
1015 | for(i=0;*p!=0 && i<1000; p=find_word_start(p2)) { |
1015 |
|
1016 | switch(*p) { |
1016 |
|
1017 | case '\'': { |
1017 |
|
1018 | p++; p2=strchr(p,'\''); if(p2==NULL) p2=p+strlen(p); |
1018 |
|
1019 | d=0; break; |
1019 |
|
1020 | } |
1020 |
|
1021 | case '"': { |
1021 |
|
1022 | p++; p2=strchr(p,'"'); if(p2==NULL) p2=p+strlen(p); |
1022 |
|
1023 | d=0; break; |
1023 |
|
1024 | } |
1024 |
|
1025 | default: d=1; p2=find_word_end(p); break; |
1025 |
|
1026 | } |
1026 |
|
1027 | if(*p2) *p2++=0; |
1027 |
|
1028 | if(!d) {arg[i++]=p; continue;} |
1028 |
|
1029 | switch(*p) { |
1029 |
|
1030 | case '<': inf=++p; break; |
1030 |
|
1031 | case '>': { |
- | 1032 | p++; |
|
1031 |
|
1033 | if(*p=='&') { |
1032 |
|
1034 | merge: p++; errf=outf=p; break; |
1033 |
|
1035 | } |
1034 |
|
1036 | else outf=p; |
1035 |
|
1037 | break; |
1036 |
|
1038 | } |
1037 |
|
1039 | case '&': { |
- | 1040 | p++; |
|
1038 |
|
1041 | if(*p=='>') goto merge; |
1039 |
|
1042 | else break; |
1040 |
|
1043 | } |
1041 |
|
1044 | case '2': { |
1042 |
|
1045 | if(*(p+1)=='>') {errf=p+2; break;} |
1043 | } |
- | |
1044 | default: arg[i++]=p; break; |
- | |
1045 | } |
1046 | } |
- | 1047 | default: arg[i++]=p; break; |
|
1046 | } |
1048 | } |
- | 1049 | } |
|
1047 |
|
1050 | arg[i]=NULL; |
1048 |
|
1051 | return execredirected(cmdf,inf,outf,errf,arg); |
1049 | } |
1052 | } |
1050 | 1053 | ||
1051 | /* Read/write to a file with variable parms to print filename */ |
1054 | /* Read/write to a file with variable parms to print filename */ |
1052 | void accessfile(char *content, char *type, char *s,...) |
1055 | void accessfile(char *content, char *type, char *s,...) |
1053 | { |
1056 | { |
1054 |
|
1057 | va_list vp; |
1055 |
|
1058 | char buf[MAX_FNAME+1]; |
1056 |
|
1059 | int fd; |
1057 | 1060 | ||
1058 |
|
1061 | if(robot_access) return; |
1059 |
|
1062 | va_start(vp,s); |
1060 |
|
1063 | vsnprintf(buf,sizeof(buf),s,vp); |
1061 |
|
1064 | va_end(vp); |
1062 |
|
1065 | if(strlen(buf)>=MAX_FNAME-1) nametoolong(buf); |
1063 |
|
1066 | switch(*type) { |
1064 |
|
1067 | case 'r': readfile(buf,content,MAX_LINELEN); return; |
1065 |
|
1068 | case 'e': readfile(buf,content,MAX_LINELEN/4); return; /* limited read */ |
1066 |
|
1069 | case 'w': fd=creat(buf,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break; |
1067 |
|
1070 | case 'a': fd=open(buf,O_WRONLY|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break; |
1068 |
|
1071 | default : return; |
1069 |
|
1072 | } |
1070 |
|
1073 | lastdatafile[0]=lastftest[0]=0; |
1071 |
|
1074 | if(fd==-1) return; |
1072 |
|
1075 | (void)write(fd,content,strlen(content)); close(fd); |
1073 | } |
1076 | } |
1074 | 1077 | ||
1075 | /* system(), but with variable parms |
1078 | /* system(), but with variable parms |
1076 | * Uses sh to execute command. |
1079 | * Uses sh to execute command. |
1077 | */ |
1080 | */ |
1078 | int call_sh(char *s,...) |
1081 | int call_sh(char *s,...) |
1079 | { |
1082 | { |
1080 |
|
1083 | va_list vp; |
1081 |
|
1084 | char buf[MAX_LINELEN+1]; |
1082 |
|
1085 | char *abuf[8]; |
1083 | 1086 | ||
1084 |
|
1087 | if(robot_access) return 0; |
1085 |
|
1088 | va_start(vp,s); |
1086 |
|
1089 | vsnprintf(buf,sizeof(buf),s,vp); |
1087 |
|
1090 | va_end(vp); |
1088 |
|
1091 | abuf[0]="sh"; abuf[1]="-c"; abuf[2]=buf; abuf[3]=NULL; |
1089 |
|
1092 | return execredirected(abuf[0],NULL,NULL,NULL,abuf); |
1090 | } |
1093 | } |
1091 | 1094 | ||
1092 | void _getdef(char buf[], char *name, char value[]) |
1095 | void _getdef(char buf[], char *name, char value[]) |
1093 | { |
1096 | { |
1094 |
|
1097 | char *p1, *p2, *p3, *p4; |
1095 | 1098 | ||
1096 |
|
1099 | if(*name==0) goto nothing; /* this would create segfault. */ |
1097 |
|
1100 | for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) { |
1098 |
|
1101 | p2=find_word_start(p1+strlen(name)); |
1099 |
|
1102 | if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue; |
1100 |
|
1103 | p3=p1; while(p3>buf && *(p3-1)!='\n') p3--; |
1101 |
|
1104 | p3=find_word_start(p3); |
1102 |
|
1105 | if(p3<p1 && *p3!='!') continue; |
1103 |
|
1106 | if(p3<p1) { |
1104 |
|
1107 | p3++; p4=find_word_end(p3); |
1105 |
|
1108 | if(find_word_start(p4)!=p1) continue; |
1106 |
|
1109 | if(p4-p3!=3 || (strncmp(p3,"set",3)!=0 && |
1107 |
|
1110 | strncmp(p3,"let",3)!=0 && |
1108 |
|
1111 | strncmp(p3,"def",3)!=0)) { |
1109 |
|
1112 | if(p4-p3!=6 || strncmp(p3,"define",6)!=0) continue; |
1110 | } |
- | |
1111 | } |
1113 | } |
1112 | p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2); |
- | |
1113 | p2=find_word_start(p2); |
- | |
1114 | if(p2>p3) goto nothing; |
- | |
1115 | if(p3-p2>=MAX_LINELEN) user_error("cmd_output_too_long"); |
- | |
1116 | memmove(value,p2,p3-p2); value[p3-p2]=0; |
- | |
1117 | strip_trailing_spaces(value); return; |
- | |
1118 | } |
1114 | } |
- | 1115 | p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2); |
|
- | 1116 | p2=find_word_start(p2); |
|
- | 1117 | if(p2>p3) goto nothing; |
|
- | 1118 | if(p3-p2>=MAX_LINELEN) user_error("cmd_output_too_long"); |
|
- | 1119 | memmove(value,p2,p3-p2); value[p3-p2]=0; |
|
- | 1120 | strip_trailing_spaces(value); return; |
|
- | 1121 | } |
|
1119 | nothing: |
1122 | nothing: |
1120 |
|
1123 | value[0]=0; return; |
1121 | } |
1124 | } |
1122 | 1125 | ||
1123 | /* Get variable definition from a file. |
1126 | /* Get variable definition from a file. |
1124 | * Result stored in buffer value of length MAX_LINELEN. |
1127 | * Result stored in buffer value of length MAX_LINELEN. |
1125 | */ |
1128 | */ |
1126 | void getdef(char *fname, char *name, char value[]) |
1129 | void getdef(char *fname, char *name, char value[]) |
1127 | { |
1130 | { |
1128 |
|
1131 | char buf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1], nbuf[MAX_NAMELEN+1]; |
1129 |
|
1132 | char *p1, *p2; |
- | 1133 | ||
- | 1134 | value[0]=0; if(readfile(fname,buf,sizeof(buf)-16)==NULL) return; |
|
- | 1135 | mystrncpy(value,name,MAX_LINELEN); |
|
- | 1136 | for(p1=value; *p1; p1=p2) { |
|
- | 1137 | while(*p1 && !myisalnum(*p1) && *p1!='_') p1++; |
|
- | 1138 | if(*p1==0) break; |
|
- | 1139 | for(p2=p1; myisalnum(*p2) || *p2=='_'; p2++); |
|
- | 1140 | if(p2-p1>MAX_NAMELEN) continue; |
|
- | 1141 | memmove(nbuf,p1,p2-p1); nbuf[p2-p1]=0; |
|
- | 1142 | _getdef(buf,nbuf,tbuf); |
|
- | 1143 | string_modify(value,p1,p2,"%s",tbuf); |
|
- | 1144 | p2=p1+strlen(tbuf); |
|
- | 1145 | } |
|
- | 1146 | } |
|
- | 1147 | ||
- | 1148 | int _setdef_changed; |
|
- | 1149 | ||
- | 1150 | void _setdef(char buf[], char *name, char *value) |
|
- | 1151 | { |
|
- | 1152 | char *p1, *p2, *p3; |
|
- | 1153 | int n; |
|
1130 | 1154 | ||
1131 |
|
1155 | for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) { |
1132 |
|
1156 | p2=find_word_start(p1+strlen(name)); |
1133 | for(p1=value; *p1; p1=p2) { |
- | |
1134 |
|
1157 | if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue; |
1135 | if(*p1==0) break; |
- | |
1136 |
|
1158 | p3=p1; while(p3>buf && *(p3-1)==' ') p3--; |
1137 |
|
1159 | if(p3>buf && *(p3-1)!='\n') continue; |
1138 |
|
1160 | p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2); |
1139 |
|
1161 | if(strlen(value)!=p3-p2 || strncmp(value,p2,p3-p2)!=0) { |
1140 | string_modify( |
1162 | string_modify(buf,p2,p3,"%s",value); |
1141 |
|
1163 | _setdef_changed++; |
1142 | } |
1164 | } |
1143 | } |
- | |
1144 | - | ||
1145 | int _setdef_changed; |
- | |
1146 | - | ||
1147 | void _setdef(char buf[], char *name, char *value) |
- | |
1148 | { |
- | |
1149 | char *p1, *p2, *p3; |
- | |
1150 | int n; |
- | |
1151 | - | ||
1152 | for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) { |
- | |
1153 | p2=find_word_start(p1+strlen(name)); |
- | |
1154 | if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue; |
- | |
1155 | p3=p1; while(p3>buf && *(p3-1)==' ') p3--; |
- | |
1156 | if(p3>buf && *(p3-1)!='\n') continue; |
- | |
1157 | p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2); |
- | |
1158 | if(strlen(value)!=p3-p2 || strncmp(value,p2,p3-p2)!=0) { |
- | |
1159 | string_modify(buf,p2,p3,"%s",value); |
- | |
1160 | _setdef_changed++; |
- | |
1161 | } |
- | |
1162 |
|
1165 | return; |
1163 |
|
1166 | } |
1164 |
|
1167 | n=strlen(buf); |
1165 |
|
1168 | if(n>0 && buf[n-1]!='\n') |
1166 |
|
1169 | snprintf(buf+n,MAX_LINELEN-n,"\n%s=%s\n",name,value); |
1167 |
|
1170 | else |
1168 |
|
1171 | snprintf(buf+n,MAX_LINELEN-n,"%s=%s\n",name,value); |
1169 |
|
1172 | _setdef_changed++; |
1170 | } |
1173 | } |
1171 | 1174 | ||
1172 | /* Set variable definition to a file. */ |
1175 | /* Set variable definition to a file. */ |
1173 | void setdef(char *fname, char *name) |
1176 | void setdef(char *fname, char *name) |
1174 | { |
1177 | { |
1175 |
|
1178 | char buf[MAX_LINELEN+1]; |
1176 |
|
1179 | char *p1, *p2, *p3; |
1177 | 1180 | ||
1178 |
|
1181 | _setdef_changed=0; |
1179 |
|
1182 | if(strchr(name,'=')==NULL) return; |
1180 |
|
1183 | for(p1=name;*p1;p1++) { |
1181 |
|
1184 | if(isspace(*p1) && *p1!=' ' && *p1!='\n') *p1=' '; |
1182 |
|
1185 | if(*p1==' ') { |
1183 |
|
1186 | for(p2=p1+1; isspace(*p2) && *p2!='\n'; p2++); |
1184 |
|
1187 | if(p2>p1+1) ovlstrcpy(p1+1,p2); |
1185 |
|
1188 | p2=p1+1; if(*p2=='=' || *p2=='\n') ovlstrcpy(p1,p2); |
1186 |
|
1189 | } |
1187 |
|
1190 | } |
1188 |
|
1191 | if(readfile(fname,buf,sizeof(buf))==NULL) buf[0]=0; |
1189 |
|
1192 | for(p1=find_word_start(name); p1!=NULL; p1=p2) { |
1190 |
|
1193 | p2=strchr(p1,'\n'); if(p2!=NULL) *p2++=0; |
1191 |
|
1194 | p1=find_word_start(p1); |
1192 |
|
1195 | p3=strchr(p1,'='); if(p3==NULL) continue; |
1193 |
|
1196 | *p3++=0; p3=find_word_start(p3); |
1194 |
|
1197 | _setdef(buf,p1,p3); |
1195 |
|
1198 | } |
1196 |
|
1199 | if(_setdef_changed) accessfile(buf,"w","%s",fname); |
1197 | } |
1200 | } |
1198 | 1201 | ||
1199 | /* check whether connecting host is part of given list. |
1202 | /* check whether connecting host is part of given list. |
1200 | * Returns 0 if no, 1 if yes. |
1203 | * Returns 0 if no, 1 if yes. |
1201 | */ |
1204 | */ |
1202 | int checkhost(char *hlist) |
1205 | int checkhost(char *hlist) |
1203 | { |
1206 | { |
1204 |
|
1207 | char buf[MAX_LINELEN+1]; |
1205 |
|
1208 | char lbuf[1024], hbuf1[256], hbuf2[256]; |
1206 |
|
1209 | char *p1, *p2, *pb, *pe, *pp; |
1207 | 1210 | ||
1208 |
|
1211 | if(*remote_addr==0) return 0; |
1209 |
|
1212 | snprintf(hbuf1,sizeof(hbuf1),"+%s+",remote_addr); |
1210 |
|
1213 | if(*remote_host!=0) { |
1211 |
|
1214 | snprintf(hbuf2,sizeof(hbuf2),"+%s+",remote_host); |
1212 |
|
1215 | for(p1=hbuf2; *p1; p1++) *p1=tolower(*p1); |
1213 |
|
1216 | } |
1214 |
|
1217 | else hbuf2[0]=0; |
1215 |
|
1218 | mystrncpy(buf,find_word_start(hlist),sizeof(buf)); strip_trailing_spaces(buf); |
1216 |
|
1219 | for(p1=buf; *p1; p1++) { |
1217 |
|
1220 | *p1=tolower(*p1); |
1218 |
|
1221 | if(!myisalnum(*p1) && strchr(".-_",*p1)==NULL) *p1=' '; |
1219 |
|
1222 | } |
1220 |
|
1223 | if(strcmp(buf,"all")==0) return 1; /* all is all */ |
1221 |
|
1224 | for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) { |
1222 |
|
1225 | p2=find_word_end(p1); if(*p2) *p2++=0; |
1223 |
|
1226 | if(p2-p1<3) continue; |
1224 |
|
1227 | if(myisalnum(*p1)) pb="+"; else pb=""; |
1225 |
|
1228 | if(myisalnum(*(p2-1))) pe="+"; else pe=""; |
1226 |
|
1229 | snprintf(lbuf,sizeof(lbuf),"%s%s%s",pb,p1,pe); |
1227 |
|
1230 | for(pp=p1; *pp && (myisdigit(*pp) || *pp=='.'); pp++); |
1228 |
|
1231 | if(*pp) pp=hbuf2; /* host name */ |
1229 |
|
1232 | else pp=hbuf1; /* ip number */ |
1230 |
|
1233 | if(strstr(pp,lbuf)!=NULL) return 1; /* found */ |
1231 |
|
1234 | } |
1232 |
|
1235 | return 0; |
1233 | } |
1236 | } |
1234 | 1237 | ||
1235 | /* return 1 if a word of bf2 is a substring of host. |
1238 | /* return 1 if a word of bf2 is a substring of host. |
1236 | * Like checkhost, but with time check. |
1239 | * Like checkhost, but with time check. |
1237 | * The content of bf2[] is destroyed. |
1240 | * The content of bf2[] is destroyed. |
1238 | */ |
1241 | */ |
1239 | int checkhostt(char bf2[]) |
1242 | int checkhostt(char bf2[]) |
1240 | { |
1243 | { |
1241 |
|
1244 | char *p1, *p2, *p3; |
1242 | /* compare with starting time */ |
1245 | /* compare with starting time */ |
1243 |
|
1246 | for(p1=strchr(bf2,'>'); p1!=NULL; p1=strchr(p1+1,'>')) { |
1244 |
|
1247 | if(p1>bf2 && !isspace(*(p1-1))) continue; |
1245 |
|
1248 | p3=find_word_start(++p1); p2=find_word_end(p3); |
1246 |
|
1249 | if(p2-p3!=14) continue; |
1247 |
|
1250 | p3[8]='.'; p3[11]=':'; if(*p2) *p2++=0; |
1248 |
|
1251 | if(strncmp(nowstr,p3,14)<0) return 0; |
1249 |
|
1252 | ovlstrcpy(p1-1,p2); p1-=2; |
1250 |
|
1253 | } |
1251 | /* compare with ending time */ |
1254 | /* compare with ending time */ |
1252 |
|
1255 | for(p1=strchr(bf2,'<'); p1!=NULL; p1=strchr(p1+1,'<')) { |
1253 |
|
1256 | if(p1>bf2 && !isspace(*(p1-1))) continue; |
1254 |
|
1257 | p3=find_word_start(++p1); p2=find_word_end(p3); |
1255 |
|
1258 | if(p2-p3!=14) continue; |
1256 |
|
1259 | p3[8]='.'; p3[11]=':'; if(*p2) *p2++=0; |
1257 |
|
1260 | if(strncmp(nowstr,p3,14)>0) return 0; |
1258 |
|
1261 | ovlstrcpy(p1-1,p2); p1-=2; |
1259 |
|
1262 | } |
1260 |
|
1263 | p1=find_word_start(bf2); if(*p1==0) return 1; |
1261 |
|
1264 | return checkhost(p1); |
1262 | } |
1265 | } |
1263 | 1266 | ||
1264 | /* bad identification */ |
1267 | /* bad identification */ |
1265 | void bad_ident(void) |
1268 | void bad_ident(void) |
1266 | { |
1269 | { |
1267 |
|
1270 | if(cookiegot[0]!=0) { |
1268 |
|
1271 | } |
1269 |
|
1272 | user_error("bad_ident"); |
1270 | } |
1273 | } |
1271 | 1274 | ||
1272 | void instex_flush(void) |
1275 | void instex_flush(void) |
1273 | { |
1276 | { |
1274 |
|
1277 | char *p; |
1275 |
|
1278 | setenv("texgif_style","",1); |
1276 |
|
1279 | setenv("texgif_tmpdir",tmp_dir,1); |
1277 |
|
1280 | setenv("texgif_src",instex_src,1); |
1278 |
|
1281 | setenv("texgif_outfile",instex_fname,1); |
1279 |
|
1282 | unsetenv("w_instex_color"); |
1280 |
|
1283 | getwimstexsize=0; fix_tex_size(); getwimstexsize=1; |
1281 |
|
1284 | for(p=instex_fname;*p;p++) if(*p=='\n') *p=' '; |
1282 |
|
1285 | wrapexec=0; call_ssh("%s/%s >%s/ins.Out 2>%s/ins.Err", |
1283 |
|
1286 | bin_dir,instex_processor, |
1284 |
|
1287 | tmp_dir,tmp_dir); |
1285 |
|
1288 | call_ssh("mv %s %s >/dev/null 2>/dev/null", instex_fname,s2_prefix); |
1286 |
|
1289 | instex_src[0]=instex_fname[0]=0; instex_cnt=0; |
1287 | } |
1290 | } |
1288 | 1291 | ||
1289 | /* put last.phtml */ |
1292 | /* put last.phtml */ |
1290 | void putlastout(void) |
1293 | void putlastout(void) |
1291 | { |
1294 | { |
1292 |
|
1295 | int t; |
1293 |
|
1296 | if(instex_cnt>0) instex_flush(); |
1294 |
|
1297 | t=catfile(stdout,"%s/%s",s2_prefix,lastout); |
1295 |
|
1298 | if(t==0) printf("Content-type: text/plain\r\n\r\n"); |
1296 | } |
1299 | } |
1297 | 1300 | ||
1298 | struct sockaddr_un sun; |
1301 | struct sockaddr_un sun; |
1299 | 1302 | ||
1300 | /* returns >=0 if OK. */ |
1303 | /* returns >=0 if OK. */ |
1301 | 1304 | ||
1302 | int kerneld(char *p, int bufsize) |
1305 | int kerneld(char *p, int bufsize) |
1303 | { |
1306 | { |
1304 |
|
1307 | int sock, s, t, t1, l, *ip; |
1305 |
|
1308 | struct timeval tv; |
1306 |
|
1309 | fd_set rset; |
1307 |
|
1310 | sock=socket(PF_UNIX,SOCK_STREAM,0); |
1308 |
|
1311 | s=connect(sock,(const struct sockaddr *)&sun,sizeof(sun)); |
1309 |
|
1312 | if(s) {bad: close(sock); return -1;} |
1310 |
|
1313 | ip=(int *) p; |
1311 |
|
1314 | l=strlen(p+sizeof(int)); *ip=l; |
1312 |
|
1315 | s=write(sock,p,l+sizeof(int)); if(s!=l+sizeof(int)) goto bad; |
1313 |
|
1316 | for(t=0, l=bufsize-1; t<l+sizeof(int);) { |
1314 |
|
1317 | tv.tv_sec=2; tv.tv_usec=0; |
1315 |
|
1318 | FD_ZERO(&rset); FD_SET(sock,&rset); |
1316 |
|
1319 | if(select(sock+1,&rset,NULL,NULL,&tv)<=0) goto bad; |
1317 |
|
1320 | t1=read(sock,p+t,l+sizeof(int)-t); |
1318 |
|
1321 | if(t1+t<sizeof(int)) goto bad; |
1319 |
|
1322 | if (t1 < 0) goto bad; |
1320 |
|
1323 | l=*ip; if(l<=0) goto bad; |
1321 |
|
1324 | if(l>=bufsize-sizeof(int)-4) user_error("cmd_output_too_long"); |
1322 |
|
1325 | t+=t1; |
1323 |
|
1326 | } |
1324 |
|
1327 | p[l+sizeof(int)]=0; |
1325 |
|
1328 | close(sock); |
1326 |
|
1329 | return l+sizeof(int); |
1327 | } |
1330 | } |
1328 | 1331 | ||
1329 | void _daemoncmd(char *p) |
1332 | void _daemoncmd(char *p) |
1330 | { |
1333 | { |
1331 |
|
1334 | char buf[MAX_LINELEN+1+sizeof(int)]; |
1332 |
|
1335 | char *p1, *p2, *p3; |
1333 |
|
1336 | mystrncpy(buf+sizeof(int),p,sizeof(buf)-sizeof(int)); |
1334 |
|
1337 | if(kerneld(buf,sizeof(buf))<0) |
1335 |
|
1338 | internal_error("Daemon communication error."); |
1336 |
|
1339 | p1=find_word_start(buf+sizeof(int)); |
1337 |
|
1340 | p2=find_word_end(p1); if(*p2) *p2++=0; |
1338 |
|
1341 | if(strcmp(p1,"OK")==0) { |
1339 |
|
1342 | mystrncpy(p,p2,MAX_LINELEN); return; |
1340 |
|
1343 | } |
1341 |
|
1344 | p1=find_word_start(p2); p2=find_word_end(p1); if(*p2) *p2++=0; |
1342 |
|
1345 | p2=find_word_start(p2); p3=find_word_end(p2); |
1343 |
|
1346 | if(*p3) { |
1344 |
|
1347 | *p3++=0; p3=find_word_start(p3); strip_trailing_spaces(p3); |
1345 |
|
1348 | setvar("wims_error_data",p3); |
1346 |
|
1349 | } |
1347 |
|
1350 | switch(*p1) { |
1348 |
|
1351 | case '1': user_error(p2); |
1349 |
|
1352 | case '2': module_error(p2); |
1350 |
|
1353 | case '3': |
1351 |
|
1354 | default: internal_error(p2); |
1352 |
|
1355 | } |
1353 |
|
1356 | *p=0; |
1354 | } |
1357 | } |
1355 | - |