phpdbg_io.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Anatol Belski <ab@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "phpdbg_io.h"
  20. ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
  21. /* is easy to generalize ... but not needed for now */
  22. PHPDBG_API int phpdbg_consume_stdin_line(char *buf) {
  23. int bytes = PHPDBG_G(input_buflen), len = 0;
  24. if (PHPDBG_G(input_buflen)) {
  25. memcpy(buf, PHPDBG_G(input_buffer), bytes);
  26. }
  27. PHPDBG_G(last_was_newline) = 1;
  28. do {
  29. int i;
  30. if (bytes <= 0) {
  31. continue;
  32. }
  33. for (i = len; i < len + bytes; i++) {
  34. if (buf[i] == '\x03') {
  35. if (i != len + bytes - 1) {
  36. memmove(buf + i, buf + i + 1, len + bytes - i - 1);
  37. }
  38. len--;
  39. i--;
  40. continue;
  41. }
  42. if (buf[i] == '\n') {
  43. PHPDBG_G(input_buflen) = len + bytes - 1 - i;
  44. if (PHPDBG_G(input_buflen)) {
  45. memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen));
  46. }
  47. if (i != PHPDBG_MAX_CMD - 1) {
  48. buf[i + 1] = 0;
  49. }
  50. return i;
  51. }
  52. }
  53. len += bytes;
  54. } while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1)) > 0);
  55. if (bytes <= 0) {
  56. PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
  57. zend_bailout();
  58. }
  59. return bytes;
  60. }
  61. PHPDBG_API int phpdbg_mixed_read(int fd, char *ptr, int len, int tmo) {
  62. int ret;
  63. do {
  64. ret = read(fd, ptr, len);
  65. } while (ret == -1 && errno == EINTR);
  66. return ret;
  67. }
  68. static int phpdbg_output_pager(int fd, const char *ptr, int len) {
  69. int count = 0, bytes = 0;
  70. const char *p = ptr, *endp = ptr + len;
  71. while ((p = memchr(p, '\n', endp - p))) {
  72. count++;
  73. p++;
  74. if (count % PHPDBG_G(lines) == 0) {
  75. bytes += write(fd, ptr + bytes, (p - ptr) - bytes);
  76. if (memchr(p, '\n', endp - p)) {
  77. char buf[PHPDBG_MAX_CMD];
  78. zend_quiet_write(fd, ZEND_STRL("\r---Type <return> to continue or q <return> to quit---"));
  79. phpdbg_consume_stdin_line(buf);
  80. if (*buf == 'q') {
  81. break;
  82. }
  83. zend_quiet_write(fd, "\r", 1);
  84. } else break;
  85. }
  86. }
  87. if (bytes && count % PHPDBG_G(lines) != 0) {
  88. bytes += write(fd, ptr + bytes, len - bytes);
  89. } else if (!bytes) {
  90. bytes += write(fd, ptr, len);
  91. }
  92. return bytes;
  93. }
  94. PHPDBG_API int phpdbg_mixed_write(int fd, const char *ptr, int len) {
  95. if ((PHPDBG_G(flags) & PHPDBG_HAS_PAGINATION)
  96. && PHPDBG_G(io)[PHPDBG_STDOUT].fd == fd
  97. && PHPDBG_G(lines) > 0) {
  98. return phpdbg_output_pager(fd, ptr, len);
  99. }
  100. return write(fd, ptr, len);
  101. }