]> git.eshelyaron.com Git - emacs.git/commitdiff
Use a pristine copy of argv to restart Emacs
authorJens Schmidt <jschmidt4gnu@vodafonemail.de>
Wed, 2 Apr 2025 20:48:31 +0000 (22:48 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sun, 13 Apr 2025 20:56:05 +0000 (22:56 +0200)
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)

(cherry picked from commit e82989757f42e95bf72a2a55de415a8162a55dc3)

src/emacs.c
src/lisp.h
src/pgtkterm.c
src/sysdep.c
src/xterm.c

index 6ff7b632c0faa6a479435c051ad0870f02bc7a76..79604d09a37f2236f9350cda9ead450840214271 100644 (file)
@@ -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
 
index 350533547a70c1b5a2ae14a0577b2e9deeb8fe74..079825cd0f41292695de31f8b24cf2bee2c2df71 100644 (file)
@@ -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;
index 889f8fc127051520d172417335ada69fb4277ffa..200578656a7a89c1645218097d2d79ac4fdbff1d 100644 (file)
@@ -7072,7 +7072,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)
          {
index a161b4af100b86565a73c959ae2faa053d4f5daf..042de2acf80084d0dd4bd628fe96e3d60f814416 100644 (file)
@@ -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)];
index b21efd5a2a2fc8fae9f24da6368dace8821cfbcb..18a9231e75ad6d8cf7f89b0c12c8b3b0cd5fe699 100644 (file)
@@ -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))
           {