Avanti Indietro Indice

9. Condividere Una Stampante Windows Con Macchine Linux.

Per condividere una stampante su una macchina Windows, è necessario:

  1. Avere una configurazione corretta in /etc/printcap che corrisponda alla struttura delle directory locali (per le directory di spool, ecc.)
  2. Usare lo script /usr/bin/smbprint. Questo script è disponibile con il sorgente di Samba, purtroppo non con tutte le distribuzioni in formato binario. Più avanti verrà presentata una versione leggermente diversa di smbprint.
  3. Se si desidera convertire file ASCII in Postscript, è necessario avere nenscript, o qualcosa di equivalente. nenscript è un convertitore Postscript generalmente installato in /usr/bin.
  4. Si potrebbe desiderare rendere la stampa con Samba più semplice tramite un semplice front-end. Di seguito è riportato un semplice script ( print) in Perl per manipolare ASCII, Postscript...

La successiva configurazione di /etc/printcap è valida per una stampante HP 5MP su un host Windows NT. Le linee hanno il seguente significato:

cm

commento

lp

dispositivo da aprire per output

sd

directory di spool della stampante sulla macchina locale

af

file per registrare le transazioni

mx

massima grandezza per un file (zero significa nessun limite)

if

nome del filtro di output (script)

Per maggiori informazioni consultare il Printing HOWTO o le pagine del manuale per la voce printcap.


# /etc/printcap
#
# //zimmerman/oreilly via smbprint
#
lp:\
        :cm=HP 5MP Postscript OReilly on zimmerman:\
        :lp=/dev/lp1:\
        :sd=/var/spool/lpd/lp:\
        :af=/var/spool/lpd/lp/acct:\
        :mx#0:\
        :if=/usr/bin/smbprint:

È necessario accertarsi che le directory di spool e per la registrazione delle transazioni (log) esistano e siano scrivibili. Assicurarsi che la linea 'if' contenga un percorso corretto allo script di smbprint ( dato oltre) ed inoltre che il dispositivo puntato sia corretto (il file speciale /dev).

Di seguito lo script smbprint. Di solito è installato in /usr/bin ed è attribuibile, per quanto ne so, ad Andrew Tridgell, la persona che ha creato Samba. Viene fornito con la distribuzione in formato sorgente di Samba ma è riportato, essendo assente in certe distribuzioni in formato binario.

Potrebbe essere utile studiarlo attentamente, alcune piccole modifiche hanno dimostrato essere di enorme utilità.


#!/bin/sh -x

# Questo script è un filtro di input per la stampa via printcap da una
# macchina UNIX. Usa il programma smbclient per stampare il file sul
# server e servizio specificati usando il protocollo smb.
# Per esempio è possibile avere una linea del printcap del tipo:
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# Che dovrebbe creare una stampante UNIX chiamata "smb" che stamperà
# attraverso questo script. E' necessario creare la directory di spool
# /usr/spool/smb con permessi, proprietario e gruppo appropriati per il
# sistema.

# Assegnare i valori che seguono in modo da accordarsi al server e
# e servizio su cui si desidera stampare. In questo esempio si suppone
# di avere un PC con WfWg chiamato "lapland" che ha una stampante
# esportata chiamata "printer" senza password.
#
# Script modificato da hamiltom@ecnz.co.nz (Michael Hamilton)
# in modo da poter leggere server, servizio e password dal file
# /usr/var/spool/lpd/PRINTNAME/.config
#
# Affinché tutto funzioni è necessario che esista una linea in
# /etc/printcap che includa il file di accounting (af=...):
#
#   cdcolour:\
#   :cm=CD IBM Colorjet on 6th:\
#   :sd=/var/spool/lpd/cdcolour:\
#   :af=/var/spool/lpd/cdcolour/acct:\
#   :if=/usr/local/etc/smbprint:\
#   :mx=0:\
#   :lp=/dev/null:
#
# Il file /usr/var/spool/lpd/PRINTNAME/.config dovrebbe contenere:
#   server=PC_SERVER
#   service=PR_SHARENAME
#   password="password"
#
# Esempio:
#   server=PAULS_PC
#   service=CJET_371
#   password=""

#
# File per i messaggi di debug, cambiare in /dev/null se si preferisce.
#
logfile=/tmp/smb-print.log
# logfile=/dev/null


#
# L'ultimo parametro del filtro è il file per la registrazione delle
# transazioni.
#
spool_dir=/var/spool/lpd/lp
config_file=$spool_dir/.config

# Le seguenti variabili dovrebbero essere assegnate nel file di
# configurazione:
#   server
#   service
#   password
#   user
eval `cat $config_file`

#
# Supporto per il debugging si può cambiare >> con > per risparmiare
# spazio.
#
echo "server $server, service $service" >> $logfile

(
# NOTA Si potrebbe desiderare di aggiungere la linea `echo translate'
# per avere la conversione automatica CR/LF quando si stampa.
    echo translate
    echo "print -"
    cat
) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $logfile

La maggior parte delle distribuzioni Linux include nenscript per convertire documenti ASCII a Postscript. Lo script Perl che segue rende la vita più semplice agendo da semplice interfaccia per la stampa di Linux attraverso smbprint.

Usage: print [-a|c|p] <filename>
       -a prints <filename> as ASCII
       -c prints <filename> formatted as source code
       -p prints <filename> as Postscript
        If no switch is given, print attempts to
        guess the file type and print appropriately.

Usare smbprint per stampare file ASCII comporta a volte troncare le linee lunghe. Lo script che segue interrompe, se possibile, le linee lunghe su uno spazio (invece che in mezzo ad una parola).

La formattazione del codice sorgente è fatta con nenscript. Il file ASCII viene formattato su 2 colonne con un'intestazione (data, nome del file, ecc.) inoltre numera le linee. Usandolo come esempio, è possibile realizzare altri tipi di formattazione.

I documenti Postscript sono già correttamente formattati, quindi passano senza essere modificati.


#!/usr/bin/perl

# Script:   print
# Autore:   Brad Marshall, David Wood
#           Plugged In Communications
# Data:     960808
#
# Script per stampare su oreilly che è attualmente connessa a zimmerman
# Scopo:  Dati diversi tipi di file come argomenti, li elabora 
# correttamente per mandarli in pipe ad uno script di stampa Samba.
#
# Tipi di file correntemente supportati:
#
# ASCII      - Verifica che le linee più lunghe di $line_length caratteri
#              si interrompano su spazio.
# Postscript - Intrapresa nessuna azione.
# Codice     - Formatta in Postscript (usando nenscript) per rendere al
#              al meglio (in orizzontale, font, ecc.)
#

# Lunghezza massima concessa per ciascuna linea di testo ASCII.
$line_length = 76;

# Nome e percorso dello script di stampa Samba
$print_prog = "/usr/bin/smbprint";

# Nome e percorso di nenscript (converte ASCII-->Postscript)
$nenscript = "/usr/bin/nenscript";

unless ( -f $print_prog ) {
    die "Non trovo: $print_prog!";
}
unless ( -f $nenscript ) {
    die "Non trovo: $nenscript!";
}

&ParseCmdLine(@ARGV);

# DBG
print "Il file e' di tipo: $filetype\n";

if ($filetype eq "ASCII") {
    &wrap($line_length);
} elsif ($filetype eq "code") {
    &codeformat;
} elsif ($filetype eq "ps") {
    &createarray;
} else {
    print "Spiacente...file di tipo sconosciuto.\n";
    exit 0;
}
# Pipe the array to smbprint
open(PRINTER, "|$print_prog") || die "Impossibile aprire $print_prog: $!\n";
foreach $line (@newlines) {
    print PRINTER $line;
}
# Spedisce un linefeed extra nel caso in cui il file abbia l'ultima linea
# incompleta.
print PRINTER "\n";
close(PRINTER);
print "Finito.\n";
exit 0;

# --------------------------------------------------- #
#   Da questo punto in poi ci sono solo subroutine    #
# --------------------------------------------------- #

sub ParseCmdLine {
    # Analizza la linea di comand, cercando di riconoscere il tipo di
    # file.

        # Se esistono imposta $arg e $file agli argomenti.
    if ($#_ < 0) {
        &usage;
    }
    # DBG
#   foreach $element (@_) {
#       print "*$element* \n";
#   }

    $arg = shift(@_);
    if ($arg =~ /\-./) {
        $cmd = $arg;
    # DBG
#   print "\$cmd trovato.\n";

        $file = shift(@_);
    } else {
        $file = $arg;
    }

    # Definisce il tipo di file
    unless ($cmd) {
        # Nessun argomento

        if ($file =~ /\.ps$/) {
            $filetype = "ps";
        } elsif ($file =~ /\.java$|\.c$|\.h$|\.pl$|\.sh$|\.csh$|\.m4$|\.inc$|\.html$|\.htm$/) {
            $filetype = "code";
        } else {
            $filetype = "ASCII";
        }

        # Elabora $file in base al suo tipo e ritorna $filetype
    } else {
        # Il tipo che e' viene restituito in $arg
        if ($cmd =~ /^-p$/) {
            $filetype = "ps";
        } elsif ($cmd =~ /^-c$/) {
            $filetype = "code";
        } elsif ($cmd =~ /^-a$/) {
            $filetype = "ASCII"
        }
    }
}

sub usage {
    print "
Uso: print [-a|c|p] <nomefile>
       -a stampa <nomefile> come ASCII
       -c stampa <nomefile> formattato come codice sorgente
       -p stampa <nomefile> come Postscript
        Se non viene fornito alcun parametro, cerca di
        indovinare il tipo e stamparlo adeguatamente.\n
";
    exit(0);
}

sub wrap {
        # Crea un array di linee del file, dove ciascuna linea e' <
        # del numero di caratteri specificato, e termina solo su spazi.

        # Recupera il numero di caratteri a cui limitare la linea.
    $limit = pop(@_);

    # DBG
    #print "Entra subroutine wrap\n";
    #print "La lunghezza limite per la linea e' $limit\n";

    # Leggi il file, analizzalo e mettilo nell'array.
    open(FILE, "<$file") || die "Impossibile aprire: $file: $!\n";
    while(<FILE>) {
        $line = $_;

        # DBG
        #print "La linea e':\n$line\n";

        # Se la linea e' oltre il limite vai a capo.
        while ( length($line) > $limit ) {

            # DBG
            #print "Limita...";

            # Prendi i primi $limit +1 caratteri.
            $part = substr($line,0,$limit +1);

            # DBG
            #print "La linea parziale e':\n$part\n";

                        # verifica se l'ultimo carattere e' spazio
            $last_char = substr($part,-1, 1);
            if ( " " eq $last_char ) {
                # Se lo e' stampa il resto.

                # DBG
                #print "L'ultimo carattere era spazio\n";

                substr($line,0,$limit + 1) = "";
                substr($part,-1,1) = "";
                push(@newlines,"$part\n");
            } else {
                 # se non lo e', cerca l'ultimo spazio nella
                 # sottolinea e stampa fino a li'.

                # DBG
                #print "L'ultimo carattere non era spazio\n";

                 # RImuove i caratteri oltre $limit
                 substr($part,-1,1) = "";
                 # Rovescia la linea per rendere semplice da trovare
                 # l'ultimo carattere.
                 $revpart = reverse($part);
                 $index = index($revpart," ");
                 if ( $index > 0 ) {
                   substr($line,0,$limit-$index) = "";
                   push(@newlines,substr($part,0,$limit-$index)
                       . "\n");
                 } else {
                   # Non c'erano spazi cosi' stampa fino a $limit
                   substr($line,0,$limit) = "";
                   push(@newlines,substr($part,0,$limit)
                       . "\n");
                 }
            }
        }
        push(@newlines,$line);
    }
    close(FILE);
}

sub codeformat {
    # Chiama la funzione wrap e poi filtra il risultato attraverso
    # nenscript
    &wrap($line_length);

    # Manda il risultato attraverso nenscript per creare un file
    # Postscript che abbia un formato accettabile di stampa per
    # il codice sorgente (stile orizzontale, font Courier, numeri
    # di linea)
    # Per prima cosa stampa su un file temporaneo.
    $tmpfile = "/tmp/nenscript$$";
    open(FILE, "|$nenscript -2G -i$file -N -p$tmpfile -r") ||
        die "Non posso aprire nenscript: $!\n";
    foreach $line (@newlines) {
        print FILE $line;
    }
    close(FILE);

    # Legge il file temporaneo inun array per passarlo allo script di
    # stampa di Samba
    @newlines = ("");
    open(FILE, "<$tmpfile") || die "Impossibile aprire $file: $!\n";
    while(<FILE>) {
        push(@newlines,$_);
    }
    close(FILE);
    system("rm $tmpfile");
}

sub createarray {
    # Crea l'array per Postscript
    open(FILE, "<$file") || die "Impossibile aprire $file: $!\n";
    while(<FILE>) {
        push(@newlines,$_);
    }
    close(FILE);
}


Avanti Indietro Indice