Subversion Repositories wimsdev

Rev

Rev 3843 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18.         /* Common routines in interfaces */
  19.  
  20. #define ch_root "bin/ch..root"
  21.  
  22. int mypid;
  23. int must_chroot=0;
  24. char inputfname[256], outputfname[256];
  25. char pidfname[256];
  26. char parmbuf[parmlim+16];
  27. char *inpf, *outpf, *errorf;
  28. char *parm;
  29. char *tmp_dir;
  30. char cmdbuf[1024];
  31. char inputbuf[inputlim];
  32. char *inputptr, *inputend;
  33. char stdinbuf[MAX_LINELEN+1];
  34. char *cmdparm;
  35. int isabout=0;
  36. char *multiexec_random;
  37. int multiexec=0, mxpid, notfirst;
  38. int pipe_in[2], pipe_out[2];
  39. int debug=0;
  40. FILE *goin;
  41. unsigned int seed;      /* random seed value */
  42. char aboutbuf[aboutlen];
  43.         /* this is only a default. It should usually be reset. */
  44. char *tmpdir="/tmp";
  45. char startstring[256], endstring[256];
  46. char *obuf;
  47.  
  48. void check_parm(char *p);
  49. void output(char *p);
  50. void about(void);
  51. char *dynsetup(char *p, char *end);
  52.  
  53. void *xmalloc(size_t n)
  54. {
  55.     void *p;
  56.     p=malloc(n);
  57.     if(p==NULL) {
  58.         fprintf(stderr, "%s: Malloc failure.\n",progname);
  59.         exit(1);
  60.     }
  61.     return p;
  62. }
  63.  
  64.         /* strip trailing spaces; return string end. */
  65. char *strip_trailing_spaces(char *p)
  66. {
  67.     char *pp;
  68.     if(*p==0) return p;
  69.     for(pp=p+strlen(p)-1; pp>=p && isspace(*pp); *(pp--)=0);
  70.     return pp;
  71. }
  72.  
  73.         /* Points to the end of the word */
  74. char *find_word_end(char *p)
  75. {
  76.     int i;
  77.     for(i=0;!isspace(*p) && *p!=0 && i<MAX_LINELEN; p++,i++);
  78.     return p;
  79. }
  80.  
  81.         /* Strips leading spaces */
  82. char *find_word_start(char *p)
  83. {
  84.     int i;
  85.     for(i=0; isspace(*p) && i<MAX_LINELEN; p++,i++);
  86.     return p;
  87. }
  88.  
  89.         /* Find first occurrence of word */
  90. char *wordchr(char *p, char *w)
  91. {
  92.     char *r;
  93.  
  94.     if(*w==0) return NULL;
  95.     for(r=strstr(p,w);r!=NULL &&
  96.         ( (r>p && !isspace(*(r-1))) || (!isspace(*(r+strlen(w))) && *(r+strlen(w))!=0) );
  97.         r=strstr(r+1,w));
  98.     return r;
  99. }
  100.  
  101.          /* Returns the pointer or NULL. */
  102. char *varchr(char *p, char *v)
  103. {
  104.         char *pp; int n=strlen(v);
  105.         for(pp=strstr(p,v); pp!=NULL; pp=strstr(pp+1,v)) {
  106.             if((pp==p || (!isalnum(*(pp-1)) && *(pp-1)!='_')) &&
  107.                ((!isalnum(*(pp+n)) && *(pp+n)!='_') || *(pp+n)==0)) break;
  108.         }
  109.         return pp;
  110. }
  111.  
  112.         /* find matching parenthesis */
  113. char *find_matching(char *p, char c)
  114. {
  115.     char *pp;
  116.     int parenth, brak, brace;
  117.     parenth=brak=brace=0;
  118.     for(pp=p; *pp!=0; pp++) {
  119.         switch(*pp) {
  120.             case '[': brak++; break;
  121.             case ']': brak--; break;
  122.             case '(': parenth++; break;
  123.             case ')': parenth--; break;
  124.             case '{': brace++; break;
  125.             case '}': brace--; break;
  126.             default: continue;
  127.         }
  128.         if(parenth<0 || brak<0 || brace<0) {
  129.             if(*pp!=c || parenth>0 || brak>0 || brace>0) return NULL;
  130.             else break;
  131.         }
  132.     }
  133.     if(*pp!=c) return NULL;
  134.     return pp;
  135. }
  136.  
  137.         /* searches a list. Returns index if found, -1 if nomatch.
  138.          * Uses binary search, list must be sorted. */
  139. int search_list(void *list, int items, size_t item_size, const char *str)
  140. {
  141.     int i1,i2,j,k;
  142.     char **p;
  143.     char c;
  144.    
  145.     if(items<=0) return -1;
  146.     j=0; c=*str;
  147.     p=list;
  148.     k=**p-c; if(k==0) k=strcmp(*p,str);
  149.     if(k==0) return k; if(k>0) return -1;
  150.     p=list+(items-1)*item_size;
  151.     k=**p-c; if(k==0) k=strcmp(*p,str);
  152.     if(k==0) return items-1; if(k<0) return -1;
  153.     for(i1=0,i2=items-1;i2>i1+1;) {
  154.         j=i1+(i2-i1)/2;
  155.         p=list+(j*item_size);
  156.         k=**p-c; if(k==0) k=strcmp(*p,str);
  157.         if(k==0) return j;
  158.         if(k>0) {i2=j; continue;}
  159.         if(k<0) {i1=j; continue;}      
  160.     }
  161.     return -1;
  162. }
  163.  
  164.         /* Read/write to a file with variable parms to print filename */
  165. void accessfile(char *content, char *type, char *s,...)
  166. {
  167.     va_list vp;
  168.     char buf[MAX_LINELEN+1];
  169.     FILE *f;
  170.     int l;
  171.  
  172.     va_start(vp,s);
  173.     vsnprintf(buf,sizeof(buf),s,vp);
  174.     va_end(vp);
  175.     f=fopen(buf,type); if(f==NULL) {
  176.         if(*type=='r') content[0]=0; return;
  177.     }
  178.     switch(*type) {
  179.         case 'a':
  180.         case 'w': {
  181.             l=strlen(content); fwrite(content,1,l,f); break;
  182.         }
  183.         case 'r': {
  184.             l=fread(content,1,MAX_LINELEN-1,f);
  185.             if(l>0 && l<MAX_LINELEN) content[l]=0;
  186.             else content[0]=0;
  187.             break;
  188.         }
  189.         default: {
  190.             content[0]=0; break;
  191.         }
  192.     }
  193.     fclose(f);
  194. }
  195.  
  196. void getstdin(void)
  197. {
  198.     char *p;
  199.     int i,j,k;
  200.     i=0; k=MAX_LINELEN; stdinbuf[0]=0;
  201.     do {
  202.         j=read(0,stdinbuf+i,k);
  203.         if(j<0 || j>k) exit(1);
  204.         i+=j; k-=j; stdinbuf[i]=0;
  205.         p=strstr(stdinbuf,multiexec_random);
  206.         if(p) {*p=0; break;}
  207.     }
  208.     while(k>0);
  209. }
  210.  
  211.         /* add a pid to the list of running childs */
  212. void addpid(int pid)
  213. {
  214.     char buf[MAX_LINELEN+1], pidbuf[32];
  215.     int l;
  216.     snprintf(pidbuf,sizeof(pidbuf),"%u",pid);
  217.     accessfile(buf,"r",pidfname); l=strlen(buf);
  218.     if(l>=MAX_LINELEN-64) return;
  219.     if(wordchr(buf,pidbuf)==NULL) {
  220.         snprintf(buf+l,sizeof(buf)-l," %s",pidbuf);
  221.         accessfile(buf,"w",pidfname);
  222.     }
  223. }
  224.  
  225.         /* Remove a pidname to the list of running childs */
  226. void rmpid(int pid)
  227. {
  228.     char buf[MAX_LINELEN+1], pidbuf[32], *p;
  229.     snprintf(pidbuf,sizeof(pidbuf),"%u",pid);
  230.     accessfile(buf,"r",pidfname);
  231.     p=wordchr(buf,pidbuf);
  232.     if(p!=NULL) {
  233.         strcpy(p,find_word_start(find_word_end(p)));
  234.         accessfile(buf,"w",pidfname);
  235.     }
  236. }
  237.  
  238. int execredirected(char *cmdf, char *inf, char *outf, char *errf,
  239.                    char *args)
  240. {
  241.     pid_t pid;
  242.     int i;
  243.     struct stat st;
  244.     char *cm, *p, *p2, abuf[MAX_LINELEN+1];
  245.     char *arg[1024];
  246.  
  247.     for(cm=cmdf; isspace(*cm); cm++); if(*cmdf==0) return -1;
  248.     fflush(NULL);       /* flush all output streams before forking
  249.                          * otherwise they will be doubled */
  250.     pid=fork(); if(pid==-1) return -1;
  251.     if(!pid) {  /* child */
  252.         if(!inf) {
  253.             dup2(pipe_in[0],0); close(pipe_in[1]);
  254.         }
  255.         else freopen(inf,"r",stdin);
  256.         if(!outf) {
  257.             dup2(pipe_out[1],1); close(pipe_out[0]);
  258.         }
  259.         else freopen(outf,"w",stdout);
  260.         if(errf) freopen(errf,"w",stderr);
  261.         snprintf(abuf,sizeof(abuf),"%s",find_word_start(args));
  262.         if(stat("../chroot/tmp/sessions/.chroot",&st)==0 || must_chroot) {
  263.             arg[0]=ch_root; i=1;
  264.         }
  265.         else {
  266.             i=0;
  267.             setreuid(getuid(),getuid());setregid(getgid(),getgid());
  268.         }
  269.         arg[i++]=cmdf;
  270.         for(p=abuf; *p && i<1000; i++, p=find_word_start(p2)) {
  271.             arg[i]=p; p2=find_word_end(p); if(*p2) *p2++=0;
  272.         }
  273.         arg[i]=NULL;
  274.         if(strchr(arg[0],'/')) execv(arg[0],arg);
  275.         else execvp(arg[0],arg);
  276.         fprintf(stderr,"%s not_INStalled",progname);
  277.         exit(127);
  278.     }
  279.     else {      /* parent */
  280.         addpid(pid); mxpid=pid;
  281.         if(outf) {
  282.             int status;
  283.             close(pipe_in[1]);
  284.             if(waitpid(pid,&status,0)==pid) {
  285.                 rmpid(pid); mxpid=-1;
  286.             }
  287.         }
  288.     }
  289.     return 0;
  290. }
  291.  
  292.         /* verify illegal strings in parms. */
  293. void find_illegal(char *p)
  294. {
  295.     char *pp, *pe;
  296.     int i, l;
  297.     for(pp=p;*pp;pp++) {
  298.         if((*pp<' ' && *pp!='\n' && *pp!='      ') || *pp>=127) *pp=' ';
  299.     }
  300.     for(i=0;i<illpart_no;i++) {
  301.         pe=illpart[i]; l=strlen(pe);
  302.         for(pp=strstr(p,pe); pp; pp=strstr(pp+1,pe)) {
  303.             if(!isupper(pe[0]) || !islower(*(pp+l))) {
  304.                 if(pp[1]!='j' && pp[1]!='J') pp[1]='J';
  305.                 else pp[1]='Z';
  306.             }
  307.         }
  308.     }
  309.     for(i=0;i<illegal_no;i++) {
  310.         pe=illegal[i]; l=strlen(pe);
  311.         for(pp=strstr(p,pe); pp; pp=strstr(pp+1,pe)) {
  312.             if((pp==p || !isalnum(*(pp-1))) && !isalnum(*(pp+l))) {
  313.                 if(pp[1]!='j' && pp[1]!='J') pp[1]='J';
  314.                 else pp[1]='Z';
  315.             }
  316.         }
  317.     }
  318. }
  319.  
  320.         /* strip trailing zeros */
  321. void strip_zeros(char *p)
  322. {
  323.     char *pp, *p2, *numend, *ee;
  324.     int i;
  325.     for(pp=p;*pp!=0;pp++) {
  326.         if(!isdigit(*pp)) continue;
  327.         i=0;
  328.         for(numend=pp;isdigit(*numend) || *numend=='.';numend++)
  329.           if(*numend=='.') i=1;
  330.         if(i==0) {
  331.             pp=numend-1;continue;
  332.         }
  333.         for(p2=numend;p2>pp && *(p2-1)=='0';p2--);
  334.         for(ee=numend;isspace(*ee);ee++);
  335.         if(*(pp+1)=='.' && (*ee=='E' || *ee=='e')
  336.            && *(ee+1)=='-') {
  337.             int k=0;
  338.             char *pt=ee+2;
  339.             while(isdigit(*pt)) {
  340.                 k*=10;k+=*pt-'0';pt++;
  341.             }
  342.             if(precision>8 && (k>precision*2 || (k>precision && *pp=='0'))) {
  343.                
  344.                 sprintf(pp,"0.0%s",pt);
  345.                
  346.                 pp+=strlen("0.0")-1;
  347.                 continue;
  348.             }
  349.         }
  350.        
  351.         if(*(p2-1)=='.' && p2<numend) p2++;
  352.        
  353.         if(p2<numend) {
  354.             strcpy(p2,numend);numend=p2;
  355.         }
  356.         pp=numend-1;
  357.     }
  358. }
  359.  
  360. char *hname[]={"", "_1","_2","_3","_4","_5","_6","_7","_8"};
  361. #define hnameno (sizeof(hname)/sizeof(hname[0]))
  362.  
  363. void putheader(void)
  364. {
  365.     char hbuf[64];
  366.     char *p;
  367.     int i;
  368.    
  369.     inputptr=dynsetup(inputptr,inputend);
  370.     snprintf(inputptr,inputend-inputptr,"%s",header);
  371.     inputptr+=strlen(inputptr);
  372.     for(i=0;i<hnameno;i++) {
  373.         snprintf(hbuf,sizeof(hbuf),"w_%s_header%s",progname,hname[i]);
  374.         p=getenv(hbuf); if(p!=NULL && *p!=0) {
  375.             snprintf(parmbuf,parmlim,"%s",p);
  376.             check_parm(parmbuf);
  377.             snprintf(inputptr,inputend-inputptr,"%s\n",parmbuf);
  378.             inputptr+=strlen(inputptr);
  379.         }
  380.     }
  381. }
  382.  
  383. void putparm(void)
  384. {
  385.     snprintf(parmbuf,parmlim,"%s",parm); check_parm(parmbuf);
  386.     snprintf(inputptr,inputend-inputptr,stringprinter,startstring);
  387.     inputptr+=strlen(inputptr);
  388.     snprintf(inputptr,inputend-inputptr,"%s",parmbuf);
  389.     inputptr+=strlen(inputptr);
  390.     if(inputptr<inputend && inputptr>inputbuf && inputptr[-1]!='\n')
  391.       *inputptr++='\n';
  392.     snprintf(inputptr,inputend-inputptr,stringprinter,endstring);
  393.     inputptr+=strlen(inputptr);
  394.     *inputptr=0;
  395. }
  396.  
  397.         /* general first preparation */
  398. void prepare1(void)
  399. {
  400.     char *p, buf[256];
  401.     int i;
  402.     unsigned int r[4];
  403.     struct timeval t;
  404.  
  405.     parm=getenv("wims_exec_parm");
  406.         /* nothing to do if no calling parameter */
  407.     if(parm==NULL || *parm==0) exit(0);
  408.     inputptr=inputbuf; inputend=inputbuf+inputlim-1;
  409.     multiexec_random=getenv("multiexec_random");
  410.     if(multiexec_random==NULL) multiexec_random="";
  411.     if(*parm && strcmp(parm,multiexec_random)==0) {
  412.         multiexec=1;
  413.         getstdin(); parm=stdinbuf;
  414.         if(parm[0]==0) exit(0);
  415.     }
  416.     if(pipe(pipe_in)<0 || pipe(pipe_out)<0) {
  417.         fprintf(stderr,"%s: unable to create pipe.\n",progname);
  418.         exit(1);
  419.     }
  420. /*    i=fcntl(pipe_in[1],F_GETFL); if(i>=0) fcntl(pipe_in[1],F_SETFL,i|O_NONBLOCK);
  421.     i=fcntl(pipe_out[0],F_GETFL); if(i>=0) fcntl(pipe_out[0],F_SETFL,i|O_NONBLOCK);
  422. */    tmp_dir=getenv("tmp_dir"); if(tmp_dir==NULL || *tmp_dir==0) tmp_dir=tmpdir;
  423.     setenv("TMPDIR",tmp_dir,1);
  424.     mypid=getpid();
  425.     gettimeofday(&t,NULL); seed=t.tv_usec*t.tv_sec+mypid;
  426.     srandom(seed);
  427.     for(i=0;i<4;i++) r[i]=random();
  428.     snprintf(startstring,sizeof(startstring),
  429.              "Start line %s %u %u %u %u",progname,r[0],r[1],r[2],r[3]);
  430.     snprintf(endstring,sizeof(endstring),
  431.              "End line %s %u %u %u %u",progname,r[0],r[1],r[2],r[3]);
  432.     snprintf(buf,sizeof(buf),"%s_command",progname); p=getenv(buf);
  433.     if(p!=NULL && *find_word_start(p)!=0) nameofcmd=find_word_start(p);
  434.     snprintf(cmdbuf,sizeof(cmdbuf),"%s",nameofcmd); nameofcmd=cmdbuf;
  435.     cmdparm=find_word_end(nameofcmd); if(*cmdparm) *cmdparm++=0;
  436.     cmdparm=find_word_start(cmdparm);
  437.     snprintf(pidfname,sizeof(pidfname),"%s/exec.pid",tmp_dir); addpid(mypid);
  438.     snprintf(inputfname,sizeof(inputfname),"%s/%s_input.%d",tmp_dir,progname,mypid);
  439.     snprintf(outputfname,sizeof(outputfname),"%s/%s_output.%d",tmp_dir,progname,mypid);
  440.     errorf=NULL;
  441.     inpf=inputfname; outpf=outputfname;
  442.     isabout=0; p=find_word_start(parm); i=strlen("about");
  443.     if(memcmp(p,"about",i)==0 && *find_word_start(p+i)==0) isabout=1;
  444.     p=getenv("multiexec_debug"); if(p && strcmp(p,"yes")==0) debug=1;
  445. }
  446.  
  447. void prepabout(char *cmd, char *outf, char *errf)
  448. {
  449.     write(pipe_in[1],cmd,strlen(cmd));
  450.     execredirected(nameofcmd,NULL,outf,errf,cmdparm);
  451. }
  452.  
  453.         /* read to aboutbuf. Returns content length. */
  454. int readabout(void)
  455. {
  456.     FILE *ff;
  457.     long int l;
  458.     char *p;
  459.    
  460.     aboutbuf[0]=0; ff=fopen(outputfname,"r");
  461.     if(ff!=NULL) {
  462.         fseek(ff,0,SEEK_END); l=ftell(ff); fseek(ff,0,SEEK_SET);
  463.         l=fread(aboutbuf,1,aboutlen-10,ff); fclose(ff);
  464.         if(l>0 && l<aboutlen) aboutbuf[l]=0; else aboutbuf[0]=0;
  465.         p=find_word_start(aboutbuf); if(p>aboutbuf) strcpy(aboutbuf,p);
  466.     }
  467.     return strlen(aboutbuf);
  468. }
  469.  
  470.         /* read result of execution */
  471. void readresult(void)
  472. {
  473.     FILE *ff;
  474.     char *p, *pp, *pe;
  475.  
  476.     if(debug) {
  477.         ff=fopen(outputfname,"a"); if(ff) {
  478.             fputs(obuf,ff); fclose(ff);
  479.         }
  480.     }
  481.     pe=NULL;
  482.     p=strstr(obuf,startstring);
  483.     if(p) {
  484.         p+=strlen(startstring);
  485.         pe=strstr(p,endstring);
  486.         if(pe) {
  487.             for(pp=pe-1; pp>=p && pp>pe-64 && *pp!='\n'; pp--);
  488.             if(pp>=p && *pp=='\n') pe=pp;
  489.         }
  490.     }
  491.     if(pe) {
  492.         *pe=0;
  493.         while((pe=strstr(p,startstring))!=NULL) {
  494.             p=pe+strlen(startstring);
  495.         }
  496.         output(p);
  497.     }
  498.     else {
  499.         if(mxpid>=0) {
  500.             if(kill(mxpid,0)<0 && errno==ESRCH) {       /* this doesn't work */
  501.                 fprintf(stderr,"%s not_INStalled",progname);
  502.             }
  503.             else {
  504.                 fprintf(stderr,"%s: execution error or time out.\n",progname);
  505.                 kill(mxpid,SIGKILL);
  506.             }
  507.             rmpid(mxpid); mxpid=-1;
  508.         }
  509.         else {
  510.             fprintf(stderr,"%s: aborted on earlier error.\n",progname);
  511.         }
  512.     }
  513.     if(multiexec && *multiexec_random) printf("%s\n",multiexec_random);
  514.     fflush(stdout);
  515. }
  516.  
  517. #ifdef linebyline1
  518.  
  519.         /* this one is for maxima but not used */
  520. void dopipes(void)
  521. {
  522.     long int i, l;
  523.     char *outptr;
  524.     char *p1, *p2, *pp, *pe;
  525.     struct timeval t;
  526.     fd_set rset;
  527.  
  528.     if(mxpid<0) {
  529.         *obuf=0; return;
  530.     }
  531.     outptr=obuf; pp=pe=NULL;
  532.     for(p1=ibuf; *p1; p1=p2) {
  533.         p2=strchr(p1,'\n'); if(p2) p2++; else p2=p1+strlen(p1);
  534.         write(pipe_in[1],p1,p2-p1);
  535.        
  536.         if(strstr(p1,startstring)!=NULL) iactive=1;
  537.         reread:
  538.         l=read(fifofd2,lp,MAX_LINELEN-(lp-lbuf));
  539.         if(!iactive) continue;
  540.         if(l<0 || l>MAX_LINELEN-(lp-lbuf)) l=0;
  541.         lp+=l; *lp=0;
  542.         if(active==0) {
  543.             char *pp;
  544.             pp=strstr(lbuf,startstring);
  545.             if(pp!=NULL) {
  546.                 active=1; strcpy(lbuf,pp); lp=lbuf+strlen(lbuf);
  547.             }
  548.         }
  549.         if(active!=0 && strstr(lbuf,linebyline)!=NULL) {
  550.             fprintf(ff,"%s",lbuf); lp=lbuf;
  551.             if(strstr(lbuf,endstring)!=NULL) {lbuf[0]=0; active=-1; break;}
  552.             lbuf[0]=0; continue;
  553.         }
  554.         /* time out allowance between each silence */
  555.         t.tv_sec=3; t.tv_usec=400000;
  556.         i=select(fifofd2+1,&rset,NULL,NULL,&t);
  557.         if(i>0) goto reread;
  558.         else break; /* time out or error */
  559.     }
  560. }
  561.  
  562. #else
  563.  
  564. void dopipes(void)
  565. {
  566.     long int i, k, l;
  567.     int interval=20000; /* in microseconds */
  568.     int timeout =300;   /* in intervals */
  569.     char *outptr;
  570.     char *p1, *p2, *inp, *pw;
  571.     struct timeval t;
  572.     fd_set rset, wset;
  573.  
  574.     *obuf=0; if(mxpid<0) return;
  575.     outptr=obuf; inp=inputbuf; k=0;
  576.     while(inp<inputptr) {
  577.         t.tv_sec=0; t.tv_usec=interval;
  578.         FD_ZERO(&rset); FD_SET(pipe_out[0],&rset);
  579.         FD_ZERO(&wset); FD_SET(pipe_in[1],&wset);
  580.         i=pipe_out[0]; if(i<pipe_in[1]) i=pipe_in[1];
  581.         i=select(i+1,&rset,&wset,NULL,&t);
  582.         if(i<=0) {
  583.             k++; if(k>=timeout) return; /* time out */
  584.         }
  585.         if(FD_ISSET(pipe_in[1],&wset)) {
  586.                 /* Writing must be line by line, for otherwise
  587.                  * it will block when the input is large. */
  588.             for(pw=inp; pw<inputptr && *pw!='\n'; pw++);
  589.             if(pw<inputptr) pw++;
  590.             l=write(pipe_in[1],inp,pw-inp);
  591.             if(l<0 || l>inputptr-inp) return;
  592.             inp+=l;
  593.         }
  594.         if(FD_ISSET(pipe_out[0],&rset)) {
  595.             l=read(pipe_out[0],outptr,fsizelim-(outptr-obuf)-1);
  596.             if(l<=0 || l>fsizelim-(outptr-obuf)-1) {
  597.                 *outptr=0; break;
  598.             }
  599.             outptr+=l; *outptr=0;
  600.         }
  601.     }
  602.     p2=NULL;
  603.     p1=strstr(obuf,startstring);
  604.     if(p1) {
  605.         p1+=strlen(startstring);
  606.         p2=strstr(p1,endstring);
  607.     }
  608.     while(!p2) {
  609.         t.tv_sec=0; t.tv_usec=interval;
  610.         FD_ZERO(&rset); FD_SET(pipe_out[0],&rset);
  611.         i=select(pipe_out[0]+1,&rset,NULL,NULL,&t);
  612.         if(i>0) {
  613.             l=read(pipe_out[0],outptr,fsizelim-(outptr-obuf)-1);
  614.             if(l<=0 || l>fsizelim-(outptr-obuf)-1) {
  615.                 *outptr=0; break;
  616.             }
  617.             outptr+=l; *outptr=0;
  618.         }
  619.         else {
  620.             k++; if(k>=timeout) break;
  621.         }
  622.         if(!p1) {
  623.             p1=strstr(obuf,startstring);
  624.             if(p1) p1+=strlen(startstring);
  625.         }
  626.         if(p1) p2=strstr(p1,endstring);
  627.     }
  628. }
  629.  
  630. #endif
  631.  
  632. void run(void)
  633. {
  634.     FILE *ff;
  635.    
  636.     if(isabout) {about(); goto end;}
  637.     execredirected(nameofcmd,NULL,NULL,NULL,cmdparm);
  638.     putheader();
  639.     obuf=xmalloc(fsizelim); if(!obuf) return;
  640.     rep:
  641.     putparm();
  642.     if(!multiexec) {
  643.         snprintf(inputptr,inputend-inputptr,"%s",quitstring);
  644.         inputptr+=strlen(inputptr);
  645.     }
  646.     if(debug) {
  647.         ff=fopen(inputfname,"a"); if(ff) {
  648.             fputs(inputbuf,ff); fclose(ff);
  649.         }
  650.     }
  651.     dopipes();
  652.     readresult();
  653.     if(multiexec) {
  654.         getstdin(); inputptr=inputbuf; inputbuf[0]=0;
  655.         goto rep;
  656.     }
  657.     end: if(strstr(tmp_dir,"tmp/sessions/")==NULL) {
  658.         unlink(inputfname); unlink(outputfname);
  659.     }
  660.     free(obuf); rmpid(mypid);
  661.     if(mxpid>0) {kill(mxpid,SIGKILL); rmpid(mxpid);}
  662. }
  663.  
  664.