Rev 8185 | Rev 10051 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8185 | Rev 8343 | ||
---|---|---|---|
Line 48... | Line 48... | ||
48 | 48 | ||
49 | /* These modules can execute private programs. |
49 | /* These modules can execute private programs. |
50 | * adm/ modules are always trusted, so need no definition here. |
50 | * adm/ modules are always trusted, so need no definition here. |
51 | */ |
51 | */ |
52 | char *trusted_modules=""; |
52 | char *trusted_modules=""; |
53 |
|
53 | /* bit 0: module is not trusted. |
54 | |
54 | * bit 1: file in wimshome. |
55 | |
55 | * bit 2: readdef or file in writable directory. |
56 | |
56 | */ |
57 | int untrust=0; /* non-zero if user detrusts the module. */ |
57 | int untrust=0; /* non-zero if user detrusts the module. */ |
58 | 58 | ||
59 | int error_status=0; |
59 | int error_status=0; |
60 | char pidbuf[32]; |
60 | char pidbuf[32]; |
61 | 61 | ||
62 | void delete_pid(void); |
62 | void delete_pid(void); |
63 | 63 | ||
64 |
|
64 | /* Internal use only */ |
65 | void _debug(char *s,...) |
65 | void _debug(char *s,...) |
66 | { |
66 | { |
67 | va_list vp; |
67 | va_list vp; |
68 | char buf[MAX_LINELEN+1]; |
68 | char buf[MAX_LINELEN+1]; |
69 | 69 | ||
Line 73... | Line 73... | ||
73 | setvar("debug",buf); module_error("debug"); |
73 | setvar("debug",buf); module_error("debug"); |
74 | exit(1); |
74 | exit(1); |
75 | } |
75 | } |
76 | 76 | ||
77 | 77 | ||
78 |
|
78 | /* HTTP response header for non-processed CGI interface */ |
79 | void nph_header(int code) |
79 | void nph_header(int code) |
80 | { |
80 | { |
81 | char *cstr; |
81 | char *cstr; |
82 | switch(code) { |
82 | switch(code) { |
83 | case 200: cstr="OK"; break; |
83 | case 200: cstr="OK"; break; |
Line 118... | Line 118... | ||
118 | fprintf(stderr,"wims: %s\n%s\n",msg,strerror(errno)); |
118 | fprintf(stderr,"wims: %s\n%s\n",msg,strerror(errno)); |
119 | snprintf(buf,sizeof(buf),"%s: %s\n",nowstr,msg); |
119 | snprintf(buf,sizeof(buf),"%s: %s\n",nowstr,msg); |
120 | accessfile(buf,"a","%s/internal_error.log",log_dir); |
120 | accessfile(buf,"a","%s/internal_error.log",log_dir); |
121 | } |
121 | } |
122 | 122 | ||
123 |
|
123 | /* Internal error: panic and forget about requester. */ |
124 | void internal_error(char msg[]) |
124 | void internal_error(char msg[]) |
125 | { |
125 | { |
126 | if(error_status<2) { |
126 | if(error_status<2) { |
127 | nph_header(500); |
127 | nph_header(500); |
128 | printf("Cache-Control: no-cache\nPragma: no-cache\r\n\ |
128 | printf("Cache-Control: no-cache\nPragma: no-cache\r\n\ |
Line 156... | Line 156... | ||
156 | module_error("file_name_too_long"); |
156 | module_error("file_name_too_long"); |
157 | } |
157 | } |
158 | 158 | ||
159 | off_t ftest_size; |
159 | off_t ftest_size; |
160 | 160 | ||
161 |
|
161 | /* A simple front-end of stat(). */ |
162 | int ftest(char *fname) |
162 | int ftest(char *fname) |
163 | { |
163 | { |
164 | if(strcmp(fname,lastftest)==0) return lastftype; |
164 | if(strcmp(fname,lastftest)==0) return lastftype; |
165 | /* if(fname[0]=='/' || fname[0]=='.') fprintf(stderr,"ftest: %s\n",fname); */ |
165 | /* if(fname[0]=='/' || fname[0]=='.') fprintf(stderr,"ftest: %s\n",fname); */ |
166 | mystrncpy(lastftest,fname,sizeof(lastftest)); |
166 | mystrncpy(lastftest,fname,sizeof(lastftest)); |
Line 176... | Line 176... | ||
176 | return lastftype=is_unknown; |
176 | return lastftype=is_unknown; |
177 | } |
177 | } |
178 | 178 | ||
179 | char fnbuf[MAX_FNAME+1]; |
179 | char fnbuf[MAX_FNAME+1]; |
180 | 180 | ||
181 |
|
181 | /* make a filename and check length */ |
182 | char *mkfname(char buf[], char *s,...) |
182 | char *mkfname(char buf[], char *s,...) |
183 | { |
183 | { |
184 | va_list vp; |
184 | va_list vp; |
185 | char *p; |
185 | char *p; |
186 | 186 | ||
Line 198... | Line 198... | ||
198 | struct stat st; |
198 | struct stat st; |
199 | mkfname(buf,"%s/%s",sysmask_trigger_dir,s); |
199 | mkfname(buf,"%s/%s",sysmask_trigger_dir,s); |
200 | stat(buf,&st); |
200 | stat(buf,&st); |
201 | } |
201 | } |
202 | 202 | ||
203 |
|
203 | /* read-in a file into buffer. Use open() and read(). |
204 | * Return buffer address which will be malloc'ed if buf=NULL. */ |
204 | * Return buffer address which will be malloc'ed if buf=NULL. */ |
205 | char *readfile(char *fname, char buf[], long int buflen) |
205 | char *readfile(char *fname, char buf[], long int buflen) |
206 | { |
206 | { |
207 | int fd, t, st; |
207 | int fd, t, st; |
208 | long int l, lc; |
208 | long int l, lc; |
Line 230... | Line 230... | ||
230 | if(lc<0 || lc>l || (lc!=l && t==0)) |
230 | if(lc<0 || lc>l || (lc!=l && t==0)) |
231 | {if(buf==NULL) free(bf); else buf[0]=0; return NULL;} |
231 | {if(buf==NULL) free(bf); else buf[0]=0; return NULL;} |
232 | bf[lc]=0; _tolinux(bf); return bf; |
232 | bf[lc]=0; _tolinux(bf); return bf; |
233 | } |
233 | } |
234 | 234 | ||
235 |
|
235 | /* Get a line in a stored working file. |
236 | * Buffer length is always MAX_LINELEN. */ |
236 | * Buffer length is always MAX_LINELEN. */ |
237 | int wgetline(char buf[], size_t buflen, WORKING_FILE *f) |
237 | int wgetline(char buf[], size_t buflen, WORKING_FILE *f) |
238 | { |
238 | { |
239 | int i,j; unsigned int n; |
239 | int i,j; unsigned int n; |
240 | i=f->linepointer; buf[0]=0; |
240 | i=f->linepointer; buf[0]=0; |
Line 260... | Line 260... | ||
260 | } |
260 | } |
261 | } |
261 | } |
262 | return -1; |
262 | return -1; |
263 | } |
263 | } |
264 | 264 | ||
265 |
|
265 | /* Open a work file. Returns 0 if OK. */ |
266 | int open_working_file(WORKING_FILE *f, char *fname) |
266 | int open_working_file(WORKING_FILE *f, char *fname) |
267 | { |
267 | { |
268 | char *p, *q; |
268 | char *p, *q; |
269 | void *vp; |
269 | void *vp; |
270 | int i,j,k,laststart,lc[LINE_LIMIT]; |
270 | int i,j,k,laststart,lc[LINE_LIMIT]; |
Line 322... | Line 322... | ||
322 | f->lines[i].isstart=1; f->lines[i].llen=0; |
322 | f->lines[i].isstart=1; f->lines[i].llen=0; |
323 | f->lines[i].address=(f->textbuf)+lc[i]; |
323 | f->lines[i].address=(f->textbuf)+lc[i]; |
324 | mfilecnt++; return 0; |
324 | mfilecnt++; return 0; |
325 | } |
325 | } |
326 | 326 | ||
327 |
|
327 | /* close an earlier opened working file */ |
328 | void close_working_file(WORKING_FILE *f, int cache) |
328 | void close_working_file(WORKING_FILE *f, int cache) |
329 | { |
329 | { |
330 | f->linepointer=f->l=0; |
330 | f->linepointer=f->l=0; |
331 | if(cache && untrust==0 && mcachecnt<MAX_MCACHE && (f->nocache&7)==0) { |
331 | if(cache && untrust==0 && mcachecnt<MAX_MCACHE && (f->nocache&7)==0) { |
332 | memmove(mcache+mcachecnt,f,sizeof(WORKING_FILE)); |
332 | memmove(mcache+mcachecnt,f,sizeof(WORKING_FILE)); |
Line 356... | Line 356... | ||
356 | nph_header(420); |
356 | nph_header(420); |
357 | printf("\r\n\r\nWIMS error processing aborted on nested error.\r\n\r\n%s\r\n",msg); |
357 | printf("\r\n\r\nWIMS error processing aborted on nested error.\r\n\r\n%s\r\n",msg); |
358 | delete_pid(); exit(1); |
358 | delete_pid(); exit(1); |
359 | } |
359 | } |
360 | 360 | ||
361 |
|
361 | /* Send an error message to requester and exit. |
362 | |
362 | * This is for user errors, language-sensitive. |
- | 363 | */ |
|
363 | void user_error(char msg[]) |
364 | void user_error(char msg[]) |
364 | { |
365 | { |
365 | char erfname[MAX_FNAME+1]; |
366 | char erfname[MAX_FNAME+1]; |
366 | 367 | ||
367 | if(error_status) nested_error(msg); |
368 | if(error_status) nested_error(msg); |
Line 384... | Line 385... | ||
384 | flushoutput(); exit(0); |
385 | flushoutput(); exit(0); |
385 | } |
386 | } |
386 | 387 | ||
387 | void module_error_log(char msg[]); |
388 | void module_error_log(char msg[]); |
388 | 389 | ||
389 |
|
390 | /* Messages for module errors. English only. |
390 |
|
391 | * This is really rudimentary for the time being. |
- | 392 | */ |
|
391 | void module_error(char msg[]) |
393 | void module_error(char msg[]) |
392 | { |
394 | { |
393 | int send=0; |
395 | int send=0; |
394 | char *p; |
396 | char *p; |
395 | WORKING_FILE mf; |
397 | WORKING_FILE mf; |
Line 469... | Line 471... | ||
469 | vsnprintf(buf,sizeof(buf),s,vp); |
471 | vsnprintf(buf,sizeof(buf),s,vp); |
470 | va_end(vp); |
472 | va_end(vp); |
471 | output0(buf); |
473 | output0(buf); |
472 | } |
474 | } |
473 | 475 | ||
474 |
|
476 | /* read in tmpf in tmp directory, and places in p. |
475 | |
477 | * Maximal length: MAX_LINELEN. |
- | 478 | */ |
|
476 | void read_tmp_file(char *p, const char *fname) |
479 | void read_tmp_file(char *p, const char *fname) |
477 | { |
480 | { |
478 | char *name, *pp; |
481 | char *name, *pp; |
479 | name=mkfname(NULL,"%s/%s",tmp_dir,fname); |
482 | name=mkfname(NULL,"%s/%s",tmp_dir,fname); |
480 | if(!exec_is_module || !outputing || !direct_exec |
483 | if(!exec_is_module || !outputing || !direct_exec |
Line 497... | Line 500... | ||
497 | free(s); *p=0; |
500 | free(s); *p=0; |
498 | chmod(name,S_IRUSR|S_IWUSR); |
501 | chmod(name,S_IRUSR|S_IWUSR); |
499 | } |
502 | } |
500 | } |
503 | } |
501 | 504 | ||
502 |
|
505 | /* verify whether the module is trusted. |
503 |
|
506 | * Returns 1 if yes, 0 if no. -1 for error. |
- | 507 | */ |
|
504 | int trusted_module(void) |
508 | int trusted_module(void) |
505 | { |
509 | { |
506 | char *modname, *w, buf[MAX_LINELEN+1]; |
510 | char *modname, *w, buf[MAX_LINELEN+1]; |
507 | int i,n; |
511 | int i,n; |
508 | static int _trusted=-1; /* avoid repeated computations */ |
512 | static int _trusted=-1; /* avoid repeated computations */ |
Line 526... | Line 530... | ||
526 | if(strcmp(w,modname)==0) goto tr; |
530 | if(strcmp(w,modname)==0) goto tr; |
527 | } |
531 | } |
528 | return _trusted=0; |
532 | return _trusted=0; |
529 | } |
533 | } |
530 | 534 | ||
531 |
|
535 | /* file should be in the module directory, but |
532 |
|
536 | * it may also be somewhere else. |
533 |
|
537 | * buf[] requires MAX_FNAME+1 length. |
534 | |
538 | * Returns 0 if found. |
- | 539 | */ |
|
535 | int find_module_file(char *fname, char buf[], int mode) |
540 | int find_module_file(char *fname, char buf[], int mode) |
536 | { |
541 | { |
537 | char *p, dtest[32]; |
542 | char *p, dtest[32]; |
538 | 543 | ||
539 | fname=find_word_start(fname); |
544 | fname=find_word_start(fname); |
540 | if(*fname==0) return -1; |
545 | if(*fname==0) return -1; |
541 |
|
546 | /* Name checking: no directory backtracing. */ |
542 | if(strstr(fname,parent_dir_string)!=NULL) { |
547 | if(strstr(fname,parent_dir_string)!=NULL) { |
543 | setvar(error_data_string,fname); module_error("illegal_fname"); |
548 | setvar(error_data_string,fname); module_error("illegal_fname"); |
544 | return -1; |
549 | return -1; |
545 | } |
550 | } |
546 | p=strchr(fname,'/'); if(p==NULL || p>fname+10) goto openit; |
551 | p=strchr(fname,'/'); if(p==NULL || p>fname+10) goto openit; |
Line 581... | Line 586... | ||
581 | } |
586 | } |
582 | } |
587 | } |
583 | return 0; |
588 | return 0; |
584 | } |
589 | } |
585 | 590 | ||
586 |
|
591 | /* check whether a file is user-submitted |
587 |
|
592 | * This is deprecated because of the wimshome/ method. |
- | 593 | */ |
|
588 | /* int user_file(char *name) { |
594 | /* int user_file(char *name) { |
589 | if(name[0]=='/' || name[0]=='.' || |
595 | if(name[0]=='/' || name[0]=='.' || |
590 | strstr(name,"classes/")!=NULL || |
596 | strstr(name,"classes/")!=NULL || |
591 | strstr(name,"forums/")!=NULL || |
597 | strstr(name,"forums/")!=NULL || |
592 | strstr(name,"sessions/")!=NULL || |
598 | strstr(name,"sessions/")!=NULL || |
593 | strstr(name,"doc/")!=NULL) return 1; else return 0; |
599 | strstr(name,"doc/")!=NULL) return 1; else return 0; |
- | 600 | } |
|
594 |
|
601 | */ |
595 | 602 | ||
596 |
|
603 | /* returns 1 if violation */ |
597 | int datafile_check(char *name) { |
604 | int datafile_check(char *name) { |
598 | if((untrust&255)==0) return 0; |
605 | if((untrust&255)==0) return 0; |
599 | if(strncmp(name,"data/",strlen("data/"))==0) return 0; |
606 | if(strncmp(name,"data/",strlen("data/"))==0) return 0; |
600 | if(strncmp(name,"authors/",strlen("authors/"))==0) return 0; |
607 | if(strncmp(name,"authors/",strlen("authors/"))==0) return 0; |
601 | if(strncmp(name,"datamodule/",strlen("datamodule/"))==0) return 0; |
608 | if(strncmp(name,"datamodule/",strlen("datamodule/"))==0) return 0; |
602 | return 1; |
609 | return 1; |
603 | } |
610 | } |
604 | 611 | ||
605 |
|
612 | /* returns 0 if success */ |
606 | void readdatafile(char *name) |
613 | void readdatafile(char *name) |
607 | { |
614 | { |
608 | char *pp; |
615 | char *pp; |
609 | if(strcmp(name,lastdatafile)==0) return; |
616 | if(strcmp(name,lastdatafile)==0) return; |
610 | lastdata[0]=0; readfile(name,lastdata,WORKFILE_LIMIT); |
617 | lastdata[0]=0; readfile(name,lastdata,WORKFILE_LIMIT); |
Line 625... | Line 632... | ||
625 | pp=strstr(p,tag_string); |
632 | pp=strstr(p,tag_string); |
626 | if(pp) return pp; |
633 | if(pp) return pp; |
627 | else return p+strlen(p); |
634 | else return p+strlen(p); |
628 | } |
635 | } |
629 | 636 | ||
630 |
|
637 | /* datafile structure: number of records. |
631 | |
638 | * tag=1 if direct access |
- | 639 | */ |
|
632 | unsigned int datafile_recordnum(char *p) |
640 | unsigned int datafile_recordnum(char *p) |
633 | { |
641 | { |
634 | char nbuf[MAX_LINELEN+1], *pp; |
642 | char nbuf[MAX_LINELEN+1], *pp; |
635 | int i, t, ret; |
643 | int i, t, ret; |
636 | 644 | ||
Line 648... | Line 656... | ||
648 | ret: |
656 | ret: |
649 | untrust=t; |
657 | untrust=t; |
650 | return ret; |
658 | return ret; |
651 | } |
659 | } |
652 | 660 | ||
653 |
|
661 | /* datafile structure: find record n, starting from 1 */ |
654 | char *datafile_fnd_record(char *p, int n, char bf[]) |
662 | char *datafile_fnd_record(char *p, int n, char bf[]) |
655 | { |
663 | { |
656 | char nbuf[MAX_LINELEN+1], *pp, *p2; |
664 | char nbuf[MAX_LINELEN+1], *pp, *p2; |
657 | int i, t; |
665 | int i, t; |
658 | 666 | ||
Line 703... | Line 711... | ||
703 | if(c1>='A') c1=c1-'A'+'9'+1; |
711 | if(c1>='A') c1=c1-'A'+'9'+1; |
704 | if(c2>='A') c2=c2-'A'+'9'+1; |
712 | if(c2>='A') c2=c2-'A'+'9'+1; |
705 | return (c1-'0')*16+c2-'0'; |
713 | return (c1-'0')*16+c2-'0'; |
706 | } |
714 | } |
707 | 715 | ||
708 |
|
716 | /* Converts back http escaped chars, slight. Does not check buffer length. |
709 | |
717 | * Returns converted string length. |
- | 718 | */ |
|
710 | int _http2env(char outs[], char ins[]) |
719 | int _http2env(char outs[], char ins[]) |
711 | { |
720 | { |
712 | int j,k,l; |
721 | int j,k,l; |
713 | l=strlen(ins); |
722 | l=strlen(ins); |
714 | for(j=k=0;j<l && !isspace(ins[j]);j++,k++) { |
723 | for(j=k=0;j<l && !isspace(ins[j]);j++,k++) { |
715 | if(isspace(ins[j])) { /* skip space characters in query string */ |
724 | if(isspace(ins[j])) { /* skip space characters in query string */ |
716 | k--;continue; |
725 | k--;continue; |
717 | } |
726 | } |
718 | if(ins[j]=='%') { |
727 | if(ins[j]=='%') { |
719 |
|
728 | /* skip Carriage-Return. */ |
720 | if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) { |
729 | if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) { |
721 | j+=2; k--; continue; |
730 | j+=2; k--; continue; |
722 | } |
731 | } |
723 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
732 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
724 | j+=2; continue; |
733 | j+=2; continue; |
Line 727... | Line 736... | ||
727 | } |
736 | } |
728 | outs[k]=0; |
737 | outs[k]=0; |
729 | return k; |
738 | return k; |
730 | } |
739 | } |
731 | 740 | ||
732 |
|
741 | /* Converts back http escaped chars. Does not check buffer length. |
733 | |
742 | * Returns converted string length. |
- | 743 | */ |
|
734 | int http2env(char outs[], char ins[]) |
744 | int http2env(char outs[], char ins[]) |
735 | { |
745 | { |
736 | int j,k,l; |
746 | int j,k,l; |
737 | l=strlen(ins); |
747 | l=strlen(ins); |
738 | for(j=k=0;j<l && !isspace(ins[j]);j++,k++) { |
748 | for(j=k=0;j<l && !isspace(ins[j]);j++,k++) { |
739 | if(isspace(ins[j])) { /* skip space characters in query string */ |
749 | if(isspace(ins[j])) { /* skip space characters in query string */ |
740 | k--;continue; |
750 | k--;continue; |
741 | } |
751 | } |
742 | if(ins[j]=='%') { |
752 | if(ins[j]=='%') { |
743 |
|
753 | /* skip Carriage-Return. */ |
744 | if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) { |
754 | if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) { |
745 | j+=2; k--; continue; |
755 | j+=2; k--; continue; |
746 | } |
756 | } |
747 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
757 | outs[k]=hex2char(ins[j+1],ins[j+2]); |
748 | j+=2; continue; |
758 | j+=2; continue; |
Line 757... | Line 767... | ||
757 | } |
767 | } |
758 | outs[k]=0; |
768 | outs[k]=0; |
759 | return k; |
769 | return k; |
760 | } |
770 | } |
761 | 771 | ||
762 |
|
772 | /* translate a string to http querystring style. |
763 |
|
773 | * '&' is not translated. |
764 | |
774 | * Buffer p must be at least MAX_LINELEN. |
- | 775 | */ |
|
765 | void tohttpquery(char *p) |
776 | void tohttpquery(char *p) |
766 | { |
777 | { |
767 | char trlist[]=" ()[]{}+-*^|/\"\'!:;,<>\n"; |
778 | char trlist[]=" ()[]{}+-*^|/\"\'!:;,<>\n"; |
768 | char *pp; |
779 | char *pp; |
769 | for(pp=p;*pp;pp++) { |
780 | for(pp=p;*pp;pp++) { |
Line 782... | Line 793... | ||
782 | string_modify(p,pp,pp+1,"%%%02X",*pp);pp+=2; |
793 | string_modify(p,pp,pp+1,"%%%02X",*pp);pp+=2; |
783 | } |
794 | } |
784 | } |
795 | } |
785 | } |
796 | } |
786 | 797 | ||
787 |
|
798 | /* substitute backslash parameters. Internal use only. */ |
788 | void slashsubst(char *p) |
799 | void slashsubst(char *p) |
789 | { |
800 | { |
790 | char *p1, *p2, *pt, *pp, namebuf[128]; |
801 | char *p1, *p2, *pt, *pp, namebuf[128]; |
791 | int n; |
802 | int n; |
792 | 803 | ||
Line 802... | Line 813... | ||
802 | } |
813 | } |
803 | else string_modify(p,p1-1,p1,"$%s",mathfont_prefix); |
814 | else string_modify(p,p1-1,p1,"$%s",mathfont_prefix); |
804 | } |
815 | } |
805 | } |
816 | } |
806 | 817 | ||
807 |
|
818 | /* two alarm handlers. */ |
808 | void alarm1(int s) |
819 | void alarm1(int s) |
809 | { |
820 | { |
810 | if(killpid>0 && kill(killpid,SIGKILL)) module_error("timeup"); |
821 | if(killpid>0 && kill(killpid,SIGKILL)) module_error("timeup"); |
811 | killpid=0; |
822 | killpid=0; |
812 | } |
823 | } |
Line 842... | Line 853... | ||
842 | if(signal(SIGALRM,alarm1)==SIG_ERR) |
853 | if(signal(SIGALRM,alarm1)==SIG_ERR) |
843 | internal_error(strerror(errno)); |
854 | internal_error(strerror(errno)); |
844 | alarm(limtimex-curr+1); |
855 | alarm(limtimex-curr+1); |
845 | } |
856 | } |
846 | 857 | ||
847 |
|
858 | /* create pid tag */ |
848 | void create_pid(void) |
859 | void create_pid(void) |
849 | { |
860 | { |
850 | char buf[MAX_FNAME+1], pbuf[256], obuf[MAX_FNAME+1]; |
861 | char buf[MAX_FNAME+1], pbuf[256], obuf[MAX_FNAME+1]; |
851 | struct stat dst; |
862 | struct stat dst; |
852 | struct utimbuf ub; |
863 | struct utimbuf ub; |
853 | 864 | ||
854 | if(robot_access || *session_prefix==0) return; |
865 | if(robot_access || *session_prefix==0) return; |
855 | if(cmd_type==cmd_getframe) return; |
866 | if(cmd_type==cmd_getframe) return; |
856 | mkfname(buf,"%s/.pid",s2_prefix); |
867 | mkfname(buf,"%s/.pid",s2_prefix); |
857 |
|
868 | /* another process running? */ |
858 | if(readfile(buf,pbuf,sizeof(pbuf))!=NULL) { |
869 | if(readfile(buf,pbuf,sizeof(pbuf))!=NULL) { |
859 | mkfname(obuf,"/proc/%s",pbuf); |
870 | mkfname(obuf,"/proc/%s",pbuf); |
860 | if(stat(obuf,&dst)==0) user_error("double_click"); |
871 | if(stat(obuf,&dst)==0) user_error("double_click"); |
861 | } |
872 | } |
862 | snprintf(pidbuf,sizeof(pidbuf),"%u",getpid()); |
873 | snprintf(pidbuf,sizeof(pidbuf),"%u",getpid()); |
863 | accessfile(pidbuf,"w","%s",buf); |
874 | accessfile(pidbuf,"w","%s",buf); |
864 |
|
875 | /* Touch session time */ |
865 | if(strstr(session_prefix,"sessions/")==NULL) return; |
876 | if(strstr(session_prefix,"sessions/")==NULL) return; |
866 | ub.actime=ub.modtime=nowtime; |
877 | ub.actime=ub.modtime=nowtime; |
867 | utime(session_prefix,&ub); |
878 | utime(session_prefix,&ub); |
868 | if(strchr(session_prefix,'_')!=NULL) { /* touch parent too */ |
879 | if(strchr(session_prefix,'_')!=NULL) { /* touch parent too */ |
869 | char sbuf[MAX_FNAME+1], *p; |
880 | char sbuf[MAX_FNAME+1], *p; |
Line 886... | Line 897... | ||
886 | if(errf!=NULL) |
897 | if(errf!=NULL) |
887 | accessfile("No time left to execute subprograms.\n","w","%s",errf); |
898 | accessfile("No time left to execute subprograms.\n","w","%s",errf); |
888 | return -100; |
899 | return -100; |
889 | } |
900 | } |
890 | lastdatafile[0]=lastftest[0]=0; |
901 | lastdatafile[0]=lastftest[0]=0; |
891 | fflush(NULL); |
902 | fflush(NULL); /* flush all output streams before forking |
892 | * otherwise they will be doubled |
903 | * otherwise they will be doubled |
- | 904 | */ |
|
893 | pid=fork(); if(pid==-1) return -1; |
905 | pid=fork(); if(pid==-1) return -1; |
894 | if(!pid) { /* child */ |
906 | if(!pid) { /* child */ |
895 | char buf[MAX_LINELEN+1]; int k; |
907 | char buf[MAX_LINELEN+1]; int k; |
896 | (void)nice(10); /* lower priority for children */ |
908 | (void)nice(10); /* lower priority for children */ |
897 | if(is_multiexec) { |
909 | if(is_multiexec) { |
Line 902... | Line 914... | ||
902 | else { |
914 | else { |
903 | if(inf!=NULL) (void)freopen(inf,"r",stdin); |
915 | if(inf!=NULL) (void)freopen(inf,"r",stdin); |
904 | if(outf!=NULL) (void)freopen(outf,"w",stdout); |
916 | if(outf!=NULL) (void)freopen(outf,"w",stdout); |
905 | if(errf!=NULL) (void)freopen(errf,"w",stderr); |
917 | if(errf!=NULL) (void)freopen(errf,"w",stderr); |
906 | } |
918 | } |
907 |
|
919 | /* This is to patch LinuxPPC uid wrapping |
908 |
|
920 | * for scripts */ |
909 | t=0; if(strchr(cmdf,'/')) { |
921 | t=0; if(strchr(cmdf,'/')) { |
910 | int tf; |
922 | int tf; |
911 | char tbuf[16]; |
923 | char tbuf[16]; |
912 | tf=open(cmdf,O_RDONLY); (void)read(tf,tbuf,8); close(tf); |
924 | tf=open(cmdf,O_RDONLY); (void)read(tf,tbuf,8); close(tf); |
913 | if(memcmp(tbuf+1,"ELF",3)!=0) t=1; |
925 | if(memcmp(tbuf+1,"ELF",3)!=0) t=1; |
Line 939... | Line 951... | ||
939 | } |
951 | } |
940 | return WEXITSTATUS(status); |
952 | return WEXITSTATUS(status); |
941 | } |
953 | } |
942 | } |
954 | } |
943 | 955 | ||
944 |
|
956 | /* preparation for resident execution. |
945 | |
957 | * Returns 1 if already up, otherwise 0. |
- | 958 | */ |
|
946 | int multiexec(char *cmd, char **abuf) |
959 | int multiexec(char *cmd, char **abuf) |
947 | { |
960 | { |
948 | char *p; |
961 | char *p; |
949 | int i; |
962 | int i; |
950 | 963 | ||
Line 975... | Line 988... | ||
975 | } |
988 | } |
976 | is_multiexec=0; |
989 | is_multiexec=0; |
977 | return 1; |
990 | return 1; |
978 | } |
991 | } |
979 | 992 | ||
980 |
|
993 | /* my system(), but with variable parms |
981 |
|
994 | * More secure than system(), and direct fork. |
- | 995 | */ |
|
982 | int call_ssh(char *s,...) |
996 | int call_ssh(char *s,...) |
983 | { |
997 | { |
984 | va_list vp; |
998 | va_list vp; |
985 | char buf[MAX_LINELEN+1]; |
999 | char buf[MAX_LINELEN+1]; |
986 | char *arg[1024]; |
1000 | char *arg[1024]; |
Line 1029... | Line 1043... | ||
1029 | } |
1043 | } |
1030 | arg[i]=NULL; |
1044 | arg[i]=NULL; |
1031 | return execredirected(cmdf,inf,outf,errf,arg); |
1045 | return execredirected(cmdf,inf,outf,errf,arg); |
1032 | } |
1046 | } |
1033 | 1047 | ||
1034 |
|
1048 | /* Read/write to a file with variable parms to print filename */ |
1035 | void accessfile(char *content, char *type, char *s,...) |
1049 | void accessfile(char *content, char *type, char *s,...) |
1036 | { |
1050 | { |
1037 | va_list vp; |
1051 | va_list vp; |
1038 | char buf[MAX_FNAME+1]; |
1052 | char buf[MAX_FNAME+1]; |
1039 | int fd; |
1053 | int fd; |
Line 1053... | Line 1067... | ||
1053 | lastdatafile[0]=lastftest[0]=0; |
1067 | lastdatafile[0]=lastftest[0]=0; |
1054 | if(fd==-1) return; |
1068 | if(fd==-1) return; |
1055 | (void)write(fd,content,strlen(content)); close(fd); |
1069 | (void)write(fd,content,strlen(content)); close(fd); |
1056 | } |
1070 | } |
1057 | 1071 | ||
1058 |
|
1072 | /* system(), but with variable parms |
1059 | |
1073 | * Uses sh to execute command. |
- | 1074 | */ |
|
1060 | int call_sh(char *s,...) |
1075 | int call_sh(char *s,...) |
1061 | { |
1076 | { |
1062 | va_list vp; |
1077 | va_list vp; |
1063 | char buf[MAX_LINELEN+1]; |
1078 | char buf[MAX_LINELEN+1]; |
1064 | char *abuf[8]; |
1079 | char *abuf[8]; |