Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

c - read a file and perform operation through another program and save the output in a separate file using system calls

  //  This is my code for reading a file from command line arguments and storing it in another file.//
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <sys/types.h>
    #include <fcntl.h>
    
    #include <unistd.h> //for system calls such as dup(),pipe(),etc...
    
    #include <sys/wait.h>
    
    #define COUNT_PROGRAM "b"
    #define CONVERT_PROGRAM "c"
    
    int main(int argc, char *argv[])
    {
        if (argc != 3)
        {
            fprintf(stderr,"%s","ERROR : argument count not satisfied!
");
            exit(1);
        }
    
        /* It is important to check all system calls (open, creat, dup, etc.) for a return value < 0, 
        particularly -1 because such a return value means an error has occurred. */
    
        int fd_in = open(argv[1], O_RDONLY);
        if (fd_in < 0) 
        {
            fprintf(stderr,"%s", "ERROR : file to be read does not exist!
");
            exit(1);
        }
        
     int fd_out = creat(argv[2], 0644); /* mode = permissions, here rw-r--r-- */
        if (fd_out < 0)
        {
            fprintf(stderr,"%s", "ERROR : file could not be created!
");
            exit(1);
        }
        
        
        if(dup(fd_in) < 0)//dup fd_in to 3
            fprintf(stderr , "ERROR assigning STREAM 3 to fd_in");     
        if(dup(fd_out) < 0)//dup fd_in to 4
            fprintf(stderr , "ERROR assigning STREAM 4 to fd_out");
    
        //dup fd_in to 0
        close(0);
        dup(fd_in);
        close(3);
    
        //dup fd_out to 1
        close(1);
        dup(fd_out);
        close(4);
    
        int fd[2];
    
        pipe(fd);   
    
        pid_t pid_child_1, pid_child_2;
        int status;
    
        if ((pid_child_1 = fork()) != 0)
        {      
            if ((pid_child_2 = fork()) != 0) 
            { 
                close(fd[0]);         
                close(fd[1]);  
                wait(&status);
                wait(&status);          
                // fprintf(stderr , "
status of child_1 = %d",wait(&status));           
                // fprintf(stderr , "
status of child_2 = %d",wait(&status));       
            } 
            else 
            {
                // close(fd[1]);
                // dup(1);       
                dup2(fd[1],1);  
                close(fd[0]);
                execl( CONVERT_PROGRAM, CONVERT_PROGRAM, (char*) NULL);
            }    
        } 
            
        else 
        {
            // close(fd[0]);
            // dup(0);
            dup2(fd[0],0);
            close(fd[1]);
            execl( COUNT_PROGRAM , COUNT_PROGRAM ,(char*) NULL);  
        }
    
    
    }

After compiling my text file which should contain the output is empty. THOSE PROGRAMS ARE WORKING WELL ALONE.

Here I am adding the strace result after running the strace command. Here it is printing 7 on the screen and no output in the text file.

  read(3, "177ELF21133>120352"..., 8                                                                             32) = 832
strace: Process 6018 attached
strace: Process 6019 attached
[pid  6019] read(3, "177ELF21133>120352                                                                             0"..., 832) = 832
[pid  6018] read(4, "177ELF21133>120352                                                                             0"..., 832) = 832
[pid  6019] read(0, "hello my name is himanshu KAUSHI"..., 4096) = 35
[pid  6019] read(0, "", 4096)           = 0
[pid  6019] write(1, "HELLO MY NAME IS HIMANSHU kaushi"..., 35) = 35
[pid  6019] +++ exited with 0 +++
[pid  6018] read(0, "HELLO MY NAME IS HIMANSHU kaushi"..., 4096) = 35
[pid  6017] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=6019, si_u                                                                             id=1062, si_status=0, si_utime=0, si_stime=0} ---
[pid  6018] read(0, "", 4096)           = 0
[pid  6018] write(2, "
7", 2
7)          = 2
[pid  6018] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=6018, si_uid=1062, si_                                                                             status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

I changed standard table descriptors in 1st dup2(f_dsc[1],3) command and I got the output in the text file but then my first program stooped running.

#include<stdio.h>
#include<ctype.h>

int main()
{
        char c;
        int count=0;

                while(1)
                {
                        c=getchar();
                        if(c==EOF)
                        {
                                break;
                        }
                        if(!isalpha(c))
                        {
                                count++;
                        }
                }
                fprintf(stderr,"
%d",count);


}

this is my simple b program.

#include<stdio.h>
#include<ctype.h>
int main()
{
        char c;
        int count=0;
        while(1)
        {
                c=getchar();
                if(c==EOF)
                {
                        break;
                }
                if(islower(c))
                {
                        c=toupper(c);
                }
                else
                {
                        c=tolower(c);
                }

                putchar(c);
        }
        return 0;
}

and this is my simple c program.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When I try your program, it correctly executes equivalently to

c <a.txt | b >b.txt

So, let's consider what may be different in your setup. Although you write

    /* It is important to check all system calls (open, creat, dup, etc.) for a return value < 0, 
    particularly -1, because such a return value means an error has occurred. */

you don't check the return value of the execl calls (or just put perror("…"); after them to see if they fail). Perhaps b or c is a script without a first line like

#!/bin/sh

You can get away without such a line when calling the script from a shell (I guess you mean that when you yell THOSE PROGRAMS ARE WORKING WELL ALONE), but not when using execl.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...