Thread: execvp and ampersand?

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    13

    execvp and ampersand?

    Hi,

    Currently, I have a shell which uses fork and execvp to execute commands. However, I am wondering how I can implement the ampersand feature of unix. ie program will not wait for process to complete.

    for example if i execute: emacs &
    the program should return to the command prompt without waiting for emacs to close!

    Thanks for any help,

    slevytam

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    You'll want to look into using fork().
    If you understand what you're doing, you're not learning anything.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    This is the code I am using currently...

    How might it need to be modified?

    Thanks,

    slevytam

    pid = fork();
    if (pid < 0) {
    fprintf(stderr, "ERROR: cannot fork!\n");
    return(-1);
    }
    else if (pid) {
    /* parent */ /* wait for the child to exit */
    pid = wait(&status);
    /* printf("waited for %d\n", pid); */
    }
    else {
    /* child */
    rc = execvp(mycmds[commandIndex].commandFile, mycmds[commandIndex].argv);
    }

  4. #4
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Well, you want to avoid calling wait(), otherwise it won't be running "in the background". Well it will, but the parent will just be sitting there waiting for it to finish instead of dropping you back at your prompt so you can do something else while the child does its thing.
    If you understand what you're doing, you're not learning anything.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    Im sorry could you explain this a little more.

    The way the code is right now it does wait for the function to finish.

    ie if I call sleep 10, i won't back to the command prompt for 10 seconds.

    If do not call wait and do something like ls -lt & it outputs the directory but then hangs and doesn't like me do anything.

    Thanks,

    slevytam

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    I've changed the code to look like this:

    pid = fork();
    if (pid < 0) {
    fprintf(stderr, "ERROR: cannot fork!\n");
    return(-1);
    }
    else if (pid) {
    if(mycmds[commandIndex].waitMode!=1){
    pid = wait(&status);
    printf("waited\n");
    }
    else{
    printf("did not wait\n");
    }
    }
    else {
    execvp.......
    ...
    }

    However, if I try to execute a command such as ls -lt &
    i run into a problem.

    What happens is that the code does not wait and returns to a prompt; however, when the results of ls -lt are outputted, they are outputted as input to the prompt....

    here is a captured script.

    /gaul/s1/student/2000/slevytam/CS305B/ASN1>ls -lt &
    did not wait
    /gaul/s1/student/2000/slevytam/CS305B/ASN1>total 86
    -rwx------ 1 slevytam 12244 Feb 1 18:33 a.out
    -rw------- 1 slevytam 10661 Feb 1 18:33 gosh.c
    -rw------- 1 slevytam 10619 Feb 1 17:59 shellbackup4.c
    -rw------- 1 slevytam 9557 Feb 1 17:49 gosh.c~
    -rw------- 1 slevytam 7721 Feb 1 15:40 shellbackup3.c
    -rw------- 1 slevytam 111 Feb 1 15:33 test4.txt
    -rw------- 1 slevytam 101 Feb 1 15:32 test3.txt
    -rw------- 1 slevytam 91 Feb 1 15:29 test2.txt
    -rw------- 1 slevytam 3392 Feb 1 15:22 shellbackup1.c
    -rw------- 1 slevytam 7334 Feb 1 15:22 shellbackup2.c
    -rwx------ 1 slevytam 10576 Jan 31 19:27 gosh
    -rw------- 1 slevytam 3392 Jan 31 18:34 shell.c
    drwx------ 2 slevytam 512 Jan 31 18:03 testdir
    -rw------- 1 slevytam 2545 Jan 31 17:54 shell.c~

    Malformed Command
    ERROR: tokenize()
    /gaul/s1/student/2000/slevytam/CS305B/ASN1>quit

    Thanks!

  7. #7
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    It should be really simple. You already fork() to call commands. All you have to do is not call wait() if you want the parent to return to doing its thing before the child exits.
    If you understand what you're doing, you're not learning anything.

  8. #8
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    What happens is that the code does not wait and returns to a prompt; however, when the results of ls -lt are outputted, they are outputted as input to the prompt....
    That isn't how execvp() works. Are you sure it's not just displaying to the screen after the prompt is printed? Just because the output shows up at the end of the prompt doesn't mean it's actually being accepted as input by the parent. "ERROR: tokenize()" doesn't give me enough information. Maybe you can make that error show what the inputted command was for debugging purposes.
    If you understand what you're doing, you're not learning anything.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    It seems as though what happens is that I(and my program) doesn't know how to reprint the command line prompt and current buffer to screen when the process finishes. In unix if I had something on the command prompt it redisplays this when ls -lt & finishes.

    Can you offer any insight on how to do this?

    Thanks!

  10. #10
    Registered User axon's Avatar
    Join Date
    Feb 2003
    Posts
    2,572
    I believe this thread belongs in the unix programming board. Anyways, search for a simple shell source code (there are a lot of them out there), look at the code, and try figuring it out.

    some entropy with that sink? entropysink.com

    there are two cardinal sins from which all others spring: Impatience and Laziness. - franz kafka

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    I have tried searching sample code but have not found a script that is smart enough to catch when the background process ends or displays output. I need to be able to catch this in order to reprint the command prompt.
    Is there a way to do this?
    Thanks!

  12. #12
    Registered User axon's Avatar
    Join Date
    Feb 2003
    Posts
    2,572
    show me the code of how you're detecting that a process is indeed running in the background.

    some entropy with that sink? entropysink.com

    there are two cardinal sins from which all others spring: Impatience and Laziness. - franz kafka

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    13
    Well unfortunately, I have no idea how to do this... Currently, my main method looks like this....

    for(; {

    /* display prompt, read input */
    printf("%s%s", getcwd(NULL,64),">");
    fgets(buffer, 256, stdin);

    removeNull(buffer);

    /* if buffer equals quit then terminate program */
    if (!strcmp(buffer, "quit")) {
    exit(0);
    }

    /* tokenize buffer, store in mycmds */
    rc=tokenize(buffer, mycmds);
    if (rc < 0) {
    fprintf(stderr, "ERROR: tokenize() on %s\n", buffer);
    } else {

    /* tokenize worked, run the command */
    rc = run(mycmds);
    if (rc < 0) {
    fprintf(stderr, "ERROR: run()\n");
    }

    }

    /* clear command struct */
    for (i=0; i<2; i++) {
    init(&mycmds[i]);
    }

    }


    My run function looks like this:
    int run(struct command *mycmds) {
    int pid;
    int rc;
    int status;
    int ofd, ifd;
    int commandIndex=0;
    int fds[2];

    pid = fork();
    if (pid < 0) {
    fprintf(stderr, "ERROR: cannot fork!\n");
    return(-1);
    }
    else if (pid) {
    /* if & was found then do not wait for function to finish */
    if(mycmds[commandIndex].waitMode!=1){
    pid = waitpid(pid,&status,WUNTRACED);
    //printf("waited\n");
    }
    else{
    //printf("did not wait\n");
    }
    }
    else {


    /* Execute command */
    rc = execvp(mycmds[commandIndex].commandFile, mycmds[commandIndex].argv);

    /* Report any error */
    if (rc < 0) {
    perror("execvp: ");
    }

    exit(1);
    }
    return(1);
    }

    Thanks!

  14. #14
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    I think you'll need to catch SIGCHLD. That's the signal raised when a child process exits.
    If you understand what you're doing, you're not learning anything.

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    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.

Popular pages Recent additions subscribe to a feed