Can't get control back after execvp and wait() - c

I'm coding a small shell that must execute my commands that I parse.
f is a char** like this: [ls][-la]
p is the same, used like this: [wc]
So I tried to pipe ls -la in wc.
My probleme is that when I execute "ls -la | wc && date", which works well for the pipe, my minishell get closed and it doesn't execute "date". I used the wait function to wait for it to finish but doesn't do anything. Looks like it's stuck and exit just after the 2nd execvp.
My arrays ends well by NULL.
ls -la | wc is well executed but I get back to bash after this.
I've tried with execlp and execl but I think this is not the probleme considering that I need options of my first argument (ls + -la).
Could you help me please ?
Thanks in advance :)

All forms of exec never return; they replace the currently running image with the indicated executable. The key word here is "replace".
The only circumstance in which the statement following a call to exec* gets executed is if the exec fails (for example, if it cannot find the executable).

Related

execl + find + -exec: missing argument to `-exec'

I am trying to run execlp with find ... -exec ..., and the find program consistently tells me:
find: missing argument to `-exec'
What could be wrong? When I run find with these arguments on my shell, it succeeds.
My function calls follow (after looking at related SO threads, I have tried several arrangements of the argmuments):
execlp("find","find","/home/me","-exec","/usr/bin/stat", "{}", "\\;",NULL);
execlp("find","find","/home/me","-exec","/usr/bin/stat", "'{}'", "\\;",NULL);
execlp("find","find","/home/me","-exec","/usr/bin/stat", "{}", "';'",NULL);
execlp("find","find","/home/me","-exec","/usr/bin/stat {} \\;",NULL);
When you execute the command from C, you don't need the \ before ;
Using this syntax should work
execlp("find","find","/home/me","-exec","/usr/bin/stat", "{}", ";",NULL);
When on the shell, ; marks the end of a command, and has to be escaped. execlp doesn't go through the shell to execute a command, it does it immediately.
Edit -- you actually only do one find so this part is not necessary
Moreover, the exec family replaces the current process with the requested command. So only the first execlp will be executed.
A solution is to fork() for each find (one by one, waiting for the child process to end, otherwise the output will be a mix of all results).

Logic to determine whether a "prompt" should be printed out

Seems like a basic idea: I want to print out a prompt for a mini shell I am making in C. Here is an example of what I mean for the prompt:
$ ls
The $ being the "prompt". This little mini shell I am making supports backgrounding a process via the normal bash notation of putting a & symbol on the end of a line. Like $ ls &.
My logic currently is that in my main command loop, if the process is not going to be backgrounded then print out the prompt:
if(isBackground == 0)
prompt();
And then in my signal handler I print out the prompt using write() which covers the case of it being a background process.
This works fine if the background command returns right away like with a quick $ ls &, but in the case of something like $ sleep 10 & the shell will look like it is being blocked as the prompt will not be printed out until it hits the signal handler.
I can't figure out how to fix this because I don't know when the background process will end which means that the signal handler somehow needs to be saying when to print the new prompt because if the background process happened to have an output, it would output and then there would no longer be a prompt.
How can I resolve this problem? Is there a better way to do this that I'm not thinking of that could resolve my problem?

Using execvp with Input,Output and redirection

In a C program, let's say i wann use Exec functions for executing a given program, for example if i wanna just try ls -l i'll do something like
args[0]="ls";
args[1]="-l";
args[2]=NULL;
...
execvp("ls", args);
and it's all fine. Now what if i wanna also add the redirection to a file (or to stderr)?
I'm stuck, it's obvious that adding >log.txt as a 3rd entry in the array won't work, but I don't know how to proceed.
And also, what if I wanna pass some Input parameters? What if i wanna execute a GCC command like "gcc -o out in redirection>log.txt" ?
[update from comment:]
It's a C program that simulate a shell which can "run strings", string that contains a command, a list o parameters, input and a redirection.
Just set up your file descriptors as the exec-d process shall find them and then do the exec.
For that you need open, dup2 and close.
All functions in the exec-family just replace the current process with whatever one you say.
Run the command in a shell:
char * args[] = {
"sh",
"-c",
"ls -l >out.ls 2>err.ls <in.ls",
NULL
};
...
execvp(args[0], args);
perror("execvp() failed");

What is happening internally when we called any shell commands

Can any one please help me in understanding the code/Steps flow internally when we are calling any shell command. For example suppose I run the follwoing on bourne shell:
ls -l | grep -r "string"
What are the function calls happening internally?
As far as I know it will call some execv family functions internally. But can anyone tell me what are the other function call it will make and what will be the sequence of that?
You can take a look yourself at what happens by using the strace utility. Run it with:
strace sh -c 'ls -l | grep -r "string"'
This will run a shell that in turn will run your command, and at the end strace will print out what's happening behind the scenes in terms of system calls.
In short:
parsing and lexical analysis
expansion
brace expansion
tidle expansin
variable expansion
artithmetic and other subrstitutions
word splitting
filename generation/expansion
execution
bash fork itself (once for every command)
restore the SIGINT handler to default
opens pipes between commands (dups stdin, stdout)
closes original stdin/stdout
exec each child with the command
parent bash waits...
maybe others will add more precise "steps"...

What does execvp actually do? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Writing a shell - how to execute commands
I've been tasked with writing a shell in C. So far I understand that execvp will try to run the program in arg1 with arg2 as parameters. Now it seems that doing this
execvp ("ls", args); //assume args is {"ls", ">", "awd.txt"}
is not equivalent to typing this in the console
ls > awd.txt
I realize that I need to use freopen to achieve the same results but I'm curious what execvp is doing.
The exec family of functions are ultimately a system call. System calls go straight into the kernel and typically perform a very specific service that only the kernel can do.
Redirection, on the other hand, is a shell feature.
So, when one types ls > awd.txt at a shell, the shell first does a fork(2), then it closes standard output in the child, then it opens awd.txt on file descriptor one so that it's the new standard output.
Then, and only then, the shell will make an exec-family system call.
In your case you simply passed the strings > and awd.txt to the exec system call, and from there to ls. BTW, be sure you terminate your execvp arg array with a null pointer.
Note: As you can see, the redirection operators are never seen by the executed program. Before Unix, directing output to a file had to be done by every program based on an option. More trivia: most programs never know they were redirected, but ironically, ls does check to see if its output is a tty, and if so, it does the multi-column formatted output thing.
It's executing ls with 2 arguments: > and awd.txt. It is equivalent to running:
'ls' '>' 'awd.txt'
You can pass your command directly to the shell:
char * const args[] = { "sh", "-c", "ls > awd.txt", NULL};
execvp("/bin/sh", args);
But it doesn't seems like a good idea.

Resources