aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2018-11-22 09:21:22 -0800
committerPaul Eggert2018-11-22 09:24:51 -0800
commit5773470ff3a85640fbaeab1a88edc3fa395184bd (patch)
treeeff420595f2bf7125d705f2f826a54360127d1c6
parenta344d9937bb7edfbfbea13dca1569fcdcad25ac2 (diff)
downloademacs-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.c46
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,
977static HSOCKET 978static HSOCKET
978set_tcp_socket (const char *local_server_file) 979set_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
1187static HSOCKET 1192static HSOCKET
1188set_local_socket (const char *local_socket_name) 1193set_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;