43 Commits
0.2.1 ... 0.4.1

Author SHA1 Message Date
macintoshplus
d1c4cdc291 bump version to 0.4.1 2026-02-27 11:56:58 +01:00
macintoshplus
1931258612 🐛 apply patch for PHP 8 Thanks @arekm
📝 add readme
2026-02-27 11:55:09 +01:00
macintoshplus
f2b2ca9e3f add config PIE and GitHub Action 2026-02-26 22:08:01 +01:00
Simon Bazley
403fa58b6f Merge pull request #3 from krejcipetr/master
Repair the returning matches
2024-08-05 11:06:50 +01:00
Simon Bazley
832872beac Merge pull request #5 from lachbaer/fix_match_array
Fix issue #4 - match array not initialized
2024-08-05 11:06:21 +01:00
Simon Bazley
3fb8cf045d Merge pull request #6 from RobWei/master
Added code support for PHP 8
2024-08-05 11:05:51 +01:00
RobWei
60eb6b9f16 Added code support for PHP 8 2024-01-23 11:17:56 +01:00
Eik Rentzow
cc2e72e3d2 Fix issue #4 - match array not initialized
Done like in function php_pcre_match_impl() of PCRE module.
2023-02-28 08:14:33 +01:00
Petr Krejčí
d19b005e00 Repair the returning matches 2022-12-13 21:55:15 +01:00
Simon Bazley
9d83d267c2 Updated package.xml for 0.4.0 release 2020-01-13 17:42:12 +00:00
sibaz
0fdba09ee3 Added reference to /usr/lib64/tcl*/tclConfig.sh to support Centos builds
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@348327 c90b9560-bf6c-de11-be94-00142212c4b1
2019-11-20 12:09:22 +00:00
sibaz
7423b65a2e Added code to support PHP 7
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@348326 c90b9560-bf6c-de11-be94-00142212c4b1
2019-11-20 12:05:44 +00:00
michael
9ff8bd236f Upgraded PHP LICENSE to version 3.01. Released a new version.
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337814 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 17:46:51 +00:00
remi
962f488073 fix global init/shudown (segfault on ZTS build)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337812 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 16:02:10 +00:00
remi
7e6b652293 add LICENSE + missing files in package.xml
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337811 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 15:32:52 +00:00
remi
6fafe17e77 set max version as not yet compatible with php 7
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337810 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 15:19:21 +00:00
remi
18ea03b802 fix build when PHP_LIBDIR = lib64 (RPM distro)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337809 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 15:15:49 +00:00
michael
a291a8ff3b Increment version
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337808 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 12:31:25 +00:00
michael
48d03837f9 Fixed #70458
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@337807 c90b9560-bf6c-de11-be94-00142212c4b1
2015-09-11 12:29:29 +00:00
michael
5fdde4afbf Fixed setting boolea value "expect.loguser"
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@334336 c90b9560-bf6c-de11-be94-00142212c4b1
2014-07-20 16:29:12 +00:00
michael
98a048f820 Fixed compilation issues (bug #59916)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@319689 c90b9560-bf6c-de11-be94-00142212c4b1
2011-11-22 16:27:35 +00:00
michael
c02699dde7 removed duplicate print added in previous commit by mistake
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@312460 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-25 15:42:54 +00:00
michael
8133790622 Updated e-mail address
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@312443 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-24 19:35:30 +00:00
michael
178e5c07c5 Fixed Segmentation Fault on use (Bug #21578)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@312414 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-23 20:43:19 +00:00
michael
9b925ac532 Fixed Bug #22566 (Can't set ini variable)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@312401 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-23 11:36:40 +00:00
michael
4411953272 Provide a default value for expect.match_max (Bug #21823)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@307741 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-25 21:07:27 +00:00
michael
f80a041dac Fixed bug #16836 (introduce expect.match_max .ini parameter for asterisk match buffer size)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@307293 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-09 08:10:44 +00:00
michael
ea50047133 Fixed package version
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@304244 c90b9560-bf6c-de11-be94-00142212c4b1
2010-10-10 07:43:20 +00:00
michael
e16b06dede Fixed bug #18998 (Change expect.logfile on runtime leave file descriptor opened)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@304243 c90b9560-bf6c-de11-be94-00142212c4b1
2010-10-10 07:37:35 +00:00
johannes
80e342cf6b s,function_entry,zend_function_entry,
As announced in http://news.php.net/php.pecl.dev/7123


git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@297236 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-31 20:39:48 +00:00
pajoye
3e030e95e6 - update to package.xml v2
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@290265 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-05 11:49:14 +00:00
gwynne
e4b08ad2de fix a huge number of wrong MIME types. UGH.
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@284003 c90b9560-bf6c-de11-be94-00142212c4b1
2009-07-13 12:15:13 +00:00
shire
ce1a540073 fixes with arginfo for php-5.3 compatability
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@276740 c90b9560-bf6c-de11-be94-00142212c4b1
2009-03-03 23:21:38 +00:00
michael
f85ba457db add new release 0.2.5
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@269920 c90b9560-bf6c-de11-be94-00142212c4b1
2008-11-27 10:13:57 +00:00
michael
b7d18cfbb9 Fixed bug #14768 (configure error in Ubuntu 8.04)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@269919 c90b9560-bf6c-de11-be94-00142212c4b1
2008-11-27 10:10:11 +00:00
sfox
c5895a300f - Bring the majority of PECL extensions into line with macro/x.x.x versioning.
- Please use the -dev tag during the development cycle so that snapshots can easily be distinguished from releases.


git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@256435 c90b9560-bf6c-de11-be94-00142212c4b1
2008-03-31 09:37:00 +00:00
michael
925378d4ae adhere to C standard
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@244616 c90b9560-bf6c-de11-be94-00142212c4b1
2007-10-22 15:27:03 +00:00
michael
4e2f9109e1 Fixed Bug #6996 (Segmentation fault on expect_expectl)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@244548 c90b9560-bf6c-de11-be94-00142212c4b1
2007-10-21 16:55:44 +00:00
michael
f6251794c5 Make expect stream non-seekable (avoid warnings)
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@244508 c90b9560-bf6c-de11-be94-00142212c4b1
2007-10-20 07:15:40 +00:00
michael
2246eef8d7 Fixed #12268 (Capturing output via exp_loguser from within PHP / Apache):
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@244507 c90b9560-bf6c-de11-be94-00142212c4b1
2007-10-20 06:50:37 +00:00
michael
50ecf39bfd - Allow proceeding with configuration, even if expect.h was not found
- Fix bug #5950 (fopen("expect://") leaves zombies)


git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@242353 c90b9560-bf6c-de11-be94-00142212c4b1
2007-09-09 15:43:36 +00:00
michael
41baa86ee3 New package with bugfix.
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@215802 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-05 14:53:16 +00:00
michael
c206870203 Fix segfault on scenario with EXP_TIMEOUT.
git-svn-id: https://svn.php.net/repository/pecl/expect/trunk@215801 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-05 14:51:56 +00:00
15 changed files with 929 additions and 113 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: [macintoshplus] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
# patreon: # Replace with a single Patreon username
# open_collective: # Replace with a single Open Collective username
# ko_fi: # Replace with a single Ko-fi username
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
# liberapay: # Replace with a single Liberapay username
# issuehunt: # Replace with a single IssueHunt username
# otechie: # Replace with a single Otechie username
# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

130
.github/windows.yml vendored Normal file
View File

@@ -0,0 +1,130 @@
name: Publish Windows Releases
on:
workflow_dispatch: ~
release:
types: [created]
push:
branches: ['*']
permissions:
contents: write
jobs:
build-lib:
runs-on: windows-2022
strategy:
fail-fast: true
matrix:
# arch: [x64, x86]
arch: [x64]
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.arch }}
- name: Build the library
run: |
mkdir tcl
cd tcl
Invoke-WebRequest -Uri https://github.com/tcltk/tcl/releases/download/core-9-0-3/tcl9.0.3-src.tar.gz -outFile tcl.tar.gz
7z x tcl.tar.gz -so | 7z x -aoa -si -ttar -o"."
cd tcl9.0.3\win
mkdir install
nmake -f Makefile.vc all INSTALLDIR=.\install
nmake -f Makefile.vc install INSTALLDIR=.\install
7z a tcl.zip .\install
- name: Upload TCL library
uses: actions/upload-artifact@v5
with:
name: tcl-${{ matrix.arch }}
path: tcl\tcl9.0.3\win\tcl.zip
if-no-files-found: error
get-extension-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.extension-matrix.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Get the extension matrix
id: extension-matrix
uses: php/php-windows-builder/extension-matrix@v1
with:
arch-list: x64
php-version-list: "8.0"
ts-list: nts
build:
needs: [get-extension-matrix, build-lib]
runs-on: ${{ matrix.os }}
continue-on-error: false
strategy:
fail-fast: true
matrix: ${{fromJson(needs.get-extension-matrix.outputs.matrix)}}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: prepare
run: |
mkdir ..\tcl
- name: Download native lib
uses: actions/download-artifact@v5
with:
name: tcl-${{ matrix.arch }}
- name: Extract native lib
run: |
dir
7z x tcl.zip -o"..\tcl"
dir ..
dir ..\tcl
dir ..\tcl\install\include
dir ..\tcl\install\lib
- name: Setup PHP SDK
id: setup-php-windows
uses: php/setup-php-sdk@v0.12
with:
version: ${{ matrix.php-version }}
arch: ${{ matrix.arch }}
ts: ${{ matrix.ts }}
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.arch }}
toolset: ${{ steps.setup-php-windows.outputs.toolset }}
- run: phpize
- run: ./configure --with-expect --with-extra-includes="$($Env:GITHUB_WORKSPACE)..\tcl\install\include" --with-extra-libs="$($Env:GITHUB_WORKSPACE)..\tcl\install\lib" --with-prefix=${{steps.setup-php-windows.outputs.prefix}}
- run: nmake
- run: nmake test TESTS=tests
# - name: Upload TCL library
# uses: actions/upload-artifact@v5
# with:
# name: tcl-${{ matrix.php }}-${{ matrix.arch }}
# path: |
# win\install\
# - name: Build the extension
# uses: php/php-windows-builder/extension@v1
# with:
# php-version: ${{ matrix.php-version }}
# arch: ${{ matrix.arch }}
# ts: ${{ matrix.ts }}
# args: '--with-expect'
release:
runs-on: ubuntu-latest
needs: build
if: ${{ github.event_name == 'release' }}
steps:
- name: Upload artifact to the release
uses: php/php-windows-builder/release@v1
with:
release: ${{ github.event.release.tag_name }}

35
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: CI
on:
push:
branches: ['*']
jobs:
test-linux:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php-rel: ['8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
# php-rel: ['8.0']
ts-state: [ts, nts]
steps:
- uses: actions/checkout@v5
- name: Install dependencies
run: sudo apt-get install -y tcl-dev tcl-expect-dev
- name: Setup PHP
id: setup-php
uses: shivammathur/setup-php@v2
with:
php-version: '${{ matrix.php-rel }}'
env:
phpts: '${{ matrix.ts-state }}'
- name: build extension
env:
CPPFLAGS: -I/usr/include/tcl
run: |
phpize
./configure --with-expect
make
- name: run tests
run: make test

25
.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
/config.h
/config.h.in
/config.log
/config.nice
/config.status
/configure
/configure.ac
/expect.la
/expect.lo
/expect_fopen_wrapper.lo
/libtool
/Makefile
/Makefile.fragments
/Makefile.objects
/run-tests.php
/tests/*.diff
/tests/*.exp
/tests/*.log
/tests/*.php
/tests/*.out
/tests/*.sh
/.libs/
/autom4te.cache/
/build/
/modules/

68
LICENSE Normal file
View File

@@ -0,0 +1,68 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2014 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes PHP software, freely available from
<http://www.php.net/software/>".
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------
This software consists of voluntary contributions made by many
individuals on behalf of the PHP Group.
The PHP Group can be contacted via Email at group@php.net.
For more information on the PHP Group and the PHP project,
please see <http://www.php.net>.
PHP includes the Zend Engine, freely available at
<http://www.zend.com>.

71
README.md Normal file
View File

@@ -0,0 +1,71 @@
PHP extension for expect library
================================
This extension allows to interact with processes through PTY, using expect library.
This extension uses a Tcl/Expect library: https://www.tcl-lang.org/.
Original author: Michael Spector
> **Unable to build this extension for Windows because the TCL Expect is not available on Windows.**
Maintained branches:
| Version | Status |
|---------|------------------------------|
| master | unmaintened :x: |
| v0.x | maintened :white_check_mark: |
Maintained PHP Versions compatibility:
| PHP Version | Status |
|-------------|------------------------|
| 5.x | no :x: |
| 7.x | no :x: |
| 8.0 | yes :white_check_mark: |
| 8.1 | yes :white_check_mark: |
| 8.2 | yes :white_check_mark: |
| 8.3 | yes :white_check_mark: |
| 8.4 | yes :white_check_mark: |
| 8.5 | yes :white_check_mark: |
Installation system support:
| Platform | Status |
|----------|------------------------|
| PECL | no :x: |
| PIE | yes :white_check_mark: |
To install the extension, install the library `tcl-dev tcl-expect-dev` first.
Debian/Ubuntu/Mint:
```shell
sudo apt-get install tcl-dev tcl-expect-dev
```
Alpine Linux:
```shell
apk add tcl-dev expect-dev
```
Fedora:
```shell
sudo dnf install tcl-devel expect-devel
```
Arch Linux:
```shell
sudo pacman -S tcl expect
```
And use PIE (PHP Installer Extension) with a command like:
```bash
pie install php-win-ext/expect
```

21
composer.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "php-win-ext/expect",
"type": "php-ext",
"license": [
"PHP-3.01"
],
"authors": [
{
"name": "Michael Spector",
"email": "michael@php.net"
}
],
"require": {
"php": ">= 8.0.0"
},
"php-ext": {
"extension-name": "expect",
"os-families-exclude": ["windows"]
},
"description": "This extension allows to interact with processes through PTY, using expect library."
}

View File

@@ -5,21 +5,46 @@ dnl
PHP_ARG_WITH(expect,for expect support,
[ --with-expect[=DIR] Include expect support (requires libexpect >= 5.43.0).])
PHP_ARG_WITH(tcldir,specify path to Tcl needed by expect,
[ --with-tcldir[=DIR] Specify path to Tcl config script (tclConfig.sh).])
if test "$PHP_EXPECT" != "no"; then
for i in $PHP_EXPECT /usr/local /usr ; do
if test -f $i/include/expect.h; then
LIBEXPECT_DIR=$i
for i in $PHP_EXPECT/include/expect.h $PHP_EXPECT/include/*/expect.h \
/usr/local/include/expect.h /usr/local/include/*/expect.h \
/usr/include/expect.h /usr/include/*/expect.h ;
do
if test -f $i; then
LIBEXPECT_INCLUDE_DIR=`dirname $i`
LIBEXPECT_DIR=`dirname $LIBEXPECT_INCLUDE_DIR`
break
fi
done
if test -z "$LIBEXPECT_DIR"; then
AC_MSG_ERROR(expect extension requires libexpect version >= 5.43.0)
AC_MSG_CHECKING(for tcl version)
for i in $PHP_TCLDIR/tclConfig.sh \
/usr/lib/tcl*/tclConfig.sh \
/usr/lib64/tcl*/tclConfig.sh \
/usr/$PHP_LIBDIR/tcl*/tclConfig.sh \
/usr/local/lib/tcl*/tclConfig.sh \
/System/Library/Frameworks/Tcl.framework/Versions/Current/tclConfig.sh;
do
if test -f $i; then
. $i
break
fi
done
if test -n "$TCL_VERSION" ; then
AC_MSG_RESULT($TCL_VERSION in $TCL_PREFIX)
else
AC_MSG_ERROR([not found])
fi
PHP_ADD_LIBRARY_WITH_PATH(expect, $LIBEXPECT_DIR/lib, EXPECT_SHARED_LIBADD)
PHP_ADD_INCLUDE($LIBEXPECT_DIR/include)
PHP_ADD_LIBRARY_WITH_PATH(tcl$TCL_VERSION, $TCL_PREFIX/$PHP_LIBDIR, EXPECT_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(expect, $LIBEXPECT_DIR/$PHP_LIBDIR, EXPECT_SHARED_LIBADD)
PHP_ADD_INCLUDE($LIBEXPECT_INCLUDE_DIR)
PHP_NEW_EXTENSION(expect, expect.c expect_fopen_wrapper.c, $ext_shared)
PHP_SUBST(EXPECT_SHARED_LIBADD)
fi

397
expect.c
View File

@@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
| PHP Version 5, 7 and 8 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
@@ -12,23 +12,39 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Michael Spector <michael@zend.com> |
| Author: Michael Spector <michael@php.net> |
+----------------------------------------------------------------------+
*/
/* $ Id: $ */
#include "php_expect.h"
#include <string.h>
#include <errno.h>
ZEND_BEGIN_ARG_INFO_EX(arginfo_expect_popen, 0, 0, 1)
ZEND_ARG_INFO(0, command)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_expect_expectl, 0, 0, 2)
ZEND_ARG_INFO(0, stream)
ZEND_ARG_INFO(0, expect_cases)
ZEND_ARG_INFO(1, match)
ZEND_END_ARG_INFO()
/* {{{ expect_functions[] */
function_entry expect_functions[] = {
PHP_FE(expect_popen, NULL)
PHP_FE(expect_expectl, third_arg_force_ref)
zend_function_entry expect_functions[] = {
PHP_FE(expect_popen, arginfo_expect_popen)
PHP_FE(expect_expectl, arginfo_expect_expectl)
{ NULL, NULL, NULL }
};
/* }}} */
ZEND_DECLARE_MODULE_GLOBALS(expect)
static PHP_GINIT_FUNCTION(expect);
static PHP_GSHUTDOWN_FUNCTION(expect);
/* {{{ expect_module_entry
*/
zend_module_entry expect_module_entry = {
@@ -37,11 +53,15 @@ zend_module_entry expect_module_entry = {
expect_functions,
PHP_MINIT(expect),
PHP_MSHUTDOWN(expect),
NULL,
PHP_RINIT(expect),
NULL,
PHP_MINFO(expect),
"0.1",
STANDARD_MODULE_PROPERTIES
PHP_EXPECT_VERSION,
PHP_MODULE_GLOBALS(expect),
PHP_GINIT(expect),
PHP_GSHUTDOWN(expect),
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
@@ -49,13 +69,53 @@ zend_module_entry expect_module_entry = {
ZEND_GET_MODULE(expect)
#endif
/* {{{ php_expect_init_globals
*/
static PHP_GINIT_FUNCTION(expect)
{
expect_globals->logfile_stream = NULL;
}
/* }}} */
/* {{{ php_expect_destroy_globals
*/
static PHP_GSHUTDOWN_FUNCTION(expect)
{
if (expect_globals->logfile_stream) {
php_stream_close(expect_globals->logfile_stream);
}
}
/* }}} */
/* {{{ PHP_INI_MH
* */
static PHP_INI_MH(OnSetExpectTimeout)
{
if (new_value) {
exp_timeout = atoi(new_value);
#if PHP_MAJOR_VERSION >= 7
exp_timeout = atoi(ZSTR_VAL(new_value));
#else
exp_timeout = atoi(new_value);
#endif
return SUCCESS;
}
return FAILURE;
}
/* }}} */
/* {{{ PHP_INI_MH
* */
static PHP_INI_MH(OnSetExpectMatchMax)
{
if (new_value) {
#if PHP_MAJOR_VERSION >= 7
exp_match_max = atoi(ZSTR_VAL(new_value));
#else
exp_match_max = atoi(new_value);
#endif
return SUCCESS;
}
return FAILURE;
}
/* }}} */
@@ -65,12 +125,24 @@ static PHP_INI_MH(OnSetExpectTimeout)
static PHP_INI_MH(OnSetExpectLogUser)
{
if (new_value) {
if (strncasecmp("on", new_value, sizeof("on"))) {
exp_loguser = atoi(new_value);
} else {
#if PHP_MAJOR_VERSION >= 7
if (strncasecmp("on", ZSTR_VAL(new_value), sizeof("on")) == 0
|| strncasecmp("true", ZSTR_VAL(new_value), sizeof("true")) == 0
|| strncasecmp("yes", ZSTR_VAL(new_value), sizeof("yes")) == 0
|| strncasecmp("1", ZSTR_VAL(new_value), sizeof("1")) == 0) {
#else
if (strncasecmp("on", new_value, sizeof("on")) == 0
|| strncasecmp("true", new_value, sizeof("true")) == 0
|| strncasecmp("yes", new_value, sizeof("yes")) == 0
|| strncasecmp("1", new_value, sizeof("1")) == 0) {
#endif
exp_loguser = 1;
} else {
exp_loguser = 0;
}
return SUCCESS;
}
return FAILURE;
}
/* }}} */
@@ -79,12 +151,40 @@ static PHP_INI_MH(OnSetExpectLogUser)
* */
static PHP_INI_MH(OnSetExpectLogFile)
{
/* PHP streams cannot be opened during module startup because the resource
* list (EG(regular_list)) is not yet initialized. The logfile will be
* opened in RINIT once the request context is available. */
if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN) {
return SUCCESS;
}
if (EXPECT_G(logfile_stream)) {
php_stream_close(EXPECT_G(logfile_stream));
EXPECT_G(logfile_stream) = NULL;
exp_logfile = NULL;
exp_logfile_all = 0;
}
#if PHP_MAJOR_VERSION >= 7
if (ZSTR_LEN(new_value) > 0) {
php_stream* stream = php_stream_open_wrapper (ZSTR_VAL(new_value), "a", 0, NULL);
#else
if (new_value_length > 0) {
exp_logfile = fopen (new_value, "a");
if (!exp_logfile) {
php_error_docref (NULL TSRMLS_CC, E_ERROR, "could not open log file for writting");
php_stream* stream = php_stream_open_wrapper (new_value, "a", 0, NULL);
#endif
if (!stream) {
php_error_docref (NULL TSRMLS_CC, E_ERROR, "could not open log file for writing");
return FAILURE;
}
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void **) &exp_logfile, REPORT_ERRORS) != SUCCESS) {
return FAILURE;
}
EXPECT_G(logfile_stream) = stream;
exp_logfile_all = 1;
} else {
EXPECT_G(logfile_stream) = NULL;
exp_logfile = NULL;
exp_logfile_all = 0;
}
return SUCCESS;
}
@@ -95,6 +195,7 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("expect.timeout", "10", PHP_INI_ALL, OnSetExpectTimeout)
PHP_INI_ENTRY_EX("expect.loguser", "1", PHP_INI_ALL, OnSetExpectLogUser, php_ini_boolean_displayer_cb)
PHP_INI_ENTRY("expect.logfile", "", PHP_INI_ALL, OnSetExpectLogFile)
PHP_INI_ENTRY("expect.match_max", "5000", PHP_INI_ALL, OnSetExpectMatchMax)
PHP_INI_END()
@@ -111,6 +212,18 @@ PHP_MINIT_FUNCTION(expect)
REGISTER_LONG_CONSTANT("EXP_FULLBUFFER", EXP_FULLBUFFER, CONST_CS | CONST_PERSISTENT);
REGISTER_INI_ENTRIES();
Tcl_Interp *interp = Tcl_CreateInterp();
if (Tcl_Init(interp) == TCL_ERROR) {
php_error_docref (NULL TSRMLS_CC, E_ERROR,
"Unable to initialize TCL interpreter: %s", Tcl_GetStringResult (interp));
return FAILURE;
}
if (Expect_Init(interp) == TCL_ERROR) {
php_error_docref (NULL TSRMLS_CC, E_ERROR,
"Unable to initialize Expect: %s", Tcl_GetStringResult (interp));
return FAILURE;
}
return SUCCESS;
}
@@ -129,11 +242,34 @@ PHP_MSHUTDOWN_FUNCTION(expect)
/* }}} */
/* {{{ PHP_RINIT_FUNCTION
* Apply ini settings that require PHP streams, skipped during MINIT. */
PHP_RINIT_FUNCTION(expect)
{
if (!EXPECT_G(logfile_stream)) {
char *logfile = zend_ini_string("expect.logfile", sizeof("expect.logfile") - 1, 0);
if (logfile && strlen(logfile) > 0) {
php_stream *stream = php_stream_open_wrapper(logfile, "a", 0, NULL);
if (stream) {
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void **) &exp_logfile, REPORT_ERRORS) == SUCCESS) {
EXPECT_G(logfile_stream) = stream;
exp_logfile_all = 1;
}
}
}
}
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(expect)
{
php_info_print_table_start();
php_info_print_table_row(2, "Expect support", "enabled");
php_info_print_table_header(2, "Expect support", "enabled");
php_info_print_table_row(2, "Version", PHP_EXPECT_VERSION);
php_info_print_table_row(2, "Stream wrapper support", "expect://");
php_info_print_table_end();
@@ -147,23 +283,55 @@ PHP_MINFO_FUNCTION(expect)
*/
PHP_FUNCTION(expect_popen)
{
#if PHP_MAJOR_VERSION >= 7
zend_string *command = NULL;
#else
char *command = NULL;
#endif
int command_len;
FILE *fp;
php_stream *stream = NULL;
#if PHP_MAJOR_VERSION >= 7
zval z_pid;
#else
zval *z_pid;
#endif
if (ZEND_NUM_ARGS() != 1) { WRONG_PARAM_COUNT; }
#if PHP_MAJOR_VERSION >= 7
if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "S", &command) == FAILURE) {
#else
if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "s", &command, &command_len) == FAILURE) {
#endif
return;
}
#if PHP_MAJOR_VERSION >= 7
if ((fp = exp_popen (ZSTR_VAL(command))) != NULL) {
#else
if ((fp = exp_popen (command)) != NULL) {
#endif
stream = php_stream_fopen_from_pipe (fp, "");
}
if (!stream) {
RETURN_FALSE;
}
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
/* PTY reads may return EIO when the child exits; suppress notices (PHP 7.4+ d59aac58b3e7). */
#ifdef PHP_STREAM_FLAG_SUPPRESS_ERRORS
stream->flags |= PHP_STREAM_FLAG_SUPPRESS_ERRORS;
#endif
#if PHP_MAJOR_VERSION >= 7
ZVAL_LONG (&z_pid, exp_pid);
#else
MAKE_STD_ZVAL (z_pid);
ZVAL_LONG (z_pid, exp_pid);
#endif
stream->wrapperdata = z_pid;
php_stream_to_zval(stream, return_value);
}
/* }}} */
@@ -174,125 +342,228 @@ PHP_FUNCTION(expect_popen)
*/
PHP_FUNCTION(expect_expectl)
{
struct exp_case *ecases, *ec, matchedcase;
struct exp_case *ecases, *ecases_ptr, matchedcase;
#if PHP_MAJOR_VERSION >= 7
zval *z_stream, *z_cases, *z_match=NULL, *z_case, *z_value;
zend_ulong key;
#else
zval *z_stream, *z_cases, *z_match=NULL, **z_case, **z_value;
ulong key;
#endif
php_stream *stream;
int fd, argc;
ulong key;
#if PHP_MAJOR_VERSION >= 7
HashPosition pos;
#endif
if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3) { WRONG_PARAM_COUNT; }
if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ra|z", &z_stream, &z_cases, &z_match) == FAILURE) {
if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ra|z/", &z_stream, &z_cases, &z_match) == FAILURE) {
return;
}
#if PHP_MAJOR_VERSION >= 7
php_stream_from_zval (stream, z_stream);
#else
php_stream_from_zval (stream, &z_stream);
if (php_stream_cast (stream, PHP_STREAM_AS_FD, (void*)&fd, 1) != SUCCESS || fd < 0) {
php_error_docref (NULL TSRMLS_CC, E_ERROR, "couldn't cast expect stream to a file descriptor");
return;
#endif
#if PHP_MAJOR_VERSION >= 7
if (Z_TYPE(stream->wrapperdata) != IS_LONG) {
#else
if (!stream->wrapperdata) {
#endif
php_error_docref (NULL TSRMLS_CC, E_ERROR, "supplied argument is not a valid stream resource");
return;
}
if (php_stream_cast (stream, PHP_STREAM_AS_FD, (void*)&fd, REPORT_ERRORS) != SUCCESS || fd < 0) {
return;
}
argc = zend_hash_num_elements (Z_ARRVAL_P(z_cases));
ecases = (struct exp_case*) safe_emalloc (argc + 1, sizeof(struct exp_case), 0);
ecases_ptr = ecases;
ec = ecases;
#if PHP_MAJOR_VERSION >= 7
zend_hash_internal_pointer_reset_ex (Z_ARRVAL_P(z_cases), &pos);
while ((z_case = zend_hash_get_current_data_ex (Z_ARRVAL_P(z_cases), &pos)) != NULL)
{
zval *z_pattern, *z_exp_type;
zend_hash_get_current_key_ex(Z_ARRVAL_P(z_cases), NULL, &key, &pos);
if (Z_TYPE_P(z_case) != IS_ARRAY) {
#else
zend_hash_internal_pointer_reset (Z_ARRVAL_P(z_cases));
while (zend_hash_get_current_data (Z_ARRVAL_P(z_cases), (void **)&z_case) == SUCCESS)
{
zval **z_pattern, **z_exp_type;
zend_hash_get_current_key(Z_ARRVAL_P(z_cases), NULL, &key, 0);
if (Z_TYPE_PP(z_case) != IS_ARRAY) {
#endif
efree (ecases);
php_error_docref (NULL TSRMLS_CC, E_ERROR, "expect case must be an array");
return;
}
ec->re = NULL;
ec->type = exp_glob;
ecases_ptr->re = NULL;
ecases_ptr->type = exp_glob;
/* Gather pattern */
#if PHP_MAJOR_VERSION >= 7
if ((z_pattern = zend_hash_index_find(Z_ARRVAL_P(z_case), 0)) == NULL) {
#else
if (zend_hash_index_find(Z_ARRVAL_PP(z_case), 0, (void **)&z_pattern) != SUCCESS) {
#endif
efree (ecases);
php_error_docref (NULL TSRMLS_CC, E_ERROR, "missing parameter for pattern at index: 0");
return;
}
#if PHP_MAJOR_VERSION >= 7
if (Z_TYPE_P(z_pattern) != IS_STRING) {
#else
if (Z_TYPE_PP(z_pattern) != IS_STRING) {
#endif
efree (ecases);
php_error_docref (NULL TSRMLS_CC, E_ERROR, "pattern must be of string type");
return;
}
ec->pattern = Z_STRVAL_PP(z_pattern);
#if PHP_MAJOR_VERSION >= 7
ecases_ptr->pattern = Z_STRVAL_P(z_pattern);
#else
ecases_ptr->pattern = Z_STRVAL_PP(z_pattern);
#endif
/* Gather value */
#if PHP_MAJOR_VERSION >= 7
if (zend_hash_index_find(Z_ARRVAL_P(z_case), 1) == NULL) {
#else
if (zend_hash_index_find(Z_ARRVAL_PP(z_case), 1, (void **)&z_value) != SUCCESS) {
#endif
efree (ecases);
php_error_docref (NULL TSRMLS_CC, E_ERROR, "missing parameter for value at index: 1");
return;
}
ec->value = key;
ecases_ptr->value = key;
/* Gather expression type (optional, default: EXPECT_GLOB) */
#if PHP_MAJOR_VERSION >= 7
if ((z_exp_type = zend_hash_index_find(Z_ARRVAL_P(z_case), 2)) != NULL) {
if (Z_TYPE_P(z_exp_type) != IS_LONG) {
#else
if (zend_hash_index_find(Z_ARRVAL_PP(z_case), 2, (void **)&z_exp_type) == SUCCESS) {
if (Z_TYPE_PP(z_exp_type) != IS_LONG) {
#endif
efree (ecases);
php_error_docref (NULL TSRMLS_CC, E_ERROR, "expression type must be an integer constant");
return;
}
#if PHP_MAJOR_VERSION >= 7
if (Z_LVAL_P(z_exp_type) != exp_glob && Z_LVAL_P(z_exp_type) != exp_exact && Z_LVAL_P(z_exp_type) != exp_regexp) {
#else
if (Z_LVAL_PP(z_exp_type) != exp_glob && Z_LVAL_PP(z_exp_type) != exp_exact && Z_LVAL_PP(z_exp_type) != exp_regexp) {
#endif
efree (ecases);
php_error_docref (NULL TSRMLS_CC, E_ERROR, "expression type must be either EXPECT_GLOB, EXPECT_EXACT or EXPECT_REGEXP");
return;
}
ec->type = Z_LVAL_PP(z_exp_type);
#if PHP_MAJOR_VERSION >= 7
ecases_ptr->type = Z_LVAL_P(z_exp_type);
#else
ecases_ptr->type = Z_LVAL_PP(z_exp_type);
#endif
}
ec++;
ecases_ptr++;
#if PHP_MAJOR_VERSION >= 7
zend_hash_move_forward_ex(Z_ARRVAL_P(z_cases), &pos);
#else
zend_hash_move_forward(Z_ARRVAL_P(z_cases));
#endif
}
ec->type = exp_end;
ecases_ptr->pattern = NULL;
ecases_ptr->re = NULL;
ecases_ptr->value = 0;
ecases_ptr->type = exp_end;
key = exp_expectv (fd, ecases);
int exp_retval = exp_expectv (fd, ecases);
int case_found = 0;
if (exp_retval >= 0) {
key = exp_retval;
int exp_match_len = exp_match_end - exp_match + 1;
if (z_match && exp_match && exp_match_len > 0) {
char *tmp = (char *)emalloc (sizeof(char) * exp_match_len);
strlcpy (tmp, exp_match, exp_match_len);
zval_dtor (z_match);
array_init(z_match);
add_index_string(z_match, 0, tmp, 1);
/* Get case that was matched */
matchedcase = ecases[key];
/* If there are subpattern matches ... */
if (matchedcase.re->startp != NULL) {
int i;
/* iterate across all possible 9 subpatterns (a limitation of libexpect)
and add matching substring to matches array */
for (i = 1; i <= 9; i++) {
if (matchedcase.re->startp[i] != NULL) {
int sub_match_len = matchedcase.re->endp[i] - matchedcase.re->startp[i] + 1;
char *sub_match = (char *)emalloc (sizeof(char) * sub_match_len);
strlcpy (sub_match, matchedcase.re->startp[i], sub_match_len);
add_next_index_string(z_match, sub_match, 1);
efree (sub_match);
int exp_match_len = exp_match_end - exp_match;
if (z_match && exp_match && exp_match_len > 0) {
char *tmp = (char *)emalloc (sizeof(char) * (exp_match_len + 1));
strlcpy (tmp, exp_match, exp_match_len + 1);
#if PHP_MAJOR_VERSION > 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION >= 4)
z_match = zend_try_array_init(z_match);
if (!z_match) {
return;
}
add_index_string(z_match, 0, tmp);
#elif PHP_MAJOR_VERSION >= 7
zval_dtor(z_match);
array_init(z_match);
add_index_string(z_match, 0, tmp);
#else
zval_dtor (z_match);
array_init(z_match);
add_index_string(z_match, 0, tmp, 1);
#endif
/* Get case that was matched */
matchedcase = ecases[key];
/* If there are subpattern matches ... */
if (matchedcase.re != NULL && matchedcase.re->startp != NULL) {
int i;
/* iterate across all possible 9 subpatterns (a limitation of libexpect)
and add matching substring to matches array */
for (i = 1; i <= 9; i++) {
if (matchedcase.re->startp[i] != NULL) {
int sub_match_len = matchedcase.re->endp[i] - matchedcase.re->startp[i];
char *sub_match = (char *)emalloc (sizeof(char) * (sub_match_len + 1));
strlcpy (sub_match, matchedcase.re->startp[i], sub_match_len + 1);
#if PHP_MAJOR_VERSION >= 7
add_next_index_string(z_match, sub_match);
#else
add_next_index_string(z_match, sub_match, 1);
#endif
efree (sub_match);
}
}
}
efree (tmp);
}
efree (tmp);
}
if (zend_hash_index_find (Z_ARRVAL_P(z_cases), key, (void **)&z_case) == SUCCESS) {
if (zend_hash_index_find(Z_ARRVAL_PP(z_case), 1, (void **)&z_value) == SUCCESS) {
*return_value = **z_value;
zval_copy_ctor (return_value);
#if PHP_MAJOR_VERSION >= 7
if ((z_case = zend_hash_index_find (Z_ARRVAL_P(z_cases), key)) != NULL) {
if ((z_value = zend_hash_index_find(Z_ARRVAL_P(z_case), 1)) != NULL) {
*return_value = *z_value;
#else
if (zend_hash_index_find (Z_ARRVAL_P(z_cases), key, (void **)&z_case) == SUCCESS) {
if (zend_hash_index_find(Z_ARRVAL_PP(z_case), 1, (void **)&z_value) == SUCCESS) {
*return_value = **z_value;
#endif
zval_copy_ctor (return_value);
case_found = 1;
}
}
}
else {
RETURN_LONG (key);
}
// Free compiled patterns:
ecases_ptr = ecases;
while (ecases_ptr != NULL && ecases_ptr->type != exp_end) {
if (ecases_ptr->re != NULL) {
free(ecases_ptr->re);
}
ecases_ptr++;
}
efree (ecases);
if (!case_found) {
RETURN_LONG(exp_retval);
}
}
/* }}} */

View File

@@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
| PHP Version 5 and 7 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
@@ -12,7 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Michael Spector <michael@zend.com> |
| Author: Michael Spector <michael@php.net> |
+----------------------------------------------------------------------+
*/
@@ -21,26 +21,74 @@
#include "php.h"
#include "php_expect.h"
#include "php_streams.h"
#include <sys/wait.h>
php_stream *php_expect_stream_opener (php_stream_wrapper *wrapper, char *command, char *mode, int options,
#if PHP_MAJOR_VERSION >= 7
php_stream *php_expect_stream_open (php_stream_wrapper *wrapper, const char *command, const char *mode, int options,
zend_string **opened_command, php_stream_context *context STREAMS_DC TSRMLS_DC)
#elif PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 6
php_stream *php_expect_stream_open (php_stream_wrapper *wrapper, const char *command, const char *mode, int options,
char **opened_command, php_stream_context *context STREAMS_DC TSRMLS_DC)
#else
php_stream *php_expect_stream_open (php_stream_wrapper *wrapper, char *command, char *mode, int options,
char **opened_command, php_stream_context *context STREAMS_DC TSRMLS_DC)
#endif
{
FILE *fp;
if (strncasecmp("expect://", command, sizeof("expect://")-1) == 0) {
command += sizeof("expect://")-1;
}
#if PHP_MAJOR_VERSION >= 7 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 6)
if ((fp = exp_popen((char*)command)) != NULL) {
#else
if ((fp = exp_popen(command)) != NULL) {
return php_stream_fopen_from_pipe (fp, "");
#endif
php_stream* stream = php_stream_fopen_from_pipe (fp, mode);
stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
/* PTY reads may return EIO when the child exits; suppress notices (PHP 7.4+ d59aac58b3e7). */
#ifdef PHP_STREAM_FLAG_SUPPRESS_ERRORS
stream->flags |= PHP_STREAM_FLAG_SUPPRESS_ERRORS;
#endif
#if PHP_MAJOR_VERSION >= 7
zval z_pid;
ZVAL_LONG (&z_pid, exp_pid);
#else
zval *z_pid;
MAKE_STD_ZVAL (z_pid);
ZVAL_LONG (z_pid, exp_pid);
#endif
stream->wrapperdata = z_pid;
return stream;
}
return NULL;
}
static int php_expect_stream_close (php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC)
{
#if PHP_MAJOR_VERSION >= 7
zval* z_pid = &(stream->wrapperdata);
#else
zval* z_pid = stream->wrapperdata;
#endif
int s = 0;
waitpid (Z_LVAL_P(z_pid), &s, 0);
#if PHP_MAJOR_VERSION >= 7
zval_ptr_dtor (z_pid);
php_stream_free(stream, PHP_STREAM_FREE_CLOSE);
#else
zval_ptr_dtor (&z_pid);
stream->wrapperdata = NULL;
#endif
return s;
}
/* }}} */
static php_stream_wrapper_ops php_expect_wrapper_ops = {
php_expect_stream_opener,
NULL, /* close */
php_expect_stream_open,
php_expect_stream_close, /* close */
NULL, /* stat */
NULL, /* stat_url */
NULL, /* opendir */

View File

@@ -1,35 +1,63 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
<package>
<name>expect</name>
<summary>PHP extension for expect library</summary>
<description>This extension allows to interact with processes through PTY, using expect library.</description>
<license>PHP License</license>
<maintainers>
<maintainer>
<user>michael</user>
<name>Michael Spector</name>
<email>michael@php.net</email>
</maintainer>
</maintainers>
<release>
<version>0.2.1</version>
<date>2006-07-04</date>
<state>beta</state>
<notes>1) Support returning match substrings in array.
2) Fix missing null-termination in returned match string.
</notes>
</release>
<filelist>
<dir role="doc" name="/">
<file role="src">config.m4</file>
<file role="src">expect.dsp</file>
<file role="src">config.w32</file>
<file role="src">expect.c</file>
<file role="src">expect_fopen_wrapper.c</file>
<file role="src">php_expect.h</file>
</dir>
</filelist>
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
<name>expect</name>
<channel>pecl.php.net</channel>
<summary>PHP extension for expect library</summary>
<description>This extension allows to interact with processes through PTY, using expect library.
</description>
<lead>
<name>Michael Spector</name>
<user>michael</user>
<email>michael@php.net</email>
<active>yes</active>
</lead>
<date>2020-01-13</date>
<time>18:00:00</time>
<version>
<release>0.4.0</release>
<api>0.4.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Added LICENSE. Fixed RPM build for 64bit.
</notes>
<contents>
<dir name="/">
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
<file name="expect.c" role="src" />
<file name="expect.dsp" role="src" />
<file name="expect_fopen_wrapper.c" role="src" />
<file name="php_expect.h" role="src" />
<file name="LICENSE" role="doc" />
<dir name="tests">
<file name="bug12268.phpt" role="test" />
<file name="bug22566.phpt" role="test" />
<file name="bug6996.phpt" role="test" />
<file name="expect_expectl.phpt" role="test" />
<file name="expect_popen.phpt" role="test" />
<file name="expect_wrapper.phpt" role="test" />
</dir>
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>4.0.0</min>
<max>8.99.99</max>
</php>
<pearinstaller>
<min>1.4.0b1</min>
</pearinstaller>
</required>
</dependencies>
<providesextension>expect</providesextension>
<extsrcrelease />
</package>

View File

@@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
| PHP Version 5, 7 and 8 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
@@ -12,7 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Michael Spector <michael@zend.com> |
| Author: Michael Spector <michael@php.net> |
+----------------------------------------------------------------------+
*/
@@ -30,11 +30,15 @@
#include <SAPI.h>
#include <ext/standard/info.h>
#include <tcl.h>
#include <expect_tcl.h>
#include <expect.h>
extern zend_module_entry expect_module_entry;
#define phpext_expect_ptr &expect_module_entry
#define PHP_EXPECT_VERSION "0.4.1"
#ifdef PHP_WIN32
#define PHP_EXPECT_API __declspec(dllexport)
#else
@@ -43,6 +47,7 @@ extern zend_module_entry expect_module_entry;
PHP_MINIT_FUNCTION(expect);
PHP_MSHUTDOWN_FUNCTION(expect);
PHP_RINIT_FUNCTION(expect);
PHP_MINFO_FUNCTION(expect);
PHP_FUNCTION(expect_popen);
@@ -50,10 +55,32 @@ PHP_FUNCTION(expect_expectl);
extern php_stream_wrapper php_expect_wrapper;
ZEND_BEGIN_MODULE_GLOBALS(expect)
php_stream* logfile_stream;
ZEND_END_MODULE_GLOBALS(expect)
#ifdef ZTS
#define EXPECT_G(v) TSRMG(expect_globals_id, zend_expect_globals *, v)
#else
#define EXPECT_G(v) (expect_globals.v)
#endif
#ifdef ZTS
#include "TSRM.h"
#endif /* ZTS */
#if ZEND_MODULE_API_NO >= 20190128
#ifndef TSRMLS_CC
#define TSRMLS_CC
#endif
#ifndef TSRMLS_DC
#define TSRMLS_DC
#endif
#ifndef TSRMLS_FETCH
#define TSRMLS_FETCH()
#endif
#endif
#endif /* PHP_EXPECT_H */
/*

24
tests/bug12268.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
PECL Bug #12268 CGI
--SKIPIF--
<?php if (!extension_loaded("expect") || php_sapi_name() == 'cli') print "skip"; ?>
--INI--
expect.loguser=0
expect.logfile=php://output
--FILE--
<?php
if (php_sapi_name() == 'cli') exit;
$stream = expect_popen("echo Hello");
ob_start();
expect_expectl ($stream, array());
$r = ob_get_contents();
fclose ($stream);
print "Output: $r";
?>
--EXPECT--
Output: Hello

16
tests/bug22566.phpt Normal file
View File

@@ -0,0 +1,16 @@
--TEST--
PECL Bug #22566 CGI
--SKIPIF--
<?php if (!extension_loaded("expect")) print "skip"; ?>
--FILE--
<?php
var_dump(ini_set('expect.timeout', 3));
var_dump(ini_set('expect.match_max', '2000'));
var_dump(ini_get('expect.timeout'));
var_dump(ini_get('expect.match_max'));
?>
--EXPECT--
string(2) "10"
string(4) "5000"
string(1) "3"
string(4) "2000"

14
tests/bug6996.phpt Normal file
View File

@@ -0,0 +1,14 @@
--TEST--
PECL Bug #6996
--SKIPIF--
<?php if (!extension_loaded("expect")) print "skip"; ?>
--FILE--
<?php
$stream = popen ("expect://echo 2>/dev/null", "r");
expect_expectl ($stream, array());
fclose ($stream);
?>
--EXPECTF--
Fatal error: expect_expectl(): supplied argument is not a valid stream resource in %s on line %d