946 lines
25 KiB
C
946 lines
25 KiB
C
/* a simple commandline client for sics and sea
|
|
|
|
Markus Zolliker
|
|
Mar. 2003 first version
|
|
Aug. 2005 visible difference between client for SICS and sea
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include "term.h"
|
|
#include "myc_err.h"
|
|
#include "myc_str.h"
|
|
#include "instr_hosts.h"
|
|
|
|
typedef enum { NORMAL, SPY, CLIENT, NMODE } Mode;
|
|
|
|
#define MAXMSG 8192
|
|
|
|
static char *clcname="six", *servername="sics";
|
|
static int clclen=3;
|
|
static char host[128];
|
|
static char instr[32];
|
|
static int sock[2]; /* main socket and spy socket */
|
|
static int level=0; /* undefined level */
|
|
static int deflevel=0;
|
|
static int remember=1;
|
|
static int hidecom=1;
|
|
static char user1[32]="";
|
|
static char pswd1[32]="";
|
|
static char user2[32]="";
|
|
static char pswd2[32]="";
|
|
static char status[MAXMSG]="Busy";
|
|
static int busy[2];
|
|
static int port;
|
|
static char msg0[MAXMSG];
|
|
static char msg1[MAXMSG]; /* contains messages for main and spy */
|
|
static int pos0 = 0;
|
|
static int pos1 = 0;
|
|
static char *prefix[NMODE+1]={"", "| ", "# ", ""};
|
|
static int newline[NMODE+1]={1,1,1,1};
|
|
static char *sim="";
|
|
|
|
static char *pw=NULL;
|
|
static char *us="";
|
|
|
|
void Put(Mode mode, char *text) {
|
|
char chr;
|
|
|
|
while (*text) {
|
|
if (newline[mode]) {
|
|
fputs("\033[0m", stdout);
|
|
fputs(prefix[mode], stdout);
|
|
newline[mode] = 0;
|
|
if (strncmp(text, "ERROR:", 6) == 0) {
|
|
fputs("\033[31;1m", stdout);
|
|
}
|
|
}
|
|
chr = *text; text++;
|
|
fputc(chr, stdout);
|
|
if (chr == '\r' || chr == '\n') {
|
|
newline[mode] = 1;
|
|
}
|
|
}
|
|
fflush(stdout);
|
|
}
|
|
|
|
void PutC(char *text) {
|
|
Put(CLIENT, text);
|
|
}
|
|
|
|
void PutClear(void) {
|
|
Put(NMODE, "");
|
|
}
|
|
|
|
void UsageNote(void) {
|
|
PutC(" (for usage type: ");
|
|
PutC(clcname);
|
|
PutC(" help)\n");
|
|
}
|
|
|
|
void Usage(int cmds_only) {
|
|
if (!cmds_only) {
|
|
PutC(" \n ");
|
|
PutC(clcname);
|
|
PutC(
|
|
" commandline options:\n"
|
|
" -x login as spy\n"
|
|
" -u login as user\n"
|
|
" -m login as manager\n"
|
|
" help show this help text\n"
|
|
" -a or a ask always for username/password, forget passwords\n"
|
|
" -c or c use background color instead of # and |\n"
|
|
" -s or s simulation mode (on some instruments)\n"
|
|
" <instr> connect to the server for instr\n"
|
|
" -h <host> connect to a server on a different host\n"
|
|
" -p <port> connect to a server on a different port\n"
|
|
" -n do only a minimal login (no check of instrument)\n"
|
|
" no option login with default privilege\n"
|
|
);
|
|
}
|
|
PutC(
|
|
"\n"
|
|
" Special commands treated by ");
|
|
PutC(clcname); PutC(" (these are no "); PutC(servername); PutC(" commands!)\n"
|
|
"\n"
|
|
" quit return to unix prompt\n"
|
|
" exit return to unix prompt\n"
|
|
" stop interrupt driving\n"
|
|
" "); PutC(clcname);
|
|
PutC(" help show this help text\n"
|
|
" "); PutC(clcname);
|
|
PutC(" def stop define a key for stop command\n"
|
|
" "); PutC(clcname);
|
|
PutC(" save save stop key and connection (host/port/access)\n"
|
|
" + increase privilege\n"
|
|
" - decrease privilege\n"
|
|
"\n"
|
|
" The "); PutC(servername);
|
|
PutC(" status is shown, if it is not 'Eager to execute commands'.\n"
|
|
" A shown status does not prohibit to enter commands.\n"
|
|
"\n"
|
|
" When "); PutC(servername);
|
|
PutC(" is busy, a vertical bar '|' is shown at the left of the line.\n"
|
|
" You may then enter more commands, but only under Spy privilege.\n"
|
|
" All messages from the client are prefixed with a hash symbol '#'.\n"
|
|
"\n"
|
|
" Markus Zolliker, Aug. 2005\n"
|
|
"\n"
|
|
);
|
|
Put(-1, ""); /* clear colors */
|
|
}
|
|
|
|
int CocCreateSockAdr(
|
|
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
|
const char *host, /* Host. NULL implies INADDR_ANY */
|
|
int port) /* Port number */
|
|
{
|
|
struct hostent *hostent; /* Host database entry */
|
|
struct in_addr addr; /* For 64/32 bit madness */
|
|
|
|
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
|
|
sockaddrPtr->sin_family = AF_INET;
|
|
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
|
|
if (host == NULL || host[0]=='\0') {
|
|
addr.s_addr = INADDR_ANY;
|
|
} else {
|
|
hostent = gethostbyname(host);
|
|
if (hostent != NULL) {
|
|
memcpy((char *) &addr,
|
|
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
|
|
} else {
|
|
addr.s_addr = inet_addr(host);
|
|
if (addr.s_addr == (unsigned long)-1) {
|
|
return -1; /* error */
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* There is a rumor that this assignment may require care on
|
|
* some 64 bit machines.
|
|
*/
|
|
|
|
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
|
|
return 0;
|
|
}
|
|
|
|
char* readWrite(int tmo, int skip, char *find) {
|
|
int lbuf, go, n, shortTmo, l, socket;
|
|
Mode idx;
|
|
char *msg, *p, *q;
|
|
char chr;
|
|
static char result[MAXMSG];
|
|
int hide;
|
|
static int laststat=0, laststatlen=0;
|
|
/*
|
|
* read from registered sockets and write to stdout until a key pressed,
|
|
* a timeout occurred (tmo [msec]), or a TRANSACTIONFINISHED message
|
|
* received. Handle also status and TRANSACTIONSTART messages.
|
|
*
|
|
* skip=0: skip response that does not match
|
|
* skip=1: skip all responses
|
|
* skip=2: skip all responses, quit on match
|
|
*
|
|
* if the response starts with the contents of find
|
|
* the second part of the line is returned
|
|
* if the response contain the contents of find, but not at the beginning
|
|
* "1" is returned
|
|
* if the text is not found, or find=NULL, an empty line is returned
|
|
*/
|
|
n=0;
|
|
go=0;
|
|
shortTmo = 0;
|
|
str_copy(result, "");
|
|
socket=term_wait_socket(0, tmo);
|
|
while (socket > 0) {
|
|
idx = (socket == sock[1]);
|
|
ERR_SI(lbuf=recv(socket, &chr, 1, 0));
|
|
if (lbuf==0) return "0";
|
|
while (lbuf>0) {
|
|
if (chr == '\n') break;
|
|
if (idx) {
|
|
if (chr != '\r' && pos1 < MAXMSG-1) { /* cut lines longer than MAXMSG */
|
|
msg1[pos1]=chr;
|
|
pos1++;
|
|
}
|
|
} else {
|
|
if (chr != '\r' && pos0 < MAXMSG-1) { /* cut lines longer than MAXMSG */
|
|
msg0[pos0]=chr;
|
|
pos0++;
|
|
}
|
|
}
|
|
socket=term_wait_socket(0, tmo);
|
|
if (socket <= 0) break;
|
|
idx = (socket == sock[1]);
|
|
ERR_SI(lbuf=recv(socket, &chr, 1, 0));
|
|
}
|
|
hide=0;
|
|
if (idx) { /* spy mode */
|
|
msg1[pos1] = '\0';
|
|
pos1 = 0;
|
|
msg = msg1;
|
|
if (!busy[1]) { /* skip spy messages if not busy (they will be doubled) */
|
|
hide = 1;
|
|
}
|
|
} else {
|
|
msg0[pos0] = '\0';
|
|
pos0 = 0;
|
|
msg = msg0;
|
|
}
|
|
/* printf("[%s]\n", msg); */
|
|
if (strncmp(msg, "TRANSACTIONSTART", 16) == 0) {
|
|
busy[idx] = 1;
|
|
hide = 1;
|
|
} else if (strncmp(msg, "TRANSACTIONFINISHED", 19) == 0) {
|
|
busy[idx] = 0;
|
|
if (skip != 2) go = 1;
|
|
shortTmo = 1;
|
|
hide = 1;
|
|
} else if (idx == 0 && strncmp(msg, "status = ", 9) == 0) {
|
|
strcpy(status, msg+9);
|
|
l = strlen(msg);
|
|
if (status[0] == 'E') {
|
|
} else if (laststat!=status[0] || laststatlen != l) {
|
|
laststat = status[0];
|
|
laststatlen = l;
|
|
}
|
|
hide = 1;
|
|
}
|
|
if (idx == 0 && find != NULL) {
|
|
p=strstr(msg, find);
|
|
|
|
if (p!=NULL) { /* copy message to result */
|
|
if (p==msg) {
|
|
str_copy(result, msg+strlen(find));
|
|
q=strchr(result,'\r');
|
|
if (q != NULL) *q='\0';
|
|
} else {
|
|
str_copy(result, "1");
|
|
}
|
|
hide=1;
|
|
if (skip == 2) go = 1;
|
|
}
|
|
}
|
|
if (hidecom && (skip || hide)) { /* skip text */
|
|
n+=strlen(msg);
|
|
} else {
|
|
term_clear();
|
|
Put(idx, msg);
|
|
if (chr == '\n') {
|
|
Put(idx, "\033[K\n");
|
|
}
|
|
}
|
|
if (go) break;
|
|
socket = term_wait_socket(0, shortTmo?100:tmo);
|
|
shortTmo = 0;
|
|
}
|
|
fflush(stdout);
|
|
if (result==NULL) laststat=0;
|
|
return result;
|
|
OnError: return NULL;
|
|
}
|
|
|
|
void PrintCmd(char *buf, int mode) {
|
|
Put(mode, "\r\033[K\n");
|
|
Put(mode, "\033[1;34m>> ");
|
|
Put(mode, buf);
|
|
Put(mode, "\033[K\033[0m\n");
|
|
}
|
|
|
|
int sendCmd(int socket, char *cmd) {
|
|
int l;
|
|
char buf[256];
|
|
|
|
snprintf(buf, sizeof buf, "fulltransact %s\n", cmd);
|
|
ERR_SI(l=send(socket, buf, strlen(buf), 0));
|
|
return l;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int scramble(char *buf) {
|
|
int i, n, cnt, chr;
|
|
int x;
|
|
/* Scrambles a string. Twice scramble gives original.
|
|
It does never convert a plain char to a ctrl char
|
|
and all standard ascii-codes to special chars and vice versa.
|
|
returns the number of special chars on output
|
|
*/
|
|
|
|
n=strlen(buf);
|
|
x=23;
|
|
cnt=0;
|
|
for (i=0; i<n; i++) {
|
|
chr=(buf[i] & 255) ^ (x % 32 + 128);
|
|
if (chr & 128) cnt++;
|
|
x=(x*13+5) % 256;
|
|
buf[i]=chr;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
void getscrambled(char *buf, int size, FILE *fil) {
|
|
term_fgets(buf, size, fil);
|
|
if (scramble(buf) > 0) scramble(buf);
|
|
}
|
|
|
|
void putscrambled(char *buf, FILE *fil) {
|
|
char cvt[256];
|
|
str_copy(cvt, buf);
|
|
scramble(cvt);
|
|
fprintf(fil, "%s\n", cvt);
|
|
}
|
|
|
|
int setrights(int gotolevel) {
|
|
char *p;
|
|
char prefhead[128], buf[128];
|
|
FILE *fil;
|
|
int ask;
|
|
static char user[32]="";
|
|
static char pswd[32]="";
|
|
int savepw;
|
|
|
|
if (pw == NULL) pw=pswd;
|
|
str_copy(prefhead, clcname);
|
|
str_append(prefhead, ".");
|
|
str_append(prefhead, instr);
|
|
|
|
if (remember) {
|
|
fil=term_open_pref(0, prefhead, "r");
|
|
if (fil != NULL) {
|
|
term_fgets(buf, sizeof(buf), fil);
|
|
getscrambled(user1, sizeof(user1), fil);
|
|
getscrambled(pswd1, sizeof(pswd1), fil);
|
|
getscrambled(user2, sizeof(user2), fil);
|
|
getscrambled(pswd2, sizeof(pswd2), fil);
|
|
fclose(fil);
|
|
}
|
|
if (deflevel==0) {
|
|
deflevel=buf[0]-'0';
|
|
if (deflevel<1 || deflevel>3) deflevel=2;
|
|
}
|
|
} else {
|
|
deflevel=2;
|
|
}
|
|
if (gotolevel == 0) gotolevel = deflevel;
|
|
if (deflevel == 0) deflevel = 3;
|
|
if (level != gotolevel) {
|
|
if (gotolevel==1) {
|
|
if (user1[0]=='\0') {
|
|
if (strcmp(clcname, "six") == 0) {
|
|
str_copy(user1, "lnsmanager");
|
|
} else {
|
|
str_copy(user2, servername);
|
|
str_append(user2, "manager");
|
|
}
|
|
}
|
|
us=user1;
|
|
pw=pswd1;
|
|
} else if (gotolevel==2) {
|
|
if (user2[0]=='\0') {
|
|
if (strcmp(clcname, "six") == 0) {
|
|
str_copy(user2, instr);
|
|
str_lowcase(user2, user2);
|
|
str_append(user2, "user");
|
|
} else {
|
|
str_copy(user2, servername);
|
|
str_append(user2, "user");
|
|
}
|
|
}
|
|
us=user2;
|
|
pw=pswd2;
|
|
} else if (gotolevel==3) {
|
|
us="Spy";
|
|
pw="007";
|
|
}
|
|
ask=1;
|
|
savepw = 1;
|
|
if (us[0]!='\0' && pw[0]!='\0' && remember) {
|
|
sprintf(buf, "config rights %s %s", us, pw);
|
|
ERR_I(sendCmd(sock[0], buf));
|
|
ERR_P(p=readWrite(12000,0,"Acknowledged"));
|
|
PutC(".");
|
|
if (*p=='\0') {
|
|
if (0==strcmp(us, user1)) {
|
|
user1[0]='\0';
|
|
pswd1[0]='\0';
|
|
}
|
|
if (0==strcmp(us, user2)) {
|
|
user2[0]='\0';
|
|
pswd2[0]='\0';
|
|
}
|
|
} else {
|
|
ask=0;
|
|
savepw = 0;
|
|
}
|
|
}
|
|
if (ask) {
|
|
PutC("\r");
|
|
PutC(servername);
|
|
PutC(" username");
|
|
if (us[0]!='\0') {
|
|
PutC(" [");
|
|
PutC(us);
|
|
PutC("]");
|
|
}
|
|
PutC(": ");
|
|
term_fgets(user, sizeof(user), stdin);
|
|
newline[CLIENT]=1;
|
|
if (0==strcmp(user, "quit")) return 1;
|
|
if (0==strcmp(user, "exit")) return 1;
|
|
if (user[0]=='\0') {
|
|
str_copy(user, us);
|
|
}
|
|
PutC("password: ");
|
|
term_fgets(pswd, sizeof(pswd), stdin);
|
|
newline[CLIENT]=1;
|
|
if (0==strcmp(pswd, "quit")) return 1;
|
|
if (0==strcmp(pswd, "exit")) return 1;
|
|
if (pswd[0]!='\0') {
|
|
sprintf(buf, "config rights %s %s", user, pswd);
|
|
ERR_I(sendCmd(sock[0], buf));
|
|
ERR_P(p=readWrite(12000,0,"Acknowledged"));
|
|
if (*p=='\0') { /* no success */
|
|
gotolevel=3;
|
|
if (0==strcmp(user, user1)) {
|
|
user1[0]='\0';
|
|
pswd1[0]='\0';
|
|
}
|
|
if (0==strcmp(user, user2)) {
|
|
user2[0]='\0';
|
|
pswd2[0]='\0';
|
|
}
|
|
pw=NULL;
|
|
} else { /* success */
|
|
if (0==strcmp(user, user1)) {
|
|
str_copy(pswd1, pswd);
|
|
}
|
|
if (0==strcmp(user, user2)) {
|
|
str_copy(pswd2, pswd);
|
|
}
|
|
us=user;
|
|
pw=pswd;
|
|
}
|
|
} else {
|
|
gotolevel=3;
|
|
}
|
|
}
|
|
level=3;
|
|
ERR_I(sendCmd(sock[0], "config myrights"));
|
|
ERR_P(p=readWrite(12000,1,"UserRights = "));
|
|
PutC(".");
|
|
if (*p!='\0') {
|
|
level=*p-'0';
|
|
}
|
|
if (level==3) {
|
|
us="Spy";
|
|
}
|
|
}
|
|
if (pw!=NULL && savepw) {
|
|
if (level==1) {
|
|
str_copy(user1, us);
|
|
str_copy(pswd1, pw);
|
|
if (0==strcmp(user1, user2)) {
|
|
user2[0]='\0';
|
|
pswd2[0]='\0';
|
|
}
|
|
} else if (level==2) {
|
|
str_copy(user2, us);
|
|
str_copy(pswd2, pw);
|
|
if (0==strcmp(user2, user1)) {
|
|
user1[0]='\0';
|
|
pswd1[0]='\0';
|
|
}
|
|
}
|
|
}
|
|
fil=term_open_pref(0, prefhead, "w");
|
|
if (fil!=NULL) {
|
|
fprintf(fil, "%d\n", deflevel);
|
|
if (remember) {
|
|
putscrambled(user1, fil);
|
|
putscrambled(pswd1, fil);
|
|
putscrambled(user2, fil);
|
|
putscrambled(pswd2, fil);
|
|
}
|
|
fclose(fil);
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int SavePrefs(void) {
|
|
char prefhead[128], name[128];
|
|
FILE *fil;
|
|
|
|
ERR_SI(gethostname(name, sizeof name)); /* get ip name of this host */
|
|
str_copy(prefhead, clcname);
|
|
str_append(prefhead, "_");
|
|
str_append(prefhead, sim);
|
|
str_append(prefhead, name);
|
|
|
|
ERR_SP(fil=term_open_pref(0, prefhead, "w"));
|
|
fprintf(fil, "keys\n");
|
|
term_save_keys(fil, PutC);
|
|
fclose(fil);
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int LoadPrefs(void) {
|
|
char prefhead[128], name[128], line[128];
|
|
FILE *fil;
|
|
|
|
ERR_SI(gethostname(name, sizeof name)); /* get ip name of this host */
|
|
str_copy(prefhead, clcname);
|
|
str_append(prefhead, "_");
|
|
str_append(prefhead, sim);
|
|
str_append(prefhead, name);
|
|
fil=term_open_pref(0, prefhead, "r");
|
|
if (fil) {
|
|
while (term_fgets(line, sizeof(line), fil)) {
|
|
if (0 == strcmp(line, "keys")) {
|
|
term_load_keys(fil, PutC);
|
|
}
|
|
}
|
|
fclose(fil);
|
|
}
|
|
return 0;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int Connect(void) {
|
|
int sock;
|
|
struct sockaddr_in sadr;
|
|
char *p;
|
|
|
|
ERR_I(CocCreateSockAdr(&sadr, host, port));
|
|
ERR_SI(sock=socket(AF_INET, SOCK_STREAM, 0));
|
|
term_reg_socket(sock);
|
|
ERR_SI(connect(sock, (struct sockaddr *)&sadr, sizeof(sadr)));
|
|
ERR_SI(send(sock, "Spy 007\n", 8, 0));
|
|
ERR_P(p=readWrite(12000,2,"Login O"));
|
|
if (*p!='K') { /* looking for the 'K' of 'Login OK' */
|
|
PutC("rejected\n");
|
|
return 0;
|
|
}
|
|
return sock;
|
|
OnError: return -1;
|
|
}
|
|
|
|
int main (int argc, char *argv[]) {
|
|
struct hostent *ent;
|
|
int iret, pos;
|
|
fd_set mask;
|
|
int i, j, gotolevel, sicslogin;
|
|
int home;
|
|
int savehist = 0;
|
|
char buf[512], lbuf[16];
|
|
char stdPrompt[128]="", prompt[256]="";
|
|
char *p;
|
|
char *bar;
|
|
char *pnam[4]={"0", "MANAGER", "user", "spy"};
|
|
char *hostArg;
|
|
char *subcmd;
|
|
char *service;
|
|
|
|
atexit(term_off);
|
|
port=-1;
|
|
home=0;
|
|
sicslogin=1;
|
|
deflevel=0;
|
|
gotolevel=0;
|
|
hostArg=NULL;
|
|
sock[1]=0; /* do not yet connect 2nd connection */
|
|
for (i=1; i<argc; i++) {
|
|
if (0==strcmp(argv[i], "-s") || 0==strcmp(argv[i], "s")) {
|
|
sim="sim-";
|
|
} else if (0==strcmp(argv[i], "-sea") || 0==strcmp(argv[i], "sea")) {
|
|
clcname="seacmd";
|
|
servername="sea";
|
|
clclen=strlen(clcname);
|
|
} else if (0==strcmp(argv[i], "-graph") || 0==strcmp(argv[i], "graph")) {
|
|
clcname="graphcmd";
|
|
servername="graph";
|
|
clclen=strlen(clcname);
|
|
} else if (0==strcmp(argv[i], "-a") || 0==strcmp(argv[i], "a")) {
|
|
remember=0;
|
|
} else if (0==strcmp(argv[i], "-c") || 0==strcmp(argv[i], "c")) {
|
|
prefix[NORMAL] = "\033[47m";
|
|
prefix[SPY] = "\033[43m";
|
|
prefix[CLIENT] = "\033[0m";
|
|
} else if (0==strcmp(argv[i], "-d") || 0==strcmp(argv[i], "d")) {
|
|
hidecom=0;
|
|
} else if (0==strcmp(argv[i], "+") || 0==strcmp(argv[i], "-m")) {
|
|
gotolevel=1;
|
|
} else if (0==strcmp(argv[i], "-") || 0==strcmp(argv[i], "-x")) {
|
|
gotolevel=3;
|
|
} else if (0==strcmp(argv[i], "0") || 0==strcmp(argv[i], "-u")) {
|
|
gotolevel=2;
|
|
} else if (0==strcmp(argv[i], "++")) {
|
|
gotolevel=1;
|
|
deflevel=1;
|
|
} else if (0==strcmp(argv[i], "--")) {
|
|
gotolevel=3;
|
|
deflevel=3;
|
|
} else if (0==strcmp(argv[i], "00")) {
|
|
gotolevel=2;
|
|
deflevel=2;
|
|
} else if (0==strcmp(argv[i], "help")) {
|
|
Usage(0);
|
|
return 0;
|
|
} else if (0==strcmp(argv[i], "-h")) {
|
|
i++;
|
|
if (i>=argc) {
|
|
PutC("missing host");
|
|
UsageNote(); return 0;
|
|
}
|
|
hostArg = argv[i];
|
|
} else if (0==strcmp(argv[i], "-p")) {
|
|
i++;
|
|
if (i>=argc) {
|
|
PutC("missing port");
|
|
UsageNote(); return 0;
|
|
}
|
|
port=atoi(argv[i]);
|
|
if (port == 0) {
|
|
PutC("illegal port");
|
|
UsageNote(); return 0;
|
|
}
|
|
} else if (0==strcmp(argv[i], "-n")) {
|
|
sicslogin=0;
|
|
} else {
|
|
if (strlen(argv[i])>=32) {
|
|
PutC("argument too long");
|
|
UsageNote(); return 0;
|
|
} else if (argv[i][0] == '-') {
|
|
PutC("unknown option: ");
|
|
PutC(argv[i]);
|
|
UsageNote(); return 0;
|
|
} else if (argv[i][1] == '\0' && isdigit(argv[i][0])) {
|
|
port = atoi(argv[i]);
|
|
} else {
|
|
hostArg = argv[i];
|
|
}
|
|
}
|
|
}
|
|
if (*sim != '\0') {
|
|
service = "simsics";
|
|
} else {
|
|
service = servername;
|
|
}
|
|
home = InstrHost(service, hostArg, instr, sizeof instr
|
|
, host, sizeof host, &port);
|
|
ent = gethostbyname(host);
|
|
if (!ent) {
|
|
if (hostArg == NULL || hostArg[0] <= ' ') {
|
|
snprintf(host, sizeof host, "%s", getenv("HOST"));
|
|
hostArg = host;
|
|
}
|
|
PutC(service);
|
|
PutC(" on ");
|
|
PutC(hostArg);
|
|
PutC(" not found in InstrumentHostList\n");
|
|
p=getenv("InstrumentHostList");
|
|
if (p) {
|
|
PutC("(");
|
|
PutC(p);
|
|
PutC(")\n");
|
|
}
|
|
return 0;
|
|
}
|
|
snprintf(host, sizeof host, "%s", ent->h_name);
|
|
LoadPrefs();
|
|
|
|
PutC( "---------------------------------------------------\n");
|
|
if (strcmp(clcname, "six") == 0) {
|
|
PutC("six, a fast sics commandline client (doc: six help)\n");
|
|
if (port == -1) {
|
|
if (*sim == '\0') {
|
|
port = 2911;
|
|
} else {
|
|
port = 2927;
|
|
}
|
|
home = 1;
|
|
}
|
|
} else if (strcmp(clcname, "seacmd") == 0) {
|
|
PutC("seacmd, a sea commandline client (doc: seacmd help)\n");
|
|
if (port == -1) {
|
|
port = 8641;
|
|
} else if (port > 0 && port < 9) {
|
|
port += 8640;
|
|
}
|
|
home = 1;
|
|
} else {
|
|
PutC("graphcmd, a graph commandline client (doc: graphcmd help)\n");
|
|
if (port == -1) {
|
|
port = 8741;
|
|
} else if (port > 0 && port < 9) {
|
|
port += 8740;
|
|
}
|
|
home = 1;
|
|
}
|
|
PutC( "---------------------------------------------------\n");
|
|
PutC(".");
|
|
ERR_I(sock[0]=Connect());
|
|
PutC(".");
|
|
if (sock[0] == 0) return 0;
|
|
if (sicslogin) {
|
|
|
|
ERR_I(sendCmd(sock[0], "Instrument"));
|
|
ERR_P(p=readWrite(12000,0,"Instrument = "));
|
|
PutC(".");
|
|
str_copy(instr, p);
|
|
if (*instr=='\0') {
|
|
PutC("can not detect instrument\n");
|
|
return 0;
|
|
}
|
|
str_lowcase(instr,instr);
|
|
p=strchr(instr,' ');
|
|
if (p!=NULL) *p='\0';
|
|
if (0==strcmp(instr,"SANS-II")) {
|
|
str_copy(instr, "SANS2");
|
|
}
|
|
if (!home) {
|
|
deflevel = 3;
|
|
gotolevel = 3;
|
|
}
|
|
ERR_I(i=setrights(gotolevel));
|
|
PutC(".");
|
|
PutC("\rlogged in to "); PutC(servername); PutC(" as ");
|
|
PutC(pnam[level]);
|
|
PutC(" on ");
|
|
PutC(instr);
|
|
PutC("\n");
|
|
|
|
sprintf(stdPrompt, "%s[%s] ", clcname, instr);
|
|
|
|
ERR_I(sendCmd(sock[0], "status interest"));
|
|
ERR_P(readWrite(12000,0,"OK"));
|
|
|
|
ERR_I(sendCmd(sock[0], "status"));
|
|
ERR_P(readWrite(12000,0,NULL));
|
|
|
|
term_read_hist(clcname, instr);
|
|
} else {
|
|
sprintf(stdPrompt, "%s[%s] ", clcname, host);
|
|
status[0]='E'; status[1]='\0';
|
|
term_read_hist(clcname, host);
|
|
}
|
|
|
|
iret=1;
|
|
buf[0]='\0';
|
|
pos=0;
|
|
|
|
savehist = 1;
|
|
|
|
while (1) {
|
|
if (busy[0]) {
|
|
bar = prefix[SPY];
|
|
} else {
|
|
bar = prefix[NORMAL];
|
|
}
|
|
if (status[0] == 'E') { /* Eager to ... */
|
|
sprintf(prompt, "%s%s", bar, stdPrompt);
|
|
} else {
|
|
sprintf(prompt, "%s%s(%s) ", bar, stdPrompt, status);
|
|
}
|
|
FD_ZERO(&mask);
|
|
FD_SET(sock[0], &mask);
|
|
iret=term_get_line(buf, sizeof(buf)-2, &pos, prompt, &mask);
|
|
if (iret==STDIN_FILENO) { /* input line terminated */
|
|
str_lowcase(lbuf, buf);
|
|
if (0==strcmp(lbuf,"quit") || 0==strcmp(lbuf,"exit")) {
|
|
PrintCmd(buf, CLIENT);
|
|
break;
|
|
}
|
|
p="";
|
|
if (0==strcmp(lbuf,"stop")) {
|
|
PrintCmd(buf, CLIENT);
|
|
ERR_SI(send(sock[0], "INT1712 3\n", 10, 0));
|
|
buf[0]='\0';
|
|
} else if (0==strcmp(buf, "-") ||
|
|
0==strcmp(buf, "--") ||
|
|
0==strcmp(buf, "+") ||
|
|
0==strcmp(buf, "++")) {
|
|
PrintCmd(buf, CLIENT);
|
|
if (level == 0) {
|
|
gotolevel = 3;
|
|
} else {
|
|
gotolevel = level;
|
|
}
|
|
if (buf[0]=='-') {
|
|
if (gotolevel<3) gotolevel++;
|
|
} else {
|
|
if (gotolevel>1) gotolevel--;
|
|
}
|
|
if (strlen(buf)==2) {
|
|
deflevel=gotolevel;
|
|
}
|
|
term_off();
|
|
j = level;
|
|
ERR_I(i=setrights(gotolevel)); /* level might be changed */
|
|
if (j!=level) {
|
|
PutC("\rswitched to ");
|
|
} else {
|
|
PutC("\rremain at ");
|
|
}
|
|
PutC(pnam[level]);
|
|
PutC(" privilege\n");
|
|
buf[0]='\0';
|
|
} else if (0==strncmp(buf, "help ", 5) && 0==strcmp(buf+5, clcname)) {
|
|
PrintCmd(buf, CLIENT);
|
|
Usage(1);
|
|
buf[0]='\0';
|
|
} else if (0==strncmp(buf, clcname, clclen) && buf[clclen] == ' ') {
|
|
subcmd = buf + clclen;
|
|
while (*subcmd <= ' ' && *subcmd != 0) {
|
|
subcmd++;
|
|
}
|
|
if (0==strcmp(subcmd, "help")) {
|
|
PrintCmd(buf, CLIENT);
|
|
Usage(0);
|
|
buf[0]='\0';
|
|
} else if (0==strncmp(subcmd, "def ", 4)) {
|
|
PrintCmd(buf, CLIENT);
|
|
term_define_key(subcmd+4, 0);
|
|
buf[0]='\0';
|
|
} else if (0==strcmp(subcmd, "def")) {
|
|
PrintCmd(buf, CLIENT);
|
|
term_define_key("", 0);
|
|
buf[0]='\0';
|
|
} else if (0==strcmp(subcmd, "save")) {
|
|
PrintCmd(buf, CLIENT);
|
|
PutC("defaults for next calls to ");
|
|
PutC(clcname); PutC(":\n");
|
|
ERR_I(SavePrefs());
|
|
if (level == 0) {
|
|
gotolevel = 3;
|
|
} else {
|
|
gotolevel = level;
|
|
}
|
|
deflevel = gotolevel;
|
|
ERR_I(setrights(gotolevel));
|
|
PutC(" login as ");
|
|
PutC(us);
|
|
PutC(" with ");
|
|
PutC(pnam[level]);
|
|
PutC(" privilege\n");
|
|
buf[0]='\0';
|
|
} else {
|
|
PrintCmd(buf, CLIENT);
|
|
PutC("ERROR: unknown command\n");
|
|
buf[0]='\0';
|
|
}
|
|
} else if (buf[0] == '\0') { /* empty command */
|
|
PrintCmd(buf, CLIENT);
|
|
ERR_P(p=readWrite(200,0,NULL)); /* just wait a little */
|
|
}
|
|
if (buf[0] != '\0') {
|
|
if (busy[0]) {
|
|
if (!sock[1]) {
|
|
ERR_I(sock[1] = Connect());
|
|
if (!sock[1]) {
|
|
PutC("spy connection rejected\n");
|
|
}
|
|
}
|
|
if (busy[1]) {
|
|
/* print in red bold */
|
|
PrintCmd(buf, CLIENT);
|
|
PutC("\033[1;31mBUSY (already 2 commands pending)\033[0m\n");
|
|
buf[0]='\0';
|
|
} else if (sock[1]) {
|
|
PrintCmd(buf, SPY);
|
|
ERR_I(sendCmd(sock[1], buf));
|
|
} else {
|
|
PrintCmd(buf, CLIENT);
|
|
buf[0]='\0';
|
|
}
|
|
} else {
|
|
PrintCmd(buf, NORMAL);
|
|
ERR_I(sendCmd(sock[0], buf));
|
|
}
|
|
}
|
|
if (buf[0] != '\0') {
|
|
ERR_P(p=readWrite(500,0,NULL));
|
|
}
|
|
buf[0]='\0';
|
|
pos=0;
|
|
} else if (iret>0) { /* something arrived from sockets */
|
|
if (iret == sock[0] || iret == sock[1]) {
|
|
ERR_P(p=readWrite(500,0,NULL));
|
|
}
|
|
} else if (iret==-2) {
|
|
goto SaveHist;
|
|
} else if (iret<0) {
|
|
ERR_MSG("term_get_line failed");
|
|
}
|
|
if (strcmp(p, "0") == 0) {
|
|
term_clear();
|
|
PutC("\nconnection lost\n");
|
|
goto SaveHist;
|
|
}
|
|
}
|
|
if (savehist) term_save_hist(1); /* save history without last line */
|
|
goto Bye;
|
|
|
|
OnError:
|
|
ErrShow("end");
|
|
SaveHist:
|
|
if (savehist) term_save_hist(0); /* save history with last line */
|
|
Bye:
|
|
term_off();
|
|
if (stdPrompt[0]) {
|
|
PutC("\nexit ");
|
|
PutC(stdPrompt);
|
|
PutC("\n");
|
|
PutClear(); /* clear colors */
|
|
}
|
|
return 0;
|
|
}
|