I am trying to pass a pipe and need to convert its identifiers into strings. My problem is that currently sprintf is turning the identifiers into '4' as a string, which the process being passed to obviously can't use (note: it is being converted to 4 in the issuing process so the problem is not the pass itself)
Code:
Issuing process: (PipeC.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(){
int fd[2], B, C, D, numberRead, i, pipeReturn, *code;
char *arg[4];
char charsRead [10000], fdNumberAsString[256];
pipeReturn = pipe(fd);
if(pipeReturn < 0){ printf("error creating pipe\n"); return;}
sprintf(fdNumberAsString, "%d", fd[0]);
arg[0] = "PipeW1";
arg[1] = fdNumberAsString;
//printf("%d\n", fdNumberAsString);
sprintf(fdNumberAsString, "%d", fd[1]);
//printf("%d\n", fdNumberAsString);
arg[2] = fdNumberAsString;
arg[3] = NULL;
printf("PipeC - fd[0] = string: %s int: %d\n", arg[1], arg[1]);
printf("PipeC - fd[1] = string: %s int: %d\n", arg[2], arg[2]);
//printf("fd[0] = %d, fd[1] = %d\n", fd[0], fd[1]);
B = fork();
if(B == 0){
execv("PipeW1", arg);
printf("execv failed\n");
exit(1);
}
close(fd[1]);
numberRead = read(fd[0], charsRead, 5);
for(i = 0; i < 5; i++)printf("%c ", charsRead[numberRead]);
wait(code);
exit(0);
}
Created Process (PipeW1.c):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int x, char** args){
printf("here\n");
int fd[2], pipeReturn, *ptr;
char num[256];
fd[0] = strtol(*(args+1), &ptr, 10);
printf("%d\n", fd[0]);
printf("PipeW1 - fd[0] = int: %d\n", fd[0], fd[0]);
fd[1] = atoi(*(args+2));
printf("PipeW1 - fd[0] = string: %s int: %d\n", fd[0], fd[0]);
printf("PipeW1 - fd[1] = string: %s int: %d\n", fd[1], fd[1]);
close(fd[0]);
write(fd[1], "12345", 5);
exit(0);
}
Resulting output:
[myname#myserver folder]$ PipeC
PipeC - fd[0] = string: 4 int: 1061374320
PipeC - fd[1] = string: 4 int: 1061374320
4
4
[myname#myserver folder]$```
Related
when i compile my program it does not create a fifo type file, yet i change the permission, but still nothing
I also changed files but still nothing, the code compiles without problem, however when I run then I check if the fifo file is generated, but it is not so no file is generated
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF
#define TEN_MEG (1024 * 1024 * 10)
int main()
{
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes_sent = 0;
char buffer[BUFFER_SIZE + 1];
res = mkfifo(FIFO_NAME, 0777);
if (access(FIFO_NAME, F_OK) == -1) {
res = mkfifo(FIFO_NAME, 0777);
if (res != 0) {
fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}
printf("Process %d opening FIFO O_WRONLY\n", getpid());
pipe_fd = open(FIFO_NAME, open_mode);
printf("Process %d result %d\n", getpid(), pipe_fd);
if (pipe_fd != -1) {
while(bytes_sent < TEN_MEG) {
res = write(pipe_fd, buffer, BUFFER_SIZE);
if (res == -1) {
fprintf(stderr, "Write error on pipe\n");
exit(EXIT_FAILURE);
}
bytes_sent += res;
}
(void)close(pipe_fd);
}
else {
exit(EXIT_FAILURE);
}
printf("Process %d finished\n", getpid());
exit(EXIT_SUCCESS);
}
here is the code of the second entity with which the first communicates
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF
int main()
{
int pipe_fd;
int res;
int open_mode = O_RDONLY;
char buffer[BUFFER_SIZE + 1];
int bytes_read = 0;
memset(buffer, '\0', sizeof(buffer));
printf("Process %d opening FIFO O_RDONLY\n", getpid());
pipe_fd = open(FIFO_NAME, open_mode);
printf("Process %d result %d\n", getpid(), pipe_fd);
if (pipe_fd != -1) {
do {
res = read(pipe_fd, buffer, BUFFER_SIZE);
bytes_read += res;
} while (res > 0);
(void)close(pipe_fd);
}
else {
exit(EXIT_FAILURE);
}
printf("Process %d finished, %d bytes read\n", getpid(), bytes_read);
exit(EXIT_SUCCESS);
}
I think the problem is blocking. The open will block if no process is reading.
For example, you might read from the fifo using:
cat /tmp/my_fifo
Here is a modified version of your code, to demonstrate:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "/tmp/my_fifo"
#define BUFFER_SIZE PIPE_BUF
#define TEN_MEG (1024 * 1024 * 10)
int main()
{
int pipe_fd;
int res;
int open_mode = O_WRONLY;
int bytes_sent = 0;
char buffer[BUFFER_SIZE + 1];
res = mkfifo(FIFO_NAME, 0666);
if (access(FIFO_NAME, F_OK) == -1) {
res = mkfifo(FIFO_NAME, 0666);
if (res != 0) {
fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
}
printf("Process %d opening FIFO O_WRONLY\n", getpid());
pipe_fd = -1;
while(pipe_fd == -1) {
printf("Sleeping in loop \n");
sleep(1);
//Either of these versions work, but one will block, while the
//other will allow the loop to run
// pipe_fd = open(FIFO_NAME, open_mode ); // blocking version
pipe_fd = open(FIFO_NAME, open_mode | O_NONBLOCK); // non-blocking
}
printf("Process %d result %d\n", getpid(), pipe_fd);
char greeting[] = "Hi there\n";
write(pipe_fd, greeting, strlen(greeting));
printf("Process %d finished\n", getpid());
exit(EXIT_SUCCESS);
}
You can use the open() line with O_NONBLOCK or the one without. In either case the process will wait until someone reads from the fifo.
Running into strange error I'm totally failing to troubleshoot. I have a fork which loads an executable I know exists, but none of the code executes. It does not fail, which I know because I check exactly that, so I'm really baffled bu what's going on. Here is the code of the two processes:
Process 1(PipeC.c):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(){
int fd[2], B, C, D, numberRead, i, pipeReturn;
char *arg[3];
char charsRead [10000], fdNumberAsString[256];
pipeReturn = pipe(fd);
if(pipeReturn < 0){ printf("error creating pipe"); return;}
sprintf(fdNumberAsString, "%d", fd[0]);
arg[0] = fdNumberAsString;
//printf("%d\n", fdNumberAsString);
sprintf(fdNumberAsString, "%d", fd[1]);
//printf("%d\n", fdNumberAsString);
arg[1] = fdNumberAsString;
arg[2] = NULL;
printf("fd[0] = string: %s int: %d\n", arg[0], arg[0]);
printf("fd[1] = string: %s int: %d\n", arg[1], arg[1]);
//printf("fd[0] = %d, fd[1] = %d\n", fd[0], fd[1]);
B = fork();
if(B == 0){
execv("PipeW1", arg);
printf("Fork failed");
exit(1);
}
close(fd[1]);
numberRead = read(fd[0], charsRead, 5);
for(i = 0; i < 5; i++)printf("%c ", charsRead[numberRead]);
exit(0);
}
Process Two (PipeW1.c):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int x, char** args){
printf("here");
int fd[2], pipeReturn;
char num[256];
fd[0] = atoi(*args);
fd[1] = atoi(*(args+1));
printf("fd[0] = string: %s int: %d\n", fd[0], fd[0]);
printf("fd[1] = string: %s int: %d\n", fd[1], fd[1]);
close(fd[0]);
write(fd[1], "12345", 5);
exit(0);
}
The second process was even printing earlier... Very confused as I said, any ideas?
edit: output:
[myname#myschool Lab6]$ PipeC
PipeC - fd[0] = string: 4 int: -737006768
PipeC - fd[1] = string: 4 int: -737006768
here
[myname#myschool Lab6]$
I've wrote two programs q & p to redirect the return value with dup2 from q to p.
I'm doing fork() in "p" and using execl to use "q" with child process that I'm creating. also I'm using dup2 to redirect the output of "q" to parent process in "p" to finally print it out.
I'm wondering why I can't see the output to the screen if I'm changing this line in "q" main:
printf("return value from q: %s\n", returnByte(argv, str)); to this line: returnByte(argv, str);
I'm new with this kind of programming, I'll appreciate any explanation.
q program:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
char* returnByte(char* argv[], char* str);
int main (int argc, char* argv[]){
char str[20];
printf("return value from q: %s\n", returnByte(argv, str));
}
char* returnByte(char* argv[], char* str){
float res = atof(argv[1])+atof(argv[2]);
snprintf(str, sizeof(str), "%.2f", res);
return str;
}
p program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
int main(){
int i;
float r[4];
srand(time(NULL));
for (i=0; i<4; i++){
r[i] = (float)rand() / (float)(RAND_MAX/100);
}
char arg1[10], arg2[10];
snprintf(arg1, sizeof(arg1), "%.2f", r[0]);
snprintf(arg2, sizeof(arg1), "%.2f", r[1]);
int pfd[2];
pipe(pfd); //Creating a new pipe
switch(fork()){ //fork()ing
case -1:
printf("error occured during fork()ing");
break;
case 0: //Child process filling "q"'s job using dup2 & execl
close(pfd[0]);
dup2(pfd[1], 0);
close(pfd[1]);
execl("./q", "./q", arg1, arg2, NULL);
break;
default: //Parent process display the output of q into the screen
waitpid(-1, NULL, 0); //Wait until child process terminate (finish "q"'s job)
close(pfd[1]);
dup2(pfd[0], 1);
close(pfd[0]);
break;
}
return 0;
}
I am trying to implement a small IPC in C, but I have an issue that I can't solve.
My main process have two children, child A and child B; Child A gets created first.
I have two pipes to pass information to these processes, pipefd and pipefd2.
First, parent process reads a file's content, and writes to both pipes these two values:
1-length of the string
2-string itself
Once they get the length of string, they create a char array with the given length, and then read the string into this array.
Then both children read from their pipes. Child B can get these values correctly from the pipe, but child A gets 0 as size.
Here's my code, thanks for your time!
Output :
Child A here, input read, size is: 0
Size is 45169child reads input, size : 45169
Child B here, input read, size is: 45169
//
// Created by Dilara on 16.02.2020.
//
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MESSAGESIZE 10
#define READ_END 0
#define WRITE_END 1
int fsize(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET); //go back to where we were
return sz;
}
void writeToPipe(int fd[2], char string[], long stell){
close(fd[READ_END]);
write(fd[WRITE_END], stell, sizeof(stell));
write(fd[WRITE_END], string, strlen(string)+1);
close(fd[WRITE_END]);
}
static void readFromPipe(int pipefd[2], char input[],long size){
// wait(NULL);
close(pipefd[WRITE_END]);
read(pipefd[READ_END], input, size);
printf("child reads input, size : %d \n",size);
close(pipefd[READ_END]);
}
static long readSize(int pipefd[2]){
long size;
close(pipefd[WRITE_END]);
read(pipefd[READ_END], size, sizeof(size));
printf("Size is %d",size);
close(pipefd[READ_END]);
return size;
}
int main()
{
int pipefd[2];
int pipefd2[2];
int childA_pid;
int childB_pid;
if (pipe(pipefd) == -1)
{
perror(" pipe");
return 0;
}
if (pipe(pipefd2) == -1)
{
perror(" pipe");
return 0;
}
childA_pid = fork();
if(childA_pid == 0){
//childA
long SIZE = readSize(pipefd);
char input[SIZE];
readFromPipe(pipefd, input, SIZE);
printf("Child A here, input read, size is: %d \n",SIZE);
}
else{
childB_pid = fork();
if(childB_pid == 0){
long SIZE = readSize(pipefd2);
char input[SIZE];
readFromPipe(pipefd2, input, SIZE);
printf("Child B here, input read, size is: %d \n",SIZE);
}else{
//parent
char *buffer;
FILE *fp = fopen("try.txt", "r");
if (fp != NULL)
{
fseek(fp, 0L, SEEK_END);
long stell = ftell(fp);
rewind(fp);
char str[stell];
buffer = (char *)malloc(stell);
if (buffer != NULL)
{
//fread(buffer, stell, 1, fp);
fread(str,stell,1, fp);
// printf("%s", str);
fclose(fp);
fp = NULL;
free(buffer);
}
printf("SIZE: %d", stell);
writeToPipe(pipefd2, str,stell);
writeToPipe(pipefd, str,stell);
}
}
}
return 0;
}
write(fd[WRITE_END], stell, sizeof(stell));
I think your code lacks an ampersand here. Instead of the stell variable you should use its address:
write(fd[WRITE_END], &stell, sizeof(stell));
I would like to fork a child and connect pipes to the stdin and stdout of child. And then run the exec ./xx. After that I send 17 from parent to child and child print it. all good so far. but when I send a 17 return to parent it doesnt work.
The result is : output nothing and look like wait for some input.
if I remove the code "fscanf(b, "%d", &x); " in parent, the output is:
from C 0 from p 17
I pretty confuse why I get the odd result?? Thank you
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
int main(int argc, char** argv) {
int fds[2], cp[2], x = 0;
pipe(fds);
pipe(cp);
int pid=fork();
// c
if (pid==0) {
close(fds[1]);
close(cp[0]);
dup2(fds[0],0);
dup2(cp[1], 1);
close(cp[1]);
close(fds[0]);
execlp("./xx", "xx", 0);
}
// p
if (pid) {
close(fds[0]);
close(cp[1]);
dup2(fds[1],1);
close(fds[1]);
FILE* a=fdopen(1, "w");
FILE* b=fdopen(cp[0], "r");
fprintf(a, "17");
fscanf(b, "%d", &x);
fprintf(stderr, "from C %d", x);
}
return 0;
}
XX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
int main() {
int y = 0;
FILE* r=fdopen(STDIN_FILENO, "r");
fscanf(r, "%d", &y);
fprintf(stderr, "from p %d \n ", y);
FILE* w=fdopen(STDOUT_FILENO, "w");
fprintf(w, "17");
return 0;
}
I think I figured it out. You need to flush your output buffers. fprintf only does this by default for stderr. So in the parent.c file:
fprintf(a, "17");
fflush(a);
And in the child:
fprintf(w, "17");
fflush(w);
I would have expected that to work on its own, but I'm not a C expert, and it didn't. However, changing the two lines in the parent to
fprintf(a, "17\n");
fflush(a);
made it work for me.
Use this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
int main(int argc, char** argv) {
int fds[2], cp[2], x = 0;
pipe(fds);
pipe(cp);
int pid = fork();
if (pid==0) {
close(fds[1]);
close(cp[0]);
dup2(fds[0], 0);
dup2(cp[1], 1);
execlp("./xx", "xx", NULL);
}
if (pid > 0) {
close(fds[0]);
close(cp[1]);
FILE * a = fdopen(fds[1], "w");
FILE * b = fdopen(cp[0], "r");
fprintf(a, "17\n");
fflush(a);
fscanf(b, "%d", &x);
fprintf(stderr, "from C %d\n", x);
} else {
// error while fork
perror("fork"); // print error to console.
return 1;
}
return 0;
}
And xx:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
int main() {
int y = 0;
FILE* r = stdin;
fscanf(r, "%d", &y);
fprintf(stderr, "from p %d \n ", y);
FILE* w = stdout;
fprintf(w, "17\n");
fflush(w);
return 0;
}
It's working for me :)