Explicitly request GSSAPI delegation so zephyr subscribing works
[snippets/.git] / barn-growl / barn-growl.py
1 #!/usr/bin/env python
2
3 """
4 Subscribes to zephyr via tzc and sends messages to notification drivers (growl or libnotify).
5 """
6
7 import sexpr
8 import os
9 import subprocess
10 import fcntl
11 import select
12 import sys
13 from abstfilter import AbstractConsumer
14 import optparse
15 import time
16
17 class Notifier(AbstractConsumer):
18     def __init__(self, usegrowl, usenotify, useprint):
19         self.usegrowl = usegrowl
20         self.usenotify = usenotify
21         if usenotify:
22             import pynotify
23             pynotify.init("Zephyr")
24             self.pings = {}
25             self.pynotify = pynotify
26         self.useprint = useprint
27         return
28     def feed(self, s):
29         if s is None or type(s) is type(''): return
30         d = dict([(ss[0], len(ss) > 2 and ss[2] or None) for ss in s])
31         if d['tzcspew'] == 'message':
32             zclass = d['class'].lower()
33             zinstance = d['instance'].lower()
34             zop = d['opcode'].lower()
35             zsender = d['sender'].lower()
36             zauth = d['auth'].lower() == 'yes'
37             ztime = "%02d:%02d" % time.strptime(d['time'])[3:5]
38             zmessage = d['message']
39             idtuple = (zclass, zinstance, zsender, ztime)
40             id = '%s/\n%s/\n%s\n %s' % idtuple
41             if zop == 'ping':
42                 header = '%s (%s)' % (id, zsender)
43                 message = '...'
44             elif zop == 'nil':
45                 header = '%s (%s)' % (id, len(zmessage) > 0 and zmessage[0] or zsender)
46                 message = '%s' % (len(zmessage) > 1 and zmessage[1] or '')
47             else:
48                 return
49             if self.useprint:
50                 print (id, header)
51                 print message
52             if self.usegrowl:
53                 growlnotify = ['growlnotify', '-a', 'MacZephyr', '-n', 'zephyr', '-d', id, '-t', header]
54                 g = subprocess.Popen(growlnotify, stdin=subprocess.PIPE)
55                 g.stdin.write(message)
56                 g.stdin.close()
57             if self.usenotify:
58                 if idtuple in self.pings:
59                     self.pings[idtuple].update(header, message)
60                     self.pings[idtuple].show()
61                 else:
62                     n = self.pynotify.Notification(header, message)
63                     n.show()
64                     if zop == 'ping':
65                         self.pings[idtuple] = n
66                 self.pings = dict(filter(lambda ((c, i, s, time), v): time == idtuple[3], self.pings.items()))
67     def close(self):
68         return
69
70 def main(argv):
71     parser = optparse.OptionParser(usage = '%prog [-s "username@machine"] (--growl | --notify | --print)',
72             description = __doc__.strip())
73     parser.add_option('-s', '--ssh',
74             type = 'string',
75             default = None,
76             dest = 'ssh',
77             help = 'optional remote host to run tzc')
78     parser.add_option('-g', '--growl',
79             action = 'store_true',
80             default = False,
81             dest = 'growl',
82             help = 'use growlnotify for output')
83     parser.add_option('-n', '--notify',
84             action = 'store_true',
85             default = False,
86             dest = 'notify',
87             help = 'use notify-send for output')
88     parser.add_option('-p', '--print',
89             action = 'store_true',
90             default = False,
91             dest = 'useprint',
92             help = 'use stdout for output')
93     opts, args = parser.parse_args()
94
95     usegrowl = opts.growl
96     usenotify = opts.notify
97     useprint = opts.useprint
98     if not usegrowl and not usenotify and not useprint:
99         parser.print_help(sys.stderr)
100         return 1
101     ssh = opts.ssh
102
103     if ssh is None:
104         retval = subprocess.call(['which', 'tzc'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
105         if retval:
106             print 'tzc not in path.  Please add -s username@machine to specify remote host.'
107             return 1
108
109     if ssh is not None:
110         command = "ssh -o GSSAPIAuthentication=yes -o GSSAPIDelegateCredentials=yes -o GSSAPIKeyExchange=yes %s 'tzc -si'" % ssh
111     else:
112         command = "tzc -si"
113     p = os.popen(command)
114     r = sexpr.SExprReader(Notifier(usegrowl, usenotify, useprint))
115
116     flags = fcntl.fcntl(p, fcntl.F_GETFL)
117     fcntl.fcntl(p, fcntl.F_SETFL, flags | os.O_NONBLOCK)
118
119     try:
120         while 1:
121             [i,o,e] = select.select([p], [], [], 5)
122             if i: s = p.read(1024)
123             else: s = ''
124
125             if s != '':
126                 r.feed(s)
127     except KeyboardInterrupt:
128         pass
129     return 0
130
131 if __name__ == "__main__":
132     sys.exit(main(sys.argv))