Thread: problems with fork() and execve()

  1. #1
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92

    problems with fork() and execve()

    I'm writing a small utility that uses the nidump command (I'm on OS X, and a lot of info on the system is located in the NetInfo database - that can be reached through the command line via the nidump command), fork() an execve(). The problem is that no file is created and no output is collected from NetInfo; The application failes completely.

    The filename is given by the user (argv[1]), and the exec funtion I chose to execute the nidump command, with arguments, was execve. I'm not sure it's the right one to use, though, as it doesn't seem to work right (maybe it's just me that's a bit rusty). Anyway, here's some code:
    Code:
    int main(int argc, char *argv[]) {
     
        int PID, status, waitsignal;
        char *args[] = {">> . ", argv[1], NULL}; // this isn't working correct
        
        printf("OS X pssword file dumping\n");
        
        if(argc < 2) {
            printf("usage: %s <filename>\n", argv[0]);
            exit(0);
        }
        
        PID = fork();
        
        if(PID == -1) {
            
            perror("fork error");
            exit(EXIT_FAILURE);
            
        } else if(PID == 0) {
            
            printf("child pid: %d\n", getpid());
            execve("/usr/bin/nidump passwd", args, NULL); // this isn't working correct either
            
            if(errno == -1) {
                perror("error");
            } else {
                //printf("nidump process completed!\n");
            }
    
    [...]
    I know there's something wrong with the args variable and the execve function, but I can't figure it out. Where should the argument for the command (nidump) be placed? Should I use another exec function instead?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    The problem is, you're treating exec like system()

    None of that friendly stuff like command line parsing into parameters, and I/O redirection is available (Wait a minute, I've just said that in another post).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    Yeah, I guess I'm treating exec like system(), but I know it can be used that way. Here's some of my other code:
    Code:
    [...]
    char *argv[] = {"ping", "-c 5", ping_host, NULL};
    
        ping_pid = (int)fork();
    
        if(ping_pid == -1) {
    
            perror("cannot execute command, an error occured\n");
            exit(EXIT_FAILURE);
    
        } else if(ping_pid == 0) {
    
            // child prosess
            execve("/sbin/ping", argv, NULL);
    [...]
    - Where execve is used like system(). Since this works, I figured the nidump command with parameters would work too. Anyone got any ideas on what I'm doing wrong?

    Edit: After re-reading your post Salem, I realized you said it wasn't possible to re-direct I/O. Is there another way to do what I want to do (without using system())?
    Last edited by kristy; 12-20-2003 at 04:25 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > I figured the nidump command with parameters would work too
    But only if you put "passwd" into args

    In fact, it should be more like this
    Code:
    char *args[] = {
    "/usr/bin/nidump",
    "passwd"
    NULL};
    
    ...
    
    execve(args[0], args, NULL);
    > I realized you said it wasn't possible to re-direct I/O
    No, I said it was tricky in DOS
    In unix/linux, its much easier

    Code:
        } else if(PID == 0) {
            int fd = open( argv[1], O_WRONLY ); // This is >, if you want >> bitwise the flag with O_APPEND
            close( 1 );  // existing stdout is no more
            dup( fd );  // stdout is now fd
            printf("child pid: %d\n", getpid());
            execve(args[0], args, NULL);
            if(errno == -1) {
                perror("error");
            }
        }
    > char *argv[] = {"ping", "-c 5", ping_host, NULL};
    It might work, though I would have said
    char *argv[] = {"ping", "-c", "5", ping_host, NULL};
    Remember, every white space separates the args on the command line (as you type it in), and this must be reflected in any argv[] you construct.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    UNIX chick
    Join Date
    Mar 2003
    Posts
    92
    Code:
        } else if(PID == 0) {
            int fd = open( argv[1], O_WRONLY ); // This is >, if you want >> bitwise the flag with O_APPEND
            close( 1 );  // existing stdout is no more
            dup( fd );  // stdout is now fd
            printf("child pid: %d\n", getpid());
            execve(args[0], args, NULL);
            if(errno == -1) {
                perror("error");
            }
        }
    Thanks a million for this! I never knew you could do this that easy.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fork, execv, spawn, or something else?
    By DavidP in forum C++ Programming
    Replies: 8
    Last Post: 01-26-2009, 04:25 PM