diff options
| author | Paul Eggert | 2018-11-22 23:42:50 -0800 |
|---|---|---|
| committer | Paul Eggert | 2018-11-22 23:46:14 -0800 |
| commit | 5daba9d8a55d4fa28600f097490bc675eb848957 (patch) | |
| tree | 0ecad1fdf29941b093464ca456bad21f8ecb1b31 /lib-src | |
| parent | 4dc73269561237d04280b0a212eee603f1e73c9f (diff) | |
| download | emacs-5daba9d8a55d4fa28600f097490bc675eb848957.tar.gz emacs-5daba9d8a55d4fa28600f097490bc675eb848957.zip | |
emacsclient: tidy socket failure cleanup
* lib-src/emacsclient.c (set_tcp_socket, set_local_socket):
Close socket (instead of leaking it) when ‘connect’ fails.
(socket_status): Return errno if stat fails and -1 if we don’t own.
(set_local_socket): Simplify based on socket_status change.
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/emacsclient.c | 50 |
1 files changed, 23 insertions, 27 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 6f2fb20ae52..ef510b1f8bc 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -485,7 +485,7 @@ message (bool is_error, const char *format, ...) | |||
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | /* Decode the options from argv and argc. | 487 | /* Decode the options from argv and argc. |
| 488 | The global variable `optind' will say how many arguments we used up. */ | 488 | The global variable 'optind' will say how many arguments we used up. */ |
| 489 | 489 | ||
| 490 | static void | 490 | static void |
| 491 | decode_options (int argc, char **argv) | 491 | decode_options (int argc, char **argv) |
| @@ -584,7 +584,7 @@ decode_options (int argc, char **argv) | |||
| 584 | 584 | ||
| 585 | /* If the -c option is used (without -t) and no --display argument | 585 | /* If the -c option is used (without -t) and no --display argument |
| 586 | is provided, try $DISPLAY. | 586 | is provided, try $DISPLAY. |
| 587 | Without the -c option, we used to set `display' to $DISPLAY by | 587 | Without the -c option, we used to set 'display' to $DISPLAY by |
| 588 | default, but this changed the default behavior and is sometimes | 588 | default, but this changed the default behavior and is sometimes |
| 589 | inconvenient. So we force users to use "--display $DISPLAY" if | 589 | inconvenient. So we force users to use "--display $DISPLAY" if |
| 590 | they want Emacs to connect to their current display. | 590 | they want Emacs to connect to their current display. |
| @@ -1011,6 +1011,7 @@ set_tcp_socket (const char *local_server_file) | |||
| 1011 | if (connect (s, &server.sa, sizeof server.in) != 0) | 1011 | if (connect (s, &server.sa, sizeof server.in) != 0) |
| 1012 | { | 1012 | { |
| 1013 | sock_err_message ("connect"); | 1013 | sock_err_message ("connect"); |
| 1014 | CLOSE_SOCKET (s); | ||
| 1014 | return INVALID_SOCKET; | 1015 | return INVALID_SOCKET; |
| 1015 | } | 1016 | } |
| 1016 | 1017 | ||
| @@ -1083,8 +1084,8 @@ find_tty (const char **tty_type, const char **tty_name, bool noabort) | |||
| 1083 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM | 1084 | # ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 1084 | 1085 | ||
| 1085 | /* Three possibilities: | 1086 | /* Three possibilities: |
| 1086 | 2 - can't be `stat'ed (sets errno) | 1087 | >0 - 'stat' failed with this errno value |
| 1087 | 1 - isn't owned by us | 1088 | -1 - isn't owned by us |
| 1088 | 0 - success: none of the above */ | 1089 | 0 - success: none of the above */ |
| 1089 | 1090 | ||
| 1090 | static int | 1091 | static int |
| @@ -1092,11 +1093,11 @@ socket_status (const char *name) | |||
| 1092 | { | 1093 | { |
| 1093 | struct stat statbfr; | 1094 | struct stat statbfr; |
| 1094 | 1095 | ||
| 1095 | if (stat (name, &statbfr) == -1) | 1096 | if (stat (name, &statbfr) != 0) |
| 1096 | return 2; | 1097 | return errno; |
| 1097 | 1098 | ||
| 1098 | if (statbfr.st_uid != geteuid ()) | 1099 | if (statbfr.st_uid != geteuid ()) |
| 1099 | return 1; | 1100 | return -1; |
| 1100 | 1101 | ||
| 1101 | return 0; | 1102 | return 0; |
| 1102 | } | 1103 | } |
| @@ -1201,8 +1202,6 @@ set_local_socket (const char *local_socket_name) | |||
| 1201 | return INVALID_SOCKET; | 1202 | return INVALID_SOCKET; |
| 1202 | } | 1203 | } |
| 1203 | 1204 | ||
| 1204 | int sock_status; | ||
| 1205 | int saved_errno; | ||
| 1206 | char const *server_name = local_socket_name; | 1205 | char const *server_name = local_socket_name; |
| 1207 | char const *tmpdir = NULL; | 1206 | char const *tmpdir = NULL; |
| 1208 | char *tmpdir_storage = NULL; | 1207 | char *tmpdir_storage = NULL; |
| @@ -1250,8 +1249,7 @@ set_local_socket (const char *local_socket_name) | |||
| 1250 | } | 1249 | } |
| 1251 | 1250 | ||
| 1252 | /* See if the socket exists, and if it's owned by us. */ | 1251 | /* See if the socket exists, and if it's owned by us. */ |
| 1253 | sock_status = socket_status (server.un.sun_path); | 1252 | int sock_status = socket_status (server.un.sun_path); |
| 1254 | saved_errno = errno; | ||
| 1255 | if (sock_status && tmpdir) | 1253 | if (sock_status && tmpdir) |
| 1256 | { | 1254 | { |
| 1257 | /* Failing that, see if LOGNAME or USER exist and differ from | 1255 | /* Failing that, see if LOGNAME or USER exist and differ from |
| @@ -1289,10 +1287,7 @@ set_local_socket (const char *local_socket_name) | |||
| 1289 | free (user_socket_name); | 1287 | free (user_socket_name); |
| 1290 | 1288 | ||
| 1291 | sock_status = socket_status (server.un.sun_path); | 1289 | sock_status = socket_status (server.un.sun_path); |
| 1292 | saved_errno = errno; | ||
| 1293 | } | 1290 | } |
| 1294 | else | ||
| 1295 | errno = saved_errno; | ||
| 1296 | } | 1291 | } |
| 1297 | } | 1292 | } |
| 1298 | 1293 | ||
| @@ -1301,14 +1296,20 @@ set_local_socket (const char *local_socket_name) | |||
| 1301 | 1296 | ||
| 1302 | switch (sock_status) | 1297 | switch (sock_status) |
| 1303 | { | 1298 | { |
| 1304 | case 1: | 1299 | case -1: |
| 1305 | /* There's a socket, but it isn't owned by us. */ | 1300 | /* There's a socket, but it isn't owned by us. */ |
| 1306 | message (true, "%s: Invalid socket owner\n", progname); | 1301 | message (true, "%s: Invalid socket owner\n", progname); |
| 1307 | return INVALID_SOCKET; | 1302 | break; |
| 1303 | |||
| 1304 | case 0: | ||
| 1305 | if (connect (s, &server.sa, sizeof server.un) == 0) | ||
| 1306 | return s; | ||
| 1307 | message (true, "%s: connect: %s\n", progname, strerror (errno)); | ||
| 1308 | break; | ||
| 1308 | 1309 | ||
| 1309 | case 2: | 1310 | default: |
| 1310 | /* `stat' failed */ | 1311 | /* 'stat' failed. */ |
| 1311 | if (saved_errno == ENOENT) | 1312 | if (sock_status == ENOENT) |
| 1312 | message (true, | 1313 | message (true, |
| 1313 | ("%s: can't find socket; have you started the server?\n" | 1314 | ("%s: can't find socket; have you started the server?\n" |
| 1314 | "%s: To start the server in Emacs," | 1315 | "%s: To start the server in Emacs," |
| @@ -1317,16 +1318,11 @@ set_local_socket (const char *local_socket_name) | |||
| 1317 | else | 1318 | else |
| 1318 | message (true, "%s: can't stat %s: %s\n", | 1319 | message (true, "%s: can't stat %s: %s\n", |
| 1319 | progname, server.un.sun_path, strerror (sock_status)); | 1320 | progname, server.un.sun_path, strerror (sock_status)); |
| 1320 | return INVALID_SOCKET; | 1321 | break; |
| 1321 | } | 1322 | } |
| 1322 | 1323 | ||
| 1323 | if (connect (s, &server.sa, sizeof server.un) != 0) | 1324 | CLOSE_SOCKET (s); |
| 1324 | { | 1325 | return INVALID_SOCKET; |
| 1325 | message (true, "%s: connect: %s\n", progname, strerror (errno)); | ||
| 1326 | return INVALID_SOCKET; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | return s; | ||
| 1330 | } | 1326 | } |
| 1331 | # endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */ | 1327 | # endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */ |
| 1332 | 1328 | ||