forked from unpbook/unpv13e
-
Notifications
You must be signed in to change notification settings - Fork 0
/
readline.c
85 lines (73 loc) · 1.53 KB
/
readline.c
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
/* include readline1 */
#include "unpthread.h"
static pthread_key_t rl_key;
static pthread_once_t rl_once = PTHREAD_ONCE_INIT;
static void
readline_destructor(void *ptr)
{
free(ptr);
}
static void
readline_once(void)
{
Pthread_key_create(&rl_key, readline_destructor);
}
typedef struct {
int rl_cnt; /* initialize to 0 */
char *rl_bufptr; /* initialize to rl_buf */
char rl_buf[MAXLINE];
} Rline;
/* end readline1 */
/* include readline2 */
static ssize_t
my_read(Rline *tsd, int fd, char *ptr)
{
if (tsd->rl_cnt <= 0) {
again:
if ( (tsd->rl_cnt = read(fd, tsd->rl_buf, MAXLINE)) < 0) {
if (errno == EINTR)
goto again;
return(-1);
} else if (tsd->rl_cnt == 0)
return(0);
tsd->rl_bufptr = tsd->rl_buf;
}
tsd->rl_cnt--;
*ptr = *tsd->rl_bufptr++;
return(1);
}
ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
size_t n, rc;
char c, *ptr;
Rline *tsd;
Pthread_once(&rl_once, readline_once);
if ( (tsd = pthread_getspecific(rl_key)) == NULL) {
tsd = Calloc(1, sizeof(Rline)); /* init to 0 */
Pthread_setspecific(rl_key, tsd);
}
ptr = vptr;
for (n = 1; n < maxlen; n++) {
if ( (rc = my_read(tsd, fd, &c)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
*ptr = 0;
return(n - 1); /* EOF, n - 1 bytes read */
} else
return(-1); /* error, errno set by read() */
}
*ptr = 0;
return(n);
}
/* end readline2 */
ssize_t
Readline(int fd, void *ptr, size_t maxlen)
{
ssize_t n;
if ( (n = readline(fd, ptr, maxlen)) < 0)
err_sys("readline error");
return(n);
}