예제 #1
0
파일: osdep.c 프로젝트: ohmori7/kcn-tools
int
start_thread(void (*fn)(void *, int), void *ptr, int l)
{
	int p[2];
	pid_t pid;

	if (c_pipe(p) < 0) return -1;
	if (set_nonblocking_fd(p[0]) < 0) return -1;
	if (set_nonblocking_fd(p[1]) < 0) return -1;

	pid = fork();
	if (!pid) {
		struct terminal *term;

		/* Close input in this thread; otherwise, if it will live
		 * longer than its parent, it'll block the terminal until it'll
		 * quit as well; this way it will hopefully just die unseen and
		 * in background, causing no trouble. */
		/* Particularly, when async dns resolving was in progress and
		 * someone quitted ELinks, it could make a delay before the
		 * terminal would be really freed and returned to shell. */
		foreach (term, terminals)
			if (term->fdin > 0)
				close(term->fdin);

		close(p[0]);
		fn(ptr, p[1]);
		write(p[1], "x", 1);
		close(p[1]);
		/* We use _exit() here instead of exit(), see
		 * http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC6 for
		 * reasons. Fixed by Sven Neumann <*****@*****.**>. */
		_exit(0);
	}
	if (pid == -1) {
		close(p[0]);
		close(p[1]);
		return -1;
	}

	close(p[1]);
	return p[0];
}
예제 #2
0
파일: beos.c 프로젝트: Efreak/elinks
int
start_thread(void (*fn)(void *, int), void *ptr, int l)
{
	int p[2];
	struct tdata *t;

	if (c_pipe(p) < 0) return -1;

	t = malloc(sizeof(*t) + l);
	if (!t) return -1;
	t->fn = fn;
	t->h = p[1];
	memcpy(t->data, ptr, l);
	if (start_thr((void (*)(void *)) bgt, t, "elinks_thread") < 0) {
		close(p[0]);
		close(p[1]);
		mem_free(t);
		return -1;
	}

	return p[0];
}
예제 #3
0
void
mailcap_protocol_handler(struct connection *conn)
{
#ifdef HAVE_FORK
	unsigned char *script, *ref;
	pid_t pid;
	struct connection_state state = connection_state(S_OK);
	int pipe_read[2], check;

	/* security checks */
	if (!conn->referrer || conn->referrer->protocol != PROTOCOL_MAILCAP) {
		goto bad;
	}
	ref = get_uri_string(conn->referrer, URI_DATA);
	if (!ref) {
		goto bad;
	}
	check = strcmp(ref, "elmailcap");
	mem_free(ref);
	if (check) goto bad;
	
	script = get_uri_string(conn->uri, URI_DATA);
	if (!script) {
		state = connection_state(S_OUT_OF_MEM);
		goto end2;
	}

	if (c_pipe(pipe_read)) {
		state = connection_state_for_errno(errno);
		goto end1;
	}

	pid = fork();
	if (pid < 0) {
		state = connection_state_for_errno(errno);
		goto end0;
	}
	if (!pid) {
		if (dup2(pipe_read[1], STDOUT_FILENO) < 0) {
			_exit(2);
		}
		/* We implicitly chain stderr to ELinks' stderr. */
		close_all_non_term_fd();

		if (execl("/bin/sh", "/bin/sh", "-c", script, (char *) NULL)) {
			_exit(3);
		}

	} else { /* ELinks */
		mem_free(script);

		if (!init_http_connection_info(conn, 1, 0, 1)) {
			close(pipe_read[0]); close(pipe_read[1]);
			return;
		}

		close(pipe_read[1]);
		conn->socket->fd = pipe_read[0];

		conn->data_socket->fd = -1;
		conn->cgi = 1;
		set_nonblocking_fd(conn->socket->fd);

		get_request(conn);
		return;
	}

end0:
	close(pipe_read[0]); close(pipe_read[1]);
end1:
	mem_free(script);
end2:
	abort_connection(conn, state);
	return;
#endif
bad:
	abort_connection(conn, connection_state(S_BAD_URL));
}
예제 #4
0
파일: smb2.c 프로젝트: Efreak/elinks
void
smb_protocol_handler(struct connection *conn)
{
	int smb_pipe[2] = { -1, -1 };
	int header_pipe[2] = { -1, -1 };
	pid_t cpid;

	if (c_pipe(smb_pipe) || c_pipe(header_pipe)) {
		int s_errno = errno;

		if (smb_pipe[0] >= 0) close(smb_pipe[0]);
		if (smb_pipe[1] >= 0) close(smb_pipe[1]);
		if (header_pipe[0] >= 0) close(header_pipe[0]);
		if (header_pipe[1] >= 0) close(header_pipe[1]);
		abort_connection(conn, connection_state_for_errno(s_errno));
		return;
	}
	conn->from = 0;
	conn->unrestartable = 1;
	find_auth(conn->uri); /* remember username and password */

	cpid = fork();
	if (cpid == -1) {
		int s_errno = errno;

		close(smb_pipe[0]);
		close(smb_pipe[1]);
		close(header_pipe[0]);
		close(header_pipe[1]);
		retry_connection(conn, connection_state_for_errno(s_errno));
		return;
	}

	if (!cpid) {
		dup2(open("/dev/null", O_RDONLY), 0);
		close(1);
		close(2);
		data_out = fdopen(smb_pipe[1], "w");
		header_out = fdopen(header_pipe[1], "w");

		if (!data_out || !header_out) exit(1);

		close(smb_pipe[0]);
		close(header_pipe[0]);

		/* There may be outgoing data in stdio buffers
		 * inherited from the parent process.  The parent
		 * process is going to write this data, so the child
		 * process must not do that.  Closing the file
		 * descriptors ensures this.
		 *
		 * FIXME: If something opens more files and gets the
		 * same file descriptors and does not close them
		 * before exit(), then stdio may attempt to write the
		 * buffers to the wrong files.  This might happen for
		 * example if libsmbclient calls syslog().  */

		close_all_fds_but_two(smb_pipe[1], header_pipe[1]);
		do_smb(conn);

	} else {
		struct read_buffer *buf2;

		conn->data_socket->fd = smb_pipe[0];
		conn->socket->fd = header_pipe[0];
		set_nonblocking_fd(conn->data_socket->fd);
		set_nonblocking_fd(conn->socket->fd);
		close(smb_pipe[1]);
		close(header_pipe[1]);
		buf2 = alloc_read_buffer(conn->socket);
		if (!buf2) {
			close_socket(conn->data_socket);
			close_socket(conn->socket);
			abort_connection(conn, connection_state(S_OUT_OF_MEM));
			return;
		}
		read_from_socket(conn->socket, buf2,
				 connection_state(S_CONN), smb_got_header);
	}
}
예제 #5
0
파일: daemon.cpp 프로젝트: rucoder/ritex
void
daemon_t::_parent(
) {

    // http://www.freedesktop.org/software/systemd/man/daemon.html

    pipe_t c_pipe( "child"  );
    pipe_t g_pipe( "grandchild" );

    // TODO: Reset signal handlers?
    // TODO: Reset signal mask?
    // TODO: Sanitize environment?

    pid_t pid = 0;

    ESYSCALL(
        "forking child",
        "fork",
        pid = fork(),
        pid >= 0,
        "child forked " << ( pid == 0 ? "(i am child)" : "(i am parent)" )
    );

    if ( pid == 0 ) {
        _child( c_pipe, g_pipe );
        return;     // TODO: Or exit?
    };

    c_pipe.writer().close();
    g_pipe.writer().close();

    int error = 0;

    ESYSCALL(
        "anti-zombying child",
        "waitpid",
        error = waitpid( pid, NULL, WNOHANG ),
        error != -1,
        "child anti-zombied"
    );

    // Wait until child finishes initialization.
    string_t c_reply = c_pipe.reader().read();
    string_t g_reply = g_pipe.reader().read();

    // Report errors, if any.
    if ( c_reply != ok || g_reply != ok ) {
        osstream_t errors;
        if ( c_reply != ok ) {
            errors << "Child: ";
            if ( c_reply.empty() ) {
                errors << "Died silently";
            } else {
                errors << split( "\n", c_reply );
            };
        }; // if
        if ( g_reply != ok ) {
            if ( ! errors.str().empty() ) {
                errors << "; ";
            };
            errors << "Grandchild: ";
            if ( g_reply.empty() ) {
                errors << "Died silently";
            } else {
                errors << split( "\n", g_reply );
            };
        }; // if
        ERR(
            1,
            "Daemon initialization failed: " << errors.str()
        );
    }; // if

    c_pipe.reader().close();
    g_pipe.reader().close();

}; // _parent