-;;;; asm/errno.h
-
-#|
-(def-unix-error ESUCCESS 0 "Successful")
-(def-unix-error EPERM 1 "Operation not permitted")
-|#
-(def-unix-error ENOENT 2 "No such file or directory")
-#|
-(def-unix-error ESRCH 3 "No such process")
-|#
-(def-unix-error EINTR 4 "Interrupted system call")
-#|
-(def-unix-error EIO 5 "I/O error")
-(def-unix-error ENXIO 6 "No such device or address")
-(def-unix-error E2BIG 7 "Arg list too long")
-(def-unix-error ENOEXEC 8 "Exec format error")
-(def-unix-error EBADF 9 "Bad file number")
-(def-unix-error ECHILD 10 "No children")
-(def-unix-error EAGAIN 11 "Try again")
-(def-unix-error ENOMEM 12 "Out of memory")
-|#
-(def-unix-error EACCES 13 "Permission denied")
-#|
-(def-unix-error EFAULT 14 "Bad address")
-(def-unix-error ENOTBLK 15 "Block device required")
-(def-unix-error EBUSY 16 "Device or resource busy")
-|#
-(def-unix-error EEXIST 17 "File exists")
-#|
-(def-unix-error EXDEV 18 "Cross-device link")
-(def-unix-error ENODEV 19 "No such device")
-|#
-(def-unix-error ENOTDIR 20 "Not a directory")
-#|
-(def-unix-error EISDIR 21 "Is a directory")
-(def-unix-error EINVAL 22 "Invalid argument")
-(def-unix-error ENFILE 23 "File table overflow")
-(def-unix-error EMFILE 24 "Too many open files")
-(def-unix-error ENOTTY 25 "Not a typewriter")
-(def-unix-error ETXTBSY 26 "Text file busy")
-(def-unix-error EFBIG 27 "File too large")
-(def-unix-error ENOSPC 28 "No space left on device")
-|#
-(def-unix-error ESPIPE 29 "Illegal seek")
-#|
-(def-unix-error EROFS 30 "Read-only file system")
-(def-unix-error EMLINK 31 "Too many links")
-(def-unix-error EPIPE 32 "Broken pipe")
-|#
-
-#|
-;;; Math
-(def-unix-error EDOM 33 "Math argument out of domain")
-(def-unix-error ERANGE 34 "Math result not representable")
-(def-unix-error EDEADLK 35 "Resource deadlock would occur")
-(def-unix-error ENAMETOOLONG 36 "File name too long")
-(def-unix-error ENOLCK 37 "No record locks available")
-(def-unix-error ENOSYS 38 "Function not implemented")
-(def-unix-error ENOTEMPTY 39 "Directory not empty")
-(def-unix-error ELOOP 40 "Too many symbolic links encountered")
-|#
-(def-unix-error EWOULDBLOCK 11 "Operation would block")
-(/show0 "unix.lisp 3192")
-#|
-(def-unix-error ENOMSG 42 "No message of desired type")
-(def-unix-error EIDRM 43 "Identifier removed")
-(def-unix-error ECHRNG 44 "Channel number out of range")
-(def-unix-error EL2NSYNC 45 "Level 2 not synchronized")
-(def-unix-error EL3HLT 46 "Level 3 halted")
-(def-unix-error EL3RST 47 "Level 3 reset")
-(def-unix-error ELNRNG 48 "Link number out of range")
-(def-unix-error EUNATCH 49 "Protocol driver not attached")
-(def-unix-error ENOCSI 50 "No CSI structure available")
-(def-unix-error EL2HLT 51 "Level 2 halted")
-(def-unix-error EBADE 52 "Invalid exchange")
-(def-unix-error EBADR 53 "Invalid request descriptor")
-(def-unix-error EXFULL 54 "Exchange full")
-(def-unix-error ENOANO 55 "No anode")
-(def-unix-error EBADRQC 56 "Invalid request code")
-(def-unix-error EBADSLT 57 "Invalid slot")
-(def-unix-error EDEADLOCK EDEADLK "File locking deadlock error")
-(def-unix-error EBFONT 59 "Bad font file format")
-(def-unix-error ENOSTR 60 "Device not a stream")
-(def-unix-error ENODATA 61 "No data available")
-(def-unix-error ETIME 62 "Timer expired")
-(def-unix-error ENOSR 63 "Out of streams resources")
-(def-unix-error ENONET 64 "Machine is not on the network")
-(def-unix-error ENOPKG 65 "Package not installed")
-(def-unix-error EREMOTE 66 "Object is remote")
-(def-unix-error ENOLINK 67 "Link has been severed")
-(def-unix-error EADV 68 "Advertise error")
-(def-unix-error ESRMNT 69 "Srmount error")
-(def-unix-error ECOMM 70 "Communication error on send")
-(def-unix-error EPROTO 71 "Protocol error")
-(def-unix-error EMULTIHOP 72 "Multihop attempted")
-(def-unix-error EDOTDOT 73 "RFS specific error")
-(def-unix-error EBADMSG 74 "Not a data message")
-(def-unix-error EOVERFLOW 75 "Value too large for defined data type")
-(def-unix-error ENOTUNIQ 76 "Name not unique on network")
-(def-unix-error EBADFD 77 "File descriptor in bad state")
-(def-unix-error EREMCHG 78 "Remote address changed")
-(def-unix-error ELIBACC 79 "Can not access a needed shared library")
-(def-unix-error ELIBBAD 80 "Accessing a corrupted shared library")
-(def-unix-error ELIBSCN 81 ".lib section in a.out corrupted")
-(def-unix-error ELIBMAX 82 "Attempting to link in too many shared libraries")
-(def-unix-error ELIBEXEC 83 "Cannot exec a shared library directly")
-(def-unix-error EILSEQ 84 "Illegal byte sequence")
-(def-unix-error ERESTART 85 "Interrupted system call should be restarted ")
-(def-unix-error ESTRPIPE 86 "Streams pipe error")
-(def-unix-error EUSERS 87 "Too many users")
-(def-unix-error ENOTSOCK 88 "Socket operation on non-socket")
-(def-unix-error EDESTADDRREQ 89 "Destination address required")
-(def-unix-error EMSGSIZE 90 "Message too long")
-(def-unix-error EPROTOTYPE 91 "Protocol wrong type for socket")
-(def-unix-error ENOPROTOOPT 92 "Protocol not available")
-(def-unix-error EPROTONOSUPPORT 93 "Protocol not supported")
-(def-unix-error ESOCKTNOSUPPORT 94 "Socket type not supported")
-(def-unix-error EOPNOTSUPP 95 "Operation not supported on transport endpoint")
-(def-unix-error EPFNOSUPPORT 96 "Protocol family not supported")
-(def-unix-error EAFNOSUPPORT 97 "Address family not supported by protocol")
-(def-unix-error EADDRINUSE 98 "Address already in use")
-(def-unix-error EADDRNOTAVAIL 99 "Cannot assign requested address")
-(def-unix-error ENETDOWN 100 "Network is down")
-(def-unix-error ENETUNREACH 101 "Network is unreachable")
-(def-unix-error ENETRESET 102 "Network dropped connection because of reset")
-(def-unix-error ECONNABORTED 103 "Software caused connection abort")
-(def-unix-error ECONNRESET 104 "Connection reset by peer")
-(def-unix-error ENOBUFS 105 "No buffer space available")
-(def-unix-error EISCONN 106 "Transport endpoint is already connected")
-(def-unix-error ENOTCONN 107 "Transport endpoint is not connected")
-(def-unix-error ESHUTDOWN 108 "Cannot send after transport endpoint shutdown")
-(def-unix-error ETOOMANYREFS 109 "Too many references: cannot splice")
-(def-unix-error ETIMEDOUT 110 "Connection timed out")
-(def-unix-error ECONNREFUSED 111 "Connection refused")
-(def-unix-error EHOSTDOWN 112 "Host is down")
-(def-unix-error EHOSTUNREACH 113 "No route to host")
-(def-unix-error EALREADY 114 "Operation already in progress")
-(def-unix-error EINPROGRESS 115 "Operation now in progress")
-(def-unix-error ESTALE 116 "Stale NFS file handle")
-(def-unix-error EUCLEAN 117 "Structure needs cleaning")
-(def-unix-error ENOTNAM 118 "Not a XENIX named type file")
-(def-unix-error ENAVAIL 119 "No XENIX semaphores available")
-(def-unix-error EISNAM 120 "Is a named type file")
-(def-unix-error EREMOTEIO 121 "Remote I/O error")
-(def-unix-error EDQUOT 122 "Quota exceeded")
-|#
-
-;;; And now for something completely different ...
-(emit-unix-errors)
+
+;; Type of the second argument to `getitimer' and
+;; the second and third arguments `setitimer'.
+(define-alien-type nil
+ (struct itimerval
+ (it-interval (struct timeval)) ; timer interval
+ (it-value (struct timeval)))) ; current value
+
+(defconstant ITIMER-REAL 0)
+(defconstant ITIMER-VIRTUAL 1)
+(defconstant ITIMER-PROF 2)
+
+(defun unix-getitimer(which)
+ "Unix-getitimer returns the INTERVAL and VALUE slots of one of
+ three system timers (:real :virtual or :profile). On success,
+ unix-getitimer returns 5 values,
+ T, it-interval-secs, it-interval-usec, it-value-secs, it-value-usec."
+ (declare (type (member :real :virtual :profile) which)
+ (values t
+ (unsigned-byte 29) (mod 1000000)
+ (unsigned-byte 29) (mod 1000000)))
+ (let ((which (ecase which
+ (:real ITIMER-REAL)
+ (:virtual ITIMER-VIRTUAL)
+ (:profile ITIMER-PROF))))
+ (with-alien ((itv (struct itimerval)))
+ (syscall* ("getitimer" int (* (struct itimerval)))
+ (values T
+ (slot (slot itv 'it-interval) 'tv-sec)
+ (slot (slot itv 'it-interval) 'tv-usec)
+ (slot (slot itv 'it-value) 'tv-sec)
+ (slot (slot itv 'it-value) 'tv-usec))
+ which (alien-sap (addr itv))))))
+
+(defun unix-setitimer (which int-secs int-usec val-secs val-usec)
+ " Unix-setitimer sets the INTERVAL and VALUE slots of one of
+ three system timers (:real :virtual or :profile). A SIGALRM signal
+ will be delivered VALUE <seconds+microseconds> from now. INTERVAL,
+ when non-zero, is <seconds+microseconds> to be loaded each time
+ the timer expires. Setting INTERVAL and VALUE to zero disables
+ the timer. See the Unix man page for more details. On success,
+ unix-setitimer returns the old contents of the INTERVAL and VALUE
+ slots as in unix-getitimer."
+ (declare (type (member :real :virtual :profile) which)
+ (type (unsigned-byte 29) int-secs val-secs)
+ (type (integer 0 (1000000)) int-usec val-usec)
+ (values t
+ (unsigned-byte 29) (mod 1000000)
+ (unsigned-byte 29) (mod 1000000)))
+ (let ((which (ecase which
+ (:real ITIMER-REAL)
+ (:virtual ITIMER-VIRTUAL)
+ (:profile ITIMER-PROF))))
+ (with-alien ((itvn (struct itimerval))
+ (itvo (struct itimerval)))
+ (setf (slot (slot itvn 'it-interval) 'tv-sec ) int-secs
+ (slot (slot itvn 'it-interval) 'tv-usec) int-usec
+ (slot (slot itvn 'it-value ) 'tv-sec ) val-secs
+ (slot (slot itvn 'it-value ) 'tv-usec) val-usec)
+ (syscall* ("setitimer" int (* (struct timeval))(* (struct timeval)))
+ (values T
+ (slot (slot itvo 'it-interval) 'tv-sec)
+ (slot (slot itvo 'it-interval) 'tv-usec)
+ (slot (slot itvo 'it-value) 'tv-sec)
+ (slot (slot itvo 'it-value) 'tv-usec))
+ which (alien-sap (addr itvn))(alien-sap (addr itvo))))))
+
+(defmacro sb!ext:with-timeout (expires &body body)
+ "Execute the body, interrupting it with a SIGALRM after at least
+EXPIRES seconds have passed. Uses Unix setitimer(), restoring any
+previous timer after the body has finished executing"
+ (with-unique-names (saved-seconds saved-useconds s u)
+ `(let (- ,saved-seconds ,saved-useconds)
+ (multiple-value-setq (- - - ,saved-seconds ,saved-useconds)
+ (unix-getitimer :real))
+ (multiple-value-bind (,s ,u) (floor ,expires)
+ (setf ,u (floor (* ,u 1000000)))
+ (if (and (> ,expires 0)
+ (or (and (zerop ,saved-seconds) (zerop ,saved-useconds))
+ (> ,saved-seconds ,s)
+ (and (= ,saved-seconds ,s)
+ (> ,saved-useconds ,u))))
+ (unwind-protect
+ (progn
+ (unix-setitimer :real 0 0 ,s ,u)
+ ,@body)
+ (unix-setitimer :real 0 0 ,saved-seconds ,saved-useconds))
+ (progn
+ ,@body))))))
+\f
+;;; FIXME: Many Unix error code definitions were deleted from the old
+;;; CMU CL source code here, but not in the exports of SB-UNIX. I
+;;; (WHN) hope that someday I'll figure out an automatic way to detect
+;;; unused symbols in package exports, but if I don't, there are
+;;; enough of them all in one place here that they should probably be
+;;; removed by hand.