1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
.TH PLUMB 3
.SH NAME
eplumb, plumbfree, plumbopen, plumbopenfid, plumbsend, plumbsendtofid, plumbsendtext, plumblookup, plumbpack, plumbpackattr, plumbaddattr, plumbdelattr, plumbrecv, plumbrecvfid, plumbunpack, plumbunpackpartial, plumbunpackattr, Plumbmsg \- plumb messages
.SH SYNOPSIS
.B #include <u.h>
.br
.B #include <libc.h>
.br
.B #include <plumb.h>
.PP
.ta \w'\fLPlumbattr* 'u
.PP
.B
int plumbopen(char *port, int omode)
.PP
.B
int plumbsend(int fd, Plumbmsg *m)
.PP
.B
int plumbsendtext(int fd, char *src, char *dst, char *wdir, char *data)
.PP
.B
void plumbfree(Plumbmsg *m)
.PP
.B
Plumbmsg* plumbrecv(int fd)
.PP
.B
char* plumbpack(Plumbmsg *m, int *np)
.PP
.B
Plumbmsg* plumbunpack(char *buf, int n)
.PP
.B
Plumbmsg* plumbunpackpartial(char *buf, int n, int *morep)
.PP
.B
char* plumbpackattr(Plumbattr *a)
.PP
.B
Plumbattr* plumbunpackattr(char *a)
.PP
.B
char* plumblookup(Plumbattr *a, char *name)
.PP
.B
Plumbattr* plumbaddattr(Plumbattr *a, Plumbattr *new)
.PP
.B
Plumbattr* plumbdelattr(Plumbattra *a, char *name)
.PP
.B
int eplumb(int key, char *port)
.PP
.B
#include <9pclient.h>
.PP
.B
CFid *plumbopenfid(char *port, int omode)
.PP
.B
Plumbmsg* plumbrecvfid(CFid *fid)
.PP
.B
int plumbsendtofid(CFid *fid, Plumbmsg *m)
.SH DESCRIPTION
These routines manipulate
.IR plumb (7)
messages, transmitting them, receiving them, and
converting them between text and these data structures:
.IP
.EX
.ta 6n +\w'\fLPlumbattr 'u +\w'ndata; 'u
typedef
struct Plumbmsg
{
char *src;
char *dst;
char *wdir;
char *type;
Plumbattr *attr;
int ndata;
char *data;
} Plumbmsg;
typedef
struct Plumbattr
{
char *name;
char *value;
Plumbattr *next;
} Plumbattr;
.EE
.PP
.I Plumbopen
opens the named plumb
.IR port ,
using
.IR open (3)
mode
.IR omode .
If
.I port
begins with a slash, it is taken as a literal file name;
otherwise
.I plumbopen
searches for the location of the
.IR plumber (4)
service and opens the port there.
.PP
For programs using the
.IR event (3)
interface,
.I eplumb
registers, using the given
.IR key ,
receipt of messages from the named
.IR port .
.PP
.I Plumbsend
formats and writes message
.I m
to the file descriptor
.IR fd ,
which will usually be the result of
.B plumbopen("send",
.BR OWRITE) .
.I Plumbsendtext
is a simplified version for text-only messages; it assumes
.B type
is
.BR text ,
sets
.B attr
to nil,
and sets
.B ndata
to
.BI strlen( data )\f1.
.PP
.I Plumbfree
frees all the data associated with the message
.IR m ,
all the components of which must therefore have been allocated with
.IR malloc (3).
.PP
.I Plumbrecv
returns the next message available on the file descriptor
.IR fd ,
or nil for error.
.PP
.I Plumbpack
encodes message
.I m
as a character string in the format of
.IR plumb (7) ,
setting
.BI * np
to the length in bytes of the string.
.I Plumbunpack
does the inverse, translating the
.I n
bytes of
.I buf
into a
.BR Plumbmsg .
.PP
.I Plumbunpackpartial
enables unpacking of messages that arrive in pieces.
The first call to
.I plumbunpackpartial
for a given message must be sufficient to unpack the header;
subsequent calls permit unpacking messages with long data sections.
For each call,
.I buf
points to the beginning of the complete message received so far, and
.I n
reports the total number of bytes received for that message.
If the message is complete, the return value will be as in
.IR plumbunpack .
If not, and
.I morep
is not null, the return value will be
.B nil
and
.BR * morep
will be set to the number of bytes remaining to be read for this message to be complete
(recall that the byte count is in the header).
Those bytes should be read by the caller, placed at location
.IB buf + n \f1,
and the message unpacked again.
If an error is encountered, the return value will be
.B nil
and
.BI * morep
will be zero.
.PP
.I Plumbpackattr
converts the list
.I a
of
.B Plumbattr
structures into a null-terminated string.
If an attribute value contains white space, quote characters, or equal signs,
the value will be quoted appropriately.
A newline character will terminate processing.
.I Plumbunpackattr
converts the null-terminated string
.I a
back into a list of
.I Plumbattr
structures.
.PP
.I Plumblookup
searches the
.B Plumbattr
list
.I a
for an attribute with the given
.I name
and returns the associated value.
The returned string is the original value, not a copy.
If the attribute has no value, the returned value will be the empty string;
if the attribute does not occur in the list at all, the value will be nil.
.PP
.I Plumbaddattr
appends the
.I new
.B Plumbattr
(which may be a list) to the attribute list
.IR a
and returns the new list.
.I Plumbattr
searches the list
.I a
for the first attribute with name
.I name
and deletes it from the list, returning the resulting list.
.I Plumbdelattr
is a no-op if no such attribute exists.
.PP
The file descriptor returned by
.I plumbopen
is created with
.I fsopenfd
(see
.IR 9pclient (3)),
which masks information about read and write errors.
This is acceptable for use in
.I plumbrecv
but not for
.IR plumbsend ,
which depends on seeing details of write errors.
.IR Plumbopenfid ,
.IR plumbrecvfid ,
and
.IR plumbsendtofid
provide an explicit interface to
.I lib9pclient
that preserves the exact error details.
.SH SOURCE
.B \*9/src/libplumb
.SH SEE ALSO
.IR plumb (1),
.IR event (3),
.IR plumber (4),
.IR plumb (7)
.SH DIAGNOSTICS
When appropriate, including when a
.I plumbsend
fails, these routine set
.IR errstr .
.SH BUGS
To avoid rewriting clients that use
.IR plumbsend ,
the call
.B plumbopen("send",
.B OWRITE)
returns a useless file descriptor
(it is opened to
.BR /dev/null ).
.I Plumbsend
looks for this particular file descriptor
and uses a static copy of the
.B CFid
instead.
|