added a nice java-free sics commandline client M.Z.
This commit is contained in:
214
tecs/six.c
Normal file
214
tecs/six.c
Normal file
@ -0,0 +1,214 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include "coc_util.h"
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "term.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int readWrite(int fd, int skip) {
|
||||
char msg[128];
|
||||
int l, i, go, iret, ires, n;
|
||||
|
||||
n=0;
|
||||
go=0;
|
||||
ires=0;
|
||||
iret=term_wait_fd(fd, skip?5000:1000);
|
||||
while (iret==1) {
|
||||
ERR_SI(l=recv(fd, msg, sizeof(msg)-1, 0));
|
||||
if (l==0) return(0);
|
||||
msg[l]='\0';
|
||||
if (skip==4) {
|
||||
ires=1;
|
||||
} else if (skip==3) {
|
||||
if (NULL!=strstr(msg, "Acknowledged")) ires=1;
|
||||
} else if (skip==1 || skip==2) {
|
||||
if (NULL!=strstr(msg, "SICS")) ires=1;
|
||||
}
|
||||
for (i=0; i<l-1; i++) {
|
||||
if (msg[i]==-1 && msg[i+1]==-7) { /* go ahead */
|
||||
go=1;
|
||||
msg[i]='<'; msg[i+1]='>';
|
||||
} else {
|
||||
go=0;
|
||||
}
|
||||
}
|
||||
if (skip<2 || skip==2 && ires==0) {
|
||||
fputs(msg, stdout);
|
||||
} else {
|
||||
n+=strlen(msg);
|
||||
}
|
||||
if (go) break;
|
||||
iret=term_wait_fd(fd, skip?5000:1000);
|
||||
}
|
||||
return ires*n;
|
||||
OnError: return -1;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
int iret, pos;
|
||||
fd_set mask;
|
||||
int fd, l, i, j, port, skip;
|
||||
char buf[128], lbuf[16], ibuf[64];
|
||||
char *rights, *instr, *sim="", *us, *ps;
|
||||
|
||||
struct sockaddr_in sadr;
|
||||
|
||||
port=1301;
|
||||
skip=2;
|
||||
j=0;
|
||||
for (i=1; i<argc; i++) {
|
||||
if (0==strcmp(argv[i], "-s")) {
|
||||
port=1303; sim="-sim";
|
||||
} else if (0==strcmp(argv[i], "-w")) {
|
||||
skip=1;
|
||||
} else {
|
||||
if (strlen(argv[i])>=32) {
|
||||
printf("argument too long\n");
|
||||
} else {
|
||||
if (j==0) {
|
||||
us=argv[i];
|
||||
j=1;
|
||||
} else if (j==1) {
|
||||
ps=argv[i];
|
||||
j=2;
|
||||
} else {
|
||||
printf("too many arguments\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j==1) {
|
||||
printf("missing password\n");
|
||||
return(0);
|
||||
}
|
||||
instr=getenv("Instrument");
|
||||
if (instr==NULL || instr[0]=='\0') {
|
||||
printf("Instrument is undefined\n");
|
||||
return(0);
|
||||
}
|
||||
ERR_I(CocCreateSockAdr(&sadr, "0", port));
|
||||
ERR_SI(fd=socket(AF_INET, SOCK_STREAM, 0));
|
||||
term_reg_socket(fd);
|
||||
ERR_SI(connect(fd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
||||
strcpy(buf, "sicslogin Spy 007\r\n");
|
||||
ERR_SI(send(fd, buf, strlen(buf), 0));
|
||||
ERR_I(i=readWrite(fd,skip));
|
||||
if (!i) {
|
||||
printf("rejected\n");
|
||||
return 0;
|
||||
}
|
||||
printf("reading welcome message ...\n");
|
||||
if (j==0) {
|
||||
rights=getenv("six_rights");
|
||||
if (rights!=NULL && 0==strcmp(rights, instr)) {
|
||||
us="lnsmanager";
|
||||
ps="lnsSICSlns";
|
||||
} else {
|
||||
sprintf(ibuf, "%suser", instr);
|
||||
str_lowcase(ibuf, ibuf);
|
||||
us=ibuf;
|
||||
ps="02lns1";
|
||||
}
|
||||
}
|
||||
sprintf(buf, "config Rights %s %s\r\n", us, ps);
|
||||
ERR_SI(send(fd, buf, strlen(buf), 0));
|
||||
ERR_I(i=readWrite(fd,3));
|
||||
if (!i) {
|
||||
us="Spy";
|
||||
}
|
||||
printf("logged in to SICS as %s on %s%s\n", us, instr, sim);
|
||||
if (*sim!='\0') {
|
||||
strcpy(buf, "sync\r\n");
|
||||
ERR_SI(send(fd, buf, strlen(buf), 0));
|
||||
ERR_I(i=readWrite(fd,4));
|
||||
printf("synchronized (%d chars read)\n", i);
|
||||
}
|
||||
iret=1;
|
||||
buf[0]='\0';
|
||||
pos=0;
|
||||
str_lowcase(instr,instr);
|
||||
sprintf(ibuf, "six[%s%s] ", instr, sim);
|
||||
while (1) {
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(fd, &mask);
|
||||
iret=term_get_line(buf, sizeof(buf)-2, &pos, ibuf, &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 (0==strcmp(lbuf,"stop")) {
|
||||
strcpy(buf, "INT1712 3");
|
||||
} else if (0==strcmp(buf, "")) {
|
||||
strcpy(buf, "status");
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
skip=0;
|
||||
if (0==strcmp(lbuf,"sync")) skip=4;
|
||||
l=strlen(buf);
|
||||
/*
|
||||
printf("sent> %s[%d chars]\n", buf, l);
|
||||
*/
|
||||
buf[l]=13;
|
||||
buf[l+1]=10;
|
||||
ERR_SI(send(fd, buf, l+2, 0));
|
||||
ERR_I(i=readWrite(fd,skip));
|
||||
if (skip==4) {
|
||||
printf("synchronize (%d chars read)\n", i);
|
||||
}
|
||||
buf[0]='\0';
|
||||
pos=0;
|
||||
} else if (iret<0) { /* ?? */
|
||||
printf("\nwhat?\n"); exit(1);
|
||||
} else { /* socket iret ready to read */
|
||||
assert(fd==iret);
|
||||
ERR_I(readWrite(fd,0));
|
||||
}
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
return(0);
|
||||
OnError:
|
||||
ErrShow("end");
|
||||
return(0);
|
||||
}
|
91
tecs/sys_select.c
Normal file
91
tecs/sys_select.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static int lastFd=-1;
|
||||
static struct termios atts;
|
||||
|
||||
void sys_keys_on(void) {
|
||||
int iret;
|
||||
|
||||
struct termios attr;
|
||||
iret=tcgetattr(STDIN_FILENO,&attr);
|
||||
atts=attr; /* save term. attr. */
|
||||
if (iret!=0) { perror("***\n");}
|
||||
attr.c_lflag &= ~(ICANON) & ~(ECHO); /* canonical mode off, echo off */
|
||||
attr.c_cc[VMIN]=0;
|
||||
attr.c_cc[VTIME]=1; /* 0.1 sec */
|
||||
iret= tcsetattr(STDIN_FILENO,TCSANOW,&attr);
|
||||
if (iret!=0) {perror("***\n");}
|
||||
}
|
||||
|
||||
void sys_keys_off(void) {
|
||||
int iret;
|
||||
|
||||
iret=tcsetattr(STDIN_FILENO,TCSANOW,&atts); /* restore term. attributes */
|
||||
if (iret!=0) {perror("***\n");};
|
||||
}
|
||||
|
||||
int sys_select_or_key(fd_set *mask, int msecTmo, char *key) {
|
||||
int chan, fd, iret, fd1, m, chr;
|
||||
struct timeval tmo, tmo0={0,0};
|
||||
fd_set rmask;
|
||||
static int init=1;
|
||||
|
||||
if (init) {
|
||||
sys_keys_on();
|
||||
init=0;
|
||||
}
|
||||
rmask=*mask;
|
||||
iret=select(FD_SETSIZE, &rmask, NULL, NULL, &tmo0);
|
||||
if (iret<0) {
|
||||
FD_ZERO(&rmask);
|
||||
perror("error in select");
|
||||
}
|
||||
fd1=STDIN_FILENO;
|
||||
chr=fgetc(stdin);
|
||||
if (chr==EOF && iret==0) {
|
||||
rmask=*mask;
|
||||
FD_SET(STDIN_FILENO, &rmask);
|
||||
if (msecTmo>=0) {
|
||||
if (msecTmo>100) { /* reduce 100 ms for the 1 tenth second in fgetc */
|
||||
msecTmo=msecTmo-100;
|
||||
} else {
|
||||
msecTmo=1;
|
||||
}
|
||||
tmo.tv_sec=msecTmo / 1000;
|
||||
tmo.tv_usec=(msecTmo%1000)*1000;
|
||||
iret=select(FD_SETSIZE, &rmask, NULL, NULL, &tmo);
|
||||
} else {
|
||||
iret=select(FD_SETSIZE, &rmask, NULL, NULL, NULL);
|
||||
}
|
||||
if (iret<0) {
|
||||
FD_ZERO(&rmask);
|
||||
perror("error in select");
|
||||
}
|
||||
if (FD_ISSET(STDIN_FILENO, &rmask)) {
|
||||
chr=fgetc(stdin);
|
||||
}
|
||||
FD_CLR(STDIN_FILENO, &rmask);
|
||||
}
|
||||
if (chr==EOF) {
|
||||
chr=0;
|
||||
fd1=-1;
|
||||
for (fd=1; fd<FD_SETSIZE; fd++) {
|
||||
if (FD_ISSET(fd, &rmask)) {
|
||||
if (fd1<0) {
|
||||
fd1=fd; /* first fd */
|
||||
} else if (fd>lastFd) {
|
||||
fd1=fd; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*mask=rmask;
|
||||
*key=chr;
|
||||
/*
|
||||
sys_keys_off();
|
||||
*/
|
||||
return(fd1);
|
||||
}
|
14
tecs/sys_select.h
Normal file
14
tecs/sys_select.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef SYS_SELECT_H_
|
||||
#define SYS_SELECT_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
int sys_select_or_key(fd_set *mask, int msecTmo, char *key);
|
||||
|
||||
/* wait for read event on sockets included in mask or from keyboard or a timeout
|
||||
result is negative for timeout,
|
||||
STDIN_FILENO for a key pressed,
|
||||
else socket number
|
||||
*/
|
||||
|
||||
#endif /* SYS_SELECT_H_ */
|
233
tecs/term.c
Normal file
233
tecs/term.c
Normal file
@ -0,0 +1,233 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "sys_select.h"
|
||||
|
||||
#define ESC_TMO 1000
|
||||
#define REF_TMO 100
|
||||
#define HISTORY_LINES 256
|
||||
|
||||
#define L_ARROW '\200'
|
||||
#define R_ARROW '\201'
|
||||
#define U_ARROW '\202'
|
||||
#define D_ARROW '\203'
|
||||
#define EVT_CHAR '\0'
|
||||
#define DEL_CHAR '\b'
|
||||
#define RET_CHAR '\n'
|
||||
|
||||
static char esc_key='\0';
|
||||
|
||||
static fd_set regMask;
|
||||
static int lastFd=-1;
|
||||
|
||||
void term_reg_socket(int fd) {
|
||||
FD_SET(fd, ®Mask);
|
||||
}
|
||||
|
||||
void term_unr_socket(int fd) {
|
||||
FD_CLR(fd, ®Mask);
|
||||
}
|
||||
|
||||
int term_raw_key(char *key, int msecTmo) {
|
||||
fd_set mask;
|
||||
|
||||
mask=regMask;
|
||||
return(sys_select_or_key(&mask, msecTmo, key));
|
||||
}
|
||||
|
||||
int term_wait_fd(int fd, int msecTmo) {
|
||||
fd_set mask;
|
||||
struct timeval tmo;
|
||||
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(fd, &mask);
|
||||
tmo.tv_sec=msecTmo / 1000;
|
||||
tmo.tv_usec=(msecTmo % 1000) * 1000+1;
|
||||
return(select(FD_SETSIZE, &mask, NULL, NULL, &tmo));
|
||||
}
|
||||
|
||||
int term_get_key(char *key, int msecTmo) {
|
||||
int iret;
|
||||
char k;
|
||||
|
||||
if (esc_key==0) {
|
||||
iret=term_raw_key(&k, msecTmo);
|
||||
} else {
|
||||
k=esc_key;
|
||||
}
|
||||
while (k==27) { /* esc */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
switch (k) {
|
||||
case 'O': k='\217'; break; /* ss3 */
|
||||
case '[': k='\233'; break; /* csi */
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
switch (k) {
|
||||
case '\233': /* csi */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
while (k>='0' && k <='9') {
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
}
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
switch (k) { /* L,R,U,D arrows */
|
||||
case 'D': k=L_ARROW; break;
|
||||
case 'C': k=R_ARROW; break;
|
||||
case 'A': k=U_ARROW; break;
|
||||
case 'B': k=D_ARROW; break;
|
||||
default: k='?';
|
||||
}
|
||||
break;
|
||||
case '\217': /* ss3 */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
if (k=='M') { /* enter */
|
||||
k=RET_CHAR;
|
||||
} else if (k >= 'l' && k <= 'y') {
|
||||
k=k-64;
|
||||
} else {
|
||||
k='?';
|
||||
}
|
||||
break;
|
||||
case '\177': /* del */
|
||||
case '\b': /* bs */
|
||||
k=DEL_CHAR;
|
||||
break;
|
||||
case '\r': /* cr */
|
||||
case '\n': /* lf */
|
||||
k=RET_CHAR;
|
||||
break;
|
||||
case EVT_CHAR: /* time out*/
|
||||
break;
|
||||
default:
|
||||
if (k<' ' || k>'\176') k='?';
|
||||
}
|
||||
*key=k;
|
||||
esc_key='\0';
|
||||
return (STDIN_FILENO);
|
||||
}
|
||||
|
||||
static char *history[HISTORY_LINES]={NULL};
|
||||
/* history array: it's a cyclic buffer, when it is full, the oldest values
|
||||
are overwritten.
|
||||
*/
|
||||
|
||||
static int hist_pos=0; /* position when scrolling through the history */
|
||||
static int hist_end=0; /* end of history. Always history[hist_end]==NULL */
|
||||
|
||||
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) {
|
||||
char key;
|
||||
int i,j,l,iret;
|
||||
char tmp[512];
|
||||
|
||||
buf[size-1]='\0'; /* make sure buf is null terminated */
|
||||
l=strlen(buf);
|
||||
if (*pos>l) {
|
||||
*pos=l;
|
||||
} else if (*pos<0) {
|
||||
*pos=0;
|
||||
}
|
||||
iret=term_get_key(&key, 0);
|
||||
while (1) {
|
||||
if (iret==-1 || key == RET_CHAR || key==EVT_CHAR) { /* refresh after a short timeout */
|
||||
assert(l*2+20+strlen(prompt)<sizeof(tmp));
|
||||
tmp[0]='\r';
|
||||
tmp[1]='\0';
|
||||
strcat(tmp, prompt);
|
||||
strcat(tmp, buf);
|
||||
strcat(tmp,"\033[K");
|
||||
j=strlen(tmp);
|
||||
for (i=l; i>*pos; i--) {
|
||||
tmp[j]='\b'; j++;
|
||||
}
|
||||
tmp[j]='\0';
|
||||
fputs(tmp, stdout);
|
||||
if (iret==-1) {
|
||||
iret=term_get_key(&key, -1); /* no timeout */
|
||||
}
|
||||
}
|
||||
switch (key) {
|
||||
case EVT_CHAR:
|
||||
fputs("\r\033[K", stdout);
|
||||
return(iret);
|
||||
|
||||
/* interrupted EXIT */
|
||||
|
||||
case RET_CHAR:
|
||||
/* fputs("\r\033[K", stdout); */
|
||||
i=hist_end-1; if (i<0) i=HISTORY_LINES-1;
|
||||
if ((history[i]==NULL || 0!=strcmp(history[i], buf)) && buf[0]!='\0') { /* do not save equal and empty lines */
|
||||
history[hist_end]=malloc(strlen(buf)+1);
|
||||
strncpy(history[hist_end], buf, size);
|
||||
hist_end++; if (hist_end>=HISTORY_LINES) hist_end=0;
|
||||
if (history[hist_end]!=NULL) free(history[hist_end]); /* clear line at end of history */
|
||||
history[hist_end]==NULL;
|
||||
}
|
||||
hist_pos=hist_end;
|
||||
return(STDIN_FILENO);
|
||||
|
||||
/* normal EXIT */
|
||||
|
||||
case DEL_CHAR:
|
||||
if (*pos>0) {
|
||||
for (i=*pos; buf[i]!='\0'; i++) {
|
||||
buf[i-1] = buf [i];
|
||||
}
|
||||
buf[i-1]='\0';
|
||||
(*pos)--;
|
||||
l--;
|
||||
}
|
||||
break;
|
||||
case L_ARROW:
|
||||
if (*pos>0) (*pos)--;
|
||||
break;
|
||||
case R_ARROW:
|
||||
if (buf[*pos]!='\0') (*pos)++;
|
||||
break;
|
||||
case U_ARROW:
|
||||
case D_ARROW:
|
||||
if (key==U_ARROW) {
|
||||
i=hist_pos-1; if (i<0) i=HISTORY_LINES-1;
|
||||
} else {
|
||||
i=hist_pos+1; if (i>=HISTORY_LINES) i=0;
|
||||
}
|
||||
if (history[i]!=NULL) {
|
||||
strncpy(buf, history[i], size-1);
|
||||
buf[size-1]='\0';
|
||||
hist_pos=i;
|
||||
l=strlen(buf);
|
||||
*pos=l;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (l<size-1) {
|
||||
for (i=l; i>*pos; i--) {
|
||||
buf[i]=buf[i-1];
|
||||
}
|
||||
(*pos)++; l++;
|
||||
buf[i]=key;
|
||||
buf[l]='\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
iret=term_get_key(&key, REF_TMO);
|
||||
}
|
||||
}
|
||||
|
19
tecs/term.h
Normal file
19
tecs/term.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef TERM_H_
|
||||
#define TERM_H_
|
||||
|
||||
void term_reg_socket(int fd);
|
||||
/* register socket */
|
||||
|
||||
void term_unr_socket(int fd);
|
||||
/* 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_get_key(char *key, int msecTmo);
|
||||
|
||||
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask);
|
||||
|
||||
#endif /* TERM_H_ */
|
Reference in New Issue
Block a user