emacsclient.c 53.5 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Client process that communicates with GNU Emacs acting as server.
2

Paul Eggert's avatar
Paul Eggert committed
3
Copyright (C) 1986-1987, 1994, 1999-2018 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
4 5 6

This file is part of GNU Emacs.

7
GNU Emacs is free software: you can redistribute it and/or modify
Richard M. Stallman's avatar
Richard M. Stallman committed
8
it under the terms of the GNU General Public License as published by
9 10
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
Richard M. Stallman's avatar
Richard M. Stallman committed
11 12 13 14 15 16 17

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
18
along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
19 20


Pavel Janík's avatar
Pavel Janík committed
21
#include <config.h>
22

23 24
#ifdef WINDOWSNT

25
/* ms-w32.h defines these, which disables sockets altogether!  */
26 27 28
# undef _WINSOCKAPI_
# undef _WINSOCK_H

29
# include <malloc.h>
Juanma Barranquero's avatar
Juanma Barranquero committed
30
# include <windows.h>
31
# include <commctrl.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
32 33
# include <io.h>
# include <winsock2.h>
34

35 36
# define HSOCKET SOCKET
# define CLOSE_SOCKET closesocket
37
# define INITIALIZE() initialize_sockets ()
38

39
char *w32_getenv (const char *);
40
# define egetenv(VAR) w32_getenv (VAR)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
41

42 43
# undef signal

44 45
#else /* !WINDOWSNT */

46
# ifdef HAVE_NTGUI
47 48
#  include <windows.h>
# endif
49

50
# include "syswait.h"
51

Dan Nicolaescu's avatar
Dan Nicolaescu committed
52
# include <arpa/inet.h>
53
# include <fcntl.h>
54 55 56
# include <netinet/in.h>
# include <sys/socket.h>
# include <sys/un.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
57

58 59
# define SOCKETS_IN_FILE_SYSTEM

60
# define INVALID_SOCKET (-1)
61 62 63
# define HSOCKET int
# define CLOSE_SOCKET close
# define INITIALIZE()
64

65
# define egetenv(VAR) getenv (VAR)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
66

67
#endif /* !WINDOWSNT */
68

69 70 71 72
#ifndef DOS_NT
# include <termios.h>
#endif

73
#include <ctype.h>
74
#include <errno.h>
75
#include <getopt.h>
76
#include <inttypes.h>
Dan Nicolaescu's avatar
Dan Nicolaescu committed
77
#include <pwd.h>
78
#include <signal.h>
79
#include <stdarg.h>
80
#include <stddef.h>
81 82 83 84
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
85

86
#include <dosname.h>
87
#include <intprops.h>
88
#include <min-max.h>
89 90
#include <unlocked-io.h>

91 92 93
#ifndef VERSION
#define VERSION "unspecified"
#endif
94

95 96 97 98 99
/* Work around GCC bug 88251.  */
#if GNUC_PREREQ (7, 0, 0)
# pragma GCC diagnostic ignored "-Wformat-truncation=2"
#endif

100

101
/* Name used to invoke this program.  */
102
static char const *progname;
103

104
/* The first argument to main.  */
105
static int main_argc;
106

107
/* The second argument to main.  */
108
static char *const *main_argv;
Karoly Lorentey's avatar
Karoly Lorentey committed
109

110
/* True means don't wait for a response from Emacs.  --no-wait.  */
111
static bool nowait;
112

113
/* True means don't print messages for successful operations.  --quiet.  */
114
static bool quiet;
115

116
/* True means don't print values returned from emacs. --suppress-output.  */
117
static bool suppress_output;
118

119
/* True means args are expressions to be evaluated.  --eval.  */
120
static bool eval;
Stefan Monnier's avatar
Stefan Monnier committed
121

122 123
/* True means open a new frame.  --create-frame etc.  */
static bool create_frame;
124

Stefan Monnier's avatar
Stefan Monnier committed
125
/* The display on which Emacs should work.  --display.  */
126
static char const *display;
Stefan Monnier's avatar
Stefan Monnier committed
127

128
/* The alternate display we should try if Emacs does not support display.  */
129
static char const *alt_display;
130

131
/* The parent window ID, if we are opening a frame via XEmbed.  */
132
static char *parent_id;
133

134
/* True means open a new Emacs frame on the current terminal.  */
135
static bool tty;
136

Stefan Monnier's avatar
Stefan Monnier committed
137 138
/* If non-NULL, the name of an editor to fallback to if the server
   is not running.  --alternate-editor.   */
139
static char *alternate_editor;
Stefan Monnier's avatar
Stefan Monnier committed
140

141
#ifdef SOCKETS_IN_FILE_SYSTEM
Richard M. Stallman's avatar
Richard M. Stallman committed
142
/* If non-NULL, the filename of the UNIX socket.  */
143
static char const *socket_name;
144
#endif
145

146
/* If non-NULL, the filename of the authentication file.  */
147
static char const *server_file;
148

149
/* If non-NULL, the tramp prefix emacs must use to find the files.  */
150
static char const *tramp_prefix;
151

152
/* If nonzero, PID of the Emacs server process.  */
153
static pid_t emacs_pid;
154

155
/* If non-NULL, a string that should form a frame parameter alist to
156
   be used for the new frame.  */
157
static char const *frame_parameters;
158

159
static _Noreturn void print_help_and_exit (void);
160

161
/* Long command-line options.  */
162

163
static struct option const longopts[] =
164
{
165
  { "no-wait",	no_argument,	   NULL, 'n' },
166
  { "quiet",	no_argument,	   NULL, 'q' },
167
  { "suppress-output", no_argument, NULL, 'u' },
Stefan Monnier's avatar
Stefan Monnier committed
168
  { "eval",	no_argument,	   NULL, 'e' },
169 170
  { "help",	no_argument,	   NULL, 'H' },
  { "version",	no_argument,	   NULL, 'V' },
171
  { "tty",	no_argument,       NULL, 't' },
172
  { "nw",	no_argument,       NULL, 't' },
173
  { "create-frame", no_argument,   NULL, 'c' },
174
  { "alternate-editor", required_argument, NULL, 'a' },
175
  { "frame-parameters", required_argument, NULL, 'F' },
176
#ifdef SOCKETS_IN_FILE_SYSTEM
177
  { "socket-name",	required_argument, NULL, 's' },
178
#endif
179
  { "server-file",	required_argument, NULL, 'f' },
Stefan Monnier's avatar
Stefan Monnier committed
180
  { "display",	required_argument, NULL, 'd' },
181
  { "parent-id", required_argument, NULL, 'p' },
182
  { "tramp",	required_argument, NULL, 'T' },
Stefan Monnier's avatar
Stefan Monnier committed
183
  { 0, 0, 0, 0 }
184 185
};

186 187 188 189
/* Short options, in the same order as the corresponding long options.
   There is no '-p' short option.  */
static char const shortopts[] =
  "nqueHVtca:F:"
190
#ifdef SOCKETS_IN_FILE_SYSTEM
191 192 193 194
  "s:"
#endif
  "f:d:T:";

195 196 197

/* Like malloc but get fatal error if memory is exhausted.  */

198
static void * ATTRIBUTE_MALLOC
199
xmalloc (size_t size)
200
{
201
  void *result = malloc (size);
202 203 204 205 206 207 208 209
  if (result == NULL)
    {
      perror ("malloc");
      exit (EXIT_FAILURE);
    }
  return result;
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
/* Like realloc but get fatal error if memory is exhausted.  */

static void *
xrealloc (void *ptr, size_t size)
{
  void *result = realloc (ptr, size);
  if (result == NULL)
    {
      perror ("realloc");
      exit (EXIT_FAILURE);
    }
  return result;
}

/* Like strdup but get a fatal error if memory is exhausted. */

226
static char * ATTRIBUTE_MALLOC
227 228 229 230 231 232 233 234 235 236 237
xstrdup (const char *s)
{
  char *result = strdup (s);
  if (result == NULL)
    {
      perror ("strdup");
      exit (EXIT_FAILURE);
    }
  return result;
}

238
/* From sysdep.c */
239
#if !defined HAVE_GET_CURRENT_DIR_NAME || defined BROKEN_GET_CURRENT_DIR_NAME
240

241
char *get_current_dir_name (void);
242

243
/* Return the current working directory.  Returns NULL on errors.
244
   Any other returned value must be freed with free.  This is used
245
   only when get_current_dir_name is not defined on the system.  */
Paul Eggert's avatar
Paul Eggert committed
246
char *
247
get_current_dir_name (void)
248 249 250
{
  char *buf;
  struct stat dotstat, pwdstat;
251
  /* If PWD is accurate, use it instead of calling getcwd.  PWD is
252 253
     sometimes a nicer name, and using it may avoid a fatal error if a
     parent directory is searchable but not readable.  */
Paul Eggert's avatar
Paul Eggert committed
254 255
  char const *pwd = egetenv ("PWD");
  if (pwd
256 257 258 259 260
      && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
      && stat (pwd, &pwdstat) == 0
      && stat (".", &dotstat) == 0
      && dotstat.st_ino == pwdstat.st_ino
      && dotstat.st_dev == pwdstat.st_dev
261
# ifdef MAXPATHLEN
262
      && strlen (pwd) < MAXPATHLEN
263
# endif
264 265
      )
    {
266
      buf = xmalloc (strlen (pwd) + 1);
267 268 269 270 271 272 273
      strcpy (buf, pwd);
    }
  else
    {
      size_t buf_size = 1024;
      for (;;)
        {
274 275 276 277
	  int tmp_errno;
	  buf = malloc (buf_size);
	  if (! buf)
	    break;
278 279
          if (getcwd (buf, buf_size) == buf)
            break;
280 281 282
	  tmp_errno = errno;
	  free (buf);
	  if (tmp_errno != ERANGE)
283 284 285 286 287
            {
              errno = tmp_errno;
              return NULL;
            }
          buf_size *= 2;
288 289 290 291 292
	  if (! buf_size)
	    {
	      errno = ENOMEM;
	      return NULL;
	    }
293 294 295 296 297 298
        }
    }
  return buf;
}
#endif

Juanma Barranquero's avatar
Juanma Barranquero committed
299
#ifdef WINDOWSNT
300

301
# define REG_ROOT "SOFTWARE\\GNU\\Emacs"
302

303 304
char *w32_get_resource (HKEY, const char *, LPDWORD);

305 306 307 308
/* Retrieve an environment variable from the Emacs subkeys of the registry.
   Return NULL if the variable was not found, or it was empty.
   This code is based on w32_get_resource (w32.c).  */
char *
309
w32_get_resource (HKEY predefined, const char *key, LPDWORD type)
310 311 312 313 314
{
  HKEY hrootkey = NULL;
  char *result = NULL;
  DWORD cbData;

315 316
  if (RegOpenKeyEx (predefined, REG_ROOT, 0, KEY_READ, &hrootkey)
      == ERROR_SUCCESS)
317
    {
318 319
      if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData)
	  == ERROR_SUCCESS)
320
	{
321
	  result = xmalloc (cbData);
322

323 324 325 326
	  if ((RegQueryValueEx (hrootkey, key, NULL, type, (LPBYTE) result,
				&cbData)
	       != ERROR_SUCCESS)
	      || *result == 0)
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
	    {
	      free (result);
	      result = NULL;
	    }
	}

      RegCloseKey (hrootkey);
    }

  return result;
}

/*
  getenv wrapper for Windows

342 343 344 345 346
  Value is allocated on the heap, and can be free'd.

  This is needed to duplicate Emacs's behavior, which is to look for
  environment variables in the registry if they don't appear in the
  environment.  */
347
char *
348
w32_getenv (const char *envvar)
349 350 351 352
{
  char *value;
  DWORD dwType;

353
  if ((value = getenv (envvar)))
354 355 356
    /* Found in the environment.  strdup it, because values returned
       by getenv cannot be free'd.  */
    return xstrdup (value);
357 358 359

  if (! (value = w32_get_resource (HKEY_CURRENT_USER, envvar, &dwType)) &&
      ! (value = w32_get_resource (HKEY_LOCAL_MACHINE, envvar, &dwType)))
360 361 362
    {
      /* "w32console" is what Emacs on Windows uses for tty-type under -nw.  */
      if (strcmp (envvar, "TERM") == 0)
363
	return xstrdup ("w32console");
364 365 366
      /* Found neither in the environment nor in the registry.  */
      return NULL;
    }
367 368 369 370 371 372 373 374 375

  if (dwType == REG_SZ)
    /* Registry; no need to expand.  */
    return value;

  if (dwType == REG_EXPAND_SZ)
    {
      DWORD size;

376
      if ((size = ExpandEnvironmentStrings (value, NULL, 0)))
377
	{
378
	  char *buffer = xmalloc (size);
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
	  if (ExpandEnvironmentStrings (value, buffer, size))
	    {
	      /* Found and expanded.  */
	      free (value);
	      return buffer;
	    }

	  /* Error expanding.  */
	  free (buffer);
	}
    }

  /* Not the right type, or not correctly expanded.  */
  free (value);
  return NULL;
}

396
int w32_window_app (void);
397

Juanma Barranquero's avatar
Juanma Barranquero committed
398
int
399
w32_window_app (void)
Juanma Barranquero's avatar
Juanma Barranquero committed
400 401 402 403 404
{
  static int window_app = -1;
  char szTitle[MAX_PATH];

  if (window_app < 0)
405 406 407 408 409
    {
      /* Checking for STDOUT does not work; it's a valid handle also in
         nonconsole apps.  Testing for the console title seems to work. */
      window_app = (GetConsoleTitleA (szTitle, MAX_PATH) == 0);
      if (window_app)
410
        InitCommonControls ();
411
    }
Juanma Barranquero's avatar
Juanma Barranquero committed
412 413 414

  return window_app;
}
415

416
/* execvp wrapper for Windows.  Quotes arguments with embedded spaces.
417 418 419 420

  This is necessary due to the broken implementation of exec* routines in
  the Microsoft libraries: they concatenate the arguments together without
  quoting special characters, and pass the result to CreateProcess, with
421
  predictably bad results.  By contrast, POSIX execvp passes the arguments
422 423
  directly into the argv array of the child process.  */

424 425
int w32_execvp (const char *, char **);

426
int
427
w32_execvp (const char *path, char **argv)
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
{
  int i;

  /* Required to allow a .BAT script as alternate editor.  */
  argv[0] = (char *) alternate_editor;

  for (i = 0; argv[i]; i++)
    if (strchr (argv[i], ' '))
      {
	char *quoted = alloca (strlen (argv[i]) + 3);
	sprintf (quoted, "\"%s\"", argv[i]);
	argv[i] = quoted;
      }

  return execvp (path, argv);
}

445 446
# undef execvp
# define execvp w32_execvp
447

448
/* Emulation of ttyname for Windows.  */
449 450
const char *ttyname (int);
const char *
451 452 453 454 455
ttyname (int fd)
{
  return "CONOUT$";
}

456
#endif /* WINDOWSNT */
Juanma Barranquero's avatar
Juanma Barranquero committed
457

Juanma Barranquero's avatar
Juanma Barranquero committed
458 459
/* Display a normal or error message.
   On Windows, use a message box if compiled as a Windows app.  */
460
static void message (bool, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3);
461
static void
462
message (bool is_error, const char *format, ...)
Juanma Barranquero's avatar
Juanma Barranquero committed
463 464 465
{
  va_list args;

466
  va_start (args, format);
Juanma Barranquero's avatar
Juanma Barranquero committed
467 468 469 470

#ifdef WINDOWSNT
  if (w32_window_app ())
    {
471 472 473 474
      char msg[2048];
      vsnprintf (msg, sizeof msg, format, args);
      msg[sizeof msg - 1] = '\0';

Juanma Barranquero's avatar
Juanma Barranquero committed
475 476 477 478 479 480 481
      if (is_error)
	MessageBox (NULL, msg, "Emacsclient ERROR", MB_ICONERROR);
      else
	MessageBox (NULL, msg, "Emacsclient", MB_ICONINFORMATION);
    }
  else
#endif
482 483 484
    {
      FILE *f = is_error ? stderr : stdout;

485
      vfprintf (f, format, args);
486 487
      fflush (f);
    }
488 489

  va_end (args);
Juanma Barranquero's avatar
Juanma Barranquero committed
490 491
}

492
/* Decode the options from argv and argc.
493
   The global variable 'optind' will say how many arguments we used up.  */
494

495
static void
496
decode_options (int argc, char **argv)
497
{
498
  alternate_editor = egetenv ("ALTERNATE_EDITOR");
499
  tramp_prefix = egetenv ("EMACSCLIENT_TRAMP");
500

501
  while (true)
502
    {
503 504
      int opt = getopt_long_only (argc, argv, shortopts, longopts, NULL);
      if (opt < 0)
505 506 507 508 509 510 511 512
	break;

      switch (opt)
	{
	case 0:
	  /* If getopt returns 0, then it has already processed a
	     long-named option.  We should do nothing.  */
	  break;
513

514 515 516
	case 'a':
	  alternate_editor = optarg;
	  break;
517

518
#ifdef SOCKETS_IN_FILE_SYSTEM
519 520 521
	case 's':
	  socket_name = optarg;
	  break;
522
#endif
523

524 525 526
	case 'f':
	  server_file = optarg;
	  break;
527

528 529 530 531
	  /* We used to disallow this argument in w32, but it seems better
	     to allow it, for the occasional case where the user is
	     connecting with a w32 client to a server compiled with X11
	     support.  */
Stefan Monnier's avatar
Stefan Monnier committed
532 533 534 535
	case 'd':
	  display = optarg;
	  break;

536
	case 'n':
537
	  nowait = true;
538 539
	  break;

Stefan Monnier's avatar
Stefan Monnier committed
540
	case 'e':
541
	  eval = true;
Stefan Monnier's avatar
Stefan Monnier committed
542 543
	  break;

544
	case 'q':
545
	  quiet = true;
546 547
	  break;

548
	case 'u':
549
	  suppress_output = true;
550 551
	  break;

552
	case 'V':
553
	  message (false, "emacsclient %s\n", VERSION);
554
	  exit (EXIT_SUCCESS);
555
	  break;
Richard M. Stallman's avatar
Richard M. Stallman committed
556

557
        case 't':
558 559
	  tty = true;
	  create_frame = true;
560 561
          break;

562
        case 'c':
563
	  create_frame = true;
564
          break;
565

566 567
	case 'p':
	  parent_id = optarg;
568
	  create_frame = true;
569 570
	  break;

571 572
	case 'H':
	  print_help_and_exit ();
573 574
	  break;

575 576 577 578
        case 'F':
          frame_parameters = optarg;
          break;

579 580 581 582
        case 'T':
          tramp_prefix = optarg;
          break;

583
	default:
584
	  message (true, "Try '%s --help' for more information\n", progname);
585
	  exit (EXIT_FAILURE);
586
	  break;
587 588
	}
    }
589

590 591
  /* If the -c option is used (without -t) and no --display argument
     is provided, try $DISPLAY.
592
     Without the -c option, we used to set 'display' to $DISPLAY by
593 594
     default, but this changed the default behavior and is sometimes
     inconvenient.  So we force users to use "--display $DISPLAY" if
595 596 597 598 599 600
     they want Emacs to connect to their current display.

     Some window systems have a notion of default display not
     reflected in the DISPLAY variable.  If the user didn't give us an
     explicit display, try this platform-specific after trying the
     display in DISPLAY (if any).  */
601
  if (create_frame && !tty && !display)
602
    {
603 604 605 606 607
      /* Set these here so we use a default_display only when the user
         didn't give us an explicit display.  */
#if defined (NS_IMPL_COCOA)
      alt_display = "ns";
#elif defined (HAVE_NTGUI)
608
      alt_display = "w32";
609
#endif
610 611 612 613 614 615 616 617

      display = egetenv ("DISPLAY");
    }

  if (!display)
    {
      display = alt_display;
      alt_display = NULL;
618
    }
619

620
  /* A null-string display is invalid.  */
621
  if (display && !display[0])
622 623
    display = NULL;

624
  /* If no display is available, new frames are tty frames.  */
625 626
  if (create_frame && !display)
    tty = true;
627

628
#ifdef WINDOWSNT
629 630 631
  /* Emacs on Windows does not support graphical and text terminal
     frames in the same instance.  So, treat the -t and -c options as
     equivalent, and open a new frame on the server's terminal.
632
     Ideally, we would set tty = true only if the server is running in a
633 634
     console, but alas we don't know that.  As a workaround, always
     ask for a tty frame, and let server.el figure it out.  */
635
  if (create_frame)
636 637
    {
      display = NULL;
638
      tty = true;
639
    }
640
#endif /* WINDOWSNT */
641 642
}

643

644
static _Noreturn void
645
print_help_and_exit (void)
646
{
647 648 649 650
  /* Spaces and tabs are significant in this message; they're chosen so the
     message aligns properly both in a tty and in a Windows message box.
     Please try to preserve them; otherwise the output is very hard to read
     when using emacsclientw.  */
651
  message (false,
Paul Eggert's avatar
Paul Eggert committed
652
	   "Usage: %s [OPTIONS] FILE...\n%s%s%s", progname, "\
Stefan Monnier's avatar
Stefan Monnier committed
653 654
Tell the Emacs server to visit the specified files.\n\
Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
655
\n\
Stefan Monnier's avatar
Stefan Monnier committed
656
The following OPTIONS are accepted:\n\
657 658
-V, --version		Just print version info and return\n\
-H, --help    		Print this usage information message\n\
659
-nw, -t, --tty 		Open a new Emacs frame on the current terminal\n\
660
-c, --create-frame    	Create a new frame instead of trying to\n\
661
			use the current Emacs frame\n\
Paul Eggert's avatar
Paul Eggert committed
662
", "\
663
-F ALIST, --frame-parameters=ALIST\n\
664
			Set the parameters of a new frame\n\
665
-e, --eval    		Evaluate the FILE arguments as ELisp expressions\n\
666
-n, --no-wait		Don't wait for the server to return\n\
667
-q, --quiet		Don't display messages on success\n\
668
-u, --suppress-output   Don't display return values from the server\n\
669
-d DISPLAY, --display=DISPLAY\n\
670
			Visit the file in the given display\n\
Paul Eggert's avatar
Paul Eggert committed
671
", "\
672
--parent-id=ID          Open in parent window ID, via XEmbed\n"
673
#ifdef SOCKETS_IN_FILE_SYSTEM
674
"-s SOCKET, --socket-name=SOCKET\n\
675
			Set filename of the UNIX socket for communication\n"
676
#endif
677
"-f SERVER, --server-file=SERVER\n\
678
			Set filename of the TCP authentication file\n\
679
-a EDITOR, --alternate-editor=EDITOR\n\
680
			Editor to fallback to if the server is not running\n"
681 682
"			If EDITOR is the empty string, start Emacs in daemon\n\
			mode and try connecting again\n"
683 684 685
"-T PREFIX, --tramp=PREFIX\n\
                        PREFIX to prepend to filenames sent by emacsclient\n\
                        for locating files remotely via Tramp\n"
686
"\n\
Paul Eggert's avatar
Paul Eggert committed
687
Report bugs with M-x report-emacs-bug.\n");
688
  exit (EXIT_SUCCESS);
689
}
690

691
/* Try to run a different command, or --if no alternate editor is
692
   defined-- exit with an error code.
693 694
   Uses argv, but gets it from the global variable main_argv.  */

695
static _Noreturn void
696
fail (void)
697
{
698
  if (alternate_editor)
699
    {
700 701
      size_t extra_args_size = (main_argc - optind + 1) * sizeof (char *);
      size_t new_argv_size = extra_args_size;
702
      char **new_argv = xmalloc (new_argv_size);
703
      char *s = xstrdup (alternate_editor);
704
      ptrdiff_t toks = 0;
705 706 707 708 709 710

      /* Unpack alternate_editor's space-separated tokens into new_argv.  */
      for (char *tok = s; tok != NULL && *tok != '\0';)
        {
          /* Allocate new token.  */
          ++toks;
711 712
          new_argv = xrealloc (new_argv,
			       new_argv_size + toks * sizeof (char *));
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730

          /* Skip leading delimiters, and set separator, skipping any
             opening quote.  */
          size_t skip = strspn (tok, " \"");
          tok += skip;
          char sep = (skip > 0 && tok[-1] == '"') ? '"' : ' ';

          /* Record start of token.  */
          new_argv[toks - 1] = tok;

          /* Find end of token and overwrite it with NUL.  */
          tok = strchr (tok, sep);
          if (tok != NULL)
            *tok++ = '\0';
        }

      /* Append main_argv arguments to new_argv.  */
      memcpy (&new_argv[toks], main_argv + optind, extra_args_size);
731

732
      execvp (*new_argv, new_argv);
733
      message (true, "%s: error executing alternate editor \"%s\"\n",
734
	       progname, alternate_editor);
735
    }
736
  exit (EXIT_FAILURE);
737 738
}

739

740
#ifdef SOCKETS_IN_FILE_SYSTEM
741
static void act_on_signals (HSOCKET);
742
#else
743
static void act_on_signals (HSOCKET s) {}
744
static void init_signals (void) {}
745
#endif
746

747
enum { AUTH_KEY_LENGTH = 64 };
748

749
static void
750
sock_err_message (const char *function_name)
751
{
752
#ifdef WINDOWSNT
753 754 755 756 757 758 759
  /* On Windows, the socket library was historically separate from the
     standard C library, so errors are handled differently.  */

  if (w32_window_app () && alternate_editor)
    return;

  char *msg = NULL;
760 761 762 763 764 765

  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
                 | FORMAT_MESSAGE_ALLOCATE_BUFFER
                 | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                 NULL, WSAGetLastError (), 0, (LPTSTR)&msg, 0, NULL);

766
  message (true, "%s: %s: %s\n", progname, function_name, msg);
767 768

  LocalFree (msg);
769
#else
770
  message (true, "%s: %s: %s\n", progname, function_name, strerror (errno));
771
#endif
772 773 774
}


775 776
/* Send to S the data in *DATA when either
   - the data's last byte is '\n', or
777
   - the buffer is full (but this shouldn't happen)
778
   Otherwise, just accumulate the data.  */
779
static void
780
send_to_emacs (HSOCKET s, const char *data)
781
{
782 783 784 785 786 787 788 789
  enum { SEND_BUFFER_SIZE = 4096 };

  /* Buffer to accumulate data to send in TCP connections.  */
  static char send_buffer[SEND_BUFFER_SIZE + 1];

  /* Fill pointer for the send buffer.  */
  static int sblen;

Paul Eggert's avatar
Paul Eggert committed
790
  for (ptrdiff_t dlen = strlen (data); dlen != 0; )
791
    {
Paul Eggert's avatar
Paul Eggert committed
792
      int part = min (dlen, SEND_BUFFER_SIZE - sblen);
793 794 795
      memcpy (&send_buffer[sblen], data, part);
      data += part;
      sblen += part;
796 797

      if (sblen == SEND_BUFFER_SIZE
Paul Eggert's avatar
Paul Eggert committed
798
	  || (0 < sblen && send_buffer[sblen - 1] == '\n'))
799
	{
800 801
	  int sent;
	  while ((sent = send (s, send_buffer, sblen, 0)) < 0)
802
	    {
803 804 805 806 807 808 809 810 811 812
	      if (errno != EINTR)
		{
		  message (true, "%s: failed to send %d bytes to socket: %s\n",
			   progname, sblen, strerror (errno));
		  fail ();
		}
	      /* Act on signals not requiring communication to Emacs,
		 but defer action on the others to avoid confusing the
		 communication currently in progress.  */
	      act_on_signals (INVALID_SOCKET);
813
	    }
814
	  sblen -= sent;
815
	  memmove (send_buffer, &send_buffer[sent], sblen);
816
	}
817 818

      dlen -= part;
819 820 821 822
    }
}


823
/* In STR, insert a & before each &, each space, each newline, and
Richard M. Stallman's avatar
Richard M. Stallman committed
824
   any initial -.  Change spaces to underscores, too, so that the
825 826
   return value never contains a space.

Juanma Barranquero's avatar
Juanma Barranquero committed
827
   Does not change the string.  Outputs the result to S.  */
828
static void
829
quote_argument (HSOCKET s, const char *str)
830
{
831
  char *copy = xmalloc (strlen (str) * 2 + 1);
832 833 834 835
  char *q = copy;
  if (*str == '-')
    *q++ = '&', *q++ = *str++;
  for (; *str; str++)
836
    {
837 838 839 840 841 842 843 844
      char c = *str;
      if (c == ' ')
	*q++ = '&', c = '_';
      else if (c == '\n')
	*q++ = '&', c = 'n';
      else if (c == '&')
	*q++ = '&';
      *q++ = c;
845
    }
846
  *q = 0;
847

848
  send_to_emacs (s, copy);
849 850

  free (copy);
851
}
852

853

854 855
/* The inverse of quote_argument.  Remove quoting in string STR by
   modifying the addressed string in place.  Return STR.  */
856

857
static char *
858
unquote_argument (char *str)
859
{
860 861 862
  char const *p = str;
  char *q = str;
  char c;
863

864
  do
865
    {
866 867 868 869 870 871 872 873 874 875
      c = *p++;
      if (c == '&')
	{
	  c = *p++;
	  if (c == '_')
	    c = ' ';
	  else if (c == 'n')
	    c = '\n';
	}
      *q++ = c;
876
    }
877 878
  while (c);

879 880 881
  return str;
}

882

883
#ifdef WINDOWSNT
884
/* Wrapper to make WSACleanup a cdecl, as required by atexit.  */
885
void __cdecl close_winsock (void);
886 887
void __cdecl
close_winsock (void)
888 889 890
{
  WSACleanup ();
}
891

892
/* Initialize the WinSock2 library.  */
893
void initialize_sockets (void);
894
void
895
initialize_sockets (void)
896
{
897 898 899 900
  WSADATA wsaData;

  if (WSAStartup (MAKEWORD (2, 0), &wsaData))
    {
901
      message (true, "%s: error initializing WinSock2\n", progname);
902 903 904 905
      exit (EXIT_FAILURE);
    }

  atexit (close_winsock);
906
}
907
#endif /* WINDOWSNT */
908

909

910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
/* If the home directory is HOME, return the configuration file with
   basename CONFIG_FILE.  Fail if there is no home directory or if the
   configuration file could not be opened.  */

static FILE *
open_config (char const *home, char const *config_file)
{
  if (!home)
    return NULL;
  ptrdiff_t homelen = strlen (home);
  static char const emacs_d_server[] = "/.emacs.d/server/";
  ptrdiff_t suffixsize = sizeof emacs_d_server + strlen (config_file);
  char *configname = xmalloc (homelen + suffixsize);
  strcpy (stpcpy (stpcpy (configname, home), emacs_d_server), config_file);

  FILE *config = fopen (configname, "rb");
  free (configname);
  return config;
}

930 931 932
/* Read the information needed to set up a TCP comm channel with
   the Emacs server: host, port, and authentication string.  */

933
static bool
934 935
get_server_config (const char *config_file, struct sockaddr_in *server,
		   char *authentication)
936
{
937 938
  char dotted[32];
  char *port;
939
  FILE *config;
940

941
  if (IS_ABSOLUTE_FILE_NAME (config_file))
942
    config = fopen (config_file, "rb");
943
  else
944
    {
945
      config = open_config (egetenv ("HOME"), config_file);