diff --git a/include/libc.h b/include/libc.h index 1440209e30a..5fd56b8bfe7 100644 --- a/include/libc.h +++ b/include/libc.h @@ -292,6 +292,10 @@ extern char* getgoversion(void); extern char* getgoarm(void); extern char* getgo386(void); +extern char* mktempdir(void); +extern void removeall(char*); +extern int runcmd(char**); + extern void flagcount(char*, char*, int*); extern void flagint32(char*, char*, int32*); extern void flagint64(char*, char*, int64*); diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c index 7bcda4508f4..ba23a7ae828 100644 --- a/src/cmd/dist/windows.c +++ b/src/cmd/dist/windows.c @@ -271,6 +271,8 @@ static void bgwait1(void); static void genrun(Buf *b, char *dir, int mode, Vec *argv, int wait) { + // Another copy of this logic is in ../../lib9/run_windows.c. + // If there's a bug here, fix the logic there too. int i, j, nslash; Buf cmd; char *q; diff --git a/src/lib9/run_plan9.c b/src/lib9/run_plan9.c new file mode 100644 index 00000000000..7feb48d981f --- /dev/null +++ b/src/lib9/run_plan9.c @@ -0,0 +1,38 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include +#include + +int +runcmd(char **argv) +{ + int pid; + Waitmsg *w; + + switch(pid = fork()) { + case -1: + return -1; + case 0: + execvp(argv[0], argv); + fprint(2, "exec %s: %r", argv[0]); + _exit(1); + } + + w = wait(); + if(w == nil) + return -1; + if(w->pid != pid) { + werrstr("unexpected pid in wait"); + free(w); + return -1; + } + if(w->msg[0]) { + werrstr("unsuccessful exit status: %s", w->msg); + free(w); + return -1; + } + free(w); + return 0; +} diff --git a/src/lib9/run_unix.c b/src/lib9/run_unix.c new file mode 100644 index 00000000000..1b4c6de1b45 --- /dev/null +++ b/src/lib9/run_unix.c @@ -0,0 +1,43 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin freebsd linux netbsd openbsd + +#include +#include +#include +#define NOPLAN9DEFINES +#include + +int +runcmd(char **argv) +{ + int pid, pid1, status; + + switch(pid = fork()) { + case -1: + return -1; + case 0: + execvp(argv[0], argv); + fprint(2, "exec %s: %r", argv[0]); + _exit(1); + } + + while((pid1 = wait(&status)) < 0) { + if(errno != EINTR) { + werrstr("waitpid: %r"); + return -1; + } + } + if(pid1 != pid) { + werrstr("unexpected pid in wait"); + return -1; + } + if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + werrstr("unsuccessful exit status %#x", status); + return -1; + } + return 0; +} + diff --git a/src/lib9/run_windows.c b/src/lib9/run_windows.c new file mode 100644 index 00000000000..87875b42dbd --- /dev/null +++ b/src/lib9/run_windows.c @@ -0,0 +1,83 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include +#include +#define NOPLAN9DEFINES +#include +#include "win.h" + +int +runcmd(char **argv) +{ + // Mostly copied from ../cmd/dist/windows.c. + // If there's a bug here, fix the logic there too. + int i, j, nslash; + Fmt fmt; + char *q; + WinRune *r; + STARTUPINFOW si; + PROCESS_INFORMATION pi; + DWORD code; + + fmtstrinit(&fmt); + for(i=0; argv[i]; i++) { + if(i > 0) + fmtprint(&fmt, " "); + q = argv[i]; + if(strstr(q, " ") || strstr(q, "\t") || strstr(q, "\"") || strstr(q, "\\\\") || (strlen(q) > 0 && q[strlen(q)-1] == '\\')) { + fmtprint(&fmt, "\""); + nslash = 0; + for(; *q; q++) { + if(*q == '\\') { + nslash++; + continue; + } + if(*q == '"') { + for(j=0; j<2*nslash+1; j++) + fmtprint(&fmt, "\\"); + nslash = 0; + } + for(j=0; j +#include + +char* +mktempdir(void) +{ + char *p; + int i; + + p = smprint("/tmp/go-link-XXXXXX"); + for(i=0; i<1000; i++) { + sprint(p, "/tmp/go-link-%06x", nrand((1<<24)-1)); + fd = create(p, OREAD|OEXCL, 0700|DMDIR); + if(fd >= 0) { + close(fd); + return p; + } + } + free(p); + return nil; +} + +void +removeall(char *p) +{ + int fd, n; + Dir *d; + char *q; + + if(remove(p) >= 0) + return; + if((d = dirstat(p)) == nil) + return; + if(!(d->mode & DMDIR)) { + free(d); + return; + } + free(d); + + if((fd = open(p, OREAD)) < 0) + return; + n = dirreadall(fd, &d); + close(fd); + for(i=0; i +#include +#include +#define NOPLAN9DEFINES +#include + +char* +mktempdir(void) +{ + char *tmp, *p; + + tmp = getenv("TMPDIR"); + if(tmp == nil) + tmp = "/var/tmp"; + p = smprint("%s/go-link-XXXXXX", tmp); + if(mkdtemp(p) == nil) + return nil; + return p; +} + +void +removeall(char *p) +{ + DIR *d; + struct dirent *dp; + char *q; + struct stat st; + + if(stat(p, &st) < 0) + return; + if(!S_ISDIR(st.st_mode)) { + unlink(p); + return; + } + + d = opendir(p); + while((dp = readdir(d)) != nil) { + if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) + continue; + q = smprint("%s/%s", p, dp->d_name); + removeall(q); + free(q); + } + closedir(d); + rmdir(p); +} diff --git a/src/lib9/tempdir_windows.c b/src/lib9/tempdir_windows.c new file mode 100644 index 00000000000..8e9322dc825 --- /dev/null +++ b/src/lib9/tempdir_windows.c @@ -0,0 +1,112 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include +#include +#include +#include "win.h" + +char* +toutf(WinRune *r) +{ + Rune *r1; + int i, n; + char *p; + + n = 0; + while(r[n] != '\0') + n++; + n++; + r1 = malloc(n*sizeof r1[0]); + for(i=0; i