blob: 24e76ef10e2c344199fd610714941c3c684342b7 [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)
36 elif os.name == 'windows': # ???
37 # XXX should 'args' be cmd[1:] or cmd?
38 # XXX how do we detect failure?
39 # XXX how to do this in pre-1.5.2?
40 # XXX is P_WAIT the correct mode?
41 # XXX how to make Windows search the path?
42 if verbose:
43 print string.join (cmd, ' ')
44 if not dry_run:
45 os.spawnv (os.P_WAIT, cmd[0], cmd[1:])
46 else:
47 raise DistutilsPlatformError, \
48 "don't know how to spawn programs on platform '%s'" % os.name
49
50# spawn ()
51
52
53def _spawn_posix (cmd,
54 search_path=1,
55 verbose=0,
56 dry_run=0):
57
58 if verbose:
59 print string.join (cmd, ' ')
60 if dry_run:
61 return
62 exec_fn = search_path and os.execvp or os.execv
63
64 pid = os.fork ()
65
66 if pid == 0: # in the child
67 try:
68 #print "cmd[0] =", cmd[0]
69 #print "cmd =", cmd
70 exec_fn (cmd[0], cmd)
71 except OSError, e:
72 sys.stderr.write ("unable to execute %s: %s\n" %
73 (cmd[0], e.strerror))
74 os._exit (1)
75
76 sys.stderr.write ("unable to execute %s for unknown reasons" % cmd[0])
77 os._exit (1)
78
79
80 else: # in the parent
81 # Loop until the child either exits or is terminated by a signal
82 # (ie. keep waiting if it's merely stopped)
83 while 1:
84 (pid, status) = os.waitpid (pid, 0)
85 if os.WIFSIGNALED (status):
86 raise DistutilsExecError, \
87 "command %s terminated by signal %d" % \
88 (cmd[0], os.WTERMSIG (status))
89
90 elif os.WIFEXITED (status):
91 exit_status = os.WEXITSTATUS (status)
92 if exit_status == 0:
93 return # hey, it succeeded!
94 else:
95 raise DistutilsExecError, \
96 "command %s failed with exit status %d" % \
97 (cmd[0], exit_status)
98
99 elif os.WIFSTOPPED (status):
100 continue
101
102 else:
103 raise DistutilsExecError, \
104 "unknown error executing %s: termination status %d" % \
105 (cmd[0], status)
106# _spawn_posix ()