A simple shell written in C exits after using pipe
I have copied a project from stackoverflow and am simply trying to understand why certain behavior is happening. I am a total beginner at C, so please be kind. (original link: https://stackoverflow.com/questions/...ith-pipes-in-c).
What follows is a simple shell written in C, it's major feature is that it is able to process the pipe '|' symbol and process the stdin and stdout as expected in a standard shell like bash. What I am failing to understand is why the program exits after the command is executed (and only if a | is used). According to the person who provided the answer on stackoverflow, another fork() is required for the while(1) loop to continue, but because two execvp() calls are made in the execpipe() function, the while(1) loop currently executes the pipe and then exits. I am very grateful at this post, as I am trying to ascertain how a shell like bash actually implements operators like pipe(|), but I've been racking my brain for days on this and have made no progress in understanding even where to start on solving this issue of the program exiting after a pipe command is executed... I have extensively documented in the notation what I believe is happening in each process, and again, am very much a beginner and am just trying to understand how to program a shell with pipes for my own understanding. Could someone please explain to me where this necessary additional fork() call should be placed within the code and how it should be implemented(meaning, are there any additional calls for pid_t, for example?)? Sorry for all the verbosity, but I'm at a loss here and any help would be greatly appreciated. Code:
/* https://stackoverflow.com/questions/33912024/shell-program-with-pipes-in-c */ |
The way it's coded, once a child exits, the parent exits. That's the answer. The rest is additional follow-up.
That's what those return statements do. There are two mismatching return values for the parent return cases by the way. Not a problem but if you're checking those you won't be able to discern if things exited as an error vs not. Make the parent case returns some other value. |
Quote:
Again, I'm just breaking this thing down trying to learn from it, but my level of understanding of the basics of C and programming in general are very rudimentary, so I'm still at a loss as to how to resolve this issue... |
in such cases you can add logging to this code to see what's going on, or you can try debugging
|
Quote:
I'm afraid I'm not yet familiar with how to debug in C. |
You picked a difficult first example.
Search for a very simple fork() example and debug that first. Also read the manual pages for fork() and one of the exec() calls, paying close attention to the return status. Nothing wrong with adding things like: Code:
printf("This is the child\n"); |
Like this example https://www.includehelp.com/c-progra...x-example.aspx
Same for searching for a simple exec() example. |
Quote:
I have gone over some basic tutorials of fork() and execlp as well as execvp, but have had no examples on how to debug super simple examples of that. Here is some simple fork() code I have looked at repeatedly, how would I debug this?: Code:
// Taken from: https://stackoverflow.com/questions/15102328/how-does-fork-work Anyways, thanks for your help so far. |
To clarify in relation to the C code in the original post, I am somewhat aware of how execvp does not return a value, but am unsure as to why this breaks a while(1) loop. I have played around with execvp and determined that you cannot, for example, call the ls command more than once whether you call execvp multiple times or put it in a loop of any sort. Can someone explain why this is?
|
TL;DR What is the actual question?
|
It’s too early in the morning to check your code, but BASH creates a process group for the pipeline. Are you doing that? See here:
https://youtu.be/NfHqGv0PlIw |
Quote:
Yes exec functions do not return, but it the code or commands they run complete and that exits, then the process goes away. If it's the parent, then it goes away and takes all it's children with it. If it's a child, then it terminates and sends a signal to the parent. Now you can put tons of debug in there to tell you "I am <this>", "I received ..." and etc. You copied code which in my opinion is doing something it doesn't need to do. They're parsing a command line, text. No need to fork processes to do this. So it's somebody's for fun experiment. I'm afraid I don't think I can help further here, sorry but not invested with debugging second hand code. Already have recommended you start with simpler code, as in write your own from the ground up, starting with the things you do know. Perspective: I work as an engineer writing code in C. We keep it simple. Period. Otherwise you're asking for bugs. We have to deal with those, but we prefer not to. In my LQ blogs I've long ago posted stuff about how I wrote a daemon and forked child processes, used pipes, monitored the children, and used the select statement. That's all I got, but those are are working examples. |
Quote:
|
Quote:
As a beginner I was looking into how to go about writing my own shell and came across a plethora of examples of how to approach the issue. Yes I copied this code, but that is because I wanted to break it down afterwards to understand what each function was doing (hence the verbose notation). I also wished to understand how to best implement | characters and their corresponding functionality that is normally available in full featured shells, but examples on how to do such a thing were practically nonexistent. This was the closest one I could find, but I found myself frustrated at it's exiting afterwards and I couldn't wrap my head around how to address this. I know it's time to take a step back, but I've been through two books, multiple videos, and many online tutorials on the beginner's aspects of C programming, and wanted to challenge myself to extend out an existing shell program to have an additional feature. I suppose I won't be figuring this out any time soon. Again, thank you for your insights. |
All times are GMT -5. The time now is 05:56 PM. |