1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <stdio.h>
22: #include <mach.h>
23: #include <device/device.h>
24: #include <errno.h>
25: #include <string.h>
26:
27:
28: static ssize_t
29: devstream_write (void *cookie, const char *buffer, size_t n)
30: {
31: const device_t dev = (device_t) cookie;
32:
33: int write_some (const char *p, size_t to_write)
34: {
35: kern_return_t err;
36: int wrote;
37: int thiswrite;
38:
39: while (to_write > 0)
40: {
41: thiswrite = to_write;
42: if (thiswrite > IO_INBAND_MAX)
43: thiswrite = IO_INBAND_MAX;
44:
45: if (err = device_write_inband (dev, 0, 0, p, thiswrite, &wrote))
46: {
47: errno = err;
48: return 0;
49: }
50: p += wrote;
51: to_write -= wrote;
52: }
53: return 1;
54: }
55: int write_crlf (void)
56: {
57: static const char crlf[] = "\r\n";
58: return write_some (crlf, 2);
59: }
60:
61:
62:
63: const char *start = buffer, *p;
64: while ((p = memchr (start, '\n', n)) != NULL)
65: {
66:
67:
68:
69: if ((p > start && !write_some (start, p - start))
70: || !write_crlf ())
71: return (start - buffer) ?: -1;
72:
73: n -= p + 1 - start;
74: start = p + 1;
75: }
76:
77:
78: if (write_some (start, n))
79: start += n;
80: return (start - buffer) ?: -1;
81: }
82:
83: static ssize_t
84: devstream_read (void *cookie, char *buffer, size_t to_read)
85: {
86: const device_t dev = (device_t) cookie;
87:
88: kern_return_t err;
89: mach_msg_type_number_t nread = to_read;
90:
91: err = device_read_inband (dev, 0, 0, to_read, buffer, &nread);
92: if (err)
93: {
94: errno = err;
95: return -1;
96: }
97:
98:
99: {
100: char *p;
101: for (p = memchr (buffer, '\r', nread); p;
102: p = memchr (p + 1, '\r', (buffer + nread) - (p + 1)))
103: *p = '\n';
104: }
105:
106:
107: (void) devstream_write (cookie, buffer, nread);
108:
109: return nread;
110: }
111:
112: static int
113: dealloc_ref (void *cookie)
114: {
115: if (mach_port_deallocate (mach_task_self (), (mach_port_t) cookie))
116: {
117: errno = EINVAL;
118: return -1;
119: }
120: return 0;
121: }
122:
123: #ifndef USE_IN_LIBIO
124: #define cookie_io_functions_t __io_functions
125: #define write __write
126: #define read __read
127: #define close __close
128: #endif
129:
130: FILE *
131: mach_open_devstream (mach_port_t dev, const char *mode)
132: {
133: FILE *stream;
134:
135: if (mach_port_mod_refs (mach_task_self (), dev, MACH_PORT_RIGHT_SEND, 1))
136: {
137: errno = EINVAL;
138: return NULL;
139: }
140:
141: stream = fopencookie ((void *) dev, mode,
142: (cookie_io_functions_t) { write: devstream_write,
143: read: devstream_read,
144: close: dealloc_ref });
145: if (stream == NULL)
146: {
147: mach_port_deallocate (mach_task_self (), dev);
148: return NULL;
149: }
150:
151: return stream;
152: }