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
|
%
% (c) The GRASP/AQUA Project, Glasgow University, 1994
%
\subsection[setBuffering.lc]{hSetBuffering Runtime Support}
\begin{code}
#include "rtsdefs.h"
#include "stgio.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#define SB_NB (0)
#define SB_LB (-1)
#define SB_BB (-2)
StgInt
setBuffering(fp, size)
StgAddr fp;
StgInt size;
{
int flags;
int input;
struct termios tio;
while ((flags = fcntl(fileno((FILE *) fp), F_GETFL)) < 0) {
if (errno != EINTR) {
cvtErrno();
stdErrno();
return -1;
}
}
flags &= O_ACCMODE;
input = flags == O_RDONLY || flags == O_RDWR;
switch (size) {
case SB_NB:
if (setvbuf((FILE *) fp, NULL, _IONBF, 0L) != 0) {
cvtErrno();
stdErrno();
return -1;
}
if (input && isatty(fileno((FILE *) fp))) {
/*
* Try to switch to CBREAK mode, or whatever they call it these days.
*/
if (tcgetattr(fileno((FILE *) fp), &tio) < 0) {
cvtErrno();
stdErrno();
return -1;
}
tio.c_lflag &= ~ICANON;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(fileno((FILE *) fp), TCSANOW, &tio) < 0) {
cvtErrno();
stdErrno();
return -1;
}
}
return 0;
break;
case SB_LB:
if (setvbuf((FILE *) fp, NULL, _IOLBF, BUFSIZ) != 0) {
cvtErrno();
stdErrno();
return -1;
}
break;
case SB_BB:
/*
* We should actually peek at the buffer size in the stat struct, if there
* is one. Something to occupy us later, when we're bored.
*/
size = BUFSIZ;
/* fall through */
default:
if (setvbuf((FILE *) fp, NULL, _IOFBF, size) != 0) {
cvtErrno();
stdErrno();
return -1;
}
break;
}
if (input && isatty(fileno((FILE *) fp))) {
/*
* Try to switch back to cooked mode.
*/
if (tcgetattr(fileno((FILE *) fp), &tio) < 0) {
cvtErrno();
stdErrno();
return -1;
}
tio.c_lflag |= ICANON;
if (tcsetattr(fileno((FILE *) fp), TCSANOW, &tio) < 0) {
cvtErrno();
stdErrno();
return -1;
}
}
return 0;
}
\end{code}
|