summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJouke Witteveen <j.witteveen@gmail.com>2012-12-28 02:38:58 +0100
committerJouke Witteveen <j.witteveen@gmail.com>2012-12-28 02:38:58 +0100
commit4e457e0efd0e5fd5df24c7e9ed63b02d0196ea8d (patch)
tree09580c92ca78e8b9b54d7ed8d6b79d7fcd6fd9ff /src
parent6737a37e5666837a8f51a2f74bdebdd756151394 (diff)
downloadnetctl-4e457e0efd0e5fd5df24c7e9ed63b02d0196ea8d.tar.gz
netctl-4e457e0efd0e5fd5df24c7e9ed63b02d0196ea8d.tar.xz
Forking netcfg to netctl (1/2)
This commit contains the moving of files.
Diffstat (limited to 'src')
-rw-r--r--src/connections/openvpn52
-rw-r--r--src/connections/ppp31
-rwxr-xr-xsrc/hooks/fancy90
-rwxr-xr-xsrc/hooks/initscripts35
-rwxr-xr-xsrc/ifplugd.action49
-rw-r--r--src/lib/8021x (renamed from src/8021x)0
-rwxr-xr-xsrc/lib/auto.action56
-rw-r--r--src/lib/connections/README28
-rw-r--r--src/lib/connections/bond (renamed from src/connections/bond)0
-rw-r--r--src/lib/connections/bridge (renamed from src/connections/bridge)0
-rw-r--r--src/lib/connections/ethernet (renamed from src/connections/ethernet)0
-rw-r--r--src/lib/connections/pppoe (renamed from src/connections/pppoe)0
-rw-r--r--src/lib/connections/tunnel (renamed from src/connections/tunnel)0
-rw-r--r--src/lib/connections/tuntap (renamed from src/connections/tuntap)0
-rw-r--r--src/lib/connections/vlan (renamed from src/connections/vlan)0
-rw-r--r--src/lib/connections/wireless (renamed from src/connections/wireless)0
-rw-r--r--src/lib/globals (renamed from src/globals)0
-rw-r--r--src/lib/network (renamed from src/network)0
-rw-r--r--src/lib/rfkill (renamed from src/rfkill)0
-rwxr-xr-xsrc/netctl106
-rwxr-xr-xsrc/netctl-auto87
-rwxr-xr-xsrc/wifi-menu263
22 files changed, 589 insertions, 208 deletions
diff --git a/src/connections/openvpn b/src/connections/openvpn
deleted file mode 100644
index 170d582..0000000
--- a/src/connections/openvpn
+++ /dev/null
@@ -1,52 +0,0 @@
-#! /bin/bash
-# Originally contributed by Thomas Jost: https://bugs.archlinux.org/task/21490
-
-. /usr/lib/network/network
-
-openvpn_up() {
- load_profile "$1"
- [[ -z "$OVPN_CONFIG" ]] && OVPN_CONFIG="/etc/openvpn/openvpn.conf"
- [[ -z "$OVPN_PID_FILE" ]] && OVPN_PID_FILE="/run/openvpn-$1.pid"
- [[ -z "$OVPN_FLAGS" ]] && OVPN_FLAGS=""
-
- OVPN_CONF_DIR="`dirname $OVPN_CONFIG`"
- OVPN_CONF_FILE="`basename $OVPN_CONFIG`"
-
- /usr/sbin/openvpn --writepid $OVPN_PID_FILE --daemon --cd "$OVPN_CONF_DIR" --config "$OVPN_CONF_FILE" $OVPN_FLAGS
-
- if [[ $? -ne 0 ]]; then
- report_fail "OpenVPN connection failed"
- exit 1
- fi
-
- # Generate a new resolv.conf
- if [[ -n "$DNS" ]]; then
- [[ -e /etc/resolv.conf ]] && cp /etc/resolv.conf /tmp/openvpn-$1-resolv.conf
- : >/etc/resolv.conf
- [[ -n "$DOMAIN" ]] && echo "domain $DOMAIN" >>/etc/resolv.conf
- [[ -n "$SEARCH" ]] && echo "search $SEARCH" >>/etc/resolv.conf
- for dns in "${DNS[@]}"; do
- echo "nameserver $dns" >>/etc/resolv.conf
- done
- for dnsoption in "${DNS_OPTIONS[@]}"; do
- echo "options $dnsoption" >>/etc/resolv.conf
- done
- fi
-}
-
-openvpn_down() {
- load_profile "$1"
- [[ -z "$OVPN_PID_FILE" ]] && OVPN_PID_FILE="/run/openvpn-$1.pid"
-
- kill $(head -1 $OVPN_PID_FILE)
- rm $OVPN_PID_FILE
-
- # Restore an old resolv.conf
- if [[ -e /tmp/openvpn-$1-resolv.conf ]]; then
- mv -f /tmp/openvpn-$1-resolv.conf /etc/resolv.conf
- fi
-}
-
-openvpn_$1 "$2"
-exit $?
-# vim: ft=sh ts=4 et sw=4:
diff --git a/src/connections/ppp b/src/connections/ppp
deleted file mode 100644
index da0fd6f..0000000
--- a/src/connections/ppp
+++ /dev/null
@@ -1,31 +0,0 @@
-#! /bin/bash
-. /usr/lib/network/network
-
-
-ppp_up() {
- load_profile "$1"
- [[ -z "$PEER" ]] && PEER="provider"
- [[ -z "$PPP_TIMEOUT" ]] && PPP_TIMEOUT=30
-
- /usr/sbin/pppd call "$PEER" updetach child-timeout "$PPP_TIMEOUT" linkname "$PEER"
-
- if [[ $? -ne 0 ]]; then
- report_fail "Couldn't make pppd connection."
- return 1
- fi
-}
-
-ppp_down() {
- load_profile "$1"
- PIDFILE="/var/run/ppp-$(basename $PEER).pid"
-
- if [[ -e $PIDFILE ]]; then
- PID=$(head -1 $PIDFILE)
- [[ -n "$PID" ]] && kill "$PID"
- fi
-}
-
-ppp_$1 "$2"
-exit $?
-
-# vim: ft=sh ts=4 et sw=4:
diff --git a/src/hooks/fancy b/src/hooks/fancy
deleted file mode 100755
index a64514e..0000000
--- a/src/hooks/fancy
+++ /dev/null
@@ -1,90 +0,0 @@
-# Fancy output is for terminal output only.
-[[ -t 1 ]] || return
-
-
-### Fancy Logging/Error reporting
-
-function report_err {
- print_prefixed "${FANCY_OTHER}" "${FANCY_HIGHLIGHT}$*"
-}
-
-function report_notice {
- print_prefixed "${FANCY_OTHER}" "$*"
-}
-
-function report_try {
- printf "${FANCY_OTHER}${PREFIX_BUSY}${FANCY_NORMAL} %s " "$*"
- report_busy
- REPORT_TRYING=1
-}
-
-function report_fail {
- if [[ -n "$*" ]]; then
- if [[ -n "$REPORT_TRYING" ]]; then
- report_append "$*"
- report_failed
- REPORT_TRYING=
- else
- print_prefixed "${FANCY_FAILED}" "${FANCY_HIGHLIGHT}$*"
- fi
- elif [[ -n "$REPORT_TRYING" ]]; then
- report_failed
- REPORT_TRYING=
- fi
-}
-
-function report_success {
- if [[ -n "$*" ]]; then
- if [[ -n "$REPORT_TRYING" ]]; then
- report_append "$*"
- report_done
- REPORT_TRYING=
- else
- print_prefixed "${FANCY_DONE}" "$*"
- fi
- elif [[ -n "$REPORT_TRYING" ]]; then
- report_done
- REPORT_TRYING=
- fi
-}
-
-function report_append {
- printf -- "${RESTORE_POSITION}${FANCY_OTHER}-${FANCY_NORMAL} %s " "$*"
-}
-
-function report_busy {
- printf "${CURSOR_STATUS} [${FANCY_BUSY} BUSY ${FANCY_NORMAL}] "
-}
-
-function report_failed {
- printf "${CURSOR_STATUS} [${FANCY_FAILED}FAILED${FANCY_NORMAL}]\n"
-}
-
-function report_done {
- printf "${CURSOR_STATUS} [${FANCY_DONE} DONE ${FANCY_NORMAL}]\n"
-}
-
-function print_prefixed {
- local c_prefix=$1
- shift
- printf "${c_prefix}${PREFIX_ATTENTION}${FANCY_NORMAL} %s${FANCY_NORMAL}\n" "$*"
-}
-
-
-SAVE_POSITION=$(tput sc)
-RESTORE_POSITION=$(tput rc)
-COLUMNS=$(tput cols)
-(( COLUMNS == 0 )) && COLUMNS=80
-CURSOR_STATUS=${SAVE_POSITION}$(tput hpa $(( COLUMNS - 10 )) )
-
-FANCY_NORMAL=$(tput sgr0)
-FANCY_HIGHLIGHT=${FANCY_NORMAL}$(tput bold)
-FANCY_BUSY=${FANCY_NORMAL}$(tput setaf 6) # cyan
-FANCY_FAILED=${FANCY_HIGHLIGHT}$(tput setaf 1) # red
-FANCY_DONE=${FANCY_HIGHLIGHT}$(tput setaf 2) # green
-FANCY_OTHER=${FANCY_HIGHLIGHT}$(tput setaf 4) # blue
-
-PREFIX_BUSY="::"
-PREFIX_ATTENTION=" >"
-
-# vim: ft=sh ts=4 et sw=4:
diff --git a/src/hooks/initscripts b/src/hooks/initscripts
deleted file mode 100755
index 07003c8..0000000
--- a/src/hooks/initscripts
+++ /dev/null
@@ -1,35 +0,0 @@
-# Use initscripts output formatting.
-# This hook must be loaded after 'fancy'.
-
-[[ ${FANCY_NORMAL+x} = x && -f /etc/rc.d/functions ]] || return
-. /etc/rc.conf
-. /etc/rc.d/functions
-
-
-function report_try {
- stat_busy "$*"
- REPORT_TRYING=1
-}
-
-function report_append {
- stat_append "- $*"
-}
-
-function report_failed {
- stat_fail
-}
-
-function report_done {
- stat_done
-}
-
-
-FANCY_NORMAL=$C_CLEAR
-FANCY_HIGHLIGHT=$C_H1
-FANCY_FAILED=$C_FAIL
-FANCY_DONE=$C_DONE
-FANCY_OTHER=$C_OTHER
-
-PREFIX_ATTENTION=$PREFIX_HL
-
-# vim: ft=sh ts=4 et sw=4:
diff --git a/src/ifplugd.action b/src/ifplugd.action
new file mode 100755
index 0000000..ea3a16c
--- /dev/null
+++ b/src/ifplugd.action
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+# ifplugd.action script for netcfg
+
+. /usr/lib/network/network
+
+case "$2" in
+ up)
+ # Look for a dhcp based profile to try first
+ # dhcp can actually outright fail, whereas
+ # it's difficult to tell if static succeeded
+ # Also check profile is same iface and is right connection
+ echo "up"
+ declare -a preferred_profiles
+ declare -a dhcp_profiles
+ declare -a static_profiles
+ for profile in $(list_profiles); do
+ (
+ echo "loading $profile"
+ load_profile "$profile"
+ [[ "$INTERFACE" == "$1" && "$CONNECTION" == "ethernet" ]] || continue
+ checkyesno "${AUTO_WIRED:-no}" && exit 1 # user preferred AUTO profile
+ [[ "$IP" == "dhcp" ]] && exit 2 # dhcp profile
+ exit 3 # static profile
+ )
+ case $? in
+ 1) preferred_profiles+=("$profile");;
+ 2) dhcp_profiles+=("$profile");;
+ 3) static_profiles+=("$profile");;
+ esac
+ done
+ if [[ ${#preferred_profiles[@]} > 1 ]]; then
+ echo "AUTO_WIRED flag for $1 set in more than one profile (${preferred_profiles[*]})"
+ fi
+ for profile in "${preferred_profiles[@]}" "${dhcp_profiles[@]}" "${static_profiles[@]}"; do
+ profile_up "$profile" && exit 0
+ done
+ ;;
+ down)
+ if check_iface "$1"; then
+ interface_down "$1" && exit 0
+ fi
+ ;;
+ *)
+ echo "Wrong arguments" > /dev/stderr
+ ;;
+esac
+
+exit 1
diff --git a/src/8021x b/src/lib/8021x
index d2ddfe4..d2ddfe4 100644
--- a/src/8021x
+++ b/src/lib/8021x
diff --git a/src/lib/auto.action b/src/lib/auto.action
new file mode 100755
index 0000000..1f29364
--- /dev/null
+++ b/src/lib/auto.action
@@ -0,0 +1,56 @@
+#! /bin/bash
+
+interface="$1"
+ssid="$2"
+profile="$3"
+action="$4"
+
+. /usr/lib/network/network
+[[ "$profile" ]] && load_profile "$profile"
+
+case $action in
+ CONNECT)
+ if [[ -z $profile ]]; then
+ # Load interface specific config
+ [[ -f "$IFACE_DIR/$interface" ]] && source "$IFACE_DIR/$interface"
+ dhcpcd -qL -t "${DHCP_TIMEOUT:-10}" -K $DHCP_OPTIONS "$interface"
+ exit $?
+ fi
+ if ! DHCPCD_INTERNAL_OPTIONS="-K" $CONN_DIR/ethernet up "$profile"; then
+ exit 1 # what to do if fail?
+ fi
+
+ set_profile up "$profile"
+
+ if ! ( eval $POST_UP ); then # JP: sandbox the eval
+ # failing POST_UP will take interface down
+ "$CONN_DIR/$ethernet" down "$profile"
+ exit 1
+ fi
+ ;;
+ DISCONNECT)
+ if [[ -z $profile ]]; then
+ dhcpcd -k "$interface"
+ exit $?
+ fi
+ if ! ( eval $PRE_DOWN ); then # JP: sandbox the eval
+ exit 1
+ fi
+ if ! "$CONN_DIR/ethernet" down "$profile"; then
+ exit 1
+ fi
+ if ! ( eval $POST_DOWN ); then # JP: sandbox the eval
+ exit 1
+ fi
+ set_profile down "$profile"
+ ;;
+ LOST|REESTABLISHED)
+ # Not handled.
+ exit 0
+ ;;
+ *)
+ # ???
+ exit 1
+ ;;
+esac
+
diff --git a/src/lib/connections/README b/src/lib/connections/README
new file mode 100644
index 0000000..38ef11a
--- /dev/null
+++ b/src/lib/connections/README
@@ -0,0 +1,28 @@
+Support for connection types is implemented by connection files in
+
+ /usr/lib/network/connections/
+
+The file name determines the name of the connection type, so support
+for the aviancarrier connection type will be provided by the file:
+
+ /usr/lib/network/connections/aviancarrier
+
+Files that implement support for a connection type should NOT be
+executable. Such files should contain valid Bash code, among which two
+functions, namely <connection_type>_up and <connection_type>_down. For
+the aviancarrier file this would be:
+
+ aviancarrier_up
+ aviancarrier_down
+
+These functions are responsible for bringing the network up and down,
+respectively. When the functions are called, three bash files are
+already sourced, so all functions and variables in those files are
+available. The readily sourced files are:
+
+ /usr/lib/network/network
+ /usr/lib/network/globals
+ /etc/network.d/<profile>
+
+Here, <profile> is the profile file specifying the desired network
+configuration.
diff --git a/src/connections/bond b/src/lib/connections/bond
index bc5aa95..bc5aa95 100644
--- a/src/connections/bond
+++ b/src/lib/connections/bond
diff --git a/src/connections/bridge b/src/lib/connections/bridge
index 6b3ab67..6b3ab67 100644
--- a/src/connections/bridge
+++ b/src/lib/connections/bridge
diff --git a/src/connections/ethernet b/src/lib/connections/ethernet
index 487adf8..487adf8 100644
--- a/src/connections/ethernet
+++ b/src/lib/connections/ethernet
diff --git a/src/connections/pppoe b/src/lib/connections/pppoe
index 17fe42d..17fe42d 100644
--- a/src/connections/pppoe
+++ b/src/lib/connections/pppoe
diff --git a/src/connections/tunnel b/src/lib/connections/tunnel
index 6cefc5c..6cefc5c 100644
--- a/src/connections/tunnel
+++ b/src/lib/connections/tunnel
diff --git a/src/connections/tuntap b/src/lib/connections/tuntap
index 6985c8c..6985c8c 100644
--- a/src/connections/tuntap
+++ b/src/lib/connections/tuntap
diff --git a/src/connections/vlan b/src/lib/connections/vlan
index 75c7fa9..75c7fa9 100644
--- a/src/connections/vlan
+++ b/src/lib/connections/vlan
diff --git a/src/connections/wireless b/src/lib/connections/wireless
index 135bec7..135bec7 100644
--- a/src/connections/wireless
+++ b/src/lib/connections/wireless
diff --git a/src/globals b/src/lib/globals
index 491f9d6..491f9d6 100644
--- a/src/globals
+++ b/src/lib/globals
diff --git a/src/network b/src/lib/network
index 1aa384c..1aa384c 100644
--- a/src/network
+++ b/src/lib/network
diff --git a/src/rfkill b/src/lib/rfkill
index 1832dc1..1832dc1 100644
--- a/src/rfkill
+++ b/src/lib/rfkill
diff --git a/src/netctl b/src/netctl
new file mode 100755
index 0000000..f1d79e8
--- /dev/null
+++ b/src/netctl
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+. /usr/lib/network/network
+
+NETCFG_VER=2-notpackaged
+
+version()
+{
+ echo "netcfg v$NETCFG_VER"
+}
+
+usage()
+{
+ version
+ cat << END
+Usage:
+ Start specified profile: netcfg profile
+ Other functions: netcfg argument profile
+Arguments:
+ current Report currently running profiles
+-a, all-down Take all active profiles down
+-c, check-iface Do not start profile if interface is already up
+-d, down Take specified profile down
+-D, iface-down Take down profile active on specified interface
+-h, help This help message
+-l, list List all available profiles
+-r, reconnect Disconnect and reconnect specified profile
+-R, iface-recon Reconnect profile active on specified interface
+-u, up Start specified profile
+-v, version Output version information and exit
+ all-resume Resume previously suspended profiles and reconnect them
+ all-suspend Store a list of current running profiles and suspend them
+END
+}
+
+# TODO: Re-add ROOT check and rewrite with getopts from BashFAQ
+
+case "$1" in
+ --version|-v|version)
+ version
+ exit 0;;
+ --help|-h|help)
+ usage
+ exit 0;;
+ list|-l)
+ list_profiles
+ exit 0;;
+ current|-s|status)
+ if [[ -d "$STATE_DIR/profiles/" ]]; then
+ ls "$STATE_DIR/profiles/"
+ exit 0
+ else
+ exit_stderr "No active profiles."
+ fi;;
+esac
+
+if [[ $(id -u) -gt 0 ]]; then
+ exit_stderr "This script should be run as root."
+fi
+
+# Ensure cwd is not in a transient directory, which may prevent unmounting due to netcfg children
+cd /
+
+case "$1" in
+ -c|check-iface|-u|up)
+ CHECK="YES"
+ profile_up "$2";;
+ -d|down)
+ profile_down "$2";;
+ -D|iface-down)
+ interface_down "$2";;
+ -a|all-down)
+ all_down;;
+ -r|reconnect)
+ profile_down "$2"
+ profile_up "$2";;
+ -R|iface-recon)
+ interface_reconnect "$2";;
+ all-resume)
+ all_resume;;
+ all-suspend)
+ all_suspend;;
+ clean)
+ rm "$STATE_DIR/interfaces"/* 2> /dev/null
+ rm "$STATE_DIR/profiles"/* 2> /dev/null
+ rm "$STATE_DIR/suspend"/* 2> /dev/null
+ rm "$STATE_DIR/netcfg-daemon" 2> /dev/null
+ killall wpa_supplicant 2> /dev/null
+ killall dhcpcd 2> /dev/null
+ killall dhclient 2> /dev/null
+ ;;
+ -*|--*)
+ usage
+ exit 1;;
+ *)
+ if [[ -n "$1" ]]; then
+ profile_up "$1"
+ else
+ usage
+ exit 1
+ fi
+ ;;
+esac
+exit $?
+
+# vim: ft=sh ts=4 et sw=4:
diff --git a/src/netctl-auto b/src/netctl-auto
new file mode 100755
index 0000000..c6aaf67
--- /dev/null
+++ b/src/netctl-auto
@@ -0,0 +1,87 @@
+#! /bin/bash
+. /usr/lib/network/network
+. "$SUBR_DIR/8021x"
+. "$SUBR_DIR/rfkill"
+. /etc/conf.d/netcfg
+
+AUTOWIFI="/usr/sbin/wpa_actiond -p /run/wpa_supplicant"
+ACTION_SCRIPT="/usr/bin/netcfg-wpa_actiond-action"
+
+case $1 in
+ help)
+ echo "netcfg-wpa_actiond <interface>"
+ echo "netcfg-wpa_actiond stop <interface>"
+ exit
+ ;;
+ stop)
+ [[ -z $2 ]] && echo "Please specify an interface to stop" && exit 1
+ interface=$2
+ PIDFILE="/run/wpa_actiond_${interface}.pid"
+ [[ -f "$IFACE_DIR/$interface" ]] && source "$IFACE_DIR/$interface"
+ netcfg -D "$interface"
+ timeout_wait 1 '[[ ! -f "$PIDFILE" ]]' || kill "$(< "$PIDFILE")"
+ # only try to disable software rfkill switches (FS#25514)
+ if [[ "$RFKILL" == "soft" ]]; then
+ set_rf_state "$interface" disabled $RFKILL_NAME || exit $?
+ fi
+ exit
+ ;;
+ *)
+ interface=$1; shift
+ PIDFILE="/run/wpa_actiond_${interface}.pid"
+ EXTRA_AUTOWIFI_OPTIONS="$*"
+ ;;
+esac
+
+if [[ -z $interface ]]; then
+ echo "No interface specified"
+ exit 1
+fi
+
+# Load interface specific config
+[[ -f "$IFACE_DIR/$interface" ]] && source "$IFACE_DIR/$interface"
+
+if [[ -f "$CONN_DIR/interfaces/$interface" ]]; then
+ netcfg -D "$interface"
+fi
+
+if [[ -n "$RFKILL" ]]; then # Enable radio if necessary
+ enable_rf "$interface" "$RFKILL" "$RFKILL_NAME" || exit $?
+fi
+
+WPA_CONF="$(make_wpa_config_file "$interface")"
+
+if [[ -n "${AUTO_PROFILES}" ]]; then
+ for prof in "${AUTO_PROFILES[@]}"; do echo "$prof"; done
+else
+ list_profiles
+fi | while read profile; do
+ echo "$profile"
+ (
+ load_profile "$profile"
+
+ [[ $CONNECTION != "wireless" ]] && exit 1
+ [[ $INTERFACE != $interface ]] && exit 1
+ # Exclude wpa-config, the wpa_conf is 'complete' and doesn't fit in this scheme
+ [[ -z "$SECURITY" ]] && SECURITY="none"
+ [[ $SECURITY == "wpa-config" ]] && exit 1
+
+ printf "%s\n" "network={" "$(make_wpa_config)" "id_str=\"$profile\"" "}" >> "$WPA_CONF"
+ )
+done
+
+
+[[ -z $WPA_DRIVER ]] && WPA_DRIVER="nl80211,wext"
+WPA_OPTS="-W $WPA_OPTS"
+
+# Kill any existing wpa_supplicant on this interface
+stop_wpa "$interface" &> /dev/null
+
+if start_wpa "$interface" "$WPA_CONF" "$WPA_DRIVER" $WPA_OPTS; then
+ if $AUTOWIFI -i "$interface" -P "$PIDFILE" -a "$ACTION_SCRIPT" $EXTRA_AUTOWIFI_OPTIONS; then
+ exit 0
+ fi
+fi
+
+exit 1
+
diff --git a/src/wifi-menu b/src/wifi-menu
new file mode 100755
index 0000000..f46db0d
--- /dev/null
+++ b/src/wifi-menu
@@ -0,0 +1,263 @@
+#! /bin/bash
+
+. /usr/lib/network/network
+. "$SUBR_DIR/8021x"
+. /etc/conf.d/netcfg
+
+usage()
+{
+ cat << END
+Usage: wifi-menu [-o | --obscure] [-h | --help] [interface]
+
+Interactively connect to a wireless network.
+
+Arguments:
+ -o, --obscure Show asterisks for the characters of the password
+ and store the password as a hexadecimal string.
+ -h, --help Show this help.
+ interface The wireless interface to use.
+ (default: WIRELESS_INTERFACE from /etc/conf.d/netcfg)
+
+For choosing from all available profiles, use netcfg-menu.
+END
+}
+
+# Fills PROFILES and ESSIDS with the profile names and essids of the profiles
+# for interface $1.
+init_profiles()
+{
+ local i=0 essid profile
+ while read profile; do
+ essid=$(
+ unset INTERFACE ESSID
+ . "$PROFILE_DIR/$profile" &> /dev/null
+ if [[ "$INTERFACE" = "$1" && -n "$ESSID" ]]; then
+ printf "%s" "$ESSID"
+ if [[ "$DESCRIPTION" =~ "Automatically generated" ]]; then
+ return 2
+ else
+ return 1
+ fi
+ fi
+ return 0
+ )
+ case $? in
+ 2)
+ GENERATED+=("$profile")
+ ;&
+ 1)
+ PROFILES[i]=$profile
+ ESSIDS[i]=$essid
+ (( ++i ))
+ ;;
+ esac
+ done < <(list_profiles)
+}
+
+# Builds ENTRIES as an argument list for dialog based on scan results in $1.
+init_entries()
+{
+ local i=0 flags signal ssid
+ while IFS=$'\t' read signal flags ssid; do
+ ENTRIES[i++]="--" # $ssid might look like an option to dialog.
+ ENTRIES[i++]=$ssid
+ if inarray "$ssid" "${ESSIDS[@]}"; then
+ if inarray "$(ssid_to_profile "$ssid")" "${GENERATED[@]}"; then
+ ENTRIES[i]="+" # Automatically generated
+ else
+ ENTRIES[i]="*" # Handmade
+ fi
+ else
+ ENTRIES[i]="-" # Not present
+ fi
+ if [[ "$ssid" = "$CONNECTION" ]]; then
+ ENTRIES[i]="!" # Currently connected
+ fi
+ if [[ "$flags" =~ WPA2|WPA|WEP ]]; then
+ ENTRIES[i]+=":${BASH_REMATCH[0],,}"
+ else
+ ENTRIES[i]+=":none"
+ fi
+ ENTRIES[i]+=" :$signal"
+ (( ++i ))
+ done < "$1"
+}
+
+# Finds a profile name for ssid $1.
+ssid_to_profile()
+{
+ local i
+ for i in $(seq 0 $((${#ESSIDS[@]}-1))); do
+ if [[ "$1" = "${ESSIDS[i]}" ]]; then
+ printf "%s" "${PROFILES[i]}"
+ return 0
+ fi
+ done
+ return 1
+}
+
+# Creates a profile for ssid $1.
+create_profile()
+{
+ local box flags key msg security
+ PROFILE="$INTERFACE-${1//\//_}"
+ [[ -e "$PROFILE_DIR/$PROFILE" ]] && PROFILE+=".wifi-menu"
+ flags=$(grep -m 1 $'\t'"$1\$" "$NETWORKS" | cut -f 2)
+ if [[ "$flags" =~ WPA|WEP ]]; then
+ security=${BASH_REMATCH[0],,}
+ else
+ security=none
+ fi
+ if [[ "$flags" =~ PSK|WEP ]]; then
+ [[ "$OBSCURE" ]] && box="--insecure --passwordbox" || box="--inputbox"
+ msg="Enter $security security key for\n'$1'"
+ key=$(dialog $box "$msg" 10 40 --stdout) || return $?
+ if [[ "${#key}" -ge 8 && "${#key}" -le 63 ]]; then
+ if [[ "$OBSCURE" ]]; then
+ key=$(wpa_passphrase "$1" "$key" | grep -m 1 "^[[:space:]]*psk=")
+ key=${key#*psk=}
+ else
+ key=$(printf "%q" "$key")
+ fi
+ elif ! [[ "${#key}" -eq 64 && "$key" = +([[:xdigit:]]) ]]; then
+ return 4
+ fi
+ fi
+ cat << EOF > "$PROFILE_DIR/$PROFILE"
+CONNECTION='wireless'
+DESCRIPTION='Automatically generated profile by wifi-menu'
+INTERFACE='$INTERFACE'
+SECURITY='$security'
+ESSID=$(printf "%q" "$1")
+IP='dhcp'
+${key+KEY=$key}
+EOF
+ printf "%s" "$PROFILE"
+ return 0
+}
+
+# Connects to ssid $1 using an available profile or an automatically created
+# one if none exists.
+connect_to_ssid()
+{
+ local msg
+ PROFILE=$(ssid_to_profile "$1")
+ if [[ $? -eq 0 ]]; then
+ clear
+ check_profile "$PROFILE" && profile_down "$PROFILE"
+ else
+ PROFILE=$(create_profile "$1")
+ RETURN=$?
+ (( RETURN == 0 )) || return $RETURN
+ SPAWNED_PROFILE=1
+ clear
+ fi
+ if ! profile_up "$PROFILE"; then
+ if (( SPAWNED_PROFILE )); then
+ msg=" CONNECTING FAILED
+
+Do you want to keep the generated profile ('$PROFILE')?"
+ dialog --yesno "$msg" 10 40 --stdout || rm "$PROFILE_DIR/$PROFILE"
+ clear
+ fi
+ return 2
+ fi
+ return 0
+}
+
+while [[ "$1" = -* ]]; do
+ case "$1" in
+ -h|--help)
+ usage
+ exit
+ ;;
+ -o|--obscure)
+ OBSCURE=1
+ shift
+ ;;
+ -*)
+ report_err "Invalid option: $1"
+ usage
+ exit 255
+ ;;
+ esac
+done
+if [[ $# -gt 1 ]]; then
+ report_err "Too many arguments"
+ usage
+ exit 255
+fi
+
+if [[ $(id -u) -ne 0 ]]; then
+ exit_stderr "This script needs to be run with root privileges"
+fi
+if ! type dialog &> /dev/null; then
+ exit_stderr "Please install 'dialog' to use wifi-menu"
+fi
+
+INTERFACE=${1-$WIRELESS_INTERFACE}
+if [[ -z "$INTERFACE" ]]; then
+ report_err "Missing interface specification"
+ usage
+ exit 255
+fi
+
+cd / # We do not want to spawn anything that can block unmounting
+is_interface "$INTERFACE" || exit_fail "No such interface: $INTERFACE"
+if ! interface_is_up "$INTERFACE"; then
+ [[ -f "$IFACE_DIR/$INTERFACE" ]] && . "$IFACE_DIR/$INTERFACE"
+ bring_interface up "$INTERFACE" || exit_fail "Interface unavailable"
+ SPAWNED_INTERFACE=1
+fi
+
+report_try "Scanning for networks"
+CONNECTION=$(wpa_call "$INTERFACE" status 2> /dev/null | grep -m 1 "^ssid=")
+CONNECTION=${CONNECTION#ssid=}
+NETWORKS=$(wpa_supplicant_scan "$INTERFACE" 3,4,5)
+if [[ $? -eq 0 ]]; then
+ trap 'rm -f "$NETWORKS"' EXIT
+ report_success
+ init_profiles "$INTERFACE"
+ init_entries "$NETWORKS"
+ MSG="Select the network you wish to use
+Flags description:
+ * - handmade profile present
+ + - automatically generated profile present
+ - - no profile present
+ ! - active connection present"
+ CHOICE=$(dialog --column-separator : --menu "$MSG" 24 50 12 \
+ "${ENTRIES[@]}" --stdout)
+ RETURN=$?
+ if (( RETURN == 0 )); then
+ connect_to_ssid "$CHOICE"
+ RETURN=$?
+ fi
+else
+ report_fail
+ RETURN=3
+fi
+
+case $RETURN in
+ 0|2) # Connected | Connecting failed
+ ;;
+ 1) # Canceled
+ clear
+ ;;
+ 3) # No networks found
+ report_err "No networks found"
+ ;;
+ 4) # Invalid passphrase length (WEP keys have tighter restrictions)
+ clear
+ report_err "Passphrase must be 8..63 characters"
+ ;;
+ 255) # ESC or error
+ clear
+ report_err "Aborted"
+ ;;
+ *) # Should not happen
+ report_err "Unexpected return code from dialog: $RETURN"
+ RETURN=7
+ ;;
+esac
+(( RETURN && SPAWNED_INTERFACE )) && bring_interface down "$INTERFACE"
+exit $RETURN