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