rackout-system.rkt
#lang racket/base
;; Copyright Neil Van Dyke.  See file "info.rkt".

(require racket/system
         (planet neil/sudo))

(provide system-command/ignored-output)
(define (system-command/ignored-output
         #:error-name (error-name 'system-command/ignored-output)
         #:sudo?      (sudo? #f)
         #:command    command
         #:args       (args '()))
  (let ((stdout-ob (open-output-bytes))
        (stderr-ob (open-output-bytes))
        (stdin-ib  (open-input-bytes #"")))
    
    (let* ((exit-code    (parameterize ((current-output-port stdout-ob)
                                        (current-error-port  stderr-ob)
                                        (current-input-port  stdin-ib))
                           (apply (if sudo?
                                      system*/exit-code/sudo
                                      system*/exit-code)
                                  command
                                  args)))
           (stdout-bytes (get-output-bytes stdout-ob))
           (stderr-bytes (get-output-bytes stderr-ob)))
      (if (zero? exit-code)
          (void)
          (error error-name
                 "command ~S had non-zero exit code (exit-code ~S, stderr ~S, stdout ~S)"
                 (cons command args)
                 exit-code
                 stderr-bytes
                 stdout-bytes)))))

(provide system-command/stdout-bytes)
(define (system-command/stdout-bytes
         #:error-name     (error-name 'system-command/stdout-bytes)
         #:sudo?          (sudo? #false)
         #:stderr-ignore? (stderr-ignore? #false)
         #:command        command
         #:args           (args '()))
  (let ((stdout-ob (open-output-bytes))
        (stderr-ob (open-output-bytes))
        (stdin-ib  (open-input-bytes #"")))
    
    (let* ((exit-code    (parameterize ((current-output-port stdout-ob)
                                        (current-error-port  stderr-ob)
                                        (current-input-port  stdin-ib))
                           (apply (if sudo?
                                      system*/exit-code/sudo
                                      system*/exit-code)
                                  command
                                  args)))
           (stdout-bytes (get-output-bytes stdout-ob))
           (stderr-bytes (get-output-bytes stderr-ob)))
      (if (zero? exit-code)
          (if (or stderr-ignore? (equal? #"" stderr-bytes))
              stdout-bytes
              (error error-name
                     "command ~S had stderr output (exit-code ~S, stderr ~S, stdout ~S)"
                     (cons command args)
                     exit-code
                     stderr-bytes
                     stdout-bytes))
          (error error-name
                 "command ~S had non-zero exit code (exit-code ~S, stderr ~S, stdout ~S)"
                 (cons command args)
                 exit-code
                 stderr-bytes
                 stdout-bytes)))))

;; (define (system-command/stdout-bytes
;;          #:error-name (error-name 'system-command/stdout-bytes)
;;          #:sudo?      (sudo? #f)
;;          #:command    command
;;          #:args       (args '()))
;;   (let ((stdout-ob (open-output-bytes))
;;         (stderr-ob (open-output-bytes))
;;         (stdin-ib  (open-input-bytes #"")))
;;     (let* ((exit-code    (parameterize ((current-output-port stdout-ob)
;;                                         (current-error-port  stderr-ob)
;;                                         (current-input-port  stdin-ib))
;;                            (apply (if sudo?
;;                                       system*/exit-code/sudo
;;                                       system*/exit-code)
;;                                   command
;;                                   args)))
;;            (stdout-bytes (get-output-bytes stdout-ob))
;;            (stderr-bytes (get-output-bytes stderr-ob)))
;;       (if (zero? exit-code)
;;           (if (equal? #"" stderr-bytes)
;;               stdout-bytes
;;               (error error-name
;;                      "command ~S had stderr output (exit-code ~S, stderr ~S, stdout ~S)"
;;                      (cons command args)
;;                      exit-code
;;                      stderr-bytes
;;                      stdout-bytes))
;;           (error error-name
;;                  "command ~S had non-zero exit code (exit-code ~S, stderr ~S, stdout ~S)"
;;                  (cons command args)
;;                  exit-code
;;                  stderr-bytes
;;                  stdout-bytes)))))

(provide system-command/stdout-line-strings)
(define (system-command/stdout-line-strings
         #:error-name (error-name 'system-command/stdout-line-strings)
         #:sudo?      (sudo? #f)
         #:command    command
         #:args       (args '()))
  (let ((stdout-bytes (system-command/stdout-bytes
                       #:error-name error-name
                       #:sudo?      sudo?
                       #:command    command
                       #:args       args)))
    (regexp-split #rx"\n" stdout-bytes)))