Pipe not sending accurate information - c

I have started using pipe for a basic exercise. From processes A and B we get 2 random numbers. Process C does the sum of these 2 numbers and it prints it.
The problem is that I don't get the correct values from reading. The values that enter in the pipe are not the ones that exit.
What is the problem here?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int ac[2],bc[2];
int f,g;
if(pipe(ac)<0 || pipe(bc)<0){
perror("Pipe error");
exit(1);
}
f=fork();
if(f<0){
perror("Error fork1");
exit(2);
}
if(f==0){
g=fork();
if(g<0){
perror("Error fork2");
exit(3);
}
if(g==0){
printf("We are in A \n");
int variab=rand()%11+10;
printf("Here we found the number %d\n",variab);
write(ac[1],&variab,sizeof(int));
}
else{
wait(0);
printf("We are in B\n");
int variab2=rand()%6+5;
printf("Here we found the number %d\n",variab2);
write(bc[1],&variab2,sizeof(int));
}
}
else{
wait(0);
printf("We are in C\n");
int suma;
int s1=read(ac[0],&s1,sizeof(int));
printf("S1=%d\n",s1);
int s2=read(bc[0],&s2,sizeof(int));
printf("S2=%d\n",s2);
suma=s1+s2;
printf("Sum is %d\n",suma);
}
close(ac[0]);
close(ac[1]);
close(bc[0]);
close(bc[1]);
return 0;
}

The problem is with the lines
int s1=read(ac[0],&s1,sizeof(int));
...
int s2=read(bc[0],&s2,sizeof(int));
You are overwriting the value you want to get with the amount of bytes received by the read operation.
Make sure not to assign a new value to s1 and s2 by breaking up the line
int s1;
read(ac[0],&s1,sizeof(int));
(and similarly with s2) and it will work.

Related

creating unknown amount of process in child without pipe and semaphore

I am trying to make a modified shell.
I have tried several times, I searched a lot on the net, but I cannot fix my problem. first of all I do not want to run this code by pipe or semaphore.
I think with semaphore it would be even more difficult, because I do not now how many process should be there (maybe I am wrong, but it seems at least in this way).
In the first way, program makes the file correctly, but I cannot run a loop until the user enter "exit". I am trying with while(1) but it does not give me more than one file and the stdin is active only once.
in the second way, the user can use stdin until he inserts "exit", but again,
it does not give more than one file, moreover there is nothing inside.
I am trying to mix these two ways, I tried for more than one day, but I do not understand where is the problem. By the way, I think in the second way,
it should be the file descriptor.
also, please let me know that do I use the wait system call correctly or not?
Thank you in advance.
/first way/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
//void MYshell(char *comm);
int main(){
/*
char cmd[100];
printf("<exit> closes shell\n");
printf("MYshell:$ ");
fscanf(stdin,"%s",cmd);
do{
if(strcmp(cmd,"exit")==0){
printf("shell has been closed.\n");
break;
exit(EXIT_SUCCESS);
}
MYshell(cmd);
printf("MYshell:$ ");
fscanf(stdin,"%s",cmd);
}while(1);
*/
//void MYshell(char *comm){
pid_t fork_ret;
int fd,dup_ret;
char cmd[100];
char name[100];
printf(" <exit> closes shell\n");
printf("MYshell:$ ");
fscanf(stdin,"%s",cmd);
if(strcmp(cmd,"exit")==0){
printf("shell has been closed.\n");
//break;
exit(EXIT_SUCCESS);
}
fork_ret = fork();
if(fork_ret == -1)
exit(1);
if(fork_ret == 0){
sprintf(name,"%d.log",getpid());
fd = open(name,O_CREAT | O_WRONLY,S_IRWXU|S_IRWXG|S_IRWXO);
if(fd<0){
printf("Error in opening or creating %s.\n",name);
exit(1);
}
dup_ret = dup2(fd,1);
if(dup_ret<0){
printf("Error in duplicating stdout descriptor.\n");
exit(1);
}
system(cmd);
close(fd);
exit(0);
}
//close(fd);
//exit(EXIT_SUCCESS);
if(fork_ret>0){
int stat;
pid_t child = wait(&stat);
printf("child = %d\n",child);
if(WIFEXITED(stat))
printf("ok\n");
else
printf("error\n");
}
wait(NULL);
exit(EXIT_SUCCESS);
}
/* second way*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
int fd;
char cmd[100];
void MYshell(void);
int main(){
pid_t fork_ret;
//int fd,dup_ret;
printf(" <exit> closes shell\n");
while(1){
printf("MYshell:$ ");
fscanf(stdin,"%s",cmd);
//tmp = fgets(cmd,sizeof(cmd),stdin);
if(strcmp(cmd,"exit")==0){
printf("shell has been closed.\n");
break;
exit(EXIT_SUCCESS);
}
}
fork_ret = fork();
if(fork_ret == -1)
exit(1);
if(fork_ret == 0){
MYshell();
exit(0);
}
if(fork_ret>0){
wait(NULL);
exit(0);
}
wait(NULL);
exit(EXIT_SUCCESS);
}
void MYshell(void){
char name[BUFSIZ];
int fd,dup_ret;
sprintf(name,"%d.log",getpid());
fd = open(name, O_CREAT|O_RDWR , S_IRWXU|S_IRWXG|S_IRWXO);
if(fd<0){
printf("Error in opening or creating %s.\n",name);
exit(1);
}
dup_ret = dup2(fd,1);
if(dup_ret<0){
printf("Error in duplicating stdout descriptor.\n");
exit(1);
}
system(cmd);
close(fd);
exit(0);
}

Piping between two programs in C

I've been stuck on getting piping to work between two programs for the last couple of hours and I'm stuck and not sure if I'm doing something wrong. The idea of my program is that I'm going to use interface.c to open a pipe, and then execute db.c. I want to use two pipes to communicate between the two different programs. Now, with interface.c being the 'parent' and db.c being the 'child', I'm not sure if I'm passing in the parameters to my pipe correctly via the execl command. Everything compiles correctly, but when I try to run the interface program, I'm getting an error stating: 'Bad File Number.' Is it possible that I'm not using pipes correctly? Currently, I'm just trying to get my program to send an integer, value, over the pipe to db.c. Any help would be much appreciated.
Code for interface.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
//PIPES:
//
//Parent: reads from P1_READ, writes on P1_WRITE
//Child: reads from P2_READ, writes on P2_WRITE
#define P1_READ 0
#define P2_WRITE 1
#define P2_READ 2
#define P1_WRITE 3
// the total number of pipe *pairs* we need
#define NUM_PIPES 2
int main(int argc, char *argv[])
{
//Create Pipe Array
int fd[2*NUM_PIPES];
//For Parameter Passing:
char param0[20]; //P1_Read
char param1[20]; //P2_Write
char param2[20]; //P2_Read
char param3[20]; //P1_Write
snprintf(param0, sizeof(param0), "%d" , fd[0]);
snprintf(param1, sizeof(param1), "%d" , fd[1]);
snprintf(param2, sizeof(param2), "%d" , fd[2]);
snprintf(param3, sizeof(param3), "%d" , fd[3]);
//Variables
pid_t pid;
int val = 42;
//Allocate the PIPES
for (int i=0; i<NUM_PIPES; ++i)
{
if(pipe(fd+(i*2)) < 0)
{
perror("Failed to allocate the pipes");
exit(EXIT_FAILURE);
}
}
//If the fork of the program does not work:
if ((pid = fork()) < 0)
{
perror("Failed to fork process");
return EXIT_FAILURE;
}
if(pid == 0)
{ //Child Process
execl("./db", "db", param0, param1, param2, param3, (char *)NULL);
}
else
{ //Parent Process
//SENDING VALUES HERE
close(fd[P2_READ]);
close(fd[P2_WRITE]);
printf("Interface is sending|%d| to DB\n", val);
if(write(fd[P1_WRITE],&val, sizeof(val)) != sizeof(val))
{
perror("Interfae failed to send value to DB");
exit(EXIT_FAILURE);
}
}
return 0;
}
This is for db.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
//Typedef-Class-
typedef struct Information
{
int accountId;
int checkNumber;
int date;
float amount;
} Information;
int main(int argc, char *argv[])
{
//For Input
//Account Data
Information acctData[25];
int dataStorageLooper = 0; //How many db entries
//For File Input
int aVal;
int bVal;
int cVal;
float dVal;
//Prepare for file input:
FILE * fp;
fp = fopen ("accountData.txt", "r");
//Reads Input
while(1)
{
if (fscanf(fp, "%d %d %d %f", &aVal, &bVal, &cVal, &dVal)!=4)
{
break;
}
//Puts data into appropriate arrays
acctData[dataStorageLooper].accountId= aVal;
acctData[dataStorageLooper].checkNumber= bVal;
acctData[dataStorageLooper].date= cVal;
acctData[dataStorageLooper].amount= dVal;
dataStorageLooper++;
}
//Decrement index to point to last item
dataStorageLooper--;
//Displays all values
printf("\nDisplaying AccountData.txt\n");
for( int i = 0; i < dataStorageLooper; i++)
{
printf("Line|%d|: Account|%d|: Check|%d|: Date|%d|: Amount|%.2f|\n",i,acctData[i].accountId,acctData[i].checkNumber,acctData[i].date,acctData[i].amount);
}
//Closes File
fclose(fp);
//End Input
//Parameter Receiving:
int pipes[4]; //Pipe Array
int value = 7;
int test;
//Build the pipes
pipes[0] = atoi(argv[1]); //P1_Read
pipes[1] = atoi(argv[2]); //P2_Write
pipes[2] = atoi(argv[3]); //P2_Read
pipes[3] = atoi(argv[4]); //P1_Write
//Troubleshooting
printf("The number of parameters: %d\n",argc);
printf("Parameter 1: %s\n", argv[0]);
printf("I stared correctly\n");
//Testing
close(pipes[0]);
close(pipes[3]);
//SHOULD RECEIVE VALUE HERE
test = read(pipes[2], &value, sizeof(value));
if (test < 0)
{
perror("DB: Failed to read data from parent");
exit(EXIT_FAILURE);
}
else if (test == 0)
{
//Unexpected
fprintf(stderr, "DB: Read End-Of-File from pipe");
}
else
{
//What did the child receive?
printf("DB: Received Value:(%d)\n", value);
}
close(pipes[2]);
close(pipes[1]);
return 0;
}
One of the things you're doing wrong is snprintfing the value of the various elements in fd before you've assigned any value to them. That's undefined behaviour, and the values you're passing as parameters are totally meaningless (at best).
This strikes me as a very odd way to do things, though. Usually you would just dup2 fds 0 and 1 so that the child's stdin and stdout are redirected to the appropriate pipe fds.

Can't send Integer to exec function through stdin redirection. C language

This is an academic exercise. I'm supposed to read an integer from the father process, send it to the child, and the child is supposed to call the exec function of factorial (which must read from stdin and write on stdout). Father must show the result of the exec function.
Apparently the exec function is reading nothing but garbage (random big values) from the stdin redirection I've made. Can't figure out why.
Here is the code of main program and exec function (factorial):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX_BUFFER 80
int main (){
int pipeFatherChild[2], pipeChildFather[2],i;
pid_t pid;
if(pipe(pipeFatherChild)==-1 || pipe(pipeChildFather)==-1){
perror("pipe Error!");
return -1;
}
pid = fork();
if(pid<0){
perror("fork Error!");
return -1;
}
if(pid>0){//father
int value;
char result[MAX_BUFFER];
close(pipeFatherChild[0]);
close(pipeChildFather[1]);
printf("Please insert nunber to calculate factorial:\n");
scanf("%d",&value);
write(pipeFatherChild[1],&value,sizeof(int));
close(pipeFatherChild[1]);
wait(NULL);//wait for child
int ret;
while((ret=read(pipeChildFather[0],&result,MAX_BUFFER)!=0)){
printf("PAI DIZ: %s\n", result);
}
close(pipeChildFather[0]);
}else{//child
close(pipeFatherChild[1]);
dup2(pipeFatherChild[0],0);
close(pipeFatherChild[0]);
close(pipeChildFather[0]);
dup2(pipeChildFather[1],1);
close(pipeChildFather[1]);
execl("./factorial", "factorial");
perror("Child Error\n");
}
return 0;
}
Factorial program:
#include <stdio.h>
int factorial(int n){
if(n==0)
return 1;
return n * factorial(n-1);
}
int main(){
int n;
fscanf(stdin,"%d", &n);
fprintf(stdout,"Factorial of %d is %d\n", n, factorial(n));
return 0;
}

synchronizing processes with alarms in c

I have to write a program about signals and alarms, and i can't use semaphores
A first process (named "B") launches another one (named "A"). "A" have to write random words in a file, once per 5 secs, if it writes the word END terminates the execution. The process "B" have to read the words from the file, if read END then relaunch the process "A". When "B" reads 50 words kills "A" and terminates the execution
The program does not work properly,I think it's because both processes accessing the file at the same time, but I do not know for sure
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define SECS 5
#define MAX_READ 50
#define MAX_TAM 10
#define N_WORDS 13
int main(void){
int i=0,flag;
pid_t pid;
static char words[][MAX_TAM]={"THE","PROCESS","A","WRITES","IN","A","FILE","WORDS","AND","KILL","ITSELF","WITH","END"};
char *word;
char read[MAX_TAM];
FILE *fp=fopen("file2.txt","w");
if(!fp){
perror("Error opening file");
exit(EXIT_FAILURE);
}
if (signal(SIGALRM, SIG_IGN) == SIG_ERR){
puts("Error");
exit (EXIT_FAILURE);
}
while(1){
flag=0;
switch(pid=fork()){
case -1:
perror("fork error");
exit(EXIT_FAILURE);
case 0: /* A */
srand(getpid());
while(1){
if(alarm(SECS))
pause();
word = words[rand()%N_WORDS];
fprintf(fp,"%s ",word);
printf("A ~ WORD: %s\n",word);
fflush(stdout);
if(!strcmp(word,"END")){
fclose(fp);
printf("ENDING A\n");
exit(EXIT_SUCCESS);
}
}
default: /* Proceso B */
sleep(1);
for( ;i<MAX_READ;i++){
if(alarm(SECS))
pause();
fscanf(fp,"%s",read);
printf("B ~ READING %s\n",read);
fflush(stdout);
if(!strcmp(read,"END")){
flag=1;
break;
}
}
}
if(flag==0)
break;
}
kill(pid,9);
exit(EXIT_SUCCESS);
}

Using Pipes in C

I wrote the following code to help me understand how pipes work in C.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
struct sum_ {
int a;
int b;
};
int main (void) {
int pipe1[2];
int pid;
struct sum_ sum;
if ( (pipe(pipe1) != 0)){
printf("pipe(): %d %s\n", errno, strerror(errno));
exit(1);
}
pid = fork();
if (pid == -1) {
printf("fork(): %d %s\n", errno, strerror(errno));
exit(1);
}
else if (pid == 0) { // Child
close(pipe1[0]);
sleep(5);
sum.a = read(pipe1[0], &sum.a, sizeof(sum.a));
printf("Your number was: %d", sum.a);
}
else { // Father
close(pipe1[1]);
printf("\nWrite a number: \n");
char a[4];
sum.a = atoi(fgets(a, 4, stdin));
write(pipe1[1], &sum.a, sizeof(sum.a));
}
return 0;
}
The code has a father and a son process. It is quite simple, the father uses a pipe to send a number to the son and the son displays the number for the user.
I always get -1 as result. What have I done wrong?
close(pipe1[0]);
sleep(5);
sum.a = read(pipe1[0], &sum.a, sizeof(sum.a));
You close the file descriptor pipe1[0], then read from it (and so get -1 returned). You make the equivalent error in the father, too. I think you mean to close pipep1[0] here and pipe1[1] in the father
Also, when you fix that, lthough you're reading into sum.a by passing the address, you're also setting it from the return value, which will overwrite what you read.

Resources