Avoid array subscript type issues (#18295)

Cast char to unsigned char for standard reasons and security purposes.

Fixes build issues on NetBSD.
This commit is contained in:
Kamil Rytarowski 2021-01-26 13:08:58 +01:00 committed by GitHub
parent 73bb7fdd66
commit 9d761f6a88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 70 additions and 71 deletions

View File

@ -651,7 +651,7 @@ static int riscv_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le
op->dst->delta = (st64)r_num_get (NULL, args.arg[0]);
op->dst->reg = r_reg_get (anal->reg, args.arg[1], -1);
j = 2;
} else if (isdigit (args.arg[j][0])) {
} else if (isdigit ((unsigned char)args.arg[j][0])) {
op->dst->imm = r_num_get (NULL, args.arg[0]);
} else {
op->dst->reg = r_reg_get (anal->reg, args.arg[0], -1);
@ -663,7 +663,7 @@ static int riscv_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le
op->src[i]->delta = (st64)r_num_get (NULL, args.arg[j]);
op->src[i]->reg = r_reg_get (anal->reg, args.arg[j + 1], -1);
j++;
} else if (isalpha (args.arg[j][0])) {
} else if (isalpha ((unsigned char)args.arg[j][0])) {
op->src[i]->reg = r_reg_get (anal->reg, args.arg[j], -1);
} else {
op->src[i]->imm = r_num_get (NULL, args.arg[j]);

View File

@ -352,7 +352,7 @@ R_API const char *r_anal_function_get_var_reg_at(RAnalFunction *fcn, st64 delta,
}
R_API bool r_anal_var_check_name(const char *name) {
return !isdigit (*name) && strcspn (name, "., =/");
return !isdigit ((unsigned char)*name) && strcspn (name, "., =/");
}
R_API bool r_anal_var_rename(RAnalVar *var, const char *new_name, bool verbose) {

View File

@ -239,15 +239,15 @@ static int str_iwhitecasecmp(char const*a, char const*b) {
if (!*a || !*b) {
break;
}
if (isspace (*a)) {
if (isspace ((unsigned char)*a)) {
a += 1;
continue;
}
if (isspace (*b)) {
if (isspace ((unsigned char)*b)) {
b += 1;
continue;
}
if (tolower (*a) == tolower (*b)) {
if (tolower ((unsigned char)*a) == tolower ((unsigned char)*b)) {
a += 1;
b += 1;
continue;
@ -277,14 +277,14 @@ static bool pattern_match(char const*str, char const*pattern) {
}
while (pattern[ti] != '\0') {
while (isspace (str[si]) && !isspace (pattern[ti])) {
while (isspace ((unsigned char)str[si]) && !isspace ((unsigned char)pattern[ti])) {
si += 1;
}
if (isspace (pattern[ti])) {
if (isspace ((unsigned char)pattern[ti])) {
ti += 1;
continue;
}
if (tolower (pattern[ti]) == tolower (str[si])) {
if (tolower ((unsigned char)pattern[ti]) == tolower ((unsigned char)str[si])) {
si += 1;
ti += 1;
}
@ -326,13 +326,13 @@ static bool is_indirect_reg(char const*str)
if (str[0] == '@' ) {
return r_str_ansi_nlen (str, 4) == 3
&& tolower (str[1]) == 'r'
&& tolower ((unsigned char)str[1]) == 'r'
&& (str[2] == '0' || str[2] == '1');
}
if (str[0] == '[' ) {
return r_str_ansi_nlen (str, 5) == 4
&& tolower (str[1]) == 'r'
&& tolower ((unsigned char)str[1]) == 'r'
&& (str[2] == '0' || str[2] == '1')
&& str[3] == ']';
}
@ -345,7 +345,7 @@ static bool is_indirect_reg(char const*str)
*/
static bool is_reg(char const*str)
{
return str && tolower (str[0]) == 'r' && r_str_ansi_nlen (str, 3) == 2
return str && tolower ((unsigned char)str[0]) == 'r' && r_str_ansi_nlen (str, 3) == 2
&& '0' <= str[1] && str[1] <= '7';
}

View File

@ -1067,7 +1067,7 @@ static bool parseOperands(char* str, ArmOp *op) {
if (*token == '#') {
token++;
}
if (!*token || !isdigit(*token)) {
if (!*token || !isdigit((unsigned char)*token)) {
return false;
}
op->operands[operand].shift_amount = r_num_math (NULL, token);
@ -1091,7 +1091,7 @@ static bool parseOperands(char* str, ArmOp *op) {
present = true;
++token;
}
if (!*token || !isdigit(*token)) {
if (!*token || !isdigit((unsigned char)*token)) {
if (present) {
return false;
}

View File

@ -824,7 +824,7 @@ R_API RAsmCode *r_asm_massemble(RAsm *a, const char *assembly) {
if (cptr && ptr && cptr < ptr) {
likely_comment = false;
for (cptr += 1; cptr < ptr ; cptr += 1) {
if ( ! isspace ( *cptr)) {
if ( ! isspace ((unsigned char) *cptr)) {
likely_comment = true;
break;
}

View File

@ -51,7 +51,7 @@ static int assemble(RAsm *a, RAsmOp *op, const char *str) {
goto beach;
}
strncpy (mnemonic, str, n);
while (*++p && isspace (*p));
while (*++p && isspace ((unsigned char)*p));
n = strcspn (p, ", "); // next separator
if (n > sizeof (arg0) - 1) {
goto beach;
@ -63,7 +63,7 @@ static int assemble(RAsm *a, RAsmOp *op, const char *str) {
while (*++p) {
if (*p == ',') {
comma++;
} else if (!isspace(*p)) {
} else if (!isspace((unsigned char)*p)) {
break;
}
}

View File

@ -4613,7 +4613,7 @@ static bool is_mm_register(const char *token) {
if (parn) {
token++;
}
if (isdigit (token[2]) && !isdigit(token[3])) {
if (isdigit ((unsigned char)token[2]) && !isdigit((unsigned char)token[3])) {
int n = token[2];
if (n >= '0' && n <= '7') {
if (parn) {
@ -4634,7 +4634,7 @@ static bool is_st_register(const char *token) {
if (parn) {
token++;
}
if (isdigit (token[2]) && !isdigit(token[3])) {
if (isdigit ((unsigned char)token[2]) && !isdigit((unsigned char)token[3])) {
int n = token[2];
if (n >= '0' && n <= '7') {
if (parn) {

View File

@ -226,7 +226,7 @@ static int get_template_params(const char *sym, size_t *amount_of_read_chars, ch
}
sym += ret + 1;
SDataType data_type;
if (isdigit (*sym)) {
if (isdigit ((unsigned char)*sym)) {
err = parse_data_type (sym, &data_type, &ret);
*str_type_code = r_str_newf ("&%s %s%s", data_type.left, str.type_str, data_type.right);
free (data_type.left);
@ -1921,7 +1921,7 @@ static EDemanglerErr parse_microsoft_mangled_name(const char *sym, char **demang
curr_pos++;
}
if (isdigit (*curr_pos)) {
if (isdigit ((unsigned char)*curr_pos)) {
err = parse_data_type (curr_pos, &data_type, &len);
if (err != eDemanglerErrOK) {
goto parse_microsoft_mangled_name_err;
@ -1935,7 +1935,7 @@ static EDemanglerErr parse_microsoft_mangled_name(const char *sym, char **demang
*demangled_name = r_str_append (*demangled_name, data_type.right);
free (data_type.left);
free (data_type.right);
} else if (isalpha (*curr_pos)) {
} else if (isalpha ((unsigned char)*curr_pos)) {
err = parse_function (curr_pos, &type_code_str, demangled_name, &len);
curr_pos += len;
} else {

View File

@ -163,7 +163,7 @@ static bool is_valid_guid(const char *guid) {
}
size_t i;
for (i = 0; guid[i]; i++) {
if (!isxdigit (guid[i])) {
if (!isxdigit ((unsigned char)guid[i])) {
return false;
}
}

View File

@ -414,9 +414,9 @@ R_API int r_cons_get_cur_line(void) {
if (isatty (fileno (stdin))) {
if (write (1, R_CONS_GET_CURSOR_POSITION, sizeof (R_CONS_GET_CURSOR_POSITION)) != -1) {
if (read (0, buf, sizeof (buf)) != sizeof (buf)) {
if (isdigit (buf[2])) {
if (isdigit ((unsigned char)buf[2])) {
curline = (buf[2] - '0');
} if (isdigit (buf[3])) {
} if (isdigit ((unsigned char)buf[3])) {
curline = curline * 10 + (buf[3] - '0');
}
}

View File

@ -1412,7 +1412,7 @@ static void load_table_asciiart(RCore *core, RTable *t, RList *lines) {
free (ss);
continue;
}
if (isdigit (*ss)) {
if (isdigit ((unsigned char)*ss)) {
int col = r_list_length (items);
RTableColumn *c = r_list_get_n (t->cols, col);
if (c) {
@ -5066,7 +5066,7 @@ static void replace_whitespaces(char *s, char ch) {
s++;
}
}
if (isspace (*s)) {
if (isspace ((unsigned char)*s)) {
*s = ch;
}
s++;

View File

@ -8053,7 +8053,7 @@ static void cmd_anal_hint(RCore *core, const char *input) {
case 'i': // "ahi"
if (input[1] == '?') {
r_core_cmd_help (core, help_msg_ahi);
} else if (isdigit (input[1])) {
} else if (isdigit ((unsigned char)input[1])) {
r_anal_hint_set_nword (core->anal, core->offset, input[1] - '0');
input++;
} else if (input[1] == '-') { // "ahi-"

View File

@ -443,7 +443,7 @@ static ut64 numvar_instruction_backward(RCore *core, const char *input) {
// N forward instructions
int i, ret;
int n = 1;
if (isdigit (input[0])) {
if (isdigit ((unsigned char)input[0])) {
n = atoi (input);
} else if (input[0] == '{') {
n = atoi (input + 1);

View File

@ -4215,7 +4215,7 @@ static int mymemwrite2(RAnalEsil *esil, ut64 addr, const ut8 *buf, int len) {
static char *ssa_get(RAnalEsil *esil, const char *reg) {
RDisasmState *ds = esil->user;
if (isdigit (*reg)) {
if (isdigit ((unsigned char)*reg)) {
return strdup (reg);
}
if (!ds->ssa) {
@ -4234,7 +4234,7 @@ static void ssa_set(RAnalEsil *esil, const char *reg) {
static int myregread(RAnalEsil *esil, const char *name, ut64 *res, int *size) {
RDisasmState *ds = esil->user;
if (ds && ds->show_emu_ssa) {
if (!isdigit (*name)) {
if (!isdigit ((unsigned char)*name)) {
char *r = ssa_get (esil, name);
ds_comment_esil (ds, true, false, "<%s", r);
free (r);

View File

@ -25,7 +25,7 @@ static bool is_valid_project_name(const char *name) {
case '-':
continue;
}
if (isalpha (name[i])) {
if (isalpha ((unsigned char)name[i])) {
continue;
}
if (IS_DIGIT (name[i])) {

View File

@ -3806,9 +3806,9 @@ R_API void r_core_visual_title(RCore *core, int color) {
int i;
for(i=0;i<6;i++) {
if (core->printidx == i) {
pm[i + 1] = toupper(pm[i + 1]);
pm[i + 1] = toupper((unsigned char)pm[i + 1]);
} else {
pm[i + 1] = tolower(pm[i + 1]);
pm[i + 1] = tolower((unsigned char)pm[i + 1]);
}
}
if (core->print->cur_enabled) {

View File

@ -214,7 +214,7 @@ static TAG_CALLBACK(spp_r2_ifeq) {
static TAG_CALLBACK(spp_r2_hex) {
size_t i;
for (i = 0; buf[i]; i++) {
if (isdigit (buf[i])) {
if (isdigit ((unsigned char)buf[i])) {
int ch, b = buf[i + 2];
buf[i + 2] = '\0';
sscanf (buf + i, "%02x", &ch);

View File

@ -588,7 +588,7 @@ dotherax:
return true;
}
if (str[0] == '0' && (tolower (str[1]) == 'x')) {
if (str[0] == '0' && (tolower ((unsigned char)str[1]) == 'x')) {
out_mode = (flags & 32)? '0': 'I';
} else if (r_str_startswith (str, "b")) {
out_mode = 'B';

View File

@ -209,7 +209,7 @@ R_API RSearchKeyword *r_search_keyword_new_regexp (const char *str, const char *
for (start = i; str[i]; i++) {
if (str[i] == '/' && str[i - 1] != '\\') {
break;
} else if (str[i - 1] == '\\' && isalpha (str[i])) {
} else if (str[i - 1] == '\\' && isalpha ((unsigned char)str[i])) {
specials++;
}
}

View File

@ -2025,7 +2025,7 @@ static bool issymbol(char c) {
static bool check_arg_name(RPrint *print, char *p, ut64 func_addr) {
if (func_addr && print->exists_var) {
int z;
for (z = 0; p[z] && (isalpha (p[z]) || isdigit (p[z]) || p[z] == '_'); z++) {
for (z = 0; p[z] && (isalpha ((unsigned char)p[z]) || isdigit ((unsigned char)p[z]) || p[z] == '_'); z++) {
;
}
char tmp = p[z];

View File

@ -239,7 +239,7 @@ R_API ut64 r_num_get(RNum *num, const char *str) {
}
} else if (!strncmp (str, "0xf..", 5) || !strncmp (str, "0xF..", 5)) {
ret = r_num_tailff (num, str + 5);
} else if (str[0] == '0' && tolower (str[1]) == 'x') {
} else if (str[0] == '0' && tolower ((unsigned char)str[1]) == 'x') {
const char *lodash = strchr (str + 2, '_');
if (lodash) {
// Support 0x1000_f000_4000

View File

@ -1607,7 +1607,7 @@ int gdbr_send_qRcmd(libgdbr_t *g, const char *cmd, PrintfCallback cb_printf) {
goto end;
}
if (g->data_len == 3 && g->data[0] == 'E'
&& isxdigit (g->data[1]) && isxdigit (g->data[2])) {
&& isxdigit ((unsigned char)g->data[1]) && isxdigit ((unsigned char)g->data[2])) {
ret = -1;
goto end;
}
@ -1956,7 +1956,7 @@ ut64 gdbr_get_baddr(libgdbr_t *g) {
}
if (r_str_startswith (g->data, "TextSeg=")) {
ptr = g->data + strlen ("TextSeg=");
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
goto end;
}
off = strtoull (ptr, NULL, 16);
@ -1969,7 +1969,7 @@ ut64 gdbr_get_baddr(libgdbr_t *g) {
ptr++;
if (*ptr && r_str_startswith (ptr, "DataSeg=")) {
ptr += strlen ("DataSeg=");
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
goto end;
}
off = strtoull (ptr, NULL, 16);
@ -1983,7 +1983,7 @@ ut64 gdbr_get_baddr(libgdbr_t *g) {
goto end;
}
ptr = g->data + strlen ("Text=");
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
goto end;
}
off = strtoull (ptr, NULL, 16);
@ -1995,7 +1995,7 @@ ut64 gdbr_get_baddr(libgdbr_t *g) {
goto end;
}
ptr += strlen (";Data=");
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
min = UINT64_MAX;
goto end;
}
@ -2009,7 +2009,7 @@ ut64 gdbr_get_baddr(libgdbr_t *g) {
ptr++;
if (r_str_startswith (ptr, "Bss=")) {
ptr += strlen ("Bss=");
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
goto end;
}
off = strtoull (ptr, NULL, 16);

View File

@ -131,7 +131,7 @@ int handle_attach(libgdbr_t *g) {
int handle_vFile_open(libgdbr_t *g) {
if (g->data_len < 2 || g->data[0] != 'F' || g->data[1] == '-'
|| !isxdigit (g->data[1])) {
|| !isxdigit ((unsigned char)g->data[1])) {
send_ack (g);
return -1;
}
@ -155,7 +155,7 @@ int handle_vFile_pread(libgdbr_t *g, ut8 *buf) {
if (g->data[1] == '-') {
return 0;
}
if (!isxdigit (g->data[1])) {
if (!isxdigit ((unsigned char)g->data[1])) {
return -1;
}
if (sscanf (g->data, "F%x;", &len) != 1) {
@ -177,7 +177,7 @@ int handle_vFile_pread(libgdbr_t *g, ut8 *buf) {
int handle_vFile_close(libgdbr_t *g) {
if (g->data_len < 2 || g->data[0] != 'F' || g->data[1] == '-'
|| !isxdigit (g->data[1])) {
|| !isxdigit ((unsigned char)g->data[1])) {
send_ack (g);
return -1;
}
@ -201,7 +201,7 @@ static int stop_reason_exit(libgdbr_t *g) {
g->stop_reason.is_valid = true;
return 0;
}
if (!isxdigit (g->data[1])) {
if (!isxdigit ((unsigned char)g->data[1])) {
eprintf ("Message from remote: %s\n", g->data);
return -1;
}
@ -229,7 +229,7 @@ static int stop_reason_terminated(libgdbr_t *g) {
g->stop_reason.is_valid = true;
return 0;
}
if (!isxdigit (g->data[1])) {
if (!isxdigit ((unsigned char)g->data[1])) {
eprintf ("Message from remote: %s\n", g->data);
return -1;
}
@ -297,7 +297,7 @@ int handle_stop_reason(libgdbr_t *g) {
continue;
}
ptr2++;
if (!isxdigit (*ptr2)) {
if (!isxdigit ((unsigned char)*ptr2)) {
continue;
}
g->stop_reason.core = (int) strtol (ptr2, NULL, 16);
@ -311,7 +311,7 @@ int handle_stop_reason(libgdbr_t *g) {
continue;
}
ptr2++;
if (!isxdigit (*ptr2)) {
if (!isxdigit ((unsigned char)*ptr2)) {
continue;
}
g->stop_reason.watchpoint.addr = strtoll (ptr2, NULL, 16);
@ -411,7 +411,7 @@ int handle_lldb_read_reg(libgdbr_t *g) {
return -1;
}
while (ptr) {
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
// This is not a reg value. Skip
ptr = strtok (NULL, ";");
continue;

View File

@ -513,7 +513,7 @@ static void _write_flag_bits(char *buf, const gdbr_xml_flags_t *flags) {
// To avoid duplicates. This skips flags if first char is same. i.e.
// for x86_64, it will skip VIF because VM already occurred. This is
// same as default reg-profiles in r2
c = tolower (flags->fields[i].name[0]) - 'a';
c = tolower ((unsigned char)flags->fields[i].name[0]) - 'a';
if (fc[c]) {
continue;
}
@ -647,7 +647,7 @@ static RList *_extract_flags(char *flagstr) {
goto exit_err;
}
tmp1 += 7;
if (!isdigit (*tmp1)) {
if (!isdigit ((unsigned char)*tmp1)) {
goto exit_err;
}
tmpflag->fields[num_fields].bit_num = (ut32) strtoul (tmp1, NULL, 10);
@ -656,7 +656,7 @@ static RList *_extract_flags(char *flagstr) {
goto exit_err;
}
tmp1 += 5;
if (!isdigit (*tmp1)) {
if (!isdigit ((unsigned char)*tmp1)) {
goto exit_err;
}
tmpflag->fields[num_fields].sz = (ut32) strtoul (tmp1, NULL, 10) + 1;
@ -799,7 +799,7 @@ static RList *_extract_regs(char *regstr, RList *flags, char *pc_alias) {
goto exit_err;
}
tmp1 += 9;
if (!isdigit (*tmp1)) {
if (!isdigit ((unsigned char)*tmp1)) {
goto exit_err;
}
regsize = strtoul (tmp1, NULL, 10);
@ -807,7 +807,7 @@ static RList *_extract_regs(char *regstr, RList *flags, char *pc_alias) {
regnum = UINT32_MAX;
if ((tmp1 = strstr (regstr, "regnum="))) {
tmp1 += 8;
if (!isdigit (*tmp1)) {
if (!isdigit ((unsigned char)*tmp1)) {
goto exit_err;
}
regnum = strtoul (tmp1, NULL, 10);

View File

@ -290,7 +290,7 @@ static int _server_handle_Hg(libgdbr_t *g, gdbr_server_cmd_cb cmd_cb, void *core
if (send_ack (g) < 0) {
return -1;
}
if (g->data_len <= 2 || isalpha (g->data[2])) {
if (g->data_len <= 2 || isalpha ((unsigned char)g->data[2])) {
return send_msg (g, "E01");
}
// Hg-1 = "all threads", Hg0 = "pick any thread"
@ -315,7 +315,7 @@ static int _server_handle_Hc(libgdbr_t *g, gdbr_server_cmd_cb cmd_cb, void *core
if (send_ack (g) < 0) {
return -1;
}
if (g->data_len <= 2 || isalpha (g->data[2])) {
if (g->data_len <= 2 || isalpha ((unsigned char)g->data[2])) {
return send_msg (g, "E01");
}
// Hc-1 = "all threads", Hc0 = "pick any thread"
@ -420,7 +420,7 @@ static int _server_handle_p(libgdbr_t *g, gdbr_server_cmd_cb cmd_cb, void *core_
if (send_ack (g) < 0) {
return -1;
}
if (!isxdigit (g->data[1])) {
if (!isxdigit ((unsigned char)g->data[1])) {
return send_msg (g, "E01");
}
regnum = strtol (g->data + 1, NULL, 16);
@ -448,11 +448,11 @@ static int _server_handle_P(libgdbr_t *g, gdbr_server_cmd_cb cmd_cb, void *core_
if (send_ack (g) < 0) {
return -1;
}
if (!isxdigit (g->data[1]) || !(ptr = strchr (g->data, '='))) {
if (!isxdigit ((unsigned char)g->data[1]) || !(ptr = strchr (g->data, '='))) {
return send_msg (g, "E01");
}
ptr++;
if (!isxdigit (*ptr)) {
if (!isxdigit ((unsigned char)*ptr)) {
return send_msg (g, "E01");
}
regnum = strtol (g->data + 1, NULL, 16);

View File

@ -168,7 +168,7 @@ int read_thread_id(const char *src, int *pid, int *tid, bool multiprocess) {
}
return -1;
}
if (!isxdigit (*src)) {
if (!isxdigit ((unsigned char)*src)) {
return -1;
}
if (r_str_startswith (ptr1, "-1")) {
@ -176,7 +176,7 @@ int read_thread_id(const char *src, int *pid, int *tid, bool multiprocess) {
*tid = -1;
return 0;
}
if (!isxdigit (*ptr1)) {
if (!isxdigit ((unsigned char)*ptr1)) {
return -1;
}
*pid = (int) strtol (src, NULL, 16);
@ -187,7 +187,7 @@ int read_thread_id(const char *src, int *pid, int *tid, bool multiprocess) {
*tid = -1;
return 0;
}
if (!isxdigit (*src)) {
if (!isxdigit ((unsigned char)*src)) {
return -1;
}
*pid = *tid = (int) strtol (src, NULL, 16);

View File

@ -2226,7 +2226,7 @@ mpc_val_t *mpcf_float(mpc_val_t *x) {
mpc_val_t *mpcf_strtriml(mpc_val_t *x) {
char *s = x;
while (isspace(*s)) {
while (isspace((unsigned char)*s)) {
memmove(s, s+1, strlen(s));
}
return s;
@ -2235,7 +2235,7 @@ mpc_val_t *mpcf_strtriml(mpc_val_t *x) {
mpc_val_t *mpcf_strtrimr(mpc_val_t *x) {
char *s = x;
size_t l = strlen(s);
while (isspace(s[l-1])) {
while (isspace((unsigned char)s[l-1])) {
s[l-1] = '\0'; l--;
}
return s;
@ -3614,4 +3614,3 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) {
void mpc_optimise(mpc_parser_t *p) {
mpc_optimise_unretained(p, 1);
}

View File

@ -753,11 +753,11 @@ next_quote:
*json++ = 0;
ok = sdb_json_set (s, cmd, json, val, 0);
} else {
while (*val && isspace (*val)) {
while (*val && isspace ((unsigned char)*val)) {
val++;
}
int i = strlen (cmd) - 1;
while (i >= 0 && isspace (cmd[i])) {
while (i >= 0 && isspace ((unsigned char)cmd[i])) {
cmd[i] = '\0';
i--;
}