* Implement r_str_argv()

- Use it from p/debug
  - Now is possible to debug programs with arguments
  - Added test program in util/t/argv
* Fix pd/pD
* Clean and fix the native debugger plugin
* More random code syntax cleanup
* Rename io plugin names without the deprecated 'io_' prefix
* Fix mk/stat-make.pl (missing ;)
This commit is contained in:
pancake 2010-02-23 00:26:13 +01:00
parent a536777d35
commit 020686b86f
12 changed files with 345 additions and 448 deletions

View File

@ -106,3 +106,4 @@ Enjoy the 'two girls one backup' viral video
A C program is like a fast dance on a newly waxed dance floor by people carrying razors - Waldi Ravens
radare2 is like windows 7 but even better
Enlarge your radare2
Excellent; we can attack in any direction!

View File

@ -11,6 +11,7 @@
#include <sys/types.h>
#include <stdarg.h>
#if __UNIX__
// TODO: move this outside
#include <sys/wait.h>
#endif
@ -173,12 +174,12 @@ static int cmd_yank_to(struct r_core_t *core, char *arg) {
char *str;
ut8 *buf;
while(*arg==' ')arg=arg+1;
while (*arg==' ')arg=arg+1;
str = strchr(arg, ' ');
if (str) {
str[0]='\0';
len = r_num_math(&core->num, arg);
pos = r_num_math(&core->num, str+1);
len = r_num_math (&core->num, arg);
pos = r_num_math (&core->num, str+1);
str[0]=' ';
}
if ( (str == NULL) || (pos == -1) || (len == 0) ) {
@ -191,13 +192,13 @@ static int cmd_yank_to(struct r_core_t *core, char *arg) {
return 1;
}
#endif
buf = (ut8*)malloc( len );
buf = (ut8*)malloc (len);
r_core_read_at (core, src, buf, len);
r_core_write_at (core, pos, buf, len);
free(buf);
core->offset = src;
r_core_block_read(core, 0);
r_core_block_read (core, 0);
return 0;
}
@ -240,8 +241,7 @@ static int cmd_yank(void *data, const char *input) {
return R_TRUE;
}
static int cmd_quit(void *data, const char *input)
{
static int cmd_quit(void *data, const char *input) {
struct r_core_t *core = (struct r_core_t *)data;
switch (input[0]) {
case '?':
@ -258,7 +258,7 @@ static int cmd_quit(void *data, const char *input)
// TODO
default:
r_line_hist_save (".radare2_history");
exit(*input?r_num_math(&core->num, input+1):0);
exit (*input?r_num_math (&core->num, input+1):0);
break;
}
return 0;
@ -266,19 +266,19 @@ static int cmd_quit(void *data, const char *input)
static int cmd_interpret(void *data, const char *input) {
char *str, *ptr, *eol;
struct r_core_t *core = (struct r_core_t *)data;
switch(input[0]) {
RCore *core = (RCore *)data;
switch (input[0]) {
case ' ':
/* interpret file */
r_core_cmd_file(core, input+1);
r_core_cmd_file (core, input+1);
break;
case '!':
/* from command */
r_core_cmd_command(core, input+1);
r_core_cmd_command (core, input+1);
break;
case '(':
//fprintf(stderr, "macro call (%s)\n", input+1);
r_macro_call(&core->macro, input+1);
r_macro_call (&core->macro, input+1);
break;
case '?':
r_cons_printf (
@ -289,15 +289,15 @@ static int cmd_interpret(void *data, const char *input) {
" ./m ELF ; interpret output of command /m ELF as r. commands\n");
break;
default:
ptr = str = r_core_cmd_str(core, input);
ptr = str = r_core_cmd_str (core, input);
for (;;) {
eol = strchr(ptr, '\n');
eol = strchr (ptr, '\n');
if (eol) eol[0]='\0';
r_core_cmd(core, ptr, 0);
r_core_cmd (core, ptr, 0);
if (!eol) break;
ptr = eol+1;
}
free(str);
free (str);
break;
}
return 0;
@ -416,11 +416,9 @@ static int cmd_seek(void *data, const char *input) {
return 0;
}
static int cmd_help(void *data, const char *input)
{
struct r_core_t *core = (struct r_core_t *)data;
static int cmd_help(void *data, const char *input) {
RCore *core = (RCore *)data;
ut64 n;
switch (input[0]) {
case ' ':
n = r_num_math (&core->num, input+1);
@ -525,8 +523,7 @@ static int cmd_help(void *data, const char *input)
return 0;
}
static int cmd_bsize(void *data, const char *input)
{
static int cmd_bsize(void *data, const char *input) {
struct r_core_t *core = (struct r_core_t *)data;
switch (input[0]) {
case '\0':
@ -534,7 +531,7 @@ static int cmd_bsize(void *data, const char *input)
break;
default:
//input = r_str_clean(input);
r_core_block_size (core, r_num_math (NULL, input));
r_core_block_size (core, r_num_math (&core->num, input));
break;
}
return 0;
@ -661,9 +658,8 @@ static int cmd_info(void *data, const char *input) {
return 0;
}
static int cmd_print(void *data, const char *input)
{
struct r_core_t *core = (struct r_core_t *)data;
static int cmd_print(void *data, const char *input) {
RCore *core = (RCore *)data;
int l, len = core->blocksize;
ut32 tbs = core->blocksize;
int show_offset = r_config_get_i (&core->config, "asm.offset");
@ -679,13 +675,15 @@ static int cmd_print(void *data, const char *input)
if (r_config_get_i (&core->config, "asm.reflineswide"))
linesopts |= R_ANAL_REFLINE_WIDE;
/* XXX: This is only for pd/pD ??? */
if (input[0] && input[1]) {
l = (int) r_num_get (&core->num, input+2);
l = (int) r_num_math (&core->num, input+2);
if (input[0] != 'd') {
if (l>0) len = l;
if (l>tbs) r_core_block_size (core, l);
l = 9999;
}
}
} else l = 9999;
switch(input[0]) {
case 'D':
@ -704,7 +702,6 @@ static int cmd_print(void *data, const char *input)
//r_anal_set_pc(&core->anal, core->offset);
r_asm_set_pc (&core->assembler, core->offset);
l = 9999; // number of lines
reflines = r_anal_reflines_get (&core->anal, core->offset,
buf, len, -1, linesout);
@ -868,8 +865,7 @@ static int cmd_flag(void *data, const char *input) {
return 0;
}
static int cmd_anal(void *data, const char *input)
{
static int cmd_anal(void *data, const char *input) {
struct r_core_t *core = (struct r_core_t *)data;
int l, len = core->blocksize;
ut32 tbs = core->blocksize;
@ -915,8 +911,7 @@ static int cmd_anal(void *data, const char *input)
}
/* TODO: simplify using r_write */
static int cmd_write(void *data, const char *input)
{
static int cmd_write(void *data, const char *input) {
int i, len = strlen(input);
char *tmp, *str = alloca(len)+1;
struct r_core_t *core = (struct r_core_t *)data;
@ -1148,8 +1143,7 @@ static int __cb_hit(struct r_search_kw_t *kw, void *user, ut64 addr)
return R_TRUE;
}
static int cmd_search(void *data, const char *input)
{
static int cmd_search(void *data, const char *input) {
struct r_core_t *core = (struct r_core_t *)data;
ut64 at;
ut32 n32;
@ -1238,8 +1232,7 @@ static int cmd_search(void *data, const char *input)
return R_TRUE;
}
static int cmd_eval(void *data, const char *input)
{
static int cmd_eval(void *data, const char *input) {
struct r_core_t *core = (struct r_core_t *)data;
switch (input[0]) {
case '\0':
@ -1274,8 +1267,7 @@ static int cmd_eval(void *data, const char *input)
return 0;
}
static int cmd_hash(void *data, const char *input)
{
static int cmd_hash(void *data, const char *input) {
char algo[32];
struct r_core_t *core = (struct r_core_t *)data;
ut32 len = core->blocksize;
@ -1331,13 +1323,11 @@ static int cmd_hash(void *data, const char *input)
return 0;
}
static int cmd_visual(void *data, const char *input)
{
static int cmd_visual(void *data, const char *input) {
return r_core_visual ((RCore *)data, input);
}
static int cmd_system(void *data, const char *input)
{
static int cmd_system(void *data, const char *input) {
//struct r_core_t *core = (struct r_core_t *)data;
// slurped from teh old radare_system
#if __FreeBSD__
@ -1363,8 +1353,7 @@ static int cmd_system(void *data, const char *input)
#endif
}
static int cmd_open(void *data, const char *input)
{
static int cmd_open(void *data, const char *input) {
RCore *core = (RCore*)data;
RCoreFile *file;
ut64 addr, size;
@ -1407,9 +1396,8 @@ static int cmd_open(void *data, const char *input)
return 0;
}
static int cmd_meta(void *data, const char *input)
{
struct r_core_t *core = (struct r_core_t *)data;
static int cmd_meta(void *data, const char *input) {
RCore *core = (RCore*)data;
int ret, line = 0;
char file[1024];
switch(input[0]) {
@ -1441,19 +1429,19 @@ static int cmd_meta(void *data, const char *input)
char fun_name[128];
int size = atoi(input);
int type = R_META_FUNCTION;
char *t, *p = strchr(input+1, ' ');
char *t, *p = strchr (input+1, ' ');
if (p) {
t = strdup(p+1);
printf("T=(%s)\n", t);
t = strdup (p+1);
eprintf ("T=(%s)\n", t);
p = strchr(t, ' ');
if (p) {
*p='\0';
strncpy(fun_name, p+1, sizeof(fun_name));
} else sprintf(fun_name, "sub_%08llx", addr);
addr = r_num_math(&core->num, t);
strncpy (fun_name, p+1, sizeof (fun_name));
} else sprintf (fun_name, "sub_%08llx", addr);
addr = r_num_math (&core->num, t);
free(t);
}
r_meta_add(&core->meta, type, addr, size, fun_name);
r_meta_add (&core->meta, type, addr, size, fun_name);
}
break;
case '\0':
@ -1467,35 +1455,32 @@ printf("T=(%s)\n", t);
return R_TRUE;
}
static int cmd_undowrite(void *data, const char *input)
{
static int cmd_undowrite(void *data, const char *input) {
//struct r_core_t *core = (struct r_core_t *)data;
// TODO:
return 0;
}
static int cmd_io_system(void *data, const char *input)
{
static int cmd_io_system(void *data, const char *input) {
struct r_core_t *core = (struct r_core_t *)data;
r_io_set_fd(&core->io, core->file->fd);
return r_io_system(&core->io, input);
}
static int cmd_macro(void *data, const char *input)
{
struct r_core_t *core = (struct r_core_t *)data;
static int cmd_macro(void *data, const char *input) {
RCore *core = (RCore*)data;
switch(input[0]) {
case ')':
r_macro_break(&core->macro, input+1);
r_macro_break (&core->macro, input+1);
break;
case '-':
r_macro_rm(&core->macro, input+1);
r_macro_rm (&core->macro, input+1);
break;
case '\0':
r_macro_list(&core->macro);
r_macro_list (&core->macro);
break;
case '?':
eprintf(
eprintf (
"Usage: (foo\\n..cmds..\\n)\n"
" Record macros grouping commands\n"
" (foo args\\n ..) ; define a macro\n"
@ -1511,7 +1496,7 @@ static int cmd_macro(void *data, const char *input)
);
break;
default:
r_macro_add(&core->macro, input);
r_macro_add (&core->macro, input);
break;
}
return 0;
@ -1557,35 +1542,34 @@ static int r_core_cmd_subst(struct r_core_t *core, char *cmd)
if (!*cmd || cmd[0]=='\0')
return 0;
cmd = r_str_trim_head_tail(cmd);
cmd = r_str_trim_head_tail (cmd);
/* quoted / raw command */
if (cmd[0] =='"') {
if (cmd[len-1] != '"') {
fprintf(stderr, "parse: Missing ending '\"'\n");
eprintf ("parse: Missing ending '\"'\n");
return -1;
} else {
cmd[len-1]='\0';
ret = r_cmd_call(&core->cmd, cmd+1);
return ret;
}
cmd[len-1]='\0';
ret = r_cmd_call (&core->cmd, cmd+1);
return ret;
}
/* multiple commands */
ptr = strrchr(cmd, ';');
ptr = strrchr (cmd, ';');
if (ptr) {
ptr[0]='\0';
if (r_core_cmd_subst(core, cmd) == -1)
if (r_core_cmd_subst (core, cmd) == -1)
return -1;
cmd = ptr+1;
r_cons_flush();
r_cons_flush ();
}
/* pipe console to shell process */
ptr = strchr(cmd, '|');
ptr = strchr (cmd, '|');
if (ptr) {
ptr[0] = '\0';
r_core_cmd_pipe(core, cmd, ptr+1);
r_core_cmd_pipe (core, cmd, ptr+1);
return 0;
}
@ -1593,19 +1577,19 @@ static int r_core_cmd_subst(struct r_core_t *core, char *cmd)
ptr = strchr(cmd, '&');
while (ptr&&ptr[1]=='&') {
ptr[0]='\0';
ret = r_cmd_call(&core->cmd, cmd);
ret = r_cmd_call (&core->cmd, cmd);
if (ret == -1){
fprintf(stderr, "command error(%s)\n", cmd);
eprintf ("command error(%s)\n", cmd);
return ret;
}
for(cmd=ptr+2;cmd&&cmd[0]==' ';cmd=cmd+1);
ptr = strchr(cmd, '&');
for (cmd=ptr+2;cmd&&cmd[0]==' ';cmd=cmd+1);
ptr = strchr (cmd, '&');
}
/* Out Of Band Input */
free(core->oobi);
free (core->oobi);
core->oobi = NULL;
ptr = strchr(cmd, '<');
ptr = strchr (cmd, '<');
if (ptr) {
ptr[0] = '\0';
if (ptr[1]=='<') {
@ -1707,8 +1691,7 @@ static int r_core_cmd_subst(struct r_core_t *core, char *cmd)
return 0;
}
R_API int r_core_cmd_foreach(struct r_core_t *core, const char *cmd, char *each)
{
R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
int i=0,j;
char ch;
char *word = NULL;
@ -1821,7 +1804,7 @@ R_API int r_core_cmd_foreach(struct r_core_t *core, const char *cmd, char *each)
radare_cmd(cmd,0);
}
#else
printf("No flags foreach implemented\n");
eprintf ("No flags foreach implemented\n");
#endif
} else {
/* for all flags in current flagspace */
@ -1867,8 +1850,7 @@ printf("No flags foreach implemented\n");
return R_TRUE;
}
R_API int r_core_cmd(struct r_core_t *core, const char *command, int log)
{
R_API int r_core_cmd(struct r_core_t *core, const char *command, int log) {
int len, rep, ret = R_FALSE;
char *cmd, *ocmd;
if (command != NULL) {
@ -1905,8 +1887,7 @@ R_API int r_core_cmd(struct r_core_t *core, const char *command, int log)
return ret;
}
R_API int r_core_cmd_file(struct r_core_t *core, const char *file)
{
R_API int r_core_cmd_file(struct r_core_t *core, const char *file) {
char buf[1024];
FILE *fd = fopen(file, "r");
if (fd == NULL) {
@ -1926,8 +1907,7 @@ 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)
{
R_API int r_core_cmd_command(struct r_core_t *core, const char *command) {
int len;
char *buf, *rcmd, *ptr;
rcmd = ptr = buf = r_sys_cmd_str (command, 0, &len);
@ -2081,8 +2061,7 @@ static int cmd_debug(void *data, const char *input) {
return 0;
}
R_API int r_core_cmd_buffer(void *user, const char *buf)
{
R_API int r_core_cmd_buffer(void *user, const char *buf) {
char *str = strdup(buf);
char *ptr = strchr(str, '\n');
char *optr = str;
@ -2097,8 +2076,7 @@ R_API int r_core_cmd_buffer(void *user, const char *buf)
return R_TRUE;
}
R_API int r_core_cmdf(void *user, const char *fmt, ...)
{
R_API int r_core_cmdf(void *user, const char *fmt, ...) {
char string[1024];
int ret;
va_list ap;
@ -2109,8 +2087,7 @@ R_API int r_core_cmdf(void *user, const char *fmt, ...)
return ret;
}
R_API int r_core_cmd0(void *user, const char *cmd)
{
R_API int r_core_cmd0(void *user, const char *cmd) {
return r_core_cmd ((struct r_core_t *)user, cmd, 0);
}
@ -2134,8 +2111,7 @@ R_API char *r_core_cmd_str(struct r_core_t *core, const char *cmd)
return retstr;
}
int r_core_cmd_init(struct r_core_t *core)
{
int r_core_cmd_init(struct r_core_t *core) {
r_cmd_init (&core->cmd);
r_cmd_set_data (&core->cmd, core);
r_cmd_add (&core->cmd, "x", "alias for px", &cmd_hexdump);

View File

@ -77,7 +77,6 @@
#define DEBUGGER 0
#endif // ARCH
#if DEBUGGER
#include <sys/ptrace.h>
#include <sys/types.h>
@ -120,21 +119,16 @@ static void debug_arch_x86_trap_set(int pid, int foo) {
if (foo) regs.__eflags |= EFLAGS_TRAP_FLAG;
else regs.__eflags &= ~EFLAGS_TRAP_FLAG;
debug_setregs (pid_to_task (pid), &regs);
#else
/* void */
#endif // __i386__ || __x86_64__
#endif
}
#endif // __APPLE__
static int r_debug_native_step(int pid) {
int ret = R_FALSE;
#if __APPLE__
//R_DEBUG_REG_T regs;
#if __APPLE__
debug_arch_x86_trap_set (pid, 1);
#define OLD_PANCAKE_CODE 1
#if OLD_PANCAKE_CODE
//eprintf ("stepping from pc = %08x\n", (ut32)get_offset("eip"));
//ret = ptrace (PT_STEP, ps.tid, (caddr_t)get_offset("eip"), SIGSTOP);
ret = ptrace (PT_STEP, pid, (caddr_t)1, SIGTRAP); //SIGINT);
@ -154,7 +148,7 @@ static int r_debug_native_step(int pid) {
perror ("native-singlestep");
ret = R_FALSE;
} else ret = R_TRUE;
#endif // __APPLE__
#endif // __APPLE_
return ret;
}
@ -186,6 +180,7 @@ static int r_debug_native_continue(int pid, int sig) {
#if __APPLE__
eprintf ("debug_contp: program is now running...\n");
/* XXX */
/* only stopped with ptrace the first time */
//ptrace(PT_CONTINUE, pid, 0, 0);
ptrace (PT_DETACH, pid, 0, 0);
@ -374,7 +369,7 @@ static const char *r_debug_native_reg_profile() {
// TODO: what about float and hardware regs here ???
// TODO: add flag for type
static int r_debug_native_reg_read(struct r_debug_t *dbg, int type, ut8 *buf, int size)
static int r_debug_native_reg_read(RDebug *dbg, int type, ut8 *buf, int size)
{
int ret;
int pid = dbg->pid;
@ -396,7 +391,7 @@ static int r_debug_native_reg_read(struct r_debug_t *dbg, int type, ut8 *buf, in
if (inferior_thread_count>0) {
/* TODO: allow to choose the thread */
if ((ret = thread_get_state (inferior_threads[0], R_DEBUG_STATE_T,
if ((ret = thread_get_state (inferior_threads[0], R_DEBUG_STATE_T,
(thread_state_t) regs, &gp_count)) != KERN_SUCCESS) {
eprintf ("debug_getregs: Failed to get thread %d %d.error (%x). (%s)\n",
(int)pid, pid_to_task (pid), (int)ret, MACH_ERROR_STRING (ret));
@ -415,8 +410,10 @@ static int r_debug_native_reg_read(struct r_debug_t *dbg, int type, ut8 *buf, in
R_DEBUG_REG_T regs;
memset (&regs, 0, sizeof (regs));
memset (buf, 0, size);
#if __NetBSD__ || __FreeBSD__ || __OpenBSD__
ret = ptrace (PTRACE_GETREGS, pid, &regs, sizeof (regs));
#elif __linux__ && __powerpc__
ret = ptrace (PTRACE_GETREGS, pid, &regs, NULL);
#else
@ -431,7 +428,6 @@ static int r_debug_native_reg_read(struct r_debug_t *dbg, int type, ut8 *buf, in
return sizeof (regs);
}
break;
//r_reg_set_bytes(reg, &regs, sizeof(struct user_regs));
}
return R_TRUE;
#else
@ -476,7 +472,7 @@ static RList *r_debug_native_map_get(struct r_debug_t *dbg)
sprintf (path, "/proc/%d/maps", dbg->pid);
#endif
fd = fopen (path, "r");
if(!fd) {
if (!fd) {
perror ("debug_init_maps");
return NULL;
}
@ -491,9 +487,10 @@ static RList *r_debug_native_map_get(struct r_debug_t *dbg)
path[0]='\0';
line[strlen (line)-1]='\0';
#if __FreeBSD__
// 0x8070000 0x8072000 2 0 0xc1fde948 rw- 1 0 0x2180 COW NC vnode /usr/bin/gcc
// 0x8070000 0x8072000 2 0 0xc1fde948 rw- 1 0 0x2180 COW NC vnode /usr/bin/gcc
sscanf (line, "%s %s %d %d 0x%s %3s %d %d",
&region[2], &region2[2], &ign, &ign, unkstr, perms, &ign, &ign);
&region[2], &region2[2], &ign, &ign,
unkstr, perms, &ign, &ign);
pos_c = strchr (line, '/');
if (pos_c) strcpy (path, pos_c);
else path[0]='\0';
@ -555,7 +552,7 @@ static RList *r_debug_native_map_get(struct r_debug_t *dbg)
#endif
r_list_append (list, map);
}
fclose(fd);
fclose (fd);
#endif // __sun
return list;
}
@ -589,14 +586,6 @@ static int r_debug_get_arch()
#endif
}
#if 0
static int r_debug_native_import(struct r_debug_handle_t *from)
{
//int pid = from->export(R_DEBUG_GET_PID);
//int maps = from->export(R_DEBUG_GET_MAPS);
return R_FALSE;
}
#endif
#if __i386__
const char *archlist[3] = { "x86", "x86-32", 0 };
#elif __x86_64__
@ -634,8 +623,8 @@ struct r_lib_struct_t radare_plugin = {
};
#endif // CORELIB
#endif
#else
//#endif
#else // DEBUGGER
struct r_debug_handle_t r_debug_plugin_native = {
.name = "native",
};

View File

@ -156,6 +156,8 @@ R_API void r_num_init(struct r_num_t *num);
#define ishexchar(x) ((x>='0'&&x<='9') || (x>='a'&&x<='f') || (x>='A'&&x<='F')) {
/* strings */
R_API char **r_str_argv(const char *str, int *_argc);
R_API void r_str_argv_free(char **argv);
R_API char *r_str_new(char *str);
R_API const char *r_str_bool(int b);
R_API const char *r_str_ansi_chrn(const char *str, int n);

View File

@ -32,39 +32,6 @@ static void inferior_abort_handler(int pid) {
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
// XXX this is OSX
static pid_t start_inferior(int argc, char **argv) {
char **child_args;
int status;
pid_t kid;
eprintf ("Starting process...\n");
if ((kid = fork ())) {
//waitpid (kid, &status, 0);
wait (&status);
if (WIFSTOPPED (status)) {
eprintf ("Process with PID %d started...\n", (int)kid);
return kid;
}
return -1;
}
child_args = (char **)malloc (sizeof (char *) * (argc + 1));
memcpy (child_args, argv, sizeof(char *) * argc);
child_args[argc] = NULL;
ptrace (PT_TRACE_ME, 0, 0, 0);
/* why altering these signals? */
/* XXX this can be monitorized by the child */
signal (SIGTRAP, SIG_IGN); // SINO NO FUNCIONA EL STEP
signal (SIGABRT, inferior_abort_handler);
execvp (argv[0], child_args);
eprintf ("Failed to start inferior.\n");
exit (0);
}
#endif
static int __waitpid(int pid) {
@ -80,25 +47,20 @@ static int __waitpid(int pid) {
return R_TRUE;
}
// TODO: move to common os/ directory
/*
* Creates a new process and returns the result:
* -1 : error
* 0 : ok
* TODO: should be pid number?
* TODO: should accept argv and so as arguments
*/
//#include <linux/user.h>
#define MAGIC_EXIT 31337
static int fork_and_ptraceme(const char *cmd)
{
static int fork_and_ptraceme(const char *cmd) {
char **argv;
int status, pid = -1;
pid = vfork();
pid = vfork ();
switch (pid) {
case -1:
fprintf(stderr, "Cannot fork.\n");
perror ("fork_and_ptraceme");
break;
case 0:
#if __APPLE__
@ -111,46 +73,24 @@ static int fork_and_ptraceme(const char *cmd)
eprintf ("ptrace-traceme failed\n");
exit (MAGIC_EXIT);
}
#if 0
eprintf ("argv = [ ");
for (i=0;ps.argv[i];i++)
eprintf ("'%s', ", ps.argv[i]);
eprintf ("]\n");
#endif
// TODO: Add support to redirect filedescriptors
// TODO: Configure process environment
argv = r_str_argv (cmd, NULL);
execvp (argv[0], argv);
r_str_argv_free (argv);
// TODO: USE TM IF POSSIBLE TO ATTACH IT FROM ANOTHER CONSOLE!!!
// TODO:
//debug_environment();
{
char *buf;
char *argv[2];
char *ptr;
// TODO: use: argv = r_str_argv ("hello \"world is bar\"", &argc);
buf = strdup (cmd);
ptr = strchr (buf, ' ');
if (ptr)
*ptr='\0';
argv[0] = r_file_path (cmd);
argv[1] = NULL;
//execv(cmd, argv); //ps.argv[0], ps.argv);
execvp (argv[0], argv);
}
perror ("fork_and_attach: execv");
//printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename);
exit (MAGIC_EXIT); /* error */
return 0; // invalid pid // if exit is overriden.. :)
break;
default:
/* XXX: clean this dirty code */
#if __APPLE__
wait (&status);
if (WIFSTOPPED (status))
eprintf ("Process with PID %d started...\n", (int)pid);
#else
__waitpid (pid);
kill (pid, SIGSTOP);
#endif
// XXX
//kill (pid, SIGSTOP);
break;
}
printf ("PID = %d\n", pid);

View File

@ -13,18 +13,15 @@
static int ewf_fd = -1;
static LIBEWF_HANDLE *ewf_h = NULL;
static int ewf__write(struct r_io_t *io, int fd, const ut8 *buf, int count)
{
static int ewf__write(struct r_io_t *io, int fd, const ut8 *buf, int count) {
return libewf_write_buffer(ewf_h, buf, count);
}
static int ewf__read(struct r_io_t *io, int fd, ut8 *buf, int count)
{
static int ewf__read(struct r_io_t *io, int fd, ut8 *buf, int count) {
return libewf_read_buffer(ewf_h, buf, count);
}
static int ewf__close(struct r_io_t *io, int fd)
{
static int ewf__close(struct r_io_t *io, int fd) {
if (fd == ewf_fd) {
libewf_close(ewf_h);
ewf_fd = -1;
@ -32,8 +29,7 @@ static int ewf__close(struct r_io_t *io, int fd)
}
}
static ut64 ewf__lseek(struct r_io_t *io, int fildes, ut64 offset, int whence)
{
static ut64 ewf__lseek(struct r_io_t *io, int fildes, ut64 offset, int whence) {
size64_t media_size;
if (fildes == ewf_fd) {
@ -56,8 +52,7 @@ static ut64 ewf__lseek(struct r_io_t *io, int fildes, ut64 offset, int whence)
return lseek(fildes, offset, whence);
}
static int ewf__handle_fd(struct r_io_t *io, int fd)
{
static int ewf__handle_fd(struct r_io_t *io, int fd) {
return fd == ewf_fd;
}
@ -69,8 +64,7 @@ static int ewf__handle_open(struct r_io_t *io, const char *pathname)
return 0;
}
static int ewf__open(struct r_io_t *io, const char *pathname, int flags, int mode)
{
static int ewf__open(struct r_io_t *io, const char *pathname, int flags, int mode) {
// XXX filename list should be dynamic. 1024 limit is ugly
const char *filenames[1024];
char *ptr,*optr;
@ -165,8 +159,7 @@ static int ewf__open(struct r_io_t *io, const char *pathname, int flags, int mod
return ewf_fd;
}
static int ewf__init(struct r_io_t *io)
{
static int ewf__init(struct r_io_t *io) {
return R_TRUE;
}

View File

@ -104,7 +104,7 @@ static int __system(struct r_io_t *io, int fd, const char *cmd)
struct r_io_handle_t r_io_plugin_malloc = {
//void *handle;
.name = "io_malloc",
.name = "malloc",
.desc = "memory allocation ( malloc://size-in-bytes )",
.open = __open,
.close = __close,

View File

@ -89,7 +89,7 @@ static int shm__init(struct r_io_t *io)
struct r_io_handle_t r_io_plugin_shm = {
//void *handle;
.name = "io_shm",
.name = "shm",
.desc = "shared memory resources (shm://key)",
.open = shm__open,
.close = shm__close,

View File

@ -11,11 +11,10 @@ static const char *nullstr = "";
static const char *nullstr_c = "(null)";
/* int c; ret = hex2int(&c, 'c'); */
static int hex2int (unsigned char *val, unsigned char c)
{
if ('0' <= c && c <= '9') *val = (unsigned char)(*val) * 16 + ( c - '0');
else if (c >= 'A' && c <= 'F') *val = (unsigned char)(*val) * 16 + ( c - 'A' + 10);
else if (c >= 'a' && c <= 'f') *val = (unsigned char)(*val) * 16 + ( c - 'a' + 10);
static int hex2int (ut8 *val, ut8 c) {
if ('0' <= c && c <= '9') *val = (ut8)(*val) * 16 + ( c - '0');
else if (c >= 'A' && c <= 'F') *val = (ut8)(*val) * 16 + ( c - 'A' + 10);
else if (c >= 'a' && c <= 'f') *val = (ut8)(*val) * 16 + ( c - 'a' + 10);
else return 1;
return 0;
}
@ -49,40 +48,38 @@ R_API char *r_str_home(const char *str)
return dst;
}
R_API int r_str_hash(const char *str)
{
R_API int r_str_hash(const char *str) {
int i = 1;
int a = 0x31;
int b = 0x337;
int h = str[0];
for(; str[i]; i++) {
h+=str[i]*i*a;
a*=b;
for (; str[i]; i++) {
h += str[i]*i*a;
a *= b;
}
return h&0x7fffffff;
}
R_API int r_str_delta(char *p, char a, char b)
{
char *_a = strchr(p, a);
char *_b = strchr(p, b);
if (!_a||!_b) return 0;
return (_a-_b);
R_API int r_str_delta(char *p, char a, char b) {
char *_a = strchr (p, a);
char *_b = strchr (p, b);
return (!_a||!_b)?0:(_a-_b);
}
R_API int r_str_word_set0(char *str)
{
int i;
R_API int r_str_word_set0(char *str) { 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
for (i=1,p=str; p[0]; p++)
if (*p==' ') {
i++;
*p='\0';
} // s/ /\0/g
return i;
}
R_API char *r_str_word_get0(char *str, int idx)
{
R_API char *r_str_word_get0(char *str, int idx) {
int i;
char *ptr = str;
if (ptr == NULL)
@ -92,107 +89,90 @@ R_API char *r_str_word_get0(char *str, int idx)
return ptr;
}
R_API int r_str_char_count(const char *string, char ch)
{
int i, count=0;
for(i=0;string[i];i++)
R_API int r_str_char_count(const char *string, char ch) {
int i, count = 0;
for (i=0; string[i]; i++)
if (string[i]==ch)
count++;
return count;
}
R_API int r_str_word_count(const char *string)
{
R_API int r_str_word_count(const char *string) {
const char *text, *tmp;
int word = 0;
int word;
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 (text = tmp = string; *text && isseparator (*text); text++);
for (word = 0; *text; word++) {
for (;*text && !isseparator (*text); text++);
for (tmp = text; *text && isseparator (*text); text++);
if (tmp == text) word--;
}
return word-1;
}
R_API char *r_str_ichr(char *str, char chr)
{
while(*str==chr) {
R_API char *r_str_ichr(char *str, char chr) {
while (*str==chr)
str = str+1;
}
return str;
}
R_API char *r_str_lchr(char *str, char chr)
{
R_API char *r_str_lchr(char *str, char chr) {
int len = strlen(str)+1;
for(;len>=0;len--)
for (;len>=0;len--)
if (str[len]==chr)
return str+len;
return NULL;
}
R_API int r_str_nchr(const char *str, char chr)
{
int n = 0;
while(str[0]) {
if (str[0]==chr)
R_API int r_str_nchr(const char *str, char chr) {
int n;
for (n = 0; *str; str++)
if (*str==chr)
n++;
str = str+1;
}
return n;
}
R_API int r_str_nstr(char *from, char *to, int size)
{
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])
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)
{
R_API const char *r_str_chop_ro(const char *str) {
if (str)
while(str[0]&&iswhitechar(str[0]))
str = str + 1;
while (*str && iswhitechar (*str))
str++;
return str;
}
R_API char *r_str_new(char *str)
{
return strdup(str);
R_API char *r_str_new(char *str) {
return strdup (str);
}
R_API char *r_str_chop(char *str)
{
R_API char *r_str_chop(char *str) {
int len;
char *ptr;
if (str == NULL)
return NULL;
while(str[0]&&iswhitechar(str[0]))
while (*str && iswhitechar (*str))
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;
for (ptr = str+len-1;ptr!=str;ptr = ptr - 1) {
if (iswhitechar (ptr[0]))
*ptr = '\0';
else break;
}
return str;
}
R_API char *r_str_trim_head(char *str)
{
R_API char *r_str_trim_head(char *str) {
if (str == NULL)
return NULL;
while (*str && iswhitechar(*str))
@ -200,8 +180,7 @@ R_API char *r_str_trim_head(char *str)
return str;
}
R_API char *r_str_trim_tail(char *str)
{
R_API char *r_str_trim_tail(char *str) {
char *ptr = str;
if (str == NULL)
return NULL;
@ -213,37 +192,33 @@ R_API char *r_str_trim_tail(char *str)
return str;
}
R_API char *r_str_trim_head_tail(char *str)
{
R_API char *r_str_trim_head_tail(char *str) {
return r_str_trim_tail(r_str_trim_head(str));
}
R_API char *r_str_trim(char *str)
{
R_API char *r_str_trim(char *str) {
int i;
char *ptr;
if (str == NULL)
return NULL;
for(ptr=str, i=0;str[i];i++)
if (!iswhitechar(str[i]))
*ptr++=str[i];
for (ptr=str, i=0;str[i];i++)
if (!iswhitechar (str[i]))
*ptr++ = str[i];
*ptr='\0';
return str;
}
/* memccmp("foo.bar", "foo.cow, '.') == 0 */
R_API int r_str_ccmp(const char *dst, const char *src, int ch)
{
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++)
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)
{
for(;len--;) {
R_API int r_str_cmp(const char *a, const char *b, int len) {
for (;len--;) {
if (*a=='\0'||*b=='\0'||*a!=*b)
return 1;
a=a+1;
@ -252,8 +227,7 @@ R_API int r_str_cmp(const char *a, const char *b, int len)
return 0;
}
R_API int r_str_ccpy(char *dst, char *src, int ch)
{
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];
@ -261,47 +235,39 @@ R_API int r_str_ccpy(char *dst, char *src, int ch)
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;
R_API char *r_str_word_get_first(const char *text) {
char *ret;
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++);
/* strdup */
ret = (char *)malloc(len+1);
if (ret == 0) {
fprintf(stderr, "Cannot allocate %d bytes.\n", len+1);
ret = (char *)malloc (len+1);
if (ret == NULL) {
eprintf ("Cannot allocate %d bytes.\n", len+1);
exit(1);
}
strncpy(ret, start, len);
strncpy (ret, text, len);
ret[len]='\0';
return ret;
}
R_API const char *r_str_get(const char *str)
{
R_API const char *r_str_get(const char *str) {
if (str == NULL)
return nullstr_c;
return str;
}
R_API char *r_str_dup(char *ptr, const char *string)
{
R_API char *r_str_dup(char *ptr, const char *string) {
if (ptr)
free(ptr);
ptr = strdup(string);
free (ptr);
ptr = strdup (string);
return ptr;
}
// TODO: rename to r_str_dupfmt
R_API char *r_str_dup_printf(const char *fmt, ...)
{
R_API char *r_str_dup_printf(const char *fmt, ...) {
char *ret;
va_list ap;
va_start(ap, fmt);
@ -315,49 +281,44 @@ R_API char *r_str_dup_printf(const char *fmt, ...)
/*
* return: the pointer ptr resized to string size.
*/
R_API char *r_str_concat(char *ptr, const char *string)
{
R_API char *r_str_concat(char *ptr, const char *string) {
if (!ptr)
return strdup(string);
ptr = realloc(ptr, strlen(string)+strlen(ptr)+1);
return strdup (string);
ptr = realloc (ptr, strlen (string)+strlen (ptr)+1);
if (ptr == NULL)
return NULL;
strcat(ptr, string);
strcat (ptr, string);
return ptr;
}
R_API char *r_str_concatf(char *ptr, const char *fmt, ...)
{
R_API char *r_str_concatf(char *ptr, const char *fmt, ...) {
char string[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(string, 1023, fmt, ap);
ptr = r_str_concat(ptr, string);
va_end(ap);
va_start (ap, fmt);
vsnprintf (string, 1023, fmt, ap);
ptr = r_str_concat (ptr, string);
va_end (ap);
return ptr;
}
R_API void r_str_concatch(char *x, char y)
{
R_API void r_str_concatch(char *x, char y) {
char b[2]={y,0};
strcat(x,b);
strcat (x,b);
}
R_API void *r_str_free(void *ptr)
{
R_API void *r_str_free(void *ptr) {
free (ptr);
return NULL;
}
R_API int r_str_inject(char *begin, char *end, char *str, int maxlen)
{
R_API int r_str_inject(char *begin, char *end, char *str, int maxlen) {
int len = strlen(end)+1;
char *tmp = alloca(len);
if (maxlen > 0 && ((strlen(begin)-(end-begin)+strlen(str)) > maxlen))
if (maxlen > 0 && ((strlen (begin)-(end-begin)+strlen(str)) > maxlen))
return 0;
memcpy (tmp, end, len);
strcpy (begin, str);
strcat(begin, tmp);
strcpy (begin, str);
strcat (begin, tmp);
return 1;
}
@ -376,21 +337,18 @@ R_API int r_str_inject(char *begin, char *end, char *str, int maxlen)
replace all occurrences, otherwise replace only the first.
This returns a new string; the caller should free it. */
static int strsub_memcmp (char *string, char *pat, int len)
{
int res = 0;
while(len--) {
static int strsub_memcmp (char *string, char *pat, int len) {
int res;
for (res = 0; len-->0; pat++) {
if (*pat!='?')
res += *string - *pat;
string = string+1;
pat = pat+1;
string++;
}
return res;
}
// TODO: rename r_str_replace
R_API char *r_str_sub(char *string, char *pat, char *rep, int global)
{
R_API char *r_str_sub(char *string, char *pat, char *rep, int global) {
int patlen, templen, tempsize, repl, i;
char *temp, *r;
@ -414,71 +372,64 @@ R_API char *r_str_sub(char *string, char *pat, char *rep, int global)
return (temp);
}
R_API char *r_str_clean(char *str)
{
R_API char *r_str_clean(char *str) {
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;
if (str != NULL) {
while (str[0] && iswhitechar (str[0]))
str = str + 1;
if ((len = strlen(str))>0)
for (ptr = str+len-1;ptr!=str;ptr = ptr - 1) {
if (iswhitechar (ptr[0]))
ptr[0]='\0';
else break;
}
}
return str;
}
R_API int r_str_escape(char *buf)
{
R_API int r_str_escape(char *buf) {
unsigned char ch = 0, ch2 = 0;
int err = 0;
int i;
for(i=0;buf[i];i++) {
if (buf[i]=='\\') {
if (buf[i+1]=='e') {
buf[i] = 0x1b;
strcpy(buf+i+1, buf+i+2);
} else if (buf[i+1]=='r') {
buf[i] = 0x0d;
strcpy(buf+i+1, buf+i+2);
} else if (buf[i+1]=='n') {
buf[i] = 0x0a;
strcpy(buf+i+1, buf+i+2);
} else if (buf[i+1]=='x') {
err = ch2 = ch = 0;
if (!buf[i+2] || !buf[i+3]) {
printf("Unexpected end of string.\n");
return 0;
}
err |= hex2int(&ch, buf[i+2]);
err |= hex2int(&ch2, buf[i+3]);
if (err) {
printf("Incorrect hexadecimal characters for conversion.\n");
return 0;
}
buf[i] = (ch<<4)+ch2;
strcpy(buf+i+1, buf+i+4);
} else {
printf("'\\x' expected.\n");
for (i=0; buf[i]; i++) {
// only parse scaped characters //
if (buf[i]!='\\')
continue;
if (buf[i+1]=='e') {
buf[i] = 0x1b;
strcpy (buf+i+1, buf+i+2);
} else if (buf[i+1]=='r') {
buf[i] = 0x0d;
strcpy (buf+i+1, buf+i+2);
} else if (buf[i+1]=='n') {
buf[i] = 0x0a;
strcpy (buf+i+1, buf+i+2);
} else if (buf[i+1]=='x') {
err = ch2 = ch = 0;
if (!buf[i+2] || !buf[i+3]) {
eprintf ("Unexpected end of string.\n");
return 0;
}
err |= hex2int (&ch, buf[i+2]);
err |= hex2int (&ch2, buf[i+3]);
if (err) {
eprintf ("Incorrect hexadecimal characters for conversion.\n");
return 0;
}
buf[i] = (ch<<4)+ch2;
strcpy (buf+i+1, buf+i+4);
} else {
eprintf ("'\\x' expected.\n");
return 0;
}
}
return i;
}
/* ansi helpers */
R_API int r_str_ansi_len(const char *str)
{
R_API int r_str_ansi_len(const char *str) {
int i=0, len = 0;
while (str[i]) {
if (str[i]==0x1b && str[i+1]=='[')
@ -489,20 +440,78 @@ R_API int r_str_ansi_len(const char *str)
return len;
}
R_API const char *r_str_ansi_chrn(const char *str, int n)
{
int i=0, len = 0;
while(str[i]) {
if (n == len)
break;
R_API const char *r_str_ansi_chrn(const char *str, int n) {
int len, i;
for (i=len=0; str[i] && (n!=len); i++) {
if (str[i]==0x1b && str[i+1]=='[')
for(++i;str[i]&&str[i]!='J'&&str[i]!='m'&&str[i]!='H';i++);
for (++i;str[i]&&str[i]!='J'&&str[i]!='m'&&str[i]!='H';i++);
else len++;
i++;
}
return str+i;
}
#define MAXARG 128
R_API char **r_str_argv(const char *_str, int *_argc) {
int argc = 0;
int escape = 0;
int quote = 0;
char *optr, *ptr, *str = strdup (_str);
char **argv = (char **)malloc (MAXARG*sizeof(char*));
optr = ptr = r_str_chop_ro (str);
for (; *ptr && argc<MAXARG; ptr++) {
switch (*ptr) {
case '\'':
case '"':
if (escape) {
escape = 0;
strcpy (ptr, ptr+1);
} else {
if (quote) {
*ptr = '\0';
argv[argc++] = optr;
optr = ptr+1;
quote = 0;
} else {
quote = *ptr;
optr = ptr+1;
}
}
break;
case '\\':
escape = 1;
break;
case ' ':
if (!escape && !quote) {
*ptr = '\0';
if (*optr) {
argv[argc++] = optr;
optr = ptr+1;
}
}
break;
default:
escape = 0;
break;
}
}
if (*optr) {
argv[argc++] = optr;
optr = ptr+1;
}
argv[argc] = NULL;
if (_argc)
*_argc = argc;
return argv;
}
R_API void r_str_argv_free(char **argv) {
// TODO: free the internal food or just the first element
// free (argv[0]); // MEMORY LEAK
free (argv);
}
#if 0
/* XXX this is necessary ??? */
// TODO: make it dynamic
@ -531,39 +540,3 @@ R_API char *r_bprintf_get()
return s;
}
#endif
#if 0
int r_str_argv_parse(const char *str, int argc, char **argv)
{
int n = 0;
int i = 0;
char *tmp, *tmp2;
free(ps.args);
ps.args = strdup(ps.filename);
tmp2 = ps.args;
// 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]=='/'))
continue;
tmp[0]='\0';
ps.argv[i] = tmp2;
tmp2 = tmp+1;
if (++i>254) {
printf("Too many arguments. truncated\n");
break;
}
}
}
ps.argv[i] = tmp2;
ps.argv[i+1] = 0;
tmp = strchr(config.file, ' ');
if (tmp) *tmp = '\0';
//config.file = strdup("/bin/ls"); //ps.argv[0];
//eprintf("ppa:A0(%s)\n", ps.argv[0]);
return n;
}
#endif

View File

@ -4,7 +4,7 @@ ifeq ($(WITHPIC),1)
# OSX
FLAGS=-I../../include -L.. -lr_util -g -DVERSION=\"${VERSION}\"
#FLAGS=-I../../include -Wl,-R.. -L.. -lr_util -g -DVERSION=\"${VERSION}\"
EFLAGS=
EFLAGS=-L.. -lr_util
else
FLAGS=-I../../include -g -DVERSION=\"${VERSION}\"
EFLAGS=../libr_util.a
@ -15,6 +15,7 @@ BINS+=rax2${EXT_EXE}
BINS+=ralloc${EXT_EXE}
BINS+=array${EXT_EXE}
BINS+=pool${EXT_EXE}
BINS+=argv${EXT_EXE}
BINS+=test_sys${EXT_EXE}
BINS+=test_str${EXT_EXE}
BINS+=test_file_slurp_hexpairs${EXT_EXE}
@ -28,6 +29,9 @@ ralloc${EXT_EXE}:
test${EXT_EXE}:
${CC} ${FLAGS} test.c ${EFLAGS} -o test${EXT_EXE}
argv${EXT_EXE}:
${CC} ${FLAGS} argv.c ${EFLAGS} -o argv${EXT_EXE}
test_sys${EXT_EXE}: test_sys.c
${CC} ${FLAGS} test_sys.c ${EFLAGS} -o test_sys${EXT_EXE}

19
libr/util/t/argv.c Normal file
View File

@ -0,0 +1,19 @@
#include <r_util.h>
static void test(const char *str) {
int i, argc;
char **argv = r_str_argv (str, &argc);
printf ("[%s]\n", str);
for(i=0; i<argc; i++)
printf (" - %s\n", argv[i]);
r_str_argv_free (argv);
}
main () {
test (" hello world ");
test ("hello world");
test ("hello \"world\"");
test ("'hello world'");
test ("/bin/ls -l 'food is pure bar' \"barra cow is low\"");
test ("'hello' \"world\"");
}

View File

@ -20,7 +20,7 @@ while(<STDIN>) {
s/:/\n\t/;
/(.*):/;
$file = $1;
print "$path/$_" if ($file ne $ofile)
print "$path/$_" if ($file ne $ofile);
$ofile = $file;
}
#{ print "$path/".$line; }