Hooks and interface scripts are now sourced more systematically. Settings of wireless profiles that depend on hooks are now picked up correctly by netctl-auto. Suggested by: Vitor Sakaguti <vis@tutao.de> --- Inspired by a report on GitHub: https://github.com/joukewitteveen/netctl/issues/185 src/ifplugd.action | 5 ++-- src/lib/auto.action | 3 --- src/lib/globals | 56 ++++++++++++++++++++++++++++++++++----------- src/lib/interface | 9 -------- src/lib/network | 1 - src/netctl-auto | 6 ++--- src/netctl.in | 11 +++------ 7 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/ifplugd.action b/src/ifplugd.action index c1f0e7d..0cebb34 100755 --- a/src/ifplugd.action +++ b/src/ifplugd.action @@ -14,11 +14,10 @@ case "$2" in printf '%s' "$profile" > "$PROFILE_FILE" exit 0 fi - done < <(list_profiles | while IFS= read -r profile; do + done < <(filter_profiles "$1" ethernet | while IFS= read -r profile; do report_debug "Examining profile '$profile'" ( - source "$PROFILE_DIR/$profile" > /dev/null - [[ $Interface == "$1" && $Connection == "ethernet" ]] || exit + load_profile "$profile" > /dev/null # Prioritize dhcp based profiles as they can outright fail, whereas # it is difficult to tell if a profile with a static address fails if [[ $IP == "dhcp" || $IP6 == dhcp* ]]; then diff --git a/src/lib/auto.action b/src/lib/auto.action index 6c13651..717d205 100755 --- a/src/lib/auto.action +++ b/src/lib/auto.action @@ -1,7 +1,6 @@ #! /bin/bash . /usr/lib/netctl/globals -. "$SUBR_DIR/interface" . "$SUBR_DIR/ip" export INTERFACE="$1" @@ -11,7 +10,6 @@ PROFILE_FILE="$STATE_DIR/netctl-auto-$INTERFACE.profile" case $ACTION in CONNECTED) load_profile "$WPA_ID_STR" - load_interface_config "$INTERFACE" DhcpcdOptions+=" -K -L" ip_set || exit 1 mkdir -p "$(dirname "$PROFILE_FILE")" @@ -26,7 +24,6 @@ case $ACTION in DISCONNECTED) if [[ -s "$PROFILE_FILE" ]]; then load_profile "$(< "$PROFILE_FILE")" - load_interface_config "$INTERFACE" rm -f "$PROFILE_FILE" # Sandbox the eval if ! ( do_debug eval "$ExecDownPre" ); then diff --git a/src/lib/globals b/src/lib/globals index 32a1802..3d2c50d 100644 --- a/src/lib/globals +++ b/src/lib/globals @@ -103,41 +103,71 @@ timeout_wait() { ### Profile management -## List all acceptable profiles names separated by newlines -list_profiles() { - # Follow aliases with -L, skip forbidden/reserved names - find -L "$PROFILE_DIR/" -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n' +## Load all available hooks +load_hooks() { + local hook + while IFS= read -r hook; do + source "$hook" + done < <(find -L "$PROFILE_DIR/hooks" -maxdepth 1 -type f -executable -not -name '.*' -not -name '*~' -not -name $'*\n*' | sort) } -## Exit if a profile file is not syntactically correct -# $1: profile name -verify_profile() { - /bin/bash -n "$PROFILE_DIR/$1" || exit 1 +## Load interface configuration, if present +# $1: interface name +load_interface_config() { + local config_file="$PROFILE_DIR/interfaces/$1" + if [[ -x $config_file ]]; then + source "$config_file" + fi } ## Sources all hooks and a profile (but no interface configuration) # $1: profile name load_profile() { - local hook # Expose the profile name Profile=$1 if [[ -z $Profile || ! -r "$PROFILE_DIR/$Profile" ]]; then exit_error "Profile '$Profile' does not exist or is not readable" fi - while IFS= read -r hook; do - source "$hook" - done < <(find -L "$PROFILE_DIR/hooks" -maxdepth 1 -type f -executable -not -name '.*' -not -name '*~' -not -name $'*\n*' | sort -u) - unset hook + load_hooks source "$PROFILE_DIR/$Profile" if [[ -z $Interface ]]; then exit_error "Profile '$Profile' does not specify an interface" fi + load_interface_config "$Interface" if [[ ! -r "${Connection:+$SUBR_DIR/connections/$Connection}" ]]; then exit_error "Profile '$Profile' does not specify a valid connection" fi source "$SUBR_DIR/connections/$Connection" } +## List all acceptable profiles names separated by newlines +list_profiles() { + # Follow aliases with -L, skip forbidden/reserved names + find -L "$PROFILE_DIR/" -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n' +} + +## List names of profiles for a given interface and/or connection +# $1: interface (optional) +# $2: connection (optional) +filter_profiles() { + list_profiles | while IFS= read -r Profile; do + if ( + source "$PROFILE_DIR/$Profile" || exit + [[ -z $1 || $1 == "$Interface" ]] || exit + load_interface_config "$Interface" + [[ -z $2 || $2 == "$Connection" ]] || exit + ); then + printf '%s\n' "$Profile" + fi + done +} + +## Exit if a profile file is not syntactically correct +# $1: profile name +verify_profile() { + /bin/bash -n "$PROFILE_DIR/$1" || exit 1 +} + ## Wrapper around systemctl converting profile names to unit names # $1: systemctl command # $2...: profile names diff --git a/src/lib/interface b/src/lib/interface index 1a51c07..8504191 100644 --- a/src/lib/interface +++ b/src/lib/interface @@ -1,15 +1,6 @@ ## /usr/lib/netctl/globals needs to be sourced before this file -## Load interface configuration, if present -# $1: interface name -load_interface_config() { - local config_file="$PROFILE_DIR/interfaces/$1" - if [[ -x $config_file ]]; then - source "$config_file" - fi -} - ## Check if a string represents a network interface # $1: potential interface name is_interface() { diff --git a/src/lib/network b/src/lib/network index b6926e3..cb79b77 100755 --- a/src/lib/network +++ b/src/lib/network @@ -88,7 +88,6 @@ elif [[ $# -eq 2 && $1 == @(start|stop) ]]; then # Expose the command Command=$1 load_profile "$2" - load_interface_config "$Interface" "network_$1" else exit_error "Usage: $0 {start|stop|wait-online} [profile]" diff --git a/src/netctl-auto b/src/netctl-auto index ec3f7a2..720949e 100755 --- a/src/netctl-auto +++ b/src/netctl-auto @@ -211,12 +211,10 @@ start() { # Disable p2p to prevent wpa_supplicant from creating another control interface echo "p2p_disabled=1" >> "$WPAConfigFile" - local profile - list_profiles | while IFS= read -r profile; do + filter_profiles "$interface" wireless | while IFS= read -r profile; do report_debug "Examining profile '$profile'" ( - source "$PROFILE_DIR/$profile" - [[ $Interface == "$interface" && $Connection == "wireless" ]] || exit + load_profile "$profile" is_yes "${ExcludeAuto:-no}" && exit # Set default and exclude wpa-config as it does not fit this scheme [[ ${Security:=none} != "wpa-config" ]] || exit diff --git a/src/netctl.in b/src/netctl.in index 929eb1e..3a96f12 100644 --- a/src/netctl.in +++ b/src/netctl.in @@ -71,16 +71,11 @@ stop_all() { } switch_to() { - cd "$PROFILE_DIR" - # We assume interface names are not quoted - # Using read removes leading whitespace - read InterfaceLine < \ - <(grep -om1 '^[[:space:]]*Interface=[[:alnum:]:._-]\+' "$1") - if [[ -z $InterfaceLine ]]; then + Interface=$(. "$PROFILE_DIR/$1" >/dev/null; printf '%s' "$Interface") + if [[ -z $Interface ]]; then exit_error "Profile '$1' does not specify an interface" fi - mapfile -t AllProfiles < <(list_profiles) - mapfile -t Profiles < <(grep -Fl "$InterfaceLine" "${AllProfiles[@]}") + mapfile -t Profiles < <(filter_profiles "$Interface") if (( ${#Profiles[@]} )); then do_debug sd_call stop "${Profiles[@]}" 2> >(grep -Fv 'not loaded' >&2) fi -- 2.31.1