#!MUNGERPATH

; Copyright (c) 2006, James Bailie.
; All rights reserved.
; 
; Redistribution and use in source form, with or without
; modification, are permitted provided that the following conditions are met:
; 
;     * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
;     * The name of James Bailie may not be used to endorse or promote 
; products derived from this software without specific prior written permission.
; 
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.

; This script implements an echo server daemon.  It needs to be run as root
; to bind to port 7, then it switches to user "nobody" and services incoming
; connections, forking a new process for each.

; Note that this server echoes whole lines of text.  If the server has to
; wait for more than 5 seconds for data from the client, it spits out any
; data it has read so far.  If it reads 1000 characters without encountering
; a newline, it will spit out the 1000 characters and continue reading.

; The script will not exit unless "listen" or "accept" return an error.  It
; must be killed with SIGKILL.  The server writes its pid to 
; /var/run/echo.munger.pid

(fatal)
(daemonize "echo.munger")

; Must be called after daemonize to get the correct pid,
; because daemonize forks.

(with_output_file "/var/run/echo.munger.pid"
   (print (getpid)))

(defun service_client ()
   (while (stringp (setq line (getline_ub 5)))
      (when line
         (print line)
         (flush_stdout))))

(when (and (fixnump (setq err (listen 7))) (>= err 0))
   (setuid "nobody")

   (while (fixnump (setq err (accept)))

      (if (not (fork))
         (progn
            (stop_listening)
            (service_client)
            (exit 0))

         (resume 0)
         (resume 1))))

(when (stringp err)
   (syslog 'ERROR err)
   (exit 1))

(quit)
