Refactor and fix up a lot of code

Don't tell the boss I forgot a couple of free()s...
This commit is contained in:
Jeremy Baxter 2023-11-26 17:13:41 +13:00
parent fe38efac42
commit 290289cbf5
12 changed files with 175 additions and 335 deletions

View file

@ -8,11 +8,9 @@
#include "callisto.h" #include "callisto.h"
static const luaL_Reg loadedlibs[] = { static const luaL_Reg loadedlibs[] = {
{CALLISTO_CLLIBNAME, luaopen_cl}, {CALLISTO_CLLIBNAME, luaopen_cl},
{CALLISTO_ENVLIBNAME, luaopen_environ}, {CALLISTO_ENVLIBNAME, luaopen_environ},
{CALLISTO_EXTLIBNAME, luaopen_extra},
{CALLISTO_FSYSLIBNAME, luaopen_fs}, {CALLISTO_FSYSLIBNAME, luaopen_fs},
{CALLISTO_JSONLIBNAME, luaopen_json}, {CALLISTO_JSONLIBNAME, luaopen_json},
{CALLISTO_MATHLIBNAME, luaopen_math}, {CALLISTO_MATHLIBNAME, luaopen_math},
@ -37,12 +35,24 @@ callisto_openall(lua_State *L)
{ {
const luaL_Reg *lib; const luaL_Reg *lib;
/* for every Callisto library */ /* for each Callisto library except extra */
for (lib = loadedlibs; lib->func; lib++) { for (lib = loadedlibs; lib->func; lib++) {
lua_newtable(L); /* make a new table for the library */ lua_newtable(L); /* make a new table for the library */
lib->func(L); /* load library */ lib->func(L); /* load library */
lua_setglobal(L, lib->name); lua_setglobal(L, lib->name);
} }
/* inject extra into the global environment */
luaopen_extra(L);
lua_pushnil(L);
while (lua_next(L, -2) != 0) { /* for each key in the extra library */
/* if the key is not a string, move on to the next one */
if (!lua_isstring(L, -2)) {
lua_pop(L, 1);
continue;
}
/* assign the value to a global */
lua_setglobal(L, lua_tostring(L, -2));
}
} }
void void

View file

@ -2,9 +2,9 @@
* Callisto, a featureful runtime for Lua 5.4. * Callisto, a featureful runtime for Lua 5.4.
*/ */
#ifndef _LCALLISTO_H_ #ifndef _CALLISTO_H_
#define _LCALLISTO_H_ #define _CALLISTO_H_
#include <lua.h> #include <lua.h>

124
lcl.c
View file

@ -19,31 +19,42 @@
#include "callisto.h" #include "callisto.h"
#include "util.h" #include "util.h"
static void static void
fmesg(lua_State *L, FILE* f, int shift) fmesgshift(lua_State *L, FILE* f, int shift)
{ {
int paramc, i; int paramc, i;
char *progname; /* argv[0] */ char *progname; /* argv[0] */
paramc = lua_gettop(L); /* get parameter count */ lua_getglobal(L, "arg");
if (!lua_istable(L, -1)) {
lua_geti(L, 1 + shift, 0); /* get index 0 of table at index 1 (argv) */ luaL_error(L, "arg table not present/inaccessible; cannot get script name");
if (lua_type(L, -1) != LUA_TSTRING) { /* if argv[0] is not a string... */ return;
luaL_argerror(L, 1, "must have a string in index 0)");
} }
progname = (char *)lua_tostring(L, -1); /* set progname to argv[0] */
lua_geti(L, -1, 0);
if (!lua_isstring(L, -1)) {
luaL_argerror(L, 1, "arg[0] is not a string; cannot print script name");
return;
}
progname = (char *)lua_tostring(L, -1);
/* format using string.format */ /* format using string.format */
lua_getglobal(L, "string"); lua_getglobal(L, "string");
lua_getfield(L, -1, "format"); lua_getfield(L, -1, "format");
for (i = 2 + shift; i <= paramc; i++) /* for every parameter */ paramc = lua_gettop(L); /* get parameter count */
for (i = 1 + shift; i <= paramc; i++) { /* for every parameter */
lua_pushvalue(L, i); /* push argument */ lua_pushvalue(L, i); /* push argument */
}
lua_call(L, paramc - (1 + shift), 1); /* call string.format */ lua_call(L, paramc - shift, 1);
fprintf(f, "%s: %s\n", basename(progname), lua_tostring(L, -1));
}
fprintf(f, "%s: %s\n", basename(progname), lua_tostring(L, -1)); /* print */ static void
fmesg(lua_State *L, FILE* f)
{
fmesgshift(L, f, 0);
} }
/*** /***
@ -63,22 +74,21 @@ fmesg(lua_State *L, FILE* f, int shift)
* @usage * @usage
local succeeded, err = io.open("file.txt") local succeeded, err = io.open("file.txt")
if not succeeded then if not succeeded then
cl.error(arg, "could not open " .. err) cl.error("could not open " .. err)
end end
* @tparam table arg The command line argument table (this function only uses index *[0]*)
* @tparam string message The message to print after the program's name. Supports *string.format*-style format specifiers. * @tparam string message The message to print after the program's name. Supports *string.format*-style format specifiers.
* @param ... Any additional values specified by the format specifiers in the *message* parameter. * @param ... Any additional values specified by the format specifiers in the *message* parameter.
*/ */
static int static int
cl_error(lua_State *L) cl_error(lua_State *L)
{ {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checkstring(L, 1);
luaL_checkstring(L, 2);
fmesg(L, stderr, 0); fmesg(L, stderr);
return 0; return 0;
} }
/*** /***
* Prints a formatted message to standard output. * Prints a formatted message to standard output.
* It looks like so: * It looks like so:
@ -94,21 +104,20 @@ cl_error(lua_State *L)
* using *string.format*. * using *string.format*.
* *
* @function mesg * @function mesg
* @usage cl.mesg(arg, "message to stdout") * @usage cl.mesg("message to stdout")
* @tparam table arg The command line argument table (this function only uses index *[0]*)
* @tparam string message The message to print after the program's name. Supports *string.format*-style format specifiers. * @tparam string message The message to print after the program's name. Supports *string.format*-style format specifiers.
* @param ... Any additional values specified by the format specifiers in the *message* parameter. * @param ... Any additional values specified by the format specifiers in the *message* parameter.
*/ */
static int static int
cl_mesg(lua_State *L) cl_mesg(lua_State *L)
{ {
luaL_checktype(L, 1, LUA_TTABLE); luaL_checkstring(L, 1);
luaL_checkstring(L, 2);
fmesg(L, stdout, 0); fmesg(L, stdout);
return 0; return 0;
} }
/*** /***
* Convenience function that calls *cl.error* to * Convenience function that calls *cl.error* to
* print a formatted error message to standard error, * print a formatted error message to standard error,
@ -122,69 +131,60 @@ cl_mesg(lua_State *L)
local succeeded, err, code = io.open("file.txt") local succeeded, err, code = io.open("file.txt")
if not succeeded then if not succeeded then
-- use a custom exit code: -- use a custom exit code:
cl.panic(code, arg, "could not open " .. err) cl.panic(code, "could not open " .. err)
-- use the default exit code (1): -- use the default exit code (1):
cl.panic(arg, "could not open " .. err) cl.panic("could not open " .. err)
end end
* @tparam[opt] integer code The exit code to return to the OS. * @tparam[opt] integer code The exit code to return to the operating system.
* @tparam table arg The command line argument table (this function only uses index *[0]*)
* @tparam string message The message to print after the program's name. Supports *string.format*-style format specifiers. * @tparam string message The message to print after the program's name. Supports *string.format*-style format specifiers.
* @param ... Any additional values specified by the format specifiers in the *message* parameter. * @param ... Any additional values specified by the format specifiers in the *message* parameter.
*/ */
static int static int
cl_panic(lua_State *L) cl_panic(lua_State *L)
{ {
ubyte code; int code, codegiven;
ubyte isinteger;
isinteger = lua_isinteger(L, 1);
/* get exit code */ /* get exit code */
code = lua_tointeger(L, 1) * isinteger + 1 * !isinteger; codegiven = lua_isinteger(L, 1);
luaL_checktype(L, 1 + isinteger, LUA_TTABLE); code = codegiven ? lua_tointeger(L, 1) : 1;
luaL_checkstring(L, 2 + isinteger);
fmesg(L, stderr, isinteger);
/* format using string.format */ /* check arguments */
lua_getglobal(L, "os"); luaL_checkstring(L, 1 + codegiven);
lua_getfield(L, -1, "exit"); fmesgshift(L, stderr, codegiven);
/* push arguments to os.exit */ /* exit */
lua_pushinteger(L, code); lua_close(L);
lua_pushboolean(L, 1); if (L) /* used to avoid "unreachable return" warnings */
exit(code);
lua_call(L, 2, 0); /* call os.exit */
return 0; return 0;
} }
/*** /***
* Parses the command line argument list *arg*. * Parses the command line argument list *arg*.
* The string *optstring* may contain the * The string *optstring* may contain the following elements:
* following elements: individual characters, * individual characters, and characters followed by a colon.
* and characters followed by a colon. * A character followed by a single colon indicates that an
* A character followed by a single colon * argument is to follow the option on the command line. For
* indicates that an argument is to follow * example, * an option string `"x"` permits a **-x** option,
* the option on the command line. For example, * and an option string `"x:"` permits a **-x** option that
* an option string `"x"` permits a **-x** option, * must take an argument. An option * string of `"x:yz"` permits
* and an option string `"x:"` permits a **-x** * a **-x** option that takes an argument, and **-y** and **-z**
* option that must take an argument. An option * options, which do not.
* string of `"x:yz"` permits a **-x** option that
* takes an argument, and **-y** and **-z** options,
* which do not.
* *
* The function *fn* is run each time a new option * The function *fn* is run each time a new option of the argument
* is processed. of the argument list. It takes the * list is processed. It takes the parameters *opt*, *optarg*,
* parameters *opt*, *optarg*, *optindex*, and *opterror*. * *optindex*, and *opterror*.
* *opt* is a string containing the option used. It is set * - *opt* is a string containing the option used. It is set
* to the option the user specified on the command line. * to the option the user specified on the command line.
* If the user specifies an unknown option (one that is * If the user specifies an unknown option (one that is
* not specified in *optstring*), the value of *opt* will * not specified in *optstring*), the value of *opt* will
* be set to nil. If the user specifies an option that * be set to nil. If the user specifies an option that
* requires an argument, but does not specify its argument, * requires an argument, but does not specify its argument,
* the value of *opt* will be the string `"*"` (a single * the value of *opt* will be the string `"*"` (a single
* asterisk). The second parameter, *optarg*, is a string * asterisk).
* containing the option argument (if applicable). * - *optarg*, is a string containing the option argument
* *optindex* is an integer that contains the index of the * (if applicable).
* - *optindex* is an integer that contains the index of the
* last command line argument processed. The last parameter, * last command line argument processed. The last parameter,
* *opterror*, is set in case of an option error (if *opt* * *opterror*, is set in case of an option error (if *opt*
* is nil or set to the string `"*"`), and is set to the * is nil or set to the string `"*"`), and is set to the
@ -215,8 +215,7 @@ end)
static int static int
cl_options(lua_State *L) cl_options(lua_State *L)
{ {
int argc; /* command line argument count */ int argc, i;
int i;
char ch, s[2]; /* opt character and string */ char ch, s[2]; /* opt character and string */
char loptopt[2]; /* opterror, returned to Lua */ char loptopt[2]; /* opterror, returned to Lua */
char **argv; /* parameter 1 (table), command line argument vector */ char **argv; /* parameter 1 (table), command line argument vector */
@ -275,6 +274,7 @@ cl_options(lua_State *L)
lua_pcall(L, 4, 0, 0); /* call Lua function */ lua_pcall(L, 4, 0, 0); /* call Lua function */
} }
free(optstring); free(optstring);
return 0; return 0;
} }

View file

@ -1,10 +1,8 @@
/*** /***
* Extra functions that don't * Extra functions that don't fit into any other category.
* fit into any other category.
* *
* This module does not provide its * This module does not provide its own table;
* own table; all functions here are * all functions here are found in the global table.
* found in the global table.
* *
* @module extra * @module extra
*/ */
@ -17,7 +15,6 @@
#include "callisto.h" #include "callisto.h"
#include "util.h" #include "util.h"
/*** /***
* Waits the specified amount of seconds. * Waits the specified amount of seconds.
* *
@ -63,6 +60,6 @@ static const luaL_Reg extlib[] = {
int int
luaopen_extra(lua_State *L) luaopen_extra(lua_State *L)
{ {
newoverride(L, extlib, CALLISTO_EXTLIBNAME); luaL_newlib(L, extlib);
return 1; return 1;
} }

188
lfs.c
View file

@ -1,6 +1,6 @@
/*** /***
* Files, directories and * Files, directories and file system manipulation.
* file system manipulation. *
* @module fs * @module fs
*/ */
@ -31,7 +31,7 @@
* *
* This function may throw an error if the given * This function may throw an error if the given
* pathname exceeds the system's path length * pathname exceeds the system's path length
* limit (On most Linux systems this will be 4096). * limit (on most Linux systems this will be 4096).
* *
* @function exists * @function exists
* @usage * @usage
@ -49,8 +49,8 @@ fs_exists(lua_State *L)
path = luaL_checkstring(L, 1); path = luaL_checkstring(L, 1);
ret = access(path, F_OK); /* check if file exists */ ret = access(path, F_OK); /* check if file exists */
if (ret == -1 && errno == ENAMETOOLONG) /* check if path is too long */ if (ret == -1) /* failed? */
return lfail(L, E_PATHNAMETOOLONG); return lfail(L);
lua_pushboolean(L, ret == 0); lua_pushboolean(L, ret == 0);
return 1; return 1;
@ -156,59 +156,21 @@ fs_mkdir(lua_State *L)
dir = (char *)luaL_checkstring(L, 1); dir = (char *)luaL_checkstring(L, 1);
if (!lua_isboolean(L, 2) && !lua_isnoneornil(L, 2)) { if (!lua_isboolean(L, 2) && !lua_isnoneornil(L, 2))
luaL_typeerror(L, 2, "boolean"); luaL_typeerror(L, 2, "boolean");
}
recursive = lua_toboolean(L, 2); recursive = lua_toboolean(L, 2);
if (recursive) { if (recursive)
ret = mkpath(dir, 0777, 0777); ret = mkpath(dir, 0777, 0777);
} else { else
ret = mkdir(dir, 0777); ret = mkdir(dir, 0777);
}
if (ret == 0) { if (ret == 0) {
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
switch (errno) { return lfail(L);
case ENOTDIR:
return lfail(L, E_NOTADIR);
break;
case ENAMETOOLONG:
return lfail(L, E_PATHNAMETOOLONG);
break;
case ENOENT:
return lfail(L, E_COMPNOTEXIST);
break;
case EACCES:
return lfail(L, E_PERM);
break;
case ELOOP:
return lfail(L, E_SYMLINK);
break;
case EROFS:
return lfail(L, E_ROFS);
break;
case EEXIST:
return lfail(L, E_FEXISTS);
break;
case ENOSPC:
return lfail(L, E_NOSPACE);
break;
case EDQUOT:
return lfail(L, E_QUOTA);
break;
case EIO:
return lfail(L, E_IOERR);
break;
case EFAULT:
return lfail(L, E_INTFAULT);
break;
}
return 0;
} }
/*** /***
@ -268,53 +230,7 @@ fs_move(lua_State *L)
return 1; return 1;
} }
switch (errno) { return lfail(L);
case ENAMETOOLONG:
return lfail(L, E_PATHNAMETOOLONG);
break;
case ENOENT:
return lfail(L, E_NOSUCHDEST);
break;
case EACCES:
return lfail(L, E_PERM);
break;
case EPERM:
return lfail(L, E_STICKYDIR);
break;
case ELOOP:
return lfail(L, E_SYMLINK);
break;
case EMLINK:
return lfail(L, E_MAXLINK);
break;
case ENOTDIR:
return lfail(L, E_NOTADIR);
break;
case EISDIR:
return lfail(L, E_ISADIR);
break;
case EXDEV:
return lfail(L, E_DIFFFS);
break;
case ENOSPC:
return lfail(L, E_NOSPACE);
break;
case EDQUOT:
return lfail(L, E_QUOTA);
break;
case EIO:
return lfail(L, E_IOERR);
break;
case EROFS:
return lfail(L, E_ROFS);
break;
case EFAULT:
return lfail(L, E_INTFAULT);
break;
case EINVAL:
return lfail(L, E_MVPARENT);
break;
}
return 0; return 0;
} }
@ -374,41 +290,7 @@ fs_rmdir(lua_State *L)
return 1; return 1;
} }
switch (errno) { return lfail(L);
case ENOTDIR:
return lfail(L, E_NOTADIR);
break;
case ENAMETOOLONG:
return lfail(L, E_PATHNAMETOOLONG);
break;
case ENOENT:
return lfail(L, E_NOSUCHDIR);
break;
case ELOOP:
return lfail(L, E_SYMLINK);
break;
case ENOTEMPTY:
return lfail(L, E_DIRNOTEMPTY);
break;
case EACCES:
return lfail(L, E_PERM);
break;
case EBUSY:
return lfail(L, E_MOUNTPOINT);
break;
case EINVAL:
return lfail(L, E_DIRDOT);
break;
case EIO:
return lfail(L, E_IOERR);
break;
case EROFS:
return lfail(L, E_ROFS);
break;
case EFAULT:
return lfail(L, E_INTFAULT);
break;
}
return 0; return 0;
} }
@ -460,27 +342,7 @@ fs_workdir(lua_State *L)
} }
free(buffer); free(buffer);
return lfail(L);
switch (errno) {
case EACCES:
return lfail(L, E_PERM);
break;
case EFAULT:
return lfail(L, E_INTFAULT);
break;
case ENOENT:
return lfail(L, E_WORKDIRNOTVALID);
break;
case ENOMEM:
return lfail(L, E_NOMEM);
break;
case ERANGE:
case ENAMETOOLONG: /* glibc */
return lfail(L, E_PATHNAMETOOLONG);
break;
}
return 0;
} else { } else {
workdir = luaL_checkstring(L, 1); workdir = luaL_checkstring(L, 1);
@ -489,31 +351,7 @@ fs_workdir(lua_State *L)
return 1; return 1;
} }
switch (errno) { return lfail(L);
case ENOTDIR:
return lfail(L, E_NOTADIR);
break;
case ENAMETOOLONG:
return lfail(L, E_PATHNAMETOOLONG);
break;
case ENOENT:
return lfail(L, E_NOSUCHDEST);
break;
case ELOOP:
return lfail(L, E_SYMLINK);
break;
case EACCES:
return lfail(L, E_PERM);
break;
case EFAULT:
return lfail(L, E_INTFAULT);
break;
case EIO:
return lfail(L, E_IOERR);
break;
}
return 0;
} }
} }

13
ljson.c
View file

@ -27,8 +27,7 @@
#include "callisto.h" #include "callisto.h"
/* Functions */
/* -=[ Functions ]=- */
/*** /***
* Returns the given Lua table encoded as a JSON object. * Returns the given Lua table encoded as a JSON object.
@ -90,7 +89,7 @@ local t = json.decode(j)
* @function new * @function new
*/ */
/* -=[ Fields ]=- */ /* Fields */
/*** /***
* The name of the module, provided for compatibility with * The name of the module, provided for compatibility with
@ -115,9 +114,9 @@ local t = json.decode(j)
* @field null * @field null
*/ */
/* -=[ Configuration options ]=- */ /* Configuration options */
/* Decoding */ /* -> decoding */
/*** /***
* Configures handling of invalid numbers while decoding; * Configures handling of invalid numbers while decoding;
@ -145,7 +144,7 @@ local t = json.decode(j)
* @tparam integer depth Max depth allowed when decoding. * @tparam integer depth Max depth allowed when decoding.
*/ */
/* Encoding */ /* -> encoding */
/*** /***
* Configures handling of invalid numbers while encoding; * Configures handling of invalid numbers while encoding;
@ -214,7 +213,7 @@ local t = json.decode(j)
*/ */
int luaopen_cjson(lua_State *L); int luaopen_cjson(lua_State *);
int int
luaopen_json(lua_State *L) luaopen_json(lua_State *L)

18
lpath.c
View file

@ -1,5 +1,6 @@
/*** /***
* File system path manipulation. * File system path manipulation.
*
* @module path * @module path
*/ */
@ -20,7 +21,6 @@
#include "errors.h" #include "errors.h"
#include "util.h" #include "util.h"
/*** /***
* Returns the last component of the given pathname, * Returns the last component of the given pathname,
* removing any trailing '/' characters. If the given * removing any trailing '/' characters. If the given
@ -30,7 +30,7 @@
* *
* This function may return nil if the given * This function may return nil if the given
* pathname exceeds the system's path length * pathname exceeds the system's path length
* limit (On most Linux systems this will be 4096). * limit (on most Linux systems this will be 4096).
* *
* @function basename * @function basename
* @usage path.basename(arg[0]) * @usage path.basename(arg[0])
@ -45,10 +45,12 @@ path_basename(lua_State *L)
path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1)); path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1));
ret = basename(path); ret = basename(path);
if (ret == NULL && errno == ENAMETOOLONG) /* check if path is too long */ if (ret == NULL) /* failed? */
return lfail(L, E_PATHNAMETOOLONG); return lfail(L);
lua_pushstring(L, ret); lua_pushstring(L, ret);
free(path);
return 1; return 1;
} }
@ -62,7 +64,7 @@ path_basename(lua_State *L)
* *
* This function may return nil if the given * This function may return nil if the given
* pathname exceeds the system's path length * pathname exceeds the system's path length
* limit (On most Linux systems this will be 4096). * limit (on most Linux systems this will be 4096).
* *
* @function dirname * @function dirname
* @usage path.dirname(arg[0]) * @usage path.dirname(arg[0])
@ -77,10 +79,12 @@ path_dirname(lua_State *L)
path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1)); path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1));
ret = dirname(path); ret = dirname(path);
if (ret == NULL && errno == ENAMETOOLONG) /* check if path is too long */ if (ret == NULL) /* failed? */
return lfail(L, E_PATHNAMETOOLONG); return lfail(L);
lua_pushstring(L, ret); lua_pushstring(L, ret);
free(path);
return 1; return 1;
} }

View file

@ -22,7 +22,6 @@
#define PID_MAX 8 /* rounded to the nearest even number */ #define PID_MAX 8 /* rounded to the nearest even number */
#define PROCESS_MAX 256 #define PROCESS_MAX 256
/* signals and signal count */ /* signals and signal count */
#define SIGC 36 #define SIGC 36
static const char *signals[] = { static const char *signals[] = {
@ -62,7 +61,7 @@ static const char *signals[] = {
[SIGPROF] = "SIGPROF", [SIGPROF] = "SIGPROF",
#ifdef SIGWINC #ifdef SIGWINC
[SIGWINC] = "SIGWINC", [SIGWINC] = "SIGWINC",
#elif defined (SIGWINCH) #elif defined(SIGWINCH)
[SIGWINCH] = "SIGWINCH", [SIGWINCH] = "SIGWINCH",
#endif #endif
#ifdef SIGINFO #ifdef SIGINFO
@ -87,33 +86,30 @@ static const char *signals[] = {
static int static int
process_pid(lua_State *L) process_pid(lua_State *L)
{ {
lua_pushinteger(L, getpid()); /* push current process pid */ lua_pushinteger(L, getpid());
return 1; return 1;
} }
/*** /***
* Returns the ID of the given process. * Returns the PID (process ID) of the given process.
* *
* Returns nil if the process was not found. * Returns nil if the process was not found.
* *
* @function pidof * @function pidof
* @usage process.pidof("init") * @usage process.pidof("init")
* @tparam string process The process to look up. * @tparam string process The name of the process to look up.
*/ */
static int static int
process_pidof(lua_State *L) process_pidof(lua_State *L)
{ {
const char *process; /* parameter 1 (string) */ const char *process; /* parameter 1 (string) */
char *command; /* pidof command buffer */ char *command; /* pidof command buffer */
char *buffer; /* pidof reading buffer */ char *buffer; /* pidof reading buffer */
long pid; /* pid to return to Lua */ int pexit; /* pidof exit code */
size_t pidmax; /* length passed to getline */ long pid; /* pid to return to Lua */
ssize_t ret; /* return value of getline */ size_t pidmax; /* length passed to getline */
FILE *p; ssize_t ret; /* getline return value */
FILE *p; /* pidof stream */
if (lua_isnoneornil(L, 1)) { /* check if first parameter wasn't given */
lua_pushinteger(L, getpid()); /* push current process pid */
return 1;
}
process = luaL_checkstring(L, 1); process = luaL_checkstring(L, 1);
command = calloc(1, PROCESS_MAX * sizeof(char *)); command = calloc(1, PROCESS_MAX * sizeof(char *));
@ -126,15 +122,21 @@ process_pidof(lua_State *L)
p = popen(command, "r"); p = popen(command, "r");
buffer = malloc(PID_MAX * sizeof(char *)); buffer = malloc(PID_MAX * sizeof(char *));
pidmax = (size_t)PID_MAX; pidmax = (size_t)PID_MAX;
ret = getline(&buffer, &pidmax, p); /* get line from pidof */
if (ret == -1 || pclose(p) != 0) { /* did getline or pidof fail? */ /* read line from pidof */
ret = getline(&buffer, &pidmax, p);
pexit = pclose(p);
if (ret == -1 || pexit != 0) { /* did getline or pidof fail? */
luaL_pushfail(L); luaL_pushfail(L);
return 1; return 1;
} }
pid = strtol(buffer, NULL, 10); /* convert it to an integer */ /* convert it to an integer and push */
lua_pushinteger(L, pid); /* push pid */ pid = strtol(buffer, NULL, 10);
lua_pushinteger(L, pid);
free(command); free(command);
free(buffer); free(buffer);
return 1; return 1;
} }
@ -144,9 +146,8 @@ strtosig(const char *sig)
int i; int i;
for (i = 1; i <= SIGC; i++) { for (i = 1; i <= SIGC; i++) {
if (streq(signals[i], sig)) { if (strcmp(signals[i], sig) == 0)
return i; /* valid signal found */ return i; /* valid signal found */
}
} }
return -1; /* invalid signal */ return -1; /* invalid signal */
} }
@ -169,7 +170,7 @@ process_signum(lua_State *L)
if ((sig = strtosig(luaL_checkstring(L, 1))) != -1) /* valid signal? */ if ((sig = strtosig(luaL_checkstring(L, 1))) != -1) /* valid signal? */
lua_pushinteger(L, sig); /* return signal */ lua_pushinteger(L, sig); /* return signal */
else else
return lfail(L, "no such signal"); return lfailm(L, "no such signal");
return 1; return 1;
} }
@ -180,27 +181,17 @@ sigsend(lua_State *L, pid_t pid, const char *sigstr)
int ret, sig; int ret, sig;
sig = strtosig(sigstr); sig = strtosig(sigstr);
if (sig != -1) { if (sig != -1) /* valid signal? */
ret = kill(pid, sig); ret = kill(pid, sig);
} else { else
lfail(L, "no such signal"); return lfailm(L, "no such signal");
return 0;
}
if (ret == 0) { /* check for success */ if (ret == 0) { /* check for success */
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 1; return 1;
} }
switch (errno) { return lfail(L);
case ESRCH:
lfail(L, "no such process");
break;
case EPERM:
lfail(L, "permission denied");
break;
}
return 0;
} }
/*** /***
@ -214,7 +205,7 @@ sigsend(lua_State *L, pid_t pid, const char *sigstr)
* @function send * @function send
* @usage * @usage
local pid = process.pid("sh") local pid = process.pid("sh")
process.send(pid, process.SIGTERM) process.send(pid, "SIGTERM")
* @tparam integer pid The PID of the process. * @tparam integer pid The PID of the process.
* @tparam string signal The signal to send. * @tparam string signal The signal to send.
*/ */
@ -227,10 +218,7 @@ process_send(lua_State *L)
pid = luaL_checkinteger(L, 1); pid = luaL_checkinteger(L, 1);
sig = luaL_checkstring(L, 2); sig = luaL_checkstring(L, 2);
if (sigsend(L, pid, sig)) return sigsend(L, pid, sig);
return 1;
else
return LFAIL_RET;
} }
/*** /***
@ -248,10 +236,7 @@ process_kill(lua_State *L)
pid = luaL_checkinteger(L, 1); pid = luaL_checkinteger(L, 1);
if (sigsend(L, pid, "SIGKILL")) return sigsend(L, pid, "SIGKILL");
return 1;
else
return LFAIL_RET;
} }
/*** /***
* Terminates the process with the given PID. * Terminates the process with the given PID.
@ -268,10 +253,7 @@ process_terminate(lua_State *L)
pid = luaL_checkinteger(L, 1); pid = luaL_checkinteger(L, 1);
if (sigsend(L, pid, "SIGTERM")) return sigsend(L, pid, "SIGTERM");
return 1;
else
return LFAIL_RET;
} }
static const luaL_Reg proclib[] = { static const luaL_Reg proclib[] = {

View file

@ -13,8 +13,7 @@
#include "callisto.h" #include "callisto.h"
int luaopen_socket_core(lua_State *);
int luaopen_socket_core(lua_State *L);
int int
luaopen_socket(lua_State *L) luaopen_socket(lua_State *L)

View file

@ -414,6 +414,10 @@ static int os_exit (lua_State *L) {
return 0; return 0;
} }
#ifndef HOST_NAME_MAX
# define HOST_NAME_MAX 256 /* according to POSIX */
#endif
/*** /***
* Returns the system hostname. * Returns the system hostname.
* *

26
util.c
View file

@ -2,31 +2,40 @@
* util.c * util.c
* *
* Utility functions. * Utility functions.
* See util.h for a description
* of these functions.
*/ */
#include <errno.h>
#include <string.h> #include <string.h>
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
#include "util.h" #include "util.h"
int int
lfail(lua_State *L, const char* mesg) lfail(lua_State *L)
{
luaL_pushfail(L);
lua_pushstring(L, strerror(errno));
lua_pushinteger(L, errno);
return 3;
}
int
lfailm(lua_State *L, const char *mesg)
{ {
luaL_pushfail(L); luaL_pushfail(L);
lua_pushstring(L, mesg); lua_pushstring(L, mesg);
return LFAIL_RET; return 2;
} }
/* /*
* String concatenation and copying functions * strlcat and strlcpy are from OpenBSD source files
* from OpenBSD lib/libc/string/strlcat.c and * lib/libc/string/strlcat.c and
* lib/libc/string/strlcpy.c respectively * lib/libc/string/strlcpy.c respectively
*/ */
#ifndef BSD #ifndef BSD
/* /*
* Appends src to string dst of size dsize (unlike strncat, dsize is the * Appends src to string dst of size dsize (unlike strncat, dsize is the
* full size of dst, not space left). At most dsize-1 characters * full size of dst, not space left). At most dsize-1 characters
@ -61,6 +70,7 @@ strlcat(char *dst, const char *src, size_t dsize)
return(dlen + (src - osrc)); /* count does not include NUL */ return(dlen + (src - osrc)); /* count does not include NUL */
} }
/* /*
* Copy string src to buffer dst of size dsize. At most dsize-1 * Copy string src to buffer dst of size dsize. At most dsize-1
* chars will be copied. Always NUL terminates (unless dsize == 0). * chars will be copied. Always NUL terminates (unless dsize == 0).
@ -90,7 +100,9 @@ strlcpy(char *dst, const char *src, size_t dsize)
return(src - osrc - 1); /* count does not include NUL */ return(src - osrc - 1); /* count does not include NUL */
} }
#endif #endif
/* /*
* Prepends t to s. * Prepends t to s.
*/ */

21
util.h
View file

@ -1,22 +1,17 @@
#ifndef _UTIL_H_
#define _UTIL_H_
#include <string.h> #include <string.h>
#include <lua.h> #include <lua.h>
#define byte char int lfail(lua_State *);
#define ubyte unsigned char int lfailm(lua_State *, const char *);
#define LFAIL_RET 2
#define streq(s1, s2) (strcmp((s1), (s2)) == 0)
#define newoverride(L, lib, libname) \
lua_getglobal(L, libname); \
for (int i = 0; lib[i].name != NULL; i++) { \
lua_pushcfunction(L, lib[i].func); \
lua_setfield(L, -2, lib[i].name); \
}
int lfail(lua_State *, const char *);
#ifndef BSD #ifndef BSD
size_t strlcat(char *, const char *, size_t); size_t strlcat(char *, const char *, size_t);
size_t strlcpy(char *, const char *, size_t); size_t strlcpy(char *, const char *, size_t);
#endif #endif
void strprepend(char *, const char *); void strprepend(char *, const char *);
#endif