]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Consult $HOME rather than calling getpwuid(),
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 20 Mar 2024 13:43:11 +0000 (14:43 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Wed, 20 Mar 2024 23:53:18 +0000 (00:53 +0100)
Quiting getpwnam(3):

An application that wants to determine its user’s home
directory should inspect the value of HOME (rather than the value
getpwuid(getuid())->pw_dir) since this allows the user to modify
their notion of "the home directory" during a login session.

Change the function to return const char *, i.e. a pointer to the
environment rather than a copy that must be freed by the caller.
Document that the caller must not modify or free this string and fix
all callers accordingly.

afs.c
audioc.c
client.c
client_common.c
file_write.c
lsu.c
play.c
server.c
string.c
string.h
upgrade_db.c

diff --git a/afs.c b/afs.c
index 445d5871097b79cdcd14170c2a1f59998354dc98..8bc7cd84bd407700b1e85727aabefea01316396d 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -571,10 +571,9 @@ static void get_database_dir(void)
                if (OPT_GIVEN(AFS_DATABASE_DIR))
                        database_dir = para_strdup(OPT_STRING_VAL(AFS_DATABASE_DIR));
                else {
-                       char *home = para_homedir();
+                       const char *home = get_homedir();
                        database_dir = make_message(
                                "%s/.paraslash/afs_database-0.7", home);
-                       free(home);
                }
        }
        PARA_INFO_LOG("afs_database dir %s\n", database_dir);
index f2e4cb91de228dcd78cae534e08d76e8514b6d88..16155d4c02a191e776a678f1ddd402935d7922b8 100644 (file)
--- a/audioc.c
+++ b/audioc.c
@@ -245,10 +245,9 @@ __noreturn static void interactive_session(void)
        if (OPT_GIVEN(HISTORY_FILE))
                history_file = para_strdup(OPT_STRING_VAL(HISTORY_FILE));
        else {
-               char *home = para_homedir();
+               const char *home = get_homedir();
                history_file = make_message("%s/.paraslash/audioc.history",
                        home);
-               free(home);
        }
        ici.history_file = history_file;
 
index 84b7580cf9554c433651da1f3eed28a6f1f39a74..916adfb0ca9172c397dea28fe91bb09819089b59 100644 (file)
--- a/client.c
+++ b/client.c
@@ -529,10 +529,9 @@ __noreturn static void interactive_session(void)
                ici.history_file = para_strdup(CLIENT_OPT_STRING_VAL(
                        HISTORY_FILE, ct->lpr));
        else {
-               char *home = para_homedir();
+               const char *home = get_homedir();
                ici.history_file = make_message("%s/.paraslash/client.history",
                        home);
-               free(home);
        }
        act.sa_handler = i9e_signal_dispatch;
        sigemptyset(&act.sa_mask);
index fe8234f98fe90f6ce74ea5e22699fbfc0059a042..e207684e61121b18333ce3a99b476b8f92511d6c 100644 (file)
@@ -559,7 +559,7 @@ int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
        struct lls_parse_result *lpr;
        int ret, ll;
        struct client_task *ct;
-       char *kf = NULL, *user, *errctx, *home = para_homedir();
+       char *kf = NULL, *user, *errctx;
 
        ret = lls(lls_parse(argc, argv, cmd, &lpr, &errctx));
        if (ret < 0)
@@ -582,6 +582,7 @@ int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
                kf = para_strdup(CLIENT_OPT_STRING_VAL(KEY_FILE, lpr));
        else {
                struct stat statbuf;
+               const char *home = get_homedir();
                kf = make_message("%s/.paraslash/key.%s", home, user);
                if (stat(kf, &statbuf) != 0) { /* assume file does not exist */
                        free(kf);
@@ -599,7 +600,6 @@ int client_parse_config(int argc, char *argv[], struct client_task **ct_ptr,
        *ct_ptr = ct;
        ret = lls_num_inputs(lpr);
 out:
-       free(home);
        if (ret < 0) {
                if (errctx)
                        PARA_ERROR_LOG("%s\n", errctx);
index ba902070d9498677e94872860aeb9bbcbcd5235e..5435db444c013c9bea8a4b00f204261d5303571d 100644 (file)
@@ -31,12 +31,12 @@ struct private_file_write_data {
  */
 __must_check __malloc static char *random_filename(void)
 {
-       char *result, *home = para_homedir();
+       char *result;
+       const char *home = get_homedir();
 
        srandom(clock_get_realtime(NULL)->tv_usec);
        result = make_message("%s/.paraslash/%08ld", home,
                para_random(99999999));
-       free(home);
        return result;
 }
 
diff --git a/lsu.c b/lsu.c
index 8ccf80d541929194f984759e38d7ffa7998d3c97..3cd6ba04e4f41a26cd8e235b0ff8899aea11ab9a 100644 (file)
--- a/lsu.c
+++ b/lsu.c
@@ -182,9 +182,8 @@ int lsu_merge_config_file_options(const char *path, const char *dflt,
        if (path)
                cf = para_strdup(path);
        else {
-               char *home = para_homedir();
+               const char *home = get_homedir();
                cf = make_message("%s/.paraslash/%s", home, dflt);
-               free(home);
        }
        ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
        if (ret < 0) {
diff --git a/play.c b/play.c
index bd183b6b8dd48906e08cf142d7ff8c1e05aad48a..efac36a1a9c9c1096edbec27ac429df397364941 100644 (file)
--- a/play.c
+++ b/play.c
@@ -1044,10 +1044,9 @@ static void session_open(void)
        if (OPT_GIVEN(HISTORY_FILE))
                history_file = para_strdup(OPT_STRING_VAL(HISTORY_FILE));
        else {
-               char *home = para_homedir();
+               const char *home = get_homedir();
                char *dot_para = make_message("%s/.paraslash", home);
 
-               free(home);
                ret = para_mkdir(dot_para);
                /* warn, but otherwise ignore mkdir error */
                if (ret < 0)
index ea9cc9c003616762a96aa546c381d54417fd34a2..0df82e000bc491d6de9e1333fb3241446674e49d 100644 (file)
--- a/server.c
+++ b/server.c
@@ -232,9 +232,8 @@ void parse_config_or_die(bool reload)
                if (OPT_GIVEN(USER_LIST))
                        user_list_file = para_strdup(OPT_STRING_VAL(USER_LIST));
                else {
-                       char *home = para_homedir();
+                       const char *home = get_homedir();
                        user_list_file = make_message("%s/.paraslash/server.users", home);
-                       free(home);
                }
                user_list_init(user_list_file);
                free(user_list_file);
index d8bd027b7010a149be59b8883b3e5ee685fb3c01..1cc59eeaa127f37e34940683b7376c5ad9690743 100644 (file)
--- a/string.c
+++ b/string.c
@@ -308,31 +308,20 @@ __must_check __malloc char *para_logname(void)
 }
 
 /**
- * Get the home directory of the calling user.
+ * Investigate $HOME to get the home directory of the calling user.
  *
- * \return A dynamically allocated string that must be freed by the caller. If
- * no entry is found which matches the UID of the calling process, or any other
- * error occurs, the function prints an error message and aborts.
+ * \return A pointer to read-only memory that must not be freed by the caller.
+ * If the environment variable HOME is unset or empty, the function prints an
+ * error message and aborts.
  *
- * \sa getpwuid(3), getuid(2).
+ * \sa getenv(3), getuid(2).
  */
-__must_check __malloc char *para_homedir(void)
+const char *get_homedir(void)
 {
-       struct passwd *pw;
-
-       /*
-        * To distinguish between the error case and the "not found" case we
-        * have to check errno after getpwuid(3). The manual page recommends to
-        * set it to zero before the call.
-        */
-       errno = 0;
-       pw = getpwuid(getuid());
-       if (pw)
-               return para_strdup(pw->pw_dir);
-       if (errno != 0)
-               PARA_EMERG_LOG("getpwuid error: %s\n", strerror(errno));
-       else
-               PARA_EMERG_LOG("no pw entry for uid %u\n", (unsigned)getuid());
+       const char *home = getenv("HOME");
+       if (home && *home)
+               return home;
+       PARA_EMERG_LOG("fatal: HOME is unset or empty");
        exit(EXIT_FAILURE);
 }
 
index d773600fbf0a0168584235a5098beabb110a3416..7cb4ed13ff2d7bf17107dc05b292b288507967ab 100644 (file)
--- a/string.h
+++ b/string.h
@@ -80,7 +80,7 @@ __printf_2_3 unsigned xasprintf(char **result, const char *fmt, ...);
 __must_check __malloc __printf_1_2 char *make_message(const char *fmt, ...);
 __must_check __malloc char *para_strcat(char *a, const char *b);
 __must_check __malloc char *para_logname(void);
-__must_check __malloc char *para_homedir(void);
+const char *get_homedir(void);
 __malloc char *para_hostname(void);
 __printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...);
 int para_atoi64(const char *str, int64_t *result);
index 487d46c06f2ce1df61630aaa34ca44dc99fb1d86..9b75ebef4cf039559b5eaf39a3f68d5e8ccc408d 100644 (file)
@@ -76,7 +76,7 @@ static char *src_db_dir, *dst_db_dir, *src_aft_dir, *dst_aft_dir;
 
 static void set_paths(const struct lls_parse_result *lpr)
 {
-       char *home = para_homedir();
+       const char *home = get_homedir();
 
        if (OPT_GIVEN(SRC_DATABASE_DIR, lpr))
                src_db_dir = para_strdup(OPT_STRING_VAL(SRC_DATABASE_DIR,
@@ -90,7 +90,6 @@ static void set_paths(const struct lls_parse_result *lpr)
        else
                dst_db_dir = make_message(
                        "%s/.paraslash/afs_database-0.7", home);
-       free(home);
        src_aft_dir = make_message("%s/audio_files", src_db_dir);
        dst_aft_dir = make_message("%s/audio-files", src_db_dir);
        PARA_NOTICE_LOG("source aft dir: %s\n", src_aft_dir);