Indirizzare dati da un programma ad un altro e ad un Terminale
Il caso in questione è quello in cui si inviano dati da un programma Gambas ad un altro programma Gambas e ad un Terminale.
Invio dei dati da un programma Gambas ad un altro
In questo caso, abbiamo due progetti Gambas, che per comodità chiameremo A e B. Il progetto A invia dati al progetto B. Per inviare i dati dal programma A al programma B si potranno utilizzare i rispettivi file speciali, ai quali essi sono associati: il loro percorso è /dev/pts/n; oppure si potrà usare il file descriptor associato al processo del programma B che riceve i dati.
Uso dei file speciali /dev/pts/n
Nel progetto A avremo il seguente codice:
Private fl As File Public Sub Form_Open() ' Viene aperto il file speciale (da individuarsi preliminarmente) che rappresenta il progetto B: fl = Open "/dev/pts/B" For Output End Public Sub Button1_Click() ' Viene inviata la stringa di caratteri al file speciale che rappresenta il progetto B: Print #fl, "Testo qualsiasi" End
Nel progetto B avremo, invece, il seguente codice:
Private fl As File Public Sub Form_Open() ' Resta in attesa sino a quando non viene creato il file speciale ' (da individuarsi preliminarmente) che rappresenta il progetto A: Do Wait 0.01 Loop Until Exist("/dev/pts/A") ' Poniamo sotto "osservazione" il file speciale che rappresenta il progetto A: fl = Open "/dev/pts/A" For Read Watch ' Può essere utilizzato anche "Process": pr = Shell "cat < /dev/pts/A" For Read Write As "pr" End Public Sub File_Read() ' Oppure, se si è utilizzato "Process": Public Sub pr_Read() Dim s As String Read #fl, s, -256 TextArea1.Text &= s End
Va sottolineato che, se il programma A scrive i dati nel programma B mediante Print o Write, la stringa compare nella console del progetto B.
Se, invece, l'utente scrive manualmente in console un testo qualsiasi, e, avendo il cursore alla fine di tale testo, preme il relativo tasto Invio della tastiera, la riga di caratteri verrà intercettata dall' "osservatore" Watch del progetto B; e verrà quindi sollevato l'evento File_Read().
Uso del file descriptor n. 1
Nel progamma A, che invia i dati, avremo il seguente codice:
Private fl As File Public Sub Form_Open() fl = Open "/proc/PID_del_programma_B/fd/1" For Output End Public Sub Button1_Click() ' Se si vuole far scrivere nel terminale una riga "sotto" l'altra ' ogni volta che si preme il tasto, allora si utilizzerà "Print": Print #fl, "testo qualsiasi" ' Se si vuole far scrivere nel terminale una riga "dopo" l'altra ' ogni volta che si preme il tasto, allora si utilizzerà "Write": Write #fl, "testo qualsiasi" End
Il programma B, che riceve i dati, avrò un codice simile al seguente:
Private pr As Process Public Sub Form_Open() ' Intercetta i dati dal "file descriptor" n. 1 del suo stesso processo: pr = Shell "cat < /proc/" & Application.Handle & "/fd/1" For Read As "pr" End Public Sub pr_Read() Dim s As String Line Input #pr, s ' Mostria i dati in una "TextLabel": TextLabel1.Text &= s End
Uso della Classe Clipboard
Si potranno trasmettere dati anche sfruttando gli "Appunti" di sistema con una sorta di copia-incolla, da effettuarsi mediante la Classe Clipboard di Gambas. In particolare utilizzeremo le funzioni .Copy() e .Paste() della Classe Clipboard.
Durante il trasferimento dei dati da un programma all'altro bisogna prestare attenzione a non effettuare alcun'altra copia di caratteri (per esempio con il mouse), o comunque di altri dati, altrimenti verrà trasmesso il contenuto della nuova copia di dati appena effettuata.
Ovviamente, trattandosi di "Appunti" di sistema, i dati potranno essere raccolti pure da altri programmi, anche non-Gambas.
Facciamo un esempio pratico. Avendo due programmi, A che deve trasferire dei dati al programma B, nel programma A avremo il seguente codice, capace di copiare dati negli appunti:
Public Sub Button1_Click() Dim s As String s = "Prova trasferimento dati stringa" Clipboard.Copy(s) End
mentre nel programma B avremo il seguente codice, capace di raccogliere quanto precedentemente copiato negli appunti dal programma A:
Public Sub Button1_Click() Dim s As String s = Clipboard.Paste() Print s End
Scrivere nella finestra del Terminale
Se viene aperto un Terminale virtuale distinto dal programma Gambas, e si intende scrivere al suo interno, si potranno utilizzare o il file speciale associato al Terminale aperto: il suo percorso è /dev/pts/n; oppure si potrà usare il file descriptor num. 1 associato al processo del Terminale.
Uso del file speciale della cartella pts
Volendo utilizzare il comando Shell per conoscere il nome del file speciale associato ad un certo terminale virtuale è sufficiente dare allo shell di quel terminale il comando tty:
Shell tty
Se, invece, si vuole fare a meno del comando Shell per conoscere il nome del file speciale associato, bisogna tenere in considerazione che la console dell'IDE di Gambas si comporta come un Terminale virtuale; e pertanto anche ad essa sarà associato un file speciale nella directory /dev/pts/N. Se non sarà già aperto un Terminale virtuale, il numero del file associato alla Console dell'IDE di Gambas, sarà 0, altrimenti sarà il primo numero successivo a quello dell'ultimo Terminale aperto. Identico discorso vale per i terminale virtuali aperti successivamente all'apertura dell'IDE di Gambas.
Mostriamo un codice esemplificativo, con il quale scriveremo all'interno di una finestra Terminale mediante le sole funzioni di Gambas.
E' necessario aver impostato nel progetto anche il componente "gb.desktop" e "gb.desktop.x11":
Public Sub Form_Open() ' Apre un Terminale: Desktop.OpenTerminal End Public Sub Button1_Click() Dim fl As File ' Apre in scrittura il file "speciale" associato al Terminale virtuale appena lanciato. ' Esso può essere individuato in questo modo: fl = Open "/dev/pts" &/ Dir("/dev/pts", "*")[0]" For Write ' ...o anche “For Output” ' Se si intende scrivere nel terminale ogni stringa appresso alla precedente, allora si userà “Write”: Write #fl, "stringa da scrivere nel terminale" ' Se si intende scrivere ogni stringa l'una sotto l'altra, allora si utilizzerà “Print”: Print #fl, "stringa da scrivere nel terminale" ' Oppure semplicemente solo "Print": Print #fl, "stringa da scrivere nel terminale" fl.Close End
N.B. Seppure sia possibile - come abbiamo visto - scrivere all'interno della finestra del terminale, non è però possibile utilizzare tale possibilità per lanciare dalla finestra del Terminale dei comandi, magari in combinazione con l'istruzione "Desktop.Sendkeys(Chr(10))", se non in quest'altra modalità.
Scrivere nel Terminale il risultato di un comando bash
Se si intende far scrivere in un Terminale il risultato complesso e non istantaneo di un comando bash, si porrà sotto osservazione il file speciale pts relativo al Terminale predetto.
Anche nel seguente esempio dovremo attivare i componenti gb.desktop e gb.desktop.x11:
Private fl As File Public Sub Form_Open() Desktop.OpenTerminal() Me.Center End Public Sub processus_Read() Dim s As String Line Input #Last, s Print #fl, s End Public Sub Button1_Click() fl = Open "/dev/pts" &/ Dir("/dev/pts", "*")[0] For Write Shell "echo 'MIA_PASSWORD | sudo -S fdisk -l" For Read As "processus" End
Uso del file descriptor associato al processo del Terminale ed utile alla scrittura dei dati
In tal caso si tratta di individuare preliminarmente il numero del PID del processo del Terminale, e quindi il file descriptor utile per la scrittura nel Terminale dei dati desiderati.
Il codice può essere il seguente:
Private fl As File Public Sub Form_Open() Dim pr, s As String pr = "/proc" &/ PID_del_processo &/ "fd" For Each s In Dir(pr, "*") If Stat(pr &/ s).Link Like "/dev/pts/*" Then Exit Next fl = Open pr &/ s For Output End Public Sub Button1_Click() ' Se si vuole far scrivere nel terminale una riga "sotto" l'altra ' ogni volta che si preme il tasto, allora si utilizzerà "Print": Print #fl, "testo qualsiasi" ' Se si vuole far scrivere nel terminale una riga "dopo" l'altra ' ogni volta che si preme il tasto, allora si utilizzerà "Write": Write #fl, "testo qualsiasi" fl.Close End