- /*    Copyright (C) 2002-2003 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. 
-  */ 
-   
- /* http dawmon for WIMS */ 
-   
- #include "../wims.h" 
- #include <netdb.h> 
- #include <sys/socket.h> 
- #include <netinet/in.h> 
- #include <arpa/inet.h> 
-   
- #if !HAVE_SOCKLEN_T 
- typedef size_t socklen_t; 
- #endif 
-   
- #define WIMS_TIMEOUT    200 
- #define WIMSD_TICK      10 
- #define WIMSD_IDLE      500 
- #define PIDLIM          100 
-   
- char *acceptstr="127.0.0.1"; 
-   
- int pidtab[PIDLIM]; 
- int pidcnt; 
-   
- int sock; 
- int sport; 
- int idle; /* limited to WIMSD_TICK * WIMSD_IDLE */ 
-   
- void errorquit(char *msg) 
- { 
- } 
-   
- void checkpid(void) 
- { 
-     int i,k; 
-     for(i=0;i<pidcnt;i++) { 
-         waitpid(pidtab[i],&k,WNOHANG); 
-         if(WIFEXITED(k)) { 
-             memmove(- pidtab +- i ,- pidtab +- i +1,(- pidcnt -- i -1)*sizeof(- pidtab [0]));
 
-             pidcnt--; 
-         } 
-     } 
- } 
-   
- void addpid(int pid) 
- { 
-     while(pidcnt>=PIDLIM) { 
-         sleep(1); checkpid(); 
-     } 
-     pidtab[pidcnt++]=pid; 
- } 
-   
- void alarm1(int s) 
- { 
- } 
-   
- void alarm2(int s) 
- { 
-     checkpid(); idle++; alarm(WIMSD_TICK); 
-     if(idle>=WIMSD_IDLE) alarm1(0); 
- } 
-   
-         /* 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; 
- } 
-   
-         /* 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; 
-   
-     vsnprintf(buf,sizeof(buf),s,vp); 
-     f =fopen(- buf ,- type ); if(- f ==- NULL ) {
-         if(*type=='r') content[0]=0; return; 
-     } 
-     switch(*type) { 
-         case 'a': 
-         case 'w': { 
-         } 
-         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; 
-         } 
-     } 
- } 
-   
- void badreq(void) 
- { 
-     printf("HTTP/1.0 400 Bad Request\r\n\r\nBad Request.\r\n"); 
- } 
-   
-         /* open a TCP/IP socket with host/port 
-          * returns the file descriptor for the socket */ 
- int net_connect(int port) 
- { 
-     int soc, vrai; 
-   
-     if ((soc = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
-       errorquit("socket() error"); 
-     if(setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, &vrai, sizeof(vrai)) == -1) 
-       errorquit("setsockopt() error"); 
-   
-     sin- . sin_port=- htons (- port );
 
-     sin- . sin_family =-  AF_INET ;
 
-     inet_aton (- acceptstr ,&sin- . sin_addr);
-     if(- bind (- soc ,(struct-  sockaddr  *)&sin, sizeof(sin))==-1)
 
-       errorquit("bind() error"); 
-     if(listen(soc,10)==-1) errorquit("listen() error"); 
-     return soc; 
- } 
-   
- void putfile(char *fname,int soc) 
- { 
-     int l; 
-     long int siz; 
-     char *p, namebuf[4096], buf[4096]; 
-     char cbuf[MAX_LINELEN+1]; 
-     struct stat st; 
-     FILE *f; 
-      
-     if(- fname [strlen(- fname )-1]=='/')
 
-       snprintf(- namebuf ,sizeof(- namebuf ),"%sindex.html",- fname );
 
-     else snprintf(- namebuf ,sizeof(- namebuf ),"%s",- fname );
 
-     statit: if(stat(namebuf,&st)!=0) badreq(); 
-     if(S_ISDIR(st.st_mode)) { 
-         snprintf(- namebuf ,sizeof(- namebuf ),"%s/index.html",- fname );
 
-         goto statit; 
-     } 
-     if(!S_ISREG(st.st_mode)) badreq(); 
-       badreq(); 
-         *- p =0; snprintf(- buf ,sizeof(- buf ),"%s/.htaccess",- namebuf ); *- p ='/';
 
-         if(stat(cbuf,&st)==0) { 
-             accessfile(cbuf,"r","%s",buf); 
-             if(strstr(- cbuf ,"deny from all")!=- NULL )-  badreq ();
 
-         } 
-     } 
-     siz=st.st_size; 
- Content-Length: %ld\r\n\r\n", 
-            siz); 
-     f =fopen(- namebuf ,"r"); if(- f ==- NULL )-  badreq ();
-     do { 
-         l =fread(- buf ,1,sizeof(- buf ),- f );
-         if(- l >0 &&-  l <=sizeof(- buf )) fwrite(- buf ,1,- l ,- stdout );
 
-     } while(l==sizeof(buf)); 
- } 
-   
- struct sockaddr_in saddr; 
-   
- void onereq(int soc) 
- { 
-     char buf[QUERY_STRING_LIMIT+1], buf2[MAX_LINELEN+1]; 
-     int i, k, l; 
- /*     FILE *fin, *fout; */ 
-     struct stat st; 
-     char *query_method, *query_url, *p, *pp, *p2, *parms; 
-   
-     i=fork(); if(i!=0) { 
-         if(i==-1) errorquit("fork() error"); 
-         addpid(i); return; 
-     } 
-     alarm(WIMS_TIMEOUT); 
-     signal(SIGALRM,alarm1); 
-     (void)chdir("public_html"); 
-     i=0; do { 
-         l=read(soc, buf+i, 1); i++; 
-     } 
-     while(- i <- QUERY_STRING_LIMIT  &&-  l >0 && (- i <4 || memcmp(- buf +- i -4,"\r\n\r\n",4)!=0));
 
-     buf[i]=0; 
- /*printf("%s\n",buf);*/ 
-     dup2(soc,0); /* fin=fdopen(0,"r"); stdin=fin; */ 
-     dup2(soc,1); /* fout=fdopen(1,"w"); stdout=fout; */ 
-     query_method=find_word_start(buf); 
-     query_url=find_word_end(query_method); if(query_url) *query_url++=0; 
-     query_url=find_word_start(query_url); 
-     p=find_word_end(query_url); if(*p) *p++=0; 
-     parms =strchr(- p ,'\n'); if(- parms )-  parms ++;
-     if(strcmp(- query_method ,"GET")!=0 &&
 
-        strcmp(- query_method ,"HEAD")!=0 &&
 
-        strcmp(- query_method ,"POST")!=0)-  badreq ();
 
-     if(- query_url [0]!='/' ||-  query_url [1]=='/' || strstr(- query_url ,"..")!=- NULL )
 
-       badreq(); 
-     setenv("REQUEST_URL",query_url,1); 
-     p =strchr(- query_url ,'?'); if(- p !=- NULL ) *- p ++=0; else-  p ="";
-     k=stat(query_url+1,&st); 
-     if(- k !=0 && strchr(- query_url +1,'/')==- NULL )
 
-       query_url="/wims.cgi"; 
-     if(i<4 || strcasecmp(query_url+i-4,".cgi")!=0) 
-       putfile(query_url+1,soc); 
-       badreq(); 
-     setenv("QUERY_STRING",p,1); 
-     setenv("QUERY_URL",query_url,1); 
-     setenv("SCRIPT_NAME",query_url,1); 
-     setenv("REQUEST_METHOD",query_method,1); 
-     setenv("SERVER_SOFTWARE","WIMS",1); 
-     setenv("SERVER_PORT",buf2,1); 
-     for(; *parms; parms=p) { 
-         if(- p ==- NULL )-  p =- parms +strlen(- parms );
 
-         else { 
-             if(*(p-1)=='\r') *(p-1)=0; 
-             *p++=0; 
-         } 
-         for(- pp =- parms ; isalnum(*- pp ) || *- pp =='-';-  pp ++);
 
-         if(*pp==':') { 
-             *pp++=0; pp=find_word_start(pp); 
-             for(p2=parms; *p2; p2++) { 
-                 if(*- p2 =='-') *- p2 ='_'; else *- p2 =toupper(*- p2 );
 
-             } 
-             if(strcmp(- parms ,"CONTENT_LENGTH")==0 ||
 
-                strcmp(- parms ,"CONTENT_TYPE")==0) {
 
-                 setenv(buf2,pp,1);           
-             } 
-             snprintf(- buf2 ,sizeof(- buf2 ),"HTTP_%s",- parms );
 
-             setenv(buf2,pp,1);       
-         } 
-     } 
-     setenv("REMOTE_ADDR",inet_ntoa(saddr.sin_addr),1); 
-     snprintf(- buf2 ,sizeof(- buf2 ),"%u",- ntohs (- saddr. sin_port));
 
-     setenv("REMOTE_PORT",buf2,1); 
-   
-     snprintf(- buf2 ,sizeof(- buf2 ),".%s",- query_url );
 
-     execl(buf2,buf2,NULL); 
-      
-     /* fclose(fout); fclose(fin); */-  close (- soc ); exit(0);
 
- } 
-   
- void serve(int soc) 
- { 
-     int newsoc; 
-     socklen_t slen=sizeof(saddr); 
-      
-     wait: 
-     alarm(WIMSD_TICK); 
-     newsoc=accept(soc,(struct sockaddr *)&saddr, &slen); 
-     if(newsoc==-1) errorquit("accept() error"); 
-     checkpid(); idle=0; 
-     onereq(newsoc); close(newsoc); goto wait; 
- } 
-   
- void parm(void) 
- { 
-     char *p; 
-     if(p!=NULL && *p!=0) (void)chdir(p); 
-     if(p!=NULL && *p!=0) { 
-         int i; 
-         if(i>0 && i<65536) sport=i; 
-     } 
-     if(- p !=- NULL  && strstr(- p ,"all")!=- NULL )-  acceptstr ="0.0.0.0";
 
- } 
-   
- int main(int argc, char *argv[]) 
- { 
-     struct stat st; 
-   
-     signal(SIGALRM,alarm2); 
-     sport=8088; pidcnt=0; idle=0; 
-     parm(); 
-     if(stat("public_html/wims.cgi",&st)!=0) { 
-         char buf[1024]; 
-         (void)getcwd(buf,sizeof(buf)); 
-         fprintf(- stderr ,"Bad home directory %s: \
 
- wims.cgi not found. \n- " ,- buf ); exit(1);
-     } 
- /*    if(stat("public_html/bin/pari",&st)==0) { 
-         fprintf(stderr,"wimsd must be run as nobody, \ 
- for security reasons!\n\n\ 
- Run bin/wrapuid as root to set things up correctly.\n"); exit(1); 
-     } 
- */    setreuid(geteuid(),getuid());setregid(getegid(),getgid()); 
-     sock=net_connect(sport); 
-      
-     serve(sock); 
-     close(sock); return 0; 
- } 
-   
-