[project @ 1998-04-10 10:54:14 by simonm]
[ghc-hetmet.git] / ghc / lib / std / cbits / setBuffering.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: setBuffering.c,v 1.1 1998/04/10 10:54:51 simonm Exp $
5  *
6  * hSetBuffering Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 #ifdef HAVE_SYS_TYPES_H
13 #include <sys/types.h>
14 #endif
15
16 #ifdef HAVE_SYS_STAT_H
17 #include <sys/stat.h>
18 #endif
19
20 #ifdef HAVE_TERMIOS_H
21 #include <termios.h>
22 #endif
23
24 #ifdef HAVE_FCNTL_H
25 #include <fcntl.h>
26 #endif
27
28 #define SB_NB (0)
29 #define SB_LB (-1)
30 #define SB_BB (-2)
31
32 StgInt
33 setBuffering(StgAddr fp, StgInt size)
34 {
35     int flags;
36     int input;
37     struct termios tio;
38
39     while ((flags = fcntl(fileno((FILE *) fp), F_GETFL)) < 0) {
40         if (errno != EINTR) {
41             cvtErrno();
42             stdErrno();
43             return -1;
44         }
45     }
46     flags &= O_ACCMODE;
47     input = flags == O_RDONLY || flags == O_RDWR;
48
49     switch (size) {
50     case SB_NB:
51         if (setvbuf((FILE *) fp, NULL, _IONBF, 0L) != 0) {
52             cvtErrno();
53             stdErrno();
54             return -1;
55         }
56         if (input && isatty(fileno((FILE *) fp))) {
57
58             /*
59              * Try to switch to CBREAK mode, or whatever they call it these days.
60              */
61
62             if (tcgetattr(fileno((FILE *) fp), &tio) < 0) {
63                 cvtErrno();
64                 stdErrno();
65                 return -1;
66             }
67             tio.c_lflag &= ~ICANON;
68             tio.c_cc[VMIN] = 1;
69             tio.c_cc[VTIME] = 0;
70             if (tcsetattr(fileno((FILE *) fp), TCSANOW, &tio) < 0) {
71                 cvtErrno();
72                 stdErrno();
73                 return -1;
74             }
75         }
76         return 0;
77         break;
78     case SB_LB:
79         if (setvbuf((FILE *) fp, NULL, _IOLBF, BUFSIZ) != 0) {
80             cvtErrno();
81             stdErrno();
82             return -1;
83         }
84         break;
85     case SB_BB:
86
87         /*
88          * We should actually peek at the buffer size in the stat struct, if there
89          * is one.  Something to occupy us later, when we're bored.
90          */
91         size = BUFSIZ;
92         /* fall through */
93     default:
94         if (setvbuf((FILE *) fp, NULL, _IOFBF, size) != 0) {
95             cvtErrno();
96             stdErrno();
97             return -1;
98         }
99         break;
100     }
101     if (input && isatty(fileno((FILE *) fp))) {
102
103         /*
104          * Try to switch back to cooked mode.
105          */
106
107         if (tcgetattr(fileno((FILE *) fp), &tio) < 0) {
108             cvtErrno();
109             stdErrno();
110             return -1;
111         }
112         tio.c_lflag |= ICANON;
113         if (tcsetattr(fileno((FILE *) fp), TCSANOW, &tio) < 0) {
114             cvtErrno();
115             stdErrno();
116             return -1;
117         }
118     }
119     return 0;
120 }