parent
610a0a8d12
commit
bf7b8e37ee
3 changed files with 108 additions and 34 deletions
@ -1,26 +0,0 @@ |
||||
#!/bin/sh |
||||
CACHE=$HOME/.dmenu_cache |
||||
IFS=: |
||||
|
||||
uptodate() { |
||||
test -f "$CACHE" && |
||||
for dir in $PATH |
||||
do |
||||
test ! $dir -nt "$CACHE" || return 1 |
||||
done |
||||
} |
||||
|
||||
if ! uptodate |
||||
then |
||||
for dir in $PATH |
||||
do |
||||
cd "$dir" && |
||||
for file in * |
||||
do |
||||
test -x "$file" && echo "$file" |
||||
done |
||||
done | sort -u > "$CACHE".$$ && |
||||
mv "$CACHE".$$ "$CACHE" |
||||
fi |
||||
|
||||
cat "$CACHE" |
@ -0,0 +1,101 @@ |
||||
/* See LICENSE file for copyright and license details. */ |
||||
#include <dirent.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
#include <sys/stat.h> |
||||
|
||||
#define CACHE ".dmenu_cache" |
||||
|
||||
static int qstrcmp(const void *a, const void *b); |
||||
static void die(const char *s); |
||||
static void scan(void); |
||||
static int uptodate(void); |
||||
|
||||
static char **items = NULL; |
||||
static const char *Home, *Path; |
||||
static size_t count = 0; |
||||
|
||||
int |
||||
main(void) { |
||||
if(!(Home = getenv("HOME"))) |
||||
die("no $HOME"); |
||||
if(!(Path = getenv("PATH"))) |
||||
die("no $PATH"); |
||||
if(chdir(Home) < 0) |
||||
die("chdir failed"); |
||||
if(uptodate()) { |
||||
execlp("cat", "cat", CACHE, NULL); |
||||
die("exec failed"); |
||||
} |
||||
scan(); |
||||
return EXIT_SUCCESS; |
||||
} |
||||
|
||||
void |
||||
die(const char *s) { |
||||
fprintf(stderr, "dmenu_path: %s\n", s); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
|
||||
int |
||||
qstrcmp(const void *a, const void *b) { |
||||
return strcmp(*(const char **)a, *(const char **)b); |
||||
} |
||||
|
||||
void |
||||
scan(void) { |
||||
char buf[PATH_MAX]; |
||||
char *dir, *path; |
||||
size_t i; |
||||
struct dirent *ent; |
||||
DIR *dp; |
||||
FILE *cache; |
||||
|
||||
if(!(path = strdup(Path))) |
||||
die("strdup failed"); |
||||
for(dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) { |
||||
if(!(dp = opendir(dir))) |
||||
continue; |
||||
while((ent = readdir(dp))) { |
||||
snprintf(buf, sizeof buf, "%s/%s", dir, ent->d_name); |
||||
if(ent->d_name[0] == '.' || access(buf, X_OK) < 0) |
||||
continue; |
||||
if(!(items = realloc(items, ++count * sizeof *items))) |
||||
die("malloc failed"); |
||||
if(!(items[count-1] = strdup(ent->d_name))) |
||||
die("strdup failed"); |
||||
} |
||||
closedir(dp); |
||||
} |
||||
qsort(items, count, sizeof *items, qstrcmp); |
||||
if(!(cache = fopen(CACHE, "w"))) |
||||
die("open failed"); |
||||
for(i = 0; i < count; i++) { |
||||
if(i > 0 && !strcmp(items[i], items[i-1])) |
||||
continue; |
||||
fprintf(cache, "%s\n", items[i]); |
||||
fprintf(stdout, "%s\n", items[i]); |
||||
} |
||||
fclose(cache); |
||||
free(path); |
||||
} |
||||
|
||||
int |
||||
uptodate(void) { |
||||
char *dir, *path; |
||||
time_t mtime; |
||||
struct stat st; |
||||
|
||||
if(stat(CACHE, &st) < 0) |
||||
return 0; |
||||
mtime = st.st_mtime; |
||||
if(!(path = strdup(Path))) |
||||
die("strdup failed"); |
||||
for(dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) |
||||
if(!stat(dir, &st) && st.st_mtime > mtime) |
||||
return 0; |
||||
free(path); |
||||
return 1; |
||||
} |
Loading…
Reference in new issue