This source file includes following definitions.
- setlocale
- using_utf8
- terminate_due_to_signal
- init_cmdargs
- DEFUN
- DEFUN
- argmatch
- find_emacs_executable
- dump_error_to_string
- load_pdump
- emacs_seccomp
- read_full
- load_seccomp
- maybe_load_seccomp
- android_emacs_init
- sort_args
- shut_down_emacs
- fixup_locale
- synchronize_locale
- synchronize_system_time_locale
- synchronize_system_messages_locale
- emacs_strerror
- decode_env_path
- DEFUN
- DEFUN
- syms_of_emacs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #define INLINE EXTERN_INLINE
22 #include <config.h>
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27
28 #include <sys/file.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #define MAIN_PROGRAM
33 #include "lisp.h"
34 #include "sysstdio.h"
35
36 #ifdef HAVE_ANDROID
37 #include "androidterm.h"
38 #endif
39
40 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
41 #include "sfntfont.h"
42 #endif
43
44 #ifdef WINDOWSNT
45 #include <fcntl.h>
46 #include <sys/socket.h>
47 #include <mbstring.h>
48 #include <filename.h>
49 #include "w32.h"
50 #include "w32heap.h"
51 #endif
52
53 #if defined WINDOWSNT || defined HAVE_NTGUI
54 #include "w32select.h"
55 #include "w32font.h"
56 #include "w32common.h"
57 #endif
58
59 #if defined CYGWIN
60 #include "cygw32.h"
61 #endif
62
63 #ifdef MSDOS
64 #include <binary-io.h>
65 #include "dosfns.h"
66 #endif
67
68 #ifdef HAVE_LIBSYSTEMD
69 # include <systemd/sd-daemon.h>
70 # include <sys/socket.h>
71 #endif
72
73 #if defined HAVE_LINUX_SECCOMP_H && defined HAVE_LINUX_FILTER_H \
74 && HAVE_DECL_SECCOMP_SET_MODE_FILTER \
75 && HAVE_DECL_SECCOMP_FILTER_FLAG_TSYNC
76 # define SECCOMP_USABLE 1
77 #else
78 # define SECCOMP_USABLE 0
79 #endif
80
81 #if SECCOMP_USABLE
82 # include <linux/seccomp.h>
83 # include <linux/filter.h>
84 # include <sys/prctl.h>
85 # include <sys/syscall.h>
86 #endif
87
88 #ifdef HAVE_WINDOW_SYSTEM
89 #include TERM_HEADER
90 #endif
91
92 #include "bignum.h"
93 #include "itree.h"
94 #include "intervals.h"
95 #include "character.h"
96 #include "buffer.h"
97 #include "window.h"
98 #include "xwidget.h"
99 #include "atimer.h"
100 #include "blockinput.h"
101 #include "syssignal.h"
102 #include "process.h"
103 #include "frame.h"
104 #include "termhooks.h"
105 #include "keyboard.h"
106 #include "keymap.h"
107 #include "category.h"
108 #include "charset.h"
109 #include "composite.h"
110 #include "dispextern.h"
111 #include "regex-emacs.h"
112 #include "sheap.h"
113 #include "syntax.h"
114 #include "sysselect.h"
115 #include "systime.h"
116 #include "puresize.h"
117
118 #include "getpagesize.h"
119 #include "gnutls.h"
120
121 #ifdef HAVE_HAIKU
122 #include <kernel/OS.h>
123 #endif
124
125 #ifdef PROFILING
126 # include <sys/gmon.h>
127 extern void moncontrol (int mode);
128 # ifdef __MINGW32__
129 extern unsigned char etext asm ("etext");
130 # else
131 extern char etext;
132 # endif
133 #endif
134
135 #ifdef HAVE_SETLOCALE
136 #include <locale.h>
137 #endif
138
139 #if HAVE_WCHAR_H
140 # include <wchar.h>
141 #endif
142
143 #ifdef HAVE_SETRLIMIT
144 #include <sys/time.h>
145 #include <sys/resource.h>
146 #endif
147
148 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
149 #include "android.h"
150 #endif
151
152
153
154 #include "treesit.h"
155
156 #include "pdumper.h"
157 #include "fingerprint.h"
158 #include "epaths.h"
159
160
161 #include "comp.h"
162 #include "thread.h"
163
164 static const char emacs_version[] = PACKAGE_VERSION;
165 static const char emacs_copyright[] = COPYRIGHT;
166 static const char emacs_bugreport[] = PACKAGE_BUGREPORT;
167
168
169 char const EXTERNALLY_VISIBLE RCS_Id[]
170 = "$Id" ": GNU Emacs " PACKAGE_VERSION
171 " (" EMACS_CONFIGURATION " " EMACS_CONFIG_FEATURES ") $";
172
173
174 Lisp_Object empty_unibyte_string, empty_multibyte_string;
175
176 #ifdef WINDOWSNT
177
178 Lisp_Object Vlibrary_cache;
179
180 static char *initial_cmdline;
181
182 static const char *initial_wd;
183 #endif
184
185 struct gflags gflags;
186 bool initialized;
187
188
189
190 bool inhibit_window_system;
191
192
193
194 bool running_asynch_code;
195
196 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS)
197
198 bool display_arg;
199 #endif
200
201 #if defined GNU_LINUX && defined HAVE_UNEXEC
202
203 static uintmax_t heap_bss_diff;
204 #endif
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222 #if defined NS_IMPL_COCOA || defined CYGWIN || defined HAVE_HAIKU
223 # define DAEMON_MUST_EXEC
224 #endif
225
226
227 bool noninteractive;
228
229
230 bool no_site_lisp;
231
232
233 bool build_details;
234
235
236 static char *daemon_name;
237
238
239
240 int daemon_type;
241
242 #ifndef WINDOWSNT
243
244
245 static int daemon_pipe[2];
246 #else
247 HANDLE w32_daemon_event;
248 #endif
249
250
251 char **initial_argv;
252 int initial_argc;
253 static char *initial_emacs_executable = NULL;
254
255
256 char const *emacs_wd;
257
258 static void sort_args (int argc, char **argv);
259 static void syms_of_emacs (void);
260
261
262
263 static char const *const usage_message[] =
264 { "\
265 \n\
266 Run Emacs, the extensible, customizable, self-documenting real-time\n\
267 display editor. The recommended way to start Emacs for normal editing\n\
268 is with no options at all.\n\
269 \n\
270 Run M-x info RET m emacs RET m emacs invocation RET inside Emacs to\n\
271 read the main documentation for these command-line arguments.\n\
272 \n\
273 Initialization options:\n\
274 \n\
275 ",
276 "\
277 --batch do not do interactive display; implies -q\n\
278 --chdir DIR change to directory DIR\n\
279 --daemon, --bg-daemon[=NAME] start a (named) server in the background\n\
280 --fg-daemon[=NAME] start a (named) server in the foreground\n\
281 --debug-init enable Emacs Lisp debugger for init file\n\
282 --display, -d DISPLAY use X server DISPLAY\n\
283 ",
284 #ifdef HAVE_MODULES
285 "\
286 --module-assertions assert behavior of dynamic modules\n\
287 ",
288 #endif
289 #ifdef HAVE_PDUMPER
290 "\
291 --dump-file FILE read dumped state from FILE\n\
292 --fingerprint output fingerprint and exit\n\
293 ",
294 #endif
295 #if SECCOMP_USABLE
296 "\
297 --seccomp=FILE read Seccomp BPF filter from FILE\n\
298 "
299 #endif
300 "\
301 --no-build-details do not add build details such as time stamps\n\
302 --no-desktop do not load a saved desktop\n\
303 --no-init-file, -q load neither ~/.emacs nor default.el\n\
304 --no-loadup, -nl do not load loadup.el into bare Emacs\n\
305 --no-site-file do not load site-start.el\n\
306 --no-x-resources do not load X resources\n\
307 --no-site-lisp, -nsl do not add site-lisp directories to load-path\n\
308 --no-splash do not display a splash screen on startup\n\
309 --no-window-system, -nw do not communicate with X, ignoring $DISPLAY\n\
310 --init-directory=DIR use DIR when looking for the Emacs init files.\n\
311 ",
312 "\
313 --quick, -Q equivalent to:\n\
314 -q --no-site-file --no-site-lisp --no-splash\n\
315 --no-x-resources\n\
316 --script FILE run FILE as an Emacs Lisp script\n\
317 -x to be used in #!/usr/bin/emacs -x\n\
318 and has approximately the same meaning\n\
319 as -Q --script\n\
320 --terminal, -t DEVICE use DEVICE for terminal I/O\n\
321 --user, -u USER load ~USER/.emacs instead of your own\n\
322 \n\
323 ",
324 "\
325 Action options:\n\
326 \n\
327 FILE visit FILE\n\
328 +LINE go to line LINE in next FILE\n\
329 +LINE:COLUMN go to line LINE, column COLUMN, in next FILE\n\
330 --directory, -L DIR prepend DIR to load-path (with :DIR, append DIR)\n\
331 --eval EXPR evaluate Emacs Lisp expression EXPR\n\
332 --execute EXPR evaluate Emacs Lisp expression EXPR\n\
333 ",
334 "\
335 --file FILE visit FILE\n\
336 --find-file FILE visit FILE\n\
337 --funcall, -f FUNC call Emacs Lisp function FUNC with no arguments\n\
338 --insert FILE insert contents of FILE into current buffer\n\
339 --kill exit without asking for confirmation\n\
340 --load, -l FILE load Emacs Lisp FILE using the load function\n\
341 --visit FILE visit FILE\n\
342 \n\
343 ",
344 "\
345 Display options:\n\
346 \n\
347 --background-color, -bg COLOR window background color\n\
348 --basic-display, -D disable many display features;\n\
349 used for debugging Emacs\n\
350 --border-color, -bd COLOR main border color\n\
351 --border-width, -bw WIDTH width of main border\n\
352 ",
353 "\
354 --color, --color=MODE override color mode for character terminals;\n\
355 MODE defaults to `auto', and\n\
356 can also be `never', `always',\n\
357 or a mode name like `ansi8'\n\
358 --cursor-color, -cr COLOR color of the Emacs cursor indicating point\n\
359 --font, -fn FONT default font; must be fixed-width\n\
360 --foreground-color, -fg COLOR window foreground color\n\
361 ",
362 "\
363 --fullheight, -fh make the first frame high as the screen\n\
364 --fullscreen, -fs make the first frame fullscreen\n\
365 --fullwidth, -fw make the first frame wide as the screen\n\
366 --maximized, -mm make the first frame maximized\n\
367 --geometry, -g GEOMETRY window geometry\n\
368 ",
369 "\
370 --no-bitmap-icon, -nbi do not use picture of gnu for Emacs icon\n\
371 --iconic start Emacs in iconified state\n\
372 --internal-border, -ib WIDTH width between text and main border\n\
373 --line-spacing, -lsp PIXELS additional space to put between lines\n\
374 --mouse-color, -ms COLOR mouse cursor color in Emacs window\n\
375 --name NAME title for initial Emacs frame\n\
376 ",
377 "\
378 --no-blinking-cursor, -nbc disable blinking cursor\n\
379 --reverse-video, -r, -rv switch foreground and background\n\
380 --title, -T TITLE title for initial Emacs frame\n\
381 --vertical-scroll-bars, -vb enable vertical scroll bars\n\
382 --xrm XRESOURCES set additional X resources\n\
383 --parent-id XID set parent window\n\
384 --help display this help and exit\n\
385 --version output version information and exit\n\
386 \n\
387 ",
388 "\
389 You can generally also specify long option names with a single -; for\n\
390 example, -batch as well as --batch. You can use any unambiguous\n\
391 abbreviation for a --option.\n\
392 \n\
393 Various environment variables and window system resources also affect\n\
394 the operation of Emacs. See the main documentation.\n\
395 \n\
396 Report bugs to " PACKAGE_BUGREPORT ". First, please see the Bugs\n\
397 section of the Emacs manual or the file BUGS.\n"
398 };
399
400
401
402 bool fatal_error_in_progress;
403
404 #ifdef HAVE_NS
405
406 static void *ns_pool;
407 #endif
408
409 #if !HAVE_SETLOCALE
410 static char *
411 setlocale (int cat, char const *locale)
412 {
413 return 0;
414 }
415 #endif
416
417
418 static bool
419 using_utf8 (void)
420 {
421
422
423
424 #if defined HAVE_WCHAR_H && !defined WINDOWSNT
425 wchar_t wc;
426 #ifndef HAVE_ANDROID
427 mbstate_t mbs = { 0 };
428 #else
429 mbstate_t mbs;
430
431
432
433 memset (&mbs, 0, sizeof mbs);
434 #endif
435 return mbrtowc (&wc, "\xc4\x80", 2, &mbs) == 2 && wc == 0x100;
436 #else
437 return false;
438 #endif
439 }
440
441
442
443
444 AVOID
445 terminate_due_to_signal (int sig, int backtrace_limit)
446 {
447 signal (sig, SIG_DFL);
448
449 if (attempt_orderly_shutdown_on_fatal_signal)
450 {
451
452 if (! fatal_error_in_progress)
453 {
454 fatal_error_in_progress = 1;
455
456 totally_unblock_input ();
457 if (sig == SIGTERM || sig == SIGHUP || sig == SIGINT)
458 {
459
460
461
462 if (noninteractive)
463 clear_message_stack ();
464 Fkill_emacs (make_fixnum (sig), Qnil);
465 }
466
467 shut_down_emacs (sig, Qnil);
468 emacs_backtrace (backtrace_limit);
469 }
470 }
471
472
473
474
475 #ifndef MSDOS
476 {
477 sigset_t unblocked;
478 sigemptyset (&unblocked);
479 sigaddset (&unblocked, sig);
480 pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
481 }
482 #endif
483
484 emacs_raise (sig);
485
486
487 exit (1);
488 }
489
490
491
492 static void
493 init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
494 {
495 int i;
496 Lisp_Object name, dir, handler;
497 specpdl_ref count = SPECPDL_INDEX ();
498 Lisp_Object raw_name;
499 AUTO_STRING (slash_colon, "/:");
500
501 initial_argv = argv;
502 initial_argc = argc;
503
504 #ifdef WINDOWSNT
505
506
507 {
508 char argv0[MAX_UTF8_PATH];
509
510 if (filename_from_ansi (argv[0], argv0) == 0)
511 raw_name = build_unibyte_string (argv0);
512 else
513 raw_name = build_unibyte_string (argv[0]);
514 }
515 #else
516 raw_name = build_unibyte_string (argv[0]);
517 #endif
518
519
520
521 handler = Ffind_file_name_handler (raw_name, Qt);
522 if (! NILP (handler))
523 raw_name = concat2 (slash_colon, raw_name);
524
525 Vinvocation_name = Ffile_name_nondirectory (raw_name);
526 Vinvocation_directory = Ffile_name_directory (raw_name);
527
528
529
530 if (NILP (Vinvocation_directory))
531 {
532 Lisp_Object found;
533 int yes = openp (Vexec_path, Vinvocation_name, Vexec_suffixes,
534 &found, make_fixnum (X_OK), false, false,
535 NULL);
536 if (yes == 1)
537 {
538
539
540 handler = Ffind_file_name_handler (found, Qt);
541 if (! NILP (handler))
542 found = concat2 (slash_colon, found);
543 Vinvocation_directory = Ffile_name_directory (found);
544 }
545 }
546
547 if (!NILP (Vinvocation_directory)
548 && NILP (Ffile_name_absolute_p (Vinvocation_directory)))
549
550
551 {
552 Lisp_Object odir =
553 original_pwd ? build_unibyte_string (original_pwd) : Qnil;
554
555 Vinvocation_directory = Fexpand_file_name (Vinvocation_directory, odir);
556 }
557
558 Vinstallation_directory = Qnil;
559
560 if (!NILP (Vinvocation_directory))
561 {
562 dir = Vinvocation_directory;
563 #ifdef WINDOWSNT
564
565
566
567 if (SBYTES (dir) > sizeof ("/i386/") - 1
568 && 0 == strcmp (SSDATA (dir) + SBYTES (dir) - sizeof ("/i386/") + 1,
569 "/i386/"))
570 {
571 if (NILP (Vpurify_flag))
572 {
573 Lisp_Object file_truename = intern ("file-truename");
574 if (!NILP (Ffboundp (file_truename)))
575 dir = call1 (file_truename, dir);
576 }
577 dir = Fexpand_file_name (build_string ("../.."), dir);
578 }
579 #endif
580 name = Fexpand_file_name (Vinvocation_name, dir);
581 while (1)
582 {
583 Lisp_Object tem, lib_src_exists;
584 Lisp_Object etc_exists, info_exists;
585
586
587
588
589 tem = Fexpand_file_name (build_string ("lib-src"), dir);
590 lib_src_exists = Ffile_exists_p (tem);
591
592 #ifdef MSDOS
593
594
595
596 tem = Fexpand_file_name (build_string ("info"), dir);
597 info_exists = Ffile_exists_p (tem);
598 #else
599 info_exists = Qnil;
600 #endif
601
602 if (!NILP (lib_src_exists) || !NILP (info_exists))
603 {
604 tem = Fexpand_file_name (build_string ("etc"), dir);
605 etc_exists = Ffile_exists_p (tem);
606 if (!NILP (etc_exists))
607 {
608 Vinstallation_directory = Ffile_name_as_directory (dir);
609 break;
610 }
611 }
612
613
614 tem = Fexpand_file_name (build_string ("../lib-src"), dir);
615 lib_src_exists = Ffile_exists_p (tem);
616
617
618 #ifdef MSDOS
619
620 tem = Fexpand_file_name (build_string ("../info"), dir);
621 info_exists = Ffile_exists_p (tem);
622 #else
623 info_exists = Qnil;
624 #endif
625
626 if (!NILP (lib_src_exists) || !NILP (info_exists))
627 {
628 tem = Fexpand_file_name (build_string ("../etc"), dir);
629 etc_exists = Ffile_exists_p (tem);
630 if (!NILP (etc_exists))
631 {
632 tem = Fexpand_file_name (build_string (".."), dir);
633 Vinstallation_directory = Ffile_name_as_directory (tem);
634 break;
635 }
636 }
637
638
639
640 tem = Ffile_symlink_p (name);
641 if (!NILP (tem))
642 {
643 name = Fexpand_file_name (tem, dir);
644 dir = Ffile_name_directory (name);
645 }
646 else
647 break;
648 }
649 }
650
651 Vcommand_line_args = Qnil;
652
653 for (i = argc - 1; i >= 0; i--)
654 {
655 if (i == 0 || i > skip_args)
656
657
658
659 Vcommand_line_args
660 = Fcons (build_unibyte_string (argv[i]), Vcommand_line_args);
661 }
662
663 unbind_to (count, Qnil);
664 }
665
666 DEFUN ("invocation-name", Finvocation_name, Sinvocation_name, 0, 0, 0,
667 doc:
668 )
669 (void)
670 {
671 return Fcopy_sequence (Vinvocation_name);
672 }
673
674 DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
675 0, 0, 0,
676 doc: )
677 (void)
678 {
679 return Fcopy_sequence (Vinvocation_directory);
680 }
681
682
683
684
685
686
687
688
689
690
691
692
693 static bool
694 argmatch (char **argv, int argc, const char *sstr, const char *lstr,
695 int minlen, char **valptr, int *skipptr)
696 {
697 char *p = NULL;
698 ptrdiff_t arglen;
699 char *arg;
700
701
702 if (argc <= *skipptr + 1)
703 return 0;
704
705 arg = argv[*skipptr+1];
706 if (arg == NULL)
707 return 0;
708 if (strcmp (arg, sstr) == 0)
709 {
710 if (valptr != NULL)
711 {
712 *valptr = argv[*skipptr+2];
713 *skipptr += 2;
714 }
715 else
716 *skipptr += 1;
717 return 1;
718 }
719 arglen = (valptr != NULL && (p = strchr (arg, '=')) != NULL
720 ? p - arg : strlen (arg));
721 if (!lstr)
722 return 0;
723 if (arglen < minlen || strncmp (arg, lstr, arglen) != 0)
724 return 0;
725 else if (valptr == NULL)
726 {
727 *skipptr += 1;
728 return 1;
729 }
730 else if (p != NULL)
731 {
732 *valptr = p+1;
733 *skipptr += 1;
734 return 1;
735 }
736 else if (argv[*skipptr+2] != NULL)
737 {
738 *valptr = argv[*skipptr+2];
739 *skipptr += 2;
740 return 1;
741 }
742 else
743 {
744 return 0;
745 }
746 }
747
748 #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
749
750
751
752
753
754
755
756
757 static char *
758 find_emacs_executable (char const *argv0, ptrdiff_t *candidate_size)
759 {
760 *candidate_size = 0;
761
762
763
764 #ifdef WINDOWSNT
765 char *prog_fname = w32_my_exename ();
766 if (prog_fname)
767 *candidate_size = strlen (prog_fname) + 1;
768 return prog_fname ? xstrdup (prog_fname) : NULL;
769 #else
770 char *candidate = NULL;
771
772
773
774 eassert (argv0);
775 if (strchr (argv0, DIRECTORY_SEP))
776 {
777 char *real_name = realpath (argv0, NULL);
778
779 if (real_name)
780 {
781 *candidate_size = strlen (real_name) + 1;
782 return real_name;
783 }
784
785 char *val = xstrdup (argv0);
786 *candidate_size = strlen (val) + 1;
787 return val;
788 }
789 ptrdiff_t argv0_length = strlen (argv0);
790
791 const char *path = getenv ("PATH");
792 if (!path)
793 {
794
795
796 return NULL;
797 }
798
799
800
801 do
802 {
803 static char const path_sep[] = { SEPCHAR, '\0' };
804 ptrdiff_t path_part_length = strcspn (path, path_sep);
805 const char *path_part = path;
806 path += path_part_length;
807 if (path_part_length == 0)
808 {
809 path_part = ".";
810 path_part_length = 1;
811 }
812 ptrdiff_t needed = path_part_length + 1 + argv0_length + 1;
813 if (*candidate_size <= needed)
814 {
815 xfree (candidate);
816 candidate = xpalloc (NULL, candidate_size,
817 needed - *candidate_size + 1, -1, 1);
818 }
819 memcpy (candidate + 0, path_part, path_part_length);
820 candidate[path_part_length] = DIRECTORY_SEP;
821 memcpy (candidate + path_part_length + 1, argv0, argv0_length + 1);
822 struct stat st;
823 if (file_access_p (candidate, X_OK)
824 && stat (candidate, &st) == 0 && S_ISREG (st.st_mode))
825 {
826
827
828
829 if (lstat (candidate, &st) == 0 && S_ISLNK (st.st_mode))
830 {
831 char *real_name = realpath (candidate, NULL);
832
833 if (real_name)
834 {
835 *candidate_size = strlen (real_name) + 1;
836 return real_name;
837 }
838 }
839 return candidate;
840 }
841 *candidate = '\0';
842 }
843 while (*path++ != '\0');
844
845 return candidate;
846 #endif
847 }
848
849 #endif
850
851 #ifdef HAVE_PDUMPER
852
853 static const char *
854 dump_error_to_string (int result)
855 {
856 switch (result)
857 {
858 case PDUMPER_LOAD_SUCCESS:
859 return "success";
860 case PDUMPER_LOAD_OOM:
861 return "out of memory";
862 case PDUMPER_NOT_LOADED:
863 return "not loaded";
864 case PDUMPER_LOAD_FILE_NOT_FOUND:
865 return "could not open file";
866 case PDUMPER_LOAD_BAD_FILE_TYPE:
867 return "not a dump file";
868 case PDUMPER_LOAD_FAILED_DUMP:
869 return "dump file is result of failed dump attempt";
870 case PDUMPER_LOAD_VERSION_MISMATCH:
871 return "not built for this Emacs executable";
872 default:
873 return (result <= PDUMPER_LOAD_ERROR
874 ? "generic error"
875 : strerror (result - PDUMPER_LOAD_ERROR));
876 }
877 }
878
879
880
881
882
883
884 static char *
885 load_pdump (int argc, char **argv, char *dump_file)
886 {
887 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
888 int skip_args = 0, result;
889
890 while (skip_args < argc - 1)
891 {
892 if (argmatch (argv, argc, "-dump-file", "--dump-file",
893 6, &dump_file, &skip_args)
894 || argmatch (argv, argc, "--", NULL, 2, NULL,
895 &skip_args))
896 break;
897 skip_args++;
898 }
899
900 if (!dump_file)
901 return argv[0];
902
903 result = pdumper_load (dump_file, argv[0]);
904
905 if (result != PDUMPER_LOAD_SUCCESS)
906 fatal ("could not load dump file \"%s\": %s",
907 dump_file, dump_error_to_string (result));
908 return argv[0];
909 #else
910
911 const char *const suffix = ".pdmp";
912 int result;
913 char *emacs_executable = argv[0];
914 ptrdiff_t hexbuf_size;
915 char *hexbuf;
916 const char *strip_suffix =
917 #if defined DOS_NT || defined CYGWIN
918 ".exe"
919 #else
920 NULL
921 #endif
922 ;
923 const char *argv0_base =
924 #ifdef NS_SELF_CONTAINED
925 "Emacs"
926 #else
927 "emacs"
928 #endif
929 ;
930
931
932
933
934
935
936 if (initialized)
937 fatal ("cannot load dump file in unexeced Emacs");
938
939
940 const char *path_exec = PATH_EXEC;
941 dump_file = NULL;
942 int skip_args = 0;
943 while (skip_args < argc - 1)
944 {
945 if (argmatch (argv, argc, "-dump-file", "--dump-file", 6,
946 &dump_file, &skip_args)
947 || argmatch (argv, argc, "--", NULL, 2, NULL, &skip_args))
948 break;
949 skip_args++;
950 }
951
952
953 ptrdiff_t exec_bufsize, bufsize, needed;
954 emacs_executable = find_emacs_executable (argv[0], &exec_bufsize);
955
956
957
958 if (!(emacs_executable && *emacs_executable))
959 {
960 bufsize = 0;
961 dump_file = NULL;
962 goto hardcoded;
963 }
964
965 if (dump_file)
966 {
967 result = pdumper_load (dump_file, emacs_executable);
968
969 if (result != PDUMPER_LOAD_SUCCESS)
970 fatal ("could not load dump file \"%s\": %s",
971 dump_file, dump_error_to_string (result));
972 return emacs_executable;
973 }
974
975
976
977
978
979
980
981 ptrdiff_t exenamelen = strlen (emacs_executable);
982 if (strip_suffix)
983 {
984 ptrdiff_t strip_suffix_length = strlen (strip_suffix);
985 ptrdiff_t prefix_length = exenamelen - strip_suffix_length;
986 if (0 <= prefix_length
987 && !memcmp (&emacs_executable[prefix_length], strip_suffix,
988 strip_suffix_length))
989 exenamelen = prefix_length;
990 }
991 bufsize = exenamelen + strlen (suffix) + 1;
992 dump_file = xpalloc (NULL, &bufsize, 1, -1, 1);
993 memcpy (dump_file, emacs_executable, exenamelen);
994 strcpy (dump_file + exenamelen, suffix);
995 result = pdumper_load (dump_file, emacs_executable);
996 if (result == PDUMPER_LOAD_SUCCESS)
997 goto out;
998
999 if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
1000 fatal ("could not load dump file \"%s\": %s",
1001 dump_file, dump_error_to_string (result));
1002
1003 hardcoded:
1004
1005 #ifdef WINDOWSNT
1006
1007
1008 path_exec = w32_relocate (path_exec);
1009 #elif defined (HAVE_NS)
1010 path_exec = ns_relocate (path_exec);
1011 #endif
1012
1013
1014
1015
1016 hexbuf_size = 2 * sizeof fingerprint;
1017 hexbuf = xmalloc (hexbuf_size + 1);
1018 hexbuf_digest (hexbuf, (char *) fingerprint, sizeof fingerprint);
1019 hexbuf[hexbuf_size] = '\0';
1020 needed = (strlen (path_exec)
1021 + 1
1022 + strlen (argv0_base)
1023 + 1
1024 + strlen (hexbuf)
1025 + strlen (suffix)
1026 + 1);
1027 if (bufsize < needed)
1028 {
1029 xfree (dump_file);
1030 dump_file = xpalloc (NULL, &bufsize, needed - bufsize, -1, 1);
1031 }
1032 sprintf (dump_file, "%s%c%s-%s%s",
1033 path_exec, DIRECTORY_SEP, argv0_base, hexbuf, suffix);
1034 #if !defined (NS_SELF_CONTAINED)
1035 if (!(emacs_executable && *emacs_executable))
1036 {
1037
1038
1039
1040 const char *go_up = "../../../../bin/";
1041 needed += (strip_suffix ? strlen (strip_suffix) : 0)
1042 - strlen (suffix) + strlen (go_up);
1043 if (exec_bufsize < needed)
1044 {
1045 xfree (emacs_executable);
1046 emacs_executable = xpalloc (NULL, &exec_bufsize,
1047 needed - exec_bufsize, -1, 1);
1048 }
1049 sprintf (emacs_executable, "%s%c%s%s%s",
1050 path_exec, DIRECTORY_SEP, go_up, argv0_base,
1051 strip_suffix ? strip_suffix : "");
1052 }
1053 #endif
1054 result = pdumper_load (dump_file, emacs_executable);
1055
1056 if (result == PDUMPER_LOAD_FILE_NOT_FOUND)
1057 {
1058
1059
1060
1061
1062 char *p, *last_sep = NULL;
1063 for (p = argv[0]; *p; p++)
1064 {
1065 if (IS_DIRECTORY_SEP (*p))
1066 last_sep = p;
1067 }
1068 argv0_base = last_sep ? last_sep + 1 : argv[0];
1069 ptrdiff_t needed = (strlen (path_exec)
1070 + 1
1071 + strlen (argv0_base)
1072 + strlen (suffix)
1073 + 1);
1074 if (bufsize < needed)
1075 {
1076 xfree (dump_file);
1077 dump_file = xmalloc (needed);
1078 }
1079 #ifdef DOS_NT
1080 ptrdiff_t argv0_len = strlen (argv0_base);
1081 if (argv0_len >= 4
1082 && c_strcasecmp (argv0_base + argv0_len - 4, ".exe") == 0)
1083 sprintf (dump_file, "%s%c%.*s%s", path_exec, DIRECTORY_SEP,
1084 (int)(argv0_len - 4), argv0_base, suffix);
1085 else
1086 #endif
1087 sprintf (dump_file, "%s%c%s%s",
1088 path_exec, DIRECTORY_SEP, argv0_base, suffix);
1089 result = pdumper_load (dump_file, emacs_executable);
1090 }
1091
1092 if (result != PDUMPER_LOAD_SUCCESS)
1093 {
1094 if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
1095 fatal ("could not load dump file \"%s\": %s",
1096 dump_file, dump_error_to_string (result));
1097 }
1098
1099 out:
1100 xfree (dump_file);
1101
1102 return emacs_executable;
1103 #endif
1104 }
1105 #endif
1106
1107 #if SECCOMP_USABLE
1108
1109
1110
1111
1112
1113 static int
1114 emacs_seccomp (unsigned int operation, unsigned int flags, void *args)
1115 {
1116 #ifdef SYS_seccomp
1117 return syscall (SYS_seccomp, operation, flags, args);
1118 #else
1119 errno = ENOSYS;
1120 return -1;
1121 #endif
1122 }
1123
1124
1125
1126
1127 static ptrdiff_t
1128 read_full (int fd, void *buffer, ptrdiff_t size)
1129 {
1130 eassert (0 <= fd);
1131 eassert (buffer != NULL);
1132 eassert (0 <= size);
1133 enum
1134 {
1135
1136 #ifdef MAX_RW_COUNT
1137 max_size = MAX_RW_COUNT
1138 #else
1139 max_size = INT_MAX >> 18 << 18
1140 #endif
1141 };
1142 if (PTRDIFF_MAX < size || max_size < size)
1143 {
1144 errno = EFBIG;
1145 return -1;
1146 }
1147 char *ptr = buffer;
1148 ptrdiff_t read = 0;
1149 while (size != 0)
1150 {
1151 ptrdiff_t n = emacs_read (fd, ptr, size);
1152 if (n < 0)
1153 return -1;
1154 if (n == 0)
1155 break;
1156 eassert (n <= size);
1157 size -= n;
1158 ptr += n;
1159 read += n;
1160 }
1161 return read;
1162 }
1163
1164
1165
1166
1167 static bool
1168 load_seccomp (const char *file)
1169 {
1170 bool success = false;
1171 void *buffer = NULL;
1172 int fd
1173 = emacs_open_noquit (file, O_RDONLY | O_CLOEXEC | O_BINARY, 0);
1174 if (fd < 0)
1175 {
1176 emacs_perror ("open");
1177 goto out;
1178 }
1179 struct stat stat;
1180 if (sys_fstat (fd, &stat) != 0)
1181 {
1182 emacs_perror ("fstat");
1183 goto out;
1184 }
1185 if (! S_ISREG (stat.st_mode))
1186 {
1187 fprintf (stderr, "seccomp file %s is not regular\n", file);
1188 goto out;
1189 }
1190 struct sock_fprog program;
1191 if (stat.st_size <= 0 || SIZE_MAX <= stat.st_size
1192 || PTRDIFF_MAX <= stat.st_size
1193 || stat.st_size % sizeof *program.filter != 0)
1194 {
1195 fprintf (stderr, "seccomp filter %s has invalid size %ld\n",
1196 file, (long) stat.st_size);
1197 goto out;
1198 }
1199 size_t size = stat.st_size;
1200 size_t count = size / sizeof *program.filter;
1201 eassert (0 < count && count < SIZE_MAX);
1202 if (USHRT_MAX < count)
1203 {
1204 fprintf (stderr, "seccomp filter %s is too big\n", file);
1205 goto out;
1206 }
1207
1208 buffer = malloc (size + 1);
1209 if (buffer == NULL)
1210 {
1211 emacs_perror ("malloc");
1212 goto out;
1213 }
1214 ptrdiff_t read = read_full (fd, buffer, size + 1);
1215 if (read < 0)
1216 {
1217 emacs_perror ("read");
1218 goto out;
1219 }
1220 eassert (read <= SIZE_MAX);
1221 if (read != size)
1222 {
1223 fprintf (stderr,
1224 "seccomp filter %s changed size while reading\n",
1225 file);
1226 goto out;
1227 }
1228 if (emacs_close (fd) != 0)
1229 emacs_perror ("close");
1230 fd = -1;
1231 program.len = count;
1232 program.filter = buffer;
1233
1234
1235
1236
1237
1238
1239 prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1240
1241
1242 if (emacs_seccomp (SECCOMP_SET_MODE_FILTER,
1243 SECCOMP_FILTER_FLAG_TSYNC, &program)
1244 != 0)
1245 {
1246 emacs_perror ("seccomp");
1247 goto out;
1248 }
1249 success = true;
1250
1251 out:
1252 if (0 <= fd)
1253 emacs_close (fd);
1254 free (buffer);
1255 return success;
1256 }
1257
1258
1259
1260
1261 static void
1262 maybe_load_seccomp (int argc, char **argv)
1263 {
1264 int skip_args = 0;
1265 char *file = NULL;
1266 while (skip_args < argc - 1)
1267 {
1268 if (argmatch (argv, argc, "-seccomp", "--seccomp", 9, &file,
1269 &skip_args)
1270 || argmatch (argv, argc, "--", NULL, 2, NULL, &skip_args))
1271 break;
1272 ++skip_args;
1273 }
1274 if (file == NULL)
1275 return;
1276 if (! load_seccomp (file))
1277 fatal ("cannot enable seccomp filter from %s", file);
1278 }
1279
1280 #endif
1281
1282 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
1283 int
1284 android_emacs_init (int argc, char **argv, char *dump_file)
1285 #else
1286 int
1287 main (int argc, char **argv)
1288 #endif
1289 {
1290
1291
1292 void *stack_bottom_variable;
1293 int old_argc;
1294 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
1295 char *dump_file;
1296
1297
1298 dump_file = NULL;
1299 #endif
1300
1301
1302
1303
1304 #if SECCOMP_USABLE
1305 maybe_load_seccomp (argc, argv);
1306 #endif
1307
1308 bool no_loadup = false;
1309 char *junk = 0;
1310 char *dname_arg = 0;
1311 #ifdef DAEMON_MUST_EXEC
1312 char dname_arg2[80];
1313 #endif
1314 char *ch_to_dir = 0;
1315
1316
1317 char const *original_pwd = 0;
1318
1319
1320 stack_bottom = (char *) &stack_bottom_variable;
1321
1322 const char *dump_mode = NULL;
1323 int skip_args = 0;
1324 char *temacs = NULL;
1325 while (skip_args < argc - 1)
1326 {
1327 if (argmatch (argv, argc, "-temacs", "--temacs", 8, &temacs, &skip_args)
1328 || argmatch (argv, argc, "--", NULL, 2, NULL, &skip_args))
1329 break;
1330 skip_args++;
1331 }
1332 #ifdef HAVE_PDUMPER
1333 bool attempt_load_pdump = false;
1334 #endif
1335
1336
1337
1338 if (!initialized && temacs)
1339 {
1340 #ifdef HAVE_UNEXEC
1341 if (strcmp (temacs, "dump") == 0 ||
1342 strcmp (temacs, "bootstrap") == 0)
1343 gflags.will_dump_with_unexec_ = true;
1344 #endif
1345 #ifdef HAVE_PDUMPER
1346 if (strcmp (temacs, "pdump") == 0 ||
1347 strcmp (temacs, "pbootstrap") == 0)
1348 gflags.will_dump_with_pdumper_ = true;
1349 #endif
1350 #if defined HAVE_PDUMPER || defined HAVE_UNEXEC
1351 if (strcmp (temacs, "bootstrap") == 0 ||
1352 strcmp (temacs, "pbootstrap") == 0)
1353 gflags.will_bootstrap_ = true;
1354 gflags.will_dump_ =
1355 will_dump_with_pdumper_p () ||
1356 will_dump_with_unexec_p ();
1357 if (will_dump_p ())
1358 dump_mode = temacs;
1359 #endif
1360 if (!dump_mode)
1361 fatal ("Invalid temacs mode '%s'", temacs);
1362 }
1363 else if (temacs)
1364 {
1365 fatal ("--temacs not supported for unexeced emacs");
1366 }
1367 else
1368 {
1369 eassert (!temacs);
1370 #ifndef HAVE_UNEXEC
1371 eassert (!initialized);
1372 #endif
1373 #ifdef HAVE_PDUMPER
1374 if (!initialized)
1375 attempt_load_pdump = true;
1376 #endif
1377 }
1378
1379 #ifdef HAVE_UNEXEC
1380 if (!will_dump_with_unexec_p ())
1381 gflags.will_not_unexec_ = true;
1382 #endif
1383
1384 #ifdef WINDOWSNT
1385
1386
1387
1388 bool use_dynamic_heap = true;
1389 if (temacs)
1390 {
1391 char *temacs_str = NULL, *p;
1392 for (p = argv[0]; (p = strstr (p, "temacs")) != NULL; p++)
1393 temacs_str = p;
1394 if (temacs_str != NULL
1395 && (temacs_str == argv[0] || IS_DIRECTORY_SEP (temacs_str[-1])))
1396 {
1397
1398
1399
1400
1401
1402 use_dynamic_heap = will_dump_with_pdumper_p ();
1403 }
1404 }
1405 init_heap (use_dynamic_heap);
1406 initial_cmdline = GetCommandLine ();
1407 #endif
1408 #if defined WINDOWSNT || defined HAVE_NTGUI
1409
1410
1411
1412 cache_system_info ();
1413 #ifdef WINDOWSNT
1414
1415
1416
1417 maybe_load_unicows_dll ();
1418
1419
1420 w32_init_file_name_codepage ();
1421
1422 w32_init_current_directory ();
1423 #endif
1424 w32_init_main_thread ();
1425 #endif
1426
1427 #ifdef HAVE_PDUMPER
1428 if (attempt_load_pdump)
1429 initial_emacs_executable = load_pdump (argc, argv, dump_file);
1430 #else
1431 ptrdiff_t bufsize;
1432 initial_emacs_executable = find_emacs_executable (argv[0], &bufsize);
1433 #endif
1434
1435 argc = maybe_disable_address_randomization (argc, argv);
1436
1437 #if defined GNU_LINUX && defined HAVE_UNEXEC
1438 if (!initialized)
1439 {
1440 char *heap_start = my_heap_start ();
1441 heap_bss_diff = heap_start - max (my_endbss, my_endbss_static);
1442 }
1443 #endif
1444
1445 #ifdef RUN_TIME_REMAP
1446 if (initialized)
1447 run_time_remap (argv[0]);
1448 #endif
1449
1450
1451 #if defined DARWIN_OS && defined HAVE_UNEXEC
1452 if (!initialized)
1453 unexec_init_emacs_zone ();
1454 #endif
1455
1456 init_standard_fds ();
1457 atexit (close_output_streams);
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492 bool only_version = false;
1493 sort_args (argc, argv);
1494 old_argc = argc, argc = 0;
1495
1496 while (argc < old_argc && argv[argc]) argc++;
1497
1498 skip_args = 0;
1499 if (argmatch (argv, argc, "-version", "--version", 3, NULL, &skip_args))
1500 only_version = true;
1501
1502 #ifdef HAVE_PDUMPER
1503 if (argmatch (argv, argc, "-fingerprint", "--fingerprint", 4,
1504 NULL, &skip_args)
1505 && !only_version)
1506 {
1507 if (initialized)
1508 {
1509 dump_fingerprint (stdout, "",
1510 (unsigned char *) fingerprint);
1511 exit (0);
1512 }
1513 else
1514 {
1515 fputs ("Not initialized\n", stderr);
1516 exit (1);
1517 }
1518 }
1519 #endif
1520
1521 emacs_wd = emacs_get_current_dir_name ();
1522 #ifdef WINDOWSNT
1523 initial_wd = emacs_wd;
1524 #endif
1525 #ifdef HAVE_PDUMPER
1526 if (dumped_with_pdumper_p ())
1527 pdumper_record_wd (emacs_wd);
1528 #endif
1529
1530 if (argmatch (argv, argc, "-chdir", "--chdir", 4, &ch_to_dir, &skip_args)
1531 && !only_version)
1532 {
1533 #ifdef WINDOWSNT
1534
1535
1536 char newdir[MAX_UTF8_PATH];
1537
1538 filename_from_ansi (ch_to_dir, newdir);
1539 ch_to_dir = newdir;
1540 #endif
1541 if (chdir (ch_to_dir) != 0)
1542 {
1543 fprintf (stderr, "%s: Can't chdir to %s: %s\n",
1544 argv[0], ch_to_dir, strerror (errno));
1545 exit (1);
1546 }
1547 original_pwd = emacs_wd;
1548 #ifdef WINDOWSNT
1549
1550 w32_init_current_directory ();
1551 #endif
1552 emacs_wd = emacs_get_current_dir_name ();
1553 }
1554
1555 #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK) && !defined (CYGWIN)
1556
1557
1558
1559
1560
1561
1562 struct rlimit rlim;
1563 if (getrlimit (RLIMIT_STACK, &rlim) == 0
1564 && 0 <= rlim.rlim_cur && rlim.rlim_cur <= LONG_MAX)
1565 {
1566 rlim_t lim = rlim.rlim_cur;
1567
1568
1569
1570
1571
1572 int min_ratio = 20 * sizeof (char *);
1573 int ratio = min_ratio + min_ratio / 3;
1574
1575
1576
1577
1578 int extra = (30 * 1000) * 50;
1579
1580 bool try_to_grow_stack = !noninteractive || initialized;
1581
1582 if (try_to_grow_stack)
1583 {
1584 rlim_t newlim = emacs_re_max_failures * ratio + extra;
1585
1586
1587
1588
1589
1590
1591
1592
1593 long pagesize = getpagesize ();
1594 newlim += pagesize - 1;
1595 if (0 <= rlim.rlim_max && rlim.rlim_max < newlim)
1596 newlim = rlim.rlim_max;
1597 newlim -= newlim % pagesize;
1598
1599 if (newlim > lim
1600 && pagesize <= newlim - lim)
1601 {
1602 rlim.rlim_cur = newlim;
1603 if (setrlimit (RLIMIT_STACK, &rlim) == 0)
1604 lim = newlim;
1605 }
1606 }
1607
1608
1609 if (lim < extra)
1610 lim = extra;
1611 ptrdiff_t max_failures
1612 = min (lim - extra, min (PTRDIFF_MAX, SIZE_MAX)) / ratio;
1613 emacs_re_safe_alloca = max (max_failures * min_ratio, MAX_ALLOCA);
1614 }
1615 #endif
1616
1617 clearerr (stdin);
1618
1619 emacs_backtrace (-1);
1620
1621 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
1622
1623 memory_warnings (0, malloc_warning);
1624
1625
1626
1627 free (realloc (malloc (4), 4));
1628
1629 #endif
1630
1631 #ifdef MSDOS
1632 set_binary_mode (STDIN_FILENO, O_BINARY);
1633 fflush (stdout);
1634 set_binary_mode (STDOUT_FILENO, O_BINARY);
1635 #endif
1636
1637
1638
1639
1640
1641
1642 char *lc_all = getenv ("LC_ALL");
1643 if (! (lc_all && strcmp (lc_all, "C") == 0))
1644 {
1645 #ifdef HAVE_NS
1646 ns_pool = ns_alloc_autorelease_pool ();
1647 ns_init_locale ();
1648 #endif
1649 setlocale (LC_ALL, "");
1650 fixup_locale ();
1651 }
1652 text_quoting_flag = using_utf8 ();
1653
1654 inhibit_window_system = 0;
1655
1656
1657 while (!only_version)
1658 {
1659 char *term;
1660 if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args))
1661 {
1662 emacs_close (STDIN_FILENO);
1663 emacs_close (STDOUT_FILENO);
1664 int result = emacs_open_noquit (term, O_RDWR, 0);
1665 if (result != STDIN_FILENO
1666 || (fcntl (STDIN_FILENO, F_DUPFD_CLOEXEC, STDOUT_FILENO)
1667 != STDOUT_FILENO))
1668 {
1669 const char *errstring = strerror (errno);
1670 fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring);
1671 exit (EXIT_FAILURE);
1672 }
1673 if (! isatty (STDIN_FILENO))
1674 {
1675 fprintf (stderr, "%s: %s: not a tty\n", argv[0], term);
1676 exit (EXIT_FAILURE);
1677 }
1678 fprintf (stderr, "Using %s\n", term);
1679 #ifdef HAVE_WINDOW_SYSTEM
1680 inhibit_window_system = true;
1681 #endif
1682 }
1683 else
1684 break;
1685 }
1686
1687
1688
1689 if (argmatch (argv, argc, "-nw", "--no-window-system", 6, NULL, &skip_args)
1690 || argmatch (argv, argc, "-nw", "--no-windows", 6, NULL, &skip_args))
1691 inhibit_window_system = 1;
1692
1693
1694 noninteractive = 0;
1695 if (argmatch (argv, argc, "-batch", "--batch", 5, NULL, &skip_args)
1696 || only_version)
1697 {
1698 noninteractive = 1;
1699 Vundo_outer_limit = Qnil;
1700 }
1701 if (argmatch (argv, argc, "-script", "--script", 3, &junk, &skip_args))
1702 {
1703 noninteractive = 1;
1704
1705
1706
1707 argv[skip_args - 1] = (char *) "-scriptload";
1708 skip_args -= 2;
1709 sort_args (argc, argv);
1710 }
1711
1712
1713 if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args)
1714 && !only_version)
1715 {
1716 int i;
1717 printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
1718 for (i = 0; i < ARRAYELTS (usage_message); i++)
1719 fputs (usage_message[i], stdout);
1720 exit (0);
1721 }
1722
1723 daemon_type = 0;
1724
1725 #ifndef WINDOWSNT
1726
1727 daemon_pipe[1] = 0;
1728 #else
1729 w32_daemon_event = NULL;
1730 #endif
1731
1732
1733 int sockfd = -1;
1734
1735 if (!only_version)
1736 {
1737 if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL,
1738 &skip_args)
1739 || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg,
1740 &skip_args))
1741 {
1742 daemon_type = 1;
1743 }
1744 else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
1745 || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg,
1746 &skip_args)
1747 || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL,
1748 &skip_args)
1749 || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10,
1750 &dname_arg, &skip_args))
1751 {
1752 daemon_type = 2;
1753 }
1754 }
1755
1756 if (daemon_type > 0)
1757 {
1758 #ifndef DOS_NT
1759 if (daemon_type == 2)
1760 {
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782 if (emacs_pipe (daemon_pipe) != 0)
1783 {
1784 fputs ("Cannot pipe!\n", stderr);
1785 exit (1);
1786 }
1787 }
1788
1789 #ifdef HAVE_LIBSYSTEMD
1790
1791 int systemd_socket = sd_listen_fds (1);
1792
1793 if (systemd_socket > 1)
1794 fputs (("\n"
1795 "Warning: systemd passed more than one socket to Emacs.\n"
1796 "Try 'Accept=false' in the Emacs socket unit file.\n"),
1797 stderr);
1798 else if (systemd_socket == 1
1799 && (0 < sd_is_socket (SD_LISTEN_FDS_START,
1800 AF_UNSPEC, SOCK_STREAM, 1)))
1801 sockfd = SD_LISTEN_FDS_START;
1802 #endif
1803
1804
1805
1806
1807
1808
1809
1810
1811 #ifdef HAVE_PGTK
1812 fputs ("Due to a limitation in GTK 3, Emacs built with PGTK will simply exit when a\n"
1813 "display connection is closed. The problem is especially difficult to fix,\n"
1814 "such that Emacs on Wayland with multiple displays is unlikely ever to be able\n"
1815 "to survive disconnects.\n",
1816 stderr);
1817 #elif defined USE_GTK
1818 fputs ("\nWarning: due to a long standing Gtk+ bug\nhttps://gitlab.gnome.org/GNOME/gtk/issues/221\n\
1819 Emacs might crash when run in daemon mode and the X11 connection is unexpectedly lost.\n\
1820 Using an Emacs configured with --with-x-toolkit=lucid does not have this problem.\n",
1821 stderr);
1822 #endif
1823
1824 if (daemon_type == 2)
1825 {
1826 pid_t f;
1827 #ifndef DAEMON_MUST_EXEC
1828
1829 f = fork ();
1830 #else
1831 if (!dname_arg || !strchr (dname_arg, '\n'))
1832 f = fork ();
1833 else
1834 f = 0;
1835 #endif
1836 if (f > 0)
1837 {
1838 int retval;
1839 char buf[1];
1840
1841
1842 emacs_close (daemon_pipe[1]);
1843
1844
1845 do
1846 {
1847 retval = read (daemon_pipe[0], &buf, 1);
1848 }
1849 while (retval == -1 && errno == EINTR);
1850
1851 if (retval < 0)
1852 {
1853 fputs ("Error reading status from child\n", stderr);
1854 exit (1);
1855 }
1856 else if (retval == 0)
1857 {
1858 fputs ("Error: server did not start correctly\n", stderr);
1859 exit (1);
1860 }
1861
1862 emacs_close (daemon_pipe[0]);
1863 exit (0);
1864 }
1865 if (f < 0)
1866 {
1867 emacs_perror ("fork");
1868 exit (EXIT_CANCELED);
1869 }
1870
1871 #ifdef DAEMON_MUST_EXEC
1872 {
1873
1874 if (!dname_arg || !strchr (dname_arg, '\n'))
1875 {
1876 char fdStr[80];
1877 int fdStrlen =
1878 snprintf (fdStr, sizeof fdStr,
1879 "--bg-daemon=\n%d,%d\n%s", daemon_pipe[0],
1880 daemon_pipe[1], dname_arg ? dname_arg : "");
1881
1882 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr))
1883 {
1884 fputs ("daemon: child name too long\n", stderr);
1885 exit (EXIT_CANNOT_INVOKE);
1886 }
1887
1888 argv[skip_args] = fdStr;
1889
1890 fcntl (daemon_pipe[0], F_SETFD, 0);
1891 fcntl (daemon_pipe[1], F_SETFD, 0);
1892 execvp (argv[0], argv);
1893 emacs_perror (argv[0]);
1894 exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1895 }
1896
1897
1898 if (!dname_arg || !*dname_arg || strnlen (dname_arg, 71) == 71
1899 || !strchr (dname_arg, '\n'))
1900 {
1901 fputs ("emacs daemon: daemon name absent or too long\n",
1902 stderr);
1903 exit (EXIT_CANNOT_INVOKE);
1904 }
1905 dname_arg2[0] = '\0';
1906 sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]),
1907 dname_arg2);
1908 dname_arg = *dname_arg2 ? dname_arg2 : NULL;
1909 fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC);
1910 }
1911 #endif
1912
1913
1914 emacs_close (daemon_pipe[0]);
1915
1916 setsid ();
1917 }
1918 #elif defined(WINDOWSNT)
1919
1920 w32_daemon_event = CreateEvent (NULL, TRUE, FALSE, W32_DAEMON_EVENT);
1921 if (w32_daemon_event == NULL)
1922 {
1923 fprintf (stderr, "Couldn't create MS-Windows event for daemon: %s\n",
1924 w32_strerror (0));
1925 exit (1);
1926 }
1927 #else
1928 fputs ("This platform does not support daemon mode.\n", stderr);
1929 exit (1);
1930 #endif
1931 if (dname_arg)
1932 daemon_name = xstrdup (dname_arg);
1933 }
1934
1935 #if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC \
1936 && !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC
1937
1938
1939
1940
1941 if (!noninteractive || !will_dump_p ())
1942 malloc_enable_thread ();
1943 #endif
1944
1945 init_signals ();
1946
1947 noninteractive1 = noninteractive;
1948
1949
1950
1951 if (!initialized)
1952 {
1953 init_alloc_once ();
1954 init_pdumper_once ();
1955 init_obarray_once ();
1956 init_eval_once ();
1957 init_charset_once ();
1958 init_coding_once ();
1959 init_syntax_once ();
1960 init_category_once ();
1961 init_casetab_once ();
1962 init_buffer_once ();
1963 init_minibuf_once ();
1964
1965
1966
1967
1968
1969
1970 syms_of_xfaces ();
1971
1972
1973 syms_of_keymap ();
1974
1975
1976
1977
1978 syms_of_keyboard ();
1979
1980
1981 syms_of_data ();
1982 syms_of_fns ();
1983 syms_of_fileio ();
1984
1985 syms_of_alloc ();
1986
1987 init_print_once ();
1988
1989 syms_of_charset ();
1990
1991
1992 syms_of_coding ();
1993 init_frame_once ();
1994
1995
1996
1997
1998
1999 init_bignum ();
2000 init_window_once ();
2001 #ifdef HAVE_WINDOW_SYSTEM
2002 init_fringe_once ();
2003 #endif
2004 #ifdef HAVE_TEXT_CONVERSION
2005 syms_of_textconv ();
2006 #endif
2007 }
2008
2009 init_alloc ();
2010 init_bignum ();
2011 init_threads ();
2012 init_eval ();
2013 running_asynch_code = 0;
2014 init_random ();
2015 init_xfaces ();
2016
2017 #if defined HAVE_JSON && !defined WINDOWSNT
2018 init_json ();
2019 #endif
2020
2021 if (!initialized)
2022 syms_of_comp ();
2023
2024
2025
2026
2027 Vgc_cons_percentage = make_float (noninteractive && initialized ? 1.0 : 0.1);
2028
2029 no_loadup
2030 = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args);
2031
2032 no_site_lisp
2033 = argmatch (argv, argc, "-nsl", "--no-site-lisp", 11, NULL, &skip_args);
2034
2035 build_details = ! argmatch (argv, argc, "-no-build-details",
2036 "--no-build-details", 7, NULL, &skip_args);
2037
2038 #ifdef HAVE_MODULES
2039 bool module_assertions
2040 = argmatch (argv, argc, "-module-assertions", "--module-assertions", 15,
2041 NULL, &skip_args);
2042 if (will_dump_p () && module_assertions && !only_version)
2043 {
2044 fputs ("Module assertions are not supported during dumping\n", stderr);
2045 exit (1);
2046 }
2047 init_module_assertions (module_assertions);
2048 #endif
2049
2050 #ifdef HAVE_NS
2051 if (!noninteractive)
2052 {
2053 #ifdef NS_IMPL_COCOA
2054
2055 bool go_home = (!ch_to_dir && !inhibit_window_system
2056 && !isatty (STDIN_FILENO));
2057 if (skip_args < argc)
2058 {
2059 if (!strncmp (argv[skip_args], "-psn", 4))
2060 {
2061 skip_args += 1;
2062 go_home |= !ch_to_dir;
2063 }
2064 else if (skip_args+1 < argc && !strncmp (argv[skip_args+1], "-psn", 4))
2065 {
2066 skip_args += 2;
2067 go_home |= !ch_to_dir;
2068 }
2069 }
2070 if (go_home)
2071 {
2072 char const *home = get_homedir ();
2073 if (*home && chdir (home) == 0)
2074 emacs_wd = emacs_get_current_dir_name ();
2075 }
2076 #endif
2077 }
2078 #endif
2079
2080 #ifdef HAVE_X_WINDOWS
2081
2082
2083
2084
2085 {
2086 char *displayname = 0;
2087 int count_before = skip_args;
2088
2089
2090 while (!only_version)
2091 {
2092 int count_before_this = skip_args;
2093
2094 if (argmatch (argv, argc, "-d", "--display", 3, &displayname, &skip_args))
2095 display_arg = 1;
2096 else if (argmatch (argv, argc, "-display", 0, 3, &displayname, &skip_args))
2097 display_arg = 1;
2098 else
2099 break;
2100
2101 count_before = count_before_this;
2102 }
2103
2104
2105
2106
2107 if (displayname && count_before < skip_args)
2108 {
2109 if (skip_args == count_before + 1)
2110 {
2111 memmove (argv + count_before + 3, argv + count_before + 2,
2112 (argc - (count_before + 2)) * sizeof *argv);
2113 argv[count_before + 2] = displayname;
2114 argc++;
2115 }
2116 argv[count_before + 1] = (char *) "-d";
2117 }
2118
2119 if (! no_site_lisp)
2120 {
2121 if (argmatch (argv, argc, "-Q", "--quick", 3, NULL, &skip_args)
2122 || argmatch (argv, argc, "-quick", 0, 2, NULL, &skip_args))
2123 no_site_lisp = 1;
2124 }
2125
2126 if (argmatch (argv, argc, "-x", 0, 1, &junk, &skip_args))
2127 {
2128 noninteractive = 1;
2129 no_site_lisp = 1;
2130
2131 argv[skip_args - 1] = (char *) "-scripteval";
2132 skip_args -= 1;
2133 sort_args (argc, argv);
2134 }
2135
2136
2137 skip_args = count_before;
2138 }
2139 #else
2140 if (! no_site_lisp)
2141 {
2142 int count_before = skip_args;
2143
2144 if (argmatch (argv, argc, "-Q", "--quick", 3, NULL, &skip_args)
2145 || argmatch (argv, argc, "-quick", 0, 2, NULL, &skip_args))
2146 no_site_lisp = 1;
2147
2148 skip_args = count_before;
2149 }
2150 #endif
2151
2152
2153
2154
2155
2156 #ifdef MSDOS
2157
2158 init_dosfns ();
2159
2160 if (initialized)
2161 init_environment (argc, argv, skip_args);
2162 else
2163 tzset ();
2164 #endif
2165
2166 #ifdef HAVE_KQUEUE
2167 globals_of_kqueue ();
2168 #endif
2169
2170 #ifdef HAVE_GFILENOTIFY
2171 globals_of_gfilenotify ();
2172 #endif
2173
2174
2175
2176
2177 if (!initialized)
2178 syms_of_callproc ();
2179
2180
2181
2182 if (!will_dump_p ())
2183 set_initial_environment ();
2184
2185
2186 init_atimer ();
2187
2188 #ifdef WINDOWSNT
2189 globals_of_w32 ();
2190 #ifdef HAVE_W32NOTIFY
2191 globals_of_w32notify ();
2192 #endif
2193
2194
2195
2196
2197
2198 init_environment (argv);
2199 init_ntproc (will_dump_p ());
2200 #endif
2201
2202
2203
2204
2205
2206 #ifdef AIX
2207 xputenv ("LANG=C");
2208 #endif
2209
2210
2211 init_buffer ();
2212
2213
2214 init_callproc_1 ();
2215
2216
2217 init_cmdargs (argc, argv, skip_args, original_pwd);
2218
2219 if (initialized)
2220 {
2221
2222 Lisp_Object old_log_max;
2223 old_log_max = Vmessage_log_max;
2224 XSETFASTINT (Vmessage_log_max, 0);
2225 message_dolog ("", 0, 1, 0);
2226 Vmessage_log_max = old_log_max;
2227 }
2228
2229 init_callproc ();
2230 init_fileio ();
2231 init_lread ();
2232
2233
2234
2235
2236
2237 if (only_version)
2238 {
2239 const char *version, *copyright;
2240
2241 if (initialized)
2242 {
2243 Lisp_Object tem = Fsymbol_value (intern_c_string ("emacs-version"));
2244 Lisp_Object tem2 = Fsymbol_value (intern_c_string ("emacs-copyright"));
2245 if (!STRINGP (tem))
2246 {
2247 fputs ("Invalid value of 'emacs-version'\n", stderr);
2248 exit (1);
2249 }
2250 if (!STRINGP (tem2))
2251 {
2252 fputs ("Invalid value of 'emacs-copyright'\n", stderr);
2253 exit (1);
2254 }
2255 else
2256 {
2257 version = SSDATA (tem);
2258 copyright = SSDATA (tem2);
2259 }
2260 }
2261 else
2262 {
2263 version = emacs_version;
2264 copyright = emacs_copyright;
2265 }
2266 printf ("%s %s\n", PACKAGE_NAME, version);
2267
2268 if (initialized)
2269 {
2270 Lisp_Object rversion, rbranch, rtime;
2271
2272 rversion
2273 = Fsymbol_value (intern_c_string ("emacs-repository-version"));
2274 rbranch
2275 = Fsymbol_value (intern_c_string ("emacs-repository-branch"));
2276 rtime
2277 = Fsymbol_value (intern_c_string ("emacs-build-time"));
2278
2279 if (!NILP (rversion) && !NILP (rbranch) && !NILP (rtime))
2280 printf ("Development version %s on %s branch; build date %s.\n",
2281 SSDATA (Fsubstring (rversion, make_fixnum (0),
2282 make_fixnum (12))),
2283 SSDATA (rbranch),
2284 SSDATA (Fformat_time_string (build_string ("%Y-%m-%d"),
2285 rtime, Qnil)));
2286 }
2287
2288 printf (("%s\n"
2289 "%s comes with ABSOLUTELY NO WARRANTY.\n"
2290 "You may redistribute copies of %s\n"
2291 "under the terms of the GNU General Public License.\n"
2292 "For more information about these matters, "
2293 "see the file named COPYING.\n"),
2294 copyright, PACKAGE_NAME, PACKAGE_NAME);
2295 exit (0);
2296 }
2297
2298 #ifdef WINDOWSNT
2299
2300 check_windows_init_file ();
2301 #endif
2302
2303
2304
2305
2306 if (!initialized)
2307 {
2308
2309
2310 syms_of_chartab ();
2311 syms_of_lread ();
2312 syms_of_print ();
2313 syms_of_eval ();
2314 syms_of_floatfns ();
2315
2316 syms_of_buffer ();
2317 syms_of_bytecode ();
2318 syms_of_callint ();
2319 syms_of_casefiddle ();
2320 syms_of_casetab ();
2321 syms_of_category ();
2322 syms_of_ccl ();
2323 syms_of_character ();
2324 syms_of_cmds ();
2325 syms_of_dired ();
2326 syms_of_display ();
2327 syms_of_doc ();
2328 syms_of_editfns ();
2329 syms_of_emacs ();
2330 syms_of_filelock ();
2331 syms_of_indent ();
2332 syms_of_insdel ();
2333
2334 syms_of_macros ();
2335 syms_of_marker ();
2336 syms_of_minibuf ();
2337 syms_of_process ();
2338 syms_of_search ();
2339 syms_of_sysdep ();
2340 syms_of_timefns ();
2341 syms_of_frame ();
2342 syms_of_syntax ();
2343 syms_of_terminal ();
2344 syms_of_term ();
2345 syms_of_undo ();
2346
2347 #ifdef HAVE_MODULES
2348 syms_of_module ();
2349 #endif
2350
2351
2352 syms_of_treesit ();
2353 #ifdef HAVE_SOUND
2354 syms_of_sound ();
2355 #endif
2356 syms_of_textprop ();
2357 syms_of_composite ();
2358 #ifdef WINDOWSNT
2359 syms_of_ntproc ();
2360 #endif
2361 #if defined CYGWIN
2362 syms_of_cygw32 ();
2363 #endif
2364 syms_of_window ();
2365 syms_of_xdisp ();
2366 syms_of_sqlite ();
2367 syms_of_font ();
2368 #ifdef HAVE_WINDOW_SYSTEM
2369 syms_of_fringe ();
2370 syms_of_image ();
2371 #endif
2372 #ifdef HAVE_X_WINDOWS
2373 syms_of_xterm ();
2374 syms_of_xfns ();
2375 syms_of_xmenu ();
2376 syms_of_fontset ();
2377 syms_of_xsettings ();
2378 #ifdef HAVE_X_SM
2379 syms_of_xsmfns ();
2380 #endif
2381 #ifdef HAVE_X11
2382 syms_of_xselect ();
2383 #endif
2384 #endif
2385
2386 syms_of_xml ();
2387
2388 #ifdef HAVE_LCMS2
2389 syms_of_lcms2 ();
2390 #endif
2391
2392 #ifdef HAVE_ZLIB
2393 syms_of_decompress ();
2394 #endif
2395
2396 syms_of_menu ();
2397
2398 #ifdef HAVE_NTGUI
2399 syms_of_w32term ();
2400 syms_of_w32fns ();
2401 syms_of_w32menu ();
2402 syms_of_fontset ();
2403 #endif
2404
2405 #if defined HAVE_NTGUI || defined CYGWIN
2406 syms_of_w32cygwinx ();
2407 #endif
2408
2409 #if defined WINDOWSNT || defined HAVE_NTGUI
2410 syms_of_w32select ();
2411 #endif
2412
2413 #ifdef MSDOS
2414 syms_of_xmenu ();
2415 syms_of_dosfns ();
2416 syms_of_msdos ();
2417 syms_of_win16select ();
2418 #endif
2419
2420 #ifdef HAVE_NS
2421 syms_of_nsterm ();
2422 syms_of_nsfns ();
2423 syms_of_nsmenu ();
2424 syms_of_nsselect ();
2425 syms_of_fontset ();
2426 #endif
2427
2428 #ifdef HAVE_PGTK
2429 syms_of_pgtkterm ();
2430 syms_of_pgtkfns ();
2431 syms_of_pgtkselect ();
2432 syms_of_pgtkmenu ();
2433 syms_of_pgtkim ();
2434 syms_of_fontset ();
2435 syms_of_xsettings ();
2436 #endif
2437 #ifdef HAVE_HAIKU
2438 syms_of_haikuterm ();
2439 syms_of_haikufns ();
2440 syms_of_haikumenu ();
2441 syms_of_haikufont ();
2442 syms_of_haikuselect ();
2443 #ifdef HAVE_NATIVE_IMAGE_API
2444 syms_of_haikuimage ();
2445 #endif
2446 syms_of_fontset ();
2447 #endif
2448 #ifdef HAVE_ANDROID
2449 syms_of_androidterm ();
2450 syms_of_androidfns ();
2451 syms_of_androidmenu ();
2452 syms_of_fontset ();
2453 #if !defined ANDROID_STUBIFY
2454 syms_of_androidfont ();
2455 syms_of_androidselect ();
2456 syms_of_sfntfont ();
2457 syms_of_sfntfont_android ();
2458 #endif
2459 #endif
2460
2461 syms_of_gnutls ();
2462
2463 #ifdef HAVE_INOTIFY
2464 syms_of_inotify ();
2465 #endif
2466
2467 #ifdef HAVE_KQUEUE
2468 syms_of_kqueue ();
2469 #endif
2470
2471 #ifdef HAVE_GFILENOTIFY
2472 syms_of_gfilenotify ();
2473 #endif
2474
2475 #ifdef HAVE_DBUS
2476 syms_of_dbusbind ();
2477 #endif
2478
2479 #ifdef WINDOWSNT
2480 syms_of_ntterm ();
2481 #ifdef HAVE_W32NOTIFY
2482 syms_of_w32notify ();
2483 #endif
2484 #endif
2485
2486 syms_of_xwidget ();
2487 syms_of_threads ();
2488 syms_of_profiler ();
2489 syms_of_pdumper ();
2490
2491 #ifdef HAVE_JSON
2492 syms_of_json ();
2493 #endif
2494
2495 keys_of_keyboard ();
2496
2497 #ifdef HAVE_NATIVE_COMP
2498
2499 hash_native_abi ();
2500 #endif
2501 }
2502 else
2503 {
2504
2505
2506 #ifdef HAVE_NTGUI
2507 globals_of_w32font ();
2508 globals_of_w32fns ();
2509 globals_of_w32menu ();
2510 #endif
2511
2512 #if defined WINDOWSNT || defined HAVE_NTGUI
2513 globals_of_w32select ();
2514 #endif
2515 }
2516
2517 #ifdef HAVE_HAIKU
2518 init_haiku_select ();
2519 #endif
2520
2521 init_charset ();
2522
2523
2524 init_timefns ();
2525
2526 init_editfns ();
2527
2528
2529 #ifdef HAVE_DBUS
2530 init_dbusbind ();
2531 #endif
2532
2533 #ifdef HAVE_X_WINDOWS
2534 init_xterm ();
2535 #endif
2536
2537
2538
2539
2540 init_process_emacs (sockfd);
2541
2542 init_keyboard ();
2543 init_display ();
2544 #if HAVE_W32NOTIFY
2545 if (noninteractive)
2546 init_crit ();
2547 #endif
2548 init_xdisp ();
2549 #ifdef HAVE_WINDOW_SYSTEM
2550 init_fringe ();
2551 #endif
2552 init_macros ();
2553 init_window ();
2554 init_font ();
2555
2556 #ifdef HAVE_ANDROID
2557 init_androidmenu ();
2558 #endif
2559
2560 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2561 init_androidfont ();
2562 init_androidselect ();
2563 init_sfntfont ();
2564 init_sfntfont_android ();
2565 #endif
2566
2567 if (!initialized)
2568 {
2569 char *file;
2570
2571 if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args))
2572 {
2573 #ifdef WINDOWSNT
2574 char file_utf8[MAX_UTF8_PATH];
2575
2576 if (filename_from_ansi (file, file_utf8) == 0)
2577 file = file_utf8;
2578 #endif
2579 Vtop_level = list2 (Qload, build_unibyte_string (file));
2580 }
2581
2582 if (! no_loadup)
2583 Vtop_level = list2 (Qload, build_string ("loadup.el"));
2584
2585 #ifdef HAVE_NATIVE_COMP
2586
2587
2588
2589 if (!NILP (Vtop_level) && !temacs)
2590 Vnative_comp_eln_load_path =
2591 Fcons (Fexpand_file_name (XCAR (Vnative_comp_eln_load_path),
2592 Vinvocation_directory),
2593 Qnil);
2594 #endif
2595 }
2596
2597
2598
2599
2600
2601 #ifdef PROFILING
2602 if (initialized)
2603 {
2604 atexit (_mcleanup);
2605 monstartup ((uintptr_t) __executable_start, (uintptr_t) &etext);
2606 }
2607 else
2608 moncontrol (0);
2609 #endif
2610
2611 initialized = true;
2612
2613 if (dump_mode)
2614 Vdump_mode = build_string (dump_mode);
2615
2616 #ifdef HAVE_PDUMPER
2617
2618 safe_run_hooks (Qafter_pdump_load_hook);
2619 #endif
2620
2621 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && 0
2622
2623
2624
2625
2626
2627 Vtop_level = list3 (Qprogn, Vtop_level,
2628 list1 (Qandroid_enumerate_fonts));
2629 #endif
2630
2631
2632 set_initial_minibuffer_mode ();
2633 Frecursive_edit ();
2634 eassume (false);
2635 }
2636
2637
2638
2639
2640
2641
2642 struct standard_args
2643 {
2644 const char *name;
2645 const char *longname;
2646 int priority;
2647 int nargs;
2648 };
2649
2650 static const struct standard_args standard_args[] =
2651 {
2652 { "-version", "--version", 150, 0 },
2653 #ifdef HAVE_PDUMPER
2654 { "-fingerprint", "--fingerprint", 140, 0 },
2655 #endif
2656 { "-chdir", "--chdir", 130, 1 },
2657 { "-t", "--terminal", 120, 1 },
2658 { "-nw", "--no-window-system", 110, 0 },
2659 { "-nw", "--no-windows", 110, 0 },
2660 { "-batch", "--batch", 100, 0 },
2661 { "-script", "--script", 100, 1 },
2662 { "-daemon", "--daemon", 99, 0 },
2663 { "-bg-daemon", "--bg-daemon", 99, 0 },
2664 { "-fg-daemon", "--fg-daemon", 99, 0 },
2665 { "-help", "--help", 90, 0 },
2666 { "-nl", "--no-loadup", 70, 0 },
2667 { "-nsl", "--no-site-lisp", 65, 0 },
2668 { "-no-build-details", "--no-build-details", 63, 0 },
2669 #ifdef HAVE_MODULES
2670 { "-module-assertions", "--module-assertions", 62, 0 },
2671 #endif
2672
2673 { "-d", "--display", 60, 1 },
2674 { "-display", 0, 60, 1 },
2675
2676
2677 { "-Q", "--quick", 55, 0 },
2678 { "-quick", 0, 55, 0 },
2679 { "-x", 0, 55, 0 },
2680 { "-q", "--no-init-file", 50, 0 },
2681 { "-no-init-file", 0, 50, 0 },
2682 { "-init-directory", "--init-directory", 30, 1 },
2683 { "-no-x-resources", "--no-x-resources", 40, 0 },
2684 { "-no-site-file", "--no-site-file", 40, 0 },
2685 { "-no-comp-spawn", "--no-comp-spawn", 60, 0 },
2686 { "-u", "--user", 30, 1 },
2687 { "-user", 0, 30, 1 },
2688 { "-debug-init", "--debug-init", 20, 0 },
2689 { "-iconic", "--iconic", 15, 0 },
2690 { "-D", "--basic-display", 12, 0},
2691 { "-basic-display", 0, 12, 0},
2692 { "-nbc", "--no-blinking-cursor", 12, 0 },
2693
2694 { "-nbi", "--no-bitmap-icon", 10, 0 },
2695 { "-bg", "--background-color", 10, 1 },
2696 { "-background", 0, 10, 1 },
2697 { "-fg", "--foreground-color", 10, 1 },
2698 { "-foreground", 0, 10, 1 },
2699 { "-bd", "--border-color", 10, 1 },
2700 { "-bw", "--border-width", 10, 1 },
2701 { "-ib", "--internal-border", 10, 1 },
2702 { "-ms", "--mouse-color", 10, 1 },
2703 { "-cr", "--cursor-color", 10, 1 },
2704 { "-fn", "--font", 10, 1 },
2705 { "-font", 0, 10, 1 },
2706 { "-fs", "--fullscreen", 10, 0 },
2707 { "-fw", "--fullwidth", 10, 0 },
2708 { "-fh", "--fullheight", 10, 0 },
2709 { "-mm", "--maximized", 10, 0 },
2710 { "-g", "--geometry", 10, 1 },
2711 { "-geometry", 0, 10, 1 },
2712 { "-T", "--title", 10, 1 },
2713 { "-title", 0, 10, 1 },
2714 { "-name", "--name", 10, 1 },
2715 { "-xrm", "--xrm", 10, 1 },
2716 { "-parent-id", "--parent-id", 10, 1 },
2717 { "-r", "--reverse-video", 5, 0 },
2718 { "-rv", 0, 5, 0 },
2719 { "-reverse", 0, 5, 0 },
2720 { "-hb", "--horizontal-scroll-bars", 5, 0 },
2721 { "-vb", "--vertical-scroll-bars", 5, 0 },
2722 { "-color", "--color", 5, 0},
2723 { "-no-splash", "--no-splash", 3, 0 },
2724 { "-no-desktop", "--no-desktop", 3, 0 },
2725
2726
2727 { "-temacs", "--temacs", 1, 1 },
2728 #ifdef HAVE_PDUMPER
2729 { "-dump-file", "--dump-file", 1, 1 },
2730 #endif
2731 #if SECCOMP_USABLE
2732 { "-seccomp", "--seccomp", 1, 1 },
2733 #endif
2734 #ifdef HAVE_NS
2735 { "-NSAutoLaunch", 0, 5, 1 },
2736 { "-NXAutoLaunch", 0, 5, 1 },
2737 { "-_NSMachLaunch", 0, 85, 1 },
2738 { "-MachLaunch", 0, 85, 1 },
2739 { "-macosx", 0, 85, 0 },
2740 { "-NSHost", 0, 85, 1 },
2741 #endif
2742
2743
2744 { "-L", "--directory", 0, 1 },
2745 { "-directory", 0, 0, 1 },
2746 { "-l", "--load", 0, 1 },
2747 { "-load", 0, 0, 1 },
2748
2749
2750
2751
2752 { "-scriptload", NULL, 0, 1 },
2753 { "-f", "--funcall", 0, 1 },
2754 { "-funcall", 0, 0, 1 },
2755 { "-eval", "--eval", 0, 1 },
2756 { "-execute", "--execute", 0, 1 },
2757 { "-find-file", "--find-file", 0, 1 },
2758 { "-visit", "--visit", 0, 1 },
2759 { "-file", "--file", 0, 1 },
2760 { "-insert", "--insert", 0, 1 },
2761 #ifdef HAVE_NS
2762 { "-NXOpen", 0, 0, 1 },
2763 { "-NXOpenTemp", 0, 0, 1 },
2764 { "-NSOpen", 0, 0, 1 },
2765 { "-NSOpenTemp", 0, 0, 1 },
2766 { "-GSFilePath", 0, 0, 1 },
2767 #endif
2768
2769 { "-kill", "--kill", -10, 0 },
2770 };
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780 static void
2781 sort_args (int argc, char **argv)
2782 {
2783 char **new = xmalloc (argc * sizeof *new);
2784
2785
2786
2787
2788
2789 int *options = xnmalloc (argc, sizeof *options);
2790 int *priority = xnmalloc (argc, sizeof *priority);
2791 int to = 1;
2792 int incoming_used = 1;
2793 int from;
2794 int i;
2795
2796
2797
2798 for (from = 1; from < argc; from++)
2799 {
2800 options[from] = -1;
2801 priority[from] = 0;
2802 if (argv[from][0] == '-')
2803 {
2804 int match;
2805
2806
2807
2808 if (argv[from][1] == '-' && argv[from][2] == 0)
2809 {
2810
2811 for (; from < argc; from++)
2812 {
2813 priority[from] = -100;
2814 options[from] = -1;
2815 }
2816 break;
2817 }
2818
2819
2820 for (i = 0; i < ARRAYELTS (standard_args); i++)
2821 if (!strcmp (argv[from], standard_args[i].name))
2822 {
2823 options[from] = standard_args[i].nargs;
2824 priority[from] = standard_args[i].priority;
2825 if (from + standard_args[i].nargs >= argc)
2826 fatal ("Option '%s' requires an argument\n", argv[from]);
2827 from += standard_args[i].nargs;
2828 goto done;
2829 }
2830
2831
2832
2833
2834 if (argv[from][1] == '-')
2835 {
2836 char const *equals = strchr (argv[from], '=');
2837 ptrdiff_t thislen =
2838 equals ? equals - argv[from] : strlen (argv[from]);
2839
2840 match = -1;
2841
2842 for (i = 0; i < ARRAYELTS (standard_args); i++)
2843 if (standard_args[i].longname
2844 && !strncmp (argv[from], standard_args[i].longname,
2845 thislen))
2846 {
2847 if (match == -1)
2848 match = i;
2849 else
2850 match = -2;
2851 }
2852
2853
2854 if (match >= 0)
2855 {
2856 options[from] = standard_args[match].nargs;
2857 priority[from] = standard_args[match].priority;
2858
2859
2860 if (equals != 0)
2861 options[from] = 0;
2862 if (from + options[from] >= argc)
2863 fatal ("Option '%s' requires an argument\n", argv[from]);
2864 from += options[from];
2865 }
2866 else if (match == -2)
2867 {
2868
2869
2870 fprintf (stderr, "Option '%s' matched multiple standard arguments\n", argv[from]);
2871 }
2872
2873 }
2874 done: ;
2875 }
2876 }
2877
2878
2879 new[0] = argv[0];
2880 while (incoming_used < argc)
2881 {
2882 int best = -1;
2883 int best_priority = -9999;
2884
2885
2886
2887 for (from = 1; from < argc; from++)
2888 {
2889 if (argv[from] != 0 && priority[from] > best_priority)
2890 {
2891 best_priority = priority[from];
2892 best = from;
2893 }
2894
2895 if (options[from] > 0)
2896 from += options[from];
2897 }
2898
2899 if (best < 0)
2900 emacs_abort ();
2901
2902
2903
2904 if (! (options[best] == 0
2905 && ! strcmp (new[to - 1], argv[best])))
2906 {
2907 new[to++] = argv[best];
2908 for (i = 0; i < options[best]; i++)
2909 new[to++] = argv[best + i + 1];
2910 }
2911
2912 incoming_used += 1 + (options[best] > 0 ? options[best] : 0);
2913
2914
2915 argv[best] = 0;
2916 for (i = 0; i < options[best]; i++)
2917 argv[best + i + 1] = 0;
2918 }
2919
2920
2921 while (to < argc)
2922 new[to++] = 0;
2923
2924 memcpy (argv, new, sizeof (char *) * argc);
2925
2926 xfree (options);
2927 xfree (new);
2928 xfree (priority);
2929 }
2930
2931 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 2, "P",
2932 doc:
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948 attributes: noreturn)
2949 (Lisp_Object arg, Lisp_Object restart)
2950 {
2951 int exit_code;
2952
2953 #ifndef WINDOWSNT
2954
2955
2956 if (!NILP (restart)
2957
2958
2959
2960 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2961 && !android_init_gui
2962 #endif
2963 )
2964 {
2965
2966
2967 if (initial_argc < 1)
2968 error ("No command line arguments known; unable to re-execute Emacs");
2969
2970
2971 if (!initial_emacs_executable)
2972 error ("Unknown Emacs executable");
2973
2974 if (!file_access_p (initial_emacs_executable, F_OK))
2975 error ("Emacs executable \"%s\" can't be found", initial_argv[0]);
2976 }
2977 #endif
2978
2979 #ifdef HAVE_LIBSYSTEMD
2980
2981
2982 if (daemon_type == -1)
2983 sd_notify(0, "STOPPING=1");
2984 #endif
2985
2986
2987
2988 waiting_for_input = 0;
2989 if (!NILP (find_symbol_value (Qkill_emacs_hook)))
2990 {
2991 if (noninteractive)
2992 safe_run_hooks (Qkill_emacs_hook);
2993 else
2994 call1 (Qrun_hook_query_error_with_timeout, Qkill_emacs_hook);
2995 }
2996
2997 #ifdef HAVE_X_WINDOWS
2998
2999 x_clipboard_manager_save_all ();
3000 #endif
3001
3002 shut_down_emacs (0, (STRINGP (arg) && !feof (stdin)) ? arg : Qnil);
3003
3004 #ifdef HAVE_NS
3005 ns_release_autorelease_pool (ns_pool);
3006 #endif
3007
3008
3009
3010
3011 if (STRINGP (Vauto_save_list_file_name))
3012 {
3013 Lisp_Object listfile;
3014 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
3015 emacs_unlink (SSDATA (listfile));
3016 }
3017
3018 #ifdef HAVE_NATIVE_COMP
3019 eln_load_path_final_clean_up ();
3020 #endif
3021
3022 if (!NILP (restart))
3023 {
3024 turn_on_atimers (false);
3025 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
3026
3027
3028
3029 if (android_init_gui)
3030 android_restart_emacs ();
3031 #endif
3032 #ifdef WINDOWSNT
3033 if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0)
3034 #else
3035 initial_argv[0] = initial_emacs_executable;
3036 if (execvp (*initial_argv, initial_argv) < 1)
3037 #endif
3038 emacs_perror ("Unable to re-execute Emacs");
3039 }
3040
3041 if (FIXNUMP (arg))
3042 exit_code = (XFIXNUM (arg) < 0
3043 ? XFIXNUM (arg) | INT_MIN
3044 : XFIXNUM (arg) & INT_MAX);
3045 else
3046 exit_code = EXIT_SUCCESS;
3047 exit (exit_code);
3048 }
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062 void
3063 shut_down_emacs (int sig, Lisp_Object stuff)
3064 {
3065
3066 Vrun_hooks = Qnil;
3067
3068
3069 Vinhibit_redisplay = Qt;
3070
3071
3072 #if !defined DOS_NT && !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
3073 pid_t tpgrp = tcgetpgrp (STDIN_FILENO);
3074 if (tpgrp != -1 && tpgrp == getpgrp ())
3075 {
3076 reset_all_sys_modes ();
3077 if (sig && sig != SIGTERM)
3078 {
3079 #ifdef HAVE_HAIKU
3080 if (haiku_debug_on_fatal_error)
3081 debugger ("Fatal error in Emacs");
3082 #endif
3083
3084
3085
3086 static char const fmt[] = "Fatal error %d: ";
3087 char buf[max ((sizeof fmt - sizeof "%d"
3088 + INT_STRLEN_BOUND (int) + 1),
3089 min (PIPE_BUF, MAX_ALLOCA))];
3090 char const *sig_desc = safe_strsignal (sig);
3091 size_t sig_desclen = strlen (sig_desc);
3092 int nlen = sprintf (buf, fmt, sig);
3093 if (nlen + sig_desclen < sizeof buf - 1)
3094 {
3095 char *p = mempcpy (buf + nlen, sig_desc, sig_desclen);
3096 *p++ = '\n';
3097 emacs_write (STDERR_FILENO, buf, p - buf);
3098 }
3099 else
3100 {
3101 emacs_write (STDERR_FILENO, buf, nlen);
3102 emacs_write (STDERR_FILENO, sig_desc, sig_desclen);
3103 emacs_write (STDERR_FILENO, "\n", 1);
3104 }
3105 }
3106 }
3107 #else
3108 fflush (stdout);
3109 reset_all_sys_modes ();
3110 #endif
3111
3112 stuff_buffered_input (stuff);
3113
3114 inhibit_sentinels = 1;
3115 kill_buffer_processes (Qnil);
3116 Fdo_auto_save (Qt, Qnil);
3117
3118 unlock_all_files ();
3119
3120
3121
3122 unrequest_sigio ();
3123
3124
3125
3126 if (sig == 0 || sig == SIGTERM)
3127 {
3128 check_glyph_memory ();
3129 check_message_stack ();
3130 }
3131
3132 #ifdef HAVE_NATIVE_COMP
3133 eln_load_path_final_clean_up ();
3134 #endif
3135
3136 #ifdef MSDOS
3137 dos_cleanup ();
3138 #endif
3139
3140 #ifdef HAVE_NS
3141 ns_term_shutdown (sig);
3142 #endif
3143
3144 #ifdef HAVE_LIBXML2
3145 xml_cleanup_parser ();
3146 #endif
3147
3148 #ifdef WINDOWSNT
3149 term_ntproc (0);
3150 #endif
3151 }
3152
3153
3154
3155 #ifdef HAVE_UNEXEC
3156
3157 #include "unexec.h"
3158
3159 DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
3160 doc:
3161
3162
3163
3164 )
3165 (Lisp_Object filename, Lisp_Object symfile)
3166 {
3167 Lisp_Object tem;
3168 Lisp_Object symbol;
3169 specpdl_ref count = SPECPDL_INDEX ();
3170
3171 check_pure_size ();
3172
3173 if (! noninteractive)
3174 error ("Dumping Emacs works only in batch mode");
3175
3176 if (dumped_with_unexec_p ())
3177 error ("Emacs can be dumped using unexec only once");
3178
3179 if (definitely_will_not_unexec_p ())
3180 error ("This Emacs instance was not started in temacs mode");
3181
3182 # if defined GNU_LINUX && defined HAVE_UNEXEC
3183
3184
3185 # define MAX_HEAP_BSS_DIFF (1024 * 1024)
3186
3187 if (heap_bss_diff > MAX_HEAP_BSS_DIFF)
3188 fprintf (stderr,
3189 ("**************************************************\n"
3190 "Warning: Your system has a gap between BSS and the\n"
3191 "heap (%"PRIuMAX" bytes). This usually means that exec-shield\n"
3192 "or something similar is in effect. The dump may\n"
3193 "fail because of this. See the section about\n"
3194 "exec-shield in etc/PROBLEMS for more information.\n"
3195 "**************************************************\n"),
3196 heap_bss_diff);
3197 # endif
3198
3199
3200
3201
3202 symbol = intern ("command-line-processed");
3203 specbind (symbol, Qnil);
3204
3205 CHECK_STRING (filename);
3206 filename = Fexpand_file_name (filename, Qnil);
3207 filename = ENCODE_FILE (filename);
3208 if (!NILP (symfile))
3209 {
3210 CHECK_STRING (symfile);
3211 if (SCHARS (symfile))
3212 {
3213 symfile = Fexpand_file_name (symfile, Qnil);
3214 symfile = ENCODE_FILE (symfile);
3215 }
3216 }
3217
3218 tem = Vpurify_flag;
3219 Vpurify_flag = Qnil;
3220
3221 # ifdef HYBRID_MALLOC
3222 {
3223 static char const fmt[] = "%d of %d static heap bytes used";
3224 char buf[sizeof fmt + 2 * (INT_STRLEN_BOUND (int) - 2)];
3225 int max_usage = max_bss_sbrk_ptr - bss_sbrk_buffer;
3226 sprintf (buf, fmt, max_usage, STATIC_HEAP_SIZE);
3227
3228 message1_nolog (buf);
3229 }
3230 # endif
3231
3232 fflush (stdout);
3233
3234
3235 # if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC && !defined WINDOWSNT
3236
3237
3238 memory_warnings (my_edata, malloc_warning);
3239 # endif
3240
3241 struct gflags old_gflags = gflags;
3242 gflags.will_dump_ = false;
3243 gflags.will_dump_with_unexec_ = false;
3244 gflags.dumped_with_unexec_ = true;
3245
3246 alloc_unexec_pre ();
3247
3248 unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
3249
3250 alloc_unexec_post ();
3251
3252 gflags = old_gflags;
3253
3254 # ifdef WINDOWSNT
3255 Vlibrary_cache = Qnil;
3256 # endif
3257
3258 Vpurify_flag = tem;
3259
3260 return unbind_to (count, Qnil);
3261 }
3262
3263 #endif
3264
3265
3266 #if HAVE_SETLOCALE
3267
3268 void
3269 fixup_locale (void)
3270 {
3271
3272
3273 setlocale (LC_NUMERIC, "C");
3274 }
3275
3276
3277
3278 static void
3279 synchronize_locale (int category, Lisp_Object *plocale, Lisp_Object desired_locale)
3280 {
3281 if (! EQ (*plocale, desired_locale))
3282 {
3283 *plocale = desired_locale;
3284 char const *locale_string
3285 = STRINGP (desired_locale) ? SSDATA (desired_locale) : "";
3286 # ifdef WINDOWSNT
3287
3288
3289
3290
3291
3292
3293 setlocale (LC_ALL, locale_string);
3294 fixup_locale ();
3295 # else
3296 setlocale (category, locale_string);
3297 # endif
3298 }
3299 }
3300
3301 static Lisp_Object Vprevious_system_time_locale;
3302
3303
3304 void
3305 synchronize_system_time_locale (void)
3306 {
3307 synchronize_locale (LC_TIME, &Vprevious_system_time_locale,
3308 Vsystem_time_locale);
3309 }
3310
3311 # ifdef LC_MESSAGES
3312 static Lisp_Object Vprevious_system_messages_locale;
3313 # endif
3314
3315
3316
3317 void
3318 synchronize_system_messages_locale (void)
3319 {
3320 # ifdef LC_MESSAGES
3321 synchronize_locale (LC_MESSAGES, &Vprevious_system_messages_locale,
3322 Vsystem_messages_locale);
3323 # endif
3324 }
3325 #endif
3326
3327
3328
3329 char *
3330 emacs_strerror (int error_number)
3331 {
3332 synchronize_system_messages_locale ();
3333 return strerror (error_number);
3334 }
3335
3336
3337 Lisp_Object
3338 decode_env_path (const char *evarname, const char *defalt, bool empty)
3339 {
3340 const char *path, *p;
3341 Lisp_Object lpath, element, tem;
3342 #ifdef NS_SELF_CONTAINED
3343 void *autorelease = NULL;
3344 #endif
3345
3346
3347 Lisp_Object empty_element = empty ? Qnil : build_string (".");
3348 #ifdef WINDOWSNT
3349 bool defaulted = 0;
3350 static const char *emacs_dir_env = "%emacs_dir%/";
3351 const size_t emacs_dir_len = strlen (emacs_dir_env);
3352 const char *edir = egetenv ("emacs_dir");
3353 char emacs_dir[MAX_UTF8_PATH];
3354
3355
3356
3357
3358 if (edir)
3359 filename_from_ansi (edir, emacs_dir);
3360 #endif
3361
3362
3363
3364
3365 if (evarname != 0)
3366 path = getenv (evarname);
3367 else
3368 path = 0;
3369 if (!path)
3370 {
3371 #ifdef NS_SELF_CONTAINED
3372
3373 autorelease = ns_alloc_autorelease_pool ();
3374 path = ns_relocate (defalt);
3375 #else
3376 path = defalt;
3377 #endif
3378 #ifdef WINDOWSNT
3379 defaulted = 1;
3380 #endif
3381 }
3382 #ifdef DOS_NT
3383
3384 if (path)
3385 {
3386 char *path_copy;
3387
3388 #ifdef WINDOWSNT
3389 char *path_utf8, *q, *d;
3390 int cnv_result;
3391
3392
3393 p = path_copy = alloca (strlen (path) + 1);
3394 strcpy (path_copy, path);
3395 d = path_utf8 = alloca (4 * strlen (path) + 1);
3396 *d = '\0';
3397 do {
3398 q = _mbschr (p, SEPCHAR);
3399 if (q)
3400 *q = '\0';
3401 cnv_result = filename_from_ansi (p, d);
3402 if (q)
3403 {
3404 *q++ = SEPCHAR;
3405 p = q;
3406
3407
3408
3409 if (cnv_result == 0)
3410 {
3411 d += strlen (d);
3412 *d++ = SEPCHAR;
3413 }
3414 }
3415 else if (cnv_result != 0 && d > path_utf8)
3416 d[-1] = '\0';
3417 } while (q);
3418 path_copy = path_utf8;
3419 #else
3420 path_copy = alloca (strlen (path) + 1);
3421 strcpy (path_copy, path);
3422 #endif
3423 dostounix_filename (path_copy);
3424 path = path_copy;
3425 }
3426 #endif
3427 lpath = Qnil;
3428 while (1)
3429 {
3430 p = strchr (path, SEPCHAR);
3431 if (!p)
3432 p = path + strlen (path);
3433 element = ((p - path) ? make_unibyte_string (path, p - path)
3434 : empty_element);
3435 if (! NILP (element))
3436 {
3437 #ifdef WINDOWSNT
3438
3439
3440 if (edir && defaulted
3441 && strncmp (path, emacs_dir_env, emacs_dir_len) == 0)
3442 element = Fexpand_file_name (Fsubstring
3443 (element,
3444 make_fixnum (emacs_dir_len),
3445 Qnil),
3446 build_unibyte_string (emacs_dir));
3447 #endif
3448
3449
3450
3451 tem = Ffind_file_name_handler (element, Qt);
3452
3453
3454
3455 if (SYMBOLP (tem))
3456 {
3457 Lisp_Object prop;
3458 prop = Fget (tem, intern ("safe-magic"));
3459 if (! NILP (prop))
3460 tem = Qnil;
3461 }
3462
3463 if (! NILP (tem))
3464 {
3465 AUTO_STRING (slash_colon, "/:");
3466 element = concat2 (slash_colon, element);
3467 }
3468 }
3469
3470 lpath = Fcons (element, lpath);
3471 if (*p)
3472 path = p + 1;
3473 else
3474 break;
3475 }
3476
3477 #ifdef NS_SELF_CONTAINED
3478 if (autorelease)
3479 ns_release_autorelease_pool (autorelease);
3480 #endif
3481 return Fnreverse (lpath);
3482 }
3483
3484 DEFUN ("daemonp", Fdaemonp, Sdaemonp, 0, 0, 0,
3485 doc:
3486 )
3487 (void)
3488 {
3489 if (IS_DAEMON)
3490 if (daemon_name)
3491 return build_string (daemon_name);
3492 else
3493 return Qt;
3494 else
3495 return Qnil;
3496 }
3497
3498 DEFUN ("daemon-initialized", Fdaemon_initialized, Sdaemon_initialized, 0, 0, 0,
3499 doc:
3500
3501 )
3502 (void)
3503 {
3504 bool err = 0;
3505
3506 if (!IS_DAEMON)
3507 error ("This function can only be called if emacs is run as a daemon");
3508
3509 if (!DAEMON_RUNNING)
3510 error ("The daemon has already been initialized");
3511
3512 if (NILP (Vafter_init_time))
3513 error ("This function can only be called after loading the init files");
3514 #ifndef WINDOWSNT
3515
3516 if (daemon_type == 1)
3517 {
3518 #ifdef HAVE_LIBSYSTEMD
3519 sd_notify(0, "READY=1");
3520 #endif
3521 }
3522
3523 if (daemon_type == 2)
3524 {
3525 int nfd;
3526
3527
3528 nfd = emacs_open_noquit ("/dev/null", O_RDWR, 0);
3529 err |= nfd < 0;
3530 err |= dup2 (nfd, STDIN_FILENO) < 0;
3531 err |= dup2 (nfd, STDOUT_FILENO) < 0;
3532 err |= dup2 (nfd, STDERR_FILENO) < 0;
3533 err |= emacs_close (nfd) != 0;
3534
3535
3536
3537
3538
3539
3540
3541
3542 err |= write (daemon_pipe[1], "\n", 1) < 0;
3543 err |= emacs_close (daemon_pipe[1]) != 0;
3544 }
3545
3546
3547 daemon_type = -daemon_type;
3548
3549 #else
3550
3551 err |= SetEvent (w32_daemon_event) == 0;
3552 err |= CloseHandle (w32_daemon_event) == 0;
3553
3554 w32_daemon_event = INVALID_HANDLE_VALUE;
3555 #endif
3556
3557 if (err)
3558 error ("I/O error during daemon initialization");
3559 return Qt;
3560 }
3561
3562 void
3563 syms_of_emacs (void)
3564 {
3565 DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist");
3566 DEFSYM (Qrisky_local_variable, "risky-local-variable");
3567 DEFSYM (Qkill_emacs, "kill-emacs");
3568 DEFSYM (Qkill_emacs_hook, "kill-emacs-hook");
3569 DEFSYM (Qrun_hook_query_error_with_timeout,
3570 "run-hook-query-error-with-timeout");
3571
3572 #ifdef HAVE_UNEXEC
3573 defsubr (&Sdump_emacs);
3574 #endif
3575
3576 defsubr (&Skill_emacs);
3577
3578 defsubr (&Sinvocation_name);
3579 defsubr (&Sinvocation_directory);
3580 defsubr (&Sdaemonp);
3581 defsubr (&Sdaemon_initialized);
3582
3583 DEFVAR_LISP ("command-line-args", Vcommand_line_args,
3584 doc:
3585 );
3586
3587 DEFVAR_LISP ("system-type", Vsystem_type,
3588 doc:
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600 );
3601 Vsystem_type = intern_c_string (SYSTEM_TYPE);
3602
3603
3604 DEFVAR_LISP ("system-configuration", Vsystem_configuration,
3605 doc: );
3606 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
3607
3608 DEFVAR_LISP ("system-configuration-options", Vsystem_configuration_options,
3609 doc: );
3610 Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS);
3611
3612 DEFVAR_LISP ("system-configuration-features", Vsystem_configuration_features,
3613 doc:
3614
3615
3616
3617
3618 );
3619 Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES);
3620
3621 DEFVAR_BOOL ("noninteractive", noninteractive1,
3622 doc: );
3623
3624 DEFVAR_LISP ("kill-emacs-hook", Vkill_emacs_hook,
3625 doc:
3626
3627
3628
3629
3630
3631
3632 );
3633 Vkill_emacs_hook = Qnil;
3634
3635 DEFVAR_LISP ("path-separator", Vpath_separator,
3636 doc:
3637 );
3638 {
3639 char c = SEPCHAR;
3640 Vpath_separator = make_string (&c, 1);
3641 }
3642
3643 DEFVAR_LISP ("invocation-name", Vinvocation_name,
3644 doc:
3645 );
3646
3647 DEFVAR_LISP ("invocation-directory", Vinvocation_directory,
3648 doc:
3649 );
3650
3651 DEFVAR_LISP ("installation-directory", Vinstallation_directory,
3652 doc:
3653
3654
3655
3656
3657 );
3658 Vinstallation_directory = Qnil;
3659
3660 DEFVAR_LISP ("system-messages-locale", Vsystem_messages_locale,
3661 doc: );
3662 Vsystem_messages_locale = Qnil;
3663 #ifdef LC_MESSAGES
3664 Vprevious_system_messages_locale = Qnil;
3665 staticpro (&Vprevious_system_messages_locale);
3666 #endif
3667
3668 DEFVAR_LISP ("system-time-locale", Vsystem_time_locale,
3669 doc: );
3670 Vsystem_time_locale = Qnil;
3671 Vprevious_system_time_locale = Qnil;
3672 staticpro (&Vprevious_system_time_locale);
3673
3674 DEFVAR_LISP ("before-init-time", Vbefore_init_time,
3675 doc: );
3676 Vbefore_init_time = Qnil;
3677
3678 DEFVAR_LISP ("after-init-time", Vafter_init_time,
3679 doc:
3680 );
3681 Vafter_init_time = Qnil;
3682
3683 DEFVAR_BOOL ("inhibit-x-resources", inhibit_x_resources,
3684 doc: );
3685 inhibit_x_resources = 0;
3686
3687 DEFVAR_LISP ("emacs-copyright", Vemacs_copyright,
3688 doc: );
3689 Vemacs_copyright = build_string (emacs_copyright);
3690
3691 DEFVAR_LISP ("emacs-version", Vemacs_version,
3692 doc:
3693
3694
3695
3696
3697 );
3698 Vemacs_version = build_string (emacs_version);
3699
3700 DEFVAR_LISP ("report-emacs-bug-address", Vreport_emacs_bug_address,
3701 doc: );
3702 Vreport_emacs_bug_address = build_string (emacs_bugreport);
3703
3704 DEFVAR_LISP ("dump-mode", Vdump_mode,
3705 doc: );
3706
3707 DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist,
3708 doc:
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721 );
3722 #ifdef WINDOWSNT
3723
3724
3725
3726 if (will_dump_p ())
3727 Vdynamic_library_alist = list1 (list2 (Qgccjit,
3728 build_string ("libgccjit-0.dll")));
3729 else
3730 Vdynamic_library_alist = Qnil;
3731 #else
3732 Vdynamic_library_alist = Qnil;
3733 #endif
3734 Fput (intern_c_string ("dynamic-library-alist"), Qrisky_local_variable, Qt);
3735
3736 #ifdef WINDOWSNT
3737 Vlibrary_cache = Qnil;
3738 staticpro (&Vlibrary_cache);
3739 #endif
3740 }