daemon.scm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. ;;; daemon.scm --- Main module for Guile-Daemon
  2. ;; Copyright © 2016, 2018 Alex Kost <alezost@gmail.com>
  3. ;; This file is part of Guile-Daemon.
  4. ;; Guile-Daemon is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;;
  9. ;; Guile-Daemon is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with Guile-Daemon. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; This module provides main subroutines to start guile-daemon.
  18. ;;; Code:
  19. (define-module (daemon)
  20. #:use-module (ice-9 match)
  21. #:use-module (system repl server)
  22. #:use-module (daemon ui)
  23. #:use-module (daemon utils)
  24. #:export (main))
  25. ;; FIFO file must be writable only by a user: the daemon evaluates an
  26. ;; arbitrary Guile code passed to the FIFO file, so it is extremely
  27. ;; dangerous to allow other users to write to this file.
  28. (define %fifo-permissions #o600)
  29. (define (load-config-file file-name)
  30. (if (file-exists? file-name)
  31. (catch #t
  32. (lambda ()
  33. (primitive-load file-name))
  34. (lambda (error . args)
  35. (print-error "Configuration file has not been loaded:")
  36. (apply report-error error args)))
  37. (print-error "Configuration file does not exist: ~a" file-name)))
  38. (define (load-fifo-file file-name)
  39. (catch #t
  40. (lambda ()
  41. (primitive-load file-name))
  42. (lambda (error . args)
  43. (match error
  44. ('quit ; (exit) or (quit) is written to the FIFO file
  45. (exit))
  46. ('system-error
  47. (print-error "Something wrong with the FIFO file:")
  48. (apply report-error error args)
  49. (exit 1))
  50. (_
  51. (print-error "The code from the FIFO file has not been loaded:")
  52. (apply report-error error args))))))
  53. (define (read-eval-loop file-name)
  54. "Read and evaluate Guile code from FIFO FILE-NAME in a loop."
  55. (load-fifo-file file-name)
  56. (read-eval-loop file-name))
  57. (define (suitable-fifo-file? file-name)
  58. "Return #t if FILE-NAME is FIFO file owned by the current user with
  59. the right permissions."
  60. (catch #t
  61. (lambda ()
  62. (let ((s (stat file-name)))
  63. (and (= (stat:uid s) (getuid))
  64. (eq? (stat:type s) 'fifo)
  65. (= (stat:perms s) %fifo-permissions))))
  66. (const #f)))
  67. (define (make-fifo-file-maybe file-name)
  68. "Make FIFO FILE-NAME if it does not exist."
  69. (unless (suitable-fifo-file? file-name)
  70. (catch #t
  71. (lambda ()
  72. (delete-file-maybe file-name)
  73. (ensure-directory (dirname file-name))
  74. (mknod file-name 'fifo %fifo-permissions 0))
  75. (lambda (error . args)
  76. (print-error "Couldn't create FIFO file ~a:" file-name)
  77. (apply report-error error args)
  78. (exit 1)))))
  79. (define (start-server file-name)
  80. "Create socket file at FILE-NAME and spawn REPL server there."
  81. (catch #t
  82. (lambda ()
  83. (delete-file-maybe file-name)
  84. (ensure-directory (dirname file-name))
  85. (spawn-server (make-unix-domain-server-socket #:path file-name)))
  86. (lambda (error . args)
  87. (print-error "Couldn't start server over socket file ~a:"
  88. file-name)
  89. (apply report-error error args))))
  90. ;;; Main
  91. (define (set-locale)
  92. (catch #t
  93. (lambda _ (setlocale LC_ALL ""))
  94. report-error))
  95. (define (main name . args)
  96. (set-locale)
  97. (let* ((opts (parse-args args))
  98. (config (assoc-ref opts 'config-file))
  99. (fifo (assoc-ref opts 'fifo-file))
  100. (socket (assoc-ref opts 'socket-file)))
  101. (start-server socket)
  102. (make-fifo-file-maybe fifo)
  103. (load-config-file config)
  104. (read-eval-loop fifo)))
  105. ;;; daemon.scm ends here