| Trees | Indices | Help |
|
|---|
|
|
1 __doc__ = """GNUmed general tools."""
2
3 #===========================================================================
4 # $Id: gmShellAPI.py,v 1.13 2010/01/11 22:03:08 ncq Exp $
5 # $Source: /cvsroot/gnumed/gnumed/gnumed/client/pycommon/gmShellAPI.py,v $
6 __version__ = "$Revision: 1.13 $"
7 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
8 __license__ = "GPL (details at http://www.gnu.org)"
9
10
11 # stdlib
12 import os, sys, logging
13
14
15 _log = logging.getLogger('gm.shell')
16 _log.info(__version__)
17
18 #===========================================================================
20 _log.debug('detecting [%s]', binary)
21
22 # is it a sufficiently qualified path ?
23 if os.access(binary, os.X_OK):
24 return (True, binary)
25
26 # maybe we are on UNIX and should use "which" to find the full path ?
27 cmd = 'which %s' % binary
28 pipe = os.popen(cmd.encode(sys.getfilesystemencoding()), "r")
29 result = pipe.readline()
30 ret_code = pipe.close()
31 if ret_code is not None:
32 _log.debug('[%s] failed, exit code: %s', cmd, ret_code)
33 else:
34 result = result.strip('\r\n')
35 _log.debug('[%s] returned: %s', cmd, result)
36 # redundant on Linux but apparently necessary on MacOSX
37 if os.access(result, os.X_OK):
38 return (True, result)
39 else:
40 _log.debug('[%s] not detected with "which"', binary)
41
42 tmp = binary.lstrip()
43 # to be run by wine ?
44 if tmp.startswith('wine'):
45
46 tmp = tmp[4:].strip().strip('"')
47
48 # "wine /standard/unix/path/to/binary" ?
49 if os.access(tmp, os.R_OK):
50 _log.debug('wine call with UNIX path')
51 return (True, binary)
52
53 # 'wine "drive:\a\windows\path\to\binary"' ?
54 cmd = 'winepath -u "%s"' % tmp
55 pipe = os.popen(cmd.encode(sys.getfilesystemencoding()), "r")
56 result = pipe.readline()
57 ret_code = pipe.close()
58 if ret_code is not None:
59 _log.debug('winepath failed')
60 else:
61 result = result.strip('\r\n')
62 if os.access(result, os.R_OK):
63 _log.debug('wine call with Windows path')
64 return (True, binary)
65 else:
66 _log.warning('"winepath -u %s" returned [%s] but the UNIX path is not verifiable', tmp, result)
67
68 return (False, None)
69 #===========================================================================
71
72 found = False
73 binary = None
74
75 for cmd in binaries:
76 found, binary = detect_external_binary(binary = cmd)
77 if found:
78 break
79
80 return (found, binary)
81 #===========================================================================
83 """Runs a command in a subshell via standard-C system().
84
85 <command>
86 The shell command to run including command line options.
87 <blocking>
88 This will make the code *block* until the shell command exits.
89 It will likely only work on UNIX shells where "cmd &" makes sense.
90 """
91 _log.debug('shell command >>>%s<<<', command)
92 _log.debug('blocking: %s', blocking)
93
94 # FIXME: command should be checked for shell exploits
95 command = command.strip()
96
97 # what the following hack does is this: the user indicated
98 # whether she wants non-blocking external display of files
99 # - the real way to go about this is to have a non-blocking command
100 # in the line in the mailcap file for the relevant mime types
101 # - as non-blocking may not be desirable when *not* displaying
102 # files from within GNUmed the really right way would be to
103 # add a "test" clause to the non-blocking mailcap entry which
104 # yields true if and only if GNUmed is running
105 # - however, this is cumbersome at best and not supported in
106 # some mailcap implementations
107 # - so we allow the user to attempt some control over the process
108 # from within GNUmed by setting a configuration option
109 # - leaving it None means to use the mailcap default or whatever
110 # was specified in the command itself
111 # - True means: tack " &" onto the shell command if necessary
112 # - False means: remove " &" from the shell command if its there
113 # - all this, of course, only works in shells which support
114 # detaching jobs with " &" (so, most POSIX shells)
115 if blocking is True:
116 if command[-2:] == ' &':
117 command = command[:-2]
118 elif blocking is False:
119 if command[-2:] != ' &':
120 command += ' &'
121
122 _log.info('running shell command >>>%s<<<', command)
123 # FIXME: use subprocess.Popen()
124 ret_val = os.system(command.encode(sys.getfilesystemencoding()))
125 _log.debug('os.system() returned: [%s]', ret_val)
126
127 exited_normally = False
128 _log.debug('exited via exit(): %s', os.WIFEXITED(ret_val))
129 if os.WIFEXITED(ret_val):
130 _log.debug('exit code: [%s]', os.WEXITSTATUS(ret_val))
131 exited_normally = (os.WEXITSTATUS(ret_val) == 0)
132 _log.debug('normal exit: %s', exited_normally)
133 _log.debug('dumped core: %s', os.WCOREDUMP(ret_val))
134 _log.debug('stopped by signal: %s', os.WIFSIGNALED(ret_val))
135 if os.WIFSIGNALED(ret_val):
136 _log.debug('STOP signal was: [%s]', os.STOPSIG(ret_val))
137 _log.debug('TERM signal was: [%s]', os.TERMSIG(ret_val))
138
139 return exited_normally
140 #===========================================================================
141 -def run_first_available_in_shell(binaries=None, args=None, blocking=False, run_last_one_anyway=False):
142
143 found, binary = find_first_binary(binaries = binaries)
144
145 if not found:
146 if run_last_one_anyway:
147 binary = binaries[-1]
148 else:
149 _log.warning('cannot find any of: %s', binaries)
150 return False
151
152 return run_command_in_shell(command = '%s %s' % (binary, args), blocking=False)
153 #===========================================================================
154 # main
155 #---------------------------------------------------------------------------
156 if __name__ == '__main__':
157
158 if len(sys.argv) > 1 and sys.argv[1] == u'test':
159
160 logging.basicConfig(level = logging.DEBUG)
161
162 #---------------------------------------------------------
164 found, path = detect_external_binary(binary = sys.argv[2])
165 if found:
166 print "found as:", path
167 else:
168 print sys.argv[2], "not found"
169 #---------------------------------------------------------
171 print "-------------------------------------"
172 print "running:", sys.argv[2]
173 if run_command_in_shell(command=sys.argv[2], blocking=True):
174 print "-------------------------------------"
175 print "success"
176 else:
177 print "-------------------------------------"
178 print "failure, consult log"
179 #---------------------------------------------------------
180
181 #test_run_command_in_shell()
182 test_detect_external_binary()
183
184 #===========================================================================
185 # $Log: gmShellAPI.py,v $
186 # Revision 1.13 2010/01/11 22:03:08 ncq
187 # - comment
188 #
189 # Revision 1.12 2010/01/03 18:16:11 ncq
190 # - find-first-binary
191 # - run-first-available-in-shell
192 #
193 # Revision 1.11 2010/01/01 21:20:01 ncq
194 # - much better logging
195 #
196 # Revision 1.10 2009/04/20 11:39:41 ncq
197 # - properly detect binaries run by Wine
198 #
199 # Revision 1.9 2008/12/09 23:26:12 ncq
200 # - improved logging
201 #
202 # Revision 1.8 2008/03/06 21:25:41 ncq
203 # - optimize detect_external_binary() for the common case
204 #
205 # Revision 1.7 2008/03/06 18:48:21 ncq
206 # - much improved wine-based executable detection
207 #
208 # Revision 1.6 2008/03/02 15:09:35 ncq
209 # - smarten up detect_external_binary about winepath
210 #
211 # Revision 1.5 2008/01/14 20:30:11 ncq
212 # - detect_external_binary()
213 # - better tests
214 #
215 # Revision 1.4 2007/12/12 16:17:16 ncq
216 # - better logger names
217 #
218 # Revision 1.3 2007/12/11 14:33:48 ncq
219 # - use standard logging module
220 #
221 # Revision 1.2 2007/03/31 21:20:34 ncq
222 # - os.system() needs encoded commands
223 #
224 # Revision 1.1 2006/12/23 13:17:32 ncq
225 # - new API
226 #
227
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Tue Feb 9 04:02:35 2010 | http://epydoc.sourceforge.net |