[About] [Copertina] |
Articoli
La pigrizia è la madre della creazione.
Se c'è una cosa che mi dà fastidio è dover
spostare le mani dalla tastiera del computer, cercare i numeri di
telefono nelle varie agende e comporre il numero.
Pensate quello che volete, ma sono pigro.
Per rimediare a questo terribile stato di fatto mi sono posto
l'obiettivo di far fare al computer ciò che non ho voglia di
fare io stesso.
Dopo un po' di mumble mumble ho deciso di realizzare un piccolo
database di nomi e numeri di telefono e un programmino che
legga dalla mia cara riga di comando il nome della persona a cui
voglio telefonare, componga il numero usando il modem e attenda la
pressione di un tasto, per resettare il modem dopo che io abbia alzato
la cornetta.
Partiamo dal database di nomi: non ho molte pretese e penso che possa bastarmi un elenco del tipo:
nome1,numero1
nome2,numero2
...,...
Dopo aver riempito un file con questi dati, ho scritto un
pezzetto di codice per leggerlo e trovare il numero di telefono
giusto.
Il codice Perl che fa questa ricerca è il seguente:
#!/usr/bin/perl -w
die "Uso: $0 nome" if ! defined @ARGV;
open(TEL, "$ENV{'HOME'}/.tel.numbers") ||
die "Non trovo i numeri di telefono: $!";
$nomei = shift @ARGV;
$trovato = 0;
while(<TEL>){
chomp;
($nome, $tel) = split /,/;
if($nome eq $nomei){
$trovato = 1;
last;
}
}
close TEL;
die "Numero non trovato\n" if ! $trovato;
print "Chiamo $nome al numero $tel\n";
Ho cercato di scrivere qualcosa che fosse almeno indipendente dall'utente che lo usa, così il file dei nomi-numeri di telefono lo apro come:
open(TEL, "$ENV{'HOME'}/.tel.numbers")
Il Perl definisce un array associativo, %ENV, che
contiene come indici i nomi delle variabili di environment e come
elementi i loro rispettivi valori.
Quindi $ENV{'HOME'} è il valore della variabile
di environment HOME, che contiene la path della home
directory dell'utente.
Il file da consultare l'ho chiamato .tel.numbers, per
evitare che mi disturbasse ad ogni ls.
Un altro array magico definito dal Perl è @ARGV. Questo array contiene la riga di comando, quindi si può verificare che l'utente abbia immesso almeno un parametro, testando semplicemente l'esistenza dell'array, che altrimenti risulterebbe indefinito:
die "Uso: $0 nome" if ! defined @ARGV;
e si può leggere il primo elemento facendolo sgusciare fuori dall'array :
$nomei = shift @ARGV;
A questo punto possiamo scorrere il file, alla ricerca del nome che si suppone l'utente abbia immesso sulla riga di comando:
while(<TEL>){
chomp;
($nome, $tel) = split /,/;
if($nome eq $nomei){
$trovato = 1;
last;
}
}
L'istruzione onomatopeica chomp mangia
l'eventuale carattere di fine riga, mentre lo split
spezza la riga all'altezza della virgola e restituisce una lista che
viene assegnata alle variabili $nome e
$tel.
Se la riga in esame contiene proprio il nome che cerchiamo, usciamo
dal loop e assegnamo il valore 1 alla variabile-flag
$trovato.
A questo punto non ci resta che comunicare al modem i nostri desideri:
open(MODEM, "+>/dev/cua1") ||
die "Non posso usare il modem: $!";
system "/bin/stty raw -echo </dev/cua1";
$in='';
$out="atz\r";
syswrite(MODEM, $out, length($out));
sleep 2;
sysread(MODEM, $in, 1000);
$out="atdt$tel\r";
syswrite(MODEM, $out, length($out));
sleep 2;
sysread(MODEM, $in, 1000);
<>;
close MODEM;
system "/bin/stty cooked echo </dev/cua1";
Innanzi tutto dobbiamo aprire il modem.
Sotto Unix qualsiasi
cosa è un file, anche una seriale. Quindi per comunicare con
la seriale (alla quale è attacato il modem) devo aprire il suo
pseudo-file:
open(MODEM, "+>/dev/cua1")
Il simbolo +> indica che il file deve essere aperto in lettura e scrittura, cosa che ci serve per poter leggere le risposte del modem ai nostri comandi.
Ciò di cui abbiamo ora bisogno è qualche
informazione sulle seriali: per poter comunicare con il modem senza
interferenze si deve configurare la linea in row
mode.
Questa operazione può essere fatta comodamente usando un
comando esterno, che Linux (come ogni altro Unix) è così
gentile da metterci a disposizione:
system "/bin/stty raw -echo </dev/cua1";
In questo modo ho configurato il tty che mi interessa in modalità raw e noecho (incidentalmente uso /dev/cua1, perché ho il modem sulla seconda seriale).
Avrei potuto programmare la linea seriale direttamente in Perl, ma essendo cosa lunga e tediosa, ho preferito usare un comando esterno, probabilmente anche più portabile (ricordate, sono pigro).
A questo punto si può cominciare il colloquio con il modem:
ogni comando viene spedito con una syswrite e il
risultato letto con una sysread.
Ho usato la syswrite al posto della print
per essere sicuro che i miei comandi non siano bufferizzati.
Ho aggiunto qualche sleep per dare al modem il tempo di capire cosa gli chiedo e spedirmi la risposta.
Dopo aver composto il numero, aspetto un input dall'utente:
<>;
l'utente a questo punto può sollevare la cornetta e premere
enter per staccare il modem.
L'operazione di esclusione del modem si ottiene semplicemente
chiudendo il file aperto, poi, perché non si dica che siamo
scortesi, rimettiamo le cose a posto sulla linea con un altro
stty:
system "/bin/stty cooked echo </dev/cua1";
Tutto qui.
C'è ancora un discorsetto da fare sulle persmissions: non
tutti possono permettersi di sparare comandi così ad un
modem.
Nel mio sistema la seconda linea seriale appare così:
$ ls -l /dev/cua1
crw-rw---- 1 root dialout 5, 65 Oct 21 17:28 /dev/cua1
Come si può vedere solo root e gli utenti del
gruppo dialout possono leggere e scrivere questo
file.
La soluzione è quella di listare tutti gli utenti che vogliono
usare questo programmino, in /etc/group, come membri
del gruppo dialout.
Infatti il mio /etc/group recita:
...
dialout:*:20:nando
...
A questo punto il mio utente personale fa parte anche del gruppo dialout e io posso scrivere inpunemente sulla seconda seriale, comunicare con il mio modem e telefonare senza usare la tastiera del telefono.
Ovviamente ci sono molte migliorie che si possono apportare a questo programmino: si potrebbe ad esempio controllare che non ci siano locks sulla seriale che stiamo per usare, controllando /var/lock/, si potrebbe cercare il primo modem libero tra quelli collegati, ecc.
Una possibilità interessante sarebbe quella di chiamare un certo numero di telefono usando una form sul Web. Questo telefono potrebbe essere collegato ad un relais, che potrebbe accendere... ooops!
Bhe, torniamo con i piedi per terra ;-)
A rileggerci al prossimo numero del Pluto Journal.
[About] [Copertina] |