11/* radare - LGPL - Copyright 2015-2025 - pancake */
2- /*
3- Usage Example:
4-
5- #include <r_core.h>
6- int main() {
7- RCoreBind rcb;
8- RCore *core = r_core_new ();
9- r_core_bind (core, &rcb);
10- r2pipe_open_corebind (&rcb);
11- char *clippy = r2pipe_cmd ("?E hello");
12- eprintf ("%s\n", clippy);
13- free (clippy);
14- r2pipe_close (r2pipe);
15- r_core_free (core);
16- }
17- */
182
193#include <r_util.h>
204#include <r_lib.h>
215#include <r_socket.h>
226#include <errno.h>
237
24- #define R2P_PID (x ) (( (R2Pipe*) (x)->data)->pid)
25- #define R2P_INPUT (x ) (( (R2Pipe*) (x)->data)->input[0])
26- #define R2P_OUTPUT (x ) (( (R2Pipe*) (x)->data)->output[1])
8+ #define R2P_PID (x) ( ( (R2Pipe *) (x)->data)->pid)
9+ #define R2P_INPUT (x) ( ( (R2Pipe *) (x)->data)->input[0])
10+ #define R2P_OUTPUT (x) ( ( (R2Pipe *) (x)->data)->output[1])
2711
2812#define USE_WIP_READ 0
2913#if R2__WINDOWS__
@@ -32,7 +16,7 @@ Usage Example:
3216#define NO_CHILD -1
3317#endif
3418
35- #if defined(__wasi__ ) && __wasi__
19+ #if defined (__wasi__ ) && __wasi__
3620#define HAVE_R2PIPE 0
3721#else
3822#define HAVE_R2PIPE 1
@@ -61,11 +45,11 @@ R_API int r2pipe_write(R2Pipe *r2pipe, const char *str) {
6145 cmd [n + 1 ] = '\0' ;
6246#if R2__WINDOWS__
6347 DWORD dwWritten = 0 ;
64- WriteFile (r2pipe -> pipe , cmd , (DWORD )(len - 1 ), & dwWritten , NULL );
65- int ret = (dwWritten == (DWORD )(len - 1 ));
48+ WriteFile (r2pipe -> pipe , cmd , (DWORD ) (len - 1 ), & dwWritten , NULL );
49+ int ret = (dwWritten == (DWORD ) (len - 1 ));
6650#else
67- ssize_t wrote = write (r2pipe -> input [1 ], cmd , (ssize_t )(len - 1 ));
68- int ret = (wrote == (ssize_t )(len - 1 ));
51+ ssize_t wrote = write (r2pipe -> input [1 ], cmd , (ssize_t ) (len - 1 ));
52+ int ret = (wrote == (ssize_t ) (len - 1 ));
6953#endif
7054 free (cmd );
7155 return ret ;
@@ -79,7 +63,7 @@ R_API char *r2pipe_read(R2Pipe *r2pipe) {
7963 R_RETURN_VAL_IF_FAIL (r2pipe , NULL );
8064 char * buf = NULL ;
8165#if HAVE_R2PIPE
82- # /* Read all available data from the pipe into a dynamically
66+ #/* Read all available data from the pipe into a dynamically
8367# * growing buffer and return a NUL-terminated string. */
8468 /* r2pipe already validated above */
8569 int bufsz = 4096 ;
@@ -91,7 +75,7 @@ R_API char *r2pipe_read(R2Pipe *r2pipe) {
9175 BOOL bSuccess = FALSE;
9276 DWORD dwRead = 0 ;
9377 // Read up to bufsz-1 bytes and NUL-terminate.
94- DWORD toRead = (DWORD )(bufsz - 1 );
78+ DWORD toRead = (DWORD ) (bufsz - 1 );
9579 bSuccess = ReadFile (r2pipe -> pipe , buf , toRead , & dwRead , NULL );
9680 if (!bSuccess || dwRead == 0 ) {
9781 free (buf );
@@ -121,7 +105,7 @@ R_API char *r2pipe_read(R2Pipe *r2pipe) {
121105 }
122106 }
123107 if (buf ) {
124- int zpos = (i < bufsz )? i : i - 1 ;
108+ int zpos = (i < bufsz ) ? i : i - 1 ;
125109 buf [zpos ] = 0 ;
126110 }
127111#endif
@@ -130,14 +114,12 @@ R_API char *r2pipe_read(R2Pipe *r2pipe) {
130114}
131115
132116R_API int r2pipe_close (R2Pipe * r2pipe ) {
133- #if HAVE_R2PIPE
134117 /* r2pipe may be NULL on non-r2pipe builds */
135118 R_RETURN_VAL_IF_FAIL (r2pipe , 0 );
136- #endif
137119#if HAVE_R2PIPE
138120 /*
139121 if (r2pipe->coreb.core && !r2pipe->coreb.puts) {
140- void (*rfre)(void *c) = r_lib_dl_sym (libr, "r_core_free");
122+ void (*rfre) (void *c) = r_lib_dl_sym (libr, "r_core_free");
141123 if (rfre) {
142124 rfre (r2pipe->coreb.core);
143125 }
@@ -166,11 +148,16 @@ R_API int r2pipe_close(R2Pipe *r2pipe) {
166148 r2pipe -> output [1 ] = -1 ;
167149 }
168150 if (r2pipe -> child != NO_CHILD ) {
169- kill (r2pipe -> child , SIGTERM );
170- waitpid (r2pipe -> child , NULL , 0 );
151+ r_sandbox_kill (r2pipe -> child , SIGTERM );
171152 r2pipe -> child = NO_CHILD ;
172153 }
173154#endif
155+ /* free http resources if used */
156+ if (r2pipe -> is_http && r2pipe -> http_url ) {
157+ free (r2pipe -> http_url );
158+ r2pipe -> http_url = NULL ;
159+ r2pipe -> is_http = false;
160+ }
174161#endif
175162 free (r2pipe );
176163 return 0 ;
@@ -180,9 +167,7 @@ R_API int r2pipe_close(R2Pipe *r2pipe) {
180167static int w32_createPipe (R2Pipe * r2pipe , const char * cmd ) {
181168 CHAR buf [1024 ];
182169 r2pipe -> pipe = CreateNamedPipe (TEXT ("\\\\.\\pipe\\R2PIPE_IN" ),
183- PIPE_ACCESS_DUPLEX ,PIPE_TYPE_MESSAGE | \
184- PIPE_READMODE_MESSAGE | \
185- PIPE_WAIT , PIPE_UNLIMITED_INSTANCES ,
170+ PIPE_ACCESS_DUPLEX , PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT , PIPE_UNLIMITED_INSTANCES ,
186171 sizeof (buf ), sizeof (buf ), 0 , NULL );
187172 if (r_sys_create_child_proc_w32 (cmd , NULL , NULL , NULL )) {
188173 if (ConnectNamedPipe (r2pipe -> pipe , NULL )) {
@@ -194,9 +179,9 @@ static int w32_createPipe(R2Pipe *r2pipe, const char *cmd) {
194179#endif
195180
196181#if HAVE_R2PIPE
197- static R2Pipe * r2p_open_pipes (R2Pipe * r2p ) {
182+ static R2Pipe * r2p_open_pipes (R2Pipe * r2p ) {
198183 R_RETURN_VAL_IF_FAIL (r2p , NULL );
199- #if R2__UNIX__ || defined(__CYGWIN__ )
184+ #if R2__UNIX__ || defined (__CYGWIN__ )
200185 char * out = r_sys_getenv ("R2PIPE_IN" );
201186 char * in = r_sys_getenv ("R2PIPE_OUT" );
202187 int done = false;
@@ -217,7 +202,7 @@ static R2Pipe* r2p_open_pipes(R2Pipe* r2p) {
217202 free (out );
218203 return r2p ;
219204#else
220- R_LOG_ERROR ("r2pipe_open(NULL) not supported on this platform" );
205+ R_LOG_ERROR ("r2pipe_open (NULL) not supported on this platform" );
221206 return NULL ;
222207#endif
223208}
@@ -230,6 +215,9 @@ static R2Pipe *r2pipe_new(void) {
230215 r2pipe -> output [0 ] = r2pipe -> output [1 ] = -1 ;
231216#endif
232217 r2pipe -> child = NO_CHILD ;
218+ /* init http support fields */
219+ r2pipe -> http_url = NULL ;
220+ r2pipe -> is_http = false;
233221 return r2pipe ;
234222}
235223
@@ -244,8 +232,8 @@ R_API R2Pipe *r2pipe_open_dl(const char *libr_path) {
244232#if HAVE_R2PIPE
245233 R_RETURN_VAL_IF_FAIL (libr_path , NULL );
246234 void * libr = r_lib_dl_open (libr_path , false);
247- void * (* rnew )() = r_lib_dl_sym (libr , "r_core_new" );
248- char * (* rcmd )(void * c , const char * cmd ) = r_lib_dl_sym (libr , "r_core_cmd_str" );
235+ void * (* rnew ) () = r_lib_dl_sym (libr , "r_core_new" );
236+ char * (* rcmd ) (void * c , const char * cmd ) = r_lib_dl_sym (libr , "r_core_cmd_str" );
249237
250238 if (rnew && rcmd ) {
251239 R2Pipe * r2pipe = r2pipe_new ();
@@ -261,12 +249,26 @@ R_API R2Pipe *r2pipe_open_dl(const char *libr_path) {
261249 return NULL ;
262250}
263251
264- R_API R2Pipe * r2pipe_open (const char * R_NULLABLE cmd ) {
252+ R_API R2Pipe * r2pipe_open (const char * R_NULLABLE cmd ) {
265253#if HAVE_R2PIPE
266254 R2Pipe * r2p = r2pipe_new ();
267255 if (!r2p ) {
268256 return NULL ;
269257 }
258+ /* HTTP/r2web mode: if the command is a http (s):// or r2web:// URL,
259+ * store it in the r2pipe and use HTTP POST for commands. */
260+ if (cmd && (r_str_startswith (cmd , "http://" ) || r_str_startswith (cmd , "https://" ) || r_str_startswith (cmd , "r2web://" ))) {
261+ char * u = NULL ;
262+ if (r_str_startswith (cmd , "r2web://" )) {
263+ u = r_str_newf ("http://%s" , cmd + sizeof ("r2web://" ) - 1 );
264+ } else {
265+ u = strdup (cmd );
266+ }
267+ r2p -> http_url = u ;
268+ r2p -> is_http = true;
269+ r2p -> child = NO_CHILD ;
270+ return r2p ;
271+ }
270272 if (R_STR_ISEMPTY (cmd )) {
271273 r2p -> child = NO_CHILD ;
272274 return r2p_open_pipes (r2p );
@@ -351,6 +353,11 @@ R_API R2Pipe *r2pipe_open(const char * R_NULLABLE cmd) {
351353R_API char * r2pipe_cmd (R2Pipe * r2p , const char * str ) {
352354#if HAVE_R2PIPE
353355 R_RETURN_VAL_IF_FAIL (r2p && str , NULL );
356+ /* HTTP mode: POST the command to the configured endpoint and return the response */
357+ if (r2p -> is_http ) {
358+ int len = 0 ;
359+ return r_socket_http_post (r2p -> http_url , NULL , str , NULL , & len );
360+ }
354361 if (!* str || !r2pipe_write (r2p , str )) {
355362 r_sys_perror ("r2pipe_write" );
356363 return NULL ;
@@ -391,7 +398,7 @@ R_API char *r2pipe_cmdf(R2Pipe *r2p, const char *fmt, ...) {
391398 }
392399 va_end (ap2 );
393400 va_end (ap );
394- return (char * )fmt ;
401+ return (char * )fmt ;
395402#else
396403 return NULL ;
397404#endif
0 commit comments