[netctl] Add verify subcommand to netctl

Message ID YARS1GNIzGzhlsgk@Mindship-03
State New
Headers show
Series [netctl] Add verify subcommand to netctl | expand

Commit Message

Jouke Witteveen Jan. 17, 2021, 3:08 p.m. UTC
The name of the subcommand mirrors the same subcommand of systemd-analyze.

Verification before restarting would be useful. However, verification
requires the profile file to be readable by the current user. The current
user may be a regular user with permission to control systemd, so
restarting does not require the profile file to be readable. Therefore, we
do not attempt verification before restarting.
---
 docs/netctl.1.txt |  6 +++++-
 src/lib/globals   |  6 ++++++
 src/netctl.in     | 26 ++++++++++++++------------
 3 files changed, 25 insertions(+), 13 deletions(-)

Patch

diff --git a/docs/netctl.1.txt b/docs/netctl.1.txt
index d6d9360..76d45b0 100644
--- a/docs/netctl.1.txt
+++ b/docs/netctl.1.txt
@@ -82,7 +82,11 @@  The following commands are understood:
 
 *edit [+PROFILE+]*::
     Open the file of the specified profile in an editor. This does not
-    reenable or restart any profiles.
+    reenable, restart, or verify any profiles.
+
+*verify [+PROFILE+]*::
+    Check the file of the specified profile for syntax errors. If no
+    errors are found, no output is produced.
 
 *wait-online [+PROFILE+]*::
     Wait until the interface of the profile has a routable IP address of
diff --git a/src/lib/globals b/src/lib/globals
index 74ce623..32a1802 100644
--- a/src/lib/globals
+++ b/src/lib/globals
@@ -109,6 +109,12 @@  list_profiles() {
     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'
 }
 
+## Exit if a profile file is not syntactically correct
+# $1: profile name
+verify_profile() {
+    /bin/bash -n "$PROFILE_DIR/$1" || exit 1
+}
+
 ## Sources all hooks and a profile (but no interface configuration)
 # $1: profile name
 load_profile() {
diff --git a/src/netctl.in b/src/netctl.in
index c1ed493..a580048 100644
--- a/src/netctl.in
+++ b/src/netctl.in
@@ -23,7 +23,8 @@  Commands:
   disable [PROFILE]      Disable the systemd unit for a profile
   reenable [PROFILE]     Reenable the systemd unit for a profile
   is-enabled [PROFILE]   Check whether a profile is enabled
-  edit [PROFILE]         Edit a profile
+  edit [PROFILE]         Edit a profile file
+  verify [PROFILE]       Check the syntax of a profile file
   wait-online [PROFILE]  Wait for a profile to finish connecting
 END
 }
@@ -71,9 +72,6 @@  stop_all() {
 
 switch_to() {
     cd "$PROFILE_DIR"
-    if [[ ! -r $1 ]]; then
-        exit_error "Profile '$1' does not exist or is not readable"
-    fi
     # We assume interface names are not quoted
     # Using read removes leading whitespace
     read InterfaceLine < \
@@ -129,6 +127,11 @@  unit_disable() {
             "@systemdsystemconfdir@/$unit.d"{/profile.conf,}
 }
 
+unit_reenable() {
+    unit_disable "$1"
+    unit_enable "$1"
+}
+
 wait_online() {
     local profile="$1"
     if sd_call "is-active --quiet" "$profile"; then
@@ -163,20 +166,19 @@  case $# in
         sd_call "$1" "$2";;
       switch-to)
         ensure_root "$(basename "$0")"
+        verify_profile "$2"
         switch_to "$2";;
-      enable|disable)
+      enable|disable|reenable)
         ensure_root "$(basename "$0")"
+        if [[ $1 != "disable" ]]; then
+            verify_profile "$2"
+        fi
         "unit_$1" "$2"
         if systemd-notify --booted; then
             systemctl daemon-reload
         fi;;
-      reenable)
-        ensure_root "$(basename "$0")"
-        unit_disable "$2"
-        unit_enable "$2"
-        if systemd-notify --booted; then
-            systemctl daemon-reload
-        fi;;
+      verify)
+        verify_profile "$2";;
       edit)
         exec ${EDITOR:-nano} "$PROFILE_DIR/$2";;
       wait-online)