* Fix make install for hud (thanks l0gic)
* Enhacements for the r_cons_hud - double-ESC to quit menu - tab and up/down arrows select row - first row is executed if enter is pressed * Add ?y[ynkm] to - ?iy ?in ask user with yesno dialogs - ?im msg show message - ?ik press any key * Add hud.once eval var to run hud forever * CC != CC*
This commit is contained in:
parent
d64b876e73
commit
6ee952c388
4
Makefile
4
Makefile
|
@ -116,8 +116,8 @@ install: install-doc install-man
|
|||
for a in ${DATADIRS} ; do \
|
||||
(cd $$a ; ${MAKE} install LIBDIR=${LIBDIR} PREFIX=${PREFIX} DESTDIR=${DESTDIR} ); \
|
||||
done
|
||||
mkdir -p ${DESTDIR}/${LIBDIR}/radare2/hud
|
||||
cp -f libr/core/hud/main ${DESTDIR}/${LIBDIR}/radare2/hud/
|
||||
mkdir -p ${DESTDIR}/${LIBDIR}/radare2/${VERSION}/hud
|
||||
cp -f libr/core/hud/main ${DESTDIR}/${LIBDIR}/radare2/${VERSION}/hud/
|
||||
|
||||
install-pkgconfig-symlink:
|
||||
@${INSTALL_DIR} ${DESTDIR}/${LIBDIR}/pkgconfig
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* radare - LGPL - Copyright 2008-2011 nibble<develsec.org> + pancake<nopcode.org> */
|
||||
/* radare - LGPL - Copyright 2008-2012 nibble<develsec.org>, pancake<nopcode.org> */
|
||||
|
||||
#include <r_anal.h>
|
||||
|
||||
|
@ -280,27 +280,31 @@ struct r_range_t *r_meta_ranges(RMeta *m)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void printmetaitem(RMeta *m, RMetaItem *d) {
|
||||
static void printmetaitem(RMeta *m, RMetaItem *d, int rad) {
|
||||
char *str = r_str_unscape (d->str);
|
||||
if (str) {
|
||||
if (d->type=='s' && !*str)
|
||||
return;
|
||||
r_str_sanitize (str);
|
||||
m->printf ("%s %d %s @ 0x%08"PFMT64x"\n",
|
||||
r_meta_type_to_string (d->type),
|
||||
(int)(d->to-d->from), str, d->from);
|
||||
if (rad)
|
||||
m->printf ("%s %d %s @ 0x%08"PFMT64x"\n",
|
||||
r_meta_type_to_string (d->type),
|
||||
(int)(d->to-d->from), str, d->from);
|
||||
else
|
||||
m->printf ("0x%08"PFMT64x" %s\n",
|
||||
d->from, str);
|
||||
free (str);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Deprecate
|
||||
R_API int r_meta_list(RMeta *m, int type) {
|
||||
R_API int r_meta_list(RMeta *m, int type, int rad) {
|
||||
int count = 0;
|
||||
RListIter *iter;
|
||||
RMetaItem *d;
|
||||
r_list_foreach (m->data, iter, d) {
|
||||
if (d->type == type || type == R_META_TYPE_ANY) {
|
||||
printmetaitem (m, d);
|
||||
printmetaitem (m, d, rad);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -414,7 +414,11 @@ R_API void r_cons_show_cursor (int cursor) {
|
|||
* If you doesn't use this order you'll probably loss your terminal properties.
|
||||
*
|
||||
*/
|
||||
static int oldraw = -1;
|
||||
R_API void r_cons_set_raw(int is_raw) {
|
||||
if (oldraw != -1)
|
||||
if (is_raw == oldraw)
|
||||
return;
|
||||
#if __UNIX__
|
||||
if (is_raw) tcsetattr (0, TCSANOW, &I.term_raw);
|
||||
else tcsetattr (0, TCSANOW, &I.term_buf);
|
||||
|
@ -425,6 +429,7 @@ R_API void r_cons_set_raw(int is_raw) {
|
|||
#warning No raw console supported for this platform
|
||||
#endif
|
||||
fflush (stdout);
|
||||
oldraw = is_raw;
|
||||
}
|
||||
|
||||
R_API void r_cons_invert(int set, int color) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* radare - LGPL - Copyright 2008-2012 pancake<nopcode.org> */
|
||||
|
||||
#include <r_cons.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if 0
|
||||
TODO?
|
||||
|
@ -68,9 +70,10 @@ static char *strmatch (char *pos, char *buf) {
|
|||
}
|
||||
|
||||
R_API char *r_cons_hud(RList *list) {
|
||||
int n, i = 0;
|
||||
int n, j, i = 0;
|
||||
int ch, nch;
|
||||
char buf[128];
|
||||
int choose = 0;
|
||||
char *p, buf[128];
|
||||
RListIter *iter;
|
||||
char *match = NULL;
|
||||
void *pos;
|
||||
|
@ -84,39 +87,62 @@ R_API char *r_cons_hud(RList *list) {
|
|||
r_list_foreach (list, iter, pos) {
|
||||
if (!buf[0] || strmatch (pos, buf)) {
|
||||
char *x = strchr (pos, '\t');
|
||||
if (x) *x = 0;
|
||||
// remove \t.*
|
||||
r_cons_printf (" - %s\n", pos);
|
||||
if (x) *x = '\t';
|
||||
if (n==0) match = pos;
|
||||
if (!choose || n>=choose) {
|
||||
if (x) *x = 0;
|
||||
p = strdup (pos);
|
||||
for (j=0; p[j]; j++) {
|
||||
if (strchr (buf, p[j]))
|
||||
p[j] = toupper (p[j]);
|
||||
}
|
||||
r_cons_printf (" - %s\n", p);
|
||||
free (p);
|
||||
if (x) *x = '\t';
|
||||
if (n==0) match = pos;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
r_cons_visual_flush ();
|
||||
ch = r_cons_readchar ();
|
||||
nch = r_cons_arrow_to_hjkl (ch);
|
||||
//eprintf ("%d %d\n", ch, nch); sleep (1);
|
||||
//ceprintf ("%c %d\n", ch, nch); sleep (1);
|
||||
if (nch == 'j' && ch != 'j') {
|
||||
if (choose+1 < n)
|
||||
choose++;
|
||||
} else if (nch == 'k' && ch != 'k') {
|
||||
if (choose>=0)
|
||||
choose--;
|
||||
} else
|
||||
switch (ch) {
|
||||
case 9: // \t
|
||||
if (choose+1 < n)
|
||||
choose++;
|
||||
break;
|
||||
case 10: // \n
|
||||
case 13: // \r
|
||||
choose = 0;
|
||||
if (!*buf)
|
||||
return NULL;
|
||||
if (n == 1) {
|
||||
if (n >= 1) {
|
||||
//eprintf ("%s\n", buf);
|
||||
//i = buf[0] = 0;
|
||||
return strdup (match);
|
||||
} // no match!
|
||||
break;
|
||||
case 23: // ^w
|
||||
choose = 0;
|
||||
i = buf[0] = 0;
|
||||
break;
|
||||
case 27: // ignore
|
||||
break;
|
||||
case 0x1b: // ESC
|
||||
return NULL;
|
||||
case 127: // bs
|
||||
choose = 0;
|
||||
if (i<1) return NULL;
|
||||
buf[--i] = 0;
|
||||
break;
|
||||
default:
|
||||
choose = 0;
|
||||
buf[i++] = ch;
|
||||
buf[i] = 0;
|
||||
break;
|
||||
|
@ -125,6 +151,28 @@ R_API char *r_cons_hud(RList *list) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
R_API char *r_cons_hud_path(const char *path, int dir) {
|
||||
// TODO
|
||||
eprintf ("TODO\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: Add fmt support
|
||||
R_API char *r_cons_message(const char *msg) {
|
||||
int cols, rows;
|
||||
int len = strlen (msg);
|
||||
cols = r_cons_get_size (&rows);
|
||||
|
||||
r_cons_clear();
|
||||
r_cons_gotoxy ((cols-len)/2, rows/2); // XXX
|
||||
/// TODO: add square, or talking clip here
|
||||
r_cons_printf ("%s\n", msg);
|
||||
r_cons_flush ();
|
||||
r_cons_gotoxy (0, rows-2); // XXX
|
||||
r_cons_any_key ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef MAIN
|
||||
main() {
|
||||
char *res;
|
||||
|
|
|
@ -3,9 +3,34 @@
|
|||
#include <r_cons.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
//__UNIX__
|
||||
#include <poll.h>
|
||||
static int is_fd_ready(int fd) {
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
if (fd==-1)
|
||||
return 0;
|
||||
FD_ZERO (&rfds);
|
||||
FD_SET (fd, &rfds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1;
|
||||
if (select (1, &rfds, NULL, NULL, &tv) == -1)
|
||||
return 0;
|
||||
return 1;
|
||||
return !FD_ISSET (0, &rfds);
|
||||
}
|
||||
#endif
|
||||
|
||||
R_API int r_cons_arrow_to_hjkl(int ch) {
|
||||
if (ch==0x1b) {
|
||||
#if 0
|
||||
//__UNIX__
|
||||
if (!is_fd_ready (0))
|
||||
return 0;
|
||||
#endif
|
||||
ch = r_cons_readchar ();
|
||||
if (!ch) return 0;
|
||||
switch (ch) {
|
||||
case 0x1b:
|
||||
ch = 'q'; // XXX: must be 0x1b (R_CONS_KEY_ESC)
|
||||
|
@ -128,7 +153,7 @@ R_API int r_cons_readchar() {
|
|||
HANDLE h = GetStdHandle (STD_INPUT_HANDLE);
|
||||
GetConsoleMode (h, &mode);
|
||||
SetConsoleMode (h, 0); // RAW
|
||||
ret = ReadConsole (h, buf,1, &out, NULL);
|
||||
ret = ReadConsole (h, buf, 1, &out, NULL);
|
||||
if (!ret)
|
||||
return -1;
|
||||
SetConsoleMode (h, mode);
|
||||
|
|
|
@ -1408,18 +1408,33 @@ static int cmd_help(void *data, const char *input) {
|
|||
}
|
||||
break;
|
||||
case 'i': // input num
|
||||
{
|
||||
r_cons_flush ();
|
||||
char foo[1024];
|
||||
for (input++; *input==' '; input++);
|
||||
// TODO: use prompt input
|
||||
eprintf ("%s: ", input);
|
||||
fgets (foo, sizeof (foo)-1, stdin);
|
||||
foo[strlen (foo)-1] = 0;
|
||||
free (core->yank);
|
||||
core->yank = (ut8 *)strdup (foo);
|
||||
core->yank_len = strlen (foo);
|
||||
core->num->value = r_num_math (core->num, foo);
|
||||
if (input[1]=='m') {
|
||||
r_cons_message (input+2);
|
||||
} else
|
||||
if (input[1]=='k') {
|
||||
r_cons_any_key ();
|
||||
} else
|
||||
if (input[1]=='y') {
|
||||
for (input+=2; *input==' '; input++);
|
||||
core->num->value =
|
||||
r_cons_yesno (1, "%s? (Y/n)", input);
|
||||
} else
|
||||
if (input[1]=='n') {
|
||||
for (input+=2; *input==' '; input++);
|
||||
core->num->value =
|
||||
r_cons_yesno (0, "%s? (y/N)", input);
|
||||
} else {
|
||||
char foo[1024];
|
||||
r_cons_flush ();
|
||||
for (input++; *input==' '; input++);
|
||||
// TODO: use prompt input
|
||||
eprintf ("%s: ", input);
|
||||
fgets (foo, sizeof (foo)-1, stdin);
|
||||
foo[strlen (foo)-1] = 0;
|
||||
free (core->yank);
|
||||
core->yank = (ut8 *)strdup (foo);
|
||||
core->yank_len = strlen (foo);
|
||||
core->num->value = r_num_math (core->num, foo);
|
||||
}
|
||||
break;
|
||||
case 't': {
|
||||
|
@ -1437,8 +1452,16 @@ static int cmd_help(void *data, const char *input) {
|
|||
" ? eip-0x804800 ; show hex and dec result for this math expr\n"
|
||||
" ?v eip-0x804800 ; show hex value of math expr\n"
|
||||
" ?= eip-0x804800 ; same as above without user feedback\n"
|
||||
" ?? [cmd] ; ? == 0 run command when math matches\n"
|
||||
" ?i prompt ; prompt for number and store in $$?\n"
|
||||
" ?? [cmd] ; ? == 0 run command when math matches\n"
|
||||
" ?i[ynmk] prompt ; prompt for number or Yes,No,Msg,Key and store in $$?\n"
|
||||
#if DONE
|
||||
//BUT NOT DOCUMENTED AT ALL
|
||||
" ?iy prompt ; yesno input prompt\n"
|
||||
" ?in prompt ; yesno input prompt\n"
|
||||
" ?im message ; show message centered in screen\n"
|
||||
" ?ik ; press any key input dialog\n"
|
||||
#endif
|
||||
" ?I hudfile ; load hud menu with given file\n"
|
||||
" ?d opcode ; describe opcode for asm.arch\n"
|
||||
" ?e string ; echo string\n"
|
||||
" ?r [from] [to] ; generate random number between from-to\n"
|
||||
|
@ -1446,7 +1469,7 @@ static int cmd_help(void *data, const char *input) {
|
|||
" ?k k[=v] ; key-value temporal storage for the user\n"
|
||||
" ?b [num] ; show binary value of number\n"
|
||||
" ?f [num] [str] ; map each bit of the number as flag string index\n"
|
||||
" ?p vaddr ; give physical address for given vaddr\n"
|
||||
" ?p vaddr ; get physical address for given vaddr\n"
|
||||
" ?s from to step ; sequence of numbers from to by steps\n"
|
||||
" ?S addr ; return section name of given address\n"
|
||||
" ?x num|0xnum|str; returns the hexpair of number or string\n"
|
||||
|
@ -4436,7 +4459,7 @@ static int cmd_meta(void *data, const char *input) {
|
|||
char file[1024];
|
||||
switch (*input) {
|
||||
case '*':
|
||||
r_meta_list (core->anal->meta, R_META_TYPE_ANY);
|
||||
r_meta_list (core->anal->meta, R_META_TYPE_ANY, 1);
|
||||
break;
|
||||
case 't':
|
||||
switch (input[1]) {
|
||||
|
@ -4544,8 +4567,10 @@ static int cmd_meta(void *data, const char *input) {
|
|||
}
|
||||
break;
|
||||
case '\0':
|
||||
r_meta_list (core->anal->meta, input[0], 0);
|
||||
break;
|
||||
case '*':
|
||||
r_meta_list (core->anal->meta, input[0]);
|
||||
r_meta_list (core->anal->meta, input[0], 1);
|
||||
break;
|
||||
case '!':
|
||||
{
|
||||
|
|
|
@ -504,6 +504,8 @@ R_API int r_core_config_init(RCore *core) {
|
|||
r_config_set_cb (cfg, "dbg.trace.tag", "0xff", &config_tracetag_callback);
|
||||
r_config_set_cb (cfg, "fs.view", "normal", &config_fsview_callback);
|
||||
r_config_desc (cfg, "fs.view", "Set visibility options for filesystems");
|
||||
r_config_set (cfg, "hud.once", "false");
|
||||
r_config_desc (cfg, "hud.once", "run");
|
||||
r_config_set (cfg, "bin.strings", "true");
|
||||
p = r_sys_getenv ("EDITOR");
|
||||
#if __WINDOWS__
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
add comment ?i Comment;CC `?y`
|
||||
list comments CC;?ik
|
||||
change block size ?i block size;b `?y`
|
||||
analyze all aa
|
||||
analyze function af
|
||||
analyze preludes ap
|
||||
|
@ -5,17 +8,20 @@ continue process execution dc;?i
|
|||
disable colors e scr.color=0
|
||||
enable colors e scr.color=1
|
||||
hide bytes in disassembly e asm.bytes=0
|
||||
list imports ii;?i
|
||||
list sections iS;?i
|
||||
list symbols is;?i
|
||||
run command ?i cmd;`?y`;?i
|
||||
list imports ii;?ik
|
||||
list sections iS;?ik
|
||||
list symbols is;?ik
|
||||
run command ?i cmd;`?y`;?ik
|
||||
seek to entrypoint s entry0
|
||||
seek to main s main
|
||||
set breakpoint db;?i new breakpoint address;db `?y`
|
||||
show backtrace dbt;?i
|
||||
show backtrace dbt;?ik
|
||||
show bytes in disassembly e asm.bytes=1
|
||||
show debugger register values dr;?i
|
||||
show process memory maps dm;?i
|
||||
step instruction sr pc;pd 1;ds;?i
|
||||
show debugger register values dr;?ik
|
||||
show process memory maps dm;?ik
|
||||
step instruction sr pc;pd 1;ds;?ik
|
||||
write string ?i string;w `?y`
|
||||
write hexadecimal data in current offset ?i hexpairs;wx `?y`
|
||||
xor current block with hexpair key ?i hexpair key;wox `?y`
|
||||
edit eval configuration Veq
|
||||
calculator ?i enter math expression;? `?y`;?ik
|
||||
|
|
|
@ -539,7 +539,9 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
|
|||
r_core_visual_prompt (core);
|
||||
break;
|
||||
case '_':
|
||||
while (r_core_visual_hud (core));
|
||||
if (r_config_get_i (core->config, "hud.once"))
|
||||
r_core_visual_hud (core);
|
||||
else while (r_core_visual_hud (core));
|
||||
break;
|
||||
case ';':
|
||||
r_cons_printf ("Enter a comment: ('-' to remove, '!' to use $EDITOR)\n");
|
||||
|
@ -601,38 +603,40 @@ R_API int r_core_visual_cmd(RCore *core, int ch) {
|
|||
zoom = !zoom;
|
||||
break;
|
||||
case '?':
|
||||
r_cons_clear00 ();
|
||||
r_cons_printf (
|
||||
"\nVisual mode help:\n\n"
|
||||
" >||< - seek aligned to block size\n"
|
||||
" hjkl - move around\n"
|
||||
" HJKL - move around faster\n"
|
||||
" pP - rotate print modes\n"
|
||||
" /*+-[] - change block size, [] = resize scr.cols\n"
|
||||
" cC - toggle cursor and colors\n"
|
||||
" gG - go seek to begin and end of file (0-$s)\n"
|
||||
" d[f?] - define function, data, code, ..\n"
|
||||
" x - show xrefs to seek between them\n"
|
||||
" sS - step / step over\n"
|
||||
" e - edit eval configuration variables\n"
|
||||
" t - track flags (browse symbols, functions..)\n"
|
||||
" T - browse anal info and comments\n"
|
||||
" v - visual code analysis menu\n"
|
||||
" fF - seek next/prev function/flag/hit (scr.fkey)\n"
|
||||
" B - toggle automatic block size\n"
|
||||
" uU - undo/redo seek\n"
|
||||
" yY - copy and paste selection\n"
|
||||
" mK/'K - mark/go to Key (any key)\n"
|
||||
" M - show mount points\n"
|
||||
" _ - enter hud mode\n"
|
||||
" :cmd - run radare command\n"
|
||||
" ;[-]cmt - add/remove comment\n"
|
||||
" . - seek to program counter\n"
|
||||
" z - toggle zoom mode\n"
|
||||
" q - back to radare shell\n");
|
||||
"Visual mode help:\n"
|
||||
" >||< seek aligned to block size\n"
|
||||
" hjkl move around\n"
|
||||
" HJKL move around faster\n"
|
||||
" pP rotate print modes\n"
|
||||
" /*+-[] change block size, [] = resize scr.cols\n"
|
||||
" cC toggle cursor and colors\n"
|
||||
" gG go seek to begin and end of file (0-$s)\n"
|
||||
" d[f?] define function, data, code, ..\n"
|
||||
" x show xrefs to seek between them\n"
|
||||
" sS step / step over\n"
|
||||
" e edit eval configuration variables\n"
|
||||
" t track flags (browse symbols, functions..)\n"
|
||||
" T browse anal info and comments\n"
|
||||
" v visual code analysis menu\n"
|
||||
" fF seek next/prev function/flag/hit (scr.fkey)\n"
|
||||
" B toggle automatic block size\n"
|
||||
" uU undo/redo seek\n"
|
||||
" yY copy and paste selection\n"
|
||||
" mK/'K mark/go to Key (any key)\n"
|
||||
" M show mount points\n"
|
||||
" _ enter hud mode\n"
|
||||
" :cmd run radare command\n"
|
||||
" ;[-]cmt add/remove comment\n"
|
||||
" . seek to program counter\n"
|
||||
" z toggle zoom mode\n"
|
||||
" q back to radare shell\n");
|
||||
r_cons_flush ();
|
||||
r_cons_any_key ();
|
||||
r_cons_clear00 ();
|
||||
break;
|
||||
case 0x1b:
|
||||
case 'q':
|
||||
case 'Q':
|
||||
return R_FALSE;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* radare - LGPL - Copyright 2009-2011 // nibble<.ds@gmail.com> + pancake<nopcode.org> */
|
||||
/* radare - LGPL - Copyright 2009-2012 // nibble<.ds@gmail.com> + pancake<nopcode.org> */
|
||||
|
||||
#ifndef _INCLUDE_R_ANAL_H_
|
||||
#define _INCLUDE_R_ANAL_H_
|
||||
|
@ -559,7 +559,7 @@ R_API int r_meta_add(RMeta *m, int type, ut64 from, ut64 size, const char *str);
|
|||
R_API struct r_meta_item_t *r_meta_find(RMeta *m, ut64 off, int type, int where);
|
||||
R_API int r_meta_cleanup(RMeta *m, ut64 from, ut64 to);
|
||||
R_API const char *r_meta_type_to_string(int type);
|
||||
R_API int r_meta_list(RMeta *m, int type);
|
||||
R_API int r_meta_list(RMeta *m, int type, int rad);
|
||||
R_API void r_meta_item_free(void *_item);
|
||||
R_API RMetaItem *r_meta_item_new(int type);
|
||||
|
||||
|
|
|
@ -227,6 +227,7 @@ R_API int r_cons_yesno(int def, const char *fmt, ...);
|
|||
R_API void r_cons_set_cup(int enable);
|
||||
R_API void r_cons_column(int c);
|
||||
R_API int r_cons_get_column();
|
||||
R_API char *r_cons_message(const char *msg);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* radare - LGPL - Copyright 2006-2011 pancake<nopcode.org> */
|
||||
/* radare - LGPL - Copyright 2006-2012 pancake<nopcode.org> */
|
||||
|
||||
#include <errno.h>
|
||||
#include <r_types.h>
|
||||
|
@ -308,20 +308,18 @@ R_API int r_socket_flush(RSocket *s) {
|
|||
/* returns -1 on error, 0 is false, 1 is true */
|
||||
R_API int r_socket_ready(RSocket *s, int secs, int usecs) {
|
||||
#if __UNIX__
|
||||
int ret;
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = s->fd;
|
||||
fds[0].events = POLLIN|POLLPRI;
|
||||
fds[0].revents = POLLNVAL|POLLHUP|POLLERR;
|
||||
ret = poll((struct pollfd *)&fds, 1, usecs);
|
||||
return ret;
|
||||
return poll((struct pollfd *)&fds, 1, usecs);
|
||||
#elif __WINDOWS__
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
if (s->fd==-1)
|
||||
return -1;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(s->fd, &rfds);
|
||||
FD_ZERO (&rfds);
|
||||
FD_SET (s->fd, &rfds);
|
||||
tv.tv_sec = secs;
|
||||
tv.tv_usec = usecs;
|
||||
if (select (1, &rfds, NULL, NULL, &tv) == -1)
|
||||
|
|
Loading…
Reference in New Issue