Subversion Repositories wimsdev

Rev

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