SCP: Add substring and string substitution to environment variable expansion
This commit is contained in:
parent
e2e17e1594
commit
82ea9c59ca
1 changed files with 143 additions and 1 deletions
144
scp.c
144
scp.c
|
@ -1536,7 +1536,27 @@ static const char simh_help[] =
|
||||||
"+then looked up as an environment variable. If found it the value is\n"
|
"+then looked up as an environment variable. If found it the value is\n"
|
||||||
"+supstituted for the original string before expanding everything else. If\n"
|
"+supstituted for the original string before expanding everything else. If\n"
|
||||||
"+it is not found, then the original beginning token on the line is left\n"
|
"+it is not found, then the original beginning token on the line is left\n"
|
||||||
"+untouched.\n"
|
"+untouched.\n\n"
|
||||||
|
"+Environment variable string substitution:\n\n"
|
||||||
|
"++%%XYZ:str1=str2%%\n\n"
|
||||||
|
"+would expand the XYZ environment variable, substituting each occurrence\n"
|
||||||
|
"+of \"str1\" in the expanded result with \"str2\". \"str2\" can be the empty\n"
|
||||||
|
"+string to effectively delete all occurrences of \"str1\" from the expanded\n"
|
||||||
|
"+output. \"str1\" can begin with an asterisk, in which case it will match\n"
|
||||||
|
"+everything from the beginning of the expanded output to the first\n"
|
||||||
|
"+occurrence of the remaining portion of str1.\n\n"
|
||||||
|
"+May also specify substrings for an expansion.\n\n"
|
||||||
|
"++%%XYZ:~10,5%%\n\n"
|
||||||
|
"+would expand the XYZ environment variable, and then use only the 5\n"
|
||||||
|
"+characters that begin at the 11th (offset 10) character of the expanded\n"
|
||||||
|
"+result. If the length is not specified, then it defaults to the\n"
|
||||||
|
"+remainder of the variable value. If either number (offset or length) is\n"
|
||||||
|
"+negative, then the number used is the length of the environment variable\n"
|
||||||
|
"+value added to the offset or length specified.\n\n"
|
||||||
|
"++%%XYZ:~-10%%\n\n"
|
||||||
|
"+would extract the last 10 characters of the XYZ variable.\n\n"
|
||||||
|
"++%%XYZ:~0,-2%%\n\n"
|
||||||
|
"+would extract all but the last 2 characters of the XYZ variable.\n"
|
||||||
#define HLP_GOTO "*Commands Executing_Command_Files GOTO"
|
#define HLP_GOTO "*Commands Executing_Command_Files GOTO"
|
||||||
"3GOTO\n"
|
"3GOTO\n"
|
||||||
" Commands in a command file execute in sequence until either an error\n"
|
" Commands in a command file execute in sequence until either an error\n"
|
||||||
|
@ -3619,11 +3639,127 @@ if (ap) { /* environment variable found? */
|
||||||
return ap;
|
return ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Environment variable substitution:
|
||||||
|
|
||||||
|
%XYZ:str1=str2%
|
||||||
|
|
||||||
|
would expand the XYZ environment variable, substituting each occurrence
|
||||||
|
of "str1" in the expanded result with "str2". "str2" can be the empty
|
||||||
|
string to effectively delete all occurrences of "str1" from the expanded
|
||||||
|
output. "str1" can begin with an asterisk, in which case it will match
|
||||||
|
everything from the beginning of the expanded output to the first
|
||||||
|
occurrence of the remaining portion of str1.
|
||||||
|
|
||||||
|
May also specify substrings for an expansion.
|
||||||
|
|
||||||
|
%XYZ:~10,5%
|
||||||
|
|
||||||
|
would expand the XYZ environment variable, and then use only the 5
|
||||||
|
characters that begin at the 11th (offset 10) character of the expanded
|
||||||
|
result. If the length is not specified, then it defaults to the
|
||||||
|
remainder of the variable value. If either number (offset or length) is
|
||||||
|
negative, then the number used is the length of the environment variable
|
||||||
|
value added to the offset or length specified.
|
||||||
|
|
||||||
|
%XYZ:~-10%
|
||||||
|
|
||||||
|
would extract the last 10 characters of the XYZ variable.
|
||||||
|
|
||||||
|
%XYZ:~0,-2%
|
||||||
|
|
||||||
|
would extract all but the last 2 characters of the XYZ variable.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void _sim_subststr_substr (const char *ops, char *rbuf, size_t rbuf_size)
|
||||||
|
{
|
||||||
|
int rbuf_len = (int)strlen (rbuf);
|
||||||
|
char *tstr = (char *)malloc (1 + rbuf_len);
|
||||||
|
|
||||||
|
strcpy (tstr, rbuf);
|
||||||
|
|
||||||
|
if (*ops == '~') { /* Substring? */
|
||||||
|
int offset, length;
|
||||||
|
int o, l;
|
||||||
|
|
||||||
|
switch (sscanf (ops + 1, "%d,%d", &o, &l)) {
|
||||||
|
case 2:
|
||||||
|
if (l < 0)
|
||||||
|
length = rbuf_len - MIN(-l, rbuf_len);
|
||||||
|
else
|
||||||
|
length = l;
|
||||||
|
/* fall through */
|
||||||
|
case 1:
|
||||||
|
if (o < 0)
|
||||||
|
offset = rbuf_len - MIN(-o, rbuf_len);
|
||||||
|
else
|
||||||
|
offset = MIN(o, rbuf_len);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
offset = 0;
|
||||||
|
length = rbuf_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (offset + length > rbuf_len)
|
||||||
|
length = rbuf_len - offset;
|
||||||
|
memcpy (rbuf, tstr + offset, length);
|
||||||
|
rbuf[length] = '\0';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char *eq;
|
||||||
|
|
||||||
|
if ((eq = strchr (ops, '='))) { /* Substitute? */
|
||||||
|
const char *last = tstr;
|
||||||
|
const char *curr = tstr;
|
||||||
|
char *match = (char *)malloc (1 + (eq - ops));
|
||||||
|
size_t move_size;
|
||||||
|
t_bool asterisk_match;
|
||||||
|
|
||||||
|
strlcpy (match, ops, 1 + (eq - ops));
|
||||||
|
asterisk_match = (*ops == '*');
|
||||||
|
if (asterisk_match)
|
||||||
|
memmove (match, match + 1, 1 + strlen (match + 1));
|
||||||
|
while ((curr = strstr (last, match))) {
|
||||||
|
if (!asterisk_match) {
|
||||||
|
move_size = MIN((size_t)(curr - last), rbuf_size);
|
||||||
|
memcpy (rbuf, last, move_size);
|
||||||
|
rbuf_size -= move_size;
|
||||||
|
rbuf += move_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
asterisk_match = FALSE;
|
||||||
|
move_size = MIN(strlen (eq + 1), rbuf_size);
|
||||||
|
memcpy (rbuf, eq + 1, move_size);
|
||||||
|
rbuf_size -= move_size;
|
||||||
|
rbuf += move_size;
|
||||||
|
curr += strlen (match);
|
||||||
|
last = curr;
|
||||||
|
}
|
||||||
|
move_size = MIN(strlen (last), rbuf_size);
|
||||||
|
memcpy (rbuf, last, move_size);
|
||||||
|
rbuf_size -= move_size;
|
||||||
|
rbuf += move_size;
|
||||||
|
if (rbuf_size)
|
||||||
|
*rbuf = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free (tstr);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size)
|
_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size)
|
||||||
{
|
{
|
||||||
const char *ap;
|
const char *ap;
|
||||||
|
const char *fixup_needed = strchr (gbuf, ':');
|
||||||
|
char *tgbuf = NULL;
|
||||||
|
size_t tgbuf_size = MAX(rbuf_size, 1 + (size_t)(fixup_needed - gbuf));
|
||||||
|
|
||||||
|
if (fixup_needed) {
|
||||||
|
tgbuf = (char *)calloc (tgbuf_size, 1);
|
||||||
|
memcpy (tgbuf, gbuf, (fixup_needed - gbuf));
|
||||||
|
gbuf = tgbuf;
|
||||||
|
}
|
||||||
ap = _sim_gen_env_uplowcase (gbuf, rbuf, rbuf_size);/* Look for environment variable */
|
ap = _sim_gen_env_uplowcase (gbuf, rbuf, rbuf_size);/* Look for environment variable */
|
||||||
if (!ap) { /* no environment variable found? */
|
if (!ap) { /* no environment variable found? */
|
||||||
time_t now = (time_t)cmd_time.tv_sec;
|
time_t now = (time_t)cmd_time.tv_sec;
|
||||||
|
@ -3788,6 +3924,12 @@ if (!ap) { /* no environment variable found? */
|
||||||
ap = rbuf;
|
ap = rbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ap && fixup_needed) { /* substring/substituted needed? */
|
||||||
|
strlcpy (tgbuf, ap, tgbuf_size);
|
||||||
|
_sim_subststr_substr (fixup_needed + 1, tgbuf, tgbuf_size);
|
||||||
|
strlcpy (rbuf, tgbuf, rbuf_size);
|
||||||
|
}
|
||||||
|
free (tgbuf);
|
||||||
return ap;
|
return ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue