#!/bin/bash # Written by oga83, amended by Jibap # Evolutions by JacquesF # See https://routeur4g.fr/discussions/discussion/2384/tuto-envoyer-des-sms-en-ligne-de-commande # This script uses the following programs: # 'host' for name resolution # 'sha256sum' and 'base64' for password encryption # 'curl' for exchanges with the router # A debug mode can be defined with TRACE_LEVEL variable: # 0 => disable traces # 1 => to see responses # 2 => to see responses and connection traces # If '-t' option is used as parameter, TRACE_LEVEL can be forced to a new value # If '-x' option is used as parameter, script traces are activated # A configuration file can be used to store router connection settings: # this file is defined in the CONFIG_FILE variable. # ROUTER_ADDR # IPv4 or Hostname format (the 'host' command must be available) # ROUTER_USER # String or empty (use 'admin' instead) # ROUTER_PASS # String # You can create this file (or a new file if exist) by using '-C' or '--create' option PRG_VERSION="1.0" CONFIG_FILE="${HOME}/.huawei.cfg" HEADER_FILE="/tmp/headers.tmp" CURL_OPTION="--silent" RAW_DISPLAY=false TRACE_LEVEL=0 PROG_ACTION="" Localize () { # Translation of program messages if [ "${LANG:0:2}" = "fr" ] ; then PRG_ERR1="Impossible de trouver le programme" PRG_ERR2="Les programmes nécessaires ne sont pas disponibles" PRG_ERR3="La résolution de nom est impossible, l'adresse du routeur DOIT être au format IP" CNF_ERR1="Impossible de résoudre l'adresse IP de" CNF_ERR2="Routeur inaccessible, impossible de continuer !" CNF_ERR3="Le mot de passe est obligatoire" CNF_ERR4="L'utilisateur n'est pas défini, utilisation du compte 'admin' à la place..." CNF_ERR5="Impossible de lire le fichier" CNF_MSG1="Le fichier de configuration '${CONFIG_FILE}' existe déjà, un nouveau fichier a été créé dans" CNF_MSG2="Le fichier de configuration '${CONFIG_FILE}' a été créé" CNF_MSG3="Vous pouvez spécifier un fichier de configuration particulier en exécutant le programme avec l'option '-f MonFichier'" BOX_ERR1="Mauvais type de boîte" BOX_ERR2="seuls les types 'Inbox' (1) et 'Outbox' (2) sont autorisés" SMS_ERR1="Numéro(s) de téléphone incorrect(s)" SMS_ERR2="Le message est obligatoire" OPT_ERR1="Option inconnue" else PRG_ERR1="Can't find the program" PRG_ERR2="The necessary programs are not available" PRG_ERR3="Name resolution is not possible, router address MUST be in IP format" CNF_ERR1="Unable to resolv IP address of" CNF_ERR2="Router unreachable, unable to continue!" CNF_ERR3="The password is mandatory" CNF_ERR4="User is undefined, use 'admin' account instead..." CNF_ERR5="Unable to read file" CNF_MSG1="The configuration file '${CONFIG_FILE}' already exists, a new file has been created in" CNF_MSG2="The configuration file '${CONFIG_FILE}' has been created" CNF_MSG3="You can specify a particular configuration file by running the program with the '-f MyFile' option" BOX_ERR1="Incorrect type of box" BOX_ERR2="only the 'Inbox' and 'Outbox' types are authorized" SMS_ERR1="Wrong phone number(s)" SMS_ERR2="The message is mandatory" OPT_ERR1="Unknown option" fi } DisplayHelp () { if [ "${LANG:0:2}" = "fr" ] ; then cat << EOT Utilisation : $0 [CONNEXION] OPTION PARAMETRES Gestion des SMS pour les routeurs Huawei. Par défaut, les paramètres de connexion sont lus depuis le fichier '${CONFIG_FILE}'. Il est possible de forcer les paramètres suivants avec les options : -f, --file ConfigFile Charge les paramètres de connexion depuis le fichier 'ConfigFile' ou -a, --address Adresse IP ou Nom d'hôte du routeur -u, --user Login ('admin' si vide ou indéfini) -p, --password Mot de passe pour se connecter au routeur Si la commande 'host' n'est pas disponible, alors le routeur DOIT être défini via son adresse IP. Si un ou plus de ces quatre paramètres sont présents, ils DOIVENT se trouver au début de la commande. Dans ce cas, les paramètres correspondants du fichier de configuration sont écrasés. Les options possibles (avec les paramètres attendus) sont les suivantes : -c, --count [Boîte] Affiche le nombre de SMS présent dans la boîte 'Boîte' indiquée Le type de boîte est optionnel et peut être 'Unread' 'Inbox' 'Outbox' 'Draft' 'Deleted' -C, --create-file Création du fichier de configuration '${CONFIG_FILE}' Si ce fichier est déjà présent, un nouveau fichier sera créé sans modifier le précédent. -d, --delete Boîte [Index] Efface tous les SMS (par défaut) ou le SMS indiqué par 'Index' dans la boîte 'Boîte' 'Boîte' peut prendre la valeur 'Inbox' ou 'Outbox' (ou respectivement les codes 1 et 2) -g, --get Boîte Affiche le contenu de la boîte 'Boîte' au format json 'Boîte' peut prendre la valeur 'Inbox' ou 'Outbox' (ou respectivement les codes 1 et 2) -h, --help Affiche cette aide -r, --read Marque tous les SMS contenus dans la boîte 'Inbox' comme lus -s, --send Numero(s) Texte Envoyez un SMS au téléphone 'Numéro' avec le message 'Texte' Le numéro peut être spécifié au format local ou international (+Numéro) Une liste peut être donnée en séparant chaque numéro par ';' ex : +33601234567;0606060606 -v, --version Affiche la version du programme Une seule des options (avec ses paramètres) peut être utilisée à la fois. Les options suivantes peuvent être utilisées en sus en cas de problème : -l, --lang Code Change la langue de l'aide et des messages utilisés dans le script Actuellement, seul le code 'fr' est traité, toute autre valeur affichera les messages en anglais La langue est défini par les 'locales', cette option permet de corriger une détection incorrecte -R, --raw Affiche les données reçues sans aucun traitement Cette option est utile dans le cas où l'on souhaite un traitement personnalisé des réponses -t, --trace 0|1|2 Masque (0), affiche les réponses (1) et les connexions (2) au routeur Le niveau de trace est défini par la variable TRACE_LEVEL, cette option permet de forcer sa valeur -x Active les traces internes au script (mode debug) EOT else cat << EOT Utilisation : $0 [CONNECTION] OPTION PARAMETERS SMS management for Huawei routers. By default, the connection parameters are read from the file '${CONFIG_FILE}'. It is possible to force the following parameters with the options: -f, --file ConfigFile Loads connection parameters from 'ConfigFile' or -a, --address IP address or Hostname of the router -u, --user Login ('admin' if empty or undefined) -p, --password Password to connect to the router If the 'host' command is not available, then the router MUST be defined via its IP address. If one or more of these four parameters are present, they MUST be at the beginning of the command. In this case, the corresponding parameter(s) of the configuration file will be overridden. The possible options (with the expected parameters) are the following: -c, --count [Box] Displays the number of SMS present in the indicated box The box type is optional and can be 'Unread' 'Inbox' 'Outbox' 'Draft' 'Deleted' -C, --create-file Creating the configuration file '${CONFIG_FILE}' If this file is already present, a new file will be created without modifying the previous one -d, --delete Box [Index] Delete all SMS (default) or the SMS indicated by 'Index' in the box 'Box' 'Box' can take the value 'Inbox' or 'Outbox' (or codes 1 and 2 respectively) -g, --get Box Displays the contents of the box 'Box' in json format 'Box' can take the value 'Inbox' or 'Outbox' (or codes 1 and 2 respectively) -h, --help Displays this help -r, --read Marks all SMS contained in the box 'Inbox' as read -s, --send Number(s) Text Send an SMS to the phone 'Number' with the message 'Text' The number can be specified in local or international format (+Number) A list can be given by separating each number by ';' ie: +33601234567;0606060606 -v, --version Displays the program version Only one of the options (with its parameters) can be used at a time. The following options can be used in addition in case of problem: -l, --lang Code Changes the language of help and messages used in the script Currently only 'fr' code is processed, any other value will display messages in English The language is defined by the 'locales', this option allows to correct an incorrect detection -R, --raw Displays received data without any processing This option is useful if you want a personalized treatment of responses -t, --trace 0|1|2 Mask (0), show responses (1) and connections (2) to router The trace level is defined by the TRACE_LEVEL variable, this option allows you to force its value -x Enable internal script traces (debug mode) EOT fi } WriteError () { # Send message to error output echo -e "$1" >&2 } WriteDebug () { # Parameters TitleTxt: $1 (optional) / DebugTxt: $2 (optional) DashText="================================================================================" # Add space around the title if necessary [ -z "$1" ] && TitleTxt="" || TitleTxt=" $1 " # Add NewLine at the begin of the debug text if exist [ -z "$2" ] && DebugTxt="" || DebugTxt="\n$2" # Size of the different texts FullSize=${#DashText} TextSize=${#TitleTxt} HalfSize=$(((FullSize / 2) - (TextSize / 2))) # Start and end of dashes HalfDash=${DashText:0:${HalfSize}} # Inserting the title at the middle of the dashes TitleStr="${HalfDash}${TitleTxt}${HalfDash}" # Writing new title with debug text (if exist) echo -e "${TitleStr:0:${FullSize}}${DebugTxt}" >&2 } CheckConfig () { local RET_CODE=0 # Testing hostname to IP address translation, warning if failure which "host" >/dev/null 2>&1 || WriteError "${PRG_ERR3}" # Testing necessary programs for PRG_NAME in "curl" "sha256sum" "base64" ; do if ! which "${PRG_NAME}" >/dev/null 2>&1 ; then let RET_CODE+=1 WriteError "${PRG_ERR1} '${PRG_NAME}'" fi done # Abort if a program is missing if [ ${RET_CODE} -ne 0 ] ; then WriteError "${PRG_ERR2}\n" exit 1 fi # Check format of router address if [ "${ROUTER_ADDR//[0-9]}" != "..." ] ; then # Convert hostname to IP address ROUTER_NAME="${ROUTER_ADDR}" ROUTER_ADDR=$(host ${ROUTER_ADDR} 2>/dev/null | awk '{print $NF}') fi # Check validity of the parameters if [ -z "${ROUTER_ADDR##*NXDOMAIN*}" ] ; then # Unknown address (DNS name resolution failure or 'host' program unavailable) WriteError "${CNF_ERR1} '${ROUTER_NAME}'\n" exit 1 elif ! ping -c1 -w1 ${ROUTER_ADDR} >/dev/null 2>&1 ; then # Router unreachable WriteError "${CNF_ERR2}\n" exit 1 elif [ -z "${ROUTER_PASS}" ] ; then # Empty password WriteError "${CNF_ERR3}\n" exit 1 elif [ -z "${ROUTER_USER}" ] ; then # Empty user, use 'admin' WriteError "${CNF_ERR4}\n" ROUTER_USER="admin" fi } CreateConfig () { # Determining the file to create if [ -s "${CONFIG_FILE}" ] ; then # Creating a new file in Home directory, the old one is not modified echo -e 'ROUTER_ADDR="192.168.8.1"\nROUTER_USER="admin"\nROUTER_PASS="YourPassword"' > "${CONFIG_FILE}-$$" WriteError "${CNF_MSG1} '${CONFIG_FILE}-$$'" else # Creating the file in Home directory echo -e 'ROUTER_ADDR="192.168.8.1"\nROUTER_USER="admin"\nROUTER_PASS="YourPassword"' > "${CONFIG_FILE}" WriteError "${CNF_MSG2}" fi # Possibility to specified a particulary file WriteError "${CNF_MSG3}\n" } CleanUp () { # Remove temporary file rm -f "${HEADER_FILE}" 2>/dev/null } ProcessRouterResponseHeader () { # Get token from header NEWTOKEN=$(awk '/__RequestVerificationTokenone: / {print $2}' ${HEADER_FILE}) [ ! -z "${NEWTOKEN}" ] && TOKEN="${NEWTOKEN}" NEWTOKEN=$(awk '/__RequestVerificationToken: / {print $2}' ${HEADER_FILE}) [ ! -z "${NEWTOKEN}" ] && TOKEN="${NEWTOKEN}" NEWSESSIONID=$(awk '/Set-Cookie: SessionID=/ {print substr($2,0,138)}' ${HEADER_FILE}) [ ! -z "${NEWSESSIONID}" ] && SESSIONID="${NEWSESSIONID}" # Display traces if activated if [ ${TRACE_LEVEL} -ge 2 ] ; then WriteDebug "ProcessRouterResponseHeader" "$(grep -ve '^[[:space:]]*$' ${HEADER_FILE})" WriteDebug "" "==> TOKEN:\n${TOKEN}" WriteDebug "" "==> SESSIONID:\n${SESSIONID}" WriteDebug ; echo fi } GetRouterData () { local RelativeUrl="$1" # Get the response from the router RESPONSE=$(curl $CURL_OPTION \ --request GET http://${ROUTER_ADDR}${RelativeUrl} \ --dump-header ${HEADER_FILE} \ -H "Cookie: ${SESSIONID}" \ -H "__RequestVerificationToken: ${TOKEN}" \ -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \ ) # Display traces if activated if [ ${TRACE_LEVEL} -ge 2 ] ; then WriteDebug "GetRouterData" "==> URL:\nhttp://${ROUTER_ADDR}${RelativeUrl}" WriteDebug "" "==> RESPONSE:\n${RESPONSE}" WriteDebug ; echo fi ProcessRouterResponseHeader } GetSessionToken () { # A new token is mandatory for each action GetRouterData "/api/webserver/SesTokInfo" SESSIONID="SessionID="$(echo "${RESPONSE}" | grep -oPm1 "(?<=)[^<]+") TOKEN=$(echo "${RESPONSE}" | grep -oPm1 "(?<=)[^<]+") } PostRouterData () { local RelativeUrl="$1" ; local Data="$2" ; local bAskNewToken="$3" # Get new token if activated [ ${bAskNewToken:=0} -ne 0 ] && GetSessionToken # Get the response from the router RESPONSE=$(curl $CURL_OPTION \ --request POST http://${ROUTER_ADDR}${RelativeUrl} \ --dump-header ${HEADER_FILE} \ -H "Cookie: ${SESSIONID}" \ -H "__RequestVerificationToken: ${TOKEN}" \ -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" --data "${Data}" \ ) # Display traces if activated if [ ${TRACE_LEVEL} -ge 2 ] ; then WriteDebug "PostRouterData" "==> URL:\nhttp://${ROUTER_ADDR}${RelativeUrl}" WriteDebug "" "==> RESPONSE:\n${RESPONSE}" WriteDebug ; echo fi ProcessRouterResponseHeader } Connect () { # Get initial SessionID and RequestVerificationToken GetSessionToken # Encoding login datas PASSWD_TYPE="4" PASSWD_CODE=$(printf ${ROUTER_PASS} | sha256sum | head -c64 | base64 -w0) CREDENTIALS=$(printf "%s%s%s" ${ROUTER_USER} ${PASSWD_CODE} ${TOKEN} | sha256sum | head -c64 | base64 -w0) } Login () { local XML_REQUEST # Constructing the XML request XML_REQUEST+="" XML_REQUEST+="${ROUTER_USER}" XML_REQUEST+="${CREDENTIALS}" XML_REQUEST+="${PASSWD_TYPE}" XML_REQUEST+="" # Sending the request PostRouterData "/api/user/login" "${XML_REQUEST}" } Logout () { local XML_REQUEST # Constructing the XML request XML_REQUEST+="" XML_REQUEST+="1" XML_REQUEST+="" # Sending the request with a new token PostRouterData "/api/user/logout" "${XML_REQUEST}" 1 } CountSMS () { # Forcing the parameter to lowercase to avoid typing errors local BoxType="${1,,}" ; local BoxList="Unread Inbox Outbox Draft Deleted" # If a type of box is indicated, restrict the list to this value [ "${BoxType:=all}" != "all" ] && BoxList="${BoxType^}" # Get all counters GetRouterData "/api/sms/sms-count" # Only displays data if 'RAW' mode is enabled ${RAW_DISPLAY} && { echo "${RESPONSE}" ; return ; } # Show just the value for a single type, or each counter otherwise for TypeBox in ${BoxList} ; do [ "${BoxType}" = "all" ] && echo -e "${TypeBox}=\c" echo "${RESPONSE}" | grep -oP "(?<=)[[:digit:]]+" done # Display traces if activated if [ ${TRACE_LEVEL} -ge 1 ] ; then WriteDebug "CountSMS" "==> BoxType:\n'$1' -> ${BoxList}" WriteDebug "" "==> RESPONSE:\n${RESPONSE}" WriteDebug ; echo fi } GetSMS () { # Forcing the parameter to lowercase to avoid typing errors local XML_REQUEST ; local BoxType="${1,,}" # Converting BoxType to correct value for XML query case "${BoxType}" in inbox | 1 ) TypeBox=1 ;; outbox | 2 ) TypeBox=2 ;; * ) WriteError "${BOX_ERR1} '$1', ${BOX_ERR2}\n" ; return 1 ;; esac # Constructing the XML request XML_REQUEST+="" XML_REQUEST+="1" XML_REQUEST+="20" XML_REQUEST+="${TypeBox}" XML_REQUEST+="0" XML_REQUEST+="0" XML_REQUEST+="1" XML_REQUEST+="" # Sending the request with a new token PostRouterData "/api/sms/sms-list" "${XML_REQUEST}" 1 # Retrieving indexes of all messages in an array SMS_INDEXES=($(echo "$RESPONSE" | grep -oP "(?<=)[[:digit:]]+")) # Displays data if requested if ${RAW_DISPLAY} ; then # Only displays data if 'RAW' mode is enabled echo "${RESPONSE}" return elif [ "${PROG_ACTION:0:6}" = "GetSMS" ] ; then # Show result if requested (only for '-g / --get' option) echo -e "${RESPONSE}\n" fi # Display traces if activated if [ ${TRACE_LEVEL} -ge 1 ] ; then WriteDebug "GetSMS" "==> BoxType [1=Inbox, 2=Outbox]:\n$1 -> ${TypeBox}" WriteDebug "" "==> SMS_INDEXES:\n${SMS_INDEXES[*]}\n==> TOTAL:\n${#SMS_INDEXES[*]}" WriteDebug "" "==> RESPONSE:\n${RESPONSE}" WriteDebug ; echo fi } SendSMS () { local XML_REQUEST ; local SMS_Nber # Storing the number(s) in an array (IFS is redefined just for this command) IFS=';' read -ra SMS_Nber <<< "${SMS_List}" # Constructing the XML request XML_REQUEST+="" XML_REQUEST+="-1" XML_REQUEST+="" for ((i=0;i<${#SMS_Nber[*]};i++)) ; do XML_REQUEST+="${SMS_Nber[$i]}" done XML_REQUEST+="" XML_REQUEST+="" XML_REQUEST+="${SMS_Text}" XML_REQUEST+="${#SMS_Text}" XML_REQUEST+="1" XML_REQUEST+="$(date +'%F %T')" XML_REQUEST+="" # Sending the request with a new token PostRouterData "/api/sms/send-sms" "${XML_REQUEST}" 1 # Only displays data if 'RAW' mode is enabled ${RAW_DISPLAY} && { echo "${RESPONSE}" ; return ; } # Display traces if activated if [ ${TRACE_LEVEL} -ge 1 ] ; then WriteDebug "SendSMS" "==> Phone number(s): ${SMS_List}\nMessage length: ${#SMS_Text}" WriteDebug "" "==> RESPONSE:\n${RESPONSE}" WriteDebug ; echo fi } SetAllRead () { local XML_REQUEST ; local MESSAGE ; local RET_CODE # Retrieving message indexes GetSMS "Inbox" # Change status of each message for SMS_Index in "${SMS_INDEXES[@]}" ; do # Constructing the XML request unset XML_REQUEST XML_REQUEST+="" XML_REQUEST+="${SMS_Index}" XML_REQUEST+="" # Sending the request with a new token PostRouterData "/api/sms/set-read" "${XML_REQUEST}" 1 # Only displays data if 'RAW' mode is enabled ${RAW_DISPLAY} && { echo "${RESPONSE}" ; continue ; } # Result control RET_CODE=$(echo "$RESPONSE" | grep -oPm1 "(?<=)[^<]+") if [ "${RET_CODE}" = "113055" ] ; then # Already marked as read MESSAGE+="\n${SMS_Index} -> NA" else RET_CODE=$(echo "$RESPONSE" | grep -oPm1 "(?<=)[^<]+") MESSAGE+="\n${SMS_Index} -> ${RET_CODE}" fi done # Only displays data if 'RAW' mode is enabled ${RAW_DISPLAY} && return # Display traces if activated if [ ${TRACE_LEVEL} -ge 1 ] ; then WriteDebug "SetAllRead" "==> SMS_INDEXES:\n${SMS_INDEXES[*]}" WriteDebug "" "==> RESULT:${MESSAGE}" WriteDebug ; echo fi } DeleteSMS () { # Forcing the parameter to lowercase to avoid typing errors local XML_REQUEST ; local BoxType="${1,,}" ; local IdxSMS="$2" # Converting BoxType to correct value for XML query case "${BoxType}" in inbox | 1 ) TypeBox=1 ;; outbox | 2 ) TypeBox=2 ;; * ) WriteError "${BOX_ERR1} '$1', ${BOX_ERR2}\n" ; return 1 ;; esac # Forcing the type to integer and checking validity of the index let IdxSMS+=0 if [ ${IdxSMS} -gt 0 ] ; then SMS_INDEXES=(${IdxSMS}) else # Retrieving message indexes into SMS_INDEXES array GetSMS ${TypeBox} fi # Delete each message of the list for SMS_Index in "${SMS_INDEXES[@]}" ; do unset XML_REQUEST XML_REQUEST+="" XML_REQUEST+="${SMS_Index}" XML_REQUEST+="" # Sending the request with a new token PostRouterData "/api/sms/delete-sms" "${XML_REQUEST}" 1 # Only displays data if 'RAW' mode is enabled ${RAW_DISPLAY} && { echo "${RESPONSE}" ; continue ; } # Result control RET_CODE=$(echo "$RESPONSE" | grep -oPm1 "(?<=)[^<]+") if [ ! -z "${RET_CODE}" ] ; then MESSAGE+="\n${SMS_Index} -> ${RET_CODE}" else RET_CODE=$(echo "$RESPONSE" | grep -oPm1 "(?<=)[^<]+") MESSAGE+="\n${SMS_Index} -> ${RET_CODE}" fi done # Only displays data if 'RAW' mode is enabled ${RAW_DISPLAY} && return # Display traces if activated if [ ${TRACE_LEVEL} -ge 1 ] ; then WriteDebug "DeleteSMS" "==> SMS_INDEXES:\n${SMS_INDEXES[*]}" WriteDebug "" "==> RESULT:${MESSAGE}" WriteDebug ; echo fi } # Loading connection parameters source "${CONFIG_FILE}" # Get messages Localize # Checking parameters while [ $# -gt 0 ] ; do case "$1" in -a | --address ) shift ; ROUTER_ADDR="$1" ;; -c | --count ) shift ; TypeOfBox="$1" PROG_ACTION="CountSMS ${TypeOfBox}" ;; -C | --create-file ) CreateConfig exit 0 ;; -d | --delete ) shift ; TypeOfBox="$1" shift ; IndexOfSms="$1" PROG_ACTION="DeleteSMS ${TypeOfBox} ${IndexOfSms}" ;; -f | --file ) shift if [ -s "$1" -a -r "$1" ] ; then # Loading new connection settings source "$1" else # Unable to read the file WriteError "${CNF_ERR5} '$1'\n" exit 1 fi ;; -g | --get ) shift ; TypeOfBox="$1" PROG_ACTION="GetSMS ${TypeOfBox}" ;; -h | --help ) DisplayHelp exit 0 ;; -l | --lang ) shift ; LANG="${1,,}" Localize ;; -p | --password ) shift ; ROUTER_PASS="$1" ;; -r | --read ) PROG_ACTION="SetAllRead" ;; -R | --raw ) RAW_DISPLAY=true ;; -s | --send ) shift ; SMS_List="${1// }" ; SMS_Ctrl="$(echo ${SMS_List} | tr -d '+[0-9];')" # Checking phone(s) number(s) [ -z "${SMS_Ctrl}" ] || { WriteError "${SMS_ERR1}\n" ; exit 1 ; } shift ; SMS_Text="$1" # Checking message text [ -z "${SMS_Text}" ] && { WriteError "${SMS_ERR2}\n" ; exit 1 ; } PROG_ACTION="SendSMS" ;; -t | --trace ) shift ; TRACE_LEVEL="$1" ;; -u | --user ) shift ; ROUTER_USER="$1" ;; -v | --version ) WriteError "$(basename $0): version ${PRG_VERSION}\n" exit 0 ;; -x ) # Enable script traces set -x ;; * ) # Unknown option WriteError "${OPT_ERR1} '$1'\n" exit 1 ;; esac shift done # Send command to router if [ ! -z "${PROG_ACTION}" ] ; then CheckConfig Connect Login ${PROG_ACTION} Logout CleanUp fi