fork_exec(struct socket *so, const char *ex, int do_pty)

{

	int s;

	struct sockaddr_in addr;

	socklen_t addrlen = sizeof(addr);

	int opt;

	const char *argv[256];

	/* don't want to clobber the original */

	char *bptr;

	const char *curarg;

	int c, i, ret;

	pid_t pid;



	DEBUG_CALL("fork_exec");

	DEBUG_ARG("so = %p", so);

	DEBUG_ARG("ex = %p", ex);

	DEBUG_ARG("do_pty = %x", do_pty);



	if (do_pty == 2) {

                return 0;

	} else {

		addr.sin_family = AF_INET;

		addr.sin_port = 0;

		addr.sin_addr.s_addr = INADDR_ANY;



		if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||

		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||

		    listen(s, 1) < 0) {

			error_report("Error: inet socket: %s", strerror(errno));

			closesocket(s);



			return 0;

		}

	}



	pid = fork();

	switch(pid) {

	 case -1:

		error_report("Error: fork failed: %s", strerror(errno));

		close(s);

		return 0;



	 case 0:

                setsid();



		/* Set the DISPLAY */

                getsockname(s, (struct sockaddr *)&addr, &addrlen);

                close(s);

                /*

                 * Connect to the socket

                 * XXX If any of these fail, we're in trouble!

                 */

                s = qemu_socket(AF_INET, SOCK_STREAM, 0);

                addr.sin_addr = loopback_addr;

                do {

                    ret = connect(s, (struct sockaddr *)&addr, addrlen);

                } while (ret < 0 && errno == EINTR);



		dup2(s, 0);

		dup2(s, 1);

		dup2(s, 2);

		for (s = getdtablesize() - 1; s >= 3; s--)

		   close(s);



		i = 0;

		bptr = g_strdup(ex); /* No need to free() this */

		if (do_pty == 1) {

			/* Setup "slirp.telnetd -x" */

			argv[i++] = "slirp.telnetd";

			argv[i++] = "-x";

			argv[i++] = bptr;

		} else

		   do {

			/* Change the string into argv[] */

			curarg = bptr;

			while (*bptr != ' ' && *bptr != (char)0)

			   bptr++;

			c = *bptr;

			*bptr++ = (char)0;

			argv[i++] = g_strdup(curarg);

		   } while (c);



                argv[i] = NULL;

		execvp(argv[0], (char **)argv);



		/* Ooops, failed, let's tell the user why */

        fprintf(stderr, "Error: execvp of %s failed: %s\n",

                argv[0], strerror(errno));

		close(0); close(1); close(2); /* XXX */

		exit(1);



	 default:

		qemu_add_child_watch(pid);

                /*

                 * XXX this could block us...

                 * XXX Should set a timer here, and if accept() doesn't

                 * return after X seconds, declare it a failure

                 * The only reason this will block forever is if socket()

                 * of connect() fail in the child process

                 */

                do {

                    so->s = accept(s, (struct sockaddr *)&addr, &addrlen);

                } while (so->s < 0 && errno == EINTR);

                closesocket(s);

                socket_set_fast_reuse(so->s);

                opt = 1;

                qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));

		qemu_set_nonblock(so->s);



		/* Append the telnet options now */

                if (so->so_m != NULL && do_pty == 1)  {

			sbappend(so, so->so_m);

                        so->so_m = NULL;

		}



		return 1;

	}

}

fork_exec(struct socket *so, const char *ex, int do_pty)

{

	int s;

	struct sockaddr_in addr;

	socklen_t addrlen = sizeof(addr);

	int opt;

	const char *argv[256];

	

	char *bptr;

	const char *curarg;

	int c, i, ret;

	pid_t pid;



	DEBUG_CALL("fork_exec");

	DEBUG_ARG("so = %p", so);

	DEBUG_ARG("ex = %p", ex);

	DEBUG_ARG("do_pty = %x", do_pty);



	if (do_pty == 2) {

                return 0;

	} else {

		addr.sin_family = AF_INET;

		addr.sin_port = 0;

		addr.sin_addr.s_addr = INADDR_ANY;



		if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||

		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||

		    listen(s, 1) < 0) {

			error_report("Error: inet socket: %s", strerror(errno));

			closesocket(s);



			return 0;

		}

	}



	pid = fork();

	switch(pid) {

	 case -1:

		error_report("Error: fork failed: %s", strerror(errno));

		close(s);

		return 0;



	 case 0:

                setsid();



		

                getsockname(s, (struct sockaddr *)&addr, &addrlen);

                close(s);

                







                s = qemu_socket(AF_INET, SOCK_STREAM, 0);

                addr.sin_addr = loopback_addr;

                do {

                    ret = connect(s, (struct sockaddr *)&addr, addrlen);

                } while (ret < 0 && errno == EINTR);



		dup2(s, 0);

		dup2(s, 1);

		dup2(s, 2);

		for (s = getdtablesize() - 1; s >= 3; s--)

		   close(s);



		i = 0;

		bptr = g_strdup(ex); 

		if (do_pty == 1) {

			

			argv[i++] = "slirp.telnetd";

			argv[i++] = "-x";

			argv[i++] = bptr;

		} else

		   do {

			

			curarg = bptr;

			while (*bptr != ' ' && *bptr != (char)0)

			   bptr++;

			c = *bptr;

			*bptr++ = (char)0;

			argv[i++] = g_strdup(curarg);

		   } while (c);



                argv[i] = NULL;

		execvp(argv[0], (char **)argv);



		

        fprintf(stderr, "Error: execvp of %s failed: %s\n",

                argv[0], strerror(errno));

		close(0); close(1); close(2); 

		exit(1);



	 default:

		qemu_add_child_watch(pid);

                













                do {

                    so->s = accept(s, (struct sockaddr *)&addr, &addrlen);

                } while (so->s < 0 && errno == EINTR);

                closesocket(s);

                socket_set_fast_reuse(so->s);

                opt = 1;

                qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));

		qemu_set_nonblock(so->s);



		

                if (so->so_m != NULL && do_pty == 1)  {

			sbappend(so, so->so_m);

                        so->so_m = NULL;

		}



		return 1;

	}

}

			closesocket(s);
FUNC_0(struct socket *VAR_0, const char *VAR_1, int VAR_2)

{

	int VAR_3;

	struct sockaddr_in VAR_4;

	socklen_t addrlen = sizeof(VAR_4);

	int VAR_5;

	const char *VAR_6[256];

	

	char *VAR_7;

	const char *VAR_8;

	int VAR_9, VAR_10, VAR_11;

	pid_t pid;



	DEBUG_CALL("FUNC_0");

	DEBUG_ARG("VAR_0 = %p", VAR_0);

	DEBUG_ARG("VAR_1 = %p", VAR_1);

	DEBUG_ARG("VAR_2 = %x", VAR_2);



	if (VAR_2 == 2) {

                return 0;

	} else {

		VAR_4.sin_family = AF_INET;

		VAR_4.sin_port = 0;

		VAR_4.sin_addr.s_addr = INADDR_ANY;



		if ((VAR_3 = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||

		    bind(VAR_3, (struct sockaddr *)&VAR_4, addrlen) < 0 ||

		    listen(VAR_3, 1) < 0) {

			error_report("Error: inet socket: %VAR_3", strerror(errno));

			closesocket(VAR_3);



			return 0;

		}

	}



	pid = fork();

	switch(pid) {

	 case -1:

		error_report("Error: fork failed: %VAR_3", strerror(errno));

		close(VAR_3);

		return 0;



	 case 0:

                setsid();



		

                getsockname(VAR_3, (struct sockaddr *)&VAR_4, &addrlen);

                close(VAR_3);

                







                VAR_3 = qemu_socket(AF_INET, SOCK_STREAM, 0);

                VAR_4.sin_addr = loopback_addr;

                do {

                    VAR_11 = connect(VAR_3, (struct sockaddr *)&VAR_4, addrlen);

                } while (VAR_11 < 0 && errno == EINTR);



		dup2(VAR_3, 0);

		dup2(VAR_3, 1);

		dup2(VAR_3, 2);

		for (VAR_3 = getdtablesize() - 1; VAR_3 >= 3; VAR_3--)

		   close(VAR_3);



		VAR_10 = 0;

		VAR_7 = g_strdup(VAR_1); 

		if (VAR_2 == 1) {

			

			VAR_6[VAR_10++] = "slirp.telnetd";

			VAR_6[VAR_10++] = "-x";

			VAR_6[VAR_10++] = VAR_7;

		} else

		   do {

			

			VAR_8 = VAR_7;

			while (*VAR_7 != ' ' && *VAR_7 != (char)0)

			   VAR_7++;

			VAR_9 = *VAR_7;

			*VAR_7++ = (char)0;

			VAR_6[VAR_10++] = g_strdup(VAR_8);

		   } while (VAR_9);



                VAR_6[VAR_10] = NULL;

		execvp(VAR_6[0], (char **)VAR_6);



		

        fprintf(stderr, "Error: execvp of %VAR_3 failed: %VAR_3\n",

                VAR_6[0], strerror(errno));

		close(0); close(1); close(2); 

		exit(1);



	 default:

		qemu_add_child_watch(pid);

                













                do {

                    VAR_0->VAR_3 = accept(VAR_3, (struct sockaddr *)&VAR_4, &addrlen);

                } while (VAR_0->VAR_3 < 0 && errno == EINTR);

                closesocket(VAR_3);

                socket_set_fast_reuse(VAR_0->VAR_3);

                VAR_5 = 1;

                qemu_setsockopt(VAR_0->VAR_3, SOL_SOCKET, SO_OOBINLINE, &VAR_5, sizeof(int));

		qemu_set_nonblock(VAR_0->VAR_3);



		

                if (VAR_0->so_m != NULL && VAR_2 == 1)  {

			sbappend(VAR_0, VAR_0->so_m);

                        VAR_0->so_m = NULL;

		}



		return 1;

	}

}

FUNC_0(struct socket *VAR_0, const char *VAR_1, int VAR_2)
{ int VAR_3; struct sockaddr_in VAR_4; socklen_t addrlen = sizeof(VAR_4); int VAR_5; const char *VAR_6[256]; char *VAR_7; const char *VAR_8; int VAR_9, VAR_10, VAR_11; pid_t pid; DEBUG_CALL("FUNC_0"); DEBUG_ARG("VAR_0 = %p", VAR_0); DEBUG_ARG("VAR_1 = %p", VAR_1); DEBUG_ARG("VAR_2 = %x", VAR_2); if (VAR_2 == 2) { return 0; } else { VAR_4.sin_family = AF_INET; VAR_4.sin_port = 0; VAR_4.sin_addr.s_addr = INADDR_ANY; if ((VAR_3 = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
bind(VAR_3, (struct sockaddr *)&VAR_4, addrlen) < 0 ||
listen(VAR_3, 1) < 0) { error_report("Error: inet socket: %VAR_3", strerror(errno)); closesocket(VAR_3); return 0; } } pid = fork(); switch(pid) { case -1:
error_report("Error: fork failed: %VAR_3", strerror(errno)); close(VAR_3); return 0; case 0:
setsid(); getsockname(VAR_3, (struct sockaddr *)&VAR_4, &addrlen); close(VAR_3); VAR_3 = qemu_socket(AF_INET, SOCK_STREAM, 0); VAR_4.sin_addr = loopback_addr; do { VAR_11 = connect(VAR_3, (struct sockaddr *)&VAR_4, addrlen); } while (VAR_11 < 0 && errno == EINTR); dup2(VAR_3, 0); dup2(VAR_3, 1); dup2(VAR_3, 2); for (VAR_3 = getdtablesize() - 1; VAR_3 >= 3; VAR_3--) close(VAR_3); VAR_10 = 0; VAR_7 = g_strdup(VAR_1); if (VAR_2 == 1) { VAR_6[VAR_10++] = "slirp.telnetd"; VAR_6[VAR_10++] = "-x"; VAR_6[VAR_10++] = VAR_7; } else do { VAR_8 = VAR_7; while (*VAR_7 != ' ' && *VAR_7 != (char)0)
VAR_7++; VAR_9 = *VAR_7; *VAR_7++ = (char)0; VAR_6[VAR_10++] = g_strdup(VAR_8); } while (VAR_9); VAR_6[VAR_10] = NULL; execvp(VAR_6[0], (char **)VAR_6); fprintf(stderr, "Error: execvp of %VAR_3 failed: %VAR_3\n",
VAR_6[0], strerror(errno)); close(0); close(1); close(2); exit(1); default:
qemu_add_child_watch(pid); do { VAR_0->VAR_3 = accept(VAR_3, (struct sockaddr *)&VAR_4, &addrlen); } while (VAR_0->VAR_3 < 0 && errno == EINTR); closesocket(VAR_3); socket_set_fast_reuse(VAR_0->VAR_3); VAR_5 = 1; qemu_setsockopt(VAR_0->VAR_3, SOL_SOCKET, SO_OOBINLINE, &VAR_5, sizeof(int)); qemu_set_nonblock(VAR_0->VAR_3); if (VAR_0->so_m != NULL && VAR_2 == 1)  { sbappend(VAR_0, VAR_0->so_m); VAR_0->so_m = NULL; } return 1; } }