blob: eee8e7f4a0cee8e9f0d1a972b5f2645aea6aad35 [file] [log] [blame]
Greg Wardb4dbfb31999-08-14 23:57:17 +00001"""distutils.spawn
2
3Provides the 'spawn()' function, a front-end to various platform-
4specific functions for launching another program in a sub-process."""
5
6# created 1999/07/24, Greg Ward
7
8__rcsid__ = "$Id$"
9
10import sys, os, string
11from distutils.errors import *
12
13
14def spawn (cmd,
15 search_path=1,
16 verbose=0,
17 dry_run=0):
18
19 """Run another program, specified as a command list 'cmd', in a new
20 process. 'cmd' is just the argument list for the new process, ie.
21 cmd[0] is the program to run and cmd[1:] are the rest of its
22 arguments. There is no way to run a program with a name different
23 from that of its executable.
24
25 If 'search_path' is true (the default), the system's executable
26 search path will be used to find the program; otherwise, cmd[0] must
27 be the exact path to the executable. If 'verbose' is true, a
28 one-line summary of the command will be printed before it is run.
29 If 'dry_run' is true, the command will not actually be run.
30
31 Raise DistutilsExecError if running the program fails in any way;
32 just return on success."""
33
34 if os.name == 'posix':
35 _spawn_posix (cmd, search_path, verbose, dry_run)
Greg Warda4d132a1999-09-08 02:23:28 +000036 elif os.name == 'nt':
Greg Ward69628b01999-08-29 18:20:56 +000037 _spawn_nt (cmd, search_path, verbose, dry_run)
Greg Wardb4dbfb31999-08-14 23:57:17 +000038 else:
39 raise DistutilsPlatformError, \
40 "don't know how to spawn programs on platform '%s'" % os.name
41
42# spawn ()
43
Greg Warda4d132a1999-09-08 02:23:28 +000044
Greg Ward69628b01999-08-29 18:20:56 +000045def _spawn_nt ( cmd,
46 search_path=1,
47 verbose=0,
48 dry_run=0):
Greg Ward69628b01999-08-29 18:20:56 +000049 executable = cmd[0]
50 if search_path:
51 paths = string.split( os.environ['PATH'], os.pathsep)
52 base,ext = os.path.splitext(executable)
53 if (ext != '.exe'):
54 executable = executable + '.exe'
55 if not os.path.isfile(executable):
56 paths.reverse() # go over the paths and keep the last one
57 for p in paths:
58 f = os.path.join( p, executable )
59 if os.path.isfile ( f ):
60 # the file exists, we have a shot at spawn working
61 executable = f
62 if verbose:
63 print string.join ( [executable] + cmd[1:], ' ')
64 if not dry_run:
65 # spawn for NT requires a full path to the .exe
66 rc = os.spawnv (os.P_WAIT, executable, cmd)
67 if rc != 0:
68 raise DistutilsExecError("command failed: %d" % rc)
Greg Wardb4dbfb31999-08-14 23:57:17 +000069
Greg Ward69628b01999-08-29 18:20:56 +000070
71
Greg Wardb4dbfb31999-08-14 23:57:17 +000072def _spawn_posix (cmd,
73 search_path=1,
74 verbose=0,
75 dry_run=0):
76
77 if verbose:
78 print string.join (cmd, ' ')
79 if dry_run:
80 return
81 exec_fn = search_path and os.execvp or os.execv
82
83 pid = os.fork ()
84
85 if pid == 0: # in the child
86 try:
87 #print "cmd[0] =", cmd[0]
88 #print "cmd =", cmd
89 exec_fn (cmd[0], cmd)
90 except OSError, e:
91 sys.stderr.write ("unable to execute %s: %s\n" %
92 (cmd[0], e.strerror))
93 os._exit (1)
94
95 sys.stderr.write ("unable to execute %s for unknown reasons" % cmd[0])
96 os._exit (1)
97
98
99 else: # in the parent
100 # Loop until the child either exits or is terminated by a signal
101 # (ie. keep waiting if it's merely stopped)
102 while 1:
103 (pid, status) = os.waitpid (pid, 0)
104 if os.WIFSIGNALED (status):
105 raise DistutilsExecError, \
106 "command %s terminated by signal %d" % \
107 (cmd[0], os.WTERMSIG (status))
108
109 elif os.WIFEXITED (status):
110 exit_status = os.WEXITSTATUS (status)
111 if exit_status == 0:
112 return # hey, it succeeded!
113 else:
114 raise DistutilsExecError, \
115 "command %s failed with exit status %d" % \
116 (cmd[0], exit_status)
117
118 elif os.WIFSTOPPED (status):
119 continue
120
121 else:
122 raise DistutilsExecError, \
123 "unknown error executing %s: termination status %d" % \
124 (cmd[0], status)
125# _spawn_posix ()