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