Files
pcas/src/libCom/cmdSubr.c

316 lines
9.0 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: 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;
}