#!/bin/sh
: ; exec klone $0 "$@"
; The above line allows not to embed the exact path of the klone executable

;;Skeleton of a typical klone script

(setq args (getopts "USAGE: %0 [options]
copies stdin to stdout, at maximum rate of N k/s (default 100) "
    ("-v" () verbose "verbose operation")
    ("-r" rate rate "max copy rate in k/s. Defaults to 100")
;; --- Hidden Options ---
    ("-debug" () enter-debugger-on-error "enter klone debugger on error"
    :hidden t)
    ("-stackdump" () stackdump-on-error "verbose stack dump on error"
    :hidden t)
))

(if enter-debugger-on-error (kdb t))
(if stackdump-on-error (stack-dump-on-error t))

rate = (if rate (Real rate) 100.0)
(if (<= rate 0) rate = 100.0)

(defun slow-pipe (rate in out &aux
    (bufsize 1024)
    (t1 (get-internal-run-time))
    buffer
    elapsed-time
    remaining-time
    alloted-time
  )
  (catch 'EOF
    (while (setq buffer (read-chars bufsize in))
      t2 = (get-internal-run-time)
      elapsed-time = (- t2 t1)
      alloted-time = (/ bufsize rate)
      remaining-time = (- alloted-time elapsed-time)
      (if (> remaining-time 0) (select :timeout remaining-time))
      (write-chars buffer () out)
      (verbose? "  %0 bytes in %1 ms %2" bufsize elapsed-time
	(if (> remaining-time 0) (PF String "(waiting %0 ms)" remaining-time)
	  "(no wait)"
      ))
      (if (< elapsed-time 400) bufsize = (* bufsize 2)
	(> elapsed-time 2000) bufsize = (/ bufsize 2)
      )
      t1 = t2
  ))
)

(defun main (&aux
  )
  (slow-pipe rate *stdin* *stdout*)
)

(main)

;;; EMACS MODES
;;; Local Variables: ***
;;; mode:lisp ***
;;; End: ***

