home *** CD-ROM | disk | FTP | other *** search
/ ftp.pasteur.org/FAQ/ / ftp-pasteur-org-FAQ.zip / FAQ / msdos-programmer-faq / part3 < prev    next >
Encoding:
Internet Message Format  |  2004-05-09  |  36.8 KB

  1. Path: senator-bedfellow.mit.edu!dreaderd!not-for-mail
  2. Message-ID: <msdos-programmer-faq/part3_1084010824@rtfm.mit.edu>
  3. Supersedes: <msdos-programmer-faq/part3_1081511793@rtfm.mit.edu>
  4. Expires: 11 Jun 2004 10:07:04 GMT
  5. References: <msdos-programmer-faq/part1_1084010824@rtfm.mit.edu>
  6. X-Last-Updated: 2003/08/14
  7. From: jeffrey@carlyle.org (Jeffrey Carlyle)
  8. Sender: jeffrey@carlyle.org (Jeffrey Carlyle)
  9. Reply-To: jeffrey@carlyle.org (Jeffrey Carlyle)
  10. Approved: news-answers-request@MIT.edu
  11. Organization: JeffC.org
  12. Subject: comp.os.msdos.programmer FAQ part 3/5
  13. Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,comp.answers,alt.answers,news.answers
  14. Followup-To: poster
  15. Summary: Frequently asked questions from DOS programmers with tested answers.
  16. Originator: faqserv@penguin-lust.MIT.EDU
  17. Date: 08 May 2004 10:08:03 GMT
  18. Lines: 942
  19. NNTP-Posting-Host: penguin-lust.mit.edu
  20. X-Trace: 1084010883 senator-bedfellow.mit.edu 574 18.181.0.29
  21. Xref: senator-bedfellow.mit.edu comp.os.msdos.programmer:127444 alt.msdos.programmer:54822 comp.answers:57100 alt.answers:72787 news.answers:270991
  22.  
  23. Archive-name: msdos-programmer-faq/part3
  24. Comp-os-msdos-programmer-archive-name: dos-faq-pt3.txt
  25. Posting-frequency: 28 days
  26. Last-modified: 14 Aug 2003
  27.  
  28. comp.os.msdos.programmer FAQ Version 2003.08.14
  29.  
  30. This is the Frequently Asked Questions list for the newsgroup
  31. comp.os.msdos.programmer.
  32.  
  33. COPYRIGHT
  34.  
  35. Copyright 2003 by Jeffrey Carlyle. All rights reserved. This article is
  36. not in the public domain, but it may be redistributed so long as this
  37. notice, the acknowledgments, and the information on obtaining the latest
  38. copy of this list are retained and no fee is charged. The code fragments
  39. may be used freely; credit to the FAQ would be polite. This FAQ is not to
  40. be included in any static: archive (e.g. CD-ROM or book); however, a
  41. pointer to the FAQ may be included. See <Q:01.14> [Where can I get the
  42. latest copy of this FAQ list?] for a link to the latest version of the
  43. FAQ.)
  44.  
  45. This is part 3 of 5 parts.
  46.  
  47. TABLE OF CONTENTS
  48.  
  49. PART 1: 
  50. Section 1.  General FAQ and Newsgroup Information
  51.   <Q:01.01> - Is MS-DOS Dead?
  52.   <Q:01.02> - What is this article for?
  53.   <Q:01.03> - Who has contributed to this article?
  54.   <Q:01.04> - How can I search this article for a particular topic?
  55.   <Q:01.05> - Are the answers guaranteed to be correct and complete?
  56.   <Q:01.06> - What is comp.os.msdos.programmer about?
  57.   <Q:01.07> - Is comp.os.msdos.programmer just for C programmers?
  58.   <Q:01.08> - What is comp.sys.ibm.pc.programmer?
  59.   <Q:01.09> - Is comp.os.msdos.programmer available as a mailing list?
  60.   <Q:01.10> - What's this netiquette?
  61.   <Q:01.11> - How can I learn more about Usenet?
  62.   <Q:01.12> - What other technical newsgroups should I know about?
  63.   <Q:01.13> - Where are FAQ lists archived?
  64.   <Q:01.14> - Where can I get the latest copy of this FAQ list?
  65.  
  66. Section 2.  General Reference
  67.   <Q:02.01> - Are there any good on-line references for PC hardware
  68.               components?
  69.   <Q:02.02> - Are there any good on-line references for PC interrupts?
  70.   <Q:02.03> - What and where is Ralf Brown's interrupt list?
  71.   <Q:02.04> - Where can I find lex, yacc, and language grammars?
  72.   <Q:02.05> - What's the best book to learn programming?
  73.   <Q:02.06> - Why won't my code work?
  74.   <Q:02.07> - Are there any good sources of example code?
  75.   <Q:02.08> - What and where is SNIPPETS?
  76.   <Q:02.09> - Is the source code MS-DOS available?
  77.   <Q:02.10> - What are my alternatives for MS-DOS compatible OSes?
  78.   <Q:02.11> - What and where is FreeDOS?
  79.   <Q:02.12> - Where can I find out about batch files?
  80.  
  81. PART 2: 
  82. Section 3.  Compile and link
  83.   <Q:03.01> - What the heck is DGROUP > 64K?
  84.   <Q:03.02> - How do I fix 'automatic data segment exceeds 64K' or 'stack
  85.               plus data exceed 64K'?
  86.   <Q:03.03> - Will Borland C code and Microsoft C code link together?
  87.   <Q:03.04> - Why did my program bomb at run time with 'floating point
  88.               formats not linked' or 'floating point not loaded'?
  89.   <Q:03.05> - How can I change the stack size in Borland's C compilers?
  90.   <Q:03.06> - What's the format of an .OBJ file?
  91.   <Q:03.07> - What's the format of an .EXE header?
  92.   <Q:03.08> - What's the difference between .COM and .EXE formats?
  93.   <Q:03.09> - How do I create a .COM file?
  94.   <Q:03.10> - Where is EXE2BIN located?
  95.   <Q:03.11> - What does this message mean: 'A20 already enabled so test
  96.               is meaning less?'
  97.  
  98. Section 4.  Keyboard
  99.   <Q:04.01> - How can I read a character without echoing it to the
  100.               screen, and without waiting for the user to press the Enter
  101.               key?
  102.   <Q:04.02> - How can I find out whether a character has been typed,
  103.               without waiting for one?
  104.   <Q:04.03> - How can I disable Ctrl-C/Ctrl-Break and/or Ctrl-Alt-Del?
  105.   <Q:04.04> - How can I disable the print screen function?
  106.   <Q:04.05> - How can my program turn NumLock (CapsLock, ScrollLock) on
  107.               or off?
  108.   <Q:04.06> - How can I speed up the keyboard's auto-repeat?
  109.   <Q:04.07> - What is the SysRq key for?
  110.   <Q:04.08> - How can my program tell what kind of keyboard is on the
  111.               system?
  112.   <Q:04.09> - How can I tell if input, output, or stderr has been
  113.               redirected?
  114.   <Q:04.10> - How can I increase the size of the keyboard buffer?
  115.   <Q:04.11> - How can I stuff characters into the keyboard buffer?
  116.  
  117. PART 3: (this part)
  118. Section 5.  Disks and files
  119.   <Q:05.01> - What drive was the PC booted from?
  120.   <Q:05.02> - How can I boot from drive B:?
  121.   <Q:05.03> - Which real and virtual disk drives are valid?
  122.   <Q:05.04> - How can I make my single floppy drive both a: and b:?
  123.   <Q:05.05> - How can I disable access to a drive?
  124.   <Q:05.06> - How can a batch file test existence of a directory?
  125.   <Q:05.07> - Why won't my C program open a file with a path?
  126.   <Q:05.08> - How can I redirect printer output to a file?
  127.   <Q:05.09> - How can I redirect the output of a batch file?
  128.   <Q:05.10> - How can I redirect stderr?
  129.   <Q:05.11> - How can my program open more files than DOS's limit of 20?
  130.   <Q:05.12> - How can I read, create, change, or delete the volume label?
  131.   <Q:05.13> - How can I get the disk serial number?
  132.   <Q:05.14> - What's the format of .OBJ, .EXE., .COM files?
  133.   <Q:05.15> - How can I flush the software disk cache?
  134.   <Q:05.16> - How can I see if a drive is a RAM drive?
  135.   <Q:05.17> - How can I determine a hard drive's manufacturer?
  136.   <Q:05.18> - Where can I find information about the ATA/ATAPI
  137.               specification?
  138.   <Q:05.19> - How can I copy files to or from filenames containing date
  139.               information?
  140.  
  141. Section 6.  Serial ports (COM ports)
  142.   <Q:06.01> - How do I set my machine up to use COM3 and COM4?
  143.   <Q:06.02> - How do I find the I/O address of a COM port?
  144.   <Q:06.03> - But aren't the COM ports always at I/O addresses 3F8, 2F8,
  145.               3E8, and 2E8?
  146.   <Q:06.04> - How do I configure a COM port and use it to transmit data?
  147.  
  148. PART 4: 
  149. Section 7.  Other hardware questions and problems
  150.   <Q:07.01> - Which 80x86 CPU is running my program?
  151.   <Q:07.02> - How can a C program send control codes to my printer?
  152.   <Q:07.03> - How can I redirect printer output?
  153.   <Q:07.04> - Which video adapter is installed?
  154.   <Q:07.05> - How do I switch to 43- or 50-line mode?
  155.   <Q:07.06> - How can I find the Microsoft mouse position and button
  156.               status?
  157.   <Q:07.07> - How can I access a specific address in the PC's memory?
  158.   <Q:07.08> - How can I read or write my PC's CMOS memory?
  159.   <Q:07.09> - How can I access memory beyond 640K?
  160.   <Q:07.10> - How can I use the protected mode?
  161.   <Q:07.11> - How can I tell if my program is running on a PS/2-style
  162.               machine.
  163.   <Q:07.12> - Is there a 80x87 math unit installed?
  164.   <Q:07.13> - How can I power off the computer from a batch file?
  165.  
  166. Section 8.  Other software questions and problems
  167.   <Q:08.01> - How can a program reboot my PC?
  168.   <Q:08.02> - How can I time events with finer resolution than the system
  169.               clock's 55 ms (about 18 ticks a second)?
  170.   <Q:08.03> - How can I find the error level of the previous program?
  171.   <Q:08.04> - How can a program set DOS environment variables?
  172.   <Q:08.05> - How can I change the switch character to - from /?
  173.   <Q:08.06> - How can I write a TSR (terminate-stay-resident utility)?
  174.   <Q:08.07> - Why does my interrupt function behave strangely?
  175.   <Q:08.08> - How can I write a device driver?
  176.   <Q:08.09> - What can I use to manage versions of software?
  177.   <Q:08.10> - What's this 'null pointer assignment' after my C program
  178.               executes?
  179.   <Q:08.11> - How can a batch file tell whether it's being run in a DOS
  180.               box under Windows?
  181.   <Q:08.12> - How can my program tell if it's running under Windows?
  182.   <Q:08.13> - How can a program tell whether ANSI.SYS is installed?
  183.   <Q:08.14> - How do I copyright software that I write?
  184.   <Q:08.15> - How can I place date and time information into environment
  185.               variables?
  186.  
  187. PART 5: 
  188. Section 9.  Downloading
  189.   <Q:09.01> - What are SimTel and Garbo?
  190.   <Q:09.02> - Can I get archives on CD-ROM?
  191.   <Q:09.03> - Where do I find program <mumble>?
  192.  
  193. Section 10.  Vendors and products
  194.   <Q:10.01> - How can I contact Borland?
  195.   <Q:10.02> - How can I contact Microsoft?
  196.   <Q:10.03> - What is the current version of DJGPP?
  197.   <Q:10.04> - What and where is DJGPP?
  198.   <Q:10.05> - Are there any good shareware/freeware compilers?
  199.   <Q:10.06> - Where is QBASIC?
  200.   <Q:10.07> - What is a vendor's web site address?
  201.  
  202. ------------------------------
  203.  
  204. Subject: Section 5. Disks and files
  205. Date: 5 Feb 2002 22:03:03 -0400
  206.  
  207.  Information about accessing disks and files from MS-DOS.
  208.  
  209. ------------------------------
  210.  
  211. Subject: <Q:05.01> - What drive was the PC booted from?
  212. Date: 5 Feb 2002 22:03:03 -0400
  213.  
  214.  Under DOS 4.0 or later, use INT 21 AX=3305. DL is returned with an
  215.  integer indicating the boot drive (1=A:, etc.).
  216.  
  217. ------------------------------
  218.  
  219. Subject: <Q:05.02> - How can I boot from drive B:?
  220. Date: 8 Feb 2002 19:52:06 -0400
  221.  
  222.  Downloadable shareware: <http://www.simtel.net/pub/pd/44102.html>
  223.  <ftp://garbo.uwasa.fi/pc/bootutil/boot_b.zip>
  224.  
  225.  The included documentation says it works by writing a new boot sector on
  226.  a disk in your a: drive that redirects the boot to your B: drive. (A
  227.  similar utility is bboot.zip in the same directory at Garbo only.)
  228.  
  229.  If that doesn't work, you can always interchange your A: and B: drives
  230.  by switching ribbon cables and changing the setup in your BIOS. From an
  231.  article posted 27 Jan 1993 on another newsgroup:
  232.  
  233.  [begin quotation]
  234.    Take  the  "ribbon" connector, as you call it, and  switch
  235.    them.  To double-check, start at the end of the cable that
  236.    connects to the motherboard or floppy controller.   Follow
  237.    the  cable until you get to the first connector.   Connect
  238.    this to the drive you want to be B:.
  239.   
  240.    After this, there should be a few lines on the cable  that
  241.    get flipped left to right.  (On most cables, they just cut
  242.    the lines and physically reverse them.  It should be quite
  243.    obvious from looking at the cable.)  Anyway, the connector
  244.    after  the pins get flipped right to left is the connector
  245.    for your a: drive.
  246.  [end quotation]
  247.  
  248. ------------------------------
  249.  
  250. Subject: <Q:05.03> - Which real and virtual disk drives are valid?
  251. Date: 5 Feb 2002 22:03:03 -0400
  252.  
  253.  Use INT 21 AH=29 (parse filename). Point DS:SI at a null- terminated
  254.  ASCII string that contains the drive letter and a colon, point ES:DI at
  255.  a 37-byte dummy FCB buffer, and call INT 21 AX=2900. On return, AL is FF
  256.  if the drive is invalid, something else if the drive is valid. RAM disks
  257.  and SUBSTed drives are considered valid.
  258.  
  259.  You can detect whether the drive is ASSIGNed by using INT 2F AX=0601. To
  260.  check whether the drive is SUBSTed, use INT 21 AX=4409; or use INT 21
  261.  AH=52 to test for both JOIN and SUBST. See Ralf Brown's interrupt list:
  262.  <Q:02.03> [What and where is Ralf Brown's interrupt list?].
  263.  
  264.  Unfortunately, the b: drive is considered valid even on a
  265.  single-diskette system. You can check that special case by interrogating
  266.  the BIOS equipment byte at 0040:0010. Bits 7- 6 contain the one less
  267.  than the number of diskette drives, so if those bits are zero you know
  268.  that b: is an invalid drive even though function 29 says it's valid.
  269.  
  270.  Following is some code originally posted by Doug Dougherty to test valid
  271.  drives (treating SUBSTed and JOINed drives as valid), with my fix for
  272.  the b: special case, tested in Borland C++ 4.5 (in the large model):
  273.  
  274.    #include <dos.h>
  275.    #include <stdio.h>
  276.    
  277.    void drvlist(void)
  278.    {
  279.      char s[3] = "A:", fcb_buff[37];
  280.      int valid;
  281.  
  282.      for( ;  *s<='Z';  (*s)++)
  283.      {
  284.        _SI = (unsigned) s;
  285.        _DI = (unsigned) fcb_buff;
  286.        _ES = _DS;
  287.        _AX = 0x2900;
  288.  
  289.        geninterrupt(0x21);
  290.        valid = _AL != 0xFF;
  291.  
  292.        if (*s == 'B'  &&  valid)
  293.        {
  294.          char far *equipbyte = (char far *)0x00400010UL;
  295.          valid = (*equipbyte & (3 << 6)) != 0;
  296.        }
  297.  
  298.        printf("Drive '%s' is %sa valid drive.\n", s, valid ? "" : "not ");
  299.      }
  300.    }
  301.  
  302.  This code was translated to MSC 7.0 and tested it in small model:
  303.  
  304.    #include <dos.h>
  305.    #include <stdio.h>
  306.  
  307.    void drvlist(void)
  308.    {
  309.      char s[3] = "A:", fcb_buff[37], *buff=fcb_buff;
  310.      int valid;
  311.  
  312.      for (   ;  *s<='Z';  (*s)++)
  313.      {
  314.        __asm mov si,s      __asm mov di,buff
  315.        __asm mov ax,ds     __asm mov es,ax
  316.        __asm mov ax,0x2900 __asm int 21h
  317.        __asm xor ah,ah     __asm mov valid,ax
  318.  
  319.        valid = (valid != 0xFF);
  320.  
  321.        if (*s == 'B'  &&  valid)
  322.        {
  323.          char far *equipbyte = (char far *)0x00400010UL;
  324.          valid = (*equipbyte & (3 << 6)) != 0;
  325.        }
  326.  
  327.        printf("Drive '%s' is %sa valid drive.\n", s, valid ? "" : "not");
  328.      }
  329.    }
  330.  
  331. ------------------------------
  332.  
  333. Subject: <Q:05.04> - How can I make my single floppy drive both a: and
  334.         b:?
  335. Date: 5 Feb 2002 22:03:03 -0400
  336.  
  337.  Under any DOS since DOS 2.0, you can put the following command into your
  338.  AUTOEXEC.BAT file:
  339.  
  340.  assign b=a
  341.  
  342.  Then, when you type "dir b:" you'll no longer get the annoying prompt to
  343.  insert diskette B (and the even more annoying prompt to insert A the
  344.  next time you type "dir a:").
  345.  
  346.  You may be wondering why anybody would want to do this. Suppose you use
  347.  two different machines, maybe one at home and one at work. One of them
  348.  has only a 3.5" diskette drive; the other machine has two drives, and b:
  349.  is the 3.5" one. You're bound to type "dir b:" on the first one, and get
  350.  the nuisance message:
  351.  
  352.  Insert diskette for drive B: and press any key when ready.
  353.  
  354.  But if you assign drive b: to point to a:, you avoid this problem.
  355.  
  356.  Caution: there are a few commands, such as DISKCOPY, that will not work
  357.  right on ASSIGNed or SUBSTed drives. See the DOS manual for the full
  358.  list. Before typing one of those commands, be sure to turn off the
  359.  mapping by typing "assign" without arguments.
  360.  
  361.  The DOS 5.0 manual says that ASSIGN is obsolete, and recommends the
  362.  equivalent form of SUBST: "subst b: a:\". Unfortunately, if this command
  363.  is executed when a: doesn't hold a diskette, the command fails. ASSIGN
  364.  doesn't have this problem, so under DOS 5.0 you should disregard that
  365.  particular bit of advice in the manual.
  366.  
  367. ------------------------------
  368.  
  369. Subject: <Q:05.05> - How can I disable access to a drive?
  370. Date: 8 Feb 2002 19:53:23 -0400
  371.  
  372.  Reader Eric DeVolder writes that he has made available a program to do
  373.  this. I haven't tried it, but it's downloadable from
  374.  <http://www.simtel.net/pub/pd/44403.html>
  375.  
  376.  Reader Igor Karp reports that MS-DOS version 5.0 and greater provides
  377.  two interrupts to do this.
  378.  
  379.    --------D-215F07-----------------------------
  380.    INT 21 - DOS 5+ - ENABLE DRIVE
  381.       AX = 5F07h
  382.       DL = drive number (0=A:)
  383.    Return: CF clear if successful
  384.       CF set on error
  385.       AX = error code (0Fh) (see #0885 at AH=59h)
  386.    Notes:   simply  sets the "valid" bit in the  drive's  CDS
  387.    this function is not supported by Novell DOS 7
  388.    See Also: AH=52h,AX=5F08h"DOS"
  389.  
  390.    --------D-215F08-----------------------------
  391.    INT 21 - DOS 5+ - DISABLE DRIVE
  392.       AX = 5F08h
  393.       DL = drive number (0=A:)
  394.    Return: CF clear if successful
  395.       CF set on error
  396.       AX = error code (0Fh) (see #0885 at AH=59h)
  397.    Notes:   simply clears the "valid" bit in the drive's  CDS
  398.    this function is not supported by Novell DOS 7
  399.  
  400. ------------------------------
  401.  
  402. Subject: <Q:05.06> - How can a batch file test existence of a directory?
  403. Date: 8 Feb 2002 19:54:04 -0400
  404.  
  405.  The standard way, which in fact is documented in the DOS manual, is:
  406.  
  407.  if exist d:\path\nul goto found
  408.  
  409.  Unfortunately, this is not entirely reliable. I found it failed in
  410.  Pathworks (a/k/a PCSA, DEC's network that connects PCs and VAXes), or on
  411.  a MARS box that uses an OEM version of MS-DOS 5.0. Readers have reported
  412.  that it gave the wrong answer on Novell networks, on DR-DOS, and in a
  413.  DOS window under OS/2. By "failed" I mean that it "found" a directory
  414.  that didn't exist, or failed to find one that did exist, or both. (It
  415.  has been reported that IBM fixed the OS/2 bug in version 2.11 of OS/2.)
  416.  As a legacy from earlier versions of DOS it always succeeds if the path
  417.  is DEV.
  418.  
  419.  There appears to be no foolproof way to use pure batch commands to test
  420.  for existence of a directory. The real solution is to write a program,
  421.  which returns a value that your batch program can then test with an "if
  422.  errorlevel". Reader Duncan Murdoch kindly posted the following Turbo
  423.  Pascal version:
  424.  
  425.    program existdir;
  426.    { Confirms  the  existence of a directory  given  on  the
  427.      command  line.  Returns errorlevel 2 on error,  1  if  not
  428.      found, 0 if found. }
  429.   
  430.    uses dos;
  431.   
  432.    var
  433.      s : searchrec;
  434.   
  435.    begin
  436.      if paramcount <> 1 then
  437.        begin
  438.          writeln('Syntax:  EXISTDIR directory');
  439.          halt(2);
  440.        end
  441.      else
  442.        begin
  443.          findfirst(paramstr(1),Directory,S);
  444.          while (Doserror = 0) and ((Directory and S.Attr) =  0) do
  445.            findnext(S);
  446.   
  447.         if Doserror <> 0 then
  448.           begin
  449.             Writeln('Directory not found.');
  450.             halt(1);
  451.           end
  452.         else
  453.           begin
  454.             Writeln('Directory found.');
  455.             halt(0);
  456.           end;
  457.        end;
  458.    end.
  459.  
  460.  Timo Salmi also has a Turbo Pascal version in his Turbo Pascal FAQ,
  461.  which is downloadable as <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>
  462.  
  463. ------------------------------
  464.  
  465. Subject: <Q:05.07> - Why won't my C program open a file with a path?
  466. Date: 5 Feb 2002 22:03:03 -0400
  467.  
  468.  You've probably got something like the following code:
  469.  
  470.    char *filename = "c:\foo\bar\mumble.dat";
  471.    FILE *fptr;
  472.    /*.*/
  473.    fptr = fopen(filename, "r");
  474.  
  475.  The problem is that \f is a form feed, \b is a backspace, and \m is m.
  476.  Whenever you want a backslash in a string constant in C, you must use
  477.  two backslashes:
  478.  
  479.  char *filename = "c:\\foo\\bar\\mumble.dat";
  480.  
  481.  This is a feature of every C compiler, because Dennis Ritchie designed C
  482.  this way. It's a problem only on MS-DOS systems, because only DOS (and
  483.  Atari ST/TT running TOS) uses the backslash in directory paths. But even
  484.  in DOS this backslash convention applies _only_ to string constants in
  485.  your source code. For file and keyboard input at run time, \ is just a
  486.  normal character, so users running your program would type in file specs
  487.  the same way as in DOS commands, with single \ characters.
  488.  
  489.  Another possibility is to code all paths in source programs with /
  490.  rather than \ characters:
  491.  
  492.  char *filename = "c:/foo/bar/mumble.dat";
  493.  
  494.  Ralf Brown writes, "All versions of the DOS kernel accept either forward
  495.  or backslashes as directory separators. I tend to use this form more
  496.  frequently than backslashes since it is easier to type and read." This
  497.  applies to DOS function calls (and therefore to calls to the file
  498.  library of every programming language), but not to DOS commands.
  499.  
  500. ------------------------------
  501.  
  502. Subject: <Q:05.08> - How can I redirect printer output to a file?
  503. Date: 8 Feb 2002 19:55:31 -0400
  504.  
  505.  Recommended: PRN2FILE from PC Magazine, downloadable as:
  506.  <http://www.simtel.net/pub/pd/49066.html>
  507.  
  508.  PRN2FILE contains ASM source code. PC Magazine has given copies away as
  509.  part of its utilities disks, so you may already have a copy.
  510.  
  511.  The directories mentioned above have lots of other utilities to redirect
  512.  printer output.
  513.  
  514. ------------------------------
  515.  
  516. Subject: <Q:05.09> - How can I redirect the output of a batch file?
  517. Date: 7 Feb 2002 14:48:46 -0400
  518.  
  519.  Assuming the batch file is called batch.bat, to send its output (stdout)
  520.  to another file, just invoke COMMAND.COM as a secondary command
  521.  processor:
  522.  
  523.  command /c batch parameters_if_any >outfile
  524.  
  525.  Timo Salmi's notes on this and other batch tricks are downloadable from:
  526.  <ftp://garbo.uwasa.fi/pc/link/tsbat.zip>
  527.  
  528.  A reader of comp.os.msdos.programmer has created a utility that can
  529.  capture batch file output. It can be found at:
  530.  <http://www.simtel.net/pub/dl/11141.shtml>
  531.  
  532. ------------------------------
  533.  
  534. Subject: <Q:05.10> - How can I redirect stderr?
  535. Date: 8 Feb 2002 19:58:21 -0400
  536.  
  537.  Use freopen(..., stderr) and then execute the desired command via
  538.  system(). There are downloadable versions of programs to do this.
  539.  
  540.  This file includes TP4 source and an executable:
  541.  <http://www.simtel.net/pub/pd/50430.html>
  542.  
  543.  A C example is downloadable as:
  544.  <http://www.simtel.net/pub/pd/41772.html>
  545.  
  546.  I compiled it with MSC 7.0, and it works fine with one exception:
  547.  Contrary to the included comments, redirected output starts writing at
  548.  the beginning of the output file rather than appending. That is easily
  549.  solved by adding "fseek(stderr, 0L, SEEK_END);" after the freopen() call
  550.  for stderr.
  551.  
  552.  A reader comp.os.msdos.programer has created a utilitiy that can capture
  553.  console output. It can be found at:
  554.  <http://www.simtel.net/pub/dl/11141.shtml>
  555.  
  556. ------------------------------
  557.  
  558. Subject: <Q:05.11> - How can my program open more files than DOS's limit
  559.         of 20?
  560. Date: 5 Feb 2002 22:03:03 -0400
  561.  
  562.  This is a summary of an article Ralf Brown posted on 8 August 1992, with
  563.  some additions from a Microsoft tech note and information from Chin
  564.  Huang.)
  565.  
  566.  DOS imposes some limits. Once you overcome those, which is pretty easy,
  567.  you may have to take additional measures to overcome the limitations
  568.  built into your compiler's run- time library.
  569.  
  570.  1) Limitations imposed by DOS:
  571.  
  572.  There are separate limits on files and file handles. For example, DOS
  573.  opens three files but five file handles: CON (stdin, stdout, and
  574.  stderr), AUX (stdaux), and PRN (stdprn).
  575.  
  576.  The limit in FILES= in CONFIG.SYS is a system-wide limit on files opened
  577.  by all programs (including the three that DOS opens and any opened by
  578.  TSRs); each process has a limit of 20 handles (including the five that
  579.  DOS opens). Example: CONFIG.SYS has FILES=40. Then program #1 will be
  580.  able to open 15 file handles. Assuming that the program actually does
  581.  open 15 handles pointing to 15 different files, other programs could
  582.  still open a total of 22 files (40-3-15 = 22), though no one program
  583.  could open more than 15 file handles. If you're running DOS 3.3 or
  584.  later, you can increase the per-process limit of 20 file handles by a
  585.  call to INT 21 AH=67, Set Handle Count. Your program is still limited by
  586.  the system-wide limit on open files, so you may also need to increase
  587.  the FILES= value in your CONFIG.SYS file (and reboot). The run-time
  588.  library that you're using may have a fixed-size table of file handles,
  589.  so you may also need to get source code for the module that contains the
  590.  table, increase the table size, and recompile it.
  591.  
  592.  2) Limitations in Microsoft C run-time library:
  593.  
  594.  In Microsoft C the run-time library limits you to 20 file handles. To
  595.  change this, you must be aware of two limits:
  596.  
  597.  File handles used with _open(), _read(), etc.: Edit _NFILE_ in
  598.  CRT0DAT.ASM.
  599.  
  600.  Stream files used with fopen(), fread(), etc.: Edit _NFILE_ in _FILE.C
  601.  for DOS or FILE.ASM for Windows/QuickWin. This must not exceed the value
  602.  of _NFILE_ in CRT0DAT.ASM. (QuickWin uses the constant _WFILE_ in
  603.  CRT0DAT.ASM and WFILE.ASM for the maximum number of child text windows.)
  604.  
  605.  After changing the limits, recompile using CSTARTUP.BAT. Microsoft
  606.  recommends that you first read README.TXT in the same directory.
  607.  
  608.  3) Limitations in Borland C++ run-time library:
  609.  
  610.  (Reader Chin Huang provided this information on 12 Sep 1993.) To
  611.  increase the open file limit for a program you compile with Borland C++
  612.  3.1, edit the file _NFILE.H in the include directory and change the
  613.  _NFILE_ value. Compile and link the modules FILES.C and FILES2.C from
  614.  the lib directory into your program.
  615.  
  616. ------------------------------
  617.  
  618. Subject: <Q:05.12> - How can I read, create, change, or delete the volume
  619.         label?
  620. Date: 5 Feb 2002 22:03:03 -0400
  621.  
  622.  In DOS 5.0 (and possibly in 4.0 as well), there are actually two volume
  623.  labels: the LABEL command reports only the first but changes both of
  624.  them.
  625.  
  626.  * The traditional volume label is an entry with "volume label" attribute
  627.    in the root directory of the disk. The DIR, VOL, and LABEL commands
  628.    report this volume label, and LABEL sets it.
  629.  
  630.  * There is a second volume label, which may be different, in the boot
  631.    record along with the serial number. In DOS 4.0 and later, INT 21
  632.    AH=69 gets or sets the boot record's serial number and volume label
  633.    together; see <Q:05.13> [How can I get the disk serial number?] DIR
  634.    and VOL ignore this volume label; the LABEL command doesn't report it
  635.    but does set it.
  636.  
  637.  The rest of this answer assumes that by "volume label" you mean the
  638.  traditional one, the one that DIR and VOL display. Though it's a
  639.  directory entry in the root directory, you can't change it using the
  640.  newer DOS file-access functions (INT 21 AH=3C, 41, 43); instead, use the
  641.  old FCB-oriented directory functions. Specifically, you need to allocate
  642.  a 64-byte buffer and a 41- byte extended FCB (file control block). Call
  643.  INT 21 AH=1A to find out whether there is a volume label. If there is,
  644.  AL returns 0 and you can change the label using DOS function 17 or
  645.  delete it using DOS function 13. If there's no volume label, function 1A
  646.  will return FF and you can create a label via function 16. Important
  647.  points to notice are that ? wildcards are allowed but * are not; the
  648.  volume label must be space filled not null terminated.
  649.  
  650.  The following MSC 7.0 code worked for me in DOS 5.0; the functions it
  651.  uses have been around since DOS 2.0. The function parameter is 0 for the
  652.  current disk, 1 for a:, 2 for b:, etc. It doesn't matter what your
  653.  current directory is; these functions always search the root directory
  654.  for volume labels. (I didn't try to change the volume label of any
  655.  networked drives.)
  656.  
  657.    // Requires DOS.H, STDIO.H, STRING.H
  658.  
  659.    void vollabel(unsigned char drivenum)
  660.    {
  661.      static  unsigned  char  extfcb[41],  dta[64],  status,  *newlabel;
  662.      int chars_got = 0;
  663.  
  664.      #define DOS(buff,func) __asm { __asm mov dx,offset buff  \
  665.        __asm mov ax,seg buff  __asm push ds  __asm mov ds,ax  \
  666.        __asm  mov  ah,func   __asm int  21h   __asm  pop  ds  \
  667.        __asm mov status,al }
  668.  
  669.      #define getlabel(buff,prompt) newlabel = buff;  \
  670.        memset(newlabel,' ',11);  printf(prompt);   \
  671.        scanf("%11[^\n]%n", newlabel, &chars_got);  \
  672.        if (chars_got < 11) newlabel[chars_got] = ' ';
  673.  
  674.      // Set up the 64-byte transfer area used by function 1A.
  675.      DOS(dta, 1Ah)
  676.   
  677.      //  Set  up  an extended FCB and search for the  volume label.
  678.      memset(extfcb, 0, sizeof extfcb);
  679.      extfcb[0] = 0xFF;           // denotes extended FCB
  680.      extfcb[6] = 8;              // volume-label attribute  bit
  681.      extfcb[7] = drivenum;       // 1=A,2=B,...; 0=current drive
  682.   
  683.      memset(&extfcb[8], '?', 11);// wildcard *.*
  684.      DOS(extfcb,11h)
  685.      if(status == 0)
  686.      {                           // DTA has volume  label's FCB
  687.        printf("volume label is %11.11s\n", &dta[8]);
  688.        getlabel(&dta[0x18], "new label (\"delete\" to delete): ");
  689.       
  690.        if(chars_got==0)
  691.          printf("label not changed\n");
  692.        else if (strncmp(newlabel,"delete  ",11) == 0)
  693.        {
  694.          DOS(dta,13h)
  695.          printf(status ? "label failed\n":"label deleted\n");
  696.        }
  697.        else
  698.        {                  // user wants to change label
  699.          DOS(dta,17h)
  700.          printf(status ? "label failed\n" : "label changed\n");
  701.        }
  702.      }
  703.      else
  704.      {                      // no volume label was found
  705.        printf("disk has no volume label.\n");
  706.        getlabel(&extfcb[8], "new label (<Enter>  for  none): ");
  707.  
  708.        if (chars_got > 0)
  709.        {
  710.          DOS(extfcb,16h)
  711.          printf(status ? "label failed\n" : "label created\n");
  712.        }
  713.      }
  714.    } // end function vollabel
  715.  
  716. ------------------------------
  717.  
  718. Subject: <Q:05.13> - How can I get the disk serial number?
  719. Date: 5 Feb 2002 22:03:03 -0400
  720.  
  721.  If the disk was formatted by DOS 4.0 or later, use INT 21: AX=6900 gets
  722.  the serial number; AX=6901 sets it. (The disk serial number doesn't
  723.  exist if the disk was formatted with an earlier version of DOS, or with
  724.  some third-party formatters.) See Ralf Brown's interrupt list (<Q:02.03>
  725.  [What and where is Ralf Brown's interrupt list?]), or PC Magazine July
  726.  1992 (xi:13) page 496, for details.
  727.  
  728.  INT 21 AH=69 also gets and sets the volume label in the boot record,
  729.  which is not necessarily the same as "the" volume label displayed by the
  730.  DIR, VOL, and LABEL commands. For that volume label, see <Q:05.12> [How
  731.  can I read, create, change, or delete the volume label?]
  732.  
  733. ------------------------------
  734.  
  735. Subject: <Q:05.14> - What's the format of .OBJ, .EXE., .COM files?
  736. Date: 5 Feb 2002 22:03:03 -0400
  737.  
  738.  Please see <Q:03.06> [What's the format of an .OBJ file?]; <Q:03.07>
  739.  [What's the format of an .EXE header?]; and <Q:03.08> [What's the
  740.  difference between .COM and .EXE formats?]
  741.  
  742. ------------------------------
  743.  
  744. Subject: <Q:05.15> - How can I flush the software disk cache?
  745. Date: 5 Feb 2002 22:03:03 -0400
  746.  
  747.  Please see <Q:08.01> [How can a program reboot my PC?] (Trust me.)
  748.  
  749. ------------------------------
  750.  
  751. Subject: <Q:05.16> - How can I see if a drive is a RAM drive?
  752. Date: 5 Feb 2002 22:03:03 -0400
  753.  
  754.  Use INT 21 AX=4409h. See Ralph Brown's interrupt list (<Q:02.03> [What
  755.  and where is Ralf Brown's interrupt list?]) for more information.
  756.  
  757. ------------------------------
  758.  
  759. Subject: <Q:05.17> - How can I determine a hard drive's manufacturer?
  760. Date: 5 Feb 2002 22:03:03 -0400
  761.  
  762.  Information about the hard drive's manufacturer is retrieved by using
  763.  the ATA and ATAPI specifications. Please see "<Q:05.18> [Where can I
  764.  find information about the ATA/ATAPI specification?]
  765.  
  766. ------------------------------
  767.  
  768. Subject: <Q:05.18> - Where can I find information about the ATA/ATAPI
  769.         specification?
  770. Date: 5 Feb 2002 22:03:03 -0400
  771.  
  772.  The AT Attachment (ATA) standard is maintained by T13, a Technical
  773.  Committee for the National Committee on Information Technology Standards
  774.  which as accredited by ANSI. Their web site can be found at
  775.  <http://www.t13.org>. At that web site the ATA and ATAPI specifications
  776.  are availible in PDF form.
  777.  
  778. ------------------------------
  779.  
  780. Subject: <Q:05.19> - How can I copy files to or from filenames containing
  781.         date information?
  782. Date: 7 Feb 2002 14:26:15 -0400
  783.  
  784.  You can use the NOWMINUS program. This program creates environment
  785.  variables containing date and time information. See <Q:08.15> [How can I
  786.  place date and time information into environment variables?] for more
  787.  information.
  788.  
  789.  Here is an example of using NOWMINUS to rename the files thisweek.* to
  790.  {lastweeksdate}.*:
  791.  
  792.         NOWMINUS d7 z7 f1 j0 vLASTWEEK
  793.         ren thisweek.* %LASTWEEK%.*
  794.         set LASTWEEK=
  795.  
  796. ------------------------------
  797.  
  798. Subject: Section 6. Serial ports (COM ports)
  799. Date: 5 Feb 2002 22:03:03 -0400
  800.  
  801.  This section provides information about how to access the serial ports.
  802.  In the future I will be working on adding information about using MS-DOS
  803.  for networking and internet access.
  804.  
  805. ------------------------------
  806.  
  807. Subject: <Q:06.01> - How do I set my machine up to use COM3 and COM4?
  808. Date: 5 Feb 2002 22:03:03 -0400
  809.  
  810.  Unless your machine is fairly old, it's probably already set up. After
  811.  installing the board that contains the extra COM port(s), check the I/O
  812.  addresses in word 0040:0004 or 0040:0006. (In DEBUG, type "D 40:4 L4"
  813.  and remember that every word is displayed low byte first, so if you see
  814.  "03 56" the word is 5603.) If those addresses are nonzero, your PC is
  815.  ready to use the ports and you don't need the rest of this answer.
  816.  
  817.  If the I/O address words in the 0040 segment are zero after you've
  818.  installed the I/O board, you need some code to store these values into
  819.  the BIOS data segment:
  820.  
  821.    0040:0004  word  I/O address of COM3
  822.    0040:0006  word  I/O address of COM4
  823.    0040:0011   byte  (bits  3-1):  number  of  serial   ports installed
  824.  
  825.  The documentation with your I/O board should tell you the port
  826.  addresses. When you know the proper port addresses, you can add code to
  827.  your program to store them and the number of serial ports into the BIOS
  828.  data area before you open communications. Or you can use DEBUG to create
  829.  a little program to include in your AUTOEXEC.BAT file, using this
  830.  script:
  831.  
  832.    n  SET_ADDR.COM     <--- or a different name  ending in .COM
  833.    a 100
  834.    mov  AX,0040
  835.    mov  DS,AX
  836.    mov  wo [0004],aaaa <--- replace aaaa with COM3 address or 0
  837.    mov  wo [0006],ffff <--- replace ffff with COM4 address or 0
  838.    and  by [0011],f1
  839.    or    by [0011],8   <--- use number of serial ports times 2
  840.    mov  AH,0
  841.    int  21
  842.                          <--- this line must be blank
  843.    rCX
  844.    1f
  845.    rBX
  846.    0
  847.    w
  848.    q
  849.  
  850. ------------------------------
  851.  
  852. Subject: <Q:06.02> - How do I find the I/O address of a COM port?
  853. Date: 8 Feb 2002 20:00:09 -0400
  854.  
  855.  Look in the four words beginning at 0040:0000 for COM1 through COM4.
  856.  (The DEBUG command "D 40:0 L8" will do this. Remember that words are
  857.  stored and displayed low byte first, so a word value of 03F8 will be
  858.  displayed as F8 03.) If the value is zero, that COM port is not
  859.  installed (or you've got an old BIOS; see <Q:06.01> [How do I set my
  860.  machine up to use COM3 and COM4?]). If the value is nonzero, it is the
  861.  I/O address of the transmit/receive register for the COM port.
  862.  
  863.  Each COM port occupies eight consecutive I/O addresses (though many
  864.  chips use only the first seven).
  865.  
  866.  Here's some C code to find the I/O address:
  867.  
  868.    unsigned ptSel(unsigned comport)
  869.    {
  870.      unsigned io_addr;
  871.   
  872.      if (comport >= 1  &&  comport <= 4)
  873.      {
  874.        unsigned far *com_addr = (unsigned far *)0x00400000UL;
  875.        io_addr = com_addr[comport-1];
  876.      }
  877.      else
  878.        io_addr = 0;
  879.   
  880.      return io_addr;
  881.    }
  882.  
  883.  You might also want to explore Port Finder, downloadable as:
  884.  <http://www.simtel.net/pub/pd/47138.html>
  885.  
  886.  I haven't tried it myself, but a posted article reviewed it very
  887.  favorably and said it also lets you swap ports around.
  888.  
  889. ------------------------------
  890.  
  891. Subject: <Q:06.03> - But aren't the COM ports always at I/O addresses
  892.         3F8, 2F8, 3E8, and 2E8?
  893. Date: 5 Feb 2002 22:03:03 -0400
  894.  
  895.  The first two are usually right (though not always); the last two are
  896.  different on many machines.
  897.  
  898. ------------------------------
  899.  
  900. Subject: <Q:06.04> - How do I configure a COM port and use it to transmit
  901.         data?
  902. Date: 8 Feb 2002 20:03:52 -0400
  903.  
  904.  Do you want actual code, or do you want books that explain what's going
  905.  on?
  906.  
  907.  1) Source code
  908.  
  909.  First, check your compiler's run-time library. Many compilers offer
  910.  functions similar to Microsoft C's _bios_serialcom() or Borland's
  911.  bioscom(), which may meet your needs.
  912.  
  913.  Second, check for downloadable resources at SimTel and Garbo. At SimTel,
  914.  <http://www.simtel.net/pub/pd/41750.html> (March 1993) is described as
  915.  "Asynchronous communications library for C"; Garbo has a whole
  916.  <ftp://garbo.uwasa.fi/pc/comm> directory. Also, an extended example is
  917.  in Borland's TechFax TI445, downloadable as part of:
  918.  <http://www.simtel.net/pub/pd/50843.html>
  919.  <ftp://garbo.uwasa.fi/pc/c-lang/bchelp10.zip>
  920.  
  921.  Though written by Borland, much of it is applicable to other forms of C,
  922.  and it should give you ideas for other programming languages.
  923.  
  924.  Third, SNIPPETS (see <Q:02.08> [What and where is SNIPPETS?]) contains a
  925.  sample interrupt-driven serial communications library.
  926.  
  927.  2) Reference books
  928.  
  929.  Highly recommended: Joe Campbell's {C Programmer's Guide to Serial
  930.  Communications}, ISBN 0-672-22584-0. He gives complete details on how
  931.  serial ports work, along with complete programs for doing polled or
  932.  interrupt-driver I/O. The book is quite thick, and none of it looks like
  933.  filler.
  934.  
  935.  If Campbell's book is overkill for you, you'll find a good short
  936.  description of serial I/O in {DOS 5: A Developer's Guide}, ISBN
  937.  1-55851-177-6, by Al Williams.
  938.  
  939.  Finally, a reader has recommended {Serial Communications Programming in
  940.  C/C++} by Mark Goodwin (ISBN 1-55828-198-3), with source code in the
  941.  book and on disk. Topics include the basics, various methods of serial
  942.  communications on the PC (with consideration of high-speed modems), ANSI
  943.  screen interface, file transfer protocols (Xmodem and Ymodem), etc.
  944.  There is code in C, and that code is extended into a C++ class for those
  945.  who use C++. There are also subroutines in Assembly.
  946.  
  947.  3) Downloadable information files
  948.  
  949.  A "Serial Port FAQ" is occasionally posted to this newsgroup, and is
  950.  downloadable as multiple files:
  951.  
  952.  <ftp://ftp.phil.uni-sb.de/pub/people/chris/>
  953.  
  954.  This directory contains a series of files beginning with Serial_Port.
  955.  
  956. ------------------------------
  957.  
  958. Subject: Conclusion
  959.  
  960. This is the end of part 3 of 5 parts.
  961.  
  962. This text is copyright 2003 by Jeffrey Carlyle. All rights reserved.
  963. Please see the top of this article for additional copyright information.
  964.  
  965.