Tools to make secret sharing easier.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

152 lines
3.9 KiB

/*
* xdg - Incenp.org Notch Library: XDG Base Directory implementation
* Copyright (C) 2011 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <xdg.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
enum {
#define XDG_VAR(variable_name, member_name, default_value) \
variable_name,
#include "xdg-vars.h"
#undef XDG_VAR
XDG_MAX_VARS
};
typedef struct {
char *var_name;
char *def_value;
char *value;
size_t len;
size_t offset;
} xdg_var_t;
xdg_t *
xdg_init(void)
{
xdg_t *xdg;
char *home_dir;
size_t home_len, needed;
int offset, i;
xdg_var_t vars[XDG_MAX_VARS + 1] = {
#define XDG_VAR(variable_name, member_name, default_value) \
{ #variable_name, default_value, NULL, 0, offsetof(xdg_t, member_name) },
#include "xdg-vars.h"
#undef XDG_VAR
{ NULL, NULL, NULL, 0, 0 }
};
needed = offset = sizeof(*xdg);
/* Retrieve home directory (needed for some default values). */
if ( ! (home_dir = getenv("HOME")) ) {
struct passwd *pw;
do {
errno = 0;
if ( (pw = getpwuid(getuid())) )
home_dir = pw->pw_dir;
} while ( ! pw && errno == EINTR );
}
home_len = home_dir ? strlen(home_dir) : 0;
/* Retrieve XDG variables and compute the amount of memory
* needed to store everything. */
for ( i = 0; i < XDG_MAX_VARS; i++ ) {
vars[i].value = getenv(vars[i].var_name);
if ( ! vars[i].value || ! vars[i].value[0] ) {
if ( i == XDG_RUNTIME_DIR )
/* XDG Base Directory specification mandates this warning. */
warnx("XDG_RUNTIME_DIR is not set");
vars[i].value = vars[i].def_value;
}
vars[i].len = strlen(vars[i].value);
needed += vars[i].len + 1;
if ( vars[i].value[0] == '~' ) {
if ( ! home_dir ) {
/* We need the home directory, but were unable to get it. */
errno = ENOENT;
return NULL;
}
needed += home_len;
}
}
if ( ! (xdg = malloc(needed)) )
return NULL;
/* Store everything into the xdg_t structure. */
for ( i = 0; i < XDG_MAX_VARS; i++ ) {
/* Left value is the offset of the member in the xdg_t
* structure; right value is the offset of the
* corresponding data in the area after the structure. */
*((char **)((char *)xdg + vars[i].offset)) = (char *)xdg + offset;
/* Replace '~' by home directory. */
if ( vars[i].value[0] == '~' ) {
vars[i].value = &(vars[i].value[1]);
strcpy((char *)xdg + offset, home_dir);
offset += home_len;
}
strcpy((char *)xdg + offset, vars[i].value);
offset += vars[i].len + 1;
}
return xdg;
}
xdg_t *xdg = NULL;
static void
xdg_free(void)
{
if ( xdg )
free(xdg);
}
xdg_t *
xdg_get(int fatal)
{
if ( ! xdg ) {
if ( ! (xdg = xdg_init()) ) {
if ( fatal )
err(EXIT_FAILURE, "Cannot get XDG variables");
return NULL;
}
atexit(xdg_free);
}
return xdg;
}