aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorPaul Eggert2018-12-01 23:06:06 -0800
committerPaul Eggert2018-12-01 23:08:48 -0800
commit92282cb50248117185774cf8076d1ff83d501be7 (patch)
tree0e03dbd31e82b3f962b54c88ce0be1290b23d7ff /lib-src
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.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/emacsclient.c130
1 files changed, 77 insertions, 53 deletions
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;