Move configuration and cache to XDG dirs
snownews kept configuration in ~/.snownews and the feed cache in ~/.snownews/cache. This commit moves configuration to ~/.config/snownews and the cache to ~/.local/share/snownews, conforming to the XDG basedir specification. snownews will migrate old settings to the new location.
This commit is contained in:
parent
5604d30c00
commit
6d776956ec
|
@ -29,10 +29,6 @@
|
|||
// Define to the value of LOCALEPATH environment variable
|
||||
#define LOCALEPATH "@localepath@"
|
||||
|
||||
// Snownews configuration files directory, starts with %s for $HOME
|
||||
#define SNOWNEWS_CONFIG_DIR "%s/.snownews/"
|
||||
#define SNOWNEWS_CACHE_DIR SNOWNEWS_CONFIG_DIR "cache/"
|
||||
|
||||
// Define to output of uname
|
||||
#undef OS
|
||||
|
||||
|
|
6
dialog.c
6
dialog.c
|
@ -23,6 +23,7 @@
|
|||
#include "feedio.h"
|
||||
#include "uiutil.h"
|
||||
#include "parse.h"
|
||||
#include "setup.h"
|
||||
#include <ncurses.h>
|
||||
|
||||
char* UIOneLineEntryField (int x, int y)
|
||||
|
@ -244,10 +245,11 @@ void FeedInfo (const struct feed* current_feed)
|
|||
free (url);
|
||||
url = NULL;
|
||||
|
||||
char cachefile[PATH_MAX];
|
||||
char* hashme = Hashify (current_feed->feedurl);
|
||||
snprintf (cachefile, sizeof (cachefile), SNOWNEWS_CACHE_DIR "%s", getenv ("HOME"), hashme);
|
||||
char cachefile [PATH_MAX];
|
||||
CacheFilePath (hashme, cachefile, sizeof(cachefile));
|
||||
free (hashme);
|
||||
|
||||
struct stat cachestat;
|
||||
move (9, centerx - (COLS / 2 - 7));
|
||||
if (stat (cachefile, &cachestat) < 0)
|
||||
|
|
11
feedio.c
11
feedio.c
|
@ -21,6 +21,7 @@
|
|||
#include "netio.h"
|
||||
#include "uiutil.h"
|
||||
#include "parse.h"
|
||||
#include "setup.h"
|
||||
#include <ncurses.h>
|
||||
#include <libxml/parser.h>
|
||||
|
||||
|
@ -99,8 +100,8 @@ int LoadFeed (struct feed* cur_ptr)
|
|||
return 0;
|
||||
|
||||
char* hashme = Hashify (cur_ptr->feedurl);
|
||||
char cachefilename[PATH_MAX];
|
||||
snprintf (cachefilename, sizeof (cachefilename), SNOWNEWS_CACHE_DIR "%s", getenv ("HOME"), hashme);
|
||||
char cachefilename [PATH_MAX];
|
||||
CacheFilePath (hashme, cachefilename, sizeof(cachefilename));
|
||||
free (hashme);
|
||||
FILE* cache = fopen (cachefilename, "r");
|
||||
if (cache == NULL) {
|
||||
|
@ -184,7 +185,7 @@ static void WriteFeedUrls (void)
|
|||
|
||||
// Make a backup of urls.
|
||||
char urlsfilename[PATH_MAX];
|
||||
snprintf (urlsfilename, sizeof (urlsfilename), SNOWNEWS_CONFIG_DIR "urls", getenv ("HOME"));
|
||||
ConfigFilePath ("urls", urlsfilename, sizeof(urlsfilename));
|
||||
|
||||
// Write urls
|
||||
FILE* urlfile = fopen (urlsfilename, "w");
|
||||
|
@ -216,8 +217,8 @@ static void WriteFeedUrls (void)
|
|||
static void WriteFeedCache (const struct feed* feed)
|
||||
{
|
||||
char* hashme = Hashify (feed->feedurl);
|
||||
char cachefilename[PATH_MAX];
|
||||
snprintf (cachefilename, sizeof (cachefilename), SNOWNEWS_CACHE_DIR "%s", getenv ("HOME"), hashme);
|
||||
char cachefilename [PATH_MAX];
|
||||
CacheFilePath (hashme, cachefilename, sizeof(cachefilename));
|
||||
free (hashme);
|
||||
|
||||
// Check if the feed has been modified since last loaded from this file
|
||||
|
|
9
main.c
9
main.c
|
@ -96,10 +96,11 @@ enum EPIDAction { pid_file_delete, pid_file_create };
|
|||
static void make_pidfile_name (char* fnbuf, size_t fnbufsz)
|
||||
{
|
||||
const char* rundir = getenv ("XDG_RUNTIME_DIR");
|
||||
if (rundir)
|
||||
snprintf (fnbuf, fnbufsz, "%s/snownews.pid", rundir);
|
||||
else
|
||||
snprintf (fnbuf, fnbufsz, SNOWNEWS_CONFIG_DIR "pid", getenv ("HOME"));
|
||||
if (!rundir)
|
||||
rundir = getenv ("TMPDIR");
|
||||
if (!rundir)
|
||||
rundir = "/tmp";
|
||||
snprintf (fnbuf, fnbufsz, "%s/snownews.pid", rundir);
|
||||
}
|
||||
|
||||
static void modifyPIDFile (enum EPIDAction action)
|
||||
|
|
1
main.h
1
main.h
|
@ -134,7 +134,6 @@ struct settings {
|
|||
struct categories* global_categories;
|
||||
const char* global_charset;
|
||||
char* browser; // Browser command. lynx is standard.
|
||||
char* useragent; // Snownews User-Agent string.
|
||||
char* proxyname; // Hostname of proxyserver.
|
||||
unsigned short proxyport; // Port on proxyserver to use.
|
||||
struct color color;
|
||||
|
|
5
netio.c
5
netio.c
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "netio.h"
|
||||
#include "uiutil.h"
|
||||
#include "setup.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
static size_t FeedReceiver (void* buffer, size_t msz, size_t nm, void* vpfeed)
|
||||
|
@ -81,8 +82,8 @@ void DownloadFeed (const char* url, struct feed* fp)
|
|||
|
||||
// Cookies, if the cookie file is in the config dir
|
||||
char cookiefile [PATH_MAX];
|
||||
unsigned cfnl = snprintf (cookiefile, sizeof(cookiefile), SNOWNEWS_CONFIG_DIR "cookies", getenv("HOME"));
|
||||
if (cfnl < sizeof(cookiefile) && access (cookiefile, R_OK) == 0)
|
||||
ConfigFilePath ("cookies", cookiefile, sizeof(cookiefile));
|
||||
if (access (cookiefile, R_OK) == 0)
|
||||
curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookiefile);
|
||||
|
||||
// Save old content
|
||||
|
|
110
setup.c
110
setup.c
|
@ -23,6 +23,34 @@
|
|||
#include "conv.h"
|
||||
#include <ncurses.h>
|
||||
|
||||
void ConfigFilePath (const char* filename, char* path, size_t pathsz)
|
||||
{
|
||||
const char* confhome = getenv ("XDG_CONFIG_HOME");
|
||||
unsigned pathlen;
|
||||
if (confhome)
|
||||
pathlen = snprintf (path, pathsz, "%s/" SNOWNEWS_NAME "/%s", confhome, filename);
|
||||
else
|
||||
pathlen = snprintf (path, pathsz, "%s/.config/" SNOWNEWS_NAME "/%s", getenv("HOME"), filename);
|
||||
if (pathlen >= pathsz)
|
||||
MainQuit ("ConfigFilePath", "configuration dir path is too long");
|
||||
if (path[pathlen-1] == '/')
|
||||
path[pathlen-1] = 0;
|
||||
}
|
||||
|
||||
void CacheFilePath (const char* filename, char* path, size_t pathsz)
|
||||
{
|
||||
const char* datahome = getenv ("XDG_DATA_HOME");
|
||||
unsigned pathlen;
|
||||
if (datahome)
|
||||
pathlen = snprintf (path, pathsz, "%s/" SNOWNEWS_NAME "/%s", datahome, filename);
|
||||
else
|
||||
pathlen = snprintf (path, pathsz, "%s/.local/share/" SNOWNEWS_NAME "/%s", getenv("HOME"), filename);
|
||||
if (pathlen >= pathsz)
|
||||
MainQuit ("CacheFilePath", "cache dir path is too long");
|
||||
if (path[pathlen-1] == '/')
|
||||
path[pathlen-1] = 0;
|
||||
}
|
||||
|
||||
// Load browser command from ~./snownews/browser.
|
||||
static void SetupBrowser (const char* filename)
|
||||
{
|
||||
|
@ -40,7 +68,7 @@ static void SetupBrowser (const char* filename)
|
|||
void SaveBrowserSetting (void)
|
||||
{
|
||||
char browserfilename[PATH_MAX];
|
||||
snprintf (browserfilename, sizeof (browserfilename), SNOWNEWS_CONFIG_DIR "browser", getenv ("HOME"));
|
||||
ConfigFilePath ("browser", browserfilename, sizeof(browserfilename));
|
||||
FILE* browserfile = fopen (browserfilename, "w");
|
||||
if (!browserfile)
|
||||
MainQuit (_("Save settings (browser)"), strerror (errno));
|
||||
|
@ -71,24 +99,6 @@ static void SetupProxy (void)
|
|||
free (proxystrbase);
|
||||
}
|
||||
|
||||
// Construct the user agent string that snownews sends to the webserver.
|
||||
// This includes Snownews/VERSION, OS name and language setting.
|
||||
static void SetupUserAgent (void)
|
||||
{
|
||||
// Constuct the User-Agent string of snownews. This is done here in program init,
|
||||
// because we need to do it exactly once and it will never change while the program
|
||||
// is running.
|
||||
const char* lang = getenv ("LANG");
|
||||
if (!lang)
|
||||
lang = "C";
|
||||
// Snonews/VERSION (Linux; de_DE; (http://kiza.kcore.de/software/snownews/)
|
||||
static const char url[] = "http://snownews.kcore.de/software/snownews/";
|
||||
const unsigned urllen = strlen (url);
|
||||
unsigned ualen = strlen ("Snownews/" SNOWNEWS_VERSION) + 2 + strlen (lang) + 2 + strlen (OS) + 2 + urllen + 2;
|
||||
_settings.useragent = malloc (ualen);
|
||||
snprintf (_settings.useragent, ualen, "Snownews/" SNOWNEWS_VERSION " (" OS "; %s; %s)", lang, url);
|
||||
}
|
||||
|
||||
// Define global keybindings and load user customized bindings.
|
||||
static void SetupKeybindings (const char* filename)
|
||||
{
|
||||
|
@ -411,6 +421,34 @@ static unsigned SetupFeedList (const char* filename)
|
|||
return numfeeds;
|
||||
}
|
||||
|
||||
// Migrates configuration from ~/.snownews to ~/.config/snownews and ~/.local/share/snownews
|
||||
static void MigrateConfigToXDG (void)
|
||||
{
|
||||
char dirname [PATH_MAX];
|
||||
const char* homedir = getenv ("HOME");
|
||||
if (!homedir)
|
||||
MainQuit ("Reading configuration", "you have no home directory");
|
||||
|
||||
// Migrate cache dir to ~/.local/snownews
|
||||
snprintf (dirname, sizeof(dirname), "%s/.snownews/cache", homedir);
|
||||
struct stat dirtest;
|
||||
if (0 == stat (dirname, &dirtest) && S_ISDIR(dirtest.st_mode)) {
|
||||
char cachedir [PATH_MAX];
|
||||
CacheFilePath ("", cachedir, sizeof(cachedir));
|
||||
if (0 != rename (dirname, cachedir))
|
||||
MainQuit ("Migrating feed cache ~/.snownews/cache to ~/.local/share/snownews", strerror (errno));
|
||||
}
|
||||
|
||||
// Migrate configuration dir to ~/.config/snownews
|
||||
snprintf (dirname, sizeof(dirname), "%s/.snownews", homedir);
|
||||
if (0 == stat (dirname, &dirtest) && S_ISDIR(dirtest.st_mode)) {
|
||||
char configdir [PATH_MAX];
|
||||
ConfigFilePath ("", configdir, sizeof(configdir));
|
||||
if (0 != rename (dirname, configdir))
|
||||
MainQuit ("Migrating configuration ~/.snownews to ~/.config/snownews", strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
// Create snownews' config directories if they do not exist yet,
|
||||
// load global configuration settings and caches.
|
||||
//
|
||||
|
@ -421,43 +459,41 @@ unsigned Config (void)
|
|||
// Set umask to 077 for all created files.
|
||||
umask (0077);
|
||||
|
||||
MigrateConfigToXDG();
|
||||
SetupProxy();
|
||||
SetupUserAgent();
|
||||
|
||||
// Setup config directories.
|
||||
char dirname[PATH_MAX];
|
||||
snprintf (dirname, sizeof (dirname), SNOWNEWS_CONFIG_DIR, getenv ("HOME"));
|
||||
char dirname [PATH_MAX];
|
||||
ConfigFilePath ("", dirname, sizeof(dirname));
|
||||
struct stat dirtest;
|
||||
if (0 > stat (dirname, &dirtest)) {
|
||||
if (0 > mkdir (dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
||||
MainQuit ("Creating config directory " SNOWNEWS_CONFIG_DIR, strerror (errno));
|
||||
if (0 > mkdir (dirname, S_IRWXU))
|
||||
MainQuit (dirname, strerror (errno));
|
||||
} else if (!S_ISDIR (dirtest.st_mode))
|
||||
MainQuit ("Creating config directory " SNOWNEWS_CONFIG_DIR, "A file with the name \"" SNOWNEWS_CONFIG_DIR "\" exists!");
|
||||
MainQuit (dirname, "is a file");
|
||||
|
||||
snprintf (dirname, sizeof (dirname), SNOWNEWS_CACHE_DIR, getenv ("HOME"));
|
||||
CacheFilePath ("", dirname, sizeof(dirname));
|
||||
if (0 > stat (dirname, &dirtest)) {
|
||||
if (0 > mkdir (dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
||||
MainQuit (_("Creating config directory " SNOWNEWS_CACHE_DIR), strerror (errno));
|
||||
if (0 > mkdir (dirname, S_IRWXU))
|
||||
MainQuit (dirname, strerror (errno));
|
||||
} else if (!S_ISDIR (dirtest.st_mode))
|
||||
MainQuit ("Creating config directory " SNOWNEWS_CACHE_DIR, "A file with the name \"" SNOWNEWS_CACHE_DIR "\" exists!");
|
||||
MainQuit (dirname, "is a file");
|
||||
|
||||
UIStatus (_("Reading configuration settings..."), 0, 0);
|
||||
|
||||
char filename[PATH_MAX];
|
||||
snprintf (filename, sizeof (filename), SNOWNEWS_CONFIG_DIR "browser", getenv ("HOME"));
|
||||
ConfigFilePath ("browser", filename, sizeof(filename));
|
||||
SetupBrowser (filename);
|
||||
|
||||
snprintf (filename, sizeof (filename), SNOWNEWS_CONFIG_DIR "urls", getenv ("HOME"));
|
||||
unsigned numfeeds = SetupFeedList (filename);
|
||||
|
||||
snprintf (filename, sizeof (filename), SNOWNEWS_CONFIG_DIR "keybindings", getenv ("HOME"));
|
||||
ConfigFilePath ("keybindings", filename, sizeof(filename));
|
||||
SetupKeybindings (filename);
|
||||
|
||||
snprintf (filename, sizeof (filename), SNOWNEWS_CONFIG_DIR "colors", getenv ("HOME"));
|
||||
ConfigFilePath ("colors", filename, sizeof(filename));
|
||||
SetupColors (filename);
|
||||
|
||||
snprintf (filename, sizeof (filename), SNOWNEWS_CONFIG_DIR "html_entities", getenv ("HOME"));
|
||||
ConfigFilePath ("html_entities", filename, sizeof(filename));
|
||||
SetupEntities (filename);
|
||||
|
||||
return numfeeds;
|
||||
ConfigFilePath ("urls", filename, sizeof(filename));
|
||||
return SetupFeedList (filename);
|
||||
}
|
||||
|
|
3
setup.h
3
setup.h
|
@ -1,6 +1,7 @@
|
|||
// This file is part of Snownews - A lightweight console RSS newsreader
|
||||
//
|
||||
// Copyright (c) 2003-2004 Oliver Feiler <kiza@kcore.de>
|
||||
// Copyright (c) 2021 Mike Sharov <msharov@users.sourceforge.net>
|
||||
//
|
||||
// Snownews is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 3
|
||||
|
@ -19,3 +20,5 @@
|
|||
|
||||
unsigned Config (void);
|
||||
void SaveBrowserSetting (void);
|
||||
void ConfigFilePath (const char* filename, char* path, size_t pathsz);
|
||||
void CacheFilePath (const char* filename, char* path, size_t pathsz);
|
||||
|
|
2
ui.c
2
ui.c
|
@ -1021,7 +1021,7 @@ void UIMainInterface (void)
|
|||
// Remove cachefile from filesystem.
|
||||
char* hashme = Hashify (highlighted->feedurl);
|
||||
char cachefilename[PATH_MAX];
|
||||
snprintf (cachefilename, sizeof (cachefilename), SNOWNEWS_CACHE_DIR "%s", getenv ("HOME"), hashme);
|
||||
CacheFilePath (hashme, cachefilename, sizeof(cachefilename));
|
||||
free (hashme);
|
||||
|
||||
// Errors from unlink can be ignored. Worst thing that happens is that
|
||||
|
|
Loading…
Reference in New Issue