| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | """distutils.spawn
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Provides the 'spawn()' function, a front-end to various platform- | 
					
						
							| 
									
										
										
										
											2000-08-02 01:08:02 +00:00
										 |  |  | specific functions for launching another program in a sub-process. | 
					
						
							|  |  |  | Also provides the 'find_executable()' to search the path for a given | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  | executable name. | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-19 13:12:28 +00:00
										 |  |  | # This module should be kept compatible with Python 1.5.2. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-02 01:49:45 +00:00
										 |  |  | __revision__ = "$Id$" | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import sys, os, string | 
					
						
							|  |  |  | from distutils.errors import * | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  | from distutils import log | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def spawn (cmd, | 
					
						
							|  |  |  |            search_path=1, | 
					
						
							|  |  |  |            verbose=0, | 
					
						
							|  |  |  |            dry_run=0): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """Run another program, specified as a command list 'cmd', in a new
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |     process.  'cmd' is just the argument list for the new process, ie. | 
					
						
							|  |  |  |     cmd[0] is the program to run and cmd[1:] are the rest of its arguments. | 
					
						
							|  |  |  |     There is no way to run a program with a name different from that of its | 
					
						
							|  |  |  |     executable. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-21 20:41:07 +00:00
										 |  |  |     If 'search_path' is true (the default), the system's executable | 
					
						
							|  |  |  |     search path will be used to find the program; otherwise, cmd[0] | 
					
						
							|  |  |  |     must be the exact path to the executable.  If 'dry_run' is true, | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |     the command will not actually be run. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Raise DistutilsExecError if running the program fails in any way; just | 
					
						
							|  |  |  |     return on success. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |     if os.name == 'posix': | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |         _spawn_posix(cmd, search_path, dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											1999-09-08 02:23:28 +00:00
										 |  |  |     elif os.name == 'nt': | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |         _spawn_nt(cmd, search_path, dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											2002-01-31 18:56:00 +00:00
										 |  |  |     elif os.name == 'os2': | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |         _spawn_os2(cmd, search_path, dry_run=dry_run) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         raise DistutilsPlatformError, \ | 
					
						
							|  |  |  |               "don't know how to spawn programs on platform '%s'" % os.name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # spawn () | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-09-08 02:23:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-07 03:25:20 +00:00
										 |  |  | def _nt_quote_args (args): | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |     """Quote command-line arguments for DOS/Windows conventions: just
 | 
					
						
							|  |  |  |     wraps every argument which contains blanks in double quotes, and | 
					
						
							|  |  |  |     returns a new argument list. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2000-03-07 03:25:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # XXX this doesn't seem very robust to me -- but if the Windows guys | 
					
						
							|  |  |  |     # say it'll work, I guess I'll have to accept it.  (What if an arg | 
					
						
							|  |  |  |     # contains quotes?  What other magic characters, other than spaces, | 
					
						
							|  |  |  |     # have to be escaped?  Is there an escaping mechanism other than | 
					
						
							|  |  |  |     # quoting?) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |     for i in range(len(args)): | 
					
						
							|  |  |  |         if string.find(args[i], ' ') != -1: | 
					
						
							| 
									
										
										
										
											2000-03-07 03:25:20 +00:00
										 |  |  |             args[i] = '"%s"' % args[i] | 
					
						
							| 
									
										
										
										
											2000-03-26 21:47:00 +00:00
										 |  |  |     return args | 
					
						
							| 
									
										
										
										
											2000-03-07 03:25:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def _spawn_nt (cmd, | 
					
						
							|  |  |  |                search_path=1, | 
					
						
							|  |  |  |                verbose=0, | 
					
						
							|  |  |  |                dry_run=0): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-08-29 18:20:56 +00:00
										 |  |  |     executable = cmd[0] | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |     cmd = _nt_quote_args(cmd) | 
					
						
							| 
									
										
										
										
											1999-08-29 18:20:56 +00:00
										 |  |  |     if search_path: | 
					
						
							| 
									
										
										
										
											2000-08-02 01:08:02 +00:00
										 |  |  |         # either we find one or it stays the same | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  |         executable = find_executable(executable) or executable | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     log.info(string.join([executable] + cmd[1:], ' ')) | 
					
						
							| 
									
										
										
										
											1999-08-29 18:20:56 +00:00
										 |  |  |     if not dry_run: | 
					
						
							|  |  |  |         # spawn for NT requires a full path to the .exe | 
					
						
							| 
									
										
										
										
											2000-01-17 21:57:55 +00:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |             rc = os.spawnv(os.P_WAIT, executable, cmd) | 
					
						
							| 
									
										
										
										
											2000-01-17 21:57:55 +00:00
										 |  |  |         except OSError, exc: | 
					
						
							|  |  |  |             # this seems to happen when the command isn't found | 
					
						
							|  |  |  |             raise DistutilsExecError, \ | 
					
						
							|  |  |  |                   "command '%s' failed: %s" % (cmd[0], exc[-1]) | 
					
						
							| 
									
										
										
										
											1999-08-29 18:20:56 +00:00
										 |  |  |         if rc != 0: | 
					
						
							| 
									
										
										
										
											2000-01-17 21:57:55 +00:00
										 |  |  |             # and this reflects the command running but failing | 
					
						
							|  |  |  |             raise DistutilsExecError, \ | 
					
						
							|  |  |  |                   "command '%s' failed with exit status %d" % (cmd[0], rc) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-01-31 18:56:00 +00:00
										 |  |  | def _spawn_os2 (cmd, | 
					
						
							|  |  |  |                 search_path=1, | 
					
						
							|  |  |  |                 verbose=0, | 
					
						
							|  |  |  |                 dry_run=0): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     executable = cmd[0] | 
					
						
							|  |  |  |     #cmd = _nt_quote_args(cmd) | 
					
						
							|  |  |  |     if search_path: | 
					
						
							|  |  |  |         # either we find one or it stays the same | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         executable = find_executable(executable) or executable | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     log.info(string.join([executable] + cmd[1:], ' ')) | 
					
						
							| 
									
										
										
										
											2002-01-31 18:56:00 +00:00
										 |  |  |     if not dry_run: | 
					
						
							|  |  |  |         # spawnv for OS/2 EMX requires a full path to the .exe | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             rc = os.spawnv(os.P_WAIT, executable, cmd) | 
					
						
							|  |  |  |         except OSError, exc: | 
					
						
							|  |  |  |             # this seems to happen when the command isn't found | 
					
						
							|  |  |  |             raise DistutilsExecError, \ | 
					
						
							|  |  |  |                   "command '%s' failed: %s" % (cmd[0], exc[-1]) | 
					
						
							|  |  |  |         if rc != 0: | 
					
						
							|  |  |  |             # and this reflects the command running but failing | 
					
						
							|  |  |  |             print "command '%s' failed with exit status %d" % (cmd[0], rc) | 
					
						
							|  |  |  |             raise DistutilsExecError, \ | 
					
						
							|  |  |  |                   "command '%s' failed with exit status %d" % (cmd[0], rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | def _spawn_posix (cmd, | 
					
						
							|  |  |  |                   search_path=1, | 
					
						
							|  |  |  |                   verbose=0, | 
					
						
							|  |  |  |                   dry_run=0): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-04 20:14:43 +00:00
										 |  |  |     log.info(string.join(cmd, ' ')) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |     if dry_run: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     exec_fn = search_path and os.execvp or os.execv | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |     pid = os.fork() | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if pid == 0:                        # in the child | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             #print "cmd[0] =", cmd[0] | 
					
						
							|  |  |  |             #print "cmd =", cmd | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |             exec_fn(cmd[0], cmd) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |         except OSError, e: | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |             sys.stderr.write("unable to execute %s: %s\n" % | 
					
						
							|  |  |  |                              (cmd[0], e.strerror)) | 
					
						
							|  |  |  |             os._exit(1) | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |         sys.stderr.write("unable to execute %s for unknown reasons" % cmd[0]) | 
					
						
							|  |  |  |         os._exit(1) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |     else:                               # in the parent | 
					
						
							|  |  |  |         # Loop until the child either exits or is terminated by a signal | 
					
						
							|  |  |  |         # (ie. keep waiting if it's merely stopped) | 
					
						
							|  |  |  |         while 1: | 
					
						
							| 
									
										
										
										
											2004-02-24 23:54:17 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 (pid, status) = os.waitpid(pid, 0) | 
					
						
							|  |  |  |             except OSError, exc: | 
					
						
							|  |  |  |                 import errno | 
					
						
							|  |  |  |                 if exc.errno == errno.EINTR: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 raise DistutilsExecError, \ | 
					
						
							|  |  |  |                       "command '%s' failed: %s" % (cmd[0], exc[-1]) | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |             if os.WIFSIGNALED(status): | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |                 raise DistutilsExecError, \ | 
					
						
							| 
									
										
										
										
											2000-01-17 21:57:55 +00:00
										 |  |  |                       "command '%s' terminated by signal %d" % \ | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |                       (cmd[0], os.WTERMSIG(status)) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |             elif os.WIFEXITED(status): | 
					
						
							|  |  |  |                 exit_status = os.WEXITSTATUS(status) | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |                 if exit_status == 0: | 
					
						
							|  |  |  |                     return              # hey, it succeeded! | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     raise DistutilsExecError, \ | 
					
						
							| 
									
										
										
										
											2000-01-17 21:57:55 +00:00
										 |  |  |                           "command '%s' failed with exit status %d" % \ | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |                           (cmd[0], exit_status) | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-26 02:00:51 +00:00
										 |  |  |             elif os.WIFSTOPPED(status): | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 raise DistutilsExecError, \ | 
					
						
							| 
									
										
										
										
											2000-01-17 21:57:55 +00:00
										 |  |  |                       "unknown error executing '%s': termination status %d" % \ | 
					
						
							| 
									
										
										
										
											1999-08-14 23:57:17 +00:00
										 |  |  |                       (cmd[0], status) | 
					
						
							|  |  |  | # _spawn_posix () | 
					
						
							| 
									
										
										
										
											2000-08-02 01:08:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def find_executable(executable, path=None): | 
					
						
							|  |  |  |     """Try to find 'executable' in the directories listed in 'path' (a
 | 
					
						
							|  |  |  |     string listing directories separated by 'os.pathsep'; defaults to | 
					
						
							|  |  |  |     os.environ['PATH']).  Returns the complete filename or None if not | 
					
						
							|  |  |  |     found. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if path is None: | 
					
						
							|  |  |  |         path = os.environ['PATH'] | 
					
						
							|  |  |  |     paths = string.split(path, os.pathsep) | 
					
						
							|  |  |  |     (base, ext) = os.path.splitext(executable) | 
					
						
							| 
									
										
										
										
											2002-01-31 18:56:00 +00:00
										 |  |  |     if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'): | 
					
						
							| 
									
										
										
										
											2000-08-02 01:08:02 +00:00
										 |  |  |         executable = executable + '.exe' | 
					
						
							|  |  |  |     if not os.path.isfile(executable): | 
					
						
							|  |  |  |         for p in paths: | 
					
						
							|  |  |  |             f = os.path.join(p, executable) | 
					
						
							|  |  |  |             if os.path.isfile(f): | 
					
						
							|  |  |  |                 # the file exists, we have a shot at spawn working | 
					
						
							|  |  |  |                 return f | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return executable | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-06 20:51:35 +00:00
										 |  |  | # find_executable() |