Help with ksh script

Hello folks;
Thanks in advance for any help!

Please bear with me on this one. I need help writing a KSH script (must be in ksh) to do the following:

  • Return usage information if no arguments are given.
  • Always return 0, for success.
  • Take as arguments:
    [list]
  • <filename:mandatory> A path to a file to be transferred.
  • <other: optional> Any number of var=val pairs supplied by the caller.
    [/list]
  • Make an HTTP POST to server A, to a specified URL.
    [list]
  • The file specified will be sent as the POST data.
  • Any supplied optional var=val pairs will be sent as parameters in the URL.
    [/list]
  • The Content-Type header in the request should match the extension of the provided file. For an unknown type, the default should be �application/octet-stream�.

The standard questions/limitations apply here:

  • What is your OS?
  • Which version of ksh?
    Namely: do you use ksh88 or ksh93?
  • Is this homework/coursework?
    If yes, please re-post in the special forum for such questions, special rules apply there.

In general i see the following problematic provisions with your requirements:

Note that there is a fine difference between "arguments", "options" and "arguments to options". If you want exactly one filename and any number of name=val pairs you might consider using an option for the filename (with the filename as argument to the option) and the name=val pairs as (open-ended list of) arguments to the script. A command line would look like this:

script -f /path/to/file var1=val1 var2=val2

This is easy to implement using the getopts -builtin of ksh. I suggest you read its man page. Provisions for automatically displaying some usage text if the parameters given are not valid is also easily done using getopts .

I hope this helps.

bakunin

Thanks Bakunin for getting back to me.
to answer your questions:

  1. The OS is RedHat
  2. I don't care which ksh we use but I think ksh93 is more advanced
  3. It's not homework or coursework.

I think passing the file name with one argument should work.

Yes, until you have a filename of "var=val", which is possible. Of course you can first examine every argument passed and if a file with that name exists, take it as a filename and if not, then examine if it is a well-formed item of the form "var=val". This is possible but it is easier (read: saves programming effort) to distinguish (for the script) between filenames and arguments up front.

Yes, but it won't matter that much here. It is quite possible to do it in both ksh-versions. Notice, though, that what some Linux-distributions (i have no experience with RedHat) have labeled as a Korn Shell is in fact not a real Korn Shell but something awful (mksh, pdksh, etc.).

I say that because one of my scripts just failed on a SLES 12 system, whereas it ran perfectly on SLES 11. Upon inspection we found that SLES 12 has only "pdksh" (which is a mixture of a bash-like shell and some ksh-isms but not even compatible with ksh88) but names it "ksh". In fact the original ksh is not even in the SLES-12-repository.

What have you tried so far and where were you stuck?

I hope this helps.

bakunin

So far i have this. Any help making it better would be greatly appreciated (especially with the curl part..

#!/bin/ksh

# Check that we got args
if [ ${#} -eq 0 ]
then
   echo "Usage is ..."
   exit 255;
fi

# Get filename from first arg
PostFilename=$1
shift

# Handle Args
argNum=1
while [ $# -gt 0 ]
do
  echo "$1"
  argArray[argNum]=$1
  ((argNum=argNum+1))
  shift
done

# POST file
echo $PostFilename
echo ${argArray[@]}
# curl -X POST -d $PostFilename http://google.com ${argArray[@]}

What's wrong with that? And, why don't you call it like

curl -X POST -d $PostFilename http://google.com $@

I think what you have is a good start. Before i suggest code a few general remarks, though:

whatever a user supplies to a program (this is not restricted to scripts) should be tested for plausibility/formal correctness before the input is used. If you get a file name: test if the file is there and if it is readable. If you expect "arg=val" lines test if they are indeed of the form you suppose they are.

Another point is the handling of variables: long ago i started to declare every variable i use before i use it. I know, one doesn't need to do so in ksh, but i like the documentation which is automatically generated this way.

third, as i already mentioned, handling parameters/arguments is easier with getopts . This part:

#!/bin/ksh

# Check that we got args
if [ ${#} -eq 0 ]
then
   echo "Usage is ..."
   exit 255;
fi

# Get filename from first arg
PostFilename=$1
shift

# Handle Args
argNum=1
while [ $# -gt 0 ]
do
  echo "$1"
  argArray[argNum]=$1
  ((argNum=argNum+1))
  shift
done

done with getopts and a few plausibility checks might look like this:

#!/bin/ksh

f_usage ()
{
print -u2 - "Here goes the usage information...."

exit 1
}


f_CheckArg ()
{
# checks a single "arg=val" if it is correctly formed
# checks could be more elaborate than that:

if [ "${1}" == "${1#*=}" ] ; then          # something before the "="?
     return 1
fi
if [ "${1}" == "${1%=*}" ] ; then          # something after the "="?
     return 1
fi

return 0
}


# main ()

typeset chOpt=""                                 # option buffer
typeset chArgs="$*"                              # save cmd line
typeset fIn=""                                   # input file
# typeset achArgs[]                              # arg=val strings

while getopts ":h:f:v:" chOpt ; do               # commandline
     case $chOpt in
          "f")
               if [ -n "$fIn" ] ; then
                    print -u2 - "Do not specify more than one file."
                    exit 2
               fi
               if [ ! -r "$OPTARG" ] ; then
                    print -u2 - "File $OPTARG does not exist or is not readable."
                    exit 2
               fi
               fIn="$OPTARG"
               ;;

          "h")
               f_usage
               ;;

          "?")
               if [ "$chOpt" == "?" -a "$OPTARG" == "?" ] ; then
                    f_usage
               else
                    print -u2 - "unknown option -${OPTARG}"
               fi
               ;;

     esac
done
shift $(( OPTIND -1 ))

if [ -n "$fIn" ] ; then
     print -u2 - "No filename specified, aborting...."
     exit 2
fi

# Handle Args
while [ -n "$1" ] ; do
     if f_CheckArg "$1" ; then   
          typeset achArgs[((${#achArgs[@]}+1))]="$1"
     else
          print -u2 - "argument $1 is not well-formed"
          exit 3
     fi
     shift
done

Call the script like:

script -f /path/to/file arg1=val1 arg2=val2 ...

or

script -?
script -h

I hope this helps.

bakunin

Thanks Bakunin so much for your help.. I will make some modification and run it like you suggested and let you know my friend. I truly appreciate the help