home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / hplip / hpssd.py < prev    next >
Encoding:
Python Source  |  2007-04-04  |  23.3 KB  |  721 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19. #
  20. # Authors: Don Welch, Pete Parks
  21. #
  22. # Thanks to Henrique M. Holschuh <hmh@debian.org> for various security patches
  23. #
  24. # ======================================================================
  25. # Async code is Copyright 1996 by Sam Rushing
  26. #
  27. #                         All Rights Reserved
  28. #
  29. # Permission to use, copy, modify, and distribute this software and
  30. # its documentation for any purpose and without fee is hereby
  31. # granted, provided that the above copyright notice appear in all
  32. # copies and that both that copyright notice and this permission
  33. # notice appear in supporting documentation, and that the name of Sam
  34. # Rushing not be used in advertising or publicity pertaining to
  35. # distribution of the software without specific, written prior
  36. # permission.
  37. #
  38. # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  39. # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  40. # NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  41. # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  42. # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  43. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  44. # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  45. # ======================================================================
  46. #
  47.  
  48.  
  49. __version__ = '9.1'
  50. __title__ = "Services and Status Daemon"
  51. __doc__ = "Provides persistent data and event services to HPLIP client applications."
  52.  
  53.  
  54. # Std Lib
  55. import sys, socket, os, os.path, signal, getopt, glob, time, select
  56. import popen2, threading, re, fcntl, pwd, tempfile
  57. #from asyncore import dispatcher, loop
  58.  
  59. from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
  60.      ENOTCONN, ESHUTDOWN, EINTR, EISCONN
  61.  
  62. # Local
  63. from base.g import *
  64. from base.codes import *
  65. from base.msg import *
  66. from base import utils, device
  67. from base.async import dispatcher, loop
  68.  
  69. # CUPS support
  70. from prnt import cups
  71.  
  72. # Per user alert settings
  73. alerts = {}
  74.  
  75. # Fax
  76. fax_file = {}
  77. fax_file_ready = {}
  78. fax_meta_data = {}
  79.  
  80. # Active devices - to hold event history
  81. devices = {} # { 'device_uri' : ServerDevice, ... }
  82.  
  83. socket_map = {}
  84. loopback_trigger = None
  85.  
  86.  
  87. class ServerDevice(object):
  88.     def __init__(self, model=''):
  89.         self.history = utils.RingBuffer(prop.history_size)
  90.         self.model = device.normalizeModelName(model)
  91.         self.cache = {}
  92.  
  93. class hpssd_server(dispatcher):
  94.     def __init__(self, ip, port):
  95.         self.ip = ip
  96.         self.send_events = False
  97.  
  98.  
  99.         if port != 0:
  100.             self.port = port
  101.         else:
  102.             self.port = socket.htons(0)
  103.  
  104.         dispatcher.__init__(self)
  105.         self.typ = 'server'
  106.         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  107.         self.set_reuse_addr()
  108.  
  109.         try:
  110.             self.bind((ip, port))
  111.         except socket.error:
  112.             raise Error(ERROR_UNABLE_TO_BIND_SOCKET)
  113.  
  114.         prop.hpssd_port = self.port = self.socket.getsockname()[1]
  115.         self.listen(5)
  116.  
  117.  
  118.     def writable(self):
  119.         return False
  120.  
  121.     def readable(self):
  122.         return self.accepting
  123.  
  124.     def handle_accept(self):
  125.         try:
  126.             conn, addr = self.accept()
  127.             log.debug("Connected to client: %s:%d (%d)" % (addr[0], addr[1], self._fileno))
  128.         except socket.error:
  129.             log.error("Socket error on accept()")
  130.             return
  131.         except TypeError:
  132.             log.error("EWOULDBLOCK exception on accept()")
  133.             return
  134.         handler = hpssd_handler(conn, addr, self)
  135.  
  136.     def handle_close(self):
  137.         dispatcher.handle_close(self)
  138.  
  139.  
  140. class hpssd_handler(dispatcher):
  141.     def __init__(self, conn, addr, server):
  142.         dispatcher.__init__(self, sock=conn)
  143.         self.addr = addr
  144.         self.in_buffer = ''
  145.         self.out_buffer = ''
  146.         self.server = server
  147.         self.fields = {}
  148.         self.payload = ''
  149.         self.signal_exit = False
  150.         self.typ = ''
  151.         self.send_events = False 
  152.         self.username = ''
  153.  
  154.         # handlers for all the messages we expect to receive
  155.         self.handlers = {
  156.             # Request/Reply Messages
  157.             'setalerts'            : self.handle_setalerts,
  158.             'testemail'            : self.handle_test_email,
  159.             'queryhistory'         : self.handle_queryhistory,
  160.             'setvalue'             : self.handle_setvalue, # device cache
  161.             'getvalue'             : self.handle_getvalue, # device cache
  162.  
  163.             # Event Messages (no reply message)
  164.             'event'                : self.handle_event,
  165.             'registerguievent'     : self.handle_registerguievent, # register for events
  166.             'unregisterguievent'   : self.handle_unregisterguievent,
  167.             'exitevent'            : self.handle_exit,
  168.  
  169.             # Fax
  170.             # hpfax: -> hpssd
  171.             'hpfaxbegin'           : self.handle_hpfaxbegin,
  172.             'hpfaxdata'            : self.handle_hpfaxdata,
  173.             'hpfaxend'             : self.handle_hpfaxend,
  174.             # hp-sendfax -> hpssd
  175.             'faxgetdata'           : self.handle_faxgetdata,
  176.             'faxcheck'             : self.handle_faxcheck,
  177.  
  178.             # Misc
  179.             'unknown'              : self.handle_unknown,
  180.         }
  181.  
  182.  
  183.     def handle_read(self):
  184.         log.debug("Reading data on channel (%d)" % self._fileno)
  185.         self.in_buffer = self.recv(prop.max_message_read)
  186.  
  187.         if not self.in_buffer:
  188.             return False
  189.  
  190.         log.debug(repr(self.in_buffer))
  191.         remaining_msg = self.in_buffer
  192.  
  193.         while True:
  194.             try:
  195.                 self.fields, self.payload, remaining_msg = parseMessage(remaining_msg)
  196.             except Error, e:
  197.                 err = e.opt
  198.                 log.warn("Message parsing error: %s (%d)" % (e.msg, err))
  199.                 self.out_buffer = self.handle_unknown(err)
  200.                 log.debug(self.out_buffer)
  201.                 return True
  202.  
  203.             msg_type = self.fields.get('msg', 'unknown').lower()
  204.             log.debug("Handling: %s %s %s" % ("*"*20, msg_type, "*"*20))
  205.             log.debug(repr(self.in_buffer))
  206.  
  207.             try:
  208.                 self.handlers.get(msg_type, self.handle_unknown)()
  209.             except Error:
  210.                 log.error("Unhandled exception during processing:")
  211.                 log.exception()
  212.  
  213.             try:
  214.                 self.handle_write()
  215.             except socket.error, why:
  216.                 log.error("Socket error: %s" % why)
  217.  
  218.             if not remaining_msg:
  219.                 break
  220.  
  221.         return True
  222.  
  223.     def handle_unknown(self, err=ERROR_INVALID_MSG_TYPE):
  224.         pass
  225.  
  226.  
  227.     def handle_write(self):
  228.         if not self.out_buffer:
  229.             return
  230.  
  231.         log.debug("Sending data on channel (%d)" % self._fileno)
  232.         log.debug(repr(self.out_buffer))
  233.  
  234.         while self.out_buffer:
  235.             sent = self.send(self.out_buffer)
  236.             self.out_buffer = self.out_buffer[sent:]
  237.  
  238.         if self.signal_exit:
  239.             self.handle_close()
  240.  
  241.  
  242.     def __checkdevice(self, device_uri):
  243.         try:
  244.             devices[device_uri]
  245.         except KeyError:
  246.             log.debug("New device: %s" % device_uri)
  247.             try:
  248.                 back_end, is_hp, bus, model, serial, dev_file, host, port = \
  249.                     device.parseDeviceURI(device_uri)
  250.             except Error:
  251.                 log.error("Invalid device URI")
  252.                 return ERROR_INVALID_DEVICE_URI
  253.  
  254.             devices[device_uri] = ServerDevice(model)
  255.  
  256.         return ERROR_SUCCESS
  257.  
  258.  
  259.     def handle_getvalue(self):
  260.         device_uri = self.fields.get('device-uri', '').replace('hpfax:', 'hp:')
  261.         value = ''
  262.         key = self.fields.get('key', '')
  263.         result_code = self.__checkdevice(device_uri)
  264.  
  265.         if result_code == ERROR_SUCCESS:
  266.             try:
  267.                 value = devices[device_uri].cache[key]
  268.             except KeyError:
  269.                 value, result_code = '', ERROR_INTERNAL
  270.  
  271.         self.out_buffer = buildResultMessage('GetValueResult', value, result_code)
  272.  
  273.     def handle_setvalue(self):
  274.         device_uri = self.fields.get('device-uri', '').replace('hpfax:', 'hp:')
  275.         key = self.fields.get('key', '')
  276.         value = self.fields.get('value', '')
  277.         result_code = self.__checkdevice(device_uri)
  278.  
  279.         if result_code == ERROR_SUCCESS:    
  280.             devices[device_uri].cache[key] = value
  281.  
  282.         self.out_buffer = buildResultMessage('SetValueResult', None, ERROR_SUCCESS)
  283.  
  284.     def handle_queryhistory(self):
  285.         device_uri = self.fields.get('device-uri', '').replace('hpfax:', 'hp:')
  286.         payload = ''
  287.         result_code = self.__checkdevice(device_uri)
  288.  
  289.         if result_code == ERROR_SUCCESS:    
  290.             for h in devices[device_uri].history.get():
  291.                 payload = '\n'.join([payload, ','.join([str(x) for x in h])])
  292.  
  293.         self.out_buffer = buildResultMessage('QueryHistoryResult', payload, result_code)
  294.  
  295.     # TODO: Need to load alerts at start-up
  296.     def handle_setalerts(self):
  297.         result_code = ERROR_SUCCESS
  298.         username = self.fields.get('username', '')
  299.  
  300.         alerts[username] = {'email-alerts'       : utils.to_bool(self.fields.get('email-alerts', '0')),
  301.                             'email-from-address' : self.fields.get('email-from-address', ''),
  302.                             'email-to-addresses' : self.fields.get('email-to-addresses', ''),
  303.                            }
  304.  
  305.         self.out_buffer = buildResultMessage('SetAlertsResult', None, result_code)
  306.  
  307.  
  308.     # EVENT
  309.     def handle_registerguievent(self):
  310.         username = self.fields.get('username', '')
  311.         typ = self.fields.get('type', 'unknown')
  312.         self.typ = typ
  313.         self.username = username
  314.         self.send_events = True
  315.         log.debug("Registering GUI for events: (%s, %s, %d)" % (username, typ, self._fileno))
  316.  
  317.     # EVENT
  318.     def handle_unregisterguievent(self):
  319.         username = self.fields.get('username', '')
  320.         self.send_events = False
  321.  
  322.  
  323.     def handle_test_email(self):
  324.         result_code = ERROR_SUCCESS
  325.         username = self.fields.get('username', prop.username)
  326.         message = device.queryString('email_test_message')
  327.         subject = device.queryString('email_test_subject')
  328.         result_code = self.sendEmail(username, subject, message, True)
  329.         self.out_buffer = buildResultMessage('TestEmailResult', None, result_code)
  330.  
  331.     def createHistory(self, device_uri, code, jobid=0, username=prop.username):
  332.         result_code = self.__checkdevice(device_uri)
  333.  
  334.         if result_code == ERROR_SUCCESS:    
  335.             history = devices[device_uri].history.get()
  336.             
  337.             if history and history[-1][11] == code:
  338.                 devices[device_uri].history.replace(tuple(time.localtime()) +
  339.                                                 (jobid, username, code))
  340.                 return True
  341.             else:
  342.                 devices[device_uri].history.append(tuple(time.localtime()) +
  343.                                                     (jobid, username, code))
  344.                 return False
  345.  
  346.     # sent by hpfax: to indicate the start of a complete fax rendering job
  347.     def handle_hpfaxbegin(self):
  348.         username = self.fields.get('username', prop.username)
  349.         job_id = self.fields.get('job-id', 0)
  350.         printer_name = self.fields.get('printer', '')
  351.         device_uri = self.fields.get('device-uri', '').replace('hp:', 'hpfax:')
  352.         title = self.fields.get('title', '')
  353.  
  354.         log.debug("Creating data store for %s:%d" % (username, job_id))
  355.         fax_file[(username, job_id)] = tempfile.NamedTemporaryFile(prefix="hpfax")
  356.         fax_file_ready[(username, job_id)] = False
  357.         fax_meta_data[(username, job_id)] = {'username': username, 'job-id': job_id, 'title': title, 'printer': printer_name, 'device-uri': device_uri, 'size': 0}
  358.  
  359.         log.debug("Fax job %d for user %s stored in temp file %s." % (job_id, username, fax_file[(username, job_id)].name))
  360.         self.out_buffer = buildResultMessage('HPFaxBeginResult', None, ERROR_SUCCESS)
  361.  
  362.  
  363.     # sent by hpfax: to transfer completed fax rendering data
  364.     def handle_hpfaxdata(self):
  365.         username = self.fields.get('username', prop.username)
  366.         job_id = self.fields.get('job-id', 0)
  367.  
  368.         if self.payload and (username, job_id) in fax_file and \
  369.             not fax_file_ready[(username, job_id)]:
  370.  
  371.             fax_file[(username, job_id)].write(self.payload)
  372.  
  373.         self.out_buffer = buildResultMessage('HPFaxDataResult', None, ERROR_SUCCESS)
  374.  
  375.  
  376.     # sent by hpfax: to indicate the end of a complete fax rendering job
  377.     def handle_hpfaxend(self):
  378.         username = self.fields.get('username', '')
  379.         job_id = self.fields.get('job-id', 0)
  380.         printer_name = self.fields.get('printer', '')
  381.         device_uri = self.fields.get('device-uri', '').replace('hp:', 'hpfax:')
  382.         title = self.fields.get('title', '')
  383.         job_size = self.fields.get('job-size', 0)
  384.  
  385.         fax_file[(username, job_id)].seek(0)
  386.         fax_file_ready[(username, job_id)] = True
  387.         fax_meta_data[(username, job_id)]['job-size'] = job_size
  388.  
  389.         self.out_buffer = buildResultMessage('HPFaxEndResult', None, ERROR_SUCCESS)
  390.  
  391.  
  392.     # sent by hp-sendfax to see if any faxes have been printed and need to be picked up
  393.     def handle_faxcheck(self):
  394.         username = self.fields.get('username', '')
  395.         result_code = ERROR_NO_DATA_AVAILABLE
  396.         other_fields = {}
  397.  
  398.         for f in fax_file:
  399.             user, job_id = f
  400.  
  401.             if user == username:
  402.                 other_fields = fax_meta_data[(username, job_id)]
  403.  
  404.                 if fax_file_ready[f]:
  405.                     result_code = ERROR_FAX_READY
  406.                 else:
  407.                     result_code = ERROR_FAX_PROCESSING
  408.  
  409.                 break
  410.  
  411.         self.out_buffer = buildResultMessage('FaxCheckResult', None, result_code, other_fields)
  412.  
  413.     # sent by hp-sendfax to retrieve a complete fax rendering job
  414.     # sent in response to the EVENT_FAX_RENDER_COMPLETE event or
  415.     # after being run with --job param, both after a hpfaxend message
  416.     def handle_faxgetdata(self):
  417.         result_code = ERROR_SUCCESS
  418.         username = self.fields.get('username', '')
  419.         job_id = self.fields.get('job-id', 0)
  420.  
  421.         try:
  422.             fax_file[(username, job_id)]
  423.  
  424.         except KeyError:
  425.             result_code, data = ERROR_NO_DATA_AVAILABLE, ''
  426.  
  427.         else:
  428.             if fax_file_ready[(username, job_id)]:
  429.                 data = fax_file[(username, job_id)].read(prop.max_message_len)
  430.  
  431.                 if not data:
  432.                     result_code = ERROR_NO_DATA_AVAILABLE
  433.                     log.debug("Deleting data store for %s:%d" % (username, job_id))
  434.                     del fax_file[(username, job_id)]
  435.                     del fax_file_ready[(username, job_id)]
  436.                     del fax_meta_data[(username, job_id)]
  437.  
  438.             else:
  439.                 result_code, data = ERROR_NO_DATA_AVAILABLE, ''
  440.  
  441.         self.out_buffer = buildResultMessage('FaxGetDataResult', data, result_code)
  442.  
  443.  
  444.     # EVENT
  445.     def handle_event(self):
  446.         gui_port, gui_host = None, None
  447.         event_type = self.fields.get('event-type', 'event')
  448.         event_code = self.fields.get('event-code', 0)
  449.         device_uri = self.fields.get('device-uri', '').replace('hpfax:', 'hp:')
  450.         log.debug("Device URI: %s" % device_uri)
  451.  
  452.         error_string_short = device.queryString(str(event_code), 0)
  453.         error_string_long = device.queryString(str(event_code), 1)
  454.  
  455.         log.debug("Short/Long: %s/%s" % (error_string_short, error_string_long))
  456.  
  457.         job_id = self.fields.get('job-id', 0)
  458.  
  459.         try:
  460.             username = self.fields['username']
  461.         except KeyError:
  462.             if job_id == 0:
  463.                 username = prop.username
  464.             else:
  465.                 jobs = cups.getAllJobs()
  466.                 for j in jobs:
  467.                     if j.id == job_id:
  468.                         username = j.user
  469.                         break
  470.                 else:
  471.                     username = prop.username
  472.  
  473.  
  474.         no_fwd = utils.to_bool(self.fields.get('no-fwd', '0'))
  475.         log.debug("Username (jobid): %s (%d)" % (username, job_id))
  476.         retry_timeout = self.fields.get('retry-timeout', 0)
  477.         user_alerts = alerts.get(username, {})        
  478.  
  479.         dup_event = False
  480.         if event_code <= EVENT_MAX_USER_EVENT:
  481.             dup_event = self.createHistory(device_uri, event_code, job_id, username)
  482.  
  483.         if not no_fwd:
  484.             if event_code <= EVENT_MAX_USER_EVENT and \
  485.                 user_alerts.get('email-alerts', False) and \
  486.                 event_type == 'error' and \
  487.                 not dup_event:
  488.  
  489.                 subject = device.queryString('email_alert_subject') + device_uri
  490.  
  491.                 message = '\n'.join([device_uri, 
  492.                                      time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()),
  493.                                      error_string_short, 
  494.                                      error_string_long,
  495.                                      str(event_code)])
  496.  
  497.                 self.sendEmail(username, subject, message, False)
  498.  
  499.  
  500.     def sendEmail(self, username, subject, message, wait):
  501.         msg = cStringIO.StringIO()
  502.         result_code = ERROR_SUCCESS
  503.  
  504.         user_alerts = alerts.get(username, {}) 
  505.         from_address = user_alerts.get('email-from-address', '')
  506.         to_addresses = user_alerts.get('email-to-addresses', from_address)
  507.  
  508.         t = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
  509.         UUID = file("/proc/sys/kernel/random/uuid").readline().rstrip("\n")
  510.  
  511.         msg.write("Date: %s\n" % t)
  512.         msg.write("From: <%s>\n" % from_address)
  513.         msg.write("To: %s\n" % to_addresses)
  514.         msg.write("Message-Id: <%s %s>\n" % (UUID, t))
  515.         msg.write('Content-Type: text/plain\n')
  516.         msg.write("Content-Transfer-Encoding: 7bit\n")
  517.         msg.write('Mime-Version: 1.0\n')
  518.         msg.write("Subject: %s\n" % subject)
  519.         msg.write('\n')
  520.         msg.write(message)
  521.         #msg.write('\n')
  522.         email_message = msg.getvalue()
  523.         log.debug(repr(email_message))
  524.  
  525.         mt = MailThread(email_message, from_address)
  526.         mt.start()
  527.  
  528.         if wait:
  529.             mt.join() # wait for thread to finish
  530.             result_code = mt.result
  531.  
  532.         return result_code
  533.  
  534.  
  535.     # EVENT
  536.     def handle_exit(self):
  537.         self.signal_exit = True
  538.  
  539.     def handle_messageerror(self):
  540.         pass
  541.  
  542.     def writable(self):
  543.         return not (not self.out_buffer and self.connected)
  544.  
  545.  
  546.     def handle_close(self):
  547.         log.debug("Closing channel (%d)" % self._fileno)
  548.         self.connected = False
  549.         self.close()
  550.  
  551.  
  552. class MailThread(threading.Thread):
  553.     def __init__(self, message, from_address):
  554.         threading.Thread.__init__(self)
  555.         self.message = message
  556.         self.from_address = from_address
  557.         self.result = ERROR_SUCCESS
  558.  
  559.     def run(self):
  560.         log.debug("Starting Mail Thread...")
  561.         sendmail = utils.which('sendmail')
  562.  
  563.         if sendmail:
  564.             sendmail = os.path.join(sendmail, 'sendmail')
  565.             sendmail += ' -t -r %s' % self.from_address
  566.  
  567.             log.debug(sendmail)
  568.             std_out, std_in, std_err = popen2.popen3(sendmail) 
  569.             log.debug(repr(self.message))
  570.             std_in.write(self.message)
  571.             std_in.close()
  572.  
  573.             r, w, e = select.select([std_err], [], [], 2.0)
  574.  
  575.             if r:
  576.                 err = std_err.read()
  577.                 if err:
  578.                     log.error(repr(err))
  579.                     self.result = ERROR_TEST_EMAIL_FAILED
  580.  
  581.         else:
  582.             log.error("Mail send failed. sendmail not found.")
  583.             self.result = ERROR_TEST_EMAIL_FAILED
  584.  
  585.         log.debug("Exiting mail thread")
  586.  
  587.  
  588. def reInit():
  589.     pass
  590.  
  591.  
  592. def handleSIGHUP(signo, frame):
  593.     log.info("SIGHUP")
  594.     reInit()
  595.  
  596.  
  597. def exitAllGUIs():
  598.     pass
  599.  
  600.  
  601. USAGE = [(__doc__, "", "name", True),
  602.          ("Usage: hpssd.py [OPTIONS]", "", "summary", True),
  603.          utils.USAGE_OPTIONS,
  604.          ("Do not daemonize:", "-x", "option", False),
  605.          ("Port to listen on:", "-p<port> or --port=<port> (overrides value in /etc/hp/hplip.conf)", "option", False),
  606.          utils.USAGE_LOGGING1, utils.USAGE_LOGGING2,
  607.          ("Run in debug mode:", "-g (same as options: -ldebug -x)", "option", False),
  608.          utils.USAGE_HELP,
  609.         ]
  610.  
  611.  
  612. def usage(typ='text'):
  613.     if typ == 'text':
  614.         utils.log_title(__title__, __version__)
  615.  
  616.     utils.format_text(USAGE, typ, __title__, 'hpssd.py', __version__)
  617.     sys.exit(0)
  618.  
  619.  
  620.  
  621. def main(args):
  622.     log.set_module('hpssd')
  623.  
  624.     prop.prog = sys.argv[0]
  625.     prop.daemonize = True
  626.  
  627.     try:
  628.         opts, args = getopt.getopt(sys.argv[1:], 'l:xhp:g', 
  629.             ['level=', 'help', 'help-man', 'help-rest', 'port=', 'help-desc'])
  630.  
  631.     except getopt.GetoptError:
  632.         usage()
  633.  
  634.     if os.getenv("HPLIP_DEBUG"):
  635.         log.set_level('debug')
  636.  
  637.     for o, a in opts:
  638.         if o in ('-l', '--logging'):
  639.             log_level = a.lower().strip()
  640.             if not log.set_level(log_level):
  641.                 usage()
  642.  
  643.         elif o == '-g':
  644.             log.set_level('debug')
  645.             prop.daemonize = False
  646.  
  647.         elif o in ('-x',):
  648.             prop.daemonize = False
  649.  
  650.         elif o in ('-h', '--help'):
  651.             usage()
  652.  
  653.         elif o == '--help-rest':
  654.             usage('rest')
  655.  
  656.         elif o == '--help-man':
  657.             usage('man')
  658.  
  659.         elif o == '--help-desc':
  660.             print __doc__,
  661.             sys.exit(0)
  662.  
  663.         elif o in ('-p', '--port'):
  664.             try:
  665.                 prop.hpssd_cfg_port = int(a)
  666.             except ValueError:
  667.                 log.error('Port must be a numeric value')
  668.                 usage()
  669.  
  670.  
  671.     utils.log_title(__title__, __version__)
  672.  
  673.     prop.history_size = 32
  674.  
  675.     # Lock pidfile before we muck around with system state
  676.     # Patch by Henrique M. Holschuh <hmh@debian.org>
  677.     utils.get_pidfile_lock(os.path.join(prop.run_dir, 'hpssd.pid'))
  678.  
  679.     # Spawn child right away so that boot up sequence
  680.     # is as fast as possible
  681.     if prop.daemonize:
  682.         utils.daemonize()
  683.  
  684.     reInit()
  685.  
  686.     # hpssd server dispatcher object
  687.     try:
  688.         server = hpssd_server(prop.hpssd_host, prop.hpssd_cfg_port)
  689.     except Error, e:
  690.         log.error("Server exited with error: %s" % e.msg)
  691.         sys.exit(1)
  692.  
  693.     os.umask(0133)
  694.     file(os.path.join(prop.run_dir, 'hpssd.port'), 'w').write('%d\n' % prop.hpssd_port)
  695.     os.umask (0077)
  696.     log.debug('port=%d' % prop.hpssd_port)
  697.     log.info("Listening on %s:%d" % (prop.hpssd_host, prop.hpssd_port))
  698.  
  699.     signal.signal(signal.SIGHUP, handleSIGHUP)
  700.  
  701.     try:
  702.         log.debug("Starting async loop...")
  703.         try:
  704.             loop(timeout=5.0)
  705.         except KeyboardInterrupt:
  706.             log.warn("Ctrl-C hit, exiting...")
  707.         except Exception:
  708.             log.exception()
  709.  
  710.         log.debug("Cleaning up...")
  711.     finally:
  712.         os.remove(os.path.join(prop.run_dir, 'hpssd.pid'))
  713.         os.remove(os.path.join(prop.run_dir, 'hpssd.port'))
  714.         server.close()
  715.         return 0
  716.  
  717. if __name__ == "__main__":
  718.     sys.exit(main(sys.argv[1:]))
  719.  
  720.  
  721.