From d45768de3e6f7b28bfecf4d19b192ccac9ce5dc2 Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Thu, 9 Nov 2023 23:03:21 +0100 Subject: feat(*): add environment variable and random functions --- CHANGELOG.md | 48 ++++++ LICENSE | 20 --- LICENSE.md | 21 +++ README.md | 29 ++-- appveyor.yml | 2 +- config.ld | 16 ++ doc_topics/01-introduction.md | 12 ++ doc_topics/ldoc.css | 291 +++++++++++++++++++++++++++++++++++ luasystem-scm-0.rockspec | 6 +- rockspecs/luasystem-0.2.1-1.rockspec | 2 +- spec/01-time_spec.lua | 77 +++++++++ spec/02-random_spec.lua | 47 ++++++ spec/03-environment_spec.lua | 81 ++++++++++ spec/time_spec.lua | 31 ---- src/Makefile | 4 +- src/compat.h | 27 ++++ src/core.c | 14 ++ src/environment.c | 173 +++++++++++++++++++++ src/random.c | 117 ++++++++++++++ src/time.c | 87 +++++++---- 20 files changed, 1004 insertions(+), 101 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 LICENSE create mode 100644 LICENSE.md create mode 100644 config.ld create mode 100644 doc_topics/01-introduction.md create mode 100644 doc_topics/ldoc.css create mode 100644 spec/01-time_spec.lua create mode 100644 spec/02-random_spec.lua create mode 100644 spec/03-environment_spec.lua delete mode 100644 spec/time_spec.lua create mode 100644 src/environment.c create mode 100644 src/random.c diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..56d1886 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# CHANGELOG + +## Versioning + +This library is versioned based on Semantic Versioning ([SemVer](https://semver.org/)). + +#### Version scoping + +The scope of what is covered by the version number excludes: + +- error messages; the text of the messages can change, unless specifically documented. + +#### Releasing new versions + +- create a release branch +- update the changelog below +- update version and copyright-years in `./LICENSE.md` and `./src/time.c` (in module constants) +- create a new rockspec and update the version inside the new rockspec:
+ `cp luasystem-scm-0.rockspec ./rockspecs/luasystem-X.Y.Z-1.rockspec` +- clean and render the docs: run `ldoc .` +- commit the changes as `Release vX.Y.Z` +- push the commit, and create a release PR +- after merging tag the release commit with `vX.Y.Z` +- upload to LuaRocks:
+ `luarocks upload ./rockspecs/luasystem-X.Y.Z-1.rockspec --api-key=ABCDEFGH` +- test the newly created rock:
+ `luarocks install luasystem` + +## Version history + +### Version X.Y.Z, unreleased + +- Feat: on Windows `sleep` now has a precision parameter +- Feat: `setenv` added to set environment variables. +- Feat: `getenvs` added to list environment variables. +- Feat: `getenv` added to get environment variable previously set (Windows). +- Feat: `random` added to return high-quality random bytes +- Feat: `isatty` added to check if a file-handle is a tty + +### Version 0.2.1, released 02-Oct-2016 + +### Version 0.2.0, released 08-May-2016 + +### Version 0.1.1, released 10-Apr-2016 + +### Version 0.1.0, released 11-Feb-2016 + +- initial release diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 0421a4a..0000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -MIT License Terms -================= - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..df2befb --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +### Copyright (c) 2016-2023 Oscar Lim + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 3aac3a1..6f3c9f6 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,21 @@ -LuaSystem -====== - -[![travis-ci status](https://travis-ci.org/o-lim/luasystem.svg?branch=master)](https://travis-ci.org/o-lim/luasystem/builds) +[![Unix build](https://img.shields.io/github/actions/workflow/status/lunarmodules/luasystem/unix_build.yml?branch=master&label=Unix%20build&logo=linux)](https://github.com/lunarmodules/luasystem/actions/workflows/unix_build.yml) +[![AppVeyor build status](https://img.shields.io/appveyor/build/Tieske/luasystem/master?label=Windows%20build&logo=windows)](https://ci.appveyor.com/project/Tieske/luasystem/branch/master) +[![Lint](https://github.com/lunarmodules/luasystem/workflows/Lint/badge.svg)](https://github.com/lunarmodules/luasystem/actions/workflows/lint.yml) +[![SemVer](https://img.shields.io/github/v/tag/lunarmodules/luasystem?color=brightgreen&label=SemVer&logo=semver&sort=semver)](CHANGELOG.md) +# LuaSystem luasystem is a platform independent system call library for Lua. -Supports Lua >= 5.1 and luajit >= 2.0.0. +Supports Unix, Windows, MacOS, `Lua >= 5.1` and `luajit >= 2.0.0`. + +## License and copyright + +See [LICENSE.md](LICENSE.md) + +## Documentation -Currently the following functions are supported: -* gettime -* monotime -* sleep +See [online documentation](https://lunarmodules.github.io/luasystem/) -License -------- +## Changelog & Versioning -This code and its accompanying README are -[MIT licensed](http://www.opensource.org/licenses/mit-license.php). -See LICENSE for details. +See [CHANGELOG.md](CHANGELOG.md) diff --git a/appveyor.yml b/appveyor.yml index 596c846..f39445b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,4 +26,4 @@ build_script: - luarocks make test_script: - - busted + - busted --Xoutput "--color" diff --git a/config.ld b/config.ld new file mode 100644 index 0000000..c13936d --- /dev/null +++ b/config.ld @@ -0,0 +1,16 @@ +project='Lua-System' +title='Lua-System docs' +description='Platform independent system calls for Lua' + +format='markdown' +use_markdown_titles = true +style="./doc_topics/" + +file={'./src/', './system/'} +topics={'./doc_topics/', './LICENSE.md', './CHANGELOG.md'} +-- examples = {'./examples'} + +dir='docs' +sort=true +sort_modules=true +all=false diff --git a/doc_topics/01-introduction.md b/doc_topics/01-introduction.md new file mode 100644 index 0000000..9cc2347 --- /dev/null +++ b/doc_topics/01-introduction.md @@ -0,0 +1,12 @@ +# 1. Introduction + +luasystem is a platform independent system call library for Lua. +Supports Unix, Windows, MacOS, `Lua >= 5.1` and `luajit >= 2.0.0`. + +Lua is typically platform independent, but it requires adhering to very old C +standards. This in turn means that many common features (according to todays standards) +are not available. This module attempts to overcome some of those hurdles by providing +functions that cover those common needs. + +This is not a kitchen sink library, but a minimalistic one with a focus on platform +independence. diff --git a/doc_topics/ldoc.css b/doc_topics/ldoc.css new file mode 100644 index 0000000..5b9fbbf --- /dev/null +++ b/doc_topics/ldoc.css @@ -0,0 +1,291 @@ +body { + color: #47555c; + font-size: 16px; + font-family: "Open Sans", sans-serif; + margin: 0; + background: #eff4ff; +} + +a:link { color: #008fee; } +a:visited { color: #008fee; } +a:hover { color: #22a7ff; } + +h1 { font-size:26px; font-weight: normal; } +h2 { font-size:22px; font-weight: normal; } +h3 { font-size:18px; font-weight: normal; } +h4 { font-size:16px; font-weight: bold; } + +hr { + height: 1px; + background: #c1cce4; + border: 0px; + margin: 15px 0; +} + +code, tt { + font-family: monospace; +} +span.parameter { + font-family: monospace; + font-weight: bold; + color: rgb(99, 115, 131); +} +span.parameter:after { + content:":"; +} +span.types:before { + content:"("; +} +span.types:after { + content:")"; +} +.type { + font-weight: bold; font-style:italic +} + +p.name { + font-family: "Andale Mono", monospace; +} + +#navigation { + float: left; + background-color: white; + border-right: 1px solid #d3dbec; + border-bottom: 1px solid #d3dbec; + + width: 14em; + vertical-align: top; + overflow: visible; +} + +#navigation br { + display: none; +} + +#navigation h1 { + background-color: white; + border-bottom: 1px solid #d3dbec; + padding: 15px; + margin-top: 0px; + margin-bottom: 0px; +} + +#navigation h2 { + font-size: 18px; + background-color: white; + border-bottom: 1px solid #d3dbec; + padding-left: 15px; + padding-right: 15px; + padding-top: 10px; + padding-bottom: 10px; + margin-top: 30px; + margin-bottom: 0px; +} + +#content h1 { + background-color: #2c3e67; + color: white; + padding: 15px; + margin: 0px; +} + +#content h2 { + background-color: #6c7ea7; + color: white; + padding: 15px; + padding-top: 15px; + padding-bottom: 15px; + margin-top: 0px; +} + +#content h2 a { + background-color: #6c7ea7; + color: white; + text-decoration: none; +} + +#content h2 a:hover { + text-decoration: underline; +} + +#content h3 { + font-style: italic; + padding-top: 15px; + padding-bottom: 4px; + margin-right: 15px; + margin-left: 15px; + margin-bottom: 5px; + border-bottom: solid 1px #bcd; +} + +#content h4 { + margin-right: 15px; + margin-left: 15px; + border-bottom: solid 1px #bcd; +} + +#content pre { + margin: 15px; +} + +pre { + background-color: rgb(50, 55, 68); + color: white; + border-radius: 3px; + /* border: 1px solid #C0C0C0; /* silver */ + padding: 15px; + overflow: auto; + font-family: "Andale Mono", monospace; +} + +#content ul pre.example { + margin-left: 0px; +} + +table.index { +/* border: 1px #00007f; */ +} +table.index td { text-align: left; vertical-align: top; } + +#navigation ul +{ + font-size:1em; + list-style-type: none; + margin: 1px 1px 10px 1px; + padding-left: 20px; +} + +#navigation li { + text-indent: -1em; + display: block; + margin: 3px 0px 0px 22px; +} + +#navigation li li a { + margin: 0px 3px 0px -1em; +} + +#content { + margin-left: 14em; +} + +#content p { + padding-left: 15px; + padding-right: 15px; +} + +#content table { + padding-left: 15px; + padding-right: 15px; + background-color: white; +} + +#content p, #content table, #content ol, #content ul, #content dl { + max-width: 900px; +} + +#about { + padding: 15px; + padding-left: 16em; + background-color: white; + border-top: 1px solid #d3dbec; + border-bottom: 1px solid #d3dbec; +} + +table.module_list, table.function_list { + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; + margin: 15px; +} +table.module_list td, table.function_list td { + border-width: 1px; + padding-left: 10px; + padding-right: 10px; + padding-top: 5px; + padding-bottom: 5px; + border: solid 1px rgb(193, 204, 228); +} +table.module_list td.name, table.function_list td.name { + background-color: white; min-width: 200px; border-right-width: 0px; +} +table.module_list td.summary, table.function_list td.summary { + background-color: white; width: 100%; border-left-width: 0px; +} + +dl.function { + margin-right: 15px; + margin-left: 15px; + border-bottom: solid 1px rgb(193, 204, 228); + border-left: solid 1px rgb(193, 204, 228); + border-right: solid 1px rgb(193, 204, 228); + background-color: white; +} + +dl.function dt { + color: rgb(99, 123, 188); + font-family: monospace; + border-top: solid 1px rgb(193, 204, 228); + padding: 15px; +} + +dl.function dd { + margin-left: 15px; + margin-right: 15px; + margin-top: 5px; + margin-bottom: 15px; +} + +#content dl.function dd h3 { + margin-top: 0px; + margin-left: 0px; + padding-left: 0px; + font-size: 16px; + color: rgb(128, 128, 128); + border-bottom: solid 1px #def; +} + +#content dl.function dd ul, #content dl.function dd ol { + padding: 0px; + padding-left: 15px; + list-style-type: none; +} + +ul.nowrap { + overflow:auto; + white-space:nowrap; +} + +.section-description { + padding-left: 15px; + padding-right: 15px; +} + +/* stop sublists from having initial vertical space */ +ul ul { margin-top: 0px; } +ol ul { margin-top: 0px; } +ol ol { margin-top: 0px; } +ul ol { margin-top: 0px; } + +/* make the target distinct; helps when we're navigating to a function */ +a:target + * { + background-color: #FF9; +} + + +/* styles for prettification of source */ +pre .comment { color: #bbccaa; } +pre .constant { color: #a8660d; } +pre .escape { color: #844631; } +pre .keyword { color: #ffc090; font-weight: bold; } +pre .library { color: #0e7c6b; } +pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } +pre .string { color: #8080ff; } +pre .number { color: #f8660d; } +pre .operator { color: #2239a8; font-weight: bold; } +pre .preprocessor, pre .prepro { color: #a33243; } +pre .global { color: #c040c0; } +pre .user-keyword { color: #800080; } +pre .prompt { color: #558817; } +pre .url { color: #272fc2; text-decoration: underline; } diff --git a/luasystem-scm-0.rockspec b/luasystem-scm-0.rockspec index 74e301d..96f10ae 100644 --- a/luasystem-scm-0.rockspec +++ b/luasystem-scm-0.rockspec @@ -11,7 +11,7 @@ version = package_version.."-"..rockspec_revision source = { url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "scm") and "master" or nil, - tag = (package_version ~= "scm") and package_version or nil, + tag = (package_version ~= "scm") and "v"..package_version or nil, } description = { @@ -39,13 +39,13 @@ local function make_platform(plat) linux = { "rt" }, unix = { }, macosx = { }, - win32 = { }, + win32 = { "advapi32", "winmm" }, mingw32 = { }, } return { modules = { ['system.core'] = { - sources = { 'src/core.c', 'src/compat.c', 'src/time.c', }, + sources = { 'src/core.c', 'src/compat.c', 'src/time.c', 'src/environment.c', 'src/random.c' }, defines = defines[plat], libraries = libraries[plat], }, diff --git a/rockspecs/luasystem-0.2.1-1.rockspec b/rockspecs/luasystem-0.2.1-1.rockspec index 7d8b9b0..e14118d 100644 --- a/rockspecs/luasystem-0.2.1-1.rockspec +++ b/rockspecs/luasystem-0.2.1-1.rockspec @@ -11,7 +11,7 @@ version = package_version.."-"..rockspec_revision source = { url = "git+https://github.com/"..github_account_name.."/"..github_repo_name..".git", branch = (package_version == "scm") and "master" or nil, - tag = (package_version ~= "scm") and package_version or nil, + tag = (package_version ~= "scm") and "v"..package_version or nil, } description = { diff --git a/spec/01-time_spec.lua b/spec/01-time_spec.lua new file mode 100644 index 0000000..80faa75 --- /dev/null +++ b/spec/01-time_spec.lua @@ -0,0 +1,77 @@ +local system = require 'system.core' + +describe('Test time functions', function() + + -- returns the new second, on the new second + local function wait_for_second_rollover() + local start_time = math.floor(os.time()) + local end_time = math.floor(os.time()) + while end_time == start_time do + end_time = math.floor(os.time()) + end + return end_time + end + + + describe("time()", function() + + it('returns current time', function() + wait_for_second_rollover() + local expected_time = wait_for_second_rollover() + local received_time = system.gettime() + assert.is.near(expected_time, received_time, 0.02) + + wait_for_second_rollover() + assert.is.near(1, system.gettime() - received_time, 0.02) + end) + + end) + + + + describe("monotime()", function() + + it('returns monotonically increasing time', function() + local starttime = system.monotime() + local endtime = system.monotime() + local delta = endtime - starttime + assert.is_true(starttime > 0) + assert.is_true(delta >= 0) + assert.is_true(system.monotime() - endtime >= 0) + end) + + end) + + + + describe("sleep()", function() + + it("should sleep for the specified time", function() + local start_time = system.gettime() + system.sleep(1, 1) + local end_time = system.gettime() + local elapsed_time = end_time - start_time + assert.is.near(elapsed_time, 1, 0.01) + end) + + + it("should sleep for the specified time; fractional", function() + local start_time = system.gettime() + system.sleep(0.5, 1) + local end_time = system.gettime() + local elapsed_time = end_time - start_time + assert.is.near(0.5, elapsed_time, 0.01) + end) + + + it("should return immediately for a non-positive sleep time", function() + local start_time = system.gettime() + system.sleep(-1) + local end_time = system.gettime() + local elapsed_time = end_time - start_time + assert.is.near(elapsed_time, 0, 0.01) + end) + + end) + +end) diff --git a/spec/02-random_spec.lua b/spec/02-random_spec.lua new file mode 100644 index 0000000..23b6d95 --- /dev/null +++ b/spec/02-random_spec.lua @@ -0,0 +1,47 @@ +local system = require("system") + +describe("Random:", function() + + describe("random()", function() + + it("should return random bytes for a valid number of bytes", function() + local num_bytes = 1 + local result, err_msg = system.random(num_bytes) + assert.is_nil(err_msg) + assert.is.string(result) + assert.is_equal(num_bytes, #result) + end) + + + it("should return an empty string for 0 bytes", function() + local num_bytes = 0 + local result, err_msg = system.random(num_bytes) + assert.is_nil(err_msg) + assert.are.equal("", result) + end) + + + it("should return an error message for an invalid number of bytes", function() + local num_bytes = -1 + local result, err_msg = system.random(num_bytes) + assert.is.falsy(result) + assert.are.equal("invalid number of bytes, must not be less than 0", err_msg) + end) + + + it("should not return duplicate results", function() + local num_bytes = 1025 + local result1, err_msg = system.random(num_bytes) + assert.is_nil(err_msg) + assert.is.string(result1) + + local result2, err_msg = system.random(num_bytes) + assert.is_nil(err_msg) + assert.is.string(result2) + + assert.is_not.equal(result1, result2) + end) + + end) + +end) diff --git a/spec/03-environment_spec.lua b/spec/03-environment_spec.lua new file mode 100644 index 0000000..842ed6f --- /dev/null +++ b/spec/03-environment_spec.lua @@ -0,0 +1,81 @@ +-- Import the library that contains the environment-related functions +local system = require("system") + +describe("Environment Variables:", function() + + describe("setenv()", function() + + it("should set an environment variable", function() + assert.is_true(system.setenv("TEST_VAR", "test_value")) + assert.is_equal("test_value", system.getenv("TEST_VAR")) + end) + + + local func = system.windows and pending or it --pending on Windows + -- Windows will unset a variable if set as an empty string + func("should set an empty environment variable value", function() + assert.is_true(system.setenv("TEST_VAR", "")) + assert.is_equal("", system.getenv("TEST_VAR")) + end) + + + it("should unset an environment variable on nil", function() + assert.is_true(system.setenv("TEST_VAR", "test_value")) + assert.is_equal("test_value", system.getenv("TEST_VAR")) + + assert.is_true(system.setenv("TEST_VAR", nil)) + assert.is_nil(system.getenv("TEST_VAR")) + end) + + + it("should error on input bad type", function() + assert.has_error(function() + system.setenv("TEST_VAR", {}) + end) + assert.has_error(function() + system.setenv({}, "test_value") + end) + end) + + + it("should return success on deleting a variable that doesn't exist", function() + if system.getenv("TEST_VAR") ~= nil then + -- clear if it was already set + assert.is_true(system.setenv("TEST_VAR", nil)) + end + + assert.is_true(system.setenv("TEST_VAR", nil)) -- clear again shouldn't fail + end) + + end) + + + + describe("getenvs()", function() + + it("should list environment variables", function() + assert.is_true(system.setenv("TEST_VAR1", nil)) + assert.is_true(system.setenv("TEST_VAR2", nil)) + assert.is_true(system.setenv("TEST_VAR3", nil)) + local envVars1 = system.getenvs() + assert.is_true(system.setenv("TEST_VAR1", "test_value1")) + assert.is_true(system.setenv("TEST_VAR2", "test_value2")) + assert.is_true(system.setenv("TEST_VAR3", "test_value3")) + local envVars2 = system.getenvs() + assert.is_true(system.setenv("TEST_VAR1", nil)) + assert.is_true(system.setenv("TEST_VAR2", nil)) + assert.is_true(system.setenv("TEST_VAR3", nil)) + + for k,v in pairs(envVars1) do + envVars2[k] = nil + end + assert.are.same({ + TEST_VAR1 = "test_value1", + TEST_VAR2 = "test_value2", + TEST_VAR3 = "test_value3", + }, envVars2) + end) + + end) + +end) diff --git a/spec/time_spec.lua b/spec/time_spec.lua deleted file mode 100644 index a017cfe..0000000 --- a/spec/time_spec.lua +++ /dev/null @@ -1,31 +0,0 @@ -local system = require 'system.core' - -describe('Test time functions', function() - it('gettime returns current time', function() - local starttime = system.gettime() - local expected = os.time() - local endtime = system.gettime() - local delta = endtime - starttime - local avg = starttime + delta/2 - assert.is_true(expected >= math.floor(starttime)) - assert.is_true(expected <= math.ceil(endtime)) - assert.is_near(expected, avg, 1 + delta) - end) - - it('monottime returns monotonically increasing time', function() - local starttime = system.monotime() - local endtime = system.monotime() - local delta = endtime - starttime - assert.is_true(starttime > 0) - assert.is_true(delta >= 0) - assert.is_true(system.monotime() - endtime >= 0) - end) - - it('sleep will wait for specified amount of time', function() - local starttime = system.gettime() - local starttick = system.monotime() - system.sleep(0.5) - assert.is_near(0.5, system.gettime() - starttime, 0.15) - assert.is_near(0.5, system.monotime() - starttick, 0.15) - end) -end) diff --git a/src/Makefile b/src/Makefile index 10fc31a..119f95e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -85,7 +85,7 @@ PLATFORM_win32?=Release CDIR_win32?=bin/lua/$(LUA_VERSION)/$(PLATFORM_win32) LDIR_win32?=bin/lua/$(LUA_VERSION)/$(PLATFORM_win32)/lua LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUA_VERSION)/$(PLATFORM_win32) -LUALIBNAME_win32?=lua$(subst .,,$(LUA_VERSION)).lib +LUALIBNAME_win32?=lua$(subst .,,$(LUA_VERSION)).lib # prefix: /usr/local /usr /opt/local /sw @@ -217,7 +217,7 @@ LUALIB= $(LUALIB_$(PLAT)) #------ # Objects # -OBJS=core.$(O) compat.$(O) time.$(O) +OBJS=core.$(O) compat.$(O) time.$(O) environment.$(O) random.$(O) #------ # Targets diff --git a/src/compat.h b/src/compat.h index f523fd9..5aca6df 100644 --- a/src/compat.h +++ b/src/compat.h @@ -8,4 +8,31 @@ void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); #endif +// Windows doesn't have ssize_t, so we define it here +#ifdef _WIN32 +#if SIZE_MAX == UINT_MAX +typedef int ssize_t; /* common 32 bit case */ +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX +#elif SIZE_MAX == ULONG_MAX +typedef long ssize_t; /* linux 64 bits */ +#define SSIZE_MIN LONG_MIN +#define SSIZE_MAX LONG_MAX +#elif SIZE_MAX == ULLONG_MAX +typedef long long ssize_t; /* windows 64 bits */ +#define SSIZE_MIN LLONG_MIN +#define SSIZE_MAX LLONG_MAX +#elif SIZE_MAX == USHRT_MAX +typedef short ssize_t; /* is this even possible? */ +#define SSIZE_MIN SHRT_MIN +#define SSIZE_MAX SHRT_MAX +#elif SIZE_MAX == UINTMAX_MAX +typedef intmax_t ssize_t; /* last resort, chux suggestion */ +#define SSIZE_MIN INTMAX_MIN +#define SSIZE_MAX INTMAX_MAX +#else +#error platform has exotic SIZE_MAX +#endif +#endif + #endif diff --git a/src/core.c b/src/core.c index 6c46981..fffedd1 100644 --- a/src/core.c +++ b/src/core.c @@ -1,3 +1,6 @@ +/// Platform independent system calls for Lua. +// @module system + #include #include @@ -10,6 +13,8 @@ #endif void time_open(lua_State *L); +void environment_open(lua_State *L); +void random_open(lua_State *L); /*------------------------------------------------------------------------- * Initializes all library modules. @@ -18,7 +23,16 @@ LUAEXPORT int luaopen_system_core(lua_State *L) { lua_newtable(L); lua_pushstring(L, "_VERSION"); lua_pushstring(L, LUASYSTEM_VERSION); + lua_rawset(L, -3); + lua_pushstring(L, "windows"); +#ifdef _WIN32 + lua_pushboolean(L, 1); +#else + lua_pushboolean(L, 0); +#endif lua_rawset(L, -3); time_open(L); + random_open(L); + environment_open(L); return 1; } diff --git a/src/environment.c b/src/environment.c new file mode 100644 index 0000000..5f1c3da --- /dev/null +++ b/src/environment.c @@ -0,0 +1,173 @@ +/// @submodule system +#include +#include +#include "compat.h" +#include +#include + +#ifdef _WIN32 +#include "windows.h" +#endif + +/*** +Gets the value of an environment variable. + +__NOTE__: Windows has multiple copies of environment variables. For this reason, +the `setenv` function will not work with Lua's `os.getenv` on Windows. If you want +to use `setenv` then consider patching `os.getenv` with this implementation of `getenv`. +@function getenv +@tparam string name name of the environment variable +@treturn string|nil value of the environment variable, or nil if the variable is not set +*/ +static int lua_get_environment_variable(lua_State* L) { + const char* variableName = luaL_checkstring(L, 1); + +#ifdef _WIN32 + // On Windows, use GetEnvironmentVariable to retrieve the value + DWORD bufferSize = GetEnvironmentVariable(variableName, NULL, 0); + if (bufferSize > 0) { + char* buffer = (char*)malloc(bufferSize); + if (GetEnvironmentVariable(variableName, buffer, bufferSize) > 0) { + lua_pushstring(L, buffer); + free(buffer); + return 1; + } + free(buffer); + } +#else + // On non-Windows platforms, use getenv to retrieve the value + const char* variableValue = getenv(variableName); + if (variableValue != NULL) { + lua_pushstring(L, variableValue); + return 1; + } +#endif + + // If the variable is not set or an error occurs, push nil + lua_pushnil(L); + return 1; +} + + +/*** +Returns a table with all environment variables. +@function getenvs +@treturn table table with all environment variables and their values +*/ +static int lua_list_environment_variables(lua_State* L) { + lua_newtable(L); + +#ifdef _WIN32 + char* envStrings = GetEnvironmentStrings(); + char* envString = envStrings; + + if (envStrings == NULL) { + lua_pushnil(L); + return 1; + } + + while (*envString != '\0') { + const char* envVar = envString; + + // Split the environment variable into key and value + char* equals = strchr(envVar, '='); + if (equals != NULL) { + lua_pushlstring(L, envVar, equals - envVar); // Push the key + lua_pushstring(L, equals + 1); // Push the value + lua_settable(L, -3); // Set the key-value pair in the table + } + + envString += strlen(envString) + 1; + } + + FreeEnvironmentStrings(envStrings); +#else + extern char** environ; + + if (environ != NULL) { + for (char** envVar = environ; *envVar != NULL; envVar++) { + const char* envVarStr = *envVar; + + // Split the environment variable into key and value + char* equals = strchr(envVarStr, '='); + if (equals != NULL) { + lua_pushlstring(L, envVarStr, equals - envVarStr); // Push the key + lua_pushstring(L, equals + 1); // Push the value + lua_settable(L, -3); // Set the key-value pair in the table + } + } + } +#endif + + return 1; +} + + +/*** +Sets an environment variable. + +__NOTE__: Windows has multiple copies of environment variables. For this reason, the +`setenv` function will not work with Lua's `os.getenv` on Windows. If you want to use +it then consider patching `os.getenv` with the implementation of `system.getenv`. +@function setenv +@tparam string name name of the environment variable +@tparam[opt] string value value of the environment variable, if `nil` the variable will be deleted (on +Windows, setting an empty string, will also delete the variable) +@treturn boolean success +*/ +static int lua_set_environment_variable(lua_State* L) { + const char* variableName = luaL_checkstring(L, 1); + const char* variableValue = luaL_optstring(L, 2, NULL); + +#ifdef _WIN32 + // if (variableValue == NULL) { + // // If the value is nil, delete the environment variable + // if (SetEnvironmentVariable(variableName, NULL)) { + // lua_pushboolean(L, 1); + // } else { + // lua_pushboolean(L, 0); + // } + // } else { + // Set the environment variable with the provided value + if (SetEnvironmentVariable(variableName, variableValue)) { + lua_pushboolean(L, 1); + } else { + lua_pushboolean(L, 0); + } + // } +#else + if (variableValue == NULL) { + // If the value is nil, delete the environment variable + if (unsetenv(variableName) == 0) { + lua_pushboolean(L, 1); + } else { + lua_pushboolean(L, 0); + } + } else { + // Set the environment variable with the provided value + if (setenv(variableName, variableValue, 1) == 0) { + lua_pushboolean(L, 1); + } else { + lua_pushboolean(L, 0); + } + } +#endif + + return 1; +} + + + +static luaL_Reg func[] = { + { "getenv", lua_get_environment_variable }, + { "setenv", lua_set_environment_variable }, + { "getenvs", lua_list_environment_variables }, + { NULL, NULL } +}; + +/*------------------------------------------------------------------------- + * Initializes module + *-------------------------------------------------------------------------*/ +void environment_open(lua_State *L) { + luaL_setfuncs(L, func, 0); +} diff --git a/src/random.c b/src/random.c new file mode 100644 index 0000000..90fb3f2 --- /dev/null +++ b/src/random.c @@ -0,0 +1,117 @@ +/// @submodule system +#include +#include +#include "compat.h" +#include + +#ifdef _WIN32 +#include "windows.h" +#include "wincrypt.h" +#else +#include +#include +#include +#endif + + +/*** +Generate random bytes. +This uses `CryptGenRandom()` on Windows, and `/dev/urandom` on other platforms. It will return the +requested number of bytes, or an error, never a partial result. +@function random +@tparam[opt=1] int length number of bytes to get +@treturn[1] string string of random bytes +@treturn[2] nil +@treturn[2] string error message +*/ +static int lua_get_random_bytes(lua_State* L) { + int num_bytes = luaL_optinteger(L, 1, 1); // Number of bytes, default to 1 if not provided + + if (num_bytes <= 0) { + if (num_bytes == 0) { + lua_pushliteral(L, ""); + return 1; + } + lua_pushnil(L); + lua_pushstring(L, "invalid number of bytes, must not be less than 0"); + return 2; + } + + unsigned char* buffer = (unsigned char*)lua_newuserdata(L, num_bytes); + if (buffer == NULL) { + lua_pushnil(L); + lua_pushstring(L, "failed to allocate memory for random buffer"); + return 2; + } + + ssize_t n; + ssize_t total_read = 0; + +#ifdef _WIN32 + HCRYPTPROV hCryptProv; + if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + DWORD error = GetLastError(); + lua_pushnil(L); + lua_pushfstring(L, "failed to acquire cryptographic context: %lu", error); + return 2; + } + + if (!CryptGenRandom(hCryptProv, num_bytes, buffer)) { + DWORD error = GetLastError(); + lua_pushnil(L); + lua_pushfstring(L, "failed to get random data: %lu", error); + CryptReleaseContext(hCryptProv, 0); + return 2; + } + + CryptReleaseContext(hCryptProv, 0); +#else + + // for macOS/unixes use /dev/urandom for non-blocking + int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd < 0) { + lua_pushnil(L); + lua_pushstring(L, "failed opening /dev/urandom"); + return 2; + } + + while (total_read < num_bytes) { + n = read(fd, buffer + total_read, num_bytes - total_read); + + if (n < 0) { + if (errno == EINTR) { + continue; // Interrupted, retry + + } else { + lua_pushnil(L); + lua_pushfstring(L, "failed reading /dev/urandom: %s", strerror(errno)); + close(fd); + return 2; + } + } + + total_read += n; + } + + close(fd); +#endif + + lua_pushlstring(L, (const char*)buffer, num_bytes); + return 1; +} + + + +static luaL_Reg func[] = { + { "random", lua_get_random_bytes }, + { NULL, NULL } +}; + + + +/*------------------------------------------------------------------------- + * Initializes module + *-------------------------------------------------------------------------*/ +void random_open(lua_State *L) { + luaL_setfuncs(L, func, 0); +} diff --git a/src/time.c b/src/time.c index 8c6a4f2..5f0ead0 100644 --- a/src/time.c +++ b/src/time.c @@ -1,3 +1,4 @@ +/// @submodule system #include #include @@ -50,11 +51,8 @@ static double time_gettime(void) { } #endif -/*------------------------------------------------------------------------- - * Gets monotonic time in s - * Returns - * time in s. - *-------------------------------------------------------------------------*/ + + #ifdef _WIN32 WINBASEAPI ULONGLONG WINAPI GetTickCount64(VOID); @@ -70,53 +68,84 @@ static double time_monotime(void) { } #endif -/*------------------------------------------------------------------------- - * Returns the current system time, 1970 (UTC), in secconds. - *-------------------------------------------------------------------------*/ + + +/*** +Get system time. +The time is returned as the seconds since the epoch (1 January 1970 00:00:00). +@function gettime +@treturn number seconds (fractional) +*/ static int time_lua_gettime(lua_State *L) { lua_pushnumber(L, time_gettime()); return 1; } -/*------------------------------------------------------------------------- - * Returns the monotonic time the system has been up, in secconds. - *-------------------------------------------------------------------------*/ + + +/*** +Get monotonic time. +The time is returned as the seconds since system start. +@function monotime +@treturn number seconds (fractional) +*/ static int time_lua_monotime(lua_State *L) { lua_pushnumber(L, time_monotime()); return 1; } -/*------------------------------------------------------------------------- - * Sleep for n seconds. - *-------------------------------------------------------------------------*/ + + +/*** +Sleep without a busy loop. +This function will sleep, without doing a busy-loop and wasting CPU cycles. +@function sleep +@tparam number seconds seconds to sleep (fractional). +@tparam[opt=16] integer precision minimum stepsize in milliseconds (Windows only, ignored elsewhere) +@return `true` on success, or `nil+err` on failure +*/ #ifdef _WIN32 static int time_lua_sleep(lua_State *L) { double n = luaL_checknumber(L, 1); - if (n < 0.0) n = 0.0; - if (n < DBL_MAX/1000.0) n *= 1000.0; - if (n > INT_MAX) n = INT_MAX; - Sleep((int)n); - return 0; + + int precision = luaL_optinteger(L, 2, 16); + if (precision < 0 || precision > 16) precision = 16; + + if (n > 0.0) { + if (n < DBL_MAX/1000.0) n *= 1000.0; + if (n > INT_MAX) n = INT_MAX; + if (timeBeginPeriod(precision) != TIMERR_NOERROR) { + lua_pushnil(L); + lua_pushstring(L, "failed to set timer precision"); + return 2; + }; + Sleep((int)n); + timeEndPeriod(precision); + } + lua_pushboolean(L, 1); + return 1; } #else static int time_lua_sleep(lua_State *L) { double n = luaL_checknumber(L, 1); struct timespec t, r; - if (n < 0.0) n = 0.0; - if (n > INT_MAX) n = INT_MAX; - t.tv_sec = (int) n; - n -= t.tv_sec; - t.tv_nsec = (int) (n * 1000000000); - if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; - while (nanosleep(&t, &r) != 0) { - t.tv_sec = r.tv_sec; - t.tv_nsec = r.tv_nsec; + if (n > 0.0) { + if (n > INT_MAX) n = INT_MAX; + t.tv_sec = (int) n; + n -= t.tv_sec; + t.tv_nsec = (int) (n * 1000000000); + if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999; + while (nanosleep(&t, &r) != 0) { + t.tv_sec = r.tv_sec; + t.tv_nsec = r.tv_nsec; + } } - return 0; + lua_pushboolean(L, 1); + return 1; } #endif -- cgit v1.2.3-55-g6feb From 5f3951a942fdc4bf489d8d590bfc891ac9548a23 Mon Sep 17 00:00:00 2001 From: Thijs Date: Sun, 12 Nov 2023 23:53:26 +0100 Subject: feat(tty): add isatty() --- luasystem-scm-0.rockspec | 9 ++++++++- spec/01-time_spec.lua | 5 ++--- src/Makefile | 2 +- src/core.c | 2 ++ src/term.c | 37 +++++++++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 src/term.c diff --git a/luasystem-scm-0.rockspec b/luasystem-scm-0.rockspec index 96f10ae..86209a6 100644 --- a/luasystem-scm-0.rockspec +++ b/luasystem-scm-0.rockspec @@ -45,7 +45,14 @@ local function make_platform(plat) return { modules = { ['system.core'] = { - sources = { 'src/core.c', 'src/compat.c', 'src/time.c', 'src/environment.c', 'src/random.c' }, + sources = { + 'src/core.c', + 'src/compat.c', + 'src/time.c', + 'src/environment.c', + 'src/random.c', + 'src/term.c', + }, defines = defines[plat], libraries = libraries[plat], }, diff --git a/spec/01-time_spec.lua b/spec/01-time_spec.lua index 80faa75..1607cca 100644 --- a/spec/01-time_spec.lua +++ b/spec/01-time_spec.lua @@ -16,7 +16,6 @@ describe('Test time functions', function() describe("time()", function() it('returns current time', function() - wait_for_second_rollover() local expected_time = wait_for_second_rollover() local received_time = system.gettime() assert.is.near(expected_time, received_time, 0.02) @@ -51,7 +50,7 @@ describe('Test time functions', function() system.sleep(1, 1) local end_time = system.gettime() local elapsed_time = end_time - start_time - assert.is.near(elapsed_time, 1, 0.01) + assert.is.near(elapsed_time, 1, 0.2) -- large marging of error due to CI priorities end) @@ -60,7 +59,7 @@ describe('Test time functions', function() system.sleep(0.5, 1) local end_time = system.gettime() local elapsed_time = end_time - start_time - assert.is.near(0.5, elapsed_time, 0.01) + assert.is.near(0.5, elapsed_time, 0.2) -- large marging of error due to CI priorities end) diff --git a/src/Makefile b/src/Makefile index 119f95e..b4ed16f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -217,7 +217,7 @@ LUALIB= $(LUALIB_$(PLAT)) #------ # Objects # -OBJS=core.$(O) compat.$(O) time.$(O) environment.$(O) random.$(O) +OBJS=core.$(O) compat.$(O) time.$(O) environment.$(O) random.$(O) term.$(O) #------ # Targets diff --git a/src/core.c b/src/core.c index fffedd1..87fd105 100644 --- a/src/core.c +++ b/src/core.c @@ -15,6 +15,7 @@ void time_open(lua_State *L); void environment_open(lua_State *L); void random_open(lua_State *L); +void term_open(lua_State *L); /*------------------------------------------------------------------------- * Initializes all library modules. @@ -33,6 +34,7 @@ LUAEXPORT int luaopen_system_core(lua_State *L) { lua_rawset(L, -3); time_open(L); random_open(L); + term_open(L); environment_open(L); return 1; } diff --git a/src/term.c b/src/term.c new file mode 100644 index 0000000..2adb1e9 --- /dev/null +++ b/src/term.c @@ -0,0 +1,37 @@ +/// @submodule system +#include +#include +#include +#include "compat.h" + +#ifndef _MSC_VER +# include +#endif + + +/*** +Checks if a file-handle is a TTY. + +@function isatty +@tparam file file the file-handle to check +@treturn boolean true if the file is a tty +*/ +static int lua_isatty(lua_State* L) { + FILE **fh = (FILE **) luaL_checkudata(L, 1, LUA_FILEHANDLE); + lua_pushboolean(L, isatty(fileno(*fh))); + return 1; +} + + + +static luaL_Reg func[] = { + { "isatty", lua_isatty }, + { NULL, NULL } +}; + +/*------------------------------------------------------------------------- + * Initializes module + *-------------------------------------------------------------------------*/ +void term_open(lua_State *L) { + luaL_setfuncs(L, func, 0); +} -- cgit v1.2.3-55-g6feb From 048f3cec7a18e7a28146f03c3c9e5d89d9613028 Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Wed, 15 Nov 2023 07:48:12 +0100 Subject: chore(docs): render the documentation --- docs/index.html | 366 ++++++++++++++++++++++++++++++++++++ docs/ldoc.css | 291 ++++++++++++++++++++++++++++ docs/topics/01-introduction.md.html | 70 +++++++ docs/topics/CHANGELOG.md.html | 121 ++++++++++++ docs/topics/LICENSE.md.html | 79 ++++++++ 5 files changed, 927 insertions(+) create mode 100644 docs/index.html create mode 100644 docs/ldoc.css create mode 100644 docs/topics/01-introduction.md.html create mode 100644 docs/topics/CHANGELOG.md.html create mode 100644 docs/topics/LICENSE.md.html diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..eb241c6 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,366 @@ + + + + + Lua-System docs + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ +

Module system

+

Platform independent system calls for Lua.

+

+ +

+ + +

environment Functions

+ + + + + + + + + + + + + +
getenv (name)Gets the value of an environment variable.
getenvs ()Returns a table with all environment variables.
setenv (name[, value])Sets an environment variable.
+

random Functions

+ + + + + +
random ([length=1])Generate random bytes.
+

term Functions

+ + + + + +
isatty (file)Checks if a file-handle is a TTY.
+

time Functions

+ + + + + + + + + + + + + +
gettime ()Get system time.
monotime ()Get monotonic time.
sleep (seconds[, precision=16])Sleep without a busy loop.
+ +
+
+ + +

environment Functions

+ +
+
+ + getenv (name) +
+
+ Gets the value of an environment variable.

+ +

NOTE: Windows has multiple copies of environment variables. For this reason, +the setenv function will not work with Lua's os.getenv on Windows. If you want +to use setenv then consider patching os.getenv with this implementation of getenv. + + +

Parameters:

+
    +
  • name + string + name of the environment variable +
  • +
+ +

Returns:

+
    + + string or nil + value of the environment variable, or nil if the variable is not set +
+ + + + +
+
+ + getenvs () +
+
+ Returns a table with all environment variables. + + + +

Returns:

+
    + + table + table with all environment variables and their values +
+ + + + +
+
+ + setenv (name[, value]) +
+
+ Sets an environment variable.

+ +

NOTE: Windows has multiple copies of environment variables. For this reason, the +setenv function will not work with Lua's os.getenv on Windows. If you want to use +it then consider patching os.getenv with the implementation of system.getenv. + + +

Parameters:

+
    +
  • name + string + name of the environment variable +
  • +
  • value + string + value of the environment variable, if nil the variable will be deleted (on +Windows, setting an empty string, will also delete the variable) + (optional) +
  • +
+ +

Returns:

+
    + + boolean + success +
+ + + + +
+
+

random Functions

+ +
+
+ + random ([length=1]) +
+
+ Generate random bytes. +This uses CryptGenRandom() on Windows, and /dev/urandom on other platforms. It will return the +requested number of bytes, or an error, never a partial result. + + +

Parameters:

+
    +
  • length + int + number of bytes to get + (default 1) +
  • +
+ +

Returns:

+
    + + string + string of random bytes +
+

Or

+
    +
  1. + nil + + +
  2. +
  3. + string + error message
  4. +
+ + + + +
+
+

term Functions

+ +
+
+ + isatty (file) +
+
+ Checks if a file-handle is a TTY. + + +

Parameters:

+
    +
  • file + file + the file-handle to check +
  • +
+ +

Returns:

+
    + + boolean + true if the file is a tty +
+ + + + +
+
+

time Functions

+ +
+
+ + gettime () +
+
+ Get system time. +The time is returned as the seconds since the epoch (1 January 1970 00:00:00). + + + +

Returns:

+
    + + number + seconds (fractional) +
+ + + + +
+
+ + monotime () +
+
+ Get monotonic time. +The time is returned as the seconds since system start. + + + +

Returns:

+
    + + number + seconds (fractional) +
+ + + + +
+
+ + sleep (seconds[, precision=16]) +
+
+ Sleep without a busy loop. +This function will sleep, without doing a busy-loop and wasting CPU cycles. + + +

Parameters:

+
    +
  • seconds + number + seconds to sleep (fractional). +
  • +
  • precision + integer + minimum stepsize in milliseconds (Windows only, ignored elsewhere) + (default 16) +
  • +
+ +

Returns:

+
    + + true on success, or nil+err on failure +
+ + + + +
+
+ + +
+
+
+generated by LDoc 1.4.6 +Last updated 2023-11-15 07:42:18 +
+
+ + diff --git a/docs/ldoc.css b/docs/ldoc.css new file mode 100644 index 0000000..5b9fbbf --- /dev/null +++ b/docs/ldoc.css @@ -0,0 +1,291 @@ +body { + color: #47555c; + font-size: 16px; + font-family: "Open Sans", sans-serif; + margin: 0; + background: #eff4ff; +} + +a:link { color: #008fee; } +a:visited { color: #008fee; } +a:hover { color: #22a7ff; } + +h1 { font-size:26px; font-weight: normal; } +h2 { font-size:22px; font-weight: normal; } +h3 { font-size:18px; font-weight: normal; } +h4 { font-size:16px; font-weight: bold; } + +hr { + height: 1px; + background: #c1cce4; + border: 0px; + margin: 15px 0; +} + +code, tt { + font-family: monospace; +} +span.parameter { + font-family: monospace; + font-weight: bold; + color: rgb(99, 115, 131); +} +span.parameter:after { + content:":"; +} +span.types:before { + content:"("; +} +span.types:after { + content:")"; +} +.type { + font-weight: bold; font-style:italic +} + +p.name { + font-family: "Andale Mono", monospace; +} + +#navigation { + float: left; + background-color: white; + border-right: 1px solid #d3dbec; + border-bottom: 1px solid #d3dbec; + + width: 14em; + vertical-align: top; + overflow: visible; +} + +#navigation br { + display: none; +} + +#navigation h1 { + background-color: white; + border-bottom: 1px solid #d3dbec; + padding: 15px; + margin-top: 0px; + margin-bottom: 0px; +} + +#navigation h2 { + font-size: 18px; + background-color: white; + border-bottom: 1px solid #d3dbec; + padding-left: 15px; + padding-right: 15px; + padding-top: 10px; + padding-bottom: 10px; + margin-top: 30px; + margin-bottom: 0px; +} + +#content h1 { + background-color: #2c3e67; + color: white; + padding: 15px; + margin: 0px; +} + +#content h2 { + background-color: #6c7ea7; + color: white; + padding: 15px; + padding-top: 15px; + padding-bottom: 15px; + margin-top: 0px; +} + +#content h2 a { + background-color: #6c7ea7; + color: white; + text-decoration: none; +} + +#content h2 a:hover { + text-decoration: underline; +} + +#content h3 { + font-style: italic; + padding-top: 15px; + padding-bottom: 4px; + margin-right: 15px; + margin-left: 15px; + margin-bottom: 5px; + border-bottom: solid 1px #bcd; +} + +#content h4 { + margin-right: 15px; + margin-left: 15px; + border-bottom: solid 1px #bcd; +} + +#content pre { + margin: 15px; +} + +pre { + background-color: rgb(50, 55, 68); + color: white; + border-radius: 3px; + /* border: 1px solid #C0C0C0; /* silver */ + padding: 15px; + overflow: auto; + font-family: "Andale Mono", monospace; +} + +#content ul pre.example { + margin-left: 0px; +} + +table.index { +/* border: 1px #00007f; */ +} +table.index td { text-align: left; vertical-align: top; } + +#navigation ul +{ + font-size:1em; + list-style-type: none; + margin: 1px 1px 10px 1px; + padding-left: 20px; +} + +#navigation li { + text-indent: -1em; + display: block; + margin: 3px 0px 0px 22px; +} + +#navigation li li a { + margin: 0px 3px 0px -1em; +} + +#content { + margin-left: 14em; +} + +#content p { + padding-left: 15px; + padding-right: 15px; +} + +#content table { + padding-left: 15px; + padding-right: 15px; + background-color: white; +} + +#content p, #content table, #content ol, #content ul, #content dl { + max-width: 900px; +} + +#about { + padding: 15px; + padding-left: 16em; + background-color: white; + border-top: 1px solid #d3dbec; + border-bottom: 1px solid #d3dbec; +} + +table.module_list, table.function_list { + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; + margin: 15px; +} +table.module_list td, table.function_list td { + border-width: 1px; + padding-left: 10px; + padding-right: 10px; + padding-top: 5px; + padding-bottom: 5px; + border: solid 1px rgb(193, 204, 228); +} +table.module_list td.name, table.function_list td.name { + background-color: white; min-width: 200px; border-right-width: 0px; +} +table.module_list td.summary, table.function_list td.summary { + background-color: white; width: 100%; border-left-width: 0px; +} + +dl.function { + margin-right: 15px; + margin-left: 15px; + border-bottom: solid 1px rgb(193, 204, 228); + border-left: solid 1px rgb(193, 204, 228); + border-right: solid 1px rgb(193, 204, 228); + background-color: white; +} + +dl.function dt { + color: rgb(99, 123, 188); + font-family: monospace; + border-top: solid 1px rgb(193, 204, 228); + padding: 15px; +} + +dl.function dd { + margin-left: 15px; + margin-right: 15px; + margin-top: 5px; + margin-bottom: 15px; +} + +#content dl.function dd h3 { + margin-top: 0px; + margin-left: 0px; + padding-left: 0px; + font-size: 16px; + color: rgb(128, 128, 128); + border-bottom: solid 1px #def; +} + +#content dl.function dd ul, #content dl.function dd ol { + padding: 0px; + padding-left: 15px; + list-style-type: none; +} + +ul.nowrap { + overflow:auto; + white-space:nowrap; +} + +.section-description { + padding-left: 15px; + padding-right: 15px; +} + +/* stop sublists from having initial vertical space */ +ul ul { margin-top: 0px; } +ol ul { margin-top: 0px; } +ol ol { margin-top: 0px; } +ul ol { margin-top: 0px; } + +/* make the target distinct; helps when we're navigating to a function */ +a:target + * { + background-color: #FF9; +} + + +/* styles for prettification of source */ +pre .comment { color: #bbccaa; } +pre .constant { color: #a8660d; } +pre .escape { color: #844631; } +pre .keyword { color: #ffc090; font-weight: bold; } +pre .library { color: #0e7c6b; } +pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } +pre .string { color: #8080ff; } +pre .number { color: #f8660d; } +pre .operator { color: #2239a8; font-weight: bold; } +pre .preprocessor, pre .prepro { color: #a33243; } +pre .global { color: #c040c0; } +pre .user-keyword { color: #800080; } +pre .prompt { color: #558817; } +pre .url { color: #272fc2; text-decoration: underline; } diff --git a/docs/topics/01-introduction.md.html b/docs/topics/01-introduction.md.html new file mode 100644 index 0000000..2901cc9 --- /dev/null +++ b/docs/topics/01-introduction.md.html @@ -0,0 +1,70 @@ + + + + + Lua-System docs + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ + +

1. Introduction

+ +

luasystem is a platform independent system call library for Lua. +Supports Unix, Windows, MacOS, Lua >= 5.1 and luajit >= 2.0.0.

+ +

Lua is typically platform independent, but it requires adhering to very old C +standards. This in turn means that many common features (according to todays standards) +are not available. This module attempts to overcome some of those hurdles by providing +functions that cover those common needs.

+ +

This is not a kitchen sink library, but a minimalistic one with a focus on platform +independence.

+ + +
+
+
+generated by LDoc 1.4.6 +Last updated 2023-11-15 07:42:18 +
+
+ + diff --git a/docs/topics/CHANGELOG.md.html b/docs/topics/CHANGELOG.md.html new file mode 100644 index 0000000..f909b4b --- /dev/null +++ b/docs/topics/CHANGELOG.md.html @@ -0,0 +1,121 @@ + + + + + Lua-System docs + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ + +

CHANGELOG

+ +

+

Versioning

+ +

This library is versioned based on Semantic Versioning (SemVer).

+ +

Version scoping

+ +

The scope of what is covered by the version number excludes:

+ +
    +
  • error messages; the text of the messages can change, unless specifically documented.
  • +
+ +

Releasing new versions

+ +
    +
  • create a release branch
  • +
  • update the changelog below
  • +
  • update version and copyright-years in ./LICENSE.md and ./src/time.c (in module constants)
  • +
  • create a new rockspec and update the version inside the new rockspec:
    + cp luasystem-scm-0.rockspec ./rockspecs/luasystem-X.Y.Z-1.rockspec
  • +
  • clean and render the docs: run ldoc .
  • +
  • commit the changes as Release vX.Y.Z
  • +
  • push the commit, and create a release PR
  • +
  • after merging tag the release commit with vX.Y.Z
  • +
  • upload to LuaRocks:
    + luarocks upload ./rockspecs/luasystem-X.Y.Z-1.rockspec --api-key=ABCDEFGH
  • +
  • test the newly created rock:
    + luarocks install luasystem
  • +
+ +

+

Version history

+ +

Version X.Y.Z, unreleased

+ +
    +
  • Feat: on Windows sleep now has a precision parameter
  • +
  • Feat: setenv added to set environment variables.
  • +
  • Feat: getenvs added to list environment variables.
  • +
  • Feat: getenv added to get environment variable previously set (Windows).
  • +
  • Feat: random added to return high-quality random bytes
  • +
  • Feat: isatty added to check if a file-handle is a tty
  • +
+ +

Version 0.2.1, released 02-Oct-2016

+ +

Version 0.2.0, released 08-May-2016

+ +

Version 0.1.1, released 10-Apr-2016

+ +

Version 0.1.0, released 11-Feb-2016

+ +
    +
  • initial release
  • +
+ + +
+
+
+generated by LDoc 1.4.6 +Last updated 2023-11-15 07:42:18 +
+
+ + diff --git a/docs/topics/LICENSE.md.html b/docs/topics/LICENSE.md.html new file mode 100644 index 0000000..67614d2 --- /dev/null +++ b/docs/topics/LICENSE.md.html @@ -0,0 +1,79 @@ + + + + + Lua-System docs + + + + +
+ +
+ +
+
+
+ + +
+ + + + + + +
+ + +

MIT License

+ +

Copyright (c) 2016-2023 Oscar Lim

+ +

Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions:

+ +

The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software.

+ +

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.

+ + +
+
+
+generated by LDoc 1.4.6 +Last updated 2023-11-15 07:42:18 +
+
+ + -- cgit v1.2.3-55-g6feb