This file is indexed.

/usr/share/scsh-0.6/scsh/sighandlers.scm is in scsh-common-0.6 0.6.7-8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
;;; Copyright (c) 1993 by Olin Shivers.
;;; Signal handler system

;;; The principal trickiness here is that we have to interface to Unix signals
;;; *through* an intermediate interface, the S48 vm's idea of interrupts.
;;; So there is a difference between delivering a signal to the underlying
;;; Unix process and delivering it to the program that runs on the VM.
;;;
;;; One effect is that we have two separate codes for the same thing -- the
;;; Unix signal code, and the S48 interrupt value. E.g., SIGNAL/TSTP and
;;; INTERRUPT/TSTP.

;;; These system calls can return EINTR or restart. In order for the S48 vm's
;;; interrupt system to detect a signal and invoke the handler, they *must*
;;; return EINTR, and this must cause a return from C to Scheme.
;;;
;;; open close dup2 accept connect
;;; read recv recvfrom recvmsg
;;; write send sendto sendmsg
;;; select
;;; wait
;;; fcntl* ioctl
;;; sigsuspend
;;; HP-UX, but I don't use: poll lockf msem_lock msgsnd msgrcv semop
;;; 
;;; * Only during a F_SETLKW
;;;
;;; From rts/interrupt.scm (package interrupts, interface interrupts-interface)
;;;     WITH-INTERRUPTS INTERRUPT-HANDLERS SET-ENABLED-INTERRUPTS !
;;;	ENABLED-INTERRUPTS
;;; Must define WITH-INTERRUPTS* and WITH-INTERRUPTS.

;;; Map a Unix async signal to its S48 interrupt value.
;;; -1 => Not defined.
(import-lambda-definition %signal->interrupt (sig) "sig2interrupt")

(define (signal->interrupt sig)
  (let ((int (%signal->interrupt sig)))
    (if (>= int 0) int
	(error "Unix signal has no Scheme 48 interrupt." sig))))


(define (interrupt-enabled? int mask)
  (interrupt-in-set? int mask))

(define (interrupt-enable int mask)
  (insert-interrupt int mask))

(define *enabled-interrupts* 
   (let lp ((i 0) (mask 0))
     (if (= i number-of-interrupts)
	 mask
	 (lp (+ i 1) (interrupt-enable i mask)))))

(define (enabled-interrupts) *enabled-interrupts*)

(define *pending-interrupts* 0)

(define (interrupt-pending? int)
  (interrupt-in-set? int *pending-interrupts*))

(define (make-interrupt-pending int)
  (set! *pending-interrupts* (insert-interrupt int *pending-interrupts*)))

(define (remove-pending-interrupt int)
  (set! *pending-interrupts* (remove-interrupt int *pending-interrupts*)))

;;; I'm trying to be consistent about the ! suffix -- I don't use it
;;; when frobbing process state. This is not a great rule; perhaps I
;;; should change it.
;;; 
;;; I think you should...
(define (set-enabled-interrupts new-enabled-interrupts)
  (let ((old-enabled-interrupts *enabled-interrupts*))
    ;;; set it here so the handlers see the correct value
    (set! *enabled-interrupts* new-enabled-interrupts)
    (do ((int 0 (+ int 1)))
	((= int number-of-interrupts) new-enabled-interrupts)
      (let ((old-state (interrupt-enabled? int old-enabled-interrupts))
	    (new-state (interrupt-enabled? int new-enabled-interrupts)))
	(if (and (not old-state) new-state (interrupt-pending? int))
	    (begin
	      (remove-pending-interrupt int)
	      (call-interrupt-handler int)))))))

(define-simple-syntax (with-enabled-interrupts interrupt-set body ...)
   (begin 
     (with-enabled-interrupts* interrupt-set (lambda () body ...))))

(define (with-enabled-interrupts* interrupt-set thunk)
  (let ((before *enabled-interrupts*))
    (set-enabled-interrupts interrupt-set)
    (let ((return (thunk)))
      (set-enabled-interrupts before)
      return)))

(define *interrupt-handlers-vector*)
  
(define (install-fresh-interrupt-handlers-vector!)
  (set! *interrupt-handlers-vector* (make-vector number-of-interrupts #t)))

(define (interrupt-handlers-vector)
  *interrupt-handlers-vector*)

(define (interrupt-handler-ref int)
  (if (or (< int 0) (>= int number-of-interrupts))
      (error "ill signum in interrupt-handler-ref" int)
      (vector-ref *interrupt-handlers-vector* int)))

(define (call-interrupt-handler int)
  (let ((handler (interrupt-handler-ref int)))
    (case handler
      ((#t) ((vector-ref default-int-handler-vec int) (enabled-interrupts)))
      ((#f) (if #f #f))
      (else (handler (enabled-interrupts))))))
    

;;; Get/Set signal handlers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; When you set a signal's handler to "default," if the default for that
;;; signal is something other than "ignore," we actually install this guy.
;;; When he is called by the S48 interrupt system, he'll magically make
;;; the default action happen (by calling C code that *really* sets the
;;; handler to SIGDFL, and then re-sending the signal). This basically
;;; terminates the process, since if the default isn't "ignore," it's always
;;; "terminate" of some kind. Doing it this way means the exit code given
;;; to our waiting parent proc correctly reflects how we died, and also
;;; makes the core dump happen if it should. Details, details.

(import-lambda-definition %do-default-sigaction (signal) "do_default_sigaction")

(define default-int-handler-vec
  ;; Non-Unix-signal interrupts just get their default values from
  ;; the current value of I-H.
  (let ((v (make-vector 32)))
    (do ((sig 31 (- sig 1)))			; For each Unix signal
	((< sig 0))				; make & install a default
      (let ((i (%signal->interrupt sig)))	; signal handler.
	(if (>= i 0)	; Don't mess with non-signal interrupts.
	    (vector-set! v i (if (memv sig signals-ignored-by-default)
				 (lambda (enabled-interrupts) #f)
				 (lambda (enabled-interrupts)
				   (%do-default-sigaction sig)))))))
    v))


;;; HANDLER is #f (ignore), #t (default), or a procedure taking an integer
;;; argument. The interrupt is delivered to a procedure by (1) setting the
;;; ENABLED-INTERRUPTS register to 0 (i.e., blocking all interrupts), and (2)
;;; applying the procedure to the previous value of the ENABLED-INTERRUPTS
;;; register. If the procedure returns normally, the ENABLED-INTERRUPTS 
;;; register will be restored to its previous value.

(define (set-interrupt-handler int handler)
  (if (or (< int 0) (>= int number-of-interrupts))
      (error "ill signum in set-interrupt-handler!" int)
      (let ((old-handler (vector-ref *interrupt-handlers-vector* int)))
	(vector-set! *interrupt-handlers-vector* int handler)
	old-handler)))

(define (interrupt-handler int)
  (interrupt-handler-ref int))

(define (with-scsh-sighandlers interactive? thunk)
  (install-fresh-interrupt-handlers-vector!)
  (do ((sig 32 (- sig 1)))
      ((< sig 0))
    (let ((i (%signal->interrupt sig)))
      (if (not (or (= i -1)
		   (= sig signal/alrm)))	; Leave alarm handler alone.
	  (set-interrupt-handler 
	   i
	   #t))))
  (let ((scsh-initial-thread  ((structure-ref threads-internal current-thread))))
    (if (not (eq? (thread-name scsh-initial-thread)
		  'scsh-initial-thread))
	(error "sighandler did not find scsh-initial-thread, but"
	       scsh-initial-thread))
    
    ;; Note: this will prevent any other system to work, since it pushes
    ;; a new command level !
    (if interactive?
	(set-interrupt-handler interrupt/keyboard
			       (lambda stuff
				 ((structure-ref threads-internal schedule-event) 
				  scsh-initial-thread
				  (enum  
				   (structure-ref threads-internal event-type) 
				   interrupt)
				  (enum interrupt keyboard))))))
  (run-as-long-as
   deliver-interrupts
   thunk 
   (structure-ref threads-internal spawn-on-root)
   'deliver-interrupts))

(define (deliver-interrupts)
  (let lp ((last ((structure-ref sigevents most-recent-sigevent))))
    (let* ((event ((structure-ref sigevents next-sigevent-set)
		   last full-interrupt-set))
	   (interrupt ((structure-ref sigevents sigevent-type) event)))
      (if (interrupt-enabled? interrupt (enabled-interrupts))
	  (call-interrupt-handler interrupt)
	  (make-interrupt-pending interrupt))
      (lp event))))

;;; Dealing with synchronous signals

(import-lambda-definition ignore-signal (sig) "ignore_signal")

(import-lambda-definition handle-signal-default (sig) "handle_signal_default")
    
;;; I am ashamed to say the 33 below is completely bogus.
;;; What we want is a value that is 1 + max interrupt value.

(define int->sig-vec
  (let ((v (make-vector 33 #f)))
    (do ((sig 32 (- sig 1)))
	((< sig 0))
      (let ((i (%signal->interrupt sig)))
	(if (not (= i -1)) (vector-set! v i sig))))
    v))

(define (int->signal i) (and (<= 0 i 32) (vector-ref int->sig-vec i)))