cleanup specfile for packaging
[profile/ivi/gpsd.git] / gpsd.hotplug
1 #!/usr/bin/python
2 #
3 # This file is Copyright (c) 2010 by the GPSD project
4 # BSD terms apply: see the file COPYING in the distribution root for details.
5 #
6 # Hotplug script for gpsd by Eric S. Raymond, March 2005
7 # This script is part of the gpsd distribution: see http://gpsd.berlios.de
8 # Can be called like "gpsd.hotplug [add|remove] /dev/ttyUSB0" for test
9 # purposes.
10 import sys, time, os, syslog, glob, socket, stat
11
12 CONTROL_SOCKET = os.getenv('GPSD_SOCKET') or "/var/run/gpsd.sock"
13 GPSD_OPTIONS = os.getenv('GPSD_OPTIONS') or ""
14
15 WHEREAMI = __file__
16
17 def gpsd_control_connect():
18     "Acquire a connection to the GPSD control socket."
19     if not os.path.exists(CONTROL_SOCKET):
20         syslog.syslog("socket %s doesn't exist" % CONTROL_SOCKET)
21         return None
22     try:
23         sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
24         sock.connect(CONTROL_SOCKET)
25     except socket.error, msg:
26         syslog.syslog("socket %s creation failure: %s" % (CONTROL_SOCKET, msg))
27         if sock:
28             sock.close()
29         sock = None
30     #else:
31     #    syslog.syslog("socket %s created OK" % CONTROL_SOCKET)
32     return sock
33
34 def gpsd_control(action, argument):
35     "Pass a command to gpsd; start the daemon if not already running."
36     syslog.syslog("gpsd_control(action=%s, arg=%s)" % (action, argument))
37     connect = gpsd_control_connect()
38     if connect:
39         syslog.syslog("reached a running gpsd")
40     elif action == 'add':
41         gpsdcmd = "gpsd %s -F %s" % (GPSD_OPTIONS, CONTROL_SOCKET)
42         syslog.syslog("launching %s" % gpsdcmd)
43         os.system(gpsdcmd)
44         connect = gpsd_control_connect()
45     if not connect:
46         syslog.syslog("can't reach gpsd")
47         return None
48     # We've got a live connection to the gpsd control socket.  No
49     # need to parse the response, because gpsd will lock on to the
50     # device if it's really a GPS and ignore it if it's not.
51     if action == 'add':
52         # Force the group-read & group-write bits on, so gpsd will still be
53         # able to use this device after dropping root privileges.
54         os.chmod(argument, stat.S_IMODE(os.stat(argument)[stat.ST_MODE])|0660)
55         connect.sendall("+%s\r\n" % argument)
56         connect.recv(12)
57     elif action == 'remove':
58         connect.sendall("-%s\r\n" % argument)
59         connect.recv(12)
60     elif action == 'send':
61         connect.sendall("%s\r\n" % argument)
62         connect.recv(12)
63     connect.close()
64     #syslog.syslog("gpsd_control ends")
65     return action
66
67 def hotplug(action, devpath):
68     #syslog.syslog("ACTION=%s DEVPATH=%s" % (action,devpath))
69     if not devpath:
70         syslog.syslog("No device")
71     else:
72         subnodes = glob.glob("/sys" + devpath + "/*")
73         subnodes = map(os.path.basename, subnodes)
74         subnodes = filter(lambda s: s.startswith("ttyUSB"), subnodes) 
75         if len(subnodes) == 0:
76             syslog.syslog("no ttyUSB device under " + devpath)
77             return
78         elif len(subnodes) > 1:
79             syslog.syslog("too many ttyUSB devices under " + devpath)
80             return
81         else:
82             tty = "/dev/" + subnodes[0]
83
84             syslog.syslog("waiting for " + tty)
85             while not os.path.exists(tty):
86                 time.sleep(1)
87             syslog.syslog(tty + " has gone active")
88
89             gpsd_control(action, tty)
90
91             remover = os.getenv("REMOVER")
92             #syslog.syslog("REMOVER=%s" % remover)
93             fp = open(remover, "w")
94             fp.write(WHEREAMI + " remove " + tty)
95             fp.close()
96             os.chmod(remover, stat.S_IRUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP)
97             return
98
99 if __name__ == '__main__':
100     # In recent versions of udev, the gpsd script runs in series with
101     # the task that creates the real /dev/ttyUSB0 device
102     # node. Unfortunately, the gpsd script runs BEFORE the creation of
103     # the node, and the node is not created until after you kill the
104     # gpsd script, because the gpsd script waits forever for the node
105     # to appear.
106     # 
107     # This is a race condition, and is best fixed by running the
108     # actual wait/hotplug portion in the background.
109     pid = os.fork()
110     if not pid:
111         syslog.openlog('gpsd.hotplug', 0, syslog.LOG_DAEMON)
112         try: 
113             if len(sys.argv) == 1:      # Called as hotplug script
114                 hotplug(os.getenv("ACTION"), os.getenv("DEVPATH"))
115             else:                       # Called by hand for testing
116                 gpsd_control(sys.argv[1], sys.argv[2])
117         except:
118             (exc_type, exc_value, exc_traceback) = sys.exc_info()
119             syslog.syslog("gpsd.hotplug: exception %s yields %s" % (exc_type, exc_value))
120             raise exc_type, exc_value, exc_traceback
121         #syslog.syslog("gpsd.hotplug ends")
122         syslog.closelog()
123