다음 이전 차례

9. M$의 프린터를 리눅스와 공유하기

M$의 프린터를 공유하기 위해서는 아래의 작업을 꼭 해야만 한다.

a) /etc/printcap 화일에 로컬 디렉토리 구조(스풀디렉토리 등)와 정확히 일치하는 적당한 사항들이 있어야 한다.

b) /usr/bin/smbprint 화일이 있어야 한다. 이 화일은 삼바 소스에 같이 포함되어 있는데, 삼바 실행 화일만이 들어있는 배포본에는 빠져있을 수 있다. 이 화일을 약간 수정한 것이 아래에 설명되어 있다.

c) 만약 아스키 화일을 포스트스크립트 화일로 변환하기 위해서는 nenscript나 그와 같은 역할을 하는 것을 가지고 있어야만 한다. nenscript는 포스트스크립트 변환기이고 보통은 /usr/bin 아래에 설치된다.

d) 삼바로 프린팅할때 사용하기 편한 도구를 이용하기를 원할 것이다. 아스키 화일, 포스트스크립트 화일을 처리해주는, 또는 포스트스크립트 화일을 생성해주는 펄 스크립트가 아래에 주어져 있다.

M$ NT 호스트의 HP 5MP 프린터를 위한 /etc/printcap 화일의 설정이 아래에 주어져 있다. 각 항목들은 다음의 의미가 있다


        cm - 주석(프린터 설명)
        lp - 출력을 위한 장치명
        sd - 로컬 컴퓨터의 프린터 스풀 디렉토리
        af - the accounting file
        mx - 최대 화일 크기( 0은 제한이 없음을 뜻한다)
        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:

스풀 디렉토리와 accounting 디렉토리가 존재하고 쓰기가능 모드로 설정을 해주어야 한다. 또한 'if' 줄에 smbprint 스크립트(아래에 주어진)의 정확한 경로가 적혀있는지, 적절한 장치를 가리키고 있는지(/dev 아래의 특별 화일)를 확인해야 한다.

다음으로 smbprint 스크립트에대한 설명이다. 스크립트는 대개 /usr/bin 아래에 위치하고, 삼바를 만든사람으로 여겨지는 Andrew Tridgell에 의한 것이다. 이 스크립트는 삼바소스 배포본에는 포함되어있지만 실행화일 배포본에는 들어있지 않다. 그래서 여기에서 다시 만들어 볼 것이다.

이 스크립트를 주의깊게 살펴볼 것으로 여겨지는데, 이 스크립트를 그냥 그대로 사용하는 것보다는 자신의 환경에 알맞게 수정하는 것이 더 바람직하고 유용하다.


#!/bin/sh -x

# 이 스크립트는 유닉스 상에서 printcap 프린팅을 위한 입력 필터이다.
# 이것은 지정된 삼바 서버와 서비스에 화일을 프린트하기 위한 smbclient
# 프로그램을 이용한다.
# 예를 들어 printcap 설정을 아래처럼 할 수 있다
#
# smb:lp=/dev/null:sd=/usr/spool/smb:sh:if=/usr/local/samba/smbprint
#
# 위의 설정은 이 스크립트를 통해 프린트하는 "smb" 라는 유닉스 프린터를
# 만든다. 또한 적절한 권한과 소유권을 가진 /usr/spool/smb 스풀디렉토리를
# 만들어야 한다.

#
# 스크립트는 hamiltom@ecnz.co.nz (Michael Hamilton)에 의해서 서버, 서비스
# 그리고 암호를 /usr/var/spool/lpd/PRINTNAME/.config 화일에서 읽을 수
# 있도록 바뀌어졌다.
#
# 이것을 가능하게 하기 위해서는 /etc/printcap에 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:
#
# /usr/var/spool/lpd/PRINTNAME/.config 화일에 다음 사항들을 포함한다:
#   server=PC_SERVER
#   service=PR_SHARENAME
#   password="password"
#
# E.g.
#   server=PAULS_PC
#   service=CJET_371
#   password=""

#
# Debugging log file, 원한다면 /dev/null로 바꿔도 된다.
#
logfile=/tmp/smb-print.log
# logfile=/dev/null


#
# 필터의 마지막 파라미터는 accounting 화일 이름이다.
#
spool_dir=/var/spool/lpd/lp
config_file=$spool_dir/.config

# config 화일에서 다음 변수 설정을 읽어 들인다.
#   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

(
# 주의: 프린트시에 자동으로 CR/LF 변환을 가능하게 하려면 `echo translate'를
# 추가한다.
  echo translate
        echo "print -"
        cat
) | /usr/bin/smbclient "\\\\$server\\$service" $password -U $user -N -P >> $logfile

대부분의 리눅스 배포판은 아스키 문서를 포스트스크립트로 변환해주는 nenscript를 가지고 있다. 다음 perl 스크립트는 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.

아스키 화일을 프린트하기 위해서 smbprint를 이용할때 긴 줄은 잘리는 경우가 있다. 이 스크립트는 가능하다면 긴 줄이 단어 중간이 잘리는 대신에 공백에서 잘리도록 해준다.

nenscript는 소스코드에 형식을 준다. 장식적인 머릿말(날짜, 화일이름 등)을 추가하여 아스키 화일과 형식을 생성한다. 또한, 줄번호를 매긴다. 아래 예를 이용하여 다른 모양의 형식도 가능하다.

포스트스크립트 문서는 이미 적절한 형식을 가지고 있으므로 직접 출력이 된다.


#!/usr/bin/perl

# Script:   print
# Authors:  Brad Marshall, David Wood
#           Plugged In Communications
# Date:     960808
#
# Script to print to oreilly which is currently on zimmerman
# 목적: 여러가지 형식의 화일들을 인자로서 받아들여 삼바 프린트 스크립트에
# 파이프로 보내는데 적당하게 처리를 한다.
#
# 가능한 화일 형식:
# 
# ASCII      - $line_length 보다 더 긴 글자들을 공백으로 줄 길이를 조정한다. 
# Postscript - 아무런 처리도 하지 않는다.
# Code       - 적당하게(출력방향, 글자모양 등) 출력하기 위해서 nenscript를
#                                                이용하여 포스트스크립트 문서로 만든다.
#

# 아스키 텍스트 문서에서 한 줄당 최대 글자수.
$line_length = 76;

# 삼바 프린트 스크립트의 경로와 이름.
$print_prog = "/usr/bin/smbprint";

# nenscript의 경로와 이름(아스키-->포스트스크립트 변환기)
$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;
}
# smbprint로 각 줄들을 연결(출력)시킨다.
open(PRINTER, "|$print_prog") || die "Can't open $print_prog: $!\n";
foreach $line (@newlines) {
        print PRINTER $line;
}
# 화일의 마지막 줄이 제대로 끝나지 않은 경우에 줄바꿈(라인피드)를 추가한다.
print PRINTER "\n";
close(PRINTER);
print "Completed\n";
exit 0;

# --------------------------------------------------- #
#        Everything below here is a subroutine        #
# --------------------------------------------------- #

sub ParseCmdLine {
        # 코맨드 라인을 분석해서 화일의 형식이 무엇인지 찾아낸다.

        # $arg와 $file 이 있다면 값을 얻는다. 
        # 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;
        }
        
        # 화일 형식을 정의한다.
        unless ($cmd) {
                # 아무런 인자가 없을 경우.

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

                # $file의 화일형식이 무엇인지 알아내서 $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 "
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.\n
";
        exit(0);
}

sub wrap {
        # 줄길이가 지정된 글자수보다 적도록 화일의 각 줄을 배열에 할당한다.
        # 공백을 이용해 줄길이를 조정한다.

        # 줄길이를 제한할 글자수의 값을 얻는다. 
        $limit = pop(@_);

        # DBG
        #print "Entering subroutine wrap\n";
        #print "The line length limit is $limit\n";

        # 화일을 읽어들여 분석하고 각 줄을 배열에 할당한다.
        open(FILE, "<$file") || die "Can't open $file: $!\n";
        while(<FILE>) {
                $line = $_;
                
                # DBG
                #print "The line is:\n$line\n";

                # 제한길이보다 긴 줄은 길이를 조정한다.
                while ( length($line) > $limit ) {
                        
                        # DBG
                        #print "Wrapping...";

                        # $limit +1 까지의 글자들을 얻는다.
                        $part = substr($line,0,$limit +1);

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

                        # 마지막 문자가 공백인지 아닌지를 조사한다.
                        $last_char = substr($part,-1, 1);
                        if ( " " eq $last_char ) {
                            # 공백이라면 그대로 출력한다.

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

                            substr($line,0,$limit + 1) = "";
                            substr($part,-1,1) = "";
                            push(@newlines,"$part\n");
                        } else {
                             # 공백이 아니라면 마지막 공백의 위치를
                             # 찾고 그곳까지 출력한다.

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

                             # $limit 이전의 글자를 지운다.
                             substr($part,-1,1) = "";
                             # 마지막 공백을 찾기 쉽게 줄을 뒤집는다.
                             $revpart = reverse($part);
                             $index = index($revpart," ");
                             if ( $index > 0 ) {
                               substr($line,0,$limit-$index) = "";
                               push(@newlines,substr($part,0,$limit-$index) 
                                   . "\n");
                             } else {
                               # 공백을 포함하지 않은 줄이라면
                               # $limit 까지 출력을 한다.
                               substr($line,0,$limit) = "";
                               push(@newlines,substr($part,0,$limit) 
                                   . "\n");
                             }
                        }
                }
                push(@newlines,$line);
        }
        close(FILE);
}

sub codeformat {
        # 서브루틴 wrap를 호출해서 nenscript를 통한 필터링을 한다. 
        &wrap($line_length);
        
        # 소스 코드를 프린트하기 위해 몇가지 알맞은 형식들(용지방향,
        # Courier font, 줄번호)을 포함시킨 포스트스크립트 화일을 생성
        # 하기 위해서 nenscript의 결과를 처리한다.
        # 첫번째로 임시화일로 출력한다.
        $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);
        
        # 임시 화일을 다시 읽어들여서 삼바 프린트 스크립트로 출력할
        # 수 있도록 배열에 저장한다.
        @newlines = ("");
        open(FILE, "<$tmpfile") || die "Can't open $file: $!\n";
        while(<FILE>) {
                push(@newlines,$_);
        }
        close(FILE);
        system("rm $tmpfile");
}

sub createarray {
        # 포스트스크립트를 위한 배열을 생성한다.
        open(FILE, "<$file") || die "Can't open $file: $!\n";
        while(<FILE>) {
                push(@newlines,$_);
        }
        close(FILE);
}


다음 이전 차례