1 
2 			/*  ########################################
3 			 *  #               CliFM                  #
4 			 *  # 	  The command line file manager    #
5 			 *  ######################################## */
6 
7 /* GPL2+ License
8  * Copyright (C) 2016-2021, L. Abramovich <johndoe.arch@outlook.com>
9  * All rights reserved.
10 
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24  * MA 02110-1301, USA.
25  *
26  */
27 
28 #include "helpers.h"
29 
30 #include <errno.h>
31 #include <libintl.h>
32 #include <locale.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <termios.h>
38 #include <unistd.h>
39 #include <readline/readline.h>
40 #include <readline/history.h>
41 
42 //#include <signal.h>
43 
44 #include "aux.h"
45 #include "checks.h"
46 #include "colors.h"
47 #include "config.h"
48 #include "exec.h"
49 #include "history.h"
50 #include "init.h"
51 #include "jump.h"
52 #include "keybinds.h"
53 #include "listing.h"
54 #include "misc.h"
55 #include "navigation.h"
56 #include "profiles.h"
57 #include "prompt.h"
58 #include "readline.h"
59 #include "strings.h"
60 #include "remotes.h"
61 
62 /* Globals */
63 
64 struct usrvar_t *usr_var = (struct usrvar_t *)NULL;
65 struct actions_t *usr_actions = (struct actions_t *)NULL;
66 /* Workspaces */
67 struct ws_t *ws = (struct ws_t *)NULL;
68 struct kbinds_t *kbinds = (struct kbinds_t *)NULL;
69 struct jump_t *jump_db = (struct jump_t *)NULL;
70 struct bookmarks_t *bookmarks = (struct bookmarks_t *)NULL;
71 struct fileinfo *file_info = (struct fileinfo *)NULL;
72 struct remote_t *remotes = (struct remote_t *)NULL;
73 struct alias_t *aliases = (struct alias_t *)NULL;
74 struct user_t user;
75 /* Store device and inode number of selected files */
76 struct devino_t *sel_devino = (struct devino_t *)NULL;
77 #ifndef _NO_SUGGESTIONS
78 struct suggestions_t suggestion;
79 #endif
80 
81 struct autocmds_t *autocmds = (struct autocmds_t *)NULL;
82 struct opts_t opts;
83 
84 /* pmsg holds the current program message type */
85 enum prog_msg pmsg = NOMSG;
86 enum comp_type cur_comp_type = TCMP_NONE;
87 struct param xargs;
88 unsigned short term_cols;
89 
90 int curcol = 0,
91 	currow = 0,
92 	flags;
93 
94 struct termios
95 	orig_termios,
96 	shell_tmodes;
97 
98 off_t total_sel_size = 0;
99 pid_t own_pid = 0;
100 
101 unsigned short
102 	term_cols = 0,
103 	term_rows = 0;
104 
105 regex_t regex_exp;
106 size_t *ext_colors_len = (size_t *)NULL;
107 
108 int
109 	auto_open = UNSET,
110 	autocd = UNSET,
111 	autocmd_set = 0,
112 	autojump = UNSET,
113 	autols = UNSET,
114 	bell = DEF_BELL_STYLE,
115 	bg_proc = 0,
116 	case_sens_dirjump = UNSET,
117 	case_sens_path_comp = UNSET,
118 	case_sensitive = UNSET, /* Case sensitive file listing */
119 	case_sens_search = UNSET,
120 	cd_on_quit = UNSET,
121 	check_cap = UNSET,
122 	check_ext = UNSET,
123 	classify = UNSET,
124 	clear_screen = UNSET,
125 	cmdhist_flag = 0,
126 	colorize = UNSET,
127 	columned = UNSET,
128 	config_ok = 1,
129 	control_d_exits = 0,
130 	copy_n_rename = 0,
131 	cp_cmd = UNSET,
132 	cur_ws = UNSET,
133 	dequoted = 0,
134 	dir_changed = 0,
135 	dirhist_map = UNSET,
136 	disk_usage = UNSET,
137 	elnpad = UNSET,
138 	expand_bookmarks = UNSET,
139 	ext_cmd_ok = UNSET,
140 	files_counter = UNSET,
141 	filter_rev = 0,
142 	follow_symlinks = UNSET,
143 	fzftab = UNSET,
144 	highlight = UNSET,
145 	home_ok = 1,
146 #ifndef _NO_ICONS
147 	icons = UNSET,
148 #endif
149 	int_vars = UNSET,
150 	internal_cmd = 0,
151 	is_sel = 0,
152 	kb_shortcut = 0,
153 	kbind_busy = 0,
154 	light_mode = UNSET,
155 	list_folders_first = UNSET,
156 	listing_mode = UNSET,
157 	logs_enabled = UNSET,
158 	long_view = UNSET,
159 	max_name_len = UNSET,
160 	mime_match = 0,
161 	min_name_trim = UNSET,
162 	mv_cmd = UNSET,
163 	no_eln = UNSET,
164 	no_log = 0,
165 	only_dirs = UNSET,
166 	open_in_foreground = 0,
167 	pager = UNSET,
168 	tips = UNSET,
169 	print_msg = 0,
170 	print_selfiles = UNSET,
171 	prompt_offset = UNSET,
172 	prompt_style = UNSET,
173 	recur_perm_error_flag = 0,
174 	restore_last_path = UNSET,
175 	rl_last_word_start = 0,
176 	rl_nohist = 0,
177 	rl_notab = 0,
178 	sel_is_last = 0,
179 	selfile_ok = 1,
180 	share_selbox = UNSET,
181 	shell = SHELL_NONE,
182 	shell_terminal = 0,
183 	show_hidden = UNSET,
184 	sort = UNSET,
185 	sort_reverse = 0,
186 	sort_switch = 0,
187 	splash_screen = UNSET,
188 	suggestions = UNSET,
189 	suggest_filetype_color = UNSET,
190 	switch_cscheme = 0,
191 #ifndef _NO_TRASH
192 	tr_as_rm = UNSET,
193 	trash_ok = 1,
194 #endif
195 	unicode = UNSET,
196 	warning_prompt = UNSET,
197 	welcome_message = UNSET,
198 	_xrename = 0,
199 	xrename = 0;
200 
201 //#ifndef _NO_HIGHLIGHT
202 int wrong_cmd = 0;
203 int wrong_cmd_line = 0;
204 //#endif
205 
206 int
207 	argc_bk = 0,
208 	dirhist_cur_index = 0,
209 	exit_code = 0,
210 	dirhist_total_index = 0,
211 	jump_total_rank = 0,
212 	max_dirhist = UNSET,
213 	max_files = UNSET,
214 	max_hist = UNSET,
215 	min_jump_rank = UNSET,
216 	max_jump_total_rank = UNSET,
217 	max_log = UNSET,
218 	max_path = UNSET,
219 	max_printselfiles = UNSET,
220 	shell_is_interactive = 0,
221 	trash_n = 0,
222 	*eln_as_file = (int *)0;
223 
224 size_t
225 	actions_n = 0,
226 	aliases_n = 0,
227 	args_n = 0,
228 	autocmds_n = 0,
229 	bm_n = 0,
230 	cdpath_n = 0,
231 	cschemes_n = 0,
232 	current_hist_n = 0,
233 	curhistindex = 0,
234 	eln_as_file_n = 0,
235 	ext_colors_n = 0,
236 	files = 0,
237 	jump_n = 0,
238 	kbinds_n = 0,
239 	longest = 0,
240 	msgs_n = 0,
241 	P_tmpdir_len = 0,
242 	path_n = 0,
243 	path_progsn = 0,
244 	prompt_cmds_n = 0,
245 	remotes_n = 0,
246 	sel_n = 0,
247 	tab_offset = 0,
248 	user_home_len = 0,
249 	usrvar_n = 0,
250 	nwords = 0;
251 
252 char
253 	div_line_char[NAME_MAX],
254 	hostname[HOST_NAME_MAX],
255 
256 	*actions_file = (char *)NULL,
257 	*alt_bm_file = (char *)NULL,
258 	*alt_config_dir = (char *)NULL,
259 	*alt_config_file = (char *)NULL,
260 	*alt_kbinds_file = (char *)NULL,
261 	*alt_profile = (char *)NULL,
262 	*bm_file = (char *)NULL,
263 	*colors_dir = (char *)NULL,
264 	*config_dir = (char *)NULL,
265 	*config_dir_gral = (char *)NULL,
266 	*config_file = (char *)NULL,
267 	*cur_color = (char *)NULL,
268 	*data_dir = (char *)NULL,
269 	*cur_cscheme = (char *)NULL,
270 	*dirhist_file = (char *)NULL,
271 	*encoded_prompt = (char *)NULL,
272 	*file_cmd_path = (char *)NULL,
273 	*_filter = (char *)NULL,
274 	*fzftab_options = (char *)NULL,
275 	*hist_file = (char *)NULL,
276 	*jump_suggestion = (char *)NULL,
277 	*kbinds_file = (char *)NULL,
278 	*last_cmd = (char *)NULL,
279 	*log_file = (char *)NULL,
280 	*ls_colors_bk = (char *)NULL,
281 	*mime_file = (char *)NULL,
282 	*msg_log_file = (char *)NULL,
283 	*opener = (char *)NULL,
284 	*pinned_dir = (char *)NULL,
285 	*plugins_dir = (char *)NULL,
286 	*profile_file = (char *)NULL,
287 	*qc = (char *)NULL,
288 	*remotes_file = (char *)NULL,
289 	*sel_file = (char *)NULL,
290 	*stdin_tmp_dir = (char *)NULL,
291 #ifndef _NO_SUGGESTIONS
292 	*suggestion_buf = (char *)NULL,
293 	*suggestion_strategy = (char *)NULL,
294 #endif
295 	*sys_shell = (char *)NULL,
296 	*term = (char *)NULL,
297 //	*term_bgcolor = (char *)NULL,
298 	*tmp_dir = (char *)NULL,
299 #ifndef _NO_TRASH
300 	*trash_dir = (char *)NULL,
301 	*trash_files_dir = (char *)NULL,
302 	*trash_info_dir = (char *)NULL,
303 #endif
304 	*usr_cscheme = (char *)NULL,
305 	*user_home = (char *)NULL,
306 	*wprompt_str = (char *)NULL,
307 
308 	**argv_bk = (char **)NULL,
309 	**bin_commands = (char **)NULL,
310 	**bookmark_names = (char **)NULL,
311 	**cdpaths = (char **)NULL,
312 	**color_schemes = (char **)NULL,
313 	**ext_colors = (char **)NULL,
314 	**history = (char **)NULL,
315 	**messages = (char **)NULL,
316 	**old_pwd = (char **)NULL,
317 	**paths = (char **)NULL,
318 	**profile_names = (char **)NULL,
319 	**prompt_cmds = (char **)NULL,
320 	**sel_elements = (char **)NULL;
321 
322 /* A list of internal commands, with short and long formats. We use two
323  * more lists of commands: one of commands dealing with file names
324  * (is_internal(), in checks.c), and another one listing commands
325  * taking ELN's as parameters (is_internal_f() in strings.c) */
326 const char *internal_cmds[] = {
327 	"?", "help",
328 	"ac", "ad",
329 	"acd", "autocd",
330 	"actions",
331 	"alias",
332 	"ao", "auto-open",
333 	"b", "back",
334 	"bb", "bleach",
335 	"bh", "fh",
336 	"bm", "bookmarks",
337 	"br", "bulk",
338 	"c", "cp",
339 	"cc", "colors",
340 	"cd",
341 	"cl", "columns",
342 	"cmd", "commands",
343 	"cs", "colorschemes",
344 	"d", "dup",
345 	"ds", "desel",
346 	"edit",
347 	"exp", "export",
348 	"ext",
349 	"f", "forth",
350 	"fc",
351 	"ff", "folders-first",
352 	"fs",
353 	"ft", "filter",
354 	"history",
355 	"hf", "hidden",
356 	"icons",
357 	"jump", "je", "jc", "jp", "jo",
358 	"kb", "keybinds",
359 	"l", "ln", "le",
360 	"lm",
361 	"log",
362 	"m", "mv",
363 	"md", "mkdir",
364 	"mf",
365 	"mm", "mime",
366 	"mp", "mountpoints",
367 	"msg", "messages",
368 	"n", "new",
369 	"net",
370 	"o", "open", "ow",
371 	"opener",
372 	"p", "pp", "pr", "prop",
373 	"path", "cwd",
374 	"paste",
375 	"pf", "prof", "profile",
376 	"pg", "pager",
377 	"pin", "unpin",
378 	"quit",
379 	"r", "rm",
380 	"rf", "refresh",
381 	"rl", "reload",
382 	"s", "sel",
383 	"sb", "selbox",
384 	"splash",
385 	"st", "sort",
386 	"t", "tr", "trash",
387 	"te",
388 	"tips",
389 	"touch",
390 	"u", "undel", "untrash",
391 	"uc", "unicode",
392 	"unlink",
393 	"v", "vv",
394 	"ver", "version",
395 	"ws",
396 	"x", "X",
397 	NULL};
398 
399 /* Just a list of internal commands and fixed parameters for the
400  * auto-suggestions system */
401 const char *param_str[] = {
402 	"actions edit",
403 	"autocd on",
404 	"acd on",
405 	"autocd off",
406 	"acd off",
407 	"autocd status",
408 	"acd status",
409 	"alias import",
410 	"ao on",
411 	"auto-open on",
412 	"ao off",
413 	"auto-open off",
414 	"ao status",
415 	"auto-open status",
416 	"b hist",
417 	"b clear",
418 	"back hist",
419 	"back clear",
420 	"bm add",
421 	"bm del",
422 	"bm edit",
423 	"bookmarks add",
424 	"bookmarks del",
425 	"bookmarks edit",
426 	"cs edit",
427 	"colorscheme edit",
428 	"edit",
429 	"edit reset",
430 	"ext on",
431 	"ext off",
432 	"ext status",
433 	"f hist",
434 	"f clear",
435 	"forth hist",
436 	"forth clear",
437 	"fc on",
438 	"filescounter on",
439 	"fc off",
440 	"filescounter off",
441 	"fc status",
442 	"filescounter status",
443 	"ff on",
444 	"folders-first on",
445 	"ff off",
446 	"folders-first off",
447 	"ff status",
448 	"folders-first status",
449 	"ft unset",
450 	"filter unset",
451 	"hf on",
452 	"hf off",
453 	"hf status",
454 	"hidden on",
455 	"hidden off",
456 	"hidden status",
457 	"history clear",
458 	"history edit",
459 	"icons on",
460 	"icons off",
461 	"kb edit",
462 	"keybinds edit",
463 	"kb reset",
464 	"keybinds reset",
465 	"kb readline",
466 	"keybinds readline",
467 	"l edit",
468 	"lm on",
469 	"lm off",
470 	"log clear",
471 	"mf unset",
472 	"mm info",
473 	"mm edit",
474 	"mm import",
475 	"mime info",
476 	"mime edit",
477 	"mime import",
478 	"msg clear",
479 	"messages clear",
480 	"net edit",
481 	"net mount",
482 	"net unmount",
483 	"pg on",
484 	"pager on",
485 	"pg off",
486 	"pager off",
487 	"pg status",
488 	"pager status",
489 	"pf set",
490 	"pf add",
491 	"pf del",
492 	"profile set",
493 	"profile add",
494 	"profile del",
495 	"st none",
496 	"st name",
497 	"st size",
498 	"st atime",
499 	"st btime",
500 	"st ctime",
501 	"st owner",
502 	"st group",
503 	"st ext",
504 	"st inode",
505 	"st version",
506 	"sort none",
507 	"sort name",
508 	"sort size",
509 	"sort atime",
510 	"sort btime",
511 	"sort ctime",
512 	"sort owner",
513 	"sort group",
514 	"sort ext",
515 	"sort inode",
516 	"sort version",
517 	"st rev",
518 	"sort rev",
519 	"t list",
520 	"t clear",
521 	"t del",
522 	"tr list",
523 	"tr clear",
524 	"tr del",
525 	"trash list",
526 	"trash clear",
527 	"trash del",
528 	"u all",
529 	"undel all",
530 	"untrash all",
531 	"uc on",
532 	"unicode on",
533 	"uc off",
534 	"unicode off",
535 	"uc status",
536 	"unicode status",
537 	NULL};
538 
539 /* To store all the 39 color variables I use, with 46 bytes each, I need
540  * a total of 1,8Kb. It's not much but it could be less if I'd use
541  * dynamically allocated arrays for them (which, on the other side,
542  * would make the whole thing slower and more tedious) */
543 
544 /* Colors */
545 char
546 	/* File types */
547 	bd_c[MAX_COLOR],  /* Block device */
548 	ca_c[MAX_COLOR],  /* Cap file */
549 	cd_c[MAX_COLOR],  /* Char device */
550 	di_c[MAX_COLOR],  /* Directory */
551 	ed_c[MAX_COLOR],  /* Empty dir */
552 	ee_c[MAX_COLOR],  /* Empty executable */
553 	ef_c[MAX_COLOR],  /* Empty reg file */
554 	ex_c[MAX_COLOR],  /* Executable */
555 	fi_c[MAX_COLOR],  /* Reg file */
556 	ln_c[MAX_COLOR],  /* Symlink */
557 	mh_c[MAX_COLOR],  /* Multi-hardlink file */
558 	nd_c[MAX_COLOR],  /* No read directory */
559 	ne_c[MAX_COLOR],  /* No read empty dir */
560 	nf_c[MAX_COLOR],  /* No read file */
561 	no_c[MAX_COLOR],  /* Unknown */
562 	or_c[MAX_COLOR],  /* Broken symlink */
563 	ow_c[MAX_COLOR],  /* Other writable */
564 	pi_c[MAX_COLOR],  /* FIFO, pipe */
565 	sg_c[MAX_COLOR],  /* SGID file */
566 	so_c[MAX_COLOR],  /* Socket */
567 	st_c[MAX_COLOR],  /* Sticky (not ow)*/
568 	su_c[MAX_COLOR],  /* SUID file */
569 	tw_c[MAX_COLOR],  /* Sticky other writable */
570 	uf_c[MAX_COLOR],  /* Non-'stat'able file */
571 
572 	/* Interface */
573 	bm_c[MAX_COLOR], /* Bookmarked directory */
574 	dc_c[MAX_COLOR], /* Files counter */
575 	df_c[MAX_COLOR], /* Default color */
576 	dh_c[MAX_COLOR], /* Dirhist index */
577 	dl_c[MAX_COLOR], /* Dividing line index */
578 	el_c[MAX_COLOR], /* ELN */
579 	mi_c[MAX_COLOR], /* Misc indicators */
580 	ts_c[MAX_COLOR], /* TAB completion suffix */
581 	wc_c[MAX_COLOR], /* Welcome message color */
582 	wp_c[MAX_COLOR], /* Warning prompt */
583 
584 	/* Suggestions */
585 	sb_c[MAX_COLOR], /* Auto-suggestions: shell builtins */
586 	sc_c[MAX_COLOR], /* Auto-suggestions: external commands */
587 	sh_c[MAX_COLOR], /* Auto-suggestions: history */
588 	sf_c[MAX_COLOR], /* Auto-suggestions: filenames */
589 	sx_c[MAX_COLOR], /* Auto-suggestions: internal commands and params */
590 	sp_c[MAX_COLOR], /* Auto-suggestions: suggestions pointer */
591 
592 #ifndef _NO_ICONS
593 	dir_ico_c[MAX_COLOR], /* Directories icon color */
594 #endif
595 
596 	/* Syntax highlighting */
597 	hb_c[MAX_COLOR],		/* Brackets: () [] {} */
598 	hc_c[MAX_COLOR],		/* Comments */
599 	hd_c[MAX_COLOR],		/* Paths (slashes) */
600 	he_c[MAX_COLOR],		/* Expansion operators: * ~ */
601 	hn_c[MAX_COLOR],		/* Numbers */
602 	hp_c[MAX_COLOR],		/* Parameters: - */
603 	hq_c[MAX_COLOR],		/* Quoted strings */
604 	hr_c[MAX_COLOR],		/* Redirection: > */
605 	hs_c[MAX_COLOR],		/* Process separators: | & ; */
606 	hv_c[MAX_COLOR],		/* Variables: $ */
607 	hw_c[MAX_COLOR],		/* Wrong, non-existent command name */
608 
609 	/* Colors used in the prompt, so that \001 and \002 needs to
610 	 * be added. This is why MAX_COLOR + 2 */
611 	/* Workspaces */
612 	ws1_c[MAX_COLOR + 2],
613 	ws2_c[MAX_COLOR + 2],
614 	ws3_c[MAX_COLOR + 2],
615 	ws4_c[MAX_COLOR + 2],
616 	ws5_c[MAX_COLOR + 2],
617 	ws6_c[MAX_COLOR + 2],
618 	ws7_c[MAX_COLOR + 2],
619 	ws8_c[MAX_COLOR + 2],
620 
621 	em_c[MAX_COLOR + 2], /* Error msg color */
622 	li_c[MAX_COLOR + 2], /* Sel indicator color */
623 	li_cb[MAX_COLOR], /* Sel indicator color (for the files list) */
624 	nm_c[MAX_COLOR + 2], /* Notice msg color */
625 	wm_c[MAX_COLOR + 2], /* Warning msg color */
626 	si_c[MAX_COLOR + 2], /* stealth indicator color */
627 	ti_c[MAX_COLOR + 2], /* Trash indicator color */
628 	tx_c[MAX_COLOR + 2]; /* Text color */
629 
630 #ifdef LINUX_INOTIFY
631 int inotify_fd, inotify_wd = -1;
632 unsigned int INOTIFY_MASK =
633 	IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE | IN_MOVE_SELF
634 /*#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
635 	| IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_ONLYDIR | IN_MASK_CREATE;
636 #else */
637 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
638 	| IN_DONT_FOLLOW | IN_ONLYDIR
639 #endif /* LINUX >= 2.6.15 */
640 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
641 	| IN_EXCL_UNLINK
642 #endif /* LINUX >= 2.6.36 */
643 	;
644 #elif defined(BSD_KQUEUE)
645 int kq, event_fd = -1;
646 struct kevent events_to_monitor[NUM_EVENT_FDS];
647 unsigned int KQUEUE_FFLAGS = NOTE_DELETE | NOTE_EXTEND| NOTE_LINK
648 	| NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE;
649 struct timespec timeout;
650 #endif
651 int watch = -1;
652 
653 /*
654 static void
655 handle_sigwinch(int c)
656 {
657 	UNUSED(c);
658 
659 	if (kbind_busy)
660 		return;
661 
662 	if (clear_screen)
663 		CLEAR;
664 
665 	keybind_exec_cmd("rf");
666 } */
667 
668 			/**
669 				 * #############################
670 				 * #           MAIN            #
671 				 * #############################
672 				 * */
673 
674 int
main(int argc,char * argv[])675 main(int argc, char *argv[])
676 {
677 	/* Though this program might perfectly work on other architectures,
678 	 * I just didn't test anything beyond x86 and ARM */
679 #if !defined(__x86_64__) && !defined(__i386__) && !defined(__ARM_ARCH)
680 	fprintf(stderr, _("%s: Unsupported CPU architecture\n"), PROGRAM_NAME);
681 	exit(EXIT_FAILURE);
682 #endif
683 
684 #if !defined(__linux__) && !defined(__FreeBSD__) \
685 && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__HAIKU__)
686 	fprintf(stderr, _("%s: Unsupported operating system\n"), PROGRAM_NAME);
687 	exit(EXIT_FAILURE);
688 #endif
689 
690 	/* Make sure we are running on a supported terminal */
691 	check_term();
692 
693 /*	get_term_bgcolor(STDIN_FILENO, STDOUT_FILENO);
694 	printf("\x1b]11;#111111\007"); */
695 
696 //	signal(SIGWINCH, handle_sigwinch);
697 
698 	/* Set the default color */
699 /*	fputs(DEF_DF_C, stdout);
700 	fflush(stdout); */
701 
702 	/* If running the program locally, that is, not from a path in PATH,
703 	 * remove the leading "./" to get the correct program invocation
704 	 * name */
705 	if (*argv[0] == '.' && *(argv[0] + 1) == '/')
706 		argv[0] += 2;
707 
708 	/* Use the locale specified by the environment */
709 	setlocale(LC_ALL, "");
710 
711 	unicode = DEF_UNICODE;
712 
713 	/* Store external arguments to be able to rerun external_arguments()
714 	 * in case the user edits the config file, in which case the program
715 	 * must rerun init_config(), get_aliases(), get_prompt_cmds(), and
716 	 * then external_arguments() */
717 	backup_argv(argc, argv);
718 
719 	/* free_stuff does some cleaning */
720 	atexit(free_stuff);
721 
722 	user = get_user();
723 	get_home();
724 
725 	if (geteuid() == 0)
726 		flags |= ROOT_USR;
727 
728 	/* Running in a graphical environment? */
729 #if __linux__
730 	if (getenv("DISPLAY") != NULL && strncmp(getenv("TERM"), "linux", 5) != 0)
731 #else
732 	if (getenv("DISPLAY") != NULL)
733 #endif
734 		flags |= GUI;
735 
736 	/* Get paths from PATH environment variable. These paths will be
737 	 * used later by get_path_programs (for the autocomplete function)
738 	 * and get_cmd_path() */
739 	path_n = get_path_env();
740 	cdpath_n = get_cdpath();
741 	P_tmpdir_len = strlen(P_tmpdir);
742 	init_workspaces();
743 
744 	/* Set all external arguments flags to uninitialized state */
745 	unset_xargs();
746 
747 	/* Manage external arguments, but only if any: argc == 1 equates to
748 	 * no argument, since this '1' is just the program invokation name.
749 	 * External arguments will override initialization values
750 	 * (init_config) */
751 	if (argc > 1)
752 		external_arguments(argc, argv);
753 	/* external_arguments is executed before init_config because, if
754 	 * specified (-P option), it sets the value of alt_profile, which
755 	 * is then checked by init_config */
756 
757 	check_env_filter();
758 	get_data_dir();
759 
760 	/* Initialize program paths and files, set options from the config
761 	 * file, if they were not already set via external arguments, and
762 	 * load sel elements, if any. All these configurations are made
763 	 * per user basis */
764 
765 	init_config();
766 	check_options();
767 	set_sel_file();
768 	create_tmp_files();
769 	load_actions();
770 	get_aliases();
771 
772 	/* Get the list of available applications in PATH to be used by my
773 	 * custom TAB-completion function */
774 	get_path_programs();
775 
776 	/* Check third-party programs availability: FZF, udevil, and udisks2 */
777 	check_third_party_cmds();
778 
779 	/* Initialize gettext() for translations */
780 #ifndef _NO_GETTEXT
781 	init_gettext();
782 #endif
783 
784 /*	cschemes_n = get_colorschemes();
785 	set_colors(usr_cscheme ? usr_cscheme : "default", 1);
786 	free(usr_cscheme);
787 	usr_cscheme = (char *)NULL; */
788 
789 	fputs(df_c, stdout);
790 	fflush(stdout);
791 
792 	if (flags & ROOT_USR) {
793 		_err(0, PRINT_PROMPT, _("%s%s: %sRunning as root%s\n"),
794 			BOLD, PROGRAM_NAME, _RED, df_c);
795 	}
796 
797 	load_remotes();
798 	automount_remotes();
799 
800 	if (splash_screen) {
801 		splash();
802 		splash_screen = 0;
803 		CLEAR;
804 	}
805 
806 	set_start_path();
807 
808 	if (ws == (struct ws_t *)NULL || !ws[cur_ws].path || !*ws[cur_ws].path) {
809 		_err(0, NOPRINT_PROMPT, _("%s: Fatal error! Failed "
810 			"retrieving current working directory\n"), PROGRAM_NAME);
811 		exit(EXIT_FAILURE);
812 	}
813 
814 	/* Set terminal window title */
815 	if (flags & GUI) {
816 		if (xargs.cwd_in_title == 0) {
817 			printf("\033]2;%s\007", PROGRAM_NAME);
818 			fflush(stdout);
819 		} else {
820 			set_term_title(ws[cur_ws].path);
821 		}
822 	}
823 
824 	exec_profile();
825 	load_dirhist();
826 	add_to_dirhist(ws[cur_ws].path);
827 	get_sel_files();
828 
829 	/* Start listing as soon as possible to speed up startup time */
830 	if (autols && isatty(STDIN_FILENO)) {
831 #ifdef LINUX_INOTIFY
832 		/* Initialize inotify */
833 		inotify_fd = inotify_init1(IN_NONBLOCK);
834 		if (inotify_fd < 0) {
835 			_err('w', PRINT_PROMPT, "%s: inotify: %s\n", PROGRAM_NAME,
836 				strerror(errno));
837 		}
838 #elif defined(BSD_KQUEUE)
839 		kq = kqueue();
840 		if (kq < 0) {
841 			_err('w', PRINT_PROMPT, "%s: kqueue: %s\n", PROGRAM_NAME,
842 				strerror(errno));
843 		}
844 #endif
845 		list_dir();
846 	}
847 
848 	shell = get_sys_shell();
849 	create_kbinds_file();
850 	load_bookmarks();
851 	load_keybinds();
852 	load_jumpdb();
853 	if (!jump_db || xargs.path == 1)
854 		add_to_jumpdb(ws[cur_ws].path);
855 
856 	initialize_readline();
857 
858 	/*Trim the directory history file if necessary */
859 	check_file_size(dirhist_file, max_dirhist);
860 
861 	/* Check whether we have a working shell */
862 	if (access(user.shell, X_OK) == -1) {
863 		_err('w', PRINT_PROMPT, _("%s: %s: System shell not found. "
864 				"Please edit the configuration file to specify a working "
865 				"shell.\n"), PROGRAM_NAME, user.shell);
866 	}
867 
868 	get_prompt_cmds();
869 
870 #ifndef _NO_TRASH
871 	if (trash_ok) {
872 		trash_n = count_dir(trash_files_dir, NO_CPOP);
873 		if (trash_n <= 2)
874 			trash_n = 0;
875 	}
876 #endif
877 
878 	if (gethostname(hostname, sizeof(hostname)) == -1) {
879 		hostname[0] = '?';
880 		hostname[1] = '\0';
881 		_err('e', PRINT_PROMPT, _("%s: Error getting hostname\n"),
882 			PROGRAM_NAME);
883 	}
884 
885 	init_shell();
886 
887 	if (config_ok)
888 		init_history();
889 
890 	/* Store history into an array to be able to manipulate it */
891 	get_history();
892 
893 	/* Check if the 'file' command is available: we need it for Lira */
894 /*	if (!opener)
895 		file_cmd_check(); */
896 
897 	get_profile_names();
898 	load_pinned_dir();
899 	set_env();
900 
901 				/* ###########################
902 				 * #   2) MAIN PROGRAM LOOP  #
903 				 * ########################### */
904 
905 	/* This is the main structure of any basic shell
906 		 1 - Infinite loop
907 		 2 - Grab user input
908 		 3 - Parse user input
909 		 4 - Execute command
910 		 See https://brennan.io/2015/01/16/write-a-shell-in-c/
911 		 */
912 
913 	int i;
914 	/* 1) Infinite loop to keep the program running */
915 	while (1) {
916 		/* 2) Grab input string from the prompt */
917 		char *input = prompt();
918 		if (!input)
919 			continue;
920 
921 		/* 3) Parse input string */
922 		char **cmd = parse_input_str(input);
923 		free(input);
924 		input = (char *)NULL;
925 
926 		if (!cmd)
927 			continue;
928 
929 		/* 4) Execute input string */
930 		char **alias_cmd = check_for_alias(cmd);
931 		if (alias_cmd) {
932 			/* If an alias is found, check_for_alias() frees cmd
933 			 * and returns alias_cmd in its place to be executed by
934 			 * exec_cmd() */
935 			exec_cmd(alias_cmd);
936 
937 			for (i = 0; alias_cmd[i]; i++)
938 				free(alias_cmd[i]);
939 			free(alias_cmd);
940 			alias_cmd = (char **)NULL;
941 		} else {
942 			exec_cmd(cmd);
943 
944 			i = (int)args_n + 1;
945 			while (--i >= 0)
946 				free(cmd[i]);
947 			free(cmd);
948 			cmd = (char **)NULL;
949 		}
950 	}
951 
952 	return exit_code; /* Never reached */
953 }
954