/* Session management module for systems which understand the X Session
management protocol.
-Copyright (C) 2002-2014 Free Software Foundation, Inc.
+Copyright (C) 2002-2016 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs 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 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
#include <unistd.h>
#include <sys/param.h>
+#include <errno.h>
#include <stdio.h>
#include "lisp.h"
-#include "systime.h"
-#include "sysselect.h"
#include "frame.h"
#include "termhooks.h"
#include "xterm.h"
/* A flag that says if we are in shutdown interactions or not. */
-static int doing_interact;
+static bool doing_interact;
/* The session manager object for the session manager connection. */
kbd_buffer_store_event (&emacs_event);
}
-/* Return non-zero if we have a connection to a session manager. */
+/* Return true if we have a connection to a session manager. */
-int
+bool
x_session_have_connection (void)
{
return ice_fd != -1;
static void
smc_interact_CB (SmcConn smcConn, SmPointer clientData)
{
- doing_interact = True;
+ doing_interact = true;
emacs_event.kind = SAVE_SESSION_EVENT;
emacs_event.arg = Qnil;
}
int val_idx = 0, vp_idx = 0;
int props_idx = 0;
int i;
- char *cwd = get_current_dir_name ();
char *smid_opt, *chdir_opt = NULL;
+ Lisp_Object user_login_name = Fuser_login_name (Qnil);
+
+ // Must have these.
+ if (! STRINGP (Vinvocation_name) || ! STRINGP (user_login_name))
+ return;
/* How to start a new instance of Emacs. */
props[props_idx] = &prop_ptr[props_idx];
props[props_idx]->type = xstrdup (SmARRAY8);
props[props_idx]->num_vals = 1;
props[props_idx]->vals = &values[val_idx++];
- props[props_idx]->vals[0].length = SBYTES (Vuser_login_name);
- props[props_idx]->vals[0].value = SDATA (Vuser_login_name);
+ props[props_idx]->vals[0].length = SBYTES (user_login_name);
+ props[props_idx]->vals[0].value = SDATA (user_login_name);
++props_idx;
-
+ char *cwd = get_current_dir_name ();
if (cwd)
{
props[props_idx] = &prop_ptr[props_idx];
props[props_idx]->name = xstrdup (SmRestartCommand);
props[props_idx]->type = xstrdup (SmLISTofARRAY8);
/* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */
- if (INT_MAX - 3 < initial_argc)
+ if (INT_ADD_WRAPV (initial_argc, 3, &i))
memory_full (SIZE_MAX);
- i = 3 + initial_argc;
props[props_idx]->num_vals = i;
vp = xnmalloc (i, sizeof *vp);
props[props_idx]->vals = vp;
props[props_idx]->vals[vp_idx++].value = emacs_program;
smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1);
- strcpy (smid_opt, SMID_OPT);
- strcat (smid_opt, client_id);
+ strcpy (stpcpy (smid_opt, SMID_OPT), client_id);
props[props_idx]->vals[vp_idx].length = strlen (smid_opt);
props[props_idx]->vals[vp_idx++].value = smid_opt;
if (cwd)
{
chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1);
- strcpy (chdir_opt, CHDIR_OPT);
- strcat (chdir_opt, cwd);
+ strcpy (stpcpy (chdir_opt, CHDIR_OPT), cwd);
props[props_idx]->vals[vp_idx].length = strlen (chdir_opt);
props[props_idx]->vals[vp_idx++].value = chdir_opt;
-1, -1, 1, 1,
CopyFromParent, CopyFromParent, CopyFromParent);
+ validate_x_resource_name ();
class_hints.res_name = SSDATA (Vx_resource_name);
class_hints.res_class = SSDATA (Vx_resource_class);
XSetClassHint (dpyinfo->display, w, &class_hints);
SmcCallbacks callbacks;
ptrdiff_t name_len = 0;
+ /* libSM seems to crash if pwd is missing - see bug#18851. */
+ if (! get_current_dir_name ())
+ {
+ fprintf (stderr, "Disabling session management due to pwd error: %s\n",
+ emacs_strerror (errno));
+ return;
+ }
+
ice_fd = -1;
- doing_interact = False;
+ doing_interact = false;
/* Check if we where started by the session manager. If so, we will
have a previous id. */
- if (! EQ (Vx_session_previous_id, Qnil) && STRINGP (Vx_session_previous_id))
+ if (STRINGP (Vx_session_previous_id))
previous_id = SSDATA (Vx_session_previous_id);
/* Construct the path to the Emacs program. */
- if (! EQ (Vinvocation_directory, Qnil))
+ if (STRINGP (Vinvocation_directory))
name_len += SBYTES (Vinvocation_directory);
- name_len += SBYTES (Vinvocation_name);
+ if (STRINGP (Vinvocation_name))
+ name_len += SBYTES (Vinvocation_name);
/* This malloc will not be freed, but it is only done once, and hopefully
not very large */
emacs_program = xmalloc (name_len + 1);
- emacs_program[0] = '\0';
+ char *z = emacs_program;
- if (! EQ (Vinvocation_directory, Qnil))
- lispstrcpy (emacs_program, Vinvocation_directory);
- strcat (emacs_program, SSDATA (Vinvocation_name));
+ if (STRINGP (Vinvocation_directory))
+ z = lispstpcpy (z, Vinvocation_directory);
+ if (STRINGP (Vinvocation_name))
+ lispstpcpy (z, Vinvocation_name);
/* The SM protocol says all callbacks are mandatory, so set up all
here and in the mask passed to SmcOpenConnection. */
Do not call this function yourself. */)
(Lisp_Object event)
{
- int kill_emacs = CONSP (event) && CONSP (XCDR (event))
- && EQ (Qt, XCAR (XCDR (event)));
+ bool kill_emacs = (CONSP (event) && CONSP (XCDR (event))
+ && EQ (Qt, XCAR (XCDR (event))));
/* Check doing_interact so that we don't do anything if someone called
this at the wrong time. */
if (doing_interact && ! kill_emacs)
{
- Bool cancel_shutdown = False;
-
- cancel_shutdown = ! EQ (call0 (intern ("emacs-session-save")), Qnil);
+ bool cancel_shutdown = ! NILP (call0 (intern ("emacs-session-save")));
SmcInteractDone (smc_conn, cancel_shutdown);
SmcSaveYourselfDone (smc_conn, True);
- doing_interact = False;
+ doing_interact = false;
}
else if (kill_emacs)
{
prevent. Fix this in next version. */
Fkill_emacs (Qnil);
-#if 0
+#if false
/* This will not be reached, but we want kill-emacs-hook to be run. */
SmcCloseConnection (smc_conn, 0, 0);
ice_connection_closed ();
Changing the value does not change the session id used by Emacs.
The value is nil if no session manager is running.
See also `x-session-previous-id', `emacs-save-session-functions',
-`emacs-session-save' and `emacs-session-restore'." */);
+`emacs-session-save' and `emacs-session-restore'. */);
Vx_session_id = Qnil;
DEFVAR_LISP ("x-session-previous-id", Vx_session_previous_id,
same, depending on how the session manager works.
See also `emacs-save-session-functions', `emacs-session-save' and
-`emacs-session-restore'." */);
+`emacs-session-restore'. */);
Vx_session_previous_id = Qnil;
defsubr (&Shandle_save_session);