Subversion Repositories wimsdev

Rev

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