summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/config-parser.c1
-rw-r--r--shared/systemd.c1
-rw-r--r--shared/utils.c176
-rw-r--r--shared/utils.h44
4 files changed, 219 insertions, 3 deletions
diff --git a/shared/config-parser.c b/shared/config-parser.c
index 4dc446c..909c558 100644
--- a/shared/config-parser.c
+++ b/shared/config-parser.c
@@ -14,7 +14,6 @@
#include "config-parser.h"
#include "server-config-options.h"
#include "server-properties-options.h"
-#include "config.h"
static bool handle_addrinfo_results(struct addrinfo *results,
struct list_head *target_list,
diff --git a/shared/systemd.c b/shared/systemd.c
index c45c7c5..4edc055 100644
--- a/shared/systemd.c
+++ b/shared/systemd.c
@@ -7,7 +7,6 @@
#include "utils.h"
#include "config-parser.h"
#include "systemd.h"
-#include "config.h"
static sd_bus *bus = NULL;
static bool bus_failed = false;
diff --git a/shared/utils.c b/shared/utils.c
index 99fcaa3..f41a8a1 100644
--- a/shared/utils.c
+++ b/shared/utils.c
@@ -5,6 +5,7 @@
#include <limits.h>
#include <arpa/inet.h>
#include <string.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
@@ -14,11 +15,156 @@
#include <netinet/tcp.h>
#include <inttypes.h>
#include <stdarg.h>
+#include <pwd.h>
#include "utils.h"
unsigned debug_mask = 0;
+static const char *get_homedir()
+{
+ const char *e;
+ struct passwd *passwd;
+ uid_t uid;
+
+ e = getenv("HOME");
+ if (e && e[0] == '/')
+ return e;
+
+ uid = getuid();
+ if (uid == 0)
+ return "/root";
+
+ passwd = getpwuid(uid);
+ if (passwd && passwd->pw_dir[0] == '/')
+ return passwd->pw_dir;
+
+ return NULL;
+}
+
+int open_subdir(int dfd, const char *subdir, bool nofail)
+{
+ int sfd;
+
+ if (nofail && mkdirat(dfd, subdir, 0777) < 0 && errno != EEXIST) {
+ error("Unable to create subdirectory %s: %m", subdir);
+ return -1;
+ }
+
+ sfd = openat(dfd, subdir, O_PATH | O_CLOEXEC | O_DIRECTORY);
+ if (sfd < 0 && nofail)
+ error("Unable to open subdirectory %s: %m", subdir);
+
+ return sfd;
+}
+
+int open_xdg_dir(const char *envname, const char *altpath, bool nofail,
+ char **rpath)
+{
+ const char *e;
+ const char *h;
+ int dfd, hfd;
+
+ e = getenv(envname);
+ if (e && e[0] == '/') {
+ dfd = open(e, O_PATH | O_CLOEXEC | O_DIRECTORY);
+ if (dfd < 0)
+ error("Unable to open $%s(%s): %m", envname, e);
+ else if (rpath) {
+ *rpath = xstrdup(e);
+ if (!rpath) {
+ error("xstrdup: %m");
+ close(dfd);
+ return -1;
+ }
+ }
+ return dfd;
+ }
+
+ h = get_homedir();
+ if (!h) {
+ error("Unable to determine home directory");
+ return -1;
+ }
+
+ hfd = open(h, O_PATH | O_CLOEXEC | O_DIRECTORY);
+ if (hfd < 0) {
+ error("Unable to open $HOME(%s): %m", h);
+ return -1;
+ }
+
+ dfd = open_subdir(hfd, altpath, nofail);
+ close(hfd);
+
+ if (dfd >= 0 && rpath) {
+ *rpath = xstrcat(h, "/", altpath, NULL);
+ if (!*rpath) {
+ error("xstrcat: %m");
+ close(dfd);
+ return -1;
+ }
+ }
+ return dfd;
+}
+
+DIR *__open_dir(const char *user_override,
+ int (*base_dir)(bool nofail, char **rpath),
+ const char *fallback, char **rpath)
+{
+ _cleanup_close_ int xfd = -1;
+ _cleanup_close_ int mfd = -1;
+ _cleanup_free_ char *tmp = NULL;
+ DIR *dir;
+
+ /* First, use explicitly set path... */
+ if (user_override) {
+ dir = opendir(user_override);
+ if (dir && rpath) {
+ *rpath = xstrdup(user_override);
+ if (!*rpath) {
+ closedir(dir);
+ return NULL;
+ }
+ }
+ return dir;
+ }
+
+ /* ...second, attempt per-user config dir... */
+ xfd = base_dir(false, &tmp);
+ if (xfd < 0)
+ goto fallback;
+
+ mfd = openat(xfd, "minecproxy", O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+ if (mfd < 0)
+ goto fallback;
+
+ dir = fdopendir(mfd);
+ if (dir)
+ mfd = -1;
+
+ if (rpath) {
+ *rpath = xstrcat(tmp, "/minecproxy", NULL);
+ if (!*rpath) {
+ closedir(dir);
+ return NULL;
+ }
+ }
+
+ return dir;
+
+ /* ...third, fallback on the system dir */
+fallback:
+ dir = opendir(fallback);
+ if (dir && rpath) {
+ *rpath = xstrdup(fallback);
+ if (!*rpath) {
+ closedir(dir);
+ return NULL;
+ }
+ }
+ return dir;
+}
+
const char *ansi_red = "";
const char *ansi_green = "";
const char *ansi_yellow = "";
@@ -252,3 +398,33 @@ char *xsprintf(size_t *rlen, const char *fmt, ...)
return str;
}
+
+char *xstrcat(const char *a, ...) {
+ size_t len;
+ const char *b;
+ char *str;
+ char *to;
+ va_list ap;
+
+ if (!a)
+ return NULL;
+
+ len = strlen(a) + 1;
+
+ va_start(ap, a);
+ while ((b = va_arg(ap, const char *)))
+ len += strlen(b);
+ va_end(ap);
+
+ str = zmalloc(len);
+ if (!str)
+ return NULL;
+
+ to = stpcpy(str, a);
+ va_start(ap, a);
+ while ((b = va_arg(ap, const char *)))
+ to = stpcpy(to, b);
+ va_end(ap);
+
+ return str;
+}
diff --git a/shared/utils.h b/shared/utils.h
index 1291d21..b6bf51c 100644
--- a/shared/utils.h
+++ b/shared/utils.h
@@ -8,9 +8,11 @@
#include <stdlib.h>
#include <linux/if_packet.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
+#include <dirent.h>
extern unsigned debug_mask;
@@ -42,6 +44,7 @@ extern unsigned debug_mask;
#include "list.h"
#include "debug.h"
#include "external.h"
+#include "config.h"
#include "ansi-colors.h"
/* Length of longest DNS name = 253 + trailing dot */
@@ -68,6 +71,37 @@ struct saddr {
struct list_head list;
};
+int open_subdir(int dfd, const char *subdir, bool nofail);
+
+int open_xdg_dir(const char *envname, const char *altpath, bool nofail,
+ char **rpath);
+
+static inline int open_xdg_data_dir(bool nofail, char **rpath)
+{
+ return open_xdg_dir("XDG_DATA_HOME", ".local/share", nofail, rpath);
+}
+
+static inline int open_xdg_cfg_dir(bool nofail, char **rpath)
+{
+ return open_xdg_dir("XDG_CONFIG_HOME", ".config", nofail, rpath);
+}
+
+DIR *__open_dir(const char *user_override,
+ int (*base_dir)(bool nofail, char **rpath),
+ const char *fallback, char **rpath);
+
+static inline DIR *open_cfg_dir(const char *user_override, char **rpath)
+{
+ return __open_dir(user_override, open_xdg_cfg_dir, DEFAULT_CFG_DIR,
+ rpath);
+}
+
+static inline DIR *open_data_dir(const char *user_override, char **rpath)
+{
+ return __open_dir(user_override, open_xdg_data_dir, DEFAULT_DATA_DIR,
+ rpath);
+}
+
void enable_colors();
void free_password(char **password);
@@ -91,6 +125,8 @@ int strtou16_strict(const char *str, uint16_t *result);
char *xsprintf(size_t *rlen, const char *fmt, ...) _printf_(2, 3);
+char *xstrcat(const char *a, ...);
+
static inline bool empty_str(const char *str)
{
if (!str || str[0] == '\0')
@@ -136,7 +172,7 @@ static inline bool strcaseeq(const char *a, const char *b)
static inline void closep(int *fd)
{
- if (*fd && *fd >= 0)
+ if (fd && *fd >= 0)
close(*fd);
}
#define _cleanup_close_ _cleanup_(closep)
@@ -146,4 +182,10 @@ static inline void freep(void *p) {
}
#define _cleanup_free_ _cleanup_(freep)
+static inline void fclosep(FILE **f) {
+ if (f && *f)
+ fclose(*f);
+}
+#define _cleanup_fclose_ _cleanup_(fclosep)
+
#endif