| @@ -481,12 +481,13 @@ void clear_resize(void) |
| 481 | 481 | | void run_key_handler(const char *key, unsigned int mask) |
| 482 | 482 | | { |
| 483 | 483 | | pid_t pid; |
| 484 | | − | int i, j, retval, status; |
| 485 | | − | int fcnt = mode == MODE_THUMB && markcnt > 0 ? markcnt : 1; |
| 484 | + | FILE *pfs; |
| 485 | + | bool marked = mode == MODE_THUMB && markcnt > 0; |
| 486 | 486 | | bool changed = false; |
| 487 | | − | char **args, kstr[32], oldbar[BAR_L_LEN]; |
| 488 | | − | struct stat *oldst, newst; |
| 489 | | − | struct { int fn; struct stat st; } *finfo; |
| 487 | + | int f, i, pfd[2], retval, status; |
| 488 | + | int fcnt = marked ? markcnt : 1; |
| 489 | + | char kstr[32], oldbar[BAR_L_LEN]; |
| 490 | + | struct stat *oldst, st; |
| 490 | 491 | | |
| 491 | 492 | | if (keyhandler.cmd == NULL) { |
| 492 | 493 | | if (!keyhandler.warned) { |
| @@ -498,55 +499,66 @@ void run_key_handler(const char *key, unsigned int mask) |
| 498 | 499 | | if (key == NULL) |
| 499 | 500 | | return; |
| 500 | 501 | | |
| 501 | | − | finfo = s_malloc(fcnt * sizeof(*finfo)); |
| 502 | | − | args = s_malloc((fcnt + 3) * sizeof(*args)); |
| 503 | | − | args[0] = keyhandler.cmd; |
| 504 | | − | args[1] = kstr; |
| 505 | | − | args[fcnt+2] = NULL; |
| 506 | | − | if (mode == MODE_IMAGE || markcnt == 0) { |
| 507 | | − | finfo[0].fn = fileidx; |
| 508 | | − | stat(files[fileidx].path, &finfo[0].st); |
| 509 | | − | args[2] = (char*) files[fileidx].path; |
| 510 | | − | } else for (i = j = 0; i < filecnt; i++) { |
| 511 | | − | if (files[i].marked) { |
| 512 | | − | finfo[j].fn = i; |
| 513 | | − | stat(files[i].path, &finfo[j++].st); |
| 514 | | − | args[j+1] = (char*) files[i].path; |
| 515 | | − | } |
| 502 | + | if (pipe(pfd) < 0) { |
| 503 | + | warn("could not create pipe for key handler"); |
| 504 | + | return; |
| 516 | 505 | | } |
| 517 | | − | snprintf(kstr, sizeof(kstr), "%s%s%s%s", |
| 518 | | − | mask & ControlMask ? "C-" : "", |
| 519 | | − | mask & Mod1Mask ? "M-" : "", |
| 520 | | − | mask & ShiftMask ? "S-" : "", key); |
| 506 | + | if ((pfs = fdopen(pfd[1], "w")) == NULL) { |
| 507 | + | close(pfd[0]), close(pfd[1]); |
| 508 | + | warn("could not open pipe for key handler"); |
| 509 | + | return; |
| 510 | + | } |
| 511 | + | oldst = s_malloc(fcnt * sizeof(*oldst)); |
| 521 | 512 | | |
| 522 | 513 | | memcpy(oldbar, win.bar.l.buf, sizeof(oldbar)); |
| 523 | 514 | | strncpy(win.bar.l.buf, "Running key handler...", win.bar.l.size); |
| 524 | 515 | | win_draw(&win); |
| 525 | 516 | | win_set_cursor(&win, CURSOR_WATCH); |
| 526 | 517 | | |
| 518 | + | snprintf(kstr, sizeof(kstr), "%s%s%s%s", |
| 519 | + | mask & ControlMask ? "C-" : "", |
| 520 | + | mask & Mod1Mask ? "M-" : "", |
| 521 | + | mask & ShiftMask ? "S-" : "", key); |
| 522 | + | |
| 527 | 523 | | if ((pid = fork()) == 0) { |
| 528 | | − | execv(keyhandler.cmd, args); |
| 524 | + | close(pfd[1]); |
| 525 | + | dup2(pfd[0], 0); |
| 526 | + | execl(keyhandler.cmd, keyhandler.cmd, kstr, NULL); |
| 529 | 527 | | warn("could not exec key handler"); |
| 530 | 528 | | exit(EXIT_FAILURE); |
| 531 | | − | } else if (pid < 0) { |
| 529 | + | } |
| 530 | + | close(pfd[0]); |
| 531 | + | if (pid < 0) { |
| 532 | + | fclose(pfs); |
| 532 | 533 | | warn("could not fork key handler"); |
| 533 | 534 | | goto end; |
| 534 | 535 | | } |
| 536 | + | |
| 537 | + | for (f = i = 0; f < fcnt; i++) { |
| 538 | + | if ((marked && files[i].marked) || (!marked && i == fileidx)) { |
| 539 | + | stat(files[i].path, &oldst[f]); |
| 540 | + | fprintf(pfs, "%s\n", files[i].name); |
| 541 | + | f++; |
| 542 | + | } |
| 543 | + | } |
| 544 | + | fclose(pfs); |
| 535 | 545 | | waitpid(pid, &status, 0); |
| 536 | 546 | | retval = WEXITSTATUS(status); |
| 537 | 547 | | if (WIFEXITED(status) == 0 || retval != 0) |
| 538 | 548 | | warn("key handler exited with non-zero return value: %d", retval); |
| 539 | 549 | | |
| 540 | | − | for (i = 0; i < fcnt; i++) { |
| 541 | | − | oldst = &finfo[i].st; |
| 542 | | − | if (stat(files[finfo[i].fn].path, &newst) != 0 || |
| 543 | | − | memcmp(&oldst->st_mtime, &newst.st_mtime, sizeof(newst.st_mtime)) != 0) |
| 544 | | − | { |
| 545 | | − | if (tns.thumbs != NULL) { |
| 546 | | − | tns_unload(&tns, finfo[i].fn); |
| 547 | | − | tns.loadnext = MIN(tns.loadnext, finfo[i].fn); |
| 550 | + | for (f = i = 0; f < fcnt; i++) { |
| 551 | + | if ((marked && files[i].marked) || (!marked && i == fileidx)) { |
| 552 | + | if (stat(files[i].path, &st) != 0 || |
| 553 | + | memcmp(&oldst[f].st_mtime, &st.st_mtime, sizeof(st.st_mtime)) != 0) |
| 554 | + | { |
| 555 | + | if (tns.thumbs != NULL) { |
| 556 | + | tns_unload(&tns, i); |
| 557 | + | tns.loadnext = MIN(tns.loadnext, i); |
| 558 | + | } |
| 559 | + | changed = true; |
| 548 | 560 | | } |
| 549 | | − | changed = true; |
| 561 | + | f++; |
| 550 | 562 | | } |
| 551 | 563 | | } |
| 552 | 564 | | end: |
| @@ -558,10 +570,9 @@ end: |
| 558 | 570 | | memcpy(win.bar.l.buf, oldbar, win.bar.l.size); |
| 559 | 571 | | } |
| 560 | 572 | | } |
| 573 | + | free(oldst); |
| 561 | 574 | | reset_cursor(); |
| 562 | 575 | | redraw(); |
| 563 | | − | free(finfo); |
| 564 | | − | free(args); |
| 565 | 576 | | } |
| 566 | 577 | | |
| 567 | 578 | | #define MODMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask)) |