Beispiel #1
0
void *update_ipc(void *data)
{
	char *socket_path = getenv("I3SOCK");
	char *i3_default_sock_path = "/tmp/i3-ipc.sock";

	main_loop = ev_default_loop(0);

	if (socket_path == NULL) {
		ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path);
		socket_path = i3_default_sock_path;
	}

	if (init_connection(socket_path)) {
		/* We subscribe to the i3-events we need */
		subscribe_events();

		/* Get current workspaces from i3. */
		i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
	}

	ev_loop(main_loop, 0);
}
Beispiel #2
0
int main(int argc, char* argv[])
{
signal( SIGTRAP, SIG_IGN );
params p = get_params( argc, argv );
unistd::addrinfo hint = addrinfo{ 0, AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0, nullptr, nullptr, nullptr };
std::vector<unistd::addrinfo> addrs = unistd::getaddrinfo( p.hostname, p.port, hint );
const unistd::addrinfo& addr = addrs.at( 0 );
unistd::fd sock = unistd::socket( addr );
subscribe_events( sock );

if ( 0 != p.sndbuf )
    unistd::setsockopt( sock, SOL_SOCKET, SO_SNDBUF, p.sndbuf );

if ( 0 != p.mtu )
    {
    unistd::setsockopt( sock, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IP_PMTUDISC_DONT );
    unistd::setsockopt( sock, IPPROTO_IPV6, IPV6_MTU, p.mtu );
    }

if ( p.nodelay )
    unistd::setsockopt( sock, SOL_SCTP, SCTP_NODELAY, 1 );

if ( 0 != p.max_burst )
    unistd::setsockopt( sock, SOL_SCTP, SCTP_MAX_BURST, p.max_burst );

if ( 0 != p.maxseg )
    unistd::setsockopt( sock, SOL_SCTP, SCTP_MAXSEG, p.maxseg );

int sndbuf = 0;
socklen_t len = sizeof(sndbuf);
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len );
fprintf( stderr, "sndbuf: set=%d get=%d\n", p.sndbuf, sndbuf );

if ( 0 != p.rcvbuf )
    unistd::setsockopt( sock, SOL_SOCKET, SO_RCVBUF, p.rcvbuf );

sctp_initmsg init_params;
memset( &init_params, 0, sizeof(init_params) );
init_params.sinit_num_ostreams = 1;
init_params.sinit_max_instreams = 1;
init_params.sinit_max_attempts = 3;
init_params.sinit_max_init_timeo = 100;
unistd::setsockopt( sock, SOL_SCTP, SCTP_INITMSG, init_params );

unistd::connect( sock, addr );

sctp_assoc_t assoc_id = 0;
while ( assoc_id == 0 )
    {
    std::vector<char> cmsg_buff( CMSG_SPACE( sizeof( sctp_sndrcvinfo ) ) );
    std::vector<char> msg_buff( 8192 ); //TODO:

    struct iovec iov;
    memset( &iov, 0, sizeof(iov) );
    iov.iov_base = msg_buff.data();
    iov.iov_len = msg_buff.size();

    struct msghdr hdr;
    memset( &hdr, 0, sizeof(hdr) );
    hdr.msg_name = nullptr;
    hdr.msg_namelen = 0;
    hdr.msg_iov = &iov;
    hdr.msg_iovlen = 1;
    hdr.msg_control = cmsg_buff.data();
    hdr.msg_controllen = cmsg_buff.size();
    hdr.msg_flags = 0;

    ssize_t nrecv = 0;
    TEMP_FAILURE_RETRY( nrecv = recvmsg( sock, &hdr, 0 ) );
    if ( 0 == nrecv )
        raise( SIGTRAP );
    if ( -1 == nrecv )
        raise( SIGTRAP );
    if ( hdr.msg_flags & MSG_NOTIFICATION )
        {
        const sctp_notification& notify = *reinterpret_cast<const sctp_notification*>( hdr.msg_iov[0].iov_base );
        switch ( notify.sn_header.sn_type )
            {
            case SCTP_ASSOC_CHANGE:
                {
                const auto& sac = notify.sn_assoc_change;
        std::cout << " assoc_id=" << sac.sac_assoc_id << " error=" << sac.sac_error << " in=" << sac.sac_inbound_streams << " out=" << sac.sac_outbound_streams << std::endl;
                assoc_id = sac.sac_assoc_id;
                break;
                }
            case SCTP_REMOTE_ERROR:
                {
                const auto& sre = notify.sn_remote_error;
                printf( "^^^ remote_error: err=%hu len=%hu\n", ntohs(sre.sre_error), ntohs(sre.sre_length) );
                return EXIT_FAILURE;
                }
            case SCTP_SHUTDOWN_EVENT:
                {
                printf( "^^^ SCTP_SHUTDOWN_EVENT\n" );
                return EXIT_FAILURE;
                }
            }
        }
    }

//int flags = fcntl( sock, F_GETFL, 0 );
//fcntl( sock, F_SETFL, flags | O_NONBLOCK );

const std::vector<char> msg = generate_message( p.msgsize );
struct iovec iov;
iov.iov_base = const_cast<char*>( msg.data() );
iov.iov_len = msg.size();
std::vector<char> cmsg_buff( CMSG_SPACE( sizeof( sctp_sndrcvinfo ) ) );

struct mmsghdr mhdr;
memset( &mhdr, 0, sizeof(mhdr) );
struct msghdr& hdr = mhdr.msg_hdr;
hdr.msg_name = nullptr;
hdr.msg_namelen = 0;
hdr.msg_iov = &iov;
hdr.msg_iovlen = 1;
hdr.msg_flags = 0;
hdr.msg_control = cmsg_buff.data();
hdr.msg_controllen = cmsg_buff.size();

cmsghdr* cmsg = CMSG_FIRSTHDR( &hdr );
cmsg->cmsg_level = IPPROTO_SCTP;
cmsg->cmsg_type = SCTP_SNDRCV;
cmsg->cmsg_len = CMSG_LEN( sizeof( sctp_sndrcvinfo ) );
sctp_sndrcvinfo& cmsg_data = *reinterpret_cast<sctp_sndrcvinfo*>( CMSG_DATA( cmsg ) );
cmsg_data.sinfo_stream = 0;
cmsg_data.sinfo_ssn = 0; //ignored
cmsg_data.sinfo_flags = SCTP_UNORDERED;
cmsg_data.sinfo_ppid = 31337;
cmsg_data.sinfo_context = 123456;
cmsg_data.sinfo_timetolive = 0;
cmsg_data.sinfo_tsn = 0; //ignored
cmsg_data.sinfo_cumtsn = 0; //ignored
cmsg_data.sinfo_assoc_id = assoc_id;

std::vector<mmsghdr> mhdrs( p.batch, mhdr );

while ( p.count )
    {
    const ssize_t count = std::min<uint64_t>( p.batch, p.count );
    ssize_t nsend = 0;
    TEMP_FAILURE_RETRY( nsend = sendmmsg( sock, mhdrs.data(), count, 0 ) );
    if ( 0 == nsend )
        raise( SIGTRAP );
    if ( -1 == nsend )
        raise( SIGTRAP );
    if ( count != nsend )
        raise( SIGTRAP );
    p.count -= count;
    }

//raise( SIGTRAP );

sock.close();
return EXIT_SUCCESS;
}
Beispiel #3
0
int main(int argc, char **argv) {
    int opt;
    int option_index = 0;
    char *socket_path = getenv("I3SOCK");
    char *command = NULL;
    char *fontname = NULL;
    char *i3_default_sock_path = "/tmp/i3-ipc.sock";
    struct xcb_color_strings_t colors = { NULL, };

    /* Definition of the standard-config */
    config.hide_on_modifier = 0;
    config.dockpos = DOCKPOS_NONE;
    config.disable_ws = 0;

    static struct option long_opt[] = {
        { "socket",               required_argument, 0, 's' },
        { "command",              required_argument, 0, 'c' },
        { "hide",                 no_argument,       0, 'm' },
        { "dock",                 optional_argument, 0, 'd' },
        { "font",                 required_argument, 0, 'f' },
        { "nows",                 no_argument,       0, 'w' },
        { "help",                 no_argument,       0, 'h' },
        { "version",              no_argument,       0, 'v' },
        { "verbose",              no_argument,       0, 'V' },
        { "color-bar-fg",         required_argument, 0, 'A' },
        { "color-bar-bg",         required_argument, 0, 'B' },
        { "color-active-ws-fg",   required_argument, 0, 'C' },
        { "color-active-ws-bg",   required_argument, 0, 'D' },
        { "color-inactive-ws-fg", required_argument, 0, 'E' },
        { "color-inactive-ws-bg", required_argument, 0, 'F' },
        { "color-urgent-ws-bg",   required_argument, 0, 'G' },
        { "color-urgent-ws-fg",   required_argument, 0, 'H' },
        { "color-focus-ws-bg",    required_argument, 0, 'I' },
        { "color-focus-ws-fg",    required_argument, 0, 'J' },
        { NULL,                   0,                 0, 0}
    };

    while ((opt = getopt_long(argc, argv, "s:c:d::mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) {
        switch (opt) {
            case 's':
                socket_path = expand_path(optarg);
                break;
            case 'c':
                command = strdup(optarg);
                break;
            case 'm':
                config.hide_on_modifier = 1;
                break;
            case 'd':
                config.hide_on_modifier = 0;
                if (optarg == NULL) {
                    config.dockpos = DOCKPOS_BOT;
                    break;
                }
                if (!strcmp(optarg, "top")) {
                    config.dockpos = DOCKPOS_TOP;
                } else if (!strcmp(optarg, "bottom")) {
                    config.dockpos = DOCKPOS_BOT;
                } else {
                    print_usage(argv[0]);
                    exit(EXIT_FAILURE);
                }
                break;
            case 'f':
                fontname = strdup(optarg);
                break;
            case 'w':
                config.disable_ws = 1;
                break;
            case 'v':
                printf("i3bar version " I3_VERSION " © 2010-2011 Axel Wagner and contributors\n");
                exit(EXIT_SUCCESS);
                break;
            case 'V':
                config.verbose = 1;
                break;
            case 'A':
                read_color(&colors.bar_fg);
                break;
            case 'B':
                read_color(&colors.bar_bg);
                break;
            case 'C':
                read_color(&colors.active_ws_fg);
                break;
            case 'D':
                read_color(&colors.active_ws_bg);
                break;
            case 'E':
                read_color(&colors.inactive_ws_fg);
                break;
            case 'F':
                read_color(&colors.inactive_ws_bg);
                break;
            case 'G':
                read_color(&colors.urgent_ws_bg);
                break;
            case 'H':
                read_color(&colors.urgent_ws_fg);
                break;
            case 'I':
                read_color(&colors.focus_ws_bg);
                break;
            case 'J':
                read_color(&colors.focus_ws_fg);
                break;
            default:
                print_usage(argv[0]);
                exit(EXIT_SUCCESS);
                break;
        }
    }

    if (fontname == NULL) {
        /* This is a very restrictive default. More sensefull would be something like
         * "-misc-*-*-*-*--*-*-*-*-*-*-*-*". But since that produces very ugly results
         * on my machine, let's stick with this until we have a configfile */
        fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1";
    }

    if (config.dockpos != DOCKPOS_NONE) {
        if (config.hide_on_modifier) {
            ELOG("--dock and --hide are mutually exclusive!\n");
            exit(EXIT_FAILURE);
        }
    } else {
        config.hide_on_modifier = 1;
    }

    main_loop = ev_default_loop(0);

    init_colors(&colors);
    char *atom_sock_path = init_xcb(fontname);

    if (socket_path == NULL) {
        socket_path = atom_sock_path;
    }

    if (socket_path == NULL) {
        ELOG("No Socket Path Specified, default to %s\n", i3_default_sock_path);
        socket_path = expand_path(i3_default_sock_path);
    }

    free_colors(&colors);

    init_outputs();
    if (init_connection(socket_path)) {
        /* We subscribe to the i3-events we need */
        subscribe_events();

        /* We initiate the main-function by requesting infos about the outputs and
         * workspaces. Everything else (creating the bars, showing the right workspace-
         * buttons and more) is taken care of by the event-driveniness of the code */
        i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL);
        if (!config.disable_ws) {
            i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
        }
    }

    /* The name of this function is actually misleading. Even if no -c is specified,
     * this function initiates the watchers to listen on stdin and react accordingly */
    start_child(command);
    FREE(command);

    /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop.
     * We only need those watchers on the stack, so putting them on the stack saves us
     * some calls to free() */
    ev_signal *sig_term = malloc(sizeof(ev_signal));
    ev_signal *sig_int = malloc(sizeof(ev_signal));
    ev_signal *sig_hup = malloc(sizeof(ev_signal));

    if (sig_term == NULL || sig_int == NULL || sig_hup == NULL) {
        ELOG("malloc() failed: %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }

    ev_signal_init(sig_term, &sig_cb, SIGTERM);
    ev_signal_init(sig_int, &sig_cb, SIGINT);
    ev_signal_init(sig_hup, &sig_cb, SIGHUP);

    ev_signal_start(main_loop, sig_term);
    ev_signal_start(main_loop, sig_int);
    ev_signal_start(main_loop, sig_hup);

    /* From here on everything should run smooth for itself, just start listening for
     * events. We stop simply stop the event-loop, when we are finished */
    ev_loop(main_loop, 0);

    kill_child();

    FREE(statusline_buffer);

    clean_xcb();
    ev_default_destroy();

    free_workspaces();

    return 0;
}