CDU has a simple strategy when dealing with command-line parameters: whatever can appear on the command-line can be used in a script file and vice-versa. Hence, unlike with most of the other ChAoS Utilities, there's no "options" section.
No script grammar is given here - CDU has quite an extensive HELP page and that is considered the definitive reference for CDU's grammar.
When CDU is parsing parameters, it will normally ignore white space and assume that "tokens" are delimited by spaces. Sometimes, of course, one wants to include a space within a parameter. So, how do we do this?
CDU handles this in a similar manner to the MSdos command-line processor. Namely, one puts double-quotes around the entire parameter.
For example, let's say that we want to present the following text as the message of a SAY word:
Mary had a little lamb
This won't work because CDU will assume that the desired message is the word "Mary" and it will try to look up the word "had" as a directive or command word:
SAY Mary had a little lamb
This is how it should be done:
SAY "Mary had a little lamb"
Note that any parameter can have double-quotes - superfluous double-quotes are ignored. For instance, the example command for the INCLUDE word has double-quotes around the file name operand even though the file's name does not contain any spaces. This doesn't matter since CDU will just discard them.
Note that this area contains one of the few differences between the way that command-line parameters are parsed and the way that parameters read from a response file are handled: in the latter it's our code that strips the double-quotes from parameters whereas in the former it's Microsoft's code.
CDU will accept a common number format wherever a number is required. One can enter numbers in one of six ways. Only the first (viz, "character" format) is case sensitive:
One can enter a character surrounded by single quotes. This is convenient except in one situation: if that character is a space character, then the whole construct has to be surrounded by double quotes as well. In this instance, it's probably easy to use one of the other modes. (For example, "0x20".)
This format will be familiar to "C" programmers; the number is expressed in hexadecimal and preceded by the string "0X". For example, an exclamation mark (ASCII decimal 33) can be represented as "0x21".
The number is written in binary and followed by a letter "B". Using this mode, our exclamation mark would be expressed as "100001b".
The number is written in the normal way with no extra strings attached. In decimal, the exclamation character is "33".
Express the number in hexadecimal followed by an "H". The exclamation mark becomes "21h" in this mode.
For really ancient programmers, we provide the octal mode: numbers are expressed as a string of octal digits followed by a letter "O". The exclamation mark thus becomes "41o".
If you want to embed comments in CDU scripts, use the semi-colon character (';'). The text from the semi-colon until the end of the current line is ignored by the program. For example:
IDENTIFY TRUE ; Auto-identify IDE drives.
If you want a semi-colon character to be treated as any other character, you can "escape" it by using two semi-colons next to each other. CDU will treated this pair of characters as a single semi-colon character:
SAY "This message contains a semi-colon (';;') character\n"
The above will result in this text from CDU:
CDU V0.6.038 Mar 02 2001 This message contains a semi-colon (';') character
CDU has limited macro capabilities. Any text between a pair of macro characters - a percent sign ('%') by default - will be "expanded". After this expansion has been done, the process of checking for a macro character is resumed, starting at the first character of the expanded text.
In a similar manner to the comment character, the macro expansion character can be "escaped" by using two percent signs next to each other. For example:
define AMACRO "Some macro text" say "The *expanded* macro text is '%AMACRO%'.\n" say "The *escaped* macro name is '%%AMACRO%%'.\n"
This will produce output similar to:
CDU V0.6.038 Mar 02 2001 The *expanded* macro text is 'Some macro text'. The *escaped* macro name is '%AMACRO%'.
The text between the macro characters is checked for a matching name to one of two items in this order:
If a match is found, then the text substitution is done as detailed above.
It is fairly common for command-line driven programs to allow the user to nominate a "response file". In essence, this allows the user to put into a file whatever they would've liked to have been able to place on the command-line. CDU allows this convention and, indeed, functionally, it's much the same as using the file INCLUDE facility.
The response file syntax also has a fairly common "standard" among command-line driven programs and CDU conforms to this:
<progname> <params> @<filename> <moreparams>
Hence, the following two examples will both run the file BATCH.CDU. Both are perfectly valid on the command-line and in a response file (that is, a script file) itself. For preference, we prefer to use the INCLUDE method in script files and the more compact '@' form on the command-line:
CDU @BATCH ; We normally use this on the command-line. CDU INCLUDE BATCH ; This seems more lucid for script files.
Note that CDU will append a default extension of .CDU if the extension-free file can't be found. Also, if you just supply a non-qualified file name, it'll look for the file in the current directory and then in the program directory. These rules apply to all script file includes and, hence, you can make CDU scripts that are not fully qualified and place them in the CDU program directory - no matter what the current directory is set to, they will run fine.
In fact, one could have CDU include some scripts from the current directory and have some of them load from the program directory. Hence, given a line like this:
If the file exists in the current (that is, "local") directory, it'll be found and run. If not, then CDU will look in its program directory. Hence, a local copy of X.CDU would "override" any copy in the place from which CDU was executed.
Note that each word is followed by an example of its use. To access the definitive grammar reference, invoke the CDU HELP page.
CDU will quite often accept synonyms for words. For example, in the current version of CDU, the following are all equivalent: OFF, DISABLE, INHIBIT, FALSE, NO. Thus, in the following word list documentation, you will find an entry for OFF but no entry for DISABLE. We have not bothered to list all possible synonyms since, as we have already said, the help pages are the definitive reference.
Adds another disk drive to the list "seen" by CDU. This can be used to add drives that CDU, for whatever reason, hasn't been able to interrogate itself. See the associated word, DELETE.
This word is used when one wants to refer to all disk drives. Thus, one can easily delete all disk drives seen by CDU by using the above example.
An archive is one of the stream types that CDU recognises. At present, only one compression system is handled: the GZIP system. A CDU archive always consists of a single file that has been GZIPped.
On IBM clones, some APIs don't always seem to return the true end-of-disk information when one retrieves the disk drive parameter block. Hence, it is sometimes possible to read past the "end" of the disk. If one is using CDU to backup a drive, one may want to make sure that the whole drive is read and, therefore, CDU has a mechanism that will detect the end of the drive by finding out the address of the last readable sector. Use of this mechanism is controlled by the AUTOEND switch.
There are several ways of performing a "bad scan" operation but the "official" way is to use the BADSCAN command. The BADSCAN command will not stop when it detects an error so that it is relatively easy to scan an entire disk for bad sectors. The other important point to bare in mind is that BADSCAN temporarily sets the BUFSIZ to one.
By default, CDU will give a "happy" beep when a "real" command executes successfully and a "sad" beep when a command fails. This behaviour can be altered by use of this word.
Currently, the two "track" buffers that CDU requires are allocated dynamically. However, this area is, at present, giving trouble possibly concerned with segment limitations and the like.
One can, using the BUFSIZ keyword, alter the size of the the buffers allocated. These buffers, by the way, are only allocated when a command (as opposed to a directive) is executed. In fact, this "delayed disk system initialisation" is exactly what allows one to, for example, enable diagnostics before the disks are "detected".
Note that the buffer sizes are, also "at present", specified in multiples of the IBM standard sector size - viz 512 bytes. Thus, if you wanted two KB (2048 byte) buffers, you would have to say "BUFSIZ 4".
By the way, when errors are detected, CDU may complain that the BUFSIZ parameter is greater than one. The problem with any BUFSIZ greater than one is that the reported location of the error really refers to the first sector of the block that contains the error. Hence, to fully locate a bad sector, BUFSIZ must be set to one. This is exactly what is done by the BADSCAN command.
You use the BYTE word to specify a byte stream object. The word must be followed by a number that represents the byte stream's value.
Note that sector ranges are ignored when applied to byte streams.
Also, note that byte streams are usually employed as stream sources. When used as a stream target, a byte stream behaves as a "bit bucket" and all output to that stream is discarded. (This is, therefore, one of the "unofficial" ways of doing a sector bad scan - you can just use a COPY command specifying a byte stream as the destination.)
You can clear the screen by using this word. Note that CDU uses a "belt and bracers" approach to clearing the screen - a "proper" clear-screen operation is done or following the emission of a large number of carriage-return / line-feed pairs.
This command allows you two compare two source streams. The command will compare the two streams until a difference is found, the user interrupts the process or an I/O error is detected. Note that if one stream ends prematurely, this is classed as a "difference".
Sometimes, especially when using a script file where the commands are known to be correct, one would like to inhibit the majority of the "Is this OK?" questions. This is what the CONFIRM switch controls.
Please note that disabling CONFIRM when writing to a user-specified (for example, via the command-line parameter) disk would probably be considered a rash act...
This, perhaps, the most useful of the CDU command set. This is how you copy one stream to another. The COPY command copies the source stream to the target stream until one or other stream terminates, the user interrupts the process or an I/O error is detected.
As with all non-trivial programs, bugs may well lurk within CDU. Enabling DEBUG will result in lots of output. If you are only interested in a small sub-set of the output, for example just the diagnostics from a single function, one can use the TRACE word to reduce the "clutter" produced.
DEFINEs are used in a similar, albeit very limited, manner to the expanded by using a special syntax.
Note that a text macro can be DEFINEd on the CDU command-line in a batch file and used within an invoked script. Thus, one can get the user to pass "parameters" into the CDU script. (Please note the caveat about using the CONFIRM word under these circumstances.)
Like it's sister word, this controls some timing loops in the IDE drive interrogation software. It is documented merely "for completeness". Don't fiddle with it.
By default, CDU will attempt to detect all of the system hard drives via the INT13EX and INT13 APIs. However, this scheme is not fool proof and so we've provided a means of over-riding the normal actions taken. The DELETE word allows you to remove hard drives "seen" by CDU. You can use the ADD word to add drives back into the list.
This word increases the amount of detail produced by CDU in certain circumstances. For example, if you enable DETAIL and use the DUMP word, you'll find that the contents of every sector read will be displayed on the screen. Likewise, the only difference between the INFO word and the VINFO word is that the latter has DETAIL enabled automatically.
The DISK word is used to specify the disk stream type. Disk streams are accessed via the INT13 or INT13EX APIs. CDU maintains a list of disks and, when the first of a set of certain set of commands is executed, it tries to IDENTIFY them.
Note that the user can dictate the contents of the disk list via the ADD and DELETE words. Also, one can dictate the API used to access each disk via the IFACE word. However, you should only use these words if you really need to control the disk list.
This word is used to "flush" any outstanding commands when using CDU interactively. See the INTERACTIVE word for more details.
The DUMP word merely dumps a sector's data to the standard output. Note that it will not dump the data if DETAIL is disabled. This fact can be used to "read check" a data stream - see also the BADSCAN word.
The END keyword is used to refer the last sector of a stream's data. (Note that this may, actually, be meaningless; for example, see the entry relating to BYTE streams.) See the item on sector ranges for details.
When used interactively, CDU does not exit when errors are detected. This allows typos to go unpunished and for failed commands to be retried. However, in this case, there is only one way to gracefully terminate the program and that is to use the EXIT word.
This is one of the most basic stream types. The word must be followed by a file name that is acceptable to the operating system.
Note that there are limitations when using large files under MSdos. Therefore, please read the entry on file SIZING if you intended to use large files.
This word causes CDU to automatically "flush" a pending command when an end-of-line is detected. This would only normally we required when using CDU interactively.
This word is used to introduce the target text in a SEARCH command.
CDU will only write to floppy disk drives when this switch is enabled. Please see the related WRITE entry.
Use this word to invoke the CDU help page. This page is quite extensive and includes a full CDU script language grammar. (This is why no grammar is given in this document - you should consider the CDU help page as the definitive source.)
CDU will only write to hard disk drives when this switch is enabled. Please see the related WRITE entry.
This is used to specify a required interface when one wants to force CDU to access a particular drive using the standard INT13 method. (See the entry for the IFACE word.)
This is used to specify a required interface when one wants to force CDU to access a particular drive using the extended INT13 method. (See the entry for the IFACE word.)
CDU relies on one of two disk interfaces being provided by the BIOS for accessing DISK streams. Namely, the INT13 and INT13EX (extended) API calls. It does attempt to identify which of these interfaces are available but, as with so many IBM PC APIs, they ain't perfect.
In particular, CDU has one trick up its sleeve that we've yet to see in commercial backups program - it can identify disk drives by their unique drive model and serial number strings. (Here, we are not talking about the MSdog volume serial numbers.)
The bad news is that the retrieval of these strings was only built into the latest versions of the INT13EX API and, as yet, we've not actually seen them in the real world. Therefore, CDU attempts to identify the drives by talking directly to the IDE hard drives itself. It goes without saying that this is not a "nice" thing to do but, in the absence of anything better, this is the way that we do things.
As of CDU version 0.6.025, the identification facility has been switched off by default. Since it's not fully reliable, it seems prudent to make the users have to enable it explicitly if they want to use this facility. We toyed with the idea of having the NAME directive enable it automagically but decided against this since one can always add an IDENTIFY directive to one's NAMES.CDU or CDU.CDU files. If we find a machine with the version three INT13 extended API, we may well make this switch enabled by default if the user has a version three API.
As explained in the entry for IDENTIFY word, CDU attempts to identify your drives and interfaces available. If, for whatever reason, it gets it wrong, you would use this word to force CDU to use the interface that you want.
See the entries for the I13 and I13EX words.
If you want to include one CDU script source in another, use this word. You can nest these "response" files several deep.
CDU will append a default extension of .CDU if the extension-free file can't be found. Also, if you just supply a non-qualified file name, it'll look for the file in the current directory and then in the program directory. (The latter is the place where the executable resides.)
This word will make CDU dump the current disk drive list to the console. This data will include the current drive serial numbers (if identification has taken place) and various other data concerning the interface being used, drive size and so on.
If DETAIL is enabled, considerably more data is produced.
You can use CDU interactively, after a fashion, by using something along the lines of:
CDU INCLUDE CON
To get the best behaviour from CDU, tell it that it's being used interactively:
This will switch interactive behaviour on. Note that when used interactively, CDU displays a small prompt before accepting each line of input.
Normally, CDU only obeys the command currently being constructed when one of two things happens: either the end of the input stream is detected or the first word of the next command forces the last command to execute. This, of course, takes place transparently unless one is using the program interactively. Usually, in such circumstances, one would want an end-of-line to "flush" the current command so that it executes. That's exactly what the FLUSH switch is for:
You may be relieved to know that the DOT word does both of these and, in addition, will open the console standard input stream if it's not already open. Hence, the best way to invoke CDU interactively is merely to type:
Please note the the flushing enabled by the FLUSH word is a bit crude - what CDU actually does is to append a DOT word onto the end of every line typed if FLUSH and INTERACTIVE are enabled. This was a simple kludge that made interactive use much easier at the expense of only a couple of lines of code.
When CDU is used interactively, you must use the EXIT to terminate CDU gracefully.
In order to associate a drive model and serial number string, use the NAME directive. For example, if you have a drive which produces "ACME" as the model string and "12345" as the serial number and you want to call it "FRED", invoke the NAME directive as in the above example.
Note that all non-printable characters are filtered out of the string and, when actually using the model and serial number strings, CDU places a colon between them.
This is the "negative" key word used to turn switches off.
This is the "positive" key word used to turn switches on.
As indicated in the entry for the BEEP word, CDU's behaviour can be altered with reference to the sounds that it makes at the end of a process.
Normally, it'll always beep and you will either hear an "all OK" beep or a "something's wrong" beep. On occasion, one might like CDU to remain silent unless something goes wrong. Using the ONERROR in conjunction with the BEEP switch will have the desired effect.
If the occasion arises where one needs to force CDU to "probe" for drives more than once, use this word to do that. Usually, this happens when using CDU interactively.
Sector ranges are specified by citing a start sector and an end sector which are separated by a colon.
Each of these two sector numbers are made up of two parts, the absolute part and the relative part. The latter is known as the "offset". Just before the command is executed, the offset is added (or subtracted from) the absolute part.
The absolute part can be either a simple number or it can be one of two words that indicate the start or end of the device's stream. So, for example, both "2880" and "END" can be used to refer to the last sector of a standard three inch floppy diskette. In order to refer to the sector before the last sector, one could use "2879" or the more lucid "END-1".
Let's say you want to copy all of a floppy except the first hundred sectors and the last hundred sectors. You could use a range of "100:2781". However, this range can also be written as "START+100:END-100".
If one of the sectors numbers in a range has the absolute part missing, then the relative part is treated as length and the absolute part is copied from the other sector number's absolute part.
For example, the last hundred sectors on our three inch floppy can be specified as:
"2781:2879" or "END-99:END" or "-100:END"
Note, in that last version, by the way, that "END:-100" won't work because, when the length is applied to the "end of range" sector number, it'll end up being smaller then the "start of range" sector number.
In a similar manner, ranges like "START:+100" can be specified and this, as one might expect, means "the first hundred sectors".
When a long operation is carried out - a full disk backup, for example - it can be very useful for the program to keep "nagging" us when it's finished. For example, if we use the above example command, we can make a cup of tea and listen out on the intercom for the "nagging" that CDU will do when it has finished.
CDU will only perform this action when it exits. It will nag by repeating the last sound it made. So, for example, if the last thing it did was successful, it'll be a "happy" sound. Otherwise, it'll nag using a "sad" sound. This nagging will be inhibited if CDU is being used interactively.
The value following the keyword, by the way, is the number of seconds between "nags". Using a value of zero will disable this feature.
When using the INT13 (rather than the INT13EX) interface, it is up to the programmer to retry disk operations to see if they will succeed after a previous attempt has failed. (For example, if a floppy drive has shut its motor off, the first couple of disk accesses may fail whereas subsequent attempts may succeed.)
In the past, I've found it useful to be able to vary the number of retries that should be done - too many and one gets impatient waiting for a program to time out on a disk that one knows will fail while too few may cause a disk to be rejected which, although marginal, may actually be readable .
This word allows the script writer to send messages to the user. So, for example, "comfort" text can be sent as the script progresses.
Note that text macro are expanded before the text is displayed. Hence, something like this typed at the MSdos command prompt will work as expected:
CDU SAY "THE COMMAND PROMPT IS SET TO '%%PROMPT%%'"
The requirement for extra percent signs is explained in the section on VCHAR. (Note also, that the double-quotes are required when the message text contains a space.)
There are complications when using text macros concerned with the character used to indicate that an expansion is required and also with the treatment of special (that is, "escaped") characters within the expanded text. This subject is explained in the section on VCHAR.
This word allows you to make CDU search for a particular text pattern in a source stream. If one had intended to search for a JPEG file header on the E: drive, the above example would not work - the text search is case sensitive and the JPEG header text is "Exif" not "EXIF". In addition, the "C"-like escapement system that was used in an attempt to search for a trailing zero character (the "\X00" bit) is also case-sensitive and, hence, one would have had to use this instead:
SEARCH VOLUME E: OFFSET 100000 FOR "Exif\x00"
By the way, when presenting the text search pattern, if the pattern does not contain a space, then the double-quotes are not necessary; this, for example, is perfectly acceptable:
SEARCH DISK HD2 FOR FAT
There appears to be no satisfactory way of obtaining a large file's size under MSdos. This is a problem because, if a "range end" sector number is left as the termination value, CDU will complain that the file is not at its end when a copy or compare is executed.
If the file size (in sectors) could be ascertained, then this value would be treated in a similar manner to a disk's "total sector count" value. MSdos does, however, allow us to get at the size of a file if it's less than 2 GB in length. Currently, CDU defaults to a state whereby it will use this value to calculate last sector number values of any source files opened. Since this could, conceivably, cause problems, there is a switch to disable this "file sizing" operation:SIZING DISABLE
There is a similar problem with DISKs and VOLUMEs. Please consult the entry for the AUTOEND word.
This word is used to introduce a source data stream. Like the TARGET word, it can sometimes be implied and, therefore, be omitted completely from the command.
The START keyword is used to refer the first sector of a stream's data. (Note that this may, actually, be meaningless; for example, see the entry relating to BYTE streams.) See the item on sector ranges for details.
This word causes CDU to print a list of the current switches and settings.
By default, CDU uses direct BIOS calls to find out whether a key has been pressed and to retrieve a keys value. The reason for this is that, under standard ANSI "C", there's no portable way of accessing the keyboard in a manner which doesn't "block" the running process.
This matters not when you are banging away at a standard IBM PC keyboard. However, if you try to run CDU over, say, a TELNET connection where all I/O is re-directed, then the BIOS keyboard handling calls won't work correctly. Hence, we have a word to make CDU use standard keyboard calls:
Note that there is one important limitation when "standard keyboard" is enabled: you cannot interrupt a running CDU program. (Because, as stated, any invocations of the "get keyboard char" library calls would block the running process.) So, if you enable standard keyboard I/O, make sure what you ask for before answering the "execute this command" question!
Also, you may have to press a carriage-return after you answer any questions whereas, in its default state, CDU doesn't require anything other than a "yes" or "no" character before continuing.
This word is used to introduce a target data stream. Like the SOURCE word, it can sometimes be implied and, therefore, be omitted completely from the command.
Since the DEBUG directive can produce so much output, we've added a "filter" facility. The output produced by "DEBUG ON" prints, as the first item on each line, the function entry point name. One can use the TRACE directive to dictate which function's output will be listed and which will be ignored. The strings after the TRACE directive is a wild-card string that will be tested against the current function name before the debug output is actually printed.
For example, if you wanted to only see the diagnostics relating to handling of the internal list of disk drives, use this:
CDU IDENTIFY TRACE *DISKTABLE* DEBUG INFO
While macro name expansion defaults to using the percent character and the special character delimiter is a back-slash, these "special" characters can be changed. Why would you want to do this? Well, consider the following: the percent character isn't a good choice if you want to send the commands to an MSdog command-line interpreter since the percent is also special to that. As a result, in order to have CDU "see" a per cent sign in its parameters, you have to use two percents. Thus, while this won't work:
CDU DEFINE X XXX SAY %X%
CDU DEFINE X XXX SAY %%X%%
CDU SAY %%PATH%%
You'll get a bit of a surprise because the "special" character processing is carried out after macro name expansion. As a result, using the default characters, the PATH environment variable will have all the back-slashes treated as special character introductions and all the file names will be corrupted.
This is how the special characters are changed from the defaults; this will change the special character from the default of a back-slash to a "hash":
Likewise, we can change the macro expansion character from the default percent to a "pling" by using this:
If we refer back to our above example of printing out the system's PATH environment variable, we could make CDU report the correct PATH by altering SCHAR before printing the message. (Note that the alteration of the VCHAR value isn't actually required but it does serve as an example of the effect of changing VCHAR.)
CDU VCHAR '!' SCHAR '#' SAY !PATH!
As usual, the normal "number grammar" can be used so these would have been acceptable alternative:
SCHAR 0X23 ; An alternative to "SCHAR '#'" VCHAR 0X21 ; An alternative to "VCHAR '!'"
This word increases the amount of "waffle" produced by CDU. This can sometimes be useful when trying to solve disk-related problems.
Using this word is merely a short cut for a more detailed version of the INFO word. It is exactly equivalent to the following:
DETAIL ON INFO
The VOLUME word is used to specify the volume stream type. Volume streams are accessed via the standard INT25 and INT26 APIs.
Note that not all disk types are accessible via this interface. For example, ZIP disks are fine but CD-ROMs may not be.
In order to prevent embarrassing little "accidents", the writing to disk and volume streams is disabled by default. Enabling the WRITE switch will permit writing to these streams. As far as volume streams go, that's it. (This means that it's very important, when targeting a volume stream, to make sure you don't, for example, use "C:" when you meant to say "A:"...)
However, CDU can detect the difference between floppy and hard disk streams. In order to prevent even more embarrassing accidents, there are separate switches for writing to floppy disks and hard disks. These are FWRITE and HWRITE respectively.
Older versions of CDU only had the WRITE switch and, to provide backwards compatibility, enabling WRITE will allow writing to both sorts of disk. However, with later versions, one can use the word that corresponds to the type of disk you are targeting.
If, for example, you've made a batch file that provides a target floppy drive name to CDU, then it's probably a good idea to enable writing using FWRITE rather than plain old WRITE:
FWRITE ENABLE COPY FILE FLOPPY.IMG TO DISK %DRIVE%
This way, if the user provides the wrong sort of drive name (for example, "HD0"), then total disaster is averted. If a user did do this, imagine what would've happened had you written the script thus:
WRITE ENABLE COPY FILE FLOPPY.IMG TO DISK %DRIVE%
In this case, the COPY could still continue with, no doubt, catastrophic results.