Newer
Older
;;; Unix-creat accepts a file name and a mode. It creates a new file
;;; with name and sets it mode to mode (as for chmod).
(defun unix-creat (name mode)
"Unix-creat accepts a file name and a mode (same as those for
unix-chmod) and creates a file by that name with the specified
permission mode. It returns a file descriptor on success,
or NIL and an error number otherwise.
This interface is made obsolete by UNIX-OPEN."
(declare (type unix-pathname name)
(type unix-file-mode mode))
(int-syscall ("creat" c-string int) name mode))
;;; Unix-dup returns a duplicate copy of the existing file-descriptor
;;; passed as an argument.
(defun unix-dup (fd)
"Unix-dup duplicates an existing file descriptor (given as the
argument) and return it. If FD is not a valid file descriptor, NIL
and an error number are returned."
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
(declare (type unix-fd fd))
(int-syscall ("dup" int) fd))
;;; Unix-dup2 makes the second file-descriptor describe the same file
;;; as the first. If the second file-descriptor points to an open
;;; file, it is first closed. In any case, the second should have a
;;; value which is a valid file-descriptor.
(defun unix-dup2 (fd1 fd2)
"Unix-dup2 duplicates an existing file descriptor just as unix-dup
does only the new value of the duplicate descriptor may be requested
through the second argument. If a file already exists with the
requested descriptor number, it will be closed and the number
assigned to the duplicate."
(declare (type unix-fd fd1 fd2))
(void-syscall ("dup2" int int) fd1 fd2))
;;; Unix-fcntl takes a file descriptor, an integer command
;;; number, and optional command arguments. It performs
;;; operations on the associated file and/or returns inform-
;;; ation about the file.
;;; Operations performed on file descriptors:
(defconstant F-DUPFD 0 "Duplicate a file descriptor")
(defconstant F-GETFD 1 "Get file desc. flags")
(defconstant F-SETFD 2 "Set file desc. flags")
(defconstant F-GETFL 3 "Get file flags")
(defconstant F-SETFL 4 "Set file flags")
#+svr4
(defconstant F-GETOWN 23 "Get owner")
#+linux
(defconstant F-GETLK 5 "Get lock")
#-(or linux svr4)
#+svr4
(defconstant F-SETOWN 24 "Set owner")
#+linux
(defconstant F-SETLK 6 "Set lock")
#+linux
(defconstant F-SETLKW 7 "Set lock, wait for release")
#+linux
(defconstant F-SETOWN 8 "Set owner")
(defconstant FNDELAY #-osf1 #o0004 #+osf1 #o100000 "Non-blocking reads")
(defconstant FAPPEND #-linux #o0010 #+linux #o2000 "Append on each write")
(defconstant FASYNC #-(or linux svr4) #o0100 #+svr4 #o10000 #+linux #o20000
;; doesn't exist in Linux ;-(
#-linux (defconstant FCREAT #-(or hpux svr4) #o1000 #+(or hpux svr4) #o0400
"Create if nonexistant")
#-linux (defconstant FTRUNC #-(or hpux svr4) #o2000 #+(or hpux svr4) #o1000
#-linux (defconstant FEXCL #-(or hpux svr4) #o4000 #+(or hpux svr4) #o2000
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
(defun unix-fcntl (fd cmd arg)
"Unix-fcntl manipulates file descriptors according to the
argument CMD which can be one of the following:
F-DUPFD Duplicate a file descriptor.
F-GETFD Get file descriptor flags.
F-SETFD Set file descriptor flags.
F-GETFL Get file flags.
F-SETFL Set file flags.
F-GETOWN Get owner.
F-SETOWN Set owner.
The flags that can be specified for F-SETFL are:
FNDELAY Non-blocking reads.
FAPPEND Append on each write.
FASYNC Signal pgrp when data ready.
FCREAT Create if nonexistant.
FTRUNC Truncate to zero length.
FEXCL Error if already created.
"
(declare (type unix-fd fd)
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
(type (unsigned-byte 16) arg))
(int-syscall ("fcntl" int int int) fd cmd arg))
;;; Unix-link creates a hard link from name2 to name1.
(defun unix-link (name1 name2)
"Unix-link creates a hard link from the file with name1 to the
file with name2."
(declare (type unix-pathname name1 name2))
(void-syscall ("link" c-string c-string) name1 name2))
;;; Unix-lseek accepts a file descriptor, an offset, and whence value.
(defconstant l_set 0 "set the file pointer")
(defconstant l_incr 1 "increment the file pointer")
(defconstant l_xtnd 2 "extend the file size")
(defun unix-lseek (fd offset whence)
"Unix-lseek accepts a file descriptor and moves the file pointer ahead
a certain offset for that file. Whence can be any of the following:
l_set Set the file pointer.
l_incr Increment the file pointer.
l_xtnd Extend the file size.
"
(declare (type unix-fd fd)
(type (unsigned-byte 32) offset)
(type (integer 0 2) whence))
#-(and x86 freebsd) (int-syscall ("lseek" int off-t int) fd offset whence)
;; Need a 64-bit return value type for this. TBD. For now,
;; don't use this with any 2G+ partitions.
#+(and freebsd x86) (int-syscall ("lseek" int unsigned-long unsigned-long int)
fd offset 0 whence ))
;;; Unix-mkdir accepts a name and a mode and attempts to create the
;;; corresponding directory with mode mode.
(defun unix-mkdir (name mode)
"Unix-mkdir creates a new directory with the specified name and mode.
(Same as those for unix-fchmod.) It returns T upon success, otherwise
NIL and an error number."
(declare (type unix-pathname name)
(type unix-file-mode mode))
(void-syscall ("mkdir" c-string int) name mode))
;;; Unix-open accepts a pathname (a simple string), flags, and mode and
;;; attempts to open file with name pathname.
(defconstant o_rdonly 0 "Read-only flag.")
(defconstant o_wronly 1 "Write-only flag.")
(defconstant o_rdwr 2 "Read-write flag.")
(defconstant o_ndelay #-linux 4 #+linux #o4000 "Non-blocking I/O")
(defconstant o_append #-linux #o10 #+linux #o2000 "Append flag.")
#+(or hpux svr4 linux)
(progn
(defconstant o_creat #-linux #o400 #+linux #o100 "Create if nonexistant flag.")
(defconstant o_trunc #o1000 "Truncate flag.")
(defconstant o_excl #-linux #o2000 #+linux #o200 "Error if already exists.")
(defconstant o_noctty #+linux #o400 #+hpux #o400000 #+(or irix solaris) #x800
"Don't assign controlling tty"))
#+(or hpux svr4)
(defconstant o_nonblock #+hpux #o200000 #+(or irix solaris) #x80
"Non-blocking mode")
#+linux
(progn
(defconstant o_sync #o10000 "Synchronous writes (on ext2)"))
#-(or hpux svr4 linux)
(progn
(defconstant o_creat #o1000 "Create if nonexistant flag.")
(defconstant o_trunc #o2000 "Truncate flag.")
(defconstant o_excl #o4000 "Error if already exists."))
(defun unix-open (path flags mode)
"Unix-open opens the file whose pathname is specified by path
for reading and/or writing as specified by the flags argument.
The flags argument can be:
o_rdonly Read-only flag.
o_wronly Write-only flag.
o_rdwr Read-and-write flag.
o_append Append flag.
o_creat Create-if-nonexistant flag.
o_trunc Truncate-to-size-0 flag.
If the o_creat flag is specified, then the file is created with
a permission of argument mode if the file doesn't exist. An
integer file descriptor is returned by unix-open."
(declare (type unix-pathname path)
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
(type unix-file-mode mode))
(int-syscall ("open" c-string int int) path flags mode))
(defun unix-pipe ()
"Unix-pipe sets up a unix-piping mechanism consisting of
an input pipe and an output pipe. Unix-Pipe returns two
values: if no error occurred the first value is the pipe
to be read from and the second is can be written to. If
an error occurred the first value is NIL and the second
the unix error code."
(with-alien ((fds (array int 2)))
(syscall ("pipe" (* int))
(values (deref fds 0) (deref fds 1))
(cast fds (* int)))))
;;; Unix-read accepts a file descriptor, a buffer, and the length to read.
;;; It attempts to read len bytes from the device associated with fd
;;; and store them into the buffer. It returns the actual number of
;;; bytes read.
(defun unix-read (fd buf len)
"Unix-read attempts to read from the file described by fd into
the buffer buf until it is full. Len is the length of the buffer.
The number of bytes actually read is returned or NIL and an error
number if an error occured."
(declare (type unix-fd fd)
(type (unsigned-byte 32) len))
#+sunos
;; Note: Under sunos we touch each page before doing the read to give
;; the segv handler a chance to fix the permissions. Otherwise,
;; read will return EFAULT. This also bypasses a bug in 4.1.1 in which
;; read fails with EFAULT if the page has never been touched even if
;; the permissions are okay.
(without-gcing
(let* ((page-size (get-page-size))
(1-page-size (1- page-size))
(sap (etypecase buf
(system-area-pointer buf)
(vector (vector-sap buf))))
(end (sap+ sap len)))
(declare (type (and fixnum unsigned-byte) page-size 1-page-size)
(type system-area-pointer sap end)
(optimize (speed 3) (safety 0)))
(do ((sap (int-sap (logand (the (unsigned-byte 32)
(+ (sap-int sap) 1-page-size))
(logxor 1-page-size (ldb (byte 32 0) -1))))
(sap+ sap page-size)))
(declare (type system-area-pointer sap))
(setf (sap-ref-8 sap 0) (sap-ref-8 sap 0)))))
(int-syscall ("read" int (* char) int) fd buf len))
(defun unix-readlink (path)
"Unix-readlink invokes the readlink system call on the file name
specified by the simple string path. It returns up to two values:
the contents of the symbolic link if the call is successful, or
NIL and the Unix error number."
(declare (type unix-pathname path))
(with-alien ((buf (array char 1024)))
(syscall ("readlink" c-string (* char) int)
(let ((string (make-string result)))
(kernel:copy-from-system-area
(alien-sap buf) 0
string (* vm:vector-data-offset vm:word-bits)
(* result vm:byte-bits))
string)
path (cast buf (* char)) 1024)))
;;; Unix-rename accepts two files names and renames the first to the second.
(defun unix-rename (name1 name2)
"Unix-rename renames the file with string name1 to the string
name2. NIL and an error code is returned if an error occured."
(declare (type unix-pathname name1 name2))
(void-syscall ("rename" c-string c-string) name1 name2))
;;; Unix-rmdir accepts a name and removes the associated directory.
(defun unix-rmdir (name)
"Unix-rmdir attempts to remove the directory name. NIL and
an error number is returned if an error occured."
(declare (type unix-pathname name))
(void-syscall ("rmdir" c-string) name))
;;; UNIX-FAST-SELECT -- public.
;;;
(defmacro unix-fast-select (num-descriptors
read-fds write-fds exception-fds
timeout-secs &optional (timeout-usecs 0))
"Perform the UNIX select(2) system call.
(declare (type (integer 0 #.FD-SETSIZE) num-descriptors)
(type (or (alien (* (struct fd-set))) null)
read-fds write-fds exception-fds)
(type (or null (unsigned-byte 31)) timeout-secs)
(type (unsigned-byte 31) timeout-usecs)
(optimize (speed 3) (safety 0) (inhibit-warnings 3)))"
`(let ((timeout-secs ,timeout-secs))
(with-alien ((tv (struct timeval)))
(when timeout-secs
(setf (slot tv 'tv-sec) timeout-secs)
(setf (slot tv 'tv-usec) ,timeout-usecs))
(int-syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
(* (struct fd-set)) (* (struct timeval)))
,num-descriptors ,read-fds ,write-fds ,exception-fds
(if timeout-secs (alien-sap (addr tv)) (int-sap 0))))))
;;; Unix-select accepts sets of file descriptors and waits for an event
;;; to happen on one of them or to time out.
(defmacro num-to-fd-set (fdset num)
`(if (fixnump ,num)
(progn
(setf (deref (slot ,fdset 'fds-bits) 0) ,num)
,@(loop for index upfrom 1 below (/ fd-setsize 32)
collect `(setf (deref (slot ,fdset 'fds-bits) ,index) 0)))
(progn
,@(loop for index upfrom 0 below (/ fd-setsize 32)
collect `(setf (deref (slot ,fdset 'fds-bits) ,index)
(ldb (byte 32 ,(* index 32)) ,num))))))
(defmacro fd-set-to-num (nfds fdset)
`(if (<= ,nfds 32)
(deref (slot ,fdset 'fds-bits) 0)
(+ ,@(loop for index upfrom 0 below (/ fd-setsize 32)
collect `(ash (deref (slot ,fdset 'fds-bits) ,index)
,(* index 32))))))
(defun unix-select (nfds rdfds wrfds xpfds to-secs &optional (to-usecs 0))
"Unix-select examines the sets of descriptors passed as arguments
to see if they are ready for reading and writing. See the UNIX
Programmers Manual for more information."
(declare (type (integer 0 #.FD-SETSIZE) nfds)
(type unsigned-byte rdfds wrfds xpfds)
(type (or (unsigned-byte 31) null) to-secs)
(type (unsigned-byte 31) to-usecs)
(optimize (speed 3) (safety 0) (inhibit-warnings 3)))
(with-alien ((tv (struct timeval))
(rdf (struct fd-set))
(wrf (struct fd-set))
(xpf (struct fd-set)))
(when to-secs
(setf (slot tv 'tv-sec) to-secs)
(setf (slot tv 'tv-usec) to-usecs))
(num-to-fd-set rdf rdfds)
(num-to-fd-set wrf wrfds)
(num-to-fd-set xpf xpfds)
(macrolet ((frob (lispvar alienvar)
`(if (zerop ,lispvar)
(int-sap 0)
(alien-sap (addr ,alienvar)))))
(syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
(* (struct fd-set)) (* (struct timeval)))
(values result
(fd-set-to-num nfds rdf)
(fd-set-to-num nfds wrf)
(fd-set-to-num nfds xpf))
(if to-secs (alien-sap (addr tv)) (int-sap 0))))))
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
;;; Unix-sync writes all information in core memory which has been modified
;;; to permanent storage (i.e. disk).
(defun unix-sync ()
"Unix-sync writes all information in core memory which has been
modified to disk. It returns NIL and an error code if an error
occured."
(void-syscall ("sync")))
;;; Unix-fsync writes the core-image of the file described by "fd" to
;;; permanent storage (i.e. disk).
(defun unix-fsync (fd)
"Unix-fsync writes the core image of the file described by
fd to disk."
(declare (type unix-fd fd))
(void-syscall ("fsync" int) fd))
;;; Unix-truncate accepts a file name and a new length. The file is
;;; truncated to the new length.
(defun unix-truncate (name len)
"Unix-truncate truncates the named file to the length (in
bytes) specified by len. NIL and an error number is returned
if the call is unsuccessful."
(declare (type unix-pathname name)
(type (unsigned-byte 32) len))
(void-syscall ("truncate" c-string int) name len))
(defun unix-ftruncate (fd len)
"Unix-ftruncate is similar to unix-truncate except that the first
argument is a file descriptor rather than a file name."
(declare (type unix-fd fd)
(type (unsigned-byte 32) len))
(void-syscall ("ftruncate" int int) fd len))
(defun unix-symlink (name1 name2)
"Unix-symlink creates a symbolic link named name2 to the file
named name1. NIL and an error number is returned if the call
is unsuccessful."
(declare (type unix-pathname name1 name2))
(void-syscall ("symlink" c-string c-string) name1 name2))
;;; Unix-unlink accepts a name and deletes the directory entry for that
;;; name and the file if this is the last link.
(defun unix-unlink (name)
"Unix-unlink removes the directory entry for the named file.
NIL and an error code is returned if the call fails."
(declare (type unix-pathname name))
(void-syscall ("unlink" c-string) name))
;;; Unix-write accepts a file descriptor, a buffer, an offset, and the
;;; length to write. It attempts to write len bytes to the device
;;; associated with fd from the the buffer starting at offset. It returns
;;; the actual number of bytes written.
(defun unix-write (fd buf offset len)
"Unix-write attempts to write a character buffer (buf) of length
len to the file described by the file descriptor fd. NIL and an
error is returned if the call is unsuccessful."
(declare (type unix-fd fd)
(type (unsigned-byte 32) offset len))
(int-syscall ("write" int (* char) int)
fd
(with-alien ((ptr (* char) (etypecase buf
((simple-array * (*))
(vector-sap buf))
(system-area-pointer
buf))))
(addr (deref ptr offset)))
len))
;;; Unix-ioctl is used to change parameters of devices in a device
;;; dependent way.
(defconstant terminal-speeds
'#(0 50 75 110 134 150 200 300 600 #+hpux 900 1200 1800 2400 #+hpux 3600
4800 #+hpux 7200 9600 19200 38400 57600 115200 230400
#+hpux 460800))
(defconstant tty-raw #-linux #o40 #+linux 1)
(defconstant tty-crmod #-linux #o20 #+linux 4)
#-(or hpux svr4 freebsd linux) (defconstant tty-echo #o10) ;; 8
(defconstant tty-cbreak #-linux #o2 #+linux 64)
#-(or linux hpux)
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
(defmacro def-enum (inc cur &rest names)
(flet ((defform (name)
(prog1 (when name `(defconstant ,name ,cur))
(setf cur (funcall inc cur 1)))))
`(progn ,@(mapcar #'defform names))))
;; input modes
(def-enum ash 1 tty-ignbrk tty-brkint tty-ignpar tty-parmrk tty-inpck
tty-istrip tty-inlcr tty-igncr tty-icrnl #-freebsd tty-iuclc
tty-ixon #-freebsd tty-ixany tty-ixoff #+freebsd tty-ixany
#+hpux tty-ienqak #+freebsd nil tty-imaxbel)
;; output modes
#-freebsd (def-enum ash 1 tty-opost tty-olcuc tty-onlcr tty-ocrnl tty-onocr
tty-onlret tty-ofill tty-ofdel)
#+freebsd (def-enum ash 1 tty-opost tty-onlcr)
;; local modes
#-freebsd (def-enum ash 1 tty-isig tty-icanon tty-xcase tty-echo tty-echoe
tty-echok tty-echonl tty-noflsh #+irix tty-iexten
#+(or sunos linux) tty-tostop tty-echoctl tty-echoprt
tty-echoke #+(or sunos svr4) tty-defecho tty-flusho
#+linux nil tty-pendin #+irix tty-tostop
#+(or sunos linux) tty-iexten)
#+freebsd (def-enum ash 1 tty-echoke tty-echoe tty-echok tty-echo tty-echonl
tty-echoprt tty-echoctl tty-isig tty-icanon nil
tty-iexten)
#+freebsd (defconstant tty-tostop #x00400000)
#+freebsd (defconstant tty-flusho #x00800000)
#+freebsd (defconstant tty-pendin #x20000000)
#+freebsd (defconstant tty-noflsh #x80000000)
#+hpux (defconstant tty-tostop #o10000000000)
#+hpux (defconstant tty-iexten #o20000000000)
;; control modes
(def-enum ash #-freebsd #o100 #+freebsd #x400 #+hpux nil tty-cstopb
tty-cread tty-parenb tty-parodd tty-hupcl tty-clocal
#+svr4 rcv1en #+svr4 xmt1en #+(or hpux svr4) tty-loblk)
;; special control characters
#+(or hpux svr4 linux) (def-enum + 0 vintr vquit verase vkill veof
#-linux veol #-linux veol2)
#+freebsd (def-enum + 0 veof veol veol2 verase nil vkill nil nil vintr vquit)
#+linux (defconstant veol 11)
#+linux (defconstant veol2 16)
(defconstant tciflush 0)
(defconstant tcoflush 1)
(defconstant tcioflush 2))
(defconstant vmin 16)
(defconstant vtime 17)
(defconstant vsusp 10)
(defconstant vstart 12)
(defconstant vstop 13)
(defconstant vdsusp 11))
#+hpux
(progn
(defconstant vmin 11)
(defconstant vtime 12)
(defconstant vsusp 13)
(defconstant vstart 14)
(defconstant vstop 15)
(defconstant vdsusp 21))
#+(or hpux freebsd linux)
(progn
(defconstant tcsanow 0)
(defconstant tcsadrain 1)
(defconstant vstart 8)
(defconstant vstop 9)
(defconstant vsusp 10)
;; control modes
(defconstant tty-cbaud #o17)
(defconstant tty-csize #o60)
(defconstant tty-cs5 #o0)
(defconstant tty-cs6 #o20)
(defconstant tty-cs7 #o40)
(defconstant tty-cs8 #o60))
#+svr4
(progn
(defconstant tcsanow #x540e)
(defconstant tcsadrain #x540f)
(defconstant tcsaflush #x5410))
#-(or (and svr4 (not irix)) linux)
(progn
(defconstant iocparm-mask #x7f) ; Freebsd: #x1fff ?
(defconstant ioc_void #x20000000)
(defconstant ioc_out #x40000000)
(defconstant ioc_in #x80000000)
(defconstant ioc_inout (logior ioc_in ioc_out)))
#-(or linux (and svr4 (not irix)))
(defmacro define-ioctl-command (name dev cmd arg &optional (parm-type :void))
(:inout ioc_inout)))
(code (logior (ash (char-code dev) 8) cmd ptype)))
(when arg
(setf code
`(logior (ash (logand (alien-size ,arg :bytes)
,iocparm-mask)
16)
,code)))
#+(or linux (and svr4 (not irix)))
(defmacro define-ioctl-command (name dev cmd arg &optional (parm-type :void))
`(eval-when (eval load compile)
(defconstant ,name ,(logior (ash (char-code #\t) 8) cmd))))
(define-ioctl-command TIOCGETP #\t #-linux 8 #+linux #x5481 (struct sgttyb) :out)
(define-ioctl-command TIOCSETP #\t #-linux 9 #+linux #x5482 (struct sgttyb) :in)
(define-ioctl-command TIOCFLUSH #\t #-linux 16 #+linux #x5489 int :in)
(define-ioctl-command TIOCSETC #\t #-linux 17 #+linux #x5484 (struct tchars) :in)
(define-ioctl-command TIOCGETC #\t #-linux 18 #+linux #x5483 (struct tchars) :out)
(define-ioctl-command TIOCGWINSZ #\t #-hpux 104 #+hpux 107 (struct winsize)
:out)
(define-ioctl-command TIOCSWINSZ #\t #-hpux 103 #+hpux 106 (struct winsize)
:in)
(define-ioctl-command TIOCNOTTY #\t #-linux 113 #+linux #x5422 nil :void)
(define-ioctl-command TIOCSLTC #\t #-linux 117 #+linux #x5484 (struct ltchars) :in)
(define-ioctl-command TIOCGLTC #\t #-linux 116 #+linux #x5485 (struct ltchars) :out)
(define-ioctl-command TIOCSPGRP #\t #-svr4 118 #+svr4 21 int :in)
(define-ioctl-command TIOCGPGRP #\t #-svr4 119 #+svr4 20 int :out))
#+hpux
(progn
(define-ioctl-command TIOCSLTC #\T 23 (struct ltchars) :in)
(define-ioctl-command TIOCGLTC #\T 24 (struct ltchars) :out)
(define-ioctl-command TIOCSPGRP #\T 29 int :in)
(define-ioctl-command TIOCGPGRP #\T 30 int :out)
(define-ioctl-command TIOCSIGSEND #\t 93 nil))
(define-ioctl-command FIONREAD #\f #-linux 127 #+linux #x541B int :out)
(defun unix-ioctl (fd cmd arg)
"Unix-ioctl performs a variety of operations on open i/o
descriptors. See the UNIX Programmer's Manual for more
information."
(declare (type unix-fd fd)
(type (unsigned-byte 32) cmd))
(void-syscall ("ioctl" int unsigned-int (* char)) fd cmd arg))
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
(progn
(defun unix-tcgetattr (fd termios)
"Get terminal attributes."
(declare (type unix-fd fd))
(void-syscall ("tcgetattr" int (* (struct termios))) fd termios))
(defun unix-tcsetattr (fd opt termios)
"Set terminal attributes."
(declare (type unix-fd fd))
(void-syscall ("tcsetattr" int int (* (struct termios))) fd opt termios))
;; XXX rest of functions in this progn probably are present in linux, but
;; not verified.
(defun unix-cfgetospeed (termios)
"Get terminal output speed."
(multiple-value-bind (speed errno)
(int-syscall ("cfgetospeed" (* (struct termios))) termios)
(if speed
(values (svref terminal-speeds speed) 0)
(values speed errno))))
(defun unix-cfsetospeed (termios speed)
"Set terminal output speed."
(let ((baud (or (position speed terminal-speeds)
(error "Bogus baud rate ~S" speed))))
(void-syscall ("cfsetospeed" (* (struct termios)) int) termios baud)))
(defun unix-cfgetispeed (termios)
"Get terminal input speed."
(multiple-value-bind (speed errno)
(int-syscall ("cfgetispeed" (* (struct termios))) termios)
(if speed
(values (svref terminal-speeds speed) 0)
(values speed errno))))
(defun unix-cfsetispeed (termios speed)
"Set terminal input speed."
(let ((baud (or (position speed terminal-speeds)
(error "Bogus baud rate ~S" speed))))
(void-syscall ("cfsetispeed" (* (struct termios)) int) termios baud)))
(defun unix-tcsendbreak (fd duration)
"Send break"
(declare (type unix-fd fd))
(void-syscall ("tcsendbreak" int int) fd duration))
(defun unix-tcdrain (fd)
"Wait for output for finish"
(declare (type unix-fd fd))
(void-syscall ("tcdrain" int) fd))
(defun unix-tcflush (fd selector)
"See tcflush(3)"
(declare (type unix-fd fd))
(void-syscall ("tcflush" int int) fd selector))
(defun unix-tcflow (fd action)
"Flow control"
(declare (type unix-fd fd))
(void-syscall ("tcflow" int int) fd action)))
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
(defun tcsetpgrp (fd pgrp)
"Set the tty-process-group for the unix file-descriptor FD to PGRP."
(alien:with-alien ((alien-pgrp c-call:int pgrp))
(unix-ioctl fd
tiocspgrp
(alien:alien-sap (alien:addr alien-pgrp)))))
(defun tcgetpgrp (fd)
"Get the tty-process-group for the unix file-descriptor FD."
(alien:with-alien ((alien-pgrp c-call:int))
(multiple-value-bind (ok err)
(unix-ioctl fd
tiocgpgrp
(alien:alien-sap (alien:addr alien-pgrp)))
(if ok
(values alien-pgrp nil)
(values nil err)))))
(defun tty-process-group (&optional fd)
"Get the tty-process-group for the unix file-descriptor FD. If not supplied,
FD defaults to /dev/tty."
(if fd
(tcgetpgrp fd)
(multiple-value-bind (tty-fd errno)
(unix-open "/dev/tty" o_rdwr 0)
(cond (tty-fd
(multiple-value-prog1
(tcgetpgrp tty-fd)
(unix-close tty-fd)))
(t
(values nil errno))))))
(defun %set-tty-process-group (pgrp &optional fd)
"Set the tty-process-group for the unix file-descriptor FD to PGRP. If not
supplied, FD defaults to /dev/tty."
(let ((old-sigs
(unix-sigblock
(sigmask :sigttou :sigttin :sigtstp :sigchld))))
(declare (type (unsigned-byte 32) old-sigs))
(unwind-protect
(if fd
(tcsetpgrp fd pgrp)
(multiple-value-bind (tty-fd errno)
(unix-open "/dev/tty" o_rdwr 0)
(cond (tty-fd
(multiple-value-prog1
(tcsetpgrp tty-fd pgrp)
(unix-close tty-fd)))
(t
(values nil errno)))))
(unix-sigsetmask old-sigs))))
(defsetf tty-process-group (&optional fd) (pgrp)
"Set the tty-process-group for the unix file-descriptor FD to PGRP. If not
supplied, FD defaults to /dev/tty."
`(%set-tty-process-group ,pgrp ,fd))
;;; Socket options.
(define-ioctl-command SIOCSPGRP #\s 8 int :in)
#+linux
(define-ioctl-command SIOCSPGRP #\s #x8904 int :in)
#+(or hpux freebsd linux)
(defun siocspgrp (fd pgrp)
"Set the socket process-group for the unix file-descriptor FD to PGRP."
(alien:with-alien ((alien-pgrp c-call:int pgrp))
(unix-ioctl fd
siocspgrp
(alien:alien-sap (alien:addr alien-pgrp)))))
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
;;; Unix-exit terminates a program.
(defun unix-exit (&optional (code 0))
"Unix-exit terminates the current process with an optional
error code. If successful, the call doesn't return. If
unsuccessful, the call returns NIL and an error number."
(declare (type (signed-byte 32) code))
(void-syscall ("exit" int) code))
;;; STAT and friends.
(defmacro extract-stat-results (buf)
`(values T
(slot ,buf 'st-dev)
(slot ,buf 'st-ino)
(slot ,buf 'st-mode)
(slot ,buf 'st-nlink)
(slot ,buf 'st-uid)
(slot ,buf 'st-gid)
(slot ,buf 'st-rdev)
(slot ,buf 'st-size)
#-(or svr4 FreeBSD) (slot ,buf 'st-atime)
#+svr4 (slot (slot ,buf 'st-atime) 'tv-sec)
#+FreeBSD (slot (slot ,buf 'st-atime) 'ts-sec)
#-(or svr4 FreeBSD)(slot ,buf 'st-mtime)
#+svr4 (slot (slot ,buf 'st-mtime) 'tv-sec)
#+FreeBSD(slot (slot ,buf 'st-mtime) 'ts-sec)
#-(or svr4 FreeBSD) (slot ,buf 'st-ctime)
#+svr4 (slot (slot ,buf 'st-ctime) 'tv-sec)
#+FreeBSD(slot (slot ,buf 'st-ctime) 'ts-sec)
(slot ,buf 'st-blksize)
(slot ,buf 'st-blocks)))
(defun unix-stat (name)
"Unix-stat retrieves information about the specified
file returning them in the form of multiple values.
See the UNIX Programmer's Manual for a description
of the values returned. If the call fails, then NIL
and an error number is returned instead."
(declare (type unix-pathname name))
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
(with-alien ((buf (struct stat)))
(syscall ("stat" c-string (* (struct stat)))
(extract-stat-results buf)
name (addr buf))))
(defun unix-lstat (name)
"Unix-lstat is similar to unix-stat except the specified
file must be a symbolic link."
(declare (type unix-pathname name))
(with-alien ((buf (struct stat)))
(syscall ("lstat" c-string (* (struct stat)))
(extract-stat-results buf)
name (addr buf))))
(defun unix-fstat (fd)
"Unix-fstat is similar to unix-stat except the file is specified
by the file descriptor fd."
(declare (type unix-fd fd))
(with-alien ((buf (struct stat)))
(syscall ("fstat" int (* (struct stat)))
(extract-stat-results buf)
fd (addr buf))))
(defconstant rusage_self 0 "The calling process.")
(defconstant rusage_children -1 "Terminated child processes.")
(declaim (inline unix-fast-getrusage))
(defun unix-fast-getrusage (who)
"Like call getrusage, but return only the system and user time, and returns
the seconds and microseconds as separate values."
(declare (values (member t)
(unsigned-byte 31) (mod 1000000)
(unsigned-byte 31) (mod 1000000)))
(with-alien ((usage (struct rusage)))
(syscall* ("getrusage" int (* (struct rusage)))
(values t
(slot (slot usage 'ru-utime) 'tv-sec)
(slot (slot usage 'ru-utime) 'tv-usec)
(slot (slot usage 'ru-stime) 'tv-sec)
(slot (slot usage 'ru-stime) 'tv-usec))
who (addr usage))))
(defun unix-getrusage (who)
"Unix-getrusage returns information about the resource usage
of the process specified by who. Who can be either the
current process (rusage_self) or all of the terminated
child processes (rusage_children). NIL and an error number
is returned if the call fails."
(with-alien ((usage (struct rusage)))
(values t
(+ (* (slot (slot usage 'ru-utime) 'tv-sec) 1000000)
(slot (slot usage 'ru-utime) 'tv-usec))
(+ (* (slot (slot usage 'ru-stime) 'tv-sec) 1000000)
(slot (slot usage 'ru-stime) 'tv-usec))
(slot usage 'ru-maxrss)
(slot usage 'ru-ixrss)
(slot usage 'ru-idrss)
(slot usage 'ru-isrss)
(slot usage 'ru-minflt)
(slot usage 'ru-majflt)
(slot usage 'ru-nswap)
(slot usage 'ru-inblock)
(slot usage 'ru-oublock)
(slot usage 'ru-msgsnd)
(slot usage 'ru-msgrcv)
(slot usage 'ru-nsignals)
(slot usage 'ru-nvcsw)
(slot usage 'ru-nivcsw))
who (addr usage))))
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
;;; Getrusage is not provided in the C library on Solaris 2.4, and is
;;; rather slow on later versions so the "times" system call is
;;; provided.
#+(and sparc svr4)
(progn
(def-alien-type nil
(struct tms
(tms-utime #-alpha long #+alpha int) ; user time used
(tms-stime #-alpha long #+alpha int) ; system time used.
(tms-cutime #-alpha long #+alpha int) ; user time, children
(tms-cstime #-alpha long #+alpha int))) ; system time, children
(declaim (inline unix-times))
(defun unix-times ()
"Unix-times returns information about the cpu time usage of the process
and its children."
(with-alien ((usage (struct tms)))
(syscall* ("times" (* (struct tms)))
(values t
(slot usage 'tms-utime)
(slot usage 'tms-stime)
(slot usage 'tms-cutime)
(slot usage 'tms-cstime))
(addr usage))))
) ; end progn
;; Requires call to tzset() in main.
;; Don't use this now: we
(progn
(def-alien-variable ("daylight" unix-daylight) int)
(def-alien-variable ("timezone" unix-timezone) time-t)
(def-alien-variable ("altzone" unix-altzone) time-t)
#-irix (def-alien-variable ("tzname" unix-tzname) (array c-string 2))
#+irix (defvar unix-tzname-addr nil)
#+irix (pushnew #'(lambda () (setq unix-tzname-addr nil))
ext:*after-save-initializations*)
#+irix (declaim (notinline fakeout-compiler))
#+irix (defun fakeout-compiler (name dst)
(unless unix-tzname-addr
(setf unix-tzname-addr (system:foreign-symbol-address name)))
(deref (sap-alien unix-tzname-addr (array c-string 2)) dst))
(def-alien-routine get-timezone c-call:void
(when c-call:long :in)
(minutes-west c-call:int :out)
(daylight-savings-p alien:boolean :out))
(defun unix-get-minutes-west (secs)
(multiple-value-bind (ignore minutes dst) (get-timezone secs)
(declare (ignore ignore) (ignore dst))
(values minutes))
)
(defun unix-get-timezone (secs)
(multiple-value-bind (ignore minutes dst) (get-timezone secs)
(declare (ignore ignore) (ignore minutes))
(values #-irix (deref unix-tzname (if dst 1 0))
#+irix (fakeout-compiler "tzname" (if dst 1 0)))
(declaim (inline unix-gettimeofday))
(defun unix-gettimeofday ()
"If it works, unix-gettimeofday returns 5 values: T, the seconds and
microseconds of the current time of day, the timezone (in minutes west
of Greenwich), and a daylight-savings flag. If it doesn't work, it
returns NIL and the errno."
(with-alien ((tv (struct timeval))
#-svr4 (tz (struct timezone)))
(syscall* ("gettimeofday" (* (struct timeval)) #-svr4 (* (struct timezone)))
(values T
(slot tv 'tv-sec)
(slot tv 'tv-usec)
#-svr4 (slot tz 'tz-minuteswest)
#+svr4 (unix-get-minutes-west (slot tv 'tv-sec))
#-svr4 (slot tz 'tz-dsttime)
#+svr4 (unix-get-timezone (slot tv 'tv-sec))
)
(addr tv)
;;; Unix-utimes changes the accessed and updated times on UNIX
;;; files. The first argument is the filename (a string) and
;;; the second argument is a list of the 4 times- accessed and
;;; updated seconds and microseconds.
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
(defun unix-utimes (file atime-sec atime-usec mtime-sec mtime-usec)
"Unix-utimes sets the 'last-accessed' and 'last-updated'
times on a specified file. NIL and an error number is
returned if the call is unsuccessful."
(declare (type unix-pathname file)
(type (alien unsigned-long)
atime-sec atime-usec
mtime-sec mtime-usec))
(with-alien ((tvp (array (struct timeval) 2)))
(setf (slot (deref tvp 0) 'tv-sec) atime-sec)
(setf (slot (deref tvp 0) 'tv-usec) atime-usec)
(setf (slot (deref tvp 1) 'tv-sec) mtime-sec)
(setf (slot (deref tvp 1) 'tv-usec) mtime-usec)
(void-syscall ("utimes" c-string (* (struct timeval)))
file
(cast tvp (* (struct timeval))))))
;;; Unix-setreuid sets the real and effective user-id's of the current
;;; process to the arguments "ruid" and "euid", respectively. Usage is
;;; restricted for anyone but the super-user. Setting either "ruid" or
;;; "euid" to -1 makes the system use the current id instead.
(defun unix-setreuid (ruid euid)
"Unix-setreuid sets the real and effective user-id's of the current
process to the specified ones. NIL and an error number is returned
if the call fails."
(void-syscall ("setreuid" int int) ruid euid))
;;; Unix-setregid sets the real and effective group-id's of the current
;;; process to the arguments "rgid" and "egid", respectively. Usage is
;;; restricted for anyone but the super-user. Setting either "rgid" or
;;; "egid" to -1 makes the system use the current id instead.
(defun unix-setregid (rgid egid)
"Unix-setregid sets the real and effective group-id's of the current
process process to the specified ones. NIL and an error number is
returned if the call fails."
(void-syscall ("setregid" int int) rgid egid))