Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Next Previous Contents

59. Доступ к принтеру Windows с машин под Linux

Для доступа к принтеру на Windows машине, вы должны сделать следующее:

a) ВЫ должны иметь правильные записи в файле /etc/printcap и они должны соответствовать локальной структуре директорий (для директории спула, и т.п.)

b) У вас должен быть скрипт /usr/bin/smbprint. Он идет вместе с исходными текстами Samba, но не со всеми двоичными дистрибутивами Samba. Его немного модифицированная копия обсуждается ниже.

c) Если вы хотите преобразовывать ASCII файлы в Postscript, вы должны иметь nenscript, или его эквивалент. nenscript -- это конвертор Postscript, он обычно устанавливается в директорию /usr/bin.

d) Вы можете хотеть сделать печать через Samba более легкой с помощью программы-надстройки. Простой скрипт на perl, который обрабатывает ASCII, Postscript или преобразованный Postscript дан ниже.

Запись в /etc/printcap ниже приведена для принтера HP 5MP на сервере Windows NT. Записи следующие:



        cm - комментарий

        lp - имя устройства, открываемого для вывода

        sd - директория спула принтера (на локальной машине)

        af - файл учета пользования принтером

        mx - максимальный размер файла (ноль -- без ограничений)

        if - имя входного фильтра (скрипта)


Для более детальной информации смотрите Printing HOWTO или справочные страницы по 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:


Убедитесь, что директории спула и учета пользования существуют и имеют право на запись. Убедитесь, что строка 'if' содержит правильный путь к скрипту smbprint (дан ниже) и будьте уверены, что указывается на правильное устройство (специальный файл /dev).

Далее идет сам скрипт smbprint. Он обычно находится в директории /usr/bin и относящийся к Andrew Tridgell, человеку кто создал Samba, насколько я знаю. Этот скрипт идет с дистрибутивом исходного кода Samba, но отсутствует в некоторых бинарных дистрибутивах, так что я воссоздал его здесь.

Вы можете захотеть взглянуть на него внимательно. Есть некоторые мелкие изменения, которые показали себя полезными.



#!/bin/sh -x



# Этот скрипт является входным фильтром для основанной на printcap

# печати на unix-машинах. Он использует программу smbclient для

# печати файла на указанный smb-сервер и сервис.

# Например вы можете иметь запись в printcap подобную этой

#

# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint

#

# которая создает unix-принтер названный "smb", который будет

# печатать с помощью этого скрипта. Вам необходимо создать директорию

# спула /usr/spool/smb с соответствующими правами и владельцем



# Установите здесь сервер и сервис на который вы хотите печатать. В

# этом примере я имею PC с WfWg PC, названную "lapland", которая

# имеет экспортируемый принтер, называемый "printer" без пароля



#

# Далее скрипт был изменен hamiltom@ecnz.co.nz (Michael Hamilton)

# так что сервер, сервис и пароль могут быть считаны из файла

# /usr/var/spool/lpd/PRINTNAME/.config 

#

# Для того чтобы это работало запись в /etc/printcap должна

# включать файл учета использования (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:

#

# Файл /usr/var/spool/lpd/PRINTNAME/.config должен содержать

#   server=PC_SERVER

#   service=PR_SHARENAME

#   password="password"

#

# Например,

#   server=PAULS_PC

#   service=CJET_371

#   password=""



#

# Debugging log file, change to /dev/null if you like.

#

logfile=/tmp/smb-print.log

# logfile=/dev/null





#

# The last parameter to the filter is the accounting file name.

#

spool_dir=/var/spool/lpd/lp

config_file=$spool_dir/.config



# Should read the following variables set in the config file:

#   server

#   service

#   password

#   user

eval `cat $config_file`



#

# Some debugging help, change the >> to > if you want to same space.

#

echo "server $server, service $service" >> $logfile



(

# NOTE You may wish to add the line `echo translate' if you want automatic

# CR/LF translation when printing.

        echo translate

        echo "print -"

        cat

) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $logfile


Большинство дистрибутивов linux идет с программой nenscript для преобразования ASCII документов в Postscript. Следующий скрипт на perl делает жизнь легче, обеспечивая простой интерфейс для печати в liinux через smbprint.



Использование: print [-a|c|p] <filename>

       -a печатает <filename> как ASCII

       -c печатает <filename> отформатированный как исходный код

       -p печатает <filename> как Postscript

        Если опции не заданы, программа попробует определить

        тип файла и печатать соответственно


Используя smbprint для печати ASCII файлов, скрипт следит за длинными строками. Если возможно этот скрипт разрывает длинную строку на пробеле (вместо разрыва в середине слова).

Форматирование исходного кода выполняется с помощью nenscript. Он берет ASCII-файл и форматирует его в 2 колонки с с заголовком (дата, имя файла и т.п.). Он также нумерует строки. Используя этот скрипт как пример другие типы форматирования могут быть сделаны.

Postscript-документы уже правильно отформатированы, так что они печатаются сразу.



#!/usr/bin/perl



# Скрипт:   print

# Авторы:   Brad Marshall, David Wood

#           Plugged In Communications

# Дата:   960808

#

# Используется для печати на сервис oreilly, который расположен на

# сервере zimmerman

# Назначение: Берет файлы разных типов как аргумент и обрабатывает

# их соответственно для передачи на скрипт печать Samba.

#

# В настоящее время поддерживаются типы файлов:

# 

# ASCII      - Если длина строки длинее чем $line_length символов, то 

#              переносит строку на пробеле

# Postscript - Берет без обработки

# Code        - Форматирует в Postscript (используя nenscript), чтобы 

#               отображать правильно (альбомный формат, фонт и т.п.)

#



# Установить максимальную длину строки ASCII текста

$line_length = 76;



# Установить путь к скрипту печати Samba

$print_prog = "/usr/bin/smbprint";



# Установить путь и имя nenscript (конвертера ASCII-->Postscript)

$nenscript = "/usr/bin/nenscript";



unless ( -f $print_prog ) {

        die "Can't find $print_prog!";

}

unless ( -f $nenscript ) {

        die "Can't find $nenscript!";

}



&ParseCmdLine(@ARGV);



# DBG

print "filetype is $filetype\n";



if ($filetype eq "ASCII") {

        &wrap($line_length);

} elsif ($filetype eq "code") {

        &codeformat;

} elsif ($filetype eq "ps") {

        &createarray;

} else {

        print "Sorry..no known file type.\n";

        exit 0;

}

# Pipe the array to smbprint

open(PRINTER, "|$print_prog") || die "Can't open $print_prog: $!\n";

foreach $line (@newlines) {

        print PRINTER $line;

}

# Send an extra linefeed in case a file has an incomplete last line.

print PRINTER "\n";

close(PRINTER);

print "Completed\n";

exit 0;



# --------------------------------------------------- #

#        Everything below here is a subroutine        #

# --------------------------------------------------- #



sub ParseCmdLine {

        # Parses the command line, finding out what file type the file is



        # Gets $arg and $file to be the arguments (if the exists)

        # and the filename

        if ($#_ < 0) {

                &usage;

        }

        # DBG

#       foreach $element (@_) {

#               print "*$element* \n";

#       }



        $arg = shift(@_);

        if ($arg =~ /\-./) {

                $cmd = $arg;

        # DBG

#       print "\$cmd found.\n";



                $file = shift(@_);

        } else {

                $file = $arg;

        }

        

        # Defining the file type

        unless ($cmd) {

                # We have no arguments



                if ($file =~ /\.ps$/) {

                        $filetype = "ps";

                } elsif ($file =~ /\.java$|\.c$|\.h$|\.pl$|\.sh$|\.csh$|\.m4$|\.inc$|\.html$|\.htm$/) {

                        $filetype = "code";

                } else {

                        $filetype = "ASCII";

                }



                # Process $file for what type is it and return $filetype 

        } else {

                # We have what type it is in $arg

                if ($cmd =~ /^-p$/) {

                        $filetype = "ps";

                } elsif ($cmd =~ /^-c$/) {

                        $filetype = "code";

                } elsif ($cmd =~ /^-a$/) {

                        $filetype = "ASCII"

                }

        }

}



sub usage {

        print "

Использование: print [-a|c|p] <filename>

       -a печатает <filename> как ASCII

       -c печатает <filename> отформатированный как исходный код

       -p печатает <filename> как Postscript

        Если опции не заданы, программа попробует определить

        тип файла и печатать соответственно\n

";

        exit(0);

}



sub wrap {

        # Create an array of file lines, where each line is < the 

        # number of characters specified, and wrapped only on whitespace



        # Get the number of characters to limit the line to.

        $limit = pop(@_);



        # DBG

        #print "Entering subroutine wrap\n";

        #print "The line length limit is $limit\n";



        # Read in the file, parse and put into an array.

        open(FILE, "<$file") || die "Can't open $file: $!\n";

        while(<FILE>) {

                $line = $_;

                

                # DBG

                #print "The line is:\n$line\n";



                # Wrap the line if it is over the limit.

                while ( length($line) > $limit ) {

                        

                        # DBG

                        #print "Wrapping...";



                        # Get the first $limit +1 characters.

                        $part = substr($line,0,$limit +1);



                        # DBG

                        #print "The partial line is:\n$part\n";



                        # Check to see if the last character is a space.

                        $last_char = substr($part,-1, 1);

                        if ( " " eq $last_char ) {

                            # If it is, print the rest.



                            # DBG

                            #print "The last character was a space\n";



                            substr($line,0,$limit + 1) = "";

                            substr($part,-1,1) = "";

                            push(@newlines,"$part\n");

                        } else {

                             # If it is not, find the last space in the 

                             # sub-line and print up to there.



                            # DBG

                            #print "The last character was not a space\n";



                             # Remove the character past $limit

                             substr($part,-1,1) = "";

                             # Reverse the line to make it easy to find

                             # the last space.

                             $revpart = reverse($part);

                             $index = index($revpart," ");

                             if ( $index > 0 ) {

                               substr($line,0,$limit-$index) = "";

                               push(@newlines,substr($part,0,$limit-$index) 

                                   . "\n");

                             } else {

                               # There was no space in the line, so

                               # print it up to $limit.

                               substr($line,0,$limit) = "";

                               push(@newlines,substr($part,0,$limit) 

                                   . "\n");

                             }

                        }

                }

                push(@newlines,$line);

        }

        close(FILE);

}



sub codeformat {

        # Call subroutine wrap then filter through nenscript

        &wrap($line_length);

        

        # Pipe the results through nenscript to create a Postscript

        # file that adheres to some decent format for printing

        # source code (landscape, Courier font, line numbers).

        # Print this to a temporary file first.

        $tmpfile = "/tmp/nenscript$$";

        open(FILE, "|$nenscript -2G -i$file -N -p$tmpfile -r") || 

                die "Can't open nenscript: $!\n";

        foreach $line (@newlines) {

                print FILE $line;

        }

        close(FILE);

        

        # Read the temporary file back into an array so it can be

        # passed to the Samba print script.

        @newlines = ("");

        open(FILE, "<$tmpfile") || die "Can't open $file: $!\n";

        while(<FILE>) {

                push(@newlines,$_);

        }

        close(FILE);

        system("rm $tmpfile");

}



sub createarray {

        # Create the array for postscript

        open(FILE, "<$file") || die "Can't open $file: $!\n";

        while(<FILE>) {

                push(@newlines,$_);

        }

        close(FILE);

}



Next Previous Contents