mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-20 04:43:01 +00:00
* Apply patch from whats implementing '.!'
- Change spaces to tabs - Initial implementation of r_sys_cmd_str_full - support stderr slurping
This commit is contained in:
parent
692f5bbb54
commit
d8b5a660df
@ -133,7 +133,7 @@ static int cmd_interpret(void *data, const char *input) {
|
||||
break;
|
||||
case '!':
|
||||
/* from command */
|
||||
fprintf(stderr, "TODO\n");
|
||||
r_core_cmd_command(core, input+1);
|
||||
break;
|
||||
case '(':
|
||||
//fprintf(stderr, "macro call (%s)\n", input+1);
|
||||
@ -1555,6 +1555,25 @@ R_API int r_core_cmd_file(struct r_core_t *core, const char *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_core_cmd_command(struct r_core_t *core, const char *command)
|
||||
{
|
||||
int len;
|
||||
char *buf = r_sys_cmd_str(command, 0, &len);
|
||||
char *rcmd = buf;
|
||||
char *ptr = buf;
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
while ((ptr = strstr(rcmd, "\n"))) {
|
||||
*ptr = '\0';
|
||||
if (r_core_cmd(core, rcmd, 0) == -1) {
|
||||
fprintf(stderr, "Error running command '%s'\n", rcmd);
|
||||
}
|
||||
rcmd += strlen(rcmd)+1;
|
||||
}
|
||||
r_str_free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_debug(void *data, const char *input) {
|
||||
struct r_core_t *core = (struct r_core_t *)data;
|
||||
char *ptr;
|
||||
|
@ -165,6 +165,11 @@ int main(int argc, char **argv)
|
||||
if (bsize)
|
||||
r_core_block_size (&r, bsize);
|
||||
|
||||
// Load the binary information from rabin2
|
||||
char *command = r_str_concat(strdup(".!rabin2 -reisS "), r.file->filename);
|
||||
r_core_cmd(&r, command, 0);
|
||||
r_str_free(command);
|
||||
|
||||
if (r_config_get_i (&r.config, "cfg.fortunes")) {
|
||||
r_core_cmd (&r, "fo", 0);
|
||||
r_cons_flush();
|
||||
|
@ -78,6 +78,7 @@ R_API int r_core_cmd0(void *user, const char *cmd);
|
||||
R_API int r_core_cmd_init(struct r_core_t *core);
|
||||
R_API char *r_core_cmd_str(struct r_core_t *core, const char *cmd);
|
||||
R_API int r_core_cmd_file(struct r_core_t *core, const char *file);
|
||||
R_API int r_core_cmd_command(struct r_core_t *core, const char *command);
|
||||
R_API int r_core_seek(struct r_core_t *core, ut64 addr, int rb);
|
||||
R_API int r_core_seek_align(struct r_core_t *core, ut64 align, int times);
|
||||
R_API int r_core_block_read(struct r_core_t *core, int next);
|
||||
|
@ -164,8 +164,8 @@ R_API int r_sys_sleep(int secs);
|
||||
R_API int r_sys_usleep(int usecs);
|
||||
R_API const char *r_sys_getenv(const char *key);
|
||||
R_API int r_sys_setenv(const char *key, const char *value, int ow);
|
||||
R_API char *r_sys_cmd_str(const char *cmd, const char *input, int *len);
|
||||
|
||||
R_API char *r_sys_cmd_str_full(const char *cmd, const char *input, int *len, char **sterr);
|
||||
#define r_sys_cmd_str(cmd, input, len) r_sys_cmd_str_full(cmd, input, len, 0)
|
||||
R_API int r_alloca_init();
|
||||
R_API ut8 *r_alloca_bytes(int len);
|
||||
R_API char *r_alloca_str(const char *str);
|
||||
|
264
libr/util/str.c
264
libr/util/str.c
@ -62,24 +62,24 @@ R_API int r_str_delta(char *p, char a, char b)
|
||||
|
||||
R_API int r_str_word_set0(char *str)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
if (str[0]=='\0')
|
||||
return 0;
|
||||
int i;
|
||||
char *p;
|
||||
if (str[0]=='\0')
|
||||
return 0;
|
||||
/* TODO: sync with r1 code */
|
||||
for(i=1,p=str;p[0];p=p+1)if(*p==' '){i++;*p='\0';} // s/ /\0/g
|
||||
return i;
|
||||
for(i=1,p=str;p[0];p=p+1)if(*p==' '){i++;*p='\0';} // s/ /\0/g
|
||||
return i;
|
||||
}
|
||||
|
||||
R_API char *r_str_word_get0(char *str, int idx)
|
||||
{
|
||||
int i;
|
||||
char *ptr = str;
|
||||
if (ptr == NULL)
|
||||
return (char *)nullstr;
|
||||
for (i=0;*ptr && i != idx;i++)
|
||||
ptr = ptr + strlen(ptr) + 1;
|
||||
return ptr;
|
||||
int i;
|
||||
char *ptr = str;
|
||||
if (ptr == NULL)
|
||||
return (char *)nullstr;
|
||||
for (i=0;*ptr && i != idx;i++)
|
||||
ptr = ptr + strlen(ptr) + 1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
R_API int r_str_char_count(const char *string, char ch)
|
||||
@ -93,20 +93,20 @@ R_API int r_str_char_count(const char *string, char ch)
|
||||
|
||||
R_API int r_str_word_count(const char *string)
|
||||
{
|
||||
const char *text, *tmp;
|
||||
int word = 0;
|
||||
const char *text, *tmp;
|
||||
int word = 0;
|
||||
|
||||
for(text=tmp=string;(*text)&&(isseparator(*text));text++);
|
||||
for(text=tmp=string;(*text)&&(isseparator(*text));text++);
|
||||
|
||||
for(word = 0; *text; word++) {
|
||||
for(;*text && !isseparator(*text);text = text +1);
|
||||
tmp = text;
|
||||
for(;*text &&isseparator(*text);text = text +1);
|
||||
if (tmp == text)
|
||||
word-=1;
|
||||
}
|
||||
for(word = 0; *text; word++) {
|
||||
for(;*text && !isseparator(*text);text = text +1);
|
||||
tmp = text;
|
||||
for(;*text &&isseparator(*text);text = text +1);
|
||||
if (tmp == text)
|
||||
word-=1;
|
||||
}
|
||||
|
||||
return word-1;
|
||||
return word-1;
|
||||
}
|
||||
|
||||
R_API char *r_str_ichr(char *str, char chr)
|
||||
@ -119,11 +119,11 @@ R_API char *r_str_ichr(char *str, char chr)
|
||||
|
||||
R_API char *r_str_lchr(char *str, char chr)
|
||||
{
|
||||
int len = strlen(str)+1;
|
||||
for(;len>=0;len--)
|
||||
if (str[len]==chr)
|
||||
return str+len;
|
||||
return NULL;
|
||||
int len = strlen(str)+1;
|
||||
for(;len>=0;len--)
|
||||
if (str[len]==chr)
|
||||
return str+len;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API int r_str_nchr(const char *str, char chr)
|
||||
@ -139,18 +139,18 @@ R_API int r_str_nchr(const char *str, char chr)
|
||||
|
||||
R_API int r_str_nstr(char *from, char *to, int size)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<size;i++)
|
||||
if (from==NULL||to==NULL||from[i]!=to[i])
|
||||
break;
|
||||
return (size!=i);
|
||||
int i;
|
||||
for(i=0;i<size;i++)
|
||||
if (from==NULL||to==NULL||from[i]!=to[i])
|
||||
break;
|
||||
return (size!=i);
|
||||
}
|
||||
|
||||
R_API const char *r_str_chop_ro(const char *str)
|
||||
{
|
||||
if (str)
|
||||
while(str[0]&&iswhitechar(str[0]))
|
||||
str = str + 1;
|
||||
while(str[0]&&iswhitechar(str[0]))
|
||||
str = str + 1;
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -161,24 +161,24 @@ R_API char *r_str_new(char *str)
|
||||
|
||||
R_API char *r_str_chop(char *str)
|
||||
{
|
||||
int len;
|
||||
char *ptr;
|
||||
int len;
|
||||
char *ptr;
|
||||
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
while(str[0]&&iswhitechar(str[0]))
|
||||
str = str + 1;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
if (len>0)
|
||||
for(ptr = str+len-1;ptr!=str;ptr = ptr - 1) {
|
||||
if (iswhitechar(ptr[0]))
|
||||
ptr[0]='\0';
|
||||
else break;
|
||||
}
|
||||
return str;
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
while(str[0]&&iswhitechar(str[0]))
|
||||
str = str + 1;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
if (len>0)
|
||||
for(ptr = str+len-1;ptr!=str;ptr = ptr - 1) {
|
||||
if (iswhitechar(ptr[0]))
|
||||
ptr[0]='\0';
|
||||
else break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
R_API char *r_str_trim(char *str)
|
||||
@ -199,11 +199,11 @@ R_API char *r_str_trim(char *str)
|
||||
/* memccmp("foo.bar", "foo.cow, '.') == 0 */
|
||||
R_API int r_str_ccmp(const char *dst, const char *src, int ch)
|
||||
{
|
||||
int i;
|
||||
for(i=0;src[i] && src[i] != ch; i++)
|
||||
if (dst[i] != src[i])
|
||||
return 1;
|
||||
return 0;
|
||||
int i;
|
||||
for(i=0;src[i] && src[i] != ch; i++)
|
||||
if (dst[i] != src[i])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_str_cmp(const char *a, const char *b, int len)
|
||||
@ -219,49 +219,49 @@ R_API int r_str_cmp(const char *a, const char *b, int len)
|
||||
|
||||
R_API int r_str_ccpy(char *dst, char *src, int ch)
|
||||
{
|
||||
int i;
|
||||
for(i=0;src[i] && src[i] != ch; i++)
|
||||
dst[i] = src[i];
|
||||
dst[i] = '\0';
|
||||
return i;
|
||||
int i;
|
||||
for(i=0;src[i] && src[i] != ch; i++)
|
||||
dst[i] = src[i];
|
||||
dst[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
R_API char *r_str_word_get_first(const char *string)
|
||||
{
|
||||
char *text = (char *)string;
|
||||
char *start = NULL;
|
||||
char *ret = NULL;
|
||||
int len = 0;
|
||||
char *text = (char *)string;
|
||||
char *start = NULL;
|
||||
char *ret = NULL;
|
||||
int len = 0;
|
||||
|
||||
for(;*text &&isseparator(*text);text = text + 1);
|
||||
start = text;
|
||||
for(;*text &&!isseparator(*text);text = text + 1) len++;
|
||||
for(;*text &&isseparator(*text);text = text + 1);
|
||||
start = text;
|
||||
for(;*text &&!isseparator(*text);text = text + 1) len++;
|
||||
|
||||
/* strdup */
|
||||
ret = (char *)malloc(len+1);
|
||||
if (ret == 0) {
|
||||
fprintf(stderr, "Cannot allocate %d bytes.\n", len+1);
|
||||
exit(1);
|
||||
}
|
||||
strncpy(ret, start, len);
|
||||
ret[len]='\0';
|
||||
/* strdup */
|
||||
ret = (char *)malloc(len+1);
|
||||
if (ret == 0) {
|
||||
fprintf(stderr, "Cannot allocate %d bytes.\n", len+1);
|
||||
exit(1);
|
||||
}
|
||||
strncpy(ret, start, len);
|
||||
ret[len]='\0';
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API const char *r_str_get(const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return nullstr_c;
|
||||
return str;
|
||||
if (str == NULL)
|
||||
return nullstr_c;
|
||||
return str;
|
||||
}
|
||||
|
||||
R_API char *r_str_dup(char *ptr, const char *string)
|
||||
{
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
ptr = strdup(string);
|
||||
return ptr;
|
||||
if (ptr)
|
||||
free(ptr);
|
||||
ptr = strdup(string);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// TODO: rename to r_str_dupfmt
|
||||
@ -279,13 +279,13 @@ R_API char *r_str_dup_printf(const char *fmt, ...)
|
||||
|
||||
R_API char *r_str_concat(char *ptr, const char *string)
|
||||
{
|
||||
if (!ptr)
|
||||
if (!ptr)
|
||||
return strdup(string);
|
||||
ptr = realloc(ptr, strlen(string)+strlen(ptr)+1);
|
||||
if (ptr == NULL)
|
||||
return NULL;
|
||||
strcat(ptr, string);
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
R_API char *r_str_concatf(char *ptr, const char *fmt, ...)
|
||||
@ -296,7 +296,7 @@ R_API char *r_str_concatf(char *ptr, const char *fmt, ...)
|
||||
vsnprintf(string, 1023, fmt, ap);
|
||||
ptr = r_str_concat(ptr, string);
|
||||
va_end(ap);
|
||||
return ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
R_API void r_str_concatch(char *x, char y)
|
||||
@ -307,20 +307,20 @@ R_API void r_str_concatch(char *x, char y)
|
||||
|
||||
R_API void *r_str_free(void *ptr)
|
||||
{
|
||||
free (ptr);
|
||||
free (ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API int r_str_inject(char *begin, char *end, char *str, int maxlen)
|
||||
{
|
||||
int len = strlen(end)+1;
|
||||
char *tmp = alloca(len);
|
||||
int len = strlen(end)+1;
|
||||
char *tmp = alloca(len);
|
||||
if (maxlen > 0 && ((strlen(begin)-(end-begin)+strlen(str)) > maxlen))
|
||||
return 0;
|
||||
memcpy(tmp, end, len);
|
||||
strcpy(begin, str);
|
||||
strcat(begin, tmp);
|
||||
return 1;
|
||||
memcpy(tmp, end, len);
|
||||
strcpy(begin, str);
|
||||
strcat(begin, tmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* unstable code */
|
||||
@ -328,11 +328,11 @@ R_API int r_str_inject(char *begin, char *end, char *str, int maxlen)
|
||||
|
||||
// FROM bash::stringlib
|
||||
#define RESIZE_MALLOCED_BUFFER(str,cind,room,csize,sincr) \
|
||||
if ((cind) + (room) >= csize) { \
|
||||
while ((cind) + (room) >= csize) \
|
||||
csize += (sincr); \
|
||||
str = realloc (str, csize); \
|
||||
}
|
||||
if ((cind) + (room) >= csize) { \
|
||||
while ((cind) + (room) >= csize) \
|
||||
csize += (sincr); \
|
||||
str = realloc (str, csize); \
|
||||
}
|
||||
|
||||
/* Replace occurrences of PAT with REP in STRING. If GLOBAL is non-zero,
|
||||
replace all occurrences, otherwise replace only the first.
|
||||
@ -340,42 +340,42 @@ R_API int r_str_inject(char *begin, char *end, char *str, int maxlen)
|
||||
|
||||
static int strsub_memcmp (char *string, char *pat, int len)
|
||||
{
|
||||
int res = 0;
|
||||
while(len--) {
|
||||
if (*pat!='?')
|
||||
res += *string - *pat;
|
||||
string = string+1;
|
||||
pat = pat+1;
|
||||
}
|
||||
return res;
|
||||
int res = 0;
|
||||
while(len--) {
|
||||
if (*pat!='?')
|
||||
res += *string - *pat;
|
||||
string = string+1;
|
||||
pat = pat+1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
R_API char *r_str_sub(char *string, char *pat, char *rep, int global)
|
||||
{
|
||||
int patlen, templen, tempsize, repl, i;
|
||||
char *temp, *r;
|
||||
int patlen, templen, tempsize, repl, i;
|
||||
char *temp, *r;
|
||||
|
||||
patlen = strlen (pat);
|
||||
for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
|
||||
{
|
||||
// if (repl && !memcmp(string + i, pat, patlen)) {
|
||||
if (repl && !strsub_memcmp(string + i, pat, patlen)) {
|
||||
RESIZE_MALLOCED_BUFFER (temp, templen, patlen, tempsize, 4096); //UGLY HACK (patlen * 2));
|
||||
if (temp == NULL)
|
||||
return NULL;
|
||||
for (r = rep; *r; )
|
||||
temp[templen++] = *r++;
|
||||
patlen = strlen (pat);
|
||||
for (temp = (char *)NULL, i = templen = tempsize = 0, repl = 1; string[i]; )
|
||||
{
|
||||
// if (repl && !memcmp(string + i, pat, patlen)) {
|
||||
if (repl && !strsub_memcmp(string + i, pat, patlen)) {
|
||||
RESIZE_MALLOCED_BUFFER (temp, templen, patlen, tempsize, 4096); //UGLY HACK (patlen * 2));
|
||||
if (temp == NULL)
|
||||
return NULL;
|
||||
for (r = rep; *r; )
|
||||
temp[templen++] = *r++;
|
||||
|
||||
i += patlen;
|
||||
repl = global != 0;
|
||||
} else {
|
||||
RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 4096); // UGLY HACK 16);
|
||||
temp[templen++] = string[i++];
|
||||
}
|
||||
}
|
||||
if (temp != NULL)
|
||||
temp[templen] = 0;
|
||||
return (temp);
|
||||
i += patlen;
|
||||
repl = global != 0;
|
||||
} else {
|
||||
RESIZE_MALLOCED_BUFFER (temp, templen, 1, tempsize, 4096); // UGLY HACK 16);
|
||||
temp[templen++] = string[i++];
|
||||
}
|
||||
}
|
||||
if (temp != NULL)
|
||||
temp[templen] = 0;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
R_API char *r_str_clean(char *str)
|
||||
@ -507,7 +507,7 @@ int r_str_argv_parse(const char *str, int argc, char **argv)
|
||||
// parse argv
|
||||
//eprintf("commandline=\"%s\"\n", ps.args);
|
||||
for(tmp=ps.args;tmp[0];tmp=tmp+1) {
|
||||
if (tmp[0]==' '&&tmp!=ps.args) { if ((tmp[-1]=='\\') || (tmp[-1]=='/'))
|
||||
if (tmp[0]==' '&&tmp!=ps.args) { if ((tmp[-1]=='\\') || (tmp[-1]=='/'))
|
||||
continue;
|
||||
tmp[0]='\0';
|
||||
ps.argv[i] = tmp2;
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* radare - LGPL - Copyright 2009 pancake<nopcode.org> */
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
/* TODO: import stuff fron bininfo/p/bininfo_addr2line */
|
||||
|
||||
R_API char *r_sys_cmd_strf(const char *cmd, ...)
|
||||
@ -45,17 +48,71 @@ R_API const char *r_sys_getenv(const char *key)
|
||||
#endif
|
||||
}
|
||||
|
||||
R_API char *r_sys_cmd_str(const char *cmd, const char *input, int *len)
|
||||
R_API char *r_sys_cmd_str_full(const char *cmd, const char *input, int *len, char **sterr)
|
||||
{
|
||||
#if __UNIX__
|
||||
char *b = malloc(1024);
|
||||
FILE *fd = popen(cmd, "r");
|
||||
char *inputptr = (char *)input;
|
||||
int bytes = 0;
|
||||
int sh_in[2];
|
||||
int sh_out[2];
|
||||
int sh_err[2];
|
||||
pipe(sh_in);
|
||||
pipe(sh_out);
|
||||
pipe(sh_err);
|
||||
*len = 0;
|
||||
if (fd == NULL)
|
||||
return NULL;
|
||||
*len = fread(b, 1, 1024, fd);
|
||||
pclose(fd);
|
||||
return b;
|
||||
|
||||
int pid = fork();
|
||||
if (!pid) {
|
||||
dup2(sh_in[0], 0);
|
||||
dup2(sh_out[1], 1);
|
||||
if (sterr) dup2(sh_err[1], 2);
|
||||
else close(2);
|
||||
execl("/bin/sh", "sh", "-c", cmd, NULL);
|
||||
} else {
|
||||
char buffer[1024];
|
||||
char *output = calloc(1, 1024);
|
||||
if (sterr)
|
||||
*sterr = calloc(1, 1024);
|
||||
|
||||
while (1) {
|
||||
fd_set rfds, wfds;
|
||||
int nfd;
|
||||
struct timeval tv;
|
||||
tv.tv_sec=0;
|
||||
tv.tv_usec=100000;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(sh_out[0], &rfds);
|
||||
FD_SET(sh_err[0], &rfds);
|
||||
if (inputptr && *inputptr)
|
||||
FD_SET(sh_in[1], &wfds);
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
nfd = select(sh_err[0] + 1, &rfds, &wfds, NULL, &tv);
|
||||
if (nfd <= 0) {
|
||||
if (waitpid(pid, NULL, WNOHANG)) break;
|
||||
else if (nfd < 0) {
|
||||
kill(pid, 15);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (FD_ISSET(sh_out[0], &rfds)) {
|
||||
*len += read(sh_out[0], buffer, sizeof(buffer)-1);
|
||||
output = r_str_concat(output, buffer);
|
||||
} else if (FD_ISSET(sh_err[0], &rfds) && sterr) {
|
||||
read(sh_err[0], buffer, sizeof(buffer)-1);
|
||||
*sterr = r_str_concat(*sterr, buffer);
|
||||
} else if (FD_ISSET(sh_in[1], &wfds) && inputptr && *inputptr) {
|
||||
bytes = write(sh_in[1], inputptr, strlen(inputptr));
|
||||
inputptr += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strlen(output))
|
||||
return output;
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
#warning NO r_sys_cmd_str support for this platform
|
||||
return NULL;
|
||||
|
@ -1,7 +1,8 @@
|
||||
# TODO: append EXECEXT to BINS
|
||||
FLAGS=-I../../include -Wl,-R.. -L.. -lr_util -g -DVERSION=\"${VERSION}\"
|
||||
|
||||
all: test rax2 ralloc iter file_slurp_hexpairs pool
|
||||
all: test rax2 ralloc iter file_slurp_hexpairs pool
|
||||
#test_sys : missing file
|
||||
|
||||
ralloc:
|
||||
${CC} ${FLAGS} ralloc.c -o ralloc
|
||||
@ -9,6 +10,9 @@ ralloc:
|
||||
test:
|
||||
${CC} ${FLAGS} test.c -o test
|
||||
|
||||
test_sys: test_sys.c
|
||||
${CC} ${FLAGS} test_sys.c -o test_sys -lr_util
|
||||
|
||||
pool:
|
||||
${CC} ${FLAGS} pool.c -o pool
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user