Cannot execute command in my own shell

May 30, 2015 at 11:09am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
while(true){

        cout<<"Shell$ ";
        getline(cin,cmd);

        strcpy(argv[0], cmd.c_str());

        if(cmd=="exit" ){
                exit(EXIT_SUCCESS);

            }

         pid_t pid=fork();
            if(pid==0){
                //exec
                execlp("/usr/bin/", argv[0]);//here it does not display the out

            }


            //wait for child
            else{
                wait(pid);
                }
            }


shell$ ls
shell$ shell$
Last edited on May 30, 2015 at 11:12am
May 30, 2015 at 1:49pm
Check your return from execlp(). That should give the answer.
May 30, 2015 at 2:54pm
> strcpy(argv[0], cmd.c_str());
¿how much space do you have in `argv[0]'?
May 30, 2015 at 4:24pm
Isn't the first argument of execlp usually the executable to run rather than a directory? (as ls is a shell comment the exe is the shell, which means you arg vector needs to be sorted out, too.)

Andy

PS See (e.g.)

Running a shell command with execlp() from a string
http://stackoverflow.com/questions/21568524/running-a-shell-command-with-execlp-from-a-string
May 31, 2015 at 5:55am
let me check...

ne555 argv[0] is length of cmd + 1
May 31, 2015 at 6:00am
kooth it return -1
May 31, 2015 at 8:10am
Why do you want to copy the command to argv[0] and then pass the copy? Pass it directly.

Read the man page for execlp. In particular:
The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the filename associated with the file being executed. The list of arguments must be terminated by a NULL pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
    std::string cmd ;
    while( std::cout << "Shell$ " && std::getline( std::cin, cmd ) && cmd != "exit" )
    {
        if( pid_t pid = fork() ) 
        {
            if( pid == -1 ) std::cerr << "fork failed\n" ;
            else
            {
                int status ; 
                wait( &status ) ; 
                std::cout << "***status: " << status << '\n' ;
            }
        }
        
        else 
        {
            std::cout << cmd << '\n' << std::flush ;
            
            // "If the -c option is present, then commands are read from string" - bash man page
            if( execlp( "/bin/bash", "/bin/bash", "-c", cmd.c_str(), (char*)nullptr ) == -1 ) 
                std::cerr << "exec failed\n" ;
        }
    }
}

http://coliru.stacked-crooked.com/a/1cc59ec13eb3af37
May 31, 2015 at 8:12am
The fact an exec function returns at all indicates an error.
As andywestken mentioned the first argument to execlp is not a directory but the executable, for example execlp("/bin/ls", "/bin/ls", "-al", 0);
May 31, 2015 at 1:11pm
@naraku9333 exactly! That's where I was going -- I wanted the OP to read the man pages and have his own "a Ha!" moment.

JLBorges: Right on!
Jun 1, 2015 at 7:37am
thanks everyone, ! the bin/bash works fine...
Jun 1, 2015 at 7:52am
but i am supposed to use system calls :(
Jun 1, 2015 at 8:00am
but i am supposed to use system calls :(

You mean you have to write code to do what ls (etc) does rather than invoking it with execlp() ??

Andy
Jun 1, 2015 at 8:14am
no, I am to use execlp but for example pipes, and chdir I have to use by system calls...so for example the user types cd /usr/bin it must use chdir in cpp code to change directory....but with bash as you shown, using cd only does the job
Last edited on Jun 1, 2015 at 8:15am
Jun 1, 2015 at 12:29pm
There is a system call name chdir() - (Try man chdir).
Jun 1, 2015 at 2:05pm
thanks, I used that already...but now I need to implement a functionality in my shell that knows how to launch new programs in the foreground and the background.

any hints?
Jun 2, 2015 at 3:36am
This may sound circular, but fork and exec ...
Jun 2, 2015 at 7:27am
Remember, a foreground task can be suspended, and a foreground task can be sent to the background and vice versa.

With that in mind, it should be obvious that foreground tasks should be started the same way as background tasks.
Jun 2, 2015 at 9:21am
how about this

string prog="./hello";

execlp(prog, prog, (char*)NULL);

thanks
Topic archived. No new replies allowed.