Wednesday, October 17, 2018

Code review: parsing the command line

This is a continuation of the Code Review article series.

At its core, DOS is a command line operating system. Sure, many users might only use the command line long enough to launch their favorite DOS application or game. But for many FreeDOS users and developers, the command line is where it's at.

When I first started working on FreeDOS, I wanted to make sure FreeDOS programs could parse the command line easily and consistently, so every FreeDOS program used pretty much the same syntax. Or as similar as possible.

Let's do a quick review: on DOS systems, most command line programs and utilities use the slash character (/) to start a command line option. Options can be single-letter or single-character options, or they can be entire words. For example, a standard option to tell the program to display a "Help" page is /?. Depending on the program, you might have other command line options, such as /A (perhaps to indicate "all") or /FORCE (to force an action). And on DOS, the options are usually case-insensitive, so /A and /a would usually be treated the same.

Under Unix and Linux systems, the standard way to parse command line arguments is via the getopt() system function. This function allows the program to parse the command line for options that begin with a hyphen (-) such as -a or -o. You can give an argument to an option using the equal sign (=) such as -f=file.txt, or as a following argument such as -f file.txt. GNU extended getopt() to provide a getopt_long() function, which makes command line options more readable. Long options start with a double dash (--) such as --print-all, and can include a short option alternative such as -a (same as --print-all).

For FreeDOS, I didn't want to re-invent the wheel. Why write a completely new library when I can modify something that already does the job? I modified the GNU getopt library to provide a DOS version of getopt() and getopt_long(). I also did some code cleanup to remove some Unix-y things and make the library more suitable for DOS. You can find version 1.2 of the FreeDOS getopt library at ibiblio under files/devel/libs/getopt.

The Readme provides a quick overview and changes from the GNU version, including:

The getopt_long() function works like getopt() except that it also
accepts long options, started out by a slash char.  Both long and
short options may take arguments, which are set off by equals ('=').

Short options are case sensitive.  Long options are not.  This is a
compromise from the UNIX getopt().

The getopt_long() function returns the option character if the option
was found successfully, ':' if there was a missing argument to one of
the options, '?' for an unknown option character, or EOF for the end
of the option list.

getopt_long_only() returns the option character when a short option
is recognized.  For a long option, they return val if flag is NULL,
and 0 otherwise.  Error and EOF returns are the same as for getopt(),
plus '?' for an ambiguous match or an extraneous parameter.

See the foo.c sample program to see how to use getopt_long.


I have not yet implemented all features from GNU getopt_long:

 - flag is not used in longopts.

 - longindex is not yet used.

These should be implemented in a future version of getopt_long.


Options must be separated on the command line.  Combining options is
not allowed.  You must write: "foo /a /v" and not "foo /av".  The
second version would try to match a long option called "/av".

Also, you must write: "foo /a /v" and not "foo /a/v".  The second
version would try to match a long option called "/a/v".

I should note this is not a perfect replacement for standard MS-DOS command line parsing. In classic MS-DOS, command line options always start with a slash character, no matter if a long or short option, and you don't need to separate them with spaces. So an MS-DOS program that used both the /A and /V options would interpret /A/V and /A /V as the same. But for the purposes of providing a standard command line experience, I figured this was a good trade-off.

You use the FreeDOS getopt just like the GNU getopt. Here's a sample program:

  The following example program, adapted from the GNU getopt_long
  manual, illustrates the use of getopt_long() with most of its

/* This program should compile under Linux and DOS equally well. */

#include <stdio.h>

#ifdef unix
#define _GNU_SOURCE
#include <getopt.h>
#else /* assumes DOS */
#include <stdlib.h>
#include "getopt_l.h"

main (argc, argv)
     int argc;
     char **argv;
  int c;
  int option_index = 0;
  static struct option long_options[] =
    {"help", 0, 0, 'h'},
    {"verbose", 0, 0, 'v'},
    {"extra", 1, 0, 'x'},
    {0, 0, 0, 0}

  while ((c = getopt_long (argc, argv, "x:hv",
         long_options, &option_index)) != EOF)
      switch (c)
      case 'x':
        printf ("x -> option = %s\n", optarg);
      case 'h':
        printf ("print help\n");
      case 'v':
        printf ("verbose mode = on\n");
        printf ("?? getopt returned character %c (optopt=%c)\n", c, optopt);

  if (optind < argc)
      printf ("non-option ARGV-elements: ");
      while (optind < argc)
 printf ("%s ", argv[optind++]);
      printf ("\n");

  exit (0);

The key is that you define the long options in a structured list, where each item gives the long option name, whether or not the option takes an argument, and the short option. End the list with zeroes.

Each time you call getopt_long(), the function returns the next option on the command line. It does some work behind the scenes to re-order the command line, in case the user put some command line options after regular arguments. For each option returned, use a switched block to trigger an action, such as setting a flag.

After all command line options are processed, the getopt library sets a variable (optind) to the index in the command line vector (in this case, argv) for the first regular option. In many programs, the regular options are files that the program will act against.

Sunday, September 30, 2018

Practical thoughts on MS-DOS source code

I recently wrote that Microsoft released the source code to MS-DOS v1.25 and v2.0 on Github. This is a huge step for Microsoft, and I congratulate them for releasing these older versions of MS-DOS under the open source MIT license!

This source code release was significant because it resolved an issue from Microsoft's previous attempt to open the source code to older MS-DOS. In 2014, Microsoft released the source code to MS-DOS 1.1 and 2.0 via the Computer History Museum. Unfortunately, the license used in the Museum release was a "look but do not touch" license.

My understanding from lawyers who have explained it to me (I am not a lawyer) is that you can be "tainted" by knowledge of proprietary source code, under US law and under similar laws agreed to by partner countries. So anyone who read or studied the source code to MS-DOS 1.1 or 2.0 as it was previously released via the Computer History Museum license was not allowed to contribute to FreeDOS afterwards. We posted several notices to this effect on the FreeDOS website and elsewhere.

But this source code release of MS-DOS 1.25 and 2.0 uses the MIT License, which is not only a recognized open source software license, but compatible with the GNU GPL. This means the "taint" concern is effectively lifted.

While this is great, there's a practical side to the source code release. Note that these are very old versions of MS-DOS. FreeDOS has already surpassed these versions of MS-DOS in functionality and features. For example, MS-DOS 2.0 was the first version to support directories and redirection. But these versions of MS-DOS did not yet include more advanced features including networking, CDROM support, and '386 support such as EMM386.

It's great to see Microsoft open-source these old versions of MS-DOS, but what will be the practical impact on FreeDOS? I think Tom E. answered this well:
“Frankly, not so much. the relevant facts about MSDOS like internal structures, memory layout aso. have been re-engineered/disassembled, documented and commented by Andrew Schulman, Mike Podanowsky, and MANY others, and merged in an almost complete (and almost correct) documented DOS API by Ralph Brown. thanks to them, and there is close to nothing to be learned by studying old MSDOS sources.”

Eric A. adds a similar comment:
“Well, this is mostly interesting for historical research, MS DOS 1.25 had almost no features and 2.0 also is very far away from running most "normal" DOS software.”

So FreeDOS would not be able to reuse this code for any modern features anyway. But for basic features, such as weird edge cases or specific application compatibility, maybe developers can reference this code to improve FreeDOS.

Set your expectations appropriately. Thanks to Microsoft for releasing this source code under an open source software license (MIT) but don't expect this to have much impact on FreeDOS. We've already advanced well beyond MS-DOS 1.25 and 2.0.

Microsoft open-sources old versions of MS-DOS

Microsoft recently released the source code to MS-DOS v1.25 and v2.0 via a repo on Github. This is a huge step for Microsoft, and I congratulate them for releasing these older versions of MS-DOS under a recognized open source software license!

This source code release uses the MIT License (also called the Expat License). From Microsoft's file on Github:
[MS-DOS 1.25 & 2.0 Source]
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, freeof charge, to any person obtaining a copy of this software and associateddocumentation files (the Software), to deal in the Software withoutrestriction, including without limitation the rights to use, copy, modify,merge, publish, distribute, sublicense, and/or sell copies of the Software, andto permit persons to whom the Software is furnished to do so, subject to thefollowing conditions:

The above copyright notice andthis permission notice shall be included in all copies or substantial portionsof the Software.

(typos are from original; copied 9/30/2018)

This is the same as the MIT License recognized by the Open Source Initiative:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


And the same as the Expat License recognized by the Free Software Foundation:
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


The Free Software Foundation (via GNU) says the Expat License (aka "MIT License") is compatible with the GNU GPL. Specifically, GNU describes the Expat License as:
"This is a lax, permissive non-copyleft free software license, compatible with the GNU GPL. It is sometimes ambiguously referred to as the MIT License."

Also according to GNU, when they say a license is compatible with the GNU GPL, "you can combine code released under the other license [MIT/Expat License] with code released under the GNU GPL in one larger program."

That means this source code release of MS-DOS 1.25 and 2.0 removes the concern of "taint" that we had with the previous MS-DOS source code, released via the Computer History Museum in March, 2014. Longtime FreeDOS users may recall that Microsoft posted the source code to MS-DOS 1.1 and 2.0 under a "look but do not touch" license that limited what you could do with the source code. Under the Museum license, users were barred from re-using the source code in other projects, or using concepts from the source code in other projects:
You may use, copy, compile, and create Derivative Works of the software, and run the software and Derivative Works on simulators or hardware solely for non-commercial research, experimentation, and educational purposes. Examples of non-commercial uses are teaching, academic research, public demonstrations, and personal experimentation. “Derivative Works” means modifications to the software, in source code or object code form, made by you pursuant to this agreement.
  • You may copy and refer to any documentation provided as part of the software.
  • You may not distribute or publish the software or Derivative Works.
  • You may not use or test the software to provide a commercial service unless Microsoft permits you to do so under another agreement.
  • You may publish and present papers or articles on the results of your research, and while distribution of all or substantial portions of the software is not permitted, you may include in any such publication or presentation an excerpt of up to fifty (50) lines of code for illustration purposes.
(emphasis mine)

I am not a lawyer, but even I can see this license does not allow users to re-use the MS-DOS source code, especially in open source software projects like FreeDOS. We saw this as a potential risk to FreeDOS; developers who had viewed the MS-DOS source code might "taint" FreeDOS if they later contributed to FreeDOS. To avoid this taint risk, we posted several announcements on the FreeDOS email lists and on the FreeDOS website, including on our FreeDOS History page, to warn FreeDOS developers that they should not view the MS-DOS source code. Anyone who did view the MS-DOS source code could not contribute to FreeDOS:
"Please note: if you download and study the MS-DOS source code, you should not contribute code to FreeDOS afterwards. We want to avoid any suggestion that FreeDOS has been "tainted" by this proprietary code."

But Microsoft's adoption of the MIT License is a significant change. The new MIT License is compatible with the GNU GPL. Therefore, the risk of taint seems to be removed. Congratulations to Microsoft for releasing MS-DOS 1.25 and 2.0 under an open source license!

Saturday, September 8, 2018

Code review: Using catgets/kitten to support different languages

This Code Review article is a repeat from last year, about how to use the Cats and Kitten libraries to support different spoken languages in your programs.

When you write a new program, you probably don't think about spoken languages other than your own. I am a native English speaker, so when I write a new program, all of my error messages and outputted text is in English. And that works well for the many people who have English as their native language, or who know enough English as a second language to get by. But what about others who don't speak English, or who only know a little English? They can't understand what my programs are saying.

The standard Unix method is with a set of C library functions built around language "catalogs." A catalog is just a file that contains all the error messages and other printed text from a program. In the Unix method, you have a different catalog for every language: English, German, Italian, Spanish, French, and so on.

The FreeDOS Cats library was a stripped-down implementation of the Unix library, using a very simple method. Every time you want to print some text in the user's preferred language, you first look up the message string from the catalog using the catgets() function—so named because it will get a string from a message catalog.

In Unix, you use catgets() this way:

  string = catgets(cat, set, num, "Hello world");

This fetches message string number num from message set set, from language catalog cat. The organization of messages into sets allows developers to group status messages into one set (say, set 1), error messages into another set (such as set 7), and so on.

Before calling catgets(), you need to open the appropriate language catalog with a previous call to catopen(). Typically, you have one catalog per language, so you have a different language file for English, another for Spanish, etc. Before your program exits, you close any message catalogs with calls to catclose().

If the string doesn't exist in the message catalog, catgets() returns a default string that you passed to it; in this case, the default string was "Hello world."

I implemented a simplified version of these functions in a FreeDOS Internationalization library called Cats. To save on memory, Cats supported only one open catalog at a time. If you tried to open a second message catalog, the call to catopen() would return an error (-1).

Message catalogs were very simple under Cats. Implemented as plain text files, Cats loaded the entire message catalog into memory at run-time. In this way, you didn't need to recompile the program just to support other languages; you just added another message catalog file for the new language. An English message catalog for a simple program might look like this:

  1.1:Hello world
  7.4:Failure writing to drive A:

The same message catalog in Spanish might look like this:

  1.1:Hola mundo
  7.4:Fallo al escribir en la unidad A:

For example, the string "Failure writing to drive A:" is message number 4 in set 7.

The Cats library was a simple way for developers to add support for different languages in their programs, written in C. And because Cats implemented a Unix standard, it made porting Unix tools to FreeDOS much easier. Once you added the calls to catgets(), all you needed to support other languages was a message catalog that someone translated to a different language. And I kept the Cats message catalogs very simple; they were plain text files.

Cats was a neat innovation, but loading the messages into memory was cumbersome because it used streams. Other FreeDOS developers improved on Cats to optimize the loading of catalogs, reduce memory footprint, and add other enhancements. The new library was noticeably smaller, so we renamed it Kitten.

Because of the optimizations, Kitten used a slightly different API. Since Cats only supported one message catalog at a time anyway, Kitten removed the cat catalog identifier. Once you open a message catalog with kittenopen(), all calls to kittengets() assume that message catalog. You only need to make a single call to kittenclose() before you end the program.

Using Kitten made it much easier to support different spoken languages in FreeDOS programs. Here's a trivial example to put it all together:

  /* test.c */

  #include <stdio.h>
  #include <stdlib.h>
  #include "kitten.h"

    char *s;
    s = kittengets(7, 4, "Failure writing to drive A:");

This loads a message catalog "test" into memory, then retrieves message 4 from set 7 into a string pointer s. If message 4 in set 7 isn't found, kittengets() returns the default string "Failure writing to drive A:" into s. The program prints the message to the user, then closes the message catalog before exiting.

Typically, you name the message catalog after the program's name. So the message catalog for the FreeDOS CHOICE program is "choice". Kitten searches for the language file in a few locations on disk, and always appends the value of the %LANG% environment variable, which is typically set to the two-letter language abbreviation: "en" for English or "es" for Spanish. The DOS filename for the English version of the "choice" language catalog is CHOICE.EN, and the Spanish language version is CHOICE.ES.

A limitation to Cats and Kitten is that it can only support single-byte character sets supported by DOS. So Cats and Kitten cannot support Chinese or Japanese, but should do fine with most other languages.
You can find Cats and Kitten at the FreeDOS files archive on ibiblio, under devel/libs/cats/

We made three revisions to Kitten, so the latest version is Kitten revision C, which you can download directly as

FreeDOS contributor Mateusz "Fox" Viste wrote a similar implementation for Pascal programs, called Cubs. You can also find it on ibiblio, under devel/libs/cats/cubs/

FreeDOS developer Eric Auer created a command-line version of Kitten, named Localize, so you can provide internationalization support for DOS Batch (BAT) files. Find it on ibiblio, under devel/libs/cats/localize/

Tuesday, August 21, 2018

New article series: code reviews

I've been thinking of ways to get new developers interested in working on FreeDOS, or at least contributing to FreeDOS in some way. I recognize that DOS is an old concept for some, and as a result, the way you construct programs for DOS can differ to how you'd construct programs for other operating systems such as Linux.

Sure, programs like Choice and Type and Find and other everyday command-line utilities are pretty straightforward. You'd probably write a DOS Type command in the same way you'd write a Unix ‘cat’ command (using streams). But other programs require different methods.

So I thought some kind of “code review” would be helpful, as a way to demonstrate certain DOS programming methods. I'll plan to examine a FreeDOS program and pull apart a specific function or method or programming trick to show how you can use these methods in your own programs.

It will be easiest for me to do a code review on my own programs, and I may start there. But I will try to explore different FreeDOS programs written by different people, so you can see a variety of methods. Every programmer is different, and this will highlight different ways to implement features or optimize execution or minimize footprint when programming in DOS.

Do you have a program you'd like to highlight? I welcome any guest posts in this series. If you have something you'd like to show off, please email me or leave a comment below. I'd be happy to include your article as a guest post here. (If you submit a guest post, it will be easiest if you can share your contribution under the Creative Commons Sharealike [cc-by] public license.)

What programs or methods would you like to see? If you have a suggestion for a “deep dive” into a FreeDOS utility, let me know! My expertise is C, so I am more likely to do code reviews for programs written in C.

Thursday, August 2, 2018

Expanding the FreeDOS COMMAND.COM

The FreeDOS COMMAND.COM (also known as "FreeCOM") is a compatible equivalent to MS-DOS COMMAND.COM. FreeCOM doesn't do anything special; it just creates a command prompt that lets you run programs.

FreeCOM also supports the standard MS-DOS batch programming syntax. Any batch script that runs in MS-DOS should run in FreeCOM. And any batch script you write for FreeCOM will run in MS-DOS COMMAND.COM.

From a recent discussion on the email list, I'd like to suggest an extension to FreeCOM. Maybe this would be better implemented as part of a new alternative shell, but it would be really interesting to see it added as a feature to FreeCOM.

Here's my idea: create a BASIC-like programming language that also supports MS-DOS batch scripts.

DOS batch scripts are simple affairs. Really, the idea behind the MS-DOS batch was to "batch up" a bunch of simple commands. DOS batch programming supports minimal flow control. You can query the exit status (ERRORLEVEL) of the previous command, and you can jump around the script (GOTO) but DOS batch programming doesn't support much else.

I'd love to see an extension to DOS batch programming. Something like a BASIC interpreter would be interesting, if it executed commands in the PATH if the instruction wasn't a keyword.

I wonder if someone is interested in writing a BASIC-like "shell"? Something that uses a combination of BASIC and COMMAND.COM syntax would make the interpreter a "superset" of COMMAND.COM, and an interesting new alternative shell.

Some suggestions for how to extend BASIC and DOS batch programming include:


Variables can store either numerical or string data. Variable names can be of any reasonable length, and can be referenced in uppercase or lowercase.

Use SET to assign values to variables, and BASIC's LET to assign values based on arithmetic. LET becomes a superset of SET:

And surround a variable with % to reference its value:
LET A=%A%​ ​+​ ​1

Possibly allow %% as a prefix to reference the value from a variable, interchangeably: (sloppy, but see later)
LET A=%%A + 1


Use ECHO to display output instead of PRINT:
ECHO Hello world


Support the standard DOS batch programming tests, such as == to test equality, and NOT to negate a test. Add extra constructs to test inequality, greater-than and less-than. One possible solution is to support simple DOS batch programming IF constructs and use Unix-style brackets for the extra constructs:

IF %VALUE%==1 ECHO Equal
IF NOT %VALUE%==1 ECHO Not equal

IF [ %VALUE% EQ 1 ] ECHO Equal
IF [ %VALUE% NE 1 ] ECHO Not equal
IF [ %VALUE% GT 1 ] ECHO Greater
IF [ %VALUE% GE 1 ] ECHO Greater or equal
IF [ %STR% LT "ABC" ] ECHO Less


The FOR statement would need to be extended as a for-next loop:
FOR N IN 1 TO 10

Or as the traditional DOS for-do one-line shortcut:

And add a special IN (…) construct to create an iteration over a set:
FOR %%N IN (1 2 3 4 5 6 7 8 9 10) DO ECHO %%N

​(If the language allows %A% and %%A then DOS batch programs would probably work seamlessly. But it's sloppy coding. Other ideas?)


Similar to both BASIC and DOS batch programming, GOTO could use : to mark labels:
LET N=%N% + 1


And of course, comments remain the same from BASIC and DOS batch programming:
REM This is a comment


If you called the BASIC-like "shell" using a special parameter (like /P) then it would be nice for anything e​lse you specify that isn't recognized as a shell statement (assuming other syntax is correct) get treated like an external command. That would make this more like a shell:

Also other internal constructs for CALL and ERRORLEVEL and SHIFT and PATH, but you get the idea.

If you can preserve COMMAND.COM syntax and add a BASIC-like programming language behind it, that would make this an interesting extended shell. Maybe an idea for an interested developer?
Note: Tom points out that Microsoft similarly extended the COMMAND.COM batch programming language when creating CMD.EXE. For example, for /L %%N in (1,1,10) do echo %%N (iterative loops) and SET /A A=%%A + 1 (arithmetic). So this hybrid BASIC-like batch programming language idea is not new.

Sunday, July 22, 2018

Planning FreeDOS 1.3

We've started planning the FreeDOS 1.3 distribution! We previously decided the next release would be an iteration from FreeDOS 1.2. We wanted the next FreeDOS distribution to remain like classic DOS. For example, we won't "retire" any classic commands utilities from Base. But FreeDOS 1.3 is an opportunity to improve and update several things.

Compatibility remains key. FreeDOS 1.3 will remain 16-bit, and will focus on a single-user command line environment, just like classic DOS. The "Base" package group will still contain everything that replicates the functionality found in MS-DOS, although we plan to promote Zip and Unzip from "Util" to "Base." This is because all FreeDOS packages are really zip files, so it makes sense to include tools in "Base" that let you create and modify your own packages. And Zip and Unzip provide a handy way to backup and restore your system; while not compatible with MS-DOS Backup and Restore, Zip and Unzip provide a modern spin on that functionality.

FreeDOS 1.3 will follow a similar release schedule as used in FreeDOS 1.2. The deadlines are: No new packages after September 30, 2018. No new languages after October 31, 2018. Assuming these deadlines, the expected schedule is:

  • November 30, 2018 - FreeDOS 1.3 RC1
  • December 31, 2018 - FreeDOS 1.3 RC2
  • January 31, 2019 - FreeDOS 1.3 release

Please join the freedos-devel email list and contribute to the discussion! Also keep an eye on the FreeDOS Road Map on the FreeDOS Wiki for more updates. Looking for ideas to contribute to FreeDOS? See our Contribute page for several suggestions.

Updating the FreeDOS website

I just wanted to share a quick note that I am planning to update the FreeDOS website. I'm not planning any site redesigns; the website should still look the same. But I am moving to a new web host provider. Among other things, the updated web host will provide and manage https for me.

Dates are approximate, but I'll set up a test site on the new provider in early August, and plan to move the site in mid August. I'll leave the old web host for another week, while DNS changes propagate everywhere. We should be fully on the new web host by late August, and I'll retire the old web host at that time.

The new web host will also include a custom MediaWiki instance for us. Currently, the FreeDOS Wiki runs on a custom MediaWiki hosted at SourceForge. This has worked well, aside from a few unplanned downtimes. Also, the SourceForge-hosted MediaWiki instance doesn't allow outbound emails, which is the main stumbling block to let other users create their own accounts. (Wiki Admins have had to do this, and it's a huge pain; I never remember how to do it.)

I'll plan to move the FreeDOS Wiki in September, well after the website move.

Thursday, July 12, 2018

FreeDOS batch programming quick reference

A few weeks ago, I posted a "quick reference" for our new users. This reference showed the most common FreeDOS commands, including a few important notes for new users.

If you're looking to take the next step in FreeDOS, here's a handy quick reference guide to batch programming.

DOS batch programs are simple scripts that "batches up" several commands into one file. Batch programs have some basic flow control that you can use to do loops and jump to different segments of the program. In batch programs, reference variable values by enclosing the variable name with %, such as %PATH%

What do you want to do?How to do it in a batch program:
Execute another batch script from within a scriptCALL SCRIPT.BAT
Run a command for each file in a listFOR %%F IN (*.TXT) DO EDIT %%F

or at the command line:

The loop variable name can only be one character.
Print a messageECHO Hello world
Jump to a label in a batch file:LOOP
Test the value of a stringIF %VAR%==Y ECHO Yes
Test if a file existsIF EXIST TEMP.DAT DEL TEMP.DAT
Test the return value of the previous commandIF ERRORLEVEL 0 ECHO Success
Test the oppositeIF NOT ERRORLEVEL 0 ECHO Fail
Set the shell's search path for programsPATH C:\FDOS\BIN;C:\MY\BIN

or to reference the existing path:

Use ; to separate paths.
Shift the command line optionsSHIFT or SHIFT 1 or any n

Reference command line options as %1, %2, and so on.
A commentREM This is a comment

Friday, June 29, 2018

FreeDOS commands quick-reference

FreeDOS turns 24 years old today (June 29)! That's a long time for any open source software project. Thanks to our FreeDOS community for keeping things going. And a special "thank you" to our developers, who continue to add new features and fix old bugs. You truly make FreeDOS better!

To celebrate this year's anniversary, I wrote a "quick reference" for our new users. This reference shows the most common FreeDOS commands, including a few important notes for new users.

You may also want to check out the free ebook we published last year: 23 Years of FreeDOS.

What do you want to do?How to do it on FreeDOS:
List directory contentsDIR
-in the directory “above”DIR ..
-in a different directoryDIR C:\FDOS\BIN
Change the current driveD:
Change the current directoryCD \FDOS\BIN
-“up” one directoryCD ..
Display the contents of a fileTYPE FILE.TXT
-one screen at a timeMORE FILE.TXT
Delete a fileDEL FILE.TXT
Copy a directory and its contentsXCOPY DIR NEWDIR
Delete a directory and its contentsDELTREE MYFILES
Create a new directoryMKDIR NEWDIR
Remove an empty directoryRMDIR MYFILES
Rename a file or directoryREN FILE.TXT FILE.OLD
Show all lines in a file that contain “HelloFIND "Hello" FILE.TXT
-without regard for caseFIND /I "Hello" FILE.TXT
Clear the screenCLS
Edit a text fileEDIT FILE.TXT
View and set the dateDATE
View and set the timeTIME
Show the usage for a programDIR /? (for most programs)
Get systemwide helpHELP
Show the command historyHISTORY
Show the DOS versionVER

A few things to remember:
  • DOS commands and filenames can be upper or lowercase (DIR is the same as dir)
  • Pipes (|) are the same on DOS as on Linux
  • Output redirection (>) is the same too
  • . and .. are the same on DOS as on Linux
  • The directory separator is \ (such as C:\ or C:\FDOS or C:\FDOS\BIN)
  • File and directory names can only be 8.3 characters long (such as FILENAME.EXT)
  • DOS uses letters for each drive (C: is the first hard drive)
  • A full path is a drive letter and a directory path

Looking for more? I wrote a full FreeDOS cheat sheet for OpenSource, which you can find here: Celebrating 24 years of FreeDOS: Useful commands cheat sheet.

Saturday, May 19, 2018

Tutorial: Installing extra software with FDIMPLES

The FreeDOS software distribution originally started as a set of programs to replace the functionality of MS-DOS. We surpassed that goal a long time ago, and only our "Base" install distribution replaces the original DOS. If you install the "Full" distribution, you get everything in "Base" plus a bunch of other useful FreeDOS programs that we find useful.

Programs in the FreeDOS distribution are included as "packages" that can be easily installed by the FreeDOS install program. Really, these are just standard zip files with a predictable directory layout, such as BIN for executable programs, HELP for any help files, SOURCE for original source code, and so on.

For the FreeDOS 1.2 distribution, we include the usual "Base" and "Full" packages, which you can install automatically as part of the FreeDOS 1.2 installer. But we also include a bunch of extra programs. These other programs are helpful programs that maybe not everyone will want to install, but we wanted to make available to you as part of the FreeDOS 1.2 distribution.

To install these packages, you use the FDIMPLES program. FDIMPLES is a derivative of the FreeDOS installer, and stands for FreeDOS Install - My Package List Editor Software. Make sure you have the FreeDOS 1.2 installation CD in your CDROM drive, then type FDIMPLES to start the program.

Installing a program

Let's walk through a simple case of installing a program. Maybe this is one of the extra software packages, or maybe you installed just the "Base" software set and want to install other packages later on. I like the game WING, so I'll demonstrate with that.

After you start FDIMPLES, you'll see a list of package sets on the left, and a list of packages from that set on the right. As you navigate through each package, you'll see the full package information below:

To install WING, navigate down to the Games package set, and press Tab to get to the list of packages. Scroll down to the WING package, and press the Space bar to mark it with an X. This selects the package for installation:

You can select other packages, including packages from other package sets. When you're done, select OK at the bottom of the screen. FDIMPLES automatically installs the package or packages for you:

Removing a program

The steps to remove a program using FDIMPLES are basically the same as installing a program with FDIMPLES. To demonstrate, let's remove the WING game we just installed.

Again, when you start FDIMPLES, you'll see a list of package sets and packages:

Navigate down to the Games package set, and press Tab to jump to the list of packages. Scroll down to WING, and press the Space bar to remove the X. This tells FDIMPLES to remove it:

You can select other packages to remove, but for this demonstration, I'll leave it with just the one package. Select OK at the bottom of the screen, and FDIMPLES automatically removes the package for you:

Thursday, May 17, 2018

Tutorial: How to install FreeDOS

Need some help installing FreeDOS 1.2 on your computer? Here is a step-by-step guide to install FreeDOS. This how-to guide is adapted from Installing FreeDOS 1.2 on the FreeDOS wiki. You can find lots more information at our wiki, but I'm posting this guide to the blog so new users can find it with the other FreeDOS tutorials I'm writing here.

Installing FreeDOS uses the same process whether you install FreeDOS in a PC emulator or on actual hardware. Note that if you install in a PC emulator, you will probably need to set your system to boot from CDROM before the hard drive, so the FreeDOS install CDROM will boot first. We recommend the CDROM installer for most users. The “standard” CDROM image should work on most computers and PC emulators. Older computers may need the “legacy” CDROM image instead.

Booting the CDROM installer gives you a menu. You can choose to install FreeDOS, or boot from the system harddisk or from a diskette:

The installer supports different languages, which you can choose. The default is English:

Welcome to the FreeDOS 1.2 install program. We provide a standard warning here. For new users, we recommend installing FreeDOS in a PC emulator or “virtual machine.” If you install FreeDOS on a computer directly, without using a PC emulator, you may overwrite the operating system you have now (for example, Windows.) That's why we include a brief message about that in the FreeDOS distribution:

If your C: drive isn't partitioned for DOS, the installer detects that. To partition your hard drive, the installer will use the FDISK program:

Just follow the prompts. Select 1 to create the DOS partition. This will be your C: drive. Follow the other prompts to create the primary DOS partition. Note that if you don't use all free space to create your FreeDOS partition, you may need to mark the new partition as the Active partition, so FreeDOS can boot from it:

After you partition your hard drive, you need to reboot for FreeDOS to see the changes. Press ESC to exit FDISK. The FDISK program and the installer will warn you that you need to reboot your computer for the changes to take effect. The FreeDOS installer has an option to reboot your computer for you, so just use that:

After rebooting, the installer starts up again automatically. If your C: drive isn't formatted for DOS, the installer automatically detects that and can format it for you:

Your preferred language might not match your keyboard language, so we let you select your keyboard layout separately:

The FreeDOS 1.2 installer has two default install modes: install only those packages that reproduce the functionality of classic DOS (“Base”) or install everything (“Full”). Because FreeDOS is open source software, we give you the option to install source code, too:

Then just sit back and let the installer do its thing. The installer will let you know it has finished installing FreeDOS. Depending on what you chose to install and the speed of your system, the install usually takes a few minutes:

That's it! Reboot your system to begin using FreeDOS:

Want to see a video demo of the FreeDOS installation? We recorded a short video to walk you through installing FreeDOS 1.2 on GNOME Boxes (a free PC emulator for Linux) but the steps are the same for any PC emulator.

Saturday, May 12, 2018

Running VisiCalc on FreeDOS

I've demonstrated Borland's Quattro Pro spreadsheet and the shareware As-Easy-As spreadsheet, so I thought I should show the progenitor of DOS spreadsheets: VisiCalc.

You thought I was going to say "Lotus 1-2-3," didn't you? While Lotus 1-2-3 was an important spreadsheet program for DOS, and arguably the "killer app" for MS-DOS, it was not the first spreadsheet for personal computers. That honor belongs to VisiCalc.

You can download a free version of VisiCalc from the VisiCalc website, and access other free resources including a cheat sheet. From the website:

This web site,, includes lots of information about VisiCalc, the first computer spreadsheet program as we know them today. It has material directly from Dan Bricklin and Bob Frankston, the co-creators of VisiCalc, including scans of original photographs from VisiCalc's development days, a working copy of the program, and other things from Software Arts, Inc., Dan and Bob's company. Additional material is constantly being added, so researchers, computer historians, and teachers should check back periodically.

Dan Bricklin first developed VisiCalc for the Apple II home computer, and later ported to MS-DOS. As the first spreadsheet, it was no-frills. Basically, VisiCalc presented a grid with letters for columns and numbers for rows, and you could enter data in each cell.

VisiCalc lacked certain functions that we find common today. For example, VisiCalc did not have the @RAND function that I used in my As-Easy-As and Quattro Pro examples. So for this simple demonstration, I entered a list of numbers, and used the @SUM function to automatically calculate the list's total value.

Performing these calculations so effortlessly on sets of data immediately set VisiCalc as the "must-have" application for businesses. With a computer-based spreadsheet, workers could perform dependent calculations much more quickly than the same calculations by hand on a paper spreadsheet.

Note the use of ... to specify a range, such as A1...A10. This differed in later DOS spreadsheets, which used .. to indicate a range. Modern spreadsheets use :.

Like other DOS spreadsheets that followed it, VisiCalc used / to access the program's menu. The spreadsheet's commands were represented by single letters, such as B to blank the values from a cell, or M to move a row or column. While this may seem unfriendly at first, frequent users found they learned the keystrokes very quickly.

To exit the program, tap the / key, then S to bring up the storage menu:

…then select the Q (quit) action:

…and finally, confirm the action:

(screenshots are QEMU, resized to 533×400)

Thursday, May 10, 2018

Running Quattro Pro on FreeDOS

In the 1990s, my spreadsheet of choice was first the venerable Lotus 1-2-3 spreadsheet, then the shareware As-Easy-As spreadsheet. As an undergraduate physics student at university, I lived by my spreadsheet. I was always analyzing data from some lab.

I was first exposed to the Lotus 1-2-3 spreadsheet when I was still in high school, and my dad brought home a copy of the DOS spreadsheet from his office, so he could do work from home. My dad's office eventually migrated from Lotus 1-2-3 to Borland's Quattro Pro. And I sometimes experimented with that, too.

Quattro Pro was the first DOS program I encountered that used a WYSIWYG interface ("what you see is what you get"). Even though Quattro Pro was a DOS application, the program actually ran in graphics mode. This allowed the application to render numbers and text using fonts, lending a modern feel to the spreadsheet. Even today, the DOS version of Quattro Pro looks similar to today's spreadsheets with the sans-serif proportionally-spaced black-on-white text, and clickable row and column headers rendered as buttons.

The graphics mode also allowed Quattro Pro to fit in more text on the screen without it feeling crowded. In other DOS spreadsheets, you really only have room for about 20 spreadsheet rows on screen. That's because a DOS text console runs at 80×25 columns and lines (standard) and with a cell data line, column headers, horizontal scroll bar, status line, and help line, you've already taken five lines from the screen (leaving 20 for data). But Quattro Pro runs in graphical mode, so can display text at various sizes. Quattro Pro manages to squeeze in a menu bar, quick-reference action bar, cell data line, column headers, horizontal scroll bar, and status line—and still have room for 20 spreadsheet rows:

As an experiment, I entered some sample download data from our website into a sample spreadsheet. Like other spreadsheets at the time, Quattro Pro used the same data entry rules as Lotus 1-2-3, using .. to specify ranges of data (modern spreadsheets use :), + or @ to start calculations (today's spreadsheets use =), and other rules.

An advantage to running the spreadsheet in graphics mode all the time is generating a chart seems to run faster. The program doesn't need to flip the display into graphics mode; it just erases the display and draws a chart. Here's a sample chart based on the data I entered:

A common function needed by many professionals (and physics students) was the ability to fit a line to x,y data. To test this feature, I generated a simple line y=x+0. Because a straight line isn't very interesting, I added some randomness to the data using the @RAND function. This generates a random value between 0 and 1, so I centered the randomness using the cell function +x+@RAND-0.5.

As you can see, Quattro Pro fit a straight line of slope 1.03 ± 0.03, and y intercept -0.3 ± 0.3. That's the y=x+0 line that you'd expect:

And charting the data is just as easy. I added the straight line by defining a second y series that was the same as a the x series. You can adjust line types in Quattro Pro, like other spreadsheets, so I adjusted the data to be a red line with dots, and the line to be dotted green without points:

Sunday, May 6, 2018

Tutorial: Basic navigation on FreeDOS

New users often ask "I installed FreeDOS, but how do I use it?" If you haven't used DOS before, the blinking C:\> FreeDOS prompt can seem a little unfriendly. And maybe scary. So I wanted to write a gentle introduction to FreeDOS, to get you started. This article introduces just the basics: how to get around, and how to look at files.

The DOS prompt

First, let's look at the empty C:\> prompt and see what it means:

DOS is a "disk operating system" and was created during a time when personal computers ran from floppy disks. Even when computers supported hard drives, it was not uncommon in the 1980s and 1990s to frequently switch between the different drives. For example, you might make a backup copy of your most important files to a floppy disk.

FreeDOS references each drive by a letter. Early PC's could only have two floppy drives, which were assigned as the A: and B: drives. The first partition on the first hard drive was the C: drive. And so on for other drive letters. So the C: in the prompt means you are using the first partition on the first hard drive.

DOS also supports directories and subdirectories, delimited by \. Putting that together with the drive letter, the C:\ in the prompt means you are in the top directory, or "root" directory, of the C: drive.

And the > is the literal prompt where you type your DOS commands. The part before the > tells you the current working directory, and you type commands at the > prompt.

Finding your way around in DOS

The basics of navigating through directories in FreeDOS are pretty simple. You need to remember only a few commands:

Displaying a directory

When you want to see the contents of the current directory, use the DIR command. Since FreeDOS commands are case-insensitive, you could also type dir. By default, FreeDOS displays the details of every file and subdirectory, including the name, extension, size, and last modified date and time.

If you don't want the extra details about individual file sizes, you can display a "wide" directory by using the /w option with the DIR command. Note that FreeDOS uses the slash character (/) to start options.

You can look inside a specific subdirectory by passing the path name as a parameter to DIR. DOS names are case-insensitive. FreeDOS will usually display files and directories in all uppercase, but you can equally reference them in lowercase.

Changing the working directory

Once you can see the contents of a directory, you can "move into" any other directory. On FreeDOS, you change your working directory with the CHDIR command, also abbreviated as CD. You can change into a subdirectory with a command like CD CHOICE or into a new path with CD \FDOS\DOC\CHOICE.

FreeDOS uses . to represent the current directory, and .. for the parent directory (one level "up" from the current directory). You can combine these. For example, CD .. changes to the parent directory, and CD ..\.. moves you two levels "up" from the current directory.

FreeDOS also supports CD - to jump back to your previous working directory. That makes it handy when you changed into a new path to do one thing, and want to go back to your previous work.

Changing the working drive

Remember that FreeDOS assigns the first partition on the first hard drive as the C: drive, and so on for other drive letters. On modern systems, people rarely divide a hard drive with multiple DOS partitions, and simply use the whole disk—or as much of it as they can assign to DOS. So C: is usually the first hard drive, and D: is usually another hard drive or the CD-ROM drive. Other network drives can be mapped to other letters, such as E: or Z:, or however you want to organize them.

Changing between drives is easy enough under FreeDOS. Just type the drive letter followed by a colon (:) on the command line, and FreeDOS will change to that working drive. For example, I keep a D: drive where I store installers for various DOS applications and games that I want to test.

Be careful that you don't try to change to a drive that doesn't exist. FreeDOS may set the working drive, but if you try to do anything there, you'll get the somewhat infamous "Abort, Retry, Fail" DOS error message.

Other things to try

With the CD and DIR commands, you have the basics of FreeDOS navigation. These commands allow you to find your way around DOS directories, and see what other subdirectories and files exist. Once you are comfortable with basic navigation, you might also try these other basic FreeDOS commands:

  • MKDIR or MD to create new directories
  • RMDIR or RD to remove directories
  • TREE to view a list of directories and subdirectories in a tree-like format
  • TYPE and MORE to display file contents
  • RENAME or REN to rename files
  • DEL or ERASE to delete files
  • EDIT to edit files
  • CLS to clear the screen

In FreeDOS, you can use the /? parameter to get brief instructions to use each command. For example, EDIT /? will show you the usage and options for the editor. Or you can type HELP to use an interactive help system.

Like any DOS, FreeDOS is meant to be a simple operating system. The DOS file system is pretty simple to navigate with only a few basic commands. So I encourage you to install FreeDOS and experiment with the DOS command line. Maybe now it won't seem so scary.

Monday, April 30, 2018

Running WordStar on FreeDOS

You may have heard that Game of Thrones author George R.R. Martin uses WordStar 4.0 to write his books. I thought it would be interesting to go back and look at this classic word processor, WordStar 4.0, on FreeDOS.

Maybe you've heard of WordStar but haven't used it. And that wouldn't be a surprise; WordStar is a very old program. Originally written for CP/M 8-bit computer systems in the late 1970s, WordStar was later ported to MS-DOS systems in the early 1980s. WordStar was one of the first programs for DOS.

At the time, WordStar was noted for being a difficult program—although today you might find it quite simple. But that doesn't mean WordStar will be very easy for new users. If you haven't used WordStar before, be prepared for a learning curve.

WordStar opens with a menu where users can open a document, print a file, or do other file operations:

WordStar includes several sample documents that demonstrate various features of the word processor, or provide an opportunity to experiment with the system. I opened an existing document (TEXT.DOC, containing an excerpt from Gulliver's Travels) as a simple demo of WordStar. The upper third of the screen is devoted to a quick-reference menu of WordStar's functions. As you become more familiar with WorStar, you can turn off display of this menu, giving you more screen area to display your document.

Unfortunately, WordStar is not open source software, so we cannot include it in future FreeDOS distributions. But it's interesting to try out this original DOS application.

(screenshots are QEMU, resized to 533×400)

Tuesday, April 24, 2018

A gentle introduction to FreeDOS

One question I get a lot from new users is "I've installed FreeDOS, but how do I use it?" I assume these people haven't used DOS for a long time, or maybe they haven't used DOS before. For the latter group, they might assume FreeDOS uses a command line like Linux. And certainly the DOS command line has a lot in common with Unix and Linux systems, but some of the assumptions are different.

So I wrote an article for to provide a gentle introduction to FreeDOS. A version of that article will appear here on the FreeDOS blog in a few weeks.

This is meant as the first part in a short series of "how to use FreeDOS" articles that I plan to write. In this article, I talk about how to find your way around the DOS file system, using the CD and DIR commands. If you're new to FreeDOS, I recommend you read this article.

Monday, April 2, 2018

PC emulator screenshots look weird

If you remember the early PC era, or if you are a hobbyist who uses original PC hardware, maybe you wonder why PC emulator screenshots don't quite look like screens running on real hardware.

It's really noticeable in text-mode screenshots. For example, here's a screenshot of FreeDOS 1.2, taken in QEMU:

And my favorite DOS spreadsheet, As-Easy-As:

In text mode, QEMU emulates a standard PC character set, at 9 pixels wide by 16 pixels high. So it's easy math to understand why this 80×25 display is 720×400 pixels in size.

If you're running FreeDOS on modern hardware, such as a laptop, using an LCD screen (most common today) then this screenshot should look normal to you. The problem is that original PC hardware didn't use an exactly square pixel. So when you compare this 720×400 screenshot to original hardware, the screenshot looks weird.

The pixel hasn't always been a square dot. In modern flat panel displays, such as LCD, the pixel is a roughly square arrangement of red, green, and blue rectangles. Light all of them at once, and the human eye perceives them as a white square.

Original PC hardware didn't use LCD technology, but instead the cathode ray tube. The CRT used a hexagonal arrangement of red, green, and blue dots. Because these were not rectilinear, each "pixel" overlapped with the one next to it.

In the image below, I've modified Peter Halasz's image (cc by-sa) from Wikipedia, showing the arrangement of RGB on both CRT (top) and LCD (bottom). I've also outlined two adjacent pixels, one with a solid white line, and the next with a dotted white outline. You can see the LCD pixels adjoin, where the CRT pixels overlap slightly.

The result is that text on CRT displays looks a little different than text on LCD displays. Not a lot different, but a little different.

Computer displays on the early IBM PC models used a 4:3 aspect ratio, and the character generator outputted 80×25 text that neatly filled the screen. But in modern PC emulators, a pixel in text mode is represented as a single square dot. That means 80×25 text at 9×16 pixel dimensions fills a 720×400 screen, at an aspect ratio of 72:40, or about 5.4:3 aspect ratio. So the text appears too wide, compared to original PC hardware.

If I take the original QEMU screenshots, and resize them to have the same height but narrower image width, I can put the 80×25 display into a 4:3 aspect ratio. These screenshots have been forced to 533×400 pixels, which is 80×25 in 4:3 aspect ratio:

This looks more like how I remember using DOS in the 1980s and 1990s.

So if you've used FreeDOS on classic PC hardware, and wondered why the screen looks a little different than the screenshots we use on the FreeDOS website, that's why. Original hardware used a 4:3 display, but modern PC emulators use a one-for-one pixel display in text mode.

I'd be interested to know of any PC emulators that simulate a 4:3 display, and if they do that through video tricks (such as 3D effects) or by implementing a DOS font with a different height and width. If your favorite PC emulator can do this, let me know.

Tuesday, March 27, 2018

Running WordPerfect on FreeDOS

In the 1980s, my preferred word processor was WordPerfect. It was a great word processing system. WordPerfect was fast, powerful, and streamlined. I liked that WordPerfect "got out of the way" so it only displayed my text, plus a small status bar at the bottom of the screen.

I used WordPerfect throughout the 1980s, but moved on to a different DOS word processor soon after 1990.

I haven't run WordPerfect 5.1 for DOS in a long time. Sure enough, it installs and runs great on FreeDOS! I tested WordPerfect on FreeDOS 1.2, running in a QEMU virtual machine.

But WordPerfect could be very challenging to use. WordPerfect used the function keys to access the different features, like turning bold text on or off, or centering a block of text, or saving your work. Each function key F1 to F12 could be modified using Alt, Ctrl, or Shift, with a possible set of 12 × 4 = 48 different key combinations. But in practice, not all of the function combinations were used.

In my test, I wrote a simple document that demonstrated centered text, and simple formatting.

A powerful feature of WordPerfect was Reveal Codes, which allowed you to see how the word processor translated your document. Have you ever messed up a document in LibreOffice or Microsoft Word, adding some random formatting, and you wish you could go in and remove the one weird formatting code? With Reveal Codes, you could do that.

As an experiment, I loaded my test file into LibreOffice, and it imported correctly. Granted, this wasn't a very complex document, but it was interesting to see that LibreOffice could read WordPerfect files.

If you're interested in learning about the history of WordPerfect, you may also want to read Almost Perfect by Pete Peterson. You can buy it on Amazon, or download the free ebook version from the author's website.

Tuesday, March 13, 2018

How to run FreeDOS on Raspberry Pi, part 2

I expanded my other item about How to run FreeDOS on Raspberry Pi, and turned it into an article for OpenSource. Here's a recap from that:

As the founder and project coordinator of the FreeDOS Project, I'm often the go-to person when users ask questions. And one question I seem to get a lot lately is "Can you run FreeDOS on the Raspberry Pi?"

The short answer is "no" because like any DOS, FreeDOS needs an Intel CPU and PC BIOS. The Raspberry Pi doesn't have either of these. The Raspberry Pi is based on an ARM CPU, which is a completely different architecture.

But you can run FreeDOS on the Raspberry Pi if you use a PC emulator, like QEMU. FreeDOS runs fine in QEMU on Raspberry Pi, including games, but be aware that installing FreeDOS will take a long time. Actually, anything that requires a lot of disk I/O (like installing software) will be slow because the microSD storage on a Raspberry Pi isn't exactly fast.

Once you have installed FreeDOS in QEMU on the Raspberry Pi, you shouldn't notice any performance issues. For example, games usually load maps, sprites, sounds, and other data when you start each level. While starting a new level in a game might take a while, I didn't notice any performance lag while playing DOS games in FreeDOS on the Raspberry Pi.