xref: /onnv-gate/usr/src/lib/libc/port/stdio/getline.c (revision 13093:48f2dbca79a2)
1*13093SRoger.Faulkner@Oracle.COM /*
2*13093SRoger.Faulkner@Oracle.COM  * CDDL HEADER START
3*13093SRoger.Faulkner@Oracle.COM  *
4*13093SRoger.Faulkner@Oracle.COM  * The contents of this file are subject to the terms of the
5*13093SRoger.Faulkner@Oracle.COM  * Common Development and Distribution License (the "License").
6*13093SRoger.Faulkner@Oracle.COM  * You may not use this file except in compliance with the License.
7*13093SRoger.Faulkner@Oracle.COM  *
8*13093SRoger.Faulkner@Oracle.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*13093SRoger.Faulkner@Oracle.COM  * or http://www.opensolaris.org/os/licensing.
10*13093SRoger.Faulkner@Oracle.COM  * See the License for the specific language governing permissions
11*13093SRoger.Faulkner@Oracle.COM  * and limitations under the License.
12*13093SRoger.Faulkner@Oracle.COM  *
13*13093SRoger.Faulkner@Oracle.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*13093SRoger.Faulkner@Oracle.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*13093SRoger.Faulkner@Oracle.COM  * If applicable, add the following below this CDDL HEADER, with the
16*13093SRoger.Faulkner@Oracle.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*13093SRoger.Faulkner@Oracle.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*13093SRoger.Faulkner@Oracle.COM  *
19*13093SRoger.Faulkner@Oracle.COM  * CDDL HEADER END
20*13093SRoger.Faulkner@Oracle.COM  */
21*13093SRoger.Faulkner@Oracle.COM 
22*13093SRoger.Faulkner@Oracle.COM /*
23*13093SRoger.Faulkner@Oracle.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*13093SRoger.Faulkner@Oracle.COM  */
25*13093SRoger.Faulkner@Oracle.COM 
26*13093SRoger.Faulkner@Oracle.COM #include "lint.h"
27*13093SRoger.Faulkner@Oracle.COM #include "file64.h"
28*13093SRoger.Faulkner@Oracle.COM #include "mtlib.h"
29*13093SRoger.Faulkner@Oracle.COM #include <stdio.h>
30*13093SRoger.Faulkner@Oracle.COM #include <errno.h>
31*13093SRoger.Faulkner@Oracle.COM #include <thread.h>
32*13093SRoger.Faulkner@Oracle.COM #include <synch.h>
33*13093SRoger.Faulkner@Oracle.COM #include <unistd.h>
34*13093SRoger.Faulkner@Oracle.COM #include <limits.h>
35*13093SRoger.Faulkner@Oracle.COM #include <malloc.h>
36*13093SRoger.Faulkner@Oracle.COM #include <sys/types.h>
37*13093SRoger.Faulkner@Oracle.COM #include "stdiom.h"
38*13093SRoger.Faulkner@Oracle.COM 
39*13093SRoger.Faulkner@Oracle.COM #define	LINESZ	128	/* initial guess for a NULL *lineptr */
40*13093SRoger.Faulkner@Oracle.COM 
41*13093SRoger.Faulkner@Oracle.COM ssize_t
getdelim(char ** _RESTRICT_KYWD lineptr,size_t * _RESTRICT_KYWD n,int delimiter,FILE * _RESTRICT_KYWD iop)42*13093SRoger.Faulkner@Oracle.COM getdelim(char **_RESTRICT_KYWD lineptr, size_t *_RESTRICT_KYWD n,
43*13093SRoger.Faulkner@Oracle.COM     int delimiter, FILE *_RESTRICT_KYWD iop)
44*13093SRoger.Faulkner@Oracle.COM {
45*13093SRoger.Faulkner@Oracle.COM 	rmutex_t *lk;
46*13093SRoger.Faulkner@Oracle.COM 	char *ptr;
47*13093SRoger.Faulkner@Oracle.COM 	size_t size;
48*13093SRoger.Faulkner@Oracle.COM 	int c;
49*13093SRoger.Faulkner@Oracle.COM 	size_t cnt;
50*13093SRoger.Faulkner@Oracle.COM 
51*13093SRoger.Faulkner@Oracle.COM 	if (lineptr == NULL || n == NULL ||
52*13093SRoger.Faulkner@Oracle.COM 	    delimiter < 0 || delimiter > UCHAR_MAX) {
53*13093SRoger.Faulkner@Oracle.COM 		errno = EINVAL;
54*13093SRoger.Faulkner@Oracle.COM 		return (-1);
55*13093SRoger.Faulkner@Oracle.COM 	}
56*13093SRoger.Faulkner@Oracle.COM 
57*13093SRoger.Faulkner@Oracle.COM 	if (*lineptr == NULL || *n < LINESZ) {	/* initial allocation */
58*13093SRoger.Faulkner@Oracle.COM 		if ((*lineptr = realloc(*lineptr, LINESZ)) == NULL) {
59*13093SRoger.Faulkner@Oracle.COM 			errno = ENOMEM;
60*13093SRoger.Faulkner@Oracle.COM 			return (-1);
61*13093SRoger.Faulkner@Oracle.COM 		}
62*13093SRoger.Faulkner@Oracle.COM 		*n = LINESZ;
63*13093SRoger.Faulkner@Oracle.COM 	}
64*13093SRoger.Faulkner@Oracle.COM 	ptr = *lineptr;
65*13093SRoger.Faulkner@Oracle.COM 	size = *n;
66*13093SRoger.Faulkner@Oracle.COM 	cnt = 0;
67*13093SRoger.Faulkner@Oracle.COM 
68*13093SRoger.Faulkner@Oracle.COM 	FLOCKFILE(lk, iop);
69*13093SRoger.Faulkner@Oracle.COM 
70*13093SRoger.Faulkner@Oracle.COM 	_SET_ORIENTATION_BYTE(iop);
71*13093SRoger.Faulkner@Oracle.COM 
72*13093SRoger.Faulkner@Oracle.COM 	do {
73*13093SRoger.Faulkner@Oracle.COM 		c = (--iop->_cnt < 0) ? __filbuf(iop) : *iop->_ptr++;
74*13093SRoger.Faulkner@Oracle.COM 		if (c == EOF)
75*13093SRoger.Faulkner@Oracle.COM 			break;
76*13093SRoger.Faulkner@Oracle.COM 		*ptr++ = c;
77*13093SRoger.Faulkner@Oracle.COM 		if (++cnt == size) {	/* must reallocate */
78*13093SRoger.Faulkner@Oracle.COM 			if ((ptr = realloc(*lineptr, 2 * size)) == NULL) {
79*13093SRoger.Faulkner@Oracle.COM 				FUNLOCKFILE(lk);
80*13093SRoger.Faulkner@Oracle.COM 				ptr = *lineptr + size - 1;
81*13093SRoger.Faulkner@Oracle.COM 				*ptr = '\0';
82*13093SRoger.Faulkner@Oracle.COM 				errno = ENOMEM;
83*13093SRoger.Faulkner@Oracle.COM 				return (-1);
84*13093SRoger.Faulkner@Oracle.COM 			}
85*13093SRoger.Faulkner@Oracle.COM 			*lineptr = ptr;
86*13093SRoger.Faulkner@Oracle.COM 			ptr += size;
87*13093SRoger.Faulkner@Oracle.COM 			*n = size = 2 * size;
88*13093SRoger.Faulkner@Oracle.COM 		}
89*13093SRoger.Faulkner@Oracle.COM 	} while (c != delimiter);
90*13093SRoger.Faulkner@Oracle.COM 
91*13093SRoger.Faulkner@Oracle.COM 	*ptr = '\0';
92*13093SRoger.Faulkner@Oracle.COM 
93*13093SRoger.Faulkner@Oracle.COM 	FUNLOCKFILE(lk);
94*13093SRoger.Faulkner@Oracle.COM 	if (cnt > SSIZE_MAX) {
95*13093SRoger.Faulkner@Oracle.COM 		errno = EOVERFLOW;
96*13093SRoger.Faulkner@Oracle.COM 		return (-1);
97*13093SRoger.Faulkner@Oracle.COM 	}
98*13093SRoger.Faulkner@Oracle.COM 	return (cnt ? cnt : -1);
99*13093SRoger.Faulkner@Oracle.COM }
100*13093SRoger.Faulkner@Oracle.COM 
101*13093SRoger.Faulkner@Oracle.COM ssize_t
getline(char ** _RESTRICT_KYWD lineptr,size_t * _RESTRICT_KYWD n,FILE * _RESTRICT_KYWD iop)102*13093SRoger.Faulkner@Oracle.COM getline(char **_RESTRICT_KYWD lineptr, size_t *_RESTRICT_KYWD n,
103*13093SRoger.Faulkner@Oracle.COM     FILE *_RESTRICT_KYWD iop)
104*13093SRoger.Faulkner@Oracle.COM {
105*13093SRoger.Faulkner@Oracle.COM 	return (getdelim(lineptr, n, '\n', iop));
106*13093SRoger.Faulkner@Oracle.COM }
107