简体   繁体   中英

simple shell linux C implementation, redirecting stdout with freopen

I'm attempting to have my shell implementation redirect stdout and stdin from the console to an output file by using freopen, but when I attempt to do this by doing something like "ls > outfile.txt", my program continues to wait for the child process until I force stop it, after force stopping it, the output file is successfully created, but I'm wondering what it is I need to do to fix this problem, do I need to use fclose() afterwards? Below is part of my code, if you need more of it let me know, but basically overrideOut is an int I set to 1 if '>' is the 2nd to last arg in the command line. I then try to split off the > and path arguments to just call ls using execvp, but I'm not sure if I'm doing this correctly. Thanks everyone.

while(1){

if((pid = fork()) != 0){


    wait(&status);
    printf("%i", overrideOut);
    printf("Myshell> ");
    fgets(buffer, 512, stdin);

    if(buffer[strlen(buffer)-1] == '\n'){
        buffer[strlen(buffer)-1] = '\0';
    }else{
        printf("\n");
        return 0;
    }
    argv[0] = strtok(buffer, " \n\0");

    for(argc=1; argv[argc-1]; argc++){


        if(!strcmp("&", argv[argc-1])){
        bg = 1;
        }
        if(!strcmp(">", argv[argc-1])){
        overrideOut = 1;
        }
        if(!strcmp(">>", argv[argc-1])){
        appendOut = 1;
        }
        if(!strcmp("<", argv[argc-1])){
        overrideIn = 1;
        }
        if(!strcmp("<<", argv[argc-1])){
        appendIn = 1;
        }

        argv[argc] = strtok(NULL, " \n\0");

    }




    if(!strcmp("exit", argv[0])) exit(0);



    printf("Waiting for child (%d)\n", pid);        
    printf("Child (%d) finished\n", pid);
    if(overrideOut == 1){           
        freopen(argv[argc-2], "w+", stdout);
        //clear the > and path args to just call ls with execvp
        argv[argc-2] = strtok(NULL, " \n\0");
        argv[argc-3] = strtok(NULL, " \n\0");
        //for(argc=0; argv[argc-1]; argc++)
        //printf("argv[%d] = %s, ", argc, argv[argc]);
    }else if(appendOut == 1){
        freopen(argv[argc-2], "a", stdout);
        argv[argc-2] = strtok(NULL, " \n\0");
        argv[argc-3] = strtok(NULL, " \n\0");
    }else{
    freopen("/dev/tty", "rw", stdin);
    }

}else{


if(buffer[0] != '\0'){

        execvp(argv[0], argv);
            printf("error\n");
            return 0;
        }else{
            return 0;
        }
    }
}

You may want to study the implementation of some simple free software shell like sash . You probably want to do the redirection after the successful call to fork(2) and you could use dup2(2) with STDOUT_FILENO (which is more human-readable than just the constant 1).

I recommend working on integer file descriptors , not on FILE* handles, when coding a shell.

You probably should not redirect files in the parent shell process (only in the child process). And you probably should call pipe(2) in the parent shell process (perhaps not in the child process).

You forgot to handle the failure of fork in your code.

Read Advanced Linux Programming which explains quite well the basic concepts.

Your code snippet is incomplete: it is very important to show where and how you are calling fork (and perhaps also show how you call execve ). Don't forget to test all three cases: failure (with the result of fork being <0 ), child process ( ==0 ), parent shell process( >0 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM