Logo Search packages:      
Sourcecode: wims version File versions  Download package

common.c

/*    Copyright (C) 1998 XIAO, Gang of Universite de Nice - Sophia Antipolis
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

      /* Common routines in interfaces */

int mypid;
char inputfname[256], outputfname[256], errorfname[256];
char inputfifo[256], outputfifo[256];
char thispid[256], pidfname[256];
char parmbuf[parmlim+16];
char *inpf, *outpf, *errorf;
char *parm;
char *tmp_dir;
char cmdbuf[1024];
char *cmdparm;
int isabout=0;
int multiexec=0, mxpid, notfirst;
int fifofd1, fifofd2;
FILE *goin;
unsigned int seed;      /* random seed value */
char aboutbuf[aboutlen];
      /* this is only a default. It should usually be reset. */
char *tmpdir="/tmp";
char startstring[256], endstring[256];

void check_parm(char *p);
void output(char *p);
void about(void);
void dynsetup(FILE *ff);

void *xmalloc(size_t n)
{
    void *p;
    p=malloc(n);
    if(p==NULL) {
      fprintf(stderr, "%s: Malloc failure.\n",progname);
      exit(1);
    }
    return p;
}

      /* strip trailing spaces; return string end. */
char *strip_trailing_spaces(char *p)
{
    char *pp;
    if(*p==0) return p;
    for(pp=p+strlen(p)-1; pp>=p && isspace(*pp); *(pp--)=0);
    return pp;
}

      /* Points to the end of the word */
char *find_word_end(char *p)
{
    int i;
    for(i=0;!isspace(*p) && *p!=0 && i<MAX_LINELEN; p++,i++);
    return p;
}

      /* Strips leading spaces */
char *find_word_start(char *p)
{
    int i;
    for(i=0; isspace(*p) && i<MAX_LINELEN; p++,i++);
    return p;
}

      /* Find first occurrence of word */
char *wordchr(char *p, char *w)
{
    char *r;

    if(*w==0) return NULL;
    for(r=strstr(p,w);r!=NULL && 
      ( (r>p && !isspace(*(r-1))) || (!isspace(*(r+strlen(w))) && *(r+strlen(w))!=0) );
      r=strstr(r+1,w));
    return r;
}

         /* Returns the pointer or NULL. */
char *varchr(char *p, char *v)
{
        char *pp; int n=strlen(v);
        for(pp=strstr(p,v); pp!=NULL; pp=strstr(pp+1,v)) {
          if((pp==p || (!isalnum(*(pp-1)) && *(pp-1)!='_')) &&
             ((!isalnum(*(pp+n)) && *(pp+n)!='_') || *(pp+n)==0)) break;
      }
        return pp;
}

      /* find matching parenthesis */
char *find_matching(char *p, char c)
{
    char *pp;
    int parenth, brak, brace;
    parenth=brak=brace=0;
    for(pp=p; *pp!=0; pp++) {
      switch(*pp) {
          case '[': brak++; break;
          case ']': brak--; break;
          case '(': parenth++; break;
          case ')': parenth--; break;
          case '{': brace++; break;
          case '}': brace--; break;
          default: continue;
      }
      if(parenth<0 || brak<0 || brace<0) {
          if(*pp!=c || parenth>0 || brak>0 || brace>0) return NULL;
          else break;
      }
    }
    if(*pp!=c) return NULL;
    return pp;
}

      /* searches a list. Returns index if found, -1 if nomatch. 
       * Uses binary search, list must be sorted. */
int search_list(void *list, int items, size_t item_size, const char *str)
{
    int i1,i2,j,k;
    char **p;
    char c;
    
    if(items<=0) return -1;
    j=0; c=*str;
    p=list;
    k=**p-c; if(k==0) k=strcmp(*p,str);
    if(k==0) return k; if(k>0) return -1;
    p=list+(items-1)*item_size; 
    k=**p-c; if(k==0) k=strcmp(*p,str);
    if(k==0) return items-1; if(k<0) return -1;
    for(i1=0,i2=items-1;i2>i1+1;) {
      j=i1+(i2-i1)/2;
      p=list+(j*item_size);
      k=**p-c; if(k==0) k=strcmp(*p,str);
      if(k==0) return j;
      if(k>0) {i2=j; continue;}
      if(k<0) {i1=j; continue;}     
    }
    return -1;
}

      /* Read/write to a file with variable parms to print filename */
void accessfile(char *content, char *type, char *s,...)
{
    va_list vp;
    char buf[MAX_LINELEN+1];
    FILE *f;
    int l;

    va_start(vp,s);
    vsnprintf(buf,sizeof(buf),s,vp);
    va_end(vp);
    f=fopen(buf,type); if(f==NULL) {
      if(*type=='r') content[0]=0; return;
    }
    switch(*type) {
      case 'a':
      case 'w': {
          l=strlen(content); fwrite(content,1,l,f); break;
      }
      case 'r': {
          l=fread(content,1,MAX_LINELEN-1,f);
          if(l>0 && l<MAX_LINELEN) content[l]=0;
          else content[0]=0;
          break;
      }
      default: {
          content[0]=0; break;
      }
    }
    fclose(f);
}

      /* add a pid to the list of running childs */
void addpid(int pid)
{
    char buf[MAX_LINELEN+1], pidbuf[32];
    int l;
    snprintf(pidbuf,sizeof(pidbuf),"%u",pid);
    accessfile(buf,"r",pidfname); l=strlen(buf);
    if(l>=MAX_LINELEN-64) return;
    if(wordchr(buf,pidbuf)==NULL) {
      snprintf(buf+l,sizeof(buf)-l," %s",pidbuf);
      accessfile(buf,"w",pidfname);
    }
}

      /* Remove a pidname to the list of running childs */
void rmpid(int pid)
{
    char buf[MAX_LINELEN+1], pidbuf[32], *p;
    snprintf(pidbuf,sizeof(pidbuf),"%u",pid);
    accessfile(buf,"r",pidfname);
    p=wordchr(buf,pidbuf);
    if(p!=NULL) {
      strcpy(p,find_word_start(find_word_end(p)));
      accessfile(buf,"w",pidfname);
    }
}

int execredirected(char *cmdf, char *inf, char *outf, char *errf,
               char *args)
{
    pid_t pid;
    int i, status;
    char *cm, *p, *p2, abuf[MAX_LINELEN+1];
    char *arg[1024];

    for(cm=cmdf; isspace(*cm); cm++); if(*cmdf==0) return -1;
    fflush(NULL); /* flush all output streams before forking
                   * otherwise they will be doubled */
    pid=fork(); if(pid==-1) return -1;
    if(!pid) {    /* child */
      if(multiexec) {
          fclose(goin); close(fifofd1); close(fifofd2);
      }
      if(inf!=NULL) freopen(inf,"r",stdin);
      if(outf!=NULL) freopen(outf,"w",stdout);
      if(errf!=NULL) freopen(errf,"w",stderr);
      snprintf(abuf,sizeof(abuf),"%s",find_word_start(args));
      arg[0]=cmdf;
      for(i=1,p=abuf; *p && i<1000; i++, p=find_word_start(p2)) {
          arg[i]=p; p2=find_word_end(p); if(*p2) *p2++=0;
      }
      arg[i]=NULL;
      setreuid(getuid(),getuid());setregid(getgid(),getgid());
      if(strchr(cmdf,'/')) execv(cmdf,arg);
      else execvp(cmdf,arg);
      fprintf(stderr,"%s not_INStalled",progname);
      exit(127);
    }
    else {  /* parent */
      addpid(pid);
      if(multiexec) {
          snprintf(abuf,sizeof(abuf),"%u",pid); mxpid=pid;
          accessfile(abuf,"w",thispid);
          return 0;
      }
      else {
          waitpid(pid,&status,0); rmpid(pid);
          return WEXITSTATUS(status);
      }
    }
    return 0;
}

      /* verify illegal strings in parms. */
void find_illegal(char *p)
{
    char *pp, *pe;
    int i, l;
    for(pp=p;*pp;pp++) {
      if((*pp<' ' && *pp!='\n' && *pp!='  ') || *pp>=127) *pp=' ';
    }
    for(i=0;i<illpart_no;i++) {
      pe=illpart[i]; l=strlen(pe);
      for(pp=strstr(p,pe); pp; pp=strstr(pp+1,pe)) {
          if(!isupper(pe[0]) || !islower(*(pp+l))) {
            if(pp[1]!='j' && pp[1]!='J') pp[1]='J';
            else pp[1]='Z';
          }
      }
    }
    for(i=0;i<illegal_no;i++) {
      pe=illegal[i];
      for(pp=strstr(p,pe); pp; pp=strstr(pp+1,pe)) {
          if(pp[1]!='j' && pp[1]!='J') pp[1]='J';
          else pp[1]='Z';
      }
    }
}

      /* strip trailing zeros */
void strip_zeros(char *p)
{
    char *pp, *p2, *numend, *ee;
    int i;
    for(pp=p;*pp!=0;pp++) {
      if(!isdigit(*pp)) continue;
      i=0;
      for(numend=pp;isdigit(*numend) || *numend=='.';numend++)
        if(*numend=='.') i=1;
      if(i==0) {
          pp=numend-1;continue;
      }
      for(p2=numend;p2>pp && *(p2-1)=='0';p2--);
      for(ee=numend;isspace(*ee);ee++);
      if(*(pp+1)=='.' && (*ee=='E' || *ee=='e') 
         && *(ee+1)=='-') {
          int k=0;
          char *pt=ee+2;
          while(isdigit(*pt)) {
            k*=10;k+=*pt-'0';pt++;
          }
          if(precision>8 && (k>precision*2 || (k>precision && *pp=='0'))) {
            
            sprintf(pp,"0.0%s",pt);
            
            pp+=strlen("0.0")-1;
            continue;
          }
      }
      
      if(*(p2-1)=='.' && p2<numend) p2++; 
      
      if(p2<numend) {
          strcpy(p2,numend);numend=p2;
      }
      pp=numend-1;
    }
}

char *hname[]={"", "_1","_2","_3","_4","_5","_6","_7","_8"};
#define hnameno (sizeof(hname)/sizeof(hname[0]))

void putheader(FILE *ff)
{
    char hbuf[64];
    char *p;
    int i;
    
    fputs(header,ff);
    dynsetup(ff);
    for(i=0;i<hnameno;i++) {
      snprintf(hbuf,sizeof(hbuf),"w_%s_header%s",progname,hname[i]);
      p=getenv(hbuf); if(p!=NULL && *p!=0) {
          snprintf(parmbuf,parmlim,"%s",p);
          check_parm(parmbuf); fprintf(ff,"%s\n",parmbuf);
      }
    }
}

void putparm(FILE *ff)
{
    int l;
    snprintf(parmbuf,parmlim,"%s",parm); check_parm(parmbuf);
    fprintf(ff,stringprinter,startstring);
    l=strlen(parmbuf);fwrite(parmbuf,1,l,ff);
    if(l<=0 || parmbuf[l-1]!='\n') fprintf(ff,"\n");
    fprintf(ff,stringprinter,endstring);
}

      /* Check to see whether this is multi-execed */
void checkmulti(void)
{
    char *p, *p1, *p2, buf[MAX_LINELEN+1];
    int i, t[3];
    
    p=getenv("fifo_fd"); if(p==NULL || *p==0) return;
    for(p1=find_word_start(p), i=0; i<3; p1=find_word_start(p2), i++) {
      p2=find_word_end(p1); if(*p2) *p2++=0;
      if(isdigit(*p1)) t[i]=atoi(p1); else t[i]=0;
    }
    if(t[0]<=0 || t[0]>MAX_MULTIEXEC || t[1]==0 || t[2]==0) return;
    goin=fdopen(t[1],"w"); if(goin==NULL) return;
    snprintf(thispid,sizeof(thispid),"%s/mx_pid.%d",tmp_dir,t[0]);
    accessfile(buf,"r",thispid); 
    if(buf[0]) mxpid=atoi(buf); else mxpid=0;
    notfirst=mxpid;
    if(mxpid<0) {
      fprintf(stderr,"%s: program aborted on earlier time out.\n",progname);
      exit(1);
    }
    errno=0;
    multiexec=t[0]; fifofd1=t[1]; fifofd2=t[2];
    snprintf(inputfifo,sizeof(inputfifo),"%s/fifo.in.%d",tmp_dir,t[0]);
    snprintf(outputfifo,sizeof(outputfifo),"%s/fifo.out.%d",tmp_dir,t[0]);
    inpf=inputfifo; outpf=outputfifo;
    p=getenv("w_wims_tmp_debug"); if(p==NULL || strstr(p,"yes")==NULL) {
      snprintf(inputfname,sizeof(inputfname),"%s/mx_input",tmp_dir);
      snprintf(outputfname,sizeof(outputfname),"%s/mx_output",tmp_dir);
    }
    snprintf(errorfname,sizeof(errorfname),"%s/mx_error",tmp_dir);
    errorf=errorfname;
}

      /* general first preparation */
void prepare1(void)
{
    char *p, buf[256];
    int i;
    unsigned int r[4];
    struct timeval t;

    parm=getenv("wims_exec_parm");
      /* nothing to do if no calling parameter */
    if(parm==NULL || *parm==0) exit(0);
    tmp_dir=getenv("tmp_dir"); if(tmp_dir==NULL || *tmp_dir==0) tmp_dir=tmpdir;
    setenv("TMPDIR",tmp_dir,1);
    mypid=getpid();
    gettimeofday(&t,NULL); seed=t.tv_usec*t.tv_sec+mypid;
    srandom(seed);
    for(i=0;i<4;i++) r[i]=random();
    snprintf(startstring,sizeof(startstring),
           "Start line %s %u %u %u %u",progname,r[0],r[1],r[2],r[3]);
    snprintf(endstring,sizeof(endstring),
           "End line %s %u %u %u %u",progname,r[0],r[1],r[2],r[3]);
    snprintf(buf,sizeof(buf),"%s_command",progname); p=getenv(buf);
    if(p!=NULL && *find_word_start(p)!=0) nameofcmd=find_word_start(p);
    snprintf(cmdbuf,sizeof(cmdbuf),"%s",nameofcmd); nameofcmd=cmdbuf;
    cmdparm=find_word_end(nameofcmd); if(*cmdparm) *cmdparm++=0;
    cmdparm=find_word_start(cmdparm);
    snprintf(pidfname,sizeof(pidfname),"%s/exec.pid",tmp_dir);
    snprintf(inputfname,sizeof(inputfname),"%s/%s_input.%d",tmp_dir,progname,mypid);
    snprintf(outputfname,sizeof(outputfname),"%s/%s_output.%d",tmp_dir,progname,mypid);
    errorf=NULL;
    inpf=inputfname; outpf=outputfname;
    isabout=0; p=find_word_start(parm); i=strlen("about");
    if(memcmp(p,"about",i)==0 && *find_word_start(p+i)==0) isabout=1;
    checkmulti();
}

void prepabout(char *cmd, char *outf, char *errf)
{
    FILE *ff;
    
    ff=fopen(inputfname,"w"); fprintf(ff,cmd); fclose(ff);
    execredirected(nameofcmd,inputfname,outf,errf,cmdparm);
}

      /* read to aboutbuf. Returns content length. */
int readabout(void)
{
    FILE *ff;
    long int l;
    char *p;
    
    aboutbuf[0]=0; ff=fopen(outputfname,"r");
    if(ff!=NULL) {
      fseek(ff,0,SEEK_END); l=ftell(ff); fseek(ff,0,SEEK_SET);
      l=fread(aboutbuf,1,aboutlen-10,ff); fclose(ff);
      if(l>0 && l<aboutlen) aboutbuf[l]=0; else aboutbuf[0]=0;
      p=find_word_start(aboutbuf); if(p>aboutbuf) strcpy(aboutbuf,p);
    }
    return strlen(aboutbuf);
}

      /* read result of execution */
void readresult(void)
{
    FILE *ff;
    long int l;
    char *obuf, *p, *pp, *pe;
    
    ff=fopen(outputfname,"r");
    if(ff!=NULL) {
      fseek(ff,0,SEEK_END); l=ftell(ff); fseek(ff,0,SEEK_SET);
      if(l<0) l=0; if(l>fsizelim) l=fsizelim;
      obuf=xmalloc(l+16);
      l=fread(obuf,1,l,ff); fclose(ff);
      if(l>0) obuf[l]=0; else obuf[0]=0;
      p=strstr(obuf,startstring);
      if(p!=NULL) {
          p+=strlen(startstring);
          pe=strstr(p,endstring);
          if(pe!=NULL) {
            for(pp=pe-1; pp>=p && pp>pe-64 && *pp!='\n'; pp--);
            if(pp>=p && *pp=='\n') *pp=0; else *pe=0;
          }
          output(p);
      }
      free(obuf);
    }
}

#ifdef linebyline

void dopipes(void)
{
    FILE *ff;
    long int i, l;
    char *ibuf, *lp, lbuf[MAX_LINELEN+1];
    char *p1, *p2;
    int active, iactive, lasterrorlen;
    struct timeval t;
    fd_set rset;

    ff=fopen(inputfname,"r");
    if(ff==NULL) return;
    fseek(ff,0,SEEK_END); l=ftell(ff); fseek(ff,0,SEEK_SET);
    if(l<0) l=0; if(l>fsizelim) l=fsizelim;
    ibuf=xmalloc(l+16);
    l=fread(ibuf,1,l,ff); fclose(ff);
    if(l>0) ibuf[l]=0; else ibuf[0]=0;
    accessfile(lbuf,"r",errorf); lasterrorlen=strlen(lbuf);
    ff=fopen(outputfname,"w"); fprintf(ff,"\n"); active=iactive=0;
    lp=lbuf; FD_ZERO(&rset); FD_SET(fifofd2,&rset);
    for(p1=ibuf; p1!=NULL && *p1; p1=p2) {
      p2=strchr(p1,'\n'); if(p2) *p2++=0;
      if(strstr(p1,startstring)!=NULL) iactive=1;
      fprintf(goin,"%s\n",p1); fflush(goin);
      reread:
      l=read(fifofd2,lp,MAX_LINELEN-(lp-lbuf));
      if(!iactive) continue;
      if(l<0 || l>MAX_LINELEN-(lp-lbuf)) l=0;
      lp+=l; *lp=0;
      if(active==0) {
          char *pp;
          pp=strstr(lbuf,startstring);
          if(pp!=NULL) {
            active=1; strcpy(lbuf,pp); lp=lbuf+strlen(lbuf);
          }
      }
      if(active!=0 && strstr(lbuf,linebyline)!=NULL) {
          fprintf(ff,"%s",lbuf); lp=lbuf;
          if(strstr(lbuf,endstring)!=NULL) {lbuf[0]=0; active=-1; break;}
          lbuf[0]=0; continue;
      }
      /* time out allowance between each silence */
      t.tv_sec=2; t.tv_usec=400000;
      i=select(fifofd2+1,&rset,NULL,NULL,&t);
      if(i>0) goto reread;
      else { /* time out */
          kill(mxpid,SIGKILL); accessfile("-1","w",thispid);
          mxpid=-1; break;
      }
    }
    fprintf(ff,"%s",lbuf);
    fclose(ff);
    accessfile(lbuf,"r",errorf);
    if(mxpid==-1) fprintf(stderr,"Execution time out.\n");
    if(strlen(lbuf)>lasterrorlen) fprintf(stderr,"%s",lbuf+lasterrorlen);
}

#else

void dopipes(void)
{
    FILE *ff;
    long int i, l;
    char *ibuf, lbuf[MAX_LINELEN+1];
    char *p1, *p2, *lp;
    int active, lasterrorlen;
    struct timeval t;
    fd_set rset;

    ff=fopen(inputfname,"r");
    if(ff==NULL) return;
    fseek(ff,0,SEEK_END); l=ftell(ff); fseek(ff,0,SEEK_SET);
    if(l<0) l=0; if(l>fsizelim) l=fsizelim;
    ibuf=xmalloc(l+16);
    l=fread(ibuf,1,l,ff); fclose(ff);
    if(l>0) ibuf[l]=0; else ibuf[0]=0;
    accessfile(lbuf,"r",errorf); lasterrorlen=strlen(lbuf);
    ff=fopen(outputfname,"w"); fprintf(ff,"\n"); active=0; lp=lbuf;
    for(p1=ibuf; p1!=NULL && *p1; p1=p2) {
      p2=strchr(p1,'\n'); if(p2) *p2++=0;
      fprintf(goin,"%s\n",p1); fflush(goin);
      l=read(fifofd2,lp,MAX_LINELEN-(lp-lbuf));
      if(l<0 || l>MAX_LINELEN) continue;
      lp[l]=0;
      if(l>0) {
          if(active==0 && strstr(lbuf,startstring)!=NULL) active=1;
          if(active>0) {
            fprintf(ff,"%s",lbuf);
            if(strstr(lbuf,endstring)!=NULL) active=-1;
            lp=lbuf; lbuf[0]=0;
          }
      }
    }
    if(active<0) goto end;
    FD_ZERO(&rset); FD_SET(fifofd2,&rset);
    while(active>=0) {
      /* time out allowance between each silence */
      if(active==0 && notfirst) {   /* no startstring: very bad */
          t.tv_sec=0; t.tv_usec=600000;
      }
      else {      /* loading or startstring already received */
          t.tv_sec=2; t.tv_usec=400000;
      }
      i=select(fifofd2+1,&rset,NULL,NULL,&t);
      if(i>0) l=read(fifofd2,lp,MAX_LINELEN-(lp-lbuf));
      else { /* time out */
            /* check for /proc information to see whether 
             * the child is running: this is 
             * probably VERY Linux-specific, and does not work well
             * in any case. So disabled for the time being. */
/*        accessfile(lbuf,"r","/proc/%u/stat",mxpid);
          for(i=0,p1=find_word_start(lbuf);i<2;i++,p1=find_word_start(p2)) {
            p2=find_word_end(p1); if(*p2) p2++;
          }
          *find_word_end(p1)=0;
          if(strcmp(p1,"R")==0) continue;   */
          kill(mxpid,SIGKILL); accessfile("-1","w",thispid);
          mxpid=-1; break;
      }
      if(l<=0 || l>MAX_LINELEN) break;    /* error or EOF */
      lp[l]=0;
      if(l>0) {
          if(active==0 && strstr(lbuf,startstring)!=NULL) active=1;
          if(active>0) {
            fprintf(ff,"%s",lbuf);
            if(strstr(lbuf,endstring)!=NULL) active=-1;
            lp=lbuf; lbuf[0]=0;
          }
      }
    }
    end: fprintf(ff,"%s",lbuf); fclose(ff);
    accessfile(lbuf,"r",errorf);
    if(mxpid==-1) fprintf(stderr,"Execution time out.\n");
    if(strlen(lbuf)>lasterrorlen) fprintf(stderr,"%s",lbuf+lasterrorlen);
}

#endif

void run(void)
{
    FILE *ff;
    
    if(isabout) {about(); goto end;}
    ff=fopen(inputfname,"w");
    if(ff==NULL) {
      fprintf(stderr,"%s: cannot open file %s.\n",progname, inputfname); exit(1);
    }
    if(!multiexec || !mxpid) putheader(ff);
    putparm(ff);
    if(!multiexec) fprintf(ff,"%s",quitstring);
    fclose(ff);
    if(!multiexec || !mxpid) execredirected(nameofcmd,inpf,outpf,errorf,cmdparm);
    if(multiexec) dopipes();
    readresult();
    end: if(strstr(tmp_dir,"tmp/sessions/")==NULL) {
      unlink(inputfname); unlink(outputfname);
    }
}


Generated by  Doxygen 1.6.0   Back to index