diff options
| author | Paul Eggert | 2018-11-22 09:21:22 -0800 |
|---|---|---|
| committer | Paul Eggert | 2018-11-22 09:24:51 -0800 |
| commit | 5773470ff3a85640fbaeab1a88edc3fa395184bd (patch) | |
| tree | eff420595f2bf7125d705f2f826a54360127d1c6 | |
| parent | a344d9937bb7edfbfbea13dca1569fcdcad25ac2 (diff) | |
| download | emacs-5773470ff3a85640fbaeab1a88edc3fa395184bd.tar.gz emacs-5773470ff3a85640fbaeab1a88edc3fa395184bd.zip | |
emacsclient: sockaddr portability fixes
* lib-src/emacsclient.c (get_server_config, set_tcp_socket)
(set_local_socket): Initialize any platform-specific extensions
of struct to zero, just in case.
(set_tcp_socket, set_local_socket): Don’t assume struct
layout details that POSIX does not specify.
Use union to sidestep some problems with strict aliasing.
Remove unnecessary casts.
| -rw-r--r-- | lib-src/emacsclient.c | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 4ab97c3c50c..e6eb3c74cf7 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -959,6 +959,7 @@ get_server_config (const char *config_file, struct sockaddr_in *server, | |||
| 959 | exit (EXIT_FAILURE); | 959 | exit (EXIT_FAILURE); |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | memset (server, 0, sizeof *server); | ||
| 962 | server->sin_family = AF_INET; | 963 | server->sin_family = AF_INET; |
| 963 | server->sin_addr.s_addr = inet_addr (dotted); | 964 | server->sin_addr.s_addr = inet_addr (dotted); |
| 964 | server->sin_port = htons (atoi (port)); | 965 | server->sin_port = htons (atoi (port)); |
| @@ -977,16 +978,19 @@ get_server_config (const char *config_file, struct sockaddr_in *server, | |||
| 977 | static HSOCKET | 978 | static HSOCKET |
| 978 | set_tcp_socket (const char *local_server_file) | 979 | set_tcp_socket (const char *local_server_file) |
| 979 | { | 980 | { |
| 980 | struct sockaddr_in server; | 981 | union { |
| 981 | struct linger l_arg = {1, 1}; | 982 | struct sockaddr_in in; |
| 983 | struct sockaddr sa; | ||
| 984 | } server; | ||
| 985 | struct linger l_arg = { .l_onoff = 1, .l_linger = 1 }; | ||
| 982 | char auth_string[AUTH_KEY_LENGTH + 1]; | 986 | char auth_string[AUTH_KEY_LENGTH + 1]; |
| 983 | 987 | ||
| 984 | if (! get_server_config (local_server_file, &server, auth_string)) | 988 | if (! get_server_config (local_server_file, &server.in, auth_string)) |
| 985 | return INVALID_SOCKET; | 989 | return INVALID_SOCKET; |
| 986 | 990 | ||
| 987 | if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) | 991 | if (server.in.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet) |
| 988 | message (false, "%s: connected to remote socket at %s\n", | 992 | message (false, "%s: connected to remote socket at %s\n", |
| 989 | progname, inet_ntoa (server.sin_addr)); | 993 | progname, inet_ntoa (server.in.sin_addr)); |
| 990 | 994 | ||
| 991 | /* Open up an AF_INET socket. */ | 995 | /* Open up an AF_INET socket. */ |
| 992 | HSOCKET s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); | 996 | HSOCKET s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| @@ -1004,7 +1008,7 @@ set_tcp_socket (const char *local_server_file) | |||
| 1004 | } | 1008 | } |
| 1005 | 1009 | ||
| 1006 | /* Set up the socket. */ | 1010 | /* Set up the socket. */ |
| 1007 | if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) | 1011 | if (connect (s, &server.sa, sizeof server.in) != 0) |
| 1008 | { | 1012 | { |
| 1009 | # ifdef WINDOWSNT | 1013 | # ifdef WINDOWSNT |
| 1010 | if(!(w32_window_app () && alternate_editor)) | 1014 | if(!(w32_window_app () && alternate_editor)) |
| @@ -1013,7 +1017,7 @@ set_tcp_socket (const char *local_server_file) | |||
| 1013 | return INVALID_SOCKET; | 1017 | return INVALID_SOCKET; |
| 1014 | } | 1018 | } |
| 1015 | 1019 | ||
| 1016 | setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg); | 1020 | setsockopt (s, SOL_SOCKET, SO_LINGER, &l_arg, sizeof l_arg); |
| 1017 | 1021 | ||
| 1018 | /* Send the authentication. */ | 1022 | /* Send the authentication. */ |
| 1019 | auth_string[AUTH_KEY_LENGTH] = '\0'; | 1023 | auth_string[AUTH_KEY_LENGTH] = '\0'; |
| @@ -1183,13 +1187,16 @@ init_signals (void) | |||
| 1183 | signal (SIGTTOU, handle_sigtstp); | 1187 | signal (SIGTTOU, handle_sigtstp); |
| 1184 | } | 1188 | } |
| 1185 | 1189 | ||
| 1190 | /* Create a local socket and connect it to Emacs. */ | ||
| 1186 | 1191 | ||
| 1187 | static HSOCKET | 1192 | static HSOCKET |
| 1188 | set_local_socket (const char *local_socket_name) | 1193 | set_local_socket (const char *local_socket_name) |
| 1189 | { | 1194 | { |
| 1190 | struct sockaddr_un server; | 1195 | union { |
| 1196 | struct sockaddr_un un; | ||
| 1197 | struct sockaddr sa; | ||
| 1198 | } server = {{ .sun_family = AF_UNIX }}; | ||
| 1191 | 1199 | ||
| 1192 | /* Open up an AF_UNIX socket in this person's home directory. */ | ||
| 1193 | HSOCKET s = socket (AF_UNIX, SOCK_STREAM, 0); | 1200 | HSOCKET s = socket (AF_UNIX, SOCK_STREAM, 0); |
| 1194 | if (s < 0) | 1201 | if (s < 0) |
| 1195 | { | 1202 | { |
| @@ -1197,8 +1204,6 @@ set_local_socket (const char *local_socket_name) | |||
| 1197 | return INVALID_SOCKET; | 1204 | return INVALID_SOCKET; |
| 1198 | } | 1205 | } |
| 1199 | 1206 | ||
| 1200 | server.sun_family = AF_UNIX; | ||
| 1201 | |||
| 1202 | int sock_status; | 1207 | int sock_status; |
| 1203 | int saved_errno; | 1208 | int saved_errno; |
| 1204 | char const *server_name = local_socket_name; | 1209 | char const *server_name = local_socket_name; |
| @@ -1221,7 +1226,7 @@ set_local_socket (const char *local_socket_name) | |||
| 1221 | # ifndef _CS_DARWIN_USER_TEMP_DIR | 1226 | # ifndef _CS_DARWIN_USER_TEMP_DIR |
| 1222 | # define _CS_DARWIN_USER_TEMP_DIR 65537 | 1227 | # define _CS_DARWIN_USER_TEMP_DIR 65537 |
| 1223 | # endif | 1228 | # endif |
| 1224 | size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, (size_t) 0); | 1229 | size_t n = confstr (_CS_DARWIN_USER_TEMP_DIR, NULL, 0); |
| 1225 | if (n > 0) | 1230 | if (n > 0) |
| 1226 | { | 1231 | { |
| 1227 | tmpdir = tmpdir_storage = xmalloc (n); | 1232 | tmpdir = tmpdir_storage = xmalloc (n); |
| @@ -1238,8 +1243,8 @@ set_local_socket (const char *local_socket_name) | |||
| 1238 | local_socket_name = socket_name_storage; | 1243 | local_socket_name = socket_name_storage; |
| 1239 | } | 1244 | } |
| 1240 | 1245 | ||
| 1241 | if (strlen (local_socket_name) < sizeof (server.sun_path)) | 1246 | if (strlen (local_socket_name) < sizeof server.un.sun_path) |
| 1242 | strcpy (server.sun_path, local_socket_name); | 1247 | strcpy (server.un.sun_path, local_socket_name); |
| 1243 | else | 1248 | else |
| 1244 | { | 1249 | { |
| 1245 | message (true, "%s: socket-name %s too long\n", | 1250 | message (true, "%s: socket-name %s too long\n", |
| @@ -1248,7 +1253,7 @@ set_local_socket (const char *local_socket_name) | |||
| 1248 | } | 1253 | } |
| 1249 | 1254 | ||
| 1250 | /* See if the socket exists, and if it's owned by us. */ | 1255 | /* See if the socket exists, and if it's owned by us. */ |
| 1251 | sock_status = socket_status (server.sun_path); | 1256 | sock_status = socket_status (server.un.sun_path); |
| 1252 | saved_errno = errno; | 1257 | saved_errno = errno; |
| 1253 | if (sock_status && tmpdir) | 1258 | if (sock_status && tmpdir) |
| 1254 | { | 1259 | { |
| @@ -1276,8 +1281,8 @@ set_local_socket (const char *local_socket_name) | |||
| 1276 | char *z = stpcpy (user_socket_name, tmpdir); | 1281 | char *z = stpcpy (user_socket_name, tmpdir); |
| 1277 | strcpy (z + sprintf (z, subdir_format, uid), server_name); | 1282 | strcpy (z + sprintf (z, subdir_format, uid), server_name); |
| 1278 | 1283 | ||
| 1279 | if (strlen (user_socket_name) < sizeof (server.sun_path)) | 1284 | if (strlen (user_socket_name) < sizeof server.un.sun_path) |
| 1280 | strcpy (server.sun_path, user_socket_name); | 1285 | strcpy (server.un.sun_path, user_socket_name); |
| 1281 | else | 1286 | else |
| 1282 | { | 1287 | { |
| 1283 | message (true, "%s: socket-name %s too long\n", | 1288 | message (true, "%s: socket-name %s too long\n", |
| @@ -1286,7 +1291,7 @@ set_local_socket (const char *local_socket_name) | |||
| 1286 | } | 1291 | } |
| 1287 | free (user_socket_name); | 1292 | free (user_socket_name); |
| 1288 | 1293 | ||
| 1289 | sock_status = socket_status (server.sun_path); | 1294 | sock_status = socket_status (server.un.sun_path); |
| 1290 | saved_errno = errno; | 1295 | saved_errno = errno; |
| 1291 | } | 1296 | } |
| 1292 | else | 1297 | else |
| @@ -1314,12 +1319,11 @@ set_local_socket (const char *local_socket_name) | |||
| 1314 | progname, progname); | 1319 | progname, progname); |
| 1315 | else | 1320 | else |
| 1316 | message (true, "%s: can't stat %s: %s\n", | 1321 | message (true, "%s: can't stat %s: %s\n", |
| 1317 | progname, server.sun_path, strerror (saved_errno)); | 1322 | progname, server.un.sun_path, strerror (sock_status)); |
| 1318 | return INVALID_SOCKET; | 1323 | return INVALID_SOCKET; |
| 1319 | } | 1324 | } |
| 1320 | 1325 | ||
| 1321 | if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) | 1326 | if (connect (s, &server.sa, sizeof server.un) != 0) |
| 1322 | < 0) | ||
| 1323 | { | 1327 | { |
| 1324 | message (true, "%s: connect: %s\n", progname, strerror (errno)); | 1328 | message (true, "%s: connect: %s\n", progname, strerror (errno)); |
| 1325 | return INVALID_SOCKET; | 1329 | return INVALID_SOCKET; |