Example #1
0
/**
 * Try to handle special commands like "cd" or "export" internally.  This will
 * work if we have a simple commend with no redirection, piping, or such.
 *
 * @param context    The Exit oontext.
 * @param cmd        The command string.
 * @param rc         The operating system return code.
 *
 * @return           True if command was handled, false otherwise.
 */
logical_t handleCommandInternally(RexxExitContext *context, char *cmd, RexxObjectPtr rc)
{
    /* check for redirection symbols, ignore them when enclosed in double quotes.
       escaped quotes are ignored. */
    bool noDirectInvoc = false;
    bool inQuotes = false;
    bool escape = false;
    size_t i;
    for (i = 0; i<strlen(cmd); i++)
    {
        if (escape)
        {
            escape = false;
        }
        else if (cmd[i] == '\\')
        {
            escape = true;
        }
        else if (cmd[i] == '"')
        {
            inQuotes = !inQuotes;
        }
        else
        {
            /* if we're in the unquoted part and the current character is one of */
            /* the redirection characters or the & for multiple commands then we */
            /* will no longer try to invoke the command directly                 */
            if (!inQuotes && (strchr("<>|&;", cmd[i]) != NULL))
            {
                noDirectInvoc = true;
                break;
            }
        }
    }

    if (!noDirectInvoc)
    {
        // execute special commands in the same process
        // we currently don't handle formats like " cd" or "'cd'" internally
        if (strcmp("cd", cmd) == 0 || strncmp("cd ", cmd, 3) == 0)
        {
            return sys_process_cd(context, cmd, rc);
        }
        if (strncmp("set ", cmd, 4) == 0)
        {
            return sys_process_export(context, cmd, rc, SET_FLAG);
        }
        if (strncmp("unset ", cmd, 6) == 0)
        {
            return sys_process_export(context, cmd, rc, UNSET_FLAG);
        }
        if (strncmp("export ", cmd, 7) == 0)
        {
            return sys_process_export(context, cmd, rc, EXPORT_FLAG);
        }
    }
    return false;
}
RexxObjectPtr RexxEntry systemCommandHandler(RexxExitContext *context, RexxStringObject address, RexxStringObject command)
{
    const char *cmd = context->StringData(command);
    const char *envName = context->StringData(address);

    RexxObjectPtr rc = NULLOBJECT;

    /* check for redirection symbols, ignore them when enclosed in double quotes.
       escaped quotes are ignored. */
    bool noDirectInvoc = false;
    bool inQuotes = false;
    bool escape = false;
    size_t i;
    for (i = 0; i<strlen(cmd); i++)
    {
        if (escape)
        {
            escape = false;
        }
        else if (cmd[i] == '\\')
        {
            escape = true;
        }
        else if (cmd[i] == '"')
        {
            inQuotes = !inQuotes;
        }
        else
        {
            /* if we're in the unquoted part and the current character is one of */
            /* the redirection characters or the & for multiple commands then we */
            /* will no longer try to invoke the command directly                 */
            if (!inQuotes && (strchr("<>|&", cmd[i]) != NULL))
            {
                noDirectInvoc = true;
                break;
            }
        }
    }

    if (!noDirectInvoc)
    {
        /* execute 'cd' in the same process */
        size_t commandLen = strlen(cmd);

        if (strcmp(cmd, "cd") == 0)
        {
            if (sys_process_cd(context, cmd, rc))
            {
                return rc;
            }
        }
        else if (commandLen >= 3)
        {
            char tmp[16];
            strncpy(tmp, cmd, 3);
            tmp[3] = '\0';
            if (strcmp("cd ",tmp) == 0)
            {
                if (sys_process_cd(context, cmd, rc))
                {
                    return rc;
                }
            }
            strncpy(tmp, cmd, 4);
            tmp[4] = '\0';
            if (strcmp("set ",tmp) == 0)
            {
                if (sys_process_export(context, cmd, rc, SET_FLAG)) /*unset works fine for me*/
                {
                    return rc;
                }
            }
            strncpy(tmp, cmd, 6);
            tmp[6] = '\0';
            if (Utilities::strCaselessCompare("unset ", tmp) == 0)
            {
                if (sys_process_export(context, cmd, rc, UNSET_FLAG))
                {
                    return rc;
                }
            }
            strncpy(tmp, cmd, 7);
            tmp[7] = '\0';
            if (Utilities::strCaselessCompare("export ", tmp) == 0)
            {
                if (sys_process_export(context, cmd, rc, EXPORT_FLAG))
                {
                    return rc;
                }
            }
        }
    }


    /****************************************************************************/
    /* Invoke the system command handler to execute the command                 */
    /****************************************************************************/
    // if this is the null string, then use the default address environment
    // for the platform
    if (strlen(envName) == 0)
    {
        envName = SYSINITIALADDRESS;
    }

    int errCode = 0;

#ifdef LINUX

    if (Utilities::strCaselessCompare("bash", envName) == 0)
    {
        errCode = system( cmd );
        if ( errCode >= 256 )
        {
            errCode = errCode / 256;
        }
    }
    else
#endif
    {
        int pid = fork();
        int status;

        if (pid != 0)                         /* spawn a child process to run the  */
        {
            waitpid ( pid, &status, 0);          /* command and wait for it to finish */
            if (WIFEXITED(status))               /* If cmd process ended normal       */
            {
                                                 /* Give 'em the exit code            */
                errCode = WEXITSTATUS(status);
            }
            else                              /* Else process died ugly, so        */
            {
                errCode = -(WTERMSIG(status));
                if (errCode == 1)                    /* If process was stopped            */
                {
                    errCode = -1;                   /* Give 'em a -1.                    */
                }
            }
        }
        else
        {
        	/* run the command in the child      */
            if (Utilities::strCaselessCompare("sh", envName) == 0)
            {
				#ifdef ANDROID
            		execl("/system/bin/sh", "sh", "-c", cmd, NULL);
				#else
                    execl("/bin/sh", "sh", "-c", cmd, NULL);
				#endif
            }
            else if (Utilities::strCaselessCompare("ksh", envName) == 0)
            {
                execl("/bin/ksh", "ksh", "-c", cmd, NULL);
            }
            else if (Utilities::strCaselessCompare("bsh", envName) == 0)
            {
                execl("/bin/bsh", "bsh", "-c", cmd, NULL);
            }
            else if (Utilities::strCaselessCompare("csh", envName) == 0)
            {
                execl("/bin/csh", "csh", "-c", cmd, NULL);
            }
            else if (Utilities::strCaselessCompare("bash", envName) == 0)
            {
                execl("/bin/bash", "bash", "-c", cmd, NULL);
            }
            else if (Utilities::strCaselessCompare("cmd", envName) == 0)
            {
                char * args[MAX_COMMAND_ARGS+1];      /* Array for argument parsing */
                if (!scan_cmd(cmd, args))             /* Parse cmd into arguments  */
                {
                    exit(1);
                }
                execvp(args[0], args);           /* Invoke command directly   */
                exit(1);                         /* we couldn't run the       */
            }
            else
            {
                execl("/bin/sh", "sh", "-c", cmd, NULL);
            }
        }
    }
    // unknown command code?
    if (errCode == UNKNOWN_COMMAND)
    {
        // failure condition
        context->RaiseCondition("FAILURE", context->String(cmd), NULL, context->WholeNumberToObject(errCode));
    }
    else if (errCode != 0)
    {
        // non-zero is an error condition
        context->RaiseCondition("ERROR", context->String(cmd), NULL, context->WholeNumberToObject(errCode));
    }

    return context->False();      // zero return code
}