#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
int val;
if(argc!=2)
{
printf("Usage: %s <descriptor> \n", argv[0]);
exit(1);
}
val=fcntl(atoi(argv[1]), F_GETFL, 0);
switch(val & O_ACCMODE)
{
case O_RDONLY:
printf("read only");
break;
case O_WRONLY:
printf("write only");
break;
case O_RDWR:
printf("read write");
break;
default:
printf("unknown access mode");
}
if(val & O_APPEND)
printf(", append");
if(val & O_NONBLOCK)
printf(", nonblocking");
if(val & O_SYNC)
printf(", synchronous writes");
putchar('\n');
exit(0);
}
in the command line input why i have to specify
$./a.out 0 </dev/tty
$./a.out 1 > temp
even though fcntl is checking only argument 1 .
pl somebody explain why i have to pass a file with redirection symbol in command line argument.
Related
I'm trying to code a simple fork() and pipe() program which gets input from the user and outputs it through the pipe in the childprocess. But somehow I'm not getting the result I wished to get.
The first input works fine, for example I type in "Hi" and get the result "Prozessmanager: Hi", but as soon as I try to input the next string, it crashes or somehow stops working until I input a "Q" which exits my Program.
I tried to debug it and got the result, that I'm trying to write into a broken pipe.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
//#include <signal.h>
#define BUFSIZE 512
//int clock = 0;
//void handler(int signum) {
//clock++;
//printf("Clock: 00:00:%d\n", clock);
//}
int main(int argc, char** argv) {
pid_t prozessmanager;
pid_t reporter;
int pipefd[2];
int status;
char str[BUFSIZE];
char buf[BUFSIZE];
if ((pipe(pipefd)) == -1) {
perror("pipe() error");
exit(1);
}
if ((prozessmanager = fork()) == -1) {
perror("fork() error");
exit(1);
} else if (prozessmanager == 0) { //Prozessmanager prozess
while (1) {
//signal(SIGALRM, handler);
//while(1){
//alarm(1);
//}
close(pipefd[1]);
read(pipefd[0], buf, sizeof (buf));
/*if (*buf == 'S') {
//handler(clock);
} else {*/
if (*buf == 'P') {
if ((reporter = fork()) == -1) {
perror("fork() error");
exit(1);
} else if (reporter == 0) { //Reporter prozess
printf("Im a Report Prozess, PID: %d\n", getpid());
exit(0);
} else { //Prozessmanager waits for Reporter
wait(&status);
printf("Report terminated, PID: %d\n", reporter);
break;
}
} else if (*buf == 'Q') {
printf("Exit Prozessmanager, PID: %d\n", getpid());
exit(0);
} else {
printf("Prozessmanager: %s", buf);
break;
}
//}
}
} else { //Kommandant prozess
while (1) {
close(pipefd[0]);
fgets(str, 80, stdin);
write(pipefd[1], str, sizeof (str));
if (*str == 'Q') {
break;
}
}
wait(&status);
printf("Exit Kommandant, PID: %d\n", getpid());
exit(0);
}
return (0);
}
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);
}
}
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....
I'm writing a coprocess program using pipe. It works fine when the child read some data, handle it and output it. But when I read all the data and handle it, it just pending. Any body have some idea? Thank you.
Here is the source code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
#define MAXSIZE 1024
char workload[MAXSIZE];
char result[MAXSIZE];
workload[strlen(workload)] = EOF;
int workload_size = strlen(workload);
int fd1[2], fd2[2];
int n;
pid_t pid;
if (pipe(fd1) < 0 || pipe(fd2) < 0) {
fprintf(stderr, "pipe error: %s\n", strerror(errno));
exit(1);
}
if ((pid = fork()) < 0) {
fprintf(stderr, "fork error: %s\n", strerror(errno));
exit(1);
} else if (pid > 0) {
close(fd1[0]);
close(fd2[1]);
while(fgets(workload, MAXSIZE, stdin) != NULL)
{
workload_size = strlen(workload);
if (write(fd1[1], workload, workload_size) != workload_size) {
fprintf(stderr, "write to pipe error: %s\n", strerror(errno));
exit(1);
}
if ((n = read(fd2[0], result, MAXSIZE)) < 0) {
fprintf(stderr, "read from pipe error: %s\n", strerror(errno));
exit(1);
}
if (n == 0) {
fprintf(stderr, "child closed the pipe\n");
exit(1);
}
result[n] = 0;
if (puts(result) == EOF) {
fprintf(stderr, "fputs error\n");
exit(1);
}
}
} else {
close(fd1[1]);
close(fd2[0]);
if (fd1[0] != STDIN_FILENO) {
if (dup2(fd1[0] ,STDIN_FILENO) != STDIN_FILENO) {
fprintf(stderr, "dup2 error to stdin.\n");
exit(1);
}
close(fd1[0]);
}
if (fd2[1] != STDOUT_FILENO) {
if (dup2(fd2[1] ,STDOUT_FILENO) != STDOUT_FILENO) {
fprintf(stderr, "dup2 error to stdout.\n");
exit(1);
}
close(fd2[1]);
}
if (execl("./a.out", "a.out", NULL) < 0) {
fprintf(stderr, "execl error: %s\n", strerror(errno));
exit(1);
}
exit(0);
}
return 0;
}
Here is the source code of a.out, it works well with this:
#include <stdio.h>
#include <string.h>
int main()
{
#define MAXSIZE 1024
char x[MAXSIZE];
int n;
while(scanf("%s", x) != EOF)
{
printf("len:%d %s", strlen(x), x);
fflush(stdout);
}
return 0;
}
But it seems just pending when I write the code like this:
#include <stdio.h>
#include <string.h>
int main()
{
#define MAXSIZE 1024
char x[MAXSIZE];
int n;
while(scanf("%s", x) != EOF);
printf("Ok\n");
fflush(stdout);
return 0;
}
The way you are calling scanf with %s may overflow the x buffer. You should at least modify the scanf with a width modifier.
#include <stdio.h>
#include <string.h>
int main()
{
#define MAXSIZE 1024
char x[MAXSIZE];
int n;
while(scanf("%1024s", x) != EOF)
{
printf("len:%d %s", strlen(x), x);
fflush(stdout);
}
return 0;
}
And similarly for your other program.
The reason your program is getting blocked is because your second a.out program is looped doing another scanf, when at the same time the parent program is trying to read a response back into result.
You should test and loop while not feof and you might use popen & pclose
You probably want to use some multiplexing system call like poll