1.1 --- a/libr/cons/cons.c Sun Feb 05 02:30:08 2012 +0100
1.2 +++ b/libr/cons/cons.c Sun Feb 05 02:39:04 2012 +0100
1.3 @@ -119,6 +119,7 @@
1.4 if (!SetConsoleCtrlHandler ((PHANDLER_ROUTINE)__w32_control, TRUE))
1.5 eprintf ("r_cons: Cannot set control console handler\n");
1.6 #endif
1.7 + I.pager = NULL; /* no pager by default */
1.8 //r_cons_palette_init(NULL);
1.9 r_cons_reset ();
1.10 return &I;
1.11 @@ -223,7 +224,15 @@
1.12 return;
1.13 r_cons_filter ();
1.14 if (I.is_interactive) {
1.15 - if (I.buffer_len > CONS_MAX_USER) {
1.16 + /* Use a pager if the output doesn't fit on the terminal window. */
1.17 + if (I.pager && *(I.pager)
1.18 + && I.buffer_len > 0
1.19 + && r_str_char_count (I.buffer, '\n') >= I.rows) {
1.20 + I.buffer[I.buffer_len-1] = 0;
1.21 + r_sys_cmd_str_full(I.pager, I.buffer, NULL, NULL, NULL);
1.22 + r_cons_reset ();
1.23 +
1.24 + } else if (I.buffer_len > CONS_MAX_USER) {
1.25 if (!r_cons_yesno ('n',"Do you want to print %d bytes? (y/N)",
1.26 I.buffer_len)) {
1.27 r_cons_reset ();
2.1 --- a/libr/core/config.c Sun Feb 05 02:30:08 2012 +0100
2.2 +++ b/libr/core/config.c Sun Feb 05 02:39:04 2012 +0100
2.3 @@ -1,4 +1,4 @@
2.4 -/* radare - LGPL - Copyright 2009-2011 pancake<nopcode.org> */
2.5 +/* radare - LGPL - Copyright 2009-2012 pancake<nopcode.org> */
2.6
2.7 #include <r_core.h>
2.8
2.9 @@ -393,6 +393,15 @@
2.10 return R_TRUE;
2.11 }
2.12
2.13 +static int config_pager_callback(void *user, void *data) {
2.14 + RCore *core = (RCore *) user;
2.15 + RConfigNode *node = (RConfigNode *) data;
2.16 +
2.17 + /* Let cons know we have a new pager. */
2.18 + core->cons->pager = node->value;
2.19 + return R_TRUE;
2.20 +}
2.21 +
2.22 #define SLURP_LIMIT (10*1024*1024)
2.23 R_API int r_core_config_init(RCore *core) {
2.24 RConfig *cfg = cfg = core->config = r_config_new (core);
2.25 @@ -475,6 +484,7 @@
2.26 r_config_desc (cfg, "asm.syntax", "Select assembly syntax");
2.27 r_config_set_cb (cfg, "asm.profile", "default", &config_asmprofile_callback);
2.28 r_config_desc (cfg, "asm.profile", "configure disassembler (default, simple, gas, smart, debug, full)");
2.29 + /* misc */
2.30 #if LIL_ENDIAN
2.31 r_config_set_cb (cfg, "cfg.bigendian", "false", &config_bigendian_callback);
2.32 #else
2.33 @@ -493,7 +503,7 @@
2.34 r_config_desc (cfg, "cfg.wseek", "Seek after write");
2.35 r_config_set_i (cfg, "cfg.hashlimit", SLURP_LIMIT);
2.36 r_config_desc (cfg, "cfg.hashlimit", "If the file its bigger than hashlimit don't calculate the hash");
2.37 -
2.38 + /* debug */
2.39 r_config_set_i (cfg, "dbg.follow", 32);
2.40 r_config_desc (cfg, "dbg.follow", "Follow program counter when pc > core->offset + dbg.follow");
2.41 r_config_set_cb (cfg, "dbg.backend", "native", &config_dbgbackend_callback);
2.42 @@ -541,6 +551,8 @@
2.43 (core->print->flags&R_PRINT_FLAGS_COLOR)?"true":"false",
2.44 &config_color_callback);
2.45 r_config_desc (cfg, "scr.color", "Enable/Disable colors");
2.46 + r_config_set_cb (cfg, "scr.pager", "", &config_pager_callback);
2.47 + r_config_desc (cfg, "scr.pager", "Select pager program (used if output doesn't fit on window)");
2.48 //r_config_set_cb (cfg, "scr.fkey", "function", &config_scrfkey_callback);
2.49 r_config_set_cb (cfg, "scr.fkey", "hit", &config_scrfkey_callback);
2.50 r_config_desc (cfg, "scr.fkey", "Select the seek mode in visual");
3.1 --- a/libr/include/r_cons.h Sun Feb 05 02:30:08 2012 +0100
3.2 +++ b/libr/include/r_cons.h Sun Feb 05 02:39:04 2012 +0100
3.3 @@ -71,6 +71,9 @@
3.4 LPDWORD term_raw, term_buf;
3.5 #endif
3.6 RNum *num;
3.7 + /* Pager (like more or less) to use if the output doesn't fit on the
3.8 + * current window. If NULL or "" no pager is used. */
3.9 + char *pager;
3.10 } RCons;
3.11
3.12 // XXX THIS MUST BE A SINGLETON AND WRAPPED INTO RCons */
4.1 --- a/libr/include/r_util.h Sun Feb 05 02:30:08 2012 +0100
4.2 +++ b/libr/include/r_util.h Sun Feb 05 02:39:04 2012 +0100
4.3 @@ -423,7 +423,7 @@
4.4 R_API int r_sys_setenv(const char *key, const char *value);
4.5 R_API char *r_sys_getdir();
4.6 R_API int r_sys_chdir(const char *s);
4.7 -R_API char *r_sys_cmd_str_full(const char *cmd, const char *input, int *len, char **sterr);
4.8 +R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr);
4.9 #if __WINDOWS__
4.10 R_API char *r_sys_cmd_str_w32(const char *cmd);
4.11 #endif
5.1 --- a/libr/util/sys.c Sun Feb 05 02:30:08 2012 +0100
5.2 +++ b/libr/util/sys.c Sun Feb 05 02:39:04 2012 +0100
5.3 @@ -209,49 +209,51 @@
5.4 }
5.5
5.6 #if __UNIX__
5.7 -R_API char *r_sys_cmd_str_full(const char *cmd, const char *input, int *len, char **sterr) {
5.8 - char buffer[1024], *output = NULL;
5.9 +R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) {
5.10 + char buffer[1024], *outputptr = NULL;
5.11 char *inputptr = (char *)input;
5.12 int pid, bytes = 0, status;
5.13 int sh_in[2], sh_out[2], sh_err[2];
5.14
5.15 if (len) *len = 0;
5.16 if (pipe (sh_in))
5.17 - return NULL;
5.18 - if (pipe (sh_out)) {
5.19 - close (sh_in[0]);
5.20 - close (sh_in[1]);
5.21 - return NULL;
5.22 + return R_FALSE;
5.23 + if (output) {
5.24 + if (pipe (sh_out)) {
5.25 + close (sh_in[0]);
5.26 + close (sh_in[1]);
5.27 + return R_FALSE;
5.28 + }
5.29 }
5.30 if (pipe (sh_err)) {
5.31 close (sh_in[0]);
5.32 close (sh_in[1]);
5.33 close (sh_out[0]);
5.34 close (sh_out[1]);
5.35 - return NULL;
5.36 + return R_FALSE;
5.37 }
5.38
5.39 switch ((pid=fork ())) {
5.40 case -1:
5.41 - return NULL;
5.42 + return R_FALSE;
5.43 case 0:
5.44 dup2 (sh_in[0], 0); close (sh_in[0]); close (sh_in[1]);
5.45 - dup2 (sh_out[1], 1); close (sh_out[0]); close (sh_out[1]);
5.46 + if (output) { dup2 (sh_out[1], 1); close (sh_out[0]); close (sh_out[1]); }
5.47 if (sterr) dup2 (sh_err[1], 2); else close (2);
5.48 close (sh_err[0]); close (sh_err[1]);
5.49 exit (execl ("/bin/sh", "sh", "-c", cmd, (char*)NULL));
5.50 default:
5.51 - output = strdup ("");
5.52 - if (!output)
5.53 - return NULL;
5.54 + outputptr = strdup ("");
5.55 + if (!outputptr)
5.56 + return R_FALSE;
5.57 if (sterr) {
5.58 *sterr = strdup ("");
5.59 if (!*sterr) {
5.60 - free (output);
5.61 - return NULL;
5.62 + free (outputptr);
5.63 + return R_FALSE;
5.64 }
5.65 }
5.66 - close (sh_out[1]);
5.67 + if (output) close (sh_out[1]);
5.68 close (sh_err[1]);
5.69 close (sh_in[0]);
5.70 if (!inputptr || !*inputptr)
5.71 @@ -263,7 +265,8 @@
5.72
5.73 FD_ZERO (&rfds);
5.74 FD_ZERO (&wfds);
5.75 - FD_SET (sh_out[0], &rfds);
5.76 + if (output)
5.77 + FD_SET (sh_out[0], &rfds);
5.78 if (sterr)
5.79 FD_SET (sh_err[0], &rfds);
5.80 if (inputptr && *inputptr)
5.81 @@ -272,46 +275,59 @@
5.82 nfd = select (sh_err[0] + 1, &rfds, &wfds, NULL, NULL);
5.83 if (nfd < 0)
5.84 break;
5.85 - if (FD_ISSET (sh_out[0], &rfds)) {
5.86 + if (output && FD_ISSET (sh_out[0], &rfds)) {
5.87 if ((bytes = read (sh_out[0], buffer, sizeof (buffer)-1)) == 0) break;
5.88 if (len) *len += bytes;
5.89 - output = r_str_concat (output, buffer);
5.90 + outputptr = r_str_concat (outputptr, buffer);
5.91 } else if (FD_ISSET (sh_err[0], &rfds) && sterr) {
5.92 if (read (sh_err[0], buffer, sizeof (buffer)-1) == 0) break;
5.93 *sterr = r_str_concat (*sterr, buffer);
5.94 } else if (FD_ISSET (sh_in[1], &wfds) && inputptr && *inputptr) {
5.95 bytes = write (sh_in[1], inputptr, strlen (inputptr));
5.96 inputptr += bytes;
5.97 - if (!*inputptr) close (sh_in[1]);
5.98 + if (!*inputptr) {
5.99 + close (sh_in[1]);
5.100 + /* If neither stdout nor stderr should be captured,
5.101 + * abort now - nothing more to do for select(). */
5.102 + if (!output && !sterr) break;
5.103 + }
5.104 }
5.105 }
5.106 - close (sh_out[0]);
5.107 + if (output)
5.108 + close (sh_out[0]);
5.109 close (sh_err[0]);
5.110 close (sh_in[1]);
5.111 waitpid (pid, &status, 0);
5.112 if (status != 0) {
5.113 eprintf ("%s: command '%s' returned !0\n", __func__, cmd);
5.114 - return (NULL);
5.115 + return R_FALSE;
5.116 }
5.117
5.118 if (output) {
5.119 - if (*output)
5.120 - return output;
5.121 - free (output);
5.122 + *output = outputptr;
5.123 + } else if (outputptr) {
5.124 + free(outputptr);
5.125 }
5.126 + return R_TRUE;
5.127 }
5.128 - return NULL;
5.129 + return R_FALSE;
5.130 }
5.131 #elif __WINDOWS__
5.132 -R_API char *r_sys_cmd_str_full(const char *cmd, const char *input, int *len, char **sterr) {
5.133 +R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) {
5.134 // TODO: fully implement the rest
5.135 + char *result;
5.136 if (len) *len = 0;
5.137 - return r_sys_cmd_str_w32 (cmd);
5.138 + result = r_sys_cmd_str_w32 (cmd);
5.139 + if (output)
5.140 + *output = result;
5.141 + if (result)
5.142 + return R_TRUE;
5.143 + return R_FALSE;
5.144 }
5.145 #else
5.146 -R_API char *r_sys_cmd_str_full(const char *cmd, const char *input, int *len, char **sterr) {
5.147 +R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) {
5.148 eprintf ("r_sys_cmd_str: not yet implemented for this platform\n");
5.149 - return NULL;
5.150 + return R_FALSE;
5.151 }
5.152 #endif
5.153
5.154 @@ -352,7 +368,10 @@
5.155 }
5.156
5.157 R_API char *r_sys_cmd_str(const char *cmd, const char *input, int *len) {
5.158 - return r_sys_cmd_str_full (cmd, input, len, NULL);
5.159 + char *output;
5.160 + if (r_sys_cmd_str_full (cmd, input, &output, len, NULL))
5.161 + return output;
5.162 + return NULL;
5.163 }
5.164
5.165 R_API int r_sys_rmkdir(const char *dir) {