Usare uno pseudoterminale per far comunicare bidirezionalmente due programmi
L'intenzione è di far comunicare bidirezionalmente mediante l'uso di un file pseudoterminale due programmi: uno Master e l'altro Slave.
In tal caso il programma Master invia dati al programma Slave, il quale riceve detti dati e ne invia altri al programma Master. Più precisamente ogni dato scritto (in uscita) dal programma Master, appare in entrata sul programma Slave; ed ogni dato scritto (in uscita) dal programma Slave, appare in entrata nel programma Master.
I programmi (il Master e lo Slave) possono essere indifferentemente entrambi programmi Gambas, oppure un programma Gambas ed un programma esterno scritto in altro linguaggio.
Si farà comunque uso di alcune funzioni esterne contenute nella libreria libc.so.6 .
Indice
Esempio pratico
Nell'esempio che segue, abbiamo i codici di un programma Master e di un programma Slave, entrambi in linguaggio Gambas, ciascuno dei quali invia dati all'altro e riceve dati dall'altro.
Va lanciato prima il programma Master, poi il programma Slave.
Il codice del programma Master
Il codice del programma Master è il seguente:
Library "libc:6" ' int grantpt (int __fd) ' Chown the slave to the calling user. Private Extern grantpt(__fd As Integer) As Integer ' int unlockpt (int __fd) ' Release an internal lock so the slave can be opened. Private Extern unlockpt(__fd As Integer) As Integer ' int ptsname_r (int __fd, char *__buf, size_t __buflen) ' Store at most BUFLEN characters of the pathname of the slave pseudo ' terminal associated with the master FD is open on in BUF. Private Extern ptsname_r(__fd As Integer, __buf As Byte[], __buflen As Long) As Integer Public Sub Main() Dim fl As File Dim i As Integer Dim percorsoSlave As New Byte[32] Dim introitus, exitus As String fl = Open "/dev/ptmx" For Read Write ' Accesso di grant al programma 'Slave': i = grantpt(fl.Handle) If i < 0 Then Error.Raise("Errore alla funzione 'grantpt()' !") ' Sblocca il programma 'Slave': i = unlockpt(fl.Handle) If i < 0 Then Error.Raise("Errore alla funzione 'unlockpt()' !") ' Ottiene il percorso del programma 'Slave': i = ptsname_r(fl.Handle, percorsoSlave, percorsoSlave.Count) If i < 0 Then Error.Raise("Errore alla funzione 'ptsname_r()' !") Print "Uso del file pts: "; String@(percorsoSlave.Data); " (da riportare in 'Open' del programma 'Slave')" exitus = "master" Do Read #fl, introitus, -256 If Len(introitus) > 0 Then Print "Lettura" Print "Letti "; Len(introitus); " byte: "; introitus Print Print "Scrittura: "; exitus Write #fl, exitus Print "Scritti "; Len(exitus); " byte\n" Endif Wait 1 Loop fl.Close End
Il codice del programma Slave
Dopo aver lanciato il programma Master, si dovrà avere cura di annotare il file pseudoterminale generato ed utilizzato (mostrato nella console del Master). Il percorso dello pseudoterminale andrà inserito nell'apposita linea di Open del codice del programma Slave, affinché possa essere aperto in lettura ed in scrittura.
Il codice del programma Slave è il seguente:
Library "libc:6" Private Const TCSANOW As Integer = 0 ' int tcgetattr (int __fd, struct termios *__termios_p) ' Put the state of FD into *TERMIOS_P. Private Extern tcgetattr(__fd As Integer, __termios_p As Pointer) As Integer ' void cfmakeraw (struct termios *__termios_p) ' Set *TERMIOS_P to indicate raw mode. Private Extern cfmakeraw(__termios_p As Pointer) ' int tcsetattr (int __fd, int __optional_actions, const struct termios *__termios_p) ' Set the state of FD to *TERMIOS_P. Private Extern tcsetattr(__fd As Integer, __optional_actions As Integer, __termios_p As Pointer) As Integer Public Sub Main() Dim termios As Pointer Dim fl As File Dim i As Integer Dim introitus, exitus As String termios = Alloc(SizeOf(gb.Byte), 60) ' Va inserito il numero del file dello pseudoterminale mostrato nella console del programma "Master": fl = Open "/dev/pts/..." For Read Write i = tcgetattr(fl.Handle, termios) If i < 0 Then Error.Raise("Errore alla funzione 'tcgetattr()' !") cfmakeraw(termios) tcsetattr(fl.Handle, TCSANOW, termios) exitus = "slave" Do Print "Lettura" Read #fl, introitus, -256 Print "Letti "; Len(introitus); " byte: "; introitus Print Print "Scrittura: "; exitus Write #fl, exitus Print "Scritti "; Len(exitus); " byte\n" Wait 1 Loop Free(termios) fl.Close End