Pass file paths to key handler via stdin; fixes issue #187
This commit is contained in:
		
							
								
								
									
										85
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								main.c
									
									
									
									
									
								
							@@ -481,12 +481,13 @@ void clear_resize(void)
 | 
			
		||||
void run_key_handler(const char *key, unsigned int mask)
 | 
			
		||||
{
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
	int i, j, retval, status;
 | 
			
		||||
	int fcnt = mode == MODE_THUMB && markcnt > 0 ? markcnt : 1;
 | 
			
		||||
	FILE *pfs;
 | 
			
		||||
	bool marked = mode == MODE_THUMB && markcnt > 0;
 | 
			
		||||
	bool changed = false;
 | 
			
		||||
	char **args, kstr[32], oldbar[BAR_L_LEN];
 | 
			
		||||
	struct stat *oldst, newst;
 | 
			
		||||
	struct { int fn; struct stat st; } *finfo;
 | 
			
		||||
	int f, i, pfd[2], retval, status;
 | 
			
		||||
	int fcnt = marked ? markcnt : 1;
 | 
			
		||||
	char kstr[32], oldbar[BAR_L_LEN];
 | 
			
		||||
	struct stat *oldst, st;
 | 
			
		||||
 | 
			
		||||
	if (keyhandler.cmd == NULL) {
 | 
			
		||||
		if (!keyhandler.warned) {
 | 
			
		||||
@@ -498,55 +499,66 @@ void run_key_handler(const char *key, unsigned int mask)
 | 
			
		||||
	if (key == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	finfo = s_malloc(fcnt * sizeof(*finfo));
 | 
			
		||||
	args = s_malloc((fcnt + 3) * sizeof(*args));
 | 
			
		||||
	args[0] = keyhandler.cmd;
 | 
			
		||||
	args[1] = kstr;
 | 
			
		||||
	args[fcnt+2] = NULL;
 | 
			
		||||
	if (mode == MODE_IMAGE || markcnt == 0) {
 | 
			
		||||
		finfo[0].fn = fileidx;
 | 
			
		||||
		stat(files[fileidx].path, &finfo[0].st);
 | 
			
		||||
		args[2] = (char*) files[fileidx].path;
 | 
			
		||||
	} else for (i = j = 0; i < filecnt; i++) {
 | 
			
		||||
		if (files[i].marked) {
 | 
			
		||||
			finfo[j].fn = i;
 | 
			
		||||
			stat(files[i].path, &finfo[j++].st);
 | 
			
		||||
			args[j+1] = (char*) files[i].path;
 | 
			
		||||
		}
 | 
			
		||||
	if (pipe(pfd) < 0) {
 | 
			
		||||
		warn("could not create pipe for key handler");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	snprintf(kstr, sizeof(kstr), "%s%s%s%s",
 | 
			
		||||
	         mask & ControlMask ? "C-" : "",
 | 
			
		||||
	         mask & Mod1Mask    ? "M-" : "",
 | 
			
		||||
	         mask & ShiftMask   ? "S-" : "", key);
 | 
			
		||||
	if ((pfs = fdopen(pfd[1], "w")) == NULL) {
 | 
			
		||||
		close(pfd[0]), close(pfd[1]);
 | 
			
		||||
		warn("could not open pipe for key handler");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	oldst = s_malloc(fcnt * sizeof(*oldst));
 | 
			
		||||
 | 
			
		||||
	memcpy(oldbar, win.bar.l.buf, sizeof(oldbar));
 | 
			
		||||
	strncpy(win.bar.l.buf, "Running key handler...", win.bar.l.size);
 | 
			
		||||
	win_draw(&win);
 | 
			
		||||
	win_set_cursor(&win, CURSOR_WATCH);
 | 
			
		||||
 | 
			
		||||
	snprintf(kstr, sizeof(kstr), "%s%s%s%s",
 | 
			
		||||
	         mask & ControlMask ? "C-" : "",
 | 
			
		||||
	         mask & Mod1Mask    ? "M-" : "",
 | 
			
		||||
	         mask & ShiftMask   ? "S-" : "", key);
 | 
			
		||||
 | 
			
		||||
	if ((pid = fork()) == 0) {
 | 
			
		||||
		execv(keyhandler.cmd, args);
 | 
			
		||||
		close(pfd[1]);
 | 
			
		||||
		dup2(pfd[0], 0);
 | 
			
		||||
		execl(keyhandler.cmd, keyhandler.cmd, kstr, NULL);
 | 
			
		||||
		warn("could not exec key handler");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	} else if (pid < 0) {
 | 
			
		||||
	}
 | 
			
		||||
	close(pfd[0]);
 | 
			
		||||
	if (pid < 0) {
 | 
			
		||||
		fclose(pfs);
 | 
			
		||||
		warn("could not fork key handler");
 | 
			
		||||
		goto end;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (f = i = 0; f < fcnt; i++) {
 | 
			
		||||
		if ((marked && files[i].marked) || (!marked && i == fileidx)) {
 | 
			
		||||
			stat(files[i].path, &oldst[f]);
 | 
			
		||||
			fprintf(pfs, "%s\n", files[i].name);
 | 
			
		||||
			f++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fclose(pfs);
 | 
			
		||||
	waitpid(pid, &status, 0);
 | 
			
		||||
	retval = WEXITSTATUS(status);
 | 
			
		||||
	if (WIFEXITED(status) == 0 || retval != 0)
 | 
			
		||||
		warn("key handler exited with non-zero return value: %d", retval);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < fcnt; i++) {
 | 
			
		||||
		oldst = &finfo[i].st;
 | 
			
		||||
		if (stat(files[finfo[i].fn].path, &newst) != 0 ||
 | 
			
		||||
				memcmp(&oldst->st_mtime, &newst.st_mtime, sizeof(newst.st_mtime)) != 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (tns.thumbs != NULL) {
 | 
			
		||||
				tns_unload(&tns, finfo[i].fn);
 | 
			
		||||
				tns.loadnext = MIN(tns.loadnext, finfo[i].fn);
 | 
			
		||||
	for (f = i = 0; f < fcnt; i++) {
 | 
			
		||||
		if ((marked && files[i].marked) || (!marked && i == fileidx)) {
 | 
			
		||||
			if (stat(files[i].path, &st) != 0 ||
 | 
			
		||||
				  memcmp(&oldst[f].st_mtime, &st.st_mtime, sizeof(st.st_mtime)) != 0)
 | 
			
		||||
			{
 | 
			
		||||
				if (tns.thumbs != NULL) {
 | 
			
		||||
					tns_unload(&tns, i);
 | 
			
		||||
					tns.loadnext = MIN(tns.loadnext, i);
 | 
			
		||||
				}
 | 
			
		||||
				changed = true;
 | 
			
		||||
			}
 | 
			
		||||
			changed = true;
 | 
			
		||||
			f++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
end:
 | 
			
		||||
@@ -558,10 +570,9 @@ end:
 | 
			
		||||
			memcpy(win.bar.l.buf, oldbar, win.bar.l.size);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	free(oldst);
 | 
			
		||||
	reset_cursor();
 | 
			
		||||
	redraw();
 | 
			
		||||
	free(finfo);
 | 
			
		||||
	free(args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user