Patch title: Release 85 bulk changes
Abstract:
File: /pliant/protocol/lpr/client.pli
Key:
    Removed line
    Added line
# Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# version 2 along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

module "/pliant/language/unsafe.pli"
module "/pliant/language/context.pli"
module "/pliant/language/stream.pli"
module "/pliant/language/stream/openmode.pli"
module "/pliant/language/stream/multi.pli"
module "/pliant/language/stream/filesystembase.pli"
module "/pliant/admin/file.pli"

constant lpr_timeout 900 # default timeout is 15 minutes

(gvar TraceSlot lpr_trace) configure "LPR client"


type LprFileSystem
  void
FileSystem maybe LprFileSystem

type LprStreamDriver
  field Link:Stream tcp
  field CBool direct nosize ; field Intn remain
  field Str filename
  field Link:Stream temp
  field Str server id
StreamDriver maybe LprStreamDriver

method lpr write buf mini maxi -> written
  arg_rw LprStreamDriver lpr ; arg Address buf ; arg Int mini maxi written
  if lpr:direct
    if lpr:nosize
      written := maxi
    eif lpr:remain>=maxi
      written := maxi
    eif lpr:remain>=mini
      written := lpr remain
    else
      written := 0
    lpr:tcp raw_write buf written
    if lpr:tcp=failure
      written := 0
    lpr remain -= written
  eif (exists lpr:temp)
    lpr:temp raw_write buf maxi
    written := shunt lpr:temp=success maxi 0
  else
    written := 0

method lpr flush level -> status
  arg_rw LprStreamDriver lpr ; arg Int level ; arg Status status
  lpr:tcp flush level
  if lpr:direct
    lpr:tcp flush level
  eif (exists lpr:temp)
    lpr:temp flush level
  status := success

method lpr query command stream answer -> status
  oarg_rw LprStreamDriver lpr ; arg Str command ; arg_rw Stream stream ; arg_w Str answer ; arg ExtendedStatus status
  if command="seek" and not lpr:direct
    stream flush anytime
    status := lpr:temp:stream_driver query command lpr:temp answer
  else
    status := failure

method lpr configure command stream -> status
  arg_rw LprStreamDriver lpr ; arg Str command ; arg_rw Stream stream ; arg ExtendedStatus status
  if (command parse word:"seek" (var Intn pos)) and not lpr:direct
    stream flush anytime
    status := lpr:temp:stream_driver configure command lpr:temp
  else
    status := failure

method lpr close -> status
  arg_rw LprStreamDriver lpr ; arg ExtendedStatus status
  var Pointer:Stream tcp :> lpr tcp
  if lpr:direct
    if not lpr:nosize and lpr:remain<>0
      return failure:"Too fiew bytes written"
  eif (exists lpr:temp)
    lpr:temp close
    var FileInfo info := file_query lpr:filename standard
    var uInt8 cmd8 := 3 ; tcp raw_write addressof:cmd8 1
    tcp writeline (string info:size)+" dfa"+lpr:id+computer_name
    tcp raw_read addressof:(var uInt8 ack) 1
    if ack<>0
      file_delete lpr:filename
      lpr_trace trace "'" lpr:server "' does not want to receive print data file"
      return (failure "'"+lpr:server+"' does not want to receive print data file")
    (var Stream s) open lpr:filename in
    while (raw_copy s tcp 1 2^24)>0
      void
    s close
    file_delete lpr:filename
  if not lpr:nosize
    var uInt8 cmd8 := 0 ; tcp raw_write addressof:cmd8 1
    tcp raw_read addressof:(var uInt8 ack) 1
    if ack<>0
      lpr_trace trace "server failed to receive data file (" (cast ack Int) ")"
      return (failure "server failed to receive data file ("+string:(cast ack Int)+")")
  status := tcp close

gvar Int counter := -1

method fs open name options flags stream support -> status
  arg_rw LprFileSystem fs ; arg Str name options ; arg Int flags ; arg_rw Stream stream support ; arg ExtendedStatus status
  if (name eparse "//" any:(var Str server) "/" any:(var Str queue) "/" any:(var Str file))
    void
  eif (name eparse "//" any:(var Str server) "/" any:(var Str queue))
    file := ""
  else
    return failure:"Incorrect name"
  if (flags .and. in_out)<>out
    return failure:"The only supported mode for LPR client is 'out'"
  var Intn size := options option "file_size" Intn
  var Link:Stream tcp :> new Stream
  var Int lap := 1
  part select_id
    tcp open "tcp://"+server+"/client/515" in+out+safe
    if tcp=failure
      lpr_trace trace "Failed to connect to '" server "' LPR port"
      return (failure "Failed to connect to '"+server+"' LPR port")
    tcp configure "timeout "+string:(options option "timeout" Int lpr_timeout)
    var uInt8 cmd8 := 2 ; tcp raw_write addressof:cmd8 1
    tcp writeline (shunt queue<>"" queue "lp")
    tcp raw_read addressof:(var uInt8 ack) 1
    if ack<>0
      lpr_trace trace "'" server "' does not want to receive a print job"
      return (failure "'"+server+"' does not want to receive a print job")
    counter := (counter+1)%1000
    var Str id := right string:counter 3 "0"
    var Str control := "H"+computer_name+"[lf]P"+(options option "user" Str "Pliant")+"[lf]"+(options option "lpr_format" Str "l")+"dfa"+id+computer_name+"[lf]Udfa"+id+computer_name+"[lf]J"+(options option "title" Str)+(shunt file<>"" "[lf]N"+file "")+"[lf]"
    var uInt8 cmd8 := 2 ; tcp raw_write addressof:cmd8 1
    tcp writeline (string control:len)+" cfa"+id+computer_name
    tcp raw_read addressof:(var uInt8 ack) 1
    if ack<>0 and lap<1000
      lap += 1
      restart select_id
    if ack<>0
      lpr_trace trace "'" server "' does not want to receive print control file"
      return (failure "'"+server+"' does not want to receive print control file")
    tcp writechars control
    var uInt8 cmd8 := 0 ; tcp raw_write addressof:cmd8 1
    tcp raw_read addressof:(var uInt8 ack) 1
    if ack<>0
      lpr_trace trace "'" server "' failed to receive print control file (" (cast ack Int) ")"
      return (failure "'"+server+"' failed to receive print control file ("+string:(cast ack Int)+")")
    var Link:LprStreamDriver lpr :> new LprStreamDriver
    lpr tcp :> tcp
    if size<>undefined or (options option "lprng")
      lpr direct := true
      lpr remain := size
      lpr nosize := size=undefined
      var uInt8 cmd8 := 3 ; tcp raw_write addressof:cmd8 1
      tcp writeline string:(shunt size=undefined 0 size)+" dfa"+id+computer_name
      tcp raw_read addressof:(var uInt8 ack) 1
      if ack<>0 and lap<1000
        var uInt8 cmd8 := 1 ; tcp raw_write addressof:cmd8 1
        tcp writeline ""
        tcp raw_read addressof:(var uInt8 ack) 1
        if ack=0
          lap += 1
          restart select_id
      if ack<>0
        lpr_trace trace "'" server "' does not want to receive print data file"
        return (failure "'"+server+"' does not want to receive print data file")
    else
      lpr direct := false
      lpr nosize := false
      lpr filename := file_temporary
      lpr temp :> new Stream
      lpr:temp open lpr:filename out+(flags .and. safe)
      lpr server := server
      lpr id := id
  stream stream_driver :> lpr
  lpr_trace trace "print job queued on '"+server+"' in queue '"+queue+"'"
  status := success
    
gvar LprFileSystem lpr_file_system
pliant_multi_file_system mount "lpr:" "" lpr_file_system
pliant_multi_file_system mount "lprng:" "" "lprng" lpr_file_system