2000-02-18 03:38:33 +08:00
|
|
|
/* fhandler_console.cc
|
|
|
|
|
2004-02-09 12:04:24 +08:00
|
|
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
2000-08-03 00:28:18 +08:00
|
|
|
#include "winsup.h"
|
2000-02-18 03:38:33 +08:00
|
|
|
#include <sys/termios.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2000-07-28 01:30:51 +08:00
|
|
|
#include <wingdi.h>
|
|
|
|
#include <winuser.h>
|
2000-09-03 12:16:35 +08:00
|
|
|
#include <wincon.h>
|
2002-06-26 13:29:41 +08:00
|
|
|
#include <winnls.h>
|
2000-02-18 03:38:33 +08:00
|
|
|
#include <ctype.h>
|
2000-09-08 10:56:55 +08:00
|
|
|
#include <sys/cygwin.h>
|
2000-08-22 11:58:47 +08:00
|
|
|
#include "cygerrno.h"
|
2001-07-27 03:22:24 +08:00
|
|
|
#include "security.h"
|
2001-10-01 12:10:07 +08:00
|
|
|
#include "path.h"
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
#include "fhandler.h"
|
2001-04-19 05:10:15 +08:00
|
|
|
#include "dtable.h"
|
|
|
|
#include "cygheap.h"
|
2000-08-22 13:10:20 +08:00
|
|
|
#include "sigproc.h"
|
|
|
|
#include "pinfo.h"
|
2000-09-08 00:23:51 +08:00
|
|
|
#include "shared_info.h"
|
2002-08-02 00:20:31 +08:00
|
|
|
#include "cygthread.h"
|
2004-05-16 12:18:50 +08:00
|
|
|
#include "cygtls.h"
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-04-03 07:01:11 +08:00
|
|
|
#define CONVERT_LIMIT 16384
|
2001-04-09 08:44:25 +08:00
|
|
|
|
2003-12-08 06:37:12 +08:00
|
|
|
static bool
|
2002-06-26 13:29:41 +08:00
|
|
|
cp_convert (UINT destcp, char *dest, UINT srccp, const char *src, DWORD size)
|
2001-04-09 08:44:25 +08:00
|
|
|
{
|
|
|
|
if (!size)
|
|
|
|
/* no action */;
|
|
|
|
else if (destcp == srccp)
|
|
|
|
{
|
|
|
|
if (dest != src)
|
|
|
|
memcpy (dest, src, size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WCHAR wbuffer[CONVERT_LIMIT]; /* same size as the maximum input, s.b. */
|
|
|
|
if (!MultiByteToWideChar (srccp, 0, src, size, wbuffer, sizeof (wbuffer)))
|
2003-12-08 06:37:12 +08:00
|
|
|
return false;
|
2001-04-09 08:44:25 +08:00
|
|
|
if (!WideCharToMultiByte (destcp, 0, wbuffer, size, dest, size,
|
|
|
|
NULL, NULL))
|
2003-12-08 06:37:12 +08:00
|
|
|
return false;
|
2001-04-09 08:44:25 +08:00
|
|
|
}
|
2003-12-08 06:37:12 +08:00
|
|
|
return true;
|
2001-04-09 08:44:25 +08:00
|
|
|
}
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/*
|
|
|
|
* Scroll the screen context.
|
|
|
|
* x1, y1 - ul corner
|
|
|
|
* x2, y2 - dr corner
|
|
|
|
* xn, yn - new ul corner
|
|
|
|
* Negative values represents current screen dimensions
|
|
|
|
*/
|
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
#define srTop (dev_state->info.winTop + dev_state->scroll_region.Top)
|
|
|
|
#define srBottom ((dev_state->scroll_region.Bottom < 0) ? dev_state->info.winBottom : dev_state->info.winTop + dev_state->scroll_region.Bottom)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
#define use_tty ISSTATE (myself, PID_USETTY)
|
|
|
|
|
2000-07-31 01:58:48 +08:00
|
|
|
const char * get_nonascii_key (INPUT_RECORD&, char *);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-15 04:25:52 +08:00
|
|
|
static console_state NO_COPY *shared_console_info;
|
2002-10-08 14:16:16 +08:00
|
|
|
|
|
|
|
dev_console NO_COPY *fhandler_console::dev_state;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
/* Allocate and initialize the shared record for the current console.
|
|
|
|
Returns a pointer to shared_console_info. */
|
2002-10-08 14:16:16 +08:00
|
|
|
tty_min *
|
|
|
|
fhandler_console::get_tty_stuff (int flags = 0)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2002-10-09 12:08:05 +08:00
|
|
|
if (dev_state)
|
2002-10-08 14:16:16 +08:00
|
|
|
return &shared_console_info->tty_min_state;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-15 15:03:45 +08:00
|
|
|
shared_console_info =
|
2002-10-08 14:16:16 +08:00
|
|
|
(console_state *) open_shared (NULL, 0, cygheap->console_h,
|
2002-10-15 04:25:52 +08:00
|
|
|
sizeof (*shared_console_info),
|
2002-10-15 15:03:45 +08:00
|
|
|
SH_SHARED_CONSOLE);
|
2002-10-09 12:08:05 +08:00
|
|
|
dev_state = &shared_console_info->dev_state;
|
|
|
|
|
2002-07-14 04:00:27 +08:00
|
|
|
ProtectHandleINH (cygheap->console_h);
|
2002-10-08 14:16:16 +08:00
|
|
|
if (!shared_console_info->tty_min_state.ntty)
|
2001-08-07 13:15:59 +08:00
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
shared_console_info->tty_min_state.setntty (TTY_CONSOLE);
|
|
|
|
shared_console_info->tty_min_state.setsid (myself->sid);
|
2003-12-11 14:12:41 +08:00
|
|
|
myself->set_ctty (&shared_console_info->tty_min_state, flags, NULL);
|
2002-10-08 14:16:16 +08:00
|
|
|
|
|
|
|
dev_state->scroll_region.Bottom = -1;
|
|
|
|
dev_state->dwLastCursorPosition.X = -1;
|
|
|
|
dev_state->dwLastCursorPosition.Y = -1;
|
|
|
|
dev_state->default_color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
|
|
dev_state->underline_color = FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
|
|
dev_state->dim_color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
|
|
|
dev_state->meta_mask = LEFT_ALT_PRESSED;
|
|
|
|
/* Set the mask that determines if an input keystroke is modified by
|
|
|
|
META. We set this based on the keyboard layout language loaded
|
|
|
|
for the current thread. The left <ALT> key always generates
|
|
|
|
META, but the right <ALT> key only generates META if we are using
|
|
|
|
an English keyboard because many "international" keyboards
|
|
|
|
replace common shell symbols ('[', '{', etc.) with accented
|
|
|
|
language-specific characters (umlaut, accent grave, etc.). On
|
|
|
|
these keyboards right <ALT> (called AltGr) is used to produce the
|
|
|
|
shell symbols and should not be interpreted as META. */
|
|
|
|
if (PRIMARYLANGID (LOWORD (GetKeyboardLayout (0))) == LANG_ENGLISH)
|
|
|
|
dev_state->meta_mask |= RIGHT_ALT_PRESSED;
|
2001-08-07 13:15:59 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
|
|
|
|
return &shared_console_info->tty_min_state;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2001-04-29 07:48:28 +08:00
|
|
|
void
|
|
|
|
set_console_ctty ()
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
(void) fhandler_console::get_tty_stuff ();
|
2001-04-29 07:48:28 +08:00
|
|
|
}
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Return the tty structure associated with a given tty number. If the
|
|
|
|
tty number is < 0, just return a dummy record. */
|
|
|
|
tty_min *
|
|
|
|
tty_list::get_tty (int n)
|
|
|
|
{
|
|
|
|
static tty_min nada;
|
|
|
|
if (n == TTY_CONSOLE)
|
2002-10-08 14:16:16 +08:00
|
|
|
return fhandler_console::get_tty_stuff ();
|
2000-02-18 03:38:33 +08:00
|
|
|
else if (n >= 0)
|
|
|
|
return &cygwin_shared->tty.ttys[n];
|
|
|
|
else
|
|
|
|
return &nada;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Determine if a console is associated with this process prior to a spawn.
|
|
|
|
If it is, then we'll return 1. If the console has been initialized, then
|
|
|
|
set it into a more friendly state for non-cygwin apps. */
|
|
|
|
int __stdcall
|
|
|
|
set_console_state_for_spawn ()
|
|
|
|
{
|
2002-09-19 23:12:48 +08:00
|
|
|
HANDLE h = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_WRITE,
|
|
|
|
&sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
|
|
|
|
NULL);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-09-19 23:12:48 +08:00
|
|
|
if (h == INVALID_HANDLE_VALUE)
|
2000-02-18 03:38:33 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (shared_console_info != NULL)
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
/* ACK. Temporarily define for use in TTYSETF macro */
|
2000-02-18 03:38:33 +08:00
|
|
|
SetConsoleMode (h, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
|
2004-04-10 21:45:10 +08:00
|
|
|
shared_console_info->tty_min_state.rstcons (true);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle (h);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-10-16 22:08:28 +08:00
|
|
|
/* The results of GetConsoleCP() and GetConsoleOutputCP() cannot be
|
|
|
|
cached, because a program or the user can change these values at
|
|
|
|
any time. */
|
2003-12-08 06:37:12 +08:00
|
|
|
inline bool
|
2003-10-16 22:08:28 +08:00
|
|
|
dev_console::con_to_str (char *d, const char *s, DWORD sz)
|
|
|
|
{
|
|
|
|
return cp_convert (get_cp (), d, GetConsoleCP (), s, sz);
|
|
|
|
}
|
|
|
|
|
2003-12-08 06:37:12 +08:00
|
|
|
inline bool
|
2003-10-16 22:08:28 +08:00
|
|
|
dev_console::str_to_con (char *d, const char *s, DWORD sz)
|
|
|
|
{
|
|
|
|
if (alternate_charset_active)
|
|
|
|
{
|
|
|
|
/* no translation when alternate charset is active */
|
|
|
|
memcpy(d, s, sz);
|
2003-12-08 06:37:12 +08:00
|
|
|
return true;
|
2003-10-16 22:08:28 +08:00
|
|
|
}
|
|
|
|
return cp_convert (GetConsoleOutputCP (), d, get_cp (), s, sz);
|
|
|
|
}
|
|
|
|
|
2003-12-08 06:37:12 +08:00
|
|
|
bool
|
|
|
|
fhandler_console::set_raw_win32_keyboard_mode (bool new_mode)
|
2001-02-27 17:14:35 +08:00
|
|
|
{
|
2003-12-08 06:37:12 +08:00
|
|
|
bool old_mode = dev_state->raw_win32_keyboard_mode;
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->raw_win32_keyboard_mode = new_mode;
|
|
|
|
syscall_printf ("raw keyboard mode %sabled", dev_state->raw_win32_keyboard_mode ? "en" : "dis");
|
2001-02-27 17:14:35 +08:00
|
|
|
return old_mode;
|
|
|
|
};
|
|
|
|
|
2000-07-30 00:24:59 +08:00
|
|
|
void
|
|
|
|
fhandler_console::set_cursor_maybe ()
|
|
|
|
{
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO now;
|
|
|
|
|
2001-04-09 08:44:25 +08:00
|
|
|
if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
|
2000-07-30 00:24:59 +08:00
|
|
|
return;
|
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->dwLastCursorPosition.X != now.dwCursorPosition.X ||
|
|
|
|
dev_state->dwLastCursorPosition.Y != now.dwCursorPosition.Y)
|
2000-07-30 00:24:59 +08:00
|
|
|
{
|
|
|
|
SetConsoleCursorPosition (get_output_handle (), now.dwCursorPosition);
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->dwLastCursorPosition = now.dwCursorPosition;
|
2000-07-30 00:24:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-19 12:43:58 +08:00
|
|
|
void
|
|
|
|
fhandler_console::send_winch_maybe ()
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
SHORT y = dev_state->info.dwWinSize.Y;
|
|
|
|
SHORT x = dev_state->info.dwWinSize.X;
|
2002-08-19 12:43:58 +08:00
|
|
|
fillin_info ();
|
2002-09-19 11:30:20 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (y != dev_state->info.dwWinSize.Y || x != dev_state->info.dwWinSize.X)
|
2002-12-27 13:31:30 +08:00
|
|
|
{
|
|
|
|
extern fhandler_tty_master *tty_master;
|
2003-01-25 09:17:51 +08:00
|
|
|
dev_state->scroll_region.Top = 0;
|
|
|
|
dev_state->scroll_region.Bottom = -1;
|
2002-12-27 13:31:30 +08:00
|
|
|
if (tty_master)
|
|
|
|
tty_master->set_winsize (true);
|
|
|
|
else
|
|
|
|
tc->kill_pgrp (SIGWINCH);
|
|
|
|
}
|
2002-08-19 12:43:58 +08:00
|
|
|
}
|
|
|
|
|
2002-12-14 12:01:32 +08:00
|
|
|
void __stdcall
|
|
|
|
fhandler_console::read (void *pv, size_t& buflen)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
HANDLE h = get_io_handle ();
|
|
|
|
|
|
|
|
#define buf ((char *) pv)
|
|
|
|
|
|
|
|
int ch;
|
|
|
|
set_input_state ();
|
2000-03-12 14:29:54 +08:00
|
|
|
|
|
|
|
int copied_chars = get_readahead_into_buffer (buf, buflen);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
if (copied_chars)
|
2002-12-14 12:01:32 +08:00
|
|
|
{
|
|
|
|
buflen = copied_chars;
|
|
|
|
return;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
HANDLE w4[2];
|
|
|
|
DWORD nwait;
|
2001-02-27 17:14:35 +08:00
|
|
|
char tmp[60];
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
w4[0] = h;
|
2004-05-16 12:18:50 +08:00
|
|
|
if (&_my_tls != _main_tls)
|
2000-03-12 12:44:37 +08:00
|
|
|
nwait = 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
w4[1] = signal_arrived;
|
|
|
|
nwait = 2;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-12-27 11:50:29 +08:00
|
|
|
termios ti = tc->ti;
|
2000-02-18 03:38:33 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
int bgres;
|
2001-01-17 22:57:09 +08:00
|
|
|
if ((bgres = bg_check (SIGTTIN)) <= bg_eof)
|
2002-12-14 12:01:32 +08:00
|
|
|
{
|
|
|
|
buflen = bgres;
|
|
|
|
return;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2000-07-30 00:24:59 +08:00
|
|
|
set_cursor_maybe (); /* to make cursor appear on the screen immediately */
|
2000-02-18 03:38:33 +08:00
|
|
|
switch (WaitForMultipleObjects (nwait, w4, FALSE, INFINITE))
|
|
|
|
{
|
|
|
|
case WAIT_OBJECT_0:
|
|
|
|
break;
|
|
|
|
case WAIT_OBJECT_0 + 1:
|
2001-03-05 14:28:25 +08:00
|
|
|
goto sig_exit;
|
2000-02-18 03:38:33 +08:00
|
|
|
default:
|
2002-12-14 12:01:32 +08:00
|
|
|
goto err;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2000-07-10 23:30:04 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
DWORD nread;
|
|
|
|
INPUT_RECORD input_rec;
|
2000-12-16 11:11:02 +08:00
|
|
|
const char *toadd = NULL;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2000-07-11 07:08:45 +08:00
|
|
|
if (!ReadConsoleInput (h, &input_rec, 1, &nread))
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2000-10-21 12:53:49 +08:00
|
|
|
syscall_printf ("ReadConsoleInput failed, %E");
|
2002-12-14 12:01:32 +08:00
|
|
|
goto err; /* seems to be failure */
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* check the event that occurred */
|
|
|
|
switch (input_rec.EventType)
|
|
|
|
{
|
|
|
|
case KEY_EVENT:
|
2001-02-27 17:14:35 +08:00
|
|
|
#define virtual_key_code (input_rec.Event.KeyEvent.wVirtualKeyCode)
|
|
|
|
#define control_key_state (input_rec.Event.KeyEvent.dwControlKeyState)
|
|
|
|
|
2003-09-27 10:36:50 +08:00
|
|
|
dev_state->nModifiers = 0;
|
|
|
|
|
2001-02-27 17:14:35 +08:00
|
|
|
#ifdef DEBUGGING
|
2001-03-03 11:56:34 +08:00
|
|
|
/* allow manual switching to/from raw mode via ctrl-alt-scrolllock */
|
|
|
|
if (input_rec.Event.KeyEvent.bKeyDown &&
|
|
|
|
virtual_key_code == VK_SCROLL &&
|
|
|
|
control_key_state & (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED) == LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED
|
|
|
|
)
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
set_raw_win32_keyboard_mode (!dev_state->raw_win32_keyboard_mode);
|
2001-03-03 11:56:34 +08:00
|
|
|
continue;
|
|
|
|
}
|
2001-02-27 17:14:35 +08:00
|
|
|
#endif
|
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->raw_win32_keyboard_mode)
|
2001-03-03 11:56:34 +08:00
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
__small_sprintf (tmp, "\033{%u;%u;%u;%u;%u;%luK",
|
|
|
|
input_rec.Event.KeyEvent.bKeyDown,
|
|
|
|
input_rec.Event.KeyEvent.wRepeatCount,
|
|
|
|
input_rec.Event.KeyEvent.wVirtualKeyCode,
|
|
|
|
input_rec.Event.KeyEvent.wVirtualScanCode,
|
|
|
|
input_rec.Event.KeyEvent.uChar.UnicodeChar,
|
|
|
|
input_rec.Event.KeyEvent.dwControlKeyState);
|
2001-03-03 11:56:34 +08:00
|
|
|
toadd = tmp;
|
|
|
|
nread = strlen (toadd);
|
|
|
|
break;
|
|
|
|
}
|
2001-02-27 17:14:35 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
#define ich (input_rec.Event.KeyEvent.uChar.AsciiChar)
|
2000-07-10 23:30:04 +08:00
|
|
|
#define wch (input_rec.Event.KeyEvent.uChar.UnicodeChar)
|
2001-06-23 04:08:06 +08:00
|
|
|
#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
|
|
|
|
#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2003-04-09 05:19:33 +08:00
|
|
|
/* Ignore key up events, except for left alt events with non-zero character
|
|
|
|
*/
|
|
|
|
if (!input_rec.Event.KeyEvent.bKeyDown &&
|
|
|
|
/*
|
|
|
|
Event for left alt, with a non-zero character, comes from
|
|
|
|
"alt + numerics" key sequence.
|
|
|
|
e.g. <left-alt> 0233 => é
|
|
|
|
*/
|
|
|
|
!(wch != 0
|
|
|
|
// ?? experimentally determined on an XP system
|
|
|
|
&& virtual_key_code == VK_MENU
|
|
|
|
// left alt -- see http://www.microsoft.com/hwdev/tech/input/Scancode.asp
|
|
|
|
&& input_rec.Event.KeyEvent.wVirtualScanCode == 0x38))
|
|
|
|
continue;
|
|
|
|
|
2003-09-27 10:36:50 +08:00
|
|
|
if (control_key_state & SHIFT_PRESSED)
|
|
|
|
dev_state->nModifiers |= 1;
|
|
|
|
if (control_key_state & RIGHT_ALT_PRESSED)
|
|
|
|
dev_state->nModifiers |= 2;
|
|
|
|
if (control_key_state & CTRL_PRESSED)
|
|
|
|
dev_state->nModifiers |= 4;
|
|
|
|
if (control_key_state & LEFT_ALT_PRESSED)
|
|
|
|
dev_state->nModifiers |= 8;
|
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
if (wch == 0 ||
|
|
|
|
/* arrow/function keys */
|
|
|
|
(input_rec.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
|
|
|
|
{
|
|
|
|
toadd = get_nonascii_key (input_rec, tmp);
|
|
|
|
if (!toadd)
|
2003-09-27 10:36:50 +08:00
|
|
|
{
|
|
|
|
dev_state->nModifiers = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2000-12-16 11:11:02 +08:00
|
|
|
nread = strlen (toadd);
|
|
|
|
}
|
2001-03-03 11:56:34 +08:00
|
|
|
else
|
|
|
|
{
|
2000-12-16 11:11:02 +08:00
|
|
|
tmp[1] = ich;
|
|
|
|
/* Need this check since US code page seems to have a bug when
|
|
|
|
converting a CTRL-U. */
|
2001-10-24 12:16:45 +08:00
|
|
|
if ((unsigned char) ich > 0x7f)
|
2003-10-16 22:08:28 +08:00
|
|
|
dev_state->con_to_str (tmp + 1, tmp + 1, 1);
|
2001-06-23 04:08:06 +08:00
|
|
|
/* Determine if the keystroke is modified by META. The tricky
|
|
|
|
part is to distinguish whether the right Alt key should be
|
|
|
|
recognized as Alt, or as AltGr. */
|
|
|
|
bool meta;
|
* Makefile.in: Build wincap.o.
* wincap.cc: New file.
* wincap.h: Ditto.
* autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
* dcrt0.cc (os_being_run): Eliminated.
(osname): Ditto.
(iswinnt): Ditto.
(set_os_type): Ditto.
(dll_crt0_1): Call wincap.init() instead of set_os_type().
(_dll_crt0): Ditto.
* environ.cc (set_chunksize): New function.
(parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
* fork.cc (chunksize): Eliminated. Moved to be member of wincap.
* host_dependent.h: Removed.
* syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
* cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
capability check throughout.
* winsup.h: Include wincap.h. Eliminate extern declarations of
`os_being_run' and `iswinnt'. Eliminate `os_type" definition.
* include/cygwin/version.h: Bump version to 1.3.4.
2001-09-13 01:46:37 +08:00
|
|
|
if (wincap.altgr_is_ctrl_alt ())
|
2001-06-23 04:08:06 +08:00
|
|
|
/* WinNT: AltGr is reported as Ctrl+Alt, and Ctrl+Alt is
|
|
|
|
treated just like AltGr. However, if Ctrl+Alt+key generates
|
|
|
|
an ASCII control character, interpret is as META. */
|
|
|
|
meta = (control_key_state & ALT_PRESSED) != 0
|
|
|
|
&& ((control_key_state & CTRL_PRESSED) == 0
|
2001-09-08 05:32:07 +08:00
|
|
|
|| (ich >= 0 && ich <= 0x1f || ich == 0x7f));
|
2001-06-23 04:08:06 +08:00
|
|
|
else
|
|
|
|
/* Win9x: there's no way to distinguish Alt from AltGr, so rely
|
2002-10-08 14:16:16 +08:00
|
|
|
on dev_state->meta_mask heuristic (see fhandler_console constructor). */
|
|
|
|
meta = (control_key_state & dev_state->meta_mask) != 0;
|
2001-06-23 04:08:06 +08:00
|
|
|
if (!meta)
|
2000-12-16 11:11:02 +08:00
|
|
|
toadd = tmp + 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp[0] = '\033';
|
|
|
|
tmp[1] = cyg_tolower (tmp[1]);
|
|
|
|
toadd = tmp;
|
|
|
|
nread++;
|
2003-09-27 10:36:50 +08:00
|
|
|
dev_state->nModifiers &= ~4;
|
2000-12-16 11:11:02 +08:00
|
|
|
}
|
2001-03-03 11:56:34 +08:00
|
|
|
}
|
2000-12-16 11:11:02 +08:00
|
|
|
#undef ich
|
|
|
|
#undef wch
|
2001-06-23 04:08:06 +08:00
|
|
|
#undef ALT_PRESSED
|
|
|
|
#undef CTRL_PRESSED
|
2000-12-16 11:11:02 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
case MOUSE_EVENT:
|
2002-08-19 12:43:58 +08:00
|
|
|
send_winch_maybe ();
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->use_mouse)
|
2000-12-15 12:42:20 +08:00
|
|
|
{
|
2002-08-19 12:43:58 +08:00
|
|
|
MOUSE_EVENT_RECORD& mouse_event = input_rec.Event.MouseEvent;
|
2000-12-16 11:11:02 +08:00
|
|
|
|
|
|
|
/* Treat the double-click event like a regular button press */
|
|
|
|
if (mouse_event.dwEventFlags == DOUBLE_CLICK)
|
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
syscall_printf ("mouse: double-click -> click");
|
2000-12-16 11:11:02 +08:00
|
|
|
mouse_event.dwEventFlags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Did something other than a click occur? */
|
|
|
|
if (mouse_event.dwEventFlags)
|
|
|
|
continue;
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* If the mouse event occurred out of the area we can handle,
|
|
|
|
ignore it. */
|
|
|
|
int x = mouse_event.dwMousePosition.X;
|
|
|
|
int y = mouse_event.dwMousePosition.Y;
|
|
|
|
if ((x + ' ' + 1 > 0xFF) || (y + ' ' + 1 > 0xFF))
|
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
syscall_printf ("mouse: position out of range");
|
2000-12-16 11:11:02 +08:00
|
|
|
continue;
|
|
|
|
}
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* Ignore unimportant mouse buttons */
|
|
|
|
mouse_event.dwButtonState &= 0x7;
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* This code assumes Windows never reports multiple button
|
|
|
|
events at the same time. */
|
|
|
|
int b = 0;
|
|
|
|
char sz[32];
|
2002-10-08 14:16:16 +08:00
|
|
|
if (mouse_event.dwButtonState == dev_state->dwLastButtonState)
|
2000-12-16 11:11:02 +08:00
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
syscall_printf ("mouse: button state unchanged");
|
2000-12-16 11:11:02 +08:00
|
|
|
continue;
|
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
else if (mouse_event.dwButtonState < dev_state->dwLastButtonState)
|
2000-12-16 11:11:02 +08:00
|
|
|
{
|
|
|
|
b = 3;
|
2001-04-09 08:44:25 +08:00
|
|
|
strcpy (sz, "btn up");
|
2000-12-16 11:11:02 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
else if ((mouse_event.dwButtonState & 1) != (dev_state->dwLastButtonState & 1))
|
2000-12-16 11:11:02 +08:00
|
|
|
{
|
|
|
|
b = 0;
|
2001-04-09 08:44:25 +08:00
|
|
|
strcpy (sz, "btn1 down");
|
2000-12-16 11:11:02 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
else if ((mouse_event.dwButtonState & 2) != (dev_state->dwLastButtonState & 2))
|
2000-12-16 11:11:02 +08:00
|
|
|
{
|
2002-11-14 03:36:12 +08:00
|
|
|
b = 2;
|
2001-04-09 08:44:25 +08:00
|
|
|
strcpy (sz, "btn2 down");
|
2000-12-16 11:11:02 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
else if ((mouse_event.dwButtonState & 4) != (dev_state->dwLastButtonState & 4))
|
2000-12-16 11:11:02 +08:00
|
|
|
{
|
2002-11-14 03:36:12 +08:00
|
|
|
b = 1;
|
2001-04-09 08:44:25 +08:00
|
|
|
strcpy (sz, "btn3 down");
|
2000-12-16 11:11:02 +08:00
|
|
|
}
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* Remember the current button state */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->dwLastButtonState = mouse_event.dwButtonState;
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* If a button was pressed, remember the modifiers */
|
|
|
|
if (b != 3)
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->nModifiers = 0;
|
2000-12-16 11:11:02 +08:00
|
|
|
if (mouse_event.dwControlKeyState & SHIFT_PRESSED)
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->nModifiers |= 0x4;
|
2000-12-16 11:11:02 +08:00
|
|
|
if (mouse_event.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->nModifiers |= 0x8;
|
2000-12-16 11:11:02 +08:00
|
|
|
if (mouse_event.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->nModifiers |= 0x10;
|
2000-12-16 11:11:02 +08:00
|
|
|
}
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
b |= dev_state->nModifiers;
|
2001-03-03 11:56:34 +08:00
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
/* We can now create the code. */
|
2001-04-09 08:44:25 +08:00
|
|
|
sprintf (tmp, "\033[M%c%c%c", b + ' ', x + ' ' + 1, y + ' ' + 1);
|
|
|
|
syscall_printf ("mouse: %s at (%d,%d)", sz, x, y);
|
2000-12-16 11:11:02 +08:00
|
|
|
|
2000-12-15 12:42:20 +08:00
|
|
|
toadd = tmp;
|
2000-12-16 11:11:02 +08:00
|
|
|
nread = 6;
|
2000-12-15 12:42:20 +08:00
|
|
|
}
|
2000-12-16 11:11:02 +08:00
|
|
|
break;
|
|
|
|
|
2002-08-19 12:43:58 +08:00
|
|
|
case FOCUS_EVENT:
|
2000-12-16 11:11:02 +08:00
|
|
|
case WINDOW_BUFFER_SIZE_EVENT:
|
2002-08-19 12:43:58 +08:00
|
|
|
send_winch_maybe ();
|
|
|
|
/* fall through */
|
2000-12-16 11:11:02 +08:00
|
|
|
default:
|
|
|
|
continue;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2001-03-05 14:28:25 +08:00
|
|
|
if (toadd)
|
|
|
|
{
|
2002-12-27 11:50:29 +08:00
|
|
|
line_edit_status res = line_edit (toadd, nread, ti);
|
2002-12-06 00:24:52 +08:00
|
|
|
if (res == line_edit_signalled)
|
2001-03-05 14:28:25 +08:00
|
|
|
goto sig_exit;
|
2002-12-06 00:24:52 +08:00
|
|
|
else if (res == line_edit_input_done)
|
2001-03-05 14:28:25 +08:00
|
|
|
break;
|
|
|
|
}
|
2000-12-15 12:42:20 +08:00
|
|
|
#undef ich
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
while (buflen)
|
|
|
|
if ((ch = get_readahead ()) < 0)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf[copied_chars++] = (unsigned char)(ch & 0xff);
|
|
|
|
buflen--;
|
|
|
|
}
|
|
|
|
#undef buf
|
|
|
|
|
2002-12-14 12:01:32 +08:00
|
|
|
buflen = copied_chars;
|
|
|
|
return;
|
|
|
|
|
|
|
|
err:
|
|
|
|
__seterrno ();
|
2003-09-05 09:55:01 +08:00
|
|
|
buflen = (size_t) -1;
|
2002-12-14 12:01:32 +08:00
|
|
|
return;
|
2001-03-05 14:28:25 +08:00
|
|
|
|
2003-09-09 11:11:31 +08:00
|
|
|
sig_exit:
|
2001-03-05 14:28:25 +08:00
|
|
|
set_sig_errno (EINTR);
|
2003-09-05 09:55:01 +08:00
|
|
|
buflen = (size_t) -1;
|
2002-12-14 12:01:32 +08:00
|
|
|
return;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2000-09-08 00:23:51 +08:00
|
|
|
void
|
|
|
|
fhandler_console::set_input_state ()
|
|
|
|
{
|
2004-04-10 21:45:10 +08:00
|
|
|
if (tc->rstcons ())
|
2000-09-08 00:23:51 +08:00
|
|
|
input_tcsetattr (0, &tc->ti);
|
|
|
|
}
|
|
|
|
|
2003-12-08 06:37:12 +08:00
|
|
|
bool
|
2000-02-18 03:38:33 +08:00
|
|
|
fhandler_console::fillin_info (void)
|
|
|
|
{
|
2003-12-08 06:37:12 +08:00
|
|
|
bool ret;
|
2000-02-18 03:38:33 +08:00
|
|
|
CONSOLE_SCREEN_BUFFER_INFO linfo;
|
|
|
|
|
2001-04-09 08:44:25 +08:00
|
|
|
if ((ret = GetConsoleScreenBufferInfo (get_output_handle (), &linfo)))
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->info.winTop = linfo.srWindow.Top;
|
|
|
|
dev_state->info.winBottom = linfo.srWindow.Bottom;
|
|
|
|
dev_state->info.dwWinSize.Y = 1 + linfo.srWindow.Bottom - linfo.srWindow.Top;
|
|
|
|
dev_state->info.dwWinSize.X = 1 + linfo.srWindow.Right - linfo.srWindow.Left;
|
|
|
|
dev_state->info.dwBufferSize = linfo.dwSize;
|
|
|
|
dev_state->info.dwCursorPosition = linfo.dwCursorPosition;
|
|
|
|
dev_state->info.wAttributes = linfo.wAttributes;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
memset (&dev_state->info, 0, sizeof dev_state->info);
|
|
|
|
dev_state->info.dwWinSize.Y = 25;
|
|
|
|
dev_state->info.dwWinSize.X = 80;
|
|
|
|
dev_state->info.winBottom = 24;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fhandler_console::scroll_screen (int x1, int y1, int x2, int y2, int xn, int yn)
|
|
|
|
{
|
|
|
|
SMALL_RECT sr1, sr2;
|
|
|
|
CHAR_INFO fill;
|
|
|
|
COORD dest;
|
|
|
|
|
2002-08-19 12:43:58 +08:00
|
|
|
(void) fillin_info ();
|
2002-10-08 14:16:16 +08:00
|
|
|
sr1.Left = x1 >= 0 ? x1 : dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (y1 == 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
sr1.Top = dev_state->info.winTop;
|
2000-02-18 03:38:33 +08:00
|
|
|
else
|
2002-10-08 14:16:16 +08:00
|
|
|
sr1.Top = y1 > 0 ? y1 : dev_state->info.winBottom;
|
|
|
|
sr1.Right = x2 >= 0 ? x2 : dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (y2 == 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
sr1.Bottom = dev_state->info.winTop;
|
2000-02-18 03:38:33 +08:00
|
|
|
else
|
2002-10-08 14:16:16 +08:00
|
|
|
sr1.Bottom = y2 > 0 ? y2 : dev_state->info.winBottom;
|
2000-02-18 03:38:33 +08:00
|
|
|
sr2.Top = srTop;
|
|
|
|
sr2.Left = 0;
|
|
|
|
sr2.Bottom = srBottom;
|
2002-10-08 14:16:16 +08:00
|
|
|
sr2.Right = dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (sr1.Bottom > sr2.Bottom && sr1.Top <= sr2.Bottom)
|
|
|
|
sr1.Bottom = sr2.Bottom;
|
2002-10-08 14:16:16 +08:00
|
|
|
dest.X = xn >= 0 ? xn : dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (yn == 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
dest.Y = dev_state->info.winTop;
|
2000-02-18 03:38:33 +08:00
|
|
|
else
|
2002-10-08 14:16:16 +08:00
|
|
|
dest.Y = yn > 0 ? yn : dev_state->info.winBottom;
|
2000-02-18 03:38:33 +08:00
|
|
|
fill.Char.AsciiChar = ' ';
|
2002-10-08 14:16:16 +08:00
|
|
|
fill.Attributes = dev_state->current_win32_attr;
|
2000-02-18 03:38:33 +08:00
|
|
|
ScrollConsoleScreenBuffer (get_output_handle (), &sr1, &sr2, dest, &fill);
|
|
|
|
|
|
|
|
/* ScrollConsoleScreenBuffer on Windows 95 is buggy - when scroll distance
|
|
|
|
* is more than half of screen, filling doesn't work as expected */
|
|
|
|
|
|
|
|
if (sr1.Top != sr1.Bottom)
|
|
|
|
if (dest.Y <= sr1.Top) /* forward scroll */
|
|
|
|
clear_screen (0, 1 + dest.Y + sr1.Bottom - sr1.Top, sr2.Right, sr2.Bottom);
|
|
|
|
else /* reverse scroll */
|
|
|
|
clear_screen (0, sr1.Top, sr2.Right, dest.Y - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
fhandler_console::open (int flags, mode_t)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
HANDLE h;
|
|
|
|
|
2001-04-29 07:48:28 +08:00
|
|
|
tcinit (get_tty_stuff (flags));
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-09-22 11:38:57 +08:00
|
|
|
set_io_handle (NULL);
|
|
|
|
set_output_handle (NULL);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-07-02 03:03:26 +08:00
|
|
|
set_flags ((flags & ~O_TEXT) | O_BINARY);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
/* Open the input handle as handle_ */
|
2002-09-19 23:12:48 +08:00
|
|
|
h = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none,
|
|
|
|
OPEN_EXISTING, 0, 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
set_io_handle (h);
|
2004-04-10 21:45:10 +08:00
|
|
|
uninterruptible_io (true); // Handled explicitly in read code
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-09-19 23:12:48 +08:00
|
|
|
h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none,
|
|
|
|
OPEN_EXISTING, 0, 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
set_output_handle (h);
|
|
|
|
|
|
|
|
if (fillin_info ())
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->default_color = dev_state->info.wAttributes;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2001-02-27 17:14:35 +08:00
|
|
|
set_default_attr ();
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
DWORD cflags;
|
|
|
|
if (GetConsoleMode (get_io_handle (), &cflags))
|
|
|
|
{
|
|
|
|
cflags |= ENABLE_PROCESSED_INPUT;
|
2000-12-16 11:11:02 +08:00
|
|
|
SetConsoleMode (get_io_handle (), ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | cflags);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
2004-04-10 21:45:10 +08:00
|
|
|
tc->rstcons (false);
|
2001-04-24 10:07:58 +08:00
|
|
|
set_open_status ();
|
2003-12-30 09:57:16 +08:00
|
|
|
cygheap->open_fhs++;
|
|
|
|
debug_printf ("incremented open_fhs, now %d", cygheap->open_fhs);
|
|
|
|
debug_printf ("opened conin$ %p, conout$ %p", get_io_handle (),
|
|
|
|
get_output_handle ());
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::close (void)
|
|
|
|
{
|
|
|
|
CloseHandle (get_io_handle ());
|
|
|
|
CloseHandle (get_output_handle ());
|
2002-09-22 11:38:57 +08:00
|
|
|
set_io_handle (NULL);
|
|
|
|
set_output_handle (NULL);
|
2004-01-17 11:47:27 +08:00
|
|
|
if (--(cygheap->open_fhs) <= 0 && myself->ctty != TTY_CONSOLE)
|
2003-03-14 07:11:38 +08:00
|
|
|
{
|
2004-01-16 03:51:49 +08:00
|
|
|
syscall_printf ("open_fhs %d", cygheap->open_fhs);
|
2003-03-14 07:11:38 +08:00
|
|
|
FreeConsole ();
|
|
|
|
}
|
2003-12-30 09:57:16 +08:00
|
|
|
debug_printf ("decremented open_fhs, now %d", cygheap->open_fhs);
|
2000-02-18 03:38:33 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special console dup to duplicate input and output
|
|
|
|
* handles.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::dup (fhandler_base *child)
|
|
|
|
{
|
|
|
|
fhandler_console *fhc = (fhandler_console *) child;
|
|
|
|
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
if (!fhc->open (get_flags () & ~O_NOCTTY, 0))
|
2000-02-18 03:38:33 +08:00
|
|
|
system_printf ("error opening console, %E");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::ioctl (unsigned int cmd, void *buf)
|
|
|
|
{
|
|
|
|
switch (cmd)
|
|
|
|
{
|
|
|
|
case TIOCGWINSZ:
|
|
|
|
int st;
|
|
|
|
|
|
|
|
st = fillin_info ();
|
|
|
|
if (st)
|
|
|
|
{
|
|
|
|
/* *not* the buffer size, the actual screen size... */
|
|
|
|
/* based on Left Top Right Bottom of srWindow */
|
2002-10-08 14:16:16 +08:00
|
|
|
((struct winsize *) buf)->ws_row = dev_state->info.dwWinSize.Y;
|
|
|
|
((struct winsize *) buf)->ws_col = dev_state->info.dwWinSize.X;
|
2000-02-18 03:38:33 +08:00
|
|
|
syscall_printf ("WINSZ: (row=%d,col=%d)",
|
|
|
|
((struct winsize *) buf)->ws_row,
|
|
|
|
((struct winsize *) buf)->ws_col);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
syscall_printf ("WINSZ failed");
|
|
|
|
__seterrno ();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case TIOCSWINSZ:
|
2000-02-21 13:20:38 +08:00
|
|
|
(void) bg_check (SIGTTOU);
|
2000-02-18 03:38:33 +08:00
|
|
|
return 0;
|
2003-09-27 10:36:50 +08:00
|
|
|
case TIOCLINUX:
|
|
|
|
if (* (int *) buf == 6)
|
|
|
|
{
|
|
|
|
* (int *) buf = dev_state->nModifiers;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
set_errno (EINVAL);
|
|
|
|
return -1;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return fhandler_base::ioctl (cmd, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::tcflush (int queue)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
if (queue == TCIFLUSH
|
|
|
|
|| queue == TCIOFLUSH)
|
|
|
|
{
|
|
|
|
if (!FlushConsoleInputBuffer (get_io_handle ()))
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
res = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::output_tcsetattr (int, struct termios const *t)
|
|
|
|
{
|
|
|
|
/* All the output bits we can ignore */
|
|
|
|
|
|
|
|
DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
|
|
|
|
|
|
int res = SetConsoleMode (get_output_handle (), flags) ? 0 : -1;
|
|
|
|
syscall_printf ("%d = tcsetattr (,%x) (ENABLE FLAGS %x) (lflag %x oflag %x)",
|
|
|
|
res, t, flags, t->c_lflag, t->c_oflag);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::input_tcsetattr (int, struct termios const *t)
|
|
|
|
{
|
|
|
|
/* Ignore the optional_actions stuff, since all output is emitted
|
|
|
|
instantly */
|
|
|
|
|
|
|
|
DWORD oflags;
|
|
|
|
|
|
|
|
if (!GetConsoleMode (get_io_handle (), &oflags))
|
|
|
|
oflags = 0;
|
|
|
|
DWORD flags = 0;
|
|
|
|
|
2002-06-05 12:01:43 +08:00
|
|
|
#if 0
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Enable/disable LF -> CRLF conversions */
|
2004-04-10 21:45:10 +08:00
|
|
|
rbinary ((t->c_iflag & INLCR) ? false : true);
|
2002-06-05 12:01:43 +08:00
|
|
|
#endif
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
/* There's some disparity between what we need and what's
|
|
|
|
available. We've got ECHO and ICANON, they've
|
|
|
|
got ENABLE_ECHO_INPUT and ENABLE_LINE_INPUT. */
|
|
|
|
|
|
|
|
tc->ti = *t;
|
|
|
|
|
|
|
|
if (t->c_lflag & ECHO)
|
|
|
|
{
|
|
|
|
flags |= ENABLE_ECHO_INPUT;
|
|
|
|
}
|
|
|
|
if (t->c_lflag & ICANON)
|
|
|
|
{
|
|
|
|
flags |= ENABLE_LINE_INPUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & ENABLE_ECHO_INPUT
|
|
|
|
&& !(flags & ENABLE_LINE_INPUT))
|
|
|
|
{
|
|
|
|
/* This is illegal, so turn off the echo here, and fake it
|
|
|
|
when we read the characters */
|
|
|
|
|
|
|
|
flags &= ~ENABLE_ECHO_INPUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t->c_lflag & ISIG)
|
|
|
|
{
|
|
|
|
flags |= ENABLE_PROCESSED_INPUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_tty)
|
|
|
|
{
|
|
|
|
flags = 0; // ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
|
|
tc->ti.c_iflag = 0;
|
|
|
|
tc->ti.c_lflag = 0;
|
|
|
|
}
|
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
flags |= ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
int res;
|
|
|
|
if (flags == oflags)
|
|
|
|
res = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
res = SetConsoleMode (get_io_handle (), flags) ? 0 : -1;
|
|
|
|
if (res < 0)
|
|
|
|
__seterrno ();
|
|
|
|
syscall_printf ("%d = tcsetattr (,%x) enable flags %p, c_lflag %p iflag %p",
|
|
|
|
res, t, flags, t->c_lflag, t->c_iflag);
|
|
|
|
}
|
|
|
|
|
2004-04-10 21:45:10 +08:00
|
|
|
tc->rstcons (false);
|
2000-02-18 03:38:33 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::tcsetattr (int a, struct termios const *t)
|
|
|
|
{
|
|
|
|
int res = output_tcsetattr (a, t);
|
|
|
|
if (res != 0)
|
|
|
|
return res;
|
|
|
|
return input_tcsetattr (a, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::tcgetattr (struct termios *t)
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
*t = tc->ti;
|
|
|
|
|
|
|
|
t->c_cflag |= CS8;
|
|
|
|
|
|
|
|
DWORD flags;
|
|
|
|
|
|
|
|
if (!GetConsoleMode (get_io_handle (), &flags))
|
|
|
|
{
|
|
|
|
__seterrno ();
|
|
|
|
res = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (flags & ENABLE_ECHO_INPUT)
|
|
|
|
t->c_lflag |= ECHO;
|
|
|
|
|
|
|
|
if (flags & ENABLE_LINE_INPUT)
|
|
|
|
t->c_lflag |= ICANON;
|
|
|
|
|
|
|
|
if (flags & ENABLE_PROCESSED_INPUT)
|
|
|
|
t->c_lflag |= ISIG;
|
|
|
|
|
|
|
|
/* What about ENABLE_WINDOW_INPUT
|
|
|
|
and ENABLE_MOUSE_INPUT ? */
|
|
|
|
|
|
|
|
/* All the output bits we can ignore */
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
syscall_printf ("%d = tcgetattr (%p) enable flags %p, t->lflag %p, t->iflag %p",
|
|
|
|
res, t, flags, t->c_lflag, t->c_iflag);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2001-10-14 01:23:35 +08:00
|
|
|
fhandler_console::fhandler_console () :
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
fhandler_termios ()
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2001-02-27 17:14:35 +08:00
|
|
|
#define FOREGROUND_ATTR_MASK (FOREGROUND_RED | FOREGROUND_GREEN | \
|
2001-03-03 11:56:34 +08:00
|
|
|
FOREGROUND_BLUE | FOREGROUND_INTENSITY)
|
2001-02-27 17:14:35 +08:00
|
|
|
#define BACKGROUND_ATTR_MASK (BACKGROUND_RED | BACKGROUND_GREEN | \
|
2001-03-03 11:56:34 +08:00
|
|
|
BACKGROUND_BLUE | BACKGROUND_INTENSITY)
|
2001-02-27 17:14:35 +08:00
|
|
|
void
|
|
|
|
fhandler_console::set_default_attr ()
|
|
|
|
{
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->blink = dev_state->underline = dev_state->reverse = false;
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->intensity = INTENSITY_NORMAL;
|
|
|
|
dev_state->fg = dev_state->default_color & FOREGROUND_ATTR_MASK;
|
|
|
|
dev_state->bg = dev_state->default_color & BACKGROUND_ATTR_MASK;
|
|
|
|
dev_state->current_win32_attr = get_win32_attr ();
|
|
|
|
SetConsoleTextAttribute (get_output_handle (), dev_state->current_win32_attr);
|
2001-02-27 17:14:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
WORD
|
|
|
|
fhandler_console::get_win32_attr ()
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
WORD win_fg = dev_state->fg;
|
|
|
|
WORD win_bg = dev_state->bg;
|
|
|
|
if (dev_state->reverse)
|
2001-03-03 11:56:34 +08:00
|
|
|
{
|
2001-02-27 17:14:35 +08:00
|
|
|
WORD save_fg = win_fg;
|
2001-03-03 11:56:34 +08:00
|
|
|
win_fg = (win_bg & BACKGROUND_RED ? FOREGROUND_RED : 0) |
|
|
|
|
(win_bg & BACKGROUND_GREEN ? FOREGROUND_GREEN : 0) |
|
|
|
|
(win_bg & BACKGROUND_BLUE ? FOREGROUND_BLUE : 0) |
|
|
|
|
(win_fg & FOREGROUND_INTENSITY);
|
|
|
|
win_bg = (save_fg & FOREGROUND_RED ? BACKGROUND_RED : 0) |
|
|
|
|
(save_fg & FOREGROUND_GREEN ? BACKGROUND_GREEN : 0) |
|
|
|
|
(save_fg & FOREGROUND_BLUE ? BACKGROUND_BLUE : 0) |
|
|
|
|
(win_bg & BACKGROUND_INTENSITY);
|
2001-02-27 17:14:35 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->underline)
|
|
|
|
win_fg = dev_state->underline_color;
|
2001-02-27 17:14:35 +08:00
|
|
|
/* emulate blink with bright background */
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->blink)
|
|
|
|
win_bg |= BACKGROUND_INTENSITY;
|
|
|
|
if (dev_state->intensity == INTENSITY_INVISIBLE)
|
2001-02-27 17:14:35 +08:00
|
|
|
win_fg = win_bg;
|
2002-10-08 14:16:16 +08:00
|
|
|
else if (dev_state->intensity == INTENSITY_BOLD)
|
2001-02-27 17:14:35 +08:00
|
|
|
win_fg |= FOREGROUND_INTENSITY;
|
2001-03-03 11:56:34 +08:00
|
|
|
return (win_fg | win_bg);
|
2001-02-27 17:14:35 +08:00
|
|
|
}
|
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/*
|
|
|
|
* Clear the screen context from x1/y1 to x2/y2 cell.
|
|
|
|
* Negative values represents current screen dimensions
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
fhandler_console::clear_screen (int x1, int y1, int x2, int y2)
|
|
|
|
{
|
|
|
|
COORD tlc;
|
|
|
|
DWORD done;
|
|
|
|
int num;
|
|
|
|
|
|
|
|
(void)fillin_info ();
|
|
|
|
|
|
|
|
if (x1 < 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
x1 = dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (y1 < 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
y1 = dev_state->info.winBottom;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (x2 < 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
x2 = dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (y2 < 0)
|
2002-10-08 14:16:16 +08:00
|
|
|
y2 = dev_state->info.winBottom;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
num = abs (y1 - y2) * dev_state->info.dwBufferSize.X + abs (x1 - x2) + 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if ((y2 * dev_state->info.dwBufferSize.X + x2) > (y1 * dev_state->info.dwBufferSize.X + x1))
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
tlc.X = x1;
|
|
|
|
tlc.Y = y1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tlc.X = x2;
|
|
|
|
tlc.Y = y2;
|
|
|
|
}
|
|
|
|
FillConsoleOutputCharacterA (get_output_handle (), ' ',
|
|
|
|
num,
|
|
|
|
tlc,
|
|
|
|
&done);
|
|
|
|
FillConsoleOutputAttribute (get_output_handle (),
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->current_win32_attr,
|
2000-02-18 03:38:33 +08:00
|
|
|
num,
|
|
|
|
tlc,
|
|
|
|
&done);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-12-08 06:37:12 +08:00
|
|
|
fhandler_console::cursor_set (bool rel_to_top, int x, int y)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
COORD pos;
|
|
|
|
|
2002-08-19 12:43:58 +08:00
|
|
|
(void) fillin_info ();
|
2002-10-08 14:16:16 +08:00
|
|
|
if (y > dev_state->info.winBottom)
|
|
|
|
y = dev_state->info.winBottom;
|
2000-02-18 03:38:33 +08:00
|
|
|
else if (y < 0)
|
|
|
|
y = 0;
|
|
|
|
else if (rel_to_top)
|
2002-10-08 14:16:16 +08:00
|
|
|
y += dev_state->info.winTop;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (x > dev_state->info.dwWinSize.X)
|
|
|
|
x = dev_state->info.dwWinSize.X - 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
else if (x < 0)
|
|
|
|
x = 0;
|
|
|
|
|
|
|
|
pos.X = x;
|
|
|
|
pos.Y = y;
|
|
|
|
SetConsoleCursorPosition (get_output_handle (), pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fhandler_console::cursor_rel (int x, int y)
|
|
|
|
{
|
|
|
|
fillin_info ();
|
2002-10-08 14:16:16 +08:00
|
|
|
x += dev_state->info.dwCursorPosition.X;
|
|
|
|
y += dev_state->info.dwCursorPosition.Y;
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, x, y);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fhandler_console::cursor_get (int *x, int *y)
|
|
|
|
{
|
|
|
|
fillin_info ();
|
2002-10-08 14:16:16 +08:00
|
|
|
*y = dev_state->info.dwCursorPosition.Y;
|
|
|
|
*x = dev_state->info.dwCursorPosition.X;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define BAK 1
|
|
|
|
#define ESC 2
|
|
|
|
#define NOR 0
|
|
|
|
#define IGN 4
|
|
|
|
#if 0
|
|
|
|
#define ERR 5
|
|
|
|
#else
|
|
|
|
#define ERR NOR
|
|
|
|
#endif
|
|
|
|
#define DWN 6
|
|
|
|
#define BEL 7
|
|
|
|
#define TAB 8 /* We should't let the console deal with these */
|
|
|
|
#define CR 13
|
|
|
|
#define LF 10
|
|
|
|
|
|
|
|
static const char base_chars[256] =
|
|
|
|
{
|
|
|
|
/*00 01 02 03 04 05 06 07 */ IGN, ERR, ERR, NOR, NOR, NOR, NOR, BEL,
|
|
|
|
/*08 09 0A 0B 0C 0D 0E 0F */ BAK, TAB, DWN, ERR, ERR, CR, ERR, IGN,
|
|
|
|
/*10 11 12 13 14 15 16 17 */ NOR, NOR, ERR, ERR, ERR, ERR, ERR, ERR,
|
|
|
|
/*18 19 1A 1B 1C 1D 1E 1F */ NOR, NOR, ERR, ESC, ERR, ERR, ERR, ERR,
|
|
|
|
/* ! " # $ % & ' */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
2001-03-03 11:56:34 +08:00
|
|
|
/*() * + , - . / */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
2000-02-18 03:38:33 +08:00
|
|
|
/*0 1 2 3 4 5 6 7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*8 9 : ; < = > ? */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*@ A B C D E F G */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*H I J K L M N O */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*P Q R S T U V W */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*X Y Z [ \ ] ^ _ */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*` a b c d e f g */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*h i j k l m n o */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*p q r s t u v w */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*x y z { | } ~ 7F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*80 81 82 83 84 85 86 87 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*88 89 8A 8B 8C 8D 8E 8F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*90 91 92 93 94 95 96 97 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*98 99 9A 9B 9C 9D 9E 9F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*A0 A1 A2 A3 A4 A5 A6 A7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*A8 A9 AA AB AC AD AE AF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*B0 B1 B2 B3 B4 B5 B6 B7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*B8 B9 BA BB BC BD BE BF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*C0 C1 C2 C3 C4 C5 C6 C7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*C8 C9 CA CB CC CD CE CF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*D0 D1 D2 D3 D4 D5 D6 D7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*D8 D9 DA DB DC DD DE DF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*E0 E1 E2 E3 E4 E5 E6 E7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*E8 E9 EA EB EC ED EE EF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*F0 F1 F2 F3 F4 F5 F6 F7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
|
|
|
|
/*F8 F9 FA FB FC FD FE FF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR };
|
|
|
|
|
|
|
|
void
|
2001-02-27 17:14:35 +08:00
|
|
|
fhandler_console::char_command (char c)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
char buf[40];
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 'm': /* Set Graphics Rendition */
|
|
|
|
int i;
|
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
for (i = 0; i <= dev_state->nargs_; i++)
|
|
|
|
switch (dev_state->args_[i])
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
case 0: /* normal color */
|
2001-03-03 11:56:34 +08:00
|
|
|
set_default_attr ();
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 1: /* bold */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->intensity = INTENSITY_BOLD;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
2001-03-03 11:56:34 +08:00
|
|
|
case 4:
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->underline = 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 5: /* blink mode */
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->blink = true;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 7: /* reverse */
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->reverse = true;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 8: /* invisible */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->intensity = INTENSITY_INVISIBLE;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 9: /* dim */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->intensity = INTENSITY_DIM;
|
2001-03-03 11:56:34 +08:00
|
|
|
break;
|
2004-05-29 03:50:07 +08:00
|
|
|
case 10: /* end alternate charset */
|
|
|
|
dev_state->alternate_charset_active = false;
|
2003-10-15 16:23:26 +08:00
|
|
|
break;
|
2004-05-29 03:50:07 +08:00
|
|
|
case 11: /* start alternate charset */
|
|
|
|
dev_state->alternate_charset_active = true;
|
2003-10-15 16:23:26 +08:00
|
|
|
break;
|
2001-03-03 11:56:34 +08:00
|
|
|
case 24:
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->underline = false;
|
2001-03-03 11:56:34 +08:00
|
|
|
break;
|
|
|
|
case 27:
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->reverse = false;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 30: /* BLACK foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = 0;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 31: /* RED foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_RED;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 32: /* GREEN foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_GREEN;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 33: /* YELLOW foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_RED | FOREGROUND_GREEN;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 34: /* BLUE foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_BLUE;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 35: /* MAGENTA foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_RED | FOREGROUND_BLUE;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 36: /* CYAN foreground */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_BLUE | FOREGROUND_GREEN;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 37: /* WHITE foreg */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
2001-03-03 11:56:34 +08:00
|
|
|
case 39:
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->fg = dev_state->default_color & FOREGROUND_ATTR_MASK;
|
2001-03-03 11:56:34 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
case 40: /* BLACK background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = 0;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 41: /* RED background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_RED;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 42: /* GREEN background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_GREEN;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 43: /* YELLOW background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_RED | BACKGROUND_GREEN;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 44: /* BLUE background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_BLUE;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 45: /* MAGENTA background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_RED | BACKGROUND_BLUE;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 46: /* CYAN background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_BLUE | BACKGROUND_GREEN;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 47: /* WHITE background */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
2001-03-03 11:56:34 +08:00
|
|
|
case 49:
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->bg = dev_state->default_color & BACKGROUND_ATTR_MASK;
|
2001-03-03 11:56:34 +08:00
|
|
|
break;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->current_win32_attr = get_win32_attr ();
|
|
|
|
SetConsoleTextAttribute (get_output_handle (), dev_state->current_win32_attr);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
case 'l':
|
2002-10-08 14:16:16 +08:00
|
|
|
if (!dev_state->saw_question_mark)
|
2001-04-09 08:44:25 +08:00
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
switch (dev_state->args_[0])
|
2001-03-31 17:19:32 +08:00
|
|
|
{
|
|
|
|
case 4: /* Insert mode */
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->insert_mode = (c == 'h') ? true : false;
|
2002-10-08 14:16:16 +08:00
|
|
|
syscall_printf ("insert mode %sabled", dev_state->insert_mode ? "en" : "dis");
|
2001-03-31 17:19:32 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
switch (dev_state->args_[0])
|
2000-12-16 11:11:02 +08:00
|
|
|
{
|
2001-03-30 19:10:13 +08:00
|
|
|
case 47: /* Save/Restore screen */
|
|
|
|
if (c == 'h') /* save */
|
|
|
|
{
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO now;
|
|
|
|
COORD cob = { 0, 0 };
|
|
|
|
|
|
|
|
if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
|
2001-04-09 08:44:25 +08:00
|
|
|
break;
|
2001-03-30 19:10:13 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->savebufsiz.X = now.srWindow.Right - now.srWindow.Left + 1;
|
|
|
|
dev_state->savebufsiz.Y = now.srWindow.Bottom - now.srWindow.Top + 1;
|
2001-03-30 19:10:13 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->savebuf)
|
|
|
|
cfree (dev_state->savebuf);
|
|
|
|
dev_state->savebuf = (PCHAR_INFO) cmalloc (HEAP_1_BUF, sizeof (CHAR_INFO) *
|
|
|
|
dev_state->savebufsiz.X * dev_state->savebufsiz.Y);
|
2001-03-30 19:10:13 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
ReadConsoleOutputA (get_output_handle (), dev_state->savebuf,
|
|
|
|
dev_state->savebufsiz, cob, &now.srWindow);
|
2001-03-30 19:10:13 +08:00
|
|
|
}
|
2002-05-28 09:55:40 +08:00
|
|
|
else /* restore */
|
2001-03-30 19:10:13 +08:00
|
|
|
{
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO now;
|
|
|
|
COORD cob = { 0, 0 };
|
|
|
|
|
|
|
|
if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
|
2001-04-09 08:44:25 +08:00
|
|
|
break;
|
2001-03-30 19:10:13 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (!dev_state->savebuf)
|
2001-04-09 08:44:25 +08:00
|
|
|
break;
|
2001-03-30 19:10:13 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
WriteConsoleOutputA (get_output_handle (), dev_state->savebuf,
|
|
|
|
dev_state->savebufsiz, cob, &now.srWindow);
|
2001-03-30 19:10:13 +08:00
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
cfree (dev_state->savebuf);
|
|
|
|
dev_state->savebuf = NULL;
|
|
|
|
dev_state->savebufsiz.X = dev_state->savebufsiz.Y = 0;
|
2001-03-30 19:10:13 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
case 1000: /* Mouse support */
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->use_mouse = (c == 'h') ? true : false;
|
2002-10-08 14:16:16 +08:00
|
|
|
syscall_printf ("mouse support %sabled", dev_state->use_mouse ? "en" : "dis");
|
2000-12-16 11:11:02 +08:00
|
|
|
break;
|
|
|
|
|
2001-03-03 11:56:34 +08:00
|
|
|
case 2000: /* Raw keyboard mode */
|
2003-12-08 06:37:12 +08:00
|
|
|
set_raw_win32_keyboard_mode ((c == 'h') ? true : false);
|
2001-03-03 11:56:34 +08:00
|
|
|
break;
|
|
|
|
|
2000-12-16 11:11:02 +08:00
|
|
|
default: /* Ignore */
|
2002-10-08 14:16:16 +08:00
|
|
|
syscall_printf ("unknown h/l command: %d", dev_state->args_[0]);
|
2000-12-16 11:11:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'J':
|
2002-10-08 14:16:16 +08:00
|
|
|
switch (dev_state->args_[0])
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
case 0: /* Clear to end of screen */
|
|
|
|
cursor_get (&x, &y);
|
|
|
|
clear_screen (x, y, -1, -1);
|
|
|
|
break;
|
|
|
|
case 1: /* Clear from beginning of screen to cursor */
|
|
|
|
cursor_get (&x, &y);
|
|
|
|
clear_screen (0, 0, x, y);
|
|
|
|
break;
|
|
|
|
case 2: /* Clear screen */
|
|
|
|
clear_screen (0, 0, -1, -1);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, 0,0);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto bad_escape;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'A':
|
2002-10-08 14:16:16 +08:00
|
|
|
cursor_rel (0, -(dev_state->args_[0] ? dev_state->args_[0] : 1));
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'B':
|
2002-10-08 14:16:16 +08:00
|
|
|
cursor_rel (0, dev_state->args_[0] ? dev_state->args_[0] : 1);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'C':
|
2002-10-08 14:16:16 +08:00
|
|
|
cursor_rel (dev_state->args_[0] ? dev_state->args_[0] : 1, 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'D':
|
2002-10-08 14:16:16 +08:00
|
|
|
cursor_rel (-(dev_state->args_[0] ? dev_state->args_[0] : 1),0);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'K':
|
2002-10-08 14:16:16 +08:00
|
|
|
switch (dev_state->args_[0])
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
case 0: /* Clear to end of line */
|
|
|
|
cursor_get (&x, &y);
|
|
|
|
clear_screen (x, y, -1, y);
|
|
|
|
break;
|
|
|
|
case 2: /* Clear line */
|
|
|
|
cursor_get (&x, &y);
|
|
|
|
clear_screen (0, y, -1, y);
|
|
|
|
break;
|
|
|
|
case 1: /* Clear from bol to cursor */
|
|
|
|
cursor_get (&x, &y);
|
|
|
|
clear_screen (0, y, x, y);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto bad_escape;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
case 'f':
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, (dev_state->args_[1] ? dev_state->args_[1] : 1) - 1,
|
2002-10-08 14:16:16 +08:00
|
|
|
(dev_state->args_[0] ? dev_state->args_[0] : 1) - 1);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'G': /* hpa - position cursor at column n - 1 */
|
|
|
|
cursor_get (&x, &y);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, (dev_state->args_[0] ? dev_state->args_[0] - 1 : 0), y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'd': /* vpa - position cursor at line n */
|
|
|
|
cursor_get (&x, &y);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, x, (dev_state->args_[0] ? dev_state->args_[0] - 1 : 0));
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 's': /* Save cursor position */
|
2002-10-08 14:16:16 +08:00
|
|
|
cursor_get (&dev_state->savex, &dev_state->savey);
|
|
|
|
dev_state->savey -= dev_state->info.winTop;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'u': /* Restore cursor position */
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, dev_state->savex, dev_state->savey);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'I': /* TAB */
|
|
|
|
cursor_get (&x, &y);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, 8 * (x / 8 + 1), y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'L': /* AL - insert blank lines */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (0, y, -1, -1, 0, y + dev_state->args_[0]);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'M': /* DL - delete lines */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (0, y + dev_state->args_[0], -1, -1, 0, y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case '@': /* IC - insert chars */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (x, y, -1, y, x + dev_state->args_[0], y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'P': /* DC - delete chars */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (x + dev_state->args_[0], y, -1, y, x, y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'S': /* SF - Scroll forward */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
|
|
|
scroll_screen (0, dev_state->args_[0], -1, -1, 0, 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'T': /* SR - Scroll down */
|
|
|
|
fillin_info ();
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
|
|
|
scroll_screen (0, 0, -1, -1, 0, dev_state->info.winTop + dev_state->args_[0]);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'X': /* ec - erase chars */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
|
2000-02-18 03:38:33 +08:00
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (x + dev_state->args_[0], y, -1, y, x, y);
|
|
|
|
scroll_screen (x, y, -1, y, x + dev_state->args_[0], y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'Z': /* Back tab */
|
|
|
|
cursor_get (&x, &y);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, ((8 * (x / 8 + 1)) - 8), y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'b': /* Repeat char #1 #2 times */
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->insert_mode)
|
2001-03-31 17:19:32 +08:00
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (x, y, -1, y, x + dev_state->args_[1], y);
|
2001-03-31 17:19:32 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
while (dev_state->args_[1]--)
|
|
|
|
WriteFile (get_output_handle (), &dev_state->args_[0], 1, (DWORD *) &x, 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'c': /* u9 - Terminal enquire string */
|
|
|
|
strcpy (buf, "\033[?6c");
|
|
|
|
puts_readahead (buf);
|
|
|
|
break;
|
|
|
|
case 'n':
|
2002-10-08 14:16:16 +08:00
|
|
|
switch (dev_state->args_[0])
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
case 6: /* u7 - Cursor position request */
|
|
|
|
cursor_get (&x, &y);
|
2002-10-08 14:16:16 +08:00
|
|
|
y -= dev_state->info.winTop;
|
|
|
|
/* x -= dev_state->info.winLeft; // not available yet */
|
2000-02-18 03:38:33 +08:00
|
|
|
__small_sprintf (buf, "\033[%d;%dR", y + 1, x + 1);
|
|
|
|
puts_readahead (buf);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto bad_escape;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r': /* Set Scroll region */
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->scroll_region.Top = dev_state->args_[0] ? dev_state->args_[0] - 1 : 0;
|
|
|
|
dev_state->scroll_region.Bottom = dev_state->args_[1] ? dev_state->args_[1] - 1 : -1;
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, 0, 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case 'g': /* TAB set/clear */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
bad_escape:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const unsigned char *
|
|
|
|
fhandler_console::write_normal (const unsigned char *src,
|
|
|
|
const unsigned char *end)
|
|
|
|
{
|
|
|
|
/* Scan forward to see what a char which needs special treatment */
|
|
|
|
DWORD done;
|
|
|
|
const unsigned char *found = src;
|
|
|
|
|
|
|
|
while (found < end)
|
|
|
|
{
|
|
|
|
if (base_chars[*found] != NOR)
|
|
|
|
break;
|
|
|
|
found++;
|
|
|
|
}
|
2001-04-09 08:44:25 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Print all the base ones out */
|
|
|
|
if (found != src)
|
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
DWORD len = found - src;
|
|
|
|
do
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2001-04-09 08:44:25 +08:00
|
|
|
DWORD buf_len;
|
|
|
|
char buf[CONVERT_LIMIT];
|
|
|
|
done = buf_len = min (sizeof (buf), len);
|
2003-10-16 22:08:28 +08:00
|
|
|
if (!dev_state->str_to_con (buf, (const char *) src, buf_len))
|
2001-04-09 08:44:25 +08:00
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
debug_printf ("conversion error, handle %p",
|
|
|
|
get_output_handle ());
|
2001-04-09 08:44:25 +08:00
|
|
|
__seterrno ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-10-08 14:16:16 +08:00
|
|
|
if (dev_state->insert_mode)
|
2001-04-09 08:44:25 +08:00
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
cursor_get (&x, &y);
|
|
|
|
scroll_screen (x, y, -1, y, x + buf_len, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!WriteFile (get_output_handle (), buf, buf_len, &done, 0))
|
|
|
|
{
|
|
|
|
debug_printf ("write failed, handle %p", get_output_handle ());
|
|
|
|
__seterrno ();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
len -= done;
|
|
|
|
src += done;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2001-04-09 08:44:25 +08:00
|
|
|
while (len > 0);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2001-04-09 08:44:25 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
if (src < end)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
switch (base_chars[*src])
|
|
|
|
{
|
|
|
|
case BEL:
|
2003-02-14 07:51:41 +08:00
|
|
|
MessageBeep (0xFFFFFFFF);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case ESC:
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = gotesc;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
2002-06-01 06:35:57 +08:00
|
|
|
case DWN:
|
2000-02-18 03:38:33 +08:00
|
|
|
cursor_get (&x, &y);
|
|
|
|
if (y >= srBottom)
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
if (y >= dev_state->info.winBottom && !dev_state->scroll_region.Top)
|
2002-06-01 06:35:57 +08:00
|
|
|
WriteFile (get_output_handle (), "\n", 1, &done, 0);
|
|
|
|
else
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
scroll_screen (0, srTop + 1, -1, srBottom, 0, srTop);
|
|
|
|
y--;
|
|
|
|
}
|
|
|
|
}
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, ((tc->ti.c_oflag & ONLCR) ? 0 : x), y + 1);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case BAK:
|
|
|
|
cursor_rel (-1, 0);
|
|
|
|
break;
|
|
|
|
case IGN:
|
|
|
|
cursor_rel (1, 0);
|
|
|
|
break;
|
|
|
|
case CR:
|
|
|
|
cursor_get (&x, &y);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, 0, y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case ERR:
|
|
|
|
WriteFile (get_output_handle (), src, 1, &done, 0);
|
|
|
|
break;
|
|
|
|
case TAB:
|
|
|
|
cursor_get (&x, &y);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (false, 8 * (x / 8 + 1), y);
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
src ++;
|
|
|
|
}
|
|
|
|
return src;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::write (const void *vsrc, size_t len)
|
|
|
|
{
|
|
|
|
/* Run and check for ansi sequences */
|
|
|
|
unsigned const char *src = (unsigned char *) vsrc;
|
|
|
|
unsigned const char *end = src + len;
|
|
|
|
|
|
|
|
debug_printf ("%x, %d", vsrc, len);
|
|
|
|
|
|
|
|
while (src < end)
|
|
|
|
{
|
|
|
|
debug_printf ("at %d(%c) state is %d", *src, isprint (*src) ? *src : ' ',
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_);
|
|
|
|
switch (dev_state->state_)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
case normal:
|
|
|
|
src = write_normal (src, end);
|
2000-10-23 11:35:50 +08:00
|
|
|
if (!src) /* write_normal failed */
|
2000-02-18 03:38:33 +08:00
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
case gotesc:
|
|
|
|
if (*src == '[')
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = gotsquare;
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->saw_question_mark = false;
|
2002-10-08 14:16:16 +08:00
|
|
|
for (dev_state->nargs_ = 0; dev_state->nargs_ < MAXARGS; dev_state->nargs_++)
|
|
|
|
dev_state->args_[dev_state->nargs_] = 0;
|
|
|
|
dev_state->nargs_ = 0;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (*src == ']')
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->rarg = 0;
|
|
|
|
dev_state->my_title_buf[0] = '\0';
|
|
|
|
dev_state->state_ = gotrsquare;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (*src == 'M') /* Reverse Index */
|
|
|
|
{
|
|
|
|
fillin_info ();
|
2002-10-08 14:16:16 +08:00
|
|
|
scroll_screen (0, 0, -1, -1, 0, dev_state->info.winTop + 1);
|
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (*src == 'c') /* Reset Linux terminal */
|
|
|
|
{
|
2001-03-03 11:56:34 +08:00
|
|
|
set_default_attr ();
|
2000-02-18 03:38:33 +08:00
|
|
|
clear_screen (0, 0, -1, -1);
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, 0, 0);
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (*src == '8') /* Restore cursor position */
|
|
|
|
{
|
2003-12-08 06:37:12 +08:00
|
|
|
cursor_set (true, dev_state->savex, dev_state->savey);
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (*src == '7') /* Save cursor position */
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
cursor_get (&dev_state->savex, &dev_state->savey);
|
|
|
|
dev_state->savey -= dev_state->info.winTop;
|
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (*src == 'R')
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
else
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
src++;
|
|
|
|
break;
|
|
|
|
case gotarg1:
|
|
|
|
if (isdigit (*src))
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->args_[dev_state->nargs_] = dev_state->args_[dev_state->nargs_] * 10 + *src - '0';
|
2000-02-18 03:38:33 +08:00
|
|
|
src++;
|
|
|
|
}
|
|
|
|
else if (*src == ';')
|
|
|
|
{
|
|
|
|
src++;
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->nargs_++;
|
|
|
|
if (dev_state->nargs_ >= MAXARGS)
|
|
|
|
dev_state->nargs_--;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = gotcommand;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case gotcommand:
|
2001-02-27 17:14:35 +08:00
|
|
|
char_command (*src++);
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
case gotrsquare:
|
2001-04-09 08:44:25 +08:00
|
|
|
if (isdigit (*src))
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->rarg = dev_state->rarg * 10 + (*src - '0');
|
|
|
|
else if (*src == ';' && (dev_state->rarg == 2 || dev_state->rarg == 0))
|
|
|
|
dev_state->state_ = gettitle;
|
2000-02-18 03:38:33 +08:00
|
|
|
else
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = eattitle;
|
2000-02-18 03:38:33 +08:00
|
|
|
src++;
|
|
|
|
break;
|
|
|
|
case eattitle:
|
|
|
|
case gettitle:
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
int n = strlen (dev_state->my_title_buf);
|
2002-11-15 02:02:05 +08:00
|
|
|
if (*src < ' ')
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
if (*src == '\007' && dev_state->state_ == gettitle)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
if (old_title)
|
2002-10-08 14:16:16 +08:00
|
|
|
strcpy (old_title, dev_state->my_title_buf);
|
|
|
|
set_console_title (dev_state->my_title_buf);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = normal;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
else if (n < TITLESIZE)
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->my_title_buf[n++] = *src;
|
|
|
|
dev_state->my_title_buf[n] = '\0';
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
src++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case gotsquare:
|
|
|
|
if (*src == ';')
|
|
|
|
{
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = gotarg1;
|
|
|
|
dev_state->nargs_++;
|
2000-02-18 03:38:33 +08:00
|
|
|
src++;
|
|
|
|
}
|
|
|
|
else if (isalpha (*src))
|
2002-11-15 12:35:13 +08:00
|
|
|
dev_state->state_ = gotcommand;
|
2000-02-18 03:38:33 +08:00
|
|
|
else if (*src != '@' && !isalpha (*src) && !isdigit (*src))
|
|
|
|
{
|
2000-12-15 12:42:20 +08:00
|
|
|
if (*src == '?')
|
2003-12-08 06:37:12 +08:00
|
|
|
dev_state->saw_question_mark = true;
|
2000-02-18 03:38:33 +08:00
|
|
|
/* ignore any extra chars between [ and first arg or command */
|
|
|
|
src++;
|
|
|
|
}
|
|
|
|
else
|
2002-10-08 14:16:16 +08:00
|
|
|
dev_state->state_ = gotarg1;
|
2000-02-18 03:38:33 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2000-07-30 00:24:59 +08:00
|
|
|
|
2000-02-18 03:38:33 +08:00
|
|
|
syscall_printf ("%d = write_console (,..%d)", len, len);
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
int vk;
|
|
|
|
const char *val[4];
|
2001-10-13 09:35:15 +08:00
|
|
|
} keytable[] NO_COPY = {
|
2000-02-18 03:38:33 +08:00
|
|
|
/* NORMAL */ /* SHIFT */ /* CTRL */ /* ALT */
|
2001-03-31 17:19:32 +08:00
|
|
|
{VK_LEFT, {"\033[D", "\033[D", "\033[D", "\033\033[D"}},
|
|
|
|
{VK_RIGHT, {"\033[C", "\033[C", "\033[C", "\033\033[C"}},
|
|
|
|
{VK_UP, {"\033[A", "\033[A", "\033[A", "\033\033[A"}},
|
|
|
|
{VK_DOWN, {"\033[B", "\033[B", "\033[B", "\033\033[B"}},
|
|
|
|
{VK_PRIOR, {"\033[5~", "\033[5~", "\033[5~", "\033\033[5~"}},
|
|
|
|
{VK_NEXT, {"\033[6~", "\033[6~", "\033[6~", "\033\033[6~"}},
|
|
|
|
{VK_HOME, {"\033[1~", "\033[1~", "\033[1~", "\033\033[1~"}},
|
|
|
|
{VK_END, {"\033[4~", "\033[4~", "\033[4~", "\033\033[4~"}},
|
|
|
|
{VK_INSERT, {"\033[2~", "\033[2~", "\033[2~", "\033\033[2~"}},
|
|
|
|
{VK_DELETE, {"\033[3~", "\033[3~", "\033[3~", "\033\033[3~"}},
|
2002-11-07 11:35:02 +08:00
|
|
|
{VK_F1, {"\033[[A", "\033[23~", NULL, NULL}},
|
|
|
|
{VK_F2, {"\033[[B", "\033[24~", NULL, NULL}},
|
|
|
|
{VK_F3, {"\033[[C", "\033[25~", NULL, NULL}},
|
|
|
|
{VK_F4, {"\033[[D", "\033[26~", NULL, NULL}},
|
|
|
|
{VK_F5, {"\033[[E", "\033[28~", NULL, NULL}},
|
2000-02-18 03:38:33 +08:00
|
|
|
{VK_F6, {"\033[17~", "\033[29~", "\036", NULL}},
|
|
|
|
{VK_F7, {"\033[18~", "\033[31~", NULL, NULL}},
|
|
|
|
{VK_F8, {"\033[19~", "\033[32~", NULL, NULL}},
|
|
|
|
{VK_F9, {"\033[20~", "\033[33~", NULL, NULL}},
|
|
|
|
{VK_F10, {"\033[21~", "\033[34~", NULL, NULL}},
|
|
|
|
{VK_F11, {"\033[23~", NULL, NULL, NULL}},
|
|
|
|
{VK_F12, {"\033[24~", NULL, NULL, NULL}},
|
|
|
|
{VK_NUMPAD5, {"\033[G", NULL, NULL, NULL}},
|
2000-04-15 11:52:24 +08:00
|
|
|
{VK_CLEAR, {"\033[G", NULL, NULL, NULL}},
|
2000-02-18 03:38:33 +08:00
|
|
|
{'6', {NULL, NULL, "\036", NULL}},
|
|
|
|
{0, {"", NULL, NULL, NULL}}
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *
|
2000-07-31 01:58:48 +08:00
|
|
|
get_nonascii_key (INPUT_RECORD& input_rec, char *tmp)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
#define NORMAL 0
|
|
|
|
#define SHIFT 1
|
|
|
|
#define CONTROL 2
|
|
|
|
#define ALT 3
|
|
|
|
int modifier_index = NORMAL;
|
|
|
|
|
|
|
|
if (input_rec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
|
|
|
|
modifier_index = SHIFT;
|
|
|
|
else if (input_rec.Event.KeyEvent.dwControlKeyState &
|
|
|
|
(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
|
|
|
|
modifier_index = CONTROL;
|
|
|
|
else if (input_rec.Event.KeyEvent.dwControlKeyState &
|
|
|
|
(LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
|
|
|
modifier_index = ALT;
|
|
|
|
|
|
|
|
for (int i = 0; keytable[i].vk; i++)
|
|
|
|
if (input_rec.Event.KeyEvent.wVirtualKeyCode == keytable[i].vk)
|
|
|
|
return keytable[i].val[modifier_index];
|
|
|
|
|
2000-07-31 01:58:48 +08:00
|
|
|
if (input_rec.Event.KeyEvent.uChar.AsciiChar)
|
2000-07-30 03:07:15 +08:00
|
|
|
{
|
2000-07-31 01:58:48 +08:00
|
|
|
tmp[0] = input_rec.Event.KeyEvent.uChar.AsciiChar;
|
|
|
|
tmp[1] = '\0';
|
|
|
|
return tmp;
|
2000-07-30 03:07:15 +08:00
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fhandler_console::init (HANDLE f, DWORD a, mode_t bin)
|
|
|
|
{
|
2002-06-05 09:42:28 +08:00
|
|
|
// this->fhandler_termios::init (f, mode, bin);
|
2000-02-18 03:38:33 +08:00
|
|
|
/* Ensure both input and output console handles are open */
|
2002-06-05 09:42:28 +08:00
|
|
|
int flags = 0;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
|
|
|
a &= GENERIC_READ | GENERIC_WRITE;
|
|
|
|
if (a == GENERIC_READ)
|
2002-06-05 09:42:28 +08:00
|
|
|
flags = O_RDONLY;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (a == GENERIC_WRITE)
|
2002-06-05 09:42:28 +08:00
|
|
|
flags = O_WRONLY;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (a == (GENERIC_READ | GENERIC_WRITE))
|
2002-06-05 09:42:28 +08:00
|
|
|
flags = O_RDWR;
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
open (flags | O_BINARY);
|
2000-02-18 03:38:33 +08:00
|
|
|
if (f != INVALID_HANDLE_VALUE)
|
|
|
|
CloseHandle (f); /* Reopened by open */
|
|
|
|
|
2003-02-04 11:01:17 +08:00
|
|
|
tcsetattr (0, &tc->ti);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fhandler_console::igncr_enabled (void)
|
|
|
|
{
|
|
|
|
return tc->ti.c_iflag & IGNCR;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-04-10 21:45:10 +08:00
|
|
|
fhandler_console::set_close_on_exec (bool val)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2003-02-04 11:01:17 +08:00
|
|
|
fhandler_base::set_close_on_exec (val);
|
2004-02-03 04:33:09 +08:00
|
|
|
set_no_inheritance (output_handle, val);
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-02-21 13:20:38 +08:00
|
|
|
fhandler_console::fixup_after_fork (HANDLE)
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
HANDLE h = get_handle ();
|
|
|
|
HANDLE oh = get_output_handle ();
|
|
|
|
|
|
|
|
/* Windows does not allow duplication of console handles between processes
|
|
|
|
so open the console explicitly. */
|
|
|
|
|
2004-01-16 03:51:49 +08:00
|
|
|
cygheap->open_fhs--; /* The downside of storing this in cygheap. */
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
if (!open (O_NOCTTY | get_flags (), 0))
|
2000-02-18 03:38:33 +08:00
|
|
|
system_printf ("error opening console after fork, %E");
|
|
|
|
|
2004-04-10 21:45:10 +08:00
|
|
|
if (!close_on_exec ())
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
CloseHandle (h);
|
|
|
|
CloseHandle (oh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void __stdcall
|
|
|
|
set_console_title (char *title)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
char buf[257];
|
2001-04-09 08:44:25 +08:00
|
|
|
strncpy (buf, title, sizeof (buf) - 1);
|
|
|
|
buf[sizeof (buf) - 1] = '\0';
|
2004-05-17 23:27:56 +08:00
|
|
|
if ((rc = WaitForSingleObject (tty_mutex, 15000)) != WAIT_OBJECT_0)
|
2000-02-18 03:38:33 +08:00
|
|
|
sigproc_printf ("wait for title mutex failed rc %d, %E", rc);
|
|
|
|
SetConsoleTitle (buf);
|
2004-05-17 23:27:56 +08:00
|
|
|
ReleaseMutex (tty_mutex);
|
2000-02-18 03:38:33 +08:00
|
|
|
debug_printf ("title '%s'", buf);
|
|
|
|
}
|
|
|
|
|
2000-09-03 12:16:35 +08:00
|
|
|
void
|
2004-02-03 05:00:07 +08:00
|
|
|
fhandler_console::fixup_after_exec ()
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
|
|
|
HANDLE h = get_handle ();
|
|
|
|
HANDLE oh = get_output_handle ();
|
|
|
|
|
2004-01-16 03:51:49 +08:00
|
|
|
cygheap->open_fhs--; /* The downside of storing this in cygheap. */
|
* devices.cc: New file.
* devices.gperf: New file.
* devices.shilka: New file.
* cygwin-gperf: New file.
* cygwin-shilka: New file.
* fhandler_fifo.cc: New file.
* fhandler_nodevice.cc : New file. Reorganize headers so that path.h precedes
fhandler.h throughout. Remove device argument and unit arguments from fhandler
constructors throughout. Remove pc arguments to fhandler functions and use
internal pc element instead, throughout. Use dev element in pc throughout.
Use major/minor elements rather than units and device numbers previously in
fhandler class. Use correct methods for fhandler file names rather than
directly accessing file name variables, throughout.
* Makefile.in (DLL_OFILES): Add devices.o, fhandler_fifo.o
* dcrt0.cc (dll_crt0_1): Call device::init.
* devices.h: Renumber devices based on more Linux-like major/minor numbers.
Add more devices. Declare standard device storage.
(device): Declare struct.
* dir.cc (opendir): Use new 'build_fh_name' to construct a fhandler_* type.
* dtable.cc (dtable::get_debugger_info): Ditto.
(cygwin_attach_handle_to_fd): Ditto.
(dtable::release): Remove special FH_SOCKET case in favor of generic
"need_fixup_before" test.
(dtable::init_std_file_from_handle): Use either build_fh_dev or build_fh_name
to build standard fhandler.
(dtable::build_fh_name): Renamed from dtable::build_fhandler_from_name. Move
out of dtable class. Don't accept a path_conv argument. Just build it here
and pass it to:
(build_fh_pc): Renamed from dtable::build_fhandler. Move out of dtable class.
Use intrinsic device type in path_conv to create new fhandler.
(build_fh_dev): Renamed from dtable::build_fhandler. Move out of dtable class.
Simplify arguments to just take new 'device' type and a name. Just return
pointer to fhandler rather than trying to insert into dtable.
(dtable::dup_worker): Accommodate above build_fh name changes.
(dtable::find_fifo): New (currently broken) function.
(handle_to_fn): Use strechr for efficiency.
* dtable.h: Reflect above build_fh name changes and argument differences.
(fhandler_base *&operator []): Return self rather than copy of self.
* fhandler.cc (fhandler_base::operator =): Use pc element to set normalized
path.
(fhandler_base::set_name): Ditto.
(fhandler_base::raw_read): Use method to access name.
(fhandler_base::write): Correctly use get_output_handle rather than get_handle.
(handler_base::device_access_denied): New function.
(fhandler_base::open): Eliminate pc argument and use pc element of
fhandler_base throughout.
(fhandler_base::fstat): Detect if device is based in filesystem and use
fstat_fs to calculate stat, if so.
(fhandler_base::fhandler_base): Eliminate handling of file names and, instead,
just free appropriate component from pc.
(fhandler_base::opendir): Remove path_conv parameter.
* fhandler.h: Remove all device flags.
(fhandler_base::pc): New element.
(fhandler_base::set_name): Change argument to path_conv.
(fhandler_base::error): New function.
(fhandler_base::exists): New function.
(fhandler_base::pc_binmode): New function.
(fhandler_base::dev): New function.
(fhandler_base::open_fs): New function.
(fhandler_base::fstat_fs): New function.
(fhandler_base::fstat_by_name): New function.
(fhandler_base::fstat_by_handle): New function.
(fhandler_base::isfifo): New function.
(fhandler_base::is_slow): New function.
(fhandler_base::is_auto_device): New function.
(fhandler_base::is_fs_special): New function.
(fhandler_base::device_access_denied): New function.
(fhandler_base::operator DWORD&): New operator.
(fhandler_base::get_name): Return normalized path from pc.
(fhandler_base::get_win32_name): Return windows path from pc.
(fhandler_base::isdevice): Renamed from is_device.
(fhandler_base::get_native_name): Return device format.
(fhandler_fifo): New class.
(fhandler_nodevice): New class.
(select_stuff::device_specific): Remove array.
(select_stuff::device_specific_pipe): New class element.
(select_stuff::device_specific_socket): New class element.
(select_stuff::device_specific_serial): New class element.
(select_stuff::select_stuff): Initialize new elements.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Move to base class
from fhandler_disk_file.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_base::fstat_by_name): Ditto.
(fhandler_disk_file::open): Move most functionality into
fhandler_base::open_fs.
(fhandler_base::open_fs): New function.
(fhandler_disk_file::close): Move most functionality into
fhandler_base::close_fs.
(fhandler_base::close_fs): New function.
* fhandler_mem.cc (fhandler_dev_mem::open): Use device name in debugging
output.
* fhandler_socket.cc (fhandler_socket::set_connect_secret): Copy standard
urandom device into appropriate place.
(fhandler_socket::accept): Reflect change in fdsock return value.
* fhandler_tty.cc: See "throughouts" above.
* net.cc: Accommodate fdsock change throughout.
(fdsock): Return success or failure, accept fd argument and device argument.
* path.cc (symlink_info::major): New element.
(symlink_info::minor): New element.
(symlink_info::parse_device): Declare new function.
(fs_info::update): Accommodate changes in path_conv class.
(path_conv::fillin): Ditto.
(path_conv::return_and_clear_normalized_path): Eliminate.
(path_conv::set_normalized_path): New function.
(path_conv::path_conv): Set info in dev element. Use path_conv methods Check
for FH_FS rather than FH_BAD to indicate when to fill in filesystem stuff.
where appropriate rather than direct access. Use set_normalized_path to set
normalized path.
(windows_device_names): Eliminate.
(get_dev): Ditto.
(get_raw_device_number): Ditto.
(get_device_number): Ditto.
(win32_device_name): Call new device name parser to do most of the heavy
lifting.
(mount_info::conv_to_win32_path): Fill in dev field as appropriate.
(symlink_worker): Handle new device files.
(symlink_info::check): Ditto.
(symlink_info::parse_device): Define new function.
* path.h (executable_states): Move here from fhandler.h.
(fs_info): Rename variables to *_storage and create methods for accessing same.
(path_conv): Add dev element, remove devn and unit and adjust inline methods to
accommodate.
(set_normalized_path): Declare new function.
* pinfo.cc (_pinfo::commune_recv): Add broken support for handling fifos.
(_pinfo::commune_send): Ditto.
* pipe.cc (fhandler_pipe::close): check for existence of handle before closing
it.
(handler_pipe::create): Rename from make_pipe. Change arguments to accept
fhandler_pipe array. Accommodate fifos.
(pipe): Rework to deal with fhandler_pipe::create changes.
(_pipe): Ditto.
* select.cc: Use individual device_specific types throughout rather than
indexing with obsolete device number.
(set_bits): Use is_socket call rather than checking device number.
* shared_info.h (CURR_MOUNT_MAGIC): Update.
(conv_to_win32_path): Reflect addition of device argument.
* syscalls.cc (mknod_worker): New function.
(open): Use build_fh_name to build fhandler.
(chown_worker): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(chmod_device): New function.
(chmod): Detect if this is an 'auto' device rather than an on-filesystem device
and handle appropriately. Use chmod_device to set mode of in-filesystem
devices.
(stat_worker): Eliminate path_conv argument. Call build_fh_name to construct
fhandler. Use fh->error() rather than pc->error to detect errors in fhandler
construction.
(access_worker): New function pulled from access. Accommodate in-filesystem
devices.
(access): Use access_worker.
(fpathconf): Detect if this is an 'auto' device rather than an on-filesystem
device and handle appropriately.
(mknod_worker): New function.
(mknod32): New function.
(chroot): Free normalized path -- assuming it was actually cmalloced.
* tty.cc (create_tty_master): Tweak for new device class.
(tty::common_init): Ditto.
* winsup.h (stat_worker): Remove.
(symlink_worker): Declare.
* exceptions.cc (set_process_mask): Just call sig_dispatch_pending and don't
worry about pending_signals since sig_dispatch_pending should always do the
right thing now.
(sig_handle): Reorganize SIGCONT handling to more closely conform to SUSv3.
* pinfo.h: Move __SIG enum to sigproc.h.
(PICOM_FIFO): New enum element.
(_pinfo): Remove 'thread2signal' stuff throughout class.
(_pinfo::commune_send): Make varargs.
(_pinfo::sigtodo): Eliminate.
(_pinfo::thread2signal): Ditto.
* signal.cc (kill_worker): Eliminate call to setthread2signal.
* sigproc.cc (local_sigtodo): Eliminate.
(getlocal_sigtodo): Ditto.
(sigelem): New class.
(pending_signals): New class.
(sigqueue): New variable, start of sigqueue linked list.
(sigcatch_nonmain): Eliminate.
(sigcatch_main): Eliminate.
(sigcatch_nosync): Eliminate.
(sigcomplete_nonmain): Eliminate.
(pending_signals): Eliminate.
(sig_clear): Call signal thread to clear pending signals, unless already in
signal thread.
(sigpending): Call signal thread to get pending signals.
(sig_dispatch_pending): Eliminate use of pending_signals and just check
sigqueue.
(sigproc_terminate): Eliminate all of the obsolete semaphore stuff. Close
signal pipe handle.
(sig_send): Eliminate all of the obsolete semaphore stuff and use pipe to send
signals.
(getevent): Eliminate.
(pending_signals::add): New function.
(pending_signals::del): New function.
(pending_signals::next): New function.
(wait_sig): Eliminate all of the obsolete semaphore stuff. Use pipe to
communicate and maintain a linked list of signals.
* sigproc.h: Move __SIG defines here. Add __SIGPENDING.
(sig_dispatch_pending): Remove "C" specifier.
(sig_handle): Accept a mask argument.
* thread.cc: Remove signal handling considerations throughout.
2003-09-25 08:37:18 +08:00
|
|
|
if (!open (O_NOCTTY | get_flags (), 0))
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2004-10-20 09:02:18 +08:00
|
|
|
bool sawerr = false;
|
2000-02-18 03:38:33 +08:00
|
|
|
if (!get_io_handle ())
|
|
|
|
{
|
|
|
|
system_printf ("error opening input console handle after exec, errno %d, %E", get_errno ());
|
2004-10-20 09:02:18 +08:00
|
|
|
sawerr = true;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
if (!get_output_handle ())
|
|
|
|
{
|
2004-10-20 09:02:18 +08:00
|
|
|
system_printf ("error opening output console handle after exec, errno %d, %E", get_errno ());
|
|
|
|
sawerr = true;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!sawerr)
|
|
|
|
system_printf ("error opening console after exec, errno %d, %E", get_errno ());
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle (h);
|
|
|
|
CloseHandle (oh);
|
2000-09-03 12:16:35 +08:00
|
|
|
return;
|
2000-02-18 03:38:33 +08:00
|
|
|
}
|