[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/build/uClibc/libc/stdio/popen.c b/ap/build/uClibc/libc/stdio/popen.c
new file mode 100644
index 0000000..d5c60cf
--- /dev/null
+++ b/ap/build/uClibc/libc/stdio/popen.c
@@ -0,0 +1,186 @@
+/* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ *
+ * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
+ */
+
+/* Jan 1, 2004
+ *
+ * Rewrite popen for SUSv3 compliance.
+ *   Added a list of popen()'d to store pids and use waitpid() in pclose().
+ *   Loop on waitpid() failure due to EINTR as required.
+ *   Close parent's popen()'d FILEs in the {v}fork()'d child.
+ *   Fix failure exit code for failed execve().
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <bits/uClibc_mutex.h>
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning "hmm... susv3 says Pipe streams are byte-oriented."
+#endif /* __UCLIBC_MJN3_ONLY__ */
+
+
+/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */
+#include <sys/syscall.h>
+#if ! defined __NR_vfork
+# define vfork fork
+# define VFORK_LOCK		((void) 0)
+# define VFORK_UNLOCK		((void) 0)
+#endif
+
+#ifndef VFORK_LOCK
+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
+# define VFORK_LOCK		__UCLIBC_MUTEX_LOCK(mylock)
+# define VFORK_UNLOCK		__UCLIBC_MUTEX_UNLOCK(mylock)
+#endif
+
+struct popen_list_item {
+	struct popen_list_item *next;
+	FILE *f;
+	pid_t pid;
+};
+
+static struct popen_list_item *popen_list /* = NULL (bss initialized) */;
+
+FILE *popen(const char *command, const char *modes)
+{
+	FILE *fp;
+	struct popen_list_item *pi;
+	struct popen_list_item *po;
+	int pipe_fd[2];
+	int parent_fd;
+	int child_fd;
+	int child_writing;			/* Doubles as the desired child fildes. */
+	pid_t pid;
+
+	child_writing = 0;			/* Assume child is writing. */
+	if (modes[0] != 'w') {		/* Parent not writing... */
+		++child_writing;		/* so child must be writing. */
+		if (modes[0] != 'r') {	/* Oops!  Parent not reading either! */
+			__set_errno(EINVAL);
+			goto RET_NULL;
+		}
+	}
+
+	if (!(pi = malloc(sizeof(struct popen_list_item)))) {
+		goto RET_NULL;
+	}
+
+	if (pipe(pipe_fd)) {
+		goto FREE_PI;
+	}
+
+	child_fd = pipe_fd[child_writing];
+	parent_fd = pipe_fd[1-child_writing];
+
+	if (!(fp = fdopen(parent_fd, modes))) {
+		close(parent_fd);
+		close(child_fd);
+		goto FREE_PI;
+	}
+
+	VFORK_LOCK;
+	if ((pid = vfork()) == 0) {	/* Child of vfork... */
+		close(parent_fd);
+		if (child_fd != child_writing) {
+			dup2(child_fd, child_writing);
+			close(child_fd);
+		}
+
+		/* SUSv3 requires that any previously popen()'d streams in the
+		 * parent shall be closed in the child. */
+		for (po = popen_list ; po ; po = po->next) {
+			close(po->f->__filedes);
+		}
+
+		execl("/bin/sh", "sh", "-c", command, (char *)0);
+
+		/* SUSv3 mandates an exit code of 127 for the child if the
+		 * command interpreter can not be invoked. */
+		_exit(127);
+	}
+	VFORK_UNLOCK;
+
+	/* We need to close the child filedes whether vfork failed or
+	 * it succeeded and we're in the parent. */
+	close(child_fd);
+
+	if (pid > 0) {				/* Parent of vfork... */
+		pi->pid = pid;
+		pi->f = fp;
+		VFORK_LOCK;
+		pi->next = popen_list;
+		popen_list = pi;
+		VFORK_UNLOCK;
+
+		return fp;
+	}
+
+	/* If we get here, vfork failed. */
+	fclose(fp);					/* Will close parent_fd. */
+
+ FREE_PI:
+	free(pi);
+
+ RET_NULL:
+	return NULL;
+}
+
+#warning is pclose correct wrt the new mutex semantics?
+
+int pclose(FILE *stream)
+{
+	struct popen_list_item *p;
+	int stat;
+	pid_t pid;
+
+	/* First, find the list entry corresponding to stream and remove it
+	 * from the list.  Set p to the list item (NULL if not found). */
+	VFORK_LOCK;
+	if ((p = popen_list) != NULL) {
+		if (p->f == stream) {
+			popen_list = p->next;
+		} else {
+			struct popen_list_item *t;
+			do {
+				t = p;
+				if (!(p = t->next)) {
+					__set_errno(EINVAL); /* Not required by SUSv3. */
+					break;
+				}
+				if (p->f == stream) {
+					t->next = p->next;
+					break;
+				}
+			} while (1);
+		}
+	}
+	VFORK_UNLOCK;
+
+	if (p) {
+		pid = p->pid;			/* Save the pid we need */
+		free(p);				/* and free the list item. */
+
+		fclose(stream);	/* The SUSv3 example code ignores the return. */
+
+		/* SUSv3 specificly requires that pclose not return before the child
+		 * terminates, in order to disallow pclose from returning on EINTR. */
+		do {
+			if (waitpid(pid, &stat, 0) >= 0) {
+				return stat;
+			}
+			if (errno != EINTR) {
+				break;
+			}
+		} while (1);
+	}
+
+	return -1;
+}