/** * @param cmd The cmd to execute * @param run_in_term Indicate if command should be run in a terminal * * Execute command. * * @returns FALSE On failure, TRUE on success */ static inline int execsh ( const char *cmd, int run_in_term ) { int retv = TRUE; char **args = NULL; int argc = 0; if ( run_in_term ) { helper_parse_setup ( config.run_shell_command, &args, &argc, "{cmd}", cmd, NULL ); } else { helper_parse_setup ( config.run_command, &args, &argc, "{cmd}", cmd, NULL ); } GError *error = NULL; g_spawn_async ( NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error ); if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd, error->message ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); retv = FALSE; } // Free the args list. g_strfreev ( args ); return retv; }
int show_error_message ( const char *msg, int markup ) { int pfd = setup (); if ( pfd < 0 ) { return FALSE; } return rofi_view_error_dialog ( msg, markup ); }
int helper_parse_setup ( char * string, char ***output, int *length, ... ) { GError *error = NULL; GHashTable *h; h = g_hash_table_new ( g_str_hash, g_str_equal ); // By default, we insert terminal and ssh-client g_hash_table_insert ( h, "{terminal}", config.terminal_emulator ); g_hash_table_insert ( h, "{ssh-client}", config.ssh_client ); // Add list from variable arguments. va_list ap; va_start ( ap, length ); while ( 1 ) { char * key = va_arg ( ap, char * ); if ( key == NULL ) { break; } char *value = va_arg ( ap, char * ); if ( value == NULL ) { break; } g_hash_table_insert ( h, key, value ); } va_end ( ap ); // Replace hits within {-\w+}. GRegex *reg = g_regex_new ( "{[-\\w]+}", 0, 0, NULL ); char *res = g_regex_replace_eval ( reg, string, -1, 0, 0, helper_eval_cb, h, NULL ); // Free regex. g_regex_unref ( reg ); // Destroy key-value storage. g_hash_table_destroy ( h ); // Parse the string into shell arguments. if ( g_shell_parse_argv ( res, length, output, &error ) ) { g_free ( res ); return TRUE; } g_free ( res ); // Throw error if shell parsing fails. if ( error ) { char *msg = g_strdup_printf ( "Failed to parse: '%s'\nError: '%s'", string, error->message ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); } return FALSE; }
static void run_switcher ( ModeMode mode ) { pfd = setup (); if ( pfd < 0 ) { return; } // Otherwise check if requested mode is enabled. for ( unsigned int i = 0; i < num_modi; i++ ) { if ( !mode_init ( modi[i] ) ) { rofi_view_error_dialog ( ERROR_MSG ( "Failed to initialize all the modi." ), ERROR_MSG_MARKUP ); teardown ( pfd ); return; } } char *input = g_strdup ( config.filter ); __run_switcher_internal ( mode, input ); g_free ( input ); }
int execute_generator ( const char * cmd ) { char **args = NULL; int argv = 0; helper_parse_setup ( config.run_command, &args, &argv, "{cmd}", cmd, NULL ); int fd = -1; GError *error = NULL; g_spawn_async_with_pipes ( NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &fd, NULL, &error ); if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd, error->message ); fputs ( msg, stderr ); fputs ( "\n", stderr ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); fd = -1; } g_strfreev ( args ); return fd; }
/** * @param host The host to connect too * * SSH into the selected host. * * @returns FALSE On failure, TRUE on success */ static inline int execshssh ( const char *host ) { char **args = NULL; int argsv = 0; helper_parse_setup ( config.ssh_command, &args, &argsv, "{host}", host, NULL ); GError *error = NULL; g_spawn_async ( NULL, args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error ); if ( error != NULL ) { char *msg = g_strdup_printf ( "Failed to execute: 'ssh %s'\nError: '%s'", host, error->message ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); // print error. g_error_free ( error ); g_strfreev ( args ); return FALSE; } // Free the args list. g_strfreev ( args ); return TRUE; }
/** * Do some input validation, especially the first few could break things. * It is good to catch them beforehand. * * This functions exits the program with 1 when it finds an invalid configuration. */ int config_sanity_check ( void ) { int found_error = FALSE; GString *msg = g_string_new ( "<big><b>The configuration failed to validate:</b></big>\n" ); if ( config.element_height < 1 ) { g_string_append_printf ( msg, "\t<b>config.element_height</b>=%d is invalid. An element needs to be atleast 1 line high.\n", config.element_height ); config.element_height = 1; found_error = TRUE; } if ( config.menu_columns == 0 ) { g_string_append_printf ( msg, "\t<b>config.menu_columns</b>=%d is invalid. You need at least one visible column.\n", config.menu_columns ); config.menu_columns = 1; found_error = TRUE; } if ( config.menu_width == 0 ) { g_string_append_printf ( msg, "<b>config.menu_width</b>=0 is invalid. You cannot have a window with no width." ); config.menu_columns = 50; found_error = TRUE; } if ( !( config.location >= WL_CENTER && config.location <= WL_WEST ) ) { g_string_append_printf ( msg, "\t<b>config.location</b>=%d is invalid. Value should be between %d and %d.\n", config.location, WL_CENTER, WL_WEST ); config.location = WL_CENTER; found_error = 1; } // Check size { int ssize = monitor_get_smallest_size ( ); if ( config.monitor >= 0 ) { workarea mon; if ( monitor_get_dimension ( config.monitor, &mon ) ) { ssize = MIN ( mon.w, mon.h ); } else{ g_string_append_printf ( msg, "\t<b>config.monitor</b>=%d Could not find monitor.\n", config.monitor ); ssize = 0; } } // Have todo an estimate here. if ( ( 2 * ( config.padding + config.menu_bw ) ) > ( 0.9 * ssize ) ) { g_string_append_printf ( msg, "\t<b>config.padding+config.menu_bw</b>=%d is too big for the minimum size of the monitor: %d.\n", ( config.padding + config.menu_bw ), ssize ); config.padding = 0; config.menu_bw = 0; found_error = TRUE; } } if ( config.menu_font ) { PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font ); const char *fam = pango_font_description_get_family ( pfd ); int size = pango_font_description_get_size ( pfd ); if ( fam == NULL || size == 0 ) { g_string_append_printf ( msg, "Pango failed to parse font: '%s'\n", config.menu_font ); g_string_append_printf ( msg, "Got font family: <b>%s</b> at size <b>%d</b>\n", fam ? fam : "{unknown}", size ); config.menu_font = NULL; found_error = TRUE; } pango_font_description_free ( pfd ); } if ( config.monitor == -3 ) { // On -3, set to location 1. config.location = 1; config.fullscreen = 0; } if ( found_error ) { g_string_append ( msg, "Please update your configuration." ); rofi_view_error_dialog ( msg->str, TRUE ); return TRUE; } g_string_free ( msg, TRUE ); return FALSE; }
static int dmenu_mode_init ( Mode *sw ) { if ( mode_get_private_data ( sw ) != NULL ) { return TRUE; } mode_set_private_data ( sw, g_malloc0 ( sizeof ( DmenuModePrivateData ) ) ); DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); pd->prompt = "dmenu "; pd->separator = '\n'; pd->selected_line = UINT32_MAX; find_arg_str ( "-mesg", &( pd->message ) ); // Input data separator. find_arg_char ( "-sep", &( pd->separator ) ); // Check prompt find_arg_str ( "-p", &( pd->prompt ) ); find_arg_uint ( "-selected-row", &( pd->selected_line ) ); // By default we print the unescaped line back. pd->format = "s"; // Allow user to override the output format. find_arg_str ( "-format", &( pd->format ) ); // Urgent. char *str = NULL; find_arg_str ( "-u", &str ); if ( str != NULL ) { parse_ranges ( str, &( pd->urgent_list ), &( pd->num_urgent_list ) ); } // Active str = NULL; find_arg_str ( "-a", &str ); if ( str != NULL ) { parse_ranges ( str, &( pd->active_list ), &( pd->num_active_list ) ); } // DMENU COMPATIBILITY find_arg_uint ( "-l", &( config.menu_lines ) ); /** * Dmenu compatibility. * `-b` put on bottom. */ if ( find_arg ( "-b" ) >= 0 ) { config.location = 6; } /* -i case insensitive */ config.case_sensitive = TRUE; if ( find_arg ( "-i" ) >= 0 ) { config.case_sensitive = FALSE; } FILE *fd = NULL; str = NULL; if ( find_arg_str ( "-input", &str ) ) { char *estr = rofi_expand_path ( str ); fd = fopen ( str, "r" ); if ( fd == NULL ) { char *msg = g_markup_printf_escaped ( "Failed to open file: <b>%s</b>:\n\t<i>%s</i>", estr, strerror ( errno ) ); rofi_view_error_dialog ( msg, TRUE ); g_free ( msg ); g_free ( estr ); return TRUE; } g_free ( estr ); } pd->cmd_list = get_dmenu ( pd, fd == NULL ? stdin : fd, &( pd->cmd_list_length ) ); if ( fd != NULL ) { fclose ( fd ); } return TRUE; }
int show_error_message ( const char *msg, int markup ) { rofi_view_error_dialog ( msg, markup ); return 0; }
// convert a Mod+key arg to mod mask and keysym gboolean x11_parse_key ( char *combo, unsigned int *mod, xkb_keysym_t *key ) { GString *str = g_string_new ( "" ); unsigned int modmask = 0; if ( strcasestr ( combo, "shift" ) ) { modmask |= x11_mod_masks[X11MOD_SHIFT]; if ( x11_mod_masks[X11MOD_SHIFT] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Shift</b> key.\n" ); } } if ( strcasestr ( combo, "control" ) ) { modmask |= x11_mod_masks[X11MOD_CONTROL]; if ( x11_mod_masks[X11MOD_CONTROL] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Control</b> key.\n" ); } } if ( strcasestr ( combo, "alt" ) ) { modmask |= x11_mod_masks[X11MOD_ALT]; if ( x11_mod_masks[X11MOD_ALT] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Alt</b> key.\n" ); } } if ( strcasestr ( combo, "super" ) ) { modmask |= x11_mod_masks[X11MOD_SUPER]; if ( x11_mod_masks[X11MOD_SUPER] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Super</b> key.\n" ); } } if ( strcasestr ( combo, "meta" ) ) { modmask |= x11_mod_masks[X11MOD_META]; if ( x11_mod_masks[X11MOD_META] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Meta</b> key.\n" ); } } if ( strcasestr ( combo, "hyper" ) ) { modmask |= x11_mod_masks[X11MOD_HYPER]; if ( x11_mod_masks[X11MOD_HYPER] == 0 ) { g_string_append_printf ( str, "X11 configured keyboard has no <b>Hyper</b> key.\n" ); } } int seen_mod = FALSE; if ( strcasestr ( combo, "Mod" ) ) { seen_mod = TRUE; } *mod = modmask; // Skip modifier (if exist) and parse key. char i = strlen ( combo ); while ( i > 0 && !strchr ( "-+", combo[i - 1] ) ) { i--; } xkb_keysym_t sym = XKB_KEY_NoSymbol; if ( ( modmask & x11_mod_masks[X11MOD_SHIFT] ) != 0 ) { gchar * str = g_utf8_next_char ( combo + i ); // If it is a single char, we make a capital out of it. if ( str != NULL && *str == '\0' ) { int l = 0; char buff[8]; gunichar v = g_utf8_get_char ( combo + i ); gunichar u = g_unichar_toupper ( v ); if ( ( l = g_unichar_to_utf8 ( u, buff ) ) ) { buff[l] = '\0'; sym = xkb_keysym_from_name ( buff, XKB_KEYSYM_NO_FLAGS ); } } } if ( sym == XKB_KEY_NoSymbol ) { sym = xkb_keysym_from_name ( combo + i, XKB_KEYSYM_CASE_INSENSITIVE ); } if ( sym == XKB_KEY_NoSymbol || ( !modmask && ( strchr ( combo, '-' ) || strchr ( combo, '+' ) ) ) ) { g_string_append_printf ( str, "Sorry, rofi cannot understand the key combination: <i>%s</i>\n", combo ); g_string_append ( str, "\nRofi supports the following modifiers:\n\t" ); g_string_append ( str, "<i>Shift,Control,Alt,Super,Meta,Hyper</i>" ); if ( seen_mod ) { g_string_append ( str, "\n\n<b>Mod1,Mod2,Mod3,Mod4,Mod5 are no longer supported, use one of the above.</b>" ); } } if ( str->len > 0 ) { rofi_view_error_dialog ( str->str, TRUE ); g_string_free ( str, TRUE ); return FALSE; } g_string_free ( str, TRUE ); *key = sym; return TRUE; }