├── LICENSE
├── Makefile
├── README
├── build
└── bin2c.c
├── lua
├── cc.lua
├── const
│ ├── entity.lua
│ ├── exit.lua
│ ├── gopher-types.lua
│ └── http-response.lua
├── date.lua
├── debug.lua
├── dns
│ └── resolv.lua
├── getopt.lua
├── gzip.lua
├── mailcap.lua
├── net
│ ├── ios.lua
│ ├── tcp.lua
│ └── tls.lua
├── nfl.lua
├── nfl
│ ├── tcp.lua
│ └── tls.lua
├── string.lua
├── table.lua
├── unix.lua
├── zip.lua
└── zip
│ ├── read.lua
│ └── write.lua
├── other
├── pollset-epoll.c
├── pollset-poll.c
└── pollset-select.c
├── rockspecs
├── org.conman.const.exit-1.1.1-1.rockspec
├── org.conman.const.gopher-types-2.0.1-1.rockspec
├── org.conman.env-1.0.4-1.rockspec
├── org.conman.errno-1.1.0-1.rockspec
├── org.conman.iconv-2.0.0-4.rockspec
├── org.conman.syslog-2.1.4-5.rockspec
└── org.conman.tls-2.0.0-3.rockspec
├── src
├── base64.c
├── clock.c
├── crc.c
├── env.c
├── errno.c
├── fsys.c
├── hash.c
├── iconv.c
├── idn.c
├── lfsr.c
├── magic.c
├── math.c
├── net.c
├── pollset.c
├── process.c
├── signal.c
├── strcore.c
├── sys.c
├── syslog.c
├── tcc.c
└── tls.c
└── test
├── base64-test.lua
├── clock-test.lua
├── idn-test.lua
├── net-test.lua
├── pollset-test.lua
├── signal-test.lua
└── tap14.lua
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #########################################################################
2 | #
3 | # Copyright 2011 by Sean Conner. All Rights Reserved.
4 | #
5 | # This library is free software; you can redistribute it and/or modify it
6 | # under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation; either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # This library is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | # License for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with this library; if not, see .
17 | #
18 | # Comments, questions and criticisms can be sent to: sean@conman.org
19 | #
20 | ########################################################################
21 |
22 | UNAME := $(shell uname)
23 |
24 | ifeq ($(UNAME),Linux)
25 | CC = gcc -std=c99
26 | CFLAGS = -g -Wall -Wextra -pedantic -Wwrite-strings
27 | SHARED = -fPIC -shared -L/usr/local/lib
28 | LDFLAGS = -g
29 | lib/clock.so : LDLIBS = -lrt
30 | endif
31 |
32 | ifeq ($(UNAME),SunOS)
33 | CC = cc -xc99
34 | CFLAGS = -g -mt -m64 -I /usr/sfw/include
35 | SHARED = -G -xcode=pic32
36 | LDFLAGS = -g
37 | lib/net.so : LDLIBS = -lsocket -lnsl
38 | lib/clock.so : LDLIBS = -lrt
39 | endif
40 |
41 | ifeq ($(UNAME),Darwin)
42 | CC = gcc -std=c99
43 | CFLAGS = -g -Wall -Wextra -pedantic
44 | SHARED = -fPIC -bundle -undefined dynamic_lookup -all_load
45 | LDFLAGS = -g
46 | lib/iconv.so : LDLIBS = -liconv
47 | endif
48 |
49 | # ===================================================
50 |
51 | INSTALL = /usr/bin/install
52 | INSTALL_PROGRAM = $(INSTALL)
53 | INSTALL_DATA = $(INSTALL) -m 644
54 |
55 | prefix = /usr/local
56 | libdir = $(prefix)/lib
57 | datarootdir = $(prefix)/share
58 | dataroot = $(datarootdir)
59 |
60 | LUA ?= lua
61 | LUA_VERSION := $(shell $(LUA) -e "print(_VERSION:match '^Lua (.*)')")
62 | LUADIR ?= $(dataroot)/lua/$(LUA_VERSION)
63 | LIBDIR ?= $(libdir)/lua/$(LUA_VERSION)
64 |
65 | ifneq ($(LUA_INCDIR),)
66 | override CFLAGS += -I$(LUA_INCDIR)
67 | endif
68 |
69 | # ===================================================
70 |
71 | .PHONY: all clean install uninstall obsolete install-obsolete
72 |
73 | lib/%.so : src/%.c
74 | $(CC) $(CFLAGS) $(SHARED) -o $@ $< $(LDLIBS)
75 |
76 | all : lib \
77 | lib/base64.so \
78 | lib/clock.so \
79 | lib/crc.so \
80 | lib/env.so \
81 | lib/errno.so \
82 | lib/fsys.so \
83 | lib/hash.so \
84 | lib/iconv.so \
85 | lib/lfsr.so \
86 | lib/idn.so \
87 | lib/magic.so \
88 | lib/math.so \
89 | lib/net.so \
90 | lib/pollset.so \
91 | lib/process.so \
92 | lib/signal.so \
93 | lib/strcore.so \
94 | lib/sys.so \
95 | lib/syslog.so \
96 | lib/tls.so \
97 | build/bin2c
98 |
99 | obsolete: lib lib/tcc.so
100 |
101 | build/bin2c : LDLIBS = -lz
102 | build/bin2c : build/bin2c.c
103 |
104 | lib :
105 | mkdir lib
106 |
107 | lib/hash.so : LDLIBS = -lcrypto
108 | lib/magic.so : LDLIBS = -lmagic
109 | lib/tcc.so : LDLIBS = -ltcc
110 | lib/idn.so : LDLIBS = -lidn
111 | lib/tls.so : LDLIBS = -lcrypto -ltls -lssl
112 |
113 | # ===================================================
114 |
115 | install : all
116 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman
117 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman/dns
118 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman/zip
119 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman/const
120 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman/net
121 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman/nfl
122 | $(INSTALL) -d $(DESTDIR)$(LIBDIR)/org/conman
123 | $(INSTALL) -d $(DESTDIR)$(LIBDIR)/org/conman/fsys
124 | $(INSTALL_PROGRAM) lib/base64.so $(DESTDIR)$(LIBDIR)/org/conman
125 | $(INSTALL_PROGRAM) lib/clock.so $(DESTDIR)$(LIBDIR)/org/conman
126 | $(INSTALL_PROGRAM) lib/crc.so $(DESTDIR)$(LIBDIR)/org/conman
127 | $(INSTALL_PROGRAM) lib/env.so $(DESTDIR)$(LIBDIR)/org/conman
128 | $(INSTALL_PROGRAM) lib/errno.so $(DESTDIR)$(LIBDIR)/org/conman
129 | $(INSTALL_PROGRAM) lib/fsys.so $(DESTDIR)$(LIBDIR)/org/conman
130 | $(INSTALL_PROGRAM) lib/hash.so $(DESTDIR)$(LIBDIR)/org/conman
131 | $(INSTALL_PROGRAM) lib/iconv.so $(DESTDIR)$(LIBDIR)/org/conman
132 | $(INSTALL_PROGRAM) lib/lfsr.so $(DESTDIR)$(LIBDIR)/org/conman
133 | $(INSTALL_PROGRAM) lib/idn.so $(DESTDIR)$(LIBDIR)/org/conman
134 | $(INSTALL_PROGRAM) lib/magic.so $(DESTDIR)$(LIBDIR)/org/conman/fsys
135 | $(INSTALL_PROGRAM) lib/math.so $(DESTDIR)$(LIBDIR)/org/conman
136 | $(INSTALL_PROGRAM) lib/net.so $(DESTDIR)$(LIBDIR)/org/conman
137 | $(INSTALL_PROGRAM) lib/pollset.so $(DESTDIR)$(LIBDIR)/org/conman
138 | $(INSTALL_PROGRAM) lib/process.so $(DESTDIR)$(LIBDIR)/org/conman
139 | $(INSTALL_PROGRAM) lib/signal.so $(DESTDIR)$(LIBDIR)/org/conman
140 | $(INSTALL_PROGRAM) lib/strcore.so $(DESTDIR)$(LIBDIR)/org/conman
141 | $(INSTALL_PROGRAM) lib/sys.so $(DESTDIR)$(LIBDIR)/org/conman
142 | $(INSTALL_PROGRAM) lib/syslog.so $(DESTDIR)$(LIBDIR)/org/conman
143 | $(INSTALL_PROGRAM) lib/tls.so $(DESTDIR)$(LIBDIR)/org/conman
144 | $(INSTALL_DATA) lua/*.lua $(DESTDIR)$(LUADIR)/org/conman
145 | $(INSTALL_DATA) lua/dns/*.lua $(DESTDIR)$(LUADIR)/org/conman/dns
146 | $(INSTALL_DATA) lua/zip/*.lua $(DESTDIR)$(LUADIR)/org/conman/zip
147 | $(INSTALL_DATA) lua/const/*.lua $(DESTDIR)$(LUADIR)/org/conman/const
148 | $(INSTALL_DATA) lua/net/*.lua $(DESTDIR)$(LUADIR)/org/conman/net
149 | $(INSTALL_DATA) lua/nfl/*.lua $(DESTDIR)$(LUADIR)/org/conman/nfl
150 |
151 | install-obsolete: obsolete
152 | $(INSTALL) -d $(DESTDIR)$(LUADIR)/org/conman
153 | $(INSTALL) -d $(DESTDIR)$(LIBDIR)/org/conman
154 | $(INSTALL_PROGRAM) lib/tcc.so $(DESTDIR)$(LIBDIR)/org/conman
155 | $(INSTALL_DATA) lua/cc.lua $(DESTDIR)$(LUADIR)/org/conman
156 |
157 | uninstall:
158 | $(RM) -r $(DESTDIR)$(LIBDIR)/org/conman
159 | $(RM) -r $(DESTDIR)$(LUADIR)/org/conman
160 |
161 | clean:
162 | $(RM) $(shell find . -name '*~')
163 | $(RM) -r lib/*
164 | $(RM) build/bin2c
165 | $(RM) -r $(shell find . -name '*.dSYM')
166 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 |
2 | This is a collection of Lua 5.1 .. 5.4 modules I've written. Yes, they
3 | include functionality found in other Lua modules like luasockets and
4 | luaposix. I wrote these not to reinvent the wheel (although I did) but to
5 | learn how to program in Lua. As such, I do find these modules useful and
6 | actually prefer them to such modules as luasockets and luaposix.
7 |
8 | Now, because of the functionality overlap of some of these modules with
9 | existing Lua modules, I decided to place them under a name that I know won't
10 | conflict with existing modules. I took a play out of the Java playbook and
11 | placed all these modules under the "org.conman" table.
12 |
13 | * * * * *
14 |
15 | MODULES AS LUAROCKS
16 |
17 | org.conman.const.exit (Lua)
18 | A table of standardize exit values.
19 |
20 | org.conman.const.gopher-types (Lua)
21 | A table mapping Gopher resource types (RFC-1436) to human
22 | readable types and back again.
23 |
24 | org.conman.env (C)
25 | A table containing all environtment variables.
26 |
27 | org.conman.errno (C)
28 | A table containing defined error codes from C and POSIX.
29 |
30 | org.conman.iconv (C)
31 | A wrapper for the GNU iconv library.
32 |
33 | org.conman.syslog (C)
34 | A wrapper for the syslog logging system.
35 |
36 | org.conman.tls (C)
37 | A wrapper for libtls from libressl, or libretls for OpenSSL.
38 |
39 | * * * * *
40 |
41 | MODULES IN C
42 |
43 | org.conman.base64
44 | Conversion routines to and from various formulations of Base-64
45 |
46 | org.conman.clock
47 | A POSIX timers interface.
48 |
49 | org.conman.fsys
50 | A module of POSIX functions releated to filesystems.
51 |
52 | org.conman.hash
53 | A module of standard hash functions as provided by libcrypto.
54 |
55 | org.conman.lfsr
56 | A function to generate 8, 16 or 32 bit linear feedback shift
57 | registers.
58 |
59 | org.conman.fsys.magic
60 | A wrapper around the GNU magic (file types) database.
61 |
62 | org.conman.net
63 | A module to wrap BSD/POSIX sockets programming. This supports
64 | IPv4, IPv6 and Unix sockets.
65 |
66 | org.conman.pollset
67 | A wrapper around the POSIX select() call, POSIX poll() call, the
68 | Linux epoll() call and the Mac OS-X kqueue() call, with the same
69 | API.
70 |
71 | org.conman.process
72 | A module of POSIX functions related to processes.
73 |
74 | org.conman.signal
75 | A wrapper around the ANSI signal() function, or the POSIX signal
76 | functions.
77 |
78 | org.conman.strcore
79 | Some functions working with strings written in C.
80 |
81 | org.conman.sys
82 | A table of various POSIX system dependent values.
83 |
84 | * * * * *
85 | MODULES IN LUA
86 |
87 | Modules written in Lua:
88 |
89 | org.conman.const.entity
90 | A table of HTML entities with their UTF-8 equivilents.
91 |
92 | org.conman.const.http-response
93 | A table of HTTP response codes.
94 |
95 | org.conman.date
96 | A module of some date related functions.
97 |
98 | org.conman.debug
99 | A module of some debug related functions.
100 |
101 | org.conman.getopt
102 | A module to handle parsing the command line.
103 |
104 | org.conman.mailcap
105 | A wrapper around the mailcap facility found on Unix systems.
106 |
107 | org.conman.string
108 | Some useful string functions (includes org.conman.strcore).
109 |
110 | org.conman.table
111 | Some useful table functions.
112 |
113 | org.conman.net.ios
114 | Implements an API similar to the Lua's file object API, but with
115 | callbacks to obtain the data.
116 |
117 | org.conman.net.tcp
118 | A module to turn a TCP connection into something that mimics the
119 | Lua's file:read()/file:write()/etc. API.
120 |
121 | org.conman.net.tls
122 | A module, with the API as org.conman.net.tcp, to manage TLS based
123 | connections.
124 |
125 | org.conman.nfl
126 | An event driven framework to manage network based connections via
127 | coroutines.
128 |
129 | org.conman.nfl.tcp
130 | A module, with a similar API to org.conman.net.tcp, to manage
131 | TCP connections via coroutines in an event driven environment.
132 |
133 | org.conman.nfl.tls
134 | A module, with a similar API to org.conman.net.tcp, to manage
135 | TLS-based connections via coroutines in an event driven environment.
136 |
137 | * * * * *
138 |
139 | Any modules found in this repository not listed above are either obsolete or
140 | experimental and should probably not be used.
141 |
--------------------------------------------------------------------------------
/build/bin2c.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2011 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #define _GNU_SOURCE
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include
31 | #include
32 |
33 | extern char *optarg;
34 | extern int optind;
35 | extern int opterr;
36 |
37 | /*************************************************************************/
38 |
39 | int load_file(
40 | const char *const fname,
41 | unsigned char **pdata,
42 | size_t *const psize
43 | )
44 | {
45 | FILE *fp;
46 | long size;
47 | unsigned char *data;
48 |
49 | assert(fname != NULL);
50 | assert(pdata != NULL);
51 | assert(psize != NULL);
52 |
53 | *pdata = NULL;
54 | *psize = 0;
55 |
56 | fp = fopen(fname,"rb");
57 | if (fp == NULL)
58 | return errno;
59 |
60 | if (fseek(fp,0,SEEK_END) < 0)
61 | {
62 | int err = errno;
63 | fclose(fp);
64 | return err;
65 | }
66 |
67 | size = ftell(fp);
68 | if (size == -1)
69 | {
70 | int err = errno;
71 | fclose(fp);
72 | return err;
73 | }
74 |
75 | if (fseek(fp,0,SEEK_SET) < 0)
76 | {
77 | int err = errno;
78 | fclose(fp);
79 | return err;
80 | }
81 |
82 | data = malloc(size);
83 | if (data == NULL)
84 | {
85 | int err = errno;
86 | fclose(fp);
87 | return err;
88 | }
89 |
90 | *psize = size;
91 | *pdata = data;
92 |
93 | fread(data,1,size,fp);
94 |
95 | fclose(fp);
96 | return 0;
97 | }
98 |
99 | /*************************************************************************/
100 |
101 | int compress_data(
102 | const int level,
103 | unsigned char **pdata,
104 | const size_t size,
105 | size_t *newsize
106 | )
107 | {
108 | z_stream sout;
109 | Bytef *buffer;
110 | int rc;
111 |
112 | if (level == 0)
113 | {
114 | *newsize = size;
115 | return 0;
116 | }
117 |
118 | buffer = malloc(size);
119 | if (buffer == NULL)
120 | return ENOMEM;
121 |
122 | sout.zalloc = Z_NULL;
123 | sout.zfree = Z_NULL;
124 | sout.opaque = NULL;
125 | rc = deflateInit(&sout,level);
126 |
127 | if (rc != Z_OK)
128 | {
129 | free(buffer);
130 | return EINVAL;
131 | }
132 |
133 | sout.next_in = (Bytef *)*pdata;
134 | sout.avail_in = size;
135 | sout.next_out = buffer;
136 | sout.avail_out = size;
137 |
138 | deflate(&sout,Z_FINISH);
139 | deflateEnd(&sout);
140 |
141 | free(*pdata);
142 | *pdata = (unsigned char *)buffer;
143 | *newsize = size - sout.avail_out;
144 | return 0;
145 | }
146 |
147 | /*************************************************************************/
148 |
149 | void process(
150 | FILE *fpout,
151 | const unsigned char *data,
152 | const size_t size,
153 | const size_t ucsize,
154 | const char *tag
155 | )
156 | {
157 | int cnt = 8;
158 |
159 | fprintf(
160 | fpout,
161 | "#include \n"
162 | "const unsigned char c_%s[] =\n"
163 | "{"
164 | "",
165 | tag
166 | );
167 |
168 | for (size_t i = 0 ; i < size ; i++)
169 | {
170 | if (cnt == 8)
171 | {
172 | fputs("\n ",fpout);
173 | cnt = 0;
174 | }
175 |
176 | fprintf(fpout,"0x%02X , ",data[i]);
177 | cnt++;
178 | }
179 |
180 | fprintf(
181 | fpout,
182 | "\n};\n\nconst size_t c_%s_size = %lu;\n",
183 | tag,
184 | (unsigned long)size
185 | );
186 |
187 | if (size != ucsize)
188 | {
189 | fprintf(
190 | fpout,
191 | "const size_t c_%s_ucsize = %lu;\n",
192 | tag,
193 | (unsigned long)ucsize
194 | );
195 | }
196 | }
197 |
198 | /**************************************************************************/
199 |
200 | int main(int argc,char *argv[])
201 | {
202 | FILE *fpout;
203 | char const *tag;
204 | int c;
205 | int level;
206 |
207 | fpout = stdout;
208 | tag = "data";
209 | level = 0;
210 |
211 | while((c = getopt(argc,argv,"o:t:hz0123456789")) != EOF)
212 | {
213 | switch(c)
214 | {
215 | default:
216 | case 'h':
217 | fprintf(stderr,"usage: %s [-o output] [-t tag] [-z] [-h] files... \n",argv[0]);
218 | return EXIT_FAILURE;
219 | case 't':
220 | tag = optarg;
221 | for ( ; *optarg ; optarg++)
222 | {
223 | if (*optarg == '-')
224 | *optarg = '_';
225 | else if (*optarg == '.')
226 | *optarg = '_';
227 | }
228 | break;
229 |
230 | case 'o':
231 | fpout = fopen(optarg,"wb");
232 | if (fpout == NULL)
233 | {
234 | perror(optarg);
235 | exit(EXIT_FAILURE);
236 | }
237 | break;
238 | case 'z':
239 | level = Z_DEFAULT_COMPRESSION;
240 | break;
241 |
242 | case '0':
243 | case '1':
244 | case '2':
245 | case '3':
246 | case '4':
247 | case '5':
248 | case '6':
249 | case '7':
250 | case '8':
251 | case '9':
252 | level = c - '0';
253 | break;
254 | }
255 | }
256 |
257 | if (optind == argc)
258 | {
259 | fprintf(stderr,"usage: %s [-o output] [-t tag] [-z] [-h] files... \n",argv[0]);
260 | return EXIT_FAILURE;
261 | }
262 | else
263 | {
264 | for (int i = optind ; i < argc ; i++)
265 | {
266 | unsigned char *data;
267 | size_t datasize;
268 | size_t realdatasize;
269 | int rc;
270 |
271 | rc = load_file(argv[i],&data,&realdatasize);
272 | if (rc != 0)
273 | {
274 | fprintf(stderr,"%s: %s\n",argv[i],strerror(rc));
275 | free(data);
276 | return EXIT_FAILURE;
277 | }
278 |
279 | rc = compress_data(level,&data,realdatasize,&datasize);
280 | if (rc != 0)
281 | {
282 | fprintf(stderr,"%s: %s\n",argv[1],strerror(rc));
283 | free(data);
284 | return EXIT_FAILURE;
285 | }
286 |
287 | process(fpout,data,datasize,realdatasize,tag);
288 | free(data);
289 | }
290 | }
291 |
292 | return EXIT_SUCCESS;
293 | }
294 |
--------------------------------------------------------------------------------
/lua/cc.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2012 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals encap CACHE compile package.ccpath
22 | -- luacheck: ignore 611
23 |
24 | local _VERSION = _VERSION
25 | local tcc = require "org.conman.tcc"
26 | local package = package
27 | local table = table
28 | local os = os
29 | local io = io
30 | local string = string
31 | local pairs = pairs
32 | local setmetatable = setmetatable
33 |
34 | if _VERSION == "Lua 5.1" then
35 | module("org.conman.cc")
36 | else
37 | _ENV = {}
38 | end
39 |
40 | package.ccpath = "/usr/loca/share/lua/5.1/?.c;/usr/local/lib/lua/5.1/?.c"
41 |
42 | local DIR = package.config:sub(1,1)
43 | local SEP = package.config:sub(3,3)
44 | local MARK = package.config:sub(5,5)
45 | local IGN = package.config:sub(9,9)
46 |
47 | do
48 | local ep = os.getenv("LUA_CCPATH")
49 | if ep ~= nil then
50 | package.ccpath = ep:gsub(";;",";" .. package.ccpath .. ";")
51 | end
52 |
53 | local function loader(name)
54 | local modulefile = name:gsub("%.",DIR)
55 | local errmsg = ""
56 | local filename
57 | local file
58 | local entry
59 | local x
60 |
61 | for path in package.ccpath:gmatch("[^%" .. SEP .. "]+") do
62 | filename = path:gsub("[%" .. MARK .. "]",modulefile)
63 | file = io.open(filename)
64 | if file then break end
65 | errmsg = errmsg .. "\n\tno file '" .. filename .. "'"
66 | end
67 |
68 | if not file then
69 | return errmsg
70 | end
71 |
72 | file:close()
73 |
74 | local _,l = name:find(IGN,1,true)
75 | if l then
76 | entry = "luaopen_" .. name:sub(l + 1,-1):gsub("%.","_")
77 | else
78 | entry = "luaopen_" .. name:gsub("%.","_")
79 | end
80 |
81 | -- ---------------------------------------------------------------------
82 | -- Why not use compile() for this? Because that caches the memory blob
83 | -- returned from relocate() via the symbol we pulled out. Lua modules
84 | -- only use this function once, then it's not used, and thus, the module
85 | -- we just loaded stands a chance of being flushed out of memory,
86 | -- causing issues.
87 | --
88 | -- Doing it this way, we avoid that problem. We still have the problem
89 | -- if the module is removed from package.loaded{} and reloaded, which
90 | -- will cause a memory leak, but that scenario is probably very rare.
91 | -- I'm willing to live with this for now.
92 | -- ---------------------------------------------------------------------
93 |
94 | x = tcc.new()
95 | x:define("LUA_REQUIRE","1")
96 | x:output_type('memory')
97 | if x:compile(filename,true,function(msg)
98 | errmsg = errmsg .. "\n\t" .. msg
99 | end)
100 | then
101 | local blob = x:relocate()
102 | local f = x:get_symbol(entry)
103 | if f then
104 | return f
105 | end
106 | tcc.dispose(blob)
107 | errmsg = errmsg
108 | .. string.format("\n\tno entry '%s' in file '%s'",entry,filename)
109 | return errmsg
110 | end
111 |
112 | return errmsg
113 | end
114 | if _VERSION == "Lua 5.1" then
115 | table.insert(package.loaders,#package.loaders,loader)
116 | else
117 | table.insert(package.searchers,#package.searchers,loader)
118 | end
119 | end
120 |
121 | -- ********************************************************************
122 |
123 | do
124 | local code = [[
125 |
126 | #include
127 |
128 | #include
129 | #include
130 | #include
131 |
132 | #define CC_TYPE "CC:type"
133 |
134 | struct cclua
135 | {
136 | void *data;
137 | };
138 |
139 | int cclua___tostring(lua_State *L)
140 | {
141 | lua_pushfstring(L,"CC:%p",luaL_checkudata(L,1,CC_TYPE));
142 | return 1;
143 | }
144 |
145 | int cclua___gc(lua_State *L)
146 | {
147 | struct cclua *obj = luaL_checkudata(L,1,CC_TYPE);
148 | luaL_getmetafield(L,1,"dispose");
149 |
150 | lua_pushlightuserdata(L,obj->data);
151 | lua_call(L,1,0);
152 | syslog(LOG_DEBUG,"garbage collect some C code");
153 |
154 | return 0;
155 | }
156 |
157 | int cclua_encap(lua_State *L)
158 | {
159 | struct cclua *obj;
160 |
161 | luaL_checktype(L,1,LUA_TLIGHTUSERDATA);
162 | obj = lua_newuserdata(L,sizeof(struct cclua));
163 | obj->data = lua_touserdata(L,1);
164 | luaL_getmetatable(L,CC_TYPE);
165 | lua_setmetatable(L,-2);
166 | return 1;
167 | }
168 |
169 | const struct luaL_Reg mcc_meta[] =
170 | {
171 | { "__tostring" , cclua___tostring } ,
172 | { "__gc" , cclua___gc } ,
173 | { NULL , NULL }
174 | };
175 |
176 | int luaopen_cc(lua_State *L)
177 | {
178 | luaL_newmetatable(L,CC_TYPE);
179 | luaL_register(L,NULL,mcc_meta);
180 | lua_pushvalue(L,-1);
181 | lua_setfield(L,-2,"__index");
182 | lua_pushvalue(L,-1);
183 | lua_setfield(L,-2,"__newindex");
184 |
185 | if (lua_isfunction(L,1))
186 | {
187 | lua_pushvalue(L,1);
188 | lua_setfield(L,-2,"dispose");
189 | }
190 |
191 | lua_pushcfunction(L,cclua_encap);
192 | return 1;
193 | }
194 | ]]
195 |
196 | local x = tcc.new()
197 | x:output_type('memory')
198 | x:compile(code)
199 | x:relocate()
200 | local init = x:get_symbol('luaopen_cc')
201 | encap = init(tcc.dispose)
202 | end
203 |
204 | -- **********************************************************************
205 |
206 | CACHE = setmetatable( {} , { __mode = "k" })
207 |
208 | function compile(fname,code,isfile,defines)
209 | defines = defines or {}
210 | local x = tcc.new()
211 |
212 | for def,val in pairs(defines) do
213 | x:define(def,val)
214 | end
215 | x:output_type('memory')
216 |
217 | if not x:compile(code,isfile) then
218 | return nil
219 | end
220 |
221 | local blob = x:relocate()
222 | local f = x:get_symbol(fname)
223 |
224 | if f then
225 | CACHE[f] = encap(blob)
226 | return f,blob
227 | end
228 |
229 | return nil
230 | end
231 |
232 | if _VERSION >= "Lua 5.2" then
233 | return _ENV
234 | end
235 |
--------------------------------------------------------------------------------
/lua/const/exit.lua:
--------------------------------------------------------------------------------
1 | -- ************************************************************************
2 | --
3 | -- Copyright 2018 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ************************************************************************
21 | -- luacheck: ignore 611
22 |
23 | return {
24 | -- --------------------------------------------------------
25 | -- The following are defined by Standard C
26 | -- --------------------------------------------------------
27 |
28 | SUCCESS = 0, -- standard C exit code
29 | FAILURE = 1, -- standard C exit code
30 |
31 | -- -----------------------------------------------------
32 | -- The following are defined by the LSB
33 | -- https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
34 | -- -----------------------------------------------------
35 |
36 | GENERIC_UNSPECIFIED = 1, -- same as standard C exit code
37 | INVALIDARGUMENT = 2, -- invalid or excess argumetns
38 | NOTIMPLEMENTED = 3, -- unimplemented feature
39 | NOPERMISSION = 4, -- the user has insufficient priviledges
40 | NOTINSTALLED = 5, -- the program is not installed
41 | NOTCONFIGURED = 6, -- the program is not configured
42 | NOTRUNNING = 7, -- the program is not running
43 |
44 | -- ------------------------------------------------------------------------
45 | -- The following are defined by BSD, and usually found in C via
46 | -- ------------------------------------------------------------------------
47 |
48 | OK = 0, -- successful termination
49 | USAGE = 64, -- command line usage error
50 | DATAERR = 65, -- data format error
51 | NOINPUT = 66, -- cannot open input
52 | NOUSER = 67, -- addressee unknown
53 | NOHOST = 68, -- host name unknown
54 | UNAVAILABLE = 69, -- service unavailable
55 | SOFTWARE = 70, -- internal software error
56 | OSERR = 71, -- system error (e.g., can't fork)
57 | OSFILE = 72, -- critical OS file missing
58 | CANTCREAT = 73, -- can't create (user) output file
59 | IOERR = 74, -- input/output error
60 | TEMPFAIL = 75, -- temp failure; user is invited to retry
61 | PROTOCOL = 76, -- remote error in protocol
62 | NOPERM = 77, -- permission denied
63 | CONFIG = 78, -- configuration error
64 | NOTFOUND = 79, -- required file not found
65 |
66 | -- -------------------------------------------------------------------
67 | -- The following are defined by systemd
68 | -- https://www.freedesktop.org/software/systemd/man/systemd.exec.html
69 | -- -------------------------------------------------------------------
70 |
71 | CHDIR = 200, -- Changing to the requested working directory failed.
72 | NICE = 201, -- Failed to set up process scheduling priority (nice level).
73 | FDS = 202, -- Failed to close unwanted file descriptors, or to adjust passed file descriptors.
74 | EXEC = 203, -- The actual process execution failed (specifically, the execve(2) system call).
75 | MEMORY = 204, -- Failed to perform an action due to memory shortage.
76 | LIMITS = 205, -- Failed to adjust resource limits.
77 | OOM_ADJUST = 206, -- Failed to adjust the OOM setting.
78 | SIGNAL_MASK = 207, -- Failed to set process signal mask.
79 | STDIN = 208, -- Failed to set up standard input.
80 | STDOUT = 209, -- Failed to set up standard output.
81 | CHROOT = 210, -- Failed to change root directory (chroot(2)).
82 | IOPRIO = 211, -- Failed to set up IO scheduling priority.
83 | TIMERSLACK = 212, -- Failed to set up timer slack.
84 | SECUREBITS = 213, -- Failed to set process secure bits.
85 | SETSCHEDULER = 214, -- Failed to set up CPU scheduling.
86 | CPUAFFINITY = 215, -- Failed to set up CPU affinity.
87 | GROUP = 216, -- Failed to determine or change group credentials.
88 | USER = 217, -- Failed to determine or change user credentials, or to set up user namespacing.
89 | CAPABILITIES = 218, -- Failed to drop capabilities, or apply ambient capabilities.
90 | CGROUP = 219, -- Setting up the service control group failed.
91 | SETSID = 220, -- Failed to create new process session.
92 | CONFIRM = 221, -- Execution has been cancelled by the user.
93 | STDERR = 222, -- Failed to set up standard error output.
94 | -- 223 not defined
95 | PAM = 224, -- Failed to set up PAM session.
96 | NETWORK = 225, -- Failed to set up network namespacing.
97 | NAMESPACE = 226, -- Failed to set up mount, UTS, or IPC namespacing.
98 | NO_NEW_PRIVILEDGES = 227, -- Failed to disable new privileges.
99 | SECCOMP = 228, -- Failed to apply system call filters.
100 | SELINUX_CONTEXT = 229, -- Determining or changing SELinux context failed.
101 | PERSONALITY = 230, -- Failed to set up an execution domain (personality).
102 | APPARMOR_PROFILE = 231, -- Failed to prepare changing AppArmor profile.
103 | ADDRESS_FAMILIES = 232, -- Failed to restrict address families.
104 | RUNTIME_DIRECTORY = 233, -- Setting up runtime directory failed.
105 | -- 234 not defined
106 | CHOWN = 235, -- Failed to adjust socket ownership.
107 | SMACK_PROCESS_LABEL = 236, -- Failed to set SMACK label.
108 | KEYRING = 237, -- Failed to set up kernel keyring.
109 | STATE_DIRECTORY = 238, -- Failed to set up unit's state directory.
110 | CACHE_DIRECTORY = 239, -- Failed to set up unit's cache directory.
111 | LOGS_DIRECTORY = 240, -- Failed to set up unit's logging directory.
112 | CONFIGURATION_DIRECTORY = 241, -- Failed to set up unit's configuration directory.
113 | NUMA_POLICY = 242, -- Failed to set up unit's NUMA memory policy.
114 | CREDENTIALS = 243, -- Failed to set up unit's credentials.
115 | -- 244 not defined
116 | BPF = 245, -- Failed to apply BPF restrictions.
117 | }
118 |
--------------------------------------------------------------------------------
/lua/const/gopher-types.lua:
--------------------------------------------------------------------------------
1 | -- ************************************************************************
2 | --
3 | -- Copyright 2018 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ************************************************************************
21 | -- luacheck: ignore 611
22 |
23 | return setmetatable(
24 | {
25 | ['0'] = 'file', -- RFC-1436
26 | ['1'] = 'dir',
27 | ['2'] = 'CSO',
28 | ['3'] = 'error',
29 | ['4'] = 'binhex',
30 | ['5'] = 'EXE',
31 | ['6'] = 'uuencode',
32 | ['7'] = 'search',
33 | ['8'] = 'telnet',
34 | ['9'] = 'binary',
35 | ['+'] = 'server',
36 | ['T'] = 'tn3270',
37 | ['g'] = 'gif',
38 | ['I'] = 'image',
39 | ['i'] = 'info', -- extensions
40 | ['c'] = 'calendar',
41 | ['d'] = 'worddoc',
42 | ['h'] = 'html',
43 | ['P'] = 'PDF',
44 | ['m'] = 'mail',
45 | ['M'] = 'MIME',
46 | ['s'] = 'sound',
47 | ['x'] = 'xml',
48 | ['p'] = 'png',
49 | [';'] = 'video',
50 |
51 | file = '0',
52 | dir = '1',
53 | CSO = '2',
54 | error = '3',
55 | binhex = '4',
56 | EXE = '5',
57 | uuencode = '6',
58 | search = '7',
59 | telnet = '8',
60 | binary = '9',
61 | server = '+',
62 | tn3270 = 'T',
63 | gif = 'g',
64 | image = 'I',
65 | info = 'i',
66 | calendar = 'c',
67 | worddoc = 'd',
68 | html = 'h',
69 | png = 'p',
70 | mail = 'm',
71 | sound = 's',
72 | xml = 'x',
73 | PDF = 'P',
74 | MIME = 'M',
75 | video = ';',
76 | },
77 | {
78 | __index = function(_,key) return key end
79 | }
80 | )
81 |
--------------------------------------------------------------------------------
/lua/const/http-response.lua:
--------------------------------------------------------------------------------
1 | -- ************************************************************************
2 | --
3 | -- Copyright 2018 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ************************************************************************
21 | -- luacheck: ignore 611
22 | -- https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
23 | -- HTTP/1.0 RFC-1945
24 | -- HTTP/1.1 RFC-7235 RFC-7233 RFC-7232 RFC-7231 RFC-2616 RFC-2068
25 | -- HTTP/1.1-2.0 RFC-9110
26 |
27 | return {
28 | PROCESS =
29 | {
30 | CONTINUE = 100, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
31 | SWITCHPROTO = 101, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
32 | PROCESSING = 102, -- RFC-2518
33 | EARLYHINTS = 103, -- RFC-8297
34 | },
35 |
36 | SUCCESS =
37 | {
38 | OKAY = 200, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
39 | CREATED = 201, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
40 | ACCEPTED = 202, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
41 | NOAUTH = 203, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
42 | NOCONTENT = 204, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
43 | RESETCONTENT = 205, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
44 | PARTIALCONTENT = 206, -- RFC-9110 RFC-7233 RFC-2616 RFC-2068
45 | MULTISTATUS = 207, -- RFC-4918
46 | ALREADYREPORTED = 208, -- RFC-5842
47 | IMUSED = 226, -- RFC-3229
48 | },
49 |
50 | REDIRECT =
51 | {
52 | MULTICHOICE = 300, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
53 | MOVEPERM = 301, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
54 | MOVETEMP = 302, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
55 | SEEOTHER = 303, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
56 | NOTMODIFIED = 304, -- RFC-9110 RFC-7232 RFC-2616 RFC-2068 RFC-1945
57 | USEPROXY = 305, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
58 | MOVETEMP_M = 307, -- RFC-9110 RFC-7231 RFC-2616
59 | MOVEPERM_M = 308, -- RFC-9110 RFC-7538 RFC-7238
60 | },
61 |
62 | CLIENT =
63 | {
64 | BADREQ = 400, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
65 | UNAUTHORIZED = 401, -- RFC-9110 RFC-7235 RFC-2616 RFC-2068 RFC-1945
66 | PAYMENTREQUIRED = 402, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
67 | FORBIDDEN = 403, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
68 | NOTFOUND = 404, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
69 | METHODNOTALLOWED = 405, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
70 | NOTACCEPTABLE = 406, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
71 | PROXYAUTHREQ = 407, -- RFC-9110 RFC-7235 RFC-2616 RFC-2068
72 | TIMEOUT = 408, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
73 | CONFLICT = 409, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
74 | GONE = 410, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
75 | LENGTHREQ = 411, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
76 | PRECONDITION = 412, -- RFC-9110 RFC-7232 RFC-2616 RFC-2068
77 | TOOLARGE = 413, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
78 | URITOOLONG = 414, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
79 | MEDIATYPE = 415, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
80 | RANGEERROR = 416, -- RFC-9110 RFC-7233 RFC-2616
81 | EXPECTATION = 417, -- RFC-9110 RFC-7231 RFC-2616
82 | IM_A_TEA_POT = 418, -- RFC-2324 section 2.3.2
83 | MISDIRECT = 421, -- RFC-9110
84 | UNPROCESSENTITY = 422, -- RFC-9110
85 | LOCKED = 423, -- RFC-4918
86 | FAILEDDEP = 424, -- RFC-4918
87 | TOOEARLY = 425, -- RFC-8470
88 | UPGRADE = 426, -- RFC-9110 RFC-7231
89 | PRECONDITION2 = 428, -- RFC-6585
90 | TOOMANYREQUESTS = 429, -- RFC-6585
91 | REQHDR2BIG = 431, -- RFC-6585
92 | LEGALCENSOR = 451, -- RFC-7725
93 | },
94 |
95 | SERVER =
96 | {
97 | INTERNALERR = 500, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
98 | NOTIMP = 501, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
99 | BADGATEWAY = 502, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068 RFC-1945
100 | NOSERVICE = 503, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
101 | GATEWAYTIMEOUT = 504, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
102 | HTTPVERSION = 505, -- RFC-9110 RFC-7231 RFC-2616 RFC-2068
103 | VARIANTALSO = 506, -- RFC-2295
104 | ENOSPC = 507, -- RFC-4918
105 | LOOP = 508, -- RFC-5842
106 | EXCEEDBW = 509, -- ?
107 | NOTEXTENDED = 510, -- RFC-2774 (obsolete)
108 | NETAUTHREQ = 511, -- RFC-6585
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lua/date.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2012 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals tojulianday fromjulianday dayofweek daysinmonth
22 | -- luacheck: ignore 611
23 |
24 | local _VERSION = _VERSION
25 | local floor = math.floor
26 | local os = os
27 |
28 | if _VERSION == "Lua 5.1" then
29 | module("org.conman.date")
30 | else
31 | _ENV = {}
32 | end
33 |
34 | -- *********************************************************************
35 | --
36 | -- Usage: day = date.tojulianday([date])
37 | --
38 | -- Desc: Convert a date to a Julian day.
39 | --
40 | -- Input: date (table/optional) given date or current date
41 | -- * year = 1999
42 | -- * month = 1..12
43 | -- * day = 1 .. 31
44 | --
45 | -- Return: day (number) Julian day
46 | --
47 | -- *********************************************************************
48 |
49 | function tojulianday(date)
50 | date = date or os.date("*t")
51 |
52 | local a = floor((14 - date.month) / 12)
53 | local y = date.year + 4800 - a
54 | local m = date.month + 12 * a - 3
55 |
56 | return date.day
57 | + floor((153 * m + 2) / 5)
58 | + y * 365
59 | + floor(y / 4)
60 | - floor(y / 100)
61 | + floor(y / 400)
62 | - 32045
63 | end
64 |
65 | -- **********************************************************************
66 | --
67 | -- Usage: date = date.fromjulianday(day)
68 | --
69 | -- Desc: Convert a Julian day to it's corresponding date
70 | --
71 | -- Input: day (number) Julian day
72 | --
73 | -- Return: date (table)
74 | -- * year = ...
75 | -- * month = 1 .. 12
76 | -- * day = 1 .. 31
77 | --
78 | -- *********************************************************************
79 |
80 | function fromjulianday(jd)
81 | local a = jd + 32044
82 | local b = floor((4 * a + 3) / 146097)
83 | local c = a - floor((b * 146097) / 4)
84 | local d = floor((4 * c + 3) / 1461)
85 | local e = c - floor((1461 * d) / 4)
86 | local m = floor((5 * e + 2) / 153)
87 |
88 | return {
89 | day = e - floor((153 * m + 2) / 5) + 1,
90 | month = m + 3 - 12 * floor((m / 10)),
91 | year = b * 100 + d - 4800 + floor(m / 10)
92 | }
93 | end
94 |
95 | -- ************************************************************************
96 | --
97 | -- Usage: day = date.dayofweek(date)
98 | --
99 | -- Desc: Calculate the day of the week (1 .. 7, 1 = Sunday) of
100 | -- the given date.
101 | --
102 | -- Input: date (table)
103 | -- * year = ...
104 | -- * month = 1 .. 12
105 | -- * day = 1 .. 31
106 | --
107 | -- Return: day (number) 1..7, 1 = Sunday
108 | --
109 | -- *********************************************************************
110 |
111 | function dayofweek(date)
112 | local a = floor((14 - date.month) / 12)
113 | local y = date.year - a
114 | local m = date.month + 12 * a - 2
115 | local d = date.day
116 | + y
117 | + floor(y / 4)
118 | - floor(y / 100)
119 | + floor(y / 400)
120 | + floor(31 * m / 12)
121 | return (d % 7) + 1
122 | end
123 |
124 | -- ************************************************************************
125 | --
126 | -- Usage: max = day.daysinmonth(date)
127 | --
128 | -- Desc: Calculate the maximum day in a month
129 | --
130 | -- Input: date (table)
131 | -- * year = ...
132 | -- * month = 1 .. 12
133 | --
134 | -- Return: max (number) 1 .. 28,29,30,31 (depends upon month)
135 | --
136 | -- *********************************************************************
137 |
138 | local maxdays = { 31 , 0 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }
139 |
140 | function daysinmonth(date)
141 | if date.month == 2 then
142 | if date.year % 400 == 0 then return 29
143 | elseif date.year % 100 == 0 then return 28
144 | elseif date.year % 4 == 0 then return 29
145 | else return 28 end
146 | else
147 | return maxdays[date.month]
148 | end
149 | end
150 |
151 | -- ************************************************************************
152 |
153 | if _VERSION >= "Lua 5.2" then
154 | return _ENV
155 | end
156 |
--------------------------------------------------------------------------------
/lua/debug.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2010 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals hexdump
22 | -- luacheck: ignore 611
23 |
24 | local io = require "io"
25 | local char = require "org.conman.parsers.ascii.char"
26 | local lpeg = require "lpeg"
27 | local _VERSION = _VERSION
28 |
29 | if _VERSION == "Lua 5.1" then
30 | module("org.conman.debug")
31 | else
32 | _ENV = {}
33 | end
34 |
35 | -- *********************************************************************
36 |
37 | local toascii = lpeg.Cs((char + lpeg.P(1) / ".")^0)
38 | local tohex = lpeg.Cs((lpeg.P(1) / function(c)
39 | return ("%02X "):format(c:byte())
40 | end)^0)
41 |
42 | function hexdump(bin,delta,bias,out)
43 | delta = delta or 16
44 | bias = bias or 0
45 | out = out or function(off,hex,ascii,d)
46 | io.stderr:write(
47 | ("%08X: "):format(off),
48 | hex,
49 | (" "):rep(3 * (d - (#hex / 3))),
50 | ascii,
51 | "\n"
52 | )
53 | end
54 |
55 | local offset = 1
56 |
57 | while offset <= #bin do
58 | local s = bin:sub(offset,offset + (delta - 1))
59 | local h = tohex:match(s)
60 | local a = toascii:match(s)
61 |
62 | out((offset - 1) + bias,h,a,delta)
63 | offset = offset + delta
64 | end
65 | end
66 |
67 | -- ********************************************************************
68 |
69 | if _VERSION >= "Lua 5.2" then
70 | return _ENV
71 | end
72 |
--------------------------------------------------------------------------------
/lua/dns/resolv.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2010 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals address
22 | -- luacheck: ignore 611
23 |
24 | local net = require "org.conman.net"
25 | local dns = require "org.conman.dns"
26 | local math = require "math"
27 |
28 | local _VERSION = _VERSION
29 | local ipairs = ipairs
30 |
31 | if _VERSION == "Lua 5.1" then
32 | module("org.conman.dns.resolv")
33 | else
34 | _ENV = {}
35 | end
36 |
37 | -- ********************************************************************
38 |
39 | local servers =
40 | {
41 | net.address("192.168.1.10","domain","udp"),
42 | }
43 |
44 | local searches =
45 | {
46 | ".",
47 | ".roswell.area51."
48 | }
49 |
50 | servers.current = 1
51 | servers.sock = net.socket(servers[1].family,'udp')
52 |
53 | -- ********************************************************************
54 |
55 | local function query(host,type)
56 | local packet
57 | local result
58 | local err
59 | local id
60 | local _
61 | local cycle
62 |
63 | id = math.random()
64 | packet,err = dns.encode {
65 | id = id,
66 | query = true,
67 | rd = true,
68 | opcode = 'query',
69 | question =
70 | {
71 | name = host,
72 | type = type,
73 | class = 'in'
74 | }
75 | }
76 |
77 | if packet == nil then
78 | return packet,err
79 | end
80 |
81 | cycle = servers.current
82 |
83 | repeat
84 | servers.sock:write(servers[servers.current],packet)
85 |
86 | _,result,err = servers.sock:read(5)
87 | if err == 0 then
88 | return dns.decode(result)
89 | end
90 |
91 | servers.sock:close()
92 | cycle = cycle + 1
93 | if cycle > #servers then
94 | cycle = 1
95 | end
96 | servers.sock = net.socket(servers[cycle].family,'udp')
97 | until cycle == servers.current
98 |
99 | return nil
100 | end
101 |
102 | -- ********************************************************************
103 |
104 | local function query_a(host,type)
105 | type = type:upper()
106 | local a = query(host,type)
107 |
108 | if a == nil then
109 | return nil
110 | end
111 |
112 | for i = 1,#a.answers do
113 | if a.answers[i].type == type then
114 | return a.answers[i].address
115 | end
116 | end
117 | return nil
118 | end
119 |
120 | -- ********************************************************************
121 |
122 | function address(host)
123 | for _,suffix in ipairs(searches) do
124 | local hostname = host .. suffix
125 | local a = query_a(hostname,'a')
126 | if a == nil then
127 | a = query_a(hostname,'aaaa')
128 | end
129 | if a ~= nil then
130 | return a
131 | end
132 | end
133 | return nil
134 | end
135 |
136 | -- ********************************************************************
137 |
138 | if _VERSION >= "Lua 5.2" then
139 | return _ENV
140 | end
141 |
--------------------------------------------------------------------------------
/lua/getopt.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2010 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- --------------------------------------------------------------------
21 | --
22 | -- Some standards for options. First, long options:
23 | -- http://www.gnu.org/prep/standards/standards.html#Option-Table
24 | --
25 | -- And now for short options:
26 | -- http://www.catb.org/~esr/writings/taoup/html/ch10s05.html
27 | -- ********************************************************************
28 | -- luacheck: globals getopt
29 | -- luacheck: ignore 611
30 |
31 | local io = require "io"
32 | local _VERSION = _VERSION
33 | local type = type
34 |
35 | if _VERSION == "Lua 5.1" then
36 | module("org.conman.getopt")
37 | else
38 | _ENV = {}
39 | end
40 |
41 | local SHORT_OPT = 1
42 | local LONG_OPT = 2
43 | local ARGUMENT = 3
44 | local CALLBACK = 4
45 |
46 | -- ************************************************************************
47 |
48 | local function long_match(lnopt,arg,i,err)
49 | local tag
50 | local value
51 |
52 | tag,value = arg[i]:match("^%-%-([^%=]+)%=?(.*)")
53 |
54 | if lnopt == nil then
55 | err(tag)
56 | return i + 1
57 | end
58 |
59 | if lnopt[ARGUMENT] then
60 | if value == "" then
61 | i = i + 1
62 | value = arg[i]
63 | end
64 | else
65 | value = nil
66 | end
67 |
68 | lnopt[CALLBACK](value)
69 |
70 | return i + 1
71 | end
72 |
73 | -- ***********************************************************************
74 |
75 | local function short_match(shopt,arg,i,err)
76 | local value
77 |
78 | for n = 2 , #arg[i] do
79 | local opt = arg[i]:sub(n,n)
80 |
81 | if shopt[opt] == nil then
82 | err(opt)
83 | elseif not shopt[opt][ARGUMENT] then
84 | shopt[opt][CALLBACK]()
85 | else
86 | if n == #arg[i] then
87 | i = i + 1
88 | value = arg[i]
89 | else
90 | if arg[i]:sub(n+1,n+1) == '=' then
91 | value = arg[i]:sub(n+2)
92 | else
93 | value = arg[i]:sub(n+1)
94 | end
95 | end
96 |
97 | shopt[opt][CALLBACK](value)
98 | return i + 1
99 | end
100 | end
101 | return i + 1
102 | end
103 |
104 | -- ***********************************************************************
105 |
106 | function getopt(arg,options,err)
107 | local shopt = {}
108 | local lnopt = {}
109 | err = err or function(opt)
110 | io.stderr:write("unsupported option: ",opt,"\n")
111 | end
112 |
113 | for i = 1 , #options do
114 | shopt[options[i][SHORT_OPT]] = options[i]
115 | if options[i][LONG_OPT] ~= nil then
116 | if type(options[i][LONG_OPT]) == 'string' then
117 | lnopt[options[i][LONG_OPT]] = options[i]
118 | elseif type(options[i][LONG_OPT]) == 'table' then
119 | for j = 1 , #options[i][LONG_OPT] do
120 | lnopt[options[i][LONG_OPT][j]] = options[i]
121 | end
122 | end
123 | end
124 | end
125 |
126 | local i = 1
127 |
128 | while(i <= #arg) do
129 | local al
130 | local as
131 |
132 | al = arg[i]:match("^%-%-([^%=]+)")
133 | as = arg[i]:match("^%-([^%-])")
134 |
135 | if al ~= nil then
136 | i = long_match(lnopt[al],arg,i,err)
137 | elseif as ~= nil then
138 | i = short_match(shopt,arg,i,err)
139 | else
140 | return i
141 | end
142 | end
143 |
144 | return i
145 | end
146 |
147 | -- ***********************************************************************
148 |
149 | if _VERSION >= "Lua 5.2" then
150 | return _ENV
151 | end
152 |
--------------------------------------------------------------------------------
/lua/gzip.lua:
--------------------------------------------------------------------------------
1 |
2 | -- RFC-1952
3 | -- luacheck: globals idiv read
4 | -- luacheck: ignore 611
5 |
6 | local _VERSION = _VERSION
7 | local pairs = pairs
8 | local setmetatable = setmetatable
9 |
10 | local math = require "math"
11 | local table = require "table"
12 |
13 | if _VERSION == "Lua 5.1" then
14 | module("org.conman.gzip")
15 | else
16 | _ENV = {}
17 | end
18 |
19 | -- ************************************************************************
20 |
21 | local function reverse_index(tab)
22 | local keys = {}
23 | for name in pairs(tab) do
24 | table.insert(keys,name)
25 | end
26 |
27 | for i = 1 , #keys do
28 | local k = keys[i]
29 | local v = tab[k]
30 | tab[v] = k
31 | end
32 |
33 | return setmetatable(tab,{
34 | __index = function(_,key)
35 | if type(key) == 'number' then
36 | return '-'
37 | elseif type(key) == 'string' then
38 | return 0
39 | end
40 | end
41 | })
42 | end
43 |
44 | os = reverse_index { -- luacheck: ignore
45 | ["MS-DOS"] = 0,
46 | ["Amiga"] = 1,
47 | ["OpenVMS"] = 2,
48 | ["UNIX"] = 3,
49 | ["VM/CMS"] = 4,
50 | ["Atari ST"] = 5,
51 | ["OS/2"] = 6,
52 | ["Macintosh"] = 7,
53 | ["Z-System"] = 8,
54 | ["CP/M"] = 9,
55 | ["Windows"] = 10,
56 | ["MVS"] = 11,
57 | ["VSE"] = 12,
58 | ["Acorn Risc"] = 13,
59 | ["VFAT"] = 14,
60 | ["alternative MVS"] = 15,
61 | ["BeOS"] = 16,
62 | ["Tandem"] = 17,
63 | ["OS/400"] = 18,
64 | ["Darwin"] = 19,
65 | }
66 |
67 | -- ************************************************************************
68 |
69 | function idiv(up,down)
70 | local q = math.floor(up/down)
71 | local r = up % down
72 | return q,r
73 | end
74 |
75 | -- ************************************************************************
76 |
77 | local function r16(gf)
78 | return gf:read(1):byte()
79 | + gf:read(1):byte() * 2*8
80 | end
81 |
82 | -- ************************************************************************
83 |
84 | local function r32(gf)
85 | return gf:read(1):byte()
86 | + gf:read(1):byte() * 2^8
87 | + gf:read(1):byte() * 2^16
88 | + gf:read(1):byte() * 2^24
89 | end
90 |
91 | -- ************************************************************************
92 |
93 | local function bool(n)
94 | local q,r = idiv(n,2)
95 | return r ~= 0 , q
96 | end
97 |
98 | -- ************************************************************************
99 |
100 | local function read_asciiz(gf,acc)
101 | acc = acc or ""
102 | local c = gf:read(1)
103 | if c == "\0" then
104 | return acc
105 | else
106 | return read_asciiz(gf,acc .. c)
107 | end
108 | end
109 |
110 | -- ************************************************************************
111 |
112 | function read(gf)
113 | local id = gf:read(2)
114 | if id ~= "\31\139" then
115 | return nil
116 | end
117 |
118 | local comp = gf:read(1)
119 | if comp ~= "\8" then
120 | return nil
121 | end
122 |
123 | local meta = {}
124 | local f = gf:read(1):byte()
125 | meta.text,f = bool(f)
126 | local fhcrc,f = bool(f) -- luacheck: ignore
127 | local fextra,f = bool(f) -- luacheck: ignore
128 | local fname,f = bool(f) -- luacheck: ignore
129 | local fcomment,_ = bool(f)
130 | meta.mtime = r32(gf)
131 | meta.xfl = gf:read(1):byte()
132 | meta.os = os[gf:read(1):byte()]
133 |
134 | if fextra then
135 | meta.extra = {}
136 |
137 | local len = r16(gf)
138 | while len > 0 do
139 | local id2 = gf:read(2)
140 | local size = r16(gf)
141 | local data = gf:read(size)
142 | meta.extra[id2] = data
143 | len = len - 4
144 | len = len - size
145 | end
146 | end
147 |
148 | if fname then
149 | meta.name = read_asciiz(gf)
150 | end
151 |
152 | if fcomment then
153 | meta.comment = read_asciiz(gf)
154 | end
155 |
156 | if fhcrc then
157 | meta.crc16 = r16(gf)
158 | end
159 |
160 | local here = gf:seek()
161 |
162 | gf:seek('end',-8)
163 | meta.crc32 = r32(gf)
164 | meta.size = r32(gf)
165 | gf:seek('set',here)
166 |
167 | return meta
168 | end
169 |
170 | -- ************************************************************************
171 |
172 | if _VERSION >= "Lua 5.2" then
173 | return _ENV
174 | end
175 |
--------------------------------------------------------------------------------
/lua/mailcap.lua:
--------------------------------------------------------------------------------
1 | -- ************************************************************************
2 | --
3 | -- Handle mailcap files
4 | -- Copyright 2019 by Sean Conner. All Rights Reserved.
5 | --
6 | -- This library is free software; you can redistribute it and/or modify it
7 | -- under the terms of the GNU Lesser General Public License as published by
8 | -- the Free Software Foundation; either version 3 of the License, or (at your
9 | -- option) any later version.
10 | --
11 | -- This library is distributed in the hope that it will be useful, but
12 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 | -- License for more details.
15 | --
16 | -- You should have received a copy of the GNU Lesser General Public License
17 | -- along with this library; if not, see .
18 | --
19 | -- Comments, questions and criticisms can be sent to: sean@conman.org
20 | --
21 | -- ************************************************************************
22 | -- luacheck: ignore 611
23 | --
24 | -- https://www.commandlinux.com/man-page/man5/mailcap.5.html
25 | -- RFC-1524
26 |
27 | local lpeg = require "lpeg" -- semver: ~1.0.0
28 |
29 | local Carg = lpeg.Carg
30 | local Cc = lpeg.Cc
31 | local Cf = lpeg.Cf
32 | local Cg = lpeg.Cg
33 | local Cs = lpeg.Cs
34 | local Ct = lpeg.Ct
35 | local C = lpeg.C
36 | local P = lpeg.P
37 | local R = lpeg.R
38 |
39 | -- ************************************************************************
40 |
41 | local mimetype do
42 | local iana_token = R("AZ","az","09","--","..")^1
43 | local majortype = iana_token
44 | local minortype = iana_token + P"*"
45 |
46 | mimetype = C(majortype) * P"/" * C(minortype)
47 | end
48 |
49 | -- ************************************************************************
50 |
51 | local CAPS = {} do
52 | local EOLN = P"\n" * Carg(1)
53 | / function(c)
54 | c._line = c._line + 1
55 | end
56 | local SP = P" "
57 | + P"\\" * EOLN
58 | + P"\t"
59 | local SEMI = P";" * SP^0
60 | local char = P"\\" * EOLN / " "
61 | + P[[\]] * C(1) / "%1"
62 | + P"\t" / " "
63 | + R(" :","<\226","\192\255")
64 | local cmd = Cs(char^1)
65 | local number = R"09"^1 / tonumber
66 | local fields = P'notes=' * Cg(cmd, 'notes')
67 | + P'test=' * Cg(cmd, 'test')
68 | + P'print=' * Cg(cmd, 'print')
69 | + P'compose=' * Cg(cmd, 'compose')
70 | + P'composetyped=' * Cg(cmd, 'composedtype')
71 | + P'stream-buffer-size=' * Cg(number, 'stream_buffer_size')
72 | + P'needsterminal' * Cg(Cc(true),'needsterminal')
73 | + P'copiousoutput' * Cg(Cc(true),'copiousoutput')
74 | + P'textualnewlines=1' * Cg(Cc(true),'textualnewlines')
75 | + P'textualnewlines=0' -- false by default
76 | local program = Cg(cmd,'view')
77 | local data = program * (SEMI * fields)^0
78 | local entry = mimetype * SEMI * Ct(data) * EOLN
79 | + Cc(false) * C(R("\t\t"," \126","\192\255")^0) * EOLN
80 |
81 | local mailcapfile = Cf(Carg(1) * (Cg(entry))^0,function(caps,major,minor,node)
82 | if major then
83 | if not caps[major] then caps[major] = {} end
84 | if minor == '*' then
85 | local mt = getmetatable(caps[major])
86 |
87 | -- ----------------------------------------------------------------
88 | -- if mt exists, there's a duplicate entry, but since I'm not doing
89 | -- anything about, there's not much point in checking for it.
90 | -- ----------------------------------------------------------------
91 |
92 | if not mt then
93 | mt = {}
94 | end
95 |
96 | mt.__index = function()
97 | return node
98 | end
99 |
100 | setmetatable(caps[major],mt)
101 | else
102 | caps[major][minor] = node
103 | end
104 | end
105 |
106 | return caps
107 | end)
108 |
109 | local function readmailcap(fname)
110 | local caps = { _file = fname , _line = 0 }
111 | local f = io.open(fname,"r")
112 | if f then
113 | mailcapfile:match(f:read("*a"),1,caps)
114 | f:close()
115 | end
116 | return caps
117 | end
118 |
119 | -- **********************************************************************
120 | -- RFC-1524 states looking through $MAILCAPS and if not present, default
121 | -- to $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap
122 | -- I don't think that default order is great---I prefer going from local
123 | -- definitions to system definitions, so I change up the order to reflect
124 | -- that. Also, I add /usr/share/etc/mailcap, juse because.
125 | -- **********************************************************************
126 |
127 | local mailcaps = os.getenv("MAILCAPS")
128 |
129 | if mailcaps then
130 | for path in mailcaps:gmatch "[^%:]+" do
131 | table.insert(CAPS,readmailcap(path))
132 | end
133 | else
134 | CAPS[1] = readmailcap(os.getenv("HOME") .. "/.mailcap")
135 | CAPS[2] = readmailcap("/usr/local/etc/mailcap")
136 | CAPS[3] = readmailcap("/usr/share/etc/mailcap")
137 | CAPS[4] = readmailcap("/usr/etc/mailcap")
138 | CAPS[5] = readmailcap("/etc/mailcap")
139 | end
140 | end
141 |
142 | -- ************************************************************************
143 |
144 | local cmd do
145 | local char = P"%s" * Carg(1) * Carg(2)
146 | / function(s,f)
147 | s.redirect = false
148 | return f
149 | end
150 | + P"%{" * Carg(4) * C(R("AZ","az","09","__","--","..")^1) * P"}"
151 | / function(tab,cap)
152 | return tab[cap] or ""
153 | end
154 | + P"%t" * Carg(3) / "%1"
155 | + R(" \126","\192\255")
156 |
157 | local redirect = Carg(1) * Carg(2)
158 | / function(s,f)
159 | if s.redirect then
160 | return string.format(" %s %s",s.dir,f)
161 | end
162 | end
163 | cmd = Carg(1) / function(s) s.redirect = true end
164 | * Cs(char^1 * redirect)
165 | end
166 |
167 | -- ************************************************************************
168 |
169 | local function handle(what,dir,page,type,params)
170 | local function runthisp(node)
171 | if not node then return false end
172 | if node.test then
173 | local program = cmd:match(node.test,1,{ dir = "<" },page,type,params)
174 | return os.execute(program)
175 | else
176 | return true
177 | end
178 | end
179 |
180 | params = params or {}
181 | local major,minor = mimetype:match(type)
182 |
183 | for _,cap in ipairs(CAPS) do
184 | local node = cap[major] and cap[major][minor]
185 | if runthisp(node) then
186 | local program = cmd:match(node[what],1,{ dir = dir },page,type,params or {})
187 | return os.execute(program)
188 | end
189 | end
190 | end
191 |
192 | -- ************************************************************************
193 |
194 | return {
195 | view = function(page,type,params)
196 | return handle('view','<',page,type,params)
197 | end,
198 |
199 | print = function(page,type,params)
200 | return handle('print','<',page,type,params)
201 | end,
202 |
203 | compose = function(page,type,params)
204 | return handle('compose','>',page,type,params)
205 | end,
206 |
207 | composetyped = function(page,type,params)
208 | return handle('composetyped','>',page,type,params)
209 | end,
210 | }
211 |
--------------------------------------------------------------------------------
/lua/net/tcp.lua:
--------------------------------------------------------------------------------
1 | -- *******************************************************************
2 | --
3 | -- Copyright 2019 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- *******************************************************************
21 | -- luacheck: globals accept listena listen connecta connect
22 | -- luacheck: ignore 611
23 |
24 | local syslog = require "org.conman.syslog"
25 | local net = require "org.conman.net"
26 | local errno = require "org.conman.errno"
27 | local ios = require "org.conman.net.ios"
28 |
29 | local _VERSION = _VERSION
30 | local setmetatable = setmetatable
31 | local ipairs = ipairs
32 |
33 | if _VERSION == "Lua 5.1" then
34 | module("org.conman.net.tcp")
35 | else
36 | _ENV = {}
37 | end
38 |
39 | -- *******************************************************************
40 |
41 | local function make_ios(conn,remote)
42 | local state = ios()
43 |
44 | state.close = function(self)
45 | self:flush()
46 | self.__socket:close()
47 | return true
48 | end
49 |
50 | state._refill = function(self)
51 | local _,data,err = self.__socket:recv()
52 | if data then
53 | if #data > 0 then
54 | return data
55 | else
56 | return nil
57 | end
58 | else
59 | return nil,errno[err],err
60 | end
61 | end
62 |
63 | state._drain = function(self,buffer)
64 | local bytes,err = self.__socket:send(nil,buffer)
65 | if bytes >= 0 then
66 | return true
67 | else
68 | return false,errno[err],err
69 | end
70 | end
71 |
72 | state.__remote = remote
73 | state.__socket = conn
74 |
75 | if _VERSION >= "Lua 5.2" then
76 | local mt = {}
77 | mt.__gc = state.close
78 | if _VERSION >= "Lua 5.4" then
79 | mt.__close = state.close
80 | end
81 | setmetatable(state,mt)
82 | end
83 |
84 | return state
85 | end
86 |
87 | -- *******************************************************************
88 | -- Usage: ios = tcp.accept(sock)
89 | -- Desc: Return a TCP connection
90 | -- Input: sock (userdata/socket) a listening socket
91 | -- Return: ios (table) an Input/Output object (nil on error)
92 | -- *******************************************************************
93 |
94 | function accept(sock)
95 | local conn,remote = sock:accept()
96 | if conn then
97 | sock.nodelay = true
98 | return make_ios(conn,remote)
99 | end
100 | end
101 |
102 | -- *******************************************************************
103 | -- Usage: sock,errmsg = tcp.listena(addr)
104 | -- Desc: Create a listening socket
105 | -- Input: addr (userdata/address) IP address and port
106 | -- Return: sock (userdata/socket) listening socket
107 | -- errmsg (string) error message
108 | -- *******************************************************************
109 |
110 | function listena(addr)
111 | local sock,err = net.socket(addr.family,'tcp')
112 | if not sock then
113 | return false,errno[err]
114 | end
115 |
116 | sock.reuseaddr = true
117 | sock:bind()
118 | sock:listen()
119 |
120 | return sock
121 | end
122 |
123 | -- *******************************************************************
124 | -- Usage: ios = tcp.listen(host,port)
125 | -- Desc: Create a listening socket
126 | -- Input: host (string) hostname of interface to listen on
127 | -- port (string number) port number
128 | -- Return: ios (table) Input/Output object (nil on error)
129 | -- *******************************************************************
130 |
131 | function listen(host,port)
132 | return listena(net.address2(host,'any','tcp',port)[1])
133 | end
134 |
135 | -- *******************************************************************
136 | -- Usage: ios = tcp.connecta(addr)
137 | -- Desc: Connect to a remote host
138 | -- Input: addr (userdata/address) IP address and port
139 | -- Return: ios (table) Input/Output object (nil on error)
140 | -- *******************************************************************
141 |
142 | function connecta(addr)
143 | if not addr then return end
144 |
145 | local sock,err = net.socket(addr.family,'tcp')
146 |
147 | if not sock then
148 | syslog('error',"socket(TCP) = %s",errno[err])
149 | return
150 | end
151 |
152 | local err1 = sock:connect(addr)
153 |
154 | if err1 ~= 0 then
155 | return
156 | end
157 |
158 | return make_ios(sock,addr)
159 | end
160 |
161 | -- *******************************************************************
162 | -- Usage: ios = tcp.connect(host,port)
163 | -- Desc: Connect to a remote host
164 | -- Input: host (string) hostname
165 | -- port (string number) port to connect to
166 | -- Return: ios (table) Input/Output object (nil on error)
167 | -- *******************************************************************
168 |
169 | function connect(host,port)
170 | local addr = net.address2(host,'any','tcp',port)
171 | if addr then
172 | for _,a in ipairs(addr) do
173 | local conn = connecta(a)
174 | if conn then
175 | return conn
176 | end
177 | end
178 | end
179 | end
180 |
181 | -- *******************************************************************
182 |
183 | if _VERSION >= "Lua 5.2" then
184 | return _ENV
185 | end
186 |
--------------------------------------------------------------------------------
/lua/net/tls.lua:
--------------------------------------------------------------------------------
1 | -- *******************************************************************
2 | --
3 | -- Copyright 2019 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- *******************************************************************
21 | -- luacheck: globals accept listens listena listen connecta connect
22 | -- luacheck: ignore 611
23 |
24 | local syslog = require "org.conman.syslog"
25 | local errno = require "org.conman.errno"
26 | local net = require "org.conman.net"
27 | local tls = require "org.conman.tls"
28 | local ios = require "org.conman.net.ios"
29 |
30 | local _VERSION = _VERSION
31 | local setmetatable = setmetatable
32 | local ipairs = ipairs
33 |
34 | if _VERSION == "Lua 5.1" then
35 | module(...)
36 | else
37 | _ENV = {} -- luacheck: ignore
38 | end
39 |
40 | -- *******************************************************************
41 |
42 | local function make_ios(ctx,conn)
43 | local state = ios()
44 | state.__ctx = ctx
45 | state.__socket = conn
46 |
47 | function state:close() -- luacheck: ignore
48 | local advice = self.__ctx:close()
49 | if advice == tls.WANT_INPUT or advice == tls.WANT_OUTPUT then
50 | return self:close()
51 | else
52 | local err = self.__socket:close()
53 | return err == 0,errno[err],err
54 | end
55 | end
56 |
57 | function state:_handshake() -- luacheck: ignore
58 | local advise = self.__ctx:handshake()
59 | if advise == tls.WANT_INPUT or advise == tls.WANT_OUTPUT then
60 | return self:_handshake()
61 | elseif advise == -1 then
62 | local msg = self.__ctx:error() or "error"
63 | syslog('error',"tls:_handshake() = %s",msg)
64 | return false,msg,-1
65 | else
66 | return true
67 | end
68 | end
69 |
70 | function state:_refill() -- luacheck: ignore
71 | local data,size = self.__ctx:read(tls.BUFFERSIZE)
72 | if size == tls.WANT_INPUT or size == tls.WANT_OUTPUT then
73 | return self:_refill()
74 | elseif size == -1 then
75 | local msg = self.__ctx:error() or "error"
76 | syslog('error',"tls:_refill() = %s",msg)
77 | return nil,msg,-1
78 | else
79 | if #data > 0 then
80 | return data
81 | else
82 | return nil
83 | end
84 | end
85 | end
86 |
87 | function state:_drain(data) -- luacheck: ignore
88 | local size = self.__ctx:write(data)
89 | if size == tls.WANT_INPUT or size == tls.WANT_OUTPUT then
90 | return self:_drain(data)
91 | elseif size == -1 then
92 | local msg = self.__ctx:error()
93 | syslog('error',"tls:_drain() = %s",msg)
94 | return false,msg,-1
95 | else
96 | return true
97 | end
98 | end
99 |
100 | if _VERSION >= "Lua 5.2" then
101 | local mt = {}
102 | mt.__gc = state.close
103 | if _VERSION >= "Lua 5.4" then
104 | mt.__close = state.close
105 | end
106 | setmetatable(state,mt)
107 | end
108 |
109 | state:setvbuf('no')
110 | return state
111 | end
112 |
113 | -- *******************************************************************
114 | -- Usage: ios = accept(sock)
115 | -- Desc: Return a TCP connection
116 | -- Input: sock (userdata/socket) a listening socket
117 | -- Return: ios (table) an Input/Output object (nil on error)
118 | -- *******************************************************************
119 |
120 | function accept(sock)
121 | local conn,remote = sock:accept()
122 | if conn then
123 | sock.nodelay = true
124 | return make_ios(conn,remote)
125 | end
126 | end
127 |
128 | -- *******************************************************************
129 | -- Usage: sock,errmsg = listens(sock,conf)
130 | -- Desc: Initialize a listening TCP socket
131 | -- Input: sock (userdata/socket) bound socket
132 | -- conf (function) function for TLS configuration
133 | -- Return: sock (userdata) socket used for listening, false on error
134 | -- errmsg (string) error message
135 | -- *******************************************************************
136 |
137 | function listens(sock,conf)
138 | local config = tls.config()
139 | local server = tls.server()
140 |
141 | if not conf(config) then return false,config:error() end
142 | if not server:configuration(config) then
143 | return false,server:error()
144 | end
145 |
146 | -- XXX finish ...
147 |
148 | return sock
149 | end
150 |
151 | -- *******************************************************************
152 | -- Usage: sock,errmsg = listena(addr,conf)
153 | -- Desc: Initialize a listening TCP socket
154 | -- Input: addr (userdata/address) IP address
155 | -- conf (function) function for TLS configuration
156 | -- Return: sock (userdata) socket used for listening, false on error
157 | -- errmsg (string) error message
158 | -- *******************************************************************
159 |
160 | function listena(addr,conf)
161 | local sock,err = net.socket(addr.family,'tcp')
162 | if not sock then
163 | return false,errno[err]
164 | end
165 |
166 | sock.reuseaddr = true
167 | sock:bind(addr)
168 | sock:listen()
169 | return listens(sock,conf)
170 | end
171 |
172 | -- *******************************************************************
173 | -- Usage: sock,errmsg = listen(host,port,conf)
174 | -- Desc: Initalize a listening TCP socket
175 | -- Input: host (string) address to bind to
176 | -- port (string integer) port
177 | -- conf (function) configuration options
178 | -- Return: sock (userdata) socket used for listening, false on error
179 | -- errmsg (string) error message
180 | -- *******************************************************************
181 |
182 | function listen(host,port,conf)
183 | return listena(net.address2(host,'ip','tcp',port)[1],conf)
184 | end
185 |
186 | -- *******************************************************************
187 | -- Usage: ios = connecta(addr,hostname[,conf])
188 | -- Desc: Connect to a remote address
189 | -- Input: addr (userdata/address) IP address
190 | -- hostname (string) hostname (required for TLS)
191 | -- conf (function) configuration options
192 | -- Return: ios (table) Input/Output object (nil on error)
193 | -- *******************************************************************
194 |
195 | function connecta(addr,hostname,conf)
196 | local sock,err = net.socket(addr.family,'tcp')
197 |
198 | if not sock then
199 | return false,errno[err]
200 | end
201 |
202 | err = sock:connect(addr)
203 |
204 | if err ~= 0 then
205 | sock:close()
206 | return false,errno[err]
207 | end
208 |
209 | local config = tls.config()
210 | local ctx = tls.client()
211 |
212 | if conf then
213 | if not conf(config) then return false,config:error() end
214 | else
215 | config:protocols("all")
216 | end
217 |
218 | ctx:configure(config)
219 |
220 | if not ctx:connect_socket(sock:_tofd(),hostname) then
221 | sock:close()
222 | return false,ctx:error() or "failed to connect"
223 | end
224 |
225 | return make_ios(ctx,sock)
226 | end
227 |
228 | -- *******************************************************************
229 | -- Usage: ios = connect(host,port[,conf])
230 | -- Desc: Connect to a remote host
231 | -- Input: host (string) IP address
232 | -- port (string number) port to connect to
233 | -- conf (function) configuration options
234 | -- Return: ios (table) Input/Output object (nil on error)
235 | -- *******************************************************************
236 |
237 | function connect(host,port,conf)
238 | local addr,err = net.address2(host,'any','tcp',port)
239 | if addr then
240 | for _,a in ipairs(addr) do
241 | local conn = connecta(a,host,conf)
242 | if conn then
243 | return conn
244 | end
245 | end
246 | else
247 | return nil,net.errno[err]
248 | end
249 | end
250 |
251 | -- *******************************************************************
252 |
253 | if _VERSION >= "Lua 5.2" then
254 | return _ENV -- luacheck: ignore
255 | end
256 |
--------------------------------------------------------------------------------
/lua/nfl.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2018 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals SOCKETS schedule spawn timeout info dump_info
22 | -- luacheck: globals client_eventloop server_eventloop
23 | -- luacheck: ignore 611
24 |
25 | local pollset = require "org.conman.pollset"
26 | local syslog = require "org.conman.syslog"
27 | local signal = require "org.conman.signal"
28 | local clock = require "org.conman.clock"
29 | local errno = require "org.conman.errno"
30 | local coroutine = require "coroutine"
31 | local table = require "table"
32 | local debug = require "debug"
33 | local math = require "math"
34 |
35 | local _VERSION = _VERSION
36 | local print = print
37 | local assert = assert
38 | local pairs = pairs
39 | local unpack = table.unpack or unpack
40 | local tostring = tostring
41 | local setmetatable = setmetatable
42 |
43 | if _VERSION == "Lua 5.1" then
44 | module(...)
45 | else
46 | _ENV = {} -- luacheck: ignore
47 | end
48 |
49 | -- **********************************************************************
50 |
51 | local REFQUEUE = { _n = 0 } -- list of all coroutines (for strong reference)
52 | local TOQUEUE = setmetatable({},{ __mode = "k" }) -- TimeOut queue
53 | local RUNQUEUE = {} -- run queue
54 | SOCKETS = pollset() -- event generators
55 |
56 | signal.ignore('pipe')
57 |
58 | -- **********************************************************************
59 | -- TOQUEUE:insert() and TOQUEUE:remove() are based, more or less directly,
60 | -- up http://en.wikipedia.org/wiki/Binary_heap
61 | -- ----------------------------------------------------------------------
62 |
63 | function TOQUEUE:insert(when,co,...)
64 | local function bubble_up(parent,child)
65 | if parent > 0 then
66 | if self[parent].awake > self[child].awake then
67 | self[parent] , self[child] = self[child] , self[parent]
68 | return bubble_up(math.floor(parent / 2),parent)
69 | end
70 | end
71 | end
72 |
73 | local idx = #self + 1
74 | local parent = math.floor(idx / 2)
75 | local info =
76 | {
77 | awake = clock.get('monotonic') + when,
78 | trigger = true,
79 | co = co,
80 | ...
81 | }
82 |
83 | self[idx] = info
84 | self[co] = info
85 | bubble_up(parent,idx)
86 | end
87 |
88 | -- **********************************************************************
89 |
90 | function TOQUEUE:remove()
91 | local function bubble_down(parent,left,right)
92 | local smallest = parent
93 |
94 | if left <= #self and self[left].awake < self[smallest].awake then
95 | smallest = left
96 | end
97 |
98 | if right <= #self and self[right].awake < self[smallest].awake then
99 | smallest = right
100 | end
101 |
102 | if smallest ~= parent then
103 | self[parent] , self[smallest] = self[smallest] , self[parent]
104 | return bubble_down(smallest,smallest * 2,smallest * 2 + 1)
105 | end
106 | end
107 |
108 | local res = self[1]
109 | local x = table.remove(self)
110 | self[res.co] = nil
111 |
112 | if #self > 0 then
113 | self[1] = x
114 | bubble_down(1,2,3)
115 | end
116 |
117 | return res
118 | end
119 |
120 | -- **********************************************************************
121 |
122 | function schedule(co , ... )
123 | if not RUNQUEUE[co] then
124 | RUNQUEUE[#RUNQUEUE + 1] = { co , ... }
125 | RUNQUEUE[co] = true
126 | end
127 | end
128 |
129 | -- **********************************************************************
130 |
131 | function spawn(f, ...)
132 | local co = coroutine.create(f)
133 |
134 | if co then
135 | REFQUEUE[co] = true
136 | REFQUEUE._n = REFQUEUE._n + 1
137 | schedule(co,...)
138 | end
139 |
140 | return co
141 | end
142 |
143 | -- **********************************************************************
144 |
145 | function timeout(when,...)
146 | local co = coroutine.running()
147 |
148 | if when == 0 then
149 | if TOQUEUE[co] then
150 | assert(TOQUEUE[co].co == co)
151 | TOQUEUE[co].trigger = false
152 | end
153 | else
154 | TOQUEUE:insert(when,co,...)
155 | end
156 | end
157 |
158 | -- **********************************************************************
159 |
160 | local function eventloop(done_f)
161 | if done_f() then return end
162 |
163 | local timeout = -1
164 | local now = clock.get('monotonic')
165 |
166 | while #TOQUEUE > 0 do
167 | local co = TOQUEUE[1]
168 |
169 | if co.trigger then
170 | timeout = co.awake - now
171 | if timeout > 0 then
172 | break
173 | end
174 |
175 | if coroutine.status(co.co) ~= 'dead' then
176 | schedule(co.co,unpack(co))
177 | end
178 | end
179 |
180 | TOQUEUE:remove()
181 | end
182 |
183 | if #RUNQUEUE > 0 then
184 | timeout = 0
185 | end
186 |
187 | local okay,err = SOCKETS:wait(timeout)
188 | if not okay then
189 | syslog('error',"SOCKETS:events() = %s",errno[err])
190 | return eventloop(done_f)
191 | end
192 |
193 | for event in SOCKETS:events() do
194 | event.obj(event)
195 | end
196 |
197 | while #RUNQUEUE > 0 do
198 | local co = table.remove(RUNQUEUE,1)
199 | RUNQUEUE[co[1]] = nil
200 |
201 | local status = coroutine.status(co[1])
202 |
203 | if status == 'dead' then
204 | syslog('warning',"A dead coroutine was scheduled to run")
205 |
206 | elseif status == 'suspended' then
207 | local ret = { coroutine.resume(unpack(co)) }
208 |
209 | if not ret[1] then
210 | syslog('error',"CRASH: coroutine %s dead: %s",tostring(co[1]),ret[2])
211 | local msg = debug.traceback(co[1])
212 | for entry in msg:gmatch("[^%\n]+") do
213 | syslog('error',"CRASH: %s: %s",tostring(co[1]),entry)
214 | end
215 | end
216 |
217 | if coroutine.status(co[1]) == 'dead' then
218 | assert(REFQUEUE._n > 0)
219 | REFQUEUE[co[1]] = nil
220 | REFQUEUE._n = REFQUEUE._n - 1
221 | end
222 |
223 | else
224 | -- =====================================================================
225 | -- There are two states not accounted for---'normal' and 'running'.
226 | -- Neither of these should happen.
227 | --
228 | -- 'running'
229 | -- Shouldn't happen because then it means we are trying to
230 | -- resume the coroutine that is currently running (namely, this
231 | -- coroutine), which not only doesn't make sense, but I can't
232 | -- see how this could happen.
233 | --
234 | -- 'normal'
235 | -- We're doing this check from a coroutine that isn't running
236 | -- and the coroutine we're checking is running, and I can't see
237 | -- how that can happen (and doesn't make much sense either).
238 | --
239 | -- So this path is one of those "This should never happen" paths,
240 | -- which should never happen. And if it does, just remove the
241 | -- reference to the coroutine, and log what happened.
242 | -- =====================================================================
243 |
244 | syslog('critical',"unexpected coroutine state %q",status)
245 | assert(REFQUEUE._n > 0)
246 | REFQUEUE[co[1]] = nil
247 | REFQUEUE._n = REFQUEUE._n - 1
248 | end
249 | end
250 |
251 | return eventloop(done_f)
252 | end
253 |
254 | -- **********************************************************************
255 |
256 | function client_eventloop(done_f)
257 | done_f = done_f or function() return false end
258 | return eventloop(function() return REFQUEUE._n == 0 or done_f() end)
259 | end
260 |
261 | -- **********************************************************************
262 |
263 | function server_eventloop(done_f)
264 | done_f = done_f or function() return false end
265 | return eventloop(done_f)
266 | end
267 |
268 | -- **********************************************************************
269 |
270 | function info()
271 | return REFQUEUE._n,#RUNQUEUE,#TOQUEUE,#SOCKETS
272 | end
273 |
274 | -- **********************************************************************
275 |
276 | function dump_info()
277 | print("SOCKETS:",#SOCKETS)
278 | for name,val in pairs(REFQUEUE) do print("REF",name,val) end
279 | for name,val in pairs(TOQUEUE) do print("TO", name,val) end
280 | for name,val in pairs(RUNQUEUE) do print("RUN",name,val) end
281 | end
282 |
283 | -- **********************************************************************
284 |
285 | if _VERSION >= "Lua 5.2" then
286 | return _ENV -- luacheck: ignore
287 | end
288 |
--------------------------------------------------------------------------------
/lua/nfl/tcp.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2018 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals listens listena listen connecta connect
22 | -- luacheck: ignore 611
23 |
24 | local syslog = require "org.conman.syslog"
25 | local errno = require "org.conman.errno"
26 | local net = require "org.conman.net"
27 | local mkios = require "org.conman.net.ios"
28 | local nfl = require "org.conman.nfl"
29 | local coroutine = require "coroutine"
30 |
31 | local _VERSION = _VERSION
32 | local tostring = tostring
33 | local setmetatable = setmetatable
34 | local assert = assert
35 | local ipairs = ipairs
36 |
37 | if _VERSION == "Lua 5.1" then
38 | module(...)
39 | else
40 | _ENV = {} -- luacheck: ignore
41 | end
42 |
43 | -- **********************************************************************
44 | -- usage: ios,handler = create_handler(conn,remote)
45 | -- desc: Create the event handler for handing network packets
46 | -- input: conn (userdata/socket) connected socket
47 | -- remote (userdata/address) remote connection
48 | -- return: ios (table) I/O object (similar to what io.open() returns)
49 | -- handler (function) event handler
50 | -- **********************************************************************
51 |
52 | local function create_handler(conn,remote)
53 | local ios = mkios()
54 | ios.__socket = conn
55 | ios.__remote = remote
56 | ios.__output = ""
57 | ios.__rbytes = 0
58 | ios.__wbytes = 0
59 |
60 | ios._refill = function()
61 | return coroutine.yield()
62 | end
63 |
64 | ios._drain = function(self,data)
65 | local bytes,err = self.__socket:send(nil,data)
66 | if err ~= 0 then
67 | syslog('error',"socket:send() = %s",errno[err])
68 | return false,errno[err],err
69 | end
70 |
71 | ios.__wbytes = self.__wbytes + bytes;
72 | if bytes < #data then
73 | nfl.SOCKETS:update(self.__socket,'w')
74 | coroutine.yield()
75 | data = data:sub(bytes + 1,-1)
76 | return self:_drain(data)
77 | end
78 | return true
79 | end
80 |
81 | ios.close = function(self)
82 | -- -----------------------------------------------------------------
83 | -- XXX - this call to assert() seems to remove a bunch of calls to
84 | -- epoll_ctl() that error out under Linux. Okay.
85 | -- -----------------------------------------------------------------
86 | assert(self.__socket:_tofd() >= 0)
87 | self:flush()
88 | nfl.SOCKETS:remove(self.__socket)
89 | local err = self.__socket:close()
90 | return err == 0,errno[err],err
91 | end
92 |
93 | if _VERSION >= "Lua 5.2" then
94 | local mt = {}
95 | mt.__gc = ios.close
96 | if _VERSION >= "Lua 5.4" then
97 | mt.__close = ios.close
98 | end
99 | setmetatable(ios,mt)
100 | end
101 |
102 | return ios,function(event)
103 | assert(not (event.read and event.write))
104 |
105 | if event.hangup then
106 | ios._eof = true
107 | nfl.schedule(ios.__co,"")
108 | return
109 | end
110 |
111 | if event.read then
112 | local _,packet,err = ios.__socket:recv()
113 | if packet then
114 | ios._eof = #packet == 0
115 | nfl.schedule(ios.__co,packet)
116 | else
117 | if err ~= errno.EAGAIN then
118 | syslog('error',"socket:recv() = %s",errno[err])
119 | nfl.schedule(ios.__co,false,errno[err],err)
120 | end
121 | end
122 | end
123 |
124 | if event.write then
125 | nfl.SOCKETS:update(ios.__socket,'r')
126 | nfl.schedule(ios.__co,true)
127 | end
128 | end
129 | end
130 |
131 | -- **********************************************************************
132 | -- Usage: sock,errmsg = listens(sock,mainf)
133 | -- Desc: Initialize a listening TCP socket
134 | -- Input: sock (userdata/socket) bound socket
135 | -- mainf (function) main handler for service
136 | -- Return: sock (userdata) socket used for listening, false on error
137 | -- errmsg (string) error message
138 | -- **********************************************************************
139 |
140 | function listens(sock,mainf)
141 | nfl.SOCKETS:insert(sock,'r',function()
142 | local conn,remote,err = sock:accept()
143 |
144 | if not conn then
145 | syslog('error',"sock:accept() = %s",errno[err])
146 | return
147 | end
148 |
149 | conn.nonblock = true
150 | conn.nodelay = true
151 | local ios,packet_handler = create_handler(conn,remote)
152 | ios.__co = nfl.spawn(mainf,ios)
153 | nfl.SOCKETS:insert(conn,'r',packet_handler)
154 | end)
155 |
156 | return sock
157 | end
158 |
159 | -- **********************************************************************
160 | -- Usage: sock,errmsg = listena(addr,mainf)
161 | -- Desc: Initalize a listening TCP socket
162 | -- Input: addr (userdata/address) IP address
163 | -- mainf (function) main handler for service
164 | -- Return: sock (userdata) socket used for listening, false on error
165 | -- errmsg (string) error message
166 | -- **********************************************************************
167 |
168 | function listena(addr,mainf)
169 | local sock,err = net.socket(addr.family,'tcp')
170 |
171 | if not sock then
172 | return false,errno[err]
173 | end
174 |
175 | sock.reuseaddr = true
176 | sock.nonblock = true
177 | sock:bind(addr)
178 | sock:listen()
179 | return listens(sock,mainf)
180 | end
181 |
182 | -- **********************************************************************
183 | -- Usage: listen(host,port,mainf)
184 | -- Desc: Initalize a listening TCP socket
185 | -- Input: host (string) address to bind to
186 | -- port (string integer) port
187 | -- mainf (function) main handler for service
188 | -- **********************************************************************
189 |
190 | function listen(host,port,mainf)
191 | return listena(net.address2(host,'any','tcp',port)[1],mainf)
192 | end
193 |
194 | -- **********************************************************************
195 | -- Usage: ios = tcp.connecta(addr[,to])
196 | -- Desc: Connect to a remote address
197 | -- Input: addr (userdata/address) IP address
198 | -- to (number/optinal) timout the operation after to seconds
199 | -- Return: ios (table) Input/Output object (nil on error)
200 | -- **********************************************************************
201 |
202 | function connecta(addr,to)
203 | if not addr then return nil end
204 |
205 | local sock,err = net.socket(addr.family,'tcp')
206 |
207 | if not sock then
208 | syslog('error',"socket(TCP) = %s",errno[err])
209 | return
210 | end
211 |
212 | sock.nonblock = true
213 | local ios,packet_handler = create_handler(sock,addr)
214 | ios.__co = coroutine.running()
215 |
216 | -- ------------------------------------------------------------
217 | -- In POSIXland, a non-blocking socket doing a connect become available
218 | -- when it's ready for writing. So we install a 'write' trigger, then
219 | -- call connect() and yield. When we return, it's connected (unless we're
220 | -- optionally timing out the operation).
221 | -- ------------------------------------------------------------
222 |
223 | nfl.SOCKETS:insert(sock,'w',packet_handler)
224 | if to then nfl.timeout(to,false,errno[errno.ETIMEDOUT]) end
225 | sock:connect(addr)
226 | local okay,err1 = coroutine.yield()
227 | if to then nfl.timeout(0) end
228 |
229 | if not okay then
230 | nfl.SOCKETS:remove(sock)
231 | sock:close()
232 | syslog('error',"sock:connect(%s) = %s",tostring(addr),err1)
233 | return nil
234 | end
235 |
236 | if ios._eof then
237 | ios:close()
238 | return nil
239 | else
240 | return ios
241 | end
242 | end
243 |
244 | -- **********************************************************************
245 | -- Usage: ios = tcp.connect(host,port[,to])
246 | -- Desc: Connect to a remote host
247 | -- Input: host (string) IP address
248 | -- port (string number) port to connect to
249 | -- to (number/optioal) timeout the operation after to seconds
250 | -- Return: ios (table) Input/Output object (nil on error)
251 | -- **********************************************************************
252 |
253 | function connect(host,port,to)
254 | local addr = net.address2(host,'any','tcp',port)
255 | if addr then
256 | for _,a in ipairs(addr) do
257 | local conn = connecta(a,to)
258 | if conn then
259 | return conn
260 | end
261 | end
262 | end
263 | end
264 |
265 | -- **********************************************************************
266 |
267 | if _VERSION >= "Lua 5.2" then
268 | return _ENV -- luacheck: ignore
269 | end
270 |
--------------------------------------------------------------------------------
/lua/string.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2010 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals wrapt metaphone compare comparen mksplit split
22 | -- luacheck: globals template filetemplate wrap safeascii safeutf8
23 | -- luacheck: globals comparei
24 | -- luacheck: ignore 611
25 |
26 | local strcore = require "org.conman.strcore"
27 | local lpeg = require "lpeg"
28 | local string = require "string"
29 | local table = require "table"
30 | local io = require "io"
31 |
32 | local _VERSION = _VERSION
33 | local type = type
34 | local tostring = tostring
35 |
36 | if _VERSION == "Lua 5.1" then
37 | module("org.conman.string")
38 | else
39 | _ENV = {}
40 | end
41 |
42 | metaphone = strcore.metaphone
43 | compare = strcore.compare
44 | comparen = strcore.comparen
45 | comparei = strcore.comparei
46 | wrapt = strcore.wrapt
47 | safeascii = strcore.safeascii
48 | safeutf8 = strcore.safeutf8
49 |
50 | -- ********************************************************************
51 |
52 | function mksplit(delim)
53 | delim = lpeg.P(delim or ':')
54 | local char = lpeg.C((lpeg.P(1) - delim)^0)
55 |
56 | return lpeg.Ct(char * (delim * char)^0)
57 | end
58 |
59 | -- ********************************************************************
60 |
61 | function split(s,delim)
62 | local sp = mksplit(delim)
63 | return sp:match(s)
64 | end
65 |
66 | -- ********************************************************************
67 |
68 | function template(temp,callbacks,data)
69 | local function cmd(tag)
70 | local word = string.sub(tag,3,-3)
71 |
72 | if type(callbacks[word]) == 'string' then
73 | return callbacks[word]
74 | elseif type(callbacks[word]) == 'function' then
75 | return callbacks[word](data)
76 | else
77 | return tostring(callbacks[word])
78 | end
79 | end
80 |
81 | local s = string.gsub(temp,"%%{[%w%.]+}%%",cmd)
82 | return s
83 | end
84 |
85 | -- ********************************************************************
86 |
87 | function filetemplate(temp,callbacks,data)
88 | local f = io.open(temp,"r")
89 | local d = f:read("*a")
90 | f:close()
91 | return template(d,callbacks,data)
92 | end
93 |
94 | -- ********************************************************************
95 |
96 | function wrap(s,margin,lead)
97 | lead = lead or ""
98 | local res = wrapt(s,margin)
99 |
100 | -- -----------------------------------------------------------------------
101 | -- insert lead into the first position. We then convert the table into a
102 | -- string, separated by a newline and the lead. This conforms to the
103 | -- behavior of the C based version of this function.
104 | -- -----------------------------------------------------------------------
105 |
106 | table.insert(res,1,lead)
107 | return table.concat(res,"\n" .. lead)
108 | end
109 |
110 | -- ********************************************************************
111 |
112 | if _VERSION >= "Lua 5.2" then
113 | return _ENV
114 | end
115 |
--------------------------------------------------------------------------------
/lua/table.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2010 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals safestring dump_value dump keepset
22 | -- luacheck: ignore 611
23 |
24 | local _VERSION = _VERSION
25 | local math = require "math"
26 | local string = require "string"
27 | local io = require "io"
28 | local ipairs = ipairs
29 | local pairs = pairs
30 | local tostring = tostring
31 | local type = type
32 | local pcall = pcall
33 | local getmetatable = getmetatable
34 |
35 | if _VERSION == "Lua 5.1" then
36 | module("org.conman.table")
37 | else
38 | _ENV = {}
39 | end
40 |
41 | -- *******************************************************************
42 |
43 | local char_trans =
44 | {
45 | ['\a'] = '\\a',
46 | ['\b'] = '\\b',
47 | ['\t'] = '\\t',
48 | ['\n'] = '\\n',
49 | ['\v'] = '\\v',
50 | ['\f'] = '\\f',
51 | ['\r'] = '\\r',
52 | ['"'] = '\\"',
53 | ['\\'] = '\\\\',
54 | }
55 |
56 | function safestring(v)
57 | if type(v) == 'string' then
58 | return '"' .. v:gsub(".",function(c)
59 | if char_trans[c] then
60 | return char_trans[c]
61 | end
62 |
63 | local b = c:byte()
64 |
65 | if b < 32 or b > 126 then
66 | return string.format("\\%03d",b)
67 | else
68 | return c
69 | end
70 | end) .. '"'
71 | else
72 | return tostring(v)
73 | end
74 | end
75 |
76 | -- *************************************************************
77 |
78 | function dump_value(name,value,path,level,marked)
79 | path = path or ""
80 | level = level or 0
81 | marked = marked or {}
82 | local lead = string.rep(" ",level)
83 |
84 | if type(name) == "nil" then
85 | return ""
86 | elseif type(name) == "number" then
87 | if _VERSION >= "Lua 5.3" then
88 | if math.type(name) == 'integer' then
89 | name = string.format("[%d]",name)
90 | else
91 | name = string.format("[%f]",name)
92 | end
93 | else
94 | name = string.format("[%f]",name)
95 | end
96 | elseif type(name) == 'string' then
97 | if not name:match "^[A-Za-z_][A-Za-z0-9_]*$" then
98 | name = "[" .. safestring(name) .. "]"
99 | end
100 | else
101 | name = "[" .. safestring(name) .. "]"
102 | end
103 |
104 | if type(value) == "nil" then
105 | return ""
106 | elseif type(value) == "boolean" then
107 | return string.format("%s%s = %s,\n",lead,name,tostring(value))
108 | elseif type(value) == "number" then
109 | return string.format("%s%s = %f,\n",lead,name,value)
110 | elseif type(value) == "string" then
111 | value = safestring(value)
112 | return string.format("%s%s = %s,\n",lead,name,value)
113 | elseif type(value) == "table" then
114 |
115 | if marked[tostring(value)] ~= nil then
116 | return string.format("%s%s = %s,\n",lead,name,marked[tostring(value)])
117 | else
118 | if path == "" then
119 | marked[tostring(value)] = name
120 | else
121 | marked[tostring(value)] = path .. "." .. name
122 | end
123 | end
124 |
125 | local s = string.format("%s%s =\n%s{\n",lead,name,lead)
126 |
127 | for k,v in pairs(value) do
128 | s = s .. dump_value(k,v,marked[tostring(value)],level + 2,marked)
129 | end
130 |
131 | s = s .. string.format("%s}",lead)
132 | if level > 0 then s = s .. string.format(",") end
133 |
134 | if getmetatable(value) ~= nil then
135 | s = s .. string.format("--METATABLE\n",lead)
136 | else
137 | s = s .. string.format("\n",lead)
138 | end
139 | return s
140 |
141 | elseif type(value) == "function" then
142 | local err,func = pcall(string.dump,value)
143 | if err == false then
144 | return string.format("%s%s = C_FUNCTION\n",lead,name)
145 | else
146 | return string.format("%s%s = loadstring(%q),\n",lead,name,func)
147 | end
148 | elseif type(value) == "thread" then
149 | return string.format("%s%s = THREAD\n",lead,name)
150 | elseif type(value) == "userdata" then
151 | local mt = getmetatable(value)
152 |
153 | if mt and (mt.__pairs or mt.__ipairs) then
154 | local s = string.format("%s%s =\n%s{\n",lead,name,lead)
155 |
156 | if mt.__ipairs then
157 | for i,v in ipairs(value) do
158 | s = s .. dump_value(i,v,marked[tostring(value)],level + 2,marked)
159 | end
160 | end
161 |
162 | if mt.__pairs then
163 | for k,v in pairs(value) do
164 | s = s .. dump_value(k,v,marked[tostring(value)],level + 2,marked)
165 | end
166 | end
167 |
168 | return s .. string.format("%s} --USERDATA\n",lead)
169 | else
170 | return string.format("%s%s = %s\n",lead,name,tostring(value))
171 | end
172 | else
173 | error("unsupported data type!")
174 | end
175 | end
176 |
177 | -- **********************************************************
178 |
179 | function dump(name,value)
180 | io.stdout:write(dump_value(name,value),'\n')
181 | end
182 |
183 | -- ***********************************************************
184 |
185 | function keepset(t,name,value)
186 | if t[name] == nil then
187 | t[name] = value
188 | elseif type(t[name]) == 'table' then
189 | t[name][#t[name] + 1] = value
190 | else
191 | t[name] = { t[name] , value }
192 | end
193 |
194 | return t
195 | end
196 |
197 | -- ************************************************************
198 |
199 | if _VERSION >= "Lua 5.2" then
200 | return _ENV
201 | end
202 |
203 |
--------------------------------------------------------------------------------
/lua/unix.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2010 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- ********************************************************************
21 | -- luacheck: globals users groups paths
22 | -- luacheck: ignore 611
23 |
24 | local _VERSION = _VERSION
25 | local setmetatable = setmetatable
26 | local tonumber = tonumber
27 |
28 | local fsys = require "org.conman.fsys"
29 | local lpeg = require "lpeg"
30 | local io = require "io"
31 | local os = require "os"
32 |
33 | if _VERSION == "Lua 5.1" then
34 | module("org.conman.unix")
35 | else
36 | _ENV = {}
37 | end
38 |
39 | local text = lpeg.C((lpeg.R" ~" - lpeg.P":")^0)
40 | local number = lpeg.R"09"^1 / tonumber
41 |
42 | -- ************************************************************************
43 |
44 | users = {} do
45 | local entry = lpeg.Ct(
46 | lpeg.Cg(text, "userid") * lpeg.P":"
47 | * lpeg.Cg(text, "passwd") * lpeg.P":"
48 | * lpeg.Cg(number,"uid") * lpeg.P":"
49 | * lpeg.Cg(number,"gid") * lpeg.P":"
50 | * lpeg.Cg(text, "name") * lpeg.P":"
51 | * lpeg.Cg(text, "home") * lpeg.P":"
52 | * lpeg.Cg(text, "shell")
53 | )
54 |
55 | for line in io.lines("/etc/passwd") do
56 | local user = entry:match(line)
57 | if user then
58 | users[user.userid] = user
59 | users[user.uid] = user
60 | end
61 | end
62 | end
63 |
64 | -- *************************************************************************
65 |
66 | groups = {} do
67 | local name = lpeg.C((lpeg.R" ~" - lpeg.S":,")^1)
68 | local users = lpeg.Ct(name * (lpeg.P"," * name)^0)
69 | + lpeg.P(true) / function() return {} end
70 | local entry = lpeg.Ct(
71 | lpeg.Cg(text, "name") * lpeg.P":"
72 | * lpeg.Cg(text, "passwd") * lpeg.P":"
73 | * lpeg.Cg(number,"gid") * lpeg.P":"
74 | * lpeg.Cg(users, "users")
75 | )
76 |
77 | for line in io.lines("/etc/group") do
78 | local group = entry:match(line)
79 | if group then
80 | groups[group.name] = group
81 | groups[group.gid] = group
82 | end
83 | end
84 | end
85 |
86 | -- ************************************************************************
87 |
88 | paths = setmetatable({},{ __index = function(t,k)
89 | for path in os.getenv("PATH"):gmatch "[^:]+" do
90 | if fsys.access(path .. "/" .. k,"X") then
91 | t[k] = path .. '/' .. k
92 | return t[k]
93 | end
94 | end
95 | end})
96 |
97 | if _VERSION >= "Lua 5.2" then
98 | return _ENV
99 | end
100 |
--------------------------------------------------------------------------------
/lua/zip.lua:
--------------------------------------------------------------------------------
1 | -- ***************************************************************
2 | --
3 | -- Copyright 2014 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This library is free software; you can redistribute it and/or modify it
6 | -- under the terms of the GNU Lesser General Public License as published by
7 | -- the Free Software Foundation; either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This library is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | -- License for more details.
14 | --
15 | -- You should have received a copy of the GNU Lesser General Public License
16 | -- along with this library; if not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- --------------------------------------------------------------------
21 | --
22 | -- To effectively use this module, you should understand the ZIP file
23 | -- format. The definitive guide to this format is at
24 | --
25 | -- http://www.pkware.com/appnote
26 | --
27 | -- NOTE: https://bugzilla.mozilla.org/show_bug.cgi?id=1534483
28 | --
29 | -- ********************************************************************
30 | -- luacheck: globals magic idiv
31 | -- luacheck: ignore 611
32 |
33 | local _VERSION = _VERSION
34 | local pairs = pairs
35 | local setmetatable = setmetatable
36 |
37 | local table = require "table"
38 | local math = require "math"
39 |
40 | if _VERSION == "Lua 5.1" then
41 | module("org.conman.zip")
42 | else
43 | _ENV = {}
44 | end
45 |
46 | -- ************************************************************************
47 |
48 | magic =
49 | {
50 | EOCD = "PK\005\006",
51 | DIR = "PK\001\002",
52 | FILE = "PK\003\004",
53 | DATA = "PK\007\008",
54 | ARCHIVE = "PK\006\008",
55 | SIGNATURE = "PK\005\005",
56 | EOCD64 = "PK\006\006",
57 | EOCDL64 = "PK\006\007",
58 |
59 | }
60 |
61 | local function reverse_index(tab)
62 | local keys = {}
63 | for name in pairs(tab) do
64 | table.insert(keys,name)
65 | end
66 |
67 | for i = 1 , #keys do
68 | local k = keys[i]
69 | local v = tab[k]
70 | tab[v] = k
71 | end
72 |
73 | return setmetatable(tab,{
74 | __index = function(_,key)
75 | if type(key) == 'number' then
76 | return '-'
77 | elseif type(key) == 'string' then
78 | return 0
79 | end
80 | end
81 | })
82 | end
83 |
84 | os = reverse_index { -- luacheck: ignore
85 | ["MS-DOS"] = 0,
86 | ["Amiga"] = 1,
87 | ["OpenVMS"] = 2,
88 | ["UNIX"] = 3,
89 | ["VM/CMS"] = 4,
90 | ["Atari ST"] = 5,
91 | ["OS/2"] = 6,
92 | ["Macintosh"] = 7,
93 | ["Z-System"] = 8,
94 | ["CP/M"] = 9,
95 | ["Windows"] = 10,
96 | ["MVS"] = 11,
97 | ["VSE"] = 12,
98 | ["Acorn Risc"] = 13,
99 | ["VFAT"] = 14,
100 | ["alternative MVS"] = 15,
101 | ["BeOS"] = 16,
102 | ["Tandem"] = 17,
103 | ["OS/400"] = 18,
104 | ["Darwin"] = 19,
105 | }
106 |
107 | -- ************************************************************************
108 |
109 | function idiv(up,down)
110 | local q = math.floor(up/down)
111 | local r = up % down
112 | return q,r
113 | end
114 |
115 | -- ************************************************************************
116 |
117 | if _VERSION >= "Lua 5.2" then
118 | return _ENV
119 | end
120 |
121 |
--------------------------------------------------------------------------------
/other/pollset-epoll.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2013 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #ifndef __GNUC__
23 | # define __attribute__(x)
24 | #endif
25 |
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | #include
32 | #include
33 |
34 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM != 501
35 | # error This module is for Lua 5.1
36 | #endif
37 |
38 | #define TYPE_POLL "org.conman.pollset"
39 |
40 | /********************************************************************/
41 |
42 | typedef struct
43 | {
44 | int efh;
45 | int ref;
46 | size_t idx;
47 | } epollset__t;
48 |
49 | /**********************************************************************/
50 |
51 | static int epollset_toevents(lua_State *const L,int idx)
52 | {
53 | int events = 0;
54 |
55 | if (lua_istable(L,idx))
56 | {
57 | lua_getfield(L,idx,"read");
58 | events |= lua_isboolean(L,-1) ? EPOLLIN : 0;
59 | lua_getfield(L,idx,"write");
60 | events |= lua_isboolean(L,-1) ? EPOLLOUT : 0;
61 | lua_getfield(L,idx,"priority");
62 | events |= lua_isboolean(L,-1) ? EPOLLPRI : 0;
63 | lua_getfield(L,idx,"error");
64 | events |= lua_isboolean(L,-1) ? EPOLLERR : 0;
65 | lua_getfield(L,idx,"hangup");
66 | events |= lua_isboolean(L,-1) ? EPOLLHUP : 0;
67 | lua_getfield(L,idx,"trigger");
68 | events |= lua_isboolean(L,-1) ? EPOLLET : 0;
69 | lua_getfield(L,idx,"oneshot");
70 | events |= lua_isboolean(L,-1) ? EPOLLONESHOT : 0;
71 | lua_pop(L,7);
72 | }
73 | else if (lua_isstring(L,idx))
74 | {
75 | const char *flags = lua_tostring(L,idx);
76 | for ( ; *flags ; flags++)
77 | {
78 | switch(*flags)
79 | {
80 | case 'r': events |= EPOLLIN; break;
81 | case 'w': events |= EPOLLOUT; break;
82 | case 'p': events |= EPOLLPRI; break;
83 | case 'e': events |= EPOLLERR; break;
84 | case 'h': events |= EPOLLHUP; break;
85 | case 't': events |= EPOLLET; break;
86 | case '1': events |= EPOLLONESHOT; break;
87 | default: break;
88 | }
89 | }
90 | }
91 | else if (lua_isnil(L,idx))
92 | events |= EPOLLIN;
93 | else
94 | return luaL_error(L,"expected table or string");
95 |
96 | return events;
97 | }
98 |
99 | /**********************************************************************/
100 |
101 | static void epollset_pushevents(lua_State *const L,int events)
102 | {
103 | lua_createtable(L,0,8);
104 | lua_pushboolean(L,(events & EPOLLIN) != 0);
105 | lua_setfield(L,-2,"read");
106 | lua_pushboolean(L,(events & EPOLLOUT) != 0);
107 | lua_setfield(L,-2,"write");
108 | lua_pushboolean(L,(events & EPOLLPRI) != 0);
109 | lua_setfield(L,-2,"priority");
110 | lua_pushboolean(L,(events & EPOLLERR) != 0);
111 | lua_setfield(L,-2,"error");
112 | lua_pushboolean(L,(events & EPOLLHUP) != 0);
113 | lua_setfield(L,-2,"hangup");
114 | lua_pushboolean(L,(events & EPOLLET) != 0);
115 | lua_setfield(L,-2,"trigger");
116 | lua_pushboolean(L,(events & EPOLLONESHOT) != 0);
117 | lua_setfield(L,-2,"oneshot");
118 | }
119 |
120 | /**********************************************************************/
121 |
122 | static int epollset_lua(lua_State *const L)
123 | {
124 | epollset__t *set;
125 |
126 | set = lua_newuserdata(L,sizeof(epollset__t));
127 | set->idx = 0;
128 | set->efh = epoll_create(10);
129 |
130 | if (set->efh == -1)
131 | {
132 | lua_pushnil(L);
133 | lua_pushinteger(L,errno);
134 | return 2;
135 | }
136 |
137 | lua_createtable(L,0,0);
138 | set->ref = luaL_ref(L,LUA_REGISTRYINDEX);
139 |
140 | luaL_getmetatable(L,TYPE_POLL);
141 | lua_setmetatable(L,-2);
142 | return 1;
143 | }
144 |
145 | /**********************************************************************/
146 |
147 | static int epollmeta___tostring(lua_State *const L)
148 | {
149 | lua_pushfstring(L,"pollset (%p)",lua_touserdata(L,1));
150 | return 1;
151 | }
152 |
153 | /**********************************************************************/
154 |
155 | static int epollmeta___gc(lua_State *const L)
156 | {
157 | epollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
158 | luaL_unref(L,LUA_REGISTRYINDEX,set->ref);
159 | close(set->efh);
160 | return 0;
161 | }
162 |
163 | /**********************************************************************/
164 |
165 | static int epollmeta_insert(lua_State *const L)
166 | {
167 | epollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
168 | int fh = luaL_checkinteger(L,2);
169 | struct epoll_event event;
170 |
171 | lua_settop(L,4);
172 |
173 | event.events = epollset_toevents(L,3);
174 | event.data.fd = fh;
175 |
176 | if (epoll_ctl(set->efh,EPOLL_CTL_ADD,fh,&event) < 0)
177 | {
178 | lua_pushinteger(L,errno);
179 | return 1;
180 | }
181 |
182 | lua_pushinteger(L,set->ref);
183 | lua_gettable(L,LUA_REGISTRYINDEX);
184 | lua_pushinteger(L,fh);
185 |
186 | if (lua_isnil(L,4))
187 | lua_pushvalue(L,2);
188 | else
189 | lua_pushvalue(L,4);
190 |
191 | lua_settable(L,-3);
192 |
193 | set->idx++;
194 | lua_pushinteger(L,0);
195 | return 1;
196 | }
197 |
198 | /**********************************************************************/
199 |
200 | static int epollmeta_update(lua_State *const L)
201 | {
202 | epollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
203 | int fh = luaL_checkinteger(L,2);
204 | struct epoll_event event;
205 |
206 | lua_settop(L,3);
207 |
208 | event.events = epollset_toevents(L,3);
209 | event.data.fd = fh;
210 | errno = 0;
211 |
212 | epoll_ctl(set->efh,EPOLL_CTL_MOD,fh,&event);
213 | lua_pushinteger(L,errno);
214 | return 1;
215 | }
216 |
217 | /**********************************************************************/
218 |
219 | static int epollmeta_remove(lua_State *const L)
220 | {
221 | epollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
222 | int fh = luaL_checkinteger(L,2);
223 | struct epoll_event event;
224 |
225 | if (epoll_ctl(set->efh,EPOLL_CTL_DEL,fh,&event) < 0)
226 | {
227 | lua_pushinteger(L,errno);
228 | return 1;
229 | }
230 |
231 | lua_pushinteger(L,set->ref);
232 | lua_gettable(L,LUA_REGISTRYINDEX);
233 | lua_pushinteger(L,fh);
234 | lua_pushnil(L);
235 | lua_settable(L,-3);
236 |
237 | set->idx--;
238 | lua_pushinteger(L,0);
239 | return 1;
240 | }
241 |
242 | /**********************************************************************/
243 |
244 | static int epollmeta_events(lua_State *const L)
245 | {
246 | epollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
247 | lua_Number dtimeout = luaL_optnumber(L,2,-1.0);
248 | int timeout;
249 | int count;
250 | size_t idx;
251 | int i;
252 |
253 | if (dtimeout < 0)
254 | timeout = -1;
255 | else
256 | timeout = (int)(dtimeout * 1000.0);
257 |
258 | struct epoll_event events[set->idx];
259 |
260 | count = epoll_wait(set->efh,events,set->idx,timeout);
261 |
262 | if (count < 0)
263 | {
264 | lua_pushnil(L);
265 | lua_pushinteger(L,errno);
266 | return 2;
267 | }
268 |
269 | lua_pushinteger(L,set->ref);
270 | lua_gettable(L,LUA_REGISTRYINDEX);
271 |
272 | lua_createtable(L,set->idx,0);
273 | for (idx = 1 , i = 0 ; i < count ; i++)
274 | {
275 | lua_pushnumber(L,idx++);
276 | epollset_pushevents(L,events[i].events);
277 | lua_pushinteger(L,events[i].data.fd);
278 | lua_gettable(L,-5);
279 | lua_setfield(L,-2,"obj");
280 | lua_settable(L,-3);
281 | }
282 |
283 | lua_pushinteger(L,0);
284 | return 2;
285 | }
286 |
287 | /**********************************************************************/
288 |
289 | static int epollmeta__POLL(lua_State *const L)
290 | {
291 | lua_pushliteral(L,"epoll");
292 | return 1;
293 | }
294 |
295 | /**********************************************************************/
296 |
297 | static const luaL_Reg m_epollmeta[] =
298 | {
299 | { "__tostring" , epollmeta___tostring } ,
300 | { "__gc" , epollmeta___gc } ,
301 | { "insert" , epollmeta_insert } ,
302 | { "update" , epollmeta_update } ,
303 | { "remove" , epollmeta_remove } ,
304 | { "events" , epollmeta_events } ,
305 | { "POLL" , epollmeta__POLL } ,
306 | { NULL , NULL }
307 | };
308 |
309 | /**********************************************************************/
310 |
311 | int luaopen_epoll(lua_State *const L)
312 | {
313 | luaL_newmetatable(L,TYPE_POLL);
314 | luaL_register(L,NULL,m_epollmeta);
315 | lua_pushvalue(L,-1);
316 | lua_setfield(L,-1,"__index");
317 |
318 | lua_pushcfunction(L,epollset_lua);
319 | return 1;
320 | }
321 |
322 | /**********************************************************************/
323 |
--------------------------------------------------------------------------------
/other/pollset-poll.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2013 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #ifndef __GNUC__
23 | # define __attribute__(x)
24 | #endif
25 |
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | #include
32 | #include
33 |
34 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM != 501
35 | # error This module is for Lua 5.1
36 | #endif
37 |
38 | #define TYPE_POLL "org.conman.pollset"
39 |
40 | /********************************************************************/
41 |
42 | typedef struct
43 | {
44 | struct pollfd *set;
45 | size_t idx;
46 | size_t max;
47 | int ref;
48 | } pollset__t;
49 |
50 | /**********************************************************************/
51 |
52 | static int pollset_toevents(lua_State *const L,int idx)
53 | {
54 | int events = 0;
55 |
56 | if (lua_istable(L,idx))
57 | {
58 | lua_getfield(L,idx,"read");
59 | events |= lua_isboolean(L,-1) ? POLLIN : 0;
60 | lua_getfield(L,idx,"write");
61 | events |= lua_isboolean(L,-1) ? POLLOUT : 0;
62 | lua_getfield(L,idx,"priority");
63 | events |= lua_isboolean(L,-1) ? POLLPRI : 0;
64 | lua_getfield(L,idx,"error");
65 | lua_pop(L,3);
66 | }
67 | else if (lua_isstring(L,idx))
68 | {
69 | const char *flags = lua_tostring(L,idx);
70 | for ( ; *flags ; flags++)
71 | {
72 | switch(*flags)
73 | {
74 | case 'r': events |= POLLIN; break;
75 | case 'w': events |= POLLOUT; break;
76 | case 'p': events |= POLLPRI; break;
77 | default: break;
78 | }
79 | }
80 | }
81 | else if (lua_isnil(L,idx))
82 | events |= POLLIN;
83 | else
84 | return luaL_error(L,"expected table or string");
85 |
86 | return events;
87 | }
88 |
89 | /**********************************************************************/
90 |
91 | static void pollset_pushevents(lua_State *const L,int events)
92 | {
93 | lua_createtable(L,0,7);
94 | lua_pushboolean(L,(events & POLLIN) != 0);
95 | lua_setfield(L,-2,"read");
96 | lua_pushboolean(L,(events & POLLOUT) != 0);
97 | lua_setfield(L,-2,"write");
98 | lua_pushboolean(L,(events & POLLPRI) != 0);
99 | lua_setfield(L,-2,"priority");
100 | lua_pushboolean(L,(events & POLLERR) != 0);
101 | lua_setfield(L,-2,"error");
102 | lua_pushboolean(L,(events & POLLHUP) != 0);
103 | lua_setfield(L,-2,"hangup");
104 | lua_pushboolean(L,(events & POLLNVAL) != 0);
105 | lua_setfield(L,-2,"invalid");
106 | }
107 |
108 | /**********************************************************************/
109 |
110 | static int pollset_lua(lua_State *const L)
111 | {
112 | pollset__t *set;
113 |
114 | set = lua_newuserdata(L,sizeof(pollset__t));
115 | set->set = NULL;
116 | set->idx = 0;
117 | set->max = 0;
118 |
119 | lua_createtable(L,0,0);
120 | set->ref = luaL_ref(L,LUA_REGISTRYINDEX);
121 |
122 | luaL_getmetatable(L,TYPE_POLL);
123 | lua_setmetatable(L,-2);
124 | return 1;
125 | }
126 |
127 | /**********************************************************************/
128 |
129 | static int pullmeta___tostring(lua_State *const L)
130 | {
131 | lua_pushfstring(L,"pollset (%p)",lua_touserdata(L,1));
132 | return 1;
133 | }
134 |
135 | /**********************************************************************/
136 |
137 | static int pullmeta___gc(lua_State *const L)
138 | {
139 | lua_Alloc allocf;
140 | void *ud;
141 |
142 | pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
143 | luaL_unref(L,LUA_REGISTRYINDEX,set->ref);
144 | allocf = lua_getallocf(L,&ud);
145 | (*allocf)(ud,set->set,set->max * sizeof(struct pollfd),0);
146 | return 0;
147 | }
148 |
149 | /**********************************************************************/
150 |
151 | static int pullmeta_insert(lua_State *const L)
152 | {
153 | pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
154 | int fh = luaL_checkinteger(L,2);
155 |
156 | lua_settop(L,4);
157 |
158 | if (set->idx == set->max)
159 | {
160 | struct pollfd *new;
161 | size_t newmax;
162 | lua_Alloc allocf;
163 | void *ud;
164 |
165 | allocf = lua_getallocf(L,&ud);
166 | newmax = set->max + 10;
167 | new = (*allocf)(
168 | ud,
169 | set->set,
170 | set->max * sizeof(struct pollfd),
171 | newmax * sizeof(struct pollfd)
172 | );
173 |
174 | if (new == NULL)
175 | {
176 | lua_pushinteger(L,ENOMEM);
177 | return 1;
178 | }
179 |
180 | set->set = new;
181 | set->max = newmax;
182 | }
183 |
184 | set->set[set->idx].events = pollset_toevents(L,3);
185 | set->set[set->idx].fd = fh;
186 |
187 | lua_pushinteger(L,set->ref);
188 | lua_gettable(L,LUA_REGISTRYINDEX);
189 | lua_pushinteger(L,fh);
190 |
191 | if (lua_isnil(L,4))
192 | lua_pushvalue(L,2);
193 | else
194 | lua_pushvalue(L,4);
195 |
196 | lua_settable(L,-3);
197 |
198 | set->idx++;
199 | lua_pushinteger(L,0);
200 | return 1;
201 | }
202 |
203 | /**********************************************************************/
204 |
205 | static int pullmeta_update(lua_State *const L)
206 | {
207 | pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
208 | int fh = luaL_checkinteger(L,2);
209 |
210 | lua_settop(L,3);
211 |
212 | for (size_t i = 0 ; i < set->idx ; i++)
213 | {
214 | if (set->set[i].fd == fh)
215 | {
216 | set->set[i].events = pollset_toevents(L,3);
217 | lua_pushinteger(L,0);
218 | return 1;
219 | }
220 | }
221 |
222 | lua_pushinteger(L,EINVAL);
223 | return 1;
224 | }
225 |
226 | /**********************************************************************/
227 |
228 | static int pullmeta_remove(lua_State *const L)
229 | {
230 | pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
231 | int fh = luaL_checkinteger(L,2);
232 |
233 | for (size_t i = 0 ; i < set->idx ; i++)
234 | {
235 | if (set->set[i].fd == fh)
236 | {
237 | lua_pushinteger(L,set->ref);
238 | lua_gettable(L,LUA_REGISTRYINDEX);
239 | lua_pushinteger(L,fh);
240 | lua_pushnil(L);
241 | lua_settable(L,-3);
242 |
243 | memmove(
244 | &set->set[i],
245 | &set->set[i+1],
246 | (set->idx - i - 1) * sizeof(struct pollfd)
247 | );
248 |
249 | set->idx--;
250 | lua_pushinteger(L,0);
251 | return 1;
252 | }
253 | }
254 |
255 | lua_pushinteger(L,EINVAL);
256 | return 1;
257 | }
258 |
259 | /**********************************************************************/
260 |
261 | static int pullmeta_events(lua_State *const L)
262 | {
263 | pollset__t *set = luaL_checkudata(L,1,TYPE_POLL);
264 | lua_Number dtimeout = luaL_optnumber(L,2,-1.0);
265 | int timeout;
266 |
267 | if (dtimeout < 0)
268 | timeout = -1;
269 | else
270 | timeout = (int)(dtimeout * 1000.0);
271 |
272 | if (poll(set->set,set->idx,timeout) < 0)
273 | {
274 | lua_pushnil(L);
275 | lua_pushinteger(L,errno);
276 | return 2;
277 | }
278 |
279 | lua_pushinteger(L,set->ref);
280 | lua_gettable(L,LUA_REGISTRYINDEX);
281 |
282 | lua_createtable(L,set->idx,0);
283 | for (size_t idx = 1 , i = 0 ; i < set->idx ; i++)
284 | {
285 | if (set->set[i].revents != 0)
286 | {
287 | lua_pushnumber(L,idx++);
288 | pollset_pushevents(L,set->set[i].events);
289 | lua_pushinteger(L,set->set[i].fd);
290 | lua_gettable(L,-5);
291 | lua_setfield(L,-2,"obj");
292 | lua_settable(L,-3);
293 | }
294 | }
295 |
296 | lua_pushinteger(L,0);
297 | return 2;
298 | }
299 |
300 | /**********************************************************************/
301 |
302 | static int pullmeta__POLL(lua_State *const L)
303 | {
304 | lua_pushliteral(L,"poll");
305 | return 1;
306 | }
307 |
308 | /**********************************************************************/
309 |
310 | static const luaL_Reg m_pullmeta[] =
311 | {
312 | { "__tostring" , pullmeta___tostring } ,
313 | { "__gc" , pullmeta___gc } ,
314 | { "insert" , pullmeta_insert } ,
315 | { "update" , pullmeta_update } ,
316 | { "remove" , pullmeta_remove } ,
317 | { "events" , pullmeta_events } ,
318 | { "POLL" , pullmeta__POLL } ,
319 | { NULL , NULL }
320 | };
321 |
322 | /**********************************************************************/
323 |
324 | int luaopen_poll(lua_State *const L)
325 | {
326 | luaL_newmetatable(L,TYPE_POLL);
327 | luaL_register(L,NULL,m_pullmeta);
328 | lua_pushvalue(L,-1);
329 | lua_setfield(L,-1,"__index");
330 |
331 | lua_pushcfunction(L,pollset_lua);
332 | return 1;
333 | }
334 |
335 | /**********************************************************************/
336 |
--------------------------------------------------------------------------------
/other/pollset-select.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2013 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #ifndef __GNUC__
23 | # define __attribute__(x)
24 | #endif
25 |
26 | #include
27 | #include
28 |
29 | #include
30 |
31 | #include
32 | #include
33 |
34 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM != 501
35 | # error This module is for Lua 5.1
36 | #endif
37 |
38 | #define TYPE_POLL "org.conman.pollset"
39 |
40 | /********************************************************************/
41 |
42 | typedef struct
43 | {
44 | fd_set read;
45 | fd_set write;
46 | fd_set except;
47 | int min;
48 | int max;
49 | size_t idx;
50 | int ref;
51 | } selectset__t;
52 |
53 | /**********************************************************************/
54 |
55 | static void selectset_toevents(
56 | lua_State *const L,
57 | int idx,
58 | selectset__t *set,
59 | int fd
60 | )
61 | {
62 | if (lua_istable(L,idx))
63 | {
64 | lua_getfield(L,idx,"read");
65 | if (lua_isboolean(L,-1)) FD_SET(fd,&set->read);
66 | lua_getfield(L,idx,"write");
67 | if (lua_isboolean(L,-1)) FD_SET(fd,&set->write);
68 | lua_getfield(L,idx,"except");
69 | if (lua_isboolean(L,-1)) FD_SET(fd,&set->except);
70 | lua_pop(L,3);
71 | }
72 | else if (lua_isstring(L,idx))
73 | {
74 | const char *flags = lua_tostring(L,idx);
75 | for ( ; *flags ; flags++)
76 | {
77 | switch(*flags)
78 | {
79 | case 'r': FD_SET(fd,&set->read); break;
80 | case 'w': FD_SET(fd,&set->write); break;
81 | case 'e': FD_SET(fd,&set->except); break;
82 | default: break;
83 | }
84 | }
85 | }
86 | else if (lua_isnil(L,idx))
87 | FD_SET(fd,&set->read);
88 | else
89 | luaL_error(L,"expected table or string");
90 | }
91 |
92 | /**********************************************************************/
93 |
94 | static void selectset_pushevents(lua_State *const L,selectset__t *set,int fd)
95 | {
96 | lua_createtable(L,0,4);
97 | lua_pushboolean(L,FD_ISSET(fd,&set->read));
98 | lua_setfield(L,-2,"read");
99 | lua_pushboolean(L,FD_ISSET(fd,&set->write));
100 | lua_setfield(L,-2,"write");
101 | lua_pushboolean(L,FD_ISSET(fd,&set->except));
102 | lua_setfield(L,-2,"except");
103 | }
104 |
105 | /**********************************************************************/
106 |
107 | static int selectset_lua(lua_State *const L)
108 | {
109 | selectset__t *set;
110 |
111 | set = lua_newuserdata(L,sizeof(selectset__t));
112 | FD_ZERO(&set->read);
113 | FD_ZERO(&set->write);
114 | FD_ZERO(&set->except);
115 | set->idx = 0;
116 | set->min = INT_MAX;
117 | set->max = 0;
118 |
119 | lua_createtable(L,0,0);
120 | set->ref = luaL_ref(L,LUA_REGISTRYINDEX);
121 |
122 | luaL_getmetatable(L,TYPE_POLL);
123 | lua_setmetatable(L,-2);
124 | return 1;
125 | }
126 |
127 | /**********************************************************************/
128 |
129 | static int selectmeta___tostring(lua_State *const L)
130 | {
131 | lua_pushfstring(L,"selectset (%p)",lua_touserdata(L,1));
132 | return 1;
133 | }
134 |
135 | /**********************************************************************/
136 |
137 | static int selectmeta___gc(lua_State *const L)
138 | {
139 | selectset__t *set = luaL_checkudata(L,1,TYPE_POLL);
140 | luaL_unref(L,LUA_REGISTRYINDEX,set->ref);
141 | return 0;
142 | }
143 |
144 | /**********************************************************************/
145 |
146 | static int selectmeta_insert(lua_State *const L)
147 | {
148 | selectset__t *set = luaL_checkudata(L,1,TYPE_POLL);
149 | int fh = luaL_checkinteger(L,2);
150 |
151 | lua_settop(L,4);
152 |
153 | if (fh > FD_SETSIZE)
154 | {
155 | lua_pushinteger(L,EINVAL);
156 | return 1;
157 | }
158 |
159 | if (fh < set->min) set->min = fh;
160 | if (fh > set->max) set->max = fh;
161 |
162 | selectset_toevents(L,3,set,fh);
163 |
164 | lua_pushinteger(L,set->ref);
165 | lua_gettable(L,LUA_REGISTRYINDEX);
166 | lua_pushinteger(L,fh);
167 |
168 | if (lua_isnil(L,4))
169 | lua_pushvalue(L,2);
170 | else
171 | lua_pushvalue(L,4);
172 |
173 | lua_settable(L,-3);
174 |
175 | set->idx++;
176 | lua_pushinteger(L,0);
177 | return 1;
178 | }
179 |
180 | /**********************************************************************/
181 |
182 | static int selectmeta_update(lua_State *const L)
183 | {
184 | selectset__t *set = luaL_checkudata(L,1,TYPE_POLL);
185 | int fh = luaL_checkinteger(L,2);
186 |
187 | FD_CLR(fh,&set->read);
188 | FD_CLR(fh,&set->write);
189 | FD_CLR(fh,&set->except);
190 |
191 | selectset_toevents(L,3,set,fh);
192 | lua_pushinteger(L,0);
193 | return 1;
194 | }
195 |
196 | /**********************************************************************/
197 |
198 | static int selectmeta_remove(lua_State *const L)
199 | {
200 | selectset__t *set = luaL_checkudata(L,1,TYPE_POLL);
201 | int fh = luaL_checkinteger(L,2);
202 |
203 | FD_CLR(fh,&set->read);
204 | FD_CLR(fh,&set->write);
205 | FD_CLR(fh,&set->except);
206 |
207 | lua_pushinteger(L,set->ref);
208 | lua_gettable(L,LUA_REGISTRYINDEX);
209 | lua_pushinteger(L,fh);
210 | lua_pushnil(L);
211 | lua_settable(L,-3);
212 |
213 | set->idx--;
214 | lua_pushinteger(L,0);
215 | return 1;
216 | }
217 |
218 | /**********************************************************************/
219 |
220 | static int selectmeta_events(lua_State *const L)
221 | {
222 | selectset__t *set = luaL_checkudata(L,1,TYPE_POLL);
223 | double timeout = luaL_optnumber(L,2,-1.0);
224 | struct timeval tout;
225 | struct timeval *ptout;
226 | fd_set read;
227 | fd_set write;
228 | fd_set except;
229 | int rc;
230 | int i;
231 | size_t idx;
232 |
233 | if (timeout < 0)
234 | ptout = NULL;
235 | else
236 | {
237 | double seconds;
238 | double fract;
239 |
240 | fract = modf(timeout,&seconds);
241 | tout.tv_sec = (long)seconds;
242 | tout.tv_usec = (long)(fract * 1000000.0);
243 | ptout = &tout;
244 | }
245 |
246 | read = set->read;
247 | write = set->write;
248 | except = set->except;
249 |
250 | rc = select(FD_SETSIZE,&read,&write,&except,ptout);
251 | if (rc < 0)
252 | {
253 | lua_pushnil(L);
254 | lua_pushinteger(L,errno);
255 | return 2;
256 | }
257 |
258 | lua_pushinteger(L,set->ref);
259 | lua_gettable(L,LUA_REGISTRYINDEX);
260 |
261 | lua_createtable(L,set->idx,0);
262 | for (idx = 1 , i = set->min ; i <= set->max ; i++)
263 | {
264 | if (FD_ISSET(i,&read) || FD_ISSET(i,&write) || FD_ISSET(i,&except))
265 | {
266 | lua_pushnumber(L,idx++);
267 | selectset_pushevents(L,set,i);
268 | lua_pushinteger(L,i);
269 | lua_gettable(L,-5);
270 | lua_setfield(L,-2,"obj");
271 | lua_settable(L,-3);
272 | }
273 | }
274 |
275 | lua_pushinteger(L,0);
276 | return 2;
277 | }
278 |
279 | /**********************************************************************/
280 |
281 | static int selectmeta__POLL(lua_State *const L)
282 | {
283 | lua_pushliteral(L,"select");
284 | return 1;
285 | }
286 |
287 | /**********************************************************************/
288 |
289 | static const luaL_Reg m_selectmeta[] =
290 | {
291 | { "__tostring" , selectmeta___tostring } ,
292 | { "__gc" , selectmeta___gc } ,
293 | { "insert" , selectmeta_insert } ,
294 | { "update" , selectmeta_update } ,
295 | { "remove" , selectmeta_remove } ,
296 | { "events" , selectmeta_events } ,
297 | { "POLL" , selectmeta__POLL } ,
298 | { NULL , NULL }
299 | };
300 |
301 | /**********************************************************************/
302 |
303 | int luaopen_select(lua_State *const L)
304 | {
305 | luaL_newmetatable(L,TYPE_POLL);
306 | luaL_register(L,NULL,m_selectmeta);
307 | lua_pushvalue(L,-1);
308 | lua_setfield(L,-1,"__index");
309 |
310 | lua_pushcfunction(L,selectset_lua);
311 | return 1;
312 | }
313 |
314 | /**********************************************************************/
315 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.const.exit-1.1.1-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "org.conman.const.exit"
2 | version = "1.1.1-1"
3 |
4 | source =
5 | {
6 | url = "https://raw.github.com/spc476/lua-conmanorg/exit-1.1.1/lua/const/exit.lua",
7 | md5 = "5887830a38db812d3b2486215b803bd5"
8 | }
9 |
10 | description =
11 | {
12 | homepage = "https://github.com/spc476/lua-conmanorg/blob/exit-1.1.1/lua/const/exit.lua",
13 | maintainer = "Sean Conner ",
14 | license = "LGPL3+",
15 | summary = "Some standard process exit return values",
16 | detailed = [[
17 | A Lua table that defines some common exit return codes for (mostly)
18 | a POSIX system (and Linux).
19 | ]]
20 | }
21 |
22 | dependencies =
23 | {
24 | "lua",
25 | }
26 |
27 | build =
28 | {
29 | type = 'builtin',
30 | copy_directories = {},
31 | modules = { ['org.conman.const.exit'] = "exit.lua" },
32 | }
33 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.const.gopher-types-2.0.1-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "org.conman.const.gopher-types"
2 | version = "2.0.1-1"
3 |
4 | source =
5 | {
6 | url = "https://raw.github.com/spc476/lua-conmanorg/gopher-types-2.0.1/lua/const/gopher-types.lua",
7 | md5 = "2602c7b56ca46f5cbbdbcbf04a3821d3",
8 | }
9 |
10 | description =
11 | {
12 | homepage = "https://github.com/spc476/lua-conmanorg/blob/gopher-types-2.0.1/lua/const/gopher-types.lua",
13 | maintainer = "Sean Conner ",
14 | license = "LGPL3+",
15 | summary = "Gopher Protocol selector types",
16 | detailed = [[
17 | A Lua table that maps Gopher Protocol selector types to a
18 | human-readable string. It can also map the human-readable string
19 | back to a Gopher Protocol selector type.
20 | ]]
21 | }
22 |
23 | dependencies =
24 | {
25 | "lua",
26 | }
27 |
28 | build =
29 | {
30 | type = 'builtin',
31 | copy_directories = {},
32 | modules = { ['org.conman.const.gopher-types'] = "gopher-types.lua" },
33 | }
34 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.env-1.0.4-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "org.conman.env"
2 | version = "1.0.4-1"
3 |
4 | source =
5 | {
6 | url = "https://raw.githubusercontent.com/spc476/lua-conmanorg/env-1.0.4/src/env.c",
7 | }
8 |
9 | description =
10 | {
11 | homepage = "https://github.com/spc476/lua-conmanorg/blob/env-1.0.4/src/env.c",
12 | maintainer = "Sean Conner ",
13 | license = "LGPL3+",
14 | summary = "Loads all environment variables into a table.",
15 | detailed = [[
16 | A Lua module that loads all current environment variables into a
17 | single table.
18 | ]],
19 | }
20 |
21 | dependencies =
22 | {
23 | "lua >= 5.1, <= 5.4",
24 | }
25 |
26 | build =
27 | {
28 | type = "builtin",
29 | copy_directories = {},
30 | modules =
31 | {
32 | ['org.conman.env'] = "env.c"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.errno-1.1.0-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "org.conman.errno"
2 | version = "1.1.0-1"
3 |
4 | source =
5 | {
6 | url = "https://raw.githubusercontent.com/spc476/lua-conmanorg/errno-1.1.0/src/errno.c"
7 | }
8 |
9 | description =
10 | {
11 | homepage = "https://github.com/spc476/lua-conmanorg/blob/errno-1.1.0/src/errno.c",
12 | maintainer = "Sean Conner ",
13 | license = "LGPL3+",
14 | summary = "C and POSIX system error codes.",
15 | detailed = [[
16 | A Lua module that enumerates all C and POSIX system error codes in
17 | a single table.
18 | ]],
19 | }
20 |
21 | dependencies =
22 | {
23 | "lua >= 5.1, <= 5.4",
24 | }
25 |
26 | build =
27 | {
28 | type = "builtin",
29 | copy_directories = {},
30 | modules =
31 | {
32 | ['org.conman.errno'] = "errno.c"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.iconv-2.0.0-4.rockspec:
--------------------------------------------------------------------------------
1 | package = "org.conman.iconv"
2 | version = "2.0.0-4"
3 |
4 | source =
5 | {
6 | url = "https://raw.github.com/spc476/lua-conmanorg/iconv-2.0.0/src/iconv.c"
7 | }
8 |
9 | description =
10 | {
11 | homepage = "https://github.com/spc476/lua-conmanorg/blob/iconv-2.0.0/src/iconv.c",
12 | maintainer = "Sean Conner ",
13 | license = "LGPL3+",
14 | summary = "Lua wrapper for IConv",
15 | detailed = [[
16 | A Lua module that wraps the iconv library call. It's simple to use:
17 |
18 | iconv = require "org.conman.iconv"
19 |
20 | trans = iconv("utf-8","iso-8859-1") -- from ISO-8869-1 to UTF-8
21 |
22 | x = This is \255 test" -- in ISO-8869-1
23 |
24 | y = trans(x) -- to UTF-8
25 | ]]
26 | }
27 |
28 | dependencies =
29 | {
30 | "lua >= 5.1, <= 5.4"
31 | }
32 |
33 | local iconv_library_dependency_override =
34 | {
35 | ICONV =
36 | {
37 | library = "iconv",
38 | },
39 | }
40 |
41 | local iconv_library_module_override =
42 | {
43 | modules =
44 | {
45 | iconv =
46 | {
47 | libraries = {"iconv"}
48 | }
49 | }
50 | }
51 |
52 | external_dependencies =
53 | {
54 | ICONV =
55 | {
56 | header = "iconv.h"
57 | },
58 |
59 | platforms =
60 | {
61 | cygwin = iconv_library_dependency_override,
62 | macosx = iconv_library_dependency_override,
63 | }
64 | }
65 |
66 | build =
67 | {
68 | type = "builtin",
69 | copy_directories = {},
70 | modules =
71 | {
72 | ['org.conman.iconv'] =
73 | {
74 | sources = "iconv.c",
75 | incdirs = {"$(ICONV_INCDIR)"},
76 | libdirs = {"$(ICONV_LIBDIR)"},
77 | }
78 | },
79 |
80 | platforms =
81 | {
82 | cygwin = iconv_library_module_override,
83 | macosx = iconv_library_module_override,
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.syslog-2.1.4-5.rockspec:
--------------------------------------------------------------------------------
1 | package = "org.conman.syslog"
2 | version = "2.1.4-5"
3 |
4 | source =
5 | {
6 | url = "https://raw.github.com/spc476/lua-conmanorg/syslog-2.1.4/src/syslog.c"
7 | }
8 |
9 | supported_platforms = { "unix" }
10 |
11 | description =
12 | {
13 | homepage = "https://github.com/spc476/lua-conmanorg/blob/syslog-2.1.4/src/syslog.c",
14 | maintainer = "Sean Conner ",
15 | license = "LGPL3+",
16 | summary = "Lua interface to syslog()",
17 | detailed = [[
18 | A Lua module that interfaces with syslog().
19 | ]],
20 | }
21 |
22 | dependencies =
23 | {
24 | "lua >= 5.1, <= 5.4",
25 | }
26 |
27 | build =
28 | {
29 | type = "builtin",
30 | copy_directories = {},
31 | modules = { ['org.conman.syslog'] = 'syslog.c' }
32 | }
33 |
--------------------------------------------------------------------------------
/rockspecs/org.conman.tls-2.0.0-3.rockspec:
--------------------------------------------------------------------------------
1 |
2 | package = "org.conman.tls"
3 | version = "2.0.0-3"
4 |
5 | source =
6 | {
7 | url ="https://raw.github.com/spc476/lua-conmanorg/tls-2.0.0/src/tls.c"
8 | }
9 |
10 | description =
11 | {
12 | homepage = "https://github.com/spc476/lua-conmanorg/blob/tls-2.0.0/src/tls.c",
13 | maintainer = "Sean Conner ",
14 | license = "LGPL3+",
15 | summary = "A Lua module that implements TLS via the libtls API.",
16 | detailed = [[
17 |
18 | This module handles TLS via the libtls API. There are several
19 | libraries now implementing this API, including LibreSSL (where it
20 | was originally developed), OpenSSL and BearSSL.
21 |
22 | You are probably better off reading the man pages for the libtls
23 | functions as this is straight port of the API.
24 |
25 | ]],
26 | }
27 |
28 | dependencies =
29 | {
30 | "lua >= 5.1, <= 5.4"
31 | }
32 |
33 | external_dependencies =
34 | {
35 | TLS =
36 | {
37 | header = "tls.h",
38 | },
39 | }
40 |
41 | build =
42 | {
43 | type = "builtin",
44 | copy_directory = {},
45 | modules =
46 | {
47 | ['org.conman.tls'] =
48 | {
49 | sources = "tls.c",
50 | incdirs = { "$(TLS_INCDIR)" },
51 | libraries = { 'tls' },
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/crc.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2010 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #include
23 | #include
24 |
25 | #include
26 | #include
27 |
28 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
29 | # error You need to compile against Lua 5.1 or higher
30 | #endif
31 |
32 | /******************************************************************/
33 |
34 | static int crc32(lua_State *L)
35 | {
36 | static uint32_t const m_crc32_table[] =
37 | {
38 | 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
39 | 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
40 | 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
41 | 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
42 | 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
43 | 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
44 | 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
45 | 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
46 | 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
47 | 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
48 | 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
49 | 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
50 | 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
51 | 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
52 | 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
53 | 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
54 | 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
55 | 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
56 | 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
57 | 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
58 | 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
59 | 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
60 | 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
61 | 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
62 | 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
63 | 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
64 | 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
65 | 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
66 | 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
67 | 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
68 | 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
69 | 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
70 | 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
71 | 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
72 | 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
73 | 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
74 | 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
75 | 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
76 | 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
77 | 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
78 | 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
79 | 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
80 | 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
81 | 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
82 | 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
83 | 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
84 | 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
85 | 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
86 | 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
87 | 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
88 | 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
89 | 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
90 | 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
91 | 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
92 | 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
93 | 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
94 | 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
95 | 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
96 | 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
97 | 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
98 | 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
99 | 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
100 | 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
101 | 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
102 | };
103 |
104 | size_t size;
105 | uint8_t const *p = (uint8_t const *)luaL_checklstring(L,1,&size);
106 | uint32_t crc = ~luaL_optinteger(L,2,0);
107 |
108 | while(size--)
109 | crc = (crc >> 8) ^ m_crc32_table[ (crc ^ *p++) & 0xFF ];
110 |
111 | lua_pushinteger(L,~crc);
112 | return 1;
113 | }
114 |
115 | /****************************************************************/
116 |
117 | int luaopen_org_conman_crc(lua_State *L)
118 | {
119 | lua_pushcfunction(L,crc32);
120 | return 1;
121 | }
122 |
123 | /*******************************************************************/
124 |
--------------------------------------------------------------------------------
/src/env.c:
--------------------------------------------------------------------------------
1 | /********************************************
2 | *
3 | * Copyright 2009 by Sean Conner. All Rights Reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | * ---------------------------------------------------------------------
21 | *
22 | * This module is nothing more than an array of the environmental variables
23 | * of the current process. There's not much more to say about this than
24 | *
25 | env = require "org.conman.env"
26 | print(env.LUA_PATH)
27 | print(env['LUA_CPATH'])
28 |
29 | *
30 | *********************************************/
31 |
32 | #include
33 | #include
34 |
35 | #include
36 | #include
37 |
38 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
39 | # error You need to compile against Lua 5.1 or higher
40 | #endif
41 |
42 | int luaopen_org_conman_env(lua_State *L)
43 | {
44 | extern char const **environ;
45 | int i;
46 |
47 | #if LUA_VERSION_NUM == 501
48 | static struct luaL_Reg const env[] =
49 | {
50 | { NULL , NULL }
51 | };
52 |
53 | luaL_register(L,"org.conman.env",env);
54 | #else
55 | lua_createtable(L,0,0);
56 | #endif
57 |
58 | for (i = 0 ; environ[i] != NULL ; i++)
59 | {
60 | char const *value = strchr(environ[i],'=');
61 | size_t len;
62 | int type;
63 |
64 | if (value != NULL)
65 | {
66 | len = (size_t)(value - environ[i]);
67 | value++;
68 | }
69 | else
70 | {
71 | len = strlen(environ[i]);
72 | value = "";
73 | }
74 |
75 | /*---------------------------------------------------------------------
76 | ; http://lwn.net/Articles/678148/
77 | ;
78 | ; The gist---if two environment variables exist with the same name,
79 | ; getenv() will return the first one, while languages like Perl and Lua,
80 | ; which dump everythinig into hash, will typically return the second
81 | ; value, which could be exploited. So we duplicate the behavior of
82 | ; getenv() and only save the environment variable if it already hasn't
83 | ; been set.
84 | ;----------------------------------------------------------------------*/
85 |
86 | lua_pushlstring(L,environ[i],len);
87 | lua_gettable(L,-2);
88 | type = lua_type(L,-1);
89 | lua_pop(L,1);
90 |
91 | if (type == LUA_TNIL)
92 | {
93 | lua_pushlstring(L,environ[i],len);
94 | lua_pushstring(L,value);
95 | lua_settable(L,-3);
96 | }
97 | }
98 |
99 | return 1;
100 | }
101 |
--------------------------------------------------------------------------------
/src/hash.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2011 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | #include
32 | #include
33 |
34 | #ifndef OPENSSL_VERSION_NUMBER
35 | # error Could not determine OpenSSL version
36 | #endif
37 |
38 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
39 | # error You need to compile against Lua 5.1 or higher
40 | #endif
41 |
42 | #define TYPE_HASH "org.conman.hash:hash"
43 |
44 | /************************************************************************/
45 |
46 | static int hash_hexa(
47 | lua_State *L,
48 | char const *data,
49 | size_t size
50 | )
51 | {
52 | luaL_Buffer buf;
53 | char hex[3];
54 |
55 | luaL_buffinit(L,&buf);
56 | while(size--)
57 | {
58 | snprintf(hex,3,"%02X",(unsigned char)*data++);
59 | luaL_addlstring(&buf,hex,2);
60 | }
61 | luaL_pushresult(&buf);
62 | return 1;
63 | }
64 |
65 | /************************************************************************/
66 |
67 | static int hashlua_new(lua_State *L)
68 | {
69 | char const *alg;
70 | EVP_MD const *m;
71 | EVP_MD_CTX **ctx;
72 |
73 | alg = luaL_optstring(L,1,"md5");
74 | m = EVP_get_digestbyname(alg);
75 | if (m == NULL)
76 | {
77 | lua_pushnil(L);
78 | return 1;
79 | }
80 |
81 | ctx = lua_newuserdata(L,sizeof(*ctx));
82 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL
83 | *ctx = malloc(sizeof(EVP_MD_CTX));
84 | #else
85 | *ctx = EVP_MD_CTX_new();
86 | #endif
87 |
88 | EVP_DigestInit(*ctx,m);
89 | luaL_getmetatable(L,TYPE_HASH);
90 | lua_setmetatable(L,-2);
91 | return 1;
92 | }
93 |
94 | /************************************************************************/
95 |
96 | static int hashlua_update(lua_State *L)
97 | {
98 | EVP_MD_CTX **ctx;
99 | char const *data;
100 | size_t size;
101 |
102 | ctx = luaL_checkudata(L,1,TYPE_HASH);
103 | data = luaL_checklstring(L,2,&size);
104 |
105 | if (size > INT_MAX)
106 | {
107 | lua_pushboolean(L,false);
108 | lua_pushinteger(L,EFBIG);
109 | return 2;
110 | }
111 |
112 | EVP_DigestUpdate(*ctx,data,size);
113 | lua_pushboolean(L,true);
114 | return 1;
115 | }
116 |
117 | /************************************************************************/
118 |
119 | static int hashlua_final(lua_State *L)
120 | {
121 | EVP_MD_CTX **ctx;
122 | unsigned char hash[EVP_MAX_MD_SIZE];
123 | unsigned int hashsize;
124 |
125 | ctx = luaL_checkudata(L,1,TYPE_HASH);
126 | hashsize = sizeof(hash);
127 |
128 | EVP_DigestFinal(*ctx,hash,&hashsize);
129 | lua_pushlstring(L,(char *)hash,hashsize);
130 | return 1;
131 | }
132 |
133 | /************************************************************************/
134 |
135 | static int hashlua_finalhexa(lua_State *L)
136 | {
137 | char const *data;
138 | size_t size;
139 |
140 | hashlua_final(L);
141 | data = lua_tolstring(L,-1,&size);
142 | return hash_hexa(L,data,size);
143 | }
144 |
145 | /************************************************************************/
146 |
147 | static int hashlua_sum(lua_State *L)
148 | {
149 | EVP_MD const *m;
150 | EVP_MD_CTX *ctx;
151 | char const *data;
152 | size_t size;
153 | char const *alg;
154 | unsigned char hash[EVP_MAX_MD_SIZE];
155 | unsigned int hashsize;
156 |
157 | data = luaL_checklstring(L,1,&size);
158 |
159 | if (size > INT_MAX)
160 | {
161 | lua_pushnil(L);
162 | lua_pushinteger(L,EFBIG);
163 | return 2;
164 | }
165 |
166 | alg = luaL_optstring(L,2,"md5");
167 | m = EVP_get_digestbyname(alg);
168 | if (m == NULL)
169 | {
170 | lua_pushnil(L);
171 | lua_pushinteger(L,EINVAL);
172 | return 2;
173 | }
174 |
175 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL
176 | ctx = malloc(sizeof(EVP_MD_CTX));
177 | #else
178 | ctx = EVP_MD_CTX_new();
179 | #endif
180 |
181 | hashsize = sizeof(hash);
182 | EVP_DigestInit(ctx,m);
183 | EVP_DigestUpdate(ctx,data,size);
184 | EVP_DigestFinal(ctx,hash,&hashsize);
185 |
186 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL
187 | free(ctx);
188 | #else
189 | EVP_MD_CTX_free(ctx);
190 | #endif
191 |
192 | lua_pushlstring(L,(char *)hash,hashsize);
193 | return 1;
194 | }
195 |
196 | /*****************************************************************/
197 |
198 | static int hashlua_hexa(lua_State *L)
199 | {
200 | char const *data;
201 | size_t size;
202 |
203 | data = luaL_checklstring(L,1,&size);
204 | return hash_hexa(L,data,size);
205 | }
206 |
207 | /************************************************************************/
208 |
209 | static int hashlua_sumhexa(lua_State *L)
210 | {
211 | char const *data;
212 | size_t size;
213 | int rc;
214 |
215 | rc = hashlua_sum(L);
216 | if (!lua_isstring(L,-1))
217 | return rc;
218 |
219 | data = lua_tolstring(L,-1,&size);
220 | return hash_hexa(L,data,size);
221 | }
222 |
223 | /************************************************************************/
224 |
225 | static int hashlua___tostring(lua_State *L)
226 | {
227 | lua_pushfstring(L,"hash (%p)",lua_touserdata(L,1));
228 | return 1;
229 | }
230 |
231 | /***********************************************************************/
232 |
233 | static int hashlua___gc(lua_State *L)
234 | {
235 | EVP_MD_CTX **ctx = luaL_checkudata(L,1,TYPE_HASH);
236 | if (*ctx != NULL)
237 | {
238 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL
239 | free(*ctx);
240 | #else
241 | EVP_MD_CTX_free(*ctx);
242 | #endif
243 | *ctx = NULL;
244 | }
245 |
246 | return 0;
247 | }
248 |
249 | /***********************************************************************/
250 |
251 | int luaopen_org_conman_hash(lua_State *L)
252 | {
253 | static struct luaL_Reg const hashlua[] =
254 | {
255 | { "new" , hashlua_new } ,
256 | { "update" , hashlua_update } ,
257 | { "final" , hashlua_final } ,
258 | { "sum" , hashlua_sum } ,
259 | { "hexa" , hashlua_hexa } ,
260 | { "sumhexa" , hashlua_sumhexa } ,
261 | { NULL , NULL }
262 | };
263 |
264 | static struct luaL_Reg const hashlua_meta[] =
265 | {
266 | { "update" , hashlua_update } ,
267 | { "final" , hashlua_final } ,
268 | { "finalhexa" , hashlua_finalhexa } ,
269 | { "__tostring" , hashlua___tostring } ,
270 | { "__gc" , hashlua___gc } ,
271 | #if LUA_VERSION_NUM >= 504
272 | { "__close" , hashlua___gc } ,
273 | #endif
274 | { NULL , NULL }
275 | };
276 |
277 | OpenSSL_add_all_digests();
278 |
279 | luaL_newmetatable(L,TYPE_HASH);
280 | #if LUA_VERSION_NUM == 501
281 | luaL_register(L,NULL,hashlua_meta);
282 | #else
283 | luaL_setfuncs(L,hashlua_meta,0);
284 | #endif
285 |
286 | lua_pushvalue(L,-1);
287 | lua_setfield(L,-2,"__index");
288 |
289 | #if LUA_VERSION_NUM == 501
290 | luaL_register(L,"org.conman.hash",hashlua);
291 | #else
292 | luaL_newlib(L,hashlua);
293 | #endif
294 |
295 | return 1;
296 | }
297 |
298 | /*************************************************************************/
299 |
--------------------------------------------------------------------------------
/src/iconv.c:
--------------------------------------------------------------------------------
1 | /*********************************************************************
2 | *
3 | * Copyright 2011 by Sean Conner. All Rights Reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | * -------------------------------------------------------------------
21 | *
22 | * Use of this module is straightforward. It returns a single function:
23 | *
24 | * iconv(target_charset,source_charset)
25 | * -- type(target_charset) == 'string'
26 | * -- type(source_charset) == 'string'
27 | *
28 | * This returns a userdata can can be used to transform a string from
29 | * one character set to another.
30 | *
31 | * trans = iconv(...)
32 | * newstr,err,idx = trans("this is a test")
33 | *
34 | * newstr = translated string, or nil if error
35 | * err = 0 if okay, otherwise, the error (integer)
36 | * idx = nil if okay, otherwise the index in the input where
37 | * the error happened.
38 | *
39 | * An example follows.
40 | *
41 |
42 | iconv = require "org.conman.iconv"
43 | trans = iconv("utf-8","iso-8859-1") -- convert from ISO-8859-1
44 | x = "This is \225 test" -- string in ISO-8859-1
45 | y = trans(x) -- string now in UTF-8
46 | print(y)
47 |
48 | *
49 | *********************************************************************/
50 |
51 | #include
52 | #include
53 | #include
54 |
55 | #include
56 |
57 | #include
58 | #include
59 |
60 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
61 | # error You need to compile against Lua 5.1 or higher
62 | #endif
63 |
64 | #define TYPE_ICONV "org.conman.iconv:iconv"
65 |
66 | /**************************************************************************/
67 |
68 | static int luaiconv_open(lua_State *L)
69 | {
70 | char const *fromcode;
71 | char const *tocode;
72 | iconv_t *pic;
73 | iconv_t ic;
74 |
75 | tocode = luaL_checkstring(L,1);
76 | fromcode = luaL_checkstring(L,2);
77 | ic = iconv_open(tocode,fromcode);
78 |
79 | if (ic == (iconv_t)-1)
80 | {
81 | lua_pushnil(L);
82 | lua_pushinteger(L,errno);
83 | lua_pushfstring(L,"%s:%s",tocode,fromcode);
84 | return 3;
85 | }
86 |
87 | pic = lua_newuserdata(L,sizeof(iconv_t));
88 | *pic = ic;
89 |
90 | luaL_getmetatable(L,TYPE_ICONV);
91 | lua_setmetatable(L,-2);
92 | lua_pushinteger(L,0);
93 | return 2;
94 | }
95 |
96 | /*************************************************************************/
97 |
98 | static int luametaiconv___call(lua_State *L)
99 | {
100 | char const *from;
101 | char const *ofrom;
102 | size_t fsize;
103 | iconv_t *pic;
104 | char to[LUAL_BUFFERSIZE];
105 | size_t tsize;
106 | char *pto;
107 | luaL_Buffer buf;
108 |
109 | pic = luaL_checkudata(L,1,TYPE_ICONV);
110 | from = luaL_checklstring(L,2,&fsize);
111 | tsize = sizeof(to);
112 | pto = to;
113 | ofrom = from;
114 |
115 | luaL_buffinit(L,&buf);
116 |
117 | while(fsize > 0)
118 | {
119 | if (iconv(*pic,(char **)&from,&fsize,&pto,&tsize) == (size_t)-1)
120 | {
121 | if (errno == E2BIG)
122 | {
123 | luaL_addlstring(&buf,to,sizeof(to) - tsize);
124 | pto = to;
125 | tsize = sizeof(to);
126 | }
127 | else
128 | {
129 | iconv(*pic,NULL,NULL,NULL,NULL); /* reset state */
130 | lua_pushnil(L);
131 | lua_pushinteger(L,errno);
132 | lua_pushinteger(L,(int)(from - ofrom) + 1);
133 | return 3;
134 | }
135 | }
136 | }
137 |
138 | luaL_addlstring(&buf,to,sizeof(to) - tsize);
139 | luaL_pushresult(&buf);
140 | lua_pushinteger(L,0);
141 | return 2;
142 | }
143 |
144 | /*************************************************************************/
145 |
146 | static int luametaiconv___tostring(lua_State *L)
147 | {
148 | lua_pushfstring(L,"iconv (%p)",lua_touserdata(L,1));
149 | return 1;
150 | }
151 |
152 | /*************************************************************************/
153 |
154 | static int luametaiconv___gc(lua_State *L)
155 | {
156 | iconv_t *ic = luaL_checkudata(L,1,TYPE_ICONV);
157 | if (*ic != NULL)
158 | {
159 | iconv_close(*ic);
160 | *ic = NULL;
161 | }
162 | return 0;
163 | }
164 |
165 | /*************************************************************************/
166 |
167 | int luaopen_org_conman_iconv(lua_State *L)
168 | {
169 | static struct luaL_Reg const reg_iconv_meta[] =
170 | {
171 | { "__call" , luametaiconv___call } ,
172 | { "__tostring" , luametaiconv___tostring } ,
173 | { "__gc" , luametaiconv___gc } ,
174 | #if LUA_VERSION_NUM >= 504
175 | { "__close" , luametaiconv___gc } ,
176 | #endif
177 | { NULL , NULL }
178 | };
179 |
180 | luaL_newmetatable(L,TYPE_ICONV);
181 | #if LUA_VERSION_NUM == 501
182 | luaL_register(L,NULL,reg_iconv_meta);
183 | #else
184 | luaL_setfuncs(L,reg_iconv_meta,0);
185 | #endif
186 | lua_pushcfunction(L,luaiconv_open);
187 | return 1;
188 | }
189 |
190 | /**************************************************************************/
191 |
--------------------------------------------------------------------------------
/src/idn.c:
--------------------------------------------------------------------------------
1 | /***************************************************************************
2 | *
3 | * Copyright 2020 by Sean Conner.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *************************************************************************/
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include
28 | #include
29 |
30 | #include
31 | #include
32 |
33 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
34 | # error You need to compile against Lua 5.1 or higher
35 | #endif
36 |
37 | /************************************************************************/
38 |
39 | union wstrp
40 | {
41 | punycode_uint *pc;
42 | uint32_t *uc;
43 | };
44 |
45 | union wstr
46 | {
47 | punycode_uint pc[64];
48 | uint32_t uc[64];
49 | };
50 |
51 | /************************************************************************/
52 |
53 | static bool add_segment(luaL_Buffer *buf,char const *seg,size_t len)
54 | {
55 | char *normalized;
56 | union wstrp domain;
57 | char topuny[64];
58 | size_t domainsize;
59 | size_t topunysize;
60 | bool rc;
61 |
62 | rc = false;
63 | normalized = stringprep_utf8_nfkc_normalize(seg,len);
64 |
65 | if (normalized != NULL)
66 | {
67 | domain.uc = stringprep_utf8_to_ucs4(normalized,-1,&domainsize);
68 | if (domain.uc != NULL)
69 | {
70 | topunysize = 64;
71 |
72 | if (punycode_encode(domainsize,domain.pc,NULL,&topunysize,topuny) == PUNYCODE_SUCCESS)
73 | {
74 | luaL_addlstring(buf,"xn--",4);
75 | luaL_addlstring(buf,topuny,topunysize);
76 | rc = true;
77 | }
78 | free(domain.uc);
79 | }
80 |
81 | free(normalized);
82 | }
83 |
84 | return rc;
85 | }
86 |
87 | /************************************************************************/
88 |
89 | static int idn_encode(lua_State *L)
90 | {
91 | char const *orig = luaL_checkstring(L,1);
92 | luaL_Buffer buf;
93 | size_t si;
94 | size_t di;
95 | bool utf8;
96 |
97 | luaL_buffinit(L,&buf);
98 |
99 | for (si = di = 0 , utf8 = false ; ; di++)
100 | {
101 | if (orig[di] == '\0')
102 | {
103 | if (utf8)
104 | {
105 | if (!add_segment(&buf,&orig[si],di - si))
106 | return 0;
107 | }
108 | else
109 | luaL_addlstring(&buf,&orig[si],di - si);
110 |
111 | luaL_pushresult(&buf);
112 | return 1;
113 | }
114 |
115 | if (orig[di] == '.')
116 | {
117 | if (utf8)
118 | {
119 | if (!add_segment(&buf,&orig[si],di - si))
120 | return 0;
121 | }
122 | else
123 | luaL_addlstring(&buf,&orig[si],di - si);
124 |
125 | luaL_addchar(&buf,'.');
126 | si = di + 1;
127 | utf8 = false;
128 | }
129 | else
130 | utf8 |= ((unsigned)orig[di]) > 127;
131 | }
132 | }
133 |
134 | /************************************************************************/
135 |
136 | static int idn_decode(lua_State *L)
137 | {
138 | char const *orig = luaL_checkstring(L,1);
139 | luaL_Buffer buf;
140 |
141 | luaL_buffinit(L,&buf);
142 |
143 | while(true)
144 | {
145 | char const *p = strchr(orig,'.');
146 | size_t len = p == NULL ? strlen(orig) : (size_t)(p - orig);
147 |
148 | if (strncmp(orig,"xn--",4) == 0)
149 | {
150 | union wstr frompuny;
151 | size_t frompunysize = 64;
152 | char *result;
153 |
154 | if (punycode_decode(len-4,&orig[4],&frompunysize,frompuny.pc,NULL) != PUNYCODE_SUCCESS)
155 | return 0;
156 |
157 | result = stringprep_ucs4_to_utf8(frompuny.uc,frompunysize,NULL,NULL);
158 |
159 | if (result != NULL)
160 | {
161 | luaL_addstring(&buf,result);
162 | free(result);
163 | }
164 | }
165 | else
166 | luaL_addlstring(&buf,orig,len);
167 |
168 | if (p != NULL)
169 | {
170 | luaL_addchar(&buf,'.');
171 | orig = ++p;
172 | }
173 | else
174 | {
175 | luaL_pushresult(&buf);
176 | return 1;
177 | }
178 | }
179 | }
180 |
181 | /************************************************************************/
182 |
183 | int luaopen_org_conman_idn(lua_State *L)
184 | {
185 | static luaL_Reg const m_idn_reg[] =
186 | {
187 | { "encode" , idn_encode },
188 | { "decode" , idn_decode },
189 | { NULL , NULL }
190 | };
191 |
192 | #if LUA_VERSION_NUM == 501
193 | luaL_register(L,"org.conman.idn",m_idn_reg);
194 | #else
195 | luaL_newlib(L,m_idn_reg);
196 | #endif
197 | return 1;
198 | }
199 |
200 | /************************************************************************/
201 |
--------------------------------------------------------------------------------
/src/lfsr.c:
--------------------------------------------------------------------------------
1 | /*********************************************************************
2 | *
3 | * Copyright 2010 by Sean Conner. All Rights Reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | * ---------------------------------------------------------------------
21 | *
22 | * This module implements LFSR of 8, 16 and 32 bits. These have the
23 | * following features:
24 | *
25 | * All sequence of bits between 1 and 2^bits are generated
26 | * It is very fast.
27 | *
28 | lfsr = require "org.conman.lfsr"
29 | rnd8 = lfsr( 8[,seed[,taps]])
30 | rnd16 = lfsr(16[,seed[,taps]])
31 | rnd32 = lfsr(32[,seed[,taps]])
32 | rnd32 = lfsr() -- 32, 0xB4000021
33 | *
34 | * NOTE: taps for 8b, 16b and 32bs can be found here:
35 | * http://users.ece.cmu.edu/~koopman/lfsr/index.html
36 | *
37 | * ALSO SEE:
38 | * https://en.wikipedia.org/wiki/Linear-feedback_shift_register
39 | *********************************************************************/
40 |
41 | #include
42 | #include
43 | #include
44 |
45 | /*********************************************************************/
46 |
47 | static int lfsrnext(lua_State *L)
48 | {
49 | lua_Integer mask = lua_tointeger(L,lua_upvalueindex(1));
50 | lua_Integer taps = lua_tointeger(L,lua_upvalueindex(2));
51 | lua_Integer lfsr = lua_tointeger(L,lua_upvalueindex(3));
52 | lua_Integer lsb = lfsr & 1;
53 |
54 | lfsr >>= 1;
55 | lfsr ^= (-lsb) & taps;
56 | lfsr &= mask;
57 | lua_pushinteger(L,lfsr);
58 | lua_pushinteger(L,lfsr);
59 | lua_replace(L,lua_upvalueindex(3));
60 | return 1;
61 | }
62 |
63 | /*********************************************************************/
64 |
65 | static int lfsr(lua_State *L)
66 | {
67 | lua_Integer bits = luaL_optinteger(L,1,32);
68 | lua_Integer seed = luaL_optinteger(L,2,0);
69 | lua_Integer taps = luaL_optinteger(L,3,0);
70 | lua_Integer mask;
71 |
72 | if (seed == 0)
73 | {
74 | FILE *fp = fopen("/dev/urandom","rb");
75 |
76 | if (fp)
77 | {
78 | fread(&seed,sizeof(seed),1,fp);
79 | fclose(fp);
80 | }
81 |
82 | if (seed == 0) seed++;
83 | }
84 |
85 | switch(bits)
86 | {
87 | case 8:
88 | if (taps == 0) taps = 0xB4; /* Pitfall! */
89 | mask = 0xFF;
90 | break;
91 |
92 | case 16:
93 | if (taps == 0) taps = 0xB400; /* more Pitfall! */
94 | mask = 0xFFFF;
95 | break;
96 |
97 | case 32:
98 | if (taps == 0) taps = 0xB4000021;
99 | mask = 0xFFFFFFFF;
100 | break;
101 |
102 | default:
103 | assert(0);
104 | return luaL_error(L,"bad mask value");
105 | }
106 |
107 | lua_pushinteger(L,mask);
108 | lua_pushinteger(L,taps);
109 | lua_pushinteger(L,seed);
110 | lua_pushcclosure(L,lfsrnext,3);
111 | return 1;
112 | }
113 |
114 | /*********************************************************************/
115 |
116 | int luaopen_org_conman_lfsr(lua_State *L)
117 | {
118 | lua_pushcfunction(L,lfsr);
119 | return 1;
120 | }
121 |
--------------------------------------------------------------------------------
/src/math.c:
--------------------------------------------------------------------------------
1 | /*********************************************************************
2 | *
3 | * Copyright 2010 by Sean Conner. All Rights Reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU Lesser General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or (at your
8 | * option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13 | * License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public License
16 | * along with this library; if not, see .
17 | *
18 | * Comments, questions and criticisms can be sent to: sean@conman.org
19 | *
20 | *********************************************************************/
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include
31 | #include
32 |
33 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
34 | # error You need to compile against Lua 5.1 or higher
35 | #endif
36 |
37 | /************************************************************************/
38 |
39 | static int math_seed(lua_State *L)
40 | {
41 | #if LUA_VERSION_NUM >= 504
42 | lua_Integer seed[2];
43 | #else
44 | lua_Integer seed[1];
45 | #endif
46 |
47 | FILE *fp = fopen("/dev/urandom","rb");
48 | if (fp == NULL)
49 | return 0;
50 | fread(seed,sizeof(seed),1,fp);
51 | fclose(fp);
52 |
53 | #if LUA_VERSION_NUM >= 504
54 | lua_pushinteger(L,seed[0]);
55 | lua_pushinteger(L,seed[1]);
56 | return 2;
57 | #else
58 | lua_pushinteger(L,seed[0]);
59 | return 1;
60 | #endif
61 | }
62 |
63 | /************************************************************************/
64 |
65 | static int math_randomseed(lua_State *const L)
66 | {
67 | char *seedbank;
68 | char *seedbank_file;
69 | char *seedbank_log;
70 | unsigned int seed;
71 |
72 | assert(L != NULL);
73 |
74 | /*--------------------------------------------------------------------
75 | ; The idea for this is from https://github.com/catseye/seedbank
76 | ;
77 | ; But slightly modified. If SEEDBANK_SEED is an integer, that's used
78 | ; as the seeed. If SEEDBANK_FILE is set and SEEDBANK_SEED=LAST, then
79 | ; the contents of $SEEDBANK_FILE is used. Otherwise, the older methods
80 | ; are used (so this is new functionality).
81 | ;
82 | ; In either case, if SEEDBANK_FILE is set, then the seed (however
83 | ; selected) will be saved in that file. I'm not sure of the security
84 | ; implications of this---a malicious user can set either environment
85 | ; variable to cause problems, but if a malicious user can do that, I
86 | ; suspect you have other issues.
87 | ;--------------------------------------------------------------------*/
88 |
89 | seedbank = getenv("SEEDBANK_SEED");
90 |
91 | if (seedbank != NULL)
92 | {
93 | char *ep;
94 | unsigned long val;
95 | char buffer[64];
96 |
97 | if (strcmp(seedbank,"LAST") == 0)
98 | {
99 | seedbank_file = getenv("SEEDBANK_FILE");
100 | if (seedbank_file != NULL)
101 | {
102 | FILE *fp = fopen(seedbank_file,"r");
103 |
104 | /*------------------------------------------------------------------
105 | ; most common error---file doesn't exist. But there's not real easy
106 | ; way to check for that condition only. So in some bizarre cases,
107 | ; not reporting an error may fail us here. Well, if we had issues
108 | ; reading, we might have issues writing, so let's hope the check
109 | ; below finds an issue.
110 | ;
111 | ; But we still need a seed. So let's skip ahead (GOTO WARNING!).
112 | ;------------------------------------------------------------------*/
113 |
114 | if (fp != NULL)
115 | {
116 | memset(buffer,0,sizeof(buffer));
117 | fgets(buffer,sizeof(buffer),fp);
118 | fclose(fp);
119 | seedbank = buffer;
120 | }
121 | else
122 | goto math_randomseed_normal;
123 | }
124 | }
125 |
126 | errno = 0;
127 | val = strtoul(seedbank,&ep,10);
128 | if (errno != 0)
129 | return luaL_error(L,"SEEDBANK_SEED not a valid number");
130 | if (val > UINT_MAX)
131 | return luaL_error(L,"SEEDBANK_SEED range exceeded");
132 |
133 | seed = val;
134 | }
135 | else
136 | {
137 | math_randomseed_normal:
138 | if (!lua_isboolean(L,1) && lua_isnumber(L,1))
139 | seed = lua_tonumber(L,1);
140 | else
141 | {
142 | FILE *fp;
143 |
144 | if (lua_toboolean(L,1))
145 | {
146 | fp = fopen("/dev/random","rb");
147 | if (fp == NULL)
148 | return luaL_error(L,"The NSA is keeping you from seeding your RNG");
149 | }
150 | else
151 | {
152 | fp = fopen("/dev/urandom","rb");
153 | if (fp == NULL)
154 | return luaL_error(L,"cannot seed RNG");
155 | }
156 |
157 | fread(&seed,sizeof(seed),1,fp);
158 | fclose(fp);
159 | }
160 | }
161 |
162 | seedbank_file = getenv("SEEDBANK_FILE");
163 | if (seedbank_file)
164 | {
165 | FILE *fp = fopen(seedbank_file,"w");
166 | if (fp != NULL)
167 | {
168 | fprintf(fp,"%u\n",seed);
169 | fclose(fp);
170 | }
171 | else
172 | return luaL_error(L,"SEEDBANK_FILE: %s",strerror(errno));
173 | }
174 |
175 | seedbank_log = getenv("SEEDBANK_LOG");
176 | if (seedbank_log != NULL)
177 | {
178 | FILE *fp = fopen(seedbank_log,"a");
179 | if (fp != NULL)
180 | {
181 | time_t now = time(NULL);
182 | char buffer[20];
183 |
184 | strftime(buffer,sizeof(buffer),"%Y-%m-%dT%H:%M:%S",localtime(&now));
185 | fprintf(fp,"%s: %u\n",buffer,seed);
186 | fclose(fp);
187 | }
188 | }
189 |
190 | srand(seed);
191 | lua_pushnumber(L,seed);
192 | return 1;
193 | }
194 |
195 | /**************************************************************************/
196 |
197 | static int math_idiv(lua_State *const L)
198 | {
199 | long numer = luaL_checkinteger(L,1);
200 | long denom = luaL_checkinteger(L,2);
201 | ldiv_t result;
202 |
203 | if (denom == 0)
204 | {
205 | if (numer < 0)
206 | {
207 | lua_pushnumber(L,-HUGE_VAL);
208 | lua_pushnumber(L,-HUGE_VAL);
209 | }
210 | else
211 | {
212 | lua_pushnumber(L,HUGE_VAL);
213 | lua_pushnumber(L,HUGE_VAL);
214 | }
215 | }
216 | else
217 | {
218 | result = ldiv(numer,denom);
219 | lua_pushinteger(L,result.quot);
220 | lua_pushinteger(L,result.rem);
221 | }
222 |
223 | return 2;
224 | }
225 |
226 | /**************************************************************************/
227 |
228 | static int math_div(lua_State *const L)
229 | {
230 | double numer = luaL_checknumber(L,1);
231 | double denom = luaL_checknumber(L,2);
232 |
233 | lua_pushnumber(L,numer / denom);
234 | lua_pushnumber(L,fmod(numer,denom));
235 |
236 | return 2;
237 | }
238 |
239 | /************************************************************************/
240 |
241 | int luaopen_org_conman_math(lua_State *L)
242 | {
243 | static const struct luaL_Reg reg_math[] =
244 | {
245 | { "seed" , math_seed },
246 | { "randomseed" , math_randomseed },
247 | { "idiv" , math_idiv },
248 | { "div" , math_div },
249 | { NULL , NULL }
250 | };
251 |
252 | #if LUA_VERSION_NUM == 501
253 | luaL_register(L,"org.conman.math",reg_math);
254 | #else
255 | luaL_newlib(L,reg_math);
256 | #endif
257 | return 1;
258 | }
259 |
260 | /**************************************************************************/
261 |
--------------------------------------------------------------------------------
/test/base64-test.lua:
--------------------------------------------------------------------------------
1 | -- luacheck: ignore 611
2 |
3 | local tap = require "tap14"
4 | local base64 = require "org.conman.base64"
5 |
6 | local data = "" do
7 | for i = 0 , 255 do
8 | data = data .. string.char(i)
9 | end
10 | for i = 255 , 0 , -1 do
11 | data = data .. string.char(i)
12 | end
13 | assert(#data == 512)
14 | end
15 |
16 | local tests =
17 | {
18 | {
19 | name = "RFC-1421 (deprecated)",
20 | last = "+/",
21 | pad = "=",
22 | len = 64,
23 | ignore = false,
24 | strict = false,
25 | nocrlf = false,
26 | },
27 |
28 | {
29 | name = "RFC-2045 (default)",
30 | last = "+/",
31 | pad = "=",
32 | len = 76,
33 | ignore = true,
34 | strict = false,
35 | nocrlf = false,
36 | },
37 |
38 | {
39 | name = "UTF-7",
40 | last = "+/",
41 | pad = "",
42 | len = -1,
43 | ignore = false,
44 | strict = false,
45 | nocrlf = true,
46 | },
47 |
48 | {
49 | name = "IMAP",
50 | last = "+,",
51 | pad = "",
52 | len = -1,
53 | ignore = false,
54 | strict = false,
55 | nocrlf = true,
56 | },
57 |
58 | {
59 | name = "RFC-4648 s4",
60 | last = "+/",
61 | pad = "",
62 | len = -1,
63 | ignore = false,
64 | strict = false,
65 | nocrlf = true,
66 | },
67 |
68 | {
69 | name = "RFC-4648 s5",
70 | last = "-_",
71 | pad = "",
72 | len = -1,
73 | ignore = false,
74 | strict = false,
75 | nocrlf = true,
76 | },
77 | }
78 |
79 | tap.plan(#tests * 5 + 4)
80 |
81 | for _,t in ipairs(tests) do
82 | local b = base64(t)
83 | local x = b:encode(data)
84 | tap.assert(x,"%s: encoding",t.name)
85 | if t.len > 0 then
86 | tap.assert(#x:match("^(.-)\n") == t.len,"%s: length check",t.name)
87 | else
88 | tap.assert(#x == 683,"%s: length check",t.name)
89 | end
90 | if t.pad == "=" then
91 | tap.assert(x:sub(-1,-1) == t.pad,"%s: pad check",t.name)
92 | else
93 | tap.assert(x:sub(-1,-1) ~= t.pad,"%s: pad check",t.name)
94 | end
95 | local y = b:decode(x)
96 | tap.assert(y,"%s: decoding",t.name)
97 | tap.assert(y == data,"%s: decoding data check",t.name)
98 | end
99 |
100 | local b = base64 { strict = true }
101 | local y = b:decode("QQ==")
102 | tap.assert(y,"strict mode: decoding good data")
103 | tap.assert(#y == 1,"strict mode: decoding length good data")
104 | tap.assert(y == 'A',"strict mode: decoding good data check")
105 | y = b:decode("QR==")
106 | tap.assert(not y,"strict mode: decoding malicious data")
107 |
108 | os.exit(tap.done())
109 |
--------------------------------------------------------------------------------
/test/clock-test.lua:
--------------------------------------------------------------------------------
1 |
2 | local tap = require "tap14"
3 | local clock = require "org.conman.clock"
4 | local process = require "org.conman.process"
5 | local signal = require "org.conman.signal"
6 |
7 | local child = process.fork()
8 | if not child then
9 | io.stderr:write("failure\n")
10 | os.exit(1)
11 | end
12 |
13 | local info
14 |
15 | if child == 0 then
16 | signal.catch('int')
17 | local left = clock.sleep(2)
18 | if left >= 0.9 and left <= 1.0 then
19 | process.exit(0)
20 | else
21 | process.exit(1)
22 | end
23 | else
24 | clock.sleep(1)
25 | signal.raise('int',child)
26 | info = process.wait(child)
27 | end
28 |
29 | tap.plan(1)
30 | tap.assert(info.rc == 0)
31 | tap.done()
32 |
--------------------------------------------------------------------------------
/test/idn-test.lua:
--------------------------------------------------------------------------------
1 |
2 | -- luacheck: ignore 611 631
3 | -- Examples pulled from RFC-3492
4 |
5 | local tap = require "tap14"
6 | local idn = require "org.conman.idn"
7 |
8 | tap.plan(2)
9 |
10 | local data =
11 | {
12 | {
13 | what = "(A) Arabic (Egyptian)",
14 | orig = "\u{0644}\u{064A}\u{0647}\u{0645}\u{0627}\u{0628}\u{062A}\u{0643}\u{0644}\u{0645}\u{0648}\u{0634}\u{0639}\u{0631}\u{0628}\u{064A}\u{061F}",
15 | puny = "xn--egbpdaj6bu4bxfgehfvwxn",
16 | },
17 |
18 | {
19 | what = "(B) Chinese (simplified)",
20 | orig = "\u{4ED6}\u{4EEC}\u{4E3A}\u{4EC0}\u{4E48}\u{4E0D}\u{8BF4}\u{4E2D}\u{6587}",
21 | puny = "xn--ihqwcrb4cv8a8dqg056pqjye",
22 | },
23 |
24 | {
25 | what = "(C) Chinese (traditional)",
26 | orig = "\u{4ED6}\u{5011}\u{7232}\u{4EC0}\u{9EBD}\u{4E0D}\u{8AAA}\u{4E2D}\u{6587}",
27 | puny = "xn--ihqwctvzc91f659drss3x8bo0yb",
28 | },
29 |
30 | {
31 | what = "(D) Czech: Proprostnemluvesky",
32 | orig = "\u{0050}\u{0072}\u{006F}\u{010D}\u{0070}\u{0072}\u{006F}\u{0073}\u{0074}\u{011B}\u{006E}\u{0065}\u{006D}\u{006C}\u{0075}\u{0076}\u{00ED}\u{010D}\u{0065}\u{0073}\u{006B}\u{0079}",
33 | puny = "xn--Proprostnemluvesky-uyb24dma41a",
34 | },
35 |
36 | {
37 | what = "(E) Hebrew",
38 | orig = "\u{05DC}\u{05DE}\u{05D4}\u{05D4}\u{05DD}\u{05E4}\u{05E9}\u{05D5}\u{05D8}\u{05DC}\u{05D0}\u{05DE}\u{05D3}\u{05D1}\u{05E8}\u{05D9}\u{05DD}\u{05E2}\u{05D1}\u{05E8}\u{05D9}\u{05EA}",
39 | puny = "xn--4dbcagdahymbxekheh6e0a7fei0b",
40 | },
41 |
42 | {
43 | what = "(F) Hindi (Devanagari)",
44 | orig = "\u{092F}\u{0939}\u{0932}\u{094B}\u{0917}\u{0939}\u{093F}\u{0928}\u{094D}\u{0926}\u{0940}\u{0915}\u{094D}\u{092F}\u{094B}\u{0902}\u{0928}\u{0939}\u{0940}\u{0902}\u{092C}\u{094B}\u{0932}\u{0938}\u{0915}\u{0924}\u{0947}\u{0939}\u{0948}\u{0902}",
45 | puny = "xn--i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
46 | },
47 |
48 | {
49 | what = "(G) Japanese (kanji and hiragana)",
50 | orig = "\u{306A}\u{305C}\u{307F}\u{3093}\u{306A}\u{65E5}\u{672C}\u{8A9E}\u{3092}\u{8A71}\u{3057}\u{3066}\u{304F}\u{308C}\u{306A}\u{3044}\u{306E}\u{304B}",
51 | puny = "xn--n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
52 | },
53 |
54 | --[[ Passed in word exceeds DNS label length
55 | {
56 | what = "(H) Korean (Hangul syllables)",
57 | orig = "\u{C138}\u{ACC4}\u{C758}\u{BAA8}\u{B4E0}\u{C0AC}\u{B78C}\u{B4E4}\u{C774}\u{D55C}\u{AD6D}\u{C5B4}\u{B97C}\u{C774}\u{D574}\u{D55C}\u{B2E4}\u{BA74}\u{C5BC}\u{B9C8}\u{B098}\u{C88B}\u{C744}\u{AE4C}",
58 | puny = "xn--989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c",
59 | },
60 | --]]
61 |
62 | {
63 | what = "(I) Russian (Cyrillic)",
64 | orig = "\u{043F}\u{043E}\u{0447}\u{0435}\u{043C}\u{0443}\u{0436}\u{0435}\u{043E}\u{043D}\u{0438}\u{043D}\u{0435}\u{0433}\u{043E}\u{0432}\u{043E}\u{0440}\u{044F}\u{0442}\u{043F}\u{043E}\u{0440}\u{0443}\u{0441}\u{0441}\u{043A}\u{0438}",
65 | puny = "xn--b1abfaaepdrnnbgefbadotcwatmq2g4l",
66 | },
67 |
68 | {
69 | what = "(J) Spanish: PorqunopuedensimplementehablarenEspaol",
70 | orig = "\u{0050}\u{006F}\u{0072}\u{0071}\u{0075}\u{00E9}\u{006E}\u{006F}\u{0070}\u{0075}\u{0065}\u{0064}\u{0065}\u{006E}\u{0073}\u{0069}\u{006D}\u{0070}\u{006C}\u{0065}\u{006D}\u{0065}\u{006E}\u{0074}\u{0065}\u{0068}\u{0061}\u{0062}\u{006C}\u{0061}\u{0072}\u{0065}\u{006E}\u{0045}\u{0073}\u{0070}\u{0061}\u{00F1}\u{006F}\u{006C}",
71 | puny = "xn--PorqunopuedensimplementehablarenEspaol-fmd56a",
72 | },
73 |
74 | {
75 | what = "(K) Vietnamese",
76 | orig = "\u{0054}\u{1EA1}\u{0069}\u{0073}\u{0061}\u{006F}\u{0068}\u{1ECD}\u{006B}\u{0068}\u{00F4}\u{006E}\u{0067}\u{0074}\u{0068}\u{1EC3}\u{0063}\u{0068}\u{1EC9}\u{006E}\u{00F3}\u{0069}\u{0074}\u{0069}\u{1EBF}\u{006E}\u{0067}\u{0056}\u{0069}\u{1EC7}\u{0074}",
77 | puny = "xn--TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
78 | },
79 |
80 | {
81 | what = "(L) 3B",
82 | orig = "\u{0033}\u{5E74}\u{0042}\u{7D44}\u{91D1}\u{516B}\u{5148}\u{751F}",
83 | puny = "xn--3B-ww4c5e180e575a65lsy2b",
84 | },
85 |
86 | {
87 | what = "(M) -with-SUPER-MONKEYS",
88 | orig = "\u{5B89}\u{5BA4}\u{5948}\u{7F8E}\u{6075}\u{002D}\u{0077}\u{0069}\u{0074}\u{0068}\u{002D}\u{0053}\u{0055}\u{0050}\u{0045}\u{0052}\u{002D}\u{004D}\u{004F}\u{004E}\u{004B}\u{0045}\u{0059}\u{0053}",
89 | puny = "xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
90 | },
91 |
92 | {
93 | what = "(N) Hello-Another-Way-",
94 | orig = "\u{0048}\u{0065}\u{006C}\u{006C}\u{006F}\u{002D}\u{0041}\u{006E}\u{006F}\u{0074}\u{0068}\u{0065}\u{0072}\u{002D}\u{0057}\u{0061}\u{0079}\u{002D}\u{305D}\u{308C}\u{305E}\u{308C}\u{306E}\u{5834}\u{6240}",
95 | puny = "xn--Hello-Another-Way--fc4qua05auwb3674vfr0b",
96 | },
97 |
98 | {
99 | what = "(O) 2",
100 | orig = "\u{3072}\u{3068}\u{3064}\u{5C4B}\u{6839}\u{306E}\u{4E0B}\u{0032}",
101 | puny = "xn--2-u9tlzr9756bt3uc0v",
102 | },
103 |
104 | {
105 | what = "(P) MajiKoi5",
106 | orig= "\u{004D}\u{0061}\u{006A}\u{0069}\u{3067}\u{004B}\u{006F}\u{0069}\u{3059}\u{308B}\u{0035}\u{79D2}\u{524D}",
107 | puny = "xn--MajiKoi5-783gue6qz075azm5e",
108 | },
109 |
110 | {
111 | what = "(Q) de",
112 | orig = "\u{30D1}\u{30D5}\u{30A3}\u{30FC}\u{0064}\u{0065}\u{30EB}\u{30F3}\u{30D0}",
113 | puny = "xn--de-jg4avhby1noc0d",
114 | },
115 |
116 | {
117 | what = "(R) ",
118 | orig = "\u{305D}\u{306E}\u{30B9}\u{30D4}\u{30FC}\u{30C9}\u{3067}",
119 | puny = "xn--d9juau41awczczp",
120 | },
121 |
122 | --[[ Not a realistic test for this
123 | {
124 | what = "(S) -> $1.00 <-",
125 | orig = "\u{002D}\u{003E}\u{0020}\u{0024}\u{0031}\u{002E}\u{0030}\u{0030}\u{0020}\u{003C}\u{002D}",
126 | puny = "xn---> $1.00 <--",
127 | },
128 | --]]
129 | }
130 |
131 | tap.plan(#data,"test set 1")
132 | for _,test in ipairs(data) do
133 | tap.plan(4,test.what)
134 | local e = idn.encode(test.orig)
135 | tap.assert(e,"encode()")
136 | tap.assert(e == test.puny,"encode() matches")
137 | local d = idn.decode(e)
138 | tap.assert(d,"decode()")
139 | tap.assert(d == test.orig,"decode() matches")
140 | tap.done()
141 | end
142 | tap.done()
143 |
144 | local data2 =
145 | {
146 | {
147 | what = "Normalization 1",
148 | orig = "re\u{0301}sume\u{0301}",
149 | puny = "xn--rsum-bpad",
150 | tran = "r\u{00E9}sum\u{00E9}",
151 | },
152 |
153 | {
154 | what = "Normalization 2",
155 | orig = "fo\u{0301}\u{0321}b",
156 | puny = "xn--fb-5ja64t",
157 | tran = "f\u{00F3}\u{0321}b",
158 | },
159 |
160 | {
161 | what = "Normalization 3",
162 | orig = "fo\u{0321}\u{0301}b",
163 | puny = "xn--fb-5ja64t",
164 | tran = "f\u{00F3}\u{0321}b",
165 | },
166 | }
167 |
168 | tap.plan(#data2,"test set 2---normalization")
169 | for _,test in ipairs(data2) do
170 | tap.plan(4,test.what)
171 | local e = idn.encode(test.orig)
172 | tap.assert(e,"encode()")
173 | tap.assert(e == test.puny,"encode() matches")
174 | local d = idn.decode(e)
175 | tap.assert(d,"decode()")
176 | tap.assert(d == test.tran,"decode() matches")
177 | tap.done()
178 | end
179 | tap.done()
180 | os.exit(tap.done())
181 |
--------------------------------------------------------------------------------
/test/net-test.lua:
--------------------------------------------------------------------------------
1 |
2 | -- luacheck: ignore 611
3 |
4 | local tap = require "tap14"
5 | local net = require "org.conman.net"
6 |
7 | local function compare_lists(a,b)
8 | if (#a ~= #b) then return false end
9 | for i = 1 , #a do
10 | if a[i] ~= b[i] then return false end
11 | end
12 | return true
13 | end
14 |
15 | -- ---------------------------------------------------------------------
16 | -- Address tests
17 | -- ---------------------------------------------------------------------
18 |
19 | tap.plan(7)
20 |
21 | local function address_test(case)
22 | tap.plan(10,case.desc)
23 | local a1 = net.address(case.addr,case.proto,case.port)
24 | local a2 = net.address(case.addr,case.proto,case.port)
25 |
26 | tap.assert(a1 == a2,"equality works")
27 | tap.assert(#a1 == case.len,"length works")
28 | tap.assert(#a2 == case.len,"length works (again)")
29 |
30 | tap.assert(a1.family == case.family,"family")
31 | tap.assert(a1.addrbits == case.addrbits,"addrbits")
32 | tap.assert(a1.port == case.iport,"port")
33 | tap.assert(tostring(a1) == case.tostring,"tostring")
34 | tap.assert(a1:display() == case.display,"display")
35 | tap.assert(a1:display(case.iport) == case.display_port,"display port")
36 |
37 | if a1.family == 'ip6' then
38 | tap.assert(a1.daddr == '[' .. a1.addr .. ']',"daddr")
39 | else
40 | tap.assert(a1.daddr == a1.addr,"daddr")
41 | end
42 | tap.done()
43 | end
44 |
45 | address_test {
46 | desc = "UDP/IP with named port",
47 | family = 'ip',
48 | addr = "127.0.0.1",
49 | addrbits = "\127\0\0\1",
50 | proto = 'udp',
51 | port = 'domain',
52 | iport = 53,
53 | len = 4,
54 | tostring = "127.0.0.1:53",
55 | display = "127.0.0.1:53",
56 | display_port = "127.0.0.1"
57 | }
58 |
59 | address_test {
60 | desc = "TCP/IP with numeric port",
61 | family = 'ip',
62 | addr = "127.0.0.1",
63 | addrbits = "\127\0\0\1",
64 | proto = 'tcp',
65 | port = 33333,
66 | iport = 33333,
67 | len = 4,
68 | tostring = "127.0.0.1:33333",
69 | display = "127.0.0.1:33333",
70 | display_port = "127.0.0.1",
71 | }
72 |
73 | address_test {
74 | desc = "OSPF/IP, named protocol",
75 | family = 'ip',
76 | addr = "127.0.0.1",
77 | addrbits = "\127\0\0\1",
78 | proto = 'ospf',
79 | iport = 89,
80 | len = 4,
81 | tostring = "127.0.0.1:89",
82 | display = "127.0.0.1:89",
83 | display_port = "127.0.0.1",
84 | }
85 |
86 | address_test {
87 | desc = "UDP/IP6 with named port",
88 | family = 'ip6',
89 | addr = "fc00::c0ff:eeba:d015:dead:beef",
90 | addrbits = "\252\0\0\0\0\0\192\255\238\186\208\21\222\173\190\239",
91 | proto = 'udp',
92 | port = 'domain',
93 | iport = 53,
94 | len = 16,
95 | tostring = "[fc00::c0ff:eeba:d015:dead:beef]:53",
96 | display = "[fc00::c0ff:eeba:d015:dead:beef]:53",
97 | display_port = "[fc00::c0ff:eeba:d015:dead:beef]",
98 | }
99 |
100 | address_test {
101 | desc = "TCP/IP6 with numeric port",
102 | family = 'ip6',
103 | addr = "fc00::c0ff:eeba:d015:dead:beef",
104 | addrbits = "\252\0\0\0\0\0\192\255\238\186\208\21\222\173\190\239",
105 | proto = 'udp',
106 | port = 33333,
107 | iport = 33333,
108 | len = 16,
109 | tostring = "[fc00::c0ff:eeba:d015:dead:beef]:33333",
110 | display = "[fc00::c0ff:eeba:d015:dead:beef]:33333",
111 | display_port = "[fc00::c0ff:eeba:d015:dead:beef]",
112 | }
113 |
114 | address_test {
115 | desc = "OSPF/IP, named protocol",
116 | family = 'ip6',
117 | addr = "fc00::c0ff:eeba:d015:dead:beef",
118 | addrbits = "\252\0\0\0\0\0\192\255\238\186\208\21\222\173\190\239",
119 | proto = 'ospf',
120 | iport = 89,
121 | len = 16,
122 | tostring = "[fc00::c0ff:eeba:d015:dead:beef]:89",
123 | display = "[fc00::c0ff:eeba:d015:dead:beef]:89",
124 | display_port = "[fc00::c0ff:eeba:d015:dead:beef]",
125 | }
126 |
127 | local list1 =
128 | {
129 | net.address('192.168.1.10','udp',3333),
130 | net.address('192.168.1.10','udp',2222),
131 | net.address('192.168.1.10','tcp',4444),
132 | net.address('192.168.1.10','tcp',1111),
133 | net.address('127.0.0.1','udp',17),
134 | net.address('127.0.0.1','udp',3),
135 | net.address('127.0.0.1','tcp',11),
136 | net.address('127.0.0.1','tcp',7),
137 | net.address('/dev/log','udp'),
138 | net.address('/dev/log','tcp'),
139 | net.address('fc00::1','udp',33),
140 | net.address('fc00::1','udp',3),
141 | net.address('fc00::1','tcp',22),
142 | net.address('fc00::1','tcp',5),
143 | net.address('::1','udp',33),
144 | net.address('::1','udp',3),
145 | net.address('::1','tcp',22),
146 | net.address('::1','tcp',5),
147 | }
148 |
149 | local list2 =
150 | {
151 | net.address('/dev/log','tcp'),
152 | net.address('/dev/log','udp'),
153 | net.address('127.0.0.1','udp',3),
154 | net.address('127.0.0.1','tcp',7),
155 | net.address('127.0.0.1','tcp',11),
156 | net.address('127.0.0.1','udp',17),
157 | net.address('192.168.1.10','tcp',1111),
158 | net.address('192.168.1.10','udp',2222),
159 | net.address('192.168.1.10','udp',3333),
160 | net.address('192.168.1.10','tcp',4444),
161 | net.address('::1','udp',3),
162 | net.address('::1','tcp',5),
163 | net.address('::1','tcp',22),
164 | net.address('::1','udp',33),
165 | net.address('fc00::1','udp',3),
166 | net.address('fc00::1','tcp',5),
167 | net.address('fc00::1','tcp',22),
168 | net.address('fc00::1','udp',33),
169 | }
170 |
171 | table.remove(list1) -- because the last call to net.address() fills in the
172 | table.remove(list2) -- last slot with 0. So remove that 0.
173 | table.sort(list1)
174 |
175 | tap.assert(compare_lists(list1,list2),"test sortability")
176 | os.exit(tap.done(),true)
177 |
--------------------------------------------------------------------------------
/test/pollset-test.lua:
--------------------------------------------------------------------------------
1 | -- luacheck: ignore 611 411
2 |
3 | local tap = require "tap14"
4 | local fsys = require "org.conman.fsys"
5 | local pollset = require "org.conman.pollset"
6 |
7 | -- -------------------------------------------------------------
8 | -- create some data to schlep around, and a pipe to select upon
9 | -- -------------------------------------------------------------
10 |
11 | local data = string.rep(" ",256)
12 | local pipe = fsys.pipe()
13 | pipe.read:setvbuf('no')
14 | pipe.write:setvbuf('no')
15 |
16 | -- ---------------
17 | -- Run the tests
18 | -- ----------------
19 |
20 | tap.plan(6)
21 | local set do
22 | set = pollset()
23 | tap.assertB(set,"set creation")
24 | tap.assertB(set._implementation,"We're testing the %s implementation",set._implemenation or "-")
25 | end
26 |
27 | tap.plan(7,"timeout test (5 seconds)") do
28 | local err = set:insert(pipe.read,"r")
29 | tap.assertB(err,"inserting the read event")
30 |
31 | local zen = os.time()
32 | local okay,err = set:wait(5)
33 | local now = os.time()
34 |
35 | tap.assert(okay,"waiting")
36 | tap.assert(err,"we got an error (even if success)")
37 | tap.assert((now - zen) >= 5,"we took five seconds")
38 |
39 | local events,state,var = set:events()
40 | tap.assert(events,"events exist")
41 | tap.assert(state,"state info")
42 | tap.assert(not var,"variable info")
43 | tap.done()
44 | end
45 |
46 | tap.plan(8,"testing read readiness") do
47 | pipe.write:write(data)
48 |
49 | local zen = os.time()
50 | local okay,err = set:wait(5)
51 | local now = os.time()
52 |
53 | tap.assert(okay,"waiting for up to 5 seconds")
54 | tap.assert(not err,"no error")
55 | tap.assert((now-zen) <= 1,"we didn't actually wait")
56 | local events,state,var = set:events()
57 | tap.assert(events,"events exist")
58 | local e = events(state,var)
59 | tap.assert(e,"event item")
60 | tap.assert(e.read,"event is read event")
61 | tap.assert(events(state,var) == nil,"no further events")
62 |
63 | local blob = pipe.read:read(256)
64 | tap.assert(#blob == 256,"we have read data")
65 | tap.done()
66 | end
67 |
68 | do
69 | local err = set:remove(pipe.read)
70 | tap.assert(err == 0,"file removed from set")
71 | end
72 |
73 | tap.plan(16,"testing write readiness") do
74 |
75 | local err = set:insert(pipe.read,"r")
76 | tap.assertB(err == 0,"insert read file into set")
77 |
78 | local err = set:insert(pipe.write,"w")
79 | tap.assertB(err == 0,"insert write file into set")
80 |
81 | local zen = os.time()
82 | local okay,err = set:wait(5)
83 | local now = os.time()
84 |
85 | tap.assert(okay,"wait for events")
86 | tap.assert(not err,"no error while waiting")
87 | tap.assert((now-zen) <= 1,"no waiting for data")
88 | local events,state,var = set:events()
89 | tap.assert(events,"we have events")
90 | local e = events(state,var)
91 | tap.assert(e,"first event")
92 | tap.assert(e.write,"we can write")
93 | tap.assert(events(state,var) == nil,"no further events")
94 |
95 | pipe.write:write(data)
96 | set:remove(pipe.write)
97 |
98 | local zen = os.time()
99 | local okay,err = set:wait(5)
100 | local now = os.time()
101 |
102 | tap.assert(okay,"wait for more events")
103 | tap.assert(not err,"no error")
104 | tap.assert((now-zen) <= 1,"no waiting for data")
105 | local events,state,var = set:events()
106 | tap.assert(events,"we have events")
107 | local e = events(state,var)
108 | tap.assert(e,"first event")
109 | tap.assert(e.read,"it's a read event")
110 |
111 | local blob = pipe.read:read(256)
112 | tap.assert(#blob == 256,"we have data")
113 | tap.done()
114 | end
115 |
116 | os.exit(tap.done(),true)
117 |
--------------------------------------------------------------------------------
/test/tap14.lua:
--------------------------------------------------------------------------------
1 | -- *************************************************************************
2 | --
3 | -- Copyright 2022 by Sean Conner. All Rights Reserved.
4 | --
5 | -- This program is free software: you can redistribute it and/or modify it
6 | -- under the terms of the GNU General Public License as published by the
7 | -- Free Software Foundation, either version 3 of the License, or (at your
8 | -- option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful, but
11 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 | -- Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program. If not, see .
17 | --
18 | -- Comments, questions and criticisms can be sent to: sean@conman.org
19 | --
20 | -- *************************************************************************
21 | -- luacheck: ignore 611
22 | -- luacheck: globals plan comment assert assertB done
23 |
24 | local io = require "io"
25 | local string = require "string"
26 | local os = require "os"
27 | local table = require "table"
28 |
29 | local _VERSION = _VERSION
30 |
31 | if _VERSION == "Lua 5.1" then
32 | module("tap14")
33 | else
34 | _ENV = {}
35 | end
36 |
37 | local mtaps = {}
38 |
39 | -- *************************************************************************
40 |
41 | local function ok(msg,...)
42 | local tap = mtaps[#mtaps]
43 | io.stdout:write(tap.pad,"ok ",tap.id)
44 | if msg then
45 | io.stdout:write(" - ",string.format(msg,...))
46 | end
47 | io.stdout:write("\n")
48 | tap.id = tap.id + 1
49 | end
50 |
51 | -- *************************************************************************
52 |
53 | local function notok(msg,...)
54 | local tap = mtaps[#mtaps]
55 | io.stdout:write(tap.pad,"not ok ",tap.id)
56 | if msg then
57 | io.stdout:write(" - ",string.format(msg,...))
58 | end
59 | io.stdout:write("\n")
60 | tap.pass = false
61 | tap.id = tap.id + 1
62 | end
63 |
64 | -- *************************************************************************
65 |
66 | local function bail(msg,...)
67 | io.stdout:write("Bail out!")
68 | if msg then
69 | io.stdout:write(" ",string.format(msg,...))
70 | end
71 | io.stdout:write("\n")
72 | os.exit(1,true)
73 | end
74 |
75 | -- *************************************************************************
76 |
77 | function plan(plan,fmt,...)
78 | local tap =
79 | {
80 | name = (fmt and string.format(fmt,...)) or "",
81 | pad = (mtaps[#mtaps] and mtaps[#mtaps].pad .. " ") or "",
82 | plan = plan or 0,
83 | id = 1,
84 | pass = true,
85 | }
86 |
87 | if tap.name and tap.name ~= "" then
88 | io.stdout:write(mtaps[#mtaps].pad,"# Subtest: ",tap.name,"\n")
89 | end
90 |
91 | if tap.plan ~= 0 then
92 | io.stdout:write(tap.pad,"1..",tap.plan,"\n")
93 | end
94 |
95 | table.insert(mtaps,tap)
96 | end
97 |
98 | -- *************************************************************************
99 |
100 | function comment(fmt,...)
101 | io.stdout:write(mtaps[#mtaps].pad,"# ",string.format(fmt,...),"\n")
102 | end
103 |
104 | -- *************************************************************************
105 |
106 | function assert(cond,...) -- luacheck: ignore
107 | if cond then
108 | ok(...)
109 | else
110 | notok(...)
111 | end
112 | return cond
113 | end
114 |
115 | -- *************************************************************************
116 |
117 | function assertB(cond,...)
118 | if cond then
119 | ok(...)
120 | else
121 | bail(...)
122 | end
123 | return cond
124 | end
125 |
126 | -- *************************************************************************
127 |
128 | function done()
129 | local tap = table.remove(mtaps)
130 |
131 | if tap.plan == 0 then
132 | io.stdout:write(tap.pad,"1..",tap.id - 1,"\n")
133 | end
134 |
135 | if #mtaps > 0 then
136 | if tap.pass then
137 | if tap.name ~= "" then
138 | ok(tap.name)
139 | else
140 | ok()
141 | end
142 | else
143 | if tap.name ~= "" then
144 | notok(tap.name)
145 | else
146 | notok()
147 | end
148 | end
149 | end
150 | return tap.pass and 0 or 1
151 | end
152 |
153 | -- *************************************************************************
154 |
155 | io.stdout:write("TAP version 14\n")
156 |
157 | if _VERSION >= "Lua 5.2" then
158 | return _ENV
159 | end
160 |
--------------------------------------------------------------------------------