diff options
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/emacsclient.c | 555 |
1 files changed, 400 insertions, 155 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index b0bf50c2c78..943053b3c0f 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -26,19 +26,42 @@ Boston, MA 02110-1301, USA. */ | |||
| 26 | #include <config.h> | 26 | #include <config.h> |
| 27 | #endif | 27 | #endif |
| 28 | 28 | ||
| 29 | #ifdef WINDOWSNT | ||
| 30 | #define HAVE_SOCKETS | ||
| 31 | #define NO_SOCKETS_IN_FILE_SYSTEM | ||
| 32 | #endif | ||
| 33 | |||
| 34 | #ifdef WINDOWSNT | ||
| 35 | # define HSOCKET SOCKET | ||
| 36 | # define CLOSE_SOCKET closesocket | ||
| 37 | # define IOCTL ioctlsocket | ||
| 38 | # define INITIALIZE() (initialize_sockets ()) | ||
| 39 | typedef unsigned long IOCTL_BOOL_ARG; | ||
| 40 | #else | ||
| 41 | # define HSOCKET int | ||
| 42 | # define CLOSE_SOCKET close | ||
| 43 | # define IOCTL ioctl | ||
| 44 | # define INITIALIZE() | ||
| 45 | typedef int IOCTL_BOOL_ARG; | ||
| 46 | #endif | ||
| 47 | |||
| 29 | #undef signal | 48 | #undef signal |
| 30 | 49 | ||
| 31 | #include <ctype.h> | 50 | #include <ctype.h> |
| 32 | #include <stdio.h> | 51 | #include <stdio.h> |
| 33 | #include <getopt.h> | 52 | #include "getopt.h" |
| 34 | #ifdef HAVE_UNISTD_H | 53 | #ifdef HAVE_UNISTD_H |
| 35 | #include <unistd.h> | 54 | #include <unistd.h> |
| 36 | #endif | 55 | #endif |
| 37 | 56 | ||
| 38 | #ifdef VMS | 57 | #ifdef VMS |
| 39 | # include "vms-pwd.h" | 58 | # include "vms-pwd.h" |
| 40 | #else | 59 | #else /* not VMS */ |
| 60 | #ifdef WINDOWSNT | ||
| 61 | # include <io.h> | ||
| 62 | #else /* not WINDOWSNT */ | ||
| 41 | # include <pwd.h> | 63 | # include <pwd.h> |
| 64 | #endif /* not WINDOWSNT */ | ||
| 42 | #endif /* not VMS */ | 65 | #endif /* not VMS */ |
| 43 | 66 | ||
| 44 | char *getenv (), *getwd (); | 67 | char *getenv (), *getwd (); |
| @@ -48,6 +71,29 @@ char *(getcwd) (); | |||
| 48 | #define VERSION "unspecified" | 71 | #define VERSION "unspecified" |
| 49 | #endif | 72 | #endif |
| 50 | 73 | ||
| 74 | #define SEND_STRING(data) (send_to_emacs (s, (data))) | ||
| 75 | #define SEND_QUOTED(data) (quote_file_name (s, (data))) | ||
| 76 | |||
| 77 | #ifndef EXIT_SUCCESS | ||
| 78 | #define EXIT_SUCCESS 0 | ||
| 79 | #endif | ||
| 80 | |||
| 81 | #ifndef EXIT_FAILURE | ||
| 82 | #define EXIT_FAILURE 1 | ||
| 83 | #endif | ||
| 84 | |||
| 85 | #ifndef FALSE | ||
| 86 | #define FALSE 0 | ||
| 87 | #endif | ||
| 88 | |||
| 89 | #ifndef TRUE | ||
| 90 | #define TRUE 1 | ||
| 91 | #endif | ||
| 92 | |||
| 93 | #ifndef NO_RETURN | ||
| 94 | #define NO_RETURN | ||
| 95 | #endif | ||
| 96 | |||
| 51 | /* Name used to invoke this program. */ | 97 | /* Name used to invoke this program. */ |
| 52 | char *progname; | 98 | char *progname; |
| 53 | 99 | ||
| @@ -67,6 +113,9 @@ const char * alternate_editor = NULL; | |||
| 67 | /* If non-NULL, the filename of the UNIX socket. */ | 113 | /* If non-NULL, the filename of the UNIX socket. */ |
| 68 | char *socket_name = NULL; | 114 | char *socket_name = NULL; |
| 69 | 115 | ||
| 116 | /* If non-NULL, the filename of the authentication file. */ | ||
| 117 | char *server_file = NULL; | ||
| 118 | |||
| 70 | void print_help_and_exit () NO_RETURN; | 119 | void print_help_and_exit () NO_RETURN; |
| 71 | 120 | ||
| 72 | struct option longopts[] = | 121 | struct option longopts[] = |
| @@ -77,6 +126,7 @@ struct option longopts[] = | |||
| 77 | { "version", no_argument, NULL, 'V' }, | 126 | { "version", no_argument, NULL, 'V' }, |
| 78 | { "alternate-editor", required_argument, NULL, 'a' }, | 127 | { "alternate-editor", required_argument, NULL, 'a' }, |
| 79 | { "socket-name", required_argument, NULL, 's' }, | 128 | { "socket-name", required_argument, NULL, 's' }, |
| 129 | { "server-file", required_argument, NULL, 'f' }, | ||
| 80 | { "display", required_argument, NULL, 'd' }, | 130 | { "display", required_argument, NULL, 'd' }, |
| 81 | { 0, 0, 0, 0 } | 131 | { 0, 0, 0, 0 } |
| 82 | }; | 132 | }; |
| @@ -90,11 +140,12 @@ decode_options (argc, argv) | |||
| 90 | char **argv; | 140 | char **argv; |
| 91 | { | 141 | { |
| 92 | alternate_editor = getenv ("ALTERNATE_EDITOR"); | 142 | alternate_editor = getenv ("ALTERNATE_EDITOR"); |
| 143 | server_file = getenv ("EMACS_SERVER_FILE"); | ||
| 93 | 144 | ||
| 94 | while (1) | 145 | while (1) |
| 95 | { | 146 | { |
| 96 | int opt = getopt_long (argc, argv, | 147 | int opt = getopt_long (argc, argv, |
| 97 | "VHnea:s:d:", longopts, 0); | 148 | "VHnea:s:f:d:", longopts, 0); |
| 98 | 149 | ||
| 99 | if (opt == EOF) | 150 | if (opt == EOF) |
| 100 | break; | 151 | break; |
| @@ -114,6 +165,10 @@ decode_options (argc, argv) | |||
| 114 | socket_name = optarg; | 165 | socket_name = optarg; |
| 115 | break; | 166 | break; |
| 116 | 167 | ||
| 168 | case 'f': | ||
| 169 | server_file = optarg; | ||
| 170 | break; | ||
| 171 | |||
| 117 | case 'd': | 172 | case 'd': |
| 118 | display = optarg; | 173 | display = optarg; |
| 119 | break; | 174 | break; |
| @@ -156,9 +211,13 @@ The following OPTIONS are accepted:\n\ | |||
| 156 | -H, --help Print this usage information message\n\ | 211 | -H, --help Print this usage information message\n\ |
| 157 | -n, --no-wait Don't wait for the server to return\n\ | 212 | -n, --no-wait Don't wait for the server to return\n\ |
| 158 | -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ | 213 | -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ |
| 159 | -d, --display=DISPLAY Visit the file in the given display\n\ | 214 | -d, --display=DISPLAY Visit the file in the given display\n" |
| 160 | -s, --socket-name=FILENAME\n\ | 215 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 161 | Set the filename of the UNIX socket for communication\n\ | 216 | "-s, --socket-name=FILENAME\n\ |
| 217 | Set the filename of the UNIX socket for communication\n" | ||
| 218 | #endif | ||
| 219 | "-f, --server-file=FILENAME\n\ | ||
| 220 | Set the filename of the TCP configuration file\n\ | ||
| 162 | -a, --alternate-editor=EDITOR\n\ | 221 | -a, --alternate-editor=EDITOR\n\ |
| 163 | Editor to fallback to if the server is not running\n\ | 222 | Editor to fallback to if the server is not running\n\ |
| 164 | \n\ | 223 | \n\ |
| @@ -166,14 +225,118 @@ Report bugs to bug-gnu-emacs@gnu.org.\n", progname); | |||
| 166 | exit (EXIT_SUCCESS); | 225 | exit (EXIT_SUCCESS); |
| 167 | } | 226 | } |
| 168 | 227 | ||
| 228 | |||
| 229 | /* | ||
| 230 | Try to run a different command, or --if no alternate editor is | ||
| 231 | defined-- exit with an errorcode. | ||
| 232 | */ | ||
| 233 | void | ||
| 234 | fail (argc, argv) | ||
| 235 | int argc; | ||
| 236 | char **argv; | ||
| 237 | { | ||
| 238 | if (alternate_editor) | ||
| 239 | { | ||
| 240 | int i = optind - 1; | ||
| 241 | execvp (alternate_editor, argv + i); | ||
| 242 | fprintf (stderr, "%s: error executing alternate editor \"%s\"\n", | ||
| 243 | progname, alternate_editor); | ||
| 244 | } | ||
| 245 | else | ||
| 246 | { | ||
| 247 | fprintf (stderr, "%s: No socket or alternate editor. Please use:\n\n" | ||
| 248 | #if !defined (NO_SOCKETS_IN_FILE_SYSTEM) | ||
| 249 | "\t--socket-name\n" | ||
| 250 | #endif | ||
| 251 | "\t--server-file (or environment variable EMACS_SERVER_FILE)\n\ | ||
| 252 | \t--alternate-editor (or environment variable ALTERNATE_EDITOR)\n", | ||
| 253 | progname); | ||
| 254 | } | ||
| 255 | exit (EXIT_FAILURE); | ||
| 256 | } | ||
| 257 | |||
| 258 | |||
| 259 | #if !defined (HAVE_SOCKETS) | ||
| 260 | |||
| 261 | int | ||
| 262 | main (argc, argv) | ||
| 263 | int argc; | ||
| 264 | char **argv; | ||
| 265 | { | ||
| 266 | fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n", | ||
| 267 | argv[0]); | ||
| 268 | fprintf (stderr, "on systems with Berkeley sockets.\n"); | ||
| 269 | |||
| 270 | fail (argc, argv); | ||
| 271 | } | ||
| 272 | |||
| 273 | #else /* HAVE_SOCKETS */ | ||
| 274 | |||
| 275 | #ifdef WINDOWSNT | ||
| 276 | # include <winsock2.h> | ||
| 277 | #else | ||
| 278 | # include <sys/types.h> | ||
| 279 | # include <sys/socket.h> | ||
| 280 | # include <sys/un.h> | ||
| 281 | # include <sys/stat.h> | ||
| 282 | # include <errno.h> | ||
| 283 | #endif | ||
| 284 | |||
| 285 | #define AUTH_KEY_LENGTH 64 | ||
| 286 | #define SEND_BUFFER_SIZE 4096 | ||
| 287 | |||
| 288 | extern char *strerror (); | ||
| 289 | extern int errno; | ||
| 290 | |||
| 291 | /* Buffer to accumulate data to send in TCP connections. */ | ||
| 292 | char send_buffer[SEND_BUFFER_SIZE + 1]; | ||
| 293 | int sblen = 0; /* Fill pointer for the send buffer. */ | ||
| 294 | |||
| 295 | /* Let's send the data to Emacs when either | ||
| 296 | - the data ends in "\n", or | ||
| 297 | - the buffer is full (but this shouldn't happen) | ||
| 298 | Otherwise, we just accumulate it. */ | ||
| 299 | void send_to_emacs (s, data) | ||
| 300 | HSOCKET s; | ||
| 301 | char *data; | ||
| 302 | { | ||
| 303 | while (data) | ||
| 304 | { | ||
| 305 | int dlen = strlen (data); | ||
| 306 | if (dlen + sblen >= SEND_BUFFER_SIZE) | ||
| 307 | { | ||
| 308 | int part = SEND_BUFFER_SIZE - sblen; | ||
| 309 | strncpy (&send_buffer[sblen], data, part); | ||
| 310 | data += part; | ||
| 311 | sblen = SEND_BUFFER_SIZE; | ||
| 312 | } | ||
| 313 | else if (dlen) | ||
| 314 | { | ||
| 315 | strcpy (&send_buffer[sblen], data); | ||
| 316 | data = NULL; | ||
| 317 | sblen += dlen; | ||
| 318 | } | ||
| 319 | else | ||
| 320 | break; | ||
| 321 | |||
| 322 | if (sblen == SEND_BUFFER_SIZE | ||
| 323 | || (sblen > 0 && send_buffer[sblen-1] == '\n')) | ||
| 324 | { | ||
| 325 | int sent = send (s, send_buffer, sblen, 0); | ||
| 326 | if (sent != sblen) | ||
| 327 | strcpy (send_buffer, &send_buffer[sent]); | ||
| 328 | sblen -= sent; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 169 | /* In NAME, insert a & before each &, each space, each newline, and | 333 | /* In NAME, insert a & before each &, each space, each newline, and |
| 170 | any initial -. Change spaces to underscores, too, so that the | 334 | any initial -. Change spaces to underscores, too, so that the |
| 171 | return value never contains a space. */ | 335 | return value never contains a space. */ |
| 172 | |||
| 173 | void | 336 | void |
| 174 | quote_file_name (name, stream) | 337 | quote_file_name (s, name) |
| 338 | HSOCKET s; | ||
| 175 | char *name; | 339 | char *name; |
| 176 | FILE *stream; | ||
| 177 | { | 340 | { |
| 178 | char *copy = (char *) malloc (strlen (name) * 2 + 1); | 341 | char *copy = (char *) malloc (strlen (name) * 2 + 1); |
| 179 | char *p, *q; | 342 | char *p, *q; |
| @@ -203,73 +366,139 @@ quote_file_name (name, stream) | |||
| 203 | } | 366 | } |
| 204 | *q++ = 0; | 367 | *q++ = 0; |
| 205 | 368 | ||
| 206 | fprintf (stream, "%s", copy); | 369 | SEND_STRING (copy); |
| 207 | 370 | ||
| 208 | free (copy); | 371 | free (copy); |
| 209 | } | 372 | } |
| 210 | 373 | ||
| 211 | /* Like malloc but get fatal error if memory is exhausted. */ | 374 | #ifdef WINDOWSNT |
| 375 | /* Wrapper to make WSACleanup a cdecl, as required by atexit(). */ | ||
| 376 | void close_winsock () | ||
| 377 | { | ||
| 378 | WSACleanup (); | ||
| 379 | } | ||
| 212 | 380 | ||
| 213 | long * | 381 | void initialize_sockets () |
| 214 | xmalloc (size) | ||
| 215 | unsigned int size; | ||
| 216 | { | 382 | { |
| 217 | long *result = (long *) malloc (size); | 383 | WSADATA wsaData; |
| 218 | if (result == NULL) | 384 | |
| 219 | { | 385 | /* Initialize the WinSock2 library. */ |
| 220 | perror ("malloc"); | 386 | if (WSAStartup (MAKEWORD (2, 0), &wsaData)) |
| 221 | exit (EXIT_FAILURE); | 387 | { |
| 222 | } | 388 | fprintf (stderr, "%s: error initializing WinSock2", progname); |
| 223 | return result; | 389 | exit (EXIT_FAILURE); |
| 390 | } | ||
| 391 | |||
| 392 | atexit (close_winsock); | ||
| 393 | #endif /* WINDOWSNT */ | ||
| 224 | } | 394 | } |
| 225 | 395 | ||
| 226 | /* | 396 | /* |
| 227 | Try to run a different command, or --if no alternate editor is | 397 | * Read the information needed to set up a TCP comm channel with |
| 228 | defined-- exit with an errorcode. | 398 | * the Emacs server: host, port and authentication string. |
| 229 | */ | 399 | */ |
| 230 | void | 400 | int get_server_config (server, authentication) |
| 231 | fail (argc, argv) | 401 | struct sockaddr_in *server; |
| 232 | int argc; | 402 | char *authentication; |
| 233 | char **argv; | ||
| 234 | { | 403 | { |
| 235 | if (alternate_editor) | 404 | FILE *config; |
| 405 | char dotted[32]; | ||
| 406 | char *port; | ||
| 407 | |||
| 408 | if (! (config = fopen (server_file, "rb"))) | ||
| 236 | { | 409 | { |
| 237 | int i = optind - 1; | 410 | char *home = getenv ("HOME"); |
| 238 | execvp (alternate_editor, argv + i); | 411 | #ifdef WINDOWSNT |
| 239 | return; | 412 | if (! home) |
| 413 | home = getenv ("APPDATA"); | ||
| 414 | #endif | ||
| 415 | if (home) | ||
| 416 | { | ||
| 417 | char *path = alloca (32 + strlen (home) + strlen (server_file)); | ||
| 418 | sprintf (path, "%s/.emacs.d/server/%s", home, server_file); | ||
| 419 | config = fopen (path, "rb"); | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | if (! config) | ||
| 424 | return FALSE; | ||
| 425 | |||
| 426 | if (fgets (dotted, sizeof dotted, config) | ||
| 427 | && (port = strchr (dotted, ':'))) | ||
| 428 | { | ||
| 429 | *port++ = '\0'; | ||
| 240 | } | 430 | } |
| 241 | else | 431 | else |
| 242 | { | 432 | { |
| 433 | fprintf (stderr, "%s: invalid configuration info", progname); | ||
| 243 | exit (EXIT_FAILURE); | 434 | exit (EXIT_FAILURE); |
| 244 | } | 435 | } |
| 245 | } | ||
| 246 | 436 | ||
| 437 | server->sin_family = AF_INET; | ||
| 438 | server->sin_addr.s_addr = inet_addr (dotted); | ||
| 439 | server->sin_port = htons (atoi (port)); | ||
| 247 | 440 | ||
| 248 | 441 | if (! fread (authentication, AUTH_KEY_LENGTH, 1, config)) | |
| 249 | #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) | 442 | { |
| 443 | fprintf (stderr, "%s: cannot read authentication info", progname); | ||
| 444 | exit (EXIT_FAILURE); | ||
| 445 | } | ||
| 250 | 446 | ||
| 251 | int | 447 | fclose (config); |
| 252 | main (argc, argv) | ||
| 253 | int argc; | ||
| 254 | char **argv; | ||
| 255 | { | ||
| 256 | fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n", | ||
| 257 | argv[0]); | ||
| 258 | fprintf (stderr, "on systems with Berkeley sockets.\n"); | ||
| 259 | 448 | ||
| 260 | fail (argc, argv); | 449 | return TRUE; |
| 261 | } | 450 | } |
| 262 | 451 | ||
| 263 | #else /* HAVE_SOCKETS */ | 452 | HSOCKET |
| 453 | set_tcp_socket () | ||
| 454 | { | ||
| 455 | HSOCKET s; | ||
| 456 | struct sockaddr_in server; | ||
| 457 | IOCTL_BOOL_ARG c_arg = 0; | ||
| 458 | struct linger l_arg = {1, 1}; | ||
| 459 | char auth_string[AUTH_KEY_LENGTH + 1]; | ||
| 264 | 460 | ||
| 265 | #include <sys/types.h> | 461 | INITIALIZE (); |
| 266 | #include <sys/socket.h> | ||
| 267 | #include <sys/un.h> | ||
| 268 | #include <sys/stat.h> | ||
| 269 | #include <errno.h> | ||
| 270 | 462 | ||
| 271 | extern char *strerror (); | 463 | if (! get_server_config (&server, auth_string)) |
| 272 | extern int errno; | 464 | return INVALID_SOCKET; |
| 465 | |||
| 466 | /* | ||
| 467 | * Open up an AF_INET socket | ||
| 468 | */ | ||
| 469 | if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) | ||
| 470 | { | ||
| 471 | fprintf (stderr, "%s: ", progname); | ||
| 472 | perror ("socket"); | ||
| 473 | return INVALID_SOCKET; | ||
| 474 | } | ||
| 475 | |||
| 476 | /* | ||
| 477 | * Set up the socket | ||
| 478 | */ | ||
| 479 | if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) | ||
| 480 | { | ||
| 481 | fprintf (stderr, "%s: ", progname); | ||
| 482 | perror ("connect"); | ||
| 483 | return INVALID_SOCKET; | ||
| 484 | } | ||
| 485 | |||
| 486 | IOCTL (s, FIONBIO, &c_arg); | ||
| 487 | setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg); | ||
| 488 | |||
| 489 | /* | ||
| 490 | * Send the authentication | ||
| 491 | */ | ||
| 492 | auth_string[AUTH_KEY_LENGTH] = '\0'; | ||
| 493 | |||
| 494 | SEND_STRING ("-auth "); | ||
| 495 | SEND_STRING (auth_string); | ||
| 496 | SEND_STRING ("\n"); | ||
| 497 | |||
| 498 | return s; | ||
| 499 | } | ||
| 500 | |||
| 501 | #if !defined (NO_SOCKETS_IN_FILE_SYSTEM) | ||
| 273 | 502 | ||
| 274 | /* Three possibilities: | 503 | /* Three possibilities: |
| 275 | 2 - can't be `stat'ed (sets errno) | 504 | 2 - can't be `stat'ed (sets errno) |
| @@ -291,28 +520,11 @@ socket_status (socket_name) | |||
| 291 | return 0; | 520 | return 0; |
| 292 | } | 521 | } |
| 293 | 522 | ||
| 294 | int | 523 | HSOCKET |
| 295 | main (argc, argv) | 524 | set_local_socket () |
| 296 | int argc; | ||
| 297 | char **argv; | ||
| 298 | { | 525 | { |
| 299 | int s, i, needlf = 0; | 526 | HSOCKET s; |
| 300 | FILE *out, *in; | ||
| 301 | struct sockaddr_un server; | 527 | struct sockaddr_un server; |
| 302 | char *cwd, *str; | ||
| 303 | char string[BUFSIZ]; | ||
| 304 | |||
| 305 | progname = argv[0]; | ||
| 306 | |||
| 307 | /* Process options. */ | ||
| 308 | decode_options (argc, argv); | ||
| 309 | |||
| 310 | if ((argc - optind < 1) && !eval) | ||
| 311 | { | ||
| 312 | fprintf (stderr, "%s: file name or argument required\n", progname); | ||
| 313 | fprintf (stderr, "Try `%s --help' for more information\n", progname); | ||
| 314 | exit (EXIT_FAILURE); | ||
| 315 | } | ||
| 316 | 528 | ||
| 317 | /* | 529 | /* |
| 318 | * Open up an AF_UNIX socket in this person's home directory | 530 | * Open up an AF_UNIX socket in this person's home directory |
| @@ -320,9 +532,9 @@ main (argc, argv) | |||
| 320 | 532 | ||
| 321 | if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) | 533 | if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) |
| 322 | { | 534 | { |
| 323 | fprintf (stderr, "%s: ", argv[0]); | 535 | fprintf (stderr, "%s: ", progname); |
| 324 | perror ("socket"); | 536 | perror ("socket"); |
| 325 | fail (argc, argv); | 537 | return INVALID_SOCKET; |
| 326 | } | 538 | } |
| 327 | 539 | ||
| 328 | server.sun_family = AF_UNIX; | 540 | server.sun_family = AF_UNIX; |
| @@ -352,7 +564,7 @@ main (argc, argv) | |||
| 352 | else | 564 | else |
| 353 | { | 565 | { |
| 354 | fprintf (stderr, "%s: socket-name %s too long", | 566 | fprintf (stderr, "%s: socket-name %s too long", |
| 355 | argv[0], socket_name); | 567 | progname, socket_name); |
| 356 | exit (EXIT_FAILURE); | 568 | exit (EXIT_FAILURE); |
| 357 | } | 569 | } |
| 358 | 570 | ||
| @@ -387,7 +599,7 @@ main (argc, argv) | |||
| 387 | else | 599 | else |
| 388 | { | 600 | { |
| 389 | fprintf (stderr, "%s: socket-name %s too long", | 601 | fprintf (stderr, "%s: socket-name %s too long", |
| 390 | argv[0], socket_name); | 602 | progname, socket_name); |
| 391 | exit (EXIT_FAILURE); | 603 | exit (EXIT_FAILURE); |
| 392 | } | 604 | } |
| 393 | 605 | ||
| @@ -399,61 +611,85 @@ main (argc, argv) | |||
| 399 | } | 611 | } |
| 400 | } | 612 | } |
| 401 | 613 | ||
| 402 | switch (sock_status) | 614 | switch (sock_status) |
| 403 | { | 615 | { |
| 404 | case 1: | 616 | case 1: |
| 405 | /* There's a socket, but it isn't owned by us. This is OK if | 617 | /* There's a socket, but it isn't owned by us. This is OK if |
| 406 | we are root. */ | 618 | we are root. */ |
| 407 | if (0 != geteuid ()) | 619 | if (0 != geteuid ()) |
| 408 | { | 620 | { |
| 409 | fprintf (stderr, "%s: Invalid socket owner\n", argv[0]); | 621 | fprintf (stderr, "%s: Invalid socket owner\n", argv[0]); |
| 410 | fail (argc, argv); | 622 | return INVALID_SOCKET; |
| 411 | } | 623 | } |
| 412 | break; | 624 | break; |
| 413 | 625 | ||
| 414 | case 2: | 626 | case 2: |
| 415 | /* `stat' failed */ | 627 | /* `stat' failed */ |
| 416 | if (saved_errno == ENOENT) | 628 | if (saved_errno == ENOENT) |
| 417 | fprintf (stderr, | 629 | fprintf (stderr, |
| 418 | "%s: can't find socket; have you started the server?\n\ | 630 | "%s: can't find socket; have you started the server?\n\ |
| 419 | To start the server in Emacs, type \"M-x server-start\".\n", | 631 | To start the server in Emacs, type \"M-x server-start\".\n", |
| 420 | argv[0]); | 632 | progname); |
| 421 | else | 633 | else |
| 422 | fprintf (stderr, "%s: can't stat %s: %s\n", | 634 | fprintf (stderr, "%s: can't stat %s: %s\n", |
| 423 | argv[0], server.sun_path, strerror (saved_errno)); | 635 | progname, server.sun_path, strerror (saved_errno)); |
| 424 | fail (argc, argv); | 636 | return INVALID_SOCKET; |
| 425 | break; | 637 | } |
| 426 | } | ||
| 427 | } | 638 | } |
| 428 | 639 | ||
| 429 | if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) | 640 | if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) |
| 430 | < 0) | 641 | < 0) |
| 431 | { | 642 | { |
| 432 | fprintf (stderr, "%s: ", argv[0]); | 643 | fprintf (stderr, "%s: ", progname); |
| 433 | perror ("connect"); | 644 | perror ("connect"); |
| 434 | fail (argc, argv); | 645 | return INVALID_SOCKET; |
| 435 | } | 646 | } |
| 436 | 647 | ||
| 437 | /* We use the stream OUT to send our command to the server. */ | 648 | return s; |
| 438 | if ((out = fdopen (s, "r+")) == NULL) | 649 | } |
| 650 | #endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */ | ||
| 651 | |||
| 652 | HSOCKET | ||
| 653 | set_socket () | ||
| 654 | { | ||
| 655 | if (server_file) | ||
| 656 | return set_tcp_socket (); | ||
| 657 | else | ||
| 658 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM | ||
| 659 | return set_local_socket (); | ||
| 660 | #else | ||
| 439 | { | 661 | { |
| 440 | fprintf (stderr, "%s: ", argv[0]); | 662 | server_file = "server"; |
| 441 | perror ("fdopen"); | 663 | return set_tcp_socket (); |
| 442 | fail (argc, argv); | ||
| 443 | } | 664 | } |
| 665 | #endif | ||
| 666 | } | ||
| 444 | 667 | ||
| 445 | /* We use the stream IN to read the response. | 668 | int |
| 446 | We used to use just one stream for both output and input | 669 | main (argc, argv) |
| 447 | on the socket, but reversing direction works nonportably: | 670 | int argc; |
| 448 | on some systems, the output appears as the first input; | 671 | char **argv; |
| 449 | on other systems it does not. */ | 672 | { |
| 450 | if ((in = fdopen (s, "r+")) == NULL) | 673 | HSOCKET s; |
| 674 | int i, rl, needlf = 0; | ||
| 675 | char *cwd; | ||
| 676 | char string[BUFSIZ+1]; | ||
| 677 | |||
| 678 | progname = argv[0]; | ||
| 679 | |||
| 680 | /* Process options. */ | ||
| 681 | decode_options (argc, argv); | ||
| 682 | |||
| 683 | if ((argc - optind < 1) && !eval) | ||
| 451 | { | 684 | { |
| 452 | fprintf (stderr, "%s: ", argv[0]); | 685 | fprintf (stderr, "%s: file name or argument required\n", progname); |
| 453 | perror ("fdopen"); | 686 | fprintf (stderr, "Try `%s --help' for more information\n", progname); |
| 454 | fail (argc, argv); | 687 | exit (EXIT_FAILURE); |
| 455 | } | 688 | } |
| 456 | 689 | ||
| 690 | if ((s = set_socket ()) == INVALID_SOCKET) | ||
| 691 | fail (argc, argv); | ||
| 692 | |||
| 457 | #ifdef HAVE_GETCWD | 693 | #ifdef HAVE_GETCWD |
| 458 | cwd = getcwd (string, sizeof string); | 694 | cwd = getcwd (string, sizeof string); |
| 459 | #else | 695 | #else |
| @@ -462,27 +698,26 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 462 | if (cwd == 0) | 698 | if (cwd == 0) |
| 463 | { | 699 | { |
| 464 | /* getwd puts message in STRING if it fails. */ | 700 | /* getwd puts message in STRING if it fails. */ |
| 465 | |||
| 466 | #ifdef HAVE_GETCWD | 701 | #ifdef HAVE_GETCWD |
| 467 | fprintf (stderr, "%s: %s (%s)\n", argv[0], | 702 | fprintf (stderr, "%s: %s (%s)\n", progname, |
| 468 | "Cannot get current working directory", strerror (errno)); | 703 | "Cannot get current working directory", strerror (errno)); |
| 469 | #else | 704 | #else |
| 470 | fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno)); | 705 | fprintf (stderr, "%s: %s (%s)\n", progname, string, strerror (errno)); |
| 471 | #endif | 706 | #endif |
| 472 | fail (argc, argv); | 707 | fail (argc, argv); |
| 473 | } | 708 | } |
| 474 | 709 | ||
| 475 | if (nowait) | 710 | if (nowait) |
| 476 | fprintf (out, "-nowait "); | 711 | SEND_STRING ("-nowait "); |
| 477 | 712 | ||
| 478 | if (eval) | 713 | if (eval) |
| 479 | fprintf (out, "-eval "); | 714 | SEND_STRING ("-eval "); |
| 480 | 715 | ||
| 481 | if (display) | 716 | if (display) |
| 482 | { | 717 | { |
| 483 | fprintf (out, "-display "); | 718 | SEND_STRING ("-display "); |
| 484 | quote_file_name (display, out); | 719 | SEND_QUOTED (display); |
| 485 | fprintf (out, " "); | 720 | SEND_STRING (" "); |
| 486 | } | 721 | } |
| 487 | 722 | ||
| 488 | if ((argc - optind > 0)) | 723 | if ((argc - optind > 0)) |
| @@ -497,61 +732,71 @@ To start the server in Emacs, type \"M-x server-start\".\n", | |||
| 497 | while (isdigit ((unsigned char) *p) || *p == ':') p++; | 732 | while (isdigit ((unsigned char) *p) || *p == ':') p++; |
| 498 | if (*p != 0) | 733 | if (*p != 0) |
| 499 | { | 734 | { |
| 500 | quote_file_name (cwd, out); | 735 | SEND_QUOTED (cwd); |
| 501 | fprintf (out, "/"); | 736 | SEND_STRING ("/"); |
| 502 | } | 737 | } |
| 503 | } | 738 | } |
| 739 | #ifndef WINDOWSNT | ||
| 504 | else if (*argv[i] != '/') | 740 | else if (*argv[i] != '/') |
| 741 | #else | ||
| 742 | else if ((*argv[i] != '/') | ||
| 743 | /* Absolute paths can also start with backslash | ||
| 744 | or drive letters. */ | ||
| 745 | && (*argv[i] != '\\') | ||
| 746 | && (!islower (tolower (*argv[i])) | ||
| 747 | || (argv[i][1] != ':'))) | ||
| 748 | #endif | ||
| 505 | { | 749 | { |
| 506 | quote_file_name (cwd, out); | 750 | SEND_QUOTED (cwd); |
| 507 | fprintf (out, "/"); | 751 | SEND_STRING ("/"); |
| 508 | } | 752 | } |
| 509 | 753 | ||
| 510 | quote_file_name (argv[i], out); | 754 | SEND_QUOTED (argv[i]); |
| 511 | fprintf (out, " "); | 755 | SEND_STRING (" "); |
| 512 | } | 756 | } |
| 513 | } | 757 | } |
| 514 | else | 758 | else |
| 515 | { | 759 | { |
| 516 | while ((str = fgets (string, BUFSIZ, stdin))) | 760 | while (fgets (string, BUFSIZ, stdin)) |
| 517 | { | 761 | { |
| 518 | quote_file_name (str, out); | 762 | SEND_QUOTED (string); |
| 519 | } | 763 | } |
| 520 | fprintf (out, " "); | 764 | SEND_STRING (" "); |
| 521 | } | 765 | } |
| 522 | 766 | ||
| 523 | fprintf (out, "\n"); | 767 | SEND_STRING ("\n"); |
| 524 | fflush (out); | ||
| 525 | 768 | ||
| 526 | /* Maybe wait for an answer. */ | 769 | /* Maybe wait for an answer. */ |
| 527 | if (nowait) | 770 | if (!nowait) |
| 528 | return EXIT_SUCCESS; | ||
| 529 | |||
| 530 | if (!eval) | ||
| 531 | { | 771 | { |
| 532 | printf ("Waiting for Emacs..."); | 772 | if (!eval) |
| 533 | needlf = 2; | 773 | { |
| 774 | printf ("Waiting for Emacs..."); | ||
| 775 | needlf = 2; | ||
| 776 | } | ||
| 777 | fflush (stdout); | ||
| 778 | |||
| 779 | /* Now, wait for an answer and print any messages. */ | ||
| 780 | while ((rl = recv (s, string, BUFSIZ, 0)) > 0) | ||
| 781 | { | ||
| 782 | string[rl] = '\0'; | ||
| 783 | if (needlf == 2) | ||
| 784 | printf ("\n"); | ||
| 785 | printf ("%s", string); | ||
| 786 | needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n'; | ||
| 787 | } | ||
| 788 | |||
| 789 | if (needlf) | ||
| 790 | printf ("\n"); | ||
| 791 | fflush (stdout); | ||
| 534 | } | 792 | } |
| 535 | fflush (stdout); | ||
| 536 | |||
| 537 | /* Now, wait for an answer and print any messages. */ | ||
| 538 | while ((str = fgets (string, BUFSIZ, in))) | ||
| 539 | { | ||
| 540 | if (needlf == 2) | ||
| 541 | printf ("\n"); | ||
| 542 | printf ("%s", str); | ||
| 543 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | ||
| 544 | } | ||
| 545 | |||
| 546 | if (needlf) | ||
| 547 | printf ("\n"); | ||
| 548 | fflush (stdout); | ||
| 549 | 793 | ||
| 794 | CLOSE_SOCKET (s); | ||
| 550 | return EXIT_SUCCESS; | 795 | return EXIT_SUCCESS; |
| 551 | } | 796 | } |
| 552 | 797 | ||
| 553 | #endif /* HAVE_SOCKETS */ | 798 | #endif /* HAVE_SOCKETS */ |
| 554 | 799 | ||
| 555 | #ifndef HAVE_STRERROR | 800 | #ifndef HAVE_STRERROR |
| 556 | char * | 801 | char * |
| 557 | strerror (errnum) | 802 | strerror (errnum) |