]>
Commit | Line | Data |
---|---|---|
42fb6204 JDF |
1 | <sect1 id="ov-ex-win"> |
2 | <title>Quick Start Guide for those more experienced with Windows</title> | |
3 | <para> | |
4 | If you are new to the world of UNIX, you may find it difficult to | |
5 | understand at first. This guide is not meant to be comprehensive, | |
6 | so we recommend that you use the many available Internet resources | |
7 | to become acquainted with UNIX basics (search for "UNIX basics" or | |
8 | "UNIX tutorial"). | |
9 | </para> | |
10 | <para> | |
11 | To install a basic Cygwin environment, run the | |
12 | <command>setup.exe</command> program and click <literal>Next</literal> | |
13 | at each page. The default settings are correct for most users. If you | |
14 | want to know more about what each option means, see | |
c98b30ea | 15 | <xref linkend="internet-setup"></xref>. Use <command>setup.exe</command> |
42fb6204 JDF |
16 | any time you want to update or install a Cygwin package. If you are |
17 | installing Cygwin for a specific purpose, use it to install the tools | |
18 | that you need. For example, if you want to compile C++ programs, you | |
19 | need the <systemitem>gcc-g++</systemitem> package and probably a text | |
20 | editor like <systemitem>nano</systemitem>. When running | |
21 | <command>setup.exe</command>, clicking on categories and packages in the | |
22 | package installation screen will provide you with the ability to control | |
23 | what is installed or updated. | |
24 | </para> | |
25 | <para> | |
26 | Another option is to install everything by clicking on the | |
27 | <literal>Default</literal> field next to the <literal>All</literal> | |
28 | category. However, be advised that this will download and install | |
29 | several hundreds of megabytes of software to your computer. The best | |
30 | plan is probably to click on individual categories and install either | |
31 | entire categories or packages from the categories themselves. | |
ede7692f JDF |
32 | After installation, you can find Cygwin-specific documentation in |
33 | the <literal>/usr/share/doc/Cygwin/</literal> directory. | |
42fb6204 JDF |
34 | </para> |
35 | <para> | |
85f1119b CV |
36 | Developers coming from a Windows background will be able to write |
37 | console or GUI executables that rely on the Microsoft Win32 API instead | |
38 | of Cygwin using the -mno-cygwin option to GCC. The <command>-shared</command> | |
39 | option allows to write Windows Dynamically Linked Libraries (DLLs). The | |
40 | resource compiler <command>windres</command> is also provided. | |
42fb6204 JDF |
41 | </para> |
42 | </sect1> | |
1fd5e000 | 43 | |
42fb6204 JDF |
44 | <sect1 id="ov-ex-unix"> |
45 | <title>Quick Start Guide for those more experienced with UNIX</title> | |
46 | <para> | |
47 | If you are an experienced UNIX user who misses a powerful command-line | |
48 | environment, you will enjoy Cygwin. Note that there are some workarounds | |
49 | that cause Cygwin to behave differently than most UNIX-like operating | |
50 | systems; these are described in more detail in | |
c98b30ea | 51 | <xref linkend="using-effectively"></xref>. |
42fb6204 JDF |
52 | </para> |
53 | <para> | |
a5032b78 CF |
54 | Use the graphical command <command>setup.exe</command> any time you want |
55 | to update or install a Cygwin package. This program must be run | |
56 | manually every time you want to check for updated packages since Cygwin | |
57 | does not currently include a mechanism for automatically detecting | |
58 | package updates. | |
59 | </para> | |
60 | <para> | |
61 | By default, <command>setup.exe</command> only installs a minimal subset of | |
62 | packages. Add any other packages by clicking on the <literal>+</literal> | |
63 | next to the Category name and then select the package from the displayed | |
64 | list. You may search for specfic tools by using the | |
65 | <ulink url="http://cygwin.com/packages/">Setup Package Search</ulink> | |
66 | at the Cygwin web site. | |
67 | </para> | |
68 | <para> | |
69 | For more information about what each option in | |
70 | <command>setup.exe</command> means, see <xref | |
71 | linkend="internet-setup"></xref>. | |
42fb6204 JDF |
72 | </para> |
73 | <para> | |
74 | Another option is to install everything by clicking on the | |
75 | <literal>Default</literal> field next to the <literal>All</literal> | |
76 | category. However, be advised that this will download and install | |
77 | several hundreds of megabytes of software to your computer. The best | |
78 | plan is probably to click on individual categories and install either | |
79 | entire categories or packages from the categories themselves. | |
ede7692f JDF |
80 | After installation, you can find Cygwin-specific documentation in |
81 | the <literal>/usr/share/doc/Cygwin/</literal> directory. | |
42fb6204 JDF |
82 | </para> |
83 | <para> | |
84 | Developers coming from a UNIX background will find a set of utilities | |
1fd5e000 CF |
85 | they are already comfortable using, including a working UNIX shell. The |
86 | compiler tools are the standard GNU compilers most people will have previously | |
87 | used under UNIX, only ported to the Windows host. Programmers wishing to port | |
85f1119b | 88 | UNIX software to Windows NT will find that the Cygwin library provides |
1fd5e000 | 89 | an easy way to port many UNIX packages, with only minimal source code |
42fb6204 JDF |
90 | changes. |
91 | </para> | |
1fd5e000 | 92 | |
1fd5e000 CF |
93 | </sect1> |
94 | ||
42fb6204 JDF |
95 | <sect1 id="highlights"><title>Highlights of Cygwin Functionality</title> |
96 | ||
1fd5e000 CF |
97 | <sect2 id="ov-hi-intro"><title>Introduction</title> <para>When a binary linked |
98 | against the library is executed, the Cygwin DLL is loaded into the | |
99 | application's text segment. Because we are trying to emulate a UNIX kernel | |
100 | which needs access to all processes running under it, the first Cygwin DLL to | |
85f1119b CV |
101 | run creates shared memory areas and global synchronization objects that other |
102 | processes using separate instances of the DLL can access. This is used to keep track of open file descriptors and to assist fork and exec, among other | |
103 | purposes. Every process also has a per_process structure that contains | |
1fd5e000 CF |
104 | information such as process id, user id, signal masks, and other similar |
105 | process-specific information.</para> | |
106 | ||
85f1119b CV |
107 | <para>The DLL is implemented as a standard DLL in the Win32 subsystem. Under |
108 | the hood it's using the Win32 API, as well as the native NT API, where | |
109 | appropriate.</para> | |
110 | ||
111 | <para>Because processes run under the standard Win32 subsystem, they | |
1fd5e000 CF |
112 | can access both the UNIX compatibility calls provided by Cygwin as well as |
113 | any of the Win32 API calls. This gives the programmer complete flexibility in | |
114 | designing the structure of their program in terms of the APIs used. For | |
115 | example, they could write a Win32-specific GUI using Win32 API calls on top of | |
116 | a UNIX back-end that uses Cygwin.</para> | |
117 | ||
85f1119b CV |
118 | <para>The native NT API is used mainly for speed, as well as to access |
119 | NT capabilities which are useful to implement certain POSIX features, but | |
120 | are hidden to the Win32 API. | |
121 | </para> | |
1fd5e000 | 122 | |
85f1119b CV |
123 | <para>Due to some restrictions in Windows, it's not always possible |
124 | to strictly adhere to existing UNIX standards like POSIX.1. Fortunately | |
125 | these are mostely border cases.</para> | |
1fd5e000 CF |
126 | </sect2> |
127 | ||
128 | <sect2 id="ov-hi-perm"><title>Permissions and Security</title> | |
129 | <para>Windows NT includes a sophisticated security model based on Access | |
85f1119b CV |
130 | Control Lists (ACLs). Cygwin maps Win32 file ownership and permissions to |
131 | ACLs by default, on file systems supporting them (usually NTFS). Solaris | |
132 | style ACLs and accompanying function calls are also supported. | |
133 | The chmod call maps UNIX-style permissions back to the Win32 equivalents. | |
134 | Because many programs expect to be able to find the | |
135 | <filename>/etc/passwd</filename> and | |
136 | <filename>/etc/group</filename> files, we provide <ulink | |
137 | url="http://cygwin.com/cygwin-ug-net/using-utils.html">utilities</ulink> | |
aba37361 JDF |
138 | that can be used to construct them from the user and group information |
139 | provided by the operating system.</para> | |
1fd5e000 | 140 | |
85f1119b CV |
141 | <para>Users with Administrator rights are permitted to chown files. |
142 | With version 1.1.3 Cygwin introduced a mechanism for setting real and | |
143 | effective UIDs. This is described in <xref linkend="ntsec"></xref>. As | |
144 | of version 1.5.13, the Cygwin developers are not aware of any feature in | |
145 | the Cygwin DLL that would allow users to gain privileges or to access | |
146 | objects to which they have no rights under Windows. However there is no | |
147 | guarantee that Cygwin is as secure as the Windows it runs on. Cygwin | |
148 | processes share some variables and are thus easier targets of denial of | |
149 | service type of attacks. | |
aba37361 | 150 | </para> |
1fd5e000 | 151 | |
1fd5e000 CF |
152 | </sect2> |
153 | ||
154 | <sect2 id="ov-hi-files"><title>File Access</title> <para>Cygwin supports | |
85f1119b CV |
155 | both POSIX- and Win32-style paths, using either forward or back slashes as the |
156 | directory delimiter. Paths coming into the DLL are translated from POSIX to | |
157 | native NT as needed. From the application perspective, the file system is | |
158 | a POSIX-compliant one. The implementation details are safely hidden in the | |
159 | Cygwin DLL. UNC pathnames (starting with two slashes) are supported for | |
160 | network paths.</para> | |
161 | ||
162 | <para>Since version 1.7.0, the layout of this POSIX view of the Windows file | |
163 | system space is stored in the <filename>/etc/fstab</filename> file. Actually, | |
164 | there is a system-wide <filename>/etc/fstab</filename> file as well as a | |
165 | user-specific fstab file <filename>/etc/fstab.d/${USER}</filename>.</para> | |
166 | ||
167 | <para>At startup the DLL has to find out where it can find the | |
168 | <filename>/etc/fstab</filename> file. The mechanism used for this is simple. | |
169 | First it retrieves it's own path, for instance | |
170 | <filename>C:\Cygwin\bin\cygwin1.dll</filename>. From there it deduces | |
171 | that the root path is <filename>C:\Cygwin</filename>. So it looks for the | |
172 | <filename>fstab</filename> file in <filename>C:\Cygwin\etc\fstab</filename>. | |
173 | The layout of this file is very similar to the layout of the | |
174 | <filename>fstab</filename> file on Linux. Just instead of block devices, | |
175 | the mount points point to Win32 paths. An installation with | |
176 | <command>setup.exe</command> installs a <filename>fstab</filename> file by | |
177 | default, which can easily be changed using the editor of your choice.</para> | |
178 | ||
179 | <para>In addition to selecting the root partition, the | |
180 | <filename>fstab</filename> file allows mounting arbitrary Win32 paths into | |
181 | the POSIX file system space. A special case is the so-called cygdrive prefix. | |
182 | It's the path under which every available drive in the system is mounted | |
183 | under its drive letter. The default value is <filename>/cygdrive</filename>, | |
184 | so you can access the drives as <filename>/cygdrive/c</filename>, | |
185 | <filename>/cygdrive/d</filename>, etc... The cygdrive prefix can be set to | |
186 | some other value (<filename>/mnt</filename> for instance) in the | |
187 | <filename>fstab</filename> file(s).</para> | |
1fd5e000 CF |
188 | |
189 | <para>The library exports several Cygwin-specific functions that can be used | |
190 | by external programs to convert a path or path list from Win32 to POSIX or vice | |
191 | versa. Shell scripts and Makefiles cannot call these functions directly. | |
85f1119b CV |
192 | Instead, they can do the same path translations by executing the |
193 | <command>cygpath</command> utility program that we provide with Cygwin.</para> | |
194 | ||
195 | <para>Win32 applications handle filenames case preserving but case | |
196 | insensitive. Cygwin supports case sensitivity on file systems supporting | |
197 | that. Since Windows XP, the OS only supports case sensitivity when a | |
198 | specific registry value is changed. Therefore case sensitivity is not | |
199 | the default usually.</para> | |
200 | ||
201 | <para>Symbolic links are not present and supported on Windows up to and | |
202 | including Windows Server 2003 R2. Only starting with Windows Vista, | |
203 | native symlinks are available. Unfortunately they are strangly implemented | |
204 | and so not very useful for a POSIX emulation layer. Consequentially | |
205 | Cygwin recognizes them as symlinks but does not create them.</para> | |
206 | ||
207 | <para>Symbolic links are potentially created in two different ways. | |
208 | The file style symlinks are files containing a magic cookie followed by | |
209 | the path to which the link points. They are marked with the System DOS | |
210 | attribute so that only files with that attribute have to be read to | |
211 | determine whether or not the file is a symbolic link. The shortcut style | |
212 | symlinks are Windows shortcut files with a special header and the | |
213 | Readonly DOS attribute set. The advantage of file symlinks is speed, | |
214 | the advantage of shortcut symlinks is the fact that they can be utilized | |
215 | by non-Cygwin Win32 tools as well.</para> | |
216 | ||
217 | <para>Hard links are fully supported on NTFS and NFS file systems. On FAT | |
218 | and some other file systems, the call falls back to simply copying the file, | |
219 | a strategy that works in many cases.</para> | |
220 | ||
221 | <para>On file systems which don't support unique persistent file IDs (FAT, | |
222 | older Samba shares) the inode number for a file is calculated by hashing its | |
223 | full Win32 path. The inode number generated by the stat call always matches | |
224 | the one returned in <literal>d_ino</literal> of the <literal>dirent</literal> | |
225 | structure. It is worth noting that the number produced by this method is not | |
226 | guaranteed to be unique. However, we have not found this to be a significant | |
227 | problem because of the low probability of generating a duplicate inode number. | |
228 | </para> | |
229 | ||
230 | <para><function>chroot(2)</function> is supported since Cygwin 1.1.3. | |
231 | However, chroot is not a concept known by Windows. This implies some | |
232 | restrictions. First of all, the <function>chroot</function> call isn't a | |
233 | privileged call. Each user may call it. Second, the chroot environment | |
234 | isn't safe against native windows processes. If you want to support a | |
235 | chroot environment as, for example, by allowing an anonymous ftp with | |
236 | restricted access, you'll have to care that only native Cygwin applications | |
237 | are accessible inside of the chroot environment. Since those applications | |
238 | are only using the Cygwin POSIX API to access the file system their access | |
239 | can be restricted as it is intended. This includes not only POSIX paths but | |
240 | Win32 paths containing drive letter and/or backslashes as well as UNC paths | |
241 | (<filename>//server/share</filename> or <filename>\\server\share</filename>). | |
242 | </para> | |
1fd5e000 CF |
243 | </sect2> |
244 | ||
245 | <sect2 id="ov-hi-textvsbinary"><title>Text Mode vs. Binary Mode</title> | |
246 | <para>Interoperability with other Win32 programs such as text editors was | |
63928f60 | 247 | critical to the success of the port of the development tools. Most Red Hat |
1fd5e000 CF |
248 | customers upgrading from the older DOS-hosted toolchains expected the new |
249 | Win32-hosted ones to continue to work with their old development | |
250 | sources.</para> | |
251 | ||
252 | <para>Unfortunately, UNIX and Win32 use different end-of-line terminators in | |
253 | text files. Consequently, carriage-return newlines have to be translated on | |
c3405ba9 | 254 | the fly by Cygwin into a single newline when reading in text mode.</para> |
1fd5e000 CF |
255 | |
256 | <para>This solution addresses the compatibility requirement at the expense of | |
257 | violating the POSIX standard that states that text and binary mode will be | |
258 | identical. Consequently, processes that attempt to lseek through text files can | |
259 | no longer rely on the number of bytes read as an accurate indicator of position | |
260 | in the file. For this reason, the CYGWIN environment variable can be | |
261 | set to override this behavior.</para> | |
262 | </sect2> | |
263 | ||
264 | <sect2 id="ov-hi-ansiclib"><title>ANSI C Library</title> | |
63928f60 | 265 | <para>We chose to include Red Hat's own existing ANSI C library |
1fd5e000 CF |
266 | "newlib" as part of the library, rather than write all of the lib C |
267 | and math calls from scratch. Newlib is a BSD-derived ANSI C library, | |
268 | previously only used by cross-compilers for embedded systems | |
85f1119b CV |
269 | development. Other functions, which are not supported by newlib have |
270 | been added to the Cygwin sources using BSD implementations as much as | |
271 | possible.</para> | |
1fd5e000 CF |
272 | |
273 | <para>The reuse of existing free implementations of such things | |
274 | as the glob, regexp, and getopt libraries saved us considerable | |
275 | effort. In addition, Cygwin uses Doug Lea's free malloc | |
276 | implementation that successfully balances speed and compactness. The | |
277 | library accesses the malloc calls via an exported function pointer. | |
278 | This makes it possible for a Cygwin process to provide its own | |
279 | malloc if it so desires.</para> | |
280 | </sect2> | |
281 | ||
282 | <sect2 id="ov-hi-process"><title>Process Creation</title> | |
85f1119b CV |
283 | <para>The <function>fork</function> call in Cygwin is particularly interesting |
284 | because it does not map well on top of the Win32 API. This makes it very | |
1fd5e000 CF |
285 | difficult to implement correctly. Currently, the Cygwin fork is a |
286 | non-copy-on-write implementation similar to what was present in early | |
287 | flavors of UNIX.</para> | |
288 | ||
289 | <para>The first thing that happens when a parent process | |
290 | forks a child process is that the parent initializes a space in the | |
291 | Cygwin process table for the child. It then creates a suspended | |
292 | child process using the Win32 CreateProcess call. Next, the parent | |
293 | process calls setjmp to save its own context and sets a pointer to | |
294 | this in a Cygwin shared memory area (shared among all Cygwin | |
295 | tasks). It then fills in the child's .data and .bss sections by | |
296 | copying from its own address space into the suspended child's address | |
297 | space. After the child's address space is initialized, the child is | |
298 | run while the parent waits on a mutex. The child discovers it has | |
299 | been forked and longjumps using the saved jump buffer. The child then | |
300 | sets the mutex the parent is waiting on and blocks on another mutex. | |
301 | This is the signal for the parent to copy its stack and heap into the | |
302 | child, after which it releases the mutex the child is waiting on and | |
303 | returns from the fork call. Finally, the child wakes from blocking on | |
304 | the last mutex, recreates any memory-mapped areas passed to it via the | |
305 | shared area, and returns from fork itself.</para> | |
306 | ||
307 | <para>While we have some | |
308 | ideas as to how to speed up our fork implementation by reducing the | |
309 | number of context switches between the parent and child process, fork | |
310 | will almost certainly always be inefficient under Win32. Fortunately, | |
311 | in most circumstances the spawn family of calls provided by Cygwin | |
312 | can be substituted for a fork/exec pair with only a little effort. | |
313 | These calls map cleanly on top of the Win32 API. As a result, they | |
314 | are much more efficient. Changing the compiler's driver program to | |
315 | call spawn instead of fork was a trivial change and increased | |
316 | compilation speeds by twenty to thirty percent in our | |
317 | tests.</para> | |
318 | ||
319 | <para>However, spawn and exec present their own set of | |
320 | difficulties. Because there is no way to do an actual exec under | |
321 | Win32, Cygwin has to invent its own Process IDs (PIDs). As a | |
322 | result, when a process performs multiple exec calls, there will be | |
323 | multiple Windows PIDs associated with a single Cygwin PID. In some | |
324 | cases, stubs of each of these Win32 processes may linger, waiting for | |
325 | their exec'd Cygwin process to exit.</para> | |
326 | </sect2> | |
327 | ||
328 | <sect2 id="ov-hi-signals"><title>Signals</title> | |
329 | <para>When | |
330 | a Cygwin process starts, the library starts a secondary thread for | |
331 | use in signal handling. This thread waits for Windows events used to | |
332 | pass signals to the process. When a process notices it has a signal, | |
333 | it scans its signal bitmask and handles the signal in the appropriate | |
334 | fashion.</para> | |
335 | ||
336 | <para>Several complications in the implementation arise from the | |
337 | fact that the signal handler operates in the same address space as the | |
338 | executing program. The immediate consequence is that Cygwin system | |
339 | functions are interruptible unless special care is taken to avoid | |
340 | this. We go to some lengths to prevent the sig_send function that | |
341 | sends signals from being interrupted. In the case of a process | |
342 | sending a signal to another process, we place a mutex around sig_send | |
343 | such that sig_send will not be interrupted until it has completely | |
344 | finished sending the signal.</para> | |
345 | ||
346 | <para>In the case of a process sending | |
347 | itself a signal, we use a separate semaphore/event pair instead of the | |
348 | mutex. sig_send starts by resetting the event and incrementing the | |
349 | semaphore that flags the signal handler to process the signal. After | |
350 | the signal is processed, the signal handler signals the event that it | |
351 | is done. This process keeps intraprocess signals synchronous, as | |
352 | required by POSIX.</para> | |
353 | ||
354 | <para>Most standard UNIX signals are provided. Job | |
355 | control works as expected in shells that support | |
356 | it.</para> | |
357 | </sect2> | |
358 | ||
359 | <sect2 id="ov-hi-sockets"><title>Sockets</title> | |
85f1119b CV |
360 | <para>Socket-related calls in Cygwin basically call the functions by the |
361 | same name in Winsock, Microsoft's implementation of Berkeley sockets, but | |
362 | with lots of tweaks. All sockets are non-blocking under the hood to allow | |
363 | to interrupt blocking calls by POSIX signals. Additional bookkeeping is | |
364 | necessary to implement correct socket sharing POSIX semantics and especially | |
365 | for the select call. Some socket-related functions are not implemented at | |
366 | all in Winsock, as, for example, socketpair. Starting with Windows Vista, | |
367 | Microsoft removed the legacy calls <function>rcmd(3)</function>, | |
368 | <function>rexec(3)</function> and <function>rresvport(3)</function>. | |
369 | Recent versions of Cygwin now implement all these calls internally.</para> | |
370 | ||
371 | <para>An especially troublesome feature of Winsock is that it must be | |
372 | initialized before the first socket function is called. As a result, Cygwin | |
373 | has to perform this initialization on the fly, as soon as the first | |
374 | socket-related function is called by the application. In order to support | |
375 | sockets across fork calls, child processes initialize Winsock if any | |
376 | inherited file descriptor is a socket.</para> | |
377 | ||
378 | <para>AF_UNIX (AF_LOCAL) sockets are not available in Winsock. They are | |
379 | implemented in Cygwin by using local AF_INET sockets instead. This is | |
380 | completely transparent to the application. Cygwin's implementation also | |
381 | supports the getpeereid BSD extension. A yet missing feature is | |
382 | descriptor passing, though.</para> | |
383 | ||
384 | <para>Starting with release 1.7.0, Cygwin gets IPv6 support. However, this | |
385 | depends on the availability of the Windows IPv6 stack. Up to Windows 2003, | |
386 | the IPv6 stack is treated as "experimental" and it's not feature complete. | |
387 | Full support is only available starting with Windows Vista and Windows Server | |
388 | 2008. The newly implemented <function>getaddrinfo</function> and | |
389 | <function>getnameinfo</function> functions are not dependent on the OS, | |
390 | though. Cygwin 1.7.0 adds replacement functions which implement the full | |
391 | functionality for IPv4.</para> | |
392 | ||
1fd5e000 CF |
393 | </sect2> |
394 | ||
395 | <sect2 id="ov-hi-select"><title>Select</title> | |
85f1119b | 396 | <para>The UNIX <function>select</function> function is another |
1fd5e000 CF |
397 | call that does not map cleanly on top of the Win32 API. Much to our |
398 | dismay, we discovered that the Win32 select in Winsock only worked on | |
399 | socket handles. Our implementation allows select to function normally | |
400 | when given different types of file descriptors (sockets, pipes, | |
401 | handles, and a custom /dev/windows Windows messages | |
402 | pseudo-device).</para> | |
403 | ||
404 | <para>Upon entry into the select function, the first | |
405 | operation is to sort the file descriptors into the different types. | |
406 | There are then two cases to consider. The simple case is when at | |
407 | least one file descriptor is a type that is always known to be ready | |
408 | (such as a disk file). In that case, select returns immediately as | |
409 | soon as it has polled each of the other types to see if they are | |
410 | ready. The more complex case involves waiting for socket or pipe file | |
411 | descriptors to be ready. This is accomplished by the main thread | |
412 | suspending itself, after starting one thread for each type of file | |
413 | descriptor present. Each thread polls the file descriptors of its | |
414 | respective type with the appropriate Win32 API call. As soon as a | |
415 | thread identifies a ready descriptor, that thread signals the main | |
416 | thread to wake up. This case is now the same as the first one since | |
417 | we know at least one descriptor is ready. So select returns, after | |
418 | polling all of the file descriptors one last time.</para> | |
419 | </sect2> | |
42fb6204 JDF |
420 | </sect1> |
421 |