Files
pcas/src/util/cmdClient.c

322 lines
8.1 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* $Id$
* Author: Roger A. Cole
* Date: 11-26-90
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 11-26-90 rac initial version
* .02 07-30-91 rac installed in SCCS
* .03 09-11-91 joh updated for v5 vxWorks
* .03 11-07-91 rac be more forgiving of unexpected interactions
* .04 12-06-91 rac total rewrite, Unix-only, no LWP
*
* make options
* -DNDEBUG don't compile assert() checking
* -DDEBUG compile various debug code, including checks on
* malloc'd memory
*/
/*+/mod***********************************************************************
* TITLE cmdClient.c - general purpose client for command-based servers
*
* DESCRIPTION
* Connects to a text-command-based server.
*
* Usage on SunOS:
* % cmdClient hostName portNum
* or
* execl("cmdClient", "cmdClient", "hostName", "portNum",
* (char *)0);
*
* Usage on VxWorks:
* > cmdClient "hostName",portNum
*
* BUGS
* o the stdout stream from this program contains, intermixed, the
* server's stdout and stderr streams
* o not all signals are caught
*-***************************************************************************/
#include <genDefs.h>
#include <tsDefs.h>
#include <ezsSockSubr.h>
#include <stdio.h>
#include <ctype.h>
#include <strings.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
/*-----------------------------------------------------------------------------
* prototypes
*----------------------------------------------------------------------------*/
int cmdcl();
void cmdclCmdProcess();
char *cmdclInTask();
long cmdclTask();
void cmdclTaskSigHandler();
/*-----------------------------------------------------------------------------
* global definitions
*----------------------------------------------------------------------------*/
jmp_buf sigEnv; /* environment for longjmp at signal time */
main(argc, argv)
int argc; /* number of command line args */
char *argv[]; /* command line args */
{
char *hostName; /* host name for server */
int portNum; /* port number for server */
if (argc != 3) /* must be command and 2 args */
goto mainUsage;
hostName = argv[1];
if (sscanf(argv[2], "%d", &portNum) != 1) {
printf("error scanning port number\n");
goto mainUsage;
}
return cmdClient(hostName, portNum);
mainUsage:
printf("Usage: %s serverHostName serverPortNumber\n", argv[0]);
return -1;
}
/*+/subr**********************************************************************
* NAME cmdClient - shell callable interface for cmdClient
*
*-*/
int
cmdClient(hostName, portNum)
char *hostName; /* I host name for server */
int portNum; /* I port number for server */
{
long stat; /* status return from calls */
int serverSock=-1; /* socket connected to server */
char serverBuf[80];
char *pBuf;
FILE *myIn=NULL;
FILE *myOut=NULL;
char *findNl;
char message[80];
int i;
char keyboard[80]; /* line from keyboard */
int eofFlag=0;
int discardNL=0;
genSigInit(cmdclTaskSigHandler);
if (setjmp(sigEnv) != 0)
goto cmdclTaskWrapup;
/*-----------------------------------------------------------------------------
* attempt to connect to the server. If the connection is successful,
* print the message returned by the server. Then open two streams to
* the socket, one for characters from keyboard to server, the other
* for characters from server to stdout.
*----------------------------------------------------------------------------*/
if ((i=ezsConnectToServer(&serverSock, portNum, hostName, serverBuf)) < 0) {
if (i == -1) {
(void)sprintf(message, "connect to %s port:%d", hostName, portNum);
perror(message);
}
else
printf("%s\n", serverBuf);
serverSock = -1;
goto cmdclTaskWrapup;
}
printf("%s\n", serverBuf);
if (ezsFopenToFd(&myIn, &serverSock) < 0) {
perror("myIn");
myIn = NULL;
goto cmdclTaskWrapup;
}
setbuf(myIn, NULL);
if (ezsFopenToFd(&myOut, &serverSock) < 0) {
perror("myOut");
myOut = NULL;
goto cmdclTaskWrapup;
}
/*----------------------------------------------------------------------------
* "processing loop"
* do the interactions with the server, attempting as much as possible
* to show the messages as they come in from the server.
*---------------------------------------------------------------------------*/
while (!eofFlag) {
if (cmdclInTask(keyboard) != NULL) {
fputs(keyboard, myOut);
fflush(myOut);
}
if (ezsCheckFpRead(myIn)) {
int i, c;
i = 0;
while (ezsCheckFpRead(myIn)) {
if ((c = fgetc(myIn)) == EOF) {
eofFlag++;
break;
}
serverBuf[i++] = c;
if (i >= 79 || c == '\n')
break;
}
pBuf = serverBuf;
serverBuf[i] = '\0';
if (i > 0) {
char *findChr;
if ((findChr = index(pBuf, '#')) != NULL) {
while (pBuf != findChr) {
putchar(*pBuf);
pBuf++;
}
if (strncmp(pBuf, "#p#r#", 5) == 0) {
pBuf += 5;
discardNL = 1;
}
}
else
pBuf = serverBuf;
if (discardNL) {
if ((findNl = index(pBuf, '\n')) != NULL) {
*findNl = '\0';
discardNL = 0;
}
}
fputs(pBuf, stdout);
fflush(stdout);
}
else {
if (strncmp(keyboard, "quit", 4) == 0)
break;
else if (strncmp(keyboard, "close", 5) == 0)
break;
else if (strncmp(keyboard, "disconnect", 10) == 0)
break;
else
printf("null message from server\n");
}
}
sleep(1);
}
cmdclTaskWrapup:
if (myIn != NULL)
fclose(myIn);
if (myOut != NULL)
fclose(myOut);
if (serverSock >= 0)
close(serverSock);
return 0;
}
/*+/subr**********************************************************************
* NAME cmdclTaskSig - signal handling and initialization
*
* DESCRIPTION
* These routines set up for the signals to be caught for cmdclTask
* and handle the signals when they occur.
*
* RETURNS
* void
*
* BUGS
* o not all signals are caught
* o it's not clear how useful it is to catch the signals which originate
* from the keyboard
*
*-*/
void
cmdclTaskSigHandler(signo)
int signo;
{
printf("entered cmdclTaskSigHandler for signal:%d\n", signo);
signal(signo, SIG_DFL);
longjmp(sigEnv, 1);
}
/*+/subr**********************************************************************
* NAME cmdclInTask - handle keyboard input
*
* DESCRIPTION
* Checks to see if input is available and reads it, if so. If
* there is EOF, then question is asked whether to shut down the
* server.
*
* RETURNS
* char *, or
* NULL
*
*-*/
char *
cmdclInTask(buf)
char *buf;
{
char *input;
char message[80];
fd_set fdSet; /* set of fd's to watch with select */
int fdSetWidth; /* width of select bit mask */
struct timeval fdSetTimeout;/* timeout interval for select */
struct rlimit rlp;
/* MDA - replace obsolete system call
fdSetWidth = getdtablesize();
*/
getrlimit(RLIMIT_NOFILE,&rlp);
fdSetWidth = rlp.rlim_cur;
fdSetTimeout.tv_sec = 0;
fdSetTimeout.tv_usec = 0;
FD_ZERO(&fdSet);
FD_SET(fileno(stdin), &fdSet);
if (select(fdSetWidth, &fdSet, NULL, NULL, &fdSetTimeout) == 0)
return NULL;
if (fgets(buf, 80, stdin) == NULL) {
strcpy(buf, "quit\n");
clearerr(stdin);
}
if (strncmp(buf, "quit", 4) == 0) {
(void)printf("stop the server (y/n) ? ");
if (fgets(message, 80, stdin) == NULL) {
strcpy(message, "y");
}
if (message[0] == 'y' || message[0] == 'Y')
strcpy(buf, "quit\n");
else
strcpy(buf, "\n");
}
return buf;
}