Test client program for SerPortServer.
This commit is contained in:
861
utils/asynsrv_test.c
Executable file
861
utils/asynsrv_test.c
Executable file
@ -0,0 +1,861 @@
|
|||||||
|
#define ident "1A09"
|
||||||
|
|
||||||
|
#ifdef __DECC
|
||||||
|
#pragma module asynsrv_test ident
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
** +--------------------------------------------------------------+
|
||||||
|
** | Paul Scherrer Institute |
|
||||||
|
** | SINQ Project |
|
||||||
|
** | |
|
||||||
|
** | This software may be used freely by non-profit organizations.|
|
||||||
|
** | It may be copied provided that the name of P.S.I. and of the |
|
||||||
|
** | author is included. Neither P.S.I. nor the author assume any |
|
||||||
|
** | responsibility for the use of this software outside of P.S.I.|
|
||||||
|
** +--------------------------------------------------------------+
|
||||||
|
**
|
||||||
|
** Link_options - Here is the Linker Option File
|
||||||
|
**!$ if p1 .eqs. "DEBUG" then dbg1 := /debug
|
||||||
|
**!$ if p1 .eqs. "DEBUG" then dbg2 := _dbg
|
||||||
|
**!$ link 'dbg1'/exe=asynsrv_test'dbg2'.exe sys$input/options
|
||||||
|
**! asynsrv_test
|
||||||
|
**! sinq_olb/lib
|
||||||
|
**! sys$share:decw$xmlibshr12/share
|
||||||
|
**! sys$share:decw$xtlibshrr5/share
|
||||||
|
**! sys$share:decw$xlibshr/share
|
||||||
|
**!$ purge/nolog asynsrv_test'dbg2'.exe
|
||||||
|
**!$ write sys$output "Exec file is asynsrv_test''DBG2'.exe
|
||||||
|
**!$ exit
|
||||||
|
**!!
|
||||||
|
**!! To build on LNSA01 ...
|
||||||
|
**!! $ build_cc_select :== decc
|
||||||
|
**!! $ import tasmad
|
||||||
|
**!! $ define/job deltat_c_tlb sinq_c_tlb
|
||||||
|
**!! $ set default ud0:[maden.scratch]
|
||||||
|
**!! $ bui tasmad_disk:[mad.tests]asynsrv_test debug
|
||||||
|
**!!
|
||||||
|
** Link_options_end
|
||||||
|
**
|
||||||
|
** Building on Alpha Digital Unix:
|
||||||
|
**
|
||||||
|
** setenv TAS_BASE ~maden/tasmad
|
||||||
|
** source $TAS_BASE/tasmad.setup
|
||||||
|
** rcp -p "lnsa09:tas_src:[utils]asynsrv_test.c" \
|
||||||
|
** $TAS_SRC/utils/asynsrv_test.c
|
||||||
|
** cc -std -g -o $TAS_BIN/asynsrv_test \
|
||||||
|
** -I$TAS_INC \
|
||||||
|
** $TAS_SRC/utils/asynsrv_test.c \
|
||||||
|
** -L$TAS_LIB -lsinq -lXm -lXt -lX11
|
||||||
|
**
|
||||||
|
** Resources and Flags File: decw$user_defaults:SinQ_rc.dat
|
||||||
|
** ------------------- or $HOME/SinQ_rc
|
||||||
|
**
|
||||||
|
** Resource Flag Default Description
|
||||||
|
** -------- ---- ------- -----------
|
||||||
|
** - -name asynsrv_test Name to use when looking up the
|
||||||
|
** resources. The default is the
|
||||||
|
** image file name.
|
||||||
|
** *AsynSrvHelp -help - Generates help info.
|
||||||
|
** *AsynSrvHost -host none The name of the host to which the
|
||||||
|
** program wishes to connect.
|
||||||
|
** *AsynSrvPort -port 4000 The TCP/IP port of the RS232C server.
|
||||||
|
** *AsynSrvChan -chan none The number of the RS232C channel to
|
||||||
|
** which the device is attached.
|
||||||
|
** *AsynSrvTmo -tmo 2 Time-out in secs for responses to
|
||||||
|
** *AsynSrvTmoConn -tmoC 5 Time-out in secs for connect.
|
||||||
|
** commands.
|
||||||
|
** *AsynSrvDebug -debug If specified, selects debug mode (not
|
||||||
|
** yet implemented).
|
||||||
|
** *AsynSrvLower -lc - If specified, causes conversion of
|
||||||
|
** input to lowercase before sending.
|
||||||
|
** *AsynSrvUpper -uc - If specified, causes conversion of
|
||||||
|
** input to uppercase before sending.
|
||||||
|
** This is the default.
|
||||||
|
** *AsynSrvNoCase -ncc - If specified, causes no case
|
||||||
|
** conversion of input before sending.
|
||||||
|
** *AsynSrvTermOut -termout "\r" Specifies a string to be appended to
|
||||||
|
** anything sent to the server.
|
||||||
|
** *AsynSrvTermIn -termin "\r" Specifies a string of up to 3 chars
|
||||||
|
** which will be recognised as
|
||||||
|
** input response terminators.
|
||||||
|
** A value given via -name will be converted to lowercase before being used.
|
||||||
|
**+
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Module Name . . . . . . . . : [...tests]asynsrv_test.c
|
||||||
|
**
|
||||||
|
** Author . . . . . . . . . . : D. Maden
|
||||||
|
** Date of creation . . . . . . : Jan 1997
|
||||||
|
**
|
||||||
|
** Purpose
|
||||||
|
** =======
|
||||||
|
** asynsrv_test is a TCP/IP server client which should make a TCP/IP
|
||||||
|
** connection to an RS-232-C server and allow the user to transmit
|
||||||
|
** commands from the keyboard to a device attached to an RS-232-C channel
|
||||||
|
** on the server.
|
||||||
|
** Use:
|
||||||
|
** ===
|
||||||
|
** 1) Set up the host name, TCP/IP port number and RS-232-C channel of the
|
||||||
|
** device in the resources file (see above). These can also
|
||||||
|
** be supplied as options on the command line.
|
||||||
|
**
|
||||||
|
** 2) Run the program
|
||||||
|
**
|
||||||
|
** $ run cpt:[exe]asynsrv_test
|
||||||
|
**
|
||||||
|
** or, to specify options on the command line, use a DCL foreign
|
||||||
|
** command:
|
||||||
|
**
|
||||||
|
** $ asynsrv_test :== $cpt:[exe]asynsrv_test
|
||||||
|
** $ asynsrv_test -host <host> -port <port-number> -chan <chan>
|
||||||
|
**
|
||||||
|
** Updates:
|
||||||
|
** 1A01 20-Jan-1997 DM. Initial version.
|
||||||
|
** 1A07 3-Apr-2000 DM. Add fortify.h
|
||||||
|
**-
|
||||||
|
**====================================================================
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef __VMS
|
||||||
|
#include <sys/unixio.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#ifdef FORTIFY
|
||||||
|
#include <fortify/fortify.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <X11/Intrinsic.h>
|
||||||
|
/*
|
||||||
|
**====================================================================
|
||||||
|
*/
|
||||||
|
#include <sinq_prototypes.h>
|
||||||
|
#include <asynsrv_def.h>
|
||||||
|
#include <rs232c_def.h>
|
||||||
|
/*
|
||||||
|
|
||||||
|
**--------------------------------------------------------------------------
|
||||||
|
** Define global structures and constants.
|
||||||
|
*/
|
||||||
|
/*-------------------------------------------------------------
|
||||||
|
** Global Variables
|
||||||
|
*/
|
||||||
|
static int C_gbl_status; /* Return status from C_... routines */
|
||||||
|
static int Ctrl_C_has_happened;
|
||||||
|
void *Hndl = NULL;
|
||||||
|
|
||||||
|
static XrmOptionDescRec OpTable[] = {
|
||||||
|
{"-name", ".name", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-help", ".AsynSrvHelp", XrmoptionNoArg, (XPointer) "1"},
|
||||||
|
{"-host", ".AsynSrvHost", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-port", ".AsynSrvPort", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-chan", ".AsynSrvChan", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-tmoC", ".AsynSrvTmoConn", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-tmoc", ".AsynSrvTmoConn", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-tmo", ".AsynSrvTmo", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-debug", ".AsynSrvDebug", XrmoptionNoArg, (XPointer) "1"},
|
||||||
|
{"-lc", ".AsynSrvLower", XrmoptionNoArg, (XPointer) "1"},
|
||||||
|
{"-uc", ".AsynSrvUpper", XrmoptionNoArg, (XPointer) "1"},
|
||||||
|
{"-ncc", ".AsynSrvNoCase", XrmoptionNoArg, (XPointer) "1"},
|
||||||
|
{"-termout", ".AsynSrvTermOut", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
{"-termin", ".AsynSrvTermIn", XrmoptionSepArg, (XPointer) NULL},
|
||||||
|
};
|
||||||
|
struct AsynSrv__info AsynSrv_info;
|
||||||
|
int Debug;
|
||||||
|
float TmoC;
|
||||||
|
float Tmo;
|
||||||
|
int DoLower, DoUpper;
|
||||||
|
char TermOut[16];
|
||||||
|
char TermIn[16];
|
||||||
|
int Do_help;
|
||||||
|
|
||||||
|
char *Errstack;
|
||||||
|
int Errcode, Errno, Vaxc_errno;
|
||||||
|
/*
|
||||||
|
**--------------------------------------------------------------------------
|
||||||
|
** PrintErrInfo: print out error information.
|
||||||
|
*/
|
||||||
|
void PrintErrInfo (char *text) {
|
||||||
|
/* ============
|
||||||
|
*/
|
||||||
|
|
||||||
|
AsynSrv_ErrInfo (&Errstack, &Errcode, &Errno, &Vaxc_errno);
|
||||||
|
fprintf (stderr, "\n"
|
||||||
|
" Error return from %s.\n"
|
||||||
|
" Errstack = \"%s\".\n"
|
||||||
|
" Errcode = %d. Errno = %d. Vaxc$errno = %d.\n",
|
||||||
|
text, Errstack, Errcode, Errno, Vaxc_errno);
|
||||||
|
switch (Errcode) {
|
||||||
|
case ASYNSRV__BAD_BIND:
|
||||||
|
fprintf (stderr, "ASYNSRV__BAD_BIND\n");
|
||||||
|
break;
|
||||||
|
case ASYNSRV__BAD_CONNECT:
|
||||||
|
fprintf (stderr, "ASYNSRV__BAD_CONNECT\n");
|
||||||
|
break;
|
||||||
|
case ASYNSRV__BAD_HOST:
|
||||||
|
fprintf (stderr, "ASYNSRV__BAD_HOST\n");
|
||||||
|
break;
|
||||||
|
case ASYNSRV__BAD_PAR:
|
||||||
|
fprintf (stderr, "ASYNSRV__BAD_PAR\n");
|
||||||
|
break;
|
||||||
|
case ASYNSRV__BAD_SOCKET:
|
||||||
|
fprintf (stderr, "ASYNSRV__BAD_SOCKET\n");
|
||||||
|
break;
|
||||||
|
case ASYNSRV__NO_ROOM:
|
||||||
|
fprintf (stderr, "ASYNSRV__NO_ROOM\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf (stderr, "Unrecognised error code!\n");
|
||||||
|
if ((Errno != 0) || (Vaxc_errno != 0)) perror (text);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
**--------------------------------------------------------------------------
|
||||||
|
** ShowUsage: A simple print-out routine.
|
||||||
|
*/
|
||||||
|
void ShowUsage (int full) {
|
||||||
|
/* =========
|
||||||
|
*/
|
||||||
|
if (!full) {
|
||||||
|
if (Do_help) return;
|
||||||
|
printf ("\n"
|
||||||
|
"To get help on running the program issue the command:\n"
|
||||||
|
"\n"
|
||||||
|
" asynsrv_test -help\n"
|
||||||
|
"\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf ("\n"
|
||||||
|
"Usage: asynsrv_test [options ...]\n"
|
||||||
|
" \n"
|
||||||
|
" Valid options are: Equivalent resource name:\n"
|
||||||
|
" -help *AsynSrvHelp\n"
|
||||||
|
" -host <host-name> *AsynSrvHost\n"
|
||||||
|
" -port <port-number> *AsynSrvPort Dflt=4000\n"
|
||||||
|
" -chan <channel-number> *AsynSrvChan\n"
|
||||||
|
" -debug *AsynSrvDebug\n"
|
||||||
|
" -tmo <secs> *AsynSrvTmo Dflt=2\n"
|
||||||
|
" -tmoC <secs> *AsynSrvTmoConn Dflt=5\n"
|
||||||
|
" -lc *AsynSrvLower\n"
|
||||||
|
" -uc *AsynSrvUpper\n"
|
||||||
|
" -ncc *AsynSrvNoCase\n"
|
||||||
|
" -termout <term-out-string> *AsynSrvTermOut Dflt=\"\\r\"\n"
|
||||||
|
" -termin <term-in-string> *AsynSrvTermIn Dflt=\"\\r\"\n"
|
||||||
|
" -termin\n"
|
||||||
|
"\n"
|
||||||
|
" No default is allowed for -host or -chan,"
|
||||||
|
" i.e. values for\n"
|
||||||
|
" these parameters must be supplied either via a resource file or"
|
||||||
|
" on the\n"
|
||||||
|
" command line.\n"
|
||||||
|
"\n"
|
||||||
|
" -tmo is the time-out for responses to commands.\n"
|
||||||
|
" -tmoC is the time-out for the initial connection to the server.\n"
|
||||||
|
"\n"
|
||||||
|
"To quit the program, issue the command \"#q\".\n"
|
||||||
|
"To send a null command, issue the command \"\\0\".\n"
|
||||||
|
"Other special commands are:\n"
|
||||||
|
" #help\n"
|
||||||
|
" #close - gets SerPortServer to close its serial ports.\n"
|
||||||
|
" #flush - gets SerPortServer to flush its output.\n"
|
||||||
|
" #trace off - turn off SerPortServer tracing.\n"
|
||||||
|
" #trace on - turn on SerPortServer tracing.\n"
|
||||||
|
" #trace write - gets SerPortServer to write its trace buffer.\n"
|
||||||
|
"To send a command starting with \"#\", start it with \"##\".\n"
|
||||||
|
"\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
**--------------------------------------------------------------------------
|
||||||
|
** DoInteract: Interact with the RS-232-C Device
|
||||||
|
*/
|
||||||
|
int DoInteract () {
|
||||||
|
/* ==========
|
||||||
|
*/
|
||||||
|
int status, go_on, no_errors, no_restore, i, j, len, act_len, tok_len;
|
||||||
|
|
||||||
|
FILE *lun;
|
||||||
|
char recd[132], buff[132], cmnd[132], cmnd_prnt[512];
|
||||||
|
char eot_save[4], tmo_save[4], term;
|
||||||
|
char *rptr, *tok;
|
||||||
|
|
||||||
|
struct RS__MsgStruct send_buff;
|
||||||
|
struct RS__RespStruct rcve_buff;
|
||||||
|
|
||||||
|
lun = stdin; /* Use standard input */
|
||||||
|
|
||||||
|
go_on = True;
|
||||||
|
no_errors = True;
|
||||||
|
|
||||||
|
if (lun == stdin) {
|
||||||
|
printf ("Issue the command \"#h\" for help and \"#q\" to quit.\n> ");
|
||||||
|
fflush (NULL);
|
||||||
|
}
|
||||||
|
while (go_on && (fgets (recd, sizeof (recd), lun) != NULL)) {
|
||||||
|
len = strlen (recd);
|
||||||
|
if (len <= 1) {
|
||||||
|
if (lun == stdin) {printf ("> "); fflush (NULL);}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (recd[len-1] != '\n') {
|
||||||
|
recd[20] = '\0';
|
||||||
|
printf (" Record not terminated by \"\\n\". "
|
||||||
|
"It is probably too long!\n"
|
||||||
|
" The record starts thus: %s ...\n"
|
||||||
|
" It has been skipped.\n", recd);
|
||||||
|
if (lun == stdin) {printf ("> "); fflush (NULL);}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
recd[len-1] = '\0'; /* Remove the terminating "\n" */
|
||||||
|
/*
|
||||||
|
** Strip off any trailing stuff (but keep it around so that we
|
||||||
|
** can print it out). "Trailing stuff" is anything after a "!".
|
||||||
|
*/
|
||||||
|
act_len = strcspn (recd, "!");
|
||||||
|
len = sizeof (buff);
|
||||||
|
if (DoLower) {
|
||||||
|
StrEdit (buff, recd, "trim uncomment lowercase", &len);
|
||||||
|
}else if (DoUpper) {
|
||||||
|
StrEdit (buff, recd, "trim uncomment upcase", &len);
|
||||||
|
}else {
|
||||||
|
StrEdit (buff, recd, "trim uncomment", &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof (cmnd);
|
||||||
|
StrEdit (cmnd, buff, "lowercase", &len);
|
||||||
|
|
||||||
|
if (strncmp (buff, "##", 2) == 0) { /* "##" at start gets compressed
|
||||||
|
** to "#" */
|
||||||
|
len = sizeof (buff);
|
||||||
|
StrEdit (buff, &buff[1], "trim", &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = strtok (cmnd, " ");
|
||||||
|
tok_len = (tok != NULL) ? strlen (tok) : 0;
|
||||||
|
if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "#exit", tok_len) == 0)) {
|
||||||
|
go_on = False;
|
||||||
|
}else if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "#quit", tok_len) == 0)) {
|
||||||
|
go_on = False;
|
||||||
|
}else if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "#trace", tok_len) == 0)) {
|
||||||
|
tok = strtok (NULL, " ");
|
||||||
|
tok_len = (tok != NULL) ? strlen (tok) : 0;
|
||||||
|
if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "on", tok_len) == 0)) {
|
||||||
|
printf ("Requesting server to turn tracing on ..."); fflush (NULL);
|
||||||
|
status = AsynSrv_Trace (&AsynSrv_info, True);
|
||||||
|
if (status) {
|
||||||
|
printf (" done.\n");
|
||||||
|
}else {
|
||||||
|
printf ("\nError detected!\n");
|
||||||
|
}
|
||||||
|
}else if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "off", tok_len) == 0)) {
|
||||||
|
printf ("Requesting server to turn tracing off ..."); fflush (NULL);
|
||||||
|
status = AsynSrv_Trace (&AsynSrv_info, False);
|
||||||
|
if (status) {
|
||||||
|
printf (" done.\n");
|
||||||
|
}else {
|
||||||
|
printf ("\nError detected!\n");
|
||||||
|
}
|
||||||
|
}else if ((tok_len >= 1) &&
|
||||||
|
(strncmp (tok, "write", tok_len) == 0)) {
|
||||||
|
printf ("Requesting server to write trace ..."); fflush (NULL);
|
||||||
|
status = AsynSrv_Trace_Write (&AsynSrv_info);
|
||||||
|
if (status) {
|
||||||
|
printf (" done.\n");
|
||||||
|
}else {
|
||||||
|
printf ("\nError detected!\n");
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
printf ("Illegal \"#trace\" command! You must "
|
||||||
|
"specify \"on\" or \"off\" or \"write\".\n");
|
||||||
|
}
|
||||||
|
}else if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "#flush", tok_len) == 0)) {
|
||||||
|
printf ("Requesting server to flush ..."); fflush (NULL);
|
||||||
|
status = AsynSrv_Flush (&AsynSrv_info);
|
||||||
|
if (status) {
|
||||||
|
printf (" done.\n");
|
||||||
|
}else {
|
||||||
|
printf ("\nError detected!\n");
|
||||||
|
}
|
||||||
|
}else if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "#close", tok_len) == 0)) {
|
||||||
|
printf ("Requesting server to close its serial channels ..."); fflush (NULL);
|
||||||
|
status = AsynSrv_ChanClose (&AsynSrv_info);
|
||||||
|
if (status) {
|
||||||
|
printf (" done.\n");
|
||||||
|
}else {
|
||||||
|
printf ("\nError detected!\n");
|
||||||
|
}
|
||||||
|
}else if ((tok_len >= 2) &&
|
||||||
|
(strncmp (tok, "#help", tok_len) == 0)) {
|
||||||
|
ShowUsage (True);
|
||||||
|
}else if ((cmnd[0] == '#') && (cmnd[1] != '#')) {
|
||||||
|
printf ("Illegal command! If you really want to start a command\n"
|
||||||
|
" with a \"#\" character, you should use\n"
|
||||||
|
" \"##\" instead!\n");
|
||||||
|
}else {
|
||||||
|
if (strlen (buff) > 0) {
|
||||||
|
StrJoin (buff, sizeof (buff), buff, TermOut); /* Append terminator */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
** Show user what's getting sent
|
||||||
|
*/
|
||||||
|
MakePrintable (cmnd_prnt, sizeof (cmnd_prnt), buff);
|
||||||
|
printf ("Sending \"%s\" ... ", cmnd_prnt); fflush (NULL);
|
||||||
|
|
||||||
|
status = AsynSrv_SendCmnds (&AsynSrv_info, &send_buff, &rcve_buff,
|
||||||
|
buff, NULL);
|
||||||
|
if (!status) {
|
||||||
|
go_on = no_errors = False;
|
||||||
|
continue;
|
||||||
|
}else {
|
||||||
|
rptr = AsynSrv_GetReply (&AsynSrv_info, &rcve_buff, NULL);
|
||||||
|
if (rptr == NULL) {
|
||||||
|
printf ("No response from server!\n");
|
||||||
|
go_on = no_errors = False;
|
||||||
|
continue;
|
||||||
|
}else {
|
||||||
|
AsynSrv_GetLenTerm (&AsynSrv_info, &rcve_buff, rptr, &len, &term);
|
||||||
|
MakeMemPrintable (cmnd_prnt, sizeof (cmnd_prnt), rptr, len);
|
||||||
|
MakeMemPrintable (recd, sizeof (recd), &term, 1);
|
||||||
|
j = strlen (cmnd_prnt);
|
||||||
|
printf ("\nResponse length = %d. Terminator = \"%s\".\n", len, recd);
|
||||||
|
for (i = 0; i < (j/70); i++)
|
||||||
|
printf (" \"%.70s\"\\...\n", &cmnd_prnt[i*70]);
|
||||||
|
printf (" \"%s\"\n", &cmnd_prnt[i*70]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lun == stdin) {printf ("> "); fflush (NULL);}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_errors) {
|
||||||
|
printf ("\"Interaction\" completed.\n");
|
||||||
|
}else {
|
||||||
|
printf ("Interaction failed.\n");
|
||||||
|
}
|
||||||
|
return no_errors;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** SetupXrmDatabase - setup Resource Manager Database
|
||||||
|
*/
|
||||||
|
int SetupXrmDatabase (
|
||||||
|
/* ================
|
||||||
|
*/ XrmDatabase *db,
|
||||||
|
char *name[],
|
||||||
|
int *argc,
|
||||||
|
char *argv[]) {
|
||||||
|
|
||||||
|
static char our_name[80] = "Unknown"; /* This holds the program name */
|
||||||
|
static char lkup_name[80] = "Unknown"; /* Name for looking in database */
|
||||||
|
|
||||||
|
int status, i, first = True;
|
||||||
|
char text[80];
|
||||||
|
char full_nm0[80];
|
||||||
|
char full_nm1[80];
|
||||||
|
char *p_fil[] = {0,0,0,0,0,0,0,0,0,0};
|
||||||
|
char *my_name;
|
||||||
|
char *my_name_last;
|
||||||
|
|
||||||
|
char *name_type;
|
||||||
|
XrmValue name_value;
|
||||||
|
|
||||||
|
XrmDatabase cmnd_line_db = NULL;
|
||||||
|
XrmDatabase lcl_db = NULL;
|
||||||
|
/*-----------------------------------------------------
|
||||||
|
** This routine merges some resource databases with options specified on
|
||||||
|
** the command line. Resources can then be looked up using XrmGetResource.
|
||||||
|
** This is a bit like the X-toolkit routine XtAppInitialize does for the
|
||||||
|
** extraction of resources by XtGetApplicationResources.
|
||||||
|
**
|
||||||
|
** I can't help but think that there's a simpler way of doing this but I
|
||||||
|
** can't find it in the X manuals. Basically, the problem arises with wanting
|
||||||
|
** to avoid the calling program being associated with an X-display, i.e. it
|
||||||
|
** is intended for use by "command-line oriented" programs. All the nice,
|
||||||
|
** easy-to-use resource/command-line setup routines in Xlib or Xtlib seem to
|
||||||
|
** assume one is going to use a display -- not surprising, I suppose,
|
||||||
|
** since the concept of Xlib is for writing window based applications!
|
||||||
|
**
|
||||||
|
** Anyway, the point is that the following way turn out to be lacking
|
||||||
|
** when it gets tested in anger.
|
||||||
|
*/
|
||||||
|
status = True; /* Assume success */
|
||||||
|
|
||||||
|
our_name[0] = '\0';
|
||||||
|
/*
|
||||||
|
** Make a list of the databases to be merged, highest priority first.
|
||||||
|
*/
|
||||||
|
#ifdef __VMS
|
||||||
|
p_fil[0] = "decw$user_defaults:SinQ_rc.dat";
|
||||||
|
p_fil[1] = "decw$group_defaults:SinQ_rc.dat";
|
||||||
|
p_fil[2] = "decw$system_defaults:SinQ_rc.dat";
|
||||||
|
p_fil[3] = "decw$user_defaults:decw$xdefaults.dat";
|
||||||
|
p_fil[4] = "decw$group_defaults:decw$xdefaults.dat";
|
||||||
|
p_fil[5] = "decw$system_defaults:decw$xdefaults.dat";
|
||||||
|
p_fil[6] = NULL;
|
||||||
|
if (*argc > 0) { /* Find out what we are called - parse file nm */
|
||||||
|
my_name = strstr (argv[0], "]"); /* Find end of directory, i.e. "]" */
|
||||||
|
my_name++; /* Skip over "]" */
|
||||||
|
if (my_name[0] == '[') { /* Handle possible concealed device */
|
||||||
|
my_name = strstr (my_name, "]");
|
||||||
|
my_name++;
|
||||||
|
}
|
||||||
|
i = sizeof (our_name);
|
||||||
|
StrEdit (our_name, my_name, "lowercase", &i); /* Copy the rest */
|
||||||
|
strtok (our_name, "."); /* Close it off at "." */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
p_fil[0] = StrJoin (full_nm0, sizeof (full_nm0),
|
||||||
|
getenv ("HOME"), "/SinQ_rc");
|
||||||
|
p_fil[1] = "/usr/lib/X11/app-defaults/SinQ_rc";
|
||||||
|
p_fil[2] = StrJoin (full_nm1, sizeof (full_nm1),
|
||||||
|
getenv ("HOME"), "/.Xdefaults");
|
||||||
|
p_fil[3] = "/usr/lib/X11/app-defaults/Xdefaults";
|
||||||
|
p_fil[4] = NULL;
|
||||||
|
if (*argc > 0) { /* Find out what we are called - parse file nm */
|
||||||
|
/* Find end of directories */
|
||||||
|
my_name = argv[0] - 1;
|
||||||
|
while (my_name != NULL) {
|
||||||
|
my_name_last = my_name;
|
||||||
|
my_name_last++;
|
||||||
|
my_name = strstr (my_name_last, "/");
|
||||||
|
}
|
||||||
|
StrJoin (our_name, sizeof (our_name), my_name_last, "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
printf ("My name is \"%s\"\n", our_name);
|
||||||
|
/*
|
||||||
|
** Initialise and combine all databases
|
||||||
|
*/
|
||||||
|
XrmInitialize ();
|
||||||
|
for (i = 0; i < XtNumber (p_fil); i++) {
|
||||||
|
if (p_fil[i] == NULL) break;
|
||||||
|
status = XrmCombineFileDatabase (p_fil[i], &lcl_db, False);
|
||||||
|
if (status != 0) {
|
||||||
|
if (first) {
|
||||||
|
printf ("Resource database created from file %s.\n", p_fil[i]);
|
||||||
|
}else {
|
||||||
|
printf ("File %s merged into resource database.\n", p_fil[i]);
|
||||||
|
}
|
||||||
|
first = False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
** See if there's anything specified on cmnd line, incl "name".
|
||||||
|
*/
|
||||||
|
XrmParseCommand (&cmnd_line_db,
|
||||||
|
OpTable, XtNumber(OpTable), our_name, argc, argv);
|
||||||
|
if (cmnd_line_db != NULL) {
|
||||||
|
/*
|
||||||
|
** There was at least 1 item on cmnd line. Process the line.
|
||||||
|
** If -name was specified, adopt it.
|
||||||
|
*/
|
||||||
|
status = XrmGetResource (cmnd_line_db, /* See if a name was specified */
|
||||||
|
StrJoin (text, sizeof (text), our_name, ".name"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&name_type, &name_value);
|
||||||
|
if (status) {
|
||||||
|
i = sizeof (lkup_name);
|
||||||
|
StrEdit (lkup_name, name_value.addr, "lowercase", &i);
|
||||||
|
printf ("Option list name is \"%s\"\n", lkup_name);
|
||||||
|
}else {
|
||||||
|
strcpy (lkup_name, our_name);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
** Loop over all items in OpTable and merge them into database,
|
||||||
|
** taking care of any possible name changes.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < XtNumber (OpTable); i++) {
|
||||||
|
if (strcmp (OpTable[i].option, "-name") == 0) continue;
|
||||||
|
status = XrmGetResource (cmnd_line_db,
|
||||||
|
StrJoin (text, sizeof (text),
|
||||||
|
our_name, OpTable[i].specifier),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&name_type, &name_value);
|
||||||
|
if (status) {
|
||||||
|
StrJoin (text, sizeof (text), lkup_name, OpTable[i].specifier);
|
||||||
|
XrmPutResource (&lcl_db, text, "String", &name_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*name = lkup_name;
|
||||||
|
*db = lcl_db;
|
||||||
|
if (lcl_db == NULL) printf ("Warning -- no resource database found.\n");
|
||||||
|
|
||||||
|
XrmDestroyDatabase (cmnd_line_db);
|
||||||
|
/*
|
||||||
|
** XrmPutFileDatabase (lcl_db, "asynsrv_test.db");
|
||||||
|
*/
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** GetCheckResources - get and check our resources
|
||||||
|
*/
|
||||||
|
int GetCheckResources (
|
||||||
|
/* =================
|
||||||
|
*/ XrmDatabase *db,
|
||||||
|
char *appName) {
|
||||||
|
|
||||||
|
int i, status;
|
||||||
|
char buff[80];
|
||||||
|
char *type;
|
||||||
|
XrmValue value;
|
||||||
|
time_t time_now;
|
||||||
|
float tmp_secs;
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvHelp"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
Do_help = (status) ? True : False;
|
||||||
|
if (Do_help) {
|
||||||
|
ShowUsage (True);
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvDebug"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
Debug = (status) ? True : False;
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvNoCase"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (status) {
|
||||||
|
DoLower = False; DoUpper = False;
|
||||||
|
}else {
|
||||||
|
DoLower = False; DoUpper = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvLower"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (status) DoLower = True;
|
||||||
|
if (DoLower) DoUpper = False;
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvUpper"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (status) DoUpper = True;
|
||||||
|
if (DoUpper) DoLower = False;
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvHost"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status) {
|
||||||
|
printf ("No server specified via the -host option. "
|
||||||
|
"No default allowed!\n");
|
||||||
|
ShowUsage (False);
|
||||||
|
return False;
|
||||||
|
}else {
|
||||||
|
StrJoin (AsynSrv_info.host, sizeof (AsynSrv_info.host), value.addr, "");
|
||||||
|
printf ("Using Internet host \"%s\".\n", AsynSrv_info.host);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvPort"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status || (sscanf (value.addr, "%d", &AsynSrv_info.port) != 1)) {
|
||||||
|
AsynSrv_info.port = 4000;
|
||||||
|
printf ("Using the default TCP/IP port number of %d.\n",
|
||||||
|
AsynSrv_info.port);
|
||||||
|
}else {
|
||||||
|
printf ("TCP/IP port number = %d\n", AsynSrv_info.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvChan"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status || (sscanf (value.addr, "%d", &AsynSrv_info.chan) != 1)) {
|
||||||
|
printf ("No RS-232-C channel specified via the -chan option. "
|
||||||
|
"No default allowed!\n");
|
||||||
|
ShowUsage (False);
|
||||||
|
return False;
|
||||||
|
}else {
|
||||||
|
printf ("RS-232-C channel number = %d\n", AsynSrv_info.chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvTmo"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status || (sscanf (value.addr, "%f", &Tmo) != 1)) {
|
||||||
|
Tmo = 2.0;
|
||||||
|
}else {
|
||||||
|
printf ("Response time-out = %d msec.\n", (int) ((Tmo + 0.0001) * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvTmoConn"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status || (sscanf (value.addr, "%f", &TmoC) != 1)) {
|
||||||
|
TmoC = 5.0;
|
||||||
|
}else {
|
||||||
|
printf ("Connection time-out = %d secs.\n", (int) (TmoC + 0.0001));
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvTermOut"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status) {
|
||||||
|
printf ("Output terminator is \"\\r\"\n");
|
||||||
|
strcpy (TermOut, "\r");
|
||||||
|
}else {
|
||||||
|
printf ("Output terminator is \"%s\"\n", value.addr);
|
||||||
|
i = sizeof (TermOut);
|
||||||
|
if (StrEdit (TermOut, value.addr, "trim", &i) == NULL) {
|
||||||
|
printf ("Bad output terminator!\n");
|
||||||
|
ShowUsage (False);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = XrmGetResource (*db,
|
||||||
|
StrJoin (buff, sizeof (buff),
|
||||||
|
appName, ".AsynSrvTermIn"),
|
||||||
|
"ProgramName.Values",
|
||||||
|
&type, &value);
|
||||||
|
if (!status) {
|
||||||
|
printf ("Input terminator is \"\\r\"\n");
|
||||||
|
memcpy (TermIn, "1\r\0\0", 4);
|
||||||
|
}else {
|
||||||
|
printf ("Input terminator is \"%s\"\n", value.addr);
|
||||||
|
i = sizeof (TermIn) - 1;
|
||||||
|
if (StrEdit (&TermIn[1], value.addr, "trim", &i) == NULL) {
|
||||||
|
printf ("Bad input terminator!\n");
|
||||||
|
ShowUsage (False);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
switch (strlen (&TermIn[1])) {
|
||||||
|
case 0: strcpy (TermIn, "0\0\0\0"); break;
|
||||||
|
case 1: TermIn[0] = '1'; TermIn[2] = TermIn[3] = '\0'; break;
|
||||||
|
case 2: TermIn[0] = '2'; TermIn[3] = '\0'; break;
|
||||||
|
case 3: TermIn[0] = '3'; break;
|
||||||
|
default:
|
||||||
|
printf ("Input terminator string is too long!\n");
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
**--------------------------------------------------------------------------
|
||||||
|
** CtrlC_Handler: Signal handler to detect <Ctrl-C> on keyboard.
|
||||||
|
*/
|
||||||
|
void CtrlC_Handler (int sigint) {
|
||||||
|
/* =============
|
||||||
|
*/
|
||||||
|
Ctrl_C_has_happened = True;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
**==========================================================================
|
||||||
|
** Main line program
|
||||||
|
** ------------------
|
||||||
|
*/
|
||||||
|
int main (int argc, char **argv) {
|
||||||
|
/* ============================
|
||||||
|
*/
|
||||||
|
char buff[80], text0[80], text1[80];
|
||||||
|
int buff_len;
|
||||||
|
int status, errcode, errno, vaxc_errno, i;
|
||||||
|
char *errName;
|
||||||
|
time_t time_now;
|
||||||
|
int sec_tmoC, msec_tmo;
|
||||||
|
|
||||||
|
XrmDatabase my_db;
|
||||||
|
char *appName;
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
time_now = time (NULL);
|
||||||
|
printf ("RS-232-C Device Test Program, Ident %s.\n", ident);
|
||||||
|
printf ("Started at %s", asctime (localtime (&time_now)));
|
||||||
|
/*-------------------------------------------------------------
|
||||||
|
** Setup the resource database and look up the resources.
|
||||||
|
*/
|
||||||
|
SetupXrmDatabase (&my_db, &appName, &argc, argv);
|
||||||
|
if (argc > 1) {
|
||||||
|
if (argc > 2) {
|
||||||
|
printf ("\nThe following arguments were not used:\n\n ");
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
printf ("\"%s\" ", argv[i]);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
printf ("\nArgument \"%s\" was not used.", argv[1]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
ShowUsage (False);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
status = GetCheckResources (&my_db, appName);
|
||||||
|
if (!status) return False;
|
||||||
|
/*
|
||||||
|
** Declare a signal handler to catch <Ctrl-C> so that we
|
||||||
|
** can exit cleanly.
|
||||||
|
*/
|
||||||
|
Ctrl_C_has_happened = False;
|
||||||
|
signal (SIGINT, CtrlC_Handler);
|
||||||
|
|
||||||
|
sec_tmoC = (int) (TmoC + 0.0001);
|
||||||
|
msec_tmo = (int) ((Tmo + 0.0001) * 1000);
|
||||||
|
status = AsynSrv_ConfigDflt (
|
||||||
|
"tmoC", sec_tmoC, /* Specify the connection time-out */
|
||||||
|
"msecTmo", msec_tmo, /* Specify the response time-out */
|
||||||
|
"eot", TermIn, /* Specify the terminators */
|
||||||
|
NULL);
|
||||||
|
if (!status) {
|
||||||
|
printf ("Error setting default configuration of server connection.\n");
|
||||||
|
PrintErrInfo ("AsynSrv_ConfigDflt");
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = AsynSrv_Open (&AsynSrv_info);
|
||||||
|
if (!status) {
|
||||||
|
printf ("Error opening connection to server.\n");
|
||||||
|
PrintErrInfo ("AsynSrv_Open");
|
||||||
|
return False;
|
||||||
|
}else {
|
||||||
|
|
||||||
|
status = DoInteract ();
|
||||||
|
if (!status) {
|
||||||
|
PrintErrInfo ("DoInteract");
|
||||||
|
AsynSrv_Close (&AsynSrv_info, 0);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = AsynSrv_Close (&AsynSrv_info, 0);
|
||||||
|
}
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------- End of asynsrv_test.c */
|
Reference in New Issue
Block a user