Ejemplo n.º 1
0
int main() {
	int ret;
    int fd_A[2];

    if (pipe(fd_A) == -1) {
        perror("pipe");
        exit(1);
    }

	ret = fork();
	if (ret < 0) {
		perror("fork");
		exit(1);

	} else if (ret == 0) {
		/* I am the child and I will write only, so close reading end of pipe */
        // STEP 1: Add the close call below 
        if XXX  {
            perror("close");
            exit(1);
        }
        write_to_parent(fd_A[1]);
        exit(0);

	} 
    /* I am the parent only so close writing end of pipe to child A */
    // STEP 1: Add the close call below 



	read_from_child(fd_A[0]);
	return 0;
}
Ejemplo n.º 2
0
G_GNUC_NORETURN static void
purple_dnsquery_resolver_run(int child_out, int child_in, gboolean show_debug)
{
	dns_params_t dns_params;
	const size_t zero = 0;
	int rc;
#ifdef HAVE_GETADDRINFO
	struct addrinfo hints, *res, *tmp;
	char servname[20];
#else
	struct sockaddr_in sin;
	const size_t addrlen = sizeof(sin);
#endif
	char *hostname;

#ifdef HAVE_SIGNAL_H
	purple_restore_default_signal_handlers();
	signal(SIGTRAP, trap_gdb_bug);
#endif

	/*
	 * We resolve 1 host name for each iteration of this
	 * while loop.
	 *
	 * The top half of this reads in the hostname and port
	 * number from the socket with our parent.  The bottom
	 * half of this resolves the IP (blocking) and sends
	 * the result back to our parent, when finished.
	 */
	while (1) {
		fd_set fds;
		struct timeval tv = { .tv_sec = 20, .tv_usec = 0 };
		FD_ZERO(&fds);
		FD_SET(child_in, &fds);
		rc = select(child_in + 1, &fds, NULL, NULL, &tv);
		if (!rc) {
			if (show_debug)
				printf("dns[%d]: nobody needs me... =(\n", getpid());
			break;
		}
		rc = read(child_in, &dns_params, sizeof(dns_params_t));
		if (rc < 0) {
			fprintf(stderr, "dns[%d]: Error: Could not read dns_params: "
					"%s\n", getpid(), strerror(errno));
			break;
		}
		if (rc == 0) {
			if (show_debug)
				printf("dns[%d]: Oops, father has gone, wait for me, wait...!\n", getpid());
			_exit(0);
		}
		if (dns_params.hostname[0] == '\0') {
			fprintf(stderr, "dns[%d]: Error: Parent requested resolution "
					"of an empty hostname (port = %d)!!!\n", getpid(),
					dns_params.port);
			_exit(1);
		}

#ifdef USE_IDN
		if (!dns_str_is_ascii(dns_params.hostname)) {
			rc = purple_network_convert_idn_to_ascii(dns_params.hostname, &hostname);
			if (rc != 0) {
				write_to_parent(child_out, &rc, sizeof(rc));
				if (show_debug)
					fprintf(stderr, "dns[%d] Error: IDN conversion returned "
							"%d\n", getpid(), rc);
				dns_params.hostname[0] = '\0';
				break;
			}
		} else /* intentional to execute the g_strdup */
#endif
		hostname = g_strdup(dns_params.hostname);

		/* We have the hostname and port, now resolve the IP */

#ifdef HAVE_GETADDRINFO
		g_snprintf(servname, sizeof(servname), "%d", dns_params.port);
		memset(&hints, 0, sizeof(hints));

		/* This is only used to convert a service
		 * name to a port number. As we know we are
		 * passing a number already, we know this
		 * value will not be really used by the C
		 * library.
		 */
		hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
		hints.ai_flags |= AI_ADDRCONFIG;
#endif /* AI_ADDRCONFIG */
		rc = getaddrinfo(hostname, servname, &hints, &res);
		write_to_parent(child_out, &rc, sizeof(rc));
		if (rc != 0) {
			if (show_debug)
				printf("dns[%d] Error: getaddrinfo returned %d\n",
					getpid(), rc);
			dns_params.hostname[0] = '\0';
			g_free(hostname);
			hostname = NULL;
			break;
		}
		tmp = res;
		while (res) {
			size_t ai_addrlen = res->ai_addrlen;
			write_to_parent(child_out, &ai_addrlen, sizeof(ai_addrlen));
			write_to_parent(child_out, res->ai_addr, res->ai_addrlen);
			res = res->ai_next;
		}
		freeaddrinfo(tmp);
#else
		struct hostent *hp;
		if (!(hp = gethostbyname(hostname))) {
			write_to_parent(child_out, &h_errno, sizeof(int));
			close(child_out);
			if (show_debug)
				printf("DNS Error: %d\n", h_errno);
			_exit(0);
		}
		memset(&sin, 0, sizeof(struct sockaddr_in));
		memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
		sin.sin_family = hp->h_addrtype;

		sin.sin_port = htons(dns_params.port);
		rc = 0;
		write_to_parent(child_out, &rc, sizeof(rc));
		write_to_parent(child_out, &addrlen, sizeof(addrlen));
		write_to_parent(child_out, &sin, addrlen);
#endif
		write_to_parent(child_out, &zero, sizeof(zero));
		dns_params.hostname[0] = '\0';

		g_free(hostname);
		hostname = NULL;
	}

	close(child_out);
	close(child_in);

	_exit(0);
}
/*
 * End the DNS resolver child process functions.
 */

/*
 * Begin the functions for dealing with the DNS child processes.
 */
static void
cope_with_gdb_brokenness(void)
{
#ifdef __linux__
	static gboolean already_done = FALSE;
	char s[256], e[512];
	int n;
	pid_t ppid;

	if(already_done)
		return;
	already_done = TRUE;
	ppid = getppid();
	g_snprintf(s, sizeof(s), "/proc/%d/exe", ppid);
	n = readlink(s, e, sizeof(e));
	if(n < 0)
		return;

	e[MIN((gsize)n,sizeof(e)-1)] = '\0';

	if(strstr(e,"gdb")) {
		purple_debug_info("dns",
				   "Debugger detected, performing useless query...\n");
		gethostbyname("x.x.x.x.x");
	}
#endif
}

static void
purple_dnsquery_resolver_destroy(PurpleDnsQueryResolverProcess *resolver)
{
	g_return_if_fail(resolver != NULL);

	/* Keep this before the kill() call below. */
	if (resolver->inpa != 0) {
		purple_input_remove(resolver->inpa);
		resolver->inpa = 0;
	}

	/*
	 * We might as well attempt to kill our child process.  It really
	 * doesn't matter if this fails, because children will expire on
	 * their own after a few seconds.
	 */
	if (resolver->dns_pid > 0)
		kill(resolver->dns_pid, SIGKILL);

	close(resolver->fd_in);
	close(resolver->fd_out);

	g_free(resolver);

	number_of_dns_children--;
}