- fd_set descriptors;
- char socket_path[MAXLEN];
- char *fifo_path = NULL;
- config_path[0] = '\0';
- status_prefix = NULL;
- int sock_fd, ret_fd, dpy_fd, sel, n;
- struct sockaddr_un sock_address;
- size_t rsp_len = 0;
- char msg[BUFSIZ] = {0};
- char rsp[BUFSIZ] = {0};
- xcb_generic_event_t *event;
- char opt;
-
- while ((opt = getopt(argc, argv, "hvc:s:p:")) != -1) {
- switch (opt) {
- case 'h':
- printf(WM_NAME " [-h|-v|-c CONFIG_PATH|-s PANEL_FIFO|-p PANEL_PREFIX]\n");
- exit(EXIT_SUCCESS);
- break;
- case 'v':
- printf("%s\n", VERSION);
- exit(EXIT_SUCCESS);
- break;
- case 'c':
- snprintf(config_path, sizeof(config_path), "%s", optarg);
- break;
- case 's':
- fifo_path = optarg;
- break;
- case 'p':
- status_prefix = optarg;
- break;
- }
- }
-
- if (config_path[0] == '\0') {
- char *config_home = getenv(CONFIG_HOME_ENV);
- if (config_home != NULL)
- snprintf(config_path, sizeof(config_path), "%s/%s/%s", config_home, WM_NAME, CONFIG_NAME);
- else
- snprintf(config_path, sizeof(config_path), "%s/%s/%s/%s", getenv("HOME"), ".config", WM_NAME, CONFIG_NAME);
- }
-
- dpy = xcb_connect(NULL, &default_screen);
-
- if (xcb_connection_has_error(dpy))
- err("Can't open the default display.\n");
-
- setup();
-
- dpy_fd = xcb_get_file_descriptor(dpy);
-
- char *sp = getenv(SOCKET_ENV_VAR);
- snprintf(socket_path, sizeof(socket_path), "%s", (sp == NULL ? DEFAULT_SOCKET_PATH : sp));
-
- sock_address.sun_family = AF_UNIX;
- snprintf(sock_address.sun_path, sizeof(sock_address.sun_path), "%s", socket_path);
- unlink(socket_path);
-
- sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (sock_fd == -1)
- err("Couldn't create the socket.\n");
-
- if (bind(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)) == -1)
- err("Couldn't bind a name to the socket.\n");
-
- if (listen(sock_fd, SOMAXCONN) == -1)
- err("Couldn't listen to the socket.\n");
-
- sel = MAX(sock_fd, dpy_fd) + 1;
-
- if (fifo_path != NULL) {
- int fifo_fd = open(fifo_path, O_RDWR | O_NONBLOCK);
- if (fifo_fd != -1)
- status_fifo = fdopen(fifo_fd, "w");
- else
- warn("Couldn't open status fifo.\n");
- }
-
- load_settings();
- run_config();
- running = true;
-
- while (running) {
-
- xcb_flush(dpy);
-
- FD_ZERO(&descriptors);
- FD_SET(sock_fd, &descriptors);
- FD_SET(dpy_fd, &descriptors);
-
- if (select(sel, &descriptors, NULL, NULL, NULL) > 0) {
-
- if (FD_ISSET(sock_fd, &descriptors)) {
- ret_fd = accept(sock_fd, NULL, 0);
- if (ret_fd > 0 && (n = recv(ret_fd, msg, sizeof(msg), 0)) > 0) {
- msg[n] = '\0';
- if (handle_message(msg, n, rsp)) {
- rsp_len = strlen(rsp);
- if (rsp[rsp_len - 1] == '\n')
- rsp[--rsp_len] = '\0';
- } else {
- rsp[0] = MESSAGE_FAILURE;
- rsp_len = 1;
- }
- send(ret_fd, rsp, rsp_len, 0);
- close(ret_fd);
- rsp[0] = '\0';
- }
- }
-
- if (FD_ISSET(dpy_fd, &descriptors)) {
- while ((event = xcb_poll_for_event(dpy)) != NULL) {
- handle_event(event);
- free(event);
- }
- }
-
- }
-
- if (xcb_connection_has_error(dpy))
- err("The server has closed the connection.\n");
- }
-
- cleanup();
- close(sock_fd);
- if (status_fifo != NULL)
- fclose(status_fifo);
- xcb_ewmh_connection_wipe(ewmh);
- xcb_destroy_window(dpy, motion_recorder);
- free(ewmh);
- xcb_flush(dpy);
- xcb_disconnect(dpy);
- return exit_status;
+ fd_set descriptors;
+ char socket_path[MAXLEN];
+ config_path[0] = '\0';
+ int sock_fd, cli_fd, dpy_fd, max_fd, n;
+ struct sockaddr_un sock_address;
+ char msg[BUFSIZ] = {0};
+ xcb_generic_event_t *event;
+ char opt;
+
+ while ((opt = getopt(argc, argv, "hvc:")) != (char)-1) {
+ switch (opt) {
+ case 'h':
+ printf(WM_NAME " [-h|-v|-c CONFIG_PATH]\n");
+ exit(EXIT_SUCCESS);
+ break;
+ case 'v':
+ printf("%s\n", VERSION);
+ exit(EXIT_SUCCESS);
+ break;
+ case 'c':
+ snprintf(config_path, sizeof(config_path), "%s", optarg);
+ break;
+ }
+ }
+
+ if (config_path[0] == '\0') {
+ char *config_home = getenv(CONFIG_HOME_ENV);
+ if (config_home != NULL)
+ snprintf(config_path, sizeof(config_path), "%s/%s/%s", config_home, WM_NAME, CONFIG_NAME);
+ else
+ snprintf(config_path, sizeof(config_path), "%s/%s/%s/%s", getenv("HOME"), ".config", WM_NAME, CONFIG_NAME);
+ }
+
+ dpy = xcb_connect(NULL, &default_screen);
+
+ if (xcb_connection_has_error(dpy))
+ err("Can't open the default display.\n");
+
+ setup();
+
+ dpy_fd = xcb_get_file_descriptor(dpy);
+
+ char *sp = getenv(SOCKET_ENV_VAR);
+ if (sp != NULL)
+ snprintf(socket_path, sizeof(socket_path), "%s", sp);
+ else
+ snprintf(socket_path, sizeof(socket_path), SOCKET_PATH_TPL, getenv("DISPLAY"));
+
+ sock_address.sun_family = AF_UNIX;
+ snprintf(sock_address.sun_path, sizeof(sock_address.sun_path), "%s", socket_path);
+
+ sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ if (sock_fd == -1)
+ err("Couldn't create the socket.\n");
+
+ if (bind(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)) == -1)
+ err("Couldn't bind a name to the socket.\n");
+
+ if (listen(sock_fd, SOMAXCONN) == -1)
+ err("Couldn't listen to the socket.\n");
+
+ signal(SIGINT, sig_handler);
+ signal(SIGHUP, sig_handler);
+ signal(SIGTERM, sig_handler);
+ signal(SIGCHLD, sig_handler);
+ signal(SIGPIPE, SIG_IGN);
+ load_settings();
+ run_config();
+ running = true;
+
+ while (running) {
+
+ xcb_flush(dpy);
+
+ FD_ZERO(&descriptors);
+ FD_SET(sock_fd, &descriptors);
+ FD_SET(dpy_fd, &descriptors);
+ max_fd = MAX(sock_fd, dpy_fd);
+ for (pending_rule_t *pr = pending_rule_head; pr != NULL; pr = pr->next) {
+ FD_SET(pr->fd, &descriptors);
+ if (pr->fd > max_fd)
+ max_fd = pr->fd;
+ }
+
+ if (select(max_fd + 1, &descriptors, NULL, NULL, NULL) > 0) {
+
+ pending_rule_t *pr = pending_rule_head;
+ while (pr != NULL) {
+ pending_rule_t *next = pr->next;
+ if (FD_ISSET(pr->fd, &descriptors)) {
+ manage_window(pr->win, pr->csq, pr->fd);
+ remove_pending_rule(pr);
+ }
+ pr = next;
+ }
+
+ if (FD_ISSET(sock_fd, &descriptors)) {
+ cli_fd = accept(sock_fd, NULL, 0);
+ if (cli_fd > 0 && (n = recv(cli_fd, msg, sizeof(msg), 0)) > 0) {
+ msg[n] = '\0';
+ FILE *rsp = fdopen(cli_fd, "w");
+ if (rsp != NULL) {
+ int ret = handle_message(msg, n, rsp);
+ if (ret == MSG_SUBSCRIBE) {
+ add_subscriber(rsp);
+ } else {
+ if (ret != MSG_SUCCESS)
+ fprintf(rsp, "%c", ret);
+ fflush(rsp);
+ fclose(rsp);
+ }
+ } else {
+ warn("Can't open the client socket as file.\n");
+ close(cli_fd);
+ }
+ }
+ }
+
+ if (FD_ISSET(dpy_fd, &descriptors)) {
+ while ((event = xcb_poll_for_event(dpy)) != NULL) {
+ handle_event(event);
+ free(event);
+ }
+ }
+ }
+
+ if (xcb_connection_has_error(dpy)) {
+ warn("The server closed the connection.\n");
+ running = false;
+ }
+ }
+
+ cleanup();
+ close(sock_fd);
+ unlink(socket_path);
+ xcb_ewmh_connection_wipe(ewmh);
+ xcb_destroy_window(dpy, motion_recorder);
+ free(ewmh);
+ xcb_flush(dpy);
+ xcb_disconnect(dpy);
+ return exit_status;