aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/misc.h2
-rw-r--r--libssh/misc.c60
2 files changed, 62 insertions, 0 deletions
diff --git a/include/libssh/misc.h b/include/libssh/misc.h
index 6d7aed9..05c6d49 100644
--- a/include/libssh/misc.h
+++ b/include/libssh/misc.h
@@ -28,6 +28,8 @@ char *ssh_get_user_home_dir(void);
char *ssh_get_local_username(ssh_session session);
int ssh_file_readaccess_ok(const char *file);
+char *ssh_path_expand_tilde(const char *d);
+
/* macro for byte ordering */
uint64_t ntohll(uint64_t);
#define htonll(x) ntohll(x)
diff --git a/libssh/misc.c b/libssh/misc.c
index ff44fb5..7bef392 100644
--- a/libssh/misc.c
+++ b/libssh/misc.c
@@ -520,6 +520,66 @@ int ssh_mkdir(const char *pathname, mode_t mode) {
return r;
}
+/**
+ * @brief Expand a directory starting with a tilde '~'
+ *
+ * @param[in] session The ssh session to use.
+ *
+ * @param[in] d The directory to expand.
+ *
+ * @return The expanded directory, NULL on error.
+ */
+char *ssh_path_expand_tilde(const char *d) {
+ char *h, *r, *p;
+ size_t ld;
+ size_t lh = 0;
+
+ if (d[0] != '~') {
+ return strdup(d);
+ }
+ d++;
+
+ /* handle ~user/path */
+ p = strchr(d, '/');
+ if (p != NULL && p > d) {
+ struct passwd *pw;
+ size_t s = p - d;
+ char u[128];
+
+ if (s > sizeof(u)) {
+ return NULL;
+ }
+ memcpy(u, d, s);
+ u[s] = '\0';
+ pw = getpwnam(u);
+ if (pw == NULL) {
+ return NULL;
+ }
+ ld = strlen(p);
+ h = strdup(pw->pw_dir);
+ } else {
+ ld = strlen(d);
+ p = (char *) d;
+ h = ssh_get_user_home_dir();
+ }
+ if (h == NULL) {
+ return NULL;
+ }
+ lh = strlen(h);
+
+ r = malloc(ld + lh + 1);
+ if (r == NULL) {
+ return NULL;
+ }
+
+ if (lh > 0) {
+ memcpy(r, h, lh);
+ }
+ memcpy(r + lh, p, ld);
+
+ return r;
+}
+
/* @} */
/* vim: set ts=4 sw=4 et cindent: */