File reversing copy in c - c

I am trying to finish a program that can fork function a child process, and parent can get the input file (under same directory) , reverse the content of this file, then using pipe function pass to the child process. Child will read the message from pipe and generate an output file. I have finished fork, create pipe and reverse function. However I got stucked on write it to the pipe. I know there must some type confusion when i try to pass the parameter into the write function, Any hits would be appreciated.
Here is the Code I have so far:
#include <stdio.h>
#include <stdlib.h> //exit
#include <string.h>
#include <sys/types.h> //pid_t
#define READ_END 0
#define WRITE_END 1
int main(int argc, char *argv[]){
long loc;
FILE *in, *out;
char ch;
if (argc != 3)
{
printf("Usage %s message\n", argv[0]);
exit(EXIT_FAILURE);
}
int pipefd[2];
int pipe_return = pipe(pipefd);
if((in = fopen(argv[1], "rb")) == NULL) {
printf("Cannot open input file.\n");
exit(1);
}
if((out = fopen(argv[2], "wb"))==NULL) {
printf("Cannot open output file.\n");
exit(1);
}
if(pipe_return == -1)
{
printf("Unable to create pipe\n");
exit(EXIT_FAILURE);
}
pid_t return_from_fork = fork();
if (return_from_fork == -1)
{
printf("Unable to fork\n");
exit(EXIT_FAILURE);
}
else if (return_from_fork == 0) //this is a child
{
char msg;
close(pipefd[WRITE_END]);
int read_return = read(pipefd[READ_END], &msg, 1);
printf("read return:%d\n", read_return);
while(read_return > 0){
fputc(ch, out);
printf("%c",msg);
read_return = read(pipefd[READ_END], &msg, 1);
}
printf("child ends\n");
close(pipefd[READ_END]);
exit(EXIT_SUCCESS);
}
else if (return_from_fork > 0)
{
close(pipefd[READ_END]);
printf("this is parent\n");
fseek(in, 0L, SEEK_END);
loc = ftell(in);
while(loc >= 0L){
fseek(in, loc, SEEK_SET);
ch = fgetc(in);
printf("%c",ch);
int write_r = write(pipefd[WRITE_END], ch, 1);//here is the problem the printf() return -1
printf("%d",write_r);
loc--;
}
printf("\n");
close(pipefd[WRITE_END]);
wait(NULL);
printf("file successful generated.\n");
fcloseall();
exit(EXIT_SUCCESS);
}
}
And Here is the compile result:
zzz#ubuntu:~/Desktop/test$ gcc filereversecopy.c -o run
zzz#ubuntu:~/Desktop/test$ ./run src.txt out.txt
this is parent
�-1
-1e-1c-1n-1e-1t-1n-1e-1s-1 -1a-1 -1s-1i-1 -1s-1i-1h-1T-1
read return:0
child ends
file successful generated.
zzz#ubuntu:~/Desktop/test$

On the line you say is problem you are passing ch to write, and ch is type char. I'm sure you mean &ch instead. I bet if you change that write will return 1 instead of -1.
Also, you seek to the end to start reading, but when you seek to the end you are pointing at EOF. You need to start reading at the position before EOF. So after "fseek(in, 0L, SEEK_END); loc = ftell(in);" adding "loc--; fseek(in, loc, SEEK_SET);" makes it work.

Related

I want to have a text from one file written to the other file through pipes

The following is my code for the said task but the output file shows a bizarre output. Also, is there any way I can do it through system calls (write(), read(), etc.), I am intermingling the system calls and the C language functions but if someone wants to do it via system calls only, then what would the code be ? Thanks in advance! :)
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#define BUFFER_SIZE 512
#define READ_END 0
#define WRITE_END 1
int main(void)
{
int destination_fd;
FILE* fpinput;
char write_message[BUFFER_SIZE];
char read_message[BUFFER_SIZE];
ssize_t bytesRead, bytesWritten;
int fd[2];
if(pipe(fd) == -1)
{
printf("Unable to create the pipe\n");
return -1;
}
pid_t pid;
pid = fork();
if(pid == -1)
{
printf("Unable to create the process\n");
return -1;
}
if(pid > 0)
{
fpinput = fopen("input.txt", "r");
if(fpinput == NULL)
{
printf("Unable to open and read the file\n");
return -1;
}
int i = 0;
while(!EOF){
write_message[i] = fgetc(fpinput);
++i;
}
close(fd[READ_END]);
write(fd[WRITE_END], fpinput, BUFFER_SIZE);
close(fd[WRITE_END]);
fclose(fpinput);
wait(NULL);
}
if(pid == 0)
{
destination_fd = open("copy.txt", O_CREAT | O_WRONLY | O_TRUNC, 0700);
if(destination_fd == -1)
{
printf("Unable to open and write to the file\n");
return -1;
}
close(fd[WRITE_END]);
read(fd[READ_END], read_message, BUFFER_SIZE);
close(fd[READ_END]);
bytesWritten = write(destination_fd, read_message, BUFFER_SIZE);
close(destination_fd);
}
return 0;
}
You have multiple problems.
First the problem you ask about: That you seem to receive "garbage" in the child-process. That's because you attempt to read into the buffer write_message, but then you write the FILE structure fpinput to the pipe.
A second problem is that you won't actually read anything, because while(!EOF) will never iterate. The symbolic constant EOF is replaced with the integer number -1, and when you apply the logical negation operator ! to it you have the value 0 which is false.
I suggest you modify your loop to e.g.
int i = 0;
while ((write_message[i] = fgetc(fpinput)) != EOF)
{
++i;
}
Or perhaps
for (size_t i = 0; i < BUFFER_SIZE && (write_message[i] = fgetc(fpinput)) != EOF; ++i)
{
}
The second loop also include buffer overrun protection.

Reading content of a file in child process and passing it to the parent process using a pipe in C

I want a program which reads a file in the child process and send the string/content to the parent process using simple pipe.
Here is what I have tried, I have read a file and tried to write into the pipe line by line in the while loop. But It doesn't seem to work that way. Your help will be highly appreciated.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
FILE * fptr;
fptr = fopen(argv[1],"r");
char str1;
int pipefds[2];
char buffer[5];
if(pipe(pipefds) == -1)
{
perror("PIPE ERROR");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if(pid == 0)
{
char singleLine[150];
close(pipefds[0]);
while(!feof(fptr))
{
fgets(singleLine, 150, fptr);
//puts(singleLine);
write(pipefds[1], singleLine, sizeof(singleLine));
}
fclose(fptr);
//Close read file descriptor
exit(EXIT_SUCCESS);
}
else if(pid > 0)
{
//wait(NULL); //Wait for child process to finish
close(pipefds[1]); //Close write file descriptor
read(pipefds[0], buffer, 100); //Read pin from pipe
close(pipefds[0]); //Close read file descriptor
printf("%s",buffer);
}
return 0;
}
Check for Program Argument
To ensure that the filename parameter is provided, you could check as follows:
if (argc < 2) {
fprintf(stderr, "usage: progname <filename>");
exit(EXIT_FAILURE);
}
Opening the File
Presumably it makes sense to check whether fopen is successful or not.
You could do a check e.g. like this:
if ((fptr = fopen(argv[1], "r")) == NULL) {
perror("error opening file");
exit(EXIT_FAILURE);
}
Also like mentioned by #pat in the comments this code can be moved to the child.
Reading the file
Reading the file could be done like this:
while (fgets(singleLine, sizeof(singleLine), fptr)) {
write(pipefds[1], singleLine, strlen(singleLine));
}
Like mentioned by Jonathan Leffler in the comments one should not check feof upfront. Also important to note that you don't want to write sizeof(singleLine) bytes, because lines can have variable size and be shorter then the buffer size, so better to use strlen(singleLine) here.
Reading the Data
Reading the data must happen in a loop - as long as data is available. The call of read returns the number of bytes read.
ssize_t n;
while ((n = read(pipefds[0], buffer, sizeof(buffer) - 1)) > 0) {
buffer[n] = '\0';
printf("%s", buffer);
}
To make sure that you don't save data beyond the end of the buffer, you can use sizeof(buffer) - 1 as the third argument to the read call.
Programm
So your program, slightly modified regarding the above points, could look like this:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int pipefds[2];
char buffer[100];
if (argc < 2) {
fprintf(stderr, "usage: progname <filename>");
exit(EXIT_FAILURE);
}
if (pipe(pipefds) == -1) {
perror("PIPE ERROR");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == 0) {
FILE *fptr;
if ((fptr = fopen(argv[1], "r")) == NULL) {
perror("error opening file");
exit(EXIT_FAILURE);
}
char singleLine[150];
close(pipefds[0]);
while (fgets(singleLine, sizeof(singleLine), fptr)) {
write(pipefds[1], singleLine, strlen(singleLine));
}
int error = ferror(fptr);
fclose(fptr);
if (error) {
perror("error reading file");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
} else if (pid > 0) {
close(pipefds[1]);
ssize_t n;
while ((n = read(pipefds[0], buffer, sizeof(buffer) - 1)) > 0) {
buffer[n] = '\0';
printf("%s", buffer);
}
close(pipefds[0]);
}
return 0;
}

named pipe won't open in C program

I have user read/write permissions on a pipe. Group has read. Other has read. But program gets "stuck" when I run it. Program 1 is the "parent". Program 2 is the "child".
Program 1:
int main(int argc, char * argv[])
{
FILE *fptr; //for opening and closing input file
int fdw;// write to pipe;
int fdr; //read to pipe;
pid_t pid;
int inputarray[500];
int arraylength = 0; int j =0;
char *mypipe = "mypipe";
if (argc < 2)
{
printf("Need to provide the file's name. \n");
return EXIT_FAILURE;
}
//open input file
fptr = fopen(argv[1], "r");
if (fptr==NULL)
{
printf("fopen fail.\n");
return EXIT_FAILURE;
}
//read input file and fill array with integers
while (!feof(fptr))
{
fscanf(fptr,"%d",&inputarray[arraylength]);
arraylength = arraylength + 1;
}
fclose(fptr); //close input file
pid = fork();
mkfifo(mypipe, 0666);
fdw = open("mypipe",O_WRONLY);
if (fdw < 0)
{
perror("File can't open to write.");
return;
}
int b;
b=3;
write(fdw,&b,sizeof(b));
close(fdw);
if ( pid ==-1)
{
perror("fork");
exit(1);
}
int status; //exit status of child
if(pid==0)//if child process
{
execl("program2", (char*) NULL);
}
else //if parent process
{
wait(&status);}
if((WIFEXITED(status)))
{
printf("Child's exit code %d", WEXITSTATUS(status));
}
else{
printf("Child did not terminate with exit");}
}
Program 2:
int fdl;
int data;
fdl = open("mypipe",O_RDONLY);
if ( fdl < 0)
{
perror("File can't open to read.");
return;
}
read(fdl,&data,sizeof(data));
close(fdl);
The program will block on writing to the fifo until what it's writing is being read. The reading in the child process won't happen since the execl() doesn't happen until after the writing.
Also, it looks like both processes will actually attempt to write to the fifo since you fork() and then immediately start writing.
You should fork(), then test on the returned PID. The parent should then write to the fifo while the child should call execl(). The fifo should be created by the parent before the fork() call.
You should also consider using indent or clang-format to properly format your code, which eases reading it and may expose bugs (forgotten curly braces etc.).
A simple complete example program. The parent writes a string to the child and the child reads it character by character and outputs it to standard output:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
void parent(void);
void child(void);
int main(void) {
pid_t pid;
mkfifo("myfifo", 0666); /* fails if exists, but we don't care here */
if ((pid = fork()) < 0)
abort();
if (pid == 0)
child(); /* will not return */
else
parent();
return EXIT_SUCCESS;
}
void parent(void) {
int fd;
int len;
int ret;
int stat;
char *ptr;
char *msg = "Hello World!";
if ((fd = open("myfifo", O_WRONLY)) < 0)
abort();
len = strlen(msg) + 1;
ptr = msg;
puts("Parent: About to write to child");
while ((ret = write(fd, ptr, len)) != 0) {
if (ret > 0) {
len -= ret;
ptr += ret;
} else
abort();
}
close(fd);
puts("Parent: Waiting for child to exit");
wait(&stat);
printf("Parent: Child exited with status %d\n", stat);
}
void child(void) {
int fd;
int ret;
char ch;
if ((fd = open("myfifo", O_RDONLY)) < 0)
abort();
puts("Child: About to read from parent");
while ((ret = read(fd, &ch, 1)) != 0) {
if (ret > 0)
putchar(ch);
else
abort();
}
putchar('\n');
close(fd);
puts("Child: I'm done here");
exit(EXIT_SUCCESS);
}
In this case, since both child and parent processes are in the same context, I could have used an anonymous pipe pair created with pipe(), but this illustrates the flow, including the creation of the named pipe.

Parent process killing child process in infinite loop

To solve my problem, I set
prctl(PR_SET_PDEATHSIG, SIGHUP); as in stackoverflow answer before i called exec*, and took out the part where we pipe the PID. It works!!!!! Wow....
HOWEVER, stackoverflow won't let me say I've answered my own question yet...
So I tried to write a program, which I want to run a program, and kill that program after a cpl seconds if it doesn't finish. DADDY forks off a CHILD, which forks off another BABY, CHILD pipes the PID of the BABY to DADDY, which then waits a second and kills them both if they haven't wrapped up their business (it's a macabre scene). But it doesn't work, DADDY stays in S+ State, and the infinite loop that is Baby goes on forever until I ctr+c. On the bright side, this code is an amalgamation of everything I've learnt on stack-overflow. Here we go.
#include <math.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static int read_from_pipe(int file)
{
int c;
FILE *stream = fdopen(file, "r");
if (fscanf(stream, "%d", &c) != 1)
{
fprintf(stderr, "Failed to read integer from pipe\n");
exit(1);
}
fclose(stream);
return c;
}
static void write_to_pipe(int file, int pidRacket)
{
FILE *stream = fdopen(file, "w");
fprintf(stream, "%d", pidRacket);
fclose(stream);
}
static int spawnpipe(char *fileName, int *fd)
{
int pid;
int pipe_fds[2];
char *command[] = {"racket", fileName, NULL};
if (pipe(pipe_fds) < 0)
{
fprintf(stderr, "FE: pipe\n");
exit(1);
}
switch ((pid = fork()))
{
case -1:
printf("syserr");
exit(1);
case 0:
close(1);
close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
exit(EXIT_FAILURE);
default:
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
static int spawnfp(char *fileName, FILE **fpp)
{
int fd, pid;
pid = spawnpipe(fileName, &fd);
*fpp = fdopen(fd, "r");
return pid;
}
int main(int argc, char *argv[])
{
pid_t pid;
int mypipe[2];
if (pipe(mypipe))
{
fprintf(stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
pid = fork();
if (pid < (pid_t) 0)
{
fprintf(stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else if (pid != (pid_t) 0)
{
double diff = 0;
clock_t launch = clock();
close(mypipe[1]);
int pidRacket = read_from_pipe(mypipe[0]);
while (diff < 1.3)
{
clock_t done = clock();
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
}
kill(pidRacket, SIGKILL);
kill(pid, SIGKILL);
return EXIT_SUCCESS;
}
else if (pid == (pid_t) 0)
{
close(mypipe[0]);
char buf[100];
FILE *fp;
char *fileName = argv[1];
int pidRacket = spawnfp(fileName, &fp);
write_to_pipe(mypipe[1], pidRacket);
if (argc == 1)
{
printf("Not enough arguments!");
_exit(EXIT_FAILURE);
}
else if (argc == 2)
{
}
sleep(1);
while (fgets(buf, sizeof buf, fp))
{
printf("%s\n", buf);
}
fclose(fp);
kill(pid, SIGKILL);
return 0;
}
}
Credit to quinsley and vijay!
Various comments as I look at the code:
End messages with newlines; you're on Linux now, not Windows. Windows systems seem to encourage people to leave messages without newlines, but it won't work well on Unix in general and Linux in particular.
Don't use _exit() if you want your error messages to appear, especially ones that don't end in a newline.
Don't report error messages on standard output; report them on standard error (that's what it is for!).
Writing else if (argc == 2) { } (with nothing in the braces) is a little odd if there is an else clause after it, but it is pointless when there is no else clause. You should arguably test for argc != 2 since that is the correct number of arguments (or, perhaps more accurately, any arguments beyond argc == 2 are ignored).
If you want to sleep for a time involving sub-second timing (e.g. 1.3 seconds), use one of the appropriate sub-second sleep commands. In this case, nanosleep() is probably the function to use.
Don't use SIGKILL except in dire emergency. The process signalled with SIGKILL has no chance to clean up or anything; it is killed immediately (assuming your process is allowed to send a signal to the other at all, of course).
case -1: printf("syserr"); with no break; after it means that on error, the flow of control goes into the following case 0: code, which is not what's required. Either break; or exit(1); is probably appropriate. (Bullet 3 applies too.)
Don't close standard error. The code:
close(1);
close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
_exit(EXIT_FAILURE);
is never going to report an error; you closed standard error. Remember that programs are entitled to have a standard error channel. The C standard guarantees it, but you have to cooperate and make sure you've not closed standard error.
Some of the casts in:
diff = ((double)((uintmax_t)(clock_t)done) - (double)((uintmax_t)(clock_t)launch)) / (double)CLOCKS_PER_SEC;
are unnecessary. Since both done and launch are of the type clock_t, the casts to clock_t are unnecessary. The intermediate cast to uintmax_t also isn't really necessary. You could simply write:
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
and even then, two of the three casts are theoretically redundant (any two of the three could be removed).
The code in read_from_pipe() is curious and error prone. Since you've got a file stream, simply read an integer from it using fscanf(), rather than the curious construct using double arithmetic and fractional values that are then multiplied at the end. This is especially appropriate since the write_to_pipe() code uses printf("%d", ...); to write the data. Since c is already an int, the cast in return (int)c; is superfluous.
Theoretically, it would be a good idea to check the streams returned by fdopen() to ensure that the operation did not fail.
If the pipe() function fails, you report the error on standard output and then continue as nothing had gone wrong.
It is not clear what the racket command actually does. It doesn't exist on my machine.
argv in spawnfp() is unused.
pid = fork(); if (pidDos < (pid_t) 0) generates a warning (accurately) that pidDos might be used uninitialized. The condition should presumably be using pid, not pidDos. You then send a SIGKILL signal to the PID identified at random by pidDos, which is unlikely to lead to happiness.
When I copy cat to racket and invoke the following code (as a program mk built from mk.c) as mk /etc/passwd, I get to see the password file double-spaced (and the message from the shell about Killed: 9.
#include <math.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static int read_from_pipe(int file)
{
int c;
FILE *stream = fdopen(file, "r");
if (fscanf(stream, "%d", &c) != 1)
{
fprintf(stderr, "Failed to read integer from pipe\n");
exit(1);
}
fclose(stream);
return c;
}
static void write_to_pipe(int file, int pidRacket)
{
FILE *stream = fdopen(file, "w");
fprintf(stream, "%d", pidRacket);
fclose(stream);
}
static int spawnpipe(char *fileName, int *fd)
{
int pid;
int pipe_fds[2];
char *command[] = {"racket", fileName, NULL};
if (pipe(pipe_fds) < 0)
{
fprintf(stderr, "FE: pipe\n");
exit(1);
}
switch ((pid = fork()))
{
case -1:
printf("syserr");
exit(1);
case 0:
close(1);
close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
exit(EXIT_FAILURE);
default:
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
static int spawnfp(char *fileName, FILE **fpp)
{
int fd, pid;
pid = spawnpipe(fileName, &fd);
*fpp = fdopen(fd, "r");
return pid;
}
int main(int argc, char *argv[])
{
pid_t pid;
int mypipe[2];
if (pipe(mypipe))
{
fprintf(stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
pid = fork();
if (pid < (pid_t) 0)
{
fprintf(stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else if (pid != (pid_t) 0)
{
double diff = 0;
clock_t launch = clock();
close(mypipe[1]);
int pidRacket = read_from_pipe(mypipe[0]);
while (diff < 1.3)
{
clock_t done = clock();
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
}
kill(pidRacket, SIGKILL);
kill(pid, SIGKILL);
return EXIT_SUCCESS;
}
else if (pid == (pid_t) 0)
{
close(mypipe[0]);
char buf[100];
FILE *fp;
char *fileName = argv[1];
int pidRacket = spawnfp(fileName, &fp);
write_to_pipe(mypipe[1], pidRacket);
if (argc == 1)
{
printf("Not enough arguments!");
_exit(EXIT_FAILURE);
}
else if (argc == 2)
{
}
sleep(1);
while (fgets(buf, sizeof buf, fp))
{
printf("%s\n", buf);
}
fclose(fp);
kill(pid, SIGKILL);
return 0;
}
}
I fixed some, but by no means all, of the issues identified in this revision of the code.
Oh, and item 16: the read end of the pipe isn't closed until the third process terminates. You need to pass mypipe[1] to spawnfp(), which needs to relay it to spawnpipe(), and the child created there needs to close the pipe descriptor before executing 'racket'. This is compounded by fscanf() looking for either EOF or a non-digit at the end of the PID it reads from the pipe. You could provide a newline or something at the end and that would also free up the parent process to spin in its timing loop. Since you say racket doesn't terminate, that's why you don't see anything much.
It's easier to paste the whole program again than present the diffs:
#include <assert.h>
#include <math.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static int read_from_pipe(int file)
{
int c;
FILE *stream = fdopen(file, "r");
assert(stream != 0);
if (fscanf(stream, "%d", &c) != 1)
{
fprintf(stderr, "Failed to read integer from pipe\n");
exit(1);
}
fclose(stream);
return c;
}
static void write_to_pipe(int file, int pidRacket)
{
FILE *stream = fdopen(file, "w");
assert(stream != 0);
fprintf(stderr, "%d: pidRacket = %d\n", (int)getpid(), pidRacket);
fprintf(stream, "%d", pidRacket);
fclose(stream);
}
static int spawnpipe(char *fileName, int *fd, int pfd)
{
int pid;
int pipe_fds[2];
char *command[] = {"racket", fileName, NULL};
if (pipe(pipe_fds) < 0)
{
fprintf(stderr, "FE: pipe\n");
exit(1);
}
switch ((pid = fork()))
{
case -1:
printf("syserr");
exit(1);
case 0:
close(pfd);
close(1);
//close(2);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execvp(*command, command);
perror("execv");
exit(EXIT_FAILURE);
default:
fprintf(stderr, "%d: pid = %d\n", (int)getpid(), pid);
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
static int spawnfp(char *fileName, FILE **fpp, int pfd)
{
int fd, pid;
pid = spawnpipe(fileName, &fd, pfd);
*fpp = fdopen(fd, "r");
assert(*fpp != 0);
return pid;
}
int main(int argc, char *argv[])
{
pid_t pid;
int mypipe[2];
if (pipe(mypipe))
{
fprintf(stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
pid = fork();
if (pid < (pid_t) 0)
{
fprintf(stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else if (pid != (pid_t) 0)
{
double diff = 0.0;
clock_t launch = clock();
close(mypipe[1]);
fprintf(stderr, "%d: Reading from pipe:\n", (int)getpid());
int pidRacket = read_from_pipe(mypipe[0]);
fprintf(stderr, "%d: Read PID %d from pipe\n", (int)getpid(), pidRacket);
while (diff < 1.3)
{
clock_t done = clock();
diff = ((double)done - (double)launch) / (double)CLOCKS_PER_SEC;
printf("%f\n", diff);
}
kill(pidRacket, SIGKILL);
kill(pid, SIGKILL);
return EXIT_SUCCESS;
}
else if (pid == (pid_t) 0)
{
close(mypipe[0]);
char buf[100];
FILE *fp;
char *fileName = argv[1];
int pidRacket = spawnfp(fileName, &fp, mypipe[1]);
fprintf(stderr, "%d: Writing PID %d to pipe\n", (int)getpid(), pidRacket);
write_to_pipe(mypipe[1], pidRacket);
fprintf(stderr, "%d: Written PID to pipe\n", (int)getpid());
if (argc == 1)
{
printf("Not enough arguments!");
_exit(EXIT_FAILURE);
}
else if (argc == 2)
{
}
sleep(1);
while (fgets(buf, sizeof buf, fp))
{
printf("%s\n", buf);
}
fclose(fp);
fprintf(stderr, "%d: Finished reading from pipe\n", (int)getpid());
kill(pid, SIGKILL);
return 0;
}
}
I made this a while back for stupid fun, it uses up a big chunk of your cpu to run but I'm sure you can modify it to break at a certain point or to fit your needs maybe.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(int argc, char*argv[])
{
int childpid;
int pids[100];
int count1 = 0, count2 = 0;
int count3 = 0;
L1:
childpid = fork();
if(childpid == 0)
{
}
else
{
if(childpid != 0 && childpid != -1)
{
if(count3 < 100)
{
pids[count3] = childpid;
printf("Pid:%d\n",pids[count3]);
count3++;
goto L1;
}
else
{
count3--;
goto L2;
}
}
L2:
while(count3 > 0)
{
if(pids[count3] != -1 || pids[count3] != 1)
{
printf("Killing pid:%d\n",pids[count3]);
kill(pids[count3],SIGKILL);
}
count3--;
}
if(count3 == 0)
{
goto L1;
}
}
return 0;
}

I want to redirect the execv of ls in a file and then in a pipe, why is not working?

First of all, I want to redirect the output of ls (exec) in a file and then from a file to pipe, why is not working? It's ok when I redirect in a file, but that's all.
How can I do to find the length of the output of ls? (that's why I did a redirect to a file).
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
int main()
{
char input[]="ls",ch, delim[]=" ",*result,aux[2000],*user=NULL,*password=NULL,aux1[2000],aux2[2000],aux3[2000],aux4[2000],*arg[1000];
int p1[2],p2[2],i,j,len,nrRead,ok,log,f;
pid_t pid,pidd;
pid=fork(); f=open("alice.txt",O_RDWR|O_TRUNC|O_CREAT,0700);
if(pid == 0){
i=0;
printf("f: %d",f);
if(strlen(input) == 2) {arg[0]="ls";arg[1]=NULL; i=2;}
else
{
result=strtok(input,delim);
arg[i++]=result;
result=strtok(NULL,delim);
while(result!= NULL)
{
printf("LS --- 5\n");
arg[i++]=result;
result=strtok(NULL,delim);
}
arg[i]=NULL;
}
close (1);
if (dup2(f,1) == -1)
{
fprintf (stderr, "dup - 1\n");
exit (9);
}
if( 0 == (pidd=fork())) {
execvp("ls",arg);
}
close(f);
i=0;
while(0 != read(1,&ch,sizeof(char)))
{
aux4[i]=ch;
i++;
}
aux4[i]='\0';
close(1);
if (dup2(p2[1],1) == -1)
{
fprintf (stderr, "dup - 1\n");
exit (9);
}
//close(p2[1]);
len=strlen(aux4);
//printf("LUNG: %d",len);
write(1,&len, sizeof(4));
return 0;
} else {
wait(NULL);
close(p2[1]);
read(p2[0],&len,sizeof(int));
printf("pp: %d",len);
}
}
Instead of forking and duping yourself you can conveniently use popen to do what you want. If you really need to know the size of the output beforehand, you don't need to redirect to a file, you can simply count the bytes you can read from the pipe before you hit EOF. Example (no error checking):
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fd;
char *buf;
size_t size; /* counter for output size */
fd = popen("ls", "r"); /* open a pipe running ls for reading ("r") */
size = 0;
while (fgetc(fd) != EOF) {
size++;
}
pclose(fd);
printf("Output is %d bytes\n", size);
fd = popen("ls", "r");
buf = malloc(size+1);
while (fgets(buf, size, fd)) {
fputs(buf, stdout); /* do what you want here */
}
pclose(fd);
return 0;
}
Note that if you intend to parse the ls output later to find files or directories, you are much better off using the opendir, readdir and closedir functions on Unix.

Resources