Skip to main content

netctl wifi-menu

#! /bin/bash

. /usr/lib/netctl/globals
. "$SUBR_DIR/interface"
. "$SUBR_DIR/rfkill"
. "$SUBR_DIR/wpa"


usage() {
    cat << END
Usage: wifi-menu [-h | --help] [-o | --obscure] [INTERFACE]

Interactively connect to a wireless network on INTERFACE using netctl.
If only one wireless interface is available, INTERFACE can be omitted.

Arguments:
  -h, --help     Show this help
  -o, --obscure  Show asterisks for the characters of the password
                 and store the password as a hexadecimal string
END
}

# Undo printf escaping in $1
printf_decode() {
    printf -- "${1//%/%%}"
}

# Prepare $1 for use in a special quoting context
quote_safe() {
    if [[ "$1" = \"* ]]; then
        printf '""%s"' "$1"
    else
        printf "%s" "$1"
    fi
}

# Fill PROFILES and ESSIDS with the profile names and essids and fill GENERATED
# with the names of automatically generated profiles for interface $1
init_profiles() {
    local i=0 essid profile
    while IFS= read -r profile; do
        # Sandbox the sourcing of profiles
        essid=$(
            source "$PROFILE_DIR/$profile" > /dev/null
            if [[ "$Interface" = "$1" && -n "$ESSID" ]]; then
                if [[ "$ESSID" = \"\"*\" ]]; then
                    ESSID=${ESSID:2:-1}
                fi
                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)
}

# Build ENTRIES as an argument list for dialog based on scan results in $1
init_entries() {
    local i=0 sep=$'\t' decoded flags signal ssid
    while IFS=$'\t' read -r signal flags ssid; do
        decoded=$(printf_decode "$ssid")
        ENTRIES[i++]="--"  # the SSID might look like an option to dialog
        if [[ "$CHARMAP" = "UTF-8" ]]; then
            ENTRIES[i++]=$decoded
        else
            ENTRIES[i++]=$ssid
        fi
        if is_yes "${CONNECTED:-no}" && [[ "$decoded" = "$CONNECTION" ]]; then
            ENTRIES[i]="*"  # Currently connected
        elif in_array "$decoded" "${ESSIDS[@]}"; then
            if in_array "$(ssid_to_profile "$decoded")" "${GENERATED[@]}"; then
                ENTRIES[i]="."  # Automatically generated
            else
                ENTRIES[i]=":"  # Handmade
            fi
        else
            ENTRIES[i]=" "  # Not present
        fi
        if [[ "$flags" =~ WPA2|WPA|WEP ]]; then
            ENTRIES[i]+="${sep}${BASH_REMATCH[0],,}"
        else
            ENTRIES[i]+="${sep}none"
        fi
        ENTRIES[i]+="   ${sep}${signal}"
        (( ++i ))
    done < "$1"
}

# Find 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
}

# Ask the user for the name of the new profile
confirm_profile() {
    local msg="Enter a name for the new profile\n"
    PROFILE=$(dialog --inputbox "$msg" 10 50 "$PROFILE" --stdout) || return $?
    if [[ "$PROFILE" = */* ]]; then
        PROFILE=${PROFILE//\//_}
        confirm_profile
    elif [[ -e "$PROFILE_DIR/$PROFILE" ]]; then
        msg="A profile by the name '$PROFILE' already exists.
Do you want to overwrite it?"
        dialog --yesno "$msg" 10 50 --stdout || confirm_profile
    fi
}

# Create a profile for ssid $1
create_profile() {
    local box flags key msg security signal ssid
    PROFILE=$(iconv -c -f UTF-8 -t //TRANSLIT <<< "$1")
    PROFILE="$INTERFACE-${PROFILE//[?\/]/_}"
    [[ -e "$PROFILE_DIR/$PROFILE" ]] && PROFILE+=".wifi-menu"
    confirm_profile || return $?
    while IFS=$'\t' read -r signal flags ssid; do
        [[ "$(printf_decode "$ssid")" != "$1" ]] || break
    done < "$NETWORKS"
    if [[ "$flags" =~ WPA|WEP ]]; then
        security=${BASH_REMATCH[0],,}
    else
        security=none
    fi
    if [[ "$flags" =~ PSK|WEP ]]; then
        if is_yes "${OBSCURE:-no}"; then
            box="--insecure --passwordbox"
        else
            box="--inputbox"
        fi
        msg="Enter $security security key for\n'$1'"
        key=$(dialog $box "$msg" 10 40 --stdout) || return $?
        if [[ "${BASH_REMATCH[0]}" = "WEP" ]]; then
            if [[ "$key" = +([[:xdigit:]][[:xdigit:]]) ]]; then
                key="\"$key"
            else
                key=$(quote_safe "$key")
            fi
        elif [[ ${#key} -ge 8 && ${#key} -le 63 ]]; then
            if is_yes "${OBSCURE:-no}"; then
                key="\"$(wpa_passphrase "$1" "$key" | sed -n "s/^[[:space:]]*psk=//p")"
            else
                key=$(quote_safe "$key")
            fi
        elif [[ ${#key} -eq 64 && "$key" = +([[:xdigit:]]) ]]; then
            key="\"$key"
        else
            return 4
        fi
    fi
    cat << EOF > "$PROFILE_DIR/$PROFILE"
Description='Automatically generated profile by wifi-menu'
Interface=$INTERFACE
Connection=wireless
Security=$security
ESSID=$(printf "%q" "$(quote_safe "$1")")
IP=dhcp
${key+Key=$(printf "%q" "$key")}
EOF
    printf "%s" "$PROFILE"
    return 0
}

# Connect 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 [[ $? -ne 0 ]]; then
        PROFILE=$(create_profile "$1") || return $?
        NEW_PROFILE=yes
    fi
    clear
    if systemctl is-active --quiet "[email protected]$INTERFACE.service"; then
        report_notice "Interface '$INTERFACE' is controlled by netctl-auto"
        if is_yes "${NEW_PROFILE:-no}"; then
            do_debug systemctl restart "[email protected]$INTERFACE.service"
        fi
        do_debug netctl-auto switch-to "$PROFILE"
    elif ! netctl switch-to "$PROFILE"; then
        if is_yes "${NEW_PROFILE:-no}"; 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=yes
            shift
            ;;
        -*)
            report_error "Invalid option: $1"
            usage
            exit 255
            ;;
    esac
done
if [[ $# -gt 1 ]]; then
    report_error "Too many arguments"
    usage
    exit 255
fi

ensure_root "$(basename "$0")"
if ! type dialog &> /dev/null; then
    exit_error "Please install 'dialog' to use wifi-menu"
fi
CHARMAP=$(locale charmap)
cd /  # We do not want to spawn anything that can block unmounting

INTERFACE=$1
if [[ -z "$INTERFACE" ]]; then
    INTERFACE=(/sys/class/net/*/wireless/)
    if [[ ${#INTERFACE[@]} -ne 1 || ! -d "$INTERFACE" ]]; then
        report_error "Invalid interface specification"
        usage
        exit 255
    fi
    INTERFACE=${INTERFACE:15:-10}
    report_debug "Using interface '$INTERFACE'"
elif ! is_interface "$INTERFACE"; then
    exit_error "No such interface: $INTERFACE"
fi
load_interface_config "$INTERFACE"

if [[ "$RFKill" && "$(rf_status "$INTERFACE" "$RFKill")" ]]; then
    if ! rf_enable "$INTERFACE" "$RFKill"; then
        exit_error "Could not unblock transmission on interface '$INTERFACE'"
    fi
    RF_UNBLOCKED=yes
fi

echo -n "Scanning for networks... "
if CONNECTION=$(wpa_call "$INTERFACE" status 2> /dev/null | grep -m 1 "^ssid="); then
    CONNECTION=$(printf_decode "${CONNECTION#ssid=}")
    CONNECTED=yes
fi
NETWORKS=$(wpa_supplicant_scan "$INTERFACE" 3,4,5)
RETURN=$?

if is_yes "${RF_UNBLOCKED:-no}"; then
    rf_disable "$INTERFACE" "$RFKill"
fi

if (( RETURN == 0 )); then
    trap 'rm -f "$NETWORKS"' EXIT
    echo "done"
    init_profiles "$INTERFACE"
    init_entries "$NETWORKS"
    MSG="Select the network you wish to use
Flags description:
 * - active connection present
 : - handmade profile present
 . - automatically generated profile present"
    CHOICE=$(dialog --menu "$MSG" 24 50 12 "${ENTRIES[@]}" --stdout)
    RETURN=$?
    if (( RETURN == 0 )); then
        if [[ "$CHARMAP" != "UTF-8" ]]; then
            CHOICE=$(printf_decode "$CHOICE")
        fi
        connect_to_ssid "$CHOICE"
        RETURN=$?
    fi
else
    echo "failed"
    RETURN=3
fi

case $RETURN in
    0|2)  # Connected | Connecting failed
        ;;
    1)  # Canceled
        clear
        ;;
    3)  # No networks found
        report_error "No networks found"
        ;;
    4)  # Invalid passphrase length (WEP keys have tighter restrictions)
        clear
        report_error "Passphrase must be 8..63 characters"
        ;;
    255)  # ESC or error
        clear
        report_error "Aborted"
        ;;
    *)  # Should not happen
        report_error "Unexpected return code from dialog: $RETURN"
        RETURN=7
        ;;
esac
exit $RETURN


# vim: ft=sh ts=4 et sw=4:

Popular posts from this blog

fix idm integration on chrome

Chrome Browser Integration I do not see IDM extension in Chrome extensions list. How can I install it?  How to configure IDM extension for Chrome? Please note that all IDM extensions that can be found in Google Store are fake and should not be used. You need to install IDM extension manually from IDM installation folder. Read in step 2 how to do it . 1. Please update IDM to the latest version by using  "IDM Help->Check for updates..."  menu item 2.  I don't see  "IDM Integration module"  extension in the list of extensions in  Chrome . How can I install it? Press on  Chrome  menu ( arrow 1  on the image), select  "Settings"  menu item ( arrow 2  on the image) and then select  "Extensions"  tab ( arrow 3  on the image). After this open IDM installation folder ( "C:\Program Files (x86)\Internet Download Manager"  by default,  arrow 4  on the image) and drag and drop  "IDMGCExt.crx"  ( arrow 5  on the image) file int

Hidden Wiki

Welcome to The Hidden Wiki New hidden wiki url 2015 http://zqktlwi4fecvo6ri.onion Add it to bookmarks and spread it!!! Editor's picks Bored? Pick a random page from the article index and replace one of these slots with it. The Matrix - Very nice to read. How to Exit the Matrix - Learn how to Protect yourself and your rights, online and off. Verifying PGP signatures - A short and simple how-to guide. In Praise Of Hawala - Anonymous informal value transfer system. Volunteer Here are five different things that you can help us out with. Plunder other hidden service lists for links and place them here! File the SnapBBSIndex links wherever they go. Set external links to HTTPS where available, good certificate, and same content. Care to start recording onionland's history? Check out Onionland's Museum Perform Dead Services Duties. Introduction Points Ahmia.fi - Clearnet search engine for Tor Hidden Services (allows you

Explainer: The nico-teen brain

Explainer: The nico-teen brain The adolescent brain is especially vulnerable to the addictive effects of nicotine BY  TERESA SHIPLEY FELDHAUSEN   7:00AM, AUGUST 19, 2015 Nicotine (black triangle towards center left) tricks the nerve cell (neuron) into sending a message to release more dopamine (yellow dots). Those molecules enter the space (synapse) between one nerve cell and the next. When they get picked up by neighboring cells, this gives users a feel-good high. It also creates the risk of addiction and other health problems.  EMail  Print  Twitter  Facebook  Reddit  Google+ NATIONAL INSTITUTE ON DRUG ABUSE, ADAPTED BY J. HIRSHFELD Nicotine is the addictive chemical in tobacco smoke and e-cigarette vapors. And doctors say the teenage brain is no place for it to end up. Nicotine can reach the brain within seven seconds of puffing on a cigar, hookah, cigarette or electronic cigarette. The area of the brain responsible f