Use "/bin/sh -c" for external commands

This commit is contained in:
Bert 2011-03-03 10:52:16 +01:00
parent 50e8fbf7b3
commit 00d4b0f7cf
3 changed files with 49 additions and 63 deletions

View File

@ -1,6 +1,6 @@
all: sxiv all: sxiv
VERSION=git-20110301 VERSION=git-20110303
CC?=gcc CC?=gcc
PREFIX?=/usr/local PREFIX?=/usr/local

View File

@ -1,29 +1,13 @@
#define FILENAME (const char*) 0x1
typedef struct { typedef struct {
KeySym ksym; KeySym ksym;
const char **cmdline;
Bool reload; Bool reload;
const char *cmdline;
} command_t; } command_t;
static const char *cmdline_1[] = {
"jpegtran", "-rotate", "270", "-copy", "all", "-outfile", FILENAME,
FILENAME, NULL };
static const char *cmdline_2[] = {
"jpegtran", "-rotate", "90", "-copy", "all", "-outfile", FILENAME,
FILENAME, NULL };
static const char *cmdline_3[] = {
"mogrify", "-rotate", "-90", FILENAME, NULL };
static const char *cmdline_4[] = {
"mogrify", "-rotate", "+90", FILENAME, NULL };
static command_t commands[] = { static command_t commands[] = {
/* key command-line reload? */ /* key reload? command, '#' is replaced by filename */
{ XK_a, cmdline_1, True }, { XK_a, True, "jpegtran -rotate 270 -copy all -outfile # #" },
{ XK_s, cmdline_2, True }, { XK_s, True, "jpegtran -rotate 90 -copy all -outfile # #" },
{ XK_A, cmdline_3, True }, { XK_A, True, "mogrify -rotate -90 #" },
{ XK_S, cmdline_4, True }, { XK_S, True, "mogrify -rotate +90 #" }
}; };

78
main.c
View File

@ -273,57 +273,59 @@ void read_dir_rec(const char *dirname) {
free(dirnames); free(dirnames);
} }
int run_command(const char **cmdline, Bool reload) { int run_command(const char *cline, Bool reload) {
int argc, i; int fncnt, fnlen;
const char **argv; char *cn, *cmdline;
const char *co, *fname;
pid_t pid; pid_t pid;
int error, ret, status; int ret, status;
if (!cmdline) if (!cline || !*cline)
return 0; return 0;
argc = 1; fncnt = 0;
while (cmdline[argc-1]) co = cline - 1;
++argc; while ((co = strchr(co + 1, '#')))
++fncnt;
if (argc < 2) if (!fncnt)
return 0; return 0;
argv = (const char**) s_malloc(argc * sizeof(const char*)); ret = 0;
error = ret = 0; fname = filenames[mode == MODE_NORMAL ? fileidx : tns.sel];
fnlen = strlen(fname);
cn = cmdline = (char*) s_malloc((strlen(cline) + fncnt * (fnlen + 2)) *
sizeof(char));
for (i = 0; i < argc; ++i) { /* replace all '#' with filename */
if (cmdline[i] != FILENAME) for (co = cline; *co; ++co) {
argv[i] = cmdline[i]; if (*co == '#') {
else *cn++ = '"';
argv[i] = filenames[mode == MODE_NORMAL ? fileidx : tns.sel]; strcpy(cn, fname);
} cn += fnlen;
*cn++ = '"';
if ((pid = fork()) == 0) { } else {
execvp(argv[0], (char **const) argv); *cn++ = *co;
warn("could not exec %s", argv[0]);
exit(1);
} else if (pid < 0 && !options->quiet) {
warn("could not fork. command line was:");
error = 1;
} else if (reload) {
waitpid(pid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
ret = 1;
} else if (!options->quiet) {
warn("child exited with non-zero return value: %d. command line was:",
WEXITSTATUS(status));
error = 1;
} }
} }
*cn = '\0';
if (error) { if ((pid = fork()) == 0) {
for (i = 0; i < argc && argv[i]; ++i) execlp("/bin/sh", "/bin/sh", "-c", cmdline, NULL);
fprintf(stderr, "%s%s", i > 0 ? " " : "", argv[i]); warn("could not exec: /bin/sh");
fprintf(stderr, "\n"); exit(1);
} else if (pid < 0) {
warn("could not fork. command line was: %s", cmdline);
} else if (reload) {
waitpid(pid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
ret = 1;
else
warn("child exited with non-zero return value: %d. command line was: %s",
WEXITSTATUS(status), cmdline);
} }
free(argv); free(cmdline);
return ret; return ret;
} }