?
Solved

return to calling cgi in bash script

Posted on 2013-11-01
6
Medium Priority
?
890 Views
Last Modified: 2013-12-25
i probably can't find this explained anywhere because it's ridiculously easy or I am not supposed to do this in the first place, however, I need to accomplish some form of this.

Throwing together a gui to allow our installers to do very basic linux functions on a little linux server we are using for a gateway.  The linux server is very barebones so I get to learn some bash.

In this example, I am popping a simple webform to get the date month and year and will run a simple bash script to change the date and then load up the main menu again.  All is fine up until I try and load up the URL I want.  I know many ways to do this in many languages, but bash isn't behaving.  I probably have a space somewhere I shouldn't or some such silliness, but I am willing to be humiliated to move on  :)

There is zero chance of security issues here so no scolding on the sudo stuff.

setdate cgi - trimmed down as much as possible:

#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Set the System Date"
echo "</title></head>"
echo "<body>"
echo "<FORM ACTION=dosetdate.cgi METHOD=POST>"
echo "Enter the date to set:"
echo "<select name=day size=1>"
echo "   <option value=1>1</option>"
echo "   <option value=2>2</option>"
echo "   <option value=3>3</option>"
echo "</select>"
echo "<select name=month size=1>"
echo "   <option value=JAN>JAN</option>"
echo "   <option value=FEB>FEB</option>"
echo "</select>"
echo "<select name=year size=1>"
echo "   <option value=2013>2013</option>"
echo "   <option value=2014>2014</option>"
echo "</select>"
echo "<input type=submit value=Submit>"
echo "</form>"
echo "</body></html>"

Open in new window


dosetdate.cgi - most of this is copy/pasted from a well known example online

#!/bin/bash
echo "Content-type: text/html"

# (internal) routine to store POST data
function cgi_get_POST_vars()
{
    # check content type
    # FIXME: not sure if we could handle uploads with this..
    [ "${CONTENT_TYPE}" != "application/x-www-form-urlencoded" ] && \
    #echo "bash.cgi warning: you should probably use MIME type "\
    #     "application/x-www-form-urlencoded!" 1>&2
    # save POST variables (only first time this is called)
    [ -z "$QUERY_STRING_POST" \
      -a "$REQUEST_METHOD" = "POST" -a ! -z "$CONTENT_LENGTH" ] && \
        read -n $CONTENT_LENGTH QUERY_STRING_POST
    # prevent shell execution
    local t
    t=${QUERY_STRING_POST//%60//} # %60 = `
    t=${t//\`//}
    t=${t//\$(//}
    QUERY_STRING_POST=${t}
    return
}

# (internal) routine to decode urlencoded strings
function cgi_decodevar()
{
    [ $# -ne 1 ] && return
    local v t h
    # replace all + with whitespace and append %%
    t="${1//+/ }%%"
    while [ ${#t} -gt 0 -a "${t}" != "%" ]; do
    v="${v}${t%%\%*}" # digest up to the first %
    t="${t#*%}"       # remove digested part
    # decode if there is anything to decode and if not at end of string
    if [ ${#t} -gt 0 -a "${t}" != "%" ]; then
        h=${t:0:2} # save first two chars
        t="${t:2}" # remove these
        v="${v}"`echo -e \\\\x${h}` # convert hex to special char
    fi
    done
    # return decoded string
    echo "${v}"
    return
}

# routine to get variables from http requests
# usage: cgi_getvars method varname1 [.. varnameN]
# method is either GET or POST or BOTH
# the magic varible name ALL gets everything
function cgi_getvars()
{
    [ $# -lt 2 ] && return
    local q p k v s
    # prevent shell execution
    t=${QUERY_STRING//%60//} # %60 = `
    t=${t//\`//}
    t=${t//\$(//}
    QUERY_STRING=${t}
    # get query
    case $1 in
    GET)
        [ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&"
        ;;
    POST)
        cgi_get_POST_vars
        [ ! -z "${QUERY_STRING_POST}" ] && q="${QUERY_STRING_POST}&"
        ;;
    BOTH)
        [ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&"
        cgi_get_POST_vars
        [ ! -z "${QUERY_STRING_POST}" ] && q="${q}${QUERY_STRING_POST}&"
        ;;
    esac
    shift
    s=" $* "
    # parse the query data
    while [ ! -z "$q" ]; do
    p="${q%%&*}"  # get first part of query string
    k="${p%%=*}"  # get the key (variable name) from it
    v="${p#*=}"   # get the value from it
    q="${q#$p&*}" # strip first part from query string
    # decode and evaluate var if requested
    [ "$1" = "ALL" -o "${s/ $k /}" != "$s" ] && \
        eval "$k=\"`cgi_decodevar \"$v\"`\""
    done
    return
}



# register all GET and POST variables
cgi_getvars BOTH ALL

datestring="$day $month $year 01:00:00"

/usr/bin/sudo /bin/su -c "/bin/date -s '$datestring' >/dev/null 2>&1"

url="http://172.22.22.22/cgi-bin/setdate.cgi"

echo "Location $url"

Open in new window



Now I am very aware that the final line could not possibly work.  However, I have not been able to come up with anything else.  In a perl script, I would simply print this and it would open the url specified.  How can this be accomplished in bash?

Thanks in advance

O
0
Comment
Question by:Owen_Parker
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
6 Comments
 
LVL 28

Accepted Solution

by:
FishMonger earned 2000 total points
ID: 39618753
I don't do bash scripting but, I'd start by removing the output of the Content-Type on line 2.

Also, I believe you need a colon after Location.
echo "Location: $url"

Open in new window

This might be a silly question but, since it sounds like you already know how to do this in Perl, why not use it instead of bash?  You'd be able to reduce the dosetdate.cgi script by about 80%.

Here's the minimalist version of the perl script.
#!/usr/bin/perl

use strict;
use warnings;
use CGI;

my $cgi        = CGI->new;
my %param      = $cgi->Vars;
my $datestring = "$param{day} $param{month} $param{year} 01:00:00";
my $url        = "http://172.22.22.22/cgi-bin/setdate.cgi";

# there are multiple ways to run this command, and this may not be the best
system( qq(/usr/bin/sudo /bin/su -c "/bin/date -s '$datestring' >/dev/null 2>&1") );

print $cgi->redirect($url);

Open in new window

0
 

Author Comment

by:Owen_Parker
ID: 39618778
Hi FishMonger

You are right on the colon after location.  That was a typo somehow.  As for doing this in bash versus perl, I had inherited this little project and the device it is running on has only a 1 GB flash for storage and I was told it was a very stripped down version of OpenSuse and not much could be done on it.  When asked to add some sort of interface, it was suggested it be done in bash due to the limitations.  So, I did it all in bash.  This and one other similar function is all that is left.  And this one little part is all that is left of those.  However, before i started answering you, I asked myself when was the last time I saw ANY linux install that didn't have perl installed.  So I type perl -v and lo and behold, perl is installed after all.  LOL

Learned a couple lessons there I guess.

However, now there is this issue with bash, and I must resolve it.  Knowing I can finish this in 15 minutes now is reassuring.  but I'm not very good at dealing with an unresolved issue, other than to find the solution!  

I thank you for asking the very obvious question and leading me to spend the 1.3 seconds checking something i should have checked a week ago!  :)
0
 
LVL 28

Expert Comment

by:FishMonger
ID: 39618864
So, did removing the outputting of the unwanted content-type header and adding the colon fix the problem?
0
Is Your Team Achieving Their Full Potential?

74% of employees feel they are not achieving their full potential. With Linux Academy, not only will you strengthen your team's core competencies but also their knowledge of of the newest IT topics.

With new material every week, we'll make sure that you stay ahead of the game.

 

Author Comment

by:Owen_Parker
ID: 39619169
No, sorry, I thought that was implied.  Same basic end result.  The echoing of the string "Location: and the URL to the screen.
0
 

Author Closing Comment

by:Owen_Parker
ID: 39620478
I never did receive the solution to my query, but since I could do it in Perl, I did.  I will see about getting the solution from my engineer Monday and will post it here for future reference if it is resolvable...  Thanks for your input FishMonger...  It was surely helpful...
0
 
LVL 28

Expert Comment

by:FishMonger
ID: 39620489
You're welcome. :)
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
In threads here at EE, each comment has a unique Identifier (ID). It is easy to get the full path for an ID via the right-click context menu. However, we often want to post a short link within a thread rather than the full link. This article shows a…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
Suggested Courses

718 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question