root / pykota / trunk / pykota / accounters / external.py @ 1180

Revision 1180, 6.5 kB (checked in by jalet, 21 years ago)

More work on new backend. This commit may be unstable.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2# -*- coding: ISO-8859-15 -*-
3#
4# PyKota - Print Quotas for CUPS and LPRng
5#
6# (c) 2003 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20#
21# $Id$
22#
23# $Log$
24# Revision 1.8  2003/11/12 23:29:24  jalet
25# More work on new backend. This commit may be unstable.
26#
27# Revision 1.7  2003/10/07 09:07:28  jalet
28# Character encoding added to please latest version of Python
29#
30# Revision 1.6  2003/09/04 07:57:18  jalet
31# Problem with Python 2.3 fixed : a bug of me.
32#
33# Revision 1.5  2003/07/07 11:49:24  jalet
34# Lots of small fixes with the help of PyChecker
35#
36# Revision 1.4  2003/06/25 14:10:01  jalet
37# Hey, it may work (edpykota --reset excepted) !
38#
39# Revision 1.3  2003/05/27 23:00:21  jalet
40# Big rewrite of external accounting methods.
41# Should work well now.
42#
43# Revision 1.2  2003/05/13 13:54:20  jalet
44# Better handling of broken pipes
45#
46# Revision 1.1  2003/05/07 19:47:06  jalet
47# v1.07 Release of the Shame is out !
48#
49#
50#
51
52import sys
53import os
54import popen2
55import tempfile
56from pykota.accounter import AccounterBase, PyKotaAccounterError
57
58class Accounter(AccounterBase) :
59    def beginJob(self, printer, user) :   
60        """Saves the computed job size."""
61        # computes job's size
62        self.JobSize = self.computeJobSize()
63       
64        # get last job information for this printer
65        if not printer.LastJob.Exists :
66            # The printer hasn't been used yet, from PyKota's point of view
67            self.LastPageCounter = 0
68        else :   
69            # get last job size and page counter from Quota Storage
70            # Last lifetime page counter before actual job is
71            # last page counter + last job size
72            self.LastPageCounter = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0)
73       
74    def endJob(self, printer, user) :   
75        """Do nothing."""
76        pass
77       
78    def getJobSize(self) :   
79        """Returns the actual job size."""
80        try :
81            return self.JobSize
82        except AttributeError :   
83            return 0
84       
85    def doAccounting(self, printer, user) :
86        """Deletgates the computation of the job size to an external command.
87       
88           The command must print the job size on its standard output and exit successfully.
89        """
90        self.beginJob(printer, user)
91       
92        # get the job size, which is real job size * number of copies.
93        jobsize = self.getJobSize() * self.filter.copies
94           
95        # Is the current user allowed to print at all ?
96        userpquota = self.filter.storage.getUserPQuota(user, printer)
97        action = self.filter.warnUserPQuota(userpquota)
98       
99        # update the quota for the current user on this printer, if allowed to print
100        if action == "DENY" :
101            jobsize = 0
102        else :   
103            userpquota.increasePagesUsage(jobsize)
104       
105        # adds the current job to history   
106        printer.addJobToHistory(self.filter.jobid, user, self.getLastPageCounter(), action, jobsize)
107       
108        self.endJob(printer, user)
109           
110        return action
111       
112    def computeJobSize(self) :   
113        """Feeds an external command with our datas to let it compute the job size, and return its value."""
114        temporary = None   
115        if self.filter.inputfile is None :   
116            infile = sys.stdin
117            # we will have to duplicate our standard input
118            temporary = tempfile.TemporaryFile()
119        else :   
120            infile = open(self.filter.inputfile, "rb")
121           
122        # launches external accounter
123        # TODO : USE tempfile.mkstemp() instead ! Needs some work !
124        infilename = tempfile.mktemp()
125        outfilename = tempfile.mktemp()
126        errfilename = tempfile.mktemp()
127       
128        try :
129            # feed it with our data
130            fakeinput = open(infilename, "wb")
131            data = infile.read(256*1024)   
132            while data :
133                fakeinput.write(data)
134                if temporary is not None :
135                    temporary.write(data)
136                data = infile.read(256*1024)
137            fakeinput.close()
138       
139            # launches child process
140            command = "%s <%s >%s 2>%s" % (self.arguments, infilename, outfilename, errfilename)
141            retcode = os.system(command)
142           
143            # check exit status
144            if (os.WIFEXITED(retcode) and not os.WEXITSTATUS(retcode)) or os.stat(errfilename) :
145                # tries to extract the job size from the external accounter's
146                # standard output
147                childoutput = open(outfilename, "r")
148                try :
149                    pagecount = int(childoutput.readline().strip())
150                except (AttributeError, ValueError) :
151                    self.filter.logger.log_message(_("Unable to compute job size with external accounter %s") % self.arguments)
152                    pagecount = 0
153                childoutput.close()   
154            else :
155                self.filter.logger.log_message(_("Unable to compute job size with external accounter %s") % self.arguments)
156                pagecount = 0
157            os.remove(infilename)
158            os.remove(outfilename)
159            os.remove(errfilename)
160        except IOError, msg :   
161            # TODO : temporary files may remain on the filesystem...
162            msg = "%s : %s" % (self.arguments, msg) 
163            self.filter.logger.log_message(_("Unable to compute job size with external accounter %s") % msg)
164            pagecount = 0
165           
166        if temporary is not None :   
167            # this is a copy of our previous standard input
168            # flush, then rewind
169            temporary.flush()
170            temporary.seek(0, 0)
171            # our temporary file will be used later if the
172            # job is allowed.
173            self.filter.inputfile = temporary
174        else :
175            infile.close()
176           
177        return pagecount   
178           
Note: See TracBrowser for help on using the browser.