#!/usr/bin/env lua
--[[ Operating System Interface Nativ Implemented Functions
--
Library is DEPRECATED and split into two:
https://holmeinbuch.de/repo/osm/ -> more functions - extends Lua os
https://holmeinbuch.de/repo/osn/ -> network (socket) part: connect/serve
There is no goal to implement every posix call for every operating system.
It supports the calls I need to interact with the system.
The interface uses Lua style (string instead of int flags)
The library is implemented for Linux.
For general purpose, check out:
https://github.com/luaposix/luaposix
https://github.com/wahern/cqueues
]]
local osinif = require("osinif")
--[[ bgexec
arg1: external program
optional arg2 - argX
return:
arg1: pid
return on error: nil, message[, errno]
]]
print("bgexec(\"echo\", \" bgexec child: Hello\")", osinif.bgexec("echo", " bgexec child: Hello"))
--[[ bgwait
optional arg1: number pid or -1
-> without arg1 (or 0) bgwait will return immediately
-> -1 will wait for any child
return:
arg1: pid or 0
-> 0, if no bgexec ended, there will be no other args returned
optional arg2: exit code
-> if signal exit code will be 128 + signal number
optional arg3: signal / error message
-> error message will be set, if bgexec failed to start program
return on error: nil, message[, errno]
]]
print("bgwait(-1)", osinif.bgwait(-1))
print("bgwait(-1)", osinif.bgwait(-1))
local s_test_temp_path = "/tmp/test_osinif.dir"
--[[ mkdir
arg1: string path -> no recursive creation
optional arg2: string mode
return:
arg1: boolean true
return on error: nil, message[, errno]
]]
print(string.format("mkdir(\"%s\")", s_test_temp_path), osinif.mkdir(s_test_temp_path))
--[[ mkfile
WHY? -> will "exclusive" create a file, fail, if it exists
arg1: string path
optional arg2: string mode
optional arg3: boolean -> request file
return:
arg1: boolean true or file (if in arg3 is true)
return on file exist: false, message
return on error: nil, message[, errno]
]]
local s_test_temp_file = "/tmp/test_osinif.file"
local f_test_temp = osinif.mkfile(s_test_temp_file, nil, true)
print(string.format("mkfile(\"%s\", nil, true)", s_test_temp_file), f_test_temp)
f_test_temp:close()
--[[ chmod
arg1: string path
arg2: string mode (set permission in numeric mode, by up to 4 octal digits)
-> 1st: suid=4, sgid=2, sticky=1 / 2nd=u,3rd=g,4th=o: r=4, w=2, x=1
-> no parsing of "u+rw" style - can be implemented in Lua, if required
return:
arg1: boolean true
return on error: nil, message[, errno]
]]
print(string.format("chmod(\"%s\", \"%s\")", s_test_temp_path, "700"), osinif.chmod(s_test_temp_path, "700"))
--[[ fmode
arg1: string filename (or stat table)
return:
arg1: string octal mode
return on error: nil, message[, errno]
]]
print(string.format("fmode(\"%s\")", s_test_temp_path), osinif.fmode(s_test_temp_path))
print(string.format("fmode(\"%s\")", s_test_temp_file), osinif.fmode(s_test_temp_file))
--[[ ftype
arg1: string filename (or stat table)
return:
arg1: string: "socket", "symlink", "file", "bdev", "dir", "cdev", "fifo"
return on error: nil, message[, errno]
]]
print(string.format("ftype(\"%s\")", s_test_temp_path), osinif.ftype(s_test_temp_path))
print(string.format("ftype(\"%s\")", s_test_temp_file), osinif.ftype(s_test_temp_file))
print(string.format("os.remove(\"%s\")", s_test_temp_file), os.remove(s_test_temp_file))
--[[ getpid
return:
arg1: integer pid
]]
print("getpid()", osinif.getpid())
--[[ gettime
optional arg1: string: "r[ealtime]" (default), "t[ai]", "m[onotonic]", "c[putime]"
- only the first letter (lowercase) is important
return:
arg1: integer seconds
arg2: integer nanoseconds
return on error: nil, message[, errno]
]]
print("gettime()", osinif.gettime())
--[[ lip -- list ip -> iterator
arg1: string name
optional arg2: string: "[IPv]4" (default), [IPv]6, ANY
return:
iteratorfunction return:
arg1: string ip
arg2: string family (IPv4, IPv6)
return on error: iteratorfunction, message
error iteratorfunction return:
arg1: nil
arg2: error
]]
print("lip(\"localhost\", \"\")")
-- set to "ANY"
for ip, family in osinif.lip("localhost", "") do
print(" -", ip, family)
end
--[[ ls -- list (dir) -> iterator
optional arg1: string dir - default: current dir
iteratorfunction return:
arg1: string file
-> it will NOT return "." and ".."
return on error: iteratorfunction, message
error iteratorfunction return:
arg1: nil
arg2: error
]]
print("ls()")
for file in osinif.ls() do
print(" -", file)
end
--[[ realpath
arg1: string filename
return:
arg1: string realpath
return on error: nil, message[, errno]
]]
print(string.format("realpath(\"%s\")", s_test_temp_path), osinif.realpath(s_test_temp_path))
--[[ stat
arg1: string filename
return:
arg1: table stat: "dev", "inode", "mode", "nlink", "uid", "gid", "size", "blksize", "blocks", "atime", "mtime", "mtins", "ctime"
-> fmode and ftype are extra (metatable) fields, which will call these functions
return on error: nil, message[, errno]
]]
print(string.format("stat(\"%s\")", s_test_temp_path), osinif.stat(s_test_temp_path))
local t_stat = osinif.stat(s_test_temp_path)
for k, v in pairs(t_stat) do
print(" -", k, v)
end
print(" +", "fmode", t_stat.fmode)
print(" +", "ftype", t_stat.ftype)
--[[ utime
arg1: string filename
optional arg2: number atime or false
optional arg3: number mtime or false
-> false will not update the time, if no time given NOW (in ns) is used
return on error: nil, message[, errno]
]]
print(string.format("utime(\"%s\", false, 12345678)", s_test_temp_path), osinif.utime(s_test_temp_path, false, 12345678))
print(" - atime:", osinif.stat(s_test_temp_path).atime)
print(" - mtime:", osinif.stat(s_test_temp_path).mtime)
--[[ rmdir
arg1: string path
return:
arg1: boolean true
return on error: nil, message[, errno]
]]
print(string.format("rmdir(\"%s\") => %s", s_test_temp_path, osinif.rmdir(s_test_temp_path)))
--[[
==== socket ====
socket errors:
nil, error message[, errno]
special error messages:
nil, "closed" socket is closed (may apply only to receive OR send)
nil, "timeout" receiving/sending did run into a timeout
-> on receive there might be:
"", "timeout" (just retry)
nil, "timeout" (better give up)
nil, "signal", sig, message, signo
-> sig is one of: {"int", "term", "pipe", "usr1", "usr2"}
== connect / serve ==
connect to a server / start a server
arg1: table:
=> port or usock must be set
- usock: string unix socket path
- port: string port (or service)
- ip: string ip (or name)
=> all other are optional
- family: string - default, depends on IP
- protocol: string - "[t]cp" (default), "[u]dp"
- tcp_nodelay: boolean (advanced setting, default false)
=> connect supports:
- connect_timeout: integer timeout in milliseconds
=> serve supports:
- remove_socket_before_start: boolean (default false)
- socket_mode: string mode
return:
arg1: socket (connected or bind)
arg2 (udp): -> server address (required for send)
return on error: nil, message[, errno]
== close ==
return:
arg1: true
return on error: nil, message[, errno]
=== listen socket ===
exist only for tcp -> serve
== accept ==
return:
arg1: socket (connected)
return on error: nil, message[, errno]
=== connected socket ===
== getpeername ==
return:
arg1: string ip / unix socket path
arg2: port
return on error: nil, message[, errno]
== receive ==
arg1: integer size
optional arg2: long polling - "BLOCK" (forever) or n seconds (0 < n)
return:
arg1: string read
arg2 (udp): -> sender address (required for send)
return on error: nil, message[, errno]
== send ==
arg1: string data
arg2 (udp): -> receiver address
return:
arg1: integer size
return on error: nil, message[, errno]
]]