J4statusIOContext * j4status_io_new(J4statusCoreContext *core, gchar *header, const gchar * const *servers_desc, const gchar * const *streams_desc) { J4statusIOContext *self; self = g_new0(J4statusIOContext, 1); self->core = core; self->header = header; _j4status_io_add_systemd(self); if ( ( servers_desc == NULL ) && ( streams_desc == NULL ) && ( ! _j4status_io_has_stream(self) ) ) /* Using stdin/stdout */ _j4status_io_add_stream(self, "std"); if ( servers_desc != NULL ) { const gchar * const *server_desc; for ( server_desc = servers_desc ; *servers_desc != NULL ; ++servers_desc) _j4status_io_server_add(self, *server_desc); } if ( streams_desc != NULL ) { const gchar * const *stream_desc; for ( stream_desc = streams_desc ; *stream_desc != NULL ; ++stream_desc) _j4status_io_add_stream(self, *stream_desc); } if ( _j4status_io_has_stream(self) ) return self; j4status_io_free(self); return NULL; }
int main(int argc, char *argv[]) { gboolean print_version = FALSE; gboolean one_shot = FALSE; gchar *output_plugin = NULL; gchar **servers_desc = NULL; gchar **streams_desc = NULL; gchar **input_plugins = NULL; gchar **order = NULL; gchar *config = NULL; int retval = 0; GError *error = NULL; GOptionContext *option_context = NULL; GOptionGroup *option_group; #if DEBUG g_setenv("G_MESSAGES_DEBUG", "all", FALSE); #endif /* ! DEBUG */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); #endif /* ENABLE_NLS */ #if DEBUG const gchar *debug_log_filename = g_getenv("J4STATUS_DEBUG_LOG_FILENAME"); GDataOutputStream *debug_stream = NULL; if ( debug_log_filename != NULL ) { GFile *debug_log; debug_log = g_file_new_for_path(debug_log_filename); GError *error = NULL; GFileOutputStream *debug_log_stream; debug_log_stream = g_file_append_to(debug_log, G_FILE_CREATE_NONE, NULL, &error); if ( debug_log_stream == NULL ) { g_warning("Couldn't open debug log file: %s", error->message); g_clear_error(&error); } else { debug_stream = g_data_output_stream_new(G_OUTPUT_STREAM(debug_log_stream)); g_object_unref(debug_log_stream); g_log_set_default_handler(_j4status_core_debug_log_handler, debug_stream); } g_object_unref(debug_log); } #endif /* DEBUG */ GOptionEntry entries[] = { { "output", 'o', 0, G_OPTION_ARG_STRING, &output_plugin, "Output plugin to use", "<plugin>" }, { "listen", 'l', 0, G_OPTION_ARG_STRING_ARRAY, &servers_desc, "Socket to listen on, will create a stream on connection (may be specified several times)", "<listen description>" }, { "stream", 't', 0, G_OPTION_ARG_STRING_ARRAY, &streams_desc, "Stream to read from/write to (may be specified several times)", "<stream description>" }, { "input", 'i', 0, G_OPTION_ARG_STRING_ARRAY, &input_plugins, "Input plugins to use (may be specified several times)", "<plugin>" }, { "order", 'O', 0, G_OPTION_ARG_STRING_ARRAY, &order, "Order of sections, specified once a section (see man)", "<section id>" }, { "one-shot", '1', 0, G_OPTION_ARG_NONE, &one_shot, "Tells j4status to stop right after starting", NULL }, { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "Config file to use", "<config>" }, { "version", 'V', 0, G_OPTION_ARG_NONE, &print_version, "Print version", NULL }, { NULL } }; option_context = g_option_context_new("- status line generator"); option_group = g_option_group_new(NULL, NULL, NULL, NULL, NULL); g_option_group_set_translation_domain(option_group, GETTEXT_PACKAGE); g_option_group_add_entries(option_group, entries); g_option_context_set_main_group(option_context, option_group); if ( ! g_option_context_parse(option_context, &argc, &argv, &error) ) { g_warning("Option parsing failed: %s\n", error->message); g_clear_error(&error); retval = 1; goto end; } g_option_context_free(option_context); if ( print_version ) { g_fprintf(stdout, PACKAGE_NAME " " PACKAGE_VERSION "\n"); goto end; } if ( config != NULL ) { g_setenv("J4STATUS_CONFIG_FILE", config, TRUE); g_free(config); } GKeyFile *key_file; key_file = j4status_config_get_key_file("Plugins"); if ( key_file != NULL ) { if ( output_plugin == NULL ) output_plugin = g_key_file_get_string(key_file, "Plugins", "Output", NULL); if ( input_plugins == NULL ) input_plugins = g_key_file_get_string_list(key_file, "Plugins", "Input", NULL, NULL); if ( order == NULL ) order = g_key_file_get_string_list(key_file, "Plugins", "Order", NULL, NULL); g_key_file_free(key_file); } J4statusCoreContext *context; context = g_new0(J4statusCoreContext, 1); J4statusCoreInterface interface = { .context = context, .add_section = _j4status_core_add_section, .remove_section = _j4status_core_remove_section, .trigger_generate = _j4status_core_trigger_generate, .trigger_action = _j4status_core_trigger_action, }; #ifdef G_OS_UNIX g_unix_signal_add(SIGTERM, _j4status_core_source_quit, context); g_unix_signal_add(SIGINT, _j4status_core_source_quit, context); g_unix_signal_add(SIGUSR1, _j4status_core_signal_usr1, context); g_unix_signal_add(SIGUSR2, _j4status_core_signal_usr2, context); /* Ignore SIGPIPE as it is useless */ signal(SIGPIPE, SIG_IGN); #endif /* G_OS_UNIX */ context->output_plugin = j4status_plugins_get_output_plugin(&interface, output_plugin); if ( context->output_plugin == NULL ) { g_warning("No usable output plugin, tried '%s'", output_plugin); retval = 10; goto end; } gchar *header = NULL; if ( context->output_plugin->interface.generate_header != NULL ) header = context->output_plugin->interface.generate_header(context->output_plugin->context); /* Creating input/output stream */ context->io = j4status_io_new(context, header, (const gchar * const *) servers_desc, (const gchar * const *) streams_desc); if ( context->io == NULL ) { g_warning("Couldn't create input/output streams"); retval = 2; goto end; } if ( order != NULL ) { context->order_weights = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); gchar **id; for ( id = order ; *id != NULL ; ++id ) g_hash_table_insert(context->order_weights, *id, GINT_TO_POINTER(1 + id - order)); g_free(order); } context->sections_hash = g_hash_table_new(g_str_hash, g_str_equal); context->input_plugins = j4status_plugins_get_input_plugins(&interface, input_plugins); if ( context->input_plugins == NULL ) { g_warning("No input plugins, will stop early"); one_shot = TRUE; retval = 11; } context->sections = g_list_reverse(context->sections); if ( context->order_weights != NULL ) context->sections = g_list_sort(context->sections, _j4status_core_compare_sections); _j4status_core_start(context); if ( one_shot ) g_idle_add(_j4status_core_source_quit, context); context->loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(context->loop); g_main_loop_unref(context->loop); context->loop = NULL; GList *input_plugin_; J4statusInputPlugin *input_plugin; for ( input_plugin_ = context->input_plugins ; input_plugin_ != NULL ; input_plugin_ = g_list_next(input_plugin_) ) { input_plugin = input_plugin_->data; input_plugin->interface.uninit(input_plugin->context); } if ( context->output_plugin->interface.uninit != NULL ) context->output_plugin->interface.uninit(context->output_plugin->context); j4status_io_free(context->io); if ( context->order_weights != NULL ) g_hash_table_unref(context->order_weights); g_hash_table_unref(context->sections_hash); end: #if DEBUG if ( debug_stream != NULL ) g_object_unref(debug_stream); #endif /* DEBUG */ return retval; }