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
/*
 *  utip -- a simple, tiny ``tip'' program (``u'' means ``micro'')
 *
 *  revision history
 *	0.1: Feb. 10, 2003 by Dai ISHIJIMA (use select(2) system call)
 *	0.2: May  14, 2003 (as tinytip2)
 *	0.3: Oct  31, 2003 (as utip, half-duplex, etc.)
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define YES 1
#define NO 0
#define NEWLINE '\n'
#define CR '\r'
#define EOS '\0'
#define TIP_ESCAPE 0x1d		/* Ctrl - ] */
#define HEXDUMP	1	/* ダンプモード */
#define HALF	2	/* 半二重 (ローカルエコー) */
#define MAPCR	4	/* CR -> CR/LF */
#define BPS_DEFAULT 9600
#define MODEM_DEFAULT "/dev/cuaa0"
#ifdef SLZAURUS
#undef  MODEM_DEFAULT
#define MODEM_DEFAULT "/dev/modem"
#undef  TIP_ESCAPE
#define TIP_ESCAPE 0x1b		/* Ctrl - [, ESCAPE */
#endif
#define SELECT_TIMEOUT 100000	/* 100,000 [us] -> 1/10 [sec] */
#ifndef O_NONBLOCK	/* for Sony NEWS, NEWS-OS 4.x */
#include 
#endif
#define FILEMODE 0777
#ifdef _POSIX_VDISABLE
#define CC_UNDEF _POSIX_VDISABLE
#else
#define CC_UNDEF 0
#endif
unsigned char *prog;
#define shift --argc; ++argv
static struct termios keyorg, keynew;	/* キーボード (stdin) の状態を保持 */
static struct termios portorg, portnew; 
/* 読み書き用にオープンする */
int opentty(char *name)
{
    int fd;
    if ((fd = open(name, O_RDWR | O_NONBLOCK, FILEMODE)) <= 0) {
	fprintf(stderr, "can't open %s\n", name);
	exit(1);
    }
    return(fd);
}
/* シリアル速度のチェック */
int speed(int sp)
{
    if (sp == 1200) {
	return(B1200);
    }
    else if (sp == 2400) {
	return(B2400);
    }
    else if (sp == 4800) {
	return(B4800);
    }
    else if (sp == 9600) {
	return(B9600);
    }
    else if (sp == 19200) {
	return(B19200);
    }
    else if (sp == 38400) {
	return(B38400);
    }
#ifdef B57600    
    else if (sp == 57600) {
	return(B57600);
    }
#endif
#ifdef B115200
    else if (sp == 115200) {
	return(B115200);
    }
#endif
    else {
	fprintf(stderr, "%d bps unavailable.  9600 bps selected.\n", sp);
    }
    return(B9600);
}
/* シリアルポートの初期化。速度の設定・RAWモードに */
void ttyinit(int fd, long sp)
{
    int i;
    sp = speed(sp);
    tcgetattr(fd, &portorg);
    memcpy(&portorg, &portnew, sizeof(struct termios));
    portnew.c_iflag = IGNBRK | IGNPAR;
    portnew.c_oflag = 0;
    portnew.c_cflag = CS8 | CREAD | CLOCAL;
    portnew.c_lflag = 0;
    cfsetispeed(&portnew, sp);
    cfsetospeed(&portnew, sp);
    for (i = 0; i < NCCS; i++) {
	portnew.c_cc[i] = CC_UNDEF;
    }
#ifndef VMIN_NULL
    portnew.c_cc[VMIN] = portorg.c_cc[VMIN];
    portnew.c_cc[VTIME] = portorg.c_cc[VTIME];
#endif
    tcsetattr(fd, TCSANOW, &portnew);
}    
/* シリアルポートの設定を元に戻す */
void ttyrestore(int fd)
{
    tcsetattr(fd, TCSANOW, &portorg);
}
/* シリアルポートを閉じる */
int closetty(int fd)
{
    ttyrestore(fd);
    return(close(fd));
}
/* シリアルポートの制御線状態を表示する */
void showmodemstat(int fd)
{
    int status;
    
    ioctl(fd, TIOCMGET, &status);
    fprintf(stderr, (status & TIOCM_LE) ? "ENABLE|" : "enable|");
    fprintf(stderr, (status & TIOCM_DTR) ? "DTR|" : "dtr|");
    fprintf(stderr, (status & TIOCM_RTS) ? "RTS|" : "rts|");
    fprintf(stderr, (status & TIOCM_CTS) ? "CTS|" : "cts|");
    fprintf(stderr, (status & TIOCM_CAR) ? "DCD|" : "dcd|");
    fprintf(stderr, (status & TIOCM_RI) ? "RI|" : "ri|");
    fprintf(stderr, (status & TIOCM_DSR) ? "DSR" : "dsr");
    fprintf(stderr, "\n");
}
/* キーボード (stdin) を「生」モード、エコーなしに */
void kbdinit()
{
    tcgetattr(fileno(stdin), &keyorg);
    memcpy(&keynew, &keyorg, sizeof(struct termios));
    cfmakeraw(&keynew);
    keynew.c_lflag &= ~ECHO;
    tcsetattr(fileno(stdin), TCSANOW, &keynew);
}
/* キーボード (stdin) の設定を元に戻す */
void kbdrestore()
{
    tcsetattr(fileno(stdin), TCSANOW, &keyorg);
}
/* 16進文字か? */
int hexdigit(char ch)
{
    /* ch に応じて 0〜15までの値を返す */
    if (('0' <= ch) && (ch <= '9')) {
	return(ch - '0');
    }
    else if (('A' <= ch) && (ch <= 'F')) {
	return(ch - 'A' + 10);
    }
    else if (('a' <= ch) && (ch <= 'f')) {
	return(ch - 'a' + 10);
    }
    return(-1);		/* 16進文字じゃないときは -1 を返す */
}
/* 16進文字列をバイナリ化する。「41 54 5a 0d 0a」→「ATZ\r\n」 */
int hexconv(char *to, char *from)
{
    int m, n;
    int x;
    m = n = 0;
    while (from[m] != EOS) {
	while ((from[m] != EOS) && ((x = hexdigit(from[m])) < 0)) {
	    ++m;
	}
	if ((from[m] != EOS) && ((x = hexdigit(from[m])) >= 0)) {
	    to[n] = x;
	    ++m;
	}
	if ((from[m] != EOS) && ((x = hexdigit(from[m])) >= 0)) {
	    to[n] = to[n] << 4 | x;
	    ++m;
	}
	if (from[m] == EOS) {
	    break;
	}
	++n;
    }
    for (m = 0; m < n; m++) {
	from[m] = to[m];
    }
    from[m] = EOS;
#ifdef EBUG
    for (m = 0; m < n; m++) {
	fprintf(stderr, "%02x ", from[m]);
    }
    fprintf(stderr, "\n");
#endif
    return(m);
}
/* エスケープ文字入力時の処理 */
int tip_escape(char *buf, int maxbuf, int fd, int *mode, long usec)
{
    char s[BUFSIZ];
    int n;
    int nfds;
    fd_set readfds;
    struct timeval timeout;
    /* 連続して入力があるかどうか調べる */
    FD_ZERO(&readfds);
    FD_SET(fileno(stdin), &readfds);
    timeout.tv_sec = 0;
    timeout.tv_usec = usec;
    nfds = select(fileno(stdin) + 1, &readfds, NULL, NULL, &timeout);
    if ((nfds > 0) && (FD_ISSET(fileno(stdin), &readfds))) {
	/* 連続入力あり */
	n = read(fileno(stdin), buf, 1);
    }
    else {
	/* プロンプトを出力してコマンド入力待ち */
	kbdrestore();
	fprintf(stderr, "%s> ", prog);
	n = 0;
	if (fgets(s, BUFSIZ, stdin) ==NULL) {
	    fprintf(stderr, "\n%s: EOF encountered\n", prog);
	    n = EOF;
	}
	else if (s[0] == 'q') {		/* q は quit */
	    n = EOF;
	}
	else if (s[0] == '?') {		/* ? はヘルプ */
	    fputs("q: quit\n", stderr);
	    fputs("v: show modem status\n", stderr);
	    fputs("d: toggle hexdump mode\n", stderr);
	    fputs("h: toggle half-duplex mode\n", stderr);
	    fputs("r: toggle map CR->CR/LF mode\n", stderr);
	    fputs("x [string]: send hex data, ", stderr);
	    fputs("'x 41 54 5a 0d 0a' is equivalent to 'ATZ\\r\\n'\n", stderr);
	    n = 0;
	}
	else if (s[0] == 'v') {		/* モデムの状態 */
	    showmodemstat(fd);
	    n = 0;
	}
	else if (s[0] == 'd') {		/* ダンプモードトグル */
	    *mode ^= HEXDUMP;
	    n = 0;
	}
	else if (s[0] == 'h') {		/* 半二重モードトグル */
	    *mode ^= HALF;
	    n = 0;
	}
	else if (s[0] == 'r') {		/* MAP CR->CR/LFモードトグル */
	    *mode ^= MAPCR;
	    n = 0;
	}
	else if (s[0] == 'x') {		/* 16進文字列 */
	    n = hexconv(buf, s);
	}
	kbdinit();
    }
    return(n);
}    
/* CR->CR/LFマップ処理 */
int mapcr(int n, char *buf)
{
    static char lastch = EOS;
    int m;
    int i;
    char convbuf[BUFSIZ];
    if ((lastch == CR) && (n == 0)) {
	lastch = EOS;
	buf[0] = NEWLINE;
	return(1);
    }
    m = 0;
    for (i = 0; (i < n) && (m < BUFSIZ); i++) {
	if ((lastch == CR) && (buf[i] != NEWLINE) && (m < BUFSIZ)) {
	    convbuf[m] = NEWLINE;
	    ++m;
	}
	convbuf[m] = buf[i];
	lastch = buf[i];
	++m;
    }
    for (i = 0; i < m; i++) {
	buf[i] = convbuf[i];
    }
    return(m);
}
/* CR->CR/LFマップ処理 */
int mapcr_in(int n, char *buf)
{
    int m;
    int i;
    char convbuf[BUFSIZ];
    m = 0;
    for (i = 0; (i < n) && (m < BUFSIZ); i++) {
	convbuf[m] = buf[i];
	++m;
	if ((m < BUFSIZ) && (buf[i] == CR)) {
	    if ((n <= i + 1) || (buf[i + 1] != NEWLINE)) {
		convbuf[m] = NEWLINE;
		++m;
	    }
	}
    }
    for (i = 0; i < m; i++) {
	buf[i] = convbuf[i];
    }
    return(m);
}
/* シリアル入出力のメイン部分 */
void communicate(int fd, int mode, long usec, char escape)
{
    int nfds;
    fd_set readfds;
    struct timeval timeout;
    char buf[BUFSIZ];
    int n, i;
    int dumped;
    
    dumped = NO;
    for (;;) {
	FD_ZERO(&readfds);
	FD_SET(fileno(stdin), &readfds);
	FD_SET(fd, &readfds);
	timeout.tv_sec = 0;
	timeout.tv_usec = usec;
	nfds = select(fd + 1, &readfds, NULL, NULL, &timeout);
	if ((nfds < 0) && (errno != EINTR)) {
	    fprintf(stderr, "%s: select failed\n", prog);
	    break;
	}
	if ((nfds > 0) && (FD_ISSET(fileno(stdin), &readfds))) {
	    /* キーボード入力あり */
	    n = read(fileno(stdin), buf, 1);
	    if (n <= 0) {
		break;
	    }
	    else {
		if (buf[0] == escape) {
		    if ((n = tip_escape(buf, BUFSIZ, fd, &mode, usec)) < 0) {
			break;
		    }
		}
		write(fd, buf, n);
		if (mode & HALF) {
		    if (mode & MAPCR) {
			n = mapcr_in(n, buf);
		    }
		    write(fileno(stdin), buf, n);
		}
	    }
	}
	if ((nfds > 0) && (FD_ISSET(fd, &readfds))) {
	    /* シリアルポート入力あり */
	    n = read(fd, buf, BUFSIZ);
	    if (n <= 0) {
		break;
	    }
	    else {
		if (mode & HEXDUMP) {
		    for (i = 0; i < n; i++) {
			printf("%02x ", buf[i]);
			dumped = YES;
		    }
		}
		else {
		    if (mode & MAPCR) {
			n = mapcr_in(n, buf);
		    }
		    write(fileno(stdin), buf, n);
		}
	    }
	}
	if ((nfds == 0) && (dumped == YES)) {
	    fprintf(stderr, "\r\n");
	    fflush(stderr);
	    dumped = NO;
	}
	fflush(stdout);
    }
}
/* 使い方の簡易説明 */
void usage()
{
    fprintf(stderr, "Usage: %s [option...] modem\n", prog);
    fprintf(stderr, "    options:\n");
    fprintf(stderr, "\t-#: set serial speed [bps]\n");
    fprintf(stderr, "\t-d[#]: toggle/set/reset hexdump display mode\n");
    fprintf(stderr, "\t-h[#]: toggle/set/reset half-duplex mode\n");
    fprintf(stderr, "\t-r[#]: toggle/set/reset map CR->CR/LF mode\n");
    fprintf(stderr, "\t-t #: set display/keyboard flush timeout [us]\n");
    fprintf(stderr, "\t-eX: set escape charactor to ctrl-X\n");
    fprintf(stderr, "    default:\n");
    fprintf(stderr, "\t%s -%d -d0 -h0 -r0 ", prog, BPS_DEFAULT);
    fprintf(stderr, "-t %d ", SELECT_TIMEOUT);
    fprintf(stderr, "-e'%c' %s\n", TIP_ESCAPE + '@', MODEM_DEFAULT);
}
/* メイン */
int main(int argc, char *argv[])
{
    long speed;
    char *modem;
    int fd;
    int mode;
    long timeout;
    char escape;
    
    prog = *argv;
    shift;
    speed = BPS_DEFAULT;
    modem = MODEM_DEFAULT;
    mode = 0;
    escape = TIP_ESCAPE;
    timeout = SELECT_TIMEOUT;
    while ((argc > 0) && (argv[0][0] == '-')) {
	if (('0' <= argv[0][1]) && (argv[0][1] <= '9')) {
	    speed = -atoi(*argv);	/* 数字 -> bps指定 */
	}
	else if (argv[0][1] == 'd') {	/* ダンプモード */
	    if ((argv[0][2] != EOS) && ((argv[0][2] & 1) == 0)) {
		mode &= ~HEXDUMP;
	    }
	    else if ((argv[0][2] != EOS) && ((argv[0][2] & 1) != 0)) {
		mode |= HEXDUMP;
	    }
	    else {
		mode ^= HEXDUMP;
	    }
	}
	else if (argv[0][1] == 'h') {
	    if (argv[0][2] == EOS) {
		mode ^= HALF;
	    }
	    else if (argv[0][2] == '1') {
		mode |= HALF;
	    }
	    else if (argv[0][2] == '0') {
		mode &= ~HALF;
	    }
	    else {
		usage();
		exit(1);
	    }
	}
	else if (argv[0][1] == 'r') {
	    if (argv[0][2] == EOS) {
		mode ^= MAPCR;
	    }
	    else if (argv[0][2] == '1') {
		mode |= MAPCR;
	    }
	    else if (argv[0][2] == '0') {
		mode &= ~MAPCR;
	    }
	    else {
		usage();
		exit(1);
	    }
	}
	else if ((argv[0][1] == 't') && (argc > 1)) {	/* タイムアウト */
	    shift;
	    timeout = atoi(*argv);
	}
	else if ((argv[0][1] == 'e') && (argv[0][2] != EOS)) {
	    escape = argv[0][2] & 0x1f;		/* エスケープ文字の指定 */
	}
	else {
	    usage();
	    exit(1);
	}
	shift;
    }
    if (argc > 0) {
	modem = *argv;
	shift;
    }
    fd = opentty(modem);	/* シリアルポートを開く */
    ttyinit(fd, speed);		/* シリアルポートを初期化 */
    kbdinit();			/* キーボードを初期化 */
    communicate(fd, mode, timeout, escape);
    kbdrestore();		/* キーボードを元に戻す */
    closetty(fd);		/* シリアルポートを閉じる */
    exit(0);
}
/* Local Variables: */
/* compile-command:"cc -Wall -o utip utip.c" */
/* End: */