runtime: revert 6974:1f3c3696babb

I missed that environment is used during runtime setup,
well before go init() functions run. Implemented os-dependent
runtime.goenvs functions to allow for different unix, plan9 and
windows versions of environment discovery.

R=rsc, paulzhol
CC=golang-dev
https://golang.org/cl/3787046
diff --git a/src/pkg/runtime/darwin/thread.c b/src/pkg/runtime/darwin/thread.c
index 185f0ce..d69c624 100644
--- a/src/pkg/runtime/darwin/thread.c
+++ b/src/pkg/runtime/darwin/thread.c
@@ -149,6 +149,12 @@
 }
 
 void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+void
 runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
 {
 	m->tls[0] = m->id;	// so 386 asm can find it
diff --git a/src/pkg/runtime/freebsd/thread.c b/src/pkg/runtime/freebsd/thread.c
index fc80dfb..9bd8838 100644
--- a/src/pkg/runtime/freebsd/thread.c
+++ b/src/pkg/runtime/freebsd/thread.c
@@ -163,6 +163,12 @@
 {
 }
 
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
 // Called to initialize a new m (including the bootstrap m).
 void
 runtime·minit(void)
diff --git a/src/pkg/runtime/linux/thread.c b/src/pkg/runtime/linux/thread.c
index 9c9fc75..979260b 100644
--- a/src/pkg/runtime/linux/thread.c
+++ b/src/pkg/runtime/linux/thread.c
@@ -263,6 +263,12 @@
 {
 }
 
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
 // Called to initialize a new m (including the bootstrap m).
 void
 runtime·minit(void)
diff --git a/src/pkg/runtime/plan9/thread.c b/src/pkg/runtime/plan9/thread.c
index f1bd1ff..fa96552 100644
--- a/src/pkg/runtime/plan9/thread.c
+++ b/src/pkg/runtime/plan9/thread.c
@@ -18,6 +18,11 @@
 }
 
 void
+runtime·goenvs(void)
+{
+}
+
+void
 runtime·initsig(int32 queue)
 {
 }
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index d469e7c..e9a19d9 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -111,6 +111,7 @@
 
 	runtime·mallocinit();
 	runtime·goargs();
+	runtime·goenvs();
 
 	// For debugging:
 	// Allocate internal symbol table representation now,
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index dbdc0f2..9d3efe9 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -152,34 +152,36 @@
 void
 runtime·goargs(void)
 {
-	String *gargv;
-	String *genvv;
-	int32 i, envc;
+	String *s;
+	int32 i;
 	
 	// for windows implementation see "os" package
 	if(Windows)
 		return;
 
-	if(runtime·isplan9)
-		envc=0;
-	else
-		for(envc=0; argv[argc+1+envc] != 0; envc++)
-			;
-
-	gargv = runtime·malloc(argc*sizeof gargv[0]);
-	genvv = runtime·malloc(envc*sizeof genvv[0]);
-
+	s = runtime·malloc(argc*sizeof s[0]);
 	for(i=0; i<argc; i++)
-		gargv[i] = runtime·gostringnocopy(argv[i]);
-	os·Args.array = (byte*)gargv;
+		s[i] = runtime·gostringnocopy(argv[i]);
+	os·Args.array = (byte*)s;
 	os·Args.len = argc;
 	os·Args.cap = argc;
+}
 
-	for(i=0; i<envc; i++)
-		genvv[i] = runtime·gostringnocopy(argv[argc+1+i]);
-	os·Envs.array = (byte*)genvv;
-	os·Envs.len = envc;
-	os·Envs.cap = envc;
+void
+runtime·goenvs_unix(void)
+{
+	String *s;
+	int32 i, n;
+	
+	for(n=0; argv[argc+1+n] != 0; n++)
+		;
+
+	s = runtime·malloc(n*sizeof s[0]);
+	for(i=0; i<n; i++)
+		s[i] = runtime·gostringnocopy(argv[argc+1+i]);
+	os·Envs.array = (byte*)s;
+	os·Envs.len = n;
+	os·Envs.cap = n;
 }
 
 // Atomic add and return new value.
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index e53855e..bde6283 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -370,6 +370,7 @@
  */
 int32	runtime·strcmp(byte*, byte*);
 int32	runtime·findnull(byte*);
+int32	runtime·findnullw(uint16*);
 void	runtime·dump(byte*, int32);
 int32	runtime·runetochar(byte*, int32);
 int32	runtime·charntorune(int32*, uint8*, int32);
@@ -384,6 +385,8 @@
 uintptr	runtime·gosave(Gobuf*);
 void	runtime·lessstack(void);
 void	runtime·goargs(void);
+void	runtime·goenvs(void);
+void	runtime·goenvs_unix(void);
 void*	runtime·getu(void);
 void	runtime·throw(int8*);
 void	runtime·panicstring(int8*);
@@ -399,6 +402,7 @@
 String	runtime·gostring(byte*);
 String  runtime·gostringn(byte*, int32);
 String	runtime·gostringnocopy(byte*);
+String	runtime·gostringw(uint16*);
 void	runtime·initsig(int32);
 int32	runtime·gotraceback(void);
 void	runtime·traceback(uint8 *pc, uint8 *sp, uint8 *lr, G* gp);
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc
index 6752f31..916559e 100644
--- a/src/pkg/runtime/string.goc
+++ b/src/pkg/runtime/string.goc
@@ -20,6 +20,18 @@
 	return l;
 }
 
+int32
+runtime·findnullw(uint16 *s)
+{
+	int32 l;
+
+	if(s == nil)
+		return 0;
+	for(l=0; s[l]!=0; l++)
+		;
+	return l;
+}
+
 int32 runtime·maxstring = 256;
 
 String
@@ -69,6 +81,24 @@
 }
 
 String
+runtime·gostringw(uint16 *str)
+{
+	int32 n, i;
+	byte buf[8];
+	String s;
+
+	n = 0;
+	for(i=0; str[i]; i++)
+		n += runtime·runetochar(buf, str[i]);
+	s = runtime·gostringsize(n+4);
+	n = 0;
+	for(i=0; str[i]; i++)
+		n += runtime·runetochar(s.str+n, str[i]);
+	s.len = n;
+	return s;
+}
+
+String
 runtime·catstring(String s1, String s2)
 {
 	String s3;
diff --git a/src/pkg/runtime/tiny/thread.c b/src/pkg/runtime/tiny/thread.c
index b976a12..0572ecb 100644
--- a/src/pkg/runtime/tiny/thread.c
+++ b/src/pkg/runtime/tiny/thread.c
@@ -17,6 +17,12 @@
 }
 
 void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+void
 runtime·initsig(int32 queue)
 {
 }
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c
index 00cd0e8..9b51813 100644
--- a/src/pkg/runtime/windows/thread.c
+++ b/src/pkg/runtime/windows/thread.c
@@ -39,6 +39,42 @@
 {
 }
 
+#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW  "kernel32.dll"
+#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW  "kernel32.dll"
+
+extern void *runtime·GetEnvironmentStringsW;
+extern void *runtime·FreeEnvironmentStringsW;
+
+void
+runtime·goenvs(void)
+{
+	extern Slice os·Envs;
+
+	uint16 *env;
+	String *s;
+	int32 i, n;
+	uint16 *p;
+
+	env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0);
+
+	n = 0;
+	for(p=env; *p; n++)
+		p += runtime·findnullw(p)+1;
+
+	s = runtime·malloc(n*sizeof s[0]);
+
+	p = env;
+	for(i=0; i<n; i++) {
+		s[i] = runtime·gostringw(p);
+		p += runtime·findnullw(p)+1;
+	}
+	os·Envs.array = (byte*)s;
+	os·Envs.len = n;
+	os·Envs.cap = n;
+
+	runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env);
+}
+
 void
 runtime·exit(int32 code)
 {