Finalize project
This commit is contained in:
commit
c75cbff329
10
Makefile
Normal file
10
Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
PROGS = sh_quote
|
||||||
|
CFLAGS = -std=c99 -pedantic
|
||||||
|
|
||||||
|
default: $(PROGS)
|
||||||
|
|
||||||
|
test: $(PROGS)
|
||||||
|
./test_sh_quote
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(PROGS)
|
39
README.md
Normal file
39
README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Shell quoting util
|
||||||
|
|
||||||
|
This tool was made to handle a specific edge case in shell scripting.
|
||||||
|
|
||||||
|
When you want to supply a command to some tool as a shell string, but you only have it as already expanded array.
|
||||||
|
|
||||||
|
This doesn't work as expected because `$@` is expanded, ending up as multiple arguments to `su`:
|
||||||
|
|
||||||
|
```
|
||||||
|
su -c "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
This does work as expected:
|
||||||
|
|
||||||
|
```
|
||||||
|
su -c "$(sh_quote "$@")"
|
||||||
|
```
|
||||||
|
|
||||||
|
Because all arguments must be relayed, `-h` or `--help` cannot be taken into account, so there is no helptext.
|
||||||
|
|
||||||
|
When no arguments are given, it returns without producing any output.
|
||||||
|
|
||||||
|
# Error messages
|
||||||
|
|
||||||
|
None. This program cannot fail.
|
||||||
|
|
||||||
|
If stdout is not writable, no sensible output will be generated.
|
||||||
|
|
||||||
|
If `$0` is not set, no output will be generated.
|
||||||
|
|
||||||
|
# Building
|
||||||
|
|
||||||
|
Run `make`.
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
|
||||||
|
Run `make test`
|
||||||
|
|
||||||
|
The test script can also run on arbitrary programs: `./run_sh_quote /path/to/other_program`.
|
26
sh_quote.c
Normal file
26
sh_quote.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
unsigned int i;
|
||||||
|
char* p;
|
||||||
|
char* delim = "'";
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (i > 1) putchar(' ');
|
||||||
|
p = argv[i];
|
||||||
|
|
||||||
|
printf("%s", delim);
|
||||||
|
while(*p != '\0') {
|
||||||
|
if (p[0] == '\'') {
|
||||||
|
printf("%s\\'%s", delim, delim);
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (p[0] == '\\') putchar('\\');
|
||||||
|
putchar((p++)[0]);
|
||||||
|
}
|
||||||
|
printf("%s", delim);
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
20
test_sh_quote
Executable file
20
test_sh_quote
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
PROG=${1:-./sh_quote}
|
||||||
|
|
||||||
|
run_test() {
|
||||||
|
r=$($PROG "$2"|sed 's/^ *//;s/ *$//')
|
||||||
|
if test "$r" == "$3"; then
|
||||||
|
echo PASS "$1"
|
||||||
|
else
|
||||||
|
echo FAIL "$1"
|
||||||
|
printf "Expected: %s\nGot: %s\n" "$3" "$r"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_test empty "" "''"
|
||||||
|
run_test whitespace "Foo Bar" "'Foo Bar'"
|
||||||
|
run_test quote "Foo'Bar" "'Foo'\''Bar'"
|
||||||
|
run_test newline "Foo
|
||||||
|
Bar" "'Foo
|
||||||
|
Bar'"
|
||||||
|
run_test trailing_space "Foobar " "'Foobar '"
|
Loading…
Reference in New Issue
Block a user