aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2018-12-01 23:06:06 -0800
committerPaul Eggert2018-12-01 23:08:48 -0800
commit92282cb50248117185774cf8076d1ff83d501be7 (patch)
tree0e03dbd31e82b3f962b54c88ce0be1290b23d7ff
parent070ef95c1007cb3d54e04bc337d9fb5463912cc1 (diff)
downloademacs-92282cb50248117185774cf8076d1ff83d501be7.tar.gz
emacs-92282cb50248117185774cf8076d1ff83d501be7.zip
emacsclient: prefer XDG_RUNTIME_DIR (Bug#33367)
* lib-src/emacsclient.c: Disable -Wformat-truncation=2, to avoid false alarms about the new snprintf calls. (local_sockname): New function. (set_local_socket): Use it. Prefer XDG_RUNTIME_DIR (if set) for location of socket directory. Avoid unnecessary memory allocation by using snprintf to destination. * lisp/server.el (server-socket-dir): Prefer XDG_RUNTIME_DIR if set.
-rw-r--r--admin/notes/multi-tty6
-rw-r--r--doc/misc/efaq.texi6
-rw-r--r--etc/NEWS6
-rw-r--r--lib-src/emacsclient.c130
-rw-r--r--lisp/server.el5
5 files changed, 96 insertions, 57 deletions
diff --git a/admin/notes/multi-tty b/admin/notes/multi-tty
index 5b34bb598ef..619af8e7fab 100644
--- a/admin/notes/multi-tty
+++ b/admin/notes/multi-tty
@@ -171,7 +171,11 @@ preload-emacs "$name" wait
171name="$1" 171name="$1"
172waitp="$2" 172waitp="$2"
173screendir="/var/run/screen/S-$USER" 173screendir="/var/run/screen/S-$USER"
174serverdir="/tmp/emacs$UID" 174if [ "${XDG_RUNTIME_DIR+set}" ]; then
175 serverdir="$XDG_RUNTIME_DIR/emacs"
176else
177 serverdir="${TMPDIR-/tmp}/emacs$UID"
178fi
175emacs=/usr/bin/emacs-multi-tty # Or wherever you installed your multi-tty Emacs 179emacs=/usr/bin/emacs-multi-tty # Or wherever you installed your multi-tty Emacs
176 180
177if [ -z "$name" ]; then 181if [ -z "$name" ]; then
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index 0d4e4ba8bdd..d457267c248 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -2005,8 +2005,10 @@ or by invoking @code{server-start} from @file{.emacs}:
2005(if (@var{some conditions are met}) (server-start)) 2005(if (@var{some conditions are met}) (server-start))
2006@end lisp 2006@end lisp
2007 2007
2008When this is done, Emacs creates a Unix domain socket named 2008When this is done, Emacs by default creates a Unix domain socket named
2009@file{server} in @file{/tmp/emacs@var{userid}}. See 2009@file{server} in a well-known directory, typically
2010@file{$XDG_RUNTIME_DIR/emacs} if Emacs is running under an X Window System
2011desktop and @file{$TMPDIR/emacs@var{userid}} otherwise. See the variable
2010@code{server-socket-dir}. 2012@code{server-socket-dir}.
2011 2013
2012To get your news reader, mail reader, etc., to invoke 2014To get your news reader, mail reader, etc., to invoke
diff --git a/etc/NEWS b/etc/NEWS
index 1ddc565b8ba..6297d078798 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -128,6 +128,12 @@ command-line value specified via '--socket-name' will override the
128environment, and the natural default to TMPDIR, then "/tmp", continues 128environment, and the natural default to TMPDIR, then "/tmp", continues
129to apply. 129to apply.
130 130
131+++
132*** Emacs and emacsclient now default to $XDG_RUNTIME_DIR/emacs
133as the directory for client/server sockets, if Emacs is running
134under an X Window System desktop that sets the XDG_RUNTIME_DIR
135environment variable to indicate where session sockets should go.
136
131--- 137---
132*** When run by root, emacsclient no longer connects to non-root sockets. 138*** When run by root, emacsclient no longer connects to non-root sockets.
133(Instead you can use Tramp methods to run root commands in a non-root Emacs.) 139(Instead you can use Tramp methods to run root commands in a non-root Emacs.)
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index c67d34f77ff..ba72651343f 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -87,6 +87,11 @@ char *w32_getenv (const char *);
87#define VERSION "unspecified" 87#define VERSION "unspecified"
88#endif 88#endif
89 89
90/* Work around GCC bug 88251. */
91#if GNUC_PREREQ (7, 0, 0)
92# pragma GCC diagnostic ignored "-Wformat-truncation=2"
93#endif
94
90 95
91/* Name used to invoke this program. */ 96/* Name used to invoke this program. */
92static char const *progname; 97static char const *progname;
@@ -1271,10 +1276,41 @@ act_on_signals (HSOCKET emacs_socket)
1271 } 1276 }
1272} 1277}
1273 1278
1274/* Create a local socket and connect it to Emacs. */ 1279/* Create in SOCKNAME (of size SOCKNAMESIZE) a name for a local socket.
1280 The first TMPDIRLEN bytes of SOCKNAME are already initialized to be
1281 the name of a temporary directory. Use UID and SERVER_NAME to
1282 concoct the name. Return the total length of the name if successful,
1283 -1 if it does not fit (and store a truncated name in that case).
1284 Fail if TMPDIRLEN is out of range. */
1285
1286static int
1287local_sockname (char *sockname, int socknamesize, int tmpdirlen,
1288 uintmax_t uid, char const *server_name)
1289{
1290 /* If ! (0 <= TMPDIRLEN && TMPDIRLEN < SOCKNAMESIZE) the truncated
1291 temporary directory name is already in SOCKNAME, so nothing more
1292 need be stored. */
1293 if (0 <= tmpdirlen)
1294 {
1295 int remaining = socknamesize - tmpdirlen;
1296 if (0 < remaining)
1297 {
1298 int suffixlen = snprintf (&sockname[tmpdirlen], remaining,
1299 "/emacs%"PRIuMAX"/%s", uid, server_name);
1300 if (0 <= suffixlen && suffixlen < remaining)
1301 return tmpdirlen + suffixlen;
1302 }
1303 }
1304 return -1;
1305}
1306
1307/* Create a local socket for SERVER_NAME and connect it to Emacs. If
1308 SERVER_NAME is a file name component, the local socket name
1309 relative to a well-known location in a temporary directory.
1310 Otherwise, the local socket name is SERVER_NAME. */
1275 1311
1276static HSOCKET 1312static HSOCKET
1277set_local_socket (const char *local_socket_name) 1313set_local_socket (char const *server_name)
1278{ 1314{
1279 union { 1315 union {
1280 struct sockaddr_un un; 1316 struct sockaddr_un un;
@@ -1288,55 +1324,54 @@ set_local_socket (const char *local_socket_name)
1288 return INVALID_SOCKET; 1324 return INVALID_SOCKET;
1289 } 1325 }
1290 1326
1291 char const *server_name = local_socket_name; 1327 char *sockname = server.un.sun_path;
1292 char const *tmpdir = NULL; 1328 enum { socknamesize = sizeof server.un.sun_path };
1293 char *tmpdir_storage = NULL; 1329 int tmpdirlen = -1;
1294 char *socket_name_storage = NULL; 1330 int socknamelen = -1;
1295 static char const subdir_format[] = "/emacs%"PRIuMAX"/";
1296 int subdir_size_bound = (sizeof subdir_format - sizeof "%"PRIuMAX
1297 + INT_STRLEN_BOUND (uid_t) + 1);
1298 1331
1299 if (! (strchr (local_socket_name, '/') 1332 if (strchr (server_name, '/')
1300 || (ISSLASH ('\\') && strchr (local_socket_name, '\\')))) 1333 || (ISSLASH ('\\') && strchr (server_name, '\\')))
1334 socknamelen = snprintf (sockname, socknamesize, "%s", server_name);
1335 else
1301 { 1336 {
1302 /* socket_name is a file name component. */ 1337 /* socket_name is a file name component. */
1303 uintmax_t uid = geteuid (); 1338 char const *xdg_runtime_dir = egetenv ("XDG_RUNTIME_DIR");
1304 tmpdir = egetenv ("TMPDIR"); 1339 if (xdg_runtime_dir)
1305 if (!tmpdir) 1340 socknamelen = snprintf (sockname, socknamesize, "%s/emacs/%s",
1341 xdg_runtime_dir, server_name);
1342 else
1306 { 1343 {
1344 char const *tmpdir = egetenv ("TMPDIR");
1345 if (tmpdir)
1346 tmpdirlen = snprintf (sockname, socknamesize, "%s", tmpdir);
1347 else
1348 {
1307# ifdef DARWIN_OS 1349# ifdef DARWIN_OS
1308# ifndef _CS_DARWIN_USER_TEMP_DIR 1350# ifndef _CS_DARWIN_USER_TEMP_DIR
1309# define _CS_DARWIN_USER_TEMP_DIR 65537 1351# define _CS_DARWIN_USER_TEMP_DIR 65537
1310# endif 1352# endif
1311 size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, 0); 1353 size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR,
1312 if (n > 0) 1354 sockname, socknamesize);
1313 { 1355 if (0 < n && n < (size_t) -1)
1314 tmpdir = tmpdir_storage = xmalloc (n); 1356 tmpdirlen = min (n - 1, socknamesize);
1315 confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir_storage, n);
1316 }
1317 else
1318# endif 1357# endif
1319 tmpdir = "/tmp"; 1358 if (tmpdirlen < 0)
1359 tmpdirlen = snprintf (sockname, socknamesize, "/tmp");
1360 }
1361 socknamelen = local_sockname (sockname, socknamesize, tmpdirlen,
1362 geteuid (), server_name);
1320 } 1363 }
1321 socket_name_storage =
1322 xmalloc (strlen (tmpdir) + strlen (server_name) + subdir_size_bound);
1323 char *z = stpcpy (socket_name_storage, tmpdir);
1324 strcpy (z + sprintf (z, subdir_format, uid), server_name);
1325 local_socket_name = socket_name_storage;
1326 } 1364 }
1327 1365
1328 if (strlen (local_socket_name) < sizeof server.un.sun_path) 1366 if (! (0 <= socknamelen && socknamelen < socknamesize))
1329 strcpy (server.un.sun_path, local_socket_name);
1330 else
1331 { 1367 {
1332 message (true, "%s: socket-name %s too long\n", 1368 message (true, "%s: socket-name %s... too long\n", progname, sockname);
1333 progname, local_socket_name);
1334 fail (); 1369 fail ();
1335 } 1370 }
1336 1371
1337 /* See if the socket exists, and if it's owned by us. */ 1372 /* See if the socket exists, and if it's owned by us. */
1338 int sock_status = socket_status (server.un.sun_path); 1373 int sock_status = socket_status (sockname);
1339 if (sock_status && tmpdir) 1374 if (sock_status)
1340 { 1375 {
1341 /* Failing that, see if LOGNAME or USER exist and differ from 1376 /* Failing that, see if LOGNAME or USER exist and differ from
1342 our euid. If so, look for a socket based on the UID 1377 our euid. If so, look for a socket based on the UID
@@ -1355,31 +1390,20 @@ set_local_socket (const char *local_socket_name)
1355 if (pw && (pw->pw_uid != geteuid ())) 1390 if (pw && (pw->pw_uid != geteuid ()))
1356 { 1391 {
1357 /* We're running under su, apparently. */ 1392 /* We're running under su, apparently. */
1358 uintmax_t uid = pw->pw_uid; 1393 socknamelen = local_sockname (sockname, socknamesize, tmpdirlen,
1359 char *user_socket_name 1394 pw->pw_uid, server_name);
1360 = xmalloc (strlen (tmpdir) + strlen (server_name) 1395 if (socknamelen < 0)
1361 + subdir_size_bound);
1362 char *z = stpcpy (user_socket_name, tmpdir);
1363 strcpy (z + sprintf (z, subdir_format, uid), server_name);
1364
1365 if (strlen (user_socket_name) < sizeof server.un.sun_path)
1366 strcpy (server.un.sun_path, user_socket_name);
1367 else
1368 { 1396 {
1369 message (true, "%s: socket-name %s too long\n", 1397 message (true, "%s: socket-name %s... too long\n",
1370 progname, user_socket_name); 1398 progname, sockname);
1371 exit (EXIT_FAILURE); 1399 exit (EXIT_FAILURE);
1372 } 1400 }
1373 free (user_socket_name);
1374 1401
1375 sock_status = socket_status (server.un.sun_path); 1402 sock_status = socket_status (sockname);
1376 } 1403 }
1377 } 1404 }
1378 } 1405 }
1379 1406
1380 free (socket_name_storage);
1381 free (tmpdir_storage);
1382
1383 switch (sock_status) 1407 switch (sock_status)
1384 { 1408 {
1385 case -1: 1409 case -1:
@@ -1403,7 +1427,7 @@ set_local_socket (const char *local_socket_name)
1403 progname, progname); 1427 progname, progname);
1404 else 1428 else
1405 message (true, "%s: can't stat %s: %s\n", 1429 message (true, "%s: can't stat %s: %s\n",
1406 progname, server.un.sun_path, strerror (sock_status)); 1430 progname, sockname, strerror (sock_status));
1407 break; 1431 break;
1408 } 1432 }
1409 1433
@@ -1421,12 +1445,12 @@ set_socket (bool no_exit_if_error)
1421 INITIALIZE (); 1445 INITIALIZE ();
1422 1446
1423#ifdef SOCKETS_IN_FILE_SYSTEM 1447#ifdef SOCKETS_IN_FILE_SYSTEM
1424 /* Explicit --socket-name argument. */
1425 if (!socket_name) 1448 if (!socket_name)
1426 socket_name = egetenv ("EMACS_SOCKET_NAME"); 1449 socket_name = egetenv ("EMACS_SOCKET_NAME");
1427 1450
1428 if (socket_name) 1451 if (socket_name)
1429 { 1452 {
1453 /* Explicit --socket-name argument, or environment variable. */
1430 s = set_local_socket (socket_name); 1454 s = set_local_socket (socket_name);
1431 if (s != INVALID_SOCKET || no_exit_if_error) 1455 if (s != INVALID_SOCKET || no_exit_if_error)
1432 return s; 1456 return s;
diff --git a/lisp/server.el b/lisp/server.el
index d0a8ca313e3..28e789a4c88 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -281,7 +281,10 @@ changed while a server is running."
281 (if internal--daemon-sockname 281 (if internal--daemon-sockname
282 (file-name-directory internal--daemon-sockname) 282 (file-name-directory internal--daemon-sockname)
283 (and (featurep 'make-network-process '(:family local)) 283 (and (featurep 'make-network-process '(:family local))
284 (format "%s/emacs%d" (or (getenv "TMPDIR") "/tmp") (user-uid)))) 284 (let ((xdg_runtime_dir (getenv "XDG_RUNTIME_DIR")))
285 (if xdg_runtime_dir
286 (format "%s/emacs" xdg_runtime_dir)
287 (format "%s/emacs%d" (or (getenv "TMPDIR") "/tmp") (user-uid))))))
285 "The directory in which to place the server socket. 288 "The directory in which to place the server socket.
286If local sockets are not supported, this is nil.") 289If local sockets are not supported, this is nil.")
287 290