1#
2# This file is part of pysnmp software.
3#
4# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
5# License: http://snmplabs.com/pysnmp/license.html
6#
7import logging
8from pyasn1.compat.octets import octs2ints
9from pysnmp import error
10from pysnmp import __version__
11
12flagNone = 0x0000
13flagIO = 0x0001
14flagDsp = 0x0002
15flagMP = 0x0004
16flagSM = 0x0008
17flagBld = 0x0010
18flagMIB = 0x0020
19flagIns = 0x0040
20flagACL = 0x0080
21flagPrx = 0x0100
22flagApp = 0x0200
23flagAll = 0xffff
24
25flagMap = {'io': flagIO,
26           'dsp': flagDsp,
27           'msgproc': flagMP,
28           'secmod': flagSM,
29           'mibbuild': flagBld,
30           'mibview': flagMIB,
31           'mibinstrum': flagIns,
32           'acl': flagACL,
33           'proxy': flagPrx,
34           'app': flagApp,
35           'all': flagAll}
36
37
38class Printer(object):
39    def __init__(self, logger=None, handler=None, formatter=None):
40        if logger is None:
41            logger = logging.getLogger('pysnmp')
42        logger.setLevel(logging.DEBUG)
43        if handler is None:
44            handler = logging.StreamHandler()
45        if formatter is None:
46            formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')
47        handler.setFormatter(formatter)
48        handler.setLevel(logging.DEBUG)
49        logger.addHandler(handler)
50        self.__logger = logger
51
52    def __call__(self, msg):
53        self.__logger.debug(msg)
54
55    def __str__(self):
56        return '<python built-in logging>'
57
58
59if hasattr(logging, 'NullHandler'):
60    NullHandler = logging.NullHandler
61else:
62    # Python 2.6 and older
63    class NullHandler(logging.Handler):
64        def emit(self, record):
65            pass
66
67
68class Debug(object):
69    defaultPrinter = None
70
71    def __init__(self, *flags, **options):
72        self._flags = flagNone
73        if options.get('printer') is not None:
74            self._printer = options.get('printer')
75        elif self.defaultPrinter is not None:
76            self._printer = self.defaultPrinter
77        else:
78            if 'loggerName' in options:
79                # route our logs to parent logger
80                self._printer = Printer(
81                    logger=logging.getLogger(options['loggerName']),
82                    handler=NullHandler()
83                )
84            else:
85                self._printer = Printer()
86        self('running pysnmp version %s' % __version__)
87        for f in flags:
88            inverse = f and f[0] in ('!', '~')
89            if inverse:
90                f = f[1:]
91            try:
92                if inverse:
93                    self._flags &= ~flagMap[f]
94                else:
95                    self._flags |= flagMap[f]
96            except KeyError:
97                raise error.PySnmpError('bad debug flag %s' % f)
98
99            self('debug category \'%s\' %s' % (f, inverse and 'disabled' or 'enabled'))
100
101    def __str__(self):
102        return 'logger %s, flags %x' % (self._printer, self._flags)
103
104    def __call__(self, msg):
105        self._printer(msg)
106
107    def __and__(self, flag):
108        return self._flags & flag
109
110    def __rand__(self, flag):
111        return flag & self._flags
112
113
114# This will yield false from bitwise and with a flag, and save
115# on unnecessary calls
116logger = 0
117
118
119def setLogger(l):
120    global logger
121    logger = l
122
123
124def hexdump(octets):
125    return ' '.join(
126        ['%s%.2X' % (n % 16 == 0 and ('\n%.5d: ' % n) or '', x) for n, x in zip(range(len(octets)), octs2ints(octets))])
127