-
Notifications
You must be signed in to change notification settings - Fork 0
/
repl
executable file
·71 lines (60 loc) · 1.71 KB
/
repl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/rlwrap /usr/bin/php
<?php
$entryPoint = false;
// set to e.g. dirname(__FILE__) . "/base.php" to include before first command
$stdin = fopen("php://stdin", 'r');
if ($pid = pcntl_fork()) {
assert($pid >= 0);
// master: linger indefinitely so the terminal stays attached
while (1) sleep(999999);
}
declare(ticks = 1);
pcntl_signal(SIGCHLD, function(){}, false);
// signal should abort reading the okPipe in the tumbling parent
$includes = array();
while (1) {
echo ">> "; flush();
$line = fgets($stdin);
socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $okPipe);
if ($pid = pcntl_fork()) {
assert($pid >= 0);
// tumbling parent: wait for result on pipe
while (!pcntl_waitpid($pid,$status,WNOHANG)) {
if (@socket_read($okPipe[0], 1) == 'x')
exit(0); // child execution worked well.. we can exit
}
echo "php fork died while executing\n";
}
else {
// tumbling child: try to execute $line
// check includes
if (!$includes && $entryPoint) {
// initial include
include $entryPoint;
}
else {
$files = get_included_files();
foreach ($files as $f) {
$mtime = @filemtime($f);
if ($mtime && isset($includes[$f]) && $includes[$f] != $mtime) {
if (function_exists('runkit_import')) {
echo "reloading $f\n";
runkit_import($f);
}
else echo "warning: $f has changed\n";
}
}
}
//$line = preg_replace('/(;|^)([^;]+?);?$/', '$1return $2;', $line);
$res = eval("return $line;");
print_r($res); echo "\n";
// construct new includes map
$files = get_included_files();
foreach ($files as $f) {
$mtime = @filemtime($f);
if ($mtime) $includes[$f] = $mtime;
}
// tell parent all is well so it can quit
socket_write($okPipe[1], 'x');
}
}