⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tminit.c

📁 UNIX下SH的实现源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * tminit.c - initializer and main part of termios emulation.
 *   designed for DJGPP by Daisuke Aoyama <jack@st.rim.or.jp>
 *   special thanks to Ryo Shimizu
 */

#include <libc/stubs.h>
#include <conio.h>
#include <fcntl.h>
#include <go32.h>
#include <io.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/farptr.h>
#include <sys/fsext.h>
#include <libc/bss.h>
#include <libc/file.h>
#include <libc/dosio.h>
#include <libc/ttyprvt.h>

#define _DEV_STDIN  0x0001
#define _DEV_STDOUT 0x0002
#define _DEV_NUL    0x0004
#define _DEV_CLOCK  0x0008
#define _DEV_RAW    0x0020
#define _DEV_CDEV   0x0080
#define _DEV_IOCTRL 0x4000

#define CPMEOF 0x1a /* Ctrl+Z */

#define _REG_STATUS_CF 0x01
#define _REG_STATUS_ZF 0x40
#define _KEY_INS  0x80
#define _KEY_CAPS 0x40
#define _KEY_NUM  0x20
#define _KEY_SCRL 0x10
#define _KEY_ALT  0x08
#define _KEY_CTRL 0x04
#define _KEY_LSFT 0x02
#define _KEY_RSFT 0x01
#define _KEYE_SYSRQ 0x80
#define _KEYE_CAPS  0x40
#define _KEYE_NUM   0x20
#define _KEYE_SCRL  0x10
#define _KEYE_RALT  0x08
#define _KEYE_RCTRL 0x04
#define _KEYE_LALT  0x02
#define _KEYE_LCTRL 0x01

#define CHECKBYTES 32

/* tty buffers */
unsigned char __libc_tty_queue_buffer[_TTY_QUEUE_SIZE];
struct tty __libc_tty_internal = TTYDEFAULT;
struct tty *__libc_tty_p = &__libc_tty_internal;
struct tty_editline __libc_tty_editline = { 0, { 0 }, { 0 }, };

/* global only in the termios functions */
int __libc_termios_hook_common_count = -1;

/* static variables */
static int __libc_use_function_and_arrow_keys = 1;
static int __libc_has_enhanced_keyboard = 0;
static unsigned int __libc_has_extended_keystroke = 0;
static unsigned char __libc_extended_keystroke[16] = { 0, };
static ssize_t __libc_termios_check_bytes = CHECKBYTES;

/* static functions */
static void __libc_termios_fflushall (void);
static void __libc_termios_init_direct_functions (void);
static ssize_t __libc_termios_read (int handle, void *buffer, size_t count, ssize_t *rv);
static ssize_t __libc_termios_read_cooked_tty (int handle, void *buffer, size_t count);
static ssize_t __libc_termios_read_raw_tty (int handle, void *buffer, size_t count);
static ssize_t __libc_termios_write (int handle, const void *buffer, size_t count, ssize_t *rv);
static ssize_t __libc_termios_write_cooked_tty (int handle, const void *buffer, size_t count);
static ssize_t __libc_termios_write_raw_tty (int handle, const void *buffer, size_t count);
#if 0
static int __libc_termios_fsext (__FSEXT_Fnumber n, int *rv, va_list ap);
#endif
static void __libc_termios_echo_ctrl (unsigned char ch);
static void __libc_termios_maybe_echo_ctrl (unsigned char ch);
static void __libc_termios_maybe_echo (unsigned char ch);
static void __libc_termios_maybe_erase1 (void);
static void __libc_termios_erase_editline (void);
static void __libc_termios_kill_editline (void);
static void __libc_termios_insert_editline (unsigned char ch);
static int __libc_termios_exist_queue (void);
static void __libc_termios_clear_queue (void);
static int __libc_termios_get_queue (void);
static int __libc_termios_put_queue (unsigned char ch);
static void __libc_termios_raise_signal (unsigned char ch, int sig);
static void __libc_termios_fill_queue (void);
void __libc_termios_check_signals (void);

/* direct I/O functions */
static void __direct_add_keystroke (int c);
static void __direct_add_keystrokes (char *s);
static void __direct_check_extended_keystroke_at (int scan);

/* AT keyboard */
static int __direct_keysense_at (void);
static unsigned char __direct_keyinput_at (void);
static int __direct_ctrlsense_at (void);

/* AT enhanced keyboard */
static int __direct_keysense_at_enh (void);
static unsigned char __direct_keyinput_at_enh (void);
static int __direct_ctrlsense_at_enh (void);

/* Output functions */
static void __direct_output_tab_at (void);
static void __direct_output_at (unsigned char ch);
static void __direct_outputns_at (int n, const unsigned char *s);
static void __direct_outputs_at (const unsigned char *s);

/* function pointers */
static int (*__direct_keysense) (void) = __direct_keysense_at;
static unsigned char (*__direct_keyinput) (void) = __direct_keyinput_at;
static int (*__direct_ctrlsense) (void) = __direct_ctrlsense_at;
static void (*__direct_output) (unsigned char ch) = __direct_output_at;
static void (*__direct_outputns) (int n, const unsigned char *s) = __direct_outputns_at;
static void (*__direct_outputs) (const unsigned char *s) = __direct_outputs_at;

/******************************************************************************/
/* initialize function ********************************************************/

static void
__libc_termios_fflushall (void)
{
#if 1 /* should now work on djgpp */
  fflush (NULL);
#else
  _fwalk ((void (*) (FILE*)) fflush);
#endif
}

static void
__libc_termios_init_direct_functions (void)
{
  __libc_has_enhanced_keyboard = 0;
  __libc_has_extended_keystroke = 0;

  if (_farpeekb (_dos_ds, 0x496) & 0x10)
    __libc_has_enhanced_keyboard = 1;

  if (__libc_has_enhanced_keyboard)
    {
      __direct_keysense = __direct_keysense_at_enh;
      __direct_keyinput = __direct_keyinput_at_enh;
      __direct_ctrlsense = __direct_ctrlsense_at_enh;
    }
  else
    {
      __direct_keysense = __direct_keysense_at;
      __direct_keyinput = __direct_keyinput_at;
      __direct_ctrlsense = __direct_ctrlsense_at;
    }
  __direct_output = __direct_output_at;
  __direct_outputns = __direct_outputns_at;
  __direct_outputs = __direct_outputs_at;
}

void
__libc_termios_init (void)
{
  if (__libc_termios_hook_common_count != __bss_count)
    {
      __libc_termios_hook_common_count = __bss_count;

      /* flush all buffered streams */
      __libc_termios_fflushall ();

      /* check enhanced keyboard, etc */
      __libc_termios_init_direct_functions ();

      /* set special hooks */
      __libc_read_termios_hook = __libc_termios_read;
      __libc_write_termios_hook = __libc_termios_write;

      /* import parameters */
      /* __libc_tty_p = ...; */

      /* fsext */
#if 0
      (void) __FSEXT_set_function (0, __libc_termios_fsext);
      (void) __FSEXT_set_function (1, __libc_termios_fsext);
      (void) __FSEXT_set_function (2, __libc_termios_fsext);
#endif
      __libc_termios_check_bytes = CHECKBYTES;
    }
}

int
__libc_termios_disable_function_and_arrow_keys (void)
{
  int old_value;

  old_value = __libc_use_function_and_arrow_keys;
  __libc_use_function_and_arrow_keys = 0;

  return old_value;
}

int
__libc_termios_enable_function_and_arrow_keys (void)
{
  int old_value;

  old_value = __libc_use_function_and_arrow_keys;
  __libc_use_function_and_arrow_keys = 1;

  return old_value;
}

/******************************************************************************/
/* direct I/O function ********************************************************/

/* function key trans function */
static void
__direct_add_keystroke (int c)
{
  if (__libc_has_extended_keystroke + 1 > sizeof (__libc_extended_keystroke))
    return;

  __libc_extended_keystroke[__libc_has_extended_keystroke++] = (unsigned char) c;
}

static void
__direct_add_keystrokes (char *s)
{
  int len;

  len = strlen (s);
  if (__libc_has_extended_keystroke + len > sizeof (__libc_extended_keystroke))
    return;

  while (--len >= 0)
    __libc_extended_keystroke[__libc_has_extended_keystroke++] = (unsigned char) s[len];
}

#define _NDUMMY (0xffU)
#define _N(c) (0x00U|(c)) /* no shift */
#define _S(c) (0x40U|(c)) /* w/shift */
#define _C(c) (0x80U|(c)) /* w/ctrl */
#define _A(c) (0xc0U|(c)) /* w/alt */

#define _TRANS_NOSHIFT "\x1b["
#define _TRANS_SHIFT "\x1b[1"
#define _TRANS_CTRL "\x1b[2"
#define _TRANS_ALT "\x1b[3"

static unsigned char trans_alphabet_chars[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";

static unsigned char trans_mapping_chars_at[] =
{
  /* 000-037: A-Z, 040-077: XA-XZ */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 00-07 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 08-0F */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 10-17 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 18-1F */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 20-27 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 28-2F */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 30-37 */
  _NDUMMY, _NDUMMY, _NDUMMY, _N(040), _N(041), _N(042), _N(043), _N(044), /* 38-3F */
  _N(045), _N(046), _N(047), _N(050), _N(051), _NDUMMY, _NDUMMY, _N(006), /* 40-47 */
  _N(000), _N(010), _NDUMMY, _N(003), _NDUMMY, _N(002), _NDUMMY, _N(007), /* 48-4F */
  _N(001), _N(011), _N(004), _N(005), _S(040), _S(041), _S(042), _S(043), /* 50-57 */
  _S(044), _S(045), _S(046), _S(047), _S(050), _S(051), _C(040), _C(041), /* 58-5F */
  _C(042), _C(043), _C(044), _C(045), _C(046), _C(047), _C(050), _C(051), /* 60-67 */
  _A(040), _A(041), _A(042), _A(043), _A(044), _A(045), _A(046), _A(047), /* 68-6F */
  _A(050), _A(051), _NDUMMY, _C(003), _C(002), _C(007), _C(011), _C(006), /* 70-77 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* 78-7F */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _C(010), _N(052), _N(053), _S(052), /* 80-87 */
  _S(053), _C(052), _C(053), _A(052), _A(053), _C(000), _NDUMMY, _NDUMMY, /* 88-8F */
  _NDUMMY, _C(001), _C(004), _C(005), _NDUMMY, _NDUMMY, _NDUMMY, _A(006), /* 90-97 */
  _A(000), _A(010), _NDUMMY, _A(003), _NDUMMY, _A(002), _NDUMMY, _A(007), /* 98-9F */
  _A(001), _A(011), _A(004), _A(005), _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* A0-A7 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* A8-AF */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* B0-B7 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* B8-BF */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* C0-C7 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* C8-CF */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* D0-D7 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* D8-DF */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* E0-E7 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* E8-EF */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* F0-F7 */
  _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, _NDUMMY, /* F8-FF */
};

static void
__direct_check_extended_keystroke_at (int scan)
{
  int c, shift;

  if (!__libc_use_function_and_arrow_keys || scan < 0 || scan > 0xff)
    return;

  c = (int) trans_mapping_chars_at[scan];
  if (c == (int) _NDUMMY)
    return;

  shift = c & 0xc0;
  c &= ~0xc0;
  __direct_add_keystroke (trans_alphabet_chars[c]);
  if (c >= 040)
    __direct_add_keystroke ('X');
  if (shift == 0x00)
    __direct_add_keystrokes (_TRANS_NOSHIFT);
  else if (shift == 0x40)
    __direct_add_keystrokes (_TRANS_SHIFT);
  else if (shift == 0x80)
    __direct_add_keystrokes (_TRANS_CTRL);
  else if (shift == 0xc0)
    __direct_add_keystrokes (_TRANS_ALT);
}

/* Input form AT keyboard */
static int
__direct_keysense_at (void)
{
  __dpmi_regs r;

  if (__libc_has_extended_keystroke)
    return 1;

  r.h.ah = 0x01;
  __dpmi_int (0x16, &r);
  if (r.x.flags & _REG_STATUS_ZF)
    return 0;

  return 1;
}

static unsigned char
__direct_keyinput_at (void)
{
  __dpmi_regs r;

  if (__libc_has_extended_keystroke)
    return __libc_extended_keystroke[--__libc_has_extended_keystroke];

  r.h.ah = 0x00;
  __dpmi_int (0x16, &r);
  if (r.h.al != 0x00)
    return r.h.al;

  __direct_check_extended_keystroke_at (r.h.ah);
  if (__libc_has_extended_keystroke)
    return __libc_extended_keystroke[--__libc_has_extended_keystroke];

  return 0;
}

static int
__direct_ctrlsense_at (void)
{
  __dpmi_regs r;

  if (__libc_has_extended_keystroke)
    return 0;

  r.h.ah = 0x02;
  __dpmi_int (0x16, &r);
  if (r.h.al & _KEY_CTRL)
    return 1;

  return 0;
}

/* Input from AT enhanced keyboard */
static int
__direct_keysense_at_enh (void)
{
  __dpmi_regs r;

  if (__libc_has_extended_keystroke)
    return 1;

  r.h.ah = 0x11;
  __dpmi_int (0x16, &r);
  if (r.x.flags & _REG_STATUS_ZF)
    return 0;

  return 1;
}

static unsigned char
__direct_keyinput_at_enh (void)
{
  __dpmi_regs r;

  if (__libc_has_extended_keystroke)
    return __libc_extended_keystroke[--__libc_has_extended_keystroke];

  r.h.ah = 0x10;
  __dpmi_int (0x16, &r);
  if (r.h.al != 0x00 && (r.h.al < 0xe0U
			 || (r.h.al != 0xe0 && r.h.al != 0xf0)))
    return r.h.al;

  __direct_check_extended_keystroke_at (r.h.ah);
  if (__libc_has_extended_keystroke)
    return __libc_extended_keystroke[--__libc_has_extended_keystroke];

  return 0;
}

static int
__direct_ctrlsense_at_enh (void)
{
  __dpmi_regs r;

  if (__libc_has_extended_keystroke)
    return 0;

  r.h.ah = 0x12;
  __dpmi_int (0x16, &r);
  if (r.h.al & _KEY_CTRL) /* either CTRL */
    return 1;

  return 0;
}

/* output to Screen */
static void
__direct_output_tab_at (void)
{
  __dpmi_regs r;
  int page, col;
  int x, y;

  page = _farpeekb (_dos_ds, 0x462);
  col = _farpeekw (_dos_ds, 0x44a);

  r.h.ah = 3;
  r.h.bh = page;
  __dpmi_int (0x10, &r);
  x = r.h.dl;
  y = r.h.dh;

  x += 8;
  x &= ~7;
  if (x > col)
    {
#if 1
      r.h.al = '\r';
      __dpmi_int (0x29, &r);
      r.h.al = '\n';
      __dpmi_int (0x29, &r);
#else
      (void) putch ('\r');
      (void) putch ('\n');
#endif
    }
  else
    {
      r.h.ah = 2;
      r.h.bh = page;
      r.h.dl = x;
      r.h.dh = y;
      __dpmi_int (0x10, &r);
    }
}

static void
__direct_output_at (unsigned char ch)
{
#if 1
  __dpmi_regs r;
#endif

  if (ch == 0x09)
    {
      __direct_output_tab_at ();
      return;
    }
  else if (ch == 0xff)
    return;

#if 1
  r.h.al = ch;
  __dpmi_int (0x29, &r);
#else
  (void) putch (ch);
#endif
}

static void
__direct_outputns_at (int n, const unsigned char *s)
{
#if 1
  __dpmi_regs r;
#endif
  unsigned char ch;

  while (--n >= 0)
    {
      ch = *s++;
      if (ch == 0x09)
	__direct_output_tab_at ();
      else if (ch != 0xff)
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -