aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-11-01 16:46:39 +0100
committerBruce Hill <bruce@bruce-hill.com>2019-11-01 16:46:39 +0100
commit478e6a9023c51521b47701673c8335f51dbfbdec (patch)
tree399e1b9a0e2d4ddf4957d26cf163c3e58ea1e3c1
parent2086cc6598b354bf298b802368807ac66d26fd21 (diff)
Cleanup/overhaul of how symlinks are handled and how paths are parsed.
Now `bb` will fail on `bb nonexistant/..` and will display `/foo/baz/atfoo/` as `/foo/` if `atfoo` is a symlink to `/foo`
-rw-r--r--bb.c71
-rw-r--r--bb.h2
2 files changed, 35 insertions, 38 deletions
diff --git a/bb.c b/bb.c
index 8369959..329b31c 100644
--- a/bb.c
+++ b/bb.c
@@ -300,7 +300,15 @@ entry_t* load_entry(bb_t *bb, const char *path, int clear_dots)
if (!path || !path[0]) return NULL;
if (lstat(path, &filestat) == -1) return NULL;
char pbuf[PATH_MAX];
- normalize_path(bb->path, path, pbuf, clear_dots);
+ char *slash = strrchr(path, '/');
+ if (slash) {
+ strncpy(pbuf, path, (slash - path));
+ normalize_path(bb->path, pbuf, pbuf);
+ strcat(pbuf, slash);
+ } else {
+ strcpy(pbuf, bb->path);
+ strcat(pbuf, path);
+ }
if (pbuf[strlen(pbuf)-1] == '/' && pbuf[1])
pbuf[strlen(pbuf)-1] = '\0';
@@ -367,43 +375,23 @@ void* memcheck(void *p)
/*
* Prepend `root` to relative paths, replace "~" with $HOME.
- * If clear_dots is 1, then also replace "/foo/." with "/foo" and replace "/foo/baz/.." with "/foo".
* The normalized path is stored in `normalized`.
*/
-void normalize_path(const char *root, const char *path, char *normalized, int clear_dots)
+void normalize_path(const char *root, const char *path, char *normalized)
{
+ char pbuf[PATH_MAX] = {0};
if (path[0] == '~' && (path[1] == '\0' || path[1] == '/')) {
char *home;
if (!(home = getenv("HOME"))) return;
- strcpy(normalized, home);
+ strcpy(pbuf, home);
++path;
- } else if (path[0] == '/') {
- normalized[0] = '\0';
- } else {
- strcpy(normalized, root);
- if (root[strlen(root)-1] != '/') strcat(normalized, "/");
- }
- strcat(normalized, path);
-
- if (clear_dots) {
- char *src = normalized, *dest = normalized;
- while (*src) {
- while (src[0] == '/' && src[1] == '.') {
- // Replace "foo/./?" with "foo/?"
- if (src[2] == '/' || src[2] == '\0') {
- src += 2;
- } else if (src[2] == '.' && (src[3] == '/' || src[3] == '\0')) {
- // Replace "foo/baz/../asdf" with "foo/asdf"
- src += 3;
- *dest = '\0';
- if (dest[-1] == '/') dest[-1] = '\0';
- while (dest > normalized && *dest != '/') dest--;
- } else break;
- }
- *(dest++) = *(src++);
- }
- *dest = '\0';
+ } else if (path[0] != '/') {
+ strcpy(pbuf, root);
+ if (root[strlen(root)-1] != '/') strcat(pbuf, "/");
}
+ strcat(pbuf, path);
+ if (realpath(pbuf, normalized) == NULL)
+ err("Could not find: \"%s\"", pbuf);
}
/*
@@ -428,7 +416,7 @@ int populate_files(bb_t *bb, const char *path)
strcpy(pbuf, bb->prev_path);
if (chdir(pbuf)) return -1;
} else {
- normalize_path(bb->path, path, pbuf, 1);
+ normalize_path(bb->path, path, pbuf);
if (pbuf[strlen(pbuf)-1] != '/')
strcat(pbuf, "/");
if (chdir(pbuf)) return -1;
@@ -610,7 +598,7 @@ void run_bbcmd(bb_t *bb, const char *cmd)
dirty = 1;
} else if (matches_cmd(cmd, "deselect:")) { // +deselect
char pbuf[PATH_MAX];
- normalize_path(bb->path, value, pbuf, 1);
+ normalize_path(bb->path, value, pbuf);
entry_t *e = load_entry(bb, pbuf, 0);
if (e) {
set_selected(bb, e, 0);
@@ -633,7 +621,7 @@ void run_bbcmd(bb_t *bb, const char *cmd)
populate_files(bb, bb->path);
} else if (matches_cmd(cmd, "execute:")) { // +execute:
move_cursor(tty_out, 0, termheight-1);
- fputs("\033[K" T_ON(T_SHOW_CURSOR), tty_out);
+ fputs("\033[K", tty_out);
restore_term(&default_termios);
run_script(bb, value);
init_term();
@@ -1251,11 +1239,20 @@ int main(int argc, char *argv[])
setenv("BBSHELLFUNC", bbcmdfn, 1);
char full_initial_path[PATH_MAX];
getcwd(full_initial_path, PATH_MAX);
- normalize_path(full_initial_path, initial_path, full_initial_path, 1);
- if (strcmp(full_initial_path, "/") != 0) strcat(full_initial_path, "/");
+ normalize_path(full_initial_path, initial_path, full_initial_path);
+ struct stat path_stat;
+ if (stat(full_initial_path, &path_stat) != 0)
+ err("Could not find: \"%s\"", initial_path);
+ if (S_ISDIR(path_stat.st_mode)) {
+ if (strcmp(full_initial_path, "/") != 0) strcat(full_initial_path, "/");
+ } else {
+ write(cmdfd, "goto:", 5);
+ write(cmdfd, full_initial_path, strlen(full_initial_path) + 1); // Include null byte
+ char *slash = strrchr(full_initial_path, '/');
+ *slash = '\0';
+ }
setenv("BBINITIALPATH", full_initial_path, 1);
-
tty_in = fopen("/dev/tty", "r");
tty_out = fopen("/dev/tty", "w");
tcgetattr(fileno(tty_out), &orig_termios);
@@ -1275,7 +1272,7 @@ int main(int argc, char *argv[])
strcpy(bb->columns, "*smpn");
strcpy(bb->sort, "+n");
if (populate_files(bb, full_initial_path))
- err("Not a valid path: %s", initial_path);
+ err("Could not find: \"%s\"", initial_path);
run_script(bb, runstartup);
write(cmdfd, "\0", 1);
diff --git a/bb.h b/bb.h
index c5378a9..1a3bd70 100644
--- a/bb.h
+++ b/bb.h
@@ -206,7 +206,7 @@ static int is_simple_bbcmd(const char *s);
static entry_t* load_entry(bb_t *bb, const char *path, int clear_dots);
static inline int matches_cmd(const char *str, const char *cmd);
static void* memcheck(void *p);
-static void normalize_path(const char *root, const char *path, char *pbuf, int clear_dots);
+static void normalize_path(const char *root, const char *path, char *pbuf);
static int populate_files(bb_t *bb, const char *path);
static void print_bindings(int fd);
static void run_bbcmd(bb_t *bb, const char *cmd);