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.)
* 0.4: Jan. 13, 2009 (parity, bits, etc.)
* 0.5: May 1, 2013 (for cron, ignore error from STDIN)
* 0.6: Dec. 15, 2015 (force disconnect/quit after # sec)
*/
#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 IGN_ERROR 64 /* シリアルポートのエラーを無視 */
#define DUMPTIME 128 /* ダンプ時にタイムスタンプ */
#define IGN_STDIN_ERR 256 /* stdinのエラーを無視 */
#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
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 cmode)
{
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 = cmode;
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()
{
if (isatty(fileno(stdin))) {
tcgetattr(fileno(stdin), &keyorg);
memcpy(&keynew, &keyorg, sizeof(struct termios));
cfmakeraw(&keynew);
keynew.c_lflag &= ~ECHO;
tcsetattr(fileno(stdin), TCSANOW, &keynew);
}
}
/* キーボード (stdin) の設定を元に戻す */
void kbdrestore()
{
if (isatty(fileno(stdin))) {
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 escapeconv(char *to, char *from)
{
int m, n;
m = n = 0;
while (from[m] == 's') {
++m;
}
while ((from[m] == ' ') || (from[m] == '\t')) {
++m;
}
while (from[m] != EOS) {
if (from[m] == '\\') { /* エスケープ文字か? */
++m;
if (from[m] == '\\') {
to[n] = '\\';
++m;
}
else if (from[m] == 'r') {
to[n] = '\r';
++m;
}
else if (from[m] == 'n') {
to[n] = '\n';
++m;
}
else if (from[m] == 't') {
to[n] = '\t';
++m;
}
else {
to[n] = from[m];
++m;
}
}
else {
to[n] = from[m];
++m;
}
++n;
}
to[n] = EOS;
#ifdef EBUG
for (m = 0; m < n; m++) {
fprintf(stderr, "%02x ", from[m]);
}
fprintf(stderr, "\n");
#endif
return(n);
}
/* エスケープ文字入力時の処理 */
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);
if ((!(*mode & IGN_STDIN_ERR)) && (n <= 0)) {
fprintf(stderr, "%s: stdin/esc EOF (%d) encountered\r\n", prog, n);
}
}
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 | DUMPTIME);
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);
}
else if (s[0] == 's') { /* 文字列送信 */
n = escapeconv(buf, s);
}
else if (s[0] == 'n') { /* 単なるコメント。何もしない */
n = 0;
}
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 quitsec, int idlesec)
{
int nfds;
fd_set readfds;
struct timeval timeout;
struct timeval current;
struct timeval tmstart;
struct timeval tmidle;
char buf[BUFSIZ];
int n, i;
int dumped;
dumped = NO;
gettimeofday(&tmstart, NULL);
gettimeofday(&tmidle, NULL);
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))) {
/* キーボード入力あり */
buf[0] = EOS;
n = read(fileno(stdin), buf, 1);
if ((!(mode & IGN_STDIN_ERR)) && (n <= 0)) {
fprintf(stderr, "%s: stdin EOF (%d) encountered\r\n", prog, n);
break;
}
else {
if (buf[0] == escape) {
if ((n = tip_escape(buf, BUFSIZ, fd, &mode, usec)) < 0) {
break;
}
}
write(fd, buf, n);
gettimeofday(&tmidle, NULL);
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 ((!(mode & IGN_ERROR)) && (n <= 0)) {
fprintf(stderr, "%s: silo EOF (%d) encountered\r\n", prog, n);
break;
}
else {
if ((n > 0) && (mode & DUMPTIME)) {
gettimeofday(¤t, NULL);
fprintf(stderr, "\r\n%8ld.%06ld: ",
current.tv_sec, current.tv_usec);
}
if (mode & HEXDUMP) {
for (i = 0; i < n; i++) {
printf("%02x ", buf[i]);
dumped = YES;
gettimeofday(&tmidle, NULL);
}
}
else {
if (mode & MAPCR) {
n = mapcr_in(n, buf);
}
write(fileno(stdout), buf, n);
gettimeofday(&tmidle, NULL);
}
}
}
if ((nfds == 0) && (dumped == YES)) {
fprintf(stderr, "\r\n");
fflush(stderr);
dumped = NO;
}
fflush(stdout);
gettimeofday(¤t, NULL);
if ((quitsec > 0) && ((current.tv_sec - tmstart.tv_sec) > quitsec)) {
/* 入出力に関わらず、一定時間が過ぎたら終了 */
break;
}
if ((idlesec > 0) && ((current.tv_sec - tmidle.tv_sec) > idlesec)) {
/* 一定時間入出力がなかったら終了 */
break;
}
}
}
/* 使い方の簡易説明 */
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-p[#]: toggle/set/reset parity mode\n");
fprintf(stderr, "\t-b[#]: toggle/set/reset chararcter bits\n");
fprintf(stderr, "\t-T[#]: toggle/set/reset print timestamp on dump\n");
fprintf(stderr, "\t-E[#]: toggle/set/reset ignore comm port error\n");
fprintf(stderr, "\t-I[#]: toggle/set/reset ignore stdin error\n");
fprintf(stderr, "\t-i #: set idle timeout to # seconds\n");
fprintf(stderr, "\t-Q #: quit after # seconds\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 -pn -b8 -I0", prog, BPS_DEFAULT);
fprintf(stderr, "-i 0 -Q 0 -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;
int cmode;
long timeout;
char escape;
int quitsec;
int idlesec;
prog = *argv;
shift;
speed = BPS_DEFAULT;
modem = MODEM_DEFAULT;
mode = 0;
escape = TIP_ESCAPE;
quitsec = idlesec = 0;
timeout = SELECT_TIMEOUT;
cmode = CREAD | CLOCAL | CS8;
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] == 'T') { /* ダンプ時タイムスタンプ */
if ((argv[0][2] != EOS) && ((argv[0][2] & 1) == 0)) {
mode &= ~DUMPTIME;
}
else if ((argv[0][2] != EOS) && ((argv[0][2] & 1) != 0)) {
mode |= DUMPTIME;
}
else {
mode ^= DUMPTIME;
}
}
else if (argv[0][1] == 'h') { /* 半二重 */
if ((argv[0][2] != EOS) && ((argv[0][2] & 1) == 0)) {
mode &= ~HALF;
}
else if ((argv[0][2] != EOS) && ((argv[0][2] & 1) != 0)) {
mode |= HALF;
}
else if (argv[0][2] == '0') {
mode ^= HALF;
}
}
else if (argv[0][1] == 'b') { /* ビット長 */
if (argv[0][2] == EOS) {
cmode &= ~CSIZE;
cmode |= CS8;
}
else if (argv[0][2] == '7') {
cmode &= ~CSIZE;
cmode |= CS7;
}
else if (argv[0][2] == '8') {
cmode &= ~CSIZE;
cmode |= CS8;
}
else {
usage();
exit(1);
}
}
else if (argv[0][1] == 'p') { /* パリティ */
if (argv[0][2] == EOS) {
cmode ^= PARENB;
}
else if (argv[0][2] == 'n') {
cmode &= ~PARENB;
cmode &= ~PARODD;
}
else if (argv[0][2] == 'e') {
cmode |= PARENB;
cmode &= ~PARODD;
}
else if (argv[0][2] == 'o') {
cmode |= PARENB;
cmode |= PARODD;
}
else {
usage();
exit(1);
}
}
else if (argv[0][1] == 'r') { /* CRLFマップ */
if ((argv[0][2] != EOS) && ((argv[0][2] & 1) == 0)) {
mode &= ~MAPCR;
}
else if ((argv[0][2] != EOS) && ((argv[0][2] & 1) != 0)) {
mode |= MAPCR;
}
else {
mode ^= MAPCR;
}
}
else if ((argv[0][1] == 't') && (argc > 1)) { /* タイムアウト */
shift;
timeout = atoi(*argv);
}
else if ((argv[0][1] == 'i') && (argc > 1)) { /* アイドルタイマー */
shift;
idlesec = atoi(*argv);
}
else if ((argv[0][1] == 'Q') && (argc > 1)) { /* 強制終了 */
shift;
quitsec = atoi(*argv);
}
else if ((argv[0][1] == 'e') && (argv[0][2] != EOS)) {
escape = argv[0][2] & 0x1f; /* エスケープ文字の指定 */
}
else if (argv[0][1] == 'E') { /* シリアルポートのエラー無視 */
if ((argv[0][2] != EOS) && ((argv[0][2] & 1) == 0)) {
mode &= ~IGN_ERROR;
}
else if ((argv[0][2] != EOS) && ((argv[0][2] & 1) != 0)) {
mode |= IGN_ERROR;
}
else {
mode ^= IGN_ERROR;
usage();
exit(1);
}
}
else if (argv[0][1] == 'I') { /* 標準入力のエラー無視 */
if ((argv[0][2] != EOS) && ((argv[0][2] & 1) == 0)) {
mode &= ~IGN_STDIN_ERR;
}
else if ((argv[0][2] != EOS) && ((argv[0][2] & 1) != 0)) {
mode |= IGN_STDIN_ERR;
}
else {
mode ^= IGN_STDIN_ERR;
}
}
else {
usage();
exit(1);
}
shift;
}
if (argc > 0) {
modem = *argv;
shift;
}
fd = opentty(modem); /* シリアルポートを開く */
ttyinit(fd, speed, cmode); /* シリアルポートを初期化 */
kbdinit(); /* キーボードを初期化 */
communicate(fd, mode, timeout, escape, quitsec, idlesec);
kbdrestore(); /* キーボードを元に戻す */
closetty(fd); /* シリアルポートを閉じる */
exit(0);
}
/* Local Variables: */
/* compile-command:"cc -Wall -o utip utip.c" */
/* End: */