Reputation: 21
I've been doing this assignment over and over again, this is about the 10th version. The problem is that only one message passes through the pipe, and the correct result is computed. The following strings don't pass at all, or after fiddling with the buffers only some characters. Please help, I've really lost a lot of time on this one and I need to learn this stuff for a test coming soon.
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <stdio_ext.h>
/* Prototypes */
void usage(void);
void calchild(void);
char command[] = "<not yet set>";
int main(int argc, char **argv)
{
char input1[512];
char input2[512];
char tmp[512];
char *endptr;
char c = 0;
int a, b, result;
pid_t cpid;
int status = 0;
int stocpipe[2]; /* Server to client pipe. [0] -read; [1]- write*/
int ctospipe[2]; /* Client to server pipe. - || - */
int i = 0;
FILE *send, *receive;
if(argc > 1)
{
usage();
}
/* Pipe Setup */
if(pipe(stocpipe) != 0 || pipe(ctospipe) != 0)
{
fprintf(stderr, "ERROR: Can't create unnamed pipe! \n");
exit(EXIT_FAILURE);
}
switch(cpid = fork())
{
case -1:
fprintf(stderr, "ERROR: Can't fork! \n");
exit(EXIT_FAILURE);
break;
case 0:
/* calchild */
close(stocpipe[1]);
close(ctospipe[0]);
receive = fdopen(stocpipe[0], "r");
send = fdopen(ctospipe[1], "w");
/*Gets the string from the parent process and does the computation.*/
while(fgets(input2, 17, receive) != NULL)
{
strcpy(tmp, input2);
fprintf(stdout, "After receive: %s", tmp);
a = strtol(tmp, &endptr, 10);
fprintf(stdout, "a = %d\n", a);
b = strtol(endptr, &endptr, 10);
fprintf(stdout, "b = %d\n", b);
c = endptr[0];
/*Loops until it finds a non-space char*/
for(i = 0; isspace(c = endptr[i]); i++);
switch(c)
{
case '+':
/*add*/
result = a + b;
break;
case '-':
/*subtract*/
result = a - b;
break;
case '*':
/*multiply*/
result = a * b;
break;
case '/':
/*divide*/
result = a / b;
break;
default:
fprintf(stderr, "the funk!? %c\n", c);
break;
}
fprintf(stderr, "%d\n", result);
fprintf(send, "%d", result);
}
break;
default:
close(stocpipe[0]);
close(ctospipe[1]);
send = fdopen(stocpipe[1], "w");
receive = fdopen(ctospipe[0], "r");
/*Reads string from stdin and sends it to the child process through a pipe. */
while(fgets(input1, 17, stdin) != NULL)
{
fprintf(stdout, "Before send: %s", input1);
fwrite(input1, 17, 1, send);
if(fflush(send) == EOF)
{
fprintf(stderr, "Flush error!");
}
}
(void) waitpid(cpid, &status, 0);
if(status != 0)
{
fprintf(stderr, "ERROR: Child calculator exited with %d \n", status);
}
break;
}
return 0;
}
void usage(void)
{
fprintf(stderr,"Usage: %s", command);
exit(EXIT_FAILURE);
}
The program is a calculator. The aim of it is learning IPC. The parent process accepts strings from stdin(e.g. 3 5 +) and sends it to the child. The child parses the string and computes the result. Then it sends the result back to the parent process which then prints it to stdout.
I got stuck on the part of sending the string to the child. The first string accepted gets sent to the child. And it computes the result fine. The second string and every after that is empty or at least it seems like empty.
Upvotes: 2
Views: 1481
Reputation: 11
Pay attention to the line fwrite(input1, 17, 1, send);
. The parent process may have sent random stuff after '\n' character to child process. In child while(fgets(input2, 17, receive) != NULL)
, fgets
stops while getting '\n' and may get less than 17-1 characters. Its next reading pipe will get random stuff.
One immediate fix is fwrite(input1, strlen(input1), 1, send);
. Referring to 'man fwrite', it's better to use fwrite(input1, sizeof (input1[0]), strlen(input1), send);
.
Anyway using magic number 17 is dangerous. Keep in mind PIPE is a continuous character stream.
Upvotes: 1