Skip to content

Fix and simplify restoring TTY mode when ext-readline is not in use #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions src/Readline.php
Original file line number Diff line number Diff line change
Expand Up @@ -491,27 +491,6 @@ public function getDrawString()
return $output;
}

/**
* Clears the current input prompt (if any)
*
* Usually, there should be no need to call this method manually. It will
* be invoked automatically whenever we detect that output needs to be
* written in place of the current prompt. The prompt will be rewritten
* after clearing the prompt and writing the output.
*
* @return self
* @see Stdio::write() which is responsible for invoking this method
* @internal
*/
public function clear()
{
if ($this->prompt !== '' || ($this->echo !== false && $this->linebuffer !== '')) {
$this->output->write("\r\033[K");
}

return $this;
}

/** @internal */
public function onKeyBackspace()
{
Expand Down
25 changes: 10 additions & 15 deletions src/Stdio.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,7 @@ public function end($data = null)
$this->ending = true;

// clear readline output, close input and end output
$this->readline->setInput('')->setPrompt('')->clear();
$this->restoreTtyMode();
$this->readline->setInput('')->setPrompt('');
$this->input->close();
$this->output->end();
}
Expand All @@ -195,8 +194,7 @@ public function close()
$this->closed = true;

// clear readline output and then close
$this->readline->setInput('')->setPrompt('')->clear()->close();
$this->restoreTtyMode();
$this->readline->setInput('')->setPrompt('');
$this->input->close();
$this->output->close();
}
Expand Down Expand Up @@ -227,6 +225,8 @@ public function handleEnd()
/** @internal */
public function handleCloseInput()
{
$this->restoreTtyMode();

if (!$this->output->isWritable()) {
$this->close();
}
Expand All @@ -249,9 +249,9 @@ private function restoreTtyMode()
// remove dummy readline handler to turn to default input mode
$this->usesExtReadlineHandler = false;
readline_callback_handler_remove();
} elseif ($this->originalTtyMode !== null && $this->isTty()) {
} elseif ($this->originalTtyMode !== null && is_resource(STDIN) && $this->isTty()) {
// Reset stty so it behaves normally again
shell_exec(sprintf('stty %s', $this->originalTtyMode));
shell_exec('stty ' . escapeshellarg($this->originalTtyMode));
Copy link
Owner Author

@clue clue Aug 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This simple change introduces a subtle bug fixed in #78. The originalTtyMode contains a trailing newline, passing this to escapeshellarg() means that this will now be passed as part of the argument to the stty bin which rejects this format because it does not expect a trailing newline.

$this->originalTtyMode = null;
}

Expand Down Expand Up @@ -344,15 +344,10 @@ private function isTty()
// For what it's worth, checking for device gid 5 (tty) is less reliable.
// @link http://man7.org/linux/man-pages/man7/inode.7.html
// @link https://www.kernel.org/doc/html/v4.11/admin-guide/devices.html#terminal-devices
if (is_resource(STDIN)) {
$stat = fstat(STDIN);
$mode = isset($stat['mode']) ? ($stat['mode'] & 0170000) : 0;
$major = isset($stat['dev']) ? (($stat['dev'] >> 8) & 0xff) : 0;
$stat = fstat(STDIN);
$mode = isset($stat['mode']) ? ($stat['mode'] & 0170000) : 0;
$major = isset($stat['dev']) ? (($stat['dev'] >> 8) & 0xff) : 0;

if ($mode === 0020000 && $major >= 2 && $major <= 143 && ($major <=5 || $major >= 128)) {
return true;
}
}
return false;
return ($mode === 0020000 && $major >= 2 && $major <= 143 && ($major <=5 || $major >= 128));
}
}