RASCSI/src/raspberrypi/rasctl.cpp

248 lines
5.0 KiB
C++
Raw Normal View History

2018-05-03 13:47:57 +00:00
//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Powered by XM6 TypeG Technology.
// Copyright (C) 2016-2018 GIMONS
// [ 制御コマンド送信 ]
//
//---------------------------------------------------------------------------
#include "os.h"
//---------------------------------------------------------------------------
//
// コマンド送信
//
//---------------------------------------------------------------------------
BOOL SendCommand(char *buf)
{
int fd;
struct sockaddr_in server;
FILE *fp;
// コマンド用ソケット生成
fd = socket(PF_INET, SOCK_STREAM, 0);
memset(&server, 0, sizeof(server));
server.sin_family = PF_INET;
server.sin_port = htons(6868);
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
// 接続
if (connect(fd, (struct sockaddr *)&server,
sizeof(struct sockaddr_in)) < 0) {
fprintf(stderr, "Error : Can't connect to rascsi process\n");
return FALSE;
}
// 送信
fp = fdopen(fd, "r+");
setvbuf(fp, NULL, _IONBF, 0);
fprintf(fp, buf);
// メッセージ受信
while (1) {
if (fgets((char *)buf, BUFSIZ, fp) == NULL) {
break;
}
printf("%s", buf);
}
// ソケットを閉じる
fclose(fp);
close(fd);
return TRUE;
}
//---------------------------------------------------------------------------
//
// 主処理
//
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
int opt;
int id;
int cmd;
int type;
char *file;
BOOL list;
int len;
char *ext;
char buf[BUFSIZ];
id = -1;
cmd = -1;
type = -1;
file = NULL;
list = FALSE;
// ヘルプの表示
if (argc < 2) {
fprintf(stderr, "SCSI Target Emulator RaSCSI Controller\n");
fprintf(stderr,
"Usage: %s -i ID [-c CMD] [-t TYPE] [-f FILE]\n",
argv[0]);
fprintf(stderr, " where ID := {0|1|2|3|4|5|6|7}\n");
fprintf(stderr, " CMD := {attach|detatch|insert|eject|protect}\n");
fprintf(stderr, " TYPE := {hd|mo|cd|bridge}\n");
fprintf(stderr, " FILE := image file path\n");
fprintf(stderr, " CMD is 'attach' or 'insert' and FILE parameter is required.\n");
fprintf(stderr, "Usage: %s -l\n", argv[0]);
fprintf(stderr, " Print device list.\n");
exit(0);
}
// 引数解析
opterr = 0;
while ((opt = getopt(argc, argv, "i:c:t:f:l")) != -1) {
switch (opt) {
case 'i':
id = optarg[0] - '0';
break;
case 'c':
switch (optarg[0]) {
case 'a': // ATTACH
case 'A':
cmd = 0;
break;
case 'd': // DETACH
case 'D':
cmd = 1;
break;
case 'i': // INSERT
case 'I':
cmd = 2;
break;
case 'e': // EJECT
case 'E':
cmd = 3;
break;
case 'p': // PROTECT
case 'P':
cmd = 4;
break;
}
break;
case 't':
switch (optarg[0]) {
case 's': // HD(SASI)
case 'S':
case 'h': // HD(SCSI)
case 'H':
type = 0;
break;
case 'm': // MO
case 'M':
type = 2;
break;
case 'c': // CD
case 'C':
type = 3;
break;
case 'b': // BRIDGE
case 'B':
type = 4;
break;
}
break;
case 'f':
file = optarg;
break;
case 'l':
list = TRUE;
break;
}
}
// リスト表示のみ
if (id < 0 && cmd < 0 && type < 0 && file == NULL && list) {
sprintf(buf, "list\n");
SendCommand(buf);
exit(0);
}
// IDチェック
if (id < 0 || id > 7) {
fprintf(stderr, "Error : Invalid ID\n");
exit(EINVAL);
}
// コマンドチェック
if (cmd < 0) {
cmd = 0; // デフォルトはATTATCHとする
}
// タイプチェック
if (cmd == 0 && type < 0) {
// 拡張子からタイプ判別を試みる
len = file ? strlen(file) : 0;
if (len > 4 && file[len - 4] == '.') {
ext = &file[len - 3];
if (xstrcasecmp(ext, "hdf") == 0 ||
xstrcasecmp(ext, "hds") == 0 ||
xstrcasecmp(ext, "hdn") == 0 ||
xstrcasecmp(ext, "hdi") == 0 ||
xstrcasecmp(ext, "nhd") == 0 ||
xstrcasecmp(ext, "hda") == 0) {
// HD(SASI/SCSI)
type = 0;
} else if (xstrcasecmp(ext, "mos") == 0) {
// MO
type = 2;
} else if (xstrcasecmp(ext, "iso") == 0) {
// CD
type = 3;
}
}
if (type < 0) {
fprintf(stderr, "Error : Invalid type\n");
exit(EINVAL);
}
}
// ファイルチェック(コマンドはATTACHでタイプはHD)
if (cmd == 0 && type >= 0 && type <= 1) {
if (!file) {
fprintf(stderr, "Error : Invalid file path\n");
exit(EINVAL);
}
}
// ファイルチェック(コマンドはINSERT)
if (cmd == 2) {
if (!file) {
fprintf(stderr, "Error : Invalid file path\n");
exit(EINVAL);
}
}
// 必要でないtypeは0としておく
if (type < 0) {
type = 0;
}
// 送信コマンド生成
sprintf(buf, "%d %d %d %s\n", id, cmd, type, file ? file : "-");
if (!SendCommand(buf)) {
exit(ENOTCONN);
}
// リスト表示
if (list) {
sprintf(buf, "list\n");
SendCommand(buf);
}
// 終了
exit(0);
}