add most files
This commit is contained in:
320
instr_hosts.c
Normal file
320
instr_hosts.c
Normal file
@ -0,0 +1,320 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "instr_hosts.h"
|
||||
|
||||
static char *service;
|
||||
static char *crit;
|
||||
static char *input;
|
||||
static int foundcount;
|
||||
static int home;
|
||||
static char hostport[128];
|
||||
static char *instr;
|
||||
static int instr_len;
|
||||
static char *host;
|
||||
static int host_len;
|
||||
static int port;
|
||||
static char remoteinstrument[128];
|
||||
static char hostname[128];
|
||||
static char remotehostbuf[128];
|
||||
static char *remotehost;
|
||||
|
||||
static char *getItem(char *line, char *name, char *value, int value_len) {
|
||||
/* get the named item for line, or check if the name/value pair is present
|
||||
* the found value is returned, if found
|
||||
* if value_len != 0, the result is copied to value
|
||||
* if value is not empty, it must be matched
|
||||
*/
|
||||
char find[64];
|
||||
char *found, *p, *sp, *result;
|
||||
int l;
|
||||
|
||||
if (value == NULL)
|
||||
value="(NULL)";
|
||||
p = strchr(value, '.');
|
||||
if (p) {
|
||||
l = p - value;
|
||||
} else {
|
||||
l = strlen(value);
|
||||
}
|
||||
snprintf(find, sizeof find, "%s=%.*s", name, l, value);
|
||||
for (p = find; *p; p++) *p = tolower(*p);
|
||||
found = strstr(line, find);
|
||||
if (found && *value != '\0' && found[strlen(find)] > ' ' && found[strlen(find)] != '.') {
|
||||
/* when value is given, it must be complete, (a dot or a space terminates the value) */
|
||||
found = NULL;
|
||||
}
|
||||
if (found) {
|
||||
found += strlen(name)+1;
|
||||
if (value_len == 0) {
|
||||
result = found;
|
||||
} else {
|
||||
sp = strchr(found, ' ');
|
||||
if (sp && sp < found + value_len) {
|
||||
l = sp - found;
|
||||
} else {
|
||||
l = strlen(found);
|
||||
}
|
||||
if (l < value_len) {
|
||||
strncpy(value, found, l);
|
||||
value[l] = '\0';
|
||||
result = value;
|
||||
} else {
|
||||
value[0] = '\0';
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (value_len > 0) {
|
||||
*value = '\0';
|
||||
}
|
||||
result = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void scanHostList(void (*func)(char *)) {
|
||||
int i;
|
||||
FILE *fil, *lfil;
|
||||
char *hostlist;
|
||||
char localhostlist[512];
|
||||
char line[512], lline[512];
|
||||
int dirty;
|
||||
|
||||
hostlist = getenv("InstrumentHostList");
|
||||
if (!hostlist) {
|
||||
hostlist="/afs/psi.ch/project/sinq/common/lib/sea/hostlist";
|
||||
}
|
||||
fil = fopen(hostlist, "r");
|
||||
snprintf(localhostlist, sizeof localhostlist, "%s/.six/hostlist", getenv("HOME"));
|
||||
lfil = fopen(localhostlist, "r");
|
||||
dirty = 0;
|
||||
if (fil) {
|
||||
if (!lfil) dirty = 1;
|
||||
} else {
|
||||
if (!lfil) return;
|
||||
fil = lfil;
|
||||
lfil = NULL;
|
||||
}
|
||||
while (NULL != fgets(line, sizeof line, fil)) {
|
||||
if (!dirty && lfil
|
||||
&& (fgets(lline, sizeof lline, lfil) == NULL
|
||||
|| strcmp(line, lline) != 0)) {
|
||||
dirty = 1;
|
||||
}
|
||||
if (line[0] != '#' && line[0] != 0) {
|
||||
i = strlen(line) - 1;
|
||||
if (line[i] == '\n') line[i] = 0;
|
||||
func(line);
|
||||
}
|
||||
}
|
||||
if (fil) fclose(fil);
|
||||
if (lfil) fclose(lfil);
|
||||
if (dirty) {
|
||||
fil = fopen(hostlist, "r");
|
||||
if (fil) {
|
||||
lfil = fopen(localhostlist, "w");
|
||||
if (lfil) {
|
||||
while( EOF != (i = getc(fil)) ) { /* copy file to local file */
|
||||
putc(i, lfil);
|
||||
}
|
||||
fclose(lfil);
|
||||
}
|
||||
fclose(fil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *GetHostName(void) {
|
||||
char *pend;
|
||||
|
||||
if (!hostname[0]) {
|
||||
gethostname(hostname, sizeof hostname);
|
||||
hostname[sizeof hostname - 1] = 0;
|
||||
pend = strchr(hostname, '.');
|
||||
if (pend)
|
||||
*pend = 0;
|
||||
}
|
||||
return hostname;
|
||||
}
|
||||
|
||||
char *InstrHostRemoteName(void) {
|
||||
struct hostent *res;
|
||||
struct in_addr inadr;
|
||||
char *pend;
|
||||
|
||||
if (remotehost == NULL) {
|
||||
remotehost = getenv("REMOTEHOST");
|
||||
if (!remotehost) {
|
||||
remotehost = getenv("SSH_CLIENT");
|
||||
if (remotehost) {
|
||||
snprintf(remotehostbuf, sizeof remotehostbuf, "%s", remotehost);
|
||||
pend = strchr(remotehostbuf, ' ');
|
||||
if (pend)
|
||||
*pend = 0;
|
||||
remotehost = remotehostbuf;
|
||||
}
|
||||
}
|
||||
if (!remotehost) {
|
||||
remotehost = GetHostName();
|
||||
}
|
||||
if (!remotehost) {
|
||||
remotehost = "";
|
||||
} else {
|
||||
if (inet_aton(remotehost, &inadr)) {
|
||||
if ((res = gethostbyaddr(&inadr, sizeof inadr, AF_INET))) {
|
||||
remotehost = res->h_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (remotehost != remotehostbuf) {
|
||||
snprintf(remotehostbuf, sizeof remotehostbuf, "%s", remotehost);
|
||||
remotehost = remotehostbuf;
|
||||
}
|
||||
pend = strchr(remotehostbuf, '.');
|
||||
if (pend) {
|
||||
if (strcmp(pend, ".psi.ch") == 0) {
|
||||
*pend = 0;
|
||||
} else {
|
||||
strcpy(remotehostbuf, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
return remotehost;
|
||||
}
|
||||
|
||||
static void findCrit(char *line) {
|
||||
char *colon;
|
||||
int i;
|
||||
char *h;
|
||||
|
||||
if (getItem(line, crit, input, 0) != NULL) {
|
||||
hostport[0]='\0';
|
||||
if (getItem(line, service, hostport, sizeof hostport) != NULL) {
|
||||
instr[0] = '\0';
|
||||
if (foundcount == 0) {
|
||||
getItem(line, "instr", instr, instr_len);
|
||||
}
|
||||
colon = strchr(hostport, ':');
|
||||
if (colon) {
|
||||
i = atoi(colon+1);
|
||||
if (i > 0) {
|
||||
*colon='\0';
|
||||
if (foundcount == 0) {
|
||||
snprintf(host, host_len, "%s", hostport);
|
||||
port = i;
|
||||
}
|
||||
foundcount++;
|
||||
GetHostName();
|
||||
if (getItem(line, "host", hostname, sizeof hostname)) {
|
||||
home = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
h = getItem(line, "host", remotehost, 0);
|
||||
if (h) {
|
||||
if (remoteinstrument[0]) {
|
||||
/* more than one entry: no real instrument */
|
||||
strcpy(remoteinstrument, "-");
|
||||
} else {
|
||||
getItem(line, "instr", remoteinstrument, sizeof remoteinstrument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int InstrHost(char *serviceArg, char *inputArg, char *instrArg, int instr_lenArg,
|
||||
char *hostArg, int host_lenArg, int *portArg) {
|
||||
service = serviceArg;
|
||||
input = inputArg;
|
||||
instr = instrArg;
|
||||
instr_len = instr_lenArg;
|
||||
host = hostArg;
|
||||
host_len = host_lenArg;
|
||||
port = 0;
|
||||
home = 0;
|
||||
foundcount = 0;
|
||||
remoteinstrument[0] = 0;
|
||||
|
||||
if (input == NULL || input[0] <= ' ') {
|
||||
crit = "host";
|
||||
input = GetHostName();
|
||||
} else {
|
||||
crit = "instr";
|
||||
}
|
||||
InstrHostRemoteName();
|
||||
scanHostList(findCrit);
|
||||
if (strcmp(remoteinstrument, "-") == 0) {
|
||||
remoteinstrument[0] = 0;
|
||||
}
|
||||
*portArg = port;
|
||||
return home * foundcount;
|
||||
}
|
||||
|
||||
char *InstrHostRemoteInstr(void) {
|
||||
return strdup(remoteinstrument);
|
||||
}
|
||||
|
||||
char *InstrHostName(void) {
|
||||
return strdup(hostname);
|
||||
}
|
||||
|
||||
static char *list;
|
||||
static int list_len;
|
||||
|
||||
static void listInstr(char *line) {
|
||||
int l;
|
||||
*list='\0';
|
||||
if (getItem(line, service, "", 0) &&
|
||||
getItem(line, "instr", list, list_len)) {
|
||||
l = strlen(list);
|
||||
list += l;
|
||||
list_len -= l;
|
||||
} else if (line[0] > ' ') {
|
||||
return;
|
||||
}
|
||||
if (list_len > 0) {
|
||||
*list = ' ';
|
||||
list++;
|
||||
list_len--;
|
||||
}
|
||||
}
|
||||
|
||||
void InstrList(char *serviceArg, char *listArg, int list_lenArg) {
|
||||
service = serviceArg;
|
||||
list = listArg;
|
||||
list_len = list_lenArg;
|
||||
scanHostList(listInstr);
|
||||
if (list > listArg) list--; /* remove trailing blank */
|
||||
*list = '\0';
|
||||
}
|
||||
|
||||
#ifdef MYC_FORTRAN
|
||||
/* compile only when fortran c interface stuff is defined */
|
||||
|
||||
#include "myc_fortran.h"
|
||||
|
||||
int F_FUN(instr_host)(F_CHAR(service), F_CHAR(input), F_CHAR(instr), F_CHAR(host), int *port
|
||||
, int service_len, int input_len, int instr_len, int host_len) {
|
||||
char buf[256], in[256], ho[256], sv[256];
|
||||
int iRet;
|
||||
|
||||
STR_TO_C(sv, service);
|
||||
STR_TO_C(buf, input);
|
||||
iRet=InstrHost(sv, buf, in, sizeof(in), ho, sizeof(ho), port);
|
||||
if (*port>0) {
|
||||
STR_TO_F(instr, in);
|
||||
STR_TO_F(host, ho);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
|
||||
#endif
|
35
instr_hosts.h
Normal file
35
instr_hosts.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef _INSTR_HOSTS_H_
|
||||
#define _INSTR_HOSTS_H_
|
||||
|
||||
int InstrHost(char *service, char *input, char *instr, int instr_len,
|
||||
char *host, int host_len, int *port);
|
||||
/* service (in) is a service name (tecs, sics, sea)
|
||||
input (in) may be a host or instrument name
|
||||
instr (out) is the instrument name
|
||||
host (out) is the host name
|
||||
port (out) is the port name
|
||||
the return value is 1, called from a computer related to the instrument,
|
||||
0 else
|
||||
*/
|
||||
|
||||
void InstrList(char *service, char *list, int list_len);
|
||||
/* get an instrument list supporting named service, separated with blanks */
|
||||
|
||||
char *InstrHostRemoteName(void);
|
||||
/*
|
||||
returns the remote host name (or the host name, if not valid)
|
||||
*/
|
||||
|
||||
char *InstrHostRemoteInstr(void);
|
||||
/*
|
||||
called after InstrHost, get the instrument running on remotehost
|
||||
or an empty string otherwise. the result is allocated, please free
|
||||
*/
|
||||
|
||||
char *InstrHostName(void);
|
||||
/*
|
||||
called after InstrHost, get the full host name where sea was started.
|
||||
the result is allocated, please free
|
||||
*/
|
||||
|
||||
#endif /* _INSTR_HOSTS_H_ */
|
31
make_gen
Normal file
31
make_gen
Normal file
@ -0,0 +1,31 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile (sytem independent part) for the TECS Client library and TecsServer
|
||||
# included in a machine-specific makefile
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .c .f
|
||||
|
||||
CC = gcc
|
||||
|
||||
SRC = term sys_select instr_hosts uselect myc_err myc_str
|
||||
SYSSRC = $(addprefix $(linuxsys)/,$(SRC))
|
||||
OBJ = $(addsuffix .o,$(SYSSRC))
|
||||
DFIL = $(addsuffix .d,$(SYSSRC))
|
||||
|
||||
all: $(linuxsys)/six
|
||||
|
||||
six: $(linuxsys)/six
|
||||
|
||||
-include $(DFIL)
|
||||
|
||||
$(linuxsys)/six: six.c $(OBJ)
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
$(linuxsys)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -f $(linuxsys)/*.o $(linuxsys)/*.a $(linuxsys)/*.d $(linuxsys)/six
|
4
makefile
Normal file
4
makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# when linuxsys is defined: use this makefile version
|
||||
# if not: show usage (see makefile_)
|
||||
|
||||
include makefile_$(linuxsys)
|
25
makefile_
Normal file
25
makefile_
Normal file
@ -0,0 +1,25 @@
|
||||
# M. Zolliker 03.2005
|
||||
# this file shows the correct usage of make in the sics source directory
|
||||
|
||||
%: usage
|
||||
@echo
|
||||
|
||||
%.o: usage
|
||||
@echo
|
||||
|
||||
default: usage
|
||||
|
||||
usage:
|
||||
@ echo ""
|
||||
@ echo "Usage:"
|
||||
@ echo ""
|
||||
@ echo " make -f makefile_xxx [target]"
|
||||
@ echo ""
|
||||
@ echo ' where makefile_xxx is one of'
|
||||
@ echo ""
|
||||
@ ls -1 makefile_?* | pr -t -o 4
|
||||
@ echo ""
|
||||
@ echo " or use make without args:"
|
||||
@ echo ""
|
||||
@ echo " setenv SICS_MAKE_VERSION slinux"
|
||||
@ echo " make [target]"
|
40
makefile_rhel7
Normal file
40
makefile_rhel7
Normal file
@ -0,0 +1,40 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# machine-dependent part
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
include sllinux_def
|
||||
|
||||
SICS=..
|
||||
|
||||
CC = gcc
|
||||
FC = g77
|
||||
CFLAGS = -DLINUX -g $(DFORTIFY) -I../.. -I.. -I. -Wall -Wno-missing-braces \
|
||||
-Wno-unused-but-set-variable
|
||||
FFLAGS = -Wimplicit -g
|
||||
ARFLAGS = cr
|
||||
|
||||
# -- system dependent routines
|
||||
|
||||
# -- PGPLOT library additions
|
||||
PGLIB = -L/usr/X11R6/lib -lX11
|
||||
|
||||
# -- library for ASYNSRV
|
||||
HARDSUPLIB=../hardsup/libhlib.a
|
||||
|
||||
# -- readline library
|
||||
RDLIB =-lreadline -ltermcap
|
||||
|
||||
# -- the following macros are used as a replacement for some automatic variables
|
||||
# due to different make versions.
|
||||
# This is for GNU make.
|
||||
#
|
||||
# list of prerequisites including paths for VPATH
|
||||
Q=$^
|
||||
|
||||
# Fortran/C source file name
|
||||
F=$<
|
||||
C=$<
|
||||
|
||||
include make_gen
|
136
myc_err.c
Normal file
136
myc_err.c
Normal file
@ -0,0 +1,136 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "myc_str.h"
|
||||
#include "myc_err.h"
|
||||
|
||||
#define SLEN 64
|
||||
#define MLEN 64
|
||||
|
||||
static char *txt[SLEN];
|
||||
static int sp=0;
|
||||
static int stack_empty=1;
|
||||
|
||||
int ErrCode;
|
||||
char *ErrMessage=NULL;
|
||||
void (*outrtn)(void *, char *)=NULL;
|
||||
void *outarg;
|
||||
|
||||
void ErrTxt(char *text, int systemError)
|
||||
{
|
||||
if (systemError) {
|
||||
stack_empty = 0;
|
||||
sp=0; ErrCode=errno; ErrMessage=strerror(errno);
|
||||
}
|
||||
if (stack_empty && sp>0) {
|
||||
sp=0;
|
||||
stack_empty=0;
|
||||
}
|
||||
if (sp<SLEN) {
|
||||
txt[sp++]=text;
|
||||
}
|
||||
}
|
||||
|
||||
void ErrMsg(char *msg)
|
||||
{
|
||||
ErrCode=-1;
|
||||
ErrMessage=msg; sp=0;
|
||||
}
|
||||
|
||||
void ErrCod(int code)
|
||||
{
|
||||
ErrCode=code;
|
||||
ErrMessage=strerror(code); sp=0;
|
||||
}
|
||||
|
||||
void ErrOutFil(void *arg, char *text) {
|
||||
fprintf((FILE *)arg, "%s\n", text);
|
||||
}
|
||||
|
||||
void ErrShow(char *text)
|
||||
{
|
||||
int i, l;
|
||||
char buf[256];
|
||||
|
||||
if (outrtn==NULL) {
|
||||
outrtn=ErrOutFil;
|
||||
outarg=stdout;
|
||||
}
|
||||
l=strlen(text)+strlen(ErrMessage)+6;
|
||||
assert(l<256);
|
||||
sprintf(buf, "--- %s: %s", text, ErrMessage);
|
||||
for (i=0;i<sp;i++) {
|
||||
if (txt[i][0]==':') {
|
||||
l+=strlen(txt[i]);
|
||||
assert(l<256);
|
||||
strcat(buf, &(txt[i][1]));
|
||||
} else {
|
||||
outrtn(outarg, buf);
|
||||
l=strlen(txt[i]);
|
||||
assert(l<256);
|
||||
strcpy(buf, txt[i]);
|
||||
}
|
||||
}
|
||||
outrtn(outarg, buf);
|
||||
outrtn(outarg, "");
|
||||
stack_empty=1;
|
||||
}
|
||||
|
||||
void ErrShort(char *msg) {
|
||||
if (outrtn==NULL) {
|
||||
outrtn=ErrOutFil;
|
||||
outarg=stdout;
|
||||
}
|
||||
outrtn(outarg, msg);
|
||||
}
|
||||
|
||||
void ErrSetOutRtn(void (*rtn)(void *, char *), void *arg) {
|
||||
outrtn=rtn;
|
||||
outarg=arg;
|
||||
}
|
||||
|
||||
void ErrSetOutFile(FILE *arg) {
|
||||
outrtn=ErrOutFil;
|
||||
outarg=arg;
|
||||
}
|
||||
|
||||
void ERR_EXIT(char *text) {
|
||||
ErrShow(text); exit(1);
|
||||
}
|
||||
|
||||
/* FORTRAN wrappers */
|
||||
|
||||
#ifdef F_CHAR
|
||||
/* compile only when fortran c interface stuff is defined */
|
||||
|
||||
void F_FUN(err_show)(F_CHAR(text), int text_len) {
|
||||
char buf[256];
|
||||
|
||||
STR_TO_C(buf, text);
|
||||
ErrShow(buf);
|
||||
}
|
||||
|
||||
void F_FUN(err_txt)(F_CHAR(text), int text_len) {
|
||||
char buf[256];
|
||||
|
||||
STR_TO_C(buf, text);
|
||||
ErrTxt(buf,0);
|
||||
}
|
||||
|
||||
void F_FUN(err_msg)(F_CHAR(text), int text_len) {
|
||||
static char buf[256];
|
||||
|
||||
STR_TO_C(buf, text);
|
||||
ErrMsg(buf);
|
||||
}
|
||||
|
||||
void F_FUN(err_set_outrtn)(void (*rtn)(void *, char*), void *arg) {
|
||||
ErrSetOutRtn(rtn, arg);
|
||||
}
|
||||
|
||||
void F_FUN(err_short)(void) {
|
||||
ErrShort(ErrMessage);
|
||||
}
|
||||
|
||||
#endif
|
85
myc_err.h
Normal file
85
myc_err.h
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef _ERR_HANDLING_H_
|
||||
#define _ERR_HANDLING_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
/* ErrHDL Error handling utilities
|
||||
-------------------------------
|
||||
Makes code more readable by hiding annoying error condition checks.
|
||||
|
||||
Macros and routines:
|
||||
|
||||
Spelling in uppercase indicates, that it the program flow
|
||||
may be modified (jump to OnError label or program exit).
|
||||
|
||||
|
||||
ERR_x
|
||||
|
||||
Usage Error condition Error message taken from
|
||||
-----------------------------------------------------------------------------------------
|
||||
ERR_SI(res=routine1(...)) res<0 errno
|
||||
ERR_SP(ptr=routine2(...)) ptr==NULL errno
|
||||
ERR_I(res=routine3(...)) res<0 stored by routine3 using errhdl mechanism
|
||||
ERR_P(ptr=routine4(...)) ptr==NULL stored by routine4 using errhdl mechanism
|
||||
|
||||
The result assignment "res=" or "ptr=" is optional.
|
||||
|
||||
Description:
|
||||
The routine routineX is called.
|
||||
If the result indicates an error, the source text is saved and the
|
||||
program continues at the OnError label.
|
||||
The error message and the source code of the calling instructions is
|
||||
saved for a later call to ErrShow or ErrExit.
|
||||
|
||||
ERR_EXIT("program_name")
|
||||
|
||||
Show error and exit program.
|
||||
|
||||
ERR_MSG("message")
|
||||
|
||||
Signals an error condition. If "message" is replaced by a variable,
|
||||
take care that it is not modified until ErrShow is called.
|
||||
|
||||
ERR_COD(cod)
|
||||
|
||||
Signals an error condition as code from errno.h
|
||||
|
||||
ErrShow("program_name")
|
||||
|
||||
Show actual error message with traceback information to stdout
|
||||
or a file fil
|
||||
|
||||
Global Variables (read only)
|
||||
|
||||
int ErrCode
|
||||
|
||||
actual error message code
|
||||
= errno for system errors or
|
||||
= -1 for custom errors signaled by ERRMSG
|
||||
|
||||
char *ErrMessage
|
||||
|
||||
actual error message
|
||||
*/
|
||||
|
||||
#define ERR_SI(R) { if(0>(R)) { ErrTxt(#R,1); goto OnError; }; }
|
||||
#define ERR_SP(R) { if(NULL==(R)) { ErrTxt(#R,1); goto OnError; }; }
|
||||
#define ERR_I(R) { if(0>(R)) { ErrTxt(#R,0); goto OnError; }; }
|
||||
#define ERR_P(R) { if(NULL==(R)) { ErrTxt(#R,0); goto OnError; }; }
|
||||
#define ERR_MSG(R) { ErrMsg(R); goto OnError; }
|
||||
#define ERR_COD(R) { ErrCod(R); goto OnError; }
|
||||
|
||||
void ErrTxt(char *text, int systemError);
|
||||
void ErrMsg(char *msg);
|
||||
void ErrCod(int code);
|
||||
void ErrShow(char *text); /* write out error message with stack info */
|
||||
void ErrShort(char *msg); /* write out short error message */
|
||||
void ERR_EXIT(char *text);
|
||||
void ErrSetOutRtn(void (*rtn)(void *,char *), void *arg);
|
||||
void ErrSetOutFile(FILE *file);
|
||||
|
||||
extern int ErrCode;
|
||||
extern char *ErrMessage;
|
||||
|
||||
#endif /* _ERR_HANDLING_H_ */
|
30
myc_mem.h
Normal file
30
myc_mem.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef _MEM_UTIL_H_
|
||||
#define _MEM_UTIL_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FORTIFY
|
||||
#include "fortify.h"
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
these macros help for safer dynamic memory
|
||||
you may change these macros if you want to log dynamic memory access
|
||||
|
||||
*/
|
||||
|
||||
#define NEW(PTR,TYP) {TYP _0_={0}; ERR_SP(PTR=malloc(sizeof(*PTR))); *PTR=_0_; }
|
||||
/*
|
||||
allocates and initializes an object of type TYP and make PTR point to it
|
||||
TYP must be defined with an appropriate typedef declaration, and
|
||||
INIT(TYP) must follow the declaration to initialize a dummy initializer
|
||||
object.
|
||||
*/
|
||||
|
||||
#define NEW_STR(TO,FROM) {ERR_SP(TO=malloc(strlen(FROM)+1)); strcpy(TO,FROM); }
|
||||
|
||||
#define MALLOC(SIZE) malloc(SIZE)
|
||||
#define FREE(PTR) { free(PTR); PTR=NULL; }
|
||||
|
||||
#endif /* _MEM_UTIL_H_ */
|
252
myc_str.c
Normal file
252
myc_str.c
Normal file
@ -0,0 +1,252 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_mem.h"
|
||||
|
||||
char *str_splitx(char *str, char sep, char *list[], int *n) {
|
||||
int i;
|
||||
char *s, *e;
|
||||
|
||||
s=str;
|
||||
for (i=0; i<*n; i++) {
|
||||
list[i]=s;
|
||||
e=strchr(s, sep);
|
||||
if (e==NULL) { *n=i+1; return(NULL); }
|
||||
s=e+1;
|
||||
e--;
|
||||
while (e>str && *e==' ') e--; /* trim sequence */
|
||||
e[1]='\0';
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
char *str_split1(char *str, char sep) {
|
||||
char *s, *e;
|
||||
|
||||
e=strchr(str, sep);
|
||||
if (e==NULL) {
|
||||
s=NULL;
|
||||
e=str+strlen(str);
|
||||
} else {
|
||||
s=e+1;
|
||||
}
|
||||
e--;
|
||||
while (e>str && *e==' ') e--; /* trim sequence */
|
||||
e[1]='\0';
|
||||
return(s);
|
||||
}
|
||||
|
||||
int str_ntrim(char *dest, const char *src, int ldest, int lsrc) {
|
||||
int i;
|
||||
|
||||
if (lsrc>=ldest) lsrc=ldest-1;
|
||||
if (dest!=src) strncpy(dest, src, lsrc);
|
||||
dest[lsrc]='\0';
|
||||
i=strlen(dest)-1;
|
||||
while (i>=0 && dest[i]==' ') i--; /* trim sequence */
|
||||
i++;
|
||||
dest[i]='\0';
|
||||
return(i);
|
||||
}
|
||||
|
||||
int str_npad(char *dest, const char *src, int ldest) {
|
||||
int i, lsrc;
|
||||
|
||||
lsrc=strlen(src);
|
||||
if (lsrc>=ldest) {
|
||||
if (dest!=src) strncpy(dest, src, ldest);
|
||||
lsrc=ldest;
|
||||
} else {
|
||||
if (dest!=src) strcpy(dest, src);
|
||||
for (i=lsrc; i<ldest; i++) {
|
||||
dest[i]=' ';
|
||||
}
|
||||
}
|
||||
return(lsrc);
|
||||
}
|
||||
|
||||
char *str_nsplit(char *dst, const char *src, char sep, int dstlen) {
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
s=strchr(src, sep);
|
||||
if (s==NULL) {
|
||||
s=NULL;
|
||||
i=strlen(src);
|
||||
} else {
|
||||
i=s-src;
|
||||
s++; /* skip separator */
|
||||
}
|
||||
if (i>=dstlen) {
|
||||
str_copy(dst, src);
|
||||
} else {
|
||||
strncpy(dst, src, i);
|
||||
dst[i]='\0';
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
char *str_read_until(FILE *fil, char *term, char *buf, char *end) {
|
||||
char fmt[24];
|
||||
int i, l, siz;
|
||||
char ch;
|
||||
|
||||
siz=end-buf-1;
|
||||
if (siz<1) return(NULL);
|
||||
sprintf(fmt, "%s%d[^%s%s", "%", siz, term, "]%n%c");
|
||||
i=fscanf(fil, fmt, buf, &l, &ch);
|
||||
if (i<0) { /* eof */
|
||||
buf[0]='\0';
|
||||
return(&buf[0]);
|
||||
} else if (i==0) { /* fscanf returns 0 if first char is terminator */
|
||||
buf[0]=fgetc(fil);
|
||||
return(&buf[0]);
|
||||
} else if (i==1) { /* terminator not found -> read until eof */
|
||||
buf[l]='\0';
|
||||
return(&buf[l]);
|
||||
} else {
|
||||
buf[l]=ch;
|
||||
if (l==siz && NULL==strchr(term, ch)) return(NULL);
|
||||
return(&buf[l]);
|
||||
}
|
||||
}
|
||||
|
||||
char *str_read_file(char *file) {
|
||||
FILE *fil;
|
||||
char *str, *s, *e, *p, *q;
|
||||
int i, size;
|
||||
struct stat statbuf;
|
||||
|
||||
i=stat(file, &statbuf);
|
||||
if (i<0) ERR_MSG("file not found");
|
||||
size=statbuf.st_size+4;
|
||||
ERR_SP(str=MALLOC(size));
|
||||
e=&str[size-1];
|
||||
ERR_SP(fil=fopen(file, "r"));
|
||||
s=str;
|
||||
while (1) {
|
||||
p=str_read_until(fil, "!", s, e);
|
||||
if (p==NULL) break;
|
||||
if (*p=='!') {
|
||||
q=str_read_until(fil, "\n", p, e);
|
||||
if (q==NULL) { p=NULL; break; }
|
||||
s=p; *s='\n'; s++;
|
||||
} else {
|
||||
assert(*p=='\0');
|
||||
break;
|
||||
}
|
||||
}
|
||||
ERR_SI(fclose(fil));
|
||||
assert(strlen(str)<size);
|
||||
return(str);
|
||||
OnError: return(NULL);
|
||||
}
|
||||
|
||||
void str_replace_char(char *str, char ch, char rep) {
|
||||
char *s;
|
||||
|
||||
assert(ch!='\0' && ch!=rep);
|
||||
s=strchr(str, ch);
|
||||
while (s!=NULL) {
|
||||
*s=rep;
|
||||
s=strchr(s, ch);
|
||||
}
|
||||
}
|
||||
|
||||
int str_nsubstitute(char *result, char *str, char *old, char *new, int reslen) {
|
||||
char *s, *p, *r;
|
||||
int l, ln, lo;
|
||||
|
||||
p=str;
|
||||
r=result;
|
||||
ln=strlen(new);
|
||||
lo=strlen(old);
|
||||
s=strstr(p, old);
|
||||
reslen--;
|
||||
if (reslen<0) ERR_MSG("result buffer too short");
|
||||
while (s!=NULL) {
|
||||
l=s-p;
|
||||
if (l>reslen) ERR_MSG("result buffer too short");
|
||||
strncpy(r, p, l);
|
||||
r+=l; reslen-=l;
|
||||
if (ln>reslen) ERR_MSG("result buffer too short");
|
||||
strncpy(r, new, reslen);
|
||||
r+=ln; reslen-=ln;
|
||||
p=s+lo;
|
||||
s=strstr(p, old);
|
||||
}
|
||||
l=strlen(p);
|
||||
if (l>reslen) ERR_MSG("result buffer too short");
|
||||
strncpy(r, p, l);
|
||||
r+=l;
|
||||
*r='\0';
|
||||
return(r-result);
|
||||
OnError:
|
||||
result[0]='\0';
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void str_nupcase(char *dst, const char *src, int dstlen) {
|
||||
dstlen--; /* space for trailing nul */
|
||||
while (*src!='\0' && dstlen>0) {
|
||||
*dst=toupper((int)*src);
|
||||
dst++; src++;
|
||||
dstlen--;
|
||||
}
|
||||
*dst='\0';
|
||||
}
|
||||
|
||||
void str_nlowcase(char *dst, const char *src, int dstlen) {
|
||||
dstlen--; /* space for trailing nul */
|
||||
while (*src!='\0' && dstlen>0) {
|
||||
*dst=tolower((int)*src);
|
||||
dst++; src++;
|
||||
dstlen--;
|
||||
}
|
||||
*dst='\0';
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
int strcasecmp(const char *str1, const char *str2) {
|
||||
int i;
|
||||
char ch1, ch2;
|
||||
ch1=tolower(*(str1++)); ch2=tolower(*(str2++));
|
||||
i=1;
|
||||
while (ch1!='\0' && ch2!='\0' && ch1==ch2) {
|
||||
ch1=tolower(*(str1++)); ch2=tolower(*(str2++)); i++;
|
||||
}
|
||||
if (ch1<ch2) {
|
||||
return(-i);
|
||||
} else if (ch1>ch2) {
|
||||
return(i);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int str_ncpy(char *dst, const char *src, int maxdest) {
|
||||
strncpy(dst, src, maxdest);
|
||||
if (dst[maxdest-1]!='\0') {
|
||||
dst[maxdest-1]='\0';
|
||||
ERR_MSG("destination string too short");
|
||||
}
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int str_ncat(char *dst, const char *src, int maxdest) {
|
||||
dst[maxdest-1]='\0';
|
||||
strncat(dst, src, maxdest-strlen(dst)-1);
|
||||
if (dst[maxdest-1]!='\0') {
|
||||
dst[maxdest-1]='\0';
|
||||
ERR_MSG("destination string too short");
|
||||
}
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
122
myc_str.h
Normal file
122
myc_str.h
Normal file
@ -0,0 +1,122 @@
|
||||
#ifndef _MYC_STR_H_
|
||||
#define _MYC_STR_H_
|
||||
|
||||
#define MYC_NAN (-1.125/1024./1024./1024.)
|
||||
|
||||
/*
|
||||
use these macros if DST is a fixed length character array
|
||||
*/
|
||||
|
||||
#define str_trim(DST,SRC,L) str_ntrim(DST,SRC,sizeof(DST),L)
|
||||
#define str_pad(DST,SRC) str_npad(DST,SRC,sizeof(DST))
|
||||
#define str_split(DST,SRC,SEP) str_nsplit(DST,SRC,SEP,sizeof(DST))
|
||||
#define str_substitute(DST,SRC,OLD,NEW) str_nsubstitute(DST,SRC,OLD,NEW,sizeof(DST))
|
||||
#define str_upcase(DST,SRC) str_nupcase(DST,SRC,sizeof(DST))
|
||||
#define str_lowcase(DST,SRC) str_nlowcase(DST,SRC,sizeof(DST))
|
||||
#define str_copy(DST,SRC) str_ncpy(DST,SRC,sizeof(DST))
|
||||
#define str_append(DST,SRC) str_ncat(DST,SRC,sizeof(DST))
|
||||
|
||||
|
||||
char *str_split1(char *str, char separator);
|
||||
/*
|
||||
trims text before separator in *str and returns
|
||||
a pointer to the first character after separator
|
||||
*/
|
||||
|
||||
char *str_splitx(char *str, char sep, char *list[], int *n);
|
||||
/*
|
||||
split string into *n strings using separator sep.
|
||||
spaces at the end of the elements are trimmed
|
||||
attention: *str is modified ('\0' placed at the end of the elements)
|
||||
|
||||
if *n separators are found, result points to string after *n-th separator
|
||||
else result is NULL
|
||||
*n contains number of elements stored in list
|
||||
*/
|
||||
|
||||
int str_ntrim(char *dest, const char *src, int ldest, int lsrc);
|
||||
/*
|
||||
copy characters 0 to lsrc-1 from src to dest (max ldest chars).
|
||||
*/
|
||||
|
||||
int str_npad(char *dest, const char *src, int ldest);
|
||||
/*
|
||||
copy src to dest and fill with spaces (fortran string format)
|
||||
*/
|
||||
|
||||
char *str_nsplit(char *dst, const char *src, char sep, int dstlen);
|
||||
/*
|
||||
returns a pointer to the text after the separator sep in *src
|
||||
and copies the text before the separator to *dst
|
||||
when *src does not contain the separator sep
|
||||
NULL is returned, and *dst is a copy of *src
|
||||
*/
|
||||
|
||||
char *str_read_file(char *file);
|
||||
/*
|
||||
return one string containing the contents of file *file
|
||||
comments separated by '!' are omitted. The caller must
|
||||
free the result after use.
|
||||
*/
|
||||
|
||||
void str_replace_char(char *str, char ch, char rep);
|
||||
/*
|
||||
replace all occurences of character ch by character rep in string *str
|
||||
*/
|
||||
|
||||
int str_nsubstitute(char *result, char *str, char *old, char *new, int reslen);
|
||||
/*
|
||||
replace every instance of old in str by new.
|
||||
the result must not overlap
|
||||
if the result would be longer than reslen, the result is en empty string
|
||||
and the return value is -1;
|
||||
else the return value is the length of the result.
|
||||
return one string containing the contents of file *file
|
||||
the contents are treated in the following way:
|
||||
- #0,#1,...#n is replaced by the corresponding argument *args[n] (n=0..nargs-1, nargs<10)
|
||||
- at the end of each line spaces and comments separated by ! are trimmed
|
||||
*/
|
||||
|
||||
void str_nupcase(char *dst, const char *src, int dstlen);
|
||||
/*
|
||||
convert *str to uppercase
|
||||
*/
|
||||
|
||||
void str_nlowcase(char *dst, const char *src, int dstlen);
|
||||
/*
|
||||
convert *str to lowercase
|
||||
*/
|
||||
|
||||
#ifdef __VMS_VER
|
||||
#if __VMS_VER<70000000
|
||||
|
||||
int strcasecmp(const char *str1, const char *str2);
|
||||
/*
|
||||
compare *str1 with *str2
|
||||
the comparison is not case sensitive
|
||||
if result=0: strings are equal
|
||||
else
|
||||
result>0 <==> *str1>*str2
|
||||
first different character is at position abs(result)-1
|
||||
*/
|
||||
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif /* __VMS_VER<70000000 */
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif /* __VMS_VER */
|
||||
|
||||
int str_ncpy(char *dst, const char *src, int maxdest);
|
||||
/*
|
||||
copy *src to *dest, maximal maxdest characters,
|
||||
it is guaranteed, that dst contains '\0'
|
||||
*/
|
||||
|
||||
int str_ncat(char *dst, const char *src, int maxdest);
|
||||
/*
|
||||
append *src to *dest, maximal maxdest characters,
|
||||
it is guaranteed, that dst contains '\0'
|
||||
*/
|
||||
|
||||
#endif /* _MYC_STR_H_ */
|
4
publish
Executable file
4
publish
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/tcsh
|
||||
cp -f $linuxsys/six $sys/stow/sea/bin/six
|
||||
|
||||
|
945
six.c
Normal file
945
six.c
Normal file
@ -0,0 +1,945 @@
|
||||
/* 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;
|
||||
}
|
106
sys_select.c
Normal file
106
sys_select.c
Normal file
@ -0,0 +1,106 @@
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include "uselect.h"
|
||||
|
||||
static int lastFd=-1;
|
||||
static struct termios atts;
|
||||
static int echo=1;
|
||||
|
||||
void sys_keys_on(void) {
|
||||
int iret;
|
||||
|
||||
struct termios attr;
|
||||
if (echo) {
|
||||
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");}
|
||||
echo=0;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_keys_off(void) {
|
||||
int iret;
|
||||
|
||||
if (!echo) {
|
||||
iret=tcsetattr(STDIN_FILENO,TCSANOW,&atts); /* restore term. attributes */
|
||||
if (iret!=0) {perror("***\n");};
|
||||
echo=1;
|
||||
}
|
||||
}
|
||||
|
||||
static int getChar(void) {
|
||||
unsigned char c;
|
||||
int rt;
|
||||
|
||||
rt = read(STDIN_FILENO, &c, 1);
|
||||
if (rt<=0) {
|
||||
return EOF;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
int sys_select_or_key(fd_set *mask, int msecTmo, int *key) {
|
||||
int fd, iret, fd1, chr;
|
||||
struct timeval tmo, tmo0={0,0};
|
||||
fd_set rmask;
|
||||
|
||||
sys_keys_on();
|
||||
rmask=*mask;
|
||||
iret=uselect(FD_SETSIZE, &rmask, NULL, NULL, &tmo0);
|
||||
if (iret<0) {
|
||||
FD_ZERO(&rmask);
|
||||
perror("error in select");
|
||||
}
|
||||
fd1=STDIN_FILENO;
|
||||
/* chr=fgetc(stdin); */
|
||||
chr = getChar();
|
||||
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=uselect(FD_SETSIZE, &rmask, NULL, NULL, &tmo);
|
||||
} else {
|
||||
iret=uselect(FD_SETSIZE, &rmask, NULL, NULL, NULL);
|
||||
}
|
||||
if (iret<0) {
|
||||
FD_ZERO(&rmask);
|
||||
perror("error in select");
|
||||
}
|
||||
if (FD_ISSET(STDIN_FILENO, &rmask)) {
|
||||
chr = getChar();
|
||||
/* 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;
|
||||
return(fd1);
|
||||
}
|
20
sys_select.h
Normal file
20
sys_select.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef SYS_SELECT_H_
|
||||
#define SYS_SELECT_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
int sys_select_or_key(fd_set *mask, int msecTmo, int *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
|
||||
switches the terminal to no-echo no-canonical
|
||||
*/
|
||||
|
||||
void sys_keys_off(void);
|
||||
/*
|
||||
switch back terminal to normal state
|
||||
*/
|
||||
|
||||
#endif /* SYS_SELECT_H_ */
|
552
term.c
Normal file
552
term.c
Normal file
@ -0,0 +1,552 @@
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "term.h"
|
||||
#include "myc_mem.h"
|
||||
#include "myc_str.h"
|
||||
#include "sys_select.h"
|
||||
#include "uselect.h"
|
||||
|
||||
#define ESC_TMO 1000
|
||||
#define REF_TMO 50
|
||||
#define HISTORY_LINES 256
|
||||
|
||||
#define L_ARROW 0200
|
||||
#define R_ARROW 0201
|
||||
#define U_ARROW 0202
|
||||
#define D_ARROW 0203
|
||||
#define EVT_CHAR '\0'
|
||||
#define DEL_CHAR '\b'
|
||||
#define RET_CHAR '\n'
|
||||
|
||||
static char esc_key='\0';
|
||||
|
||||
static fd_set regMask;
|
||||
static int minReg=0, maxReg=0;
|
||||
static char filehead[256]="";
|
||||
|
||||
static char *func[256]={NULL};
|
||||
|
||||
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 socket) {
|
||||
FD_CLR(socket, ®Mask);
|
||||
}
|
||||
|
||||
int term_raw_key(int *key, int msecTmo) {
|
||||
fd_set mask;
|
||||
|
||||
mask=regMask;
|
||||
return(sys_select_or_key(&mask, msecTmo, key));
|
||||
}
|
||||
|
||||
int term_wait_socket(int socket, int msecTmo) {
|
||||
fd_set mask;
|
||||
struct timeval tmo;
|
||||
int i;
|
||||
|
||||
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;
|
||||
i=uselect(FD_SETSIZE, &mask, NULL, NULL, &tmo);
|
||||
if (FD_ISSET(STDIN_FILENO, &mask)) {
|
||||
return 0;
|
||||
}
|
||||
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(int *key, int msecTmo) {
|
||||
int iret;
|
||||
int k;
|
||||
int kode;
|
||||
|
||||
fflush(stdout);
|
||||
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=0217; break; /* ss3 */
|
||||
case '[': k=0233; break; /* csi */
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
switch (k) {
|
||||
case 0233: /* csi */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
kode=0;
|
||||
while (k>='0' && k <='9') {
|
||||
kode=kode*10+(k-'0');
|
||||
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:
|
||||
if (k=='~') {
|
||||
k = 128 + kode;
|
||||
} else {
|
||||
k += 128;
|
||||
}
|
||||
if (k>255) k='?';
|
||||
}
|
||||
break;
|
||||
case 0217: /* 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 {
|
||||
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 += 128; if (k>255) k='?';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0177: /* del */
|
||||
case '\b': /* bs */
|
||||
k=DEL_CHAR;
|
||||
break;
|
||||
case '\r': /* cr */
|
||||
case '\n': /* lf */
|
||||
k=RET_CHAR;
|
||||
break;
|
||||
case 4: /* ctrl-D, end of file */
|
||||
break;
|
||||
case EVT_CHAR: /* time out*/
|
||||
break;
|
||||
default:
|
||||
if (k>0176) {
|
||||
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 */
|
||||
|
||||
FILE *term_open_pref(int temp, char *head, char *mode) {
|
||||
char buf[PATH_MAX+1], old[PATH_MAX+1], wd[PATH_MAX];
|
||||
char *usr, *home, *p;
|
||||
int l;
|
||||
FILE *fil;
|
||||
mode_t oldmask;
|
||||
|
||||
usr = getenv("USER");
|
||||
if (temp && usr==NULL) return NULL;
|
||||
if (usr != NULL && *usr != '\0' && strstr(usr, "lnsg") != 0) {
|
||||
if (! getcwd(wd, sizeof wd)) return NULL;
|
||||
home=getenv("HOME");
|
||||
if (!home) return NULL;
|
||||
realpath(home, buf);
|
||||
l = strlen(buf);
|
||||
buf[l] = '/'; l++;
|
||||
buf[l]= '\0';
|
||||
if (wd[l] != '\0' && strncmp(wd, buf, l) == 0) { /* wd starts with $HOME */
|
||||
p = strchr(wd+l, '/');
|
||||
if (p) *p='\0'; /* determine 1st subdirectory of $HOME */
|
||||
if (temp) {
|
||||
str_append(wd, "_lnsg");
|
||||
usr = wd+l;
|
||||
} else {
|
||||
home = wd;
|
||||
}
|
||||
} else {
|
||||
home = buf;
|
||||
}
|
||||
} else {
|
||||
home=getenv("HOME");
|
||||
if (!home) return NULL;
|
||||
}
|
||||
if (temp) {
|
||||
/* old file name */
|
||||
str_copy(old, "/tmp/");
|
||||
str_append(old, head);
|
||||
str_append(old, ".");
|
||||
str_append(old, usr);
|
||||
/* new file name */
|
||||
str_copy(buf, "/tmp/six/");
|
||||
oldmask = umask(0);
|
||||
mkdir(buf, S_IRWXU+S_IRWXG+S_IRWXO);
|
||||
umask(oldmask);
|
||||
str_append(buf, head);
|
||||
str_append(buf, ".");
|
||||
str_append(buf, usr); /* usr is the username, or lnsg_<subdirectory> */
|
||||
} else {
|
||||
/* old file name */
|
||||
str_copy(old, home);
|
||||
str_append(old, "/.");
|
||||
str_append(old, head);
|
||||
/* new file name */
|
||||
str_copy(buf, home);
|
||||
str_append(buf, "/.six/");
|
||||
mkdir(buf, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH);
|
||||
str_append(buf, head);
|
||||
}
|
||||
rename(old, buf); /* if old file exists, rename it to new */
|
||||
if (*mode == 'd') {
|
||||
unlink(buf);
|
||||
return NULL;
|
||||
} else {
|
||||
fil = fopen(buf, mode);
|
||||
return fil;
|
||||
}
|
||||
}
|
||||
|
||||
char *term_fgets(char *buf, int size, FILE *fil) {
|
||||
char *p, *ret;
|
||||
char skipbuf[256];
|
||||
|
||||
buf[0]='\0';
|
||||
ret=fgets(buf, size, fil);
|
||||
if (ret==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p=strchr(buf,'\n');
|
||||
if (p==NULL) {
|
||||
while (p==NULL) { /* skip rest of line */
|
||||
ret=fgets(skipbuf, sizeof(skipbuf), fil);
|
||||
if (ret==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p=strchr(skipbuf,'\n');
|
||||
}
|
||||
} else {
|
||||
*p='\0';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void term_save_hist(int trimlast) {
|
||||
FILE *fil;
|
||||
int i,n;
|
||||
if (filehead[0]=='\0') return;
|
||||
fil=term_open_pref(1, filehead, "w");
|
||||
if (fil==NULL) return;
|
||||
n=HISTORY_LINES-1;
|
||||
if (trimlast) {
|
||||
n--;
|
||||
}
|
||||
i=hist_end;
|
||||
while (n>0) {
|
||||
n--;
|
||||
i++; if (i>=HISTORY_LINES) i=0;
|
||||
if (history[i]!=NULL) {
|
||||
fputs(history[i], fil); fputs("\n", fil);
|
||||
}
|
||||
}
|
||||
fclose(fil);
|
||||
}
|
||||
|
||||
void term_read_hist(char *id, char *instr) {
|
||||
FILE *fil;
|
||||
int i;
|
||||
char buf[1024], *lin;
|
||||
|
||||
str_copy(filehead, id);
|
||||
str_append(filehead, "_hist_");
|
||||
str_append(filehead, instr);
|
||||
fil=term_open_pref(1, filehead, "r");
|
||||
if (fil==NULL) return;
|
||||
hist_end=0;
|
||||
while (hist_end<HISTORY_LINES-1 && !feof(fil)) {
|
||||
term_fgets(buf, sizeof(buf), fil);
|
||||
i=strlen(buf);
|
||||
if (i>0) {
|
||||
lin=MALLOC(i+1);
|
||||
strncpy(lin, buf, i+1);
|
||||
history[hist_end]=lin;
|
||||
hist_end++;
|
||||
}
|
||||
}
|
||||
fclose(fil);
|
||||
history[hist_end]=NULL;
|
||||
hist_pos=hist_end;
|
||||
}
|
||||
|
||||
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); /* clear to end of line, clear colors */
|
||||
dirty=0;
|
||||
}
|
||||
}
|
||||
|
||||
void term_off(void) {
|
||||
dirty=1;
|
||||
term_clear();
|
||||
sys_keys_off();
|
||||
}
|
||||
|
||||
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) {
|
||||
char *lin;
|
||||
int key;
|
||||
int i,l,iret,buflen;
|
||||
char tmp[1024];
|
||||
static char back[512]="";
|
||||
|
||||
if (back[0] == '\0') {
|
||||
memset(back, '\b', sizeof back);
|
||||
}
|
||||
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 */
|
||||
snprintf(tmp, sizeof tmp, "%s%s%s%s%s%.*s",
|
||||
"\r\033[0m\033[1m", /* no color, 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 */
|
||||
}
|
||||
}
|
||||
switch (key) {
|
||||
case EVT_CHAR:
|
||||
/* caller must clear line before next write with term_clear() */
|
||||
dirty=1;
|
||||
return(iret);
|
||||
|
||||
/* interrupted EXIT */
|
||||
|
||||
case RET_CHAR:
|
||||
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 */
|
||||
buflen=strlen(buf)+1;
|
||||
lin=MALLOC(buflen);
|
||||
strncpy(lin, buf, buflen);
|
||||
history[hist_end]=lin;
|
||||
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;
|
||||
term_save_hist(0);
|
||||
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);
|
||||
} else {
|
||||
buf[0]='\0';
|
||||
l=0;
|
||||
if (history[hist_pos]!=NULL) {
|
||||
hist_pos=i;
|
||||
}
|
||||
}
|
||||
*pos=l;
|
||||
break;
|
||||
case 1: /* ctrl-A: jump to begin of line */
|
||||
*pos = 0;
|
||||
break;
|
||||
case 5: /* ctrl-E: jump to end of line */
|
||||
*pos = strlen(buf);
|
||||
break;
|
||||
case 4: /* ctrl-D: abort */
|
||||
return -2;
|
||||
default:
|
||||
if (key <' ' || key > 0176) { /* untreated special key */
|
||||
if (func[key] != NULL) {
|
||||
snprintf(buf, size, "%s", func[key]);
|
||||
key = RET_CHAR;
|
||||
continue;
|
||||
}
|
||||
key = '?';
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void term_define_key(char *cmd, int keyArg) {
|
||||
int iret;
|
||||
int key;
|
||||
|
||||
if (keyArg) {
|
||||
key = keyArg;
|
||||
} else {
|
||||
if (*cmd) {
|
||||
printf("\n# press key for command '%s' or return", cmd);
|
||||
} else {
|
||||
printf("\n# press key for which to remove command");
|
||||
}
|
||||
iret = term_get_key(&key, 5000);
|
||||
}
|
||||
switch (key) {
|
||||
case EVT_CHAR:
|
||||
case DEL_CHAR:
|
||||
case L_ARROW:
|
||||
case R_ARROW:
|
||||
case U_ARROW:
|
||||
case D_ARROW:
|
||||
break;
|
||||
case RET_CHAR:
|
||||
printf("\n# canceled\n");
|
||||
default:
|
||||
if (key <' ' || key > 0176) { /* special key */
|
||||
if (*cmd) {
|
||||
if (func[key]) free(func[key]);
|
||||
func[key] = strdup(cmd);
|
||||
if (!keyArg) {
|
||||
printf("\n# programmed key %d\n", key);
|
||||
}
|
||||
} else {
|
||||
if (func[key]) {
|
||||
if (!keyArg) {
|
||||
printf("\n# removed command '%s' from key %d\n", func[key], key);
|
||||
}
|
||||
free(func[key]);
|
||||
} else {
|
||||
if (!keyArg) {
|
||||
printf("\n# no command on key %d\n", key);
|
||||
}
|
||||
}
|
||||
func[key] = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("\n# key %d is not programmable\n", key);
|
||||
}
|
||||
|
||||
void term_save_keys(FILE *fil, void (*out)(char *)) {
|
||||
int key;
|
||||
char buf[128];
|
||||
|
||||
for (key=0; key<256; key++) {
|
||||
if (func[key]) {
|
||||
fprintf(fil, "%d %s\n", key, func[key]);
|
||||
if (out) {
|
||||
snprintf(buf, sizeof buf, " key %d defined as '%s'\n", key, func[key]);
|
||||
out(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void term_load_keys(FILE *fil, void (*out)(char *)) {
|
||||
char line[136], buf[128];
|
||||
int key, l;
|
||||
|
||||
while (term_fgets(line, sizeof line, fil)) {
|
||||
key = 0;
|
||||
sscanf(line, "%d %n", &key, &l);
|
||||
if (key != 0) {
|
||||
term_define_key(line+l, key);
|
||||
if (out) {
|
||||
snprintf(buf, sizeof buf, " key %d defined as '%s'\n", key, line+l);
|
||||
out(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
term.h
Normal file
49
term.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef TERM_H_
|
||||
#define TERM_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void term_reg_socket(int socket);
|
||||
/* register socket */
|
||||
|
||||
void term_unr_socket(int socket);
|
||||
/* unregister socket */
|
||||
|
||||
int term_raw_key(int *key, int msecTmo);
|
||||
|
||||
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(int *key, int msecTmo);
|
||||
|
||||
void term_clear(void);
|
||||
|
||||
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask);
|
||||
|
||||
FILE *term_open_pref(int temp, char *head, char *mode);
|
||||
/* open a user specific preferences or temporary file */
|
||||
|
||||
char *term_fgets(char *buf, int size, FILE *fil);
|
||||
/* fgets without newline */
|
||||
|
||||
void term_read_hist(char *id, char *instr);
|
||||
/* read history from temporary file with id */
|
||||
|
||||
void term_save_hist(int trimlast);
|
||||
/* store history (without last line if trimlast) */
|
||||
|
||||
void term_off(void);
|
||||
|
||||
void term_define_key(char *cmd, int keyArg);
|
||||
|
||||
void term_save_keys(FILE *fil, void (*out)(char *));
|
||||
/* save keys on file */
|
||||
|
||||
void term_load_keys(FILE *fil, void (*out)(char *));
|
||||
/* load keys on file */
|
||||
|
||||
#endif /* TERM_H_ */
|
24
uselect.c
Normal file
24
uselect.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include "uselect.h"
|
||||
|
||||
/* an uninterruptable version of select. M.Z. Oct 2008 */
|
||||
|
||||
int uselect(int nfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
struct timeval *timeout) {
|
||||
|
||||
sigset_t sigmask;
|
||||
struct timespec tmo, *tmoPtr;
|
||||
|
||||
sigfillset(&sigmask);
|
||||
if (timeout) {
|
||||
tmo.tv_sec = timeout->tv_sec;
|
||||
tmo.tv_nsec = timeout->tv_usec * 1000;
|
||||
tmoPtr = &tmo;
|
||||
} else {
|
||||
tmoPtr = NULL;
|
||||
}
|
||||
return pselect(nfds, readfds, writefds, exceptfds, tmoPtr, &sigmask);
|
||||
}
|
Reference in New Issue
Block a user