;;; -*- Mode:LISP; Package:SI; Readtable:CL; Base:10 -*- ;;; Printer type :UNIX-CHAOS-EVAL-PRINTER ;;; The printer spec (:unix-chaos-eval-printer host . options) ;;; Options: ;;; :PRINT, defaults to "/usr/bin/lpr", format string takes the filename ;;; :STATUS, is the command string to get status; if not supplied, you can't ;;; get the status ;;; ;;; Useful options: ;;; System V Unix Imagen software ;;; :PRINT "/usr/imagen/imprint -h '~A' -L -l60 2>/tmp/ierror" :STATUS "/usr/imagen/ipq" ;;; 4.2bsd Imagen software, using printer called im1 ;;; :PRINT "/usr/local/bin/imprint -h '~A' -L -l60 2>/tmp/ierror" :STATUS "/usr/ucb/lpq" ;;; 4.2bsd, using standard software ;;; :PRINT "/usr/ucb/lpr -J '~A'" :STATUS "/ucb/ucb/lpq" ;;; System V, using standard software ;;; :PRINT "/usr/bin/lpr" (defun check-for-text-type (format) (unless (eq format :text) (ferror "Only ~S format is supported by this software, not ~S." :text FORMAT))) (defun check-unix-printer-spec (printer) (unless (and (consp printer) (cdr printer)) (ferror "You can't use just ~S as a Unix printer spec." printer))) (defun (:property :unix-chaos-eval-printer print-file) (printer file-name &rest args) (with-open-file-case (file-stream file-name :direction :input) (fs:file-error (format *error-output* "~&Error in opening file: ") (send file-stream :report *error-output*)) (:no-error (apply #'unix-chaos-eval-print-stream printer file-stream :file-name (send file-stream :truename) args)))) (defprop :unix-chaos-eval-printer unix-chaos-eval-print-stream print-stream) (defconst unix-chaos-eval-printer-rfc-string "EVAL /usr/imagen/imprint -L -h -n \"~a\" 1>/dev/null 2>/dev/null") (defun unix-chaosnet-eval-stream (printer eval-arg-string &rest options) (apply #'chaos:open-stream (second printer) (string-append "EVAL " eval-arg-string) options)) (defun unix-chaos-eval-print-stream (printer from-stream &key (format :text) (file-name "Stream Output") &allow-other-keys) (check-for-text-type format) (check-unix-printer-spec printer) (with-open-stream-case (stream (unix-chaosnet-eval-stream printer (format nil (or (get (cdr printer) :print) "/usr/bin/lpr") file-name) :direction :output)) (error (format *error-output* "~&Error: ") (send stream :report *error-output*)) (:no-error (do ((c (read-char from-stream nil) (read-char from-stream nil))) ((null c)) (case c (#\epsilon (read-char from-stream)) ; skip font speficier (#\newline (send stream :tyo #o12)) (#\tab (send stream :tyo #o11)) (#\overstrike (send stream :tyo #o10)) (#\page (send stream :tyo #o14)) (t (send stream :tyo c))))))) (defun copy-from-unix-stream-until-eof (from-stream to-stream) (do ((c (read-char from-stream nil) (read-char from-stream nil))) ((null c)) (case c (#\newline (send to-stream :tyo #o12)) (#\line (send to-stream :tyo #\newline)) (t (send to-stream :tyo c))))) (defun get-unix-chaos-eval-printer-status (printer &optional (report-stream *standard-output*)) (check-unix-printer-spec printer) (fresh-line report-stream) (let ((contact (get (cdr printer) :status))) (if contact (with-open-stream-case (stream (unix-chaosnet-eval-stream printer contact :ascii-translation t :direction :input)) (error (format *error-output* "Error: ") (send stream :report *error-output*)) (:no-error (copy-from-unix-stream-until-eof stream report-stream))) (format *error-output* "~&Cannot get status of this printer.")))) (setf (get :unix-chaos-eval-printer print-status) 'get-unix-chaos-eval-printer-status) ;;; Yet another workaround. :TYPE is the real of printer at the other end. ;;; :PRINT is just a command, not a FORMAT string. (defun queue-via-unix-eval (printer operation args) (let ((handler (get (getf printer :type) 'use-supplied-stream))) (unless handler (error "Can't do ~S on ~A." operation printer)) (let ((stream nil)) (unwind-protect (progn (setq stream (unix-chaosnet-eval-stream printer (or (get (cdr printer) :print) "/usr/bin/lpr") :direction :output)) (apply handler stream operation args)) (close stream :abort t))))) (defun (:queue-via-unix si:print-stream) (printer &rest args) (check-unix-printer-spec printer) (queue-via-unix-eval printer :print-stream args)) (defun (:queue-via-unix si:print-file) (printer &rest args) (check-unix-printer-spec printer) (queue-via-unix-eval printer :print-file args)) (defun (:queue-via-unix si:print-bit-array) (printer &rest args) (check-unix-printer-spec printer) (queue-via-unix-eval printer :print-bit-array args)) (setf (get :queue-via-unix 'print-status) 'get-unix-chaos-eval-printer-status)