fast dmenu_path script
							parent
							
								
									86468aafe5
								
							
						
					
					
						commit
						15505bd711
					
				
							
								
								
									
										10
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										10
									
								
								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} | ||||
|  |  | |||
							
								
								
									
										2
									
								
								dmenu.1
								
								
								
								
							
							
						
						
									
										2
									
								
								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 | ||||
|  |  | |||
|  | @ -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" | ||||
							
								
								
									
										100
									
								
								dmenu_path.c
								
								
								
								
							
							
						
						
									
										100
									
								
								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; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue