예제 #1
0
ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
    ssize_t r;

    pa_assert(io);
    pa_assert(data);
    pa_assert(l);
    pa_assert(io->ofd >= 0);

    r = pa_write(io->ofd, data, l, &io->ofd_type);

    if ((size_t) r == l)
        return r; /* Fast path - we almost always successfully write everything */

    if (r < 0) {
        if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
            r = 0;
        else
            return r;
    }

    /* Partial write - let's get a notification when we can write more */
    io->writable = io->hungup = false;
    enable_events(io);

    return r;
}
예제 #2
0
static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
    pa_iochannel *io = userdata;
    bool changed = false;

    pa_assert(m);
    pa_assert(e);
    pa_assert(fd >= 0);
    pa_assert(userdata);

    if ((f & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) && !io->hungup) {
        io->hungup = true;
        changed = true;
    }

    if ((f & PA_IO_EVENT_INPUT) && !io->readable) {
        io->readable = true;
        changed = true;
        pa_assert(e == io->input_event);
    }

    if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
        io->writable = true;
        changed = true;
        pa_assert(e == io->output_event);
    }

    if (changed) {
        enable_events(io);

        if (io->callback)
            io->callback(io, io->userdata);
    }
}
예제 #3
0
int create_live_local_session(char **session_path, char **session_name, int print)
{
	int ret;
	char *name;
	int sudo = 0;

	ret = check_requirements(&sudo);

	name = random_session_name();
	if (!name) {
		ret = -1;
		goto end;
	}

	ret = check_session_name(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = live_local_session(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = enable_events(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = add_contexts(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = start(name, sudo, 0, print);
	if (ret < 0) {
		goto end_free;
	}

	if (session_path)
		*session_path = live_path(name);
	if (session_name) {
		*session_name = name;
		goto end;
	}

end_free:
	free(name);
end:
	return ret;
}
예제 #4
0
/* For more details on FD passing, check the cmsg(3) manpage
 * and IETF RFC #2292: "Advanced Sockets API for IPv6" */
ssize_t pa_iochannel_write_with_fds(pa_iochannel*io, const void*data, size_t l, int nfd, const int *fds) {
    ssize_t r;
    int *msgdata;
    struct msghdr mh;
    struct iovec iov;
    union {
        struct cmsghdr hdr;
        uint8_t data[CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
    } cmsg;

    pa_assert(io);
    pa_assert(data);
    pa_assert(l);
    pa_assert(io->ofd >= 0);
    pa_assert(fds);
    pa_assert(nfd > 0);
    pa_assert(nfd <= MAX_ANCIL_DATA_FDS);

    pa_zero(iov);
    iov.iov_base = (void*) data;
    iov.iov_len = l;

    pa_zero(cmsg);
    cmsg.hdr.cmsg_level = SOL_SOCKET;
    cmsg.hdr.cmsg_type = SCM_RIGHTS;

    msgdata = (int*) CMSG_DATA(&cmsg.hdr);
    memcpy(msgdata, fds, nfd * sizeof(int));
    cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int) * nfd);

    pa_zero(mh);
    mh.msg_iov = &iov;
    mh.msg_iovlen = 1;
    mh.msg_control = &cmsg;

    /* If we followed the example on the cmsg man page, we'd use
     * sizeof(cmsg.data) here, but if nfd < MAX_ANCIL_DATA_FDS, then the data
     * buffer is larger than needed, and the kernel doesn't like it if we set
     * msg_controllen to a larger than necessary value. The commit message for
     * commit 451d1d6762 contains a longer explanation. */
    mh.msg_controllen = CMSG_SPACE(sizeof(int) * nfd);

    if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
        io->writable = io->hungup = false;
        enable_events(io);
    }
    return r;
}
예제 #5
0
ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l, const pa_creds *ucred) {
    ssize_t r;
    struct msghdr mh;
    struct iovec iov;
    union {
        struct cmsghdr hdr;
        uint8_t data[CMSG_SPACE(sizeof(struct ucred))];
    } cmsg;
    struct ucred *u;

    pa_assert(io);
    pa_assert(data);
    pa_assert(l);
    pa_assert(io->ofd >= 0);

    pa_zero(iov);
    iov.iov_base = (void*) data;
    iov.iov_len = l;

    pa_zero(cmsg);
    cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(struct ucred));
    cmsg.hdr.cmsg_level = SOL_SOCKET;
    cmsg.hdr.cmsg_type = SCM_CREDENTIALS;

    u = (struct ucred*) CMSG_DATA(&cmsg.hdr);

    u->pid = getpid();
    if (ucred) {
        u->uid = ucred->uid;
        u->gid = ucred->gid;
    } else {
        u->uid = getuid();
        u->gid = getgid();
    }

    pa_zero(mh);
    mh.msg_iov = &iov;
    mh.msg_iovlen = 1;
    mh.msg_control = &cmsg;
    mh.msg_controllen = sizeof(cmsg);

    if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
        io->writable = io->hungup = false;
        enable_events(io);
    }

    return r;
}
예제 #6
0
ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
    ssize_t r;

    pa_assert(io);
    pa_assert(data);
    pa_assert(io->ifd >= 0);

    if ((r = pa_read(io->ifd, data, l, &io->ifd_type)) >= 0) {

        /* We also reset the hangup flag here to ensure that another
         * IO callback is triggered so that we will again call into
         * user code */
        io->readable = io->hungup = false;
        enable_events(io);
    }

    return r;
}
예제 #7
0
int create_local_session()
{
	int ret;
	char *name;
	int sudo = 0;

	ret = check_requirements(&sudo);

	name = random_session_name();
	if (!name) {
		ret = -1;
		goto end;
	}

	ret = check_session_name(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = local_session(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = enable_events(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = add_contexts(name, sudo);
	if (ret < 0) {
		goto end_free;
	}

	ret = start(name, sudo, 1, 1);
	if (ret < 0) {
		goto end_free;
	}

end_free:
	free(name);
end:
	return ret;
}
예제 #8
0
pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
    pa_iochannel *io;

    pa_assert(m);
    pa_assert(ifd >= 0 || ofd >= 0);

    io = pa_xnew0(pa_iochannel, 1);
    io->ifd = ifd;
    io->ofd = ofd;
    io->mainloop = m;

    if (io->ifd >= 0)
        pa_make_fd_nonblock(io->ifd);

    if (io->ofd >= 0 && io->ofd != io->ifd)
        pa_make_fd_nonblock(io->ofd);

    enable_events(io);
    return io;
}
예제 #9
0
    scroll_bar::
    scroll_bar(  
        drawable_window& w,
        bar_orientation orientation 
    ) :
        drawable(w),
        width_(16),
        b1(w,arrow_button::UP),
        b2(w,arrow_button::DOWN),
        slider(w,*this,&scroll_bar::on_slider_drag),
        ori(orientation),
        top_filler(w,*this,&scroll_bar::top_filler_down,&scroll_bar::top_filler_up),
        bottom_filler(w,*this,&scroll_bar::bottom_filler_down,&scroll_bar::bottom_filler_up),
        pos(0),
        max_pos(0),
        js(10),
        b1_timer(*this,&scroll_bar::b1_down_t),
        b2_timer(*this,&scroll_bar::b2_down_t),
        top_filler_timer(*this,&scroll_bar::top_filler_down_t),
        bottom_filler_timer(*this,&scroll_bar::bottom_filler_down_t)
    {
        if (ori == HORIZONTAL)
        {
            b1.set_direction(arrow_button::LEFT);
            b2.set_direction(arrow_button::RIGHT);
        }

        // don't show the slider when there is no place it can move.
        slider.hide();

        set_length(100);

        b1.set_button_down_handler(*this,&scroll_bar::b1_down);
        b2.set_button_down_handler(*this,&scroll_bar::b2_down);

        b1.set_button_up_handler(*this,&scroll_bar::b1_up);
        b2.set_button_up_handler(*this,&scroll_bar::b2_up);
        b1.disable();
        b2.disable();
        enable_events();
    }
예제 #10
0
/*
 * Add event to trace session
 */
int cmd_enable_events(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	char *session_name = NULL;
	const char *leftover = NULL;
	int event_type = -1;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	/* Default event type */
	opt_event_type = LTTNG_EVENT_ALL;

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_TRACEPOINT:
			opt_event_type = LTTNG_EVENT_TRACEPOINT;
			break;
		case OPT_PROBE:
			opt_event_type = LTTNG_EVENT_PROBE;
			break;
		case OPT_USERSPACE_PROBE:
			opt_event_type = LTTNG_EVENT_USERSPACE_PROBE;
			break;
		case OPT_FUNCTION:
			opt_event_type = LTTNG_EVENT_FUNCTION;
			break;
		case OPT_SYSCALL:
			opt_event_type = LTTNG_EVENT_SYSCALL;
			break;
		case OPT_USERSPACE:
			opt_userspace = 1;
			break;
		case OPT_LOGLEVEL:
			opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
			opt_loglevel = poptGetOptArg(pc);
			break;
		case OPT_LOGLEVEL_ONLY:
			opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
			opt_loglevel = poptGetOptArg(pc);
			break;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		case OPT_FILTER:
			break;
		case OPT_EXCLUDE:
			break;
		default:
			ret = CMD_UNDEFINED;
			goto end;
		}

		/* Validate event type. Multiple event type are not supported. */
		if (event_type == -1) {
			event_type = opt_event_type;
		} else {
			if (event_type != opt_event_type) {
				ERR("Multiple event type not supported.");
				ret = CMD_ERROR;
				goto end;
			}
		}
	}

	ret = print_missing_or_multiple_domains(
		opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_python);
	if (ret) {
		ret = CMD_ERROR;
		goto end;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_enable_event);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	opt_event_list = (char*) poptGetArg(pc);
	if (opt_event_list == NULL && opt_enable_all == 0) {
		ERR("Missing event name(s).\n");
		ret = CMD_ERROR;
		goto end;
	}

	leftover = poptGetArg(pc);
	if (leftover) {
		ERR("Unknown argument: %s", leftover);
		ret = CMD_ERROR;
		goto end;
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			command_ret = CMD_ERROR;
			success = 0;
			goto mi_closing;
		}
	} else {
		session_name = opt_session_name;
	}

	command_ret = enable_events(session_name);
	if (command_ret) {
		success = 0;
		goto mi_closing;
	}

mi_closing:
	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
	}

	if (opt_session_name == NULL) {
		free(session_name);
	}

	/* Overwrite ret if an error occurred in enable_events */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
예제 #11
0
ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l, pa_cmsg_ancil_data *ancil_data) {
    ssize_t r;
    struct msghdr mh;
    struct iovec iov;
    union {
        struct cmsghdr hdr;
        uint8_t data[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
    } cmsg;

    pa_assert(io);
    pa_assert(data);
    pa_assert(l);
    pa_assert(io->ifd >= 0);
    pa_assert(ancil_data);

    if (io->ifd_type > 0) {
        ancil_data->creds_valid = false;
        ancil_data->nfd = 0;
        return pa_iochannel_read(io, data, l);
    }

    iov.iov_base = data;
    iov.iov_len = l;

    pa_zero(mh);
    mh.msg_iov = &iov;
    mh.msg_iovlen = 1;
    mh.msg_control = &cmsg;
    mh.msg_controllen = sizeof(cmsg);

    if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) {
        struct cmsghdr *cmh;

        ancil_data->creds_valid = false;
        ancil_data->nfd = 0;

        for (cmh = CMSG_FIRSTHDR(&mh); cmh; cmh = CMSG_NXTHDR(&mh, cmh)) {

            if (cmh->cmsg_level != SOL_SOCKET)
                continue;

            if (cmh->cmsg_type == SCM_CREDENTIALS) {
                struct ucred u;
                pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
                memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred));

                ancil_data->creds.gid = u.gid;
                ancil_data->creds.uid = u.uid;
                ancil_data->creds_valid = true;
            }
            else if (cmh->cmsg_type == SCM_RIGHTS) {
                int nfd = (cmh->cmsg_len - CMSG_LEN(0)) / sizeof(int);
                if (nfd > MAX_ANCIL_DATA_FDS) {
                    int i;
                    pa_log("Trying to receive too many file descriptors!");
                    for (i = 0; i < nfd; i++)
                        pa_close(((int*) CMSG_DATA(cmh))[i]);
                    continue;
                }
                memcpy(ancil_data->fds, CMSG_DATA(cmh), nfd * sizeof(int));
                ancil_data->nfd = nfd;
                ancil_data->close_fds_on_cleanup = true;
            }
        }

        io->readable = io->hungup = false;
        enable_events(io);
    }

    if (r == -1 && errno == ENOTSOCK) {
        io->ifd_type = 1;
        return pa_iochannel_read_with_ancil_data(io, data, l, ancil_data);
    }

    return r;
}