/* my.c:
*
****************************************************************
* Copyright (C) 2003 Tom Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/os/stdlib.h"
#include "hackerlab/os/errno.h"
#include "hackerlab/os/errno-to-string.h"
#include "hackerlab/bugs/panic.h"
#include "hackerlab/char/str.h"
#include "hackerlab/fs/file-names.h"
#include "hackerlab/fs/cwd.h"
#include "hackerlab/vu/safe.h"
#include "hackerlab/char/pika-escaping-utils.h"
#include "libfsutils/ensure-dir.h"
#include "libfsutils/read-line.h"
#include "libfsutils/file-contents.h"
#include "libawk/trim.h"
#include "libawk/associative.h"
#include "libarch/namespace.h"
#include "libarch/my.h"
#include "libarch/chatter.h"
#include "libarch/arch.h"
static t_uchar * get_cache_path_file(void);
static t_uchar * my_default_cache_path (void);
t_uchar const *
arch_my_arch_params (void)
{
t_uchar * home;
static t_uchar * answer = NULL;
if (answer)
return answer;
home = getenv ("HOME");
invariant (!!home);
answer = file_name_in_vicinity (0, home, ".arch-params");
return answer;
}
void
arch_ensure_my_arch_params (void)
{
int errn;
t_uchar * dir = 0;
if (vu_mkdir (&errn, (t_uchar *)arch_my_arch_params(), 0700) && errn != EEXIST)
{
safe_printfmt (2, "arch: unable to create directory %s\n", dir);
exit (2);
}
}
t_uchar *
arch_my_hook_script (void)
{
t_uchar * hook_script;
hook_script = file_name_in_vicinity (0, arch_my_arch_params(), "hook");
{
int euid;
int egid;
struct stat stat;
int stat_ok;
int errn;
euid = geteuid ();
egid = getegid ();
stat_ok = vu_stat (&errn, hook_script, &stat);
if (stat_ok
|| !(((euid == stat.st_uid) && (stat.st_mode & S_IXUSR))
|| ((egid == stat.st_gid) && (stat.st_mode & S_IXGRP))
|| (stat.st_mode & S_IXOTH)))
{
lim_free (0, hook_script);
hook_script = 0;
}
}
return hook_script;
}
static assoc_table memoised_results = NULL;
#define MYIDKEY "my-id"
#define CACHEPATHKEY "cache-path"
t_uchar *
arch_my_id_file (void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "=id");
}
void
arch_set_my_id (t_uchar * id)
{
t_uchar * id_file;
int out_fd;
invariant (arch_valid_id (id));
id_file = arch_my_id_file ();
arch_ensure_my_arch_params ();
out_fd = safe_open (id_file, O_WRONLY | O_CREAT, 0666);
safe_ftruncate (out_fd, 0L);
safe_printfmt (out_fd, "%s\n", id);
safe_close (out_fd);
lim_free (0, id_file);
assoc_set (&memoised_results, MYIDKEY, id);
}
void
arch_my_id_memoise (t_uchar const * an_id, int const len)
{
t_uchar * temp = str_save_n (0, an_id, len);
assoc_set (&memoised_results, MYIDKEY, temp);
lim_free (0, temp);
}
t_uchar *
arch_my_id_default (t_uchar const *default_id)
{
t_uchar *result = arch_my_id_unsafe ();
if (!result)
{
arch_my_id_memoise (default_id, str_length (default_id));
}
return str_save (0, default_id);
}
/* find the arch id, returning NULL if one cannot be
* found
*/
t_uchar *
arch_my_id_unsafe (void)
{
int errn;
t_uchar * id_file;
int in_fd;
t_uchar * id_contents;
size_t len;
t_uchar * eoid;
t_uchar * found_id;
if ((found_id = assoc_ref (memoised_results, MYIDKEY)))
return str_save (0, found_id);
id_file = arch_my_id_file ();
in_fd = vu_open (&errn, id_file, O_RDONLY, 0);
if (in_fd < 0)
{
if (errn == ENOENT)
safe_printfmt (2, "arch: no arch user id set\n");
else
safe_printfmt (2, "arch: i/o error for file %s (%s)\n", id_file, errno_to_string (errn));
lim_free (0, id_file);
return NULL;
}
lim_free (0, id_file);
id_contents = 0;
len = 0;
safe_file_to_string (&id_contents, &len, in_fd);
safe_close (in_fd);
eoid = str_chr_index_n (id_contents, len, '\n');
if (!eoid)
eoid = id_contents + len;
arch_my_id_memoise(id_contents, eoid - id_contents);
lim_free (0, id_contents);
return str_save (0, assoc_ref (memoised_results, MYIDKEY));
}
/* find the arch id, exiting on failure
*/
t_uchar *
arch_my_id (void)
{
t_uchar *result = arch_my_id_unsafe ();
if (!result)
exit (2);
return result;
}
t_uchar *
arch_my_id_uid_default (t_uchar const *default_id)
{
t_uchar * id = 0;
t_uchar * lb;
t_uchar * rb;
t_uchar * answer = 0;
id = arch_my_id_default (default_id);
if (!id)
return 0;
lb = str_chr_rindex (id, '<');
rb = str_chr_rindex (id, '>');
invariant (lb && rb && ((lb + 1) < rb));
answer = str_save_n (0, (lb + 1), rb - (lb + 1));
lim_free (0, id);
return answer;
}
t_uchar *
arch_my_id_uid (void)
{
t_uchar * id = arch_my_id ();
t_uchar * result = arch_my_id_uid_default (id);
lim_free (0, id);
return result;
}
static t_uchar * my_home_archive = 0;
t_uchar *
arch_my_default_archive (t_uchar const * default_archive)
{
t_uchar * default_archive_file = 0;
int in_fd;
t_uchar * default_archive_file_contents = 0;
size_t archive_contents_len;
t_uchar * nl_pos;
t_uchar * answer = 0;
int errn;
/* This does away with the arch conventions of using $ARCHIVE
* and has no support for -R
*/
if (default_archive)
{
if (!arch_valid_archive_name (default_archive))
{
safe_printfmt (2, "invalid archive name %s\n", default_archive);
exit (2);
}
return str_save (0, default_archive);
}
if (my_home_archive)
return str_save (0, my_home_archive);
default_archive_file = file_name_in_vicinity (0, arch_my_arch_params(), "=default-archive");
in_fd = vu_open (&errn, default_archive_file, O_RDONLY, 0);
if (in_fd < 0)
{
if (errn != ENOENT)
{
safe_printfmt (2, "arch: error opening %s\n", default_archive_file);
exit (2);
}
answer = 0;
}
else
{
safe_file_to_string (&default_archive_file_contents, &archive_contents_len, in_fd);
safe_close (in_fd);
nl_pos = str_chr_index_n (default_archive_file_contents, archive_contents_len, '\n');
if (!nl_pos)
nl_pos = default_archive_file_contents + archive_contents_len;
answer = str_save_n (0, default_archive_file_contents, nl_pos - default_archive_file_contents);
}
lim_free (0, default_archive_file_contents);
lim_free (0, default_archive_file);
if (answer)
{
lim_free (0, my_home_archive);
my_home_archive = str_save (0, answer);
}
return answer;
}
void
arch_set_my_default_archive (t_uchar * archive)
{
t_uchar * default_archive_file;
int out_fd;
invariant (arch_valid_archive_name (archive));
if (my_home_archive)
{
lim_free (0, my_home_archive);
my_home_archive = 0;
}
arch_ensure_my_arch_params ();
default_archive_file = file_name_in_vicinity (0, arch_my_arch_params(), "=default-archive");
out_fd = safe_open (default_archive_file, O_WRONLY | O_CREAT, 0666);
safe_ftruncate (out_fd, (long)0);
safe_write_retry (out_fd, archive, str_length (archive));
safe_close (out_fd);
lim_free (0, default_archive_file);
my_home_archive = str_save (0, archive);
}
void
arch_delete_my_default_archive (void)
{
t_uchar * default_archive_file;
int errn;
if (my_home_archive)
{
lim_free (0, my_home_archive);
my_home_archive = 0;
}
default_archive_file = file_name_in_vicinity (0, arch_my_arch_params(), "=default-archive");
if (vu_unlink (&errn, default_archive_file) && (errn != ENOENT))
{
panic ("unable to delete ~/.arch-params/=default-archive");
}
lim_free (0, default_archive_file);
}
t_uchar *
arch_my_archive_locations_dir (void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "=locations");
}
/**
* \brief the dir archives ini files are stored in
*/
t_uchar *
arch_my_archives_dir (void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "archives");
}
static t_uchar *
arch_my_default_library_file (void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "=revision-library");
}
static t_uchar *
arch_my_default_library_add_file (void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "=revision-library-adds");
}
rel_table
arch_my_library_path (enum arch_library_path_type path_type)
{
t_uchar * first_file = 0;
t_uchar * second_file = 0;
rel_table answer = 0;
switch (path_type)
{
case arch_library_path_search_only:
{
first_file = arch_my_default_library_file ();
break;
}
case arch_library_path_add_only:
{
first_file = arch_my_default_library_add_file ();
break;
}
case arch_library_path_search_order:
{
first_file = arch_my_default_library_file ();
second_file = arch_my_default_library_add_file ();
break;
}
case arch_library_path_add_order:
{
second_file = arch_my_default_library_file ();
first_file = arch_my_default_library_add_file ();
break;
}
}
if (first_file && !safe_access (first_file, F_OK))
{
int fd;
fd = safe_open (first_file, O_RDONLY, 0);
answer = rel_read_pika_unescape_iso8859_1_table (fd, 1, "baz", first_file);
safe_close (fd);
}
if (second_file && !safe_access (second_file, F_OK))
{
int fd;
rel_table answer2 = 0;
fd = safe_open (second_file, O_RDONLY, 0);
answer2 = rel_read_pika_unescape_iso8859_1_table (fd, 1, "baz", second_file);
safe_close (fd);
rel_append_x (&answer, answer2);
rel_free_table (answer2);
}
lim_free (0, first_file);
lim_free (0, second_file);
return answer;
}
int
arch_set_my_library_path (enum arch_library_path_type path_type,
enum arch_library_edit_op op,
t_uchar * dir_spec)
{
t_uchar * lib_file = 0;
rel_table old_path = 0;
rel_table new_path = 0;
int out_fd;
int found = 0;
switch (path_type)
{
case arch_library_path_search_order:
case arch_library_path_search_only:
{
lib_file = arch_my_default_library_file ();
old_path = arch_my_library_path (arch_library_path_search_only);
break;
}
case arch_library_path_add_order:
case arch_library_path_add_only:
{
lib_file = arch_my_default_library_add_file ();
old_path = arch_my_library_path (arch_library_path_add_only);
break;
}
}
/* install first if appropriate
*/
if (dir_spec && (op == arch_library_first))
{
rel_add_records (&new_path, rel_make_record (dir_spec, 0), 0);
}
/* copy the old path, removing dir_spec (if any)
*/
if (dir_spec)
{
int x;
for (x = 0; x < rel_n_records (old_path); ++x)
{
if (str_cmp (old_path[x][0], dir_spec))
{
rel_add_records (&new_path, rel_make_record (old_path[x][0], 0), 0);
}
else
{
found = 1;
}
}
}
/* install last if appropriate
*/
if (dir_spec && (op == arch_library_last))
{
rel_add_records (&new_path, rel_make_record (dir_spec, 0), 0);
}
/* install the new path
*/
arch_ensure_my_arch_params ();
out_fd = safe_open (lib_file, O_WRONLY | O_CREAT, 0666);
safe_ftruncate (out_fd, 0L);
rel_print_pika_escape_iso8859_1_table (out_fd, arch_escape_classes, new_path);
safe_close (out_fd);
lim_free (0, lib_file);
rel_free_table (old_path);
rel_free_table (new_path);
return found || (op != arch_library_remove);
}
t_uchar *
arch_my_util_path_file (void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "path");
}
t_uchar **
arch_my_util_path (void)
{
t_uchar * path_file = 0;
t_uchar ** answer = 0;
path_file = arch_my_util_path_file ();
if (!safe_access (path_file, F_OK))
{
t_uchar * contents = 0;
contents = trim_surrounding_ws (file_contents (path_file));
answer = path_parse (0, contents);
lim_free (0, contents);
}
lim_free (0, path_file);
return answer;
}
static t_uchar *
get_cache_path_file(void)
{
return file_name_in_vicinity (0, arch_my_arch_params(), "=arch-cache");
}
static void
arch_memoise_cache_path (t_uchar const *path)
{
assoc_set (&memoised_results, CACHEPATHKEY, path);
}
extern t_uchar const *
arch_my_cache_path(void)
{
t_uchar * answer;
t_uchar * temp;
t_uchar * cache_path_file;
if ((answer = assoc_ref (memoised_results, CACHEPATHKEY)))
{
if (str_length (answer) < 2)
return NULL;
return str_save (0, answer);
}
cache_path_file = get_cache_path_file();
if (safe_access(cache_path_file, F_OK))
{
lim_free (0, cache_path_file);
arch_memoise_cache_path ("");
return NULL;
}
temp = file_contents (cache_path_file);
answer = str_save (0, trim_surrounding_ws (temp));
lim_free (0, temp);
lim_free (0, cache_path_file);
if (str_length (answer) < 2)
{
lim_free (0, answer);
arch_memoise_cache_path ("");
return NULL;
}
arch_memoise_cache_path (answer);
return answer;
}
extern void
arch_set_my_cache_path(t_uchar const * location)
{
t_uchar * cache_path_file = get_cache_path_file();
int errn = -1;
int out_fd=-1;
arch_ensure_my_arch_params ();
out_fd = vu_open (&errn, cache_path_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (out_fd < 0)
{
safe_printfmt (2, "arch: error opening %s\n %s opening %s (in vu_open)\n", cache_path_file, errno_to_string(errn), cache_path_file);
exit (2);
}
else
{
safe_printfmt (out_fd, "%s\n", location);
safe_close (out_fd);
}
arch_memoise_cache_path (location);
}
static t_uchar *
my_default_cache_path (void)
{
t_uchar * home;
t_uchar * answer;
home = getenv ("HOME");
invariant (!!home);
answer = file_name_in_vicinity (0, home, ".arch-cache");
return answer;
}
extern void
arch_ensure_cache_path ()
{
t_uchar * cache_path_file = get_cache_path_file();
int errn = -1;
struct stat stat;
int stat_ok = vu_stat (&errn, cache_path_file, &stat);
if (stat_ok != 0 && errn == ENOENT)
{
t_uchar * default_path = my_default_cache_path ();
arch_set_my_cache_path(default_path);
safe_printfmt (2, "Setting arch cache to default path: %s\n", default_path);
lim_free (0, default_path);
}
}
/* tag: Tom Lord Mon May 12 15:01:17 2003 (my.c)
*/
syntax highlighted by Code2HTML, v. 0.9.1