You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Ben Laurie <be...@hyperreal.com> on 1997/06/15 21:22:56 UTC

cvs commit: apache/src/regex regex.mak

ben         97/06/15 12:22:54

  Modified:    src       .cvsignore alloc.c alloc.h buff.c buff.h conf.h 
                        http_conf_globals.h http_core.c http_log.c
                        http_main.c  http_main.h http_protocol.c
                        http_request.c httpd.h mod_alias.c  mod_cgi.c
                        mod_dir.c mod_include.c mod_info.c mod_log_agent.c 
                        mod_log_config.c mod_log_referer.c
                        mod_negotiation.c  mod_rewrite.c mod_rewrite.h
                        mod_userdir.c rfc1413.c  scoreboard.h util.c
                        util_script.c util_script.h
               src/modules/proxy  mod_proxy.c mod_proxy.h proxy_cache.c
                        proxy_connect.c  proxy_ftp.c proxy_http.c
                        proxy_util.c
  Added:       .         README.NT
               src       apache.mak multithread.h
               src/modules/proxy  proxy.mak
               src/nt    getopt.c getopt.h modules.c multithread.c
                        readdir.c readdir.h  service.c service.h
               src/regex  regex.mak
  Log:
  Initial NT support.
  Reviewed by:	Ben
  Submitted by:	Ambarish Malpani <am...@valicert.com> (integrated by Ben Laurie <be...@algroup.co.uk>)
  
  Revision  Changes    Path
  1.3       +3 -0      apache/src/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  RCS file: /export/home/cvs/apache/src/.cvsignore,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -C3 -r1.2 -r1.3
  *** .cvsignore	1997/02/18 05:29:29	1.2
  --- .cvsignore	1997/06/15 19:22:23	1.3
  ***************
  *** 3,5 ****
  --- 3,8 ----
    modules.c
    httpd
    Makefile.config
  + apache.mdp
  + apache.ncb
  + Release
  
  
  
  1.29      +207 -8    apache/src/alloc.c
  
  Index: alloc.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/alloc.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -C3 -r1.28 -r1.29
  *** alloc.c	1997/05/27 04:14:20	1.28
  --- alloc.c	1997/06/15 19:22:23	1.29
  ***************
  *** 60,67 ****
  --- 60,69 ----
    
    #include "conf.h"
    #include "alloc.h"
  + #include "multithread.h"
    
    #include <stdarg.h>
  + #include <assert.h>
    
    /*****************************************************************
     *
  ***************
  *** 97,103 ****
    };
    
    union block_hdr *block_freelist = NULL;
  ! 
    
    
    /* Get a completely new block from the system pool. Note that we rely on
  --- 99,106 ----
    };
    
    union block_hdr *block_freelist = NULL;
  ! mutex *alloc_mutex = NULL;
  ! mutex *spawn_mutex = NULL;
    
    
    /* Get a completely new block from the system pool. Note that we rely on
  ***************
  *** 143,152 ****
       * in the chain to point to the free blocks we already had.
       */
      
  !   union block_hdr *old_free_list = block_freelist;
    
      if (blok == NULL) return;	/* Sanity check --- freeing empty pool? */
      
      block_freelist = blok;
      
      /*
  --- 146,157 ----
       * in the chain to point to the free blocks we already had.
       */
      
  !   union block_hdr *old_free_list;
    
      if (blok == NULL) return;	/* Sanity check --- freeing empty pool? */
      
  +   acquire_mutex(alloc_mutex);
  +   old_free_list = block_freelist;
      block_freelist = blok;
      
      /*
  ***************
  *** 167,172 ****
  --- 172,178 ----
      /* Finally, reset next pointer to get the old free blocks back */
    
      blok->h.next = old_free_list;
  +   release_mutex(alloc_mutex);
    }
    
    
  ***************
  *** 264,269 ****
  --- 270,277 ----
      pool *new_pool;
    
      block_alarms();
  + 
  +   acquire_mutex(alloc_mutex);
      
      blok = new_block (0);
      new_pool = (pool *)blok->h.first_avail;
  ***************
  *** 280,291 ****
        p->sub_pools = new_pool;
      }
      
      unblock_alarms();
      
      return new_pool;
    }
    
  ! void init_alloc() { permanent_pool = make_sub_pool (NULL); }
    
    void clear_pool (struct pool *a)
    {
  --- 288,305 ----
        p->sub_pools = new_pool;
      }
      
  +   release_mutex(alloc_mutex);
      unblock_alarms();
      
      return new_pool;
    }
    
  ! void init_alloc()
  ! {
  !     alloc_mutex = create_mutex(NULL);
  !     spawn_mutex = create_mutex(NULL);
  !     permanent_pool = make_sub_pool (NULL);
  ! }
    
    void clear_pool (struct pool *a)
    {
  ***************
  *** 359,367 ****
  --- 373,387 ----
      /* Nope --- get a new one that's guaranteed to be big enough */
      
      block_alarms();
  +   
  +   acquire_mutex(alloc_mutex);
  + 
      blok = new_block (size);
      a->last->h.next = blok;
      a->last = blok;
  +   
  +   release_mutex(alloc_mutex);
  + 
      unblock_alarms();
    
      first_avail = blok->h.first_avail;
  ***************
  *** 771,779 ****
  --- 791,810 ----
    
    void cleanup_for_exec()
    {
  + #ifndef WIN32
  +     /*
  +      * Don't need to do anything on NT, because I
  +      * am actually going to spawn the new process - not
  +      * exec it. All handles that are not inheritable, will
  +      * be automajically closed. The only problem is with
  +      * file handles that are open, but there isn't much
  +      * I can do about that (except if the child decides
  +      * to go out and close them
  +      */
      block_alarms();
      cleanup_pool_for_exec (permanent_pool);
      unblock_alarms();
  + #endif /* ndef WIN32 */
    }
    
    /*****************************************************************
  ***************
  *** 837,842 ****
  --- 868,880 ----
    {
      FILE *fd = NULL;
      int baseFlag, desc;
  +   int modeFlags = 0;
  + 
  + #ifdef WIN32
  +   modeFlags = _S_IREAD | _S_IWRITE;
  + #else
  +   modeFlags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
  + #endif
    
      block_alarms();
    
  ***************
  *** 844,850 ****
        /* Work around faulty implementations of fopen */
        baseFlag = (*(mode+1) == '+') ? O_RDWR : O_WRONLY;
        desc = open(name, baseFlag | O_APPEND | O_CREAT,
  ! 		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if (desc >= 0) {
          fd = fdopen(desc, mode);
        }
  --- 882,888 ----
        /* Work around faulty implementations of fopen */
        baseFlag = (*(mode+1) == '+') ? O_RDWR : O_WRONLY;
        desc = open(name, baseFlag | O_APPEND | O_CREAT,
  ! 		modeFlags);
        if (desc >= 0) {
          fd = fdopen(desc, mode);
        }
  ***************
  *** 881,886 ****
  --- 919,964 ----
      return res;
    }
    
  + /*****************************************************************
  +  *
  +  * Files and file descriptors; these are just an application of the
  +  * generic cleanup interface.
  +  */
  + 
  + static void socket_cleanup (void *fdv)
  + {
  +     int rv;
  +     
  +     rv = closesocket((int)fdv);
  + }
  + 
  + void note_cleanups_for_socket (pool *p, int fd) {
  +   register_cleanup (p, (void *)fd, socket_cleanup, socket_cleanup);
  + }
  + 
  + void kill_cleanups_for_socket(pool *p,int sock)
  + {
  +     kill_cleanup(p,(void *)sock,socket_cleanup);
  + }
  + 
  + int pclosesocket(pool *a, int sock)
  + {
  +   int res;
  +   int save_errno;
  +   
  +   block_alarms();
  +   res = closesocket(sock);
  + #ifdef WIN32
  +   errno = WSAGetLastError() - WSABASEERR;
  + #endif /* WIN32 */
  +   save_errno = errno;
  +   kill_cleanup(a, (void *)sock, socket_cleanup);
  +   unblock_alarms();
  +   errno = save_errno;
  +   return res;
  + }
  + 
  + 
    /*
     * Here's a pool-based interface to POSIX regex's regcomp().
     * Note that we return regex_t instead of being passed one.
  ***************
  *** 939,945 ****
      a->subprocesses = new;
    }
    
  ! int spawn_child_err (pool *p, void (*func)(void *), void *data,
    		     enum kill_conditions kill_how,
    		     FILE **pipe_in, FILE **pipe_out, FILE **pipe_err)
    {
  --- 1017,1029 ----
      a->subprocesses = new;
    }
    
  ! #ifdef WIN32
  ! #define enc_pipe(fds) _pipe(fds, 512, O_TEXT | O_NOINHERIT)
  ! #else
  ! #define enc_pipe(fds) pipe(fds)
  ! #endif /* WIN32 */
  ! 
  ! int spawn_child_err (pool *p, int (*func)(void *), void *data,
    		     enum kill_conditions kill_how,
    		     FILE **pipe_in, FILE **pipe_out, FILE **pipe_err)
    {
  ***************
  *** 951,957 ****
    
      block_alarms();
      
  !   if (pipe_in && pipe (in_fds) < 0)
      {
          save_errno = errno;
          unblock_alarms();
  --- 1035,1041 ----
    
      block_alarms();
      
  !   if (pipe_in && enc_pipe (in_fds) < 0)
      {
          save_errno = errno;
          unblock_alarms();
  ***************
  *** 959,965 ****
          return 0;
      }
      
  !   if (pipe_out && pipe (out_fds) < 0) {
        save_errno = errno;
        if (pipe_in) {
          close (in_fds[0]); close (in_fds[1]);
  --- 1043,1049 ----
          return 0;
      }
      
  !   if (pipe_out && enc_pipe (out_fds) < 0) {
        save_errno = errno;
        if (pipe_in) {
          close (in_fds[0]); close (in_fds[1]);
  ***************
  *** 969,975 ****
        return 0;
      }
    
  !   if (pipe_err && pipe (err_fds) < 0) {
        save_errno = errno;
        if (pipe_in) {
          close (in_fds[0]); close (in_fds[1]);
  --- 1053,1059 ----
        return 0;
      }
    
  !   if (pipe_err && enc_pipe (err_fds) < 0) {
        save_errno = errno;
        if (pipe_in) {
          close (in_fds[0]); close (in_fds[1]);
  ***************
  *** 982,987 ****
  --- 1066,1151 ----
        return 0;
      }
    
  + #ifdef WIN32
  + 
  +   {
  +       HANDLE thread_handle;
  +       int hStdIn, hStdOut, hStdErr;
  +       int old_priority;
  +       
  +       acquire_mutex(spawn_mutex);
  +       thread_handle = GetCurrentThread(); /* doesn't need to be closed */
  +       old_priority = GetThreadPriority(thread_handle);
  +       SetThreadPriority(thread_handle, THREAD_PRIORITY_HIGHEST);
  +       /* Now do the right thing with your pipes */
  +       if(pipe_in)
  +       {
  +           hStdIn = dup(fileno(stdin));
  +           dup2(in_fds[0], fileno(stdin));
  +           close(in_fds[0]);
  +       }
  +       if(pipe_out)
  +       {
  +           hStdOut = dup(fileno(stdout));
  +           dup2(out_fds[1], fileno(stdout));
  +           close(out_fds[1]);
  +       }
  +       if(pipe_err)
  +       {
  +           hStdErr = dup(fileno(stderr));
  +           dup2(err_fds[1], fileno(stderr));
  +           close(err_fds[1]);
  +       }
  + 
  +       pid = (*func)(data);
  +       if(!pid)
  +       {
  +           save_errno = errno;
  +           close(in_fds[1]);
  +           close(out_fds[0]);
  +           close(err_fds[0]);
  +       }
  + 
  +       /* restore the original stdin, stdout and stderr */
  +       if(pipe_in)
  +           dup2(hStdIn, fileno(stdin));
  +       if(pipe_out)
  +           dup2(hStdOut, fileno(stdout));
  +       if(pipe_err)
  +           dup2(hStdErr, fileno(stderr));
  + 
  +       if(pid)
  +       {
  +           note_subprocess(p, pid, kill_how);
  +           if(pipe_in)
  +           {
  +               *pipe_in = fdopen(in_fds[1], "wb");
  +               if(*pipe_in)
  +                   note_cleanups_for_file(p, *pipe_in);
  +           }
  +           if(pipe_out)
  +           {
  +               *pipe_out = fdopen(out_fds[0], "rb");
  +               if(*pipe_out)
  +                   note_cleanups_for_file(p, *pipe_out);
  +           }
  +           if(pipe_err)
  +           {
  +               *pipe_err = fdopen(err_fds[0], "rb");
  +               if(*pipe_err)
  +                   note_cleanups_for_file(p, *pipe_err);
  +           }
  +       }
  +       SetThreadPriority(thread_handle, old_priority);
  +       release_mutex(spawn_mutex);
  +       /*
  +        * go on to the end of the function, where you can
  +        * unblock alarms and return the pid
  +        */
  + 
  +   }
  + #else
  + 
      if ((pid = fork()) < 0) {
        save_errno = errno;
        if (pipe_in) {
  ***************
  *** 1065,1070 ****
  --- 1229,1235 ----
      
        if (*pipe_err) note_cleanups_for_file (p, *pipe_err);
      }
  + #endif /* WIN32 */
    
      unblock_alarms();
      return pid;
  ***************
  *** 1089,1095 ****
  --- 1254,1293 ----
       * don't waste any more cycles doing whatever it is that they shouldn't
       * be doing anymore.
       */
  + #ifdef WIN32
  +   /* Pick up all defunct processes */
  +   for (p = procs; p; p = p->next) {
  +     if (GetExitCodeProcess((HANDLE)p->pid, &status)) {
  +       p->kill_how = kill_never;
  +     }
  +   }
  + 
    
  +   for (p = procs; p; p = p->next) {
  +     if (p->kill_how == kill_after_timeout) {
  + 	need_timeout = 1;
  +     } else if (p->kill_how == kill_always) {
  +       TerminateProcess((HANDLE)p->pid, 1);
  +     }
  +   }
  +   /* Sleep only if we have to... */
  + 
  +   if (need_timeout) sleep (3);
  + 
  +   /* OK, the scripts we just timed out for have had a chance to clean up
  +    * --- now, just get rid of them, and also clean up the system accounting
  +    * goop...
  +    */
  + 
  +   for (p = procs; p; p = p->next){
  +     if (p->kill_how == kill_after_timeout) 
  +       TerminateProcess((HANDLE)p->pid, 1);
  +   }
  + 
  +   for (p = procs; p; p = p->next){
  +     CloseHandle((HANDLE)p->pid);
  +   }
  + #else
    #ifndef NEED_WAITPID
      /* Pick up all defunct processes */
      for (p = procs; p; p = p->next) {
  ***************
  *** 1126,1130 ****
  --- 1324,1329 ----
        if (p->kill_how != kill_never)
          waitpid (p->pid, &status, 0);
      }
  + #endif /* WIN32 */
    }
    
  
  
  
  1.22      +5 -1      apache/src/alloc.h
  
  Index: alloc.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/alloc.h,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -C3 -r1.21 -r1.22
  *** alloc.h	1997/05/27 04:14:19	1.21
  --- alloc.h	1997/06/15 19:22:23	1.22
  ***************
  *** 213,218 ****
  --- 213,222 ----
    void note_cleanups_for_fd (pool *, int);
    void kill_cleanups_for_fd (pool *p, int fd);
    
  + void note_cleanups_for_socket (pool *, int);
  + void kill_cleanups_for_socket (pool *p, int sock);
  + int pclosesocket(pool *a, int sock);
  + 
    regex_t *pregcomp (pool *p, const char *pattern, int cflags);
    void pregfree (pool *p, regex_t *reg);
    
  ***************
  *** 235,241 ****
         
    enum kill_conditions { kill_never, kill_always, kill_after_timeout, just_wait};
    
  ! int spawn_child_err (pool *, void (*)(void *), void *,
    		 enum kill_conditions, FILE **pipe_in, FILE **pipe_out,
                     FILE **pipe_err);
    #define spawn_child(p,f,v,k,in,out) spawn_child_err(p,f,v,k,in,out,NULL)
  --- 239,245 ----
         
    enum kill_conditions { kill_never, kill_always, kill_after_timeout, just_wait};
    
  ! int spawn_child_err (pool *, int (*)(void *), void *,
    		 enum kill_conditions, FILE **pipe_in, FILE **pipe_out,
                     FILE **pipe_err);
    #define spawn_child(p,f,v,k,in,out) spawn_child_err(p,f,v,k,in,out,NULL)
  
  
  
  1.27      +174 -14   apache/src/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.c,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -C3 -r1.26 -r1.27
  *** buff.c	1997/05/29 05:21:15	1.26
  --- buff.c	1997/06/15 19:22:24	1.27
  ***************
  *** 72,77 ****
  --- 72,79 ----
    
    #define DEFAULT_BUFSIZE (4096)
    
  + extern int check_alarm(); /* didn't want to include http_main.h */
  + 
    /*
     * Buffered I/O routines.
     * These are a replacement for the stdio routines.
  ***************
  *** 96,101 ****
  --- 98,199 ----
     * futher I/O will be done
     */
    
  + #ifdef WIN32
  + #include <assert.h>
  + 
  + int
  + sendwithtimeout(int sock, const char *buf, int len, int flags)
  + {
  +     int iostate = 1;
  +     fd_set fdset;
  +     struct timeval tv;
  +     int err = WSAEWOULDBLOCK;
  +     int rv;
  + 
  +     if(!(tv.tv_sec = check_alarm()))
  +         return(send(sock, buf, len, flags));
  +     
  +     rv = ioctlsocket(sock, FIONBIO, &iostate);
  +     iostate = 0;
  +     if(rv)
  +     {
  +         err = WSAGetLastError();
  +         assert(0);
  +     }
  +     rv = send(sock, buf, len, flags);
  +     if(rv == SOCKET_ERROR)
  +     {
  +         err = WSAGetLastError();
  +         if(err == WSAEWOULDBLOCK)
  +         {
  +             FD_ZERO(&fdset);
  +             FD_SET(sock, &fdset);
  +             tv.tv_usec = 0;
  +             rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
  +             if(rv == 0)
  +             {
  +                 ioctlsocket(sock, FIONBIO, &iostate);
  +                 check_alarm();
  +                 WSASetLastError(WSAEWOULDBLOCK);
  +                 return(SOCKET_ERROR);
  +             }
  +             rv = send(sock, buf, len, flags);
  +             if(rv == SOCKET_ERROR)
  +                 err = WSAGetLastError();
  +         }
  +     }
  +     ioctlsocket(sock, FIONBIO, &iostate);
  +     if(rv == SOCKET_ERROR)
  +         WSASetLastError(err);
  +     return(rv);
  + }
  + 
  + 
  + int
  + recvwithtimeout(int sock, char *buf, int len, int flags)
  + {
  +     int iostate = 1;
  +     fd_set fdset;
  +     struct timeval tv;
  +     int err = WSAEWOULDBLOCK;
  +     int rv;
  + 
  +     if(!(tv.tv_sec = check_alarm()))
  +         return(recv(sock, buf, len, flags));
  +     
  +     rv = ioctlsocket(sock, FIONBIO, &iostate);
  +     iostate = 0;
  +     assert(!rv);
  +     rv = recv(sock, buf, len, flags);
  +     if(rv == SOCKET_ERROR)
  +     {
  +         err = WSAGetLastError();
  +         if(err == WSAEWOULDBLOCK)
  +         {
  +             FD_ZERO(&fdset);
  +             FD_SET(sock, &fdset);
  +             tv.tv_usec = 0;
  +             rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
  +             if(rv == 0)
  +             {
  +                 ioctlsocket(sock, FIONBIO, &iostate);
  +                 check_alarm();
  +                 WSASetLastError(WSAEWOULDBLOCK);
  +                 return(SOCKET_ERROR);
  +             }
  +             rv = recv(sock, buf, len, flags);
  +             if(rv == SOCKET_ERROR)
  +                 err = WSAGetLastError();
  +         }
  +     }
  +     ioctlsocket(sock, FIONBIO, &iostate);
  +     if(rv == SOCKET_ERROR)
  +         WSASetLastError(err);
  +     return(rv);
  + }
  + 
  + #endif /* WIN32 */    
  + 
    static void
    doerror(BUFF *fb, int err)
    {
  ***************
  *** 115,121 ****
     * Create a new buffered stream
     */
    BUFF *
  ! bcreate(pool *p, int flags)
    {
        BUFF *fb;
    
  --- 213,219 ----
     * Create a new buffered stream
     */
    BUFF *
  ! bcreate(pool *p, int flags, int is_socket)
    {
        BUFF *fb;
    
  ***************
  *** 142,147 ****
  --- 240,246 ----
    
        fb->fd = -1;
        fb->fd_in = -1;
  +     fb->is_socket = is_socket;
    
        return fb;
    }
  ***************
  *** 324,330 ****
  --- 423,440 ----
    	}
        }
        do {
  + #ifdef WIN32
  +         if(fb->is_socket)
  +         {
  +             rv = recvwithtimeout( fb->fd_in, buf, nbyte, 0 );
  +             if(rv == SOCKET_ERROR)
  +                 errno = WSAGetLastError() - WSABASEERR;
  +         }
  +         else
  +             rv = read( fb->fd_in, buf, nbyte );
  + #else
    	rv = read( fb->fd_in, buf, nbyte );
  + #endif /* WIN32 */
        } while (rv == -1 && errno == EINTR && !(fb->flags & B_EOUT));
        return( rv );
    }
  ***************
  *** 621,629 ****
    	return -1;
    
        while (nbyte > 0) {
  ! 	i = write(fb->fd, buf, nbyte);
  ! 	if (i < 0) {
  ! 	    if (errno != EAGAIN && errno != EINTR) {
    		return -1;
    	    }
    	}
  --- 731,750 ----
    	return -1;
    
        while (nbyte > 0) {
  ! #ifdef WIN32
  !         if(fb->is_socket)
  !         {
  !             i = sendwithtimeout( fb->fd, buf, nbyte, 0);
  !             if(i == SOCKET_ERROR)
  !                 errno = WSAGetLastError() - WSABASEERR;
  !         }
  !         else
  !             i = write( fb->fd, buf, nbyte );
  ! #else
  ! 	i = write( fb->fd, buf, nbyte );
  ! #endif /* WIN32 */
  ! 	if( i < 0 ) {
  ! 	    if( errno != EAGAIN && errno != EINTR ) {
    		return -1;
    	    }
    	}
  ***************
  *** 648,663 ****
    bcwrite(BUFF *fb, const void *buf, int nbyte)
    {
        char chunksize[16];	/* Big enough for practically anything */
    #ifndef NO_WRITEV
        struct iovec vec[3];
  !     int i, rv;
    #endif
    
        if (fb->flags & (B_WRERR|B_EOUT))
    	return -1;
    
        if (!(fb->flags & B_CHUNK))
  ! 	return write(fb->fd, buf, nbyte);
    
    #ifdef NO_WRITEV
        /* without writev() this has poor performance, too bad */
  --- 769,799 ----
    bcwrite(BUFF *fb, const void *buf, int nbyte)
    {
        char chunksize[16];	/* Big enough for practically anything */
  +     int i;
    #ifndef NO_WRITEV
        struct iovec vec[3];
  !     int rv;
    #endif
    
        if (fb->flags & (B_WRERR|B_EOUT))
    	return -1;
    
        if (!(fb->flags & B_CHUNK))
  !     {
  ! #ifdef WIN32
  !         if(fb->is_socket)
  !         {
  !             i = sendwithtimeout(fb->fd, buf, nbyte, 0 );
  !             if(i == SOCKET_ERROR)
  !                 errno = WSAGetLastError() - WSABASEERR;
  !         }
  !         else
  !             i = write(fb->fd, buf, nbyte);
  ! #else
  ! 	i = write(fb->fd, buf, nbyte);
  ! #endif /* WIN32 */
  !         return(i);
  !     }
    
    #ifdef NO_WRITEV
        /* without writev() this has poor performance, too bad */
  ***************
  *** 778,787 ****
    	     */
    	    i = (write_it_all(fb, fb->outbase, fb->outcnt) == -1) ?
    	            -1 : fb->outcnt;
  ! 	}
  ! 	else {
  ! 	    do i = write(fb->fd, fb->outbase, fb->outcnt);
  ! 	    while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
    	}
    	if (i <= 0) {
    	    if (i == 0) /* return of 0 means non-blocking */
  --- 914,935 ----
    	     */
    	    i = (write_it_all(fb, fb->outbase, fb->outcnt) == -1) ?
    	            -1 : fb->outcnt;
  ! 	} else {
  ! 	    do {
  ! #ifdef WIN32
  !                 if(fb->is_socket)
  !                 {
  !                     i = sendwithtimeout(fb->fd, fb->outbase, fb->outcnt, 0 );
  !                     if(i == SOCKET_ERROR)
  !                         errno = WSAGetLastError() - WSABASEERR;
  !                 }
  !                 else
  !                     i = write(fb->fd, fb->outbase, fb->outcnt);
  ! 
  ! #else
  ! 	        i = write(fb->fd, fb->outbase, fb->outcnt);
  ! #endif /* WIN32 */
  ! 	    } while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
    	}
    	if (i <= 0) {
    	    if (i == 0) /* return of 0 means non-blocking */
  ***************
  *** 862,869 ****
        while (fb->outcnt > 0)
        {
    	/* the buffer must be full */
  ! 	do i = write(fb->fd, fb->outbase, fb->outcnt);
  ! 	while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
    	if (i == 0) {
    	    errno = EAGAIN;
    	    return -1;  /* return of 0 means non-blocking */
  --- 1010,1029 ----
        while (fb->outcnt > 0)
        {
    	/* the buffer must be full */
  ! 	do {
  ! #ifdef WIN32
  !                 if(fb->is_socket)
  !                 {
  !                     i = sendwithtimeout(fb->fd, fb->outbase, fb->outcnt, 0 );
  !                     if(i == SOCKET_ERROR)
  !                         errno = WSAGetLastError() - WSABASEERR;
  !                 }
  !                 else
  !                     i = write(fb->fd, fb->outbase, fb->outcnt);
  ! #else
  ! 	        i = write(fb->fd, fb->outbase, fb->outcnt);
  ! #endif /* WIN32 */
  ! 	} while (i == -1 && errno == EINTR && !(fb->flags & B_EOUT));
    	if (i == 0) {
    	    errno = EAGAIN;
    	    return -1;  /* return of 0 means non-blocking */
  ***************
  *** 908,915 ****
    
        if (fb->flags & B_WR) rc1 = bflush(fb);
        else rc1 = 0;
  !     rc2 = close(fb->fd);
  !     if (fb->fd_in != fb->fd) rc3 = close(fb->fd_in);
        else rc3 = 0;
    
        fb->inptr = fb->inbase;
  --- 1068,1075 ----
    
        if (fb->flags & B_WR) rc1 = bflush(fb);
        else rc1 = 0;
  !     rc2 = closesocket(fb->fd);
  !     if (fb->fd_in != fb->fd) rc3 = closesocket(fb->fd_in);
        else rc3 = 0;
    
        fb->inptr = fb->inbase;
  
  
  
  1.13      +2 -1      apache/src/buff.h
  
  Index: buff.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.h,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -C3 -r1.12 -r1.13
  *** buff.h	1997/02/10 15:49:54	1.12
  --- buff.h	1997/06/15 19:22:24	1.13
  ***************
  *** 94,106 ****
    /* could also put pointers to the basic I/O routines here */
        int fd;                /* the file descriptor */
        int fd_in;             /* input file descriptor, if different */
    };
    
    /* Options to bset/getopt */
    #define BO_BYTECT (1)
    
    /* Stream creation and modification */
  ! extern BUFF *bcreate(pool *p, int flags);
    extern void bpushfd(BUFF *fb, int fd_in, int fd_out);
    extern int bsetopt(BUFF *fb, int optname, const void *optval);
    extern int bgetopt(BUFF *fb, int optname, void *optval);
  --- 94,107 ----
    /* could also put pointers to the basic I/O routines here */
        int fd;                /* the file descriptor */
        int fd_in;             /* input file descriptor, if different */
  +     int is_socket;         /* whether fd/fd_in are sockets */
    };
    
    /* Options to bset/getopt */
    #define BO_BYTECT (1)
    
    /* Stream creation and modification */
  ! extern BUFF *bcreate(pool *p, int flags, int is_socket);
    extern void bpushfd(BUFF *fb, int fd_in, int fd_out);
    extern int bsetopt(BUFF *fb, int optname, const void *optval);
    extern int bgetopt(BUFF *fb, int optname, void *optval);
  
  
  
  1.100     +74 -13    apache/src/conf.h
  
  Index: conf.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/conf.h,v
  retrieving revision 1.99
  retrieving revision 1.100
  diff -C3 -r1.99 -r1.100
  *** conf.h	1997/06/04 07:03:11	1.99
  --- conf.h	1997/06/15 19:22:24	1.100
  ***************
  *** 55,61 ****
     * See README for a listing of what they mean
     */
    
  ! #if !defined(QNX) && !defined(MPE)
    #include <sys/param.h>
    #endif
    
  --- 55,61 ----
     * See README for a listing of what they mean
     */
    
  ! #if !defined(QNX) && !defined(MPE) && !defined(WIN32)
    #include <sys/param.h>
    #endif
    
  ***************
  *** 500,505 ****
  --- 500,551 ----
    #define JMP_BUF sigjmp_buf
    #define USE_FCNTL_SERIALIZED_ACCEPT
    
  + #elif defined(WIN32)     
  + /* Put your NT stuff here - Ambarish */
  + 
  + /* temporarily replace crypt */
  + //char *crypt(const char *pw, const char *salt);
  + #define crypt(buf,salt)	    (buf)
  + 
  + /* Although DIR_TYPE is dirent (see nt/readdir.h) we need direct.h for
  +    chdir() */
  + #include <direct.h>
  + 
  + #define WIN32_LEAN_AND_MEAN
  + #define STRICT
  + #define NO_UNISTD_H
  + #define NO_WRITEV
  + #define NO_SETSID
  + #define NO_USE_SIGACTION
  + #define NEED_PROCESS_H
  + #define USE_LONGJMP
  + #define HAVE_MMAP
  + #define MULTITHREAD
  + typedef int uid_t;
  + typedef int gid_t;
  + typedef int pid_t;
  + typedef int mode_t;
  + typedef char * caddr_t;
  + #define strcasecmp(s1, s2) stricmp(s1, s2)
  + #define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
  + #define lstat(x, y) stat(x, y)
  + #define S_ISLNK(m) (0)
  + #define S_ISREG(m) ((m & _S_IFREG) == _S_IFREG)
  + #ifndef S_ISDIR
  + #define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR)
  + #endif
  + #ifndef S_ISREG
  + #define S_ISREG(m)      (((m)&(S_IFREG)) == (S_IFREG))
  + #endif
  + #define STDIN_FILENO  0
  + #define STDOUT_FILENO 1
  + #define STDERR_FILENO 2
  + #define JMP_BUF jmp_buf
  + #define sleep(t) Sleep(t*1000)
  + #define O_CREAT _O_CREAT
  + #define O_RDWR _O_RDWR
  + #define SIGPIPE 17
  + #include <stddef.h>
    /* Unknown system - Edit these to match */
    #else
    #ifdef BSD
  ***************
  *** 545,587 ****
    int ap_vsnprintf(char *buf, size_t len, const char *format, va_list ap);
    #endif
    
  ! #if !defined(NEXT) && !defined(CONVEXOS)
    #include <dirent.h>
    #define DIR_TYPE dirent
  ! #else
    #include <sys/dir.h>
    #define DIR_TYPE direct
    #endif
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
  ! #ifndef MPE
    #include <sys/file.h>
    #endif
    #include <sys/socket.h>
    #ifdef HAVE_SYS_SELECT_H
    #include <sys/select.h>
  ! #endif
  ! #include <ctype.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/ioctl.h>
    #ifndef MPE
    #include <arpa/inet.h>  /* for inet_ntoa */
  ! #endif
  ! #include <time.h>  /* for ctime */
  ! #include <signal.h>
  ! #include <errno.h>
    #include <sys/wait.h>
    #include <pwd.h>
    #include <grp.h>
    #include <fcntl.h>
    #include <limits.h>
    #if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT)
    #include <memory.h>
    #endif
    #ifdef NEED_PROCESS_H
    #include <process.h>
    #endif
  --- 591,648 ----
    int ap_vsnprintf(char *buf, size_t len, const char *format, va_list ap);
    #endif
    
  ! #if !defined(NEXT) && !defined(CONVEXOS) && !defined(WIN32)
    #include <dirent.h>
    #define DIR_TYPE dirent
  ! #elif !defined(WIN32)
    #include <sys/dir.h>
    #define DIR_TYPE direct
  + #else
  + #define DIR_TYPE dirent
    #endif
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/stat.h>
  ! #include <ctype.h>
  ! #if !defined(MPE) && !defined(WIN32)
    #include <sys/file.h>
    #endif
  + #ifndef WIN32
    #include <sys/socket.h>
    #ifdef HAVE_SYS_SELECT_H
    #include <sys/select.h>
  ! #endif /* HAVE_SYS_SELECT_H */
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/ioctl.h>
    #ifndef MPE
    #include <arpa/inet.h>  /* for inet_ntoa */
  ! #endif /* ndef MPE */
    #include <sys/wait.h>
    #include <pwd.h>
    #include <grp.h>
    #include <fcntl.h>
    #include <limits.h>
  + #define closesocket(s) close(s)
  + #define O_BINARY (0)
  + 
  + #else /* WIN32 */
  + #include <winsock.h>
  + #include <malloc.h>
  + #include <io.h>
  + #include <fcntl.h>
  + #endif /* ndef WIN32 */
  + 
  + #include <time.h>  /* for ctime */
  + #include <signal.h>
  + #include <errno.h>
    #if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT)
    #include <memory.h>
    #endif
  + 
  + 
    #ifdef NEED_PROCESS_H
    #include <process.h>
    #endif
  ***************
  *** 596,602 ****
    #endif
    #endif
    #ifdef HAVE_MMAP
  ! #ifndef __EMX__
    /* This file is not needed for OS/2 */
    #include <sys/mman.h>
    #endif
  --- 657,663 ----
    #endif
    #endif
    #ifdef HAVE_MMAP
  ! #if !defined(__EMX__) && !defined(WIN32)
    /* This file is not needed for OS/2 */
    #include <sys/mman.h>
    #endif
  ***************
  *** 613,619 ****
    #define LOGNAME_MAX 25
    #endif
    
  ! #ifndef NEXT
    #include <unistd.h>
    #endif
    
  --- 674,680 ----
    #define LOGNAME_MAX 25
    #endif
    
  ! #if !defined(NEXT) && !defined(WIN32)
    #include <unistd.h>
    #endif
    
  ***************
  *** 749,752 ****
         
    long vfprintf (FILE *, char *, va_list);
         
  ! #endif
  --- 810,813 ----
         
    long vfprintf (FILE *, char *, va_list);
         
  ! #endif /* SUNOS_LIB_PROTOTYPES */
  
  
  
  1.10      +2 -0      apache/src/http_conf_globals.h
  
  Index: http_conf_globals.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_conf_globals.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -C3 -r1.9 -r1.10
  *** http_conf_globals.h	1997/01/01 18:10:16	1.9
  --- http_conf_globals.h	1997/06/15 19:22:25	1.10
  ***************
  *** 62,67 ****
  --- 62,69 ----
    extern gid_t group_id_list[NGROUPS_MAX];
    #endif
    extern int max_requests_per_child;
  + extern int threads_per_child;
  + extern int excess_requests_per_child;
    extern struct in_addr bind_address;
    extern listen_rec *listeners;
    extern int daemons_to_start;
  
  
  
  1.83      +15 -2     apache/src/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_core.c,v
  retrieving revision 1.82
  retrieving revision 1.83
  diff -C3 -r1.82 -r1.83
  *** http_core.c	1997/06/10 00:28:31	1.82
  --- http_core.c	1997/06/15 19:22:25	1.83
  ***************
  *** 1020,1025 ****
  --- 1020,1036 ----
        return NULL;
    }
    
  + const char *set_threads (cmd_parms *cmd, void *dummy, char *arg) {
  +     threads_per_child = atoi (arg);
  +     return NULL;
  + }
  + 
  + const char *set_excess_requests (cmd_parms *cmd, void *dummy, char *arg) {
  +     excess_requests_per_child = atoi (arg);
  +     return NULL;
  + }
  + 
  + 
    #if defined(RLIMIT_CPU) || defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_NPROC)
    static void set_rlimit(cmd_parms *cmd, struct rlimit **plimit, const char *arg,
                           const char * arg2, int type)
  ***************
  *** 1258,1263 ****
  --- 1269,1276 ----
    { "AddModule", add_module_command, NULL, RSRC_CONF, ITERATE,
      "the name of a module" },
    { "ClearModuleList", clear_module_list_command, NULL, RSRC_CONF, NO_ARGS, NULL },
  + { "ThreadsPerChild", set_threads, NULL, RSRC_CONF, TAKE1, "Number of threads a child creates" },
  + { "ExcessRequestsPerChild", set_excess_requests, NULL, RSRC_CONF, TAKE1, "Maximum number of requests a particular child serves after it is ready to die." },
    { NULL },
    };
    
  ***************
  *** 1325,1332 ****
    	return NOT_FOUND;
        }
        if (r->method_number != M_GET) return METHOD_NOT_ALLOWED;
  !     
  ! #ifdef __EMX__
        /* Need binary mode for OS/2 */
        f = pfopen (r->pool, r->filename, "rb");
    #else
  --- 1338,1345 ----
    	return NOT_FOUND;
        }
        if (r->method_number != M_GET) return METHOD_NOT_ALLOWED;
  ! 	
  ! #if defined(__EMX__) || defined(WIN32)
        /* Need binary mode for OS/2 */
        f = pfopen (r->pool, r->filename, "rb");
    #else
  
  
  
  1.14      +12 -3     apache/src/http_log.c
  
  Index: http_log.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_log.c,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -C3 -r1.13 -r1.14
  *** http_log.c	1997/03/22 23:51:01	1.13
  --- http_log.c	1997/06/15 19:22:25	1.14
  ***************
  *** 65,86 ****
    
    #include <stdarg.h>
    
  ! void error_log_child (void *cmd)
    {
        /* Child process code for 'ErrorLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     
        cleanup_for_exec();
        signal (SIGHUP, SIG_IGN);
  ! #ifdef __EMX__
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else    
        execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    #endif    
        exit (1);
    }
    
    void open_error_log(server_rec *s, pool *p)
  --- 65,95 ----
    
    #include <stdarg.h>
    
  ! static int
  ! error_log_child (void *cmd)
    {
        /* Child process code for 'ErrorLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     int child_pid = 0;
  ! 
        cleanup_for_exec();
  + #ifdef SIGHUP
  +     /* No concept of a child process on Win32 */
        signal (SIGHUP, SIG_IGN);
  ! #endif /* ndef SIGHUP */
  ! #if defined(WIN32)
  !     child_pid = spawnl (_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  !     return(child_pid);
  ! #elif defined(__EMX__)
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else    
        execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    #endif    
        exit (1);
  +     return(child_pid);
    }
    
    void open_error_log(server_rec *s, pool *p)
  
  
  
  1.150     +1232 -187 apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.149
  retrieving revision 1.150
  diff -C3 -r1.149 -r1.150
  *** http_main.c	1997/05/29 04:50:27	1.149
  --- http_main.c	1997/06/15 19:22:26	1.150
  ***************
  *** 84,89 ****
  --- 84,90 ----
    #include "http_conf_globals.h"
    #include "http_core.h"          /* for get_remote_host */
    #include "scoreboard.h"
  + #include "multithread.h"
    #include <assert.h>
    #include <sys/stat.h>
    #ifdef HAVE_SHMGET
  ***************
  *** 96,102 ****
  --- 97,107 ----
    #include <sys/audit.h>
    #include <prot.h>
    #endif
  + #ifdef WIN32
  + #include "nt/getopt.h"
  + #else
    #include <netinet/tcp.h>
  + #endif
    
    #ifdef HAVE_BSTRING_H
    #include <bstring.h>		/* for IRIX, FD_SET calls bzero() */
  ***************
  *** 108,113 ****
  --- 113,123 ----
    #define max(a,b)        (a > b ? a : b)
    #endif
    
  + #ifdef WIN32
  + #include "nt/service.h"
  + #endif
  + 
  + 
    #ifdef __EMX__
        /* Add MMAP style functionality to OS/2 */
        #ifdef HAVE_MMAP
  ***************
  *** 136,141 ****
  --- 146,153 ----
    gid_t group_id_list[NGROUPS_MAX];
    #endif
    int max_requests_per_child;
  + int threads_per_child;
  + int excess_requests_per_child;
    char *pid_fname;
    char *scoreboard_fname;
    char *server_argv0;
  ***************
  *** 154,160 ****
    /* *Non*-shared http_main globals... */
    
    server_rec *server_conf;
  ! JMP_BUF jmpbuffer;
    int sd;
    static fd_set listenfds;
    static int listenmaxfd;
  --- 166,172 ----
    /* *Non*-shared http_main globals... */
    
    server_rec *server_conf;
  ! JMP_BUF __declspec( thread ) jmpbuffer;
    int sd;
    static fd_set listenfds;
    static int listenmaxfd;
  ***************
  *** 175,185 ****
  --- 187,201 ----
    
    /* small utility macros to make things easier to read */
    
  + #ifdef WIN32
  + #define ap_killpg(x, y)
  + #else 
    #ifdef NO_KILLPG
    #define ap_killpg(x, y)		(kill (-(x), (y)))
    #else
    #define ap_killpg(x, y)		(killpg ((x), (y)))
    #endif
  + #endif /* WIN32 */
    
    #if defined(USE_FCNTL_SERIALIZED_ACCEPT)
    static struct flock lock_it;
  ***************
  *** 335,345 ****
     * one timeout in progress at a time...
     */
    
  ! static conn_rec *current_conn;
  ! static request_rec *timeout_req;
  ! static char *timeout_name = NULL;
  ! static int alarms_blocked = 0;
  ! static int alarm_pending = 0;
    
    #ifndef NO_USE_SIGACTION
    /*
  --- 351,361 ----
     * one timeout in progress at a time...
     */
    
  ! static  __declspec( thread ) conn_rec * current_conn;
  ! static __declspec( thread ) request_rec *timeout_req;
  ! static __declspec( thread ) char *timeout_name = NULL;
  ! static __declspec( thread ) int alarms_blocked = 0;
  ! static __declspec( thread ) int alarm_pending = 0;
    
    #ifndef NO_USE_SIGACTION
    /*
  ***************
  *** 440,455 ****
        }
    }
    
    void keepalive_timeout (char *name, request_rec *r)
    {
        timeout_req = r;
        timeout_name = name;
  !     
  !     signal(SIGALRM, timeout);
        if (r->connection->keptalive) 
  !        alarm (r->server->keep_alive_timeout);
        else
  !        alarm (r->server->timeout);
    }
    
    void hard_timeout (char *name, request_rec *r)
  --- 456,555 ----
        }
    }
    
  + 
  + static __declspec( thread ) void (*alarm_fn)(int) = NULL;
  + #ifdef WIN32
  + static __declspec( thread ) unsigned int alarm_expiry_time = 0;
  + #endif /* WIN32 */
  + 
  + unsigned int
  + set_callback_and_alarm(void (*fn)(int), int x)
  + {
  +     unsigned int old;
  + 
  + #ifdef WIN32
  +     old = alarm_expiry_time;
  +     if(old)
  +         old -= time(0);
  +     if(x == 0)
  +     {
  +         alarm_fn = NULL;
  +         alarm_expiry_time = 0;
  +     }
  +     else
  +     {
  +         alarm_fn = fn;
  +         alarm_expiry_time = time(NULL) + x;
  +     }
  + #else
  +     if(x)
  + 	alarm_fn = fn;
  +     signal(SIGALRM, fn);
  +     old = alarm(x);
  + #endif
  +     return(old);
  + }
  + 
  + 
  + int
  + check_alarm()
  + {
  + #ifdef WIN32
  +     if(alarm_expiry_time)
  +     {
  +         unsigned int t;
  + 
  +         t = time(NULL);
  +         if(t >= alarm_expiry_time)
  +         {
  +             alarm_expiry_time = 0;
  +             (*alarm_fn)(0);
  +             return(-1);
  +         }
  +         else
  +         {
  +             return(alarm_expiry_time - t);
  +         }
  +     }
  +     else
  +         return(0);
  + #else
  +     return(0);
  + #endif /* WIN32 */
  + }
  + 
  + 
  + 
  + /* reset_timeout (request_rec *) resets the timeout in effect,
  +  * as long as it hasn't expired already.
  +  */
  + 
  + void reset_timeout (request_rec *r) {
  +     int i;
  + 
  +     if (timeout_name) { /* timeout has been set */
  +         i = set_callback_and_alarm(alarm_fn, r->server->timeout);
  +         if (i == 0) /* timeout already expired, so set it back to 0 */
  + 	    set_callback_and_alarm(alarm_fn, 0);
  +     }
  + }
  + 
  + 
  + 
  + 
    void keepalive_timeout (char *name, request_rec *r)
    {
  +     unsigned int to;
  + 
        timeout_req = r;
        timeout_name = name;
  ! 
        if (r->connection->keptalive) 
  !        to = r->server->keep_alive_timeout;
        else
  !        to = r->server->timeout;
  !     set_callback_and_alarm(timeout, to);
  ! 
    }
    
    void hard_timeout (char *name, request_rec *r)
  ***************
  *** 457,493 ****
        timeout_req = r;
        timeout_name = name;
        
  !     signal(SIGALRM, timeout);
  !     alarm (r->server->timeout);
    }
    
    void soft_timeout (char *name, request_rec *r)
    {
        timeout_name = name;
        
  !     signal(SIGALRM, timeout);
  !     alarm (r->server->timeout);
    }
    
    void kill_timeout (request_rec *dummy) {
  !     alarm (0);
        timeout_req = NULL;
        timeout_name = NULL;
    }
    
  - /* reset_timeout (request_rec *) resets the timeout in effect,
  -  * as long as it hasn't expired already.
  -  */
  - 
  - void reset_timeout (request_rec *r) {
  -     int i;
  - 
  -     if (timeout_name) { /* timeout has been set */
  -         i = alarm(r->server->timeout);
  -         if (i == 0) /* timeout already expired, so set it back to 0 */
  - 	    alarm(0);
  -     }
  - }
    
    /*
     * More machine-dependent networking gooo... on some systems,
  --- 557,580 ----
        timeout_req = r;
        timeout_name = name;
        
  !     set_callback_and_alarm(timeout, r->server->timeout);
  ! 
    }
    
    void soft_timeout (char *name, request_rec *r)
    {
        timeout_name = name;
        
  !     set_callback_and_alarm(timeout, r->server->timeout);
  ! 
    }
    
    void kill_timeout (request_rec *dummy) {
  !     set_callback_and_alarm(NULL, 0);
        timeout_req = NULL;
        timeout_name = NULL;
    }
    
    
    /*
     * More machine-dependent networking gooo... on some systems,
  ***************
  *** 538,545 ****
    
    /* Special version of timeout for lingering_close */
    
  ! static void lingerout(sig)
  ! int sig;
    {
        if (alarms_blocked) {
    	alarm_pending = 1;
  --- 625,631 ----
    
    /* Special version of timeout for lingering_close */
    
  ! static void lingerout(int sig)
    {
        if (alarms_blocked) {
    	alarm_pending = 1;
  ***************
  *** 557,564 ****
    {
        timeout_name = "lingering close";
        
  !     signal(SIGALRM, lingerout);
  !     alarm(MAX_SECS_TO_LINGER);
    }
    
    /* Since many clients will abort a connection instead of closing it,
  --- 643,649 ----
    {
        timeout_name = "lingering close";
        
  !     set_callback_and_alarm(lingerout, MAX_SECS_TO_LINGER);
    }
    
    /* Since many clients will abort a connection instead of closing it,
  ***************
  *** 653,658 ****
  --- 738,772 ----
     * We begin with routines which deal with the file itself... 
     */
    
  + #ifdef MULTITHREAD
  + /*
  +  * In the multithreaded mode, have multiple threads - not multiple
  +  * processes that need to talk to each other. Just use a simple
  +  * malloc. But let the routines that follow, think that you have
  +  * shared memory (so they use memcpy etc.)
  +  */
  + #undef HAVE_MMAP
  + #define HAVE_MMAP 1
  + static scoreboard *scoreboard_image = NULL;
  + 
  + void reinit_scoreboard (pool *p)
  + {
  +     assert(!scoreboard_image);
  +     scoreboard_image = (scoreboard *)calloc(HARD_SERVER_LIMIT, sizeof(short_score));
  + }
  + 
  + void cleanup_scoreboard ()
  + {
  +     assert(scoreboard_image);
  +     free(scoreboard_image);
  +     scoreboard_image = NULL;
  + }
  + 
  + void sync_scoreboard_image ()
  + {}
  + 
  + 
  + #else /* MULTITHREAD */
    #if defined(HAVE_MMAP)
    static scoreboard *scoreboard_image=NULL;
    
  ***************
  *** 941,946 ****
  --- 1055,1062 ----
    #endif
    }
    
  + #endif /* MULTITHREAD */
  + 
    int update_child_status (int child_num, int status, request_rec *r)
    {
        int old_status;
  ***************
  *** 1110,1115 ****
  --- 1226,1232 ----
    
    void reclaim_child_processes ()
    {
  + #ifndef MULTITHREAD
        int i, status;
        int my_pid = getpid();
    
  ***************
  *** 1169,1174 ****
  --- 1286,1292 ----
    	    }
    	}
        }
  + #endif /* ndef MULTITHREAD */
    }
    
    #if defined(BROKEN_WAIT) || defined(NEED_WAITPID)
  ***************
  *** 1203,1208 ****
  --- 1321,1360 ----
    
    static int wait_or_timeout ()
    {
  + #ifdef WIN32
  + #define MAXWAITOBJ MAXIMUM_WAIT_OBJECTS
  +     HANDLE h[MAXWAITOBJ];
  +     int e[MAXWAITOBJ];
  +     int round, pi, hi, rv, err;
  +     for(round=0; round<=(HARD_SERVER_LIMIT-1)/MAXWAITOBJ+1; round++)
  +     {
  +         hi = 0;
  +         for(pi=round*MAXWAITOBJ;
  +                 (pi<(round+1)*MAXWAITOBJ) && (pi<HARD_SERVER_LIMIT);
  +                 pi++)
  +         {
  +             if(scoreboard_image->servers[pi].status != SERVER_DEAD)
  +             {
  +                 e[hi] = pi;
  +                 h[hi++] = (HANDLE)scoreboard_image->servers[pi].pid;
  +             }
  + 
  +         }
  +         if(hi > 0)
  +         {
  +             rv = WaitForMultipleObjects(hi, h, FALSE, 10000);
  +             if(rv == -1)
  +                 err = GetLastError();
  +             if((WAIT_OBJECT_0 <= (unsigned int)rv) && ((unsigned int)rv < (WAIT_OBJECT_0 + hi)))
  +                 return(scoreboard_image->servers[e[rv - WAIT_OBJECT_0]].pid);
  +             else if((WAIT_ABANDONED_0 <= (unsigned int)rv) && ((unsigned int)rv < (WAIT_ABANDONED_0 + hi)))
  +                 return(scoreboard_image->servers[e[rv - WAIT_ABANDONED_0]].pid);
  + 
  +         }
  +     }
  +     return(-1);
  + 
  + #else /* WIN32 */
    #ifndef NEED_WAITPID
        int ret;
    
  ***************
  *** 1221,1233 ****
  --- 1373,1388 ----
        }
        return -1;
    #endif
  + #endif /* WIN32 */
    }
    
    
    void sig_term() {
        log_error("httpd: caught SIGTERM, shutting down", server_conf);
        cleanup_scoreboard();
  + #ifdef SIGKILL
        ap_killpg (pgrp, SIGKILL);
  + #endif /* SIGKILL */
        close(sd);
        exit(1);
    }
  ***************
  *** 1283,1289 ****
  --- 1438,1448 ----
    
    static void restart (int sig)
    {
  + #ifdef WIN32
  +     is_graceful = 0;
  + #else
        is_graceful = (sig == SIGUSR1);
  + #endif /* WIN32 */
        restart_pending = 1;
    }
    
  ***************
  *** 1327,1339 ****
    	log_unixerr ("sigaction(SIGUSR1)", NULL, NULL, server_conf);
    #else
        if(!one_process) {
  ! 	signal (SIGSEGV, (void (*)())seg_fault);
  !     	signal (SIGBUS, (void (*)())bus_error);
        }
    
  !     signal (SIGTERM, (void (*)())sig_term);
  !     signal (SIGHUP, (void (*)())restart);
        signal (SIGUSR1, (void (*)())restart);
    #endif
    }
    
  --- 1486,1504 ----
    	log_unixerr ("sigaction(SIGUSR1)", NULL, NULL, server_conf);
    #else
        if(!one_process) {
  ! 	signal (SIGSEGV, (void (*)(int))seg_fault);
  ! #ifdef SIGBUS
  !     	signal (SIGBUS, (void (*)(int))bus_error);
  ! #endif /* SIGBUS */
        }
    
  !     signal (SIGTERM, (void (*)(int))sig_term);
  ! #ifdef SIGHUP
  !     signal (SIGHUP, (void (*)(int))restart);
  ! #endif /* SIGHUP */
  ! #ifdef SIGUSR1
        signal (SIGUSR1, (void (*)())restart);
  + #endif /* SIGUSR1 */
    #endif
    }
    
  ***************
  *** 1344,1349 ****
  --- 1509,1515 ----
    
    void detach()
    {
  + #ifndef WIN32
        int x;
    
        chdir("/");
  ***************
  *** 1371,1378 ****
            exit(1);
        }
    #elif defined(__EMX__)
  !     /* OS/2 doesn't support process group IDs */
  !     pgrp=getpid();
    #elif defined(MPE)
        /* MPE uses negative pid for process group */
        pgrp=-getpid();
  --- 1537,1544 ----
            exit(1);
        }
    #elif defined(__EMX__)
  !     /* OS/2 don't support process group IDs */
  !     pgrp=-getpid();
    #elif defined(MPE)
        /* MPE uses negative pid for process group */
        pgrp=-getpid();
  ***************
  *** 1382,1388 ****
            fprintf(stderr,"httpd: setpgrp failed\n");
            exit(1);
        }
  ! #endif
    }
    
    /* Reset group privileges, after rereading the config files
  --- 1548,1555 ----
            fprintf(stderr,"httpd: setpgrp failed\n");
            exit(1);
        }
  ! #endif    
  ! #endif /* ndef WIN32 */
    }
    
    /* Reset group privileges, after rereading the config files
  ***************
  *** 1399,1404 ****
  --- 1566,1572 ----
      
    static void set_group_privs()
    {
  + #ifndef WIN32
      if(!geteuid()) {
        char *name;
      
  ***************
  *** 1437,1447 ****
  --- 1605,1617 ----
        }
    #endif 
      }
  + #endif /* ndef WIN32 */
    }
    
    /* check to see if we have the 'suexec' setuid wrapper installed */
    int init_suexec ()
    {
  + #ifndef WIN32
        struct stat wrapper;
        
        if ((stat(SUEXEC_BIN, &wrapper)) != 0)
  ***************
  *** 1451,1457 ****
          suexec_enabled = 1;
          fprintf(stderr, "Configuring Apache for use with suexec wrapper.\n");
        }
  ! 
        return (suexec_enabled);
    }
    
  --- 1621,1627 ----
          suexec_enabled = 1;
          fprintf(stderr, "Configuring Apache for use with suexec wrapper.\n");
        }
  ! #endif /* ndef WIN32 */
        return (suexec_enabled);
    }
    
  ***************
  *** 1637,1642 ****
  --- 1807,2001 ----
    #define sock_disable_nagle(s) /* NOOP */
    #endif
    
  + static int make_sock(pool *pconf, const struct sockaddr_in *server)
  + {
  +     int s;
  +     int one = 1;
  + 
  +     if ((s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  +         log_unixerr("socket", NULL, "Failed to get a socket, exiting child",
  +                     server_conf);
  +         exit(1);
  +     }
  + 
  +     note_cleanups_for_socket(pconf, s); /* arrange to close on exec or restart */
  +     
  + #ifndef MPE
  + /* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
  +     if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) {
  +         log_unixerr("setsockopt", "(SO_REUSEADDR)", NULL, server_conf);
  +         exit(1);
  +     }
  +     one = 1;
  +     if (setsockopt(s, SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(int)) < 0) {
  +         log_unixerr("setsockopt", "(SO_KEEPALIVE)", NULL, server_conf);
  +         exit(1);
  +     }
  + #endif
  + 
  +     sock_disable_nagle(s);
  +     sock_enable_linger(s);
  +     
  +     /*
  +      * To send data over high bandwidth-delay connections at full
  +      * speed we must force the TCP window to open wide enough to keep the
  +      * pipe full.  The default window size on many systems
  +      * is only 4kB.  Cross-country WAN connections of 100ms
  +      * at 1Mb/s are not impossible for well connected sites.
  +      * If we assume 100ms cross-country latency,
  +      * a 4kB buffer limits throughput to 40kB/s.
  +      *
  +      * To avoid this problem I've added the SendBufferSize directive
  +      * to allow the web master to configure send buffer size.
  +      *
  +      * The trade-off of larger buffers is that more kernel memory
  +      * is consumed.  YMMV, know your customers and your network!
  +      *
  +      * -John Heidemann <jo...@isi.edu> 25-Oct-96
  +      *
  +      * If no size is specified, use the kernel default.
  +      */
  +     if (server_conf->send_buffer_size) {
  +         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  +               (char *)&server_conf->send_buffer_size, sizeof(int)) < 0) {
  +             log_unixerr("setsockopt", "(SO_SNDBUF)",
  +                         "Failed to set SendBufferSize, using default",
  +                         server_conf);
  + 	    /* not a fatal error */
  + 	}
  +     }
  + 
  + #ifdef MPE
  + /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
  +     if (ntohs(server->sin_port) < 1024) GETPRIVMODE();
  + #endif
  +     if(bind(s, (struct sockaddr *)server,sizeof(struct sockaddr_in)) == -1)
  +     {
  +         perror("bind");
  + #ifdef MPE
  +         if (ntohs(server->sin_port) < 1024) GETUSERMODE();
  + #endif
  + 	if (server->sin_addr.s_addr != htonl(INADDR_ANY))
  + 	    fprintf(stderr,"httpd: could not bind to address %s port %d\n",
  + 		    inet_ntoa(server->sin_addr), ntohs(server->sin_port));
  + 	else
  + 	    fprintf(stderr,"httpd: could not bind to port %d\n",
  + 		    ntohs(server->sin_port));
  +         exit(1);
  +     }
  + #ifdef MPE
  +     if (ntohs(server->sin_port) < 1024) GETUSERMODE();
  + #endif
  +     listen(s, 512);
  +     return s;
  + }
  + 
  + static listen_rec *old_listeners;
  + 
  + static void copy_listeners(pool *p)
  +     {
  +     listen_rec *lr;
  + 
  +     assert(old_listeners == NULL);
  +     for(lr=listeners ; lr ; lr=lr->next)
  + 	{
  + 	listen_rec *nr=malloc(sizeof *nr);
  + 	if (nr == NULL) {
  + 	  fprintf (stderr, "Ouch!  malloc failed in copy_listeners()\n");
  + 	  exit (1);
  + 	}
  + 	*nr=*lr;
  + 	kill_cleanups_for_socket(p,nr->fd);
  + 	nr->next=old_listeners;
  + 	assert(!nr->used);
  + 	old_listeners=nr;
  + 	}
  +     }
  + 
  + static int find_listener(listen_rec *lr)
  +     {
  +     listen_rec *or;
  + 
  +     for(or=old_listeners ; or ; or=or->next)
  + 	if(!memcmp(&or->local_addr,&lr->local_addr,sizeof or->local_addr))
  + 	    {
  + 	    or->used=1;
  + 	    return or->fd;
  + 	    }
  +     return -1;
  +     }
  + 
  + static void close_unused_listeners()
  +     {
  +     listen_rec *or,*next;
  + 
  +     for(or=old_listeners ; or ; or=next)
  + 	{
  + 	next=or->next;
  + 	if(!or->used)
  + 	    closesocket(or->fd);
  + 	free(or);
  + 	}
  +     old_listeners=NULL;
  +     }
  + 
  + 
  + static int s_iInitCount = 0;
  + 
  + int
  + AMCSocketInitialize()
  + {
  + #ifdef WIN32
  +     int iVersionRequested;
  +     WSADATA wsaData;
  +     int err;
  +     
  +     if(s_iInitCount > 0)
  +     {
  +         s_iInitCount++;
  +         return(0);
  +     }
  +     else if(s_iInitCount < 0)
  +         return(s_iInitCount);
  + 
  +     /* s_iInitCount == 0. Do the initailization */
  +     iVersionRequested = MAKEWORD(1, 1);
  +     err = WSAStartup((WORD)iVersionRequested, &wsaData);
  +     if(err)
  +     {
  +         s_iInitCount = -1;
  +         return(s_iInitCount);
  +     }
  +     if ( LOBYTE( wsaData.wVersion ) != 1 || 
  +         HIBYTE( wsaData.wVersion ) != 1 )
  +     { 
  +         s_iInitCount = -2; 
  +         WSACleanup(); 
  +         return(s_iInitCount); 
  +     }
  + #else
  +     signal(SIGPIPE, SIG_IGN);
  + #endif /* WIN32 */
  + 
  +     s_iInitCount++;
  +     return(s_iInitCount);
  + 
  + }
  + 
  + 
  + void
  + AMCSocketCleanup()
  + {
  + #ifdef WIN32
  +     if(--s_iInitCount == 0)
  +         WSACleanup();
  + #else /* not WIN32 */
  +     s_iInitCount--;
  + #endif /* WIN32 */
  +     return;
  + }
  + 
  + #ifndef MULTITHREAD
    /*****************************************************************
     * Child process main loop.
     * The following vars are static to avoid getting clobbered by longjmp();
  ***************
  *** 1831,1837 ****
    	(void)update_child_status(child_num, SERVER_BUSY_READ,
    	                          (request_rec*)NULL);
    
  ! 	conn_io = bcreate(ptrans, B_RDWR);
    	dupped_csd = csd;
    #if defined(NEED_DUPPED_CSD)
    	if ((dupped_csd = dup(csd)) < 0) {
  --- 2190,2196 ----
    	(void)update_child_status(child_num, SERVER_BUSY_READ,
    	                          (request_rec*)NULL);
    
  ! 	conn_io = bcreate(ptrans, B_RDWR, 1);
    	dupped_csd = csd;
    #if defined(NEED_DUPPED_CSD)
    	if ((dupped_csd = dup(csd)) < 0) {
  ***************
  *** 1970,2110 ****
        return 0;
    }
    
  - static int make_sock(pool *pconf, const struct sockaddr_in *server)
  - {
  -     int s;
  -     int one = 1;
    
  !     if ((s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
  !         log_unixerr("socket", NULL, "Failed to get a socket, exiting child",
  !                     server_conf);
  !         exit(1);
  !     }
  ! 
  !     note_cleanups_for_fd(pconf, s); /* arrange to close on exec or restart */
  !     
  ! #ifndef MPE
  ! /* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
  !     if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) {
  !         log_unixerr("setsockopt", "(SO_REUSEADDR)", NULL, server_conf);
  !         exit(1);
  !     }
  !     one = 1;
  !     if (setsockopt(s, SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(int)) < 0) {
  !         log_unixerr("setsockopt", "(SO_KEEPALIVE)", NULL, server_conf);
  !         exit(1);
  !     }
  ! #endif
  ! 
  !     sock_disable_nagle(s);
  !     sock_enable_linger(s);
  !     
  !     /*
  !      * To send data over high bandwidth-delay connections at full
  !      * speed we must force the TCP window to open wide enough to keep the
  !      * pipe full.  The default window size on many systems
  !      * is only 4kB.  Cross-country WAN connections of 100ms
  !      * at 1Mb/s are not impossible for well connected sites.
  !      * If we assume 100ms cross-country latency,
  !      * a 4kB buffer limits throughput to 40kB/s.
  !      *
  !      * To avoid this problem I've added the SendBufferSize directive
  !      * to allow the web master to configure send buffer size.
  !      *
  !      * The trade-off of larger buffers is that more kernel memory
  !      * is consumed.  YMMV, know your customers and your network!
  !      *
  !      * -John Heidemann <jo...@isi.edu> 25-Oct-96
  !      *
  !      * If no size is specified, use the kernel default.
  !      */
  !     if (server_conf->send_buffer_size) {
  !         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  !               (char *)&server_conf->send_buffer_size, sizeof(int)) < 0) {
  !             log_unixerr("setsockopt", "(SO_SNDBUF)",
  !                         "Failed to set SendBufferSize, using default",
  !                         server_conf);
  ! 	    /* not a fatal error */
  ! 	}
  !     }
  ! 
  ! #ifdef MPE
  ! /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
  !     if (ntohs(server->sin_port) < 1024) GETPRIVMODE();
  ! #endif
  !     if(bind(s, (struct sockaddr *)server,sizeof(struct sockaddr_in)) == -1)
  !     {
  !         perror("bind");
  ! #ifdef MPE
  !         if (ntohs(server->sin_port) < 1024) GETUSERMODE();
  ! #endif
  ! 	if (server->sin_addr.s_addr != htonl(INADDR_ANY))
  ! 	    fprintf(stderr,"httpd: could not bind to address %s port %d\n",
  ! 		    inet_ntoa(server->sin_addr), ntohs(server->sin_port));
  ! 	else
  ! 	    fprintf(stderr,"httpd: could not bind to port %d\n",
  ! 		    ntohs(server->sin_port));
  !         exit(1);
  !     }
  ! #ifdef MPE
  !     if (ntohs(server->sin_port) < 1024) GETUSERMODE();
  ! #endif
  !     listen(s, 512);
  !     return s;
  ! }
  ! 
  ! static listen_rec *old_listeners;
  ! 
  ! static void copy_listeners(pool *p)
  !     {
  !     listen_rec *lr;
  ! 
  !     assert(old_listeners == NULL);
  !     for(lr=listeners ; lr ; lr=lr->next)
  ! 	{
  ! 	listen_rec *nr=malloc(sizeof *nr);
  ! 	if (nr == NULL) {
  ! 	  fprintf (stderr, "Ouch!  malloc failed in copy_listeners()\n");
  ! 	  exit (1);
  ! 	}
  ! 	*nr=*lr;
  ! 	kill_cleanups_for_fd(p,nr->fd);
  ! 	nr->next=old_listeners;
  ! 	assert(!nr->used);
  ! 	old_listeners=nr;
  ! 	}
  !     }
  ! 
  ! static int find_listener(listen_rec *lr)
  !     {
  !     listen_rec *or;
  ! 
  !     for(or=old_listeners ; or ; or=or->next)
  ! 	if(!memcmp(&or->local_addr,&lr->local_addr,sizeof or->local_addr))
  ! 	    {
  ! 	    or->used=1;
  ! 	    return or->fd;
  ! 	    }
  !     return -1;
  !     }
  ! 
  ! static void close_unused_listeners()
  !     {
  !     listen_rec *or,*next;
  ! 
  !     for(or=old_listeners ; or ; or=next)
  ! 	{
  ! 	next=or->next;
  ! 	if(!or->used)
  ! 	    close(or->fd);
  ! 	free(or);
  ! 	}
  !     old_listeners=NULL;
  !     }
  ! 
  ! /*****************************************************************
  !  * Executive routines.
  !  */
    
    void standalone_main(int argc, char **argv)
    {
  --- 2329,2338 ----
        return 0;
    }
    
    
  ! /*****************************************************************
  !  * Executive routines.
  !  */
    
    void standalone_main(int argc, char **argv)
    {
  ***************
  *** 2439,2445 ****
    	    exit(1);
    	}
    	server_conf->port =ntohs(((struct sockaddr_in *)&sa_server)->sin_port);
  ! 	cio = bcreate(ptrans, B_RDWR);
    #ifdef MPE
    /* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas
       HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).
  --- 2667,2673 ----
    	    exit(1);
    	}
    	server_conf->port =ntohs(((struct sockaddr_in *)&sa_server)->sin_port);
  ! 	cio = bcreate(ptrans, B_RDWR, 1);
    #ifdef MPE
    /* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas
       HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).
  ***************
  *** 2515,2518 ****
  --- 2743,3563 ----
    }
    #endif
    #endif
  + 
  + #else /* ndef MULTITHREAD */
  + 
  + 
  + 
  + 
  + typedef struct joblist_s
  + {
  +     struct joblist_s *next;
  +     int sock;
  + } joblist;
  + 
  + typedef struct globals_s
  + {
  +     int exit_now;
  +     semaphore *jobsemaphore;
  +     joblist *jobhead;
  +     joblist *jobtail;
  +     mutex *jobmutex;
  +     int jobcount;
  + } globals;
  + 
  + 
  + globals allowed_globals = { 0, NULL, NULL, NULL, 0 };
  + 
  + 
  + void
  + add_job(int sock)
  + {
  +     joblist *new_job;
  +     
  +     assert(allowed_globals.jobmutex);
  +     /* TODO: If too many jobs in queue, sleep, check for problems */
  +     acquire_mutex(allowed_globals.jobmutex);
  +     new_job = (joblist *)malloc(sizeof(joblist));
  +     new_job->next = NULL;
  +     new_job->sock = sock;
  +     if(allowed_globals.jobtail != NULL)
  +         allowed_globals.jobtail->next = new_job;
  +     allowed_globals.jobtail = new_job;
  +     if(!allowed_globals.jobhead)
  +         allowed_globals.jobhead = new_job;
  +     allowed_globals.jobcount++;
  +     release_semaphore(allowed_globals.jobsemaphore);
  +     release_mutex(allowed_globals.jobmutex);
  + }
  + 
  + int
  + remove_job()
  + {
  +     joblist *job;
  +     int sock;
  +     
  +     assert(allowed_globals.jobmutex);
  +     acquire_semaphore(allowed_globals.jobsemaphore);
  +     acquire_mutex(allowed_globals.jobmutex);
  +     if(allowed_globals.exit_now && !allowed_globals.jobhead)
  +     {
  +         release_mutex(allowed_globals.jobmutex);
  +         return(-1);
  +     }
  +     job = allowed_globals.jobhead;
  +     assert(job);
  +     allowed_globals.jobhead = job->next;
  +     if(allowed_globals.jobhead == NULL)
  +         allowed_globals.jobtail = NULL;
  +     release_mutex(allowed_globals.jobmutex);
  +     sock = job->sock;
  +     free(job);
  +     return(sock);
  + }
  + 
  + 
  + 
  + void child_sub_main(int child_num, int srv,
  +                     int csd, int dupped_csd,
  +                     int requests_this_child, pool *pchild)
  + {
  + #if defined(UW)
  +     size_t clen;
  + #else
  +     int clen;
  + #endif
  +     struct sockaddr sa_server;
  +     struct sockaddr sa_client;
  + 
  +     csd = -1;
  +     dupped_csd = -1;
  +     requests_this_child = 0;
  +     (void)update_child_status(child_num, SERVER_READY, (request_rec*)NULL);
  + 
  +     /*
  +      * Setup the jump buffers so that we can return here after
  +      * a signal or a timeout (yeah, I know, same thing).
  +      */
  + #if defined(USE_LONGJMP)
  +     setjmp(jmpbuffer);
  + #else
  +     sigsetjmp(jmpbuffer,1);
  + #endif
  + #ifdef SIGURG
  +     signal(SIGURG, timeout);
  + #endif
  +     
  + 
  +     pchild = make_sub_pool(NULL);
  + 
  +     while (1) {
  + 	BUFF *conn_io;
  + 	request_rec *r;
  +       
  +         /*
  +          * (Re)initialize this child to a pre-connection state.
  +          */
  + 
  +         set_callback_and_alarm(NULL, 0); /* Cancel any outstanding alarms. */
  +         timeout_req = NULL;	/* No request in progress */
  + 	current_conn = NULL;
  + #ifdef SIGPIPE
  +         signal(SIGPIPE, timeout);  
  + #endif
  +         
  + 	clear_pool (pchild);
  + 
  + 	(void)update_child_status(child_num, SERVER_READY, (request_rec*)NULL);
  + 
  +         csd = remove_job();
  +         if(csd == -1)
  +             break; /* time to exit */
  +         requests_this_child++;
  + 
  + 	note_cleanups_for_socket(pchild,csd);
  + 
  +         /*
  +          * We now have a connection, so set it up with the appropriate
  +          * socket options, file descriptors, and read/write buffers.
  +          */
  + 
  + 	clen = sizeof(sa_server);
  + 	if (getsockname(csd, &sa_server, &clen) < 0) {
  + 	    log_unixerr("getsockname", NULL, NULL, server_conf);
  + 	    continue;
  + 	}
  +         clen = sizeof(sa_client);
  + 	if ((getpeername(csd, &sa_client, &clen)) < 0)
  + 	{
  +             /* get peername will fail if the input isn't a socket */
  + 	    perror("getpeername");
  + 	    memset(&sa_client, '\0', sizeof(sa_client));
  + 	}
  + 
  + 	sock_disable_nagle(csd);
  + 
  + 	(void)update_child_status(child_num, SERVER_BUSY_READ,
  + 	                          (request_rec*)NULL);
  + 
  + 	conn_io = bcreate(pchild, B_RDWR, 1);
  + 	dupped_csd = csd;
  + #if defined(NEED_DUPPED_CSD)
  + 	if ((dupped_csd = dup(csd)) < 0) {
  + 	    log_unixerr("dup", NULL, "couldn't duplicate csd", server_conf);
  + 	    dupped_csd = csd;   /* Oh well... */
  + 	}
  + 	note_cleanups_for_socket(pchild,dupped_csd);
  + #endif
  + 	bpushfd(conn_io, csd, dupped_csd);
  + 
  + 	current_conn = new_connection (pchild, server_conf, conn_io,
  + 				       (struct sockaddr_in *)&sa_client,
  + 				       (struct sockaddr_in *)&sa_server,
  + 				       child_num);
  + 
  +         /*
  +          * Read and process each request found on our connection
  +          * until no requests are left or we decide to close.
  +          */
  + 
  +         while ((r = read_request(current_conn)) != NULL) {
  +             (void)update_child_status(child_num, SERVER_BUSY_WRITE, r);
  + 
  +             process_request(r);
  + #if defined(STATUS)
  +             increment_counts(child_num, r);
  + #endif
  +             if (!current_conn->keepalive || current_conn->aborted)
  +                 break;
  + 
  +             destroy_pool(r->pool);
  +             (void)update_child_status(child_num, SERVER_BUSY_KEEPALIVE,
  +                                       (request_rec*)NULL);
  + 
  +             sync_scoreboard_image();
  +         }
  + 
  +         /*
  +          * Close the connection, being careful to send out whatever is still
  +          * in our buffers.  If possible, try to avoid a hard close until the
  +          * client has ACKed our FIN and/or has stopped sending us data.
  +          */
  +         kill_cleanups_for_socket(pchild,csd);
  + 
  + #ifdef NO_LINGCLOSE
  +         bclose(conn_io);        /* just close it */
  + #else
  +         if (r &&  r->connection
  +             && !r->connection->aborted
  +             &&  r->connection->client
  +             && (r->connection->client->fd >= 0)) {
  + 
  +             lingering_close(r);
  +         }
  +         else {
  +             bsetflag(conn_io, B_EOUT, 1);
  +             bclose(conn_io);
  +         }
  + #endif
  +     }
  +     destroy_pool(pchild);
  +     (void)update_child_status(child_num,SERVER_DEAD, NULL);
  + }
  + 
  + 
  + void
  + child_main(int child_num_arg)
  + {
  +     
  +     int srv = 0;
  +     int csd = 0;
  +     int dupped_csd = 0;
  +     int requests_this_child = 0;
  +     pool *ppool = NULL;
  + 
  +     /*
  +      * Only reason for this function, is to pass in
  +      * arguments to child_sub_main() on its stack so
  +      * that longjump doesn't try to corrupt its local
  +      * variables and I don't need to make those
  +      * damn variables static/global
  +      */
  +     child_sub_main(child_num_arg, srv,
  +                         csd, dupped_csd,
  +                         requests_this_child, ppool);
  + 
  + }
  + 
  + 
  + 
  + void
  + cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
  + {
  +     int i;
  +     
  +     free_thread(handles[thread_to_clean]);
  +     for(i=thread_to_clean; i<((*thread_cnt)-1); i++)
  +         handles[i] = handles[i+1];
  +     (*thread_cnt)--;
  + }
  + 
  + /*****************************************************************
  +  * Executive routines.
  +  */
  + 
  + event *exit_event;
  + mutex *start_mutex;
  + 
  + void worker_main()
  + {
  +     /*
  +      * I am writing this stuff specifically for NT.
  +      * have pulled out a lot of the restart and
  +      * graceful restart stuff, because that is only
  +      * useful on Unix (not sure it even makes sense
  +      * in a multi-threaded env.
  +      */
  +     int saved_sd;
  +     int nthreads;
  +     fd_set main_fds;
  +     int srv;
  +     int clen;
  +     int csd;
  +     struct sockaddr_in sa_server;
  +     struct sockaddr_in sa_client;
  +     int total_jobs = 0;
  +     thread **child_handles;
  +     int rv;
  +     time_t end_time;
  +     int i;
  +     struct timeval tv;
  +     int wait_time = 100;
  +     int start_exit = 0;
  +     int count_down = 0;
  +     int start_mutex_released = 0;
  +     int max_jobs_per_exe;
  +     int max_jobs_after_exit_request;
  + 
  +     standalone = 1;
  +     sd = listenmaxfd = -1;
  +     nthreads = threads_per_child;
  +     max_jobs_after_exit_request = excess_requests_per_child;
  +     max_jobs_per_exe = max_requests_per_child;
  +     if(nthreads <= 0)
  +         nthreads = 40;
  +     if(max_jobs_per_exe <= 0)
  +         max_jobs_per_exe = 0;
  +     if(max_jobs_after_exit_request <= 0)
  +         max_jobs_after_exit_request = max_jobs_per_exe/10;
  +     
  +     if (!one_process) detach(); 
  +     
  +     ++generation;
  +   
  +     copy_listeners(pconf);
  +     saved_sd=sd;
  +     restart_time = time(NULL);
  + 
  +     reinit_scoreboard(pconf);
  +     default_server_hostnames (server_conf);
  + 
  +     acquire_mutex(start_mutex);
  +     {
  +         listenmaxfd = -1;
  + 	FD_ZERO(&listenfds);
  + 
  +         if (listeners == NULL) {
  + 	    memset((char *) &sa_server, 0, sizeof(sa_server));
  + 	    sa_server.sin_family=AF_INET;
  + 	    sa_server.sin_addr=bind_address;
  + 	    sa_server.sin_port=htons(server_conf->port);
  + 
  + 	    sd = make_sock(pconf, &sa_server);
  +             FD_SET(sd, &listenfds);
  +             listenmaxfd = sd;
  +         }
  +         else {
  + 	    listen_rec *lr;
  + 	    int fd;
  + 
  + 	    
  + 	    for (lr=listeners; lr != NULL; lr=lr->next)
  + 	    {
  + 	        fd=find_listener(lr);
  + 	        if(fd < 0)
  +                 {
  + 		    fd = make_sock(pconf, &lr->local_addr);
  +                 }
  + 	        FD_SET(fd, &listenfds);
  + 	        if (fd > listenmaxfd) listenmaxfd = fd;
  + 	        lr->fd=fd;
  + 	    }
  + 	    close_unused_listeners();
  + 	    sd = -1;
  +         }
  +     }
  + 
  +     set_signals();
  + 
  +     /*
  +      * - Initialize allowed_globals
  +      * - Create the thread table
  +      * - Spawn off threads
  +      * - Create listen socket set (done above)
  +      * - loop {
  +      *       wait for request
  +      *       create new job
  +      *   } while (!time to exit)
  +      * - Close all listeners
  +      * - Wait for all threads to complete
  +      * - Exit
  +      */
  + 
  +     allowed_globals.jobsemaphore = create_semaphore(0);
  +     allowed_globals.jobmutex = create_mutex(NULL);
  + 
  +     /* spawn off the threads */
  +     child_handles = (thread *)alloca(nthreads * sizeof(int));
  +     {
  +         int i;
  + 
  +         for(i=0; i<nthreads; i++)
  +         {
  +             child_handles[i] = create_thread((void (*)(void *))child_main, (void *)i);
  +         }
  +     }
  + 
  +     /* main loop */
  +     for(;;)
  +     {
  +         if(max_jobs_per_exe && (total_jobs > max_jobs_per_exe) && !start_exit)
  +         {
  +             start_exit = 1;
  +             wait_time = 1;
  +             count_down = max_jobs_after_exit_request;
  +             release_mutex(start_mutex);
  +             start_mutex_released = 1;
  +             /* set the listen queue to 1 */
  +             {
  +                 if (listeners == NULL) {
  + 	            listen(sd, 1);
  +                 }
  +                 else {
  + 	            listen_rec *lr;
  + 	            
  + 	            for (lr=listeners; lr != NULL; lr=lr->next)
  + 	            {
  + 	                if(lr->used)
  +                         {
  +                             listen(lr->fd, 1);
  +                         }
  + 	            }
  +                 }
  +             }
  +         }
  +         if(!start_exit)
  +         {
  +             rv = WaitForSingleObject(exit_event, 0);
  +             assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
  +             if(rv == WAIT_OBJECT_0)
  +                 break;
  +             rv = WaitForMultipleObjects(nthreads, child_handles, 0, 0);
  +             if(rv != WAIT_TIMEOUT)
  +             {
  +                 rv = rv - WAIT_OBJECT_0;
  +                 assert((rv >= 0) && (rv < nthreads));
  +                 cleanup_thread(child_handles, &nthreads, rv);
  +                 break;
  +             }
  +         }
  +         if(start_exit && max_jobs_after_exit_request && (count_down-- < 0))
  +             break;
  +         tv.tv_sec = wait_time;
  +         tv.tv_usec = 0;
  + 
  +         memcpy(&main_fds, &listenfds, sizeof(fd_set));
  + #ifdef SELECT_NEEDS_CAST
  +         srv = select(listenmaxfd+1, (int*)&main_fds, NULL, NULL, &tv);
  + #else
  +         srv = select(listenmaxfd+1, &main_fds, NULL, NULL, &tv);
  + #endif
  + #ifdef WIN32
  +         if(srv == SOCKET_ERROR)
  +             errno = WSAGetLastError() - WSABASEERR;
  + #endif /* WIN32 */
  + 
  +         if (srv < 0 && errno != EINTR)
  +             log_unixerr("select", "(listen)", NULL, server_conf);
  + 
  +         if (srv < 0)
  +             continue;
  +         if(srv == 0)
  +         {
  +             if(start_exit)
  +                 break;
  +             else
  +                 continue;
  +         }
  + 
  +         if (listeners != NULL) {
  + 	    listen_rec *lr;
  + 	    int fd;
  + 	    
  + 	    for (lr=listeners; lr != NULL; lr=lr->next)
  + 	    {
  + 	        if(!lr->used)
  +                     continue;
  +                 fd=lr->fd;
  + 	        
  + 	        FD_ISSET(fd, &listenfds);
  + 	        sd = fd;
  +                 break;
  + 	    }
  +         }
  + 
  +         do {
  +             clen = sizeof(sa_client);
  +             csd  = accept(sd, (struct sockaddr *)&sa_client, &clen);
  + #ifdef WIN32
  +             if(csd == SOCKET_ERROR)
  +             {
  +                 csd = -1;
  +                 errno = WSAGetLastError() - WSABASEERR;
  +             }
  + #endif /* WIN32 */
  +         } while (csd < 0 && errno == EINTR);
  + 
  +         if (csd < 0) {
  + 
  + #if defined(EPROTO) && defined(ECONNABORTED)
  +             if ((errno != EPROTO) && (errno != ECONNABORTED))
  + #elif defined(EPROTO)
  +                 if (errno != EPROTO)
  + #elif defined(ECONNABORTED)
  +                     if (errno != ECONNABORTED)
  + #endif
  +                         log_unixerr("accept", "(client socket)", NULL, server_conf);
  +         }
  +         else
  +         {
  +             add_job(csd);
  +             total_jobs++;
  +         }
  +     }
  + 
  +     /* Get ready to shutdown and exit */
  +     allowed_globals.exit_now = 1;
  +     if(!start_mutex_released)
  +     {
  +         release_mutex(start_mutex);
  +     }
  +             
  +     {
  +         if (listeners == NULL) {
  + 	    closesocket(sd);
  +         }
  +         else {
  + 	    listen_rec *lr;
  + 	    
  + 	    for (lr=listeners; lr != NULL; lr=lr->next)
  + 	    {
  + 	        if(lr->used)
  +                 {
  +                     closesocket(lr->fd);
  +                     lr->fd = -1;
  +                 }
  + 	    }
  +         }
  +     }
  + 
  +     for(i=0; i<nthreads; i++)
  +     {
  +         add_job(-1);
  +     }
  + 
  +     /* Wait for all your children */
  +     end_time = time(NULL) + 180;
  +     while(nthreads)
  +     {
  +         rv = WaitForMultipleObjects(nthreads, child_handles, 0, (end_time-time(NULL))*1000);
  +         if(rv != WAIT_TIMEOUT)
  +         {
  +             rv = rv - WAIT_OBJECT_0;
  +             assert((rv >= 0) && (rv < nthreads));
  +             cleanup_thread(child_handles, &nthreads, rv);
  +             continue;
  +         }
  +         break;
  +     }
  + 
  +     for(i=0; i<nthreads; i++)
  +     {
  +         kill_thread(child_handles[i]);
  +         free_thread(child_handles[i]);
  +     }
  +     destroy_semaphore(allowed_globals.jobsemaphore);
  +     destroy_mutex(allowed_globals.jobmutex);
  +     cleanup_scoreboard();
  +     exit(0);
  + 
  + 
  + } /* standalone_main */
  + 
  + 
  + int
  + create_event_and_spawn(int argc, char **argv, event **ev, int *child_num, char* prefix)
  + {
  +     int pid = getpid();
  +     char buf[40], mod[200];
  +     int i, rv;
  +     char **pass_argv = (char **)alloca(sizeof(char *)*(argc+3));
  + 
  +     sprintf(buf, "%s_%d", prefix, ++(*child_num));
  +     _flushall();
  +     *ev = create_event(0, 0, buf);
  +     assert(*ev);
  +     pass_argv[0] = argv[0];
  +     pass_argv[1] = "-c";
  +     pass_argv[2] = buf;
  +     for(i=1; i<argc; i++)
  +     {
  +         pass_argv[i+2] = argv[i];
  +     }
  +     pass_argv[argc+2] = NULL;
  + 
  + 
  +     GetModuleFileName(NULL, mod, 200);
  +     rv = spawnv(_P_NOWAIT, mod, pass_argv);
  + 
  +     return(rv);
  + }
  + 
  + 
  + static int service_pause = 0;
  + static int service_stop = 0;
  + 
  + 
  + int
  + master_main(int argc, char **argv)
  + {
  +     /*
  +      * 1. Create exit events for children
  +      * 2. Spawn children
  +      * 3. Wait for either of your children to die
  +      * 4. Close hand to dead child & its event
  +      * 5. Respawn that child
  +      */
  + 
  +     int nchild = daemons_to_start;
  +     event **ev;
  +     int *child;
  +     int child_num = 0;
  +     int rv, cld;
  +     char buf[100];
  +     int i;
  +     time_t tmstart;
  + 
  +     sprintf(buf, "Apache%d", getpid());
  +     start_mutex = create_mutex(buf);
  +     ev = (event **)alloca(sizeof(event *)*nchild);
  +     child = (int *)alloca(sizeof(int)*nchild);
  +     for(i=0; i<nchild; i++)
  +     {
  +         service_set_status(SERVICE_START_PENDING);
  +         child[i] = create_event_and_spawn(argc, argv, &ev[i], &child_num, buf);
  +         assert(child[i]);
  +     }
  +     service_set_status(SERVICE_RUNNING);
  + 
  +     for(;!service_stop;)
  +     {
  +         rv = WaitForMultipleObjects(nchild, (HANDLE *)child, FALSE, 2000);
  +         assert(rv != WAIT_FAILED);
  +         if(rv == WAIT_TIMEOUT)
  +             continue;
  +         cld = rv - WAIT_OBJECT_0;
  +         assert(rv < nchild);
  +         CloseHandle((HANDLE)child[rv]);
  +         CloseHandle(ev[rv]);
  +         child[rv] = create_event_and_spawn(argc, argv, &ev[rv], &child_num, buf);
  +         assert(child[rv]);
  +     }
  + 
  +     /*
  +      * Tell all your kids to stop. Wait for them for some time
  +      * Kill those that haven't yet stopped
  +      */
  +     for(i=0; i<nchild; i++)
  +     {
  +         SetEvent(ev[i]);
  +     }
  + 
  +     for(tmstart=time(NULL); nchild && (tmstart < (time(NULL) + 60));)
  +     {
  +         service_set_status(SERVICE_STOP_PENDING);
  +         rv = WaitForMultipleObjects(nchild, (HANDLE *)child, FALSE, 2000);
  +         assert(rv != WAIT_FAILED);
  +         if(rv == WAIT_TIMEOUT)
  +             continue;
  +         cld = rv - WAIT_OBJECT_0;
  +         assert(rv < nchild);
  +         CloseHandle((HANDLE)child[rv]);
  +         CloseHandle(ev[rv]);
  +         for(i=rv; i<(nchild-1); i++)
  +         {
  +             child[i] = child[i+1];
  +             ev[i] = ev[i+1];
  +         }
  +         nchild--;
  +     }
  +     for(i=0; i<nchild; i++)
  +     {
  +         TerminateProcess((HANDLE)child[i], 1);
  +     }
  +     service_set_status(SERVICE_STOPPED);          
  + 
  + 
  +     destroy_mutex(start_mutex);
  +     return(0);
  + }
  + 
  + 
  + 
  + 
  + 
  + 
  + int
  + main(int argc, char *argv[])
  + {
  +     int c;
  +     int child = 0;
  +     char *cp;
  +     int run_as_service = 1;
  +     int install = 0;
  + 
  + #ifdef AUX
  +     (void)set42sig();
  + #endif
  + 
  + #ifdef SecureWare
  +     if(set_auth_parameters(argc,argv) < 0)
  +     	perror("set_auth_parameters");
  +     if(getluid() < 0)
  + 	if(setluid(getuid()) < 0)
  + 	    perror("setluid");
  +     if(setreuid(0, 0) < 0)
  + 	perror("setreuid");
  + #endif
  + 
  + #ifdef WIN32
  +     /* Initialize the stupid sockets */
  +     AMCSocketInitialize();
  + #endif /* WIN32 */
  + 
  +     init_alloc();
  +     pconf = permanent_pool;
  +     ptrans = make_sub_pool(pconf);
  + 
  +     server_argv0 = argv[0];
  +     strncpy (server_root, HTTPD_ROOT, sizeof(server_root)-1);
  +     server_root[sizeof(server_root)-1] = '\0';
  +     strncpy (server_confname, SERVER_CONFIG_FILE, sizeof(server_root)-1);
  +     server_confname[sizeof(server_confname)-1] = '\0';
  + 
  +     while((c = getopt(argc,argv,"Xd:f:vhlc:ius")) != -1) {
  +         switch(c) {
  + #ifdef WIN32
  +         case 'c':
  +             exit_event = open_event(optarg);
  +             cp = strchr(optarg, '_');
  +             assert(cp);
  +             *cp = 0;
  +             start_mutex = open_mutex(optarg);
  +             child = 1;
  +             break;
  +         case 'i':
  +             install = 1;
  +             break;
  +         case 'u':
  +             install = -1;
  +             break;
  +         case 's':
  +             run_as_service = 0;
  +             break;
  + #endif /* WIN32 */
  +           case 'd':
  +             strncpy (server_root, optarg, sizeof(server_root)-1);
  +             server_root[sizeof(server_root)-1] = '\0';
  +             break;
  +           case 'f':
  +             strncpy (server_confname, optarg, sizeof(server_confname)-1);
  +             server_confname[sizeof(server_confname)-1] = '\0';
  +             break;
  +           case 'v':
  +             printf("Server version %s.\n",SERVER_VERSION);
  +             exit(0);
  +           case 'h':
  + 	    show_directives();
  + 	    exit(0);
  + 	  case 'l':
  + 	    show_modules();
  + 	    exit(0);
  + 	  case 'X':
  + 	    ++one_process;	/* Weird debugging mode. */
  + 	    break;
  +           case '?':
  +             usage(argv[0]);
  +         }
  +     }
  + 
  + #ifdef __EMX__
  +     printf("%s \n",SERVER_VERSION);
  +     printf("OS/2 port by Garey Smiley <ga...@slink.com> \n");
  + #endif
  + #ifdef WIN32
  +     if(!child)
  +     {
  +         printf("%s \n",SERVER_VERSION);
  +         printf("WIN32 port by Ambarish Malpani <am...@valicert.com> and the Apache Group.\n");
  +     }
  + #endif
  +     if(!child && run_as_service)
  +     {
  +         service_cd();
  +     }
  +     setup_prelinked_modules();
  + 
  +     server_conf = read_config (pconf, ptrans, server_confname);
  +     suexec_enabled = init_suexec();
  +     open_logs(server_conf, pconf);
  +     set_group_privs();
  + 
  +     if(one_process && !exit_event)
  +         exit_event = create_event(0, 0, NULL);
  +     if(one_process && !start_mutex)
  +         start_mutex = create_mutex(NULL);
  +     /*
  +      * In the future, the main will spawn off a couple
  +      * of children and monitor them. As soon as a child
  +      * exits, it spawns off a new one
  +      */
  +     if(child || one_process)
  +     {
  +         if(!exit_event || !start_mutex)
  +             exit(-1);
  +         worker_main();
  +         destroy_mutex(start_mutex);
  +         destroy_event(exit_event);
  +     }
  +     else
  +     {
  +         service_main(master_main, argc, argv,
  +                 &service_pause, &service_stop, "Apache", install, run_as_service);
  +     }    
  + 
  +     return(0);
  + }
  + 
  + 
  + #endif /* ndef MULTITHREAD */
    
  
  
  
  1.11      +2 -0      apache/src/http_main.h
  
  Index: http_main.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.h,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -C3 -r1.10 -r1.11
  *** http_main.h	1997/04/26 20:20:06	1.10
  --- http_main.h	1997/06/15 19:22:26	1.11
  ***************
  *** 97,99 ****
  --- 97,101 ----
    int count_busy_servers ();
    int count_idle_servers ();
    
  + unsigned int set_callback_and_alarm(void (*fn)(int), int x);
  + int check_alarm();
  
  
  
  1.127     +5 -3      apache/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.c,v
  retrieving revision 1.126
  retrieving revision 1.127
  diff -C3 -r1.126 -r1.127
  *** http_protocol.c	1997/05/29 03:44:31	1.126
  --- http_protocol.c	1997/06/15 19:22:27	1.127
  ***************
  *** 503,509 ****
    {
        const char *s;
    
  ! #ifdef __EMX__
        /* Variable for OS/2 fix below. */
        int loop;
    #endif
  --- 503,509 ----
    {
        const char *s;
    
  ! #if defined(__EMX__) || defined(WIN32)
        /* Variable for OS/2 fix below. */
        int loop;
    #endif
  ***************
  *** 527,533 ****
    	r->proxyreq = 0;
    	r->uri = getword (r->pool, &uri, '?');
    
  ! #ifdef __EMX__
        /* Handle path translations for OS/2 and plug security hole. */
        /* This will prevent "http://www.wherever.com/..\..\/" from
           returning a directory for the root drive. */
  --- 527,533 ----
    	r->proxyreq = 0;
    	r->uri = getword (r->pool, &uri, '?');
    
  ! #if defined(__EMX__) || defined(WIN32)
        /* Handle path translations for OS/2 and plug security hole. */
        /* This will prevent "http://www.wherever.com/..\..\/" from
           returning a directory for the root drive. */
  ***************
  *** 627,633 ****
  --- 627,635 ----
    	}
        }
        /* we've probably got something to do, ignore graceful restart requests */
  + #ifdef SIGUSR1
        signal (SIGUSR1, SIG_IGN);
  + #endif /* SIGUSR1 */
        bsetflag( conn->client, B_SAFEREAD, 0 );
        if (len == (HUGE_STRING_LEN - 1)) {
            log_printf(r->server, "request failed for %s, reason: URI too long",
  ***************
  *** 1209,1215 ****
                              "byteranges; boundary=", r->boundary, NULL));
        else if (r->content_type)
            table_set(r->headers_out, "Content-Type", r->content_type);
  !     else 
            table_set(r->headers_out, "Content-Type", default_type(r));
        
        if (r->content_encoding)
  --- 1211,1217 ----
                              "byteranges; boundary=", r->boundary, NULL));
        else if (r->content_type)
            table_set(r->headers_out, "Content-Type", r->content_type);
  !     else
            table_set(r->headers_out, "Content-Type", default_type(r));
        
        if (r->content_encoding)
  
  
  
  1.51      +8 -8      apache/src/http_request.c
  
  Index: http_request.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_request.c,v
  retrieving revision 1.50
  retrieving revision 1.51
  diff -C3 -r1.50 -r1.51
  *** http_request.c	1997/05/14 19:22:52	1.50
  --- http_request.c	1997/06/15 19:22:27	1.51
  ***************
  *** 86,100 ****
     */
    
    int check_symlinks (char *d, int opts)
  ! {
  !     struct stat lfi, fi;
  !     char *lastp;
  !     int res;
  !   
  ! #ifdef __EMX__
        /* OS/2 dosen't have symlinks */
        return OK;
    #else
      
        if (opts & OPT_SYM_LINKS) return OK;
    
  --- 86,100 ----
     */
    
    int check_symlinks (char *d, int opts)
  ! { 
  ! #if defined(__EMX__) || defined(WIN32)
        /* OS/2 dosen't have symlinks */
        return OK;
    #else
  +     struct stat lfi, fi;
  +     char *lastp;
  +     int res;
  +  
      
        if (opts & OPT_SYM_LINKS) return OK;
    
  ***************
  *** 259,265 ****
         * for the moment, that's not worth the trouble.
         */
    
  ! #ifdef __EMX__
        /* Add OS/2 drive name support */
        if ((test_filename[0] != '/') && (test_filename[1] != ':'))
    #else
  --- 259,265 ----
         * for the moment, that's not worth the trouble.
         */
    
  ! #if defined(__EMX__) || defined(WIN32)
        /* Add OS/2 drive name support */
        if ((test_filename[0] != '/') && (test_filename[1] != ':'))
    #else
  ***************
  *** 763,769 ****
        }
           
        r->status = type;
  ! 
        /* Two types of custom redirects --- plain text, and URLs.
         * Plain text has a leading '"', so the URL code, here, is triggered
         * on its absence
  --- 763,769 ----
        }
           
        r->status = type;
  !     
        /* Two types of custom redirects --- plain text, and URLs.
         * Plain text has a leading '"', so the URL code, here, is triggered
         * on its absence
  
  
  
  1.113     +4 -1      apache/src/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/httpd.h,v
  retrieving revision 1.112
  retrieving revision 1.113
  diff -C3 -r1.112 -r1.113
  *** httpd.h	1997/06/06 13:51:10	1.112
  --- httpd.h	1997/06/15 19:22:28	1.113
  ***************
  *** 171,177 ****
    
    /* The path to the Bourne shell, for parsed docs */
    #ifndef SHELL_PATH
  ! #ifdef __EMX__
    /* Set default for OS/2 file system */ 
    #define SHELL_PATH "CMD.EXE"
    #else
  --- 171,177 ----
    
    /* The path to the Bourne shell, for parsed docs */
    #ifndef SHELL_PATH
  ! #if defined(__EMX__) || defined(WIN32)
    /* Set default for OS/2 file system */ 
    #define SHELL_PATH "CMD.EXE"
    #else
  ***************
  *** 236,241 ****
  --- 236,244 ----
     */
    
    #define DEFAULT_MAX_REQUESTS_PER_CHILD 0
  + 
  + #define DEFAULT_THREADS_PER_CHILD 50
  + #define DEFAULT_EXCESS_REQUESTS_PER_CHILD 0
    
    /* If you have altered Apache and wish to change the SERVER_VERSION
     * identifier below, please keep to the HTTP specification.  This states that
  
  
  
  1.16      +1 -1      apache/src/mod_alias.c
  
  Index: mod_alias.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_alias.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -C3 -r1.15 -r1.16
  *** mod_alias.c	1997/04/14 01:09:13	1.15
  --- mod_alias.c	1997/06/15 19:22:28	1.16
  ***************
  *** 263,269 ****
        char *ret;
        int status;
    
  ! #ifdef __EMX__
        /* Add support for OS/2 drive names */
        if ((r->uri[0] != '/' && r->uri[0] != '\0') && r->uri[1] != ':')
    #else    
  --- 263,269 ----
        char *ret;
        int status;
    
  ! #if defined(__EMX__) || defined(WIN32)
        /* Add support for OS/2 drive names */
        if ((r->uri[0] != '/' && r->uri[0] != '\0') && r->uri[1] != ':')
    #else    
  
  
  
  1.40      +16 -7     apache/src/mod_cgi.c
  
  Index: mod_cgi.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -C3 -r1.39 -r1.40
  *** mod_cgi.c	1997/04/21 20:29:09	1.39
  --- mod_cgi.c	1997/06/15 19:22:28	1.40
  ***************
  *** 272,283 ****
        char *argv0;
    };
    
  ! void cgi_child (void *child_stuff)
    {
        struct cgi_child_stuff *cld = (struct cgi_child_stuff *)child_stuff;
        request_rec *r = cld->r;
        char *argv0 = cld->argv0;
        int nph = cld->nph;
    
    #ifdef DEBUG_CGI    
    #ifdef __EMX__
  --- 272,284 ----
        char *argv0;
    };
    
  ! static int cgi_child (void *child_stuff)
    {
        struct cgi_child_stuff *cld = (struct cgi_child_stuff *)child_stuff;
        request_rec *r = cld->r;
        char *argv0 = cld->argv0;
        int nph = cld->nph;
  +     int child_pid;
    
    #ifdef DEBUG_CGI    
    #ifdef __EMX__
  ***************
  *** 309,315 ****
        if (!cld->debug)
          error_log2stderr (r->server);
    
  ! #ifndef __EMX__
        if (nph) client_to_stdout (r->connection);
    #endif    
    
  --- 310,316 ----
        if (!cld->debug)
          error_log2stderr (r->server);
    
  ! #if !defined(__EMX__) && !defined(WIN32)
        if (nph) client_to_stdout (r->connection);
    #endif    
    
  ***************
  *** 319,325 ****
        
        cleanup_for_exec();
        
  !     call_exec(r, argv0, env, 0);
    
        /* Uh oh.  Still here.  Where's the kaboom?  There was supposed to be an
         * EARTH-shattering kaboom!
  --- 320,329 ----
        
        cleanup_for_exec();
        
  !     child_pid = call_exec(r, argv0, env, 0);
  ! #ifdef WIN32
  !     return(child_pid);
  ! #else
    
        /* Uh oh.  Still here.  Where's the kaboom?  There was supposed to be an
         * EARTH-shattering kaboom!
  ***************
  *** 336,341 ****
  --- 340,348 ----
    	    "exec of %s failed, errno is %d\n", r->filename, errno);
        write(2, err_string, strlen(err_string));
        exit(0);
  +     /* NOT REACHED */
  +     return(0);
  + #endif
    }
    
    int cgi_handler (request_rec *r)
  ***************
  *** 375,381 ****
        if (S_ISDIR(r->finfo.st_mode))
    	return log_scripterror(r, conf, FORBIDDEN,
    			       "attempt to invoke directory as script");
  ! #ifdef __EMX__
        /* Allow for cgi files without the .EXE extension on them under OS/2 */
        if (r->finfo.st_mode == 0) {
            struct stat statbuf;
  --- 382,388 ----
        if (S_ISDIR(r->finfo.st_mode))
    	return log_scripterror(r, conf, FORBIDDEN,
    			       "attempt to invoke directory as script");
  ! #if defined(__EMX__) || defined(WIN32)
        /* Allow for cgi files without the .EXE extension on them under OS/2 */
        if (r->finfo.st_mode == 0) {
            struct stat statbuf;
  ***************
  *** 414,420 ****
    	  spawn_child_err (r->main ? r->main->pool : r->pool, cgi_child,
    			    (void *)&cld,
    			   nph ? just_wait : kill_after_timeout,
  ! #ifdef __EMX__
    			   &script_out, &script_in, &script_err))) {
    #else
    			   &script_out, nph ? NULL : &script_in,
  --- 421,427 ----
    	  spawn_child_err (r->main ? r->main->pool : r->pool, cgi_child,
    			    (void *)&cld,
    			   nph ? just_wait : kill_after_timeout,
  ! #if defined(__EMX__) || defined(WIN32)
    			   &script_out, &script_in, &script_err))) {
    #else
    			   &script_out, nph ? NULL : &script_in,
  ***************
  *** 434,440 ****
         */
        
         if (should_client_block(r)) {
  !         void (*handler)();
    	int dbsize, len_read;
    
    	if (conf->logname) {
  --- 441,447 ----
         */
        
         if (should_client_block(r)) {
  !         void (*handler)(int);
    	int dbsize, len_read;
    
    	if (conf->logname) {
  ***************
  *** 443,449 ****
  --- 450,458 ----
    	}
    
            hard_timeout ("copy script args", r);
  + #ifdef SIGPIPE
            handler = signal (SIGPIPE, SIG_IGN);
  + #endif
        
    	while ((len_read =
                    get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0)
  ***************
  *** 536,542 ****
        }
    
        if (nph) {
  ! #ifdef __EMX__
            while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in) != NULL) {
                bputs(argsbuffer, r->connection->client);
            }
  --- 545,551 ----
        }
    
        if (nph) {
  ! #if defined(__EMX__) || defined(WIN32)
            while (fgets(argsbuffer, HUGE_STRING_LEN-1, script_in) != NULL) {
                bputs(argsbuffer, r->connection->client);
            }
  
  
  
  1.27      +4 -0      apache/src/mod_dir.c
  
  Index: mod_dir.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_dir.c,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -C3 -r1.26 -r1.27
  *** mod_dir.c	1997/05/13 04:01:50	1.26
  --- mod_dir.c	1997/06/15 19:22:29	1.27
  ***************
  *** 68,73 ****
  --- 68,77 ----
    #include "http_main.h"
    #include "util_script.h"
    
  + #ifdef WIN32
  + #include "nt/readdir.h"
  + #endif
  + 
    module dir_module;
    
    /****************************************************************
  
  
  
  1.34      +15 -5     apache/src/mod_include.c
  
  Index: mod_include.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_include.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -C3 -r1.33 -r1.34
  *** mod_include.c	1997/06/05 00:57:45	1.33
  --- mod_include.c	1997/06/15 19:22:29	1.34
  ***************
  *** 104,110 ****
  --- 104,112 ----
    
    void add_include_vars(request_rec *r, char *timefmt)
    {
  + #ifndef WIN32
        struct passwd *pw;
  + #endif /* ndef WIN32 */
        table *e = r->subprocess_env;
        char *t;
        time_t date = r->request_time;
  ***************
  *** 114,119 ****
  --- 116,122 ----
        table_set(e, "LAST_MODIFIED",ht_time(r->pool,r->finfo.st_mtime,timefmt,0));
        table_set(e, "DOCUMENT_URI", r->uri);
        table_set(e, "DOCUMENT_PATH_INFO", r->path_info);
  + #ifndef WIN32
        pw = getpwuid(r->finfo.st_uid);
        if (pw) {
          table_set(e, "USER_NAME", pw->pw_name);
  ***************
  *** 122,127 ****
  --- 125,131 ----
          ap_snprintf(uid, sizeof(uid), "user#%lu", (unsigned long)r->finfo.st_uid);
          table_set(e, "USER_NAME", uid);
        }
  + #endif /* ndef WIN32 */
    
        if((t = strrchr(r->filename, '/')))
            table_set (e, "DOCUMENT_NAME", ++t);
  ***************
  *** 590,600 ****
        char *s;
    } include_cmd_arg;
    
  ! void include_cmd_child (void *arg)
    {
        request_rec *r =  ((include_cmd_arg *)arg)->r;
        char *s = ((include_cmd_arg *)arg)->s;
        table *env = r->subprocess_env;
    #ifdef DEBUG_INCLUDE_CMD    
        FILE *dbg = fopen ("/dev/tty", "w");
    #endif    
  --- 594,605 ----
        char *s;
    } include_cmd_arg;
    
  ! int include_cmd_child (void *arg)
    {
        request_rec *r =  ((include_cmd_arg *)arg)->r;
        char *s = ((include_cmd_arg *)arg)->s;
        table *env = r->subprocess_env;
  +     int child_pid = 0;
    #ifdef DEBUG_INCLUDE_CMD    
        FILE *dbg = fopen ("/dev/tty", "w");
    #endif    
  ***************
  *** 636,643 ****
    #endif    
        cleanup_for_exec();
        /* set shellcmd flag to pass arg to SHELL_PATH */
  !     call_exec(r, s, create_environment (r->pool, env), 1);
  !     
        /* Oh, drat.  We're still here.  The log file descriptors are closed,
         * so we have to whimper a complaint onto stderr...
         */
  --- 641,650 ----
    #endif    
        cleanup_for_exec();
        /* set shellcmd flag to pass arg to SHELL_PATH */
  !     child_pid = call_exec(r, s, create_environment (r->pool, env), 1);
  ! #ifdef WIN32
  !     return(child_pid);
  ! #else    
        /* Oh, drat.  We're still here.  The log file descriptors are closed,
         * so we have to whimper a complaint onto stderr...
         */
  ***************
  *** 650,655 ****
  --- 657,665 ----
    	SHELL_PATH,errno);
        write (2, err_string, strlen(err_string));
        exit(0);
  +     /* NOT REACHED */
  +     return(child_pid);
  + #endif /* WIN32 */
    }
    
    int include_cmd(char *s, request_rec *r) {
  ***************
  *** 1799,1805 ****
        }
    
        if (*state == xbithack_full
  ! #ifndef __EMX__    
        /*  OS/2 dosen't support Groups. */
    	&& (r->finfo.st_mode & S_IXGRP)
    #endif
  --- 1809,1815 ----
        }
    
        if (*state == xbithack_full
  ! #if !defined(__EMX__) && !defined(WIN32)
        /*  OS/2 dosen't support Groups. */
    	&& (r->finfo.st_mode & S_IXGRP)
    #endif
  ***************
  *** 1845,1851 ****
    {
        enum xbithack *state;
    	
  ! #ifdef __EMX__
        /* OS/2 dosen't currently support the xbithack. This is being worked on. */
        return DECLINED;
    #else
  --- 1855,1861 ----
    {
        enum xbithack *state;
    	
  ! #if defined(__EMX__) || defined(WIN32)
        /* OS/2 dosen't currently support the xbithack. This is being worked on. */
        return DECLINED;
    #else
  
  
  
  1.17      +5 -0      apache/src/mod_info.c
  
  Index: mod_info.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_info.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -C3 -r1.16 -r1.17
  *** mod_info.c	1997/04/12 04:24:59	1.16
  --- mod_info.c	1997/06/15 19:22:30	1.17
  ***************
  *** 76,81 ****
  --- 76,82 ----
    #include "http_main.h"
    #include "http_protocol.h"
    #include "util_script.h"
  + #include "http_conf_globals.h"
    
    typedef struct mod_info_config_lines {
    	char *cmd;
  ***************
  *** 318,323 ****
  --- 319,328 ----
    			rputs(buf,r);
    			ap_snprintf(buf, sizeof(buf), "<strong>Max Requests:</strong> <tt>per child: %d &nbsp;&nbsp; keep alive: %s &nbsp;&nbsp; max per connection: %d</tt><br>\n",max_requests_per_child,serv->keep_alive ? "on":"off", serv->keep_alive_max);
    			rputs(buf,r);
  +                         ap_snprintf(buf, sizeof(buf), "<strong>Threads:</strong> <tt>per child: %d &nbsp;&nbsp; </tt><br>\n",threads_per_child);
  + 			rputs(buf,r);
  +                         ap_snprintf(buf, sizeof(buf), "<strong>Excess requests:</strong> <tt>per child: %d &nbsp;&nbsp; </tt><br>\n",excess_requests_per_child);
  + 			rputs(buf,r);                        
    			ap_snprintf(buf, sizeof(buf), "<strong>Timeouts:</strong> <tt>connection: %d &nbsp;&nbsp; keep-alive: %d</tt><br>",serv->timeout,serv->keep_alive_timeout);
    			rputs(buf,r);
    			ap_snprintf(buf, sizeof(buf), "<strong>Server Root:</strong> <tt>%s</tt><br>\n",server_root);
  
  
  
  1.12      +8 -3      apache/src/mod_log_agent.c
  
  Index: mod_log_agent.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_log_agent.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -C3 -r1.11 -r1.12
  *** mod_log_agent.c	1997/03/22 23:51:02	1.11
  --- mod_log_agent.c	1997/06/15 19:22:30	1.12
  ***************
  *** 96,111 ****
    { NULL }
    };
    
  ! void agent_log_child (void *cmd)
    {
        /* Child process code for 'AgentLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     
        cleanup_for_exec();
        signal (SIGHUP, SIG_IGN);
  ! #ifdef __EMX__    
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else    
  --- 96,115 ----
    { NULL }
    };
    
  ! static int agent_log_child (void *cmd)
    {
        /* Child process code for 'AgentLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     int child_pid = 0;
  ! 
        cleanup_for_exec();
        signal (SIGHUP, SIG_IGN);
  ! #if defined(WIN32)
  !     child_pid = spawnl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  !     return(child_pid);
  ! #elif defined(__EMX__)    
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else    
  ***************
  *** 114,119 ****
  --- 118,124 ----
        perror ("exec");
        fprintf (stderr, "Exec of shell for logging failed!!!\n");
        exit (1);
  +     return(child_pid);
    }
    
    void open_agent_log (server_rec *s, pool *p)
  
  
  
  1.29      +11 -4     apache/src/mod_log_config.c
  
  Index: mod_log_config.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_log_config.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -C3 -r1.28 -r1.29
  *** mod_log_config.c	1997/05/04 20:47:47	1.28
  --- mod_log_config.c	1997/06/15 19:22:30	1.29
  ***************
  *** 165,171 ****
    module config_log_module;
    
    static int xfer_flags = ( O_WRONLY | O_APPEND | O_CREAT );
  ! #ifdef __EMX__
    /* OS/2 dosen't support users and groups */
    static mode_t xfer_mode = ( S_IREAD | S_IWRITE );
    #else
  --- 165,171 ----
    module config_log_module;
    
    static int xfer_flags = ( O_WRONLY | O_APPEND | O_CREAT );
  ! #if defined(__EMX__) || defined(WIN32)
    /* OS/2 dosen't support users and groups */
    static mode_t xfer_mode = ( S_IREAD | S_IWRITE );
    #else
  ***************
  *** 673,688 ****
    { NULL }
    };
    
  ! void config_log_child (void *cmd)
    {
        /* Child process code for 'TransferLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     
        cleanup_for_exec();
        signal (SIGHUP, SIG_IGN);
  ! #ifdef __EMX__
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
  --- 673,694 ----
    { NULL }
    };
    
  ! static int config_log_child (void *cmd)
    {
        /* Child process code for 'TransferLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     int child_pid = 0;
  ! 
        cleanup_for_exec();
  + #ifdef SIGHUP
        signal (SIGHUP, SIG_IGN);
  ! #endif
  ! #if defined(WIN32)
  !     child_pid = spawnl (_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  !     return(child_pid);
  ! #elif defined(__EMX__)
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
  ***************
  *** 691,696 ****
  --- 697,703 ----
        perror ("exec");
        fprintf (stderr, "Exec of shell for logging failed!!!\n");
        exit (1);
  +     return(child_pid);
    }
    
    config_log_state *open_config_log (server_rec *s, pool *p,
  
  
  
  1.12      +9 -3      apache/src/mod_log_referer.c
  
  Index: mod_log_referer.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_log_referer.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -C3 -r1.11 -r1.12
  *** mod_log_referer.c	1997/03/22 23:51:03	1.11
  --- mod_log_referer.c	1997/06/15 19:22:30	1.12
  ***************
  *** 110,125 ****
    { NULL }
    };
    
  ! void referer_log_child (void *cmd)
    {
        /* Child process code for 'RefererLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     
        cleanup_for_exec();
        signal (SIGHUP, SIG_IGN);
  ! #ifdef __EMX__
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
  --- 110,130 ----
    { NULL }
    };
    
  ! static int referer_log_child (void *cmd)
    {
        /* Child process code for 'RefererLog "|..."';
         * may want a common framework for this, since I expect it will
         * be common for other foo-loggers to want this sort of thing...
         */
  !     int child_pid = 0;
  ! 
        cleanup_for_exec();
        signal (SIGHUP, SIG_IGN);
  ! #if defined(WIN32)
  !     /* For OS/2 we need to use a '/' */
  !     child_pid = spawnl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  !     return(child_pid);
  ! #elif defined(__EMX__)
        /* For OS/2 we need to use a '/' */
        execl (SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
  ***************
  *** 128,133 ****
  --- 133,139 ----
        perror ("execl");
        fprintf (stderr, "Exec of shell for logging failed!!!\n");
        exit (1);
  +     return(child_pid);
    }
    
    void open_referer_log (server_rec *s, pool *p)
  
  
  
  1.41      +4 -1      apache/src/mod_negotiation.c
  
  Index: mod_negotiation.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_negotiation.c,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -C3 -r1.40 -r1.41
  *** mod_negotiation.c	1997/04/17 02:50:20	1.40
  --- mod_negotiation.c	1997/06/15 19:22:31	1.41
  ***************
  *** 63,68 ****
  --- 63,71 ----
    #include "http_core.h"
    #include "http_log.h"
    #include "util_script.h"
  + #ifdef WIN32
  + #include "nt/readdir.h"
  + #endif
    
    /* define TCN_02 to allow for Holtman I-D transparent negotiation.
     * This file currently implements the draft-02, except for
  ***************
  *** 678,684 ****
    		set_mime_fields (&mime_info, &accept_info);
    	    }
    	    else if (!strncmp (buffer, "content-length:", 15)) {
  ! 		mime_info.bytes = atoi(body);
    	    }
    	    else if (!strncmp (buffer, "content-language:", 17)) {
    		mime_info.content_languages = 
  --- 681,687 ----
    		set_mime_fields (&mime_info, &accept_info);
    	    }
    	    else if (!strncmp (buffer, "content-length:", 15)) {
  ! 		mime_info.bytes = atof(body);
    	    }
    	    else if (!strncmp (buffer, "content-language:", 17)) {
    		mime_info.content_languages = 
  
  
  
  1.29      +19 -5     apache/src/mod_rewrite.c
  
  Index: mod_rewrite.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_rewrite.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -C3 -r1.28 -r1.29
  *** mod_rewrite.c	1997/04/24 23:35:22	1.28
  --- mod_rewrite.c	1997/06/15 19:22:31	1.29
  ***************
  *** 100,106 ****
  --- 100,108 ----
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/stat.h>
  + #ifndef WIN32
    #include <netinet/in.h>
  + #endif
    
        /* from the Apache server ... */
    #include "httpd.h"
  ***************
  *** 1684,1690 ****
                    rc = 1;
        }
        else if (strcmp(p->pattern, "-l") == 0) {
  ! #ifndef __EMX__
    /* OS/2 dosen't support links. */
            if (stat(input, &sb) == 0)
                if (S_ISLNK(sb.st_mode))
  --- 1686,1692 ----
                    rc = 1;
        }
        else if (strcmp(p->pattern, "-l") == 0) {
  ! #if !defined(__EMX__) && !defined(WIN32)
    /* OS/2 dosen't support links. */
            if (stat(input, &sb) == 0)
                if (S_ISLNK(sb.st_mode))
  ***************
  *** 2278,2294 ****
    }
    
    /* Child process code for 'RewriteLog "|..."' */
  ! static void rewritelog_child(void *cmd)
    {
        cleanup_for_exec();
        signal(SIGHUP, SIG_IGN);
  ! #ifdef __EMX__
        /* OS/2 needs a '/' */
        execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
        execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    #endif
        exit(1);
    }
    
    static void rewritelog(request_rec *r, int level, const char *text, ...)
  --- 2280,2302 ----
    }
    
    /* Child process code for 'RewriteLog "|..."' */
  ! static int rewritelog_child(void *cmd)
    {
  +     int child_pid = 0;
  + 
        cleanup_for_exec();
        signal(SIGHUP, SIG_IGN);
  ! #if defined(WIN32)
  !     child_pid = spawnl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  !     return(child_pid);
  ! #elif defined(__EMX__)
        /* OS/2 needs a '/' */
        execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
        execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    #endif
        exit(1);
  +     return(child_pid);
    }
    
    static void rewritelog(request_rec *r, int level, const char *text, ...)
  ***************
  *** 2425,2441 ****
    }
    
    /* child process code */
  ! static void rewritemap_program_child(void *cmd)
    {
        cleanup_for_exec();
        signal(SIGHUP, SIG_IGN);
  ! #ifdef __EMX__
        /* OS/2 needs a '/' */
        execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
        execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    #endif
        exit(1);
    }
    
    
  --- 2433,2455 ----
    }
    
    /* child process code */
  ! static int rewritemap_program_child(void *cmd)
    {
  +     int child_pid = 0;
  +     
        cleanup_for_exec();
        signal(SIGHUP, SIG_IGN);
  ! #if defined(WIN32)
  !     child_pid = spawnl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  !     return(child_pid);
  ! #elif defined(__EMX__)
        /* OS/2 needs a '/' */
        execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
    #else
        execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
    #endif
        exit(1);
  +     return(0);
    }
    
    
  
  
  
  1.23      +1 -1      apache/src/mod_rewrite.h
  
  Index: mod_rewrite.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_rewrite.h,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -C3 -r1.22 -r1.23
  *** mod_rewrite.h	1997/04/17 02:52:51	1.22
  --- mod_rewrite.h	1997/06/15 19:22:32	1.23
  ***************
  *** 122,128 ****
    #endif
    #if !defined(USE_FCNTL) && !defined(USE_FLOCK)
    #define USE_FLOCK 1
  ! #ifndef MPE
    #include <sys/file.h>
    #endif
    #ifndef LOCK_UN
  --- 122,128 ----
    #endif
    #if !defined(USE_FCNTL) && !defined(USE_FLOCK)
    #define USE_FLOCK 1
  ! #if !defined(MPE) && !defined(WIN32)
    #include <sys/file.h>
    #endif
    #ifndef LOCK_UN
  
  
  
  1.15      +17 -2     apache/src/mod_userdir.c
  
  Index: mod_userdir.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_userdir.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -C3 -r1.14 -r1.15
  *** mod_userdir.c	1997/03/07 14:15:44	1.14
  --- mod_userdir.c	1997/06/15 19:22:32	1.15
  ***************
  *** 142,155 ****
          if (strchr(userdir, '*'))
    	x = getword(r->pool, &userdir, '*');
    
  ! #ifdef __EMX__
          /* Add support for OS/2 drive letters */
          if ((userdir[0] == '/') || (userdir[1] == ':') || (userdir[0] == '\0')) {
    #else
          if ((userdir[0] == '/') || (userdir[0] == '\0')) {
    #endif
    	if (x) {
    	  if (strchr(x, ':')) {
    	    redirect = pstrcat(r->pool, x, w, userdir, dname, NULL);
    	    table_set (r->headers_out, "Location", redirect);
    	    return REDIRECT;
  --- 142,166 ----
          if (strchr(userdir, '*'))
    	x = getword(r->pool, &userdir, '*');
    
  ! #if defined(__EMX__) || defined(WIN32)
          /* Add support for OS/2 drive letters */
          if ((userdir[0] == '/') || (userdir[1] == ':') || (userdir[0] == '\0')) {
    #else
          if ((userdir[0] == '/') || (userdir[0] == '\0')) {
    #endif
    	if (x) {
  + #ifdef WIN32
  +           /*
  +            * Crummy hack. Need to figure out whether we have
  +            * been redirected to a URL or to a file on some
  +            * drive. Since I know of no protocols that are a
  +            * single letter, if the : is the second character,
  +            * I will assume a file was specified
  +            */
  +           if (strchr(x+2, ':')) {
  + #else
    	  if (strchr(x, ':')) {
  + #endif /* WIN32 */
    	    redirect = pstrcat(r->pool, x, w, userdir, dname, NULL);
    	    table_set (r->headers_out, "Location", redirect);
    	    return REDIRECT;
  ***************
  *** 166,171 ****
  --- 177,186 ----
    	return REDIRECT;
          }
          else {
  + #ifdef WIN32
  +           /* Need to figure out home dirs on NT */
  +           return DECLINED;
  + #else /* WIN32 */
    	struct passwd *pw;
    	if((pw=getpwnam(w)))
    #ifdef __EMX__
  ***************
  *** 174,180 ****
    #else
    	  filename = pstrcat (r->pool, pw->pw_dir, "/", userdir, NULL);
    #endif
  ! 
          }
    
          /* Now see if it exists, or we're at the last entry. If we are at the
  --- 189,195 ----
    #else
    	  filename = pstrcat (r->pool, pw->pw_dir, "/", userdir, NULL);
    #endif
  ! #endif /* WIN32 */
          }
    
          /* Now see if it exists, or we're at the last entry. If we are at the
  
  
  
  1.12      +6 -6      apache/src/rfc1413.c
  
  Index: rfc1413.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/rfc1413.c,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -C3 -r1.11 -r1.12
  *** rfc1413.c	1997/05/29 18:29:12	1.11
  --- rfc1413.c	1997/06/15 19:22:33	1.12
  ***************
  *** 75,82 ****
    #include "httpd.h"    /* for server_rec, conn_rec, ap_longjmp, etc. */
    #include "http_log.h" /* for log_unixerr */
    #include "rfc1413.h"
    
  ! #ifndef SCO
    extern char *strchr();
    extern char *inet_ntoa();
    #endif
  --- 75,83 ----
    #include "httpd.h"    /* for server_rec, conn_rec, ap_longjmp, etc. */
    #include "http_log.h" /* for log_unixerr */
    #include "rfc1413.h"
  + #include "http_main.h" /* set_callback_and_alarm */
    
  ! #if !defined(SCO) && !defined(WIN32)
    extern char *strchr();
    extern char *inet_ntoa();
    #endif
  ***************
  *** 100,106 ****
    JMP_BUF timebuf;
    
    /* bind_connect - bind both ends of a socket */
  ! 
    static int
    get_rfc1413(int sock, const struct sockaddr_in *our_sin,
    	  const struct sockaddr_in *rmt_sin, char user[256], server_rec *srv)
  --- 101,107 ----
    JMP_BUF timebuf;
    
    /* bind_connect - bind both ends of a socket */
  ! /* Ambarish fix this. Very broken */
    static int
    get_rfc1413(int sock, const struct sockaddr_in *our_sin,
    	  const struct sockaddr_in *rmt_sin, char user[256], server_rec *srv)
  ***************
  *** 209,225 ****
         */
        if (ap_setjmp(timebuf) == 0)
        {
  ! 	signal(SIGALRM, ident_timeout);
  ! 	alarm(rfc1413_timeout);
    	
    	if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user,
    		      srv)
    	    >= 0)
    	    result = user;
    
  ! 	alarm(0);
        }
  !     close(sock);
        conn->remote_logname = result;
    
        return conn->remote_logname;
  --- 210,225 ----
         */
        if (ap_setjmp(timebuf) == 0)
        {
  !         set_callback_and_alarm(ident_timeout, rfc1413_timeout);
    	
    	if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user,
    		      srv)
    	    >= 0)
    	    result = user;
    
  ! 	set_callback_and_alarm(NULL, 0);
        }
  !     closesocket(sock);
        conn->remote_logname = result;
    
        return conn->remote_logname;
  
  
  
  1.22      +2 -0      apache/src/scoreboard.h
  
  Index: scoreboard.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/scoreboard.h,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -C3 -r1.21 -r1.22
  *** scoreboard.h	1997/04/24 23:35:23	1.21
  --- scoreboard.h	1997/06/15 19:22:34	1.22
  ***************
  *** 50,56 ****
  --- 50,58 ----
     *
     */
    
  + #ifndef WIN32
    #include <sys/times.h>
  + #endif
    
    /* Scoreboard info on a process is, for now, kept very brief --- 
     * just status value and pid (the latter so that the caretaker process
  
  
  
  1.53      +10 -2     apache/src/util.c
  
  Index: util.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/util.c,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -C3 -r1.52 -r1.53
  *** util.c	1997/04/12 04:24:59	1.52
  --- util.c	1997/06/15 19:22:34	1.53
  ***************
  *** 703,709 ****
        
        for(x=0;cmd[x];x++) {
        
  ! #ifdef __EMX__
            /* Don't allow '&' in parameters under OS/2. */
            /* This can be used to send commands to the shell. */
            if (cmd[x] == '&') {
  --- 703,709 ----
        
        for(x=0;cmd[x];x++) {
        
  ! #if defined(__EMX__) || defined(WIN32)
            /* Don't allow '&' in parameters under OS/2. */
            /* This can be used to send commands to the shell. */
            if (cmd[x] == '&') {
  ***************
  *** 941,947 ****
    #ifdef MULTIPLE_GROUPS
      int cnt;
    #endif
  ! #ifdef __EMX__
        /* OS/2 dosen't have Users and Groups */
        return 1;
    #else    
  --- 941,947 ----
    #ifdef MULTIPLE_GROUPS
      int cnt;
    #endif
  ! #if defined(__EMX__) || defined(WIN32)
        /* OS/2 dosen't have Users and Groups */
        return 1;
    #else    
  ***************
  *** 1087,1092 ****
  --- 1087,1095 ----
    }
            
    uid_t uname2id(const char *name) {
  + #ifdef WIN32
  +     return(1);
  + #else
        struct passwd *ent;
    
        if(name[0] == '#') 
  ***************
  *** 1097,1105 ****
  --- 1100,1112 ----
            exit(1);
        }
        return(ent->pw_uid);
  + #endif
    }
    
    gid_t gname2id(const char *name) {
  + #ifdef WIN32
  +     return(1);
  + #else
        struct group *ent;
    
        if(name[0] == '#') 
  ***************
  *** 1110,1115 ****
  --- 1117,1123 ----
            exit(1);
        }
        return(ent->gr_gid);
  + #endif
    }
    
    #if 0
  
  
  
  1.59      +112 -7    apache/src/util_script.c
  
  Index: util_script.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/util_script.c,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -C3 -r1.58 -r1.59
  *** util_script.c	1997/05/11 23:13:22	1.58
  --- util_script.c	1997/06/15 19:22:34	1.59
  ***************
  *** 421,427 ****
        rputs(ss, r);
    }
    
  ! #ifdef __EMX__
    static char **create_argv_cmd(pool *p, char *av0, const char *args, char *path)
    {
        register int x,n;
  --- 421,427 ----
        rputs(ss, r);
    }
    
  ! #if defined(__EMX__) || defined(WIN32)
    static char **create_argv_cmd(pool *p, char *av0, const char *args, char *path)
    {
        register int x,n;
  ***************
  *** 452,459 ****
    #endif
    
    
  ! void call_exec (request_rec *r, char *argv0, char **env, int shellcmd) 
    {
    #if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \
        defined(RLIMIT_DATA) || defined(RLIMIT_VMEM)
    
  --- 452,460 ----
    #endif
    
    
  ! int call_exec (request_rec *r, char *argv0, char **env, int shellcmd) 
    {
  +     int pid = 0;
    #if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \
        defined(RLIMIT_DATA) || defined(RLIMIT_VMEM)
    
  ***************
  *** 506,512 ****
                /* write(2, err_string, strlen(err_string)); */
                /* exit(0); */
                log_unixerr("fopen", NULL, err_string, r->server);
  !             return;
            }
            fgets (interpreter, 2048, program);
            fclose (program);
  --- 507,513 ----
                /* write(2, err_string, strlen(err_string)); */
                /* exit(0); */
                log_unixerr("fopen", NULL, err_string, r->server);
  !             return(pid);
            }
            fgets (interpreter, 2048, program);
            fclose (program);
  ***************
  *** 561,566 ****
  --- 562,670 ----
    	    execv(r->filename,
    	          create_argv(r->pool, NULL, NULL, NULL, argv0, r->args));
        }
  +     return(pid);
  +     }
  + #elif defined(WIN32)
  +     {
  +         /* Adapted from work by Alec Kloss, to allow exec'ing of scripts under OS/2 */
  +         int is_script = 0;
  +         int is_binary = 0;
  +         char interpreter[2048]; /* hope this is large enough for the interpreter path */
  +         FILE * program;
  +         int i, sz;
  +         char *dot;
  +         char *exename;
  +         int is_exe = 0;
  + 
  +         interpreter[0] = 0;
  + 
  +         exename = strrchr(r->filename, '/');
  +         if(!exename)
  +             exename = strrchr(r->filename, '\\');
  +         if(!exename)
  +             exename = r->filename;
  +         else
  +             exename++;
  +         dot = strrchr(exename, '.');
  +         if(dot)
  +         {
  +             if(!strcasecmp(dot, ".BAT") ||
  +                 !strcasecmp(dot, ".EXE") ||
  +                 !strcasecmp(dot, ".COM"))
  +                 is_exe = 1;
  +         }
  +         if(!is_exe)
  +         {
  +             program = fopen (r->filename, "rb");
  +             if (!program) {
  +                 char err_string[HUGE_STRING_LEN];
  +                 ap_snprintf(err_string, sizeof(err_string), "open of %s failed, errno is %d\n", r->filename, errno);
  +                 /* write(2, err_string, strlen(err_string)); */
  +                 /* exit(0); */
  +                 log_unixerr("fopen", NULL, err_string, r->server);
  +                 return(pid);
  +             }
  +             sz = fread (interpreter, 1, 2047, program);
  +             if(sz < 0) {
  +                 char err_string[HUGE_STRING_LEN];
  +                 ap_snprintf(err_string, sizeof(err_string), "open of %s failed, errno is %d\n", r->filename, errno);
  +                 log_unixerr("fread", NULL, err_string, r->server);
  +                 fclose(program);
  +                 return(pid);
  +             }
  +             interpreter[sz] = 0;
  +             fclose (program);
  +             if (!strncmp (interpreter, "#!", 2)) {
  +                 is_script = 1;
  +                 for(i=2; i<2048; i++)
  +                 {
  +                     if((interpreter[i] == '\r') ||
  +                             (interpreter[i] == '\n'))
  +                         break;
  +                 }
  +                 interpreter[i] = 0;
  +             } else {
  +                 /*
  +                  * check and see how many control chars. On
  +                  * that basis, I will classify it as a text
  +                  * or binary file
  +                  */
  +                 int ctrl = 0;
  + 
  +                 for(i=0; i<sz; i++)
  +                 {
  +                     static char *spec = "\r\n\t";
  +                     if(iscntrl(interpreter[i]) && !strchr(spec, interpreter[i]))
  +                         ctrl++;
  +                 }
  +                 if(ctrl > sz/10)
  +                     is_binary = 1;
  +                 else
  +                     is_binary = 0;
  +                 
  +             }
  +         }
  + 
  +         if ((!r->args) || (!r->args[0]) || (ind(r->args,'=') >= 0)) {
  +             if (is_exe || is_binary) {
  +                 pid = spawnle(_P_NOWAIT, r->filename, r->filename, NULL, env);
  +             } else if(is_script) {
  + 	        pid = spawnle(_P_NOWAIT, interpreter+2, interpreter+2, r->filename, NULL, env);
  +             } else {             
  +                 pid = spawnle(_P_NOWAIT, "CMD.EXE", "CMD.EXE", "/C", r->filename, NULL, env);
  +             }
  +         }
  +         else {
  +             if (is_exe || is_binary) {
  +                 pid = spawnve(_P_NOWAIT, r->filename, create_argv(r->pool, argv0, NULL, NULL, r->args, (void *)NULL), env);
  +             } else if(is_script) {
  + 	        assert(0);
  +                 pid = spawnve(_P_NOWAIT, interpreter+2, create_argv(r->pool, interpreter+2, NULL, NULL, r->filename, r->args), env);
  +             } else {  
  +                 pid = spawnve(_P_NOWAIT, "CMD.EXE", create_argv_cmd(r->pool, argv0, r->args, r->filename), env);
  +             }
  +         }
  +         return(pid);
        }
    #else
        if ( suexec_enabled &&
  ***************
  *** 581,594 ****
    
    	    if ((pw = getpwnam(username)) == NULL) {
    	        log_unixerr("getpwnam",username,"invalid username",r->server);
  ! 	        return;
    	    }
    	    execuser = pstrcat(r->pool, "~", pw->pw_name, NULL);
    	    user_gid = pw->pw_gid;
    
    	    if ((gr = getgrgid(user_gid)) == NULL) {
    	        if ((grpname = palloc (r->pool, 16)) == NULL) 
  ! 	            return;
    	        else
    	            ap_snprintf(grpname, 16, "%d", user_gid);
    	    }
  --- 685,698 ----
    
    	    if ((pw = getpwnam(username)) == NULL) {
    	        log_unixerr("getpwnam",username,"invalid username",r->server);
  ! 	        return(pid);
    	    }
    	    execuser = pstrcat(r->pool, "~", pw->pw_name, NULL);
    	    user_gid = pw->pw_gid;
    
    	    if ((gr = getgrgid(user_gid)) == NULL) {
    	        if ((grpname = palloc (r->pool, 16)) == NULL) 
  ! 	            return(pid);
    	        else
    	            ap_snprintf(grpname, 16, "%d", user_gid);
    	    }
  ***************
  *** 598,610 ****
    	else {
    	    if ((pw = getpwuid (r->server->server_uid)) == NULL) {
    		log_unixerr("getpwuid", NULL, "invalid userid", r->server);
  ! 		return;
    	    }
    	    execuser = pstrdup(r->pool, pw->pw_name);
    
    	    if ((gr = getgrgid (r->server->server_gid)) == NULL) {
    		log_unixerr("getgrgid", NULL, "invalid groupid", r->server);
  ! 		return;
    	    }
    	    grpname = gr->gr_name;
    	}
  --- 702,714 ----
    	else {
    	    if ((pw = getpwuid (r->server->server_uid)) == NULL) {
    		log_unixerr("getpwuid", NULL, "invalid userid", r->server);
  ! 		return(pid);
    	    }
    	    execuser = pstrdup(r->pool, pw->pw_name);
    
    	    if ((gr = getgrgid (r->server->server_gid)) == NULL) {
    		log_unixerr("getgrgid", NULL, "invalid groupid", r->server);
  ! 		return(pid);
    	    }
    	    grpname = gr->gr_name;
    	}
  ***************
  *** 634,638 ****
  --- 738,743 ----
    	           create_argv(r->pool, NULL, NULL, NULL, argv0, r->args),
    	           env);
        }
  +     return(pid);
    #endif
    }
  
  
  
  1.17      +1 -1      apache/src/util_script.h
  
  Index: util_script.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/util_script.h,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -C3 -r1.16 -r1.17
  *** util_script.h	1997/04/29 03:41:13	1.16
  --- util_script.h	1997/06/15 19:22:35	1.17
  ***************
  *** 65,69 ****
    #define scan_script_header(a1,a2) scan_script_header_err(a1,a2,NULL)
    int scan_script_header_err(request_rec *r, FILE *f, char *buffer);
    void send_size(size_t size, request_rec *r);
  ! void call_exec (request_rec *r, char *argv0, char **env, int shellcmd);
    
  --- 65,69 ----
    #define scan_script_header(a1,a2) scan_script_header_err(a1,a2,NULL)
    int scan_script_header_err(request_rec *r, FILE *f, char *buffer);
    void send_size(size_t size, request_rec *r);
  ! int call_exec (request_rec *r, char *argv0, char **env, int shellcmd);
    
  
  
  
  1.13      +10 -1     apache/src/modules/proxy/mod_proxy.c
  
  Index: mod_proxy.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.c,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -C3 -r1.12 -r1.13
  *** mod_proxy.c	1997/04/28 20:54:40	1.12
  --- mod_proxy.c	1997/06/15 19:22:47	1.13
  ***************
  *** 179,184 ****
  --- 179,193 ----
        else return OK; /* otherwise; we've done the best we can */
    }
    
  + static int
  + proxy_init(server_rec *r, pool *p)
  + {
  +     proxy_garbage_init(r, p);
  + 
  +     return(0);
  + } 
  + 
  + 
    /* -------------------------------------------------------------- */
    /* Invoke handler */
     
  ***************
  *** 535,541 ****
    
    module proxy_module = {
       STANDARD_MODULE_STUFF,
  !    NULL,                        /* initializer */
       NULL,                        /* create per-directory config structure */
       NULL,                        /* merge per-directory config structures */
       create_proxy_config,         /* create per-server config structure */
  --- 544,550 ----
    
    module proxy_module = {
       STANDARD_MODULE_STUFF,
  !    proxy_init,                        /* initializer */
       NULL,                        /* create per-directory config structure */
       NULL,                        /* merge per-directory config structures */
       create_proxy_config,         /* create per-server config structure */
  
  
  
  1.12      +1 -0      apache/src/modules/proxy/mod_proxy.h
  
  Index: mod_proxy.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -C3 -r1.11 -r1.12
  *** mod_proxy.h	1997/04/16 00:13:05	1.11
  --- mod_proxy.h	1997/06/15 19:22:47	1.12
  ***************
  *** 270,273 ****
  --- 270,274 ----
    int proxyerror(request_rec *r, const char *message);
    const char *proxy_host2addr(const char *host, struct hostent *reqhp);
    int proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r);
  + int proxy_garbage_init(server_rec *, pool *);
    
  
  
  
  1.14      +53 -8     apache/src/modules/proxy/proxy_cache.c
  
  Index: proxy_cache.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_cache.c,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -C3 -r1.13 -r1.14
  *** proxy_cache.c	1997/05/29 15:16:01	1.13
  --- proxy_cache.c	1997/06/15 19:22:47	1.14
  ***************
  *** 58,64 ****
  --- 58,70 ----
    #include "http_log.h"
    #include "http_main.h"
    #include "util_date.h"
  + #ifdef WIN32
  + #include <sys/utime.h>
  + #include "nt/dirent.h"
  + #else
    #include <utime.h>
  + #endif /* WIN32 */
  + #include "multithread.h"
    
    #define	abs(c)	((c) >= 0 ? (c) : -(c))
    
  ***************
  *** 84,94 ****
  --- 90,135 ----
    static unsigned long int curblocks;
    static time_t now, expire;
    static char *filename;
  + static mutex *garbage_mutex = NULL;
  + 
  + 
  + int
  + proxy_garbage_init(server_rec *r, pool *p)
  + {
  +     if(!garbage_mutex)
  +         garbage_mutex = create_mutex(NULL);
  + 
  +     return(0);
  + }
  + 
    
    static int sub_garbage_coll(request_rec *r,array_header *files,
    			    const char *cachedir,const char *cachesubdir);
  + static void help_proxy_garbage_coll(request_rec *r);
    
    void proxy_garbage_coll(request_rec *r)
  + {
  +     static int inside = 0;
  + 
  +     acquire_mutex(garbage_mutex);
  +     if(inside == 1)
  +     {
  +         release_mutex(garbage_mutex);
  +         return;
  +     }
  +     else
  +         inside = 1;
  +     release_mutex(garbage_mutex);
  + 
  +     help_proxy_garbage_coll(r);
  + 
  +     acquire_mutex(garbage_mutex);
  +     inside = 0;
  +     release_mutex(garbage_mutex);
  + }
  + 
  + 
  + void help_proxy_garbage_coll(request_rec *r)
        {
        const char *cachedir;
        void *sconf = r->server->module_config;
  ***************
  *** 196,202 ****
        struct stat buf;
        int fd,i;
        DIR *dir;
  ! #if defined(NEXT)
        struct DIR_TYPE *ent;
    #else
        struct dirent *ent;
  --- 237,243 ----
        struct stat buf;
        int fd,i;
        DIR *dir;
  ! #if defined(NEXT) || defined(WIN32)
        struct DIR_TYPE *ent;
    #else
        struct dirent *ent;
  ***************
  *** 244,250 ****
    	/*	if (strlen(ent->d_name) != HASH_LEN) continue; */
    
    /* read the file */
  ! 	fd = open(filename, O_RDONLY);
    	if (fd == -1)
    	{
    	    if (errno  != ENOENT) proxy_log_uerror("open", filename,NULL,
  --- 285,291 ----
    	/*	if (strlen(ent->d_name) != HASH_LEN) continue; */
    
    /* read the file */
  ! 	fd = open(filename, O_RDONLY | O_BINARY);
    	if (fd == -1)
    	{
    	    if (errno  != ENOENT) proxy_log_uerror("open", filename,NULL,
  ***************
  *** 421,427 ****
    proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf,
    	     struct cache_req **cr)
    {
  !     char hashfile[33], *imstr, *pragma, *p, *auth;
        struct cache_req *c;
        time_t now;
        BUFF *cachefp;
  --- 462,468 ----
    proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf,
    	     struct cache_req **cr)
    {
  !     char hashfile[66], *imstr, *pragma, *p, *auth;
        struct cache_req *c;
        time_t now;
        BUFF *cachefp;
  ***************
  *** 466,476 ****
    	    auth == NULL)
        {
            Explain1("Check file %s",c->filename);
  ! 	cfd = open(c->filename, O_RDWR);
    	if (cfd != -1)
    	{
    	    note_cleanups_for_fd(r->pool, cfd);
  ! 	    cachefp = bcreate(r->pool, B_RD | B_WR);
    	    bpushfd(cachefp, cfd, cfd);
    	} else if (errno != ENOENT)
    	    proxy_log_uerror("open", c->filename,
  --- 507,517 ----
    	    auth == NULL)
        {
            Explain1("Check file %s",c->filename);
  ! 	cfd = open(c->filename, O_RDWR | O_BINARY);
    	if (cfd != -1)
    	{
    	    note_cleanups_for_fd(r->pool, cfd);
  ! 	    cachefp = bcreate(r->pool, B_RD | B_WR, 0);
    	    bpushfd(cachefp, cfd, cfd);
    	} else if (errno != ENOENT)
    	    proxy_log_uerror("open", c->filename,
  ***************
  *** 807,813 ****
    
        Explain1("Create temporary file %s",c->tempfile);
    
  !     i = open(c->tempfile, O_WRONLY | O_CREAT | O_EXCL, 0622);
        if (i == -1)
        {
    	proxy_log_uerror("open", c->tempfile,
  --- 848,854 ----
    
        Explain1("Create temporary file %s",c->tempfile);
    
  !     i = open(c->tempfile, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0622);
        if (i == -1)
        {
    	proxy_log_uerror("open", c->tempfile,
  ***************
  *** 815,821 ****
    	return DECLINED;
        }
        note_cleanups_for_fd(r->pool, i);
  !     c->fp = bcreate(r->pool, B_WR);
        bpushfd(c->fp, -1, i);
    
        if (bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1)
  --- 856,862 ----
    	return DECLINED;
        }
        note_cleanups_for_fd(r->pool, i);
  !     c->fp = bcreate(r->pool, B_WR, 0);
        bpushfd(c->fp, -1, i);
    
        if (bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1)
  ***************
  *** 904,916 ****
    	    if(!p)
    		break;
    	    *p='\0';
    	    if(mkdir(c->filename,S_IREAD|S_IWRITE|S_IEXEC) < 0 && errno != EEXIST)
    		proxy_log_uerror("mkdir",c->filename,
    		    "proxy: error creating cache directory",s);
    	    *p='/';
    	    ++p;
    	    }
  ! #ifdef __EMX__
            /* Under OS/2 use rename. */            
            if (rename(c->tempfile, c->filename) == -1)
                proxy_log_uerror("rename", c->filename,
  --- 945,961 ----
    	    if(!p)
    		break;
    	    *p='\0';
  + #ifdef WIN32
  + 	    if(mkdir(c->filename) < 0 && errno != EEXIST)
  + #else
    	    if(mkdir(c->filename,S_IREAD|S_IWRITE|S_IEXEC) < 0 && errno != EEXIST)
  + #endif /* WIN32 */
    		proxy_log_uerror("mkdir",c->filename,
    		    "proxy: error creating cache directory",s);
    	    *p='/';
    	    ++p;
    	    }
  ! #if defined(__EMX__) || defined(WIN32)
            /* Under OS/2 use rename. */            
            if (rename(c->tempfile, c->filename) == -1)
                proxy_log_uerror("rename", c->filename,
  
  
  
  1.9       +1 -1      apache/src/modules/proxy/proxy_connect.c
  
  Index: proxy_connect.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_connect.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -C3 -r1.8 -r1.9
  *** proxy_connect.c	1997/04/24 23:21:35	1.8
  --- proxy_connect.c	1997/06/15 19:22:48	1.9
  ***************
  *** 221,227 ****
          else break;
        }
    
  !     pclosef(r->pool,sock);
        
        return OK;
    }     
  --- 221,227 ----
          else break;
        }
    
  !     pclosesocket(r->pool,sock);
        
        return OK;
    }     
  
  
  
  1.22      +25 -25    apache/src/modules/proxy/proxy_ftp.c
  
  Index: proxy_ftp.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_ftp.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -C3 -r1.21 -r1.22
  *** proxy_ftp.c	1997/04/22 03:29:37	1.21
  --- proxy_ftp.c	1997/06/15 19:22:48	1.22
  ***************
  *** 497,510 ****
    	    r->server);
    	return SERVER_ERROR;
        }
  !     note_cleanups_for_fd(pool, sock);
    
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one,
    		   sizeof(int)) == -1)
        {
    	proxy_log_uerror("setsockopt", NULL,
    	    "proxy: error setting reuseaddr option", r->server);
  ! 	pclosef(pool, sock);
    	return SERVER_ERROR;
        }
    
  --- 497,510 ----
    	    r->server);
    	return SERVER_ERROR;
        }
  !     note_cleanups_for_socket(pool, sock);
    
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one,
    		   sizeof(int)) == -1)
        {
    	proxy_log_uerror("setsockopt", NULL,
    	    "proxy: error setting reuseaddr option", r->server);
  ! 	pclosesocket(pool, sock);
    	return SERVER_ERROR;
        }
    
  ***************
  *** 520,526 ****
        if (i == -1)
    	return proxyerror(r, "Could not connect to remote machine");
    
  !     f = bcreate(pool, B_RDWR);
        bpushfd(f, sock, sock);
    /* shouldn't we implement telnet control options here? */
    
  --- 520,526 ----
        if (i == -1)
    	return proxyerror(r, "Could not connect to remote machine");
    
  !     f = bcreate(pool, B_RDWR, 1);
        bpushfd(f, sock, sock);
    /* shouldn't we implement telnet control options here? */
    
  ***************
  *** 667,677 ****
        { 
    	proxy_log_uerror("socket", NULL, "proxy: error creating PASV socket",
    	    r->server);
  ! 	pclosef(pool, sock);
    	kill_timeout(r);
            return SERVER_ERROR;
        }
  !     note_cleanups_for_fd(pool, dsock);
    
        bputs("PASV\015\012", f);
        bflush(f);
  --- 667,677 ----
        { 
    	proxy_log_uerror("socket", NULL, "proxy: error creating PASV socket",
    	    r->server);
  ! 	pclosesocket(pool, sock);
    	kill_timeout(r);
            return SERVER_ERROR;
        }
  !     note_cleanups_for_socket(pool, dsock);
    
        bputs("PASV\015\012", f);
        bflush(f);
  ***************
  *** 683,690 ****
        {
    	proxy_log_uerror("command", NULL, "PASV: control connection is toast",
    	    r->server);
  ! 	pclosef(pool, dsock);
  ! 	pclosef(pool, sock);
    	kill_timeout(r);
    	return SERVER_ERROR;
        } else
  --- 683,690 ----
        {
    	proxy_log_uerror("command", NULL, "PASV: control connection is toast",
    	    r->server);
  ! 	pclosesocket(pool, dsock);
  ! 	pclosesocket(pool, sock);
    	kill_timeout(r);
    	return SERVER_ERROR;
        } else
  ***************
  *** 721,732 ****
    		return proxyerror(r, "Could not connect to remote machine");
    	    }
    	    else {
  ! 	        data = bcreate(pool, B_RDWR); 
    	        bpushfd(data, dsock, dsock);
    	        pasvmode = 1;
    	    }
    	} else
  ! 	    pclosef(pool, dsock);	/* and try the regular way */
        }
    
        if (!pasvmode)	/* set up data connection */
  --- 721,732 ----
    		return proxyerror(r, "Could not connect to remote machine");
    	    }
    	    else {
  ! 	        data = bcreate(pool, B_RDWR, 1); 
    	        bpushfd(data, dsock, dsock);
    	        pasvmode = 1;
    	    }
    	} else
  ! 	    pclosesocket(pool, dsock);	/* and try the regular way */
        }
    
        if (!pasvmode)	/* set up data connection */
  ***************
  *** 736,742 ****
            {
    	    proxy_log_uerror("getsockname", NULL,
    	        "proxy: error getting socket address", r->server);
  ! 	    pclosef(pool, sock);
    	    kill_timeout(r);
    	    return SERVER_ERROR;
            }
  --- 736,742 ----
            {
    	    proxy_log_uerror("getsockname", NULL,
    	        "proxy: error getting socket address", r->server);
  ! 	    pclosesocket(pool, sock);
    	    kill_timeout(r);
    	    return SERVER_ERROR;
            }
  ***************
  *** 746,752 ****
            {
    	    proxy_log_uerror("socket", NULL, "proxy: error creating socket",
    	        r->server);
  ! 	    pclosef(pool, sock);
    	    kill_timeout(r);
    	    return SERVER_ERROR;
            }
  --- 746,752 ----
            {
    	    proxy_log_uerror("socket", NULL, "proxy: error creating socket",
    	        r->server);
  ! 	    pclosesocket(pool, sock);
    	    kill_timeout(r);
    	    return SERVER_ERROR;
            }
  ***************
  *** 757,764 ****
            {
    	    proxy_log_uerror("setsockopt", NULL,
    	        "proxy: error setting reuseaddr option", r->server);
  ! 	    pclosef(pool, dsock);
  ! 	    pclosef(pool, sock);
    	    kill_timeout(r);
    	    return SERVER_ERROR;
            }
  --- 757,764 ----
            {
    	    proxy_log_uerror("setsockopt", NULL,
    	        "proxy: error setting reuseaddr option", r->server);
  ! 	    pclosesocket(pool, dsock);
  ! 	    pclosesocket(pool, sock);
    	    kill_timeout(r);
    	    return SERVER_ERROR;
            }
  ***************
  *** 771,778 ****
    	    ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port);
    	    proxy_log_uerror("bind", buff,
    	        "proxy: error binding to ftp data socket", r->server);
  !     	    pclosef(pool, sock);
  !     	    pclosef(pool, dsock);
            }
            listen(dsock, 2); /* only need a short queue */
        }
  --- 771,778 ----
    	    ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port);
    	    proxy_log_uerror("bind", buff,
    	        "proxy: error binding to ftp data socket", r->server);
  !     	    pclosesocket(pool, sock);
  !     	    pclosesocket(pool, dsock);
            }
            listen(dsock, 2); /* only need a short queue */
        }
  ***************
  *** 912,919 ****
    
        if (i != DECLINED)
        {
  ! 	pclosef(pool, dsock);
  ! 	pclosef(pool, sock);
    	return i;
        }
        cache = c->fp;
  --- 912,919 ----
    
        if (i != DECLINED)
        {
  ! 	pclosesocket(pool, dsock);
  ! 	pclosesocket(pool, sock);
    	return i;
        }
        cache = c->fp;
  ***************
  *** 928,941 ****
            {
    	    proxy_log_uerror("accept", NULL,
    	        "proxy: failed to accept data connection", r->server);
  ! 	    pclosef(pool, dsock);
  ! 	    pclosef(pool, sock);
    	    kill_timeout(r);
    	    proxy_cache_error(c);
    	    return BAD_GATEWAY;
            }
  !         note_cleanups_for_fd(pool, csd);
  !         data = bcreate(pool, B_RDWR);
            bpushfd(data, csd, -1);
    	kill_timeout(r);
        }
  --- 928,941 ----
            {
    	    proxy_log_uerror("accept", NULL,
    	        "proxy: failed to accept data connection", r->server);
  ! 	    pclosesocket(pool, dsock);
  ! 	    pclosesocket(pool, sock);
    	    kill_timeout(r);
    	    proxy_cache_error(c);
    	    return BAD_GATEWAY;
            }
  !         note_cleanups_for_socket(pool, csd);
  !         data = bcreate(pool, B_RDWR, 1);
            bpushfd(data, csd, -1);
    	kill_timeout(r);
        }
  ***************
  *** 986,992 ****
    	bputs("ABOR\015\012", f);
    	bflush(f);
    	if (!pasvmode)
  !             pclosef(pool, csd);
            Explain0("FTP: ABOR");
    /* responses: 225, 226, 421, 500, 501, 502 */
    	i = ftp_getrc(f);
  --- 986,992 ----
    	bputs("ABOR\015\012", f);
    	bflush(f);
    	if (!pasvmode)
  !             pclosesocket(pool, csd);
            Explain0("FTP: ABOR");
    /* responses: 225, 226, 421, 500, 501, 502 */
    	i = ftp_getrc(f);
  ***************
  *** 1003,1011 ****
    /* responses: 221, 500 */    
    
        if (!pasvmode)
  !         pclosef(pool, csd);
  !     pclosef(pool, dsock);
  !     pclosef(pool, sock);
    
        proxy_garbage_coll(r);
    
  --- 1003,1011 ----
    /* responses: 221, 500 */    
    
        if (!pasvmode)
  !         pclosesocket(pool, csd);
  !     pclosesocket(pool, dsock);
  !     pclosesocket(pool, sock);
    
        proxy_garbage_coll(r);
    
  
  
  
  1.18      +6 -6      apache/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -C3 -r1.17 -r1.18
  *** proxy_http.c	1997/04/11 05:10:51	1.17
  --- proxy_http.c	1997/06/15 19:22:48	1.18
  ***************
  *** 224,230 ****
    	log_error("proxy: error creating socket", r->server);
    	return SERVER_ERROR;
        }
  !     note_cleanups_for_fd(pool, sock);
    
        
        j = 0;
  --- 224,230 ----
    	log_error("proxy: error creating socket", r->server);
    	return SERVER_ERROR;
        }
  !     note_cleanups_for_socket(pool, sock);
    
        
        j = 0;
  ***************
  *** 244,250 ****
    
        clear_connection(r->headers_in);	/* Strip connection-based headers */
    
  !     f = bcreate(pool, B_RDWR);
        bpushfd(f, sock, sock);
    
        hard_timeout ("proxy send", r);
  --- 244,250 ----
    
        clear_connection(r->headers_in);	/* Strip connection-based headers */
    
  !     f = bcreate(pool, B_RDWR, 1);
        bpushfd(f, sock, sock);
    
        hard_timeout ("proxy send", r);
  ***************
  *** 281,287 ****
        len = bgets(buffer, HUGE_STRING_LEN-1, f);
        if (len == -1 || len == 0)
        {
  ! 	pclosef(pool, sock);
    	kill_timeout(r);
    	return proxyerror(r, "Error reading from remote server");
        }
  --- 281,287 ----
        len = bgets(buffer, HUGE_STRING_LEN-1, f);
        if (len == -1 || len == 0)
        {
  ! 	pclosesocket(pool, sock);
    	kill_timeout(r);
    	return proxyerror(r, "Error reading from remote server");
        }
  ***************
  *** 292,298 ****
    /* If not an HTTP/1 messsage or if the status line was > 8192 bytes */
    	if (buffer[5] != '1' || buffer[len-1] != '\n')
    	{
  ! 	    pclosef(pool, sock);
    	    kill_timeout(r);
    	    return BAD_GATEWAY;
    	}
  --- 292,298 ----
    /* If not an HTTP/1 messsage or if the status line was > 8192 bytes */
    	if (buffer[5] != '1' || buffer[len-1] != '\n')
    	{
  ! 	    pclosesocket(pool, sock);
    	    kill_timeout(r);
    	    return BAD_GATEWAY;
    	}
  ***************
  *** 354,360 ****
        i = proxy_cache_update(c, resp_hdrs, inprotocol, nocache);
        if (i != DECLINED)
        {
  ! 	pclosef(pool, sock);
    	return i;
        }
    
  --- 354,360 ----
        i = proxy_cache_update(c, resp_hdrs, inprotocol, nocache);
        if (i != DECLINED)
        {
  ! 	pclosesocket(pool, sock);
    	return i;
        }
    
  ***************
  *** 406,412 ****
    
        proxy_cache_tidy(c);
    
  !     pclosef(pool, sock);
    
        proxy_garbage_coll(r);
        return OK;
  --- 406,412 ----
    
        proxy_cache_tidy(c);
    
  !     pclosesocket(pool, sock);
    
        proxy_garbage_coll(r);
        return OK;
  
  
  
  1.18      +77 -5     apache/src/modules/proxy/proxy_util.c
  
  Index: proxy_util.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_util.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -C3 -r1.17 -r1.18
  *** proxy_util.c	1997/06/04 21:20:27	1.17
  --- proxy_util.c	1997/06/15 19:22:49	1.18
  ***************
  *** 55,60 ****
  --- 55,61 ----
    #include "mod_proxy.h"
    #include "http_main.h"
    #include "md5.h"
  + #include "multithread.h"
    
    /* already called in the knowledge that the characters are hex digits */
    int
  ***************
  *** 235,242 ****
  --- 236,249 ----
    	if (!isdigit(host[i]) && host[i] != '.')
    	    break;
     /* must be an IP address */
  + #ifdef WIN32
  +     if (host[i] == '\0' && (inet_addr(host) == -1))
  + #else
        if (host[i] == '\0' && (inet_addr(host) == -1 || inet_network(host) == -1))
  + #endif
  +     {
    	    return "Bad IP address in URL";
  +     }
    
        *urlp = url;
        *hostp = host;
  ***************
  *** 419,424 ****
  --- 426,433 ----
                    if (f2 != NULL) {
                        pclosef(c->req->pool, c->fp->fd);
                        c->fp = NULL; 
  +                     f2 = NULL;
  +                     con->aborted = 1;
                        unlink(c->tempfile);
                    }
                    break;
  ***************
  *** 549,554 ****
  --- 558,619 ----
        return 0;
    }
    
  + #ifdef WIN32
  + 
  + /*
  +  * On NT, the file system is NOT case sensitive. So, a == A
  +  * need to map to smaller set of characters
  +  */
  + void
  + proxy_hash(const char *it, char *val,int ndepth,int nlength)
  + {
  +     MD5_CTX context;
  +     unsigned char digest[16];
  +     char tmp[26];
  +     int i, k, d;
  +     unsigned int x;
  +     static const char table[32]= "abcdefghijklmnopqrstuvwxyz012345";
  + 
  +     MD5Init(&context);
  +     MD5Update(&context, (const unsigned char *)it, strlen(it));
  +     MD5Final(digest, &context);
  + 
  + /* encode 128 bits as 26 characters, using a modified uuencoding */
  + /* the encoding is 5 bytes -> 8 characters
  +  * i.e. 128 bits is 3 x 5 bytes + 1 byte -> 3 * 8 characters + 2 characters
  +  */
  +     for (i=0, k=0; i < 15; i += 5)
  +     {
  + 	x = (digest[i] << 24) | (digest[i+1] << 16) | (digest[i+2] << 8) | digest[i+3];
  + 	tmp[k++] = table[x >> 27];
  + 	tmp[k++] = table[(x >> 22) & 0x1f];
  + 	tmp[k++] = table[(x >> 17) & 0x1f];
  +         tmp[k++] = table[(x >> 12) & 0x1f];
  +         tmp[k++] = table[(x >> 7) & 0x1f];
  +         tmp[k++] = table[(x >> 2) & 0x1f];
  +         x = ((x & 0x3) << 8) | digest[i+4];
  +         tmp[k++] = table[x >> 5];
  + 	tmp[k++] = table[x & 0x1f];
  +     }
  + /* one byte left */
  +     x = digest[15];
  +     tmp[k++] = table[x >> 3];  /* use up 5 bits */
  +     tmp[k++] = table[x & 0x7];
  +     /* now split into directory levels */
  + 
  +     for(i=k=d=0 ; d < ndepth ; ++d)
  + 	{
  + 	strncpy(&val[i],&tmp[k],nlength);
  + 	k+=nlength;
  + 	val[i+nlength]='/';
  + 	i+=nlength+1;
  + 	}
  +     memcpy(&val[i],&tmp[k],22-k);
  +     val[i+22-k]='\0';
  + }
  + 
  + #else
  + 
    void
    proxy_hash(const char *it, char *val,int ndepth,int nlength)
    {
  ***************
  *** 593,598 ****
  --- 658,665 ----
        val[i+22-k]='\0';
    }
    
  + #endif /* WIN32 */
  + 
    /*
     * Converts 8 hex digits to a time integer
     */
  ***************
  *** 699,707 ****
    {
        int i;
        struct hostent *hp;
  !     static struct hostent hpbuf;
  !     static u_long ipaddr;
  !     static char* charpbuf[2];
    
        for (i=0; host[i] != '\0'; i++)
    	if (!isdigit(host[i]) && host[i] != '.')
  --- 766,774 ----
    {
        int i;
        struct hostent *hp;
  !     static __declspec( thread ) struct hostent hpbuf;
  !     static __declspec( thread ) u_long ipaddr;
  !     static __declspec( thread ) char* charpbuf[2];
    
        for (i=0; host[i] != '\0'; i++)
    	if (!isdigit(host[i]) && host[i] != '.')
  ***************
  *** 737,744 ****
        int i;
    
        hard_timeout("proxy connect", r);
  !     do	i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
  !     while (i == -1 && errno == EINTR);
        if (i == -1) proxy_log_uerror("connect", NULL, NULL, r->server);
        kill_timeout(r);
    
  --- 804,816 ----
        int i;
    
        hard_timeout("proxy connect", r);
  !     do {
  ! 	i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
  ! #ifdef WIN32
  !         if(i == SOCKET_ERROR)
  !             errno = WSAGetLastError() - WSABASEERR;
  ! #endif /* WIN32 */
  !     } while (i == -1 && errno == EINTR);
        if (i == -1) proxy_log_uerror("connect", NULL, NULL, r->server);
        kill_timeout(r);