File: new_system_call.man

package info (click to toggle)
libexplain 1.4.D001-17
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 42,248 kB
  • sloc: ansic: 156,043; makefile: 47,892; sh: 16,304; yacc: 1,898; awk: 245
file content (357 lines) | stat: -rw-r--r-- 13,093 bytes parent folder | download | duplicates (6)
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
.\"
.\" libexplain - Explain errno values returned by libc functions
.\" Copyright (C) 2008-2012 Peter Miller
.\" Written by Peter Miller <pmiller@opensource.org.au>
.\"
.\" This program is free software; you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation; either version 3 of the License, or
.\" (at your option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
.\" General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
.\"
.cp 0
.TH New\[hy]System\[hy]Call libexplain
.SH NAME
new system call \- How to add a new system call to libexplain
.XX "" "How to add a new system call to libexplain"
.SH DESCRIPTION
Adding a new system call to libexplain is both simple and tedious.
.PP
In this example, the system call is called \f[I]example\fP, and takes
two arguments, \f[I]pathname\fP and \f[I]flags\fP.
.RS
example(const char *pathname, int flags);
.RE
The libexplain library presents a C interface to the user, and explains
the C system calls.  It tries to avoid dynamic memory, and has several
helper functions and structures to make this simpler.
.SS Naming Conventions
In general, one function per file.  This gives the static linker more
opportunity to leave things out, thus producing smaller executables.
Exceptions to make use of \f[CR]static\fP common functions are
acceptable.
No savings for shared libraries, of course.
.PP
Functions that write their output into a
\f[I]explain_string_buffer_t\fP via the
\f[CR]explain_string_buffer_*\fP functions, all have a filename of
\f[CR]libexplain/buffer/\fP\f[I]something\fP.
.PP
Functions that write their output to a \f[I]message\fP,
\f[I]message_size\fP pair have a \f[CR]message\fP path component in
their file name.
.PP
Functions that accept an \f[I]errno\fP value as an argument have an
\f[CR]errno\fP path component in their file name, called \f[CR]errnum\fP.
If a function has
both a buffer and an errno, the buffer comes first, both in the argument
list, and the file's name.  If a function has both a message+size and
an errno, the message comes first, both in the argument list, and the
file's name.
.\" ------------------------------------------------------------------------
.SH MODIFIED FILES
Note that the \f[I]codegen\fP command does most of the work for
you.  Pass it the function prototype (in single quotes) and it will do
most of the work.
.PP
.RS
.ft CW
.nf
$ \f[CB]bin/codegen '\fP\f[CI]example(const char *pathname, \
int flags);\fP\f[CB]'\fP
creating catalogue/\f[CI]example\fP
$
.fi
.ft R
.RE
.PP
then you mast edit the \f[CW]catalogue/\fP\f[CI]example\fP file to
make any adjustment necessary.
This file is then used to do the boring stuff:
.RS
.nf
.ft CW
$ \f[CB]bin/codegen\fP \f[CI]example\fP
creating explain/syscall/\f[CI]example\fP.c
creating explain/syscall/\f[CI]example\fP.h
creating libexplain/buffer/errno/\f[CI]example\fP.c
creating libexplain/buffer/errno/\f[CI]example\fP.h
creating libexplain/\f[CI]example\fP.c
creating libexplain/\f[CI]example\fP.h
creating libexplain/\f[CI]example\f[P]_or_die.c
creating man/man3/explain_\f[CI]example\fP.3
creating man/man3/explain_\f[CI]example\f[P]_or_die.3
creating test_\f[CI]example\fP/main.c
modify explain/syscall.c
modify libexplain/libexplain.h
modify man/man1/explain.1
modify man/man3/explain.3
$
.ft R
.fi
.RE
.PP
All of these files have been added to the Aegis change set.
Edit the last 4 to place the appended line in their correct positions
within the files, respecting the symbol sort ordering of each file.
.\"
.SS libexplain/libexplain.h
The \f[CR]libexplain/libexplain.h\fP include file defines the
user API.  It, and any files it includes,
are installed into \f[CR]$(prefix)/include\fP by \f[I]make install\fP.
.PP
This file needs another include line.
This means that the entire API is available to the user as a
single include directive.
.PP
.RS
\f[CR]#include <libexplain/\fP\f[I]example\fP\f[CR].h>\fP
.RE
.PP
This file is also used to decide which files are installed by the \f[I]make
install\fP command.
.PP
Take care that none of those files, directly or indirectly, wind
up including \f[CR]libexplain/config.h\fP which is generated by the
\f[I]configure\fP script, and has \f[B]no\fP namespace protection.
.PP
This means you can't \f[CR]#include <stddef.h>\fP, or use any of the
types it defines, because on older systems \f[I]configure\fP works quite
hard to cope with its absence.
Ditto \f[CR]<unistd.h>\fP and \f[CR]<sys/types.h>\fP.
.\"
.SS explain/main.c
Include the include file for the new function,
and add the function to the table.
.\"
.SS man/man1/explain.1
Add a description of the new system call.
.\"
.SS man/man3/libexplain.3
Add your new man pages,
man/man3/explain_\f[I]example\fP.3 and
man/man3/explain_\f[I]example\f[P]_or_die.3,
to the list.
Keep the list sorted.
.\" ------------------------------------------------------------------------
.SH NEW FILES
Note that the \f[I]codegen\fP command does most of the work for
you.  Pass it the function prototype (in single quotes) and it will do
most of the work.
.\"
.SS libexplain/buffer/errno/\f[I]example\fP.c
The central file for adding a new example
is \f[CR]libexplain/buffer/errno/\fP\f[I]example\fP\f[CR].c\fP
Which defines a function
.RS
\f[CR]void explain_buffer_errno_\fP\f[I]example\fP\f[CR](\
explain_string_buffer_t *buffer, int errnum, \fP\fIconst char *pathname,
int flags\fP\f[CR]);\fP
.RE
The \f[CR]errnum\fP argument holds the \f[I]errno\fP value.
Note that calling \f[I]errno\fP usually has problems because many
systems have \f[I]errno\fP as a macro, which makes the compiler barf,
and because there are times you want access to the global \f[I]errno\fP,
and having it shadowed by the argument is a nuisance.
.PP
This function writes its output into the buffer via the
\f[CR]explain_string_buffer_printf\fP, \f[I]etc\fP, functions.
First the argument list is reprinted.
.PP
The \f[CR]explain_string_buffer_puts_quoted\fP
function should be used to print pathnames,
because it uses full C quoting and escape sequences.
.PP
If an argument is a file descriptor, it should be called \f[I]fildes\fP,
short for \[lq]file descriptor\[rq].
On systems capable of it, the file descriptor can be mapped to a pathname
using the \f[CR]explain_buffer_fildes_to_pathname\fP function.  This
makes explanations for system calls like \f[I]read\fP and \f[I]write\fP
much more informative.
.PP
Next comes a switch on the errnum value,
and additional explanation is given for each errno value documented (or
sometimes undocumented)
for that system call.
Copy\[hy]and\[hy]paste of the man page is often useful as a basis for the text
of the explanation, but be sure it is open source documentation, and
not Copyright proprietary text.
.PP
Don't forget to check the existing \f[CW]libexplain/buffer/e*.h\fP
files for pre\[hy]canned explanations for common errors.
Some pre\[hy]canned explanations include
.TS
tab(;);
l l.
EACCES;explain_buffer_eacces
EADDRINUSE;explain_buffer_eaddrinuse
EAFNOSUPPORT;explain_buffer_eafnosupport
EBADF;explain_buffer_ebadf
EFAULT;explain_buffer_efault
EFBIG;explain_buffer_efbig
EINTR;explain_buffer_eintr
EINVAL;explain_buffer_einval_vague, \f[I]etc\fP
EIO;explain_buffer_eio
ELOOP;explain_buffer_eloop
EMFILE;explain_buffer_emfile
EMLINK;explain_buffer_emlink
ENAMETOOLONG;explain_buffer_enametoolong
ENFILE;explain_buffer_enfile
ENOBUFS;explain_buffer_enobufs
ENOENT;explain_buffer_enoent
ENOMEM;explain_buffer_enomem
ENOTCONN;explain_buffer_enotconn
ENOTDIR;explain_buffer_enotdir
ENOTSOCK;explain_buffer_enotsock
EROFS;explain_buffer_erofs
ETXTBSY;explain_buffer_etxtbsy
EXDEV;explain_buffer_exdev
.TE
.\"
.SS libexplain/buffer/errno/example.h
This file holds the function prototype
for the above function definition.
.\"
.SS libexplain/example.h
The file contains the user visible API for the \f[I]example\fP system call.
There are five function prototypes declared in this file:
.RS
\f[CR]void explain_\fP\f[I]example\fP\f[CR]_or_die(\
\fP\fIconst char *pathname, int flags\fP\f[CR]);\fP
.br
\f[CR]void explain_\fP\f[I]example\fP\f[CR](
\fP\fIconst char *pathname, int flags\fP\f[CR]);\fP
.br
\f[CR]void explain_errno_\fP\f[I]example\fP\f[CR](\
int errnum, \fP\fIconst char *pathname, int flags\fP\f[CR]);\fP
.br
\f[CR]void explain_message_\fP\f[I]example\fP\f[CR](\
const char *message, int message_size,
\fP\fIconst char *pathname, int flags\fP\f[CR]);\fP
.br
\f[CR]void explain_message_errno_\fP\f[I]example\fP\f[CR](\
const char *message, int message_size,
int errnum, \fP\fIconst char *pathname, int flags\fP\f[CR]);\fP
.RE
The function prototypes for these appear in the
\f[CR]libexplain/\f[I]example\fP.h include file.
.PP
Each function prototype shall be accompanied by thorough Doxygen style
comments.  These are extracted and placed on the web site.
.PP
The buffer functions are \f[B]never\fP part of the user visible API.
.\"
.SS libexplain/\f[I]example\f[P]_or_die.c
One function per file,
\f[CR]explain_\fP\f[I]example\fP\f[CR]_or_die\fP in this case.
It simply calls \f[I]example\fP and then, if fails,
\f[CR]explain_\fP\f[I]example\fP to print why, and then exit(EXIT_FAILURE).
.\"
.SS libexplain/example.c
One function per file,
\f[CR]explain_\fP\f[I]example\fP in this case.
It simply calls \f[CR]explain_errno_\fP\f[I]example\fP to pass in the
global \f[I]errno\fP value.
.\"
.SS libexplain/errno/example.c
One function per file,
\f[CR]explain_errno_\fP\f[I]example\fP in this case.
It calls \f[CR]explain_message_errno_\fP\f[I]example\fP,
using the
\f[CR]<libexplain/global_message_buffer.h>\fP to hold the string.
.\"
.SS libexplain/message/example.c
One function per file,
\f[CR]explain_message_\fP\f[I]example\fP in this case.
It simply calls \f[CR]explain_message_errno_\fP\f[I]example\fP to
pass in the global \f[I]errno\fP value.
.\"
.SS libexplain/message/errno/example.c
One function per file,
\f[CR]explain_message_errno_\fP\f[I]example\fP in this case.
It declares and initializes a \f[CR]explain_string_buffer_t\fP instance,
which ensures that the message buffer will not be exceeded,
and passes that buffer to the
\f[CR]explain_buffer_errno_\fP\f[I]example\fP function.
.\"
.SS man/man3/explain_example.3
This file also documents the error explanations functions,
except \f[CR]explain_\fP\f[I]example\fP\f[CW]_or_dir\fP.
Use the same text as you did in \f[CR]libexplain/\fP\f[I]example\fP\f[CR].h\fP
.\"
.SS man/man3/explain_example_or_die.3
This file also documents the helper function.
Use the same text as you did in \f[CR]libexplain/\fP\f[I]example\fP\f[CR].h\fP
.\"
.SS explain/example.c
Glue to turn the command line into arguments to a call to
\f[CR]explain_\fP\f[I]example\fP
.\"
.SS explain/example.h
Function prototype for the above.
.\"
.SS test_example/main.c
This program should call \f[CR]explain_\fP\f[I]explain\fP\f[CW]_or_die\fP.
.\" ------------------------------------------------------------------------
.SH NEW IOCTL REQUESTS
Each different \f[I]ioctl\fP(2) request is, in effect, yet another
system call.  Except that they all have appallingly bad type safety.  I
have seen fugly C++ classes with less overloading than \f[I]ioctl\fP(2).
.TP
libexplain/iocontrol/request_by_number.c
This file has one include line for each \f[I]ioctl\fP(2) request.
There is a \f[CW]table\fP array that contains a pointer to the
explain_iocontrol_t variable declared in the include file (see next).
Keep both sets of lines sorted alphabetically,
it makes it easier to detect duplicates.
.TP
libexplain/iocontrol/\f[I]name\fP.h
Where \f[I]name\fP is the name of the \f[I]ioctl\fP(2) request in lower
case.  This declares an global const variable describing how to handle
it.
.TP
libexplain/iocontrol/\f[I]name\fP.c
This defines the above global variable, and defines any static glue
functions necessary to print a representation of it.
You will probably have to read the kernel source to discover the errors
the ioctl can return, and what causes them, in order to write the
explanation function; they are almost never described in the man pages.
.\" ------------------------------------------------------------------------
.SH TESTS
Write at least one separate test for each case in the errnum switch.
.SH Debian Notes
You can check that the Debian stuff builds by using
.RS
.nf
apt\[hy]get install pbuilder
pbuiler create
pbuilder login
.fi
.RE
now copy the files from \f[I]web\[hy]site/debian/\fP into the chroot
.RS
.nf
cd libexplain\-*
dpkg\-checkbuilddeps
apt\-get install \f[I]what dpkg\-checkbuilddeps said\fP
apt\-get install devscripts
debuild
.fi
.RE
This should report success.
.SH COPYRIGHT
.if n .ds C) (C)
.if t .ds C) \(co
libexplain version \*(v)
.br
Copyright \*(C) 2008 Peter Miller
.SH AUTHOR
Written by Peter Miller <pmiller@opensource.org.au>
.\" vim: set ts=8 sw=4 et :