34 #define G_LOG_DOMAIN "Dialogs.Run"
46 #include <sys/types.h>
63 #define RUN_CACHE_FILE "rofi-3.runcache"
99 static gboolean
exec_cmd(
const char *cmd,
int run_in_term) {
100 GError *error = NULL;
101 if (!cmd || !cmd[0]) {
104 gsize lf_cmd_size = 0;
105 gchar *lf_cmd = g_locale_from_utf8(cmd, -1, NULL, &lf_cmd_size, &error);
107 g_warning(
"Failed to convert command to locale encoding: %s",
117 run_in_term ? &context : NULL)) {
157 static int sort_func(
const void *a,
const void *b, G_GNUC_UNUSED
void *data) {
161 if (astr->
entry == NULL && bstr->
entry == NULL) {
164 if (astr->
entry == NULL) {
167 if (bstr->
entry == NULL) {
177 unsigned int num_favorites) {
180 FILE *inp = fdopen(fd,
"r");
183 size_t buffer_length = 0;
185 while (getline(&buffer, &buffer_length, inp) > 0) {
188 if (buffer[strlen(buffer) - 1] ==
'\n') {
189 buffer[strlen(buffer) - 1] =
'\0';
194 for (
unsigned int j = 0; found == 0 && j < num_favorites; j++) {
195 if (strcasecmp(buffer, retv[j].entry) == 0) {
205 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
RunEntry));
206 retv[(*length)].
entry = g_strdup(buffer);
207 retv[(*length)].
icon = NULL;
212 if (buffer != NULL) {
215 if (fclose(inp) != 0) {
216 g_warning(
"Failed to close stdout off executor script: '%s'",
221 retv[(*length)].
entry = NULL;
222 retv[(*length)].
icon = NULL;
231 GError *error = NULL;
233 unsigned int num_favorites = 0;
236 if (g_getenv(
"PATH") == NULL) {
243 for (
unsigned int i = 0; i < *length; i++) {
244 retv[i].
entry = hretv[i];
249 num_favorites = (*length);
251 path = g_strdup(g_getenv(
"PATH"));
254 gchar *homedir = g_locale_to_utf8(g_get_home_dir(), -1, NULL, &l, &error);
256 g_debug(
"Failed to convert homedir to UTF-8: %s", error->message);
257 for (
unsigned int i = 0; retv[i].
entry != NULL; i++) {
258 g_free(retv[i].entry);
261 g_clear_error(&error);
266 const char *
const sep =
":";
267 char *strtok_savepointer = NULL;
268 for (
const char *dirname = strtok_r(path, sep, &strtok_savepointer);
269 dirname != NULL; dirname = strtok_r(NULL, sep, &strtok_savepointer)) {
271 DIR *dir = opendir(fpath);
272 g_debug(
"Checking path %s for executable.", fpath);
278 gchar *dirn = g_locale_to_utf8(dirname, -1, NULL, &dirn_len, &error);
280 g_debug(
"Failed to convert directory name to UTF-8: %s",
282 g_clear_error(&error);
286 gboolean is_homedir = g_str_has_prefix(dirn, homedir);
289 while ((dent = readdir(dir)) != NULL) {
290 if (dent->d_type != DT_REG && dent->d_type != DT_LNK &&
291 dent->d_type != DT_UNKNOWN) {
295 if (dent->d_name[0] ==
'.') {
299 gchar *full_path = g_build_filename(dirname, dent->d_name, NULL);
300 gboolean b = g_file_test(full_path, G_FILE_TEST_IS_EXECUTABLE);
309 g_filename_to_utf8(dent->d_name, -1, NULL, &name_len, &error);
311 g_debug(
"Failed to convert filename to UTF-8: %s", error->message);
312 g_clear_error(&error);
319 for (
unsigned int j = 0; found == 0 && j < num_favorites; j++) {
320 if (g_strcmp0(name, retv[j].entry) == 0) {
330 retv = g_realloc(retv, ((*length) + 2) *
sizeof(
RunEntry));
331 retv[(*length)].
entry = name;
332 retv[(*length)].
icon = NULL;
334 retv[(*length) + 1].
entry = NULL;
335 retv[(*length) + 1].
icon = NULL;
350 if ((*length) == 0) {
354 if ((*length) > num_favorites) {
355 g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites,
360 unsigned int removed = 0;
361 for (
unsigned int index = num_favorites; index < ((*length) - 1); index++) {
362 if (g_strcmp0(retv[index].entry, retv[index + 1].entry) == 0) {
363 g_free(retv[index].entry);
364 retv[index].
entry = NULL;
369 if ((*length) > num_favorites) {
370 g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites,
374 (*length) -= removed;
420 unsigned int selected_line) {
442 selected_line, &path);
447 char *arg = g_strdup_printf(
464 if (!
exec_cmd(*input, run_in_term)) {
479 if (selected_line < rmpd->cmd_list_length) {
498 G_GNUC_UNUSED
int *state,
499 G_GNUC_UNUSED GList **list,
int get_entry) {
503 state, list, get_entry);
505 return get_entry ? g_strdup(rmpd->
cmd_list[selected_line].
entry) : NULL;
509 unsigned int index) {
523 g_strdup_printf(
"File complete for: %s\n%s",
528 return g_strdup_printf(
"File complete for: %s",
545 static cairo_surface_t *
_get_icon(
const Mode *sw,
unsigned int selected_line,
551 g_return_val_if_fail(pd->
cmd_list != NULL, NULL);
562 char **str = g_strsplit(dr->
entry,
" ", 2);
576 .cfg_name_key =
"display-run",
585 ._get_completion = NULL,
586 ._preprocess_input = NULL,
587 .private_data = NULL,