1

I have to write a little C program that does the following:

  • read from stdin
  • create a child process using fork and encrypt the input with crypt in that child process
  • use sleep with some random time to simulate the encrypting process and the asynchronous work of the child processes
  • in my parent process I should catch all the exit-codes of my child processes (using the singal SIGCHLD)
  • if the user presses Ctrl+C my program should wait for all child processes to finish, then terminate
  • if the user presses Ctrl+D, I should "ignore" that and read again from stdin
  • I'm reading from stdin using fgets and I also should catch the EINTR error (I think that's the Ctrl+D "signal"?)

Here is my code so far:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "crypt.h"
#include "signal.h"
#include "errno.h"
#include "sys/wait.h"

char * encryptWord(char* word);
void childTerminated(int sig);
void terminateAllAndExit(int sig);
void nop(int sig);

void readFromStdin();

int childPIDs[1024];
int childProcesses = 0;

int main(int argc, char ** argv) {
    readFromStdin();
}

void readFromStdin(void) {
    char buffer[1024];
    int pid;
    while(fgets(buffer, 1024, stdin) != NULL) {
        pid = fork();
        if(pid == 0) {
            signal(SIGINT, nop);
            char * encrypted = encryptWord(buffer);
            sleep(rand() % 10);
            printf("ecnr: %s -> %s\n", buffer, encrypted);
            exit(EXIT_SUCCESS);
        }
        else if(pid > 0) {
            signal(SIGCHLD, childTerminated);
            signal(SIGINT, terminateAllAndExit);
            childPIDs[childProcesses] = pid;
            childProcesses++;           
        }       
    }
    //printf("childProcesses: %d", childProcesses);
}

char * encryptWord(char* word) {
    // remove the \n at the end of the input
    word[strlen(word)-1] = 0;
    word = crypt(word,"sr");
    return word;
}

void childTerminated(int sig) {
    childProcesses--;
    //printf("child terminated.\n");
}

void terminateAllAndExit(int sig) {
    //pid_t p;
    int status; 
    //printf("childProcesses: %d\n", childProcesses);
    while(childProcesses > 0) {
        (void)wait(&status);
        if(WEXITSTATUS(status) == EXIT_SUCCESS) {
            childProcesses--;
        }
    }
    printf("All child processes terminated. Exiting...\n");
    exit(EXIT_SUCCESS);
}

void nop(int sig) {
    //signal(SIGINT, nop);
}

The code is working pretty nice now, encrypting works in my child processes and simulating the time they need to encrypt the input.

But, if I press Ctrl+C it's not working how it should. All child processes terminate immediately instead of waiting the time I've set in sleep.

And the last one, how can I catch the EINTR error?

Thank's for your help!

sina72
  • 4,931
  • 3
  • 35
  • 36
beeef
  • 2,664
  • 4
  • 17
  • 27

0 Answers0