add most files

This commit is contained in:
2025-06-10 12:11:08 +02:00
parent 36217e809e
commit fceffa933c
19 changed files with 2787 additions and 0 deletions

320
instr_hosts.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,4 @@
#!/bin/tcsh
cp -f $linuxsys/six $sys/stow/sea/bin/six

945
six.c Normal file
View 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
View 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
View 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
View 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, &regMask);
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, &regMask);
}
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
View 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
View 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);
}

7
uselect.h Normal file
View File

@ -0,0 +1,7 @@
#include <sys/select.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);