Executing Shell Commands Programmatically

Version originale

VxWorks does not provide a system( ) API like the one available with the UNIX operating system.

In order to be able to execute shell commands from an application, the same technique can be used as illustrated in 2.21 Launching a Shell Script Programmatically. For executing shell commands programmatically, however, a pseudo-device slave file descriptor is passed to shellGenericInit( ) instead of a file handle (see the API reference for the ptyDrv library for information about pseudo-devices). The application writes the commands it wants to be executed into the master side of the pseudo-device.

The following example allows you to control another shell session interactively, in addition to the console one. It can be used to send commands to a shell for execution and get the associated results (similar to the Unix system( ) command).

VxExec.c
#include <vxWorks.h>
#include <stdio.h>
#include <ioLib.h>
#include <string.h>
#include <errnoLib.h>
#include <sysLib.h>
#include <shellLib.h>
#include <taskLib.h>
#include <ptyDrv.h>
#include -I$(WIND_BASE)/target/h/wrn/coreip
 
#define NAME_LEN 30
int fdMaster = 0;
char * shellTaskName;
 
STATUS runShell
(
BOOL uniqueFd /* whether to use one fd for the new shell I/Os (allows tip)*/
)
{
char buffer [NAME_LEN];
int fdSlave = 0;
static BOOL initialized = FALSE;
STATUS status = ERROR;
 
/* Initialize the pseudo-tty layer */
 
if (!initialized)
        {
        if (ptyDrv () != OK)
         {
         printErr ("Error while ptys init! [errno = %s]\n",
             strerror (errnoGet ()));
         return ERROR;
         }
 
        /* Create pseudo-terminal devices */
        memset (buffer, 0, NAME_LEN);
        snprintf (buffer, NAME_LEN, "shell.");
        if (ptyDevCreate (buffer, 512, 512) != OK)
         {
         printErr ("Error while creating pty %s [errno = %s]!\n",
             buffer, strerror (errnoGet ()), index);
         return ERROR;
         }
        initialized = TRUE;
    }
 
/* Open fds */
memset (buffer, 0, NAME_LEN);
snprintf (buffer, NAME_LEN, "shell.S");
fdSlave = open (buffer, O_RDWR, 0);
 
memset (buffer, 0, NAME_LEN);
snprintf (buffer, NAME_LEN, "shell.M");
fdMaster = open (buffer, O_RDWR, 0);
 
if (fdSlave == ERROR || fdMaster == ERROR)
{
printErr ("Error while opening master/slave pty sides [errno = %s]!\n",
strerror (errnoGet ()));
goto failure;
}
 
ioctl (fdMaster, FIOSETOPTIONS, OPT_LINE);
 
status = shellGenericInit ("INTERPRETER=C", 
                           0 ,
                           "-newShell-", 
                           &shellTaskName, 
                           TRUE, 
                           FALSE, 
                           fdSlave, 
                           uniqueFd ? fdSlave : STD_OUT, uniqueFd ? fdSlave : STD_ERR);
 
 
if (status == ERROR)
    {
        printErr ("Error spawning shell [%s]\n!", strerror (errnoGet ()));
        goto failure;
    }
 
printf ("Successful shell creation.\n");
if (!uniqueFd)
        printf ("Use `run' to send it commands and `finish' to terminate.\n");
else
        printf ("Connect tip() on the master side of the pty for an "
        "interactive session\n");
 
return OK;
 
failure:
close (fdSlave);
close (fdMaster);
return ERROR;
}
 
STATUS run
(
char * cmd
)
{
if (cmd != NULL)
    write (fdMaster, cmd, strlen (cmd));
 
write (fdMaster, "\n", 1); /* send newline for the command to be processed */
return OK;
}
 
STATUS finish (void)
{
SHELL_ID shellId;
 
shellId = shellFromNameGet (shellTaskName);
if (shellId == 0)
    {
        printErr ("Cannot find shell ID for task `%s'\n", shellTaskName);
        return ERROR;
    }
 
shellTerminate (shellId);
printf ("Killed shell.\n");
return OK;
}