Commit 58435909 authored by 's avatar

untabify

parent f4a65b80
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
# Id: asyncore.py,v 2.49 2000/05/04 06:06:04 jim Exp # Id: asyncore.py,v 2.49 2000/05/04 06:06:04 jim Exp
# $Id: asyncore.py,v 1.9 2000/05/05 17:28:57 jim Exp $ # $Id: asyncore.py,v 1.10 2000/05/12 19:43:07 brian Exp $
# Author: Sam Rushing <rushing@nightmare.com> # Author: Sam Rushing <rushing@nightmare.com>
# ====================================================================== # ======================================================================
# Copyright 1996 by Sam Rushing # Copyright 1996 by Sam Rushing
...@@ -34,347 +34,347 @@ import sys ...@@ -34,347 +34,347 @@ import sys
import os import os
if os.name == 'nt': if os.name == 'nt':
EWOULDBLOCK = 10035 EWOULDBLOCK = 10035
EINPROGRESS = 10036 EINPROGRESS = 10036
EALREADY = 10037 EALREADY = 10037
ECONNRESET = 10054 ECONNRESET = 10054
ENOTCONN = 10057 ENOTCONN = 10057
ESHUTDOWN = 10058 ESHUTDOWN = 10058
else: else:
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN
try: try:
socket_map socket_map
except NameError: except NameError:
socket_map = {} socket_map = {}
class ExitNow (exceptions.Exception): class ExitNow (exceptions.Exception):
pass pass
DEBUG = 0 DEBUG = 0
def poll (timeout=0.0, map=None): def poll (timeout=0.0, map=None):
global DEBUG global DEBUG
if map is None: if map is None:
map = socket_map map = socket_map
if map: if map:
r = []; w = []; e = [] r = []; w = []; e = []
for fd, obj in map.items(): for fd, obj in map.items():
if obj.readable(): if obj.readable():
r.append (fd) r.append (fd)
if obj.writable(): if obj.writable():
w.append (fd) w.append (fd)
r,w,e = select.select (r,w,e, timeout) r,w,e = select.select (r,w,e, timeout)
if DEBUG: if DEBUG:
print r,w,e print r,w,e
for fd in r: for fd in r:
try: try:
obj = map[fd] obj = map[fd]
try: try:
obj.handle_read_event() obj.handle_read_event()
except ExitNow: except ExitNow:
raise ExitNow raise ExitNow
except: except:
obj.handle_error() obj.handle_error()
except KeyError: except KeyError:
pass pass
for fd in w: for fd in w:
try: try:
obj = map[fd] obj = map[fd]
try: try:
obj.handle_write_event() obj.handle_write_event()
except ExitNow: except ExitNow:
raise ExitNow raise ExitNow
except: except:
obj.handle_error() obj.handle_error()
except KeyError: except KeyError:
pass pass
def poll2 (timeout=0.0, map=None): def poll2 (timeout=0.0, map=None):
import poll import poll
if map is None: if map is None:
map=socket_map map=socket_map
# timeout is in milliseconds # timeout is in milliseconds
timeout = int(timeout*1000) timeout = int(timeout*1000)
if map: if map:
l = [] l = []
for fd, obj in map.items(): for fd, obj in map.items():
flags = 0 flags = 0
if obj.readable(): if obj.readable():
flags = poll.POLLIN flags = poll.POLLIN
if obj.writable(): if obj.writable():
flags = flags | poll.POLLOUT flags = flags | poll.POLLOUT
if flags: if flags:
l.append ((fd, flags)) l.append ((fd, flags))
r = poll.poll (l, timeout) r = poll.poll (l, timeout)
for fd, flags in r: for fd, flags in r:
try: try:
obj = map[fd] obj = map[fd]
try: try:
if (flags & poll.POLLIN): if (flags & poll.POLLIN):
obj.handle_read_event() obj.handle_read_event()
if (flags & poll.POLLOUT): if (flags & poll.POLLOUT):
obj.handle_write_event() obj.handle_write_event()
except ExitNow: except ExitNow:
raise ExitNow raise ExitNow
except: except:
obj.handle_error() obj.handle_error()
except KeyError: except KeyError:
pass pass
def loop (timeout=30.0, use_poll=0, map=None): def loop (timeout=30.0, use_poll=0, map=None):
if use_poll: if use_poll:
poll_fun = poll2 poll_fun = poll2
else: else:
poll_fun = poll poll_fun = poll
if map is None: if map is None:
map=socket_map map=socket_map
while map: while map:
poll_fun (timeout, map) poll_fun (timeout, map)
class dispatcher: class dispatcher:
debug = 0 debug = 0
connected = 0 connected = 0
accepting = 0 accepting = 0
closing = 0 closing = 0
addr = None addr = None
def __init__ (self, sock=None, map=None): def __init__ (self, sock=None, map=None):
if sock: if sock:
self.set_socket (sock, map) self.set_socket (sock, map)
# I think it should inherit this anyway # I think it should inherit this anyway
self.socket.setblocking (0) self.socket.setblocking (0)
self.connected = 1 self.connected = 1
def __repr__ (self): def __repr__ (self):
try: try:
status = [] status = []
if self.accepting and self.addr: if self.accepting and self.addr:
status.append ('listening') status.append ('listening')
elif self.connected: elif self.connected:
status.append ('connected') status.append ('connected')
if self.addr: if self.addr:
status.append ('%s:%d' % self.addr) status.append ('%s:%d' % self.addr)
return '<%s %s at %x>' % ( return '<%s %s at %x>' % (
self.__class__.__name__, self.__class__.__name__,
string.join (status, ' '), string.join (status, ' '),
id(self) id(self)
) )
except: except:
try: try:
ar = repr(self.addr) ar = repr(self.addr)
except: except:
ar = 'no self.addr!' ar = 'no self.addr!'
return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar) return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar)
def add_channel (self, map=None): def add_channel (self, map=None):
#self.log_info ('adding channel %s' % self) #self.log_info ('adding channel %s' % self)
if map is None: if map is None:
map=socket_map map=socket_map
map [self._fileno] = self map [self._fileno] = self
def del_channel (self, map=None): def del_channel (self, map=None):
fd = self._fileno fd = self._fileno
if map is None: if map is None:
map=socket_map map=socket_map
if map.has_key (fd): if map.has_key (fd):
#self.log_info ('closing channel %d:%s' % (fd, self)) #self.log_info ('closing channel %d:%s' % (fd, self))
del map [fd] del map [fd]
def create_socket (self, family, type): def create_socket (self, family, type):
self.family_and_type = family, type self.family_and_type = family, type
self.socket = socket.socket (family, type) self.socket = socket.socket (family, type)
self.socket.setblocking(0) self.socket.setblocking(0)
self._fileno = self.socket.fileno() self._fileno = self.socket.fileno()
self.add_channel() self.add_channel()
def set_socket (self, sock, map=None): def set_socket (self, sock, map=None):
self.__dict__['socket'] = sock self.__dict__['socket'] = sock
self._fileno = sock.fileno() self._fileno = sock.fileno()
self.add_channel (map) self.add_channel (map)
def set_reuse_addr (self): def set_reuse_addr (self):
# try to re-use a server port if possible # try to re-use a server port if possible
try: try:
self.socket.setsockopt ( self.socket.setsockopt (
socket.SOL_SOCKET, socket.SO_REUSEADDR, socket.SOL_SOCKET, socket.SO_REUSEADDR,
self.socket.getsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1 self.socket.getsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1
) )
except: except:
pass pass
# ================================================== # ==================================================
# predicates for select() # predicates for select()
# these are used as filters for the lists of sockets # these are used as filters for the lists of sockets
# to pass to select(). # to pass to select().
# ================================================== # ==================================================
def readable (self): def readable (self):
return 1 return 1
if os.name == 'mac': if os.name == 'mac':
# The macintosh will select a listening socket for # The macintosh will select a listening socket for
# write if you let it. What might this mean? # write if you let it. What might this mean?
def writable (self): def writable (self):
return not self.accepting return not self.accepting
else: else:
def writable (self): def writable (self):
return 1 return 1
# ================================================== # ==================================================
# socket object methods. # socket object methods.
# ================================================== # ==================================================
def listen (self, num): def listen (self, num):
self.accepting = 1 self.accepting = 1
if os.name == 'nt' and num > 5: if os.name == 'nt' and num > 5:
num = 1 num = 1
return self.socket.listen (num) return self.socket.listen (num)
def bind (self, addr): def bind (self, addr):
self.addr = addr self.addr = addr
return self.socket.bind (addr) return self.socket.bind (addr)
def connect (self, address): def connect (self, address):
self.connected = 0 self.connected = 0
try: try:
self.socket.connect (address) self.socket.connect (address)
except socket.error, why: except socket.error, why:
if why[0] in (EINPROGRESS, EALREADY, EWOULDBLOCK): if why[0] in (EINPROGRESS, EALREADY, EWOULDBLOCK):
return return
else: else:
raise socket.error, why raise socket.error, why
self.connected = 1 self.connected = 1
self.handle_connect() self.handle_connect()
def accept (self): def accept (self):
try: try:
conn, addr = self.socket.accept() conn, addr = self.socket.accept()
return conn, addr return conn, addr
except socket.error, why: except socket.error, why:
if why[0] == EWOULDBLOCK: if why[0] == EWOULDBLOCK:
pass pass
else: else:
raise socket.error, why raise socket.error, why
def send (self, data): def send (self, data):
try: try:
result = self.socket.send (data) result = self.socket.send (data)
return result return result
except socket.error, why: except socket.error, why:
if why[0] == EWOULDBLOCK: if why[0] == EWOULDBLOCK:
return 0 return 0
else: else:
raise socket.error, why raise socket.error, why
return 0 return 0
def recv (self, buffer_size): def recv (self, buffer_size):
try: try:
data = self.socket.recv (buffer_size) data = self.socket.recv (buffer_size)
if not data: if not data:
# a closed connection is indicated by signaling # a closed connection is indicated by signaling
# a read condition, and having recv() return 0. # a read condition, and having recv() return 0.
self.handle_close() self.handle_close()
return '' return ''
else: else:
return data return data
except socket.error, why: except socket.error, why:
# winsock sometimes throws ENOTCONN # winsock sometimes throws ENOTCONN
if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]: if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
self.handle_close() self.handle_close()
return '' return ''
else: else:
raise socket.error, why raise socket.error, why
def close (self): def close (self):
self.del_channel() self.del_channel()
self.socket.close() self.socket.close()
# cheap inheritance, used to pass all other attribute # cheap inheritance, used to pass all other attribute
# references to the underlying socket object. # references to the underlying socket object.
def __getattr__ (self, attr): def __getattr__ (self, attr):
return getattr (self.socket, attr) return getattr (self.socket, attr)
# log and log_info maybe overriden to provide more sophisitcated # log and log_info maybe overriden to provide more sophisitcated
# logging and warning methods. In general, log is for 'hit' logging # logging and warning methods. In general, log is for 'hit' logging
# and 'log_info' is for informational, warning and error logging. # and 'log_info' is for informational, warning and error logging.
def log (self, message): def log (self, message):
sys.stderr.write ('log: %s\n' % str(message)) sys.stderr.write ('log: %s\n' % str(message))
def log_info (self, message, type='info'): def log_info (self, message, type='info'):
if __debug__ or type != 'info': if __debug__ or type != 'info':
print '%s: %s' % (type, message) print '%s: %s' % (type, message)
def handle_read_event (self): def handle_read_event (self):
if self.accepting: if self.accepting:
# for an accepting socket, getting a read implies # for an accepting socket, getting a read implies
# that we are connected # that we are connected
if not self.connected: if not self.connected:
self.connected = 1 self.connected = 1
self.handle_accept() self.handle_accept()
elif not self.connected: elif not self.connected:
self.handle_connect() self.handle_connect()
self.connected = 1 self.connected = 1
self.handle_read() self.handle_read()
else: else:
self.handle_read() self.handle_read()
def handle_write_event (self): def handle_write_event (self):
# getting a write implies that we are connected # getting a write implies that we are connected
if not self.connected: if not self.connected:
self.handle_connect() self.handle_connect()
self.connected = 1 self.connected = 1
self.handle_write() self.handle_write()
def handle_expt_event (self): def handle_expt_event (self):
self.handle_expt() self.handle_expt()
def handle_error (self): def handle_error (self):
(file,fun,line), t, v, tbinfo = compact_traceback() (file,fun,line), t, v, tbinfo = compact_traceback()
# sometimes a user repr method will crash. # sometimes a user repr method will crash.
try: try:
self_repr = repr (self) self_repr = repr (self)
except: except:
self_repr = '<__repr__ (self) failed for object at %0x>' % id(self) self_repr = '<__repr__ (self) failed for object at %0x>' % id(self)
self.log_info ( self.log_info (
'uncaptured python exception, closing channel %s (%s:%s %s)' % ( 'uncaptured python exception, closing channel %s (%s:%s %s)' % (
self_repr, self_repr,
t, t,
v, v,
tbinfo tbinfo
), ),
'error' 'error'
) )
self.close() self.close()
def handle_expt (self): def handle_expt (self):
self.log_info ('unhandled exception', 'warning') self.log_info ('unhandled exception', 'warning')
def handle_read (self): def handle_read (self):
self.log_info ('unhandled read event', 'warning') self.log_info ('unhandled read event', 'warning')
def handle_write (self): def handle_write (self):
self.log_info ('unhandled write event', 'warning') self.log_info ('unhandled write event', 'warning')
def handle_connect (self): def handle_connect (self):
self.log_info ('unhandled connect event', 'warning') self.log_info ('unhandled connect event', 'warning')
def handle_accept (self): def handle_accept (self):
self.log_info ('unhandled accept event', 'warning') self.log_info ('unhandled accept event', 'warning')
def handle_close (self): def handle_close (self):
self.log_info ('unhandled close event', 'warning') self.log_info ('unhandled close event', 'warning')
self.close() self.close()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# adds simple buffered output capability, useful for simple clients. # adds simple buffered output capability, useful for simple clients.
...@@ -382,63 +382,63 @@ class dispatcher: ...@@ -382,63 +382,63 @@ class dispatcher:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class dispatcher_with_send (dispatcher): class dispatcher_with_send (dispatcher):
def __init__ (self, sock=None): def __init__ (self, sock=None):
dispatcher.__init__ (self, sock) dispatcher.__init__ (self, sock)
self.out_buffer = '' self.out_buffer = ''
def initiate_send (self): def initiate_send (self):
num_sent = 0 num_sent = 0
num_sent = dispatcher.send (self, self.out_buffer[:512]) num_sent = dispatcher.send (self, self.out_buffer[:512])
self.out_buffer = self.out_buffer[num_sent:] self.out_buffer = self.out_buffer[num_sent:]
def handle_write (self): def handle_write (self):
self.initiate_send() self.initiate_send()
def writable (self): def writable (self):
return (not self.connected) or len(self.out_buffer) return (not self.connected) or len(self.out_buffer)
def send (self, data): def send (self, data):
if self.debug: if self.debug:
self.log_info ('sending %s' % repr(data)) self.log_info ('sending %s' % repr(data))
self.out_buffer = self.out_buffer + data self.out_buffer = self.out_buffer + data
self.initiate_send() self.initiate_send()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# used for debugging. # used for debugging.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def compact_traceback (): def compact_traceback ():
t,v,tb = sys.exc_info() t,v,tb = sys.exc_info()
tbinfo = [] tbinfo = []
while 1: while 1:
tbinfo.append (( tbinfo.append ((
tb.tb_frame.f_code.co_filename, tb.tb_frame.f_code.co_filename,
tb.tb_frame.f_code.co_name, tb.tb_frame.f_code.co_name,
str(tb.tb_lineno) str(tb.tb_lineno)
)) ))
tb = tb.tb_next tb = tb.tb_next
if not tb: if not tb:
break break
# just to be safe # just to be safe
del tb del tb
file, function, line = tbinfo[-1] file, function, line = tbinfo[-1]
info = '[' + string.join ( info = '[' + string.join (
map ( map (
lambda x: string.join (x, '|'), lambda x: string.join (x, '|'),
tbinfo tbinfo
), ),
'] [' '] ['
) + ']' ) + ']'
return (file, function, line), t, v, info return (file, function, line), t, v, info
def close_all (map=None): def close_all (map=None):
if map is None: if map is None:
map=socket_map map=socket_map
for x in map.values(): for x in map.values():
x.socket.close() x.socket.close()
map.clear() map.clear()
# Asynchronous File I/O: # Asynchronous File I/O:
# #
...@@ -455,39 +455,39 @@ def close_all (map=None): ...@@ -455,39 +455,39 @@ def close_all (map=None):
import os import os
if os.name == 'posix': if os.name == 'posix':
import fcntl import fcntl
import FCNTL import FCNTL
class file_wrapper: class file_wrapper:
# here we override just enough to make a file # here we override just enough to make a file
# look like a socket for the purposes of asyncore. # look like a socket for the purposes of asyncore.
def __init__ (self, fd): def __init__ (self, fd):
self.fd = fd self.fd = fd
def recv (self, *args): def recv (self, *args):
return apply (os.read, (self.fd,)+args) return apply (os.read, (self.fd,)+args)
def write (self, *args): def write (self, *args):
return apply (os.write, (self.fd,)+args) return apply (os.write, (self.fd,)+args)
def close (self): def close (self):
return os.close (self.fd) return os.close (self.fd)
def fileno (self): def fileno (self):
return self.fd return self.fd
class file_dispatcher (dispatcher): class file_dispatcher (dispatcher):
def __init__ (self, fd): def __init__ (self, fd):
dispatcher.__init__ (self) dispatcher.__init__ (self)
self.connected = 1 self.connected = 1
# set it to non-blocking mode # set it to non-blocking mode
flags = fcntl.fcntl (fd, FCNTL.F_GETFL, 0) flags = fcntl.fcntl (fd, FCNTL.F_GETFL, 0)
flags = flags | FCNTL.O_NONBLOCK flags = flags | FCNTL.O_NONBLOCK
fcntl.fcntl (fd, FCNTL.F_SETFL, flags) fcntl.fcntl (fd, FCNTL.F_SETFL, flags)
self.set_file (fd) self.set_file (fd)
def set_file (self, fd): def set_file (self, fd):
self._fileno = fd self._fileno = fd
self.socket = file_wrapper (fd) self.socket = file_wrapper (fd)
self.add_channel() self.add_channel()
...@@ -68,144 +68,144 @@ Usage: ...@@ -68,144 +68,144 @@ Usage:
# #
# priorities (these are ordered) # priorities (these are ordered)
LOG_EMERG = 0 # system is unusable LOG_EMERG = 0 # system is unusable
LOG_ALERT = 1 # action must be taken immediately LOG_ALERT = 1 # action must be taken immediately
LOG_CRIT = 2 # critical conditions LOG_CRIT = 2 # critical conditions
LOG_ERR = 3 # error conditions LOG_ERR = 3 # error conditions
LOG_WARNING = 4 # warning conditions LOG_WARNING = 4 # warning conditions
LOG_NOTICE = 5 # normal but significant condition LOG_NOTICE = 5 # normal but significant condition
LOG_INFO = 6 # informational LOG_INFO = 6 # informational
LOG_DEBUG = 7 # debug-level messages LOG_DEBUG = 7 # debug-level messages
# facility codes # facility codes
LOG_KERN = 0 # kernel messages LOG_KERN = 0 # kernel messages
LOG_USER = 1 # random user-level messages LOG_USER = 1 # random user-level messages
LOG_MAIL = 2 # mail system LOG_MAIL = 2 # mail system
LOG_DAEMON = 3 # system daemons LOG_DAEMON = 3 # system daemons
LOG_AUTH = 4 # security/authorization messages LOG_AUTH = 4 # security/authorization messages
LOG_SYSLOG = 5 # messages generated internally by syslogd LOG_SYSLOG = 5 # messages generated internally by syslogd
LOG_LPR = 6 # line printer subsystem LOG_LPR = 6 # line printer subsystem
LOG_NEWS = 7 # network news subsystem LOG_NEWS = 7 # network news subsystem
LOG_UUCP = 8 # UUCP subsystem LOG_UUCP = 8 # UUCP subsystem
LOG_CRON = 9 # clock daemon LOG_CRON = 9 # clock daemon
LOG_AUTHPRIV = 10 # security/authorization messages (private) LOG_AUTHPRIV = 10 # security/authorization messages (private)
# other codes through 15 reserved for system use # other codes through 15 reserved for system use
LOG_LOCAL0 = 16 # reserved for local use LOG_LOCAL0 = 16 # reserved for local use
LOG_LOCAL1 = 17 # reserved for local use LOG_LOCAL1 = 17 # reserved for local use
LOG_LOCAL2 = 18 # reserved for local use LOG_LOCAL2 = 18 # reserved for local use
LOG_LOCAL3 = 19 # reserved for local use LOG_LOCAL3 = 19 # reserved for local use
LOG_LOCAL4 = 20 # reserved for local use LOG_LOCAL4 = 20 # reserved for local use
LOG_LOCAL5 = 21 # reserved for local use LOG_LOCAL5 = 21 # reserved for local use
LOG_LOCAL6 = 22 # reserved for local use LOG_LOCAL6 = 22 # reserved for local use
LOG_LOCAL7 = 23 # reserved for local use LOG_LOCAL7 = 23 # reserved for local use
priority_names = { priority_names = {
"alert": LOG_ALERT, "alert": LOG_ALERT,
"crit": LOG_CRIT, "crit": LOG_CRIT,
"debug": LOG_DEBUG, "debug": LOG_DEBUG,
"emerg": LOG_EMERG, "emerg": LOG_EMERG,
"err": LOG_ERR, "err": LOG_ERR,
"error": LOG_ERR, # DEPRECATED "error": LOG_ERR, # DEPRECATED
"info": LOG_INFO, "info": LOG_INFO,
"notice": LOG_NOTICE, "notice": LOG_NOTICE,
"panic": LOG_EMERG, # DEPRECATED "panic": LOG_EMERG, # DEPRECATED
"warn": LOG_WARNING, # DEPRECATED "warn": LOG_WARNING, # DEPRECATED
"warning": LOG_WARNING, "warning": LOG_WARNING,
} }
facility_names = { facility_names = {
"auth": LOG_AUTH, "auth": LOG_AUTH,
"authpriv": LOG_AUTHPRIV, "authpriv": LOG_AUTHPRIV,
"cron": LOG_CRON, "cron": LOG_CRON,
"daemon": LOG_DAEMON, "daemon": LOG_DAEMON,
"kern": LOG_KERN, "kern": LOG_KERN,
"lpr": LOG_LPR, "lpr": LOG_LPR,
"mail": LOG_MAIL, "mail": LOG_MAIL,
"news": LOG_NEWS, "news": LOG_NEWS,
"security": LOG_AUTH, # DEPRECATED "security": LOG_AUTH, # DEPRECATED
"syslog": LOG_SYSLOG, "syslog": LOG_SYSLOG,
"user": LOG_USER, "user": LOG_USER,
"uucp": LOG_UUCP, "uucp": LOG_UUCP,
"local0": LOG_LOCAL0, "local0": LOG_LOCAL0,
"local1": LOG_LOCAL1, "local1": LOG_LOCAL1,
"local2": LOG_LOCAL2, "local2": LOG_LOCAL2,
"local3": LOG_LOCAL3, "local3": LOG_LOCAL3,
"local4": LOG_LOCAL4, "local4": LOG_LOCAL4,
"local5": LOG_LOCAL5, "local5": LOG_LOCAL5,
"local6": LOG_LOCAL6, "local6": LOG_LOCAL6,
"local7": LOG_LOCAL7, "local7": LOG_LOCAL7,
} }
import socket import socket
class syslog_client: class syslog_client:
def __init__ (self, address='/dev/log'): def __init__ (self, address='/dev/log'):
self.address = address self.address = address
if type (address) == type(''): if type (address) == type(''):
try: # APUE 13.4.2 specifes /dev/log as datagram socket try: # APUE 13.4.2 specifes /dev/log as datagram socket
self.socket = socket.socket( socket.AF_UNIX self.socket = socket.socket( socket.AF_UNIX
, socket.SOCK_DGRAM) , socket.SOCK_DGRAM)
self.socket.connect (address) self.socket.connect (address)
except: # older linux may create as stream socket except: # older linux may create as stream socket
self.socket = socket.socket( socket.AF_UNIX self.socket = socket.socket( socket.AF_UNIX
, socket.SOCK_STREAM) , socket.SOCK_STREAM)
self.socket.connect (address) self.socket.connect (address)
self.unix = 1 self.unix = 1
else: else:
self.socket = socket.socket( socket.AF_INET self.socket = socket.socket( socket.AF_INET
, socket.SOCK_DGRAM) , socket.SOCK_DGRAM)
self.unix = 0 self.unix = 0
# curious: when talking to the unix-domain '/dev/log' socket, a # curious: when talking to the unix-domain '/dev/log' socket, a
# zero-terminator seems to be required. this string is placed # zero-terminator seems to be required. this string is placed
# into a class variable so that it can be overridden if # into a class variable so that it can be overridden if
# necessary. # necessary.
log_format_string = '<%d>%s\000' log_format_string = '<%d>%s\000'
def log (self, message, facility=LOG_USER, priority=LOG_INFO): def log (self, message, facility=LOG_USER, priority=LOG_INFO):
message = self.log_format_string % ( message = self.log_format_string % (
self.encode_priority (facility, priority), self.encode_priority (facility, priority),
message message
) )
if self.unix: if self.unix:
self.socket.send (message) self.socket.send (message)
else: else:
self.socket.sendto (message, self.address) self.socket.sendto (message, self.address)
def encode_priority (self, facility, priority): def encode_priority (self, facility, priority):
if type(facility) == type(''): if type(facility) == type(''):
facility = facility_names[facility] facility = facility_names[facility]
if type(priority) == type(''): if type(priority) == type(''):
priority = priority_names[priority] priority = priority_names[priority]
return (facility<<3) | priority return (facility<<3) | priority
def close (self): def close (self):
if self.unix: if self.unix:
self.socket.close() self.socket.close()
if __name__ == '__main__': if __name__ == '__main__':
""" """
Unit test for syslog_client. Set up for the test by: Unit test for syslog_client. Set up for the test by:
* tail -f /var/log/allstuf (to see the "normal" log messages). * tail -f /var/log/allstuf (to see the "normal" log messages).
* Running the test_logger.py script with a junk file name (which * Running the test_logger.py script with a junk file name (which
will be opened as a Unix-domain socket). "Custom" log messages will be opened as a Unix-domain socket). "Custom" log messages
will go here. will go here.
* Run this script, passing the same junk file name. * Run this script, passing the same junk file name.
* Check that the "bogus" test throws, and that none of the rest do. * Check that the "bogus" test throws, and that none of the rest do.
* Check that the 'default' and 'UDP' messages show up in the tail. * Check that the 'default' and 'UDP' messages show up in the tail.
* Check that the 'non-std' message shows up in the test_logger * Check that the 'non-std' message shows up in the test_logger
console. console.
* Finally, kill off the tail and test_logger, and clean up the * Finally, kill off the tail and test_logger, and clean up the
socket file. socket file.
""" """
import sys, traceback import sys, traceback
...@@ -215,14 +215,14 @@ if __name__ == '__main__': ...@@ -215,14 +215,14 @@ if __name__ == '__main__':
def test_client( desc, address=None ): def test_client( desc, address=None ):
try: try:
if address: if address:
client = syslog_client( address ) client = syslog_client( address )
else: else:
client = syslog_client() client = syslog_client()
except: except:
print 'syslog_client() [%s] ctor threw' % desc print 'syslog_client() [%s] ctor threw' % desc
traceback.print_exc() traceback.print_exc()
return return
try: try:
client.log( 'testing syslog_client() [%s]' % desc client.log( 'testing syslog_client() [%s]' % desc
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
############################################################################## ##############################################################################
"""Image object""" """Image object"""
__version__='$Revision: 1.101 $'[11:-2] __version__='$Revision: 1.102 $'[11:-2]
import Globals, string, struct, content_types import Globals, string, struct, content_types
from OFS.content_types import guess_content_type from OFS.content_types import guess_content_type
...@@ -194,12 +194,12 @@ class File(Persistent,Implicit,PropertyManager, ...@@ -194,12 +194,12 @@ class File(Persistent,Implicit,PropertyManager,
if header is not None: if header is not None:
header=string.split(header, ';')[0] header=string.split(header, ';')[0]
mod_since=int(DateTime(header).timeTime()) mod_since=int(DateTime(header).timeTime())
if self._p_mtime: if self._p_mtime:
last_mod = int(self._p_mtime) last_mod = int(self._p_mtime)
else: else:
last_mod = 0 last_mod = 0
if last_mod > 0 and last_mod <= mod_since: if last_mod > 0 and last_mod <= mod_since:
RESPONSE.setStatus(304) RESPONSE.setStatus(304)
return RESPONSE return RESPONSE
......
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
############################################################################## ##############################################################################
"""Utility module to help manage the asyncore mainloop in a multi-threaded app """Utility module to help manage the asyncore mainloop in a multi-threaded app
""" """
__version__='$Revision: 1.1 $'[11:-2] __version__='$Revision: 1.2 $'[11:-2]
import thread import thread
import asyncore import asyncore
...@@ -105,7 +105,7 @@ def _start_loop(map): ...@@ -105,7 +105,7 @@ def _start_loop(map):
try: try:
global _looping global _looping
_looping=1 _looping=1
while _loop_callbacks: while _loop_callbacks:
cb, args, kw = _loop_callbacks.pop() cb, args, kw = _loop_callbacks.pop()
apply(cb, (map,)+args, kw or {}) apply(cb, (map,)+args, kw or {})
......
...@@ -68,144 +68,144 @@ Usage: ...@@ -68,144 +68,144 @@ Usage:
# #
# priorities (these are ordered) # priorities (these are ordered)
LOG_EMERG = 0 # system is unusable LOG_EMERG = 0 # system is unusable
LOG_ALERT = 1 # action must be taken immediately LOG_ALERT = 1 # action must be taken immediately
LOG_CRIT = 2 # critical conditions LOG_CRIT = 2 # critical conditions
LOG_ERR = 3 # error conditions LOG_ERR = 3 # error conditions
LOG_WARNING = 4 # warning conditions LOG_WARNING = 4 # warning conditions
LOG_NOTICE = 5 # normal but significant condition LOG_NOTICE = 5 # normal but significant condition
LOG_INFO = 6 # informational LOG_INFO = 6 # informational
LOG_DEBUG = 7 # debug-level messages LOG_DEBUG = 7 # debug-level messages
# facility codes # facility codes
LOG_KERN = 0 # kernel messages LOG_KERN = 0 # kernel messages
LOG_USER = 1 # random user-level messages LOG_USER = 1 # random user-level messages
LOG_MAIL = 2 # mail system LOG_MAIL = 2 # mail system
LOG_DAEMON = 3 # system daemons LOG_DAEMON = 3 # system daemons
LOG_AUTH = 4 # security/authorization messages LOG_AUTH = 4 # security/authorization messages
LOG_SYSLOG = 5 # messages generated internally by syslogd LOG_SYSLOG = 5 # messages generated internally by syslogd
LOG_LPR = 6 # line printer subsystem LOG_LPR = 6 # line printer subsystem
LOG_NEWS = 7 # network news subsystem LOG_NEWS = 7 # network news subsystem
LOG_UUCP = 8 # UUCP subsystem LOG_UUCP = 8 # UUCP subsystem
LOG_CRON = 9 # clock daemon LOG_CRON = 9 # clock daemon
LOG_AUTHPRIV = 10 # security/authorization messages (private) LOG_AUTHPRIV = 10 # security/authorization messages (private)
# other codes through 15 reserved for system use # other codes through 15 reserved for system use
LOG_LOCAL0 = 16 # reserved for local use LOG_LOCAL0 = 16 # reserved for local use
LOG_LOCAL1 = 17 # reserved for local use LOG_LOCAL1 = 17 # reserved for local use
LOG_LOCAL2 = 18 # reserved for local use LOG_LOCAL2 = 18 # reserved for local use
LOG_LOCAL3 = 19 # reserved for local use LOG_LOCAL3 = 19 # reserved for local use
LOG_LOCAL4 = 20 # reserved for local use LOG_LOCAL4 = 20 # reserved for local use
LOG_LOCAL5 = 21 # reserved for local use LOG_LOCAL5 = 21 # reserved for local use
LOG_LOCAL6 = 22 # reserved for local use LOG_LOCAL6 = 22 # reserved for local use
LOG_LOCAL7 = 23 # reserved for local use LOG_LOCAL7 = 23 # reserved for local use
priority_names = { priority_names = {
"alert": LOG_ALERT, "alert": LOG_ALERT,
"crit": LOG_CRIT, "crit": LOG_CRIT,
"debug": LOG_DEBUG, "debug": LOG_DEBUG,
"emerg": LOG_EMERG, "emerg": LOG_EMERG,
"err": LOG_ERR, "err": LOG_ERR,
"error": LOG_ERR, # DEPRECATED "error": LOG_ERR, # DEPRECATED
"info": LOG_INFO, "info": LOG_INFO,
"notice": LOG_NOTICE, "notice": LOG_NOTICE,
"panic": LOG_EMERG, # DEPRECATED "panic": LOG_EMERG, # DEPRECATED
"warn": LOG_WARNING, # DEPRECATED "warn": LOG_WARNING, # DEPRECATED
"warning": LOG_WARNING, "warning": LOG_WARNING,
} }
facility_names = { facility_names = {
"auth": LOG_AUTH, "auth": LOG_AUTH,
"authpriv": LOG_AUTHPRIV, "authpriv": LOG_AUTHPRIV,
"cron": LOG_CRON, "cron": LOG_CRON,
"daemon": LOG_DAEMON, "daemon": LOG_DAEMON,
"kern": LOG_KERN, "kern": LOG_KERN,
"lpr": LOG_LPR, "lpr": LOG_LPR,
"mail": LOG_MAIL, "mail": LOG_MAIL,
"news": LOG_NEWS, "news": LOG_NEWS,
"security": LOG_AUTH, # DEPRECATED "security": LOG_AUTH, # DEPRECATED
"syslog": LOG_SYSLOG, "syslog": LOG_SYSLOG,
"user": LOG_USER, "user": LOG_USER,
"uucp": LOG_UUCP, "uucp": LOG_UUCP,
"local0": LOG_LOCAL0, "local0": LOG_LOCAL0,
"local1": LOG_LOCAL1, "local1": LOG_LOCAL1,
"local2": LOG_LOCAL2, "local2": LOG_LOCAL2,
"local3": LOG_LOCAL3, "local3": LOG_LOCAL3,
"local4": LOG_LOCAL4, "local4": LOG_LOCAL4,
"local5": LOG_LOCAL5, "local5": LOG_LOCAL5,
"local6": LOG_LOCAL6, "local6": LOG_LOCAL6,
"local7": LOG_LOCAL7, "local7": LOG_LOCAL7,
} }
import socket import socket
class syslog_client: class syslog_client:
def __init__ (self, address='/dev/log'): def __init__ (self, address='/dev/log'):
self.address = address self.address = address
if type (address) == type(''): if type (address) == type(''):
try: # APUE 13.4.2 specifes /dev/log as datagram socket try: # APUE 13.4.2 specifes /dev/log as datagram socket
self.socket = socket.socket( socket.AF_UNIX self.socket = socket.socket( socket.AF_UNIX
, socket.SOCK_DGRAM) , socket.SOCK_DGRAM)
self.socket.connect (address) self.socket.connect (address)
except: # older linux may create as stream socket except: # older linux may create as stream socket
self.socket = socket.socket( socket.AF_UNIX self.socket = socket.socket( socket.AF_UNIX
, socket.SOCK_STREAM) , socket.SOCK_STREAM)
self.socket.connect (address) self.socket.connect (address)
self.unix = 1 self.unix = 1
else: else:
self.socket = socket.socket( socket.AF_INET self.socket = socket.socket( socket.AF_INET
, socket.SOCK_DGRAM) , socket.SOCK_DGRAM)
self.unix = 0 self.unix = 0
# curious: when talking to the unix-domain '/dev/log' socket, a # curious: when talking to the unix-domain '/dev/log' socket, a
# zero-terminator seems to be required. this string is placed # zero-terminator seems to be required. this string is placed
# into a class variable so that it can be overridden if # into a class variable so that it can be overridden if
# necessary. # necessary.
log_format_string = '<%d>%s\000' log_format_string = '<%d>%s\000'
def log (self, message, facility=LOG_USER, priority=LOG_INFO): def log (self, message, facility=LOG_USER, priority=LOG_INFO):
message = self.log_format_string % ( message = self.log_format_string % (
self.encode_priority (facility, priority), self.encode_priority (facility, priority),
message message
) )
if self.unix: if self.unix:
self.socket.send (message) self.socket.send (message)
else: else:
self.socket.sendto (message, self.address) self.socket.sendto (message, self.address)
def encode_priority (self, facility, priority): def encode_priority (self, facility, priority):
if type(facility) == type(''): if type(facility) == type(''):
facility = facility_names[facility] facility = facility_names[facility]
if type(priority) == type(''): if type(priority) == type(''):
priority = priority_names[priority] priority = priority_names[priority]
return (facility<<3) | priority return (facility<<3) | priority
def close (self): def close (self):
if self.unix: if self.unix:
self.socket.close() self.socket.close()
if __name__ == '__main__': if __name__ == '__main__':
""" """
Unit test for syslog_client. Set up for the test by: Unit test for syslog_client. Set up for the test by:
* tail -f /var/log/allstuf (to see the "normal" log messages). * tail -f /var/log/allstuf (to see the "normal" log messages).
* Running the test_logger.py script with a junk file name (which * Running the test_logger.py script with a junk file name (which
will be opened as a Unix-domain socket). "Custom" log messages will be opened as a Unix-domain socket). "Custom" log messages
will go here. will go here.
* Run this script, passing the same junk file name. * Run this script, passing the same junk file name.
* Check that the "bogus" test throws, and that none of the rest do. * Check that the "bogus" test throws, and that none of the rest do.
* Check that the 'default' and 'UDP' messages show up in the tail. * Check that the 'default' and 'UDP' messages show up in the tail.
* Check that the 'non-std' message shows up in the test_logger * Check that the 'non-std' message shows up in the test_logger
console. console.
* Finally, kill off the tail and test_logger, and clean up the * Finally, kill off the tail and test_logger, and clean up the
socket file. socket file.
""" """
import sys, traceback import sys, traceback
...@@ -215,14 +215,14 @@ if __name__ == '__main__': ...@@ -215,14 +215,14 @@ if __name__ == '__main__':
def test_client( desc, address=None ): def test_client( desc, address=None ):
try: try:
if address: if address:
client = syslog_client( address ) client = syslog_client( address )
else: else:
client = syslog_client() client = syslog_client()
except: except:
print 'syslog_client() [%s] ctor threw' % desc print 'syslog_client() [%s] ctor threw' % desc
traceback.print_exc() traceback.print_exc()
return return
try: try:
client.log( 'testing syslog_client() [%s]' % desc client.log( 'testing syslog_client() [%s]' % desc
......
# -*- Mode: Python; tab-width: 4 -*- # -*- Mode: Python; tab-width: 4 -*-
# Id: asyncore.py,v 2.49 2000/05/04 06:06:04 jim Exp # Id: asyncore.py,v 2.49 2000/05/04 06:06:04 jim Exp
# $Id: asyncore.py,v 1.9 2000/05/05 17:28:57 jim Exp $ # $Id: asyncore.py,v 1.10 2000/05/12 19:43:07 brian Exp $
# Author: Sam Rushing <rushing@nightmare.com> # Author: Sam Rushing <rushing@nightmare.com>
# ====================================================================== # ======================================================================
# Copyright 1996 by Sam Rushing # Copyright 1996 by Sam Rushing
...@@ -34,347 +34,347 @@ import sys ...@@ -34,347 +34,347 @@ import sys
import os import os
if os.name == 'nt': if os.name == 'nt':
EWOULDBLOCK = 10035 EWOULDBLOCK = 10035
EINPROGRESS = 10036 EINPROGRESS = 10036
EALREADY = 10037 EALREADY = 10037
ECONNRESET = 10054 ECONNRESET = 10054
ENOTCONN = 10057 ENOTCONN = 10057
ESHUTDOWN = 10058 ESHUTDOWN = 10058
else: else:
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, ENOTCONN, ESHUTDOWN
try: try:
socket_map socket_map
except NameError: except NameError:
socket_map = {} socket_map = {}
class ExitNow (exceptions.Exception): class ExitNow (exceptions.Exception):
pass pass
DEBUG = 0 DEBUG = 0
def poll (timeout=0.0, map=None): def poll (timeout=0.0, map=None):
global DEBUG global DEBUG
if map is None: if map is None:
map = socket_map map = socket_map
if map: if map:
r = []; w = []; e = [] r = []; w = []; e = []
for fd, obj in map.items(): for fd, obj in map.items():
if obj.readable(): if obj.readable():
r.append (fd) r.append (fd)
if obj.writable(): if obj.writable():
w.append (fd) w.append (fd)
r,w,e = select.select (r,w,e, timeout) r,w,e = select.select (r,w,e, timeout)
if DEBUG: if DEBUG:
print r,w,e print r,w,e
for fd in r: for fd in r:
try: try:
obj = map[fd] obj = map[fd]
try: try:
obj.handle_read_event() obj.handle_read_event()
except ExitNow: except ExitNow:
raise ExitNow raise ExitNow
except: except:
obj.handle_error() obj.handle_error()
except KeyError: except KeyError:
pass pass
for fd in w: for fd in w:
try: try:
obj = map[fd] obj = map[fd]
try: try:
obj.handle_write_event() obj.handle_write_event()
except ExitNow: except ExitNow:
raise ExitNow raise ExitNow
except: except:
obj.handle_error() obj.handle_error()
except KeyError: except KeyError:
pass pass
def poll2 (timeout=0.0, map=None): def poll2 (timeout=0.0, map=None):
import poll import poll
if map is None: if map is None:
map=socket_map map=socket_map
# timeout is in milliseconds # timeout is in milliseconds
timeout = int(timeout*1000) timeout = int(timeout*1000)
if map: if map:
l = [] l = []
for fd, obj in map.items(): for fd, obj in map.items():
flags = 0 flags = 0
if obj.readable(): if obj.readable():
flags = poll.POLLIN flags = poll.POLLIN
if obj.writable(): if obj.writable():
flags = flags | poll.POLLOUT flags = flags | poll.POLLOUT
if flags: if flags:
l.append ((fd, flags)) l.append ((fd, flags))
r = poll.poll (l, timeout) r = poll.poll (l, timeout)
for fd, flags in r: for fd, flags in r:
try: try:
obj = map[fd] obj = map[fd]
try: try:
if (flags & poll.POLLIN): if (flags & poll.POLLIN):
obj.handle_read_event() obj.handle_read_event()
if (flags & poll.POLLOUT): if (flags & poll.POLLOUT):
obj.handle_write_event() obj.handle_write_event()
except ExitNow: except ExitNow:
raise ExitNow raise ExitNow
except: except:
obj.handle_error() obj.handle_error()
except KeyError: except KeyError:
pass pass
def loop (timeout=30.0, use_poll=0, map=None): def loop (timeout=30.0, use_poll=0, map=None):
if use_poll: if use_poll:
poll_fun = poll2 poll_fun = poll2
else: else:
poll_fun = poll poll_fun = poll
if map is None: if map is None:
map=socket_map map=socket_map
while map: while map:
poll_fun (timeout, map) poll_fun (timeout, map)
class dispatcher: class dispatcher:
debug = 0 debug = 0
connected = 0 connected = 0
accepting = 0 accepting = 0
closing = 0 closing = 0
addr = None addr = None
def __init__ (self, sock=None, map=None): def __init__ (self, sock=None, map=None):
if sock: if sock:
self.set_socket (sock, map) self.set_socket (sock, map)
# I think it should inherit this anyway # I think it should inherit this anyway
self.socket.setblocking (0) self.socket.setblocking (0)
self.connected = 1 self.connected = 1
def __repr__ (self): def __repr__ (self):
try: try:
status = [] status = []
if self.accepting and self.addr: if self.accepting and self.addr:
status.append ('listening') status.append ('listening')
elif self.connected: elif self.connected:
status.append ('connected') status.append ('connected')
if self.addr: if self.addr:
status.append ('%s:%d' % self.addr) status.append ('%s:%d' % self.addr)
return '<%s %s at %x>' % ( return '<%s %s at %x>' % (
self.__class__.__name__, self.__class__.__name__,
string.join (status, ' '), string.join (status, ' '),
id(self) id(self)
) )
except: except:
try: try:
ar = repr(self.addr) ar = repr(self.addr)
except: except:
ar = 'no self.addr!' ar = 'no self.addr!'
return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar) return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id(self),ar)
def add_channel (self, map=None): def add_channel (self, map=None):
#self.log_info ('adding channel %s' % self) #self.log_info ('adding channel %s' % self)
if map is None: if map is None:
map=socket_map map=socket_map
map [self._fileno] = self map [self._fileno] = self
def del_channel (self, map=None): def del_channel (self, map=None):
fd = self._fileno fd = self._fileno
if map is None: if map is None:
map=socket_map map=socket_map
if map.has_key (fd): if map.has_key (fd):
#self.log_info ('closing channel %d:%s' % (fd, self)) #self.log_info ('closing channel %d:%s' % (fd, self))
del map [fd] del map [fd]
def create_socket (self, family, type): def create_socket (self, family, type):
self.family_and_type = family, type self.family_and_type = family, type
self.socket = socket.socket (family, type) self.socket = socket.socket (family, type)
self.socket.setblocking(0) self.socket.setblocking(0)
self._fileno = self.socket.fileno() self._fileno = self.socket.fileno()
self.add_channel() self.add_channel()
def set_socket (self, sock, map=None): def set_socket (self, sock, map=None):
self.__dict__['socket'] = sock self.__dict__['socket'] = sock
self._fileno = sock.fileno() self._fileno = sock.fileno()
self.add_channel (map) self.add_channel (map)
def set_reuse_addr (self): def set_reuse_addr (self):
# try to re-use a server port if possible # try to re-use a server port if possible
try: try:
self.socket.setsockopt ( self.socket.setsockopt (
socket.SOL_SOCKET, socket.SO_REUSEADDR, socket.SOL_SOCKET, socket.SO_REUSEADDR,
self.socket.getsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1 self.socket.getsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR) | 1
) )
except: except:
pass pass
# ================================================== # ==================================================
# predicates for select() # predicates for select()
# these are used as filters for the lists of sockets # these are used as filters for the lists of sockets
# to pass to select(). # to pass to select().
# ================================================== # ==================================================
def readable (self): def readable (self):
return 1 return 1
if os.name == 'mac': if os.name == 'mac':
# The macintosh will select a listening socket for # The macintosh will select a listening socket for
# write if you let it. What might this mean? # write if you let it. What might this mean?
def writable (self): def writable (self):
return not self.accepting return not self.accepting
else: else:
def writable (self): def writable (self):
return 1 return 1
# ================================================== # ==================================================
# socket object methods. # socket object methods.
# ================================================== # ==================================================
def listen (self, num): def listen (self, num):
self.accepting = 1 self.accepting = 1
if os.name == 'nt' and num > 5: if os.name == 'nt' and num > 5:
num = 1 num = 1
return self.socket.listen (num) return self.socket.listen (num)
def bind (self, addr): def bind (self, addr):
self.addr = addr self.addr = addr
return self.socket.bind (addr) return self.socket.bind (addr)
def connect (self, address): def connect (self, address):
self.connected = 0 self.connected = 0
try: try:
self.socket.connect (address) self.socket.connect (address)
except socket.error, why: except socket.error, why:
if why[0] in (EINPROGRESS, EALREADY, EWOULDBLOCK): if why[0] in (EINPROGRESS, EALREADY, EWOULDBLOCK):
return return
else: else:
raise socket.error, why raise socket.error, why
self.connected = 1 self.connected = 1
self.handle_connect() self.handle_connect()
def accept (self): def accept (self):
try: try:
conn, addr = self.socket.accept() conn, addr = self.socket.accept()
return conn, addr return conn, addr
except socket.error, why: except socket.error, why:
if why[0] == EWOULDBLOCK: if why[0] == EWOULDBLOCK:
pass pass
else: else:
raise socket.error, why raise socket.error, why
def send (self, data): def send (self, data):
try: try:
result = self.socket.send (data) result = self.socket.send (data)
return result return result
except socket.error, why: except socket.error, why:
if why[0] == EWOULDBLOCK: if why[0] == EWOULDBLOCK:
return 0 return 0
else: else:
raise socket.error, why raise socket.error, why
return 0 return 0
def recv (self, buffer_size): def recv (self, buffer_size):
try: try:
data = self.socket.recv (buffer_size) data = self.socket.recv (buffer_size)
if not data: if not data:
# a closed connection is indicated by signaling # a closed connection is indicated by signaling
# a read condition, and having recv() return 0. # a read condition, and having recv() return 0.
self.handle_close() self.handle_close()
return '' return ''
else: else:
return data return data
except socket.error, why: except socket.error, why:
# winsock sometimes throws ENOTCONN # winsock sometimes throws ENOTCONN
if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]: if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
self.handle_close() self.handle_close()
return '' return ''
else: else:
raise socket.error, why raise socket.error, why
def close (self): def close (self):
self.del_channel() self.del_channel()
self.socket.close() self.socket.close()
# cheap inheritance, used to pass all other attribute # cheap inheritance, used to pass all other attribute
# references to the underlying socket object. # references to the underlying socket object.
def __getattr__ (self, attr): def __getattr__ (self, attr):
return getattr (self.socket, attr) return getattr (self.socket, attr)
# log and log_info maybe overriden to provide more sophisitcated # log and log_info maybe overriden to provide more sophisitcated
# logging and warning methods. In general, log is for 'hit' logging # logging and warning methods. In general, log is for 'hit' logging
# and 'log_info' is for informational, warning and error logging. # and 'log_info' is for informational, warning and error logging.
def log (self, message): def log (self, message):
sys.stderr.write ('log: %s\n' % str(message)) sys.stderr.write ('log: %s\n' % str(message))
def log_info (self, message, type='info'): def log_info (self, message, type='info'):
if __debug__ or type != 'info': if __debug__ or type != 'info':
print '%s: %s' % (type, message) print '%s: %s' % (type, message)
def handle_read_event (self): def handle_read_event (self):
if self.accepting: if self.accepting:
# for an accepting socket, getting a read implies # for an accepting socket, getting a read implies
# that we are connected # that we are connected
if not self.connected: if not self.connected:
self.connected = 1 self.connected = 1
self.handle_accept() self.handle_accept()
elif not self.connected: elif not self.connected:
self.handle_connect() self.handle_connect()
self.connected = 1 self.connected = 1
self.handle_read() self.handle_read()
else: else:
self.handle_read() self.handle_read()
def handle_write_event (self): def handle_write_event (self):
# getting a write implies that we are connected # getting a write implies that we are connected
if not self.connected: if not self.connected:
self.handle_connect() self.handle_connect()
self.connected = 1 self.connected = 1
self.handle_write() self.handle_write()
def handle_expt_event (self): def handle_expt_event (self):
self.handle_expt() self.handle_expt()
def handle_error (self): def handle_error (self):
(file,fun,line), t, v, tbinfo = compact_traceback() (file,fun,line), t, v, tbinfo = compact_traceback()
# sometimes a user repr method will crash. # sometimes a user repr method will crash.
try: try:
self_repr = repr (self) self_repr = repr (self)
except: except:
self_repr = '<__repr__ (self) failed for object at %0x>' % id(self) self_repr = '<__repr__ (self) failed for object at %0x>' % id(self)
self.log_info ( self.log_info (
'uncaptured python exception, closing channel %s (%s:%s %s)' % ( 'uncaptured python exception, closing channel %s (%s:%s %s)' % (
self_repr, self_repr,
t, t,
v, v,
tbinfo tbinfo
), ),
'error' 'error'
) )
self.close() self.close()
def handle_expt (self): def handle_expt (self):
self.log_info ('unhandled exception', 'warning') self.log_info ('unhandled exception', 'warning')
def handle_read (self): def handle_read (self):
self.log_info ('unhandled read event', 'warning') self.log_info ('unhandled read event', 'warning')
def handle_write (self): def handle_write (self):
self.log_info ('unhandled write event', 'warning') self.log_info ('unhandled write event', 'warning')
def handle_connect (self): def handle_connect (self):
self.log_info ('unhandled connect event', 'warning') self.log_info ('unhandled connect event', 'warning')
def handle_accept (self): def handle_accept (self):
self.log_info ('unhandled accept event', 'warning') self.log_info ('unhandled accept event', 'warning')
def handle_close (self): def handle_close (self):
self.log_info ('unhandled close event', 'warning') self.log_info ('unhandled close event', 'warning')
self.close() self.close()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# adds simple buffered output capability, useful for simple clients. # adds simple buffered output capability, useful for simple clients.
...@@ -382,63 +382,63 @@ class dispatcher: ...@@ -382,63 +382,63 @@ class dispatcher:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class dispatcher_with_send (dispatcher): class dispatcher_with_send (dispatcher):
def __init__ (self, sock=None): def __init__ (self, sock=None):
dispatcher.__init__ (self, sock) dispatcher.__init__ (self, sock)
self.out_buffer = '' self.out_buffer = ''
def initiate_send (self): def initiate_send (self):
num_sent = 0 num_sent = 0
num_sent = dispatcher.send (self, self.out_buffer[:512]) num_sent = dispatcher.send (self, self.out_buffer[:512])
self.out_buffer = self.out_buffer[num_sent:] self.out_buffer = self.out_buffer[num_sent:]
def handle_write (self): def handle_write (self):
self.initiate_send() self.initiate_send()
def writable (self): def writable (self):
return (not self.connected) or len(self.out_buffer) return (not self.connected) or len(self.out_buffer)
def send (self, data): def send (self, data):
if self.debug: if self.debug:
self.log_info ('sending %s' % repr(data)) self.log_info ('sending %s' % repr(data))
self.out_buffer = self.out_buffer + data self.out_buffer = self.out_buffer + data
self.initiate_send() self.initiate_send()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# used for debugging. # used for debugging.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def compact_traceback (): def compact_traceback ():
t,v,tb = sys.exc_info() t,v,tb = sys.exc_info()
tbinfo = [] tbinfo = []
while 1: while 1:
tbinfo.append (( tbinfo.append ((
tb.tb_frame.f_code.co_filename, tb.tb_frame.f_code.co_filename,
tb.tb_frame.f_code.co_name, tb.tb_frame.f_code.co_name,
str(tb.tb_lineno) str(tb.tb_lineno)
)) ))
tb = tb.tb_next tb = tb.tb_next
if not tb: if not tb:
break break
# just to be safe # just to be safe
del tb del tb
file, function, line = tbinfo[-1] file, function, line = tbinfo[-1]
info = '[' + string.join ( info = '[' + string.join (
map ( map (
lambda x: string.join (x, '|'), lambda x: string.join (x, '|'),
tbinfo tbinfo
), ),
'] [' '] ['
) + ']' ) + ']'
return (file, function, line), t, v, info return (file, function, line), t, v, info
def close_all (map=None): def close_all (map=None):
if map is None: if map is None:
map=socket_map map=socket_map
for x in map.values(): for x in map.values():
x.socket.close() x.socket.close()
map.clear() map.clear()
# Asynchronous File I/O: # Asynchronous File I/O:
# #
...@@ -455,39 +455,39 @@ def close_all (map=None): ...@@ -455,39 +455,39 @@ def close_all (map=None):
import os import os
if os.name == 'posix': if os.name == 'posix':
import fcntl import fcntl
import FCNTL import FCNTL
class file_wrapper: class file_wrapper:
# here we override just enough to make a file # here we override just enough to make a file
# look like a socket for the purposes of asyncore. # look like a socket for the purposes of asyncore.
def __init__ (self, fd): def __init__ (self, fd):
self.fd = fd self.fd = fd
def recv (self, *args): def recv (self, *args):
return apply (os.read, (self.fd,)+args) return apply (os.read, (self.fd,)+args)
def write (self, *args): def write (self, *args):
return apply (os.write, (self.fd,)+args) return apply (os.write, (self.fd,)+args)
def close (self): def close (self):
return os.close (self.fd) return os.close (self.fd)
def fileno (self): def fileno (self):
return self.fd return self.fd
class file_dispatcher (dispatcher): class file_dispatcher (dispatcher):
def __init__ (self, fd): def __init__ (self, fd):
dispatcher.__init__ (self) dispatcher.__init__ (self)
self.connected = 1 self.connected = 1
# set it to non-blocking mode # set it to non-blocking mode
flags = fcntl.fcntl (fd, FCNTL.F_GETFL, 0) flags = fcntl.fcntl (fd, FCNTL.F_GETFL, 0)
flags = flags | FCNTL.O_NONBLOCK flags = flags | FCNTL.O_NONBLOCK
fcntl.fcntl (fd, FCNTL.F_SETFL, flags) fcntl.fcntl (fd, FCNTL.F_SETFL, flags)
self.set_file (fd) self.set_file (fd)
def set_file (self, fd): def set_file (self, fd):
self._fileno = fd self._fileno = fd
self.socket = file_wrapper (fd) self.socket = file_wrapper (fd)
self.add_channel() self.add_channel()
...@@ -68,144 +68,144 @@ Usage: ...@@ -68,144 +68,144 @@ Usage:
# #
# priorities (these are ordered) # priorities (these are ordered)
LOG_EMERG = 0 # system is unusable LOG_EMERG = 0 # system is unusable
LOG_ALERT = 1 # action must be taken immediately LOG_ALERT = 1 # action must be taken immediately
LOG_CRIT = 2 # critical conditions LOG_CRIT = 2 # critical conditions
LOG_ERR = 3 # error conditions LOG_ERR = 3 # error conditions
LOG_WARNING = 4 # warning conditions LOG_WARNING = 4 # warning conditions
LOG_NOTICE = 5 # normal but significant condition LOG_NOTICE = 5 # normal but significant condition
LOG_INFO = 6 # informational LOG_INFO = 6 # informational
LOG_DEBUG = 7 # debug-level messages LOG_DEBUG = 7 # debug-level messages
# facility codes # facility codes
LOG_KERN = 0 # kernel messages LOG_KERN = 0 # kernel messages
LOG_USER = 1 # random user-level messages LOG_USER = 1 # random user-level messages
LOG_MAIL = 2 # mail system LOG_MAIL = 2 # mail system
LOG_DAEMON = 3 # system daemons LOG_DAEMON = 3 # system daemons
LOG_AUTH = 4 # security/authorization messages LOG_AUTH = 4 # security/authorization messages
LOG_SYSLOG = 5 # messages generated internally by syslogd LOG_SYSLOG = 5 # messages generated internally by syslogd
LOG_LPR = 6 # line printer subsystem LOG_LPR = 6 # line printer subsystem
LOG_NEWS = 7 # network news subsystem LOG_NEWS = 7 # network news subsystem
LOG_UUCP = 8 # UUCP subsystem LOG_UUCP = 8 # UUCP subsystem
LOG_CRON = 9 # clock daemon LOG_CRON = 9 # clock daemon
LOG_AUTHPRIV = 10 # security/authorization messages (private) LOG_AUTHPRIV = 10 # security/authorization messages (private)
# other codes through 15 reserved for system use # other codes through 15 reserved for system use
LOG_LOCAL0 = 16 # reserved for local use LOG_LOCAL0 = 16 # reserved for local use
LOG_LOCAL1 = 17 # reserved for local use LOG_LOCAL1 = 17 # reserved for local use
LOG_LOCAL2 = 18 # reserved for local use LOG_LOCAL2 = 18 # reserved for local use
LOG_LOCAL3 = 19 # reserved for local use LOG_LOCAL3 = 19 # reserved for local use
LOG_LOCAL4 = 20 # reserved for local use LOG_LOCAL4 = 20 # reserved for local use
LOG_LOCAL5 = 21 # reserved for local use LOG_LOCAL5 = 21 # reserved for local use
LOG_LOCAL6 = 22 # reserved for local use LOG_LOCAL6 = 22 # reserved for local use
LOG_LOCAL7 = 23 # reserved for local use LOG_LOCAL7 = 23 # reserved for local use
priority_names = { priority_names = {
"alert": LOG_ALERT, "alert": LOG_ALERT,
"crit": LOG_CRIT, "crit": LOG_CRIT,
"debug": LOG_DEBUG, "debug": LOG_DEBUG,
"emerg": LOG_EMERG, "emerg": LOG_EMERG,
"err": LOG_ERR, "err": LOG_ERR,
"error": LOG_ERR, # DEPRECATED "error": LOG_ERR, # DEPRECATED
"info": LOG_INFO, "info": LOG_INFO,
"notice": LOG_NOTICE, "notice": LOG_NOTICE,
"panic": LOG_EMERG, # DEPRECATED "panic": LOG_EMERG, # DEPRECATED
"warn": LOG_WARNING, # DEPRECATED "warn": LOG_WARNING, # DEPRECATED
"warning": LOG_WARNING, "warning": LOG_WARNING,
} }
facility_names = { facility_names = {
"auth": LOG_AUTH, "auth": LOG_AUTH,
"authpriv": LOG_AUTHPRIV, "authpriv": LOG_AUTHPRIV,
"cron": LOG_CRON, "cron": LOG_CRON,
"daemon": LOG_DAEMON, "daemon": LOG_DAEMON,
"kern": LOG_KERN, "kern": LOG_KERN,
"lpr": LOG_LPR, "lpr": LOG_LPR,
"mail": LOG_MAIL, "mail": LOG_MAIL,
"news": LOG_NEWS, "news": LOG_NEWS,
"security": LOG_AUTH, # DEPRECATED "security": LOG_AUTH, # DEPRECATED
"syslog": LOG_SYSLOG, "syslog": LOG_SYSLOG,
"user": LOG_USER, "user": LOG_USER,
"uucp": LOG_UUCP, "uucp": LOG_UUCP,
"local0": LOG_LOCAL0, "local0": LOG_LOCAL0,
"local1": LOG_LOCAL1, "local1": LOG_LOCAL1,
"local2": LOG_LOCAL2, "local2": LOG_LOCAL2,
"local3": LOG_LOCAL3, "local3": LOG_LOCAL3,
"local4": LOG_LOCAL4, "local4": LOG_LOCAL4,
"local5": LOG_LOCAL5, "local5": LOG_LOCAL5,
"local6": LOG_LOCAL6, "local6": LOG_LOCAL6,
"local7": LOG_LOCAL7, "local7": LOG_LOCAL7,
} }
import socket import socket
class syslog_client: class syslog_client:
def __init__ (self, address='/dev/log'): def __init__ (self, address='/dev/log'):
self.address = address self.address = address
if type (address) == type(''): if type (address) == type(''):
try: # APUE 13.4.2 specifes /dev/log as datagram socket try: # APUE 13.4.2 specifes /dev/log as datagram socket
self.socket = socket.socket( socket.AF_UNIX self.socket = socket.socket( socket.AF_UNIX
, socket.SOCK_DGRAM) , socket.SOCK_DGRAM)
self.socket.connect (address) self.socket.connect (address)
except: # older linux may create as stream socket except: # older linux may create as stream socket
self.socket = socket.socket( socket.AF_UNIX self.socket = socket.socket( socket.AF_UNIX
, socket.SOCK_STREAM) , socket.SOCK_STREAM)
self.socket.connect (address) self.socket.connect (address)
self.unix = 1 self.unix = 1
else: else:
self.socket = socket.socket( socket.AF_INET self.socket = socket.socket( socket.AF_INET
, socket.SOCK_DGRAM) , socket.SOCK_DGRAM)
self.unix = 0 self.unix = 0
# curious: when talking to the unix-domain '/dev/log' socket, a # curious: when talking to the unix-domain '/dev/log' socket, a
# zero-terminator seems to be required. this string is placed # zero-terminator seems to be required. this string is placed
# into a class variable so that it can be overridden if # into a class variable so that it can be overridden if
# necessary. # necessary.
log_format_string = '<%d>%s\000' log_format_string = '<%d>%s\000'
def log (self, message, facility=LOG_USER, priority=LOG_INFO): def log (self, message, facility=LOG_USER, priority=LOG_INFO):
message = self.log_format_string % ( message = self.log_format_string % (
self.encode_priority (facility, priority), self.encode_priority (facility, priority),
message message
) )
if self.unix: if self.unix:
self.socket.send (message) self.socket.send (message)
else: else:
self.socket.sendto (message, self.address) self.socket.sendto (message, self.address)
def encode_priority (self, facility, priority): def encode_priority (self, facility, priority):
if type(facility) == type(''): if type(facility) == type(''):
facility = facility_names[facility] facility = facility_names[facility]
if type(priority) == type(''): if type(priority) == type(''):
priority = priority_names[priority] priority = priority_names[priority]
return (facility<<3) | priority return (facility<<3) | priority
def close (self): def close (self):
if self.unix: if self.unix:
self.socket.close() self.socket.close()
if __name__ == '__main__': if __name__ == '__main__':
""" """
Unit test for syslog_client. Set up for the test by: Unit test for syslog_client. Set up for the test by:
* tail -f /var/log/allstuf (to see the "normal" log messages). * tail -f /var/log/allstuf (to see the "normal" log messages).
* Running the test_logger.py script with a junk file name (which * Running the test_logger.py script with a junk file name (which
will be opened as a Unix-domain socket). "Custom" log messages will be opened as a Unix-domain socket). "Custom" log messages
will go here. will go here.
* Run this script, passing the same junk file name. * Run this script, passing the same junk file name.
* Check that the "bogus" test throws, and that none of the rest do. * Check that the "bogus" test throws, and that none of the rest do.
* Check that the 'default' and 'UDP' messages show up in the tail. * Check that the 'default' and 'UDP' messages show up in the tail.
* Check that the 'non-std' message shows up in the test_logger * Check that the 'non-std' message shows up in the test_logger
console. console.
* Finally, kill off the tail and test_logger, and clean up the * Finally, kill off the tail and test_logger, and clean up the
socket file. socket file.
""" """
import sys, traceback import sys, traceback
...@@ -215,14 +215,14 @@ if __name__ == '__main__': ...@@ -215,14 +215,14 @@ if __name__ == '__main__':
def test_client( desc, address=None ): def test_client( desc, address=None ):
try: try:
if address: if address:
client = syslog_client( address ) client = syslog_client( address )
else: else:
client = syslog_client() client = syslog_client()
except: except:
print 'syslog_client() [%s] ctor threw' % desc print 'syslog_client() [%s] ctor threw' % desc
traceback.print_exc() traceback.print_exc()
return return
try: try:
client.log( 'testing syslog_client() [%s]' % desc client.log( 'testing syslog_client() [%s]' % desc
......
...@@ -368,7 +368,7 @@ def server_info(old, v, offset=0): ...@@ -368,7 +368,7 @@ def server_info(old, v, offset=0):
if v == '-': v='' if v == '-': v=''
l=string.find(v, ':') l=string.find(v, ':')
if l >= 0: if l >= 0:
a=v[:l] a=v[:l]
v=v[l+1:] v=v[l+1:]
else: else:
a=IP_ADDRESS a=IP_ADDRESS
...@@ -592,24 +592,24 @@ else: ...@@ -592,24 +592,24 @@ else:
if HTTP_PORT: if HTTP_PORT:
if type(HTTP_PORT) is type(0): HTTP_PORT=((IP_ADDRESS, HTTP_PORT),) if type(HTTP_PORT) is type(0): HTTP_PORT=((IP_ADDRESS, HTTP_PORT),)
for address, port in HTTP_PORT: for address, port in HTTP_PORT:
hs = zhttp_server( hs = zhttp_server(
ip=address, ip=address,
port=port, port=port,
resolver=rs, resolver=rs,
logger_object=lg) logger_object=lg)
# Handler for a published module. zhttp_handler takes 3 arguments: # Handler for a published module. zhttp_handler takes 3 arguments:
# The name of the module to publish, and optionally the URI base # The name of the module to publish, and optionally the URI base
# which is basically the SCIRPT_NAME, and optionally a dictionary # which is basically the SCIRPT_NAME, and optionally a dictionary
# with CGI environment variables which override default # with CGI environment variables which override default
# settings. The URI base setting is useful when you want to # settings. The URI base setting is useful when you want to
# publish more than one module with the same HTTP server. The CGI # publish more than one module with the same HTTP server. The CGI
# environment setting is useful when you want to proxy requests # environment setting is useful when you want to proxy requests
# from another web server to ZServer, and would like the CGI # from another web server to ZServer, and would like the CGI
# environment to reflect the CGI environment of the other web # environment to reflect the CGI environment of the other web
# server. # server.
zh = zhttp_handler(MODULE, '', HTTP_ENV) zh = zhttp_handler(MODULE, '', HTTP_ENV)
hs.install_handler(zh) hs.install_handler(zh)
# FTP Server # FTP Server
...@@ -618,7 +618,7 @@ if FTP_PORT: ...@@ -618,7 +618,7 @@ if FTP_PORT:
for address, port in FTP_PORT: for address, port in FTP_PORT:
FTPServer( FTPServer(
module=MODULE, module=MODULE,
ip=address, ip=address,
port=port, port=port,
resolver=rs, resolver=rs,
logger_object=lg) logger_object=lg)
...@@ -659,8 +659,8 @@ if MONITOR_PORT: ...@@ -659,8 +659,8 @@ if MONITOR_PORT:
from AccessControl.User import super from AccessControl.User import super
monitor=secure_monitor_server( monitor=secure_monitor_server(
password=super._getPassword(), password=super._getPassword(),
hostname=address, hostname=address,
port=port) port=port)
# Try to set uid to "-u" -provided uid. # Try to set uid to "-u" -provided uid.
# Try to set gid to "-u" user's primary group. # Try to set gid to "-u" user's primary group.
...@@ -675,7 +675,7 @@ try: ...@@ -675,7 +675,7 @@ try:
elif type(UID) == type(1): elif type(UID) == type(1):
uid = pwd.getpwuid(UID)[2] uid = pwd.getpwuid(UID)[2]
gid = pwd.getpwuid(UID)[3] gid = pwd.getpwuid(UID)[3]
else: else:
raise KeyError raise KeyError
try: try:
if gid is not None: if gid is not None:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment