diff options
author | Charadon <dev@iotib.net> | 2022-10-08 22:23:17 -0400 |
---|---|---|
committer | Charadon <dev@iotib.net> | 2022-10-08 22:23:17 -0400 |
commit | 7013bbd6e8d0c81c6b0d4ccc3ba12afa1341ad63 (patch) | |
tree | 6e4e9bf584453bf5bebbc9c084e8a450c205ada3 /docs | |
parent | 52facfe07f82aa1639f9fb7e4141ccd902a28c74 (diff) | |
download | dscip-7013bbd6e8d0c81c6b0d4ccc3ba12afa1341ad63.tar.gz |
docs/manual.tex: Moved to docs
Diffstat (limited to 'docs')
-rw-r--r-- | docs/manual.tex | 653 |
1 files changed, 653 insertions, 0 deletions
diff --git a/docs/manual.tex b/docs/manual.tex new file mode 100644 index 0000000..0a7b542 --- /dev/null +++ b/docs/manual.tex @@ -0,0 +1,653 @@ +\input texinfo +@setfilename dscip.info +@settitle Dead Simple Continuous Integration POSIX + +@copying +@verbatim +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. +@end verbatim +@end copying + +@contents + +@node Top +@top Dead Simple Continuous Integration POSIX Manual + +This is the manual for the Dead Simple Continuous Integration POSIX program. + +@verbatim +Dead Simple Continuous Integration POSIX Manual by Charadon +(DSCIP Manual for short.) + +To the extent possible under law, the person who associated CC0 with +DSCIP Manual has waived all copyright and related or neighboring rights +to DSCIP Manual. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see: +@end verbatim +@url{https://creativecommons.org/publicdomain/zero/1.0/}. + +@menu +* Installing:: +* Using:: +* Quirks:: + +* Manual's License:: +* Index:: +@end menu + +@node Installing +@chapter Installing +@cindex Installing + Details on installing DSCIP onto various systems. + @node Downloading + @section Downloading + @cindex Downloading + Currently, the upstream repo for DSCIP is located at this + @url{https://www.opencode.net/charadon/dscip, Git Repo}. If your OS + doesn't have DSCIP packaged, you can download the @command{setup.sh} + from the releases page, and use that to install dscip. Alternatively, + you can clone the git repo into whatever directory you want. + @node Unix + @section Unix + @cindex Installing on Unix + In this section, Unix refers to systems that are similar in nature to the + old System V Unix or is POSIX in nature. This would include: Linux, BSD, + Mac, Haiku, and Illumos.@*@* + The instructions will pretty much be the same for all systems. + + @node As a Package + @subsection As a Package + @cindex Unix: Installing Packaged DSCIP + If your host OS packaged DSCIP correctly according to + Packaging (@xref{Packaging}), these instructions should work. + + @enumerate + @item + Run @command{setup-dscip} in the terminal. See @command{setup-dscip + -h} for more details. + @item + Add the new script as a cronjob or daemon. See your OS's + manual for instructions on how to do so. + @end enumerate + + And that's it! You're ready to go! + + @node Manually + @subsection Manually + @cindex Unix: Install Manually + While not as simple as if it was packaged. The process is still not + that hard. + @enumerate + @item + Run @command{setup.sh}. See @command{setup.sh -h} for more + details. + @item + Add the new script as a cronjob or daemon. See your OS's manual + for instructions on how to do so. + @end enumerate + And that's it! You're ready to go! + + @node Windows + @section Windows + @cindex Installing on Windows + Windows is a different beast from Unix. So it warrants it's own dedicated + section. + @node MSYS2 (Recommended) + @subsection MSYS2 (Recommended) + @cindex Windows: Installing on MSYS2 + @enumerate + @item + Install @url{https://www.msys2.org, MSYS2} in whatever way you want. I recommend using + @url{https://scoop.sh, Scoop}. + @item + Once MSYS2 is installed, run setup.sh (@command{setup.sh -h} for + more info.). + @item + Now we'll need a way to run it regularly. I recommend using the Task Scheduler + that comes with Windows. Here's a step-by-step guide: @xref{Task Scheduler} + @end enumerate + + @node Only Bash + @subsection Bash + @cindex Windows: Installing with only Bash + The easiest way to get Bash on Windows is to install git, so we'll + be assuming that path. + @enumerate + @item + Install @url{https://gitforwindows.org/, Git for Windows}, I recommend using @url{https://scoop.sh, + Scoop}. + @item + Once Git is installed, you should be able to run @command{bash} from + the command prompt or powershell. Once in Bash, run setup.sh + (@command{setup.sh -h} for more info.) and install dscip. + @item + Now we'll need a way to run it regularly. I recommend using Task Scheduler + that comes with Windows. Here's a step-by-step guide: @xref{Task Scheduler} + @end enumerate + @node Task Scheduler + @subsection Using Task Scheduler + @cindex Windows: Using Task Scheduler + Once you have DSCIP installed, you'll need to have it run on a regular basis. + For this, Windows has the Task Scheduler. Using it is very simple, and i'll go + over a basic set up with it. Also, you should always use an unpriviledged user. + @enumerate + @item + Create a batch/powershell script that runs bash on the DSCIP script. This script should + be located somewhere that the unpriviledged user can run it.@* + Here is an a batch example:@* + @example +set MSYSTEM=MINGW64 :: If you're using MSYS2 +C:\Users\Build\scoop\apps\msys2\current\usr\bin\bash -l -c "/home/Build/project/dscip" + @end example + @item + Log in as an Administrator user and open Task Scheduler by press Win+R, and typing taskschd.msc into the Run Dialog. + @item + Right click on @command{Task Scheduler Library} and click @command{Create Task} + @item + Under Security Options, change the User to an unpriviledged user, and set to 'Run whether user is logged on or not.' + @item + Go to 'Triggers' and click the 'New...' button. A new window will pop up with options + to schedule when the task will execute. First thing you should do is click the 'Begin the Task' + drop-down menu and select 'At startup', this will ensure that the task will run with every reboot. + As for schedule settings, I recommend going down to advanced and checking the box 'Repeat task every:' and + putting in '1 minute' into the box, and then selecting 'Indenfinitely' in the 'for a duration of' box. + Now click the 'OK' button to save your settings. + @item + Go to the 'Actions' tab and click the 'New...' button at the bottom. In the 'New Action' dialog that will pop up, + select the Batch/Powershell script you made earlier. There's no need to select a 'Start In' location, as the script + by default tries to change directory into the directory where the script is stored at. + @item + From here, you can configure any options you want, but if you have no further configuration needs, click the 'Ok' button + to close out of the 'Create Task' window. Now just reboot the machine. + @end enumerate + @noindent + And that should be it, it will now run DSCIP every minute. + + @node Packaging + @section Packaging + @cindex Packaging + Packaging is pretty easy, just run @command{make install} and it'll do + everything for you. You can use environment variables to change where + certain things go though. + @enumerate + @item + @env{PREFIX}: This specifies where on the system everything will go. By + default it's /usr/local. + @item + @env{BINDIR}: The directory to install setup.sh to. When installed, it + will change it's name to @command{setup-dscip}. + @item + @env{INFODIR}: The directory to install the manual. Default is + @env{PREFIX}/share/info. + @end enumerate + @noindent + This is the general layout that the Makefile defaults to: + @example +. +|-- bin +| `-- setup-dscip (setup.sh) +`-- share + |-- charadon + | `-- dscip + | |-- build.sh + | |-- config.sh + | |-- dscip + | |-- failed.sh + | |-- post.sh + | `-- pre.sh + `-- info + `-- dscip.info.gz + @end example + @* + @noindent + You'll note two things: + @enumerate + @item + @command{update.sh} is not included. This is mainly mean't for non-package + installs. Such as direct @command{git} clones, or using the + @command{setup.sh} script on it's own. + @item + @env{SCRIPT_DIR} cannot be changed from it's default of + $PREFIX/share/charadon/dscip. This is because the @command{setup.sh} + script relies on the scripts being there to symlink to them. + @end enumerate + + @node Using Templates + @section Using Templates + @cindex Using Templates + Templates are an easy way to quickly get a DSCIP instance up and + running. Since most developers tend to have all their projects build + almost the exact same way, you can easily create a git repo with your DSCIP + scripts and have the setup script copy them over. You can point to the + directory containing your templates by using the @option{-t} argument with + setup.sh. You find find an example of templates here at my + @url{https://www.opencode.net/charadon/my-dscip-templates-v1, Git Repo} + + + +@node Using +@chapter Using +@cindex Using + This chapter goes over how to actually use DSCIP. + @node Scripts + @section Scripts + @cindex Using: Scripts + This section covers all the scripts in DSCIP, what they do, and with + examples. + @node config_dot_sh + @subsection config.sh + @cindex Scripts: config.sh + @command{config.sh} is where all the variables for dscip are stored. + Any variable in here can be used in any other script. See + @xref{Basic Variables}.@*Example: + @example +#!/bin/sh +# Variables that control the program. # +# GIT Repo # +export DSCIP_GITREPO="https://www.example.com/example/example.git" +export DSCIP_NAME="Example" +# GIT MODE: # +# pull: Doesn't delete previous clone and just pulls changes. # +# clone: Deletes previous clone, and creates a fresh clone. # +export DSCIP_GITMODE="clone" +# Branch to check # +export DSCIP_BRANCH="master" +# The directory where all the scripts are. By default tries to detect where # +# automatically. # +WORKING_DIRECTORY="$(pwd -P)" +export WORKING_DIRECTORY +# Commands to run before building. # +export DSCIP_PRE_CMD="$WORKING_DIRECTORY/pre.sh" +# Commands to run to build program. # +export DSCIP_BUILD_CMD="$WORKING_DIRECTORY/build.sh" +# Commands to run after building has succeeded. # +export DSCIP_POST_CMD="$WORKING_DIRECTORY/post.sh" +# Commands to run after building has failed. +export DSCIP_FAILED_CMD="$WORKING_DIRECTORY/failed.sh" +# Daemon mode options # +export DSCIP_DAEMON="false" # If daemon mode should be enabled or not. # +export DSCIP_DAEMON_FORK="true" # If the daemon should run in the background. # +export DSCIP_SLEEP="60" # How many seconds before the daemon re-runs itself. # +# etc # +export DSCIP_DISREGARD_COMMIT_CHECK="false" # If the script should just rebuild even # +# if upstream has not updated. # +export DSCIP_OUTPUT_TO="$WORKING_DIRECTORY/output.txt" # Output to file, default is output.txt +# Automatically update DSCIP? +export DSCIP_AUTO_UPDATE="false" + @end example + @node setup_dot_sh + @subsection setup.sh + @cindex Scripts: setup.sh + This script will handle the downloading, installing/symlinking, and + configuration of a DSCIP instance. It has two modes of operation: + @enumerate + @item + Interactive Mode: If no argument is supplied, it will ask the + user questions on how it wants to set up the dscip instance. + @item + Non-interactive Mode: If arguments are supplied, it will use + those arguments to create a DSCIP instance. + @end enumerate + @noindent @* + See @command{setup.sh -h} for + more info. This script can also go by the name @command{setup-dscip} + if it's packaged.@*@* Example: + @example +./setup.sh -n "Pong-C" -d /home/builder/Pong-C -u "https://opencode.net/charadon/pong-c" -b master -t /home/builder/templates + @end example + @node update_dot_sh + @subsection update.sh + @cindex Scripts: update.sh + This script updates the @command{dscip} script. It shouldn't be + present if packaged for a system. It's only useful manual + installations. + @node pre_dot_sh + @subsection pre.sh + @cindex Scripts: pre.sh + This script contains the commands to run *before* the build + commands. This script can do things such as: + @enumerate + @item + Update the System. + @item + Grab assets from a remote URL not part of the git repo. + @item + Probe to see if certain services are up and running. Such as a + FTP server to upload artifacts to. + @end enumerate + @* + @noindent + If this script doesn't exit with 0, then DSCIP aborts. Another thing + to note, is that DSCIP will run whatever the shebang is, so this script can be + made in other languages, such as Perl, Python, Powershell, Batch, C Shell, etc.@*@*Example: + @example +#!/bin/sh +set -eu + +# Execute commands before building. +# Below is an example. + +# Build user implied to have sudo access to apt update and upgrade +sudo apt update -y +sudo apt upgrade -y + +# Including assets with game code is usually a bad idea, so we grab the assets +# from a mirror. +wget https://www.example.com/project/game_assets.zip +unzip game_assets.zip + +exit 0 + @end example + @node build_dot_sh + @subsection build.sh + @cindex Scripts: build.sh + This script contains the build commands for your project. If the + script doesn't return 0, it will run @xref{failed_dot_sh, + @command{failed.sh}}, otherwise, it will run + @xref{post_dot_sh,@command{post.sh}}.@*Example:@* + @example + +#!/bin/sh + +set -eu + +# Insert build commands in here. # +# If you're feeling particular paranoid, you can make it chroot here. # + +./configure +make -j4 +make DESTDIR=app install + +exit 0 + @end example + @node failed_dot_sh + @subsection failed.sh + @cindex Scripts: failed.sh + This script tells DSCIP what to do if the build failed. Like pre.sh, + it must return 0 or else DSCIP will abort. @*Example:@* + @example +#!/bin/sh + +set -eu + +# This script determines what to do if the build failed. +# Below is an example of uploading the output.txt to an ftp server. +ftp -in <<EOF +open 192.168.1.5 +user username password +mkdir $DSCIP_NAME +cd $DSCIP_NAME +mkdir $CURRENT_COMMIT +cd $CURRENT_COMMIT +mkdir $(uname) +cd $(uname) +put $WORKING_DIRECTORY/output.txt output-failed.txt +close +bye +EOF + @end example + @node post_dot_sh + @subsection post.sh + @cindex Scripts: post.sh + This script tells DSCIP what to do if the build succeeded. Like + pre.sh, it must return 0 or else DSCIP will abort. @*Example:@* + @example +#!/bin/sh + +set -eu + +# Execute commands after building. Like pushing to an FTP server. # +# Example below. # + +# TAR up the program. # +bsdtar -a -cf \ +$DSCIP_NAME-$(uname)-$(uname -r)_$(uname -m)-$CURRENT_COMMIT.tar.xz app/ + +# Send the artifacts to an FTP server. # +ftp -in <<EOF +open 192.168.255.255 +user username pAssw0rd +mkdir $DSCIP_NAME +cd $DSCIP_NAME +mkdir $CURRENT_COMMIT +cd $CURRENT_COMMIT +mkdir $(uname) +cd $(uname) +put $DSCIP_NAME-$(uname)-$(uname -r)_$(uname -m)-$CURRENT_COMMIT.tar.xz +put $WORKING_DIRECTORY/output.txt output-success.txt +close +bye +EOF + +exit 0 + @end example + @node Basic Variables + @section Basic Variables + @cindex Basic Variables + This section goes over variables that you can safely modify in + config.sh and/or use in your scripts. + @subsection DSCIP_GITREPO + @cindex Basic Variables: DSCIP_GITREPO + This is the variable that determines what git repo DSCIP clones into + wrkdir. It should be noted that this isn't limited to a remote URL. + It can also clone from a local system git repo. This can be useful + if you want to forbid internet access to the builder user. + @subsection DSCIP_NAME + @cindex Basic Variables: DSCIP_NAME + This variable determines the name of the program that's being build. + Mostly for use with the @command{post.sh} and @command{failed.sh} + scripts when publishing artifacts. + @subsection DSCIP_BRANCH + @cindex Basic Variables: DSCIP_BRANCH + This variable tells DSCIP which branch to clone. This is useful if + you develop in a branch other than master. + @subsection DSCIP_DAEMON + @cindex Basic Variables: DSCIP_DAEMON + This variable will tell DSCIP to not close, but rather stay open and + just sleep before re-running itself. Useful for Windows, if you + want DSCIP to run in shorter time periods than 60 seconds, or use + special features that your OS's init system gives. + @subsection DSCIP_DAEMON_FORK + @cindex Basic Variables: DSCIP_DAEMON_FORK + This variable tells DSCIP if it should run itself in the background. + Some init systems prefer one or the other, so consult your OS's + documentation. + @subsection DSCIP_SLEEP + @cindex Basic Variables: DSCIP_SLEEP + When in daemon mode, this controls how long DSCIP should wait + between attempted builds before checking for a new commit and + building if one exists. + @subsection DSCIP_OUTPUT_TO + @cindex Basic Variables: DSCIP_OUTPUT_TO + This variable tells DSCIP where to put logs. By default it puts all + output into output.txt. This is useful if, for example, you're + running DSCIP in daemon mode, and need to store logs somewhere else. + @subsection DSCIP_DATE_FORMAT + @cindex Basic Variables: DSCIP_DATE_FORMAT + This variable tells DSCIP how it should format @env{COMMIT_DATE}. See + @command{strftime(3)} for more information of time codes. + @subsection LAST_COMMIT + @cindex Basic Variables: LAST_COMMIT + This variable tells DSCIP what the last commit was. This variable + should be treated as *readonly* and should never be modified. + @subsection CURRENT_COMMIT + @cindex Basic Variables: CURRENT_COMMIT + This variable tells DSCIP what commit it's currently building. This + variable like LAST_COMMIT should be treated as *readonly* and should + never be modified. + @subsection COMMIT_DATE + @cindex Basic Variables: COMMIT_DATE + This variable is the date that the commit was created on. This can + be used in your post scripts to organize artifacts if you wish. This + string is formatted with @env{DSCIP_DATE_FORMAT} above. + @node Advanced Variables + @section Advanced Variables + @cindex Advanced Variables + These are variables you should only change if you absolutely need to! + @subsection DSCIP_GITMODE + @cindex Advanced Variables: DSCIP_GITMODE + This tells DSCIP to, rather than delete the wrkdir and get a fresh + clone, to just pull changes. This is really only useful in + situations where you have limited bandwidth. + @subsection WORKING_DIRECTORY + @cindex Advanced Variables: WORKING_DIRECTORY + This should probably never be changed. The only situation that + *might* warrant changing it, is in a very restricted environment + where it *has* to run in a specific place. + @subsection DSCIP_@{PRE,BUILD,POST,FAILED@}_CMD + @cindex Advanced Variables: DSCIP_@{PRE,BUILD,POST,FAILED@}_CMD + These variables tell DSCIP where to find their respective scripts. Like + WORKING_DIRECTORY, this really shouldn't be changed and is really + only useful in situations that are very restrictive. + @subsection DSCIP_DISREGARD_COMMIT_CHECK + @cindex Advanced Variables: DSCIP_DISREGARD_COMMIT_CHECK + This variable tells DSCIP to ignore the commit check and just keep + rebuilding. This is useful for seeing if old/unmaintained software + will still build on modern systems. But other than that, should be + left off. + @subsection DSCIP_AUTO_UPDATE + @cindex Advanced Variables: DSCIP_AUTO_UPDATE + This variable tells DSCIP to run @command{update.sh}, and then run a + checksum on itself. If it's different from when it first launched, + It'll re-run itself. This is useful for manual installations. + +@node Quirks +@chapter Quirks +@cindex Quirks + This chapter goes over various quirks that have been discovered with DSCIP. + None so far... + +@node Manual's License +@chapter Manual's License +@cindex Manual's License + @insertcopying + + + +@node Index +@unnumbered Index +@printindex cp + +@bye |