Add "shellescape" built-in function.

This commit is contained in:
Dianne Skoll
2021-09-08 09:33:47 -04:00
parent 8e3ddb96b3
commit 5ceffddd5b
7 changed files with 78 additions and 17 deletions

View File

@@ -2895,6 +2895,23 @@ If \fImaxlen\fR is specified, then \fBshell()\fR returns the first
\fImaxlen\fR is specified as a negative number, then \fIall\fR the
output from \fIcmd\fR is returned.
.RE
.TP
.B shellescape(s_str)
Returns \fIstr\fR with all shell metacharacters such as " ", "*", etc
escaped with a backslash. For example:
.PP
.nf
SET a shellescape("a b*? c&d$e")
.fi
.RS
.PP
will set \fBa\fR to:
.RE
.PP
.nf
"a\\ b\\*\\?\\ c\\&d\\$e"
.fi
.TP
.B slide(d_start, i_amt [,s_wkday...])
This function is the inverse of \fBnonomitted\fR. It adds \fIamt\fR

View File

@@ -24,10 +24,6 @@
#include "protos.h"
#include "expr.h"
/* Define the shell characters not to escape */
static char const DontEscapeMe[] =
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,";
static int ParseTimeTrig (ParsePtr s, TimeTrig *tim, int save_in_globals);
static int ParseLocalOmit (ParsePtr s, Trigger *t);
static int ParseScanFrom (ParsePtr s, Trigger *t, int type);
@@ -1230,24 +1226,16 @@ int DoMsgCommand(char const *cmd, char const *msg)
DynamicBuffer execBuffer;
DynamicBuffer buf;
char const *s;
DBufInit(&buf);
DBufInit(&execBuffer);
/* Escape shell characters in msg INCLUDING WHITESPACE! */
for (s=msg; *s; s++) {
if (isspace(*s) || !strchr(DontEscapeMe, *s)) {
if (DBufPutc(&buf, '\\') != OK) {
r = E_NO_MEM;
goto finished;
}
}
if (DBufPutc(&buf, *s) != OK) {
r = E_NO_MEM;
goto finished;
}
/* Escape shell characters in msg */
if (ShellEscape(msg, &buf) != OK) {
r = E_NO_MEM;
goto finished;
}
msg = DBufValue(&buf);
/* Do "%s" substitution */

View File

@@ -151,6 +151,7 @@ static int FWeekno (func_info *);
static int FWkday (func_info *);
static int FWkdaynum (func_info *);
static int FYear (func_info *);
static int FShellescape (func_info *);
static int CleanUpAfterFunc (func_info *);
static int CheckArgs (BuiltinFunc *f, int nargs);
@@ -267,6 +268,7 @@ BuiltinFunc Func[] = {
{ "realtoday", 0, 0, 0, FRealtoday },
{ "sgn", 1, 1, 1, FSgn },
{ "shell", 1, 2, 0, FShell },
{ "shellescape", 1, 1, 1, FShellescape },
{ "slide", 2, NO_MAX, 0, FSlide },
{ "strlen", 1, 1, 1, FStrlen },
{ "substr", 2, 3, 1, FSubstr },
@@ -1072,6 +1074,28 @@ static int FOstype(func_info *info)
return RetStrVal("UNIX", info);
}
/***************************************************************/
/* */
/* FShellescape - escape shell meta-characters */
/* */
/***************************************************************/
static int FShellescape(func_info *info)
{
DynamicBuffer buf;
int r;
ASSERT_TYPE(0, STR_TYPE);
DBufInit (&buf);
if (ShellEscape(ARG(0).v.str, &buf) != OK) {
DBufFree(&buf);
return E_NO_MEM;
}
r = RetStrVal(DBufValue(&buf), info);
DBufFree(&buf);
return r;
}
/***************************************************************/
/* */
/* FUpper - convert string to upper-case */

View File

@@ -162,3 +162,4 @@ void PrintJSONKeyPairDate(char const *name, int jul);
void PrintJSONKeyPairDateTime(char const *name, int dt);
void PrintJSONKeyPairTime(char const *name, int t);
void System(char const *cmd);
int ShellEscape(char const *in, DynamicBuffer *out);

View File

@@ -9,7 +9,11 @@
/* */
/***************************************************************/
static char const DontEscapeMe[] =
"1234567890_-=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@.,/";
#include "config.h"
#include "err.h"
#include <string.h>
#include <stdio.h>
@@ -146,3 +150,15 @@ int _private_unminus_overflow(int a, int b)
if (a < 0 && b < 0) return 1;
return 0;
}
int
ShellEscape(char const *in, DynamicBuffer *out)
{
while(*in) {
if (!strchr(DontEscapeMe, *in)) {
if (DBufPutc(out, '\\') != OK) return E_NO_MEM;
}
if (DBufPutc(out, *in++) != OK) return E_NO_MEM;
}
return OK;
}

View File

@@ -3255,6 +3255,16 @@ $IntMin => -2147483648
abs(-2147483648) => Number too high
../tests/test.rem(587): Number too high
# Shellescape
set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
shellescape(" !"#$%%&'()*+,-./0123456789:;<=>?@ABCDEF"...) => "\ \!\"\#\$\%\%\&\'\(\)\*+,-./0123456789\"...
msg [a]
../tests/test.rem(592): Trig = Saturday, 16 February, 1991
a => "\ \!\"\#\$\%\%\&\'\(\)\*+,-./0123456789\"...
\ \!\"\#\$\\\&\'\(\)\*+,-./0123456789\:\;\<=\>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]\^_\`abcdefghijklmnopqrstuvwxyz\{\|\}\~
# Don't want Remind to queue reminders
EXIT

View File

@@ -586,6 +586,11 @@ set a $IntMin * (-1)
set a (-1) * $IntMin
set a abs($IntMin)
# Shellescape
set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
msg [a]
# Don't want Remind to queue reminders
EXIT