version 1.4, 2009/09/21 15:32:06 |
version 1.5, 2009/10/11 09:10:57 |
|
|
|
|
/* |
/* |
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> |
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> |
|
* Copyright (c) 2009 Nicholas Marriott <nicm@openbsd.org> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
*/ |
*/ |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
|
#include <sys/wait.h> |
|
|
#include <errno.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
#include <string.h> |
|
|
#include "tmux.h" |
#include "tmux.h" |
|
|
* Executes a tmux command if a shell command returns true. |
* Executes a tmux command if a shell command returns true. |
*/ |
*/ |
|
|
int cmd_if_shell_parse(struct cmd *, int, char **, char **); |
|
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *); |
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *); |
void cmd_if_shell_free(struct cmd *); |
|
void cmd_if_shell_init(struct cmd *, int); |
|
size_t cmd_if_shell_print(struct cmd *, char *, size_t); |
|
|
|
struct cmd_if_shell_data { |
void cmd_if_shell_callback(struct job *); |
char *cmd; |
void cmd_if_shell_free(void *); |
char *sh_cmd; |
|
}; |
|
|
|
const struct cmd_entry cmd_if_shell_entry = { |
const struct cmd_entry cmd_if_shell_entry = { |
"if-shell", "if", |
"if-shell", "if", |
"shell-command command", |
"shell-command command", |
0, 0, |
CMD_ARG2, 0, |
cmd_if_shell_init, |
cmd_target_init, |
cmd_if_shell_parse, |
cmd_target_parse, |
cmd_if_shell_exec, |
cmd_if_shell_exec, |
cmd_if_shell_free, |
cmd_target_free, |
cmd_if_shell_print |
cmd_target_print |
}; |
}; |
|
|
void |
struct cmd_if_shell_data { |
cmd_if_shell_init(struct cmd *self, unused int arg) |
char *cmd; |
{ |
struct cmd_ctx ctx; |
struct cmd_if_shell_data *data; |
}; |
|
|
self->data = data = xmalloc(sizeof *data); |
|
data->cmd = NULL; |
|
data->sh_cmd = NULL; |
|
} |
|
|
|
int |
int |
cmd_if_shell_parse(struct cmd *self, int argc, char **argv, char **cause) |
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) |
{ |
{ |
struct cmd_if_shell_data *data; |
struct cmd_target_data *data = self->data; |
int opt; |
struct cmd_if_shell_data *cdata; |
|
struct job *job; |
|
|
self->entry->init(self, KEYC_NONE); |
cdata = xmalloc(sizeof *cdata); |
data = self->data; |
cdata->cmd = xstrdup(data->arg2); |
|
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); |
|
|
while ((opt = getopt(argc, argv, "")) != -1) { |
if (ctx->cmdclient != NULL) |
switch (opt) { |
ctx->cmdclient->references++; |
default: |
if (ctx->curclient != NULL) |
goto usage; |
ctx->curclient->references++; |
} |
|
} |
|
argc -= optind; |
|
argv += optind; |
|
if (argc != 2) |
|
goto usage; |
|
|
|
data->sh_cmd = xstrdup(argv[0]); |
job = job_add(NULL, NULL, |
data->cmd = xstrdup(argv[1]); |
data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata); |
return (0); |
job_run(job); |
|
|
usage: |
return (1); /* don't let client exit */ |
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); |
|
|
|
self->entry->free(self); |
|
return (-1); |
|
} |
} |
|
|
int |
void |
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) |
cmd_if_shell_callback(struct job *job) |
{ |
{ |
struct cmd_if_shell_data *data = self->data; |
struct cmd_if_shell_data *cdata = job->data; |
|
struct cmd_ctx *ctx = &cdata->ctx; |
struct cmd_list *cmdlist; |
struct cmd_list *cmdlist; |
char *cause; |
char *cause; |
int ret; |
|
|
|
if ((ret = system(data->sh_cmd)) < 0) { |
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) { |
ctx->error(ctx, "system error: %s", strerror(errno)); |
job_free(job); /* calls cmd_if_shell_free */ |
return (-1); |
return; |
} else if (ret != 0) |
} |
return (0); |
|
|
|
if (cmd_string_parse(data->cmd, &cmdlist, &cause) != 0) { |
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) { |
if (cause != NULL) { |
if (cause != NULL) { |
ctx->error(ctx, "%s", cause); |
ctx->error(ctx, "%s", cause); |
xfree(cause); |
xfree(cause); |
} |
} |
return (-1); |
return; |
} |
} |
|
|
if (cmd_list_exec(cmdlist, ctx) < 0) { |
if (cmd_list_exec(cmdlist, ctx) < 0) { |
cmd_list_free(cmdlist); |
cmd_list_free(cmdlist); |
return (-1); |
return; |
} |
} |
|
|
cmd_list_free(cmdlist); |
cmd_list_free(cmdlist); |
return (0); |
|
} |
} |
|
|
void |
void |
cmd_if_shell_free(struct cmd *self) |
cmd_if_shell_free(void *data) |
{ |
{ |
struct cmd_if_shell_data *data = self->data; |
struct cmd_if_shell_data *cdata = data; |
|
struct cmd_ctx *ctx = &cdata->ctx; |
|
|
if (data->cmd != NULL) |
if (ctx->cmdclient != NULL) { |
xfree(data->cmd); |
ctx->cmdclient->references--; |
if (data->sh_cmd != NULL) |
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); |
xfree(data->sh_cmd); |
} |
xfree(data); |
if (ctx->curclient != NULL) |
} |
ctx->curclient->references--; |
|
|
size_t |
xfree(cdata->cmd); |
cmd_if_shell_print(struct cmd *self, char *buf, size_t len) |
xfree(cdata); |
{ |
|
struct cmd_if_shell_data *data = self->data; |
|
size_t off = 0; |
|
|
|
off += xsnprintf(buf, len, "%s", self->entry->name); |
|
if (data == NULL) |
|
return (off); |
|
if (off < len && data->sh_cmd != NULL) |
|
off += cmd_prarg(buf + off, len - off, " ", data->sh_cmd); |
|
if (off < len && data->cmd != NULL) |
|
off += cmd_prarg(buf + off, len - off, " ", data->cmd); |
|
return (off); |
|
} |
} |