user1093114
user1093114

Reputation: 1

can't get input after first time in do while

I am trying to fork a child process put him in sleep and wake him up whenever the user enter a line of text to print number of lines entered.

My code is working fine. But weird thing I found is I have to user two gets(str) statement if I didn't the user will be prompted for 1 time only.

if run the code and comment one gets(str) you will know what I mean.

Your help is appreciated. Thanks

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>

main () {
    int n;
    char ch;
    pid_t child;
    int erret;
    char str[20];
    int c = 0;

    if ((child = fork ()) < 0) {
        perror ("fork");
        exit (0);
    }

    else {
        //waitpid(child,NULL,0);
        do {
            waitpid (child, NULL, 0);
            printf ("Enter a line(s) \n");
            //funn();
            //fflush(stdin);
            //scanf("%d",&n);
            gets (str);
            gets (str);
            erret = kill (child, SIGCHLD);
            printf ("Signal %d\n", erret);
            if (erret >= 0) {
                c++;
                printf ("You have entered : %d line(s)\n", c);
                //pause();
                //waitpid(child,NULL,0);
            }

            else {
                kill (child, SIGKILL);
                exit (0);

            }
            printf ("\nPress 9 to exit  :");
            fflush (stdin);
            scanf ("%d", &n);
            fflush (stdin);
        } while (n != 9);
        kill (child, SIGKILL);
    }
}

Upvotes: 0

Views: 76

Answers (2)

Dan
Dan

Reputation: 1884

Your concept is flawed, you're forking with out specifying what the parant and child does. So you have a race conditon on gets. This is because after the fork call two copies of the code is run, one copy by the parent and one copy by the child. So the fix is to add a swich or else if statement to separate your code into sections for the child and parent. BTW as already stated use fgets

switch(fork()):
    case -1:
        //Error
    case 0:
        // Child code
    default:
        // Parant code

Upvotes: 1

David C. Rankin
David C. Rankin

Reputation: 84551

There are a number of ways to get repetitive string input as you are trying to do. One of the standard approaches is to gather input until the user signals EOF signifying there is no more data to enter. (On Linux EOF is generated from the terminal with ctrl + d). Without changing your logic and without commenting on your fork, waitpid, etc.. implementation, the following is one way to handle gathering string input for your program until the users sends an EOF by pressing ctrl+d on the keyboard:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>

int main () {

    pid_t child;
    int erret;
    int c = 0;

    ssize_t nread = 0;          /* number of chars read by getline  */
    char *lineptr = NULL;       /* string read by (NULL forces getline to allocate) */
    size_t nbytes = 0;          /* number of bytes to read (ignored with lineptr = NULL) */

    if ((child = fork ()) < 0) {
        perror ("fork");
        exit (0);
    }
    else
    {
        waitpid (child, NULL, 0);
        printf ("\nEnter line(s) of text (ctrl+d to exit):\n\n");

        while (printf ("  Input: ") && (nread = getline (&lineptr, &nbytes, stdin) != -1)) 
        {
            erret = kill (child, SIGCHLD);
            printf ("\n  Signal %d\n", erret);

            if (erret >= 0) {
                c++;
                printf ("  You have entered : %d line(s)\n\n", c);
            }
            else
            {
                kill (child, SIGKILL);
                exit (0);
            }
        }

        kill (child, SIGKILL);
    }

    return 0;
}

output:

$ ./bin/ind2

Enter line(s) of text (ctrl+d to exit):

  Input: line one

  Signal 0
  You have entered : 1 line(s)

  Input: line 2

  Signal 0
  You have entered : 2 line(s)

  Input: line 3

  Signal 0
  You have entered : 3 line(s)

  Input: Killed

Upvotes: 0

Related Questions