The Boston Diaries' Journal
 
[Most Recent Entries] [Calendar View] [Friends View]

Tuesday, October 10th, 2023

    Time Event
    1:54p
    YAML config file? Pain? Try Lua

    Several articles about using YAML for configuration have been making the rounds, yet rarely do I see Lua 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_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;
    }
    

    Yes, it's all too possible for someone to write:

    (function() while true do end end)()
    

    in the configuration and block the process with 100% CPU utilization, but as I stated in the code example, if that's a worry, you have bigger security issues to worry about.

    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 codebasejust 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:

    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.
    ]=]
    

    I use Lua for the configuration file for my blogging engine (to see how I pull the configuration from Lua) which looks like:

    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  = "joe@example.com",
    }
    
    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,
      },
    }
    

    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:

    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  = "joe@example.com";
    };
    
    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;
      };
    };
    

    to simplify the configuration instructions (just add a semicolon to the end of each line & ). One other benefitcomments. That's one of the biggest complaints about using JSON as a configuration file formata lack of comments.

    Also, you don't even have to mention you are using Lua as a configuration filemost likely, no one will really notice anyway. I used Lua to configure “Project: Sippy-Cup” and “Project: Cleese” at The Enterprise and no one said anything about the format. It was also used for “Project: Bradenburg” (written by another team member) and there were no issues with that either.

    1:54p
    Mowing Da Lawn

    I've taken over mowing the lawn over the past few months, and I've learned a thing or two:

    1. The electric mower is much nicer than the gas mower. Both are self-propelled, but the speed control is nicer on the electric than the gas. Also, the electric mower is easier to start.
    2. One bad thing about the electric mowerthe grass accumulates inside, and when it gets too thick, the mower stops. I then have to tip it over and scoop out the cut grass. The gas mower does a much better job of mulching the grass.
    3. Also, the electric mower has a safety mechanism where two latches that lock down the handle length (it can slide in and out, shortening or lengthening the handle) must be in the locked position, or the cutting blade won't start (just learned this today). Interesting.
    4. Over the past few months, I've learned that I can finish the entire yard (front, sides and back) with the two batteries we have, but only if the lawn isn't terribly overgrown. And by overgrown I mean longer than two weeks (we've been having a lot of rain lately).
    5. Moving the cars out of the driveway makes mowing the front lawn easier, as I can just simple go back and forth, crossing the driveway. I wish I could do that for the entire lawn, but alas, there are some trees, a fence, and oh yes, the house, in the way.
    6. Chez Boca is on a & I don't want to say a hill, because get real, we're in Florida where we give Kansas a run for its money for Flattest State in America. But there is an incline you can feel when walking towards the house. I suspect that when it rains, the water seeps into the ground, and because the ground here is nothing but sand, the water slowly seeps down the incline towards the street. I say this, because there's a two-foot strip of grass along the road that is gorgeous, but three weeks makes it a bit too long to cut with the electric mower without having to stop several times to clean it out.
    7. The north side of Chez Boca is the most annoying section to mow. It's too narrowthere's a fence on one side, the house on the other. There's also a large tree on the east end, and a shed on the west end, so there's no long stretches to mow. I now do that section after the front yard.
    8. The north-west side of Chez Boca is the second most annoying section to mow. It's next to the house, There are two small trees in the way (I mean, I like trees, but mowing around them, especially given they're very low to the ground, is annoying) and I've smashed several sprinkler heads a few times. I do that after doing the north side, as I'm not completely wrecked yet.
    9. I do the back yard last, when I'm completely wrecked from doing the north and north-west portionslike the front yard, I can do long stretches of back-and-forth mowing which helps when I'm exhausted from mowing (when I first took over mowing, I would end up with doing the north-west then north sections last, and that nearly killed me each time).
    10. After mowing the front yard, I move the cars back into the driveway, instead of after mowing the entire lawn. It's easier to do it then than when I'm about to pass out.

    I'm having a hard time seeing why Bunny would give up mowing the lawn. It's so much fun!

    << Previous Day 2023/10/10
    [Calendar]
    Next Day >>

The Boston Diaries   About InsaneJournal