• # Piloter stdin et stdout d'un fils

    Posté par (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);
    }