/* MS-DOS specific C utilities. -*- coding: cp850 -*-
-Copyright (C) 1993-1997, 1999-2014 Free Software Foundation, Inc.
+Copyright (C) 1993-1997, 1999-2015 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <unistd.h> /* for chdir, dup, dup2, etc. */
#include <dir.h> /* for getdisk */
#pragma pack(0) /* dir.h does a pack(4), which isn't GCC's default */
+#undef opendir
+#include <dirent.h> /* for opendir */
#include <fcntl.h>
#include <io.h> /* for setmode */
#include <dpmi.h> /* for __dpmi_xxx stuff */
#include "coding.h"
#include "disptab.h"
#include "window.h"
+#include "menu.h"
#include "buffer.h"
#include "commands.h"
#include "blockinput.h"
};
int i = 0;
- while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
+ while (i < ARRAYELTS (std_dimension))
{
if (std_dimension[i].need_vga <= have_vga
&& std_dimension[i].rows >= *rows)
}
Vinitial_window_system = Qpc;
- Vwindow_system_version = make_number (24); /* RE Emacs version */
+ Vwindow_system_version = make_number (25); /* RE Emacs version */
tty->terminal->type = output_msdos_raw;
/* If Emacs was dumped on DOS/V machine, forget the stale VRAM
term->update_end_hook = IT_update_end;
term->frame_up_to_date_hook = IT_frame_up_to_date;
term->mouse_position_hook = 0; /* set later by dos_ttraw */
+ term->menu_show_hook = x_menu_show;
term->frame_rehighlight_hook = 0;
term->frame_raise_lower_hook = 0;
term->set_vertical_scroll_bar_hook = 0;
#endif
}
-#ifndef HAVE_X_WINDOWS
-
-/* We are not X, but we can emulate it well enough for our needs... */
-void
-check_window_system (void)
-{
- if (! FRAME_MSDOS_P (SELECTED_FRAME ()))
- error ("Not running under a window system");
-}
-
-#endif
-
\f
/* ----------------------- Keyboard control ----------------------
*
static const char * const tempdirs[] = {
"$TMPDIR", "$TEMP", "$TMP", "c:/"
};
- const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
+ const int imax = ARRAYELTS (tempdirs);
/* Make sure they have a usable $TMPDIR. Many Emacs functions use
temporary files and assume "/tmp" if $TMPDIR is unset, which
int setpriority (int x, int y, int z) { return 0; }
pid_t setsid (void) { return 0; }
+\f
+/* Gnulib support and emulation. */
+
#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
ssize_t
readlink (const char *name, char *dummy1, size_t dummy2)
}
#endif
+/* dir_pathname is set by sys_opendir and used in readlinkat and in
+ fstatat, when they get a special FD of zero, which means use the
+ last directory opened by opendir. */
+static char dir_pathname[MAXPATHLEN];
+DIR *
+sys_opendir (const char *dirname)
+{
+ _fixpath (dirname, dir_pathname);
+ return opendir (dirname);
+}
+
+ssize_t
+readlinkat (int fd, char const *name, char *buffer, size_t buffer_size)
+{
+ /* Rely on a hack: an open directory is modeled as file descriptor 0,
+ as in fstatat. FIXME: Add proper support for readlinkat. */
+ char fullname[MAXPATHLEN];
+
+ if (fd != AT_FDCWD)
+ {
+ if (strlen (dir_pathname) + strlen (name) + 1 >= MAXPATHLEN)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ sprintf (fullname, "%s/%s", dir_pathname, name);
+ name = fullname;
+ }
+
+ return readlink (name, buffer, buffer_size);
+}
+
char *
careadlinkat (int fd, char const *filename,
char *buffer, size_t buffer_size,
return buffer;
}
-\f
-#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
-
-/* Augment DJGPP library POSIX signal functions. This is needed
- as of DJGPP v2.01, but might be in the library in later releases. */
-
-#include <libc/bss.h>
-
-/* A counter to know when to re-initialize the static sets. */
-static int sigprocmask_count = -1;
-
-/* Which signals are currently blocked (initially none). */
-static sigset_t current_mask;
-
-/* Which signals are pending (initially none). */
-static sigset_t msdos_pending_signals;
+/* Emulate faccessat(2). */
+int
+faccessat (int dirfd, const char * path, int mode, int flags)
+{
+ /* We silently ignore FLAGS. */
+ flags = flags;
-/* Previous handlers to restore when the blocked signals are unblocked. */
-typedef void (*sighandler_t)(int);
-static sighandler_t prev_handlers[320];
+ if (dirfd != AT_FDCWD
+ && !(IS_DIRECTORY_SEP (path[0])
+ || IS_DEVICE_SEP (path[1])))
+ {
+ errno = EBADF;
+ return -1;
+ }
-/* A signal handler which just records that a signal occurred
- (it will be raised later, if and when the signal is unblocked). */
-static void
-sig_suspender (int signo)
-{
- sigaddset (&msdos_pending_signals, signo);
+ return access (path, mode);
}
+/* Emulate fstatat. */
int
-sigprocmask (int how, const sigset_t *new_set, sigset_t *old_set)
+fstatat (int fd, char const *name, struct stat *st, int flags)
{
- int signo;
- sigset_t new_mask;
+ /* Rely on a hack: an open directory is modeled as file descriptor 0.
+ This is good enough for the current usage in Emacs, but is fragile.
- /* If called for the first time, initialize. */
- if (sigprocmask_count != __bss_count)
+ FIXME: Add proper support for fdopendir, fstatat, readlinkat.
+ Gnulib does this and can serve as a model. */
+ char fullname[MAXPATHLEN];
+
+ flags = flags;
+
+ if (fd != AT_FDCWD)
{
- sigprocmask_count = __bss_count;
- sigemptyset (&msdos_pending_signals);
- sigemptyset (¤t_mask);
- for (signo = 0; signo < 320; signo++)
- prev_handlers[signo] = SIG_ERR;
+ char lastc = dir_pathname[strlen (dir_pathname) - 1];
+
+ if (strlen (dir_pathname) + strlen (name) + IS_DIRECTORY_SEP (lastc)
+ >= MAXPATHLEN)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ sprintf (fullname, "%s%s%s",
+ dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name);
+ name = fullname;
}
- if (old_set)
- *old_set = current_mask;
+#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 3
+ return (flags & AT_SYMLINK_NOFOLLOW) ? lstat (name, st) : stat (name, st);
+#else
+ return stat (name, st);
+#endif
+}
- if (new_set == 0)
- return 0;
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 4
+/* Emulate the Posix unsetenv. DJGPP v2.04 has this in the library. */
+int
+unsetenv (const char *name)
+{
+ char *var;
+ size_t name_len;
+ int retval;
- if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK)
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
{
errno = EINVAL;
return -1;
}
- sigemptyset (&new_mask);
-
- /* DJGPP supports upto 320 signals. */
- for (signo = 0; signo < 320; signo++)
- {
- if (sigismember (¤t_mask, signo))
- sigaddset (&new_mask, signo);
- else if (sigismember (new_set, signo) && how != SIG_UNBLOCK)
- {
- sigaddset (&new_mask, signo);
+ /* DJGPP's 'putenv' deletes the entry if it doesn't include '='. */
+ putenv (name);
- /* SIGKILL is silently ignored, as on other platforms. */
- if (signo != SIGKILL && prev_handlers[signo] == SIG_ERR)
- prev_handlers[signo] = signal (signo, sig_suspender);
- }
- if (( how == SIG_UNBLOCK
- && sigismember (&new_mask, signo)
- && sigismember (new_set, signo))
- || (how == SIG_SETMASK
- && sigismember (&new_mask, signo)
- && !sigismember (new_set, signo)))
- {
- sigdelset (&new_mask, signo);
- if (prev_handlers[signo] != SIG_ERR)
- {
- signal (signo, prev_handlers[signo]);
- prev_handlers[signo] = SIG_ERR;
- }
- if (sigismember (&msdos_pending_signals, signo))
- {
- sigdelset (&msdos_pending_signals, signo);
- raise (signo);
- }
- }
- }
- current_mask = new_mask;
return 0;
}
+#endif
-#endif /* not __DJGPP_MINOR__ < 2 */
-
+\f
#ifndef HAVE_SELECT
#include "sysselect.h"
/* We don't have to call timer_check here
because wait_reading_process_output takes care of that. */
int
-sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
+sys_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
struct timespec *timeout, void *ignored)
{
int check_input;
dos_ttcooked ();
ScreenSetCursor (10, 0);
cputs ("\r\n\nEmacs aborted!\r\n");
-#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
- if (screen_virtual_segment)
- dosv_refresh_virtual_screen (2 * 10 * screen_size_X, 4 * screen_size_X);
- /* Generate traceback, so we could tell whodunit. */
- signal (SIGINT, SIG_DFL);
- __asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
-#else /* __DJGPP_MINOR__ >= 2 */
raise (SIGABRT);
-#endif /* __DJGPP_MINOR__ >= 2 */
exit (2);
}