Bourne/ Bash Shell CGI Scripts

Usually I do my server-side scripting in Perl, but some time ago when writing CGI scripts for an embedded system I ran into memory and flash space contraints. Because the system used Busybox, I had the Bourne compatible ash shell available. So I wrote a very small Bourne shell script to include in my CGI scripts, which I share here, maybe it is of use to someone. (Of course this will work in the Bash shell as well.)

Caveat Emptor: This code is probably one big security hole waiting to happen, interactive shells and the Internet don’t mix very well, please use wisely. :)

This is the script to be included from each individual CGI:

(cgi.cgi) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/sh

# cgi - CGI framework voor bourne shell
# Hessel Schut, hessel@vpro.nl, 2006-04-07

_DEBUG_=

if [ "${REQUEST_METHOD}" = "POST" ]
then
  POST_QUERY_STRING=`dd bs=1 count=${CONTENT_LENGTH} 2>/dev/null`
  if [ "${QUERY_STRING}" != "" ]
  then
      QUERY_STRING=${POST_QUERY_STRING}"&"${QUERY_STRING}
  else
      QUERY_STRING=${POST_QUERY_STRING}"&"
  fi
fi

echo "Content-type: text/plain"; echo

_IFS=${IFS}; IFS=\&
i=0
for _VAR in ${QUERY_STRING}
do
  if [ ${_DEBUG_} ]
  then
      i=`expr $i + 1`; echo "--- ENTER LOOP $i ---"
      echo _VAR: ${_VAR}
      echo -n variable: `echo ${_VAR} | cut -d= -f1`" "
      echo value: `echo ${_VAR} | cut -d= -f2`
  fi

  eval "`echo F_${_VAR} | cut -d= -f1`=`echo ${_VAR} | cut -d= -f2`"

  if [ ${_DEBUG_} ]
  then
      echo "--- EXIT LOOP $i ---"
  fi
done
IFS=${_IFS}
unset i _IFS _VAR

if [ ${_DEBUG_} ]
then
  echo query string: ${QUERY_STRING}
  echo post-part of query string: ${POST_QUERY_STRING}
fi

This code can be then be used in your CGI scripts like so, for example this little script, that simply displays all posted variables. All posted variables, together with those in the query string in the URL are prefixed with F_ which makes this small example very simple:

(test.cgi) download
1
2
3
4
5
6
#!/bin/sh

. ./cgi.cgi

echo POSTed or GETted variables:
set | grep -e '^F_'

This example uses the following form to provide input:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="iso-8859-1"?>

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head> </head>

<body>
        <form method="POST" action="cgi-bin/test.cgi?get_var=blah">
        <input type="text" name="field1"><br>
        <input type="text" name="field2"><br>
        <input type="text" name="field3"><br>
        <input type="submit">
        </form>
</body>
</html>

All the code on this page is available in a tarball here: cgi.tar.gz

Comments