C/Here I let you the program,I really need help before tomorrow...THANK YOU
Expert: Zlatko - 11/25/2011
QuestionQUESTION: Hi,I'm sorry I thought I sent you the message,maybe I did something wrong. Thank you anyway for your reply, and here I let you my problem...
I would like to know if you could help me with this code(C Unix), because I solved all the warnings but my program is still not working...it doesn't create the .txt neither asking me to introduce text...Is everything in the correct order/place? What is wrong? I really need your help, THANKS A LOT. Sorry because it is in Spanish.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
int pidHijo1;
int descrTub1[2];
int pidHijo2;
int descrTub2[2];
void ProcesoHijo1();
void ProcesoHijo2();
void ProcesoPadre();
int main(int argc, char *argv[]) {
pipe(descrTub1);
pipe(descrTub2);
pidHijo1 = fork();
if (pidHijo1 == 0) {
ProcesoHijo1();
return 0;
}
pidHijo2 = fork();
if (pidHijo2 == 0)
ProcesoHijo2();
else
ProcesoPadre();
}
void ProcesoHijo1() {
char bufferLectura[256];
close(0);
dup(descrTub1[0]);
while (1) {
fgets(bufferLectura, 255, stdin);
printf("%s\n", bufferLectura);
}
}
void ProcesoHijo2() {
char bufferLectura[256];
int descrFichero;
close(0);
dup(descrTub1[0]);
descrFichero = open("salida.txt", O_APPEND | O_TRUNC | O_RDWR, 0600);
FILE*fp = fdopen(descrTub2[0], "r");
while(1) {
fgets(bufferLectura,255,fp);
write(descrFichero, bufferLectura, strlen(bufferLectura));
}
}
void ProcesoPadre() {
char bufferLectura[256];
close(2);
dup(descrTub1[1]);
printf("[Proceso padre]Introduce un texto, o exit para salir");//parent process Insert text or exit
fgets(bufferLectura, 255,stdin);
while(strcmp(bufferLectura, "exit\n")) {
fprintf(stderr,"%s/n", bufferLectura);
write(descrTub2[1], bufferLectura,strlen(bufferLectura));
printf("[Proceso padre] Introduce un texto, o exit para salir ");//parent process Insert text or exit
fgets(bufferLectura, 255,stdin);
}
kill(pidHijo1, SIGTERM);
kill(pidHijo2, SIGTERM);
}
ANSWER: Hello odaetiep
I promise to take a closer look at your program tonight when I have time. For now I have 2 concerns.
In Hijo1, you do close(0), but then try to read from stdin. I think stdin relies on file descriptor 0. For testing, simplify your program so that Hijo1 repeatedly sends a predefined message (like HELLO_X) where X is a counter, and sleeps between sends. Then you will not rely on reading from the user.
Padre also reads from stdin, and it shares the tty with Hijo1, so there could be a conflict there. For testing, I would remove the salir loop from Padre.
As I said, I will not have time to look closely at your program until tonight but I will work on it.
---------- FOLLOW-UP ----------
QUESTION: Thank you!!! that was a prompt reply! I tried what you said, but I guess wrong because it is not working at all. The matter is I don't know C, I've been asked by a professor to create this program and I'm getting mad...He gave us a few tips in two days and, a structure to follow and create the program using what you see, but nothing else...do I have to close(descrTub1[1]);? When you change something of the program, if you could write down the code from the part is changed just to clarify me...I never know if I'm doing it right.
Thank you very much, Ill be waiting till you can have a closer look.
Thanks.
ANSWER: What is your program supposed to do?
I think this is what you want:
The child1 reads a message from the user.
The child1 sends the message to child2 through the pipe
The child2 reads from the pipe and writes to the file.
Is that what you want ?
If that is what you want, then you need only 1 pipe. Pipes have only 1 direction, so name your pipe to describe who is the sender and who is the reciever. Assign names to the pipe ends as I have done below. Using names like READ_END and WRITE_END will help you to stay organized. You should have started with a simple program without user input and without file output. Once that is working, then add the other features. Below is the starting point. Try to run it. Ask me about what you don't understand. Then add features to write to the file. Once that is working, add features to read from the keyboard.
When reading/writing with pipes, I think you should not use the stdio FILE* functions. Use the UNIX read/write. There is no need to do the dup or fdopen.
Start with my code below.
Don't forget to tell me what you want your program to do.
email zlatko.c.help@gmail.com
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#define READ_END 0
#define WRITE_END 1
int pWriterToReader[2];
volatile int keepGoing = 1;
void mySighandler(int sig)
{
keepGoing = 0;
}
void writer()
{
int i = 0;
close(pWriterToReader[READ_END]);
while(keepGoing)
{
char buf[64];
int len;
len = sprintf(buf, "HELLO %d", i++);
write(pWriterToReader[WRITE_END], buf, len + 1);
sleep(3);
}
printf("writer done\n");
}
void reader()
{
close(pWriterToReader[WRITE_END]);
while(keepGoing)
{
char buf[64];
int len;
buf[0] = 0;
len = read(pWriterToReader[READ_END], buf, sizeof(buf));
if (len > 0) printf("READER read '%s'\n", buf);
}
printf("reader done\n");
}
int main()
{
int readerChild;
int writerChild;
{
struct sigaction newAct;
newAct.sa_handler = mySighandler;
sigaction(SIGTERM, &newAct, NULL);
}
printf("kill -s TERM %d to stop tasks\n", getpid());
pipe(pWriterToReader);
if ((readerChild = fork()) == 0)
{
reader();
return 0;
}
if ((writerChild = fork()) == 0)
{
writer();
return 0;
}
while(keepGoing)
{
sleep(1);
}
kill(readerChild, SIGTERM);
kill(writerChild, SIGTERM);
printf("main done\n");
return 0;
}
---------- FOLLOW-UP ----------
QUESTION: Nope...Sorry, I might be turning you crazy...
The parent process generates two child processes.
The parent will read data from stdin and will send it to his children.
The 1st child will show on screen the text read from his father,to standard output.
The 2nd child will show the read data in a file. When the parent has as input an "exit", he will send termination signals to his children and will exit.
And it has to follow what I'm giving you.I changed a little bit the code and I translated some parts to English language...that wasn't clear...
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
int pidHijo1; //first child
int descrTub1[2]; //first pipe
int pidHijo2; //2nd child
int descrTub2[2];//2nd pipe
void ProcesoHijo1();//first child process
void ProcesoHijo2();//second child process
void ProcesoPadre();//paren process
int main(int argc, char *argv[]) {
pipe(descrTub1); // creation of 1st pipe
pipe(descrTub2); // creation of the 2nd one
//creation of 1st child
pidHijo1 = fork();
if (pidHijo1 == 0) {
printf("I'm the first one/n");
ProcesoHijo1();
return 0;
}
//creation of 2nd child
pidHijo2 = fork();
if (pidHijo2 == 0){
printf("I'm the second one/n");
ProcesoHijo2();
}else
ProcesoPadre();
}
void ProcesoHijo1() { // this is what the 1st child does
char bufferLectura[256];
close(0);
dup(descrTub1[0]);
while (1) {
fgets(bufferLectura, 255, stdin);
printf("%s\n", bufferLectura);
}
}
void ProcesoHijo2() { // this is what the 2nd child does
char bufferLectura[256]; //buffer
int descrFichero; //file descriptor
close(0);
dup(descrTub1[0]);
descrFichero = open("salida.txt", O_CREAT | O_TRUNC | O_WRONLY, 0600);
while(1) {
fgets(bufferLectura,255,???); // --->I have trouble here...
close(descrFichero); //-->and here....
descrFichero = open("salida.txt", O_APPEND| O_WRONLY, 0600);
write(descrFichero, bufferLectura, strlen(bufferLectura));
}
}
void ProcesoPadre() { // What the father does
char bufferLectura[256];//buffer
close(2);
dup(descrTub1[1]);
printf("[PAren Process]Insert text or exit");
fgets(bufferLectura, 255,stdin);
while(strcmp(bufferLectura, "exit\n")) {
fprintf(stderr,"%s/n", bufferLectura); //this goes to 1st child
write(descrTub2[1], bufferLectura, strlen(bufferLectura));//this goes to 2nd child
printf("[paren process] Insert text or exit ");
fgets(bufferLectura, 255,stdin);
}
kill(pidHijo1, SIGTERM);
kill(pidHijo2, SIGTERM);
}
AnswerVery well, then you should be starting with one parent and one child, and you should get that working first before adding the next child. If you read my program, you should be able to change it to do what you want. However, I understand you are short on time. Here is a new starting point. Now I see why you needed 2 pipes. Again, it is important to name your functions and variables so that they show their purpose.
Take the program below.
Run it to prove to yourself that the parent is sending data to the children.
Then add the salir and user input logic to the parent.
Then change the fileWriter function to write to a file instead of stdout.
Then you are done.
As I said earlier, don't use fgets to read from pipes. User read/write.
Don't close anything except the parts of the pipe you will not be using. A reader does not use the WRITE_END, and a writer does not use the READ_END, so a reader can close the WRITE_ENDs, and a writer can close the READ_ENDS. You don't need to close 0 which is stdin.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#define READ_END 0
#define WRITE_END 1
int pParentToStdoutWriter[2];
int pParentToFileWriter[2];
void stdoutWriter()
{
close(pParentToStdoutWriter[WRITE_END]);
while(1)
{
char buf[64];
int len;
len = read(pParentToStdoutWriter[READ_END], buf, sizeof(buf));
printf("stdout writer read '%s'\n", buf);
}
}
void fileWriter()
{
close(pParentToFileWriter[WRITE_END]);
/* For you to do: instead of writing to stdout, write to a file */
while(1)
{
char buf[64];
int len;
len = read(pParentToFileWriter[READ_END], buf, sizeof(buf));
printf("file writer read '%s'\n", buf);
}
}
int main()
{
int stdoutWriterChild;
int fileWriterChild;
int msgCount = 0;
pipe(pParentToFileWriter);
pipe(pParentToStdoutWriter);
if ((stdoutWriterChild = fork()) == 0)
{
stdoutWriter();
return 0;
}
if ((fileWriterChild = fork()) == 0)
{
fileWriter();
return 0;
}
close(pParentToStdoutWriter[READ_END]);
close(pParentToFileWriter[READ_END]);
/* for you to do: get input from user into buf. Check for "salir" */
while(1)
{
char buf[64];
int len = sprintf(buf, "HELLO %d", msgCount++);
printf("****** parent writing *******\n");
write(pParentToStdoutWriter[WRITE_END], buf, len + 1);
sleep(1);
write(pParentToFileWriter[WRITE_END], buf, len + 1);
sleep(1);
}
kill(stdoutWriterChild, SIGTERM);
kill(fileWriterChild, SIGTERM);
return 0;
}