1 /* config.c -- functions to define, create, and set configuration files */
2
3 /*
4 * This file is part of CliFM
5 *
6 * Copyright (C) 2016-2021, L. Abramovich <johndoe.arch@outlook.com>
7 * All rights reserved.
8
9 * CliFM is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * CliFM is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * MA 02110-1301, USA.
23 */
24
25 #include "helpers.h"
26
27 #include <errno.h>
28 #include <limits.h>
29 #include <stdio.h>
30 #include <readline/readline.h>
31 #include <string.h>
32 #include <sys/stat.h>
33 #include <time.h>
34 #include <unistd.h>
35
36 #include "aux.h"
37 #include "colors.h"
38 #include "config.h"
39 #include "exec.h"
40 #include "init.h"
41 #include "listing.h"
42 #include "mime.h"
43 #include "misc.h"
44 #include "navigation.h"
45 #include "file_operations.h"
46 #include "autocmds.h"
47
48 /* Regenerate the configuration file and create a back up of the old
49 * one */
50 static int
regen_config(void)51 regen_config(void)
52 {
53 int config_found = 1;
54 struct stat config_attrib;
55
56 if (stat(config_file, &config_attrib) == -1) {
57 puts(_("No configuration file found"));
58 config_found = 0;
59 }
60
61 if (config_found) {
62 time_t rawtime = time(NULL);
63 struct tm t;
64 localtime_r(&rawtime, &t);
65
66 char date[18];
67 strftime(date, 18, "%Y%m%d@%H:%M:%S", &t);
68
69 char *bk = (char *)xnmalloc(strlen(config_file) + strlen(date) + 2, sizeof(char));
70 sprintf(bk, "%s.%s", config_file, date);
71
72 char *cmd[] = {"mv", config_file, bk, NULL};
73
74 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) != EXIT_SUCCESS) {
75 free(bk);
76 return EXIT_FAILURE;
77 }
78
79 printf(_("Old configuration file stored as '%s'\n"), bk);
80 free(bk);
81 }
82
83 if (create_config(config_file) != EXIT_SUCCESS)
84 return EXIT_FAILURE;
85
86 printf(_("New configuration file written to '%s'\n"), config_file);
87 reload_config();
88 return EXIT_SUCCESS;
89 }
90
91 /* Edit the config file, either via the mime function or via the first
92 * passed argument (Ex: 'edit nano'). The 'gen' option regenerates
93 * the configuration file and creates a back up of the old one. */
94 int
edit_function(char ** comm)95 edit_function(char **comm)
96 {
97 if (xargs.stealth_mode == 1) {
98 printf(_("%s: Access to configuration files is not allowed in "
99 "stealth mode\n"), PROGRAM_NAME);
100 return EXIT_SUCCESS;
101 }
102
103 if (comm[1] && *comm[1] == '-' && strcmp(comm[1], "--help") == 0) {
104 printf("%s\n", EDIT_USAGE);
105 return EXIT_SUCCESS;
106 }
107
108 if (comm[1] && *comm[1] == 'r' && strcmp(comm[1], "reset") == 0)
109 return regen_config();
110
111 if (!config_ok) {
112 fprintf(stderr, _("%s: Cannot access the configuration file\n"),
113 PROGRAM_NAME);
114 return EXIT_FAILURE;
115 }
116
117 /* Get modification time of the config file before opening it */
118 struct stat file_attrib;
119
120 /* If, for some reason (like someone erasing the file while the
121 * program is running) clifmrc doesn't exist, recreate the
122 * configuration file. Then run 'stat' again to reread the attributes
123 * of the file */
124 if (stat(config_file, &file_attrib) == -1) {
125 create_config(config_file);
126 stat(config_file, &file_attrib);
127 }
128
129 time_t mtime_bfr = (time_t)file_attrib.st_mtime;
130 int ret = EXIT_SUCCESS;
131
132 /* If there is an argument... */
133 if (comm[1]) {
134 char *cmd[] = {comm[1], config_file, NULL};
135 ret = launch_execve(cmd, FOREGROUND, E_NOSTDERR);
136 } else {
137 /* If no application was passed as 2nd argument */
138 open_in_foreground = 1;
139 ret = open_file(config_file);
140 open_in_foreground = 0;
141 }
142
143 if (ret != EXIT_SUCCESS)
144 return EXIT_FAILURE;
145
146 /* Get modification time after opening the config file */
147 stat(config_file, &file_attrib);
148 /* If modification times differ, the file was modified after being
149 * opened */
150
151 if (mtime_bfr != (time_t)file_attrib.st_mtime) {
152 /* Reload configuration only if the config file was modified */
153 reload_config();
154 welcome_message = 0;
155
156 if (autols) {
157 free_dirlist();
158 ret = list_dir();
159 }
160 }
161
162 return ret;
163 }
164
165 void
set_env(void)166 set_env(void)
167 {
168 if (xargs.stealth_mode == 1)
169 return;
170
171 /* Set a few environment variables, mostly useful to run custom
172 * scripts via the actions function */
173 /* CLIFM env variable is set to one when CliFM is running, so that
174 * external programs can determine if they were spawned by CliFM */
175 setenv("CLIFM", config_dir ? config_dir : "1", 1);
176 setenv("CLIFM_PROFILE", alt_profile ? alt_profile : "default", 1);
177
178 if (sel_file)
179 setenv("CLIFM_SELFILE", sel_file, 1);
180 }
181
182 /* Define the file for the Selection Box */
183 void
set_sel_file(void)184 set_sel_file(void)
185 {
186 if (sel_file) {
187 free(sel_file);
188 sel_file = (char *)NULL;
189 }
190
191 if (!config_dir)
192 return;
193
194 size_t config_len = strlen(config_dir);
195
196 if (!share_selbox) {
197 /* Private selection box is stored in the profile
198 * directory */
199 sel_file = (char *)xnmalloc(config_len + 9, sizeof(char));
200
201 sprintf(sel_file, "%s/selbox", config_dir);
202 } else {
203 /* Common selection box is stored in the general
204 * configuration directory */
205 sel_file = (char *)xnmalloc(config_len + 17, sizeof(char));
206 sprintf(sel_file, "%s/.config/%s/selbox", user.home, PNL);
207 }
208
209 return;
210 }
211
212 int
create_kbinds_file(void)213 create_kbinds_file(void)
214 {
215 if (!config_ok)
216 return EXIT_FAILURE;
217
218 struct stat attr;
219 /* If the file already exists, do nothing */
220 if (stat(kbinds_file, &attr) == EXIT_SUCCESS)
221 return EXIT_SUCCESS;
222
223 /* If not, try to import it from DATADIR */
224 if (data_dir) {
225 char sys_file[PATH_MAX];
226 snprintf(sys_file, PATH_MAX - 1, "%s/%s/keybindings.cfm", data_dir, PNL);
227 if (stat(sys_file, &attr) == EXIT_SUCCESS) {
228 char *cmd[] = {"cp", sys_file, kbinds_file, NULL};
229 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) == EXIT_SUCCESS)
230 return EXIT_SUCCESS;
231 }
232 }
233
234 /* Else, create it */
235 FILE *fp = fopen(kbinds_file, "w");
236 if (!fp) {
237 _err('w', PRINT_PROMPT, "%s: '%s': %s\n", PROGRAM_NAME, kbinds_file,
238 strerror(errno));
239 return EXIT_FAILURE;
240 }
241
242 fprintf(fp, "# Keybindings file for %s\n\n\
243 # Use the 'kbgen' plugin (compile it first: gcc -o kbgen kbgen.c) to \n\
244 # find out the escape code for the key or key sequence you want. Use \n\
245 # either octal, hexadecimal codes or symbols.\n\
246 # Ex: For Alt-/ (in rxvt terminals) 'kbgen' will print the following \n\
247 # lines:\n\
248 # Hex | Oct | Symbol\n\
249 # ---- | ---- | ------\n\
250 # \\x1b | \\033 | ESC (\\e)\n\
251 # \\x2f | \\057 | /\n\
252 # In this case, the keybinding, if using symbols, is: \"\\e/:function\"\n\
253 # In case you prefer the hex codes it would be: \\x1b\\x2f:function.\n\
254 # GNU emacs escape sequences are also allowed (ex: \"\\M-a\", Alt-a\n\
255 # in most keyboards, or \"\\C-r\" for Ctrl-r).\n\
256 # Some codes, especially those involving keys like Ctrl or the arrow\n\
257 # keys, vary depending on the terminal emulator and the system settings.\n\
258 # These keybindings should be set up thus on a per terminal basis.\n\
259 # You can also consult the terminfo database via the infocmp command.\n\
260 # See terminfo(5) and infocmp(1).\n\
261 \n\
262 # Alt-j\n\
263 previous-dir:\\M-j\n\
264 # Shift-Left (rxvt)\n\
265 previous-dir2:\\e[d\n\
266 # Shift-Left (xterm)\n\
267 previous-dir3:\\e[2D\n\
268 # Shift-Left (others)\n\
269 previous-dir4:\\e[1;2D\n\
270 \n\
271 # Alt-k\n\
272 next-dir:\\M-k\n\
273 # Shift-right (rxvt)\n\
274 next-dir2:\\e[c\n\
275 # Shift-Right (xterm)\n\
276 next-dir3:\\e[2C\n\
277 # Shift-Right (others)\n\
278 next-dir4:\\e[1;2C\n\
279 first-dir:\\C-\\M-j\n\
280 last-dir:\\C-\\M-k\n\
281 \n\
282 # Alt-u\n\
283 parent-dir:\\M-u\n\
284 # Shift-Up (rxvt)\n\
285 parent-dir2:\\e[a\n\
286 # Shift-Up (xterm)\n\
287 parent-dir3:\\e[2A\n\
288 # Shift-Up (others)\n\
289 parent-dir4:\\e[1;2A\n\
290 \n\
291 # Alt-e\n\
292 home-dir:\\M-e\n\
293 # Home key (rxvt)\n\
294 home-dir2:\\e[7~\n\
295 # Home key (xterm)\n\
296 home-dir3:\\e[H\n\
297 home-dir4:\n\
298 \n\
299 # Alt-r\n\
300 root-dir:\\M-r\n\
301 # Alt-/ (rxvt)\n\
302 root-dir2:\\e/\n\
303 #root-dir3:\n\
304 \n\
305 pinned-dir:\\M-p\n\
306 workspace1:\\M-1\n\
307 workspace2:\\M-2\n\
308 workspace3:\\M-3\n\
309 workspace4:\\M-4\n\
310 \n\
311 # Help\n\
312 # F1-3\n\
313 show-manpage:\\eOP\n\
314 show-cmds:\\eOQ\n\
315 show-kbinds:\\eOR\n\
316 \n\
317 prepend-sudo:\\M-v\n\
318 create-file:\\M-n\n\
319 new-instance:\\C-x\n\
320 previous-profile:\\C-\\M-o\n\
321 next-profile:\\C-\\M-p\n\
322 archive-sel:\\C-\\M-a\n\
323 rename-sel:\\C-\\M-r\n\
324 remove-sel:\\C-\\M-d\n\
325 trash-sel:\\C-\\M-t\n\
326 untrash-all:\\C-\\M-u\n\
327 paste-sel:\\C-\\M-v\n\
328 move-sel:\\C-\\M-n\n\
329 export-sel:\\C-\\M-e\n\
330 open-sel:\\C-\\M-g\n\
331 bookmark-sel:\\C-\\M-b\n\
332 refresh-screen:\\C-r\n\
333 clear-line:\\M-c\n\
334 clear-msgs:\\M-t\n\
335 show-dirhist:\\M-h\n\
336 toggle-hidden:\\M-i\n\
337 toggle-hidden2:\\M-.\n\
338 toggle-light:\\M-y\n\
339 toggle-long:\\M-l\n\
340 sort-previous:\\M-z\n\
341 sort-next:\\M-x\n\
342 bookmarks:\\M-b\n\
343 select-all:\\M-a\n\
344 deselect-all:\\M-d\n\
345 mountpoints:\\M-m\n\
346 folders-first:\\M-g\n\
347 selbox:\\M-s\n\
348 lock:\\M-o\n\
349 # F6-12\n\
350 open-mime:\\e[17~\n\
351 open-jump-db:\\e[18~\n\
352 edit-color-scheme:\\e[19~\n\
353 open-keybinds:\\e[20~\n\
354 open-config:\\e[21~\n\
355 open-bookmarks:\\e[23~\n\
356 quit:\\e[24~\n\n\
357 # Plugins\n\
358 # 1) Make sure your plugin is in the plugins directory (or use any of the\n\
359 # plugins in there)\n\
360 # 2) Link pluginx to your plugin using the 'actions edit' command. Ex:\n\
361 # \"plugin1=myplugin.sh\"\n\
362 # 3) Set a keybinding here for pluginx. Ex: \"plugin1:\\M-7\"\n\n\
363 #plugin1:\n\
364 #plugin2:\n\
365 #plugin3:\n\
366 #plugin4:\n",
367 PROGRAM_NAME);
368
369 fclose(fp);
370 return EXIT_SUCCESS;
371 }
372
373 static int
import_from_data_dir(char * src_filename,char * dest)374 import_from_data_dir(char *src_filename, char *dest)
375 {
376 if (!data_dir || !src_filename || !dest)
377 return EXIT_FAILURE;
378
379 if (!*data_dir || !*src_filename || !*dest)
380 return EXIT_FAILURE;
381
382 struct stat attr;
383 char sys_file[PATH_MAX];
384 snprintf(sys_file, PATH_MAX - 1, "%s/%s/%s", data_dir, PNL, src_filename);
385 if (stat(sys_file, &attr) == EXIT_SUCCESS) {
386 char *cmd[] = {"cp", sys_file, dest, NULL};
387 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) == EXIT_SUCCESS)
388 return EXIT_SUCCESS;
389 }
390
391 return EXIT_FAILURE;
392 }
393
394 static int
create_actions_file(char * file)395 create_actions_file(char *file)
396 {
397 struct stat attr;
398 /* If the file already exists, do nothing */
399 if (stat(file, &attr) == EXIT_SUCCESS)
400 return EXIT_SUCCESS;
401
402 /* If not, try to import it from DATADIR */
403 if (import_from_data_dir("actions.cfm", file) == EXIT_SUCCESS)
404 return EXIT_SUCCESS;
405
406 /* Else, create it */
407 int fd;
408 FILE *fp = open_fstream_w(file, &fd);
409 if (!fp) {
410 _err('e', PRINT_PROMPT, "%s: '%s': %s\n", PROGRAM_NAME,
411 file, strerror(errno));
412 return EXIT_FAILURE;
413 }
414
415 fprintf(fp, "######################\n"
416 "# Actions file for %s #\n"
417 "######################\n\n"
418 "# Define here your custom actions. Actions are "
419 "custom command names\n"
420 "# bound to a executable file located either in "
421 "DATADIR/clifm/plugins\n"
422 "# (usually /usr/share/clifm/plugins) or in "
423 "$XDG_CONFIG_HOME/clifm/plugins.\n"
424 "# Actions can be executed directly from "
425 "%s command line, as if they\n"
426 "# were any other command, and the associated "
427 "file will be executed\n"
428 "# instead. All parameters passed to the action "
429 "command will be passed\n"
430 "# to the corresponding plugin as well.\n\n"
431 "i=img_viewer.sh\n"
432 "kbgen=kbgen\n"
433 "vid=vid_viewer.sh\n"
434 "ptot=pdf_viewer.sh\n"
435 "music=music_player.sh\n"
436 "update=update.sh\n"
437 "wall=wallpaper_setter.sh\n"
438 "dragon=dragondrop.sh\n"
439 "bn=batch_create.sh\n"
440 "+=finder.sh\n"
441 "++=jumper.sh\n"
442 "-=fzfnav.sh\n"
443 "*=fzfsel.sh\n"
444 "**=fzfdesel.sh\n"
445 "h=fzfhist.sh\n"
446 "dh=fzfdirhist.sh\n"
447 "//=rgfind.sh\n"
448 "ih=ihelp.sh\n",
449 PROGRAM_NAME, PROGRAM_NAME);
450
451 close_fstream(fp, fd);
452 return EXIT_SUCCESS;
453 }
454
455 void
create_tmp_files(void)456 create_tmp_files(void)
457 {
458 if (xargs.stealth_mode == 1)
459 return;
460
461 if (!user.name)
462 return;
463
464 size_t pnl_len = strlen(PNL);
465
466 /* #### CHECK THE TMP DIR #### */
467
468 /* If the temporary directory doesn't exist, create it. I create
469 * the parent directory (/tmp/clifm) with 1777 permissions (world
470 * writable with the sticky bit set), so that every user is able
471 * to create files in here, but only the file's owner can remove
472 * or modify them */
473 size_t user_len = strlen(user.name);
474 tmp_dir = (char *)xnmalloc(P_tmpdir_len + pnl_len + user_len + 3, sizeof(char));
475 sprintf(tmp_dir, "%s/%s", P_tmpdir, PNL);
476 /* P_tmpdir is defined in stdio.h and it's value is usually /tmp */
477
478 int tmp_root_ok = 1;
479 struct stat attr;
480 /* Create /tmp */
481 if (stat(P_tmpdir, &attr) == -1)
482 if (xmkdir(P_tmpdir, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX) == EXIT_FAILURE)
483 tmp_root_ok = 0;
484 /* Create /tmp/clifm */
485 if (stat(tmp_dir, &attr) == -1)
486 xmkdir(tmp_dir, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
487
488 /* Once the parent directory exists, create the user's directory to
489 * store the list of selected files:
490 * TMP_DIR/clifm/username/.selbox_PROFILE. I use here very
491 * restrictive permissions (700), since only the corresponding user
492 * must be able to read and/or modify this list */
493 sprintf(tmp_dir, "%s/%s/%s", P_tmpdir, PNL, user.name);
494 if (stat(tmp_dir, &attr) == -1) {
495 if (xmkdir(tmp_dir, S_IRWXU) == EXIT_FAILURE) {
496 selfile_ok = 0;
497 _err('e', PRINT_PROMPT, _("%s: %s: %s\n"), PROGRAM_NAME,
498 tmp_dir, strerror(errno));
499 }
500 }
501
502 /* If the directory exists, check it is writable */
503 else if (access(tmp_dir, W_OK) == -1) {
504 if (!sel_file) {
505 selfile_ok = 0;
506 _err('w', PRINT_PROMPT, "%s: %s: Directory not writable. Selected "
507 "files will be lost after program exit\n",
508 PROGRAM_NAME, tmp_dir);
509 }
510 }
511
512 /* sel_file should has been set before by set_sel_file(). If not set,
513 * we do not have access to the config dir */
514 if (sel_file)
515 return;
516
517 /*"We will write a temporary selfile in /tmp. Check if this latter is
518 * available */
519 if (!tmp_root_ok) {
520 _err('w', PRINT_PROMPT, "%s: Could not create the selections file.\n"
521 "Selected files will be lost after program exit\n",
522 PROGRAM_NAME, tmp_dir);
523 return;
524 }
525
526 /* If the config directory isn't available, define an alternative
527 * selection file in /tmp (if available) */
528 if (!share_selbox) {
529 size_t prof_len = 0;
530
531 if (alt_profile)
532 prof_len = strlen(alt_profile);
533 else
534 prof_len = 7; /* Lenght of "default" */
535
536 sel_file = (char *)xnmalloc(P_tmpdir_len + prof_len + 9,
537 sizeof(char));
538 sprintf(sel_file, "%s/selbox_%s", P_tmpdir,
539 (alt_profile) ? alt_profile : "default");
540 } else {
541 sel_file = (char *)xnmalloc(P_tmpdir_len + 8, sizeof(char));
542 sprintf(sel_file, "%s/selbox", P_tmpdir);
543 }
544
545 _err('w', PRINT_PROMPT, _("%s: '%s': Using a temporary directory for "
546 "the Selection Box. Selected files won't be persistent across "
547 "reboots"), PROGRAM_NAME, tmp_dir);
548 }
549
550 static void
define_config_file_names(void)551 define_config_file_names(void)
552 {
553 size_t pnl_len = strlen(PNL);
554
555 if (alt_config_dir) {
556 config_dir_gral = (char *)xnmalloc(strlen(alt_config_dir) + pnl_len
557 + 2, sizeof(char));
558 sprintf(config_dir_gral, "%s/%s", alt_config_dir, PNL);
559 free(alt_config_dir);
560 } else {
561 /* If $XDG_CONFIG_HOME is set, use it for the config file.
562 * Else, fall back to $HOME/.config */
563 char *xdg_config_home = getenv("XDG_CONFIG_HOME");
564 if (xdg_config_home) {
565 size_t xdg_config_home_len = strlen(xdg_config_home);
566 config_dir_gral = (char *)xnmalloc(xdg_config_home_len + pnl_len
567 + 2, sizeof(char));
568 sprintf(config_dir_gral, "%s/%s", xdg_config_home, PNL);
569 xdg_config_home = (char *)NULL;
570 } else {
571 config_dir_gral = (char *)xnmalloc(user.home_len + pnl_len + 11,
572 sizeof(char));
573 sprintf(config_dir_gral, "%s/.config/%s", user.home, PNL);
574 }
575 }
576
577 size_t config_gral_len = strlen(config_dir_gral);
578
579 /* alt_profile will not be NULL whenever the -P option is used
580 * to run the program under an alternative profile */
581 if (alt_profile) {
582 config_dir = (char *)xnmalloc(config_gral_len + strlen(alt_profile) + 11, sizeof(char));
583 sprintf(config_dir, "%s/profiles/%s", config_dir_gral, alt_profile);
584 } else {
585 config_dir = (char *)xnmalloc(config_gral_len + 18, sizeof(char));
586 sprintf(config_dir, "%s/profiles/default", config_dir_gral);
587 }
588
589 if (alt_kbinds_file) {
590 kbinds_file = savestring(alt_kbinds_file, strlen(alt_kbinds_file));
591 free(alt_kbinds_file);
592 alt_kbinds_file = (char *)NULL;
593 } else {
594 /* Keybindings per user, not per profile */
595 kbinds_file = (char *)xnmalloc(config_gral_len + 17, sizeof(char));
596 sprintf(kbinds_file, "%s/keybindings.cfm", config_dir_gral);
597 }
598
599 colors_dir = (char *)xnmalloc(config_gral_len + 8, sizeof(char));
600 sprintf(colors_dir, "%s/colors", config_dir_gral);
601
602 plugins_dir = (char *)xnmalloc(config_gral_len + 9, sizeof(char));
603 sprintf(plugins_dir, "%s/plugins", config_dir_gral);
604
605 #ifndef _NO_TRASH
606 trash_dir = (char *)xnmalloc(user.home_len + 20, sizeof(char));
607 sprintf(trash_dir, "%s/.local/share/Trash", user.home);
608
609 size_t trash_len = strlen(trash_dir);
610
611 trash_files_dir = (char *)xnmalloc(trash_len + 7, sizeof(char));
612 sprintf(trash_files_dir, "%s/files", trash_dir);
613
614 trash_info_dir = (char *)xnmalloc(trash_len + 6, sizeof(char));
615 sprintf(trash_info_dir, "%s/info", trash_dir);
616 #endif
617
618 size_t config_len = strlen(config_dir);
619
620 dirhist_file = (char *)xnmalloc(config_len + 13, sizeof(char));
621 sprintf(dirhist_file, "%s/dirhist.cfm", config_dir);
622
623 if (!alt_bm_file) {
624 bm_file = (char *)xnmalloc(config_len + 15, sizeof(char));
625 sprintf(bm_file, "%s/bookmarks.cfm", config_dir);
626 } else {
627 bm_file = savestring(alt_bm_file, strlen(alt_bm_file));
628 free(alt_bm_file);
629 alt_bm_file = (char *)NULL;
630 }
631
632 log_file = (char *)xnmalloc(config_len + 9, sizeof(char));
633 sprintf(log_file, "%s/log.cfm", config_dir);
634
635 hist_file = (char *)xnmalloc(config_len + 13, sizeof(char));
636 sprintf(hist_file, "%s/history.cfm", config_dir);
637
638 if (!alt_config_file) {
639 config_file = (char *)xnmalloc(config_len + pnl_len + 4, sizeof(char));
640 sprintf(config_file, "%s/%src", config_dir, PNL);
641 } else {
642 config_file = savestring(alt_config_file, strlen(alt_config_file));
643 free(alt_config_file);
644 alt_config_file = (char *)NULL;
645 }
646
647 profile_file = (char *)xnmalloc(config_len + 13, sizeof(char));
648 sprintf(profile_file, "%s/profile.cfm", config_dir);
649
650 msg_log_file = (char *)xnmalloc(config_len + 14, sizeof(char));
651 sprintf(msg_log_file, "%s/messages.cfm", config_dir);
652
653 mime_file = (char *)xnmalloc(config_len + 14, sizeof(char));
654 sprintf(mime_file, "%s/mimelist.cfm", config_dir);
655
656 actions_file = (char *)xnmalloc(config_len + 13, sizeof(char));
657 sprintf(actions_file, "%s/actions.cfm", config_dir);
658
659 remotes_file = (char *)xnmalloc(config_len + 10, sizeof(char));
660 sprintf(remotes_file, "%s/nets.cfm", config_dir);
661
662 return;
663 }
664
665 static int
import_rl_file(void)666 import_rl_file(void)
667 {
668 if (!data_dir || !config_dir_gral)
669 return EXIT_FAILURE;
670
671 char tmp[PATH_MAX];
672 sprintf(tmp, "%s/readline.cfm", config_dir_gral);
673 struct stat attr;
674 if (lstat(tmp, &attr) == 0)
675 return EXIT_SUCCESS;
676
677 char rl_file[PATH_MAX];
678 snprintf(rl_file, PATH_MAX - 1, "%s/%s/readline.cfm", data_dir, PNL);
679 if (stat(rl_file, &attr) == EXIT_SUCCESS) {
680 char *cmd[] = {"cp", rl_file, config_dir_gral, NULL};
681 if (launch_execve(cmd, FOREGROUND, E_NOSTDERR) == EXIT_SUCCESS)
682 return EXIT_SUCCESS;
683 }
684
685 return EXIT_FAILURE;
686 }
687
688 int
create_config(char * file)689 create_config(char *file)
690 {
691 // struct stat attr;
692
693 /* First, try to import it from DATADIR */
694 char src_filename[NAME_MAX];
695 snprintf(src_filename, NAME_MAX, "%src", PNL);
696 if (import_from_data_dir(src_filename, file) == EXIT_SUCCESS)
697 return EXIT_SUCCESS;
698 /* if (data_dir) {
699 char sys_file[PATH_MAX];
700 snprintf(sys_file, PATH_MAX - 1, "%s/%s/%src", data_dir, PNL, PNL);
701 if (stat(sys_file, &attr) == EXIT_SUCCESS) {
702 char *cmd[] = {"cp", sys_file, file, NULL};
703 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) == EXIT_SUCCESS)
704 return EXIT_SUCCESS;
705 }
706 } */
707
708 /* If not found, create it */
709 int fd;
710 FILE *config_fp = open_fstream_w(file, &fd);
711
712 if (!config_fp) {
713 fprintf(stderr, "%s: fopen: %s: %s\n", PROGRAM_NAME, file, strerror(errno));
714 return EXIT_FAILURE;
715 }
716
717 /* Do not translate anything in the config file */
718 fprintf(config_fp,
719
720 "\t\t###########################################\n\
721 \t\t# CLIFM #\n\
722 \t\t# The command line file manager #\n\
723 \t\t###########################################\n\n"
724
725 "# This is the configuration file for CliFM\n\n"
726
727 "# Color schemes are stored in the colors directory. By default,\n\
728 # the 'default' color scheme is used. Visit %s\n\
729 # to get a few more\n\
730 ColorScheme=%s\n\n"
731
732 "# The amount of files contained by a directory is informed next\n\
733 # to the directory name. However, this feature might slow things down when,\n\
734 # for example, listing files on a remote server. The filescounter can be\n\
735 # disabled here, via the --no-files-counter option, or using the 'fc'\n\
736 # command while in the program itself.\n\
737 FilesCounter=%s\n\n"
738
739 "# The character(s) used to construct the line dividing the list of files and\n\
740 # the prompt. if '0', print just an empty line; if only one char, this char\n\
741 # is printed reapeatedly to fulfill the screen; if 3 or more chars, only these\n\
742 # chars (no more) will be printed. Finally, if unset, print a special line\n\
743 # drawn with bow-drawing characters (not supported by all terminals/consoles)\n\
744 DividingLineChar='%c'\n\n"
745
746 "# How to list files: 0 = vertically (like ls(1) would), 1 = horizontally\n\
747 ListingMode=%d\n\n"
748
749 "# List files automatically after changing current directory\n\
750 AutoLs=%s\n\n"
751
752 "# If set to true, print a map of the current position in the directory\n\
753 # history list, showing previous, current, and next entries\n\
754 DirhistMap=%s\n\n"
755
756 "# Use a regex expression to filter file names when listing files.\n\
757 # Example: !.*~$ to exclude backup files (ending with ~), or ^\\. to list \n\
758 # only hidden files. Do not quote the regular expression\n\
759 Filter=\n\n"
760
761 "# Set the default copy command. Available options are: 0 = cp,\n\
762 # 1 = advcp, and 2 = wcp. Both 1 and 2 add a progress bar to cp.\n\
763 cpCmd=%d\n\n"
764
765 "# Set the default move command. Available options are: 0 = mv,\n\
766 # and 1 = advmv. 1 adds a progress bar to mv.\n\
767 mvCmd=%d\n\n"
768
769 "# The prompt line is built using string literals and/or one or more of\n\
770 # the following escape sequences:\n"
771 "# \\e: Escape character\n\
772 # \\h: The hostname, up to the first dot\n\
773 # \\u: The username\n\
774 # \\H: The full hostname\n\
775 # \\n: A newline character\n\
776 # \\r: A carriage return\n\
777 # \\a: A bell character\n\
778 # \\d: The date, in abbrevieted form (ex: 'Tue May 26')\n\
779 # \\s: The name of the shell (everything after the last slash) currently used\n\
780 # by CliFM\n\
781 # \\S: The number of the current workspace\n\
782 # \\l: Print an 'L' if running in light mode\n\
783 # \\P: Current profile name\n\
784 # \\t: The time, in 24-hour HH:MM:SS format\n\
785 # \\T: The time, in 12-hour HH:MM:SS format\n\
786 # \\@: The time, in 12-hour am/pm format\n\
787 # \\A: The time, in 24-hour HH:MM format\n\
788 # \\w: The full current working directory, with $HOME abbreviated with a tilde\n\
789 # \\W: The basename of $PWD, with $HOME abbreviated with a tilde\n\
790 # \\p: A mix of the two above, it abbreviates the current working directory \n\
791 # only if longer than PathMax (a value defined in the configuration file).\n\
792 # \\z: Exit code of the last executed command. :) if success and :( in case of\n\
793 # error\n\
794 # \\$ '#', if the effective user ID is 0, and '$' otherwise\n\
795 # \\nnn: The character whose ASCII code is the octal value nnn\n\
796 # \\\\: A backslash\n\
797 # \\[: Begin a sequence of non-printing characters. This is mostly used to\n\
798 # add color to the prompt line\n\
799 # \\]: End a sequence of non-printing characters\n\n"
800
801 "Prompt=\"%s\"\n\n"
802
803 "# If set to 'default', CliFM state information (selected files,\n\
804 # trashed files, current workspace, messages, and stealth mode) will be printed\n\
805 # to the left of the prompt. Otherwise, if set to 'custom', this information\n\
806 # will be stored in environment variables to be handled by the prompt string\n\
807 # itself. Consult the manpage for more information.\n\
808 PromptStyle=default\n\n"
809
810 "# A prompt to warn the user about invalid command names\n\
811 WarningPrompt=%s\n\n"
812
813 "# String to be used by the warning prompt. The color of this prompt\n\
814 # can be customized using the 'wp' code in the color scheme file\n\
815 WarningPromptStr=\"%s\"\n\n"
816
817 "# Should we add padding to ELN's. Possible values: 0:none, 1=zeroes\n\
818 # 2=spaces on the left, and 3=spaces on the right\n\
819 ELNPad=%d\n\n",
820
821 COLORS_REPO,
822 DEF_COLOR_SCHEME,
823 DEF_FILES_COUNTER == 1 ? "true" : "false",
824 DEF_DIV_LINE_CHAR,
825 DEF_LISTING_MODE,
826 DEF_AUTOLS == 1 ? "true" : "false",
827 DEF_DIRHIST_MAP == 1 ? "true" : "false",
828 DEF_CP_CMD,
829 DEF_MV_CMD,
830 DEFAULT_PROMPT,
831 DEF_WARNING_PROMPT == 1 ? "true" : "false",
832 DEF_WPROMPT_STR,
833 DEF_ELNPAD);
834
835 fprintf(config_fp,
836
837 "# TAB completion mode: either 'standard' (default) or 'fzf'\n\
838 TabCompletionMode=%s\n\n"
839
840 "# If FZF TAB completion mode is enabled, pass these options to fzf.\n\
841 # --height, --margin, +i/-i, and --query will be appended to set up the \n\
842 # completions interface.\n\
843 FzfTabOptions=%s\n\n"
844
845 "# MaxPath is only used for the /p option of the prompt: the current working\n\
846 # directory will be abbreviated to its basename (everything after last slash)\n\
847 # whenever the current path is longer than MaxPath.\n\
848 MaxPath=%d\n\n"
849
850 "WelcomeMessage=%s\n\n\
851 # Print %s's logo screen at startup\n\
852 SplashScreen=%s\n\n\
853 ShowHiddenFiles=%s\n\n\
854 # List files properties next to file names instead of just file names\n\
855 LongViewMode=%s\n\n\
856 # Keep a record of both external commands and internal commands able to\n\
857 # modify the files system (e.g. 'r', 'c', 'm', and so on)\n\
858 LogCmds=%s\n\n"
859
860 "# Minimum length at which a file name can be trimmed in long view mode\n\
861 # (including ELN length and spaces). When running in long mode, this setting\n\
862 # overrides MaxFilenameLen\n\
863 MinFilenameTrim=%d\n\n"
864
865 "# When a directory rank in the jump database is below MinJumpRank, it\n\
866 # will be forgotten\n\
867 MinJumpRank=%d\n\n"
868
869 "# When the sum of all ranks in the jump database reaches MaxJumpTotalRank,\n\
870 # all ranks will be reduced 10%%, and those falling below MinJumpRank will\n\
871 # be deleted\n\
872 MaxJumpTotalRank=%d\n\n"
873
874 "# Should CliFM be allowed to run external, shell commands?\n\
875 ExternalCommands=%s\n\n"
876
877 "# Write the last visited directory to $XDG_CONFIG_HOME/clifm/.last to be\n\
878 # later accessed by the corresponding shell function at program exit.\n\
879 # To enable this feature consult the manpage.\n\
880 CdOnQuit=%s\n\n"
881
882 "# If set to true, a command name that is the name of a directory or a\n\
883 # file is executed as if it were the argument to the the 'cd' or the \n\
884 # 'open' commands respectivelly: 'cd DIR' works the same as just 'DIR'\n\
885 # and 'open FILE' works the same as just 'FILE'.\n\
886 Autocd=%s\n\
887 AutoOpen=%s\n\n"
888
889 "# If set to true, enable auto-suggestions.\n\
890 AutoSuggestions=%s\n\n"
891
892 "# The following checks will be performed in the order specified\n\
893 # by SuggestionStrategy. Available checks:\n\
894 # a = Aliases names\n\
895 # b = Bookmarks names\n\
896 # c = Possible completions\n\
897 # e = ELN's\n\
898 # f = File names in current directory\n\
899 # h = Commands history\n\
900 # j = Jump database\n\
901 # Use a dash (-) to skip a check. Ex: 'eahfj-c' to skip the bookmarks check\n\
902 SuggestionStrategy=%s\n\n"
903
904 "# If set to true, suggest file names using the corresponding\n\
905 # file type color (set via the color scheme file).\n\
906 SuggestFiletypeColor=%s\n\n"
907
908 "SyntaxHighlighting=%s\n\n"
909
910 "# If set to true, expand bookmark names into the corresponding bookmark\n\
911 # path: if the bookmark is \"name=/path\", \"name\" will be interpreted\n\
912 # as /path. TAB completion is also available for bookmark names.\n\
913 ExpandBookmarks=%s\n\n"
914
915 "# In light mode, extra file type checks (except those provided by\n\
916 # the d_type field of the dirent structure (see readdir(3))\n\
917 # are disabled to speed up the listing process. stat(3) and access(3)\n\
918 # are not executed at all, so that we cannot know in advance if a file\n\
919 # is readable by the current user, if it is executable, SUID, SGID, if a\n\
920 # symlink is broken, and so on. The file extension check is ignored as\n\
921 # well, so that the color per extension feature is disabled.\n\
922 LightMode=%s\n\n",
923
924 DEF_FZFTAB == 1 ? "fzf" : "standard",
925 DEF_FZFTAB_OPTIONS,
926 DEF_MAX_PATH,
927 DEF_WELCOME_MESSAGE == 1 ? "true" : "false",
928 PROGRAM_NAME,
929 DEF_SPLASH_SCREEN == 1 ? "true" : "false",
930 DEF_SHOW_HIDDEN == 1 ? "true" : "false",
931 DEF_LONG_VIEW == 1 ? "true" : "false",
932 DEF_LOGS_ENABLED == 1 ? "true" : "false",
933 DEF_MIN_NAME_TRIM,
934 DEF_MIN_JUMP_RANK,
935 DEF_MAX_JUMP_TOTAL_RANK,
936 DEF_EXT_CMD_OK == 1 ? "true" : "false",
937 DEF_CD_ON_QUIT == 1 ? "true" : "false",
938 DEF_AUTOCD == 1 ? "true" : "false",
939 DEF_AUTO_OPEN == 1 ? "true" : "false",
940 DEF_SUGGESTIONS == 1 ? "true" : "false",
941 DEF_SUG_STRATEGY,
942 DEF_SUG_FILETYPE_COLOR == 1 ? "true" : "false",
943 DEF_HIGHLIGHT == 1 ? "true" : "false",
944 DEF_EXPAND_BOOKMARKS == 1 ? "true" : "false",
945 DEF_LIGHT_MODE == 1 ? "true" : "false"
946 );
947
948 fprintf(config_fp,
949 "# If running with colors, append directory indicator\n\
950 # to directories. If running without colors (via the --no-colors option),\n\
951 # append file type indicator at the end of file names: '/' for directories,\n\
952 # '@' for symbolic links, '=' for sockets, '|' for FIFO/pipes, '*'\n\
953 # for for executable files, and '?' for unknown file types. Bear in mind\n\
954 # that when running in light mode the check for executable files won't be\n\
955 # performed, and thereby no indicator will be added to executable files.\n\
956 Classify=%s\n\n"
957
958 "# Should the Selection Box be shared among different profiles?\n\
959 ShareSelbox=%s\n\n"
960
961 "# Choose the resource opener to open files with their default associated\n\
962 # application. If not set, 'lira', CLiFM's built-in opener, is used.\n\
963 Opener=\n\n"
964
965 "# Only used when opening a directory via a new CliFM instance (with the 'x'\n\
966 # command), this option specifies the command to be used to launch a\n\
967 # terminal emulator to run CliFM on it.\n\
968 TerminalCmd='%s'\n\n"
969
970 "# Choose sorting method: 0 = none, 1 = name, 2 = size, 3 = atime\n\
971 # 4 = btime (ctime if not available), 5 = ctime, 6 = mtime, 7 = version\n\
972 # (name if note available) 8 = extension, 9 = inode, 10 = owner, 11 = group\n\
973 # NOTE: the 'version' method is not available on FreeBSD\n\
974 Sort=%d\n\
975 # By default, CliFM sorts files from less to more (ex: from 'a' to 'z' if\n\
976 # using the \"name\" method). To invert this ordering, set SortReverse to\n\
977 # true (you can also use the --sort-reverse option or the 'st' command)\n\
978 SortReverse=%s\n\n"
979
980 "# Print a usage tip at startup\n\
981 Tips=%s\n\n\
982 ListFoldersFirst=%s\n\n\
983 # Enable case sensitive listing for files in the current directory\n\
984 CaseSensitiveList=%s\n\n\
985 # Enable case sensitive lookup for the directory jumper function (via \n\
986 # the 'j' command)\n\
987 CaseSensitiveDirJump=%s\n\n\
988 # Enable case sensitive completion for file names\n\
989 CaseSensitivePathComp=%s\n\n\
990 # Enable case sensitive search\n\
991 CaseSensitiveSearch=%s\n\n\
992 Unicode=%s\n\n\
993 # Enable Mas, the files list pager (executed whenever the list of files\n\
994 # does not fit in the screen)\n\
995 Pager=%s\n\n"
996
997 "# Maximum file name length for listed files. Names larger than\n\
998 # MAXFILENAMELEN will be truncated at MAXFILENAMELEN using a tilde.\n\
999 # When running in long mode, this setting is overriden by MinFilenameTrim\n\
1000 MaxFilenameLen=\n\n"
1001
1002 "MaxHistory=%d\n\
1003 MaxDirhist=%d\n\
1004 MaxLog=%d\n\
1005 Icons=%s\n\
1006 DiskUsage=%s\n\n"
1007
1008 "# If set to true, always print the list of selected files. Since this\n\
1009 # list could become quite extensive, you can limit the number of printed \n\
1010 # entries using the MaxPrintSelfiles option (-1 = no limit, 0 = auto (never\n\
1011 # print more than half terminal height), or any custom value)\n\
1012 PrintSelfiles=%s\n\
1013 MaxPrintSelfiles=%d\n\n"
1014
1015 "# If set to true, clear the screen before listing files\n\
1016 ClearScreen=%s\n\n"
1017
1018 "# If not specified, StartingPath defaults to the current working\n\
1019 # directory.\n\
1020 StartingPath=\n\n"
1021
1022 "# If set to true, start CliFM in the last visited directory (and in the\n\
1023 # last used workspace). This option overrides StartingPath.\n\
1024 RestoreLastPath=%s\n\n"
1025
1026 "# If set to true, the 'r' command executes 'trash' instead of 'rm' to\n\
1027 # prevent accidental deletions.\n\
1028 TrashAsRm=%s\n\n"
1029
1030 "# Set readline editing mode: 0 for vi and 1 for emacs (default).\n\
1031 RlEditMode=%d\n\n",
1032
1033 DEF_CLASSIFY == 1 ? "true" : "false",
1034 DEF_SHARE_SELBOX == 1 ? "true" : "false",
1035 DEFAULT_TERM_CMD,
1036 DEF_SORT,
1037 DEF_SORT_REVERSE == 1 ? "true" : "false",
1038 DEF_TIPS == 1 ? "true" : "false",
1039 DEF_LIST_FOLDERS_FIRST == 1 ? "true" : "false",
1040 DEF_CASE_SENS_LIST == 1 ? "true" : "false",
1041 DEF_CASE_SENS_DIRJUMP == 1 ? "true" : "false",
1042 DEF_CASE_SENS_PATH_COMP == 1 ? "true" : "false",
1043 DEF_CASE_SENS_SEARCH == 1 ? "true" : "false",
1044 DEF_UNICODE == 1 ? "true" : "false",
1045 DEF_PAGER == 1 ? "true" : "false",
1046 DEF_MAX_HIST,
1047 DEF_MAX_DIRHIST,
1048 DEF_MAX_LOG,
1049 DEF_ICONS == 1 ? "true" : "false",
1050 DEF_DISK_USAGE == 1 ? "true" : "false",
1051 DEF_PRINTSEL == 1 ? "true" : "false",
1052 DEF_MAXPRINTSEL,
1053 DEF_CLEAR_SCREEN == 1 ? "true" : "false",
1054 DEF_RESTORE_LAST_PATH == 1 ? "true" : "false",
1055 DEF_TRASRM == 1 ? "true" : "false",
1056 DEF_RL_EDIT_MODE
1057 );
1058
1059 fputs(
1060
1061 "# ALIASES\n\
1062 #alias ls='ls --color=auto -A'\n\n"
1063
1064 "# PROMPT COMMANDS\n\
1065 # Write below the commands you want to be executed before the prompt. Ex:\n\
1066 #promptcmd /usr/share/clifm/plugins/git_status.sh\n\
1067 #promptcmd date | awk '{print $1\", \"$2,$3\", \"$4}'\n\n"
1068
1069 "# AUTOCOMMANDS\n\
1070 # Control CliFM settings on a per directory basis. For more information\n\
1071 # consult the manpage\n\
1072 #autocmd /media/remotes/** lm=1,fc=0\n\
1073 #autocmd ~/important !printf \"Keep your fingers outta here!\n\" && read -n1\n\
1074 #autocmd ~/Downloads !/usr/share/clifm/plugins/fzfnav.sh\n\n",
1075 config_fp);
1076
1077 close_fstream(config_fp, fd);
1078 return EXIT_SUCCESS;
1079 }
1080
1081 static void
create_def_cscheme(void)1082 create_def_cscheme(void)
1083 {
1084 if (!colors_dir)
1085 return;
1086
1087 char *cscheme_file = (char *)xnmalloc(strlen(colors_dir) + 13, sizeof(char));
1088 sprintf(cscheme_file, "%s/default.cfm", colors_dir);
1089
1090 /* If the file already exists, do nothing */
1091 struct stat attr;
1092 if (stat(cscheme_file, &attr) != -1) {
1093 free(cscheme_file);
1094 return;
1095 }
1096
1097 int fd;
1098 FILE *fp = open_fstream_w(cscheme_file, &fd);
1099 if (!fp) {
1100 _err('w', PRINT_PROMPT, "%s: Error creating default color scheme "
1101 "file: %s\n", PROGRAM_NAME, strerror(errno));
1102 free(cscheme_file);
1103 return;
1104 }
1105
1106 fprintf(fp, "# Default color scheme for %s\n\n\
1107 # FiletypeColors defines the color used for file types when listing files,\n\
1108 # just as InterfaceColors defines colors for CliFM's interface and ExtColors\n\
1109 # for file extensions. They all make use of the same format used by the\n\
1110 # LS_COLORS environment variable. Thus, \"di=01;34\" means that (non-empty)\n\
1111 # directories will be listed in bold blue.\n\
1112 # Color codes are traditional ANSI escape sequences less the escape char and\n\
1113 # the final 'm'. 8 bit, 256 colors, and RGB colors are supported.\n\
1114 # A detailed explanation of all these codes can be found in the manpage.\n\n"
1115
1116 "FiletypeColors=\"%s\"\n\n"
1117
1118 "InterfaceColors=\"%s\"\n\n"
1119
1120 "# Same as FiletypeColors, but for file extensions. The format is always\n\
1121 # *.EXT=COLOR\n"
1122 #ifndef _NO_ICONS
1123 "ExtColors=\"%s\"\n\n"
1124
1125 "DirIconsColor=\"00;33\"\n",
1126 #else
1127 "ExtColors=\"%s\"\n\n",
1128 #endif
1129 PROGRAM_NAME,
1130 DEF_FILE_COLORS,
1131 DEF_IFACE_COLORS,
1132 DEF_EXT_COLORS);
1133
1134 close_fstream(fp, fd);
1135 free(cscheme_file);
1136 return;
1137 }
1138
1139 static int
create_remotes_file(void)1140 create_remotes_file(void)
1141 {
1142 if (!remotes_file || !*remotes_file)
1143 return EXIT_FAILURE;
1144
1145 struct stat attr;
1146 if (stat(remotes_file, &attr) == EXIT_SUCCESS)
1147 return EXIT_SUCCESS;
1148
1149 int fd;
1150 FILE *fp = open_fstream_w(remotes_file, &fd);
1151 if (!fp) {
1152 _err('e', PRINT_PROMPT, "%s: '%s': %s\n", PROGRAM_NAME,
1153 remotes_file, strerror(errno));
1154 return EXIT_FAILURE;
1155 }
1156
1157 fprintf(fp, "#####################################\n"
1158 "# Remotes management file for %s #\n"
1159 "#####################################\n\n"
1160 "# Blank and commented lines are omitted\n\n"
1161 "# Example:\n"
1162 "# A name for this remote. It will be used by the 'net' command\n"
1163 "# and will be available for TAB completion\n"
1164 "# [work_smb]\n\n"
1165 "# Comment=My work samba server\n"
1166 "# Mountpoint=/home/user/.config/clifm/mounts/work_smb\n\n"
1167 "# Use %%m as a placeholder for Mountpoint\n"
1168 "# MountCmd=mount.cifs //WORK_IP/shared %%m -o OPTIONS\n"
1169 "# UnmountCmd=umount %%m\n\n"
1170 "# Automatically mount this remote at startup\n"
1171 "# AutoMount=true\n\n"
1172 "# Automatically unmount this remote at exit\n"
1173 "# AutoUnmount=true\n\n", PROGRAM_NAME);
1174
1175 close_fstream(fp, fd);
1176 return EXIT_SUCCESS;
1177 }
1178
1179 static void
create_config_files(void)1180 create_config_files(void)
1181 {
1182 struct stat attr;
1183
1184 /* #############################
1185 * # TRASH DIRS #
1186 * ############################# */
1187 #ifndef _NO_TRASH
1188 if (stat(trash_dir, &attr) == -1) {
1189 char *trash_files = (char *)NULL;
1190 trash_files = (char *)xnmalloc(strlen(trash_dir) + 7, sizeof(char));
1191
1192 sprintf(trash_files, "%s/files", trash_dir);
1193 char *trash_info = (char *)NULL;
1194 trash_info = (char *)xnmalloc(strlen(trash_dir) + 6, sizeof(char));
1195
1196 sprintf(trash_info, "%s/info", trash_dir);
1197 char *cmd[] = {"mkdir", "-p", trash_files, trash_info, NULL};
1198
1199 int ret = launch_execve(cmd, FOREGROUND, E_NOFLAG);
1200 free(trash_files);
1201 free(trash_info);
1202
1203 if (ret != EXIT_SUCCESS) {
1204 trash_ok = 0;
1205 _err('w', PRINT_PROMPT, _("%s: mkdir: '%s': Error creating trash "
1206 "directory. Trash function disabled\n"), PROGRAM_NAME, trash_dir);
1207 }
1208 }
1209
1210 /* If it exists, check it is writable */
1211 else if (access(trash_dir, W_OK) == -1) {
1212 trash_ok = 0;
1213 _err('w', PRINT_PROMPT, _("%s: '%s': Directory not writable. "
1214 "Trash function disabled\n"), PROGRAM_NAME, trash_dir);
1215 }
1216 #endif
1217 /* ####################
1218 * # CONFIG DIR #
1219 * #################### */
1220
1221 /* If the config directory doesn't exist, create it */
1222 /* Use the mkdir(1) to let it handle parent directories */
1223 if (stat(config_dir, &attr) == -1) {
1224 char *tmp_cmd[] = {"mkdir", "-p", config_dir, NULL};
1225 if (launch_execve(tmp_cmd, FOREGROUND, E_NOFLAG) != EXIT_SUCCESS) {
1226 config_ok = 0;
1227 _err('e', PRINT_PROMPT, _("%s: mkdir: '%s': Error creating "
1228 "configuration directory. Bookmarks, commands logs, and "
1229 "command history are disabled. Program messages won't be "
1230 "persistent. Using default options\n"),
1231 PROGRAM_NAME, config_dir);
1232 return;
1233 }
1234 }
1235
1236 /* If it exists, check it is writable */
1237 else if (access(config_dir, W_OK) == -1) {
1238 config_ok = 0;
1239 _err('e', PRINT_PROMPT, _("%s: '%s': Directory not writable. Bookmarks, "
1240 "commands logs, and commands history are disabled. Program messages "
1241 "won't be persistent. Using default options\n"),
1242 PROGRAM_NAME, config_dir);
1243 return;
1244 }
1245
1246 /* #####################
1247 * # CONFIG FILE #
1248 * #####################*/
1249
1250 if (stat(config_file, &attr) == -1) {
1251 if (create_config(config_file) == EXIT_SUCCESS)
1252 config_ok = 1;
1253 else
1254 config_ok = 0;
1255 }
1256
1257 if (!config_ok)
1258 return;
1259
1260 /* ######################
1261 * # PROFILE FILE #
1262 * ###################### */
1263
1264 if (stat(profile_file, &attr) == -1) {
1265 FILE *profile_fp = fopen(profile_file, "w");
1266 if (!profile_fp) {
1267 _err('e', PRINT_PROMPT, "%s: fopen: '%s': %s\n", PROGRAM_NAME,
1268 profile_file, strerror(errno));
1269 } else {
1270 fprintf(profile_fp, _("#%s profile\n\
1271 # Write here the commands you want to be executed at startup\n\
1272 # Ex:\n#echo -e \"%s, the anti-eye-candy/KISS file manager\"\n"),
1273 PROGRAM_NAME, PROGRAM_NAME);
1274 fclose(profile_fp);
1275 }
1276 }
1277
1278 /* #####################
1279 * # COLORS DIR #
1280 * ##################### */
1281
1282 if (stat(colors_dir, &attr) == -1) {
1283 /* char *cmd[] = {"mkdir", colors_dir, NULL};
1284 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) != EXIT_SUCCESS) { */
1285 if (xmkdir(colors_dir, S_IRWXU) == EXIT_FAILURE) {
1286 _err('w', PRINT_PROMPT, _("%s: mkdir: Error creating colors "
1287 "directory. Using the default color scheme\n"),
1288 PROGRAM_NAME);
1289 }
1290 }
1291
1292 /* Generate the default color scheme file */
1293 create_def_cscheme();
1294
1295 /* #####################
1296 * # PLUGINS #
1297 * #####################*/
1298
1299 if (stat(plugins_dir, &attr) == -1) {
1300 /* char *cmd[] = {"mkdir", plugins_dir, NULL};
1301 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) != EXIT_SUCCESS) { */
1302 if (xmkdir(plugins_dir, S_IRWXU) == EXIT_FAILURE) {
1303 _err('e', PRINT_PROMPT, _("%s: mkdir: Error creating plugins "
1304 "directory. The actions function is disabled\n"),
1305 PROGRAM_NAME);
1306 }
1307 }
1308
1309 import_rl_file();
1310 create_actions_file(actions_file);
1311 create_mime_file(mime_file, 0);
1312 create_remotes_file();
1313 }
1314
1315 int
create_mime_file(char * file,int new_prof)1316 create_mime_file(char *file, int new_prof)
1317 {
1318 struct stat attr;
1319 if (stat(file, &attr) == EXIT_SUCCESS)
1320 return EXIT_SUCCESS;
1321
1322 if (!data_dir)
1323 return EXIT_FAILURE;
1324
1325 char sys_mimelist[PATH_MAX];
1326 snprintf(sys_mimelist, PATH_MAX - 1, "%s/%s/mimelist.cfm", data_dir, PNL);
1327
1328 if (stat(sys_mimelist, &attr) == -1) {
1329 _err('e', PRINT_PROMPT, "%s: %s: %s\n", PROGRAM_NAME,
1330 sys_mimelist, strerror(errno));
1331 return EXIT_FAILURE;
1332 }
1333
1334 char *cmd[] = {"cp", "-f", sys_mimelist, file, NULL};
1335 if (launch_execve(cmd, FOREGROUND, E_NOFLAG) == EXIT_SUCCESS) {
1336 if (!new_prof) {
1337 _err('n', PRINT_PROMPT, _("%s created a new MIME list file (%s) "
1338 "It is recommended to edit this file (entering 'mm edit' or "
1339 "pressing F6) to add the programs you use and remove those "
1340 "you don't. This will make the process of opening files "
1341 "faster and smoother\n"),
1342 PROGRAM_NAME, file, sys_mimelist);
1343 }
1344 return EXIT_SUCCESS;
1345 }
1346
1347 return EXIT_FAILURE;
1348 }
1349
1350 int
create_bm_file(void)1351 create_bm_file(void)
1352 {
1353 if (!bm_file)
1354 return EXIT_FAILURE;
1355
1356 struct stat file_attrib;
1357 if (stat(bm_file, &file_attrib) == -1) {
1358 FILE *fp = fopen(bm_file, "w+");
1359 if (!fp) {
1360 _err('e', PRINT_PROMPT, "bookmarks: '%s': %s\n", bm_file,
1361 strerror(errno));
1362 return EXIT_FAILURE;
1363 } else {
1364 fprintf(fp, "### This is the bookmarks file for %s ###\n\n"
1365 "# Empty and commented lines are ommited\n"
1366 "# The bookmarks syntax is: [shortcut]name:path\n"
1367 "# Example:\n"
1368 "[c]clifm:%s\n",
1369 PROGRAM_NAME, config_dir ? config_dir : "path/to/file");
1370 fclose(fp);
1371 }
1372 }
1373
1374 return EXIT_SUCCESS;
1375 }
1376
1377 static char *
get_line_value(char * line)1378 get_line_value(char *line)
1379 {
1380 char *opt = strchr(line, '=');
1381 if (!opt || !*opt || !*(++opt) )
1382 return (char *)NULL;
1383
1384 return remove_quotes(opt);
1385 }
1386
1387 static void
read_config(void)1388 read_config(void)
1389 {
1390 int ret = -1;
1391
1392 int fd;
1393 FILE *config_fp = open_fstream_r(config_file, &fd);
1394 if (!config_fp) {
1395 _err('e', PRINT_PROMPT, _("%s: fopen: '%s': %s. Using default values.\n"),
1396 PROGRAM_NAME, config_file, strerror(errno));
1397 return;
1398 }
1399
1400 if (xargs.rl_vi_mode == 1)
1401 rl_vi_editing_mode(1, 0);
1402
1403 max_name_len = UNSET;
1404
1405 *div_line_char = '\0';
1406 #define MAX_BOOL 6 /* false (5) + 1 */
1407 /* starting path(14) + PATH_MAX + \n(1)*/
1408 char line[PATH_MAX + 15];
1409
1410 while (fgets(line, (int)sizeof(line), config_fp)) {
1411
1412 if (*line == '\n' || *line == '#')
1413 continue;
1414 /* if (*line == '\n' || (*line == '#' && line[1] != 'E'))
1415 continue;
1416 if (*line == '#' && strncmp(line, "#END OF OPTIONS", 15) == 0)
1417 break; */
1418
1419 else if (*line == 'a' && strncmp(line, "autocmd ", 8) == 0)
1420 parse_autocmd_line(line + 8);
1421
1422 else if (xargs.autocd == UNSET && *line == 'A'
1423 && strncmp(line, "Autocd=", 7) == 0) {
1424 char opt_str[MAX_BOOL] = "";
1425 ret = sscanf(line, "Autocd=%5s\n", opt_str);
1426 if (ret == -1)
1427 continue;
1428 if (strncmp(opt_str, "true", 4) == 0)
1429 autocd = 1;
1430 else if (strncmp(opt_str, "false", 5) == 0)
1431 autocd = 0;
1432 }
1433
1434 else if (xargs.autojump == UNSET && *line == 'A'
1435 && strncmp(line, "AutoJump=", 9) == 0) {
1436 char opt_str[MAX_BOOL] = "";
1437 ret = sscanf(line, "AutoJump=%5s\n", opt_str);
1438 if (ret == -1)
1439 continue;
1440 if (strncmp(opt_str, "true", 4) == 0)
1441 autojump = autocd = 1;
1442 else if (strncmp(opt_str, "false", 5) == 0)
1443 autojump = 0;
1444 }
1445
1446 else if (xargs.auto_open == UNSET && *line == 'A'
1447 && strncmp(line, "AutoOpen=", 9) == 0) {
1448 char opt_str[MAX_BOOL] = "";
1449 ret = sscanf(line, "AutoOpen=%5s\n", opt_str);
1450 if (ret == -1)
1451 continue;
1452 if (strncmp(opt_str, "true", 4) == 0)
1453 auto_open = 1;
1454 else if (strncmp(opt_str, "false", 5) == 0)
1455 auto_open = 0;
1456 }
1457
1458 #ifndef _NO_SUGGESTIONS
1459 else if (xargs.suggestions == UNSET && *line == 'A'
1460 && strncmp(line, "AutoSuggestions=", 16) == 0) {
1461 char opt_str[MAX_BOOL] = "";
1462 ret = sscanf(line, "AutoSuggestions=%5s\n", opt_str);
1463 if (ret == -1)
1464 continue;
1465 if (strncmp(opt_str, "true", 4) == 0)
1466 suggestions = 1;
1467 else if (strncmp(opt_str, "false", 5) == 0)
1468 suggestions = 0;
1469 }
1470 #endif
1471
1472 else if (xargs.case_sens_dirjump == UNSET && *line == 'C'
1473 && strncmp(line, "CaseSensitiveDirJump=", 21) == 0) {
1474 char opt_str[MAX_BOOL] = "";
1475 ret = sscanf(line, "CaseSensitiveDirJump=%5s\n", opt_str);
1476
1477 if (ret == -1)
1478 continue;
1479
1480 if (strncmp(opt_str, "true", 4) == 0)
1481 case_sens_dirjump = 1;
1482 else if (strncmp(opt_str, "false", 5) == 0)
1483 case_sens_dirjump = 0;
1484 }
1485
1486 else if (*line == 'C'
1487 && strncmp(line, "CaseSensitiveSearch=", 20) == 0) {
1488 char opt_str[MAX_BOOL] = "";
1489 ret = sscanf(line, "CaseSensitiveSearch=%5s\n", opt_str);
1490
1491 if (ret == -1)
1492 continue;
1493
1494 if (strncmp(opt_str, "true", 4) == 0)
1495 case_sens_search = 1;
1496 else if (strncmp(opt_str, "false", 5) == 0)
1497 case_sens_search = 0;
1498 }
1499
1500 else if (xargs.sensitive == UNSET && *line == 'C'
1501 && strncmp(line, "CaseSensitiveList=", 18) == 0) {
1502 char opt_str[MAX_BOOL] = "";
1503 ret = sscanf(line, "CaseSensitiveList=%5s\n",
1504 opt_str);
1505 if (ret == -1)
1506 continue;
1507 if (strncmp(opt_str, "true", 4) == 0)
1508 case_sensitive = 1;
1509 else if (strncmp(opt_str, "false", 5) == 0)
1510 case_sensitive = 0;
1511 }
1512
1513 else if (xargs.case_sens_path_comp == UNSET && *line == 'C'
1514 && strncmp(line, "CaseSensitivePathComp=", 22) == 0) {
1515 char opt_str[MAX_BOOL] = "";
1516 ret = sscanf(line, "CaseSensitivePathComp=%5s\n", opt_str);
1517 if (ret == -1)
1518 continue;
1519 if (strncmp(opt_str, "true", 4) == 0)
1520 case_sens_path_comp = 1;
1521 else if (strncmp(opt_str, "false", 5) == 0)
1522 case_sens_path_comp = 0;
1523 }
1524
1525 else if (xargs.autols == UNSET && *line == 'A'
1526 && strncmp(line, "AutoLs=", 7) == 0) {
1527 char opt_str[MAX_BOOL] = "";
1528 ret = sscanf(line, "AutoLs=%5s\n",
1529 opt_str);
1530 if (ret == -1)
1531 continue;
1532 if (strncmp(opt_str, "true", 4) == 0)
1533 autols = 1;
1534 else if (strncmp(opt_str, "false", 5) == 0)
1535 autols = 0;
1536 }
1537
1538 else if (xargs.cd_on_quit == UNSET && *line == 'C'
1539 && strncmp(line, "CdOnQuit=", 9) == 0) {
1540 char opt_str[MAX_BOOL] = "";
1541 ret = sscanf(line, "CdOnQuit=%5s\n", opt_str);
1542 if (ret == -1)
1543 continue;
1544 if (strncmp(opt_str, "true", 4) == 0)
1545 cd_on_quit = 1;
1546 else if (strncmp(opt_str, "false", 5) == 0)
1547 cd_on_quit = 0;
1548 }
1549
1550 else if (xargs.classify == UNSET && *line == 'C'
1551 && strncmp(line, "Classify=", 9) == 0) {
1552 char opt_str[MAX_BOOL] = "";
1553 ret = sscanf(line, "Classify=%5s\n", opt_str);
1554 if (ret == -1)
1555 continue;
1556 if (strncmp(opt_str, "true", 4) == 0)
1557 classify = 1;
1558 else if (strncmp(opt_str, "false", 5) == 0)
1559 classify = 0;
1560 }
1561
1562 else if (xargs.clear_screen == UNSET && *line == 'C'
1563 && strncmp(line, "ClearScreen=", 12) == 0) {
1564 char opt_str[MAX_BOOL] = "";
1565 ret = sscanf(line, "ClearScreen=%5s\n",
1566 opt_str);
1567 if (ret == -1)
1568 continue;
1569 if (strncmp(opt_str, "true", 4) == 0)
1570 clear_screen = 1;
1571 else if (strncmp(opt_str, "false", 5) == 0)
1572 clear_screen = 0;
1573 }
1574
1575 else if (!usr_cscheme && *line == 'C' && strncmp(line, "ColorScheme=", 12) == 0) {
1576 char *opt = strchr(line, '=');
1577 if (!opt)
1578 continue;
1579
1580 size_t len = strlen(opt);
1581 if (opt[len - 1] == '\n')
1582 opt[len - 1] = '\0';
1583
1584 if (!*(++opt))
1585 continue;
1586
1587 usr_cscheme = savestring(opt, len);
1588 }
1589
1590 else if (*line == 'c' && strncmp(line, "cpCmd=", 6) == 0) {
1591 int opt_num = 0;
1592 ret = sscanf(line, "cpCmd=%d\n", &opt_num);
1593 if (ret == -1)
1594 continue;
1595 if (opt_num >= 0 && opt_num <= 2)
1596 cp_cmd = opt_num;
1597 else /* default (sort by name) */
1598 cp_cmd = DEF_CP_CMD;
1599 }
1600
1601 else if (xargs.dirmap == UNSET && *line == 'D'
1602 && strncmp(line, "DirhistMap=", 11) == 0) {
1603 char opt_str[MAX_BOOL] = "";
1604 ret = sscanf(line, "DirhistMap=%5s\n", opt_str);
1605 if (ret == -1)
1606 continue;
1607 if (strncmp(opt_str, "true", 4) == 0)
1608 dirhist_map = 1;
1609 else if (strncmp(opt_str, "false", 5) == 0)
1610 dirhist_map = 0;
1611 }
1612
1613 else if (xargs.disk_usage == UNSET && *line == 'D'
1614 && strncmp(line, "DiskUsage=", 10) == 0) {
1615 char opt_str[MAX_BOOL] = "";
1616 ret = sscanf(line, "DiskUsage=%5s\n", opt_str);
1617 if (ret == -1)
1618 continue;
1619 if (strncmp(opt_str, "true", 4) == 0)
1620 disk_usage = 1;
1621 else if (strncmp(opt_str, "false", 5) == 0)
1622 disk_usage = 0;
1623 }
1624
1625 else if (*line == 'D' && strncmp(line, "DividingLineChar=", 17) == 0) {
1626 char *opt = strchr(line, '=');
1627 if (!opt || !*opt || !*(++opt)) {
1628 div_line_char[0] = '\0';
1629 } else {
1630 char *tmp = remove_quotes(opt);
1631 if (tmp)
1632 xstrsncpy(div_line_char, tmp, NAME_MAX);
1633 else
1634 div_line_char[0] = '\0';
1635 }
1636 }
1637
1638 else if (*line == 'E' && strncmp(line, "ELNPad=", 7) == 0) {
1639 char *opt = strchr(line, '=');
1640 if (!opt || !*opt || !*(++opt)) {
1641 elnpad = DEF_ELNPAD;
1642 } else {
1643 int ivalue = atoi(opt);
1644 switch(ivalue) {
1645 case NOPAD: elnpad = NOPAD; break;
1646 case ZEROPAD: elnpad = ZEROPAD; break;
1647 case LEFTSPACEPAD: elnpad = LEFTSPACEPAD; break;
1648 case RIGHTSPACEPAD: elnpad = RIGHTSPACEPAD; break;
1649 default: elnpad = DEF_ELNPAD;
1650 }
1651 }
1652 }
1653
1654 else if (xargs.expand_bookmarks == UNSET && *line == 'E'
1655 && strncmp(line, "ExpandBookmarks=", 16) == 0) {
1656 char opt_str[MAX_BOOL] = "";
1657 ret = sscanf(line, "ExpandBookmarks=%5s\n",
1658 opt_str);
1659 if (ret == -1)
1660 continue;
1661 if (strncmp(opt_str, "true", 4) == 0)
1662 expand_bookmarks = 1;
1663 else if (strncmp(opt_str, "false", 5) == 0)
1664 expand_bookmarks = 0;
1665 }
1666
1667 else if (xargs.ext == UNSET && *line == 'E'
1668 && strncmp(line, "ExternalCommands=", 17) == 0) {
1669 char opt_str[MAX_BOOL] = "";
1670 ret = sscanf(line, "ExternalCommands=%5s\n",
1671 opt_str);
1672 if (ret == -1)
1673 continue;
1674 if (strncmp(opt_str, "true", 4) == 0)
1675 ext_cmd_ok = 1;
1676 else if (strncmp(opt_str, "false", 5) == 0)
1677 ext_cmd_ok = 0;
1678 }
1679
1680 else if (xargs.files_counter == UNSET && *line == 'F'
1681 && strncmp(line, "FilesCounter=", 13) == 0) {
1682 char opt_str[MAX_BOOL] = "";
1683 ret = sscanf(line, "FilesCounter=%5s\n", opt_str);
1684 if (ret == -1)
1685 continue;
1686 if (strncmp(opt_str, "true", 4) == 0)
1687 files_counter = 1;
1688 else if (strncmp(opt_str, "false", 5) == 0)
1689 files_counter = 0;
1690 }
1691
1692 else if (!_filter && *line == 'F' && strncmp(line, "Filter=", 7) == 0) {
1693 char *opt_str = strchr(line, '=');
1694 if (!opt_str)
1695 continue;
1696 size_t len = strlen(opt_str);
1697 if (opt_str[len - 1] == '\n')
1698 opt_str[len - 1] = '\0';
1699
1700 if (!*(++opt_str))
1701 continue;
1702
1703 if (*opt_str == '!') {
1704 filter_rev = 1;
1705 opt_str++;
1706 len--;
1707 } else {
1708 filter_rev = 0;
1709 }
1710
1711 _filter = savestring(opt_str, len);
1712 }
1713
1714 #ifndef _NO_HIGHLIGHT
1715 else if (xargs.highlight == UNSET && *line == 'S'
1716 && strncmp(line, "SyntaxHighlighting=", 19) == 0) {
1717 char opt_str[MAX_BOOL] = "";
1718 ret = sscanf(line, "SyntaxHighlighting=%5s\n", opt_str);
1719 if (ret == -1)
1720 continue;
1721 if (strncmp(opt_str, "true", 4) == 0)
1722 highlight = 1;
1723 else if (strncmp(opt_str, "false", 5) == 0)
1724 highlight = 0;
1725 }
1726 #endif /* !_NO_HIGHLIGHT */
1727
1728 #ifndef _NO_ICONS
1729 else if (xargs.icons == UNSET && *line == 'I'
1730 && strncmp(line, "Icons=", 6) == 0) {
1731 char opt_str[MAX_BOOL] = "";
1732 ret = sscanf(line, "Icons=%5s\n", opt_str);
1733 if (ret == -1)
1734 continue;
1735 if (strncmp(opt_str, "true", 4) == 0)
1736 icons = 1;
1737 else if (strncmp(opt_str, "false", 5) == 0)
1738 icons = 0;
1739 }
1740 #endif /* !_NO_ICONS */
1741
1742 else if (xargs.light == UNSET && *line == 'L'
1743 && strncmp(line, "LightMode=", 10) == 0) {
1744 char opt_str[MAX_BOOL] = "";
1745 ret = sscanf(line, "LightMode=%5s\n", opt_str);
1746 if (ret == -1)
1747 continue;
1748 if (strncmp(opt_str, "true", 4) == 0)
1749 light_mode = 1;
1750 else if (strncmp(opt_str, "false", 5) == 0)
1751 light_mode = 0;
1752 }
1753
1754 else if (xargs.ffirst == UNSET && *line == 'L'
1755 && strncmp(line, "ListFoldersFirst=", 17) == 0) {
1756 char opt_str[MAX_BOOL] = "";
1757 ret = sscanf(line, "ListFoldersFirst=%5s\n",
1758 opt_str);
1759 if (ret == -1)
1760 continue;
1761 if (strncmp(opt_str, "true", 4) == 0)
1762 list_folders_first = 1;
1763 else if (strncmp(opt_str, "false", 5) == 0)
1764 list_folders_first = 0;
1765 }
1766
1767 else if (xargs.horizontal_list == UNSET && *line == 'L'
1768 && strncmp(line, "ListingMode=", 12) == 0) {
1769 char *opt = strchr(line, '=');
1770 if (!opt || !*opt || !*(++opt)) {
1771 listing_mode = DEF_LISTING_MODE;
1772 } else {
1773 int ivalue = atoi(opt);
1774 switch(ivalue) {
1775 case VERTLIST: listing_mode = VERTLIST; break;
1776 case HORLIST: listing_mode = HORLIST; break;
1777 default: listing_mode = DEF_LISTING_MODE;
1778 }
1779 }
1780 }
1781
1782 else if (xargs.longview == UNSET && *line == 'L'
1783 && strncmp(line, "LongViewMode=", 13) == 0) {
1784 char opt_str[MAX_BOOL] = "";
1785 ret = sscanf(line, "LongViewMode=%5s\n",
1786 opt_str);
1787 if (ret == -1)
1788 continue;
1789 if (strncmp(opt_str, "true", 4) == 0)
1790 long_view = 1;
1791 else if (strncmp(opt_str, "false", 5) == 0)
1792 long_view = 0;
1793 }
1794
1795 else if (xargs.logs == UNSET && *line == 'L'
1796 && strncmp(line, "LogCmds=", 8) == 0) {
1797 char opt_str[MAX_BOOL] = "";
1798 ret = sscanf(line, "LogCmds=%5s\n", opt_str);
1799 if (ret == -1)
1800 continue;
1801 if (strncmp(opt_str, "true", 4) == 0)
1802 logs_enabled = 1;
1803 else if (strncmp(opt_str, "false", 5) == 0)
1804 logs_enabled = 0;
1805 }
1806
1807 else if (xargs.max_dirhist == UNSET && *line == 'M'
1808 && strncmp(line, "MaxDirhist=", 11) == 0) {
1809 int opt_num = 0;
1810 ret = sscanf(line, "MaxDirhist=%d\n", &opt_num);
1811 if (ret == -1)
1812 continue;
1813 if (opt_num >= 0)
1814 max_dirhist = opt_num;
1815 else /* default */
1816 max_dirhist = DEF_MAX_DIRHIST;
1817 }
1818
1819 else if (*line == 'M' && strncmp(line, "MaxFilenameLen=", 15) == 0) {
1820 int opt_num = 0;
1821 sscanf(line, "MaxFilenameLen=%d\n", &opt_num);
1822 if (opt_num <= 0)
1823 continue;
1824 max_name_len = opt_num;
1825 }
1826
1827 else if (*line == 'M' && strncmp(line, "MaxHistory=", 11) == 0) {
1828 int opt_num = 0;
1829 sscanf(line, "MaxHistory=%d\n", &opt_num);
1830 if (opt_num <= 0)
1831 continue;
1832 max_hist = opt_num;
1833 }
1834
1835 else if (*line == 'M' && strncmp(line, "MaxJumpTotalRank=", 17) == 0) {
1836 int opt_num = 0;
1837 ret = sscanf(line, "MaxJumpTotalRank=%d\n", &opt_num);
1838 if (ret == -1 || opt_num < INT_MIN || opt_num > INT_MAX)
1839 continue;
1840 max_jump_total_rank = opt_num;
1841 }
1842
1843 else if (*line == 'M' && strncmp(line, "MaxLog=", 7) == 0) {
1844 int opt_num = 0;
1845 sscanf(line, "MaxLog=%d\n", &opt_num);
1846 if (opt_num <= 0)
1847 continue;
1848 max_log = opt_num;
1849 }
1850
1851 else if (xargs.max_path == UNSET && *line == 'M'
1852 && strncmp(line, "MaxPath=", 8) == 0) {
1853 int opt_num = 0;
1854 sscanf(line, "MaxPath=%d\n", &opt_num);
1855 if (opt_num <= 0)
1856 continue;
1857 max_path = opt_num;
1858 }
1859
1860 else if (*line == 'M' && strncmp(line, "MaxPrintSelfiles=", 17) == 0) {
1861 int opt_num = 0;
1862 ret = sscanf(line, "MaxPrintSelfiles=%d\n", &opt_num);
1863 if (ret == -1)
1864 continue;
1865 max_printselfiles = opt_num;
1866 }
1867
1868 else if (*line == 'M' && strncmp(line, "MinFilenameTrim=", 16) == 0) {
1869 int opt_num = 0;
1870 ret = sscanf(line, "MinFilenameTrim=%d\n", &opt_num);
1871 if (ret == -1)
1872 continue;
1873 if (opt_num > 0)
1874 min_name_trim = opt_num;
1875 else /* default */
1876 min_name_trim = DEF_MIN_NAME_TRIM;
1877 }
1878
1879 else if (*line == 'M' && strncmp(line, "MinJumpRank=", 12) == 0) {
1880 int opt_num = 0;
1881 ret = sscanf(line, "MinJumpRank=%d\n", &opt_num);
1882 if (ret == -1 || opt_num < INT_MIN || opt_num > INT_MAX)
1883 continue;
1884 min_jump_rank = opt_num;
1885 }
1886
1887 else if (*line == 'm' && strncmp(line, "mvCmd=", 6) == 0) {
1888 int opt_num = 0;
1889 ret = sscanf(line, "mvCmd=%d\n", &opt_num);
1890 if (ret == -1)
1891 continue;
1892 if (opt_num == 0 || opt_num == 1)
1893 mv_cmd = opt_num;
1894 else /* default (sort by name) */
1895 mv_cmd = DEF_MV_CMD;
1896 }
1897
1898 else if (!opener && *line == 'O' && strncmp(line, "Opener=", 7) == 0) {
1899 char *tmp = get_line_value(line);
1900 if (!tmp)
1901 continue;
1902 opener = savestring(tmp, strlen(tmp));
1903 }
1904
1905 else if (xargs.pager == UNSET && *line == 'P'
1906 && strncmp(line, "Pager=", 6) == 0) {
1907 char opt_str[MAX_BOOL] = "";
1908 ret = sscanf(line, "Pager=%5s\n", opt_str);
1909 if (ret == -1)
1910 continue;
1911 if (strncmp(opt_str, "true", 4) == 0)
1912 pager = 1;
1913 else if (strncmp(opt_str, "false", 5) == 0)
1914 pager = 0;
1915 }
1916
1917 else if (xargs.printsel == UNSET && *line == 'P'
1918 && strncmp(line, "PrintSelfiles=", 14) == 0) {
1919 char opt_str[MAX_BOOL] = "";
1920 ret = sscanf(line, "PrintSelfiles=%5s\n", opt_str);
1921 if (ret == -1)
1922 continue;
1923 if (strncmp(opt_str, "true", 4) == 0)
1924 print_selfiles = 1;
1925 else if (strncmp(opt_str, "false", 5) == 0)
1926 print_selfiles = 0;
1927 }
1928
1929 else if (*line == 'P' && strncmp(line, "Prompt=", 7) == 0) {
1930 if (encoded_prompt)
1931 free(encoded_prompt);
1932 char *p = strchr(line, '=');
1933 if (p && *(++p))
1934 encoded_prompt = savestring(p, strlen(p));
1935 }
1936
1937 else if (*line == 'P' && strncmp(line, "PromptStyle=", 12) == 0) {
1938 char opt_str[8] = "";
1939 ret = sscanf(line, "PromptStyle=%7s\n", opt_str);
1940 if (ret == -1)
1941 continue;
1942 if (strncmp(opt_str, "default", 7) == 0)
1943 prompt_style = DEF_PROMPT_STYLE;
1944 else if (strncmp(opt_str, "custom", 6) == 0)
1945 prompt_style = CUSTOM_PROMPT_STYLE;
1946 else
1947 prompt_style = DEF_PROMPT_STYLE;
1948 }
1949
1950 else if (xargs.restore_last_path == UNSET && *line == 'R'
1951 && strncmp(line, "RestoreLastPath=", 16) == 0) {
1952 char opt_str[MAX_BOOL] = "";
1953 ret = sscanf(line, "RestoreLastPath=%5s\n", opt_str);
1954 if (ret == -1)
1955 continue;
1956 if (strncmp(opt_str, "true", 4) == 0)
1957 restore_last_path = 1;
1958 else if (strncmp(opt_str, "false", 5) == 0)
1959 restore_last_path = 0;
1960 }
1961
1962 else if (*line == 'R' && strncmp(line, "RlEditMode=0", 12) == 0) {
1963 rl_vi_editing_mode(1, 0);
1964 /* By default, readline uses emacs editing mode */
1965 }
1966
1967 else if (xargs.share_selbox == UNSET && *line == 'S'
1968 && strncmp(line, "ShareSelbox=", 12) == 0) {
1969 char opt_str[MAX_BOOL] = "";
1970 ret = sscanf(line, "ShareSelbox=%5s\n", opt_str);
1971 if (ret == -1)
1972 continue;
1973 if (strncmp(opt_str, "true", 4) == 0)
1974 share_selbox = 1;
1975 else if (strncmp(opt_str, "false", 5) == 0)
1976 share_selbox = 0;
1977 }
1978
1979 else if (xargs.hidden == UNSET && *line == 'S'
1980 && strncmp(line, "ShowHiddenFiles=", 16) == 0) {
1981 char opt_str[MAX_BOOL] = "";
1982 ret = sscanf(line, "ShowHiddenFiles=%5s\n",
1983 opt_str);
1984 if (ret == -1)
1985 continue;
1986 if (strncmp(opt_str, "true", 4) == 0)
1987 show_hidden = 1;
1988 else if (strncmp(opt_str, "false", 5) == 0)
1989 show_hidden = 0;
1990 }
1991
1992 else if (xargs.sort == UNSET && *line == 'S' && strncmp(line, "Sort=", 5) == 0) {
1993 int opt_num = 0;
1994 ret = sscanf(line, "Sort=%d\n", &opt_num);
1995 if (ret == -1)
1996 continue;
1997 if (opt_num >= 0 && opt_num <= SORT_TYPES)
1998 sort = opt_num;
1999 else /* default (sort by name) */
2000 sort = DEF_SORT;
2001 }
2002
2003 else if (xargs.sort_reverse == UNSET && *line == 'S'
2004 && strncmp(line, "SortReverse=", 12) == 0) {
2005 char opt_str[MAX_BOOL] = "";
2006 ret = sscanf(line, "SortReverse=%5s\n", opt_str);
2007 if (ret == -1)
2008 continue;
2009 if (strncmp(opt_str, "true", 4) == 0)
2010 sort_reverse = 1;
2011 else if (strncmp(opt_str, "false", 5) == 0)
2012 sort_reverse = 0;
2013 }
2014
2015 /* Check for the xargs.splash flag. If -1, it was
2016 * not set via command line, so that it must be
2017 * set here */
2018 else if (xargs.splash == UNSET && *line == 'S'
2019 && strncmp(line, "SplashScreen=", 13) == 0) {
2020 char opt_str[MAX_BOOL] = "";
2021 ret = sscanf(line, "SplashScreen=%5s\n", opt_str);
2022 /* According to cppcheck: "sscanf() without field
2023 * width limits can crash with huge input data".
2024 * Field width limits = %5s */
2025 if (ret == -1)
2026 continue;
2027
2028 if (strncmp(opt_str, "true", 4) == 0)
2029 splash_screen = 1;
2030 else if (strncmp(opt_str, "false", 5) == 0)
2031 splash_screen = 0;
2032 }
2033
2034 else if (xargs.path == UNSET && cur_ws == UNSET && *line == 'S'
2035 && strncmp(line, "StartingPath=", 13) == 0) {
2036 char *tmp = get_line_value(line);
2037 if (!tmp)
2038 continue;
2039
2040 /* If starting path is not NULL, and exists, and is a
2041 * directory, and the user has appropriate permissions,
2042 * set path to starting path. If any of these conditions
2043 * is false, path will be set to default, that is, CWD */
2044 if (xchdir(tmp, SET_TITLE) == 0) {
2045 if (cur_ws < 0)
2046 cur_ws = 0;
2047 free(ws[cur_ws].path);
2048 ws[cur_ws].path = savestring(tmp, strlen(tmp));
2049 } else {
2050 _err('w', PRINT_PROMPT, _("%s: '%s': %s. Using the "
2051 "current working directory as starting path\n"),
2052 PROGRAM_NAME, tmp, strerror(errno));
2053 }
2054 }
2055
2056 #ifndef _NO_SUGGESTIONS
2057 else if (*line == 'S' && strncmp(line, "SuggestFiletypeColor=", 21) == 0) {
2058 char opt_str[MAX_BOOL] = "";
2059 ret = sscanf(line, "SuggestFiletypeColor=%5s\n", opt_str);
2060 if (ret == -1)
2061 continue;
2062 if (strncmp(opt_str, "true", 4) == 0)
2063 suggest_filetype_color = 1;
2064 else if (strncmp(opt_str, "false", 5) == 0)
2065 suggest_filetype_color = 0;
2066 }
2067
2068 else if (*line == 'S'
2069 && strncmp(line, "SuggestionStrategy=", 19) == 0) {
2070 char opt_str[SUG_STRATS + 1] = "";
2071 ret = sscanf(line, "SuggestionStrategy=%7s\n", opt_str);
2072 if (ret == -1)
2073 continue;
2074 int fail = 0;
2075 size_t s = 0;
2076 for (; opt_str[s]; s++) {
2077 if (opt_str[s] != 'a' && opt_str[s] != 'b'
2078 && opt_str[s] != 'c' && opt_str[s] != 'e'
2079 && opt_str[s] != 'f' && opt_str[s] != 'h'
2080 && opt_str[s] != 'j' && opt_str[s] != '-') {
2081 fail = 1;
2082 break;
2083 }
2084 }
2085 if (fail || s != SUG_STRATS)
2086 continue;
2087 suggestion_strategy = savestring(opt_str, strlen(opt_str));
2088 }
2089 #endif /* !_NO_SUGGESTIONS */
2090
2091 else if (xargs.fzftab == UNSET && *line == 'T'
2092 && strncmp(line, "TabCompletionMode=", 18) == 0) {
2093 char opt_str[9] = "";
2094 ret = sscanf(line, "TabCompletionMode=%8s\n", opt_str);
2095 if (ret == -1)
2096 continue;
2097 if (strncmp(opt_str, "standard", 8) == 0)
2098 fzftab = 0;
2099 else if (strncmp(opt_str, "fzf", 3) == 0)
2100 fzftab = 1;
2101 }
2102
2103 else if (*line == 'F' && strncmp(line, "FzfTabOptions=", 14) == 0) {
2104 char *tmp = get_line_value(line);
2105 if (!tmp)
2106 continue;
2107 fzftab_options = savestring(tmp, strlen(tmp));
2108 }
2109
2110 else if (*line == 'T' && strncmp(line, "TerminalCmd=", 12) == 0) {
2111 if (term) {
2112 free(term);
2113 term = (char *)NULL;
2114 }
2115
2116 char *opt = strchr(line, '=');
2117 if (!opt || !*opt || !*(++opt))
2118 continue;
2119
2120 char *tmp = remove_quotes(opt);
2121 if (!tmp)
2122 continue;
2123
2124 term = savestring(tmp, strlen(tmp));
2125 }
2126
2127 else if (xargs.tips == UNSET && *line == 'T' && strncmp(line, "Tips=", 5) == 0) {
2128 char opt_str[MAX_BOOL] = "";
2129 ret = sscanf(line, "Tips=%5s\n", opt_str);
2130 if (ret == -1)
2131 continue;
2132 if (strncmp(opt_str, "false", 5) == 0)
2133 tips = 0;
2134 else if (strncmp(opt_str, "true", 4) == 0)
2135 tips = 1;
2136 }
2137
2138 #ifndef _NO_TRASH
2139 else if (xargs.trasrm == UNSET && *line == 'T'
2140 && strncmp(line, "TrashAsRm=", 10) == 0) {
2141 char opt_str[MAX_BOOL] = "";
2142 ret = sscanf(line, "TrashAsRm=%5s\n", opt_str);
2143 if (ret == -1)
2144 continue;
2145 if (strncmp(opt_str, "true", 4) == 0)
2146 tr_as_rm = 1;
2147 else if (strncmp(opt_str, "false", 5) == 0)
2148 tr_as_rm = 0;
2149 }
2150 #endif
2151
2152 else if (xargs.unicode == UNSET && *line == 'U'
2153 && strncmp(line, "Unicode=", 8) == 0) {
2154 char opt_str[MAX_BOOL] = "";
2155 ret = sscanf(line, "Unicode=%5s\n", opt_str);
2156 if (ret == -1)
2157 continue;
2158 if (strncmp(opt_str, "true", 4) == 0)
2159 unicode = 1;
2160 else if (strncmp(opt_str, "false", 5) == 0)
2161 unicode = 0;
2162 }
2163
2164 else if (xargs.warning_prompt == UNSET && *line == 'W'
2165 && strncmp(line, "WarningPrompt=", 14) == 0) {
2166 char opt_str[MAX_BOOL] = "";
2167 ret = sscanf(line, "WarningPrompt=%5s\n", opt_str);
2168 if (ret == -1)
2169 continue;
2170 if (strncmp(opt_str, "true", 4) == 0)
2171 warning_prompt = 1;
2172 else if (strncmp(opt_str, "false", 5) == 0)
2173 warning_prompt = 0;
2174 }
2175
2176 else if (*line == 'W' && strncmp(line, "WarningPromptStr=", 17) == 0) {
2177 char *tmp = get_line_value(line);
2178 if (!tmp)
2179 continue;
2180 wprompt_str = savestring(tmp, strlen(tmp));
2181 }
2182
2183 else if (xargs.welcome_message == UNSET && *line == 'W'
2184 && strncmp(line, "WelcomeMessage=", 15) == 0) {
2185 char opt_str[MAX_BOOL] = "";
2186 ret = sscanf(line, "WelcomeMessage=%5s\n",
2187 opt_str);
2188 if (ret == -1)
2189 continue;
2190 if (strncmp(opt_str, "true", 4) == 0)
2191 welcome_message = 1;
2192 else if (strncmp(opt_str, "false", 5) == 0)
2193 welcome_message = 0;
2194 }
2195 }
2196
2197 close_fstream(config_fp, fd);
2198
2199 if (_filter) {
2200 ret = regcomp(®ex_exp, _filter, REG_NOSUB | REG_EXTENDED);
2201 if (ret != EXIT_SUCCESS) {
2202 _err('w', PRINT_PROMPT, _("%s: '%s': Invalid regular "
2203 "expression\n"), PROGRAM_NAME, _filter);
2204 free(_filter);
2205 _filter = (char *)NULL;
2206 regfree(®ex_exp);
2207 }
2208 }
2209
2210 return;
2211 }
2212
2213 /* Set up CliFM directories and config files. Load the user's
2214 * configuration from clifmrc */
2215 void
init_config(void)2216 init_config(void)
2217 {
2218 if (xargs.stealth_mode == 1) {
2219 _err(0, PRINT_PROMPT, _("%s: Running in stealth mode: trash, "
2220 "persistent selection and directory history, just as bookmarks, "
2221 "logs and configuration files, are disabled.\n"),
2222 PROGRAM_NAME);
2223 config_ok = 0;
2224 return;
2225 }
2226
2227 /* Store a pointer to the current LS_COLORS value to be used by
2228 * external commands */
2229 ls_colors_bk = getenv("LS_COLORS");
2230
2231 if (!home_ok)
2232 return;
2233
2234 define_config_file_names();
2235 create_config_files();
2236
2237 if (config_ok)
2238 read_config();
2239
2240 cschemes_n = get_colorschemes();
2241 set_colors(usr_cscheme ? usr_cscheme : "default", 1);
2242
2243 if ((flags & GUI) && getenv("XTERM_VERSION")) {
2244 /* If running Xterm, instruct it to send an escape code (27)
2245 * for Meta (Alt) key sequences. Otherwise, Alt keybindings won't
2246 * work */
2247 printf("\x1b[?1036h"); /* metaSendsEscape = true */
2248 /* printf("\x1b[?1034l"); // eightBitInput = false
2249 printf("\x1b[>1;1m"); // modifyCursorKeys = 1
2250 printf("\x1b[>2;1m"); // modifyFunctionKeys = 1
2251 ("\x1b[>1m" and "\x1b[>2m", reset to initial value) */
2252 }
2253 }
2254
2255 static void
reset_variables(void)2256 reset_variables(void)
2257 {
2258 /* Free everything */
2259 free(config_dir_gral);
2260 free(config_dir);
2261 config_dir = config_dir_gral = (char *)NULL;
2262
2263 #ifndef _NO_TRASH
2264 free(trash_dir);
2265 free(trash_files_dir);
2266 free(trash_info_dir);
2267 trash_dir = trash_files_dir = trash_info_dir = (char *)NULL;
2268 #endif
2269
2270 free(bm_file);
2271 free(log_file);
2272 free(hist_file);
2273 free(dirhist_file);
2274 bm_file = log_file = hist_file = dirhist_file = (char *)NULL;
2275
2276 free(config_file);
2277 free(profile_file);
2278 free(msg_log_file);
2279 config_file = profile_file = msg_log_file = (char *)NULL;
2280
2281 free(mime_file);
2282 free(plugins_dir);
2283 free(actions_file);
2284 free(kbinds_file);
2285 mime_file = plugins_dir = actions_file = kbinds_file = (char *)NULL;
2286
2287 free(colors_dir);
2288 free(tmp_dir);
2289 free(sel_file);
2290 free(remotes_file);
2291 tmp_dir = colors_dir = sel_file = remotes_file = (char *)NULL;
2292
2293 #ifndef _NO_SUGGESTIONS
2294 free(suggestion_buf);
2295 suggestion_buf = (char *)NULL;
2296
2297 free(suggestion_strategy);
2298 suggestion_strategy = (char *)NULL;
2299 #endif
2300
2301 free(fzftab_options);
2302 fzftab_options = (char *)NULL;
2303
2304 free(wprompt_str);
2305 wprompt_str = (char *)NULL;
2306
2307 #ifdef AUTOCMDS_TEST
2308 free_autocmds();
2309 #endif
2310
2311 free_remotes(0);
2312
2313 if (_filter) {
2314 regfree(®ex_exp);
2315 free(_filter);
2316 _filter = (char *)NULL;
2317 }
2318
2319 free(opener);
2320 opener = (char *)NULL;
2321
2322 free(encoded_prompt);
2323 encoded_prompt = (char *)NULL;
2324
2325 free(term);
2326 term = (char *)NULL;
2327
2328 int i = (int)cschemes_n;
2329 while (--i >= 0)
2330 free(color_schemes[i]);
2331 free(color_schemes);
2332 color_schemes = (char **)NULL;
2333 cschemes_n = 0;
2334 free(usr_cscheme);
2335 usr_cscheme = (char *)NULL;
2336
2337 free(user.shell);
2338 user.shell = (char *)NULL;
2339
2340 /* Reset all variables */
2341 auto_open = UNSET;
2342 autocd = UNSET;
2343 autojump = UNSET;
2344 autols = UNSET;
2345 case_sens_dirjump = UNSET;
2346 case_sens_path_comp = UNSET;
2347 case_sensitive = UNSET;
2348 case_sens_search = UNSET;
2349 cd_on_quit = UNSET;
2350 check_cap = UNSET;
2351 check_ext = UNSET;
2352 classify = UNSET;
2353 clear_screen = UNSET;
2354 colorize = UNSET;
2355 columned = UNSET;
2356 dirhist_map = UNSET;
2357 disk_usage = UNSET;
2358 elnpad = UNSET;
2359 ext_cmd_ok = UNSET;
2360 files_counter = UNSET;
2361 follow_symlinks = UNSET;
2362 #ifndef _NO_FZF
2363 fzftab = UNSET;
2364 #endif
2365 #ifndef _NO_HIGHLIGHT
2366 highlight = UNSET;
2367 #endif
2368 #ifndef _NO_ICONS
2369 icons = UNSET;
2370 #endif
2371 int_vars = UNSET;
2372 light_mode = UNSET;
2373 list_folders_first = UNSET;
2374 listing_mode = UNSET;
2375 logs_enabled = UNSET;
2376 long_view = UNSET;
2377 max_jump_total_rank = UNSET;
2378 max_printselfiles = UNSET;
2379 min_name_trim = UNSET;
2380 min_jump_rank = UNSET;
2381 no_eln = UNSET;
2382 pager = UNSET;
2383 print_selfiles = UNSET;
2384 prompt_offset = UNSET;
2385 prompt_style = UNSET;
2386 restore_last_path = UNSET;
2387 share_selbox = UNSET;
2388 show_hidden = UNSET;
2389 sort = UNSET;
2390 splash_screen = UNSET;
2391 tips = UNSET;
2392 unicode = UNSET;
2393 warning_prompt = UNSET;
2394 welcome_message = UNSET;
2395
2396 #ifndef _NO_SUGGESTIONS
2397 suggestions = suggest_filetype_color = UNSET;
2398 #endif
2399
2400 #ifndef _NO_TRASH
2401 tr_as_rm = UNSET;
2402 trash_ok = 1;
2403 #endif
2404
2405 dir_changed = 0;
2406 dequoted = 0;
2407 internal_cmd = 0;
2408 is_sel = 0;
2409 kbind_busy = 0;
2410 mime_match = 0;
2411 no_log = 0;
2412 print_msg = 0;
2413 recur_perm_error_flag = 0;
2414 sel_is_last = 0;
2415 shell_is_interactive = 0;
2416 shell_terminal = 0;
2417 sort_reverse = 0;
2418 sort_switch = 0;
2419
2420 config_ok = 1;
2421 home_ok = 1;
2422 selfile_ok = 1;
2423
2424 pmsg = NOMSG;
2425
2426 return;
2427 }
2428
2429 static void
check_cmd_line_options(void)2430 check_cmd_line_options(void)
2431 {
2432 #ifndef _NO_SUGGESTIONS
2433 if (xargs.suggestions != UNSET)
2434 suggestions = xargs.suggestions;
2435 #endif
2436
2437 #ifndef _NO_TRASH
2438 if (xargs.trasrm != UNSET)
2439 tr_as_rm = xargs.trasrm;
2440 #endif
2441
2442 #ifndef _NO_ICONS
2443 if (xargs.icons != UNSET)
2444 icons = xargs.icons;
2445 #endif
2446
2447 if (xargs.auto_open != UNSET)
2448 auto_open = xargs.auto_open;
2449
2450 if (xargs.autocd != UNSET)
2451 autocd = xargs.autocd;
2452
2453 if (xargs.autojump != UNSET)
2454 autojump = xargs.autojump;
2455 if (autojump)
2456 autocd = 1;
2457
2458 if (xargs.case_sens_dirjump != UNSET)
2459 case_sens_dirjump = xargs.case_sens_dirjump;
2460
2461 if (xargs.case_sens_path_comp != UNSET)
2462 case_sens_path_comp = xargs.case_sens_path_comp;
2463
2464 if (xargs.autols != UNSET)
2465 autols = xargs.autols;
2466
2467 if (xargs.cd_on_quit != UNSET)
2468 cd_on_quit = xargs.cd_on_quit;
2469
2470 if (xargs.classify != UNSET)
2471 classify = xargs.classify;
2472
2473 if (xargs.clear_screen != UNSET)
2474 clear_screen = xargs.clear_screen;
2475
2476 if (xargs.dirmap != UNSET)
2477 dirhist_map = xargs.dirmap;
2478
2479 if (xargs.disk_usage != UNSET)
2480 disk_usage = xargs.disk_usage;
2481
2482 if (xargs.expand_bookmarks != UNSET)
2483 expand_bookmarks = xargs.expand_bookmarks;
2484
2485 if (xargs.ext != UNSET)
2486 ext_cmd_ok = xargs.ext;
2487
2488 if (xargs.ffirst != UNSET)
2489 list_folders_first = xargs.ffirst;
2490
2491 if (xargs.files_counter != UNSET)
2492 files_counter = xargs.files_counter;
2493
2494 if (xargs.hidden != UNSET)
2495 show_hidden = xargs.hidden;
2496
2497 if (xargs.light != UNSET)
2498 light_mode = xargs.light;
2499
2500 if (xargs.logs != UNSET)
2501 logs_enabled = xargs.logs;
2502
2503 if (xargs.longview != UNSET)
2504 long_view = xargs.longview;
2505
2506 if (xargs.max_dirhist != UNSET)
2507 max_dirhist = xargs.max_dirhist;
2508
2509 if (xargs.max_path != UNSET)
2510 max_path = xargs.max_path;
2511
2512 if (xargs.colorize != UNSET)
2513 colorize = xargs.colorize;
2514
2515 if (xargs.columns != UNSET)
2516 columned = xargs.columns;
2517
2518 if (xargs.noeln != UNSET)
2519 no_eln = xargs.noeln;
2520
2521 if (xargs.only_dirs != UNSET)
2522 only_dirs = xargs.only_dirs;
2523
2524 if (xargs.pager != UNSET)
2525 pager = xargs.pager;
2526
2527 if (xargs.printsel != UNSET)
2528 print_selfiles = xargs.printsel;
2529
2530 if (xargs.restore_last_path != UNSET)
2531 restore_last_path = xargs.restore_last_path;
2532
2533 if (xargs.sensitive != UNSET)
2534 case_sensitive = xargs.sensitive;
2535
2536 if (xargs.share_selbox != UNSET)
2537 share_selbox = xargs.share_selbox;
2538
2539 if (xargs.sort != UNSET)
2540 sort = xargs.sort;
2541
2542 if (xargs.sort_reverse != UNSET)
2543 sort_reverse = xargs.sort_reverse;
2544
2545 if (xargs.splash != UNSET)
2546 splash_screen = xargs.splash;
2547
2548 if (xargs.tips != UNSET)
2549 tips = xargs.tips;
2550
2551 if (xargs.unicode != UNSET)
2552 unicode = xargs.unicode;
2553
2554 if (xargs.welcome_message != UNSET)
2555 welcome_message = xargs.welcome_message;
2556
2557 return;
2558 }
2559
2560 int
reload_config(void)2561 reload_config(void)
2562 {
2563 reset_variables();
2564
2565 /* Set up config files and options */
2566 init_config();
2567
2568 /* If some option was not set, set it to the default value*/
2569 check_options();
2570 set_sel_file();
2571 create_tmp_files();
2572
2573 /* If some option was set via command line, keep that value
2574 * for any profile */
2575 check_cmd_line_options();
2576
2577 /* Free the aliases and prompt_cmds arrays to be allocated again */
2578 int i = dirhist_total_index;
2579 while (--i >= 0)
2580 free(old_pwd[i]);
2581 free(old_pwd);
2582 old_pwd = (char **)NULL;
2583
2584 if (jump_db) {
2585 for (i = 0; jump_db[i].path; i++)
2586 free(jump_db[i].path);
2587
2588 free(jump_db);
2589 jump_db = (struct jump_t *)NULL;
2590 }
2591 jump_n = 0;
2592
2593 i = (int)aliases_n;
2594 while (--i >= 0) {
2595 free(aliases[i].name);
2596 free(aliases[i].cmd);
2597 }
2598 free(aliases);
2599 aliases = (struct alias_t *)NULL;
2600 aliases_n = 0;
2601
2602 i = (int)prompt_cmds_n;
2603 while (--i >= 0)
2604 free(prompt_cmds[i]);
2605
2606 dirhist_total_index = 0;
2607 prompt_cmds_n = 0;
2608
2609 get_aliases();
2610 get_prompt_cmds();
2611 load_dirhist();
2612 load_jumpdb();
2613 load_remotes();
2614
2615 /* Set the current poistion of the dirhist index to the last
2616 * entry */
2617 dirhist_cur_index = dirhist_total_index - 1;
2618
2619 dir_changed = 1;
2620 set_env();
2621 return EXIT_SUCCESS;
2622 }
2623