commit 15505bd711d77fbd88dbdcbc464c78d863e03250
parent 86468aafe52a94ce6ba1a3601a587c65724a61aa
Author: Connor Lane Smith <cls@lubutu.com>
Date:   Sat, 14 May 2011 20:43:11 +0100

fast dmenu_path script
Diffstat:
MMakefile | 10+++-------
Mdmenu.1 | 2+-
Admenu_path | 9+++++++++
Ddmenu_path.c | 100-------------------------------------------------------------------------------
4 files changed, 13 insertions(+), 108 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,7 +3,7 @@ include config.mk -all: options dmenu dmenu_path +all: options dmenu options: @echo dmenu build options: @@ -15,22 +15,18 @@ dmenu: dmenu.o draw.o @echo CC -o $@ @${CC} -o $@ dmenu.o draw.o ${LDFLAGS} -dmenu_path: dmenu_path.o - @echo CC -o $@ - @${CC} -o $@ dmenu_path.o ${LDFLAGS} - .c.o: config.mk @echo CC -c $< @${CC} -c $< ${CFLAGS} clean: @echo cleaning - @rm -f dmenu dmenu.o draw.o dmenu_path dmenu_path.o dmenu-${VERSION}.tar.gz + @rm -f dmenu dmenu.o draw.o dmenu-${VERSION}.tar.gz dist: clean @echo creating dist tarball @mkdir -p dmenu-${VERSION} - @cp LICENSE Makefile README config.mk dmenu.1 dmenu.c draw.c draw.h dmenu_path.c dmenu_run dmenu-${VERSION} + @cp LICENSE Makefile README config.mk dmenu.1 dmenu.c draw.c draw.h dmenu_path dmenu_run dmenu-${VERSION} @tar -cf dmenu-${VERSION}.tar dmenu-${VERSION} @gzip dmenu-${VERSION}.tar @rm -rf dmenu-${VERSION} diff --git a/dmenu.1 b/dmenu.1 @@ -42,7 +42,7 @@ is a dmenu script used by dwm which lists programs in the user's PATH and executes the selected item. .P .B dmenu_path -is a program used by dmenu_run to find and cache a list of executables. +is a script used by dmenu_run to find and cache a list of executables. .SH OPTIONS .TP .B \-b diff --git a/dmenu_path b/dmenu_path @@ -0,0 +1,9 @@ +#!/bin/sh +CACHE=$HOME/.dmenu_cache +IFS=: + +if ! test -f "$CACHE" || find $PATH -type d -newer "$CACHE" | grep -q .; then + find $PATH -type f \( -perm -1 -o -perm -10 -o -perm -100 \) | sort -u > "$CACHE" +fi + +cat "$CACHE" diff --git a/dmenu_path.c b/dmenu_path.c @@ -1,100 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <dirent.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> - -static void die(const char *s); -static int qstrcmp(const void *a, const void *b); -static void scan(void); -static int uptodate(void); - -static char **items = NULL; -static const char *home, *path; - -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()) { - execl("/bin/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, *p; - size_t i, count; - struct dirent *ent; - DIR *dp; - FILE *cache; - - count = 0; - if(!(p = strdup(path))) - die("strdup failed"); - for(dir = strtok(p, ":"); 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(p); -} - -int -uptodate(void) { - char *dir, *p; - time_t mtime; - struct stat st; - - if(stat(CACHE, &st) < 0) - return 0; - mtime = st.st_mtime; - if(!(p = strdup(path))) - die("strdup failed"); - for(dir = strtok(p, ":"); dir; dir = strtok(NULL, ":")) - if(!stat(dir, &st) && st.st_mtime > mtime) - return 0; - free(p); - return 1; -}