#!/bin/sh MYVERSION="0.2.0e" # Transform debug to DEBUG, in order to declare debug method. if [ -n "${debug}" ]; then echo "Warning: debug variable is obsolete. Use DEBUG instead." >> /dev/stderr export DEBUG="${debug}" unset debug fi # Display formatted debug output if DEBUG variable is set. # This method should have as less dependencies as possible. debug() { if [ "a$1" != "arun_command" -a "a$1" != "ashow_file" -a -z "${DEBUG}" ]; then return 0 elif [ "a$1" = "arun_command" -a -z "${DEBUG}" ]; then shift sh -c "$*" > /dev/null 2> /dev/null return $? elif [ "a$1" = "arun_command" -a -n "${DEBUG}" ]; then shift printf "/-------------------------------------------------------------------------------\n" >> "/dev/stderr" printf "[%.5d] [%s] Will now run command: \'%s\'\n" "$$" "`date "+%H:%M:%S"`" "${*}" >> "/dev/stderr" printf "/-------------------------------------------------------------------------------\n" >> "/dev/stderr" sh -c "$*" >> "/dev/stderr" 2>&1 rdebug=$? printf "\-------------------------------------------------------------------------------\n" >> "/dev/stderr" printf "[%.5d] [%s] Command returned %d.\n" "$$" "`date "+%H:%M:%S"`" "${rdebug}" >> "/dev/stderr" printf "\-------------------------------------------------------------------------------\n" >> "/dev/stderr" return ${rdebug} elif [ -z "${DEBUG}" ]; then return 0 elif [ "a$1" = "ashow_file" ]; then if [ -f "$2" ]; then printf "/-------------------------------------------------------------------------------\n" >> "/dev/stderr" printf "[%.5d] [%s] Will now display contents of: \'%s\'\n" "$$" "`date "+%H:%M:%S"`" "$2" >> "/dev/stderr" printf "/-------------------------------------------------------------------------------\n" >> "/dev/stderr" cat "$2" >> "/dev/stderr" printf "\-------------------------------------------------------------------------------\n" >> "/dev/stderr" ls -ld "$2" >> "/dev/stderr" printf "\-------------------------------------------------------------------------------\n" >> "/dev/stderr" else printf "/-------------------------------------------------------------------------------\n" >> "/dev/stderr" printf "[%.5d] [%s] File does not exist: \'%s\'\n" "$$" "`date "+%H:%M:%S"`" "$2" >> "/dev/stderr" printf "\-------------------------------------------------------------------------------\n" >> "/dev/stderr" fi return 0 else rfmt="$1" shift if [ "a${YESFUNCNAME}" = "a" ]; then if [ "$#" -ge "1" ]; then printf "[%.5d] [%s] ${rfmt}" "$$" "`date "+%H:%M:%S"`" "${@}" >> "/dev/stderr" else printf "[%.5d] [%s] ${rfmt}" "$$" "`date "+%H:%M:%S"`" >> "/dev/stderr" fi else if [ "$#" -ge "1" ]; then printf "[%.5d] [%s] [%-20s] ${rfmt}" "$$" "`date "+%H:%M:%S"`" "${FUNCNAME[1]}" "${@}" >> "/dev/stderr" else printf "[%.5d] [%s] [%-20s] ${rfmt}" "$$" "`date "+%H:%M:%S"`" "${FUNCNAME[1]}" >> "/dev/stderr" fi fi unset rfmt fi return 0 } # Print debug header debug_header() { if [ -n "${DEBUG}" ]; then echo >> "/dev/stderr" echo "-------------------------------------------" >> "/dev/stderr" echo "Sakis3G ${MYVERSION} running on DEBUG mode." >> "/dev/stderr" echo "-------------------------------------------" >> "/dev/stderr" date >> "/dev/stderr" echo "-------------------------------------------" >> "/dev/stderr" if [ "a${allargs}" = "a" ]; then echo "Command line was: $0 $@" >> "/dev/stderr" else echo "Command line was: $0 ${allargs}" >> "/dev/stderr" fi echo "Running with PID: $$" >> "/dev/stderr" echo "-------------------------------------------" >> "/dev/stderr" echo "Environment is:" >> "/dev/stderr" set >> "/dev/stderr" echo "-------------------------------------------" >> "/dev/stderr" echo "Will now proceed with Sakis3G execution." >> "/dev/stderr" echo "-------------------------------------------" >> "/dev/stderr" fi } need_arg() { [ "a`eval echo \\\$$1 2> /dev/null`" != "a" ] && return 0 case "$1" in foldwrapping) export foldwrapping=60 ;; pppint) export pppint="ppp0" ;; CHAT_ABORT_STRINGS) # Abort strings that chat program may encounter export CHAT_ABORT_STRINGS="ABORT BUSY ABORT ERROR ABORT BLOCKED ABORT NOCARRIER" ;; BAUD) export BAUD="460800" ;; PPPD_OPTIONS) # Options passed to pppd when called directly export PPPD_OPTIONS="modem crtscts -detach defaultroute dump noipdefault usepeerdns usehostname ktune logfd 2 noauth name sakis3g lock maxfail 3" ;; PPPD_PEERS) # Directory where pppd keeps its peers export PPPD_PEERS=/etc/ppp/peers ;; SERIALDRIVERS) export SERIALDRIVERS="ftdi_sio ipaq safe_serial usbserial visor" ;; LOGPOSITION) export LOGPOSITION="/var/log/sakis3g.log" ;; XOSDFONT) export XOSDFONT='-*-freesans-bold-r-*-*-36-*-*-*-*-*-*-*' ;; AOSDFONT) export AOSDFONT='DejaVuSans 36' ;; MENUFONT) export MENUFONT="-monotype-arial-medium-r-normal-*-18-*-*-*-*-*-*-*" ;; *) debug "No default value for %s was found.\n" "$1" ;; esac debug "Loaded default value for %s: %s\n" "$1" "`eval echo \\\$$1 2> /dev/null`" } sanitize() { echo "$@" 2> /dev/null | ${trbin} "\\" " " 2> /dev/null | ${trbin} "\"" " " | ${trbin} "'" " " | ${trbin} "\`" " " } release_X_cookie() { debug "Disposing stolen X session cookie for %s.\n" "${XCOOKIE}" if [ -n "${XCOOKIE}" ] && find_binary "xauth"; then # If having an authority file that does not belong to us, unset it. if [ "a${XAUTHORITY}" = "a${runhome}/.Xauthority" -a "a$HOME" != "a${runhome}" ]; then unset XAUTHORITY fi found=`${xauthbin} nlist ${XCOOKIE} | ${wcbin} -l` found=`echo ${found}` if [ "a${found}" = "a0" ]; then debug "Cookie already disposed.\n" else ${xauthbin} remove ${XCOOKIE} found=`xauth nlist ${XCOOKIE} | ${wcbin} -l` found=`echo ${found}` if [ "a${found}" = "a0" ]; then debug "Cookie disposed as it should.\n" unset XCOOKIE else debug "Failed to dispose cookie.\n" fi fi unset found fi } # Callback function called on EXIT to execute traps. exittrap() { if [ -n "${TRAPS}" ]; then debug "Now executing traps.\n" for tr in ${TRAPS} do debug "Executing trap \"%s\".\n" "${tr}" ${tr} done else debug "No exit traps defined.\n" fi if ppp_fast_status; then debug "\n>>>>>>>>> If program is paused, you may freely press Ctrl+C. <<<<<<<<<\n>>> This happens due to DEBUG being set. Connection will NOT drop. <<<\n" fi } # Adds trap to be executed on EXIT addexittrap() { [ "a$1" = "a" ] && return 0; if [ "a${TRAPS}" = "a" ]; then trap exittrap EXIT debug "Established trap handler.\n" fi if ! strinstr "$1" "${TRAPS}" " "; then TRAPS="$1 ${TRAPS}" debug "Traps are now: %s\n" "${TRAPS}" else debug "Trap %s already registered.\n" "${1}" fi } translate_load() { unset translatebase ! find_binary "printf" && return 1 ! find_binary "grep" && return 1 ! find_binary "head" && return 1 ! find_binary "tail" && return 1 ! find_binary "sed" && return 1 ! find_binary "cat" && return 1 ! find_binary "cut" && return 1 ! find_binary "tr" && return 1 if [ "a${notranslate}" != "a" ]; then export notranslate=yes; unset foldwrapping; need_arg "foldwrapping" return 1 fi if [ "a${TRANSLATION}" != "a" ] && [ -f "${TRANSLATION}" ]; then debug "Requested to use file %s for translations.\n" "${TRANSLATION}" translatebase=`${catbin} "${TRANSLATION}" 2> /dev/null` elif [ "a${PROVIDER}" != "a" ] && [ -x "${PROVIDER}" ]; then translatelocale="${LC_MESSAGES}" [ "a${translatelocale}" = "a" ] && translatelocale="${LC_ALL}" [ "a${translatelocale}" = "a" ] && translatelocale="${LOCALE}" [ "a${translatelocale}" = "a" ] && translatelocale="${LANG}" if [ "a${translatelocale}" = "a" ]; then debug "No locale reported by system. Will not be using translations.\n" export notranslate=yes; unset foldwrapping; need_arg "foldwrapping" return 1 fi debug "Locale %s found in environment.\n" "${translatelocale}" translatelocale=`echo ${translatelocale} | ${grepbin} -i "UTF\(.*\)8"` if [ "a${translatelocale}" = "a" ]; then debug "Reported locale is not UTF-8. Will not be using translations.\n" export notranslate=yes; unset foldwrapping; need_arg "foldwrapping" return 1 fi translatelocale=`echo ${translatelocale} | ${cutbin} -d. -f1 | ${sedbin} -e "s/$/.UTF-8/g"` debug "Will attempt to get translation file from package: %s.\n" "messages/${translatelocale}" translatebase=`${PROVIDER} getfile "messages/${translatelocale}" 2> /dev/null` else debug "Unable to retrieve any translation file. Will not be using translations.\n" export notranslate=yes; unset foldwrapping; need_arg "foldwrapping" return 1 fi helperfactor=`echo "${translatebase}" 2> /dev/null | ${headbin} -1 | ${grepbin} "^##\([0-9]\)$" | ${sedbin} -e "s/^##//g"` [ "a${helperfactor}" = "a" ] && helperfactor=1 unset foldwrapping; need_arg "foldwrapping"; foldwrapping=`expr ${foldwrapping} \* ${helperfactor} 2> /dev/null`; foldwrapping=`echo ${foldwrapping}` [ "a${foldwrapping}" = "a" ] && unset foldwrapping need_arg "foldwrapping"; unset helperfactor translatebase=`${printfbin} "%s" "${translatebase}" | ${grepbin} -v "^#"` if [ "a${translatebase}" = "a" ]; then debug "No translations retrieved from file. Will not be using translations.\n" export notranslate=yes; unset foldwrapping; need_arg "foldwrapping" return 1 fi export foldwrapping debug "Translations loaded. Wrapping at %d bytes.\n" "${foldwrapping}" return 0 } # Translates argument to locale translate_text() { if [ "a${notranslate}" != "a" ]; then ${printfbin} "%s" "$1" return 0 fi [ "a${translatebase}" = "a" ] && translate_load if [ "a${notranslate}" != "a" -o "a${translatebase}" = "a" ]; then ${printfbin} "%s" "$1" return 0 fi # Safer, still slower way to translate #texttomatch=`${printfbin} "%s" "$1" | ${trbin} "\\n" ".." | ${trbin} "\n" "." | ${trbin} "\t" "." | ${trbin} "\\\\\\\" "." | ${sedbin} -e "s/\\\\\\/\./g" | ${sedbin} -e "s/\"/\./g"` texttomatch=`${printfbin} "%s" "$1" | ${trbin} "\\\\\\\" "." | ${trbin} "\\\\\"" "." | ${trbin} "\n" "."` # Comment below is to help gedit in colouring text # `"` if [ -n "${showtext}" ]; then debug "Text to check: %s\n" "${1}" debug "Text to match: %s\n" "${texttomatch}" fi texttranslated=`${printfbin} "%s" "${translatebase}" | ${grepbin} -A 1 -G "^.${texttomatch}.$" | ${headbin} -2 | ${tailbin} -1 | ${sedbin} -e "s/^\"\(.*\)\"$/\1/g"` unset texttomatch if [ "a${texttranslated}" != "a" -a "a${texttranslated}" != "a\"" ]; then [ -n "${showtext}" ] && debug "Text returned: %s\n" "${texttranslated}" ${printfbin} "%s" "${texttranslated}" else [ -n "${showtext}" ] && debug "No translation found, returning original text: %s\n" "$1" ${printfbin} "%s" "$1" fi unset texttranslated return 0 } # Safety helper safe_invoke() { if [ "a${NOFUNCNAME}" != "a" ]; then debug "FIXME: Called %s without FUNCNAME variables available.\n" "$0" return 99 fi if [ "a${FUNCNAME[1]}" = "a" ]; then debug "FIXME: %s called without FUNCNAME[1] being available.\n" return 99 fi debug "Function %s requested to call it in a safe manner.\n" "${FUNCNAME[1]}" callertimeout="$1"; callertimeout=`expr ${callertimeout} + 1 - 1 2> /dev/null` if [ "a${callertimeout}" = "a$1" ]; then debug "Timeout set by %s to %d seconds.\n" "${FUNCNAME[1]}" "${callertimeout}" shift else callertimeout=5 debug "Caller did not provide timeout. Using default (%d seconds).\n" "${callertimeout}" fi if [ "a${safetimeout}" != "a" ]; then unset callertimeout debug "FIXME: However, we are already within a safe session.\n" ${FUNCNAME[1]} "safe" "$@" ret=$? debug "FIXME: Function %s returned from within a nested safe session.\n" "${FUNCNAME[1]}" return ${ret} elif [ "a${nosafety}" != "a" ]; then unset callertimeout debug "However, config instructs not to use safety-checks.\n" ${FUNCNAME[1]} "safe" "$@" ret=$? unset TIMEOUTOCCURED debug "Unsafe function %s returned.\n" "${FUNCNAME[1]}" return ${ret} fi safetimeout="${callertimeout}" callermethod="${FUNCNAME[1]}" unset TIMEOUTOCCURED; unset callertimeout if find_binary "mktemp"; then debug "Using %s to store standard output and error of %s.\n" "${mktempbin}" "${callermethod}" outputholder=`${mktempbin} -p /tmp -q sakis3g.safe.output.$$.XXXXXXXX` errorholder=`${mktempbin} -p /tmp -q sakis3g.safe.error.$$.XXXXXXXX` fi if [ "a${outputholder}" = "a" ]; then debug "Using backup method for creating temporary output holder.\n" outputholder="/tmp/sakis3g.unsafe.output.$$" fi if [ "a${errorholder}" = "a" ]; then debug "Using backup method for creating temporary output holder.\n" errorholder="/tmp/sakis3g.unsafe.error.$$" fi debug "Will store output at: %s\n" "${outputholder}" debug "Will store error at: %s\n" "${errorholder}" debug "Initiating safe session for %s (%d seconds timeout).\n" "${callermethod}" "${safetimeout}" "${callermethod}" "safe" "$@" > "${outputholder}" 2> "${errorholder}" & safecallerpid=$!; eval "disown -a" > /dev/null 2> /dev/null debug "Method spawned with PID %d.\n" "${safecallerpid}" while ! notrunning "${safecallerpid}" do debug "%s still runs. %d seconds before killing.\n" "${callermethod}" "${safetimeout}" if [ "a${safetimeout}" = "a0" ]; then debug "Time expired with no results.\n" if find_binary "kill"; then debug "Will attempt to kill process with PID %d.\n" "${safecallerpid}" ! notrunning "${safecallerpid}" && debug run_command "${killbin} -1 ${safecallerpid}" ! notrunning "${safecallerpid}" && debug run_command "${killbin} -9 ${safecallerpid}" ! notrunning "${safecallerpid}" && debug "Failed to kill it.\n" fi if find_binary "rm"; then debug "Will attempt to unlink temporary holders.\n" debug run_command "${rmbin} -f \"${outputholder}\" \"${errorholder}\"" fi export TIMEOUTOCCURED="${callermethod}" unset callermethod; unset safecallerpid; unset outputholder; unset errorholder debug "Method %s failed to respond within timeout.\n" unset safetimeout return 99 fi safetimeout=`expr ${safetimeout} - 1`; safetimeout=`echo ${safetimeout}` sleep 1 done debug "Method returned while %d seconds were remaining.\n" "${safetimeout}" debug show_file "${outputholder}" debug show_file "${errorholder}" if find_binary "cat"; then debug "Will now route output and error to mine.\n" [ -f "${outputholder}" ] && ${catbin} "${outputholder}" 2> /dev/null [ -f "${errorholder}" ] && ${catbin} "${errorholder}" >> /dev/stderr 2> /dev/null fi if find_binary "rm"; then debug "Will attempt to unlink temporary holders.\n" debug run_command "${rmbin} -f \"${outputholder}\" \"${errorholder}\"" fi debug "Method %s responded within timeout specified.\n" "${FUNCNAME[1]}" unset callermethod; unset safecallerpid; unset outputholder; unset errorholder unset safetimeout debug "Left safe mode.\n" return 0 } safe_lsusb() { if [ "a$1" != "asafe" -a "a${NOFUNCNAME}" = "a" ]; then safe_invoke "5" "$@" return $? elif [ "a${NOFUNCNAME}" = "a" ]; then shift fi [ "a${lsusbbin}" != "a" ] && ${lsusbbin} "$@" } safe_chat() { if [ "a$1" != "asafe" -a "a${NOFUNCNAME}" = "a" ]; then safe_invoke "10" "$@" return $? elif [ "a${NOFUNCNAME}" = "a" ]; then shift fi [ "a${chatbin}" != "a" ] && ${chatbin} "$@" } safe_cat() { if [ "a$1" != "asafe" -a "a${NOFUNCNAME}" = "a" ]; then safe_invoke "5" "$@" return $? elif [ "a${NOFUNCNAME}" = "a" ]; then shift fi [ "a${catbin}" != "a" ] && ${catbin} "$@" } # Formats text format_text() { if find_binary "printf"; then rfmt="$1" [ "$#" -gt "0" ] && shift rfmt=`translate_text "${rfmt}"` if [ "$#" -ge "1" ]; then ${printfbin} "${rfmt}" "${@}" else ${printfbin} "${rfmt}" fi unset rfmt else echo "${@}" fi } # Clears terminal line if required term_clearline() { [ "a${COLUMNS}" != "a" ] && find_binary "printf" && [ -n "${interactive}" ] && ${printfbin} "\r%.-${COLUMNS}s\r" "" && return 0 [ "a${COLUMNS}" = "a" ] && find_binary "printf" && [ -n "${interactive}" ] && ${printfbin} "\r%s\r" " " && return 0 } # Prints argument to terminal term_print() { term_clearline echo "${@}" } # Sends error to terminal, colored if possible. term_error() { if find_binary "grep" && [ -n "${interactive}" ]; then term_print "$@" | ${grepbin} --color "." else term_print "$@" fi } term_verbose() { if [ -n "${interactive}" ]; then if find_binary "grep" && find_binary "tr"; then currentlyverbosing=yes term_print "$@" | GREP_COLOR=2 ${grepbin} --color=always "." | ${trbin} "\n" " " unset currentlyverbosing; lastlineverbose=yes else term_print "$@" fi fi } term_notify() { if find_binary "grep" && [ -n "${interactive}" ]; then term_print "$@" | GREP_COLOR=1 ${grepbin} --color "." else term_print "$@" fi } select_example() { examplevariable=`selection_argument variable "$@"` exampleoptions=`selection_argument options "$@"` [ "a${exampleoptions}" != "a" ] && format_text "\nAvailable options are:\n" && format_text "%s\n" "${exampleoptions}" [ "a${exampleoptions}" = "a" ] && exampleoptions="foo" format_text "\nExample:\n" format_text "\t$ %s [...] %s=\"%s\"\n\r\n" "${ME}" "${examplevariable}" "`echo ${exampleoptions} | ${cutbin} -d\ -f1`" unset exampletitle; unset examplevariable; unset exampleoptions } term_select_example() { examplevariable=`selection_argument variable "$@"` exampleoptions=`selection_argument options "$@"` [ "a${exampleoptions}" != "a" ] && notify "\nAvailable options are:\n" && notify "%s\n" "${exampleoptions}" [ "a${exampleoptions}" = "a" ] && exampleoptions="foo" notify "\nExample:\n" notify "\t$ %s %s=\"%s\"\n\r\n" "${ME}" "${examplevariable}" "`echo ${exampleoptions} | ${cutbin} -d\ -f1`" unset exampletitle; unset examplevariable; unset exampleoptions } term_select() { options=`selection_argument options "$@" | ${wcbin} -l`; options=`echo ${options}` variable=`selection_argument variable "$@"` if [ "a${options}" != "a1" ]; then exampletitle=`selection_argument title "$@"` notify "%s by using %s variable, or by enabling interactive mode.\n" "${exampletitle}" "${variable}" notify "\t$ %s --interactive %s\n" "${ME}" "${allargs}" unset exampletitle term_select_example "$@" else eval export ${variable}="`selection_argument option 1 "$@"`" debug "Returning sole available option \"%s\" on behalf of user.\n" "`eval echo \\\${${variable}}`" unset variable return 1 fi unset variable; unset options stop_with 98 return 98 } term_confirm() { options=`selection_argument options "$@" | ${wcbin} -l`; options=`echo ${options}` variable=`selection_argument variable "$@"` exampletitle=`selection_argument title "$@"` notify "%s by using --%syes or --%sno switches, or by enabling interactive mode.\n" "${exampletitle}" "${variable}" "${variable}" notify "\t$ %s --interactive %s\n" "${ME}" "${allargs}" unset exampletitle stop_with 98 return 98 } term_prompt() { variable=`selection_argument variable "$@"` exampletitle=`selection_argument title "$@"` notify "%s by using %s variable, or by enabling interactive mode.\n" "${exampletitle}" "${variable}" notify "\t$ %s --interactive %s\n" "${ME}" "${allargs}" unset exampletitle term_select_example "$@" return 98 } interactive_term_select() { variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` options=`selection_argument options "$@" | ${wcbin} -l` ; options=`echo ${options}` debug "Prompting user to select variable %s.\n" "${variable}" [ "a${title}" != "a" ] && notify "%s\n\r\n" "${title}" [ "a${text}" != "a" ] && ${printfbin} "%s\n\r\n" "${text}" notify "Available options are:\n" selection_argument options "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)/\1. \3/g" | GREP_COLOR=1 ${grepbin} --color=AUTO "\([0-9]*\)\." selection_argument button2 "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\)/0. \2/g" | GREP_COLOR=1 ${grepbin} --color=AUTO "\([0-9]*\)\." format_text "You can automate this selection by setting %s variable.\nEnter \"*\" to discover how.\n" "${variable}" | GREP_COLOR=2 ${grepbin} --color=ALWAYS "." notify "\r\n" echo -n "`format_text "Please use numbers %d-%d to perform your selection: " "0" "${options}"`" read termselection debug "User typed: \"%s\"\n" "${termselection}" if [ "a${termselection}" = "a*" ]; then debug "Showing select example through variable %s.\n" "${variable}" term_select_example "$@" interactive_term_select "$@" selection=$? else selection=`${printfbin} "%d\n" "${termselection}" 2> /dev/null` [ "${selection}" -gt "${options}" ] && selection=0 [ "${selection}" -eq "0" ] && selection=98 [ "${selection}" -gt "0" -a "${selection}" -le "${options}" ] && eval export ${variable}="`selection_argument option ${selection} "$@"`" fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset options; unset termselection [ "a${DEBUG}" = "a" ] && find_binary "clear" && ${clearbin} return "${selection}" } interactive_term_confirm() { variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` debug "Prompting user to select variable %s.\n" "${variable}" [ "a${title}" != "a" ] && notify "%s\n\r\n" "${title}" [ "a${text}" != "a" ] && ${printfbin} "%s\n\r\n" "${text}" notify "Available options are:\n" selection_argument button1 "$@" | ${sedbin} -e "s/^\(.*\)$/1. \1/g" | GREP_COLOR=1 ${grepbin} --color=AUTO "^\([0-9]*\)\." selection_argument button2 "$@" | ${sedbin} -e "s/^\(.*\)$/2. \1/g" | GREP_COLOR=1 ${grepbin} --color=AUTO "^\([0-9]*\)\." [ "a$6" != "areset" ] && format_text "You can automate this selection by setting --%syes or --%sno switches.\n" "${variable}" "${variable}" | GREP_COLOR=2 ${grepbin} --color=ALWAYS "." notify "\r\n" echo -n "`format_text "Please use numbers %d-%d to perform your selection: " "1" "2"`" read termselection debug "User typed: \"%s\"\n" "${termselection}" if [ "a${termselection}" = "a1" ]; then debug "User selected \"yes\".\n" selection=0 elif [ "a${termselection}" = "a2" ]; then debug "User selected \"no\".\n" selection=1 else interactive_term_confirm "$@" selection=$? return ${selection} fi unset variable; unset title; unset text; unset options; unset termselection [ "a${DEBUG}" = "a" ] && find_binary "clear" && ${clearbin} return "${selection}" } interactive_term_prompt() { variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` debug "Prompting user to type variable %s.\n" "${variable}" [ "a${title}" != "a" ] && notify "%s\n" "${title}" format_text "You can automate this selection by setting %s variable.\nEnter \"*\" to discover how.\n" "${variable}" | GREP_COLOR=2 ${grepbin} --color=ALWAYS "." notify "\r\n" [ "a${text}" != "a" ] && ${printfbin} "%s: " "${text}" read termselection termselection=`sanitize "${termselection}"` termselection=`echo "${termselection}" | ${sedbin} -e "s/^ *//g" | ${sedbin} -e "s/ *$//g"` debug "User typed: \"%s\"\n" "${termselection}" if [ "a${termselection}" = "a*" ]; then debug "Showing select example through variable %s.\n" "${variable}" term_select_example "$@" interactive_term_prompt "$@" selection=$? elif [ "a${termselection}" = "a" ]; then debug "User pressed enter which indicates to abort.\n" selection=98 else eval "export ${variable}=\"${termselection}\"" selection=0 fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset termselection [ "a${DEBUG}" = "a" ] && find_binary "clear" && ${clearbin} return "${selection}" } nine_verbose() { term_verbose "$@" } nine_fixcolors() { status_connected [ "a${NINEISP}" != "a${ISPID}" -o "a${ISPID}" = "a" ] && unset NINEBGCOLOR && unset NINEFGCOLOR [ "a${NINEFGCOLOR}" = "a" ] && NINEFGCOLOR=`echo ${ISP_FGCOLOR} | ${sedbin} -e "s/^\(..\)\(..\)\(..\)$/rgb:\1\/\2\/\3/g"` [ "a${NINEBGCOLOR}" = "a" ] && NINEBGCOLOR=`echo ${ISP_BGCOLOR} | ${sedbin} -e "s/^\(..\)\(..\)\(..\)$/rgb:\1\/\2\/\3/g"` [ "a${ISPID}" = "a" ] && unset NINEBGCOLOR && unset NINEFGCOLOR [ "a${NINEFGCOLOR}" = "a" ] && NINEFGCOLOR="rgb:00/00/00" [ "a${NINEBGCOLOR}" = "a" ] && NINEBGCOLOR="rgb:ec/ec/ec" [ "a${NINEISP}" = "a" ] && NINEISP="${ISPID}" export NINEISP; export NINEFGCOLOR; export NINEBGCOLOR } nine_notify() { unset nineerrormode ! find_binary "9menu" && return 1 if [ "a${1}" = "aerror" ]; then nineerrormode=1 shift debug "Going into error mode.\n" else debug "Normal notification.\n" fi ninetext=`echo "$@" | ${sedbin} -e "s/:/;/g"` need_arg "MENUFONT" need_arg "foldwrapping" if find_binary "fold"; then ninetext=`echo "${ninetext}" | ${foldbin} -s -w ${foldwrapping}` else ninetext=`echo "${ninetext}" | ${sedbin} -e "s/^\(............................................................\)\(.*\)$/\1\\n\2/g"` fi ninetext=`echo "${ninetext}" | ${sedbin} -e "s/^\(.*\)$/\"\1:\"/g" | ${trbin} " " " " | ${trbin} "\n" " "` debug "Displaying text to user through 9menu:%s\n" " $@ " debug "Displaying text to user through 9menu:%s\n" " ${ninetext} " if [ "a${nineerrormode}" = "a1" ]; then result=`eval "${ninemenubin} -font \"${MENUFONT}\" -bg \"rgb:ff/80/80\" -fg white -display \"${DISPLAY}\" -label \"\`translate_text "Error"\`\" ${ninetext} \":\" \"OK:exec echo OK-\"" 2> /dev/null | ${grepbin} "^OK-" | ${cutbin} -d- -f1` else nine_fixcolors result=`eval "${ninemenubin} -font \"${MENUFONT}\" -bg ${NINEBGCOLOR} -fg ${NINEFGCOLOR} -display \"${DISPLAY}\" -label \"\`translate_text "Notification"\`\" ${ninetext} \":\" \"OK:exec echo OK-\"" 2> /dev/null | ${grepbin} "^OK-" | ${cutbin} -d- -f1` fi if [ "a${result}" = "aOK" ]; then debug "User saw message.\n" else debug "9menu died or user closed it.\n" fi unset ninetext; unset result; unset nineerrormode } nine_error() { nine_notify "error" "$@" } nine_select() { ! find_binary "9menu" && return 1 nine_fixcolors need_arg "MENUFONT" need_arg "foldwrapping" debug "Prompting user to select variable %s with 9menu.\n" "${variable}" variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` options=`selection_argument options "$@" | ${wcbin} -l` ; options=`echo ${options}` helptext=`format_text "You can automate this selection by setting %s variable on command line, click here to discover how.\n" "${variable}" | ${sedbin} -e "s/:/;/g"` localbutton2=`selection_argument button2 "$@"`; [ "a${localbutton2}" = "a" ] && localbutton2="Cancel" ninetext=`echo "${text}" | ${sedbin} -e "s/:/;/g"` if find_binary "fold"; then ninetext=`echo "${ninetext}" | ${foldbin} -s -w ${foldwrapping}` helptext=`echo "${helptext}" | ${foldbin} -s -w ${foldwrapping}` else ninetext=`echo "${ninetext}" | ${sedbin} -e "s/^\(............................................................\)\(.*\)$/\1\\n\2/g"` helptext=`echo "${helptext}" | ${sedbin} -e "s/^\(............................................................\)\(.*\)$/\1\\n\2/g"` fi ninetext=`echo "${ninetext}" | ${sedbin} -e "s/^\(.*\)$/\"\1:\"/g" | ${trbin} " " " " | ${trbin} "\n" " "` helptext=`echo "${helptext}" | ${sedbin} -e "s/^\(.*\)$/\"\1:exec echo OPTION-AUTOMATE\"/g" | ${trbin} " " " " | ${trbin} "\n" " "` localarguments=`selection_argument options "$@" | ${sedbin} -e "s/:/;/g" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)$/\"\1. \3:exec echo OPTION-\1\"/g" | ${trbin} "\n" " "` termselection=`eval "${ninemenubin} -font \"${MENUFONT}\" -bg ${NINEBGCOLOR} -fg ${NINEFGCOLOR} -display \"${DISPLAY}\" -label \"${title}\" ${ninetext} \":\" ${localarguments} \":\" ${helptext} \":\" \"${localbutton2}:exec echo OPTION-9menuexit\"" 2> /dev/null | ${grepbin} "^OPTION-" | ${cutbin} -d- -f2-` debug "User selected: \"%s\"\n" "${termselection}" if [ "a${termselection}" = "aAUTOMATE" ]; then localtext=`format_text "You can automate this selection by setting %s variable on command line.\n" "${variable}"` notify "${localtext}\n`select_example "$@"`" nine_select "$@" selection=$? return ${selection} elif [ "a${termselection}" = "a9menuexit" -o "a${termselection}" = "a" ]; then debug "User selected button: %s\n" "${localbutton2}" selection=98 else termselection=`echo "${termselection}" | ${trbin} -t "." ""` selection=`${printfbin} "%d\n" "${termselection}" 2> /dev/null` [ "${selection}" -gt "${options}" ] && selection=0 [ "${selection}" -eq "0" ] && selection=98 [ "${selection}" -gt "0" -a "${selection}" -le "${options}" ] && eval export ${variable}="`selection_argument option ${selection} "$@"`" fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset ninetext; unset helptext; unset options; unset termselection; unset buttonselection; unset localtext; unset localarguments; unset localbutton2 return "${selection}" } nine_confirm() { ! find_binary "9menu" && return 1 nine_fixcolors need_arg "MENUFONT" need_arg "foldwrapping" variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` ninetext=`selection_argument text "$@" | ${sedbin} -e "s/:/;/g"` localbutton1=`selection_argument button1 "$@"`; [ "a${localbutton1}" = "a" ] && localbutton1="OK" localbutton2=`selection_argument button2 "$@"`; [ "a${localbutton2}" = "a" ] && localbutton2="Cancel" debug "Prompting user to confirm variable %s with 9menu.\n" "${variable}" helptext="" [ "a$6" != "areset" ] && helptext=`format_text "You can automate this selection by setting --%syes or --%sno switches.\n" "${variable}" "${variable}" | ${sedbin} -e "s/:/;/g"` if find_binary "fold"; then ninetext=`echo "${ninetext}" | ${foldbin} -s -w ${foldwrapping}` helptext=`echo "${helptext}" | ${foldbin} -s -w ${foldwrapping}` else ninetext=`echo "${ninetext}" | ${sedbin} -e "s/^\(............................................................\)\(.*\)$/\1\\n\2/g"` helptext=`echo "${helptext}" | ${sedbin} -e "s/^\(............................................................\)\(.*\)$/\1\\n\2/g"` fi ninetext=`echo "${ninetext}" | ${sedbin} -e "s/^\(.*\)$/\"\1:\"/g" | ${trbin} " " " " | ${trbin} "\n" " "` helptext=`echo "${helptext}" | ${sedbin} -e "s/^\(.*\)$/\"\1:\"/g" | ${trbin} " " " " | ${trbin} "\n" " "` localarguments="\"${localbutton1}:exec echo Answer-Yes\" \"${localbutton2}:exec echo Answer-No\"" termselection=`eval "${ninemenubin} -font \"${MENUFONT}\" -bg ${NINEBGCOLOR} -fg ${NINEFGCOLOR} -display \"${DISPLAY}\" -label \"${title}\" ${ninetext} \":\" ${localarguments} \":\" ${helptext} \":\"" 2> /dev/null | ${grepbin} "^Answer-" | ${cutbin} -d- -f2-` debug "User selected: \"%s\"\n" "${termselection}" if [ "a${termselection}" = "aYes" ]; then selection=0 else selection=1 fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset ninetext; unset helptext; unset options; unset termselection; unset buttonselection; unset localtext; unset localarguments; unset localbutton2; unset localbutton1 return "${selection}" } nine_prompt() { ! find_binary "xterm" && return 1 variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` debug "Prompting user to type variable %s through xterm.\n" "${variable}" localtext=`format_text "You can automate this selection by setting %s variable.\n" "${variable}"` [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\n\n%s: " "${localtext}" "${text}"` locallines=`echo "${localtext}" | ${wcbin} -l`; locallines=`echo ${locallines}`; locallines=`expr ${locallines} + 10`; locallines=`echo ${locallines}`; ${printfbin} "%s\n" "${localtext}" > "/tmp/sakis3g.xterm.pipe.$$" ${xtermbin} -T "${title}" +cm +dc -e sh -c "${catbin} /tmp/sakis3g.xterm.pipe.$$; read XTERMANSWER; set >> /tmp/sakis3g.xterm.pipe.$$;" 2> /dev/null debug show_file "/tmp/sakis3g.xterm.pipe.$$" termselection=`${grepbin} "^XTERMANSWER=" "/tmp/sakis3g.xterm.pipe.$$" 2> /dev/null | ${cutbin} -d= -f2- | ${sedbin} -e "s/^\"\(.*\)\"$/\1/g" | ${sedbin} -e "s/^\'\(.*\)\'$/\1/g"`; ${rmbin} -f "/tmp/sakis3g.xterm.pipe.$$" termselection=`sanitize "${termselection}"` debug "User typed: \"%s\"\n" "${termselection}" # TODO: Implement example if [ "a${termselection}" != "a" ]; then debug "User typed: %s\n" "${termselection}" eval "export ${variable}=\"${termselection}\"" selection=0 elif [ "a${termselection}" = "a" ]; then debug "User requested to cancel.\n" selection=98 else debug "Unknown error.\n" selection=99 fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset termselection; unset buttonselection; unset localtext return "${selection}" } dialog_error() { dialog_cleanscreen if [ "a${SGUI}" = "adialog" ]; then ! find_binary "dialog" && return 1 ${dialogbin} --backtitle "Sakis3G ${MYVERSION}" --colors --title "\Z1\Zb`translate_text "Error occured"`" --ok-label `translate_text "OK"` --clear --colors --aspect 30 --msgbox "\Z1\ZB$@" 0 0 elif [ "a${SGUI}" = "aXdialog" ]; then ! find_binary "Xdialog" && return 1 ${Xdialogbin} --backtitle `translate_text "Error occured"` --title "Sakis3G ${MYVERSION}" --ok-label `translate_text "OK"` --msgbox "$@ " 0 0 elif [ "a${SGUI}" = "azenity" ]; then ! find_binary "zenity" && return 1 ${zenitybin} --title "`translate_text "Error occured"`" --error --text "$@ " elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 ${kdialogbin} --title "`translate_text "Error occured"`" --error "$@ " > /dev/null 2> /dev/null elif [ "a${SGUI}" = "awhiptail" ]; then ! find_binary "whiptail" && return 1 ${whiptailbin} --backtitle "Sakis3G ${MYVERSION}" --title "`translate_text "Error occured"`" --clear --msgbox "$@ " 0 0 fi } dialog_notify() { dialog_cleanscreen if [ "a${SGUI}" = "adialog" ]; then ! find_binary "dialog" && return 1 ${dialogbin} --backtitle "Sakis3G ${MYVERSION}" --title `translate_text "Notification"` --ok-label `translate_text "OK"` --clear --aspect 30 --msgbox "$@" 0 0 elif [ "a${SGUI}" = "aXdialog" ]; then ! find_binary "Xdialog" && return 1 ${Xdialogbin} --title "Sakis3G ${MYVERSION}" --ok-label `translate_text "OK"` --msgbox "$@" 0 0 elif [ "a${SGUI}" = "azenity" ]; then ! find_binary "zenity" && return 1 ${zenitybin} --title "Sakis3G ${MYVERSION}" --info --text "$@ " elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 ${kdialogbin} --title "Sakis3G ${MYVERSION}" --msgbox "$@ " > /dev/null 2> /dev/null elif [ "a${SGUI}" = "awhiptail" ]; then ! find_binary "whiptail" && return 1 ${whiptailbin} --backtitle "Sakis3G ${MYVERSION}" --title `translate_text "Notification"` --clear --msgbox "$@" 0 0 fi } dialog_cleanscreen() { if [ "a${SGUI}" = "aXdialog" ]; then if [ "a${XdialogVerbose}" != "a" -a "a${XdialogVerbose}" != "a0" ]; then ! notrunning "${XdialogVerbose}" && find_binary "kill" && ${killbin} -1 "${XdialogVerbose}" 2> /dev/null unset XdialogVerbose fi unset currentlyverbosing elif [ "a${SGUI}" = "azenity" ]; then [ -f "/tmp/sakis3g.zenity.pipe" ] && ${printfbin} "\n100\n" >> "/tmp/sakis3g.zenity.pipe" [ -f "/tmp/sakis3g.zenity.pipe" ] && debug run_command "${rmbin} -f /tmp/sakis3g.zenity.pipe" [ "a${zenityverbosepid}" != "a" ] && ! notrunning "${zenityverbosepid}" && ${killbin} -1 "${zenityverbosepid}" 2> /dev/null [ "a${zenityverbosepid}" != "a" ] && ! notrunning "${zenityverbosepid}" && ${killbin} -9 "${zenityverbosepid}" 2> /dev/null unset zenityverbosepid elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 if [ "a${kdialogaddress}" != "a" ]; then dcopbased=`echo ${kdialogaddress} | ${grepbin} -i "dcop"` if [ "a${dcopbased}" != "a" ]; then if find_binary "dcop"; then debug run_command "${dcopbin} \"${kdialogaddress}\" close" fi else ! find_binary "dbus-send" && find_binary "qdbus" if [ "a${dbus_sendbin}" != "a" ]; then debug run_command "${dbus_sendbin} --print-reply --dest=${kdialogaddress} \"org.kde.kdialog.ProgressDialog.close\"" elif [ "a${qdbusbin}" != "a" ]; then debug run_command "${qdbusbin} ${kdialogaddress} \"org.kde.kdialog.ProgressDialog.close\"" fi fi else term_clearline fi unset kdialogaddress fi } dialog_verbose() { if [ "a${SGUI}" = "adialog" ]; then ! find_binary "dialog" && return 1 verbwidth=`echo "${COLUMNS}"`; verbwidth=`expr ${verbwidth} + 1 - 1`; verbwidth=`echo ${verbwidth}` verbheight=0; [ "${verbwidth}" -gt "40" ] && verbheight=3 currentlyverbosing=yes ${dialogbin} --backtitle "Sakis3G ${MYVERSION}" --title "Working" --aspect 40 --infobox "$@..." ${verbheight} ${verbwidth} unset currentlyverbosing; lastlineverbose=yes; unset verbwidth; unset verbheight elif [ "a${SGUI}" = "aXdialog" ]; then # ! find_binary "Xdialog" && return 1 # ${Xdialogbin} --title "Sakis3G is working" --infobox "$@..." 0 0 30000 & # XdialogVerbose=$!; currentlyverbosing=yes term_verbose "$@" elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 if ! find_binary "dbus-send" && ! find_binary "qdbus"; then term_verbose "$@"; return 0 fi if [ "a${kdialogaddress}" = "a" ]; then temptext=`translate_text Working...` kdialogaddress=`${kdialogbin} --title "Sakis3G ${MYVERSION}" --progressbar "${temptext}" 100` # kdialogaddress=`${kdialogbin} --title "Sakis3G ${MYVERSION}" --progressbar "${temptext}" 100 2> /dev/null` debug "Returned 1\n" unset temptext [ "a${kdialogaddress}" != "a" ] && export kdialogaddress fi debug "Returned 2\n" if [ "a${kdialogaddress}" != "a" ]; then dcopbased=`echo ${kdialogaddress} | ${grepbin} -i "dcop"` if [ "a${dcopbased}" != "a" ]; then if find_binary "dcop"; then debug run_command "${dcopbin} --user \"${runner}\" --all-sessions \"${kdialogaddress}\" setProgress ${verbosecurrentcount}" debug run_command "${dcopbin} --user \"${runner}\" --all-sessions \"${kdialogaddress}\" setLabel \"$@\"" fi else if [ "a${kdialogaddress}" != "a" ] && [ "a${dbus_sendbin}" != "a" ]; then debug run_command "${dbus_sendbin} --print-reply --dest=${kdialogaddress} \"org.freedesktop.DBus.Properties.Set\" string:'org.kde.kdialog.ProgressDialog' string:'value' variant:int32:${verbosecurrentcount}" debug run_command "${dbus_sendbin} --print-reply --dest=${kdialogaddress} \"org.kde.kdialog.ProgressDialog.setLabelText\" \"string:$@\"" elif [ "a${kdialogaddress}" != "a" ] && [ "a${qdbusbin}" != "a" ]; then debug run_command "qdbus ${kdialogaddress} \"org.kde.kdialog.ProgressDialog.setLabelText\" \"$@\"" debug run_command "qdbus ${kdialogaddress} \"org.freedesktop.DBus.Properties.Set\" \"\" \"value\" \"${verbosecurrentcount}\"" fi fi else term_verbose "$@" fi elif [ "a${SGUI}" = "azenity" ]; then ! find_binary "zenity" && return 1 [ "a${zenityverbosepid}" != "a" ] && notrunning "${zenityverbosepid}" && unset zenityverbosepid [ ! -f "/tmp/sakis3g.zenity.pipe" ] && unset zenityverbosepid if [ "a${zenityverbosepid}" = "a" ] && find_binary "rm" && find_binary "tail" && find_binary "kill" && find_binary "printf" && find_binary "touch" && find_binary "chmod" && find_binary "setsid"; then debug "Establishing zenity verbose helper.\n" [ -f "/tmp/sakis3g.zenity.pipe" ] && ${printfbin} "\n100\n" >> "/tmp/sakis3g.zenity.pipe" [ -f "/tmp/sakis3g.zenity.pipe" ] && debug run_command "${rmbin} -f /tmp/sakis3g.zenity.pipe" debug run_command "${touchbin} /tmp/sakis3g.zenity.pipe" debug run_command "${chmodbin} 666 /tmp/sakis3g.zenity.pipe" if [ -f "/tmp/sakis3g.zenity.pipe" ]; then eval ${tailbin} -f "/tmp/sakis3g.zenity.pipe" "2> /dev/null" | ${zenitybin} --title="Sakis3G ${MYVERSION}" --text="`translate_text Working...`" --progress --percentage=0 --auto-close "> /dev/null 2> /dev/null" & zenityverbosepid=$! eval "disown -a" > /dev/null 2> /dev/null export zenityverbosepid fi fi [ "a${zenityverbosepid}" != "a" ] && notrunning "${zenityverbosepid}" && unset zenityverbosepid [ "a${zenityverbosepid}" = "a" ] && term_verbose "$@" && return 1 ${printfbin} "\n%d\n# $@...\n\n" "${verbosecurrentcount}" >> "/tmp/sakis3g.zenity.pipe" elif [ "a${SGUI}" = "awhiptail" ]; then term_verbose "$@" fi } dialog_confirm() { dialog_cleanscreen if [ "a${SGUI}" = "adialog" ]; then ! find_binary "dialog" && return 1 elif [ "a${SGUI}" = "aXdialog" ]; then ! find_binary "Xdialog" && return 1 elif [ "a${SGUI}" = "azenity" ]; then ! find_binary "zenity" && return 1 elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 elif [ "a${SGUI}" = "awhiptail" ]; then ! find_binary "whiptail" && return 1 fi variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` debug "Prompting user to select yes%s or no%s.\n" "${variable}" "${variable}" localtext="" [ "a$6" != "areset" ] && localtext=`format_text "You can automate this selection by setting --%syes or --%sno switches.\n" "${variable}" "${variable}"` if [ "a${SGUI}" = "adialog" ]; then [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\\\\\\n\\\\\\n%s\n" "${text}" "${localtext}"` ${dialogbin} --backtitle "Sakis3G ${MYVERSION}" --title " ${title} " --clear --cr-wrap --yesno "${localtext}" 0 0 2> /dev/null buttonselection=$? elif [ "a${SGUI}" = "aXdialog" ]; then [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\\\\\\n\\\\\\n%s\n" "${text}" "${localtext}"` ${Xdialogbin} --backtitle " ${title} " --title "Sakis3G ${MYVERSION}" --wrap --fill --yesno "${localtext}" 0 0 2> /dev/null buttonselection=$? elif [ "a${SGUI}" = "akdialog" ]; then [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\\\\\\n\\\\\\n%s\n" "${text}" "${localtext}"` ${kdialogbin} --title " ${title} " --yesno "${text}" 2> /dev/null buttonselection=$? elif [ "a${SGUI}" = "azenity" ]; then need_arg "foldwrapping" text=`echo "${text}" | ${sedbin} -e "s/_/__/g"` localtext=`echo "${localtext}" | ${sedbin} -e "s/_/__/g"` # if find_binary "fold"; then # localtext=`echo "${localtext}" | ${foldbin} -s -w ${foldwrapping}` # text=`echo "${text}" | ${foldbin} -s -w ${foldwrapping}` # fi [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\\\\\\n\\\\\\n%s\n" "${text}" "${localtext}"` ${zenitybin} --title " ${title} " --question --text "${localtext}" 2> /dev/null buttonselection=$? elif [ "a${SGUI}" = "awhiptail" ]; then [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\\\\\\n\\\\\\n%s\n" "${text}" "${localtext}"` ${whiptailbin} --backtitle "Sakis3G ${MYVERSION}" --title " ${title} " --clear --yesno "${localtext}" 0 0 2> /dev/null buttonselection=$?; fi if [ "a${buttonselection}" = "a0" ]; then debug "User selected \"yes\" (%d).\n" "${buttonselection}" return 0 else debug "User selected \"no\" (%d).\n" "${buttonselection}" return 1 fi } dialog_select() { dialog_cleanscreen if [ "a${SGUI}" = "adialog" ]; then ! find_binary "dialog" && return 1 elif [ "a${SGUI}" = "aXdialog" ]; then ! find_binary "Xdialog" && return 1 elif [ "a${SGUI}" = "azenity" ]; then ! find_binary "zenity" && return 1 elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 elif [ "a${SGUI}" = "awhiptail" ]; then ! find_binary "whiptail" && return 1 fi variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` options=`selection_argument options "$@" | ${wcbin} -l` ; options=`echo ${options}` debug "Prompting user to select variable %s.\n" "${variable}" localtext=`format_text "You can automate this selection by setting %s variable on command line.\n" "${variable}"` [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\\\\\\n\\\\\\n%s\n" "${localtext}" "${text}"` localbutton2=`selection_argument button2 "$@"`; [ "a${localbutton2}" = "a" ] && localbutton2="Cancel" if [ "a${SGUI}" = "adialog" ]; then localarguments=`selection_argument options "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)$/\"\1.\" \"\3\" \"${variable}=\\\\\"\2\\\\\"\"/g"` eval ${dialogbin} --backtitle \"Sakis3G ${MYVERSION}\" --title \" ${title} \" --ok-label \"`translate_text "OK"`\" --cancel-label \"${localbutton2}\" --item-help --clear --cr-wrap --menu \"${localtext}\" 0 0 0 ${localarguments} 2> "/tmp/sakis3g.dialog.$$" buttonselection=$? elif [ "a${SGUI}" = "aXdialog" ]; then localarguments=`selection_argument options "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)$/\"\1.\" \"\3\" \"${variable}=\\\\\"\2\\\\\"\"/g"` eval ${Xdialogbin} --backtitle \" ${title} \" --title \"Sakis3G ${MYVERSION}\" --ok-label \"`translate_text "OK"`\" --cancel-label \"${localbutton2}\" --item-help --wrap --fill --menubox \""${localtext}"\" 0 0 0 ${localarguments} 2> "/tmp/sakis3g.dialog.$$" buttonselection=$? elif [ "a${SGUI}" = "akdialog" ]; then localarguments=`selection_argument options "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)$/\"\1.\" \"\3\"/g"` eval ${kdialogbin} --title \" ${title} \" --menu \""${text}"\" ${localarguments} \"AUTOMATE\" \"`translate_text "Help with this question"`\" > "/tmp/sakis3g.dialog.$$" 2> /dev/null buttonselection=$? elif [ "a${SGUI}" = "azenity" ]; then need_arg "foldwrapping" localarguments=`selection_argument options "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)$/\"\1.\" \"\3\"/g"` localtext=`echo "${text}" | ${sedbin} -e "s/_/__/g"` find_binary "fold" && localtext=`echo "${localtext}" | ${foldbin} -s -w ${foldwrapping}` eval ${zenitybin} --title \" ${title} \" --list --text \""${localtext}"\" --hide-column 1 --column Index --column `translate_text "Option"` ${localarguments} \"AUTOMATE\" \"`translate_text "Help with this question"`\" > "/tmp/sakis3g.dialog.$$" buttonselection=$? elif [ "a${SGUI}" = "awhiptail" ]; then localarguments=`selection_argument options "$@" | ${grepbin} -n "." | ${sedbin} -e "s/^\([0-9]*\):\(.*\) \(.*\)$/\"\1. \3\" \"\2\"/g"` eval ${whiptailbin} --backtitle \"Sakis3G ${MYVERSION}\" --title \" ${title} \" --noitem --clear --menu \"${localtext}\" 0 0 0 ${localarguments} 2> "/tmp/sakis3g.dialog.$$" buttonselection=$?; fi termselection=`${catbin} "/tmp/sakis3g.dialog.$$" 2> /dev/null`; ${rmbin} -f "/tmp/sakis3g.dialog.$$" debug "User selected: \"%s\"\n" "${termselection}" if [ "a${termselection}" = "aAUTOMATE" ]; then variable=`selection_argument variable "$@"` localtext=`format_text "You can automate this selection by setting %s variable on command line.\n" "${variable}"` notify "${localtext}\n`select_example "$@" | ${sedbin} -e "s/ /\\\n /g"`" dialog_select "$@" selection=$? return ${selection} elif [ "a${buttonselection}" != "a0" ]; then debug "User selected button: %d\n" "${buttonselection}" selection=98 else termselection=`echo "${termselection}" | ${trbin} -t "." ""` selection=`${printfbin} "%d\n" "${termselection}" 2> /dev/null` [ "${selection}" -gt "${options}" ] && selection=0 [ "${selection}" -eq "0" ] && selection=98 [ "${selection}" -gt "0" -a "${selection}" -le "${options}" ] && eval export ${variable}="`selection_argument option ${selection} "$@"`" fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset options; unset termselection; unset buttonselection; unset localtext; unset localarguments; unset localbutton2 return "${selection}" } dialog_prompt() { dialog_cleanscreen if [ "a${SGUI}" = "adialog" ]; then ! find_binary "dialog" && return 1 elif [ "a${SGUI}" = "aXdialog" ]; then ! find_binary "Xdialog" && return 1 elif [ "a${SGUI}" = "azenity" ]; then ! find_binary "zenity" && return 1 elif [ "a${SGUI}" = "akdialog" ]; then ! find_binary "kdialog" && return 1 elif [ "a${SGUI}" = "awhiptail" ]; then ! find_binary "whiptail" && return 1 fi variable=`selection_argument variable "$@"` title=`selection_argument title "$@"` text=`selection_argument text "$@"` debug "Prompting user to type variable %s.\n" "${variable}" localtext=`format_text "You can automate this selection by setting %s variable.\n" "${variable}"` [ "a${text}" != "a" ] && localtext=`${printfbin} "%s\n\n%s: " "${localtext}" "${text}"` locallines=`echo "${localtext}" | ${wcbin} -l`; locallines=`echo ${locallines}`; locallines=`expr ${locallines} + 10`; locallines=`echo ${locallines}`; if [ "a${SGUI}" = "adialog" ]; then ${dialogbin} --backtitle "Sakis3G ${MYVERSION}" --title " ${title} " --ok-label `translate_text "OK"` --cancel-label `translate_text "Cancel"` --clear --inputbox "${localtext}" ${locallines} 0 2> "/tmp/sakis3g.dialog.$$" buttonselection=$? elif [ "a${SGUI}" = "aXdialog" ]; then ${Xdialogbin} --backtitle " ${title} " --title "Sakis3G ${MYVERSION}" --ok-label `translate_text "OK"` --cancel-label `translate_text "Cancel"` --wrap --fill --clear --inputbox "${localtext}" ${locallines} 0 2> "/tmp/sakis3g.dialog.$$" buttonselection=$? elif [ "a${SGUI}" = "akdialog" ]; then ${kdialogbin} --title " ${title} " --inputbox "${localtext}" "" > "/tmp/sakis3g.dialog.$$" 2> /dev/null buttonselection=$? elif [ "a${SGUI}" = "azenity" ]; then need_arg "foldwrapping" localtext=`echo "${localtext}" | ${sedbin} -e "s/_/__/g"` find_binary "fold" && localtext=`echo "${localtext}" | ${foldbin} -s -w ${foldwrapping}` ${zenitybin} --title " ${title} " --entry --text "${localtext}" > "/tmp/sakis3g.dialog.$$" buttonselection=$? elif [ "a${SGUI}" = "awhiptail" ]; then ${whiptailbin} --backtitle "Sakis3G ${MYVERSION}" --title " ${title} " --clear --inputbox "${localtext}" 0 0 2> "/tmp/sakis3g.dialog.$$" buttonselection=$? fi termselection=`${catbin} "/tmp/sakis3g.dialog.$$" 2> /dev/null`; ${rmbin} -f "/tmp/sakis3g.dialog.$$" termselection=`sanitize "${termselection}"` debug "User pressed button %d while typed: \"%s\"\n" "${buttonselection}" "${termselection}" # TODO: Implement example if [ "a${buttonselection}" = "a0" ]; then debug "User pressed OK.\n" if [ "a${termselection}" != "a" ]; then debug "User typed: %s\n" "${termselection}" eval "export ${variable}=\"${termselection}\"" selection=0 else debug "User entered no text.\n" "${variable}" selection=98 fi elif [ "a${termselection}" = "a" -o "a${buttonselection}" != "a0" ]; then debug "User requested to cancel.\n" selection=98 else debug "Unknown error.\n" selection=99 fi debug "Considering selection: %d\n" "${selection}" unset variable; unset title; unset text; unset termselection; unset buttonselection; unset localtext return "${selection}" } dialog_clearscreen() { [ "a${DEBUG}" = "a" ] && find_binary "clear" && ${clearbin} return 0 } selection_argument() { selectarg="$1" [ "$#" -gt "0" ] && shift case "${selectarg}" in variable) echo "$1" ;; title) echo "$2" ;; text) echo "$3" ;; button1) echo "$4" ;; button2) echo "$5" ;; options) for selectind in `${seqbin} 6 2 $#` do eval selcode=\${${selectind}} selectinc=`expr ${selectind} + 1`; selectinc=`echo ${selectinc}` eval seloption=\${${selectinc}} echo "${selcode} ${seloption}" unset selcode; unset seloption; unset selectinc done unset selectind ;; option) selectind=$1 [ "$#" -gt "0" ] && shift selectind=`expr ${selectind} \* 2`; selectind=`echo ${selectind}` selectind=`expr ${selectind} + 4`; selectind=`echo ${selectind}` eval selcode=\${${selectind}} echo "${selcode}" unset selcode; unset selectind ;; invalid) for selectind in `${seqbin} 7 2 $#` do eval selcode=\${${selectind}} if [ "a${selcode}" = "a$1" ]; then debug "%s==%s.\n" "$1" "${selcode}" unset selcode; unset selectarg selectind=`expr ${selectind} - 5`; selectind=`echo ${selectind}` selectind=`expr ${selectind} / 2`; selectind=`echo ${selectind}` return ${selectind} fi debug "%s!=%s\n" "${selcode}" "${1}" unset selcode done debug "Not a valid option \"%s\".\n" "$1" unset selectind return 0 ;; *) debug "Unknown selection id %s.\n" "${selectarg}" ;; esac unset selectarg } # Returns true if $1 is found within $2. strinstr() { [ "a$1" = "a" -o "a$2" = "a" ] && return 1 if [ "a$3" = "a" ]; then strinstrsep=":" else strinstrsep="$3" fi strinstrfound=`echo "${strinstrsep}${2}${strinstrsep}" | grep "${strinstrsep}${1}${strinstrsep}"` strinstrfound=`echo "${strinstrfound}"` unset strinstrsep if [ "a${strinstrfound}" != "a" ]; then unset strinstrfound return 0 fi unset strinstrfound return 1 } # Checks if running with root priviledges we_are_root_already() { if [ "a${UID}" = "a0" -o "a${USER}" = "aroot" -o "a${EUID}" = "a0" ]; then return 0 fi debug "Not currently running with root privileges.\n" return 1 } # Makes sure we are root we_are_root() { if we_are_root_already; then debug "We are root already. Proceeding.\n" return 0 fi state_variables verbose "Acquiring root privileges" [ -z "${SUMETHOD}" ] && check_su_software [ -z "${ME}" ] && have_me cleanscreen debug "This instance will call %s and abort.\n" "${SUMETHOD}" case "${SUMETHOD}" in "sudo") [ "a${DEBUG}" = "a" ] && find_binary "clear" && ${clearbin} eval ${sudobin} ${ME} ${allargs} ${statevariables} ret=$? if [ "$ret" -eq "1" ]; then echo echo If it didn\'t worked, you need to add yourself echo to sudo file: as root, type visudo and add the echo following line at the end of file: echo ${runner} ALL=\(root\) NOPASSWD: ${ME} stop_fmt_error 1 "Failed to become root." fi ;; "gksu") # Nusty workaround because gksu does not properly handle arguments containing whitespaces ${touchbin} "/tmp/sakis3g.gksu.wrapper.$$" ${chmodbin} +x "/tmp/sakis3g.gksu.wrapper.$$" ${printfbin} "#!/bin/sh\nexport PROVIDER=\"%s\"\n%s %s %s\nexit \$?\n\n" "${PROVIDER}" "${ME}" "${allargs}" "${statevariables}" > "/tmp/sakis3g.gksu.wrapper.$$" [ ! -f "/tmp/sakis3g.gksu.wrapper.$$" ] && stop_fmt_error 3 "No method for acquiring root privileges found." debug show_file "/tmp/sakis3g.gksu.wrapper.$$" ${gksubin} /tmp/sakis3g.gksu.wrapper.$$ ret=$? ${rmbin} -f "/tmp/sakis3g.gksu.wrapper.$$" ;; "kdesu") ${kdesubin} "${ME} ${allargs} ${statevariables}" ret=$? ;; "su") if [ -n "${stick_to_console}" -a -z "${interactive}" ]; then notify "\nUtility \"%s\" found but cannot be used since we are not interactive.\n" "su" notify "Either enable interactive mode:\n" notify "\t%s --interactive %s\n" "${ME}" "${allargs}" notify "or, force using %s instead:\n" "sudo" notify "\t%s --sudo %s\n\r\n" "${ME}" "${allargs}" stop_fmt_error 3 "No method for acquiring root privileges found." fi [ "a${DEBUG}" = "a" ] && find_binary "clear" && ${clearbin} term_print "Please supply root password, or press enter to abort." ${subin} -c "${ME} ${allargs} ${statevariables}" ret=$? ;; esac stop_with ${ret} } # Shows error show_fmt_error() { errortext=`format_text "$@"` debug "Error: %s\n" "${errortext}" if [ "a${noerror}" != "a" ]; then debug "Skipping error notification due to configuration.\n" unset errortext return 0 fi guruplug_error case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_error "${errortext}" ;; "9menu") nine_error "${errortext}" ;; "interactive terminal") term_error "${errortext}" ;; "terminal") term_error "${errortext}" ;; *) term_error "${errortext}" ;; esac unset errortext } cleanscreen() { osd_cleanscreen case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_cleanscreen term_clearline ;; "9menu") term_clearline ;; "interactive terminal") term_clearline ;; "terminal") term_clearline ;; *) term_clearline ;; esac } osd_cleanscreen() { if [ "a${OSDPID}" != "a" ]; then if find_binary "kill"; then ! notrunning "${OSDPID}" && ${killbin} -1 "${OSDPID}" 2> /dev/null ! notrunning "${OSDPID}" && ${killbin} -9 "${OSDPID}" 2> /dev/null fi unset OSDPID fi return 0 } osd_verbose() { [ "a${OSDOUTPUT}" = "a" ] && return 1 osd_cleanscreen case "${OSDOUTPUT}" in osd_cat) need_arg "XOSDFONT" if [ "a${OSDISP}" != "a${ISPID}" ]; then unset OSDFGCOLOR; unset OSDBGCOLOR; fi [ "a${OSDFGCOLOR}" = "a" ] && OSDFGCOLOR=`echo ${ISP_FG_COLOR} | ${sedbin} -e "s/^\(..\)\(..\)\(..\)$/rgb:\1\/\2\/\3/g"` [ "a${OSDBGCOLOR}" = "a" ] && OSDBGCOLOR=`echo ${ISP_BG_COLOR} | ${sedbin} -e "s/^\(..\)\(..\)\(..\)$/rgb:\1\/\2\/\3/g"` [ "a${OSDFGCOLOR}" = "a" ] && OSDFGCOLOR="rgb:80/ff/80" [ "a${OSDBGCOLOR}" = "a" ] && OSDBGCOLOR="rgb:00/40/00" OSDISP="${ISPID}" export OSDISP; export OSDFGCOLOR; export OSDBGCOLOR; ${OSDOUTPUT} -T "Sakis3G: $1" -P ${verbosecurrentcount} -b percentage -O 2 -c ${OSDFGCOLOR} -u ${OSDBGCOLOR} -f "${XOSDFONT}" -p bottom -a 0 -d 10 -A center & OSDPID=$! eval "disown -a" > /dev/null 2> /dev/null export OSDPID [ "a${verbosecurrentcount}" = "a100" ] && sleep 3 ;; aosd_cat) need_arg "AOSDFONT" ${OSDOUTPUT} -n "${AOSDFONT}" -f 100 -t 2 --input=- -u 10000 -o 3000 < /dev/null 2> /dev/null export OSDPID [ "a${verbosecurrentcount}" = "a100" ] && sleep 3 ;; esac } verbose() { need_binary "printf" if [ "a$1" = "a100" ]; then verbosecurrentcount=93 shift fi verbosetext=`format_text "$@"` [ "${verbosecurrentcount}" = "a" ] && verbosecurrentcount=0 if [ "a${verbosetext}" = "a${lastverbosetext}" ]; then verbosecurrentcount=`expr ${verbosecurrentcount} + 1`; guruplug_verbose_same else verbosecurrentcount=`expr ${verbosecurrentcount} + 7`; guruplug_verbose fi lastverbosetext="${verbosetext}" verbosecurrentcount=`echo ${verbosecurrentcount}` export lastverbosetext export verbosecurrentcount debug "Verbosing: %d%% %s\n" "${verbosecurrentcount}" "${verbosetext}" if [ "a${noverbose}" != "a" ]; then debug "Skipping verbose due to configuration.\n" unset verbosetext return 0 fi if [ "a${OSDOUTPUT}" != "a" ]; then osdtext=`${printfbin} "$@"` osd_verbose "${osdtext}" unset osdtext else case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_verbose "${verbosetext}" ;; "9menu") nine_verbose "${verbosetext}" ;; "interactive terminal") term_verbose "${verbosetext}" ;; "terminal") term_verbose "${verbosetext}" ;; *) term_verbose "${verbosetext}" ;; esac fi unset verbosetext } notify() { notificationtext=`format_text "$@"` debug "Notify: %s\n" "${notificationtext}" if [ "a${nonotify}" != "a" ]; then debug "Skipping notification due to configuration.\n" unset notificationtext return 0 fi case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_notify "${notificationtext}" ;; "9menu") nine_notify "${notificationtext}" ;; "interactive terminal") term_notify "${notificationtext}" ;; "terminal") term_notify "${notificationtext}" ;; *) term_notify "${notificationtext}" ;; esac unset notificationtext } balloon_notify() { notificationtext=`format_text "$@"` if [ "a${nonotify}" != "a" ]; then debug "Skipping balloon notification due to configuration: %s\n" "${notificationtext}" unset notificationtext return 0 fi # File is deleted during release_X_cookie [ "a${PROVIDER}" != "a" ] && [ -x "${PROVIDER}" ] && ${PROVIDER} getfile "files/sakis3g.png" 2> /dev/null > "/tmp/sakis3g.notification.icon.$$.png" debug "Will display final message using libnotify.\n" if [ ! -f "/tmp/sakis3g.notification.icon.$$.png" ]; then debug "Notifying user without icon.\n" debug run_command "${notify_sendbin} \"Sakis3G\" \"${notificationtext}\"" else debug "Notifying user with icon.\n" debug run_command "${notify_sendbin} --icon=\"/tmp/sakis3g.notification.icon.$$.png\" \"Sakis3G\" \"${notificationtext}\"" debug run_command "${rmbin} -f \"/tmp/sakis3g.notification.icon.$$.png\"" fi unset notificationtext } finalnotify() { guruplug_notify if [ "a${prefer_osd}" != "a" -a "a${OSDOUTPUT}" != "a" ]; then verbose "100" "$@" elif [ "a${prefer_osd}" = "a" -a "a${balloons}" != "a" -a "a${stick_to_console}" = "a" ] && find_binary "notify-send" && [ "a${DBUS_SESSION_BUS_ADDRESS}" != "a" -a "a${SESSION_MANAGER}" != "a" ]; then balloon_notify "$@" else notify "$@" fi } translate_selection() { unset translatedarguments localcounter=0 for localargument in "$@" do localcounter=`expr ${localcounter} + 1`; localcounter=`echo ${localcounter}` if [ "${localcounter}" -eq "1" ]; then translatedarguments="\"${localargument}\"" elif [ "${localcounter}" -le "5" ]; then translatedtext=`translate_text "${localargument}"` translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${translatedtext}"` unset translatedtext elif [ "${localcounter}" -gt "5" ]; then verification=`expr \( ${localcounter} / 2 \) \* 2`; verification=`echo ${verification}` if [ "a${verification}" = "a${localcounter}" ]; then translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${localargument}"` else translatedtext=`translate_text "${localargument}"` translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${translatedtext}"` unset translatedtext fi unset verification fi done unset localcounter; unset eval "user_select \"translated\" ${translatedarguments}" translatedselection=$? unset translatedarguments return ${translatedselection} } translate_confirm() { unset translatedarguments localcounter=0 for localargument in "$@" do localcounter=`expr ${localcounter} + 1`; localcounter=`echo ${localcounter}` if [ "${localcounter}" -eq "1" ]; then translatedarguments="\"${localargument}\"" elif [ "${localcounter}" -le "5" ]; then translatedtext=`translate_text "${localargument}"` translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${translatedtext}"` unset translatedtext elif [ "${localcounter}" -gt "5" ]; then translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${localargument}"` fi done unset localcounter; unset eval "user_confirm \"translated\" ${translatedarguments}" translatedselection=$? unset translatedarguments return ${translatedselection} } translate_prompt() { unset translatedarguments localcounter=0 for localargument in "$@" do localcounter=`expr ${localcounter} + 1`; localcounter=`echo ${localcounter}` if [ "${localcounter}" -eq "1" ]; then translatedarguments="\"${localargument}\"" elif [ "${localcounter}" -le "5" ]; then translatedtext=`translate_text "${localargument}"` translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${translatedtext}"` unset translatedtext elif [ "${localcounter}" -gt "5" ]; then verification=`expr \( ${localcounter} / 2 \) \* 2`; verification=`echo ${verification}` if [ "a${verification}" = "a${localcounter}" ]; then translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${localargument}"` else translatedtext=`translate_text "${localargument}"` translatedarguments=`${printfbin} "%s \"%s\"" "${translatedarguments}" "${translatedtext}"` unset translatedtext fi unset verification fi done unset localcounter; unset eval "user_prompt \"translated\" ${translatedarguments}" translatedselection=$? unset translatedarguments return ${translatedselection} } user_confirm() { unset selection if [ "a$1" != "atranslated" ]; then debug "Asking user to confirm: %s\n" "`echo "$@"`" translate_confirm "$@" return $? else shift debug "Asking user to confirm: %s\n" "`echo "$@"`" fi if [ "$#" -lt 3 ]; then debug "FIXME: Wrong number of arguments (%d). Returning 99.\n" "$#" return 99 fi variable=`selection_argument variable "$@"` if [ "a$6" = "areset" -a "a${interactive}" != "a" ]; then eval unset ${variable}yes eval unset ${variable}no else eval alreadyset=\${${variable}yes} if [ "a${alreadyset}" != "a" ]; then debug "Switch %syes is already set.\n" "${variable}" return 0 fi eval alreadyset=\${${variable}no} if [ "a${alreadyset}" != "a" ]; then debug "Switch %sno is already set.\n" "${variable}" return 1 fi fi if voodoo_mode; then debug "Voodoo-mode is enabled. Will consider it a yes.\n" eval unset ${variable}no eval ${variable}yes=1 eval export ${variable}yes selection=0 return 0 fi case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_confirm "$@" selection=$? ;; "9menu") nine_confirm "$@" selection=$? ;; "interactive terminal") interactive_term_confirm "$@" selection=$? ;; "terminal") term_confirm "$@" selection=$? ;; *) term_confirm "$@" selection=$? ;; esac variable=`selection_argument variable "$@"` if [ "a${selection}" = "a0" ]; then debug "User answered \"yes\".\n" eval unset ${variable}no eval ${variable}yes=1 eval export ${variable}yes selection=0 else debug "User answered \"no\".\n" eval unset ${variable}yes eval ${variable}no=1 eval export ${variable}no selection=1 fi unset variable return ${selection} } user_select() { unset selection if [ "a$1" != "atranslated" ]; then debug "Asking user to select: %s\n" "`echo "$@"`" translate_selection "$@" return $? else shift debug "Asking user to select: %s\n" "`echo "$@"`" fi if [ "$#" -lt 3 ]; then debug "FIXME: Wrong number of arguments (%d). Returning 99.\n" "$#" return 99 fi variable=`selection_argument variable "$@"` eval alreadyset=\${${variable}} if [ "a${alreadyset}" != "a" ]; then debug "%s=%s\n" "${variable}" "${alreadyset}" # Check tokens first for selectioniterator in ${alreadyset} do selection_argument invalid "${selectioniterator}" "$@" selection=$? if [ "a${selection}" != "a0" -a "a${selection}" != "a" ]; then debug "User has already selected %s=\"%s\". Returning %d.\n" "${variable}" "${selectioniterator}" "${selection}" eval export ${variable}="${selectioniterator}" unset variable; unset alreadyset; unset selectioniterator return ${selection} fi unset selection; done unset selectioniterator # Check whole value then selection_argument invalid "${alreadyset}" "$@" selection=$? if [ "a${selection}" != "a0" -a "a${selection}" != "a" ]; then debug "User has already selected %s=\"%s\". Returning %d.\n" "${variable}" "${alreadyset}" "${selection}" eval export ${variable}="${alreadyset}" unset variable; unset alreadyset return ${selection} fi # Else warn show_fmt_error "Already selected value %s=\"%s\". Is not valid.\n" "${variable}" "${alreadyset}" eval unset ${variable} unset variable; unset alreadyset; else debug "Variable %s is not set already.\n" "${variable}" unset alreadyset; unset variable fi if voodoo_mode; then variable=`selection_argument variable "$@"` selectioncount=`selection_argument options "$@" | ${wcbin} -l`; selectioncount=`echo ${selectioncount}` if [ "a${selectioncount}" = "a1" ]; then selection=1 eval export ${variable}="`selection_argument option 1 "$@"`" debug "Employed voodoo-mode in selecting %s from unique option: %s\n" "${variable}" "`eval echo \\${${variable}}`" unset selectioncount; unset variable return ${selection} elif [ "a${selectioncount}" = "a2" ]; then for selection in 1 2 do voodoovalue=`selection_argument option ${selection} "$@" | ${grepbin} -i "custom" | ${wcbin} -l`; voodoovalue=`echo ${voodoovalue}` [ "a${voodoovalue}" = "a0" ] && voodoovalue=`selection_argument option ${selection} "$@" | ${grepbin} -i "other" | ${wcbin} -l`; voodoovalue=`echo ${voodoovalue}` if [ "a${voodoovalue}" = "a1" ]; then debug "Voodoo determined that selection %d leads to custom/other.\n" "${selection}" if [ "${selection}" -eq "1" ]; then selection=2 else selection=1 fi eval export ${variable}="`selection_argument option 1 "$@"`" debug "Employed voodoo-mode in selecting %s from option %d: %s\n" "${variable}" "${selection}" "`eval echo \\${${variable}}`" unset selectioncount; unset voodoovalue; unset variable return ${selection} fi unset voodoovalue done unset selection fi unset selectioncount; unset variable fi case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_select "$@" selection=$? ;; "9menu") nine_select "$@" selection=$? ;; "interactive terminal") interactive_term_select "$@" selection=$? ;; "terminal") term_select "$@" selection=$? ;; *) term_select "$@" selection=$? ;; esac debug "User selection was %d.\n" "${selection}" return ${selection} } # Prompts user to enter text user_prompt() { if [ "a$1" != "atranslated" ]; then debug "Asking user to enter: %s\n" "`echo "$@"`" translate_prompt "$@" return $? else shift debug "Asking user to enter: %s\n" "`echo "$@"`" fi if [ "$#" -lt 3 ]; then debug "FIXME: Wrong number of arguments (%d). Returning 99.\n" "$#" return 99 fi promptvariable=`selection_argument variable "$@"` eval alreadyset=\${${promptvariable}} if [ "a${alreadyset}" != "a" ]; then selection=0 debug "%s=%s\n" "${promptvariable}" "${alreadyset}" debug "User has already entered %s=\"%s\". Returning %d.\n" "${promptvariable}" "${alreadyset}" "${selection}" unset alreadyset; unset promptvariable return ${selection} else debug "Variable %s is not set already.\n" "${promptvariable}" unset alreadyset; unset promptvariable fi case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) dialog_prompt "$@" selection=$? ;; "9menu") nine_prompt "$@" selection=$? ;; "interactive terminal") interactive_term_prompt "$@" selection=$? ;; "terminal") term_prompt "$@" selection=$? ;; *) term_prompt "$@" selection=$? ;; esac promptvariable=`selection_argument variable "$@"` eval "alreadyset=\"\${${promptvariable}}\"" debug "New value is %s=\"%s\". Returning %d.\n" "${promptvariable}" "${alreadyset}" "${selection}" unset alreadyset; unset promptvariable return ${selection} } # Stops execution with return status $1 stop_with() { verbose "Cleaning" if [ "a$1" = "a" ]; then debug "Stopping operation with return status: %d\n" "99" exit 99 else debug "Stopping operation with return status: %d\n" "$1" exit $1 fi } # Shows error and aborts execution stop_fmt_error() { errorcode="$1" [ "$#" -gt "0" ] && shift show_fmt_error "$@" stop_with ${errorcode} } # Make sure usual binary containing directories exist in PATH, even # if not running as root. Some distributions do not include those # folders in PATH (although they contain some useful user oriented # utilities) if not running as root, or if not running from an # interactive shell. fix_path() { [ -n "${PATHFIXXED}" ] && return 0 for fixpathi in "/bin" "/usr/bin" "/sbin" "/usr/sbin" do if strinstr "${fixpathi}" "${PATH}"; then debug "Dir \"%s\" exists in PATH.\n" "${fixpathi}" else export PATH="${fixpathi}:${PATH}" debug "Added \"%s\" to PATH.\n" "${fixpathi}" fi done unset fixpathi PATHFIXXED=YES debug "Done setting up PATH.\n" } # Locates full path of binary specified in argument find_binary() { [ "a$1" = "a" ] && return 1 binaryvariable=`echo "$1" | sed -e "s/-/_/g"` binaryvariable=`echo "${binaryvariable}" | sed -e "s/9/nine/g"` [ "a${binaryvariable}" = "a" ] && binaryvariable="$1" findbinaryfound=`eval echo \\\${${binaryvariable}bin}` if [ "a${findbinaryfound}" = "a" ]; then if [ "a${whichbin}" = "a" ]; then findbinaryfound=`which which 2> /dev/null` elif [ ! -x "${whichbin}" ]; then findbinaryfound=`which which 2> /dev/null` else findbinaryfound="${whichbin}" fi if [ "a${findbinaryfound}" = "a" ]; then debug "Unable to locate \"%s\" within PATH, because \"%s\" utility is not available.\n" "$1" "which" unset findbinaryfound return 1 else if [ -z "${whichbin}" ]; then export whichbin="${findbinaryfound}" debug "Can search through PATH, \"%s\" binary found.\n" "which" fi findbinaryfound=`${findbinaryfound} "${1}" 2> /dev/null` if [ "a${findbinaryfound}" = "a" ]; then debug "Unable to locate \"%s\" within PATH.\n" "$1" unset findbinaryfound return 1 elif [ -x "${findbinaryfound}" ]; then debug "Located \"%s\" within PATH (%s).\n" "$1" "${findbinaryfound}" eval export ${binaryvariable}bin="${findbinaryfound}" fi fi fi if [ -x "${findbinaryfound}" ]; then unset findbinaryfound return 0 else debug "Unable to execute \"%s\" from \"%s\".\n" "$1" "${findbinaryfound}" unset findbinaryfound eval unset ${binaryvariable}bin return 1 fi } # Aborts execution if "$1" binary is not found. need_binary() { [ "a$1" = "a" ] && term_error "FIXME: Executed need_binary with no argument." ! find_binary "$1" && stop_fmt_error 4 "Unable to locate dependency \"%s\". Script will now abort." "$1" } # Check dependencies. Only really required staff should be placed here. # We cannot yet search in PATH. check_level_one_deps() { for checkdependency in which echo grep do need_binary "${checkdependency}" done unset checkdependency debug "Level 1 dependencies met.\n" } # Checks if communication software is available and aborts if not check_com_software() { ! find_binary "wvdial" && direct_pppd=yes if [ -n "${direct_pppd}" ]; then need_binary "pppd" need_arg "PPPD_PEERS" if [ ! -d "${PPPD_PEERS}" ]; then debug "Unable to locate pppd peers directory (%s)." "${pppdpeerdir}" fi fi for checkdependency in chat do need_binary "${checkdependency}" done unset checkdependency return 0 } # Checks if method for becoming root, exists. check_su_software() { unset SUMETHOD if [ -z "${alwayssudo}" ]; then if [ -z "${stick_to_console}" ]; then if find_binary "gksu"; then debug "Running on a GNOME system.\n" SUMETHOD="gksu" elif find_binary "kdesu"; then debug "Running on a KDE system.\n" SUMETHOD="kdesu" elif [ -x "/usr/lib/kde4/libexec/kdesu" ]; then export kdesubin="/usr/lib/kde4/libexec/kdesu" debug "Running on a KDE4 system.\n" SUMETHOD="kdesu" fi fi if [ -z "${SUMETHOD}" ]; then if find_binary "su"; then debug "Using plain text mode su.\n" SUMETHOD="su" else debug "No su method found. Will check if sudo available.\n" export alwayssudo=yes fi fi fi if [ -n "${alwayssudo}" ]; then ! find_binary "sudo" && stop_fmt_error 3 "No method for acquiring root privileges found." debug "Running with sudo configuration.\n" SUMETHOD="sudo" fi return 0 } # Forces use of text mode utilities for getting root privileges console_su_software() { if [ "${SUMETHOD}" = "kdesu" -o "${SUMETHOD}" = "gksu" ]; then if find_binary "su"; then debug "Reverting to plain text mode su.\n" SUMETHOD="su" else debug "No text mode su found. Will check if sudo available.\n" export alwayssudo=yes check_su_software fi fi } # Check dependencies. Only really required staff should be placed here. # We can now search within path. check_level_two_deps() { for checkdependency in printf wc cut cat tail head sort uniq ls sed setsid getent ps chmod chown touch expr tr seq cp rm who mv expr basename dirname do need_binary "${checkdependency}" done unset checkdependency debug "Level 2 dependencies met.\n" if [ "a${PROVIDER}" != "a" ] && [ ! -x "${PROVIDER}" ]; then debug run_command "${chmodbin} +x \"${PROVIDER}\"" if [ ! -x "${PROVIDER}" ]; then stop_fmt_error 5 "Unable to determine my path.\n" fi debug "Successfully turned myself an executable.\n" fi } # If running as root, checks dependencies that should be met # once running as root. If not running as root, checks if # software for becoming root, is available. check_root_deps() { if ! we_are_root_already; then check_su_software else for checkdependency in ifconfig do need_binary "${checkdependency}" done unset checkdependency fi debug "Root level dependencies met.\n" } # Locate required utilities within PATH resolv_binaries() { check_level_one_deps fix_path get_me ${1} check_level_two_deps debug "Basic binaries are resolved.\n" } # Provides a writable log position need_log() { need_arg "LOGPOSITION" for logcandidate in "${LOGPOSITION}" "/var/log/sakis3g.log" "sakis3g.log.$$" "/tmp/sakis3g.log.$$" do if [ "a${logcandidate}" != "a" ]; then ${touchbin} "${logcandidate}" 2> /dev/null if [ -w "${logcandidate}" ]; then export LOGPOSITION="${logcandidate}" debug "Log file is set to \"%s\".\n" "${LOGPOSITION}" return 0 else unset logposition fi fi done debug "Failed to find a place to store log.\n" export LOGPOSITION="/dev/null" debug "Log file is set to \"%s\".\n" "${logposition}" return 1 } # Returns true(0) if process with PID given as # argument, is not running any more. notrunning() { if [ -n "$1" ]; then pidrunning=`${psbin} -p $1 -o pid= 2> /dev/null | wc -l` pidrunning=`echo ${pidrunning}` else pidrunning=1 fi if [ "${pidrunning}" -ne "0" ]; then debug "PID %s is still running.\n" "$1" else debug "PID %s is not running any more.\n" "$1" fi return ${pidrunning} } # Sets PPROCESS variable get_parent_process() { pidtocheck=$1 [ "a${pidtocheck}" = "a" ] && pidtocheck="${PPID}" PPROCESS=`${psbin} -p ${pidtocheck} -o comm= 2> /dev/null` export PPROCESS if [ "a${PPROCESS}" = "a" ]; then debug "Unable to get parent process name.\n" unset PPROCESS; unset pidtocheck return 1 fi unset pidtocheck return 0 } # Check if called by udevd. If yes, spawn in background # and exit this instance. check_udevd() { if [ "a${PROVIDER}" = "a" ]; then get_parent_process else pppid=`${psbin} -p ${PPID} -o ppid= 2> /dev/null` pppid=`echo ${pppid}` get_parent_process "${pppid}" unset pppid fi debug "Parent process is: %s\n" "${PPROCESS}" if [ "a${PPROCESS}" = "audevd" ]; then debug "Running by a udevd event.\n" need_log if have_me; then debug "Unconditionally setting DISPLAY to :0.\n" export DISPLAY=:0 debug "Will now spawn child process in background.\n" ${ME} "$@" > "${LOGPOSITION}" 2>&1 & stop_with 0 fi else debug "Running by user request.\n" fi } # Get my location if possible get_me() { unset metarget [ -x "${PROVIDER}" ] && metarget="${PROVIDER}" [ -z "${metarget}" ] && metarget="$1" find_binary "readlink" && ME=`${readlinkbin} -e ${metarget} 2> /dev/null` [ -z "${ME}" ] && find_binary "which" && ME="`${whichbin} ${metarget} 2> /dev/null`" unset metarget [ -n "${ME}" ] && [ ! -x "${ME}" ] && unset ME if [ -z "${ME}" ]; then unset ME debug "Unable to determine my own location.\n" else debug "My location is \"%s\".\n" "${ME}" fi } # Makes sure we know our own executable have_me() { [ -n "${ME}" ] && [ -x "${ME}" ] && return 0; stop_fmt_error 5 "Unable to determine my path.\n" } # If we are root, attempts to determine real user # behind it, by looking back the process tree. Goes # back 15 processes before giving up. resolv_root() { [ -z "$1" ] && pid=$$ [ -z "${pid}" ] && pid=$1 puser=`${psbin} -p ${pid} -o user= 2> /dev/null` if [ -z "${puser}" ]; then unset pid; unset puser return elif [ "${puser}" != "root" ]; then runner="${puser}" unset pid; unset puser return fi unset puser ppid=`${psbin} -p ${pid} -o ppid= 2> /dev/null`; unset pid if [ -z "${ppid}" ]; then unset ppid return elif [ "a${ppid}" = "a1" ]; then unset ppid return fi [ -z "$2" ] && count=0 count=`expr $2 + 1` count=`echo ${count}` [ "$count" -lt 15 ] && resolv_root ${ppid} ${count} unset ppid; unset count } # Locates really running user. If root, attempts to resolv # it to real user. find_user() { unset runner; unset runhome [ -n "${USER}" ] && runner="${USER}" [ -n "${LOGNAME}" ] && runner="${LOGNAME}" [ -n "${USERNAME}" ] && runner="${USERNAME}" [ -z "${runner}" ] && find_binary "who" && runner=`${whobin} -m | ${cutbin} -d\ -f1` [ -z "${runner}" ] && we_are_root_already && runner="root" [ -n "${runner}" ] && [ "${runner}" = "root" ] && resolv_root $$ 0 if [ -n "${runner}" ]; then runhome=`${getentbin} passwd ${runner} 2> /dev/null | ${cutbin} -d: -f6` [ -n "${runhome}" ] && [ ! -d "${runhome}" ] && unset runhome [ -z "${runhome}" ] && unset runner [ -n "${runner}" ] && debug "Person behind screen is %s.\n" "${runner}" fi [ -z "${runner}" ] && debug "Unable to find our username.\n" } # Determines if display $1 is unique local display. unique_local_display() { debug "Will check if display %s belongs to unique user logged in.\n" "$1" [ "a$1" = "a" ] && return 1 ! find_binary "who" && return 1 loggedusers=`${whobin} | ${grepbin} -v root | ${cutbin} -d\ -f1 | ${sortbin} | ${uniqbin} | ${wcbin} -l` loggedusers=`echo ${loggedusers}` if [ "a${loggedusers}" != "a1" ]; then debug "Found %d logged users. Cannot make sure who will really see message.\n" "${loggedusers}" unset loggedusers return 1 fi unset loggedusers loggeduser=`${whobin} | ${grepbin} -v root | ${cutbin} -d\ -f1 | ${sortbin} | ${uniqbin}` confirm=`${whobin} | ${grepbin} ${1} | ${cutbin} -d\ -f1 | ${sortbin} | ${uniqbin} | ${grepbin} "^${loggeduser}$"` if [ "a${loggeduser}" = "a${confirm}" ]; then debug "Unique display %s belongs to user %s.\n" "$1" "${loggeduser}" unset confirm; unset loggeduser; return 0 fi debug "Display %s does not belongs to user %s.\n" "$1" "${loggeduser}" unset confirm; unset loggeduser; return 1 } # Attemtps to get access to display $1 access_display() { debug "Will attempt to get access to display %s.\n" "$1" [ "a$1" = "a" ] && return 1 ! find_binary "xauth" && return 1 [ "a${XAUTHORITY}" = "a" ] && unset XAUTHORITY gotaccess=`${xauthbin} nlist $1 2> /dev/null | ${wcbin} -l` gotaccess=`echo ${gotaccess}` if [ "a${gotaccess}" = "a0" ]; then xuser=`${whobin} -u | ${grepbin} -v "^root" | ${grepbin} ${1} | ${cutbin} -d\ -f1 | ${sortbin} | ${uniqbin}` xhome=$(${getentbin} passwd ${xuser} | ${cutbin} -d: -f6) debug "Not currently trusted to display %s belonging to %s.\n" "${1}" "${xuser}" if [ "a${LOCALAUTHORITY}" != "a" ] && [ -r "${LOCALAUTHORITY}" ]; then xholder="${LOCALAUTHORITY}" elif [ -d "${xhome}" ] && [ -r "${xhome}/.Xauthority" ]; then xholder="${xhome}/.Xauthority" else unset xholder fi if [ "a${xholder}" = "a" ]; then debug "Unable to locate Xauthority file of %s.\n" "${xuser}" else debug "Will attempt to steal cookie from %s.\n" "${xholder}" if [ "a${HOME}" = "a" ]; then rruser="${runner}" we_are_root_already && rruser="root" rrhome=$(${getentbin} passwd ${rruser} | ${cutbin} -d: -f6) if [ -d "${rrhome}" -a "a${xhome}" != "a${rrhome}" ]; then debug "HOME variable not set already. Setting HOME for %s: %s\n" "${rruser}" "${rrhome}" export HOME="${rrhome}" fi unset rruser; unset rrhome; else debug "HOME directory set already (%s).\n" "${HOME}" fi ${xauthbin} -f "${xholder}" nextract - $1 2> /dev/null | ${xauthbin} nmerge - 2> /dev/null gotaccess=`${xauthbin} nlist ${1} 2> /dev/null | ${wcbin} -l` gotaccess=`echo ${gotaccess}` if [ "a${gotaccess}" = "a0" ]; then debug "Failed to steal cookie.\n" else debug "Cookie stolen from %s(%s) to %s.\n" "${xuser}" "${1}" "${HOME}/.Xauthority" export XCOOKIE="$1" addexittrap "release_X_cookie" EXIT unset xuser; unset xhome; unset gotaccess; unset xholder return 0 fi fi unset xuser; unset xhome; unset gotaccess; unset xholder else debug "Already granted access to display %s.\n" "${1}" [ "a${XAUTHORITY}" != "a" ] && export LOCALAUTHORITY="${XAUTHORITY}" unset gotaccess return 0 fi return 1 } # Find DISPLAY find_display() { if [ -n "${stick_to_console}" ]; then unset DISPLAY; unset display; debug "Not using an X display due to stick-to-console variable.\n" else display="${DISPLAY}" # If display is not set, or is remote, attempt to find a local display of runner user. [ -z "${DISPLAY}" -o "`echo ${DISPLAY} | ${cutbin} -b1`" != ":" ] \ && display="" \ && [ -n "${runner}" -a "a${runner}" != "aroot" ] \ && find_binary "who" \ && display=`${whobin} -m | ${grepbin} "^${runner}" | ${grepbin} "(\:.*)" | ${cutbin} -d\( -f2 | ${cutbin} -d\) -f1 | ${sortbin} | ${headbin} -1` # If DISPLAY is set to a local display, but we are run # from root himself, and that X display is the unique # local X display available, use it no matter what. [ -n "${display}" -a -n "${DISPLAY}" -a "a${runner}" = "aroot" ] \ && ! unique_local_display "${DISPLAY}" && unset display # Get number of display (if any) displaynum=`echo ${display} | ${cutbin} -b2- | ${cutbin} -d. -f1` display=":${displaynum}" # Validate that determined xsession exists. [ ! -S "/tmp/.X11-unix/X${displaynum}" ] && unset display unset displaynum [ -n "${display}" ] && ! access_display "${display}" && unset display if [ -z "${display}" ]; then debug "Unable to find a local X display, will stick to terminal.\n" unset DISPLAY; unset display; export stick_to_console=yes find_gui else export display export DISPLAY="${display}" fi fi if [ -z "${display}" ]; then unset DISPLAY; unset display; export stick_to_console=yes console_su_software else debug "Will be using display %s.\n" "${display}" fi } # Selects GUI to be used if not already set by SGUI variable. find_gui() { debug "Selecting GUI.\n" if [ -n "${stick_to_console}" -a -n "$SGUI" ]; then debug "Validating pre-selected GUI: %s\n" "${SGUI}" [ "a$SGUI" = "azenity" ] && unset SGUI [ "a$SGUI" = "agdialog" ] && unset SGUI [ "a$SGUI" = "akdialog" ] && unset SGUI [ "a$SGUI" = "aXdialog" ] && unset SGUI [ "a$SGUI" = "a9menu" ] && unset SGUI [ "a$SGUI" = "agnome-terminal" ] && unset SGUI [ "a$SGUI" = "akonsole" ] && unset SGUI [ "a$SGUI" = "axterm" ] && unset SGUI [ -z "${SGUI}" ] && debug "Could not be used from console. Will seek an alternative.\n" fi if [ "a${SGUI}" != "a" -a "a${SGUI}" != "ainteractive terminal" -a "a${SGUI}" != "aterminal" ] && ! find_binary "${SGUI}"; then debug "%s not found. Will search for another GUI provider.\n" "${SGUI}" unset SGUI fi if [ "a${stick_to_console}" = "a" ]; then [ "a${SGUI}" = "a9menu" ] && ! find_binary "9menu" && unset SGUI [ "a${SGUI}" = "a9menu" ] && ! find_binary "xterm" && unset SGUI [ -z "${SGUI}" ] && find_binary "kdialog" && SGUI="kdialog" [ -z "${SGUI}" ] && find_binary "zenity" && SGUI="zenity" [ -z "${SGUI}" ] && find_binary "Xdialog" && SGUI="Xdialog" [ -z "${SGUI}" ] && find_binary "gnome-terminal" && SGUI="gnome-terminal" [ -z "${SGUI}" ] && find_binary "konsole" && SGUI="konsole" [ -z "${SGUI}" ] && find_binary "xterm" && SGUI="xterm" if [ -z "${SGUI}" ]; then debug "No graphical GUI found. Forced to stick to terminal.\n" export stick_to_console=yes fi fi if [ "a${interactive}" != "a" ]; then [ -z "${SGUI}" ] && find_binary "dialog" && SGUI="dialog" [ -z "${SGUI}" ] && find_binary "whiptail" && SGUI="whiptail" [ -z "${SGUI}" ] && SGUI="interactive terminal" fi [ -z "${SGUI}" ] && SGUI="terminal" # Custom setup per GUI [ "a${SGUI}" = "adialog" ] && addexittrap "dialog_clearscreen" [ "a${SGUI}" = "aXdialog" -o "a${SGUI}" = "a9menu" ] && export notranslate=yes && unset foldwrapping && need_arg "foldwrapping" [ "a${SGUI}" = "adialog" -o "a${SGUI}" = "awhiptail" -o "a${SGUI}" = "aterminal" -o "a${SGUI}" = "ainteractive terminal" ] && export stick_to_console=yes [ "a${SGUI}" = "adialog" -o "a${SGUI}" = "awhiptail" -o "a${SGUI}" = "ainteractive terminal" -o "a${SGUI}" = "aXdialog" -o "a${SGUI}" = "azenity" -o "a${SGUI}" = "akdialog" -o "a${SGUI}" = "a9menu" ] && export interactive=yes debug "%s selected as GUI.\n" "${SGUI}" # Forward to terminal if have to do so case "${SGUI}" in xterm) debug "Will spawn xterm window.\n" unset SGUI; export stick_to_console=yes; export interactive=yes; state_variables eval ${xtermbin} -T "Sakis3G" +cm +dc -e ${ME} ${allargs} ${statevariables} stop_with $? ;; gnome-terminal) debug "Will spawn gnome-terminal window.\n" unset SGUI; export stick_to_console=yes; export interactive=yes; state_variables eval ${gnome_terminalbin} -t "Sakis3G" -x ${ME} ${allargs} ${statevariables} stop_with $? ;; konsole) debug "Will spawn konsole window.\n" unset SGUI; export stick_to_console=yes; export interactive=yes; state_variables eval ${konsolebin} --title "Sakis3G" -e "${ME} ${allargs} ${statevariables}" stop_with $? ;; esac # Check for OSD unset OSDOUTPUT if [ "a${stick_to_console}" = "a" -a "a${prefer_osd}" != "a" ]; then if find_binary "osd_cat"; then export OSDOUTPUT="osd_cat" elif find_binary "aosd_cat"; then export OSDOUTPUT="aosd_cat" fi [ "a${OSDOUTPUT}" != "a" ] && debug "Will be using \"%s\" for displaying OSD messages.\n" "${OSDOUTPUT}" fi [ "a${prefer_osd}" != "a" -a "a${OSDOUTPUT}" = "a" ] && unset prefer_osd && debug "OSD will not appear.\n" return 0 } # Checks if module $1 is loaded module_loaded() { [ "a$1" = "a" ] && return 99 unset moduleloaded debug "Checking if module \"%s\" is currently loaded.\n" "$1" if [ -r "/proc/modules" ]; then moduleloaded=`${grepbin} "^$1 " "/proc/modules" 2> /dev/null | ${sedbin} -e "s/^$1 \([0-9][0-9]*\) \([0-9][0-9]*\) \(.*\)$/\1 \3/g"` if [ "a${moduleloaded}" = "a" ]; then debug "Module \"%s\" is not currently loaded.\n" "$1" unset moduleloaded return 1 elif [ "a${moduleloaded}" = "a$1 0" ]; then debug "Module \"%s\" is currently loaded having no users.\n" "$1" unset moduleloaded return 0 else debug "Module \"%s\" is currently loaded and occupied.\n" "$1" unset moduleloaded return 0 fi elif find_binary "lsmod"; then moduleloaded=`${lsmodbin} | ${grepbin} "^$1 " | ${wcbin} -l`; moduleloaded=`echo ${moduleloaded}` if [ "a${moduleloaded}" = "a" -o "a${moduleloaded}" = "a0" ]; then debug "Module \"%s\" is not currently loaded.\n" "$1" unset moduleloaded return 1 else debug "Module \"%s\" is currently loaded.\n" "$1" unset moduleloaded return 0 fi else show_fmt_error "Unable to check if module is currently loaded or if it has users.\n" return 1 fi } # Unloads module from system if possible module_unload() { [ "a$1" = "a" ] && return 99 ! module_loaded "$1" && return 0 ! find_binary "modprobe" && return 1 debug "Attempting to unload module \"%s\".\n" "$1" debug run_command "${modprobebin} -r -v $1" debug "Waiting for module to vanish.\n" if module_loaded "$1"; then show_fmt_error "Failed to unload module \"%s\".\n" "$1" return 1 else debug "Module \"%s\" succesfully unloaded.\n" "$1" return 0 fi } # Loads module $1 if possible, providing arguments for device $2 if applicable module_load() { [ "a$1" = "a" ] && return 99 module_loaded "$1" && return 0 ! find_binary "modprobe" && return 1 debug "Attempting to load module \"%s\".\n" "$1" need_arg "SERIALDRIVERS" needsarg=`echo " ${SERIALDRIVERS} " | ${grepbin} " $1 " | ${wcbin} -l`; needsarg=`echo ${needsarg}` if [ "a${needsarg}" = "a1" -a "a$2" != "a" ]; then if usb_device_connected "$2"; then modulevend=`echo "$2" | ${cutbin} -d: -f1` moduleprod=`echo "$2" | ${cutbin} -d: -f2` modargs="vendor=0x${modulevend} product=0x${moduleprod}" unset modulevend; unset moduleprod debug "Will provide arguments to \"%s\": %s\n" "$1" "${modargs}" else debug "Warning: Module \"%s\" needs arguments, but \"%s\" does not refer to a connected device.\n" "$1" "$2" unset modargs fi elif [ "a${needsarg}" = "a1" ]; then debug "Warning: Module \"%s\" needs arguments but device was not specified.\n" "$1" unset modargs fi debug run_command "${modprobebin} $1 ${modargs}" debug "Waiting for module to get loaded.\n" unset modargs; unset needsarg counter=0 while [ "${counter}" -lt "6" ] do if ! module_loaded "$1"; then debug "Module \"%s\" still not live. Waiting a second.\n" "$1" sleep 1 fi if module_loaded "$1"; then debug "Module \"%s\" succesfully loaded.\n" "$1" unset counter return 0 fi counter=`expr ${counter} + 1`; counter=`echo ${counter}` done unset counter show_fmt_error "Failed to load module \"%s\".\n" "$1" return 1 } # Attempts to detach driver $1 from device $2 interface $3 # If failed to detach, attempts to completely unload $1 before failing. module_unbind() { [ "a$1" = "a" ] && return 99 verbose "Unloading driver %s" "$1" if [ "a$2" = "a" -a "a$3" = "a" ]; then debug "Requested to unbind module \"%s\" without device specified. Will try to unload it.\n" "$1" module_unload "$1" return $? fi moduleattached=`usb_loaded_driver "$2" "$3" | ${tailbin} -1 | ${grepbin} "$1" | ${wcbin} -l` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi moduleattached=`echo ${moduleattached}` if [ "a${moduleattached}" = "a" -o "a${moduleattached}" = "a0" ]; then debug "Module \"%s\" does not appear to be attached to device \"%s\".\n" "$1" "$2" unset moduleattached return 0 fi debug "Module \"%s\" is currently attached to \"%s\".\n" "$1" "$2" [ "a$3" != "a" ] && usb_sysfsdir_int "$2" "$3" && unbindvalue=`${basenamebin} ${sysfsintloc}` [ "a$3" = "a" ] && usb_sysfsdir && unbindvalue=`cd "${sysfsloc}"; ${lsbin} -1d \`${basenamebin} ${sysfsloc}\`*` [ "a${unbindvalue}" = "a" ] && unbindvalue=`echo "$2" | ${sedbin} -e "s/:/ /g"` sent=0 [ "a$1" = "ausb_storage" ] && localdrivername="usb-storage" for endpoint in /sys/bus/usb/drivers/${localdrivername}/unbind /sys/bus/usb/drivers/$1/unbind do for destination in ${unbindvalue} do if [ -w "${endpoint}" ]; then echo -n "${destination}" > "${endpoint}" 2> /dev/null debug "Sent \"%s\" to \"%s\".\n" "${destination}" "${endpoint}" sent=1 fi done unset destination done unset unbindvalue; unset endpoint; unset localdrivername if [ "${sent}" -eq "1" ]; then debug "Expecting module to detach from device.\n" while [ "${sent}" -lt "6" ] do unset moduleattached moduleattached=`usb_loaded_driver "$2" "$3" | ${tailbin} -1 | ${grepbin} "$1" | ${wcbin} -l` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED break fi moduleattached=`echo ${moduleattached}` if [ "a${moduleattached}" = "a" -o "a${moduleattached}" = "a0" ]; then debug "Module \"%s\" has detached from device \"%s\".\n" "$1" "$2" unset moduleattached; unset sent if find_binary "modprobe"; then if [ "a$1" != "ausb_storage" -a "a$1" != "ausb-storage" ]; then debug "Will attempt to also remove it.\n" debug run_command "${modprobebin} -r -v $1" module_loaded "$1" fi fi return 0 fi debug "Module still attached. Waiting for %d second(s).\n" "${sent}" sent=`expr ${sent} + 1`; sent=`echo ${sent}` sleep 1 done debug "Module \"%s\" did not detach from device \"%s\". Will try to unload it.\n" "$1" "$2" fi module_unload "$1" return $? } # Attempts to bind module $1 to device $2, interface $3 (optional) module_bind() { [ "a$1" = "a" -o "a$2" = "a" ] && return 99 verbose "Loading driver %s" "$1" module_load "$1" "$2" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} unset moduleattached modulename="$1" [ "a${modulename}" = "ausb-storage" ] && modulename="usb_storage" [ "a${modulename}" = "acdc-acm" ] && modulename="cdc_acm" moduleattached=`usb_loaded_driver "$2" "$3" | ${tailbin} -1 | ${grepbin} "${modulename}" | ${wcbin} -l` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi moduleattached=`echo ${moduleattached}` if [ "a${moduleattached}" != "a" -a "a${moduleattached}" != "a0" ]; then debug "Module \"%s\" attached to device \"%s\".\n" "$1" "$2" unset moduleattached; unset sent; unset modulename return 0 fi unset moduleattached debug "Module \"%s\" not yet attached to \"%s\".\n" "$1" "$2" bindvalue=`echo "$2" | ${sedbin} -e "s/:/ /g"` sent=0 for endpoint in /sys/module/${modulename}/drivers/usb-serial:*/new_id do if [ -w "${endpoint}" ]; then echo -n "${bindvalue}" > "${endpoint}" 2> /dev/null if [ "$?" -eq "0" ]; then debug "Sent \"%s\" to \"%s\".\n" "${bindvalue}" "${endpoint}" sent=1 fi fi done if [ "a${sent}" != "a1" ]; then for endpoint in /sys/module/${modulename}/drivers/usb:*/new_id do echo -n "${bindvalue}" > "${endpoint}" 2> /dev/null if [ "$?" -eq "0" ]; then debug "Sent \"%s\" to \"%s\".\n" "${bindvalue}" "${endpoint}" sent=1 fi done fi unset bindvalue; unset endpoint if [ "a${sent}" = "a1" ]; then counter=0 while [ "${counter}" -lt "10" ] do moduleattached=`usb_loaded_driver "$2" "$3" | ${tailbin} -1 | ${grepbin} "${modulename}" | ${wcbin} -l` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED break; fi moduleattached=`echo ${moduleattached}` if [ "a${moduleattached}" != "a1" ]; then debug "Waiting one second.\n" sleep 1 fi moduleattached=`usb_loaded_driver "$2" "$3" | ${tailbin} -1 | ${grepbin} "${modulename}" | ${wcbin} -l` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED break; fi moduleattached=`echo ${moduleattached}` if [ "a${moduleattached}" != "a" -a "a${moduleattached}" != "a0" ]; then debug "Module \"%s\" attached to device \"%s\".\n" "$1" "$2" unset moduleattached; unset sent; unset counter; unset modulename return 0 fi unset moduleattached counter=`expr ${counter} + 1`; counter=`echo ${counter}` done unset counter fi debug "Module \"%s\" did not bind to device \"%s\".\n" "$1" "$2" if [ "a$4" != "anoreload" ]; then debug "Will attempt to do a reload cycle.\n" if module_unload "$1" "$2" "$3"; then if module_bind "$1" "$2" "$3" "noreload"; then unset counter; unset sent; unset moduleattached; unset modulename debug "Reload cycle did the trick.\n" debug "Module \"%s\" attached to device \"%s\".\n" "$1" "$2" return 0 else return $? fi fi fi unset moduleattached; unset modulename if [ "${sent}" -eq "0" ]; then show_fmt_error "Module \"%s\" loaded but did not bind to device \"%s\".\n" "$1" "$2" else show_fmt_error "Module \"%s\" loaded but refused to bind to device \"%s\".\n" "$1" "$2" fi unset sent; unset counter return 1 return 99 } # Unlocks a previously acquired lock to hal hal_unlock() { [ "a${nohal}" != "a" ] && return 0 [ "a${HAL_LOCK}" = "a" ] && return 0 debug "Releasing HAL lock %d.\n" "${HAL_LOCK}" if notrunning "${HAL_LOCK}"; then debug "Already unlocked.\n" else if [ -f "/tmp/sakis3g.hal.lock.$$" ]; then ${rmbin} -f "/tmp/sakis3g.hal.lock.$$" sleep 2 fi if ! notrunning "${HAL_LOCK}"; then debug "Failed to unlock by unlinking mutex file. Will try to kill.\n" term_clearline ${killbin} -1 ${HAL_LOCK} 2> /dev/null if ! notrunning "${HAL_LOCK}"; then debug "Failed to kill PID %d.\n" "${HAL_LOCK}" return 1 fi fi debug "Unlocked.\n" fi unset HAL_LOCK return 0 } # Attempts to establish lock of interface $1 (i.e. org.freedesktop.Hal.Device.Storage) hal_acquire_lock() { [ "a${nohal}" != "a" ] && return 0 [ "a${HAL_LOCK}" != "a" ] && ! hal_unlock && return 1 ! find_binary "hal-lock" && return 1 ! find_binary "kill" && return 1 ! find_binary "touch" && return 1 ! we_are_root && return 1 debug "Acquiring lock in HAL for \"%s\".\n" "$1" ${touchbin} "/tmp/sakis3g.hal.lock.$$" hal-lock --interface "$1" --exclusive --run "${ME} holdlock /tmp/sakis3g.hal.lock.$$" & halpid=$!; unset informed while ! notrunning ${halpid} do hallocksuccess=`${catbin} "/tmp/sakis3g.hal.lock.$$" 2> /dev/null`; hallocksuccess=`echo ${hallocksuccess} | ${sedbin} -e "s/ //g"` if [ "a${hallocksuccess}" = "a" ]; then unset hallocksuccess [ "a${informed}" = "a" ] && verbose "Acquiring exclusive lock to HAL" informed=`expr ${informed} + 1`; informed=`echo ${informed}` if [ "${informed}" -le "20" ]; then debug "Waiting for spawned process to acquire lock (%d secs will have passed).\n" "${informed}" sleep 1 else debug "Giving up waiting for lock to occur. Will try to terminate current lock attempt.\n" export HAL_LOCK=${halpid} hal_unlock; unset HAL_LOCK break fi else debug "Exclusive lock granted to PID %d.\n" "${hallocksuccess}" break; fi done if [ "a${hallocksuccess}" != "a" ]; then export HAL_LOCK=${halpid} addexittrap hal_unlock debug "Succesfully locked HAL interface \"%s\" (hal-lock itself running with PID %d).\n" "$1" "${HAL_LOCK}" unset halpid; unset informed; unset hallocksuccess return 0 fi unset halpid; unset informed; unset hallocksuccess debug "Failed to acquire exclusive lock to %s.\n" "$1" return 1 } # Makes sure that only one instance of $3 is contained within # list $2 of hal udi $1. hal_add_to_list() { ! find_binary "hal-get-property" && return 1 ! find_binary "hal-set-property" && return 1 [ "$#" -ne "3" ] && return 1 halfound=0 while [ "${halfound}" -ne "1" ]; do contents=`hal-get-property --udi "$1" --key "$2" 2> /dev/null` halfound=0 for op in ${contents} do if [ "a${op}" = "a$3" ]; then halfound=`expr ${halfound} + 1` halfound=`echo ${halfound}` fi done if [ "${halfound}" -eq "0" ]; then debug "Will attempt to add \"%s\" inside \"%s\".\n" "$3" "$2" hal-set-property --udi "$1" --key "$2" --strlist-post "$3" 2> /dev/null elif [ "${halfound}" -gt "1" ]; then debug "Will attempt to remove multiple instance of \"%s\" inside \"%s\".\n" "$3" "$2" hal-set-property --udi "$1" --key "$2" --strlist-rem "$3" 2> /dev/null fi hala=$? if [ "a${hala}" != "a0" ]; then debug "Unable to properly modify HAL.\n" break fi done [ "${halfound}" -eq "1" ] && debug "HAL is updated.\n" unset contents; unset op; unset hala if [ "a${halfound}" = "a1" ]; then unset halfound return 0 fi unset halfound return 1 } # Makes sure modem $1 capabilities are loaded on hal hal_tty_update() { [ "a${nohal}" != "a" ] && return 0 [ "a${nohalinform}" != "a" ] && return 0 ! find_binary "hal-get-property" && return 1 ! find_binary "hal-set-property" && return 1 ! find_binary "hal-find-by-property" && return 1 unset halcapabilities case "a${TTY_CAPABILITIES}" in aGSM) halcapabilities="GSM-07.07 GSM-07.05" ;; a) debug "No capabilities found. Don't know what to tell to HAL.\n" ;; *) debug "FIX ME: Unknown capabilities %s. Don't know what to tell to HAL.\n" "${TTY_CAPABILITIES}" ;; esac [ "a${halcapabilities}" = "a" ] && unset halcapabilities && return 1 debug "Capabilities of %s are: %s\n" "$1" "${halcapabilities}" haludi=`hal-find-by-property --key "linux.device_file" --string "$1" 2> /dev/null | ${tailbin} -1` if [ "a${haludi}" = "a" ]; then unset haludi; unset halcapabilities debug "No HAL device referring to %s was found.\n" "$1" return 1 fi debug "Found device in HAL: %s\n" "${haludi}" verbose "Updating HAL" hal_add_to_list "${haludi}" info.capabilities "modem" for cap in ${halcapabilities} do hal_add_to_list "${haludi}" modem.command_sets "${cap}" done debug "HAL was updated that %s is a modem.\n" "$1" find_binary "hal-device" && debug run_command "hal-device \"${haludi}\"" unset cap; unset halcapabilities; unset haludi return 0 } # If $1 node does not exist, creates it with major $2 and minor $3 dev_create_node() { [ "a$1" = "a" -o "a$2" = "a" -o "a$3" = "a" ] && return 99 if [ ! -c "$1" ]; then debug "Device node \"%s\" does not exist.\n" "$1" if ! find_binary "mknod"; then show_fmt_error "Unable to create device node \"%s\"." "$1" return 1 fi debug run_command "${mknodbin} \"$1\" c $2 $3" if [ ! -c "$1" ]; then show_fmt_error "Failed to create device node \"%s\"." "$1" return 1 fi debug "Made node \"%s (%d,%d)\" ourselves.\n" "$1" "$2" "$3" return 0 else debug "Device node \"%s\" already exists.\n" "$1" return 0 fi } pin_valid() { [ "a$1" = "a" ] && return 1 need_binary "expr" givenpin=`echo $1` mathpin=`${exprbin} 1${givenpin} + 1 - 1 2> /dev/null`; mathpin=`echo ${mathpin}` if [ "a${mathpin}" = "a1${givenpin}" ]; then if [ "1${givenpin}" -ge "10000" -a "1${givenpin}" -le "19999" ]; then debug "Valid PIN %s.\n" "$1" return 0 fi fi debug "Invalid PIN %s.\n" "$1" return 1 } pin_prompt() { user_prompt "SIM_PIN" "Modem needs PIN" "Please enter PIN number, or leave empty to abort" "OK" "Cancel" case "a${SIM_PIN}" in a) debug "User did not provide PIN.\n" unset SIM_PIN return 98 ;; *) if ! pin_valid "${SIM_PIN}"; then debug "PIN supplied by user was not a valid PIN number (%s).\n" "${SIM_PIN}" unset SIM_PIN pin_prompt ret=$? fi export SIM_PIN return 0 ;; esac } # Makes sure tty $1 is not busy tty_not_busy() { [ "a$1" = "a" ] && return 1 [ ! -c "$1" ] && return 1 if we_are_root; then ttyusers=`${lsbin} -l /proc/*/fd/* 2> /dev/null | ${grepbin} "${1}$" | ${sedbin} -e "s/\(.*\)\/proc\/\([0-9][0-9]*\)\/fd\/\(.*\)/\2/g" | ${sortbin} | ${uniqbin} | ${wcbin} -l` ; ttyusers=`echo ${ttyusers}` if [ "a${ttyusers}" = "a0" ]; then unset ttyusers debug "Device %s is not busy.\n" "$1" [ "a$2" != "a" ] && verbose "Resuming" return 0 fi debug "Device %s is currently occupied by %d process(es).\n" "$1" "${users}" ttyusers=`${lsbin} -l /proc/*/fd/* 2> /dev/null | ${grepbin} "${1}$" | ${sedbin} -e "s/\(.*\)\/proc\/\([0-9][0-9]*\)\/fd\/\(.*\)/\2/g" | ${sortbin} | ${uniqbin}` ; ttyusers=`echo ${ttyusers}` debug "PID(s) are: %s\n" "${ttyusers}" for ttyp in ${ttyusers} do debug run_command "${psbin} -p ${ttyp} -o pid,comm= | ${tailbin} -1" ttyusers="${ttyusers} `${psbin} -p ${ttyp} -o comm= 2> /dev/null`" done unset ttyp if [ "a$2" = "a" ]; then debug "Will wait for 10 seconds in case port is freed.\n" verbose "Waiting %s to be released by PID %s." "$1" "${ttyusers}" ttycount=11 else ttycount=$2 fi ttycount=`expr ${ttycount} - 1` if [ "a${ttycount}" = "a0" ]; then show_fmt_error "Port %s is currently occupied by %s." "$1" "${ttyusers}" unset ttyusers; unset ttycount; return 1 else debug "Wait for another %d seconds in case port %s is freed.\n" "${ttycount}" "$1" sleep 1 if tty_not_busy $1 $ttycount; then unset ttyusers; unset ttycount; return 0 else unset ttyusers; unset ttycount; return 1 fi fi unset ttyusers; unset ttycount; else show_fmt_error "Unable to check if %s is occupied. Not root." "$1" fi return 1 } at_default_commands() { unset ttycommands [ "a$1" = "a" ] && return 1 case "a$1" in aPROBEGSM) ttycommands="ATI OK 'AT+GCAP' OK 'AT+CGSN' OK" ;; aIDENTIFY) ttycommands="AT+CGMM OK" ;; aSTAGE0) if [ "a${INIT_STAGE0}" != "a" ]; then ttycommands="${INIT_STAGE0}" fi ;; aSTAGE1) if [ "a${INIT_STAGE1}" != "a" ]; then ttycommands="${INIT_STAGE1}" fi ;; aPINCHECK) if [ "a${INIT_STAGE2}" != "a" ]; then ttycommands="${INIT_STAGE2}" debug "Using instructed PINCHECK.\n" else ttycommands="'AT+CPIN?' OK" debug "Using default PINCHECK.\n" fi ;; aPINSUPPLY) if pin_valid "${2}"; then if [ "a${INIT_STAGE3}" != "a" ]; then ttycommands=`${printfbin} "${INIT_STAGE3}\n" "${2}"` debug "Using instructed PINSUPPLY.\n" else ttycommands=`${printfbin} "'AT+CPIN=\"%s\"' OK\n" "${2}"` debug "Using default PINSUPPLY.\n" fi fi ;; aSTAGE4) if [ "a${INIT_STAGE4}" != "a" ]; then ttycommands="${INIT_STAGE4}" fi ;; aOPERATOR) ttycommands="AT+COPS=3,2 OK 'AT+COPS?' OK" ;; aOPERATORS) ttycommands="AT+COPS=3,2 OK 'AT+COPS=?' TIMEOUT 120 OK" ;; aOPERATORNAME) ttycommands="AT+COPS=3,0 OK 'AT+COPS?' OK" ;; aSIMOPERATORNAME) ttycommands="'AT+CRSM=176,28486,0,0,17' OK" ;; aSETOPERATOR) ttycommands=`${printfbin} "'AT+COPS=1,2,\"%s\"' OK\n" "${2}"` ;; aSTAGE5) if [ "a${INIT_STAGE5}" != "a" ]; then ttycommands="${INIT_STAGE5}" fi ;; aDETECTAPN) ttycommands="AT+CGDCONT? OK" ;; aINITIALIZE) if [ "a${APN}" != "a" ]; then apnpart=`echo "${APN}" | ${cutbin} -d: -f1` [ "a${apnpart}" = "aCUSTOM_APN" ] && apnpart="${CUSTOM_APN}" if [ "a${INIT_STAGE6}" != "a" ]; then ttycommands=`${printfbin} "${INIT_STAGE6}\n" "${apnpart}"` debug "Using instructed INITIALIZE.\n" else ttycommands=`${printfbin} "ATZ OK 'AT&F' OK 'ATQ0 V1 E1' OK 'AT&D2 &C1' OK AT+FCLASS=0 OK ATS0=0 OK 'AT+CGDCONT=1,\"IP\",\"%s\"' OK\n" "${apnpart}"` debug "Using default INITIALIZE.\n" fi unset apnpart fi ;; aSTAGE7) if [ "a${INIT_STAGE7}" != "a" ]; then ttycommands="${INIT_STAGE7}" fi ;; aSTAGE8) if [ "a${INIT_STAGE8}" != "a" ]; then ttycommands="${INIT_STAGE8}" fi ;; aDIAL) dialphone="${ISP_DIAL}" [ "a${dialphone}" = "a" ] && dialphone="*99#" ttycommands=`${printfbin} "ATD%s\n" "${dialphone}"` unset dialphone ;; esac [ "a${ttycommands}" != "a" ] && debug "Command \"%s\" refers to AT commands: %s\n" "$1" "${ttycommands}" && return 0 debug "Unknown command \"%s\".\n" "$1" return 1 } # Send command $2 to tty $1 tty_send_command() { unset LASTTTYLOG [ "a$1" = "a" -o "a$2" = "a" ] && return 99 if [ ! -c "$1" ]; then debug "Device node %s did not exist while trying \"%s\" command.\n" "$1" "$2" if [ "a${informedspurious}" != "a1" ] && [ "a${usbdevice}" != "a" ] && usb_device_connected "${usbdevice}" && usb_has_storage "$1" && [ "a${killstorage}" = "a" ]; then show_fmt_error "Spurious changes in tty %s. Consider using \"killstorage\" switch in case it improves stability." "$1" export informedspurious=1 fi if [ "a${informedspurious}" != "a1" ]; then show_fmt_error "Spurious changes in tty %s. Problem may be solved by upgrading your kernel or by choosing another driver." "$1" export informedspurious=1 fi [ ! -c "$1" ] && debug "Waiting one second in case it appears.\n" && sleep 1 [ ! -c "$1" ] && debug "Device still missing. Aborting.\n" && return 1 debug "Device %s appeared. Will proceed sending %s commands.\n" "$1" "$2" fi ! find_binary "chat" && return 4 need_arg "CHAT_ABORT_STRINGS" ! at_default_commands "$2" "$3" && return 1 ttycommands="\"\" '\pAT' OK ${ttycommands} '\pAT' OK" debug "Will send %s commands to tty %s: %s\n" "$2" "$1" "${ttycommands}" ! tty_not_busy "$1" && return 1 timestamp_before=`${lsbin} --full-time -G1 $1 2> /dev/null`; timestamp_before=`echo ${timestamp_before}` sh -c "${chatbin} -t 2 -e ${CHAT_ABORT_STRINGS} ${ttycommands} >> ${1} < ${1} 2> /tmp/sakis3g.chat.$$.log" timestamp_after=`${lsbin} --full-time -G1 $1 2> /dev/null`; timestamp_before=`echo ${timestamp_after}` if [ "a${timestamp_before}" != "a${timestamp_after}" ]; then debug "Spurious changes in tty %s.\n" "$1" if [ "a${usbdevice}" != "a" ] && usb_device_connected "${usbdevice}" && usb_has_storage "$1" && [ "a${killstorage}" = "a" ] && [ "a${informedspurious}" != "a1" ]; then show_fmt_error "Spurious changes in tty %s. Consider using \"killstorage\" switch in case it improves stability." "$1" export informedspurious=1 fi if [ "a${informedspurious}" != "a1" ]; then show_fmt_error "Spurious changes in tty %s. Problem may be solved by upgrading your kernel or by choosing another driver." "$1" export informedspurious=1 fi fi unset ttycommands if [ -f "/tmp/sakis3g.chat.$$.log" ]; then LASTTTYLOG=`${catbin} "/tmp/sakis3g.chat.$$.log"` debug "Got response from tty:\n%s\n" "${LASTTTYLOG}" rm -f "/tmp/sakis3g.chat.$$.log" return 0 else debug "No response from tty %s.\n" "$1" return 1 fi } # Finds capabilities of tty $1 and sets TTY_CAPABILITIES variable tty_get_caps() { unset TTY_CAPABILITIES [ "a$1" = "a" ] && return 1 ! tty_send_command "$1" "PROBEGSM" && return 1 gsmfound=`echo "${LASTTTYLOG}" | ${grepbin} "+CGSM" | wc -l`; gsmfound=`echo ${gsmfound}` if [ "a${gsmfound}" = "a0" ]; then debug "No GSM capabilities were advertised.\n" gsmfound=`echo "${LASTTTYLOG}" | ${grepbin} "^\([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\)$" | wc -l` ; gsmfound=`echo ${gsmfound}` if [ "a${gsmfound}" = "a1" ]; then debug "However, IMEI information was provided. Will consider it GSM capable.\n" fi fi [ "a${gsmfound}" = "a0" -o "a${gsmfound}" = "a" ] && [ "a${NOPROBEGSM}" != "a" ] && debug "Forced by user to consider tty %s GSM capable.\n" "$1" && gsmfound=1 if [ "a${gsmfound}" != "a0" ]; then export TTY_CAPABILITIES="GSM" debug "Found GSM capabilities on tty %s.\n" "$1" return 0 fi # TODO: Implement support for non GSM devices. debug "Device did not report GSM capabilities.\n" if [ "a$2" != "anoretry" ]; then debug "Will check one more time.\n" tty_get_caps "$1" "noretry" return $? fi show_fmt_error "Device did not report GSM capabilities. You can skip this by adding --noprobe command line switch.\n" return 1 } # Sets MODEM_VARIANT, if possible, for tty $1 tty_identify() { unset MODEM_VARIANT [ "a$1" = "a" ] && return 1 ! tty_send_command "$1" "IDENTIFY" && return 1 MODEM_VARIANT=`echo "${LASTTTYLOG}" | ${grepbin} -v "^AT" | ${sedbin} -e "s/AT//g" | ${sedbin} -e "s/OK//g" | ${sedbin} -e "s/ERROR//g" | ${trbin} "\n" " " | ${trbin} "\t" " " | ${sedbin} -e "s/ */ /g" | ${sedbin} -e "s/^ *//g" | ${sedbin} -e "s/ *$//g"` MODEM_VARIANT=`echo ${MODEM_VARIANT}` if [ "a${MODEM_VARIANT}" = "a" ]; then debug "Modem did not report a name.\n" unset MODEM_VARIANT else debug "Modem on tty identified itself as: %s\n" "${MODEM_VARIANT}" base_modem "${usbdevice}" "${MODEM_VARIANT}" fi return 0 } # Checks if tty $1 needs PIN. tty_needspin() { unset pinrequirement [ "a$1" = "a" ] && return 1 ! tty_send_command "$1" "PINCHECK" && return 1 pinrequirement=`echo "${LASTTTYLOG}" | ${grepbin} "ERROR"` [ "a${pinrequirement}" != "a" ] && pinrequirement="ERROR" [ "a${pinrequirement}" = "a" ] && pinrequirement=`echo "${LASTTTYLOG}" | ${grepbin} "^.CPIN: " | ${cutbin} -d\ -f2-` [ "a${pinrequirement}" = "a" ] && pinrequirement="ERROR" [ "a${pinrequirement}" = "aREADY" ] && debug "Modem on %s does not need PIN.\n" "$1" && return 1 [ "a${pinrequirement}" = "aSIM PIN" ] && debug "Modem on %s needs PIN.\n" "$1" && return 0 debug "Got \"%s\" while checking modem on %s for PIN requirement.\n" "${pinrequirement}" "$1" return 0 } # Unlocks tty $1 from PIN. tty_pin_unlock() { [ "a$1" = "a" ] && return 1 ! tty_needspin "$1" && unset pinrequirement && return 0 if [ "a${pinrequirement}" = "a" ]; then show_fmt_error "Failed to get valid response from modem while checking for PIN." unset pinrequirement return 1 elif [ "a${pinrequirement}" != "aSIM PIN" ]; then show_fmt_error "Modem responded \"%s\" while checking for PIN." "${pinrequirement}" unset pinrequirement return 1 fi unset pinrequirement if ! pin_valid "${SIM_PIN}"; then unset SIM_PIN ! pin_prompt && return 98 ! pin_valid "${SIM_PIN}" && return 1 fi verbose "Sending PIN" ! tty_send_command "$1" "PINSUPPLY" "${SIM_PIN}" && return 1 debug "PIN sent to %s. Waiting 3 seconds before checking success.\n" "$1" sleep 3 if ! tty_needspin "$1"; then unset pinrequirement debug "SIM is now READY.\n" return 0 fi unset SIM_PIN stop_fmt_error 12 "WRONG PIN. Aborting to prevent you from locking your SIM card." return 1 } tty_detect_apn() { unset MODEM_APN [ "a${MODEM_TTY}" = "a" ] && return 1 ! tty_send_command "${MODEM_TTY}" "DETECTAPN" && return 1 MODEM_APN=`echo "${LASTTTYLOG}" | ${grepbin} "^+CGDCONT" | ${sedbin} -e "s/^\(.*\)IP\",\"\(.*\)\",\"\(.*\)$/\2/g" | ${grepbin} -v "^+CGDCONT"` export MODEM_APN debug "APN stored in modem was: %s\n" "${MODEM_APN}" [ "a${MODEM_APN}" = "a" ] && unset MODEM_APN && return 1 return 0 } tty_sim_provider_name() { unset ISPSIMNAME [ "a$1" = "a" ] && return 1 if tty_send_command "$1" "SIMOPERATORNAME"; then ISPSIMNAME=`echo "${LASTTTYLOG}" | ${grepbin} "^+CRSM:\( *\)144," | ${sedbin} -e "s/^.CRSM:\( *\)144,\(.*\),\"\(.*\)\"\(.*\)$/ISPSIMNAME=\3/g" | ${grepbin} "^ISPSIMNAME=" | ${cutbin} -d= -f2-` [ "a${ISPSIMNAME}" = "a" ] && unset ISPSIMNAME && return 1 ISPSIMNAME=`${printfbin} "\`echo "${ISPSIMNAME}" | ${sedbin} -e "s/\([0-9A-Fa-f][0-9A-Fa-f]\)/\\\\\\\\\\x\1/g" | ${sedbin} -e "s/\\\\\\\\\\xFF//g" | ${sedbin} -e "s/\\\\\\\\\\x01//g" | ${sedbin} -e "s/\\\\\\\\\\x02//g"\`\n"` ISPSIMNAME=`echo ${ISPSIMNAME}` [ "a${ISPSIMNAME}" = "a" ] && unset ISPSIMNAME && return 1 debug "SIM contains \"service provider\" name: %s\n" "${ISPSIMNAME}" export ISPSIMNAME return 0 fi return 1 } tty_select_network() { unset FORCE_ISP verbose "Scanning networks" ! tty_send_command "$1" "OPERATORS" && return 1 networks=`echo "${LASTTTYLOG}" | ${grepbin} "^+COPS:" | ${cutbin} -d: -f2- -s | ${sedbin} -e "s/(/\\\n(/g" | ${sedbin} -e "s/)/)\\\n/g" | ${grepbin} "^([1-3],\"\(.*\)\",\"\(.*\)\",\"\([0-9][0-9]*\)\",0)$" | ${sedbin} -e "s/^(1,/(Allowed,/g" | ${sedbin} -e "s/^(2,/(Current,/g" | ${sedbin} -e "s/^(3,/(Forbidden,/g" | ${sedbin} -e "s/^(\(.*\),\"\(.*\)\",\"\(.*\)\",\"\([0-9][0-9]*\)\",0)$/\"\4\" \"\2 (\1\)\" /g"` eval user_select \"FORCE_ISP\" \"Please select a network\" \"Select network for modem to register.\" \"Select\" \"Cancel\" ${networks} # in case "$?" in 0) unset FORCE_ISP; unset networks return 98 ;; 98) unset FORCE_ISP; unset networks return 98 ;; 99) unset FORCE_ISP; unset networks return 99 ;; *) case "a${FORCE_ISP}" in a) unset FORCE_ISP; unset networks return 98 ;; *) debug "User selected %s.\n" "${FORCE_ISP}" return 0 ;; esac ;; esac return 1 } tty_registered_network() { unset ISPID; unset ISPNAME; unset ISPTEXT [ "a$1" = "a" ] && return 1 ! tty_send_command "$1" "OPERATOR" && return 1 ISPID=`echo "${LASTTTYLOG}" | ${grepbin} "^+COPS:" | ${cutbin} -d\" -f2`; ISPID=`echo ${ISPID}` if [ "a${ISPID}" = "a+COPS: 0" -o "a${ISPID}" = "a" ]; then debug "Modem not registered to a network yet.\n" unset ISPID return 1 fi debug "Modem registered to network ID \"%s\".\n" "${ISPID}" if [ -n "${FORCE_ISP}" ]; then if [ "a${ISPID}" != "a${FORCE_ISP}" ]; then debug "FORCE_ISP variable instructs to use \"%s\" instead.\n" "${FORCE_ISP}" fi debug "Will attempt to manually set %s and prevent roaming.\n" "${FORCE_ISP}" ! tty_send_command "$1" "SETOPERATOR" "${FORCE_ISP}" if [ "a$2" != "aFORCE_ISP" ]; then tty_registered_network "$1" "FORCE_ISP" else if [ "a${ISPID}" != "a" ]; then show_fmt_error "Modem refused to register operator \"%s\" (currently registered to \"%s\").\n" "${FORCE_ISP}" "${ISPID}" else show_fmt_error "Modem refused to register operator \"%s\".\n" "${FORCE_ISP}" fi unset ISPID return 1 fi unset ISPID return $? fi export ISPID if tty_send_command "$1" "OPERATORNAME"; then ISPNAME=`echo "${LASTTTYLOG}" | ${grepbin} "^+COPS:" | ${sedbin} -e "s/^.COPS: 0,0,\"\(.*\)\"\(.*\)$/ISPNAME=\1/g" | ${grepbin} "^ISPNAME=" | ${cutbin} -d= -f2-` if tty_sim_provider_name "$1" && [ "a${ISPSIMNAME}" != "a" -a "a${ISPSIMNAME}" != "a${ISPNAME}" ]; then debug "SIM card instructs to use \"%s\" as service provider name, instead of \"%s\".\n" "${ISPSIMNAME}" "${ISPNAME}" ISPNAME="${ISPSIMNAME}" fi # Some modems return numeric ID, even if instructed to display name. [ "a${ISPNAME}" = "a${ISPID}" ] && unset ISPNAME # Some SIMs incorrectly confuse modem to display FFs as service provider name. [ "a`echo ${ISPNAME} | ${cutbin} -b1-8`" = "aFFFFFFFF" ] && unset ISPNAME # Huawei E160 does not correctly report operator name. # This is not true. Was a SIM issue. This is not true. #[ "a${MODEM_VARIANT}" = "aE160" ] && unset ISPNAME export ISPNAME [ "a${ISPNAME}" = "a" ] && net_info "${ISPID}" [ "a${ISPNAME}" = "a" ] && unset ISPNAME fi export ISPTEXT="${ISPID}" [ "a${ISPNAME}" != "a" ] && export ISPTEXT="${ISPNAME}" return 0 } tty_register_network() { [ "a$1" = "a" ] && return 1 wat=0 if [ -n "${FORCE_ISP}" ]; then debug "FORCE_ISP variable instructs to enter network \"%s\".\n" "${FORCE_ISP}" debug "Will attempt to manually set %s and prevent roaming.\n" "${FORCE_ISP}" ! tty_send_command "$1" "SETOPERATOR" "${FORCE_ISP}" fi while ! tty_registered_network $1; do if [ "${wat}" -gt "20" ]; then debug "Giving up after %d seconds have passed.\n" "${wat}" break else wat=`expr ${wat} + 4` wat=`echo ${wat}` fi debug "Waiting modem to register network (%d seconds).\n" "${wat}" verbose "Registering network" sleep 4 done unset wat if [ "a${ISPID}" = "a" ]; then show_fmt_error "Modem unable to register a network." unset ISPID if user_confirm "scan" "Scan for network" "Modem was unable to register a network. Would you like to manually select a network?" "Yes" "No" "reset"; then if tty_select_network "$@"; then tty_register_network "$@" return $? fi fi return 13 else debug "Modem on %s has registered %s.\n" "$1" "${ISPID}" return 0 fi } # Makes sure tty $1 is ready for connection to be established. tty_prepare() { check_com_software ret=$?; [ "${ret}" -ne "0" ] && return ${ret} [ "a$1" = "a" ] && return 1 verbose "Preparing modem" tty_send_command "$1" "STAGE0" ! tty_get_caps "$@" && return 1 ! tty_identify "$@" && return 1 tty_send_command "$1" "STAGE1" ! tty_pin_unlock "$@" && return 1 tty_send_command "$1" "STAGE4" tty_register_network "$@"; ret=$?; [ "${ret}" -ne "0" ] && return ${ret} tty_send_command "$1" "STAGE5" hal_tty_update "$@" debug "Modem on device node %s is now ready for connection.\n" "$1" return 0 } # Attempts to get connected USB devices, exiting if it fails. usb_connected_devices() { unset usb_devices need_binary "sort"; need_binary "uniq"; need_binary "sed" if [ -r "/proc/bus/usb/devices" ]; then debug "Fetching connected USB devices by using \"%s\".\n" "/proc/bus/usb/devices" usb_devices=`safe_cat "/proc/bus/usb/devices" | ${grepbin} -A 4 "^P:" | ${sedbin} -e "s/^\(.*\)Ven\(.*\)=\(....\) Pro\(.*\)=\(....\) \(.*\)$/\3:\5:/g" | ${sedbin} -e "s/^S:\(.*\)Pro\(.*\)=\(.*\)$/\3/g" | ${sedbin} -e "s/^.:\(.*\)$//g" | ${grepbin} -v "^$"` usb_devices=`echo ${usb_devices} | ${sedbin} -e "s/: */:/g" | ${sedbin} -e "s/ -- /\\\n/g" | ${sortbin} | ${uniqbin} | ${grepbin} -v "HCI Host Controller"` elif [ -d "/sys/bus/usb/devices" ]; then debug "Fetching connected USB devices by using \"%s\".\n" "/sys/bus/usb/devices" usb_devices=`cd /sys/bus/usb/devices/; ${grepbin} . */idProduct */idVendor */product */uevent | ${sortbin} | ${sedbin} -e "s/idProduct:\(.*\)$/idProduct:\1:/g" | ${sedbin} -e "s/idVendor:\(.*\)$/idVendor:\1:/g" | ${grepbin} -A 2 "idProduct" | ${sedbin} -e "s/^\(.*\):\(..*\):*$/\2/g"` usb_devices=`echo ${usb_devices} | ${sedbin} -e "s/: */:/g" | ${sedbin} -e "s/ -- /\\\n/g" | ${sortbin} | ${uniqbin} | ${sedbin} -e "s/^\(....\):\(....\):/\2:\1:/g" | ${sortbin} | ${uniqbin} | ${grepbin} -v "HCI Host Controller"` elif find_binary "lsusb"; then debug "Fetching connected USB devices by using \"%s\".\n" "${lsusbbin}" usb_devices=`safe_lsusb | ${sedbin} -e "s/\(.*\)ID \(....\):\(....\) \(.*\)$/\2:\3:\4/g" | ${sortbin} | ${uniqbin} | ${grepbin} -v "root hub"` else stop_fmt_error 7 "Unable to discover connected USB devices. Script will now abort." fi if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi debug "Connected USB devices are:\n%s\n" "${usb_devices}" return 0 } # Helper method. Prints equivalent of usb_devices only for those devices in $1 usb_device_list() { for condevice in $@ do echo "${usb_devices}" | ${grepbin} "^${condevice}:" done } # Does scoring things to determine if which usb device looks like a sure candidate for being a modem. # On success, returns 0 and sets usb_modems. # On failure, returns 1 voodoo_connected_modems() { unset usb_modems need_binary "uname" debug "Voodoo mode employed to discover a possible modem.\n" debug "Attempting to enumerate interfaces.\n" uevents=`cd /sys/bus/usb/devices; ${grepbin} . [0-9]*/uevent 2> /dev/null` interfaces=`echo "${uevents}" | ${cutbin} -d/ -f1 -s | ${grepbin} ":" | ${sortbin} | ${uniqbin}` ; interfaces=`echo ${interfaces}` debug "uevent contents are:\n%s\n" "${uevents}" debug "Interfaces are:\n%s\n" "${interfaces}" unset orphaninterfaces; unset storageinterfaces; unset communicationdevices; unset suspectdevices; unset serialinterfaces; unset interruptinterfaces for intstr in ${interfaces} do intclass=`echo "${uevents}" | ${grepbin} "^${intstr}\/" | ${grepbin} "uevent:INTERFACE=" | ${cutbin} -d= -f2 -s | ${cutbin} -d/ -f1` [ "a${intclass}" = "a9" ] && continue intdriver=`echo "${uevents}" | ${grepbin} "^${intstr}\/" | ${grepbin} "uevent:DRIVER=" | ${cutbin} -d= -f2 -s | ${sedbin} -e "s/-/_/g"` intserial=0; [ "a${intdriver}" != "a" ] && intserial=`usb_serial_drivers ${intdriver} 2> /dev/null | ${wcbin} -w`; intserial=`echo ${intserial}` intpoint=`cd /sys/bus/usb/devices; ${grepbin} . ${intstr}/ep_*/type 2> /dev/null | ${grepbin} -i "interrupt$" | ${wcbin} -l`; intpoint=`echo ${intpoint}` intdevice=`echo "${intstr}" | ${cutbin} -d: -f1 -s` intvendor=`${catbin} /sys/bus/usb/devices/${intdevice}/idVendor 2> /dev/null` intmodemmaker=`${grepbin} -i "usb:v${intvendor}" /lib/modules/\`${unamebin} -r\`/modules.alias 2> /dev/null | ${cutbin} -d\ -f3 -s | ${sortbin} | ${uniqbin}` intmodemmaker=`usb_serial_drivers ${intmodemmaker} 2> /dev/null` intbrothers=`echo "${interfaces}" | ${trbin} " " "\n" | ${sedbin} -e "s/^\( *\)//g" | ${grepbin} "^${intdevice}:" | ${wcbin} -l`; intbrothers=`echo ${intbrothers}` if [ "a${intdriver}" = "a" ]; then orphaninterfaces="${orphaninterfaces} ${intstr} ${intstr} ${intstr}" debug "Added interface %s to orphan interfaces.\n" "${intstr}" fi if [ "a${intpoint}" = "a1" ]; then interruptinterfaces="${interruptinterfaces} ${intstr} ${intstr} ${intstr}" debug "Added interface %s to interrupt interfaces.\n" "${intstr}" fi if [ "a${intdriver}" = "ausb-storage" -o "a${intdriver}" = "ausb_storage" -o "a${intclass}" = "a8" ]; then storageinterfaces="${storageinterfaces} ${intstr} ${intstr} ${intstr} ${intstr}" debug "Added interface %s to storage interfaces.\n" "${intstr}" if [ "a${intbrothers}" = "a1" ]; then storageinterfaces="${storageinterfaces} ${intstr} ${intstr}" debug "+2 for being unique interface of device %s.\n" "${intdevice}" fi if [ "a${intbrothers}" = "a1" ] && [ "a${intmodemmaker}" != "a" ]; then storageinterfaces="${storageinterfaces} ${intstr} ${intstr} ${intstr}" debug "+3 for vendor %s being a modem maker.\n" "${intvendor}" fi fi if [ "a${intclass}" = "a2" ]; then communicationdevices="${communicationdevices} ${intstr} ${intstr}" debug "Added interface %s to communication interfaces.\n" "${intstr}" fi if [ "a${intclass}" = "a255" -o "a${intclass}" = "a224" ]; then suspectdevices="${suspectdevices} ${intstr}" debug "Added interface %s to suspect interfaces.\n" "${intstr}" fi if [ "a${intserial}" = "a1" ]; then serialinterfaces="${serialinterfaces} ${intstr} ${intstr} ${intstr} ${intstr} ${intstr}" debug "Added interface %s to serial interfaces.\n" "${intstr}" fi done unset interfaces; unset uevents unset intstr; unset intclass; unset intdriver; unset intserial; unset intpoint; unset intdevice; unset intvendor; unset intmodemmaker; unset intbrothers devicescore=`echo ${serialinterfaces} ${suspectdevices} ${communicationdevices} ${storageinterfaces} ${orphaninterfaces} ${interruptinterfaces} | ${trbin} " " "\n" | ${sedbin} -e "s/ //g" | ${grepbin} -v "^$" | ${cutbin} -d: -f1 -s | ${sortbin} | ${uniqbin} -c | ${sedbin} -e "s/^\( *\)//g" | ${sedbin} -e "s/\( *\)/ /g" | ${sedbin} -e "s/^\([0-9]\) /0\1 /g" | ${sedbin} -e "s/^\([0-9][0-9]\) /0\1 /g" | ${sedbin} -e "s/^\([0-9][0-9][0-9]\) /0\1 /g" | ${sortbin} -r` interfacescore=`echo ${serialinterfaces} ${suspectdevices} ${communicationdevices} ${storageinterfaces} ${orphaninterfaces} ${interruptinterfaces} | ${trbin} " " "\n" | ${sedbin} -e "s/ //g" | ${grepbin} -v "^$" | ${sortbin} | ${uniqbin} -c | ${sedbin} -e "s/^\( *\)//g" | ${sedbin} -e "s/\( *\)/ /g" | ${sedbin} -e "s/^\([0-9]\) /0\1 /g" | ${sedbin} -e "s/^\([0-9][0-9]\) /0\1 /g" | ${sedbin} -e "s/^\([0-9][0-9][0-9]\) /0\1 /g" | ${sortbin} -r` unset serialinterfaces; unset suspectdevices; unset communicationdevices; unset storageinterfaces; unset orphaninterfaces; unset interruptinterfaces; debug "Device score is:\n%s\n" "${devicescore}" debug "Interface score is:\n%s\n" "${interfacescore}" besttwo=`echo "${interfacescore}" | ${headbin} -2 | ${cutbin} -d\ -f2 -s | ${cutbin} -d: -f1 -s | ${uniqbin}` besttwocount=`echo "${besttwo}" | ${wcbin} -w`; besttwocount=`echo ${besttwocount}` if [ "a${besttwocount}" != "a" ] && [ "${besttwocount}" -eq "1" ]; then intvendor=`${catbin} /sys/bus/usb/devices/${besttwo}/idVendor 2> /dev/null` intproduct=`${catbin} /sys/bus/usb/devices/${besttwo}/idProduct 2> /dev/null` if usb_device_connected "${intvendor}:${intproduct}"; then export usb_modems="${intvendor}:${intproduct}" unset intvendor; unset intproduct debug "Voodoo operations determined device %s (%s) is a modem.\n" "${usb_modems}" "${besttwo}" unset besttwocount; unset besttwo; unset interfacescore; unset devicescore return 0 fi unset intvendor; unset intproduct fi debug "No device is the absolute winner. Will check for dominating score.\n" firstscore=`echo "${interfacescore}" | ${headbin} -1 | ${cutbin} -d\ -f1 -s | ${sedbin} -e "s/^\(0*\)//g" | ${sedbin} -e "s/^$/0/g"` firstscore=`${printfbin} "%d\n" "${firstscore}" 2> /dev/null`; [ "a${firstscore}" = "a" ] && firstscore=0 secondscore=`echo "${interfacescore}" | ${headbin} -2 | ${tailbin} -1 | ${cutbin} -d\ -f1 -s | ${sedbin} -e "s/^\(0*\)//g" | ${sedbin} -e "s/^$/0/g"` secondscore=`${printfbin} "%d\n" "${secondscore}" 2> /dev/null`; [ "a${secondscore}" = "a" ] && secondscore=0 if [ "a${firstscore}" != "a" -a "a${secondscore}" != "a" ] && [ "a${firstscore}" != "a${secondscore}" ] && [ "${firstscore}" -gt "0" -a "${firstscore}" -gt "${secondscore}" ]; then secondscore=`expr ${secondscore} + ${secondscore}`; secondscore=`echo ${secondscore}` if [ "${firstscore}" -gt "${secondscore}" ]; then besttwo=`echo "${interfacescore}" | ${headbin} -1 | ${cutbin} -d\ -f2 -s | ${cutbin} -d: -f1 -s | ${uniqbin}` intvendor=`${catbin} /sys/bus/usb/devices/${besttwo}/idVendor 2> /dev/null` intproduct=`${catbin} /sys/bus/usb/devices/${besttwo}/idProduct 2> /dev/null` if usb_device_connected "${intvendor}:${intproduct}"; then export usb_modems="${intvendor}:${intproduct}" unset intvendor; unset intproduct debug "Device %s (%s) out-numbered second candidate and will be considered a modem.\n" "${usb_modems}" "${besttwo}" unset firstscore; unset secondscore unset besttwocount; unset besttwo; unset interfacescore; unset devicescore return 0 fi fi fi unset firstscore; unset secondscore debug "No device dominates the other in score. Cannot decide.\n" unset besttwo; unset besttwocount; unset interfacescore; unset devicescore return 1 } # Attempts to get connected modems, and sets usb_modems and usb_modem_devices variables usb_connected_modems() { unset usb_modems; unset usb_modem_devices [ "a${KNOWN_devices}" = "a" ] && ! modeswitch_load && return 1 ! usb_connected_devices && return 1 connectedevices=`echo "${usb_devices}" | ${cutbin} -d: -f1,2` for condevice in ${connectedevices} do devfound=`${printfbin} "%s\n%s\n%s\n" "${KNOWN_devices}" "${MODEM}" "${USBMODEM}" | ${grepbin} "${condevice}"` [ "a${devfound}" != "a" ] && usb_modems="${usb_modems} ${condevice}" unset devfound done unset condevice; unset connectedevices usb_modems=`echo ${usb_modems}` export usb_modems if [ "a${usb_modems}" = "a" ] && unset usb_modems; then debug "No plugged modems found.\n" ! voodoo_mode && return 1 ! voodoo_connected_modems && return 1 fi usb_modem_devices=`usb_device_list ${usb_modems}` export usb_modem_devices debug "Connected USB modems are:\n%s\n" "${usb_modem_devices}" return 0 } # Returns true if device $1 is currently connected usb_device_connected() { [ "a$1" = "a" ] && return 99 usb_connected_devices usbconnected=`echo "${usb_devices}" | ${cutbin} -d: -f1,2 | ${grepbin} "^$1"` [ "a${usbconnected}" = "a$1" ] && unset usbconnected && return 0 unset usbconnected debug "Device \"%s\" is not connected.\n" "$1" return 1 } # Parses /proc/bus/usb/devices and only returns block referring to $1. usb_device_block() { unset usbdeviceblock [ "a$1" = "a" ] && return 1 if [ -r "/proc/bus/usb/devices" ]; then usbvend=`echo "$1" | ${cutbin} -d: -f1` usbprod=`echo "$1" | ${cutbin} -d: -f2` usbdevcat=`safe_cat /proc/bus/usb/devices` usblines=`${printfbin} "%s\n\n" "${usbdevcat}" | ${grepbin} -A 60 "=${usbvend} \(.*\)=${usbprod}" | ${grepbin} -n "^$" | ${headbin} -1 | ${sedbin} -e "s/:$//g"`; usblines=`echo ${usblines}` [ "a${usblines}" = "a" ] && usblines=0 [ "${usblines}" -gt "0" ] && usbdeviceblock=`echo "${usbdevcat}" | ${grepbin} -A 60 "Vendor=${usbvend} ProdID=${usbprod}" | ${headbin} -${usblines}` unset usblines; unset usbvend; unset usbprod; unset usbdevcat echo "${usbdeviceblock}" | ${grepbin} -v "^$" return 0 fi return 1 } # Filters arguments and returns back only those that usb serial drivers usb_serial_drivers() { [ "a${kernel}" = "a" ] && find_binary "uname" && kernel=`${unamebin} -r` [ "a${kernel}" = "a" ] && return 1 export kernel for driver in $@ do [ -f "/lib/modules/${kernel}/kernel/drivers/usb/serial/${driver}.ko" ] && echo "${driver}" && continue [ "a${driver}" = "acdc_acm" ] && [ -f "/lib/modules/${kernel}/kernel/drivers/usb/class/cdc-acm.ko" ] && echo "${driver}" done } # Attempts to find appropriate driver for USB device $1, and sets USBDRIVER usb_serial_detect_driver() { unset USBDRIVER [ "a$1" = "a" ] && return 99 serialvend=`echo "$1" | ${cutbin} -d: -f1` serialprod=`echo "$1" | ${cutbin} -d: -f2` if ! find_binary "uname"; then debug "Failed to locate running kernel's modules. Uname missing.\n" else kernel=`${unamebin} -r` if [ -f "/lib/modules/${kernel}/modules.alias" ]; then drivercandidates=`${grepbin} -i "usb:v${serialvend}p${serialprod}" "/lib/modules/${kernel}/modules.alias" | ${cutbin} -d\ -f3 | ${sortbin} | ${uniqbin}`; drivercandidates=`usb_serial_drivers ${drivercandidates}` if [ "a${drivercandidates}" = "a" ]; then debug "No perfect match found for device \"%s\".\n" "$1" debug "Will seek if exists a driver for other devices from vendor \"%s\".\n" "${serialvend}" drivercandidates=`${grepbin} -i "usb:v${serialvend}p" "/lib/modules/${kernel}/modules.alias" | ${cutbin} -d\ -f3 | ${sortbin} | ${uniqbin}`; drivercandidates=`usb_serial_drivers ${drivercandidates}` if [ "a${drivercandidates}" = "a" ]; then debug "No candidates were found.\n" else debug "Found driver(s) for other devices of same vendor: %s\n" "${drivercandidates}" fi drivercandidates=`echo "${drivercandidates}" | ${trbin} " " "\n" | ${sedbin} -e "s/ //g" | ${sortbin} | ${uniqbin}` else debug "Found driver(s) available for \"%s\": %s\n" "$1" "${drivercandidates}" fi fi unset kernel fi if base_drivers "${serialvend}" "${serialprod}"; then drivercandidates=`echo ${drivercandidates} ${basedrivercandidates}` unset basedrivercandidates fi drivercandidates=`echo ${drivercandidates} | ${trbin} " " "\n" | ${sedbin} -e "s/ //g" | ${sortbin} | ${uniqbin}` candidatenum=`echo ${drivercandidates} | ${wcbin} -w`; candidatenum=`echo ${candidatenum}` if [ "a${candidatenum}" = "a1" ]; then USBDRIVER=`echo ${drivercandidates}` export USBDRIVER debug "Only one candidate, will use it unconditionally: %s\n" "${USBDRIVER}" unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 0 elif [ "a${candidatenum}" = "a0" ]; then drivercandidates="option" debug "No driver found, will propose \"%s\" driver.\n" "${drivercandidates}" if usb_usable_interfaces "$1" && [ "a${usableinterfacecount}" != "a" ] && [ "${usableinterfacecount}" -gt "1" ]; then debug "Device has %d usable interfaces. Will propose cdc_acm also.\n" drivercandidates="cdc_acm option" fi fi debug "Driver candidates are: %s\n" "${drivercandidates}" if voodoo_mode; then for safetoprobe in cdc_acm do debug "Will try safe to probe driver %s.\n" "${safetoprobe}" if module_bind "${safetoprobe}" "$1"; then debug "Appropriate driver %s determined.\n" "${safetoprobe}" export USBDRIVER="${safetoprobe}" unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 0 else debug "Determined %s is not a valid candidate. Will make sure is not within list of candidates either.\n" "${safetoprobe}" drivercandidates=`echo ${drivercandidates} | ${sedbin} -e "s/\( *\)${safetoprobe}\( *\)/ /g" | ${sedbin} -e "s/ / /g"` drivercandidates=`echo ${drivercandidates}` debug "Driver candidates are: %s\n" "${drivercandidates}" fi done fi drivers=`echo ${drivercandidates} | ${trbin} " " "\n" | ${sedbin} -e "s/^\( *\)\(.*\)\( *\)$/\2/g" | ${sortbin} | ${uniqbin} | ${sedbin} -e "s/^\(.*\)$/\"\1\" \"\1 kernel module\"/g"` eval user_select \"USBDRIVER\" \"Please select appropriate driver\" \"Select kernel module that should be used.\" \"Select\" \"Cancel\" ${drivers} \"OTHER\" \"Other driver...\" case "$?" in 0) unset drivers unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 98 ;; 98) unset drivers unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 98 ;; 99) unset drivers unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 99 ;; *) case "a${USBDRIVER}" in aOTHER) unset USBDRIVER user_prompt "USBDRIVER" "Please enter name of driver" "Enter name of appropriate kernel module that should be used, or leave empty to abort" "OK" "Cancel" if [ "a${USBDRIVER}" != "a" ]; then unset drivers unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 0 fi usb_serial_detect_driver "$@" return $? ;; *) unset drivers unset candidatenum; unset drivercandidates; unset serialvend; unset serialprod return 0 ;; esac ;; esac return 99 } # Returns driver attached to interface $2 of device $1 usb_loaded_driver() { [ "a$1" = "a" ] && return 99 if [ -r "/proc/bus/usb/devices" ]; then usbblock=`usb_device_block "$1"`; [ "a${usbblock}" = "a" ] && return 7 if [ "a$2" != "a" ]; then usbdriver=`echo "${usbblock}" | ${grepbin} "^I:\(.*\)If.=\( *\)$2 " | ${sedbin} -e "s/^I:\(.*\)If.=\( *\)$2 \(.*\) Driver=\(.*\)/\4/g"` else usbdriver=`echo "${usbblock}" | ${grepbin} "^I:\(.*\)If.=" | ${sedbin} -e "s/^I:\(.*\)If.=\( *\) \(.*\) Driver=\(.*\)/\4/g"` fi case "a${usbdriver}" in a) usbdriver="FAIL" echo ${usbdriver} unset usbdriver return 1 ;; "a(none)") usbdriver="NONE" echo ${usbdriver} unset usbdriver return 0 ;; *) usbdriver=`echo ${usbdriver} | ${trbin} "-" "_"` usbdriver=`echo ${usbdriver} | ${sedbin} -e "s/usbserial_generic/usbserial/g"` echo ${usbdriver} unset usbdriver return 1 esac elif usb_sysfsdir "$1"; then if [ "a$2" != "a" ]; then usbdriver=`${grepbin} . ${sysfsloc}/*-*\:*.$2/uevent | ${grepbin} -i DRIVER= | ${cutbin} -d= -f2 -s` else usbdriver=`${grepbin} . ${sysfsloc}/*-*\:*.*/uevent | ${grepbin} -i DRIVER= | ${cutbin} -d= -f2 -s`; usbdriver=`echo ${usbdriver}` fi usbdriver=`echo ${usbdriver} | ${trbin} "-" "_"` usbdriver=`echo ${usbdriver} | ${sedbin} -e "s/usbserial_generic/usbserial/g"` [ "a${usbdriver}" = "a" ] && usbdriver="NONE" echo ${usbdriver} unset usbdriver return 0 else debug "Unable to determine driver attached to interface %s of device %s.\n" "$2" "$1" usbdriver="FAIL" echo ${usbdriver} unset usbdriver return 1 fi } usb_usable_interfaces() { unset usableinterfaces; usableinterfacecount=0 [ "a$1" = "a" ] && return 99 if [ -r "/proc/bus/usb/devices" ]; then debug "Using information of %s to determine usable interfaces.\n" "/proc/bus/usb/devices" usbblock=`usb_device_block "$1"` usbinter=`echo "${usbblock}" | ${grepbin} "^I:" | ${wcbin} -l`; usbinter=`echo ${usbinter}` debug "USB Device %s provides %d interface(s).\n" "$1" "${usbinter}" usbinter=`echo "${usbblock}" | ${grepbin} "(I)\(.*\)Atr=...Int\.. " | ${wcbin} -l`; usbinter=`echo ${usbinter}` debug "USB Device %s provides %d interruptable endpoint(s).\n" "$1" "${usbinter}" if [ "a${usbinter}" = "a0" -o "a${usbinter}" = "a" ]; then debug "USB device block output was:\n%s\n" "${usbblock}" debug "No modem lines on USB device \"%s\". Device may need switching.\n" "$1" else usbinter=`echo "${usbblock}" | ${grepbin} "(I)\(.*\)Atr=...Int\.. " | ${sedbin} -e "s/^E:\(.*\)Ad=\(.*\)(I)\(.*\)Atr=...Int\..\(.*\)$/\2/g"`; usbinter=`echo ${usbinter}` debug "Interruptable endpoint(s) are: %s\n" "${usbinter}" unset USB_INTERFACE for endpoint in ${usbinter} do localinter=`echo "${usbblock}" | ${grepbin} -B 10 "^E\(.*\)Ad=${endpoint}(I)" | ${grepbin} "^I" | ${tailbin} -1 | ${sedbin} -e "s/^\(.*\)If.=\( *\)\([0-9][0-9]*\) \(.*\)$/\3/g"` if [ "a${localinter}" != "a" ]; then localinter=`${printfbin} "%d\n" ${localinter} 2> /dev/null` if [ "a${localinter}" != "a" ]; then debug "Added interface %s, containing endpoint %s.\n" "${localinter}" "${endpoint}" usableinterfaces="${usableinterfaces} ${localinter}" fi fi unset localinter done unset localinter; unset endpoint fi unset usbinter; unset usbblock usableinterfaces=`echo ${usableinterfaces}` export usableinterfaces debug "Interfaces collected from %s are: %s\n" "/proc/bus/usb/devices" "${usableinterfaces}" fi if find_binary "lsusb"; then debug "Using information of %s to determine usable interfaces.\n" "lsusb" usbvend=`echo "$1" | ${cutbin} -d: -f1`; usbprod=`echo "$1" | ${cutbin} -d: -f2` usbblock=`safe_lsusb -v -d ${usbvend}:${usbprod}` usbinter=`echo "${usbblock}" | ${sedbin} -e "s/ */ /g" | ${grepbin} -i "transfer type interrupt" | ${wcbin} -l`; usbinter=`echo ${usbinter}` debug "USB Device %s provides %d interruptable endpoint(s).\n" "$1" "${usbinter}" if [ "a${usbinter}" = "a0" -o "a${usbinter}" = "a" ]; then debug "lsusb output was:\n%s\n" "${usbblock}" debug "No modem lines on USB device \"%s\". Device may need switching.\n" "$1" unset usbinter else # Enter character after "interrupt" word on following line IS NOT a mistake usbinter=`echo "${usbblock}" | ${sedbin} -e "s/ */ /g" | ${grepbin} -F -i "transfer type interrupt binterfacenumber" | ${grepbin} -B 1 -i interrupt | ${grepbin} -i "binterfacenumber" | ${cutbin} -d\ -f3 -s`; usbinter=`echo ${usbinter}` fi debug "Interfaces collected from %s are: %s\n" "lsusb" "${usbinter}" [ "a${usbinter}" != "a" ] && usableinterfaces=`echo "${usableinterfaces} ${usbinter}"` export usableinterfaces unset usbvend; unset usbprod; unset usbblock; unset usbinter; elif [ ! -r "/proc/bus/usb/devices" ]; then debug "Failed to read USB information.\n" show_fmt_error "Both \"%s\" and \"%s\" are missing." "lsusb" "/proc/bus/usb/devices" return 7 fi if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi usableinterfaces=`echo ${usableinterfaces} | ${trbin} " " "\n" | ${sedbin} -e "s/ //g" | ${sortbin} | ${uniqbin}` usableinterfaces=`echo ${usableinterfaces}` usableinterfacecount=`echo ${usableinterfaces} | ${wcbin} -w`; usableinterfacecount=`echo ${usableinterfacecount}` return 0 } usb_get_interface() { unset USB_INTERFACE [ "a$1" = "a" ] && return 99 usb_usable_interfaces "$1" ret=$?; [ "a${ret}" != "a0" ] && return ${ret} USB_INTERFACE=`echo ${usableinterfaces}` export USB_INTERFACE if [ "a${USB_INTERFACE}" = "a" -o "a${usableinterfacecount}" = "a0" ]; then debug "Failed to locate any usable interface for device %s.\n" "$1" unset USB_INTERFACE return 8 fi debug "Collected %d interface(s): %s\n" "${usableinterfacecount}" "${USB_INTERFACE}" if [ "a${usableinterfacecount}" = "a1" ]; then debug "Only one interface available. Will use that one unconditionally.\n" return 0 fi usbvend=`echo "$1" | ${cutbin} -d: -f1 -s` usbprod=`echo "$1" | ${cutbin} -d: -f2 -s` if base_drivers "${usbvend}" "${usbprod}"; then if [ "a${baseintercandidates}" != "a" ]; then ifvalid=`echo ${USB_INTERFACE} | ${trbin} " " "\n" | ${grepbin} "^${baseintercandidates}$"` if [ "a${ifvalid}" = "a${baseintercandidates}" ]; then if [ "a${USBINTERFACE}" = "a" ]; then export USB_INTERFACE="${baseintercandidates}" debug "Will use interface #%d derived by config.\n" "${USB_INTERFACE}" unset ifvalid; unset usbvend; unset usbprod; unset baseintercandidates return 0 else debug "However, will not use it in favor of already selected USBINTERFACE: %s\n" "${USBINTERFACE}" fi else debug "However, this interface is not available from device.\n" fi unset ifvalid else debug "Config does not specify interface for device %s.\n" "$1" fi unset baseintercandidates else debug "No configuration for device %s.\n" "$1" fi unset usbvend; unset usbprod if flow_select_interface "$1" "${USB_INTERFACE}"; then [ "a${USBINTERFACE}" = "a" ] && return 98 export USB_INTERFACE="${USBINTERFACE}" debug "Will use interface #%d of USB device \"%s\".\n" "${USB_INTERFACE}" "$1" return 0 else unset USB_INTERFACE debug "User did not provide an interface.\n" return 98 fi return 99 } usb_sysfsdir() { unset sysfsloc [ "a$1" = "a" ] && return 1 ! find_binary "dirname" && return 1 usbven=`echo "$1" | ${cutbin} -d: -f1`; usbpro=`echo "$1" | ${cutbin} -d: -f2` venentry=`${grepbin} -H . /sys/bus/usb/devices/*/*/idVendor 2> /dev/null | ${grepbin} ":${usbven}$"` if [ "a${venentry}" != "a" ]; then for ff in ${venentry} do unset dirloc dirloc=`${dirnamebin} \`echo ${ff} | ${sedbin} -e "s/:${usbven}$//g"\` 2> /dev/null` if [ "a${dirloc}" != "a" ]; then if [ -d "${dirloc}" ]; then dirpro=`${catbin} ${dirloc}/idProduct` if [ "a${dirpro}" = "a${usbpro}" ]; then export sysfsloc="${dirloc}" debug "Device %s sysfs dir found: %s\n" "$1" "${sysfsloc}" unset dirpro; unset dirloc; unset venentry; unset usbven; unset usbpro return 0 fi unset dirpro fi fi unset dirloc done fi debug "No device %s located in sysfs.\n" "$1" unset venentry; unset usbven; unset usbpro return 1 } usb_sysfsdir_int() { unset sysfsintloc [ "a$1" = "a" -o "a$2" = "a" ] && return 99 ! usb_sysfsdir "$1" && return 1 intnum="$2"; [ "${intnum}" -lt "10" ] && intnum="0$2" intdir=`${grepbin} "." ${sysfsloc}/*/bInterfaceNumber | ${grepbin} "bInterfaceNumber:${intnum}$" | ${sedbin} -e "s/bInterfaceNumber:${intnum}$/bInterfaceNumber/g"`; intdir=`${dirnamebin} "${intdir}" 2> /dev/null`; unset intnum if [ "a${intdir}" = "a" ]; then unset intdir; debug "Failed to retrieve sysfs directory of interface #%d.\n" "$2" return 1 elif [ ! -d "${intdir}" ]; then unset intdir; debug "Unable to retrieve sysfs directory of interface #%d.\n" "$2" return 1 fi debug "Interface #%d sysfs dir is: %s\n" "$2" "${intdir}" export sysfsintloc="${intdir}" unset intdir return 0 } # Finds tty which resides on interface $2 of usb device $1 and sets USBTTY usb_sysfs_locate_tty() { unset USBTTY [ "a$1" = "a" -o "a$2" = "a" ] && return 99 ! usb_sysfsdir_int "$1" "$2" && return 1 intstr=`cd ${sysfsintloc} ; ${grepbin} -H "." tty*/dev tty*/tty*/dev tty*/tty*/tty*/dev 2> /dev/null | ${sortbin} | ${uniqbin}`; unset intdir if [ "a${intstr}" = "a" ]; then unset intstr; debug "Failed to retrieve sysfs tty for interface #%d.\n" "$2" return 1 fi debug "Interface #%d tty string is: %s\n" "$2" "${intstr}" unset ttynode [ "a${ttynode}" = "a" ] && ttynode=`echo "${intstr}" | ${sedbin} -e "s/^\(.*\)ttyUSB\([0-9][0-9]*\)\(.*\)$/ttyUSB\2/g" | ${grepbin} "^ttyUSB"` [ "a${ttynode}" = "a" ] && ttynode=`echo "${intstr}" | ${sedbin} -e "s/^\(.*\)ttyACM\([0-9][0-9]*\)\(.*\)$/ttyACM\2/g" | ${grepbin} "^ttyACM"` [ "a${ttynode}" = "a" ] && ttynode=`echo "${intstr}" | ${sedbin} -e "s/^\(.*\)ttyHS\([0-9][0-9]*\)\(.*\)$/ttyHS\2/g" | ${grepbin} "^ttyHS"` devicenode=`echo "${intstr}" | ${sedbin} -e "s/^\(.*\)dev:\([0-9][0-9]*\):\([0-9][0-9]*\)$/\2:\3/g"` ttymajor=`echo "${devicenode}" | ${cutbin} -d: -f1` ttyminor=`echo "${devicenode}" | ${cutbin} -d: -f2` unset intstr; unset devicenode debug "Will check if \"%s\" exists, or will create it with major %d and minor %d.\n" "/dev/${ttynode}" "${ttymajor}" "${ttyminor}" if dev_create_node "/dev/${ttynode}" "${ttymajor}" "${ttyminor}"; then export USBTTY="/dev/${ttynode}" unset ttynode; unset ttymajor; unset ttyminor debug "Found tty device node of interface #%d from device \"%s\": %s\n" "$2" "$1" "${USBTTY}" return 0 else debug "Failed to create tty device of interface #%d from device \"%s\".\n" "$2" "$1" unset ttynode; unset ttymajor; unset ttyminor return 8 fi unset ttynode; unset ttymajor; unset ttyminor return 99 } usb_sysfsattr() { unset SYSFS_USB_Manufacturer unset SYSFS_USB_Product unset SYSFS_USB_Serial [ "a$1" = "a" ] && return 1 ! usb_sysfsdir "$1" && return 1 [ "a${sysfsloc}" = "a" ] && return 1 [ ! -d "${sysfsloc}" ] && return 1 SYSFS_USB_Manufacturer=`${sedbin} -e "s/ /_/g" "${sysfsloc}/manufacturer" 2> /dev/null` SYSFS_USB_Product=`${sedbin} -e "s/ /_/g" "${sysfsloc}/product" 2> /dev/null` SYSFS_USB_Serial=`${sedbin} -e "s/ /_/g" "${sysfsloc}/serial" 2> /dev/null` debug "Information from sysfs:\nUSB Manufacturer: %s\nUSB Product: %s\nUSB Serial: %s\n" "${SYSFS_USB_Manufacturer}" "${SYSFS_USB_Product}" "${SYSFS_USB_Serial}" return 0 } usb_scsisysfsattr() { unset scsidir unset SYSFS_SCSI_Vendor unset SYSFS_SCSI_Model unset SYSFS_SCSI_Revision [ "a$1" = "a" ] && return 1 ! usb_sysfsattr "$1" && return 1 ! find_binary "dirname" && return 1 # How many seconds to wait for SCSI device to settle counter=30 while [ "a${scsidir}" = "a" ]; do if [ "a$2" = "a" ]; then debug "Checking interface #%d of device %s.\n" "0" "$1" target=`${lsbin} -1d ${sysfsloc}/*.0/host*/target*/*/vendor 2> /dev/null` else debug "Checking interface #%d of device %s.\n" "$2" "$1" target=`${lsbin} -1d ${sysfsloc}/*.$2/host*/target*/*/vendor 2> /dev/null | ${tailbin} -1` fi [ "a${target}" != "a" ] && scsidir=`${dirnamebin} "${target}" 2> /dev/null` [ "a${scsidir}" = "a" ] && unset scsidir [ "a${scsidir}" != "a" ] && [ ! -d "${scsidir}" ] && unset scsidir unset target if [ "a${scsidir}" = "a" ]; then if [ "${counter}" -gt "0" ]; then debug "Device not yet settled. Will be waiting for another %d second(s).\n" "${counter}" [ "${counter}" -eq "30" ] && verbose "Waiting device to settle" sleep 1 else debug "Giving up. SCSI device did not settle, or is switched already.\n" break fi counter=`expr ${counter} - 1`; counter=`echo ${counter}` fi done unset counter [ "a${scsidir}" = "a" ] && unset scsidir && return 1 SYSFS_SCSI_Vendor=`${sedbin} -e "s/ /_/g" "${scsidir}/vendor" 2> /dev/null` SYSFS_SCSI_Model=`${sedbin} -e "s/ /_/g" "${scsidir}/model" 2> /dev/null` SYSFS_SCSI_Revision=`${sedbin} -e "s/ /_/g" "${scsidir}/rev" 2> /dev/null` debug "SCSI device is settled:\nSCSI Vendor: %s\nSCSI Model: %s\nSCSI Revision: %s\n" "${SYSFS_SCSI_Vendor}" "${SYSFS_SCSI_Model}" "${SYSFS_SCSI_Revision}" return 0 } # Returns true if device $1 has a storage interface usb_has_storage() { unset STORAGEIF [ "a$1" = "a" ] && return 99 if [ -r "/proc/bus/usb/devices" ]; then usbblock=`usb_device_block "$1"` if [ "a${usbblock}" = "a" ]; then if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi debug "No information for device was available. Is device really connected?\n" debug "Will consider storage part does not exist.\n" debug "However, this may lead into problems later.\n" unset usbblock return 1 fi storageclass=`echo "${usbblock}" | ${grepbin} "Cls=08.stor."` [ "a${storageclass}" = "a" ] && storageclass=`echo "${usbblock}" | ${grepbin} "river=usb_storage"` [ "a${storageclass}" = "a" ] && storageclass=`echo "${usbblock}" | ${grepbin} "river=usb-storage"` if [ "a${storageclass}" = "a" ]; then debug "Device \"%s\" has no storage part.\n" "$1" unset usbblock; unset storageclass return 1 fi storageclass=`echo "${storageclass}" | ${sedbin} -e "s/^I:\(.*\)If.=\( *\)\([0-9][0-9]*\) \(.*\)$/\3/g"` debug "Device has storage part on interface #%s.\n" "${storageclass}" STORAGEIF=`echo "${storageclass}" | ${headbin} -1 | ${cutbin} "-d " -f1` export STORAGEIF unset usbblock; unset storageclass return 0 elif find_binary "lsusb"; then storageclass=`safe_lsusb -d "$1" -v | ${grepbin} -B 10 -A 10 -i storage | ${grepbin} -i "bInterfaceNumber" | ${tailbin} -1 | ${sedbin} -e "s/ */ /g" | ${sedbin} -e "s/^ //g" | ${cutbin} -d\ -f2` if [ "a${storageclass}" = "a" ]; then if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi debug "Device \"%s\" has no storage part.\n" "$1" unset storageclass return 1 fi debug "Device has storage part on interface #%s.\n" "${storageclass}" # TODO: What happens when more storage interfaces exist? STORAGEIF=`echo "${storageclass}" | ${headbin} -1 | ${cutbin} -d\ -f1` export STORAGEIF unset storageclass return 0 else debug "Both %s and %s are not available.\n" "/proc/bus/usb/devices" "lsusb" debug "Failed to determine if device %s has a storage interface.\n" "$1" debug "Will consider storage part does not exist.\n" debug "However, this may lead into problems later.\n" return 1 fi } # Newer kernels provide this feature usb_stabilize() { [ "a$1" = "a" ] && return 1 ! usb_sysfsdir "$1" && return 1 [ "a${sysfsloc}" = "a" ] && return 1 [ ! -d "${sysfsloc}" ] && return 1 [ ! -w "${sysfsloc}/avoid_reset_quirk" ] && return 1 debug "Kernel provides AVOID_RESET_QUIRK for device %s.\n" "$1" echo "1" > "${sysfsloc}/avoid_reset_quirk" 2> /dev/null ret=$? [ "a${ret}" = "a0" ] && debug "Succesfully enabled AVOID_RESET_QUIRK for device %s.\n" "$1" [ "a${ret}" = "a0" ] && debug "Failed to enable AVOID_RESET_QUIRK for device %s.\n" "$1" return ${ret} } # Makes sure that if device $1 has a storage part, this part # is settled. usb_storage_settled() { if ! usb_has_storage "$1"; then hal_unlock return 0 fi debug "Device %s, provides storage interface #%s.\n" "$1" "${STORAGEIF}" storageloaded=`usb_loaded_driver "$1" "${STORAGEIF}" | ${tailbin} -1` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi if [ "a${storageloaded}" != "ausb-storage" -a "a${storageloaded}" != "ausb_storage" ]; then debug "Interface %s of device %s is bound to driver: %s\n" "${STORAGEIF}" "$1" "${storageloaded}" debug "No need to wait for storage interface to settle.\n" unset storageloaded hal_unlock return 0 fi debug "Storage interface #%s is binded by %s driver.\n" "${STORAGEIF}" "${storageloaded}" if [ "a${killstorage}" != "a" ]; then debug "User has set \"%s\" switch. Will try to unbind %s driver from interface #%d.\n" "killstorage" "${storageloaded}" "${STORAGEIF}" if module_unbind "${storageloaded}" "$1" "${STORAGEIF}"; then debug "Storage interface has been freed as instructed.\n" debug "No need to wait for storage interface to settle.\n" unset storageloaded hal_unlock return 0 else debug "Failed to unbind it. Too bad.\n" show_fmt_error "Failed to unbind driver %s. I am sorry." "${storageloaded}" fi fi unset storageloaded if ! usb_scsisysfsattr "$1" "${STORAGEIF}"; then debug "Will consider storage part is settled.\n" debug "However, this may lead into problems later.\n" fi storagedevices=`${grepbin} . ${sysfsloc}/*.${STORAGEIF}/host*/target*/*/block*/size 2> /dev/null | ${grepbin} -v ":0$" | ${sedbin} -e "s/^\(.*\)\/block:\(.*\)\/size:\(.*\)$/\2/g" | ${trbin} "\n" " "`; storagedevices=`echo ${storagedevices}` if [ "a${storagedevices}" = "a" ]; then debug "No storage device(s) with inserted media exist. Safe to unlock HAL.\n" hal_unlock unset storagedevices; unset STORAGEIF return 0 fi debug "Media found on following device(s) provided by interface #%s of device %s: %s\n" "${STORAGEIF}" "$1" "${storagedevices}" if [ "a${HAL_LOCK}" != "a" ]; then hal_unlock debug "HAL is unlocked. Checking if HAL will kick in.\n" pausecounter=21 while [ "${pausecounter}" -gt "0" ] do blocking="" for blockdevice in ${storagedevices} do poller=`${psbin} -Af | ${grepbin} "hald" | ${grepbin} "storage" | ${grepbin} "polling \(.*\)${blockdevice}" | ${grepbin} -v "${grepbin}"` if [ "a${poller}" = "a" ]; then debug "No polling process exists for %s.\n" "${blockdevice}" continue fi debug "Polling process exists for %s: %s\n" "${blockdevice}" "${poller}" poller=`${grepbin} "\/${blockdevice} " "/proc/mounts" 2> /dev/null` if [ "a${poller}" != "a" ]; then debug "Device %s mounted: %s\n" "${blockdevice}" "${poller}" else debug "Device %s still not mounted.\n" "${blockdevice}" blocking="${blocking} ${blockdevice}" fi done unset blockdevice; unset poller; blocking=`echo ${blocking}` if [ "a${blocking}" = "a" ]; then debug "HAL has finished mounting media on device(s): %s\n" "${storagedevices}" break fi pausecounter=`expr ${pausecounter} - 1`; pausecounter=`echo ${pausecounter}` if [ "${pausecounter}" -eq "0" ]; then debug "Giving up waiting for HAL to mount devices.\n" debug "This may lead into problems later on.\n" else [ "${pausecounter}" -eq "20" ] && verbose "Waiting HAL to mount device(s)" debug "Waiting for HAL to mount all devices. %d second(s) to abort.\n" "${pausecounter}" sleep 1 fi done unset poller; unset blockdevice unset pausecounter; unset blocking else debug "HAL was not locked. Will skip waiting for device mount.\n" fi unset storagedevices; unset STORAGEIF return 0 } # Scans for bluetooth devices bluetooth_scan_devices() { ! find_binary "hcitool" && return 1 verbose "Scanning bluetooth devices" bluetooth_devices=`${hcitoolbin} scan 2> /dev/null | ${grepbin} "^ " | ${sedbin} -e "s/^ \(.*\) \(.*\)/\1 \2/g"` debug "Found bluetooth devices:\n%s\n" "${bluetooth_devices}" return 0 } # Returns rfcomm channel for service $2 for device $1 bluetooth_rfcomm_channel() { ! find_binary "sdptool" && return 0 rfchannel=`${sdptoolbin} search --raw --bdaddr "$1" "$2" 2> /dev/null | ${grepbin} -A 1 --binary-files=text "RFCOMM" | ${grepbin} "UINT8" | ${sedbin} -e "s/^\(.*\)UINT8 \(.*\)/\2/g"` rfchannel=`echo ${rfchannel}` debug "Found RFCOMM channel \"%s\" of service \"%s\" on device \"%s\".\n" "${rfchannel}" "$2" "$1" [ "a${rfchannel}" != "a" ] && rfchannel=`${printfbin} "%d\n" ${rfchannel} 2> /dev/null` [ "a${rfchannel}" = "a" ] && rfchannel="0" debug "Returning RFCOMM channels \"%s\".\n" "`echo ${rfchannel}`" return `echo ${rfchannel} | ${cutbin} -d\ -f1` } # Returns true if device $1, channel $2 is on tty $3 # NOTE: Does not depend on bluetooth_rfcomm_dev because # bluetooth_rfcomm_dev only returns 1st valid # channel bluetooth_rfcomm_match() { ! find_binary "rfcomm" && return 1 [ "a${3}" != "a" ] && [ ! -c "${3}" ] && return 1 bluematch=`${rfcommbin} -a --raw | ${grepbin} --binary-files=text " $1 " | ${grepbin} --binary-files=text " channel $2 " | ${grepbin} "^\`${basenamebin} $3\`:" | ${wcbin} -l`; bluematch=`echo ${bluematch}` if [ "a${bluematch}" = "a1" ]; then debug "%s refers to RFCOMM channel %d of device %s.\n" "$3" "$2" "$1" unset bluematch return 0 fi debug "%s does not refer to RFCOMM channel %d of device %s.\n" "$3" "$2" "$1" unset bluematch return 1 } # Returns tty where device $1, channel $2 resides (if any) bluetooth_rfcomm_dev() { ! find_binary "rfcomm" > /dev/null && return 1 bluematch=`${rfcommbin} -a --raw 2> /dev/null | ${grepbin} --binary-files=text " $1 " | ${grepbin} --binary-files=text " channel $2 " | ${headbin} -1 | ${cutbin} -d: -f1` if [ "a${bluematch}" = "a" ]; then unset bluematch return 1 fi echo "${bluematch}" unset bluematch return 0 } # Creates rfcomm device for device $1, channel $2 and sets RFCOMM_TTY bluetooth_create_dev() { ! we_are_root_already && debug "Need root privileges to create rfcomm nodes.\n" ! we_are_root && return 1 need_binary "rfcomm" for devindex in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 do unset occupied occupied=`${rfcommbin} show ${devindex} 2> /dev/null` [ "a${occupied}" = "a" ] && break done if [ "a${occupied}" != "a" ]; then unset occupied unset devindex show_fmt_error "Unable to find available rfcomm device index. Minors occupied." return 1 fi unset occupied debug "Found available rfcomm device node %d.\n" "${devindex}" debug run_command "${rfcommbin} bind ${devindex} \"$1\" \"$2\"" if ! bluetooth_rfcomm_match "$1" "$2" "/dev/rfcomm${devindex}"; then show_fmt_error "Unable to create rfcomm node %s." "rfcomm${devindex}" unset devindex return 1 fi if [ ! -c "/dev/rfcomm${devindex}" ]; then debug "Device node \"%s\" was not automatically created.\n" "/dev/rfcomm${devindex}" if ! dev_create_node "/dev/rfcomm${devindex}" "216" "${devindex}"; then show_fmt_error "Unable to create rfcomm device node \"%s\"." "/dev/rfcomm${devindex}" unset devindex return 1 fi debug "Made node \"%s\" ourselves.\n" "/dev/rfcomm${devindex}" fi export RFCOMM_TTY="/dev/rfcomm${devindex}" unset devindex } # Setups rfcomm device for device $1, channel $2 and sets RFCOMM_TTY bluetooth_setup_rfcomm() { if [ "a${RFCOMM_TTY}" != "a" ]; then if bluetooth_rfcomm_match "$1" "$2" "${RFCOMM_TTY}"; then debug "Will use already set RFCOMM_TTY (%s).\n" "${RFCOMM_TTY}" return 0 else debug "Already set RFCOMM_TTY does not refer to a tty of \"%s\": \"%s\"\n" "$1" "${RFCOMM_TTY}" unset RFCOMM_TTY fi fi RFCOMM_TTY=`bluetooth_rfcomm_dev "$1" "$2"` if [ "a${RFCOMM_TTY}" != "a" ]; then export RFCOMM_TTY="/dev/${RFCOMM_TTY}" if [ -c "${RFCOMM_TTY}" ]; then debug "Found already binded rfcomm tty %s.\n" "${RFCOMM_TTY}" return 0 fi unset RFCOMM_TTY fi unset RFCOMM_TTY if bluetooth_create_dev "$1" "$2"; then debug "Succesfully binded to rfcomm tty %s.\n" "${RFCOMM_TTY}" return 0 fi debug "Failed to setup rfcomm tty for device \"%s\".\n" "$1" return 1 } # Method invoked when "status" action was requested. ppp_fast_status() { need_binary "grep" need_arg "pppint" unset status [ -f "/proc/net/dev" ] && [ -r "/proc/net/dev" ] && status=`${grepbin} "${pppint}:" /proc/net/dev` [ -z "${status}" ] && find_binary "ifconfig" && status=`${ifconfigbin} ${pppint} 2> /dev/null | ${grepbin} " UP "` if [ "a${status}" = "a" ]; then unset status return 1 else unset status return 0 fi } # Called by ispconnect to determine if connection is established ppp_slow_status() { need_arg "pppint" need_binary "netstat" [ "a${pppint}" = "a" ] && pppint="ppp0" pppcon=`${catbin} /proc/net/dev | ${grepbin} "^\( *\)${pppint}:" | ${wcbin} -l`; pppcon=`echo ${pppcon}` [ "a${pppcon}" = "a0" ] && unset pppcon && return 1 debug "Interface %s is up.\n" "${pppint}" pppcon=`${netstatbin} -rn | ${grepbin} " ${pppint}$" | ${grepbin} -v "^0.0.0.0" | ${wcbin} -l`; pppcon=`echo ${pppcon}` [ "a${pppcon}" = "a0" ] && unset pppcon && return 1 debug "Default route through %s is established.\n" "${pppint}" debug "Really connected.\n" return 0 } # Shows version show_version() { if find_binary "printf"; then format_text "Sakis 3G All-in-one script - Version %s\n" "${MYVERSION}" format_text "(c) Sakis Dimopoulos 2009, 2010 under GNU GPL v2\n\n" else need_binary "echo" echo "Sakis 3G All-in-one script - Version ${MYVERSION}" echo "(c) Sakis Dimopoulos 2009, 2010 under GNU GPL v2" echo fi } # Shows usage help show_help() { helptext=`raw_help` notify "%s\n" "${helptext}" return 0 } raw_help() { [ "a${PROVIDER}" = "a" ] && return 1 [ ! -x "${PROVIDER}" ] && return 1 show_version echo "${PROVIDER}" getfile "files/help.txt" 2> /dev/null } modeswitch_load_realtime() { debug "Loading system supplied device database.\n" for dep in sed rm grep tr sort uniq cut printf basename do ! find_binary "${dep}" && return 1 done unset dep; unset realtime_switchable; unset realtime_switched; unset CheckSuccess; unset Configuration; unset GCTMode; unset HuaweiMode; unset SierraMode; unset SonyMode; unset Interface; unset MessageContent; unset ResponseNeeded unset DefaultProduct; unset DefaultVendor; unset TargetClass; unset TargetProduct; unset TargetProductList; unset TargetVendor for filename in /etc/usb_modeswitch.d/* /etc/usb_modeswitch.d/* do current_device=`${basenamebin} ${filename} | ${cutbin} -d: -f1,2 -s` [ "a${current_device}" = "a" ] && unset current_device && continue realtime_switchable="${realtime_switchable} ${current_device}" ${sedbin} -e "s/ //g" "${filename}" > "/tmp/$$.tmp" 2> /dev/null . "/tmp/$$.tmp" > /dev/null 2> /dev/null ${rmbin} -f "/tmp/$$.tmp" > /dev/null 2> /dev/null for ven in ${TargetVendor} do if [ -n "${TargetProductList}" ]; then list=`echo ${TargetProductList} | ${sedbin} -e "s/,/ /g"` for pro in $list do realtime_switched="${realtime_switched} ${ven}:${pro}" done unset list elif [ -n "${TargetProduct}" ]; then realtime_switched="${realtime_switched} ${ven}:${TargetProduct}" fi done unset current_device unset CheckSuccess; unset Configuration; unset GCTMode; unset HuaweiMode; unset SierraMode; unset SonyMode; unset Interface; unset MessageContent; unset ResponseNeeded unset DefaultProduct; unset DefaultVendor; unset TargetClass; unset TargetProduct; unset TargetProductList; unset TargetVendor done realtime_switched=`echo ${realtime_switched} | ${sedbin} -e "s/0x//g" | ${trbin} " " "\n" | ${sortbin} | ${uniqbin}` realtime_switched=`echo ${realtime_switched}` realtime_switchable=`echo ${realtime_switchable} | ${sedbin} -e "s/0x//g" | ${trbin} " " "\n" | ${sortbin} | ${uniqbin}` realtime_switchable=`echo ${realtime_switchable}` debug "Switchable devices within system device database:\n%s\n" "${realtime_switchable}" debug "Switched devices within system device database:\n%s\n" "${realtime_switched}" ${printfbin} "%s\n%s\n" "${realtime_switchable}" "${realtime_switched}" unset realtime_switched; unset realtime_switchable return 0 } # Loads Usb-ModeSwitch device database, both embedded and system supplied modeswitch_load() { unset SWITCHABLE_devices; unset SWITCHED_devices; unset KNOWN_devices debug "Loading Usb-ModeSwitch device database.\n" # Check if possible to include embedded database if [ "a${PROVIDER}" = "a" ]; then debug "Unable to locate package provider.\n" elif [ ! -x "${PROVIDER}" ]; then debug "Unable to execute package provider.\n" else "${PROVIDER}" getfile "build/switchconfig" > "/tmp/sakis3g.$$.sw" if [ ! -f "/tmp/sakis3g.$$.sw" ]; then debug "Unable to find device database.\n" elif [ ! -s "/tmp/sakis3g.$$.sw" ]; then rm -f "/tmp/sakis3g.$$.sw" debug "Embedded device database contains 0 entries.\n" else . "/tmp/sakis3g.$$.sw" rm -f "/tmp/sakis3g.$$.sw" getswitchabledevices 2> /dev/null # TODO: Comment following line to render embedded device database unusable. #unset usbswitchabledevices && unset usbswitcheddevices && debug "DELETED DATABASE TO EMULATE VOODOO MODE.\n" ret=$?; if [ "${ret}" -ne "0" ]; then debug "Failed to load embedded Usb-ModeSwitch device database.\n" else debug "Embedded device database loaded.\n" export SWITCHABLE_devices="${usbswitchabledevices}" export SWITCHED_devices="${usbswitcheddevices}" debug "Switchable devices within embedded device database:\n%s\n" "${SWITCHABLE_devices}" debug "Switched devices within embedded device database:\n%s\n" "${SWITCHED_devices}" KNOWN_devices=`echo "${SWITCHABLE_devices} ${SWITCHED_devices}" | ${trbin} " " "\n" | ${sortbin} | ${uniqbin}` KNOWN_devices=`echo "${KNOWN_devices}"` export KNOWN_devices devicecount=`echo "${KNOWN_devices}" | ${wcbin} -w`; devicecount=`echo ${devicecount}`; [ "a${devicecount}" = "a" ] && devicecount=0 debug "Embedded Usb-ModeSwitch device database contains %d entries.\n" "${devicecount}" unset devicecount fi fi fi # Check if system supplied Usb-ModeSwitch database exists if [ -d "/etc/usb_modeswitch.d" ]; then debug "Folder \"%s\" exists. Will check if it contains configuration files.\n" "/etc/usb_modeswitch.d" realtime_devices=`modeswitch_load_realtime` if [ "a${realtime_devices}" != "a" ]; then usbswitchabledevices=`echo "${realtime_devices}" | ${tailbin} -2 | ${headbin} -1` usbswitcheddevices=`echo "${realtime_devices}" | ${tailbin} -1` SWITCHABLE_devices="${SWITCHABLE_devices} ${usbswitchabledevices}" SWITCHED_devices="${SWITCHED_devices} ${usbswitcheddevices}" SWITCHABLE_devices=`echo "${SWITCHABLE_devices}" | ${trbin} " " "\n" | ${sortbin} | ${uniqbin}` SWITCHED_devices=`echo "${SWITCHED_devices}" | ${trbin} " " "\n" | ${sortbin} | ${uniqbin}` SWITCHABLE_devices=`echo ${SWITCHABLE_devices}` SWITCHED_devices=`echo ${SWITCHED_devices}` KNOWN_devices=`echo "${SWITCHABLE_devices} ${SWITCHED_devices}" | ${trbin} " " "\n" | ${sortbin} | ${uniqbin}` KNOWN_devices=`echo "${KNOWN_devices}"` export SWITCHABLE_devices export SWITCHED_devices export KNOWN_devices devicecount=`echo "${KNOWN_devices}" | ${wcbin} -w`; devicecount=`echo ${devicecount}`; [ "a${devicecount}" = "a" ] && devicecount=0 debug "Device database now contains %d entries.\n" "${devicecount}" unset devicecount fi unset realtime_devices fi unset usbswitchabledevices; unset usbswitcheddevices return 0 } # Returns 0 if device $1 is switchable modeswitch_is_switchable() { [ "a${KNOWN_devices}" = "a" ] && ! modeswitch_load && return 1 isswitchable=`echo "${SWITCHABLE_devices}" | ${grepbin} "$1" | ${wcbin} -l`; isswitchable=`echo ${isswitchable}` [ "a${isswitchable}" = "a" ] && isswitchable="0" if [ "a${isswitchable}" = "a0" ]; then if [ -f "/etc/usb_modeswitch.d/$1" ]; then debug "Since file \"%s\" exists, will consider device \"%s\" switchable.\n" "/etc/usb_modeswitch.d/$1" "$1" unset isswitchable return 0 fi debug "Device \"%s\" is not switchable.\n" "$1" unset isswitchable return 1 else unset isswitchable return 0 fi } modeswitch_switchable_devices() { ! usb_connected_modems && return 1 for condevice in ${usb_modems} do if modeswitch_is_switchable "${condevice}"; then debug "There is at least one (%s) switchable device plugged.\n" "${condevice}" unset condevice return 0 fi done unset condevice debug "No switchable device plugged.\n" "${condevice}" return 1 } modeswitch_conf_realtime() { unset modeswitch_config debug "Seeking a system supplied configuration file for switching device %s.\n" "$1" [ ! -d "/etc/usb_modeswitch.d" -a ! -d "/etc/usb-modeswitch.d" ] && return 1 # Check if exists a candidate which needs SCSI information needscsi=`${lsbin} -1r /etc/usb_modeswitch.d/$1:s* /etc/usb-modeswitch.d/$1:s* 2> /dev/null | ${wcbin} -l` needscsi=`echo ${needscsi}` if [ "a${needscsi}" != "a0" -a "a${needscsi}" != "a" ]; then debug "Will need SCSI information for finding appropriate file.\n" usb_scsisysfsattr "$1" fi unset needscsi # Iterate through files files=`${lsbin} -1r /etc/usb_modeswitch.d/$1* /etc/usb-modeswitch.d/$1* 2> /dev/null` for filename in ${files} do debug "Checking if file \"%s\" matches.\n" "${filename}" bn=`${basenamebin} "${filename}"` crit=`echo "${bn}" | ${cutbin} -d: -f3-`; crit=`echo ${crit}` if [ "a${crit}" != "a" ]; then field=`echo "${crit}" | ${cutbin} -d= -f1 -s` value=`echo "${crit}" | ${cutbin} -d= -f2 -s` if [ "a${field}" = "a" ]; then debug "File %s does not specify criteria to match. Skipping it." "${bn}" unset bn; unset crit; unset field; unset value continue fi if [ "a${value}" = "a" ]; then debug "File %s does not specify value for attribute %s. Skipping it." "${bn}" "${field}" unset bn; unset crit; unset field; unset value continue fi len=`echo "${value}" | ${wcbin} -c`; len=`echo ${len}`; len=`expr ${len} - 1 2> /dev/null`; len=`echo ${len}` if [ "a${len}" = "a" ] || [ "${len}" -eq "0" ]; then debug "Value \"%s\" to be checked is not valid. Skipping file %s." "${value}" "${bn}" unset bn; unset crit; unset field; unset value continue fi unset attribute case "${field}" in sVe) attribute=`echo ${SYSFS_SCSI_Vendor}` ;; sMo) attribute=`echo ${SYSFS_SCSI_Model}` ;; sRe) attribute=`echo ${SYSFS_SCSI_Revision}` ;; uMa) attribute=`echo ${SYSFS_USB_Manufacturer}` ;; uPr) attribute=`echo ${SYSFS_USB_Product}` ;; uSe) attribute=`echo ${SYSFS_USB_Serial}` ;; *) debug "FIXME: Unknown field \"%s\". Try downloading a newer Sakis3G version.\n" "${field}" ;; esac if [ "a${attribute}" = "a" ]; then debug "No value for field %s exists for device %s.\n" "${field}" "$1" unset attribute; unset len; unset field; unset value; unset bn; unset crit continue fi debug "Found %s.%s=\"%s\".\n" "$1" "${field}" "${attribute}" attribute=`echo ${attribute} | ${cutbin} -b1-${len} 2> /dev/null` if [ "a${attribute}" != "a" -a "a${attribute}" = "a${value}" ]; then debug "File %s matches information derived from device.\n" "${bn}" modeswitch_config="${filename}" unset attribute; unset len; unset field; unset value; unset bn; unset crit break; fi debug "File %s does not match.\n" "${bn}" unset attribute; unset len; unset field; unset value; else debug "Found an exact match file: %s\n" "${filename}" modeswitch_config="${filename}" fi unset crit; unset bn done filename="${modeswitch_config}" unset modeswitch_config if [ "a${filename}" != "a" ] && [ -f "${filename}" ]; then ${catbin} "${filename}" > "/tmp/sakis3g.sw.dev.$$" 2> /dev/null if [ -s "/tmp/sakis3g.sw.dev.$$" ]; then export modeswitch_config="/tmp/sakis3g.sw.dev.$$" unset filename return 0 else ${rmbin} -f "/tmp/sakis3g.sw.dev.$$" fi fi unset filename debug "No system supplied configuration file found for switching device \"%s\".\n" "$1" return 1 } # Returns location of extracted configuration file that should be used to switch device $1 within modeswitch_config variable modeswitch_conf_embedded() { unset modeswitch_config debug "Seeking embedded configuration file for switching device %s.\n" "$1" switchfunc="usbswitchconf_`echo "$1" | ${sedbin} -e "s/:/_/g"`" unset modeswitchconf eval ${switchfunc} 2> /dev/null ret=$?; unset switchfunc if [ "${ret}" -ne "0" ]; then debug "Failed to retrieve configuration for switching device \"%s\".\n" "$1" return 1 fi [ "a${modeswitchconf}" = "a" ] && debug "No configuration file found for switching device \"%s\".\n" "$1" && return 1 [ "a${PROVIDER}" = "a" ] && debug "Unable to locate package provider.\n" && unset modeswitchconf && return 1 [ ! -x "${PROVIDER}" ] && debug "Unable to execute package provider.\n" && unset modeswitchconf && return 1 eval "${PROVIDER}" getfile "${modeswitchconf}" > "/tmp/sakis3g.sw.dev.$$" [ ! -f "/tmp/sakis3g.sw.dev.$$" ] && debug "Configuration file \"%s\" for switching device \"%s\" not found within package.\n" "${modeswitchconf}" "$1" && unset modeswitchconf && return 1 if [ ! -s "/tmp/sakis3g.sw.dev.$$" ]; then ${rmbin} -f "/tmp/sakis3g.sw.dev.$$" debug "Configuration file \"%s\" for switching device \"%s\" not found within package.\n" "${modeswitchconf}" "$1" unset modeswitchconf return 1 fi unset modeswitchconf export modeswitch_config="/tmp/sakis3g.sw.dev.$$" return 0 } modeswitch_conf() { unset modeswitch_config debug "Seeking configuration file for switching device %s.\n" "$1" [ "a${KNOWN_devices}" = "a" ] && ! modeswitch_load && return 1 ! modeswitch_conf_embedded "$1" && modeswitch_conf_realtime "$1" if [ "a${modeswitch_config}" = "a" ] || [ ! -f "${modeswitch_config}" ] || [ ! -s "${modeswitch_config}" ]; then unset modeswitch_config show_fmt_error "Unable to locate a configuration file for switching device %s.\n" "$1" return 1 fi debug run_command "${catbin} \"${modeswitch_config}\"" debug "Configuration file for switching device \"%s\" at: %s\n" "$1" "${modeswitch_config}" return 0 } # Executed when binary Usb-ModeSwitch is binary incompatible on running platform. modeswitch_emergency() { ! usb_has_storage "$1" && return 1 debug "Will attempt to switch device by detaching usb-storage driver.\n" storageloaded=`usb_loaded_driver "$1" "${STORAGEIF}" | ${tailbin} -1` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi [ "a${storageloaded}" = "aNONE" ] && ! module_bind "usb_storage" "$1" "${STORAGEIF}" ! module_unbind "usb_storage" "$1" "${STORAGEIF}" unset STORAGEIF return 0 } # Switches device $1. Caller should check NEWIDS variable, because device most likely will change its ID. modeswitch_switch() { [ "a$1" = "a" ] && return 1 ! modeswitch_is_switchable "$1" && return 1 ! modeswitch_conf "$1" && return 1 [ ! -f "${modeswitch_config}" ] && debug "Configuration file \"%s\" disappeared.\n" "${modeswitch_config}" # Block hal from messing with us hal_acquire_lock "org.freedesktop.Hal.Device.Storage" verbose "Switching modem" debug "Connected devices before switching.\n" usb_connected_devices previously=`echo "${usb_devices}" | ${grepbin} -v "^$1:" | ${cutbin} -d: -f1,2` if [ "a${binaryfree}" = "a" ]; then debug run_command "${PROVIDER} usb_modeswitch -W -I -c \"${modeswitch_config}\"" ret=$? else ret=95 fi if [ "${ret}" -eq "95" ]; then [ "a${binaryfree}" = "a" ] && debug "Binary incompatibility of package provided usb-modeswitch.\n" if find_binary "usb_modeswitch"; then debug "Will try system provided binary, hoping it is a recent one: %s\n" "${usb_modeswitchbin}" verbose "Switching modem (using %s)" "${usb_modeswitchbin}" debug run_command "${usb_modeswitchbin} --version" debug run_command "${usb_modeswitchbin} -W -I -c \"${modeswitch_config}\"" ret=$? elif [ "a${binaryfree}" = "a" ]; then show_fmt_error "Embedded Usb-ModeSwitch binary is not valid for your architect. You need to recompile for devices to switch properly. Start by issueing: %s recompile" "${PROVIDER}" debug "Will try emergency mode.\n" verbose "Trying emergency switch" modeswitch_emergency "$1" ret=$? else show_fmt_error "%s is not installed on your system.\n" "Usb-ModeSwitch" return 4 fi fi rm -f "${modeswitch_config}"; unset modeswitch_config counter=0 while [ "${counter}" -lt "20" ] do usb_connected_devices after=`echo "${usb_devices}" | ${grepbin} "^$1:"` if [ "a${after}" != "a" -a "${counter}" -eq "0" ]; then debug "Device \"%s\" still there. Lets hope it has switched.\n" "$1" unset after; unset previously export NEWIDS="$1" return 0 fi after="`echo "${usb_devices}" | ${cutbin} -d: -f1,2`" for device in ${after} do newdevice=`echo "${previously}" | ${grepbin} "^${device}"` if [ "a${newdevice}" = "a" ]; then export NEWIDS="${device}" debug "New device \"%s\" appeared.\n" "${NEWIDS}" unset device; unset after; unset previously return 0 fi done unset device counter=`expr ${counter} + 1`; counter=`echo ${counter}` [ "${counter}" -lt "20" ] && debug "Waiting a second for device to appear.\n" && sleep 1 done debug "Giving up waiting for new device to appear after %d seconds.\n" "${counter}" unset after; unset previously; unset counter return 1 } # Detects usable interface of device $1 and sets USB_INTERFACE variable. Device will get switched if required. # Callers should check NEWIDS variable modem_usb_detect_int() { [ "a$1" = "a" ] && return 99 usb_get_interface "$1"; ret=$? case "${ret}" in 7) debug "Failed to get USB interface.\n" return 7 ;; 98) debug "Failed to get USB interface, by user request.\n" return 98 ;; 8) debug "Failed to get an interface for device.\n" if modeswitch_is_switchable "$1"; then if [ "a$2" != "aNOSWITCH" ]; then debug "This is normal, device \"%s\" is switchable.\n" "$1" modeswitch_switch "$1" ret=$? if [ "${ret}" -eq "0" -a "a${NEWIDS}" != "a" -a "a$2" != "aNOSWITCH" ]; then debug "Device \"%s\" is now switched to \"%s\". Will attempt to setup this one instead.\n" "$1" "${NEWIDS}" modem_usb_detect_int "${NEWIDS}" "NOSWITCH" ret=$? return ${ret} else debug "Failed to switch device \"%s\".\n" "$1" return ${ret} fi else debug "However, device \"%s\" is already switched.\n" "$1" return 8 fi fi debug "Failed setting up USB modem \"%s\".\n" "$1" return 8 ;; 0) debug "Got valid USB interface %d of USB modem \"%s\".\n" "${USB_INTERFACE}" "$1" return 0 ;; *) debug "Unknown error %d while retrieving interface number of USB Device.\n" "${ret}" return ${ret} ;; esac } # Sets USBTTY one way or another modem_usb_locate_tty() { verbose "Locating tty" lcounter=0 while ! usb_sysfs_locate_tty "$1" "$2" "$3" do lcounter=`expr ${lcounter} + 1`; lcounter=`echo ${lcounter}` if [ "${lcounter}" -le "20" ]; then if [ "a$3" != "a" ]; then debug "Waiting for driver %s to create tty of device %s (interface #%d). [%d second(s) will have pass]\n" "$3" "$1" "$2" "${lcounter}" else debug "Waiting for tty of device %s (interface #%d). [%d second(s) will have pass]\n" "$1" "$2" "${lcounter}" fi sleep 1 else if [ "a$3" != "a" ]; then debug "Driver %s failed to create a tty node for interface #%d of device %s.\n" "$3" "$2" "$1" else debug "No tty node created for interface #%d of device %s.\n" "$2" "$1" fi debug "Failed to locate tty device of interface #%d from device \"%s\".\n" "$2" "$1" unset lcounter return 8 fi done return 0 } modem_usb_fix_driver() { [ "a$1" = "a" -o "a$2" = "a" ] && return 99 usb_stabilize "$1" # Make sure storage part (if exists), is settled before # we start playing with drivers. This should eliminate # cases that appeared on 2.6.31+ kernels. usb_storage_settled "$1" # Retrieve loaded driver usbdriver=`usb_loaded_driver "$1" "$2" | ${tailbin} -1` if [ "a${TIMEOUTOCCURED}" != "a" ]; then show_fmt_error "Seems like an electrical/USB bus error occured. You may need to replug your modem for it to properly work.\n" unset TIMEOUTOCCURED fi # Check value if [ "a${usbdriver}" = "a" -o "a${usbdriver}" = "aFAIL" ]; then show_fmt_error "Failed to detect driver of interface %d.\n" "$2" unset usbdriver return 7 elif [ "a${usbdriver}" = "aNONE" ]; then debug "No driver attached to interface #%d of \"%s\".\n" "$2" "$1" else debug "Found already loaded driver \"%s\".\n" "${usbdriver}" fi # If driver mismatch, unload wrong driver if [ "a${USBDRIVER}" != "a" -a "a${usbdriver}" != "a" -a "a${usbdriver}" != "a${USBDRIVER}" -a "a${usbdriver}" != "aNONE" ]; then debug "USBDRIVER variable instructs to use \"%s\" instead.\n" "${USBDRIVER}" if ! module_unbind "${usbdriver}" "$1" "$2"; then show_fmt_error "Failed to detach wrong driver \"%s\". Please do it yourself and retry.\n" "${usbdriver}" unset usbdriver return 9 fi usbdriver="NONE" fi # If no driver, attempt to detect one [ "a${USBDRIVER}" = "a" -a "a${usbdriver}" != "aNONE" ] && USBDRIVER="${usbdriver}" if [ "a${USBDRIVER}" = "a" -a "a${usbdriver}" = "aNONE" ]; then if [ "a${USB_INTERFACE}" != "a" ]; then usb_serial_detect_driver "$1" "$2" if [ "a${USB_INTERFACE}" = "a" ]; then # "usb_serial_detect_driver" call above, called "usb_usable_interfaces" which reset USB_INTERFACE USB_INTERFACE="$2" ; export USB_INTERFACE debug "Interface of device \"%s\" is still #%d.\n" "$1" "${USB_INTERFACE}" fi else usb_serial_detect_driver "$1" "$2" fi fi # We should know a driver now if [ "a${USBDRIVER}" = "a" ]; then unset usbdriver show_fmt_error "Unable to locate driver to use for device \"%s\"" "$1" return 10 fi # Load driver (if required) if [ "${USBDRIVER}" = "${usbdriver}" ]; then debug "Driver \"%s\" already attached to interface #%d of device \"%s\".\n" "${USBDRIVER}" "$2" "$1" unset usbdriver return 0 elif module_bind "${USBDRIVER}" "$1" "$2"; then debug "Driver \"%s\" loaded for interface #%d of device \"%s\".\n" "${USBDRIVER}" "$2" "$1" unset usbdriver return 0 else show_fmt_error "Unable to load driver \"%s\" for device \"%s\"" "${USBDRIVER}" "$1" unset usbdriver return 11 fi } modem_usb() { unset MODEM_TTY [ "a$1" = "a" ] && return 99 ! usb_device_connected "$1" && debug "Device \"%s\" not found.\n" "$1" && return 7 export usbdevice="$1" # Find appropriate interface, switching if required modem_usb_detect_int "${usbdevice}" ret=$?; [ "${ret}" -ne "0" ] && unset usbdevice && return ${ret} # Check if device is switched [ "a${NEWIDS}" != "a" ] && export usbdevice="${NEWIDS}" # Load driver modem_usb_fix_driver "${usbdevice}" "${USB_INTERFACE}" ret=$?; [ "${ret}" -ne "0" ] && unset usbdevice && return ${ret} # Locate tty modem_usb_locate_tty "${usbdevice}" "${USB_INTERFACE}" "${USBDRIVER}" ret=$?; [ "${ret}" -ne "0" ] && unset usbdevice && return ${ret} if [ "a${USBTTY}" != "a" ]; then if [ -c "${USBTTY}" ]; then debug "Nothing more to do for setting it up device \"%s\".\n" "$1" export MODEM_TTY="${USBTTY}" return 0 fi fi unset USB_INTERFACE unset USBTTY unset MODEM_TTY unset usbdevice return 99 } modem_bluetooth() { unset MODEM_TTY [ "a$1" = "a" -o "a$2" = "a" ] && return 99 debug "Attempting to setup bluetooth modem \"%s\" on channel \"%s\".\n" "$1" "$2" bluetooth_setup_rfcomm "$1" "$2" ret=$? if [ "a${ret}" = "a0" ]; then if [ "a${RFCOMM_TTY}" = "a" ]; then debug "No RFCOMM tty returned.\n" elif [ ! -c "${RFCOMM_TTY}" ]; then debug "RFCOMM tty returned (%s), does exist.\n" "${RFCOMM_TTY}" else debug "Nothing more to do for setting it up %s(channel #%d).\n" "$1" "$2" export MODEM_TTY="${RFCOMM_TTY}" return 0 fi fi return 8 } modem_custom() { [ "a$1" = "a" ] && return 99 debug "Attempting to setup custom tty modem on \"%s\".\n" "$1" if [ -c "$1" ]; then debug "Custom tty \"%s\" exists. Nothing more to do for setting it up.\n" "$1" export MODEM_TTY="$1" return 0 else debug "Custom tty \"%s\" does not exist. Unable to proceed.\n" "$1" show_fmt_error "Device node \"%s\" does not exist. Setup failed." "$1" unset MODEM_TTY return 8 fi } modem_setup() { unset MODEM_TTY debug "Setting up modem.\n" ! we_are_root && return 3 [ "a${MODEM}" = "a" ] && ! flow_select_modem "$@" && return 98 if [ "a${MODEM}" = "aOTHER" ]; then [ "a${OTHER}" = "a" ] && ! flow_other_modem "$@" && return 98 if [ "a${OTHER}" = "aUSBMODEM" ]; then [ "a${USBMODEM}" = "a" ] && ! flow_usb_modem "$@" && return 98 if [ "a${USBMODEM}" != "a" ]; then debug "Setting up USB modem %s.\n" "${USBMODEM}" modem_usb "${USBMODEM}" "$@" ret=$? [ "a${usbdevice}" != "a" -a "a${usbdevice}" = "a${NEWIDS}" ] && export USBMODEM="${USBMODEM} ${usbdevice}" return ${ret} fi elif [ "a${OTHER}" = "aBLUETOOTH" ]; then [ "a${BLUETOOTH}" = "a" ] && ! flow_blue_modem "$@" && return 98 if [ "a${BLUETOOTH}" = "aUNDISCOVERABLE" ]; then [ "a${UNDISCOVERABLE}" = "a" ] && ! flow_undiscoverable "$@" && return 98 if [ "a${UNDISCOVERABLE}" != "a" ]; then [ "a${RFSERVICE}" = "a" ] && ! flow_rfchannel "$@" && return 98 if [ "a${RFSERVICE}" = "aRFCHANNEL" ]; then [ "a${RFCHANNEL}" = "a" ] && ! flow_manual_rfcomm "$@" && return 98 if [ "a${RFCHANNEL}" != "a" ]; then debug "Setting up Bluetooth modem %s on channel %s.\n" "${UNDISCOVERABLE}" "${RFCHANNEL}" modem_bluetooth "${UNDISCOVERABLE}" "${RFCHANNEL}" "$@" return $? fi elif [ "a${RFSERVICE}" != "a" ]; then debug "Setting up Bluetooth modem %s on channel %s.\n" "${UNDISCOVERABLE}" "${RFSERVICE}" modem_bluetooth "${UNDISCOVERABLE}" "${RFSERVICE}" "$@" return $? fi fi elif [ "a${BLUETOOTH}" != "a" ]; then [ "a${RFSERVICE}" = "a" ] && ! flow_rfchannel "$@" && return 98 if [ "a${RFSERVICE}" = "aRFCHANNEL" ]; then [ "a${RFCHANNEL}" = "a" ] && ! flow_manual_rfcomm "$@" && return 98 if [ "a${RFCHANNEL}" != "a" ]; then debug "Setting up Bluetooth modem %s on channel %s.\n" "${BLUETOOTH}" "${RFCHANNEL}" modem_bluetooth "${BLUETOOTH}" "${RFCHANNEL}" "$@" return $? fi elif [ "a${RFSERVICE}" != "a" ]; then debug "Setting up Bluetooth modem %s on channel %s.\n" "${BLUETOOTH}" "${RFSERVICE}" modem_bluetooth "${BLUETOOTH}" "${RFSERVICE}" "$@" return $? fi fi elif [ "a${OTHER}" = "aCUSTOM_TTY" ]; then [ "a${CUSTOM_TTY}" = "a" ] && ! flow_custom_tty "$@" && return 98 if [ "a${CUSTOM_TTY}" != "a" ]; then debug "Setting up custom modem on %s.\n" "${CUSTOM_TTY}" modem_custom "${CUSTOM_TTY}" "$@" return $? fi fi elif [ "a${MODEM}" != "a" ]; then debug "Setting up USB modem %s.\n" "${MODEM}" modem_usb "${MODEM}" "$@" ret=$? [ "a${usbdevice}" != "a" -a "a${usbdevice}" = "a${NEWIDS}" ] && export MODEM="${MODEM} ${usbdevice}" return ${ret} fi debug "Failed to setup any modem.\n" return 99 } # Gets entries from file $1 that start with $2:$3 base_fetch() { unset BASERESULT [ "a$1" = "a" ] && return 1 [ "a${PROVIDER}" = "a" ] && debug "Unable to locate package provider.\n" && return 1 [ ! -x "${PROVIDER}" ] && debug "Unable to execute package provider.\n" && return 1 baseentries=`"${PROVIDER}" getfile "$1" | ${grepbin} -v "^#" | ${grepbin} -i "^$2:"` if [ "a${baseentries}" = "a" ]; then unset baseentries debug "No information found for %s within %s database.\n" "$2" "$1" return 1 fi [ "a$3" != "a" ] && BASERESULT=`echo "${baseentries}" | ${grepbin} -i "^$2:$3:"` [ "a${BASERESULT}" = "a" ] && BASERESULT=`echo "${baseentries}" | ${grepbin} -i "^$2::"` export BASERESULT unset baseentries if [ "a${BASERESULT}" = "a" ]; then unset BASERESULT [ "a$3" != "a" ] && debug "No information found for \"%s:%s:\" within %s.\n" "$2" "$3" "$1" [ "a$3" = "a" ] && debug "No default entry \"%s::\" found within %s.\n" "$2" "$1" return 1 fi debug "Loaded entries from %s:\n%s\n" "$1" "${BASERESULT}" return 0 } base_drivers() { unset basedrivercandidates; unset baseintercandidates [ "a$1" = "a" ] && return 1 ! base_fetch "files/usb_devices.db" "$1" "$2" && return 1 [ "a${BASERESULT}" = "a" ] && return 1 BASERESULT=`echo "${BASERESULT}" | ${headbin} -1` basedrivercandidates=`echo "${BASERESULT}" | ${cutbin} -f2 -s` baseintercandidates=`echo "${BASERESULT}" | ${cutbin} -f3 -s` [ "a${basedrivercandidates}" != "a" ] && debug "Device database indicates to use \"%s\" driver(s) for device %s.\n" "${basedrivercandidates}" "$1" [ "a${baseintercandidates}" != "a" ] && debug "Device database indicates to use interface #%d for device %s.\n" "${baseintercandidates}" "$1" unset BASERESULT return 0 } # Sets INIT_STAGES of modem $1 with optional name $2. # Parses files/modem_init.db. base_modem() { unset INIT_STAGE0; unset INIT_STAGE1; unset INIT_STAGE2; unset INIT_STAGE3; unset INIT_STAGE4; unset INIT_STAGE5; unset INIT_STAGE6; unset INIT_STAGE7; unset INIT_STAGE8; [ "a$1" = "a" -a "a$2" = "a" ] && return 1 ! base_fetch "files/modem_init.db" "$1" "$2" && return 1 [ "a${BASERESULT}" = "a" ] && return 1 BASERESULT=`echo "${BASERESULT}" | ${headbin} -1` for item in 0 1 2 3 4 5 6 7 8 do plusone=`expr ${item} + 1`; plusone=`echo ${plusone}` if [ "${item}" -le "7" -a "${item}" -ge "1" ]; then contents=`${printfbin} "%s\n" "${BASERESULT}" | ${cutbin} -f${plusone}` elif [ "${item}" -eq "8" ]; then contents=`${printfbin} "%s\n" "${MODEM_INIT}"` elif [ "${item}" -eq "0" ]; then contents=`${printfbin} "%s\n" "${MODEM_PREPARE}"` fi if [ "a${contents}" != "a" ]; then replacement=`${printfbin} "%s\n" "${contents}" | ${sedbin} -e "s/AT/\\nAT/g" | ${sedbin} -e "s/ *$//g" | ${grepbin} -v "^$" | ${grepbin} "^AT" | ${sedbin} -e "s/^\(.*\)$/\\\'\1\\\' OK/g" | ${trbin} "\n" " "` eval "INIT_STAGE${item}=\${replacement}" eval export INIT_STAGE${item} unset replacement if [ "a$1" != "a" ]; then if [ "a$2" != "a" ]; then debug "Loaded INIT Stage #%d for %s(%s): %s\n" "${item}" "$1" "$2" "`eval echo \\"\\${INIT_STAGE${item}}\\"`" else debug "Loaded INIT Stage #%d for %s: %s\n" "${item}" "$1" "`eval echo \\"\\${INIT_STAGE${item}}\\"`" fi else debug "Loaded INIT Stage #%d for %s: %s\n" "${item}" "$2" "`eval echo \\"\\${INIT_STAGE${item}}\\"`" fi else eval unset INIT_STAGE${item} fi unset contents; unset plusone done debug run_command "set | ${grepbin} \"^INIT_STAGE\"" unset item return 0 } # Sets NETINFO of ISP $1 with optional name $2. If $1==$ISPID sets ISP_ fields also # Parses files/operators.db. base_net() { unset NETINFO [ "a$1" = "a" ] && return 1 ! base_fetch "files/operators.db" "$1" "$2" && return 1 [ "a${BASERESULT}" = "a" ] && return 1 BASERESULT=`echo "${BASERESULT}" | ${headbin} -1` ISP_NAME=`echo "${BASERESULT}" | ${cutbin} -f2` ISP_PRODUCT=`echo "${BASERESULT}" | ${cutbin} -f3` ISP_FGCOLOR=`echo "${BASERESULT}" | ${cutbin} -f4` ISP_BGCOLOR=`echo "${BASERESULT}" | ${cutbin} -f5` ISP_DIAL=`echo "${BASERESULT}" | ${cutbin} -f6` ISP_APNS=`echo "${BASERESULT}" | ${cutbin} -f7 | ${trbin} " " "\n"` ISP_ICON=`echo "${BASERESULT}" | ${cutbin} -f8` export ISP_NAME export ISP_PRODUCT export ISP_FGCOLOR export ISP_BGCOLOR export ISP_DIAL export ISP_APNS export ISP_ICON return 0 } # Gathers information about ISP $1 with optional name $2 net_info() { [ "a$1" != "a" ] && base_net "$@" [ "a$1" != "a${ISPID}" -a "a$1" != "a" ] && return 0 [ "a${ISP_NAME}" = "a" ] && export ISP_NAME="${ISPNAME}" [ "a${ISP_NAME}" = "a" ] && export ISP_NAME="Unknown operator ${ISPID}" [ "a${ISPNAME}" = "a${ISPID}" -o "a${ISPNAME}" = "a" ] && export ISPNAME="${ISP_NAME}" [ "a${ISPNAME}" = "a${ISPID}" -o "a${ISPNAME}" = "a" ] && export ISPNAME="${ISP_NAME}" export ISPTEXT="${ISPNAME}" [ "a${ISP_PRODUCT}" = "a" ] && export ISP_PRODUCT="${ISP_NAME} Internet" [ "a${ISP_FGCOLOR}" = "a" ] && export ISP_FGCOLOR="ffffff" [ "a${ISP_BGCOLOR}" = "a" ] && export ISP_BGCOLOR="000000" [ "a${ISP_DIAL}" = "a" ] && export ISP_DIAL="*99#" [ "a${ISP_ICON}" = "a" ] && export ISP_ICON="files/sakis3g.png" if [ "a${CUSTOM_DIAL}" != "a" -a "a${CUSTOM_DIAL}" != "a${ISP_DIAL}" ]; then debug "Will dial \"%s\" specified by user instead of \"%s\" found in database.\n" "${CUSTOM_DIAL}" "${ISP_DIAL}" export ISP_DIAL="${CUSTOM_DIAL}" fi debug "ISPID: %s / ISPNAME: %s / ISPTEXT: %s\n" "${ISPID}" "${ISPNAME}" "${ISPTEXT}" return 0 } # Select a device interface flow_select_interface() { usbinterfaces=`echo "$2" | ${trbin} " " "\n" | ${sedbin} -e "s/^\(.*\)$/\"\1\" \"Interface #\1\"/g" | ${trbin} "\n" " "` eval user_select \"USBINTERFACE\" \"Please appropriate interface\" \"Select modem interface of USB device that provides modem capabilities.\" \"Select\" \"Cancel\" ${usbinterfaces} case "$?" in 0) unset usbinterfaces return 98 ;; 98) unset usbinterfaces return 98 ;; 99) unset usbinterfaces return 99 ;; *) unset usbinterfaces return 0 ;; esac return 99 } # Makes sure one USB modem exists flow_usb_modem() { usb_connected_devices usbmodems=`echo "${usb_devices}" | ${sedbin} -e "s/^\(....\):\(....\):\(.*\)$/\"\1:\2\" \"\3\"/g"` eval user_select \"USBMODEM\" \"Please select USB modem\" \"Select USB device that provides modem capabilities.\" \"Select\" \"Cancel\" ${usbmodems} case "$?" in 0) unset usbmodems return 98 ;; 98) unset usbmodems return 98 ;; 99) unset usbmodems return 99 ;; *) unset usbmodems usb_connected_devices usbmodems=`echo "${usb_devices}" | ${sedbin} -e "s/^\(....\):\(....\):\(.*\)$/ \1:\2 /g" | ${grepbin} " ${USBMODEM} "`; usbmodems=`echo ${usbmodems}` if [ "a${usbmodems}" = "a${USBMODEM}" ]; then debug "User selected USB modem \"%s\".\n" "${USBMODEM}" unset usbmodems return 0 else debug "USB modem \"%s\" is not currently plugged.\n" "${USBMODEM}" unset usbmodems; unset USBMODEM flow_usb_modem "$@" return "$?" fi ;; esac return 99 } flow_manual_rfcomm() { user_prompt "RFCHANNEL" "Please enter RFCOMM channel" "Enter RFCOMM channel that should be used, or leave empty to abort [1-255]" "OK" "Cancel" case "a${RFCHANNEL}" in a) return 98 ;; *) RFCHANNEL=`${printfbin} "%d\n" "${RFCHANNEL}" 2> /dev/null` [ "a$RFCHANNEL" = "a" ] && RFCHANNEL=0 [ "$RFCHANNEL" -gt "255" ] && RFCHANNEL=0 export RFCHANNEL if [ "$RFCHANNEL" -eq "0" ]; then unset RFCHANNEL return 98 fi return 0 ;; esac } flow_custom_tty() { user_prompt "CUSTOM_TTY" "Please enter tty" "Enter tty node where your 3G modem resides, or leave empty to abort" "OK" "Cancel" case "a${CUSTOM_TTY}" in a) unset CUSTOM_TTY return 98 ;; *) [ ! -c "${CUSTOM_TTY}" ] && [ -c "/dev/${CUSTOM_TTY}" ] && CUSTOM_TTY="/dev/${CUSTOM_TTY}" [ ! -c "${CUSTOM_TTY}" ] && [ -c "/dev${CUSTOM_TTY}" ] && CUSTOM_TTY="/dev${CUSTOM_TTY}" if [ ! -c "${CUSTOM_TTY}" ]; then show_fmt_error "Device node \"%s\" does not exist.\n" "${CUSTOM_TTY}" unset CUSTOM_TTY flow_custom_tty "$@" return $? else debug "Using device node \"%s\".\n" "${CUSTOM_TTY}" export CUSTOM_TTY return 0 fi ;; esac } flow_rfchannel() { [ "a${BLUETOOTH}" = "a" ] && ! flow_blue_modem "$@" && return $? if [ "a${RFSERVICE}" = "aRFCHANNEL" ]; then if ! flow_manual_rfcomm; then unset RFSERVICE flow_rfchannel "$@" return "$?" fi return 0 fi verbose "Seeking %s" "${BLUETOOTH}" if bluetooth_rfcomm_channel "${BLUETOOTH}" "DUN"; then debug "No DUN rfcomm channels returned from \"%s\".\n" "${BLUETOOTH}" bluetooth_rfcomm_channel "${BLUETOOTH}" "SP" rfchannels=`echo "${rfchannel}" | ${sedbin} -e "s/^\([0-9][0-9]*\)$/\"\1\" \"Serial Port from RFCOMM channel #\1\"/g"` else rfchannels=`echo "${rfchannel}" | ${sedbin} -e "s/^\([0-9][0-9]*\)$/\"\1\" \"Dialup Networking from RFCOMM channel #\1\"/g"` bluetooth_rfcomm_channel "${BLUETOOTH}" "SP" rfchannels="${rfchannels} `echo \"${rfchannel}\" | ${sedbin} -e \"s/^\\\([0-9][0-9]*\\\)$/\\\"\\\1\\\" \\\"Serial Port from RFCOMM channel #\\\1\\\"/g\"`" fi eval user_select \"RFSERVICE\" \"Please select RFCOMM service\" \"Select RFCOMM service of Bluetooth device that provides 3G modem capabilities.\" \"Select\" \"Cancel\" \"RESCAN\" \"Scan device again\" ${rfchannels} \"RFCHANNEL\" \"Manually enter non-discovered channel...\" case "$?" in 0) unset rfchannels return 98 ;; 98) unset rfchannels return 98 ;; 99) unset rfchannels return 99 ;; *) unset rfchannels case "a${RFSERVICE}" in aRESCAN) unset RFSERVICE flow_rfchannel "$@" return "$?" ;; aRFCHANNEL) if ! flow_manual_rfcomm; then unset RFSERVICE flow_rfchannel "$@" return "$?" fi return 0 ;; *) export RFCHANNEL="${RFSERVICE}" return 0 ;; esac ;; esac return 99 } # Makes sure one UNDISCOVERABLE BLUETOOTH modem exists flow_undiscoverable() { user_prompt "UNDISCOVERABLE" "Enter Bluetooth address" "Enter Bluetooth address of undiscoverable device, or leave empty to abort" "OK" "Cancel" case "a${UNDISCOVERABLE}" in a) return 98 ;; *) export BLUETOOTH="${UNDISCOVERABLE}" if ! flow_rfchannel; then unset UNDISCOVERABLE; unset BLUETOOTH return 98 fi export BLUETOOTH="UNDISCOVERABLE" return 0 ;; esac } # Makes sure one BLUETOOTH modem exists flow_blue_modem() { if [ "a${BLUETOOTH}" = "aUNDISCOVERABLE" ]; then if ! flow_undiscoverable; then unset BLUETOOTH flow_blue_modem "$@" return "$?" fi return 0 fi bluetooth_scan_devices bluemodems=`echo "${bluetooth_devices}" | ${sedbin} -e "s/^\(.*\) \(.*\)$/\"\1\" \"\2 (\1)\"/g"` eval user_select \"BLUETOOTH\" \"Please select Bluetooth device\" \"Select Bluetooth device that provides 3G modem capabilities.\" \"Select\" \"Cancel\" \"RESCAN\" \"Scan devices again\" ${bluemodems} \"UNDISCOVERABLE\" \"Manually enter undiscoverable device...\" case "$?" in 0) unset bluemodems return 98 ;; 98) unset bluemodems return 98 ;; 99) unset bluemodems return 99 ;; *) unset bluemodems case "a${BLUETOOTH}" in aRESCAN) unset BLUETOOTH flow_blue_modem "$@" return "$?" ;; aUNDISCOVERABLE) if ! flow_undiscoverable; then unset BLUETOOTH flow_blue_modem "$@" return "$?" fi return 0 ;; *) if ! flow_rfchannel; then unset BLUETOOTH flow_blue_modem "$@" return "$?" fi return 0 ;; esac ;; esac return 99 } # Makes sure one other modem is selected flow_other_modem() { user_select "OTHER" "Please select modem type" "Select modem category that best fits your 3G modem." "Select" "Cancel" "USBMODEM" "USB device" "BLUETOOTH" "Bluetooth modem" "CUSTOM_TTY" "Custom tty..." case "$?" in 0) return 98 ;; 98) return 98 ;; 99) return 99 ;; *) case "a${OTHER}" in aUSBMODEM) if ! flow_usb_modem; then unset OTHER flow_other_modem "$@" return "$?" fi return 0 ;; aBLUETOOTH) if ! flow_blue_modem; then unset OTHER flow_other_modem "$@" return "$?" fi return 0 ;; aCUSTOM_TTY) if ! flow_custom_tty; then unset OTHER flow_other_modem "$@" return "$?" fi return 0 ;; *) return 99 ;; esac ;; esac return 99 } # Makes sure one selected modem exists flow_select_modem() { verbose "Locating device" usb_connected_modems modems=`echo "${usb_modem_devices}" | ${sedbin} -e "s/^\(....\):\(....\):\(.*\)$/\"\1:\2\" \"\3\"/g"` if [ "a${modems}" != "a" ]; then modemscount=`echo "${usb_modem_devices}" | ${wcbin} -l`; modemscount=`echo ${modemscount}` if [ "a${modemscount}" = "a1" -a "a${MODEM}" = "a" ]; then MODEM=`echo "${usb_modem_devices}" | ${headbin} -1 | ${sedbin} -e "s/^\(....\):\(....\):\(.*\)$/\1:\2/g"` export MODEM debug "Autoselecting unique USB modem plugged: %s\n" "${MODEM}" ret=1 else eval user_select \"MODEM\" \"Please select modem\" \"Select modem that will be used for establishing 3G connection.\" \"Select\" \"Cancel\" ${modems} \"OTHER\" \"Other...\" # in ret=$? fi unset modemscount else export MODEM="OTHER" ret=97 fi case "${ret}" in 0) return 98 ;; 98) return 98 ;; 99) return 99 ;; *) case "a${MODEM}" in aOTHER) if [ "${ret}" -eq "97" ]; then flow_other_modem "$@" ret=$? [ "${ret}" -ne "0" ] && unset MODEM return ${ret} else if ! flow_other_modem "$@"; then unset MODEM flow_select_modem "$@" return "$?" fi fi return 0 ;; a) return 98 ;; *) return 0 ;; esac return 99 ;; esac return 0 } flow_custom_apn() { user_prompt "CUSTOM_APN" "Please enter APN" "Enter correct APN, or leave empty to abort. Contact your operator if unsure" "OK" "Cancel" case "a${CUSTOM_APN}" in a) unset CUSTOM_APN return 98 ;; *) export CUSTOM_APN return 0 ;; esac } # Makes selected APN exists flow_select_apn() { net_info "${ISPID}" "${ISPNAME}" [ "a${FORCE_APN}" != "a" ] && export ISP_APNS="${FORCE_APN}" [ "a${ISP_APNS}" = "a" ] && tty_detect_apn && export ISP_APNS="${MODEM_APN}" if [ "a${ISP_APNS}" != "a" -a "a${FORCE_APN}" = "a" ]; then apnoptions="" for apnoption in ${ISP_APNS} do apnname=`echo "${apnoption}" | ${cutbin} -d: -f1 -s` if [ "a${apnname}" = "a" ]; then apnname="${apnoption}" apndesc="${apnoption}" apnuser="" ; apnpass="" else apndesc=`echo "${apnoption}" | ${cutbin} -d: -f2 | ${sedbin} -e "s/_/ /g"` apndesc="${apndesc} (${apnname})" apnuser=`echo "${apnoption}" | ${cutbin} -d: -f3` apnpass=`echo "${apnoption}" | ${cutbin} -d: -f4` fi if [ "a${apnname}" = "a${MODEM_APN}" -a "a${MODEM_APN}" != "a" ]; then apndesc=`format_text "Reported by your modem (%s)" "${apnname}"` fi apnoptions="${apnoptions} \"${apnname}\" \"${apndesc}\"" unset apnname; unset apndesc; unset apnuser; unset apnpass done unset apnoption eval user_select \"APN\" \"Please select APN\" \"Select APN that best describes your connection. Contact your operator if unsure. This information, along with APN username and password, is usually easily retrieved through a fast call to customer support\" \"Select\" \"Cancel\" ${apnoptions} \"CUSTOM_APN\" \"Custom APN...\" ret=$? unset apnoptions elif [ "a${FORCE_APN}" != "a" ]; then debug "Selected APN by FORCE_APN: %s\n" "${FORCE_APN}" APN=`echo "${FORCE_APN}" | ${cutbin} -d: -f1` export APN ret=1 else export APN="CUSTOM_APN" ret=97 fi case "${ret}" in 0) return 98 ;; 98) return 98 ;; 99) return 99 ;; *) case "a${APN}" in aCUSTOM_APN) if [ "${ret}" -eq "97" ]; then if ! flow_custom_apn "$@"; then unset APN return 98 fi else if ! flow_custom_apn "$@"; then unset APN flow_select_apn "$@" return "$?" fi fi return 0 ;; a) return 98 ;; *) APN=`echo "${ISP_APNS}" | ${grepbin} "^${APN}\(:*\)" | ${cutbin} -d: -f1` export APN if [ "a${APN}" = "a" ]; then unset APN flow_select_apn "$@" return "$?" else apnuser=`echo "${ISP_APNS}" | ${grepbin} "^${APN}\(:*\)" | ${cutbin} -d: -f3 -s` [ "a${apnuser}" != "a" -a "a${APN_USER}" = "a" ] && export APN_USER="${apnuser}" apnpass=`echo "${ISP_APNS}" | ${grepbin} "^${APN}\(:*\)" | ${cutbin} -d: -f4 -s` [ "a${apnuser}" != "a" -a "a${APN_PASS}" = "a" ] && export APN_PASS="${apnpass}" unset apnuser; unset apnpass fi return 0 ;; esac return 99 ;; esac return 0 } flow_apn_user() { [ "a${APN}" = "a" ] && return 98 if [ "a${APN_USER}" = "a" ]; then if [ "a${APN}" != "a" ]; then if [ "a${APN}" = "aCUSTOM_APN" -a "a${CUSTOM_APN}" != "a" ]; then APN_USER=`echo "${CUSTOM_APN}" | ${cutbin} -d: -s -f3` else APN_USER=`echo "${APN}" | ${cutbin} -d: -s -f3` fi fi fi [ "a${APN_USER}" = "a" ] && unset APN_USER if [ "a${APN}" = "aCUSTOM_APN" -a "a${CUSTOM_APN}" != "a" ]; then apntitle=`echo "${CUSTOM_APN}" | ${cutbin} -d: -f1` elif [ "a${APN}" != "a" ]; then apntitle=`echo "${APN}" | ${cutbin} -d: -f1` fi user_prompt "APN_USER" "APN: ${apntitle}" "Enter username required by APN, or leave empty to abort. Contact your operator if unsure. This information, along with APN password, is usually easily retrieved through a fast call to customer support" "OK" "Cancel" case "a${APN_USER}" in a) unset APN_USER return 98 ;; *) export APN_USER return 0 ;; esac } flow_apn_pass() { [ "a${APN}" = "a" ] && return 98 if [ "a${APN_PASS}" = "a" ]; then if [ "a${APN}" != "a" ]; then if [ "a${APN}" = "aCUSTOM_APN" -a "a${CUSTOM_APN}" != "a" ]; then APN_PASS=`echo "${CUSTOM_APN}" | ${cutbin} -d: -s -f4` else APN_PASS=`echo "${APN}" | ${cutbin} -d: -s -f4` fi fi fi [ "a${APN_PASS}" = "a" ] && unset APN_PASS if [ "a${APN}" = "aCUSTOM_APN" -a "a${CUSTOM_APN}" != "a" ]; then apntitle=`echo "${CUSTOM_APN}" | ${cutbin} -d: -f1` elif [ "a${APN}" != "a" ]; then apntitle=`echo "${APN}" | ${cutbin} -d: -f1` fi user_prompt "APN_PASS" "APN: ${apntitle}" "Enter password required by APN, or leave empty to abort. Contact your operator if unsure. This information is usually easily retrieved through a fast call to customer support" "OK" "Cancel" case "a${APN_PASS}" in a) unset APN_PASS return 98 ;; *) export APN_PASS return 0 ;; esac } flow_switch() { flow_select_modem "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} unset NEWIDS if modeswitch_is_switchable "${MODEM}" && usb_device_connected "${MODEM}"; then modeswitch_switch "${MODEM}" ret=$? if [ "a${NEWIDS}" != "a" -a "a${NEWIDS}" != "a${MODEM}" ]; then debug "Device changed ID. From \"%s\" to \"%s\".\n" "${MODEM}" "${NEWIDS}" export MODEM="${NEWIDS}" fi localdev="${MODEM}" elif modeswitch_is_switchable "${USBMODEM}" && usb_device_connected "${USBMODEM}"; then modeswitch_switch "${USBMODEM}" ret=$? if [ "a${NEWIDS}" != "a" -a "a${NEWIDS}" != "a${USBMODEM}" ]; then debug "Device changed ID. From \"%s\" to \"%s\".\n" "${USBMODEM}" "${NEWIDS}" export USBMODEM="${NEWIDS}" fi localdev="${USBMODEM}" else debug "Currently selected modem cannot be switched. No need to switch anything.\n" return 0 fi # Should normally unlock HAL here. But we don't. # If we will stay within program, it will get unlocked during driver setup. # If stand-alone action, exit trap will unlock it. # So, line below should be commented out. #hal_unlock return ${ret} } flow_setup() { flow_select_modem "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} if modem_setup "$@"; then debug "Modem is now setup and resides on %s.\n" "${MODEM_TTY}" return 0 else return $? fi } flow_prepare() { flow_setup "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} if tty_prepare "${MODEM_TTY}" "$@"; then debug "Device %s is now prepared and registered to %s.\n" "${MODEM_TTY}" "${ISPTEXT}" else return $? fi } pppd_config() { need_binary "pppd" need_arg "PPPD_OPTIONS"; need_arg "BAUD" unset CONNECTION_CONF; unset CONNECTION_COMMAND ${touchbin} "/tmp/pppd.tmp.$$" if [ ! -w "/tmp/pppd.tmp.$$" ]; then show_fmt_error "Unable to create temporary pppd config file within %s directory.\n" "/tmp" return 99 fi CONNECTION_CONF="/tmp/pppd.tmp.$$" find_binary "chmod" && ${chmodbin} 600 "${CONNECTION_CONF}" ${catbin} > "${CONNECTION_CONF}" <> "${CONNECTION_CONF}" unset initstrings if [ ! -s "${CONNECTION_CONF}" ]; then ${rmbin} -f "${CONNECTION_CONF}" show_fmt_error "Failure to write on %s.\n" "${CONNECTION_CONF}" unset CONNECTION_CONF return 99 fi debug "Config file that will be used is: \"%s\".\n" "${CONNECTION_CONF}" debug show_file "${CONNECTION_CONF}" pppdoptions="${PPPD_OPTIONS}" [ "a${pppdoptions}" = "a" ] && pppdoptions="modem crtscts -detach defaultroute dump noipdefault usepeerdns usehostname ktune logfd 2 noauth name sakis3g lock maxfail 3" if [ "a${PPPD_PEERS}" != "a" ]; then if [ -d "${PPPD_PEERS}" ]; then if [ -f "${PPPD_PEERS}/sakis3g" ]; then debug "Found peers file %s.\n" "${PPPD_PEERS}/sakis3g" pppdoptions="-detach dump logfd 2 name sakis3gpeer maxfail 3 call sakis3g" fi fi fi export CONNECTION_COMMAND="${setsidbin} ${pppdbin} ${MODEM_TTY} ${BAUD} ${pppdoptions} connect \"${chatbin} -v -f ${CONNECTION_CONF}\" user \"${APN_USER}\" password \"${APN_PASS}\"" unset pppdoptions debug "Connection command that will be used is: %s\n" "${CONNECTION_COMMAND}" return 0 } wvdial_config() { need_binary "wvdial" need_arg "BAUD" unset CONNECTION_CONF; unset CONNECTION_COMMAND ${touchbin} "/tmp/wvdial.tmp.$$" if [ ! -w "/tmp/wvdial.tmp.$$" ]; then show_fmt_error "Unable to create temporary wvdial config file within %s directory.\n" "/tmp" return 99 fi CONNECTION_CONF="/tmp/wvdial.tmp.$$" find_binary "chmod" && ${chmodbin} 600 "${CONNECTION_CONF}" ${catbin} > "${CONNECTION_CONF}" <> "${CONNECTION_CONF}" if [ ! -s "${CONNECTION_CONF}" ]; then ${rmbin} -f "${CONNECTION_CONF}" show_fmt_error "Failure to write on %s.\n" "${CONNECTION_CONF}" unset CONNECTION_CONF return 99 fi debug "Config file that will be used is: \"%s\".\n" "${CONNECTION_CONF}" debug show_file "${CONNECTION_CONF}" export CONNECTION_COMMAND="${setsidbin} ${wvdialbin} --config \"${CONNECTION_CONF}\"" debug "Connection command that will be used is: %s\n" "${CONNECTION_COMMAND}" return 0 } ispconnect() { [ "a${CONNECTION_COMMAND}" = "a" ] && return 95 if ppp_fast_status; then debug "Already connected.\n" return 0 fi ! we_are_root && return 1 debug run_command "${rmbin} -f \"/tmp/sakis3g.3gnet\"" ! tty_not_busy "${MODEM_TTY}" && return 1 if [ "a$1" = "anoretry" ]; then verbose "Connecting (second attempt)" else verbose "Connecting" fi logpid=0 if [ -n "${DEBUG}" ]; then eval "${CONNECTION_COMMAND} &" logpid=$! else eval "${CONNECTION_COMMAND} <&- >&- 2>&- &" logpid=$! fi passed=0 while ! notrunning "${logpid}" do ppp_slow_status && break debug "Waiting for interface to go up (%d seconds passed).\n" "${passed}" passed=`expr ${passed} + 1`; passed=`echo ${passed}` if [ "a${passed}" = "a21" ]; then debug "Giving up waiting for connection to occur.\n" if find_binary "kill"; then ${killbin} -1 ${logpid} 2> /dev/null ! notrunning "${logpid}" && sleep 1 ! notrunning "${logpid}" && sleep 1 fi break fi sleep 1 done if notrunning "${logpid}" && [ "a$1" != "anoretry" ]; then unset logpid ispconnect "noretry" return $? fi unset passed if ! ppp_slow_status; then debug "Failed to connect.\n" unset logpid return 95 fi debug "Connection is established.\n" ${printfbin} "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" "${ISPID}" "${ISPTEXT}" "${MODEM_VARIANT}" "${USBDRIVER}" "${MODEM_TTY}" "${MODEM}" "${OTHER}" "${APN}" "${CUSTOM_APN}" "${APN_USER}" "${APN_PASS}" "${logpid}" > "/tmp/sakis3g.3gnet" [ -f "/tmp/sakis3g.3gnet" ] && ${chmodbin} 644 "/tmp/sakis3g.3gnet" unset logpid return 0 } # Deletes all currently existing default gateways. routing_delete_gateways() { ! we_are_root && return 1 ! find_binary "netstat" && return 1 ! find_binary "route" && return 1 while [ "1" = "1" ]; do gatehost=`${netstatbin} -rn | ${grepbin} "^0.0.0.0 " | ${tailbin} -1 | ${sedbin} -e "s/ */ /g" | ${cutbin} -d\ -f2` if [ "a${gatehost}" != "a" ]; then debug "Deleting default gateway %s.\n" "${gatehost}" debug run_command "${routebin} del default gw ${gatehost}" else debug "Deleted all default gateways.\n" break fi done unset gatehost return 0 } # Makes sure only our pppint(ppp0) peer is used as default gateway. routing_fix() { ! find_binary "netstat" && return 1 ! find_binary "route" && return 1 need_arg "pppint" hostpeer=`${netstatbin} -rn | ${grepbin} " ${pppint}$" | ${grepbin} -v "^0.0.0.0 " | ${cutbin} -d\ -f1` if [ "a${hostpeer}" != "a" ]; then routing_delete_gateways debug run_command "${routebin} add default gw ${hostpeer}" debug "Added correct default gateway: %s.\n" "${hostpeer}" debug run_command "${netstatbin} -rn" fi unset hostpeer return 0 } dns_fix() { debug "Checking if required to fix DNS settings.\n" unset needdnsfix if [ ! -f "/etc/resolv.conf" ]; then needdnsfix=1 debug "No %s exists. Will make it ourselves.\n" "/etc/resolv.conf" else debug show_file "/etc/resolv.conf" baddns=`${grepbin} "10.11.12.13" "/etc/resolv.conf" | ${wcbin} -l`; baddns=`echo ${baddns}` [ "a${baddns}" = "a0" ] && baddns=`${grepbin} "10.11.12.14" "/etc/resolv.conf" | ${wcbin} -l` baddns=`echo ${baddns}` if [ "a${baddns}" != "a0" ]; then needdnsfix=1 debug "File %s contains bad DNS servers. Will fix it.\n" "/etc/resolv.conf" fi unset baddns fi if [ "a${DNS}" != "a" ]; then needdnsfix=1 debug "Will fix DNS due to DNS servers being set: %s\n" "${DNS}" fi if [ "a${needdnsfix}" != "a1" ]; then debug "No need to fix DNS servers. Skipping it.\n" unset needdnsfix return 0 fi if [ "a${DNS}" = "a" ]; then debug "No DNS servers where set. Will use Google DNS.\n" export DNS="8.8.8.8 8.8.4.4" fi ${rmbin} -f "/etc/resolv.conf" ${touchbin} "/etc/resolv.conf" ${chmodbin} 644 "/etc/resolv.conf" for dnsserver in ${DNS} do ${printfbin} "nameserver %s\n" "${dnsserver}" >> "/etc/resolv.conf" debug "Added name server %s to %s.\n" "${dnsserver}" "/etc/resolv.conf" done unset dnsserver ${printfbin} "\n# This file was autogenerated by %s.\n\n" "Sakis3G script" >> "/etc/resolv.conf" debug "Done setting up custom DNS server(s).\n" return 0 } flow_post_connection() { if [ "a${NOSMART}" != "a" ]; then debug "Requested not to smart-fix connection.\n" return 0 fi verbose "Fixing connection" debug "Running post-connection setup.\n" routing_fix dns_fix } flow_connect() { ppp_fast_status && return 0 flow_prepare "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} verbose "Resolving connection details" flow_select_apn "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} flow_apn_user "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} flow_apn_pass "$@" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} [ "a${MODEM_TTY}" = "a" ] && return 99 [ ! -c "${MODEM_TTY}" ] && return 99 [ "a${APN}" = "a" -o "a${APN_USER}" = "a" -o "a${APN_PASS}" = "a" -o "a${ISP_DIAL}" = "a" ] && return 99 ! at_default_commands "DIAL" && return 99 [ "a${ttycommands}" = "a" ] && return 99 export DIAL_COMMANDS="${ttycommands}" if [ "a${direct_pppd}" != "a" ]; then pppd_config "$@" ret=$? else wvdial_config "$@" ret=$? fi unset DIAL_COMMANDS [ "${ret}" -ne "0" ] && return ${ret} verbose "Initializing modem" tty_send_command "${MODEM_TTY}" "INITIALIZE" ret=$?; [ "${ret}" -ne "0" ] && return ${ret} tty_send_command "${MODEM_TTY}" "STAGE7" tty_send_command "${MODEM_TTY}" "STAGE8" ispconnect "$@" ret=$? [ "a${CONNECTION_CONF}" != "a" ] && [ -f "${CONNECTION_CONF}" ] && ${rmbin} -f "${CONNECTION_CONF}" unset CONNECTION_CONF; unset CONNECTION_COMMAND [ "${ret}" -ne "0" ] && return ${ret} flow_post_connection "$@" if [ "a${CONNECTION_HOOK}" != "a" ]; then debug "Will now execute CONNECTION_HOOK: %s.\n" "${CONNECTION_HOOK}" term_clearline debug run_command "${CONNECTION_HOOK}" debug "Connection hook returned.\n" fi ! ppp_slow_status && return 99 return ${ret} } flow_disconnect() { ! ppp_fast_status && return 0 ! we_are_root && return 1 verbose "Disconnecting" if find_binary "killall"; then ${killallbin} -q -1 pppd sleep 1 ppp_fast_status && ${killallbin} -q -9 pppd elif find_binary "ps" && find_binary "kill"; then ppppid=`${psbin} -C "pppd" -o pid= 2> /dev/null | ${grepbin} -i "PID"`; ppppid=`echo ${ppppid}` for propid in ${ppppid} do debug run_command "kill -1 ${propid}" done ppppid=`${psbin} -C "pppd" -o pid= 2> /dev/null | ${grepbin} -i "PID"`; ppppid=`echo ${ppppid}` for propid in ${ppppid} do debug run_command "kill -9 ${propid}" done unset ppppid; unset propid else show_fmt_error "Unable to stop running pppd session. Both %s and % were not found.\n" "kill" "killall" return 1 fi sleep 1 if ppp_fast_status; then debug "Failed to disconnect.\n" return 1 fi debug "Disconnected.\n" return 0 } compile_check_local_requirements() { if [ "a${PROVIDER}" = "a" ]; then show_fmt_error "Not running from within package.\n" return 1 fi if [ ! -x "${PROVIDER}" ]; then show_fmt_error "Reported package location is not executable: %s\n" "${PROVIDER}" return 1 fi if [ ! -w "${PROVIDER}" ] && we_are_root; then show_fmt_error "Unable to overwrite existing package %s. Check if on read-only filesystem.\n" "${PROVIDER}" return 1 fi return 0 } compile_check_dependencies() { unset missing for localdependency in bzip2 bunzip2 pwd basename dirname gcc tar dd stat cp chmod rm mkdir mv find rmdir printf grep expr ls sort uniq cut sed tr cat touch do ! find_binary "${localdependency}" && missing="${missing} ${localdependency}" done missing=`echo ${missing}` if [ "a${missing}" != "a" ]; then show_fmt_error "Following dependencies not found within path: %s\n" "${missing}" unset missing return 1 fi unset missing return 0 } compile_compilation_dependencies() { [ "a${PROVIDER}" = "a" ] && return 1 [ ! -x "${PROVIDER}" ] && return 1 ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" > /dev/null 2> /dev/null ${touchbin} "/tmp/sakis3g.source.$$.combined.c" > /dev/null 2> /dev/null if [ ! -f "/tmp/sakis3g.source.$$.combined.c" ]; then show_fmt_error "Unable to create file %s.\n" "/tmp/sakis3g.source.$$.combined.c" return 1 fi ${PROVIDER} getfile usb_modeswitch.c 2> /dev/null > "/tmp/sakis3g.source.$$.c" ${PROVIDER} getfile usb_modeswitch.h 2> /dev/null > "/tmp/sakis3g.source.$$.h" ${catbin} "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > "/tmp/sakis3g.source.$$.combined.c" if [ ! -s "/tmp/sakis3g.source.$$.combined.c" ]; then ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > /dev/null 2> /dev/null show_fmt_error "Unable to extract %s source from package.\n" "Usb-ModeSwitch" return 1 fi headerfiles=`${grepbin} "^#include <" "/tmp/sakis3g.source.$$.combined.c" | ${sedbin} -e "s/\( *\)/ /g" | ${cutbin} -d\ -f2 -s | ${sedbin} -e "s/^<\(.*\)>$/INCLUDE:\1/g" | ${grepbin} "^INCLUDE:" | ${cutbin} -d: -f2- -s` if [ "a${headerfiles}" = "a" ]; then unset headerfiles ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > /dev/null 2> /dev/null show_fmt_error "Problem while parsing %s sources.\n" "Usb-ModeSwitch" return 1 fi debug "Header files are:\n%s\n" "${headerfiles}" accumulative="" for header in ${headerfiles} do debug "Probing: %s\n" "${header}" accumulative=`${printfbin} "%s\n%s\n" "${accumulative}" "${header}" | ${grepbin} -v "^$"` echo "${accumulative}" | ${sedbin} -e "s/^\(.*\)$/#include <\1\>/g" > "/tmp/sakis3g.source.$$.combined.c" ${printfbin} "int main(int argc, char **argv) {\nreturn 22;\n}\n\n" >> "/tmp/sakis3g.source.$$.combined.c" ${rmbin} -f "/tmp/sakis3g.object.$$" > /dev/null 2> /dev/null if [ -f "/tmp/sakis3g.object.$$" ]; then unset headerfiles; unset header; unset accumulative; ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > /dev/null 2> /dev/null show_fmt_error "Unable to delete \"%s\".\n" "/tmp/sakis3g.object.$$" return 1 fi debug run_command "${gccbin} -Wall -o \"/tmp/sakis3g.object.$$\" \"/tmp/sakis3g.source.$$.combined.c\"" if [ ! -x "/tmp/sakis3g.object.$$" ]; then if [ "a${header}" != "ausb.h" ]; then show_fmt_error "Header file %s missing from your system.\n" "${header}" else show_fmt_error "Header file %s missing from your system. This usually indicates libusb (or libusb-compat) development kit missing.\n" "${header}" fi unset headerfiles; unset header; unset accumulative; ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > /dev/null 2> /dev/null ${rmbin} -f "/tmp/sakis3g.object.$$" > /dev/null 2> /dev/null return 1 fi debug run_command "/tmp/sakis3g.object.$$" ret=$? if [ "${ret}" -ne "22" ]; then show_fmt_error "Unusable binary after including \"%s\".\n" "${header}" unset headerfiles; unset header; unset accumulative; ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > /dev/null 2> /dev/null ${rmbin} -f "/tmp/sakis3g.object.$$" > /dev/null 2> /dev/null return 1 fi debug "No problem encountered when including \"%s\".\n" "${header}" ${rmbin} -f "/tmp/sakis3g.object.$$" > /dev/null 2> /dev/null done ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" > /dev/null 2> /dev/null unset header; unset headerfiles; debug "Will now attempt linking.\n" echo "${accumulative}" | ${sedbin} -e "s/^\(.*\)$/#include <\1\>/g" > "/tmp/sakis3g.source.$$.combined.c" ${catbin} "/tmp/sakis3g.source.$$.h" "/tmp/sakis3g.source.$$.c" | ${grepbin} -v "^#include" >> "/tmp/sakis3g.source.$$.combined.c" debug show_file "/tmp/sakis3g.source.$$.combined.c" debug run_command "${gccbin} -Wall -lusb -o \"/tmp/sakis3g.object.$$\" \"/tmp/sakis3g.source.$$.combined.c\"" unset accumulative; ${rmbin} -f "/tmp/sakis3g.source.$$.combined.c" "/tmp/sakis3g.source.$$.c" "/tmp/sakis3g.source.$$.h" > /dev/null 2> /dev/null if [ ! -x "/tmp/sakis3g.object.$$" ]; then ${rmbin} -f "/tmp/sakis3g.object.$$" > /dev/null 2> /dev/null show_fmt_error "Failed to link %s. This usually indicates libusb (or libusb-compat) development kit missing.\n" "Usb-ModeSwitch" return 1 fi ${rmbin} -f "/tmp/sakis3g.object.$$" > /dev/null 2> /dev/null debug "Linking test was successful.\n" return 0 } compile_perform() { [ "a${PROVIDER}" = "a" ] && return 1 [ ! -x "${PROVIDER}" ] && return 1 tempdestination="/tmp/sakis3g.recompile.$$" debug run_command "${rmbin} -rf \"${tempdestination}\"" debug run_command "${mkdirbin} \"${tempdestination}\"" if [ ! -d "${tempdestination}" ]; then show_fmt_error "Unable to create temporary folder \"%s\".\n" "${tempdestination}" unset tempdestination return 1 fi debug run_command "${touchbin} \"${tempdestination}/test.$$\"" if [ ! -w "${tempdestination}/test.$$" ]; then debug run_command "${rmbin} -rf \"${tempdestination}\"" show_fmt_error "No write access to temporary folder \"%s\".\n" "${tempdestination}" unset tempdestination return 1 fi debug run_command "${rmbin} -rf \"${tempdestination}/\"*" if [ ! -d "${tempdestination}" ]; then show_fmt_error "Oops. Weird \"%s\" version. Deleted temporary folder \"%s\".\n" "${rmbin}" "${tempdestination}" unset tempdestination return 1 fi debug run_command "${PROVIDER} disassemble \"${tempdestination}/.\"" if [ ! -x "${tempdestination}/sakis3g-${MYVERSION}/compile" ]; then debug run_command "${rmbin} -rf \"${tempdestination}\"" show_fmt_error "Failed to disassemble Sakis3G package.\n" "${tempdestination}" unset tempdestination return 1 fi debug run_command "${rmbin} -f \"${tempdestination}/sakis3g-${MYVERSION}/build/sakis3gz\"" compilation_error=`cd "${tempdestination}/sakis3g-${MYVERSION}"; ./compile 2>&1` debug "Compilation output:\n%s\n" "${compilation_error}" if [ ! -x "${tempdestination}/sakis3g-${MYVERSION}/build/sakis3gz" -o ! -s "${tempdestination}/sakis3g-${MYVERSION}/build/sakis3gz" ]; then debug run_command "${rmbin} -rf \"${tempdestination}\"" show_fmt_error "Failed to compile. Compilation output:\n%s\n" "${compilation_error}" unset compilation_error; unset tempdestination return 1 fi unset compilation_error verification=`"${tempdestination}/sakis3g-${MYVERSION}/build/sakis3gz" usb_modeswitch --version 2> /dev/null | ${grepbin} -i "josua" | ${wcbin} -l`; verification=`echo ${verification}` if [ "a${verification}" = "a" -o "a${verification}" = "a0" ]; then unset verification debug run_command "${rmbin} -rf \"${tempdestination}\"" show_fmt_error "Failed to verify result of compilation.\n" unset tempdestination return 1 fi unset verification debug run_command "${rmbin} -f \"${PROVIDER}.backup\"" if [ -f "${PROVIDER}.backup" ]; then debug run_command "${rmbin} -rf \"${tempdestination}\"" show_fmt_error "Unable to delete previously existing \"%s\".\n" "${PROVIDER}.backup" unset tempdestination return 1 fi debug run_command "${cpbin} \"${PROVIDER}\" \"${PROVIDER}.backup\"" if [ ! -f "${PROVIDER}.backup" ]; then debug run_command "${rmbin} -rf \"${tempdestination}\"" show_fmt_error "Unable to create a safe backup to \"%s\".\n" "${PROVIDER}.backup" unset tempdestination return 1 fi debug run_command "${lsbin} -l \"${PROVIDER}\"" # No rm, or we loose owner and rights information #debug run_command "${rmbin} -f \"${PROVIDER}\"" #debug run_command "${lsbin} -l \"${PROVIDER}\"" debug run_command "${cpbin} \"${tempdestination}/sakis3g-${MYVERSION}/build/sakis3gz\" \"${PROVIDER}\"" debug run_command "${lsbin} -l \"${PROVIDER}\"" debug run_command "${rmbin} -rf \"${tempdestination}\"" unset tempdestination verification=`"${PROVIDER}" usb_modeswitch --version 2> /dev/null | ${grepbin} -i "josua" | ${wcbin} -l`; verification=`echo ${verification}` if [ "a${verification}" = "a" -o "a${verification}" = "a0" ]; then debug "Verification failed. Restoring previous version.\n" debug run_command "${cpbin} \"${PROVIDER}.backup\" \"${PROVIDER}\"" unset verification if [ -x "${PROVIDER}" ]; then show_fmt_error "Failed to succesfully place new version. You are still using old version.\n" elif [ -x "${PROVIDER}.backup" ]; then show_fmt_error "Failed to succesfully create new version. Old version is still available at \"%s\".\n" "${PROVIDER}.backup" else show_fmt_error "Something really bad happened. I am really sorry. You may need to re-download Sakis3G.\n" fi return 1 fi unset verification debug run_command "${rmbin} -f \"${PROVIDER}.backup\"" debug run_command "${lsbin} -l \"${PROVIDER}.backup\"" debug "Succesfully recompiled.\n" return 0 } flow_compile() { if [ "a${binaryfree}" != "a" ]; then show_fmt_error "You are running a binary free version of Sakis3G. Unable to recompile %s.\n" "Usb-ModeSwitch" return 99 fi verbose "Checking tools availability" compile_check_local_requirements ret=$?; [ "${ret}" -ne "0" ] && return ${ret} verbose "Checking dependencies" compile_check_dependencies ret=$?; [ "${ret}" -ne "0" ] && return ${ret} verbose "Testing compiler" compile_compilation_dependencies ret=$?; [ "${ret}" -ne "0" ] && return ${ret} verbose "Compiling" compile_perform ret=$?; [ "${ret}" -ne "0" ] && return ${ret} return 0 } flow_report() { if ! status_connected; then show_fmt_error "You need to be connected for generating report.\n" return 6 fi unset report_text old_translation=${notranslate} export notranslate=1 report_text="Sakis3G version: ${MYVERSION}" if [ "a${PROVIDER}" = "a" ]; then report_text=`${printfbin} "%s\nNot running from within package.\n" "${report_text}"` elif [ ! -x "${PROVIDER}" ]; then report_text=`${printfbin} "%s\nPackage is not executable.\n" "${report_text}"` else if [ "a${binaryfree}" != "a" ]; then if [ "a${stripped}" != "a" ]; then report_text=`${printfbin} "%s\nRunning a binary free version.\n" "${report_text}"` else report_text=`${printfbin} "%s\nRunning a stripped version.\n" "${report_text}"` fi switchversion="95" else switchversion=`${PROVIDER} usb_modeswitch --version 2> /dev/null || echo $?` fi if [ "a${switchversion}" = "a95" ]; then if find_binary "usb_modeswitch"; then switchversion=`${usb_modeswitchbin} --version 2> /dev/null` report_text=`${printfbin} "%s\nSystem provided Usb-ModeSwitch:\n%s\n" "${report_text}" "${switchversion}"` else report_text=`${printfbin} "%s\nUsb-ModeSwitch is not available.\n" "${report_text}"` fi else switchversion=`${printfbin} "%s\n" "${switchversion}" | ${grepbin} -i version` report_text=`${printfbin} "%s\nUsing embedded Usb-ModeSwitch version:\n%s\n" "${report_text}" "${switchversion}"` fi fi if find_binary "uname"; then report_text=`${printfbin} "%s\nKernel version: %s\nArchitect: %s\n" "${report_text}" "\`${unamebin} -r\`" "\`${unamebin} -m\`"` else report_text=`${printfbin} "%s\nUtility uname is not available.\n" "${report_text}"` fi report_text=`${printfbin} "%s\nSelected UI is: %s\n" "${report_text}" "${SGUI}"` info_text=`action_info report | ${grepbin} -v "^$" | ${grepbin} -v "^ $"` report_text=`${printfbin} "%s\n%s\n" "${report_text}" "${info_text}"` state_variables "APN_USER APN_PASS SIM_PIN SGUI UNDISCOVERABLE BLUETOOTH MENU MOREMENU BALOONIZER" report_text=`${printfbin} "%s\nVariables: %s\n" "${report_text}" "${statevariables}"` unset info_text export notranslate="${old_translation}" [ "a${notranslate}" = "a" ] && unset notranslate unset old_translation trtext=`format_text "Please report following text:\n"` notify "%s\n\n%s\n" "${trtext}" "${report_text}" unset trtext; unset switchversion; unset report_text return 0 } # Returns 0 if connected, 1 if not connected. # Sets as much of the following information: # - statusnet containing numeric ID of ISP # - statusname containing text of ISP or nothing # - statusicon if statusnet exists within operator database and contains icon. # Sets ISPID only if not set already. # It is possible that it returns 0 and not set variables. This happens # if ppp interface was initiated by another application. status_connected() { unset statusnet; unset statusname; unset statusicon; unset localpid ! ppp_fast_status && return 1 if [ -r "/tmp/sakis3g.3gnet" ]; then statusnet=`${headbin} -1 "/tmp/sakis3g.3gnet"` statusname=`${headbin} -2 "/tmp/sakis3g.3gnet" | ${tailbin} -1` debug "Retrieved from %s: \"%s\" - \"%s\"\n" "/tmp/sakis3g.3gnet" "${statusnet}" "${statusname}" statusnet=`echo "${statusnet}" | ${grepbin} "^[0-9][0-9][0-9][0-9][0-9]"` if [ "a${statusnet}" != "a" ]; then [ "a${statusname}" = "a${statusnet}" ] && unset statusname debug "Retrieved ISP ID from %s: %s\n" "/tmp/sakis3g.3gnet" "${statusnet}" [ "a${statusname}" != "a" ] && debug "Also retrieved ISP name: %s\n" "${statusname}" else unset statusname; unset statusnet debug "Invalid or not existing %s within %s.\n" "ISPID" "/tmp/sakis3g.3gnet" fi if [ "a${statusnet}" != "a" ] && [ "a${ISPID}" = "a" -o "a${ISPID}" = "a${statusnet}" ]; then if [ "a${MODEM_VARIANT}" = "a" ]; then MODEM_VARIANT=`${headbin} -3 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${MODEM_VARIANT}" != "a" ] && export MODEM_VARIANT && debug "Also read: %s\n" "${MODEM_VARIANT}" fi if [ "a${USBDRIVER}" = "a" ]; then USBDRIVER=`${headbin} -4 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${USBDRIVER}" != "a" ] && export USBDRIVER && debug "Also read: %s\n" "${USBDRIVER}" fi if [ "a${MODEM_TTY}" = "a" ]; then MODEM_TTY=`${headbin} -5 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${MODEM_TTY}" != "a" ] && export MODEM_TTY && debug "Also read: %s\n" "${MODEM_TTY}" fi if [ "a${MODEM}" = "a" ]; then MODEM=`${headbin} -6 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${MODEM}" != "a" ] && export MODEM && debug "Also read: %s\n" "${MODEM}" fi if [ "a${OTHER}" = "a" ]; then OTHER=`${headbin} -7 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${OTHER}" != "a" ] && export OTHER && debug "Also read: %s\n" "${OTHER}" fi if [ "a${APN}" = "a" ]; then APN=`${headbin} -8 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${APN}" != "a" ] && export APN && debug "Also read: %s\n" "${APN}" fi if [ "a${CUSTOM_APN}" = "a" -a "a${APN}" = "aCUSTOM_APN" ]; then CUSTOM_APN=`${headbin} -9 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${CUSTOM_APN}" != "a" ] && export CUSTOM_APN && debug "Also read: %s\n" "${CUSTOM_APN}" fi if [ "a${APN_USER}" = "a" ]; then APN_USER=`${headbin} -10 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${APN_USER}" != "a" ] && export APN_USER && debug "Also read: %s\n" "${APN_USER}" fi if [ "a${APN_PASS}" = "a" ]; then APN_PASS=`${headbin} -11 "/tmp/sakis3g.3gnet" | ${tailbin} -1` [ "a${APN_PASS}" != "a" ] && export APN_PASS && debug "Also read: %s\n" "${APN_PASS}" fi localpid=`${headbin} -12 "/tmp/sakis3g.3gnet" | ${tailbin} -1` if [ "a${localpid}" != "a" ]; then localprocess=`${psbin} -p ${localpid} -o comm= 2> /dev/null` if [ "a${localprocess}" != "a" ]; then debug "Process ID %s is: %s\n" "${localpid}" "${localprocess}" [ "${localprocess}" != "pppd" -a "${localprocess}" != "wvdial" ] && unset localprocess elif notrunning "${localpid}"; then debug "Process ID %s is not running.\n" "${localpid}" elif [ "a${localprocess}" = "a" ]; then debug "Process ID %s is not valid.\n" "${localpid}" fi if [ "a${localprocess}" = "a" -a "a${ISPID}" = "a" ]; then debug "Status file %s is stalled. Will discard information read from it.\n" "/tmp/sakis3g.3gnet" unset statusnet; unset statusname fi fi unset localpid; unset localprocess fi else debug "Invalid or not existing %s.\n" "/tmp/sakis3g.3gnet" fi if [ "a${ISPID}" != "a" ]; then debug "%s is set to: %s\n" "ISPID" "${ISPID}" if [ "a${statusnet}" = "a" ]; then statusnet="${ISPID}" debug "Was adapted since file not available.\n" "statusnet" if [ "a${ISPTEXT}" != "a" -a "a${ISPTEXT}" != "a${ISPID}" ]; then statusname="${ISPTEXT}" debug "Also adapted %s: %s\n" "ISPTEXT" "${ISPTEXT}" fi elif [ "a${statusnet}" = "a${ISPID}" ]; then debug "It matches value retrieved from file.\n" if [ "a${ISPTEXT}" != "a" -a "a${ISPTEXT}" != "a${ISPID}" -a "a${statusname}" = "a" ]; then statusname="${ISPTEXT}" debug "Also adapted %s since networks match: %s\n" "ISPTEXT" "${ISPTEXT}" fi else debug "Does not match value retrieved from file.\n" debug "Will trust file.\n" fi else debug "%s is not set.\n" "ISPID" if [ "a${statusnet}" = "a" ]; then debug "Unable to determine on which network we are connected.\n" else export ISPID="${statusnet}" debug "All information derived from file.\n" debug "Also set %s from file contents.\n" "ISPID" fi fi if net_info "${statusnet}" "${statusname}" && [ "a${BASERESULT}" != "a" ]; then statusproduct=`echo "${BASERESULT}" | ${cutbin} -f3 -s` [ "a${statusproduct}" != "a" ] && export statusproduct statusicon=`echo "${BASERESULT}" | ${cutbin} -f8 -s` [ "a${statusicon}" != "a" ] && export statusicon if [ "a${statusname}" = "a" ]; then statusname=`echo "${BASERESULT}" | ${cutbin} -d: -f2 -s` [ "a${statusname}" != "a" ] && debug "Retrieved %s name from database: %s\n" "${statusnet}" "${statusname}" fi fi if [ "a${statusnet}" = "a" ]; then unset statusnet; unset statusname else export statusnet if [ "a${statusname}" = "a" ]; then unset statusname else export statusname fi fi return 0 } # Method invoked when "status" action was requested. action_status() { unset verbosecurrentcount if ! ppp_fast_status; then show_fmt_error "Not connected.\n" return 6 fi status_connected if [ "a${statusnet}" != "a" ]; then if [ "a${statusnet}" != "a${statusname}" -a "a${statusname}" != "a" ]; then if [ "a${MODEM_VARIANT}" != "a" ]; then finalnotify "%s connected to %s (%s)." "${MODEM_VARIANT}" "${statusname}" "${statusnet}" else finalnotify "Connected to %s (%s)." "${statusname}" "${statusnet}" fi else if [ "a${MODEM_VARIANT}" != "a" ]; then finalnotify "%s connected to %s." "${MODEM_VARIANT}" "${statusnet}" else finalnotify "Connected to %s." "${statusnet}" fi fi else finalnotify "Connected." fi return 0 } action_info() { unset verbosecurrentcount if ! ppp_fast_status; then notify "Not connected.\n" return 0 fi status_connected if [ "a${statusnet}" = "a" ]; then notify "Unable to gather connection information.\n" return 0 fi if [ "a$1" != "areport" ]; then infotext=`translate_text "Connection Information"` infotext=`${printfbin} "%s\n \n" "${infotext}"` fi [ "a${pppint}" != "a" ] && localtext=`format_text "Interface:\t\t\tP-t-P (%s)\n" "${pppint}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext infotext=`${printfbin} "%s\n \n" "${infotext}"` if [ "a$1" != "areport" ]; then if find_binary "stat"; then upsince=`${statbin} --printf="%z" "/tmp/sakis3g.3gnet" | ${cutbin} -d: -f1,2 -s` if [ "a${upsince}" != "a" ]; then localtext=`format_text "Connected since:\t%s\n" "${upsince}"` infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext fi unset upsince fi if [ -r "/proc/net/dev" -a "a${pppint}" != "a" ]; then traffic=`${sedbin} -e "s/ */ /g" "/proc/net/dev" | ${grepbin} "^\( *\)${pppint}:" | ${headbin} -1 | ${cutbin} -d: -f2- | ${sedbin} -e "s/^ *//g" | ${cutbin} -d\ -f1,9` debug "Traffic details are: %s\n" "${traffic}" bytesreceived=`echo ${traffic} | ${cutbin} -d\ -f1 -s` [ "a${bytesreceived}" != "a" ] && bytesreceived=`expr \( ${bytesreceived} + 512 \) / 1024 2> /dev/null` [ "a${bytesreceived}" != "a" ] && localtext=`format_text "Kilobytes received:\t%d\n" ${bytesreceived}` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext bytessent=`echo ${traffic} | ${cutbin} -d\ -f2 -s` [ "a${bytessent}" != "a" ] && bytessent=`expr \( ${bytessent} + 512 \) / 1024 2> /dev/null` [ "a${bytessent}" != "a" ] && localtext=`format_text "Kilobytes sent:\t%d\n" ${bytessent}` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext unset traffic; unset bytesreceived; unset bytessent fi fi localtext=`format_text "Network ID:\t\t%s" "${statusnet}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n\n%s\n" "${infotext}" "${localtext}"`; unset localtext [ "a${statusname}" != "a" ] && localtext=`format_text "Operator name:\t%s" "${statusname}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext if [ "a${APN}" != "a" ]; then if [ "a${APN}" = "aCUSTOM_APN" -a "a${CUSTOM_APN}" != "a" ]; then localtext=`format_text "APN:\t\t\t%s" "${CUSTOM_APN}"` elif [ "a${APN}" != "aCUSTOM_APN" ]; then localtext=`format_text "APN:\t\t\t%s" "${APN}"` fi fi [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext infotext=`${printfbin} "%s\n \n" "${infotext}"` [ "a${MODEM_VARIANT}" != "a" ] && localtext=`format_text "Modem:\t\t\t%s\n" "${MODEM_VARIANT}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext if [ "a${MODEM}" != "a" ]; then if [ "a${MODEM}" != "a" -a "a${MODEM}" != "aOTHER" ]; then localtext=`format_text "Modem type:\t\tUSB\n"` elif [ "a${MODEM}" = "aOTHER" ]; then if [ "a${OTHER}" = "aUSBMODEM" ]; then localtext=`format_text "Modem type:\t\tUSB\n"` elif [ "a${OTHER}" = "aBLUETOOTH" ]; then localtext=`format_text "Modem type:\t\tBluetooth\n"` else localtext=`format_text "Modem type:\t\tCustom\n"` fi else localtext=`format_text "Modem type:\t\tUnknown\n"` fi else localtext=`format_text "Modem type:\t\tUnspecified\n"` fi [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext [ "a${USBDRIVER}" != "a" ] && localtext=`format_text "Kernel driver:\t\t%s\n" "${USBDRIVER}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext [ "a${MODEM_TTY}" != "a" ] && localtext=`format_text "Device:\t\t\t%s\n" "${MODEM_TTY}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext infotext=`${printfbin} "%s\n \n" "${infotext}"` if [ "a$1" != "areport" ]; then if find_binary "ifconfig" && [ "a${pppint}" != "a" ]; then ipaddress=`${ifconfigbin} ${pppint} | ${sedbin} -e "s/^.*:\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\) .*:\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\) \(.*\):\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)$/IPADDRESSES: \1.\2.\3.\4 \5.\6.\7.\8/g" | ${grepbin} "^IPADDRESSES:" | ${cutbin} -d: -f2- -s` if [ "a${ipaddress}" != "a" ]; then localip=`echo ${ipaddress} | ${cutbin} -d\ -f1 -s` localpeer=`echo ${ipaddress} | ${cutbin} -d\ -f2 -s` localmask="255.255.255.255" [ "a${localip}" != "a" ] && localtext=`format_text "IP Address:\t\t%s\n" "${localip}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext [ "a${localip}" != "a" ] && localtext=`format_text "Subnet Mask:\t\t%s\n" "${localmask}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext [ "a${localpeer}" != "a" ] && localtext=`format_text "Peer IP Address:\t%s\n" "${localpeer}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext unset localip; unset localpeer; unset localmask fi unset ipaddress fi if find_binary "netstat" && [ "a${pppint}" != "a" ]; then localpeer=`${netstatbin} -rn | ${grepbin} "^0.0.0.0 " | ${sedbin} -e "s/ */ /g" | ${cutbin} -d\ -f2 -s`; localpeer=`echo ${localpeer}` [ "a${localpeer}" != "a" ] && localtext=`format_text "Default route(s):\t%s\n" "${localpeer}"` [ "a${localtext}" != "a" ] && infotext=`${printfbin} "%s\n%s\n" "${infotext}" "${localtext}"`; unset localtext unset localpeer fi [ "a${SGUI}" != "azenity" ] && infotext=`echo "${infotext}" | ${sedbin} -e "s/\( *\)/ /g"` notify "%s\n" "${infotext}" else infotext=`echo "${infotext}" | ${sedbin} -e "s/\( *\)/ /g"` ${printfbin} "%s\n" "${infotext}" fi unset localtext; unset infotext return 0 } action_desktop() { # Retrieve icon information if possible [ "a${runner}" = "a" ] && return 1 [ "a${runhome}" = "a" ] && return 1 [ ! -d "${runhome}" ] && return 1 need_binary "touch"; need_binary "mkdir"; need_binary "chown"; need_binary "chmod"; need_binary "cat" unset desktopdestination if [ "a${DESKTOP}" = "a" ] && find_binary "xdg-user-dir"; then DESKTOP=`${xdg_user_dirbin} DESKTOP` [ "a${DESKTOP}" = "a" ] && DESKTOP=`${xdg_user_dirbin} desktop` if [ "a${DESKTOP}" != "a" ]; then DESKTOP=`echo "${DESKTOP}" | ${sedbin} -e "s/\/$//g"` DESKTOP=`${basenamebin} "${DESKTOP}"` fi fi if [ "a${DESKTOP}" != "a" ] && [ -d "${DESKTOP}" ]; then desktopdestination="${DESKTOP}" elif [ -d "${runhome}/Desktop" ]; then desktopdestination="${runhome}/Desktop" elif [ -d "${runhome}/desktop" ]; then desktopdestination="${runhome}/desktop" elif [ "a${HOME}" != "a" -a "a${DESKTOP}" != "a" ] && [ -d "${HOME}/${DESKTOP}" ]; then desktopdestination="${HOME}/${DESKTOP}" elif find_binary "pwd"; then desktopdestination="`${pwdbin} 2> /dev/null`" else desktopdestination="." fi [ "a${desktopdestination}" = "a" ] && desktopdestination="." debug "Destination of shortcut is: %s\n" "${desktopdestination}" if status_connected && [ "a${statusicon}" != "a" -a "a${statusname}" != "a" ] && find_binary "wget" && find_binary "basename"; then user_select "DESKTOPICON" "Desktop icon" "Select icon to use for shortcut" "OK" "Cancel" "SAKIS3G" "Sakis3G tux icon" "OPERATOR" "${statusname} icon" selection=$? case "${selection}" in 1) DESKTOPICON="SAKIS3G" ;; 2) DESKTOPICON="OPERATOR" ;; 98) return 98 ;; *) return 99 ;; esac else debug "${statusicon} ${statusname}\n" debug "Automatically selecting %s icon.\n" "Sakis3G" DESKTOPICON="SAKIS3G" fi if [ "a${DESKTOPICON}" = "aOPERATOR" ]; then extension=`${basenamebin} "${statusicon}" | ${cutbin} -d. -f2-` verbose "Retrieving operator icon" debug run_command "${rmbin} -f \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\"" debug run_command "${wgetbin} -O \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\" \"${statusicon}\"" if [ ! -s "/tmp/sakis3g.$$.${ISPID}_logo.${extension}" ]; then debug run_command "${rmbin} -f \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\"" show_fmt_error "Unable to get %s icon, unknown reason." "${statusname}" DESKTOPICON="SAKIS3G" else debug "Successfully retrieved %s icon.\n" "operator" fi fi if [ "a${DESKTOPICON}" = "aSAKIS3G" ] && [ "a${PROVIDER}" != "a" ] && [ -x "${PROVIDER}" ]; then extension="png" "${PROVIDER}" getfile "files/sakis3g.png" > "/tmp/sakis3g.$$.${ISPID}_logo.${extension}" 2> /dev/null if [ ! -s "/tmp/sakis3g.$$.${ISPID}_logo.${extension}" ]; then debug run_command "${rmbin} -f \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\"" show_fmt_error "Unable to get %s icon, unknown reason." "Sakis3G" DESKTOPICON="" else debug "Successfully retrieved %s icon.\n" "Sakis3G" fi fi if [ -s "/tmp/sakis3g.$$.${ISPID}_logo.${extension}" ]; then debug run_command "${mkdirbin} -p \"${runhome}/.local\"" debug run_command "${chownbin} ${runner} \"${runhome}/.local\"" debug run_command "${mkdirbin} -p \"${runhome}/.local/share\"" debug run_command "${chownbin} ${runner} \"${runhome}/.local/share\"" debug run_command "${mkdirbin} -p \"${runhome}/.local/share/icons\"" debug run_command "${chownbin} ${runner} \"${runhome}/.local/share/icons\"" if [ "a${extension}" = "agif" -o "a${extension}" = "aGIF" -o "a${extension}" = "aGif" ]; then debug run_command "${mvbin} \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\" \"${runhome}/.local/share/icons/sakis3g.png\"" debug run_command "${rmbin} -f \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\"" extension="png" else debug run_command "${mvbin} \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\" \"${runhome}/.local/share/icons/sakis3g.${extension}\"" debug run_command "${rmbin} -f \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\"" fi if [ -s "${runhome}/.local/share/icons/sakis3g.${extension}" ]; then debug run_command "${chownbin} ${runner} \"${runhome}/.local/share/icons/sakis3g.${extension}\"" debug run_command "${chmodbin} 644 \"${runhome}/.local/share/icons/sakis3g.${extension}\"" icon="${runhome}/.local/share/icons/sakis3g.${extension}" debug "Successfully installed icon to \"%s\".\n" "${runhome}/.local/share/icons/sakis3g.${extension}" fi else debug "File %s does not exist or is empty.\n" "/tmp/sakis3g.$$.${ISPID}_logo.${extension}" [ -f "/tmp/sakis3g.$$.${ISPID}_logo.${extension}" ] && debug run_command "${rmbin} -f \"/tmp/sakis3g.$$.${ISPID}_logo.${extension}\"" if [ -f "/usr/share/icons/gnome/scalable/status/nm-device-wireless.svg" ]; then debug "Selecting default GNOME icon.\n" icon="/usr/share/icons/gnome/scalable/status/nm-device-wireless.svg" else debug "Unable to locate any icon.\n" icon="" fi fi debug "Icon selected is: %s\n" "${icon}" shortcuttitle="Sakis3G" [ "a${DESKTOPICON}" = "aOPERATOR" ] && shortcuttitle="${statusproduct}" && [ "a${shortcuttitle}" = "a" ] && shortcuttitle="${statusname} Internet" [ "a${shortcuttitle}" = "a" ] && shortcuttitle="Sakis3G" commenttext=`format_text "Manages 3G internet connection and 3G USB modems"` ${catbin} > "${desktopdestination}/sakis3g.desktop" < /dev/null > /dev/null [ "a${helperpid}" != "a" ] && ! notrunning "${helperpid}" && ${killbin} -9 ${helperpid} 2> /dev/null > /dev/null if [ "a${balloons}" != "a" ] && [ "a${BALOONIZERPID}" != "a" -o "a${BALOONIZER}" != "a" ]; then [ "a${BALOONIZER}" != "a" ] && [ -f "${BALOONIZER}" ] && debug run_command "${rmbin} -f \"${BALOONIZER}\"" [ "a${BALOONIZERPID}" != "a" ] && ! notrunning "${BALOONIZERPID}" && debug run_command "${killbin} -1 ${BALOONIZERPID}" [ "a${BALOONIZERPID}" != "a" ] && ! notrunning "${BALOONIZERPID}" && debug run_command "${killbin} -9 ${BALOONIZERPID}" find_binary "ps" && tailpid=`${psbin} -A -o pid,command | ${grepbin} "${tailbin} -f ${BALOONIZER}" | ${grepbin} -v "${grepbin}" | ${cutbin} -d\ -f1` [ "a${tailpid}" != "a" ] && ! notrunning "${tailpid}" && debug run_command "${killbin} -1 ${tailpid}" [ "a${tailpid}" != "a" ] && ! notrunning "${tailpid}" && debug run_command "${killbin} -9 ${tailpid}" unset BALOONIZERPID; unset BALOONIZER fi } action_helper() { if ! find_binary "zenity"; then show_fmt_error "Unable to install tray icon to system notification area. You need to install %s.\n" "zenity" return 0 fi need_binary "kill" [ "a${PROVIDER}" = "a" ] && return 1 [ ! -x "${PROVIDER}" ] && return 1 if we_are_root_already && [ "a${MENU}" != "a" ]; then debug "Calling menu since state variable MENU is set.\n" action_menu "$@" unset MENU debug "MENU actor returned. Will now run as helper.\n" fi debug run_command "${rmbin} -f /tmp/sakis3g.helper.icon.red.$$.png /tmp/sakis3g.helper.icon.green.$$.png /tmp/sakis3g.helper.icon.yellow.$$.png" addexittrap helper_cleaner ${PROVIDER} getfile files/sakis3g.red.png > "/tmp/sakis3g.helper.icon.red.$$.png" 2> /dev/null ${PROVIDER} getfile files/sakis3g.green.png > "/tmp/sakis3g.helper.icon.green.$$.png" 2> /dev/null ${PROVIDER} getfile files/sakis3g.yellow.png > "/tmp/sakis3g.helper.icon.yellow.$$.png" 2> /dev/null if [ ! -s "/tmp/sakis3g.helper.icon.green.$$.png" ]; then debug "Failed to retrieve green/connected state icon.\n" return 1 elif [ ! -s "/tmp/sakis3g.helper.icon.red.$$.png" ]; then debug "Failed to retrieve red/no hardware state icon.\n" return 1 elif [ ! -s "/tmp/sakis3g.helper.icon.yellow.$$.png" ]; then debug "Failed to retrieve yellow/not connected state icon.\n" return 1 fi debug run_command "${chmodbin} 644 \"/tmp/sakis3g.helper.icon.red.$$.png\"" debug run_command "${chmodbin} 644 \"/tmp/sakis3g.helper.icon.green.$$.png\"" debug run_command "${chmodbin} 644 \"/tmp/sakis3g.helper.icon.yellow.$$.png\"" if [ "a${balloons}" != "a" ]; then # Establish balloon helper now that will be accessible from root session later if [ "a${BALOONIZER}" = "a" ]; then BALOONIZER="/tmp/sakis3g.baloon.pipe.$$" debug run_command "${rmbin} -f \"${BALOONIZER}\"" debug run_command "${touchbin} -f \"${BALOONIZER}\"" if [ -w "${BALOONIZER}" ]; then ${printfbin} "\n\n\n\n\nvisible:false\n" >> "${BALOONIZER}" export BALOONIZER eval ${tailbin} -f "${BALOONIZER}" "2> /dev/null" | ${zenitybin} --notification --listen > /dev/null 2> /dev/null & BALOONIZERPID=$!; eval "disown -a" > /dev/null 2> /dev/null export BALOONIZERPID ${printfbin} "visible:false\n" >> "${BALOONIZER}" ${printfbin} "visible:false\nvisible:false\n" >> "${BALOONIZER}" debug "Balloon pipe created. Location is \"%s\" and runs with PID %d.\n" "${BALOONIZER}" "${BALOONIZERPID}" else debug "Error while creating pipe for balloons.\n" debug run_command "${rmbin} -f \"${BALOONIZER}\"" unset BALOONIZER fi elif [ -w "${BALOONIZER}" ]; then debug "Will be using already existing balloon pipe: %s\n" "${BALOONIZER}" elif [ ! -w "${BALOONIZER}" ]; then debug "Balloons pipe \"%s\" exists but no write access granted.\n" "${BALOONIZER}" fi [ "a${BALOONIZER}" = "a" ] && debug "No balloons will be appearing.\n" fi debug "All set. Going into helper mode.\n" while [ "1" = "1" ] do if ppp_slow_status && status_connected; then helpertext="`translate_text "Connected"`" [ "a${statusname}" != "a" ] && helpertext="${statusname}" helperconnected=2 else usb_connected_modems if [ "a${usb_modem_devices}" != "a" ]; then helpertext="`translate_text "Not connected"`" helperconnected=1 helpermodems=`echo "${usb_modem_devices}" | ${cutbin} -d: -f3- | ${trbin} "\n" " "` else helpertext="`translate_text "No USB modem"`" helperconnected=0 fi fi # Check if something was changed not by us. Then balloon user. if [ "a${balloons}" != "a" ]; then if [ "a${BALOONIZER}" != "a" ] && [ "a${previousstatus}" != "a" -a "a${previousstatus}" != "a${helperconnected}" ]; then debug "Status changed. Not by us.\n" notificationtext=`translate_text "Notification"` if [ "a${helperconnected}" = "a2" ]; then iconpath="/tmp/sakis3g.helper.icon.green.$$.png" elif [ "a${helperconnected}" = "a1" ]; then iconpath="/tmp/sakis3g.helper.icon.yellow.$$.png" elif [ "a${helperconnected}" = "a0" ]; then iconpath="/tmp/sakis3g.helper.icon.red.$$.png" else iconpath="/tmp/sakis3g.helper.icon.yellow.$$.png" fi unset largetext; unset smalltext if [ "a${previousstatus}" = "a0" -a "a${helperconnected}" = "a1" ]; then largetext=`translate_text "USB Modem plugged"` smalltext=`format_text "USB Modem %s is now plugged on computer." "${helpermodems}"` elif [ "a${helperconnected}" = "a2" ]; then largetext=`translate_text "Connected"` if [ "a${MODEM_VARIANT}" != "a" -a "a${statusname}" != "a" ]; then smalltext=`format_text "Modem %s is now connected to %s." "${MODEM_VARIANT}" "${statusname}"` elif [ "a${MODEM_VARIANT}" != "a" ]; then smalltext=`format_text "Modem %s is now connected." "${MODEM_VARIANT}"` elif [ "a${statusname}" != "a" ]; then smalltext=`format_text "You are now connected to %s." "${statusname}"` else smalltext=`translate_text "Computer is now connected.\n"` fi elif [ "a${previousstatus}" = "a1" -a "a${helperconnected}" = "a0" ]; then largetext=`translate_text "USB Modem Unplugged"` smalltext=`translate_text "No USB modem is anymore plugged on computer."` elif [ "a${previousstatus}" = "a2" ]; then largetext=`translate_text "Disconnected"` if [ "a${helperconnected}" = "a0" ]; then smalltext=`translate_text "You were disconnected due to modem being unplugged."` elif [ "a${helperconnected}" = "a1" ]; then smalltext=`translate_text "You are now disconnected from operator."` fi fi debug "Will display baloon:\nIcon: %s\nTitle: %s\nMessage: %s\n" "${iconpath}" "${largetext}" "${smalltext}" if [ "a${smalltext}" != "a" -a "a${largetext}" != "a" ]; then ${printfbin} "icon:%s\n" "${iconpath}" >> "${BALOONIZER}" 2> /dev/null ${printfbin} "tooltip:%s\n" "${notificationtext}" >> "${BALOONIZER}" 2> /dev/null ${printfbin} "visible:true\n" >> "${BALOONIZER}" 2> /dev/null ${printfbin} "message:%s\\\n%s\n" "${largetext}" "${smalltext}" >> "${BALOONIZER}" 2> /dev/null ${printfbin} "visible:false\n" >> "${BALOONIZER}" 2> /dev/null fi unset iconpath; unset smalltext; unset largetext; unset notificationtext fi previousstatus="${helperconnected}" fi if [ "a${helpertext}" != "a${announcedtext}" -a "a${helperpid}" != "a" ] && ! notrunning "${helperpid}"; then [ "a${helperpid}" != "a" ] && ! notrunning "${helperpid}" && ${killbin} -1 ${helperpid} 2> /dev/null > /dev/null [ "a${helperpid}" != "a" ] && ! notrunning "${helperpid}" && ${killbin} -9 ${helperpid} 2> /dev/null > /dev/null notrunning "${helperpid}" && unset helperpid fi if [ "a${helperpid}" = "a" ]; then if [ "a${helperconnected}" = "a2" ]; then ${zenitybin} --notification --window-icon=/tmp/sakis3g.helper.icon.green.$$.png --text="${helpertext}" > /dev/null 2> /dev/null & elif [ "a${helperconnected}" = "a1" ]; then ${zenitybin} --notification --window-icon=/tmp/sakis3g.helper.icon.yellow.$$.png --text="${helpertext}" > /dev/null 2> /dev/null & elif [ "a${helperconnected}" = "a0" ]; then ${zenitybin} --notification --window-icon=/tmp/sakis3g.helper.icon.red.$$.png --text="${helpertext}" > /dev/null 2> /dev/null & else ${zenitybin} --notification --text="${helpertext}" > /dev/null 2> /dev/null & fi helperpid=$!; eval "disown -a" > /dev/null 2> /dev/null announcedtext="${helpertext}" export helperpid elif notrunning "${helperpid}"; then unset helperpid; unset previousstatus debug "User clicked on icon.\n" action_menu "$@"; ret=$? if [ "${ret}" -eq "98" ]; then if [ "a${forever}" != "a" ]; then debug "User selected exit on MENU. However, \"forever\" is set.\n" unset MENU; unset MOREMENU; else debug "User selected exit on MENU. Will ask for confirmation to exit.\n" #${zenitybin} --question --title="`translate_text "Confirm exit"`" --text="`translate_text "Exiting will also remove tray icon. Are you sure you want to exit Sakis3G?"`" #ret=$? #if [ "a${ret}" = "a0" ]; then if user_confirm "helperexit" "Confirm exit" "Exiting will also remove tray icon. Are you sure you want to exit Sakis3G?" "Yes" "No" "reset"; then debug "User confirmed he wants to exit. Helper will die.\n" break else debug "User did not confirm.\n" unset MENU; unset MOREMENU fi fi fi debug "Resuming helper operation.\n" else debug "Helper is sleeping for a second.\n" sleep 1 fi done helper_cleaner return 98 } # Method called when called as a helper to hold HAL lock action_holdlock() { unset verbosecurrentcount [ "a$2" != "a" ] && [ -f "$2" ] && checkfile="$2" && echo "$$" > "${checkfile}" unset TRAPS while [ "1" = "1" ] do if [ "a${PROVIDER}" = "a" ]; then ppppp=`ps -p $$ -o ppid=` else ppppp=`ps -p $$ -o ppid=` ppppp=`ps -p ${ppppp} -o ppid=` fi ppppp=`echo $ppppp` [ "a${ppppp}" = "a1" ] && exit 0 [ "a${ppppp}" = "a${PPID}" ] && exit 0 [ "a${checkfile}" != "a" ] && [ ! -f "${checkfile}" ] && exit 0 #echo $ppppp sleep 1 done } action_state() { unset verbosecurrentcount state_variables "SGUI interactive stick_to_console DEBUG LOCALAUTHORITY BALOONIZER" notify "To automatically repeat result of last action, use following command line:\n%s\n" "${ME} ${actors} ${statevariables}" return 0 } action_udevrule() { unset verbosecurrentcount state_variables "SGUI MODEM interactive stick_to_console USBMODEM OTHER DEBUG LOCALAUTHORITY BALOONIZER" # statevariables=`echo "${statevariables}" | ${sedbin} -e "s/\"/\\\\\\\\\"/g"` statevariables=`echo "${statevariables}" | ${sedbin} -e "s/\"//g"` unset content candidates="${MODEM}" [ "a${candidates}" = "aOTHER" ] && unset candidates [ "a${candidates}" = "aOTHER" -a "a${OTHER}" = "aUSBMODEM" -a "a${USBMODEM}" != "a" ] && candidates="${USBMODEM}" localactors=`echo ${actors}` for candidate in ${candidates} do modemvendor=`echo ${candidate} | ${cutbin} -d: -f1 -s` modemproduct=`echo ${candidate} | ${cutbin} -d: -f2 -s` if [ "a${modemvendor}" != "a" -a "a${modemproduct}" != "a" ]; then content=`${printfbin} "%s\nACTION==\"add\", SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%s\", ATTRS{idProduct}==\"%s\", ATTRS{bInterfaceNumber}==\"00\", RUN+=\"%s %s %s MODEM=OTHER OTHER=USBMODEM USBMODEM=%s:%s\"\n\n" "${content}" "${modemvendor}" "${modemproduct}" "${ME}" "${localactors}" "${statevariables}" "${modemvendor}" "${modemproduct}"` break; fi done unset localactors; unset modemvendor; unset modemproduct; unset candidate; unset candidates; unset statevariables term_clearline if [ "a${content}" != "a" ]; then format_text "To automatically repeat result of last action, immediately upon device connection, include following line within a %s file within \"%s\" directory:\n%s\n" ".rules" "/etc/udev/rules.d/" "${content}" else format_text "No USB modem was selected. No need for a udev example.\n" fi unset content return 0 } action_about() { unset verbosecurrentcount notify "%s\n" "`show_version`" return 0 } show_man() { destination="$1" case "a${destination}" in ausb_modeswitch|ausb-modeswitch) destination="dependencies/usb-modeswitch/usb_modeswitch.1" ;; asakis3g.conf) destination="man/sakis3g.conf.5" ;; *) destination="man/sakis3g.1" ;; esac debug "Destination man page is: %s\n" "${destination}" [ "a${PROVIDER}" = "a" ] && return 1 [ ! -x "${PROVIDER}" ] && return 1 need_binary "man" need_binary "rm" "${PROVIDER}" getfile "${destination}" > "/tmp/sakis3g.man.$$" debug "Will now display man page %s.\n" "${destination}" [ -s "/tmp/sakis3g.man.$$" ] && ${manbin} -l "/tmp/sakis3g.man.$$" ${rmbin} -f "/tmp/sakis3g.man.$$" return 0 } action_report() { unset verbosecurrentcount flow_report "$@" ret=$? if [ "a${ret}" = "a0" ]; then return 0 else return ${ret} fi } # Executes actor $1 with the arguments run_action() { actioncandidate=$1 [ "$#" -gt "0" ] && shift unset verbosecurrentcount newactors="${actors} ${actioncandidate}" case "${actioncandidate}" in about) action_about "$@" actionresult=$? ;; desktop) action_desktop "$@" actionresult=$? ;; helper) action_helper "$@" actionresult=$? ;; status) action_status "$@" actionresult=$? ;; connected) ppp_fast_status actionresult=$? ;; disconnected) if ppp_fast_status; then actionresult=99 else actionresult=0 fi ;; plugged) if usb_connected_modems; then actionresult=0 else actionresult=99 fi ;; unplugged) if usb_connected_modems; then actionresult=99 else actionresult=0 fi ;; switched) if usb_connected_modems; then if modeswitch_switchable_devices; then actionresult=99 else actionresult=0 fi else actionresult=0 fi ;; switchable) if modeswitch_switchable_devices; then actionresult=0 else actionresult=99 fi ;; wait|sleep) debug "Sleeping for 1 second.\n" sleep 1 actionresult=0 ;; info) action_info "$@" actionresult=$? ;; clicked) action_clicked "$@" actionresult=$? ;; modem|select) action_modem "$@" actionresult=$? ;; switchonly) action_switch "$@" actionresult=$? ;; setup) action_setup "$@" actionresult=$? ;; prepare|init) action_prepare "$@" actionresult=$? ;; connect|start) action_connect "$@" actionresult=$? ;; toggle) action_toggle "$@" actionresult=$? ;; reconnect|restart) action_reconnect "$@" actionresult=$? ;; disconnect|stop) action_disconnect "$@" actionresult=$? ;; more|moremenu|menumore) action_more "$@" actionresult=$? ;; menu) action_menu "$@" actionresult=$? ;; state) action_state "$@" actionresult=$? ;; udevrule) action_udevrule "$@" actionresult=$? ;; compile|recompile) action_compile "$@" actionresult=$? ;; report) action_report "$@" actionresult=$? ;; *) newactors="${actors}" unset actioncandidate actionresult=0 ;; esac actors="${newactors}" unset actioncandidate; unset newactors [ "a${actionresult}" = "a" ] && actionresult=99 return ${actionresult} } # Executes actors in the order defined action_command() { unset actors while [ "$#" -gt "0" ] do if [ "a${1}" = "anot" -o "a${1}" = "aNot" -o "a${1}" = "a!" ]; then [ "$#" -gt "0" ] && shift actors="${actors} not" run_action "$@" actionresult=$? if [ "${actionresult}" -eq "0" ]; then actionresult=99 debug "Actor \"%s\" returned %d, \"not\" operator instructs to abort.\n" "${1}" "${actionresult}" break else debug "Actor \"%s\" returned %d, but was inverted by \"not\" operator.\n" "${1}" "${actionresult}" actionresult=0 fi elif [ "a${1}" = "aignore" -o "a${1}" = "aIgnore" -o "a${1}" = "aignoring" -o "a${1}" = "aIgnoring" -o "a${1}" = "a|" ]; then [ "$#" -gt "0" ] && shift actors="${actors} ignore" run_action "$@" actionresult=$? if [ "${actionresult}" -ne "0" ]; then debug "Actor \"%s\" returned %d, \"ignore\" operator instructs to continue.\n" "${1}" "${actionresult}" actionresult=0 fi elif [ "a${1}" != "a" ] && ! run_action "$@"; then debug "Aborting execution chain due to actor \"%s\" returning %d.\n" "${1}" "${actionresult}" break fi [ "$#" -gt "0" ] && shift done unset arg actors=`echo ${actors}` if [ "a${actors}" = "a" ]; then debug "No actors defined.\n" unset actors return 1 else debug "Following actors executed: %s\n" "${actors}" unset actors return 0 fi } # Checks if arguments defined a dummy action and aborts if it does no_action_command() { for arg in $@ do case "$arg" in --help|help) unset arg if find_binary "fold"; then if [ "a${COLUMNS}" != "a" ]; then raw_help | ${foldbin} -s -w "${COLUMNS}" else raw_help | ${foldbin} -s -w "80" fi else raw_help fi return 0 ;; --version|version) unset arg show_version return 0 ;; --holdlock|holdlock) unset arg action_holdlock "$@" return 0 ;; usb_modeswitch) if [ "a${binaryfree}" != "a" ]; then show_fmt_error "You are running a binary free version of Sakis3G. This action is not available.\n" fi return 0 ;; man) if [ "a${stripped}" != "a" ]; then show_fmt_error "You are running a stripped version of Sakis3G. This action is not available.\n" else shift show_man "$@" fi unset arg return 0 ;; esac done unset arg return 1 } # When no actor defined, executes default actor of GUI selected. default_actor() { debug "Executing default actor for \"%s\".\n" "${SGUI}" if voodoo_mode; then debug "Voodoo actions will happen.\n" if action_connect "$@"; then actors="connect" action_state "$@" return $? else return $? fi fi case "${SGUI}" in whiptail|dialog|Xdialog|zenity|kdialog) action_menu "$@" return $? ;; "9menu") action_menu "$@" return $? ;; "interactive terminal") action_menu "$@" return $? ;; "terminal") show_help return $? ;; *) debug "No default actor for this GUI. Showing help.\n" show_help return $? ;; esac } voodoo_mode() { [ "a${voodoo}" != "a" ] && return 0 return 1 } guruplug_led() { if [ "a$1" = "anoexecute" ]; then noexecute=1 shift elif [ "a$1" = "aall" ]; then shift guruplug_leds "$@" return 0 else noexecute=0 fi ledcolor=""; ledname=""; othercolor=""; otherled=""; ledblink=""; ledon=""; ledoff="" for ledarg in "$@" do case "a${ledarg}" in ared|aRED|aRed|aR|ar|"a${redcolor}") ledcolor="${redcolor}" othercolor="${othercolor} ${greencolor}" ;; agreen|aGREEN|aGreen|aG|ag|"a${greencolor}") ledcolor="${greencolor}" othercolor="${othercolor} ${redcolor}" ;; ablack|aBLACK|aBlack|aB|ab|anone|aNONE|aNone|aN|an|aNO|aNo|ano|aReset|aRESET|areset) ledcolor="" othercolor="${othercolor} ${redcolor} ${greencolor}" ;; aorange|aOrange|aORANGE|aO|ao|ayellow|aYellow|aYellow|aY|ay|aBOTH|aBoth|aboth) ledcolor="${ledcolors}" othercolor="" ;; aleft|aLEFT|aLeft|aL|al|"a${leftled}") ledname="${leftled}" otherled="${otherled}" ;; aright|aRIGHT|aRight|"a${rightled}") ledname="${rightled}" otherled="${otherled}" ;; ablink|aBlink|aBLINK) ledblink=1; ;; anand|aNAND|assd|aSSD|adisk|aDISK|aDisk|aNand|aSsd|anand-disk|ananddisk|assddisk|assd-disk) ledblink=2; ;; ammc|ammc0|aMMC|aMmc|aMMC0|acard|aCard|aCARD) ledblink=3; ;; *) ledcheck=`expr ${ledarg} + 1 - 1 2> /dev/null` if [ "a${ledcheck}" = "a${ledarg}" ]; then if [ "a${ledon}" = "a" ]; then ledon="${ledarg}" elif [ "a${ledoff}" = "a" ]; then ledoff="${ledarg}" fi fi ;; esac done if [ "a${ledcolor}${othercolor}" = "a" -o "a${ledname}" = "a" ]; then unset noexecute; unset ledarg; unset ledcolor; unset ledname; unset othercolor; unset otherled; unset color; unset oled; unset ledcommand; unset ledblink; unset ledmode; unset ledon; unset ledoff; return 1 fi ledcommand="" for oled in ${otherled} do for color in ${ledcolors} do ledcommand="${ledcommand} echo \"none\" > \"${ledpath}/${color}:${oled}/trigger\";" ledcommand="${ledcommand} echo \"0\" > \"${ledpath}/${color}:${oled}/brightness\";" done done if [ "a${ledblink}" = "a1" ]; then unset othercolor ledmode="timer" [ "a${ledon}" = "a" ] && ledon=500 [ "a${ledoff}" = "a" ] && ledoff=500 if [ "a${ledcolor}" = "a" ]; then ttt="${ledon}"; ledon="${ledoff}"; ledoff="${ttt}"; unset ttt ledcheck=`guruplug_led_getstate "${ledname}" | ${grepbin} "_brightness=1" | ${sedbin} -e "s/^${ledname}_\(.*\)_brightness=1$/\1/g" | tr "\n" " "` ledcheck=`echo ${ledcheck}` for color in ${ledcolors} do colorname=`echo "${color}" | ${sedbin} -e "s/:/_/g"` if strinstr "${colorname}" "${ledcheck}" " "; then ledcolor="${ledcolor} ${color}" else othercolor="${othercolor} ${color}" fi done unset color; unset colorname; unset ledcheck fi [ "a${ledcolor}" = "a" ] && unset othercolor elif [ "a${ledblink}" = "a2" ]; then ledmode="nand-disk" elif [ "a${ledblink}" = "a3" ]; then ledmode="mmc0" else ledmode="none" fi for color in ${othercolor} do ledcommand="${ledcommand} echo \"none\" > \"${ledpath}/${color}:${ledname}/trigger\";" ledcommand="${ledcommand} echo \"0\" > \"${ledpath}/${color}:${ledname}/brightness\";" done if [ "a${ledcolor}" != "a" ]; then for color in ${ledcolor} do ledcommand="${ledcommand} echo \"${ledmode}\" > \"${ledpath}/${color}:${ledname}/trigger\";" [ "a${ledmode}" = "anone" ] && ledcommand="${ledcommand} echo \"1\" > \"${ledpath}/${color}:${ledname}/brightness\";" if [ "a${ledblink}" = "a1" ]; then ledcommand="${ledcommand} echo \"${ledon}\" > \"${ledpath}/${color}:${ledname}/delay_on\";" ledcommand="${ledcommand} echo \"${ledoff}\" > \"${ledpath}/${color}:${ledname}/delay_off\";" fi done unset color fi if [ "a${noexecute}" = "a1" ]; then echo "${ledcommand}" else unset LEDSCLEAN eval ${ledcommand} fi unset noexecute; unset ledarg; unset ledcolor; unset ledname; unset othercolor; unset otherled; unset color; unset oled; unset ledcommand; unset ledblink; unset ledmode; unset ledon; unset ledoff; return 0 } guruplug_leds() { ledscommands="" for ledi in ${allleds} do ledscommands="${ledscommands} `guruplug_led noexecute "${ledi}" "$@"`" done unset LEDSCLEAN eval ${ledscommands} unset ledscommands; unset ledi return 0 } guruplug_verbose() { [ "a${guruplug}" = "a" ] && return 0 if [ "a${gurucycle}" = "a" -o "a${gurucycle}" = "a0" ]; then gurucycle="1" led1="left" led2="right" elif [ "a${gurucycle}" = "a1" ]; then gurucycle="0" led1="right" led2="left" fi export gurucycle ledscommands="" ledscommands="${ledscommands} `guruplug_led noexecute ${led1} reset`" ledscommands="${ledscommands} `guruplug_led noexecute ${led2} reset`" ledscommands="${ledscommands} `guruplug_led noexecute ${led1} green`" ledscommands="${ledscommands} `guruplug_led noexecute ${led2} blink green`" eval ${ledscommands} unset led1; unset led2; unset ledscommands return 0 } guruplug_verbose_same() { [ "a${guruplug}" = "a" ] && return 0 if [ "a${gurucycle}" = "a" -o "a${gurucycle}" = "a0" ]; then led1="left" led2="right" elif [ "a${gurucycle}" = "a1" ]; then led1="right" led2="left" fi export gurucycle ledscommands="" ledscommands="${ledscommands} `guruplug_led noexecute ${led1} reset`" ledscommands="${ledscommands} `guruplug_led noexecute ${led2} reset`" ledscommands="${ledscommands} `guruplug_led noexecute ${led1} green`" ledscommands="${ledscommands} `guruplug_led noexecute ${led2} green`" ledscommands="${ledscommands} `guruplug_led noexecute ${led2} blink red`" eval ${ledscommands} unset led1; unset led2; unset ledscommands return 0 } guruplug_notify() { [ "a${guruplug}" = "a" ] && return 0 guruplug_leds black guruplug_leds blink green [ "a${interactive}" = "a" ] && sleep 5 } guruplug_error() { [ "a${guruplug}" = "a" ] && return 0 guruplug_leds black guruplug_leds blink red [ "a${interactive}" = "a" ] && sleep 5 } guruplug_led_exists() { [ "a${guruplug}" = "a" ] && return 1 [ "a$1" = "a" ] && return 1 for color in ${ledcolors} do [ ! -d "${ledpath}/${color}:$1" ] && return 1 done unset color return 0 } guruplug_led_getstate() { [ "a${guruplug}" = "a" ] && return 0 ! guruplug_led_exists "$@" && return 1 for color in ${ledcolors} do colorname=`echo ${color} | ${sedbin} -e "s/:/_/g"` for file in ${ledvariables} do if [ -r "${ledpath}/${color}:${1}/${file}" ]; then value=`${catbin} "${ledpath}/${color}:$1/${file}"` eval "$1_${colorname}_${file}=\"${value}\"" eval "export $1_${colorname}_${file}" else eval "unset $1_${colorname}_${file}" fi done value=`${catbin} "${ledpath}/${color}:$1/trigger" | ${sedbin} -e "s/^\(.*\)\[\(.*\)\]\(.*\)$/\2/g"` eval "$1_${colorname}_trigger=\"${value}\"" eval "export $1_${colorname}_trigger" [ "a${value}" != "anone" ] && eval "unset $1_${colorname}_brightness" done unset colorname; unset color; unset value; unset file; debug "Led $1 saved.\n" set | ${grepbin} "^$1_" return 0 } guruplug_state() { [ "a${guruplug}" = "a" ] && return 0 for ledi in ${allleds} do ! guruplug_led_getstate ${ledi} && return 1 done unset ledi debug "All leds are saved.\n" return 0 } guruplug_restore() { [ "a${guruplug}" = "a" ] && return 0 command="" for ledi in ${allleds} do for color in ${ledcolors} do colorname=`echo ${color} | ${sedbin} -e "s/:/_/g"` for file in trigger ${ledvariables} do value=`echo "$1" | ${grepbin} "^${ledi}_${colorname}_${file}=" | ${cutbin} -d= -f2- -s` if [ "a${value}" != "a" ]; then debug "echo \"${value}\" > \"${ledpath}/${color}:${ledi}/${file}\"\n" command="${command} echo \"${value}\" > \"${ledpath}/${color}:${ledi}/${file}\";" fi done done done unset LEDSCLEAN eval ${command} unset command unset value; unset file; unset colorname; unset color; unset ledi; return 0 } guruplug_restore_state() { [ "a${guruplug}" = "a" ] && return 0 [ "a${guruplug_original_state}" != "a" ] && guruplug_restore "${guruplug_original_state}" && debug "Original state of GuruPlug leds is now restored.\n" && return 0 debug "Failed to restore GuruPlug leds into original state.\n" return 1 } guruplug_save_state() { [ "a${guruplug}" = "a" ] && return 0 ! guruplug_state > /dev/null && return 1 guruplug_original_state=`guruplug_state` export guruplug_original_state addexittrap guruplug_restore_state debug "Original state of GuruPlug leds is saved.\n" return 0 } guruplug_probe() { [ "a${guruplug}" = "a" ] && return 1 [ ! -w "/sys/class/leds/guruplug:green:health/trigger" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:green:health/brightness" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:red:health/trigger" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:red:health/brightness" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:green:wmode/trigger" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:green:wmode/brightness" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:red:wmode/trigger" ] && unset guruplug [ ! -w "/sys/class/leds/guruplug:red:wmode/brightness" ] && unset guruplug if [ "a${guruplug}" = "a" ]; then debug "GuruPlug leds not found, or not accessible.\n" return 1 else ############################################## export ledpath="/sys/class/leds" ############################################## export redcolor="guruplug:red" export greencolor="guruplug:green" export ledcolors="${redcolor} ${greencolor}" ############################################## export leftled="health" export rightled="wmode" export allleds="${leftled} ${rightled}" ############################################## export ledvariables="brightness delay_off delay_on" ############################################## debug "GuruPlug leds found.\n" fi if ! guruplug_save_state; then unset guruplug debug "Failed to retrieve state of leds.\n" return 1 fi } config_args_read() { for arg in "$@" do debug "Parsing configuration value: %s.\n" "${arg}" parse_eval "readconfig" "${arg}" && continue parse_switches "${arg}" done unset arg } config_load() { # If no PIN supplied from command line and $HOME/.3gnet exists, use PIN from there. [ "a${SIM_PIN}" = "a" -a "a${runhome}" != "a" ] && [ -d "${runhome}" ] && [ -r "${runhome}/.3gpin" ] && SIM_PIN=`${headbin} -1 "${runhome}/.3gpin" 2> /dev/null | ${cutbin} -b1-4` && [ "a${SIM_PIN}" != "a" ] && export SIM_PIN && debug "Loaded PIN value from %s.\n" "${runhome}/.3gpin" && ! pin_valid "${SIM_PIN}" && unset SIM_PIN && debug "PIN supplied was not valid.\n" # Load PIN from system-wide PIN suppliers for pinsupplier in "/etc/default/3gpin" "/etc/sysconfig/3gpin" "/etc/3gpin" "/etc/default/sakis3g.3gpin" "/etc/sysconfig/sakis3g.3gpin" "/etc/sakis3g.3gpin" do [ -r "${pinsupplier}" ] && unset SIM_PIN && SIM_PIN=`${headbin} -1 "${pinsupplier}" 2> /dev/null | ${cutbin} -b1-4` && [ "a${SIM_PIN}" != "a" ] && export SIM_PIN && debug "Loaded PIN value from %s.\n" "${pinsupplier}" &&! pin_valid "${SIM_PIN}" && unset SIM_PIN && debug "PIN supplied was not valid.\n" done unset pinsupplier # If system-wide configuration exists, load it overriding anything (user configuration/arguments/everything) for configfile in "/etc/default/sakis3g" "/etc/sysconfig/sakis3g" "/etc/sakis3g.conf" do if [ -r "${configfile}" ]; then debug "Loading system-wide configuration file %s.\n" "${configfile}" debug show_file "${configfile}" configargs=`${grepbin} -v "^#" "${configfile}" | ${grepbin} -v "^$" | ${sedbin} -e "s/^\(.*\)$/\"\1\"/g" | ${sedbin} -e "s/^\"\([A-Za-z_]*\)=\"\(.*\)\"\"$/\"\1=\2\"/g" | ${trbin} "\n" " "` debug "Configuration arguments are: %s\n" "${configargs}" eval config_args_read ${configargs} unset configargs debug "Finished loading file %s.\n" "${configfile}" else debug "Configuration file %s does not exist or is not readable.\n" "${configfile}" fi done unset configfile debug "Configuration file(s) loaded.\n" } # Parses command line switch arguments parse_switch() { if [ "a$1" = "a$2" -o "a$1" = "a--$2" -o "a$1" = "a-$2" ]; then debug "Command line switch defined: %s\n" "$1" return 0 fi return 1 } # Parses command line variable settings parse_eval() { ! find_binary "cut" && return 1 ! find_binary "grep" && return 1 if [ "a$1" = "areadconfig" ]; then readconfig=1 shift [ "a$1" = "a" ] && unset readconfig && return 1 else readconfig=0 fi [ "a`echo "$1" | ${grepbin} "="`" = "a" ] && unset readconfig && return 1 variable=`echo "${1}" | ${cutbin} -d= -f1` [ "a${variable}" = "a" ] && unset variable && unset readconfig && return 1 value=`echo "${1}" | ${cutbin} -d= -f2-` [ "a${value}" = "a" ] && unset variable && unset value && unset readconfig && return 1 case "${variable}" in pppint|PPPINT) export pppint="${value}" ;; CHAT_ABORT_STRINGS) # Abort strings that chat program may encounter export CHAT_ABORT_STRINGS="${value}" ;; BAUD) # Baud rate if [ "a${value}" = "aMAX" -o "a${value}" = "amax" ]; then export BAUD="4000000" elif [ "a${value}" = "aMIN" -o "a${value}" = "amin" ]; then export BAUD="115200" elif [ "a${value}" = "aDEFAULT" -o "a${value}" = "adefault" -o "a${value}" = "aNORMAL" -o "a${value}" = "anormal" ]; then export BAUD="460800" else export BAUD="${value}" fi ;; PPPD_OPTIONS) # Options passed to pppd when called directly export PPPD_OPTIONS="${value}" ;; PPPD_PEERS) # Directory where pppd keeps its peers export PPPD_PEERS="${value}" ;; XOSDFONT) # Font that will be used when displaying messages through XOSD (osd_cat) export XOSDFONT="${value}" ;; AOSDFONT) # Font that will be used when displaying messages through XOSD (osd_cat) export AOSDFONT="${value}" ;; MENUFONT|menufont) # Font that will be used when using 9menu export MENUFONT="${value}" ;; OSDFONT) # Font that will be used when displaying messages through XOSD (osd_cat) export AOSDFONT="${value}" export XOSDFONT="${value}" ;; LOGPOSITION|logposition) # Directory where pppd keeps its peers export LOGPOSITION="${value}" ;; DESKTOPICON) # Directory where pppd keeps its peers export DESKTOPICON="${value}" ;; DCOPSERVER) # Directory where pppd keeps its peers export DCOPSERVER="${value}" ;; connection_hook|CONNECTION_HOOK|HOOK) # Enabling this is a security issue. # Users can pass argument to do whatever they want. if [ "a${readconfig}" = "a1" ]; then export CONNECTION_HOOK="${value}" else echo "Ignoring ${variable} variable for security reasons." > /dev/stderr echo "This variable is only usable through global configuration." > /dev/stderr echo "Consult documentation." > /dev/stderr fi ;; DNS) export DNS="${value}" ;; MODEM_PREPARE|PREPARE) export MODEM_PREPARE="${value}" INIT_STAGE0=`${printfbin} "%s\n" "${value}" | ${sedbin} -e "s/AT/\\nAT/g" | ${sedbin} -e "s/ *$//g" | ${grepbin} -v "^$" | ${grepbin} "^AT" | ${sedbin} -e "s/^\(.*\)$/\\\'\1\\\' OK/g" | ${trbin} "\n" " "` export INIT_STAGE0 ;; MODEM_INIT|INIT) export MODEM_INIT="${value}" ;; DIAL|CUSTOM_DIAL) export CUSTOM_DIAL="${value}" ;; FORCE_APN) export FORCE_APN="${value}" ;; CUSTOM_APN) export CUSTOM_APN="${value}" ;; APN) export APN="${value}" ;; APN_USER) export APN_USER="${value}" ;; APN_PASS) export APN_PASS="${value}" ;; FORCE_ISP) export FORCE_ISP="${value}" ;; SIM_PIN) export SIM_PIN="${value}" ;; RFCOMM_TTY) export RFCOMM_TTY="${value}" ;; CUSTOM_TTY) export CUSTOM_TTY="${value}" ;; RFSERVICE) export RFSERVICE="${value}" ;; RFCHANNEL) export RFCHANNEL="${value}" ;; UNDISCOVERABLE) export UNDISCOVERABLE="${value}" ;; BLUETOOTH) export BLUETOOTH="${value}" ;; USBINTERFACE) export USBINTERFACE="${value}" ;; USBDRIVER) export USBDRIVER="${value}" ;; USBMODEM) export USBMODEM="${value}" ;; OTHER) export OTHER="${value}" ;; MODEM) export MODEM="${value}" ;; MOREMENU) export MOREMENU="${value}" ;; MENU) export MENU="${value}" ;; DISPLAY) export DISPLAY="${value}" ;; XAUTHORITY|LOCALAUTHORITY) export LOCALAUTHORITY="${value}" ;; BALOONIZER|BALLOONIZER) export BALOONIZER="${value}" ;; DESKTOP) export DESKTOP="${value}" ;; SGUI) export SGUI="${value}" ;; TRANSLATION) export TRANSLATION="${value}" ;; *) debug "Unknown variable %s specified in command line.\n" "${variable}" unset variable ;; esac unset readconfig if [ "a${variable}" != "a" ]; then debug "Command line set variable %s to \"%s\".\n" "${variable}" "`eval echo \\\${${variable}}`" unset variable; unset value; return 0 fi unset variable; unset value return 1 } parse_switches() { parse_switch "${1}" "balloons" && export balloons=yes parse_switch "${1}" "balloon" && export balloons=yes parse_switch "${1}" "baloons" && export balloons=yes parse_switch "${1}" "baloon" && export balloons=yes parse_switch "${1}" "ballons" && export balloons=yes parse_switch "${1}" "ballon" && export balloons=yes parse_switch "${1}" "balons" && export balloons=yes parse_switch "${1}" "balon" && export balloons=yes parse_switch "${1}" "b" && export balloons=yes parse_switch "${1}" "console" && export stick_to_console=yes parse_switch "${1}" "stick_to_console" && export stick_to_console=yes parse_switch "${1}" "c" && export stick_to_console=yes parse_switch "${1}" "debug" && export DEBUG=on parse_switch "${1}" "DEBUG" && export DEBUG=on parse_switch "${1}" "d" && export DEBUG=on parse_switch "${1}" "NOSMART" && export NOSMART=yes parse_switch "${1}" "NOFIX" && export NOSMART=yes parse_switch "${1}" "nosmart" && export NOSMART=yes parse_switch "${1}" "nofix" && export NOSMART=yes parse_switch "${1}" "smart" && export NOSMART=yes parse_switch "${1}" "fix" && export NOSMART=yes parse_switch "${1}" "f" && export NOSMART=yes parse_switch "${1}" "GOOGLEDNS" && export DNS="8.8.8.8 8.8.4.4" parse_switch "${1}" "GOOGLE" && export DNS="8.8.8.8 8.8.4.4" parse_switch "${1}" "googledns" && export DNS="8.8.8.8 8.8.4.4" parse_switch "${1}" "google" && export DNS="8.8.8.8 8.8.4.4" parse_switch "${1}" "g" && export DNS="8.8.8.8 8.8.4.4" parse_switch "${1}" "GURUPLUG" && export guruplug=yes parse_switch "${1}" "guruplug" && export guruplug=yes parse_switch "${1}" "GURU" && export guruplug=yes parse_switch "${1}" "guru" && export guruplug=yes parse_switch "${1}" "G" && export guruplug=yes parse_switch "${1}" "nohal" && export nohal=yes parse_switch "${1}" "hal" && export nohal=yes parse_switch "${1}" "h" && export nohal=yes parse_switch "${1}" "interactive" && export interactive=yes parse_switch "${1}" "i" && export interactive=yes parse_switch "${1}" "killstorage" && export killstorage=yes parse_switch "${1}" "nostorage" && export killstorage=yes parse_switch "${1}" "storage" && export killstorage=yes parse_switch "${1}" "k" && export killstorage=yes parse_switch "${1}" "nohalinform" && export nohalinform=yes parse_switch "${1}" "noinform" && export nohalinform=yes parse_switch "${1}" "l" && export nohalinform=yes parse_switch "${1}" "NOPROBE" && export NOPROBEGSM=yes parse_switch "${1}" "NOPROBEGSM" && export NOPROBEGSM=yes parse_switch "${1}" "noprobe" && export NOPROBEGSM=yes parse_switch "${1}" "noprobegsm" && export NOPROBEGSM=yes parse_switch "${1}" "GSM" && export NOPROBEGSM=yes parse_switch "${1}" "gsm" && export NOPROBEGSM=yes parse_switch "${1}" "n" && export NOPROBEGSM=yes parse_switch "${1}" "prefer_osd" && export prefer_osd=yes parse_switch "${1}" "preferosd" && export prefer_osd=yes parse_switch "${1}" "osd" && export prefer_osd=yes parse_switch "${1}" "OSD" && export prefer_osd=yes parse_switch "${1}" "o" && export prefer_osd=yes parse_switch "${1}" "forever" && export forever=yes parse_switch "${1}" "persist" && export forever=yes parse_switch "${1}" "P" && export forever=yes parse_switch "${1}" "directpppd" && export direct_pppd=yes parse_switch "${1}" "direct_pppd" && export direct_pppd=yes parse_switch "${1}" "ppp" && export direct_pppd=yes parse_switch "${1}" "pppd" && export direct_pppd=yes parse_switch "${1}" "p" && export direct_pppd=yes parse_switch "${1}" "noverbose" && export noverbose=yes parse_switch "${1}" "noinformation" && export nonotify=yes parse_switch "${1}" "nonotifications" && export nonotify=yes parse_switch "${1}" "nonotify" && export nonotify=yes parse_switch "${1}" "noerrors" && export noerror=yes parse_switch "${1}" "noerror" && export noerror=yes if parse_switch "${1}" "silent" || parse_switch "${1}" "quiet" || parse_switch "${1}" "q"; then export noerror=yes export nonotify=yes export noverbose=yes fi parse_switch "${1}" "sudo" && export alwayssudo=yes parse_switch "${1}" "alwayssudo" && export alwayssudo=yes parse_switch "${1}" "always_sudo" && export alwayssudo=yes parse_switch "${1}" "s" && export alwayssudo=yes parse_switch "${1}" "showtext" && export showtext=yes parse_switch "${1}" "T" && export showtext=yes parse_switch "${1}" "notranslate" && export notranslate=yes parse_switch "${1}" "t" && export notranslate=yes parse_switch "${1}" "nosafety" && export nosafety=yes parse_switch "${1}" "unsafe" && export nosafety=yes parse_switch "${1}" "u" && export nosafety=yes parse_switch "${1}" "voodoo" && export voodoo=yes parse_switch "${1}" "please" && export voodoo=yes parse_switch "${1}" "magic" && export voodoo=yes parse_switch "${1}" "Voodoo" && export voodoo=yes parse_switch "${1}" "Please" && export voodoo=yes parse_switch "${1}" "Magic" && export voodoo=yes parse_switch "${1}" "v" && export voodoo=yes parse_switch "${1}" "whiptail" && export SGUI="whiptail" parse_switch "${1}" "dialog" && export SGUI="dialog" parse_switch "${1}" "Xdialog" && export SGUI="Xdialog" parse_switch "${1}" "xdialog" && export SGUI="Xdialog" parse_switch "${1}" "zenity" && export SGUI="zenity" parse_switch "${1}" "kdialog" && export SGUI="kdialog" parse_switch "${1}" "9menu" && export SGUI="9menu" parse_switch "${1}" "xterm" && export SGUI="xterm" parse_switch "${1}" "gnome-terminal" && export SGUI="gnome-terminal" parse_switch "${1}" "konsole" && export SGUI="konsole" parse_switch "${1}" "interactiveterminal" && export SGUI="interactive terminal" parse_switch "${1}" "iterm" && export SGUI="interactive terminal" parse_switch "${1}" "terminal" && export SGUI="terminal" parse_switch "${1}" "term" && export SGUI="terminal" if parse_switch "${1}" "legacy"; then export SGUI="9menu" export prefer_osd="yes" fi parse_switch "${1}" "scanyes" && export scanyes="1" parse_switch "${1}" "scanno" && export scanno="1" } state_variables() { unset statevariables for flagvariable in stick_to_console:console interactive:interactive DEBUG:debug NOSMART:nofix killstorage:nostorage NOPROBEGSM:noprobegsm prefer_osd:osd direct_pppd:pppd alwayssudo:sudo forever:forever balloons:balloons do variablename=`echo "${flagvariable}" | cut -d: -f1` strinstr "${variablename}" "${1}" " " && debug "Variable %s excluded from state variables.\n" "${variablename}" && continue variablearg=`echo "${flagvariable}" | cut -d: -f2` variablevalue=`eval echo \\\${${variablename}}` [ "a${variablevalue}" != "a" ] && statevariables="${statevariables} --${variablearg}" done unset flagvariable; unset variablename; unset variablearg; unset variablevalue [ "a${DNS}" = "a8.8.8.8 8.8.4.4" ] && statevariables="${statevariables} --googledns" [ "a${DNS}" != "a8.8.8.8 8.8.4.4" -a "a${DNS}" != "a" ] && statevariables="${statevariables} DNS=\"${DNS}\"" for valuevariable in MODEM_INIT FORCE_APN APN APN_USER APN_PASS FORCE_ISP SIM_PIN SGUI RFCOMM_TTY CUSTOM_TTY RFSERVICE RFCHANNEL UNDISCOVERABLE BLUETOOTH USBINTERFACE USBDRIVER USBMODEM OTHER MODEM MENU MOREMENU DISPLAY DESKTOP DCOPSERVER LOCALAUTHORITY BALOONIZER do strinstr "${valuevariable}" "${1}" " " && debug "Variable %s excluded from state variables.\n" "${valuevariable}" && continue variablevalue=`eval echo \\\${${valuevariable}}` [ "a${variablevalue}" != "a" ] && statevariables="${statevariables} ${valuevariable}=\"${variablevalue}\"" done unset valuevariable; unset variablevalue statevariables=`echo ${statevariables}` export statevariables debug "State variables are: %s\n" "${statevariables}" return 0 } # Parses command line arguments parse_arguments() { need_binary "tr" unset allargs for arg in "$@" do varg=`sanitize "${arg}"` allargs="${allargs} \"${varg}\"" parse_eval "${varg}" && continue parse_switches "${varg}" unset varg done unset arg allargs=`echo ${allargs}` export allargs } # Unsets binary variables if running as root. This eliminates the chance # that a malicious user has succeed into setting a "trojan" binary helper # that will be executed with root privileges. secure_path() { PATH="/bin:/sbin:/usr/bin:/usr/sbin" export PATH unset whichbin unset grepbin unset cutbin need_binary "grep" need_binary "cut" for variable in `set | ${grepbin} "bin=" | ${cutbin} -d= -f1` do value=`eval echo \\${${variable}} 2> /dev/null` if [ "a${value}" != "a" ] && [ -x "${value}" ]; then eval "unset ${variable}" debug "Unset variable %s for security reasons.\n" "${variable}" fi done unset variable; unset value return 0 } # Removes \, ", ', ` from variables' contents secure_variables() { need_binary "sed" need_binary "tr" for variable in DISPLAY XAUTHORITY USERNAME HOME USER DESKTOP do debug "Sanitizing %s: %s\n" "${variable}" "`eval echo \"\\${${variable}}\"`" value=`eval "echo \"\\${${variable}}\"" 2> /dev/null | ${trbin} "\\\\" " " 2> /dev/null | ${trbin} "\"" " " | ${trbin} "'" " " | ${trbin} "\\\`" " "` debug "Sanitized value: %s\n" "${value}" eval "${variable}=\"""${value}""\"" eval "${variable}=\"`eval echo \"\\${${variable}}\"`\"" eval "export ${variable}" debug "Sanitized %s: %s\n" "${variable}" "`eval echo \"\\${${variable}}\"`" done unset value; unset variable return 0 } secure_capabilities() { debug "Will check shell capabilities.\n" set +o monitor > /dev/null 2> /dev/null set +m > /dev/null 2> /dev/null funcname=`set | grep "^FUNCNAME="` if [ "a${funcname}" = "a" ]; then debug "Shell does not provide FUNCNAME environment variable.\n" debug "USB Safety will be disabled.\n" export NOFUNCNAME="1" unset YESFUNCNAME="" else debug "Shell provides FUNCNAME environment variable.\n" unset NOFUNCNAME export YESFUNCNAME="1" fi unset funcname return 0 } # Makes sure no danger exists when run as root secure_environment() { secure_capabilities ! we_are_root_already && return 0 secure_path secure_variables return 0 } # Preparation or death startup() { # try to set shell as helpful as possible with background jobs secure_environment addexittrap cleanscreen me=$1; [ "$#" -gt "0" ] && shift # Draftly set allargs. Will better do it during parse_arguments allargs="$@"; export allargs no_action_command "$@" && stop_with 0 verbose "Starting up" parse_arguments "$@" debug_header "$@" resolv_binaries "${me}"; unset me check_udevd "$@" find_user config_load find_display find_gui translate_load check_root_deps modeswitch_load guruplug_probe debug "Finished starting up.\n" } # Main program sakis3g_main() { # Initialization startup "$@" # Get action action_command "$@" && stop_with ${actionresult} default_actor ret=$? stop_with ${ret} } # Execute main method sakis3g_main $0 "$@" # In case all actors performed well debug "Reached end of program.\n" stop_with 0