From 561caf46dbd76221d98b8c3e55b96148794fad3c Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 06:05:30 +0000 Subject: [PATCH 001/268] Add the noice file browser --- Makefile | 9 ++ noice.c | 354 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 363 insertions(+) create mode 100644 Makefile create mode 100644 noice.c diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..922bf96d --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +#CPPFLAGS += -DDEBUG +#CFLAGS += -g +LDLIBS = -lncursesw +BIN = noice + +all: $(BIN) + +clean: + rm -f $(BIN) diff --git a/noice.c b/noice.c new file mode 100644 index 00000000..a399d24f --- /dev/null +++ b/noice.c @@ -0,0 +1,354 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +#define DPRINTF_D(x) printw(#x "=%d\n", x) +#define DPRINTF_S(x) printw(#x "=%s\n", x) +#define DPRINTF_P(x) printw(#x "=0x%p\n", x) +#else +#define DPRINTF_D(x) +#define DPRINTF_S(x) +#define DPRINTF_P(x) +#endif /* DEBUG */ + +#define LEN(x) (sizeof(x) / sizeof(*(x))) + +/* + * Layout: + * .--------- + * | cwd: /mnt/path + * | + * | > file0 + * | file1 + * ... + * | filen + * | + * | msg: invalid extension + * '------ + */ + +int die = 0; + +struct assoc { + char *ext; + char *bin; +} assocs[] = { + { "avi", "mplayer" }, + { "mp4", "mplayer" }, + { "mkv", "mplayer" }, + { "mp3", "mplayer" }, + { "ogg", "mplayer" }, + { "srt", "less" }, + { "txt", "less" }, +}; + +char * +extension(char *file) +{ + char *dot; + + dot = strrchr(file, '.'); + if (dot == NULL || dot == file) + return NULL; + else + return dot + 1; +} + +char * +openwith(char *ext) +{ + int i; + + for (i = 0; i < LEN(assocs); i++) + if (strncmp(assocs[i].ext, ext, strlen(ext)) == 0) + return assocs[i].bin; + return NULL; +} + +int +dentcmp(const void *va, const void *vb) +{ + const struct dirent *a, *b; + + a = *(struct dirent **)va; + b = *(struct dirent **)vb; + + return strcmp(a->d_name, b->d_name); +} + +/* Warning shows up at the bottom */ +void +printwarn(char *prefix) +{ + move(LINES - 1, 0); + printw("%s: %s\n", prefix, strerror(errno)); +} + +/* Kill curses and display error before exiting */ +void +printerr(int ret, char *prefix) +{ + endwin(); + printf("%s: %s\n", prefix, strerror(errno)); + exit(ret); +} + +/* + * Returns 0 normally + * On movement it updates *cur + * Returns 1 on quit + * Returns 2 on go in + * Returns 3 on go up + */ +int +nextsel(int *cur, int max) +{ + int c; + + c = getch(); + switch (c) { + case 'q': + return 1; + /* go up */ + case KEY_BACKSPACE: + case KEY_LEFT: + case 'h': + return 2; + /* go in */ + case KEY_ENTER: + case '\r': + case KEY_RIGHT: + case 'l': + return 3; + /* next */ + case 'j': + case KEY_DOWN: + if (*cur < max - 1) + (*cur)++; + break; + /* prev */ + case 'k': + case KEY_UP: + if (*cur > 0) + (*cur)--; + break; + } + + return 0; +} + +int +testopen(char *path) +{ + int fd; + + fd = open(path, O_RDONLY); + if (fd == -1) { + return 0; + } else { + close(fd); + return 1; + } +} + +int +testopendir(char *path) +{ + DIR *dirp; + + dirp = opendir(path); + if (dirp == NULL) { + return 0; + } else { + closedir(dirp); + return 1; + } +} + +void +browse(const char *ipath) +{ + DIR *dirp; + struct dirent *dp; + struct dirent **dents; + int i, n, cur; + int r, ret; + char *path = strdup(ipath); + +begin: + /* Path is a malloc(3)-ed string */ + n = 0; + cur = 0; + dents = NULL; + + dirp = opendir(path); + if (dirp == NULL) { + printwarn("opendir"); + goto nochange; + } + + while ((dp = readdir(dirp)) != NULL) { + /* Skip self and parent */ + if (strncmp(dp->d_name, ".", 2) == 0 + || strncmp(dp->d_name, "..", 3) == 0) + continue; + dents = realloc(dents, (n + 1) * sizeof(*dents)); + if (dents == NULL) + printerr(1, "realloc"); + dents[n] = dp; + n++; + } + + qsort(dents, n, sizeof(*dents), dentcmp); + + for (;;) { +redraw: + /* Clean screen */ + erase(); + + /* Strip slashes */ + for (i = strlen(path) - 1; i > -1; i--) + if (path[i] == '/') + path[i] = '\0'; + else + break; + + DPRINTF_D(cur); + DPRINTF_S(path); + + /* Print cwd */ + printw("cwd: %s%s\n\n", + strncmp(path, "", 1) == 0 ? "/" : "", + path); + + /* Print listing */ + for (i = 0; i < n; i++) + printw(" %s %s\n", + i == cur ? ">" : " ", + dents[i]->d_name); + +nochange: + ret = nextsel(&cur, n); + if (ret == 1) { + free(path); + return; + } + if (ret == 2) { + /* Handle root case */ + if (strncmp(path, "", 1) == 0) { + goto nochange; + } else { + path = dirname(path); + goto out; + } + } + if (ret == 3) { + char *name, *file = NULL; + char *newpath; + char *ext, *bin; + pid_t pid; + + name = dents[cur]->d_name; + + switch (dents[cur]->d_type) { + case DT_DIR: + newpath = malloc(strlen(path) + 1 + + strlen(name) + 1); + sprintf(newpath, "%s/%s", path, name); + if (testopen(newpath)) { + free(path); + path = newpath; + goto out; + } else { + printwarn(newpath); + free(newpath); + goto nochange; + } + case DT_REG: + file = malloc(strlen(path) + 1 + + strlen(name) + 1); + sprintf(file, "%s/%s", path, name); + DPRINTF_S(file); + + /* Open with */ + ext = extension(name); + if (ext == NULL) { + printwarn("invalid extension\n"); + goto nochange; + } + bin = openwith(ext); + if (bin == NULL) { + printwarn("no association\n"); + goto nochange; + } + DPRINTF_S(ext); + DPRINTF_S(bin); + + /* Run program */ + pid = fork(); + if (pid == 0) + execlp(bin, bin, file, NULL); + else + waitpid(pid, NULL, 0); + + free(file); + + /* Screen may be messed up */ + clear(); + /* Some programs reset this */ + keypad(stdscr, TRUE); + goto redraw; + default: + DPRINTF_D(dents[cur]->d_type); + } + } + } + +out: + free(dents); + + r = closedir(dirp); + if (r == -1) + printerr(1, "closedir"); + + goto begin; +} + +int +main(int argc, char *argv[]) +{ + char *ipath = argv[1] != NULL ? argv[1] : "/"; + + /* Test initial path */ + if (!testopendir(ipath)) + printerr(1, ipath); + + /* Set locale before curses setup */ + setlocale(LC_ALL, ""); + + /* Init curses */ + initscr(); + cbreak(); + noecho(); + nonl(); + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + curs_set(FALSE); /* Hide cursor */ + + browse(ipath); + + endwin(); /* Restore terminal */ + + return 0; +} From 4fa2a994499211ed558c8e6fea1cf623b5feaad4 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 06:49:46 +0000 Subject: [PATCH 002/268] Scrolling listing and dirname handling --- noice.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/noice.c b/noice.c index a399d24f..b241e20a 100644 --- a/noice.c +++ b/noice.c @@ -23,6 +23,7 @@ #endif /* DEBUG */ #define LEN(x) (sizeof(x) / sizeof(*(x))) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) /* * Layout: @@ -187,7 +188,7 @@ browse(const char *ipath) char *path = strdup(ipath); begin: - /* Path is a malloc(3)-ed string */ + /* Path should be a malloc(3)-ed string at all times */ n = 0; cur = 0; dents = NULL; @@ -213,6 +214,7 @@ begin: qsort(dents, n, sizeof(*dents), dentcmp); for (;;) { + int nlines = MIN(LINES - 4, n); redraw: /* Clean screen */ erase(); @@ -233,10 +235,22 @@ redraw: path); /* Print listing */ - for (i = 0; i < n; i++) - printw(" %s %s\n", - i == cur ? ">" : " ", - dents[i]->d_name); + if (cur < nlines / 2) { + for (i = 0; i < nlines; i++) + printw(" %s %s\n", + i == cur ? ">" : " ", + dents[i]->d_name); + } else if (cur >= n - nlines / 2) { + for (i = n - nlines; i < n; i++) + printw(" %s %s\n", + i == cur ? ">" : " ", + dents[i]->d_name); + } else { + for (i = cur - nlines / 2; i <= cur + nlines / 2; i++) + printw(" %s %s\n", + i == cur ? ">" : " ", + dents[i]->d_name); + } nochange: ret = nextsel(&cur, n); @@ -249,7 +263,13 @@ nochange: if (strncmp(path, "", 1) == 0) { goto nochange; } else { - path = dirname(path); + char *dir, *tmp; + + dir = dirname(path); + tmp = malloc(strlen(dir) + 1); + strncpy(tmp, dir, strlen(dir) + 1); + free(path); + path = tmp; goto out; } } From 4e818a3980ac2331d507773b51e7d0c8cfc899b5 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 11:23:44 +0000 Subject: [PATCH 003/268] Include lines calculation in redraw --- noice.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index b241e20a..062e26b7 100644 --- a/noice.c +++ b/noice.c @@ -214,8 +214,11 @@ begin: qsort(dents, n, sizeof(*dents), dentcmp); for (;;) { - int nlines = MIN(LINES - 4, n); + int nlines; + redraw: + nlines = MIN(LINES - 4, n); + /* Clean screen */ erase(); From fdf42ec50293a27f70f89ceddc84a98fe0e1d599 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 11:37:23 +0000 Subject: [PATCH 004/268] Exit curses mode while programs run --- noice.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/noice.c b/noice.c index 062e26b7..91a6a891 100644 --- a/noice.c +++ b/noice.c @@ -42,8 +42,8 @@ int die = 0; struct assoc { - char *ext; - char *bin; + char *ext; /* Extension */ + char *bin; /* Program */ } assocs[] = { { "avi", "mplayer" }, { "mp4", "mplayer" }, @@ -88,6 +88,25 @@ dentcmp(const void *va, const void *vb) return strcmp(a->d_name, b->d_name); } +void +initcurses(void) +{ + initscr(); + cbreak(); + noecho(); + nonl(); + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + curs_set(FALSE); /* Hide cursor */ +} + +void +exitcurses(void) +{ + endwin(); /* Restore terminal */ +} + + /* Warning shows up at the bottom */ void printwarn(char *prefix) @@ -318,6 +337,8 @@ nochange: DPRINTF_S(ext); DPRINTF_S(bin); + exitcurses(); + /* Run program */ pid = fork(); if (pid == 0) @@ -325,6 +346,8 @@ nochange: else waitpid(pid, NULL, 0); + initcurses(); + free(file); /* Screen may be messed up */ @@ -360,18 +383,11 @@ main(int argc, char *argv[]) /* Set locale before curses setup */ setlocale(LC_ALL, ""); - /* Init curses */ - initscr(); - cbreak(); - noecho(); - nonl(); - intrflush(stdscr, FALSE); - keypad(stdscr, TRUE); - curs_set(FALSE); /* Hide cursor */ + initcurses(); browse(ipath); - endwin(); /* Restore terminal */ + exitcurses(); return 0; } From 908e43cc67f29456bd1abbb0bd4eaa838b10eb8b Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 14:00:25 +0000 Subject: [PATCH 005/268] Take care of line wrapping and odd number of lines --- noice.c | 59 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/noice.c b/noice.c index 91a6a891..0acd4cba 100644 --- a/noice.c +++ b/noice.c @@ -24,6 +24,7 @@ #define LEN(x) (sizeof(x) / sizeof(*(x))) #define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define ISODD(x) ((x) & 1) /* * Layout: @@ -41,6 +42,10 @@ int die = 0; +struct entry { + char name[MAXNAMLEN + 1]; +}; + struct assoc { char *ext; /* Extension */ char *bin; /* Program */ @@ -205,6 +210,7 @@ browse(const char *ipath) int i, n, cur; int r, ret; char *path = strdup(ipath); + char *cwd; begin: /* Path should be a malloc(3)-ed string at all times */ @@ -234,6 +240,8 @@ begin: for (;;) { int nlines; + struct entry *tmpents; + int odd; redraw: nlines = MIN(LINES - 4, n); @@ -251,29 +259,50 @@ redraw: DPRINTF_D(cur); DPRINTF_S(path); +#define CWD "cwd: " +#define CURSR " > " +#define EMPTY " " + + /* No text wrapping in cwd line */ + cwd = malloc(COLS * sizeof(char)); + strncpy(cwd, path, COLS); + cwd[COLS - strlen(CWD) - 1] = '\0'; + + /* No text wrapping in entries */ + tmpents = malloc(n * sizeof(*tmpents)); + for (i = 0; i < n; i++) { + strncpy(tmpents[i].name, dents[i]->d_name, + sizeof(tmpents[i].name)); + tmpents[i].name[COLS - strlen(CURSR) - 1] = '\0'; + } + /* Print cwd */ - printw("cwd: %s%s\n\n", - strncmp(path, "", 1) == 0 ? "/" : "", - path); + printw(CWD "%s%s\n\n", + strncmp(cwd, "", 1) == 0 ? "/" : "", + cwd); /* Print listing */ + odd = ISODD(nlines); if (cur < nlines / 2) { for (i = 0; i < nlines; i++) - printw(" %s %s\n", - i == cur ? ">" : " ", - dents[i]->d_name); + printw("%s%s\n", + i == cur ? CURSR : EMPTY, + tmpents[i].name); } else if (cur >= n - nlines / 2) { for (i = n - nlines; i < n; i++) - printw(" %s %s\n", - i == cur ? ">" : " ", - dents[i]->d_name); + printw("%s%s\n", + i == cur ? CURSR : EMPTY, + tmpents[i].name); } else { - for (i = cur - nlines / 2; i <= cur + nlines / 2; i++) - printw(" %s %s\n", - i == cur ? ">" : " ", - dents[i]->d_name); + for (i = cur - nlines / 2; + i < cur + nlines / 2 + odd; i++) + printw("%s%s\n", + i == cur ? CURSR : EMPTY, + tmpents[i].name); } + free(tmpents); + nochange: ret = nextsel(&cur, n); if (ret == 1) { @@ -350,10 +379,6 @@ nochange: free(file); - /* Screen may be messed up */ - clear(); - /* Some programs reset this */ - keypad(stdscr, TRUE); goto redraw; default: DPRINTF_D(dents[cur]->d_type); From 4384f09726a3178ee6c9c38d0c357068d66140a2 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 14:07:56 +0000 Subject: [PATCH 006/268] Fix the empty dir bug --- noice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/noice.c b/noice.c index 0acd4cba..549eaa36 100644 --- a/noice.c +++ b/noice.c @@ -330,6 +330,10 @@ nochange: char *ext, *bin; pid_t pid; + /* Cannot descend in empty directories */ + if (n == 0) + goto nochange; + name = dents[cur]->d_name; switch (dents[cur]->d_type) { From a543eed112b4167c410a2fb75d672df9df926a1a Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 14:32:03 +0000 Subject: [PATCH 007/268] Simplify associations and handle README files --- noice.c | 55 +++++++++++++++++++++++-------------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/noice.c b/noice.c index 549eaa36..655ac39b 100644 --- a/noice.c +++ b/noice.c @@ -50,36 +50,34 @@ struct assoc { char *ext; /* Extension */ char *bin; /* Program */ } assocs[] = { - { "avi", "mplayer" }, - { "mp4", "mplayer" }, - { "mkv", "mplayer" }, - { "mp3", "mplayer" }, - { "ogg", "mplayer" }, - { "srt", "less" }, - { "txt", "less" }, + { ".avi", "mplayer" }, + { ".mp4", "mplayer" }, + { ".mkv", "mplayer" }, + { ".mp3", "mplayer" }, + { ".ogg", "mplayer" }, + { ".srt", "less" }, + { ".txt", "less" }, + { "README", "less" }, }; char * -extension(char *file) -{ - char *dot; - - dot = strrchr(file, '.'); - if (dot == NULL || dot == file) - return NULL; - else - return dot + 1; -} - -char * -openwith(char *ext) +openwith(char *file) { + char *ext = NULL; + char *bin = NULL; int i; + ext = strrchr(file, '.'); + if (ext == NULL) + ext = file; + DPRINTF_S(ext); + for (i = 0; i < LEN(assocs); i++) - if (strncmp(assocs[i].ext, ext, strlen(ext)) == 0) - return assocs[i].bin; - return NULL; + if (strncmp(assocs[i].ext, ext, strlen(ext) + 1) == 0) + bin = assocs[i].bin; + DPRINTF_S(bin); + + return bin; } int @@ -327,7 +325,7 @@ nochange: if (ret == 3) { char *name, *file = NULL; char *newpath; - char *ext, *bin; + char *bin; pid_t pid; /* Cannot descend in empty directories */ @@ -357,18 +355,11 @@ nochange: DPRINTF_S(file); /* Open with */ - ext = extension(name); - if (ext == NULL) { - printwarn("invalid extension\n"); - goto nochange; - } - bin = openwith(ext); + bin = openwith(name); if (bin == NULL) { printwarn("no association\n"); goto nochange; } - DPRINTF_S(ext); - DPRINTF_S(bin); exitcurses(); From 9acdb3332b9c1e1fc0af8d1453dad0aa3b155e62 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 14:47:35 +0000 Subject: [PATCH 008/268] Rework messages and errno warnings --- noice.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/noice.c b/noice.c index 655ac39b..224625b5 100644 --- a/noice.c +++ b/noice.c @@ -109,13 +109,19 @@ exitcurses(void) endwin(); /* Restore terminal */ } - -/* Warning shows up at the bottom */ +/* Messages show up at the bottom */ void -printwarn(char *prefix) +printmsg(char *msg) { move(LINES - 1, 0); - printw("%s: %s\n", prefix, strerror(errno)); + printw("%s\n", msg); +} + +/* Display warning as a message */ +void +printwarn(void) +{ + printmsg(strerror(errno)); } /* Kill curses and display error before exiting */ @@ -218,7 +224,7 @@ begin: dirp = opendir(path); if (dirp == NULL) { - printwarn("opendir"); + printwarn(); goto nochange; } @@ -344,7 +350,7 @@ nochange: path = newpath; goto out; } else { - printwarn(newpath); + printwarn(); free(newpath); goto nochange; } @@ -357,7 +363,7 @@ nochange: /* Open with */ bin = openwith(name); if (bin == NULL) { - printwarn("no association\n"); + printmsg("No association"); goto nochange; } From 88fd8fcf8b325cb5c5e6cb0a5553537039a10690 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 14:55:14 +0000 Subject: [PATCH 009/268] Get layout comment in sync --- noice.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 224625b5..e2ec37df 100644 --- a/noice.c +++ b/noice.c @@ -31,12 +31,15 @@ * .--------- * | cwd: /mnt/path * | - * | > file0 + * | file0 * | file1 + * | > file2 + * | file3 + * | file4 * ... * | filen * | - * | msg: invalid extension + * | Permission denied * '------ */ From 10d2d18cb244d76862b508d7dffa65c6a5147040 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 15:36:29 +0000 Subject: [PATCH 010/268] Reorder configuration stuff --- noice.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/noice.c b/noice.c index e2ec37df..3e735fe2 100644 --- a/noice.c +++ b/noice.c @@ -26,6 +26,27 @@ #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define ISODD(x) ((x) & 1) +struct assoc { + char *ext; /* Extension */ + char *bin; /* Program */ +}; + +/* Configuration */ +struct assoc assocs[] = { + { ".avi", "mplayer" }, + { ".mp4", "mplayer" }, + { ".mkv", "mplayer" }, + { ".mp3", "mplayer" }, + { ".ogg", "mplayer" }, + { ".srt", "less" }, + { ".txt", "less" }, + { "README", "less" }, +}; + +#define CWD "cwd: " +#define CURSR " > " +#define EMPTY " " + /* * Layout: * .--------- @@ -49,20 +70,6 @@ struct entry { char name[MAXNAMLEN + 1]; }; -struct assoc { - char *ext; /* Extension */ - char *bin; /* Program */ -} assocs[] = { - { ".avi", "mplayer" }, - { ".mp4", "mplayer" }, - { ".mkv", "mplayer" }, - { ".mp3", "mplayer" }, - { ".ogg", "mplayer" }, - { ".srt", "less" }, - { ".txt", "less" }, - { "README", "less" }, -}; - char * openwith(char *file) { @@ -266,10 +273,6 @@ redraw: DPRINTF_D(cur); DPRINTF_S(path); -#define CWD "cwd: " -#define CURSR " > " -#define EMPTY " " - /* No text wrapping in cwd line */ cwd = malloc(COLS * sizeof(char)); strncpy(cwd, path, COLS); From 1475ebbf9a5166bed3946707a113a93552e385c3 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 20:59:41 +0300 Subject: [PATCH 011/268] Be consistent on exiting curses mode --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 3e735fe2..0f8e61f2 100644 --- a/noice.c +++ b/noice.c @@ -138,7 +138,7 @@ printwarn(void) void printerr(int ret, char *prefix) { - endwin(); + exitcurses(); printf("%s: %s\n", prefix, strerror(errno)); exit(ret); } From c5e5a19d0f3a8a2180f924beedcbb272073de218 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 7 Oct 2014 21:02:58 +0300 Subject: [PATCH 012/268] Comment on the multiple slashes handling logic --- noice.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 0f8e61f2..90680d19 100644 --- a/noice.c +++ b/noice.c @@ -263,7 +263,7 @@ redraw: /* Clean screen */ erase(); - /* Strip slashes */ + /* Strip trailing slashes */ for (i = strlen(path) - 1; i > -1; i--) if (path[i] == '/') path[i] = '\0'; @@ -286,7 +286,9 @@ redraw: tmpents[i].name[COLS - strlen(CURSR) - 1] = '\0'; } - /* Print cwd */ + /* Print cwd. If empty we are on the root. We store it + * as an empty string so that when we navigate in /mnt + * is doesn't come up as //mnt. */ printw(CWD "%s%s\n\n", strncmp(cwd, "", 1) == 0 ? "/" : "", cwd); From 0deba427a92c654253d66cf84ba88f56ccd7b589 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 10:52:44 +0300 Subject: [PATCH 013/268] Support symbolic links and fix message reporting --- noice.c | 72 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/noice.c b/noice.c index 90680d19..4289300d 100644 --- a/noice.c +++ b/noice.c @@ -1,3 +1,4 @@ +#include #include #include @@ -337,37 +338,73 @@ nochange: } } if (ret == 3) { - char *name, *file = NULL; - char *newpath; + char *pathnew, *pathtmp; + char *name; + u_int8_t type; char *bin; pid_t pid; + struct stat sb; /* Cannot descend in empty directories */ if (n == 0) goto nochange; name = dents[cur]->d_name; + type = dents[cur]->d_type; - switch (dents[cur]->d_type) { + pathnew = malloc(strlen(path) + 1 + + strlen(name) + 1); + sprintf(pathnew, "%s/%s", path, name); + DPRINTF_S(pathnew); + +again: + switch (type) { + case DT_LNK: + /* Resolve link */ + pathtmp = realpath(pathnew, NULL); + if (pathtmp == NULL) { + printwarn(); + free(pathnew); + goto nochange; + } else { + r = stat(pathtmp, &sb); + free(pathtmp); + if (r == -1) { + printwarn(); + free(pathnew); + goto nochange; + } + /* Directory or file */ + if (S_ISDIR(sb.st_mode)) { + type = DT_DIR; + goto again; + } + if (S_ISREG(sb.st_mode)) { + type = DT_REG; + goto again; + } + /* All the rest */ + printmsg("Unsupported file"); + free(pathnew); + goto nochange; + } case DT_DIR: - newpath = malloc(strlen(path) + 1 - + strlen(name) + 1); - sprintf(newpath, "%s/%s", path, name); - if (testopen(newpath)) { + /* Change to new path */ + if (testopen(pathnew)) { free(path); - path = newpath; + path = pathnew; goto out; } else { printwarn(); - free(newpath); + free(pathnew); goto nochange; } case DT_REG: - file = malloc(strlen(path) + 1 - + strlen(name) + 1); - sprintf(file, "%s/%s", path, name); - DPRINTF_S(file); - + if (!testopen(pathnew)) { + printwarn(); + free(pathnew); + goto nochange; + } /* Open with */ bin = openwith(name); if (bin == NULL) { @@ -380,17 +417,18 @@ nochange: /* Run program */ pid = fork(); if (pid == 0) - execlp(bin, bin, file, NULL); + execlp(bin, bin, pathnew, NULL); else waitpid(pid, NULL, 0); initcurses(); - free(file); - + free(pathnew); goto redraw; default: DPRINTF_D(dents[cur]->d_type); + printmsg("Unsupported file"); + goto nochange; } } } From da09d92b25a3da5d763e1365cb33fe6b72fb2e79 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 11:36:17 +0300 Subject: [PATCH 014/268] Use dprintf(3) for debugging --- noice.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 4289300d..9712f803 100644 --- a/noice.c +++ b/noice.c @@ -14,11 +14,14 @@ #include #ifdef DEBUG -#define DPRINTF_D(x) printw(#x "=%d\n", x) -#define DPRINTF_S(x) printw(#x "=%s\n", x) -#define DPRINTF_P(x) printw(#x "=0x%p\n", x) +#define DEBUG_FD 8 +#define DPRINTF_D(x) dprintf(DEBUG_FD, #x "=%d\n", x) +#define DPRINTF_U(x) dprintf(DEBUG_FD, #x "=%u\n", x) +#define DPRINTF_S(x) dprintf(DEBUG_FD, #x "=%s\n", x) +#define DPRINTF_P(x) dprintf(DEBUG_FD, #x "=0x%p\n", x) #else #define DPRINTF_D(x) +#define DPRINTF_U(x) #define DPRINTF_S(x) #define DPRINTF_P(x) #endif /* DEBUG */ @@ -355,6 +358,9 @@ nochange: pathnew = malloc(strlen(path) + 1 + strlen(name) + 1); sprintf(pathnew, "%s/%s", path, name); + + DPRINTF_S(name); + DPRINTF_U(type); DPRINTF_S(pathnew); again: @@ -426,7 +432,6 @@ again: free(pathnew); goto redraw; default: - DPRINTF_D(dents[cur]->d_type); printmsg("Unsupported file"); goto nochange; } From f56dec0a4f24de60f85199b95691852a79a349b2 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 11:43:11 +0300 Subject: [PATCH 015/268] Shell scripts may be useful --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index 9712f803..0e6a000a 100644 --- a/noice.c +++ b/noice.c @@ -44,6 +44,7 @@ struct assoc assocs[] = { { ".ogg", "mplayer" }, { ".srt", "less" }, { ".txt", "less" }, + { ".sh", "sh" }, { "README", "less" }, }; From 1734a96745f54c4b53a0adef2ca03d9389339314 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 14:57:22 +0300 Subject: [PATCH 016/268] No need for strncmp(3), use strcmp(3) instead --- noice.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index 0e6a000a..c69e85ee 100644 --- a/noice.c +++ b/noice.c @@ -88,7 +88,7 @@ openwith(char *file) DPRINTF_S(ext); for (i = 0; i < LEN(assocs); i++) - if (strncmp(assocs[i].ext, ext, strlen(ext) + 1) == 0) + if (strcmp(assocs[i].ext, ext) == 0) bin = assocs[i].bin; DPRINTF_S(bin); @@ -245,8 +245,8 @@ begin: while ((dp = readdir(dirp)) != NULL) { /* Skip self and parent */ - if (strncmp(dp->d_name, ".", 2) == 0 - || strncmp(dp->d_name, "..", 3) == 0) + if (strcmp(dp->d_name, ".") == 0 + || strcmp(dp->d_name, "..") == 0) continue; dents = realloc(dents, (n + 1) * sizeof(*dents)); if (dents == NULL) @@ -295,7 +295,7 @@ redraw: * as an empty string so that when we navigate in /mnt * is doesn't come up as //mnt. */ printw(CWD "%s%s\n\n", - strncmp(cwd, "", 1) == 0 ? "/" : "", + strcmp(cwd, "") == 0 ? "/" : "", cwd); /* Print listing */ @@ -328,7 +328,7 @@ nochange: } if (ret == 2) { /* Handle root case */ - if (strncmp(path, "", 1) == 0) { + if (strcmp(path, "") == 0) { goto nochange; } else { char *dir, *tmp; From b6c43f66a9adeb7e3f19d6cffc9c14abf60dd855 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 15:08:29 +0300 Subject: [PATCH 017/268] Change string copies to use strlcpy(3) --- Makefile | 1 + noice.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 922bf96d..c2cdcad1 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ #CPPFLAGS += -DDEBUG #CFLAGS += -g LDLIBS = -lncursesw +#LDLIBS += -lbsd BIN = noice all: $(BIN) diff --git a/noice.c b/noice.c index c69e85ee..656ec8f6 100644 --- a/noice.c +++ b/noice.c @@ -13,6 +13,10 @@ #include #include +#ifdef LINUX +#include +#endif + #ifdef DEBUG #define DEBUG_FD 8 #define DPRINTF_D(x) dprintf(DEBUG_FD, #x "=%d\n", x) @@ -280,13 +284,13 @@ redraw: /* No text wrapping in cwd line */ cwd = malloc(COLS * sizeof(char)); - strncpy(cwd, path, COLS); + strlcpy(cwd, path, COLS * sizeof(char)); cwd[COLS - strlen(CWD) - 1] = '\0'; /* No text wrapping in entries */ tmpents = malloc(n * sizeof(*tmpents)); for (i = 0; i < n; i++) { - strncpy(tmpents[i].name, dents[i]->d_name, + strlcpy(tmpents[i].name, dents[i]->d_name, sizeof(tmpents[i].name)); tmpents[i].name[COLS - strlen(CURSR) - 1] = '\0'; } @@ -335,7 +339,7 @@ nochange: dir = dirname(path); tmp = malloc(strlen(dir) + 1); - strncpy(tmp, dir, strlen(dir) + 1); + strlcpy(tmp, dir, strlen(dir) + 1); free(path); path = tmp; goto out; From 4b56e4a122c9c16d00f459a992496423e2abce63 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 15:14:11 +0300 Subject: [PATCH 018/268] Avoid sprintf(3) and use snprintf(3) instead --- noice.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 656ec8f6..eed91895 100644 --- a/noice.c +++ b/noice.c @@ -347,6 +347,7 @@ nochange: } if (ret == 3) { char *pathnew, *pathtmp; + size_t pathsiz; char *name; u_int8_t type; char *bin; @@ -360,9 +361,9 @@ nochange: name = dents[cur]->d_name; type = dents[cur]->d_type; - pathnew = malloc(strlen(path) + 1 - + strlen(name) + 1); - sprintf(pathnew, "%s/%s", path, name); + pathsiz = strlen(path) + 1 + strlen(name) + 1; + pathnew = malloc(pathsiz); + snprintf(pathnew, pathsiz, "%s/%s", path, name); DPRINTF_S(name); DPRINTF_U(type); From bc766bc4a88accf873d9ec29e7c274804065a916 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 15:27:46 +0300 Subject: [PATCH 019/268] Fix memory leaks --- noice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/noice.c b/noice.c index eed91895..9c6aac58 100644 --- a/noice.c +++ b/noice.c @@ -421,6 +421,7 @@ again: bin = openwith(name); if (bin == NULL) { printmsg("No association"); + free(pathnew); goto nochange; } @@ -439,6 +440,7 @@ again: goto redraw; default: printmsg("Unsupported file"); + free(pathnew); goto nochange; } } From 7028eb1838e43ec695e9a1421c264bc5e64f2ac1 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 15:50:39 +0300 Subject: [PATCH 020/268] Keep local copies of dir entries, just keeping pointers was a bug --- noice.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/noice.c b/noice.c index 9c6aac58..08cc105e 100644 --- a/noice.c +++ b/noice.c @@ -75,10 +75,6 @@ struct assoc assocs[] = { int die = 0; -struct entry { - char name[MAXNAMLEN + 1]; -}; - char * openwith(char *file) { @@ -104,8 +100,8 @@ dentcmp(const void *va, const void *vb) { const struct dirent *a, *b; - a = *(struct dirent **)va; - b = *(struct dirent **)vb; + a = (struct dirent *)va; + b = (struct dirent *)vb; return strcmp(a->d_name, b->d_name); } @@ -229,7 +225,7 @@ browse(const char *ipath) { DIR *dirp; struct dirent *dp; - struct dirent **dents; + struct dirent *dents; int i, n, cur; int r, ret; char *path = strdup(ipath); @@ -255,7 +251,7 @@ begin: dents = realloc(dents, (n + 1) * sizeof(*dents)); if (dents == NULL) printerr(1, "realloc"); - dents[n] = dp; + memcpy(&dents[n], dp, sizeof(*dents)); n++; } @@ -263,7 +259,7 @@ begin: for (;;) { int nlines; - struct entry *tmpents; + struct dirent *tmpents; int odd; redraw: @@ -289,11 +285,9 @@ redraw: /* No text wrapping in entries */ tmpents = malloc(n * sizeof(*tmpents)); - for (i = 0; i < n; i++) { - strlcpy(tmpents[i].name, dents[i]->d_name, - sizeof(tmpents[i].name)); - tmpents[i].name[COLS - strlen(CURSR) - 1] = '\0'; - } + memcpy(tmpents, dents, n * sizeof(*tmpents)); + for (i = 0; i < n; i++) + tmpents[i].d_name[COLS - strlen(CURSR) - 1] = '\0'; /* Print cwd. If empty we are on the root. We store it * as an empty string so that when we navigate in /mnt @@ -308,18 +302,18 @@ redraw: for (i = 0; i < nlines; i++) printw("%s%s\n", i == cur ? CURSR : EMPTY, - tmpents[i].name); + tmpents[i].d_name); } else if (cur >= n - nlines / 2) { for (i = n - nlines; i < n; i++) printw("%s%s\n", i == cur ? CURSR : EMPTY, - tmpents[i].name); + tmpents[i].d_name); } else { for (i = cur - nlines / 2; i < cur + nlines / 2 + odd; i++) printw("%s%s\n", i == cur ? CURSR : EMPTY, - tmpents[i].name); + tmpents[i].d_name); } free(tmpents); @@ -358,8 +352,8 @@ nochange: if (n == 0) goto nochange; - name = dents[cur]->d_name; - type = dents[cur]->d_type; + name = dents[cur].d_name; + type = dents[cur].d_type; pathsiz = strlen(path) + 1 + strlen(name) + 1; pathnew = malloc(pathsiz); From 3459f6a5e79b1cd248185a7562565a851cea57ab Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 17:59:35 +0300 Subject: [PATCH 021/268] Use asprintf(3) and avoid manual allocation --- noice.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 08cc105e..88741485 100644 --- a/noice.c +++ b/noice.c @@ -341,7 +341,6 @@ nochange: } if (ret == 3) { char *pathnew, *pathtmp; - size_t pathsiz; char *name; u_int8_t type; char *bin; @@ -355,9 +354,7 @@ nochange: name = dents[cur].d_name; type = dents[cur].d_type; - pathsiz = strlen(path) + 1 + strlen(name) + 1; - pathnew = malloc(pathsiz); - snprintf(pathnew, pathsiz, "%s/%s", path, name); + asprintf(&pathnew, "%s/%s", path, name); DPRINTF_S(name); DPRINTF_U(type); From 6b51ec45854bea03a344e77a2cedff9df062cb78 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 18:30:39 +0300 Subject: [PATCH 022/268] Use open(2)/fstat(2) and don't bother with links at all --- noice.c | 99 +++++++++++++++++---------------------------------------- 1 file changed, 29 insertions(+), 70 deletions(-) diff --git a/noice.c b/noice.c index 88741485..07f2f78d 100644 --- a/noice.c +++ b/noice.c @@ -192,20 +192,6 @@ nextsel(int *cur, int max) return 0; } -int -testopen(char *path) -{ - int fd; - - fd = open(path, O_RDONLY); - if (fd == -1) { - return 0; - } else { - close(fd); - return 1; - } -} - int testopendir(char *path) { @@ -340,11 +326,11 @@ nochange: } } if (ret == 3) { - char *pathnew, *pathtmp; + char *pathnew; char *name; - u_int8_t type; char *bin; pid_t pid; + int fd; struct stat sb; /* Cannot descend in empty directories */ @@ -352,62 +338,35 @@ nochange: goto nochange; name = dents[cur].d_name; - type = dents[cur].d_type; asprintf(&pathnew, "%s/%s", path, name); DPRINTF_S(name); - DPRINTF_U(type); DPRINTF_S(pathnew); -again: - switch (type) { - case DT_LNK: - /* Resolve link */ - pathtmp = realpath(pathnew, NULL); - if (pathtmp == NULL) { - printwarn(); - free(pathnew); - goto nochange; - } else { - r = stat(pathtmp, &sb); - free(pathtmp); - if (r == -1) { - printwarn(); - free(pathnew); - goto nochange; - } - /* Directory or file */ - if (S_ISDIR(sb.st_mode)) { - type = DT_DIR; - goto again; - } - if (S_ISREG(sb.st_mode)) { - type = DT_REG; - goto again; - } - /* All the rest */ - printmsg("Unsupported file"); - free(pathnew); - goto nochange; - } - case DT_DIR: - /* Change to new path */ - if (testopen(pathnew)) { - free(path); - path = pathnew; - goto out; - } else { - printwarn(); - free(pathnew); - goto nochange; - } - case DT_REG: - if (!testopen(pathnew)) { - printwarn(); - free(pathnew); - goto nochange; - } + /* Get path info */ + fd = open(pathnew, O_RDONLY | O_NONBLOCK); + if (fd == -1) { + printwarn(); + free(pathnew); + goto nochange; + } + r = fstat(fd, &sb); + close(fd); + DPRINTF_U(sb.st_mode); + if (r == -1) { + printwarn(); + free(pathnew); + goto nochange; + } + /* Directory */ + if (S_ISDIR(sb.st_mode)) { + free(path); + path = pathnew; + goto out; + } + /* Regular file */ + if (S_ISREG(sb.st_mode)) { /* Open with */ bin = openwith(name); if (bin == NULL) { @@ -429,11 +388,11 @@ again: free(pathnew); goto redraw; - default: - printmsg("Unsupported file"); - free(pathnew); - goto nochange; } + /* All the rest */ + printmsg("Unsupported file"); + free(pathnew); + goto nochange; } } From 0b0869ab44c3622826d183ea8ff12e5f29a1ce49 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 18:37:55 +0300 Subject: [PATCH 023/268] Move debug print after return value check --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 07f2f78d..e61e8201 100644 --- a/noice.c +++ b/noice.c @@ -353,12 +353,12 @@ nochange: } r = fstat(fd, &sb); close(fd); - DPRINTF_U(sb.st_mode); if (r == -1) { printwarn(); free(pathnew); goto nochange; } + DPRINTF_U(sb.st_mode); /* Directory */ if (S_ISDIR(sb.st_mode)) { free(path); From 973aff99b713d300b5b5a17847960707c675702c Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 18:39:07 +0300 Subject: [PATCH 024/268] Strip redundant spaces --- noice.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index e61e8201..8d6f0d75 100644 --- a/noice.c +++ b/noice.c @@ -223,7 +223,7 @@ begin: cur = 0; dents = NULL; - dirp = opendir(path); + dirp = opendir(path); if (dirp == NULL) { printwarn(); goto nochange; @@ -365,7 +365,7 @@ nochange: path = pathnew; goto out; } - /* Regular file */ + /* Regular file */ if (S_ISREG(sb.st_mode)) { /* Open with */ bin = openwith(name); @@ -399,7 +399,7 @@ nochange: out: free(dents); - r = closedir(dirp); + r = closedir(dirp); if (r == -1) printerr(1, "closedir"); From 368b43572d3017542b2c2f056b196a4f7c79820f Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 8 Oct 2014 22:55:44 +0300 Subject: [PATCH 025/268] Comment on dirents deep copy --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index 8d6f0d75..66d856bc 100644 --- a/noice.c +++ b/noice.c @@ -234,6 +234,7 @@ begin: if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; + /* Deep copy because readdir(3) reuses the entries */ dents = realloc(dents, (n + 1) * sizeof(*dents)); if (dents == NULL) printerr(1, "realloc"); From 46669d7606e7e763f63aa7b2533291a3699d5911 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 9 Oct 2014 10:33:49 +0100 Subject: [PATCH 026/268] Add regex support --- noice.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/noice.c b/noice.c index 66d856bc..60dbfbd6 100644 --- a/noice.c +++ b/noice.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -35,21 +36,17 @@ #define ISODD(x) ((x) & 1) struct assoc { - char *ext; /* Extension */ - char *bin; /* Program */ + char *regex; /* Regex to match on filename */ + char *bin; /* Program */ }; /* Configuration */ struct assoc assocs[] = { - { ".avi", "mplayer" }, - { ".mp4", "mplayer" }, - { ".mkv", "mplayer" }, - { ".mp3", "mplayer" }, - { ".ogg", "mplayer" }, - { ".srt", "less" }, - { ".txt", "less" }, - { ".sh", "sh" }, - { "README", "less" }, + { ".(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, + { ".srt$", "less" }, + { ".txt$", "less" }, + { ".sh$", "sh" }, + { "^README$", "less" }, }; #define CWD "cwd: " @@ -78,18 +75,19 @@ int die = 0; char * openwith(char *file) { - char *ext = NULL; + regex_t regex; char *bin = NULL; int i; - ext = strrchr(file, '.'); - if (ext == NULL) - ext = file; - DPRINTF_S(ext); - - for (i = 0; i < LEN(assocs); i++) - if (strcmp(assocs[i].ext, ext) == 0) + for (i = 0; i < LEN(assocs); i++) { + if (regcomp(®ex, assocs[i].regex, + REG_NOSUB | REG_EXTENDED) != 0) + continue; + if (regexec(®ex, file, 0, NULL, 0) != REG_NOMATCH) { bin = assocs[i].bin; + break; + } + } DPRINTF_S(bin); return bin; From ee8898547cb4ddab3724c8df0d3c4e18c79beab6 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 9 Oct 2014 16:23:12 +0300 Subject: [PATCH 027/268] Use our own entry struct instead of dirent --- noice.c | 65 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/noice.c b/noice.c index 60dbfbd6..ad89bc95 100644 --- a/noice.c +++ b/noice.c @@ -49,6 +49,11 @@ struct assoc assocs[] = { { "^README$", "less" }, }; +struct entry { + char *name; + mode_t mode; +}; + #define CWD "cwd: " #define CURSR " > " #define EMPTY " " @@ -94,14 +99,14 @@ openwith(char *file) } int -dentcmp(const void *va, const void *vb) +entrycmp(const void *va, const void *vb) { - const struct dirent *a, *b; + const struct entry *a, *b; - a = (struct dirent *)va; - b = (struct dirent *)vb; + a = (struct entry *)va; + b = (struct entry *)vb; - return strcmp(a->d_name, b->d_name); + return strcmp(a->name, b->name); } void @@ -208,12 +213,14 @@ void browse(const char *ipath) { DIR *dirp; + int dfd; struct dirent *dp; - struct dirent *dents; + struct entry *dents; int i, n, cur; int r, ret; char *path = strdup(ipath); char *cwd; + struct stat sb; begin: /* Path should be a malloc(3)-ed string at all times */ @@ -226,8 +233,13 @@ begin: printwarn(); goto nochange; } + dfd = dirfd(dirp); + if (dfd == -1) + printerr(1, "dirfd"); while ((dp = readdir(dirp)) != NULL) { + char *name; + /* Skip self and parent */ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) @@ -236,15 +248,23 @@ begin: dents = realloc(dents, (n + 1) * sizeof(*dents)); if (dents == NULL) printerr(1, "realloc"); - memcpy(&dents[n], dp, sizeof(*dents)); + dents[n].name = strdup(dp->d_name); + if (dents[n].name == NULL) + printerr(1, "strdup"); + /* Get mode flags */ + r = fstatat(dfd, dents[n].name, &sb, 0); + if (r == -1) + printerr(1, "stat"); + dents[n].mode = sb.st_mode; n++; } - qsort(dents, n, sizeof(*dents), dentcmp); + qsort(dents, n, sizeof(*dents), entrycmp); for (;;) { int nlines; - struct dirent *tmpents; + struct entry *tmpents; + int maxlen; int odd; redraw: @@ -270,9 +290,17 @@ redraw: /* No text wrapping in entries */ tmpents = malloc(n * sizeof(*tmpents)); - memcpy(tmpents, dents, n * sizeof(*tmpents)); - for (i = 0; i < n; i++) - tmpents[i].d_name[COLS - strlen(CURSR) - 1] = '\0'; + maxlen = COLS - strlen(CURSR) - 1; + for (i = 0; i < n; i++) { + struct entry *tmpent = &tmpents[i]; + + tmpent->name = strdup(dents[i].name); + if (tmpent->name == NULL) + printerr(1, "strdup tmp"); + tmpent->mode = dents[i].mode; + if (strlen(tmpent->name) > maxlen) + tmpent->name[maxlen] = '\0'; + } /* Print cwd. If empty we are on the root. We store it * as an empty string so that when we navigate in /mnt @@ -287,20 +315,22 @@ redraw: for (i = 0; i < nlines; i++) printw("%s%s\n", i == cur ? CURSR : EMPTY, - tmpents[i].d_name); + tmpents[i].name); } else if (cur >= n - nlines / 2) { for (i = n - nlines; i < n; i++) printw("%s%s\n", i == cur ? CURSR : EMPTY, - tmpents[i].d_name); + tmpents[i].name); } else { for (i = cur - nlines / 2; i < cur + nlines / 2 + odd; i++) printw("%s%s\n", i == cur ? CURSR : EMPTY, - tmpents[i].d_name); + tmpents[i].name); } + for (i = 0; i < n; i++) + free(tmpents[i].name); free(tmpents); nochange: @@ -330,13 +360,12 @@ nochange: char *bin; pid_t pid; int fd; - struct stat sb; /* Cannot descend in empty directories */ if (n == 0) goto nochange; - name = dents[cur].d_name; + name = dents[cur].name; asprintf(&pathnew, "%s/%s", path, name); @@ -396,6 +425,8 @@ nochange: } out: + for (i = 0; i < n; i++) + free(dents[i].name); free(dents); r = closedir(dirp); From 0e2ea28a3097ed98c96042cd32dc6d7ef72abc7b Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 9 Oct 2014 17:07:21 +0300 Subject: [PATCH 028/268] Printing and line wrapping in a function, show dirs and links --- noice.c | 70 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/noice.c b/noice.c index ad89bc95..79043674 100644 --- a/noice.c +++ b/noice.c @@ -209,6 +209,38 @@ testopendir(char *path) } } +void +printent(struct entry *ent, int active) +{ + char *name; + unsigned int maxlen = COLS - strlen(CURSR) - 1; + char cm = 0; + + /* Copy name locally */ + name = strdup(ent->name); + if (name == NULL) + printerr(1, "strdup name"); + + if (S_ISDIR(ent->mode)) { + cm = '/'; + maxlen--; + } else if (S_ISLNK(ent->mode)) { + cm = '@'; + maxlen--; + } + + /* No text wrapping in entries */ + if (strlen(name) > maxlen) + name[maxlen] = '\0'; + + if (cm == 0) + printw("%s%s\n", active ? CURSR : EMPTY, name); + else + printw("%s%s%c\n", active ? CURSR : EMPTY, name, cm); + + free(name); +} + void browse(const char *ipath) { @@ -233,9 +265,6 @@ begin: printwarn(); goto nochange; } - dfd = dirfd(dirp); - if (dfd == -1) - printerr(1, "dirfd"); while ((dp = readdir(dirp)) != NULL) { char *name; @@ -252,7 +281,9 @@ begin: if (dents[n].name == NULL) printerr(1, "strdup"); /* Get mode flags */ - r = fstatat(dfd, dents[n].name, &sb, 0); + asprintf(&name, "%s/%s", path, dents[n].name); + r = lstat(name, &sb); + free(name); if (r == -1) printerr(1, "stat"); dents[n].mode = sb.st_mode; @@ -263,7 +294,6 @@ begin: for (;;) { int nlines; - struct entry *tmpents; int maxlen; int odd; @@ -288,20 +318,6 @@ redraw: strlcpy(cwd, path, COLS * sizeof(char)); cwd[COLS - strlen(CWD) - 1] = '\0'; - /* No text wrapping in entries */ - tmpents = malloc(n * sizeof(*tmpents)); - maxlen = COLS - strlen(CURSR) - 1; - for (i = 0; i < n; i++) { - struct entry *tmpent = &tmpents[i]; - - tmpent->name = strdup(dents[i].name); - if (tmpent->name == NULL) - printerr(1, "strdup tmp"); - tmpent->mode = dents[i].mode; - if (strlen(tmpent->name) > maxlen) - tmpent->name[maxlen] = '\0'; - } - /* Print cwd. If empty we are on the root. We store it * as an empty string so that when we navigate in /mnt * is doesn't come up as //mnt. */ @@ -313,26 +329,16 @@ redraw: odd = ISODD(nlines); if (cur < nlines / 2) { for (i = 0; i < nlines; i++) - printw("%s%s\n", - i == cur ? CURSR : EMPTY, - tmpents[i].name); + printent(&dents[i], i == cur); } else if (cur >= n - nlines / 2) { for (i = n - nlines; i < n; i++) - printw("%s%s\n", - i == cur ? CURSR : EMPTY, - tmpents[i].name); + printent(&dents[i], i == cur); } else { for (i = cur - nlines / 2; i < cur + nlines / 2 + odd; i++) - printw("%s%s\n", - i == cur ? CURSR : EMPTY, - tmpents[i].name); + printent(&dents[i], i == cur); } - for (i = 0; i < n; i++) - free(tmpents[i].name); - free(tmpents); - nochange: ret = nextsel(&cur, n); if (ret == 1) { From 51253b056474cf261c3b8c6af936f100d0aa39b5 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 9 Oct 2014 15:23:16 +0100 Subject: [PATCH 029/268] Add support a default association --- noice.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 79043674..a1d488f4 100644 --- a/noice.c +++ b/noice.c @@ -42,11 +42,12 @@ struct assoc { /* Configuration */ struct assoc assocs[] = { - { ".(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, - { ".srt$", "less" }, - { ".txt$", "less" }, - { ".sh$", "sh" }, + { "\\.(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, + { "\\.srt$", "less" }, + { "\\.txt$", "less" }, + { "\\.sh$", "sh" }, { "^README$", "less" }, + { ".*", "less" }, }; struct entry { From ac2a7e2788517aeddcdbe3bc05198e6073de94db Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 9 Oct 2014 17:43:31 +0300 Subject: [PATCH 030/268] Add license and todo files --- LICENSE | 24 ++++++++++++++++++++++++ TODO | 3 +++ 2 files changed, 27 insertions(+) create mode 100644 LICENSE create mode 100644 TODO diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d31ea441 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2014 Lazaros Koromilas +Copyright (c) 2014 sin +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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. diff --git a/TODO b/TODO new file mode 100644 index 00000000..2e859a2c --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +- File filtering. +- Searching using slash and next keys. +- Screen skip using page up and page down. From dc711f2fadde0b74934f7679b48938fcc1cf319c Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 9 Oct 2014 15:54:07 +0100 Subject: [PATCH 031/268] Add emacs-like keybinds for next/prev entry selection --- noice.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/noice.c b/noice.c index a1d488f4..b61ea0d8 100644 --- a/noice.c +++ b/noice.c @@ -34,6 +34,7 @@ #define LEN(x) (sizeof(x) / sizeof(*(x))) #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define ISODD(x) ((x) & 1) +#define CONTROL(c) ((c) ^ 0x40) struct assoc { char *regex; /* Regex to match on filename */ @@ -182,12 +183,14 @@ nextsel(int *cur, int max) /* next */ case 'j': case KEY_DOWN: + case CONTROL('N'): if (*cur < max - 1) (*cur)++; break; /* prev */ case 'k': case KEY_UP: + case CONTROL('P'): if (*cur > 0) (*cur)--; break; From b0df3806deb4ae5c6eb01f7d6b71a50ca16610b7 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 01:35:47 +0300 Subject: [PATCH 032/268] Search filter support with a very basic readline --- noice.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index b61ea0d8..2760e77f 100644 --- a/noice.c +++ b/noice.c @@ -79,6 +79,10 @@ struct entry { int die = 0; +void printmsg(char *msg); +void printwarn(void); +void printerr(int ret, char *prefix); + char * openwith(char *file) { @@ -100,6 +104,31 @@ openwith(char *file) return bin; } +int +setfilter(regex_t *regex, char *filter) +{ + char *errbuf; + int r; + + r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED); + if (r != 0) { + errbuf = malloc(COLS * sizeof(char)); + regerror(r, regex, errbuf, COLS * sizeof(char)); + printmsg(errbuf); + free(errbuf); + } + + return r; +} + +int +visible(regex_t *regex, char *file) +{ + if (regexec(regex, file, 0, NULL, 0) != REG_NOMATCH) + return 1; + return 0; +} + int entrycmp(const void *va, const void *vb) { @@ -159,6 +188,7 @@ printerr(int ret, char *prefix) * Returns 1 on quit * Returns 2 on go in * Returns 3 on go up + * Returns 4 on search */ int nextsel(int *cur, int max) @@ -180,6 +210,10 @@ nextsel(int *cur, int max) case KEY_RIGHT: case 'l': return 3; + /* search */ + case '/': + case '&': + return 4; /* next */ case 'j': case KEY_DOWN: @@ -199,6 +233,52 @@ nextsel(int *cur, int max) return 0; } +char * +readln(void) +{ + int c; + int i = 0; + char *ln = NULL; + int y, x, x0; + + echo(); + curs_set(TRUE); + + /* Starting point */ + getyx(stdscr, y, x); + x0 = x; + + while (c = getch()) { + if (c == KEY_ENTER || c == '\r') + break; + if (c == KEY_BACKSPACE) { + getyx(stdscr, y, x); + if (x >= x0) { + ln = realloc(ln, (i - 1) * sizeof(*ln)); + i--; + move(y, x); + printw("%c", ' '); + move(y, x); + } else { + move(y, x0); + } + continue; + } + ln = realloc(ln, (i + 1) * sizeof(*ln)); + ln[i] = c; + i++; + } + if (ln != NULL) { + ln = realloc(ln, (i + 1) * sizeof(*ln)); + ln[i] = '\0'; + } + + curs_set(FALSE); + noecho(); + + return ln; +} + int testopendir(char *path) { @@ -246,7 +326,7 @@ printent(struct entry *ent, int active) } void -browse(const char *ipath) +browse(const char *ipath, const char *ifilter) { DIR *dirp; int dfd; @@ -255,6 +335,8 @@ browse(const char *ipath) int i, n, cur; int r, ret; char *path = strdup(ipath); + char *filter = strdup(ifilter); + regex_t filter_re; char *cwd; struct stat sb; @@ -270,6 +352,11 @@ begin: goto nochange; } + /* Search filter */ + r = setfilter(&filter_re, filter); + if (r != 0) + goto nochange; + while ((dp = readdir(dirp)) != NULL) { char *name; @@ -277,6 +364,8 @@ begin: if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; + if (!visible(&filter_re, dp->d_name)) + continue; /* Deep copy because readdir(3) reuses the entries */ dents = realloc(dents, (n + 1) * sizeof(*dents)); if (dents == NULL) @@ -432,6 +521,28 @@ nochange: free(pathnew); goto nochange; } + if (ret == 4) { + char *tmp; + regex_t re; + + /* Read filter */ + move(LINES - 1, 0); + printw("filter: "); + tmp = readln(); + if (tmp == NULL) { + printmsg(""); + goto nochange; + } + r = setfilter(&re, tmp); + if (r != 0) { + printmsg(""); + goto nochange; + } + filter = tmp; + filter_re = re; + DPRINTF_S(filter); + goto out; + } } out: @@ -450,6 +561,7 @@ int main(int argc, char *argv[]) { char *ipath = argv[1] != NULL ? argv[1] : "/"; + char *ifilter = "^[^.].*"; /* Hide dotfiles */ /* Test initial path */ if (!testopendir(ipath)) @@ -460,7 +572,7 @@ main(int argc, char *argv[]) initcurses(); - browse(ipath); + browse(ipath, ifilter); exitcurses(); From a75021c2d2ba1f23a110c5bfd795ef74e324e321 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 09:50:46 +0300 Subject: [PATCH 033/268] Reset to initial filter on directory change --- noice.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/noice.c b/noice.c index 2760e77f..1ac32797 100644 --- a/noice.c +++ b/noice.c @@ -450,6 +450,8 @@ nochange: strlcpy(tmp, dir, strlen(dir) + 1); free(path); path = tmp; + free(filter); + filter = strdup(ifilter); /* Reset filter */ goto out; } } @@ -490,6 +492,8 @@ nochange: if (S_ISDIR(sb.st_mode)) { free(path); path = pathnew; + free(filter); + filter = strdup(ifilter); /* Reset filter */ goto out; } /* Regular file */ @@ -538,6 +542,7 @@ nochange: printmsg(""); goto nochange; } + free(filter); filter = tmp; filter_re = re; DPRINTF_S(filter); From 1cdfa84f699755d97873a90d856e4db5d7a6e0b8 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 10:06:31 +0300 Subject: [PATCH 034/268] Define return codes for nextsel() and use a switch --- noice.c | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/noice.c b/noice.c index 1ac32797..fd10234b 100644 --- a/noice.c +++ b/noice.c @@ -185,11 +185,12 @@ printerr(int ret, char *prefix) /* * Returns 0 normally * On movement it updates *cur - * Returns 1 on quit - * Returns 2 on go in - * Returns 3 on go up - * Returns 4 on search + * Returns SEL_{QUIT,BACK,GOIN,FLTR} otherwise */ +#define SEL_QUIT 1 +#define SEL_BACK 2 +#define SEL_GOIN 3 +#define SEL_FLTR 4 int nextsel(int *cur, int max) { @@ -198,22 +199,22 @@ nextsel(int *cur, int max) c = getch(); switch (c) { case 'q': - return 1; - /* go up */ + return SEL_QUIT; + /* back */ case KEY_BACKSPACE: case KEY_LEFT: case 'h': - return 2; - /* go in */ + return SEL_BACK; + /* inside */ case KEY_ENTER: case '\r': case KEY_RIGHT: case 'l': - return 3; - /* search */ + return SEL_GOIN; + /* filter */ case '/': case '&': - return 4; + return SEL_FLTR; /* next */ case 'j': case KEY_DOWN: @@ -389,6 +390,14 @@ begin: int nlines; int maxlen; int odd; + char *pathnew; + char *name; + char *bin; + pid_t pid; + int fd; + char *dir; + char *tmp; + regex_t re; redraw: nlines = MIN(LINES - 4, n); @@ -434,17 +443,15 @@ redraw: nochange: ret = nextsel(&cur, n); - if (ret == 1) { + switch (ret) { + case SEL_QUIT: free(path); return; - } - if (ret == 2) { + case SEL_BACK: /* Handle root case */ if (strcmp(path, "") == 0) { goto nochange; } else { - char *dir, *tmp; - dir = dirname(path); tmp = malloc(strlen(dir) + 1); strlcpy(tmp, dir, strlen(dir) + 1); @@ -454,14 +461,7 @@ nochange: filter = strdup(ifilter); /* Reset filter */ goto out; } - } - if (ret == 3) { - char *pathnew; - char *name; - char *bin; - pid_t pid; - int fd; - + case SEL_GOIN: /* Cannot descend in empty directories */ if (n == 0) goto nochange; @@ -524,11 +524,7 @@ nochange: printmsg("Unsupported file"); free(pathnew); goto nochange; - } - if (ret == 4) { - char *tmp; - regex_t re; - + case SEL_FLTR: /* Read filter */ move(LINES - 1, 0); printw("filter: "); From 50329302907c5435fead471b6a571b9d24215c1d Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 10:11:50 +0300 Subject: [PATCH 035/268] Also release filter memory --- noice.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index fd10234b..27a4b324 100644 --- a/noice.c +++ b/noice.c @@ -342,7 +342,7 @@ browse(const char *ipath, const char *ifilter) struct stat sb; begin: - /* Path should be a malloc(3)-ed string at all times */ + /* Path and filter should be malloc(3)-ed strings at all times */ n = 0; cur = 0; dents = NULL; @@ -446,6 +446,7 @@ nochange: switch (ret) { case SEL_QUIT: free(path); + free(filter); return; case SEL_BACK: /* Handle root case */ From bc2d9e7c11f010e3f2c8ccf6d9a082aafc1a98b8 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 10:31:57 +0300 Subject: [PATCH 036/268] Cursor stack item --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 2e859a2c..edfd1a97 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ - File filtering. - Searching using slash and next keys. - Screen skip using page up and page down. +- Remember cursor position when going back. From 61cd0f8041e36757f4a02aa8894309412e35ccff Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 10 Oct 2014 10:12:01 +0100 Subject: [PATCH 037/268] Only closedir when dirp is valid --- noice.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 27a4b324..4c88701e 100644 --- a/noice.c +++ b/noice.c @@ -552,9 +552,11 @@ out: free(dents[i].name); free(dents); - r = closedir(dirp); - if (r == -1) - printerr(1, "closedir"); + if (dirp != NULL) { + r = closedir(dirp); + if (r == -1) + printerr(1, "closedir"); + } goto begin; } From 327720107565e730a15b8d16351c8c4efd34a471 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 13:14:55 +0300 Subject: [PATCH 038/268] Handle the root path case correctly --- noice.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/noice.c b/noice.c index 4c88701e..d03400e9 100644 --- a/noice.c +++ b/noice.c @@ -374,8 +374,12 @@ begin: dents[n].name = strdup(dp->d_name); if (dents[n].name == NULL) printerr(1, "strdup"); + /* Handle root case */ + if (strcmp(path, "/") == 0) + asprintf(&name, "/%s", dents[n].name); + else + asprintf(&name, "%s/%s", path, dents[n].name); /* Get mode flags */ - asprintf(&name, "%s/%s", path, dents[n].name); r = lstat(name, &sb); free(name); if (r == -1) @@ -406,7 +410,7 @@ redraw: erase(); /* Strip trailing slashes */ - for (i = strlen(path) - 1; i > -1; i--) + for (i = strlen(path) - 1; i > 0; i--) if (path[i] == '/') path[i] = '\0'; else @@ -420,12 +424,7 @@ redraw: strlcpy(cwd, path, COLS * sizeof(char)); cwd[COLS - strlen(CWD) - 1] = '\0'; - /* Print cwd. If empty we are on the root. We store it - * as an empty string so that when we navigate in /mnt - * is doesn't come up as //mnt. */ - printw(CWD "%s%s\n\n", - strcmp(cwd, "") == 0 ? "/" : "", - cwd); + printw(CWD "%s\n\n", cwd); /* Print listing */ odd = ISODD(nlines); @@ -449,8 +448,8 @@ nochange: free(filter); return; case SEL_BACK: - /* Handle root case */ - if (strcmp(path, "") == 0) { + /* There is no going back */ + if (strcmp(path, "/") == 0) { goto nochange; } else { dir = dirname(path); From f05f98e4feb9a6100301800870c74365c5430ac9 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 13:22:18 +0300 Subject: [PATCH 039/268] Another part that needs special handling for root --- noice.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index d03400e9..f224c964 100644 --- a/noice.c +++ b/noice.c @@ -468,7 +468,11 @@ nochange: name = dents[cur].name; - asprintf(&pathnew, "%s/%s", path, name); + /* Handle root case */ + if (strcmp(path, "/") == 0) + asprintf(&pathnew, "/%s", name); + else + asprintf(&pathnew, "%s/%s", path, name); DPRINTF_S(name); DPRINTF_S(pathnew); From 11bebdf23e4c2dd6015f949b65f802f36cedc06c Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 13:24:19 +0300 Subject: [PATCH 040/268] The dirp should be initialized here --- noice.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index f224c964..5916fca0 100644 --- a/noice.c +++ b/noice.c @@ -555,11 +555,10 @@ out: free(dents[i].name); free(dents); - if (dirp != NULL) { - r = closedir(dirp); - if (r == -1) - printerr(1, "closedir"); - } + /* Should never be null */ + r = closedir(dirp); + if (r == -1) + printerr(1, "closedir"); goto begin; } From bfd5f9b1d45268106210cafa28a445d8c035e36f Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 14:57:02 +0300 Subject: [PATCH 041/268] Change default associations --- noice.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 5916fca0..c016d9ac 100644 --- a/noice.c +++ b/noice.c @@ -44,10 +44,10 @@ struct assoc { /* Configuration */ struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, - { "\\.srt$", "less" }, - { "\\.txt$", "less" }, + { "\\.(png|jpg|gif)$", "feh" }, + { "\\.(html|svg)$", "firefox" }, + { "\\.pdf$", "mupdf" }, { "\\.sh$", "sh" }, - { "^README$", "less" }, { ".*", "less" }, }; From e9489496249aaf31940c7906104ab1222f77447c Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 14:59:30 +0300 Subject: [PATCH 042/268] Consistent comments capitalization --- noice.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index c016d9ac..a0e98fcb 100644 --- a/noice.c +++ b/noice.c @@ -200,29 +200,29 @@ nextsel(int *cur, int max) switch (c) { case 'q': return SEL_QUIT; - /* back */ + /* Back */ case KEY_BACKSPACE: case KEY_LEFT: case 'h': return SEL_BACK; - /* inside */ + /* Inside */ case KEY_ENTER: case '\r': case KEY_RIGHT: case 'l': return SEL_GOIN; - /* filter */ + /* Filter */ case '/': case '&': return SEL_FLTR; - /* next */ + /* Next */ case 'j': case KEY_DOWN: case CONTROL('N'): if (*cur < max - 1) (*cur)++; break; - /* prev */ + /* Previous */ case 'k': case KEY_UP: case CONTROL('P'): From f30e02239ebdae179682ed3765d3b2f1a4ff5075 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 15:02:26 +0300 Subject: [PATCH 043/268] Another leak in the wall --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index a0e98fcb..11d950a7 100644 --- a/noice.c +++ b/noice.c @@ -539,6 +539,7 @@ nochange: } r = setfilter(&re, tmp); if (r != 0) { + free(tmp); printmsg(""); goto nochange; } From de7072bdd537cead9cc117010b03afe6b6e21e86 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 15:13:13 +0300 Subject: [PATCH 044/268] Let filter errors show up in status line --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 11d950a7..3330b675 100644 --- a/noice.c +++ b/noice.c @@ -530,6 +530,7 @@ nochange: goto nochange; case SEL_FLTR: /* Read filter */ + printmsg(""); move(LINES - 1, 0); printw("filter: "); tmp = readln(); @@ -540,7 +541,6 @@ nochange: r = setfilter(&re, tmp); if (r != 0) { free(tmp); - printmsg(""); goto nochange; } free(filter); From 15ba1b15b8df852b69d9108b7af8b3e5dfb640be Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 15:46:13 +0300 Subject: [PATCH 045/268] Faster movement key bindings --- noice.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/noice.c b/noice.c index 3330b675..4af580ec 100644 --- a/noice.c +++ b/noice.c @@ -229,6 +229,18 @@ nextsel(int *cur, int max) if (*cur > 0) (*cur)--; break; + /* Page down */ + case KEY_NPAGE: + case CONTROL('D'): + if (*cur < max -1) + (*cur) += MIN((LINES - 4) / 2, max - 1 - *cur); + break; + /* Page up */ + case KEY_PPAGE: + case CONTROL('U'): + if (*cur > 0) + (*cur) -= MIN((LINES - 4) / 2, *cur); + break; } return 0; From a1e96d7d1978bdc2e9b5443a96d755581d3b75d3 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 16:55:06 +0300 Subject: [PATCH 046/268] Remember cursor position when going back --- noice.c | 37 +++- queue.h | 648 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 684 insertions(+), 1 deletion(-) create mode 100644 queue.h diff --git a/noice.c b/noice.c index 4af580ec..54cedef6 100644 --- a/noice.c +++ b/noice.c @@ -18,6 +18,8 @@ #include #endif +#include "queue.h" + #ifdef DEBUG #define DEBUG_FD 8 #define DPRINTF_D(x) dprintf(DEBUG_FD, #x "=%d\n", x) @@ -56,6 +58,13 @@ struct entry { mode_t mode; }; +struct history { + int pos; + SLIST_ENTRY(history) entry; +}; + +SLIST_HEAD(histhead, history) histhead = SLIST_HEAD_INITIALIZER(histhead); + #define CWD "cwd: " #define CURSR " > " #define EMPTY " " @@ -353,10 +362,10 @@ browse(const char *ipath, const char *ifilter) char *cwd; struct stat sb; + cur = 0; begin: /* Path and filter should be malloc(3)-ed strings at all times */ n = 0; - cur = 0; dents = NULL; dirp = opendir(path); @@ -400,6 +409,9 @@ begin: n++; } + /* Make sure cur is in range */ + cur = MIN(cur, n - 1); + qsort(dents, n, sizeof(*dents), entrycmp); for (;;) { @@ -414,6 +426,7 @@ begin: char *dir; char *tmp; regex_t re; + struct history *hist; redraw: nlines = MIN(LINES - 4, n); @@ -458,6 +471,12 @@ nochange: case SEL_QUIT: free(path); free(filter); + /* Forget history */ + while (!SLIST_EMPTY(&histhead)) { + hist = SLIST_FIRST(&histhead); + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); + } return; case SEL_BACK: /* There is no going back */ @@ -471,6 +490,16 @@ nochange: path = tmp; free(filter); filter = strdup(ifilter); /* Reset filter */ + /* Recall history */ + hist = SLIST_FIRST(&histhead); + if (hist != NULL) { + cur = hist->pos; + DPRINTF_D(hist->pos); + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); + } else { + cur = 0; + } goto out; } case SEL_GOIN: @@ -510,6 +539,11 @@ nochange: path = pathnew; free(filter); filter = strdup(ifilter); /* Reset filter */ + /* Save history */ + hist = malloc(sizeof(struct history)); + hist->pos = cur; + SLIST_INSERT_HEAD(&histhead, hist, entry); + cur = 0; goto out; } /* Regular file */ @@ -559,6 +593,7 @@ nochange: filter = tmp; filter_re = re; DPRINTF_S(filter); + cur = 0; goto out; } } diff --git a/queue.h b/queue.h new file mode 100644 index 00000000..a09d8ca6 --- /dev/null +++ b/queue.h @@ -0,0 +1,648 @@ +/* $OpenBSD: src/sys/sys/queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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 the University 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 REGENTS 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 REGENTS 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) +#define _Q_INVALIDATE(a) (a) = ((void *)-1) +#else +#define _Q_INVALIDATE(a) +#endif + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST(head); \ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) { \ + SLIST_FIRST(head) = SLIST_END(head); \ +} + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + _Q_INVALIDATE((elm)->field.sle_next); \ + } \ +} while (0) + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for((var) = LIST_FIRST(head); \ + (var)!= LIST_END(head); \ + (var) = LIST_NEXT(var, field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST(head); \ + (var) && ((tvar) = LIST_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * List functions. + */ +#define LIST_INIT(head) do { \ + LIST_FIRST(head) = LIST_END(head); \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (0) + +#define LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ +} while (0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for((var) = SIMPLEQ_FIRST(head); \ + (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + +/* + * XOR Simple queue definitions. + */ +#define XSIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ +} + +#define XSIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqx_next; /* next element */ \ +} + +/* + * XOR Simple queue access methods. + */ +#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ + (unsigned long)(ptr))) +#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) +#define XSIMPLEQ_END(head) NULL +#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) +#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) + + +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) + +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) + +/* + * XOR Simple queue functions. + */ +#define XSIMPLEQ_INIT(head) do { \ + arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ + (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ + (elm)->field.sqx_next)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) NULL +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + +#define TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head) && \ + ((tvar) = TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ +} while (0) + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue access methods + */ +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_END(head) ((void *)(head)) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define CIRCLEQ_EMPTY(head) \ + (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_NEXT(var, field)) + +#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = CIRCLEQ_FIRST(head); \ + (var) != CIRCLEQ_END(head) && \ + ((tvar) = CIRCLEQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = CIRCLEQ_LAST(head); \ + (var) != CIRCLEQ_END(head); \ + (var) = CIRCLEQ_PREV(var, field)) + +#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = CIRCLEQ_LAST(head, headname); \ + (var) != CIRCLEQ_END(head) && \ + ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = CIRCLEQ_END(head); \ + (head)->cqh_last = CIRCLEQ_END(head); \ +} while (0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = CIRCLEQ_END(head); \ + if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = CIRCLEQ_END(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ + _Q_INVALIDATE((elm)->field.cqe_prev); \ + _Q_INVALIDATE((elm)->field.cqe_next); \ +} while (0) + +#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ + CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ + CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ + _Q_INVALIDATE((elm)->field.cqe_prev); \ + _Q_INVALIDATE((elm)->field.cqe_next); \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ From 3f95571b3892b3faaaf94c3571ac9669f1d1fd91 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 10 Oct 2014 16:57:13 +0300 Subject: [PATCH 047/268] Those features are there --- TODO | 3 --- 1 file changed, 3 deletions(-) diff --git a/TODO b/TODO index edfd1a97..855ae147 100644 --- a/TODO +++ b/TODO @@ -1,4 +1 @@ -- File filtering. - Searching using slash and next keys. -- Screen skip using page up and page down. -- Remember cursor position when going back. From 955152417fd24026dfd5582068cb50219419b137 Mon Sep 17 00:00:00 2001 From: lostd Date: Mon, 13 Oct 2014 10:22:05 +0300 Subject: [PATCH 048/268] Properly wait for processes to terminate --- noice.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 54cedef6..0420cc39 100644 --- a/noice.c +++ b/noice.c @@ -427,6 +427,7 @@ begin: char *tmp; regex_t re; struct history *hist; + int status; redraw: nlines = MIN(LINES - 4, n); @@ -560,10 +561,16 @@ nochange: /* Run program */ pid = fork(); - if (pid == 0) + if (pid == 0) { execlp(bin, bin, pathnew, NULL); - else - waitpid(pid, NULL, 0); + _exit(0); + } else { + /* Ignore interruptions */ + while (waitpid(pid, &status, + 0) == -1) + DPRINTF_D(status); + DPRINTF_D(pid); + } initcurses(); From a9b5370ac67c586771472f4d2763a971cc519c5c Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:08:57 +0100 Subject: [PATCH 049/268] Add strlcpy() --- Makefile | 13 +++++++++++-- strlcpy.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ util.h | 2 ++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 strlcpy.c create mode 100644 util.h diff --git a/Makefile b/Makefile index c2cdcad1..19b52d36 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,19 @@ #CPPFLAGS += -DDEBUG #CFLAGS += -g LDLIBS = -lncursesw -#LDLIBS += -lbsd +OBJ = noice.o strlcpy.o BIN = noice all: $(BIN) +$(BIN): $(OBJ) + $(CC) -o $@ $(OBJ) $(LDLIBS) + +noice.o: noice.c queue.h util.h + $(CC) -c noice.c + +strlcpy.o: strlcpy.c util.h + $(CC) -c strlcpy.c + clean: - rm -f $(BIN) + rm -f $(BIN) $(OBJ) diff --git a/strlcpy.c b/strlcpy.c new file mode 100644 index 00000000..7df8aa23 --- /dev/null +++ b/strlcpy.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include "util.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + return(s - src - 1); /* count does not include NUL */ +} diff --git a/util.h b/util.h new file mode 100644 index 00000000..4da38854 --- /dev/null +++ b/util.h @@ -0,0 +1,2 @@ +#undef strlcpy +size_t strlcpy(char *, const char *, size_t); From 43fa667cd62e7736fc99afb2dd56b81b1acc9693 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:15:27 +0100 Subject: [PATCH 050/268] Add config.def.h --- Makefile | 8 ++++++-- config.def.h | 9 +++++++++ noice.c | 10 +--------- 3 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 config.def.h diff --git a/Makefile b/Makefile index 19b52d36..29ca2b67 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,14 @@ BIN = noice all: $(BIN) -$(BIN): $(OBJ) +$(BIN): config.h $(OBJ) $(CC) -o $@ $(OBJ) $(LDLIBS) -noice.o: noice.c queue.h util.h +config.h: + @echo copying config.def.h to $@ + @cp config.def.h $@ + +noice.o: noice.c util.h $(CC) -c noice.c strlcpy.o: strlcpy.c util.h diff --git a/config.def.h b/config.def.h new file mode 100644 index 00000000..cebb942f --- /dev/null +++ b/config.def.h @@ -0,0 +1,9 @@ +/* Configuration */ +struct assoc assocs[] = { + { "\\.(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, + { "\\.(png|jpg|gif)$", "feh" }, + { "\\.(html|svg)$", "firefox" }, + { "\\.pdf$", "mupdf" }, + { "\\.sh$", "sh" }, + { ".*", "less" }, +}; diff --git a/noice.c b/noice.c index 0420cc39..d78cf5e9 100644 --- a/noice.c +++ b/noice.c @@ -43,15 +43,7 @@ struct assoc { char *bin; /* Program */ }; -/* Configuration */ -struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, - { "\\.(png|jpg|gif)$", "feh" }, - { "\\.(html|svg)$", "firefox" }, - { "\\.pdf$", "mupdf" }, - { "\\.sh$", "sh" }, - { ".*", "less" }, -}; +#include "config.h" struct entry { char *name; From a13096b773fac95b5fa3757edbf925566e68326b Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:17:59 +0100 Subject: [PATCH 051/268] Force rebuild of noice.o if queue.h is modified --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 29ca2b67..3972d846 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ config.h: @echo copying config.def.h to $@ @cp config.def.h $@ -noice.o: noice.c util.h +noice.o: noice.c queue.h util.h $(CC) -c noice.c strlcpy.o: strlcpy.c util.h From e776ebe36ce5b7fa7c7ec945af5a884ea4259dd2 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:21:50 +0100 Subject: [PATCH 052/268] Use CFLAGS too --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 3972d846..7cc1ee1d 100644 --- a/Makefile +++ b/Makefile @@ -7,17 +7,17 @@ BIN = noice all: $(BIN) $(BIN): config.h $(OBJ) - $(CC) -o $@ $(OBJ) $(LDLIBS) + $(CC) $(CFLAGS) -o $@ $(OBJ) $(LDLIBS) config.h: @echo copying config.def.h to $@ @cp config.def.h $@ noice.o: noice.c queue.h util.h - $(CC) -c noice.c + $(CC) $(CFLAGS) -c noice.c strlcpy.o: strlcpy.c util.h - $(CC) -c strlcpy.c + $(CC) $(CFLAGS) -c strlcpy.c clean: rm -f $(BIN) $(OBJ) From 4c330409b0c94b7c9ef8ef987f216c93eeca710f Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:23:37 +0100 Subject: [PATCH 053/268] And CPPFLAGS --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7cc1ee1d..6ef05082 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ config.h: @cp config.def.h $@ noice.o: noice.c queue.h util.h - $(CC) $(CFLAGS) -c noice.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c noice.c strlcpy.o: strlcpy.c util.h $(CC) $(CFLAGS) -c strlcpy.c From 5999cef3967293c53faca42941e6090f4fd99e28 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:29:41 +0100 Subject: [PATCH 054/268] Default to cwd if not argument is provided --- noice.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index d78cf5e9..38459809 100644 --- a/noice.c +++ b/noice.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -613,9 +614,17 @@ out: int main(int argc, char *argv[]) { - char *ipath = argv[1] != NULL ? argv[1] : "/"; + char cwd[PATH_MAX], *ipath; char *ifilter = "^[^.].*"; /* Hide dotfiles */ + if (argv[1] != NULL) { + ipath = argv[1]; + } else { + ipath = getcwd(cwd, sizeof(cwd)); + if (ipath == NULL) + ipath = "/"; + } + /* Test initial path */ if (!testopendir(ipath)) printerr(1, ipath); From d330033c4f2c0fb219f1e65a5e40042af34f9120 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:35:08 +0100 Subject: [PATCH 055/268] Move some more config params to config.def.h --- config.def.h | 5 ++++- noice.c | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/config.def.h b/config.def.h index cebb942f..e7af17f0 100644 --- a/config.def.h +++ b/config.def.h @@ -1,4 +1,7 @@ -/* Configuration */ +#define CWD "cwd: " +#define CURSR " > " +#define EMPTY " " + struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, { "\\.(png|jpg|gif)$", "feh" }, diff --git a/noice.c b/noice.c index 38459809..22bec3be 100644 --- a/noice.c +++ b/noice.c @@ -58,10 +58,6 @@ struct history { SLIST_HEAD(histhead, history) histhead = SLIST_HEAD_INITIALIZER(histhead); -#define CWD "cwd: " -#define CURSR " > " -#define EMPTY " " - /* * Layout: * .--------- From d7d40366bdaf521573f0f6f6e7cd4d4c16125f46 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:35:57 +0100 Subject: [PATCH 056/268] Remove unused global variable --- noice.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/noice.c b/noice.c index 22bec3be..59389ef0 100644 --- a/noice.c +++ b/noice.c @@ -75,8 +75,6 @@ SLIST_HEAD(histhead, history) histhead = SLIST_HEAD_INITIALIZER(histhead); * '------ */ -int die = 0; - void printmsg(char *msg); void printwarn(void); void printerr(int ret, char *prefix); From 65a01f96363e7c6e1a7d479f18cacde8e32eb2a0 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 11:37:34 +0100 Subject: [PATCH 057/268] Include util.h and remove ifdef for Linux --- noice.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 59389ef0..3a9e241c 100644 --- a/noice.c +++ b/noice.c @@ -15,11 +15,8 @@ #include #include -#ifdef LINUX -#include -#endif - #include "queue.h" +#include "util.h" #ifdef DEBUG #define DEBUG_FD 8 From 3bc66a43a7d1610776ff25af3675f9527fc4aabc Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 12:03:53 +0100 Subject: [PATCH 058/268] Show hidden files if run as root --- noice.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 3a9e241c..5d8cc475 100644 --- a/noice.c +++ b/noice.c @@ -606,7 +606,12 @@ int main(int argc, char *argv[]) { char cwd[PATH_MAX], *ipath; - char *ifilter = "^[^.].*"; /* Hide dotfiles */ + char *ifilter; + + if (getuid() == 0) + ifilter = ".*"; + else + ifilter = "^[^.].*"; /* Hide dotfiles */ if (argv[1] != NULL) { ipath = argv[1]; From 7273c9d6819c50ab546885f7d6d0e81d03b7ca16 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 12:07:20 +0100 Subject: [PATCH 059/268] Add flac to default associations --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index e7af17f0..3d733a2d 100644 --- a/config.def.h +++ b/config.def.h @@ -3,7 +3,7 @@ #define EMPTY " " struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg)$", "mplayer" }, + { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, { "\\.(png|jpg|gif)$", "feh" }, { "\\.(html|svg)$", "firefox" }, { "\\.pdf$", "mupdf" }, From d53e604cc24f5b17985cf3bc5937d16c4a4ed2fc Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 14:21:00 +0100 Subject: [PATCH 060/268] Add '!' command to spawn a shell in cwd --- noice.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/noice.c b/noice.c index 5d8cc475..b01961fe 100644 --- a/noice.c +++ b/noice.c @@ -76,6 +76,24 @@ void printmsg(char *msg); void printwarn(void); void printerr(int ret, char *prefix); +void +spawn(const char *file, const char *arg) +{ + pid_t pid; + int status; + + pid = fork(); + if (pid == 0) { + execlp(file, file, arg, NULL); + _exit(1); + } else { + /* Ignore interruptions */ + while (waitpid(pid, &status, 0) == -1) + DPRINTF_D(status); + DPRINTF_D(pid); + } +} + char * openwith(char *file) { @@ -234,6 +252,11 @@ nextsel(int *cur, int max) if (*cur > 0) (*cur) -= MIN((LINES - 4) / 2, *cur); break; + case '!': + exitcurses(); + spawn("/bin/sh", NULL); + initcurses(); + break; } return 0; @@ -405,13 +428,11 @@ begin: char *pathnew; char *name; char *bin; - pid_t pid; int fd; char *dir; char *tmp; regex_t re; struct history *hist; - int status; redraw: nlines = MIN(LINES - 4, n); @@ -451,7 +472,11 @@ redraw: } nochange: + if (chdir(path) == -1) + printwarn(); ret = nextsel(&cur, n); + if (chdir(ipath) == -1) + printwarn(); switch (ret) { case SEL_QUIT: free(path); @@ -542,20 +567,7 @@ nochange: } exitcurses(); - - /* Run program */ - pid = fork(); - if (pid == 0) { - execlp(bin, bin, pathnew, NULL); - _exit(0); - } else { - /* Ignore interruptions */ - while (waitpid(pid, &status, - 0) == -1) - DPRINTF_D(status); - DPRINTF_D(pid); - } - + spawn(bin, pathnew); initcurses(); free(pathnew); From 273cb9150c30b882800fb4b2d8adb77444a67974 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 14:25:33 +0100 Subject: [PATCH 061/268] README contributed by z3bra --- README | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 00000000..70b5fd30 --- /dev/null +++ b/README @@ -0,0 +1,54 @@ + __ + ___ ___ /\_\ ___ __ +/' _ `\ / __`\/\ \ /'___\ /'__`\ +/\ \/\ \/\ \L\ \ \ \/\ \__//\ __/ +\ \_\ \_\ \____/\ \_\ \____\ \____\ + \/_/\/_/\/___/ \/_/\/____/\/____/ + -- by lostd and sin +======================================================= + +What is it? +=========== + +noice is a small ncurse-based file manager. +It was first developped to be used with a tv remote control for a media center +solution. + +Getting started +=============== + +Get the latest version from the git-repository; build and install it. +Run noice in a directory to display its content in the form of a list, where +each line is a file or direcotry. The currently selected item will be preceded +with a " > " by default. + +Navigation +---------- + +You can navigate the list using the following keybinds (hardcoded): + ++------+-------+-------+--------------------------------------------------- +| k | UP | ^P | go up +| j | DOWN | ^N | go down +| | PGUP | ^U | go up (fast) +| | PGDN | ^D | go down (fast) +| l | RIGHT | ^M | open file / directory (see section "File opening") +| h | LEFT | ^? | navigate up one directory +| / | & | | filter output +| q | | | exit program +| ! | | | spawn shell in current directory ++------+-------+-------+--------------------------------------------------- + +File opening +------------ + +Depending on the filetype, noice will open the selected file with the +application specified in `config.h` at compilation time. The associations +specified are regexes, so you might experience issues when trying to open a file +that do not match those regexes. + +Contact +======= + +You can reach us through the freenode IRC network at #2f30. +If you have any patches, ideas or feedback feel free to join. From 31c5e5912db0f6a955fd4c529366a853bc674e7a Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 14:27:38 +0100 Subject: [PATCH 062/268] Fix typo in README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 70b5fd30..e837a750 100644 --- a/README +++ b/README @@ -10,7 +10,7 @@ What is it? =========== -noice is a small ncurse-based file manager. +noice is a small ncurses-based file manager. It was first developped to be used with a tv remote control for a media center solution. From 4919b910b992996433f617415aff1d01f9077af3 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 14:34:06 +0100 Subject: [PATCH 063/268] Add comment about less(1) --- README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README b/README index e837a750..6936ff11 100644 --- a/README +++ b/README @@ -47,6 +47,9 @@ application specified in `config.h` at compilation time. The associations specified are regexes, so you might experience issues when trying to open a file that do not match those regexes. +The default program is less(1). For text files, you can use the 'v' +commaind in less(1) to open the file in your $EDITOR. + Contact ======= From 65b8aa2ab0df59db1e9bf92a33f1fdd5f969ba65 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 14:54:32 +0100 Subject: [PATCH 064/268] Add SEL_SH and bring out spawning of the shell in the main loop --- noice.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/noice.c b/noice.c index b01961fe..aad67ba5 100644 --- a/noice.c +++ b/noice.c @@ -198,10 +198,14 @@ printerr(int ret, char *prefix) * On movement it updates *cur * Returns SEL_{QUIT,BACK,GOIN,FLTR} otherwise */ -#define SEL_QUIT 1 -#define SEL_BACK 2 -#define SEL_GOIN 3 -#define SEL_FLTR 4 +enum { + SEL_QUIT = 1, + SEL_BACK, + SEL_GOIN, + SEL_FLTR, + SEL_SH, +}; + int nextsel(int *cur, int max) { @@ -253,10 +257,7 @@ nextsel(int *cur, int max) (*cur) -= MIN((LINES - 4) / 2, *cur); break; case '!': - exitcurses(); - spawn("/bin/sh", NULL); - initcurses(); - break; + return SEL_SH; } return 0; @@ -472,11 +473,7 @@ redraw: } nochange: - if (chdir(path) == -1) - printwarn(); ret = nextsel(&cur, n); - if (chdir(ipath) == -1) - printwarn(); switch (ret) { case SEL_QUIT: free(path); @@ -598,6 +595,14 @@ nochange: DPRINTF_S(filter); cur = 0; goto out; + case SEL_SH: + if (chdir(path) == -1) + printwarn(); + exitcurses(); + spawn("/bin/sh", NULL); + initcurses(); + if (chdir(ipath) == -1) + printwarn(); } } From b0ca406e28bf68b274643f64841f6bfae18b971b Mon Sep 17 00:00:00 2001 From: "Alex-P. Natsios" Date: Tue, 21 Oct 2014 16:50:27 +0300 Subject: [PATCH 065/268] more typo and grammar fixes for README --- README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index 6936ff11..a023074a 100644 --- a/README +++ b/README @@ -11,7 +11,7 @@ What is it? =========== noice is a small ncurses-based file manager. -It was first developped to be used with a tv remote control for a media center +It was first developed to be used with a tv remote control for a media center solution. Getting started @@ -19,7 +19,7 @@ Getting started Get the latest version from the git-repository; build and install it. Run noice in a directory to display its content in the form of a list, where -each line is a file or direcotry. The currently selected item will be preceded +each line is a file or directory. The currently selected item will be preceded with a " > " by default. Navigation @@ -44,8 +44,8 @@ File opening Depending on the filetype, noice will open the selected file with the application specified in `config.h` at compilation time. The associations -specified are regexes, so you might experience issues when trying to open a file -that do not match those regexes. +are specified by regexes, so you might experience issues when trying to open a file +that does not match those regexes. The default program is less(1). For text files, you can use the 'v' commaind in less(1) to open the file in your $EDITOR. From 58f897fead53d15621029d5f76a68500588a23af Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 14:57:09 +0100 Subject: [PATCH 066/268] Add missing break --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index aad67ba5..b15a5edf 100644 --- a/noice.c +++ b/noice.c @@ -603,6 +603,7 @@ nochange: initcurses(); if (chdir(ipath) == -1) printwarn(); + break; } } From 61bc5cd817ca25f2a1b2c3d10f739772376d1dbe Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 15:13:21 +0100 Subject: [PATCH 067/268] Add 'c' command to change into a destination directory by typing the path --- README | 3 ++- noice.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/README b/README index a023074a..c43bf087 100644 --- a/README +++ b/README @@ -35,8 +35,9 @@ You can navigate the list using the following keybinds (hardcoded): | l | RIGHT | ^M | open file / directory (see section "File opening") | h | LEFT | ^? | navigate up one directory | / | & | | filter output -| q | | | exit program | ! | | | spawn shell in current directory +| c | | | type and change into destination directory +| q | | | exit program +------+-------+-------+--------------------------------------------------- File opening diff --git a/noice.c b/noice.c index b15a5edf..ba2774ae 100644 --- a/noice.c +++ b/noice.c @@ -204,6 +204,7 @@ enum { SEL_GOIN, SEL_FLTR, SEL_SH, + SEL_CD, }; int @@ -258,6 +259,8 @@ nextsel(int *cur, int max) break; case '!': return SEL_SH; + case 'c': + return SEL_CD; } return 0; @@ -604,6 +607,28 @@ nochange: if (chdir(ipath) == -1) printwarn(); break; + case SEL_CD: + /* Read target dir */ + printmsg(""); + move(LINES - 1, 0); + printw("chdir: "); + tmp = readln(); + if (tmp == NULL) { + printmsg(""); + goto nochange; + } + if (testopendir(tmp) == 0) { + printwarn(); + goto nochange; + } else { + free(path); + path = strdup(tmp); + free(filter); + filter = strdup(ifilter); /* Reset filter */ + DPRINTF_S(path); + cur = 0; + goto out; + } } } From 330adc995f4528a29626b34da0a3d885b98139f7 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 15:17:44 +0100 Subject: [PATCH 068/268] No need to strdup() --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index ba2774ae..ee70d582 100644 --- a/noice.c +++ b/noice.c @@ -622,7 +622,7 @@ nochange: goto nochange; } else { free(path); - path = strdup(tmp); + path = tmp; free(filter); filter = strdup(ifilter); /* Reset filter */ DPRINTF_S(path); From cfd530b167a36a613fa9e8b55246a7b388c02005 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 15:29:35 +0100 Subject: [PATCH 069/268] Fix segfault in readln() This could be reproduced simply by doing: [TAB] and backspacing a few times. --- noice.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index ee70d582..12c8ae90 100644 --- a/noice.c +++ b/noice.c @@ -287,8 +287,13 @@ readln(void) if (c == KEY_BACKSPACE) { getyx(stdscr, y, x); if (x >= x0) { - ln = realloc(ln, (i - 1) * sizeof(*ln)); - i--; + if (i > 0) { + ln = realloc(ln, (i - 1) * sizeof(*ln)); + i--; + } else { + free(ln); + ln = NULL; + } move(y, x); printw("%c", ' '); move(y, x); From fef2d63e7608a6facc09e837f5a3e37c05bfb33f Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 15:32:49 +0100 Subject: [PATCH 070/268] Update README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index c43bf087..79a9c653 100644 --- a/README +++ b/README @@ -36,7 +36,7 @@ You can navigate the list using the following keybinds (hardcoded): | h | LEFT | ^? | navigate up one directory | / | & | | filter output | ! | | | spawn shell in current directory -| c | | | type and change into destination directory +| c | | | chdir into the given path | q | | | exit program +------+-------+-------+--------------------------------------------------- From 56252bdf9862806bcfdf2b7521c37489e33e1bad Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 15:36:23 +0100 Subject: [PATCH 071/268] Add '*' suffix to executables --- noice.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/noice.c b/noice.c index 12c8ae90..9088c83a 100644 --- a/noice.c +++ b/noice.c @@ -349,6 +349,9 @@ printent(struct entry *ent, int active) } else if (S_ISLNK(ent->mode)) { cm = '@'; maxlen--; + } else if (ent->mode & S_IXUSR) { + cm = '*'; + maxlen--; } /* No text wrapping in entries */ From 3808dde64162455d349ca1075ccbbeb1184a078f Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 15:52:59 +0100 Subject: [PATCH 072/268] Always use realpath() and properly chdir() so relative changes via 'c' work --- noice.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/noice.c b/noice.c index 9088c83a..e288f92d 100644 --- a/noice.c +++ b/noice.c @@ -375,7 +375,7 @@ browse(const char *ipath, const char *ifilter) struct entry *dents; int i, n, cur; int r, ret; - char *path = strdup(ipath); + char *path = realpath(ipath, NULL); char *filter = strdup(ifilter); regex_t filter_re; char *cwd; @@ -391,6 +391,9 @@ begin: if (dirp == NULL) { printwarn(); goto nochange; + } else { + if (chdir(path) == -1) + printwarn(); } /* Search filter */ @@ -607,13 +610,9 @@ nochange: cur = 0; goto out; case SEL_SH: - if (chdir(path) == -1) - printwarn(); exitcurses(); spawn("/bin/sh", NULL); initcurses(); - if (chdir(ipath) == -1) - printwarn(); break; case SEL_CD: /* Read target dir */ @@ -630,7 +629,8 @@ nochange: goto nochange; } else { free(path); - path = tmp; + path = realpath(tmp, NULL); + free(tmp); free(filter); filter = strdup(ifilter); /* Reset filter */ DPRINTF_S(path); From 4aa96d0a72c2020112724ce60a5d895f82f18206 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 16:24:08 +0100 Subject: [PATCH 073/268] Explain filters a bit more --- README | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README b/README index 79a9c653..1cbefae8 100644 --- a/README +++ b/README @@ -51,6 +51,16 @@ that does not match those regexes. The default program is less(1). For text files, you can use the 'v' commaind in less(1) to open the file in your $EDITOR. +Filters +------- + +Filters narrow down the view. This effectively allows you to easily search/jump +to a particular file or directory. If you want to reset the filter then you can +just use the match-any regex (i.e. .*). You can think of noice being in search +mode all the time. + +Filters do not stack or nest. They are applied afresh every time. + Contact ======= From 04767d440d32d2ee1866076d97685fda9284c08f Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 16:27:46 +0100 Subject: [PATCH 074/268] Fix typo --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 1cbefae8..0d388aa4 100644 --- a/README +++ b/README @@ -49,7 +49,7 @@ are specified by regexes, so you might experience issues when trying to open a f that does not match those regexes. The default program is less(1). For text files, you can use the 'v' -commaind in less(1) to open the file in your $EDITOR. +command in less(1) to open the file in your $EDITOR. Filters ------- From 12106af2a774159cf61934a235639ab4b6ef3bd5 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 16:34:31 +0100 Subject: [PATCH 075/268] Update outdated comment --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index e288f92d..cd938f3a 100644 --- a/noice.c +++ b/noice.c @@ -196,7 +196,7 @@ printerr(int ret, char *prefix) /* * Returns 0 normally * On movement it updates *cur - * Returns SEL_{QUIT,BACK,GOIN,FLTR} otherwise + * Returns SEL_{QUIT,BACK,GOIN,FLTR,SH,CD} otherwise */ enum { SEL_QUIT = 1, From 65c1dfe1678ba53f2a55e18d508b19a4348d7291 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 21 Oct 2014 16:52:40 +0100 Subject: [PATCH 076/268] Add install/uninstall targets --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 6ef05082..4146a777 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +PREFIX = /usr/local #CPPFLAGS += -DDEBUG #CFLAGS += -g LDLIBS = -lncursesw @@ -19,5 +20,15 @@ noice.o: noice.c queue.h util.h strlcpy.o: strlcpy.c util.h $(CC) $(CFLAGS) -c strlcpy.c +install: all + @echo installing $(BIN) to $(DESTDIR)$(PREFIX)/bin + @mkdir -p $(DESTDIR)$(PREFIX)/bin + @cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin + @chmod 755 $(DESTDIR)$(PREFIX)/bin/$(BIN) + +uninstall: + @echo removing $(BIN) from $(DESTDIR)$(PREFIX)/bin + @rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) + clean: rm -f $(BIN) $(OBJ) From ef11c024b9187f3b0317c5be304d8a62e2a5ed41 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 21 Oct 2014 20:42:01 +0300 Subject: [PATCH 077/268] Use double spacing on sentence start, smaller text width, style --- README | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/README b/README index 0d388aa4..5e9200f1 100644 --- a/README +++ b/README @@ -7,20 +7,22 @@ -- by lostd and sin ======================================================= + What is it? =========== noice is a small ncurses-based file manager. -It was first developed to be used with a tv remote control for a media center -solution. +It was first developed to be used with a tv remote control for a media +center solution. + Getting started =============== -Get the latest version from the git-repository; build and install it. -Run noice in a directory to display its content in the form of a list, where -each line is a file or directory. The currently selected item will be preceded -with a " > " by default. +Get the latest version from the git-repository; build and install it. Run +noice in a directory to display its content in the form of a list, where +each line is a file or directory. The currently selected item will be +preceded with a " > " by default. Navigation ---------- @@ -44,25 +46,26 @@ File opening ------------ Depending on the filetype, noice will open the selected file with the -application specified in `config.h` at compilation time. The associations -are specified by regexes, so you might experience issues when trying to open a file -that does not match those regexes. +application specified in `config.h` at compilation time. The associations +are specified by regexes, so you might experience issues when trying to +open a file that does not match those regexes. -The default program is less(1). For text files, you can use the 'v' -command in less(1) to open the file in your $EDITOR. +The default program is `less(1)`. For text files, you can use the 'v' +command in `less(1)` to open the file in your $EDITOR. Filters ------- -Filters narrow down the view. This effectively allows you to easily search/jump -to a particular file or directory. If you want to reset the filter then you can -just use the match-any regex (i.e. .*). You can think of noice being in search -mode all the time. +Filters narrow down the view. This effectively allows you to easily +search/jump to a particular file or directory. If you want to reset the +filter then you can just use the match-any regex (i.e. '.'). You can +think of noice being in search mode all the time. Filters do not stack or nest. They are applied afresh every time. + Contact ======= -You can reach us through the freenode IRC network at #2f30. -If you have any patches, ideas or feedback feel free to join. +You can reach us through the freenode IRC network at #2f30. If you have +any patches, ideas or feedback feel free to join. From 8e0f853f20768fba32654a816da86c2691a54bcd Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 21 Oct 2014 22:58:46 +0300 Subject: [PATCH 078/268] Still use some of the implicit magic --- Makefile | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 4146a777..5648b572 100644 --- a/Makefile +++ b/Makefile @@ -7,18 +7,11 @@ BIN = noice all: $(BIN) -$(BIN): config.h $(OBJ) +$(BIN): $(OBJ) $(CC) $(CFLAGS) -o $@ $(OBJ) $(LDLIBS) -config.h: - @echo copying config.def.h to $@ - @cp config.def.h $@ - -noice.o: noice.c queue.h util.h - $(CC) $(CFLAGS) $(CPPFLAGS) -c noice.c - -strlcpy.o: strlcpy.c util.h - $(CC) $(CFLAGS) -c strlcpy.c +noice.o: queue.h util.h config.h +strlcpy.o: util.h install: all @echo installing $(BIN) to $(DESTDIR)$(PREFIX)/bin @@ -32,3 +25,8 @@ uninstall: clean: rm -f $(BIN) $(OBJ) + +.SUFFIXES: .def.h + +.def.h.h: + cp $< $@ From 6d991593d67c9957074a1277994f63fefc009fc3 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 12:52:45 +0100 Subject: [PATCH 079/268] Add manpage --- Makefile | 7 +++++ noice.1 | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 noice.1 diff --git a/Makefile b/Makefile index 5648b572..4bbbd9c0 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,10 @@ PREFIX = /usr/local +MANPREFIX = $(PREFIX)/man + #CPPFLAGS += -DDEBUG #CFLAGS += -g LDLIBS = -lncursesw + OBJ = noice.o strlcpy.o BIN = noice @@ -18,10 +21,14 @@ install: all @mkdir -p $(DESTDIR)$(PREFIX)/bin @cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin @chmod 755 $(DESTDIR)$(PREFIX)/bin/$(BIN) + @echo installing $(BIN).1 to $(DESTDIR)$(MANPREFIX)/man1 + @cp -f $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1 uninstall: @echo removing $(BIN) from $(DESTDIR)$(PREFIX)/bin @rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) + @echo removing $(BIN).1 from $(DESTDIR)$(MANPREFIX)/man1 + @rm -f $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1 clean: rm -f $(BIN) $(OBJ) diff --git a/noice.1 b/noice.1 new file mode 100644 index 00000000..3e4d97b0 --- /dev/null +++ b/noice.1 @@ -0,0 +1,83 @@ +.Dd Oct 22, 2014 +.Dt NOICE 1 +.Os +.Sh NAME +.Nm noice +.Nd small file manager +.Sh SYNOPSIS +.Nm noice +.Op Ar dir +.Sh DESCRIPTION +.Nm +is a simple and efficient file manager that gets out of your way +as much as possible. It was initially implemented to be controlled +with a TV remote control. +.Pp +.Nm +supports both vi-like and emacs-like key bindings in the default +configuration. The default key bindings are described below; +their functionality is described in more detail later. +.Pp +.Bl -tag -width "h | Left | BackspaceXXXX" -offset indent -compact +.It Ic k | Up | C-p +Move to previous entry. +.It Ic j | Down | C-n +Move to next entry. +.It Ic Pgup | C-u +Scroll backwards one page. +.It Ic Pgdown | C-d +Scroll forwards one page. +.It Ic l | Right | C-m +Open file or enter directory. +.It Ic h | Left | Backspace +Back up one directory level. +.It Ic / | & +Filter view (see below for more details). +.It Ic ! +Spawn shell in current directory. +.It Ic c +Change into the given directory. +.It Ic q +Quit +.Nm . +.Sh CONFIGURATION +.Nm +is configured by modifying +.Pa config.h +and recompiling the code. +.Pp +The file associations are specified by regexes +matching on the currently selected filename. If a match is found the associated +program is executed with the filename passed in as the argument. If no match +is found the program less(1) is invoked. This is useful for editing text files +as one can use the 'v' command in less(1) to edit the file in $EDITOR. +.Pp +See the examples section below for more information. +.Sh FILTERS +Filters allow you to use regexes to display only the matched +entries in the current directory view. This effectively allows +searching through the directory tree for a particular entry. +.Pp +Filters do not stack on top of each other. They are applied anew +every time. +.Pp +To reset the filter you can use the match-any regex (i.e. '.'). +.Sh EXAMPLES +The following example shows one possible configuration for +file associations. This is the default configuration for +.Nm . +.Bd -literal +struct assoc assocs[] = { + { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, + { "\\.(png|jpg|gif)$", "feh" }, + { "\\.(html|svg)$", "firefox" }, + { "\\.pdf$", "mupdf" }, + { "\\.sh$", "sh" }, + { ".*", "less" }, +}; +.Ed +.Pp +.Sh AUTHORS +.Nm +was developed by Lazaros Koromilas with +contributions by sin . From c941b58c6865b9acb28fe51bce5a2cac4666b4a6 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 12:53:02 +0100 Subject: [PATCH 080/268] Remove TODO --- TODO | 1 - 1 file changed, 1 deletion(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 855ae147..00000000 --- a/TODO +++ /dev/null @@ -1 +0,0 @@ -- Searching using slash and next keys. From 55f74a0e88cad3c68e46edabe0d0dbbc9296c3f1 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 12:57:22 +0100 Subject: [PATCH 081/268] Fix manpage .Bl needs a matching .El --- noice.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.1 b/noice.1 index 3e4d97b0..dde2cb27 100644 --- a/noice.1 +++ b/noice.1 @@ -40,6 +40,7 @@ Change into the given directory. .It Ic q Quit .Nm . +.El .Sh CONFIGURATION .Nm is configured by modifying From 6935d1a6cf259619c4b5f1556e64b9c09a1c17a4 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 13:24:35 +0100 Subject: [PATCH 082/268] Remove duplicate info from README It is a pain to maintain both the README and the manpage. --- README | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/README b/README index 5e9200f1..5afe5fca 100644 --- a/README +++ b/README @@ -24,44 +24,7 @@ noice in a directory to display its content in the form of a list, where each line is a file or directory. The currently selected item will be preceded with a " > " by default. -Navigation ----------- - -You can navigate the list using the following keybinds (hardcoded): - -+------+-------+-------+--------------------------------------------------- -| k | UP | ^P | go up -| j | DOWN | ^N | go down -| | PGUP | ^U | go up (fast) -| | PGDN | ^D | go down (fast) -| l | RIGHT | ^M | open file / directory (see section "File opening") -| h | LEFT | ^? | navigate up one directory -| / | & | | filter output -| ! | | | spawn shell in current directory -| c | | | chdir into the given path -| q | | | exit program -+------+-------+-------+--------------------------------------------------- - -File opening ------------- - -Depending on the filetype, noice will open the selected file with the -application specified in `config.h` at compilation time. The associations -are specified by regexes, so you might experience issues when trying to -open a file that does not match those regexes. - -The default program is `less(1)`. For text files, you can use the 'v' -command in `less(1)` to open the file in your $EDITOR. - -Filters -------- - -Filters narrow down the view. This effectively allows you to easily -search/jump to a particular file or directory. If you want to reset the -filter then you can just use the match-any regex (i.e. '.'). You can -think of noice being in search mode all the time. - -Filters do not stack or nest. They are applied afresh every time. +For more information refer to the manpage. Contact From 7852edcbaf1374b4a64cbb3c4a737d1e2928b4a2 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 13:28:00 +0100 Subject: [PATCH 083/268] Clarify filter semantics when executed as root --- noice.1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/noice.1 b/noice.1 index dde2cb27..fd85f439 100644 --- a/noice.1 +++ b/noice.1 @@ -14,6 +14,11 @@ as much as possible. It was initially implemented to be controlled with a TV remote control. .Pp .Nm +defaults to the current directory if +.Ar dir +is not specified. +.Pp +.Nm supports both vi-like and emacs-like key bindings in the default configuration. The default key bindings are described below; their functionality is described in more detail later. @@ -63,6 +68,11 @@ Filters do not stack on top of each other. They are applied anew every time. .Pp To reset the filter you can use the match-any regex (i.e. '.'). +.Pp +If +.Nm +is invoked as root the default filter will also match hidden +files. .Sh EXAMPLES The following example shows one possible configuration for file associations. This is the default configuration for From 2e729d3f63ee9990256e316ec5fdd099c0a65185 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 13:55:10 +0100 Subject: [PATCH 084/268] Update keybind list --- noice.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noice.1 b/noice.1 index fd85f439..82d44c32 100644 --- a/noice.1 +++ b/noice.1 @@ -23,7 +23,7 @@ supports both vi-like and emacs-like key bindings in the default configuration. The default key bindings are described below; their functionality is described in more detail later. .Pp -.Bl -tag -width "h | Left | BackspaceXXXX" -offset indent -compact +.Bl -tag -width "l | Right | Return | C-mXXXX" -offset indent -compact .It Ic k | Up | C-p Move to previous entry. .It Ic j | Down | C-n @@ -32,7 +32,7 @@ Move to next entry. Scroll backwards one page. .It Ic Pgdown | C-d Scroll forwards one page. -.It Ic l | Right | C-m +.It Ic l | Right | Return | C-m Open file or enter directory. .It Ic h | Left | Backspace Back up one directory level. From da0f20f52ba718dc1a8d1af6674c6e2e14981dca Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 13:57:24 +0100 Subject: [PATCH 085/268] Update manpage wording --- noice.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index 82d44c32..40eae676 100644 --- a/noice.1 +++ b/noice.1 @@ -37,7 +37,7 @@ Open file or enter directory. .It Ic h | Left | Backspace Back up one directory level. .It Ic / | & -Filter view (see below for more details). +Filter view (see below for more information). .It Ic ! Spawn shell in current directory. .It Ic c From 8326a75762cc4e842a9827f286d5cbcaaae54697 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:08:16 +0100 Subject: [PATCH 086/268] printerr() should print to stderr --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index cd938f3a..b8e0b4ad 100644 --- a/noice.c +++ b/noice.c @@ -189,7 +189,7 @@ void printerr(int ret, char *prefix) { exitcurses(); - printf("%s: %s\n", prefix, strerror(errno)); + fprintf(stderr, "%s: %s\n", prefix, strerror(errno)); exit(ret); } From 7d4d60e778e6ba2623784a249d26145ddf6a6acf Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:10:04 +0100 Subject: [PATCH 087/268] Add xmalloc() + xrealloc() --- noice.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/noice.c b/noice.c index b8e0b4ad..5ddec69b 100644 --- a/noice.c +++ b/noice.c @@ -76,6 +76,26 @@ void printmsg(char *msg); void printwarn(void); void printerr(int ret, char *prefix); +void * +xmalloc(size_t size) +{ + void *p; + + p = malloc(size); + if (!p) + printerr(1, "malloc"); + return p; +} + +void * +xrealloc(void *ptr, size_t size) +{ + ptr = realloc(ptr, size); + if (!ptr) + printerr(1, "realloc"); + return ptr; +} + void spawn(const char *file, const char *arg) { @@ -123,7 +143,7 @@ setfilter(regex_t *regex, char *filter) r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED); if (r != 0) { - errbuf = malloc(COLS * sizeof(char)); + errbuf = xmalloc(COLS * sizeof(char)); regerror(r, regex, errbuf, COLS * sizeof(char)); printmsg(errbuf); free(errbuf); @@ -288,7 +308,7 @@ readln(void) getyx(stdscr, y, x); if (x >= x0) { if (i > 0) { - ln = realloc(ln, (i - 1) * sizeof(*ln)); + ln = xrealloc(ln, (i - 1) * sizeof(*ln)); i--; } else { free(ln); @@ -302,12 +322,12 @@ readln(void) } continue; } - ln = realloc(ln, (i + 1) * sizeof(*ln)); + ln = xrealloc(ln, (i + 1) * sizeof(*ln)); ln[i] = c; i++; } if (ln != NULL) { - ln = realloc(ln, (i + 1) * sizeof(*ln)); + ln = xrealloc(ln, (i + 1) * sizeof(*ln)); ln[i] = '\0'; } @@ -411,9 +431,7 @@ begin: if (!visible(&filter_re, dp->d_name)) continue; /* Deep copy because readdir(3) reuses the entries */ - dents = realloc(dents, (n + 1) * sizeof(*dents)); - if (dents == NULL) - printerr(1, "realloc"); + dents = xrealloc(dents, (n + 1) * sizeof(*dents)); dents[n].name = strdup(dp->d_name); if (dents[n].name == NULL) printerr(1, "strdup"); @@ -466,7 +484,7 @@ redraw: DPRINTF_S(path); /* No text wrapping in cwd line */ - cwd = malloc(COLS * sizeof(char)); + cwd = xmalloc(COLS * sizeof(char)); strlcpy(cwd, path, COLS * sizeof(char)); cwd[COLS - strlen(CWD) - 1] = '\0'; @@ -505,7 +523,7 @@ nochange: goto nochange; } else { dir = dirname(path); - tmp = malloc(strlen(dir) + 1); + tmp = xmalloc(strlen(dir) + 1); strlcpy(tmp, dir, strlen(dir) + 1); free(path); path = tmp; @@ -561,7 +579,7 @@ nochange: free(filter); filter = strdup(ifilter); /* Reset filter */ /* Save history */ - hist = malloc(sizeof(struct history)); + hist = xmalloc(sizeof(struct history)); hist->pos = cur; SLIST_INSERT_HEAD(&histhead, hist, entry); cur = 0; From 9d25101ad9be009d4bceb56c67e01c2b5857129f Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:15:27 +0100 Subject: [PATCH 088/268] Add xstrdup() and xrealpath() --- noice.c | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/noice.c b/noice.c index 5ddec69b..573c90ad 100644 --- a/noice.c +++ b/noice.c @@ -82,18 +82,40 @@ xmalloc(size_t size) void *p; p = malloc(size); - if (!p) + if (p == NULL) printerr(1, "malloc"); return p; } void * -xrealloc(void *ptr, size_t size) +xrealloc(void *p, size_t size) { - ptr = realloc(ptr, size); - if (!ptr) + p = realloc(p, size); + if (p == NULL) printerr(1, "realloc"); - return ptr; + return p; +} + +char * +xstrdup(const char *s) +{ + char *p; + + p = strdup(s); + if (p == NULL) + printerr(1, "strdup"); + return p; +} + +char * +xrealpath(const char *pathname) +{ + char *p; + + p = realpath(pathname, NULL); + if (p == NULL) + printerr(1, "realpath"); + return p; } void @@ -359,9 +381,7 @@ printent(struct entry *ent, int active) char cm = 0; /* Copy name locally */ - name = strdup(ent->name); - if (name == NULL) - printerr(1, "strdup name"); + name = xstrdup(ent->name); if (S_ISDIR(ent->mode)) { cm = '/'; @@ -395,8 +415,8 @@ browse(const char *ipath, const char *ifilter) struct entry *dents; int i, n, cur; int r, ret; - char *path = realpath(ipath, NULL); - char *filter = strdup(ifilter); + char *path = xrealpath(ipath); + char *filter = xstrdup(ifilter); regex_t filter_re; char *cwd; struct stat sb; @@ -432,9 +452,7 @@ begin: continue; /* Deep copy because readdir(3) reuses the entries */ dents = xrealloc(dents, (n + 1) * sizeof(*dents)); - dents[n].name = strdup(dp->d_name); - if (dents[n].name == NULL) - printerr(1, "strdup"); + dents[n].name = xstrdup(dp->d_name); /* Handle root case */ if (strcmp(path, "/") == 0) asprintf(&name, "/%s", dents[n].name); @@ -528,7 +546,7 @@ nochange: free(path); path = tmp; free(filter); - filter = strdup(ifilter); /* Reset filter */ + filter = xstrdup(ifilter); /* Reset filter */ /* Recall history */ hist = SLIST_FIRST(&histhead); if (hist != NULL) { @@ -577,7 +595,7 @@ nochange: free(path); path = pathnew; free(filter); - filter = strdup(ifilter); /* Reset filter */ + filter = xstrdup(ifilter); /* Reset filter */ /* Save history */ hist = xmalloc(sizeof(struct history)); hist->pos = cur; @@ -647,10 +665,10 @@ nochange: goto nochange; } else { free(path); - path = realpath(tmp, NULL); + path = xrealpath(tmp); free(tmp); free(filter); - filter = strdup(ifilter); /* Reset filter */ + filter = xstrdup(ifilter); /* Reset filter */ DPRINTF_S(path); cur = 0; goto out; From abd301333da81b72070fbb575dcd0824d3af038e Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:18:15 +0100 Subject: [PATCH 089/268] No need to manually strip trailing slashes We use realpath() now. --- noice.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/noice.c b/noice.c index 573c90ad..b7f3ba08 100644 --- a/noice.c +++ b/noice.c @@ -491,13 +491,6 @@ redraw: /* Clean screen */ erase(); - /* Strip trailing slashes */ - for (i = strlen(path) - 1; i > 0; i--) - if (path[i] == '/') - path[i] = '\0'; - else - break; - DPRINTF_D(cur); DPRINTF_S(path); From 75143cd93ec82eb1346eefa955ed42f189d6f449 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:22:55 +0100 Subject: [PATCH 090/268] Add xdirname() to avoid quirks with dirname(3) --- noice.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index b7f3ba08..71e4897b 100644 --- a/noice.c +++ b/noice.c @@ -108,16 +108,30 @@ xstrdup(const char *s) } char * -xrealpath(const char *pathname) +xrealpath(const char *path) { char *p; - p = realpath(pathname, NULL); + p = realpath(path, NULL); if (p == NULL) printerr(1, "realpath"); return p; } +char * +xdirname(const char *path) +{ + char *p, *tmp; + + /* Some implementations of dirname(3) may modify `path' */ + tmp = xstrdup(path); + p = dirname(tmp); + free(tmp); + if (p == NULL) + printerr(1, "dirname"); + return p; +} + void spawn(const char *file, const char *arg) { @@ -533,7 +547,7 @@ nochange: if (strcmp(path, "/") == 0) { goto nochange; } else { - dir = dirname(path); + dir = xdirname(path); tmp = xmalloc(strlen(dir) + 1); strlcpy(tmp, dir, strlen(dir) + 1); free(path); From 9f3241b0837757304dc631311856db9ba009fb1f Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:28:47 +0100 Subject: [PATCH 091/268] Add section on history --- noice.1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/noice.1 b/noice.1 index 40eae676..28079b62 100644 --- a/noice.1 +++ b/noice.1 @@ -73,6 +73,14 @@ If .Nm is invoked as root the default filter will also match hidden files. +.Sh HISTORY +.Nm +keeps track of the current cursor position per directory +level. Backing up one directory level will restore the +cursor position at that level. +.Pp +History is discarded for the backed out directory. In other +words, history is recorded only when entering directories. .Sh EXAMPLES The following example shows one possible configuration for file associations. This is the default configuration for From 5aceade801f5d7c7cf44e528a9eae3ff24edfc72 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 16:26:58 +0300 Subject: [PATCH 092/268] Forget all history on manual dir change --- noice.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/noice.c b/noice.c index 71e4897b..f41c90aa 100644 --- a/noice.c +++ b/noice.c @@ -676,6 +676,12 @@ nochange: free(tmp); free(filter); filter = xstrdup(ifilter); /* Reset filter */ + /* Forget history */ + while (!SLIST_EMPTY(&histhead)) { + hist = SLIST_FIRST(&histhead); + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); + } DPRINTF_S(path); cur = 0; goto out; From ef7082b69181fa4857486e473ef67b04b1186be1 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:33:00 +0100 Subject: [PATCH 093/268] Use stat() instead of open() + fstat() --- noice.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/noice.c b/noice.c index f41c90aa..ff11b2f2 100644 --- a/noice.c +++ b/noice.c @@ -493,7 +493,6 @@ begin: char *pathnew; char *name; char *bin; - int fd; char *dir; char *tmp; regex_t re; @@ -583,14 +582,7 @@ nochange: DPRINTF_S(pathnew); /* Get path info */ - fd = open(pathnew, O_RDONLY | O_NONBLOCK); - if (fd == -1) { - printwarn(); - free(pathnew); - goto nochange; - } - r = fstat(fd, &sb); - close(fd); + r = stat(pathnew, &sb); if (r == -1) { printwarn(); free(pathnew); @@ -619,11 +611,9 @@ nochange: free(pathnew); goto nochange; } - exitcurses(); spawn(bin, pathnew); initcurses(); - free(pathnew); goto redraw; } From 577e0284a11f675b7b9845da7e3a8006905b4fcf Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:44:16 +0100 Subject: [PATCH 094/268] Remove xdirname() dirname(3) should be shot to death. --- noice.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/noice.c b/noice.c index ff11b2f2..7a6d6751 100644 --- a/noice.c +++ b/noice.c @@ -118,20 +118,6 @@ xrealpath(const char *path) return p; } -char * -xdirname(const char *path) -{ - char *p, *tmp; - - /* Some implementations of dirname(3) may modify `path' */ - tmp = xstrdup(path); - p = dirname(tmp); - free(tmp); - if (p == NULL) - printerr(1, "dirname"); - return p; -} - void spawn(const char *file, const char *arg) { @@ -546,7 +532,7 @@ nochange: if (strcmp(path, "/") == 0) { goto nochange; } else { - dir = xdirname(path); + dir = dirname(path); tmp = xmalloc(strlen(dir) + 1); strlcpy(tmp, dir, strlen(dir) + 1); free(path); From 36cf4136b5ec5ddc1e84b426e1992b599efbe6ae Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 17:02:15 +0300 Subject: [PATCH 095/268] Add xdirname() again and give dirname(3) another chance --- noice.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 7a6d6751..e804e686 100644 --- a/noice.c +++ b/noice.c @@ -118,6 +118,25 @@ xrealpath(const char *path) return p; } +char * +xdirname(const char *path) +{ + char *p, *tmp; + + /* Some implementations of dirname(3) may modify `path' and some + * return a pointer inside `path` and we cannot free(3) the + * original string if we lose track of it. */ + tmp = xstrdup(path); + p = dirname(tmp); + free(tmp); + if (p == NULL) + printerr(1, "dirname"); + + /* Make sure this is a malloc(3)-ed string */ + p = xstrdup(p); + return p; +} + void spawn(const char *file, const char *arg) { @@ -532,7 +551,7 @@ nochange: if (strcmp(path, "/") == 0) { goto nochange; } else { - dir = dirname(path); + dir = xdirname(path); tmp = xmalloc(strlen(dir) + 1); strlcpy(tmp, dir, strlen(dir) + 1); free(path); From 6d04c5329e57a7305dea779f599743ccab9fd9a4 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 14:59:15 +0100 Subject: [PATCH 096/268] Add a KNOWN ISSUES sections --- noice.1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/noice.1 b/noice.1 index 28079b62..627a5939 100644 --- a/noice.1 +++ b/noice.1 @@ -95,6 +95,9 @@ struct assoc assocs[] = { { ".*", "less" }, }; .Ed +.Sh KNOWN ISSUES +In urxvt you might have to start your terminal with +backspacekey set to DEC. .Pp .Sh AUTHORS .Nm From 35f3b250bb1e218a46da9e6287f31fb5aeaa3f62 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 15:05:14 +0100 Subject: [PATCH 097/268] Only free() after xstrdup() --- noice.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noice.c b/noice.c index e804e686..37cc91db 100644 --- a/noice.c +++ b/noice.c @@ -128,12 +128,11 @@ xdirname(const char *path) * original string if we lose track of it. */ tmp = xstrdup(path); p = dirname(tmp); - free(tmp); if (p == NULL) printerr(1, "dirname"); - /* Make sure this is a malloc(3)-ed string */ p = xstrdup(p); + free(tmp); return p; } From 9bc4b92474ded6ff9097525646311e424a5cddc3 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 15:14:33 +0100 Subject: [PATCH 098/268] No need for a temporary buffer xdirname() uses xstrdup() internally so we are safe to use that pointer directly. --- noice.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 37cc91db..820b851a 100644 --- a/noice.c +++ b/noice.c @@ -551,10 +551,8 @@ nochange: goto nochange; } else { dir = xdirname(path); - tmp = xmalloc(strlen(dir) + 1); - strlcpy(tmp, dir, strlen(dir) + 1); free(path); - path = tmp; + path = dir; free(filter); filter = xstrdup(ifilter); /* Reset filter */ /* Recall history */ From 0809871aebbdf51b0539ce70e7ff72a53cb1b2e6 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 17:21:53 +0300 Subject: [PATCH 099/268] Free tmp string if dirname fails --- noice.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 820b851a..24e687ae 100644 --- a/noice.c +++ b/noice.c @@ -128,8 +128,10 @@ xdirname(const char *path) * original string if we lose track of it. */ tmp = xstrdup(path); p = dirname(tmp); - if (p == NULL) + if (p == NULL) { + free(tmp); printerr(1, "dirname"); + } /* Make sure this is a malloc(3)-ed string */ p = xstrdup(p); free(tmp); From b2970c9516662f62d59ad6ca21f9809b5d1105a2 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 17:27:53 +0300 Subject: [PATCH 100/268] More accurate description --- README | 2 +- noice.1 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index 5afe5fca..0df5c4b6 100644 --- a/README +++ b/README @@ -11,7 +11,7 @@ What is it? =========== -noice is a small ncurses-based file manager. +noice is a small ncurses-based file browser. It was first developed to be used with a tv remote control for a media center solution. diff --git a/noice.1 b/noice.1 index 627a5939..32f4a573 100644 --- a/noice.1 +++ b/noice.1 @@ -3,13 +3,13 @@ .Os .Sh NAME .Nm noice -.Nd small file manager +.Nd small file browser .Sh SYNOPSIS .Nm noice .Op Ar dir .Sh DESCRIPTION .Nm -is a simple and efficient file manager that gets out of your way +is a simple and efficient file browser that gets out of your way as much as possible. It was initially implemented to be controlled with a TV remote control. .Pp From 5335be58322644e16f6478539b4f5846a1f80ac8 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 17:54:13 +0300 Subject: [PATCH 101/268] Functions for setting and clearing the prompt --- noice.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/noice.c b/noice.c index 24e687ae..f983fefe 100644 --- a/noice.c +++ b/noice.c @@ -255,6 +255,21 @@ printerr(int ret, char *prefix) exit(ret); } +/* Clear the last line */ +void +clearprompt(void) +{ + printmsg(""); +} + +/* Print prompt on the last line */ +void +printprompt(char *str) +{ + clearprompt(); + printw(str); +} + /* * Returns 0 normally * On movement it updates *cur @@ -627,12 +642,10 @@ nochange: goto nochange; case SEL_FLTR: /* Read filter */ - printmsg(""); - move(LINES - 1, 0); - printw("filter: "); + printprompt("filter: "); tmp = readln(); if (tmp == NULL) { - printmsg(""); + clearprompt(); goto nochange; } r = setfilter(&re, tmp); @@ -653,12 +666,10 @@ nochange: break; case SEL_CD: /* Read target dir */ - printmsg(""); - move(LINES - 1, 0); - printw("chdir: "); + printprompt("chdir: "); tmp = readln(); if (tmp == NULL) { - printmsg(""); + clearprompt(); goto nochange; } if (testopendir(tmp) == 0) { From 32bce991be84ba1e5ae1cb81bfe48738e4977077 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:21:50 +0100 Subject: [PATCH 102/268] Add dentfill() and dentfree() --- noice.c | 70 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/noice.c b/noice.c index f983fefe..42a1d0da 100644 --- a/noice.c +++ b/noice.c @@ -441,6 +441,46 @@ printent(struct entry *ent, int active) free(name); } +int +dentfill(DIR *dirp, struct entry **dents, + int (*filter)(regex_t *, char *), regex_t *re) +{ + struct dirent *dp; + struct stat sb; + int n = 0; + int r; + + while ((dp = readdir(dirp)) != NULL) { + /* Skip self and parent */ + if (strcmp(dp->d_name, ".") == 0 + || strcmp(dp->d_name, "..") == 0) + continue; + if (filter(re, dp->d_name) == 0) + continue; + *dents = xrealloc(*dents, (n + 1) * sizeof(**dents)); + (*dents)[n].name = xstrdup(dp->d_name); + /* Get mode flags */ + r = fstatat(dirfd(dirp), dp->d_name, &sb, + AT_SYMLINK_NOFOLLOW); + if (r == -1) + printerr(1, "stat"); + (*dents)[n].mode = sb.st_mode; + n++; + } + + return n; +} + +void +dentfree(struct entry *dents, int n) +{ + int i; + + for (i = 0; i < n; i++) + free(dents[i].name); + free(dents); +} + void browse(const char *ipath, const char *ifilter) { @@ -476,31 +516,7 @@ begin: if (r != 0) goto nochange; - while ((dp = readdir(dirp)) != NULL) { - char *name; - - /* Skip self and parent */ - if (strcmp(dp->d_name, ".") == 0 - || strcmp(dp->d_name, "..") == 0) - continue; - if (!visible(&filter_re, dp->d_name)) - continue; - /* Deep copy because readdir(3) reuses the entries */ - dents = xrealloc(dents, (n + 1) * sizeof(*dents)); - dents[n].name = xstrdup(dp->d_name); - /* Handle root case */ - if (strcmp(path, "/") == 0) - asprintf(&name, "/%s", dents[n].name); - else - asprintf(&name, "%s/%s", path, dents[n].name); - /* Get mode flags */ - r = lstat(name, &sb); - free(name); - if (r == -1) - printerr(1, "stat"); - dents[n].mode = sb.st_mode; - n++; - } + n = dentfill(dirp, &dents, visible, &filter_re); /* Make sure cur is in range */ cur = MIN(cur, n - 1); @@ -695,9 +711,7 @@ nochange: } out: - for (i = 0; i < n; i++) - free(dents[i].name); - free(dents); + dentfree(dents, n); /* Should never be null */ r = closedir(dirp); From 7ee4928a3f10e03186578e5da3a8eb44cc4e6b46 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 18:24:05 +0300 Subject: [PATCH 103/268] Just let the commands show up --- Makefile | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 4bbbd9c0..22130a54 100644 --- a/Makefile +++ b/Makefile @@ -17,18 +17,13 @@ noice.o: queue.h util.h config.h strlcpy.o: util.h install: all - @echo installing $(BIN) to $(DESTDIR)$(PREFIX)/bin - @mkdir -p $(DESTDIR)$(PREFIX)/bin - @cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin - @chmod 755 $(DESTDIR)$(PREFIX)/bin/$(BIN) - @echo installing $(BIN).1 to $(DESTDIR)$(MANPREFIX)/man1 - @cp -f $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1 + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin + cp -f $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1 uninstall: - @echo removing $(BIN) from $(DESTDIR)$(PREFIX)/bin - @rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) - @echo removing $(BIN).1 from $(DESTDIR)$(MANPREFIX)/man1 - @rm -f $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1 + rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) + rm -f $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1 clean: rm -f $(BIN) $(OBJ) From ce1fcfc7b8777d3d3459fad11d4941cc22f4eb9b Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:25:59 +0100 Subject: [PATCH 104/268] Remove unused vars --- noice.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/noice.c b/noice.c index 42a1d0da..21f4e42e 100644 --- a/noice.c +++ b/noice.c @@ -485,8 +485,6 @@ void browse(const char *ipath, const char *ifilter) { DIR *dirp; - int dfd; - struct dirent *dp; struct entry *dents; int i, n, cur; int r, ret; @@ -498,10 +496,6 @@ browse(const char *ipath, const char *ifilter) cur = 0; begin: - /* Path and filter should be malloc(3)-ed strings at all times */ - n = 0; - dents = NULL; - dirp = opendir(path); if (dirp == NULL) { printwarn(); @@ -525,7 +519,6 @@ begin: for (;;) { int nlines; - int maxlen; int odd; char *pathnew; char *name; From dbac1486c6f72845e2fdd524b58fec114f78ca91 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:27:08 +0100 Subject: [PATCH 105/268] Include sys/wait.h for waitpid() --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index 21f4e42e..6355defc 100644 --- a/noice.c +++ b/noice.c @@ -1,5 +1,6 @@ #include #include +#include #include #include From c6614067e4e47234c6e2602b6c963735135bd7ae Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:28:23 +0100 Subject: [PATCH 106/268] Remember to set dents to NULL --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index 6355defc..09a63db0 100644 --- a/noice.c +++ b/noice.c @@ -511,6 +511,7 @@ begin: if (r != 0) goto nochange; + dents = NULL; n = dentfill(dirp, &dents, visible, &filter_re); /* Make sure cur is in range */ From ce599b8e6bf44d089820b5b5558835e57f67db7b Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:30:27 +0100 Subject: [PATCH 107/268] Check getch() against ERR --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 09a63db0..a2599d7e 100644 --- a/noice.c +++ b/noice.c @@ -359,7 +359,7 @@ readln(void) getyx(stdscr, y, x); x0 = x; - while (c = getch()) { + while ((c = getch()) != ERR) { if (c == KEY_ENTER || c == '\r') break; if (c == KEY_BACKSPACE) { From b06a4d4eeb7d95af4f0b0b02a5cfe21b3e9de69d Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:33:59 +0100 Subject: [PATCH 108/268] Initialize `n' and `dents' --- noice.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index a2599d7e..48ee1057 100644 --- a/noice.c +++ b/noice.c @@ -497,6 +497,10 @@ browse(const char *ipath, const char *ifilter) cur = 0; begin: + /* Path and filter should be malloc(3)-ed strings at all times */ + n = 0; + dents = NULL; + dirp = opendir(path); if (dirp == NULL) { printwarn(); @@ -511,7 +515,6 @@ begin: if (r != 0) goto nochange; - dents = NULL; n = dentfill(dirp, &dents, visible, &filter_re); /* Make sure cur is in range */ From 05957936f5a7e452f4b8cda5bf50e92e745c4187 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:50:30 +0100 Subject: [PATCH 109/268] Use fstatat() wherever possible --- noice.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/noice.c b/noice.c index 48ee1057..a0a8f175 100644 --- a/noice.c +++ b/noice.c @@ -525,7 +525,6 @@ begin: for (;;) { int nlines; int odd; - char *pathnew; char *name; char *bin; char *dir; @@ -605,27 +604,19 @@ nochange: name = dents[cur].name; - /* Handle root case */ - if (strcmp(path, "/") == 0) - asprintf(&pathnew, "/%s", name); - else - asprintf(&pathnew, "%s/%s", path, name); - DPRINTF_S(name); - DPRINTF_S(pathnew); /* Get path info */ - r = stat(pathnew, &sb); + r = fstatat(dirfd(dirp), name, &sb, 0); if (r == -1) { printwarn(); - free(pathnew); goto nochange; } DPRINTF_U(sb.st_mode); - /* Directory */ - if (S_ISDIR(sb.st_mode)) { + switch (sb.st_mode & S_IFMT) { + case S_IFDIR: free(path); - path = pathnew; + path = xrealpath(name); free(filter); filter = xstrdup(ifilter); /* Reset filter */ /* Save history */ @@ -634,26 +625,21 @@ nochange: SLIST_INSERT_HEAD(&histhead, hist, entry); cur = 0; goto out; - } - /* Regular file */ - if (S_ISREG(sb.st_mode)) { + case S_IFREG: /* Open with */ bin = openwith(name); if (bin == NULL) { printmsg("No association"); - free(pathnew); goto nochange; } exitcurses(); - spawn(bin, pathnew); + spawn(bin, name); initcurses(); - free(pathnew); goto redraw; + default: + printmsg("Unsupported file"); + goto nochange; } - /* All the rest */ - printmsg("Unsupported file"); - free(pathnew); - goto nochange; case SEL_FLTR: /* Read filter */ printprompt("filter: "); From bc690212332bc9f461f75876606054c82fe34445 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:53:38 +0100 Subject: [PATCH 110/268] Save one level of indentation --- noice.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/noice.c b/noice.c index a0a8f175..4f48b2f3 100644 --- a/noice.c +++ b/noice.c @@ -577,26 +577,24 @@ nochange: return; case SEL_BACK: /* There is no going back */ - if (strcmp(path, "/") == 0) { + if (strcmp(path, "/") == 0) goto nochange; + dir = xdirname(path); + free(path); + path = dir; + free(filter); + filter = xstrdup(ifilter); /* Reset filter */ + /* Recall history */ + hist = SLIST_FIRST(&histhead); + if (hist != NULL) { + cur = hist->pos; + DPRINTF_D(hist->pos); + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); } else { - dir = xdirname(path); - free(path); - path = dir; - free(filter); - filter = xstrdup(ifilter); /* Reset filter */ - /* Recall history */ - hist = SLIST_FIRST(&histhead); - if (hist != NULL) { - cur = hist->pos; - DPRINTF_D(hist->pos); - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist); - } else { - cur = 0; - } - goto out; + cur = 0; } + goto out; case SEL_GOIN: /* Cannot descend in empty directories */ if (n == 0) From b39da16920b46dec42a5c3059cfeb1a2612667ee Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:55:26 +0100 Subject: [PATCH 111/268] Vertical spacing fixes --- noice.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 4f48b2f3..897bcb97 100644 --- a/noice.c +++ b/noice.c @@ -601,7 +601,6 @@ nochange: goto nochange; name = dents[cur].name; - DPRINTF_S(name); /* Get path info */ @@ -611,6 +610,7 @@ nochange: goto nochange; } DPRINTF_U(sb.st_mode); + switch (sb.st_mode & S_IFMT) { case S_IFDIR: free(path); @@ -624,7 +624,6 @@ nochange: cur = 0; goto out; case S_IFREG: - /* Open with */ bin = openwith(name); if (bin == NULL) { printmsg("No association"); From 1183a9428fa3d9462fd2272c8963f43b073d3d87 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 16:56:31 +0100 Subject: [PATCH 112/268] Save one level of indentation --- noice.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/noice.c b/noice.c index 897bcb97..73ecc0f2 100644 --- a/noice.c +++ b/noice.c @@ -672,22 +672,21 @@ nochange: if (testopendir(tmp) == 0) { printwarn(); goto nochange; - } else { - free(path); - path = xrealpath(tmp); - free(tmp); - free(filter); - filter = xstrdup(ifilter); /* Reset filter */ - /* Forget history */ - while (!SLIST_EMPTY(&histhead)) { - hist = SLIST_FIRST(&histhead); - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist); - } - DPRINTF_S(path); - cur = 0; - goto out; } + free(path); + path = xrealpath(tmp); + free(tmp); + free(filter); + filter = xstrdup(ifilter); /* Reset filter */ + /* Forget history */ + while (!SLIST_EMPTY(&histhead)) { + hist = SLIST_FIRST(&histhead); + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); + } + DPRINTF_S(path); + cur = 0; + goto out; } } From aedec0ddf3cfc31ba50e5a10f0f3655abcdb2438 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:07:04 +0100 Subject: [PATCH 113/268] Add pushhist(), pophist() and forgethist() --- noice.c | 76 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/noice.c b/noice.c index 73ecc0f2..90fc3bd1 100644 --- a/noice.c +++ b/noice.c @@ -482,6 +482,47 @@ dentfree(struct entry *dents, int n) free(dents); } +void +pushhist(int pos) +{ + struct history *hist; + + hist = xmalloc(sizeof(*hist)); + hist->pos = pos; + SLIST_INSERT_HEAD(&histhead, hist, entry); +} + +int +pophist(void) +{ + struct history *hist; + int pos; + + /* Recall history */ + hist = SLIST_FIRST(&histhead); + if (hist != NULL) { + pos = hist->pos; + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); + } else { + pos = 0; + } + + return pos; +} + +void +forgethist(void) +{ + struct history *hist; + + while (!SLIST_EMPTY(&histhead)) { + hist = SLIST_FIRST(&histhead); + SLIST_REMOVE_HEAD(&histhead, entry); + free(hist); + } +} + void browse(const char *ipath, const char *ifilter) { @@ -530,7 +571,6 @@ begin: char *dir; char *tmp; regex_t re; - struct history *hist; redraw: nlines = MIN(LINES - 4, n); @@ -569,11 +609,7 @@ nochange: free(path); free(filter); /* Forget history */ - while (!SLIST_EMPTY(&histhead)) { - hist = SLIST_FIRST(&histhead); - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist); - } + forgethist(); return; case SEL_BACK: /* There is no going back */ @@ -582,18 +618,11 @@ nochange: dir = xdirname(path); free(path); path = dir; + /* Reset filter */ free(filter); - filter = xstrdup(ifilter); /* Reset filter */ + filter = xstrdup(ifilter); /* Recall history */ - hist = SLIST_FIRST(&histhead); - if (hist != NULL) { - cur = hist->pos; - DPRINTF_D(hist->pos); - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist); - } else { - cur = 0; - } + cur = pophist(); goto out; case SEL_GOIN: /* Cannot descend in empty directories */ @@ -615,12 +644,11 @@ nochange: case S_IFDIR: free(path); path = xrealpath(name); + /* Reset filter */ free(filter); - filter = xstrdup(ifilter); /* Reset filter */ - /* Save history */ - hist = xmalloc(sizeof(struct history)); - hist->pos = cur; - SLIST_INSERT_HEAD(&histhead, hist, entry); + filter = xstrdup(ifilter); + /* Remember history */ + pushhist(cur); cur = 0; goto out; case S_IFREG: @@ -679,11 +707,7 @@ nochange: free(filter); filter = xstrdup(ifilter); /* Reset filter */ /* Forget history */ - while (!SLIST_EMPTY(&histhead)) { - hist = SLIST_FIRST(&histhead); - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist); - } + forgethist(); DPRINTF_S(path); cur = 0; goto out; From 48f9c5a79df7431c60aee74ddea0d4a47384a373 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:25:25 +0100 Subject: [PATCH 114/268] Test if we can back out/enter directories --- noice.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 90fc3bd1..9a9fc6a4 100644 --- a/noice.c +++ b/noice.c @@ -615,6 +615,10 @@ nochange: /* There is no going back */ if (strcmp(path, "/") == 0) goto nochange; + if (testopendir(path) == 0) { + printwarn(); + goto nochange; + } dir = xdirname(path); free(path); path = dir; @@ -642,6 +646,10 @@ nochange: switch (sb.st_mode & S_IFMT) { case S_IFDIR: + if (testopendir(path) == 0) { + printwarn(); + goto nochange; + } free(path); path = xrealpath(name); /* Reset filter */ @@ -745,7 +753,7 @@ main(int argc, char *argv[]) } /* Test initial path */ - if (!testopendir(ipath)) + if (testopendir(ipath) == 0) printerr(1, ipath); /* Set locale before curses setup */ From 789f9336f4bc2c73158e86cb6952726d63e70ec4 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:26:35 +0100 Subject: [PATCH 115/268] Rename testopendir() to canopendir() --- noice.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index 9a9fc6a4..89db4bd0 100644 --- a/noice.c +++ b/noice.c @@ -396,7 +396,7 @@ readln(void) } int -testopendir(char *path) +canopendir(char *path) { DIR *dirp; @@ -615,7 +615,7 @@ nochange: /* There is no going back */ if (strcmp(path, "/") == 0) goto nochange; - if (testopendir(path) == 0) { + if (canopendir(path) == 0) { printwarn(); goto nochange; } @@ -646,7 +646,7 @@ nochange: switch (sb.st_mode & S_IFMT) { case S_IFDIR: - if (testopendir(path) == 0) { + if (canopendir(path) == 0) { printwarn(); goto nochange; } @@ -705,7 +705,7 @@ nochange: clearprompt(); goto nochange; } - if (testopendir(tmp) == 0) { + if (canopendir(tmp) == 0) { printwarn(); goto nochange; } @@ -753,7 +753,7 @@ main(int argc, char *argv[]) } /* Test initial path */ - if (testopendir(ipath) == 0) + if (canopendir(ipath) == 0) printerr(1, ipath); /* Set locale before curses setup */ From 0e214e23b71453ecae331f51917cf6b0411784fd Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:28:27 +0100 Subject: [PATCH 116/268] Call dentfree() when we quit --- noice.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 89db4bd0..7dab6468 100644 --- a/noice.c +++ b/noice.c @@ -608,8 +608,8 @@ nochange: case SEL_QUIT: free(path); free(filter); - /* Forget history */ forgethist(); + dentfree(dents, n); return; case SEL_BACK: /* There is no going back */ @@ -714,7 +714,6 @@ nochange: free(tmp); free(filter); filter = xstrdup(ifilter); /* Reset filter */ - /* Forget history */ forgethist(); DPRINTF_S(path); cur = 0; From 1c467fce7adc8a3fd703c934ab3892be3c73715e Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:31:08 +0100 Subject: [PATCH 117/268] Style fix --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 7dab6468..3019dada 100644 --- a/noice.c +++ b/noice.c @@ -516,7 +516,7 @@ forgethist(void) { struct history *hist; - while (!SLIST_EMPTY(&histhead)) { + while (SLIST_EMPTY(&histhead) == 0) { hist = SLIST_FIRST(&histhead); SLIST_REMOVE_HEAD(&histhead, entry); free(hist); From 11ca2b408da2c2493cee813d92efd9c751e9f070 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:41:16 +0100 Subject: [PATCH 118/268] Some systems define this already. --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index 3019dada..e4f86a03 100644 --- a/noice.c +++ b/noice.c @@ -33,6 +33,7 @@ #endif /* DEBUG */ #define LEN(x) (sizeof(x) / sizeof(*(x))) +#undef MIN #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define ISODD(x) ((x) & 1) #define CONTROL(c) ((c) ^ 0x40) From 644dd348d6e0a85c9e8ce472e631a2713e07efcc Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:43:55 +0100 Subject: [PATCH 119/268] Manpage reword --- noice.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index 32f4a573..05911869 100644 --- a/noice.1 +++ b/noice.1 @@ -96,7 +96,7 @@ struct assoc assocs[] = { }; .Ed .Sh KNOWN ISSUES -In urxvt you might have to start your terminal with +If you are using urxvt you might have to start it with backspacekey set to DEC. .Pp .Sh AUTHORS From 8d018e620f159d63c1617a87844d11e51f7a3a23 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 22 Oct 2014 17:57:59 +0100 Subject: [PATCH 120/268] realloc() behaves like free() if size is 0 --- noice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index e4f86a03..638211d8 100644 --- a/noice.c +++ b/noice.c @@ -366,9 +366,9 @@ readln(void) if (c == KEY_BACKSPACE) { getyx(stdscr, y, x); if (x >= x0) { + i--; if (i > 0) { - ln = xrealloc(ln, (i - 1) * sizeof(*ln)); - i--; + ln = xrealloc(ln, i * sizeof(*ln)); } else { free(ln); ln = NULL; From aa555a3b35236a3cb8ff37da7388dfcde7426a2c Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 21:05:59 +0300 Subject: [PATCH 121/268] Keep history based on paths instead of positions --- noice.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/noice.c b/noice.c index 638211d8..4626286e 100644 --- a/noice.c +++ b/noice.c @@ -51,7 +51,7 @@ struct entry { }; struct history { - int pos; + char *path; SLIST_ENTRY(history) entry; }; @@ -483,33 +483,71 @@ dentfree(struct entry *dents, int n) free(dents); } +char * +makepath(char *dir, char *name) +{ + char *path; + + /* Handle root case */ + if (strcmp(dir, "/") == 0) + asprintf(&path, "/%s", name); + else + asprintf(&path, "%s/%s", dir, name); + + return path; +} + +/* Return the position of the matching entry or 0 otherwise */ +int +dentfind(struct entry *dents, int n, char *cwd, char *path) +{ + int i; + char *tmp; + + if (path == NULL) + return 0; + + for (i = 0; i < n; i++) { + tmp = makepath(cwd, dents[i].name); + DPRINTF_S(path); + DPRINTF_S(tmp); + if (strcmp(tmp, path) == 0) { + free(tmp); + return i; + } + free(tmp); + } + + return 0; +} + void -pushhist(int pos) +pushhist(char *path) { struct history *hist; hist = xmalloc(sizeof(*hist)); - hist->pos = pos; + hist->path = xstrdup(path); SLIST_INSERT_HEAD(&histhead, hist, entry); } -int +char * pophist(void) { struct history *hist; - int pos; + char *path; /* Recall history */ hist = SLIST_FIRST(&histhead); if (hist != NULL) { - pos = hist->pos; + path = hist->path; SLIST_REMOVE_HEAD(&histhead, entry); free(hist); } else { - pos = 0; + path = NULL; } - return pos; + return path; } void @@ -520,6 +558,7 @@ forgethist(void) while (SLIST_EMPTY(&histhead) == 0) { hist = SLIST_FIRST(&histhead); SLIST_REMOVE_HEAD(&histhead, entry); + free(hist->path); free(hist); } } @@ -536,8 +575,10 @@ browse(const char *ipath, const char *ifilter) regex_t filter_re; char *cwd; struct stat sb; + char *hpath; cur = 0; + hpath = NULL; begin: /* Path and filter should be malloc(3)-ed strings at all times */ n = 0; @@ -559,11 +600,13 @@ begin: n = dentfill(dirp, &dents, visible, &filter_re); - /* Make sure cur is in range */ - cur = MIN(cur, n - 1); - qsort(dents, n, sizeof(*dents), entrycmp); + /* Find cur from history */ + cur = dentfind(dents, n, path, hpath); + free(hpath); + hpath = NULL; + for (;;) { int nlines; int odd; @@ -627,7 +670,7 @@ nochange: free(filter); filter = xstrdup(ifilter); /* Recall history */ - cur = pophist(); + hpath = pophist(); goto out; case SEL_GOIN: /* Cannot descend in empty directories */ @@ -657,7 +700,7 @@ nochange: free(filter); filter = xstrdup(ifilter); /* Remember history */ - pushhist(cur); + pushhist(path); cur = 0; goto out; case S_IFREG: From 81239754064e6b5bfeeeb90d0043a3e48f13f65c Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 22:12:09 +0300 Subject: [PATCH 122/268] Strip trailing whitespace --- README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index 0df5c4b6..44e79eff 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ - __ - ___ ___ /\_\ ___ __ -/' _ `\ / __`\/\ \ /'___\ /'__`\ -/\ \/\ \/\ \L\ \ \ \/\ \__//\ __/ + __ + ___ ___ /\_\ ___ __ +/' _ `\ / __`\/\ \ /'___\ /'__`\ +/\ \/\ \/\ \L\ \ \ \/\ \__//\ __/ \ \_\ \_\ \____/\ \_\ \____\ \____\ \/_/\/_/\/___/ \/_/\/____/\/____/ -- by lostd and sin From d84c3b1079091298e7f92cf9fcf21416f3fe2c6d Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 22 Oct 2014 22:32:45 +0300 Subject: [PATCH 123/268] Only free history path if it is valid --- noice.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 4626286e..1d0a0c96 100644 --- a/noice.c +++ b/noice.c @@ -604,8 +604,10 @@ begin: /* Find cur from history */ cur = dentfind(dents, n, path, hpath); - free(hpath); - hpath = NULL; + if (hpath != NULL) { + free(hpath); + hpath = NULL; + } for (;;) { int nlines; From 1c23cbc2ad07ae62c47ce1b091c86dd112c469f9 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 00:12:57 +0300 Subject: [PATCH 124/268] Create test files and directories --- mktest.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 mktest.sh diff --git a/mktest.sh b/mktest.sh new file mode 100644 index 00000000..8ab7be50 --- /dev/null +++ b/mktest.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Create test files and directories + +test -e test && { + echo "Remove test and try again" + exit 1 +} + +mkdir test && cd test + +echo 'It works!' > normal.txt +ln -s normal.txt ln-normal.txt +ln -s normal.txt ln-normal +mkdir normal-dir +ln -s normal-dir ln-normal-dir +ln -s nowhere ln-nowhere +mkfifo mk-fifo +touch no-access && chmod 000 no-access +ln -s ../normal.txt normal-dir/ln-normal.txt +ln -s ../normal.txt normal-dir/ln-normal From a6060732964cf4e9212c9d69926b412b7a7b8fee Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 00:31:45 +0300 Subject: [PATCH 125/268] Try to open file to see access errors on the status bar --- noice.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 1d0a0c96..c276db39 100644 --- a/noice.c +++ b/noice.c @@ -569,7 +569,7 @@ browse(const char *ipath, const char *ifilter) DIR *dirp; struct entry *dents; int i, n, cur; - int r, ret; + int r, ret, fd; char *path = xrealpath(ipath); char *filter = xstrdup(ifilter); regex_t filter_re; @@ -683,6 +683,12 @@ nochange: DPRINTF_S(name); /* Get path info */ + fd = openat(dirfd(dirp), name, O_RDONLY | O_NONBLOCK); + if (fd == -1) { + printwarn(); + goto nochange; + } + close(fd); r = fstatat(dirfd(dirp), name, &sb, 0); if (r == -1) { printwarn(); From 8d4019f3aaae17fad2348e27c2b8dc0880544ce9 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 17:37:12 +0300 Subject: [PATCH 126/268] Only use chdir(3) just before spawning a shell --- noice.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/noice.c b/noice.c index c276db39..a44388e4 100644 --- a/noice.c +++ b/noice.c @@ -141,13 +141,15 @@ xdirname(const char *path) } void -spawn(const char *file, const char *arg) +spawn(const char *file, const char *arg, const char *dir) { pid_t pid; int status; pid = fork(); if (pid == 0) { + if (dir != NULL) + chdir(dir); execlp(file, file, arg, NULL); _exit(1); } else { @@ -570,10 +572,10 @@ browse(const char *ipath, const char *ifilter) struct entry *dents; int i, n, cur; int r, ret, fd; - char *path = xrealpath(ipath); + char *path = xstrdup(ipath); char *filter = xstrdup(ifilter); regex_t filter_re; - char *cwd; + char *cwd, *newpath; struct stat sb; char *hpath; @@ -588,9 +590,6 @@ begin: if (dirp == NULL) { printwarn(); goto nochange; - } else { - if (chdir(path) == -1) - printwarn(); } /* Search filter */ @@ -680,30 +679,35 @@ nochange: goto nochange; name = dents[cur].name; - DPRINTF_S(name); + newpath = makepath(path, name); + DPRINTF_S(newpath); /* Get path info */ - fd = openat(dirfd(dirp), name, O_RDONLY | O_NONBLOCK); + fd = open(newpath, O_RDONLY | O_NONBLOCK); if (fd == -1) { printwarn(); + free(newpath); + goto nochange; + } + r = fstat(fd, &sb); + if (r == -1) { + printwarn(); + close(fd); + free(newpath); goto nochange; } close(fd); - r = fstatat(dirfd(dirp), name, &sb, 0); - if (r == -1) { - printwarn(); - goto nochange; - } DPRINTF_U(sb.st_mode); switch (sb.st_mode & S_IFMT) { case S_IFDIR: - if (canopendir(path) == 0) { + if (canopendir(newpath) == 0) { printwarn(); + free(newpath); goto nochange; } free(path); - path = xrealpath(name); + path = newpath; /* Reset filter */ free(filter); filter = xstrdup(ifilter); @@ -715,11 +719,13 @@ nochange: bin = openwith(name); if (bin == NULL) { printmsg("No association"); + free(newpath); goto nochange; } exitcurses(); - spawn(bin, name); + spawn(bin, newpath, NULL); initcurses(); + free(newpath); goto redraw; default: printmsg("Unsupported file"); @@ -746,7 +752,7 @@ nochange: goto out; case SEL_SH: exitcurses(); - spawn("/bin/sh", NULL); + spawn("/bin/sh", NULL, path); initcurses(); break; case SEL_CD: @@ -757,13 +763,15 @@ nochange: clearprompt(); goto nochange; } - if (canopendir(tmp) == 0) { + newpath = makepath(path, tmp); + free(tmp); + if (canopendir(newpath) == 0) { + free(newpath); printwarn(); goto nochange; } free(path); - path = xrealpath(tmp); - free(tmp); + path = newpath; free(filter); filter = xstrdup(ifilter); /* Reset filter */ forgethist(); From 9407399230577243ee81a28af8d2c2744eb14ea7 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 17:39:39 +0300 Subject: [PATCH 127/268] Don't attempt to go back if on the relative root --- noice.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index a44388e4..c3d3728f 100644 --- a/noice.c +++ b/noice.c @@ -658,7 +658,9 @@ nochange: return; case SEL_BACK: /* There is no going back */ - if (strcmp(path, "/") == 0) + if (strcmp(path, "/") == 0 || + strcmp(path, ".") == 0 || + strchr(path, '/') == NULL) goto nochange; if (canopendir(path) == 0) { printwarn(); From 4b1b156a3b477f242f9cb0984558010c887a5c8a Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 17:53:26 +0300 Subject: [PATCH 128/268] If you call makepath() with an absolute name it returns a copy of it --- noice.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index c3d3728f..6b372fd2 100644 --- a/noice.c +++ b/noice.c @@ -490,11 +490,16 @@ makepath(char *dir, char *name) { char *path; - /* Handle root case */ - if (strcmp(dir, "/") == 0) - asprintf(&path, "/%s", name); - else - asprintf(&path, "%s/%s", dir, name); + /* Handle absolute path */ + if (name[0] == '/') { + path = xstrdup(name); + } else { + /* Handle root case */ + if (strcmp(dir, "/") == 0) + asprintf(&path, "/%s", name); + else + asprintf(&path, "%s/%s", dir, name); + } return path; } From 24567ce6f5f0314513f67d6083c7f823ea0b3b7f Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 18:10:45 +0300 Subject: [PATCH 129/268] Get rid of the LIFO history, an oldpath is enough --- noice.c | 71 +++++++-------------------------------------------------- 1 file changed, 8 insertions(+), 63 deletions(-) diff --git a/noice.c b/noice.c index 6b372fd2..c6df0d50 100644 --- a/noice.c +++ b/noice.c @@ -16,7 +16,6 @@ #include #include -#include "queue.h" #include "util.h" #ifdef DEBUG @@ -50,13 +49,6 @@ struct entry { mode_t mode; }; -struct history { - char *path; - SLIST_ENTRY(history) entry; -}; - -SLIST_HEAD(histhead, history) histhead = SLIST_HEAD_INITIALIZER(histhead); - /* * Layout: * .--------- @@ -528,48 +520,6 @@ dentfind(struct entry *dents, int n, char *cwd, char *path) return 0; } -void -pushhist(char *path) -{ - struct history *hist; - - hist = xmalloc(sizeof(*hist)); - hist->path = xstrdup(path); - SLIST_INSERT_HEAD(&histhead, hist, entry); -} - -char * -pophist(void) -{ - struct history *hist; - char *path; - - /* Recall history */ - hist = SLIST_FIRST(&histhead); - if (hist != NULL) { - path = hist->path; - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist); - } else { - path = NULL; - } - - return path; -} - -void -forgethist(void) -{ - struct history *hist; - - while (SLIST_EMPTY(&histhead) == 0) { - hist = SLIST_FIRST(&histhead); - SLIST_REMOVE_HEAD(&histhead, entry); - free(hist->path); - free(hist); - } -} - void browse(const char *ipath, const char *ifilter) { @@ -582,10 +532,10 @@ browse(const char *ipath, const char *ifilter) regex_t filter_re; char *cwd, *newpath; struct stat sb; - char *hpath; + char *oldpath; cur = 0; - hpath = NULL; + oldpath = NULL; begin: /* Path and filter should be malloc(3)-ed strings at all times */ n = 0; @@ -607,10 +557,10 @@ begin: qsort(dents, n, sizeof(*dents), entrycmp); /* Find cur from history */ - cur = dentfind(dents, n, path, hpath); - if (hpath != NULL) { - free(hpath); - hpath = NULL; + cur = dentfind(dents, n, path, oldpath); + if (oldpath != NULL) { + free(oldpath); + oldpath = NULL; } for (;;) { @@ -658,7 +608,6 @@ nochange: case SEL_QUIT: free(path); free(filter); - forgethist(); dentfree(dents, n); return; case SEL_BACK: @@ -672,13 +621,12 @@ nochange: goto nochange; } dir = xdirname(path); - free(path); + /* Save history */ + oldpath = path; path = dir; /* Reset filter */ free(filter); filter = xstrdup(ifilter); - /* Recall history */ - hpath = pophist(); goto out; case SEL_GOIN: /* Cannot descend in empty directories */ @@ -718,8 +666,6 @@ nochange: /* Reset filter */ free(filter); filter = xstrdup(ifilter); - /* Remember history */ - pushhist(path); cur = 0; goto out; case S_IFREG: @@ -781,7 +727,6 @@ nochange: path = newpath; free(filter); filter = xstrdup(ifilter); /* Reset filter */ - forgethist(); DPRINTF_S(path); cur = 0; goto out; From 70d292ed24489347cf1e45a8c2f92814b7ec0823 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 18:12:17 +0300 Subject: [PATCH 130/268] We don't use realpath(3) anymore --- noice.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/noice.c b/noice.c index c6df0d50..8eeb7d14 100644 --- a/noice.c +++ b/noice.c @@ -101,17 +101,6 @@ xstrdup(const char *s) return p; } -char * -xrealpath(const char *path) -{ - char *p; - - p = realpath(path, NULL); - if (p == NULL) - printerr(1, "realpath"); - return p; -} - char * xdirname(const char *path) { From 2d46c45a431ede154d0908c0a92a2c74b579ec04 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 18:14:18 +0300 Subject: [PATCH 131/268] The queue header is not needed for now --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 22130a54..bee31efa 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ all: $(BIN) $(BIN): $(OBJ) $(CC) $(CFLAGS) -o $@ $(OBJ) $(LDLIBS) -noice.o: queue.h util.h config.h +noice.o: util.h config.h strlcpy.o: util.h install: all From ce7411e93ab43cbad335dceb5f1d65f6ec81b174 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 18:26:06 +0300 Subject: [PATCH 132/268] Document the old path history thing --- noice.1 | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/noice.1 b/noice.1 index 05911869..491e94f1 100644 --- a/noice.1 +++ b/noice.1 @@ -75,12 +75,8 @@ is invoked as root the default filter will also match hidden files. .Sh HISTORY .Nm -keeps track of the current cursor position per directory -level. Backing up one directory level will restore the -cursor position at that level. -.Pp -History is discarded for the backed out directory. In other -words, history is recorded only when entering directories. +remembers the old path. Backing up one directory level will set the +cursor position at the directory you came out of. .Sh EXAMPLES The following example shows one possible configuration for file associations. This is the default configuration for From 9a14dcd8d2516e44feaf1a65af4ea8ac76fa33b5 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 23 Oct 2014 18:38:00 +0300 Subject: [PATCH 133/268] Revert "No need to manually strip trailing slashes" This reverts commit abd301333da81b72070fbb575dcd0824d3af038e. --- noice.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/noice.c b/noice.c index 8eeb7d14..81df9075 100644 --- a/noice.c +++ b/noice.c @@ -567,6 +567,13 @@ redraw: /* Clean screen */ erase(); + /* Strip trailing slashes */ + for (i = strlen(path) - 1; i > 0; i--) + if (path[i] == '/') + path[i] = '\0'; + else + break; + DPRINTF_D(cur); DPRINTF_S(path); From cae14a8208c0a0e33fb0ef7d61400dd774b4b711 Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 27 Oct 2014 13:56:33 +0000 Subject: [PATCH 134/268] Ensure manprefix exists --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index bee31efa..85c46314 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ strlcpy.o: util.h install: all mkdir -p $(DESTDIR)$(PREFIX)/bin cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin + mkdir -p $(DESTDIR)$(MANPREFIX)/man1 cp -f $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1 uninstall: From 12da2ff0280329a65667d38c9f05353c734b932b Mon Sep 17 00:00:00 2001 From: lostd Date: Sat, 1 Nov 2014 01:55:26 +0200 Subject: [PATCH 135/268] Emulate ls -F completely including sockets and FIFOs --- noice.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/noice.c b/noice.c index 81df9075..a9f08c4a 100644 --- a/noice.c +++ b/noice.c @@ -409,6 +409,12 @@ printent(struct entry *ent, int active) } else if (S_ISLNK(ent->mode)) { cm = '@'; maxlen--; + } else if (S_ISSOCK(ent->mode)) { + cm = '='; + maxlen--; + } else if (S_ISFIFO(ent->mode)) { + cm = '|'; + maxlen--; } else if (ent->mode & S_IXUSR) { cm = '*'; maxlen--; From 77565ecdb87d9771bcd929b222c2af2345a37e26 Mon Sep 17 00:00:00 2001 From: lostd Date: Sat, 1 Nov 2014 01:56:26 +0200 Subject: [PATCH 136/268] Style fix in a comment --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index a9f08c4a..89da6765 100644 --- a/noice.c +++ b/noice.c @@ -107,7 +107,7 @@ xdirname(const char *path) char *p, *tmp; /* Some implementations of dirname(3) may modify `path' and some - * return a pointer inside `path` and we cannot free(3) the + * return a pointer inside `path' and we cannot free(3) the * original string if we lose track of it. */ tmp = xstrdup(path); p = dirname(tmp); From ef3bfef45449a2d660a0ee8880a8888a5aef63fc Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 6 Nov 2014 10:54:20 +0200 Subject: [PATCH 137/268] Now nextsel() just maps keys to actions --- noice.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/noice.c b/noice.c index 89da6765..3bbdb468 100644 --- a/noice.c +++ b/noice.c @@ -256,21 +256,24 @@ printprompt(char *str) } /* - * Returns 0 normally - * On movement it updates *cur - * Returns SEL_{QUIT,BACK,GOIN,FLTR,SH,CD} otherwise + * Returns SEL_{QUIT,BACK,GOIN,FLTR,NEXT,PREV,PGDN,PGUP,SH,CD} + * Returns 0 otherwise */ enum { SEL_QUIT = 1, SEL_BACK, SEL_GOIN, SEL_FLTR, + SEL_NEXT, + SEL_PREV, + SEL_PGDN, + SEL_PGUP, SEL_SH, SEL_CD, }; int -nextsel(int *cur, int max) +nextsel(void) { int c; @@ -297,28 +300,20 @@ nextsel(int *cur, int max) case 'j': case KEY_DOWN: case CONTROL('N'): - if (*cur < max - 1) - (*cur)++; - break; + return SEL_NEXT; /* Previous */ case 'k': case KEY_UP: case CONTROL('P'): - if (*cur > 0) - (*cur)--; - break; + return SEL_PREV; /* Page down */ case KEY_NPAGE: case CONTROL('D'): - if (*cur < max -1) - (*cur) += MIN((LINES - 4) / 2, max - 1 - *cur); - break; + return SEL_PGDN; /* Page up */ case KEY_PPAGE: case CONTROL('U'): - if (*cur > 0) - (*cur) -= MIN((LINES - 4) / 2, *cur); - break; + return SEL_PGUP; case '!': return SEL_SH; case 'c': @@ -605,8 +600,7 @@ redraw: } nochange: - ret = nextsel(&cur, n); - switch (ret) { + switch (nextsel()) { case SEL_QUIT: free(path); free(filter); @@ -705,6 +699,22 @@ nochange: DPRINTF_S(filter); cur = 0; goto out; + case SEL_NEXT: + if (cur < n - 1) + cur++; + break; + case SEL_PREV: + if (cur > 0) + cur--; + break; + case SEL_PGDN: + if (cur < n - 1) + cur += MIN((LINES - 4) / 2, n - 1 - cur); + break; + case SEL_PGUP: + if (cur > 0) + cur -= MIN((LINES - 4) / 2, cur); + break; case SEL_SH: exitcurses(); spawn("/bin/sh", NULL, path); From 6b7c2506db2844d718be714e88cb631b0c721ad2 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 6 Nov 2014 13:46:37 +0200 Subject: [PATCH 138/268] Expose key bindings in the configuration header --- config.def.h | 35 +++++++++++++++++++++++ noice.c | 78 ++++++++++++++++------------------------------------ 2 files changed, 59 insertions(+), 54 deletions(-) diff --git a/config.def.h b/config.def.h index 3d733a2d..855af216 100644 --- a/config.def.h +++ b/config.def.h @@ -10,3 +10,38 @@ struct assoc assocs[] = { { "\\.sh$", "sh" }, { ".*", "less" }, }; + +struct key bindings[] = { + /* Quit */ + { 'q', SEL_QUIT }, + /* Back */ + { KEY_BACKSPACE, SEL_BACK }, + { KEY_LEFT, SEL_BACK }, + { 'h', SEL_BACK }, + /* Inside */ + { KEY_ENTER, SEL_GOIN }, + { '\r', SEL_GOIN }, + { KEY_RIGHT, SEL_GOIN }, + { 'l', SEL_GOIN }, + /* Filter */ + { '/', SEL_FLTR }, + { '&', SEL_FLTR }, + /* Next */ + { 'j', SEL_NEXT }, + { KEY_DOWN, SEL_NEXT }, + { CONTROL('N'), SEL_NEXT }, + /* Previous */ + { 'k', SEL_PREV }, + { KEY_UP, SEL_PREV }, + { CONTROL('P'), SEL_PREV }, + /* Page down */ + { KEY_NPAGE, SEL_PGDN }, + { CONTROL('D'), SEL_PGDN }, + /* Page up */ + { KEY_PPAGE, SEL_PGUP }, + { CONTROL('U'), SEL_PGUP }, + /* Shell */ + { '!', SEL_SH }, + /* Change dir */ + { 'c', SEL_CD }, +}; diff --git a/noice.c b/noice.c index 3bbdb468..fdda2162 100644 --- a/noice.c +++ b/noice.c @@ -42,6 +42,25 @@ struct assoc { char *bin; /* Program */ }; +/* Supported actions */ +enum action { + SEL_QUIT = 1, + SEL_BACK, + SEL_GOIN, + SEL_FLTR, + SEL_NEXT, + SEL_PREV, + SEL_PGDN, + SEL_PGUP, + SEL_SH, + SEL_CD, +}; + +struct key { + int sym; /* Key pressed */ + enum action act; /* Action */ +}; + #include "config.h" struct entry { @@ -259,65 +278,16 @@ printprompt(char *str) * Returns SEL_{QUIT,BACK,GOIN,FLTR,NEXT,PREV,PGDN,PGUP,SH,CD} * Returns 0 otherwise */ -enum { - SEL_QUIT = 1, - SEL_BACK, - SEL_GOIN, - SEL_FLTR, - SEL_NEXT, - SEL_PREV, - SEL_PGDN, - SEL_PGUP, - SEL_SH, - SEL_CD, -}; - int nextsel(void) { - int c; + int c, i; c = getch(); - switch (c) { - case 'q': - return SEL_QUIT; - /* Back */ - case KEY_BACKSPACE: - case KEY_LEFT: - case 'h': - return SEL_BACK; - /* Inside */ - case KEY_ENTER: - case '\r': - case KEY_RIGHT: - case 'l': - return SEL_GOIN; - /* Filter */ - case '/': - case '&': - return SEL_FLTR; - /* Next */ - case 'j': - case KEY_DOWN: - case CONTROL('N'): - return SEL_NEXT; - /* Previous */ - case 'k': - case KEY_UP: - case CONTROL('P'): - return SEL_PREV; - /* Page down */ - case KEY_NPAGE: - case CONTROL('D'): - return SEL_PGDN; - /* Page up */ - case KEY_PPAGE: - case CONTROL('U'): - return SEL_PGUP; - case '!': - return SEL_SH; - case 'c': - return SEL_CD; + + for (i = 0; i < LEN(bindings); i++) { + if (c == bindings[i].sym) + return bindings[i].act; } return 0; From ca07068dcb1d506bd999f61b5942fb09194a0f44 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 6 Nov 2014 14:41:16 +0000 Subject: [PATCH 139/268] Update error to reflect actual syscall --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index fdda2162..bd905f0c 100644 --- a/noice.c +++ b/noice.c @@ -419,7 +419,7 @@ dentfill(DIR *dirp, struct entry **dents, r = fstatat(dirfd(dirp), dp->d_name, &sb, AT_SYMLINK_NOFOLLOW); if (r == -1) - printerr(1, "stat"); + printerr(1, "fstatat"); (*dents)[n].mode = sb.st_mode; n++; } From cc88af72ca6a18925e28748cce854c514fbc7752 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 13 Nov 2014 18:49:57 +0200 Subject: [PATCH 140/268] Same functionality using lstat(2) instead of fstatat(2) --- noice.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/noice.c b/noice.c index bd905f0c..16622dd6 100644 --- a/noice.c +++ b/noice.c @@ -88,6 +88,7 @@ struct entry { void printmsg(char *msg); void printwarn(void); void printerr(int ret, char *prefix); +char *makepath(char *dir, char *name); void * xmalloc(size_t size) @@ -398,13 +399,19 @@ printent(struct entry *ent, int active) } int -dentfill(DIR *dirp, struct entry **dents, +dentfill(char *path, struct entry **dents, int (*filter)(regex_t *, char *), regex_t *re) { + DIR *dirp; struct dirent *dp; struct stat sb; + char *newpath; int n = 0; - int r; + int fd, r; + + dirp = opendir(path); + if (dirp == NULL) + return 0; while ((dp = readdir(dirp)) != NULL) { /* Skip self and parent */ @@ -416,14 +423,19 @@ dentfill(DIR *dirp, struct entry **dents, *dents = xrealloc(*dents, (n + 1) * sizeof(**dents)); (*dents)[n].name = xstrdup(dp->d_name); /* Get mode flags */ - r = fstatat(dirfd(dirp), dp->d_name, &sb, - AT_SYMLINK_NOFOLLOW); + newpath = makepath(path, dp->d_name); + r = lstat(newpath, &sb); if (r == -1) - printerr(1, "fstatat"); + printerr(1, "lstat"); (*dents)[n].mode = sb.st_mode; n++; } + /* Should never be null */ + r = closedir(dirp); + if (r == -1) + printerr(1, "closedir"); + return n; } @@ -483,7 +495,6 @@ dentfind(struct entry *dents, int n, char *cwd, char *path) void browse(const char *ipath, const char *ifilter) { - DIR *dirp; struct entry *dents; int i, n, cur; int r, ret, fd; @@ -501,8 +512,7 @@ begin: n = 0; dents = NULL; - dirp = opendir(path); - if (dirp == NULL) { + if (canopendir(path) == 0) { printwarn(); goto nochange; } @@ -512,7 +522,7 @@ begin: if (r != 0) goto nochange; - n = dentfill(dirp, &dents, visible, &filter_re); + n = dentfill(path, &dents, visible, &filter_re); qsort(dents, n, sizeof(*dents), entrycmp); @@ -718,11 +728,6 @@ nochange: out: dentfree(dents, n); - /* Should never be null */ - r = closedir(dirp); - if (r == -1) - printerr(1, "closedir"); - goto begin; } From f4b5df5b3af4d367f2116ecb27100ac4befcc79b Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 14 Nov 2014 09:59:19 +0000 Subject: [PATCH 141/268] Replace asprintf() with strlcpy() and strlcat() --- Makefile | 3 ++- noice.c | 14 +++++++++----- strlcat.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 4 ++++ 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 strlcat.c diff --git a/Makefile b/Makefile index 85c46314..d8736dfb 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ MANPREFIX = $(PREFIX)/man #CFLAGS += -g LDLIBS = -lncursesw -OBJ = noice.o strlcpy.o +OBJ = noice.o strlcat.o strlcpy.o BIN = noice all: $(BIN) @@ -14,6 +14,7 @@ $(BIN): $(OBJ) $(CC) $(CFLAGS) -o $@ $(OBJ) $(LDLIBS) noice.o: util.h config.h +strlcat.o: util.h strlcpy.o: util.h install: all diff --git a/noice.c b/noice.c index 16622dd6..f52e910f 100644 --- a/noice.c +++ b/noice.c @@ -458,13 +458,17 @@ makepath(char *dir, char *name) if (name[0] == '/') { path = xstrdup(name); } else { + path = xmalloc(PATH_MAX); /* Handle root case */ - if (strcmp(dir, "/") == 0) - asprintf(&path, "/%s", name); - else - asprintf(&path, "%s/%s", dir, name); + if (strcmp(dir, "/") == 0) { + strlcpy(path, "/", PATH_MAX); + strlcat(path, name, PATH_MAX); + } else { + strlcpy(path, dir, PATH_MAX); + strlcat(path, "/", PATH_MAX); + strlcat(path, name, PATH_MAX); + } } - return path; } diff --git a/strlcat.c b/strlcat.c new file mode 100644 index 00000000..979c41bc --- /dev/null +++ b/strlcat.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "util.h" + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/util.h b/util.h index 4da38854..89110e51 100644 --- a/util.h +++ b/util.h @@ -1,2 +1,6 @@ +#include + +#undef strlcat +size_t strlcat(char *, const char *, size_t); #undef strlcpy size_t strlcpy(char *, const char *, size_t); From 89d0dc35ee86838b781b37d93172426cf5251609 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 14 Nov 2014 12:20:37 +0000 Subject: [PATCH 142/268] Add dist target --- Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d8736dfb..ed40ea97 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +VERSION = 0.0 + PREFIX = /usr/local MANPREFIX = $(PREFIX)/man @@ -27,8 +29,15 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) rm -f $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1 +dist: + mkdir -p noice-$(VERSION) + cp LICENSE Makefile README config.def.h noice.1 noice.c queue.h strlcat.c strlcpy.c util.h noice-$(VERSION) + tar -cf noice-$(VERSION).tar noice-$(VERSION) + gzip noice-$(VERSION).tar + rm -rf noice-$(VERSION) + clean: - rm -f $(BIN) $(OBJ) + rm -f $(BIN) $(OBJ) noice-$(VERSION).tar.gz .SUFFIXES: .def.h From 3639f1bbb4547f14ec792b311f117aef27dcc7f9 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 14 Nov 2014 12:50:41 +0000 Subject: [PATCH 143/268] Just use xstrdup() in makepath() --- noice.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/noice.c b/noice.c index f52e910f..d0b00948 100644 --- a/noice.c +++ b/noice.c @@ -452,24 +452,23 @@ dentfree(struct entry *dents, int n) char * makepath(char *dir, char *name) { - char *path; + char path[PATH_MAX]; /* Handle absolute path */ if (name[0] == '/') { - path = xstrdup(name); + strlcpy(path, name, sizeof(path)); } else { - path = xmalloc(PATH_MAX); /* Handle root case */ if (strcmp(dir, "/") == 0) { - strlcpy(path, "/", PATH_MAX); - strlcat(path, name, PATH_MAX); + strlcpy(path, "/", sizeof(path)); + strlcat(path, name, sizeof(path)); } else { - strlcpy(path, dir, PATH_MAX); - strlcat(path, "/", PATH_MAX); - strlcat(path, name, PATH_MAX); + strlcpy(path, dir, sizeof(path)); + strlcat(path, "/", sizeof(path)); + strlcat(path, name, sizeof(path)); } } - return path; + return xstrdup(path); } /* Return the position of the matching entry or 0 otherwise */ From 3e8555fdc62905e1b696d1d96f981492d7ccbd13 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 14 Nov 2014 13:05:17 +0000 Subject: [PATCH 144/268] Add a simple dprintf() implementation for systems that do not have it --- noice.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/noice.c b/noice.c index d0b00948..e656949f 100644 --- a/noice.c +++ b/noice.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -90,6 +91,22 @@ void printwarn(void); void printerr(int ret, char *prefix); char *makepath(char *dir, char *name); +#undef dprintf +int +dprintf(int fd, const char *fmt, ...) +{ + char buf[BUFSIZ]; + int r; + va_list ap; + + va_start(ap, fmt); + r = vsnprintf(buf, sizeof(buf), fmt, ap); + if (r > 0) + write(fd, buf, r); + va_end(ap); + return r; +} + void * xmalloc(size_t size) { From eebbf61c10fd8acb173e30186d1e49242af0d39c Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 15:47:18 +0200 Subject: [PATCH 145/268] Use a var for dist files and remove queue.h --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ed40ea97..85114c72 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,8 @@ MANPREFIX = $(PREFIX)/man #CFLAGS += -g LDLIBS = -lncursesw +DISTFILES = noice.c strlcat.c strlcpy.c util.h config.def.h\ + noice.1 Makefile README LICENSE OBJ = noice.o strlcat.o strlcpy.o BIN = noice @@ -31,7 +33,7 @@ uninstall: dist: mkdir -p noice-$(VERSION) - cp LICENSE Makefile README config.def.h noice.1 noice.c queue.h strlcat.c strlcpy.c util.h noice-$(VERSION) + cp $(DISTFILES) noice-$(VERSION) tar -cf noice-$(VERSION).tar noice-$(VERSION) gzip noice-$(VERSION).tar rm -rf noice-$(VERSION) From b456bc23f261bd0918356c2047a2ef4e3878bd1c Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 16:22:07 +0200 Subject: [PATCH 146/268] Document the relative path feature --- noice.1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index 491e94f1..ebd301bf 100644 --- a/noice.1 +++ b/noice.1 @@ -16,7 +16,12 @@ with a TV remote control. .Nm defaults to the current directory if .Ar dir -is not specified. +is not specified. As an extra feature, if +.Ar dir +is a relative path, +.Nm +will not go back beyond the first component of the path using standard +navigation key presses. .Pp .Nm supports both vi-like and emacs-like key bindings in the default From c719a856f374a466dc581bc815a20c6556c0b64c Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 16:41:46 +0200 Subject: [PATCH 147/268] Style changes and rephrasing --- noice.1 | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/noice.1 b/noice.1 index ebd301bf..2c8ba51c 100644 --- a/noice.1 +++ b/noice.1 @@ -28,28 +28,27 @@ supports both vi-like and emacs-like key bindings in the default configuration. The default key bindings are described below; their functionality is described in more detail later. .Pp -.Bl -tag -width "l | Right | Return | C-mXXXX" -offset indent -compact -.It Ic k | Up | C-p +.Bl -tag -width "l, [Right], [Return] or C-mXXXX" -offset indent -compact +.It Ic k, [Up] or C-p Move to previous entry. -.It Ic j | Down | C-n +.It Ic j, [Down] or C-n Move to next entry. -.It Ic Pgup | C-u -Scroll backwards one page. -.It Ic Pgdown | C-d -Scroll forwards one page. -.It Ic l | Right | Return | C-m +.It Ic [Pgup] or C-u +Scroll up half a page. +.It Ic [Pgdown] or C-d +Scroll down half a page. +.It Ic l, [Right], [Return] or C-m Open file or enter directory. -.It Ic h | Left | Backspace +.It Ic h, [Left] or [Backspace] Back up one directory level. -.It Ic / | & -Filter view (see below for more information). -.It Ic ! -Spawn shell in current directory. +.It Ic / or & +Change filter (see below for more information). .It Ic c Change into the given directory. +.It Ic ! +Spawn shell in current directory. .It Ic q -Quit -.Nm . +Quit. .El .Sh CONFIGURATION .Nm @@ -60,8 +59,11 @@ and recompiling the code. The file associations are specified by regexes matching on the currently selected filename. If a match is found the associated program is executed with the filename passed in as the argument. If no match -is found the program less(1) is invoked. This is useful for editing text files -as one can use the 'v' command in less(1) to edit the file in $EDITOR. +is found the program +.Xr less 1 +is invoked. This is useful for editing text files +as one can use the 'v' command in +.Xr less 1 to edit the file in $EDITOR. .Pp See the examples section below for more information. .Sh FILTERS @@ -84,8 +86,7 @@ remembers the old path. Backing up one directory level will set the cursor position at the directory you came out of. .Sh EXAMPLES The following example shows one possible configuration for -file associations. This is the default configuration for -.Nm . +file associations which is also the default: .Bd -literal struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, From e7fe3699032bfb5aa29de9b78b19e37bd5c878b9 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 16:45:17 +0200 Subject: [PATCH 148/268] Remove history section because it resembles historical notes --- noice.1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/noice.1 b/noice.1 index 2c8ba51c..3122c67b 100644 --- a/noice.1 +++ b/noice.1 @@ -50,6 +50,9 @@ Spawn shell in current directory. .It Ic q Quit. .El +.Pp +Backing up one directory level will set the cursor position at the +directory you came out of. .Sh CONFIGURATION .Nm is configured by modifying @@ -80,10 +83,6 @@ If .Nm is invoked as root the default filter will also match hidden files. -.Sh HISTORY -.Nm -remembers the old path. Backing up one directory level will set the -cursor position at the directory you came out of. .Sh EXAMPLES The following example shows one possible configuration for file associations which is also the default: From 3419e18c61e11b77ade3d9094fbf863786a89bde Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 16:50:29 +0200 Subject: [PATCH 149/268] Renew date --- noice.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index 3122c67b..34ac05dd 100644 --- a/noice.1 +++ b/noice.1 @@ -1,4 +1,4 @@ -.Dd Oct 22, 2014 +.Dd November 14, 2014 .Dt NOICE 1 .Os .Sh NAME From 7b34fc4c1e1e8c06a4eb8cced08824e6f20aff9f Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 17:24:54 +0200 Subject: [PATCH 150/268] Building and compatibility notes --- README | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README b/README index 44e79eff..4f3b7896 100644 --- a/README +++ b/README @@ -27,6 +27,26 @@ preceded with a " > " by default. For more information refer to the manpage. +Building +======== + +To build noice you need a curses implementation available. In most +cases you just do: + + make + +It is known to work on OpenBSD, Arch Linux, Slackware, NetBSD, IRIX. Some notes +for building on certain systems follow. + + * NetBSD: + + make LDLIBS="-lcurses" + + * IRIX: + + make CC="gcc" LDLIBS="-lgen -lcurses" + + Contact ======= From 7c31c572a557eb1f2e56923edcbcbc3d2ebcf7b0 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 18:12:14 +0200 Subject: [PATCH 151/268] Test unicode on filename and content --- mktest.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/mktest.sh b/mktest.sh index 8ab7be50..6a6b6505 100644 --- a/mktest.sh +++ b/mktest.sh @@ -10,6 +10,7 @@ test -e test && { mkdir test && cd test echo 'It works!' > normal.txt +echo 'Με δουλέβει;' > 'κοινό.txt' ln -s normal.txt ln-normal.txt ln -s normal.txt ln-normal mkdir normal-dir From bd6b3e932eab81101100dbdfa8517b2a0a055b8b Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 18:13:02 +0200 Subject: [PATCH 152/268] Build with -lcurses by default to be more generic --- Makefile | 2 +- README | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 85114c72..7acef009 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ MANPREFIX = $(PREFIX)/man #CPPFLAGS += -DDEBUG #CFLAGS += -g -LDLIBS = -lncursesw +LDLIBS = -lcurses DISTFILES = noice.c strlcat.c strlcpy.c util.h config.def.h\ noice.1 Makefile README LICENSE diff --git a/README b/README index 4f3b7896..236e5b4b 100644 --- a/README +++ b/README @@ -38,13 +38,9 @@ cases you just do: It is known to work on OpenBSD, Arch Linux, Slackware, NetBSD, IRIX. Some notes for building on certain systems follow. - * NetBSD: - - make LDLIBS="-lcurses" - * IRIX: - make CC="gcc" LDLIBS="-lgen -lcurses" + make CC="gcc" LDLIBS="-lgen" Contact From f57c0a4dfec34243f4fc79b4b78a26a622d6a3cc Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 14 Nov 2014 16:26:49 +0000 Subject: [PATCH 153/268] Works on Haiku too so update README --- README | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README b/README index 236e5b4b..01b31b57 100644 --- a/README +++ b/README @@ -35,13 +35,16 @@ cases you just do: make -It is known to work on OpenBSD, Arch Linux, Slackware, NetBSD, IRIX. Some notes -for building on certain systems follow. +It is known to work on OpenBSD, NetBSD, Arch Linux, Slackware, IRIX 6.5 +and Haiku. Some notes for building on certain systems follow. - * IRIX: + * IRIX 6.5: make CC="gcc" LDLIBS="-lgen" + * Haiku: + + make LDLIBS="-lncurses" Contact ======= From d5bfdfd916ab429959287ca6c7de5dbc89e93414 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 18:28:48 +0200 Subject: [PATCH 154/268] Also on FreeBSD --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 01b31b57..5116cd3b 100644 --- a/README +++ b/README @@ -35,8 +35,8 @@ cases you just do: make -It is known to work on OpenBSD, NetBSD, Arch Linux, Slackware, IRIX 6.5 -and Haiku. Some notes for building on certain systems follow. +It is known to work on OpenBSD, NetBSD, FreeBSD, Arch Linux, Slackware, +IRIX 6.5 and Haiku. Some notes for building on certain systems follow. * IRIX 6.5: From 4d72d592d891eea97d1b081991c4922a5361165b Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 18:32:24 +0200 Subject: [PATCH 155/268] No need for +=, also favors portability --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7acef009..1bd8268e 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ VERSION = 0.0 PREFIX = /usr/local MANPREFIX = $(PREFIX)/man -#CPPFLAGS += -DDEBUG -#CFLAGS += -g +#CPPFLAGS = -DDEBUG +#CFLAGS = -g LDLIBS = -lcurses DISTFILES = noice.c strlcat.c strlcpy.c util.h config.def.h\ From 532ac6a251f65f32d6d6c85347cc2d991b200f09 Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 20:13:00 +0200 Subject: [PATCH 156/268] More notes on building --- README | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README b/README index 5116cd3b..728104f7 100644 --- a/README +++ b/README @@ -36,9 +36,11 @@ cases you just do: make It is known to work on OpenBSD, NetBSD, FreeBSD, Arch Linux, Slackware, -IRIX 6.5 and Haiku. Some notes for building on certain systems follow. +IRIX 6.5, Haiku, Solaris 9. Some notes for building on certain systems +follow. * IRIX 6.5: + Tested with gcc from http://freeware.sgi.com/. make CC="gcc" LDLIBS="-lgen" @@ -46,6 +48,13 @@ IRIX 6.5 and Haiku. Some notes for building on certain systems follow. make LDLIBS="-lncurses" + * Solaris 9: + Tested with gcc from http://www.opencsw.org/. + + export PATH=/usr/ccs/bin:/opt/csw/bin + make CC="gcc" + + Contact ======= From b78755bb01c8615339085bcfe0ab30b49e13109c Mon Sep 17 00:00:00 2001 From: lostd Date: Fri, 14 Nov 2014 20:17:33 +0200 Subject: [PATCH 157/268] First release --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1bd8268e..0231438d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.0 +VERSION = 0.1 PREFIX = /usr/local MANPREFIX = $(PREFIX)/man From 3f1a93a5981d81936e6d18288213b71fb46cfc15 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 25 Nov 2014 17:20:06 +0200 Subject: [PATCH 158/268] Simplify default regexes --- config.def.h | 2 +- noice.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 855af216..150968e5 100644 --- a/config.def.h +++ b/config.def.h @@ -8,7 +8,7 @@ struct assoc assocs[] = { { "\\.(html|svg)$", "firefox" }, { "\\.pdf$", "mupdf" }, { "\\.sh$", "sh" }, - { ".*", "less" }, + { ".", "less" }, }; struct key bindings[] = { diff --git a/noice.c b/noice.c index e656949f..0f55a8bf 100644 --- a/noice.c +++ b/noice.c @@ -758,9 +758,9 @@ main(int argc, char *argv[]) char *ifilter; if (getuid() == 0) - ifilter = ".*"; + ifilter = "."; else - ifilter = "^[^.].*"; /* Hide dotfiles */ + ifilter = "^[^.]"; /* Hide dotfiles */ if (argv[1] != NULL) { ipath = argv[1]; From 3d256b8bf2c0a9e61d937e86c7421b4bbcb67c18 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 26 Nov 2014 15:38:51 +0000 Subject: [PATCH 159/268] Works on DragonFly BSD as well --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 728104f7..ea0bb350 100644 --- a/README +++ b/README @@ -35,8 +35,8 @@ cases you just do: make -It is known to work on OpenBSD, NetBSD, FreeBSD, Arch Linux, Slackware, -IRIX 6.5, Haiku, Solaris 9. Some notes for building on certain systems +It is known to work on OpenBSD, NetBSD, FreeBSD, DragonFly BSD, Arch Linux, +Slackware, IRIX 6.5, Haiku, Solaris 9. Some notes for building on certain systems follow. * IRIX 6.5: From 55d45dd39d090dfcc1d05eac082b713774af39a7 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 26 Nov 2014 17:39:19 +0200 Subject: [PATCH 160/268] Don't care about cur, it defaults to 0 --- noice.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/noice.c b/noice.c index 0f55a8bf..a95ab6fd 100644 --- a/noice.c +++ b/noice.c @@ -525,7 +525,6 @@ browse(const char *ipath, const char *ifilter) struct stat sb; char *oldpath; - cur = 0; oldpath = NULL; begin: /* Path and filter should be malloc(3)-ed strings at all times */ @@ -662,7 +661,6 @@ nochange: /* Reset filter */ free(filter); filter = xstrdup(ifilter); - cur = 0; goto out; case S_IFREG: bin = openwith(name); @@ -697,7 +695,6 @@ nochange: filter = tmp; filter_re = re; DPRINTF_S(filter); - cur = 0; goto out; case SEL_NEXT: if (cur < n - 1) @@ -740,7 +737,6 @@ nochange: free(filter); filter = xstrdup(ifilter); /* Reset filter */ DPRINTF_S(path); - cur = 0; goto out; } } From 15a7a7826450237bb9b5588b5ec9c920e232e1c4 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 26 Nov 2014 17:42:57 +0200 Subject: [PATCH 161/268] Remember current entry accross filter changes --- noice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/noice.c b/noice.c index a95ab6fd..3ee658d7 100644 --- a/noice.c +++ b/noice.c @@ -695,6 +695,8 @@ nochange: filter = tmp; filter_re = re; DPRINTF_S(filter); + /* Save current */ + oldpath = makepath(path, dents[cur].name); goto out; case SEL_NEXT: if (cur < n - 1) From 414c9e27fcbb182c36d112d5236db8de3a7f2e24 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 26 Nov 2014 18:09:03 +0200 Subject: [PATCH 162/268] Fix whitespace --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 3ee658d7..831f4756 100644 --- a/noice.c +++ b/noice.c @@ -695,7 +695,7 @@ nochange: filter = tmp; filter_re = re; DPRINTF_S(filter); - /* Save current */ + /* Save current */ oldpath = makepath(path, dents[cur].name); goto out; case SEL_NEXT: From 82747b38f94dd60eb1838dbcaf7f74d6467c3706 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 2 Dec 2014 16:10:37 +0000 Subject: [PATCH 163/268] Just say Linux --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index ea0bb350..83033755 100644 --- a/README +++ b/README @@ -35,8 +35,8 @@ cases you just do: make -It is known to work on OpenBSD, NetBSD, FreeBSD, DragonFly BSD, Arch Linux, -Slackware, IRIX 6.5, Haiku, Solaris 9. Some notes for building on certain systems +It is known to work on OpenBSD, NetBSD, FreeBSD, DragonFly BSD, Linux, +IRIX 6.5, Haiku, Solaris 9. Some notes for building on certain systems follow. * IRIX 6.5: From a7b29afcef1f21a2001c711a44c935a556105a07 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 17 Dec 2014 11:25:55 +0000 Subject: [PATCH 164/268] regexec: check on success return code on OpenBSD: "Other non-zero error codes may be returned in exceptional situations; see DIAGNOSTICS" regcomp(3). --- noice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 831f4756..135f453b 100644 --- a/noice.c +++ b/noice.c @@ -189,7 +189,7 @@ openwith(char *file) if (regcomp(®ex, assocs[i].regex, REG_NOSUB | REG_EXTENDED) != 0) continue; - if (regexec(®ex, file, 0, NULL, 0) != REG_NOMATCH) { + if (regexec(®ex, file, 0, NULL, 0) == 0) { bin = assocs[i].bin; break; } @@ -219,7 +219,7 @@ setfilter(regex_t *regex, char *filter) int visible(regex_t *regex, char *file) { - if (regexec(regex, file, 0, NULL, 0) != REG_NOMATCH) + if (regexec(regex, file, 0, NULL, 0) == 0) return 1; return 0; } From 446fc35593507469a059e7dec85b724c13c5ba4c Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 17 Dec 2014 11:48:34 +0000 Subject: [PATCH 165/268] remove unused variables --- noice.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 135f453b..458ac422 100644 --- a/noice.c +++ b/noice.c @@ -423,8 +423,7 @@ dentfill(char *path, struct entry **dents, struct dirent *dp; struct stat sb; char *newpath; - int n = 0; - int fd, r; + int r, n = 0; dirp = opendir(path); if (dirp == NULL) @@ -517,7 +516,7 @@ browse(const char *ipath, const char *ifilter) { struct entry *dents; int i, n, cur; - int r, ret, fd; + int r, fd; char *path = xstrdup(ipath); char *filter = xstrdup(ifilter); regex_t filter_re; From d444bf1cb6b1ef1c0436dd4b9e8ce0c6ea7b4ee9 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 17 Dec 2014 11:51:53 +0000 Subject: [PATCH 166/268] style: dont declare vars inline --- noice.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/noice.c b/noice.c index 458ac422..b50cddfe 100644 --- a/noice.c +++ b/noice.c @@ -515,16 +515,15 @@ void browse(const char *ipath, const char *ifilter) { struct entry *dents; - int i, n, cur; - int r, fd; + int i, n, cur, r, fd; + int nlines, odd; char *path = xstrdup(ipath); char *filter = xstrdup(ifilter); - regex_t filter_re; - char *cwd, *newpath; + regex_t filter_re, re; + char *cwd, *newpath, *oldpath = NULL; struct stat sb; - char *oldpath; + char *name, *bin, *dir, *tmp; - oldpath = NULL; begin: /* Path and filter should be malloc(3)-ed strings at all times */ n = 0; @@ -552,14 +551,6 @@ begin: } for (;;) { - int nlines; - int odd; - char *name; - char *bin; - char *dir; - char *tmp; - regex_t re; - redraw: nlines = MIN(LINES - 4, n); From 81a0c57783c3d1dae93f0b13d7236146f094a5c2 Mon Sep 17 00:00:00 2001 From: Hiltjo Posthuma Date: Wed, 17 Dec 2014 11:54:57 +0000 Subject: [PATCH 167/268] no need to check for NULL before free --- noice.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/noice.c b/noice.c index b50cddfe..f62619a2 100644 --- a/noice.c +++ b/noice.c @@ -545,10 +545,8 @@ begin: /* Find cur from history */ cur = dentfind(dents, n, path, oldpath); - if (oldpath != NULL) { - free(oldpath); - oldpath = NULL; - } + free(oldpath); + oldpath = NULL; for (;;) { redraw: From 905b74161e0a37b8ffb57f8dbd252e7dfbddaeb3 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 18 Dec 2014 11:13:45 +0200 Subject: [PATCH 168/268] Remove unnecessary label --- noice.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noice.c b/noice.c index f62619a2..81191088 100644 --- a/noice.c +++ b/noice.c @@ -549,7 +549,6 @@ begin: oldpath = NULL; for (;;) { -redraw: nlines = MIN(LINES - 4, n); /* Clean screen */ @@ -661,7 +660,7 @@ nochange: spawn(bin, newpath, NULL); initcurses(); free(newpath); - goto redraw; + continue; default: printmsg("Unsupported file"); goto nochange; From d907c3f9941a922579d3ad92aedeb1e4e2ab5c2e Mon Sep 17 00:00:00 2001 From: sin Date: Sat, 20 Dec 2014 19:14:10 +0000 Subject: [PATCH 169/268] Remove unnecessary curly brackets --- noice.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 81191088..ecad4475 100644 --- a/noice.c +++ b/noice.c @@ -303,10 +303,9 @@ nextsel(void) c = getch(); - for (i = 0; i < LEN(bindings); i++) { + for (i = 0; i < LEN(bindings); i++) if (c == bindings[i].sym) return bindings[i].act; - } return 0; } From 3fa6a6272cd304671b195111b283417d2d24f851 Mon Sep 17 00:00:00 2001 From: sin Date: Sat, 20 Dec 2014 19:21:03 +0000 Subject: [PATCH 170/268] Simplify visible() --- noice.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/noice.c b/noice.c index ecad4475..b3aff682 100644 --- a/noice.c +++ b/noice.c @@ -219,9 +219,7 @@ setfilter(regex_t *regex, char *filter) int visible(regex_t *regex, char *file) { - if (regexec(regex, file, 0, NULL, 0) == 0) - return 1; - return 0; + return regexec(regex, file, 0, NULL, 0) == 0; } int From 3b5fe15166c2c2bd84654e97b3898bb9548472c1 Mon Sep 17 00:00:00 2001 From: sin Date: Sat, 20 Dec 2014 19:35:27 +0000 Subject: [PATCH 171/268] Simplify condition --- noice.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index b3aff682..2aa32049 100644 --- a/noice.c +++ b/noice.c @@ -365,12 +365,10 @@ canopendir(char *path) DIR *dirp; dirp = opendir(path); - if (dirp == NULL) { + if (dirp == NULL) return 0; - } else { - closedir(dirp); - return 1; - } + closedir(dirp); + return 1; } void From 57642a941010cc523808631bb1ef3c31f7de04ae Mon Sep 17 00:00:00 2001 From: lostd Date: Mon, 12 Jan 2015 00:28:54 +0200 Subject: [PATCH 172/268] Match the whole path to enable associations based on a prefix dir --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 2aa32049..aa0e8723 100644 --- a/noice.c +++ b/noice.c @@ -645,7 +645,7 @@ nochange: filter = xstrdup(ifilter); goto out; case S_IFREG: - bin = openwith(name); + bin = openwith(newpath); if (bin == NULL) { printmsg("No association"); free(newpath); From ad76a7be57dfa5eecf192594e49711335a20ac84 Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 12 Jan 2015 17:10:45 +0000 Subject: [PATCH 173/268] Update assocs section in manpage --- noice.1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/noice.1 b/noice.1 index 34ac05dd..70eb697d 100644 --- a/noice.1 +++ b/noice.1 @@ -88,12 +88,12 @@ The following example shows one possible configuration for file associations which is also the default: .Bd -literal struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, - { "\\.(png|jpg|gif)$", "feh" }, - { "\\.(html|svg)$", "firefox" }, - { "\\.pdf$", "mupdf" }, - { "\\.sh$", "sh" }, - { ".*", "less" }, + { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, + { "\\.(png|jpg|gif)$", "feh" }, + { "\\.(html|svg)$", "firefox" }, + { "\\.pdf$", "mupdf" }, + { "\\.sh$", "sh" }, + { ".", "less" }, }; .Ed .Sh KNOWN ISSUES From 892c7c850a27331f6debb0d5968282d0e3278592 Mon Sep 17 00:00:00 2001 From: lostd Date: Mon, 26 Jan 2015 22:48:47 +0200 Subject: [PATCH 174/268] Spawn a program that segfaults for testing --- mktest.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mktest.sh b/mktest.sh index 6a6b6505..1af7a6ee 100644 --- a/mktest.sh +++ b/mktest.sh @@ -20,3 +20,6 @@ mkfifo mk-fifo touch no-access && chmod 000 no-access ln -s ../normal.txt normal-dir/ln-normal.txt ln -s ../normal.txt normal-dir/ln-normal +echo 'int main(void) { *((char *)0) = 0; }' > ill.c +make ill > /dev/null +echo 'test/ill' > ill.sh From 9679e132d48dc6e39e3e4e0798aed75696784ba3 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 09:47:56 +0200 Subject: [PATCH 175/268] Fix segfault when a non-matching filter is applied twice --- noice.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index aa0e8723..bd35eaa6 100644 --- a/noice.c +++ b/noice.c @@ -678,7 +678,8 @@ nochange: filter_re = re; DPRINTF_S(filter); /* Save current */ - oldpath = makepath(path, dents[cur].name); + if (n > 0) + oldpath = makepath(path, dents[cur].name); goto out; case SEL_NEXT: if (cur < n - 1) From 48e3305be834bf0877a16ec5e855e66fb1787bd7 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 09:55:07 +0200 Subject: [PATCH 176/268] Empty filter resets filter to the default --- noice.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/noice.c b/noice.c index bd35eaa6..8fe7f98d 100644 --- a/noice.c +++ b/noice.c @@ -664,10 +664,8 @@ nochange: /* Read filter */ printprompt("filter: "); tmp = readln(); - if (tmp == NULL) { - clearprompt(); - goto nochange; - } + if (tmp == NULL) + tmp = xstrdup(ifilter); r = setfilter(&re, tmp); if (r != 0) { free(tmp); From 1295b7f0e64aabbddce008adbb9fc7fb025f54a4 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 09:58:32 +0200 Subject: [PATCH 177/268] Comment and cleanup --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 8fe7f98d..784ccb95 100644 --- a/noice.c +++ b/noice.c @@ -666,6 +666,7 @@ nochange: tmp = readln(); if (tmp == NULL) tmp = xstrdup(ifilter); + /* Check and report regex errors */ r = setfilter(&re, tmp); if (r != 0) { free(tmp); @@ -673,7 +674,6 @@ nochange: } free(filter); filter = tmp; - filter_re = re; DPRINTF_S(filter); /* Save current */ if (n > 0) From 84e124bb465889c957c4501679cdd38670b26d64 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 10:47:57 +0200 Subject: [PATCH 178/268] Basic filter-as-you-type mode --- config.def.h | 2 ++ noice.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/config.def.h b/config.def.h index 150968e5..4c7ade3e 100644 --- a/config.def.h +++ b/config.def.h @@ -26,6 +26,8 @@ struct key bindings[] = { /* Filter */ { '/', SEL_FLTR }, { '&', SEL_FLTR }, + /* Type */ + { '?', SEL_TYPE }, /* Next */ { 'j', SEL_NEXT }, { KEY_DOWN, SEL_NEXT }, diff --git a/noice.c b/noice.c index 784ccb95..e841efa9 100644 --- a/noice.c +++ b/noice.c @@ -49,6 +49,7 @@ enum action { SEL_BACK, SEL_GOIN, SEL_FLTR, + SEL_TYPE, SEL_NEXT, SEL_PREV, SEL_PGDN, @@ -359,6 +360,55 @@ readln(void) return ln; } +/* + * Read one key and modify the provided string accordingly. + * Returns 0 when more input is expected and 1 on completion. + */ +int +readmore(char **str) +{ + int c; + int i; + char *ln = *str; + int ret = 0; + + if (ln != NULL) + i = strlen(ln); + else + i = 0; + + DPRINTF_D(i); + + curs_set(TRUE); + + c = getch(); + if (c == KEY_ENTER || c == '\r') { + ret = 1; + goto out; + } + if (c == KEY_BACKSPACE) { + i--; + if (i > 0) { + ln = xrealloc(ln, (i + 1) * sizeof(*ln)); + ln[i] = '\0'; + } else { + free(ln); + ln = NULL; + } + goto out; + } + ln = xrealloc(ln, (i + 2) * sizeof(*ln)); + ln[i] = c; + i++; + ln[i] = '\0'; +out: + curs_set(FALSE); + + *str = ln; + + return ret; +} + int canopendir(char *path) { @@ -518,6 +568,7 @@ browse(const char *ipath, const char *ifilter) char *cwd, *newpath, *oldpath = NULL; struct stat sb; char *name, *bin, *dir, *tmp; + int nowtyping = 0; begin: /* Path and filter should be malloc(3)-ed strings at all times */ @@ -580,6 +631,10 @@ begin: printent(&dents[i], i == cur); } + /* Handle filter-as-you-type mode */ + if (nowtyping) + goto moretyping; + nochange: switch (nextsel()) { case SEL_QUIT: @@ -679,6 +734,35 @@ nochange: if (n > 0) oldpath = makepath(path, dents[cur].name); goto out; + case SEL_TYPE: + nowtyping = 1; + tmp = NULL; +moretyping: + printprompt("type: "); + if (tmp != NULL) + printw("%s", tmp); + r = readmore(&tmp); + DPRINTF_D(r); + DPRINTF_S(tmp); + if (r == 1) + nowtyping = 0; + /* Check regex errors */ + if (tmp != NULL) + r = setfilter(&re, tmp); + if (r != 0 && nowtyping) + goto moretyping; + /* Copy or reset filter */ + free(filter); + if (tmp != NULL) + filter = xstrdup(tmp); + else + filter = xstrdup(ifilter); + /* Save current */ + if (n > 0) + oldpath = makepath(path, dents[cur].name); + if (!nowtyping) + free(tmp); + goto out; case SEL_NEXT: if (cur < n - 1) cur++; From cb6b2e53451c2c740d3f3a860bc448a3bbd38d05 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 12:24:09 +0200 Subject: [PATCH 179/268] Document changes regarding filters --- noice.1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/noice.1 b/noice.1 index 70eb697d..e4f187fe 100644 --- a/noice.1 +++ b/noice.1 @@ -1,4 +1,4 @@ -.Dd November 14, 2014 +.Dd January 27, 2015 .Dt NOICE 1 .Os .Sh NAME @@ -43,6 +43,8 @@ Open file or enter directory. Back up one directory level. .It Ic / or & Change filter (see below for more information). +.It Ic ? +Enter filter-as-you-type mode. .It Ic c Change into the given directory. .It Ic ! @@ -77,7 +79,7 @@ searching through the directory tree for a particular entry. Filters do not stack on top of each other. They are applied anew every time. .Pp -To reset the filter you can use the match-any regex (i.e. '.'). +To reset the filter you can input an empty filter expression. .Pp If .Nm From c150af8e9bfe624d87a8860a3246d62b0dbe18c1 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 27 Jan 2015 10:42:13 +0000 Subject: [PATCH 180/268] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d31ea441..036c735e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ Copyright (c) 2014 Lazaros Koromilas -Copyright (c) 2014 sin +Copyright (c) 2014 Dimitris Papastamos All rights reserved. Redistribution and use in source and binary forms, with or without From 6313043448a991d60fa8d1f14617678934c76e48 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 27 Jan 2015 10:42:30 +0000 Subject: [PATCH 181/268] Update author section in manpage --- noice.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index e4f187fe..61669e5f 100644 --- a/noice.1 +++ b/noice.1 @@ -105,4 +105,4 @@ backspacekey set to DEC. .Sh AUTHORS .Nm was developed by Lazaros Koromilas with -contributions by sin . +contributions by Dimitris Papastamos . From df41119f334b3d9a2386616c35a05e5b5b091a70 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 12:46:42 +0200 Subject: [PATCH 182/268] Update dates --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 036c735e..1f62a516 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2014 Lazaros Koromilas -Copyright (c) 2014 Dimitris Papastamos +Copyright (c) 2014-2015 Lazaros Koromilas +Copyright (c) 2014-2015 Dimitris Papastamos All rights reserved. Redistribution and use in source and binary forms, with or without From f39db2b36bdc2660f8d15c7ce166615a86d2a8c4 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 13:28:00 +0200 Subject: [PATCH 183/268] Correct IRIX build notes --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 83033755..cc25355e 100644 --- a/README +++ b/README @@ -42,7 +42,7 @@ follow. * IRIX 6.5: Tested with gcc from http://freeware.sgi.com/. - make CC="gcc" LDLIBS="-lgen" + make CC="gcc" LDLIBS="-lgen -lcurses" * Haiku: From 68be0868c642b7c96fe247b22af933a58371f781 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 13:29:12 +0200 Subject: [PATCH 184/268] Also treat ^H as backspace --- config.def.h | 1 + noice.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index 4c7ade3e..996436f3 100644 --- a/config.def.h +++ b/config.def.h @@ -18,6 +18,7 @@ struct key bindings[] = { { KEY_BACKSPACE, SEL_BACK }, { KEY_LEFT, SEL_BACK }, { 'h', SEL_BACK }, + { CONTROL('H'), SEL_BACK }, /* Inside */ { KEY_ENTER, SEL_GOIN }, { '\r', SEL_GOIN }, diff --git a/noice.c b/noice.c index e841efa9..af9a34d6 100644 --- a/noice.c +++ b/noice.c @@ -327,7 +327,7 @@ readln(void) while ((c = getch()) != ERR) { if (c == KEY_ENTER || c == '\r') break; - if (c == KEY_BACKSPACE) { + if (c == KEY_BACKSPACE || c == CONTROL('H')) { getyx(stdscr, y, x); if (x >= x0) { i--; @@ -386,7 +386,7 @@ readmore(char **str) ret = 1; goto out; } - if (c == KEY_BACKSPACE) { + if (c == KEY_BACKSPACE || c == CONTROL('H')) { i--; if (i > 0) { ln = xrealloc(ln, (i + 1) * sizeof(*ln)); From cacd576240f61a3bfb1da47c58446c20bec31cb3 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 13:45:25 +0200 Subject: [PATCH 185/268] Remove unused include --- util.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/util.h b/util.h index 89110e51..b1540858 100644 --- a/util.h +++ b/util.h @@ -1,5 +1,3 @@ -#include - #undef strlcat size_t strlcat(char *, const char *, size_t); #undef strlcpy From ab0c9e592146fefe4298cdc3e061bfb8f8a8fb1f Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 27 Jan 2015 14:38:37 +0200 Subject: [PATCH 186/268] Keep last valid state on regex errors --- noice.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index af9a34d6..85ec3d73 100644 --- a/noice.c +++ b/noice.c @@ -749,8 +749,13 @@ moretyping: /* Check regex errors */ if (tmp != NULL) r = setfilter(&re, tmp); - if (r != 0 && nowtyping) - goto moretyping; + if (r != 0) + if (nowtyping) { + goto moretyping; + } else { + free(tmp); + goto nochange; + } /* Copy or reset filter */ free(filter); if (tmp != NULL) From 3c45733f470bebf036289348d7c2fae7b02b14eb Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 28 Jan 2015 12:30:59 +0200 Subject: [PATCH 187/268] Rework readmore(), replace goto with a switch --- noice.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/noice.c b/noice.c index 85ec3d73..63002cf9 100644 --- a/noice.c +++ b/noice.c @@ -367,26 +367,26 @@ readln(void) int readmore(char **str) { - int c; - int i; + int c, ret = 0; + size_t i; char *ln = *str; - int ret = 0; if (ln != NULL) i = strlen(ln); else i = 0; - DPRINTF_D(i); curs_set(TRUE); c = getch(); - if (c == KEY_ENTER || c == '\r') { + switch (c) { + case KEY_ENTER: + case '\r': ret = 1; - goto out; - } - if (c == KEY_BACKSPACE || c == CONTROL('H')) { + break; + case KEY_BACKSPACE: + case CONTROL('H'): i--; if (i > 0) { ln = xrealloc(ln, (i + 1) * sizeof(*ln)); @@ -395,13 +395,14 @@ readmore(char **str) free(ln); ln = NULL; } - goto out; + break; + default: + i++; + ln = xrealloc(ln, (i + 1) * sizeof(*ln)); + ln[i - 1] = c; + ln[i] = '\0'; } - ln = xrealloc(ln, (i + 2) * sizeof(*ln)); - ln[i] = c; - i++; - ln[i] = '\0'; -out: + curs_set(FALSE); *str = ln; From 0aefc2f4962a89b7a7731583862416871afeacd7 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 28 Jan 2015 12:47:11 +0200 Subject: [PATCH 188/268] Change scope to always check the correct return value --- noice.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/noice.c b/noice.c index 63002cf9..80be09f0 100644 --- a/noice.c +++ b/noice.c @@ -748,15 +748,16 @@ moretyping: if (r == 1) nowtyping = 0; /* Check regex errors */ - if (tmp != NULL) + if (tmp != NULL) { r = setfilter(&re, tmp); - if (r != 0) - if (nowtyping) { - goto moretyping; - } else { - free(tmp); - goto nochange; - } + if (r != 0) + if (nowtyping) { + goto moretyping; + } else { + free(tmp); + goto nochange; + } + } /* Copy or reset filter */ free(filter); if (tmp != NULL) From 6735c1f9796a5d06d39ed78538d64a6ba26008f9 Mon Sep 17 00:00:00 2001 From: lostd Date: Wed, 28 Jan 2015 22:01:26 +0200 Subject: [PATCH 189/268] More concise comment on nextsel() --- noice.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 80be09f0..5358111f 100644 --- a/noice.c +++ b/noice.c @@ -291,10 +291,7 @@ printprompt(char *str) printw(str); } -/* - * Returns SEL_{QUIT,BACK,GOIN,FLTR,NEXT,PREV,PGDN,PGUP,SH,CD} - * Returns 0 otherwise - */ +/* Returns SEL_* if key is bound and 0 otherwise */ int nextsel(void) { From a63aac0b11c1bc8e54eed95f2fce6fd6dbb41ca8 Mon Sep 17 00:00:00 2001 From: sin Date: Sat, 31 Jan 2015 22:02:59 +0000 Subject: [PATCH 190/268] Add 't' command to sort output by entry's mtime --- config.def.h | 1 + noice.1 | 2 ++ noice.c | 10 ++++++++++ 3 files changed, 13 insertions(+) diff --git a/config.def.h b/config.def.h index 996436f3..3b12199e 100644 --- a/config.def.h +++ b/config.def.h @@ -47,4 +47,5 @@ struct key bindings[] = { { '!', SEL_SH }, /* Change dir */ { 'c', SEL_CD }, + { 't', SEL_MTIME }, }; diff --git a/noice.1 b/noice.1 index 61669e5f..d3d08790 100644 --- a/noice.1 +++ b/noice.1 @@ -47,6 +47,8 @@ Change filter (see below for more information). Enter filter-as-you-type mode. .It Ic c Change into the given directory. +.It Ic t +Sort by time modified. .It Ic ! Spawn shell in current directory. .It Ic q diff --git a/noice.c b/noice.c index 5358111f..04115cf5 100644 --- a/noice.c +++ b/noice.c @@ -56,6 +56,7 @@ enum action { SEL_PGUP, SEL_SH, SEL_CD, + SEL_MTIME, }; struct key { @@ -68,8 +69,11 @@ struct key { struct entry { char *name; mode_t mode; + time_t t; }; +int mtimeorder; + /* * Layout: * .--------- @@ -231,6 +235,8 @@ entrycmp(const void *va, const void *vb) a = (struct entry *)va; b = (struct entry *)vb; + if (mtimeorder) + return b->t - a->t; return strcmp(a->name, b->name); } @@ -487,6 +493,7 @@ dentfill(char *path, struct entry **dents, if (r == -1) printerr(1, "lstat"); (*dents)[n].mode = sb.st_mode; + (*dents)[n].t = sb.st_mtime; n++; } @@ -809,6 +816,9 @@ moretyping: filter = xstrdup(ifilter); /* Reset filter */ DPRINTF_S(path); goto out; + case SEL_MTIME: + mtimeorder = !mtimeorder; + goto out; } } From c2e82550f7597212fd9837a69c116d81ebdc2199 Mon Sep 17 00:00:00 2001 From: sin Date: Sat, 31 Jan 2015 22:58:08 +0000 Subject: [PATCH 191/268] Minor manpage fix --- noice.1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/noice.1 b/noice.1 index d3d08790..c2e24dc1 100644 --- a/noice.1 +++ b/noice.1 @@ -101,8 +101,7 @@ struct assoc assocs[] = { }; .Ed .Sh KNOWN ISSUES -If you are using urxvt you might have to start it with -backspacekey set to DEC. +If you are using urxvt you might have to set backspacekey to DEC. .Pp .Sh AUTHORS .Nm From cefb945e35c39f98cbbdb3926155bcd2ecd287f4 Mon Sep 17 00:00:00 2001 From: lostd Date: Sun, 1 Feb 2015 14:10:28 +0200 Subject: [PATCH 192/268] Meaningful comments --- config.def.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 3b12199e..f3f6a48c 100644 --- a/config.def.h +++ b/config.def.h @@ -27,7 +27,7 @@ struct key bindings[] = { /* Filter */ { '/', SEL_FLTR }, { '&', SEL_FLTR }, - /* Type */ + /* Filter as you type */ { '?', SEL_TYPE }, /* Next */ { 'j', SEL_NEXT }, @@ -47,5 +47,6 @@ struct key bindings[] = { { '!', SEL_SH }, /* Change dir */ { 'c', SEL_CD }, + /* Sort by time */ { 't', SEL_MTIME }, }; From 162922b98474db445511bc45ca70ebaec82bd77c Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 4 Feb 2015 12:32:16 +0000 Subject: [PATCH 193/268] Move mtimeorder to config.def.h --- config.def.h | 2 ++ noice.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index f3f6a48c..311adb27 100644 --- a/config.def.h +++ b/config.def.h @@ -2,6 +2,8 @@ #define CURSR " > " #define EMPTY " " +int mtimeorder = 0; /* set to 1 to sort by time in the default case */ + struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, { "\\.(png|jpg|gif)$", "feh" }, diff --git a/noice.c b/noice.c index 04115cf5..0a811378 100644 --- a/noice.c +++ b/noice.c @@ -72,8 +72,6 @@ struct entry { time_t t; }; -int mtimeorder; - /* * Layout: * .--------- From cc65e4098fbf2b99409b37cc4c8d42e794781937 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 5 Feb 2015 17:53:50 +0200 Subject: [PATCH 194/268] Clarify state toggling --- config.def.h | 4 ++-- noice.1 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.def.h b/config.def.h index 311adb27..a7e5ffce 100644 --- a/config.def.h +++ b/config.def.h @@ -2,7 +2,7 @@ #define CURSR " > " #define EMPTY " " -int mtimeorder = 0; /* set to 1 to sort by time in the default case */ +int mtimeorder = 0; /* Set to 1 to sort by time in the default case */ struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, @@ -49,6 +49,6 @@ struct key bindings[] = { { '!', SEL_SH }, /* Change dir */ { 'c', SEL_CD }, - /* Sort by time */ + /* Toggle sort by time */ { 't', SEL_MTIME }, }; diff --git a/noice.1 b/noice.1 index c2e24dc1..1a353b3d 100644 --- a/noice.1 +++ b/noice.1 @@ -48,7 +48,7 @@ Enter filter-as-you-type mode. .It Ic c Change into the given directory. .It Ic t -Sort by time modified. +Toggle sort by time modified. .It Ic ! Spawn shell in current directory. .It Ic q From cdf8a429c5fe8efc176132aed266db2e6746aeee Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 17 Feb 2015 19:03:51 +0200 Subject: [PATCH 195/268] Fix an unsigned conversion error --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 0a811378..31c0771e 100644 --- a/noice.c +++ b/noice.c @@ -369,7 +369,7 @@ int readmore(char **str) { int c, ret = 0; - size_t i; + int i; char *ln = *str; if (ln != NULL) From 3682c720ba1eb4ce05ea756c4b287b2b83fbae3e Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 11 Mar 2015 18:55:28 +0000 Subject: [PATCH 196/268] Add C-l to force a redraw Often I am waiting for a file to download and be renamed from .foo.part to .foo. Forcing a redraw is a simple way to check if the file has completed downloading. --- config.def.h | 1 + noice.1 | 2 ++ noice.c | 3 +++ 3 files changed, 6 insertions(+) diff --git a/config.def.h b/config.def.h index a7e5ffce..45e9d5b0 100644 --- a/config.def.h +++ b/config.def.h @@ -51,4 +51,5 @@ struct key bindings[] = { { 'c', SEL_CD }, /* Toggle sort by time */ { 't', SEL_MTIME }, + { CONTROL('L'), SEL_REDRAW }, }; diff --git a/noice.1 b/noice.1 index 1a353b3d..2d940ad7 100644 --- a/noice.1 +++ b/noice.1 @@ -49,6 +49,8 @@ Enter filter-as-you-type mode. Change into the given directory. .It Ic t Toggle sort by time modified. +.It Ic l +Force a redraw. .It Ic ! Spawn shell in current directory. .It Ic q diff --git a/noice.c b/noice.c index 31c0771e..e56a5f9a 100644 --- a/noice.c +++ b/noice.c @@ -57,6 +57,7 @@ enum action { SEL_SH, SEL_CD, SEL_MTIME, + SEL_REDRAW, }; struct key { @@ -817,6 +818,8 @@ moretyping: case SEL_MTIME: mtimeorder = !mtimeorder; goto out; + case SEL_REDRAW: + goto out; } } From 97cfd82eedfc5173736c6780e8efcdc335054a8b Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 11 Mar 2015 19:03:43 +0000 Subject: [PATCH 197/268] Update contact information in README --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index cc25355e..44edb931 100644 --- a/README +++ b/README @@ -58,5 +58,5 @@ follow. Contact ======= -You can reach us through the freenode IRC network at #2f30. If you have -any patches, ideas or feedback feel free to join. +To report bugs and/or submit patches, you can reach us through +the freenode IRC network at #2f30 or by subscribing to tech@lists.2f30.org. From bc11d7b201fcb81f5457d5e3916512126649f6cf Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 12 Mar 2015 14:57:34 +0200 Subject: [PATCH 198/268] Confirm we are in a terminal --- noice.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/noice.c b/noice.c index e56a5f9a..600e5702 100644 --- a/noice.c +++ b/noice.c @@ -835,6 +835,10 @@ main(int argc, char *argv[]) char cwd[PATH_MAX], *ipath; char *ifilter; + /* Confirm we are in a terminal */ + if (!isatty(STDIN_FILENO)) + printerr(1, "isatty"); + if (getuid() == 0) ifilter = "."; else From 3dc40acbffd2c57f92401eab8ce32114bea8788f Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 12 Mar 2015 16:12:01 +0200 Subject: [PATCH 199/268] Key bindings to run user-defined commands --- config.def.h | 7 +++++-- noice.1 | 8 ++++++-- noice.c | 33 ++++++++++++++++++++++----------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/config.def.h b/config.def.h index 45e9d5b0..9b730ba4 100644 --- a/config.def.h +++ b/config.def.h @@ -45,11 +45,14 @@ struct key bindings[] = { /* Page up */ { KEY_PPAGE, SEL_PGUP }, { CONTROL('U'), SEL_PGUP }, - /* Shell */ - { '!', SEL_SH }, /* Change dir */ { 'c', SEL_CD }, /* Toggle sort by time */ { 't', SEL_MTIME }, { CONTROL('L'), SEL_REDRAW }, + /* Run command */ + { '!', SEL_RUN, "sh" }, + { 'z', SEL_RUN, "top" }, + /* Run command with argument */ + { 'e', SEL_RUNARG, "vi" }, }; diff --git a/noice.1 b/noice.1 index 2d940ad7..076b1888 100644 --- a/noice.1 +++ b/noice.1 @@ -1,4 +1,4 @@ -.Dd January 27, 2015 +.Dd March 12, 2015 .Dt NOICE 1 .Os .Sh NAME @@ -52,7 +52,11 @@ Toggle sort by time modified. .It Ic l Force a redraw. .It Ic ! -Spawn shell in current directory. +Spawn an sh shell in current directory. +.It Ic z +Run the system top utility. +.It Ic e +Open selected entry with the vi editor. .It Ic q Quit. .El diff --git a/noice.c b/noice.c index 600e5702..1d34017c 100644 --- a/noice.c +++ b/noice.c @@ -54,15 +54,17 @@ enum action { SEL_PREV, SEL_PGDN, SEL_PGUP, - SEL_SH, SEL_CD, SEL_MTIME, SEL_REDRAW, + SEL_RUN, + SEL_RUNARG, }; struct key { int sym; /* Key pressed */ enum action act; /* Action */ + char *run; /* Program to run */ }; #include "config.h" @@ -296,17 +298,20 @@ printprompt(char *str) printw(str); } -/* Returns SEL_* if key is bound and 0 otherwise */ +/* Returns SEL_* if key is bound and 0 otherwise + Also modifies the run pointer (used on SEL_{RUN,RUNARG}) */ int -nextsel(void) +nextsel(char **run) { int c, i; c = getch(); for (i = 0; i < LEN(bindings); i++) - if (c == bindings[i].sym) + if (c == bindings[i].sym) { + *run = bindings[i].run; return bindings[i].act; + } return 0; } @@ -571,7 +576,7 @@ browse(const char *ipath, const char *ifilter) regex_t filter_re, re; char *cwd, *newpath, *oldpath = NULL; struct stat sb; - char *name, *bin, *dir, *tmp; + char *name, *bin, *dir, *tmp, *run; int nowtyping = 0; begin: @@ -640,7 +645,7 @@ begin: goto moretyping; nochange: - switch (nextsel()) { + switch (nextsel(&run)) { case SEL_QUIT: free(path); free(filter); @@ -789,11 +794,6 @@ moretyping: if (cur > 0) cur -= MIN((LINES - 4) / 2, cur); break; - case SEL_SH: - exitcurses(); - spawn("/bin/sh", NULL, path); - initcurses(); - break; case SEL_CD: /* Read target dir */ printprompt("chdir: "); @@ -820,6 +820,17 @@ moretyping: goto out; case SEL_REDRAW: goto out; + case SEL_RUN: + exitcurses(); + spawn(run, NULL, path); + initcurses(); + break; + case SEL_RUNARG: + name = dents[cur].name; + exitcurses(); + spawn(run, name, path); + initcurses(); + break; } } From d337e25fb317391331ee6883a3c1c1a5eee890b1 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 12 Mar 2015 14:20:36 +0000 Subject: [PATCH 200/268] Bump to 0.2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0231438d..3c96ba19 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.1 +VERSION = 0.2 PREFIX = /usr/local MANPREFIX = $(PREFIX)/man From 2ab57e77995749b6c9a5b374128ba0601bfa1cbe Mon Sep 17 00:00:00 2001 From: Alexander Huemer Date: Mon, 4 May 2015 23:19:20 +0200 Subject: [PATCH 201/268] Be case insensitive for file extensions --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 1d34017c..8d7f7f1d 100644 --- a/noice.c +++ b/noice.c @@ -193,7 +193,7 @@ openwith(char *file) for (i = 0; i < LEN(assocs); i++) { if (regcomp(®ex, assocs[i].regex, - REG_NOSUB | REG_EXTENDED) != 0) + REG_NOSUB | REG_EXTENDED | REG_ICASE) != 0) continue; if (regexec(®ex, file, 0, NULL, 0) == 0) { bin = assocs[i].bin; From b9cac3a190df07bcc0da7aa8318983f8e061f7c0 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 5 May 2015 18:45:35 +0100 Subject: [PATCH 202/268] Make setfilter() regexes case-insensitive --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 8d7f7f1d..1cd97263 100644 --- a/noice.c +++ b/noice.c @@ -211,7 +211,7 @@ setfilter(regex_t *regex, char *filter) char *errbuf; int r; - r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED); + r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED | REG_ICASE); if (r != 0) { errbuf = xmalloc(COLS * sizeof(char)); regerror(r, regex, errbuf, COLS * sizeof(char)); From ee72ebd042e395e8c646a14d26d60fb99a8faa90 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 4 Jun 2015 23:03:57 +0100 Subject: [PATCH 203/268] Make config independent to avoid accidental overwrites --- Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 3c96ba19..ea06b2d1 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,9 @@ noice.o: util.h config.h strlcat.o: util.h strlcpy.o: util.h +config.h: + cp config.def.h $@ + install: all mkdir -p $(DESTDIR)$(PREFIX)/bin cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin @@ -40,8 +43,3 @@ dist: clean: rm -f $(BIN) $(OBJ) noice-$(VERSION).tar.gz - -.SUFFIXES: .def.h - -.def.h.h: - cp $< $@ From f6fd1cc02fa33a62d1f01cbabac220c0f67b27c5 Mon Sep 17 00:00:00 2001 From: lostd Date: Tue, 9 Jun 2015 09:12:17 +0100 Subject: [PATCH 204/268] Sort includes --- noice.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index 1cd97263..62324894 100644 --- a/noice.c +++ b/noice.c @@ -2,18 +2,18 @@ #include #include +#include +#include #include #include -#include -#include #include #include #include #include -#include -#include -#include #include +#include +#include +#include #include #include From d9b231742a1088f9bab4968563c3bd1c25975014 Mon Sep 17 00:00:00 2001 From: lostd Date: Sat, 13 Jun 2015 11:09:58 +0100 Subject: [PATCH 205/268] We no longer use lists --- queue.h | 648 -------------------------------------------------------- 1 file changed, 648 deletions(-) delete mode 100644 queue.h diff --git a/queue.h b/queue.h deleted file mode 100644 index a09d8ca6..00000000 --- a/queue.h +++ /dev/null @@ -1,648 +0,0 @@ -/* $OpenBSD: src/sys/sys/queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */ -/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. 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 the University 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 REGENTS 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 REGENTS 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. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) -#define _Q_INVALIDATE(a) (a) = ((void *)-1) -#else -#define _Q_INVALIDATE(a) -#endif - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST(head); \ - (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ - (var) = (tvar)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->slh_first; \ - \ - while (curelm->field.sle_next != (elm)) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - _Q_INVALIDATE((elm)->field.sle_next); \ - } \ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List access methods - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST(head); \ - (var) && ((tvar) = LIST_NEXT(var, field), 1); \ - (var) = (tvar)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SIMPLEQ_FIRST(head); \ - (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ - (var) = (tvar)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ - if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ - == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -/* - * XOR Simple queue definitions. - */ -#define XSIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqx_first; /* first element */ \ - struct type **sqx_last; /* addr of last next element */ \ - unsigned long sqx_cookie; \ -} - -#define XSIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqx_next; /* next element */ \ -} - -/* - * XOR Simple queue access methods. - */ -#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ - (unsigned long)(ptr))) -#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) -#define XSIMPLEQ_END(head) NULL -#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) -#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) - - -#define XSIMPLEQ_FOREACH(var, head, field) \ - for ((var) = XSIMPLEQ_FIRST(head); \ - (var) != XSIMPLEQ_END(head); \ - (var) = XSIMPLEQ_NEXT(head, var, field)) - -#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = XSIMPLEQ_FIRST(head); \ - (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ - (var) = (tvar)) - -/* - * XOR Simple queue functions. - */ -#define XSIMPLEQ_INIT(head) do { \ - arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ - (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ -} while (0) - -#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqx_next = (head)->sqx_first) == \ - XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ - (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ -} while (0) - -#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ - *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ -} while (0) - -#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ - XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ - (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ -} while (0) - -#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ - (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ -} while (0) - -#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ - if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ - (elm)->field.sqx_next)->field.sqx_next) \ - == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = \ - XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ -} while (0) - - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * tail queue access methods - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_NEXT(var, field), 1); \ - (var) = (tvar)) - - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_PREV(var, headname, field), 1); \ - (var) = (tvar)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue access methods - */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head) && \ - ((tvar) = CIRCLEQ_NEXT(var, field), 1); \ - (var) = (tvar)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) - -#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = CIRCLEQ_LAST(head, headname); \ - (var) != CIRCLEQ_END(head) && \ - ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \ - (var) = (tvar)) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ From ac36d0b287d5c54f811aab3e896516aa0cb68ec7 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 2 Jul 2015 00:56:47 +0100 Subject: [PATCH 206/268] Refactor parts of browse() into populate() and redraw() --- noice.c | 191 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 109 insertions(+), 82 deletions(-) diff --git a/noice.c b/noice.c index 62324894..ac965bd4 100644 --- a/noice.c +++ b/noice.c @@ -75,6 +75,12 @@ struct entry { time_t t; }; +/* Global context */ +struct entry *dents; +int n, cur; +char *path, *oldpath; +char *fltr; + /* * Layout: * .--------- @@ -565,36 +571,29 @@ dentfind(struct entry *dents, int n, char *cwd, char *path) return 0; } -void -browse(const char *ipath, const char *ifilter) +int +populate(void) { - struct entry *dents; - int i, n, cur, r, fd; - int nlines, odd; - char *path = xstrdup(ipath); - char *filter = xstrdup(ifilter); - regex_t filter_re, re; - char *cwd, *newpath, *oldpath = NULL; - struct stat sb; - char *name, *bin, *dir, *tmp, *run; - int nowtyping = 0; - -begin: - /* Path and filter should be malloc(3)-ed strings at all times */ - n = 0; - dents = NULL; + regex_t re; + int r; + /* Can fail when permissions change while browsing */ if (canopendir(path) == 0) { printwarn(); - goto nochange; + return -1; } /* Search filter */ - r = setfilter(&filter_re, filter); + r = setfilter(&re, fltr); if (r != 0) - goto nochange; + return -1; - n = dentfill(path, &dents, visible, &filter_re); + dentfree(dents, n); + + n = 0; + dents = NULL; + + n = dentfill(path, &dents, visible, &re); qsort(dents, n, sizeof(*dents), entrycmp); @@ -603,52 +602,85 @@ begin: free(oldpath); oldpath = NULL; + return 0; +} + +void +redraw(void) +{ + int nlines, odd; + char *cwd; + int i; + + nlines = MIN(LINES - 4, n); + + /* Clean screen */ + erase(); + + /* Strip trailing slashes */ + for (i = strlen(path) - 1; i > 0; i--) + if (path[i] == '/') + path[i] = '\0'; + else + break; + + DPRINTF_D(cur); + DPRINTF_S(path); + + /* No text wrapping in cwd line */ + cwd = xmalloc(COLS * sizeof(char)); + strlcpy(cwd, path, COLS * sizeof(char)); + cwd[COLS - strlen(CWD) - 1] = '\0'; + + printw(CWD "%s\n\n", cwd); + + /* Print listing */ + odd = ISODD(nlines); + if (cur < nlines / 2) { + for (i = 0; i < nlines; i++) + printent(&dents[i], i == cur); + } else if (cur >= n - nlines / 2) { + for (i = n - nlines; i < n; i++) + printent(&dents[i], i == cur); + } else { + for (i = cur - nlines / 2; + i < cur + nlines / 2 + odd; i++) + printent(&dents[i], i == cur); + } +} + +void +browse(const char *ipath, const char *ifilter) +{ + int r, fd; + regex_t re; + char *newpath; + struct stat sb; + char *name, *bin, *dir, *tmp, *run; + int nowtyping = 0; + + oldpath = NULL; + path = xstrdup(ipath); + fltr = xstrdup(ifilter); +begin: + /* Path and filter should be malloc(3)-ed strings at all times */ + r = populate(); + if (r == -1) { + nowtyping = 0; + goto nochange; + } + for (;;) { - nlines = MIN(LINES - 4, n); - - /* Clean screen */ - erase(); - - /* Strip trailing slashes */ - for (i = strlen(path) - 1; i > 0; i--) - if (path[i] == '/') - path[i] = '\0'; - else - break; - - DPRINTF_D(cur); - DPRINTF_S(path); - - /* No text wrapping in cwd line */ - cwd = xmalloc(COLS * sizeof(char)); - strlcpy(cwd, path, COLS * sizeof(char)); - cwd[COLS - strlen(CWD) - 1] = '\0'; - - printw(CWD "%s\n\n", cwd); - - /* Print listing */ - odd = ISODD(nlines); - if (cur < nlines / 2) { - for (i = 0; i < nlines; i++) - printent(&dents[i], i == cur); - } else if (cur >= n - nlines / 2) { - for (i = n - nlines; i < n; i++) - printent(&dents[i], i == cur); - } else { - for (i = cur - nlines / 2; - i < cur + nlines / 2 + odd; i++) - printent(&dents[i], i == cur); - } + redraw(); /* Handle filter-as-you-type mode */ if (nowtyping) goto moretyping; - nochange: switch (nextsel(&run)) { case SEL_QUIT: free(path); - free(filter); + free(fltr); dentfree(dents, n); return; case SEL_BACK: @@ -666,9 +698,9 @@ nochange: oldpath = path; path = dir; /* Reset filter */ - free(filter); - filter = xstrdup(ifilter); - goto out; + free(fltr); + fltr = xstrdup(ifilter); + goto begin; case SEL_GOIN: /* Cannot descend in empty directories */ if (n == 0) @@ -705,9 +737,9 @@ nochange: free(path); path = newpath; /* Reset filter */ - free(filter); - filter = xstrdup(ifilter); - goto out; + free(fltr); + fltr = xstrdup(ifilter); + goto begin; case S_IFREG: bin = openwith(newpath); if (bin == NULL) { @@ -736,13 +768,13 @@ nochange: free(tmp); goto nochange; } - free(filter); - filter = tmp; - DPRINTF_S(filter); + free(fltr); + fltr = tmp; + DPRINTF_S(fltr); /* Save current */ if (n > 0) oldpath = makepath(path, dents[cur].name); - goto out; + goto begin; case SEL_TYPE: nowtyping = 1; tmp = NULL; @@ -767,17 +799,17 @@ moretyping: } } /* Copy or reset filter */ - free(filter); + free(fltr); if (tmp != NULL) - filter = xstrdup(tmp); + fltr = xstrdup(tmp); else - filter = xstrdup(ifilter); + fltr = xstrdup(ifilter); /* Save current */ if (n > 0) oldpath = makepath(path, dents[cur].name); if (!nowtyping) free(tmp); - goto out; + goto begin; case SEL_NEXT: if (cur < n - 1) cur++; @@ -811,15 +843,15 @@ moretyping: } free(path); path = newpath; - free(filter); - filter = xstrdup(ifilter); /* Reset filter */ + free(fltr); + fltr = xstrdup(ifilter); /* Reset filter */ DPRINTF_S(path); - goto out; + goto begin; case SEL_MTIME: mtimeorder = !mtimeorder; - goto out; + goto begin; case SEL_REDRAW: - goto out; + goto begin; case SEL_RUN: exitcurses(); spawn(run, NULL, path); @@ -833,11 +865,6 @@ moretyping: break; } } - -out: - dentfree(dents, n); - - goto begin; } int From 018b52a8ee0fce1f6697cd8c806d9a91f4a82663 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 2 Jul 2015 00:58:01 +0100 Subject: [PATCH 207/268] More test cases about permissions --- mktest.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mktest.sh b/mktest.sh index 1af7a6ee..e72b81fb 100644 --- a/mktest.sh +++ b/mktest.sh @@ -18,8 +18,11 @@ ln -s normal-dir ln-normal-dir ln -s nowhere ln-nowhere mkfifo mk-fifo touch no-access && chmod 000 no-access +mkdir no-access-dir && chmod 000 no-access-dir ln -s ../normal.txt normal-dir/ln-normal.txt ln -s ../normal.txt normal-dir/ln-normal echo 'int main(void) { *((char *)0) = 0; }' > ill.c make ill > /dev/null echo 'test/ill' > ill.sh +mkdir empty-dir +echo 'chmod 000 test' > lock.sh From 0548a181e64bd9e5af6cc72282620356890b7bed Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 2 Jul 2015 01:02:47 +0100 Subject: [PATCH 208/268] Test for when permissions change while browsing --- mktest.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mktest.sh b/mktest.sh index e72b81fb..9509f45e 100644 --- a/mktest.sh +++ b/mktest.sh @@ -25,4 +25,6 @@ echo 'int main(void) { *((char *)0) = 0; }' > ill.c make ill > /dev/null echo 'test/ill' > ill.sh mkdir empty-dir -echo 'chmod 000 test' > lock.sh +mkdir cage +echo 'chmod 000 test/cage' > cage/lock.sh +echo 'chmod 755 test/cage' > cage-unlock.sh From 1742598256abf086385b4fb4a2cf2a81fc6aff05 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 2 Jul 2015 01:07:09 +0100 Subject: [PATCH 209/268] Escape unreadable dirs we are already into We care about the directory we are going to, so there is no reason to get locked inside there if the parent is readable. --- noice.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index ac965bd4..8fe09436 100644 --- a/noice.c +++ b/noice.c @@ -689,11 +689,12 @@ nochange: strcmp(path, ".") == 0 || strchr(path, '/') == NULL) goto nochange; - if (canopendir(path) == 0) { + dir = xdirname(path); + if (canopendir(dir) == 0) { + free(dir); printwarn(); goto nochange; } - dir = xdirname(path); /* Save history */ oldpath = path; path = dir; From 11274e0baa2312140c6625d20ebd22502b939367 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 2 Jul 2015 01:14:27 +0100 Subject: [PATCH 210/268] Test the case of unreadable parent --- mktest.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mktest.sh b/mktest.sh index 9509f45e..c808d387 100644 --- a/mktest.sh +++ b/mktest.sh @@ -28,3 +28,5 @@ mkdir empty-dir mkdir cage echo 'chmod 000 test/cage' > cage/lock.sh echo 'chmod 755 test/cage' > cage-unlock.sh +mkdir cage/lion +echo 'chmod 000 test/cage' > cage/lion/lock.sh From 0152d363515a774111bc08182873566ffb079db4 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 2 Jul 2015 17:49:17 +0100 Subject: [PATCH 211/268] Use proper tags for AUTHORS section in manpage Fix some mandoc -Tlint warnings as well. --- noice.1 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/noice.1 b/noice.1 index 076b1888..0c8eea03 100644 --- a/noice.1 +++ b/noice.1 @@ -43,7 +43,7 @@ Open file or enter directory. Back up one directory level. .It Ic / or & Change filter (see below for more information). -.It Ic ? +.It Ic \&? Enter filter-as-you-type mode. .It Ic c Change into the given directory. @@ -51,7 +51,7 @@ Change into the given directory. Toggle sort by time modified. .It Ic l Force a redraw. -.It Ic ! +.It Ic \&! Spawn an sh shell in current directory. .It Ic z Run the system top utility. @@ -108,8 +108,6 @@ struct assoc assocs[] = { .Ed .Sh KNOWN ISSUES If you are using urxvt you might have to set backspacekey to DEC. -.Pp .Sh AUTHORS -.Nm -was developed by Lazaros Koromilas with -contributions by Dimitris Papastamos . +.An Lazaros Koromilas Aq Mt lostd@2f30.org , +.An Dimitris Papastamos Aq Mt sin@2f30.org . From 4db0d0dae08090f1bdf7b9a629777ba09e222667 Mon Sep 17 00:00:00 2001 From: lostd Date: Thu, 2 Jul 2015 22:51:58 +0100 Subject: [PATCH 212/268] We don't want to exit the typing mode because of an error Delay displaying the message until return is pressed. Also contain all printwarn() calls inside browse(). --- noice.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index 8fe09436..2c408fe1 100644 --- a/noice.c +++ b/noice.c @@ -578,10 +578,8 @@ populate(void) int r; /* Can fail when permissions change while browsing */ - if (canopendir(path) == 0) { - printwarn(); + if (canopendir(path) == 0) return -1; - } /* Search filter */ r = setfilter(&re, fltr); @@ -666,8 +664,10 @@ begin: /* Path and filter should be malloc(3)-ed strings at all times */ r = populate(); if (r == -1) { - nowtyping = 0; - goto nochange; + if (!nowtyping) { + printwarn(); + goto nochange; + } } for (;;) { From dcde07637141064a39c79db93d47f6fe588a782d Mon Sep 17 00:00:00 2001 From: lostd Date: Sun, 12 Jul 2015 13:32:31 +0100 Subject: [PATCH 213/268] Add keys to move to the first and last entry --- config.def.h | 8 ++++++++ noice.1 | 4 ++++ noice.c | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/config.def.h b/config.def.h index 9b730ba4..167e6481 100644 --- a/config.def.h +++ b/config.def.h @@ -45,6 +45,14 @@ struct key bindings[] = { /* Page up */ { KEY_PPAGE, SEL_PGUP }, { CONTROL('U'), SEL_PGUP }, + /* Home */ + { KEY_HOME, SEL_HOME }, + { CONTROL('A'), SEL_HOME }, + { '^', SEL_HOME }, + /* End */ + { KEY_END, SEL_END }, + { CONTROL('E'), SEL_END }, + { '$', SEL_END }, /* Change dir */ { 'c', SEL_CD }, /* Toggle sort by time */ diff --git a/noice.1 b/noice.1 index 0c8eea03..ab400d61 100644 --- a/noice.1 +++ b/noice.1 @@ -37,6 +37,10 @@ Move to next entry. Scroll up half a page. .It Ic [Pgdown] or C-d Scroll down half a page. +.It Ic [Home] or C-a or ^ +Move to the first entry. +.It Ic [End] or C-e or $ +Move to the last entry. .It Ic l, [Right], [Return] or C-m Open file or enter directory. .It Ic h, [Left] or [Backspace] diff --git a/noice.c b/noice.c index 2c408fe1..228aedfa 100644 --- a/noice.c +++ b/noice.c @@ -54,6 +54,8 @@ enum action { SEL_PREV, SEL_PGDN, SEL_PGUP, + SEL_HOME, + SEL_END, SEL_CD, SEL_MTIME, SEL_REDRAW, @@ -827,6 +829,12 @@ moretyping: if (cur > 0) cur -= MIN((LINES - 4) / 2, cur); break; + case SEL_HOME: + cur = 0; + break; + case SEL_END: + cur = n - 1; + break; case SEL_CD: /* Read target dir */ printprompt("chdir: "); From 108996a802181e7acf3c562771bda8864c855e1d Mon Sep 17 00:00:00 2001 From: lostd Date: Mon, 13 Jul 2015 00:56:51 +0100 Subject: [PATCH 214/268] Recall current item on refresh or sorting mode change --- noice.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/noice.c b/noice.c index 228aedfa..ba529d6c 100644 --- a/noice.c +++ b/noice.c @@ -858,8 +858,14 @@ moretyping: goto begin; case SEL_MTIME: mtimeorder = !mtimeorder; + /* Save current */ + if (n > 0) + oldpath = makepath(path, dents[cur].name); goto begin; case SEL_REDRAW: + /* Save current */ + if (n > 0) + oldpath = makepath(path, dents[cur].name); goto begin; case SEL_RUN: exitcurses(); From c5283392fbf14c3a94be6b04e2561a14e9ec98df Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 19 Aug 2015 08:39:19 +0100 Subject: [PATCH 215/268] Add .mov to config.h --- config.def.h | 2 +- noice.1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.def.h b/config.def.h index 167e6481..a3553331 100644 --- a/config.def.h +++ b/config.def.h @@ -5,7 +5,7 @@ int mtimeorder = 0; /* Set to 1 to sort by time in the default case */ struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, + { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mplayer" }, { "\\.(png|jpg|gif)$", "feh" }, { "\\.(html|svg)$", "firefox" }, { "\\.pdf$", "mupdf" }, diff --git a/noice.1 b/noice.1 index ab400d61..bba780b7 100644 --- a/noice.1 +++ b/noice.1 @@ -102,7 +102,7 @@ The following example shows one possible configuration for file associations which is also the default: .Bd -literal struct assoc assocs[] = { - { "\\.(avi|mp4|mkv|mp3|ogg|flac)$", "mplayer" }, + { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mplayer" }, { "\\.(png|jpg|gif)$", "feh" }, { "\\.(html|svg)$", "firefox" }, { "\\.pdf$", "mupdf" }, From 1e18b85e56d98ca2daeb7adc587c28f5d653a01f Mon Sep 17 00:00:00 2001 From: lostd Date: Mon, 2 Nov 2015 03:21:41 +0200 Subject: [PATCH 216/268] Run screensaver after a period of idleness --- config.def.h | 2 ++ noice.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/config.def.h b/config.def.h index a3553331..80cb48c3 100644 --- a/config.def.h +++ b/config.def.h @@ -3,6 +3,8 @@ #define EMPTY " " int mtimeorder = 0; /* Set to 1 to sort by time in the default case */ +int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */ +char *idlecmd = "rain"; /* The screensaver program */ struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mplayer" }, diff --git a/noice.c b/noice.c index ba529d6c..18577d38 100644 --- a/noice.c +++ b/noice.c @@ -82,6 +82,7 @@ struct entry *dents; int n, cur; char *path, *oldpath; char *fltr; +int idle; /* * Layout: @@ -259,6 +260,7 @@ initcurses(void) intrflush(stdscr, FALSE); keypad(stdscr, TRUE); curs_set(FALSE); /* Hide cursor */ + timeout(1000); /* One second */ } void @@ -314,6 +316,10 @@ nextsel(char **run) int c, i; c = getch(); + if (c == -1) + idle++; + else + idle = 0; for (i = 0; i < LEN(bindings); i++) if (c == bindings[i].sym) { @@ -879,6 +885,13 @@ moretyping: initcurses(); break; } + /* Screensaver */ + if (idletimeout != 0 && idle == idletimeout) { + idle = 0; + exitcurses(); + spawn(idlecmd, NULL, NULL); + initcurses(); + } } } From 62736bf43a528f472dd01c87fa1d4ac247e07043 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 3 Nov 2015 17:48:39 +0000 Subject: [PATCH 217/268] Ignore SIGINT to allow returning back to noice when we kill the screensaver Use 'q' to quit. --- noice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/noice.c b/noice.c index 18577d38..ef866d04 100644 --- a/noice.c +++ b/noice.c @@ -918,6 +918,8 @@ main(int argc, char *argv[]) ipath = "/"; } + signal(SIGINT, SIG_IGN); + /* Test initial path */ if (canopendir(ipath) == 0) printerr(1, ipath); From d6e89ef07f46895077807c0db78ffd27334de392 Mon Sep 17 00:00:00 2001 From: sin Date: Sat, 14 Nov 2015 14:51:29 +0000 Subject: [PATCH 218/268] Revert "Run screensaver after a period of idleness" This reverts commit 1e18b85e56d98ca2daeb7adc587c28f5d653a01f. Revert until remaining issues are fixed. The filter search expires after 1 second of inactivity without the revert. --- config.def.h | 2 -- noice.c | 13 ------------- 2 files changed, 15 deletions(-) diff --git a/config.def.h b/config.def.h index 80cb48c3..a3553331 100644 --- a/config.def.h +++ b/config.def.h @@ -3,8 +3,6 @@ #define EMPTY " " int mtimeorder = 0; /* Set to 1 to sort by time in the default case */ -int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */ -char *idlecmd = "rain"; /* The screensaver program */ struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mplayer" }, diff --git a/noice.c b/noice.c index ef866d04..7192f48e 100644 --- a/noice.c +++ b/noice.c @@ -82,7 +82,6 @@ struct entry *dents; int n, cur; char *path, *oldpath; char *fltr; -int idle; /* * Layout: @@ -260,7 +259,6 @@ initcurses(void) intrflush(stdscr, FALSE); keypad(stdscr, TRUE); curs_set(FALSE); /* Hide cursor */ - timeout(1000); /* One second */ } void @@ -316,10 +314,6 @@ nextsel(char **run) int c, i; c = getch(); - if (c == -1) - idle++; - else - idle = 0; for (i = 0; i < LEN(bindings); i++) if (c == bindings[i].sym) { @@ -885,13 +879,6 @@ moretyping: initcurses(); break; } - /* Screensaver */ - if (idletimeout != 0 && idle == idletimeout) { - idle = 0; - exitcurses(); - spawn(idlecmd, NULL, NULL); - initcurses(); - } } } From f77b6a3fa6830c4e52e5ab7c4c07eb310743c75f Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 11:38:19 +0000 Subject: [PATCH 219/268] Simplify readln() Use getnstr() and be done with it. It will even beep now! --- noice.c | 46 ++++------------------------------------------ 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/noice.c b/noice.c index 7192f48e..17a0cea4 100644 --- a/noice.c +++ b/noice.c @@ -327,52 +327,14 @@ nextsel(char **run) char * readln(void) { - int c; - int i = 0; - char *ln = NULL; - int y, x, x0; + char ln[LINE_MAX]; echo(); curs_set(TRUE); - - /* Starting point */ - getyx(stdscr, y, x); - x0 = x; - - while ((c = getch()) != ERR) { - if (c == KEY_ENTER || c == '\r') - break; - if (c == KEY_BACKSPACE || c == CONTROL('H')) { - getyx(stdscr, y, x); - if (x >= x0) { - i--; - if (i > 0) { - ln = xrealloc(ln, i * sizeof(*ln)); - } else { - free(ln); - ln = NULL; - } - move(y, x); - printw("%c", ' '); - move(y, x); - } else { - move(y, x0); - } - continue; - } - ln = xrealloc(ln, (i + 1) * sizeof(*ln)); - ln[i] = c; - i++; - } - if (ln != NULL) { - ln = xrealloc(ln, (i + 1) * sizeof(*ln)); - ln[i] = '\0'; - } - - curs_set(FALSE); + getnstr(ln, sizeof(ln)); noecho(); - - return ln; + curs_set(FALSE); + return strdup(ln); } /* From ea0cce7b6390cab3ba7c16560f50e69322eb89fb Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 11:42:15 +0000 Subject: [PATCH 220/268] Make room for null-terminator --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 17a0cea4..c72417f9 100644 --- a/noice.c +++ b/noice.c @@ -331,7 +331,7 @@ readln(void) echo(); curs_set(TRUE); - getnstr(ln, sizeof(ln)); + getnstr(ln, sizeof(ln) - 1); noecho(); curs_set(FALSE); return strdup(ln); From 30ca80310aa805aee1e3501da6c6a27812855978 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 11:55:41 +0000 Subject: [PATCH 221/268] Properly handle empty filters --- noice.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index c72417f9..fa712ffa 100644 --- a/noice.c +++ b/noice.c @@ -331,10 +331,11 @@ readln(void) echo(); curs_set(TRUE); + memset(ln, 0, sizeof(ln)); getnstr(ln, sizeof(ln) - 1); noecho(); curs_set(FALSE); - return strdup(ln); + return strlen(ln) ? strdup(ln) : NULL; } /* From 9b47bfd9aa26c0dbc3ed63dd1960918359cf09b0 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 14:04:01 +0000 Subject: [PATCH 222/268] Use wgetnstr() instead of getnstr() because IRIX lacks the latter --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index fa712ffa..f44f8f90 100644 --- a/noice.c +++ b/noice.c @@ -332,7 +332,7 @@ readln(void) echo(); curs_set(TRUE); memset(ln, 0, sizeof(ln)); - getnstr(ln, sizeof(ln) - 1); + wgetnstr(stdscr, ln, sizeof(ln) - 1); noecho(); curs_set(FALSE); return strlen(ln) ? strdup(ln) : NULL; From ebaa637b0b30d7fa70fdd4ca61f8b1149e60e819 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 14:12:47 +0000 Subject: [PATCH 223/268] Sync strlcpy/strlcat from OpenBSD --- strlcat.c | 49 ++++++++++++++++++++++++++----------------------- strlcpy.c | 39 +++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/strlcat.c b/strlcat.c index 979c41bc..bc523fb2 100644 --- a/strlcat.c +++ b/strlcat.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998 Todd C. Miller + * Copyright (c) 1998, 2015 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,33 +20,36 @@ #include "util.h" /* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. + * Appends src to string dst of size dsize (unlike strncat, dsize is the + * full size of dst, not space left). At most dsize-1 characters + * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). + * Returns strlen(src) + MIN(dsize, strlen(initial dst)). + * If retval >= dsize, truncation occurred. */ size_t -strlcat(char *dst, const char *src, size_t siz) +strlcat(char *dst, const char *src, size_t dsize) { - char *d = dst; - const char *s = src; - size_t n = siz; + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; size_t dlen; - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; + + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; + + if (n-- == 0) + return(dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; n--; } - s++; + src++; } - *d = '\0'; - return(dlen + (s - src)); /* count does not include NUL */ + *dst = '\0'; + + return(dlen + (src - osrc)); /* count does not include NUL */ } diff --git a/strlcpy.c b/strlcpy.c index 7df8aa23..0ec2b787 100644 --- a/strlcpy.c +++ b/strlcpy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998 Todd C. Miller + * Copyright (c) 1998, 2015 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,32 +16,35 @@ #include #include + #include "util.h" /* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. */ size_t -strlcpy(char *dst, const char *src, size_t siz) +strlcpy(char *dst, const char *src, size_t dsize) { - char *d = dst; - const char *s = src; - size_t n = siz; - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*d++ = *s++) == '\0') + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') break; } } - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) ; } - return(s - src - 1); /* count does not include NUL */ + + return(src - osrc - 1); /* count does not include NUL */ } From 756b50be2760c840eeb4dd556b847dd296064ada Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 14:14:58 +0000 Subject: [PATCH 224/268] Restore screensaver mode Disable timeout when in filter or type mode. --- config.def.h | 2 ++ noice.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/config.def.h b/config.def.h index a3553331..80cb48c3 100644 --- a/config.def.h +++ b/config.def.h @@ -3,6 +3,8 @@ #define EMPTY " " int mtimeorder = 0; /* Set to 1 to sort by time in the default case */ +int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */ +char *idlecmd = "rain"; /* The screensaver program */ struct assoc assocs[] = { { "\\.(avi|mp4|mkv|mp3|ogg|flac|mov)$", "mplayer" }, diff --git a/noice.c b/noice.c index f44f8f90..12de74ac 100644 --- a/noice.c +++ b/noice.c @@ -82,6 +82,7 @@ struct entry *dents; int n, cur; char *path, *oldpath; char *fltr; +int idle; /* * Layout: @@ -259,6 +260,7 @@ initcurses(void) intrflush(stdscr, FALSE); keypad(stdscr, TRUE); curs_set(FALSE); /* Hide cursor */ + timeout(1000); /* One second */ } void @@ -314,6 +316,10 @@ nextsel(char **run) int c, i; c = getch(); + if (c == -1) + idle++; + else + idle = 0; for (i = 0; i < LEN(bindings); i++) if (c == bindings[i].sym) { @@ -329,12 +335,14 @@ readln(void) { char ln[LINE_MAX]; + timeout(-1); echo(); curs_set(TRUE); memset(ln, 0, sizeof(ln)); wgetnstr(stdscr, ln, sizeof(ln) - 1); noecho(); curs_set(FALSE); + timeout(1000); return strlen(ln) ? strdup(ln) : NULL; } @@ -349,6 +357,7 @@ readmore(char **str) int i; char *ln = *str; + timeout(-1); if (ln != NULL) i = strlen(ln); else @@ -384,6 +393,7 @@ readmore(char **str) curs_set(FALSE); *str = ln; + timeout(1000); return ret; } @@ -842,6 +852,13 @@ moretyping: initcurses(); break; } + /* Screensaver */ + if (idletimeout != 0 && idle == idletimeout) { + idle = 0; + exitcurses(); + spawn(idlecmd, NULL, NULL); + initcurses(); + } } } From 8c04bea678b1ab72a213580a6edf310fb2825f9d Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 14:36:40 +0000 Subject: [PATCH 225/268] Add license pointer --- config.def.h | 1 + noice.c | 1 + util.h | 1 + 3 files changed, 3 insertions(+) diff --git a/config.def.h b/config.def.h index 80cb48c3..39c17994 100644 --- a/config.def.h +++ b/config.def.h @@ -1,3 +1,4 @@ +/* See LICENSE file for copyright and license details. */ #define CWD "cwd: " #define CURSR " > " #define EMPTY " " diff --git a/noice.c b/noice.c index 12de74ac..9955a8d3 100644 --- a/noice.c +++ b/noice.c @@ -1,3 +1,4 @@ +/* See LICENSE file for copyright and license details. */ #include #include #include diff --git a/util.h b/util.h index b1540858..c4d1904b 100644 --- a/util.h +++ b/util.h @@ -1,3 +1,4 @@ +/* See LICENSE file for copyright and license details. */ #undef strlcat size_t strlcat(char *, const char *, size_t); #undef strlcpy From fccf6f0f96e28ea77b39868b05b92cf2f7d7e02a Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 14:37:27 +0000 Subject: [PATCH 226/268] The 2f30 lists were taken down so update README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 44edb931..b21c237a 100644 --- a/README +++ b/README @@ -59,4 +59,4 @@ Contact ======= To report bugs and/or submit patches, you can reach us through -the freenode IRC network at #2f30 or by subscribing to tech@lists.2f30.org. +the freenode IRC network at #2f30. From 252e8561ef124662be1c98f147e6a4ef345d7f28 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 14:59:41 +0000 Subject: [PATCH 227/268] Bump to 0.3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ea06b2d1..68064ff5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.2 +VERSION = 0.3 PREFIX = /usr/local MANPREFIX = $(PREFIX)/man From d1d086d91edd89e5a8edcc3349488b3ed89f8c9d Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 20 Nov 2015 17:41:11 +0000 Subject: [PATCH 228/268] No need for strlen() Thanks Hiltjo! --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 9955a8d3..63c7b6bd 100644 --- a/noice.c +++ b/noice.c @@ -344,7 +344,7 @@ readln(void) noecho(); curs_set(FALSE); timeout(1000); - return strlen(ln) ? strdup(ln) : NULL; + return ln[0] ? strdup(ln) : NULL; } /* From d1ed0cff118a07327b3b237ea65836f5c673acbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20K=C3=BChl?= Date: Fri, 20 Nov 2015 16:42:33 +0100 Subject: [PATCH 229/268] Support commands specified by environment variables Specifying commands by name in config.h means that every time one switches ones editor (for example), one has to modify every config.h file referencing that editor and then recompile every corresponding program. This change adds a string `env` for specifying an environment variable to `struct key` and uses it to optionally specify the command to run on SEL_{RUN,RUNARG}. The `run` string is used as a fallback when the environment variable has not been specified or is not set. It also updates `config.def.h` to demonstrate this new capability. --- config.def.h | 7 ++++--- noice.c | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/config.def.h b/config.def.h index 39c17994..beae17d3 100644 --- a/config.def.h +++ b/config.def.h @@ -62,8 +62,9 @@ struct key bindings[] = { { 't', SEL_MTIME }, { CONTROL('L'), SEL_REDRAW }, /* Run command */ - { '!', SEL_RUN, "sh" }, - { 'z', SEL_RUN, "top" }, + { 'z', SEL_RUN, "top" }, + { '!', SEL_RUN, "sh", "SHELL" }, /* Run command with argument */ - { 'e', SEL_RUNARG, "vi" }, + { 'e', SEL_RUNARG, "vi", "EDITOR" }, + { 'p', SEL_RUNARG, "less", "PAGER" }, }; diff --git a/noice.c b/noice.c index 63c7b6bd..8b278458 100644 --- a/noice.c +++ b/noice.c @@ -68,6 +68,7 @@ struct key { int sym; /* Key pressed */ enum action act; /* Action */ char *run; /* Program to run */ + char *env; /* Environment variable to run */ }; #include "config.h" @@ -194,6 +195,17 @@ spawn(const char *file, const char *arg, const char *dir) } } +char * +xgetenv(char *name, char *fallback) +{ + if (name == NULL) + return fallback; + char *value = getenv(name); + if (value) + return value; + return fallback; +} + char * openwith(char *file) { @@ -310,9 +322,9 @@ printprompt(char *str) } /* Returns SEL_* if key is bound and 0 otherwise - Also modifies the run pointer (used on SEL_{RUN,RUNARG}) */ + Also modifies the run and env pointers (used on SEL_{RUN,RUNARG}) */ int -nextsel(char **run) +nextsel(char **run, char **env) { int c, i; @@ -325,6 +337,7 @@ nextsel(char **run) for (i = 0; i < LEN(bindings); i++) if (c == bindings[i].sym) { *run = bindings[i].run; + *env = bindings[i].env; return bindings[i].act; } @@ -630,7 +643,7 @@ browse(const char *ipath, const char *ifilter) regex_t re; char *newpath; struct stat sb; - char *name, *bin, *dir, *tmp, *run; + char *name, *bin, *dir, *tmp, *run, *env; int nowtyping = 0; oldpath = NULL; @@ -653,7 +666,7 @@ begin: if (nowtyping) goto moretyping; nochange: - switch (nextsel(&run)) { + switch (nextsel(&run, &env)) { case SEL_QUIT: free(path); free(fltr); @@ -842,12 +855,14 @@ moretyping: oldpath = makepath(path, dents[cur].name); goto begin; case SEL_RUN: + run = xgetenv(env, run); exitcurses(); spawn(run, NULL, path); initcurses(); break; case SEL_RUNARG: name = dents[cur].name; + run = xgetenv(env, run); exitcurses(); spawn(run, name, path); initcurses(); From 7ceda4f7d2916c0123aacea8005fc39cd8c04d02 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 13:42:41 +0000 Subject: [PATCH 230/268] Declare var at top of block --- noice.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 8b278458..54a9455b 100644 --- a/noice.c +++ b/noice.c @@ -198,12 +198,12 @@ spawn(const char *file, const char *arg, const char *dir) char * xgetenv(char *name, char *fallback) { + char *value; + if (name == NULL) return fallback; - char *value = getenv(name); - if (value) - return value; - return fallback; + value = getenv(name); + return value ? value : fallback; } char * From c3707c749f6b800a21134ecf72acd47f1814d12f Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 13:45:20 +0000 Subject: [PATCH 231/268] Minor grammar fix in README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index b21c237a..793a6672 100644 --- a/README +++ b/README @@ -36,7 +36,7 @@ cases you just do: make It is known to work on OpenBSD, NetBSD, FreeBSD, DragonFly BSD, Linux, -IRIX 6.5, Haiku, Solaris 9. Some notes for building on certain systems +IRIX 6.5, Haiku and Solaris 9. Some notes for building on certain systems follow. * IRIX 6.5: From 016d59ad8e1a4fec51a3269544c6d001453fd601 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 13:51:09 +0000 Subject: [PATCH 232/268] Fix instructions for Solaris 9 --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 793a6672..bcd3267a 100644 --- a/README +++ b/README @@ -51,7 +51,7 @@ follow. * Solaris 9: Tested with gcc from http://www.opencsw.org/. - export PATH=/usr/ccs/bin:/opt/csw/bin + export PATH=/usr/ccs/bin:/opt/csw/bin:$PATH make CC="gcc" From 77b78caae86c8cd19f611c5f191fb755458710dc Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 15:03:26 +0000 Subject: [PATCH 233/268] Minor fixes for manpage --- noice.1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/noice.1 b/noice.1 index bba780b7..0762d443 100644 --- a/noice.1 +++ b/noice.1 @@ -1,4 +1,4 @@ -.Dd March 12, 2015 +.Dd November 26, 2015 .Dt NOICE 1 .Os .Sh NAME @@ -37,13 +37,13 @@ Move to next entry. Scroll up half a page. .It Ic [Pgdown] or C-d Scroll down half a page. -.It Ic [Home] or C-a or ^ +.It Ic [Home], ^ or C-a Move to the first entry. -.It Ic [End] or C-e or $ +.It Ic [End], $ or C-e Move to the last entry. .It Ic l, [Right], [Return] or C-m Open file or enter directory. -.It Ic h, [Left] or [Backspace] +.It Ic h, C-h, [Left] or [Backspace] Back up one directory level. .It Ic / or & Change filter (see below for more information). @@ -53,7 +53,7 @@ Enter filter-as-you-type mode. Change into the given directory. .It Ic t Toggle sort by time modified. -.It Ic l +.It Ic C-l Force a redraw. .It Ic \&! Spawn an sh shell in current directory. @@ -61,6 +61,8 @@ Spawn an sh shell in current directory. Run the system top utility. .It Ic e Open selected entry with the vi editor. +.It Ic p +Open selected entry with the less pager. .It Ic q Quit. .El @@ -97,6 +99,9 @@ If .Nm is invoked as root the default filter will also match hidden files. +.Sh ENVIRONMENT +The SHELL, EDITOR and PAGER environment variables take precedence +when dealing with the !, e and p commands respectively. .Sh EXAMPLES The following example shows one possible configuration for file associations which is also the default: From b77477d3777bc6ebd43875cd3e9b68d44cdb1bd3 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 15:05:16 +0000 Subject: [PATCH 234/268] Be consistent in manpage --- noice.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index 0762d443..e4cba0c2 100644 --- a/noice.1 +++ b/noice.1 @@ -82,7 +82,7 @@ is found the program .Xr less 1 is invoked. This is useful for editing text files as one can use the 'v' command in -.Xr less 1 to edit the file in $EDITOR. +.Xr less 1 to edit the file using the EDITOR environment variable. .Pp See the examples section below for more information. .Sh FILTERS From 16109053f59a944f75b3aab947bccea103974759 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 15:10:12 +0000 Subject: [PATCH 235/268] Only use the environment variable when it is not empty --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 54a9455b..dda028c1 100644 --- a/noice.c +++ b/noice.c @@ -203,7 +203,7 @@ xgetenv(char *name, char *fallback) if (name == NULL) return fallback; value = getenv(name); - return value ? value : fallback; + return value && value[0] ? value : fallback; } char * From 29701b48781ca01c8a9747c1baf196423e02081f Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 15:33:49 +0000 Subject: [PATCH 236/268] Rename makepath() to mkpath() --- noice.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/noice.c b/noice.c index dda028c1..09568dcc 100644 --- a/noice.c +++ b/noice.c @@ -106,7 +106,7 @@ int idle; void printmsg(char *msg); void printwarn(void); void printerr(int ret, char *prefix); -char *makepath(char *dir, char *name); +char *mkpath(char *dir, char *name); #undef dprintf int @@ -487,7 +487,7 @@ dentfill(char *path, struct entry **dents, *dents = xrealloc(*dents, (n + 1) * sizeof(**dents)); (*dents)[n].name = xstrdup(dp->d_name); /* Get mode flags */ - newpath = makepath(path, dp->d_name); + newpath = mkpath(path, dp->d_name); r = lstat(newpath, &sb); if (r == -1) printerr(1, "lstat"); @@ -515,7 +515,7 @@ dentfree(struct entry *dents, int n) } char * -makepath(char *dir, char *name) +mkpath(char *dir, char *name) { char path[PATH_MAX]; @@ -547,7 +547,7 @@ dentfind(struct entry *dents, int n, char *cwd, char *path) return 0; for (i = 0; i < n; i++) { - tmp = makepath(cwd, dents[i].name); + tmp = mkpath(cwd, dents[i].name); DPRINTF_S(path); DPRINTF_S(tmp); if (strcmp(tmp, path) == 0) { @@ -697,7 +697,7 @@ nochange: goto nochange; name = dents[cur].name; - newpath = makepath(path, name); + newpath = mkpath(path, name); DPRINTF_S(newpath); /* Get path info */ @@ -763,7 +763,7 @@ nochange: DPRINTF_S(fltr); /* Save current */ if (n > 0) - oldpath = makepath(path, dents[cur].name); + oldpath = mkpath(path, dents[cur].name); goto begin; case SEL_TYPE: nowtyping = 1; @@ -796,7 +796,7 @@ moretyping: fltr = xstrdup(ifilter); /* Save current */ if (n > 0) - oldpath = makepath(path, dents[cur].name); + oldpath = mkpath(path, dents[cur].name); if (!nowtyping) free(tmp); goto begin; @@ -830,7 +830,7 @@ moretyping: clearprompt(); goto nochange; } - newpath = makepath(path, tmp); + newpath = mkpath(path, tmp); free(tmp); if (canopendir(newpath) == 0) { free(newpath); @@ -847,12 +847,12 @@ moretyping: mtimeorder = !mtimeorder; /* Save current */ if (n > 0) - oldpath = makepath(path, dents[cur].name); + oldpath = mkpath(path, dents[cur].name); goto begin; case SEL_REDRAW: /* Save current */ if (n > 0) - oldpath = makepath(path, dents[cur].name); + oldpath = mkpath(path, dents[cur].name); goto begin; case SEL_RUN: run = xgetenv(env, run); From 4abc9f0b4601b530cf3d5aaefa1f745eb958680c Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 15:35:53 +0000 Subject: [PATCH 237/268] Don't name vars in prototypes --- noice.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noice.c b/noice.c index 09568dcc..60423e77 100644 --- a/noice.c +++ b/noice.c @@ -103,10 +103,10 @@ int idle; * '------ */ -void printmsg(char *msg); +void printmsg(char *); void printwarn(void); -void printerr(int ret, char *prefix); -char *mkpath(char *dir, char *name); +void printerr(int, char *); +char *mkpath(char *, char *); #undef dprintf int From 013bcdee35b54fd7be928e8b57e9c659d325fff3 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 15:54:54 +0000 Subject: [PATCH 238/268] Don't use printerr() before curses has been initialized --- noice.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index 60423e77..38604dc7 100644 --- a/noice.c +++ b/noice.c @@ -885,8 +885,10 @@ main(int argc, char *argv[]) char *ifilter; /* Confirm we are in a terminal */ - if (!isatty(STDIN_FILENO)) - printerr(1, "isatty"); + if (!isatty(0) || !isatty(1)) { + fprintf(stderr, "stdin or stdout is not a tty\n"); + exit(1); + } if (getuid() == 0) ifilter = "."; @@ -904,8 +906,10 @@ main(int argc, char *argv[]) signal(SIGINT, SIG_IGN); /* Test initial path */ - if (canopendir(ipath) == 0) - printerr(1, ipath); + if (canopendir(ipath) == 0) { + fprintf(stderr, "%s: %s\n", ipath, strerror(errno)); + exit(1); + } /* Set locale before curses setup */ setlocale(LC_ALL, ""); @@ -916,5 +920,5 @@ main(int argc, char *argv[]) exitcurses(); - return 0; + exit(0); } From 71ece08aad38de2e938d7f378b00ef8360922336 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 16:00:26 +0000 Subject: [PATCH 239/268] Add usage --- noice.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/noice.c b/noice.c index 38604dc7..9f4f0cb0 100644 --- a/noice.c +++ b/noice.c @@ -878,12 +878,22 @@ moretyping: } } +void +usage(char *argv0) +{ + fprintf(stderr, "usage: %s [dir]\n", argv0); + exit(1); +} + int main(int argc, char *argv[]) { char cwd[PATH_MAX], *ipath; char *ifilter; + if (argc > 2) + usage(argv[0]); + /* Confirm we are in a terminal */ if (!isatty(0) || !isatty(1)) { fprintf(stderr, "stdin or stdout is not a tty\n"); From 2d87145fa23f582baf9d057a295a007e5c0a873b Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 26 Nov 2015 16:05:13 +0000 Subject: [PATCH 240/268] Fix comment --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index beae17d3..4b128468 100644 --- a/config.def.h +++ b/config.def.h @@ -3,7 +3,7 @@ #define CURSR " > " #define EMPTY " " -int mtimeorder = 0; /* Set to 1 to sort by time in the default case */ +int mtimeorder = 0; /* Set to 1 to sort by time modified */ int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */ char *idlecmd = "rain"; /* The screensaver program */ From a7152012558006b0f0ffca633c8c90ff4ce9726d Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 6 Jan 2016 15:21:41 +0000 Subject: [PATCH 241/268] Print the resolved path for cwd Avoids weird things like /etc/.. when displaying cwd. Also no need for cwd to be on the heap. --- noice.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index 9f4f0cb0..41172409 100644 --- a/noice.c +++ b/noice.c @@ -595,8 +595,9 @@ populate(void) void redraw(void) { + char cwd[PATH_MAX], cwdresolved[PATH_MAX]; + size_t ncols; int nlines, odd; - char *cwd; int i; nlines = MIN(LINES - 4, n); @@ -615,11 +616,14 @@ redraw(void) DPRINTF_S(path); /* No text wrapping in cwd line */ - cwd = xmalloc(COLS * sizeof(char)); - strlcpy(cwd, path, COLS * sizeof(char)); - cwd[COLS - strlen(CWD) - 1] = '\0'; + ncols = COLS; + if (ncols > PATH_MAX) + ncols = PATH_MAX; + strlcpy(cwd, path, ncols); + cwd[ncols - strlen(CWD) - 1] = '\0'; + realpath(cwd, cwdresolved); - printw(CWD "%s\n\n", cwd); + printw(CWD "%s\n\n", cwdresolved); /* Print listing */ odd = ISODD(nlines); From e27af6f1dbc804e90a3b98f19afdf1055bab8dc9 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 6 Jan 2016 15:24:35 +0000 Subject: [PATCH 242/268] sizeof(char) is always 1, no need to be explicit --- noice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 41172409..ada28fcb 100644 --- a/noice.c +++ b/noice.c @@ -235,8 +235,8 @@ setfilter(regex_t *regex, char *filter) r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED | REG_ICASE); if (r != 0) { - errbuf = xmalloc(COLS * sizeof(char)); - regerror(r, regex, errbuf, COLS * sizeof(char)); + errbuf = xmalloc(COLS); + regerror(r, regex, errbuf, COLS); printmsg(errbuf); free(errbuf); } From fa6b45a96de53621d4e89bd63ee810210712f043 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 6 Jan 2016 15:53:04 +0000 Subject: [PATCH 243/268] Avoid unneeded memory allocation in xdirname() --- noice.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/noice.c b/noice.c index ada28fcb..50674243 100644 --- a/noice.c +++ b/noice.c @@ -158,21 +158,17 @@ xstrdup(const char *s) char * xdirname(const char *path) { - char *p, *tmp; + char tmp[PATH_MAX], *p; /* Some implementations of dirname(3) may modify `path' and some * return a pointer inside `path' and we cannot free(3) the * original string if we lose track of it. */ - tmp = xstrdup(path); + strlcpy(tmp, path, sizeof(tmp)); p = dirname(tmp); - if (p == NULL) { - free(tmp); + if (p == NULL) printerr(1, "dirname"); - } /* Make sure this is a malloc(3)-ed string */ - p = xstrdup(p); - free(tmp); - return p; + return xstrdup(p); } void From 5fb5e9f82f89a2a9257bd375dfb8d065c5afa7bb Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 6 Jan 2016 15:55:25 +0000 Subject: [PATCH 244/268] Avoid another allocation --- noice.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 50674243..d1b2c919 100644 --- a/noice.c +++ b/noice.c @@ -423,12 +423,12 @@ canopendir(char *path) void printent(struct entry *ent, int active) { - char *name; + char name[PATH_MAX]; unsigned int maxlen = COLS - strlen(CURSR) - 1; char cm = 0; /* Copy name locally */ - name = xstrdup(ent->name); + strlcpy(name, ent->name, sizeof(name)); if (S_ISDIR(ent->mode)) { cm = '/'; @@ -455,8 +455,6 @@ printent(struct entry *ent, int active) printw("%s%s\n", active ? CURSR : EMPTY, name); else printw("%s%s%c\n", active ? CURSR : EMPTY, name, cm); - - free(name); } int From 6d4166f0d6b67bbaecb57cdf821d28f4356ae67f Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 6 Jan 2016 15:59:27 +0000 Subject: [PATCH 245/268] Fix memory leak --- noice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/noice.c b/noice.c index d1b2c919..b0321355 100644 --- a/noice.c +++ b/noice.c @@ -485,6 +485,7 @@ dentfill(char *path, struct entry **dents, r = lstat(newpath, &sb); if (r == -1) printerr(1, "lstat"); + free(newpath); (*dents)[n].mode = sb.st_mode; (*dents)[n].t = sb.st_mtime; n++; From 65fae61bea713e004b7698cb424fa2a24847b40d Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 7 Jan 2016 10:26:44 +0000 Subject: [PATCH 246/268] noice: No need to perform so many memory allocations The code was quite fragile. As a first pass, use buffers of size PATH_MAX and LINE_MAX accordingly until we simplify the overall logic. --- noice.c | 140 ++++++++++++++++++++++---------------------------------- 1 file changed, 55 insertions(+), 85 deletions(-) diff --git a/noice.c b/noice.c index b0321355..6194062c 100644 --- a/noice.c +++ b/noice.c @@ -74,7 +74,7 @@ struct key { #include "config.h" struct entry { - char *name; + char name[PATH_MAX]; mode_t mode; time_t t; }; @@ -82,8 +82,8 @@ struct entry { /* Global context */ struct entry *dents; int n, cur; -char *path, *oldpath; -char *fltr; +char path[PATH_MAX], oldpath[PATH_MAX]; +char fltr[LINE_MAX]; int idle; /* @@ -106,7 +106,7 @@ int idle; void printmsg(char *); void printwarn(void); void printerr(int, char *); -char *mkpath(char *, char *); +char *mkpath(char *, char *, char *, size_t); #undef dprintf int @@ -155,20 +155,20 @@ xstrdup(const char *s) return p; } +/* Some implementations of dirname(3) may modify `path' and some + * return a pointer inside `path'. */ char * xdirname(const char *path) { + static char out[PATH_MAX]; char tmp[PATH_MAX], *p; - /* Some implementations of dirname(3) may modify `path' and some - * return a pointer inside `path' and we cannot free(3) the - * original string if we lose track of it. */ strlcpy(tmp, path, sizeof(tmp)); p = dirname(tmp); if (p == NULL) printerr(1, "dirname"); - /* Make sure this is a malloc(3)-ed string */ - return xstrdup(p); + strlcpy(out, p, sizeof(out)); + return out; } void @@ -226,15 +226,17 @@ openwith(char *file) int setfilter(regex_t *regex, char *filter) { - char *errbuf; + char errbuf[LINE_MAX]; + size_t len; int r; r = regcomp(regex, filter, REG_NOSUB | REG_EXTENDED | REG_ICASE); if (r != 0) { - errbuf = xmalloc(COLS); - regerror(r, regex, errbuf, COLS); + len = COLS; + if (len > sizeof(errbuf)) + len = sizeof(errbuf); + regerror(r, regex, errbuf, len); printmsg(errbuf); - free(errbuf); } return r; @@ -461,10 +463,10 @@ int dentfill(char *path, struct entry **dents, int (*filter)(regex_t *, char *), regex_t *re) { + char newpath[PATH_MAX]; DIR *dirp; struct dirent *dp; struct stat sb; - char *newpath; int r, n = 0; dirp = opendir(path); @@ -479,13 +481,12 @@ dentfill(char *path, struct entry **dents, if (filter(re, dp->d_name) == 0) continue; *dents = xrealloc(*dents, (n + 1) * sizeof(**dents)); - (*dents)[n].name = xstrdup(dp->d_name); + strlcpy((*dents)[n].name, dp->d_name, sizeof((*dents)[n].name)); /* Get mode flags */ - newpath = mkpath(path, dp->d_name); + mkpath(path, dp->d_name, newpath, sizeof(newpath)); r = lstat(newpath, &sb); if (r == -1) printerr(1, "lstat"); - free(newpath); (*dents)[n].mode = sb.st_mode; (*dents)[n].t = sb.st_mtime; n++; @@ -500,58 +501,47 @@ dentfill(char *path, struct entry **dents, } void -dentfree(struct entry *dents, int n) +dentfree(struct entry *dents) { - int i; - - for (i = 0; i < n; i++) - free(dents[i].name); free(dents); } char * -mkpath(char *dir, char *name) +mkpath(char *dir, char *name, char *out, size_t n) { - char path[PATH_MAX]; - /* Handle absolute path */ if (name[0] == '/') { - strlcpy(path, name, sizeof(path)); + strlcpy(out, name, n); } else { /* Handle root case */ if (strcmp(dir, "/") == 0) { - strlcpy(path, "/", sizeof(path)); - strlcat(path, name, sizeof(path)); + strlcpy(out, "/", n); + strlcat(out, name, n); } else { - strlcpy(path, dir, sizeof(path)); - strlcat(path, "/", sizeof(path)); - strlcat(path, name, sizeof(path)); + strlcpy(out, dir, n); + strlcat(out, "/", n); + strlcat(out, name, n); } } - return xstrdup(path); + return out; } /* Return the position of the matching entry or 0 otherwise */ int dentfind(struct entry *dents, int n, char *cwd, char *path) { + char tmp[PATH_MAX]; int i; - char *tmp; if (path == NULL) return 0; - for (i = 0; i < n; i++) { - tmp = mkpath(cwd, dents[i].name); + mkpath(cwd, dents[i].name, tmp, sizeof(tmp)); DPRINTF_S(path); DPRINTF_S(tmp); - if (strcmp(tmp, path) == 0) { - free(tmp); + if (strcmp(tmp, path) == 0) return i; - } - free(tmp); } - return 0; } @@ -570,7 +560,7 @@ populate(void) if (r != 0) return -1; - dentfree(dents, n); + dentfree(dents); n = 0; dents = NULL; @@ -581,9 +571,6 @@ populate(void) /* Find cur from history */ cur = dentfind(dents, n, path, oldpath); - free(oldpath); - oldpath = NULL; - return 0; } @@ -638,18 +625,16 @@ redraw(void) void browse(const char *ipath, const char *ifilter) { - int r, fd; - regex_t re; - char *newpath; - struct stat sb; + char newpath[PATH_MAX]; char *name, *bin, *dir, *tmp, *run, *env; + struct stat sb; + regex_t re; + int r, fd; int nowtyping = 0; - oldpath = NULL; - path = xstrdup(ipath); - fltr = xstrdup(ifilter); + strlcpy(path, ipath, sizeof(path)); + strlcpy(fltr, ifilter, sizeof(fltr)); begin: - /* Path and filter should be malloc(3)-ed strings at all times */ r = populate(); if (r == -1) { if (!nowtyping) { @@ -667,9 +652,7 @@ begin: nochange: switch (nextsel(&run, &env)) { case SEL_QUIT: - free(path); - free(fltr); - dentfree(dents, n); + dentfree(dents); return; case SEL_BACK: /* There is no going back */ @@ -679,16 +662,14 @@ nochange: goto nochange; dir = xdirname(path); if (canopendir(dir) == 0) { - free(dir); printwarn(); goto nochange; } /* Save history */ - oldpath = path; - path = dir; + strlcpy(oldpath, path, sizeof(path)); + strlcpy(path, dir, sizeof(path)); /* Reset filter */ - free(fltr); - fltr = xstrdup(ifilter); + strlcpy(fltr, ifilter, sizeof(fltr)); goto begin; case SEL_GOIN: /* Cannot descend in empty directories */ @@ -696,21 +677,19 @@ nochange: goto nochange; name = dents[cur].name; - newpath = mkpath(path, name); + mkpath(path, name, newpath, sizeof(newpath)); DPRINTF_S(newpath); /* Get path info */ fd = open(newpath, O_RDONLY | O_NONBLOCK); if (fd == -1) { printwarn(); - free(newpath); goto nochange; } r = fstat(fd, &sb); if (r == -1) { printwarn(); close(fd); - free(newpath); goto nochange; } close(fd); @@ -720,26 +699,21 @@ nochange: case S_IFDIR: if (canopendir(newpath) == 0) { printwarn(); - free(newpath); goto nochange; } - free(path); - path = newpath; + strlcpy(path, newpath, sizeof(path)); /* Reset filter */ - free(fltr); - fltr = xstrdup(ifilter); + strlcpy(fltr, ifilter, sizeof(fltr)); goto begin; case S_IFREG: bin = openwith(newpath); if (bin == NULL) { printmsg("No association"); - free(newpath); goto nochange; } exitcurses(); spawn(bin, newpath, NULL); initcurses(); - free(newpath); continue; default: printmsg("Unsupported file"); @@ -757,12 +731,11 @@ nochange: free(tmp); goto nochange; } - free(fltr); - fltr = tmp; + strlcpy(fltr, tmp, sizeof(fltr)); DPRINTF_S(fltr); /* Save current */ if (n > 0) - oldpath = mkpath(path, dents[cur].name); + mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; case SEL_TYPE: nowtyping = 1; @@ -788,14 +761,13 @@ moretyping: } } /* Copy or reset filter */ - free(fltr); if (tmp != NULL) - fltr = xstrdup(tmp); + strlcpy(fltr, tmp, sizeof(fltr)); else - fltr = xstrdup(ifilter); + strlcpy(fltr, ifilter, sizeof(fltr)); /* Save current */ if (n > 0) - oldpath = mkpath(path, dents[cur].name); + mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); if (!nowtyping) free(tmp); goto begin; @@ -829,29 +801,27 @@ moretyping: clearprompt(); goto nochange; } - newpath = mkpath(path, tmp); + mkpath(path, tmp, newpath, sizeof(newpath)); free(tmp); if (canopendir(newpath) == 0) { - free(newpath); printwarn(); goto nochange; } - free(path); - path = newpath; - free(fltr); - fltr = xstrdup(ifilter); /* Reset filter */ + strlcpy(path, newpath, sizeof(path)); + /* Reset filter */ + strlcpy(fltr, ifilter, sizeof(fltr)) DPRINTF_S(path); goto begin; case SEL_MTIME: mtimeorder = !mtimeorder; /* Save current */ if (n > 0) - oldpath = mkpath(path, dents[cur].name); + mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; case SEL_REDRAW: /* Save current */ if (n > 0) - oldpath = mkpath(path, dents[cur].name); + mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; case SEL_RUN: run = xgetenv(env, run); From 05f6e92a17129e6daa4ec5972640ff82677c717e Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 13 Jan 2016 18:52:19 +0000 Subject: [PATCH 247/268] Year bump --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 1f62a516..3379649d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2014-2015 Lazaros Koromilas -Copyright (c) 2014-2015 Dimitris Papastamos +Copyright (c) 2014-2016 Lazaros Koromilas +Copyright (c) 2014-2016 Dimitris Papastamos All rights reserved. Redistribution and use in source and binary forms, with or without From 98e06fc7399661c89b1eebdba0bcbb22ff706334 Mon Sep 17 00:00:00 2001 From: sin Date: Tue, 26 Jan 2016 20:07:29 +0000 Subject: [PATCH 248/268] Bump to 0.4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 68064ff5..98528571 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.3 +VERSION = 0.4 PREFIX = /usr/local MANPREFIX = $(PREFIX)/man From d909de605c133037b72b4cfbcd34e83b130aa55c Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 16:44:39 +0000 Subject: [PATCH 249/268] No need for cast in qsort callback --- noice.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/noice.c b/noice.c index 6194062c..d1b3b82f 100644 --- a/noice.c +++ b/noice.c @@ -251,10 +251,7 @@ visible(regex_t *regex, char *file) int entrycmp(const void *va, const void *vb) { - const struct entry *a, *b; - - a = (struct entry *)va; - b = (struct entry *)vb; + const struct entry *a = va, *b = vb; if (mtimeorder) return b->t - a->t; From 9f6d1cfb334d7268608e04379400ce8bbe0429c9 Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 16:52:07 +0000 Subject: [PATCH 250/268] Remove filter as you type mode Nobody uses it and adds additional complexity. --- config.def.h | 2 -- noice.1 | 2 -- noice.c | 98 ++-------------------------------------------------- 3 files changed, 2 insertions(+), 100 deletions(-) diff --git a/config.def.h b/config.def.h index 4b128468..e1368dc0 100644 --- a/config.def.h +++ b/config.def.h @@ -32,8 +32,6 @@ struct key bindings[] = { /* Filter */ { '/', SEL_FLTR }, { '&', SEL_FLTR }, - /* Filter as you type */ - { '?', SEL_TYPE }, /* Next */ { 'j', SEL_NEXT }, { KEY_DOWN, SEL_NEXT }, diff --git a/noice.1 b/noice.1 index e4cba0c2..c23cb9aa 100644 --- a/noice.1 +++ b/noice.1 @@ -47,8 +47,6 @@ Open file or enter directory. Back up one directory level. .It Ic / or & Change filter (see below for more information). -.It Ic \&? -Enter filter-as-you-type mode. .It Ic c Change into the given directory. .It Ic t diff --git a/noice.c b/noice.c index d1b3b82f..2b000adf 100644 --- a/noice.c +++ b/noice.c @@ -50,7 +50,6 @@ enum action { SEL_BACK, SEL_GOIN, SEL_FLTR, - SEL_TYPE, SEL_NEXT, SEL_PREV, SEL_PGDN, @@ -355,58 +354,6 @@ readln(void) return ln[0] ? strdup(ln) : NULL; } -/* - * Read one key and modify the provided string accordingly. - * Returns 0 when more input is expected and 1 on completion. - */ -int -readmore(char **str) -{ - int c, ret = 0; - int i; - char *ln = *str; - - timeout(-1); - if (ln != NULL) - i = strlen(ln); - else - i = 0; - DPRINTF_D(i); - - curs_set(TRUE); - - c = getch(); - switch (c) { - case KEY_ENTER: - case '\r': - ret = 1; - break; - case KEY_BACKSPACE: - case CONTROL('H'): - i--; - if (i > 0) { - ln = xrealloc(ln, (i + 1) * sizeof(*ln)); - ln[i] = '\0'; - } else { - free(ln); - ln = NULL; - } - break; - default: - i++; - ln = xrealloc(ln, (i + 1) * sizeof(*ln)); - ln[i - 1] = c; - ln[i] = '\0'; - } - - curs_set(FALSE); - - *str = ln; - timeout(1000); - - return ret; -} - int canopendir(char *path) { @@ -627,25 +574,18 @@ browse(const char *ipath, const char *ifilter) struct stat sb; regex_t re; int r, fd; - int nowtyping = 0; strlcpy(path, ipath, sizeof(path)); strlcpy(fltr, ifilter, sizeof(fltr)); begin: r = populate(); if (r == -1) { - if (!nowtyping) { - printwarn(); - goto nochange; - } + printwarn(); + goto nochange; } for (;;) { redraw(); - - /* Handle filter-as-you-type mode */ - if (nowtyping) - goto moretyping; nochange: switch (nextsel(&run, &env)) { case SEL_QUIT: @@ -734,40 +674,6 @@ nochange: if (n > 0) mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; - case SEL_TYPE: - nowtyping = 1; - tmp = NULL; -moretyping: - printprompt("type: "); - if (tmp != NULL) - printw("%s", tmp); - r = readmore(&tmp); - DPRINTF_D(r); - DPRINTF_S(tmp); - if (r == 1) - nowtyping = 0; - /* Check regex errors */ - if (tmp != NULL) { - r = setfilter(&re, tmp); - if (r != 0) - if (nowtyping) { - goto moretyping; - } else { - free(tmp); - goto nochange; - } - } - /* Copy or reset filter */ - if (tmp != NULL) - strlcpy(fltr, tmp, sizeof(fltr)); - else - strlcpy(fltr, ifilter, sizeof(fltr)); - /* Save current */ - if (n > 0) - mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); - if (!nowtyping) - free(tmp); - goto begin; case SEL_NEXT: if (cur < n - 1) cur++; From 35ca388e9d12db68f3e6a566b051a968489dea8e Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 16:57:56 +0000 Subject: [PATCH 251/268] Remove some more useless memory allocations --- noice.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/noice.c b/noice.c index 2b000adf..fa773b0b 100644 --- a/noice.c +++ b/noice.c @@ -341,7 +341,7 @@ nextsel(char **run, char **env) char * readln(void) { - char ln[LINE_MAX]; + static char ln[LINE_MAX]; timeout(-1); echo(); @@ -351,7 +351,7 @@ readln(void) noecho(); curs_set(FALSE); timeout(1000); - return ln[0] ? strdup(ln) : NULL; + return ln[0] ? ln : NULL; } int @@ -567,7 +567,7 @@ redraw(void) } void -browse(const char *ipath, const char *ifilter) +browse(char *ipath, char *ifilter) { char newpath[PATH_MAX]; char *name, *bin, *dir, *tmp, *run, *env; @@ -661,13 +661,11 @@ nochange: printprompt("filter: "); tmp = readln(); if (tmp == NULL) - tmp = xstrdup(ifilter); + tmp = ifilter; /* Check and report regex errors */ r = setfilter(&re, tmp); - if (r != 0) { - free(tmp); + if (r != 0) goto nochange; - } strlcpy(fltr, tmp, sizeof(fltr)); DPRINTF_S(fltr); /* Save current */ @@ -705,7 +703,6 @@ nochange: goto nochange; } mkpath(path, tmp, newpath, sizeof(newpath)); - free(tmp); if (canopendir(newpath) == 0) { printwarn(); goto nochange; From 9af81fdc653558a6bc69da5209136c1a1dc46b74 Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 16:59:19 +0000 Subject: [PATCH 252/268] Remove some const bullshit --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index fa773b0b..2f58ffba 100644 --- a/noice.c +++ b/noice.c @@ -171,7 +171,7 @@ xdirname(const char *path) } void -spawn(const char *file, const char *arg, const char *dir) +spawn(char *file, char *arg, char *dir) { pid_t pid; int status; From c27f605a62c33f79563ea2271b60df083ae530c8 Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 17:08:26 +0000 Subject: [PATCH 253/268] Nuke some newlines --- noice.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/noice.c b/noice.c index 2f58ffba..5249ca9f 100644 --- a/noice.c +++ b/noice.c @@ -792,12 +792,8 @@ main(int argc, char *argv[]) /* Set locale before curses setup */ setlocale(LC_ALL, ""); - initcurses(); - browse(ipath, ifilter); - exitcurses(); - exit(0); } From 78461b8a06b35509f91173fa9fe5ff78b2f645d8 Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 17:22:30 +0000 Subject: [PATCH 254/268] Minor style fix --- noice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 5249ca9f..a95d8fff 100644 --- a/noice.c +++ b/noice.c @@ -315,8 +315,8 @@ printprompt(char *str) printw(str); } -/* Returns SEL_* if key is bound and 0 otherwise - Also modifies the run and env pointers (used on SEL_{RUN,RUNARG}) */ +/* Returns SEL_* if key is bound and 0 otherwise. + * Also modifies the run and env pointers (used on SEL_{RUN,RUNARG}) */ int nextsel(char **run, char **env) { From 43aebe099812bcce3e0b223d1ec8f50141351b3f Mon Sep 17 00:00:00 2001 From: sin Date: Mon, 8 Feb 2016 17:25:35 +0000 Subject: [PATCH 255/268] Minor README update --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index bcd3267a..eff4230f 100644 --- a/README +++ b/README @@ -11,8 +11,8 @@ What is it? =========== -noice is a small ncurses-based file browser. -It was first developed to be used with a tv remote control for a media +noice is a small curses-based file browser. +It was first developed to be used with a TV remote control for a media center solution. From 414ea845bbd4eac43dada7dc97f45556e1f8a060 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 10 Feb 2016 15:09:04 +0000 Subject: [PATCH 256/268] Use dents name directly like we do in other places --- noice.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/noice.c b/noice.c index a95d8fff..44317739 100644 --- a/noice.c +++ b/noice.c @@ -570,7 +570,7 @@ void browse(char *ipath, char *ifilter) { char newpath[PATH_MAX]; - char *name, *bin, *dir, *tmp, *run, *env; + char *bin, *dir, *tmp, *run, *env; struct stat sb; regex_t re; int r, fd; @@ -613,8 +613,7 @@ nochange: if (n == 0) goto nochange; - name = dents[cur].name; - mkpath(path, name, newpath, sizeof(newpath)); + mkpath(path, dents[cur].name, newpath, sizeof(newpath)); DPRINTF_S(newpath); /* Get path info */ @@ -730,10 +729,9 @@ nochange: initcurses(); break; case SEL_RUNARG: - name = dents[cur].name; run = xgetenv(env, run); exitcurses(); - spawn(run, name, path); + spawn(run, dents[cur].name, path); initcurses(); break; } From 872a0f462053ce3083a0f2d0d3210bcad2fc1d1a Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 10 Feb 2016 15:16:19 +0000 Subject: [PATCH 257/268] Rename global `n` to `ndents` This is more descriptive for a global variable which can easily be shadowed. --- noice.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/noice.c b/noice.c index 44317739..7955c73e 100644 --- a/noice.c +++ b/noice.c @@ -80,7 +80,7 @@ struct entry { /* Global context */ struct entry *dents; -int n, cur; +int ndents, cur; char path[PATH_MAX], oldpath[PATH_MAX]; char fltr[LINE_MAX]; int idle; @@ -506,15 +506,15 @@ populate(void) dentfree(dents); - n = 0; + ndents = 0; dents = NULL; - n = dentfill(path, &dents, visible, &re); + ndents = dentfill(path, &dents, visible, &re); - qsort(dents, n, sizeof(*dents), entrycmp); + qsort(dents, ndents, sizeof(*dents), entrycmp); /* Find cur from history */ - cur = dentfind(dents, n, path, oldpath); + cur = dentfind(dents, ndents, path, oldpath); return 0; } @@ -526,7 +526,7 @@ redraw(void) int nlines, odd; int i; - nlines = MIN(LINES - 4, n); + nlines = MIN(LINES - 4, ndents); /* Clean screen */ erase(); @@ -556,8 +556,8 @@ redraw(void) if (cur < nlines / 2) { for (i = 0; i < nlines; i++) printent(&dents[i], i == cur); - } else if (cur >= n - nlines / 2) { - for (i = n - nlines; i < n; i++) + } else if (cur >= ndents - nlines / 2) { + for (i = ndents - nlines; i < ndents; i++) printent(&dents[i], i == cur); } else { for (i = cur - nlines / 2; @@ -610,7 +610,7 @@ nochange: goto begin; case SEL_GOIN: /* Cannot descend in empty directories */ - if (n == 0) + if (ndents == 0) goto nochange; mkpath(path, dents[cur].name, newpath, sizeof(newpath)); @@ -668,11 +668,11 @@ nochange: strlcpy(fltr, tmp, sizeof(fltr)); DPRINTF_S(fltr); /* Save current */ - if (n > 0) + if (ndents > 0) mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; case SEL_NEXT: - if (cur < n - 1) + if (cur < ndents - 1) cur++; break; case SEL_PREV: @@ -680,8 +680,8 @@ nochange: cur--; break; case SEL_PGDN: - if (cur < n - 1) - cur += MIN((LINES - 4) / 2, n - 1 - cur); + if (cur < ndents - 1) + cur += MIN((LINES - 4) / 2, ndents - 1 - cur); break; case SEL_PGUP: if (cur > 0) @@ -691,7 +691,7 @@ nochange: cur = 0; break; case SEL_END: - cur = n - 1; + cur = ndents - 1; break; case SEL_CD: /* Read target dir */ @@ -714,12 +714,12 @@ nochange: case SEL_MTIME: mtimeorder = !mtimeorder; /* Save current */ - if (n > 0) + if (ndents > 0) mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; case SEL_REDRAW: /* Save current */ - if (n > 0) + if (ndents > 0) mkpath(path, dents[cur].name, oldpath, sizeof(oldpath)); goto begin; case SEL_RUN: From 5456b8a36a4bac19968ba39ba25d04981a4eee79 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 10 Feb 2016 15:20:28 +0000 Subject: [PATCH 258/268] Minor style fix --- noice.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/noice.c b/noice.c index 7955c73e..632cef3a 100644 --- a/noice.c +++ b/noice.c @@ -218,7 +218,6 @@ openwith(char *file) } } DPRINTF_S(bin); - return bin; } @@ -237,7 +236,6 @@ setfilter(regex_t *regex, char *filter) regerror(r, regex, errbuf, len); printmsg(errbuf); } - return r; } @@ -334,7 +332,6 @@ nextsel(char **run, char **env) *env = bindings[i].env; return bindings[i].act; } - return 0; } @@ -440,7 +437,6 @@ dentfill(char *path, struct entry **dents, r = closedir(dirp); if (r == -1) printerr(1, "closedir"); - return n; } From 5629b4911354876c9b88fe668bd4b17382c79f75 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 10 Feb 2016 15:32:41 +0000 Subject: [PATCH 259/268] Move path[], oldpath[] and fltr[] inside browse() --- noice.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/noice.c b/noice.c index 632cef3a..7f2f8733 100644 --- a/noice.c +++ b/noice.c @@ -81,8 +81,6 @@ struct entry { /* Global context */ struct entry *dents; int ndents, cur; -char path[PATH_MAX], oldpath[PATH_MAX]; -char fltr[LINE_MAX]; int idle; /* @@ -486,7 +484,7 @@ dentfind(struct entry *dents, int n, char *cwd, char *path) } int -populate(void) +populate(char *path, char *oldpath, char *fltr) { regex_t re; int r; @@ -515,7 +513,7 @@ populate(void) } void -redraw(void) +redraw(char *path) { char cwd[PATH_MAX], cwdresolved[PATH_MAX]; size_t ncols; @@ -565,7 +563,8 @@ redraw(void) void browse(char *ipath, char *ifilter) { - char newpath[PATH_MAX]; + char path[PATH_MAX], oldpath[PATH_MAX], newpath[PATH_MAX]; + char fltr[LINE_MAX]; char *bin, *dir, *tmp, *run, *env; struct stat sb; regex_t re; @@ -573,15 +572,16 @@ browse(char *ipath, char *ifilter) strlcpy(path, ipath, sizeof(path)); strlcpy(fltr, ifilter, sizeof(fltr)); + oldpath[0] = '\0'; begin: - r = populate(); + r = populate(path, oldpath, fltr); if (r == -1) { printwarn(); goto nochange; } for (;;) { - redraw(); + redraw(path); nochange: switch (nextsel(&run, &env)) { case SEL_QUIT: From afc065206727ac56ec781becb20ecb573c15c625 Mon Sep 17 00:00:00 2001 From: sin Date: Wed, 10 Feb 2016 15:38:22 +0000 Subject: [PATCH 260/268] Move mkpath() higher up so we don't need to declare it --- noice.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/noice.c b/noice.c index 7f2f8733..4d032d37 100644 --- a/noice.c +++ b/noice.c @@ -103,7 +103,6 @@ int idle; void printmsg(char *); void printwarn(void); void printerr(int, char *); -char *mkpath(char *, char *, char *, size_t); #undef dprintf int @@ -361,6 +360,26 @@ canopendir(char *path) return 1; } +char * +mkpath(char *dir, char *name, char *out, size_t n) +{ + /* Handle absolute path */ + if (name[0] == '/') { + strlcpy(out, name, n); + } else { + /* Handle root case */ + if (strcmp(dir, "/") == 0) { + strlcpy(out, "/", n); + strlcat(out, name, n); + } else { + strlcpy(out, dir, n); + strlcat(out, "/", n); + strlcat(out, name, n); + } + } + return out; +} + void printent(struct entry *ent, int active) { @@ -444,26 +463,6 @@ dentfree(struct entry *dents) free(dents); } -char * -mkpath(char *dir, char *name, char *out, size_t n) -{ - /* Handle absolute path */ - if (name[0] == '/') { - strlcpy(out, name, n); - } else { - /* Handle root case */ - if (strcmp(dir, "/") == 0) { - strlcpy(out, "/", n); - strlcat(out, name, n); - } else { - strlcpy(out, dir, n); - strlcat(out, "/", n); - strlcat(out, name, n); - } - } - return out; -} - /* Return the position of the matching entry or 0 otherwise */ int dentfind(struct entry *dents, int n, char *cwd, char *path) From 13c0aef16377a3a6b9a0d48baee33f91e9c8437e Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 19 Feb 2016 13:37:24 +0000 Subject: [PATCH 261/268] Update README - OSX works too --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index eff4230f..258fd8f4 100644 --- a/README +++ b/README @@ -35,7 +35,7 @@ cases you just do: make -It is known to work on OpenBSD, NetBSD, FreeBSD, DragonFly BSD, Linux, +It is known to work on OpenBSD, NetBSD, FreeBSD, DragonFly BSD, Linux, OSX, IRIX 6.5, Haiku and Solaris 9. Some notes for building on certain systems follow. From 81ec2605165985c4e53800a6707469227b9335a2 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 19 Feb 2016 13:40:44 +0000 Subject: [PATCH 262/268] Fix strlcpy() size argument It should be the size of the destination buffer, not the source. In this case, both src and dest have the same size. --- noice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 4d032d37..6b04d4e0 100644 --- a/noice.c +++ b/noice.c @@ -598,7 +598,7 @@ nochange: goto nochange; } /* Save history */ - strlcpy(oldpath, path, sizeof(path)); + strlcpy(oldpath, path, sizeof(oldpath)); strlcpy(path, dir, sizeof(path)); /* Reset filter */ strlcpy(fltr, ifilter, sizeof(fltr)); From 9475edadd1e6e9728c702a8d1dd2a97c29ab8298 Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 19 Feb 2016 13:56:42 +0000 Subject: [PATCH 263/268] Fix grammar in manpage --- noice.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noice.1 b/noice.1 index c23cb9aa..666b1e04 100644 --- a/noice.1 +++ b/noice.1 @@ -54,7 +54,7 @@ Toggle sort by time modified. .It Ic C-l Force a redraw. .It Ic \&! -Spawn an sh shell in current directory. +Spawn a shell in current directory. .It Ic z Run the system top utility. .It Ic e From de1e3394a6700781c49f93bec6745bd8caa74d3c Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 19 Feb 2016 14:03:06 +0000 Subject: [PATCH 264/268] Style fix --- noice.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noice.c b/noice.c index 6b04d4e0..d9794606 100644 --- a/noice.c +++ b/noice.c @@ -433,8 +433,8 @@ dentfill(char *path, struct entry **dents, while ((dp = readdir(dirp)) != NULL) { /* Skip self and parent */ - if (strcmp(dp->d_name, ".") == 0 - || strcmp(dp->d_name, "..") == 0) + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) continue; if (filter(re, dp->d_name) == 0) continue; From e1c26079b109a8ef074362142636c970ccdc9465 Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 25 Feb 2016 14:54:41 +0000 Subject: [PATCH 265/268] Add command to toggle hide .dot files Patch written by Richard Hyde and taken from https://github.com/RichardHyde/noice --- config.def.h | 2 ++ noice.1 | 2 ++ noice.c | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/config.def.h b/config.def.h index e1368dc0..64040797 100644 --- a/config.def.h +++ b/config.def.h @@ -56,6 +56,8 @@ struct key bindings[] = { { '$', SEL_END }, /* Change dir */ { 'c', SEL_CD }, + /* Toggle hide .dot files */ + { '.', SEL_TOGGLEDOT }, /* Toggle sort by time */ { 't', SEL_MTIME }, { CONTROL('L'), SEL_REDRAW }, diff --git a/noice.1 b/noice.1 index 666b1e04..cb5b56d4 100644 --- a/noice.1 +++ b/noice.1 @@ -49,6 +49,8 @@ Back up one directory level. Change filter (see below for more information). .It Ic c Change into the given directory. +.It Ic \&. +Toggle hide .dot files. .It Ic t Toggle sort by time modified. .It Ic C-l diff --git a/noice.c b/noice.c index d9794606..b3a28525 100644 --- a/noice.c +++ b/noice.c @@ -57,6 +57,7 @@ enum action { SEL_HOME, SEL_END, SEL_CD, + SEL_TOGGLEDOT, SEL_MTIME, SEL_REDRAW, SEL_RUN, @@ -706,6 +707,12 @@ nochange: strlcpy(fltr, ifilter, sizeof(fltr)) DPRINTF_S(path); goto begin; + case SEL_TOGGLEDOT: + if (strcmp(fltr, ifilter) != 0) + strlcpy(fltr, ifilter, sizeof(fltr)); + else + strlcpy(fltr, ".", sizeof(fltr)); + goto begin; case SEL_MTIME: mtimeorder = !mtimeorder; /* Save current */ From 829bcdd7d419b8e07d77edfa9b9878f0f399a99f Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 25 Feb 2016 15:06:57 +0000 Subject: [PATCH 266/268] Add command to cd back to HOME Original patch written by Richard Hyde and taken from https://github.com/RichardHyde/noice --- config.def.h | 1 + noice.1 | 4 +++- noice.c | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 64040797..af9bcbb6 100644 --- a/config.def.h +++ b/config.def.h @@ -56,6 +56,7 @@ struct key bindings[] = { { '$', SEL_END }, /* Change dir */ { 'c', SEL_CD }, + { '~', SEL_CDHOME }, /* Toggle hide .dot files */ { '.', SEL_TOGGLEDOT }, /* Toggle sort by time */ diff --git a/noice.1 b/noice.1 index cb5b56d4..f9ac1afc 100644 --- a/noice.1 +++ b/noice.1 @@ -1,4 +1,4 @@ -.Dd November 26, 2015 +.Dd February 25, 2016 .Dt NOICE 1 .Os .Sh NAME @@ -49,6 +49,8 @@ Back up one directory level. Change filter (see below for more information). .It Ic c Change into the given directory. +.It Ic ~ +Change to the HOME directory. .It Ic \&. Toggle hide .dot files. .It Ic t diff --git a/noice.c b/noice.c index b3a28525..489caabe 100644 --- a/noice.c +++ b/noice.c @@ -57,6 +57,7 @@ enum action { SEL_HOME, SEL_END, SEL_CD, + SEL_CDHOME, SEL_TOGGLEDOT, SEL_MTIME, SEL_REDRAW, @@ -707,6 +708,21 @@ nochange: strlcpy(fltr, ifilter, sizeof(fltr)) DPRINTF_S(path); goto begin; + case SEL_CDHOME: + tmp = getenv("HOME"); + if (tmp == NULL) { + clearprompt(); + goto nochange; + } + if (canopendir(tmp) == 0) { + printwarn(); + goto nochange; + } + strlcpy(path, tmp, sizeof(path)); + /* Reset filter */ + strlcpy(fltr, ifilter, sizeof(fltr)); + DPRINTF_S(path); + goto begin; case SEL_TOGGLEDOT: if (strcmp(fltr, ifilter) != 0) strlcpy(fltr, ifilter, sizeof(fltr)); From 3ccbaef87bb70273a6181b298aee01b0cb1f29ab Mon Sep 17 00:00:00 2001 From: sin Date: Thu, 10 Mar 2016 17:00:12 +0000 Subject: [PATCH 267/268] Fix initscr() crash on NetBSD NetBSD has its own curses implementation and initscr() does not terminate with an error if TERM is not set properly. Instead check the return value and exit if an initialization error occurs. --- noice.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/noice.c b/noice.c index 489caabe..a588a55c 100644 --- a/noice.c +++ b/noice.c @@ -257,7 +257,16 @@ entrycmp(const void *va, const void *vb) void initcurses(void) { - initscr(); + char *term; + + if (initscr() == NULL) { + term = getenv("TERM"); + if (term != NULL) + fprintf(stderr, "error opening terminal: %s\n", term); + else + fprintf(stderr, "failed to initialize curses\n"); + exit(1); + } cbreak(); noecho(); nonl(); From d56de6318faef8450770a7d139ac30840296de6a Mon Sep 17 00:00:00 2001 From: sin Date: Fri, 11 Mar 2016 09:59:48 +0000 Subject: [PATCH 268/268] Bump to 0.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 98528571..9035141d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.4 +VERSION = 0.5 PREFIX = /usr/local MANPREFIX = $(PREFIX)/man