File: process.l

package info (click to toggle)
euslisp 9.31%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,448 kB
  • sloc: ansic: 41,610; lisp: 3,339; makefile: 286; sh: 238; asm: 138; python: 53
file content (213 lines) | stat: -rw-r--r-- 7,348 bytes parent folder | download | duplicates (2)
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
;;;
;;;	process.l
;;;	unix process handling functions
;;;	1987-Apr
;;;	(c) Toshihiro Matsui, Electrotechnical Laboratory
;;;

(eval-when (load eval)
(in-package "LISP")
(export '(cd pwd ez piped-fork popen xfork dir directory rusage))

(defmacro cd (&optional (dir (unix:getenv "HOME")))
    (if (symbolp dir) (setq dir (string-downcase (string dir))))
    `(unix:chdir ,dir))
(defun pwd () (unix:getwd))
(defun ez (&optional (key (read-from-string (unix:getenv "LOGINPID") )))
   (let ((msg1 (unix:msgget (+ key #x50000)))
	 (msg2 (unix:msgget (+ key #x60000)))
	 (buf (instantiate string 256))
	 (inputs nil) (msg nil))
      (unix:msgsnd msg1 "" 0 2)	;start ez
      (while (not (equal (car (setq msg (unix:msgrcv msg2 buf 0))) 99))
	  (setq inputs (nconc inputs (list (subseq buf 0 (cadr msg))))))
      (if (null inputs) (return-from ez nil))
      (setq inputs (make-string-input-stream
			 (apply 'concatenate string inputs)))
      (while (null (equal (setq msg (read inputs nil :eof)) :eof))
         (print (eval msg)))))


;;; fork a new euslisp and connect it through pipes
;;; First, forked process set up pipes after closing old standard io's.
;;; Then, if exec is given, child process issues exec call to start off
;;; a new program.
;;; If no exec is given, it enters read-eval-print loop through the pipes.
;;; Piped-fork returns an io-stream whose components are two pipes to
;;; the parent process.
;;;
;;;	modified on 1987-Nov-21 to comform to the new toplevel by T.Matsui
;;;	December, 1999; unix:system is used instead of exec.
;;;
;;; Note that although standard-io is switched to pipes, the tty remains
;;; as the control terminal and signals raised from the keyboard (^C) are 
;;; sent to the child euslisp.


(defun piped-fork (&optional (exec) &rest args)
  (let ((p1 (unix:pipe)) (p2 (unix:pipe)) (pid (unix:fork)) ifd ofd is os ts tty)
    (unless (streamp p2)
	(error (unix:syserrlist (- p2))))
    (if (= pid 0)
	(progn	;; child
	     (close *standard-input*)
	     (close *standard-output*)
	     (close (p1 . outstream))
	     (close (p2 . instream))
	     (setq ifd (unix:dup (send p1 :infd))    ;fd=0
	    	   ofd (unix:dup (send p2 :outfd)))  ;fd=1
	     ; (setq tty (open "/dev/tty" :direction :io))
	     ; (format tty "stdin=~d stdout=~d~%" ifd ofd)
	     (unix:signal 2 1)	;; SIGINT = SIG_IGN
	     (setq *standard-input*
			 (instance file-stream :init ifd "pipe" :input)
		   *standard-output*
			 (instance file-stream :init ofd "pipe" :output)
		   *terminal-io*
			 (make-two-way-stream *standard-input*
					      *standard-output*))
	     (cond ((stringp exec)
		     (if (position #\space exec)
			 (unix:system exec)
			 (apply #'unix:exec exec args)))
		   ((functionp exec)
		     (apply exec args)
		     (throw :eusexit t))
		   (t  (while t 
			  (catch 0
			      (setq *replevel* 0)
			      (reploop "")
			      (throw :eusexit nil)) )  )
		  )
	;; Matsui is not very sure whether the child process should exit here.
        ;; Okada suppose we should use _exit not exit.
	(unix::_exit 1))
    (let ((io (instantiate io-stream)) in out)
      (if *debug* (format t ";; child_pid=~D~%" pid))
      (setf (get io :pid) pid)
      (setq in (p2 . instream)
	    out (p1 . outstream))
      (setq (io . instream) in
	    (io . outstream) out)
      (setf (get in :pid) pid)
      (close (p1 . instream))
      (close (p2 . outstream))
      io)
    ))
  )

(defun popen (exec &rest args)
  (let ((p1 (unix:pipe)) (p2 (unix:pipe))
        pid)
    ;; the next call used to be unix::fork1 that was available only on  Solaris
    (if (= (setq pid (unix::fork)) 0)
      (progn
        (close *standard-input*)
        (close *standard-output*)
        (close (p1 . outstream))
        (close (p2 . instream))
        (unix:dup (send p1 :infd))      ;fd=0
        (unix:dup (send p2 :outfd))     ;fd=1
	(if (position #\space exec)
	    (unix:system exec)
	    (apply #'unix:exec exec args)) )
      (let ((io (instantiate io-stream)) in out)
        (if *debug* (format t ";; child_pid=~D~%" pid))
        (setf (get io :pid) pid)
        (setq in (p2 . instream)
              out (p1 . outstream))
        (setq (io . instream) in
              (io . outstream) out)
        (setf (get in :pid) pid)
        (close (p1 . instream))
        (close (p2 . outstream))
        io))
    ))


(defun xfork (exec &key (stdin  *standard-input*)
			(stdout *standard-output*)
			(stderr *error-output*)
			(args nil))
   (let ((pid (unix:fork)) (ios))
      (cond ((= pid 0)  ;child proc
	     (unless (= (send stdin :infd) 0)
		(unix:dup2 (send stdin :infd) 0))
	     (unless (= (send stdout :outfd) 1)
		(unix:dup2 (send stdout :outfd) 1))
	     (unless (= (send stderr :outfd) 2)
		(unix:dup2 (send stderr :outfd) 2))
	     (if (position #\space exec)
		 (unix:system exec)
		 (apply #'unix:exec exec args))
	     (error "exec") (exit 1))
            (t (if *debug* (format t ";; child_pid=~D~%" pid))))
      (setq ios (instance io-stream :init
			(send stdout :instream) (send stdin :outstream)))
;      (if (io-stream-p stdin) (close (send stdin :instream)))
;      (if (io-stream-p stdout) (close (send stdout :outstream)))
      ios)
    )
;;
;; slower but more complete "directory"
;;

#+(or :linux :solaris2 :cygwin :alpha)
   (setf (symbol-function 'directory) (symbol-function 'unix::readdir))
#-(or :linux :solaris2 :cygwin :alpha)
 (defun directory (&optional (dir "."))
   (let ((fnlist) (ls) (eof (cons nil nil)) (fn))
      (setq ls (piped-fork "ls" "-a" dir))
      (while (not (eq (setq fn (read-line ls nil eof)) eof))
	 (push fn fnlist))
      (nreverse fnlist))) 

(defun dir (&optional (dir "."))
   (let ((dirs (sort (directory dir) #'string<)))
     (tprint dirs
	     (max 16 (1+ (apply #'max (mapcar #'length dirs))))
             0 80 )))

(defun rusage (&optional (who 0) (s t))
  (let ((r (unix:getrusage who))
	(psize (/ (unix:getpagesize) 1024)))
     (format s "user time ~f sec~%system time ~f sec~%" (pop r) (pop r))
     (format s "max resident core ~d Kb~%" (* (pop r) psize))
     (pop r)	;ru_ixrss
     (format s "integral resident   ~d Kb~%" (* (pop r) psize))
     (pop r)	; ru_isrss
     (format s "page faults without I/O ~d ~%" (pop r))
     (format s "page faults with I/O   ~d ~%" (pop r))
     (format s "swaps         ~d ~%" (pop r))
     (format s "input op.     ~d ~%" (pop r))
     (format s "output op.    ~d ~%" (pop r))
     (format s "message sent  ~d ~%" (pop r))
     (format s "message rcvd  ~d ~%" (pop r))
     (format s "signals       ~d ~%" (pop r))
     (format s "volutary sw.  ~d ~%" (pop r))
     (format s "involutary sw.~d ~%" (pop r))))


(defun xterm-window (&optional (cmnd "xterm") (port))
  (let ((ptyname) (c #\p) (n 0) (ptystream) (fd) (pipe))
    (while (null ptystream)
	(setq ptyname (format nil "/dev/pty~c~1,1x" c n) )
	;; (print ptyname)
	(setq ptystream
	      (open ptyname :if-does-not-exist nil  :direction :io ))
	(unless ptystream
	   (incf n)
	   (when (= n 16)
	      (incf c)   (setq n 0)
	      (if (= c #\z) (return-from xterm-window nil))) )
	)
    (when (> (setq fd (send ptystream :infd)) 9)
	(close ptystream) (return-from xterm-window nil))
    (send ptystream :name ptyname)
    (setq pipe (piped-fork cmnd (format nil "-S~c~1,1x~1d" c n 0)) )
    (list   ptystream pipe)))


(provide :process "@(#)$Id$")