globals 4.42 KB
Newer Older
Jouke Witteveen's avatar
Jouke Witteveen committed
1
NETCTL_VERSION="notpackaged"
2
PROFILE_DIR="/etc/netctl"
3
4
SUBR_DIR="/usr/lib/netctl"
STATE_DIR="/run/netctl"
5
STATE_FILE="${NETCTL_STATE_FILE:-/var/lib/netctl/netctl.state}"
6

Jim Pryor's avatar
Jim Pryor committed
7

8
9
### Logging/Error reporting

10
report_notice() {
11
12
13
    echo "$*"
}

14
report_error() {
Jouke Witteveen's avatar
Jouke Witteveen committed
15
16
17
18
19
20
    local prefix="<3>" suffix=""
    if [[ -t 2 ]]; then
        prefix=$(tput bold; tput setaf 1)
        suffix=$(tput sgr0)
    fi
    echo "$prefix$*$suffix" >&2
21
22
}

23
24
report_debug() {
    is_yes "${NETCTL_DEBUG:-no}" && echo "DEBUG: $*" >&2
25
26
}

27
exit_error() {
Jouke Witteveen's avatar
Jouke Witteveen committed
28
    report_error "$@"
29
    exit 1
30
31
32
}


33
34
35
36
37
38
39
40
41
42
43
44
### Variable management

## Check if a variable occurs in an array
# $1: the variable to find
# $2...: the array elements
in_array() {
    local hay needle=$1
    shift
    for hay; do
        [[ $hay == "$needle" ]] && return 0
    done
    return 1
45
46
}

47
## Check if a variable denotes a positive truth value
Jouke Witteveen's avatar
Jouke Witteveen committed
48
# $1: the variable to check, use is_yes "${VAR:-yes}" to set a default
49
50
51
is_yes() {
    case ${1,,} in
      yes|true|on|1)
52
        return 0
Jouke Witteveen's avatar
Jouke Witteveen committed
53
      ;;
54
      no|false|off|0)
55
        return 1
Jouke Witteveen's avatar
Jouke Witteveen committed
56
      ;;
57
58
      *)
        report_error "Not a valid truth value: '$1'"
Jouke Witteveen's avatar
Jouke Witteveen committed
59
        return 2
Jouke Witteveen's avatar
Jouke Witteveen committed
60
      ;;
61
62
63
    esac
}

64
65
66
67
68

### Control flow

## Show what we evaluate when debugging, but always evaluate
do_debug() {
Jouke Witteveen's avatar
Jouke Witteveen committed
69
70
    report_debug "${FUNCNAME[1]}:" "$@"
    "$@"
71
72
}

73
74
75
76
77
78
79
80
81
82
## Evaluate with a permissive umask
do_readable() {
    local result
    umask 022
    "$@"
    result=$?
    umask 077
    return $result
}

83
84
85
86
## Exit if we are not effectively root
# $1: program name (optional)
ensure_root() {
    (( EUID == 0 )) || exit_error "${1-$0} needs root privileges"
Jouke Witteveen's avatar
Jouke Witteveen committed
87
}
88

89
90
91
## Waits until a statement succeeds or a timeout occurs
# $1: timeout in seconds
# $2...: condition command
92
93
94
timeout_wait() {
    local timeout=$1
    (( timeout *= 5 ))
95
    shift
96
    until eval "$@"; do
97
        (( timeout-- > 0 )) || return 1
98
        sleep 0.2
99
100
101
102
103
    done
    return 0
}


104
105
### Profile management

106
107
108
109
110
111
## 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)
112
113
}

114
115
116
117
118
119
120
## 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
121
122
}

123
## Sources all hooks and a profile (but no interface configuration)
124
125
# $1: profile name
load_profile() {
126
127
128
129
    # 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"
130
    fi
131
    load_hooks
132
    source "$PROFILE_DIR/$Profile"
133
    if [[ -z $Interface ]]; then
134
        exit_error "Profile '$Profile' does not specify an interface"
135
    fi
136
    load_interface_config "$Interface"
Jouke Witteveen's avatar
Jouke Witteveen committed
137
    if [[ ! -r "${Connection:+$SUBR_DIR/connections/$Connection}" ]]; then
138
        exit_error "Profile '$Profile' does not specify a valid connection"
139
    fi
Jouke Witteveen's avatar
Jouke Witteveen committed
140
    source "$SUBR_DIR/connections/$Connection"
141
142
}

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
## 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" &> /dev/null
          [[ $Interface && ( -z $1 || $1 == "$Interface" ) ]] || exit
          load_interface_config "$Interface" > /dev/null
          [[ $Connection && ( -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
}

171
172
173
174
175
176
177
178
179
## Wrapper around systemctl converting profile names to unit names
# $1: systemctl command
# $2...: profile names
sd_call() {
    local command=$1
    shift
    systemctl $command $(systemd-escape --template=netctl@.service "$@")
}

180
181
182
## Retrieves the status string from the unit for a profile
# $1: profile name
sd_status_text() {
183
    sd_call "show --property=StatusText --value" "$1"
184
185
}

186

187
188
189
190
# Set a restrictive umask
do_readable :


Jim Pryor's avatar
Jim Pryor committed
191
# vim: ft=sh ts=4 et sw=4: