| Home | Trees | Indices | Help |
|
|---|
|
|
1 __doc__ = """GNUmed general tools."""
2
3 #===========================================================================
4 __version__ = "$Revision: 1.13 $"
5 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
6 __license__ = "GPL (details at http://www.gnu.org)"
7
8
9 # stdlib
10 import os, sys, logging
11
12
13 _log = logging.getLogger('gm.shell')
14 _log.info(__version__)
15
16 #===========================================================================
18 _log.debug('detecting [%s]', binary)
19
20 # is it a sufficiently qualified path ?
21 if os.access(binary, os.X_OK):
22 return (True, binary)
23
24 # try "which" to find the full path
25 cmd = 'which %s' % binary
26 pipe = os.popen(cmd.encode(sys.getfilesystemencoding()), "r")
27 result = pipe.readline()
28 ret_code = pipe.close()
29 if ret_code is not None:
30 _log.debug('[%s] failed, exit code: %s', cmd, ret_code)
31 else:
32 result = result.strip('\r\n')
33 _log.debug('[%s] returned: %s', cmd, result)
34 # redundant on Linux but apparently necessary on MacOSX
35 if os.access(result, os.X_OK):
36 return (True, result)
37 else:
38 _log.debug('[%s] not detected with "which"', binary)
39
40 # consider "d/m/s/locate" to find the full path
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 _log.debug('looking for [%s]', cmd)
77
78 if cmd is None:
79 continue
80
81 found, binary = detect_external_binary(binary = cmd)
82 if found:
83 break
84
85 return (found, binary)
86 #===========================================================================
88 """Runs a command in a subshell via standard-C system().
89
90 <command>
91 The shell command to run including command line options.
92 <blocking>
93 This will make the code *block* until the shell command exits.
94 It will likely only work on UNIX shells where "cmd &" makes sense.
95 """
96 if acceptable_return_codes is None:
97 acceptable_return_codes = [0]
98
99 _log.debug('shell command >>>%s<<<', command)
100 _log.debug('blocking: %s', blocking)
101 _log.debug('acceptable return codes: %s', str(acceptable_return_codes))
102
103 # FIXME: command should be checked for shell exploits
104 command = command.strip()
105
106 # what the following hack does is this: the user indicated
107 # whether she wants non-blocking external display of files
108 # - the real way to go about this is to have a non-blocking command
109 # in the line in the mailcap file for the relevant mime types
110 # - as non-blocking may not be desirable when *not* displaying
111 # files from within GNUmed the really right way would be to
112 # add a "test" clause to the non-blocking mailcap entry which
113 # yields true if and only if GNUmed is running
114 # - however, this is cumbersome at best and not supported in
115 # some mailcap implementations
116 # - so we allow the user to attempt some control over the process
117 # from within GNUmed by setting a configuration option
118 # - leaving it None means to use the mailcap default or whatever
119 # was specified in the command itself
120 # - True means: tack " &" onto the shell command if necessary
121 # - False means: remove " &" from the shell command if its there
122 # - all this, of course, only works in shells which support
123 # detaching jobs with " &" (so, most POSIX shells)
124 if blocking is True:
125 if command[-2:] == ' &':
126 command = command[:-2]
127 elif blocking is False:
128 if command[-2:] != ' &':
129 command += ' &'
130
131 _log.info('running shell command >>>%s<<<', command)
132 # FIXME: use subprocess.Popen()
133 ret_val = os.system(command.encode(sys.getfilesystemencoding()))
134 _log.debug('os.system() returned: [%s]', ret_val)
135
136 exited_normally = False
137
138 if not hasattr(os, 'WIFEXITED'):
139 _log.debug('platform does not support exit status differentiation')
140 return exited_normally
141
142 _log.debug('exited via exit(): %s', os.WIFEXITED(ret_val))
143 if os.WIFEXITED(ret_val):
144 _log.debug('exit code: [%s]', os.WEXITSTATUS(ret_val))
145 exited_normally = (os.WEXITSTATUS(ret_val) in acceptable_return_codes)
146 _log.debug('normal exit: %s', exited_normally)
147 _log.debug('dumped core: %s', os.WCOREDUMP(ret_val))
148 _log.debug('stopped by signal: %s', os.WIFSIGNALED(ret_val))
149 if os.WIFSIGNALED(ret_val):
150 _log.debug('STOP signal was: [%s]', os.STOPSIG(ret_val))
151 _log.debug('TERM signal was: [%s]', os.TERMSIG(ret_val))
152
153 return exited_normally
154 #===========================================================================
155 -def run_first_available_in_shell(binaries=None, args=None, blocking=False, run_last_one_anyway=False, acceptable_return_codes=None):
156
157 found, binary = find_first_binary(binaries = binaries)
158
159 if not found:
160 if run_last_one_anyway:
161 binary = binaries[-1]
162 else:
163 _log.warning('cannot find any of: %s', binaries)
164 return False
165
166 return run_command_in_shell(command = '%s %s' % (binary, args), blocking = blocking, acceptable_return_codes = acceptable_return_codes)
167 #===========================================================================
168 # main
169 #---------------------------------------------------------------------------
170 if __name__ == '__main__':
171
172 if len(sys.argv) < 2:
173 sys.exit()
174
175 if sys.argv[1] != u'test':
176 sys.exit()
177
178 logging.basicConfig(level = logging.DEBUG)
179 #---------------------------------------------------------
181 found, path = detect_external_binary(binary = sys.argv[2])
182 if found:
183 print "found as:", path
184 else:
185 print sys.argv[2], "not found"
186 #---------------------------------------------------------
188 print "-------------------------------------"
189 print "running:", sys.argv[2]
190 if run_command_in_shell(command=sys.argv[2], blocking=True):
191 print "-------------------------------------"
192 print "success"
193 else:
194 print "-------------------------------------"
195 print "failure, consult log"
196 #---------------------------------------------------------
197 test_run_command_in_shell()
198 #test_detect_external_binary()
199
200 #===========================================================================
201
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Tue Apr 12 03:59:04 2011 | http://epydoc.sourceforge.net |