version 1.49, 2009/10/10 14:51:16 |
version 1.50, 2009/10/21 20:11:47 |
|
|
int login_shell; |
int login_shell; |
|
|
__dead void usage(void); |
__dead void usage(void); |
|
void fill_session(struct msg_command_data *); |
char *makesockpath(const char *); |
char *makesockpath(const char *); |
int prepare_cmd(enum msgtype *, void **, size_t *, int, char **); |
int prepare_cmd(enum msgtype *, void **, size_t *, int, char **); |
int dispatch_imsg(struct client_ctx *, const char *, int *); |
int dispatch_imsg(struct imsgbuf *, const char *, int *); |
__dead void shell_exec(const char *, const char *); |
__dead void shell_exec(const char *, const char *); |
|
|
__dead void |
__dead void |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
void |
|
fill_session(struct msg_command_data *data) |
|
{ |
|
char *env, *ptr1, *ptr2, buf[256]; |
|
size_t len; |
|
const char *errstr; |
|
long long ll; |
|
|
|
data->pid = -1; |
|
if ((env = getenv("TMUX")) == NULL) |
|
return; |
|
|
|
if ((ptr2 = strrchr(env, ',')) == NULL || ptr2 == env) |
|
return; |
|
for (ptr1 = ptr2 - 1; ptr1 > env && *ptr1 != ','; ptr1--) |
|
; |
|
if (*ptr1 != ',') |
|
return; |
|
ptr1++; |
|
ptr2++; |
|
|
|
len = ptr2 - ptr1 - 1; |
|
if (len > (sizeof buf) - 1) |
|
return; |
|
memcpy(buf, ptr1, len); |
|
buf[len] = '\0'; |
|
|
|
ll = strtonum(buf, 0, LONG_MAX, &errstr); |
|
if (errstr != NULL) |
|
return; |
|
data->pid = ll; |
|
|
|
ll = strtonum(ptr2, 0, UINT_MAX, &errstr); |
|
if (errstr != NULL) |
|
return; |
|
data->idx = ll; |
|
} |
|
|
char * |
char * |
makesockpath(const char *label) |
makesockpath(const char *label) |
{ |
{ |
|
|
{ |
{ |
static struct msg_command_data cmddata; |
static struct msg_command_data cmddata; |
|
|
client_fill_session(&cmddata); |
fill_session(&cmddata); |
|
|
cmddata.argc = argc; |
cmddata.argc = argc; |
if (cmd_pack_argv(argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) { |
if (cmd_pack_argv(argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) { |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
struct client_ctx cctx; |
struct cmd_list *cmdlist; |
struct cmd_list *cmdlist; |
struct cmd *cmd; |
struct cmd *cmd; |
struct pollfd pfd; |
struct pollfd pfd; |
enum msgtype msg; |
enum msgtype msg; |
struct passwd *pw; |
struct passwd *pw; |
struct options *so, *wo; |
struct options *so, *wo; |
struct keylist *keylist; |
struct keylist *keylist; |
struct imsgbuf *ibuf; |
char *s, *shellcmd, *path, *label, *home, *cause; |
char *s, *shellcmd, *path, *label, *home, *cause; |
char cwd[MAXPATHLEN], **var; |
char cwd[MAXPATHLEN], **var; |
void *buf; |
void *buf; |
size_t len; |
size_t len; |
int retcode, opt, flags, cmdflags = 0; |
int nfds, retcode, opt, flags, cmdflags = 0; |
int nfds; |
|
|
|
flags = 0; |
flags = 0; |
shellcmd = label = path = NULL; |
shellcmd = label = path = NULL; |
|
|
cmd_list_free(cmdlist); |
cmd_list_free(cmdlist); |
} |
} |
|
|
memset(&cctx, 0, sizeof cctx); |
if ((ibuf = client_init(path, cmdflags, flags)) == NULL) |
if (client_init(path, &cctx, cmdflags, flags) != 0) |
|
exit(1); |
exit(1); |
xfree(path); |
xfree(path); |
|
|
client_write_server(&cctx, msg, buf, len); |
imsg_compose(ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len); |
memset(buf, 0, len); |
|
|
|
retcode = 0; |
retcode = 0; |
for (;;) { |
for (;;) { |
pfd.fd = cctx.ibuf.fd; |
pfd.fd = ibuf->fd; |
pfd.events = POLLIN; |
pfd.events = POLLIN; |
if (cctx.ibuf.w.queued != 0) |
if (ibuf->w.queued != 0) |
pfd.events |= POLLOUT; |
pfd.events |= POLLOUT; |
|
|
if ((nfds = poll(&pfd, 1, INFTIM)) == -1) { |
if ((nfds = poll(&pfd, 1, INFTIM)) == -1) { |
|
|
fatalx("socket error"); |
fatalx("socket error"); |
|
|
if (pfd.revents & POLLIN) { |
if (pfd.revents & POLLIN) { |
if (dispatch_imsg(&cctx, shellcmd, &retcode) != 0) |
if (dispatch_imsg(ibuf, shellcmd, &retcode) != 0) |
break; |
break; |
} |
} |
|
|
if (pfd.revents & POLLOUT) { |
if (pfd.revents & POLLOUT) { |
if (msgbuf_write(&cctx.ibuf.w) < 0) |
if (msgbuf_write(&ibuf->w) < 0) |
fatalx("msgbuf_write failed"); |
fatalx("msgbuf_write failed"); |
} |
} |
} |
} |
|
|
} |
} |
|
|
int |
int |
dispatch_imsg(struct client_ctx *cctx, const char *shellcmd, int *retcode) |
dispatch_imsg(struct imsgbuf *ibuf, const char *shellcmd, int *retcode) |
{ |
{ |
struct imsg imsg; |
struct imsg imsg; |
ssize_t n, datalen; |
ssize_t n, datalen; |
struct msg_print_data printdata; |
struct msg_print_data printdata; |
struct msg_shell_data shelldata; |
struct msg_shell_data shelldata; |
|
|
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) |
if ((n = imsg_read(ibuf)) == -1 || n == 0) |
fatalx("imsg_read failed"); |
fatalx("imsg_read failed"); |
|
|
for (;;) { |
for (;;) { |
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1) |
if ((n = imsg_get(ibuf, &imsg)) == -1) |
fatalx("imsg_get failed"); |
fatalx("imsg_get failed"); |
if (n == 0) |
if (n == 0) |
return (0); |
return (0); |
|
|
if (datalen != 0) |
if (datalen != 0) |
fatalx("bad MSG_READY size"); |
fatalx("bad MSG_READY size"); |
|
|
*retcode = client_main(cctx); |
client_main(); /* doesn't return */ |
return (-1); |
|
case MSG_VERSION: |
case MSG_VERSION: |
if (datalen != 0) |
if (datalen != 0) |
fatalx("bad MSG_VERSION size"); |
fatalx("bad MSG_VERSION size"); |