Pour piloter le stdin et le stdout d'un fils, il faut, juste après le fork(), fermer stdin et stdout et faire un dup() de deux descripteurs de fichier au préalable défini sur respectivement stdin et stdout. Les deux descripteurs de fichier étant connu du père, en écrivant dessus, on pilote mplayer (avec de préférence -slave mais pas obligé).
Exemple de code repompé d'un d'un de mes vieux projets (le programme à lancer s'appelait apt, rien à voir avec Debian) par flemme de chercher dans Google:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> // exit()
#include <string.h> // memset(), strcat()...
#include "apt.h"
#include "msg.h"
#include "init.h"
#include "parse.h"
#define STDIN 0
#define STDOUT 1
#define STDERR 2
/* The size should be around 500, because of the mvts answer */
#define APT_OUTPUT_LINE_MAX_LENGTH 1000
extern config* current_configuration;
int APTIN_K,APTOUT_K;
FILE* STREAM_IN;
FILE* STREAM_OUT;
void APTlaunch(const char *apt_path,int* aptin_k,int* aptout_k){
int childPid;
int pipefdin[2],pipefdout[2];
/* Pipes init */
if( pipe(pipefdin) == -1 || pipe(pipefdout) == -1 ){
perror("Creating apt communication pipes");
exit(1);
}
childPid = fork();
if( !childPid ){
// son, so we launch apt and we connect
// its standards channels to pipes
// close unused channels
close(pipefdin[1]);
close(pipefdout[0]);
// Duplicate stdin to our pipe
close(STDIN);
if( dup(pipefdin[0]) == -1 ){
perror("duplicating apt stdin");
exit(1);
}
// Duplicate stdout to our pipe
close(STDOUT);
if( dup(pipefdout[1]) == -1 ){
perror("duplicating apt stdout");
exit(1);
}
// Duplicate stderr to the same pipe as stdout
close(STDERR);
if( dup(pipefdout[1]) == -1 ){
perror("duplicating apt stderr");
exit(1);
}
// Launch apt
if( execl(apt_path,apt_path,NULL) == -1 ){
perror("can't find apt");
exit(1);
}
}else{
// father, this process, continues execution
// Close unusable channels
close(pipefdin[0]);
close(pipefdout[1]);
// Return the right values to control the apt
*aptin_k = pipefdin[1];
*aptout_k = pipefdout[0];
}
}
void APTstart(const char* apt_path){
// Launch the apt upon the connection
APTlaunch(apt_path,&APTIN_K,&APTOUT_K);
// Use stdio to manipulate the commands
STREAM_IN = fdopen(APTIN_K,"w");
STREAM_OUT = fdopen(APTOUT_K,"r");
}
void APTstop(){
write(APTIN_K,"q\n",2);
}
int APTloadDataFile(const char* filename){
int written;
written = fprintf(STREAM_IN,"load %s%s\n",current_configuration->apt_data_path
,filename);
fflush(STREAM_IN);
return written;
}
int APTsendCommand(const char* cmd){
int written;
written = fprintf(STREAM_IN,"%s\n",cmd);
fflush(STREAM_IN);
return written;
}
char* APTgetNextLine(){
char* line;
line = (char*)malloc(APT_OUTPUT_LINE_MAX_LENGTH*sizeof(char));
fgets(line,APT_OUTPUT_LINE_MAX_LENGTH,STREAM_OUT);
// Careful, the \n is still in line
return line;
}
char* APTgetOutputTillEmptyLine(){
char* buffer;
lineList* acftList = (lineList*)malloc(sizeof(lineList));
lineList* otherLines;
int byteCounter = 0;
acftList->line = APTgetNextLine();
acftList->nextLines = NULL;
otherLines = acftList;
if( acftList->line[0] != '\n' ){
buffer = APTgetNextLine();
while( buffer[0] != '\n' ){
byteCounter += strlen(buffer);
otherLines = addToLineList(otherLines,buffer);
buffer = APTgetNextLine();
}
}
buffer = lineList2string(acftList,byteCounter);
freeLineList(acftList);
return buffer;
}
void APTflushOutput(){
char* line = APTgetNextLine();
while( strcmp(line,"\n") ){
free(line);
line = APTgetNextLine();
}
free(line);
}
# Piloter stdin et stdout d'un fils
Posté par niol (site web personnel) . En réponse au message Gestion STDIN + pilotage Mplayer. Évalué à 1.
Pour piloter le stdin et le stdout d'un fils, il faut, juste après le fork(), fermer stdin et stdout et faire un dup() de deux descripteurs de fichier au préalable défini sur respectivement stdin et stdout. Les deux descripteurs de fichier étant connu du père, en écrivant dessus, on pilote mplayer (avec de préférence -slave mais pas obligé).
Exemple de code repompé d'un d'un de mes vieux projets (le programme à lancer s'appelait apt, rien à voir avec Debian) par flemme de chercher dans Google:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> // exit() #include <string.h> // memset(), strcat()... #include "apt.h" #include "msg.h" #include "init.h" #include "parse.h" #define STDIN 0 #define STDOUT 1 #define STDERR 2 /* The size should be around 500, because of the mvts answer */ #define APT_OUTPUT_LINE_MAX_LENGTH 1000 extern config* current_configuration; int APTIN_K,APTOUT_K; FILE* STREAM_IN; FILE* STREAM_OUT; void APTlaunch(const char *apt_path,int* aptin_k,int* aptout_k){ int childPid; int pipefdin[2],pipefdout[2]; /* Pipes init */ if( pipe(pipefdin) == -1 || pipe(pipefdout) == -1 ){ perror("Creating apt communication pipes"); exit(1); } childPid = fork(); if( !childPid ){ // son, so we launch apt and we connect // its standards channels to pipes // close unused channels close(pipefdin[1]); close(pipefdout[0]); // Duplicate stdin to our pipe close(STDIN); if( dup(pipefdin[0]) == -1 ){ perror("duplicating apt stdin"); exit(1); } // Duplicate stdout to our pipe close(STDOUT); if( dup(pipefdout[1]) == -1 ){ perror("duplicating apt stdout"); exit(1); } // Duplicate stderr to the same pipe as stdout close(STDERR); if( dup(pipefdout[1]) == -1 ){ perror("duplicating apt stderr"); exit(1); } // Launch apt if( execl(apt_path,apt_path,NULL) == -1 ){ perror("can't find apt"); exit(1); } }else{ // father, this process, continues execution // Close unusable channels close(pipefdin[0]); close(pipefdout[1]); // Return the right values to control the apt *aptin_k = pipefdin[1]; *aptout_k = pipefdout[0]; } } void APTstart(const char* apt_path){ // Launch the apt upon the connection APTlaunch(apt_path,&APTIN_K,&APTOUT_K); // Use stdio to manipulate the commands STREAM_IN = fdopen(APTIN_K,"w"); STREAM_OUT = fdopen(APTOUT_K,"r"); } void APTstop(){ write(APTIN_K,"q\n",2); } int APTloadDataFile(const char* filename){ int written; written = fprintf(STREAM_IN,"load %s%s\n",current_configuration->apt_data_path ,filename); fflush(STREAM_IN); return written; } int APTsendCommand(const char* cmd){ int written; written = fprintf(STREAM_IN,"%s\n",cmd); fflush(STREAM_IN); return written; } char* APTgetNextLine(){ char* line; line = (char*)malloc(APT_OUTPUT_LINE_MAX_LENGTH*sizeof(char)); fgets(line,APT_OUTPUT_LINE_MAX_LENGTH,STREAM_OUT); // Careful, the \n is still in line return line; } char* APTgetOutputTillEmptyLine(){ char* buffer; lineList* acftList = (lineList*)malloc(sizeof(lineList)); lineList* otherLines; int byteCounter = 0; acftList->line = APTgetNextLine(); acftList->nextLines = NULL; otherLines = acftList; if( acftList->line[0] != '\n' ){ buffer = APTgetNextLine(); while( buffer[0] != '\n' ){ byteCounter += strlen(buffer); otherLines = addToLineList(otherLines,buffer); buffer = APTgetNextLine(); } } buffer = lineList2string(acftList,byteCounter); freeLineList(acftList); return buffer; } void APTflushOutput(){ char* line = APTgetNextLine(); while( strcmp(line,"\n") ){ free(line); line = APTgetNextLine(); } free(line); }