Previous Contents Next

4   Corrigé du DS du 18 janvier 2001

Tous documents autorisés (y compris ordinateurs).

4.1   Manipulations sous X11

Voici les réponses aux questions :
  1. Vous souhaitez lancer une application graphique de la machine artichaud avec affichage sur la machine poireau. Les deux machines tournent sous X11 et sont connectées en réseau (mais sans montage NFS). Donnez les lignes à taper sur les deux machines pour que l'exécution réussisse.
    poireau$ xauth list
    artichaud$ xauth add poireau:0 <clef trouvée au-dessus>
    artichaud$ export DISPLAY=poireau:0
    artichaud$ xeyes &
             
  2. En supposant que les droits adéquats sont accordés, donnez le nom du serveur X11 lancé par les commandes ci-dessous :
    artichaud$ export DISPLAY=poireau:0
    artichaud$ Xnest :5
          
    C'est un serveur s'exécutant sur artichaud (bien que s'affichant sur poireau), le nom est donc artichaud:5.
  3. Même question pour la commande ci-dessous :
    artichaud$ ssh poireau "export DISPLAY=artichaud:0 ; Xnest :7"
          
    C'est un serveur s'exécutant sur poireau (bien que s'affichant sur artichaud), le nom est donc poireau:7.
  4. Quelle(s) option(s) faut-il ajouter à la commande Xnest pour lancer un serveur X11 avec des droits d'utilisation pour n'importe quel utilisateur de n'importe quelle machine ?
    Il faut désactiver les protections par l'option -ac.

4.2   Programmation réseau

Voici les réponses aux questions :
  1. Donnez le code permettant d'initialiser une structure ARRAYofARRAY8 avec une seule adresse IP contenue dans la variable globale adresseIP de type struct in_addr.
    Exemple de code convenable :
    ARRAYofARRAY8 listeAdresses;
    ARRAY8 adresse;
    adresse.length=sizeof adresseIP;
    adresse.data=(CARD8Ptr)&adresseIP;
    adresses.length=1;
    adresses.data=&adresse;
          
  2. Donnez la fonction remplissant une structure XdmcpBuffer avec un paquet XDMCP de type MANAGE. Le prototype de cette fonction est imposé :
    XdmcpBufferPtr remplirManage(CARD32 sessionID,CARD16 displayNumber);
          
    Exemple de code convenable :
    XdmcpBufferPtr remplirManage(CARD32 sessionID,CARD16 displayNumber){
    XdmcpBufferPtr buffer;
    XdmcpHeader header;
    ARRAY8 displayClass;
     
    /* Allocation du tampon XDMCP */
    
    buffer=allocXDMCPBuffer();
    
    /* Ecriture de l'entete XDMCP */
    
    header.version=XDM_PROTOCOL_VERSION;
    header.opcode=(CARD16)MANAGE;
    header.length=8+strlen(DISPLAY_CLASS);
    XdmcpWriteHeader(buffer,&header);
    
    /* Ecriture des champs additionnels */
    
    XdmcpWriteCARD32(buffer,sessionID);
    XdmcpWriteCARD16(buffer,displayNumber);
    displayClass.length=strlen(DISPLAY_CLASS);
    displayClass.data=DISPLAY_CLASS;
    XdmcpWriteARRAY8(buffer,&displayClass);
    
    return buffer;
    } 
          
  3. Donnez la fonction decoderAccept de décodage d'un paquet XDMCP du type ACCEPT contenu dans une structure XdmcpBuffer (l'entête XDMCP est sensée avoir été déjà lue). Précisez bien le prototype de cette fonction. Vous pouvez supposer que les fonctions ARRAY8toString et ARRAY8toHexa sont déjà écrites.
    Exemple de code convenable :
    CARD32 decoderAccept(XdmcpBufferPtr paquet){
    ARRAY8 authenName,authenData;
    ARRAY8 authorName,authorData;
    CARD32 sessionID;
    
    /* Initialisation des champs d'Accept */
    authenName.length=authenData.length=0;
    authenName.data=authenData.data=NULL;
    authorName.length=authorData.length=0;
    authorName.data=authorData.data=NULL;
    
    /* Lecture des champs dans le tampon */
    if(XdmcpReadCARD32(paquet,&sessionID) &&
       XdmcpReadARRAY8(paquet,&authenName) &&
       XdmcpReadARRAY8(paquet,&authenData) &&
       XdmcpReadARRAY8(paquet,&authorName) &&
       XdmcpReadARRAY8(paquet,&authorData)){
        char authorDataStr[MAX_CHAINE];
        char authorNameStr[MAX_CHAINE];
        char command[MAX_CHAINE];
    
        /* Conversion en chaines des champs utiles */
        ARRAY8toString(authorName,authorNameStr);
        ARRAY8toHexa(authorData,authorDataStr);
        if(strcmp(authorNameStr,AUTHORIZE_NAME)!=0){
           fprintf(stderr,"Unknown authorization %s\n",authorNameStr);
           exit(-1);
           }
        if(verbose) printf("Authorization data is %s\n",authorDataStr);
        }
    
    /* Libere la memoire */
    XdmcpDisposeARRAY8(&authenName); XdmcpDisposeARRAY8(&authenData); 
    XdmcpDisposeARRAY8(&authorName); XdmcpDisposeARRAY8(&authorData); 
    XdmcpDisposeARRAY8(&status); 
    
    return sessionID;
    }
          
  4. Dites dans quels cas le programme quémandeur de session doit se terminer (on se place dans le cas où tous les paquets XDMCP sont gérés). Soyez précis : terminaison sur réception de tel paquet, après l'envoi de tel autre (avec ou non attente de réponse du serveur), etc.
    Il faut sortir sur réception des paquets UNWILLING et DECLINE. Si l'envoi de paquets KEEPALIVE est implanté il faut en plus sortir lors de la réception de REFUSE ou de FAILED. Il faut aussi sortir si l'on ne reçoit plus de paquet ALIVE. Si on n'implante pas l'envoi de paquets KEEPALIVE, il faut sortir après l'émission du paquet MANAGE et sans s'attendre à une réponse.
  5. En tenant compte de votre réponse à la question précédente, donnez le code de la fonction d'envoi de paquet XDMCP. Ce code doit, bien sûr, envoyer le datagramme au serveur de sessions mais aussi éventuellement gérer la perte de paquets par UDP (réémissions). Le prototype de la fonction est à préciser avec soin.
    Exemple de code convenable :
    void envoyerPaquet(int ds,                      /* Socket locale */
                       XdmcpBufferPtr paquet,       /* Contient le paquet XDMCP */
                       struct sockaddr_in adresse,  /* Socket du serveur */
                       unsigned char reponse        /* Attente d'une reponse ? */
                       ){
    fd_set lecture ;           /* Ensemble de descripteurs en lecture */
    struct timeval minuteur;   /* Structure du minuteur */
    int compteur=0;
     
    while(TRUE) {
    
       /* Envoyer le datagramme XDMCP */
       sendto(ds,paquet->data,paquet->pointer,0,
              (struct sockaddr *)&adresse,sizeof adresse);
    
       /* Sortie immediate si on ne s'attend pas a une reponse */
       if(!reponse) return;
     
       /* Attente d'une reponse avec armement d'un minuteur */
       FD_ZERO(&lecture); FD_SET(ds,&lecture);
       minuteur.tv_sec=MINUTEUR_DUREE; minuteur.tv_usec=0;
       select(ds+1,&lecture,NULL,NULL,&minuteur);
    
       /* Sortie si la reponse est prete a lire */
       if(FD_ISSET(ds,&lecture)) break;
    
       /* Nombre d'essais depasse ? */
       if(++compteur>MAX_COMPTEUR){
          fprintf(stderr,"Server is not answering !\n");
          exit(-1);
          }
       }
    }
          

Previous Contents Next