ecl.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) README (DIR) LICENSE --- ecl.lisp (5141B) --- 1 ;;;; -*- Mode: Lisp -*- 2 3 ;;;; Foreign functions defined by ECL's DFFI, used for #+ecl-bytecmp only. 4 ;;;; See LICENSE for licensing information. 5 6 (in-package :usocket) 7 8 #+(and ecl-bytecmp windows) 9 (eval-when (:load-toplevel :execute) 10 (ffi:load-foreign-library "ws2_32.dll" :module "ws2_32")) 11 12 #+(and ecl-bytecmp windows) 13 (progn 14 (ffi:def-function ("gethostname" c-gethostname) 15 ((name (* :unsigned-char)) 16 (len :int)) 17 :returning :int 18 :module "ws2_32") 19 20 (defun get-host-name () 21 "Returns the hostname" 22 (ffi:with-foreign-object (name '(:array :unsigned-char 256)) 23 (when (zerop (c-gethostname (ffi:char-array-to-pointer name) 256)) 24 (ffi:convert-from-foreign-string name)))) 25 26 (ffi:def-foreign-type ws-socket :unsigned-int) 27 (ffi:def-foreign-type ws-dword :unsigned-long) 28 (ffi:def-foreign-type ws-event :unsigned-int) 29 30 (ffi:def-struct wsa-network-events 31 (network-events :long) 32 (error-code (:array :int 10))) 33 34 (ffi:def-function ("WSACreateEvent" wsa-event-create) 35 () 36 :returning ws-event 37 :module "ws2_32") 38 39 (ffi:def-function ("WSACloseEvent" c-wsa-event-close) 40 ((event-object ws-event)) 41 :returning :int 42 :module "ws2_32") 43 44 (defun wsa-event-close (ws-event) 45 (not (zerop (c-wsa-event-close ws-event)))) 46 47 (ffi:def-function ("WSAEnumNetworkEvents" wsa-enum-network-events) 48 ((socket ws-socket) 49 (event-object ws-event) 50 (network-events (* wsa-network-events))) 51 :returning :int 52 :module "ws2_32") 53 54 (ffi:def-function ("WSAEventSelect" wsa-event-select) 55 ((socket ws-socket) 56 (event-object ws-event) 57 (network-events :long)) 58 :returning :int 59 :module "ws2_32") 60 61 (ffi:def-function ("WSAWaitForMultipleEvents" c-wsa-wait-for-multiple-events) 62 ((number-of-events ws-dword) 63 (events (* ws-event)) 64 (wait-all-p :int) 65 (timeout ws-dword) 66 (alertable-p :int)) 67 :returning ws-dword 68 :module "ws2_32") 69 70 (defun wsa-wait-for-multiple-events (number-of-events events wait-all-p timeout alertable-p) 71 (c-wsa-wait-for-multiple-events number-of-events 72 events 73 (if wait-all-p -1 0) 74 timeout 75 (if alertable-p -1 0))) 76 77 (ffi:def-function ("ioctlsocket" wsa-ioctlsocket) 78 ((socket ws-socket) 79 (cmd :long) 80 (argp (* :unsigned-long))) 81 :returning :int 82 :module "ws2_32") 83 84 (ffi:def-function ("WSAGetLastError" wsa-get-last-error) 85 () 86 :returning :int 87 :module "ws2_32") 88 89 (defun maybe-wsa-error (rv &optional socket) 90 (unless (zerop rv) 91 (raise-usock-err (wsa-get-last-error) socket))) 92 93 (defun bytes-available-for-read (socket) 94 (ffi:with-foreign-object (int-ptr :unsigned-long) 95 (maybe-wsa-error (wsa-ioctlsocket (socket-handle socket) fionread int-ptr) 96 socket) 97 (let ((int (ffi:deref-pointer int-ptr :unsigned-long))) 98 (prog1 int 99 (when (plusp int) 100 (setf (state socket) :read)))))) 101 102 (defun map-network-events (func network-events) 103 (let ((event-map (ffi:get-slot-value network-events 'wsa-network-events 'network-events)) 104 (error-array (ffi:get-slot-pointer network-events 'wsa-network-events 'error-code))) 105 (unless (zerop event-map) 106 (dotimes (i fd-max-events) 107 (unless (zerop (ldb (byte 1 i) event-map)) 108 (funcall func (ffi:deref-array error-array '(:array :int 10) i))))))) 109 110 (defun update-ready-and-state-slots (sockets) 111 (dolist (socket sockets) 112 (if (%ready-p socket) 113 (progn 114 (setf (state socket) :READ)) 115 (ffi:with-foreign-object (network-events 'wsa-network-events) 116 (let ((rv (wsa-enum-network-events (socket-handle socket) 0 network-events))) 117 (if (zerop rv) 118 (map-network-events 119 #'(lambda (err-code) 120 (if (zerop err-code) 121 (progn 122 (setf (state socket) :READ) 123 (when (stream-server-usocket-p socket) 124 (setf (%ready-p socket) t))) 125 (raise-usock-err err-code socket))) 126 network-events) 127 (maybe-wsa-error rv socket))))))) 128 129 (defun os-wait-list-%wait (wait-list) 130 (ffi:deref-pointer (wait-list-%wait wait-list) 'ws-event)) 131 132 (defun (setf os-wait-list-%wait) (value wait-list) 133 (setf (ffi:deref-pointer (wait-list-%wait wait-list) 'ws-event) value)) 134 135 (defun free-wait-list (wl) 136 (when (wait-list-p wl) 137 (unless (null (wait-list-%wait wl)) 138 (wsa-event-close (os-wait-list-%wait wl)) 139 (ffi:free-foreign-object (wait-list-%wait wl)) 140 (setf (wait-list-%wait wl) nil)))) 141 142 (defun %setup-wait-list (wait-list) 143 (setf (wait-list-%wait wait-list) 144 (ffi:allocate-foreign-object 'ws-event)) 145 (setf (os-wait-list-%wait wait-list) 146 (wsa-event-create)) 147 (ext:set-finalizer wait-list #'free-wait-list)) 148 149 (defun os-socket-handle (usocket) 150 (socket-handle usocket)) 151 152 ) ; #+(and ecl-bytecmp windows)