Reimplement popen(3)/pclose(3).

pclose(3) is now an alias for fclose(3). We could add a FORTIFY check
that you use pclose(3) if and only if you used popen(3), but there seems
little value to that when we can just do the right thing.

This patch also adds the missing locking to _fwalk --- we need to lock
both the global list of FILE*s and also each FILE* we touch. POSIX says
that "The popen() function shall ensure that any streams from previous
popen() calls that remain open in the parent process are closed in the
new child process", which we implement via _fwalk(fclose) in the child,
but we might want to just make *all* popen(3) file descriptors O_CLOEXEC
in all cases.

Ignore fewer errors in popen(3) failure cases.

Improve popen(3) test coverage.

Bug: http://b/72470344
Test: ran tests
Change-Id: Ic937594bf28ec88b375f7e5825b9c05f500af438
diff --git a/libc/private/thread_private.h b/libc/private/thread_private.h
index 0081ad0..1f9eeb6 100644
--- a/libc/private/thread_private.h
+++ b/libc/private/thread_private.h
@@ -2,8 +2,7 @@
 
 /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
 
-#ifndef _THREAD_PRIVATE_H_
-#define _THREAD_PRIVATE_H_
+#pragma once
 
 #include <pthread.h>
 
@@ -16,33 +15,15 @@
  * described functions for operation in a non-threaded environment.
  */
 
-/*
- * helper macro to make unique names in the thread namespace
- */
-#define __THREAD_NAME(name)	__CONCAT(_thread_tagname_,name)
-
-struct __thread_private_tag_t {
-    pthread_mutex_t    _private_lock;
-    pthread_key_t      _private_key;
-};
-
-#define _THREAD_PRIVATE_MUTEX(name)  \
-	static struct __thread_private_tag_t  __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 }
-#define _THREAD_PRIVATE_MUTEX_LOCK(name)  \
-	pthread_mutex_lock( &__THREAD_NAME(name)._private_lock )
-#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
-	pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock )
+#define __MUTEX_NAME(name) __CONCAT(__libc_mutex_,name)
+#define _THREAD_PRIVATE_MUTEX(name) static pthread_mutex_t __MUTEX_NAME(name) = PTHREAD_MUTEX_INITIALIZER
+#define _THREAD_PRIVATE_MUTEX_LOCK(name) pthread_mutex_lock(&__MUTEX_NAME(name))
+#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) pthread_mutex_unlock(&__MUTEX_NAME(name))
 
 /* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
 #define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
 #define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
 
-__LIBC_HIDDEN__ void  _thread_atexit_lock(void);
-__LIBC_HIDDEN__ void  _thread_atexit_unlock(void);
-
-#define _ATEXIT_LOCK() _thread_atexit_lock()
-#define _ATEXIT_UNLOCK() _thread_atexit_unlock()
-
 __LIBC_HIDDEN__ void    _thread_arc4_lock(void);
 __LIBC_HIDDEN__ void    _thread_arc4_unlock(void);
 
@@ -53,5 +34,3 @@
 extern volatile sig_atomic_t _rs_forked;
 
 __END_DECLS
-
-#endif /* _THREAD_PRIVATE_H_ */