summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJens Schmidt <jschmidt4gnu@vodafonemail.de>2025-04-02 22:48:31 +0200
committerEli Zaretskii <eliz@gnu.org>2025-04-13 11:33:30 +0300
commite82989757f42e95bf72a2a55de415a8162a55dc3 (patch)
treea403b48a17f89cc6a001eeeaad84a4e4e5c685bb /src
parent5665b446b7a5b2f6ff4d4e7ea9b2c91e0e733c92 (diff)
Use a pristine copy of argv to restart Emacs
argv as left after main has proccessed the command-line can differ both in order and contents of the original command-line arguments, which can lead to surprising results when restarting emacs on the cooked argv through `kill-emacs'. Starting from that observation, consistenly use variables 'initial_cmdline' on Windows, 'initial_argc', 'initial_argv' on non-Windows, and 'initial_argv0' in all ports. * src/lisp.h: Declare 'initial_argv0', limit declaration of 'initial_argv' and 'initial_argc' to non-Windows ports. * src/emacs.c: Likewise, but for the definitions. (init_cmdargs): Move initialization of 'initial_argv' and 'initial_argc' ... (copy_args) [!WINDOWSNT]: ... to this new function ... (main): ... and call that in 'main', also initializing 'initial_argv0' before the command-line processing. * src/emacs.c (Fkill_emacs): * src/pgtkterm.c (pgtk_term_init): * src/sysdep.c (emacs_perror): * src/xterm.c (x_term_init): Use 'initial_argv0' where only that is required. (Bug#77389)
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c50
-rw-r--r--src/lisp.h3
-rw-r--r--src/pgtkterm.c2
-rw-r--r--src/sysdep.c3
-rw-r--r--src/xterm.c2
5 files changed, 51 insertions, 9 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 6ff7b632c0f..79604d09a37 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -238,14 +238,32 @@ static int daemon_pipe[2];
HANDLE w32_daemon_event;
#endif
-/* Save argv and argc. */
+/* Save argv and argc.
+
+ initial_argc, initial_argv:
+ A pristine copy of the command-line arguments as passed into main,
+ saved away before main has had a chance to modify them. On
+ Windows, we use initial_cmdline instead.
+
+ initial_argv0:
+ argv[0] as passed into main. Available on all ports.
+
+ initial_emacs_executable:
+ Path to the current executable. Based on argv[0] but verified to
+ point to an existing executable if non-NULL. */
+#ifndef WINDOWSNT
char **initial_argv;
int initial_argc;
+#endif
+char *initial_argv0;
static char *initial_emacs_executable = NULL;
/* The name of the working directory, or NULL if this info is unavailable. */
char const *emacs_wd;
+#ifndef WINDOWSNT
+static void copy_args (int argc, char **argv);
+#endif
static void sort_args (int argc, char **argv);
static void syms_of_emacs (void);
@@ -476,9 +494,6 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
Lisp_Object raw_name;
AUTO_STRING (slash_colon, "/:");
- initial_argv = argv;
- initial_argc = argc;
-
#ifdef WINDOWSNT
/* Must use argv[0] converted to UTF-8, as it begets many standard
file and directory names. */
@@ -1396,6 +1411,11 @@ android_emacs_init (int argc, char **argv, char *dump_file)
init_standard_fds ();
atexit (close_output_streams);
+#ifndef WINDOWSNT
+ copy_args (argc, argv);
+#endif
+ initial_argv0 = argv[0];
+
/* Command-line argument processing.
The arguments in the argv[] array are sorted in the descending
@@ -2696,6 +2716,26 @@ static const struct standard_args standard_args[] =
{ "-kill", "--kill", -10, 0 },
};
+#ifndef WINDOWSNT
+
+/* Copy the elements of ARGV (assumed to have ARGC elements) and store
+ the copy in initial_argv. Store ARGC in initial_argc. */
+
+static void
+copy_args (int argc, char **argv)
+{
+ char **new = xmalloc ((argc + 1) * sizeof *new);
+ int i;
+ new[0] = argv[0];
+ for (i = 1; i < argc; i++)
+ new[i] = xstrdup (argv[i]);
+ new[argc] = argv[argc];
+ initial_argv = new;
+ initial_argc = argc;
+}
+
+#endif
+
/* Reorder the elements of ARGV (assumed to have ARGC elements)
so that the highest priority ones come first.
Do not change the order of elements of equal priority.
@@ -2900,7 +2940,7 @@ killed. */
error ("Unknown Emacs executable");
if (!file_access_p (initial_emacs_executable, F_OK))
- error ("Emacs executable \"%s\" can't be found", initial_argv[0]);
+ error ("Emacs executable \"%s\" can't be found", initial_argv0);
}
#endif
diff --git a/src/lisp.h b/src/lisp.h
index 243e8cc7f36..bca58b9c12d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -5136,8 +5136,11 @@ extern void init_frame_once (void);
extern void syms_of_frame (void);
/* Defined in emacs.c. */
+#ifndef WINDOWSNT
extern char **initial_argv;
extern int initial_argc;
+#endif
+extern char *initial_argv0;
extern char const *emacs_wd;
#if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) || defined (HAVE_NS)
extern bool display_arg;
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index a2e23a5616b..3d59a239ccd 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -7075,7 +7075,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
argv[argc] = 0;
argc = 0;
- argv[argc++] = initial_argv[0];
+ argv[argc++] = initial_argv0;
if (strlen (dpy_name) != 0)
{
diff --git a/src/sysdep.c b/src/sysdep.c
index a161b4af100..042de2acf80 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2854,8 +2854,7 @@ emacs_perror (char const *message)
{
int err = errno;
char const *error_string = emacs_strerror (err);
- char const *command = (initial_argv && initial_argv[0]
- ? initial_argv[0] : "emacs");
+ char const *command = (initial_argv0 ? initial_argv0 : "emacs");
/* Write it out all at once, if it's short; this is less likely to
be interleaved with other output. */
char buf[min (PIPE_BUF, MAX_ALLOCA)];
diff --git a/src/xterm.c b/src/xterm.c
index b21efd5a2a2..18a9231e75a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -30619,7 +30619,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
argv[argc] = 0;
argc = 0;
- argv[argc++] = initial_argv[0];
+ argv[argc++] = initial_argv0;
if (! NILP (display_name))
{