[Xfce4-commits] [xfce/xfce4-session] 01/03: Added better shutdown fallback support for the BSDs (Bug #14722)

noreply at xfce.org noreply at xfce.org
Thu May 2 19:50:36 CEST 2019


This is an automated email from the git hooks/post-receive script.

l   a   n   d   r   y       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository xfce/xfce4-session.

commit 1d56462b83cf320dff96d5b9ac3a767b019a0dd4
Author: Ali Abdallah <ali at xfce.org>
Date:   Mon Sep 24 09:47:55 2018 +0200

    Added better shutdown fallback support for the BSDs (Bug #14722)
    
    On the BSDs, users of group operator can shutdown/reboot the machine.
    We added some code on the fallback support in case consolekit is not
    running.
    
    Also, users with write access to /var/run/apmdev on OpenBSD and to
    /dev/acpi on the other BSDs can suspend and hibernate the machine.
    So we also support this on the fallback code.
---
 libxfsm/Makefile.am                    |   3 +-
 libxfsm/xfsm-shutdown-common.h         |  73 +++++++++++++
 xfce4-session/xfsm-shutdown-fallback.c | 192 ++++++++++++++++++++++++++++++---
 xfsm-shutdown-helper/main.c            |  38 +------
 4 files changed, 254 insertions(+), 52 deletions(-)

diff --git a/libxfsm/Makefile.am b/libxfsm/Makefile.am
index 538ab84..1b61dca 100644
--- a/libxfsm/Makefile.am
+++ b/libxfsm/Makefile.am
@@ -6,7 +6,8 @@ lib_LTLIBRARIES = libxfsm-4.6.la
 
 libxfsm_4_6_la_SOURCES =						\
 	xfsm-util.h							\
-	xfsm-util.c
+	xfsm-util.c							\
+	xfsm-shutdown-common.h
 
 libxfsm_4_6_la_CFLAGS =							\
 	$(LIBX11_CFLAGS)						\
diff --git a/libxfsm/xfsm-shutdown-common.h b/libxfsm/xfsm-shutdown-common.h
new file mode 100644
index 0000000..3b9fbd0
--- /dev/null
+++ b/libxfsm/xfsm-shutdown-common.h
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2018      Ali Abdallah <ali at xfce.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+#ifndef __XFSM_SHUTDOWN_COMMON_H_
+#define __XFSM_SHUTDOWN_COMMON_H_
+
+#ifdef POWEROFF_CMD
+#undef POWEROFF_CMD
+#endif
+#ifdef REBOOT_CMD
+#undef REBOOT_CMD
+#endif
+#ifdef UP_BACKEND_SUSPEND_COMMAND
+#undef UP_BACKEND_SUSPEND_COMMAND
+#endif
+#ifdef UP_BACKEND_HIBERNATE_COMMAND
+#undef UP_BACKEND_HIBERNATE_COMMAND
+#endif
+
+/* On FreeBSD, NetBSD and DragonFly BSD users with write access to
+ * /dev/acpi can suspend/hibernate the system */
+#define BSD_SLEEP_ACCESS_NODE "/dev/acpi"
+
+/* On OpenBSD this is done via apmd, so we check /var/run/apmdev to see
+ * zzz and ZZZ commands can write to it*/
+#ifdef BACKEND_TYPE_OPENBSD
+#undef BSD_SLEEP_ACCESS_NODE
+#define BSD_SLEEP_ACCESS_NODE "/var/run/apmdev"
+#endif
+
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#define POWEROFF_CMD  "/sbin/shutdown -p now"
+#define REBOOT_CMD    "/sbin/shutdown -r now"
+#elif defined(sun) || defined(__sun)
+#define POWEROFF_CMD  "/usr/sbin/shutdown -i 5 -g 0 -y"
+#define REBOOT_CMD    "/usr/sbin/shutdown -i 6 -g 0 -y"
+#else
+#define POWEROFF_CMD  "/sbin/shutdown -h now"
+#define REBOOT_CMD    "/sbin/shutdown -r now"
+#endif
+
+#ifdef BACKEND_TYPE_FREEBSD
+#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/acpiconf -s 3"
+#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/acpiconf -s 4"
+#endif
+
+#ifdef BACKEND_TYPE_LINUX
+#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/pm-suspend"
+#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/pm-hibernate"
+#endif
+
+#ifdef BACKEND_TYPE_OPENBSD
+#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/zzz"
+#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/ZZZ"
+#endif
+
+#endif /* __XFSM_SHUTDOWN_COMMON_H_ */
diff --git a/xfce4-session/xfsm-shutdown-fallback.c b/xfce4-session/xfsm-shutdown-fallback.c
index 1903161..28df8f8 100644
--- a/xfce4-session/xfsm-shutdown-fallback.c
+++ b/xfce4-session/xfsm-shutdown-fallback.c
@@ -2,6 +2,7 @@
  * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
  * Copyright (c) 2011      Nick Schermer <nick at xfce.org>
  * Copyright (c) 2014      Xfce Development Team <xfce4-dev at xfce.org>
+ * Copyright (c) 2018      Ali Abdallah <ali at xfce.org>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -59,14 +60,25 @@
 #include <gio/gio.h>
 #include <libxfce4util/libxfce4util.h>
 #include <gtk/gtk.h>
+#include <glib/gstdio.h>
+
 #ifdef HAVE_POLKIT
 #include <polkit/polkit.h>
 #endif
 
+#include <pwd.h>
+#include <grp.h>
+
+#define MAX_USER_GROUPS 100
+
 #include <libxfsm/xfsm-util.h>
+#include <libxfsm/xfsm-shutdown-common.h>
 #include <xfce4-session/xfsm-shutdown-fallback.h>
 #include <xfce4-session/xfce-screensaver.h>
 
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#define __BACKEND_TYPE_BSD__ 1
+#endif
 
 #define POLKIT_AUTH_SHUTDOWN_XFSM     "org.xfce.session.xfsm-shutdown-helper"
 #define POLKIT_AUTH_RESTART_XFSM      "org.xfce.session.xfsm-shutdown-helper"
@@ -117,6 +129,12 @@ freebsd_supports_sleep_state (const gchar *state)
   gboolean ret = FALSE;
   gchar *sleep_states;
 
+#if defined(__FreeBSD__)
+  gboolean status;
+  gint v;
+  size_t value_len = sizeof(int);
+#endif
+
   sleep_states = get_string_sysctl (NULL, "hw.acpi.supported_sleep_state");
   if (sleep_states != NULL)
     {
@@ -124,6 +142,27 @@ freebsd_supports_sleep_state (const gchar *state)
           ret = TRUE;
     }
 
+#if defined(__FreeBSD__)
+  /* On FreeBSD, S4 is not supported unless S4BIOS is available.
+   * If S4 will ever be implemented on FreeBSD, we can disable S4bios
+   * check below, using #if __FreeBSD_version >= XXXXXX.
+   **/
+  if (g_strcmp0(state, "S4") == 0)
+  {
+    status = sysctlbyname ("hw.acpi.s4bios", &v, &value_len, NULL, 0) == 0;
+    if (G_UNLIKELY(!status))
+    {
+      g_warning ("sysctl failed on 'hw.acpi.s4bios'");
+    }
+    else
+    {
+      /* No S4Bios support */
+      if (v == 0)
+        ret = FALSE;
+    }
+  }
+#endif /* __FreeBSD__ */
+
   g_free (sleep_states);
 
   return ret;
@@ -162,8 +201,86 @@ out:
 
 
 
+#ifdef __BACKEND_TYPE_BSD__
+static gboolean
+xfsm_shutdown_fallback_user_is_operator (void)
+{
+  struct passwd *pw;
+  gid_t groups[MAX_USER_GROUPS];
+  int max_grp = MAX_USER_GROUPS;
+  int i = 0;
+  int ret;
+  static gboolean is_operator = FALSE;
+  static gboolean once = FALSE;
+
+  /* Only check once */
+  if (once == TRUE)
+    goto out;
+
+  pw = getpwuid (getuid());
+
+  ret = getgrouplist (pw->pw_name, pw->pw_gid, groups, &max_grp);
+
+  if (ret < 0)
+    {
+      fprintf (stderr,
+               "Failed to get user group list, user belongs to more than %u groups?\n",
+               MAX_USER_GROUPS);
+      goto out;
+    }
+
+  once = TRUE;
+
+  for (i = 0; i < max_grp; i++)
+    {
+      struct group *gr;
+
+      gr = getgrgid (groups[i]);
+      if (strncmp(gr->gr_name, "operator", 8) == 0)
+        {
+          is_operator = TRUE;
+          break;
+        }
+    }
+out:
+  return is_operator;
+}
+#endif /* __BACKEND_TYPE_BSD__ */
+
+
+
+#ifdef __BACKEND_TYPE_BSD__
 static gboolean
-xfsm_shutdown_fallback_check_auth (const gchar *action_id)
+xfsm_shutdown_fallback_bsd_check_auth (XfsmShutdownType shutdown_type)
+{
+  gboolean auth_result = FALSE;
+  switch (shutdown_type)
+    {
+    /* On the BSDs users of the operator group are allowed to shutdown/restart the system */
+    case XFSM_SHUTDOWN_SHUTDOWN:
+    case XFSM_SHUTDOWN_RESTART:
+      auth_result = xfsm_shutdown_fallback_user_is_operator ();
+      break;
+    case XFSM_SHUTDOWN_SUSPEND:
+    case XFSM_SHUTDOWN_HIBERNATE:
+    case XFSM_SHUTDOWN_HYBRID_SLEEP:
+      /* Check rw access on '/var/run/apmdev' on OpenBSD and to /dev/acpi'
+       * for the other BSDs */
+      auth_result = g_access(BSD_SLEEP_ACCESS_NODE, R_OK|W_OK) == 0;
+      break;
+    default:
+      g_warning ("Unexpected shutdow id '%d'\n", shutdown_type);
+      break;
+    }
+
+  return auth_result;
+}
+#endif /* __BACKEND_TYPE_BSD__ */
+
+
+
+static gboolean
+xfsm_shutdown_fallback_check_auth_polkit (const gchar *action_id)
 {
   gboolean auth_result = FALSE;
 #ifdef HAVE_POLKIT
@@ -240,33 +357,41 @@ gboolean
 xfsm_shutdown_fallback_try_action (XfsmShutdownType   type,
                                    GError           **error)
 {
-  const gchar *action;
-  gboolean ret;
+  const gchar *xfsm_helper_action;
+  const gchar *cmd;
+  gboolean ret = FALSE;
   gint exit_status = 0;
+#ifdef HAVE_POLKIT
   gchar *command = NULL;
+#endif
 
   switch (type)
   {
     case XFSM_SHUTDOWN_SHUTDOWN:
-      action = "shutdown";
+      xfsm_helper_action = "shutdown";
+      cmd = POWEROFF_CMD;
       break;
     case XFSM_SHUTDOWN_RESTART:
-      action = "restart";
+      xfsm_helper_action = "restart";
+      cmd = REBOOT_CMD;
       break;
     case XFSM_SHUTDOWN_SUSPEND:
-      action = "suspend";
+      xfsm_helper_action = "suspend";
+      cmd = UP_BACKEND_SUSPEND_COMMAND;
       /* On suspend we try to lock the screen */
       if (!lock_screen (error))
         return FALSE;
       break;
     case XFSM_SHUTDOWN_HIBERNATE:
-      action = "hibernate";
+      xfsm_helper_action = "hibernate";
+      cmd = UP_BACKEND_HIBERNATE_COMMAND;
       /* On hibernate we try to lock the screen */
       if (!lock_screen (error))
         return FALSE;
       break;
     case XFSM_SHUTDOWN_HYBRID_SLEEP:
-      action = "hybrid-sleep";
+      xfsm_helper_action = "hybrid-sleep";
+      cmd = UP_BACKEND_HIBERNATE_COMMAND;
       /* On hybrid sleep we try to lock the screen */
       if (!lock_screen (error))
         return FALSE;
@@ -275,10 +400,22 @@ xfsm_shutdown_fallback_try_action (XfsmShutdownType   type,
       return FALSE;
   }
 
-  command = g_strdup_printf ("pkexec " XFSM_SHUTDOWN_HELPER_CMD " --%s", action);
+#ifdef __BACKEND_TYPE_BSD__
+  /* Make sure we can use native shutdown commands */
+  if (xfsm_shutdown_fallback_bsd_check_auth (type))
+    {
+      return g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, error);
+    }
+#endif
+
+  /* xfsm-shutdown-helper requires polkit to run */
+#ifdef HAVE_POLKIT
+  command = g_strdup_printf ("pkexec " XFSM_SHUTDOWN_HELPER_CMD " --%s", xfsm_helper_action);
+
   ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, error);
 
   g_free (command);
+#endif
   return ret;
 }
 
@@ -345,7 +482,7 @@ xfsm_shutdown_fallback_can_hybrid_sleep (void)
   return linux_supports_sleep_state ("hibernate");
 #endif
 #ifdef BACKEND_TYPE_OPENBSD
-  return TRUE;
+  return FALSE;
 #endif
 
   return FALSE;
@@ -361,7 +498,12 @@ xfsm_shutdown_fallback_can_hybrid_sleep (void)
 gboolean
 xfsm_shutdown_fallback_auth_shutdown (void)
 {
-  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_SHUTDOWN_XFSM);
+#ifdef __BACKEND_TYPE_BSD__
+  gboolean ret_val = xfsm_shutdown_fallback_bsd_check_auth (XFSM_SHUTDOWN_SHUTDOWN);
+  if (ret_val)
+    return TRUE;
+#endif
+  return xfsm_shutdown_fallback_check_auth_polkit (POLKIT_AUTH_SHUTDOWN_XFSM);
 }
 
 
@@ -374,7 +516,12 @@ xfsm_shutdown_fallback_auth_shutdown (void)
 gboolean
 xfsm_shutdown_fallback_auth_restart (void)
 {
-  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_RESTART_XFSM);
+#ifdef __BACKEND_TYPE_BSD__
+  gboolean ret_val = xfsm_shutdown_fallback_bsd_check_auth (XFSM_SHUTDOWN_RESTART);
+  if (ret_val)
+    return TRUE;
+#endif
+  return xfsm_shutdown_fallback_check_auth_polkit (POLKIT_AUTH_RESTART_XFSM);
 }
 
 
@@ -387,7 +534,12 @@ xfsm_shutdown_fallback_auth_restart (void)
 gboolean
 xfsm_shutdown_fallback_auth_suspend (void)
 {
-  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_SUSPEND_XFSM);
+#ifdef __BACKEND_TYPE_BSD__
+  gboolean ret_val = xfsm_shutdown_fallback_bsd_check_auth (XFSM_SHUTDOWN_SUSPEND);
+  if (ret_val)
+    return TRUE;
+#endif
+  return xfsm_shutdown_fallback_check_auth_polkit (POLKIT_AUTH_SUSPEND_XFSM);
 }
 
 
@@ -400,7 +552,12 @@ xfsm_shutdown_fallback_auth_suspend (void)
 gboolean
 xfsm_shutdown_fallback_auth_hibernate (void)
 {
-  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_HIBERNATE_XFSM);
+#ifdef __BACKEND_TYPE_BSD__
+  gboolean ret_val = xfsm_shutdown_fallback_bsd_check_auth (XFSM_SHUTDOWN_HIBERNATE);
+  if (ret_val)
+    return TRUE;
+#endif
+  return xfsm_shutdown_fallback_check_auth_polkit (POLKIT_AUTH_HIBERNATE_XFSM);
 }
 
 
@@ -413,5 +570,10 @@ xfsm_shutdown_fallback_auth_hibernate (void)
 gboolean
 xfsm_shutdown_fallback_auth_hybrid_sleep (void)
 {
-  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_HYBRID_SLEEP_XFSM);
+#ifdef __BACKEND_TYPE_BSD__
+  gboolean ret_val = xfsm_shutdown_fallback_bsd_check_auth (XFSM_SHUTDOWN_HYBRID_SLEEP);
+  if (ret_val)
+    return TRUE;
+#endif
+  return xfsm_shutdown_fallback_check_auth_polkit (POLKIT_AUTH_HYBRID_SLEEP_XFSM);
 }
diff --git a/xfsm-shutdown-helper/main.c b/xfsm-shutdown-helper/main.c
index 2c9bb1a..793d9fb 100644
--- a/xfsm-shutdown-helper/main.c
+++ b/xfsm-shutdown-helper/main.c
@@ -48,6 +48,8 @@
 #include <unistd.h>
 #endif
 
+#include "libxfsm/xfsm-shutdown-common.h"
+
 #include <glib.h>
 
 /* XXX */
@@ -56,42 +58,6 @@
 #define EXIT_CODE_ARGUMENTS_INVALID 3
 #define EXIT_CODE_INVALID_USER      4
 
-#ifdef POWEROFF_CMD
-#undef POWEROFF_CMD
-#endif
-#ifdef REBOOT_CMD
-#undef REBOOT_CMD
-#endif
-#ifdef UP_BACKEND_SUSPEND_COMMAND
-#undef UP_BACKEND_SUSPEND_COMMAND
-#endif
-#ifdef UP_BACKEND_HIBERNATE_COMMAND
-#undef UP_BACKEND_HIBERNATE_COMMAND
-#endif
-
-#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#define POWEROFF_CMD  "/sbin/shutdown -p now"
-#define REBOOT_CMD    "/sbin/shutdown -r now"
-#elif defined(sun) || defined(__sun)
-#define POWEROFF_CMD  "/usr/sbin/shutdown -i 5 -g 0 -y"
-#define REBOOT_CMD    "/usr/sbin/shutdown -i 6 -g 0 -y"
-#else
-#define POWEROFF_CMD  "/sbin/shutdown -h now"
-#define REBOOT_CMD    "/sbin/shutdown -r now"
-#endif
-#ifdef BACKEND_TYPE_FREEBSD
-#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/acpiconf -s 3"
-#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/acpiconf -s 4"
-#endif
-#if BACKEND_TYPE_LINUX
-#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/pm-suspend"
-#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/pm-hibernate"
-#endif
-#ifdef BACKEND_TYPE_OPENBSD
-#define UP_BACKEND_SUSPEND_COMMAND	"/usr/sbin/zzz"
-#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/ZZZ"
-#endif
-
 
 static gboolean
 run (const gchar *command)

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list