/*
 * Xportを利用した...
 */ 

#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define	SVR_HOSTNAME		"localhost"
#define	SVR_PORT		14000	/* port for XPort */

#define	OPT_HOSTNAME		0x01
#define	OPT_PORT		0x02
/*#define	OPT_XPORT		0x04*/
#define	OPT_VERBOSE		0x08
#define	OPT_CONFIG		0x10	/* configuration confirm */
#define	OPT_WRITE		0x20	/* write active/unactive */
#define	OPT_READ		0x40	/* read port status */
#define	OPT_READSIMPLE		0x80	/* read port status (extra) */

#define	CP1			0x00010000;	/* XPort CP1 */
#define	CP2			0x00020000;	/* XPort CP2 */
#define	CP3			0x00040000;	/* XPort CP3 */

#define	XPORT_CONFIG		0x01	/* check configuration status */
#define	XPORT_WRITE		0x02	/* write port */
#define	XPORT_READ		0x03	/* read port */
#define	XPORT_SAVEAPPLET	0x04	/* Java Applet save */
#define	XPORT_LOADAPPLET	0x05	/* Java Applet load */

FILE *fp;

char tmp[1024];

void verbose(pre, buf, len)
char *pre, *buf;
int len;
{
	int n = 0;

	printf("%s: ", pre);
	while(n < len){
		printf("%02X ", 0x0ff & *(buf+n));
		n++;
	}
	putchar('\n');
}

/*
 * xport_readconfig -- 設定状態の確認
 *
 * args:
 *  sock	ソケット
 *  buf		保存先
 * ret:
 *  == -1	エラー
 *  != -1	正常終了(読み込んだバイト数)
 */
int xport_readconfig(sock, buf)
int sock;
char *buf;
{
	int l;
	char ch = XPORT_CONFIG;

	/* 設定状態確認コマンドを発行 */
	if(write(sock, &ch, 1) < 1)
		return -1;

	/* 設定状態の読み込み */
	if((l = read(sock, buf, 5)) < 5)
		return -1;

	return l;
}

/*
 * xport_read -- 汎用ポートの状態読み込み
 *
 * args:
 *  sock	ソケット
 *  buf		保存先
 * ret:
 *  == -1	エラー
 *  != -1	正常終了(読み込んだバイト数)
 */
int xport_read(sock, buf)
int sock;
char *buf;
{
	int l;
	char ch = XPORT_READ;

	/* 汎用ポート状態確認コマンドを発行 */
	if(write(sock, &ch, 1) < 1)
		return -1;

	/* 汎用ポート状態の読み込み */
	if((l = read(sock, buf,2)) < 2)
		return -1;

	return l;
}

/*
 * xport_write -- ポートの状態書き込み
 */
int xport_write(sock)
int sock;
{
  char buff[1024];
  int i;
  char tmp[1];
  char cmd[] = {0x1b, 0x40,   // イニシャライズ
				0x1f, 0x28, 0x67, 0x1, 0x2, // フォントサイズ
				0x1f, 0x28, 0x67, 0x2, 0x1, // ２バイトコード
				0x1b, 0x74, 0x1, //カタカナ
				0x1f, 0x1,       //オーバライド
				0x1f, 0x24, 0x0, 0x0, 0x0, 0x0, //カーソルセット
				0xc,  //画面クリア
				0x1f, 0x28, 0x67, 0x40, 0x1, 0x1, //キャラクタ拡大
				};


  char cmd2[] = {0x1b, 0x40,   // イニシャライズ
				0x1f, 0x58, 0x02, // 輝度 50%
				0x1f, 0x28, 0x67, 0x1, 0x2, // フォントサイズ
				0x1f, 0x28, 0x67, 0x2, 0x1, // ２バイトコード
				0x1b, 0x74, 0x1, //カタカナ
				0x1f, 0x1,       //オーバライド
				0xc,  //画面クリア
				0x1f, 0x28, 0x67, 0x40, 0x1, 0x1, //キャラクタ拡大
				0x1f, 0x28, 0x61, 0x10, 0x4, 0x0, 0x0, 0x0, 0x1, //スクロール表示指定
				0x1f, 0x03, // 横スクロールモード
				0x1f, 0x73, 0x02, // スクロール速度
				0x1f, 0x6d, 0x01, // スクロール品質(高)
				0x1f, 0x24, 0xfe, 0x0, 0x0, 0x0, // カーソルをセット
				};
  write(sock, cmd2, sizeof(cmd2));
  gets(buff);
  write(sock, buff, strlen(buff));

  return(0);
}


usage()
{
	printf("usage: xport [-crR] [-h hostname] [-p port] [-w#={0|1} ...]\n");
	exit(0);
}

main(argc, argv)
int argc;
char *argv[];
{
int ii;
	int ret = 255;				/* return value */
	int ch, d, n, len;
	int flag = OPT_READSIMPLE;		/* フラグ */
	int sock;								/* ソケット */
	int port;								/* ポート番号 */
	int xport[] = {-1, -1, -1, -1};		/* ライト用XPortポート配列 */
	char *p;
	char cliname[BUFSIZ];			/* 自ホスト名格納用 */
	char svrname[BUFSIZ];			/* サーバ名格納用 */
	char str[16];				/* メッセージバッファ */
	char msg[BUFSIZ];			/* メッセージ表示用 */
	char data[BUFSIZ];			/* データバッファ用 */
	struct hostent *host;			/* サーバ用ホスト構造体 */
	struct sockaddr_in svr;			/* サーバの情報 */
	struct sockaddr_in cli;			/* クライアントの情報 */
	struct in_addr tmp_ip;


	while((ch = getopt(argc, argv, "ch:p:w:rv")) != -1){
		switch(ch){
		case 'c':		/* read XPort configuration */
			flag |= OPT_CONFIG;
			break;

		case 'p':		/* port number */
			port = atoi(optarg);
			flag |= OPT_PORT;
			break;

		case 'h':		/* server name */
			len = strlen(optarg);
			len = (len > BUFSIZ-1) ? BUFSIZ-1 : len;
	 		strncpy(svrname, optarg, len+1);	/* copy whole null termination */
			flag |= OPT_HOSTNAME;
			break;

		case 'r':		/* read XPort */
			flag |= OPT_READ;
			break;

		case 'R':		/* read XPort extra */
			flag |= OPT_READSIMPLE;
			break;

		case 'w':		/* output to port */
			if(isdigit(optarg[0]) && optarg[1] == '='
						&& isdigit(optarg[2])){
				/* XPort No. (CP1〜3) */
				n = optarg[0] - '0';
				n = (n < 1 || n > 3) ? 1 : n;

				/* switch */
				xport[n] = (atoi(optarg+2)) ? 1 : 0;
				flag |= (0x00010000 << n) | OPT_WRITE;
			}
			break;

		case 'v':		/* verbose mode */
			flag |= OPT_VERBOSE;
			break;

		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;


	/* ソケットアドレス構造体のクリア */
	bzero(&svr, sizeof(svr));

	/* サーバのホスト情報の取得 */
	if(flag & OPT_HOSTNAME){
		p = svrname;
	}else{
		p = SVR_HOSTNAME;
	}
	host = gethostbyname(p);

	/* アドレスファミリの設定 */
	svr.sin_family = AF_INET;

	/* サーバのIPアドレスをソケットアドレス構造体にセットする */
	bcopy(host->h_addr, &svr.sin_addr, host->h_length);

	/* アドレスファミリの設定 */
	svr.sin_family = host->h_addrtype;	/* AF_INET */

	/* 接続ポート番号の設定 */
	if(!(flag & OPT_PORT)){
		port = SVR_PORT;
	}
	svr.sin_port = htons(port);

	/* ソケットの作成 */
	if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("Error: can't create socket.");
	}

	/* 自ホスト名の取得 */
	gethostname(cliname, sizeof(cliname));

	/* ソケット構造体の初期化 */
	bzero(&cli, sizeof(cli));

	/* インタフェースが複数あるホストの場合、
					どちらのインタフェースも特定しないためのアドレス */
	cli.sin_addr.s_addr = INADDR_ANY;

	/* クライアントをシステムに登録する */
	if(bind(sock, (struct sockaddr *)&cli, sizeof(cli)) < 0){
		perror("Error: can't create bind.");
	}


	/* サーバへ接続する */
	if(connect(sock, (struct sockaddr *)&svr, sizeof(svr)) < 0){
		perror("Error: can't create connect");
	}

	xport_write(sock);

exit:
	/* 通信が終了したらソケットを解放する */
	close( sock );
	exit(0);
}

