2021-09-07 16:19:11 +00:00
|
|
|
#include "misc/socket.h"
|
2021-08-13 13:58:00 +00:00
|
|
|
#define SOCKET_PATH_FMT "/tmp/sketchybar_%s.socket"
|
|
|
|
#define LCFILE_PATH_FMT "/tmp/sketchybar_%s.lock"
|
2020-03-29 10:22:38 +00:00
|
|
|
|
|
|
|
#define CLIENT_OPT_LONG "--message"
|
|
|
|
#define CLIENT_OPT_SHRT "-m"
|
|
|
|
|
|
|
|
#define DEBUG_VERBOSE_OPT_LONG "--verbose"
|
|
|
|
#define DEBUG_VERBOSE_OPT_SHRT "-V"
|
|
|
|
#define VERSION_OPT_LONG "--version"
|
|
|
|
#define VERSION_OPT_SHRT "-v"
|
|
|
|
|
2021-10-21 21:32:44 +00:00
|
|
|
#define MAJOR 2
|
2021-12-19 21:57:39 +00:00
|
|
|
#define MINOR 3
|
2021-12-24 23:50:51 +00:00
|
|
|
#define PATCH 2
|
2020-03-29 10:22:38 +00:00
|
|
|
|
|
|
|
extern int SLSMainConnectionID(void);
|
2021-09-01 13:32:00 +00:00
|
|
|
extern int RunApplicationEventLoop(void);
|
2020-03-29 10:22:38 +00:00
|
|
|
|
|
|
|
struct event_loop g_event_loop;
|
|
|
|
void *g_workspace_context;
|
|
|
|
struct daemon g_daemon;
|
|
|
|
struct bar_manager g_bar_manager;
|
|
|
|
int g_connection;
|
|
|
|
|
|
|
|
char g_socket_file[MAXLEN];
|
|
|
|
char g_config_file[4096];
|
|
|
|
char g_lock_file[MAXLEN];
|
|
|
|
bool g_verbose;
|
|
|
|
|
2021-09-01 17:13:16 +00:00
|
|
|
static int client_send_message(int argc, char **argv) {
|
2020-03-29 10:22:38 +00:00
|
|
|
if (argc <= 1) {
|
2021-09-08 15:53:17 +00:00
|
|
|
return EXIT_SUCCESS;
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *user = getenv("USER");
|
|
|
|
if (!user) {
|
2021-08-13 13:58:00 +00:00
|
|
|
error("sketchybar-msg: 'env USER' not set! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int sockfd;
|
|
|
|
char socket_file[MAXLEN];
|
|
|
|
snprintf(socket_file, sizeof(socket_file), SOCKET_PATH_FMT, user);
|
|
|
|
|
2021-09-06 13:17:15 +00:00
|
|
|
int count = 0;
|
|
|
|
while (!socket_connect_un(&sockfd, socket_file)) {
|
|
|
|
count++;
|
2021-11-07 18:24:54 +00:00
|
|
|
if (count > 100) {
|
|
|
|
shutdown(sockfd, SHUT_WR);
|
|
|
|
socket_close(sockfd);
|
|
|
|
error("sketchybar-msg: failed to connect to socket..\n");
|
|
|
|
}
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
2021-03-27 13:24:09 +00:00
|
|
|
int message_length = argc;
|
2020-03-29 10:22:38 +00:00
|
|
|
int argl[argc];
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
argl[i] = strlen(argv[i]);
|
|
|
|
message_length += argl[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
char message[message_length];
|
|
|
|
char *temp = message;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
memcpy(temp, argv[i], argl[i]);
|
|
|
|
temp += argl[i];
|
|
|
|
*temp++ = '\0';
|
|
|
|
}
|
2021-03-27 13:24:09 +00:00
|
|
|
*temp++ = '\0';
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-09-06 13:17:15 +00:00
|
|
|
count = 0;
|
|
|
|
while (!socket_write_bytes(sockfd, message, message_length)) {
|
|
|
|
count++;
|
2021-09-07 16:19:11 +00:00
|
|
|
if (count > 100) {
|
|
|
|
shutdown(sockfd, SHUT_WR);
|
|
|
|
socket_close(sockfd);
|
|
|
|
error("sketchybar-msg: failed to send data..\n");
|
|
|
|
}
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
shutdown(sockfd, SHUT_WR);
|
2021-09-26 16:23:06 +00:00
|
|
|
int result = EXIT_SUCCESS;
|
|
|
|
int byte_count = 0;
|
|
|
|
char rsp[BUFSIZ];
|
|
|
|
|
|
|
|
struct pollfd fds[] = {
|
|
|
|
{ sockfd, POLLIN, 0 }
|
|
|
|
};
|
|
|
|
|
2021-11-07 18:24:54 +00:00
|
|
|
int timeout = 100;
|
2021-10-24 17:58:45 +00:00
|
|
|
while (poll(fds, 1, timeout) > 0) {
|
2021-09-26 16:23:06 +00:00
|
|
|
if (fds[0].revents & POLLIN) {
|
|
|
|
if ((byte_count = recv(sockfd, rsp, sizeof(rsp)-1, 0)) <= 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
rsp[byte_count] = '\0';
|
|
|
|
|
|
|
|
if (rsp[0] == FAILURE_MESSAGE[0]) {
|
|
|
|
result = EXIT_FAILURE;
|
|
|
|
fprintf(stderr, "%s", rsp + 1);
|
|
|
|
fflush(stderr);
|
|
|
|
} else {
|
|
|
|
fprintf(stdout, "%s", rsp);
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-29 10:22:38 +00:00
|
|
|
socket_close(sockfd);
|
2021-09-26 16:23:06 +00:00
|
|
|
return result;
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 17:13:16 +00:00
|
|
|
static void acquire_lockfile(void) {
|
2020-03-29 10:22:38 +00:00
|
|
|
int handle = open(g_lock_file, O_CREAT | O_WRONLY, 0600);
|
|
|
|
if (handle == -1) {
|
2021-08-13 13:58:00 +00:00
|
|
|
error("sketchybar: could not create lock-file! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct flock lockfd = {
|
|
|
|
.l_start = 0,
|
|
|
|
.l_len = 0,
|
|
|
|
.l_pid = getpid(),
|
|
|
|
.l_type = F_WRLCK,
|
|
|
|
.l_whence = SEEK_SET
|
|
|
|
};
|
|
|
|
|
|
|
|
if (fcntl(handle, F_SETLK, &lockfd) == -1) {
|
2021-08-13 13:58:00 +00:00
|
|
|
error("sketchybar: could not acquire lock-file! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-01 17:13:16 +00:00
|
|
|
static bool get_config_file(char *restrict filename, char *restrict buffer, int buffer_size) {
|
2020-03-29 10:22:38 +00:00
|
|
|
char *xdg_home = getenv("XDG_CONFIG_HOME");
|
|
|
|
if (xdg_home && *xdg_home) {
|
2021-08-13 13:58:00 +00:00
|
|
|
snprintf(buffer, buffer_size, "%s/sketchybar/%s", xdg_home, filename);
|
2020-03-29 10:22:38 +00:00
|
|
|
if (file_exists(buffer)) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *home = getenv("HOME");
|
|
|
|
if (!home) return false;
|
|
|
|
|
2021-08-13 13:58:00 +00:00
|
|
|
snprintf(buffer, buffer_size, "%s/.config/sketchybar/%s", home, filename);
|
2020-03-29 10:22:38 +00:00
|
|
|
if (file_exists(buffer)) return true;
|
|
|
|
|
|
|
|
snprintf(buffer, buffer_size, "%s/.%s", home, filename);
|
|
|
|
return file_exists(buffer);
|
|
|
|
}
|
|
|
|
|
2021-09-01 17:13:16 +00:00
|
|
|
static void exec_config_file(void) {
|
2021-12-22 17:22:58 +00:00
|
|
|
if (!get_config_file("sketchybarrc", g_config_file, sizeof(g_config_file))) {
|
2021-08-28 08:53:42 +00:00
|
|
|
printf("could not locate config file..");
|
2020-03-29 10:22:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!file_exists(g_config_file)) {
|
2021-08-28 08:53:42 +00:00
|
|
|
printf("file '%s' does not exist..", g_config_file);
|
2020-03-29 10:22:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ensure_executable_permission(g_config_file)) {
|
2021-08-28 08:53:42 +00:00
|
|
|
printf("could not set the executable permission bit for '%s'", g_config_file);
|
2020-03-29 10:22:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fork_exec(g_config_file, NULL)) {
|
2021-08-28 08:53:42 +00:00
|
|
|
printf("failed to execute file '%s'", g_config_file);
|
2020-03-29 10:22:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma clang diagnostic push
|
|
|
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
2021-09-01 17:13:16 +00:00
|
|
|
static inline void init_misc_settings(void) {
|
2020-03-29 10:22:38 +00:00
|
|
|
char *user = getenv("USER");
|
|
|
|
if (!user) {
|
2021-08-13 13:58:00 +00:00
|
|
|
error("sketchybar: 'env USER' not set! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(g_socket_file, sizeof(g_socket_file), SOCKET_PATH_FMT, user);
|
|
|
|
snprintf(g_lock_file, sizeof(g_lock_file), LCFILE_PATH_FMT, user);
|
|
|
|
|
|
|
|
NSApplicationLoad();
|
|
|
|
signal(SIGCHLD, SIG_IGN);
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
CGSetLocalEventsSuppressionInterval(0.0f);
|
|
|
|
CGEnableEventStateCombining(false);
|
|
|
|
g_connection = SLSMainConnectionID();
|
|
|
|
}
|
|
|
|
#pragma clang diagnostic pop
|
|
|
|
|
2021-09-01 17:13:16 +00:00
|
|
|
static void parse_arguments(int argc, char **argv) {
|
2021-12-22 17:22:58 +00:00
|
|
|
if ((string_equals(argv[1], VERSION_OPT_LONG)) || (string_equals(argv[1], VERSION_OPT_SHRT))) {
|
|
|
|
fprintf(stdout, "sketchybar-v%d.%d.%d\n", MAJOR, MINOR, PATCH);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((string_equals(argv[1], DEBUG_VERBOSE_OPT_LONG) || string_equals(argv[1], DEBUG_VERBOSE_OPT_SHRT)))
|
|
|
|
g_verbose = true;
|
|
|
|
|
|
|
|
if ((string_equals(argv[1], CLIENT_OPT_LONG)) || (string_equals(argv[1], CLIENT_OPT_SHRT)))
|
|
|
|
exit(client_send_message(argc-1, argv+1));
|
|
|
|
|
|
|
|
exit(client_send_message(argc, argv));
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|
|
|
|
|
2021-09-01 17:13:16 +00:00
|
|
|
int main(int argc, char **argv) {
|
2021-12-22 17:22:58 +00:00
|
|
|
if (argc > 1) parse_arguments(argc, argv);
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
if (is_root()) error("sketchybar: running as root is not allowed! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
init_misc_settings();
|
|
|
|
acquire_lockfile();
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
if (!event_loop_init(&g_event_loop))
|
|
|
|
error("sketchybar: could not initialize event_loop! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
workspace_event_handler_init(&g_workspace_context);
|
|
|
|
bar_manager_init(&g_bar_manager);
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
event_loop_begin(&g_event_loop);
|
|
|
|
mouse_begin();
|
|
|
|
display_begin();
|
|
|
|
workspace_event_handler_begin(&g_workspace_context);
|
|
|
|
bar_manager_begin(&g_bar_manager);
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
if (!socket_daemon_begin_un(&g_daemon, g_socket_file, message_handler))
|
|
|
|
error("sketchybar: could not initialize daemon! abort..\n");
|
2020-03-29 10:22:38 +00:00
|
|
|
|
2021-12-22 17:22:58 +00:00
|
|
|
exec_config_file();
|
|
|
|
RunApplicationEventLoop();
|
|
|
|
return 0;
|
2020-03-29 10:22:38 +00:00
|
|
|
}
|