as400->pdf
cschen33.tw@yahoo.com
日期:2006/02/22

這是應用tn52500軟體及Redhat FC4來實作,不使用IBM personal communication(PC) 軟體
使用CUPS印表系統,作完了覺得可以完全取代PC的印表機轉向工作,但無法列印中文

原理:
linux (lp5250d)->as400 (產生虛擬印表機)
as400(列印)->linux(lp5250d)->產生pdf檔
因此重點在linux上的lp5250d的設定

使用系統及軟體
FC4
CUPS
tn5250
a2ps
ghostscript-ps2pdf
python

設定lp5250d
它可以在命令列直接下命令,也可以讀取使用者目錄下.tn5250rc的設定
例:
lp5250d env.DEVNAME=testprint  outputcommand="scs2ascii | lpr"  192.168.0.100
連線到192.168.0.100產生虛擬印表機testprint,當使用者列印時轉向本機的預設列表機

同下先編輯.tn5250rc在個人的目錄下
cd
vi .tn5250rc,加入下面內容
mytest {
          host=192.168.0.100
         env.DEVNAME=testprint
          outputcommand=scs2ascii  | lpr
}
然後在命令列下
lp525pd  mytest 
就可以了

三個有用的程式
scs2ascii
scs2ps
scs2pdf
這個三個程式可以用在outputcommand=
scs2ascii-將資料轉為文字檔
scs2ps-將資料轉為ps檔
scs2pdf-將資料轉為pdf檔
#outputcommand 會將自as400取得的列印資料流(stream)轉到這堜狳洏峈熊{式
#scs2pdf及scs2ps對於寬的報表會產生一邊被裁掉,因此無法應用才有本文件

lp5250d設定
outputcommand =scs2ascii  | 自己的程式
現在定了之後重點就是自己的程式
我沿用之前使用python的程式

測試
使用outputcommand=scs2ascii > /tmp/abc.txt
由400印列到linux後,產生一個abc.txt檔案
注意:列印的文件有兩種,一種是含有^M,另外一種是不含^M,若不含^M很簡單(取得最寬行,如果超過某個寬度,假設85,在a2ps 使用橫向列印參數-r,小於85直向參數-R)
以下討論含有^M
在linux下
vi檢視
多了^M 及^L
hexdump  abc.txt  -C | more
查到
^M = 0d
^L=0c  
man ascii
查到
0d-回到行首
0a-換行(linux)
0d 0a -換行(dos)

0c-換頁
#^M是將該行文字分為兩段假設該行為 aaaaa^Mbbbbb, 文字為A及B段,B回到行首直接覆寫在A上,^M可能有多個
#因為有10進位、16進位、ASCII的表示法,無法得知在python程式中表示法為何?
python 測試
python
>> tmpf=open("/tmp/abc.txt")
>>line=tmpf.readline()      
##重複執行數次到含有^M
>>sub_string=line.split("\r")
##將字串分割

以下是程式碼:
#!/usr/bin/python
import sys,tempfile,commands,time,string
from time import localtime,time,strftime
dir='/home/samba/ps2pdf/'
tempdir=dir+'temp/'
output_dir='outfile/'
tempn1=tempfile.mktemp('.tmp')
tempn2=tempfile.mktemp('.txt')
tempn3=tempfile.mktemp('.ps')
maxline=0
p_unix2dos=commands.getoutput('which unix2dos ')+" -o "
p_a2ps=commands.getoutput('which a2ps')+" "
p_ps2pdf=commands.getoutput('which ps2pdf14')+" "
#請修改out_file到你要輸出的地方
out_file=dir+output_dir+strftime('%m%d-%H%M%S.pdf',localtime(time()))
def combine_string(subs1,subs2):
    return_string=""
    s_wide=max(len(subs1),len(subs2))
    subs1=subs1.ljust(s_wide)
    subs2=subs2.ljust(s_wide)
    for i in xrange(0,s_wide):
        if subs1[i]==" " and subs2[i]!=" " :
           return_string=return_string+subs2[i]
        else:
           return_string=return_string+subs1[i]
    return return_string+"\n"


pipefile=sys.stdin
tempf1=open(tempn1,'w+')
tempf1.write(pipefile.read())
tempf1.close()
tempf1=open(tempn1,'r')
line=tempf1.readline()
tempf2=open(tempn2,'w+')
while line:
     sub_str=line.split("\r")
     if len(sub_str)==1:
        line=sub_str[0]   
     elif len(sub_str)==2:
        s1=sub_str[0]
        s2=sub_str[1]
        s2=s2[1:]
        s2=s2.replace("\n","")
        line=combine_string(s1,s2)
     else:
        s1=sub_str[0]
        s2=sub_str[1]
        line=combine_string(s1,s2)
     if len(line)>=maxline:
        maxline=len(line)

     tempf2.write(line)
     line=tempf1.readline()

tempf1.close()
tempf2.close()
pipefile.close()
convert_prg1='/usr/bin/a2ps '
convert_prg2='/usr/bin/ps2pdf14 '
#page width
#if width >85 then we chang the print orientation from
if maxline>=85:
   print_dir=' -r '
else:
   print_dir=' -R '

convert_opt=' --no-header --borders=0 -M letter --columns=1 --rows=1 '+print_dir+'-l '+str(maxline)+' -o '
convert_string=p_a2ps+tempn2+convert_opt+tempn3
a=commands.getoutput(convert_string)
#轉換PDF檔,為了除錯我分成兩行,你可以使用|合成一行
a=commands.getoutput('/usr/bin/ps2pdf '+tempn3+" "+out_file)
a=commands.getoutput('/bin/chmod 444 '+out_file)
#列印PS檔到印表機laser
#若要使用下這個功能,將前兩行mark起來
#a=commands.getoutput('lpr -P laser '+tempn3)
a=commands.getoutput('unlink '+tempn1)
a=commands.getoutput('unlink '+tempn2)
a=commands.getoutput('unlink '+tempn3)



程式 說明
讀取scs2ascii所傳來的stream,將行中有^M合併字串,使用a2ps轉為ps檔,再使用ps2pdf14將檔案轉為pdf檔,a2ps使用 的參數--no-header --borders=0 -M letter --columns=1 --rows=1 ,還有一個是要根據每行的字數看要直印還是橫印,我是使用 85為分界,<85 -R ,>=85 -r

再設定.tn5250rc
假設寫好的程式為/home/csc/txt2pdf
pdf  {
          host=192.168.0.100
         env.DEVNAME=pdf
          outputcommand=scs2ascii  | /home/csc/txt2pdf
}

排程
你可以在/etc/cron.d內編輯,或是用其它工具來設定,時間自己定
1.啟動
    lp5250d  pdf
2.關閉
    killall lp5250d -s KILL
    用於跑多個lp5250d

EPSON2080C轉向測試
以下示範兩種方式
1.smb -假設主機名稱為test1,分享印表機epson
2.lpd  - 假設ip=192.168.0.50,分享印表機 epson
執行setup -> printer configure ->新增印表機(dot,dot1)選用epson 點矩陣,填入上述資料,驅動程式在設定解析度180x180

dot{
   host=192.168.0.100
   env.DEVNAME = dot
   env.IBMMFRTYPMDL = *EPLQ1170
   outputcommand = lpr -P dot -oraw
}
dot1 {
   host=192.168.0.100
   env.DEVNAME = dot1
   env.IBMMFRTYPMDL =*EPLQ1170
   outputcommand = lpr -P dot1 -oraw
}
其中-oraw一定要下否則在/var/log/cups/error_log,會警告你無法列印stream
#或是  修改/etc/cups/中
mime.convs-application/octet-stream
mime.types-application/octet-stream
的#去掉,則可以不用-oraw
將轉成的pdf檔直接列印
測試,你要先設定好印表機假設laser
lpr abc.pdf -P laser 如果列印正常設定
.tn5250rc
laser {
         host=192.168.0.100
          env.DEVNAME=laser
          env.IBMMFRTYPMDL=*HP4
         outputcommand=scs2pdf | 你的pdf轉檔程式 
}
你的程式中可以加入lpr 檔案名稱 -P laser -oraw ,當使用者列印這個印表機時會被轉成pdf檔,然後再列印

我的kyeroa mita fs1010,無法使用hp4相容直接列印
laser {
         host=192.168.0.100
          env.DEVNAME=laser
          env.IBMMFRTYPMDL=*HP4
         outputcommand=lpr -P laser  -oraw
}
因此使用轉為ps然後再列印,沒有問題,任何資料都可以被我的程式轉為ps再列印