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
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "phpdbg_io.h"
22
ZEND_EXTERN_MODULE_GLOBALS(phpdbg)23 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
24
25 /* is easy to generalize ... but not needed for now */
26 PHPDBG_API int phpdbg_consume_stdin_line(char *buf) {
27 int bytes = PHPDBG_G(input_buflen), len = 0;
28
29 if (PHPDBG_G(input_buflen)) {
30 memcpy(buf, PHPDBG_G(input_buffer), bytes);
31 }
32
33 PHPDBG_G(last_was_newline) = 1;
34
35 do {
36 int i;
37 if (bytes <= 0) {
38 continue;
39 }
40
41 for (i = len; i < len + bytes; i++) {
42 if (buf[i] == '\x03') {
43 if (i != len + bytes - 1) {
44 memmove(buf + i, buf + i + 1, len + bytes - i - 1);
45 }
46 len--;
47 i--;
48 continue;
49 }
50 if (buf[i] == '\n') {
51 PHPDBG_G(input_buflen) = len + bytes - 1 - i;
52 if (PHPDBG_G(input_buflen)) {
53 memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen));
54 }
55 if (i != PHPDBG_MAX_CMD - 1) {
56 buf[i + 1] = 0;
57 }
58 return i;
59 }
60 }
61
62 len += bytes;
63 } while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1)) > 0);
64
65 if (bytes <= 0) {
66 PHPDBG_G(flags) |= PHPDBG_IS_QUITTING;
67 zend_bailout();
68 }
69
70 return bytes;
71 }
72
phpdbg_mixed_read(int fd,char * ptr,int len,int tmo)73 PHPDBG_API int phpdbg_mixed_read(int fd, char *ptr, int len, int tmo) {
74 int ret;
75
76 do {
77 ret = read(fd, ptr, len);
78 } while (ret == -1 && errno == EINTR);
79
80 return ret;
81 }
82
phpdbg_output_pager(int fd,const char * ptr,int len)83 static int phpdbg_output_pager(int fd, const char *ptr, int len) {
84 int count = 0, bytes = 0;
85 const char *p = ptr, *endp = ptr + len;
86
87 while ((p = memchr(p, '\n', endp - p))) {
88 count++;
89 p++;
90
91 if (count % PHPDBG_G(lines) == 0) {
92 bytes += write(fd, ptr + bytes, (p - ptr) - bytes);
93
94 if (memchr(p, '\n', endp - p)) {
95 char buf[PHPDBG_MAX_CMD];
96 zend_quiet_write(fd, ZEND_STRL("\r---Type <return> to continue or q <return> to quit---"));
97 phpdbg_consume_stdin_line(buf);
98 if (*buf == 'q') {
99 break;
100 }
101 zend_quiet_write(fd, "\r", 1);
102 } else break;
103 }
104 }
105 if (bytes && count % PHPDBG_G(lines) != 0) {
106 bytes += write(fd, ptr + bytes, len - bytes);
107 } else if (!bytes) {
108 bytes += write(fd, ptr, len);
109 }
110 return bytes;
111 }
112
phpdbg_mixed_write(int fd,const char * ptr,int len)113 PHPDBG_API int phpdbg_mixed_write(int fd, const char *ptr, int len) {
114 if ((PHPDBG_G(flags) & PHPDBG_HAS_PAGINATION)
115 && PHPDBG_G(io)[PHPDBG_STDOUT].fd == fd
116 && PHPDBG_G(lines) > 0) {
117 return phpdbg_output_pager(fd, ptr, len);
118 }
119
120 return write(fd, ptr, len);
121 }
122