316 lines
9.0 KiB
C
316 lines
9.0 KiB
C
/* $Id$
|
|
* Author: Roger A. Cole
|
|
* Date: 10-24-90
|
|
*
|
|
* Experimental Physics and Industrial Control System (EPICS)
|
|
*
|
|
* Copyright 1991-92, 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:
|
|
* -----------------
|
|
* .00 10-24-90 rac initial version
|
|
* .01 06-18-91 rac installed in SCCS
|
|
* .02 12-05-91 rac abandon use of lightweight process library;
|
|
* cmdRead ignores blank lines and comment
|
|
* lines; added cmdInitContext
|
|
* .03 09-14-92 rac discontinue use of special malloc routines
|
|
*
|
|
* make options
|
|
* -DvxWorks makes a version for VxWorks
|
|
* -DNDEBUG don't compile assert() checking
|
|
* -DDEBUG compile various debug code
|
|
*/
|
|
/*+/mod***********************************************************************
|
|
* TITLE cmdSubr - routines for implementing keyboard command processing
|
|
*
|
|
* DESCRIPTION
|
|
*
|
|
* long cmdBgCheck( pCxCmd )
|
|
* void cmdCloseContext( ppCxCmd )
|
|
* void cmdInitContext( ppCxCmd, prompt )
|
|
* char *cmdRead( ppCxCmd )
|
|
* void cmdSource( ppCxCmd )
|
|
*
|
|
* BUGS
|
|
* o if changes in the command context (e.g., re-directing output) are
|
|
* made at other than root context level, such changes aren't preserved
|
|
* when closing out the level and moving to the previous level.
|
|
*
|
|
*-***************************************************************************/
|
|
#ifdef vxWorks
|
|
/*----------------------------------------------------------------------------
|
|
* includes and defines for VxWorks compile
|
|
*---------------------------------------------------------------------------*/
|
|
# include <vxWorks.h>
|
|
# include <stdioLib.h>
|
|
# include <ctype.h>
|
|
#else
|
|
/*----------------------------------------------------------------------------
|
|
* includes and defines for Sun compile
|
|
*---------------------------------------------------------------------------*/
|
|
# include <stdio.h>
|
|
# include <ctype.h>
|
|
# include <sys/types.h> /* for 'select' operations */
|
|
# include <sys/time.h> /* for 'select' operations */
|
|
|
|
# include <sys/resource.h>
|
|
#endif
|
|
|
|
#include <genDefs.h>
|
|
#include <cmdDefs.h>
|
|
|
|
/*+/subr**********************************************************************
|
|
* NAME cmdBgCheck - validate a ``bg'' command
|
|
*
|
|
* DESCRIPTION
|
|
* Check to see if a bg command can be honored. This depends on
|
|
* whether the command was in a source'd file (can't have bg there),
|
|
* and on whether running under VxWorks (bg is OK) or UNIX (not OK).
|
|
*
|
|
* If the command shouldn't be honored, this routine prints a message.
|
|
*
|
|
* RETURNS
|
|
* OK, or
|
|
* ERROR if the bg command should not be honored
|
|
*
|
|
*-*/
|
|
long
|
|
cmdBgCheck(pCxCmd)
|
|
CX_CMD *pCxCmd; /* IO pointer to command context */
|
|
{
|
|
HELP_TOPIC *pBgTopic;
|
|
|
|
if (pCxCmd != pCxCmd->pCxCmdRoot) {
|
|
(void)printf("can't use bg command in source file\n");
|
|
return ERROR;
|
|
}
|
|
#ifdef vxWorks
|
|
return OK;
|
|
#else
|
|
pBgTopic = helpTopicFind(&pCxCmd->helpList, "bg");
|
|
if (pBgTopic != NULL)
|
|
helpTopicPrint(stdout, pBgTopic);
|
|
return ERROR;
|
|
#endif
|
|
}
|
|
|
|
/*+/subr**********************************************************************
|
|
* NAME cmdRead - read the next input line
|
|
*
|
|
* DESCRIPTION
|
|
* If a prompt hasn't previously been printed, prints a prompt (except
|
|
* if input is from a file). Then a check is made to see if input is
|
|
* available. If not, NULL is returned. If input is available, it is
|
|
* read into the buffer in the command context.
|
|
*
|
|
* If input is from a source'd file, no prompt is printed, and the
|
|
* input line is printed. At EOF on the file, the "source level"
|
|
* in the command context is closed, changing to the previous
|
|
* source level; the line buffer will contain a zero length line.
|
|
*
|
|
* Under VxWorks, this routine always waits until input is available,
|
|
* rather than doing a check and early NULL return if none is ready.
|
|
*
|
|
* RETURNS
|
|
* char * pointer to input, or
|
|
* NULL if no input was obtained
|
|
*
|
|
* BUGS
|
|
* o under VxWorks, with stdout redirected to a socket, a prompt which
|
|
* doesn't end with '\n' doesn't get sent
|
|
*
|
|
* SEE ALSO
|
|
* cmdSource()
|
|
*
|
|
*-*/
|
|
char *
|
|
cmdRead(ppCxCmd)
|
|
CX_CMD **ppCxCmd; /* I pointer to pointer to command context */
|
|
{
|
|
#ifndef vxWorks
|
|
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;
|
|
#endif
|
|
CX_CMD *pCxCmd=*ppCxCmd;/* pointer to command context */
|
|
int i;
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
* for keyboard and socket input, check to see if input is available
|
|
*----------------------------------------------------------------------------*/
|
|
if (pCxCmd->inputName == NULL) {
|
|
if (pCxCmd->prompt != NULL && pCxCmd->promptFlag) {
|
|
(void)printf("%s", pCxCmd->prompt);
|
|
(void)fflush(stdout);
|
|
pCxCmd->promptFlag = 0;
|
|
}
|
|
|
|
#ifndef vxWorks
|
|
/* MDA - use getrlimit since getdtablesize() is obsolete
|
|
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;
|
|
#endif
|
|
pCxCmd->promptFlag = 1;
|
|
}
|
|
|
|
if (fgets(pCxCmd->line, 80, pCxCmd->input) == NULL) {
|
|
if (pCxCmd->inputName != NULL) {
|
|
(void)printf("EOF on source'd file: %s\n", pCxCmd->inputName);
|
|
}
|
|
else {
|
|
(void)printf("^D\n");
|
|
pCxCmd->inputEOF = 1;
|
|
}
|
|
clearerr(pCxCmd->input);
|
|
cmdCloseContext(ppCxCmd);
|
|
pCxCmd = *ppCxCmd;
|
|
}
|
|
else if (pCxCmd->inputName != NULL)
|
|
(void)printf("%s", pCxCmd->line);
|
|
|
|
pCxCmd->pLine = pCxCmd->line;
|
|
if ((i=nextANField(&pCxCmd->pLine, &pCxCmd->pCommand, &pCxCmd->delim)) < 1)
|
|
return NULL;
|
|
if (i == 1 && pCxCmd->delim == '#')
|
|
return NULL;
|
|
return pCxCmd->pLine;
|
|
}
|
|
|
|
/*+/subr**********************************************************************
|
|
* NAME cmdCloseContext - closes a command context
|
|
*
|
|
* DESCRIPTION
|
|
* Closes a command context. The action depends on source of input:
|
|
*
|
|
* keyboard (or socket):
|
|
* o store "quit\n" in the line buffer
|
|
*
|
|
* source'd file:
|
|
* o close out this "source level"
|
|
* o move to the previous "source level"
|
|
* o store '\0' in the line buffer
|
|
*
|
|
* RETURNS
|
|
* void
|
|
*
|
|
*-*/
|
|
void
|
|
cmdCloseContext(ppCxCmd)
|
|
CX_CMD **ppCxCmd; /* IO ptr to pointer to command context */
|
|
{
|
|
CX_CMD *pCxCmd; /* temp pointer */
|
|
|
|
assert(ppCxCmd != NULL);
|
|
|
|
if ((*ppCxCmd)->inputName == NULL)
|
|
strcpy((*ppCxCmd)->line, "quit\n");
|
|
else {
|
|
(void)fclose((*ppCxCmd)->input);
|
|
assert((*ppCxCmd)->pPrev != NULL);
|
|
pCxCmd = (*ppCxCmd)->pPrev;
|
|
free((char *)(*ppCxCmd));
|
|
*ppCxCmd = pCxCmd;
|
|
(*ppCxCmd)->line[0] = '\0';
|
|
}
|
|
}
|
|
|
|
/*+/subr**********************************************************************
|
|
* NAME cmdInitContext - closes a command context
|
|
*
|
|
* DESCRIPTION
|
|
* Initializes a command context.
|
|
*
|
|
* RETURNS
|
|
* void
|
|
*
|
|
*-*/
|
|
void
|
|
cmdInitContext(pCxCmd, prompt)
|
|
CX_CMD *pCxCmd; /* I pointer to command context */
|
|
char *prompt; /* I pointer to static prompt string */
|
|
{
|
|
assert(pCxCmd != NULL);
|
|
|
|
pCxCmd->promptFlag = 1;
|
|
pCxCmd->input = stdin;
|
|
pCxCmd->inputEOF = 0;
|
|
pCxCmd->inputName = NULL;
|
|
pCxCmd->dataOut = stdout;
|
|
pCxCmd->dataOutRedir = 0;
|
|
pCxCmd->prompt = prompt;
|
|
pCxCmd->pPrev = NULL;
|
|
pCxCmd->pCxCmdRoot = pCxCmd;
|
|
}
|
|
|
|
/*+/subr**********************************************************************
|
|
* NAME cmdSource - process a ``source'' command
|
|
*
|
|
* DESCRIPTION
|
|
* Processes a "source fileName" command. A new command context is
|
|
* built and set up for reading from the named file. If an error
|
|
* is detected, the present command context is preserved.
|
|
*
|
|
* RETURNS
|
|
* void
|
|
*
|
|
*-*/
|
|
void
|
|
cmdSource(ppCxCmd)
|
|
CX_CMD **ppCxCmd; /* IO ptr to pointer to command context. The
|
|
pCommand item is assumed to point to the
|
|
source command. This routine scans for
|
|
the file name. */
|
|
{
|
|
CX_CMD *pCxCmdNew; /* new command context structure */
|
|
CX_CMD *pCxCmd; /* present command context structure */
|
|
|
|
pCxCmd = *ppCxCmd;
|
|
pCxCmd->fldLen =
|
|
nextNonSpaceField(&pCxCmd->pLine, &pCxCmd->pField, &pCxCmd->delim);
|
|
if (pCxCmd->fldLen <= 1) {
|
|
(void)printf("you must specify a file name\n");
|
|
return;
|
|
}
|
|
if ((pCxCmdNew = (CX_CMD *)malloc(sizeof(CX_CMD))) == NULL) {
|
|
(void)printf("couldn't malloc command structure\n");
|
|
return;
|
|
}
|
|
*pCxCmdNew = *pCxCmd; /* inherit useful info from present context */
|
|
if ((pCxCmdNew->input = fopen(pCxCmd->pField, "r")) == NULL) {
|
|
(void)printf("couldn't open file\n");
|
|
free((char *)pCxCmdNew);
|
|
return;
|
|
}
|
|
pCxCmdNew->pPrev = pCxCmd;
|
|
pCxCmdNew->inputName = pCxCmd->pField;
|
|
*ppCxCmd = pCxCmdNew;
|
|
}
|