diff options
Diffstat (limited to 'src/sysdep.c')
-rw-r--r-- | src/sysdep.c | 286 |
1 files changed, 267 insertions, 19 deletions
diff --git a/src/sysdep.c b/src/sysdep.c index ef2dc127e2a..cf2985b4b89 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -36,7 +36,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <utimens.h> #include "lisp.h" -#include "sheap.h" #include "sysselect.h" #include "blockinput.h" @@ -134,6 +133,14 @@ int _cdecl _spawnlp (int, const char *, const char *, ...); # include <sys/socket.h> #endif +#ifdef HAVE_ANDROID +#include "android.h" +#endif + +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY +#include "sfntfont.h" +#endif + /* Declare here, including term.h is problematic on some systems. */ extern void tputs (const char *, int, int (*)(int)); @@ -252,7 +259,7 @@ init_standard_fds (void) /* Set buferr if possible on platforms defining _PC_PIPE_BUF, as they support the notion of atomic writes to pipes. */ #ifdef _PC_PIPE_BUF - buferr = fdopen (STDERR_FILENO, "w"); + buferr = emacs_fdopen (STDERR_FILENO, "w"); if (buferr) setvbuf (buferr, NULL, _IOLBF, 0); #endif @@ -790,6 +797,7 @@ init_sigio (int fd) #endif } +#ifndef HAVE_ANDROID #ifndef DOS_NT #ifdef F_SETOWN static void @@ -801,6 +809,7 @@ reset_sigio (int fd) } #endif /* F_SETOWN */ #endif +#endif void request_sigio (void) @@ -972,6 +981,8 @@ narrow_foreground_group (int fd) tcsetpgrp_without_stopping (fd, getpid ()); } +#ifndef HAVE_ANDROID + /* Set the tty to our original foreground group. */ static void widen_foreground_group (int fd) @@ -979,6 +990,9 @@ widen_foreground_group (int fd) if (inherited_pgroup && setpgid (0, inherited_pgroup) == 0) tcsetpgrp_without_stopping (fd, inherited_pgroup); } + +#endif + /* Getting and setting emacs_tty structures. */ @@ -1496,6 +1510,8 @@ reset_sys_modes (struct tty_display_info *tty_out) fflush (stdout); return; } + +#ifndef HAVE_ANDROID if (!tty_out->term_initted) return; @@ -1552,6 +1568,7 @@ reset_sys_modes (struct tty_display_info *tty_out) #endif widen_foreground_group (fileno (tty_out->input)); +#endif } #ifdef HAVE_PTYS @@ -1802,6 +1819,40 @@ handle_arith_signal (int sig) xsignal0 (Qarith_error); } +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP + +static void +handle_sigbus (int sig, siginfo_t *siginfo, void *arg) +{ + /* If this arrives during sfntfont_open, then Emacs may be + screwed. */ + + if (sfntfont_detect_sigbus (siginfo->si_addr)) + return; + + handle_fatal_signal (sig); +} + +/* Try to set up SIGBUS handling for the sfnt font driver. + Value is 1 upon failure, 0 otherwise. */ + +static int +init_sigbus (void) +{ + struct sigaction sa; + + sigfillset (&sa.sa_mask); + sa.sa_sigaction = handle_sigbus; + sa.sa_flags = SA_SIGINFO; + + if (sigaction (SIGBUS, &sa, NULL)) + return 1; + + return 0; +} + +#endif + #if defined HAVE_STACK_OVERFLOW_HANDLING && !defined WINDOWSNT /* Alternate stack used by SIGSEGV handler below. */ @@ -1866,6 +1917,8 @@ stack_overflow (siginfo_t *siginfo) return 0 <= top - addr && top - addr < (bot - top) >> LG_STACK_HEURISTIC; } +/* Signal handler for SIGSEGV before our new handler was installed. */ +static struct sigaction old_sigsegv_handler; /* Attempt to recover from SIGSEGV caused by C stack overflow. */ @@ -1884,6 +1937,15 @@ handle_sigsegv (int sig, siginfo_t *siginfo, void *arg) if (!fatal && stack_overflow (siginfo)) siglongjmp (return_to_command_loop, 1); +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY + /* Tombstones (crash reports with stack traces) won't be generated on + Android unless the original SIGSEGV handler is installed and the + signal is resent, such as by returning from the first signal + handler called. */ + sigaction (SIGSEGV, &old_sigsegv_handler, NULL); + return; +#endif /* HAVE_ANDROID && ANDROID_STUBIFY */ + /* Otherwise we can't do anything with this. */ deliver_fatal_thread_signal (sig); } @@ -1906,7 +1968,7 @@ init_sigsegv (void) sigfillset (&sa.sa_mask); sa.sa_sigaction = handle_sigsegv; sa.sa_flags = SA_SIGINFO | SA_ONSTACK | emacs_sigaction_flags (); - if (sigaction (SIGSEGV, &sa, NULL) < 0) + if (sigaction (SIGSEGV, &sa, &old_sigsegv_handler) < 0) return 0; return 1; @@ -2027,12 +2089,17 @@ init_signals (void) #endif /* __vax__ */ } + /* SIGUSR1 and SIGUSR2 are used internally by the android_select + function. */ +#if !defined HAVE_ANDROID #ifdef SIGUSR1 add_user_signal (SIGUSR1, "sigusr1"); #endif #ifdef SIGUSR2 add_user_signal (SIGUSR2, "sigusr2"); #endif +#endif + sigaction (SIGABRT, &thread_fatal_action, 0); #ifdef SIGPRE sigaction (SIGPRE, &thread_fatal_action, 0); @@ -2056,7 +2123,10 @@ init_signals (void) sigaction (SIGEMT, &thread_fatal_action, 0); #endif #ifdef SIGBUS - sigaction (SIGBUS, &thread_fatal_action, 0); +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP + if (init_sigbus ()) +#endif + sigaction (SIGBUS, &thread_fatal_action, 0); #endif if (!init_sigsegv ()) sigaction (SIGSEGV, &thread_fatal_action, 0); @@ -2313,7 +2383,8 @@ emacs_backtrace (int backtrace_limit) } } -#ifndef HAVE_NTGUI +#if !defined HAVE_NTGUI && !(defined HAVE_ANDROID \ + && !defined ANDROID_STUBIFY) void emacs_abort (void) { @@ -2335,11 +2406,20 @@ int emacs_fstatat (int dirfd, char const *filename, void *st, int flags) { int r; - while ((r = fstatat (dirfd, filename, st, flags)) != 0 && errno == EINTR) +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + while ((r = fstatat (dirfd, filename, st, flags)) != 0 + && errno == EINTR) + maybe_quit (); +#else + while ((r = android_fstatat (dirfd, filename, st, flags)) != 0 + && errno == EINTR) maybe_quit (); +#endif return r; } +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + static int sys_openat (int dirfd, char const *file, int oflags, int mode) { @@ -2354,6 +2434,28 @@ sys_openat (int dirfd, char const *file, int oflags, int mode) #endif } +#endif + +int +sys_fstat (int fd, struct stat *statb) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return fstat (fd, statb); +#else + return android_fstat (fd, statb); +#endif +} + +int +sys_faccessat (int fd, const char *pathname, int mode, int flags) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return faccessat (fd, pathname, mode, flags); +#else + return android_faccessat (fd, pathname, mode, flags); +#endif +} + /* Assuming the directory DIRFD, open FILE for Emacs use, using open flags OFLAGS and mode MODE. Use binary I/O on systems that care about text vs binary I/O. @@ -2362,6 +2464,8 @@ sys_openat (int dirfd, char const *file, int oflags, int mode) Do not fail merely because the open was interrupted by a signal. Allow the user to quit. */ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + int emacs_openat (int dirfd, char const *file, int oflags, int mode) { @@ -2374,10 +2478,23 @@ emacs_openat (int dirfd, char const *file, int oflags, int mode) return fd; } +#endif + int emacs_open (char const *file, int oflags, int mode) { +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY + int fd; +#endif + +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) return emacs_openat (AT_FDCWD, file, oflags, mode); +#else + while ((fd = android_open (file, oflags, mode)) < 0 && errno == EINTR) + maybe_quit (); + + return fd; +#endif } /* Same as above, but doesn't allow the user to quit. */ @@ -2389,9 +2506,15 @@ emacs_open_noquit (char const *file, int oflags, int mode) if (! (oflags & O_TEXT)) oflags |= O_BINARY; oflags |= O_CLOEXEC; +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) do fd = open (file, oflags, mode); while (fd < 0 && errno == EINTR); +#else + do + fd = android_open (file, oflags, mode); + while (fd < 0 && errno == EINTR); +#endif return fd; } @@ -2422,7 +2545,7 @@ emacs_fopen (char const *file, char const *mode) } fd = emacs_open (file, omode | oflags | bflag, 0666); - return fd < 0 ? 0 : fdopen (fd, mode); + return fd < 0 ? 0 : emacs_fdopen (fd, mode); } /* Create a pipe for Emacs use. */ @@ -2441,6 +2564,8 @@ emacs_pipe (int fd[2]) For the background behind this mess, please see Austin Group defect 529 <https://austingroupbugs.net/view.php?id=529>. */ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + #ifndef POSIX_CLOSE_RESTART # define POSIX_CLOSE_RESTART 1 static int @@ -2467,6 +2592,8 @@ posix_close (int fd, int flag) } #endif +#endif + /* Close FD, retrying if interrupted. If successful, return 0; otherwise, return -1 and set errno to a non-EINTR value. Consider an EINPROGRESS error to be successful, as that's merely a signal @@ -2479,9 +2606,17 @@ posix_close (int fd, int flag) int emacs_close (int fd) { + int r; + while (1) { - int r = posix_close (fd, POSIX_CLOSE_RESTART); +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + r = posix_close (fd, POSIX_CLOSE_RESTART); +#else + r = android_close (fd) == 0 || errno == EINTR ? 0 : -1; +#define POSIX_CLOSE_RESTART 1 +#endif + if (r == 0) return r; if (!POSIX_CLOSE_RESTART || errno != EINTR) @@ -2492,6 +2627,106 @@ emacs_close (int fd) } } +/* Wrapper around fdopen. On Android, this calls `android_fclose' to + clear information associated with FD if necessary. */ + +FILE * +emacs_fdopen (int fd, const char *mode) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return fdopen (fd, mode); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_fdopen (fd, mode); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +/* Wrapper around fclose. On Android, this calls `android_fclose' to + clear information associated with the FILE's file descriptor if + necessary. */ + +#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY +int +emacs_fclose (FILE *stream) +{ + return android_fclose (stream); +} +#endif + +/* Wrappers around unlink, symlink, rename, renameat_noreplace, and + rmdir. These operations handle asset and content directories on + Android, and may return EINTR. */ + +int +emacs_unlink (const char *name) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return unlink (name); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_unlink (name); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +int +emacs_symlink (const char *target, const char *linkname) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return symlink (target, linkname); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_symlink (target, linkname); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +int +emacs_rmdir (const char *dirname) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return rmdir (dirname); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_rmdir (dirname); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +int +emacs_mkdir (const char *dirname, mode_t mode) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return mkdir (dirname, mode); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_mkdir (dirname, mode); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +int +emacs_renameat_noreplace (int srcfd, const char *src, + int dstfd, const char *dst) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return renameat_noreplace (srcfd, src, dstfd, dst); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_renameat_noreplace (srcfd, src, dstfd, dst); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +int +emacs_rename (const char *src, const char *dst) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return rename (src, dst); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_rename (src, dst); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + +int +emacs_fchmodat (int fd, const char *path, mode_t mode, int flags) +{ +#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) + return fchmodat (fd, path, mode, flags); +#else /* !defined HAVE_ANDROID || defined ANDROID_STUBIFY */ + return android_fchmodat (fd, path, mode, flags); +#endif /* !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY) */ +} + /* Maximum number of bytes to read or write in a single system call. This works around a serious bug in Linux kernels before 2.6.16; see <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>. @@ -2660,10 +2895,11 @@ emacs_perror (char const *message) int renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst) { -#if defined SYS_renameat2 && defined RENAME_NOREPLACE - return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE); -#elif defined CYGWIN && defined RENAME_NOREPLACE +#if HAVE_RENAMEAT2 && defined RENAME_NOREPLACE return renameat2 (srcfd, src, dstfd, dst, RENAME_NOREPLACE); +#elif defined SYS_renameat2 && defined RENAME_NOREPLACE + /* Linux kernel 3.15 (2014) or later, with glibc 2.27 (2018) or earlier. */ + return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE); #elif defined RENAME_EXCL return renameatx_np (srcfd, src, dstfd, dst, RENAME_EXCL); #else @@ -2735,6 +2971,17 @@ errwrite (void const *buf, ptrdiff_t nbuf) void close_output_streams (void) { + /* Android comes with some kind of ``file descriptor sanitizer'' + that aborts when stdout or stderr is closed. (bug#65340) + + Perform this unconditionally as long as __ANDROID__ is defined, + since the file descriptor sanitizer also applies to regular TTY + builds under Android. */ + +#ifdef __ANDROID__ + fflush (stderr); + fflush (stdout); +#else /* !__ANDROID__ */ if (close_stream (stdout) != 0) { emacs_perror ("Write error to standard output"); @@ -2748,6 +2995,7 @@ close_output_streams (void) ? fflush (stderr) != 0 || ferror (stderr) : close_stream (stderr) != 0)) _exit (EXIT_FAILURE); +#endif /* __ANDROID__ */ } #ifndef DOS_NT @@ -3204,7 +3452,7 @@ make_lisp_timeval (struct timeval t) #endif -#if defined (GNU_LINUX) || defined (CYGWIN) +#if defined (GNU_LINUX) || defined (CYGWIN) || defined __ANDROID__ static Lisp_Object time_from_jiffies (unsigned long long ticks, Lisp_Object hz, Lisp_Object form) @@ -3245,14 +3493,14 @@ get_up_time (void) Lisp_Object subsec = Fcons (make_fixnum (upfrac), make_fixnum (hz)); up = Ftime_add (sec, subsec); } - fclose (fup); + emacs_fclose (fup); } unblock_input (); return up; } -# ifdef GNU_LINUX +# if defined GNU_LINUX || defined __ANDROID__ #define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff) #define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12)) @@ -3293,12 +3541,12 @@ procfs_ttyname (int rdev) } } } - fclose (fdev); + emacs_fclose (fdev); } unblock_input (); return build_string (name); } -# endif /* GNU_LINUX */ +# endif /* GNU_LINUX || __ANDROID__ */ static uintmax_t procfs_get_total_memory (void) @@ -3335,7 +3583,7 @@ procfs_get_total_memory (void) } while (!done); - fclose (fmem); + emacs_fclose (fmem); } unblock_input (); return retval; @@ -3447,9 +3695,9 @@ system_process_attributes (Lisp_Object pid) attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (ppid)), attrs); attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pgrp)), attrs); attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (sess)), attrs); -# ifdef GNU_LINUX +# if defined GNU_LINUX || defined __ANDROID__ attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs); -# endif +# endif /* GNU_LINUX || __ANDROID__ */ attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (tpgid)), attrs); attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (minflt)), attrs); attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (majflt)), attrs); |