/* 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) */