nginx-0.0.1-2003-11-19-19:26:41 import
diff --git a/src/os/unix/ngx_daemon.c b/src/os/unix/ngx_daemon.c
index 7d05fef..b2a37c1 100644
--- a/src/os/unix/ngx_daemon.c
+++ b/src/os/unix/ngx_daemon.c
@@ -9,7 +9,7 @@
 
     switch (fork()) {
     case -1:
-        ngx_log_error(NGX_LOG_EMERG, log, errno, "fork() failed");
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
         return NGX_ERROR;
 
     case 0:
@@ -20,7 +20,7 @@
     }
 
     if (setsid() == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, errno, "setsid() failed");
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
         return NGX_ERROR;
     }
 
@@ -28,30 +28,31 @@
 
     fd = open("/dev/null", O_RDWR);
     if (fd == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, errno, "open(\"/dev/null\") failed");
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
+                      "open(\"/dev/null\") failed");
         return NGX_ERROR;
     }
 
     if (dup2(fd, STDIN_FILENO) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDIN) failed");
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
         return NGX_ERROR;
     }
 
     if (dup2(fd, STDOUT_FILENO) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDOUT) failed");
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
         return NGX_ERROR;
     }
 
 #if 0
     if (dup2(fd, STDERR_FILENO) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, errno, "dup2(STDERR) failed");
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
         return NGX_ERROR;
     }
 #endif
 
     if (fd > STDERR_FILENO) {
         if (close(fd) == -1) {
-            ngx_log_error(NGX_LOG_EMERG, log, errno, "close() failed");
+            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
             return NGX_ERROR;
         }
     }
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index d0f255a..a7326b6 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -19,6 +19,7 @@
 #define NGX_ECONNRESET    ECONNRESET
 #define NGX_ETIMEDOUT     ETIMEDOUT
 #define NGX_ECANCELED     ECANCELED
+#define NGX_ECHILD        ECHILD
 #define NGX_ENOMOREFILES  0
 
 
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
index 7b9d4e4..651113d 100644
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -30,9 +30,9 @@
             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
             return NGX_ERROR;
         }
-    }
 
-    file->sys_offset = offset;
+        file->sys_offset = offset;
+    }
 
     n = read(file->fd, buf, size);
 
@@ -77,9 +77,9 @@
             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
             return NGX_ERROR;
         }
-    }
 
-    file->sys_offset = offset;
+        file->sys_offset = offset;
+    }
 
     n = write(file->fd, buf, size);
 
@@ -151,14 +151,14 @@
         return ngx_write_file(file, iov[0].iov_base, iov[0].iov_len, offset);
     }
 
-    if (file->offset != offset) {
+    if (file->sys_offset != offset) {
         if (lseek(file->fd, offset, SEEK_SET) == -1) {
             ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
             return NGX_ERROR;
         }
-    }
 
-    file->sys_offset = offset;
+        file->sys_offset = offset;
+    }
 
     n = writev(file->fd, io.elts, io.nelts);
 
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index 0493b3b..a045a1d 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -16,6 +16,7 @@
 #include <sys/ioctl.h>
 #include <sys/resource.h>
 #include <sys/sysctl.h>
+#include <sys/wait.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c
index c970833..7462dcf 100644
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -13,8 +13,8 @@
 
 int ngx_posix_init(ngx_log_t *log)
 {
-    struct sigaction sa;
-    struct rlimit  rlmt;
+    struct rlimit     rlmt;
+    struct sigaction  sa;
 
     ngx_memzero(&sa, sizeof(struct sigaction));
     sa.sa_handler = SIG_IGN;
@@ -25,6 +25,15 @@
         return NGX_ERROR;
     }
 
+    ngx_memzero(&sa, sizeof(struct sigaction));
+    sa.sa_handler = ngx_sigchld_handler;
+    sigemptyset(&sa.sa_mask);
+    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
+                      "sigaction(SIGCHLD) failed");
+        return NGX_ERROR;
+    }
+
     sa.sa_handler = ngx_restart_signal_handler;
     if (sigaction(ngx_signal_value(NGX_RESTART_SIGNAL), &sa, NULL) == -1) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c
new file mode 100644
index 0000000..e487151
--- /dev/null
+++ b/src/os/unix/ngx_process.c
@@ -0,0 +1,112 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+void testone(ngx_log_t *log)
+{
+    ngx_log_debug(log, "child process");
+    ngx_msleep(5000);
+    exit(0);
+}
+
+
+int ngx_spawn_process(ngx_log_t *log)
+{
+    pid_t     pid;
+    sigset_t  set, oset; 
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGCHLD);
+    if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed");
+    }
+
+    pid = fork();
+
+    if (pid == -1 || pid == 0) {
+        if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                          "sigprocmask() failed");
+        }
+    }
+
+    switch (pid) {
+    case -1:
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "fork() failed");
+        return NGX_ERROR;
+
+    case 0:
+        testone(log);
+        break;
+
+    default:
+    }
+
+ngx_log_debug(log, "parent process, child: " PID_FMT _ pid);
+
+    /* book keeping */
+
+    if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed");
+    }
+
+    return NGX_OK;
+}
+
+
+void ngx_sigchld_handler(int signo)
+{
+    int             status, one;
+    pid_t           pid;
+    ngx_err_t       err;
+    struct timeval  tv;
+
+    ngx_gettimeofday(&tv);
+
+    if (ngx_cached_time != tv.tv_sec) {
+        ngx_cached_time = tv.tv_sec;
+        ngx_time_update();
+    }
+
+    one = 0;
+
+    for ( ;; ) {
+        pid = waitpid(-1, &status, WNOHANG);
+
+        if (pid == 0) {
+            return;
+        }
+
+        if (pid == -1) {
+            err = ngx_errno;
+
+            if (err == NGX_EINTR) {
+                continue;
+            }
+
+            if (err == NGX_ECHILD && one) {
+                return;
+            }
+
+            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,
+                          "waitpid() failed");
+            return;
+        }
+
+        one = 1;
+
+        ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
+                      "process " PID_FMT " exited with code %d", pid, status);
+
+        /* TODO: restart handler */
+
+#if 0
+        ngx_msleep(2000);
+#endif
+
+#if 0
+        ngx_spawn_process(ngx_cycle->log);
+#endif
+    }
+}
diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h
index 60689ba..15d9c0d 100644
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -2,7 +2,13 @@
 #define _NGX_PROCESS_H_INCLUDED_
 
 
+typedef pid_t       ngx_pid_t;
+
 #define ngx_getpid  getpid
 
 
+int ngx_spawn_process(ngx_log_t *log);
+void ngx_sigchld_handler(int signo);
+
+
 #endif /* _NGX_PROCESS_H_INCLUDED_ */