* * * * *
YAML config file? Pain? Try Lua
Several articles about using YAML (YAML Ain't Markup Language) for
configuration have been making the rounds, yet rarely do I see Lua [1] being
mentioned as an alternative for configuration files.
Yes, it's a language, but it started out life as a configuration format. It's
also small for a language, easy to embed, and easy to sandbox for the
paranoid. Here's an example:
-----[ Lua ]-----
lua_State *gL;
bool config_read(char const *conf)
{
int rc;
assert(conf != NULL);
/*---------------------------------------------------
; Create the Lua state, which includes NO predefined
; functions or values. This is literally an empty
; slate.
;----------------------------------------------------*/
gL = luaL_newstate();
if (gL == NULL)
{
fprintf(stderr,"cannot create Lua state");
return false;
}
/*-----------------------------------------------------
; For the truly paranoid about sandboxing, enable the
; following code, which removes the string library,
; which some people find problematic to leave un-sand-
; boxed. But in my opinion, if you are worried about
; such attacks in a configuration file, you have bigger
; security issues to worry about than this.
;------------------------------------------------------*/
#ifdef PARANOID
lua_pushliteral(gL,"x");
lua_pushnil(gL);
lua_setmetatable(gL,-2);
lua_pop(gL,1);
#endif
/*-----------------------------------------------------
; Lua 5.2+ can restrict scripts to being text only,
; to avoid a potential problem with loading pre-compiled
; Lua scripts that may have malformed Lua VM code that
; could possibly lead to an exploit, but again, if you
; have to worry about that, you have bigger security
; issues to worry about. But in any case, here I'm
; restricting the file to "text" only.
;------------------------------------------------------*/
rc = luaL_loadfilex(gL,conf,"t");
if (rc != LUA_OK)
{
fprintf(stderr,"Lua error: (%d) %s",rc,lua_tostring(gL,-1));
return false;
}
rc = lua_pcall(gL,0,0,0);
if (rc != LUA_OK)
{
fprintf(stderr,"Lua error: (%d) %s",rc,lua_tostring(gL,-1));
return false;
}
/*--------------------------------------------
; the Lua state gL contains our configuration,
; we can now query it for values
;---------------------------------------------*/
/* ... */
return true;
}
-----[ END OF LINE ]-----
Yes, it's all too possible for someone to write:
-----[ Lua ]-----
(function() while true do end end)()
-----[ END OF LINE ]-----
in the configuration and block the process with 100% CPU (Central Processing
Unit) utilization, but as I stated in the code example, if that's a worry,
you have bigger security issues to worry about [2].
Another nice benefit of using Lua is string management. If you are only using
Lua for the configuration file, and once read, don't execute any more Lua
code, then there's no need to duplicate the strings for your codebase—just
keep using the strings directly from Lua. As long as you close the Lua state
at the end of the program, they'll be cleaned up for you. And speaking of
strings, you'll also have Lua's “long strings:”
-----[ Lua ]-----
long_string = [[
This is a long Lua string that can
span several lines. Escapes like '\n' don't work in this,
but then again,
you don't really need the '\n' here because they're part of the
string.
]]
long_string_2 = [=[
And if you want to embed a literal ']]' in a long string,
you can, no problems here.
]=]
-----[ END OF LINE ]-----
I use Lua for the configuration file for my blogging engine [3] (to see how I
pull the configuration from Lua [4]) which looks like:
-----[ Lua ]-----
name = "A Blog Grows in Cyberspace"
description = "A place where I talk about stuff in cyperspace."
class = "blog, rants, random stuff, programming"
basedir = "."
webdir = "htdocs"
lockfile = ".modblog.lock"
url = "
http://www.example.com/blog/"
adtag = "programming"
conversion = "html"
prehook = "./prehook_script"
posthook = "./posthook_script"
author =
{
name = "Joe Blog" ,
email = "
[email protected]",
}
templates =
{
{
template = "html",
output = webdir .. "/index.html",
items = "7d",
reverse = true,
posthook = "posthook_template_script"
},
{
template = "atom",
output = webdir .. "/index.atom",
items = 15,
reverse = true,
},
}
-----[ END OF LINE ]-----
But if you think it'll be too complicated to instruct devops as to when to
use a comma and not, you can always include semicolons at the end of each
line:
-----[ Lua ]-----
name = "A Blog Grows in Cyberspace";
description = "A place where I talk about stuff in cyperspace.";
class = "blog, rants, random stuff, programming";
basedir = ".";
webdir = "htdocs";
lockfile = ".modblog.lock";
url = "
http://www.example.com/blog/";
adtag = "programming";
conversion = "html";
prehook = "./prehook_script";
posthook = "./posthook_script";
author =
{
name = "Joe Blog";
email = "
[email protected]";
};
templates =
{
{
template = "html";
output = webdir .. "/index.html";
items = "7d";
reverse = true;
posthook = "posthook_template_script";
};
{
template = "atom";
output = webdir .. "/index.atom";
items = 15;
reverse = true;
};
};
-----[ END OF LINE ]-----
to simplify the configuration instructions (“just add a semicolon to the end
of each line … ”). One other benefit—comments. That's one of the biggest
complaints about using JSON (JavaScript Object Notation) as a configuration
file format—a lack of comments.
Also, you don't even have to mention you are using Lua as a configuration
file—most likely, no one will really notice anyway. I used Lua to configure
“Project: Sippy-Cup [5]” and “Project: Cleese [6]” at The Enterprise and no
one said anything about the format. It was also used for “Project: Bradenburg
[7]” (written by another team member) and there were no issues with that
either.
[1]
https://www.lua.org/
[2]
gopher://gopher.conman.org/0Phlog:2004/09/19.1
[3]
https://github.com/spc476/mod_blog
[4]
https://github.com/spc476/mod_blog/blob/20ec614b33a1e3d26893c2d3a70ff1bad4aa5c2d/src/blog.c#L695C8-L695C8
[5]
gopher://gopher.conman.org/0Phlog:2014/03/05.1
[6]
gopher://gopher.conman.org/0Phlog:2018/09/11.2
[7]
gopher://gopher.conman.org/0Phlog:2021/12/10.1
---
Discussions about this page
YAML config file? Pain? Try Lua | Lobsters
https://lobste.rs/s/sq5sss/yaml_config_file_pain_try_lua
YAML config file? Pain? Try Lua | Hacker News
https://news.ycombinator.com/item?id=37711974
Email author at
[email protected]