#!/bin/bash
# wlcardconfig - A light-weight text-based wireless configuration tool.
# Rewritten from scratch by Klaus Knopper Feb. 2007
# messages based on Eckhard Rggeberg's version from 2005.

PATH="/bin:/sbin:/usr/bin:/usr/sbin"
export PATH

XDIALOG_HIGH_DIALOG_COMPAT=1
export XDIALOG_HIGH_DIALOG_COMPAT

[ "`id -u`" != "0" ] && exec sudo "$0" "$@"

TMP="/tmp/wlcardconfig.tmp$$"
CONFIGFILEBASE="/etc/sysconfig/wireless"

bailout(){
 rm -f "$TMP"
 exit $1
}

# Simple shell grep
stringinfile(){
 case "$(cat $2)" in *$1*) return 0;; esac
 return 1
}

# Clear/Defaults
DEVICE=""
MODEL=""
IWCONFIG_BASE_KEYS=(MODE ESSID KEY)
MODE="managed"
ESSID=""
KEY="off"
IWCONFIG_EXTENDED_KEYS=(CHANNEL FREQ NWID) 
CHANNEL=""
FREQ=""
NWID=""
IWCONFIG_KEYS=("${IWCONFIG_BASE_KEYS[@]}" "${IWCONFIG_EXTENDED_KEYS[@]}")
WPA_KEYS=(WPADRIVER WPAPASSWORD)
WPADRIVER=""
WPAPASSWORD=""

KNOPPIX_MAGIC="Managed by KNOPPIX."

WPACONFIGFILE="/etc/wpa_supplicant.conf"

WPACONFIG_BASE="# Minimal $WPACONFIGFILE.
# $KNOPPIX_MAGIC
#  Please see 
#  /usr/share/doc/wpasupplicant/examples/README.wpa_supplicant.conf.gz
#  for more complete configuration parameters.
#
# Also see the other files in /usr/share/doc/wpasupplicant/examples/ for
#  specific configuration examples.

# path to UNIX socket control interface
ctrl_interface=/var/run/wpa_supplicant
"

WPACONFIG_OPEN="### Associate with any open access point
###  Scans/ESSID changes can be done with wpa_cli
network={
        key_mgmt=NONE
}"

WPACONFIG_PSK="### Example of basic WPA-PSK secured AP
network={
    @@SSID@@
    @@PSK@@
}"

getessid_list(){
 ESSID_LIST=()
 count=0
 while read line; do
  case "$line" in ESSID:*)
   essid="${line#ESSID:\"}"
   essid="${essid%\"}"
   if [ -n "$essid" -a "$essid" != "<hidden>" ]; then
    ESSID_LIST[$((count++))]="$essid"
    ESSID_LIST[$((count++))]=""
   fi
  esac
 done <<EOT
$(iwlist "$1" scanning 2>/dev/null)
EOT
}

# readconfig configfile
readconfig(){
 MODE="managed"
 ESSID=""
 KEY="off"
 CHANNEL=""
 FREQ=""
 NWID=""
 WPADRIVER=""
 WPAPASSWORD=""

 [ -r "$1" ] && . "$1" || return 0
}
  
# writeconfig configfile
writeconfig(){
 rm -f "$1"
 for key in "${IWCONFIG_KEYS[@]}" "${WPA_KEYS[@]}"; do
  echo "$key=\"${!key}\""
 done > "$1"
 if [ -n "${WPADRIVER}" ]; then
  if [ -r "$WPACONFIGFILE" ] && ! stringinfile "$KNOPPIX_MAGIC" "$WPACONFIGFILE" ; then
   # Move away Distribution-supplied config file
   mv -f "$WPACONFIGFILE" "$WPACONFIGFILE".distrib
  fi
  if [ -n "${WPAPASSWORD}" ]; then 
   WPACONFIG="${WPACONFIG_PSK/@@PSK@@/psk=\"${WPAPASSWORD}\"}"
   [ -n "${ESSID}" -a "${ESSID}" != "any" ] && WPACONFIG="${WPACONFIG/@@SSID@@/ssid=\"${ESSID}\"}" || WPACONFIG="${WPACONFIG/@@SSID@@/}"
  else
   WPACONFIG="$WPACONFIG_OPEN"
  fi
  cat >"$WPACONFIGFILE" <<EOT
$WPACONFIG_BASE
$WPACONFIG
EOT
 fi
}

# There must be a better way to do this in bash :-(
tolower(){
 echo "$*" | tr '[:upper:]' '[:lower:]'
}

# setconfig
setconfig(){
 [ -n "${DEVICE}" ] || return 1
 ifconfig "${DEVICE}" up
 for key in "${IWCONFIG_BASE_KEYS[@]}"; do
  # These options MUST be set, even if empty.
  iwconfig "${DEVICE}" "$(tolower "$key")" "${!key}"
 done
 for key in "${IWCONFIG_EXTENDED_KEYS[@]}"; do
  # These options are optional.
  [ -n "${!key}" ] && iwconfig "${DEVICE}" "$(tolower "$key")" "${!key}"
 done
 if [ -n "${WPADRIVER}" -a -r "$WPACONFIGFILE" ]; then
  wpa_cli -i"${DEVICE}" terminate >/dev/null 2>&1
  wpa_supplicant -i"${DEVICE}" -D"${WPADRIVER}" -c"$WPACONFIGFILE" -Bw
 fi
}

# getcardinfo device
getcardinfo(){
 INFO="Unknown Wireless Card"
 v="$(cat "/sys/class/net/$1/device/vendor" 2>/dev/null)"
 d="$(cat "/sys/class/net/$1/device/device" 2>/dev/null)"
 if [ -n "$v" -a -n "$d" ]; then
  while read a b; do
   case "$a" in Device:) INFO="${b}" ;; esac
  done <<EOT
$(LANG=C LC_MESSAGES=C lspci -d "$v":"$d" -m -v 2>/dev/null)
EOT
 fi
 echo "$INFO"
 return 0
}

ICON="/usr/share/icons/crystalsvg/48x48/apps/knoppix-penguin.xpm"
[ -r "$ICON" ] && ICON="--icon $ICON" || ICON=""

DIALOG="dialog"
[ -n "$DISPLAY" ] && type Xdialog >/dev/null 2>&1 && DIALOG="Xdialog $ICON"

# Language-specific messages
[ -f /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n

case "$LANGUAGE" in
    de|at|ch)
	TITLE="Wireless-Konfiguration"
	MESSAGE0="Keine Wireless-Netzwerkkarte gefunden."
	MESSAGE1="Konfiguration der Wireless-Parameter von"
	MESSAGE2="Bitte Wireless-Adapter auswhlen"
	MESSAGE3="Bitte konfigurieren Sie vorher die IP-Parameter der Karte!"
	MESSAGE4A="Bitte whlen Sie ein Netzwerk (ESSID) aus."
	MESSAGE4="Geben Sie die ESSID fr"
	MESSAGE5="ein\n\n\n(leer fr 'any')\n"
	MESSAGE6="Geben Sie ggf. die NWID (Cell Identifier)\nfr"
	MESSAGE7="ein, falls es eine gibt\n\n\n"
	MESSAGE8="Geben Sie den Modus fr"
	MESSAGE9="ein\n\n(Managed(=default), Ad-Hoc, Master,\nRepeater, Secondary, auto)\n"
	MESSAGE10="Geben Sie den Kanal fr"
	MESSAGE11="ein\n\n(0 bis 16, leer fr auto oder Frequenz-\neingabe im nchsten Fenster)\n"
	MESSAGE12="Geben Sie die Frequenz fr"
	MESSAGE13="ein\n\n(z.B. 2.412G, leer fr auto)"
	MESSAGE14="Geben Sie den Verschlsselungs-Key\nfr"
	MESSAGE15="ein\nBeispiele: s:passwort, oder 0123ABCDEF fr HEX\n(leer fr Klartext)"
	MESSAGE16="Geben Sie ggf. zustzliche Parameter fr\n'iwconfig"
	MESSAGE17="' ein, z.B.\n\n\nsens -80  rts 512  frag 512  rate 5.5M"
	MESSAGE18="Geben Sie den fr diese Karte gewnschten WPA/WPA2-Treiber an"
	MESSAGE19="Geben Sie den WPA/WPA2-\"Shared Key\" ein"
	OPTION_EXPERT="Weitere (Experten-) Optionen"
	OPTION_NORMAL="(Experten-) Optionen verstecken"
	OPTION_WPA="WPA/WPA2 Einstellungen"
	CONNECT="Aktivieren/Verbinden"
	BACK="Zurck"
	SELECT="Auswhlen"
	QUIT="Beenden"
	MANUAL="Manuell"
	NWC="Adapter:"
	;;
    es)
	TITLE="Configuracin inalmbricos"
	MESSAGE0="No se ha encontrado una tarjeta inalmbrica."
	MESSAGE1="Configuracin de los parmetros inalmbricos para"
	MESSAGE2="Por favor, seleccione un dispositivo de red inalmbrico"
	MESSAGE3="Por favor, configure primero los parmetros de la IP para la interfaz"
	MESSAGE4A="Teclee el ESSID para"
	MESSAGE4="Teclee el ESSID para"
	MESSAGE5="\n\n\n(vaco para 'cualquiera')\n"
	MESSAGE6="Teclee el NWID (identificador de celda)\npara"
	MESSAGE7=", si es necesario\n\n\n"
	MESSAGE8="Teclee el modo para"
	MESSAGE9="\n\n(Managed(=por_defecto), Ad-Hoc, Master,\nRepeater, Secondary, auto)\n"
	MESSAGE10="Teclee el nmero del canal para"
	MESSAGE11="\n\n(0 bis 16, vaco para auto o si lo prefiere\n teclee la frecuencia seguidamente)\n"
	MESSAGE12="Teclee la frecuencia para"
	MESSAGE13="\n\n(ej. 2.412G, vaco para auto)"
	MESSAGE14="Teclee la clave de encriptacin\npara"
	MESSAGE15="\n\n(vaco para texto plano)"
	MESSAGE16="Teclee los parmetros adicionales para\n'iwconfig"
	MESSAGE17="' Si es necesario, ej.\n\n\nsens -80  rts 512  frag 512  rate 5.5M"
	MESSAGE18="Teclee la clave de encriptacin WPA/WPA2"
	MESSAGE19="Teclee la 'Driver' para WPA/WPA2"
	OPTION_EXPERT="More (expert) options"
	OPTION_NORMAL="Hide expert options"
	OPTION_WPA="WPA/WPA2 parmetros"
	CONNECT="Configuracin"
	BACK="Vuelva"
	SELECT="Selecto"
	QUIT="Parado"
	NWC="tarjeta de red:"
	MANUAL="Configuracin"
	;;
    *)
    	TITLE="Wireless Configuration"
	MESSAGE0="No wireless network card found."
	MESSAGE1="Configuration of wireless parameters for"
	MESSAGE2="Please select wireless network device"
	MESSAGE3="Please configure IP parameters of the interface first"
	MESSAGE4A="Please select a network (ESSID)"
	MESSAGE4="Enter the ESSID for"
	MESSAGE5="\n\n\n(empty for 'any')\n"
	MESSAGE6="Enter the NWID (cell identifier)\nfor"
	MESSAGE7=", if needed\n\n\n"
	MESSAGE8="Enter the mode for"
	MESSAGE9="\n\n(Managed(=default), Ad-Hoc, Master,\nRepeater, Secondary, auto)\n"
	MESSAGE10="Enter channel number for"
	MESSAGE11="\n\n(0 bis 16, empty for auto or if you want to\n enter the frequency next)\n"
	MESSAGE12="Enter the frequency for"
	MESSAGE13="\n\n(e.g 2.412G, empty for auto)"
	MESSAGE14="Enter the encryption key\nfor"
	MESSAGE15="\nExamples: s:password or 01234ABCDEF for hex\n(empty for cleartext)"
	MESSAGE16="Enter additional parameters for\n'iwconfig"
	MESSAGE17="' if needed, e.g.\n\n\nsens -80  rts 512  frag 512  rate 5.5M"
	MESSAGE18="Specify desired WPA/WPA2 driver for this card"
	MESSAGE19="Enter \"Shared Key\" for WPA/WPA2"
	OPTION_EXPERT="More (expert) options"
	OPTION_NORMAL="Hide expert options"
	OPTION_WPA="WPA/WPA2 parameters"
	CONNECT="Set/Connect"
	BACK="Back"
	SELECT="Select"
	QUIT="Quit"
	MANUAL="Manual"
	NWC="network card:"
	;;
esac

# MAIN

# unset if non-expert
EXPERT=""

# If given as parameter and being a wireless device, chose $1.
if [ "$1" -a -d "/sys/class/net/$1/wireless" ]; then
 DEVICE="$1"
else # select from list.
 while [ -z "${DEVICE}" ]; do
  MENU_CARDS=()
  count=0
  # Build card array
  for dev in /sys/class/net/*; do
   if [ -d "$dev/wireless" ]; then
    MENU_CARDS[$((count++))]="${dev##*/}"
    MENU_CARDS[$((count++))]="$(getcardinfo ${dev##*/})"
   fi
  done
  if [ -z "${MENU_CARDS[*]}" ]; then
   $DIALOG --title "$TITLE" --msgbox "$MESSAGE0" 10 65
   bailout
  fi
  if [ "$count" -le 2 ]; then # Only 1 card
   DEVICE="${MENU_CARDS[0]}"
  else
   $DIALOG --title "$TITLE" --ok-label "$SELECT" --cancel-label "$QUIT" --menu "$MESSAGE2" 15 65 10 "${MENU_CARDS[@]}" 2>"$TMP" || bailout
   read DEVICE <"$TMP" ; rm -f "$TMP"
  fi
  [ -n "${DEVICE}" ] && MODEL="$(getcardinfo "${DEVICE}")"
 done
fi

# Configfile name is /etc/sysconfig/wireless_devicename
CONFIGFILE="${CONFIGFILEBASE}_${DEVICE}"

# Get last saved values.
readconfig "$CONFIGFILE"

# Stay in main menu until user quits
while true; do

MENU_BASE=( "MODE:" "${MODE}" "ESSID:" "${ESSID:-any}" "WEP KEY:" "${KEY:+***}" "WPA:" "${OPTION_WPA}" )
MENU_EXPERT=( "${MENU_BASE[@]}" "NETWORK ID:" "${NWID}" "FREQ:" "${FREQ}" "CHANNEL:" "${CHANNEL}" )

 if [ -n "$EXPERT" ]; then
  MAINMENUHEIGHT1=21
  MEINMENUHEIGHT2=13
  MAINMENU=( "${MENU_EXPERT[@]}" "IP:" "${CONNECT}" "EASY" "${OPTION_NORMAL}" )
 else
  MAINMENUHEIGHT1=16
  MEINMENUHEIGHT2=8
  MAINMENU=( "${MENU_BASE[@]}" "IP:" "${CONNECT}" "EXPERT" "${OPTION_EXPERT}" )
 fi
  
 $DIALOG --title "$TITLE" --ok-label "$SELECT" --cancel-label "$QUIT" --menu "${NWC} ${DEVICE} (${MODEL})" "$MAINMENUHEIGHT1" 65 "$MAINMENUHEIGHT2" "${MAINMENU[@]}" 2>"$TMP" || bailout
 read SELECTION <"$TMP" ; rm -f "$TMP"

 case "${SELECTION}" in
  IP:) netcardconfig "$DEVICE" ;;
  MODE:) $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE8 $DEVICE $MESSAGE9" 15 50 "$MODE" 2>"$TMP" && { read t <"$TMP" ; MODE="${t:-managed}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
  ESSID:) getessid_list "$DEVICE" ; rm -f "$TMP"
          if [ -n "${ESSID_LIST[*]}" ]; then
	   $DIALOG --title "$TITLE" --cancel-label "$MANUAL" --ok-label "$SELECT" --menu "$MESSAGE4A"  16 65 8 "${ESSID_LIST[@]}" 2>"$TMP"
	  fi
	  t=""
	  [ -r "$TMP" ] && read t <"$TMP" ; rm -f "$TMP"
	  if [ -z "$t" ]; then
           $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE4 $DEVICE $MESSAGE5" 15 50 "$ESSID" 2>"$TMP"
	  fi
	  { [ -r "$TMP" ] && read t <"$TMP" ; ESSID="${t:-any}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
  WEP\ KEY:) $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE14 $DEVICE $MESSAGE15" 15 50 "$KEY" 2>"$TMP" && { read t <"$TMP" ; KEY="${t:-off}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
  NETWORK\ ID:) $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE6 $DEVICE $MESSAGE7" 15 50 "$NWID" 2>"$TMP" && { read t <"$TMP" ; NWID="${t}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
  CHANNEL:) $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE10 $DEVICE $MESSAGE11" 15 50 "$CHANNEL" 2>"$TMP" && { read t <"$TMP" ; CHANNEL="${t}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
  FREQ:) $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE12 $DEVICE $MESSAGE13" 15 50 "$FREQ" 2>"$TMP" && { read t <"$TMP" ; FREQ="${t}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
  EXPERT) EXPERT="true"; continue ;;
  EASY) EXPERT=""; continue ;;
  WPA:)
    while true; do
     MENU_WPA=( "WPA DRIVER:" "${WPADRIVER}" "WPA SHARED KEY:" "${WPAPASSWORD:+***}" )
     MENU_WPADRIVERS=( off      "NO WPA" \
                       wext     "*** Linux wireless extensions (recommended) ***" \
                       hostap   "Host AP driver (Intersil Prism2/2.5/3)" \
                       hermes   "(Hermes-I/Hermes-II)" \
                       madwifi  "MADWIFI 802.11 support (Atheros, etc.)" \
                       atmel    "ATMEL AT76C5XXx (USB, PCMCIA)" \
                       ndiswrapper "Linux ndiswrapper" \
	               broadcom "Broadcom driver" \
                       wired    "Wired Ethernet driver" \
                       bsd      "BSD 802.11 support (Atheros, etc.)" \
                       ndis     "Windows NDIS driver")

     $DIALOG --title "$TITLE" --ok-label "$SELECT" --cancel-label "$BACK" --menu "${OPTION_WPA}" 11 65 5 "${MENU_WPA[@]}" 2>"$TMP" || break 1
     read SELECTION2 <"$TMP" ; rm -f "$TMP"
     case "${SELECTION2}" in
      WPA\ DRIVER:) $DIALOG --title "$TITLE" --ok-label "$SELECT" --cancel-label "$BACK" --menu "$MESSAGE18" 21 65 17 "${MENU_WPADRIVERS[@]}" 2>"$TMP" && { read t <"$TMP" ; [ "$t" = "off" ] && WPADRIVER="" || WPADRIVER="${t}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
      WPA\ SHARED\ KEY:) $DIALOG --title "$TITLE" --cancel-label "$BACK" --inputbox "$MESSAGE19" 15 50 "$WPAPASSWORD" 2>"$TMP" && { read t <"$TMP" ; WPAPASSWORD="${t}"; writeconfig "${CONFIGFILE}"; setconfig; } ; rm -f "$TMP" ;;
     esac
    done ;;
 esac
done
