159
|
1
|
|
2
|
|
3 // Copyright (c) 1999-2007 by Digital Mars
|
|
4 // All Rights Reserved
|
|
5 // written by Walter Bright
|
|
6 // http://www.digitalmars.com
|
|
7 // License for redistribution is by either the Artistic License
|
|
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
|
|
9 // See the included readme.txt for details.
|
|
10
|
|
11
|
|
12 #include <stdio.h>
|
|
13 #include <ctype.h>
|
|
14 #include <assert.h>
|
|
15 #include <stdarg.h>
|
|
16 #include <string.h>
|
|
17 #include <stdlib.h>
|
|
18
|
|
19 #if _WIN32
|
|
20 #include <process.h>
|
|
21 #endif
|
|
22
|
|
23 #if linux
|
|
24 #include <sys/types.h>
|
|
25 #include <sys/wait.h>
|
|
26 #include <unistd.h>
|
|
27 #endif
|
|
28
|
|
29 #include "root.h"
|
|
30
|
|
31 #include "mars.h"
|
|
32
|
|
33 #include "mem.h"
|
|
34
|
160
|
35 #include "gen/logger.h"
|
|
36
|
159
|
37 int executecmd(char *cmd, char *args, int useenv);
|
|
38 int executearg0(char *cmd, char *args);
|
|
39
|
|
40 /**********************************
|
|
41 * Delete generated EXE file.
|
|
42 */
|
|
43
|
|
44 void deleteExeFile()
|
|
45 {
|
|
46 if (global.params.exefile)
|
|
47 {
|
|
48 //printf("deleteExeFile() %s\n", global.params.exefile);
|
|
49 remove(global.params.exefile);
|
|
50 }
|
|
51 }
|
|
52
|
|
53 /******************************
|
|
54 * Execute a rule. Return the status.
|
|
55 * cmd program to run
|
|
56 * args arguments to cmd, as a string
|
|
57 * useenv if cmd knows about _CMDLINE environment variable
|
|
58 */
|
|
59
|
|
60 #if _WIN32
|
|
61 int executecmd(char *cmd, char *args, int useenv)
|
|
62 {
|
|
63 int status;
|
|
64 char *buff;
|
|
65 size_t len;
|
|
66
|
|
67 if (!global.params.quiet || global.params.verbose)
|
|
68 {
|
|
69 printf("%s %s\n", cmd, args);
|
|
70 fflush(stdout);
|
|
71 }
|
|
72
|
|
73 if ((len = strlen(args)) > 255)
|
|
74 { char *q;
|
|
75 static char envname[] = "@_CMDLINE";
|
|
76
|
|
77 envname[0] = '@';
|
|
78 switch (useenv)
|
|
79 { case 0: goto L1;
|
|
80 case 2: envname[0] = '%'; break;
|
|
81 }
|
|
82 q = (char *) alloca(sizeof(envname) + len + 1);
|
|
83 sprintf(q,"%s=%s", envname + 1, args);
|
|
84 status = putenv(q);
|
|
85 if (status == 0)
|
|
86 args = envname;
|
|
87 else
|
|
88 {
|
|
89 L1:
|
|
90 error("command line length of %d is too long",len);
|
|
91 }
|
|
92 }
|
|
93
|
|
94 status = executearg0(cmd,args);
|
|
95 #if _WIN32
|
|
96 if (status == -1)
|
|
97 status = spawnlp(0,cmd,cmd,args,NULL);
|
|
98 #endif
|
|
99 // if (global.params.verbose)
|
|
100 // printf("\n");
|
|
101 if (status)
|
|
102 {
|
|
103 if (status == -1)
|
|
104 printf("Can't run '%s', check PATH\n", cmd);
|
|
105 else
|
|
106 printf("--- errorlevel %d\n", status);
|
|
107 }
|
|
108 return status;
|
|
109 }
|
|
110 #endif
|
|
111
|
|
112 /**************************************
|
|
113 * Attempt to find command to execute by first looking in the directory
|
|
114 * where DMD was run from.
|
|
115 * Returns:
|
|
116 * -1 did not find command there
|
|
117 * !=-1 exit status from command
|
|
118 */
|
|
119
|
|
120 #if _WIN32
|
|
121 int executearg0(char *cmd, char *args)
|
|
122 {
|
|
123 char *file;
|
|
124 char *argv0 = global.params.argv0;
|
|
125
|
|
126 //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args);
|
|
127
|
|
128 // If cmd is fully qualified, we don't do this
|
|
129 if (FileName::absolute(cmd))
|
|
130 return -1;
|
|
131
|
|
132 file = FileName::replaceName(argv0, cmd);
|
|
133
|
|
134 //printf("spawning '%s'\n",file);
|
|
135 #if _WIN32
|
|
136 return spawnl(0,file,file,args,NULL);
|
|
137 #elif linux
|
|
138 char *full;
|
|
139 int cmdl = strlen(cmd);
|
|
140
|
|
141 full = (char*) mem.malloc(cmdl + strlen(args) + 2);
|
|
142 if (full == NULL)
|
|
143 return 1;
|
|
144 strcpy(full, cmd);
|
|
145 full [cmdl] = ' ';
|
|
146 strcpy(full + cmdl + 1, args);
|
|
147
|
|
148 int result = system(full);
|
|
149
|
|
150 mem.free(full);
|
|
151 return result;
|
|
152 #else
|
|
153 assert(0);
|
|
154 #endif
|
|
155 }
|
|
156 #endif
|
|
157
|
|
158 /***************************************
|
|
159 * Run the compiled program.
|
|
160 * Return exit status.
|
|
161 */
|
|
162
|
|
163 int runProgram()
|
|
164 {
|
|
165 //printf("runProgram()\n");
|
|
166 if (global.params.verbose)
|
|
167 {
|
|
168 printf("%s", global.params.exefile);
|
|
169 for (size_t i = 0; i < global.params.runargs_length; i++)
|
|
170 printf(" %s", (char *)global.params.runargs[i]);
|
|
171 printf("\n");
|
|
172 }
|
|
173
|
|
174 // Build argv[]
|
|
175 Array argv;
|
|
176
|
|
177 argv.push((void *)global.params.exefile);
|
|
178 for (size_t i = 0; i < global.params.runargs_length; i++)
|
|
179 { char *a = global.params.runargs[i];
|
|
180
|
|
181 #if _WIN32
|
|
182 // BUG: what about " appearing in the string?
|
|
183 if (strchr(a, ' '))
|
|
184 { char *b = (char *)mem.malloc(3 + strlen(a));
|
|
185 sprintf(b, "\"%s\"", a);
|
|
186 a = b;
|
|
187 }
|
|
188 #endif
|
|
189 argv.push((void *)a);
|
|
190 }
|
|
191 argv.push(NULL);
|
|
192
|
|
193 #if _WIN32
|
|
194 char *ex = FileName::name(global.params.exefile);
|
|
195 if (ex == global.params.exefile)
|
|
196 ex = FileName::combine(".", ex);
|
|
197 else
|
|
198 ex = global.params.exefile;
|
|
199 return spawnv(0,ex,(char **)argv.data);
|
|
200 #elif linux
|
|
201 pid_t childpid;
|
|
202 int status;
|
|
203
|
|
204 childpid = fork();
|
|
205 if (childpid == 0)
|
|
206 {
|
|
207 char *fn = (char *)argv.data[0];
|
|
208 if (!FileName::absolute(fn))
|
|
209 { // Make it "./fn"
|
|
210 fn = FileName::combine(".", fn);
|
|
211 }
|
|
212 execv(fn, (char **)argv.data);
|
|
213 perror(fn); // failed to execute
|
|
214 return -1;
|
|
215 }
|
|
216
|
|
217 waitpid(childpid, &status, 0);
|
|
218
|
|
219 status = WEXITSTATUS(status);
|
|
220 return status;
|
|
221 #else
|
|
222 assert(0);
|
|
223 #endif
|
|
224 }
|