Skip to content

Commit 87b556e

Browse files
committed
simple tcp interface for phpdbg
1 parent 2299584 commit 87b556e

File tree

3 files changed

+130
-5
lines changed

3 files changed

+130
-5
lines changed

phpdbg.c

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
#include "phpdbg_utils.h"
2828
#include "phpdbg_set.h"
2929

30+
#include <sys/socket.h>
31+
#include <sys/select.h>
32+
#include <sys/time.h>
33+
#include <sys/types.h>
34+
#include <unistd.h>
35+
#include <arpa/inet.h>
36+
3037
ZEND_DECLARE_MODULE_GLOBALS(phpdbg);
3138

3239
#if PHP_VERSION_ID >= 50500
@@ -477,6 +484,7 @@ const opt_struct OPTIONS[] = { /* {{{ */
477484
{'O', 1, "opline log"},
478485
{'r', 0, "run"},
479486
{'E', 0, "step-through-eval"},
487+
{'l', 1, "listen"},
480488
{'-', 0, NULL}
481489
}; /* }}} */
482490

@@ -535,6 +543,90 @@ static inline void phpdbg_sigint_handler(int signo) /* {{{ */
535543
}
536544
} /* }}} */
537545

546+
int phpdbg_open_socket(short port) /* {{{ */
547+
{
548+
int fd = socket(AF_INET, SOCK_STREAM, 0);
549+
550+
switch (fd) {
551+
case -1:
552+
return -1;
553+
554+
default: {
555+
int boolean = 1;
556+
557+
switch (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &boolean, sizeof(int))) {
558+
case -1:
559+
close(fd);
560+
return -2;
561+
562+
default: {
563+
struct sockaddr_in address;
564+
565+
memset(&address, 0, sizeof(address));
566+
567+
address.sin_port = htons(port);
568+
address.sin_family = AF_INET;
569+
570+
if (!inet_pton(AF_INET, "127.0.0.1", &address.sin_addr)) {
571+
close(fd);
572+
return -3;
573+
}
574+
575+
switch (bind(fd, (struct sockaddr *)&address, sizeof(address))) {
576+
case -1:
577+
close(fd);
578+
return -4;
579+
580+
default: {
581+
listen(fd, 5);
582+
}
583+
}
584+
}
585+
}
586+
}
587+
}
588+
589+
return fd;
590+
} /* }}} */
591+
592+
int phpdbg_open_sockets(short listen[2], FILE* streams[2]) /* {{{ */
593+
{
594+
int sockets[2] = {
595+
phpdbg_open_socket(listen[0]),
596+
phpdbg_open_socket(listen[1])
597+
};
598+
int accepted[2] = {-1, -1};
599+
600+
streams[0] = NULL;
601+
streams[1] = NULL;
602+
603+
if (sockets[0] < 0 || sockets[1] < 0) {
604+
if (sockets[0] >= 0)
605+
close(sockets[0]);
606+
if (sockets[1] >= 0)
607+
close(sockets[1]);
608+
return FAILURE;
609+
}
610+
611+
{
612+
struct sockaddr_in address;
613+
socklen_t size = sizeof(address);
614+
615+
memset(&address, 0, size);
616+
accepted[0] = accept(
617+
sockets[0], &address, &size);
618+
619+
memset(&address, 0, size);
620+
accepted[1] = accept(
621+
sockets[1], &address, &size);
622+
}
623+
624+
streams[0] = fdopen(accepted[0], "r");
625+
streams[1] = fdopen(accepted[1], "w");
626+
627+
return SUCCESS;
628+
} /* }}} */
629+
538630
int main(int argc, char **argv) /* {{{ */
539631
{
540632
sapi_module_struct *phpdbg = &phpdbg_sapi_module;
@@ -556,6 +648,8 @@ int main(int argc, char **argv) /* {{{ */
556648
int run = 0;
557649
int step = 0;
558650
char *bp_tmp_file;
651+
short listen[2];
652+
FILE* streams[2] = {NULL, NULL};
559653

560654
#ifdef ZTS
561655
void ***tsrm_ls;
@@ -599,7 +693,9 @@ int main(int argc, char **argv) /* {{{ */
599693
opt = 0;
600694
run = 0;
601695
step = 0;
602-
696+
listen[0] = 0;
697+
listen[1] = 0;
698+
603699
while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
604700
switch (opt) {
605701
case 'r':
@@ -693,9 +789,23 @@ int main(int argc, char **argv) /* {{{ */
693789
case 'q': /* hide banner */
694790
show_banner = 0;
695791
break;
792+
793+
/* if you pass a listen port, we will accept input on listen port */
794+
/* and write output to listen port * 2 */
795+
796+
case 'l': /* set listen settings */
797+
listen[0] = atoi(php_optarg);
798+
listen[1] = (listen[0] * 2);
799+
break;
696800
}
697801
}
698802

803+
if (!cleaning &&
804+
(listen[0] && listen[1])) {
805+
phpdbg_open_sockets(listen, streams);
806+
/* now is a sensible time to announce listen settings on the console */
807+
}
808+
699809
phpdbg->ini_defaults = phpdbg_ini_defaults;
700810
phpdbg->phpinfo_as_text = 1;
701811
phpdbg->php_ini_ignore_cwd = 1;
@@ -733,10 +843,21 @@ int main(int argc, char **argv) /* {{{ */
733843

734844
PG(modules_activated) = 0;
735845

736-
/* set up basic io here */
737-
PHPDBG_G(io)[PHPDBG_STDIN] = stdin;
738-
PHPDBG_G(io)[PHPDBG_STDOUT] = stdout;
739-
PHPDBG_G(io)[PHPDBG_STDERR] = stderr;
846+
/* setup io here */
847+
if (streams[0] && streams[1]) {
848+
PHPDBG_G(flags) |= PHPDBG_IS_REMOTE;
849+
/* remote console */
850+
PHPDBG_G(io)[PHPDBG_STDIN] = streams[0];
851+
PHPDBG_G(io)[PHPDBG_STDOUT] = streams[1];
852+
PHPDBG_G(io)[PHPDBG_STDERR] = stderr;
853+
854+
signal(SIGPIPE, SIG_IGN);
855+
} else {
856+
/* local console */
857+
PHPDBG_G(io)[PHPDBG_STDIN] = stdin;
858+
PHPDBG_G(io)[PHPDBG_STDOUT] = stdout;
859+
PHPDBG_G(io)[PHPDBG_STDERR] = stderr;
860+
}
740861

741862
if (exec) { /* set execution context */
742863
PHPDBG_G(exec) = phpdbg_resolve_path(

phpdbg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
#define PHPDBG_IS_SIGNALED (1<<20)
127127
#define PHPDBG_IS_INTERACTIVE (1<<21)
128128
#define PHPDBG_IS_BP_ENABLED (1<<22)
129+
#define PHPDBG_IS_REMOTE (1<<23)
129130

130131
#ifndef _WIN32
131132
# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED)

phpdbg_cmd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ PHPDBG_API phpdbg_input_t *phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */
219219

220220
if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) {
221221
if (buffered == NULL) {
222+
223+
fflush(PHPDBG_G(io)[PHPDBG_STDOUT]);
224+
222225
#ifndef HAVE_LIBREADLINE
223226
char buf[PHPDBG_MAX_CMD];
224227
if (!phpdbg_write(phpdbg_get_prompt(TSRMLS_C)) ||

0 commit comments

Comments
 (0)