diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-10-11 14:49:26 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-10-11 15:19:40 -0700 |
commit | 011c1d1c0766c65517ebd495465c99e86edb63ec (patch) | |
tree | 30d8f6a13235af90897c3223554871ef52225462 /lib/sh/zgetline.c | |
parent | 40cfaccf7b178b6239b5cd0013ef80b7ff8e503e (diff) | |
download | vyatta-bash-011c1d1c0766c65517ebd495465c99e86edb63ec.tar.gz vyatta-bash-011c1d1c0766c65517ebd495465c99e86edb63ec.zip |
Update to bash-4.1
Diffstat (limited to 'lib/sh/zgetline.c')
-rw-r--r-- | lib/sh/zgetline.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/lib/sh/zgetline.c b/lib/sh/zgetline.c new file mode 100644 index 0000000..33ac830 --- /dev/null +++ b/lib/sh/zgetline.c @@ -0,0 +1,121 @@ +/* zgetline - read a line of input from a specified file descriptor and return + a pointer to a newly-allocated buffer containing the data. */ + +/* Copyright (C) 2008,2009 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <sys/types.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include <errno.h> +#include "xmalloc.h" + +#if !defined (errno) +extern int errno; +#endif + +extern ssize_t zread __P((int, char *, size_t)); +extern ssize_t zreadc __P((int, char *)); +extern ssize_t zreadintr __P((int, char *, size_t)); +extern ssize_t zreadcintr __P((int, char *)); + +typedef ssize_t breadfunc_t __P((int, char *, size_t)); +typedef ssize_t creadfunc_t __P((int, char *)); + +/* Initial memory allocation for automatic growing buffer in zreadlinec */ +#define GET_LINE_INITIAL_ALLOCATION 16 + +/* Derived from GNU libc's getline. + The behavior is almost the same as getline. See man getline. + The differences are + (1) using file descriptor instead of FILE *, + (2) the order of arguments; the file descriptor comes the first, and + (3) the addtion of thired argument, UNBUFFERED_READ; this argument + controls whether get_line uses buffering or not to get a byte data + from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and + uses zread if UNBUFFERED_READ is non-zero. + + Returns number of bytes read or -1 on error. */ + +ssize_t +zgetline (fd, lineptr, n, unbuffered_read) + int fd; + char **lineptr; + size_t *n; + int unbuffered_read; +{ + int nr, retval; + char *line, c; + + if (lineptr == 0 || n == 0 || (*lineptr == 0 && *n != 0)) + return -1; + + nr = 0; + line = *lineptr; + + while (1) + { + retval = unbuffered_read ? zread (fd, &c, 1) : zreadc(fd, &c); + + if (retval <= 0) + { + if (line && nr > 0) + line[nr] = '\0'; + break; + } + + if (nr + 2 >= *n) + { + size_t new_size; + + new_size = (*n == 0) ? GET_LINE_INITIAL_ALLOCATION : *n * 2; + line = (*n >= new_size) ? NULL : xrealloc (*lineptr, new_size); + + if (line) + { + *lineptr = line; + *n = new_size; + } + else + { + if (*n > 0) + { + (*lineptr)[*n - 1] = '\0'; + nr = *n - 2; + } + break; + } + } + + line[nr] = c; + nr++; + + if (c == '\n') + { + line[nr] = '\0'; + break; + } + } + + return nr - 1; +} |