1 |
/* Copyright (c) 1997 Regents of the University of California */ |
2 |
|
3 |
#ifndef lint |
4 |
static char SCCSid[] = "$SunId$ LBL"; |
5 |
#endif |
6 |
|
7 |
/* |
8 |
* I/O routines for GL display process. |
9 |
*/ |
10 |
|
11 |
#include "standard.h" |
12 |
#include <sys/uio.h> |
13 |
#include "gldisp.h" |
14 |
#include "gderrs.h" |
15 |
|
16 |
|
17 |
gdSendRequest(d, r) /* send a request across a connection */ |
18 |
GDconnect *d; |
19 |
GDrequest *r; |
20 |
{ |
21 |
unsigned char rbuf[10]; |
22 |
struct iovec iov[2]; |
23 |
/* encode header */ |
24 |
gdPutInt(rbuf, (int4)r->type, 2); |
25 |
gdPutInt(rbuf+2, r->id, 4); |
26 |
gdPutInt(rbuf+6, r->alen, 4); |
27 |
if (r->alen == 0) /* write header, null body */ |
28 |
write(d->fdout, rbuf, 10); |
29 |
else { /* write header and body */ |
30 |
iov[0].iov_base = (MEM_PTR)rbuf; |
31 |
iov[0].iov_len = 10; |
32 |
iov[1].iov_base = (MEM_PTR)r->args; |
33 |
iov[1].iov_len = r->alen; |
34 |
writev(d->fdout, iov, 2); |
35 |
} |
36 |
} |
37 |
|
38 |
|
39 |
GDrequest * |
40 |
gdRecvRequest(d) /* receive a request across a connection */ |
41 |
register GDconnect *d; |
42 |
{ |
43 |
register GDrequest *r; |
44 |
int type; |
45 |
int4 id, alen; |
46 |
unsigned char rbuf[10]; |
47 |
/* read header */ |
48 |
fread(rbuf, 1, 10, d->fpin); |
49 |
if (feof(d->fpin)) |
50 |
return(NULL); |
51 |
type = gdGetInt(rbuf, 2); |
52 |
id = gdGetInt(rbuf+2, 4); |
53 |
if (type < 0 | type > GD_NREQ) { |
54 |
gdSendError(d, GD_E_UNRECOG, id); |
55 |
return(NULL); |
56 |
} |
57 |
alen = gdGetInt(rbuf+6, 4); |
58 |
r = (GDrequest *)malloc(sizeof(GDrequest)-GD_ARG0+alen); |
59 |
if (r == NULL) { |
60 |
gdSendError(d, GD_E_NOMEMOR, id); |
61 |
return(NULL); |
62 |
} |
63 |
r->type = type; |
64 |
r->id = id; |
65 |
if ((r->alen = alen) > 0) { /* read arguments */ |
66 |
fread(r->args, 1, alen, d->fpin); |
67 |
if (feof(d->fpin)) { |
68 |
gdSendError(d, GD_E_ARGMISS, id); |
69 |
gdFree(r); |
70 |
return(NULL); |
71 |
} |
72 |
} |
73 |
if (type == GD_R_Error) { /* our error */ |
74 |
gdReportError(d, (int)gdGetInt(r->args, 2), id); |
75 |
gdFree(r); |
76 |
return(NULL); |
77 |
} |
78 |
return(r); /* success! */ |
79 |
} |
80 |
|
81 |
|
82 |
gdSendError(d, ec, id) /* send fatal error associated with a request */ |
83 |
GDconnect *d; |
84 |
int ec; |
85 |
int4 id; |
86 |
{ |
87 |
GDrequest rq; |
88 |
/* build error request */ |
89 |
rq.type = GD_R_Error; |
90 |
rq.id = id; |
91 |
gdPutInt(rq.args, (int4)ec, rq.alen=2); |
92 |
gdSendRequest(d, &rq); /* send it */ |
93 |
gdClose(d); /* all errors are fatal */ |
94 |
} |
95 |
|
96 |
|
97 |
gdReportError(d, ec, id) /* report fatal error to stderr */ |
98 |
GDconnect *d; |
99 |
int ec; |
100 |
int4 id; |
101 |
{ |
102 |
fprintf(stderr, "RequestId %d: %s\nConnection %d closed.\n", |
103 |
id, gdErrMsg[ec], d->cno); |
104 |
gdClose(d); /* all errors are fatal */ |
105 |
} |
106 |
|
107 |
|
108 |
GDconnect * |
109 |
gdOpen(inp, outp, x, y) /* establish a client/server connection */ |
110 |
char *inp, *outp; /* named pipes, currently */ |
111 |
int x, y; /* (0,0) for client */ |
112 |
{ |
113 |
static int nconnections = 0; |
114 |
register GDrequest *rp; |
115 |
GDrequest rq; |
116 |
register GDconnect *dp; |
117 |
|
118 |
dp = (GDconnect *)malloc(sizeof(GDconnect)); |
119 |
if (dp == NULL) { |
120 |
gdReportError(dp, GD_E_NOMEMOR, 0); |
121 |
return(NULL); |
122 |
} |
123 |
dp->cno = ++nconnections; |
124 |
if (!x) /* client opens to write first */ |
125 |
dp->fdout = open(outp, O_WRONLY); |
126 |
dp->fpin = fopen(inp, "r"); |
127 |
if (dp->fpin == NULL) |
128 |
goto connecterr; |
129 |
if (x) /* server opens to write second */ |
130 |
dp->fdout = open(outp, O_WRONLY); |
131 |
if (dp->fdout < 0) |
132 |
goto connecterr; |
133 |
if (x) { /* server sends resolution */ |
134 |
dp->xres = x; dp->yres = y; |
135 |
rq.type = GD_R_Init; |
136 |
rq.id = dp->cno; |
137 |
rq.alen = 4; |
138 |
gdPutInt(rq.args, (int4)x, 2); |
139 |
gdPutInt(rq.args+2, (int4)y, 2); |
140 |
gdSendRequest(dp, &rq); |
141 |
} else { /* client receives resolution */ |
142 |
rp = gdRecvRequest(dp); |
143 |
if (rp == NULL) |
144 |
return(NULL); |
145 |
if (rp->type != GD_R_Init) |
146 |
goto connecterr; |
147 |
dp->cno = rp->id; |
148 |
dp->xres = gdGetInt(rp->args, 2); |
149 |
dp->yres = gdGetInt(rp->args+2, 2); |
150 |
gdFree(rp); |
151 |
} |
152 |
return(dp); /* success! */ |
153 |
connecterr: |
154 |
gdReportError(dp, GD_E_CONNECT, 0); |
155 |
return(NULL); |
156 |
} |
157 |
|
158 |
|
159 |
gdClose(d) /* close a display server/client connection */ |
160 |
register GDconnect *d; |
161 |
{ |
162 |
if (d == NULL) return; |
163 |
close(d->fdout); |
164 |
fclose(d->fpin); |
165 |
gdFree(d); /* free associated memory */ |
166 |
} |
167 |
|
168 |
|
169 |
int4 |
170 |
gdGetInt(ab, n) /* get an n-byte integer from buffer ab */ |
171 |
register unsigned char *ab; |
172 |
register int n; /* maximum length 4 */ |
173 |
{ |
174 |
register int4 res; |
175 |
|
176 |
res = *ab&0x80 ? -1 : 0; /* sign extend */ |
177 |
while (n--) |
178 |
res = res<<8 | *ab++; |
179 |
return(res); |
180 |
} |
181 |
|
182 |
|
183 |
gdPutInt(ab, i, n) /* put an n-byte integer into buffer ab */ |
184 |
register unsigned char *ab; |
185 |
register int4 i; |
186 |
register int n; |
187 |
{ |
188 |
while (n--) |
189 |
*ab++ = i>>(n<<3) & 0xff; |
190 |
} |
191 |
|
192 |
|
193 |
double |
194 |
gdGetReal(ab) /* get a 5-byte real value from buffer ab */ |
195 |
char *ab; |
196 |
{ |
197 |
register int4 i; |
198 |
register double d; |
199 |
|
200 |
i = gdGetInt(ab, 4); |
201 |
d = (i + (i>0 ? .5 : -.5)) * (1./0x7fffffff); |
202 |
return(ldexp(d, (int)gdGetInt(ab+4,1))); |
203 |
} |
204 |
|
205 |
|
206 |
gdPutReal(ab, d) /* put a 5-byte real value to buffer ab */ |
207 |
unsigned char *ab; |
208 |
double d; |
209 |
{ |
210 |
int e; |
211 |
|
212 |
gdPutInt(ab, (int4)(frexp(d,&e)*0x7fffffff), 4); |
213 |
gdPutInt(ab+4, (int4)e, 1); |
214 |
} |