summaryrefslogtreecommitdiff
path: root/lib-src/emacsclient.c
diff options
context:
space:
mode:
authorReuben Thomas <rrt@sc3d.org>2016-12-01 15:21:57 +0000
committerReuben Thomas <rrt@sc3d.org>2017-08-30 21:59:38 +0100
commit98f01a13a3bf2a4db2dcc82a342ee017326de732 (patch)
tree70aac99762c0ee95026ec72fc307304b6700d372 /lib-src/emacsclient.c
parentdc313922d826b9f53cf1426ff36c8cc3f71d64c6 (diff)
downloademacs-98f01a13a3bf2a4db2dcc82a342ee017326de732.tar.gz
Add support for arguments in emacsclient's ALTERNATE_EDITOR (Bug #25082)
* lib-src/emacsclient.c (fail): Parse ALTERNATE_EDITOR, or corresponding command-line argument, into quote- or space-separated tokens. If a token starts with a quote, then it naturally is expected to end with a quote; escaping is not supported. This is enough to cope with the typical case of requiring the initial path to be quoted, common on Windows where it may contain spaces. * etc/NEWS: Document. * doc/emacs/misc.texi: Likewise. * doc/man/emacsclient.1: Tweak to remove the implication that only an editor can be specified (the manual already mentions a “command”). Fix a small error where “EDITOR” is referred to rather than “ALTERNATE_EDITOR”. * test/lib-src/emacsclient-tests.el: Add tests.
Diffstat (limited to 'lib-src/emacsclient.c')
-rw-r--r--lib-src/emacsclient.c84
1 files changed, 66 insertions, 18 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index f1d4e8976da..5e181ccacb1 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -110,6 +110,9 @@ char *w32_getenv (const char *);
/* Name used to invoke this program. */
const char *progname;
+/* The first argument to main. */
+int main_argc;
+
/* The second argument to main. */
char **main_argv;
@@ -201,6 +204,35 @@ xmalloc (size_t size)
return result;
}
+/* 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. */
+char *xstrdup (const char *);
+
+char *
+xstrdup (const char *s)
+{
+ char *result = strdup (s);
+ if (result == NULL)
+ {
+ perror ("strdup");
+ exit (EXIT_FAILURE);
+ }
+ return result;
+}
+
/* From sysdep.c */
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
@@ -264,21 +296,6 @@ get_current_dir_name (void)
#ifdef WINDOWSNT
-/* Like strdup but get a fatal error if memory is exhausted. */
-char *xstrdup (const char *);
-
-char *
-xstrdup (const char *s)
-{
- char *result = strdup (s);
- if (result == NULL)
- {
- perror ("strdup");
- exit (EXIT_FAILURE);
- }
- return result;
-}
-
#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
char *w32_get_resource (HKEY, const char *, LPDWORD);
@@ -673,7 +690,7 @@ Report bugs with M-x report-emacs-bug.\n");
}
/* Try to run a different command, or --if no alternate editor is
- defined-- exit with an errorcode.
+ defined-- exit with an error code.
Uses argv, but gets it from the global variable main_argv. */
static _Noreturn void
@@ -681,9 +698,38 @@ fail (void)
{
if (alternate_editor)
{
- int i = optind - 1;
+ size_t extra_args_size = (main_argc - optind + 1) * sizeof (char *);
+ size_t new_argv_size = extra_args_size;
+ char **new_argv = NULL;
+ char *s = xstrdup (alternate_editor);
+ unsigned toks = 0;
+
+ /* Unpack alternate_editor's space-separated tokens into new_argv. */
+ for (char *tok = s; tok != NULL && *tok != '\0';)
+ {
+ /* Allocate new token. */
+ ++toks;
+ new_argv = xrealloc (new_argv, new_argv_size + toks * sizeof (char *));
+
+ /* 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);
- execvp (alternate_editor, main_argv + i);
+ execvp (*new_argv, new_argv);
message (true, "%s: error executing alternate editor \"%s\"\n",
progname, alternate_editor);
}
@@ -696,6 +742,7 @@ fail (void)
int
main (int argc, char **argv)
{
+ main_argc = argc;
main_argv = argv;
progname = argv[0];
message (true, "%s: Sorry, the Emacs server is supported only\n"
@@ -1629,6 +1676,7 @@ main (int argc, char **argv)
int start_daemon_if_needed;
int exit_status = EXIT_SUCCESS;
+ main_argc = argc;
main_argv = argv;
progname = argv[0];