aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtin.cpp
diff options
context:
space:
mode:
authorGravatar Kevin Ballard <kevin@sb.org>2014-09-21 19:18:56 -0700
committerGravatar Kevin Ballard <kevin@sb.org>2014-09-21 19:27:26 -0700
commit8f8c4cdd176fda4d93a2d1d4b0ae6321d5706e5f (patch)
tree68c2f6d4eb2bbd7a4b975b7901cc0db95f83b740 /builtin.cpp
parentf889ad0fda9bf8d1f354cad37d508e0c4205af48 (diff)
Implement new `read --null` flag
The `--null` flag to `read` makes it split incoming lines on NUL instead of newlines. This is intended for processing the output of a command that uses NUL separators (such as `find -print0`). Fixes #1694.
Diffstat (limited to 'builtin.cpp')
-rw-r--r--builtin.cpp80
1 files changed, 42 insertions, 38 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 3ab3bb48..4604190c 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -65,6 +65,7 @@
#include "path.h"
#include "history.h"
#include "parse_tree.h"
+#include "wcstringutil.h"
/**
The default prompt for the read command
@@ -2305,10 +2306,9 @@ static int builtin_random(parser_t &parser, wchar_t **argv)
*/
static int builtin_read(parser_t &parser, wchar_t **argv)
{
- wchar_t *buff=0;
+ wcstring buff;
int i, argc = builtin_count_args(argv);
int place = ENV_USER;
- wchar_t *nxt;
const wchar_t *prompt = DEFAULT_READ_PROMPT;
const wchar_t *commandline = L"";
int exit_res=STATUS_BUILTIN_OK;
@@ -2317,6 +2317,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
wchar_t *end;
int shell = 0;
int array = 0;
+ bool split_null = false;
woptind=0;
@@ -2370,6 +2371,10 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
}
,
{
+ L"null", no_argument, 0, 'z'
+ }
+ ,
+ {
L"help", no_argument, 0, 'h'
}
,
@@ -2383,7 +2388,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
int opt = wgetopt_long(argc,
argv,
- L"xglUup:c:hm:n:sa",
+ L"xglUup:c:hm:n:saz",
long_options,
&opt_index);
if (opt == -1)
@@ -2468,6 +2473,10 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
array = 1;
break;
+ case L'z':
+ split_null = true;
+ break;
+
case 'h':
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_OK;
@@ -2541,7 +2550,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
/*
Check if we should read interactively using \c reader_readline()
*/
- if (isatty(0) && builtin_stdin == 0)
+ if (isatty(0) && builtin_stdin == 0 && !split_null)
{
const wchar_t *line;
@@ -2572,13 +2581,11 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
// note: we're deliberately throwing away the tail of the commandline.
// It shouldn't be unread because it was produced with `commandline -i`,
// not typed.
- buff = (wchar_t *)malloc(((size_t)nchars + 1) * sizeof(wchar_t));
- wmemcpy(buff, line, (size_t)nchars);
- buff[nchars] = 0;
+ buff = wcstring(line, nchars);
}
else
{
- buff = wcsdup(line);
+ buff = wcstring(line);
}
}
else
@@ -2591,7 +2598,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
{
int eof=0;
- wcstring sb;
+ buff.clear();
while (1)
{
@@ -2621,7 +2628,6 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
case (size_t)(-2):
break;
case 0:
- eof=1;
finished = 1;
break;
@@ -2635,44 +2641,43 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
if (eof)
break;
- if (res == L'\n')
+ if (!split_null && res == L'\n')
break;
- sb.push_back(res);
+ if (split_null && res == L'\0')
+ break;
+
+ buff.push_back(res);
- if (0 < nchars && (size_t)nchars <= sb.size())
+ if (0 < nchars && (size_t)nchars <= buff.size())
{
break;
}
}
- if (sb.size() < 2 && eof)
+ if (buff.size() < 2 && eof)
{
exit_res = 1;
}
-
- buff = wcsdup(sb.c_str());
}
if (i != argc && !exit_res)
{
-
- wchar_t *state;
-
env_var_t ifs = env_get_string(L"IFS");
-
if (ifs.missing_or_empty())
{
/* Every character is a separate token */
- size_t bufflen = wcslen(buff);
+ size_t bufflen = buff.size();
if (array)
{
if (bufflen > 0)
{
wcstring chars(bufflen+(bufflen-1), ARRAY_SEP);
- for (size_t j=0; j<bufflen; ++j)
+ wcstring::iterator out = chars.begin();
+ for (wcstring::const_iterator it = buff.begin(), end = buff.end(); it != end; ++it)
{
- chars[j*2] = buff[j];
+ *out = *it;
+ out += 2;
}
env_set(argv[i], chars.c_str(), place);
}
@@ -2686,14 +2691,15 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
size_t j = 0;
for (; i+1 < argc; ++i)
{
- if (j < bufflen) {
- wchar_t buffer[2] = {buff[j], 0};
+ if (j < bufflen)
+ {
+ wchar_t buffer[2] = {buff[j++], 0};
env_set(argv[i], buffer, place);
}
- else {
+ else
+ {
env_set(argv[i], L"", place);
}
- if (j < bufflen) ++j;
}
if (i < argc) env_set(argv[i], &buff[j], place);
}
@@ -2701,34 +2707,32 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
else if (array)
{
wcstring tokens;
- tokens.reserve(wcslen(buff));
+ tokens.reserve(buff.size());
bool empty = true;
- for (nxt = wcstok(buff, ifs.c_str(), &state); nxt != 0; nxt = wcstok(0, ifs.c_str(), &state))
+ for (wcstring_range loc = wcstring_tok(buff, ifs); loc.first != wcstring::npos; loc = wcstring_tok(buff, ifs, loc))
{
- if (! tokens.empty()) tokens.push_back(ARRAY_SEP);
- tokens.append(nxt);
+ if (!empty) tokens.push_back(ARRAY_SEP);
+ tokens.append(buff, loc.first, loc.second);
empty = false;
}
env_set(argv[i], empty ? NULL : tokens.c_str(), place);
}
else
{
- nxt = wcstok(buff, (i<argc-1)?ifs.c_str():L"", &state);
+ wcstring_range loc = wcstring_range(0,0);
while (i<argc)
{
- env_set(argv[i], nxt != 0 ? nxt: L"", place);
+ loc = wcstring_tok(buff, (i+1<argc) ? ifs : L"", loc);
+ env_set(argv[i], loc.first == wcstring::npos ? L"" : &buff.c_str()[loc.first], place);
- i++;
- if (nxt != 0)
- nxt = wcstok(0, (i<argc-1)?ifs.c_str():L"", &state);
+ ++i;
}
+
}
}
- free(buff);
-
return exit_res;
}