# Copyright (c) 2023 Yuki Kimoto
# MIT License
class Sys {
version "0.532";
use Resource::SocketUtil;
use Format;
use Sys::IO;
use Sys::IO::FileStream;
use Sys::IO::Stat;
use Sys::IO::Constant as IO;
use Sys::Ioctl;
use Sys::Select;
use Sys::Socket;
use Sys::Socket::Constant as SOCKET;
use Sys::OS;
use Sys::Env;
use Sys::Time;
use Sys::Time::Util;
use Sys::Time::Utimbuf;
use Sys::Process;
use Sys::Signal;
use Sys::User;
use Sys::Socket::Sockaddr::Storage;
static method STDIN : Sys::IO::FileStream () { return Sys::IO->spvm_stdin; }
static method STDOUT : Sys::IO::FileStream () { return Sys::IO->spvm_stdout; }
static method STDERR : Sys::IO::FileStream () { return Sys::IO->spvm_stderr; }
static method open : void ($stream_ref : Sys::IO::FileStream[], $open_mode : string, $file : string) {
unless ($stream_ref) {
die "\$stream_ref must be defined.";
}
unless (@$stream_ref == 1) {
die "The length of \$stream_ref must be equal to 1.";
}
my $fopen_mode = &to_fopen_mode($open_mode);
my $stream = Sys::IO->fopen($file, $fopen_mode);
unless (Sys::OS->is_windows) {
Sys->fcntl(Sys->fileno($stream), IO->F_SETFD, IO->FD_CLOEXEC);
}
$stream_ref->[0] = $stream;
}
static method fdopen : void ($stream_ref : Sys::IO::FileStream[], $open_mode : string, $fd : int) {
unless ($stream_ref) {
die "\$stream_ref must be defined.";
}
unless (@$stream_ref == 1) {
die "The length of \$stream_ref must be equal to 1.";
}
my $fopen_mode = &to_fopen_mode($open_mode);
my $stream = Sys::IO->fdopen($fd, $fopen_mode);
$stream_ref->[0] = $stream;
}
private static method to_fopen_mode : string ($open_mode : string) {
my $fopen_mode = (string)undef;
if ($open_mode eq "<") {
$fopen_mode = "rb";
}
elsif ($open_mode eq ">") {
$fopen_mode = "wb";
}
elsif ($open_mode eq ">>") {
$fopen_mode = "wa";
}
elsif ($open_mode eq "+<") {
$fopen_mode = "r+b";
}
elsif ($open_mode eq "+>") {
$fopen_mode = "w+b";
}
elsif ($open_mode eq "+>>") {
$fopen_mode = "a+b";
}
else {
$fopen_mode = $open_mode;
}
return $fopen_mode;
}
static method fileno : int ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
my $fd = Sys::IO->fileno($stream);
return $fd;
}
static method read : int ($stream : Sys::IO::FileStream, $buffer : mutable string, $length : int, $buffer_offset : int = 0) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
my $read_length = Sys::IO->fread($buffer, 1, $length, $stream);
return $read_length;
}
static method eof : int ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
my $eof = Sys::IO->feof($stream);
return $eof;
}
precompile static method readline : mutable string ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
my $capacity = 80;
my $buffer = (mutable string)new_string_len $capacity;
my $pos = 0;
my $end_is_eof = 0;
my $eof = IO->EOF;
while (1) {
my $ch = Sys->getc($stream);
if ($ch == $eof) {
$end_is_eof = 1;
last;
}
else {
if ($pos >= $capacity) {
my $new_capacity = $capacity * 2;
my $new_buf = (mutable string)new_string_len $new_capacity;
Fn->memcpy($new_buf, 0, $buffer, 0, $capacity);
$capacity = $new_capacity;
$buffer = $new_buf;
}
if ($ch == '\n') {
$buffer->[$pos] = (byte)$ch;
$pos++;
last;
}
else {
$buffer->[$pos] = (byte)$ch;
$pos++;
}
}
}
my $line = (mutable string)undef;
if ($pos > 0 || !$end_is_eof) {
if ($pos == 0) {
$line = (mutable string)new_string_len 0;
}
else {
$line = (mutable string)new_string_len $pos;
Fn->memcpy($line, 0, $buffer, 0, $pos);
}
}
return $line;
}
static method getc : int ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
my $char = Sys::IO->getc($stream);
return $char;
}
static method print : void ($stream : Sys::IO::FileStream, $string : string) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
Sys::IO->fwrite($string, 1, length $string, $stream);
}
static method printf : void ($stream : Sys::IO::FileStream, $format : string, $args : object[]) {
my $formated_string = Format->sprintf($format, $args);
&print($stream, $formated_string);
}
static method say : void ($stream : Sys::IO::FileStream, $string : string) {
&print($stream, $string);
&print($stream, "\n");
}
static method close : void ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
Sys::IO->fclose($stream);
}
static method seek : void ($stream : Sys::IO::FileStream, $offset : long, $whence : int) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
Sys::IO->fseek($stream, $offset, $whence);
}
static method tell : long ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The file stream \$stream must be defined.";
}
if ($stream->closed) {
die "The file stream \$stream is already closed.";
}
my $current_position = Sys::IO->ftell($stream);
return $current_position;
}
static method sysopen : void ($fd_ref : int*, $file : string, $flags : int, $mode : int = 0) {
my $fd = Sys::IO->open($file, $flags, $mode);
$$fd_ref = $fd;
}
static method sysread : int ($fd : int, $buffer : mutable string, $length : int, $buffer_offset : int = 0) {
my $read_length = Sys::IO->read($fd, $buffer, $length, $buffer_offset);
return $read_length;
}
static method syswrite : int ($fd : int, $buffer : string, $length : int = -1, $buffer_offset : int = 0) {
my $write_length = Sys::IO->write($fd, $buffer, $length, $buffer_offset);
return $write_length;
}
static method sysseek : long ($fd : int, $offset : long, $whence : int) {
my $result_offset = Sys::IO->lseek($fd, $offset, $whence);
return $result_offset;
}
static method fcntl : int ($fd : int, $command : int, $command_arg : object of Int|Sys::IO::Flock|object = undef) {
my $fcntl_ret = Sys::IO->fcntl($fd, $command, $command_arg);
return $fcntl_ret;
}
static method truncate : void ($fd : int, $legnth : long) {
Sys::IO->ftruncate($fd, $legnth);
}
static method flock : void ($fd : int, $operation : int) {
Sys::IO->flock($fd, $operation);
}
static method mkdir : void ($dir : string, $mode : int = -1) {
if ($mode < 0) {
$mode = 0777;
}
Sys::IO->mkdir($dir, $mode);
}
static method umask : int ($mode : int) {
my $current_umask = Sys::IO->umask($mode);
return $current_umask;
}
static method rmdir : void ($dir : string) {
Sys::IO->rmdir($dir);
}
static method unlink : void ($file : string) {
if (Sys::OS->is_windows) {
Sys::IO::Windows->unlink($file);
}
else {
Sys::IO->unlink($file);
}
}
static method rename : void ($old_path : string, $new_path : string) {
if (Sys::OS->is_windows) {
Sys::IO::Windows->rename($old_path, $new_path);
}
else {
Sys::IO->rename($old_path, $new_path);
}
}
static method symlink : int ($old_path : string, $new_path : string) {
if (Sys::OS->is_windows) {
Sys::IO::Windows->symlink($old_path, $new_path);
}
else {
Sys::IO->symlink($old_path, $new_path);
}
my $success = 1;
return $success;
}
static method readlink : string ($file : string) {
my $stat = Sys->lstat($file);
my $readlink_buffer_size = (int)$stat->st_size;
my $buffer = (mutable string)new_string_len $readlink_buffer_size;
if (Sys::OS->is_windows) {
Sys::IO::Windows->readlink($file, $buffer, $readlink_buffer_size);
}
else {
Sys::IO->readlink($file, $buffer, $readlink_buffer_size);
}
return $buffer;
}
static method chdir : void ($dir : string) {
Sys::IO->chdir($dir);
}
static method chmod : void ($mode :int, $file : string) {
Sys::IO->chmod($file, $mode);
}
static method chown : void ($owner : int, $group : int, $file : string) {
Sys::IO->chown($file, $owner, $group);
}
static method opendir : void ($dir_stream_ref : Sys::IO::DirStream[], $dir : string) {
my $dh = Sys::IO->opendir($dir);
$dir_stream_ref->[0] = $dh;
}
static method closedir : void ($dir_stream : Sys::IO::DirStream) {
unless ($dir_stream) {
die "The directory stream \$dir_stream must be defined.";
}
if ($dir_stream->closed) {
die "The directory stream \$dir_stream is already closed.";
}
Sys::IO->closedir($dir_stream);
}
static method readdir : Sys::IO::Dirent ($dir_stream : Sys::IO::DirStream) {
unless ($dir_stream) {
die "The directory stream \$dir_stream must be defined.";
}
if ($dir_stream->closed) {
die "The directory stream \$dir_stream is already closed.";
}
my $dirent = Sys::IO->readdir($dir_stream);
return $dirent;
}
static method rewinddir : void ($dir_stream : Sys::IO::DirStream) {
unless ($dir_stream) {
die "The directory stream \$dir_stream must be defined.";
}
if ($dir_stream->closed) {
die "The directory stream \$dir_stream is already closed.";
}
Sys::IO->rewinddir($dir_stream);
}
static method seekdir : void ($dir_stream : Sys::IO::DirStream, $offset : long) {
unless ($dir_stream) {
die "The directory stream \$dir_stream must be defined.";
}
if ($dir_stream->closed) {
die "The directory stream \$dir_stream is already closed.";
}
Sys::IO->seekdir($dir_stream, $offset);
}
static method telldir : long ($dir_stream : Sys::IO::DirStream) {
unless ($dir_stream) {
die "The directory stream \$dir_stream must be defined.";
}
if ($dir_stream->closed) {
die "The directory stream \$dir_stream is already closed.";
}
my $offset = Sys::IO->telldir($dir_stream);
return $offset;
}
static method popen : void ($stream_ref : Sys::IO::FileStream[], $open_mode : string, $command : string) {
my $type = (string)undef;
if ($open_mode eq "|-") {
$type = "wb";
}
elsif ($open_mode eq "-|") {
$type = "rb";
}
else {
die "The open mode \"$open_mode\" is not available.";
}
my $stream = (Sys::IO::FileStream)undef;
if (Sys::OS->is_windows) {
$stream = Sys::IO->_popen($command, $type);
}
else {
$stream = Sys::IO->popen($command, $type);
Sys->fcntl(Sys->fileno($stream), IO->F_SETFD, IO->FD_CLOEXEC);
}
$stream_ref->[0] = $stream;
}
static method pclose : void ($stream : Sys::IO::FileStream) {
unless ($stream) {
die "The pipe stream \$stream must be defined.";
}
if ($stream->closed) {
die "The pipe stream \$stream is already closed.";
}
if (Sys::OS->is_windows) {
Sys::IO->_pclose($stream);
}
else {
Sys::IO->pclose($stream);
}
}
static method select : int ($read_fds : Sys::Select::Fd_set, $write_fds : Sys::Select::Fd_set, $except_fds : Sys::Select::Fd_set, $timeout : double = 0) {
my $nfds = 1024;
my $timeout_tv = (Sys::Time::Timeval)undef;
if ($timeout >= 0) {
$timeout_tv = Sys::Time::Util->float_seconds_to_timeval($timeout);
}
else {
$timeout_tv = undef;
}
my $fd_number = Sys::Select->select($nfds, $read_fds, $write_fds, $except_fds, $timeout_tv);
return $fd_number;
}
static method ioctl : int ($fd : int, $request : int, $request_arg_ref : object of byte[]|short[]|int[]|long[]|float[]|double[]|object = undef) {
my $ioctl_ret = -1;
if (Sys::OS->is_windows) {
$ioctl_ret = Sys::Ioctl->ioctlsocket($fd, $request, (int[])$request_arg_ref);
}
else {
$ioctl_ret = Sys::Ioctl->ioctl($fd, $request, $request_arg_ref);
}
return $ioctl_ret;
}
static method stat : Sys::IO::Stat ($file : string) {
my $stat = Sys::IO::Stat->new;
Sys::IO::Stat->stat($file, $stat);
return $stat;
}
static method lstat : Sys::IO::Stat ($file : string) {
my $stat = Sys::IO::Stat->new;
if (Sys::OS->is_windows) {
Sys::IO::Windows->lstat($file, $stat);
}
else {
Sys::IO::Stat->lstat($file, $stat);
}
return $stat;
}
static method fstat : Sys::IO::Stat ($fd : int) {
my $stat = Sys::IO::Stat->new;
Sys::IO::Stat->fstat($fd, $stat);
return $stat;
}
static method A : double ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = Sys->stat($file);
my $result_time = $stat->A;
return $result_time;
}
static method C : double ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = Sys->stat($file);
my $result_time = $stat->C;
return $result_time;
}
static method M : double ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = Sys->stat($file);
my $result_time = $stat->M;
return $result_time;
}
static method O : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->O;
}
return $ok;
}
static method R : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->R;
}
return $ok;
}
static method S : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->S;
}
return $ok;
}
static method W : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->W;
}
return $ok;
}
static method X : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->X;
}
return $ok;
}
static method b : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->b;
}
return $ok;
}
static method c : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
# Character device
my $ok = 0;
unless ($@) {
$ok = $stat->c;
}
return $ok;
}
static method d : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->d;
}
return $ok;
}
static method e : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->e;
}
return $ok;
}
static method f : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->f;
}
return $ok;
}
static method g : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->g;
}
return $ok;
}
static method k : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->k;
}
return $ok;
}
static method l : int ($file : string) {
my $ok = 0;
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->lstat($file); }
unless ($@) {
$ok = $stat->l;
}
return $ok;
}
static method o : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->o;
}
return $ok;
}
static method p : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
# FIFO/PIPE
my $ok = 0;
unless ($@) {
$ok = $stat->p;
}
return $ok;
}
static method r : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
# Character device
my $ok = 0;
unless ($@) {
$ok = $stat->r;
}
return $ok;
}
static method s : long ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = Sys->stat($file);
my $size = $stat->s;
return $size;
}
static method u : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->u;
}
return $ok;
}
static method w : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->w;
}
return $ok;
}
static method x : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = (Sys::IO::Stat)undef;
eval { $stat = Sys->stat($file); }
my $ok = 0;
unless ($@) {
$ok = $stat->x;
}
return $ok;
}
static method z : int ($file : string) {
unless ($file) {
die "\$file must be defined.";
}
my $stat = Sys->stat($file);
my $ok = $stat->z;
return $ok;
}
static method socket : void ($socket_fd_ref : int*, $domain : int, $type : int, $protocol : int) {
$$socket_fd_ref = Sys::Socket->socket($domain, $type, $protocol);
unless (Sys::OS->is_windows) {
Sys->fcntl($$socket_fd_ref, IO->F_SETFD, IO->FD_CLOEXEC);
}
}
static method connect : void ($socket_fd : int, $sockaddr : Sys::Socket::Sockaddr) {
my $sockaddr_size = $sockaddr->size;
Sys::Socket->connect($socket_fd, $sockaddr, $sockaddr_size);
}
static method bind : void ($socket_fd : int, $sockaddr : Sys::Socket::Sockaddr) {
my $sockaddr_size = $sockaddr->size;
Sys::Socket->bind($socket_fd, $sockaddr, $sockaddr_size);
}
static method listen : void ($socket_fd : int, $backlog : int) {
Sys::Socket->listen($socket_fd, $backlog);
}
static method accept : Sys::Socket::Sockaddr ($client_fd_ref : int*, $server_fd : int) {
my $sockaddr = Sys::Socket::Sockaddr->new;
my $sockaddr_size = Sys::Socket::Sockaddr::Storage->new->size;
$$client_fd_ref = Sys::Socket->accept($server_fd, $sockaddr, \$sockaddr_size);
unless (Sys::OS->is_windows) {
Sys->fcntl($$client_fd_ref, IO->F_SETFD, IO->FD_CLOEXEC);
}
$sockaddr = $sockaddr->upgrade;
return $sockaddr;
}
static method recv : int ($socket_fd : int, $buffer : mutable string, $length : int, $flags : int, $buffer_offset : int = 0) {
my $recv_length = Sys::Socket->recv($socket_fd, $buffer, $length, $flags, $buffer_offset);
return $recv_length;
}
static method recvfrom : int ($socket_fd : int, $buffer : mutable string, $length : int, $flags : int, $sockaddr_ref : Sys::Socket::Sockaddr[], $buffer_offset : int = 0) {
my $sockaddr = (Sys::Socket::Sockaddr)undef;
my $addrlen = -1;
if ($sockaddr_ref) {
unless (@$sockaddr_ref == 1) {
die "If \$sockaddr_ref for an array for a peer socket address for output is defined, the length must be 1.";
}
$sockaddr = Sys::Socket::Sockaddr->new;
}
my $recv_length = Sys::Socket->recvfrom($socket_fd, $buffer, $length, $flags, $sockaddr, \$addrlen, $buffer_offset);
if ($sockaddr_ref) {
$sockaddr = $sockaddr->upgrade;
$sockaddr_ref->[0] = $sockaddr;
}
return $recv_length;
}
static method send : int ($socket_fd : int, $buffer : string, $flags : int, $length : int = -1, $buffer_offset : int = 0) {
if ($length < 0) {
$length = length $buffer;
}
my $send_length = Sys::Socket->send($socket_fd, $buffer, $length, $flags, $buffer_offset);
return $send_length;
}
static method sendto : int ($socket_fd : int, $buffer : string, $flags : int, $sockaddr : Sys::Socket::Sockaddr, $length : int = -1, $buffer_offset : int = 0) {
if ($length < 0) {
$length = length $buffer;
}
my $addrlen = -1;
if ($sockaddr) {
$addrlen = $sockaddr->size;
}
my $send_length = Sys::Socket->sendto($socket_fd, $buffer, $length, $flags, $sockaddr, $addrlen, $buffer_offset);
return $send_length;
}
static method shutdown : void ($socket_fd : int, $how : int) {
Sys::Socket->shutdown($socket_fd, $how);
}
static method getpeername : Sys::Socket::Sockaddr ($socket_fd : int) {
my $sockaddr_size = Sys::Socket::Sockaddr::Storage->new->size;
my $sockaddr = Sys::Socket::Sockaddr->new;
Sys::Socket->getpeername($socket_fd, $sockaddr, \$sockaddr_size);
$sockaddr = $sockaddr->upgrade;
return $sockaddr;
}
static method getsockname : Sys::Socket::Sockaddr ($socket_fd : int) {
my $sockaddr_size = Sys::Socket::Sockaddr::Storage->new->size;
my $sockaddr = Sys::Socket::Sockaddr->new;
Sys::Socket->getsockname($socket_fd, $sockaddr, \$sockaddr_size);
$sockaddr = $sockaddr->upgrade;
return $sockaddr;
}
static method socketpair : void ($socket_fd1_ref : int*, $socket_fd2_ref : int*, $domain : int, $type : int, $protocol : int) {
my $pair = new int[2];
Sys::Socket->socketpair($domain, $type, $protocol, $pair);
$$socket_fd1_ref = $pair->[0];
$$socket_fd2_ref = $pair->[1];
unless (Sys::OS->is_windows) {
Sys->fcntl($$socket_fd1_ref, IO->F_SETFD, IO->FD_CLOEXEC);
Sys->fcntl($$socket_fd2_ref, IO->F_SETFD, IO->FD_CLOEXEC);
}
}
static method setsockopt : void ($socket_fd : int, $level : int, $option_name : int, $option_value : object of string|Int) {
unless ($option_value) {
die "\$option_value must be defined.";
}
if ($option_value is_type Int) {
my $option_value_ref = [$option_value->(Int)->value];
my $option_value_string = new_string_len 4;
Fn->memcpy($option_value_string, 0, $option_value_ref, 0, 4);
Sys::Socket->setsockopt($socket_fd, $level, $option_name, $option_value_string, 4);
}
elsif ($option_value is_type string) {
my $option_value_string = (string)$option_value;
Sys::Socket->setsockopt($socket_fd, $level, $option_name, $option_value_string, length $option_value_string);
}
else {
die "The type of \$option_value must be the Int or string type.";
}
}
static method getsockopt : string ($socket_fd : int, $level : int, $option_name : int, $option_value_length : int = -1) {
unless ($option_value_length >= 0) {
$option_value_length = 4;
}
my $option_value = (mutable string)new_string_len $option_value_length;
Sys::Socket->getsockopt($socket_fd, $level, $option_name, $option_value, \$option_value_length);
return $option_value;
}
static method osname : string () {
my $osname : string;
if (Sys::OS->defined("__linux__")) {
$osname = "linux";
}
elsif (Sys::OS->defined("_WIN32")) {
$osname = "MSWin32";
}
elsif (Sys::OS->defined("__FreeBSD__")) {
$osname = "freebsd";
}
elsif (Sys::OS->defined("__OpenBSD__")) {
$osname = "openbsd";
}
elsif (Sys::OS->defined("__solaris")) {
$osname = "solaris";
}
elsif (Sys::OS->defined("__sun")) {
$osname = "solaris";
}
elsif (Sys::OS->defined("__APPLE__")) {
$osname = "darwin";
}
else {
die "The OS name could not be determined.";
}
return $osname;
}
static method env : string ($name : string) {
my $env_value = Sys::Env->getenv($name);
return $env_value;
}
static method set_env : void ($name : string, $value : string) {
if (Sys::OS->is_windows) {
unless ($value) {
$value = "";
}
Sys::Env->_putenv_s($name, $value);
}
else {
if ($value && $value ne "") {
my $overwrite = 1;
Sys::Env->setenv($name, $value, $overwrite);
}
else {
Sys::Env->unsetenv($name);
}
}
}
static method time : long () {
my $time = Sys::Time->time();
return $time;
}
static method localtime : Sys::Time::Tm ($epoch : long = -1, $allow_minus : int = 0) {
unless ($allow_minus) {
if ($epoch < 0) {
$epoch = Sys->time;
}
}
my $tm = Sys::Time->localtime(\$epoch);
return $tm;
}
static method gmtime : Sys::Time::Tm ($epoch : long = -1, $allow_minus : int = 0) {
unless ($allow_minus) {
if ($epoch < 0) {
$epoch = Sys->time;
}
}
my $tm = Sys::Time->gmtime(\$epoch);
return $tm;
}
static method utime : void ($atime : long, $mtime : long, $file : string) {
my $utimbuf = (Sys::Time::Utimbuf)undef;
if ($atime < 0 && $mtime < 0) {
# Set current time
}
else {
$utimbuf = Sys::Time::Utimbuf->new;
$utimbuf->set_actime($atime);
$utimbuf->set_modtime($mtime);
}
Sys::Time->utime($file, $utimbuf);
}
static method signal : Sys::Signal::Handler ($signal_number : int, $handler_name : string) {
my $handler = (Sys::Signal::Handler)undef;
if ($handler_name eq "IGNORE") {
$handler = Sys::Signal->SIG_IGN;
}
elsif ($handler_name eq "DEFAULT") {
$handler = Sys::Signal->SIG_DFL;
}
else {
die "\$handler_name \"$handler_name\" is not available.";
}
my $old_handler = Sys::Signal->signal($signal_number, $handler);
return $old_handler;
}
static method kill : void ($signal_number : int, $process_id : int) {
if (Sys::OS->is_windows) {
if ($process_id == Sys->process_id) {
Sys::Signal->raise($signal_number);
}
else {
die "\$process_id must be equal to Sys->process_id in Windows.";
}
}
else {
Sys::Signal->kill($process_id, $signal_number);
}
}
static method alarm : int ($seconds : int) {
Sys::Signal->alarm($seconds);
}
static method fork : int () {
my $child_process_id = Sys::Process->fork;
return $child_process_id;
}
static method getpriority : int ($which : int, $who : int) {
my $priority = Sys::Process->getpriority($which, $who);
return $priority;
}
static method setpriority : void ($which : int, $who : int, $priority : int) {
Sys::Process->setpriority($which, $who, $priority);
}
static method sleep : int ($seconds : int) {
my $slept_number = Sys::Process->sleep($seconds);
return $slept_number;
}
static method wait : int ($wstatus_ref : int*) {
my $process_id = Sys::Process->wait($wstatus_ref);
return $process_id;
}
static method waitpid : int ($process_id : int, $options : int, $wstatus_ref : int*) {
my $process_id_status_changed = Sys::Process->waitpid($process_id, $wstatus_ref, $options);
return $process_id_status_changed;
}
static method system : int ($command : string) {
my $wstatus = Sys::Process->system($command);
return $wstatus;
}
static method exit : void ($status : int) {
Sys::Process->exit($status);
}
static method pipe : void ($read_fd_ref : int*, $write_fd_ref : int*) {
my $pipe_fds = new int[2];
if (Sys::OS->is_windows) {
Sys::Process->_pipe($pipe_fds, 0, IO->O_BINARY);
}
else {
Sys::Process->pipe($pipe_fds);
Sys->fcntl($pipe_fds->[0], IO->F_SETFD, IO->FD_CLOEXEC);
Sys->fcntl($pipe_fds->[1], IO->F_SETFD, IO->FD_CLOEXEC);
}
$$read_fd_ref = $pipe_fds->[0];
$$write_fd_ref = $pipe_fds->[1];
}
static method getpgrp : int ($process_id : int) {
my $process_group_id = Sys::Process->getpgid($process_id);
return $process_group_id;
}
static method setpgrp : void ($process_id : int, $process_group_id : int) {
Sys::Process->setpgid($process_id, $process_group_id);
}
static method process_id : int () {
my $process_id = Sys::Process->getpid();
return $process_id;
}
static method getppid : int () {
my $parent_process_id = Sys::Process->getppid();
return $parent_process_id;
}
static method exec : void ($program : string, $args : string[] = undef) {
my $exec_args_list = StringList->new;
$exec_args_list->push($program);
if ($args) {
for (my $i = 0; $i < @$args; $i++) {
my $arg = $args->[$i];
$exec_args_list->push($arg);
}
}
my $execv_args = $exec_args_list->to_array;
Sys::Process->execv($program, $execv_args);
}
static method real_user_id : int () {
my $real_user_id = Sys::User->getuid;
return $real_user_id;
}
static method effective_user_id : int () {
my $effective_user_id = Sys::User->geteuid;
return $effective_user_id;
}
static method real_group_id : int () {
my $real_group_id = Sys::User->getgid;
return $real_group_id;
}
static method effective_group_id : int () {
my $effective_group_id = Sys::User->getegid();
return $effective_group_id;
}
static method set_real_user_id : void ($uid : int) {
Sys::User->setuid($uid);
}
static method set_effective_user_id : void ($euid : int) {
Sys::User->seteuid($euid);
}
static method set_real_group_id : void ($real_group_id : int) {
Sys::User->setgid($real_group_id);
}
static method set_effective_group_id : void ($effective_group_id : int) {
Sys::User->setegid($effective_group_id);
}
static method setpwent : void () {
Sys::User->setpwent;
}
static method endpwent : void () {
Sys::User->endpwent;
}
static method getpwent : Sys::User::Passwd () {
my $pwent = Sys::User->getpwent;
return $pwent;
}
static method setgrent : void () {
Sys::User->setgrent;
}
static method endgrent : void () {
Sys::User->endgrent;
}
static method getgrent : Sys::User::Group () {
my $grent = Sys::User->getgrent;
return $grent;
}
static method getgroups : int[] () {
my $group_ids_length = Sys::User->getgroups(0, undef);
my $group_ids = new int [$group_ids_length];
Sys::User->getgroups($group_ids_length, $group_ids);
return $group_ids;
}
static method setgroups : void ($group_ids : int[]) {
Sys::User->setgroups($group_ids);
}
static method getpwuid : Sys::User::Passwd ($id : int) {
my $pwent = Sys::User->getpwuid($id);
return $pwent;
}
static method getpwnam : Sys::User::Passwd ($name : string) {
my $pwent = Sys::User->getpwnam($name);
return $pwent;
}
static method getgrgid : Sys::User::Group ($id : int) {
my $grent = Sys::User->getgrgid($id);
return $grent;
}
static method getgrnam : Sys::User::Group ($name : string) {
my $grent = Sys::User->getgrnam($name);
return $grent;
}
static method srand : void ($seed : int) {
Fn->set_seed($seed);
}
static method rand : double ($max : int = 1) {
my $seed_initialized = Fn->seed_initialized;
my $seed = 0;
if ($seed_initialized) {
$seed = Fn->get_seed;
}
else {
$seed = &process_id * (int)&time;
}
my $random_number = Fn->rand(\$seed, $max);
&srand($seed);
return $random_number;
}
}