tmate-decoder.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #include "tmate.h"
  2. #include "tmate-protocol.h"
  3. static void handle_notify(__unused struct tmate_session *session,
  4. struct tmate_unpacker *uk)
  5. {
  6. char *msg = unpack_string(uk);
  7. tmate_status_message("%s", msg);
  8. free(msg);
  9. }
  10. static void handle_legacy_pane_key(__unused struct tmate_session *_session,
  11. struct tmate_unpacker *uk)
  12. {
  13. struct session *s;
  14. struct window *w;
  15. struct window_pane *wp;
  16. int key = unpack_int(uk);
  17. s = RB_MIN(sessions, &sessions);
  18. if (!s)
  19. return;
  20. w = s->curw->window;
  21. if (!w)
  22. return;
  23. wp = w->active;
  24. if (!wp)
  25. return;
  26. window_pane_key(wp, NULL, s, key, NULL);
  27. }
  28. static struct window_pane *find_window_pane(struct session *s, int pane_id)
  29. {
  30. struct window *w;
  31. if (pane_id != -1)
  32. return window_pane_find_by_id(pane_id);
  33. w = s->curw->window;
  34. if (!w)
  35. return NULL;
  36. return w->active;
  37. }
  38. static void handle_pane_key(__unused struct tmate_session *_session,
  39. struct tmate_unpacker *uk)
  40. {
  41. struct session *s;
  42. struct window_pane *wp;
  43. int pane_id = unpack_int(uk);
  44. key_code key = unpack_int(uk);
  45. s = RB_MIN(sessions, &sessions);
  46. if (!s)
  47. return;
  48. wp = find_window_pane(s, pane_id);
  49. if (!wp)
  50. return;
  51. window_pane_key(wp, NULL, s, key, NULL);
  52. }
  53. static void handle_resize(struct tmate_session *session,
  54. struct tmate_unpacker *uk)
  55. {
  56. session->min_sx = unpack_int(uk);
  57. session->min_sy = unpack_int(uk);
  58. recalculate_sizes();
  59. }
  60. extern char **cfg_causes;
  61. extern u_int cfg_ncauses;
  62. static void handle_exec_cmd_str(__unused struct tmate_session *session,
  63. struct tmate_unpacker *uk)
  64. {
  65. struct cmd_q *cmd_q;
  66. struct cmd_list *cmdlist;
  67. char *cause;
  68. u_int i;
  69. int client_id = unpack_int(uk);
  70. char *cmd_str = unpack_string(uk);
  71. if (cmd_string_parse(cmd_str, &cmdlist, NULL, 0, &cause) != 0) {
  72. tmate_failed_cmd(client_id, cause);
  73. free(cause);
  74. goto out;
  75. }
  76. cmd_q = cmdq_new(NULL);
  77. cmdq_run(cmd_q, cmdlist, NULL);
  78. cmd_list_free(cmdlist);
  79. cmdq_free(cmd_q);
  80. /* error messages land in cfg_causes */
  81. for (i = 0; i < cfg_ncauses; i++) {
  82. tmate_failed_cmd(client_id, cfg_causes[i]);
  83. free(cfg_causes[i]);
  84. }
  85. free(cfg_causes);
  86. cfg_causes = NULL;
  87. cfg_ncauses = 0;
  88. out:
  89. free(cmd_str);
  90. }
  91. static void handle_exec_cmd(__unused struct tmate_session *session,
  92. struct tmate_unpacker *uk)
  93. {
  94. struct cmd_q *cmd_q;
  95. struct cmd_list *cmdlist;
  96. struct cmd *cmd;
  97. char *cause;
  98. u_int i;
  99. unsigned int argc;
  100. char **argv;
  101. int client_id = unpack_int(uk);
  102. argc = uk->argc;
  103. argv = xmalloc(sizeof(char *) * argc);
  104. for (i = 0; i < argc; i++)
  105. argv[i] = unpack_string(uk);
  106. cmd = cmd_parse(argc, argv, NULL, 0, &cause);
  107. if (!cmd) {
  108. tmate_failed_cmd(client_id, cause);
  109. free(cause);
  110. goto out;
  111. }
  112. cmdlist = xcalloc(1, sizeof *cmdlist);
  113. cmdlist->references = 1;
  114. TAILQ_INIT(&cmdlist->list);
  115. TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
  116. cmd_q = cmdq_new(NULL);
  117. cmdq_run(cmd_q, cmdlist, NULL);
  118. cmd_list_free(cmdlist);
  119. cmdq_free(cmd_q);
  120. /* error messages land in cfg_causes */
  121. for (i = 0; i < cfg_ncauses; i++) {
  122. tmate_failed_cmd(client_id, cfg_causes[i]);
  123. free(cfg_causes[i]);
  124. }
  125. free(cfg_causes);
  126. cfg_causes = NULL;
  127. cfg_ncauses = 0;
  128. out:
  129. cmd_free_argv(argc, argv);
  130. }
  131. static void maybe_save_reconnection_data(struct tmate_session *session,
  132. const char *name, const char *value)
  133. {
  134. if (!strcmp(name, "tmate_reconnection_data")) {
  135. free(session->reconnection_data);
  136. session->reconnection_data = xstrdup(value);
  137. }
  138. }
  139. static void handle_set_env(struct tmate_session *session,
  140. struct tmate_unpacker *uk)
  141. {
  142. char *name = unpack_string(uk);
  143. char *value = unpack_string(uk);
  144. tmate_set_env(name, value);
  145. maybe_save_reconnection_data(session, name, value);
  146. free(name);
  147. free(value);
  148. }
  149. static void handle_ready(struct tmate_session *session,
  150. __unused struct tmate_unpacker *uk)
  151. {
  152. session->tmate_env_ready = 1;
  153. signal_waiting_clients("tmate-ready");
  154. }
  155. void tmate_dispatch_slave_message(struct tmate_session *session,
  156. struct tmate_unpacker *uk)
  157. {
  158. int cmd = unpack_int(uk);
  159. switch (cmd) {
  160. #define dispatch(c, f) case c: f(session, uk); break
  161. dispatch(TMATE_IN_NOTIFY, handle_notify);
  162. dispatch(TMATE_IN_LEGACY_PANE_KEY, handle_legacy_pane_key);
  163. dispatch(TMATE_IN_RESIZE, handle_resize);
  164. dispatch(TMATE_IN_EXEC_CMD_STR, handle_exec_cmd_str);
  165. dispatch(TMATE_IN_SET_ENV, handle_set_env);
  166. dispatch(TMATE_IN_READY, handle_ready);
  167. dispatch(TMATE_IN_PANE_KEY, handle_pane_key);
  168. dispatch(TMATE_IN_EXEC_CMD, handle_exec_cmd);
  169. default: tmate_info("Bad message type: %d", cmd);
  170. }
  171. }