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!