Jump to content

Execute A Shell Command For An External .exe File

- - - - -

  • Please log in to reply
9 replies to this topic

#1
rsnider19

rsnider19

    Learning Programmer

  • Members
  • PipPipPip
  • 34 posts
Ok, so I am doing some android app development. I have exported a database I created and I am running it through sqlite3.exe so I can view it and stuff. I run from the shell "sqlite3.exe TestDB" and it then gives me "sqlite> _" so i can run my commands manually. I want to be able to pass commands through here as well. The following gets me exactly where I want to be where I can send sqlite commands:

system("C:\\Users\\Rob\\Desktop\\sqlite.exe C:\\Users\\Rob\\Desktop\\TestDB");

I tried the following in hopes of passing a simple select statement to the sqlite3 program:

system("C:\\Users\\Rob\\Desktop\\sqlite.exe C:\\Users\\Rob\\Desktop\\TestDB && select * from TestTable");

It doesn't actually get passed and I believe it is because It is waiting for sqlite proggy to end so it can move on and then try the select statement. So, how can I send the select statement to sqlite instead?

#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,717 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
If I'm reading this right--and I'm generalizing this here--you want to start up a program, then send commands to the program as if you were typing them directly at the terminal?
sudo rm -rf /

#3
rsnider19

rsnider19

    Learning Programmer

  • Members
  • PipPipPip
  • 34 posts
Yes

#4
abzero

abzero

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 217 posts
you need to redirect the input streams. Or see if the exe has a mode in which it reads commands from a file, if it does you can write a temporary file execute the binary then delete the file.

#5
rsnider19

rsnider19

    Learning Programmer

  • Members
  • PipPipPip
  • 34 posts
How do i redirect the input stream? I tried piping, but I may have been doing it wrong, or its the wrong idea :P

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,717 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
No, piping is exactly how you want to go. Gimme an hour and I'll get you some goodies.

EDIT (Ten minutes late...)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>

#define READFD      0
#define WRITEFD     1
#define STDIN       0
#define STDOUT      1
#define STDERR      2

/*
FORK_OBEDIENT_CHILD
Creates a child process, redirecting the STDIN, STDOUT, and STDERR descriptors
so that the parent can read from STDOUT and STDERR and write to STDIN.

Inputs:
    const char *program     Path to the program we want to execute
    char* const env[]       Environment for the child program
    char* const args[]      Arguments to pass to the child program

    Note that env[] and args[] may be of any length, but MUST have a null point-
    er as the last element. Otherwise execve() will gag and your computer will
    most likely catch fire and/or explode. I'm not responsible for any injuries
    resulting from your negligence.

Outputs:
    int *child_stdin        File descriptor to the child's STDIN. Write-only.
    int *child_stdout       File descriptor to the child's STDOUT. Read-only.
    int *child_stderr       File descriptor to the child's STDERR. Read-only.
    
    These integer file descriptors will only work with the kernel's read(),
    write(), and other similar functions. Any of the C stdio stuff won't be able
    to handle it. However, you can do this:
    
    FILE *fstdin = fdopen(*child_stdin, "w");
    FILE *fstdout = fdopen(*child_stdout, "r");
    FILE *fstderr = fdopen(*child_stderr, "r");
    
    DO NOT SIMPLY USE stdin, stdout, OR stderr AS YOUR VARIABLES. You'll destroy
    your own descriptors.
    
    If you're expecting binary data or something else, change the mode to suit
    your needs. I'm almost 100% sure that you should NOT close the integer
    descriptors you get back from this function. In either case, once your child
    has exited, you may close the descriptors with the usual fclose(). Closing
    fstdout or fstderr shouldn't do too much, but closing fstdin would probably
    cause the child to crash or at least hang indefinitely if it ever tries to
    read from it after you've closed it on your side.
    
Return value:   PID of the child process, or -1 if an error occured. Should the
                function return -1, the values of the child descriptor outputs
                are undefined.
*/
pid_t fork_obedient_child(int *child_stdin, int *child_stdout, int *child_stderr,
                    const char *program, char* const env[], char* const args[])
{
    int stdin_pipe[2], stdout_pipe[2], stderr_pipe[2];
    pid_t pid;
    
    /* gag on bad parameters */
    if( !child_stdin || !child_stdout || !child_stderr || !program )
        return -1;
    
    /* create pipe pairs we'll use later. if pipe() returns -1 then it failed.*/
    if( pipe(stdin_pipe) == -1 )
        return -1;

    /* create STDOUT pair */
    if( pipe(stdout_pipe) == -1 )
    {
        close(stdin_pipe[0]);
        close(stdin_pipe[1]);
        return -1;
    }
    
    /* create STDERR pair */
    if( pipe(stderr_pipe) == -1 )
    {
        close(stdin_pipe[0]);
        close(stdin_pipe[1]);
        close(stdout_pipe[0]);
        close(stdout_pipe[1]);
        return -1;
    }
    
    pid = fork();
    if( pid == -1 )
        /* failed to fork */
        return -1;
    else if( pid == 0 )
    {
        /* CHILD CODE
        We're never going to write to STDIN nor read from STDOUT or STDERR, so
        we should close those file descriptors. */
        close(stdin_pipe[WRITEFD]);
        close(stdout_pipe[READFD]);
        close(stderr_pipe[READFD]);
        
        /* The operating system opens new file descriptors for the new process
        for STDIN, STDOUT, and STDERR. We don't want those, as the parent pro-
        gram can't access them. Close them all. */
        close(STDIN);
        close(STDOUT);
        close(STDERR);
        
        /* What we do want is for the stdin/stdout descriptors to be associated
        with our pipe descriptors. Since STDIN, STDOUT, and STDERR are always
        descriptors 0, 1, and 2 respectively, this is quite easy. dup2() opens
        the second descriptor argument as an independent clone of the first. So
        if we clone our pipe descriptors (stdin_pipe[READFD], etc.) into the
        fixed STDIN, STDOUT and STDERR descriptors, then the parent program can
        communicate with the child via the descriptors returned in child_stdin
        child_stdout and child_stderr. */
        dup2(stdin_pipe[READFD], STDIN);
        dup2(stdout_pipe[WRITEFD], STDOUT);
        dup2(stderr_pipe[WRITEFD], STDERR);
        
        /* Now that we've cloned the descriptors, we don't need the originals
        that we inherited from the parent anymore. Note that this won't affect
        the parent at all, because the child has its own copies of the descrip-
        tors. Closing these won't close them on the parent. */
        close(stdin_pipe[READFD]);
        close(stdout_pipe[WRITEFD]);
        close(stderr_pipe[WRITEFD]);
        
        /* Execute the child process */
        execve(program, args, env);
        
        /* Everything after the EXEC() call should never execute unless the call
        failed. If it does, then we have a problem and should crash the child.
        If you want to stick any special error-handling code, do it here. Just
        remember that the output of whatever you print will now go to the parent
        program, not the terminal.*/
        exit(-1);
        
    }
    else
    {
        /* PARENT CODE
        We're not going to read from the child's STDIN nor write to its STDOUT.
        That's the child's job. We're going to do the opposite, in fact. We
        read from the child's STDOUT so we know what it's doing, and write to
        its STDIN so we can tell it what to do. */
        close(stdin_pipe[READFD]);
        close(stdout_pipe[WRITEFD]);
        close(stderr_pipe[WRITEFD]);
        
        /* Set the file descriptor variables we're returning. These will be used
        to communicate with the child process. Remember, you write to the 
        stdin descriptor, and read from the stdout/stderr descriptors. */
        *child_stdin = stdin_pipe[WRITEFD];
        *child_stdout = stdout_pipe[READFD];
        *child_stderr = stderr_pipe[READFD];
        return pid;
    }
    
    /* Should never get here, but the compiler complains unless we put a return
    statement at the end of the function. */
    return -1;
}
Try that. Make sure you adhere to the rules I outlined in the documentation.

By the way...for you old CodeCallers out there who still remember the days when we had syntax highlighting...what happened to that?

Edited by dargueta, 02 July 2010 - 12:07 AM.
Added code/nostalgic note

sudo rm -rf /

#7
rsnider19

rsnider19

    Learning Programmer

  • Members
  • PipPipPip
  • 34 posts
Thanks a lot! I was able to incorporate this and get what I need done!

#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,717 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
So it works, then?
sudo rm -rf /

#9
Guest

Guest

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 3,414 posts

dargueta said:

By the way...for you old CodeCallers out there who still remember the days when we had syntax highlighting...what happened to that?
I don't know, I'm assuming it got lost in some stupid update, and James won't fix it. (He never fixes anything)

For C code though, you can wrap it in [noparse]
[/noparse] tags and it should look great.

Example:
    /* gag on bad parameters */
    if( !child_stdin || !child_stdout || !child_stderr || !program )
        return -1;
    
    /* create pipe pairs we'll use later. if pipe() returns -1 then it failed.*/
    if( pipe(stdin_pipe) == -1 )
        return -1;
Very nice code by the way. I will definitely find it useful. +rep
Root Beer == System Administrator's Beer
Download the new operating system programming kit! (some assembly required)

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,717 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Thanks!
sudo rm -rf /




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users