#!/bin/sh
: ; exec klone $0 "$@"
; The above line finds the klone executable in the $PATH

(if (file-stats "/usr/5bin/touch")
  (setq touch-SYSV "/usr/5bin/touch")
  (file-stats "/sbin/touch")
  (setq touch-SYSV "/sbin/touch")

  (progn
    (print-format *standard-error* "Sorry, you must have a SYSV touch to run Z2z\n")
    (exit 1)
))

(setq Z2z-usage-text
  "USAGE: Z2z files...
converts files compressed by compress to GZIP compression
if directories are given, recursively re-compresses their contents
Exemple: Z2z ~     recompresses all your files")

(eval `(setq *arguments* (getopts ,Z2z-usage-text
  (-q 0 quiet "quiet operation")
)))

(setq verbose (not quiet))

;; usage printed if called without arguments
(if (not *arguments*) (progn
    (print-format *standard-error* "%0\n" Z2z-usage-text)
    (exit 1)
))

(setq temp-file (+ "/tmp/Z2z." (String *current-process-id*)))

;; Z2z files process each file
(defun toplevel ()
  (dolist (file *arguments*)
    (recompress-file file)
))

(defun recompress-file (file-Z &aux
    base
    dest-file
    file-date
    success
    size-o
    size-n
  )
  (if (setq base (match "^(.*)[.]Z$" file-Z 1))
    t
    (setq base (match "^(.*)[.]CZ$" file-Z 1))
    (nconc base ".cpio")
  )
  (if base  (progn			; Ok, .Z file
      (setq dest-file (+ base ".gz"))
      (setq file-date (seconds-to-date (getn (file-stats file-Z) 'mtime)))
      (if file-date (progn
	  (if verbose (progn
	      (print-format ()
		"%0 (%1).Z ==> " base
		(setq size-o (get (file-stats file-Z) 'size 0)) dest-file
	      )
	      (flush *standard-output*)
	  ))
	  
	  ;; recompress
	  (setq success
	    (wait (system (+ "gzip -d < " file-Z " | gzip -9> " dest-file)))
	  )
	)
	(progn
	  (setq success 'nofile)
	  (print-format *standard-error* "Cannot open %0\n" file-Z)
      ))
      
      (if (= 0 success)
	(with (count 60)		;compute dest size, but retry (NFS?)
	  (setq size-n (get (file-stats dest-file) 'size 0))
	  (while (and (= 0 size-n) (> count 0))
	    (wait (system (list "sleep" "1")))
	    (setq count (- count 1))
	    (setq size-n (get (file-stats dest-file) 'size 0))
	  )
	  (if (= 0 size-n)
	    (setq success 1)
      )))
      
      (if (/= 0 success)		;failed
	(progn
	  (if (/= 'nofile success) (progn
	      (if verbose (print-format () "ERROR!\n"))
	      (print-format *standard-error*
		"Z2z ERROR: Recompression of %0 failed\n" file-Z)
	      (system (list "rm" "-f" dest-file))
	  ))
	)
	(progn				;OK
	  (if verbose
	    (print-format ()
	      "(%0).gz. Gained: %1 (%2%%)\n"
	      size-n (- size-o size-n)
	      (if (/= 0 size-o) (/ (* 100 (- size-o size-n)) size-o) "??")
	    )
	  )
	  (system (list "rm" "-f" file-Z))
	  
	  (if (not (and file-date
		(= 0 (wait (system (list touch-SYSV "-cf"
		      ;; mmddhhmmyy
			(+ "" (itoa2 (get file-date 1))
			  (itoa2 (get file-date 2))
			  (itoa2 (get file-date 3))
			  (itoa2 (get file-date 4))
			  (itoa2 (get file-date 0))
			)
			dest-file
	    ))))))
	    (print-format *standard-error* "Could not reset date of %0 to %1\n"
	      dest-file
	      (+ "" (itoa2 (get file-date 1))
		(itoa2 (get file-date 2))
		(itoa2 (get file-date 3))
		(itoa2 (get file-date 4))
		(itoa2 (get file-date 0))
	      )
    )))))
					; recurse on dirs
    (if (= 'directory (file-type file-Z))
      (with (old-dir *current-directory*)
	(if (setq *current-directory* file-Z) (progn
	    (if verbose
	      (print-format () "Compressing files in %0\n" *current-directory*)
	    )
	    (dolist (file (directory))
	      (recompress-file file)
	    )
	    (setq *current-directory* old-dir)
    ))))
))

;; takes a positive int and retuns it as a string on 2 chars

(defun itoa2 (n)
  (if (< n 10)
    (+ "0" (String n))
    (< n 100)
    (String n)
    (String (mod n 100))
))    

;; end of definitions, start the job
(toplevel)

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