Don't assume STDIN_FD and STDOUT_FD are interchangeable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
diff --git a/linenoise.c b/linenoise.c
index af90699..28f0749 100644
--- a/linenoise.c
+++ b/linenoise.c
@@ -123,7 +123,8 @@ char **history = NULL;
* We pass this state to functions implementing specific editing
* functionalities. */
struct linenoiseState {
- int fd; /* Terminal file descriptor. */
+ int ifd; /* Terminal stdin file descriptor. */
+ int ofd; /* Terminal stdout file descriptor. */
char *buf; /* Edited line buffer. */
size_t buflen; /* Edited line buffer size. */
const char *prompt; /* Prompt to display. */
@@ -258,7 +259,7 @@ static int getColumns(void) {
/* Clear the screen. Used to handle ctrl+l */
void linenoiseClearScreen(void) {
- if (write(STDIN_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
+ if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
/* nothing to do, just to avoid warning. */
}
}
@@ -313,7 +314,7 @@ static int completeLine(struct linenoiseState *ls) {
refreshLine(ls);
}
- nread = read(ls->fd,&c,1);
+ nread = read(ls->ifd,&c,1);
if (nread <= 0) {
freeCompletions(&lc);
return -1;
@@ -406,7 +407,7 @@ static void abFree(struct abuf *ab) {
static void refreshSingleLine(struct linenoiseState *l) {
char seq[64];
size_t plen = strlen(l->prompt);
- int fd = l->fd;
+ int fd = l->ofd;
char *buf = l->buf;
size_t len = l->len;
size_t pos = l->pos;
@@ -449,7 +450,7 @@ static void refreshMultiLine(struct linenoiseState *l) {
int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
int rpos2; /* rpos after refresh. */
int old_rows = l->maxrows;
- int fd = l->fd, j;
+ int fd = l->ofd, j;
struct abuf ab;
/* Update maxrows if needed. */
@@ -539,7 +540,7 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
if ((!mlmode && l->plen+l->len < l->cols) /* || mlmode */) {
/* Avoid a full update of the line in the
* trivial case. */
- if (write(l->fd,&c,1) == -1) return -1;
+ if (write(l->ofd,&c,1) == -1) return -1;
} else {
refreshLine(l);
}
@@ -643,13 +644,14 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
* when ctrl+d is typed.
*
* The function returns the length of the current buffer. */
-static int linenoiseEdit(int fd, char *buf, size_t buflen, const char *prompt)
+static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt)
{
struct linenoiseState l;
/* Populate the linenoise state that we pass to functions implementing
* specific editing functionalities. */
- l.fd = fd;
+ l.ifd = stdin_fd;
+ l.ofd = stdout_fd;
l.buf = buf;
l.buflen = buflen;
l.prompt = prompt;
@@ -668,13 +670,13 @@ static int linenoiseEdit(int fd, char *buf, size_t buflen, const char *prompt)
* initially is just an empty string. */
linenoiseHistoryAdd("");
- if (write(fd,prompt,l.plen) == -1) return -1;
+ if (write(l.ofd,prompt,l.plen) == -1) return -1;
while(1) {
char c;
int nread;
char seq[2], seq2[2];
- nread = read(fd,&c,1);
+ nread = read(l.ifd,&c,1);
if (nread <= 0) return l.len;
/* Only autocomplete when the callback is set. It returns < 0 when
@@ -733,7 +735,7 @@ static int linenoiseEdit(int fd, char *buf, size_t buflen, const char *prompt)
break;
case ESC: /* escape sequence */
/* Read the next two bytes representing the escape sequence. */
- if (read(fd,seq,2) == -1) break;
+ if (read(l.ifd,seq,2) == -1) break;
if (seq[0] == 91 && seq[1] == 68) {
/* Left arrow */
@@ -748,7 +750,7 @@ static int linenoiseEdit(int fd, char *buf, size_t buflen, const char *prompt)
LINENOISE_HISTORY_NEXT);
} else if (seq[0] == 91 && seq[1] > 48 && seq[1] < 55) {
/* extended escape, read additional two bytes. */
- if (read(fd,seq2,2) == -1) break;
+ if (read(l.ifd,seq2,2) == -1) break;
if (seq[1] == 51 && seq2[0] == 126) {
/* Delete key. */
linenoiseEditDelete(&l);
@@ -791,7 +793,6 @@ static int linenoiseEdit(int fd, char *buf, size_t buflen, const char *prompt)
/* This function calls the line editing function linenoiseEdit() using
* the STDIN file descriptor set in raw mode. */
static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
- int fd = STDIN_FILENO;
int count;
if (buflen == 0) {
@@ -799,6 +800,7 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
return -1;
}
if (!isatty(STDIN_FILENO)) {
+ /* Not a tty: read from file / pipe. */
if (fgets(buf, buflen, stdin) == NULL) return -1;
count = strlen(buf);
if (count && buf[count-1] == '\n') {
@@ -806,9 +808,10 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
buf[count] = '\0';
}
} else {
- if (enableRawMode(fd) == -1) return -1;
- count = linenoiseEdit(fd, buf, buflen, prompt);
- disableRawMode(fd);
+ /* Interactive editing. */
+ if (enableRawMode(STDIN_FILENO) == -1) return -1;
+ count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
+ disableRawMode(STDIN_FILENO);
printf("\n");
}
return count;