aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-11-17 20:00:16 +0200
committerEli Zaretskii2012-11-17 20:00:16 +0200
commitcf2d22b874ca2df0072e32ee641e8efffe4abd6d (patch)
tree1795142ec7861fc85c61adc90f03265b69041556 /src
parent3c4ca7155293ffc2d04708007131bcbc882d8913 (diff)
parent6ad30855c02908fdd99d9b11943719e185e65ee3 (diff)
downloademacs-cf2d22b874ca2df0072e32ee641e8efffe4abd6d.tar.gz
emacs-cf2d22b874ca2df0072e32ee641e8efffe4abd6d.zip
Merge from trunk.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog157
-rw-r--r--src/Makefile.in3
-rw-r--r--src/callproc.c12
-rw-r--r--src/charset.c2
-rw-r--r--src/conf_post.h4
-rw-r--r--src/editfns.c4
-rw-r--r--src/eval.c4
-rw-r--r--src/fileio.c184
-rw-r--r--src/lisp.h2
-rw-r--r--src/lread.c92
-rw-r--r--src/makefile.w32-in2
-rw-r--r--src/nsterm.m24
-rw-r--r--src/process.c72
-rw-r--r--src/sysdep.c13
-rw-r--r--src/term.c4
-rw-r--r--src/w32.c37
-rw-r--r--src/w32proc.c165
-rw-r--r--src/xdisp.c12
-rw-r--r--src/xfaces.c8
-rw-r--r--src/xrdb.c101
20 files changed, 546 insertions, 356 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e3be3f9149d..cea22d498ed 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,160 @@
12012-11-17 Eli Zaretskii <eliz@gnu.org>
2
3 * w32.c (faccessat): Pretend that directories have the execute bit
4 set. Emacs expects that, e.g., in files.el:cd-absolute.
5
6 * w32proc.c (create_child): Don't clip the PID of the child
7 process to fit into an Emacs integer, as this is no longer a
8 restriction.
9 (waitpid): Rename from sys_wait. Emulate a Posix 'waitpid' by
10 reaping only the process specified by PID argument, if that is
11 positive. Use PID instead of dead_child to know which process to
12 reap. Wait for the child to die only if WNOHANG is not in
13 OPTIONS.
14 (sys_select): Don't set dead_child.
15
16 * sysdep.c (wait_for_termination_1): Remove the WINDOWSNT portion,
17 as it is no longer needed.
18
19 * process.c (waitpid, WUNTRACED) [!WNOHANG]: Remove definitions,
20 no longer needed.
21 (record_child_status_change): Remove the setting of
22 record_at_most_one_child for the !WNOHANG case.
23
242012-11-17 Paul Eggert <eggert@cs.ucla.edu>
25
26 Fix problems in ns port found by static checking.
27 * nsterm.m: Include <pthread.h>, for pthread_mutex_lock etc.
28 (hold_event, setPosition:portion:whole:): Send SIGIO only to self,
29 not to process group.
30 (ns_select): Use emacs_write, not write, as that's more robust
31 in the presence of signals.
32 (fd_handler:): Check for read errors.
33
342012-11-16 Glenn Morris <rgm@gnu.org>
35
36 * editfns.c (Fmessage): Mention message-log-max. (Bug#12849)
37
382012-11-16 Stefan Monnier <monnier@iro.umontreal.ca>
39
40 * eval.c (Finteractive_p): Revert lexbind-merge mishap.
41
422012-11-16 Eli Zaretskii <eliz@gnu.org>
43
44 * w32proc.c (timer_loop): Make sure SuspendThread and ResumeThread
45 use the same value of thread handle.
46 (start_timer_thread): If the timer thread exited (due to error),
47 clean up by closing the two handles it used. Duplicate the caller
48 thread's handle here, so it gets duplicated only once, when
49 launching the timer thread. Set priority of the timer thread, not
50 the caller thread.
51 (getitimer): Don't duplicate the caller thread's handle here.
52 (Bug#12832)
53
542012-11-16 Jan Djärv <jan.h.d@swipnet.se>
55
56 * nsterm.m (hold_event): Send SIGIO to make sure ns_read_socket is
57 called (Bug#12834).
58
592012-11-16 Paul Eggert <eggert@cs.ucla.edu>
60
61 Remove no-longer-used pty_max_bytes variable.
62 * process.c (pty_max_bytes): Remove; unused.
63 (send_process): Do not set it.
64
652012-11-15 Juanma Barranquero <lekktu@gmail.com>
66
67 * makefile.w32-in ($(BLD)/dispnew.$(O), $(BLD)/emacs.$(O)):
68 Update dependencies.
69
702012-11-15 Paul Eggert <eggert@cs.ucla.edu>
71
72 * eval.c (mark_backtrace) [BYTE_MARK_STACK]: Remove stray '*'.
73 This follows up on the 2012-09-29 patch that removed indirection
74 for the 'function' field. Reported by Sergey Vinokurov in
75 <http://lists.gnu.org/archive/html/emacs-devel/2012-11/msg00263.html>.
76
772012-11-14 Eli Zaretskii <eliz@gnu.org>
78
79 * w32.c (faccessat): Rename from sys_faccessat. (No need to use a
80 different name, as the MS runtime does not have such a function,
81 and probably never will.) All callers changed. Ignore DIRFD
82 value if PATH is an absolute file name, to match Posix spec
83 better. If AT_SYMLINK_NOFOLLOW is set in FLAGS, don't resolve
84 symlinks.
85
862012-11-14 Dmitry Antipov <dmantipov@yandex.ru>
87
88 * xdisp.c (echo_area_display, redisplay_internal):
89 Omit redundant check whether frame_garbaged is set.
90
912012-11-14 Paul Eggert <eggert@cs.ucla.edu>
92
93 Use faccessat, not access, when checking file permissions (Bug#12632).
94 This fixes a bug that has been present in Emacs since its creation.
95 It was reported by Chris Torek in 1983 even before GNU Emacs existed,
96 which must set some sort of record. (Torek's bug report was against
97 a predecessor of GNU Emacs, but GNU Emacs happened to have the
98 same common flaw.) See Torek's Usenet posting
99 "setuid/setgid programs & Emacs" Article-I.D.: sri-arpa.858
100 Posted: Fri Apr 8 14:18:56 1983.
101 * Makefile.in (LIB_EACCESS): New macro.
102 (LIBES): Use it.
103 * callproc.c (init_callproc):
104 * charset.c (init_charset):
105 * fileio.c (check_existing, check_executable, check_writable)
106 (Ffile_readable_p):
107 * lread.c (openp, load_path_check):
108 * process.c (allocate_pty):
109 * xrdb.c (file_p):
110 Use effective UID when checking permissions, not real UID.
111 * callproc.c (init_callproc):
112 * charset.c (init_charset):
113 * lread.c (load_path_check, init_lread):
114 Test whether directories are accessible, not merely whether they exist.
115 * conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): New macro.
116 * fileio.c (check_existing, check_executable, check_writable)
117 (Ffile_readable_p):
118 Use symbolic names instead of integers for the flags, as they're
119 portable now.
120 (check_writable): New arg AMODE. All uses changed.
121 Set errno on failure.
122 (Ffile_readable_p): Use faccessat, not stat + open + close.
123 (Ffile_writable_p): No need to call check_existing + check_writable.
124 Just call check_writable and then look at errno. This saves a syscall.
125 dir should never be nil; replace an unnecessary runtime check
126 with an eassert. When checking the parent directory of a nonexistent
127 file, check that the directory is searchable as well as writable, as
128 we can't create files in unsearchable directories.
129 (file_directory_p): New function, which uses 'stat' on most platforms
130 but faccessat with D_OK (for efficiency) if WINDOWSNT.
131 (Ffile_directory_p, Fset_file_times): Use it.
132 (file_accessible_directory_p): New function, which uses a single
133 syscall for efficiency.
134 (Ffile_accessible_directory_p): Use it.
135 * xrdb.c (file_p): Use file_directory_p.
136 * lisp.h (file_directory_p, file_accessible_directory_p): New decls.
137 * lread.c (openp): When opening a file, use fstat rather than
138 stat, as that avoids a permissions race. When not opening a file,
139 use file_directory_p rather than stat.
140 (dir_warning): First arg is now a usage string, not a format.
141 Use errno. All uses changed.
142 * nsterm.m (ns_term_init): Remove unnecessary call to file-readable
143 that merely introduced a race.
144 * process.c, sysdep.c, term.c: All uses of '#ifdef O_NONBLOCK'
145 changed to '#if O_NONBLOCK', to accommodate gnulib O_* style,
146 and similarly for the other O_* flags.
147 * w32.c (sys_faccessat): Rename from sys_access and switch to
148 faccessat's API. All uses changed.
149 * xrdb.c: Do not include <sys/stat.h>; no longer needed.
150 (magic_db): Rename from magic_file_p.
151 (magic_db, search_magic_path): Return an XrmDatabase rather than a
152 char *, so that we don't have to test for file existence
153 separately from opening the file for reading. This removes a race
154 fixes a permission-checking problem, and simplifies the code.
155 All uses changed.
156 (file_p): Remove; no longer needed.
157
12012-11-13 Dmitry Antipov <dmantipov@yandex.ru> 1582012-11-13 Dmitry Antipov <dmantipov@yandex.ru>
2 159
3 Omit glyphs initialization at startup. 160 Omit glyphs initialization at startup.
diff --git a/src/Makefile.in b/src/Makefile.in
index 9d8e9698ec8..330066d0103 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -150,6 +150,7 @@ M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
150M17N_FLT_LIBS = @M17N_FLT_LIBS@ 150M17N_FLT_LIBS = @M17N_FLT_LIBS@
151 151
152LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@ 152LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
153LIB_EACCESS=@LIB_EACCESS@
153LIB_TIMER_TIME=@LIB_TIMER_TIME@ 154LIB_TIMER_TIME=@LIB_TIMER_TIME@
154 155
155DBUS_CFLAGS = @DBUS_CFLAGS@ 156DBUS_CFLAGS = @DBUS_CFLAGS@
@@ -392,7 +393,7 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
392LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \ 393LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \
393 $(LIBX_OTHER) $(LIBSOUND) \ 394 $(LIBX_OTHER) $(LIBSOUND) \
394 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \ 395 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \
395 $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 396 $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
396 $(LIB_EXECINFO) \ 397 $(LIB_EXECINFO) \
397 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ 398 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
398 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 399 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
diff --git a/src/callproc.c b/src/callproc.c
index c7bbe36e605..8ecaba2b408 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1576,15 +1576,13 @@ init_callproc (void)
1576#endif 1576#endif
1577 { 1577 {
1578 tempdir = Fdirectory_file_name (Vexec_directory); 1578 tempdir = Fdirectory_file_name (Vexec_directory);
1579 if (access (SSDATA (tempdir), 0) < 0) 1579 if (! file_accessible_directory_p (SSDATA (tempdir)))
1580 dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n", 1580 dir_warning ("arch-dependent data dir", Vexec_directory);
1581 Vexec_directory);
1582 } 1581 }
1583 1582
1584 tempdir = Fdirectory_file_name (Vdata_directory); 1583 tempdir = Fdirectory_file_name (Vdata_directory);
1585 if (access (SSDATA (tempdir), 0) < 0) 1584 if (! file_accessible_directory_p (SSDATA (tempdir)))
1586 dir_warning ("Warning: arch-independent data dir (%s) does not exist.\n", 1585 dir_warning ("arch-independent data dir", Vdata_directory);
1587 Vdata_directory);
1588 1586
1589 sh = (char *) getenv ("SHELL"); 1587 sh = (char *) getenv ("SHELL");
1590 Vshell_file_name = build_string (sh ? sh : "/bin/sh"); 1588 Vshell_file_name = build_string (sh ? sh : "/bin/sh");
@@ -1593,7 +1591,7 @@ init_callproc (void)
1593 Vshared_game_score_directory = Qnil; 1591 Vshared_game_score_directory = Qnil;
1594#else 1592#else
1595 Vshared_game_score_directory = build_string (PATH_GAME); 1593 Vshared_game_score_directory = build_string (PATH_GAME);
1596 if (NILP (Ffile_directory_p (Vshared_game_score_directory))) 1594 if (NILP (Ffile_accessible_directory_p (Vshared_game_score_directory)))
1597 Vshared_game_score_directory = Qnil; 1595 Vshared_game_score_directory = Qnil;
1598#endif 1596#endif
1599} 1597}
diff --git a/src/charset.c b/src/charset.c
index 6b999824dab..c9133c780e8 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -2293,7 +2293,7 @@ init_charset (void)
2293{ 2293{
2294 Lisp_Object tempdir; 2294 Lisp_Object tempdir;
2295 tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory); 2295 tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory);
2296 if (access (SSDATA (tempdir), 0) < 0) 2296 if (! file_accessible_directory_p (SSDATA (tempdir)))
2297 { 2297 {
2298 /* This used to be non-fatal (dir_warning), but it should not 2298 /* This used to be non-fatal (dir_warning), but it should not
2299 happen, and if it does sooner or later it will cause some 2299 happen, and if it does sooner or later it will cause some
diff --git a/src/conf_post.h b/src/conf_post.h
index 66390ddf103..b1997e79081 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -178,6 +178,10 @@ extern void _DebPrint (const char *fmt, ...);
178#endif 178#endif
179#endif 179#endif
180 180
181/* Tell gnulib to omit support for openat-related functions having a
182 first argument other than AT_FDCWD. */
183#define GNULIB_SUPPORT_ONLY_AT_FDCWD
184
181#include <string.h> 185#include <string.h>
182#include <stdlib.h> 186#include <stdlib.h>
183 187
diff --git a/src/editfns.c b/src/editfns.c
index c5d4ed295ab..8122ffdd0d4 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3434,8 +3434,8 @@ static ptrdiff_t message_length;
3434 3434
3435DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, 3435DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
3436 doc: /* Display a message at the bottom of the screen. 3436 doc: /* Display a message at the bottom of the screen.
3437The message also goes into the `*Messages*' buffer. 3437The message also goes into the `*Messages*' buffer, if `message-log-max'
3438\(In keyboard macros, that's all it does.) 3438is non-nil. (In keyboard macros, that's all it does.)
3439Return the message. 3439Return the message.
3440 3440
3441The first argument is a format control string, and the rest are data 3441The first argument is a format control string, and the rest are data
diff --git a/src/eval.c b/src/eval.c
index dcd48cb7250..f8a76646352 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -508,7 +508,7 @@ spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
508use `called-interactively-p'. */) 508use `called-interactively-p'. */)
509 (void) 509 (void)
510{ 510{
511 return interactive_p () ? Qt : Qnil; 511 return (INTERACTIVE && interactive_p ()) ? Qt : Qnil;
512} 512}
513 513
514 514
@@ -3369,7 +3369,7 @@ mark_backtrace (void)
3369 3369
3370 for (backlist = backtrace_list; backlist; backlist = backlist->next) 3370 for (backlist = backtrace_list; backlist; backlist = backlist->next)
3371 { 3371 {
3372 mark_object (*backlist->function); 3372 mark_object (backlist->function);
3373 3373
3374 if (backlist->nargs == UNEVALLED 3374 if (backlist->nargs == UNEVALLED
3375 || backlist->nargs == MANY) /* FIXME: Can this happen? */ 3375 || backlist->nargs == MANY) /* FIXME: Can this happen? */
diff --git a/src/fileio.c b/src/fileio.c
index b9541e78838..572f6d8ef83 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2425,15 +2425,7 @@ On Unix, this is a name starting with a `/' or a `~'. */)
2425bool 2425bool
2426check_existing (const char *filename) 2426check_existing (const char *filename)
2427{ 2427{
2428#ifdef DOS_NT 2428 return faccessat (AT_FDCWD, filename, F_OK, AT_EACCESS) == 0;
2429 /* The full emulation of Posix 'stat' is too expensive on
2430 DOS/Windows, when all we want to know is whether the file exists.
2431 So we use 'access' instead, which is much more lightweight. */
2432 return (access (filename, F_OK) >= 0);
2433#else
2434 struct stat st;
2435 return (stat (filename, &st) >= 0);
2436#endif
2437} 2429}
2438 2430
2439/* Return true if file FILENAME exists and can be executed. */ 2431/* Return true if file FILENAME exists and can be executed. */
@@ -2441,56 +2433,40 @@ check_existing (const char *filename)
2441static bool 2433static bool
2442check_executable (char *filename) 2434check_executable (char *filename)
2443{ 2435{
2444#ifdef DOS_NT 2436 return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0;
2445 struct stat st;
2446 if (stat (filename, &st) < 0)
2447 return 0;
2448 return ((st.st_mode & S_IEXEC) != 0);
2449#else /* not DOS_NT */
2450#ifdef HAVE_EUIDACCESS
2451 return (euidaccess (filename, 1) >= 0);
2452#else
2453 /* Access isn't quite right because it uses the real uid
2454 and we really want to test with the effective uid.
2455 But Unix doesn't give us a right way to do it. */
2456 return (access (filename, 1) >= 0);
2457#endif
2458#endif /* not DOS_NT */
2459} 2437}
2460 2438
2461/* Return true if file FILENAME exists and can be written. */ 2439/* Return true if file FILENAME exists and can be accessed
2440 according to AMODE, which should include W_OK.
2441 On failure, return false and set errno. */
2462 2442
2463static bool 2443static bool
2464check_writable (const char *filename) 2444check_writable (const char *filename, int amode)
2465{ 2445{
2466#ifdef MSDOS 2446#ifdef MSDOS
2447 /* FIXME: an faccessat implementation should be added to the
2448 DOS/Windows ports and this #ifdef branch should be removed. */
2467 struct stat st; 2449 struct stat st;
2468 if (stat (filename, &st) < 0) 2450 if (stat (filename, &st) < 0)
2469 return 0; 2451 return 0;
2452 errno = EPERM;
2470 return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode)); 2453 return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
2471#else /* not MSDOS */ 2454#else /* not MSDOS */
2472#ifdef HAVE_EUIDACCESS 2455 bool res = faccessat (AT_FDCWD, filename, amode, AT_EACCESS) == 0;
2473 bool res = (euidaccess (filename, 2) >= 0);
2474#ifdef CYGWIN 2456#ifdef CYGWIN
2475 /* euidaccess may have returned failure because Cygwin couldn't 2457 /* faccessat may have returned failure because Cygwin couldn't
2476 determine the file's UID or GID; if so, we return success. */ 2458 determine the file's UID or GID; if so, we return success. */
2477 if (!res) 2459 if (!res)
2478 { 2460 {
2461 int faccessat_errno = errno;
2479 struct stat st; 2462 struct stat st;
2480 if (stat (filename, &st) < 0) 2463 if (stat (filename, &st) < 0)
2481 return 0; 2464 return 0;
2482 res = (st.st_uid == -1 || st.st_gid == -1); 2465 res = (st.st_uid == -1 || st.st_gid == -1);
2466 errno = faccessat_errno;
2483 } 2467 }
2484#endif /* CYGWIN */ 2468#endif /* CYGWIN */
2485 return res; 2469 return res;
2486#else /* not HAVE_EUIDACCESS */
2487 /* Access isn't quite right because it uses the real uid
2488 and we really want to test with the effective uid.
2489 But Unix doesn't give us a right way to do it.
2490 Opening with O_WRONLY could work for an ordinary file,
2491 but would lose for directories. */
2492 return (access (filename, 2) >= 0);
2493#endif /* not HAVE_EUIDACCESS */
2494#endif /* not MSDOS */ 2470#endif /* not MSDOS */
2495} 2471}
2496 2472
@@ -2547,9 +2523,6 @@ See also `file-exists-p' and `file-attributes'. */)
2547{ 2523{
2548 Lisp_Object absname; 2524 Lisp_Object absname;
2549 Lisp_Object handler; 2525 Lisp_Object handler;
2550 int desc;
2551 int flags;
2552 struct stat statbuf;
2553 2526
2554 CHECK_STRING (filename); 2527 CHECK_STRING (filename);
2555 absname = Fexpand_file_name (filename, Qnil); 2528 absname = Fexpand_file_name (filename, Qnil);
@@ -2561,35 +2534,10 @@ See also `file-exists-p' and `file-attributes'. */)
2561 return call2 (handler, Qfile_readable_p, absname); 2534 return call2 (handler, Qfile_readable_p, absname);
2562 2535
2563 absname = ENCODE_FILE (absname); 2536 absname = ENCODE_FILE (absname);
2564 2537 return (faccessat (AT_FDCWD, SSDATA (absname), R_OK, AT_EACCESS) == 0
2565#if defined (DOS_NT) || defined (macintosh) 2538 ? Qt : Qnil);
2566 /* Under MS-DOS, Windows, and Macintosh, open does not work for
2567 directories. */
2568 if (access (SDATA (absname), 0) == 0)
2569 return Qt;
2570 return Qnil;
2571#else /* not DOS_NT and not macintosh */
2572 flags = O_RDONLY;
2573#ifdef O_NONBLOCK
2574 /* Opening a fifo without O_NONBLOCK can wait.
2575 We don't want to wait. But we don't want to mess wth O_NONBLOCK
2576 except in the case of a fifo, on a system which handles it. */
2577 desc = stat (SSDATA (absname), &statbuf);
2578 if (desc < 0)
2579 return Qnil;
2580 if (S_ISFIFO (statbuf.st_mode))
2581 flags |= O_NONBLOCK;
2582#endif
2583 desc = emacs_open (SSDATA (absname), flags, 0);
2584 if (desc < 0)
2585 return Qnil;
2586 emacs_close (desc);
2587 return Qt;
2588#endif /* not DOS_NT and not macintosh */
2589} 2539}
2590 2540
2591/* Having this before file-symlink-p mysteriously caused it to be forgotten
2592 on the RT/PC. */
2593DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0, 2541DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2594 doc: /* Return t if file FILENAME can be written or created by you. */) 2542 doc: /* Return t if file FILENAME can be written or created by you. */)
2595 (Lisp_Object filename) 2543 (Lisp_Object filename)
@@ -2607,14 +2555,15 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2607 return call2 (handler, Qfile_writable_p, absname); 2555 return call2 (handler, Qfile_writable_p, absname);
2608 2556
2609 encoded = ENCODE_FILE (absname); 2557 encoded = ENCODE_FILE (absname);
2610 if (check_existing (SSDATA (encoded))) 2558 if (check_writable (SSDATA (encoded), W_OK))
2611 return (check_writable (SSDATA (encoded)) 2559 return Qt;
2612 ? Qt : Qnil); 2560 if (errno != ENOENT)
2561 return Qnil;
2613 2562
2614 dir = Ffile_name_directory (absname); 2563 dir = Ffile_name_directory (absname);
2564 eassert (!NILP (dir));
2615#ifdef MSDOS 2565#ifdef MSDOS
2616 if (!NILP (dir)) 2566 dir = Fdirectory_file_name (dir);
2617 dir = Fdirectory_file_name (dir);
2618#endif /* MSDOS */ 2567#endif /* MSDOS */
2619 2568
2620 dir = ENCODE_FILE (dir); 2569 dir = ENCODE_FILE (dir);
@@ -2622,10 +2571,9 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2622 /* The read-only attribute of the parent directory doesn't affect 2571 /* The read-only attribute of the parent directory doesn't affect
2623 whether a file or directory can be created within it. Some day we 2572 whether a file or directory can be created within it. Some day we
2624 should check ACLs though, which do affect this. */ 2573 should check ACLs though, which do affect this. */
2625 return (access (SDATA (dir), D_OK) < 0) ? Qnil : Qt; 2574 return file_directory_p (SDATA (dir)) ? Qt : Qnil;
2626#else 2575#else
2627 return (check_writable (!NILP (dir) ? SSDATA (dir) : "") 2576 return check_writable (SSDATA (dir), W_OK | X_OK) ? Qt : Qnil;
2628 ? Qt : Qnil);
2629#endif 2577#endif
2630} 2578}
2631 2579
@@ -2703,8 +2651,7 @@ Symbolic links to directories count as directories.
2703See `file-symlink-p' to distinguish symlinks. */) 2651See `file-symlink-p' to distinguish symlinks. */)
2704 (Lisp_Object filename) 2652 (Lisp_Object filename)
2705{ 2653{
2706 register Lisp_Object absname; 2654 Lisp_Object absname;
2707 struct stat st;
2708 Lisp_Object handler; 2655 Lisp_Object handler;
2709 2656
2710 absname = expand_and_dir_to_file (filename, BVAR (current_buffer, directory)); 2657 absname = expand_and_dir_to_file (filename, BVAR (current_buffer, directory));
@@ -2717,9 +2664,20 @@ See `file-symlink-p' to distinguish symlinks. */)
2717 2664
2718 absname = ENCODE_FILE (absname); 2665 absname = ENCODE_FILE (absname);
2719 2666
2720 if (stat (SSDATA (absname), &st) < 0) 2667 return file_directory_p (SSDATA (absname)) ? Qt : Qnil;
2721 return Qnil; 2668}
2722 return S_ISDIR (st.st_mode) ? Qt : Qnil; 2669
2670/* Return true if FILE is a directory or a symlink to a directory. */
2671bool
2672file_directory_p (char const *file)
2673{
2674#ifdef WINDOWSNT
2675 /* This is cheaper than 'stat'. */
2676 return faccessat (AT_FDCWD, file, D_OK, AT_EACCESS) == 0;
2677#else
2678 struct stat st;
2679 return stat (file, &st) == 0 && S_ISDIR (st.st_mode);
2680#endif
2723} 2681}
2724 2682
2725DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, 2683DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p,
@@ -2733,21 +2691,65 @@ if the directory so specified exists and really is a readable and
2733searchable directory. */) 2691searchable directory. */)
2734 (Lisp_Object filename) 2692 (Lisp_Object filename)
2735{ 2693{
2694 Lisp_Object absname;
2736 Lisp_Object handler; 2695 Lisp_Object handler;
2737 bool tem; 2696
2738 struct gcpro gcpro1; 2697 CHECK_STRING (filename);
2698 absname = Fexpand_file_name (filename, Qnil);
2739 2699
2740 /* If the file name has special constructs in it, 2700 /* If the file name has special constructs in it,
2741 call the corresponding file handler. */ 2701 call the corresponding file handler. */
2742 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); 2702 handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p);
2743 if (!NILP (handler)) 2703 if (!NILP (handler))
2744 return call2 (handler, Qfile_accessible_directory_p, filename); 2704 return call2 (handler, Qfile_accessible_directory_p, absname);
2745 2705
2746 GCPRO1 (filename); 2706 absname = ENCODE_FILE (absname);
2747 tem = (NILP (Ffile_directory_p (filename)) 2707 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil;
2748 || NILP (Ffile_executable_p (filename))); 2708}
2749 UNGCPRO; 2709
2750 return tem ? Qnil : Qt; 2710/* If FILE is a searchable directory or a symlink to a
2711 searchable directory, return true. Otherwise return
2712 false and set errno to an error number. */
2713bool
2714file_accessible_directory_p (char const *file)
2715{
2716#ifdef DOS_NT
2717 /* There's no need to test whether FILE is searchable, as the
2718 searchable/executable bit is invented on DOS_NT platforms. */
2719 return file_directory_p (file);
2720#else
2721 /* On POSIXish platforms, use just one system call; this avoids a
2722 race and is typically faster. */
2723 ptrdiff_t len = strlen (file);
2724 char const *dir;
2725 bool ok;
2726 int saved_errno;
2727 USE_SAFE_ALLOCA;
2728
2729 /* Normally a file "FOO" is an accessible directory if "FOO/." exists.
2730 There are three exceptions: "", "/", and "//". Leave "" alone,
2731 as it's invalid. Append only "." to the other two exceptions as
2732 "/" and "//" are distinct on some platforms, whereas "/", "///",
2733 "////", etc. are all equivalent. */
2734 if (! len)
2735 dir = file;
2736 else
2737 {
2738 /* Just check for trailing '/' when deciding whether to append '/'.
2739 That's simpler than testing the two special cases "/" and "//",
2740 and it's a safe optimization here. */
2741 char *buf = SAFE_ALLOCA (len + 3);
2742 memcpy (buf, file, len);
2743 strcpy (buf + len, "/." + (file[len - 1] == '/'));
2744 dir = buf;
2745 }
2746
2747 ok = check_existing (dir);
2748 saved_errno = errno;
2749 SAFE_FREE ();
2750 errno = saved_errno;
2751 return ok;
2752#endif
2751} 2753}
2752 2754
2753DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0, 2755DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
@@ -3044,10 +3046,8 @@ Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of
3044 if (set_file_times (-1, SSDATA (encoded_absname), t, t)) 3046 if (set_file_times (-1, SSDATA (encoded_absname), t, t))
3045 { 3047 {
3046#ifdef MSDOS 3048#ifdef MSDOS
3047 struct stat st;
3048
3049 /* Setting times on a directory always fails. */ 3049 /* Setting times on a directory always fails. */
3050 if (stat (SSDATA (encoded_absname), &st) == 0 && S_ISDIR (st.st_mode)) 3050 if (file_directory_p (SSDATA (encoded_absname)))
3051 return Qnil; 3051 return Qnil;
3052#endif 3052#endif
3053 report_file_error ("Setting file times", Fcons (absname, Qnil)); 3053 report_file_error ("Setting file times", Fcons (absname, Qnil));
diff --git a/src/lisp.h b/src/lisp.h
index c909287b7cd..2148a623cc7 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3202,6 +3202,8 @@ extern Lisp_Object close_file_unwind (Lisp_Object);
3202extern Lisp_Object restore_point_unwind (Lisp_Object); 3202extern Lisp_Object restore_point_unwind (Lisp_Object);
3203extern _Noreturn void report_file_error (const char *, Lisp_Object); 3203extern _Noreturn void report_file_error (const char *, Lisp_Object);
3204extern void internal_delete_file (Lisp_Object); 3204extern void internal_delete_file (Lisp_Object);
3205extern bool file_directory_p (const char *);
3206extern bool file_accessible_directory_p (const char *);
3205extern void syms_of_fileio (void); 3207extern void syms_of_fileio (void);
3206extern Lisp_Object make_temp_name (Lisp_Object, bool); 3208extern Lisp_Object make_temp_name (Lisp_Object, bool);
3207extern Lisp_Object Qdelete_file; 3209extern Lisp_Object Qdelete_file;
diff --git a/src/lread.c b/src/lread.c
index 3a82e0057e2..5859a2f85a9 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1403,7 +1403,7 @@ Returns the file's name in absolute form, or nil if not found.
1403If SUFFIXES is non-nil, it should be a list of suffixes to append to 1403If SUFFIXES is non-nil, it should be a list of suffixes to append to
1404file name when searching. 1404file name when searching.
1405If non-nil, PREDICATE is used instead of `file-readable-p'. 1405If non-nil, PREDICATE is used instead of `file-readable-p'.
1406PREDICATE can also be an integer to pass to the access(2) function, 1406PREDICATE can also be an integer to pass to the faccessat(2) function,
1407in which case file-name-handlers are ignored. 1407in which case file-name-handlers are ignored.
1408This function will normally skip directories, so if you want it to find 1408This function will normally skip directories, so if you want it to find
1409directories, make sure the PREDICATE function returns `dir-ok' for them. */) 1409directories, make sure the PREDICATE function returns `dir-ok' for them. */)
@@ -1441,7 +1441,6 @@ static Lisp_Object Qdir_ok;
1441int 1441int
1442openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate) 1442openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate)
1443{ 1443{
1444 int fd;
1445 ptrdiff_t fn_size = 100; 1444 ptrdiff_t fn_size = 100;
1446 char buf[100]; 1445 char buf[100];
1447 char *fn = buf; 1446 char *fn = buf;
@@ -1496,7 +1495,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1496 { 1495 {
1497 ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail)); 1496 ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail));
1498 Lisp_Object handler; 1497 Lisp_Object handler;
1499 bool exists;
1500 1498
1501 /* Concatenate path element/specified name with the suffix. 1499 /* Concatenate path element/specified name with the suffix.
1502 If the directory starts with /:, remove that. */ 1500 If the directory starts with /:, remove that. */
@@ -1520,6 +1518,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1520 handler = Ffind_file_name_handler (string, Qfile_exists_p); 1518 handler = Ffind_file_name_handler (string, Qfile_exists_p);
1521 if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) 1519 if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate))
1522 { 1520 {
1521 bool exists;
1523 if (NILP (predicate)) 1522 if (NILP (predicate))
1524 exists = !NILP (Ffile_readable_p (string)); 1523 exists = !NILP (Ffile_readable_p (string));
1525 else 1524 else
@@ -1541,37 +1540,40 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1541 } 1540 }
1542 else 1541 else
1543 { 1542 {
1544#ifndef WINDOWSNT 1543 int fd;
1545 struct stat st;
1546#endif
1547 const char *pfn; 1544 const char *pfn;
1548 1545
1549 encoded_fn = ENCODE_FILE (string); 1546 encoded_fn = ENCODE_FILE (string);
1550 pfn = SSDATA (encoded_fn); 1547 pfn = SSDATA (encoded_fn);
1551#ifdef WINDOWSNT
1552 exists = access (pfn, F_OK) == 0 && access (pfn, D_OK) < 0;
1553#else
1554 exists = (stat (pfn, &st) == 0 && ! S_ISDIR (st.st_mode));
1555#endif
1556 if (exists)
1557 {
1558 /* Check that we can access or open it. */
1559 if (NATNUMP (predicate))
1560 fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
1561 && access (pfn, XFASTINT (predicate)) == 0)
1562 ? 1 : -1);
1563 else
1564 fd = emacs_open (pfn, O_RDONLY, 0);
1565 1548
1566 if (fd >= 0) 1549 /* Check that we can access or open it. */
1550 if (NATNUMP (predicate))
1551 fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
1552 && (faccessat (AT_FDCWD, pfn, XFASTINT (predicate),
1553 AT_EACCESS)
1554 == 0)
1555 && ! file_directory_p (pfn))
1556 ? 1 : -1);
1557 else
1558 {
1559 struct stat st;
1560 fd = emacs_open (pfn, O_RDONLY, 0);
1561 if (0 <= fd
1562 && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode)))
1567 { 1563 {
1568 /* We succeeded; return this descriptor and filename. */ 1564 emacs_close (fd);
1569 if (storeptr) 1565 fd = -1;
1570 *storeptr = string;
1571 UNGCPRO;
1572 return fd;
1573 } 1566 }
1574 } 1567 }
1568
1569 if (fd >= 0)
1570 {
1571 /* We succeeded; return this descriptor and filename. */
1572 if (storeptr)
1573 *storeptr = string;
1574 UNGCPRO;
1575 return fd;
1576 }
1575 } 1577 }
1576 } 1578 }
1577 if (absolute) 1579 if (absolute)
@@ -4087,9 +4089,8 @@ load_path_check (void)
4087 if (STRINGP (dirfile)) 4089 if (STRINGP (dirfile))
4088 { 4090 {
4089 dirfile = Fdirectory_file_name (dirfile); 4091 dirfile = Fdirectory_file_name (dirfile);
4090 if (access (SSDATA (dirfile), 0) < 0) 4092 if (! file_accessible_directory_p (SSDATA (dirfile)))
4091 dir_warning ("Warning: Lisp directory `%s' does not exist.\n", 4093 dir_warning ("Lisp directory", XCAR (path_tail));
4092 XCAR (path_tail));
4093 } 4094 }
4094 } 4095 }
4095} 4096}
@@ -4201,11 +4202,11 @@ init_lread (void)
4201 Lisp_Object tem, tem1; 4202 Lisp_Object tem, tem1;
4202 4203
4203 /* Add to the path the lisp subdir of the installation 4204 /* Add to the path the lisp subdir of the installation
4204 dir, if it exists. Note: in out-of-tree builds, 4205 dir, if it is accessible. Note: in out-of-tree builds,
4205 this directory is empty save for Makefile. */ 4206 this directory is empty save for Makefile. */
4206 tem = Fexpand_file_name (build_string ("lisp"), 4207 tem = Fexpand_file_name (build_string ("lisp"),
4207 Vinstallation_directory); 4208 Vinstallation_directory);
4208 tem1 = Ffile_exists_p (tem); 4209 tem1 = Ffile_accessible_directory_p (tem);
4209 if (!NILP (tem1)) 4210 if (!NILP (tem1))
4210 { 4211 {
4211 if (NILP (Fmember (tem, Vload_path))) 4212 if (NILP (Fmember (tem, Vload_path)))
@@ -4222,10 +4223,10 @@ init_lread (void)
4222 Lisp dirs instead. */ 4223 Lisp dirs instead. */
4223 Vload_path = nconc2 (Vload_path, dump_path); 4224 Vload_path = nconc2 (Vload_path, dump_path);
4224 4225
4225 /* Add leim under the installation dir, if it exists. */ 4226 /* Add leim under the installation dir, if it is accessible. */
4226 tem = Fexpand_file_name (build_string ("leim"), 4227 tem = Fexpand_file_name (build_string ("leim"),
4227 Vinstallation_directory); 4228 Vinstallation_directory);
4228 tem1 = Ffile_exists_p (tem); 4229 tem1 = Ffile_accessible_directory_p (tem);
4229 if (!NILP (tem1)) 4230 if (!NILP (tem1))
4230 { 4231 {
4231 if (NILP (Fmember (tem, Vload_path))) 4232 if (NILP (Fmember (tem, Vload_path)))
@@ -4237,7 +4238,7 @@ init_lread (void)
4237 { 4238 {
4238 tem = Fexpand_file_name (build_string ("site-lisp"), 4239 tem = Fexpand_file_name (build_string ("site-lisp"),
4239 Vinstallation_directory); 4240 Vinstallation_directory);
4240 tem1 = Ffile_exists_p (tem); 4241 tem1 = Ffile_accessible_directory_p (tem);
4241 if (!NILP (tem1)) 4242 if (!NILP (tem1))
4242 { 4243 {
4243 if (NILP (Fmember (tem, Vload_path))) 4244 if (NILP (Fmember (tem, Vload_path)))
@@ -4282,7 +4283,7 @@ init_lread (void)
4282 { 4283 {
4283 tem = Fexpand_file_name (build_string ("site-lisp"), 4284 tem = Fexpand_file_name (build_string ("site-lisp"),
4284 Vsource_directory); 4285 Vsource_directory);
4285 tem1 = Ffile_exists_p (tem); 4286 tem1 = Ffile_accessible_directory_p (tem);
4286 if (!NILP (tem1)) 4287 if (!NILP (tem1))
4287 { 4288 {
4288 if (NILP (Fmember (tem, Vload_path))) 4289 if (NILP (Fmember (tem, Vload_path)))
@@ -4338,21 +4339,28 @@ init_lread (void)
4338 Vloads_in_progress = Qnil; 4339 Vloads_in_progress = Qnil;
4339} 4340}
4340 4341
4341/* Print a warning, using format string FORMAT, that directory DIRNAME 4342/* Print a warning that directory intended for use USE and with name
4342 does not exist. Print it on stderr and put it in *Messages*. */ 4343 DIRNAME cannot be accessed. On entry, errno should correspond to
4344 the access failure. Print the warning on stderr and put it in
4345 *Messages*. */
4343 4346
4344void 4347void
4345dir_warning (const char *format, Lisp_Object dirname) 4348dir_warning (char const *use, Lisp_Object dirname)
4346{ 4349{
4347 fprintf (stderr, format, SDATA (dirname)); 4350 static char const format[] = "Warning: %s `%s': %s\n";
4351 int access_errno = errno;
4352 fprintf (stderr, format, use, SSDATA (dirname), strerror (access_errno));
4348 4353
4349 /* Don't log the warning before we've initialized!! */ 4354 /* Don't log the warning before we've initialized!! */
4350 if (initialized) 4355 if (initialized)
4351 { 4356 {
4357 char const *diagnostic = emacs_strerror (access_errno);
4352 USE_SAFE_ALLOCA; 4358 USE_SAFE_ALLOCA;
4353 char *buffer = SAFE_ALLOCA (SBYTES (dirname) 4359 char *buffer = SAFE_ALLOCA (sizeof format - 3 * (sizeof "%s" - 1)
4354 + strlen (format) - (sizeof "%s" - 1) + 1); 4360 + strlen (use) + SBYTES (dirname)
4355 ptrdiff_t message_len = esprintf (buffer, format, SDATA (dirname)); 4361 + strlen (diagnostic));
4362 ptrdiff_t message_len = esprintf (buffer, format, use, SSDATA (dirname),
4363 diagnostic);
4356 message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname)); 4364 message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname));
4357 SAFE_FREE (); 4365 SAFE_FREE ();
4358 } 4366 }
diff --git a/src/makefile.w32-in b/src/makefile.w32-in
index 50e5e2ec4df..71cafeb4d8b 100644
--- a/src/makefile.w32-in
+++ b/src/makefile.w32-in
@@ -738,6 +738,7 @@ $(BLD)/dispnew.$(O) : \
738 $(SRC)/termchar.h \ 738 $(SRC)/termchar.h \
739 $(SRC)/w32.h \ 739 $(SRC)/w32.h \
740 $(NT_INC)/unistd.h \ 740 $(NT_INC)/unistd.h \
741 $(GNU_LIB)/fpending.h \
741 $(BUFFER_H) \ 742 $(BUFFER_H) \
742 $(CHARACTER_H) \ 743 $(CHARACTER_H) \
743 $(CONFIG_H) \ 744 $(CONFIG_H) \
@@ -803,6 +804,7 @@ $(BLD)/emacs.$(O) : \
803 $(SRC)/w32select.h \ 804 $(SRC)/w32select.h \
804 $(NT_INC)/sys/file.h \ 805 $(NT_INC)/sys/file.h \
805 $(NT_INC)/unistd.h \ 806 $(NT_INC)/unistd.h \
807 $(GNU_LIB)/close-stream.h \
806 $(GNU_LIB)/ignore-value.h \ 808 $(GNU_LIB)/ignore-value.h \
807 $(ATIMER_H) \ 809 $(ATIMER_H) \
808 $(BUFFER_H) \ 810 $(BUFFER_H) \
diff --git a/src/nsterm.m b/src/nsterm.m
index 7ba1608268b..3640ac0c5e8 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -31,6 +31,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
31#include <config.h> 31#include <config.h>
32 32
33#include <math.h> 33#include <math.h>
34#include <pthread.h>
34#include <sys/types.h> 35#include <sys/types.h>
35#include <time.h> 36#include <time.h>
36#include <signal.h> 37#include <signal.h>
@@ -330,6 +331,8 @@ hold_event (struct input_event *event)
330 } 331 }
331 332
332 hold_event_q.q[hold_event_q.nr++] = *event; 333 hold_event_q.q[hold_event_q.nr++] = *event;
334 /* Make sure ns_read_socket is called, i.e. we have input. */
335 raise (SIGIO);
333} 336}
334 337
335static Lisp_Object 338static Lisp_Object
@@ -3387,7 +3390,7 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
3387 if ([NSApp modalWindow] != nil) 3390 if ([NSApp modalWindow] != nil)
3388 return -1; 3391 return -1;
3389 3392
3390 if (hold_event_q.nr > 0) 3393 if (hold_event_q.nr > 0)
3391 { 3394 {
3392 int i; 3395 int i;
3393 for (i = 0; i < hold_event_q.nr; ++i) 3396 for (i = 0; i < hold_event_q.nr; ++i)
@@ -3502,7 +3505,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3502 3505
3503 /* Inform fd_handler that select should be called */ 3506 /* Inform fd_handler that select should be called */
3504 c = 'g'; 3507 c = 'g';
3505 write (selfds[1], &c, 1); 3508 emacs_write (selfds[1], &c, 1);
3506 } 3509 }
3507 else if (nr == 0 && timeout) 3510 else if (nr == 0 && timeout)
3508 { 3511 {
@@ -3535,7 +3538,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3535 if (nr > 0 && readfds) 3538 if (nr > 0 && readfds)
3536 { 3539 {
3537 c = 's'; 3540 c = 's';
3538 write (selfds[1], &c, 1); 3541 emacs_write (selfds[1], &c, 1);
3539 } 3542 }
3540 unblock_input (); 3543 unblock_input ();
3541 3544
@@ -4112,8 +4115,6 @@ ns_term_init (Lisp_Object display_name)
4112 4115
4113 color_file = Fexpand_file_name (build_string ("rgb.txt"), 4116 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4114 Fsymbol_value (intern ("data-directory"))); 4117 Fsymbol_value (intern ("data-directory")));
4115 if (NILP (Ffile_readable_p (color_file)))
4116 fatal ("Could not find %s.\n", SDATA (color_file));
4117 4118
4118 color_map = Fx_load_color_file (color_file); 4119 color_map = Fx_load_color_file (color_file);
4119 if (NILP (color_map)) 4120 if (NILP (color_map))
@@ -4576,11 +4577,8 @@ not_in_argv (NSString *arg)
4576 4577
4577 FD_SET (selfds[0], &fds); 4578 FD_SET (selfds[0], &fds);
4578 result = select (selfds[0]+1, &fds, NULL, NULL, NULL); 4579 result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
4579 if (result > 0) 4580 if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g')
4580 { 4581 waiting = 0;
4581 read (selfds[0], &c, 1);
4582 if (c == 'g') waiting = 0;
4583 }
4584 } 4582 }
4585 else 4583 else
4586 { 4584 {
@@ -4620,8 +4618,8 @@ not_in_argv (NSString *arg)
4620 { 4618 {
4621 if (FD_ISSET (selfds[0], &readfds)) 4619 if (FD_ISSET (selfds[0], &readfds))
4622 { 4620 {
4623 read (selfds[0], &c, 1); 4621 if (read (selfds[0], &c, 1) == 1 && c == 's')
4624 if (c == 's') waiting = 1; 4622 waiting = 1;
4625 } 4623 }
4626 else 4624 else
4627 { 4625 {
@@ -6696,7 +6694,7 @@ not_in_argv (NSString *arg)
6696 /* Events may come here even if the event loop is not running. 6694 /* Events may come here even if the event loop is not running.
6697 If we don't enter the event loop, the scroll bar will not update. 6695 If we don't enter the event loop, the scroll bar will not update.
6698 So send SIGIO to ourselves. */ 6696 So send SIGIO to ourselves. */
6699 if (apploopnr == 0) kill (0, SIGIO); 6697 if (apploopnr == 0) raise (SIGIO);
6700 6698
6701 return self; 6699 return self;
6702} 6700}
diff --git a/src/process.c b/src/process.c
index 43f0239d301..5fe6a6540f3 100644
--- a/src/process.c
+++ b/src/process.c
@@ -130,18 +130,6 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
130 EMACS_TIME *, void *); 130 EMACS_TIME *, void *);
131#endif 131#endif
132 132
133/* This is for DOS_NT ports. FIXME: Remove this old portability cruft
134 by having DOS_NT ports implement waitpid instead of wait. Nowadays
135 POSIXish hosts all define waitpid, WNOHANG, and WUNTRACED, as these
136 have been standard since POSIX.1-1988. */
137#ifndef WNOHANG
138# undef waitpid
139# define waitpid(pid, status, options) wait (status)
140#endif
141#ifndef WUNTRACED
142# define WUNTRACED 0
143#endif
144
145/* Work around GCC 4.7.0 bug with strict overflow checking; see 133/* Work around GCC 4.7.0 bug with strict overflow checking; see
146 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. 134 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
147 These lines can be removed once the GCC bug is fixed. */ 135 These lines can be removed once the GCC bug is fixed. */
@@ -208,7 +196,7 @@ static EMACS_INT update_tick;
208#ifndef NON_BLOCKING_CONNECT 196#ifndef NON_BLOCKING_CONNECT
209#ifdef HAVE_SELECT 197#ifdef HAVE_SELECT
210#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX) 198#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
211#if defined (O_NONBLOCK) || defined (O_NDELAY) 199#if O_NONBLOCK || O_NDELAY
212#if defined (EWOULDBLOCK) || defined (EINPROGRESS) 200#if defined (EWOULDBLOCK) || defined (EINPROGRESS)
213#define NON_BLOCKING_CONNECT 201#define NON_BLOCKING_CONNECT
214#endif /* EWOULDBLOCK || EINPROGRESS */ 202#endif /* EWOULDBLOCK || EINPROGRESS */
@@ -340,9 +328,6 @@ static struct sockaddr_and_len {
340#define DATAGRAM_CONN_P(proc) (0) 328#define DATAGRAM_CONN_P(proc) (0)
341#endif 329#endif
342 330
343/* Maximum number of bytes to send to a pty without an eof. */
344static int pty_max_bytes;
345
346/* These setters are used only in this file, so they can be private. */ 331/* These setters are used only in this file, so they can be private. */
347static void 332static void
348pset_buffer (struct Lisp_Process *p, Lisp_Object val) 333pset_buffer (struct Lisp_Process *p, Lisp_Object val)
@@ -655,7 +640,7 @@ allocate_pty (void)
655 PTY_OPEN; 640 PTY_OPEN;
656#else /* no PTY_OPEN */ 641#else /* no PTY_OPEN */
657 { 642 {
658# ifdef O_NONBLOCK 643# if O_NONBLOCK
659 fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0); 644 fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
660# else 645# else
661 fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0); 646 fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
@@ -672,7 +657,7 @@ allocate_pty (void)
672#else 657#else
673 sprintf (pty_name, "/dev/tty%c%x", c, i); 658 sprintf (pty_name, "/dev/tty%c%x", c, i);
674#endif /* no PTY_TTY_NAME_SPRINTF */ 659#endif /* no PTY_TTY_NAME_SPRINTF */
675 if (access (pty_name, 6) != 0) 660 if (faccessat (AT_FDCWD, pty_name, R_OK | W_OK, AT_EACCESS) != 0)
676 { 661 {
677 emacs_close (fd); 662 emacs_close (fd);
678# ifndef __sgi 663# ifndef __sgi
@@ -1624,7 +1609,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1624#if ! defined (USG) || defined (USG_SUBTTY_WORKS) 1609#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
1625 /* On most USG systems it does not work to open the pty's tty here, 1610 /* On most USG systems it does not work to open the pty's tty here,
1626 then close it and reopen it in the child. */ 1611 then close it and reopen it in the child. */
1627#ifdef O_NOCTTY 1612#if O_NOCTTY
1628 /* Don't let this terminal become our controlling terminal 1613 /* Don't let this terminal become our controlling terminal
1629 (in case we don't have one). */ 1614 (in case we don't have one). */
1630 forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); 1615 forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
@@ -1678,11 +1663,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1678 } 1663 }
1679#endif 1664#endif
1680 1665
1681#ifdef O_NONBLOCK 1666#if O_NONBLOCK
1682 fcntl (inchannel, F_SETFL, O_NONBLOCK); 1667 fcntl (inchannel, F_SETFL, O_NONBLOCK);
1683 fcntl (outchannel, F_SETFL, O_NONBLOCK); 1668 fcntl (outchannel, F_SETFL, O_NONBLOCK);
1684#else 1669#else
1685#ifdef O_NDELAY 1670#if O_NDELAY
1686 fcntl (inchannel, F_SETFL, O_NDELAY); 1671 fcntl (inchannel, F_SETFL, O_NDELAY);
1687 fcntl (outchannel, F_SETFL, O_NDELAY); 1672 fcntl (outchannel, F_SETFL, O_NDELAY);
1688#endif 1673#endif
@@ -1943,7 +1928,7 @@ create_pty (Lisp_Object process)
1943#if ! defined (USG) || defined (USG_SUBTTY_WORKS) 1928#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
1944 /* On most USG systems it does not work to open the pty's tty here, 1929 /* On most USG systems it does not work to open the pty's tty here,
1945 then close it and reopen it in the child. */ 1930 then close it and reopen it in the child. */
1946#ifdef O_NOCTTY 1931#if O_NOCTTY
1947 /* Don't let this terminal become our controlling terminal 1932 /* Don't let this terminal become our controlling terminal
1948 (in case we don't have one). */ 1933 (in case we don't have one). */
1949 int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); 1934 int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
@@ -1963,11 +1948,11 @@ create_pty (Lisp_Object process)
1963 } 1948 }
1964#endif /* HAVE_PTYS */ 1949#endif /* HAVE_PTYS */
1965 1950
1966#ifdef O_NONBLOCK 1951#if O_NONBLOCK
1967 fcntl (inchannel, F_SETFL, O_NONBLOCK); 1952 fcntl (inchannel, F_SETFL, O_NONBLOCK);
1968 fcntl (outchannel, F_SETFL, O_NONBLOCK); 1953 fcntl (outchannel, F_SETFL, O_NONBLOCK);
1969#else 1954#else
1970#ifdef O_NDELAY 1955#if O_NDELAY
1971 fcntl (inchannel, F_SETFL, O_NDELAY); 1956 fcntl (inchannel, F_SETFL, O_NDELAY);
1972 fcntl (outchannel, F_SETFL, O_NDELAY); 1957 fcntl (outchannel, F_SETFL, O_NDELAY);
1973#endif 1958#endif
@@ -2927,7 +2912,7 @@ usage: (make-network-process &rest ARGS) */)
2927 { 2912 {
2928 /* Don't support network sockets when non-blocking mode is 2913 /* Don't support network sockets when non-blocking mode is
2929 not available, since a blocked Emacs is not useful. */ 2914 not available, since a blocked Emacs is not useful. */
2930#if !defined (O_NONBLOCK) && !defined (O_NDELAY) 2915#if !O_NONBLOCK && !O_NDELAY
2931 error ("Network servers not supported"); 2916 error ("Network servers not supported");
2932#else 2917#else
2933 is_server = 1; 2918 is_server = 1;
@@ -3193,7 +3178,7 @@ usage: (make-network-process &rest ARGS) */)
3193#ifdef NON_BLOCKING_CONNECT 3178#ifdef NON_BLOCKING_CONNECT
3194 if (is_non_blocking_client) 3179 if (is_non_blocking_client)
3195 { 3180 {
3196#ifdef O_NONBLOCK 3181#if O_NONBLOCK
3197 ret = fcntl (s, F_SETFL, O_NONBLOCK); 3182 ret = fcntl (s, F_SETFL, O_NONBLOCK);
3198#else 3183#else
3199 ret = fcntl (s, F_SETFL, O_NDELAY); 3184 ret = fcntl (s, F_SETFL, O_NDELAY);
@@ -3410,10 +3395,10 @@ usage: (make-network-process &rest ARGS) */)
3410 3395
3411 chan_process[inch] = proc; 3396 chan_process[inch] = proc;
3412 3397
3413#ifdef O_NONBLOCK 3398#if O_NONBLOCK
3414 fcntl (inch, F_SETFL, O_NONBLOCK); 3399 fcntl (inch, F_SETFL, O_NONBLOCK);
3415#else 3400#else
3416#ifdef O_NDELAY 3401#if O_NDELAY
3417 fcntl (inch, F_SETFL, O_NDELAY); 3402 fcntl (inch, F_SETFL, O_NDELAY);
3418#endif 3403#endif
3419#endif 3404#endif
@@ -4145,10 +4130,10 @@ server_accept_connection (Lisp_Object server, int channel)
4145 4130
4146 chan_process[s] = proc; 4131 chan_process[s] = proc;
4147 4132
4148#ifdef O_NONBLOCK 4133#if O_NONBLOCK
4149 fcntl (s, F_SETFL, O_NONBLOCK); 4134 fcntl (s, F_SETFL, O_NONBLOCK);
4150#else 4135#else
4151#ifdef O_NDELAY 4136#if O_NDELAY
4152 fcntl (s, F_SETFL, O_NDELAY); 4137 fcntl (s, F_SETFL, O_NDELAY);
4153#endif 4138#endif
4154#endif 4139#endif
@@ -4849,11 +4834,11 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4849#endif 4834#endif
4850 /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK, 4835 /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
4851 and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */ 4836 and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */
4852#ifdef O_NONBLOCK 4837#if O_NONBLOCK
4853 else if (nread == -1 && errno == EAGAIN) 4838 else if (nread == -1 && errno == EAGAIN)
4854 ; 4839 ;
4855#else 4840#else
4856#ifdef O_NDELAY 4841#if O_NDELAY
4857 else if (nread == -1 && errno == EAGAIN) 4842 else if (nread == -1 && errno == EAGAIN)
4858 ; 4843 ;
4859 /* Note that we cannot distinguish between no input 4844 /* Note that we cannot distinguish between no input
@@ -5532,19 +5517,6 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
5532 buf = SSDATA (object); 5517 buf = SSDATA (object);
5533 } 5518 }
5534 5519
5535 if (pty_max_bytes == 0)
5536 {
5537#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
5538 pty_max_bytes = fpathconf (p->outfd, _PC_MAX_CANON);
5539 if (pty_max_bytes < 0)
5540 pty_max_bytes = 250;
5541#else
5542 pty_max_bytes = 250;
5543#endif
5544 /* Deduct one, to leave space for the eof. */
5545 pty_max_bytes--;
5546 }
5547
5548 /* If there is already data in the write_queue, put the new data 5520 /* If there is already data in the write_queue, put the new data
5549 in the back of queue. Otherwise, ignore it. */ 5521 in the back of queue. Otherwise, ignore it. */
5550 if (!NILP (p->write_queue)) 5522 if (!NILP (p->write_queue))
@@ -6311,17 +6283,9 @@ record_child_status_change (pid_t pid, int w)
6311{ 6283{
6312#ifdef SIGCHLD 6284#ifdef SIGCHLD
6313 6285
6314# ifdef WNOHANG
6315 /* On POSIXish hosts, record at most one child only if we already 6286 /* On POSIXish hosts, record at most one child only if we already
6316 know one child that has exited. */ 6287 know one child that has exited. */
6317 bool record_at_most_one_child = 0 <= pid; 6288 bool record_at_most_one_child = 0 <= pid;
6318# else
6319 /* On DOS_NT (the only porting target that lacks WNOHANG),
6320 record the status of at most one child process, since the SIGCHLD
6321 handler must return right away. If any more processes want to
6322 signal us, we will get another signal. */
6323 bool record_at_most_one_child = 1;
6324# endif
6325 6289
6326 Lisp_Object tail; 6290 Lisp_Object tail;
6327 6291
@@ -7348,7 +7312,7 @@ init_process_emacs (void)
7348#ifdef HAVE_GETSOCKNAME 7312#ifdef HAVE_GETSOCKNAME
7349 ADD_SUBFEATURE (QCservice, Qt); 7313 ADD_SUBFEATURE (QCservice, Qt);
7350#endif 7314#endif
7351#if defined (O_NONBLOCK) || defined (O_NDELAY) 7315#if O_NONBLOCK || O_NDELAY
7352 ADD_SUBFEATURE (QCserver, Qt); 7316 ADD_SUBFEATURE (QCserver, Qt);
7353#endif 7317#endif
7354 7318
diff --git a/src/sysdep.c b/src/sysdep.c
index aa9d0f38c3c..06dc41b511e 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -289,10 +289,6 @@ wait_for_termination_1 (pid_t pid, int interruptible)
289{ 289{
290 while (1) 290 while (1)
291 { 291 {
292#ifdef WINDOWSNT
293 wait (0);
294 break;
295#else /* not WINDOWSNT */
296 int status; 292 int status;
297 int wait_result = waitpid (pid, &status, 0); 293 int wait_result = waitpid (pid, &status, 0);
298 if (wait_result < 0) 294 if (wait_result < 0)
@@ -306,7 +302,8 @@ wait_for_termination_1 (pid_t pid, int interruptible)
306 break; 302 break;
307 } 303 }
308 304
309#endif /* not WINDOWSNT */ 305 /* Note: the MS-Windows emulation of waitpid calls QUIT
306 internally. */
310 if (interruptible) 307 if (interruptible)
311 QUIT; 308 QUIT;
312 } 309 }
@@ -1287,7 +1284,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
1287 old_fcntl_owner[fileno (tty_out->input)]); 1284 old_fcntl_owner[fileno (tty_out->input)]);
1288 } 1285 }
1289#endif /* F_SETOWN */ 1286#endif /* F_SETOWN */
1290#ifdef O_NDELAY 1287#if O_NDELAY
1291 fcntl (fileno (tty_out->input), F_SETFL, 1288 fcntl (fileno (tty_out->input), F_SETFL,
1292 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY); 1289 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
1293#endif 1290#endif
@@ -2384,12 +2381,12 @@ serial_open (char *port)
2384 2381
2385 fd = emacs_open ((char*) port, 2382 fd = emacs_open ((char*) port,
2386 O_RDWR 2383 O_RDWR
2387#ifdef O_NONBLOCK 2384#if O_NONBLOCK
2388 | O_NONBLOCK 2385 | O_NONBLOCK
2389#else 2386#else
2390 | O_NDELAY 2387 | O_NDELAY
2391#endif 2388#endif
2392#ifdef O_NOCTTY 2389#if O_NOCTTY
2393 | O_NOCTTY 2390 | O_NOCTTY
2394#endif 2391#endif
2395 , 0); 2392 , 0);
diff --git a/src/term.c b/src/term.c
index 578c701858f..96549290da5 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2992,7 +2992,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
2992 int fd; 2992 int fd;
2993 FILE *file; 2993 FILE *file;
2994 2994
2995#ifdef O_IGNORE_CTTY 2995#if O_IGNORE_CTTY
2996 if (!ctty) 2996 if (!ctty)
2997 /* Open the terminal device. Don't recognize it as our 2997 /* Open the terminal device. Don't recognize it as our
2998 controlling terminal, and don't make it the controlling tty 2998 controlling terminal, and don't make it the controlling tty
@@ -3023,7 +3023,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
3023 name); 3023 name);
3024 } 3024 }
3025 3025
3026#ifndef O_IGNORE_CTTY 3026#if !O_IGNORE_CTTY
3027 if (!ctty) 3027 if (!ctty)
3028 dissociate_if_controlling_tty (fd); 3028 dissociate_if_controlling_tty (fd);
3029#endif 3029#endif
diff --git a/src/w32.c b/src/w32.c
index 5ac1bc3eb7c..46433626802 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1597,7 +1597,7 @@ init_environment (char ** argv)
1597 see if it succeeds. But I think that's too much to ask. */ 1597 see if it succeeds. But I think that's too much to ask. */
1598 1598
1599 /* MSVCRT's _access crashes with D_OK. */ 1599 /* MSVCRT's _access crashes with D_OK. */
1600 if (tmp && sys_access (tmp, D_OK) == 0) 1600 if (tmp && faccessat (AT_FDCWD, tmp, D_OK, AT_EACCESS) == 0)
1601 { 1601 {
1602 char * var = alloca (strlen (tmp) + 8); 1602 char * var = alloca (strlen (tmp) + 8);
1603 sprintf (var, "TMPDIR=%s", tmp); 1603 sprintf (var, "TMPDIR=%s", tmp);
@@ -2708,16 +2708,20 @@ logon_network_drive (const char *path)
2708 WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE); 2708 WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE);
2709} 2709}
2710 2710
2711/* Shadow some MSVC runtime functions to map requests for long filenames 2711/* Emulate faccessat(2). */
2712 to reasonable short names if necessary. This was originally added to
2713 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
2714 long file names. */
2715
2716int 2712int
2717sys_access (const char * path, int mode) 2713faccessat (int dirfd, const char * path, int mode, int flags)
2718{ 2714{
2719 DWORD attributes; 2715 DWORD attributes;
2720 2716
2717 if (dirfd != AT_FDCWD
2718 && !(IS_DIRECTORY_SEP (path[0])
2719 || IS_DEVICE_SEP (path[1])))
2720 {
2721 errno = EBADF;
2722 return -1;
2723 }
2724
2721 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its 2725 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
2722 newer versions blow up when passed D_OK. */ 2726 newer versions blow up when passed D_OK. */
2723 path = map_w32_filename (path, NULL); 2727 path = map_w32_filename (path, NULL);
@@ -2725,7 +2729,8 @@ sys_access (const char * path, int mode)
2725 to get the attributes of its target file. Note: any symlinks in 2729 to get the attributes of its target file. Note: any symlinks in
2726 PATH elements other than the last one are transparently resolved 2730 PATH elements other than the last one are transparently resolved
2727 by GetFileAttributes below. */ 2731 by GetFileAttributes below. */
2728 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0) 2732 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0
2733 && (flags & AT_SYMLINK_NOFOLLOW) == 0)
2729 path = chase_symlinks (path); 2734 path = chase_symlinks (path);
2730 2735
2731 if ((attributes = GetFileAttributes (path)) == -1) 2736 if ((attributes = GetFileAttributes (path)) == -1)
@@ -2757,7 +2762,8 @@ sys_access (const char * path, int mode)
2757 } 2762 }
2758 return -1; 2763 return -1;
2759 } 2764 }
2760 if ((mode & X_OK) != 0 && !is_exec (path)) 2765 if ((mode & X_OK) != 0
2766 && !(is_exec (path) || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
2761 { 2767 {
2762 errno = EACCES; 2768 errno = EACCES;
2763 return -1; 2769 return -1;
@@ -2775,6 +2781,11 @@ sys_access (const char * path, int mode)
2775 return 0; 2781 return 0;
2776} 2782}
2777 2783
2784/* Shadow some MSVC runtime functions to map requests for long filenames
2785 to reasonable short names if necessary. This was originally added to
2786 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
2787 long file names. */
2788
2778int 2789int
2779sys_chdir (const char * path) 2790sys_chdir (const char * path)
2780{ 2791{
@@ -2960,7 +2971,7 @@ sys_mktemp (char * template)
2960 { 2971 {
2961 int save_errno = errno; 2972 int save_errno = errno;
2962 p[0] = first_char[i]; 2973 p[0] = first_char[i];
2963 if (sys_access (template, 0) < 0) 2974 if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0)
2964 { 2975 {
2965 errno = save_errno; 2976 errno = save_errno;
2966 return template; 2977 return template;
@@ -4011,7 +4022,7 @@ symlink (char const *filename, char const *linkname)
4011 { 4022 {
4012 /* Non-absolute FILENAME is understood as being relative to 4023 /* Non-absolute FILENAME is understood as being relative to
4013 LINKNAME's directory. We need to prepend that directory to 4024 LINKNAME's directory. We need to prepend that directory to
4014 FILENAME to get correct results from sys_access below, since 4025 FILENAME to get correct results from faccessat below, since
4015 otherwise it will interpret FILENAME relative to the 4026 otherwise it will interpret FILENAME relative to the
4016 directory where the Emacs process runs. Note that 4027 directory where the Emacs process runs. Note that
4017 make-symbolic-link always makes sure LINKNAME is a fully 4028 make-symbolic-link always makes sure LINKNAME is a fully
@@ -4025,10 +4036,10 @@ symlink (char const *filename, char const *linkname)
4025 strncpy (tem, linkfn, p - linkfn); 4036 strncpy (tem, linkfn, p - linkfn);
4026 tem[p - linkfn] = '\0'; 4037 tem[p - linkfn] = '\0';
4027 strcat (tem, filename); 4038 strcat (tem, filename);
4028 dir_access = sys_access (tem, D_OK); 4039 dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
4029 } 4040 }
4030 else 4041 else
4031 dir_access = sys_access (filename, D_OK); 4042 dir_access = faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
4032 4043
4033 /* Since Windows distinguishes between symlinks to directories and 4044 /* Since Windows distinguishes between symlinks to directories and
4034 to files, we provide a kludgy feature: if FILENAME doesn't 4045 to files, we provide a kludgy feature: if FILENAME doesn't
diff --git a/src/w32proc.c b/src/w32proc.c
index e074ece020d..2951df7ed89 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -431,13 +431,14 @@ timer_loop (LPVOID arg)
431 /* Simulate a signal delivered to the thread which installed 431 /* Simulate a signal delivered to the thread which installed
432 the timer, by suspending that thread while the handler 432 the timer, by suspending that thread while the handler
433 runs. */ 433 runs. */
434 DWORD result = SuspendThread (itimer->caller_thread); 434 HANDLE th = itimer->caller_thread;
435 DWORD result = SuspendThread (th);
435 436
436 if (result == (DWORD)-1) 437 if (result == (DWORD)-1)
437 return 2; 438 return 2;
438 439
439 handler (sig); 440 handler (sig);
440 ResumeThread (itimer->caller_thread); 441 ResumeThread (th);
441 } 442 }
442 443
443 /* Update expiration time and loop. */ 444 /* Update expiration time and loop. */
@@ -562,6 +563,7 @@ static int
562start_timer_thread (int which) 563start_timer_thread (int which)
563{ 564{
564 DWORD exit_code; 565 DWORD exit_code;
566 HANDLE th;
565 struct itimer_data *itimer = 567 struct itimer_data *itimer =
566 (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; 568 (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
567 569
@@ -570,9 +572,29 @@ start_timer_thread (int which)
570 && exit_code == STILL_ACTIVE) 572 && exit_code == STILL_ACTIVE)
571 return 0; 573 return 0;
572 574
575 /* Clean up after possibly exited thread. */
576 if (itimer->timer_thread)
577 {
578 CloseHandle (itimer->timer_thread);
579 itimer->timer_thread = NULL;
580 }
581 if (itimer->caller_thread)
582 {
583 CloseHandle (itimer->caller_thread);
584 itimer->caller_thread = NULL;
585 }
586
573 /* Start a new thread. */ 587 /* Start a new thread. */
588 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
589 GetCurrentProcess (), &th, 0, FALSE,
590 DUPLICATE_SAME_ACCESS))
591 {
592 errno = ESRCH;
593 return -1;
594 }
574 itimer->terminate = 0; 595 itimer->terminate = 0;
575 itimer->type = which; 596 itimer->type = which;
597 itimer->caller_thread = th;
576 /* Request that no more than 64KB of stack be reserved for this 598 /* Request that no more than 64KB of stack be reserved for this
577 thread, to avoid reserving too much memory, which would get in 599 thread, to avoid reserving too much memory, which would get in
578 the way of threads we start to wait for subprocesses. See also 600 the way of threads we start to wait for subprocesses. See also
@@ -591,7 +613,7 @@ start_timer_thread (int which)
591 /* This is needed to make sure that the timer thread running for 613 /* This is needed to make sure that the timer thread running for
592 profiling gets CPU as soon as the Sleep call terminates. */ 614 profiling gets CPU as soon as the Sleep call terminates. */
593 if (which == ITIMER_PROF) 615 if (which == ITIMER_PROF)
594 SetThreadPriority (itimer->caller_thread, THREAD_PRIORITY_TIME_CRITICAL); 616 SetThreadPriority (itimer->timer_thread, THREAD_PRIORITY_TIME_CRITICAL);
595 617
596 return 0; 618 return 0;
597} 619}
@@ -626,17 +648,9 @@ getitimer (int which, struct itimerval *value)
626 648
627 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; 649 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
628 650
629 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
630 GetCurrentProcess (), &itimer->caller_thread, 0,
631 FALSE, DUPLICATE_SAME_ACCESS))
632 {
633 errno = ESRCH;
634 return -1;
635 }
636
637 ticks_now = w32_get_timer_time ((which == ITIMER_REAL) 651 ticks_now = w32_get_timer_time ((which == ITIMER_REAL)
638 ? NULL 652 ? NULL
639 : itimer->caller_thread); 653 : GetCurrentThread ());
640 654
641 t_expire = &itimer->expire; 655 t_expire = &itimer->expire;
642 t_reload = &itimer->reload; 656 t_reload = &itimer->reload;
@@ -775,7 +789,6 @@ alarm (int seconds)
775/* Child process management list. */ 789/* Child process management list. */
776int child_proc_count = 0; 790int child_proc_count = 0;
777child_process child_procs[ MAX_CHILDREN ]; 791child_process child_procs[ MAX_CHILDREN ];
778child_process *dead_child = NULL;
779 792
780static DWORD WINAPI reader_thread (void *arg); 793static DWORD WINAPI reader_thread (void *arg);
781 794
@@ -1028,9 +1041,6 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
1028 if (cp->pid < 0) 1041 if (cp->pid < 0)
1029 cp->pid = -cp->pid; 1042 cp->pid = -cp->pid;
1030 1043
1031 /* pid must fit in a Lisp_Int */
1032 cp->pid = cp->pid & INTMASK;
1033
1034 *pPid = cp->pid; 1044 *pPid = cp->pid;
1035 1045
1036 return TRUE; 1046 return TRUE;
@@ -1106,55 +1116,110 @@ reap_subprocess (child_process *cp)
1106 delete_child (cp); 1116 delete_child (cp);
1107} 1117}
1108 1118
1109/* Wait for any of our existing child processes to die 1119/* Wait for a child process specified by PID, or for any of our
1110 When it does, close its handle 1120 existing child processes (if PID is nonpositive) to die. When it
1111 Return the pid and fill in the status if non-NULL. */ 1121 does, close its handle. Return the pid of the process that died
1122 and fill in STATUS if non-NULL. */
1112 1123
1113int 1124pid_t
1114sys_wait (int *status) 1125waitpid (pid_t pid, int *status, int options)
1115{ 1126{
1116 DWORD active, retval; 1127 DWORD active, retval;
1117 int nh; 1128 int nh;
1118 int pid;
1119 child_process *cp, *cps[MAX_CHILDREN]; 1129 child_process *cp, *cps[MAX_CHILDREN];
1120 HANDLE wait_hnd[MAX_CHILDREN]; 1130 HANDLE wait_hnd[MAX_CHILDREN];
1131 DWORD timeout_ms;
1132 int dont_wait = (options & WNOHANG) != 0;
1121 1133
1122 nh = 0; 1134 nh = 0;
1123 if (dead_child != NULL) 1135 /* According to Posix:
1136
1137 PID = -1 means status is requested for any child process.
1138
1139 PID > 0 means status is requested for a single child process
1140 whose pid is PID.
1141
1142 PID = 0 means status is requested for any child process whose
1143 process group ID is equal to that of the calling process. But
1144 since Windows has only a limited support for process groups (only
1145 for console processes and only for the purposes of passing
1146 Ctrl-BREAK signal to them), and since we have no documented way
1147 of determining whether a given process belongs to our group, we
1148 treat 0 as -1.
1149
1150 PID < -1 means status is requested for any child process whose
1151 process group ID is equal to the absolute value of PID. Again,
1152 since we don't support process groups, we treat that as -1. */
1153 if (pid > 0)
1124 { 1154 {
1125 /* We want to wait for a specific child */ 1155 int our_child = 0;
1126 wait_hnd[nh] = dead_child->procinfo.hProcess; 1156
1127 cps[nh] = dead_child; 1157 /* We are requested to wait for a specific child. */
1128 if (!wait_hnd[nh]) emacs_abort (); 1158 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
1129 nh++; 1159 {
1130 active = 0; 1160 /* Some child_procs might be sockets; ignore them. Also
1131 goto get_result; 1161 ignore subprocesses whose output is not yet completely
1162 read. */
1163 if (CHILD_ACTIVE (cp)
1164 && cp->procinfo.hProcess
1165 && cp->pid == pid)
1166 {
1167 our_child = 1;
1168 break;
1169 }
1170 }
1171 if (our_child)
1172 {
1173 if (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
1174 {
1175 wait_hnd[nh] = cp->procinfo.hProcess;
1176 cps[nh] = cp;
1177 nh++;
1178 }
1179 else if (dont_wait)
1180 {
1181 /* PID specifies our subprocess, but its status is not
1182 yet available. */
1183 return 0;
1184 }
1185 }
1186 if (nh == 0)
1187 {
1188 /* No such child process, or nothing to wait for, so fail. */
1189 errno = ECHILD;
1190 return -1;
1191 }
1132 } 1192 }
1133 else 1193 else
1134 { 1194 {
1135 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) 1195 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
1136 /* some child_procs might be sockets; ignore them */ 1196 {
1137 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess 1197 if (CHILD_ACTIVE (cp)
1138 && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)) 1198 && cp->procinfo.hProcess
1139 { 1199 && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
1140 wait_hnd[nh] = cp->procinfo.hProcess; 1200 {
1141 cps[nh] = cp; 1201 wait_hnd[nh] = cp->procinfo.hProcess;
1142 nh++; 1202 cps[nh] = cp;
1143 } 1203 nh++;
1204 }
1205 }
1206 if (nh == 0)
1207 {
1208 /* Nothing to wait on, so fail. */
1209 errno = ECHILD;
1210 return -1;
1211 }
1144 } 1212 }
1145 1213
1146 if (nh == 0) 1214 if (dont_wait)
1147 { 1215 timeout_ms = 0;
1148 /* Nothing to wait on, so fail */ 1216 else
1149 errno = ECHILD; 1217 timeout_ms = 1000; /* check for quit about once a second. */
1150 return -1;
1151 }
1152 1218
1153 do 1219 do
1154 { 1220 {
1155 /* Check for quit about once a second. */
1156 QUIT; 1221 QUIT;
1157 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000); 1222 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms);
1158 } while (active == WAIT_TIMEOUT); 1223 } while (active == WAIT_TIMEOUT);
1159 1224
1160 if (active == WAIT_FAILED) 1225 if (active == WAIT_FAILED)
@@ -1184,8 +1249,10 @@ get_result:
1184 } 1249 }
1185 if (retval == STILL_ACTIVE) 1250 if (retval == STILL_ACTIVE)
1186 { 1251 {
1187 /* Should never happen */ 1252 /* Should never happen. */
1188 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); 1253 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
1254 if (pid > 0 && dont_wait)
1255 return 0;
1189 errno = EINVAL; 1256 errno = EINVAL;
1190 return -1; 1257 return -1;
1191 } 1258 }
@@ -1199,6 +1266,8 @@ get_result:
1199 else 1266 else
1200 retval <<= 8; 1267 retval <<= 8;
1201 1268
1269 if (pid > 0 && active != 0)
1270 emacs_abort ();
1202 cp = cps[active]; 1271 cp = cps[active];
1203 pid = cp->pid; 1272 pid = cp->pid;
1204#ifdef FULL_DEBUG 1273#ifdef FULL_DEBUG
@@ -2004,9 +2073,7 @@ count_children:
2004 DebPrint (("select calling SIGCHLD handler for pid %d\n", 2073 DebPrint (("select calling SIGCHLD handler for pid %d\n",
2005 cp->pid)); 2074 cp->pid));
2006#endif 2075#endif
2007 dead_child = cp;
2008 sig_handlers[SIGCHLD] (SIGCHLD); 2076 sig_handlers[SIGCHLD] (SIGCHLD);
2009 dead_child = NULL;
2010 } 2077 }
2011 } 2078 }
2012 else if (fdindex[active] == -1) 2079 else if (fdindex[active] == -1)
diff --git a/src/xdisp.c b/src/xdisp.c
index a74628db392..27d9fff0b7d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -10816,8 +10816,7 @@ echo_area_display (int update_frame_p)
10816#endif /* HAVE_WINDOW_SYSTEM */ 10816#endif /* HAVE_WINDOW_SYSTEM */
10817 10817
10818 /* Redraw garbaged frames. */ 10818 /* Redraw garbaged frames. */
10819 if (frame_garbaged) 10819 clear_garbaged_frames ();
10820 clear_garbaged_frames ();
10821 10820
10822 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0) 10821 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
10823 { 10822 {
@@ -13104,8 +13103,7 @@ redisplay_internal (void)
13104 } 13103 }
13105 13104
13106 /* Clear frames marked as garbaged. */ 13105 /* Clear frames marked as garbaged. */
13107 if (frame_garbaged) 13106 clear_garbaged_frames ();
13108 clear_garbaged_frames ();
13109 13107
13110 /* Build menubar and tool-bar items. */ 13108 /* Build menubar and tool-bar items. */
13111 if (NILP (Vmemory_full)) 13109 if (NILP (Vmemory_full))
@@ -13189,8 +13187,7 @@ redisplay_internal (void)
13189 /* If window configuration was changed, frames may have been 13187 /* If window configuration was changed, frames may have been
13190 marked garbaged. Clear them or we will experience 13188 marked garbaged. Clear them or we will experience
13191 surprises wrt scrolling. */ 13189 surprises wrt scrolling. */
13192 if (frame_garbaged) 13190 clear_garbaged_frames ();
13193 clear_garbaged_frames ();
13194 } 13191 }
13195 } 13192 }
13196 else if (EQ (selected_window, minibuf_window) 13193 else if (EQ (selected_window, minibuf_window)
@@ -13213,8 +13210,7 @@ redisplay_internal (void)
13213 /* If window configuration was changed, frames may have been 13210 /* If window configuration was changed, frames may have been
13214 marked garbaged. Clear them or we will experience 13211 marked garbaged. Clear them or we will experience
13215 surprises wrt scrolling. */ 13212 surprises wrt scrolling. */
13216 if (frame_garbaged) 13213 clear_garbaged_frames ();
13217 clear_garbaged_frames ();
13218 } 13214 }
13219 13215
13220 13216
diff --git a/src/xfaces.c b/src/xfaces.c
index daf329791c1..1e27d5cc043 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2870,6 +2870,12 @@ FRAME 0 means change the face on all frames, and change the default
2870 Lisp_Object key, val, list; 2870 Lisp_Object key, val, list;
2871 2871
2872 list = value; 2872 list = value;
2873 /* FIXME? This errs on the side of acceptance. Eg it accepts:
2874 (defface foo '((t :underline 'foo) "doc")
2875 Maybe this is intentional, maybe it isn't.
2876 Non-nil symbols other than t are not documented as being valid.
2877 Eg compare with inverse-video, which explicitly rejects them.
2878 */
2873 valid_p = 1; 2879 valid_p = 1;
2874 2880
2875 while (!NILP (CAR_SAFE(list))) 2881 while (!NILP (CAR_SAFE(list)))
@@ -5660,6 +5666,8 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
5660 face->underline_defaulted_p = 1; 5666 face->underline_defaulted_p = 1;
5661 face->underline_type = FACE_UNDER_LINE; 5667 face->underline_type = FACE_UNDER_LINE;
5662 5668
5669 /* FIXME? This is also not robust about checking the precise form.
5670 See comments in Finternal_set_lisp_face_attribute. */
5663 while (CONSP (underline)) 5671 while (CONSP (underline))
5664 { 5672 {
5665 Lisp_Object keyword, value; 5673 Lisp_Object keyword, value;
diff --git a/src/xrdb.c b/src/xrdb.c
index 9d056a607e4..59b0876ebf8 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -41,7 +41,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#ifdef HAVE_PWD_H 41#ifdef HAVE_PWD_H
42#include <pwd.h> 42#include <pwd.h>
43#endif 43#endif
44#include <sys/stat.h>
45 44
46#ifdef USE_MOTIF 45#ifdef USE_MOTIF
47/* For Vdouble_click_time. */ 46/* For Vdouble_click_time. */
@@ -50,7 +49,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
50 49
51char *x_get_string_resource (XrmDatabase rdb, const char *name, 50char *x_get_string_resource (XrmDatabase rdb, const char *name,
52 const char *class); 51 const char *class);
53static int file_p (const char *filename);
54 52
55 53
56/* X file search path processing. */ 54/* X file search path processing. */
@@ -108,7 +106,7 @@ x_get_customization_string (XrmDatabase db, const char *name,
108 database associated with display. 106 database associated with display.
109 (This is x_customization_string.) 107 (This is x_customization_string.)
110 108
111 Return the expanded file name if it exists and is readable, and 109 Return the resource database if its file was read successfully, and
112 refers to %L only when the LANG environment variable is set, or 110 refers to %L only when the LANG environment variable is set, or
113 otherwise provided by X. 111 otherwise provided by X.
114 112
@@ -117,10 +115,11 @@ x_get_customization_string (XrmDatabase db, const char *name,
117 115
118 Return NULL otherwise. */ 116 Return NULL otherwise. */
119 117
120static char * 118static XrmDatabase
121magic_file_p (const char *string, ptrdiff_t string_len, const char *class, 119magic_db (const char *string, ptrdiff_t string_len, const char *class,
122 const char *escaped_suffix) 120 const char *escaped_suffix)
123{ 121{
122 XrmDatabase db;
124 char *lang = getenv ("LANG"); 123 char *lang = getenv ("LANG");
125 124
126 ptrdiff_t path_size = 100; 125 ptrdiff_t path_size = 100;
@@ -217,14 +216,9 @@ magic_file_p (const char *string, ptrdiff_t string_len, const char *class,
217 } 216 }
218 217
219 path[path_len] = '\0'; 218 path[path_len] = '\0';
220 219 db = XrmGetFileDatabase (path);
221 if (! file_p (path)) 220 xfree (path);
222 { 221 return db;
223 xfree (path);
224 return NULL;
225 }
226
227 return path;
228} 222}
229 223
230 224
@@ -258,22 +252,11 @@ gethomedir (void)
258} 252}
259 253
260 254
261static int
262file_p (const char *filename)
263{
264 struct stat status;
265
266 return (access (filename, 4) == 0 /* exists and is readable */
267 && stat (filename, &status) == 0 /* get the status */
268 && (S_ISDIR (status.st_mode)) == 0); /* not a directory */
269}
270
271
272/* Find the first element of SEARCH_PATH which exists and is readable, 255/* Find the first element of SEARCH_PATH which exists and is readable,
273 after expanding the %-escapes. Return 0 if we didn't find any, and 256 after expanding the %-escapes. Return 0 if we didn't find any, and
274 the path name of the one we found otherwise. */ 257 the path name of the one we found otherwise. */
275 258
276static char * 259static XrmDatabase
277search_magic_path (const char *search_path, const char *class, 260search_magic_path (const char *search_path, const char *class,
278 const char *escaped_suffix) 261 const char *escaped_suffix)
279{ 262{
@@ -286,18 +269,16 @@ search_magic_path (const char *search_path, const char *class,
286 269
287 if (p > s) 270 if (p > s)
288 { 271 {
289 char *path = magic_file_p (s, p - s, class, escaped_suffix); 272 XrmDatabase db = magic_db (s, p - s, class, escaped_suffix);
290 if (path) 273 if (db)
291 return path; 274 return db;
292 } 275 }
293 else if (*p == ':') 276 else if (*p == ':')
294 { 277 {
295 char *path; 278 static char const ns[] = "%N%S";
296 279 XrmDatabase db = magic_db (ns, strlen (ns), class, escaped_suffix);
297 s = "%N%S"; 280 if (db)
298 path = magic_file_p (s, strlen (s), class, escaped_suffix); 281 return db;
299 if (path)
300 return path;
301 } 282 }
302 283
303 if (*p == ':') 284 if (*p == ':')
@@ -312,21 +293,12 @@ search_magic_path (const char *search_path, const char *class,
312static XrmDatabase 293static XrmDatabase
313get_system_app (const char *class) 294get_system_app (const char *class)
314{ 295{
315 XrmDatabase db = NULL;
316 const char *path; 296 const char *path;
317 char *p;
318 297
319 path = getenv ("XFILESEARCHPATH"); 298 path = getenv ("XFILESEARCHPATH");
320 if (! path) path = PATH_X_DEFAULTS; 299 if (! path) path = PATH_X_DEFAULTS;
321 300
322 p = search_magic_path (path, class, 0); 301 return search_magic_path (path, class, 0);
323 if (p)
324 {
325 db = XrmGetFileDatabase (p);
326 xfree (p);
327 }
328
329 return db;
330} 302}
331 303
332 304
@@ -340,35 +312,40 @@ get_fallback (Display *display)
340static XrmDatabase 312static XrmDatabase
341get_user_app (const char *class) 313get_user_app (const char *class)
342{ 314{
315 XrmDatabase db = 0;
343 const char *path; 316 const char *path;
344 char *file = 0;
345 char *free_it = 0;
346 317
347 /* Check for XUSERFILESEARCHPATH. It is a path of complete file 318 /* Check for XUSERFILESEARCHPATH. It is a path of complete file
348 names, not directories. */ 319 names, not directories. */
349 if (((path = getenv ("XUSERFILESEARCHPATH")) 320 path = getenv ("XUSERFILESEARCHPATH");
350 && (file = search_magic_path (path, class, 0))) 321 if (path)
322 db = search_magic_path (path, class, 0);
351 323
324 if (! db)
325 {
352 /* Check for APPLRESDIR; it is a path of directories. In each, 326 /* Check for APPLRESDIR; it is a path of directories. In each,
353 we have to search for LANG/CLASS and then CLASS. */ 327 we have to search for LANG/CLASS and then CLASS. */
354 || ((path = getenv ("XAPPLRESDIR")) 328 path = getenv ("XAPPLRESDIR");
355 && ((file = search_magic_path (path, class, "/%L/%N")) 329 if (path)
356 || (file = search_magic_path (path, class, "/%N")))) 330 {
331 db = search_magic_path (path, class, "/%L/%N");
332 if (!db)
333 db = search_magic_path (path, class, "/%N");
334 }
335 }
357 336
337 if (! db)
338 {
358 /* Check in the home directory. This is a bit of a hack; let's 339 /* Check in the home directory. This is a bit of a hack; let's
359 hope one's home directory doesn't contain any %-escapes. */ 340 hope one's home directory doesn't contain any %-escapes. */
360 || (free_it = gethomedir (), 341 char *home = gethomedir ();
361 ((file = search_magic_path (free_it, class, "%L/%N")) 342 db = search_magic_path (home, class, "%L/%N");
362 || (file = search_magic_path (free_it, class, "%N"))))) 343 if (! db)
363 { 344 db = search_magic_path (home, class, "%N");
364 XrmDatabase db = XrmGetFileDatabase (file); 345 xfree (home);
365 xfree (file);
366 xfree (free_it);
367 return db;
368 } 346 }
369 347
370 xfree (free_it); 348 return db;
371 return NULL;
372} 349}
373 350
374 351