2010-03-23 24 views
4

J'essaie de développer un démon simple "telnet/server" qui doit exécuter un programme sur une nouvelle connexion socket. Cette partie fonctionne très bien.forkpty - socket

Mais je dois associer mon nouveau processus à un pty, car ce processus a des capacités de terminal (comme une readline).

Le code que j'ai developpé est (où socketfd est le nouveau descripteur de fichier socket pour la nouvelle connexion d'entrée):

int masterfd, pid; 
const char *prgName = "..."; 
char *arguments[10] = ....; 

if ((pid = forkpty(&masterfd, NULL, NULL, NULL)) < 0) 
    perror("FORK"); 
else if (pid) 
    return pid; 
else 
{ 
    close(STDOUT_FILENO); 
    dup2(socketfd, STDOUT_FILENO); 

    close(STDIN_FILENO); 
    dup2(socketfd, STDIN_FILENO); 

    close(STDERR_FILENO); 
    dup2(socketfd, STDERR_FILENO); 

    if (execvp(prgName, arguments) < 0) 
    { 
     perror("execvp"); 
     exit(2); 
    } 
} 

Avec ce code, le fichier stdin/stdout/stderr descripteur de mon « prgName "sont associés à la socket (en regardant avec ls -la/proc/PID/fd), et donc, les capacités du terminal de ce processus ne fonctionne pas. Un test avec une connexion via ssh/sshd sur le périphérique distant, et l'exécution de "localy" (sous la connexion ssh) prgName, montre que le stdin/stdout/stderr fd de ce processus "prgName" est associé à un pty (et ainsi les capacités terminales de ce processus fonctionnent bien).

Qu'est-ce que je fais mal? Comment associer mon socketfd avec le pty (créé par forkpty)?

Remerciez

Alex

Répondre

4

Vous devez écrire un code pour transférer des données de la prise du pty maître et vice-versa. C'est généralement un travail de processus parent. Notez que le transfert de données doit être bidirectionnel. Il y a beaucoup d'options: select() - cycle conduit à suivre à la fois la masterfd et la socketfd

(comme indice, le code très mauvais, pas pour la production !!! erreur est manquante et contrôles de fin de fichier !!!)

for (;;) { 
    FD_ZERO(&set); 
    FD_SET(masterfd,&set); 
    FD_SET(socketfd,&set); 
    select(...,&set,...); 
    if (FD_ISSET(masterfd,&set)) { 
     read(masterfd,&c,1); 
     write(socketfd,&c,1); 
    } 
    if (FD_ISSET(sockerfd,&set)) { 
     read(sochetfd,&c,1); 
     write(masterfd,&c,1); 
    } 

ou une paire de threads, un pour socketfd-> masterfd et un pour les transferts masterfd-> sockefd.

(comme indice, le code très mauvais, pas pour la production !!!)

/*thread 1 */ 
     while (read(masterfd,&c,1) > 0) 
      write(socketfd,&c,1); 


/*thread 2 */ 
     while (read(socketfd,&c,1) > 0) 
      write(masterfdfd,&c,1); 

Quoi qu'il en soit vous devez ajouter du code dans le côté parent de la branche.

Cordialement

--- --- EDIT Bien sûr, vous ne devez pas rediriger fd 0,1 et 2 à socketfd dans le processus de l'enfant.

+0

Ok merci. Y at-il un moyen de faire un "dup" au lieu de copier manuellement le masterfd à la sockfd et vice versa? Ou y a-t-il un moyen de rendre la slavefd communiquant directement avec le socketfd (au lieu de créer un masterfd) en utilisant d'autres fonctions (openpty, grantpt, ...)? – Alexxx

+0

Pour autant que je sache, non, il n'y a pas de mécanisme automatique pour "lier" un descripteur de fichier à un autre (peut-être que c'est une "bonne question" à poster sur débordement de pile!). J'ai peur que vous deviez choisir l'une des solutions "traditionnelles". Au revoir! –