Fork neither failing nor loading program specified? - c

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]$

Related

Sprintf turning massive number into '4'

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]$```

mkfifo don't make a FIFO special file

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.

Redirecting return value with dup2 from two different programs

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;
}

C on LINUX - Multiple child proces exec unusual number of times

I'm trying to create n = 10 child processes and make its execute a peace of code ..
However it creates 14 child processes indifferent of n.
Why is that?
This is the sample code :
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("It worked! ");
return 0;
}
And this is the main program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char *argv[])
{
int n = 10;
pid_t pid;
int status = 0;
int fd2[2];
int i = 0;
while (i < n)
{
/*create the pipe */
if (pipe(fd2) == -1)
{
fprintf(stderr, "Problem at pipe: %s\n", strerror(errno));
exit(1);
}
/*create fork*/
pid = fork();
if (pid == -1)
{
fprintf(stderr, "Problem at fork: %s\n", strerror(errno));
exit(1);
}
else if (pid == 0) /*in child*/
{
close(fd2[0]);
close(1);
dup2(fd2[1], 1);
close(fd2[1]);
execl("sample.bin", "sample.bin", NULL);
fprintf(stderr, "Problem at exec: %s", strerror(errno));
exit(1);
}
/* in parent */
close(fd2[1]);
char line[255];
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
close(fd2[0]);
wait(&status);
i++;
}
return 0;
}
I corrected the code, now the output is what I've expected. And of course another problem was that I used at read the same variable n.
I modified from this:
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
To this:
int m;
while((m = read(fd2[0], line, 254) > 0)
{
printf("%d The message is: %s\n", i, line);
}

linux C sending data from child to parent is fine, but fail to send data from child to parent

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 :)

Resources