Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

211 linhas
5.2 KiB

  1. /*
  2. * term swallow a terminal-based application
  3. * Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. #include "config.h"
  14. #include "common.h"
  15. #if !defined __KERNEL__
  16. # include <stdio.h>
  17. # include <string.h>
  18. # include <stdlib.h>
  19. # include <unistd.h>
  20. # include <fcntl.h>
  21. # if defined HAVE_PTY_H
  22. # include <pty.h> /* for openpty and forkpty */
  23. # endif
  24. #endif
  25. #include "cucul.h"
  26. #include "caca.h"
  27. static int run_in_pty(char *cmd);
  28. int main(int argc, char **argv)
  29. {
  30. static cucul_canvas_t *cv, *app[2];
  31. static caca_display_t *dp;
  32. unsigned char *buf[2];
  33. long int total[2];
  34. int ptyfd[2], pty = 0;
  35. int w, h, eof = 0;
  36. if(argc < 3)
  37. {
  38. fprintf(stderr, "usage: %s <cmd1> <cmd2>\n", argv[0]);
  39. fprintf(stderr, "eg. \"%s bash bash\"\n", argv[0]);
  40. return 1;
  41. }
  42. cv = cucul_create_canvas(80 + 7, 24 + 7);
  43. dp = caca_create_display(cv);
  44. if(!dp)
  45. return 1;
  46. // w = cucul_get_canvas_width(cv) - 7;
  47. // h = cucul_get_canvas_height(cv) - 7;
  48. w = 80; h = 24;
  49. if(w < 0 || h < 0)
  50. return 1;
  51. app[0] = cucul_create_canvas(w, h);
  52. app[1] = cucul_create_canvas(w, h);
  53. cucul_set_color_ansi(cv, CUCUL_LIGHTRED, CUCUL_BLACK);
  54. cucul_draw_thin_box(cv, pty * 5, pty * 5,
  55. 80 + pty * 5 + 1, 24 + pty * 5 + 1);
  56. caca_refresh_display(dp);
  57. buf[0] = buf[1] = NULL;
  58. total[0] = total[1] = 0;
  59. ptyfd[0] = run_in_pty(argv[1]);
  60. ptyfd[1] = run_in_pty(argv[2]);
  61. if(ptyfd[0] < 0 || ptyfd[1] < 0)
  62. return -1;
  63. fcntl(ptyfd[0], F_SETFL, O_NDELAY);
  64. fcntl(ptyfd[1], F_SETFL, O_NDELAY);
  65. for(;;)
  66. {
  67. struct timeval tv;
  68. fd_set fdset;
  69. caca_event_t ev;
  70. int i, ret, refresh = 0;
  71. ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
  72. if(ret && ev.type & CACA_EVENT_KEY_PRESS)
  73. {
  74. switch(ev.data.key.ch)
  75. {
  76. case CACA_KEY_CTRL_A:
  77. cucul_draw_box(cv, pty * 5, pty * 5,
  78. 80 + pty * 5 + 1, 24 + pty * 5 + 1, ' ');
  79. pty = 1 - pty;
  80. refresh = 1;
  81. break;
  82. case CACA_KEY_UP:
  83. write(ptyfd[pty], "\x1b[A", 3); break;
  84. case CACA_KEY_DOWN:
  85. write(ptyfd[pty], "\x1b[B", 3); break;
  86. case CACA_KEY_RIGHT:
  87. write(ptyfd[pty], "\x1b[C", 3); break;
  88. case CACA_KEY_LEFT:
  89. write(ptyfd[pty], "\x1b[D", 3); break;
  90. default:
  91. write(ptyfd[pty], &ev.data.key.ch, 1); break;
  92. }
  93. }
  94. /* Read data, if any */
  95. FD_ZERO(&fdset);
  96. FD_SET(ptyfd[0], &fdset);
  97. FD_SET(ptyfd[1], &fdset);
  98. tv.tv_sec = 0;
  99. tv.tv_usec = 50000;
  100. ret = select(ptyfd[0] + ptyfd[1] + 1, &fdset, NULL, NULL, &tv);
  101. if(ret < 0)
  102. {
  103. if(!total[0] && !total[1])
  104. break;
  105. }
  106. else if(ret) for(i = 0; i < 2; i++)
  107. {
  108. if(FD_ISSET(ptyfd[i], &fdset))
  109. {
  110. ssize_t n;
  111. buf[i] = realloc(buf[i], total[i] + 4096);
  112. n = read(ptyfd[i], buf[i] + total[i], 4096);
  113. if(n > 0)
  114. total[i] += n;
  115. else if(n == 0 || errno != EWOULDBLOCK)
  116. eof = 1;
  117. }
  118. }
  119. for(i = 0; i < 2; i++) if(total[i])
  120. {
  121. unsigned long int bytes;
  122. bytes = cucul_import_memory(app[i], buf[i], total[i], "utf8");
  123. if(bytes > 0)
  124. {
  125. total[i] -= bytes;
  126. memmove(buf[i], buf[i] + bytes, total[i]);
  127. refresh = 1;
  128. }
  129. }
  130. if(refresh)
  131. {
  132. cucul_blit(cv, 5 * !pty + 1, 5 * !pty + 1, app[!pty], NULL);
  133. cucul_blit(cv, 5 * pty + 1, 5 * pty + 1, app[pty], NULL);
  134. cucul_draw_thin_box(cv, pty * 5, pty * 5,
  135. 80 + pty * 5 + 1, 24 + pty * 5 + 1);
  136. caca_refresh_display(dp);
  137. }
  138. if(eof && !total[0] && !total[1])
  139. break;
  140. }
  141. caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, -1);
  142. /* Clean up */
  143. caca_free_display(dp);
  144. cucul_free_canvas(cv);
  145. cucul_free_canvas(app[0]);
  146. cucul_free_canvas(app[1]);
  147. return 0;
  148. }
  149. static int run_in_pty(char *cmd)
  150. {
  151. #if defined HAVE_PTY_H
  152. char **argv;
  153. int fd;
  154. pid_t pid;
  155. pid = forkpty(&fd, NULL, NULL, NULL);
  156. if(pid < 0)
  157. {
  158. fprintf(stderr, "forkpty() error\n");
  159. return -1;
  160. }
  161. else if(pid == 0)
  162. {
  163. putenv("CACA_DRIVER=slang");
  164. argv = malloc(2 * sizeof(char *));
  165. argv[0] = cmd;
  166. argv[1] = NULL;
  167. execvp(cmd, argv);
  168. fprintf(stderr, "execvp() error\n");
  169. return -1;
  170. }
  171. return fd;
  172. #else
  173. fprintf(stderr, "forkpty() not available\n");
  174. return -1;
  175. #endif
  176. }