Channels ▼

Al Williams

Dr. Dobb's Bloggers

Compiling Shell Scripts

June 23, 2012

The last few weeks I've been playing with the BeagleBone — an inexpensive little Linux box aimed at embedded systems. Naturally, you can program it as you would any similar board using C, C++, or a variety of other Linux languages. However, I've been probing into how much use the shell (especially bash) might be for some simple embedded tasks.

Although many of the tasks I've tackled have been pretty straightforward, bash is actually quite powerful and makes for quick prototyping and even development (yes, there is a bash debugger available). There is at least one objection to using script, though. Since the program is just a text file and it is fairly easy to understand, it might be tempting for users to modify the program with good intentions or bad.

I had this exact problem a number of years ago on a UNIX system. A very complex build system would break and the culprit would be some developer who had to "fix" something in one of the scripts. After a few late nights figuring that sort of thing out, I decided I had to do something.

Ideally, what I wanted was a shell script compiler. That's a pretty big task, though. You have to track changes in the shell — lots of extra work if you want to support more than one shell or (as I did) more than one platform. I decided to take a shortcut, and a program I called scbind was born.

The idea behind scbind is simple. At a very high level it takes a script as input and outputs an executable file. Just like a compiler. However, it isn't really a compiler. Instead, it simply embeds an encrypted version of the script in the executable. The executable launches the interpreter and feeds it a named pipe (something I talked about in a different way last time). As you might guess, the executable then decodes the script and feeds it to the interpreter via the pipe.

The interpreter doesn't have to be the shell. Almost anything that you can use with the #! syntax will work. The executable, then, is really just boilerplate to do the decoding. The encoded text is simply a file with a C-language array in it. A shell script (what else?) does the work of calling the system C compiler to generate the executable, so there's no need to worry about the back end of the "compilation."

If you download scbind, you'll see that the driver shell script normally discards the C source code after the compiler completes. But the -s option will save that file. You can probably install the whole thing on the BeagleBone, but you can also let the compiler give you the C file, move that to the BeagleBone, and compile it there.

The encoder/decoder is split out of the main file so you can use your own scheme. In my case, I wasn't worried about high security. I just wanted to keep casual hackers out. My encoder is simple:

#if HAVE_MEMFROB != 1
void *memfrob(char *s, size_t len)
{
  char *s0=s;
  while (len--) {
    *s=*s^0x2A;
    s++;
  }
}

#endif


char *encode(char *s, size_t len, size_t *lenout)
{
  if (lenout) *lenout=len;
  memfrob(s,len);
  return s;
}

If you haven't run into memfrob() before, it simply XORs a string with the number 42 (which, I am sure, is a nod to The Hitchhiker's Guide to the Galaxy). Running a string through memfrob once produces seeming gibberish. Running that gibberish back through produces the original string. The examples directory shows a high-low game "compiled" from a shell script, along with examples with awk and Perl.

Of course, you don't get the other benefits of compilation. The code doesn't stand alone, nor will it perform better (in fact, I'd expect it to perform slightly worse). But it isn't much different from running a script and it will keep casual, prying eyes out of your system.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video