Subversion Repositories wimsdev

Rev

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