nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nano-devel] [PATCH] startup: look for nanorc and history files also in


From: Benno Schulenberg
Subject: [Nano-devel] [PATCH] startup: look for nanorc and history files also in the XDG directories
Date: Wed, 1 Nov 2017 21:13:07 +0100

From: Simon Ochsenreither <address@hidden>

Signed-off-by: Benno Schulenberg <address@hidden>
---
 src/global.c  |  2 ++
 src/history.c | 88 ++++++++++++++++++++++++++++++++---------------------------
 src/nano.c    |  3 +-
 src/proto.h   |  4 ++-
 src/rcfile.c  | 37 +++++++++++++++++++------
 src/utils.c   | 12 ++++++++
 6 files changed, 94 insertions(+), 52 deletions(-)

diff --git a/src/global.c b/src/global.c
index d20d9e45..42bbddcb 100644
--- a/src/global.c
+++ b/src/global.c
@@ -242,6 +242,8 @@ int interface_color_pair[] = {0};
 
 char *homedir = NULL;
        /* The user's home directory, from $HOME or /etc/passwd. */
+char *statedir = NULL;
+       /* The directory for nano's history files. */
 
 
 /* Return the number of entries in the shortcut list for a given menu. */
diff --git a/src/history.c b/src/history.c
index 1a9f1225..97a9b364 100644
--- a/src/history.c
+++ b/src/history.c
@@ -25,6 +25,19 @@
 #include <string.h>
 
 #ifdef ENABLE_HISTORIES
+
+#ifndef XDG_DATA_FALLBACK
+#define XDG_DATA_FALLBACK "/.local/share/nano"
+#endif
+
+#ifndef SEARCH_HISTORY
+#define SEARCH_HISTORY "search_history"
+#endif
+
+#ifndef POSITION_HISTORY
+#define POSITION_HISTORY "filepos_history"
+#endif
+
 static bool history_changed = FALSE;
        /* Whether any of the history lists has changed. */
 
@@ -216,29 +229,6 @@ char *get_history_completion(filestruct **h, char *s, 
size_t len)
 }
 #endif /* ENSABLE_TABCOMP */
 
-/* Return a dynamically-allocated path that is the concatenation of the
- * user's home directory and the given name. */
-char *construct_filename(const char *name)
-{
-    size_t homelen = strlen(homedir);
-    char *joined = charalloc(homelen + strlen(name) + 1);
-
-    strcpy(joined, homedir);
-    strcpy(joined + homelen, name);
-
-    return joined;
-}
-
-char *histfilename(void)
-{
-    return construct_filename("/.nano/search_history");
-}
-
-char *poshistfilename(void)
-{
-    return construct_filename("/.nano/filepos_history");
-}
-
 void history_error(const char *msg, ...)
 {
     va_list ap;
@@ -252,38 +242,56 @@ void history_error(const char *msg, ...)
        ;
 }
 
-/* Check whether the ~/.nano subdirectory for history files exists.  Return
- * TRUE if it exists or was successfully created, and FALSE otherwise. */
-bool have_dotnano(void)
+/* Check whether we have or could make a directory for history files. */
+bool have_statedir(void)
 {
-    bool retval = TRUE;
     struct stat dirstat;
-    char *nanodir = construct_filename("/.nano");
+    char *xdgdatadir;
+
+    get_homedir();
+
+    if (homedir != NULL) {
+       statedir = concatenate(homedir, "/.nano");
+
+       if (stat(statedir, &dirstat) != 0 && S_ISDIR(dirstat.st_mode))
+           return TRUE;
+    }
+
+    free(statedir);
+    xdgdatadir = getenv("XDG_DATA_HOME");
 
-    if (stat(nanodir, &dirstat) == -1) {
-       if (mkdir(nanodir, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+    if (homedir == NULL && xdgdatadir == NULL)
+       return FALSE;
+
+    if (xdgdatadir != NULL) {
+       statedir = concatenate(xdgdatadir, "/nano/");
+       free(xdgdatadir);
+    } else
+       statedir = concatenate(homedir, XDG_DATA_FALLBACK "/");
+
+    if (stat(statedir, &dirstat) == -1) {
+       if (mkdir(statedir, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
            history_error(N_("Unable to create directory %s: %s\n"
                                "It is required for saving/loading "
                                "search history or cursor positions.\n"),
-                               nanodir, strerror(errno));
-           retval = FALSE;
+                               statedir, strerror(errno));
+           return FALSE;
        }
     } else if (!S_ISDIR(dirstat.st_mode)) {
        history_error(N_("Path %s is not a directory and needs to be.\n"
                                "Nano will be unable to load or save "
                                "search history or cursor positions.\n"),
-                               nanodir);
-       retval = FALSE;
+                               statedir);
+       return FALSE;
     }
 
-    free(nanodir);
-    return retval;
+    return TRUE;
 }
 
 /* Load the histories for Search and Replace and Execute Command. */
 void load_history(void)
 {
-    char *histname = histfilename();
+    char *histname = concatenate(statedir, SEARCH_HISTORY);
     FILE *hisfile = fopen(histname, "rb");
 
     if (hisfile == NULL) {
@@ -356,7 +364,7 @@ void save_history(void)
     if (!history_changed)
        return;
 
-    histname = histfilename();
+    histname = concatenate(statedir, SEARCH_HISTORY);
     hisfile = fopen(histname, "wb");
 
     if (hisfile == NULL)
@@ -381,7 +389,7 @@ void save_history(void)
 /* Load the recorded cursor positions for files that were edited. */
 void load_poshistory(void)
 {
-    char *poshist = poshistfilename();
+    char *poshist = concatenate(statedir, POSITION_HISTORY);
     FILE *hisfile = fopen(poshist, "rb");
 
     if (hisfile == NULL) {
@@ -447,7 +455,7 @@ void load_poshistory(void)
 /* Save the recorded cursor positions for files that were edited. */
 void save_poshistory(void)
 {
-    char *poshist = poshistfilename();
+    char *poshist = concatenate(statedir, POSITION_HISTORY);
     poshiststruct *posptr;
     FILE *hisfile = fopen(poshist, "wb");
 
diff --git a/src/nano.c b/src/nano.c
index f4196aac..0cd7c525 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -2363,8 +2363,7 @@ int main(int argc, char **argv)
     /* If we need any of the history files, verify that the user's home
      * directory and its .nano subdirctory exist. */
     if (ISSET(HISTORYLOG) || ISSET(POS_HISTORY)) {
-       get_homedir();
-       if (homedir == NULL || !have_dotnano()) {
+       if (!have_statedir()) {
            UNSET(HISTORYLOG);
            UNSET(POS_HISTORY);
        }
diff --git a/src/proto.h b/src/proto.h
index 9c3c6383..d8a5054d 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -181,6 +181,7 @@ extern char* specified_color_combo[NUMBER_OF_ELEMENTS];
 extern int interface_color_pair[NUMBER_OF_ELEMENTS];
 
 extern char *homedir;
+extern char *statedir;
 
 typedef void (*functionptrtype)(void);
 
@@ -364,7 +365,7 @@ void get_history_newer_void(void);
 #ifdef ENABLE_TABCOMP
 char *get_history_completion(filestruct **h, char *s, size_t len);
 #endif
-bool have_dotnano(void);
+bool have_statedir(void);
 void load_history(void);
 void save_history(void);
 void load_poshistory(void);
@@ -580,6 +581,7 @@ void complete_a_word(void);
 
 /* All functions in utils.c. */
 void get_homedir(void);
+char *concatenate(const char *path, const char *name);
 #ifdef ENABLE_LINENUMBERS
 int digits(ssize_t n);
 #endif
diff --git a/src/rcfile.c b/src/rcfile.c
index bbc0a542..d1307e53 100644
--- a/src/rcfile.c
+++ b/src/rcfile.c
@@ -31,7 +31,7 @@
 #ifdef ENABLE_NANORC
 
 #ifndef RCFILE_NAME
-#define RCFILE_NAME ".nanorc"
+#define RCFILE_NAME "nanorc"
 #endif
 
 static const rcoption rcopts[] = {
@@ -511,11 +511,15 @@ void parse_binding(char *ptr, bool dobind)
     free(keycopy);
 }
 
-/* Verify that the given file is not a folder nor a device. */
+/* Verify that the given file exists, is not a folder nor a device. */
 bool is_good_file(char *file)
 {
     struct stat rcinfo;
 
+    /* First check that the file exists and is readable. */
+    if (access(file, R_OK) != 0)
+       return FALSE;
+
     /* If the thing exists, it may not be a directory nor a device. */
     if (stat(file, &rcinfo) != -1 && (S_ISDIR(rcinfo.st_mode) ||
                S_ISCHR(rcinfo.st_mode) || S_ISBLK(rcinfo.st_mode))) {
@@ -1218,6 +1222,17 @@ void parse_one_nanorc(void)
        rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
 }
 
+bool have_nanorc(char *path, char *name)
+{
+    if (path == NULL)
+       return FALSE;
+
+    free(nanorc);
+    nanorc = concatenate(path, name);
+
+    return is_good_file(nanorc);
+}
+
 /* First read the system-wide rcfile, then the user's rcfile. */
 void do_rcfiles(void)
 {
@@ -1235,18 +1250,22 @@ void do_rcfiles(void)
 
     get_homedir();
 
-    if (homedir == NULL)
-       rcfile_error(N_("I can't find my home directory!  Wah!"));
-    else {
-       nanorc = charealloc(nanorc, strlen(homedir) + strlen(RCFILE_NAME) + 2);
-       sprintf(nanorc, "%s/%s", homedir, RCFILE_NAME);
+    char *xdgconfdir = getenv("XDG_CONFIG_HOME");
 
-       /* Process the current user's nanorc. */
+    /* Now try the to find a nanorc file in the user's home directory
+     * or in the XDG configuration directories. */
+    if (have_nanorc(homedir, "/." RCFILE_NAME))
        parse_one_nanorc();
-    }
+    else if (have_nanorc(xdgconfdir, "/nano/" RCFILE_NAME))
+       parse_one_nanorc();
+    else if (have_nanorc(homedir, "/.config/nano/" RCFILE_NAME))
+       parse_one_nanorc();
+    else if (homedir == NULL && xdgconfdir == NULL)
+       rcfile_error(N_("I can't find my home directory!  Wah!"));
 
     check_vitals_mapped();
 
+    free(xdgconfdir);
     free(nanorc);
 
     if (errors && !ISSET(QUIET) && !ISSET(NO_PAUSES)) {
diff --git a/src/utils.c b/src/utils.c
index 42f12540..530dd2cd 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -53,6 +53,18 @@ void get_homedir(void)
     }
 }
 
+/* Return a copy of the two given strings, welded together. */
+char *concatenate(const char *path, const char *name)
+{
+    size_t pathlen = strlen(path);
+    char *joined = charalloc(pathlen + strlen(name) + 1);
+
+    strcpy(joined, path);
+    strcpy(joined + pathlen, name);
+
+    return joined;
+}
+
 #ifdef ENABLE_LINENUMBERS
 /* Return the number of digits that the given integer n takes up. */
 int digits(ssize_t n)
-- 
2.14.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]