|
1 ## |
|
2 ## openpkg dev -- OpenPKG Package Development Tool |
|
3 ## Copyright (c) 2008-2012 OpenPKG GmbH <http://openpkg.com/> |
|
4 ## |
|
5 ## This software is property of the OpenPKG GmbH, DE MUC HRB 160208. |
|
6 ## All rights reserved. Licenses which grant limited permission to use, |
|
7 ## copy, modify and distribute this software are available from the |
|
8 ## OpenPKG GmbH. |
|
9 ## |
|
10 ## THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
|
11 ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|
12 ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|
13 ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR |
|
14 ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
15 ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
16 ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
17 ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
18 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
19 ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
|
20 ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
21 ## SUCH DAMAGE. |
|
22 ## |
|
23 |
|
24 =pod |
|
25 |
|
26 B<openpkg dev> - OpenPKG Package Development Tool |
|
27 |
|
28 =head1 DESCRIPTION |
|
29 |
|
30 B<openpkg dev> is a package development tool for B<OpenPKG>. |
|
31 |
|
32 =head2 SOURCE PACKAGE HANDLING |
|
33 |
|
34 =over 4 |
|
35 |
|
36 =item B<openpkg dev unpack> |
|
37 [C<-l> I<layout>] |
|
38 [C<-b> I<basedir>] |
|
39 [C<-s>] |
|
40 [C<-d>] |
|
41 I<name>C<->I<version>C<->I<release>C<.src.rpm> |
|
42 |
|
43 Unpacks an OpenPKG source RPM package |
|
44 I<name>C<->I<version>C<->I<release>C<.src.rpm> into I<basedir> |
|
45 (default is I<name>C<->I<version>C<->I<release>) |
|
46 using I<layout> (default is I<structured>). |
|
47 Additionally, |
|
48 I<file-rpmmacros> |
|
49 configuration file is generated where |
|
50 C<-s> enables shared mode and |
|
51 C<-d> enables debug mode, see I<file-rpmmacros>. |
|
52 |
|
53 =back |
|
54 |
|
55 =head2 SOURCE PACKAGE DEVELOPMENT |
|
56 |
|
57 =over 4 |
|
58 |
|
59 =item B<openpkg dev shell> |
|
60 |
|
61 This is a convenience command which enters an interactive B<GNU Bash> |
|
62 shell which provides the following work environment: |
|
63 |
|
64 =over 4 |
|
65 |
|
66 =item B<Environment Variables:> |
|
67 |
|
68 OPENPKG_PREFIX "<prefix>" |
|
69 PS1 "\\[\\e[31;1m\\]\\u\\[\\e[0m\\]@\\h:\\w [OPENPKG_PREFIX=$OPENPKG_PREFIX]\n\\\$ " |
|
70 T %{_tmppath} |
|
71 S %{_specdir} |
|
72 D %{_sourcedir} |
|
73 |
|
74 =item B<Command-Line Aliases:> |
|
75 |
|
76 openpkg "${OPENPKG_PREFIX}/bin/openpkg" |
|
77 opd "${OPENPKG_PREFIX}/bin/openpkg dev" |
|
78 |
|
79 =item B<Command-Line Keystrokes:> |
|
80 |
|
81 ESC+x "opd unpack\n" |
|
82 ESC+v "opd edit\n" |
|
83 ESC+t "opd build -s track\n" |
|
84 ESC+f "opd build -s fetch\n" |
|
85 ESC+b "opd build\n" |
|
86 ESC+1 "opd build -s prep\n" |
|
87 ESC+2 "opd build -s compile\n" |
|
88 ESC+3 "opd build -s install\n" |
|
89 ESC+4 "opd build -s binary\n" |
|
90 ESC+s "opd build -s source\n" |
|
91 ESC+p "opd peek\n" |
|
92 ESC+d "opd diff\n" |
|
93 ESC+i "opd install\n" |
|
94 ESC+e "opd erase\n" |
|
95 ESC+l "opd lint\n" |
|
96 ESC+r "opd release\n" |
|
97 |
|
98 =back |
|
99 |
|
100 If option C<-s> is passed to B<openpkg dev shell> and screen(1) is |
|
101 available in C<$PATH>, the interactive development shell is started up |
|
102 in a convenient virtual screen environment. |
|
103 |
|
104 =item B<openpkg dev edit> |
|
105 |
|
106 Load spec file into editor. |
|
107 |
|
108 =over 4 |
|
109 |
|
110 =item B<Environment Variables:> |
|
111 |
|
112 EDITOR "vi" |
|
113 |
|
114 =back |
|
115 |
|
116 =item B<openpkg dev build> |
|
117 [C<-s> I<step>] |
|
118 [C<-D> I<define>[=I<value>]] |
|
119 [C<-w> I<variant>] |
|
120 |
|
121 Builds package steps. Default I<step> is C<all>. Option C<-D> translated |
|
122 into "C<--define 'I<define> I<value>'>" while option C<-w> translated |
|
123 into "C<--with> I<variant>". The I<step> arguments translate into the |
|
124 following RPM options: |
|
125 |
|
126 track: -bt |
|
127 fetch: -bf |
|
128 prep: -bp |
|
129 compile: -bc --short-circuit |
|
130 install: -bi --short-circuit |
|
131 binary: -bb --short-circuit |
|
132 source: -bs |
|
133 all: -ba |
|
134 |
|
135 =item B<openpkg dev peek> |
|
136 |
|
137 Peeks file list from package and tags configuration and documentation files. |
|
138 |
|
139 =item B<openpkg dev diff> |
|
140 |
|
141 Shows modifications with the help of a possibly underlying Version |
|
142 Control System (VCS) like CVS, Subversion, Monotone, Git, Mercurial or |
|
143 (as a fallback ) OSSP svs. |
|
144 |
|
145 =item B<openpkg dev install> |
|
146 [C<-f>] |
|
147 [C<-o>] |
|
148 [C<-n>] |
|
149 [C<-s>] |
|
150 |
|
151 Installs package. |
|
152 Option |
|
153 C<-f> adds C<--force>, |
|
154 C<-n> adds C<--nodeps> and |
|
155 C<-o> adds C<--oldpackage> |
|
156 to the underlying C<rpm> call. |
|
157 Option C<-s> prefixes the command with sudo(1). |
|
158 |
|
159 =item B<openpkg dev erase> |
|
160 [C<-f>] |
|
161 [C<-o>] |
|
162 [C<-a>] |
|
163 [C<-s>] |
|
164 |
|
165 Erases package. |
|
166 Option |
|
167 C<-f> adds C<--force>, |
|
168 C<-n> adds C<--nodeps> and |
|
169 C<-a> adds C<--allmatches> |
|
170 to the underlying C<rpm> call. |
|
171 Option C<-s> prefixes the command with sudo(1). |
|
172 |
|
173 =item B<openpkg dev lint> |
|
174 [C<-v>] |
|
175 [C<-b>] |
|
176 |
|
177 Lints package sources C<*.spec>, C<fsl.*>, C<rc.*> and binary package files. |
|
178 Option C<-v> enables verboseness. |
|
179 Option C<-b> disables the linting of an existing binary package file. |
|
180 |
|
181 =item B<openpkg dev release> |
|
182 [C<-m> I<message>] |
|
183 [C<-n>] |
|
184 |
|
185 Releases package specification to the repository. Unlike previous |
|
186 incarnations of "openpkg dev" this one is not tied to any repository or |
|
187 structure. The default message is created using the difference between |
|
188 the previous and current version of the package specification. In order |
|
189 to grab the previous version, the working directory and three levels |
|
190 towards root are checked for signs of CVS, Subversion, Monotone, Git, |
|
191 Mercurial or SVS information, in that order. The appropriate command is |
|
192 then executed to retrieve the data and the VCS found is passed to the |
|
193 actual release command. |
|
194 |
|
195 Finally, the command specified by the environment variable |
|
196 C<OPENPKG_DEV_RELEASE> or, if omitted, specified by the rpm macro |
|
197 C<%{openpkg_dev_release}> is run and passed the following positional |
|
198 arguments: |
|
199 |
|
200 =over 4 |
|
201 |
|
202 openpkg-prefix |
|
203 spec-dir |
|
204 source-dir |
|
205 binary-rpm-file |
|
206 source-rpm-file |
|
207 package-name |
|
208 package-version |
|
209 package-release |
|
210 package-version-old |
|
211 package-release-old |
|
212 commit-message |
|
213 vcs |
|
214 |
|
215 =back |
|
216 |
|
217 For a dry run, set C<$OPENPKG_DEV_RELEASE> to "echo" or use option "C<-n>". |
|
218 |
|
219 =back |
|
220 |
|
221 =head1 UNPACKED SOURCE RPM PACKAGE FILESYSTEM LAYOUT |
|
222 |
|
223 When an OpenPKG source RPM package |
|
224 I<name>C<->I<version>C<->I<release>C<.src.rpm> is unpacked to the |
|
225 filesystem, the following distinct filesystem layouts are known: |
|
226 |
|
227 =over 4 |
|
228 |
|
229 =item B<global> |
|
230 |
|
231 =over 4 |
|
232 |
|
233 =item I<prefix>C</RPM/SRC/>I<name>C</.openpkg/rpmmacros> |
|
234 |
|
235 =item I<prefix>C</RPM/SRC/>I<name>C</>I<name>C<.spec> |
|
236 |
|
237 =item I<prefix>C</RPM/SRC/>I<name>C</>I<packaging-source-file> |
|
238 |
|
239 =item I<prefix>C</RPM/SRC/>I<name>C</>I<thirdparty-distribution-file> |
|
240 |
|
241 =item I<prefix>C</RPM/PKG/>I<binary-rpm-package-file> |
|
242 |
|
243 =item I<prefix>C</RPM/PKG/>I<source-rpm-package-file> |
|
244 |
|
245 =item I<prefix>C</RPM/TMP/>I<temporary-file> |
|
246 |
|
247 =back |
|
248 |
|
249 This is just the "simple" filesystem layout (see below) with the |
|
250 I<base-dir> set to I<prefix>C</RPM/SRC/>. |
|
251 |
|
252 This is the filesystem layout used by default for building OpenPKG |
|
253 packages during C<openpkg build> or the underlying C<openpkg rpm |
|
254 --rebuild> commands. |
|
255 |
|
256 =item B<local> |
|
257 |
|
258 =over 4 |
|
259 |
|
260 =item I<base-dir>C</.openpkg/rpmmacros> |
|
261 |
|
262 =item I<base-dir>C</>I<name>C<.spec> |
|
263 |
|
264 =item I<base-dir>C</>I<packaging-source-file> |
|
265 |
|
266 =item I<base-dir>C</>I<thirdparty-distribution-file> |
|
267 |
|
268 =item I<base-dir>C</>I<binary-rpm-package-file> |
|
269 |
|
270 =item I<base-dir>C</>I<source-rpm-package-file> |
|
271 |
|
272 =item I<base-dir>C</>I<temporary-file> |
|
273 |
|
274 =back |
|
275 |
|
276 This puts everything into one directory. |
|
277 |
|
278 =item B<simple> |
|
279 |
|
280 =over 4 |
|
281 |
|
282 =item I<base-dir>C</>I<name>C</.openpkg/rpmmacros> |
|
283 |
|
284 =item I<base-dir>C</>I<name>C</>I<name>C<.spec> |
|
285 |
|
286 =item I<base-dir>C</>I<name>C</>I<packaging-source-file> |
|
287 |
|
288 =item I<base-dir>C</>I<name>C</>I<thirdparty-distribution-file> |
|
289 |
|
290 =item I<base-dir>C</>I<binary-rpm-package-file> |
|
291 |
|
292 =item I<base-dir>C</>I<source-rpm-package-file> |
|
293 |
|
294 =item I<$TMPDIR>C</openpkg/>I<temporary-file> |
|
295 |
|
296 =back |
|
297 |
|
298 This is the simple filesystem layout of an unpacked |
|
299 OpenPKG package. All files are simply put into a sub-directory with the |
|
300 I<name> of the package. |
|
301 |
|
302 This is the filesystem layout used for the quick patching of a single |
|
303 OpenPKG package in a stand-alone environment. |
|
304 |
|
305 =item B<structured> |
|
306 |
|
307 =over 4 |
|
308 |
|
309 =item I<base-dir>C</>I<name>C</.openpkg/rpmmacros> |
|
310 |
|
311 =item I<base-dir>C</>I<name>C</src/>I<name>C<.spec> |
|
312 |
|
313 =item I<base-dir>C</>I<name>C</src/>I<packaging-source-file> |
|
314 |
|
315 =item I<base-dir>C</>I<name>C</dst/>I<thirdparty-distribution-file> |
|
316 |
|
317 =item I<base-dir>C</>I<name>C</pkg/>[C<bin/>]I<binary-rpm-package-file> |
|
318 |
|
319 =item I<base-dir>C</>I<name>C</pkg/>[C<src/>]I<source-rpm-package-file> |
|
320 |
|
321 =item I<base-dir>C</>I<name>C</tmp/>I<temporary-file> |
|
322 |
|
323 =back |
|
324 |
|
325 This is the structured (and default) filesystem layout of an unpacked |
|
326 OpenPKG package. A top-level sub-directory with the I<name> of the |
|
327 package is created. There the package specification and all packaging |
|
328 source files are put into the sub-directory I<src> and all the |
|
329 third-party distribution files are put into the sub-directory I<dst>. |
|
330 |
|
331 This is the filesystem layout used for the development of a single |
|
332 OpenPKG package in a stand-alone environment. |
|
333 |
|
334 =item B<distributed> |
|
335 |
|
336 =over 4 |
|
337 |
|
338 =item I<base-dir>C</>C<.openpkg/rpmmacros> |
|
339 |
|
340 =item I<base-dir>C</>C<src/>I<name>C</>I<name>C<.spec> |
|
341 |
|
342 =item I<base-dir>C</>C<src/>I<name>C</>I<packaging-source-file> |
|
343 |
|
344 =item I<base-dir>C</>C<dst/>I<name>C</>I<thirdparty-distribution-file> |
|
345 |
|
346 =item I<base-dir>C</>C<pkg/>[C<bin/>]I<binary-rpm-package-file> |
|
347 |
|
348 =item I<base-dir>C</>C<pkg/>[C<src/>]I<source-rpm-package-file> |
|
349 |
|
350 =item I<base-dir>C</>C<tmp/>I<temporary-file> |
|
351 |
|
352 =back |
|
353 |
|
354 This is the distributed filesystem layout of an unpacked OpenPKG |
|
355 package. It is similar to the structured filesystem layout but the |
|
356 C<src> and C<dst> directories and the I<name> directory are swapped, |
|
357 mainly with the intention of bundling together all third-party |
|
358 distribution files of a large number of packages. |
|
359 |
|
360 This is the filesystem layout used for regular OpenPKG package |
|
361 development. |
|
362 |
|
363 =back |
|
364 |
|
365 |
|
366 =head1 LOCAL RPM MACROS FILE (.openpkg/rpmmacros) |
|
367 |
|
368 OpenPKG supports local RPM macros files F<.openpkg/rpmmacros> which |
|
369 can be used to configure RPM in a local scope. This is especially |
|
370 interesting to configure a local (even per-package) build environment |
|
371 with the help of the C<%openpkg_layout> macro. |
|
372 |
|
373 C<%openpkg_layout> |
|
374 [C<macrosfile=>I<filename>] |
|
375 [C<basedir=>I<directory>] |
|
376 [C<specdir=>I<directory>] |
|
377 [C<sourcedir=>I<directory>] |
|
378 [C<builddir=>I<directory>] |
|
379 [C<tmpdir=>I<directory>] |
|
380 [C<binrpmdir=>I<directory>] |
|
381 [C<srcrpmdir=>I<directory>] |
|
382 [C<shared=>I<yes-or-no>] |
|
383 [C<debug=>I<yes-or-no>] |
|
384 |
|
385 =over 4 |
|
386 |
|
387 =item C<macrosfile=>I<filename> |
|
388 |
|
389 Absolute file path of the C<.openpkg/rpmmacros> file where this |
|
390 C<%openpkg_layout> macro is defined. Usually, the intended usage is to |
|
391 leverage from OpenPKG RPM's special C<%{macrosfile}> macro by simply |
|
392 using C<macrosfile=%{macrosfile}>. This parameter is important as |
|
393 the default C<basename> is derived from it. |
|
394 |
|
395 =item C<basedir=>I<directory> |
|
396 |
|
397 Absolute directory path where the C<.openpkg/rpmmacros> file is |
|
398 located under. Usually, the intended usage is to not explicitly |
|
399 set this parameter but let it be determined indirectly via |
|
400 C<macrosfile>. The effective default value is equal to a value like |
|
401 C<%{realpath:%{dirname:%{realpath:%{macrosfile}}}/..}> This parameter is |
|
402 important as all standard filesystem layouts (see parameter C<layout>) |
|
403 are always at least partially based on this base directory in order |
|
404 to provide absolute-path-independent flexible filesystem layouts. |
|
405 |
|
406 =item C<layout=>I<layout> |
|
407 |
|
408 The name of the filesystem layout type to use. The following standard |
|
409 filesystem layout types are pre-defined: C<global>, C<local>, C<simple>, |
|
410 C<structured> (default) and C<distributed>. |
|
411 |
|
412 global macrosdir <openpkg_prefix>/etc/openpkg |
|
413 global macrosfile <openpkg_prefix>/etc/openpkg/rpmmacros |
|
414 global specdir <openpkg_prefix>/RPM/SRC/$name |
|
415 global sourcedir <openpkg_prefix>/RPM/SRC/$name |
|
416 global builddir <openpkg_prefix>/RPM/TMP |
|
417 global tmpdir <openpkg_prefix>/RPM/TMP |
|
418 global binrpmdir <openpkg_prefix>/RPM/PKG |
|
419 global srcrpmdir <openpkg_prefix>/RPM/PKG |
|
420 |
|
421 local macrosdir <basedir>/.openpkg |
|
422 local macrosfile <basedir>/.openpkg/rpmmacros |
|
423 local specdir <basedir> |
|
424 local sourcedir <basedir> |
|
425 local builddir <basedir> |
|
426 local tmpdir <basedir> |
|
427 local binrpmdir <basedir> |
|
428 local srcrpmdir <basedir> |
|
429 |
|
430 simple macrosdir <basedir>/.openpkg |
|
431 simple macrosfile <basedir>/.openpkg/rpmmacros |
|
432 simple specdir <basedir> |
|
433 simple sourcedir <basedir> |
|
434 simple builddir <tmpdir> |
|
435 simple tmpdir <tmpdir> |
|
436 simple binrpmdir <basedir>/.. |
|
437 simple srcrpmdir <basedir>/.. |
|
438 |
|
439 structured macrosdir <basedir>/.openpkg |
|
440 structured macrosfile <basedir>/.openpkg/rpmmacros |
|
441 structured specdir <basedir>/src |
|
442 structured sourcedir <basedir>/dst |
|
443 structured builddir <basedir>/tmp |
|
444 structured tmpdir <basedir>/tmp |
|
445 structured binrpmdir <basedir>/pkg/bin |
|
446 structured srcrpmdir <basedir>/pkg/src |
|
447 |
|
448 distributed macrosdir <basedir>/.openpkg |
|
449 distributed macrosfile <basedir>/.openpkg/rpmmacros |
|
450 distributed specdir <basedir>/src/<name> |
|
451 distributed sourcedir <basedir>/dst/<name> |
|
452 distributed builddir <basedir>/tmp |
|
453 distributed tmpdir <basedir>/tmp |
|
454 distributed binrpmdir <basedir>/pkg/bin |
|
455 distributed srcrpmdir <basedir>/pkg/src |
|
456 |
|
457 |
|
458 =item C<specdir=>I<directory-list> |
|
459 |
|
460 =item C<sourcedir=>I<directory-list> |
|
461 |
|
462 =item C<builddir=>I<directory-list> |
|
463 |
|
464 =item C<tmpdir=>I<directory-list> |
|
465 |
|
466 =item C<binrpmdir=>I<directory-list> |
|
467 |
|
468 =item C<srcrpmdir=>I<directory-list> |
|
469 |
|
470 These parameters correspond to the six individual directories provided |
|
471 by a standard layout and allow you to selectively adjust parts of a |
|
472 standard layout to local needs and without having to define a full |
|
473 standard layout yourself. |
|
474 |
|
475 The I<directory-list> is a whitespace-separated list of |
|
476 I<directory>[C<:>[C<+>]I<directory>] specifications which are |
|
477 "first-match" searched for existence. The last directory in the list |
|
478 is always taken as the fallback and if it is not existing it is |
|
479 even created on-the-fly. The I<directory-check>C<:>I<directory-use> |
|
480 syntax variant allows the existence test to use I<directory-check>, |
|
481 but expands to I<directory-use> (replace mode). The |
|
482 I<directory-check>C<:+>I<directory-use> syntax variant allows |
|
483 the existence test to use I<directory-check>, but expands to |
|
484 I<directory-check>I<directory-use> (append mode). For instance |
|
485 C<tmpdir="%{getenv:HOME)/tmp:+/openpkg %{getenv:TMPDIR}:+/openpkg |
|
486 /tmp/%(echo $LOGNAME)/openpkg"> will first check for ~/tmp (and then use |
|
487 ~/tmp/openpkg), then for $TMPDIR (and use $TMPDIR/openpkg) and finally |
|
488 it will use /tmp/$LOGNAME/openpkg at last resort. |
|
489 |
|
490 Paths are usually assembled by using RPM macros like |
|
491 C<%{l_prefix}> (the instance prefix), C<%{__openpkg_basename}> (the |
|
492 I<basename> parameter), C<%{realpath:<path>} (path resolution), |
|
493 C<%{dirname:<path>} (directory name extraction), C<%{basename:<path>} |
|
494 (file name extraction), etc. |
|
495 |
|
496 =item C<shared=>I<yes-or-no> |
|
497 |
|
498 This enables the I<subdir> components in the standard filesystem |
|
499 layouts by setting it to an automatically generated sub-directory named |
|
500 I<host>C<->I<arch>-I<os>. This allows one to build the same OpenPKG |
|
501 package in parallel on multiple hosts in a shared environment (usually |
|
502 on an NFS based filesystem). |
|
503 |
|
504 =item C<debug=>I<yes-or-no> |
|
505 |
|
506 This enables debug outputs which shows the effectively used directory |
|
507 paths. |
|
508 |
|
509 =back |
|
510 |
|
511 The generated C<.openpkg/rpmmacros> file contains the generic filesystem |
|
512 layout glue configuration for the particular filesystem I<layout>. |
|
513 |
|
514 =over 1 |
|
515 |
|
516 =item C<%openpkg_layout macrosfile=%{macrosfile} layout=>I<type> |
|
517 |
|
518 =back |
|
519 |
|
520 =head1 CONFIGURATION |
|
521 |
|
522 =over 4 |
|
523 |
|
524 OPENPKG_NAME="Ralf S. Engelschall" |
|
525 OPENPKG_MAIL="rse@openpkg.net" |
|
526 OPENPKG_MODE="developer" |
|
527 |
|
528 OPENPKG_PREFIX="/openpkg" |
|
529 OPENPKG_TMPDIR="${TMPDIR-/tmp}/openpkg" |
|
530 |
|
531 OPENPKG_VCS="cvs ci -m '<msg>' ." |
|
532 OPENPKG_UPLD="scp <srpm> openpkg-ftp@ftp.openpkg.org:/current/SRC/00UPLOAD/" |
|
533 |
|
534 =back |
|
535 |
|
536 =head1 ABOUT |
|
537 |
|
538 OpenPKG B<dev> is Ralf S. Engelschall's Perl-based clean-room partial |
|
539 re-implementation of 2008 for OpenPKG 4.0 of Thomas Lotterer's original |
|
540 OpenPKG B<dev> Bash-based shell from 2002. |
|
541 |
|
542 =cut |
|
543 |