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