Version bump for release.
[irker.git] / irkerd
diff --git a/irkerd b/irkerd
index 790a2560add04ea0cc0e9b1717b6e86b34962b06..d9505b378ae1bfa0ce7c48f15b5b8f848ae9cf5b 100755 (executable)
--- a/irkerd
+++ b/irkerd
@@ -40,11 +40,13 @@ CONNECTION_MAX = 200                # To avoid hitting a thread limit
 
 # No user-serviceable parts below this line
 
-version = "2.7"
+version = "2.9"
 
 import argparse
 import logging
+import logging.handlers
 import json
+import os
 try:  # Python 3
     import queue
 except ImportError:  # Python 2
@@ -112,7 +114,7 @@ except NameError:  # Python 3
 # same problem - there is little point in reliable delivery to a relay
 # that is down or unreliable.
 #
-# This code uses only NICK, JOIN, PART, MODE, PRIVMSG, USER, and QUIT. 
+# This code uses only NICK, JOIN, PART, MODE, PRIVMSG, USER, and QUIT.
 # It is strictly compliant to RFC1459, except for the interpretation and
 # use of the DEAF and CHANLIMIT and (obsolete) MAXCHANNELS features.
 #
@@ -132,7 +134,7 @@ class IRCError(Exception):
     pass
 
 
-class InvalidRequest (ValueError):
+class InvalidRequest(ValueError):
     "An invalid JSON request"
     pass
 
@@ -231,13 +233,13 @@ class IRCServerConnection():
         self.master = master
         self.socket = None
 
-    def _wrap_socket(self, socket, target, cafile=None,
+    def _wrap_socket(self, socket, target, certfile=None, cafile=None,
                      protocol=ssl.PROTOCOL_TLSv1):
         try:  # Python 3.2 and greater
             ssl_context = ssl.SSLContext(protocol)
         except AttributeError:  # Python < 3.2
             self.socket = ssl.wrap_socket(
-                socket, cert_reqs=ssl.CERT_REQUIRED,
+                socket, certfile=certfile, cert_reqs=ssl.CERT_REQUIRED,
                 ssl_version=protocol, ca_certs=cafile)
         else:
             ssl_context.verify_mode = ssl.CERT_REQUIRED
@@ -454,7 +456,7 @@ class Connection:
         if n is None:
             n = self.nick_trial
         if self.nick_needs_number:
-            return (self.nick_template % n)
+            return self.nick_template % n
         else:
             return self.nick_template
     def handle_ping(self):
@@ -738,7 +740,7 @@ class Dispatcher:
                 if age < time.time() - CHANNEL_TTL:
                     ancients.append((connection, chan, age))
         if ancients:
-            ancients.sort(key=lambda x: x[2]) 
+            ancients.sort(key=lambda x: x[2])
             (found_connection, drop_channel, _drop_age) = ancients[0]
             found_connection.part(drop_channel, "scavenged by irkerd")
             del found_connection.channels_joined[drop_channel]
@@ -807,7 +809,7 @@ class Irker:
                     m = int(lump[12:])
                     for pref in "#&+":
                         cxt.channel_limits[pref] = m
-                    LOG.info("%s maxchannels is %d" % (connection.server, m))
+                    LOG.info("%s maxchannels is %d" % (connection.target, m))
                 elif lump.startswith("CHANLIMIT=#:"):
                     limits = lump[10:].split(",")
                     try:
@@ -933,6 +935,12 @@ class IrkerUDPHandler(socketserver.BaseRequestHandler):
             line = UNICODE_TYPE(line, 'utf-8')
         irker.handle(line=line.strip())
 
+def in_background():
+    "Is this process running in background?"
+    try:
+        return os.getpgrp() != os.tcgetpgrp(1)
+    except OSError:
+        return True
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser(
@@ -940,9 +948,15 @@ if __name__ == '__main__':
     parser.add_argument(
         '-c', '--ca-file', metavar='PATH',
         help='file of trusted certificates for SSL/TLS')
+    parser.add_argument(
+        '-e', '--cert-file', metavar='PATH',
+        help='pem file used to authenticate to the server')
     parser.add_argument(
         '-d', '--log-level', metavar='LEVEL', choices=LOG_LEVELS,
-        help='file of trusted certificates for SSL/TLS')
+        help='how much to log to the log file (one of %(choices)s)')
+    parser.add_argument(
+        '-H', '--host', metavar='ADDRESS', default=HOST,
+        help='IP address to listen on')
     parser.add_argument(
         '-l', '--log-file', metavar='PATH',
         help='file for saving captured message traffic')
@@ -965,7 +979,12 @@ if __name__ == '__main__':
         help='message for --immediate mode')
     args = parser.parse_args()
 
-    handler = logging.StreamHandler()
+    if not args.log_file and in_background():
+        handler = logging.handlers.SysLogHandler(address='/dev/log',
+                                                 facility='daemon')
+    else:
+        handler = logging.StreamHandler()
+
     LOG.addHandler(handler)
     if args.log_level:
         log_level = getattr(logging, args.log_level.upper())
@@ -977,6 +996,7 @@ if __name__ == '__main__':
         nick_needs_number=re.search('%.*d', args.nick),
         password=args.password,
         cafile=args.ca_file,
+        certfile=args.cert_file,
         )
     LOG.info("irkerd version %s" % version)
     if args.immediate:
@@ -997,8 +1017,8 @@ if __name__ == '__main__':
             raise SystemExit(1)
         irker.thread_launch()
         try:
-            tcpserver = socketserver.TCPServer((HOST, PORT), IrkerTCPHandler)
-            udpserver = socketserver.UDPServer((HOST, PORT), IrkerUDPHandler)
+            tcpserver = socketserver.TCPServer((args.host, PORT), IrkerTCPHandler)
+            udpserver = socketserver.UDPServer((args.host, PORT), IrkerUDPHandler)
             for server in [tcpserver, udpserver]:
                 server = threading.Thread(target=server.serve_forever)
                 server.setDaemon(True)