我尝试做的是运行程序并返回整个输出并一次打印一行结果。
当我使用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;
}
答案 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]);
}
}