*/
#include "libbb.h"
#include "shell_common.h"
+#include <sys/resource.h> /* getrlimit */
const char defifsvar[] ALIGN1 = "IFS= \t\n";
/* read builtin */
+/* Needs to be interruptible: shell mush handle traps and shell-special signals
+ * while inside read. To implement this, be sure to not loop on EINTR
+ * and return errno == EINTR reliably.
+ */
//TODO: use more efficient setvar() which takes a pointer to malloced "VAR=VAL"
//string. hush naturally has it, and ash has setvareq().
//Here we can simply store "VAR=" at buffer start and store read data directly
const char *opt_u
)
{
+ unsigned err;
unsigned end_ms; /* -t TIMEOUT */
int fd; /* -u FD */
int nchars; /* -n NUM */
int startword;
smallint backslash;
+ errno = err = 0;
+
pp = argv;
while (*pp) {
if (!is_well_formed_var_name(*pp, '\0')) {
old_tty = tty;
if (nchars) {
tty.c_lflag &= ~ICANON;
- tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
+ // Setting it to more than 1 breaks poll():
+ // it blocks even if there's data. !??
+ //tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
+ /* reads would block only if < 1 char is available */
+ tty.c_cc[VMIN] = 1;
+ /* no timeout (reads block forever) */
+ tty.c_cc[VTIME] = 0;
}
if (read_flags & BUILTIN_READ_SILENT) {
tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
bufpos = 0;
do {
char c;
+ struct pollfd pfd[1];
+ int timeout;
- if (end_ms) {
- int timeout;
- struct pollfd pfd[1];
+ if ((bufpos & 0xff) == 0)
+ buffer = xrealloc(buffer, bufpos + 0x101);
- pfd[0].fd = fd;
- pfd[0].events = POLLIN;
+ timeout = -1;
+ if (end_ms) {
timeout = end_ms - (unsigned)monotonic_ms();
- if (timeout <= 0 /* already late? */
- || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
- ) { /* timed out! */
+ if (timeout <= 0) { /* already late? */
retval = (const char *)(uintptr_t)1;
goto ret;
}
}
- if ((bufpos & 0xff) == 0)
- buffer = xrealloc(buffer, bufpos + 0x100);
- if (nonblock_immune_read(fd, &buffer[bufpos], 1) != 1) {
+ /* We must poll even if timeout is -1:
+ * we want to be interrupted if signal arrives,
+ * regardless of SA_RESTART-ness of that signal!
+ */
+ errno = 0;
+ pfd[0].fd = fd;
+ pfd[0].events = POLLIN;
+ if (poll(pfd, 1, timeout) != 1) {
+ /* timed out, or EINTR */
+ err = errno;
+ retval = (const char *)(uintptr_t)1;
+ goto ret;
+ }
+ if (read(fd, &buffer[bufpos], 1) != 1) {
+ err = errno;
retval = (const char *)(uintptr_t)1;
break;
}
+
c = buffer[bufpos];
if (c == '\0')
continue;
free(buffer);
if (read_flags & BUILTIN_READ_SILENT)
tcsetattr(fd, TCSANOW, &old_tty);
+
+ errno = err;
return retval;
}