602 lines
16 KiB
C
602 lines
16 KiB
C
#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 "term.h"
|
|
#include "coc_util.h"
|
|
#include "myc_err.h"
|
|
#include "myc_str.h"
|
|
|
|
static char *host;
|
|
static char instr[32];
|
|
static int fd;
|
|
static int level=3;
|
|
static int deflevel=0;
|
|
static int remember=1;
|
|
static char user1[32]="";
|
|
static char pswd1[32]="";
|
|
static char user2[32]="";
|
|
static char pswd2[32]="";
|
|
|
|
void Usage(int cmds_only) {
|
|
if (!cmds_only) {
|
|
printf("\n");
|
|
printf(" six commandline options:\n");
|
|
printf(" - login as spy\n");
|
|
printf(" + login as manager\n");
|
|
printf(" 0 login as user\n");
|
|
printf(" -- set spy as default\n");
|
|
printf(" 00 set user as default\n");
|
|
printf(" ++ set manager as default\n");
|
|
printf(" help show this help text\n");
|
|
printf(" -a or a ask always for username/password, forget passwords\n");
|
|
printf(" -s or s simulation mode (on some instruments)\n");
|
|
printf(" -w or w do not skip welcome message\n");
|
|
printf(" -h \"host\" connect to a SICServer on a different host\n");
|
|
printf(" -p \"port\" connect to a SICServer on a different port\n");
|
|
printf(" -n do not login\n");
|
|
printf(" no option login with default privilege\n");
|
|
}
|
|
printf("\n");
|
|
printf(" Special commands treated by six (these are no SICS commands!)\n");
|
|
printf("\n");
|
|
printf(" quit exit six\n");
|
|
printf(" exit exit six\n");
|
|
printf(" stop interrupt SICS\n");
|
|
printf(" help show this help text\n");
|
|
printf(" + increase privilege\n");
|
|
printf(" - decrease privilege\n");
|
|
printf("\n");
|
|
printf(" The SICS status is shown, if it is not 'Eager to execute commands'.\n");
|
|
printf(" A shown status does not prohibit to enter commands.\n");
|
|
printf("\n");
|
|
printf(" Markus Zolliker, Oct. 2003\n");
|
|
printf("\n");
|
|
}
|
|
|
|
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 fd, int tmo, int skip, char *find) {
|
|
char msg[256];
|
|
int lbuf, pos, go, iret, n, ga;
|
|
char *p, chr;
|
|
static char result[256];
|
|
int match;
|
|
static int laststat=0;
|
|
/*
|
|
* read from fd and write to stdout until a key pressed,
|
|
* a timeout occurred (tmo [msec]), or a <go ahead> message
|
|
* received.
|
|
* skip=0: skip response that does not match
|
|
* skip=1: skip all responses
|
|
*
|
|
* 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;
|
|
ga=0;
|
|
str_copy(result, "");
|
|
iret=term_wait_fd(fd, tmo);
|
|
while (iret>0) {
|
|
pos=0;
|
|
ERR_SI(lbuf=recv(fd, &chr, 1, 0));
|
|
if (lbuf==0) return "0";
|
|
while (lbuf>0) {
|
|
if (chr<' ') {
|
|
if (chr=='\n') break;
|
|
if (chr==-1) {
|
|
ga=1;
|
|
} else if (chr==-7 && ga) {
|
|
go=1; break;
|
|
} else {
|
|
ga=0;
|
|
if (chr!='\r') {
|
|
msg[pos++]=chr;
|
|
}
|
|
}
|
|
} else {
|
|
msg[pos++]=chr;
|
|
}
|
|
iret=term_wait_fd(fd, tmo);
|
|
if (iret!=1) break;
|
|
ERR_SI(lbuf=recv(fd, &chr, 1, 0));
|
|
}
|
|
msg[pos]='\0';
|
|
/* printf("[%s]\n", msg); */
|
|
match=0;
|
|
if (find != NULL) {
|
|
p=strstr(msg, find);
|
|
if (p!=NULL) { /* copy message to result */
|
|
if (p==msg) {
|
|
str_copy(result, msg+strlen(find));
|
|
p=strchr(result,'\r');
|
|
if (p != NULL) *p='\0';
|
|
} else {
|
|
str_copy(result, "1");
|
|
}
|
|
match=1;
|
|
if (find==strstr(find,"status")) {
|
|
if (result[0]=='E') {
|
|
tmo=100;
|
|
} else if (laststat!=result[0]) {
|
|
laststat=result[0];
|
|
go=1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (skip || match) { /* skip text */
|
|
n+=strlen(msg);
|
|
} else {
|
|
term_clear();
|
|
if (strncmp(msg, "ERROR:", 6)==0) {
|
|
fputs("\033[1;31m", stdout);
|
|
fputs(msg, stdout);
|
|
fputs("\033[0m", stdout);
|
|
} else {
|
|
fputs(msg, stdout);
|
|
}
|
|
if (chr=='\n') fputs("\n", stdout);
|
|
}
|
|
if (go) break;
|
|
iret=term_wait_fd(fd, tmo);
|
|
}
|
|
if (iret==0) laststat=0;
|
|
return result;
|
|
OnError: return NULL;
|
|
}
|
|
|
|
int sendCmd(int fd, char *cmd) {
|
|
int l;
|
|
char buf[256];
|
|
ERR_I(str_copy(buf, cmd));
|
|
ERR_I(str_append(buf, "\r\n"));
|
|
ERR_SI(l=send(fd, 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 user[32];
|
|
char pswd[32];
|
|
char *pw, *us, *p;
|
|
char prefhead[128], buf[128];
|
|
FILE *fil;
|
|
int ask;
|
|
|
|
us="";
|
|
user[0]='\0';
|
|
pw=pswd;
|
|
pswd[0]='\0';
|
|
|
|
p=getenv("HOME");
|
|
if (p != NULL) str_copy(prefhead, p);
|
|
str_append(prefhead, "/.six.");
|
|
str_append(prefhead, instr);
|
|
str_append(prefhead, ".");
|
|
|
|
if (0==strcmp(host, "0") && remember) {
|
|
fil=term_open_pref(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 (gotolevel==1) {
|
|
if (user1[0]=='\0') {
|
|
str_copy(user1, "lnsmanager");
|
|
}
|
|
us=user1;
|
|
pw=pswd1;
|
|
} else if (gotolevel==2) {
|
|
if (user2[0]=='\0') {
|
|
str_copy(user2, instr);
|
|
str_lowcase(user2, user2);
|
|
str_append(user2, "user");
|
|
}
|
|
us=user2;
|
|
pw=pswd2;
|
|
} else if (gotolevel==3) {
|
|
us="Spy";
|
|
pw="007";
|
|
}
|
|
ask=1;
|
|
if (us[0]!='\0' && pw[0]!='\0' && remember) {
|
|
sprintf(buf, "config rights %s %s", us, pw);
|
|
ERR_I(sendCmd(fd, buf));
|
|
ERR_P(p=readWrite(fd,10000,0,"Acknowledged"));
|
|
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;
|
|
pw=NULL;
|
|
}
|
|
}
|
|
if (ask) {
|
|
printf("SICS username");
|
|
if (us[0]!='\0') {
|
|
printf(" [%s]", us);
|
|
}
|
|
printf(": ");
|
|
term_fgets(user, sizeof(user), stdin);
|
|
if (0==strcmp(user, "quit")) return 1;
|
|
if (0==strcmp(user, "exit")) return 1;
|
|
if (user[0]=='\0') {
|
|
str_copy(user, us);
|
|
}
|
|
printf("password: ");
|
|
term_fgets(pswd, sizeof(pswd), stdin);
|
|
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(fd, buf));
|
|
ERR_P(p=readWrite(fd,10000,0,"Acknowledged"));
|
|
if (*p=='\0') {
|
|
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 {
|
|
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=gotolevel;
|
|
ERR_I(sendCmd(fd, "config list"));
|
|
ERR_P(p=readWrite(fd,10000,1,"UserRights = "));
|
|
if (*p!='\0') {
|
|
level=*p-'0';
|
|
}
|
|
if (level==3) {
|
|
us="Spy";
|
|
}
|
|
if (pw!=NULL) {
|
|
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';
|
|
}
|
|
}
|
|
}
|
|
if (0==strcmp(host, "0")) {
|
|
fil=term_open_pref(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 main (int argc, char *argv[]) {
|
|
int iret, pos;
|
|
fd_set mask;
|
|
int i, j, port, skip, gotolevel, sicslogin;
|
|
int savehist = 0;
|
|
char buf[128], lbuf[16], ilow[64];
|
|
char stdPrompt[128], prompt[256];
|
|
char *sim="";
|
|
char *p, *statusMatch=NULL;
|
|
char *pnam[4]={"0", "MANAGER", "user", "spy"};
|
|
|
|
struct sockaddr_in sadr;
|
|
|
|
printf("---------------------------------------------------\n");
|
|
printf("six, a fast SICS commandline client (doc: six help)\n");
|
|
printf("---------------------------------------------------\n");
|
|
port=1301;
|
|
skip=1;
|
|
sicslogin=1;
|
|
j=0;
|
|
deflevel=0;
|
|
gotolevel=0;
|
|
host="0"; /* localhost by default */
|
|
for (i=1; i<argc; i++) {
|
|
if (0==strcmp(argv[i], "-s") || 0==strcmp(argv[i], "s")) {
|
|
port=1303; sim="-sim";
|
|
} else if (0==strcmp(argv[i], "-w") || 0==strcmp(argv[i], "w")) {
|
|
skip=0;
|
|
} else if (0==strcmp(argv[i], "-a") || 0==strcmp(argv[i], "a")) {
|
|
remember=0;
|
|
} else if (0==strcmp(argv[i], "+")) {
|
|
gotolevel=1;
|
|
} else if (0==strcmp(argv[i], "-")) {
|
|
gotolevel=3;
|
|
} else if (0==strcmp(argv[i], "0")) {
|
|
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) {
|
|
printf("missing host\n");
|
|
Usage(0); return 0;
|
|
}
|
|
host=argv[i];
|
|
} else if (0==strcmp(argv[i], "-p")) {
|
|
i++;
|
|
if (i>=argc) {
|
|
printf("missing port\n");
|
|
Usage(0); return 0;
|
|
}
|
|
port=atoi(argv[i]);
|
|
if (port == 0) {
|
|
printf("illegal port\n");
|
|
Usage(0); return 0;
|
|
}
|
|
} else if (0==strcmp(argv[i], "-n")) {
|
|
sicslogin=0;
|
|
} else {
|
|
if (strlen(argv[i])>=32) {
|
|
printf("argument too long\n");
|
|
Usage(0); return 0;
|
|
} else if (argv[i][0]!='-') {
|
|
if (j==0) {
|
|
printf("syntax has changed, username can not be given as argument\n");
|
|
Usage(0); j=1;
|
|
}
|
|
} else {
|
|
printf("unknown option: %s\n", argv[i]);
|
|
Usage(0); return 0;
|
|
}
|
|
}
|
|
}
|
|
ERR_I(CocCreateSockAdr(&sadr, host, port));
|
|
ERR_SI(fd=socket(AF_INET, SOCK_STREAM, 0));
|
|
term_reg_socket(fd);
|
|
ERR_SI(connect(fd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
|
if (sicslogin) {
|
|
ERR_I(sendCmd(fd, "sicslogin Spy 007"));
|
|
ERR_P(p=readWrite(fd,10000,skip,"SICS"));
|
|
if (*p=='\0') {
|
|
printf("rejected\n");
|
|
return 0;
|
|
}
|
|
if (skip) printf("reading welcome message ...\n");
|
|
|
|
ERR_I(sendCmd(fd, "status interest"));
|
|
ERR_P(readWrite(fd,10000,0,"OK"));
|
|
|
|
ERR_I(sendCmd(fd, "Instrument"));
|
|
ERR_P(p=readWrite(fd,10000,0,"Instrument = "));
|
|
str_copy(instr, p);
|
|
if (*instr=='\0') {
|
|
printf("can not detect instrument\n");
|
|
return 0;
|
|
}
|
|
p=strchr(instr,' ');
|
|
if (p!=NULL) *p='\0';
|
|
if (0==strcmp(instr,"SANS-II")) {
|
|
str_copy(instr, "SANS2");
|
|
}
|
|
ERR_I(i=setrights(gotolevel));
|
|
if (i==1) return 0;
|
|
printf("\rlogged in to SICS as %s on %s\n", pnam[level], instr);
|
|
|
|
str_lowcase(ilow,instr);
|
|
sprintf(stdPrompt, "six[%s] ", ilow);
|
|
|
|
ERR_I(sendCmd(fd, "status"));
|
|
ERR_P(p=readWrite(fd,10000,0,"status = "));
|
|
|
|
} else {
|
|
sprintf(stdPrompt, "six[%s] ", host);
|
|
p="E";
|
|
}
|
|
|
|
iret=1;
|
|
buf[0]='\0';
|
|
pos=0;
|
|
|
|
term_read_hist("six");
|
|
savehist = 1;
|
|
|
|
while (1) {
|
|
if (*p=='E') { /* Eager to ... */
|
|
strcpy(prompt, stdPrompt);
|
|
} else if (*p>'1') {
|
|
sprintf(prompt, "%s(%s) ", stdPrompt, p);
|
|
}
|
|
FD_ZERO(&mask);
|
|
FD_SET(fd, &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")) break;
|
|
if (0==strcmp(lbuf,"exit")) break;
|
|
if (sicslogin) statusMatch="status = ";
|
|
skip=0;
|
|
printf("\n");
|
|
if (0==strcmp(lbuf,"stop")) {
|
|
strcpy(buf, "INT1712 3");
|
|
} else if (0==strcmp(buf, "-") ||
|
|
0==strcmp(buf, "--") ||
|
|
0==strcmp(buf, "+") ||
|
|
0==strcmp(buf, "++")) {
|
|
j=level;
|
|
if (buf[0]=='-') {
|
|
if (level<3) level++;
|
|
} else {
|
|
if (level>1) level--;
|
|
}
|
|
if (strlen(buf)==2) {
|
|
deflevel=level;
|
|
}
|
|
term_off();
|
|
ERR_I(i=setrights(level)); /* level might be changed */
|
|
if (i==1) return 0;
|
|
if (j!=level) {
|
|
printf("\rswitched to %s privilege\n", pnam[level]);
|
|
} else {
|
|
printf("\rremain at %s privilege\n", pnam[level]);
|
|
}
|
|
skip=1;
|
|
strcpy(buf, "status");
|
|
} else if (0==strcmp(buf, "help")) {
|
|
Usage(1);
|
|
strcpy(buf, "status");
|
|
} else if (0==strcmp(buf, "six help")) {
|
|
Usage(0);
|
|
strcpy(buf, "status");
|
|
} else if (0==strcmp(buf, "")) {
|
|
strcpy(buf, "status");
|
|
statusMatch=NULL;
|
|
}
|
|
ERR_I(sendCmd(fd, buf));
|
|
ERR_P(p=readWrite(fd,1000,skip,statusMatch));
|
|
buf[0]='\0';
|
|
pos=0;
|
|
} else if (iret<0) { /* ?? */
|
|
printf("\nwhat?\n"); exit(1);
|
|
} else { /* socket iret ready to read */
|
|
assert(fd==iret);
|
|
ERR_P(p=readWrite(fd,1000,0,"status = "));
|
|
if (strcmp(p, "0") == 0) {
|
|
term_clear();
|
|
printf("\nconnection lost");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
printf("\nexit %s\n", prompt);
|
|
term_save_hist(1); /* save history without last line */
|
|
return 0;
|
|
OnError:
|
|
if (savehist) term_save_hist(0); /* save history with last line */
|
|
ErrShow("end");
|
|
return 0;
|
|
}
|