Skip to content

Commit a65282d

Browse files
committed
feat(sapi): add initial work on having it's own sapi
1 parent 5fdd8fa commit a65282d

File tree

13 files changed

+311
-42
lines changed

13 files changed

+311
-42
lines changed

allowed_bindings.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,15 @@ bind! {
260260
zend_eval_string,
261261
zend_file_handle,
262262
zend_stream_init_filename,
263+
zend_destroy_file_handle,
263264
php_execute_script,
264265
zend_register_module_ex,
265-
_zend_bailout
266+
_zend_bailout,
267+
sapi_module_struct,
268+
sapi_startup,
269+
sapi_shutdown,
270+
php_module_startup,
271+
php_module_shutdown,
272+
php_request_startup,
273+
php_request_shutdown
266274
}

src/builders/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
mod class;
55
mod function;
66
mod module;
7+
#[cfg(feature = "embed")]
8+
mod sapi;
79

810
pub use class::ClassBuilder;
911
pub use function::FunctionBuilder;
1012
pub use module::ModuleBuilder;
13+
#[cfg(feature = "embed")]
14+
pub use sapi::SapiBuilder;

src/builders/sapi.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use crate::ffi::sapi_header_struct;
2+
use crate::{embed::SapiModule, error::Result};
3+
4+
use std::ffi::c_void;
5+
use std::{ffi::CString, ptr};
6+
7+
pub struct SapiBuilder {
8+
name: String,
9+
pretty_name: String,
10+
module: SapiModule,
11+
}
12+
13+
impl SapiBuilder {
14+
pub fn new<T: Into<String>, U: Into<String>>(name: T, pretty_name: U) -> Self {
15+
Self {
16+
name: name.into(),
17+
pretty_name: pretty_name.into(),
18+
module: SapiModule {
19+
name: ptr::null_mut(),
20+
pretty_name: ptr::null_mut(),
21+
startup: None,
22+
shutdown: None,
23+
activate: None,
24+
deactivate: None,
25+
ub_write: None,
26+
flush: None,
27+
get_stat: None,
28+
getenv: None,
29+
sapi_error: None,
30+
header_handler: None,
31+
send_headers: None,
32+
send_header: None,
33+
read_post: None,
34+
read_cookies: None,
35+
register_server_variables: None,
36+
log_message: None,
37+
get_request_time: None,
38+
terminate_process: None,
39+
php_ini_path_override: ptr::null_mut(),
40+
default_post_reader: None,
41+
treat_data: None,
42+
executable_location: ptr::null_mut(),
43+
php_ini_ignore: 0,
44+
php_ini_ignore_cwd: 0,
45+
get_fd: None,
46+
force_http_10: None,
47+
get_target_uid: None,
48+
get_target_gid: None,
49+
input_filter: None,
50+
ini_defaults: None,
51+
phpinfo_as_text: 0,
52+
ini_entries: ptr::null_mut(),
53+
additional_functions: ptr::null(),
54+
input_filter_init: None,
55+
},
56+
}
57+
}
58+
59+
/// Sets the send header function for this SAPI
60+
///
61+
/// # Arguments
62+
///
63+
/// * `func` - The function to be called on shutdown.
64+
pub fn send_header_function(mut self, func: SapiSendHeaderFunc) -> Self {
65+
self.module.send_header = Some(func);
66+
self
67+
}
68+
69+
/// Builds the extension and returns a `SapiModule`.
70+
///
71+
/// Returns a result containing the sapi module if successful.
72+
pub fn build(mut self) -> Result<SapiModule> {
73+
self.module.name = CString::new(self.name)?.into_raw();
74+
self.module.pretty_name = CString::new(self.pretty_name)?.into_raw();
75+
76+
if self.module.send_header.is_none() {
77+
self.module.send_header = Some(dummy_send_header);
78+
}
79+
80+
Ok(self.module)
81+
}
82+
}
83+
84+
/// A function to be called when the extension is starting up or shutting down.
85+
pub type SapiSendHeaderFunc =
86+
extern "C" fn(header: *mut sapi_header_struct, server_context: *mut c_void);
87+
88+
extern "C" fn dummy_send_header(_header: *mut sapi_header_struct, _server_context: *mut c_void) {}

src/embed/embed.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,18 @@ void* ext_php_rs_embed_callback(int argc, char** argv, void* (*callback)(void *)
1313

1414
return result;
1515
}
16+
17+
void ext_php_rs_sapi_startup() {
18+
#if defined(SIGPIPE) && defined(SIG_IGN)
19+
signal(SIGPIPE, SIG_IGN);
20+
#endif
21+
22+
#ifdef ZTS
23+
php_tsrm_startup();
24+
#ifdef PHP_WIN32
25+
ZEND_TSRMLS_CACHE_UPDATE();
26+
#endif
27+
#endif
28+
29+
zend_signal_startup();
30+
}

src/embed/embed.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
#include "sapi/embed/php_embed.h"
33

44
void* ext_php_rs_embed_callback(int argc, char** argv, void* (*callback)(void *), void *ctx);
5+
6+
void ext_php_rs_sapi_startup();

src/embed/ffi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ extern "C" {
1313
func: unsafe extern "C" fn(*const c_void) -> *const c_void,
1414
ctx: *const c_void,
1515
) -> *mut c_void;
16+
17+
pub fn ext_php_rs_sapi_startup();
1618
}

src/embed/mod.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! You should only use this crate for test purpose, it's not production ready
66
77
mod ffi;
8+
mod sapi;
89

910
use crate::boxed::ZBox;
1011
use crate::embed::ffi::ext_php_rs_embed_callback;
@@ -20,6 +21,9 @@ use std::panic::{resume_unwind, RefUnwindSafe};
2021
use std::path::Path;
2122
use std::ptr::null_mut;
2223

24+
pub use ffi::ext_php_rs_sapi_startup;
25+
pub use sapi::SapiModule;
26+
2327
pub struct Embed;
2428

2529
#[derive(Debug)]
@@ -86,7 +90,7 @@ impl Embed {
8690
zend_stream_init_filename(&mut file_handle, path.as_ptr());
8791
}
8892

89-
let exec_result = try_catch(|| unsafe { php_execute_script(&mut file_handle) });
93+
let exec_result = try_catch(|| unsafe { php_execute_script(&mut file_handle) }, false);
9094

9195
match exec_result {
9296
Err(_) => Err(EmbedError::CatchError),
@@ -180,13 +184,16 @@ impl Embed {
180184

181185
let mut result = Zval::new();
182186

183-
let exec_result = try_catch(|| unsafe {
184-
zend_eval_string(
185-
cstr.as_ptr() as *const c_char,
186-
&mut result,
187-
b"run\0".as_ptr() as *const _,
188-
)
189-
});
187+
let exec_result = try_catch(
188+
|| unsafe {
189+
zend_eval_string(
190+
cstr.as_ptr() as *const c_char,
191+
&mut result,
192+
b"run\0".as_ptr() as *const _,
193+
)
194+
},
195+
false,
196+
);
190197

191198
match exec_result {
192199
Err(_) => Err(EmbedError::CatchError),

src/embed/sapi.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//! Builder and objects for creating modules in PHP. A module is the base of a
2+
//! PHP extension.
3+
4+
use crate::ffi::sapi_module_struct;
5+
6+
/// A Zend module entry, also known as an extension.
7+
pub type SapiModule = sapi_module_struct;
8+
9+
impl SapiModule {
10+
/// Allocates the module entry on the heap, returning a pointer to the
11+
/// memory location. The caller is responsible for the memory pointed to.
12+
pub fn into_raw(self) -> *mut Self {
13+
Box::into_raw(Box::new(self))
14+
}
15+
}

src/ffi.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,19 @@ extern "C" {
2626
pub fn ext_php_rs_zend_object_alloc(obj_size: usize, ce: *mut zend_class_entry) -> *mut c_void;
2727
pub fn ext_php_rs_zend_object_release(obj: *mut zend_object);
2828
pub fn ext_php_rs_executor_globals() -> *mut zend_executor_globals;
29+
2930
pub fn ext_php_rs_zend_try_catch(
3031
func: unsafe extern "C" fn(*const c_void) -> *const c_void,
3132
ctx: *const c_void,
3233
result: *mut *mut c_void,
3334
) -> bool;
35+
36+
pub fn ext_php_rs_zend_first_try_catch(
37+
func: unsafe extern "C" fn(*const c_void) -> *const c_void,
38+
ctx: *const c_void,
39+
result: *mut *mut c_void,
40+
) -> bool;
41+
3442
pub fn ext_php_rs_zend_bailout() -> !;
3543
}
3644

src/wrapper.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ bool ext_php_rs_zend_try_catch(void* (*callback)(void *), void *ctx, void **resu
5050
return false;
5151
}
5252

53+
bool ext_php_rs_zend_first_try_catch(void* (*callback)(void *), void *ctx, void **result) {
54+
zend_first_try {
55+
*result = callback(ctx);
56+
} zend_catch {
57+
return true;
58+
} zend_end_try();
59+
60+
return false;
61+
}
62+
5363
void ext_php_rs_zend_bailout() {
5464
zend_bailout();
5565
}

0 commit comments

Comments
 (0)