[successivo] [precedente] [inizio] [fine] [indice generale] [violazione GPL] [translators] [docinfo] [indice analitico] [volume] [parte]


Capitolo 87.   Stampa

Tradizionalmente, il dispositivo di stampa permette solo la scrittura, cioè si comporta come un file al quale si possono solo aggiungere dati. In questa situazione, la stampa si ottiene semplicemente trasferendo (copiando) un file alla stampante. Naturalmente, il file deve essere stato predisposto in modo da poter essere interpretato correttamente dalla stampante che si utilizza.

Quando si ha la necessità di applicare una trasformazione al file da stampare, prima che questo raggiunga la stampante, si utilizza normalmente un filtro di stampa, cioè un programma o uno script che può essere inserito in una pipeline. I filtri di stampa vengono quindi utilizzati sia per adattare i file da stampare alle caratteristiche particolari della stampante che si ha a disposizione, sia per ottenere degli effetti, come l'aggiunta di intestazioni.

Recentemente sono state introdotte nel mercato stampanti che non si accontentano più di ricevere un file per iniziare a stampare, ma richiedono l'utilizzo di un protocollo di comunicazione, che spesso è mantenuto segreto. Queste stampanti, per funzionare, hanno bisogno della presenza di un programma speciale, predisposto dalla casa produttrice; pertanto non sono compatibili in alcun modo con i sistemi GNU. Si tratta in particolare delle stampanti che utilizzano il cosiddetto Windows printing system. Si deve fare attenzione quindi, prima di acquistare una stampante da usare con un sistema GNU.

Questa parte del documento, dedicata alla stampa, fa riferimento a concetti che verranno chiariti solo più avanti, come la stampa remota e l'utilizzo di strumenti grafici. Sotto questo aspetto, l'argomento dovrebbe essere trattato più tardi; tuttavia, dal momento che l'esigenza di stampare si avverte molto presto, l'argomento viene anticipato. Pertanto, chi ha l'esigenza di realizzare un servente di stampa in grado di ricevere richieste da una rete, se non è già informato su queste cose, deve attendere e leggere una serie di capitoli sul TCP/IP nel volume III.

Per poter utilizzare la stampante, occorre avere compilato il kernel inserendo la gestione della porta parallela e della stampa. Se si utilizza un elaboratore con architettura i386, occorre specificarlo con l'opzione apposita (sezioni 29.2.5 e 29.2.13).

Con kernel più recenti non dovrebbero porsi problemi per la gestione simultanea di attività diverse attraverso la porta parallela.

87.1   Dispositivi e stampa brutale

I dispositivi di stampa sono le porte parallele, o seriali, utilizzate per la connessione con le stampanti. In origine, il nome assegnato alle porte parallele destinate alla stampa, dipendeva dell'indirizzo I/O di queste, secondo l'elenco seguente:

Di solito, la prima porta parallela utilizza l'indirizzo di I/O 37816 e di conseguenza, quasi sempre, il dispositivo utilizzato per la stampa è stato /dev/lp1. Ma questo ragionamento non vale più per i kernel più recenti: adesso la prima porta stampante corrisponde a /dev/lp0. Per controllare è sufficiente eseguire il comando

dmesg | less

e cercare una riga simile a quella seguente:

lp0: using parport0 (polling)

L'utente root può utilizzare direttamente il dispositivo di stampa copiando su di essa il file che vuole stampare.

cp stampa.prn /dev/lp0

Si tratta comunque di un modo di utilizzo della stampante decisamente sconsigliabile o quantomeno da riservare a circostanze particolari. Un'azione del genere corrisponde a quello che in ambiente Dos si poteva fare nel modo seguente:

C:> COPY /B STAMPA.PRN LPT1:

87.2   Visione generale e astratta

Il sistema di stampa tipico si avvale di una coda, ovvero di un deposito in cui accodare i file da inviare alla stampante. Di solito, il programma che si occupa di inserire il file da stampare nella coda non fa altro: per inviare questi file alla stampante c'è un demone apposito che attende di vedere qualcosa nella coda (figura 87.1).

Figura 87.1. Coda di stampa in un sistema locale chiuso.

.----------.
| file da  |          .------------.
| stampare |--------->| programma  |
`----------'          | che accoda |
                      `------------'
                             |
                             |
                             V
                    .-----------------.
                    | directory usata |           .-----------.
                    | come coda di    |---------->| demone    |
                    | stampa:         |           | di stampa |
                    | /var/spool/...  |           `-----------'
                    `-----------------'                 |
                                                        |
                                                        |     .-------------.
                                                        `---->| stampante:  |
                                                              | /dev/lp...  |
                                                              `-------------'

Quando il sistema di stampa gestisce anche le stampe remote, si introduce un protocollo di comunicazione e, assieme a questo, anche qualche problema in più. Dal lato dell'elaboratore che offre il servizio ci deve essere un demone in grado di ricevere queste richieste di stampa, con il compito di accodare tali stampe nel proprio sistema (figura 87.2).

Figura 87.2. Coda di stampa in un sistema che riceve richieste dall'esterno, attraverso la rete.

.---------------.
| porta di      |          .------------.
| comunicazione |--------->| demone in  |
`---------------'          | ascolto    |
                           | che accoda |
                           `------------'
                                 |
                                 |
                                 V
                    .-----------------.
                    | directory usata |           .-----------.
                    | come coda di    |---------->| demone    |
                    | stampa:         |           | di stampa |
                    | /var/spool/...  |           `-----------'
                    `-----------------'                 |
                                                        |
                                                        |     .-------------.
                                                        `---->| stampante:  |
                                                              | /dev/lp...  |
                                                              `-------------'

Per inviare una richiesta di stampa a un elaboratore remoto, ci possono essere due tipi di approcci. Nella situazione più semplice, un programma potrebbe provvedere da solo a riceve il file da stampare e a instaurare la connessione con il nodo remoto al quale questo deve essere rinviato per la stampa; in alternativa, potrebbe essere la stessa coda di stampa locale che si occupa di rinviare la stampa a un nodo remoto (figura 87.3).

Figura 87.3. Trasmissione delle stampe a un nodo remoto.

.----------.
| file da  |          .----------------.
| stampare |--------->| programma che  |
`----------'          | si collega con |          .---------------.
    A                 | un nodo remoto |--------->| porta di      |
                      `----------------'          | comunicazione |
                                                  `---------------'
.----------.
| file da  |          .------------.
| stampare |--------->| programma  |
`----------'          | che accoda |
    B                 `------------'
                             |
                             |
                             V
                    .-----------------.
                    | directory usata |           .-----------.
                    | come coda di    |---------->| demone    |
                    | stampa:         |           | di stampa |
                    | /var/spool/...  |           `-----------'
                    `-----------------'                 |
                                                        |
                                                        |     .---------------.
                                                        `---->| porta di      |
                                                              | comunicazione |
                                                              `---------------'

Spesso, molte funzionalità sono raggruppate assieme in uno stesso programma, o in uno stesso demone. Per esempio, è normale che il demone che si occupa di provvedere alla stampa di ciò che trova nella coda, sia anche in grado di ricevere una richiesta di stampa dall'esterno, provvedendo da solo ad accodarla, ed è normale che lo stesso demone sia in grado di instaurare una connessione con un altro servizio di stampa remoto quando deve demandare la stampa a quel sistema.

87.2.1   Problemi collegati con la stampa remota

La stampa remota introduce tanti piccoli problemi e spesso si deve penare un po' prima di arrivare al risultato. Per prima cosa è necessario che ci sia accordo tra il programma che invia una richiesta di stampa e quello che deve riceverla, cosa questa che riguarda la coerenza con i protocolli relativi. Tuttavia, il protocollo standard che esiste attualmente è insufficiente per le esigenze reali (RFC 1179) e ogni sistema di stampa introduce le sue estensioni più o meno incompatibili con gli altri.

Quando un sistema offre un servizio attraverso la rete, come nel caso di un servente di stampa, si pone il problema di non accettare tutte le richieste incondizionatamente e di stabilire chi sia abilitato ad accedere. In pratica, occorre autenticare gli accessi. Questo problema non è previsto dal protocollo citato e il sistema di stampa che vuole essere compatibile con tutto, può solo limitarsi a selezionare gli accessi in base alla loro origine.

L'ultimo problema da considerare è legato al fatto che con la stampa remota si fanno transitare le informazioni relative attraverso la rete, rischiando l'intercettazione di informazioni che potrebbero essere delicate. Un sistema di stampa evoluto potrebbe prevedere la cifratura di queste comunicazioni, introducendo una propria estensione al protocollo standard.

87.2.2   Filtri di stampa

Nel momento in cui si considera che per stampare si prepara un file e lo si invia alla stampante, per gestire stampanti di tipo diverso in modo trasparente, basta realizzare dei programmi filtro appositi con lo scopo di rielaborare i dati nel modo più opportuno prima di passarli effettivamente alla stampante.

Questi programmi filtro potrebbero essere inseriti in diversi punti della catena di un sistema di stampa; in particolare si potrebbe scegliere se questa elaborazione deve avvenire prima dell'inserimento nella coda di stampa, o se questo debba avvenire dopo. Di solito, i file vengono messi nella coda così come sono, ed è il demone di stampa che si occupa di farli rielaborare da un programma filtro adatto (figura 87.4).

Figura 87.4. Introduzione di un filtro in un sistema di stampa tipico.

.-----------------.
| directory usata |           .-----------.
| come coda di    |---------->| demone    |
| stampa:         |           | di stampa |--------> alla stampante locale
| /var/spool/...  |           `-----------'          o remota
`-----------------'                |^
                                   ||
                                   ||
                                   V|
                             .------------.
                             | programma  |
                             | filtro che |
                             | rielabora  |
                             `------------'

Tuttavia, occorre considerare che si possono fare delle acrobazie imprevedibili per un principiante, per cui la distinzione non diventa più tanto netta. Infatti, capita a volte che il programma filtro prenda i dati e non restituisca nulla, o meglio, invece di restituire qualcosa nel modo previsto, potrebbe farci qualcosa di diverso.

87.2.3   Stampanti virtuali multiple

Un sistema di stampa come descritto astrattamente in queste sezioni, potrebbe essere in grado di gestire code differenti, senza che questo implichi la disponibilità effettiva di più stampanti collegate allo stesso elaboratore. Dal punto di vista del sistema di stampa, queste code sono delle stampanti «virtuali» collegate in qualche modo a delle stampanti reali.

Per fare un esempio pratico, un sistema di stampa potrebbe essere stato configurato in modo da avere due code di stampa: per una stampante locale per una stampante remota. In questo modo, quando si richiede di stampare utilizzando una coda, si ottiene alla fine la stampa attraverso la propria stampante locale, mentre utilizzando l'altra, si ottiene l'invio di una richiesta di stampa a un sistema remoto.

Le possibilità non si limitano a questo; per esempio le code potrebbero essere state distinte perché a ognuna di queste viene attribuito un filtro di stampa differente, di solito per permettere di utilizzare una stampante differente a quella solita. Per esempio, si potrebbe avere la coda denominata lp per la stampa diretta senza filtri; la coda lp-lj da utilizzare quando si collega una stampante HP Laserjet o compatibile; la coda lp-ps da utilizzare quando si collega una stampante PostScript.

87.2.4   Quando il meccanismo dei filtri non funziona bene

In precedenza è stato mostrato lo schema di un sistema di stampa che permette l'inserimento di un filtro prima di arrivare alla stampante. Si è accennato anche al fatto che il demone che legge la coda, mandando i dati al filtro, potrebbe essere difettoso e non essere in grado di rileggere ciò che restituisce il filtro stesso. In questi casi, che sono capitati effettivamente, si può attuare un rimedio, apparentemente un po' strano: il programma filtro, invece di restituire il risultato della sua elaborazione attraverso lo standard output, lo invia in un'altra coda di stampa, per la quale non è previsto alcun filtro (figura 87.5).

Figura 87.5. Quando il meccanismo del filtro è zoppicante.

.-----------------.
| coda di stampa  |           .-----------.
| che prevede un  |---------->| demone    |
| filtro.         |           | di stampa |
`-----------------'           `-----------'
                                   |
                                   |
                                   V
                             .------------.
                             | programma  |
            .----------------| filtro che |
            |                | rielabora  |
            V                `------------'
.-----------------.
| coda di stampa  |           .-----------.
| che non prevede |---------->| demone    |
| alcun filtro    |           | di stampa |--------> alla stampante locale
`-----------------'           `-----------'          o remota

Riprendendo l'esempio già descritto in precedenza, in cui la coda denominata lp è prevista per la stampa diretta senza filtri e la lp-lj è fatta per stampare attraverso una stampante HP Laserjet o compatibile, il filtro abbinato a questa seconda coda, potrebbe semplicemente inviare il risultato della sua elaborazione nella coda di stampa normale, lp, che non avendo filtri non ha alcun problema.

87.3   Sistema di stampa BSD o compatibile

Nei sistemi Unix non esiste un sistema di stampa «standard» per vari motivi, a cominciare dal fatto che i pochi riferimenti disponibili hanno caratteristiche insufficienti rispetto alle esigenze attuali. Bene o male, i comandi per la stampa tendono a imitare il comportamento del sistema di stampa BSD, ovvero il lavoro di Berkeley. (1) Alcune distribuzioni GNU/Linux utilizzano proprio il sistema BSD, altre preferiscono qualcosa di più potente che gli assomiglia vagamente. In generale, non è il caso di approfondire questo o quel sistema di stampa, proprio perché si tratta di una materia in evoluzione, a meno che ci siano delle esigenze particolari, nel qual caso si possono studiare le pagine di manuale o la documentazione che accompagna il sistema di stampa che offre la propria distribuzione GNU.

Figura 87.6. Coda di stampa in stile BSD.

.----------.                                            .---------------.
| file da  |          .-----.           .-----.         | porta di      |
| stampare |--------->| lpr |           | lpd |<--------| comunicazione |
`----------'          `-----'           `-----'         | 515/TCP       |
                         |                 |            `---------------'
                         |     .-----------'
                         |     |
                         V     V
               .--------------------.                        .----------------.
               | coda di stampa     |         .-----.        | configurazione |
               | /var/spool/lpd/... |-------->| lpd |<-------| /etc/printcap  |
               `--------------------'         `-----'        `----------------'
                                               |   |
                                               |   `-------------.
                                               |                 |
                                               V                 V
                                        .------------.      .-----------.
                                        | stampante  |      | stampante |
                                        | locale     |      | remota    |
                                        | /dev/lp... |      `-----------'
                                        `------------'

Come si può vedere nella figura 87.6, il sistema di stampa in stile BSD si avvale del programma lpr per accodare le stampe e del demone lpd per gestire la stampa di ciò che è stato accodato, oltre che per ricevere le richieste attraverso la rete. Fa parte della tradizione anche il file di configurazione /etc/printcap, nel quale vengono definite le varie code di stampa, a cui si possono abbinare o meno dei filtri opportuni.

87.3.1   Configurazione con /etc/printcap

La configurazione di un sistema di stampa in stile BSD avviene principalmente attraverso il file /etc/printcap, con il quale si definiscono le code di stampa e il loro comportamento. Il suo contenuto è organizzato in record, dove ognuno di questi contiene le informazioni relative a una coda. I campi di questi record sono separati da due punti verticali (alle volte doppi e altre singoli) e possono essere spezzati su più righe, utilizzando la barra obliqua inversa (\) seguita immediatamente dal codice di interruzione di riga. Si osservi il fatto che l'ultimo campo è concluso da due punti.

campo_1:campo_2:...:campo_n:

campo_1:\
    :campo_2:\
    :campo_3:\
    ...
    :campo_n_1:\
    :campo_n:

Il sistema di stampa BSD originale richiede il simbolo di continuazione delle righe nel caso i record vengano spezzati, mentre altri sistemi compatibili, potrebbero farne a meno. In generale, è sempre meglio indicare la continuazione, anche se ciò non dovesse servire.

All'interno di questo file si possono trovare le indicazioni di code differenti che si riferiscono a un'unica stampante reale, per esempio quando si utilizzano configurazioni multiple per la stessa unità fisica.

Si osservi che il simbolo # rappresenta l'inizio di un commento, con il quale, il testo che segue fino alla fine della riga non viene tenuto in considerazione; nello stesso modo vengono ignorate le righe vuote e quelle bianche.

Viene mostrato subito un esempio, il cui contenuto verrà descritto gradualmente in questa sezione.

# Stampante predefinita
lp|laserjet|HP Laserjet:\
        :sd=/var/spool/lpd/lp:\
        :mx#0:\
        :sh:\
        :lp=/dev/lp0:\
        :if=/var/spool/lpd/lp/filtro:

# Stampa di testo
ascii:\
        :sd=/var/spool/lpd/tx:\
        :mx#0:\
        :sh:\
        :lp=/dev/lp0:\
        :if=/var/spool/lpd/ascii/filtro:

# Stampa diretta senza filtri
bare:\
        :sd=/var/spool/lpd/bare:\
        :mx#0:\
        :sh:\
        :lp=/dev/lp0:

# Stampante condivisa dell'elaboratore weizen.mehl.dg
net:\
        :sd=/var/spool/lpd/net:\
        :mx#0:\
        :sh:\
        :rm=weizen.mehl.dg:\
        :rp=lp:\
        :if=/var/spool/lpd/net/filtro:

Il primo campo di ogni record identifica tutti gli pseudonimi possibili di una certa coda di stampa, solitamente per identificare anche la stampante a cui la coda è abbinata. Questi sono separati da una barra verticale. Gli altri campi contengono tutti una sigla identificativa composta da due caratteri, seguita eventualmente da un valore che gli viene attribuito.

nome_coda[|nome_stampante]...:{sigla_campo[assegnamento]:}...

La presenza di queste sigle permette in pratica di avere un numero variabile di campi, con un ordine variabile, dove solo il primo ha un ruolo prestabilito: quello di identificare la coda.

Durante la compilazione di questo file è molto importante fare bene attenzione a non lasciare spazi di qualunque tipo dopo i simboli di continuazione (\), altrimenti questi simboli verrebbero intesi solo come una sequenza di escape che conferma il valore letterale del carattere che segue e non ci sarebbe alcuna continuazione. Questa considerazione è importante, perché poi è difficile scoprire errori del genere.

Il sistema di stampa BSD tradizionale prevede una quantità molto grande di campi nei record di /etc/printcap. Le esigenze attuali sono tali per cui i campi che si utilizzano in pratica sono molto pochi e non vale la pena di approfondire tecniche ormai superate, riferite a campi che in alcuni sistemi derivati potrebbero anche non essere più disponibili. La tabella 87.1 riepiloga i campi più comuni.

Tabella 87.1. I campi più importanti dei record che compongono il file /etc/printcap.

Campo Descrizione
if Input filter -- filtro di ingresso.
lf Log file -- file per la registrazione degli errori.
af Account file -- file per la registrazione della contabilità.
lp Line printer -- file di dispositivo di stampa.
mx Max -- dimensione massima di una stampa.
pl Page length -- altezza della pagina in righe.
pw Page width -- larghezza della pagina in caratteri.
pc Price -- prezzo per pagina.
rm Remote machine -- nodo di stampa remota.
rp Remote printer -- coda di stampa remota.
sd Spool directory -- directory usata per la coda.
sf Suppress feed -- soppressione dell'avanzamento di separazione.
sh Suppress header -- soppressione dell'intestazione.

I campi possono servire a indicare informazioni di tipo diverso e a seconda di questo cambia il modo con cui i dati relativi sono indicati:

Alcuni campi

if=filtro_di_ingresso

Indica il percorso assoluto del programma, o dello script, che serve come filtro dei dati in ingresso. Il programma o lo script in questione deve essere in grado di ricevere i dati dallo standard input e di emettere il risultato attraverso lo standard output.

lf=file_delle_registrazioni

Permette di specificare il percorso assoluto di un file da utilizzare come registro degli eventi importanti che riguardano la stampa. In generale serve per annotare gli errori.

lp=file_di_dispositivo

È indispensabile e serve a indicare il file di dispositivo corrispondente alla porta presso cui è connessa la stampante.

mx#n

Indica la dimensione massima (in multipli di 1 024 byte) di un file di stampa. Di solito, questo campo viene indicato con il valore zero (mx#0), per non porre alcun limite di dimensione.

rm=host

Indica un nodo di rete a cui ci si deve connettere per richiedere la stampa.

rp=nome_coda_remota

Si utilizza in abbinamento con il campo rm, allo scopo di indicare esplicitamente il nome della coda di stampa remota.

sd=directory_contenente_la_coda

Indica il percorso della directory da utilizzare per la gestione di questa coda. In linea di principio, dovrebbe essere possibile usare una sola directory per più code di stampa, al contrario di quanto si vede nell'esempio introduttivo.

sf

È un campo booleano che, se presente, elimina l'avanzamento della carta alla fine di ogni processo di stampa.

sh

È un campo booleano che, se presente, elimina l'emissione dell'informazione sul cliente che ha richiesto la stampa, nella pagina di intestazione (ovvero di separazione) tra un processo di stampa e il successivo. Se viene usato in combinazione con sf, viene eliminata completamente la pagina di separazione.

Esempi

Di seguito vengono descritte alcune porzioni dell'esempio introduttivo.


bare:\
        :sd=/var/spool/lpd/bare:\
        :mx#0:\
        :sh:\
        :lp=/dev/lp0:

La voce bare indica semplicemente le informazioni seguenti:

  • la directory usata per la coda di stampa è /var/spool/lpd/bare/, tenendo conto che la scelta del nome finale .../bare/ non è obbligatoria, ma è solo conveniente all'amministratore del sistema;

  • l'indicazione della dimensione massima del file è azzerata, stando a significare che non vengono posti dei limiti;

  • la pagina di intestazione non viene generata;

  • il file di dispositivo corrispondente alla porta della stampante è /dev/lp0.

La cosa importante da notare in questo tipo di definizione è che non è stato indicato un filtro per i dati. Ciò significa che i dati da inviare alla stampante non subiscono trasformazioni; infatti, il nome bare è stato scelto opportunamente.


lp|laserjet|HP Laserjet:\
        :sd=/var/spool/lpd/lp:\
        :mx#0:\
        :sh:\
        :lp=/dev/lp0:\
        :if=/var/spool/lpd/lp/filtro:

Questo record del file /etc/printcap è più complesso. Per prima cosa si nota che è possibile fare riferimento a questo utilizzando tre nomi possibili: lp, laserjet o HP Laserjet. A parte questo, si nota l'inserimento di un filtro di ingresso. Il file /var/spool/lpd/lp/filtro potrebbe essere sia un programma che uno script che esegue un qualche tipo di trasformazione sui dati ricevuti.


net:\
        :sd=/var/spool/lpd/net:\
        :mx#0:\
        :sh:\
        :rm=weizen.mehl.dg:\
        :rp=lp:\
        :if=/var/spool/lpd/net/filtro:

Questo esempio rappresenta un record del file /etc/printcap che dichiara l'utilizzo di una stampante remota. La differenza sta quindi nel fatto che il campo lp è assente e al suo posto si utilizzano rm e rp per indicare rispettivamente il nome dell'elaboratore remoto (weizen.mehl.dg) e il nome della coda presso l'elaboratore remoto.

Quando si utilizza una stampante remota, nel caso in cui i dati da stampare richiedano un'elaborazione attraverso un filtro, occorre decidere se tale elaborazione debba avvenire prima dell'invio, o alla destinazione. In questo caso, viene indicato un filtro attraverso il campo if: probabilmente, la coda corrispondente al nome lp dell'elaboratore remoto non ha un filtro adatto.

87.3.2   Servizio di stampa

Il servizio di stampa nel sistema derivato da BSD è gestito dal demone lpd. Questo si occupa principalmente di scandire le code e di mettere in stampa ciò che vi dovesse trovare. È anche in grado di ricevere richieste di stampa attraverso la rete, occupandosi di metterle in coda; infine, è anche capace di inviare una richiesta di stampa a un nodo remoto.

In condizioni normali, lpd non richiede argomenti nella riga di comando; comunque, la sintassi degli argomenti di lpd è molto diversa da un sistema all'altro.

Ogni sistema di stampa utilizza le proprie tecniche di autorizzazione per concedere l'accesso al servizio di stampa. In generale, un sistema di stampa installato attraverso i pacchetti della propria distribuzione GNU/Linux dovrebbe consentire la stampa quando questa è richiesta a partire dallo stesso elaboratore locale; mentre per consentire l'accesso dall'esterno, occorre predisporre altri file di configurazione che non sono standard.

Di solito, il servizio di stampa viene avviato e arrestato attraverso uno script della procedura di inizializzazione del sistema, che potrebbe assomigliare all'esempio seguente:


#!/bin/sh

test -f /usr/sbin/lpd || exit 0

case "$1" in
  start)
        echo -n "Avvio del servizio di stampa: "
        /usr/sbin/lpd
        echo
        ;;
  stop)
        echo -n "Disattivazione del servizio di stampa: "
        killall lpd
        echo
        ;;
  *)
        echo "Utilizzo: lpd {start|stop}"
        exit 1
esac

Dal momento che la stampa è controllata da un demone, quando si modifica il file di configurazione /etc/printcap, bisogna fare in modo che lpd lo rilegga. Questo lo si può ottenere arrestando e riavviando il servizio, oppure inviando al processo del demone un segnale di aggancio (SIGHUP):

kill -HUP pid_di_lpd

87.3.3   Stampante predefinita

Il file /etc/printcap permette di definire le code di stampa, comprese quelle che fanno riferimento a servizi remoti. Tra queste code, è necessario stabilire quale sia quella predefinita, ovvero quella che deve essere presa in considerazione quando non vi si fa riferimento in modo esplicito.

La coda predefinita (ovvero la stampante predefinita) corrisponde per tradizione al nome lp, ma questa definizione può essere alterata utilizzando la variabile di ambiente PRINTER. Se esiste, definisce il nome della stampante predefinita, altrimenti resta lp.

È importante tenere presente che la politica del proprio sistema di stampa potrebbe essere anche differente; per esempio, in mancanza di indicazioni la coda predefinita potrebbe essere quella corrispondente alla prima dichiarazione del genere nel file /etc/printcap. A questo proposito, è bene che la definizione della coda tradizionale lp, sia sempre la prima.

87.3.4   Clienti di stampa

Il cliente del sistema di stampa è un programma in grado di accodare una stampa. In generale, nei sistemi di stampa derivati da quello di BSD, si utilizza il programma lpr e in alcuni casi il programma lp:

lpr [opzioni] [file...]

lp [opzioni] [file...]

In condizioni normali, questi programmi sono in grado di mettere in stampa i file indicati alla fine della riga di comando, oppure, in loro mancanza, utilizzano per questo lo standard input. Sono molto poche le opzioni standard di questi programmi e, in generale, la cosa più importante è la definizione della coda di stampa a cui si vuole inviare il file:

lpr -P coda [file...]

lp -m coda [file...]

Lo schema sintattico semplificato mostra esattamente questa possibilità, sia per lpr che per lp. Si osservi in particolare che nel caso di lpr, la tradizione prevede anche che il nome della coda possa essere attaccato alla lettera dell'opzione.

Alcune opzioni di lpr

-Pcoda | -P coda

Permette di specificare una coda di stampa particolare, tra quelle previste all'interno di /etc/printcap. Se non viene utilizzata questa opzione, si fa riferimento alla stampante predefinita (che di solito è lp).

-m

Al termine della stampa, invia un messaggio attraverso mail all'utente che ha avviato il programma.

-#n_copie

Permette di specificare il numero di copie che si vuole siano stampate. Il numero di copie è indicato da un numero che segue il simbolo #.

Alcune opzioni di lp

-d coda

Permette di specificare una coda di stampa particolare, tra quelle previste all'interno di /etc/printcap. Se non viene utilizzata questa opzione, si fa riferimento alla stampante predefinita (che di solito è lp).

-m

Al termine della stampa, invia un messaggio attraverso mail all'utente che ha avviato il programma.

-n n_copie

Permette di specificare il numero di copie che si vuole siano stampate.

Esempi

lpr lettera

oppure

lp lettera

Accoda la stampa del file lettera utilizzando la coda predefinita.

lpr -P laser lettera

oppure

lp -d laser lettera

Accoda la stampa del file lettera utilizzando la coda identificata con il nome laser all'interno del file /etc/printcap.

lpr -Plaser lettera

Esattamente come nell'esempio precedente.

ls -l | lpr

oppure

ls -l | lp

Accoda la stampa dell'elenco della directory corrente. In pratica, viene accodato quanto proveniente dallo standard input che proviene dal comando ls -l.

87.3.5   Esame delle code di stampa

Per conoscere la situazione delle code di stampa si utilizza il comando lpq:

lpq [opzioni] [numero_processo_di_stampa...] [utente...]

lpq esamina le code di stampa e restituisce lo stato di una o di tutte le stampe accodate dall'utente specificato. Se lpq viene eseguito senza alcun argomento, restituisce lo stato di tutte le stampe accodate.

Alcune opzioni

-P coda

Permette di specificare una coda particolare. Se non viene specificato, si fa riferimento a quella predefinita.

-l

Restituisce maggiori informazioni su ogni processo di stampa.

87.3.6   Rimozione dei processi di stampa dalle code

I processi di stampa che risultano ancora visibili nelle code, possono essere rimossi dall'utente che li ha generati, o dall'utente root.

lprm [opzioni] [utente...]

Permette di rimuovere uno o più processi di stampa accodati precedentemente. Il nome dell'utente può essere specificato solo se il comando viene utilizzato dall'utente root, nel senso che solo lui può interrompere la stampa di altri utenti. Se non viene specificato il nome dell'utente, si intende che si tratti dello stesso che ha eseguito lprm. Se non vengono specificati argomenti, l'esecuzione del comando lprm implica l'eliminazione della stampa in corso per l'utente che lo ha richiesto. Naturalmente, ciò vale solo se l'utente in questione ha, in quel momento, una stampa in esecuzione.

Se l'utente root utilizza lprm senza specificare un utente a cui fare riferimento, ottiene l'eliminazione di tutti i processi di stampa nelle code, attivi o meno che siano.

Alcune opzioni

-P coda

Permette di specificare una coda particolare. Se non viene specificata, si fa riferimento alla coda predefinita.

numero_processo_di_stampa...

Se tra gli argomenti vengono indicati uno o più numeri, questi si intendono riferiti ai processi di stampa che si vogliono eliminare.

87.3.7   Controllo del sistema di stampa

L'utente root controlla il sistema di stampa, ovvero il funzionamento dei vari demoni lpd, attraverso il programma lpc:

lpc [comando [argomento...]]

Le possibilità effettive di lpc dipendono dalle caratteristiche del sistema di stampa. In generale, per ogni coda di stampa configurata all'interno di /etc/printcap, lpc può eseguire le azioni seguenti:

Se lpc viene avviato senza argomenti, si attiva la modalità di comando evidenziata dalla presenza dell'invito lpc>. Se invece vengono forniti degli argomenti, il primo di questi viene interpretato come un comando, mentre i restanti come parametri del comando. È possibile inviare a lpc, attraverso lo standard input, un file contenente una serie di comandi.

lpc può essere eseguito anche da un utente comune, ma in tal caso potranno essere eseguite solo alcune funzioni.

Comandi a disposizione di tutti gli utenti

[comando...] | help [comando...]

Visualizza una descrizione sintetica dei comandi elencati, oppure, se non ne viene indicato alcuno, l'elenco di tutti i comandi a disposizione.

exit | quit

Termina l'esecuzione di lpc.

status {all | coda}

Visualizza lo stato della coda di stampa locale indicata, oppure di tutte, se si utilizza la parola chiave all.

Comandi a disposizione dell'utente root

abort {all | coda}

Termina l'esecuzione del demone attivo che si occupa della stampa nell'elaboratore locale, quindi disabilita la stampa, prevenendo l'avvio di altri demoni da parte di lpr. Quando verrà riavviata la stampa, verrà ripreso il processo di stampa che era attivo nel momento dell'interruzione.

enable {all | coda}

disable {all | coda}

Abilita o disabilita l'uso della coda specificata, consentendo o impedendo la generazione di nuovi processi di stampa.

up {all | coda}

down {all | coda} messaggio

Abilita o disabilita l'uso della coda indicata, consentendo o bloccando la stampa dei processi di stampa esistenti.

start {all | coda}

stop {all | coda}

Abilita o arresta il demone che gestisce la coda. Nel caso di arresto, questo avviene al termine del processo di stampa eventualmente in esecuzione. Tuttavia, gli utenti possono continuare ad accodare stampe.

Il comando start può essere utile anche per riavviare un demone che per qualche ragione ha cessato di funzionare in modo inatteso.

topq coda [numero_processo_di_stampa...]

Cambia l'ordine di esecuzione dei processi di stampa ponendo quelli indicati in precedenza rispetto agli altri.

87.3.8   Particolarità del sistema BSD vero e proprio

Il sistema di stampa BSD prevede l'uso dei file /etc/hosts.equiv e /etc/hosts.lpd. Questi servono a elencare i nomi degli elaboratori remoti cui è consentito collegarsi per ottenere l'accesso al sistema di stampa locale. Per la precisione, è il file /etc/hosts.lpd che dovrebbe essere utilizzato per questo tipo di autorizzazione; tuttavia, dal momento che l'elenco contenuto in /etc/hosts.equiv serve già per consentire l'accesso attraverso programmi come Rsh (140.3), è ragionevole che anche a questi sia concesso di accedere al servizio di stampa.

È importante ribadire che con questo sistema di stampa, se non si predispone correttamente il file /etc/hosts.lpd, oppure il file /etc/hosts.equiv, o entrambi, non si ottiene l'accesso da clienti remoti.

Con il sistema di stampa BSD non è possibile accedere a stampanti remote se non è stata prevista una coda locale corrispondente nel file di configurazione /etc/printcap (con l'uso dei campi rm e rp). Per questo esistono anche dei programmi di servizio specifici che instaurano una connessione con il sistema remoto di stampa in modo autonomo. Si tratta di rlpr e rlpq, che vengono descritti più avanti.

87.3.9   Particolarità di LPRng

Il sistema di stampa LPRng (2) è molto più evoluto rispetto a quello della tradizione BSD, anche se di solito viene utilizzato in modo abbastanza conforme a quello; tuttavia consentirebbe di accedere a delle estensioni molto sofisticate, soprattutto per ciò che riguarda la stampa remota.

LPRng fa uso di /etc/printcap e di altri file di configurazione; precisamente si tratta di /etc/lpd.conf e di /etc/lpd.perms. Per quanto riguarda /etc/printcap, c'è da osservare che i record di definizione delle code, possono essere continuati su più righe, anche senza utilizzare il simbolo di continuazione (\). Se il pacchetto utilizzato per installare LPRng è stato predisposto correttamente, non dovrebbe essere necessario indicare alcunché nel file di configurazione /etc/lpd.conf, che di solito viene fornito commentato completamente, con gli esempi delle varie direttive che vi potrebbero apparire. Infine, il file /etc/lpd.perms serve a definire i permessi di accesso al servizio. Di solito, questo file viene fornito già predisposto per l'utilizzo locale normale; se si vuole concedere l'accesso da parte di clienti remoti è indispensabile modificare questo file, allo scopo di attivare i permessi necessari. Con ciò, si può intendere che LPRng non considera i file /etc/hosts.equiv e /etc/hosts.lpd.

# concede all'utente root sul servente di controllare i processi di stampa
ACCEPT SERVICE=C SERVER REMOTEUSER=root

# concede a chiunque di ottenere lo stato dei processi di stampa
ACCEPT SERVICE=S

# rifiuta le richieste di stampa dai nodi remoti
REJECT SERVICE=XRPQ NOT SERVER

# rifiuta tutto il resto
REJECT SERVICE=CSU

# concede agli utenti che accedono dai nodi originari,
# di eliminare i propri processi di stampa
ACCEPT SERVICE=M SAMEHOST SAMEUSER

# concede all'utente root sul servente di eliminare i processi di stampa
ACCEPT SERVICE=M SERVER REMOTEUSER=root
REJECT SERVICE=M

# tutte le altre operazioni sono concesse
DEFAULT ACCEPT

L'esempio rappresenta un file /etc/lpd.perms tipico, dove in particolare sono esclusi gli accessi da parte di clienti remoti. Per fare in modo di consentire l'accesso sommario da parte di una sottorete, si può modificare la direttiva

REJECT SERVICE=XRPQ NOT SERVER

in:

REJECT SERVICE=XRPQ NOT SERVER NOT REMOTEIP=192.168.0.0/255.255.0.0

In questo modo, secondo l'esempio, si concede a tutta la sottorete 192.168.*.* di accedere.

Un vantaggio importante nell'uso di LPRng sta nella possibilità di accedere direttamente a servizi di stampa remoti, senza dover passare per una coda locale configurata nel file /etc/printcap. Tutto è molto semplice: nelle situazioni in cui è consentito indicare il nome di una coda di stampa, si può usare la notazione seguente per accedere direttamente al servizio remoto corrispondente:

coda@host

L'esempio seguente invia alla stampa, presso la coda lp del nodo roggen.brot.dg, il file lettera.

lpr -P lp@roggen.brot.dg lettera

Infine, è bene tenere presente che è possibile verificare la correttezza della configurazione attraverso il programma di servizio checkpc:(3)

checkpc [opzioni] [file_printcap]

Di solito si utilizza checkpc senza argomenti di alcun tipo, allo scopo di controllare il file /etc/printcap (ovvero quello predefinito), gli altri file di configurazione e le directory delle code. Il controllo riguarda sia la configurazione che i permessi dei file. È molto importante l'opzione -f, con la quale si richiede a checkpc di provvedere da solo a sistemare ciò che è possibile. Naturalmente, l'uso di checkpc con l'opzione -f è riservato all'utente root.

Prima di utilizzare checkpc è opportuno concludere il funzionamento di tutti i demoni lpd che fossero eventualmente in funzione.

checkpc -f

A titolo di esempio viene mostrato quello che potrebbe essere generato da questo comando:

 Checking permission file '/etc/lpd.perms:/usr/etc/lpd.perms'
 Freeing Perms
 Done Perms
 LPD lockfile '/var/spool/lpd/lpd.lock.tizio.printer'
  Checking directory: '/var/spool/lpd'
   checking file '/var/spool/lpd/lpd.lock.tizio.printer'
 Truncating LPD log file '/var/spool/lpd/lpd.log.tizio'
 Checking /var/spool/lpd/lpd.log.tizio file '/var/spool/lpd/lpd.log.tizio'
checkpc: Warning - cannot open '/var/spool/lpd/lpd.log.tizio'
 lp: Checking printer 'lp'
 lp:  Checking directory: '/var/spool/lpd/lp'
 lp:   checking file '/var/spool/lpd/lp/control.lp'
 lp:   checking file '/var/spool/lpd/lp/status.lp'
 lp:   checking file '/var/spool/lpd/lp/status'
 lp:   checking file '/var/log/lp-errs'
 lp:   checking file '/var/log/lp-acct'
 lp: Checking log file '/var/log/lp-errs'
 lp:    'log' file 0 bytes long: no truncation
 lp: Checking accounting file '/var/log/lp-acct'
 lp:    'accounting' file 2316 bytes long: no truncation
 lp: Checking filter status file '/var/spool/lpd/lp/status'
 lp:    'filter status' file 0 bytes long: no truncation

87.4   Stampa remota attraverso Rlpr

Il pacchetto di programmi Rlpr, (4) estraneo al sistema di stampa BSD tradizionale, può essere molto utile per stampare utilizzando servizi remoti, senza passare per la configurazione del file /etc/printcap locale. Tuttavia, è il caso di ricordare che non c'è bisogno di tali programmi nel caso si disponga già di un sistema di stampa LPRng, in cui i programmi clienti normali sono in grado di fare questo da soli.

Rlpr sostituisce in pratica alcuni programmi di servizio, tipici del sistema di stampa BSD, con altri, caratterizzati da una lettera «r» iniziale, che sta per «remoto»:

rlpr [opzioni] [file_da_stampare...]

rlpq [opzioni] [numero_processo_di_stampa...] [utente...]

rlprm [opzioni] [utente...]

Come si può intuire, questi programmi sostituiscono, nell'ordine, lpr, lpq e lprm.

Questi programmi, per compiere il loro lavoro correttamente, richiedono i privilegi dell'utente root, pertanto hanno solitamente il bit SUID attivo, appartenendo all'utente root (SUID-root), come documentato chiaramente nelle pagine di manuale rlpr(1), rlpq(1) e rlprm(1).

Molte delle opzioni dei programmi originali, sono preservate; con qualche aggiunta e qualche modifica. In particolare:

Opzione Descrizione

-H host

 

--printhost=host

Definisce l'elaboratore remoto al quale ci si vuole rivolgere per ottenere la stampa. Al posto di utilizzare questa opzione si può sfruttare il nome della coda di stampa per includervi anche l'indicazione del nodo remoto. Si osservi a tal fine la descrizione dell'opzione -P.

-Pcoda[@host]

 

--printer=coda[@host]

 

--queue=coda[@host]

Seleziona la coda di stampa remota. Se non si utilizza l'opzione -H, si può usare la notazione coda@host.

A titolo di esempio vengono mostrati due comandi equivalenti, per ottenere la stampa del contenuto della directory corrente, attraverso la coda lp presso l'indirizzo 192.168.1.1:

ls -l | rlpr --printhost=192.168.1.1 -Plp

ls -l | rlpr -Plp@192.168.1.1

87.4.1   Scelta automatica della stampante remota

Supponendo di avere a disposizione diverse stampanti remote, si potrebbe avere la necessità di selezionare in qualche modo la coda di stampa, cercando di sfruttare la prima stampante libera. Qui viene proposto un piccolo programma Perl che trova la stampante con la coda libera, oppure accoda in modo casuale, purché si tratti di una coda attiva. Per comodità, si può dare a questo programma proprio il nome lpr, in modo da renderlo trasparente all'utilizzatore.


#!/usr/bin/perl

# Indicare qui l'elenco delle code di stampa remote disponibili:
@printers = ("lp\@stampante1.brot.dg",
              "lp\@stampante2.brot.dg",
              "lp\@stampante3.brot.dg",
              "lp\@stampante4.brot.dg",
              "lp\@stampante5.brot.dg",
              "lp\@stampante6.brot.dg",
              "lp\@stampante7.brot.dg");

# Questa funzione esegue un comando del sistema operativo, restituendo
# quanto emesso dallo stesso attraverso i flussi standard.
sub system_output
{
    local ($command)  = $_[0];
    local ($line)     = "";
    local ($result)   = "";

    # Esegue il comando.
    open (COMMAND, "$command 2>&1 |");
    
    # Recupera il risultato emesso dal comando.
    while ($line = <COMMAND>)
      {
        $result = $result . $line
      }

    # Chiude la pipeline del comando.
    close (COMMAND);

    return $result;
}

# Inizio del programma.
local ($arguments)      = "";
local ($noauto)         = 0;
local ($n)              = 0;
local ($test)           = "";

# Scandisce gli argomenti.
for ($n = 0; $n <= $#ARGV; $n++)
  {
    # Analizza l'argomento $n-esimo.
    if ($ARGV[$n] =~ m/^-P.*/
           || $ARGV[$n] =~ m/^--printer=.*/
           || $ARGV[$n] =~ m/^--queue=.*/)
      {
        # In questo caso, è stata già specificata la coda di stampa
        # dall'utilizzatore.
        $noauto    = 1;
      }
    # Mette da parte l'argomento scandito.
    $arguments = $arguments . " " . $ARGV[$n];
  }

# Se è stata specificata la stampante, non si procede in modo automatico.
if ($noauto)
  {
    system ("| rlpr $arguments");
    exit;
  }

# In condizioni normali, si cerca la prima stampante che risulta pronta.
for ($n = 0; $n <= $#printers; $n++)
  {
    $test = &system_output ("rlpq -P$printers[$n]");
    if ($test =~ m/^no entries$/)
      {
        system ("rlpr -P$printers[$n] $arguments");
        print STDOUT ("Stampa inviata a $printers[$n]\n");
        exit;
      }
  }

# Se non è stata trovata una stampante libera, si cerca una stampante
# che non abbia problemi.
while ($#printers > 0)
  {
        $n = (int ((rand) * $#printers) - 1);
        $test = &system_output ("rlpq -P$printers[$n]");
        if ($test !~ m/error/i
            && $test !~ m/warning/i)
          {
            system ("rlpr -P$printers[$n] $arguments");
            print STDOUT ("Stampa inviata a $printers[$n]\n");
            exit;
          }
        # Elimina l'elemento dall'array.
        splice (@printers, $n, 1);
  }

# Se nessuna stampante è nelle condizioni di poter stampare,
# avvisa.
print STDERR ("Nessuna delle stampanti previste è nelle condizioni di ");
print STDERR ("poter stampare.\n");

87.5   Stampare attraverso X

Quando si inizia a utilizzare il sistema grafico X, provenendo dall'esperienza di un sistema operativo grafico estraneo alle convenzioni Unix, uno dei primi problemi (apparenti) che si incontrano è la stampa: in che modo i programmi accodano le stampe? Semplice: utilizzano un comando per la stampa come se fossero programmi normalissimi senza grafica.

In effetti, la standardizzazione del formato PostScript è molto importante. Praticamente tutti i programmi che devono emettere qualcosa di diverso dal semplice testo ASCII, utilizzano il formato PostScript.

Restano allora solo un paio di problemi:

Generalmente, i programmi che hanno la necessità di stampare propongono una riga di comando per la stampa, per cui è anche possibile utilizzare un sistema di stampa che dispone di un cliente diverso dal solito programma lpr.

Alcuni programmi più vecchi richiedono solo l'indicazione della voce del file /etc/printcap e quindi pretendono di utilizzare il programma lpr con l'opzione -P.

Figura 87.7. Questo è un esempio di un programma che è in grado di stampare solo attraverso lpr. Se non viene indicato il nome di una coda di stampa, si fa riferimento a lp, o comunque a quella predefinita.

figure/a2-stampa-x-ghostview

Figura 87.8. Questo è un esempio di un programma normale che permette l'indicazione di una riga di comando completa (o quasi). Non deve essere inserito il nome del file da stampare che di norma viene fornito attraverso lo standard input.

figure/a2-stampa-x-starwriter

87.6   Riferimenti

Appunti di informatica libera 2003.01.01 --- Copyright © 2000-2003 Daniele Giacomini -- daniele @ swlibero.org

1) BSD line printing spool system   UCB BSD

2) LPRng   software non libero: licenza Artistic

3) Check printcap

4) Rlpr   GNU GPL


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome stampa.html

[successivo] [precedente] [inizio] [fine] [indice generale] [violazione GPL] [translators] [docinfo] [indice analitico]