Index: fep/uim-fep.c =================================================================== --- fep/uim-fep.c (revision 5259) +++ fep/uim-fep.c (working copy) @@ -243,7 +243,7 @@ }; FILE *fp; const char *suffix = NULL; - char *uim_dir; + char uim_dir[UNIX_PATH_MAX]; const char *sty_str; const char *win_str; struct stat stat_buf; @@ -415,7 +415,7 @@ tcgetattr(g_win_in, &s_save_tios); setupterm(NULL, g_win_out, NULL); - if ((uim_dir = get_ud_path()) == NULL) { + if (!get_ud_path(uim_dir, sizeof(uim_dir))) { sendline("uim-fep cannot make directory"); return EXIT_FAILURE; } @@ -475,7 +475,6 @@ } } } - free(uim_dir); snprintf(pid_str, sizeof(pid_str), "%d", getpid()); setenv("UIM_FEP_PID", pid_str, 1); Index: fep/udsock.c =================================================================== --- fep/udsock.c (revision 5259) +++ fep/udsock.c (working copy) @@ -62,62 +62,30 @@ #include #include +#include "uim-posix.h" #include "udsock.h" static int s_send_sockfd = -1; static int s_recv_sockfd = -1; static struct sockaddr_un s_servaddr; -static uim_bool -check_dir(const char *dir) +uim_bool +get_ud_path(char *path, int len) { - struct stat st; - - if (dir == NULL) + if (len <= 0) return UIM_FALSE; - if (stat(dir, &st) < 0) - return (mkdir(dir, 0700) < 0) ? UIM_FALSE : UIM_TRUE; - else { - mode_t mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; - return ((st.st_mode & mode) == mode) ? UIM_TRUE : UIM_FALSE; + if (!uim_get_config_path(path, len, !uim_helper_is_setugid())) { + path[0] = '\0'; + return UIM_FALSE; } -} -char * -get_ud_path(void) -{ - char *path, *home = NULL; - struct passwd *pw; + strlcat(path, "/fep", len); - pw = getpwuid(getuid()); - if (pw) - home = pw->pw_dir; + if (!uim_check_dir(path)) + return UIM_FALSE; - if (!home && !uim_helper_is_setugid()) - home = getenv("HOME"); - - if (!home) - return NULL; - - if (asprintf(&path, "%s/.uim.d", home) == -1) - return NULL; /* XXX: fatal */ - - if (!check_dir(path)) { - free(path); - return NULL; - } - free(path); - - if (asprintf(&path, "%s/.uim.d/fep", home) == -1) - return NULL; /* XXX: fatal */ - - if (!check_dir(path)) { - free(path); - return NULL; - } - - return path; + return UIM_TRUE; } @@ -125,7 +93,7 @@ { static char buf[UNIX_PATH_MAX]; char filebuf[UNIX_PATH_MAX]; - char *sock_dir; + char sock_dir[UNIX_PATH_MAX]; if (file != NULL && file[0] == '/') { return file; @@ -137,8 +105,7 @@ strlcpy(filebuf, file, UNIX_PATH_MAX); } - sock_dir = get_ud_path(); - if (!sock_dir) { + if (!get_ud_path(sock_dir, sizeof(sock_dir))) { sendline("uim-fep cannot create directory"); exit(EXIT_FAILURE); } Index: fep/udsock.h =================================================================== --- fep/udsock.h (revision 5259) +++ fep/udsock.h (working copy) @@ -34,6 +34,8 @@ #ifndef UDSOCK_H #define UDSOCK_H +#include "uim.h" + #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 100 #endif @@ -44,6 +46,6 @@ void init_recvsocket(const char *sock_path); int recvline(char *buf, int n); void close_socket(void); -char *get_ud_path(void); +uim_bool get_ud_path(char *, int); #endif Index: scm/skk-custom.scm =================================================================== --- scm/skk-custom.scm (revision 5259) +++ scm/skk-custom.scm (working copy) @@ -394,14 +394,14 @@ (N_ "long description will be here.")) (define-custom 'skk-personal-dic-filename - (string-append (or (getenv "HOME") "") "/.skk-jisyo") + (string-append (or (home-directory (user-name)) "") "/.skk-jisyo") '(skk-dict dict-files) '(pathname regular-file) (N_ "Personal dictionary file") (N_ "long description will be here.")) (define-custom 'skk-uim-personal-dic-filename - (string-append (or (getenv "HOME") "") "/.skk-uim-jisyo") + (string-append (or (home-directory (user-name)) "") "/.skk-uim-jisyo") '(skk-dict dict-files) '(pathname regular-file) (N_ "Personal dictionary file (dedicated to uim)") Index: scm/init.scm =================================================================== --- scm/init.scm (revision 5259) +++ scm/init.scm (working copy) @@ -68,7 +68,7 @@ (define load-user-conf (lambda () - (let ((home-dir (getenv "HOME"))) + (let ((home-dir (or (home-directory (user-name)) ""))) (if (or (setugid?) (not home-dir)) Index: scm/plugin.scm =================================================================== --- scm/plugin.scm (revision 5259) +++ scm/plugin.scm (working copy) @@ -37,7 +37,7 @@ (define uim-plugin-lib-load-path (if (setugid?) (list (string-append (sys-pkglibdir) "/plugin")) - (let ((home-dir (getenv "HOME")) + (let ((home-dir (or (home-directory (user-name)) "")) (ld-library-path (getenv "LD_LIBRARY_PATH"))) (filter string? (append (list (getenv "LIBUIM_PLUGIN_LIB_DIR") @@ -53,7 +53,7 @@ (define uim-plugin-scm-load-path (if (setugid?) (list (sys-pkgdatadir)) - (let ((home-dir (getenv "HOME"))) + (let ((home-dir (or (home-directory (user-name)) ""))) (filter string? (list (getenv "LIBUIM_SCM_FILES") (if home-dir @@ -128,7 +128,7 @@ ;; TODO: write test (define load-module-conf (lambda () - (let* ((home-dir (getenv "HOME")) + (let* ((home-dir (or (home-directory (user-name)) "")) (user-module-dir (if home-dir (string-append home-dir "/.uim.d/plugin/") #f)) @@ -155,7 +155,7 @@ ;; TODO: write test (define load-enabled-modules (lambda () - (let* ((home-dir (getenv "HOME")) + (let* ((home-dir (or (home-directory (user-name)) "")) (user-module-dir (if home-dir (string-append home-dir "/.uim.d/plugin/") #f)) Index: scm/tutcode-custom.scm =================================================================== --- scm/tutcode-custom.scm (revision 5259) +++ scm/tutcode-custom.scm (working copy) @@ -55,7 +55,7 @@ (N_ "long description will be here.")) (define-custom 'tutcode-personal-dic-filename - (string-append (or (getenv "HOME") "") "/.mazegaki.dic") + (string-append (or (home-directory (user-name)) "") "/.mazegaki.dic") '(tutcode tutcode-dict) '(pathname regular-file) (N_ "Personal mazegaki dictionary file") Index: scm/sj3-custom.scm =================================================================== --- scm/sj3-custom.scm (revision 5259) +++ scm/sj3-custom.scm (working copy) @@ -319,7 +319,7 @@ (lambda () sj3-use-remote-server?)) -(define-custom 'sj3-user (getenv "USER") +(define-custom 'sj3-user (or (home-directory (user-name)) "") '(sj3-advanced sj3server) '(string ".*") (N_ "SJ3 user name") Index: scm/look-custom.scm =================================================================== --- scm/look-custom.scm (revision 5259) +++ scm/look-custom.scm (working copy) @@ -47,7 +47,7 @@ (N_ "long description will be here.")) (define-custom 'look-personal-dict-filename - (string-append (or (getenv "HOME") "") "/.look-uim-dict") + (string-append (or (home-directory (user-name)) "") "/.look-uim-dict") '(look) '(pathname regular-file) (N_ "Personal dictionary file") Index: scm/custom-rt.scm =================================================================== --- scm/custom-rt.scm (revision 5259) +++ scm/custom-rt.scm (working copy) @@ -63,7 +63,7 @@ (define custom-file-path (lambda (gsym) (let* ((group-name (symbol->string gsym)) - (path (string-append (or (getenv "HOME") "") + (path (string-append (or (home-directory (user-name)) "") "/.uim.d/customs/custom-" group-name ".scm"))) Index: uim/uim-posix.h =================================================================== --- uim/uim-posix.h (revision 0) +++ uim/uim-posix.h (revision 0) @@ -0,0 +1,55 @@ +/* + + Copyright (c) 2008 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ + +#ifndef UIM_POSIX_H +#define UIM_POSIX_H + +#include "uim.h" + +#ifdef __cplusplus +extern "C" { +#endif + +uim_bool uim_get_user_name(char *, int, int); +uim_bool uim_get_home_directory(char *, int, int); +uim_bool uim_check_dir(const char *); +uim_bool uim_get_config_path(char *, int, int); + +void uim_init_posix_subrs(void); + +#ifdef __cplusplus +} +#endif + +#endif + Index: uim/uim-custom.c =================================================================== --- uim/uim-custom.c (revision 5259) +++ uim/uim-custom.c (working copy) @@ -1032,7 +1032,7 @@ { char *dir; - UIM_EVAL_STRING(NULL, "(string-append (or (getenv \"HOME\") \"\") \"/.uim.d\")"); + UIM_EVAL_STRING(NULL, "(string-append (or (home-directory (user-name)) \"\") \"/.uim.d\")"); dir = uim_scm_c_str(uim_scm_return_value()); if (subpath) { UIM_EVAL_FSTRING2(NULL, "\"%s/%s\"", dir, subpath); Index: uim/uim-util.c =================================================================== --- uim/uim-util.c (revision 5259) +++ uim/uim-util.c (working copy) @@ -80,92 +80,6 @@ return MAKE_STR(PKGDATADIR); } -static uim_lisp -file_stat_mode(uim_lisp filename, mode_t mode) -{ - struct stat st; - int err; - - err = stat(REFER_C_STR(filename), &st); - if (err) - return uim_scm_f(); /* intentionally returns #f instead of error */ - - return MAKE_BOOL((st.st_mode & mode) == mode); -} - -static uim_lisp -file_readablep(uim_lisp filename) -{ - return file_stat_mode(filename, S_IRUSR); -} - -static uim_lisp -file_writablep(uim_lisp filename) -{ - return file_stat_mode(filename, S_IWUSR); -} - -static uim_lisp -file_executablep(uim_lisp filename) -{ - return file_stat_mode(filename, S_IXUSR); -} - -static uim_lisp -file_regularp(uim_lisp filename) -{ - return file_stat_mode(filename, S_IFREG); -} - -static uim_lisp -file_directoryp(uim_lisp filename) -{ - return file_stat_mode(filename, S_IFDIR); -} - -static uim_lisp -file_mtime(uim_lisp filename) -{ - struct stat st; - int err; - - err = stat(REFER_C_STR(filename), &st); - if (err) - ERROR_OBJ("stat failed for file", filename); - - return MAKE_INT(st.st_mtime); -} - -static uim_lisp -c_getenv(uim_lisp str) -{ - char *val; - - ENSURE_TYPE(str, str); - - val = getenv(REFER_C_STR(str)); - - return (val) ? MAKE_STR(val) : uim_scm_f(); -} - -static uim_lisp -c_setenv(uim_lisp name, uim_lisp val, uim_lisp overwrite) -{ - int err; - - err = setenv(REFER_C_STR(name), REFER_C_STR(val), TRUEP(overwrite)); - - return MAKE_BOOL(!err); -} - -static uim_lisp -c_unsetenv(uim_lisp name) -{ - unsetenv(REFER_C_STR(name)); - - return uim_scm_t(); -} - /* Limited version of SRFI-13 string-contains. The number of args are * fixed to 3. */ static uim_lisp @@ -277,14 +191,6 @@ return name; } -static uim_lisp -setugidp(void) -{ - assert(uim_scm_gc_any_contextp()); - - return MAKE_BOOL(uim_issetugid()); -} - void uim_init_util_subrs(void) { @@ -298,19 +204,6 @@ uim_scm_init_proc0("sys-datadir", sys_datadir); uim_scm_init_proc0("sys-pkgdatadir", sys_pkgdatadir); - uim_scm_init_proc1("file-readable?", file_readablep); - uim_scm_init_proc1("file-writable?", file_writablep); - uim_scm_init_proc1("file-executable?", file_executablep); - uim_scm_init_proc1("file-regular?", file_regularp); - uim_scm_init_proc1("file-directory?", file_directoryp); - uim_scm_init_proc1("file-mtime", file_mtime); - - uim_scm_init_proc0("setugid?", setugidp); - - uim_scm_init_proc1("getenv", c_getenv); - uim_scm_init_proc3("setenv", c_setenv); - uim_scm_init_proc1("unsetenv", c_unsetenv); - /* SRFI-13 */ uim_scm_init_proc3("string-contains", string_contains); uim_scm_init_proc2("string-prefix?", string_prefixp); Index: uim/prime.c =================================================================== --- uim/prime.c (revision 5259) +++ uim/prime.c (working copy) @@ -55,6 +55,7 @@ #include "plugin.h" #include "uim-helper.h" #include "uim-util.h" +#include "uim-posix.h" #define BUFFER_SIZE (4 * 1024) @@ -63,7 +64,7 @@ static char *prime_command = "prime"; -static char *prime_ud_path; +static char prime_ud_path[MAXPATHLEN]; static int prime_fd = -1; static uim_bool use_unix_domain_socket; @@ -73,7 +74,7 @@ int fd; struct sockaddr_un server; - if (!path) + if (path[0] == '\0') return -1; memset(&server, 0, sizeof(server)); @@ -109,56 +110,28 @@ } static uim_bool -check_dir(const char *dir) +prime_get_ud_path(char *prime_path, int len) { - struct stat st; + char socket_path[MAXPATHLEN], ud_path[MAXPATHLEN]; - if (stat(dir, &st) < 0) - return (mkdir(dir, 0700) < 0) ? UIM_FALSE : UIM_TRUE; - else { - mode_t mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; - return ((st.st_mode & mode) == mode) ? UIM_TRUE : UIM_FALSE; + if (len <= 0) + return UIM_FALSE; + + if (!uim_get_config_path(ud_path, sizeof(ud_path), !uim_helper_is_setugid())) { + prime_path[0] = '\0'; + return UIM_FALSE; } -} -static char * -prime_get_ud_path(void) -{ - char *path, *home = NULL; - struct passwd *pw; - int len; - - pw = getpwuid(getuid()); - if (pw) - home = pw->pw_dir; + snprintf(socket_path, len, "%s/socket", ud_path); - if (!home && !uim_helper_is_setugid()) - home = getenv("HOME"); - - if (!home) - return NULL; - - len = strlen(home) + strlen("/.uim.d"); - path = uim_malloc(len + 1); - snprintf(path, len + 1, "%s/.uim.d", home); - if (!check_dir(path)) { - free(path); - return NULL; + if (!uim_check_dir(socket_path)) { + prime_path[0] = '\0'; + return UIM_FALSE; } - len += strlen("/socket"); - path = uim_realloc(path, len + 1); - strlcat(path, "/socket", len + 1); - if (!check_dir(path)) { - free(path); - return NULL; - } + snprintf(prime_path, len, "%s/uim-prime", ud_path); - len += strlen("/uim-prime"); - path = uim_realloc(path, len + 1); - strlcat(path, "/uim-prime", len + 1); - - return path; + return UIM_TRUE; } static void @@ -166,8 +139,7 @@ { close(prime_fd); prime_fd = -1; - free(prime_ud_path); - prime_ud_path = NULL; + prime_ud_path[0] = '\0'; } static char * @@ -262,10 +234,9 @@ if (prime_fd != -1) return uim_scm_t(); - prime_ud_path = prime_get_ud_path(); - if (!prime_ud_path) + if (!prime_get_ud_path(prime_ud_path, sizeof(prime_ud_path))) return uim_scm_f(); - + prime_fd = prime_init_ud(prime_ud_path); if (prime_fd == -1) { unlink(prime_ud_path); Index: uim/uim-helper-client.c =================================================================== --- uim/uim-helper-client.c (revision 5259) +++ uim/uim-helper-client.c (working copy) @@ -74,22 +74,19 @@ int uim_helper_init_client_fd(void (*disconnect_cb)(void)) { struct sockaddr_un server; - char *path; + char path[MAXPATHLEN]; FILE *serv_r = NULL, *serv_w = NULL; int fd = -1; uim_fd = -1; - - path = uim_helper_get_pathname(); - if (!path) + + if (!uim_helper_get_pathname(path, sizeof(path))) goto error; memset(&server, 0, sizeof(server)); server.sun_family = PF_UNIX; strlcpy(server.sun_path, path, sizeof(server.sun_path)); - free(path); - fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { perror("fail to create socket"); Index: uim/uim-helper.c =================================================================== --- uim/uim-helper.c (revision 5259) +++ uim/uim-helper.c (working copy) @@ -51,6 +51,7 @@ #include "uim-internal.h" #include "uim-helper.h" #include "uim-util.h" +#include "uim-posix.h" /* * uim-notify is disabled since I'm not confident about: @@ -162,51 +163,52 @@ } } -char * -uim_helper_get_pathname(void) +uim_bool +uim_helper_get_pathname(char *helper_path, int len) { - char *path, *home = NULL; + char socket_path[MAXPATHLEN], ud_path[MAXPATHLEN]; struct passwd *pw; - int len; - - if (UIM_CATCH_ERROR_BEGIN()) - return NULL; - pw = getpwuid(getuid()); - if (pw) - home = pw->pw_dir; + if (len <= 0) + return UIM_FALSE; - if (!home && !uim_issetugid()) - home = getenv("HOME"); + if (UIM_CATCH_ERROR_BEGIN()) { + helper_path[0] = '\0'; + return UIM_FALSE; + } - if (!home) + pw = getpwuid(getuid()); + if (!pw) { uim_fatal_error("uim_helper_get_pathname()"); + endpwent(); + helper_path[0] = '\0'; + return UIM_FALSE; + } + snprintf(ud_path, len, "%s/.uim.d", pw->pw_dir); + endpwent(); + /* check ~/.uim.d/ */ - len = strlen(home) + strlen("/.uim.d"); - path = uim_malloc(len + 1); - snprintf(path, len + 1, "%s/.uim.d", home); - if (!check_dir(path)) { - free(path); + if (!check_dir(ud_path)) { uim_fatal_error("uim_helper_get_pathname()"); + helper_path[0] = '\0'; + return UIM_FALSE; } /* check ~/.uim.d/socket/ */ - len += strlen("/socket"); - path = uim_realloc(path, len + 1); - strlcat(path, "/socket", len + 1); - if (!check_dir(path)) { - free(path); + snprintf(socket_path, sizeof(socket_path), "%s/socket", ud_path); + + if (!check_dir(socket_path)) { uim_fatal_error("uim_helper_get_pathname()"); + helper_path[0] = '\0'; + return UIM_FALSE; } - len += strlen("/uim-helper"); - path = uim_realloc(path, len + 1); - strlcat(path, "/uim-helper", len + 1); + snprintf(helper_path, len, "%s/uim-helper", ud_path); UIM_CATCH_ERROR_END(); - return path; + return UIM_TRUE; } int Index: uim/uim-helper-server.c =================================================================== --- uim/uim-helper-server.c (revision 5259) +++ uim/uim-helper-server.c (working copy) @@ -369,13 +369,12 @@ int main(int argc, char **argv) { - char *path; + char path[MAXPATHLEN]; int server_fd; uim_init_error(); - path = uim_helper_get_pathname(); - if (!path) + if (!uim_helper_get_pathname(path, sizeof(path))) return 0; unlink(path); @@ -387,7 +386,6 @@ FD_ZERO(&s_fdset_write); s_max_fd = 0; server_fd = init_server_fd(path); - free(path); printf("waiting\n\n"); fflush(stdout); Index: uim/uim-helper.h =================================================================== --- uim/uim-helper.h (revision 5259) +++ uim/uim-helper.h (working copy) @@ -49,7 +49,7 @@ void uim_helper_send_message(int fd, const char *message); /* functions for libuim server/client's implementation */ -char *uim_helper_get_pathname(void); +uim_bool uim_helper_get_pathname(char *, int); int uim_helper_str_terminated(const char *str); int uim_helper_check_connection_fd(int fd); int uim_helper_fd_readable(int fd); Index: uim/Makefile.am =================================================================== --- uim/Makefile.am (revision 5259) +++ uim/Makefile.am (working copy) @@ -37,7 +37,7 @@ $(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/sigscheme/src combined pkginclude_HEADERS = uim-scm.h uim-scm-abbrev.h uim.h \ - uim-util.h plugin.h \ + uim-util.h uim-posix.h plugin.h \ uim-helper.h uim-im-switcher.h \ uim-custom.h # Install even if !NOTIFY since plugins will need this to use @@ -46,7 +46,7 @@ libuim_la_SOURCES = \ uim-internal.h uim-error.c uim.c \ - uim-key.c uim-func.c uim-util.c \ + uim-key.c uim-func.c uim-util.c uim-posix.c \ iconv.c plugin.c \ uim-ipc.c uim-helper.c uim-helper-client.c \ gettext.h intl.c \ Index: uim/uim.c =================================================================== --- uim/uim.c (revision 5259) +++ uim/uim.c (working copy) @@ -43,6 +43,7 @@ #include "uim.h" #include "uim-internal.h" #include "uim-util.h" +#include "uim-posix.h" #include "uim-im-switcher.h" #include "uim-scm.h" #include "uim-scm-abbrev.h" @@ -126,6 +127,7 @@ uim_init_im_subrs(); uim_init_intl_subrs(); + uim_init_posix_subrs(); uim_init_util_subrs(); #if UIM_USE_NOTIFY uim_notify_init(); /* init uim-notify facility */ Index: uim/uim-posix.c =================================================================== --- uim/uim-posix.c (revision 0) +++ uim/uim-posix.c (revision 0) @@ -0,0 +1,279 @@ +/* + + Copyright (c) 2008 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "uim-internal.h" +#include "uim-scm.h" +#include "uim-scm-abbrev.h" +#include "uim-util.h" +#include "uim-posix.h" + +uim_bool +uim_get_user_name(char *name, int len, int uid) +{ + struct passwd *pw; + + if (len <= 0) + return UIM_FALSE; + pw = getpwuid(uid); + if (!pw) { + name[0] = '\0'; + return UIM_FALSE; + } + strlcpy(name, pw->pw_name, len); + endpwent(); + return UIM_TRUE; +} + +static uim_lisp +user_name(void) +{ + char name[BUFSIZ]; + + if (!uim_get_user_name(name, sizeof(name), getuid())) + return uim_scm_f(); + + return MAKE_STR(name); +} + +uim_bool +uim_get_home_directory(char *home, int len, int uid) +{ + struct passwd *pw; + + if (len <= 0) + return UIM_FALSE; + pw = getpwuid(uid); + if (!pw) { + home[0] = '\0'; + return UIM_FALSE; + } + strlcpy(home, pw->pw_dir, len); + endpwent(); + return UIM_TRUE; +} + +static uim_lisp +home_directory(uim_lisp user_) +{ + int uid; + char home[MAXPATHLEN]; + + if (INTP(user_)) { + uid = C_INT(user_); + } else if (STRP(user_)) { + struct passwd *pw; + + pw = getpwnam(REFER_C_STR(user_)); + + if (!pw) + return uim_scm_f(); + + uid = pw->pw_uid; + endpwent(); + } else { + return uim_scm_f(); + } + + if (!uim_get_home_directory(home, sizeof(home), uid)) { + char *home_env = getenv("HOME"); + if (home_env) + return MAKE_STR(home_env); + return uim_scm_f(); + } + + return MAKE_STR(home); +} + +uim_bool +uim_check_dir(const char *dir) +{ + struct stat st; + + if (stat(dir, &st) < 0) + return (mkdir(dir, 0700) < 0) ? UIM_FALSE : UIM_TRUE; + else { + mode_t mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; + return ((st.st_mode & mode) == mode) ? UIM_TRUE : UIM_FALSE; + } +} + +uim_bool +uim_get_config_path(char *path, int len, int is_getenv) +{ + char home[MAXPATHLEN]; + + if (len <= 0) + return UIM_FALSE; + + if (!uim_get_home_directory(home, sizeof(home), getuid()) && is_getenv) { + char *home_env = getenv("HOME"); + + if (!home_env) + return UIM_FALSE; + + strlcpy(home, home_env, sizeof(home)); + } + + if (snprintf(path, len, "%s/.uim.d", home) == -1) + return UIM_FALSE; + + if (!uim_check_dir(path)) { + return UIM_FALSE; + } + + return UIM_TRUE; +} + +static uim_lisp +file_stat_mode(uim_lisp filename, mode_t mode) +{ + struct stat st; + int err; + + err = stat(REFER_C_STR(filename), &st); + if (err) + return uim_scm_f(); /* intentionally returns #f instead of error */ + + return MAKE_BOOL((st.st_mode & mode) == mode); +} + +static uim_lisp +file_readablep(uim_lisp filename) +{ + return file_stat_mode(filename, S_IRUSR); +} + +static uim_lisp +file_writablep(uim_lisp filename) +{ + return file_stat_mode(filename, S_IWUSR); +} + +static uim_lisp +file_executablep(uim_lisp filename) +{ + return file_stat_mode(filename, S_IXUSR); +} + +static uim_lisp +file_regularp(uim_lisp filename) +{ + return file_stat_mode(filename, S_IFREG); +} + +static uim_lisp +file_directoryp(uim_lisp filename) +{ + return file_stat_mode(filename, S_IFDIR); +} + +static uim_lisp +file_mtime(uim_lisp filename) +{ + struct stat st; + int err; + + err = stat(REFER_C_STR(filename), &st); + if (err) + ERROR_OBJ("stat failed for file", filename); + + return MAKE_INT(st.st_mtime); +} + +static uim_lisp +c_getenv(uim_lisp str) +{ + char *val; + + ENSURE_TYPE(str, str); + + val = getenv(REFER_C_STR(str)); + + return (val) ? MAKE_STR(val) : uim_scm_f(); +} + +static uim_lisp +c_setenv(uim_lisp name, uim_lisp val, uim_lisp overwrite) +{ + int err; + + err = setenv(REFER_C_STR(name), REFER_C_STR(val), TRUEP(overwrite)); + + return MAKE_BOOL(!err); +} + +static uim_lisp +c_unsetenv(uim_lisp name) +{ + unsetenv(REFER_C_STR(name)); + + return uim_scm_t(); +} + +static uim_lisp +setugidp(void) +{ + assert(uim_scm_gc_any_contextp()); + + return MAKE_BOOL(uim_issetugid()); +} + +void +uim_init_posix_subrs(void) +{ + uim_scm_init_proc0("user-name", user_name); + uim_scm_init_proc1("home-directory", home_directory); + + uim_scm_init_proc1("file-readable?", file_readablep); + uim_scm_init_proc1("file-writable?", file_writablep); + uim_scm_init_proc1("file-executable?", file_executablep); + uim_scm_init_proc1("file-regular?", file_regularp); + uim_scm_init_proc1("file-directory?", file_directoryp); + uim_scm_init_proc1("file-mtime", file_mtime); + + uim_scm_init_proc0("setugid?", setugidp); + + uim_scm_init_proc1("getenv", c_getenv); + uim_scm_init_proc3("setenv", c_setenv); + uim_scm_init_proc1("unsetenv", c_unsetenv); +}