Formerly ../mach/devstream.c.~7~
[kopensolaris-gnu/glibc.git] / mach / devstream.c
1 /* stdio on a Mach device port.
2    Translates \n to \r on output.
3
4 Copyright (C) 1992 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB.  If
19 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
20 Cambridge, MA 02139, USA.  */
21
22 #include <stdio.h>
23 #include <mach.h>
24 #include <device/device.h>
25 #include <errno.h>
26 #include <string.h>
27
28 static int
29 input (FILE *f)
30 {
31   kern_return_t err;
32   char *buffer;
33   size_t to_read, nread;
34   char c;
35
36   if (f->__buffer == NULL)
37     {
38       buffer = &c;
39       to_read = 1;
40     }
41   else
42     {
43       buffer = f->__buffer;
44       to_read = f->__bufsize;
45     }
46
47   f->__eof = 0;
48
49   if (err = device_read_inband ((device_t) f->__cookie, 0, f->__target,
50                                 to_read, buffer, &nread))
51     {
52       f->__error = 1;
53       f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
54       errno = err;
55       return EOF;
56     }
57
58   if (f->__buffer == NULL)
59     return (unsigned char) c;
60
61   f->__get_limit = f->__buffer + nread;
62   f->__bufp = f->__buffer;
63   f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
64   return (unsigned char) *f->__bufp++;
65 }
66
67 static void
68 output (FILE *f, int c)
69 {
70   kern_return_t err;
71   size_t to_write;
72   int wrote;
73   char *p;
74
75   if (f->__buffer == NULL)
76     {
77       /* The stream is unbuffered.  */
78
79       if (c != EOF)
80         {
81           char buf[2];
82           size_t n;
83           if (c == '\n')
84             {
85               buf[0] = '\r';
86               buf[1] = '\n';
87               n = 2;
88             }
89           else
90             {
91               buf[0] = (unsigned char) c;
92               n = 1;
93             }
94
95           if ((err = device_write_inband ((device_t) f->__cookie, 0,
96                                           f->__target, buf, n, &wrote)) ||
97               wrote != n)
98             {
99               errno = err;
100               f->__error = 1;
101             }
102
103           f->__target += n;
104         }
105       return;
106     }
107
108   if (f->__put_limit == f->__buffer)
109     {
110       f->__put_limit = f->__buffer + f->__bufsize;
111       f->__bufp = f->__buffer;
112       if (c != EOF)
113         {
114           *f->__bufp++ = (unsigned char) c;
115           c = EOF;
116         }
117     }
118
119   to_write = f->__bufp - f->__buffer;
120   p = f->__buffer;
121   while (1)
122     {
123       char *p2 = memchr (p, '\n', to_write);
124       if (p2 == NULL)
125         break;
126       *p2++ = '\r';
127       to_write -= p2 - p;
128       p = p2;
129     }
130
131   to_write = f->__bufp - f->__buffer;
132   p = f->__buffer;
133   while (to_write > 0)
134     {
135       if (err = device_write_inband ((device_t) f->__cookie, 0, f->__target,
136                                      p, to_write, &wrote))
137         {
138           errno = EIO;
139           f->__error = 1;
140           break;
141         }
142       p += wrote;
143       to_write -= wrote;
144       f->__target += wrote;
145     }
146
147   f->__bufp = f->__buffer;
148
149   if (c != EOF && !ferror (f))
150     {
151       if (f->__linebuf && (unsigned char) c == '\n')
152         {
153           static const char crlf[] = "\r\n";
154           if ((err = device_write_inband ((device_t) f->__cookie, 0,
155                                           f->__target, crlf, 2, &wrote)) ||
156               wrote != 2)
157             {
158               errno = EIO;
159               f->__error = 1;
160             }
161           else
162             f->__target += 2;
163         }
164       else
165         *f->__bufp++ = (unsigned char) c;
166     }
167 }
168
169 FILE *
170 mach_open_devstream (device_t dev, const char *mode)
171 {
172   FILE *stream = fopencookie ((void *) dev, mode, __default_io_functions);
173   if (stream == NULL)
174     return NULL;
175
176   stream->__room_funcs.__input = input;
177   stream->__room_funcs.__output = output;
178   stream->__io_funcs.__close = device_close;
179   stream->__seen = 1;
180
181   return stream;
182 }