Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // These #ifdefs are being used as a substitute for | 5 // These #ifdefs are being used as a substitute for |
6 // build configuration, so that on any system, this | 6 // build configuration, so that on any system, this |
7 // tool can be built with the local equivalent of | 7 // tool can be built with the local equivalent of |
8 // cc *.c | 8 // cc *.c |
9 // | 9 // |
10 #ifdef PLAN9 | 10 #ifdef PLAN9 |
11 | 11 |
12 #include <u.h> | |
13 #include <libc.h> | |
14 #include <stdio.h> | |
15 #undef nil | |
16 #undef nelem | |
12 #include "a.h" | 17 #include "a.h" |
13 | 18 |
14 // bprintf replaces the buffer with the result of the printf formatting | 19 // bprintf replaces the buffer with the result of the printf formatting |
15 // and returns a pointer to the NUL-terminated buffer contents. | 20 // and returns a pointer to the NUL-terminated buffer contents. |
16 char* | 21 char* |
17 bprintf(Buf *b, char *fmt, ...) | 22 bprintf(Buf *b, char *fmt, ...) |
18 { | 23 { |
19 va_list arg; | 24 va_list arg; |
20 char buf[4096]; | 25 char buf[4096]; |
21 ········ | 26 ········ |
22 breset(b); | 27 breset(b); |
23 va_start(arg, fmt); | 28 va_start(arg, fmt); |
24 » vsnprint(buf, sizeof buf, fmt, arg); | 29 » vsnprintf(buf, sizeof buf, fmt, arg); |
25 va_end(arg); | 30 va_end(arg); |
26 bwritestr(b, buf); | 31 bwritestr(b, buf); |
27 return bstr(b); | 32 return bstr(b); |
28 } | 33 } |
29 | 34 |
30 // bpathf is the same as bprintf (on windows it turns / into \ after the printf) . | 35 // bpathf is the same as bprintf (on windows it turns / into \ after the printf) . |
31 // It returns a pointer to the NUL-terminated buffer contents. | 36 // It returns a pointer to the NUL-terminated buffer contents. |
32 char* | 37 char* |
33 bpathf(Buf *b, char *fmt, ...) | 38 bpathf(Buf *b, char *fmt, ...) |
34 { | 39 { |
35 va_list arg; | 40 va_list arg; |
36 char buf[4096]; | 41 char buf[4096]; |
37 ········ | 42 ········ |
38 breset(b); | 43 breset(b); |
39 va_start(arg, fmt); | 44 va_start(arg, fmt); |
40 » vsnprint(buf, sizeof buf, fmt, arg); | 45 » vsnprintf(buf, sizeof buf, fmt, arg); |
41 va_end(arg); | 46 va_end(arg); |
42 bwritestr(b, buf); | 47 bwritestr(b, buf); |
43 return bstr(b); | 48 return bstr(b); |
44 } | 49 } |
45 | 50 |
46 // bwritef is like bprintf but does not reset the buffer | 51 // bwritef is like bprintf but does not reset the buffer |
47 // and does not return the NUL-terminated string. | 52 // and does not return the NUL-terminated string. |
48 void | 53 void |
49 bwritef(Buf *b, char *fmt, ...) | 54 bwritef(Buf *b, char *fmt, ...) |
50 { | 55 { |
51 va_list arg; | 56 va_list arg; |
52 char buf[4096]; | 57 char buf[4096]; |
53 ········ | 58 ········ |
54 va_start(arg, fmt); | 59 va_start(arg, fmt); |
55 » vsnprint(buf, sizeof buf, fmt, arg); | 60 » vsnprintf(buf, sizeof buf, fmt, arg); |
56 va_end(arg); | 61 va_end(arg); |
57 bwritestr(b, buf); | 62 bwritestr(b, buf); |
58 } | 63 } |
59 | 64 |
60 // breadfrom appends to b all the data that can be read from fd. | 65 // breadfrom appends to b all the data that can be read from fd. |
61 static void | 66 static void |
62 breadfrom(Buf *b, int fd) | 67 breadfrom(Buf *b, int fd) |
63 { | 68 { |
64 int n; | 69 int n; |
65 | 70 |
66 for(;;) { | 71 for(;;) { |
67 bgrow(b, 4096); | 72 bgrow(b, 4096); |
68 n = read(fd, b->p+b->len, 4096); | 73 n = read(fd, b->p+b->len, 4096); |
69 if(n < 0) | 74 if(n < 0) |
70 » » » fatal("read: %r"); | 75 » » » fatal("read"); |
71 if(n == 0) | 76 if(n == 0) |
72 break; | 77 break; |
73 b->len += n; | 78 b->len += n; |
74 } | 79 } |
75 } | 80 } |
76 | 81 |
77 // xgetenv replaces b with the value of the named environment variable. | 82 // xgetenv replaces b with the value of the named environment variable. |
78 void | 83 void |
79 xgetenv(Buf *b, char *name) | 84 xgetenv(Buf *b, char *name) |
80 { | 85 { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 { | 130 { |
126 genrun(nil, dir, mode, argv, 0); | 131 genrun(nil, dir, mode, argv, 0); |
127 } | 132 } |
128 | 133 |
129 #define MAXBG 4 /* maximum number of jobs to run at once */ | 134 #define MAXBG 4 /* maximum number of jobs to run at once */ |
130 | 135 |
131 static struct { | 136 static struct { |
132 int pid; | 137 int pid; |
133 int mode; | 138 int mode; |
134 char *cmd; | 139 char *cmd; |
140 Buf *b; | |
135 } bg[MAXBG]; | 141 } bg[MAXBG]; |
136 static int nbg; | 142 static int nbg; |
143 static int maxnbg = nelem(bg); | |
137 | 144 |
138 static void bgwait1(void); | 145 static void bgwait1(void); |
139 | 146 |
140 // genrun is the generic run implementation. | 147 // genrun is the generic run implementation. |
141 static void | 148 static void |
142 genrun(Buf *b, char *dir, int mode, Vec *argv, int wait) | 149 genrun(Buf *b, char *dir, int mode, Vec *argv, int wait) |
143 { | 150 { |
144 int i, p[2], pid; | 151 int i, p[2], pid; |
145 Buf b1, cmd; | 152 Buf b1, cmd; |
146 char *q; | 153 char *q; |
147 | 154 |
148 » while(nbg >= nelem(bg)) | 155 » while(nbg >= maxnbg) |
149 bgwait1(); | 156 bgwait1(); |
150 | 157 |
151 binit(&b1); | 158 binit(&b1); |
152 » if(isabs(argv->p[0])) | 159 » binit(&cmd); |
153 » » argv0 = argv->p[0]; | 160 |
154 » else { | 161 » if(!isabs(argv->p[0])) { |
155 bpathf(&b1, "/bin/%s", argv->p[0]); | 162 bpathf(&b1, "/bin/%s", argv->p[0]); |
156 » » argv0 = btake(&b1); | 163 » » free(argv->p[0]); |
157 » } | 164 » » argv->p[0] = xstrdup(bstr(&b1)); |
158 » bfree(&b1); | 165 » } |
159 | 166 |
160 // Generate a copy of the command to show in a log. | 167 // Generate a copy of the command to show in a log. |
161 // Substitute $WORK for the work directory. | 168 // Substitute $WORK for the work directory. |
162 binit(&cmd); | |
163 for(i=0; i<argv->len; i++) { | 169 for(i=0; i<argv->len; i++) { |
164 if(i > 0) | 170 if(i > 0) |
165 bwritestr(&cmd, " "); | 171 bwritestr(&cmd, " "); |
166 q = argv->p[i]; | 172 q = argv->p[i]; |
167 if(workdir != nil && hasprefix(q, workdir)) { | 173 if(workdir != nil && hasprefix(q, workdir)) { |
168 bwritestr(&cmd, "$WORK"); | 174 bwritestr(&cmd, "$WORK"); |
169 q += strlen(workdir); | 175 q += strlen(workdir); |
170 } | 176 } |
171 bwritestr(&cmd, q); | 177 bwritestr(&cmd, q); |
172 } | 178 } |
173 if(vflag > 1) | 179 if(vflag > 1) |
174 xprintf("%s\n", bstr(&cmd)); | 180 xprintf("%s\n", bstr(&cmd)); |
175 | 181 |
176 if(b != nil) { | 182 if(b != nil) { |
177 breset(b); | 183 breset(b); |
178 if(pipe(p) < 0) | 184 if(pipe(p) < 0) |
179 » » » fatal("pipe: %r"); | 185 » » » fatal("pipe"); |
180 } | 186 } |
181 | 187 |
182 switch(pid = fork()) { | 188 switch(pid = fork()) { |
183 case -1: | 189 case -1: |
184 » » fatal("fork: %r"); | 190 » » fatal("fork"); |
185 case 0: | 191 case 0: |
186 if(b != nil) { | 192 if(b != nil) { |
187 close(0); | 193 close(0); |
188 close(p[0]); | 194 close(p[0]); |
189 dup(p[1], 1); | 195 dup(p[1], 1); |
190 dup(p[1], 2); | 196 dup(p[1], 2); |
191 if(p[1] > 2) | 197 if(p[1] > 2) |
192 close(p[1]); | 198 close(p[1]); |
193 } | 199 } |
194 if(dir != nil) { | 200 if(dir != nil) { |
195 if(chdir(dir) < 0) { | 201 if(chdir(dir) < 0) { |
196 » » » » fprint(2, "chdir %s: %r\n", dir); | 202 » » » » fprint(2, "chdir: %r\n"); |
197 _exits("chdir"); | 203 _exits("chdir"); |
198 } | 204 } |
199 } | 205 } |
200 vadd(argv, nil); | 206 vadd(argv, nil); |
201 exec(argv->p[0], argv->p); | 207 exec(argv->p[0], argv->p); |
202 fprint(2, "%s\n", bstr(&cmd)); | 208 fprint(2, "%s\n", bstr(&cmd)); |
203 » » fprint(2, "exec %s: %r\n", argv0); | 209 » » fprint(2, "exec: %r\n"); |
204 _exits("exec"); | 210 _exits("exec"); |
205 } | 211 } |
206 if(b != nil) { | 212 if(b != nil) { |
207 close(p[1]); | 213 close(p[1]); |
208 breadfrom(b, p[0]); | 214 breadfrom(b, p[0]); |
209 close(p[0]); | 215 close(p[0]); |
210 } | 216 } |
211 | 217 |
212 if(nbg < 0) | 218 if(nbg < 0) |
213 fatal("bad bookkeeping"); | 219 fatal("bad bookkeeping"); |
214 bg[nbg].pid = pid; | 220 bg[nbg].pid = pid; |
215 bg[nbg].mode = mode; | 221 bg[nbg].mode = mode; |
216 bg[nbg].cmd = btake(&cmd); | 222 bg[nbg].cmd = btake(&cmd); |
223 bg[nbg].b = b; | |
217 nbg++; | 224 nbg++; |
218 ········ | 225 ········ |
219 if(wait) | 226 if(wait) |
220 bgwait(); | 227 bgwait(); |
221 | 228 |
222 bfree(&cmd); | 229 bfree(&cmd); |
230 bfree(&b1); | |
223 } | 231 } |
224 | 232 |
225 // bgwait1 waits for a single background job. | 233 // bgwait1 waits for a single background job. |
226 static void | 234 static void |
227 bgwait1(void) | 235 bgwait1(void) |
228 { | 236 { |
229 Waitmsg *w; | 237 Waitmsg *w; |
230 int i, mode; | 238 int i, mode; |
231 char *cmd; | 239 char *cmd; |
240 Buf *b; | |
232 | 241 |
233 w = wait(); | 242 w = wait(); |
234 if(w == nil) | 243 if(w == nil) |
235 » » fatal("wait: %r"); | 244 » » fatal("wait"); |
236 ················ | 245 ················ |
237 for(i=0; i<nbg; i++) | 246 for(i=0; i<nbg; i++) |
238 if(bg[i].pid == w->pid) | 247 if(bg[i].pid == w->pid) |
239 goto ok; | 248 goto ok; |
240 fatal("wait: unexpected pid"); | 249 fatal("wait: unexpected pid"); |
241 | 250 |
242 ok: | 251 ok: |
243 cmd = bg[i].cmd; | 252 cmd = bg[i].cmd; |
244 mode = bg[i].mode; | 253 mode = bg[i].mode; |
245 bg[i].pid = 0; | 254 bg[i].pid = 0; |
255 b = bg[i].b; | |
256 bg[i].b = nil; | |
246 bg[i] = bg[--nbg]; | 257 bg[i] = bg[--nbg]; |
247 ········ | 258 ········ |
248 » if(mode == CheckExit && w->msg[0]) | 259 » if(mode == CheckExit && w->msg[0]) { |
260 » » if(b != nil) | |
261 » » » xprintf("%s\n", bstr(b)); | |
249 fatal("FAILED: %s", cmd); | 262 fatal("FAILED: %s", cmd); |
263 } | |
250 xfree(cmd); | 264 xfree(cmd); |
251 } | 265 } |
252 | 266 |
253 // bgwait waits for all the background jobs. | 267 // bgwait waits for all the background jobs. |
254 void | 268 void |
255 bgwait(void) | 269 bgwait(void) |
256 { | 270 { |
257 while(nbg > 0) | 271 while(nbg > 0) |
258 bgwait1(); | 272 bgwait1(); |
259 } | 273 } |
260 | 274 |
261 // xgetwd replaces b with the current directory. | 275 // xgetwd replaces b with the current directory. |
262 void | 276 void |
263 xgetwd(Buf *b) | 277 xgetwd(Buf *b) |
264 { | 278 { |
265 char buf[4096]; | 279 char buf[4096]; |
266 ········ | 280 ········ |
267 breset(b); | 281 breset(b); |
268 if(getwd(buf, sizeof buf) == nil) | 282 if(getwd(buf, sizeof buf) == nil) |
269 » » fatal("getcwd: %r"); | 283 » » fatal("getwd"); |
270 bwritestr(b, buf); | 284 bwritestr(b, buf); |
271 } | 285 } |
272 | 286 |
273 // xrealwd replaces b with the 'real' name for the given path. | 287 // xrealwd replaces b with the 'real' name for the given path. |
274 // real is defined as what getcwd returns in that directory. | 288 // real is defined as what getcwd returns in that directory. |
275 void | 289 void |
276 xrealwd(Buf *b, char *path) | 290 xrealwd(Buf *b, char *path) |
277 { | 291 { |
278 char buf[4096]; | 292 char buf[4096]; |
279 int fd; | 293 int fd; |
280 | 294 |
281 » fd = open(".", 0); | 295 » fd = open(path, OREAD); |
282 » if(fd < 0) | |
283 » » fatal("open .: %r"); | |
284 » if(chdir(path) < 0) | |
285 » » fatal("chdir %s: %r", path); | |
286 » xgetwd(b); | |
287 if(fd2path(fd, buf, sizeof buf) < 0) | 296 if(fd2path(fd, buf, sizeof buf) < 0) |
288 » » fatal("fdpath: %r"); | 297 » » fatal("fd2path"); |
289 » if(chdir(buf) < 0) | |
290 » » fatal("chdir %s: %r", buf); | |
291 close(fd); | 298 close(fd); |
299 breset(b); | |
300 bwritestr(b, buf); | |
292 } | 301 } |
293 | 302 |
294 // isdir reports whether p names an existing directory. | 303 // isdir reports whether p names an existing directory. |
295 bool | 304 bool |
296 isdir(char *p) | 305 isdir(char *p) |
297 { | 306 { |
298 Dir *d; | 307 Dir *d; |
299 ulong mode; | 308 ulong mode; |
300 | 309 |
301 d = dirstat(p); | 310 d = dirstat(p); |
(...skipping 24 matching lines...) Expand all Loading... | |
326 mtime(char *p) | 335 mtime(char *p) |
327 { | 336 { |
328 Dir *d; | 337 Dir *d; |
329 ulong t; | 338 ulong t; |
330 | 339 |
331 d = dirstat(p); | 340 d = dirstat(p); |
332 if(d == nil) | 341 if(d == nil) |
333 return 0; | 342 return 0; |
334 t = d->mtime; | 343 t = d->mtime; |
335 free(d); | 344 free(d); |
336 » return (Time)t*1000000000LL; | 345 » return (Time)t; |
337 } | 346 } |
338 | 347 |
339 // isabs reports whether p is an absolute path. | 348 // isabs reports whether p is an absolute path. |
340 bool | 349 bool |
341 isabs(char *p) | 350 isabs(char *p) |
342 { | 351 { |
343 return hasprefix(p, "/"); | 352 return hasprefix(p, "/"); |
344 } | 353 } |
345 | 354 |
346 // readfile replaces b with the content of the named file. | 355 // readfile replaces b with the content of the named file. |
347 void | 356 void |
348 readfile(Buf *b, char *file) | 357 readfile(Buf *b, char *file) |
349 { | 358 { |
350 int fd; | 359 int fd; |
351 » | 360 |
352 breset(b); | 361 breset(b); |
353 fd = open(file, OREAD); | 362 fd = open(file, OREAD); |
354 if(fd < 0) | 363 if(fd < 0) |
355 » » fatal("open %s: %r", file); | 364 » » fatal("open %s", file); |
356 breadfrom(b, fd); | 365 breadfrom(b, fd); |
357 close(fd); | 366 close(fd); |
358 } | 367 } |
359 | 368 |
360 // writefile writes b to the named file, creating it if needed. | 369 // writefile writes b to the named file, creating it if needed. |
361 void | 370 void |
362 writefile(Buf *b, char *file) | 371 writefile(Buf *b, char *file, int exec) |
363 { | 372 { |
364 int fd; | 373 int fd; |
374 Dir d; | |
365 ········ | 375 ········ |
366 fd = create(file, ORDWR, 0666); | 376 fd = create(file, ORDWR, 0666); |
367 if(fd < 0) | 377 if(fd < 0) |
368 » » fatal("create %s: %r", file); | 378 » » fatal("create %s", file); |
369 if(write(fd, b->p, b->len) != b->len) | 379 if(write(fd, b->p, b->len) != b->len) |
370 » » fatal("short write: %r"); | 380 » » fatal("short write"); |
381 » if(exec) { | |
382 » » nulldir(&d); | |
383 » » d.mode = 0755; | |
384 » » dirfwstat(fd, &d); | |
385 » } | |
371 close(fd); | 386 close(fd); |
372 } | 387 } |
373 » | 388 |
374 // xmkdir creates the directory p. | 389 // xmkdir creates the directory p. |
375 void | 390 void |
376 xmkdir(char *p) | 391 xmkdir(char *p) |
377 { | 392 { |
378 Dir *d; | |
379 int fd; | 393 int fd; |
380 | 394 |
381 » fd = open(p, OREAD); | 395 » if(isdir(p)) |
382 » if(fd < 0) { | |
383 » » fd = create(p, OREAD, 0777|DMDIR); | |
384 » » if(fd < 0) | |
385 » » » fatal("mkdir create %s: %r", p); | |
386 » » close(fd); | |
387 return; | 396 return; |
388 » } | 397 » fd = create(p, OREAD, 0777|DMDIR); |
389 » d = dirfstat(fd); | |
390 » if(d == nil) | |
391 » » fatal("mkdir %s: stat: %r", p); | |
392 » if((d->mode & DMDIR) == 0) | |
393 » » fatal("mkdir %s: not a directory", p); | |
394 » free(d); | |
395 close(fd); | 398 close(fd); |
399 if(fd < 0) | |
400 fatal("mkdir %s", p); | |
396 } | 401 } |
397 | 402 |
398 // xmkdirall creates the directory p and its parents, as needed. | 403 // xmkdirall creates the directory p and its parents, as needed. |
399 void | 404 void |
400 xmkdirall(char *p) | 405 xmkdirall(char *p) |
401 { | 406 { |
402 char *q; | 407 char *q; |
403 | 408 |
404 if(isdir(p)) | 409 if(isdir(p)) |
405 return; | 410 return; |
406 q = strrchr(p, '/'); | 411 q = strrchr(p, '/'); |
407 if(q != nil) { | 412 if(q != nil) { |
408 *q = '\0'; | 413 *q = '\0'; |
409 xmkdirall(p); | 414 xmkdirall(p); |
410 *q = '/'; | 415 *q = '/'; |
411 } | 416 } |
412 xmkdir(p); | 417 xmkdir(p); |
413 } | 418 } |
414 | 419 |
415 // xremove removes the file p. | 420 // xremove removes the file p. |
416 void | 421 void |
417 xremove(char *p) | 422 xremove(char *p) |
418 { | 423 { |
419 » if(vflag > 1) | 424 » if(vflag > 2) |
420 xprintf("rm %s\n", p); | 425 xprintf("rm %s\n", p); |
421 remove(p); | 426 remove(p); |
422 } | 427 } |
423 | 428 |
424 // xremoveall removes the file or directory tree rooted at p. | 429 // xremoveall removes the file or directory tree rooted at p. |
425 void | 430 void |
426 xremoveall(char *p) | 431 xremoveall(char *p) |
427 { | 432 { |
428 int i; | 433 int i; |
429 Buf b; | 434 Buf b; |
430 Vec dir; | 435 Vec dir; |
431 | 436 |
432 binit(&b); | 437 binit(&b); |
433 vinit(&dir); | 438 vinit(&dir); |
434 | 439 |
435 if(isdir(p)) { | 440 if(isdir(p)) { |
436 xreaddir(&dir, p); | 441 xreaddir(&dir, p); |
437 for(i=0; i<dir.len; i++) { | 442 for(i=0; i<dir.len; i++) { |
438 bprintf(&b, "%s/%s", p, dir.p[i]); | 443 bprintf(&b, "%s/%s", p, dir.p[i]); |
439 xremoveall(bstr(&b)); | 444 xremoveall(bstr(&b)); |
440 } | 445 } |
441 } | 446 } |
442 » if(vflag > 1) | 447 » if(vflag > 2) |
443 xprintf("rm %s\n", p); | 448 xprintf("rm %s\n", p); |
444 remove(p); | 449 remove(p); |
445 ········ | 450 ········ |
446 bfree(&b); | 451 bfree(&b); |
447 vfree(&dir);···· | 452 vfree(&dir);···· |
448 } | 453 } |
449 | 454 |
450 // xreaddir replaces dst with a list of the names of the files in dir. | 455 // xreaddir replaces dst with a list of the names of the files in dir. |
451 // The names are relative to dir; they are not full paths. | 456 // The names are relative to dir; they are not full paths. |
452 void | 457 void |
453 xreaddir(Vec *dst, char *dir) | 458 xreaddir(Vec *dst, char *dir) |
454 { | 459 { |
455 Dir *d; | 460 Dir *d; |
456 int fd, i, n; | 461 int fd, i, n; |
457 | 462 |
458 vreset(dst); | 463 vreset(dst); |
459 | 464 |
460 fd = open(dir, OREAD); | 465 fd = open(dir, OREAD); |
461 if(fd < 0) | 466 if(fd < 0) |
462 » » fatal("open %s: %r", dir); | 467 » » fatal("open %s", dir); |
463 n = dirreadall(fd, &d); | 468 n = dirreadall(fd, &d); |
464 for(i=0; i<n; i++) | 469 for(i=0; i<n; i++) |
465 vadd(dst, d[i].name); | 470 vadd(dst, d[i].name); |
466 free(d); | 471 free(d); |
467 close(fd); | 472 close(fd); |
468 } | 473 } |
469 | 474 |
470 // xworkdir creates a new temporary directory to hold object files | 475 // xworkdir creates a new temporary directory to hold object files |
471 // and returns the name of that directory. | 476 // and returns the name of that directory. |
472 char* | 477 char* |
473 xworkdir(void) | 478 xworkdir(void) |
474 { | 479 { |
475 Buf b; | 480 Buf b; |
476 char *p; | 481 char *p; |
477 int fd, tries; | 482 int fd, tries; |
478 | 483 |
479 binit(&b); | 484 binit(&b); |
480 | 485 |
481 fd = 0; | 486 fd = 0; |
482 for(tries=0; tries<1000; tries++) { | 487 for(tries=0; tries<1000; tries++) { |
483 bprintf(&b, "/tmp/go-cbuild-%06x", nrand((1<<24)-1)); | 488 bprintf(&b, "/tmp/go-cbuild-%06x", nrand((1<<24)-1)); |
484 » » fd = create(bstr(&b), OREAD, 0700|DMDIR); | 489 » » fd = create(bstr(&b), OREAD|OEXCL, 0700|DMDIR); |
485 if(fd >= 0) | 490 if(fd >= 0) |
486 goto done; | 491 goto done; |
487 } | 492 } |
488 » fatal("xworkdir create: %r"); | 493 » fatal("xworkdir create"); |
489 | 494 |
490 done: | 495 done: |
491 close(fd); | 496 close(fd); |
492 p = btake(&b); | 497 p = btake(&b); |
493 | 498 |
494 bfree(&b); | 499 bfree(&b); |
495 return p; | 500 return p; |
496 } | 501 } |
497 | 502 |
498 // fatal prints an error message to standard error and exits. | 503 // fatal prints an error message to standard error and exits. |
499 void | 504 void |
500 fatal(char *msg, ...) | 505 fatal(char *msg, ...) |
501 { | 506 { |
507 char buf[ERRMAX]; | |
502 va_list arg; | 508 va_list arg; |
503 ········ | 509 ········ |
504 » fprint(2, "go tool dist: "); | 510 » rerrstr(buf, sizeof buf); |
511 | |
512 » fflush(stdout); | |
513 » fprintf(stderr, "go tool dist: "); | |
505 va_start(arg, msg); | 514 va_start(arg, msg); |
506 » vfprint(2, msg, arg); | 515 » vfprintf(stderr, msg, arg); |
507 va_end(arg); | 516 va_end(arg); |
508 » fprint(2, "\n"); | 517 |
518 » if(buf[0]) | |
519 » » fprintf(stderr, ": %s", buf); | |
520 » fprintf(stderr, "\n"); | |
521 | |
522 » bgwait(); | |
509 exits(msg); | 523 exits(msg); |
510 } | 524 } |
511 | 525 |
512 // xmalloc returns a newly allocated zeroed block of n bytes of memory. | 526 // xmalloc returns a newly allocated zeroed block of n bytes of memory. |
513 // It calls fatal if it runs out of memory. | 527 // It calls fatal if it runs out of memory. |
514 void* | 528 void* |
515 xmalloc(int n) | 529 xmalloc(int n) |
516 { | 530 { |
517 void *p; | 531 void *p; |
518 ········ | 532 ········ |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 { | 632 { |
619 return strlen(p); | 633 return strlen(p); |
620 } | 634 } |
621 | 635 |
622 // xexit exits the process with return code n. | 636 // xexit exits the process with return code n. |
623 void | 637 void |
624 xexit(int n) | 638 xexit(int n) |
625 { | 639 { |
626 char buf[32]; | 640 char buf[32]; |
627 | 641 |
628 » snprint(buf, sizeof buf, "%d", n); | 642 » snprintf(buf, sizeof buf, "%d", n); |
629 exits(buf); | 643 exits(buf); |
630 } | 644 } |
631 | 645 |
632 // xatexit schedules the exit-handler f to be run when the program exits. | 646 // xatexit schedules the exit-handler f to be run when the program exits. |
633 void | 647 void |
634 xatexit(void (*f)(void)) | 648 xatexit(void (*f)(void)) |
635 { | 649 { |
636 atexit(f); | 650 atexit(f); |
637 } | 651 } |
638 | 652 |
639 // xprintf prints a message to standard output. | 653 // xprintf prints a message to standard output. |
640 void | 654 void |
641 xprintf(char *fmt, ...) | 655 xprintf(char *fmt, ...) |
642 { | 656 { |
643 va_list arg; | 657 va_list arg; |
644 ········ | 658 ········ |
645 va_start(arg, fmt); | 659 va_start(arg, fmt); |
646 » vfprint(1, fmt, arg); | 660 » vprintf(fmt, arg); |
647 va_end(arg); | 661 va_end(arg); |
648 } | 662 } |
649 | 663 |
650 // xsetenv sets the environment variable $name to the given value. | 664 // xsetenv sets the environment variable $name to the given value. |
651 void | 665 void |
652 xsetenv(char *name, char *value) | 666 xsetenv(char *name, char *value) |
653 { | 667 { |
654 putenv(name, value); | 668 putenv(name, value); |
655 } | 669 } |
656 | 670 |
657 // main takes care of OS-specific startup and dispatches to xmain. | 671 // main takes care of OS-specific startup and dispatches to xmain. |
658 int | 672 void |
659 main(int argc, char **argv) | 673 main(int argc, char **argv) |
660 { | 674 { |
661 » char *p; | 675 » Buf b; |
662 » Buf b, b1; | 676 |
677 » setvbuf(stdout, nil, _IOLBF, BUFSIZ); | |
678 » setvbuf(stderr, nil, _IOLBF, BUFSIZ); | |
663 | 679 |
664 binit(&b); | 680 binit(&b); |
665 » binit(&b1); | 681 |
666 | 682 » rfork(RFENVG); |
667 » p = argv[0]; | 683 |
668 » if(hassuffix(p, "bin/tool/dist")) { | |
669 » » default_goroot = xstrdup(p); | |
670 » » default_goroot[strlen(p)-strlen("bin/tool/dist")] = '\0'; | |
671 » } | |
672 »······· | |
673 slash = "/"; | 684 slash = "/"; |
674 gohostos = "plan9"; | 685 gohostos = "plan9"; |
675 | 686 |
676 » xgetenv(&b1, "objtype"); | 687 » xgetenv(&b, "objtype"); |
677 » if(b1.len == 0) | 688 » if(b.len == 0) |
678 fatal("$objtype is unset"); | 689 fatal("$objtype is unset"); |
679 » gohostarch = btake(&b1); | 690 » gohostarch = btake(&b); |
691 | |
692 » xgetenv(&b, "GOBIN"); | |
693 » if(b.len == 0){ | |
694 » » bpathf(&b, "/%s/bin", gohostarch); | |
695 » » xsetenv("GOBIN", bstr(&b)); | |
696 » } | |
680 | 697 |
681 srand(time(0)+getpid()); | 698 srand(time(0)+getpid()); |
682 rfork(RFENVG); | |
683 init(); | 699 init(); |
684 xmain(argc, argv); | 700 xmain(argc, argv); |
685 | 701 |
686 bfree(&b1); | |
687 bfree(&b); | 702 bfree(&b); |
688 » return 0; | 703 » exits(nil); |
689 } | 704 } |
690 | 705 |
691 // xqsort is a wrapper for the C standard qsort. | 706 // xqsort is a wrapper for the C standard qsort. |
692 void | 707 void |
693 xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*)) | 708 xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*)) |
694 { | 709 { |
695 qsort(data, n, elemsize, cmp); | 710 qsort(data, n, elemsize, cmp); |
696 } | 711 } |
697 | 712 |
698 // xstrcmp compares the NUL-terminated strings a and b. | 713 // xstrcmp compares the NUL-terminated strings a and b. |
(...skipping 10 matching lines...) Expand all Loading... | |
709 return strstr(a, b); | 724 return strstr(a, b); |
710 } | 725 } |
711 | 726 |
712 // xstrrchr returns a pointer to the final occurrence of c in p. | 727 // xstrrchr returns a pointer to the final occurrence of c in p. |
713 char* | 728 char* |
714 xstrrchr(char *p, int c) | 729 xstrrchr(char *p, int c) |
715 { | 730 { |
716 return strrchr(p, c); | 731 return strrchr(p, c); |
717 } | 732 } |
718 | 733 |
719 #endif // __WINDOWS__ | 734 #endif // PLAN9 |
rsc
2012/02/04 06:52:56
PLAN9
ality
2012/02/04 07:23:13
Done.
| |
LEFT | RIGHT |