In my program, I want to send user enter value "select1" to another program using a named pipe "pipeselect". When I run my program and enter 1, the program is on hold and cannot print "Option 1 is selected". What's wrong with my program?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char pipeselect[] = "/tmp/pipeselect";
char bufs[2];
int fds;
int select1;
/* Pipe Creation */
if (access(pipeselect, F_OK) == -1) {
fds = mkfifo(pipeselect, 0700);
if (fds != 0) {
printf("Pipe creation error\n");
exit(1);
}
}
printf("1. Option 1\n");
printf("2. Option 2\n");
printf("Please select an option: ");
scanf("%d", &select1);
int i = select1;
switch(i) {
case 1:
if ((fds = open(pipeselect, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
bufs[0] = i;
write(fds,bufs,1);
close(fds);
printf("Option 1 is selected\n");
break;
case 2:
if ((fds = open(pipeselect, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
write(fds,bufs,i);
close(fds);
printf("Option 2 is selected\n");
break;
default:
printf("Wrong Input!\n");
break;
unlink(pipeselect);
exit(0);
}
}
Related
I have a C program where I can offer as input different commands. The commands are processed by children and the answers are send it back to the parent. One of my command is quit and one command is login. If I have as a input commands in this order : login and quit, the quit must pe introduced twice to close the program. Also the parent takes the input in a while loop and quit is supposed to close the program. Also I'm getting the result from the first login as answer.
If you know what could be, please let me know. Thanks! Have a great day!
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#define verde printf("\033[0;32m")
#define alb printf("\033[0m")
#define rosu printf("\033[0;31m")
#define blue printf("\033[1;34m")
typedef int bool;
#define true 1
#define false 0
int main(int argc, char **argv)
{
char *comanda = (char *)malloc(55);
bool loggedIn = false;
while (1)
{
blue;
printf("Insert the command: ");
alb;
fgets(comanda, 55, stdin);
if(strstr(comanda, "quit") != NULL)
{
exit(0);
}
if (strstr(comanda, "login : ") != NULL )
{
pid_t pid;
int fd[2];
if (pipe(fd) == -1)
{
rosu;
perror("Am esuat in a crea un pipe...");
exit(1);
}
if ((pid = fork()) == -1)
{
rosu;
perror("Child failed...");
exit(2);
}
else if (pid)
{
FILE *ptr;
close(fd[0]);
if ((ptr = fopen("users.txt", "r")) == NULL)
{
rosu;
perror("Failed to open users.txt ...");
exit(3);
}
char username[30];
bool gasit = false;
while (fgets(username, 30, ptr))
{
if (strstr(comanda, username) != NULL)
{
gasit = true;
break;
}
}
if (write(fd[1], &gasit, sizeof(bool)) == -1)
{
rosu;
perror("Failed to write in pipe...");
exit(4);
}
close(fd[1]);
}
wait(NULL);
bool raspuns;
close(fd[1]);
if (read(fd[0], &raspuns, sizeof(bool)) == -1)
{
rosu;
perror("Can't write from pipe...");
exit(5);
}
if (raspuns == true)
{
verde;
printf("Succes!\n");
alb;
}
else
{
rosu;
printf("Failed to login!\n");
alb;
}
close(fd[0]);
}
else if(strstr(comanda, "myfind : ") != NULL)
{
}
else if(strstr(comanda,"mystat : ")!=NULL)
{
}
else
{
rosu;
printf("Wrong command!\n");
alb;
}
}
return 0;
}
So I have created a simple shell program which takes input from the user through cmd, and then creates a new task and executes the input as a command. For example:
ls -l /home/user/Downloads | sort –u > listing.txt
But my program can only handle one piping. Can I somehow make it work with no limitations to pipings?? For example:
ls -l /home/user/Downloads | sort –u | wc –l > count.txt
So far I have been unable to implement something like that.
Here is my code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
pid_t pid1,pid2,waitPid;
int status,n,j,k,in,out,pdes[2],current_out,current_in,returnValue;
char *token;
char array[256];
char *temp[256];
char *temp2[256];
current_out=dup(1);
current_in=dup(0);
for(;;)
{
if(dup2(current_out,1) < 0)
{
printf("Error restoring output");
}
if(dup2(current_in, 0) < 0)
{
printf("Error restoring input");
}
int i=0;
k=0;
printf("mysh4>");
int check = scanf("%d",&n);
if(check == EOF)
{
printf("You now exit.\n");
break;
}
else
{
fgets(array,sizeof(array),stdin);
array[strcspn(array,"\n")] = 0;
token = strtok(array, " ");
while(token != NULL)
{
temp[i] = token;
token = strtok(NULL, " ");
i++;
k++;
}
temp[i]= NULL;
int p=0;
int qq;
for(i=0;i<k;i++)
{
if(strcmp(temp[i],"|") == 0)
{
for(qq=i+1; qq<k; qq++)
{
temp2[p]=temp[qq];
temp[qq-1] = NULL;
printf("Temp2[%d] is: %s\n" , p , temp2[p]);
printf("Temp1[%d] is: %s\n" , p , temp[p]);
p++;
}
temp2[p]= NULL;
}
}
returnValue=pipe(pdes);
if (returnValue == -1)
{
printf("ERROR: Pipe command failed.\n");
return -1;
}
close(pdes[0]);
close(pdes[1]);
pid1 = fork();
if (pid1 < 0)
{
perror("ERROR: Fork failed.\n");
return -1;
}
//child process
if (pid1 == 0)
{
close(pdes[0]);
dup2(pdes[1],1);
printf("Array:%s", array);
execvp(array,temp);
printf("Invalid Code\n");
return -1;
}
pid2 = fork();
if(pid2 < 0)
{
perror("Error: Fork2 failed.\n");
return -1;
}
//child process 2
if(pid2 == 0)
{
close(pdes[1]);
dup2(pdes[0],0);
for(j=0;j<k;j++)
{
if(strcmp(temp[j],">") == 0)
{
out=j+1;
printf("Output is %s\n", temp[out]);
temp[j] = temp[out];
pdes[1]=open(temp[out],
O_APPEND | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if(dup2(pdes[1],1) < 0)
{
printf("error in dup2");
return -1;
}
}
}
execvp(temp2[0],temp2);
printf("Invalid Code 2\n");
return -1;
}
//father process
else
{
//father waits child process to finish
waitPid = wait(NULL);
if (waitPid == -1)
{
perror("ERROR: Waitpid failed.\n");
return -1;
}
}
}
}
return 0;
}
I want to write a program with 1 sender and 3 receivers. The sender can send individual message to each receivers and group message to all receivers. I am using named pipes to achieve this but can't send group message to all receivers synchronously. Any idea to send broadcast message with named pipe?
Sender program:
/* Sender */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char pipename1[] = "/tmp/pipe1";
char pipename2[] = "/tmp/pipe2";
char pipename3[] = "/tmp/pipe3";
char pipename4[] = "/tmp/pipe4";
char buf1[80];
char buf2[80];
char buf3[80];
char buf4[80];
int fd1, fd2, fd3, fd4;
int select1, select2;
int n,pid;
/* Pipe Creation */
if (access(pipename1, F_OK) == -1) {
fd1 = mkfifo(pipename1, 0700);
if (fd1 != 0) {
printf("Pipe creation error\n");
exit(1);
}
}
if (access(pipename2, F_OK) == -1) {
fd2 = mkfifo(pipename2, 0700);
if (fd2 != 0) {
printf("Pipe creation error\n");
exit(1);
}
}
if (access(pipename3, F_OK) == -1) {
fd3 = mkfifo(pipename3, 0700);
if (fd3 != 0) {
printf("Pipe creation error\n");
exit(1);
}
}
if (access(pipename4, F_OK) == -1) {
fd4 = mkfifo(pipename4, 0700);
if (fd4 != 0) {
printf("Pipe creation error\n");
exit(1);
}
}
pid = fork();
if (pid < 0) {
printf("Fork failed\n");
exit(1);
} else if (pid == 0) {
printf("1. Send individual message\n");
printf("2. Send group message\n");
printf("Please select an option: ");
scanf("%d", &select1);
switch(select1) {
case 1:
printf("1. Receiver 1 (Mary)\n");
printf("2. Receiver 2 (John)\n");
printf("3. Receiver 3 (Peter)\n");
printf("Please select a receiver: ");
scanf("%d", &select2);
switch(select2) {
case 1:
/* Open pipe for writing */
if ((fd1 = open(pipename1, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while (1) {
printf("Send message to Mary: \n");
n = read(STDIN_FILENO,buf1,80);
if (n <= 0) break;
buf1[--n] = 0;
printf("Sending message [%s] to Mary\n",buf1);
write(fd1,buf1,n);
}
close(fd1);
break;
case 2:
/* Open pipe for writing */
if ((fd2 = open(pipename2, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while (1) {
printf("Send message to John: \n");
n = read(STDIN_FILENO,buf2,80);
if (n <= 0) break;
buf2[--n] = 0;
printf("Sending message [%s] to John\n",buf2);
write(fd2,buf2,n);
}
break;
case 3:
/* Open pipe for writing */
if ((fd3 = open(pipename3, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while (1) {
printf("Send message to Peter: \n");
n = read(STDIN_FILENO,buf3,80);
if (n <= 0) break;
buf3[--n] = 0;
printf("Sending message [%s] to Peter\n",buf3);
write(fd3,buf3,n);
}
break;
default:
printf("Receiver not found\n");
break;
}
case 2:
/* Open pipe for writing */
if ((fd4 = open(pipename4, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while (1) {
printf("Send message to Group: \n");
n = read(STDIN_FILENO,buf4,80);
if (n <= 0) break;
buf4[--n] = 0;
printf("Sending message [%s] to Group\n",buf4);
write(fd4,buf4,n);
}
break;
default:
printf("Wrong Input!\n");
break;
}
} else {
wait(NULL);
}
unlink(pipename1);
unlink(pipename2);
unlink(pipename3);
unlink(pipename4);
exit(0);
}
Receiver1 program:
/* Receiver1 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char pipename1[] = "/tmp/pipe1";
char pipename4[] = "/tmp/pipe4";
char buf1[80];
char buf4[80];
int fd1, fd4;
int n, pid;
printf("Mary is online\n");
pid = fork();
if (pid < 0) {
printf("Fork failed\n");
exit(1);
} else if (pid == 0) {
/* Open pipe for reading */
if ((fd1 = open(pipename1, O_RDONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while ((n = read(fd1, buf1, 80)) > 0) {
buf1[n] = 0;
printf("[Message received:] %s\n", buf1, n);
}
close(fd1);
exit(0);
} else {
/* Open pipe for reading */
if ((fd4 = open(pipename4, O_RDONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while ((n = read(fd4, buf4, 80)) > 0) {
buf4[n] = 0;
printf("[Message received:] %s\n", buf4, n);
}
close(fd4);
wait(NULL);
exit(0);
}
}
Receiver2 program:
/* Receiver2 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char pipename2[] = "/tmp/pipe2";
char pipename4[] = "/tmp/pipe4";
char buf2[80];
char buf4[80];
int fd2, fd4;
int n, pid;
printf("John is online\n");
pid = fork();
if (pid < 0) {
printf("Fork failed\n");
exit(1);
} else if (pid == 0) {
/* Open pipe for reading */
if ((fd2 = open(pipename2, O_RDONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while ((n = read(fd2, buf2, 80)) > 0) {
buf2[n] = 0;
printf("[Message received:] %s\n", buf2, n);
}
close(fd2);
exit(0);
} else {
/* Open pipe for reading */
if ((fd4 = open(pipename4, O_RDONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while ((n = read(fd4, buf4, 80)) > 0) {
buf4[n] = 0;
printf("[Message received:] %s\n", buf4, n);
}
close(fd4);
wait(NULL);
exit(0);
}
}
Receiver3 program:
/* Receiver3 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char pipename3[] = "/tmp/pipe3";
char pipename4[] = "/tmp/pipe4";
char buf3[80];
char buf4[80];
int fd3, fd4;
int n, pid;
printf("Peter is online\n");
pid = fork();
if (pid < 0) {
printf("Fork failed\n");
exit(1);
} else if (pid == 0) {
/* Open pipe for reading */
if ((fd3 = open(pipename3, O_RDONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while ((n = read(fd3, buf3, 80)) > 0) {
buf3[n] = 0;
printf("[Message received:] %s\n", buf3, n);
}
close(fd3);
exit(0);
} else {
/* Open pipe for reading */
if ((fd6 = open(pipename4, O_RDONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
while ((n = read(fd4, buf4, 80)) > 0) {
buf4[n] = 0;
printf("[Message received:] %s\n", buf4, n);
}
close(fd4);
wait(NULL);
exit(0);
}
}
In my program, I want to send my switch case value to another process using named pipe "pipeselect". I write the number in the pipe and read the number in another program. But When I run the problem, it cannot show anything when I enter a case value. How can I do this?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
char pipeselect[] = "/tmp/pipeselect";
char bufs[2];
int fds;
int select1;
/* Pipe Creation */
if (access(pipeselect, F_OK) == -1)
{
fds = mkfifo(pipeselect, 0700);
if (fds != 0)
{
printf("Pipe creation error\n");
exit(1);
}
}
printf("1. Option 1\n");
printf("2. Option 2\n");
printf("Please select an option: ");
scanf("%d", &select1);
int i = select1;
switch (i)
{
case 1:
if ((fds = open(pipeselect, O_WRONLY)) < 0)
{
printf("Pipe open error\n");
exit(1);
}
write(fds, bufs, i);
close(fds);
printf("Option 1 is selected\n");
break;
case 2:
if ((fds = open(pipeselect, O_WRONLY)) < 0)
{
printf("Pipe open error\n");
exit(1);
}
write(fds, bufs, i);
close(fds);
printf("Option 2 is selected\n");
break;
default:
printf("Wrong Input!\n");
break;
unlink(pipeselect);
exit(0);
}
}
You probably need to use write like this:
bufs[0] = i; // put value entered by user into buffer
write(fds, bufs, 1); // write 1 byte from the buffer
BTW you could narrow down your code like this:
...
scanf("%d", &select1);
if (select1 == 1 || select1 == 2)
{
if ((fds = open(pipeselect, O_WRONLY)) < 0) {
printf("Pipe open error\n");
exit(1);
}
bufs[0] = select1; // put value entered by user into buffer
write(fds, bufs, 1); // write 1 byte from the buffer
close(fds);
printf("Option %d is selected\n", select1);
}
else {
printf("Wrong Input!\n");
}
unlink(pipeselect);
exit(0);
I am having a problem with my assignment I have due for class. I have to create a read/write program that will read a text file into it and write the contents to a new text file. The thing is, I have to use parent/child processes and piping. I have to pass the contents into the pipe with one child, and use another child to read the data from the pipe and write it to a new file.
I have three files: parent.c, read.c and write.c. The program works fine for the most part! It even transfers the data from one file to the other perfectly. The problem I am having is that the write.c process will never complete. I think it may have something to do with the reading from pipe(won't return 0 or EOF). Here is my source code:
parent.c
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFF_SIZE 255
int main(int ac, char* av[])
{
if(ac <3)
{
printf("Please enter all required arguments!\n");
exit(0);
}
int pfd[2];
int pipeCreated;
char readFile[50];
char writePipe[20];
pid_t child_pid_read;
pid_t child_pid_write;
pipeCreated = pipe(pfd);
if(pipeCreated == -1)
{
printf("An error occurred when trying to create a pipe\n");
exit(0);
}
strcpy(readFile, av[1]);
sprintf(writePipe,"%d", pfd[1]);
child_pid_read = fork();
char writeFile[50];
char readPipe[20];
//Handling the read()
switch(child_pid_read)
{
//Error in case forfk() failed
case -1:
perror("fork failed");
return 1;
//Handle child processes
case 0:
if(close(pfd[0]) == -1)
{
printf("An error occurred while closing the pipe\n");
exit(0);
}
if(execle("./read.out", "./read.out", readFile, writePipe, (char*)0, NULL) == -1)
{
printf("Child: Error creating read.\n");
exit(0);
}
default:
wait(&child_pid_read);
strcpy(writeFile, av[2]);
sprintf(readPipe,"%d", pfd[0]);
child_pid_write = fork();
break;
}
//Handling the write
switch(child_pid_write)
{
//Error in case fork() failed
case -1:
perror("fork failed");
return 1;
//Handle child processes
case 0:
if(close(pfd[1]) == -1)
{
printf("An error occurred while closing the pipe\n");
exit(0);
}
if(execle("./write.out", "./write.out", writeFile, readPipe, (char*)0, NULL) == -1)
{
printf("Child: Error creating read.\n");
exit(-1);
}
break;
default:
wait(&child_pid_write);
break;
}
printf("Write completed!");
return 0;
}
read.c:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define BUFF_SIZE 16
int main(int ac, char* av[])
{
char buffer[BUFF_SIZE];
int fd;
int pid;
if(ac > 1)
{
fd = open(av[1], O_RDONLY);
if(fd == -1)
{
printf("error: Could Not Open File\n");
exit(0);
}
pid = atoi(av[2]);
}
int num_read = 1;
while(1)
{
num_read = read(fd, buffer, BUFF_SIZE);
if(num_read == -1)
{
printf("Error reading file\n");
exit(0);
}
if(num_read == 0)
{
break;
}
if(write(pid, buffer, num_read) != num_read)
{
printf("Error writing to pipe\n");
break;
}
}
close(fd);
return 1;
}
write.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define BUFF_SIZE 1
int main(int ac, char* av[])
{
char buffer[BUFF_SIZE];
int fd = open(av[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
int pid = atoi(av[2]);
int num_read = 1;
while(1)
{
num_read = read(pid, buffer, BUFF_SIZE);
printf("num_read: %d\n", num_read);
if(num_read == -1)
{
printf("Error reading pipe\n");
break;
}
if(write(fd, buffer, num_read) != num_read)
{
printf("Error writing to file\n");
break;
}
if(num_read == EOF)
{
break;
}
}
close(fd);
return 1;
}
Please look over my code and suggest corrections. I am passing in the names of the text files through the terminal (./parent.out, oldFile.txt, newFile.txt).
Two problems:
You're not forking the write process until after wait() for the read process returns. If the read process tries to write more data than will fit in the pipe buffer, it will block and never exit. You need to allow both processes to run concurrently to avoid this deadlock. It will work with a small file, but if the file is bigger than 4KB it will hang.
After forking the write process, the parent process has to close pfd[0]. The reader of a pipe doesn't get EOF until all processes that have the write end open close it. It should be:
default:
if(close(pfd[0]) == -1)
{
printf("An error occurred while closing the pipe\n");
exit(0);
}
wait(&child_pid_write);
break;
Your child want to read data,why you close the fd[0], return from pipe indicating that fd[0] for reading and fd[1] for writing.As i can't add a comment, i have to post the comment here....