diff options
Diffstat (limited to 'util-src')
-rw-r--r-- | util-src/Makefile | 47 | ||||
-rw-r--r-- | util-src/crand.c | 122 | ||||
-rw-r--r-- | util-src/encodings.c | 347 | ||||
-rw-r--r-- | util-src/hashes.c | 71 | ||||
-rw-r--r-- | util-src/net.c | 73 | ||||
-rw-r--r-- | util-src/pposix.c | 714 | ||||
-rw-r--r-- | util-src/ringbuffer.c | 214 | ||||
-rw-r--r-- | util-src/signal.c | 502 | ||||
-rw-r--r-- | util-src/table.c | 33 | ||||
-rw-r--r-- | util-src/windows.c | 63 |
10 files changed, 1387 insertions, 799 deletions
diff --git a/util-src/Makefile b/util-src/Makefile index 3a1ba3f2..f18d5a80 100644 --- a/util-src/Makefile +++ b/util-src/Makefile @@ -1,41 +1,34 @@ include ../config.unix -LUA_SUFFIX?=5.1 -LUA_INCDIR?=/usr/include/lua$(LUA_SUFFIX) -LUA_LIB?=lua$(LUA_SUFFIX) -IDN_LIB?=idn -OPENSSL_LIB?=crypto -CC?=gcc -CXX?=g++ -LD?=gcc -CFLAGS+=-ggdb +CFLAGS+=-I$(LUA_INCDIR) + +INSTALL_DATA=install -m644 +TARGET?=../util/ + +ALL=encodings.so hashes.so net.so pposix.so signal.so table.so ringbuffer.so + +ifdef RANDOM +ALL+=crand.so +endif .PHONY: all install clean .SUFFIXES: .c .o .so -all: encodings.so hashes.so net.so pposix.so signal.so +all: $(ALL) -install: encodings.so hashes.so net.so pposix.so signal.so - install *.so ../util/ +install: $(ALL) + $(INSTALL_DATA) $^ $(TARGET) clean: - rm -f *.o - rm -f *.so - rm -f ../util/*.so - -encodings.so: encodings.o - MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET; - $(CC) -o $@ $< $(LDFLAGS) $(IDNA_LIBS) + rm -f $(ALL) $(patsubst %.so,%.o,$(ALL)) -hashes.so: hashes.o - MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET; - $(CC) -o $@ $< $(LDFLAGS) -l$(OPENSSL_LIB) +encodings.so: LDLIBS+=$(IDNA_LIBS) -.c.o: - $(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o $@ $< +hashes.so: LDLIBS+=$(OPENSSL_LIBS) -.o.so: - MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET; - $(LD) -o $@ $< $(LDFLAGS) +crand.o: CFLAGS+=-DWITH_$(RANDOM) +crand.so: LDLIBS+=$(RANDOM_LIBS) +%.so: %.o + $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) diff --git a/util-src/crand.c b/util-src/crand.c new file mode 100644 index 00000000..7eea1f2b --- /dev/null +++ b/util-src/crand.c @@ -0,0 +1,122 @@ +/* Prosody IM +-- Copyright (C) 2008-2017 Matthew Wild +-- Copyright (C) 2008-2017 Waqas Hussain +-- Copyright (C) 2016-2017 Kim Alvefur +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- +*/ + +/* +* crand.c +* C PRNG interface +* +* The purpose of this module is to provide access to a PRNG in +* environments without /dev/urandom +* +* Caution! This has not been extensively tested. +* +*/ + +#define _DEFAULT_SOURCE + +#include "lualib.h" +#include "lauxlib.h" + +#include <string.h> +#include <errno.h> + +#if defined(WITH_GETRANDOM) + +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(a,b) 0 +#endif + +#if ! __GLIBC_PREREQ(2,25) +#include <unistd.h> +#include <sys/syscall.h> + +#ifndef SYS_getrandom +#error getrandom() requires Linux 3.17 or later +#endif + +/* This wasn't present before glibc 2.25 */ +int getrandom(void *buf, size_t buflen, unsigned int flags) { + return syscall(SYS_getrandom, buf, buflen, flags); +} +#else +#include <sys/random.h> +#endif + +#elif defined(WITH_ARC4RANDOM) +#include <stdlib.h> +#elif defined(WITH_OPENSSL) +#include <openssl/rand.h> +#else +#error util.crand compiled without a random source +#endif + +int Lrandom(lua_State *L) { + int ret = 0; + size_t len = (size_t)luaL_checkinteger(L, 1); + void *buf = lua_newuserdata(L, len); + +#if defined(WITH_GETRANDOM) + /* + * This acts like a read from /dev/urandom with the exception that it + * *does* block if the entropy pool is not yet initialized. + */ + ret = getrandom(buf, len, 0); + + if(ret < 0) { + lua_pushstring(L, strerror(errno)); + return lua_error(L); + } + +#elif defined(WITH_ARC4RANDOM) + arc4random_buf(buf, len); + ret = len; +#elif defined(WITH_OPENSSL) + if(!RAND_status()) { + lua_pushliteral(L, "OpenSSL PRNG not seeded"); + return lua_error(L); + } + + ret = RAND_bytes(buf, len); + + if(ret == 1) { + ret = len; + } else { + /* TODO ERR_get_error() */ + lua_pushstring(L, "RAND_bytes() failed"); + return lua_error(L); + } + +#endif + + lua_pushlstring(L, buf, ret); + return 1; +} + +int luaopen_util_crand(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif + + lua_createtable(L, 0, 2); + lua_pushcfunction(L, Lrandom); + lua_setfield(L, -2, "bytes"); + +#if defined(WITH_GETRANDOM) + lua_pushstring(L, "Linux"); +#elif defined(WITH_ARC4RANDOM) + lua_pushstring(L, "arc4random()"); +#elif defined(WITH_OPENSSL) + lua_pushstring(L, "OpenSSL"); +#endif + lua_setfield(L, -2, "_source"); + + return 1; +} + diff --git a/util-src/encodings.c b/util-src/encodings.c index 91826ca4..465819d5 100644 --- a/util-src/encodings.c +++ b/util-src/encodings.c @@ -2,7 +2,7 @@ -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain -- Copyright (C) 1994-2015 Lua.org, PUC-Rio. --- +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- @@ -21,97 +21,140 @@ #include "lua.h" #include "lauxlib.h" +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + /***************** BASE64 *****************/ -static const char code[]= -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char code[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static void base64_encode(luaL_Buffer *b, unsigned int c1, unsigned int c2, unsigned int c3, int n) -{ - unsigned long tuple=c3+256UL*(c2+256UL*c1); +static void base64_encode(luaL_Buffer *b, unsigned int c1, unsigned int c2, unsigned int c3, int n) { + unsigned long tuple = c3 + 256UL * (c2 + 256UL * c1); int i; char s[4]; - for (i=0; i<4; i++) { - s[3-i] = code[tuple % 64]; + + for(i = 0; i < 4; i++) { + s[3 - i] = code[tuple % 64]; tuple /= 64; } - for (i=n+1; i<4; i++) s[i]='='; - luaL_addlstring(b,s,4); + + for(i = n + 1; i < 4; i++) { + s[i] = '='; + } + + luaL_addlstring(b, s, 4); } -static int Lbase64_encode(lua_State *L) /** encode(s) */ -{ +static int Lbase64_encode(lua_State *L) { /** encode(s) */ size_t l; - const unsigned char *s=(const unsigned char*)luaL_checklstring(L,1,&l); + const unsigned char *s = (const unsigned char *)luaL_checklstring(L, 1, &l); luaL_Buffer b; int n; - luaL_buffinit(L,&b); - for (n=l/3; n--; s+=3) base64_encode(&b,s[0],s[1],s[2],3); - switch (l%3) - { - case 1: base64_encode(&b,s[0],0,0,1); break; - case 2: base64_encode(&b,s[0],s[1],0,2); break; + luaL_buffinit(L, &b); + + for(n = l / 3; n--; s += 3) { + base64_encode(&b, s[0], s[1], s[2], 3); + } + + switch(l % 3) { + case 1: + base64_encode(&b, s[0], 0, 0, 1); + break; + + case 2: + base64_encode(&b, s[0], s[1], 0, 2); + break; } + luaL_pushresult(&b); return 1; } -static void base64_decode(luaL_Buffer *b, int c1, int c2, int c3, int c4, int n) -{ - unsigned long tuple=c4+64L*(c3+64L*(c2+64L*c1)); +static void base64_decode(luaL_Buffer *b, int c1, int c2, int c3, int c4, int n) { + unsigned long tuple = c4 + 64L * (c3 + 64L * (c2 + 64L * c1)); char s[3]; - switch (--n) - { - case 3: s[2]=(char) tuple; - case 2: s[1]=(char) (tuple >> 8); - case 1: s[0]=(char) (tuple >> 16); + + switch(--n) { + case 3: + s[2] = (char) tuple; + + case 2: + s[1] = (char)(tuple >> 8); + + case 1: + s[0] = (char)(tuple >> 16); } - luaL_addlstring(b,s,n); + + luaL_addlstring(b, s, n); } -static int Lbase64_decode(lua_State *L) /** decode(s) */ -{ +static int Lbase64_decode(lua_State *L) { /** decode(s) */ size_t l; - const char *s=luaL_checklstring(L,1,&l); + const char *s = luaL_checklstring(L, 1, &l); luaL_Buffer b; - int n=0; + int n = 0; char t[4]; - luaL_buffinit(L,&b); - for (;;) - { - int c=*s++; - switch (c) - { - const char *p; + luaL_buffinit(L, &b); + + for(;;) { + int c = *s++; + + switch(c) { + const char *p; + default: - p=strchr(code,c); if (p==NULL) return 0; - t[n++]= (char) (p-code); - if (n==4) - { - base64_decode(&b,t[0],t[1],t[2],t[3],4); - n=0; + p = strchr(code, c); + + if(p == NULL) { + return 0; + } + + t[n++] = (char)(p - code); + + if(n == 4) { + base64_decode(&b, t[0], t[1], t[2], t[3], 4); + n = 0; } + break; + case '=': - switch (n) - { - case 1: base64_decode(&b,t[0],0,0,0,1); break; - case 2: base64_decode(&b,t[0],t[1],0,0,2); break; - case 3: base64_decode(&b,t[0],t[1],t[2],0,3); break; + + switch(n) { + case 1: + base64_decode(&b, t[0], 0, 0, 0, 1); + break; + + case 2: + base64_decode(&b, t[0], t[1], 0, 0, 2); + break; + + case 3: + base64_decode(&b, t[0], t[1], t[2], 0, 3); + break; } - n=0; + + n = 0; break; + case 0: luaL_pushresult(&b); return 1; - case '\n': case '\r': case '\t': case ' ': case '\f': case '\b': + + case '\n': + case '\r': + case '\t': + case ' ': + case '\f': + case '\b': break; } } } -static const luaL_Reg Reg_base64[] = -{ +static const luaL_Reg Reg_base64[] = { { "encode", Lbase64_encode }, { "decode", Lbase64_decode }, { NULL, NULL } @@ -129,28 +172,41 @@ static const luaL_Reg Reg_base64[] = /* * Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. */ -static const char *utf8_decode (const char *o, int *val) { - static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; +static const char *utf8_decode(const char *o, int *val) { + static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; const unsigned char *s = (const unsigned char *)o; unsigned int c = s[0]; unsigned int res = 0; /* final result */ - if (c < 0x80) /* ascii? */ + + if(c < 0x80) { /* ascii? */ res = c; - else { + } else { int count = 0; /* to count number of continuation bytes */ - while (c & 0x40) { /* still have continuation bytes? */ + + while(c & 0x40) { /* still have continuation bytes? */ int cc = s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ - return NULL; /* invalid byte sequence */ + + if((cc & 0xC0) != 0x80) { /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + } + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ c <<= 1; /* to test next bit */ } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ - if (count > 3 || res > MAXUNICODE || res <= limits[count] || (0xd800 <= res && res <= 0xdfff) ) - return NULL; /* invalid byte sequence */ + + if(count > 3 || res > MAXUNICODE || res <= limits[count] || (0xd800 <= res && res <= 0xdfff)) { + return NULL; /* invalid byte sequence */ + } + s += count; /* skip continuation bytes read */ } - if (val) *val = res; + + if(val) { + *val = res; + } + return (const char *)s + 1; /* +1 to include first byte */ } @@ -158,20 +214,25 @@ static const char *utf8_decode (const char *o, int *val) { * Check that a string is valid UTF-8 * Returns NULL if not */ -const char* check_utf8 (lua_State *L, int idx, size_t *l) { +const char *check_utf8(lua_State *L, int idx, size_t *l) { size_t pos, len; const char *s = luaL_checklstring(L, 1, &len); pos = 0; - while (pos <= len) { + + while(pos <= len) { const char *s1 = utf8_decode(s + pos, NULL); - if (s1 == NULL) { /* conversion error? */ + + if(s1 == NULL) { /* conversion error? */ return NULL; } + pos = s1 - s; } + if(l != NULL) { *l = len; } + return s; } @@ -182,23 +243,23 @@ static int Lutf8_valid(lua_State *L) { static int Lutf8_length(lua_State *L) { size_t len; + if(!check_utf8(L, 1, &len)) { lua_pushnil(L); lua_pushliteral(L, "invalid utf8"); return 2; } + lua_pushinteger(L, len); return 1; } -static const luaL_Reg Reg_utf8[] = -{ +static const luaL_Reg Reg_utf8[] = { { "valid", Lutf8_valid }, { "length", Lutf8_length }, { NULL, NULL } }; - /***************** STRINGPREP *****************/ #ifdef USE_STRINGPREP_ICU @@ -206,8 +267,7 @@ static const luaL_Reg Reg_utf8[] = #include <unicode/ustring.h> #include <unicode/utrace.h> -static int icu_stringprep_prep(lua_State *L, const UStringPrepProfile *profile) -{ +static int icu_stringprep_prep(lua_State *L, const UStringPrepProfile *profile) { size_t input_len; int32_t unprepped_len, prepped_len, output_len; const char *input; @@ -215,52 +275,63 @@ static int icu_stringprep_prep(lua_State *L, const UStringPrepProfile *profile) UChar unprepped[1024]; /* Temporary unicode buffer (1024 characters) */ UChar prepped[1024]; - + UErrorCode err = U_ZERO_ERROR; if(!lua_isstring(L, 1)) { lua_pushnil(L); return 1; } + input = lua_tolstring(L, 1, &input_len); - if (input_len >= 1024) { + + if(input_len >= 1024) { lua_pushnil(L); return 1; } + u_strFromUTF8(unprepped, 1024, &unprepped_len, input, input_len, &err); - if (U_FAILURE(err)) { + + if(U_FAILURE(err)) { lua_pushnil(L); return 1; } + prepped_len = usprep_prepare(profile, unprepped, unprepped_len, prepped, 1024, 0, NULL, &err); - if (U_FAILURE(err)) { + + if(U_FAILURE(err)) { lua_pushnil(L); return 1; } else { u_strToUTF8(output, 1024, &output_len, prepped, prepped_len, &err); - if (U_SUCCESS(err) && output_len < 1024) + + if(U_SUCCESS(err) && output_len < 1024) { lua_pushlstring(L, output, output_len); - else + } else { lua_pushnil(L); + } + return 1; } } UStringPrepProfile *icu_nameprep; UStringPrepProfile *icu_nodeprep; -UStringPrepProfile *icu_resourceprep; +UStringPrepProfile *icu_resourceprep; UStringPrepProfile *icu_saslprep; /* initialize global ICU stringprep profiles */ -void init_icu() -{ +void init_icu() { UErrorCode err = U_ZERO_ERROR; utrace_setLevel(UTRACE_VERBOSE); icu_nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, &err); icu_nodeprep = usprep_openByType(USPREP_RFC3920_NODEPREP, &err); icu_resourceprep = usprep_openByType(USPREP_RFC3920_RESOURCEPREP, &err); icu_saslprep = usprep_openByType(USPREP_RFC4013_SASLPREP, &err); - if (U_FAILURE(err)) fprintf(stderr, "[c] util.encodings: error: %s\n", u_errorName((UErrorCode)err)); + + if(U_FAILURE(err)) { + fprintf(stderr, "[c] util.encodings: error: %s\n", u_errorName((UErrorCode)err)); + } } #define MAKE_PREP_FUNC(myFunc, prep) \ @@ -271,8 +342,7 @@ MAKE_PREP_FUNC(Lstringprep_nodeprep, icu_nodeprep) /** stringprep.nodeprep(s) * MAKE_PREP_FUNC(Lstringprep_resourceprep, icu_resourceprep) /** stringprep.resourceprep(s) */ MAKE_PREP_FUNC(Lstringprep_saslprep, icu_saslprep) /** stringprep.saslprep(s) */ -static const luaL_Reg Reg_stringprep[] = -{ +static const luaL_Reg Reg_stringprep[] = { { "nameprep", Lstringprep_nameprep }, { "nodeprep", Lstringprep_nodeprep }, { "resourceprep", Lstringprep_resourceprep }, @@ -285,24 +355,28 @@ static const luaL_Reg Reg_stringprep[] = #include <stringprep.h> -static int stringprep_prep(lua_State *L, const Stringprep_profile *profile) -{ +static int stringprep_prep(lua_State *L, const Stringprep_profile *profile) { size_t len; const char *s; char string[1024]; int ret; + if(!lua_isstring(L, 1)) { lua_pushnil(L); return 1; } + s = check_utf8(L, 1, &len); - if (s == NULL || len >= 1024 || len != strlen(s)) { + + if(s == NULL || len >= 1024 || len != strlen(s)) { lua_pushnil(L); return 1; /* TODO return error message */ } + strcpy(string, s); ret = stringprep(string, 1024, (Stringprep_profile_flags)0, profile); - if (ret == STRINGPREP_OK) { + + if(ret == STRINGPREP_OK) { lua_pushstring(L, string); return 1; } else { @@ -319,8 +393,7 @@ MAKE_PREP_FUNC(Lstringprep_nodeprep, stringprep_xmpp_nodeprep) /** stringprep.n MAKE_PREP_FUNC(Lstringprep_resourceprep, stringprep_xmpp_resourceprep) /** stringprep.resourceprep(s) */ MAKE_PREP_FUNC(Lstringprep_saslprep, stringprep_saslprep) /** stringprep.saslprep(s) */ -static const luaL_Reg Reg_stringprep[] = -{ +static const luaL_Reg Reg_stringprep[] = { { "nameprep", Lstringprep_nameprep }, { "nodeprep", Lstringprep_nodeprep }, { "resourceprep", Lstringprep_resourceprep }, @@ -334,8 +407,7 @@ static const luaL_Reg Reg_stringprep[] = #include <unicode/ustdio.h> #include <unicode/uidna.h> /* IDNA2003 or IDNA2008 ? ? ? */ -static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */ -{ +static int Lidna_to_ascii(lua_State *L) { /** idna.to_ascii(s) */ size_t len; int32_t ulen, dest_len, output_len; const char *s = luaL_checklstring(L, 1, &len); @@ -345,27 +417,31 @@ static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */ char output[1024]; u_strFromUTF8(ustr, 1024, &ulen, s, len, &err); - if (U_FAILURE(err)) { + + if(U_FAILURE(err)) { lua_pushnil(L); return 1; } dest_len = uidna_IDNToASCII(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err); - if (U_FAILURE(err)) { + + if(U_FAILURE(err)) { lua_pushnil(L); return 1; } else { u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err); - if (U_SUCCESS(err) && output_len < 1024) + + if(U_SUCCESS(err) && output_len < 1024) { lua_pushlstring(L, output, output_len); - else + } else { lua_pushnil(L); + } + return 1; } } -static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */ -{ +static int Lidna_to_unicode(lua_State *L) { /** idna.to_unicode(s) */ size_t len; int32_t ulen, dest_len, output_len; const char *s = luaL_checklstring(L, 1, &len); @@ -375,21 +451,26 @@ static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */ char output[1024]; u_strFromUTF8(ustr, 1024, &ulen, s, len, &err); - if (U_FAILURE(err)) { + + if(U_FAILURE(err)) { lua_pushnil(L); return 1; } dest_len = uidna_IDNToUnicode(ustr, ulen, dest, 1024, UIDNA_USE_STD3_RULES, NULL, &err); - if (U_FAILURE(err)) { + + if(U_FAILURE(err)) { lua_pushnil(L); return 1; } else { u_strToUTF8(output, 1024, &output_len, dest, dest_len, &err); - if (U_SUCCESS(err) && output_len < 1024) + + if(U_SUCCESS(err) && output_len < 1024) { lua_pushlstring(L, output, output_len); - else + } else { lua_pushnil(L); + } + return 1; } } @@ -400,17 +481,20 @@ static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */ #include <idna.h> #include <idn-free.h> -static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */ -{ +static int Lidna_to_ascii(lua_State *L) { /** idna.to_ascii(s) */ size_t len; const char *s = check_utf8(L, 1, &len); - if (s == NULL || len != strlen(s)) { + char *output = NULL; + int ret; + + if(s == NULL || len != strlen(s)) { lua_pushnil(L); return 1; /* TODO return error message */ } - char* output = NULL; - int ret = idna_to_ascii_8z(s, &output, IDNA_USE_STD3_ASCII_RULES); - if (ret == IDNA_SUCCESS) { + + ret = idna_to_ascii_8z(s, &output, IDNA_USE_STD3_ASCII_RULES); + + if(ret == IDNA_SUCCESS) { lua_pushstring(L, output); idn_free(output); return 1; @@ -421,13 +505,13 @@ static int Lidna_to_ascii(lua_State *L) /** idna.to_ascii(s) */ } } -static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */ -{ +static int Lidna_to_unicode(lua_State *L) { /** idna.to_unicode(s) */ size_t len; const char *s = luaL_checklstring(L, 1, &len); - char* output = NULL; + char *output = NULL; int ret = idna_to_unicode_8z8z(s, &output, 0); - if (ret == IDNA_SUCCESS) { + + if(ret == IDNA_SUCCESS) { lua_pushstring(L, output); idn_free(output); return 1; @@ -439,8 +523,7 @@ static int Lidna_to_unicode(lua_State *L) /** idna.to_unicode(s) */ } #endif -static const luaL_Reg Reg_idna[] = -{ +static const luaL_Reg Reg_idna[] = { { "to_ascii", Lidna_to_ascii }, { "to_unicode", Lidna_to_unicode }, { NULL, NULL } @@ -448,40 +531,32 @@ static const luaL_Reg Reg_idna[] = /***************** end *****************/ -static const luaL_Reg Reg[] = -{ - { NULL, NULL } -}; - -LUALIB_API int luaopen_util_encodings(lua_State *L) -{ +LUALIB_API int luaopen_util_encodings(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif #ifdef USE_STRINGPREP_ICU init_icu(); #endif - luaL_register(L, "encodings", Reg); + lua_newtable(L); - lua_pushliteral(L, "base64"); lua_newtable(L); - luaL_register(L, NULL, Reg_base64); - lua_settable(L,-3); + luaL_setfuncs(L, Reg_base64, 0); + lua_setfield(L, -2, "base64"); - lua_pushliteral(L, "stringprep"); lua_newtable(L); - luaL_register(L, NULL, Reg_stringprep); - lua_settable(L,-3); + luaL_setfuncs(L, Reg_stringprep, 0); + lua_setfield(L, -2, "stringprep"); - lua_pushliteral(L, "idna"); lua_newtable(L); - luaL_register(L, NULL, Reg_idna); - lua_settable(L,-3); + luaL_setfuncs(L, Reg_idna, 0); + lua_setfield(L, -2, "idna"); - lua_pushliteral(L, "utf8"); lua_newtable(L); - luaL_register(L, NULL, Reg_utf8); - lua_settable(L, -3); + luaL_setfuncs(L, Reg_utf8, 0); + lua_setfield(L, -2, "utf8"); - lua_pushliteral(L, "version"); /** version */ lua_pushliteral(L, "-3.14"); - lua_settable(L,-3); + lua_setfield(L, -2, "version"); return 1; } diff --git a/util-src/hashes.c b/util-src/hashes.c index 33041e83..82f5876e 100644 --- a/util-src/hashes.c +++ b/util-src/hashes.c @@ -1,13 +1,12 @@ /* Prosody IM -- Copyright (C) 2009-2010 Matthew Wild -- Copyright (C) 2009-2010 Waqas Hussain --- +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- */ - /* * hashes.c * Lua library for sha1, sha256 and md5 hashes @@ -27,15 +26,20 @@ typedef unsigned __int32 uint32_t; #include <openssl/sha.h> #include <openssl/md5.h> +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + #define HMAC_IPAD 0x36363636 #define HMAC_OPAD 0x5c5c5c5c const char *hex_tab = "0123456789abcdef"; void toHex(const unsigned char *in, int length, unsigned char *out) { int i; - for (i = 0; i < length; i++) { - out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; - out[i*2+1] = hex_tab[(in[i]) & 0xF]; + + for(i = 0; i < length; i++) { + out[i * 2] = hex_tab[(in[i] >> 4) & 0xF]; + out[i * 2 + 1] = hex_tab[(in[i]) & 0xF]; } } @@ -63,16 +67,15 @@ MAKE_HASH_FUNCTION(Lsha512, SHA512, SHA512_DIGEST_LENGTH) MAKE_HASH_FUNCTION(Lmd5, MD5, MD5_DIGEST_LENGTH) struct hash_desc { - int (*Init)(void*); - int (*Update)(void*, const void *, size_t); - int (*Final)(unsigned char*, void*); + int (*Init)(void *); + int (*Update)(void *, const void *, size_t); + int (*Final)(unsigned char *, void *); size_t digestLength; void *ctx, *ctxo; }; static void hmac(struct hash_desc *desc, const char *key, size_t key_len, - const char *msg, size_t msg_len, unsigned char *result) -{ + const char *msg, size_t msg_len, unsigned char *result) { union xory { unsigned char bytes[64]; uint32_t quadbytes[16]; @@ -82,11 +85,11 @@ static void hmac(struct hash_desc *desc, const char *key, size_t key_len, unsigned char hashedKey[64]; /* Maximum used digest length */ union xory k_ipad, k_opad; - if (key_len > 64) { + if(key_len > 64) { desc->Init(desc->ctx); desc->Update(desc->ctx, key, key_len); desc->Final(hashedKey, desc->ctx); - key = (const char*)hashedKey; + key = (const char *)hashedKey; key_len = desc->digestLength; } @@ -94,7 +97,7 @@ static void hmac(struct hash_desc *desc, const char *key, size_t key_len, memset(k_ipad.bytes + key_len, 0, 64 - key_len); memcpy(k_opad.bytes, k_ipad.bytes, 64); - for (i = 0; i < 16; i++) { + for(i = 0; i < 16; i++) { k_ipad.quadbytes[i] ^= HMAC_IPAD; k_opad.quadbytes[i] ^= HMAC_OPAD; } @@ -142,7 +145,7 @@ MAKE_HMAC_FUNCTION(Lhmac_md5, MD5, MD5_DIGEST_LENGTH, MD5_CTX) static int LscramHi(lua_State *L) { union xory { unsigned char bytes[SHA_DIGEST_LENGTH]; - uint32_t quadbytes[SHA_DIGEST_LENGTH/4]; + uint32_t quadbytes[SHA_DIGEST_LENGTH / 4]; }; int i; SHA_CTX ctx, ctxo; @@ -156,37 +159,43 @@ static int LscramHi(lua_State *L) { char *salt2; const int iter = luaL_checkinteger(L, 3); - desc.Init = (int (*)(void*))SHA1_Init; - desc.Update = (int (*)(void*, const void *, size_t))SHA1_Update; - desc.Final = (int (*)(unsigned char*, void*))SHA1_Final; + desc.Init = (int (*)(void *))SHA1_Init; + desc.Update = (int (*)(void *, const void *, size_t))SHA1_Update; + desc.Final = (int (*)(unsigned char *, void *))SHA1_Final; desc.digestLength = SHA_DIGEST_LENGTH; desc.ctx = &ctx; desc.ctxo = &ctxo; salt2 = malloc(salt_len + 4); - if (salt2 == NULL) - luaL_error(L, "Out of memory in scramHi"); + + if(salt2 == NULL) { + return luaL_error(L, "Out of memory in scramHi"); + } + memcpy(salt2, salt, salt_len); memcpy(salt2 + salt_len, "\0\0\0\1", 4); hmac(&desc, str, str_len, salt2, salt_len + 4, Ust); free(salt2); memcpy(res.bytes, Ust, sizeof(res)); - for (i = 1; i < iter; i++) { + + for(i = 1; i < iter; i++) { int j; - hmac(&desc, str, str_len, (char*)Ust, sizeof(Ust), Und.bytes); - for (j = 0; j < SHA_DIGEST_LENGTH/4; j++) + hmac(&desc, str, str_len, (char *)Ust, sizeof(Ust), Und.bytes); + + for(j = 0; j < SHA_DIGEST_LENGTH / 4; j++) { res.quadbytes[j] ^= Und.quadbytes[j]; + } + memcpy(Ust, Und.bytes, sizeof(Ust)); } - lua_pushlstring(L, (char*)res.bytes, SHA_DIGEST_LENGTH); + lua_pushlstring(L, (char *)res.bytes, SHA_DIGEST_LENGTH); return 1; } -static const luaL_Reg Reg[] = -{ +static const luaL_Reg Reg[] = { { "sha1", Lsha1 }, { "sha224", Lsha224 }, { "sha256", Lsha256 }, @@ -201,11 +210,13 @@ static const luaL_Reg Reg[] = { NULL, NULL } }; -LUALIB_API int luaopen_util_hashes(lua_State *L) -{ - luaL_register(L, "hashes", Reg); - lua_pushliteral(L, "version"); /** version */ +LUALIB_API int luaopen_util_hashes(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif + lua_newtable(L); + luaL_setfuncs(L, Reg, 0);; lua_pushliteral(L, "-3.14"); - lua_settable(L,-3); + lua_setfield(L, -2, "version"); return 1; } diff --git a/util-src/net.c b/util-src/net.c index e307c628..bb159d57 100644 --- a/util-src/net.c +++ b/util-src/net.c @@ -9,34 +9,38 @@ -- */ +#define _GNU_SOURCE #include <stddef.h> #include <string.h> #include <errno.h> #ifndef _WIN32 - #include <sys/ioctl.h> - #include <sys/types.h> - #include <sys/socket.h> - #include <net/if.h> - #include <ifaddrs.h> - #include <arpa/inet.h> - #include <netinet/in.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <arpa/inet.h> +#include <netinet/in.h> #endif #include <lua.h> #include <lauxlib.h> +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + /* Enumerate all locally configured IP addresses */ -const char * const type_strings[] = { +const char *const type_strings[] = { "both", "ipv4", "ipv6", NULL }; -static int lc_local_addresses(lua_State *L) -{ +static int lc_local_addresses(lua_State *L) { #ifndef _WIN32 /* Link-local IPv4 addresses; see RFC 3927 and RFC 5735 */ const long ip4_linklocal = htonl(0xa9fe0000); /* 169.254.0.0 */ @@ -50,68 +54,87 @@ static int lc_local_addresses(lua_State *L) const char ipv6 = (type == 0 || type == 2); #ifndef _WIN32 - if (getifaddrs(&addr) < 0) { + + if(getifaddrs(&addr) < 0) { lua_pushnil(L); lua_pushfstring(L, "getifaddrs failed (%d): %s", errno, - strerror(errno)); + strerror(errno)); return 2; } + #endif lua_newtable(L); #ifndef _WIN32 - for (a = addr; a; a = a->ifa_next) { + + for(a = addr; a; a = a->ifa_next) { int family; char ipaddr[INET6_ADDRSTRLEN]; const char *tmp = NULL; - if (a->ifa_addr == NULL || a->ifa_flags & IFF_LOOPBACK) + if(a->ifa_addr == NULL || a->ifa_flags & IFF_LOOPBACK) { continue; + } family = a->ifa_addr->sa_family; - if (ipv4 && family == AF_INET) { + if(ipv4 && family == AF_INET) { struct sockaddr_in *sa = (struct sockaddr_in *)a->ifa_addr; - if (!link_local &&((sa->sin_addr.s_addr & ip4_mask) == ip4_linklocal)) + + if(!link_local && ((sa->sin_addr.s_addr & ip4_mask) == ip4_linklocal)) { continue; + } + tmp = inet_ntop(family, &sa->sin_addr, ipaddr, sizeof(ipaddr)); - } else if (ipv6 && family == AF_INET6) { + } else if(ipv6 && family == AF_INET6) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *)a->ifa_addr; - if (!link_local && IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) + + if(!link_local && IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) { continue; - if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr)) + } + + if(IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr)) { continue; + } + tmp = inet_ntop(family, &sa->sin6_addr, ipaddr, sizeof(ipaddr)); } - if (tmp != NULL) { + if(tmp != NULL) { lua_pushstring(L, tmp); lua_rawseti(L, -2, n++); } + /* TODO: Error reporting? */ } freeifaddrs(addr); #else - if (ipv4) { + + if(ipv4) { lua_pushstring(L, "0.0.0.0"); lua_rawseti(L, -2, n++); } - if (ipv6) { + + if(ipv6) { lua_pushstring(L, "::"); lua_rawseti(L, -2, n++); } + #endif return 1; } -int luaopen_util_net(lua_State* L) -{ +int luaopen_util_net(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif luaL_Reg exports[] = { { "local_addresses", lc_local_addresses }, { NULL, NULL } }; - luaL_register(L, "net", exports); + lua_createtable(L, 0, 1); + luaL_setfuncs(L, exports, 0); return 1; } diff --git a/util-src/pposix.c b/util-src/pposix.c index df814c28..e70a9d7f 100644 --- a/util-src/pposix.c +++ b/util-src/pposix.c @@ -13,7 +13,15 @@ * POSIX support functions for Lua */ -#define MODULE_VERSION "0.3.6" +#define MODULE_VERSION "0.4.0" + + +#if defined(__linux__) +#define _GNU_SOURCE +#else +#define _DEFAULT_SOURCE +#endif +#define _POSIX_C_SOURCE 200809L #include <stdlib.h> #include <math.h> @@ -35,40 +43,52 @@ #include "lualib.h" #include "lauxlib.h" +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + #include <fcntl.h> -#if defined(__linux__) && defined(_GNU_SOURCE) +#if defined(__linux__) #include <linux/falloc.h> #endif -#if (defined(_SVID_SOURCE) && !defined(WITHOUT_MALLINFO)) - #include <malloc.h> - #define WITH_MALLINFO +#if !defined(WITHOUT_MALLINFO) && defined(__linux__) +#include <malloc.h> +#define WITH_MALLINFO +#endif + +#if defined(__FreeBSD__) && defined(RFPROC) +/* + * On FreeBSD, calling fork() is equivalent to rfork(RFPROC | RFFDG). + * + * RFFDG being set means that the file descriptor table is copied, + * otherwise it's shared. We want the later, otherwise libevent gets + * messed up. + * + * See issue #412 + */ +#define fork() rfork(RFPROC) #endif /* Daemonization support */ -static int lc_daemonize(lua_State *L) -{ +static int lc_daemonize(lua_State *L) { pid_t pid; - if ( getppid() == 1 ) - { + if(getppid() == 1) { lua_pushboolean(L, 0); lua_pushstring(L, "already-daemonized"); return 2; } /* Attempt initial fork */ - if((pid = fork()) < 0) - { + if((pid = fork()) < 0) { /* Forking failed */ lua_pushboolean(L, 0); lua_pushstring(L, "fork-failed"); return 2; - } - else if(pid != 0) - { + } else if(pid != 0) { /* We are the parent process */ lua_pushboolean(L, 1); lua_pushnumber(L, pid); @@ -76,8 +96,7 @@ static int lc_daemonize(lua_State *L) } /* and we are the child process */ - if(setsid() == -1) - { + if(setsid() == -1) { /* We failed to become session leader */ /* (we probably already were) */ lua_pushboolean(L, 0); @@ -95,8 +114,9 @@ static int lc_daemonize(lua_State *L) open("/dev/null", O_WRONLY); /* Final fork, use it wisely */ - if(fork()) + if(fork()) { exit(0); + } /* Show's over, let's continue */ lua_pushboolean(L, 1); @@ -106,59 +126,59 @@ static int lc_daemonize(lua_State *L) /* Syslog support */ -const char * const facility_strings[] = { - "auth", +const char *const facility_strings[] = { + "auth", #if !(defined(sun) || defined(__sun)) - "authpriv", + "authpriv", #endif - "cron", - "daemon", + "cron", + "daemon", #if !(defined(sun) || defined(__sun)) - "ftp", + "ftp", #endif - "kern", - "local0", - "local1", - "local2", - "local3", - "local4", - "local5", - "local6", - "local7", - "lpr", - "mail", - "syslog", - "user", - "uucp", - NULL - }; + "kern", + "local0", + "local1", + "local2", + "local3", + "local4", + "local5", + "local6", + "local7", + "lpr", + "mail", + "syslog", + "user", + "uucp", + NULL +}; int facility_constants[] = { - LOG_AUTH, + LOG_AUTH, #if !(defined(sun) || defined(__sun)) - LOG_AUTHPRIV, + LOG_AUTHPRIV, #endif - LOG_CRON, - LOG_DAEMON, + LOG_CRON, + LOG_DAEMON, #if !(defined(sun) || defined(__sun)) - LOG_FTP, + LOG_FTP, #endif - LOG_KERN, - LOG_LOCAL0, - LOG_LOCAL1, - LOG_LOCAL2, - LOG_LOCAL3, - LOG_LOCAL4, - LOG_LOCAL5, - LOG_LOCAL6, - LOG_LOCAL7, - LOG_LPR, - LOG_MAIL, - LOG_NEWS, - LOG_SYSLOG, - LOG_USER, - LOG_UUCP, - -1 - }; + LOG_KERN, + LOG_LOCAL0, + LOG_LOCAL1, + LOG_LOCAL2, + LOG_LOCAL3, + LOG_LOCAL4, + LOG_LOCAL5, + LOG_LOCAL6, + LOG_LOCAL7, + LOG_LPR, + LOG_MAIL, + LOG_NEWS, + LOG_SYSLOG, + LOG_USER, + LOG_UUCP, + -1 +}; /* " The parameter ident in the call of openlog() is probably stored as-is. @@ -168,17 +188,17 @@ int facility_constants[] = { constant. " -- syslog manpage */ -char* syslog_ident = NULL; +char *syslog_ident = NULL; -int lc_syslog_open(lua_State* L) -{ +int lc_syslog_open(lua_State *L) { int facility = luaL_checkoption(L, 2, "daemon", facility_strings); facility = facility_constants[facility]; luaL_checkstring(L, 1); - if(syslog_ident) + if(syslog_ident) { free(syslog_ident); + } syslog_ident = strdup(lua_tostring(L, 1)); @@ -186,53 +206,52 @@ int lc_syslog_open(lua_State* L) return 0; } -const char * const level_strings[] = { - "debug", - "info", - "notice", - "warn", - "error", - NULL - }; +const char *const level_strings[] = { + "debug", + "info", + "notice", + "warn", + "error", + NULL +}; int level_constants[] = { - LOG_DEBUG, - LOG_INFO, - LOG_NOTICE, - LOG_WARNING, - LOG_CRIT, - -1 - }; -int lc_syslog_log(lua_State* L) -{ + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_WARNING, + LOG_CRIT, + -1 +}; +int lc_syslog_log(lua_State *L) { int level = level_constants[luaL_checkoption(L, 1, "notice", level_strings)]; - if(lua_gettop(L) == 3) + if(lua_gettop(L) == 3) { syslog(level, "%s: %s", luaL_checkstring(L, 2), luaL_checkstring(L, 3)); - else + } else { syslog(level, "%s", lua_tostring(L, 2)); + } return 0; } -int lc_syslog_close(lua_State* L) -{ +int lc_syslog_close(lua_State *L) { closelog(); - if(syslog_ident) - { + + if(syslog_ident) { free(syslog_ident); syslog_ident = NULL; } + return 0; } -int lc_syslog_setmask(lua_State* L) -{ +int lc_syslog_setmask(lua_State *L) { int level_idx = luaL_checkoption(L, 1, "notice", level_strings); int mask = 0; - do - { + + do { mask |= LOG_MASK(level_constants[level_idx]); - } while (++level_idx<=4); + } while(++level_idx <= 4); setlogmask(mask); return 0; @@ -240,72 +259,69 @@ int lc_syslog_setmask(lua_State* L) /* getpid */ -int lc_getpid(lua_State* L) -{ +int lc_getpid(lua_State *L) { lua_pushinteger(L, getpid()); return 1; } /* UID/GID functions */ -int lc_getuid(lua_State* L) -{ +int lc_getuid(lua_State *L) { lua_pushinteger(L, getuid()); return 1; } -int lc_getgid(lua_State* L) -{ +int lc_getgid(lua_State *L) { lua_pushinteger(L, getgid()); return 1; } -int lc_setuid(lua_State* L) -{ +int lc_setuid(lua_State *L) { int uid = -1; - if(lua_gettop(L) < 1) + + if(lua_gettop(L) < 1) { return 0; - if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) - { + } + + if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) { /* Passed UID is actually a string, so look up the UID */ struct passwd *p; p = getpwnam(lua_tostring(L, 1)); - if(!p) - { + + if(!p) { lua_pushboolean(L, 0); lua_pushstring(L, "no-such-user"); return 2; } + uid = p->pw_uid; - } - else - { + } else { uid = lua_tonumber(L, 1); } - if(uid>-1) - { + if(uid > -1) { /* Ok, attempt setuid */ errno = 0; - if(setuid(uid)) - { + + if(setuid(uid)) { /* Fail */ lua_pushboolean(L, 0); - switch(errno) - { - case EINVAL: - lua_pushstring(L, "invalid-uid"); - break; - case EPERM: - lua_pushstring(L, "permission-denied"); - break; - default: - lua_pushstring(L, "unknown-error"); + + switch(errno) { + case EINVAL: + lua_pushstring(L, "invalid-uid"); + break; + + case EPERM: + lua_pushstring(L, "permission-denied"); + break; + + default: + lua_pushstring(L, "unknown-error"); } + return 2; - } - else - { + } else { /* Success! */ lua_pushboolean(L, 1); return 1; @@ -318,52 +334,52 @@ int lc_setuid(lua_State* L) return 2; } -int lc_setgid(lua_State* L) -{ +int lc_setgid(lua_State *L) { int gid = -1; - if(lua_gettop(L) < 1) + + if(lua_gettop(L) < 1) { return 0; - if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) - { + } + + if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) { /* Passed GID is actually a string, so look up the GID */ struct group *g; g = getgrnam(lua_tostring(L, 1)); - if(!g) - { + + if(!g) { lua_pushboolean(L, 0); lua_pushstring(L, "no-such-group"); return 2; } + gid = g->gr_gid; - } - else - { + } else { gid = lua_tonumber(L, 1); } - if(gid>-1) - { + if(gid > -1) { /* Ok, attempt setgid */ errno = 0; - if(setgid(gid)) - { + + if(setgid(gid)) { /* Fail */ lua_pushboolean(L, 0); - switch(errno) - { - case EINVAL: - lua_pushstring(L, "invalid-gid"); - break; - case EPERM: - lua_pushstring(L, "permission-denied"); - break; - default: - lua_pushstring(L, "unknown-error"); + + switch(errno) { + case EINVAL: + lua_pushstring(L, "invalid-gid"); + break; + + case EPERM: + lua_pushstring(L, "permission-denied"); + break; + + default: + lua_pushstring(L, "unknown-error"); } + return 2; - } - else - { + } else { /* Success! */ lua_pushboolean(L, 1); return 1; @@ -376,90 +392,93 @@ int lc_setgid(lua_State* L) return 2; } -int lc_initgroups(lua_State* L) -{ +int lc_initgroups(lua_State *L) { int ret; gid_t gid; struct passwd *p; - if(!lua_isstring(L, 1)) - { + if(!lua_isstring(L, 1)) { lua_pushnil(L); lua_pushstring(L, "invalid-username"); return 2; } + p = getpwnam(lua_tostring(L, 1)); - if(!p) - { + + if(!p) { lua_pushnil(L); lua_pushstring(L, "no-such-user"); return 2; } - if(lua_gettop(L) < 2) - lua_pushnil(L); - switch(lua_type(L, 2)) - { - case LUA_TNIL: - gid = p->pw_gid; - break; - case LUA_TNUMBER: - gid = lua_tointeger(L, 2); - break; - default: + + if(lua_gettop(L) < 2) { lua_pushnil(L); - lua_pushstring(L, "invalid-gid"); - return 2; } - ret = initgroups(lua_tostring(L, 1), gid); - if(ret) - { - switch(errno) - { - case ENOMEM: - lua_pushnil(L); - lua_pushstring(L, "no-memory"); + + switch(lua_type(L, 2)) { + case LUA_TNIL: + gid = p->pw_gid; break; - case EPERM: - lua_pushnil(L); - lua_pushstring(L, "permission-denied"); + + case LUA_TNUMBER: + gid = lua_tointeger(L, 2); break; + default: lua_pushnil(L); - lua_pushstring(L, "unknown-error"); - } + lua_pushstring(L, "invalid-gid"); + return 2; } - else - { + + ret = initgroups(lua_tostring(L, 1), gid); + + if(ret) { + switch(errno) { + case ENOMEM: + lua_pushnil(L); + lua_pushstring(L, "no-memory"); + break; + + case EPERM: + lua_pushnil(L); + lua_pushstring(L, "permission-denied"); + break; + + default: + lua_pushnil(L); + lua_pushstring(L, "unknown-error"); + } + } else { lua_pushboolean(L, 1); lua_pushnil(L); } + return 2; } -int lc_umask(lua_State* L) -{ +int lc_umask(lua_State *L) { char old_mode_string[7]; mode_t old_mode = umask(strtoul(luaL_checkstring(L, 1), NULL, 8)); snprintf(old_mode_string, sizeof(old_mode_string), "%03o", old_mode); - old_mode_string[sizeof(old_mode_string)-1] = 0; + old_mode_string[sizeof(old_mode_string) - 1] = 0; lua_pushstring(L, old_mode_string); return 1; } -int lc_mkdir(lua_State* L) -{ +int lc_mkdir(lua_State *L) { int ret = mkdir(luaL_checkstring(L, 1), S_IRUSR | S_IWUSR | S_IXUSR - | S_IRGRP | S_IWGRP | S_IXGRP - | S_IROTH | S_IXOTH); /* mode 775 */ + | S_IRGRP | S_IWGRP | S_IXGRP + | S_IROTH | S_IXOTH); /* mode 775 */ + + lua_pushboolean(L, ret == 0); - lua_pushboolean(L, ret==0); - if(ret) - { + if(ret) { lua_pushstring(L, strerror(errno)); return 2; } + return 1; } @@ -474,68 +493,110 @@ int lc_mkdir(lua_State* L) * pposix.setrlimit("NOFILE", 1000, 2000) */ int string2resource(const char *s) { - if (!strcmp(s, "CORE")) return RLIMIT_CORE; - if (!strcmp(s, "CPU")) return RLIMIT_CPU; - if (!strcmp(s, "DATA")) return RLIMIT_DATA; - if (!strcmp(s, "FSIZE")) return RLIMIT_FSIZE; - if (!strcmp(s, "NOFILE")) return RLIMIT_NOFILE; - if (!strcmp(s, "STACK")) return RLIMIT_STACK; + if(!strcmp(s, "CORE")) { + return RLIMIT_CORE; + } + + if(!strcmp(s, "CPU")) { + return RLIMIT_CPU; + } + + if(!strcmp(s, "DATA")) { + return RLIMIT_DATA; + } + + if(!strcmp(s, "FSIZE")) { + return RLIMIT_FSIZE; + } + + if(!strcmp(s, "NOFILE")) { + return RLIMIT_NOFILE; + } + + if(!strcmp(s, "STACK")) { + return RLIMIT_STACK; + } + #if !(defined(sun) || defined(__sun)) - if (!strcmp(s, "MEMLOCK")) return RLIMIT_MEMLOCK; - if (!strcmp(s, "NPROC")) return RLIMIT_NPROC; - if (!strcmp(s, "RSS")) return RLIMIT_RSS; + + if(!strcmp(s, "MEMLOCK")) { + return RLIMIT_MEMLOCK; + } + + if(!strcmp(s, "NPROC")) { + return RLIMIT_NPROC; + } + + if(!strcmp(s, "RSS")) { + return RLIMIT_RSS; + } + #endif #ifdef RLIMIT_NICE - if (!strcmp(s, "NICE")) return RLIMIT_NICE; + + if(!strcmp(s, "NICE")) { + return RLIMIT_NICE; + } + #endif return -1; } +rlim_t arg_to_rlimit(lua_State *L, int idx, rlim_t current) { + switch(lua_type(L, idx)) { + case LUA_TSTRING: + + if(strcmp(lua_tostring(L, idx), "unlimited") == 0) { + return RLIM_INFINITY; + } + + case LUA_TNUMBER: + return lua_tointeger(L, idx); + + case LUA_TNONE: + case LUA_TNIL: + return current; + + default: + return luaL_argerror(L, idx, "unexpected type"); + } +} + int lc_setrlimit(lua_State *L) { + struct rlimit lim; int arguments = lua_gettop(L); - int softlimit = -1; - int hardlimit = -1; - const char *resource = NULL; int rid = -1; + if(arguments < 1 || arguments > 3) { lua_pushboolean(L, 0); lua_pushstring(L, "incorrect-arguments"); return 2; } - resource = luaL_checkstring(L, 1); - softlimit = luaL_checkinteger(L, 2); - hardlimit = luaL_checkinteger(L, 3); + rid = string2resource(luaL_checkstring(L, 1)); - rid = string2resource(resource); - if (rid != -1) { - struct rlimit lim; - struct rlimit lim_current; - - if (softlimit < 0 || hardlimit < 0) { - if (getrlimit(rid, &lim_current)) { - lua_pushboolean(L, 0); - lua_pushstring(L, "getrlimit-failed"); - return 2; - } - } + if(rid == -1) { + lua_pushboolean(L, 0); + lua_pushstring(L, "invalid-resource"); + return 2; + } - if (softlimit < 0) lim.rlim_cur = lim_current.rlim_cur; - else lim.rlim_cur = softlimit; - if (hardlimit < 0) lim.rlim_max = lim_current.rlim_max; - else lim.rlim_max = hardlimit; + /* Fetch current values to use as defaults */ + if(getrlimit(rid, &lim)) { + lua_pushboolean(L, 0); + lua_pushstring(L, "getrlimit-failed"); + return 2; + } - if (setrlimit(rid, &lim)) { - lua_pushboolean(L, 0); - lua_pushstring(L, "setrlimit-failed"); - return 2; - } - } else { - /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */ + lim.rlim_cur = arg_to_rlimit(L, 2, lim.rlim_cur); + lim.rlim_max = arg_to_rlimit(L, 3, lim.rlim_max); + + if(setrlimit(rid, &lim)) { lua_pushboolean(L, 0); - lua_pushstring(L, "invalid-resource"); + lua_pushstring(L, "setrlimit-failed"); return 2; } + lua_pushboolean(L, 1); return 1; } @@ -546,7 +607,7 @@ int lc_getrlimit(lua_State *L) { int rid = -1; struct rlimit lim; - if (arguments != 1) { + if(arguments != 1) { lua_pushboolean(L, 0); lua_pushstring(L, "invalid-arguments"); return 2; @@ -554,40 +615,52 @@ int lc_getrlimit(lua_State *L) { resource = luaL_checkstring(L, 1); rid = string2resource(resource); - if (rid != -1) { - if (getrlimit(rid, &lim)) { + + if(rid != -1) { + if(getrlimit(rid, &lim)) { lua_pushboolean(L, 0); lua_pushstring(L, "getrlimit-failed."); return 2; } } else { - /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */ + /* Unsupported resource. Sorry I'm pretty limited by POSIX standard. */ lua_pushboolean(L, 0); lua_pushstring(L, "invalid-resource"); return 2; } + lua_pushboolean(L, 1); - lua_pushnumber(L, lim.rlim_cur); - lua_pushnumber(L, lim.rlim_max); + + if(lim.rlim_cur == RLIM_INFINITY) { + lua_pushstring(L, "unlimited"); + } else { + lua_pushnumber(L, lim.rlim_cur); + } + + if(lim.rlim_max == RLIM_INFINITY) { + lua_pushstring(L, "unlimited"); + } else { + lua_pushnumber(L, lim.rlim_max); + } + return 3; } -int lc_abort(lua_State* L) -{ +int lc_abort(lua_State *L) { abort(); return 0; } -int lc_uname(lua_State* L) -{ +int lc_uname(lua_State *L) { struct utsname uname_info; - if(uname(&uname_info) != 0) - { + + if(uname(&uname_info) != 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; } - lua_newtable(L); + + lua_createtable(L, 0, 6); lua_pushstring(L, uname_info.sysname); lua_setfield(L, -2, "sysname"); lua_pushstring(L, uname_info.nodename); @@ -598,31 +671,32 @@ int lc_uname(lua_State* L) lua_setfield(L, -2, "version"); lua_pushstring(L, uname_info.machine); lua_setfield(L, -2, "machine"); +#ifdef __USE_GNU + lua_pushstring(L, uname_info.domainname); + lua_setfield(L, -2, "domainname"); +#endif return 1; } -int lc_setenv(lua_State* L) -{ +int lc_setenv(lua_State *L) { const char *var = luaL_checkstring(L, 1); const char *value; /* If the second argument is nil or nothing, unset the var */ - if(lua_isnoneornil(L, 2)) - { - if(unsetenv(var) != 0) - { + if(lua_isnoneornil(L, 2)) { + if(unsetenv(var) != 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; } + lua_pushboolean(L, 1); return 1; } value = luaL_checkstring(L, 2); - if(setenv(var, value, 1) != 0) - { + if(setenv(var, value, 1) != 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; @@ -633,10 +707,9 @@ int lc_setenv(lua_State* L) } #ifdef WITH_MALLINFO -int lc_meminfo(lua_State* L) -{ +int lc_meminfo(lua_State *L) { struct mallinfo info = mallinfo(); - lua_newtable(L); + lua_createtable(L, 0, 5); /* This is the total size of memory allocated with sbrk by malloc, in bytes. */ lua_pushinteger(L, info.arena); lua_setfield(L, -2, "allocated"); @@ -657,67 +730,74 @@ int lc_meminfo(lua_State* L) } #endif -/* File handle extraction blatantly stolen from - * https://github.com/rrthomas/luaposix/blob/master/lposix.c#L631 - * */ +/* + * Append some data to a file handle + * Attempt to allocate space first + * Truncate to original size on failure + */ +int lc_atomic_append(lua_State *L) { + int err; + size_t len; -#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L || defined(_GNU_SOURCE) -int lc_fallocate(lua_State* L) -{ - int ret; - off_t offset, len; - FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE); - if (f == NULL) - luaL_error(L, "attempt to use a closed file"); - - offset = luaL_checkinteger(L, 2); - len = luaL_checkinteger(L, 3); - -#if defined(__linux__) && defined(_GNU_SOURCE) - errno = 0; - ret = fallocate(fileno(f), FALLOC_FL_KEEP_SIZE, offset, len); - if(ret == 0) - { - lua_pushboolean(L, 1); - return 1; - } - /* Some old versions of Linux apparently use the return value instead of errno */ - if(errno == 0) errno = ret; + FILE *f = *(FILE **) luaL_checkudata(L, 1, LUA_FILEHANDLE); + const char *data = luaL_checklstring(L, 2, &len); - if(errno != ENOSYS && errno != EOPNOTSUPP) - { - lua_pushnil(L); - lua_pushstring(L, strerror(errno)); - return 2; + off_t offset = ftell(f); + +#if defined(__linux__) + /* Try to allocate space without changing the file size. */ + if((err = fallocate(fileno(f), FALLOC_FL_KEEP_SIZE, offset, len))) { + if(errno != 0) { + /* Some old versions of Linux apparently use the return value instead of errno */ + err = errno; + } + switch(err) { + case ENOSYS: /* Kernel doesn't implement fallocate */ + case EOPNOTSUPP: /* Filesystem doesn't support it */ + /* Ignore and proceed to try to write */ + break; + + case ENOSPC: /* No space left */ + default: /* Other issues */ + lua_pushnil(L); + lua_pushstring(L, strerror(err)); + lua_pushinteger(L, err); + return 3; + } } -#else -#warning Only using posix_fallocate() fallback. -#warning Linux fallocate() is strongly recommended if available: recompile with -D_GNU_SOURCE -#warning Note that posix_fallocate() will still be used on filesystems that dont support fallocate() #endif - ret = posix_fallocate(fileno(f), offset, len); - if(ret == 0) - { - lua_pushboolean(L, 1); - return 1; + if(fwrite(data, sizeof(char), len, f) == len) { + if(fflush(f) == 0) { + lua_pushboolean(L, 1); /* Great success! */ + return 1; + } else { + err = errno; + } + } else { + err = ferror(f); } - else - { - lua_pushnil(L); - lua_pushstring(L, strerror(ret)); - /* posix_fallocate() can leave a bunch of NULs at the end, so we cut that - * this assumes that offset == length of the file */ - ftruncate(fileno(f), offset); - return 2; + + fseek(f, offset, SEEK_SET); + + /* Cut partially written data */ + if(ftruncate(fileno(f), offset)) { + /* The file is now most likely corrupted, throw hard error */ + return luaL_error(L, "atomic_append() failed in ftruncate(): %s", strerror(errno)); } + + lua_pushnil(L); + lua_pushstring(L, strerror(err)); + lua_pushinteger(L, err); + return 3; } -#endif /* Register functions */ -int luaopen_util_pposix(lua_State *L) -{ +int luaopen_util_pposix(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif luaL_Reg exports[] = { { "abort", lc_abort }, @@ -751,14 +831,18 @@ int luaopen_util_pposix(lua_State *L) { "meminfo", lc_meminfo }, #endif -#if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L || defined(_GNU_SOURCE) - { "fallocate", lc_fallocate }, -#endif + { "atomic_append", lc_atomic_append }, { NULL, NULL } }; - luaL_register(L, "pposix", exports); + lua_newtable(L); + luaL_setfuncs(L, exports, 0); + +#ifdef ENOENT + lua_pushinteger(L, ENOENT); + lua_setfield(L, -2, "ENOENT"); +#endif lua_pushliteral(L, "pposix"); lua_setfield(L, -2, "_NAME"); diff --git a/util-src/ringbuffer.c b/util-src/ringbuffer.c new file mode 100644 index 00000000..8d9e49e6 --- /dev/null +++ b/util-src/ringbuffer.c @@ -0,0 +1,214 @@ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <lua.h> +#include <lauxlib.h> + +typedef struct { + size_t rpos; /* read position */ + size_t wpos; /* write position */ + size_t alen; /* allocated size */ + size_t blen; /* current content size */ + char buffer[]; +} ringbuffer; + +char readchar(ringbuffer *b) { + b->blen--; + return b->buffer[(b->rpos++) % b->alen]; +} + +void writechar(ringbuffer *b, char c) { + b->blen++; + b->buffer[(b->wpos++) % b->alen] = c; +} + +/* make sure position counters stay within the allocation */ +void modpos(ringbuffer *b) { + b->rpos = b->rpos % b->alen; + b->wpos = b->wpos % b->alen; +} + +int find(ringbuffer *b, const char *s, size_t l) { + size_t i, j; + int m; + + if(b->rpos == b->wpos) { /* empty */ + return 0; + } + + for(i = 0; i <= b->blen - l; i++) { + if(b->buffer[(b->rpos + i) % b->alen] == *s) { + m = 1; + + for(j = 1; j < l; j++) + if(b->buffer[(b->rpos + i + j) % b->alen] != s[j]) { + m = 0; + break; + } + + if(m) { + return i + l; + } + } + } + + return 0; +} + +int rb_find(lua_State *L) { + size_t l, m; + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + const char *s = luaL_checklstring(L, 2, &l); + m = find(b, s, l); + + if(m > 0) { + lua_pushinteger(L, m); + return 1; + } + + return 0; +} + +int rb_read(lua_State *L) { + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + size_t r = luaL_checkinteger(L, 2); + int peek = lua_toboolean(L, 3); + + if(r > b->blen) { + lua_pushnil(L); + return 1; + } + + if((b->rpos + r) > b->alen) { + lua_pushlstring(L, &b->buffer[b->rpos], b->alen - b->rpos); + lua_pushlstring(L, b->buffer, r - (b->alen - b->rpos)); + lua_concat(L, 2); + } else { + lua_pushlstring(L, &b->buffer[b->rpos], r); + } + + if(!peek) { + b->blen -= r; + b->rpos += r; + modpos(b); + } + + return 1; +} + +int rb_readuntil(lua_State *L) { + size_t l, m; + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + const char *s = luaL_checklstring(L, 2, &l); + m = find(b, s, l); + + if(m > 0) { + lua_settop(L, 1); + lua_pushinteger(L, m); + return rb_read(L); + } + + return 0; +} + +int rb_write(lua_State *L) { + size_t l, w = 0; + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + const char *s = luaL_checklstring(L, 2, &l); + + /* Does `l` bytes fit? */ + if((l + b->blen) > b->alen) { + lua_pushnil(L); + return 1; + } + + while(l-- > 0) { + writechar(b, *s++); + w++; + } + + modpos(b); + + lua_pushinteger(L, w); + + return 1; +} + +int rb_tostring(lua_State *L) { + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + lua_pushfstring(L, "ringbuffer: %p %d/%d", b, b->blen, b->alen); + return 1; +} + +int rb_length(lua_State *L) { + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + lua_pushinteger(L, b->blen); + return 1; +} + +int rb_size(lua_State *L) { + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + lua_pushinteger(L, b->alen); + return 1; +} + +int rb_free(lua_State *L) { + ringbuffer *b = luaL_checkudata(L, 1, "ringbuffer_mt"); + lua_pushinteger(L, b->alen - b->blen); + return 1; +} + +int rb_new(lua_State *L) { + size_t size = luaL_optinteger(L, 1, sysconf(_SC_PAGESIZE)); + ringbuffer *b = lua_newuserdata(L, sizeof(ringbuffer) + size); + + b->rpos = 0; + b->wpos = 0; + b->alen = size; + b->blen = 0; + + luaL_getmetatable(L, "ringbuffer_mt"); + lua_setmetatable(L, -2); + + return 1; +} + +int luaopen_util_ringbuffer(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif + + if(luaL_newmetatable(L, "ringbuffer_mt")) { + lua_pushcfunction(L, rb_tostring); + lua_setfield(L, -2, "__tostring"); + lua_pushcfunction(L, rb_length); + lua_setfield(L, -2, "__len"); + + lua_createtable(L, 0, 7); /* __index */ + { + lua_pushcfunction(L, rb_find); + lua_setfield(L, -2, "find"); + lua_pushcfunction(L, rb_read); + lua_setfield(L, -2, "read"); + lua_pushcfunction(L, rb_readuntil); + lua_setfield(L, -2, "readuntil"); + lua_pushcfunction(L, rb_write); + lua_setfield(L, -2, "write"); + lua_pushcfunction(L, rb_size); + lua_setfield(L, -2, "size"); + lua_pushcfunction(L, rb_length); + lua_setfield(L, -2, "length"); + lua_pushcfunction(L, rb_free); + lua_setfield(L, -2, "free"); + } + lua_setfield(L, -2, "__index"); + } + + lua_createtable(L, 0, 1); + lua_pushcfunction(L, rb_new); + lua_setfield(L, -2, "new"); + return 1; +} diff --git a/util-src/signal.c b/util-src/signal.c index 961d2d3e..2268e11c 100644 --- a/util-src/signal.c +++ b/util-src/signal.c @@ -23,23 +23,28 @@ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. + * OTHER DEALINGS IN THE SOFTWARE. */ +#define _GNU_SOURCE + #include <signal.h> #include <stdlib.h> #include "lua.h" #include "lauxlib.h" +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + #ifndef lsig #define lsig -struct lua_signal -{ - char *name; /* name of the signal */ - int sig; /* the signal */ +struct lua_signal { + char *name; /* name of the signal */ + int sig; /* the signal */ }; #endif @@ -47,107 +52,107 @@ struct lua_signal #define LUA_SIGNAL "lua_signal" static const struct lua_signal lua_signals[] = { - /* ANSI C signals */ + /* ANSI C signals */ #ifdef SIGABRT - {"SIGABRT", SIGABRT}, + {"SIGABRT", SIGABRT}, #endif #ifdef SIGFPE - {"SIGFPE", SIGFPE}, + {"SIGFPE", SIGFPE}, #endif #ifdef SIGILL - {"SIGILL", SIGILL}, + {"SIGILL", SIGILL}, #endif #ifdef SIGINT - {"SIGINT", SIGINT}, + {"SIGINT", SIGINT}, #endif #ifdef SIGSEGV - {"SIGSEGV", SIGSEGV}, + {"SIGSEGV", SIGSEGV}, #endif #ifdef SIGTERM - {"SIGTERM", SIGTERM}, + {"SIGTERM", SIGTERM}, #endif - /* posix signals */ + /* posix signals */ #ifdef SIGHUP - {"SIGHUP", SIGHUP}, + {"SIGHUP", SIGHUP}, #endif #ifdef SIGQUIT - {"SIGQUIT", SIGQUIT}, + {"SIGQUIT", SIGQUIT}, #endif #ifdef SIGTRAP - {"SIGTRAP", SIGTRAP}, + {"SIGTRAP", SIGTRAP}, #endif #ifdef SIGKILL - {"SIGKILL", SIGKILL}, + {"SIGKILL", SIGKILL}, #endif #ifdef SIGUSR1 - {"SIGUSR1", SIGUSR1}, + {"SIGUSR1", SIGUSR1}, #endif #ifdef SIGUSR2 - {"SIGUSR2", SIGUSR2}, + {"SIGUSR2", SIGUSR2}, #endif #ifdef SIGPIPE - {"SIGPIPE", SIGPIPE}, + {"SIGPIPE", SIGPIPE}, #endif #ifdef SIGALRM - {"SIGALRM", SIGALRM}, + {"SIGALRM", SIGALRM}, #endif #ifdef SIGCHLD - {"SIGCHLD", SIGCHLD}, + {"SIGCHLD", SIGCHLD}, #endif #ifdef SIGCONT - {"SIGCONT", SIGCONT}, + {"SIGCONT", SIGCONT}, #endif #ifdef SIGSTOP - {"SIGSTOP", SIGSTOP}, + {"SIGSTOP", SIGSTOP}, #endif #ifdef SIGTTIN - {"SIGTTIN", SIGTTIN}, + {"SIGTTIN", SIGTTIN}, #endif #ifdef SIGTTOU - {"SIGTTOU", SIGTTOU}, + {"SIGTTOU", SIGTTOU}, #endif - /* some BSD signals */ + /* some BSD signals */ #ifdef SIGIOT - {"SIGIOT", SIGIOT}, + {"SIGIOT", SIGIOT}, #endif #ifdef SIGBUS - {"SIGBUS", SIGBUS}, + {"SIGBUS", SIGBUS}, #endif #ifdef SIGCLD - {"SIGCLD", SIGCLD}, + {"SIGCLD", SIGCLD}, #endif #ifdef SIGURG - {"SIGURG", SIGURG}, + {"SIGURG", SIGURG}, #endif #ifdef SIGXCPU - {"SIGXCPU", SIGXCPU}, + {"SIGXCPU", SIGXCPU}, #endif #ifdef SIGXFSZ - {"SIGXFSZ", SIGXFSZ}, + {"SIGXFSZ", SIGXFSZ}, #endif #ifdef SIGVTALRM - {"SIGVTALRM", SIGVTALRM}, + {"SIGVTALRM", SIGVTALRM}, #endif #ifdef SIGPROF - {"SIGPROF", SIGPROF}, + {"SIGPROF", SIGPROF}, #endif #ifdef SIGWINCH - {"SIGWINCH", SIGWINCH}, + {"SIGWINCH", SIGWINCH}, #endif #ifdef SIGPOLL - {"SIGPOLL", SIGPOLL}, + {"SIGPOLL", SIGPOLL}, #endif #ifdef SIGIO - {"SIGIO", SIGIO}, + {"SIGIO", SIGIO}, #endif - /* add odd signals */ + /* add odd signals */ #ifdef SIGSTKFLT - {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */ + {"SIGSTKFLT", SIGSTKFLT}, /* stack fault */ #endif #ifdef SIGSYS - {"SIGSYS", SIGSYS}, + {"SIGSYS", SIGSYS}, #endif - {NULL, 0} + {NULL, 0} }; static lua_State *Lsig = NULL; @@ -155,62 +160,55 @@ static lua_Hook Hsig = NULL; static int Hmask = 0; static int Hcount = 0; -static struct signal_event -{ +static struct signal_event { int Nsig; struct signal_event *next_event; } *signal_queue = NULL; static struct signal_event *last_event = NULL; -static void sighook(lua_State *L, lua_Debug *ar) -{ - struct signal_event *event; - /* restore the old hook */ - lua_sethook(L, Hsig, Hmask, Hcount); +static void sighook(lua_State *L, lua_Debug *ar) { + struct signal_event *event; + /* restore the old hook */ + lua_sethook(L, Hsig, Hmask, Hcount); - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); - while((event = signal_queue)) - { - lua_pushnumber(L, event->Nsig); - lua_gettable(L, -2); - lua_call(L, 0, 0); - signal_queue = event->next_event; - free(event); - }; + while((event = signal_queue)) { + lua_pushnumber(L, event->Nsig); + lua_gettable(L, -2); + lua_call(L, 0, 0); + signal_queue = event->next_event; + free(event); + }; - lua_pop(L, 1); /* pop lua_signal table */ + lua_pop(L, 1); /* pop lua_signal table */ } -static void handle(int sig) -{ - if(!signal_queue) - { - /* Store the existing debug hook (if any) and its parameters */ - Hsig = lua_gethook(Lsig); - Hmask = lua_gethookmask(Lsig); - Hcount = lua_gethookcount(Lsig); - - signal_queue = malloc(sizeof(struct signal_event)); - signal_queue->Nsig = sig; - signal_queue->next_event = NULL; - - last_event = signal_queue; - - /* Set our new debug hook */ - lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); - } - else - { - last_event->next_event = malloc(sizeof(struct signal_event)); - last_event->next_event->Nsig = sig; - last_event->next_event->next_event = NULL; - - last_event = last_event->next_event; - } +static void handle(int sig) { + if(!signal_queue) { + /* Store the existing debug hook (if any) and its parameters */ + Hsig = lua_gethook(Lsig); + Hmask = lua_gethookmask(Lsig); + Hcount = lua_gethookcount(Lsig); + + signal_queue = malloc(sizeof(struct signal_event)); + signal_queue->Nsig = sig; + signal_queue->next_event = NULL; + + last_event = signal_queue; + + /* Set our new debug hook */ + lua_sethook(Lsig, sighook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); + } else { + last_event->next_event = malloc(sizeof(struct signal_event)); + last_event->next_event->Nsig = sig; + last_event->next_event->next_event = NULL; + + last_event = last_event->next_event; + } } /* @@ -222,108 +220,113 @@ static void handle(int sig) * if caught, Lua function _must_ * exit, as the stack is most likely * in an unstable state. -*/ - -static int l_signal(lua_State *L) -{ - int args = lua_gettop(L); - int t, sig; /* type, signal */ - - /* get type of signal */ - luaL_checkany(L, 1); - t = lua_type(L, 1); - if (t == LUA_TNUMBER) - sig = (int) lua_tonumber(L, 1); - else if (t == LUA_TSTRING) - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 1); - lua_gettable(L, -2); - if (!lua_isnumber(L, -1)) - luaL_error(L, "invalid signal string"); - sig = (int) lua_tonumber(L, -1); - lua_pop(L, 1); /* get rid of number we pushed */ - } else - luaL_checknumber(L, 1); /* will always error, with good error msg */ - - /* set handler */ - if (args == 1 || lua_isnil(L, 2)) /* clear handler */ - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushnumber(L, sig); - lua_gettable(L, -2); /* return old handler */ - lua_pushnumber(L, sig); - lua_pushnil(L); - lua_settable(L, -4); - lua_remove(L, -2); /* remove LUA_SIGNAL table */ - signal(sig, SIG_DFL); - } else - { - luaL_checktype(L, 2, LUA_TFUNCTION); - - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - - lua_pushnumber(L, sig); - lua_pushvalue(L, 2); - lua_settable(L, -3); - - /* Set the state for the handler */ - Lsig = L; - - if (lua_toboolean(L, 3)) /* c hook? */ - { - if (signal(sig, handle) == SIG_ERR) - lua_pushboolean(L, 0); - else - lua_pushboolean(L, 1); - } else /* lua_hook */ - { - if (signal(sig, handle) == SIG_ERR) - lua_pushboolean(L, 0); - else - lua_pushboolean(L, 1); - } - } - return 1; +*/ + +static int l_signal(lua_State *L) { + int args = lua_gettop(L); + int t, sig; /* type, signal */ + + /* get type of signal */ + luaL_checkany(L, 1); + t = lua_type(L, 1); + + if(t == LUA_TNUMBER) { + sig = (int) lua_tonumber(L, 1); + } else if(t == LUA_TSTRING) { + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 1); + lua_gettable(L, -2); + + if(!lua_isnumber(L, -1)) { + return luaL_error(L, "invalid signal string"); + } + + sig = (int) lua_tonumber(L, -1); + lua_pop(L, 1); /* get rid of number we pushed */ + } else { + luaL_checknumber(L, 1); /* will always error, with good error msg */ + return luaL_error(L, "unreachable: invalid number was accepted"); + } + + /* set handler */ + if(args == 1 || lua_isnil(L, 2)) { /* clear handler */ + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushnumber(L, sig); + lua_gettable(L, -2); /* return old handler */ + lua_pushnumber(L, sig); + lua_pushnil(L); + lua_settable(L, -4); + lua_remove(L, -2); /* remove LUA_SIGNAL table */ + signal(sig, SIG_DFL); + } else { + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + + lua_pushnumber(L, sig); + lua_pushvalue(L, 2); + lua_settable(L, -3); + + /* Set the state for the handler */ + Lsig = L; + + if(lua_toboolean(L, 3)) { /* c hook? */ + if(signal(sig, handle) == SIG_ERR) { + lua_pushboolean(L, 0); + } else { + lua_pushboolean(L, 1); + } + } else { /* lua_hook */ + if(signal(sig, handle) == SIG_ERR) { + lua_pushboolean(L, 0); + } else { + lua_pushboolean(L, 1); + } + } + } + + return 1; } /* * l_raise == raise(signal) * * signal = signal number or string -*/ - -static int l_raise(lua_State *L) -{ - /* int args = lua_gettop(L); */ - int t = 0; /* type */ - lua_Number ret; - - luaL_checkany(L, 1); - - t = lua_type(L, 1); - if (t == LUA_TNUMBER) - { - ret = (lua_Number) raise((int) lua_tonumber(L, 1)); - lua_pushnumber(L, ret); - } else if (t == LUA_TSTRING) - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 1); - lua_gettable(L, -2); - if (!lua_isnumber(L, -1)) - luaL_error(L, "invalid signal string"); - ret = (lua_Number) raise((int) lua_tonumber(L, -1)); - lua_pop(L, 1); /* get rid of number we pushed */ - lua_pushnumber(L, ret); - } else - luaL_checknumber(L, 1); /* will always error, with good error msg */ - - return 1; +*/ + +static int l_raise(lua_State *L) { + /* int args = lua_gettop(L); */ + int t = 0; /* type */ + lua_Number ret; + + luaL_checkany(L, 1); + + t = lua_type(L, 1); + + if(t == LUA_TNUMBER) { + ret = (lua_Number) raise((int) lua_tonumber(L, 1)); + lua_pushnumber(L, ret); + } else if(t == LUA_TSTRING) { + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 1); + lua_gettable(L, -2); + + if(!lua_isnumber(L, -1)) { + return luaL_error(L, "invalid signal string"); + } + + ret = (lua_Number) raise((int) lua_tonumber(L, -1)); + lua_pop(L, 1); /* get rid of number we pushed */ + lua_pushnumber(L, ret); + } else { + luaL_checknumber(L, 1); /* will always error, with good error msg */ + } + + return 1; } #if defined(__unix__) || defined(__APPLE__) @@ -335,78 +338,83 @@ static int l_raise(lua_State *L) * * pid = process id * signal = signal number or string -*/ - -static int l_kill(lua_State *L) -{ - int t; /* type */ - lua_Number ret; /* return value */ - - luaL_checknumber(L, 1); /* must be int for pid */ - luaL_checkany(L, 2); /* check for a second arg */ - - t = lua_type(L, 2); - if (t == LUA_TNUMBER) - { - ret = (lua_Number) kill((int) lua_tonumber(L, 1), - (int) lua_tonumber(L, 2)); - lua_pushnumber(L, ret); - } else if (t == LUA_TSTRING) - { - lua_pushstring(L, LUA_SIGNAL); - lua_gettable(L, LUA_REGISTRYINDEX); - lua_pushvalue(L, 2); - lua_gettable(L, -2); - if (!lua_isnumber(L, -1)) - luaL_error(L, "invalid signal string"); - ret = (lua_Number) kill((int) lua_tonumber(L, 1), - (int) lua_tonumber(L, -1)); - lua_pop(L, 1); /* get rid of number we pushed */ - lua_pushnumber(L, ret); - } else - luaL_checknumber(L, 2); /* will always error, with good error msg */ - return 1; +*/ + +static int l_kill(lua_State *L) { + int t; /* type */ + lua_Number ret; /* return value */ + + luaL_checknumber(L, 1); /* must be int for pid */ + luaL_checkany(L, 2); /* check for a second arg */ + + t = lua_type(L, 2); + + if(t == LUA_TNUMBER) { + ret = (lua_Number) kill((int) lua_tonumber(L, 1), + (int) lua_tonumber(L, 2)); + lua_pushnumber(L, ret); + } else if(t == LUA_TSTRING) { + lua_pushstring(L, LUA_SIGNAL); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 2); + lua_gettable(L, -2); + + if(!lua_isnumber(L, -1)) { + return luaL_error(L, "invalid signal string"); + } + + ret = (lua_Number) kill((int) lua_tonumber(L, 1), + (int) lua_tonumber(L, -1)); + lua_pop(L, 1); /* get rid of number we pushed */ + lua_pushnumber(L, ret); + } else { + luaL_checknumber(L, 2); /* will always error, with good error msg */ + } + + return 1; } #endif static const struct luaL_Reg lsignal_lib[] = { - {"signal", l_signal}, - {"raise", l_raise}, + {"signal", l_signal}, + {"raise", l_raise}, #if defined(__unix__) || defined(__APPLE__) - {"kill", l_kill}, + {"kill", l_kill}, #endif - {NULL, NULL} + {NULL, NULL} }; -int luaopen_util_signal(lua_State *L) -{ - int i = 0; - - /* add the library */ - luaL_register(L, "signal", lsignal_lib); - - /* push lua_signals table into the registry */ - /* put the signals inside the library table too, - * they are only a reference */ - lua_pushstring(L, LUA_SIGNAL); - lua_createtable(L, 0, 0); - - while (lua_signals[i].name != NULL) - { - /* registry table */ - lua_pushstring(L, lua_signals[i].name); - lua_pushnumber(L, lua_signals[i].sig); - lua_settable(L, -3); - /* signal table */ - lua_pushstring(L, lua_signals[i].name); - lua_pushnumber(L, lua_signals[i].sig); - lua_settable(L, -5); - i++; - } - - /* add newtable to the registry */ - lua_settable(L, LUA_REGISTRYINDEX); - - return 1; +int luaopen_util_signal(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif + int i = 0; + + /* add the library */ + lua_newtable(L); + luaL_setfuncs(L, lsignal_lib, 0); + + /* push lua_signals table into the registry */ + /* put the signals inside the library table too, + * they are only a reference */ + lua_pushstring(L, LUA_SIGNAL); + lua_newtable(L); + + while(lua_signals[i].name != NULL) { + /* registry table */ + lua_pushstring(L, lua_signals[i].name); + lua_pushnumber(L, lua_signals[i].sig); + lua_settable(L, -3); + /* signal table */ + lua_pushstring(L, lua_signals[i].name); + lua_pushnumber(L, lua_signals[i].sig); + lua_settable(L, -5); + i++; + } + + /* add newtable to the registry */ + lua_settable(L, LUA_REGISTRYINDEX); + + return 1; } diff --git a/util-src/table.c b/util-src/table.c new file mode 100644 index 00000000..9a9553fc --- /dev/null +++ b/util-src/table.c @@ -0,0 +1,33 @@ +#include <lua.h> +#include <lauxlib.h> + +static int Lcreate_table(lua_State *L) { + lua_createtable(L, luaL_checkinteger(L, 1), luaL_checkinteger(L, 2)); + return 1; +} + +static int Lpack(lua_State *L) { + unsigned int n_args = lua_gettop(L); + lua_createtable(L, n_args, 1); + lua_insert(L, 1); + + for(int arg = n_args; arg >= 1; arg--) { + lua_rawseti(L, 1, arg); + } + + lua_pushinteger(L, n_args); + lua_setfield(L, -2, "n"); + return 1; +} + +int luaopen_util_table(lua_State *L) { +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif + lua_createtable(L, 0, 2); + lua_pushcfunction(L, Lcreate_table); + lua_setfield(L, -2, "create"); + lua_pushcfunction(L, Lpack); + lua_setfield(L, -2, "pack"); + return 1; +} diff --git a/util-src/windows.c b/util-src/windows.c index 3d14ca95..89bec57b 100644 --- a/util-src/windows.c +++ b/util-src/windows.c @@ -1,7 +1,7 @@ /* Prosody IM -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain --- +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- @@ -19,23 +19,30 @@ #include "lua.h" #include "lauxlib.h" +#if (LUA_VERSION_NUM == 501) +#define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) +#endif + static int Lget_nameservers(lua_State *L) { char stack_buffer[1024]; // stack allocated buffer - IP4_ARRAY* ips = (IP4_ARRAY*) stack_buffer; + IP4_ARRAY *ips = (IP4_ARRAY *) stack_buffer; DWORD len = sizeof(stack_buffer); DNS_STATUS status; status = DnsQueryConfig(DnsConfigDnsServerList, FALSE, NULL, NULL, ips, &len); - if (status == 0) { + + if(status == 0) { DWORD i; lua_createtable(L, ips->AddrCount, 0); - for (i = 0; i < ips->AddrCount; i++) { + + for(i = 0; i < ips->AddrCount; i++) { DWORD ip = ips->AddrArray[i]; char ip_str[16] = ""; sprintf_s(ip_str, sizeof(ip_str), "%d.%d.%d.%d", (ip >> 0) & 255, (ip >> 8) & 255, (ip >> 16) & 255, (ip >> 24) & 255); lua_pushstring(L, ip_str); - lua_rawseti(L, -2, i+1); + lua_rawseti(L, -2, i + 1); } + return 1; } else { lua_pushnil(L); @@ -44,7 +51,7 @@ static int Lget_nameservers(lua_State *L) { } } -static int lerror(lua_State *L, char* string) { +static int lerror(lua_State *L, char *string) { lua_pushnil(L); lua_pushfstring(L, "%s: %d", string, GetLastError()); return 2; @@ -52,13 +59,22 @@ static int lerror(lua_State *L, char* string) { static int Lget_consolecolor(lua_State *L) { HWND console = GetStdHandle(STD_OUTPUT_HANDLE); - WORD color; DWORD read_len; - + WORD color; + DWORD read_len; + CONSOLE_SCREEN_BUFFER_INFO info; - - if (console == INVALID_HANDLE_VALUE) return lerror(L, "GetStdHandle"); - if (!GetConsoleScreenBufferInfo(console, &info)) return lerror(L, "GetConsoleScreenBufferInfo"); - if (!ReadConsoleOutputAttribute(console, &color, 1, info.dwCursorPosition, &read_len)) return lerror(L, "ReadConsoleOutputAttribute"); + + if(console == INVALID_HANDLE_VALUE) { + return lerror(L, "GetStdHandle"); + } + + if(!GetConsoleScreenBufferInfo(console, &info)) { + return lerror(L, "GetConsoleScreenBufferInfo"); + } + + if(!ReadConsoleOutputAttribute(console, &color, 1, info.dwCursorPosition, &read_len)) { + return lerror(L, "ReadConsoleOutputAttribute"); + } lua_pushnumber(L, color); return 1; @@ -66,14 +82,20 @@ static int Lget_consolecolor(lua_State *L) { static int Lset_consolecolor(lua_State *L) { int color = luaL_checkint(L, 1); HWND console = GetStdHandle(STD_OUTPUT_HANDLE); - if (console == INVALID_HANDLE_VALUE) return lerror(L, "GetStdHandle"); - if (!SetConsoleTextAttribute(console, color)) return lerror(L, "SetConsoleTextAttribute"); + + if(console == INVALID_HANDLE_VALUE) { + return lerror(L, "GetStdHandle"); + } + + if(!SetConsoleTextAttribute(console, color)) { + return lerror(L, "SetConsoleTextAttribute"); + } + lua_pushboolean(L, 1); return 1; } -static const luaL_Reg Reg[] = -{ +static const luaL_Reg Reg[] = { { "get_nameservers", Lget_nameservers }, { "get_consolecolor", Lget_consolecolor }, { "set_consolecolor", Lset_consolecolor }, @@ -81,9 +103,12 @@ static const luaL_Reg Reg[] = }; LUALIB_API int luaopen_util_windows(lua_State *L) { - luaL_register(L, "windows", Reg); - lua_pushliteral(L, "version"); /** version */ +#if (LUA_VERSION_NUM > 501) + luaL_checkversion(L); +#endif + lua_newtable(L); + luaL_setfuncs(L, Reg, 0); lua_pushliteral(L, "-3.14"); - lua_settable(L,-3); + lua_setfield(L, -2, "version"); return 1; } |