Example #1
0
R_API char *r_str_clean(char *str) {
	int len;
	char *ptr;
	if (str != NULL) {
		while (*str && iswhitechar (*str))
			str++;
		if ((len = strlen (str)) > 0 )
			for (ptr = str+len-1; ptr!=str; ptr = ptr - 1) {
				if (iswhitechar (*ptr))
					*ptr = '\0';
				else break;
			}
	}
	return str;
}
Example #2
0
// TODO: rename to r_str_trim_inplace() or something like that
R_API char *r_str_chop(char *str) {
	int len;
	char *ptr;

	if (!str) return NULL;
	while (*str && iswhitechar (*str))
		memmove (str, str + 1, strlen (str + 1) + 1);
	len = strlen (str);
	if (len > 0) {
		for (ptr = str + len-1; ptr != str; ptr--) {
			if (!iswhitechar (*ptr)) break;
			*ptr = '\0';
		}
	}
	return str;
}
Example #3
0
R_API char *r_str_trim_tail(char *str) {
	char *ptr = str;
	if (str == NULL) return NULL;
	if (!*str) return str;
	ptr += strlen (str);
	for (ptr--; (ptr > str) && iswhitechar (*ptr); ptr--)
		*ptr = '\0';
	return str;
}
Example #4
0
R_API char *r_str_trim(char *str) {
	int i;
	char *ptr;
	if (!str) return NULL;
	for (ptr = str, i=0; str[i]; i++)
		if (!iswhitechar (str[i]))
			*ptr++ = str[i];
	*ptr = '\0';
	return str;
}
Example #5
0
R_API char *r_str_chop(char *str) {
	int len;
	char *ptr;

	if (str == NULL)
		return NULL;
		
	while (*str && iswhitechar (*str))
		str = str + 1;
		
	len = strlen (str);
	
	if (len>0)
	for (ptr = str+len-1; ptr!=str; ptr--) {
		if (iswhitechar (*ptr)) 
			*ptr = '\0';
		else break;
	}	       
	return str;
}
Example #6
0
/* remove spaces from the head of the string.
 * the string is changed in place */
R_API char *r_str_trim_head(char *str) {
	char *p;

	if (!str)
		return NULL;

	for (p = str; *p && iswhitechar (*p); p++)
		;

	/* Take the trailing null into account */
	memmove (str, p, strlen (p) + 1);

	return str;
}
Example #7
0
// Remove whitespace chars from the tail of the string, replacing them with
// null bytes. The string is changed in-place.
R_API char *r_str_trim_tail(char *str) {
	int length;

	if (!str)
		return NULL;

	length = strlen (str);

	if (!length)
		return str;

	while (length--) {
		if (iswhitechar (str[length]))
			str[length] = '\0';
		else break;
	}

	return str;
}
Example #8
0
// Remove whitespace chars from the tail of the string, replacing them with
// null bytes. The string is changed in-place.
R_API char *r_str_trim_tail(char *str) {
	int length;

	if (!str) {
		return NULL;
	}
	length = strlen (str);
	if (!length) {
		return str;
	}

	while (length--) {
		if (iswhitechar (str[length])) {
			str[length] = '\0';
		} else {
			break;
		}
	}

	return str;
}
Example #9
0
// Returns a pointer to the first non-whitespace character of str.
R_API const char *r_str_trim_const(const char *str) {
	if (str)
		for (; *str && iswhitechar (*str); str++);
	return str;
}
Example #10
0
// TODO: rewrite in macro?
R_API const char *r_str_chop_ro(const char *str) {
	if (str) while (*str && iswhitechar (*str)) str++;
	return str;
}
Example #11
0
File: rtr.c Project: moon2l/radare2
R_API void r_core_rtr_add(RCore *core, const char *_input) {
	char *port, input[1024], *host = NULL, *file = NULL, *ptr = NULL, buf[1024];
	int proto, i;
	RSocket *fd;

	strncpy (input, _input, sizeof (input)-4);
	/* Parse uri */
	if ((ptr = strstr(input, "tcp://"))) {
		proto = RTR_PROT_TCP;
		host = ptr+6;
	} else if ((ptr = strstr(input, "udp://"))) {
		proto = RTR_PROT_UDP;
		host = ptr+6;
	} else if ((ptr = strstr(input, "rap://"))) {
		proto = RTR_PROT_RAP;
		host = ptr+6;
	} else {
		proto = RTR_PROT_RAP;
		host = input;
	}
	while (*host&&iswhitechar(*host))
		host++;

	if (!(ptr = strchr (host, ':'))) {
		eprintf ("Error: Port is not specified\n");
		return;
	}
	ptr[0] = '\0';
	ptr = ptr+1;

	if (!(file = strchr (ptr, '/'))) {
		eprintf("Error: Missing '/'\n");
		return;
	}
	file[0] = '\0';
	file = file+1;
	port = ptr;

	fd = r_socket_new (R_FALSE);
	if (!fd) {
		eprintf ("Error: Cannot create new socket\n");
		return;
	}
	switch (proto) {
	case RTR_PROT_RAP:
		if (!r_socket_connect_tcp (fd, host, port)) { //TODO: Use rap.ssl
			eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port);
			return;
		}
		eprintf ("Connected to: %s at port %s\n", host, port);
		/* send */
		buf[0] = RTR_RAP_OPEN;
		buf[1] = 0;
		buf[2] = (ut8)(strlen (file)+1);
		memcpy (buf+3, file, buf[2]);
		r_socket_write(fd, buf, 3+buf[2]);
		/* read */
		eprintf ("waiting... "); fflush(stdout);
		r_socket_read (fd, (ut8*)buf, 5);
		r_mem_copyendian ((ut8 *)&i, (ut8*)buf+1, 4, core->assembler->big_endian);
		if (buf[0] != (char)(RTR_RAP_OPEN|RTR_RAP_REPLY) || i<= 0) {
			eprintf ("Error: Wrong reply\n");
			return;
		}
		eprintf ("ok\n");
		break;
	case RTR_PROT_TCP:
		if (!r_socket_connect_tcp (fd, host, port)) { //TODO: Use rap.ssl
			eprintf("Error: Cannot connect to '%s' (%s)\n", host, port);
			return;
		}
		eprintf ("Connected to: %s at port %s\n", host, port);
		break;
	case RTR_PROT_UDP:
		if (!r_socket_connect_udp(fd, host, port)) { //TODO: Use rap.ssl
			eprintf("Error: Cannot connect to '%s' (%s)\n", host, port);
			return;
		}
		eprintf("Connected to: %s at port %s\n", host, port);
		break;
	}

	for (i = 0; i < RTR_MAX_HOSTS; i++)
		if (!rtr_host[i].fd) {
			rtr_host[i].proto = proto;
			memcpy (rtr_host[i].host, host, 512);
			rtr_host[i].port = atoi(port);
			memcpy (rtr_host[i].file, file, 1024);
			rtr_host[i].fd = fd;
			rtr_n = i;
			break;
		}

	r_core_rtr_list (core);
}
Example #12
0
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len,
		const char *formatname, int mode, const char *setval, char *ofield) {
	int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0;
	const int old_bits = p->bits;
	char *args = NULL, *bracket, tmp, last = 0;
	ut64 addr = 0, addr64 = 0, seeki = 0;
	static int slide = 0, oldslide = 0;
	char namefmt[8], *field = NULL;
	const char *arg = NULL;
	const char *fmt = NULL;
	const char *argend;
	int viewflags = 0;
	char *oarg = NULL;
	ut8 *buf;

	/* Load format from name into fmt */
	if (!formatname) return 0;
	fmt = r_strht_get (p->formats, formatname);
	if (!fmt) fmt = formatname;
	while (*fmt && iswhitechar (*fmt)) fmt++;
	argend = fmt+strlen (fmt);
	arg = fmt;

	nexti = nargs = i = j = 0;

	if (len < 1) return 0;
	// len+2 to save space for the null termination in wide strings
	buf = calloc (1,len + 2);
	if (!buf) return 0;
	memcpy (buf, b, len);
	endian = p->big_endian;

	if (ofield && ofield != MINUSONE) field = strdup (ofield);

	/* get times */
	otimes = times = atoi (arg);
	if (times > 0) {
		while (*arg >= '0' && *arg <= '9') arg++;
	}

	bracket = strchr (arg,'{');
	if (bracket) {
		char *end = strchr (arg, '}');
		if (end == NULL) {
			eprintf ("No end bracket. Try pm {ecx}b @ esi\n");
			goto beach;
		}
		*end = '\0';
		times = r_num_math (NULL, bracket+1);
		arg = end + 1;
	}

	if (*arg=='\0') {
		goto beach;
	}

	/* get args */
	args = get_args_offset (arg);
	if (args) {
		int l=0, maxl = 0;
		argend = args;
		args = strdup (args+1);
		nargs = r_str_word_set0 (args);
		if (nargs == 0)
			R_FREE (args);
		for (i=0; i<nargs; i++) {
			const int len = strlen (r_str_word_get0 (args, i));
			if (len > maxl)
				maxl = len;
		}
		l++;
		snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR);
	}
#define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR)
#define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR))
	if (mode == R_PRINT_JSON && slide==0) p->cb_printf("[");
	if (arg[0] == '0') {
		mode |= R_PRINT_UNIONMODE;
		arg++;
	} else {
		mode &= ~R_PRINT_UNIONMODE;
	}
	if (mode & R_PRINT_DOT) {
		char *fmtname;
		if (formatname && *formatname) {
			if (strchr (formatname, ' ')) {
				fmtname = r_str_newf ("0x%"PFMT64x, seek);
			} else {
				fmtname = strdup (formatname);
			}
		} else {
			fmtname = r_str_newf ("0x%"PFMT64x, seek);
		}
		p->cb_printf ("digraph g { graph [ rank=same; rankdir=LR; ];\n");
		p->cb_printf ("root [ rank=1; shape=record\nlabel=\"%s", fmtname);
	}

	/* go format */
	i = 0;
	if (!times)
		otimes = times = 1;
	for (; times; times--) { // repeat N times
		const char * orig = arg;
		int first = 1;
		if (otimes>1) {
			if (mode & R_PRINT_JSON) {
				if (otimes > times) p->cb_printf (",");
				p->cb_printf ("[{\"index\":%d,\"offset\":%d},", otimes-times, seek+i);
			} else {
				p->cb_printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times);
			}
		}
		arg = orig;
		for (idx=0; i<len && arg<argend && *arg; arg++) {
			int size = 0, elem = 0; /* size of the array, element of the array */
			char *fieldname = NULL, *fmtname = NULL;
			if (mode & R_PRINT_UNIONMODE) {
				i = 0;
			}
			seeki = seek+i;
			addr = 0LL;
			invalid = 0;
			p->bits = old_bits;
			if (arg[0] == '[') {
				char *end = strchr (arg,']');
				if (end == NULL) {
					eprintf ("No end bracket.\n");
					goto beach;
				}
				*end = '\0';
				size = r_get_size (p->num, buf, endian, arg+1);
				arg = end + 1;
				*end = ']';
			} else {
				size = -1;
			}
			if (i+7<len) { // Max byte number where updateAddr will look into
				updateAddr (buf, i, endian, &addr, &addr64);
			} else {
				eprintf ("Likely a heap buffer overflow in %s at %d\n", __FILE__, __LINE__);
				goto beach;
			}

			tmp = *arg;

			if (args == NULL)
				mode |= R_PRINT_ISFIELD;
			if (mode & R_PRINT_MUSTSEE && otimes>1)
				p->cb_printf ("   ");
			if (idx<nargs && tmp != 'e' && isptr == 0) {
				char *dot = NULL, *bracket = NULL;
				if (field)
					dot = strchr (field, '.');
				if (dot)
					*dot = '\0';
				if (oarg != NULL)
					free (oarg);
				oarg = fieldname = strdup(r_str_word_get0 (args, idx));
				if (ISSTRUCT || tmp=='E' || tmp=='B' || tmp=='r') {
					if (*fieldname == '(') {
						fmtname = fieldname+1;
						fieldname = strchr (fieldname, ')');
						if (fieldname) *fieldname++ = '\0';
						else {
							eprintf ("Missing closing parenthesis in format ')'\n");
							goto beach;
						}
					} else {
						eprintf ("Missing name (%s)\n", fieldname);
						goto beach;
					}
				}
				if (args == NULL || (field==NULL && ofield != MINUSONE)
						|| (field && !strncmp(field, fieldname,
								strchr(field, '[')!=NULL?strchr(field, '[')-field:strlen(field)+1))) {
					mode |= R_PRINT_ISFIELD;
				} else {
					mode &= ~R_PRINT_ISFIELD;
				}

				/* There we handle specific element in array */
				if (field != NULL && (bracket = strchr (field, '[')) != NULL && mode & R_PRINT_ISFIELD) {
					char *end = strchr (field, ']');
					if (end == NULL) {
						eprintf ("Missing closing bracket\n");
						goto beach;
					}
					*end = '\0';
					elem = r_num_math (NULL, bracket+1)+1; // +1 to handle 0 index easily
					for ( ; bracket < end; bracket++)
						*bracket = '\0';
					size += elem*ARRAYINDEX_COEF;
				} else {
					elem = -1;
				}
				idx++;
				if (MUSTSEE && !SEEVALUE) {
					p->cb_printf (namefmt, fieldname);
				}
			}

		feed_me_again:
			switch (isptr) {
			case PTRSEEK:
				{
				nexti = i + (p->bits/8);
				i = 0;
				if (tmp == '?' ) seeki = addr;
				memset (buf, '\0', len);
				if (MUSTSEE)
					p->cb_printf ("(*0x%"PFMT64x") ", addr);
				if (addr == 0) isptr = NULLPTR;
				else isptr = PTRBACK;
				if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line,
						but len make it doesnt work... */
					p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4);
					if (i+3<len || i+7<len)
						updateAddr (buf, i, endian, &addr, &addr64);
					else {
						eprintf ("Likely a heap buffer overflow at %s at %d\n", __FILE__, __LINE__);
						goto beach;
					}
				} else {
					eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n",
							addr, b, len);
					p->cb_printf("\n");
					goto beach;
				}
				}
				break;
			case PTRBACK:
				// restore state after pointer seek
				i = nexti;
				memcpy (buf, b, len);
				isptr = NOPTR;
				arg--;
				continue;
			}
			if (tmp == 0 && last != '*')
				break;

			/* skip chars */
			switch (tmp) {
			case '*': // next char is a pointer
				isptr = PTRSEEK;
				arg++;
				tmp = *arg; //last;
				goto feed_me_again;
			case '+': // toggle view flags
				viewflags = !viewflags;
				continue;
			case 'e': // tmp swap endian
				endian ^= 1;
				continue;
			case ':': // skip 4 bytes
				if (size == -1) i+=4;
				else while (size--) i+=4;
				continue;
			case '.': // skip 1 byte
				if (size == -1) i++;
				else i+=size;
				continue;
			case 'p': // pointer reference
				if (*(arg+1) == '2') {
					p->bits = 16;
					arg++;
				} else if (*(arg+1) == '4') {
					p->bits = 32;
					arg++;
				} else if (*(arg+1) == '8') {
					p->bits = 64;
					arg++;
				}
				switch (p->bits) {
					case 16: tmp = 'w'; break;
					case 32: tmp = 'x'; break;
					default: tmp = 'q'; break;
				}
				break;
			}

			/* flags */
			if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
				char *newname = NULL;
				if (!fieldname) {
					newname = fieldname = r_str_newf ("pf.%d", seeki);
				}
				if (mode & R_PRINT_UNIONMODE) {
					p->cb_printf ("f %s=0x%08"PFMT64x"\n", formatname, seeki);
					goto beach;
				} else if (tmp == '?') {
					p->cb_printf ("f %s.%s_", fmtname, fieldname);
				} else if (tmp == 'E') {
					p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki);
				} else if (slide/STRUCTFLAG>0 && idx==1) {
					p->cb_printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki);
				} else p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname , seeki);
				if (newname) {
					free (newname);
					newname = fieldname = NULL;
				}
			}

			/* dot */
			if (mode & R_PRINT_DOT) {
				if (fieldname) {
					p->cb_printf ("|{0x%"PFMT64x"|%c|%s|<%s>",
						seeki, tmp, fieldname, fieldname);
				} else {
					p->cb_printf ("|{0x%"PFMT64x"|%c|",
						seeki, tmp);
				}
			}

			/* json */
			if (MUSTSEEJSON && mode & R_PRINT_JSON) {
				if (oldslide <= slide) {
					if (first) first = 0;
					else p->cb_printf (",");
				} else if (oldslide) {
					p->cb_printf ("]},");
				}
				p->cb_printf ("{\"name\":\"%s\",\"type\":\"", fieldname);
				if (ISSTRUCT) {
					p->cb_printf ("%s", fmtname);
				} else {
					p->cb_printf ("%c", tmp);
				}
				if (isptr) p->cb_printf ("*");
				p->cb_printf ("\",\"offset\":%d,\"value\":",(isptr)?(seek+nexti-(p->bits/8)):seek+i);
			}

			if (isptr == NULLPTR) {
				if (MUSTSEEJSON) p->cb_printf ("\"NULL\"}", tmp, seek+i);
				else if (MUSTSEE) p->cb_printf ("NULL\n");
				isptr = PTRBACK;
			} else
			/* format chars */
			// before to enter in the switch statement check buf boundaries due to  updateAddr
			// might go beyond its len and it's usually called in each of the following functions
			if (((i+3)<len) || (i+7)<len) {
				switch (tmp) {
				case 'u':
					i+= r_print_format_uleb (p, endian, mode, setval, seeki, buf, i, size);
					break;
				case 't':
					r_print_format_time (p, endian, mode, setval, seeki, buf, i, size);
					i+= (size==-1) ? 4 : 4*size;
					break;
				case 'q':
					r_print_format_quadword (p, endian, mode, setval, seeki, buf, i, size);
					i += (size==-1) ? 8 : 8*size;
					break;
				case 'b':
					r_print_format_byte (p, endian, mode, setval, seeki, buf, i, size);
					i+= (size==-1) ? 1 : size;
					break;
				case 'C':
					r_print_format_decchar (p, endian, mode,
						setval, seeki, buf, i, size);
					i+= (size==-1) ? 1 : size;
					break;
				case 'c':
					r_print_format_char (p, endian, mode,
						setval, seeki, buf, i, size);
					i+= (size==-1) ? 1 : size;
					break;
				case 'X':
					size = r_print_format_hexpairs (p, endian, mode,
						setval, seeki, buf, i, size);
					i += size;
					break;
				case 'T':
					if (r_print_format_10bytes (p, mode,
						setval, seeki, addr, buf) == 0)
						i += (size==-1) ? 4 : 4*size;
					break;
				case 'f':
					r_print_format_float (p, endian, mode, setval, seeki, buf, i, size);
					i += (size==-1) ? 4 : 4*size;
					break;
				case 'i':
				case 'd':
					r_print_format_hex (p, endian, mode, setval, seeki, buf, i, size);
					i+= (size==-1) ? 4 : 4*size;
					break;
				case 'D':
					if (size>0) p->cb_printf ("Size not yet implemented\n");
					if (p->disasm && p->user)
						i += p->disasm (p->user, seeki);
					break;
				case 'o':
					r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size);
					i+= (size==-1) ? 4 : 4*size;
					break;
				case 'x':
					r_print_format_hexflag (p, endian, mode, setval, seeki, buf, i, size);
					i+= (size==-1) ? 4 : 4*size;
					break;
				case 'w':
					r_print_format_word(p, endian, mode, setval, seeki, buf, i, size);
					i+= (size==-1) ? 2 : 2*size;
					break;
				case 'z': // zero terminated string
					r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size);
					if (size == -1)
						i+=strlen((char*)buf+i)+1;
					else
						while (size--) i++;
					break;
				case 'Z': // zero terminated wide string
					r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size);
					if (size == -1)
						i += r_wstr_clen((char*)(buf+i))*2+2;
					else
						while (size--) i+=2;
					break;
				case 's':
					if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0)
						i += (size==-1) ? 4 : 4*size;
					break;
				case 'S':
					if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0)
						i += (size==-1) ? 8 : 8*size;
					break;
				case 'B': // resolve bitfield
					if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF;
					r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size);
					i+=(size==-1)?1:size;
					break;
				case 'E': // resolve enum
					if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF;
					r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size);
					i+=(size==-1)?1:size;
					break;
				case 'r':
					r_print_format_register (p, mode, fmtname, setval);
					break;
				case '?':
					{
					int s = 0;
					char *nxtfield = NULL;
					if (size >= ARRAYINDEX_COEF) {
						elem = size/ARRAYINDEX_COEF-1;
						size %= ARRAYINDEX_COEF;
					}
					if (!(mode & R_PRINT_ISFIELD)) nxtfield = MINUSONE;
					else if (field) nxtfield = strchr (ofield, '.');
					if (nxtfield != MINUSONE && nxtfield != NULL) nxtfield++;

					if (MUSTSEE)
						if (!SEEVALUE) p->cb_printf ("\n");
					if (MUSTSEEJSON) {
						if (isptr)
							p->cb_printf ("%d},", seeki);
						else
							p->cb_printf ("[");
					}
					if (mode & R_PRINT_SEEFLAGS) slide+=STRUCTFLAG;
					oldslide = slide;
					slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
					if (size == -1) {
						s = r_print_format_struct (p, seeki,
							buf+i, len-i, fmtname, slide,
							mode, setval, nxtfield);
						i+= (isptr) ? 4 : s;
					} else {
						if (mode & R_PRINT_ISFIELD)
							if (!SEEVALUE) p->cb_printf ("[\n");
						while (size--) {
							if (elem == -1 || elem == 0) {
								mode |= R_PRINT_MUSTSEE;
								if (elem == 0) elem = -2;
							} else {
								mode &= ~R_PRINT_MUSTSEE;
							}
							s = r_print_format_struct (p, seek+i,
								buf+i, len-i, fmtname, slide, mode, setval, nxtfield);
							if ((MUSTSEE || MUSTSEEJSON) && size != 0 && elem == -1) {
								p->cb_printf (",");
								if (MUSTSEE) p->cb_printf ("\n");
							}
							if (elem > -1) elem--;
							i+= (isptr) ? 4 : s;
						}
						if (mode & R_PRINT_ISFIELD)
							if (!SEEVALUE) p->cb_printf ("]");
						if (MUSTSEEJSON) p->cb_printf ("]}]}");
					}
					oldslide = slide;
					slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
					if (mode & R_PRINT_SEEFLAGS) {
						oldslide = slide;
						slide-=STRUCTFLAG;
					}
					break;
					}
				default:
					/* ignore unknown chars */
					invalid = 1;
					break;
				} //switch
			} else {
				eprintf ("Likely a heap buffer overflow in %s at %d\n", __FILE__, __LINE__);
				goto beach;
			}
			if (mode & R_PRINT_DOT) {
				p->cb_printf ("}");
			}
			if (viewflags && p->offname) {
				const char *s = p->offname (p->user, seeki);
				if (s)
					p->cb_printf ("@(%s)", s);
				s = p->offname (p->user, addr);
				if (s)
					p->cb_printf ("*(%s)", s);
			}
			if (tmp != 'D' && !invalid && fmtname==NULL && MUSTSEE)
				p->cb_printf ("\n");
			last = tmp;
		}
		if (otimes>1) {
			if (MUSTSEEJSON) p->cb_printf ("]");
			else p->cb_printf ("}\n");
		}
		arg = orig;
		oldslide = 0;
	}
	if (mode & R_PRINT_JSON && slide==0) p->cb_printf("]\n");
	if (mode & R_PRINT_DOT) {
		p->cb_printf ("\"];\n}\n");
		// TODO: show nested structs and field reference lines
	}
beach:
	free (oarg);
	free (buf);
	free (field);
	free (args);
	return i;
}
Example #13
0
/* TODO: needs refactoring */
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, int len, const char *fmt, int elem, const char *setval) {
	int nargs, i, j, nexti, idx, times, otimes, endian, isptr = 0;
	int (*realprintf)(const char *str, ...);
	int (*oldprintf)(const char *str, ...);
	const char *argend = fmt+strlen (fmt);
	ut64 addr = 0, addr64 = 0, seeki = 0;;
	char *args = NULL, *bracket, tmp, last = 0;
	const char *arg = fmt;
	int viewflags = 0;
	char namefmt[8];
	ut8 *buf, buffer[256];

	nexti = nargs = endian = i = j = 0;

	if (len<1) return 0;
	buf = malloc (len);
	if (!buf) return 0;
	memcpy (buf, b, len);
	endian = p->big_endian;

	oldprintf = NULL;
	realprintf = p->printf;

	while (*arg && iswhitechar (*arg)) arg++;
	/* get times */
	otimes = times = atoi (arg);
	if (times > 0)
		while ((*arg>='0'&&*arg<='9')) arg++;
	bracket = strchr (arg,'{');
	if (bracket) {
		char *end = strchr (arg,'}');
		if (end == NULL) {
			eprintf ("No end bracket. Try pm {ecx}b @ esi\n");
			goto beach;
		}
		*end='\0';
		times = r_num_math (NULL, bracket+1);
		arg = end + 1;
	}

	if (*arg=='\0') {
		print_format_help (p);
		goto beach;
	}
	/* get args */
	args = strchr (arg, ' ');
	if (args) {
		int l=0, maxl = 0;
		argend = args;
		args = strdup (args+1);
		nargs = r_str_word_set0 (args+1);
		if (nargs == 0)
			R_FREE (args);
		for (i=0; i<nargs; i++) {
			int len = strlen (r_str_word_get0 (args+1, i));
			if (len>maxl) maxl = len;
		}
		l++;
		snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl);
	}

	/* go format */
	i = 0;
	if (!times) otimes = times = 1;
	for (; times; times--) { // repeat N times
		const char * orig = arg;
		if (otimes>1)
			p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times);
		idx = 0;
		arg = orig;
		for (idx=0; i<len && arg<argend && *arg; idx++, arg++) {
			seeki = seek+i;
			addr = 0LL;
			if (endian)
				 addr = (*(buf+i))<<24   | (*(buf+i+1))<<16 | *(buf+i+2)<<8 | *(buf+i+3);
			else     addr = (*(buf+i+3))<<24 | (*(buf+i+2))<<16 | *(buf+i+1)<<8 | *(buf+i);
			if (endian)
				 addr64 = (ut64)(*(buf+i))<<56 | (ut64)(*(buf+i+1))<<48
					| (ut64)*(buf+i+2)<<40 | (ut64)(*(buf+i+3))<<32
				 	| (*(buf+i+4))<<24 | (*(buf+i+5))<<16 | *(buf+i+6)<<8 | *(buf+i+7);
			else addr64 = ((ut64)(*(buf+i+7)))<<56 | (ut64)(*(buf+i+6))<<48
					| (ut64)(*(buf+i+5))<<40 | (ut64)(*(buf+i+4))<<32
				 	| (*(buf+i+3))<<24 | (*(buf+i+2))<<16 | *(buf+i+1)<<8 | *(buf+i);
			tmp = *arg;
		feed_me_again:
			switch (isptr) {
			case 1:
				nexti = i + (p->bits/8);
				i = 0;
				tmp = *arg;
				memset (buf, '\0', len);
				p->printf ("(*0x%"PFMT64x") ", addr);
				if (p->iob.read_at) {
					p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4);
				} else {
					eprintf ("(cannot read memory)\n");
					break;
				}
				isptr = 2;
				break;
			case 2:
				// restore state after pointer seek
				i = nexti;
				seeki = seek+i;
				memcpy (buf, b, len);
				isptr = 0;
				arg--;
				idx--;
				continue;
			}
			if (tmp == 0 && last != '*')
				break;
			/* skip chars */
			switch (tmp) {
			case '*':
				isptr = 1;
				if (i<=0 || !arg[1]) break;
				arg++;
				tmp = *arg; //last;
			//	arg--;
			//	idx--;
				goto feed_me_again;
			case '+':
				idx--;
				viewflags = !viewflags;
				continue;
			case 'e': // tmp swap endian
				idx--;
				endian ^= 1;
				continue;
			case ':': // skip char
				i+=4;
				idx-=4;
				continue;
			case '.': // skip char
				i++;
				idx--;
				continue;
			case 'p':
				tmp = (p->bits==64)?'q': 'x';
				//tmp = (sizeof (void*)==8)? 'q': 'x';
				break;
			case '?': // help
				print_format_help (p);
				idx--;
				i = len; // exit
				continue;
			}
			if (otimes>1)
				p->printf ("   ");
#define MUSTSET (setval && elem == idx)
#define MUSTSEE (elem == -1 || elem == idx)
			if (MUSTSEE) {
				if (!(MUSTSET)) {
					if (oldprintf)
						p->printf = oldprintf;
					if (idx<nargs)
						p->printf (namefmt, r_str_word_get0 (args, idx));
				}
			} else {
				if (!oldprintf)
					oldprintf = p->printf;
				p->printf = nullprintf;
			}
			/* cmt chars */
			switch (tmp) {
	#if 0
			case 'n': // enable newline
				j ^= 1;
				continue;
	#endif
#if 0
			case 't':
				/* unix timestamp */
				D cons_printf("0x%08x = ", config.seek+i);
				{
				/* dirty hack */
				int oldfmt = last_print_format;
				ut64 old = config.seek;
				radare_seek(config.seek+i, SEEK_SET);
				radare_read(0);
				print_data(config.seek+i, "8", buf+i, 4, FMT_TIME_UNIX);
				last_print_format=oldfmt;
				radare_seek(old, SEEK_SET);
				}
				break;
#endif
			case 'e':
				if (MUSTSET) {
					realprintf ("?e pf e not yet supported\n");
				} else {
					double doub;
					memcpy (&doub, buf+i, sizeof (double));
					p->printf ("0x%08"PFMT64x" = (double) ", seeki);
					p->printf ("%e", doub);
					i += 8;
				}
				break;
			case 'q':
				if (MUSTSET) {
					realprintf ("wv8 %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					p->printf ("(qword) ");
					p->printf ("0x%08"PFMT64x" ", addr64);
				}
				i += 8;
				break;
			case 'b':
				if (MUSTSET) {
					realprintf ("w %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					p->printf ("%d ; 0x%02x ; '%c' ", 
						buf[i], buf[i], IS_PRINTABLE (buf[i])?buf[i]:0);
				}
				i++;
				break;
			case 'c':
				if (MUSTSET) {
					realprintf ("?e pf c not yet implemented\n");
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					p->printf ("%d ; %d ; '%c' ",
						buf[i], (char)buf[i],
						IS_PRINTABLE (buf[i])?buf[i]:0);
				}
				i++;
				break;
			case 'B':
				if (MUSTSET) {
					realprintf ("?e pf B not yet implemented\n");
				} else {
					memset (buffer, '\0', 255);
					if (!p->iob.read_at) {
						printf ("(cannot read memory)\n");
						break;
					} else p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
					p->printf ("0x%08"PFMT64x" = ", seeki);
					for (j=0; j<10; j++) p->printf ("%02x ", buf[j]);
					p->printf (" ... (");
					for (j=0; j<10; j++)
						if (IS_PRINTABLE (buf[j]))
							p->printf ("%c", buf[j]);
					p->printf (")");
				}
				i += 4;
				break;
			case 'f':
				if (MUSTSET) {
					realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08"PFMT64x" = %f", seeki,
						(float)(addr));
				}
				i += 4;
				break;
			case 'i':
			case 'd': // TODO: support unsigned int?
				if (MUSTSET) {
					realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					p->printf ("%"PFMT64d" ", addr);
				}
				i += 4;
				break;
			case 'D':
				if (p->disasm && p->user)
					i += p->disasm (p->user, seeki);
				break;
			case 'x':
				if (MUSTSET) {
					realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					ut32 addr32 = (ut32)addr;
					p->printf ("0x%08"PFMT64x" = ", seeki);
					p->printf ("0x%08"PFMT64x" ", addr32);
				}
				//if (string_flag_offset(buf, (ut64)addr32, -1))
				//	p->printf("; %s", buf);
				i += 4;
				break;
			case 'w':
			case '1': // word (16 bits)
				if (MUSTSET) {
					realprintf ("wv2 %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08x = ", seeki);
					if (endian)
						 addr = (*(buf+i))<<8 | (*(buf+i+1));
					else     addr = (*(buf+i+1))<<8 | (*(buf+i));
					p->printf ("0x%04x ", addr);
				}
				i+=2;
				break;
			case 'z': // zero terminated string
				if (MUSTSET) {
					realprintf ("?e pf z not yet supported\n");
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					for (; buf[i]&&i<len; i++) {
						if (IS_PRINTABLE (buf[i]))
							p->printf ("%c", buf[i]);
						else p->printf (".");
					}
				}
				break;
			case 'Z': // zero terminated wide string
				p->printf ("0x%08"PFMT64x" = ", seeki);
				for (; buf[i] && i<len; i+=2) {
					if (IS_PRINTABLE (buf[i]))
						p->printf ("%c", buf[i]);
					else p->printf (".");
				}
				p->printf (" ");
				break;
			case 's':
				p->printf ("0x%08"PFMT64x" = ", seeki);
				memset (buffer, '\0', 255);
				if (p->iob.read_at) {
					p->iob.read_at (p->iob.io, (ut64)addr,
						buffer, sizeof (buffer)-8);
				} else {
					printf ("(cannot read memory)\n");
					break;
				}
				p->printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ",
					seeki, addr);
				p->printf ("%s ", buffer);
				i += 4;
				break;
			case 'S':
				p->printf ("0x%08"PFMT64x" = ", seeki);
				memset (buffer, '\0', 255);
				if (p->iob.read_at) {
					p->iob.read_at (p->iob.io, addr64,
						buffer, sizeof (buffer)-8);
				} else {
					printf ("(cannot read memory)\n");
					break;
				}
				p->printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ",
					seeki, addr);
				p->printf ("%s ", buffer);
				i += 8;
				break;
			default:
				/* ignore unknown chars */
				break;
			}
			if (viewflags && p->offname) {
				const char *s = p->offname (p->user, seeki);
				if (s) p->printf ("@(%s)", s);
				s = p->offname (p->user, addr);
				if (s) p->printf ("*(%s)", s);
			}
			if (tmp != 'D')
				p->printf ("\n");
			last = tmp;
		}
		if (otimes>1)
			p->printf ("}\n");
		arg = orig;
		idx = 0;
	}
	if (oldprintf)
		p->printf = oldprintf;
beach:
	free (buf);
	if (args) {
		free (args);
	}
	return i;
}
Example #14
0
R_API const char *r_str_trim_head(const char *str) {
	if (str)
		while (*str && iswhitechar (*str)) 
			str++;
	return str;
}
Example #15
0
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len,
		const char *fmt, int elem, const char *setval) {
	int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0;
	int (*oldprintf)(const char *str, ...);
	const char *argend = fmt+strlen (fmt);
	ut64 addr = 0, addr64 = 0, seeki = 0;;
	char *args = NULL, *bracket, tmp, last = 0;
	const char *arg = fmt;
	int viewflags = 0, flag = (elem==SEEFLAG)?1:0;
	char namefmt[8];
	static int slide=0;
	ut8 *buf;

	nexti = nargs = i = j = 0;

	if (len < 1)
		return 0;
	buf = malloc (len);
	if (!buf)
		return 0;
	memcpy (buf, b, len);
	endian = p->big_endian;

	oldprintf = NULL;
	realprintf = p->printf;

	while (*arg && iswhitechar (*arg)) arg++;

	/* get times */
	otimes = times = atoi (arg);
	if (times > 0)
		while ((*arg>='0'&&*arg<='9')) arg++;

	bracket = strchr (arg,'{');
	if (bracket) {
		char *end = strchr (arg, '}');
		if (end == NULL) {
			eprintf ("No end bracket. Try pm {ecx}b @ esi\n");
			goto beach;
		}
		*end='\0';
		times = r_num_math (NULL, bracket+1);
		arg = end + 1;
	}

	if (*arg=='\0' || *arg=='?') {
		print_format_help (p);
		goto beach;
	}

	/* get args */
	args = strchr (arg, ' ');
	if (args) {
		int l=0, maxl = 0;
		argend = args;
		args = strdup (args+1);
		nargs = r_str_word_set0 (args);
		if (nargs == 0)
			R_FREE (args);
		for (i=0; i<nargs; i++) {
			const int len = strlen (r_str_word_get0 (args, i));
			if (len > maxl)
				maxl = len;
		}
		l++;
		snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR);
	}

	/* go format */
	i = 0;
	if (!times)
		otimes = times = 1;
	for (; times; times--) { // repeat N times
		const char * orig = arg;
		if (otimes>1)
			p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times);
		arg = orig;
		for (idx=0; i<len && arg<argend && *arg; arg++) {
			int size;
			char *name = NULL;
			seeki = seek+i;
			addr = 0LL;
			invalid = 0;
			if (arg[0] == '[') {
				char *end = strchr (arg,']');
				if (end == NULL) {
					eprintf ("No end bracket.\n");
					goto beach;
				}
				*end = '\0';
				size = r_num_math (NULL, arg+1);
				arg = end + 1;
				*end = ']';
			} else {
				size = -1;
			}
			updateAddr (buf, i, endian, &addr, &addr64);

			tmp = *arg;

			if (otimes>1)
				p->printf ("   ");
#define MUSTSET (setval && elem == idx)
#define MUSTSEE (elem == -1 || elem == idx)
			if (MUSTSEE && !flag) {
				if (!(MUSTSET)) {
					if (oldprintf)
						p->printf = oldprintf;
					if (idx<nargs && tmp != 'e' && isptr == 0) {
						p->printf (namefmt, r_str_word_get0 (args, idx));
						idx++;
					}
				}
			} else {
				if (!oldprintf)
					oldprintf = p->printf;
				p->printf = nullprintf;
			}

		feed_me_again:
			switch (isptr) {
			case 1:
				{
				nexti = i + (p->bits/8);
				i = 0;
				if(tmp == '?' )seeki = addr;
				memset (buf, '\0', len);
				p->printf ("(*0x%"PFMT64x") ", addr);
				if (addr == 0) isptr = NULLPTR;
				else isptr = PTRBACK;
				if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line, 
						but len make it doesnt work... */
					p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4);
					updateAddr (buf, i, endian, &addr, &addr64);
				} else {
					eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n",
							addr, b, len);
					p->printf("\n");
					goto beach;
				}
				}
				break;
			case 2:
				// restore state after pointer seek
				i = nexti;
				seeki = seek+i;
				memcpy (buf, b, len);
				isptr = NOPTR;
				arg--;
				continue;
			}
			if (tmp == 0 && last != '*')
				break;

			/* skip chars */
			switch (tmp) {
			case '*': // next char is a pointer
				isptr = PTRSEEK;
				arg++;
				tmp = *arg; //last;
				goto feed_me_again;
			case '+': // toggle view flags
				viewflags = !viewflags;
				continue;
			case 'e': // tmp swap endian
				endian ^= 1;
				continue;
			case ':': // skip 4 bytes
				if (size == -1) i+=4;
				else
					while (size--) i+=4;
				continue;
			case '.': // skip 1 byte
				if (size == -1) i++;
				else
					while (size--) i++;
				continue;
			case 'p': // pointer reference
				tmp = (p->bits == 64)? 'q': 'x';
				//tmp = (sizeof (void*)==8)? 'q': 'x';
				break;
			}
			if (flag && isptr != NULLPTR) {
				if (tmp == '?') {
					char *n = strdup (r_str_word_get0 (args, idx)+1);
					char *par = strchr (n, ')');
					if (par == NULL) {
						eprintf ("No end parenthesis for struct name");
						free (n);
						goto beach;
					} else {
						*par = '.';
					}
					realprintf ("f %s_", n);
					free(n);
				} else if (slide>0 && idx==0) {
					realprintf ("%s=0x%08"PFMT64x"\n",
						r_str_word_get0 (args, idx), seeki);
				} else realprintf ("f %s=0x%08"PFMT64x"\n",
					r_str_word_get0 (args, idx) , seeki);
				idx++;
			}

			if (isptr == NULLPTR) {
				p->printf ("NULL");
				isptr = PTRBACK;
			} else
			/* cmt chars */
			switch (tmp) {
#if 0
			case 't':
				/* unix timestamp */
				D cons_printf("0x%08x = ", config.seek+i);
				{
				/* dirty hack */
				int oldfmt = last_print_format;
				ut64 old = config.seek;
				radare_seek(config.seek+i, SEEK_SET);
				radare_read(0);
				print_data(config.seek+i, "8", buf+i, 4, FMT_TIME_UNIX);
				last_print_format=oldfmt;
				radare_seek(old, SEEK_SET);
				}
				break;
#endif
			case 'e': //WTF is this? 'e' is supposed to swap endians?!
				if (size > 0)
					p->printf ("Size not yet implemented\n");
				if (MUSTSET) {
					realprintf ("?e pf e not yet supported\n");
				} else {
					double doub;
					memcpy (&doub, buf+i, sizeof (double));
					p->printf ("0x%08"PFMT64x" = (double) ", seeki);
					p->printf ("%e", doub);
					i += 8;
				}
				break;
			case 'q':
				r_print_format_quadword(p, endian, MUSTSET, setval, seeki, buf, i, size);
				i += (size==-1) ? 8 : 8*size;
				break;
			case 'b':
				r_print_format_byte(p, endian, MUSTSET, setval, seeki, buf, i, size);
				i+= (size==-1) ? 1 : size;
				break;
			case 'c':
				r_print_format_char (p, endian, MUSTSET,
					setval, seeki, buf, i, size);
				i+= (size==-1) ? 1 : size;
				break;
			case 'X':
				size = r_print_format_hexpairs (p, endian, MUSTSET,
					setval, seeki, buf, size);
				i += size;
				break;
			case 'T':
				if(r_print_format_10bytes(p, MUSTSET,
					setval, seeki, addr, buf) == 0)
					i += (size==-1) ? 4 : 4*size;
				break;
			case 'f':
				r_print_format_float(p, endian, MUSTSET, setval, seeki, buf, i, size);
				i += (size==-1) ? 4 : 4*size;
				break;
			case 'i':
			case 'd':
				r_print_format_hex(p, endian, MUSTSET, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'D':
				if (size>0) p->printf ("Size not yet implemented\n");
				if (p->disasm && p->user)
					i += p->disasm (p->user, seeki);
				break;
			case 'o':
				r_print_format_octal (p, endian, MUSTSET, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'x':
				r_print_format_hexflag(p, endian, MUSTSET, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'w':
			case '1': // word (16 bits)
				r_print_format_word(p, endian, MUSTSET, setval, seeki, buf, i, size);
				i+= (size==-1) ? 2 : 2*size;
				break;
			case 'z': // zero terminated string
				if (MUSTSET) {
					int buflen = strlen ((const char *)buf);
					if (buflen>seeki) {
						buflen = strlen ((const char *)buf+seeki);
					}
					if (strlen (setval) > buflen) {
						eprintf ("Warning: new string is longer than previous one \n");
					}
					realprintf ("w %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					for (; ((size || size==-1) && buf[i]) && i<len; i++) {
						if (IS_PRINTABLE (buf[i]))
							p->printf ("%c", buf[i]);
						else p->printf (".");
						size -= (size==-1) ? 0 : 1;
					}
				}
				if (size == -1)
					i++;
				else
					while (size--) i++;
				break;
			case 'Z': // zero terminated wide string
				if (MUSTSET) {
					if ((size = strlen(setval)) > r_wstr_clen((char*)(buf+seeki)))
						eprintf ("Warning: new string is longer than previous one\n");
					realprintf ("ww %s @ 0x%08"PFMT64x"\n", setval, seeki);
				} else {
					p->printf ("0x%08"PFMT64x" = ", seeki);
					for (; ((size || size==-1) && buf[i]) && i<len; i+=2) {
						if (IS_PRINTABLE (buf[i]))
							p->printf ("%c", buf[i]);
						else p->printf (".");
						size -= (size==-1) ? 0 : 1;
					}
				}
				if (size == -1)
					i+=2;
				else
					while (size--) i+=2;
				break;
			case 's':
				if (r_print_format_ptrstring (p, seeki, addr64, addr, 0) == 0)
					i += (size==-1) ? 4 : 4*size;
				break;
			case 'S':
				if (r_print_format_ptrstring (p, seeki, addr64, addr, 1) == 0)
					i += (size==-1) ? 8 : 8*size;
				break;
			case 'B': // resolve bitfield
				{
				char *structname, *osn;
				char *bitfield = NULL;
				structname = osn = strdup (r_str_word_get0 (args, idx-1));
				switch (size) {
				case 1: addr &= UT8_MAX; break;
				case 2: addr &= UT16_MAX; break;
				case 4: addr &= UT32_MAX; break;
				}
				if (*structname == '(') {
					name = strchr (structname, ')');
				} else {
					eprintf ("Bitfield name missing (%s)\n", structname);
					free (structname);
					goto beach;
				}
				structname++;
				if (name) *(name++) = '\0';
				else eprintf ("No ')'\n");

				if (p->get_bitfield) 
					bitfield = p->get_bitfield (p->user, structname, addr);
				if (bitfield && *bitfield) {
					p->printf (" %s (bitfield) = %s\n", name, bitfield);
				} else {
					p->printf (" %s (bitfield) = `tb %s 0x%x`\n",
						name, structname, addr);
				}
				i+= 4; //(isptr) ? 4 : s;
				free (osn);
				free (bitfield);
				}
				break;
			case 'E': // resolve enum
				{
				char *enumname, *osn;
				char *enumvalue = NULL;
				enumname = osn = strdup (r_str_word_get0 (args, idx-1));
				switch (size) {
				case 1: addr &= UT8_MAX; break;
				case 2: addr &= UT16_MAX; break;
				case 4: addr &= UT32_MAX; break;
				}
				if (*enumname == '(') {
					name = strchr (enumname, ')');
				} else {
					eprintf ("Enum name missing (%s)\n", enumname);
					free (enumname);
					goto beach;
				}
				enumname++;
				if (name) *(name++) = '\0';
				else eprintf ("No ')'\n");
				if (p->get_enumname) 
					enumvalue = p->get_enumname (p->user, enumname, addr);
				if (enumvalue && *enumvalue) {
					p->printf (" %s (enum) = 0x%"PFMT64x" ; %s\n",
						name, addr, enumvalue);
				} else {
					p->printf (" %s (enum) = `te %s 0x%x`\n",
						name, enumname, addr);
				}
				i+= (size==-1) ? 1 : size;
				free (osn);
				free (enumvalue);
				}
				break;
			case '?':
				{
				int s;
				char *structname, *osn;
				structname = osn = strdup (r_str_word_get0 (args, idx-1));
				if (*structname == '(') {
					name = strchr (structname, ')');
				} else {
					eprintf ("Struct name missing (%s)\n", structname);
					free (structname);
					goto beach;
				}
				structname++;
				if (name) *(name++) = '\0';
				else eprintf ("No ')'\n");
				p->printf ("<struct>\n");
				if (flag) slide+=STRUCTFLAG;
				slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
				s = r_print_format_struct (p, seeki,
					buf+i, len, structname--, slide);
				i+= (isptr) ? 4 : s;
				slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
				if (flag) slide-=STRUCTFLAG;
				free (osn);
				break;
				}
			default:
				/* ignore unknown chars */
				invalid = 1;
				break;
			}
			if (!flag && (!MUSTSEE || MUSTSET))
				idx++;
			if (viewflags && p->offname) {
				const char *s = p->offname (p->user, seeki);
				if (s)
					p->printf ("@(%s)", s);
				s = p->offname (p->user, addr);
				if (s)
					p->printf ("*(%s)", s);
			}
			if (tmp != 'D' && !invalid && name==NULL)
				p->printf ("\n");
			last = tmp;
		}
		if (otimes>1)
			p->printf ("}\n");
		arg = orig;
	}
	if (oldprintf)
		p->printf = oldprintf;
beach:
	free (buf);
	if (args)
		free (args);
	return i;
}
Example #16
0
R_API void r_core_rtr_add(RCore *core, const char *_input) {
	char *port, input[1024], *host = NULL, *file = NULL, *ptr = NULL, buf[1024];
	int proto, i, timeout, ret;
	RSocket *fd;

	timeout = r_config_get_i (core->config, "http.timeout");
	strncpy (input, _input, sizeof (input)-4);
	/* Parse uri */
	if ((ptr = strstr (input, "tcp://"))) {
		proto = RTR_PROT_TCP;
		host = ptr+6;
	} else if ((ptr = strstr(input, "http://"))) {
		proto = RTR_PROT_HTTP;
		host = ptr+7;
	} else if ((ptr = strstr(input, "udp://"))) {
		proto = RTR_PROT_UDP;
		host = ptr+6;
	} else if ((ptr = strstr(input, "rap://"))) {
		proto = RTR_PROT_RAP;
		host = ptr+6;
	} else {
		proto = RTR_PROT_RAP;
		host = input;
	}
	while (*host && iswhitechar (*host))
		host++;

	if (!(ptr = strchr (host, ':'))) {
		ptr = host;
		port = "80";
	} else {
		*ptr++ = '\0';
		port = ptr;
	}

	if (!(file = strchr (ptr, '/'))) {
		eprintf("Error: Missing '/'\n");
		return;
	}
	*file++ = 0;
	port = r_str_chop (port);
	while (*file==' ') file++;
	if (r_sandbox_enable (0)) {
		eprintf ("sandbox: connect disabled\n");
		return;
	}

	fd = r_socket_new (R_FALSE);
	if (!fd) {
		eprintf ("Error: Cannot create new socket\n");
		return;
	}
	switch (proto) {
	case RTR_PROT_HTTP:
		{
			char uri[1024], prompt[64];
			int len;
			char *str, *res;
			if (file[strlen (file)-1]=='/') {
				snprintf (prompt, sizeof (prompt), "[http://%s:%s/%s]> ",
					host, port, file);
				r_line_set_prompt (prompt);
				for (;;) {
					char *ptr, *str = r_line_readline ();
					if (!str || !*str) break;
					if (*str == 'q') break;
					ptr = r_str_uri_encode (str);
					if (ptr) str = ptr;
					snprintf (uri, sizeof (uri), "http://%s:%s/%s%s",
						host, port, file, str);
					if (ptr == str) free (ptr);
					str = r_socket_http_get (uri, NULL, &len);
					if (str) {
						str[len] = 0;
						res = strstr (str, "\n\n");
						if (res) res = strstr (res+1, "\n\n");
						if (res) res += 2; else res = str;
						printf ("%s%s", res, (res[strlen (res)-1]=='\n')?"":"\n");
						r_line_hist_add (str);
						free (str);
					}
				}
				r_socket_free (fd);
				return;
			}
			snprintf (uri, sizeof (uri), "http://%s:%s/%s",
				host, port, file);
			str = r_socket_http_get (uri, NULL, &len);
			if (str) {
				str[len] = 0;
				res = strstr (str, "\n\n");
				if (res) res = strstr (res+1, "\n\n");
				if (res) res += 2; else res = str;
				printf ("%s", res);
				free (str);
			} else eprintf ("HTTP connection has failed\n");
			// do not add connection. wtf
			return;
		}
		break;
	case RTR_PROT_RAP:
		if (!r_socket_connect_tcp (fd, host, port, timeout)) { //TODO: Use rap.ssl
			eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port);
			return;
		}
		eprintf ("Connected to %s at port %s\n", host, port);
		/* send */
		buf[0] = RTR_RAP_OPEN;
		buf[1] = 0;
		buf[2] = (ut8)(strlen (file)+1);
		memcpy (buf+3, file, buf[2]);
		r_socket_write(fd, buf, 3+buf[2]);
		/* read */
		eprintf ("waiting... "); fflush(stdout);
		r_socket_read (fd, (ut8*)buf, 5);
		r_mem_copyendian ((ut8 *)&i, (ut8*)buf+1, 4, core->assembler->big_endian);
		if (buf[0] != (char)(RTR_RAP_OPEN|RTR_RAP_REPLY) || i<= 0) {
			eprintf ("Error: Wrong reply\n");
			return;
		}
		eprintf ("ok\n");
		break;
	case RTR_PROT_TCP:
		if (!r_socket_connect_tcp (fd, host, port, timeout)) { //TODO: Use rap.ssl
			core->num->value = 1;
			eprintf("Error: Cannot connect to '%s' (%s)\n", host, port);
			return;
		}
		core->num->value = 0;
		eprintf ("Connected to: %s at port %s\n", host, port);
		break;
	case RTR_PROT_UDP:
		if (!r_socket_connect_udp (fd, host, port, timeout)) { //TODO: Use rap.ssl
			core->num->value = 1;
			eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port);
			return;
		}
		core->num->value = 0;
		eprintf("Connected to: %s at port %s\n", host, port);
		break;
	}

	ret = core->num->value;
	for (i = 0; i < RTR_MAX_HOSTS; i++)
		if (!rtr_host[i].fd) {
			rtr_host[i].proto = proto;
			memcpy (rtr_host[i].host, host, 512);
			rtr_host[i].port = r_num_get (core->num, port);
			memcpy (rtr_host[i].file, file, 1024);
			rtr_host[i].fd = fd;
			rtr_n = i;
			break;
		}
	core->num->value = ret;
	r_socket_free(fd);
	//r_core_rtr_list (core);
}
Example #17
0
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len,
		const char *fmt, int mode, const char *setval, char *ofield) {
	int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0;
	const char *argend;
	ut64 addr = 0, addr64 = 0, seeki = 0;;
	char *args = NULL, *bracket, tmp, last = 0;
	const char *arg = fmt;
	int viewflags = 0;
	char namefmt[8], *field = NULL;
	static int slide=0, oldslide=0;
	ut8 *buf;
	if (!fmt)
		return 0;
	argend = fmt+strlen (fmt);

	nexti = nargs = i = j = 0;

	if (len < 1)
		return 0;
	buf = malloc (len);
	if (!buf)
		return 0;
	memcpy (buf, b, len);
	endian = p->big_endian;

	if (ofield && ofield != MINUSONE) field = strdup (ofield);

	while (*arg && iswhitechar (*arg)) arg++;

	/* get times */
	otimes = times = atoi (arg);
	if (times > 0)
		while ((*arg>='0'&&*arg<='9')) arg++;

	bracket = strchr (arg,'{');
	if (bracket) {
		char *end = strchr (arg, '}');
		if (end == NULL) {
			eprintf ("No end bracket. Try pm {ecx}b @ esi\n");
			goto beach;
		}
		*end='\0';
		times = r_num_math (NULL, bracket+1);
		arg = end + 1;
	}

	if (*arg=='\0') {
		goto beach;
	}

	/* get args */
	args = strchr (arg, ' ');
	if (args) {
		int l=0, maxl = 0;
		argend = args;
		args = strdup (args+1);
		nargs = r_str_word_set0 (args);
		if (nargs == 0)
			R_FREE (args);
		for (i=0; i<nargs; i++) {
			const int len = strlen (r_str_word_get0 (args, i));
			if (len > maxl)
				maxl = len;
		}
		l++;
		snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR);
	}
#define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR)
#define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR))
	if (mode == R_PRINT_JSON && slide==0) p->printf("[");
	if (arg[0] == '0') {
		mode |= R_PRINT_UNIONMODE;
		arg++;
	} else {
		mode &= ~R_PRINT_UNIONMODE;
	}

	/* go format */
	i = 0;
	if (!times)
		otimes = times = 1;
	for (; times; times--) { // repeat N times
		const char * orig = arg;
		int first = 1;
		if (otimes>1) {
			if (mode & R_PRINT_JSON) {
				if (otimes > times) p->printf (",");
				p->printf ("[{\"index\":%d,\"offset\":%d},", otimes-times, seek+i);
			} else
				p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times);
		}
		arg = orig;
		for (idx=0; i<len && arg<argend && *arg; arg++) {
			int size, elem; /* size of the array, element of the array */
			char *fieldname = NULL, *fmtname = NULL, *oarg = NULL;
			if (mode & R_PRINT_UNIONMODE) {
				i = 0;
			}
			seeki = seek+i;
			addr = 0LL;
			invalid = 0;
			if (arg[0] == '[') {
				char *end = strchr (arg,']');
				if (end == NULL) {
					eprintf ("No end bracket.\n");
					goto beach;
				}
				*end = '\0';
				size = r_num_math (NULL, arg+1);
				arg = end + 1;
				*end = ']';
			} else {
				size = -1;
			}
			updateAddr (buf, i, endian, &addr, &addr64);

			tmp = *arg;

			if (args == NULL)
				mode |= R_PRINT_ISFIELD;
			if (mode & R_PRINT_MUSTSEE && otimes>1)
				p->printf ("   ");
			if (idx<nargs && tmp != 'e' && isptr == 0) {
				char *dot = NULL, *bracket = NULL;
				if (field)
					dot = strchr (field, '.');
				if (dot)
					*dot = '\0';
				oarg = fieldname = strdup(r_str_word_get0 (args, idx));
				if (ISSTRUCT || tmp=='E' || tmp=='B') {
					if (*fieldname == '(') {
						fmtname = fieldname+1;
						fieldname = strchr (fieldname, ')');
						if (fieldname) *fieldname++ = '\0';
						else {
							eprintf ("Missing closing parenthesis in format ')'\n");
							free (oarg);
							goto beach;
						}
					} else {
						eprintf ("Missing name (%s)\n", fieldname);
						free(oarg);
						goto beach;
					}
				}
				if (args == NULL || (field==NULL && ofield != MINUSONE)
						|| (field && !strncmp(field, fieldname, strlen(fieldname)))) {
					mode |= R_PRINT_ISFIELD;
				} else {
					mode &= ~R_PRINT_ISFIELD;
				}
				/* There we handle specific element in array */
				if (field != NULL && (bracket = strchr (field, '[')) != NULL && mode & R_PRINT_ISFIELD) {
					char *end = strchr (field, ']');
					if (end == NULL) {
						eprintf ("Missing closing bracket\n");
						goto beach;
					}
					*end = '\0';
					elem = r_num_math (NULL, bracket+1)+1; // +1 to handle 0 index easily
					for ( ; bracket < end; bracket++)
						*bracket = '\0';
					size += elem*ARRAYINDEX_COEF;
				} else {
					elem = -1;
				}
				idx++;
				if (MUSTSEE) {
					p->printf (namefmt, fieldname);
				}
			}

		feed_me_again:
			switch (isptr) {
			case 1:
				{
				nexti = i + (p->bits/8);
				i = 0;
				if(tmp == '?' )seeki = addr;
				memset (buf, '\0', len);
				if (MUSTSEE)
					p->printf ("(*0x%"PFMT64x") ", addr);
				if (addr == 0) isptr = NULLPTR;
				else isptr = PTRBACK;
				if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line,
						but len make it doesnt work... */
					p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4);
					updateAddr (buf, i, endian, &addr, &addr64);
				} else {
					eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n",
							addr, b, len);
					p->printf("\n");
					free (oarg);
					goto beach;
				}
				}
				break;
			case 2:
				// restore state after pointer seek
				i = nexti;
				seeki = seek+i;
				memcpy (buf, b, len);
				isptr = NOPTR;
				arg--;
				continue;
			}
			if (tmp == 0 && last != '*')
				break;

			/* skip chars */
			switch (tmp) {
			case '*': // next char is a pointer
				isptr = PTRSEEK;
				arg++;
				tmp = *arg; //last;
				goto feed_me_again;
			case '+': // toggle view flags
				viewflags = !viewflags;
				continue;
			case 'e': // tmp swap endian
				endian ^= 1;
				continue;
			case ':': // skip 4 bytes
				if (size == -1) i+=4;
				else
					while (size--) i+=4;
				continue;
			case '.': // skip 1 byte
				if (size == -1) i++;
				else
					i+=size;
				continue;
			case 'p': // pointer reference
				tmp = (p->bits == 64)? 'q': 'x';
				break;
			}
			/* flags */
			if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
				if (tmp == '?') {
					p->printf ("f %s.%s_", fmtname, fieldname);
				} else if (tmp == 'E') {
					p->printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki);
				} else if (slide/STRUCTFLAG>0 && idx==1) {
					p->printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki);
				} else p->printf ("f %s=0x%08"PFMT64x"\n", fieldname , seeki);
			}
			/* json */
			if (mode & R_PRINT_JSON) {
				if (oldslide<=slide) {
					if (!first)
						p->printf (",");
					else
						first = 0;
				} else if(oldslide!=0) {
					p->printf ("]},");
				}
				p->printf ("{\"name\":\"%s\",\"type\":\"", fieldname);
				if (ISSTRUCT) {
					p->printf ("%s", fmtname);
				} else {
					p->printf ("%c", tmp);
				}
				if (isptr) p->printf ("*");
				p->printf ("\",\"offset\":%d,\"value\":",(isptr)?(seek+nexti-(p->bits/8)):seek+i);
			}

			if (isptr == NULLPTR) {
				if (MUSTSEEJSON)
					p->printf ("\"NULL\"}", tmp, seek+i);
				else if (MUSTSEE)
					p->printf ("NULL\n");
				isptr = PTRBACK;
			} else
			/* format chars */
			switch (tmp) {
			case 't':
				r_print_format_time(p, endian, mode, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'q':
				r_print_format_quadword(p, endian, mode, setval, seeki, buf, i, size);
				i += (size==-1) ? 8 : 8*size;
				break;
			case 'b':
				r_print_format_byte(p, endian, mode, setval, seeki, buf, i, size);
				i+= (size==-1) ? 1 : size;
				break;
			case 'c':
				r_print_format_char (p, endian, mode,
					setval, seeki, buf, i, size);
				i+= (size==-1) ? 1 : size;
				break;
			case 'X':
				size = r_print_format_hexpairs (p, endian, mode,
					setval, seeki, buf, size);
				i += size;
				break;
			case 'T':
				if(r_print_format_10bytes(p, mode,
					setval, seeki, addr, buf) == 0)
					i += (size==-1) ? 4 : 4*size;
				break;
			case 'f':
				r_print_format_float(p, endian, mode, setval, seeki, buf, i, size);
				i += (size==-1) ? 4 : 4*size;
				break;
			case 'i':
			case 'd':
				r_print_format_hex(p, endian, mode, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'D':
				if (size>0) p->printf ("Size not yet implemented\n");
				if (p->disasm && p->user)
					i += p->disasm (p->user, seeki);
				break;
			case 'o':
				r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'x':
				r_print_format_hexflag(p, endian, mode, setval, seeki, buf, i, size);
				i+= (size==-1) ? 4 : 4*size;
				break;
			case 'w':
				r_print_format_word(p, endian, mode, setval, seeki, buf, i, size);
				i+= (size==-1) ? 2 : 2*size;
				break;
			case 'z': // zero terminated string
				r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size);
				if (size == -1)
					i+=strlen((char*)buf+i)+1;
				else
					while (size--) i++;
				break;
			case 'Z': // zero terminated wide string
				r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size);
				if (size == -1)
					i+=r_wstr_clen((char*)(buf+seeki))*2+2;
				else
					while (size--) i+=2;
				break;
			case 's':
				if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0)
					i += (size==-1) ? 4 : 4*size;
				break;
			case 'S':
				if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0)
					i += (size==-1) ? 8 : 8*size;
				break;
			case 'B': // resolve bitfield
				if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF;
				r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size);
				i+=(size==-1)?1:size;
				break;
			case 'E': // resolve enum
				if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF;
				r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size);
				i+=(size==-1)?1:size;
				break;
			case '?':
				{
				int s = 0;
				char *nxtfield = NULL;
				if (size >= ARRAYINDEX_COEF) {
					elem = size/ARRAYINDEX_COEF-1;
					size %= ARRAYINDEX_COEF;
				}
				if (!(mode & R_PRINT_ISFIELD)) nxtfield = MINUSONE;
				else if (field) nxtfield = strchr (ofield, '.');
				if (nxtfield != MINUSONE && nxtfield != NULL) nxtfield++;

				if (MUSTSEE)
					p->printf ("\n");
				if (MUSTSEEJSON) {
					if (isptr)
						p->printf ("%d},", seeki);
					else
						p->printf ("[");
				}
				if (mode & R_PRINT_SEEFLAGS) slide+=STRUCTFLAG;
				oldslide = slide;
				slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
				if (size == -1) {
					s = r_print_format_struct (p, seeki,
						buf+i, len-i, fmtname, slide,
						mode, setval, nxtfield);
					i+= (isptr) ? 4 : s;
				} else {
					p->printf ("[\n");
					while (size--) {
						if (elem == -1 || elem == 0) {
							mode |= R_PRINT_MUSTSEE;
							if (elem == 0) elem = -2;
						} else {
							mode &= ~R_PRINT_MUSTSEE;
						}
						s = r_print_format_struct (p, seek+i,
							buf+i, len-i, fmtname, slide, mode, setval, nxtfield);
						if (size != 0 && elem == -1)
							p->printf (",\n");
						if (elem > -1) elem--;
						i+= (isptr) ? 4 : s;
					}
					if (MUSTSEEJSON) p->printf ("]]}");
					else p->printf ("]");
				}
				oldslide = slide;
				slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
				if (mode & R_PRINT_SEEFLAGS) {
					oldslide = slide;
					slide-=STRUCTFLAG;
				}
				break;
				}
			default:
				/* ignore unknown chars */
				invalid = 1;
				break;
			}
			if (viewflags && p->offname) {
				const char *s = p->offname (p->user, seeki);
				if (s)
					p->printf ("@(%s)", s);
				s = p->offname (p->user, addr);
				if (s)
					p->printf ("*(%s)", s);
			}
			if (tmp != 'D' && !invalid && fmtname==NULL && MUSTSEE)
				p->printf ("\n");
			last = tmp;
			if (oarg)
				free (oarg);
		}
		if (otimes>1) {
			if (MUSTSEEJSON) p->printf ("]");
			else p->printf ("}\n");
		}
		arg = orig;
		oldslide = 0;
	}
	if (mode & R_PRINT_JSON && slide==0) p->printf("]");
beach:
	free (buf);
	free (field);
	if (args)
		free (args);
	return i;
}
Example #18
0
/* hack from print */
R_API int r_print_format_length (const char *fmt) {
	int nargs, i, j, idx, times, endian;
	char *args, *bracket, tmp, last = 0;
	const char *arg = fmt;
	const char *argend = arg+strlen (fmt);
	char namefmt[8];
	int viewflags = 0;
	nargs = endian = i = j = 0;

	while (*arg && iswhitechar (*arg)) arg++;
	/* get times */
	times = atoi (arg);
	if (times > 0)
		while ((*arg>='0'&&*arg<='9')) arg++;
	bracket = strchr (arg,'{');
	if (bracket) {
		char *end = strchr (arg,'}');
		if (end == NULL) {
			eprintf ("No end bracket. Try pm {ecx}b @ esi\n");
			return 0;
		}
		*end='\0';
		times = r_num_math (NULL, bracket+1);
		arg = end + 1;
	}

	if (*arg=='\0')
		return 0;

	/* get args */
	args = strchr (arg, ' ');
	if (args) {
		int l=0, maxl = 0;
		argend = args;
		args = strdup (args+1);
		nargs = r_str_word_set0 (args+1);
		if (nargs == 0)
			R_FREE (args);
		for (i=0; i<nargs; i++) {
			int len = strlen (r_str_word_get0 (args+1, i));
			if (len>maxl) maxl = len;
		}
		l++;
		snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl);
	}

	/* go format */
	i = 0;
	if (!times) times = 1;
	for (; times; times--) { // repeat N times
		const char * orig = arg;
		idx = 0;
		arg = orig;
		for (idx=0; arg<argend && *arg; idx++, arg++) {
			tmp = *arg;
		feed_me_again:
			if (tmp == 0 && last != '*')
				break;
			/* skip chars */
			switch (tmp) {
			case '*':
				if (i<=0) break;
				tmp = last;
				arg--;
				idx--;
				goto feed_me_again;
			case '+':
				idx--;
				viewflags = !viewflags;
				continue;
			case 'e': // tmp swap endian
				idx--;
				endian ^= 1;
				continue;
			case '.': // skip char
				i++;
				idx--;
				continue;
			case 'p':
				tmp = (sizeof (void*)==8)? 'q': 'x';
				break;
			case '?': // help
				idx--;
				return 0;
			}
			switch (tmp) {
			case 'e': i += 8; break;
			case 'q': i += 8; break;
			case 'b': i++; break;
			case 'c': i++; break;
			case 'B': i += 4; break;
			case 'i': i += 4; break;
			case 'd': i += 4; break;
			case 'x': i += 4; break;
			case 'w':
			case '1': i+=2; break;
			case 'z': // XXX unsupported
			case 'Z': // zero terminated wide string
				break;
			case 's': i += 4; break; // S for 8?
			case 'S': i += 8; break; // S for 8?
			default:
				/* ignore unknown chars */
				break;
			}
			last = tmp;
		}
		arg = orig;
		idx = 0;
	}
//	free((void *)&args);
	return i;
}