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
2081
2082
2083
2084 {
2085 int count_before = skip_args;
2086
2087 #ifdef HAVE_X_WINDOWS
2088 char *displayname = 0;
2089
2090
2091 while (!only_version)
2092 {
2093 int count_before_this = skip_args;
2094
2095 if (argmatch (argv, argc, "-d", "--display", 3, &displayname, &skip_args))
2096 display_arg = 1;
2097 else if (argmatch (argv, argc, "-display", 0, 3, &displayname, &skip_args))
2098 display_arg = 1;
2099 else
2100 break;
2101
2102 count_before = count_before_this;
2103 }
2104
2105
2106
2107
2108 if (displayname && count_before < skip_args)
2109 {
2110 if (skip_args == count_before + 1)
2111 {
2112 memmove (argv + count_before + 3, argv + count_before + 2,
2113 (argc - (count_before + 2)) * sizeof *argv);
2114 argv[count_before + 2] = displayname;
2115 argc++;
2116 }
2117 argv[count_before + 1] = (char *) "-d";
2118 }
2119 #endif
2120
2121 if (! no_site_lisp)
2122 {
2123
2124 if (argmatch (argv, argc, "-Q", "--quick", 3, NULL, &skip_args)
2125 || argmatch (argv, argc, "-quick", 0, 2, NULL, &skip_args))
2126 no_site_lisp = 1;
2127
2128 }
2129
2130 if (argmatch (argv, argc, "-x", 0, 1, &junk, &skip_args))
2131 {
2132 noninteractive = 1;
2133 no_site_lisp = 1;
2134
2135 argv[skip_args - 1] = (char *) "-scripteval";
2136 skip_args -= 1;
2137 sort_args (argc, argv);
2138 }
2139
2140
2141 skip_args = count_before;
2142 }
2143
2144
2145
2146
2147
2148 #ifdef MSDOS
2149
2150 init_dosfns ();
2151
2152 if (initialized)
2153 init_environment (argc, argv, skip_args);
2154 else
2155 tzset ();
2156 #endif
2157
2158 #ifdef HAVE_KQUEUE
2159 globals_of_kqueue ();
2160 #endif
2161
2162 #ifdef HAVE_GFILENOTIFY
2163 globals_of_gfilenotify ();
2164 #endif
2165
2166
2167
2168
2169 if (!initialized)
2170 syms_of_callproc ();
2171
2172
2173
2174 if (!will_dump_p ())
2175 set_initial_environment ();
2176
2177
2178 init_atimer ();
2179
2180 #ifdef WINDOWSNT
2181 globals_of_w32 ();
2182 #ifdef HAVE_W32NOTIFY
2183 globals_of_w32notify ();
2184 #endif
2185
2186
2187
2188
2189
2190 init_environment (argv);
2191 init_ntproc (will_dump_p ());
2192 #endif
2193
2194
2195
2196
2197
2198 #ifdef AIX
2199 xputenv ("LANG=C");
2200 #endif
2201
2202
2203 init_buffer ();
2204
2205
2206 init_callproc_1 ();
2207
2208
2209 init_cmdargs (argc, argv, skip_args, original_pwd);
2210
2211 if (initialized)
2212 {
2213
2214 Lisp_Object old_log_max;
2215 old_log_max = Vmessage_log_max;
2216 XSETFASTINT (Vmessage_log_max, 0);
2217 message_dolog ("", 0, 1, 0);
2218 Vmessage_log_max = old_log_max;
2219 }
2220
2221 init_callproc ();
2222 init_fileio ();
2223 init_lread ();
2224
2225
2226
2227
2228
2229 if (only_version)
2230 {
2231 const char *version, *copyright;
2232
2233 if (initialized)
2234 {
2235 Lisp_Object tem = Fsymbol_value (intern_c_string ("emacs-version"));
2236 Lisp_Object tem2 = Fsymbol_value (intern_c_string ("emacs-copyright"));
2237 if (!STRINGP (tem))
2238 {
2239 fputs ("Invalid value of 'emacs-version'\n", stderr);
2240 exit (1);
2241 }
2242 if (!STRINGP (tem2))
2243 {
2244 fputs ("Invalid value of 'emacs-copyright'\n", stderr);
2245 exit (1);
2246 }
2247 else
2248 {
2249 version = SSDATA (tem);
2250 copyright = SSDATA (tem2);
2251 }
2252 }
2253 else
2254 {
2255 version = emacs_version;
2256 copyright = emacs_copyright;
2257 }
2258 printf ("%s %s\n", PACKAGE_NAME, version);
2259
2260 if (initialized)
2261 {
2262 Lisp_Object rversion, rbranch, rtime;
2263
2264 rversion
2265 = Fsymbol_value (intern_c_string ("emacs-repository-version"));
2266 rbranch
2267 = Fsymbol_value (intern_c_string ("emacs-repository-branch"));
2268 rtime
2269 = Fsymbol_value (intern_c_string ("emacs-build-time"));
2270
2271 if (!NILP (rversion) && !NILP (rbranch) && !NILP (rtime))
2272 printf ("Development version %s on %s branch; build date %s.\n",
2273 SSDATA (Fsubstring (rversion, make_fixnum (0),
2274 make_fixnum (12))),
2275 SSDATA (rbranch),
2276 SSDATA (Fformat_time_string (build_string ("%Y-%m-%d"),
2277 rtime, Qnil)));
2278 }
2279
2280 printf (("%s\n"
2281 "%s comes with ABSOLUTELY NO WARRANTY.\n"
2282 "You may redistribute copies of %s\n"
2283 "under the terms of the GNU General Public License.\n"
2284 "For more information about these matters, "
2285 "see the file named COPYING.\n"),
2286 copyright, PACKAGE_NAME, PACKAGE_NAME);
2287 exit (0);
2288 }
2289
2290 #ifdef WINDOWSNT
2291
2292 check_windows_init_file ();
2293 #endif
2294
2295
2296
2297
2298 if (!initialized)
2299 {
2300
2301
2302 syms_of_chartab ();
2303 syms_of_lread ();
2304 syms_of_print ();
2305 syms_of_eval ();
2306 syms_of_floatfns ();
2307
2308 syms_of_buffer ();
2309 syms_of_bytecode ();
2310 syms_of_callint ();
2311 syms_of_casefiddle ();
2312 syms_of_casetab ();
2313 syms_of_category ();
2314 syms_of_ccl ();
2315 syms_of_character ();
2316 syms_of_cmds ();
2317 syms_of_dired ();
2318 syms_of_display ();
2319 syms_of_doc ();
2320 syms_of_editfns ();
2321 syms_of_emacs ();
2322 syms_of_filelock ();
2323 syms_of_indent ();
2324 syms_of_insdel ();
2325
2326 syms_of_macros ();
2327 syms_of_marker ();
2328 syms_of_minibuf ();
2329 syms_of_process ();
2330 syms_of_search ();
2331 syms_of_sysdep ();
2332 syms_of_timefns ();
2333 syms_of_frame ();
2334 syms_of_syntax ();
2335 syms_of_terminal ();
2336 syms_of_term ();
2337 syms_of_undo ();
2338
2339 #ifdef HAVE_MODULES
2340 syms_of_module ();
2341 #endif
2342
2343
2344 syms_of_treesit ();
2345 #ifdef HAVE_SOUND
2346 syms_of_sound ();
2347 #endif
2348 syms_of_textprop ();
2349 syms_of_composite ();
2350 #ifdef WINDOWSNT
2351 syms_of_ntproc ();
2352 #endif
2353 #if defined CYGWIN
2354 syms_of_cygw32 ();
2355 #endif
2356 syms_of_window ();
2357 syms_of_xdisp ();
2358 syms_of_sqlite ();
2359 syms_of_font ();
2360 #ifdef HAVE_WINDOW_SYSTEM
2361 syms_of_fringe ();
2362 syms_of_image ();
2363 #endif
2364 #ifdef HAVE_X_WINDOWS
2365 syms_of_xterm ();
2366 syms_of_xfns ();
2367 syms_of_xmenu ();
2368 syms_of_fontset ();
2369 syms_of_xsettings ();
2370 #ifdef HAVE_X_SM
2371 syms_of_xsmfns ();
2372 #endif
2373 #ifdef HAVE_X11
2374 syms_of_xselect ();
2375 #endif
2376 #endif
2377
2378 syms_of_xml ();
2379
2380 #ifdef HAVE_LCMS2
2381 syms_of_lcms2 ();
2382 #endif
2383
2384 #ifdef HAVE_ZLIB
2385 syms_of_decompress ();
2386 #endif
2387
2388 syms_of_menu ();
2389
2390 #ifdef HAVE_NTGUI
2391 syms_of_w32term ();
2392 syms_of_w32fns ();
2393 syms_of_w32menu ();
2394 syms_of_fontset ();
2395 #endif
2396
2397 #if defined HAVE_NTGUI || defined CYGWIN
2398 syms_of_w32cygwinx ();
2399 #endif
2400
2401 #if defined WINDOWSNT || defined HAVE_NTGUI
2402 syms_of_w32select ();
2403 #endif
2404
2405 #ifdef MSDOS
2406 syms_of_xmenu ();
2407 syms_of_dosfns ();
2408 syms_of_msdos ();
2409 syms_of_win16select ();
2410 #endif
2411
2412 #ifdef HAVE_NS
2413 syms_of_nsterm ();
2414 syms_of_nsfns ();
2415 syms_of_nsmenu ();
2416 syms_of_nsselect ();
2417 syms_of_fontset ();
2418 #endif
2419
2420 #ifdef HAVE_PGTK
2421 syms_of_pgtkterm ();
2422 syms_of_pgtkfns ();
2423 syms_of_pgtkselect ();
2424 syms_of_pgtkmenu ();
2425 syms_of_pgtkim ();
2426 syms_of_fontset ();
2427 syms_of_xsettings ();
2428 #endif
2429 #ifdef HAVE_HAIKU
2430 syms_of_haikuterm ();
2431 syms_of_haikufns ();
2432 syms_of_haikumenu ();
2433 syms_of_haikufont ();
2434 syms_of_haikuselect ();
2435 #ifdef HAVE_NATIVE_IMAGE_API
2436 syms_of_haikuimage ();
2437 #endif
2438 syms_of_fontset ();
2439 #endif
2440 #ifdef HAVE_ANDROID
2441 syms_of_androidterm ();
2442 syms_of_androidfns ();
2443 syms_of_androidmenu ();
2444 syms_of_fontset ();
2445 #if !defined ANDROID_STUBIFY
2446 syms_of_androidfont ();
2447 syms_of_androidselect ();
2448 syms_of_sfntfont ();
2449 syms_of_sfntfont_android ();
2450 #endif
2451 #endif
2452
2453 syms_of_gnutls ();
2454
2455 #ifdef HAVE_INOTIFY
2456 syms_of_inotify ();
2457 #endif
2458
2459 #ifdef HAVE_KQUEUE
2460 syms_of_kqueue ();
2461 #endif
2462
2463 #ifdef HAVE_GFILENOTIFY
2464 syms_of_gfilenotify ();
2465 #endif
2466
2467 #ifdef HAVE_DBUS
2468 syms_of_dbusbind ();
2469 #endif
2470
2471 #ifdef WINDOWSNT
2472 syms_of_ntterm ();
2473 #ifdef HAVE_W32NOTIFY
2474 syms_of_w32notify ();
2475 #endif
2476 #endif
2477
2478 syms_of_xwidget ();
2479 syms_of_threads ();
2480 syms_of_profiler ();
2481 syms_of_pdumper ();
2482
2483 #ifdef HAVE_JSON
2484 syms_of_json ();
2485 #endif
2486
2487 keys_of_keyboard ();
2488
2489 #ifdef HAVE_NATIVE_COMP
2490
2491 hash_native_abi ();
2492 #endif
2493 }
2494 else
2495 {
2496
2497
2498 #ifdef HAVE_NTGUI
2499 globals_of_w32font ();
2500 globals_of_w32fns ();
2501 globals_of_w32menu ();
2502 #endif
2503
2504 #if defined WINDOWSNT || defined HAVE_NTGUI
2505 globals_of_w32select ();
2506 #endif
2507 }
2508
2509 #ifdef HAVE_HAIKU
2510 init_haiku_select ();
2511 #endif
2512
2513 init_charset ();
2514
2515
2516 init_timefns ();
2517
2518 init_editfns ();
2519
2520
2521 #ifdef HAVE_DBUS
2522 init_dbusbind ();
2523 #endif
2524
2525 #ifdef HAVE_X_WINDOWS
2526 init_xterm ();
2527 #endif
2528
2529
2530
2531
2532 init_process_emacs (sockfd);
2533
2534 init_keyboard ();
2535 init_display ();
2536 #if HAVE_W32NOTIFY
2537 if (noninteractive)
2538 init_crit ();
2539 #endif
2540 init_xdisp ();
2541 #ifdef HAVE_WINDOW_SYSTEM
2542 init_fringe ();
2543 #endif
2544 init_macros ();
2545 init_window ();
2546 init_font ();
2547
2548 #ifdef HAVE_ANDROID
2549 init_androidmenu ();
2550 #endif
2551
2552 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2553 init_androidfont ();
2554 init_androidselect ();
2555 init_sfntfont ();
2556 init_sfntfont_android ();
2557 #endif
2558
2559 if (!initialized)
2560 {
2561 char *file;
2562
2563 if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args))
2564 {
2565 #ifdef WINDOWSNT
2566 char file_utf8[MAX_UTF8_PATH];
2567
2568 if (filename_from_ansi (file, file_utf8) == 0)
2569 file = file_utf8;
2570 #endif
2571 Vtop_level = list2 (Qload, build_unibyte_string (file));
2572 }
2573
2574 if (! no_loadup)
2575 Vtop_level = list2 (Qload, build_string ("loadup.el"));
2576
2577 #ifdef HAVE_NATIVE_COMP
2578
2579
2580
2581 if (!NILP (Vtop_level) && !temacs)
2582 Vnative_comp_eln_load_path =
2583 Fcons (Fexpand_file_name (XCAR (Vnative_comp_eln_load_path),
2584 Vinvocation_directory),
2585 Qnil);
2586 #endif
2587 }
2588
2589
2590
2591
2592
2593 #ifdef PROFILING
2594 if (initialized)
2595 {
2596 atexit (_mcleanup);
2597 monstartup ((uintptr_t) __executable_start, (uintptr_t) &etext);
2598 }
2599 else
2600 moncontrol (0);
2601 #endif
2602
2603 initialized = true;
2604
2605 if (dump_mode)
2606 Vdump_mode = build_string (dump_mode);
2607
2608 #ifdef HAVE_PDUMPER
2609
2610 safe_run_hooks (Qafter_pdump_load_hook);
2611 #endif
2612
2613 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && 0
2614
2615
2616
2617
2618
2619 Vtop_level = list3 (Qprogn, Vtop_level,
2620 list1 (Qandroid_enumerate_fonts));
2621 #endif
2622
2623
2624 set_initial_minibuffer_mode ();
2625 Frecursive_edit ();
2626 eassume (false);
2627 }
2628
2629
2630
2631
2632
2633
2634 struct standard_args
2635 {
2636 const char *name;
2637 const char *longname;
2638 int priority;
2639 int nargs;
2640 };
2641
2642 static const struct standard_args standard_args[] =
2643 {
2644 { "-version", "--version", 150, 0 },
2645 #ifdef HAVE_PDUMPER
2646 { "-fingerprint", "--fingerprint", 140, 0 },
2647 #endif
2648 { "-chdir", "--chdir", 130, 1 },
2649 { "-t", "--terminal", 120, 1 },
2650 { "-nw", "--no-window-system", 110, 0 },
2651 { "-nw", "--no-windows", 110, 0 },
2652 { "-batch", "--batch", 100, 0 },
2653 { "-script", "--script", 100, 1 },
2654 { "-daemon", "--daemon", 99, 0 },
2655 { "-bg-daemon", "--bg-daemon", 99, 0 },
2656 { "-fg-daemon", "--fg-daemon", 99, 0 },
2657 { "-help", "--help", 90, 0 },
2658 { "-nl", "--no-loadup", 70, 0 },
2659 { "-nsl", "--no-site-lisp", 65, 0 },
2660 { "-no-build-details", "--no-build-details", 63, 0 },
2661 #ifdef HAVE_MODULES
2662 { "-module-assertions", "--module-assertions", 62, 0 },
2663 #endif
2664
2665 { "-d", "--display", 60, 1 },
2666 { "-display", 0, 60, 1 },
2667
2668
2669 { "-Q", "--quick", 55, 0 },
2670 { "-quick", 0, 55, 0 },
2671 { "-x", 0, 55, 0 },
2672 { "-q", "--no-init-file", 50, 0 },
2673 { "-no-init-file", 0, 50, 0 },
2674 { "-init-directory", "--init-directory", 30, 1 },
2675 { "-no-x-resources", "--no-x-resources", 40, 0 },
2676 { "-no-site-file", "--no-site-file", 40, 0 },
2677 { "-no-comp-spawn", "--no-comp-spawn", 60, 0 },
2678 { "-u", "--user", 30, 1 },
2679 { "-user", 0, 30, 1 },
2680 { "-debug-init", "--debug-init", 20, 0 },
2681 { "-iconic", "--iconic", 15, 0 },
2682 { "-D", "--basic-display", 12, 0},
2683 { "-basic-display", 0, 12, 0},
2684 { "-nbc", "--no-blinking-cursor", 12, 0 },
2685
2686 { "-nbi", "--no-bitmap-icon", 10, 0 },
2687 { "-bg", "--background-color", 10, 1 },
2688 { "-background", 0, 10, 1 },
2689 { "-fg", "--foreground-color", 10, 1 },
2690 { "-foreground", 0, 10, 1 },
2691 { "-bd", "--border-color", 10, 1 },
2692 { "-bw", "--border-width", 10, 1 },
2693 { "-ib", "--internal-border", 10, 1 },
2694 { "-ms", "--mouse-color", 10, 1 },
2695 { "-cr", "--cursor-color", 10, 1 },
2696 { "-fn", "--font", 10, 1 },
2697 { "-font", 0, 10, 1 },
2698 { "-fs", "--fullscreen", 10, 0 },
2699 { "-fw", "--fullwidth", 10, 0 },
2700 { "-fh", "--fullheight", 10, 0 },
2701 { "-mm", "--maximized", 10, 0 },
2702 { "-g", "--geometry", 10, 1 },
2703 { "-geometry", 0, 10, 1 },
2704 { "-T", "--title", 10, 1 },
2705 { "-title", 0, 10, 1 },
2706 { "-name", "--name", 10, 1 },
2707 { "-xrm", "--xrm", 10, 1 },
2708 { "-parent-id", "--parent-id", 10, 1 },
2709 { "-r", "--reverse-video", 5, 0 },
2710 { "-rv", 0, 5, 0 },
2711 { "-reverse", 0, 5, 0 },
2712 { "-hb", "--horizontal-scroll-bars", 5, 0 },
2713 { "-vb", "--vertical-scroll-bars", 5, 0 },
2714 { "-color", "--color", 5, 0},
2715 { "-no-splash", "--no-splash", 3, 0 },
2716 { "-no-desktop", "--no-desktop", 3, 0 },
2717
2718
2719 { "-temacs", "--temacs", 1, 1 },
2720 #ifdef HAVE_PDUMPER
2721 { "-dump-file", "--dump-file", 1, 1 },
2722 #endif
2723 #if SECCOMP_USABLE
2724 { "-seccomp", "--seccomp", 1, 1 },
2725 #endif
2726 #ifdef HAVE_NS
2727 { "-NSAutoLaunch", 0, 5, 1 },
2728 { "-NXAutoLaunch", 0, 5, 1 },
2729 { "-_NSMachLaunch", 0, 85, 1 },
2730 { "-MachLaunch", 0, 85, 1 },
2731 { "-macosx", 0, 85, 0 },
2732 { "-NSHost", 0, 85, 1 },
2733 #endif
2734
2735
2736 { "-L", "--directory", 0, 1 },
2737 { "-directory", 0, 0, 1 },
2738 { "-l", "--load", 0, 1 },
2739 { "-load", 0, 0, 1 },
2740
2741
2742
2743
2744 { "-scriptload", NULL, 0, 1 },
2745 { "-f", "--funcall", 0, 1 },
2746 { "-funcall", 0, 0, 1 },
2747 { "-eval", "--eval", 0, 1 },
2748 { "-execute", "--execute", 0, 1 },
2749 { "-find-file", "--find-file", 0, 1 },
2750 { "-visit", "--visit", 0, 1 },
2751 { "-file", "--file", 0, 1 },
2752 { "-insert", "--insert", 0, 1 },
2753 #ifdef HAVE_NS
2754 { "-NXOpen", 0, 0, 1 },
2755 { "-NXOpenTemp", 0, 0, 1 },
2756 { "-NSOpen", 0, 0, 1 },
2757 { "-NSOpenTemp", 0, 0, 1 },
2758 { "-GSFilePath", 0, 0, 1 },
2759 #endif
2760
2761 { "-kill", "--kill", -10, 0 },
2762 };
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772 static void
2773 sort_args (int argc, char **argv)
2774 {
2775 char **new = xmalloc (argc * sizeof *new);
2776
2777
2778
2779
2780
2781 int *options = xnmalloc (argc, sizeof *options);
2782 int *priority = xnmalloc (argc, sizeof *priority);
2783 int to = 1;
2784 int incoming_used = 1;
2785 int from;
2786 int i;
2787
2788
2789
2790 for (from = 1; from < argc; from++)
2791 {
2792 options[from] = -1;
2793 priority[from] = 0;
2794 if (argv[from][0] == '-')
2795 {
2796 int match;
2797
2798
2799
2800 if (argv[from][1] == '-' && argv[from][2] == 0)
2801 {
2802
2803 for (; from < argc; from++)
2804 {
2805 priority[from] = -100;
2806 options[from] = -1;
2807 }
2808 break;
2809 }
2810
2811
2812 for (i = 0; i < ARRAYELTS (standard_args); i++)
2813 if (!strcmp (argv[from], standard_args[i].name))
2814 {
2815 options[from] = standard_args[i].nargs;
2816 priority[from] = standard_args[i].priority;
2817 if (from + standard_args[i].nargs >= argc)
2818 fatal ("Option '%s' requires an argument\n", argv[from]);
2819 from += standard_args[i].nargs;
2820 goto done;
2821 }
2822
2823
2824
2825
2826 if (argv[from][1] == '-')
2827 {
2828 char const *equals = strchr (argv[from], '=');
2829 ptrdiff_t thislen =
2830 equals ? equals - argv[from] : strlen (argv[from]);
2831
2832 match = -1;
2833
2834 for (i = 0; i < ARRAYELTS (standard_args); i++)
2835 if (standard_args[i].longname
2836 && !strncmp (argv[from], standard_args[i].longname,
2837 thislen))
2838 {
2839 if (match == -1)
2840 match = i;
2841 else
2842 match = -2;
2843 }
2844
2845
2846 if (match >= 0)
2847 {
2848 options[from] = standard_args[match].nargs;
2849 priority[from] = standard_args[match].priority;
2850
2851
2852 if (equals != 0)
2853 options[from] = 0;
2854 if (from + options[from] >= argc)
2855 fatal ("Option '%s' requires an argument\n", argv[from]);
2856 from += options[from];
2857 }
2858 else if (match == -2)
2859 {
2860
2861
2862 fprintf (stderr, "Option '%s' matched multiple standard arguments\n", argv[from]);
2863 }
2864
2865 }
2866 done: ;
2867 }
2868 }
2869
2870
2871 new[0] = argv[0];
2872 while (incoming_used < argc)
2873 {
2874 int best = -1;
2875 int best_priority = -9999;
2876
2877
2878
2879 for (from = 1; from < argc; from++)
2880 {
2881 if (argv[from] != 0 && priority[from] > best_priority)
2882 {
2883 best_priority = priority[from];
2884 best = from;
2885 }
2886
2887 if (options[from] > 0)
2888 from += options[from];
2889 }
2890
2891 if (best < 0)
2892 emacs_abort ();
2893
2894
2895
2896 if (! (options[best] == 0
2897 && ! strcmp (new[to - 1], argv[best])))
2898 {
2899 new[to++] = argv[best];
2900 for (i = 0; i < options[best]; i++)
2901 new[to++] = argv[best + i + 1];
2902 }
2903
2904 incoming_used += 1 + (options[best] > 0 ? options[best] : 0);
2905
2906
2907 argv[best] = 0;
2908 for (i = 0; i < options[best]; i++)
2909 argv[best + i + 1] = 0;
2910 }
2911
2912
2913 while (to < argc)
2914 new[to++] = 0;
2915
2916 memcpy (argv, new, sizeof (char *) * argc);
2917
2918 xfree (options);
2919 xfree (new);
2920 xfree (priority);
2921 }
2922
2923 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 2, "P",
2924 doc:
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940 attributes: noreturn)
2941 (Lisp_Object arg, Lisp_Object restart)
2942 {
2943 int exit_code;
2944
2945 #ifndef WINDOWSNT
2946
2947
2948 if (!NILP (restart)
2949
2950
2951
2952 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
2953 && !android_init_gui
2954 #endif
2955 )
2956 {
2957
2958
2959 if (initial_argc < 1)
2960 error ("No command line arguments known; unable to re-execute Emacs");
2961
2962
2963 if (!initial_emacs_executable)
2964 error ("Unknown Emacs executable");
2965
2966 if (!file_access_p (initial_emacs_executable, F_OK))
2967 error ("Emacs executable \"%s\" can't be found", initial_argv[0]);
2968 }
2969 #endif
2970
2971 #ifdef HAVE_LIBSYSTEMD
2972
2973
2974 if (daemon_type == -1)
2975 sd_notify(0, "STOPPING=1");
2976 #endif
2977
2978
2979
2980 waiting_for_input = 0;
2981 if (!NILP (find_symbol_value (Qkill_emacs_hook)))
2982 {
2983 if (noninteractive)
2984 safe_run_hooks (Qkill_emacs_hook);
2985 else
2986 call1 (Qrun_hook_query_error_with_timeout, Qkill_emacs_hook);
2987 }
2988
2989 #ifdef HAVE_X_WINDOWS
2990
2991 x_clipboard_manager_save_all ();
2992 #endif
2993
2994 shut_down_emacs (0, (STRINGP (arg) && !feof (stdin)) ? arg : Qnil);
2995
2996 #ifdef HAVE_NS
2997 ns_release_autorelease_pool (ns_pool);
2998 #endif
2999
3000
3001
3002
3003 if (STRINGP (Vauto_save_list_file_name))
3004 {
3005 Lisp_Object listfile;
3006 listfile = Fexpand_file_name (Vauto_save_list_file_name, Qnil);
3007 emacs_unlink (SSDATA (listfile));
3008 }
3009
3010 #ifdef HAVE_NATIVE_COMP
3011 eln_load_path_final_clean_up ();
3012 #endif
3013
3014 if (!NILP (restart))
3015 {
3016 turn_on_atimers (false);
3017 #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
3018
3019
3020
3021 if (android_init_gui)
3022 android_restart_emacs ();
3023 #endif
3024 #ifdef WINDOWSNT
3025 if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0)
3026 #else
3027 initial_argv[0] = initial_emacs_executable;
3028 if (execvp (*initial_argv, initial_argv) < 1)
3029 #endif
3030 emacs_perror ("Unable to re-execute Emacs");
3031 }
3032
3033 if (FIXNUMP (arg))
3034 exit_code = (XFIXNUM (arg) < 0
3035 ? XFIXNUM (arg) | INT_MIN
3036 : XFIXNUM (arg) & INT_MAX);
3037 else
3038 exit_code = EXIT_SUCCESS;
3039 exit (exit_code);
3040 }
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054 void
3055 shut_down_emacs (int sig, Lisp_Object stuff)
3056 {
3057
3058 Vrun_hooks = Qnil;
3059
3060
3061 Vinhibit_redisplay = Qt;
3062
3063
3064 #if !defined DOS_NT && !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
3065 pid_t tpgrp = tcgetpgrp (STDIN_FILENO);
3066 if (tpgrp != -1 && tpgrp == getpgrp ())
3067 {
3068 reset_all_sys_modes ();
3069 if (sig && sig != SIGTERM)
3070 {
3071 #ifdef HAVE_HAIKU
3072 if (haiku_debug_on_fatal_error)
3073 debugger ("Fatal error in Emacs");
3074 #endif
3075
3076
3077
3078 static char const fmt[] = "Fatal error %d: ";
3079 char buf[max ((sizeof fmt - sizeof "%d"
3080 + INT_STRLEN_BOUND (int) + 1),
3081 min (PIPE_BUF, MAX_ALLOCA))];
3082 char const *sig_desc = safe_strsignal (sig);
3083 size_t sig_desclen = strlen (sig_desc);
3084 int nlen = sprintf (buf, fmt, sig);
3085 if (nlen + sig_desclen < sizeof buf - 1)
3086 {
3087 char *p = mempcpy (buf + nlen, sig_desc, sig_desclen);
3088 *p++ = '\n';
3089 emacs_write (STDERR_FILENO, buf, p - buf);
3090 }
3091 else
3092 {
3093 emacs_write (STDERR_FILENO, buf, nlen);
3094 emacs_write (STDERR_FILENO, sig_desc, sig_desclen);
3095 emacs_write (STDERR_FILENO, "\n", 1);
3096 }
3097 }
3098 }
3099 #else
3100 fflush (stdout);
3101 reset_all_sys_modes ();
3102 #endif
3103
3104 stuff_buffered_input (stuff);
3105
3106 inhibit_sentinels = 1;
3107 kill_buffer_processes (Qnil);
3108 Fdo_auto_save (Qt, Qnil);
3109
3110 unlock_all_files ();
3111
3112
3113
3114 unrequest_sigio ();
3115
3116
3117
3118 if (sig == 0 || sig == SIGTERM)
3119 {
3120 check_glyph_memory ();
3121 check_message_stack ();
3122 }
3123
3124 #ifdef HAVE_NATIVE_COMP
3125 eln_load_path_final_clean_up ();
3126 #endif
3127
3128 #ifdef MSDOS
3129 dos_cleanup ();
3130 #endif
3131
3132 #ifdef HAVE_NS
3133 ns_term_shutdown (sig);
3134 #endif
3135
3136 #ifdef HAVE_LIBXML2
3137 xml_cleanup_parser ();
3138 #endif
3139
3140 #ifdef WINDOWSNT
3141 term_ntproc (0);
3142 #endif
3143 }
3144
3145
3146
3147 #ifdef HAVE_UNEXEC
3148
3149 #include "unexec.h"
3150
3151 DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
3152 doc:
3153
3154
3155
3156 )
3157 (Lisp_Object filename, Lisp_Object symfile)
3158 {
3159 Lisp_Object tem;
3160 Lisp_Object symbol;
3161 specpdl_ref count = SPECPDL_INDEX ();
3162
3163 check_pure_size ();
3164
3165 if (! noninteractive)
3166 error ("Dumping Emacs works only in batch mode");
3167
3168 if (dumped_with_unexec_p ())
3169 error ("Emacs can be dumped using unexec only once");
3170
3171 if (definitely_will_not_unexec_p ())
3172 error ("This Emacs instance was not started in temacs mode");
3173
3174 # if defined GNU_LINUX && defined HAVE_UNEXEC
3175
3176
3177 # define MAX_HEAP_BSS_DIFF (1024 * 1024)
3178
3179 if (heap_bss_diff > MAX_HEAP_BSS_DIFF)
3180 fprintf (stderr,
3181 ("**************************************************\n"
3182 "Warning: Your system has a gap between BSS and the\n"
3183 "heap (%"PRIuMAX" bytes). This usually means that exec-shield\n"
3184 "or something similar is in effect. The dump may\n"
3185 "fail because of this. See the section about\n"
3186 "exec-shield in etc/PROBLEMS for more information.\n"
3187 "**************************************************\n"),
3188 heap_bss_diff);
3189 # endif
3190
3191
3192
3193
3194 symbol = intern ("command-line-processed");
3195 specbind (symbol, Qnil);
3196
3197 CHECK_STRING (filename);
3198 filename = Fexpand_file_name (filename, Qnil);
3199 filename = ENCODE_FILE (filename);
3200 if (!NILP (symfile))
3201 {
3202 CHECK_STRING (symfile);
3203 if (SCHARS (symfile))
3204 {
3205 symfile = Fexpand_file_name (symfile, Qnil);
3206 symfile = ENCODE_FILE (symfile);
3207 }
3208 }
3209
3210 tem = Vpurify_flag;
3211 Vpurify_flag = Qnil;
3212
3213 # ifdef HYBRID_MALLOC
3214 {
3215 static char const fmt[] = "%d of %d static heap bytes used";
3216 char buf[sizeof fmt + 2 * (INT_STRLEN_BOUND (int) - 2)];
3217 int max_usage = max_bss_sbrk_ptr - bss_sbrk_buffer;
3218 sprintf (buf, fmt, max_usage, STATIC_HEAP_SIZE);
3219
3220 message1_nolog (buf);
3221 }
3222 # endif
3223
3224 fflush (stdout);
3225
3226
3227 # if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC && !defined WINDOWSNT
3228
3229
3230 memory_warnings (my_edata, malloc_warning);
3231 # endif
3232
3233 struct gflags old_gflags = gflags;
3234 gflags.will_dump_ = false;
3235 gflags.will_dump_with_unexec_ = false;
3236 gflags.dumped_with_unexec_ = true;
3237
3238 alloc_unexec_pre ();
3239
3240 unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
3241
3242 alloc_unexec_post ();
3243
3244 gflags = old_gflags;
3245
3246 # ifdef WINDOWSNT
3247 Vlibrary_cache = Qnil;
3248 # endif
3249
3250 Vpurify_flag = tem;
3251
3252 return unbind_to (count, Qnil);
3253 }
3254
3255 #endif
3256
3257
3258 #if HAVE_SETLOCALE
3259
3260 void
3261 fixup_locale (void)
3262 {
3263
3264
3265 setlocale (LC_NUMERIC, "C");
3266 }
3267
3268
3269
3270 static void
3271 synchronize_locale (int category, Lisp_Object *plocale, Lisp_Object desired_locale)
3272 {
3273 if (! EQ (*plocale, desired_locale))
3274 {
3275 *plocale = desired_locale;
3276 char const *locale_string
3277 = STRINGP (desired_locale) ? SSDATA (desired_locale) : "";
3278 # ifdef WINDOWSNT
3279
3280
3281
3282
3283
3284
3285 setlocale (LC_ALL, locale_string);
3286 fixup_locale ();
3287 # else
3288 setlocale (category, locale_string);
3289 # endif
3290 }
3291 }
3292
3293 static Lisp_Object Vprevious_system_time_locale;
3294
3295
3296 void
3297 synchronize_system_time_locale (void)
3298 {
3299 synchronize_locale (LC_TIME, &Vprevious_system_time_locale,
3300 Vsystem_time_locale);
3301 }
3302
3303 # ifdef LC_MESSAGES
3304 static Lisp_Object Vprevious_system_messages_locale;
3305 # endif
3306
3307
3308
3309 void
3310 synchronize_system_messages_locale (void)
3311 {
3312 # ifdef LC_MESSAGES
3313 synchronize_locale (LC_MESSAGES, &Vprevious_system_messages_locale,
3314 Vsystem_messages_locale);
3315 # endif
3316 }
3317 #endif
3318
3319
3320
3321 char *
3322 emacs_strerror (int error_number)
3323 {
3324 synchronize_system_messages_locale ();
3325 return strerror (error_number);
3326 }
3327
3328
3329 Lisp_Object
3330 decode_env_path (const char *evarname, const char *defalt, bool empty)
3331 {
3332 const char *path, *p;
3333 Lisp_Object lpath, element, tem;
3334 #ifdef NS_SELF_CONTAINED
3335 void *autorelease = NULL;
3336 #endif
3337
3338
3339 Lisp_Object empty_element = empty ? Qnil : build_string (".");
3340 #ifdef WINDOWSNT
3341 bool defaulted = 0;
3342 static const char *emacs_dir_env = "%emacs_dir%/";
3343 const size_t emacs_dir_len = strlen (emacs_dir_env);
3344 const char *edir = egetenv ("emacs_dir");
3345 char emacs_dir[MAX_UTF8_PATH];
3346
3347
3348
3349
3350 if (edir)
3351 filename_from_ansi (edir, emacs_dir);
3352 #endif
3353
3354
3355
3356
3357 if (evarname != 0)
3358 path = getenv (evarname);
3359 else
3360 path = 0;
3361 if (!path)
3362 {
3363 #ifdef NS_SELF_CONTAINED
3364
3365 autorelease = ns_alloc_autorelease_pool ();
3366 path = ns_relocate (defalt);
3367 #else
3368 path = defalt;
3369 #endif
3370 #ifdef WINDOWSNT
3371 defaulted = 1;
3372 #endif
3373 }
3374 #ifdef DOS_NT
3375
3376 if (path)
3377 {
3378 char *path_copy;
3379
3380 #ifdef WINDOWSNT
3381 char *path_utf8, *q, *d;
3382 int cnv_result;
3383
3384
3385 p = path_copy = alloca (strlen (path) + 1);
3386 strcpy (path_copy, path);
3387 d = path_utf8 = alloca (4 * strlen (path) + 1);
3388 *d = '\0';
3389 do {
3390 q = _mbschr (p, SEPCHAR);
3391 if (q)
3392 *q = '\0';
3393 cnv_result = filename_from_ansi (p, d);
3394 if (q)
3395 {
3396 *q++ = SEPCHAR;
3397 p = q;
3398
3399
3400
3401 if (cnv_result == 0)
3402 {
3403 d += strlen (d);
3404 *d++ = SEPCHAR;
3405 }
3406 }
3407 else if (cnv_result != 0 && d > path_utf8)
3408 d[-1] = '\0';
3409 } while (q);
3410 path_copy = path_utf8;
3411 #else
3412 path_copy = alloca (strlen (path) + 1);
3413 strcpy (path_copy, path);
3414 #endif
3415 dostounix_filename (path_copy);
3416 path = path_copy;
3417 }
3418 #endif
3419 lpath = Qnil;
3420 while (1)
3421 {
3422 p = strchr (path, SEPCHAR);
3423 if (!p)
3424 p = path + strlen (path);
3425 element = ((p - path) ? make_unibyte_string (path, p - path)
3426 : empty_element);
3427 if (! NILP (element))
3428 {
3429 #ifdef WINDOWSNT
3430
3431
3432 if (edir && defaulted
3433 && strncmp (path, emacs_dir_env, emacs_dir_len) == 0)
3434 element = Fexpand_file_name (Fsubstring
3435 (element,
3436 make_fixnum (emacs_dir_len),
3437 Qnil),
3438 build_unibyte_string (emacs_dir));
3439 #endif
3440
3441
3442
3443 tem = Ffind_file_name_handler (element, Qt);
3444
3445
3446
3447 if (SYMBOLP (tem))
3448 {
3449 Lisp_Object prop;
3450 prop = Fget (tem, intern ("safe-magic"));
3451 if (! NILP (prop))
3452 tem = Qnil;
3453 }
3454
3455 if (! NILP (tem))
3456 {
3457 AUTO_STRING (slash_colon, "/:");
3458 element = concat2 (slash_colon, element);
3459 }
3460 }
3461
3462 lpath = Fcons (element, lpath);
3463 if (*p)
3464 path = p + 1;
3465 else
3466 break;
3467 }
3468
3469 #ifdef NS_SELF_CONTAINED
3470 if (autorelease)
3471 ns_release_autorelease_pool (autorelease);
3472 #endif
3473 return Fnreverse (lpath);
3474 }
3475
3476 DEFUN ("daemonp", Fdaemonp, Sdaemonp, 0, 0, 0,
3477 doc:
3478 )
3479 (void)
3480 {
3481 if (IS_DAEMON)
3482 if (daemon_name)
3483 return build_string (daemon_name);
3484 else
3485 return Qt;
3486 else
3487 return Qnil;
3488 }
3489
3490 DEFUN ("daemon-initialized", Fdaemon_initialized, Sdaemon_initialized, 0, 0, 0,
3491 doc:
3492
3493 )
3494 (void)
3495 {
3496 bool err = 0;
3497
3498 if (!IS_DAEMON)
3499 error ("This function can only be called if emacs is run as a daemon");
3500
3501 if (!DAEMON_RUNNING)
3502 error ("The daemon has already been initialized");
3503
3504 if (NILP (Vafter_init_time))
3505 error ("This function can only be called after loading the init files");
3506 #ifndef WINDOWSNT
3507
3508 if (daemon_type == 1)
3509 {
3510 #ifdef HAVE_LIBSYSTEMD
3511 sd_notify(0, "READY=1");
3512 #endif
3513 }
3514
3515 if (daemon_type == 2)
3516 {
3517 int nfd;
3518
3519
3520 nfd = emacs_open_noquit ("/dev/null", O_RDWR, 0);
3521 err |= nfd < 0;
3522 err |= dup2 (nfd, STDIN_FILENO) < 0;
3523 err |= dup2 (nfd, STDOUT_FILENO) < 0;
3524 err |= dup2 (nfd, STDERR_FILENO) < 0;
3525 err |= emacs_close (nfd) != 0;
3526
3527
3528
3529
3530
3531
3532
3533
3534 err |= write (daemon_pipe[1], "\n", 1) < 0;
3535 err |= emacs_close (daemon_pipe[1]) != 0;
3536 }
3537
3538
3539 daemon_type = -daemon_type;
3540
3541 #else
3542
3543 err |= SetEvent (w32_daemon_event) == 0;
3544 err |= CloseHandle (w32_daemon_event) == 0;
3545
3546 w32_daemon_event = INVALID_HANDLE_VALUE;
3547 #endif
3548
3549 if (err)
3550 error ("I/O error during daemon initialization");
3551 return Qt;
3552 }
3553
3554 void
3555 syms_of_emacs (void)
3556 {
3557 DEFSYM (Qfile_name_handler_alist, "file-name-handler-alist");
3558 DEFSYM (Qrisky_local_variable, "risky-local-variable");
3559 DEFSYM (Qkill_emacs, "kill-emacs");
3560 DEFSYM (Qkill_emacs_hook, "kill-emacs-hook");
3561 DEFSYM (Qrun_hook_query_error_with_timeout,
3562 "run-hook-query-error-with-timeout");
3563
3564 #ifdef HAVE_UNEXEC
3565 defsubr (&Sdump_emacs);
3566 #endif
3567
3568 defsubr (&Skill_emacs);
3569
3570 defsubr (&Sinvocation_name);
3571 defsubr (&Sinvocation_directory);
3572 defsubr (&Sdaemonp);
3573 defsubr (&Sdaemon_initialized);
3574
3575 DEFVAR_LISP ("command-line-args", Vcommand_line_args,
3576 doc:
3577 );
3578
3579 DEFVAR_LISP ("system-type", Vsystem_type,
3580 doc:
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592 );
3593 Vsystem_type = intern_c_string (SYSTEM_TYPE);
3594
3595
3596 DEFVAR_LISP ("system-configuration", Vsystem_configuration,
3597 doc: );
3598 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
3599
3600 DEFVAR_LISP ("system-configuration-options", Vsystem_configuration_options,
3601 doc: );
3602 Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS);
3603
3604 DEFVAR_LISP ("system-configuration-features", Vsystem_configuration_features,
3605 doc:
3606
3607
3608
3609
3610 );
3611 Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES);
3612
3613 DEFVAR_BOOL ("noninteractive", noninteractive1,
3614 doc: );
3615
3616 DEFVAR_LISP ("kill-emacs-hook", Vkill_emacs_hook,
3617 doc:
3618
3619
3620
3621
3622
3623
3624 );
3625 Vkill_emacs_hook = Qnil;
3626
3627 DEFVAR_LISP ("path-separator", Vpath_separator,
3628 doc:
3629 );
3630 {
3631 char c = SEPCHAR;
3632 Vpath_separator = make_string (&c, 1);
3633 }
3634
3635 DEFVAR_LISP ("invocation-name", Vinvocation_name,
3636 doc:
3637 );
3638
3639 DEFVAR_LISP ("invocation-directory", Vinvocation_directory,
3640 doc:
3641 );
3642
3643 DEFVAR_LISP ("installation-directory", Vinstallation_directory,
3644 doc:
3645
3646
3647
3648
3649 );
3650 Vinstallation_directory = Qnil;
3651
3652 DEFVAR_LISP ("system-messages-locale", Vsystem_messages_locale,
3653 doc: );
3654 Vsystem_messages_locale = Qnil;
3655 #ifdef LC_MESSAGES
3656 Vprevious_system_messages_locale = Qnil;
3657 staticpro (&Vprevious_system_messages_locale);
3658 #endif
3659
3660 DEFVAR_LISP ("system-time-locale", Vsystem_time_locale,
3661 doc: );
3662 Vsystem_time_locale = Qnil;
3663 Vprevious_system_time_locale = Qnil;
3664 staticpro (&Vprevious_system_time_locale);
3665
3666 DEFVAR_LISP ("before-init-time", Vbefore_init_time,
3667 doc: );
3668 Vbefore_init_time = Qnil;
3669
3670 DEFVAR_LISP ("after-init-time", Vafter_init_time,
3671 doc:
3672 );
3673 Vafter_init_time = Qnil;
3674
3675 DEFVAR_BOOL ("inhibit-x-resources", inhibit_x_resources,
3676 doc: );
3677 inhibit_x_resources = 0;
3678
3679 DEFVAR_LISP ("emacs-copyright", Vemacs_copyright,
3680 doc: );
3681 Vemacs_copyright = build_string (emacs_copyright);
3682
3683 DEFVAR_LISP ("emacs-version", Vemacs_version,
3684 doc:
3685
3686
3687
3688
3689 );
3690 Vemacs_version = build_string (emacs_version);
3691
3692 DEFVAR_LISP ("report-emacs-bug-address", Vreport_emacs_bug_address,
3693 doc: );
3694 Vreport_emacs_bug_address = build_string (emacs_bugreport);
3695
3696 DEFVAR_LISP ("dump-mode", Vdump_mode,
3697 doc: );
3698
3699 DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist,
3700 doc:
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713 );
3714 #ifdef WINDOWSNT
3715
3716
3717
3718 if (will_dump_p ())
3719 Vdynamic_library_alist = list1 (list2 (Qgccjit,
3720 build_string ("libgccjit-0.dll")));
3721 else
3722 Vdynamic_library_alist = Qnil;
3723 #else
3724 Vdynamic_library_alist = Qnil;
3725 #endif
3726 Fput (intern_c_string ("dynamic-library-alist"), Qrisky_local_variable, Qt);
3727
3728 #ifdef WINDOWSNT
3729 Vlibrary_cache = Qnil;
3730 staticpro (&Vlibrary_cache);
3731 #endif
3732 }