Cannot execute command in my own shell

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
Check your return from execlp(). That should give the answer.
> strcpy(argv[0], cmd.c_str());
¿how much space do you have in `argv[0]'?
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
let me check...

ne555 argv[0] is length of cmd + 1
kooth it return -1
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
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);
@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!
thanks everyone, ! the bin/bash works fine...
but i am supposed to use system calls :(
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
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
There is a system call name chdir() - (Try man chdir).
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?
This may sound circular, but fork and exec ...
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.
how about this

string prog="./hello";

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

thanks
Topic archived. No new replies allowed.