为什么我在C中的管道输出仍然产生垃圾数据?

时间:2016-10-30 20:14:26

标签: c memory pipe

我尝试做的是运行程序并返回整个输出并一次打印一行结果。

当我使用a.out作为参数执行程序时,一切都工作到目前为止,直到我开始尝试从管道中读取更多数据。我收到以下结果:

Line 0: 
Line 1: 
MCS-51 Family Macro Assembler ASEM-51 V1.3
Line 2:                                   

Line 3: 
a.out(1): illegal character
Line 4:                    
a.out(2): illegal character
Line 5:                    
a.out(3): illegal character
Line 6:                    
a.out(4): illegal character
Line 7:                    
a.out(5): illegal character
Line 8:                    
a.out(5): no END statement found
Line 9:                         

Line 10: 
             6 errors detected
Line 11:                      
Application tried to create a window, but no driver could be loaded.
Line 12:
Make sure that your X server is running and that $DISPLAY is set      correctly.
Line 13:
err:systray:initialize_systray Could not create tray window
Line 14:

但是,在打印第10行的内容后,我执行的远程程序完成后,第11到14行根本不应出现。

请忽略非法字符语句。这是因为我正在制作一个执行第三方汇编程序的程序,并且我传递了无效的源代码。

我尝试添加一个字符代码255以从子级输出回父级,但是我无法在父级中接收它,但是如果我尝试在我的系统上执行不存在的文件,我和#39;能够发送单词" ERROR"返回父级并在父级中检索它。

我不知道我在这里做错了什么但是我试图找到一种方法来确定何时停止尝试将更多数据读取到父母从中接收垃圾的点孩子而不是真正的输出。

我该如何解决这个问题?

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

char line[100][512];
int numlines=0;

int run(char* dir,char* mainapp,char *par1,char *par2){
int pf[2]; //pf = PipeFields
pipe(pf);
if (fork()==0){
  //CHILD START
  //cmdline = commandline to program = directory (dir) + / + main app name + padded nulls
  char cmdline[10000];
  memset(cmdline,0,10000);
  strcat(cmdline,dir);
  strcat(cmdline,"/");
  strcat(cmdline,mainapp);
  char *args[5]={cmdline,par1,par2,NULL}; //arguments to program
  close(pf[0]);
  //redirect all output streams to same place
  dup2(pf[1],1);
  dup2(pf[1],2);
  //return error as part of output if program can't execute
  if (execve(cmdline,args,NULL) < 0){write(pf[1],"ERROR",5);}
  //return ascii character as last byte to output back to caller
  write(pf[1],(unsigned char*)255,1);
  close(pf[1]);
  //CHILD END
}else{
  //b = buffer
  memset(line,0,51200); //clear all lines of output
  char b[102400];
  memset(b,0,102400); //clear temporary buffer
  char *b2=b; //make reference to buffer for strcat
  char incoming[10001]; //incoming buffer of 10000 bytes of data plus null
  close(pf[1]); //don't need to write to child. close pipe.
  long hasdata=0,sz=0;
  while((sz=read(pf[0],incoming,sizeof(incoming)-1)) > 0){
//execute this while incoming pipe has between 1 and 10000 bytes of data
printf(">>> %ld >> %s\n",sz,incoming); // <-- show output for debugging
incoming[sz]='\0'; //add null to end of incoming data so strcat can work
strcat(b2,incoming); //add incoming data to main buffer
hasdata=1; //we have data
//see if incoming data contains magic character code 255 as a byte
if (strchr(incoming,255)){
  //but this never gets executed? what's going on???
  printf("BREAKKKKK");
  break;
}
  }
  //if theres data then convert it into lines
  if (hasdata==1){
numlines=0; //reset number of lines
char *bp=b; //make reference to data
char *thisln=line[0]; //make reference to line
while(*bp){
  if(*bp=='\n'){ //if theres a new line,...
    numlines++; //increment counter...
    if (numlines > 100){break;} //and exit if theres too many lines
    thisln=line[numlines]; //make reference to next line
  }
  *thisln=*bp; //transfer bytes 1 by 1 to appropiate areas
  bp++;        //and increment pointer
  thisln++;
}
  }
  close(pf[0]);
  }
return 0;
}

int main(int argc,char *argv[]){
  int thisline;
  //get 2 arguments
  if (argc < 2){printf("Filename required\n");return -1;}
  //make sure argument is valid file
  if (access(argv[1],R_OK) < 0){printf("File not found: %s\n",argv[1]);return -2;}
  //run app
  run("/usr/bin","wine","/DOS/8051asm/asemw.exe",argv[1]);
  //print results line by line
  for (thisline=0;thisline<=numlines;thisline++){
printf("Line %d: %s\n",thisline,line[thisline]);
  }
  return 0;
}

1 个答案:

答案 0 :(得分:0)

以下代码应该做你想要的。

注意:当'wine'不可用时,将输出:

execve failed: No such file or directory

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX_LINES    (512)
#define MAX_LINE_LEN (100)

void run(char* mainapp, char *par1, char *par2)
{
    int pf[2]; //pf = PipeFields
    if( pipe(pf) )
    { // then pipe() failed
        perror( "pipe failed" );
        exit( EXIT_FAILURE );
    }

    pid_t pid = fork();
    if( 0 == pid )
    { // child

        //CHILD START
        char *args[]={ mainapp, par1, par2, NULL}; //arguments to program

        close( pf[0] ); // close child output end of pipe
        //redirect all output streams to pipe
        dup2(pf[1],1);
        dup2(pf[1],2);
        close(pf[1]);

        //return error as part of output if program can't execute
        execve(mainapp, args, NULL); // should never return
        perror( "execve failed" );
        exit( EXIT_FAILURE );
    } // end child

    else if (-1 == pid )
    { // error occurred
        perror( "fork failed");
        exit( EXIT_FAILURE );
    } // end fork() error handling

    else
    { // parent
        close( pf[1] ); // close input end of pipe
        size_t thisline;
        char line[ MAX_LINES ][ MAX_LINE_LEN ];
        size_t lineNum=0;
        size_t charNum=0;
        int status;

        memset(line, '\0', MAX_LINES*MAX_LINE_LEN); //clear all lines of output


        while((read(pf[0], &line[lineNum][charNum], 1)) > 0)
        {
            if( '\n' == line[lineNum][charNum] )
            { // then step to next line
                // terminate string
                //charNum++;
                //line[lineNum][charNum] = '\0';
                // init for next line
                lineNum++;
                charNum = 0;
            }

            else
            {
                // step to next char
                charNum++;
            }

            if( charNum >= MAX_LINE_LEN )
            {
                printf( "input line too long -- exiting\n" );
                printf( "%s\n", line[lineNum] );
                wait( &status );
                exit( EXIT_FAILURE );
            }

            if( lineNum >= MAX_LINES )
            {
                printf( "more than %ul lines in file -- exiting\n", MAX_LINES );
                wait( &status );
                exit( EXIT_FAILURE );
            }   
        }
        close( pf[0] ); // close output end of pipe

        //printf( "%lu\n", lineNum); // for testing
        if( strncmp( line[0], "execve", strlen("execve") ) == 0 )
        {
             printf("%s\n", line[thisline]);
        }

        else 
        { // then some data to output
            //print results line by line
            for (thisline=0; thisline<lineNum; thisline++)
            {
                printf("Line %lu: %s\n", thisline, line[thisline]);
            }
        }
    }  // end parent
} // end function: run


int main( int argc, char *argv[] )
{

    if (argc < 2)
    {
        fprintf( stderr, "USAGE: %s <Filename>\n", argv[0]);
        return -1;
    }

    //make sure argument is valid file
    if (access(argv[1],F_OK) < 0)
    {
        perror( "file not found" );
        fprintf( stderr, "Missing file is: %s\n",argv[1]);
        return -2;
    }

    else
    { 
        //run app
        run("/usr/bin/wine", "/DOS/8051asm/asemw.exe", argv[1]);
    }
}
相关问题