Arguments for the program must be strings.
Therefore, to transfer the identifier of the semaphore, the identifier of the shared memory and the file descriptor to the executable program, the code of the calling program for converting numbers to strings is necessary, and the executable program for converting strings back to a number, which then uses it accordingly.
'Pipe2' does not appear in your code ... I assumed that it was a simple int , but if it was an array (for example, pipe1 is), then you need to fine-tune it with 0 or 1 to get the corresponding file descriptor:
char shmarg[20]; char semarg[20]; char piparg[20]; int semid = semget (key1, 4, IPC_CREAT | 0666); int shmid = shmget(key2, 1024, 0644 | IPC_CREAT); int pipe1[2]; const char *cmd = "/home/tropix/program-3"; if (pipe(pipe1)) { printf("Failed to create pipe: %s\n", strerror(errno)); exit(1); } snprintf(shmarg, sizeof(shmarg), "%d", shmid); snprintf(semarg, sizeof(semarg), "%d", semid); snprintf(piparg, sizeof(piparg), "%d", pipe2); execl(cmd, cmd, semarg, shmarg, piparg, (char*)0); fprintf(stderr, "File Execution of program 3 failed.\n"); exit(1);
It is not clear why you created pipe1 ; you need to do the appropriate plumbing with it. If execl() returned, this did not work. You do not need to check its return value.
From the comments:
[I] just cut out the appropriate sections for simplicity [...] [I] not sure what you mean by "appropriate plumbing" with pipe1? Can you tell me how this should be done, or pass me some information on how I can initialize the channel and transfer it to the next file? I understand that creating a channel in a program requires this to be the best option, but in this case it needs to be initialized in program 1.
Simplicity in question is a good idea ...
I assume that between the call to pipe() and execl() was fork() , which was omitted. Otherwise pipe() makes no sense.
Presumably, the goal of creating the channel is to allow the child process to talk to the parent or the parent process to talk to the child. Bidirectional pipes exist, but they are neither standard nor portable; therefore, I suppose you have a regular unidirectional pipe. Since you pass the file descriptor number as an argument to the child, we do not redirect standard input or standard output for the child — this is what you often (but not always) do with the pipe.
So your updated code could be (empty lines removed to avoid scrollbar):
char shmarg[20]; char semarg[20]; char piparg[20]; int semid = semget(key1, 4, IPC_CREAT | 0666); int shmid = shmget(key2, 1024, 0644 | IPC_CREAT); int pipe1[2]; const char *cmd = "/home/tropix/program-3"; if (pipe(pipe1)) { printf("Failed to create pipe: %s\n", strerror(errno)); exit(1); } pid_t pid = fork(); if (pid < 0) err_exit("Failed to fork"); else if (pid > 0) { close(pipe1[0]); ...write to pipe1[1]... } else { close(pipe1[1]); snprintf(shmarg, sizeof(shmarg), "%d", shmid); snprintf(semarg, sizeof(semarg), "%d", semid); snprintf(piparg, sizeof(piparg), "%d", pipe1[0]); execl(cmd, cmd, semarg, shmarg, piparg, (char*)0); fprintf(stderr, "File Execution of program 3 failed.\n"); exit(1); }
Obviously, if the channel is read by the parent and written by the child, you need to juggle the closure and the specified file descriptor number.
Almost always, you end with at least one of the two file descriptors returned from pipe() . If you redirect the pipe to standard input or standard output, you usually use dup2() to duplicate the corresponding end of the pipe, and then close both file descriptors returned from pipe() . Since all this is fiddling with pipes, it is usually called plumbing.