diff options
| author | Jens Schmidt | 2025-04-02 22:48:31 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2025-04-13 11:33:30 +0300 |
| commit | e82989757f42e95bf72a2a55de415a8162a55dc3 (patch) | |
| tree | a403b48a17f89cc6a001eeeaad84a4e4e5c685bb | |
| parent | 5665b446b7a5b2f6ff4d4e7ea9b2c91e0e733c92 (diff) | |
| download | emacs-e82989757f42e95bf72a2a55de415a8162a55dc3.tar.gz emacs-e82989757f42e95bf72a2a55de415a8162a55dc3.zip | |
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)
| -rw-r--r-- | src/emacs.c | 50 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/pgtkterm.c | 2 | ||||
| -rw-r--r-- | src/sysdep.c | 3 | ||||
| -rw-r--r-- | src/xterm.c | 2 |
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]; | |||
| 238 | HANDLE w32_daemon_event; | 238 | HANDLE w32_daemon_event; |
| 239 | #endif | 239 | #endif |
| 240 | 240 | ||
| 241 | /* Save argv and argc. */ | 241 | /* Save argv and argc. |
| 242 | |||
| 243 | initial_argc, initial_argv: | ||
| 244 | A pristine copy of the command-line arguments as passed into main, | ||
| 245 | saved away before main has had a chance to modify them. On | ||
| 246 | Windows, we use initial_cmdline instead. | ||
| 247 | |||
| 248 | initial_argv0: | ||
| 249 | argv[0] as passed into main. Available on all ports. | ||
| 250 | |||
| 251 | initial_emacs_executable: | ||
| 252 | Path to the current executable. Based on argv[0] but verified to | ||
| 253 | point to an existing executable if non-NULL. */ | ||
| 254 | #ifndef WINDOWSNT | ||
| 242 | char **initial_argv; | 255 | char **initial_argv; |
| 243 | int initial_argc; | 256 | int initial_argc; |
| 257 | #endif | ||
| 258 | char *initial_argv0; | ||
| 244 | static char *initial_emacs_executable = NULL; | 259 | static char *initial_emacs_executable = NULL; |
| 245 | 260 | ||
| 246 | /* The name of the working directory, or NULL if this info is unavailable. */ | 261 | /* The name of the working directory, or NULL if this info is unavailable. */ |
| 247 | char const *emacs_wd; | 262 | char const *emacs_wd; |
| 248 | 263 | ||
| 264 | #ifndef WINDOWSNT | ||
| 265 | static void copy_args (int argc, char **argv); | ||
| 266 | #endif | ||
| 249 | static void sort_args (int argc, char **argv); | 267 | static void sort_args (int argc, char **argv); |
| 250 | static void syms_of_emacs (void); | 268 | static void syms_of_emacs (void); |
| 251 | 269 | ||
| @@ -476,9 +494,6 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) | |||
| 476 | Lisp_Object raw_name; | 494 | Lisp_Object raw_name; |
| 477 | AUTO_STRING (slash_colon, "/:"); | 495 | AUTO_STRING (slash_colon, "/:"); |
| 478 | 496 | ||
| 479 | initial_argv = argv; | ||
| 480 | initial_argc = argc; | ||
| 481 | |||
| 482 | #ifdef WINDOWSNT | 497 | #ifdef WINDOWSNT |
| 483 | /* Must use argv[0] converted to UTF-8, as it begets many standard | 498 | /* Must use argv[0] converted to UTF-8, as it begets many standard |
| 484 | file and directory names. */ | 499 | file and directory names. */ |
| @@ -1396,6 +1411,11 @@ android_emacs_init (int argc, char **argv, char *dump_file) | |||
| 1396 | init_standard_fds (); | 1411 | init_standard_fds (); |
| 1397 | atexit (close_output_streams); | 1412 | atexit (close_output_streams); |
| 1398 | 1413 | ||
| 1414 | #ifndef WINDOWSNT | ||
| 1415 | copy_args (argc, argv); | ||
| 1416 | #endif | ||
| 1417 | initial_argv0 = argv[0]; | ||
| 1418 | |||
| 1399 | /* Command-line argument processing. | 1419 | /* Command-line argument processing. |
| 1400 | 1420 | ||
| 1401 | The arguments in the argv[] array are sorted in the descending | 1421 | The arguments in the argv[] array are sorted in the descending |
| @@ -2696,6 +2716,26 @@ static const struct standard_args standard_args[] = | |||
| 2696 | { "-kill", "--kill", -10, 0 }, | 2716 | { "-kill", "--kill", -10, 0 }, |
| 2697 | }; | 2717 | }; |
| 2698 | 2718 | ||
| 2719 | #ifndef WINDOWSNT | ||
| 2720 | |||
| 2721 | /* Copy the elements of ARGV (assumed to have ARGC elements) and store | ||
| 2722 | the copy in initial_argv. Store ARGC in initial_argc. */ | ||
| 2723 | |||
| 2724 | static void | ||
| 2725 | copy_args (int argc, char **argv) | ||
| 2726 | { | ||
| 2727 | char **new = xmalloc ((argc + 1) * sizeof *new); | ||
| 2728 | int i; | ||
| 2729 | new[0] = argv[0]; | ||
| 2730 | for (i = 1; i < argc; i++) | ||
| 2731 | new[i] = xstrdup (argv[i]); | ||
| 2732 | new[argc] = argv[argc]; | ||
| 2733 | initial_argv = new; | ||
| 2734 | initial_argc = argc; | ||
| 2735 | } | ||
| 2736 | |||
| 2737 | #endif | ||
| 2738 | |||
| 2699 | /* Reorder the elements of ARGV (assumed to have ARGC elements) | 2739 | /* Reorder the elements of ARGV (assumed to have ARGC elements) |
| 2700 | so that the highest priority ones come first. | 2740 | so that the highest priority ones come first. |
| 2701 | Do not change the order of elements of equal priority. | 2741 | Do not change the order of elements of equal priority. |
| @@ -2900,7 +2940,7 @@ killed. */ | |||
| 2900 | error ("Unknown Emacs executable"); | 2940 | error ("Unknown Emacs executable"); |
| 2901 | 2941 | ||
| 2902 | if (!file_access_p (initial_emacs_executable, F_OK)) | 2942 | if (!file_access_p (initial_emacs_executable, F_OK)) |
| 2903 | error ("Emacs executable \"%s\" can't be found", initial_argv[0]); | 2943 | error ("Emacs executable \"%s\" can't be found", initial_argv0); |
| 2904 | } | 2944 | } |
| 2905 | #endif | 2945 | #endif |
| 2906 | 2946 | ||
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); | |||
| 5136 | extern void syms_of_frame (void); | 5136 | extern void syms_of_frame (void); |
| 5137 | 5137 | ||
| 5138 | /* Defined in emacs.c. */ | 5138 | /* Defined in emacs.c. */ |
| 5139 | #ifndef WINDOWSNT | ||
| 5139 | extern char **initial_argv; | 5140 | extern char **initial_argv; |
| 5140 | extern int initial_argc; | 5141 | extern int initial_argc; |
| 5142 | #endif | ||
| 5143 | extern char *initial_argv0; | ||
| 5141 | extern char const *emacs_wd; | 5144 | extern char const *emacs_wd; |
| 5142 | #if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) || defined (HAVE_NS) | 5145 | #if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) || defined (HAVE_NS) |
| 5143 | extern bool display_arg; | 5146 | 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) | |||
| 7075 | argv[argc] = 0; | 7075 | argv[argc] = 0; |
| 7076 | 7076 | ||
| 7077 | argc = 0; | 7077 | argc = 0; |
| 7078 | argv[argc++] = initial_argv[0]; | 7078 | argv[argc++] = initial_argv0; |
| 7079 | 7079 | ||
| 7080 | if (strlen (dpy_name) != 0) | 7080 | if (strlen (dpy_name) != 0) |
| 7081 | { | 7081 | { |
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) | |||
| 2854 | { | 2854 | { |
| 2855 | int err = errno; | 2855 | int err = errno; |
| 2856 | char const *error_string = emacs_strerror (err); | 2856 | char const *error_string = emacs_strerror (err); |
| 2857 | char const *command = (initial_argv && initial_argv[0] | 2857 | char const *command = (initial_argv0 ? initial_argv0 : "emacs"); |
| 2858 | ? initial_argv[0] : "emacs"); | ||
| 2859 | /* Write it out all at once, if it's short; this is less likely to | 2858 | /* Write it out all at once, if it's short; this is less likely to |
| 2860 | be interleaved with other output. */ | 2859 | be interleaved with other output. */ |
| 2861 | char buf[min (PIPE_BUF, MAX_ALLOCA)]; | 2860 | 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) | |||
| 30619 | argv[argc] = 0; | 30619 | argv[argc] = 0; |
| 30620 | 30620 | ||
| 30621 | argc = 0; | 30621 | argc = 0; |
| 30622 | argv[argc++] = initial_argv[0]; | 30622 | argv[argc++] = initial_argv0; |
| 30623 | 30623 | ||
| 30624 | if (! NILP (display_name)) | 30624 | if (! NILP (display_name)) |
| 30625 | { | 30625 | { |