| 
									
										
										
										
											2008-01-18 18:18:54 -05:00
										 |  |  | ! Copyright (C) 2004, 2008 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2010-12-25 19:54:45 -05:00
										 |  |  | USING: alien alien.c-types alien.data alien.syntax generic | 
					
						
							|  |  |  | assocs kernel kernel.private math io.ports sequences strings | 
					
						
							| 
									
										
										
										
											2011-10-14 22:14:59 -04:00
										 |  |  | sbufs threads unix unix.ffi unix.stat vectors io.buffers io.backend | 
					
						
							| 
									
										
										
										
											2013-10-21 16:58:33 -04:00
										 |  |  | io.encodings io.files math.parser continuations system libc namespaces | 
					
						
							| 
									
										
										
										
											2010-12-25 19:54:45 -05:00
										 |  |  | make io.timeouts io.encodings.utf8 destructors | 
					
						
							|  |  |  | destructors.private accessors summary combinators locals | 
					
						
							| 
									
										
										
										
											2011-10-14 22:14:59 -04:00
										 |  |  | unix.time unix.types fry io.backend.unix.multiplexers | 
					
						
							| 
									
										
										
										
											2011-11-09 18:38:03 -05:00
										 |  |  | classes.struct hints ;
 | 
					
						
							| 
									
										
										
										
											2008-01-18 18:18:54 -05:00
										 |  |  | QUALIFIED: io | 
					
						
							| 
									
										
										
										
											2008-12-14 21:03:00 -05:00
										 |  |  | IN: io.backend.unix | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-12 19:53:22 -04:00
										 |  |  | GENERIC: handle-fd ( handle -- fd )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-24 03:26:13 -04:00
										 |  |  | TUPLE: fd < disposable fd ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | : init-fd ( fd -- fd )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         |dispose | 
					
						
							| 
									
										
										
										
											2010-01-23 10:07:35 -05:00
										 |  |  |         dup fd>> F_SETFL O_NONBLOCK [ fcntl ] unix-system-call drop
 | 
					
						
							|  |  |  |         dup fd>> F_SETFD FD_CLOEXEC [ fcntl ] unix-system-call drop
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  |     ] with-destructors ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-15 19:14:46 -04:00
										 |  |  | : <fd> ( n -- fd )
 | 
					
						
							| 
									
										
										
										
											2009-08-24 03:26:13 -04:00
										 |  |  |     fd new-disposable swap >>fd ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-22 01:41:18 -04:00
										 |  |  | M: fd dispose | 
					
						
							| 
									
										
										
										
											2010-08-23 22:08:16 -04:00
										 |  |  |     [ | 
					
						
							| 
									
										
										
										
											2009-08-24 03:26:13 -04:00
										 |  |  |         { | 
					
						
							|  |  |  |             [ cancel-operation ] | 
					
						
							|  |  |  |             [ t >>disposed drop ] | 
					
						
							|  |  |  |             [ unregister-disposable ] | 
					
						
							|  |  |  |             [ fd>> close-file ] | 
					
						
							|  |  |  |         } cleave
 | 
					
						
							| 
									
										
										
										
											2010-08-23 22:08:16 -04:00
										 |  |  |     ] unless-disposed ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-20 19:52:11 -04:00
										 |  |  | M: fd handle-fd dup check-disposed fd>> ;
 | 
					
						
							| 
									
										
										
										
											2008-05-12 19:53:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-21 02:36:30 -04:00
										 |  |  | M: fd cancel-operation ( fd -- )
 | 
					
						
							| 
									
										
										
										
											2010-08-23 22:08:16 -04:00
										 |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-05-20 19:52:11 -04:00
										 |  |  |         fd>> | 
					
						
							|  |  |  |         mx get-global
 | 
					
						
							|  |  |  |         [ remove-input-callbacks [ t swap resume-with ] each ] | 
					
						
							|  |  |  |         [ remove-output-callbacks [ t swap resume-with ] each ] | 
					
						
							|  |  |  |         2bi
 | 
					
						
							| 
									
										
										
										
											2010-08-23 22:08:16 -04:00
										 |  |  |     ] unless-disposed ;
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-03 19:27:09 -04:00
										 |  |  | M: unix tell-handle ( handle -- n )
 | 
					
						
							| 
									
										
										
										
											2010-01-19 17:53:15 -05:00
										 |  |  |     fd>> 0 SEEK_CUR [ lseek ] unix-system-call [ io-error ] [ ] bi ;
 | 
					
						
							| 
									
										
										
										
											2009-10-03 19:27:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-08 11:35:30 -05:00
										 |  |  | M: unix seek-handle ( n seek-type handle -- )
 | 
					
						
							| 
									
										
										
										
											2009-02-07 11:30:51 -05:00
										 |  |  |     swap { | 
					
						
							|  |  |  |         { io:seek-absolute [ SEEK_SET ] } | 
					
						
							|  |  |  |         { io:seek-relative [ SEEK_CUR ] } | 
					
						
							|  |  |  |         { io:seek-end [ SEEK_END ] } | 
					
						
							| 
									
										
										
										
											2009-02-07 12:24:12 -05:00
										 |  |  |         [ io:bad-seek-type ] | 
					
						
							| 
									
										
										
										
											2009-02-07 11:30:51 -05:00
										 |  |  |     } case
 | 
					
						
							| 
									
										
										
										
											2010-01-23 10:07:35 -05:00
										 |  |  |     [ fd>> swap ] dip [ lseek ] unix-system-call drop ;
 | 
					
						
							| 
									
										
										
										
											2009-02-07 02:03:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 22:14:59 -04:00
										 |  |  | M: unix can-seek-handle? ( handle -- ? )
 | 
					
						
							|  |  |  |     fd>> SEEK_CUR 0 lseek -1 = not ;
 | 
					
						
							| 
									
										
										
										
											2011-10-18 00:12:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 22:14:59 -04:00
										 |  |  | M: unix handle-length ( handle -- n/f )
 | 
					
						
							|  |  |  |     fd>> \ stat <struct> [ fstat -1 = not ] keep
 | 
					
						
							|  |  |  |     swap [ st_size>> ] [ drop f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-21 02:36:30 -04:00
										 |  |  | ERROR: io-timeout ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: io-timeout summary drop "I/O operation timed out" ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-21 12:27:29 -04:00
										 |  |  | M: unix wait-for-fd ( handle event -- )
 | 
					
						
							| 
									
										
										
										
											2008-05-21 02:36:30 -04:00
										 |  |  |     dup +retry+ eq? [ 2drop ] [ | 
					
						
							| 
									
										
										
										
											2010-03-27 12:03:06 -04:00
										 |  |  |         [ [ self ] dip handle-fd mx get-global ] dip { | 
					
						
							|  |  |  |             { +input+ [ add-input-callback ] } | 
					
						
							|  |  |  |             { +output+ [ add-output-callback ] } | 
					
						
							|  |  |  |         } case
 | 
					
						
							|  |  |  |         "I/O" suspend [ io-timeout ] when
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | : wait-for-port ( port event -- )
 | 
					
						
							| 
									
										
										
										
											2008-12-02 04:10:13 -05:00
										 |  |  |     '[ handle>> _ wait-for-fd ] with-timeout ;
 | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! Some general stuff | 
					
						
							| 
									
										
										
										
											2011-11-23 21:49:33 -05:00
										 |  |  | CONSTANT: file-mode 0o0666
 | 
					
						
							| 
									
										
										
										
											2008-05-12 19:53:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | M: fd refill | 
					
						
							|  |  |  |     fd>> over buffer>> [ buffer-end ] [ buffer-capacity ] bi read
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-05-18 20:02:50 -04:00
										 |  |  |         { [ dup 0 >= ] [ swap buffer>> n>buffer f ] } | 
					
						
							| 
									
										
										
										
											2009-02-06 19:22:28 -05:00
										 |  |  |         { [ errno EINTR = ] [ 2drop +retry+ ] } | 
					
						
							|  |  |  |         { [ errno EAGAIN = ] [ 2drop +input+ ] } | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |         [ (io-error) ] | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-09 18:38:03 -05:00
										 |  |  | HINTS: M\ fd refill | 
					
						
							|  |  |  |     { buffered-port fd } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  | M: unix (wait-to-read) ( port -- )
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:50:12 -04:00
										 |  |  |     dup
 | 
					
						
							|  |  |  |     dup handle>> dup check-disposed refill dup
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |     [ dupd wait-for-port (wait-to-read) ] [ 2drop ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Writers | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  | M: fd drain | 
					
						
							|  |  |  |     fd>> over buffer>> [ buffer@ ] [ buffer-length ] bi write
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |         { [ dup 0 >= ] [ | 
					
						
							|  |  |  |             over buffer>> buffer-consume | 
					
						
							|  |  |  |             buffer>> buffer-empty? f +output+ ?
 | 
					
						
							|  |  |  |         ] } | 
					
						
							| 
									
										
										
										
											2009-02-06 19:22:28 -05:00
										 |  |  |         { [ errno EINTR = ] [ 2drop +retry+ ] } | 
					
						
							|  |  |  |         { [ errno EAGAIN = ] [ 2drop +output+ ] } | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |         [ (io-error) ] | 
					
						
							|  |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: unix (wait-to-write) ( port -- )
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:50:12 -04:00
										 |  |  |     dup
 | 
					
						
							|  |  |  |     dup handle>> dup check-disposed drain | 
					
						
							|  |  |  |     dup [ wait-for-port ] [ 2drop ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-01 15:08:18 -04:00
										 |  |  | M: unix io-multiplex ( nanos -- )
 | 
					
						
							| 
									
										
										
										
											2008-02-09 22:34:42 -05:00
										 |  |  |     mx get-global wait-for-events ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | ! On Unix, you're not supposed to set stdin to non-blocking | 
					
						
							|  |  |  | ! because the fd might be shared with another process (either | 
					
						
							|  |  |  | ! parent or child). So what we do is have the VM start a thread | 
					
						
							|  |  |  | ! which pumps data from the real stdin to a pipe. We set the | 
					
						
							|  |  |  | ! pipe to non-blocking, and read from it instead of the real | 
					
						
							|  |  |  | ! stdin. Very crufty, but it will suffice until we get native | 
					
						
							|  |  |  | ! threading support at the language level. | 
					
						
							| 
									
										
										
										
											2009-08-24 03:26:13 -04:00
										 |  |  | TUPLE: stdin < disposable control size data ;
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-09 20:23:35 -04:00
										 |  |  | M: stdin dispose* | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         [ control>> &dispose drop ] | 
					
						
							|  |  |  |         [ size>> &dispose drop ] | 
					
						
							|  |  |  |         [ data>> &dispose drop ] | 
					
						
							|  |  |  |         tri
 | 
					
						
							|  |  |  |     ] with-destructors ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-21 19:09:15 -04:00
										 |  |  | : wait-for-stdin ( stdin -- size )
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  |     [ control>> CHAR: X over io:stream-write1 io:stream-flush ] | 
					
						
							| 
									
										
										
										
											2011-05-19 18:45:39 -04:00
										 |  |  |     [ size>> ssize_t heap-size swap io:stream-read ssize_t deref ] | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  |     bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: refill-stdin ( buffer stdin size -- )
 | 
					
						
							|  |  |  |     stdin data>> handle-fd buffer buffer-end size read
 | 
					
						
							|  |  |  |     dup 0 < [ | 
					
						
							|  |  |  |         drop
 | 
					
						
							| 
									
										
										
										
											2009-02-06 19:22:28 -05:00
										 |  |  |         errno EINTR = [ buffer stdin size refill-stdin ] [ (io-error) ] if
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         size = [ "Error reading stdin pipe" throw ] unless
 | 
					
						
							|  |  |  |         size buffer n>buffer | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: stdin refill | 
					
						
							| 
									
										
										
										
											2010-05-21 19:09:15 -04:00
										 |  |  |     '[ | 
					
						
							|  |  |  |         buffer>> _ dup wait-for-stdin refill-stdin f
 | 
					
						
							|  |  |  |     ] with-timeout ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: stdin cancel-operation | 
					
						
							|  |  |  |     [ size>> ] [ control>> ] bi [ cancel-operation ] bi@ ;
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 18:42:53 -04:00
										 |  |  | : control-write-fd ( -- fd ) &: control_write uint deref ;
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 18:42:53 -04:00
										 |  |  | : size-read-fd ( -- fd ) &: size_read uint deref ;
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-20 18:42:53 -04:00
										 |  |  | : data-read-fd ( -- fd ) &: stdin_read uint deref ;
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <stdin> ( -- stdin )
 | 
					
						
							| 
									
										
										
										
											2009-08-24 03:26:13 -04:00
										 |  |  |     stdin new-disposable | 
					
						
							| 
									
										
										
										
											2008-07-09 20:23:35 -04:00
										 |  |  |         control-write-fd <fd> <output-port> >>control | 
					
						
							|  |  |  |         size-read-fd <fd> init-fd <input-port> >>size | 
					
						
							|  |  |  |         data-read-fd <fd> >>data ;
 | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 13:15:44 -05:00
										 |  |  | SYMBOL: dispatch-signal-hook | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dispatch-signal-hook [ [ drop ] ] initialize
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 00:14:41 -05:00
										 |  |  | : signal-pipe-fd ( -- n )
 | 
					
						
							| 
									
										
										
										
											2011-11-08 02:07:00 -05:00
										 |  |  |     OBJ-SIGNAL-PIPE special-object ; inline
 | 
					
						
							| 
									
										
										
										
											2011-11-08 00:14:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 13:15:44 -05:00
										 |  |  | : signal-pipe-loop ( port -- )
 | 
					
						
							|  |  |  |     '[ | 
					
						
							|  |  |  |         int heap-size _ io:stream-read | 
					
						
							|  |  |  |         dup [ int deref dispatch-signal-hook get call( x -- ) ] when*
 | 
					
						
							|  |  |  |     ] loop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 02:07:00 -05:00
										 |  |  | : start-signal-pipe-thread ( -- )
 | 
					
						
							| 
									
										
										
										
											2011-11-08 13:15:44 -05:00
										 |  |  |     signal-pipe-fd [ | 
					
						
							|  |  |  |         <fd> init-fd <input-port> | 
					
						
							|  |  |  |         '[ _ signal-pipe-loop ] "Signals" spawn drop
 | 
					
						
							| 
									
										
										
										
											2011-11-08 02:07:00 -05:00
										 |  |  |     ] when* ;
 | 
					
						
							| 
									
										
										
										
											2011-11-08 00:14:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-12 04:35:48 -04:00
										 |  |  | M: unix init-stdio | 
					
						
							| 
									
										
										
										
											2008-07-03 18:44:44 -04:00
										 |  |  |     <stdin> <input-port> | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  |     1 <fd> <output-port> | 
					
						
							| 
									
										
										
										
											2009-05-12 04:35:48 -04:00
										 |  |  |     2 <fd> <output-port> | 
					
						
							|  |  |  |     set-stdio ;
 | 
					
						
							| 
									
										
										
										
											2008-01-18 19:43:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-20 17:07:18 -05:00
										 |  |  | ! mx io-task for embedding an fd-based mx inside another mx | 
					
						
							| 
									
										
										
										
											2008-04-11 17:08:40 -04:00
										 |  |  | TUPLE: mx-port < port mx ;
 | 
					
						
							| 
									
										
										
										
											2008-01-20 17:07:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <mx-port> ( mx -- port )
 | 
					
						
							| 
									
										
										
										
											2008-04-11 17:08:40 -04:00
										 |  |  |     dup fd>> mx-port <port> swap >>mx ;
 | 
					
						
							| 
									
										
										
										
											2008-01-20 17:07:18 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 21:10:47 -05:00
										 |  |  | : multiplexer-error ( n -- n )
 | 
					
						
							|  |  |  |     dup 0 < [ | 
					
						
							| 
									
										
										
										
											2009-02-06 19:22:28 -05:00
										 |  |  |         errno [ EAGAIN = ] [ EINTR = ] bi or
 | 
					
						
							| 
									
										
										
										
											2008-12-10 21:10:47 -05:00
										 |  |  |         [ drop 0 ] [ (io-error) ] if
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |     ] when ;
 | 
					
						
							| 
									
										
										
										
											2008-04-11 10:54:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-15 10:04:09 -05:00
										 |  |  | :: ?flag ( n mask symbol -- n )
 | 
					
						
							|  |  |  |     n mask bitand 0 > [ symbol , ] when n ;
 |