Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
/*
* ek -- serial external keyboard :-) for FreeBSD/Linux
*
* revision history
* 0.0: Feb. 5, 2003 by Dai ISHIJIMA
* 0.1: Feb. 6, 2003 (code conversion)
* 0.2: Feb. 11, 2003 (IrKB101 support)
* 0.3: Feb. 17, 2003 (HHC support)
*
* usage: ek [serial device]
*
* example: ek /dev/ttyS1
*
* see also: source of ``script'' command
*/
#ifdef SLZAURUS
#ifndef LINUX
#define LINUX
#endif
#endif
#ifdef LINUX
#define NEED_PTY_H
#define NEED_UTMP_H
#define NEED_WAIT_H
#else
#define NEED_LIBUTIL_H
#endif
#include
#include
#include
#include
#include /* bzero() <- FDZERO() */
#include
#include
#include
#ifdef NEED_LIBUTIL_H
#include /* openpty() */ /* -lutil */
#endif
#ifdef NEED_PTY_H
#include /* openpty() */ /* -lutil */
#endif
#ifdef NEED_UTMP_H
#include /* login_tty() */ /* -lutil */
#endif
#ifdef NEED_WAIT_H
#include /* wait3(), WNOHANG */
#endif
#include
#include
#include
#include "tty.h"
#include "codeconv.h"
#include "irkb101.h"
#include "ps2key.h"
#ifdef LINUX
#define DEFAULT_SHELL "/bin/sh"
#ifdef SLZAURUS
#define DEFAULT_DEVICE "/dev/ttyS1" /* raw IrDA */
#else
#define DEFAULT_DEVICE "/dev/ttyS0" /* COM1: */
#endif
#else
#define DEFAULT_SHELL "/bin/csh"
#define DEFAULT_DEVICE "/dev/cuaa1" /* IrDA, COM2: */
#endif
#define DEFAULT_SPEED 9600
#define RAW_KEYBOARD 'r'
#define SJIS_RAW_KEYBOARD 's'
#define IRKB101_PS2KEYBOARD 'i'
#define HHC 'h'
#define HHC_BPS 4800
#define EK_ENVIRON "EXTERNAL_KEYBOARD"
#define EK_VALUE "SERIAL"
#define SHELL_ENV "SHELL"
#define ENV_OVERWRITE 1
/* 子プロセスの状態その他 */
#define RUNNING 0x01
#define ORG_KBD_EOF 0xc0
#define EXT_KBD_EOF 0xa0
#define CHILD_EOF 0x90
#define CHILD_EXIT 0x08
#define CHILD_CHANGED 0x04
#define YES 1
#define NO 0
char *prog;
#define shift --argc; ++argv
static int childstatus = RUNNING;
static pid_t child;
/*
* 仮想端末関連
*/
/* 子プロセスとしてシェルを起動する */
void subshell(int master, int slave)
{
char *shell;
/* 起動するシェルを決める */
shell = getenv(SHELL_ENV);
if (shell == NULL) {
shell = DEFAULT_SHELL;
}
close(master);
login_tty(slave);
execl(shell, "sh", "-i", NULL); /* シェルを「対話モード」で起動 */
/* ここから下は実行されないはず… */
fprintf(stderr, "%s: can't start subshell (%s)\r\n", prog, shell);
kill(0, SIGTERM);
exit(1);
}
#ifdef LINUX
/* SIGCHILD で飛んでくる。exitした場合、電源OFF→ON */
void chk_child(int dummy)
{
int status;
pid_t pid;
while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
if (pid == child) {
/* 多分、exit した */
childstatus = CHILD_EXIT;
}
}
/* 多分、電源OFF→ON */
childstatus |= CHILD_CHANGED;
}
#endif
/* ウィンドウサイズ変更, 縦横切り替え...(?) */
void winch(int dummy)
{
kill(child, SIGWINCH);
}
/* バイトの分解と合成 */
#define lobyte(x) (((unsigned short)(x)) & 0xff)
#define hibyte(x) ((((unsigned short)(x)) >> 8) & 0xff)
#define hilo(h,l) ((((unsigned char)(h)) << 8) | ((unsigned char)(l)))
int sjisconv(int n, char *buf)
{
static unsigned char mybuf[BUFSIZ];
static int p = 0;
int i, j;
int code;
j = p;
for (i = 0; (j < BUFSIZ) && (i < n); i++, j++) {
mybuf[j] = buf[i];
}
n = 0;
for (i = 0; (i < j) && (n < BUFSIZ); i++, n++) {
if (mybuf[i] < 0x80) {
buf[n] = mybuf[i];
}
else if (iskana(mybuf[i])) {
code = jtoe(kanakana(mybuf[i]));
buf[n] = hibyte(code);
buf[n + 1] = lobyte(code);
++n;
}
else if ((i + 1 < j) && (n - 1 < BUFSIZ)) {
code = jtoe(stoj(hilo(mybuf[i], mybuf[i + 1])));
++i;
buf[n] = hibyte(code);
buf[n + 1] = lobyte(code);
++n;
}
else {
break;
}
}
for (p = 0; i < j; p++, i++) {
mybuf[p] = mybuf[i];
}
return(n);
}
/* 外部キーボードを使う */
int keyboard(int extkey, int master, int mode)
{
int nfds;
fd_set readfds;
struct timeval timeout;
int n; /* 読み込んだ文字の数 */
char buf[BUFSIZ];
childstatus = RUNNING;
while (ttygetc(extkey) != EOF) {
; /* 起動時のごみキャラクタを読み飛ばす */
}
while (childstatus & RUNNING) {
FD_ZERO(&readfds);
FD_SET(master, &readfds); /* 子プロセスの出力を調べる */
FD_SET(fileno(stdin), &readfds); /* 標準入力 (本体キー) を調べる */
FD_SET(extkey, &readfds); /* 外部キーボードを調べる */
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
nfds = select(master + 1, &readfds, NULL, NULL, &timeout);
if ((nfds < 0) && (errno != EINTR)) {
fprintf(stderr, ">>>if ((nfds < 0) && (errno != EINTR)) {\n");
break;
}
if ((nfds > 0) && (FD_ISSET(fileno(stdin), &readfds))) {
/* 標準入力 (本体キーボード) からのデータを */
/* 子プロセスに書き込む */
n = read(fileno(stdin), buf, BUFSIZ);
if (n <= 0) {
childstatus = ORG_KBD_EOF;
}
if (n > 0) {
(void)write(master, buf, n);
}
}
if ((nfds > 0) && (FD_ISSET(extkey, &readfds))) {
/* 外部キーボードからのデータを子プロセスに書き込む */
if (childstatus & CHILD_CHANGED) {
while (ttygetc(extkey) != EOF) {
; /* 再起動時のごみキャラクタを読み飛ばす */
}
childstatus &= ~CHILD_CHANGED;
}
else {
n = read(extkey, buf, BUFSIZ);
if (n <= 0) {
childstatus = EXT_KBD_EOF;
}
if (n > 0) {
if (mode == SJIS_RAW_KEYBOARD) {
n = sjisconv(n, buf);
}
else if (mode == IRKB101_PS2KEYBOARD) {
n = irkb101conv(n, buf);
n = ps2conv(n, buf);
}
else if (mode == HHC) {
n = ps2conv(n, buf);
}
(void)write(master, buf, n);
}
}
}
if (nfds > 0 && FD_ISSET(master, &readfds)) {
/* 子プロセスからのデータを標準出力へ書き出す */
n = read(master, buf, BUFSIZ);
if (n <= 0) {
childstatus = CHILD_EOF;
break;
}
write(fileno(stdout), buf, n);
}
} /* while */
if (childstatus == CHILD_EOF) {
fprintf(stderr, "%s: EOF encountered, child process finished\r\n",
prog);
}
else if (childstatus & CHILD_EXIT) {
fprintf(stderr, "%s: caught SIGCHLD, child process finished\r\n",
prog);
}
else if (childstatus == ORG_KBD_EOF) {
fprintf(stderr, "%s: EOF encountered on keyboard\r\n",
prog);
}
else if (childstatus == EXT_KBD_EOF) {
fprintf(stderr, "%s: EOF encountered on external keyboard\r\n",
prog);
}
else {
fprintf(stderr, "%s: child process finished (may be)\r\n", prog);
}
return(childstatus);
}
/* 仮想端末を開く */
void pseudoterm(int extkey, int mode)
{
struct termios tsave; /* 端末の設定 保存版 */
struct termios t; /* 端末の設定 */
struct winsize w; /* 端末の画面サイズ */
int master, slave;
int status;
tcgetattr(fileno(stdin), &t);
tcgetattr(fileno(stdin), &tsave);
ioctl(fileno(stdin), TIOCGWINSZ, &w);
if (openpty(&master, &slave, NULL, &t, &w) != 0) {
fprintf(stderr, "%s: can't open pty\n", prog);
exit(1);
}
cfmakeraw(&t);
t.c_lflag &= ~ECHO;
(void)tcsetattr(fileno(stdin), TCSAFLUSH, &t);
child = fork();
if (child < 0) { /* fork失敗 */
fprintf(stderr, "%s: can't fork\n", prog);
exit(1);
}
else if (child == 0) { /* 子プロセス */
subshell(master, slave);
}
else { /* 元々のプロセス */
#ifdef LINUX
signal(SIGCHLD, chk_child); /* 子プロセスが死んだかチェック */
#endif
signal(SIGWINCH, winch); /* ウィンドウサイズ変更 */
/* 外部キーボードを使う */
fprintf(stderr, "%s: external keyboard now enabled\r\n", prog);
status = keyboard(extkey, master, mode);
fprintf(stderr, "%s: external keyboard now disabled\r\n", prog);
}
(void)tcsetattr(fileno(stdin), TCSAFLUSH, &tsave);
}
void usage()
{
fprintf(stderr, "Usage: %s [option]... [device]\n", prog);
fputs(" options:\n", stderr);
fputs("\t-raw: RAW keyboard (no conversion) mode\n", stderr);
fputs("\t-sjis: SJIS conversion mode\n", stderr);
fputs("\t-irkb101: IrKB101+PS/2 mode\n", stderr);
fputs("\t-IrKB101: IrKB101+PS/2 mode without initialize\n", stderr);
fputs("\t-cradle: Happy Hacking Cradle+PS/2 mode\n", stderr);
fputs("\t-#: set serial speed [bps]\n", stderr);
fputs(" default:\n", stderr);
fprintf(stderr, "\t%s -%d -sjis %s\n",
prog, DEFAULT_SPEED, DEFAULT_DEVICE);
}
int main(int argc, char *argv[])
{
int mode;
char *keydev;
char *keyenv;
int fd;
int speed;
int n;
int init101;
prog = *argv;
shift;
speed = DEFAULT_SPEED;
mode = SJIS_RAW_KEYBOARD;
init101 = YES;
while ((argc > 0) && (argv[0][0] == '-')) {
if (argv[0][1] == 'r') {
mode = RAW_KEYBOARD;
}
else if (argv[0][1] == 's') {
mode = SJIS_RAW_KEYBOARD;
}
else if (argv[0][1] == 'i') {
mode = IRKB101_PS2KEYBOARD;
}
else if (argv[0][1] == 'I') {
mode = IRKB101_PS2KEYBOARD;
init101 = NO;
}
else if (argv[0][1] == 'c') {
mode = HHC;
speed = HHC_BPS;
}
else if (('0' <= argv[0][1]) && (argv[0][1] <= '9')) {
speed = -atoi(*argv);
}
else {
usage();
exit(1);
}
shift;
}
if (argc > 0) {
keydev = *argv;
}
else {
keydev = DEFAULT_DEVICE;
}
/* すでに外部キーボードが有効になっているか? */
keyenv = getenv(EK_ENVIRON);
if (keyenv != NULL) {
fprintf(stderr, "%s: may already running %s, ", prog, prog);
fprintf(stderr, "environ $%s set, value = %s\r\n", EK_ENVIRON, keyenv);
/* IrKB101の場合は初期化しない */
init101 = NO;
}
setenv(EK_ENVIRON, EK_VALUE, ENV_OVERWRITE);
/* */
fd = opentty(keydev);
ttyinit(fd, speed);
if ((mode == IRKB101_PS2KEYBOARD) && (init101 == YES)) {
if ((n = init_irkb101(fd)) != 0) {
fprintf(stderr,
"%s: can't initialize IrKB101+PS/2 keyboard (%d)\n",
prog, n);
closetty(fd);
exit(1);
}
fprintf(stderr, "%s: IrKB101+PS/2 initialized\n", prog);
}
pseudoterm(fd, mode);
closetty(fd);
exit(0);
}
/* Local Variables: */
/* compile-command:"gcc -g -Wall -o ek2 ek2.c tty.c codeconv.c irkb101.c ps2key.c -lutil" */
/* End: */