Unix IO Interface.
For Julia programs that need to interact with Unix-specific IO interfaces.
e.g. Character devices, Terminals, Unix domain sockets, Block devices etc.
using UnixIO
using UnixIO: C
UnixIO.read(`curl https://julialang.org`, String; timeout=5)
io = UnixIO.open("/dev/ttyUSB0", C.O_RDWR | C.O_NOCTTY)
UnixIO.tcsetattr(io) do attr
attr.speed=9600
attr.c_lflag |= C.ICANON
end
readline(io; timeout=5)
fd = C.open("file.txt", C.O_CREAT | C.O_WRONLY, 0o644)
C.write(fd, pointer("Hello!"), 7)
C.close(fd)
io = UnixIO.open("file.txt", C.O_CREAT | C.O_WRONLY)
write(io, "Hello!")
close(io)
Blocking IO is multiplexed by running poll(2)
under a task started by Threads.@spawn
. See src/poll.jl
If ENV["JULIA_IO_EVENT_SOURCE"]
is set to epoll
the Linux epoll(7)
API is used instead.
If ENV["JULIA_IO_EVENT_SOURCE"]
is set to sleep
IO polling is done by a dumb loop with a 10ms delay. This may be more efficient for small systems with simple IO requirements. (e.g. communicating with a few serial ports and sub-processes on a Raspberry Pi).
UnixIO.open([FDType], pathname, [flags = C.O_RDWR],
[mode = 0o644]];
[timeout=Inf],
[tcattr=nothing]) -> UnixIO{FDType}
Open the file specified by pathname.
Use Base.close
to close the file.
The IO
returned by UnixIO.open
can be used with
UnixIO.read
and UnixIO.write
. It can also be used with
the standard Base.IO
functions
(Base.read
, Base.write
, Base.readbytes!
, Base.close
etc).
See open(2)
open
returns UnixFD{FDType}
, where FDType
is one of:
FDType
├─ File
│ ├─ S_IFBLK
│ └─ S_IFREG
├─ MetaFile
│ ├─ S_IFDIR
│ └─ S_IFLNK
├─ PidFD
└─ Stream
├─ S_IFCHR
│ ├─ CanonicalMode
│ └─ Pseudoterminal
├─ S_IFIFO
└─ S_IFSOCK
If the FDType
argument is provided then open
guarantees to return
UnixIO{FDType}
(or throw an ArgumentError
if FDType
is not applicable
to pathname
.
Note: C.O_NONBLOCK
is always added to flags
to ensure compatibility with
poll(2)
.
A RawFD
can be opened in blocking mode by calling C.open
directly.
UnixIO.set_timeout(fd::UnixFD, timeout)
Configure fd
to limit IO operations to timeout
seconds.
UnixIO.tcgetattr(tty) -> C.termios_m
Get terminal device options. See tcgetattr(3).
UnixIO.tcsetattr(tty, attr::C.termios_m)
UnixIO.tcsetattr(tty) do attr
[attr.c_iflag = ...]
[attr.c_oflag = ...]
[attr.c_cflag = ...]
[attr.c_lflag = ...]
[attr.speed = ...]
end
Set terminal device options.
e.g.
io = UnixIO.open("/dev/ttyUSB0", C.O_RDWR | C.O_NOCTTY)
UnixIO.tcsetattr(io) do attr
setraw(attr)
attr.speed=9600
attr.c_lflag |= C.ICANON
end
If raw
is true
the attributes are initialised to:
attr.c_iflag = 0
attr.c_oflag = 0
attr.c_cflag = C.CS8
attr.c_lflag = 0
See tcsetattr(3) for flag descriptions.
tcflush(tty, flags)
See tcflush(3p)
tiocgwinsz(tty) -> C.winsize
See tty_ioctl(4)
UnixIO.shutdown(sockfd, how)
Shut down part of a full-duplex connection.
how
is one of C.SHUT_RD
, C.SHUT_WR
or C.SHUT_RDWR
.
See shutdown(2)
UnixIO.read(fd, buf, [count=length(buf)];
[timeout=Inf] ) -> number of bytes read
Attempt to read up to count bytes from file descriptor fd
into the buffer starting at buf
.
See read(2)
UnixIO.println(x...)
UnixIO.printerr(x...)
Write directly to STDOUT
or STDERR
.
Does not yield control from the current task.
UnixIO.socketpair() -> fd1, fd2
Create a pair of connected Unix Domain Sockets (AF_UNIX
, SOCK_STREAM
).
See socketpair(2)
UnixIO.openpt([flags = C._NOCTTY | C.O_RDWR]) -> ptfd::UnixFD, "/dev/pts/X"
Open an unused pseudoterminal device, returning: a file descriptor that can be used to refer to that device, and the path of the pseudoterminal device.
See posix_openpt(3) and prsname(3).
sh"shell command"
String containing result of shell command. e.g.
julia> println("Machine is ", sh"uname -m")
Machine is x86_64
julia> println("V: ", sh"grep version Project.toml | awk '{print$3}'")
V: "0.1.0"
UnixIO.system(command) -> exit status
See system(3)
e.g.
julia> UnixIO.system("uname -srm")
Darwin 20.3.0 x86_64
UnixIO.open(f, cmd::Cmd; [check_status=true, capture_stderr=false])
Run cmd
using posix_spawn
.
Call f(cmdin, cmdout)
with (STDIN, STDOUT) of cmd
connected to (cmdin
, cmdout
).
If capture_stderr
is true
STDERR of cmd
is merged into cmdout
.
If check_status
is true
an exception is thrown on non-zero exit status.
e.g.
julia> UnixIO.open(`hexdump -C`) do cmdin, cmdout
write(cmdin, "Hello World!")
close(cmdin)
read(cmdout, String)
end |> println
00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 |Hello World!|
0000000c
UnixIO.ptopen(f, cmd::Cmd; [env=ENV, check_status=true])
Run cmd
using posix_spawn
.
Call f(cmdin, cmdout)
with (STDIN, STDOUT and STDERR) of cmd
connected to (cmdin
, cmdout
) via a pseudoterminal.
If check_status
is true
an exception is thrown on non-zero exit status.
Run cmd
using posix_spawn
.
read(cmd::Cmd; [timeout=Inf,
check_status=true,
capture_stderr=false]) -> Vector{UInt8}
read(cmd::Cmd, String; kw...) -> String
Run cmd
using fork
and execv
.
Return byes written to stdout by cmd
.
e.g.
julia> UnixIO.read(`uname -srm`, String)
"Darwin 20.3.0 x86_64
"
UnixIO.waitpid(pid) -> status
See waitpid(3)