# PyKota sample configuration file # # Copy this file into the /etc/pykota/ directory # under the name /etc/pykota/pykota.conf # # PyKota - Print Quotas for CUPS and LPRng # # (c) 2003-2004 Jerome Alet <[email protected]> # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # 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 # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. # # $Id: pykota.conf.sample,v 1.104 2004/10/06 08:19:29 jalet Exp $ # [global] # Storage backend for quotas # only PGStorage (PostgreSQL) and LDAPStorage (OpenLDAP) are supported. # MySQL and BerkeleyDB are planned. # the 'postgresql' value is deprecated, use 'pgstorage' instead. storagebackend: ldapstorage # Quota Storage Server hostname (and optional port) # e.g. db.example.com:5432 storageserver: ldap://gsr.pt:389 # # name of the Quota Storage Database storagename: dc=gsr,dc=pt # # Quota Storage normal user's name and password # These two fields contain a username and optional password # which may give readonly access to your print quota database. # # PLEASE ENSURE THAT THIS USER CAN'T WRITE TO YOUR PRINT QUOTA # DATABASE, OTHERWISE ANY USER WHO COULD READ THIS CONFIGURATION # FILE COULD CHANGE HIS PRINT QUOTA. # storageuser: cn=pykotauser,dc=gsr,dc=pt storageuserpw: ********** # Should the database caching mechanism be enabled or not ? # If unset, caching is disabled. Possible values Y/N/YES/NO # caching mechanism works with both PostgreSQL and OpenLDAP backends # but may be really interesting only with OpenLDAP. # # ACTIVATING CACHE MAY CAUSE PRECISION PROBLEMS IN PRINT ACCOUNTING # IF AN USER PRINTS ON SEVERAL PRINTERS AT THE SAME TIME. # YOU MAY FIND IT INTERESTING ANYWAY, ESPECIALLY FOR LDAP. # # FYI, I ALWAYS SET IT TO YES ! # storagecaching: No # Should full job history be disabled ? # If unset or set to No, full job history is kept in the database. # This will be useful in the future when the report generator # will be written. # Disabling the job history can be useful with heavily loaded # LDAP servers, to not make the LDAP tree grow out of control. # Disabling the job history with the PostgreSQL backend works too # but it's probably less useful than with LDAP. disablehistory: No # LDAP example, uncomment and adapt it to your own configuration : #storagebackend: ldapstorage #storageserver: ldap://ldap.librelogiciel.com:389 #storagename: dc=librelogiciel,dc=com #storageuser: cn=notadmin,dc=librelogiciel,dc=com #storageuserpw: abc.123 # # Here we define some helpers to know where # to plug into an existing LDAP directory userbase: ou=people,dc=gsr,dc=pt userrdn: uid balancebase: ou=people,dc=gsr,dc=pt balancerdn: uid groupbase: ou=groups,dc=gsr,dc=pt grouprdn: cn printerbase: ou=printers,ou=pykota,dc=gsr,dc=pt printerrdn: cn jobbase: ou=jobs,ou=pykota,dc=gsr,dc=pt userquotabase: ou=uquotas,ou=pykota,dc=gsr,dc=pt groupquotabase: ou=gquotas,ou=pykota,dc=gsr,dc=pt lastjobbase: ou=lastjobs,ou=pykota,dc=gsr,dc=pt # # How to create new accounts and groups # authorized values are "below" and "attach(objectclass name [, fail|warn])" # # "below" creates the new accounts/groups as standalone entries # below the above defined 'userbase' ou # # attach(objectclass name [, action]) tries to find some existing user/group # using the above defined 'userrdn' or 'grouprdn' and 'userbase' # 'groupbase', and attach the PyKota specific entries to it. # if action is "warn" and no entry exists to attach to, a new # entry is created, and a message is logged. # if action is "fail" and no entry exists to attach to, program # logs an error message and aborts. # if action is not set, the default value is "fail". # # a possible value: newuser: attach(posixAccount, warn) newuser : attach(posixAccount, warn) newgroup : attach(posixGroup, warn) # # LDAP attribute which stores the user's email address usermail : mail # # Choose what attribute contains the list of group members # common values are : memberUid, uniqueMember, member groupmembers: memberUid # Activate low-level LDAP cache yes/no # Nothing to do with "storagecaching" which is higher level # and database independant. # This saves some search queries and may help with heavily # loaded LDAP servers. # This is EXPERIMENTAL. # # BEWARE : SETTING THIS TO 'YES' CAUSES PROBLEMS FOR NOW # BETTER TO LET IT SET TO 'NO' # ldapcache: no # Where to log ? # supported values : stderr, system (system means syslog, # but don't use 'syslog' here) if the value is not set # then the default SYSTEM applies. logger: system # Enable debugging ? Put YES or NO there. # From now on, YES is the default in this sample # configuration file, so that debugging is activated # when configuring PyKota. After all works, just # put NO instead to save some disk space in your # logs. # Actually only database queries are logged. debug : Yes # Mail server to use to warn users # If the value is not set then localhost is used. smtpserver: localhost # Crash messages' recipient : in addition to the log files # each software crash can be sent to the author of PyKota # or any other person of your choice. By default this # is disabled. The recipient [email protected] # reaches PyKota's author. # The 'adminmail' (defined a bit below) is CCed. # # Privacy concerns : what is sent is only : # # - a copy of the software's traceback # - a copy of the software's command line arguments # - a copy of the software's environment variables # # suggested value # crashrecipient: [email protected] # Email domain # If the value is not set, and the mail attribute for the user # is not set in the PyKota storage, be it LDAP (see usermail directive # above) or PostgreSQL, then email messages are sent to # username@smtpserver # # If the value is set, then email messages are sent to # username@maildomain using the SMTP server defined above # # Set the appropriate value below, example.com set as per RFC2606. maildomain: gsr.pt # Should we force usernames to be all lowercase when printing ? # Default is No. # This is a global option only. # Some people reported that WinXP sends mixed case usernames # setting 'utolower: Yes' solves the problem. # Of course you have to use lowercase only when adding # users with edpykota, because ALL database accesses are # still case sensitive. # # If utolower is Yes, the usernames received from the printing # system is converted to lowercase at the start of the cupspykota # backend or of the lprngpykota filter. # # If utolower is No, which is the default, strict case checking # is done, this means that users 'Jerome' and 'jerome' are # different. Printer and groups names are ALWAYS case sensitive. utolower: No # Should we split usernames on a specific separator when printing ? # Default is No, i.e. if the value is unset. # This is a global option only. # This option adds support for Samba's Winbind utility, which # prefixes usernames with domain name and separator character. # Of course if you set this then you have to use NO separator when # adding users with edpykota. # # If winbind_separator is set, the usernames received from the printing # system are split on the separator's value, and only the last part # (real username) is used. # # If winbind_separator is not set, which is the default, strict # username equality checking will be done (modulo the setting # of the 'utolower' directive), this means that users 'DOMAIN1/jerome', # 'Domain2/jerome' and 'jerome' are different. # winbind_separator: / # What is the accounting backend to use # # supported values : # # - hardware : asks the printer for its lifetime page counter # via either SNMP, AppleTalk, or any external # command. This method is the method used by # default in PyKota since its beginning. # # In the lines below "%(printer)s" is automatically replaced # at run time with your printer's Fully Qualified Domain Name # for network printers. # e.g. myprinter.example.com # # Recommended values : # # accounter: hardware(snmp) # # Extracts the printer's internal page counter via SNMP. # # Or : # # accounter: hardware(pjl) # # Extracts the printer's internal page counter via PJL queries # over port tcp/9100. # # Other Examples : # # accounter: hardware(/usr/bin/snmpget -v1 -c public -Ov \ # %(printer)s mib-2.43.10.2.1.4.1.1 | cut -f 2,2 -d " ") # # Another untested example, using npadmin : # # accounter: hardware(/usr/bin/npadmin --pagecount %(printer)s) # # Another example, for AppleTalk printers which works fine : # (You may need the pap CUPS backend installed, and copy the # pagecount.ps file from untested/netatalk into /etc or any # appropriate location) # # accounter: hardware(/usr/share/pykota/papwaitprinter.sh \ # "MyPrinter:LaserWriter@*" && /usr/bin/pap -p \ # "MyPrinter:LaserWriter@*" /usr/share/pykota/pagecount.ps \ # 2>/dev/null | /bin/grep -v status | /bin/grep \ # -v Connect | /usr/bin/tail -1) # # An example for parallel printers like the HP Laserjet 5MP : # # accounter: hardware(/bin/cat /usr/share/pykota/pagecount.pjl \ # >/dev/lp0 && /usr/bin/head -2 </dev/lp0 | /usr/bin/tail -1) # # This value can be set either globally or per printer or both. # If both are defined, the printer option has priority. # # Some examples and comments provided by Bob Martel from csuohio.edu # # For several printers I could not get the page count using snmpget. I # resorted to snmpwalk: # # accounter: hardware(/opt/local/net-snmp/bin/snmpwalk -v 1 -Cc \ # -c public %(printer)s | grep \ # mib-2.43.10.2.1.4.1.1 | cut -d " " -f4) # # The last example is still more ugly, some of the printers only provided # their counters without names, but at least always on the same line: # # accounter: hardware(/opt/local/net-snmp/bin/snmpwalk \ # -v 1 -Cc -c public -Ov %(printer)s | \ # grep Counter32 | tail -2 | head -1 | cut -d " " -f2) # # An example using netcat and a preformatted PJL job which you can find # in the untested/pjl directory, which is sent to a JetDirect print # server on port 9100 : # # accounter: hardware(/bin/nc -w 2 %(printer)s 9100 \ # </usr/share/pykota/pagecount.pjl | /usr/bin/tail -2) # # An example using the contributed pagecount.pl script which does # the same as above, but should work on more printers : # # accounter: hardware(LC_ALL=C /usr/share/pykota/pagecount.pl \ # %(printer)s 9100) # # NB : the LC_ALL=C is used because sometimes Perl can correctly set # locale and is verbose about it, causing PyKota to miss the # correct answer. # # WARNING : In any case, when using an hardware accounter, please test # the command line outside of PyKota before. This will save # you some headaches in case it doesn't work as expected. # # The waitprinter.sh is there to wait until the printer is idle again. # This should prevent a job to be sent to the printer while another one is # not yet finished (not all pages are printed, but the complete job is in # the printer) # # YOU ABSOLUTELY HAVE TO BE SURE YOU HAVE A SCRIPT WHICH WAITS FOR THE # PRINTER BEING READY BEFORE ASKING FOR ITS INTERNAL PAGE COUNTER. # # PYKOTA INCLUDES SUCH SCRIPTS FOR SNMP AND APPLETALK PRINTERS, MORE TO COME # # SOME OF THE ABOVE EXAMPLES DON'T USE SUCH A SCRIPT, YOU HAVE BEEN WARNED # # # WITH THE SPECIAL MAGIC hardware(snmp) AND hardware(pjl) VALUES, PYKOTA # TAKES CARE OF ALL THIS FOR YOU, SO PLEASE UNDERSTAND THAT IT IS PREFERABLE # TO USE THESE TWO METHODS : THEY WORK FINE, REQUIRE LITTLE TO NO CPU, # AND DO ALL THE HARD WORK AUTOMATICALLY. IF YOU REALLY NEED TO YOU CAN USE # YOUR OWN EXTERNAL COMMANDS AS DESCRIBED ABOVE, JUST BE CAREFUL WITH THIS. # # # - software : delegates the job's size computation to any # external command of your choice. # # best choice for this is probably to set it # this way : # # accounter: software(/usr/bin/pkpgcounter) # # pkpgcounter is a command line tool which is # part of PyKota and which can handle both # DSC compliant or binary PostScript, PCL5, PCL6 (aka PCLXL) # and PDF documents. More file formats will be added # in the future, as time permits. # # while pkpgcounter is the recommended value # you can use whatever command you want provided # that your command accepts the job's data on its # standard input and prints the job's size in pages # as a single integer on its standard output. # # This value can be set either globally or on a per printer basis # If both are defined, the printer option has priority. # # accounter: hardware(/usr/share/pykota/waitprinter.sh %(printer)s && \ # /usr/bin/snmpget -v1 -c public -Ov %(printer)s \ # mib-2.43.10.2.1.4.1.1 | cut -f 2,2 -d " ") # accounter: hardware(snmp) # accounter: hardware(pjl) accounter: software(/usr/bin/pkpgcounter) # What should we do if the accounter's subprocess doesn't return # a valid result (for example doesn't return an integer on its stdout) # # Valid values are : 'continue' and 'stop'. 'stop' is the default # if unset. # # 'continue' means try to process as usual, this may introduce # accounting errors and free jobs. This was the default behavior # until v1.20alpha5. # # 'stop' means fail and stop the print queue. If an accounter # error occurs, most of the time this is a misconfiguration, so # stopping the print queue is usually the better thing to do # until the admin has fixed the configuration. # # This value can be set either globally or on a per printer basis # If both are defined, the printer option has priority. # # onaccountererror: continue onaccountererror: stop # Print Quota administrator # These values can be set either globally or per printer or both. # If both are defined, the printer option has priority. # If these values are not set, the default admin root # and the default adminmail root@localhost are used. admin: Sergio González González adminmail: root@localhost # # Who should we send an email to in case a quota is reached ? # possible values are : DevNull, User, Admin, Both, External(some command) # The Both value means that the User and the Admin will receive # an email message. # The DevNull value means no email message will be sent. # This value can be set either globally or per printer or both. # If both are defined, the printer option has priority. # If the value is not set, then the default BOTH applies. # # Format of the external syntax : # # mailto: external(/usr/bin/mycommand >/dev/null) # # You can use : # # '%(action)s' will contain either WARN or DENY # '%(username)s' will contain the user's name # '%(printername)s' will contain the printer's name # '%(email)s' will contain the user's email address # '%(message)s' will contain the message if you want # to use it. # # On your command line, to pass arguments to your command. # Example : # # mailto: external(/usr/bin/callpager %(username)s \ # "Quota problem on %(printername)s" >/dev/null) # # To automatically send a WinPopup message (this may only work with a PDC, # here the same machine does Samba as PDC + CUPS) : # # mailto: external(echo "%(message)s" | /usr/bin/iconv --to-code utf-8 \ # --from-code iso-8859-15 | /usr/bin/smbclient -M "%(username)s" 2>&1 >/dev/null) # # NB : I use ISO-8859-15, but Windows expects UTF-8, so we pipe the message # into iconv before sending it to the Windows user. # # or more simply : # # mailto: external(/usr/share/pykota/mailandpopup.sh %(username)s \ # %(printername)s "%(email)s" "%(message)s" 2>&1 >/dev/null) # # NB : The mailandpopup.sh shell script is now included in PyKota # # NB : in ANY case, don't forget to redirect your command's standard output # somewhere (e.g. >/dev/null) so that there's no perturbation to the # underlying layer (filter or backend) # mailto: both # # Grace delay in days # This value can be set either globally or per printer or both. # If both are defined, the printer option has priority. # If the value is not set then the default seven (7) days applies. gracedelay: 7 # # Poor man's threshold # If account balance reaches below this amount, # a warning message is sent by email # # If unset, default poor man's threshold is 1.0. # This option can only appear in the global section poorman: 2.0 # Poor man's warning message # The warning message that is sent if the "poorman" value is reached # Again this must appear in the global section poorwarn: Su saldo en la cuota de impresión es bajo. Dentro de poco no podrá volver a imprimir. # Soft limit reached warning message # The warning message that is sent if the soft quota limit is reached # May appear either globally or on a per-printer basis softwarn: Ha alcanzado su límite blando en la cuota de impresión. Esto significa que podrá seguir imprimiendo algún tiempo, pero debería contactar con su administrador para comprar más cuota de impresión. # Hard limit reached error message # The error message that is sent if the hard quota limit is reached # May appear either globally or on a per-printer basis hardwarn: Ha alcanzado su límite duro en la cuota de impresión. Esto significa que no podrá volver a imprimir. Contacte con su administrador en <[email protected]> tan pronto como le sea posible para solucionar el problema. # one section per printer, or no other section at all if all options # are defined globally. # Each section's name must be the same as the printer's queue name as defined # in your printing system, be it CUPS or LPRng, between square brackets, for # example a print queue named 'hpmarketing' would appear in this file as # [hpmarketing] # Default policy to apply when either : # # - Printer doesn't exist in PyKota's database # - User doesn't exist in PyKota's database # - User has no quota entry for this Printer in PyKota's database # # Value can be either allow or deny or external(some command here) # # This value can be set either globally or per printer or both. # If both are defined, the printer option has priority. # If the value is not set then the default policy DENY applies. # There's no policy wrt inexistant groups, they are ignored. # # external policy can be used to launch any external command of your choice, # for example to automatically add the user to the quota storage # if he is unknown. Example : # # policy: external(/usr/bin/edpykota --add --printer %(printername)s \ # --softlimit 50 --hardlimit 60 %(username)s >/dev/null) # # NB : If you want to limit users by their account balance value, it is preferable to # use the following policy to automate user account creation on first print : # # policy: external(/usr/bin/autopykota --initbalance 25.0 >/dev/null) # # This will automatically add the user if he doesn't already exist, and # set his initial balance value to 25.0 (for example). If the user already # exists then his balance value will not be modified. # Please don't use autopykota if you want to limit your users by page # quota, and in any case, carefully read autopykota's help or manpage # and understand its goal before using it in your own configuration. # # Of course you can launch any command of your choice with this, e.g. : # # policy: external(/usr/local/bin/myadminscript.sh %(username)s >/dev/null) # You can use : # # '%(username)s' will contain the user's name # '%(printername)s' will contain the printer's name # # On your command line, to pass arguments to your command. # # NB : Don't forget to redirect your command's standard output somewhere # (e.g. >/dev/null) so that there's no perturbation to the underlying # layer (filter or backend) # # If the printer, user, or user quota entry still doesn't exist after # external policy command was launched (the external command didn't add it), # or if an error occured during the execution of the external policy # command, then the job is rejected. # policy: deny # Pre and Post Hooks # These directives allow the easy plug-in of any command of your choice # at different phases of PyKota's execution. # Pre and Post Hooks can access some of PyKota's internal information # by reading environment variables as described below. # The actual phase of PyKota's execution is available in the # PYKOTAPHASE environment variable. # Pre and Post Hooks can be defined either globally, per printer, # or both. If both are defined, the printer specific hook has # priority. # # List of available environment variables : # NB : Most of these variables are also available during the execution # of external commands defined in the accounter and mailto # directives. # # PYKOTAMD5SUM : Contains an hexadecimal digest of the md5 sum of the job's datas # PYKOTAPHASE : BEFORE or AFTER the job is sent to the printer # PYKOTAACTION : ALLOW or DENY or WARN for current print job # PYKOTAUSERNAME : user's name # PYKOTAPRINTERNAME : printer's name # PYKOTAPGROUPS : list of printers groups the current printer is a member of # PYKOTAJOBID : job's id # PYKOTATITLE : job's title # PYKOTAFILENAME : job's filename # PYKOTACOPIES : number of copies # PYKOTAOPTIONS : job's options # PYKOTABALANCE : user's account balance # PYKOTALIFETIMEPAID : user's grand total paid # PYKOTALIMITBY : user print limiting factor, for example 'quota' or 'balance' # PYKOTAPAGECOUNTER : user's page counter on this printer # PYKOTALIFEPAGECOUNTER : user's life time page counter on this printer # PYKOTASOFTLIMIT : user's soft page limit on this printer # PYKOTAHARDLIMIT : user's hard page limit on this printer # PYKOTADATELIMIT : user's soft to hard limit date limit on this printer # PYKOTASTATUS : contains "CANCELLED" when SIGTERM was received by PyKota # else is not set. # PYKOTAJOBSIZEBYTES : contains the job's size in bytes. Always available. # PYKOTAPRECOMPUTEDJOBSIZE : contains the precomputed job's size (with enforcement: strict) # PYKOTAPRECOMPUTEDJOBPRICE : contains the precomputed job's price (with enforcement: strict) # PYKOTAJOBORIGINATINGHOSTNAME : contains the client's hostname if # it is possible to retrieve it. # PYKOTAPRINTERHOSTNAME : the printer's hostname or IP address for network # printers, or "localhost" if not defined or not # meaningful. # PreHook : gets executed after being sure the user, printer and user quota # entry on the printer both exist in the PyKota database, and after # checking if the user is allowed to print or not, but just before # the job is sent to the printer (if allowed) # prehook has access to many environment variables : # # PYKOTAACTION contains either "ALLOW", "WARN" or "DENY" and # represents the action which is to be done wrt the print job. # PYKOTAPHASE contains 'BEFORE' during execution of prehook # # uncomment the line below to see what environment variables are available # prehook: /usr/bin/printenv >/tmp/before # PostHook : gets executed after the job has been added to the history. # posthook has access to all the environment variables defined above, # as well as two additionnal environment variables : PYKOTAJOBPRICE # and PYKOTAJOBSIZE. # PYKOTAPHASE contains 'AFTER' during execution of posthook. # # uncomment the line below to see what environment variables are available # posthook: /usr/bin/printenv >/tmp/after # How should enforcement be done for this printer ? # # "laxist" is the default if value is not set, and allows users # to be over quota on their last job. # # "strict" tries to prevent users from ever being over quota. # # Enforcement can be defined either globally, per printer, # or both. If both are defined, the printer specific enforcement # setting has priority. # # valid values : "strict" or "laxist" # # default value # enforcement : laxist enforcement : strict |