Last minute change.
[glibc.git] / mach / devstream.c
blobc35e548dd2f397f159dbdc03ef0391a1bd15e8ce
1 /* stdio on a Mach device port.
2 Translates \n to \r\n on output, echos and translates \r to \n on input.
4 Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
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.
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.
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. */
22 #include <stdio.h>
23 #include <mach.h>
24 #include <device/device.h>
25 #include <errno.h>
26 #include <string.h>
28 static int
29 input (FILE *f)
31 kern_return_t err;
32 char *buffer;
33 size_t to_read;
34 mach_msg_type_number_t nread;
35 char c;
37 if (f->__buffer == NULL)
39 buffer = &c;
40 to_read = 1;
42 else
44 buffer = f->__buffer;
45 to_read = f->__bufsize;
48 f->__eof = 0;
50 nread = to_read;
51 err = device_read_inband ((device_t) f->__cookie, 0, f->__target,
52 to_read, buffer, &nread);
54 if (err)
56 f->__error = 1;
57 f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
58 errno = err;
59 return EOF;
62 /* Echo it back. */
63 err = device_write_inband ((device_t) f->__cookie, 0, f->__target,
64 buffer, nread, (int *) &to_read);
66 /* Translate LF to CR. */
68 char *p;
69 for (p = memchr (buffer, '\r', nread); p;
70 p = memchr (p + 1, '\r', (buffer + nread) - (p + 1)))
71 *p = '\n';
74 if (f->__buffer == NULL)
75 return (unsigned char) c;
77 f->__get_limit = f->__buffer + nread;
78 f->__bufp = f->__buffer;
79 f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
80 return (unsigned char) *f->__bufp++;
84 #if 0
85 static void
86 output (FILE *f, int c)
88 inline void write_some (const char *p, size_t to_write)
90 kern_return_t err;
91 int wrote;
92 while (to_write > 0)
94 if (err = device_write ((device_t) f->__cookie, 0,
95 f->__target, (char *)p,
96 to_write, &wrote))
98 errno = err;
99 f->__error = 1;
100 break;
102 p += wrote;
103 to_write -= wrote;
104 f->__target += wrote;
108 if (f->__buffer != NULL)
110 if (f->__put_limit == f->__buffer)
112 /* Prime the stream for writing. */
113 f->__put_limit = f->__buffer + f->__bufsize;
114 f->__bufp = f->__buffer;
115 if (c != EOF)
117 *f->__bufp++ = (unsigned char) c;
118 c = EOF;
123 /* Write out the buffer. */
125 write_some (f->__buffer, f->__bufp - f->__buffer);
127 f->__bufp = f->__buffer;
130 if (c != EOF && !ferror (f))
132 if (f->__linebuf && (unsigned char) c == '\n')
134 static const char nl = '\n';
135 write_some (&nl, 1);
137 else
138 *f->__bufp++ = (unsigned char) c;
141 #endif
144 static void
145 output (FILE *f, int c)
147 void write_some (const char *p, size_t to_write)
149 kern_return_t err;
150 int wrote;
151 while (to_write > 0)
153 if (err = device_write_inband ((device_t) f->__cookie, 0,
154 f->__target, p, to_write, &wrote))
156 errno = err;
157 f->__error = 1;
158 break;
160 p += wrote;
161 to_write -= wrote;
162 f->__target += wrote;
165 void write_crlf (void)
167 static const char crlf[] = "\r\n";
168 write_some (crlf, 2);
171 if (f->__buffer == NULL)
173 /* The stream is unbuffered. */
175 if (c == '\n')
176 write_crlf ();
177 else if (c != EOF)
179 char cc = (unsigned char) c;
180 write_some (&cc, 1);
183 return;
186 if (f->__put_limit == f->__buffer)
188 /* Prime the stream for writing. */
189 f->__put_limit = f->__buffer + f->__bufsize;
190 f->__bufp = f->__buffer;
191 if (c != EOF)
193 *f->__bufp++ = (unsigned char) c;
194 c = EOF;
199 /* Search for newlines (LFs) in the buffer. */
201 char *start = f->__buffer, *p = start;
203 while (!ferror (f) && (p = memchr (p, '\n', f->__bufp - start)))
205 /* Found one. Replace it with a CR and write out through that CR. */
207 *p = '\r';
208 write_some (start, p + 1 - start);
210 /* Change it back to an LF; the next iteration will write it out
211 first thing. Start the next searching iteration one char later. */
213 start = p;
214 *p++ = '\n';
217 /* Write the remainder of the buffer. */
219 if (!ferror (f))
220 write_some (start, f->__bufp - start);
223 f->__bufp = f->__buffer;
225 if (c != EOF && !ferror (f))
227 if (f->__linebuf && (unsigned char) c == '\n')
228 write_crlf ();
229 else
230 *f->__bufp++ = (unsigned char) c;
234 static int
235 dealloc_ref (void *cookie)
237 if (mach_port_deallocate (mach_task_self (), (mach_port_t) cookie))
239 errno = EINVAL;
240 return -1;
242 return 0;
246 FILE *
247 mach_open_devstream (mach_port_t dev, const char *mode)
249 FILE *stream;
251 if (mach_port_mod_refs (mach_task_self (), dev, MACH_PORT_RIGHT_SEND, 1))
253 errno = EINVAL;
254 return NULL;
257 stream = fopencookie ((void *) dev, mode, __default_io_functions);
258 if (stream == NULL)
260 mach_port_deallocate (mach_task_self (), dev);
261 return NULL;
264 stream->__room_funcs.__input = input;
265 stream->__room_funcs.__output = output;
266 stream->__io_funcs.__close = dealloc_ref;
267 stream->__io_funcs.__seek = NULL; /* Cannot seek. */
268 stream->__io_funcs.__fileno = NULL; /* No corresponding POSIX.1 fd. */
269 stream->__seen = 1;
271 return stream;