mirror of
https://github.com/radareorg/r0.git
synced 2026-11-07 23:02:41 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28d49ebd95 | ||
|
|
4312ed31c8 |
No files matched your search
@@ -1,8 +1,8 @@
|
||||
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
|
||||
|
||||
static void cmd_hexdump(char *arg) {
|
||||
unsigned int len = bsize;
|
||||
unsigned char *buf = getcurblk(arg, &len);
|
||||
int len = bsize;
|
||||
ut8 *buf = getcurblk(arg, &len);
|
||||
if (buf) {
|
||||
hexdump(buf, len, 16);
|
||||
free(buf);
|
||||
@@ -10,8 +10,8 @@ static void cmd_hexdump(char *arg) {
|
||||
}
|
||||
|
||||
static void cmd_print(char *arg) {
|
||||
unsigned char *buf;
|
||||
unsigned int len = bsize;
|
||||
ut8 *buf;
|
||||
int len = bsize;
|
||||
if (*arg) {
|
||||
buf = getcurblk(arg, &len);
|
||||
if (!buf) return;
|
||||
@@ -26,18 +26,19 @@ static void cmd_print(char *arg) {
|
||||
}
|
||||
|
||||
static void cmd_bytedump(char *arg) {
|
||||
unsigned int i, len = bsize;
|
||||
unsigned char *buf = getcurblk(arg, &len);
|
||||
if (!buf) return;
|
||||
for(i=0;i<len;i++)
|
||||
printf("%02x", buf[i]);
|
||||
printf("\n");
|
||||
free(buf);
|
||||
int i, len = bsize;
|
||||
ut8 *buf = getcurblk(arg, &len);
|
||||
if (buf) {
|
||||
for(i=0;i<len;i++)
|
||||
printf("%02x", buf[i]);
|
||||
printf("\n");
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_search(char *arg) {
|
||||
unsigned char *buf;
|
||||
unsigned int i, len, hit=0;
|
||||
static void cmd_search(char *arg) {
|
||||
ut8 *buf;
|
||||
int i, len, hit = 0;
|
||||
arg = skipspaces(arg);
|
||||
if (*arg=='"') {
|
||||
arg++;
|
||||
@@ -74,41 +75,44 @@ static void cmd_seek(char *arg) {
|
||||
}
|
||||
|
||||
static void cmd_dump(char *file) {
|
||||
unsigned int len = bsize;
|
||||
void *buf = getcurblk("", &len);
|
||||
FILE *fd = fopen(file, "wb");
|
||||
if (fwrite(buf, len, 1, fd)<len)
|
||||
perror("fwrite");
|
||||
fclose(fd);
|
||||
free(buf);
|
||||
int len = bsize;
|
||||
ut8 *buf = getcurblk("", &len);
|
||||
if (len<1 || buf) {
|
||||
FILE *fd = fopen(file, "wb");
|
||||
if (fd) {
|
||||
if (fwrite(buf, len, 1, fd)<len)
|
||||
perror("fwrite");
|
||||
fclose(fd);
|
||||
} else perror("fopen");
|
||||
free(buf);
|
||||
} else perror("getcurblk");
|
||||
}
|
||||
|
||||
static void cmd_load(char *file) {
|
||||
int len;
|
||||
void *buf;
|
||||
FILE *fd = fopen(file, "rb");
|
||||
if (!fd) return;
|
||||
buf = malloc(bsize);
|
||||
if (!buf) return;
|
||||
len = fread(buf, 1, bsize, fd);
|
||||
if (len<bsize)
|
||||
perror("fread");
|
||||
if (io_write(buf, len)<len)
|
||||
perror("io_write");
|
||||
fclose(fd);
|
||||
free(buf);
|
||||
if (fd) {
|
||||
void *buf = malloc(bsize);
|
||||
if (bsize>0 && buf) {
|
||||
int len = fread(buf, 1, bsize, fd);
|
||||
if (len<bsize)
|
||||
perror("fread");
|
||||
if (io_write(buf, len)<len)
|
||||
perror("io_write");
|
||||
} else perror("malloc");
|
||||
free(buf);
|
||||
fclose(fd);
|
||||
} else perror("fopen");
|
||||
}
|
||||
|
||||
static void cmd_write(char *arg) {
|
||||
unsigned int len;
|
||||
int len;
|
||||
arg = skipspaces(arg);
|
||||
if (*arg=='"') {
|
||||
arg++;
|
||||
len = strlen(arg)-1;
|
||||
len = strlen(++arg)-1;
|
||||
arg[len]='\0';
|
||||
} else len = hexstr2raw(arg);
|
||||
io_seek(curseek, SEEK_SET);
|
||||
if (io_write(arg, len)<len)
|
||||
if (len<1 || io_write(arg, len)<len)
|
||||
perror("io_write");
|
||||
}
|
||||
|
||||
@@ -117,40 +121,40 @@ static void cmd_help(char *arg) {
|
||||
ut64 ret = str2ut64(arg);
|
||||
printf("0x%"LLF"x %"LLF"d 0%"LLF"o\n", ret, ret, ret);
|
||||
} else printf(
|
||||
"s[+-addr] seek to relative or absolute address\n"
|
||||
"b[+-size] change block size\n"
|
||||
"w[hex|\"str\"] write hexpair or string\n"
|
||||
"/[hex|\"str\"] search hexpair or string\n"
|
||||
"x[size] hexdump\n"
|
||||
"X[size] hexpair dump\n"
|
||||
"p[fmt] print formatted current block ('p' for help)\n"
|
||||
"r[-[num]] truncate or -remove N bytes\n"
|
||||
".[file] interpret file\n"
|
||||
"<[file] load file in current seek\n"
|
||||
">[file] dump current block to file\n"
|
||||
"!cmd run shell command\n"
|
||||
"?expr calculate numeric expression\n"
|
||||
"q quit\n");
|
||||
"s[+-addr] seek to relative or absolute address\n"
|
||||
"b[+-size] change block size\n"
|
||||
"w[hex|\"str\"] write hexpair or string\n"
|
||||
"/[hex|\"str\"] search hexpair or string\n"
|
||||
"x[size] hexdump\n"
|
||||
"X[size] hexpair dump\n"
|
||||
"p[fmt] print formatted current block ('p' for help)\n"
|
||||
"r[-[num]] truncate or -remove N bytes\n"
|
||||
".[file] interpret file\n"
|
||||
"<[file] load file in current seek\n"
|
||||
">[file] dump current block to file\n"
|
||||
"!cmd run shell command\n"
|
||||
"?expr calculate numeric expression\n"
|
||||
"q quit\n");
|
||||
}
|
||||
|
||||
static void cmd_resize(char *arg) {
|
||||
unsigned int len;
|
||||
int ret = 0;
|
||||
if (!*arg) printf("%"LLF"d\n", (long long int)io_seek(0, SEEK_END));
|
||||
int len, ret = 0;
|
||||
if (!*arg) printf("%"LLF"d\n", (ut64)io_seek(0, SEEK_END));
|
||||
else if (*arg=='-') {
|
||||
ut8 *buf = malloc(bsize);
|
||||
if (buf) {
|
||||
ut64 i, n = str2ut64(arg+1);
|
||||
for(i=0;;i+=len) {
|
||||
for(i=0;!ret;i+=len) {
|
||||
io_seek(curseek+n+i, SEEK_SET);
|
||||
len = io_read(buf, bsize);
|
||||
if (len<1) break;
|
||||
io_seek(curseek+i, SEEK_SET);
|
||||
if (io_write(buf, len)<len)
|
||||
perror("io_write");
|
||||
if ((len = io_read(buf, bsize))>0) {
|
||||
io_seek(curseek+i, SEEK_SET);
|
||||
if (io_write(buf, len)<len)
|
||||
perror("io_write"),ret=-1;
|
||||
} else perror("io_read"), ret=-1;
|
||||
}
|
||||
free(buf);
|
||||
ret = io_truncate(io_seek(0, SEEK_END)-n);
|
||||
if ((ret = io_seek(0, SEEK_END))>n)
|
||||
ret = io_truncate(ret-n);
|
||||
}
|
||||
} else ret = io_truncate(str2ut64(arg));
|
||||
if (ret<0)
|
||||
@@ -158,32 +162,29 @@ static void cmd_resize(char *arg) {
|
||||
}
|
||||
|
||||
static void cmd_system(char *arg) {
|
||||
unsigned int len = bsize;
|
||||
char *buf = NULL, str[64];
|
||||
int len = bsize;
|
||||
char *buf, str[1024];
|
||||
if (strstr(arg, "BLOCK")) {
|
||||
FILE *fd = fopen(".curblk", "w");
|
||||
FILE *fd = fopen(".curblk", "wb");
|
||||
if (fd) {
|
||||
buf = getcurblk("", &len);
|
||||
if (buf) {
|
||||
if ((buf = getcurblk("", &len))) {
|
||||
setenv("BLOCK", ".curblk", 1);
|
||||
if (fwrite(buf, len, 1, fd)<len)
|
||||
perror("fwrite");
|
||||
fclose(fd);
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
if (strstr(arg, "OFFSET")) {
|
||||
sprintf(str, "%"LLF"d", curseek);
|
||||
setenv("OFFSET", str, 1); // XXX
|
||||
setenv("OFFSET", str, 1);
|
||||
}
|
||||
if (strstr(arg, "XOFFSET")) {
|
||||
sprintf(str, "0x%"LLF"x", curseek);
|
||||
setenv("XOFFSET", str, 1); // XXX
|
||||
setenv("XOFFSET", str, 1);
|
||||
}
|
||||
if (io_system(arg)<0)
|
||||
perror("system");
|
||||
unlink(".curblk");
|
||||
free(buf);
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#if __WIN32__
|
||||
|
||||
#include <windows.h>
|
||||
static HANDLE _fd = NULL;
|
||||
#define setenv(x,y,z) SetEnvironmentVariable(x, y)
|
||||
static inline int io_open(char *file) {
|
||||
_fd = CreateFile(file, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
@@ -15,10 +13,11 @@ static inline int io_open(char *file) {
|
||||
NULL, OPEN_ALWAYS, 0, NULL);
|
||||
return (_fd==INVALID_HANDLE_VALUE)?-1:0;
|
||||
}
|
||||
static int io_read(void *x, int y) {
|
||||
static inline int io_read(void *x, int y) {
|
||||
DWORD ret;
|
||||
return ReadFile(_fd,x,y,&ret,NULL)?ret:-1;
|
||||
return ReadFile(_fd, x, y, &ret, NULL)?ret:-1;
|
||||
}
|
||||
#define setenv(x,y,z) SetEnvironmentVariable(x, y)
|
||||
#define io_write(x,y) WriteFile(_fd, x, y, NULL, NULL)
|
||||
#define io_seek(x,y) SetFilePointer(_fd,x,0,!y?FILE_BEGIN:y==1?FILE_CURRENT:FILE_END)
|
||||
#define io_close() CloseHandle(_fd)
|
||||
@@ -41,5 +40,6 @@ static inline int io_open(char *file) {
|
||||
#define io_seek(x,y) lseek(_fd, x, y)
|
||||
#define io_close() close(_fd)
|
||||
#define io_system(x) system(x)
|
||||
#define io_truncate(x) ftruncate(_fd,(unsigned long)x)
|
||||
#define io_truncate(x) ftruncate(_fd, (unsigned long)x)
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
.Dd Sep 1, 2009
|
||||
.Dd Oct 7, 2009
|
||||
.Dt IRED 1
|
||||
.Os
|
||||
.Th IRED 1
|
||||
@@ -95,7 +95,15 @@ dump current block to file
|
||||
.It !cmd
|
||||
run shell command
|
||||
.Pp
|
||||
> !cp $BLOCK $FILE.curblock # save current block
|
||||
The following environment variables are defined when found in the command string:
|
||||
.Pp
|
||||
FILE is the filename of the current working file
|
||||
.Pp
|
||||
BLOCK points to the temporal filename with the current block dump
|
||||
.Pp
|
||||
OFFSET and XOFFSET are decimal and hexadecimal values of the current seek
|
||||
.Pp
|
||||
> !cp $BLOCK $FILE-$XOFFSET.curblock # save current block
|
||||
.It ?expr
|
||||
calculate numeric expression
|
||||
.Pp
|
||||
|
||||
@@ -6,28 +6,27 @@
|
||||
static int verbose = 1;
|
||||
static char *script = 0;
|
||||
static ut64 oldseek, curseek = 0LL;
|
||||
static unsigned int obsize, bsize = 256;
|
||||
static int obsize, bsize = 256;
|
||||
static int red_cmd(char *cmd); // XXX : recursive depenency
|
||||
|
||||
#include "red.h"
|
||||
#include "util.c"
|
||||
#include "cmd.c"
|
||||
|
||||
int red_slurpin() {
|
||||
int len;
|
||||
unsigned char buf[4096];
|
||||
static void red_slurpin() {
|
||||
ut8 buf[4096];
|
||||
for(;;) {
|
||||
len = read(0, buf, 4096);
|
||||
int len = read(0, buf, 4096);
|
||||
if (len<1) break;
|
||||
hexdump(buf, len, 16);
|
||||
curseek += len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *red_interpret(char *file) {
|
||||
static void red_interpret(char *file) {
|
||||
char buf[1024];
|
||||
FILE *fd = fopen(file, "r");
|
||||
if (fd != NULL) {
|
||||
file = NULL;
|
||||
for(;;) {
|
||||
if (fgets(buf, 1023, fd) == NULL)
|
||||
break;
|
||||
@@ -35,13 +34,12 @@ static char *red_interpret(char *file) {
|
||||
}
|
||||
fclose(fd);
|
||||
} else fprintf(stderr, "Cannot open script file '%s'\n", file);
|
||||
return file;
|
||||
}
|
||||
|
||||
static int red_cmd(char *cmd) {
|
||||
switch(*cmd) {
|
||||
case ';': case '#': break; // comment
|
||||
case 'q': return 0;
|
||||
case ';': case '#': break; // comment
|
||||
case '>': cmd_dump(cmd+1); break;
|
||||
case '<': cmd_load(cmd+1); break;
|
||||
case '.': red_interpret(skipspaces(cmd+1)); break;
|
||||
@@ -68,14 +66,14 @@ static int red_prompt() {
|
||||
}
|
||||
if (fgets(line, 4095, stdin) == NULL)
|
||||
return 0;
|
||||
line[strlen(line)-1] = 0;
|
||||
if (line[0] != '!') {
|
||||
line[strlen(line)-1] = '\0';
|
||||
if (*line != '!') {
|
||||
at = strchr(line, '@');
|
||||
oldseek = curseek;
|
||||
obsize = bsize;
|
||||
if (at) {
|
||||
*at = 0; at++;
|
||||
at2 = strchr(at, ':');
|
||||
*at = 0;
|
||||
at2 = strchr(++at, ':');
|
||||
if (at2) {
|
||||
*at2 = 0; at2++;
|
||||
if (*at2) bsize = (int)str2ut64(at2);
|
||||
@@ -86,18 +84,20 @@ static int red_prompt() {
|
||||
return red_cmd(skipspaces(line));
|
||||
}
|
||||
|
||||
static void red_open(char *file) {
|
||||
oldseek = 0;
|
||||
setenv("FILE", file, 1);
|
||||
if (io_open(file) != -1) {
|
||||
static int red_open(char *file) {
|
||||
int ret = io_open(file);
|
||||
if (ret != -1) {
|
||||
oldseek = 0;
|
||||
setenv("FILE", file, 1);
|
||||
if (script)
|
||||
script = red_interpret(script);
|
||||
red_interpret(script);
|
||||
while(red_prompt()) {
|
||||
curseek = oldseek;
|
||||
bsize = obsize;
|
||||
}
|
||||
io_close();
|
||||
} else fprintf(stderr, "Cannot open '%s'\n", file);
|
||||
return ret==-1 ?1:0;;
|
||||
}
|
||||
|
||||
static int red_help() {
|
||||
@@ -106,17 +106,17 @@ static int red_help() {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
int i, ret = 1;
|
||||
if (argc>1)
|
||||
for(i=1;i<argc;i++) {
|
||||
if (argv[i][0]=='-')
|
||||
switch(argv[i][1]) {
|
||||
case 'i': script = argv[++i]; break;
|
||||
case 'n': verbose = 0; break;
|
||||
case 'v': puts("red "VERSION" 2009"); return 0;
|
||||
case 'h': return red_help();
|
||||
case 0x0: return red_slurpin();
|
||||
} else red_open(argv[i]);
|
||||
} else return red_help();
|
||||
return 0;
|
||||
case 'v': puts("red "VERSION" 2009"); ret = 0; break;
|
||||
case 'h': ret = red_help(); break;
|
||||
case 0x0: red_slurpin(); ret = 0; break;
|
||||
} else ret = red_open(argv[i]);
|
||||
} else ret = red_help();
|
||||
return ret;
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#define VERSION "0.3"
|
||||
#define VERSION "0.4"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include "io.c"
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
@@ -8,16 +10,11 @@
|
||||
|
||||
#if(plan9)
|
||||
static int setenv(char *var, char *val, int force) {
|
||||
char str[128];
|
||||
char str[256];
|
||||
snprintf(str, sizeof(str), "echo %s > /env/%s", var, val);
|
||||
if (system(str)<0)
|
||||
perror("system");
|
||||
return force;
|
||||
return system(str);
|
||||
}
|
||||
#define LLF "L"
|
||||
#else
|
||||
#define LLF "ll"
|
||||
#endif
|
||||
|
||||
#include "util.c"
|
||||
#include "cmd.c"
|
||||
@@ -10,14 +10,13 @@ static inline char *skipspaces(char *arg) {
|
||||
static inline void hexdump(const ut8 *buf, unsigned int len, int w) {
|
||||
unsigned int i, j;
|
||||
for(i=0;i<len;i+=w) {
|
||||
printf("0x%08" LLF "x ", curseek+i);
|
||||
printf("0x%08"LLF"x ", curseek+i);
|
||||
for(j=i;j<i+w;j++) {
|
||||
if (j>=len) {
|
||||
printf(j%2?" ":" ");
|
||||
continue;
|
||||
}
|
||||
printf("%02x", buf[j]);
|
||||
if (j%2) printf(" ");
|
||||
printf(j%2?"%02x ":"%02x", buf[j]);
|
||||
}
|
||||
for(j=i;j<i+w;j++) {
|
||||
if (j>=len) printf(" ");
|
||||
@@ -28,7 +27,7 @@ static inline void hexdump(const ut8 *buf, unsigned int len, int w) {
|
||||
}
|
||||
|
||||
static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
|
||||
unsigned int i, inc=0, lup=0, up, rep = 0;
|
||||
unsigned int i, up, inc = 0, lup = 0, rep = 0;
|
||||
char *ofmt = fmt;
|
||||
do { /* TODO: needs cleanup */
|
||||
for(;(*fmt||rep);fmt++) {
|
||||
@@ -50,8 +49,8 @@ static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); inc=8; break;
|
||||
case '.': inc=1; break;
|
||||
case ':': inc=4; break;
|
||||
case 'z': for(i=0; inc<len && isascii(buf[0]);i++) { printf("%c", buf[0]); buf++; inc++; } if(i)printf("\n"); break;
|
||||
case 'Z': for(i=0; inc<len && isascii(buf[0]);i++) { printf("%c", buf[0]); buf+=2; inc+=2; } if(i)printf("\n"); break;
|
||||
case 'z': for(i=0; inc<len && isascii(buf[0]);i++) { printf(i?"%c\n":"%c", buf[0]); buf++; } inc++; break;
|
||||
case 'Z': for(i=0; inc<len && isascii(buf[0]);i++) { printf(i?"%c\n":"%c", buf[0]); buf+=2; } inc+=2; break;
|
||||
case '*': rep = lup; break;
|
||||
default: fprintf(stderr, "Unknown format '%c' (%d)\n", up, up);
|
||||
return;
|
||||
@@ -62,19 +61,19 @@ static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
|
||||
len -= inc;
|
||||
}
|
||||
fmt = ofmt;
|
||||
} while(!rep && inc && inc <len);
|
||||
} while(!rep && inc && inc<len);
|
||||
}
|
||||
|
||||
static ut64 str2ut64(char *str) {
|
||||
ut64 ret = 0LL;
|
||||
str = skipspaces(str);
|
||||
if (str[0]=='b'&&str[1]==0)
|
||||
if (str[0]=='b'&&str[1]=='\0')
|
||||
ret = bsize;
|
||||
else if (str[0]=='0') {
|
||||
if (str[1]=='x') sscanf(str, "0x%"LLF"x", &ret);
|
||||
else sscanf(str, "0x%"LLF"o", &ret);
|
||||
} else sscanf(str, "%"LLF"u", &ret);
|
||||
str+=strlen(str)-1;
|
||||
str += strlen(str)-1;
|
||||
if (*str=='K') ret *= 1024;
|
||||
else if (*str=='M') ret *= 1024*1024;
|
||||
else if (*str=='G') ret *= 1024*1024*1024;
|
||||
@@ -82,17 +81,17 @@ static ut64 str2ut64(char *str) {
|
||||
}
|
||||
|
||||
static int hex2byte(ut8 *val, ut8 c) {
|
||||
if ('0' <= c && c <= '9') *val = (ut8)(*val) * 16 + ( c - '0');
|
||||
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;
|
||||
}
|
||||
|
||||
static int hexstr2raw(char *arg) {
|
||||
ut8 *ptr, c = 0, d;
|
||||
static unsigned int hexstr2raw(char *arg) {
|
||||
ut8 *ptr, d, c = 0;
|
||||
unsigned int j = 0, len = 0;
|
||||
for (ptr=(ut8 *)arg;*ptr;ptr++) {
|
||||
for (ptr=(ut8 *)arg; *ptr; ptr++) {
|
||||
if (*ptr==' ') continue;
|
||||
d = c;
|
||||
if (hex2byte(&c, *ptr))
|
||||
@@ -107,13 +106,13 @@ static int hexstr2raw(char *arg) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static void *getcurblk(char *arg, unsigned int *len) {
|
||||
void *buf;
|
||||
static void *getcurblk(char *arg, int *len) {
|
||||
void *buf = NULL;
|
||||
if (*arg) {
|
||||
*len = (int)str2ut64(arg);
|
||||
if (*len <1) *len = bsize;
|
||||
if (*len<1) *len = bsize;
|
||||
}
|
||||
if ((buf = malloc(*len)) != NULL) {
|
||||
if (*len>0 && (buf = malloc(*len)) != NULL) {
|
||||
if (io_seek((int)curseek, SEEK_SET)<0) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# vired: the visual raw editor
|
||||
# copyleft: pancake at nopcode dot org @ 2009
|
||||
|
||||
PATH=.:$PATH
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
$0 | ired -n $@
|
||||
exit 0
|
||||
|
||||
Reference in new issue
Block a user