Commit db0cbbd8 authored by Lukasz Zalewski's avatar Lukasz Zalewski Committed by Brian Cameron

Fixes enhancement request #358114. Added variables & functions used to

2006-10-25  Lukasz Zalewski  <lukas@dcs.qmul.ac.uk>

        Fixes enhancement request #358114.
        * daemon/gdmconfig.c: Added variables & functions used to read/store
          CustomCommands related values
        * daemon/gdm.c (custom_cmd): New function that handles
          execution of CustomCommands.
        * daemon/gdm.c (custom_cmd_restart): New function that handles
          execution of CustomCommand if NoRestart option is set to false
        * daemon/gdm.c (custom_cmd_no_restart): New function that handles
          execution of CustomCommand if NoRestart option is set to true
        * daemon/gdm. [ch]: Updated macros and several functions to accomodate
          new CustomCommands functionality
        * daemon/slave.c: Added Custom command interrupt handler to handle
          the CustomCommands execution.
        * gui/gdmlogin.c (gdm_custom_cmd_handler): New function that handles
          execution of CustomCommands
        * gui/gdmlogin.c: Added variables and updated several functions to
          accomodate new CustomCommand functionality
        * gui/greeter/greeter_configuration.h: Added variables used to
          store CustomCommand related values
        * gui/greeter/greeter.c: Added variables that use/store
          CustomCommand related values
        * gui/greeter/greeter_item.c: Added visibility check for custom_cmd
          related widgets
        * gui/greeter/greeter_parser.c: Added code for parsing custom_cmd stock
          items
        * gui/greeter/greeter_system.c (greeter_custom_cmd_handler): New
          function that handles execution of CustomCommand
        * gui/greeter/greeter_system.c (query_greeter_custom_cmd_handler): New
          function that handles execution of CustomCommand (with warn message
          query beforehand)
        * gui/greeter/greeter_system.c: Updated macros and several functions
          to accomodate new CustomCommand functionality
parent 5493859f
......@@ -76,6 +76,7 @@ Contributions from:
Lee Mallabone <lee0@callnetuk.com>
Leena Gunda <leena.gunda@wipro.com>
Luis Villa <louie@ximian.com>
Lukasz Zalewski <lukas@dcs.qmul.ac.uk>
Mark McLoughlin <mark@skynet.ie>
Mathieu Lacage <mathieu@eazel.com>
Matt Forrest <mforrest@scs.ryerson.ca>
......
2006-10-25 Lukasz Zalewski <lukas@dcs.qmul.ac.uk>
Fixes enhancement request #358114.
* daemon/gdmconfig.c: Added variables & functions used to read/store
CustomCommands related values
* daemon/gdm.c (custom_cmd): New function that handles
execution of CustomCommands.
* daemon/gdm.c (custom_cmd_restart): New function that handles
execution of CustomCommand if NoRestart option is set to false
* daemon/gdm.c (custom_cmd_no_restart): New function that handles
execution of CustomCommand if NoRestart option is set to true
* daemon/gdm. [ch]: Updated macros and several functions to accomodate
new CustomCommands functionality
* daemon/slave.c: Added Custom command interrupt handler to handle
the CustomCommands execution.
* gui/gdmlogin.c (gdm_custom_cmd_handler): New function that handles
execution of CustomCommands
* gui/gdmlogin.c: Added variables and updated several functions to
accomodate new CustomCommand functionality
* gui/greeter/greeter_configuration.h: Added variables used to
store CustomCommand related values
* gui/greeter/greeter.c: Added variables that use/store
CustomCommand related values
* gui/greeter/greeter_item.c: Added visibility check for custom_cmd
related widgets
* gui/greeter/greeter_parser.c: Added code for parsing custom_cmd stock
items
* gui/greeter/greeter_system.c (greeter_custom_cmd_handler): New
function that handles execution of CustomCommand
* gui/greeter/greeter_system.c (query_greeter_custom_cmd_handler): New
function that handles execution of CustomCommand (with warn message
query beforehand)
* gui/greeter/greeter_system.c: Updated macros and several functions
to accomodate new CustomCommand functionality
2006-10-26 Brian Cameron <brian.cameron@sun.com>
* gui/gdmcommon.c, gui/greeter/greeter.c: Never die if
at-spi-registryd can not be started. Fixes bug #345434. Patch by
Ariel Rios <ariel@gnu.org>.
2006-10-26 Erwann Chenede - <erwann.chenede@sun.com>
* gui/greeter/greeter_parser.c: introduced altfile[n] property
......
......@@ -597,3 +597,70 @@ flexible=false
# Run the chooser instead of the greeter. When the user chooses a machine they
# will get this same server but run with "-terminate -query hostname".
chooser=true
[customcommand]
# This section allows you specify up to 10 custom commands. Each of the
# commands can be defined by the six parameters listed below. In each of the
# descriptions of the parameters N can take on any values between 0 and 9,
# i.e. CustomCommand0=,CustomCommand1=,...,CustomCommand9=. The numbers
# can have gaps as long as they fit within predefined set of 10, and their
# placement order within this section and with respect to each other is
# not important.
#
# CustomCommandN, CustomCommandTextN, CustomCommandLabelN,
# CustomCommandLRLabelN, CustomCommandTooltipN, and CustomCommandNoRestartN
# must all be defined for a given integer N, where N can be a number from
# 0-9.
# Custom command to run. Multiple commands may be specified separated by
# semicolons. GDM will use the first valid command. Examples:
# /sbin/bootwindoze;/usr/bin/bootwindoze, or
# /sbin/runupdate;/usr/local/sbin/runupdate
#
#CustomCommandN=
# Custom command dialog message that will appear on all warning dialogs.
# This will vary depending on what you want to do. Examples:
# Are you sure you want to restart system into Windoze?, or
# Are you sure you want do do this?
#CustomCommandTextN=
# Custom command label that will appear as stock label on buttons/menu items.
# Examples:
# _Windoze, or
# _Update Me
#CustomCommandLabelN=
# Custom command label that will appear as stock label on radio buttons/lista
# items. Examples:
# Restart into _Windoze, or
# Perform system _Update
#CustomCommandLRLabelN=
# Custom command tooltip. Examples
# Restarts the computer into Windoze
# Updates the computer software to the most recent version(s)
#CustomCommandTooltipN=
# Custom command gdm/system restart option. Setting it to true will not
# restart gdm after command execution. The default commands (reboot, shut
# down) all reboot the system by default which is why the default setting
# is true.
#CustomCommandNoRestartN=
#
# Example layout for more than one command:
#CustomCommand0=
#CustomCommandText0=
#CustomCommandLabel0=
#CustomCommandLRLabel0=
#CustomCommandTooltip0=
#CustomCommandNoRestart0=
#
#CustomCommand1=
#CustomCommandText1=
#CustomCommandLabel1=
#CustomCommandLRLabel1=
#CustomCommandTooltip1=
#CustomCommandNoRestart1=
#
# and so on
......@@ -94,6 +94,8 @@ static void handle_flexi_server (GdmConnection *conn,
uid_t xnest_uid,
const gchar *xnest_auth_file,
const gchar *xnest_cookie);
static void custom_cmd_restart (long cmd_id);
static void custom_cmd_no_restart (long cmd_id);
/* Global vars */
gint xdmcp_sessions = 0; /* Number of remote sessions */
......@@ -418,8 +420,8 @@ gdm_rmdir(char *thedir)
if (strcmp(dp->d_name, ".") == 0 ||
strcmp(dp->d_name, "..") == 0)
continue ;
snprintf(thefile, FILENAME_MAX, "%s/%s", thedir, dp->d_name);
if (stat(thefile, &buf) == -1)
snprintf (thefile, FILENAME_MAX, "%s/%s", thedir, dp->d_name);
if (stat (thefile, &buf) == -1)
continue ;
if (S_ISDIR(buf.st_mode))
gdm_rmdir(thefile);
......@@ -708,6 +710,93 @@ restart_machine (void)
"gdm_child_action", strerror (errno));
}
static void
custom_cmd (long cmd_id)
{
if (cmd_id < 0 || cmd_id >= GDM_CUSTOM_COMMAND_MAX) {
/* We are just feeling very paranoid */
gdm_error (_("custom_cmd: Custom command index %ld outside permitted range [0,%d)"),
cmd_id, GDM_CUSTOM_COMMAND_MAX);
return;
}
gchar * key_string = g_strdup_printf (_("%s%ld="), GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, cmd_id);
if (gdm_get_value_bool (key_string))
custom_cmd_no_restart (cmd_id);
else
custom_cmd_restart (cmd_id);
g_free(key_string);
}
static void
custom_cmd_restart (long cmd_id)
{
gdm_info (_("Executing custom command %ld with restart option..."), cmd_id);
gdm_final_cleanup ();
VE_IGNORE_EINTR (g_chdir ("/"));
#ifdef __linux__
change_to_first_and_clear (TRUE);
#endif /* __linux */
gchar * key_string = g_strdup_printf (_("%s%ld="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id);
char **argv;
argv = ve_split (gdm_get_value_string (key_string));
g_free(key_string);
if (argv != NULL && argv[0] != NULL)
VE_IGNORE_EINTR (execv (argv[0], argv));
g_strfreev (argv);
gdm_error (_("%s: Execution of custom command failed: %s"),
"gdm_child_action", strerror (errno));
}
static void
custom_cmd_no_restart (long cmd_id)
{
gdm_info (_("Executing custom command %ld with no restart option ..."), cmd_id);
pid_t pid = fork ();
if (pid < 0) {
/*failed fork*/
gdm_error (_("custom_cmd: forking process for custom command %ld failed"), cmd_id);
return;
}
else if (pid == 0) {
/* child */
char **argv;
gchar * key_string = g_strdup_printf (_("%s%ld="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id);
argv = ve_split (gdm_get_value_string (key_string));
g_free(key_string);
if (argv != NULL && argv[0] != NULL)
VE_IGNORE_EINTR (execv (argv[0], argv));
g_strfreev (argv);
gdm_error (_("%s: Execution of custom command failed: %s"),
"gdm_child_action", strerror (errno));
_exit (0);
}
else {
/* parent */
gint exitstatus = 0, status;
pid_t p_stat = waitpid (1, &exitstatus, WNOHANG);
if(p_stat > 0){
if G_LIKELY (WIFEXITED (exitstatus)){
status = WEXITSTATUS (exitstatus);
gdm_debug (_("custom_cmd: child %d returned %d"), p_stat, status);
}
return;
}
}
}
static gboolean
gdm_cleanup_children (void)
......@@ -1080,6 +1169,11 @@ gdm_do_logout_action (GdmLogoutAction logout_action)
break;
default:
/* This is a bit ugly but its the only place we can
check for the range of values */
if (logout_action >= GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST &&
logout_action <= GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST)
custom_cmd (logout_action - GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST);
break;
}
}
......@@ -2383,6 +2477,20 @@ gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data)
send_slave_ack (d, NULL);
}
} else if (strncmp (msg, GDM_SOP_CUSTOM_CMD " ",
strlen (GDM_SOP_CUSTOM_CMD " ")) == 0) {
GdmDisplay *d;
long slave_pid;
long cmd_id;
if (sscanf (msg, GDM_SOP_CUSTOM_CMD " %ld %ld", &slave_pid, &cmd_id) != 2)
return;
d = gdm_display_lookup (slave_pid);
if (d != NULL) {
custom_cmd (cmd_id);
send_slave_ack (d, NULL);
}
} else if (strcmp (msg, GDM_SOP_FLEXI_XSERVER) == 0) {
handle_flexi_server (NULL, TYPE_FLEXI, gdm_get_value_string (GDM_KEY_STANDARD_XSERVER),
TRUE /* handled */,
......@@ -3255,7 +3363,7 @@ gdm_handle_user_message (GdmConnection *conn, const gchar *msg, gpointer data)
if (logout_action == GDM_LOGOUT_ACTION_REBOOT)
g_string_append (msg, "!");
sep = ";";
}
}
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_get_value_string (GDM_KEY_SUSPEND))) {
g_string_append_printf (msg, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_SUSPEND);
......@@ -3263,6 +3371,21 @@ gdm_handle_user_message (GdmConnection *conn, const gchar *msg, gpointer data)
g_string_append (msg, "!");
sep = ";";
}
register int i = 0;
for (; i < GDM_CUSTOM_COMMAND_MAX; i++) {
gchar *key_string = NULL;
key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_get_value_string (key_string))) {
g_string_append_printf (msg, "%s%s%d", sep, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, i);
if (logout_action == (GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + i))
g_string_append (msg, "!");
sep = ";";
}
g_free(key_string);
}
g_string_append (msg, "\n");
gdm_connection_write (conn, msg->str);
g_string_free (msg, TRUE);
......@@ -3313,6 +3436,21 @@ gdm_handle_user_message (GdmConnection *conn, const gchar *msg, gpointer data)
was_ok = TRUE;
}
}
else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0) {
int cmd_index;
if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) {
gchar *key_string = NULL;
key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index);
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_get_value_string (key_string))) {
disp->logout_action =
GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
was_ok = TRUE;
}
g_free(key_string);
}
}
if (was_ok) {
gdm_connection_write (conn, "OK\n");
gdm_try_logout_action (disp);
......@@ -3366,6 +3504,21 @@ gdm_handle_user_message (GdmConnection *conn, const gchar *msg, gpointer data)
was_ok = TRUE;
}
}
else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0) {
int cmd_index;
if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) {
gchar *key_string = NULL;
key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index);
if (sysmenu && disp->attached &&
! ve_string_empty (gdm_get_value_string (key_string))) {
safe_logout_action =
GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
was_ok = TRUE;
}
g_free(key_string);
}
}
if (was_ok) {
gdm_connection_write (conn, "OK\n");
gdm_try_logout_action (disp);
......
......@@ -127,6 +127,7 @@ enum {
#define GDM_INTERRUPT_SELECT_USER 'U'
#define GDM_INTERRUPT_LOGIN_SOUND 'L'
#define GDM_INTERRUPT_THEME 'H'
#define GDM_INTERRUPT_CUSTOM_CMD 'M'
#define GDM_INTERRUPT_CANCEL 'X'
/* List delimiter for config file lists */
......@@ -234,6 +235,12 @@ enum {
#define GDM_KEY_FAILSAFE_XSERVER "daemon/FailsafeXServer="
#define GDM_KEY_X_KEEPS_CRASHING "daemon/XKeepsCrashing=" GDMCONFDIR "/XKeepsCrashing"
#define GDM_KEY_REBOOT "daemon/RebootCommand=" REBOOT_COMMAND
#define GDM_KEY_CUSTOM_CMD_TEMPLATE "customcommand/CustomCommand"
#define GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE "customcommand/CustomCommandLabel"
#define GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE "customcommand/CustomCommandLRLabel"
#define GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE "customcommand/CustomCommandText"
#define GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE "customcommand/CustomCommandTooltip"
#define GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE "customcommand/CustomCommandNoRestart"
#define GDM_KEY_ROOT_PATH "daemon/RootPath=/sbin:/usr/sbin:" GDM_USER_PATH
#define GDM_KEY_SERV_AUTHDIR "daemon/ServAuthDir=" AUTHDIR
#define GDM_KEY_SESSION_DESKTOP_DIR "daemon/SessionDesktopDir=/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/"
......@@ -434,11 +441,30 @@ enum {
typedef struct _GdmConnection GdmConnection;
#endif /* TYPEDEF_GDM_CONNECTION */
#ifndef TYPEDEF_GDM_CUSTOM_CMD
#define TYPEDEF_GDM_CUSTOM_CMD
typedef struct _GdmCustomCmd GdmCustomCmd;
#endif /* TYPEDEF_GDM_CUSTOM_CMD */
struct _GdmCustomCmd {
gchar *command; /* command(s) to execute */
gchar *command_label; /* button/menu item label */
gchar *command_lr_label; /* radio button/list item label */
gchar *command_text; /* warning dialog text */
gchar *command_tooltip; /* tooltip string */
gboolean command_no_restart; /* no restart flag */
};
#define GDM_CUSTOM_COMMAND_MAX 10 /* maximum number of supported custom commands */
/* Values between GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST and
GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST are reserved and should not be used */
typedef enum {
GDM_LOGOUT_ACTION_NONE = 0,
GDM_LOGOUT_ACTION_HALT,
GDM_LOGOUT_ACTION_REBOOT,
GDM_LOGOUT_ACTION_SUSPEND,
GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST,
GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST = GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + GDM_CUSTOM_COMMAND_MAX - 1,
GDM_LOGOUT_ACTION_LAST
} GdmLogoutAction;
......@@ -708,6 +734,9 @@ void gdm_final_cleanup (void);
#define GDM_SOP_SUSPEND_MACHINE "SUSPEND_MACHINE" /* no arguments */
#define GDM_SOP_CHOSEN_THEME "CHOSEN_THEME" /* <slave pid> <theme name> */
/*Execute custom cmd*/
#define GDM_SOP_CUSTOM_CMD "CUSTOM_CMD" /* <slave pid> <cmd id> */
/* Start a new standard X flexible server */
#define GDM_SOP_FLEXI_XSERVER "FLEXI_XSERVER" /* no arguments */
......@@ -731,6 +760,7 @@ void gdm_final_cleanup (void);
#define GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE "SoundOnLoginFailureFile" /* <sound file> */
#define GDM_NOTIFY_ADD_GTK_MODULES "AddGtkModules" /* <true/false as int> */
#define GDM_NOTIFY_GTK_MODULES_LIST "GtkModulesList" /* <modules list> */
#define GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "CustomCommand" /* <custom command path> */
/* commands, seel GDM_SLAVE_NOTIFY_COMMAND */
#define GDM_NOTIFY_DIRTY_SERVERS "DIRTY_SERVERS"
......@@ -1136,8 +1166,8 @@ void gdm_final_cleanup (void);
* Supported since: 2.5.90.0
* Answers:
* OK <action>;<action>;...
* Where action is one of HALT, REBOOT or SUSPEND. An empty list
* can also be returned if no action is possible. A '!' is appended
* Where action is one of HALT, REBOOT, SUSPEND or CUSTOM_CMDX (where X in [0,GDM_CUSTOM_COMMAND_MAX)).
* An empty list can also be returned if no action is possible. A '!' is appended
* to an action if it was already set with SET_LOGOUT_ACTION or
* SET_SAFE_LOGOUT_ACTION. Note that SET_LOGOUT_ACTION has precedence
* over SET_SAFE_LOGOUT_ACTION.
......@@ -1157,6 +1187,7 @@ void gdm_final_cleanup (void);
* HALT Set exit action to 'halt'
* REBOOT Set exit action to 'reboot'
* SUSPEND Set exit action to 'suspend'
* CUSTOM_CMDX Set exit action to 'custom command X' where where X in [0,GDM_CUSTOM_COMMAND_MAX)
* Answers:
* OK
* ERROR <err number> <english error description>
......@@ -1183,6 +1214,7 @@ void gdm_final_cleanup (void);
* HALT Set exit action to 'halt'
* REBOOT Set exit action to 'reboot'
* SUSPEND Set exit action to 'suspend'
* CUSTOM_CMDX Set exit action to 'custom command X' where where X in [0,GDM_CUSTOM_COMMAND_MAX)
*
* Answers:
* OK
......@@ -1193,10 +1225,11 @@ void gdm_final_cleanup (void);
* 200 = Too many messages
* 999 = Unknown error
*/
#define GDM_SUP_LOGOUT_ACTION_NONE "NONE"
#define GDM_SUP_LOGOUT_ACTION_HALT "HALT"
#define GDM_SUP_LOGOUT_ACTION_REBOOT "REBOOT"
#define GDM_SUP_LOGOUT_ACTION_SUSPEND "SUSPEND"
#define GDM_SUP_LOGOUT_ACTION_NONE "NONE"
#define GDM_SUP_LOGOUT_ACTION_HALT "HALT"
#define GDM_SUP_LOGOUT_ACTION_REBOOT "REBOOT"
#define GDM_SUP_LOGOUT_ACTION_SUSPEND "SUSPEND"
#define GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "CUSTOM_CMD"
/*
*/
#define GDM_SUP_QUERY_VT "QUERY_VT" /* None */
......
......@@ -115,6 +115,7 @@ static gchar *GdmFailsafeXserver = NULL;
static gchar *GdmXKeepsCrashing = NULL;
static gchar *GdmHalt = NULL;
static gchar *GdmReboot = NULL;
static GdmCustomCmd *GdmCustomCommands = NULL;
static gchar *GdmSuspend = NULL;
static gchar *GdmServAuthDir = NULL;
static gchar *GdmMulticastAddr;
......@@ -506,6 +507,37 @@ gdm_config_init (void)
&GdmPreFetchProgram, &string_type);
gdm_config_add_hash (GDM_KEY_PAM_STACK, &GdmPamStack, &string_type);
/* custom command string values */
GdmCustomCommands = g_new0 (GdmCustomCmd, GDM_CUSTOM_COMMAND_MAX);
register int i = 0;
gchar *key_string = NULL;
for (; i < GDM_CUSTOM_COMMAND_MAX; i++) {
/* For each possible custom command */
key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
GdmCustomCommands[i].command = NULL;
gdm_config_add_hash (key_string, &GdmCustomCommands[i].command, &string_type);
key_string = g_strdup_printf (_("%s%d=_Custom%d"), GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE, i, i);
GdmCustomCommands[i].command_label = NULL;
gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_label, &string_type);
key_string = g_strdup_printf (_("%s%d=Execute _custom command %d"), GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE, i, i);
GdmCustomCommands[i].command_lr_label = NULL;
gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_lr_label, &string_type);
key_string = g_strdup_printf (_("%s%d=Are you sure?"), GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE, i);
GdmCustomCommands[i].command_text = NULL;
gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_text, &string_type);
key_string = g_strdup_printf (_("%s%d=Execute custom command %d"), GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE, i, i);
GdmCustomCommands[i].command_tooltip = NULL;
gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_tooltip, &string_type);
key_string = g_strdup_printf (_("%s%d=false"), GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, i);
GdmCustomCommands[i].command_no_restart = FALSE;
gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_no_restart, &bool_type);
}
/* int values */
gdm_config_add_hash (GDM_KEY_XINERAMA_SCREEN, &GdmXineramaScreen, &int_type);
gdm_config_add_hash (GDM_KEY_RETRY_DELAY, &GdmRetryDelay, &int_type);
......@@ -1159,6 +1191,23 @@ _gdm_set_value_string (gchar *key, gchar *value_in, gboolean doing_update)
/* All others */
} else {
register int i = 0;
gchar * key_string = NULL;
for (; i < GDM_CUSTOM_COMMAND_MAX; i++) {
/* For each possible custom command */
key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
if(is_key (key, key_string)) {
if (value != NULL)
*setting = ve_get_first_working_command (value, FALSE);
else
*setting = NULL;
break;
}
}
g_free(key_string);
if (value != NULL)
*setting = g_strdup (value);
else {
......@@ -1192,6 +1241,19 @@ _gdm_set_value_string (gchar *key, gchar *value_in, gboolean doing_update)
notify_displays_string (GDM_NOTIFY_GTK_MODULES_LIST, *setting);
else if (is_key (key, GDM_KEY_TIMED_LOGIN))
notify_displays_string (GDM_NOTIFY_TIMED_LOGIN, *setting);
register int i = 0;
gchar * key_string = NULL;
for (; i < GDM_CUSTOM_COMMAND_MAX; i++) {
/* For each possible custom command */
key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
if (is_key (key, key_string)) {
g_free(key_string);
key_string = g_strdup_printf (_("%s%d"), GDM_NOTIFY_CUSTOM_CMD_TEMPLATE, i);
notify_displays_string (key_string, *setting);
}
}
g_free(key_string);
}
if (setting_copy != NULL)
......
......@@ -4955,6 +4955,17 @@ check_for_interruption (const char *msg)
case GDM_INTERRUPT_CANCEL:
do_cancel = TRUE;
break;
case GDM_INTERRUPT_CUSTOM_CMD:
if (d->attached &&
! ve_string_empty (&msg[2])) {
gchar *message = g_strdup_printf ("%s %ld %s",
GDM_SOP_CUSTOM_CMD,
(long)getpid (), &msg[2]);
gdm_slave_send (message, TRUE);
g_free (message);
}
return TRUE;
case GDM_INTERRUPT_THEME:
g_free (d->theme_name);
d->theme_name = NULL;
......@@ -5541,6 +5552,30 @@ gdm_slave_handle_notify (const char *msg)
}
}
}
} else if (strncmp (msg, GDM_NOTIFY_CUSTOM_CMD_TEMPLATE,
strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE)) == 0) {
if (sscanf (msg, GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "%d", &val) == 1) {
gchar * key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, val);
/* This assumes that the number of commands is < 100, i.e two digits
if that is not the case then this will fail */
gdm_set_value_string (key_string, ((gchar *)&msg[strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE) + 2]));
g_free(key_string);
if (d->attached) {
do_restart_greeter = TRUE;
if (restart_greeter_now) {
; /* will get restarted later */
} else if (d->type == TYPE_STATIC) {
/* FIXME: can't handle flexi servers like this
* without going all cranky */
if ( ! d->logged_in) {
gdm_slave_quick_exit (DISPLAY_REMANAGE);
} else {
remanage_asap = TRUE;
}
}
}
}
} else if (strncmp (msg, GDM_NOTIFY_REMOTE_GREETER " ",
strlen (GDM_NOTIFY_REMOTE_GREETER) + 1) == 0) {
gdm_set_value_string (GDM_KEY_REMOTE_GREETER,
......
......@@ -141,7 +141,7 @@
The Gnome Display Manager (GDM) is a display manager that
implements all significant features required for managing
local and remote displays. GDM was written from scratch and
does not contain any XDM / X Consortium code.
does not contain any XDM / X Consortium code.
</para>
<para>
......@@ -170,8 +170,9 @@
(ServAuthDir, PidFile, etc.), system applications (SoundProgram), etc.
Some configuration values depend on OS interfaces may need to be
modified to work on a given OS. Typical examples are HaltCommand,
RebootCommand, SuspendCommand, StandardXServer, Xnest, SoundProgram,
and the &quot;command&quot; value for each &quot;server-foo&quot;.
RebootCommand, CustomCommands, SuspendCommand, StandardXServer, Xnest,
SoundProgram, and the &quot;command&quot; value for each
&quot;server-foo&quot;.
</para>
<para>
......@@ -1860,7 +1861,7 @@ PostSession/
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>DefaultPath</term>
<listitem>
......@@ -2067,7 +2068,7 @@ PostSession/
missing, the shut down command is not available. Note that the
default for this value is not empty, so to disable
&quot;Shut Down&quot; it must be
set to an empty value.
set to an empty value.
</para>
</listitem>
</varlistentry>
......@@ -3965,6 +3966,122 @@ gdm:.my.domain
</variablelist>
</sect3>
<sect3 id="customcmdsection">
<title>Custom Commands</title>
<para>
You can create up to 10 different commands. Gaps between command
numbers are allowed and their relative positioning within the
section and with respect to each other is not important as long as
they conform to the permitted range of [0-9].
</para>
<variablelist>
<title>[customcommand]</title>
<varlistentry>
<term>CustomCommand[0-9]</term>
<listitem>
<synopsis>CustomCommand[0-9]=</synopsis>
<para>
Full path and arguments to command to be executed when user
selects <filename>n-th</filename> &quot;Custom Command&quot;
from the Actions menu. This can be a ';' separated list of
commands to try. If the value is empty or missing, then the
custom command is not available. By default this value is not
enabled, so to enable &quot;Custom Command&quot; it must be
set to a nonempty value. [0-9] represents the
<filename>CustomCommand</filename> suffix and can be an
integer between 0 and 9.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>CustomCommandLabel[0-9]</term>
<listitem>
<synopsis>CustomCommandLabel[0-9]=</synopsis>
<para>
Specifies the stock label that will be displayed on the
<filename>n-th</filename> &quot;Custom Command&quot;
buttons and menu items. If not specified the default value is
&quot;_Custom[0-9]&quot;. This option is only valid if
corresponding <filename>CustomCommand</filename> is defined.
[0-9] represents <filename>CustomCommand</filename> suffix
and can be an integer between 0 and 9.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>CustomCommandLRLabel[0-9]</term>
<listitem>
<synopsis>CustomCommandLRLabel[0-9]=</synopsis>
<para>
Specifies the stock label that will be displayed on the
<filename>n-th</filename> &quot;Custom Command&quot;
list items and radio buttons. If not specified the default
value is &quot;Execute _custom command [0-9]&quot;. This
option is only valid if corresponding
<filename>CustomCommand</filename> is defined. [0-9]
represents <filename>CustomCommand</filename> suffix and
can be an integer between 0 and 9.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>CustomCommandNoRestart[0-9]</term>
<listitem>
<synopsis>CustomCommandNoRestart[0-9]=</synopsis>
<para>
Specifies if gdm will be stopped/restarted once
<filename>n-th</filename> &quot;Custom Command&quot;
has been executed. If not specified the default value is
&quot;false&quot;. This option is only valid if corresponding
<filename>CustomCommand</filename> is defined. [0-9]
represents <filename>CustomCommand</filename> suffix and
can be an integer between 0 and 9.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>CustomCommandText[0-9]</term>
<listitem>
<synopsis>CustomCommandText[0-9]=</synopsis>
<para>
Specifies the message that will be displayed on the warning
dialog box once <filename>n-th</filename>
&quot;Custom Command&quot; button/menu item/radio button/list
item has been activated. If not specified the default value is
&quot;Are you sure?&quot;. This option is only valid if
corresponding <filename>CustomCommand</filename> is defined.
[0-9] represents <filename>CustomCommand</filename> suffix and
can be an integer between 0 and 9.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>CustomCommandTooltip[0-9]</term>
<listitem>
<synopsis>CustomCommandTooltip[0-9]=</synopsis>
<para>
Specifies the message that will be displayed on tooltips for
<filename>n-th</filename> &quot;Custom Command&quot;
entries. If not specified the default value is &quot;Execute
custom command [0-9]&quot;. This option is only valid if
corresponding <filename>CustomCommand</filename> is defined.
[0-9] represents <filename>CustomCommand</filename> suffix and
can be an integer between 0 and 9.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3 id="serverdefs">
<title>X Server Definitions</title>
......@@ -4665,8 +4782,8 @@ QUERY_LOGOUT_ACTION: Query which logout actions are possible
Supported since: 2.5.90.0