I'm trying to implement a subshell in C. I already have a normal shell, which looks like this:
int status;
pid = fork();
if (pid < 0) {
exit(1);
}
else if (pid == 0) {
if (execvp(node->command.program, node->command.argv) < 0) {
exit(1);
}
}
else {
waitpid(pid, &status, 0);
}
I'm trying to figure out how a subshell works, and how it differs from the code above.
Thanks in advance.
Related
I'm a beginner to systems programming and I am currently trying to play around with basic server/client communication using sockets, pipes, etc
More specifically I want to be able to connect as a client and input something like '/bin/echo hello'. The server will then split the string into the command and its arguments, and run the command with a call to a function that calls execl(). For now I'm just testing exec call before trying to pass user input in. Why does the following fail with errno set to EFAULT: bad address?
int do_command(char *command) {
if(strcmp(command, "some_string") == 0) {
pid_t pid = fork();
if(pid == -1) {
perror("fork");
exit(1);
}
if(pid == 0) {
if (execl("/bin/echo", "/bin/echo/", "hello", (char*)NULL) == -1) {
perror("execl");
exit(1);
}
} else {
printf("parent\n");
}
}
}
But running the same code in main() runs just fine with an output of 'hello'
int main() {
pid_t pid = fork();
if(pid == -1) {
perror("fork");
exit(1);
}
if(pid == 0) {
if (execl("/bin/echo", "/bin/echo/", "hello", (char*)NULL) == -1) {
perror("execl");
exit(1);
}
} else {
printf("parent\n");
}
}
Is it not possible to run exec() system calls within functions? Thanks in advance.
I am trying to write a simple shell program, but have a small bug, which I can't seem to solve.
The program should be capable of launching a background process, but it fails to do so properly. It seems to work at first (program launches & the shell is still responsible) but fails at the second command.
In other words what happens is
launch some background process (browser) - works (launches and keeps working)
launch some regular process - works (lunches & finishes)
launch another process - doesn't work. The shell isn't responsive and waits until the background process is over.
Removing the following line:
waitpid(pid,NULL,0);
Solves this issue, but now all programs are 'background' (shell won't wait for anything to finish).
This is the complete function:
int launchprog(int background, char** arglist){
/* create a background process*/
if(background == 1){
pid_t pid = fork();
if(pid == 0){
/* child*/
arglist[-1] = NULL;
if (execvp(arglist[0], arglist) == -1) {
perror("Error in execvp, cannot init child process");
}
exit(1);
} else if (pid < 0) {
perror("Forking error");
exit(1);
}
return 1;
}
/* create a simple process*/
printf("shalom, %d,%d\n", background,getpid());
pid_t pid = fork();
if (pid == 0) {
/* child*/
struct sigaction saint;
saint.sa_handler = &int_signal_handle_exit;
sigemptyset(&saint.sa_mask);
saint.sa_flags = 0;
if (sigaction(SIGINT, &saint, 0) == -1) {
perror("Sigaction Error");
exit(1);
}
if (execvp(arglist[0], arglist) == -1) {
perror("Error in execvp, cannot init child process");
}
exit(1);
}
else if (pid < 0) {
perror("Forking error");
exit(1);
} else {
if (background == 0){ /* this should always be true*/
waitpid(pid,NULL,0);
}
}
return 1;
}
I have a function in C which creates a child process and makes it run execvp.
int Execute(char **arg)
{
pid_t pid;
int status;
if ((pid=fork()) == 0)
{
execvp(arg[0],arg);
perror("Execvp error");
exit(1);
}
else if (pid > 0)
{
waitpid(pid, &status, 0);
}
else
{
perror("Fork error");
exit(2);
}
}
Now I want to alter the function to actually run execvp several times (for example 5), and make the parent process wait for all the children to finish. Tried wrapping it all in for loop, but execvp gets executed just once. I know that basically execvp 'replaces' the current program code, but have no idea whether the iteration does not go on.
Thank you for your help!
First, loop around the process creation collecting the child PIDs
pid_t pid[5];
int i;
for (i = 0; i < 5; i++) {
if ((pid[i]=fork()) == 0) {
execvp(arg[0],arg);
perror("Execvp error");
_exit(1);
}
if (pid[i] < 0) {
perror("Fork error");
}
}
Second, loop around the waitpid call for every valid PID.
for (i = 0; i < 5; i++) {
if (pid[i] > 0) {
int status;
waitpid(pid[i], &status, 0);
if (status > 0) {
// handle a process sent exit status error
}
} else {
// handle a proccess was not started
}
}
I am making my own shell in C. This is my basic code for running a process:
pid_t childpid;
int status;
int ret = 0;
if (strcmp(line[0], "exit") == 0) {
return;
}
childpid = fork();
if (childpid >= 0) {
if (childpid == 0) {
ret = execvp(line[0], &line[0]);
if (ret == -1) {
printf("ERROR\n");
exit(0);
}
exit(ret);
} else {
waitpid(childpid, &status, 0);
ret = WEXITSTATUS(status);
}
} else {
perror("fork");
exit(-1);
}
Where line is a "string array" holding the commands to run.
Now say I want to run a background process - I have to use sigset. A parent doesn't wait for a backgrounded child process, right? How do I handle this without the child becoming a background process?
How can I have 3 processes running in parallel? Is this solution below correct?
In my solution I put some code to see the time elapsed and I think this is tunning in sequential mode. I need to put pid1, pid2 and pid3 running at the same time.
pid = fork();
if(pid == 0) {
//code...
exit(EXIT_SUCCESS);
} else if(pid > 0) {
pid1 = fork();
if(pid1 == 0) {
//pid1 code...
exit(EXIT_SUCCESS);
} else if(pid1 > 0) {
waitpid(pid1, &status, 0);
} else {
printf("Fork error %d.\n", errno);
}
pid2 = fork();
if(pid2 == 0) {
//pid2 code...
exit(EXIT_SUCCESS);
} else if(pid2 > 0) {
waitpid(pid2, &status, 0);
} else {
printf("Fork error %d.\n", errno);
}
pid3 = fork();
if(pid3 == 0) {
//pid3 code...
exit(EXIT_SUCCESS);
} else if(pid3 > 0) {
waitpid(pid3, &status, 0);
} else {
printf("Fork error %d.\n", errno);
}
waitpid(pid, &status, 0);
}
You keep waiting for one child to complete before you launch the next. Try something like:
for (int i = 0; i < 3; ++i)
{
pid = fork();
if (pid < 0)
error
if (pid == 0)
{
child does thing
exit
}
}
for (int i = 0; i < 3; ++i)
{
wait(&status);
}
EDIT
So just change your code to something like this and wait at the end.
if (pid2 == 0)
{
//pid2 code...
exit(EXIT_SUCCESS);
}
else
if (pid2 < 0)
{
printf("Fork error %d.\n", errno);
}
//....same outline for 3, etc.
Check out my wrap program, specifically the code for wrapc. It forks itself twice, execs one child into wrap, reads, writes to wrap, then reads back in the other child.
Your question is somewhat vague -- are you seeing 3 processes running in parallel or not?
the way your code is written you are exiting the child processes straight away.