#include #include #include #include #include #include #include #include #include "term.h" #include "coc_util.h" #include "myc_err.h" #include "myc_str.h" typedef enum { NORMAL, SPY, CLIENT } Mode; #define MAXMSG 256 static char *host; static char instr[32]; static int sock[2]; /* main socket and spy socket */ static int level=3; 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[3]={"| ", "* ", ""}; 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(" -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 only a miminal login (no check of instrument)\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(" six 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(" When SICS is busy, an asterisk '*' is shown at the left of the line.\n"); printf(" You may then enter more commands, but only under Spy privilege.\n"); printf(" All communication to and from SICS is prefixed with '|' or '*',\n"); printf(" messages from the six client have no prefix.\n"); printf("\n"); printf(" Markus Zolliker, Mar. 2005\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 tmo, int skip, char *find) { int lbuf, go, iret, n, shortTmo, l, socket; Mode idx; char *msg, *p, *q; char chr; static char result[MAXMSG]; int match; static int laststat=0, laststatlen=0; static int newline[2]={1,1}; /* * 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)); } if (idx) { msg1[pos1] = '\0'; pos1 = 0; msg = msg1; } else { msg0[pos0] = '\0'; pos0 = 0; msg = msg0; } /* printf("[%s]\n", msg); */ match=0; if (strncmp(msg, "TRANSACTIONSTART", 16) == 0) { busy[idx] = 1; match = 1; } else if (strncmp(msg, "TRANSACTIONFINISHED", 19) == 0) { busy[idx] = 0; if (skip != 2) go = 1; shortTmo = 1; match = 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; } match = 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"); } match=1; if (skip == 2) go = 1; } } if (hidecom && (skip || match)) { /* skip text */ n+=strlen(msg); } else { term_clear(); if (newline[idx]) { fputs(prefix[idx], stdout); newline[idx]=0; } if (strncmp(msg, "ERROR:", 6)==0) { fputs("\033[1;31m", stdout); /* red bold */ fputs(msg, stdout); fputs("\033[0m", stdout); /* clear colors */ } else { fputs(msg, stdout); } if (chr=='\n') { newline[idx]=1; fputs("\n", stdout); } } if (go) break; socket = term_wait_socket(0, shortTmo?100:tmo); shortTmo = 0; } fflush(stdout); if (iret==0) laststat=0; return result; OnError: return NULL; } void PrintCmd(char *buf, int mode) { fputs("\r", stdout); /* clear command line */ fputs(prefix[mode], stdout); fputs("\033[K\n", stdout); /* empty line */ fputs(prefix[mode], stdout); fputs("\033[1;34m", stdout); /* bold blue */ fputs(">> ", stdout); fputs(buf, stdout); fputs("\033[0m\n", stdout); /* clear colors */ } 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 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(sock[0], buf)); ERR_P(p=readWrite(12000,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(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=gotolevel; ERR_I(sendCmd(sock[0], "config list")); ERR_P(p=readWrite(12000,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 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' */ printf("rejected\n"); return 0; } return sock; OnError: return -1; } int main (int argc, char *argv[]) { int iret, pos; fd_set mask; int i, j, gotolevel, sicslogin; int savehist = 0; char buf[128], lbuf[16], ilow[64]; char stdPrompt[128], prompt[256]; char *sim=""; char *p; char *bar; char *pnam[4]={"0", "MANAGER", "user", "spy"}; printf("---------------------------------------------------\n"); printf("six, a fast SICS commandline client (doc: six help)\n"); printf("---------------------------------------------------\n"); port=2911; sicslogin=1; j=0; deflevel=0; gotolevel=0; host="0"; /* localhost by default */ sock[1]=0; /* do not yet connect 2nd connection */ for (i=1; 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(sock[0]=Connect()); if (sock[0] == 0) return 0; if (sicslogin) { ERR_I(sendCmd(sock[0], "Instrument")); ERR_P(p=readWrite(12000,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)); 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(sock[0], "status interest")); ERR_P(readWrite(12000,0,"OK")); ERR_I(sendCmd(sock[0], "status")); ERR_P(readWrite(12000,0,NULL)); } else { sprintf(stdPrompt, "six[%s] ", host); status[0]='E'; status[1]='\0'; } iret=1; buf[0]='\0'; pos=0; term_read_hist("six"); savehist = 1; while (1) { if (busy[0]) { bar = prefix[SPY]; } else { bar = ""; } 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; } if (0==strcmp(lbuf,"stop")) { PrintCmd(buf, CLIENT); ERR_SI(send(sock[1], "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); 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 (j!=level) { printf("\rswitched to %s privilege\n", pnam[level]); } else { printf("\rremain at %s privilege\n", pnam[level]); } buf[0]='\0'; } else if (0==strcmp(buf, "help six")) { PrintCmd(buf, CLIENT); Usage(1); buf[0]='\0'; } else if (0==strcmp(buf, "six help")) { PrintCmd(buf, CLIENT); Usage(0); buf[0]='\0'; } if (buf[0] != 0) { if (busy[0]) { if (!sock[1]) { ERR_I(sock[1] = Connect()); if (!sock[1]) { printf("spy connection rejected\n"); } } if (busy[1]) { /* print in red bold */ PrintCmd(buf, CLIENT); fputs("\033[1;31mBUSY (already 2 commands pending)\033[0m\n", stdout); 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)); } else { p=""; } buf[0]='\0'; pos=0; } else { /* something arrived from sockets */ assert(iret == sock[0] || iret == sock[1]); ERR_P(p=readWrite(500,0,NULL)); } 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; }