From c33fb15498cad6018dcc2b18052de0fa1e31f9a9 Mon Sep 17 00:00:00 2001 From: zolliker Date: Thu, 17 Mar 2005 16:08:08 +0000 Subject: [PATCH] - inserted possiblity to send spy commands when busy - general enhancements of six --- tecs/six.c | 390 ++++++++++++++++++++++++++++++++-------------------- tecs/term.c | 63 +++++---- tecs/term.h | 12 +- 3 files changed, 289 insertions(+), 176 deletions(-) diff --git a/tecs/six.c b/tecs/six.c index 8451749..574651b 100644 --- a/tecs/six.c +++ b/tecs/six.c @@ -11,50 +11,67 @@ #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 fd; +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(" -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(" 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(" 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(" 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(" 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(" 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"); } @@ -92,19 +109,23 @@ int CocCreateSockAdr( 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]; +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; + static int laststat=0, laststatlen=0; + static int newline[2]={1,1}; /* - * read from fd and write to stdout until a key pressed, - * a timeout occurred (tmo [msec]), or a message - * received. + * 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 @@ -114,84 +135,123 @@ char* readWrite(int fd, int tmo, int skip, char *find) { */ n=0; go=0; - ga=0; + shortTmo = 0; str_copy(result, ""); - iret=term_wait_fd(fd, tmo); - while (iret>0) { - pos=0; - ERR_SI(lbuf=recv(fd, &chr, 1, 0)); + 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<' ') { - 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; - } + if (chr == '\n') break; + if (idx) { + if (chr != '\r' && pos1 < MAXMSG-1) { /* cut lines longer than MAXMSG */ + msg1[pos1]=chr; + pos1++; } } else { - msg[pos++]=chr; + if (chr != '\r' && pos0 < MAXMSG-1) { /* cut lines longer than MAXMSG */ + msg0[pos0]=chr; + pos0++; + } } - iret=term_wait_fd(fd, tmo); - if (iret!=1) break; - ERR_SI(lbuf=recv(fd, &chr, 1, 0)); + 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; } - msg[pos]='\0'; /* printf("[%s]\n", msg); */ match=0; - if (find != NULL) { + 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)); - p=strchr(result,'\r'); - if (p != NULL) *p='\0'; + q=strchr(result,'\r'); + if (q != NULL) *q='\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 == 2) go = 1; } } - if (skip || match) { /* skip text */ + 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); + fputs("\033[1;31m", stdout); /* red bold */ fputs(msg, stdout); - fputs("\033[0m", stdout); + fputs("\033[0m", stdout); /* clear colors */ } else { fputs(msg, stdout); } - if (chr=='\n') fputs("\n", stdout); + if (chr=='\n') { + newline[idx]=1; + fputs("\n", stdout); + } } if (go) break; - iret=term_wait_fd(fd, tmo); + socket = term_wait_socket(0, shortTmo?100:tmo); + shortTmo = 0; } + fflush(stdout); if (iret==0) laststat=0; return result; OnError: return NULL; } -int sendCmd(int fd, char *cmd) { +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]; - ERR_I(str_copy(buf, cmd)); - ERR_I(str_append(buf, "\r\n")); - ERR_SI(l=send(fd, buf, strlen(buf), 0)); + + snprintf(buf, sizeof buf, "fulltransact %s\n", cmd); + ERR_SI(l=send(socket, buf, strlen(buf), 0)); return l; OnError: return -1; } @@ -287,8 +347,8 @@ int setrights(int gotolevel) { 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")); + ERR_I(sendCmd(sock[0], buf)); + ERR_P(p=readWrite(12000,0,"Acknowledged")); if (*p=='\0') { if (0==strcmp(us, user1)) { user1[0]='\0'; @@ -321,9 +381,9 @@ int setrights(int gotolevel) { 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') { + 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'; @@ -334,7 +394,7 @@ int setrights(int gotolevel) { pswd2[0]='\0'; } pw=NULL; - } else { + } else { /* success */ if (0==strcmp(user, user1)) { str_copy(pswd1, pswd); } @@ -349,8 +409,8 @@ int setrights(int gotolevel) { } } level=gotolevel; - ERR_I(sendCmd(fd, "config list")); - ERR_P(p=readWrite(fd,10000,1,"UserRights = ")); + ERR_I(sendCmd(sock[0], "config list")); + ERR_P(p=readWrite(12000,1,"UserRights = ")); if (*p!='\0') { level=*p-'0'; } @@ -391,36 +451,54 @@ int setrights(int gotolevel) { 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, port, skip, gotolevel, sicslogin; + int i, j, gotolevel, sicslogin; int savehist = 0; char buf[128], lbuf[16], ilow[64]; char stdPrompt[128], prompt[256]; char *sim=""; - char *p, *statusMatch=NULL; + char *p; + char *bar; 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; + 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'1') { - sprintf(prompt, "%s(%s) ", stdPrompt, p); + 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(fd, &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")) break; - if (0==strcmp(lbuf,"exit")) break; - if (sicslogin) statusMatch="status = "; - skip=0; - printf("\n"); + if (0==strcmp(lbuf,"quit") || 0==strcmp(lbuf,"exit")) { + PrintCmd(buf, CLIENT); + break; + } if (0==strcmp(lbuf,"stop")) { - strcpy(buf, "INT1712 3"); + 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++; @@ -557,38 +632,61 @@ int main (int argc, char *argv[]) { } 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")) { + buf[0]='\0'; + } else if (0==strcmp(buf, "help six")) { + PrintCmd(buf, CLIENT); Usage(1); - strcpy(buf, "status"); + buf[0]='\0'; } else if (0==strcmp(buf, "six help")) { + PrintCmd(buf, CLIENT); Usage(0); - strcpy(buf, "status"); - } else if (0==strcmp(buf, "")) { - strcpy(buf, "status"); - statusMatch=NULL; + 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=""; } - 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; - } + } 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); diff --git a/tecs/term.c b/tecs/term.c index 228744a..a3e8564 100644 --- a/tecs/term.c +++ b/tecs/term.c @@ -25,13 +25,20 @@ static char esc_key='\0'; static fd_set regMask; +static int minReg=0, maxReg=0; -void term_reg_socket(int fd) { - FD_SET(fd, ®Mask); +void term_reg_socket(int socket) { + FD_SET(socket, ®Mask); + if (socket > maxReg) { + if (maxReg == 0) minReg = socket; + maxReg = socket; + } else if (socket < minReg) { + minReg = socket; + } } -void term_unr_socket(int fd) { - FD_CLR(fd, ®Mask); +void term_unr_socket(int socket) { + FD_CLR(socket, ®Mask); } int term_raw_key(char *key, int msecTmo) { @@ -41,21 +48,37 @@ int term_raw_key(char *key, int msecTmo) { return(sys_select_or_key(&mask, msecTmo, key)); } -int term_wait_fd(int fd, int msecTmo) { +int term_wait_socket(int socket, int msecTmo) { fd_set mask; struct timeval tmo; int i; - FD_ZERO(&mask); - FD_SET(fd, &mask); + if (socket == 0) { + mask = regMask; + } else { + FD_ZERO(&mask); + FD_SET(socket, &mask); + } FD_SET(STDIN_FILENO, &mask); tmo.tv_sec=msecTmo / 1000; - tmo.tv_usec=(msecTmo % 1000) * 1000+1; + tmo.tv_usec=(msecTmo % 1000) * 1000; i=select(FD_SETSIZE, &mask, NULL, NULL, &tmo); if (FD_ISSET(STDIN_FILENO, &mask)) { return 0; } - return i; + if (i<0) return i; + if (i) { + if (socket && FD_ISSET(socket, &mask)) { + return socket; + } + for (i=minReg; i<=maxReg; i++) { + if (FD_ISSET(i, &mask)) { + return i; + }; + } + return -1; + } + return 0; } int term_get_key(char *key, int msecTmo) { @@ -250,7 +273,7 @@ static int dirty=0; /* line is to be cleared through a call of term_clear */ void term_clear(void) { if (dirty) { - fputs("\r\033[K\033[0m", stdout); + fputs("\r\033[K\033[0m", stdout); /* clear to end of line, clear colors */ dirty=0; } } @@ -281,19 +304,10 @@ int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) { while (1) { if (iret==-1 || key == RET_CHAR || key==EVT_CHAR) { /* refresh after a short timeout */ snprintf(tmp, sizeof tmp, "%s%s%s%s%s%.*s", - "\r\033[1m", prompt, "\033[34m", buf, "\033[K\033[0m", l - *pos, back); -/* - assert(l*2+20+strlen(prompt)*pos; i--) { - tmp[j]='\b'; j++; - } - tmp[j]='\0'; -*/ + "\r\033[1m", /* bold */ + prompt, "\033[34m", /* blue */ + buf, "\033[K\033[0m", /* clear to end of line, clear colors */ + l - *pos, back); fputs(tmp, stdout); if (iret==-1) { iret=term_get_key(&key, -1); /* no timeout */ @@ -322,9 +336,6 @@ int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) { } hist_pos=hist_end; term_save_hist(0); - printf("\r\033[K\n\033[1;34m"); - printf("%s", buf); - printf("\033[0m"); return(STDIN_FILENO); /* normal EXIT */ diff --git a/tecs/term.h b/tecs/term.h index 97aaf0c..5d74610 100644 --- a/tecs/term.h +++ b/tecs/term.h @@ -3,16 +3,20 @@ #include -void term_reg_socket(int fd); +void term_reg_socket(int socket); /* register socket */ -void term_unr_socket(int fd); +void term_unr_socket(int socket); /* unregister socket */ int term_raw_key(char *key, int msecTmo); -int term_wait_fd(int fd, int msecTmo); -/* wait for a read event on fd or timeout */ +int term_wait_socket(int socket, int msecTmo); +/* wait for a read event on socket or timeout + special case socket=0: wait for a read event on any socket + return socket number + or 0 for timeout +*/ int term_get_key(char *key, int msecTmo);