home *** CD-ROM | disk | FTP | other *** search
/ PC Press 1997 July / Sezamfile97_1.iso / msdos / infoprog / dosprog3.faq < prev    next >
Internet Message Format  |  1997-06-15  |  32KB

  1. Path: Eunet.yu!EU.net!news.mathworks.com!bloom-beacon.mit.edu!senator-bedfellow.mit.edu!faqserv
  2. From: carlyle@tocnet.com (Jeffrey Carlyle)
  3. Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,comp.answers,news.answers
  4. Subject: comp.os.msdos.programmer FAQ part 3/5
  5. Supersedes: <msdos-programmer-faq/part3_840820372@rtfm.mit.edu>
  6. Followup-To: comp.os.msdos.programmer
  7. Date: 16 Sep 1996 08:25:27 GMT
  8. Organization: Stratoware
  9. Lines: 739
  10. Sender: carlyle@tocnet.com (Jeffrey Carlyle)
  11. Approved: news-answers-request@MIT.Edu
  12. Expires: 20 Oct 1996 07:39:43 GMT
  13. Message-ID: <msdos-programmer-faq/part3_842859583@rtfm.mit.edu>
  14. References: <msdos-programmer-faq/part1_842859583@rtfm.mit.edu>
  15. Reply-To: carlyle@tocnet.com (Jeffrey Carlyle)
  16. NNTP-Posting-Host: bloom-picayune.mit.edu
  17. Summary: Frequently asked questions by DOS programmers with tested answers.
  18. X-Last-Updated: 1996/03/30
  19. Originator: faqserv@bloom-picayune.MIT.EDU
  20. Xref: Eunet.yu comp.os.msdos.programmer:6032 comp.answers:1092
  21.  
  22. Archive-name: msdos-programmer-faq/part3
  23. Comp-os-msdos-programmer-archive-name: dos-faq-pt3.txt
  24. Posting-frequency: 20 days
  25. Last-modified: 20 Mar 1996
  26.  
  27. ------------------------------
  28.  
  29. Subject: comp.os.msdos.programmer FAQ part 3/5
  30.  
  31. This is part 3 of the frequently asked questions list for the newsgroup
  32. comp.os.msdos.programmer.
  33.  
  34. Part 3:
  35.   Section 5.  Disks and files
  36.   Section 6.  Serial ports (COM ports)
  37.  
  38. ------------------------------
  39.  
  40. Subject: comp.os.msdos.programmer FAQ
  41.  
  42. comp.os.msdos.programmer FAQ Version 2.06
  43.  
  44. Copyright 1996 by Jeffrey Carlyle, Stratoware. All rights reserved. This
  45. article is not in the public domain, but it may be redistributed so long
  46. as this notice, the acknowledgments, and the information on obtaining the
  47. latest copy of this list are retained and no fee is charged. The code
  48. fragments may be used freely;  credit would be polite. This FAQ is not to
  49. be included in any static archive (e.g. CD-ROM or book); however, a pointer
  50. to the FAQ may be included.
  51.  
  52.  =============================
  53.  TABLE OF CONTENTS
  54.  =============================
  55.  
  56. Part 1:
  57.   Section 1.  General FAQ and Newsgroup Information
  58.   Section 2.  General Reference
  59. Part 2:
  60.   Section 3.  Compile and Link
  61.   Section 4.  Keyboard
  62. Part 3:
  63.   Section 5.  Disks and files
  64.   Section 6.  Serial ports (COM ports)
  65. Part 4:
  66.   Section 7.  Other hardware questions and problems
  67.   Section 8.  Other software questions and problems
  68. Part 5:
  69.   Section 9.  Downloading
  70.   Section 10. Vendors and products
  71.  
  72. ------------------------------
  73.  
  74. Subject: Section 5.  Disks and files
  75.  
  76.   <q:5.01> - What drive was the PC booted from?
  77.   <q:5.02> - How can I boot from drive b:?
  78.   <q:5.03> - Which real and virtual disk drives are valid? 
  79.   <q:5.04> - How can I make my single floppy drive both a: and b:?
  80.   <q:5.05> - How can I disable access to a drive?
  81.   <q:5.06> - How can a batch file test existence of a directory? 
  82.   <q:5.07> - Why won't my C program open a file with a path?
  83.   <q:5.08> - How can I redirect printer output to a file? 
  84.   <q:5.09> - How can I redirect the output of a batch file? 
  85.   <q:5.10> - How can I redirect stderr? 
  86.   <q:5.11> - How can my program open more files than DOS's limit of 20?
  87.   <q:5.12> - How can I read, create, change, or delete the volume label?
  88.   <q:5.13> - How can I get the disk serial number? 
  89.   <q:5.14> - What's the format of .OBJ, .EXE., .COM files?
  90.   <q:5.15> - How can I flush the software disk cache?
  91.   <q:5.16> - How can I see if a drive is a RAM drive? 
  92.  
  93. ------------------------------
  94.  
  95. Subject: <q:5.01> - What drive was the PC booted from?
  96.     
  97.     Under DOS 4.0 or later, use INT 21 AX=3305.  DL is returned with an
  98.     integer indicating the boot drive (1=A:, etc.).
  99.  
  100. ------------------------------
  101.  
  102. Subject: <q:5.02> - How can I boot from drive b:?
  103.  
  104.     Downloadable shareware:
  105.  
  106.     <ftp://oak.oakland.edu/pub/msdos/diskutil/boot_b.zip>
  107.     <ftp://garbo.uwasa.fi/pc/bootutil/boot_b.zip>
  108.  
  109.     The included documentation says it works by writing a new boot
  110.     sector on a disk in your a: drive that redirects the boot to your b:
  111.     drive.  (A similar utility is bboot.zip in the same directory at
  112.     Garbo only.)
  113.  
  114.     If that doesn't work, you can always interchange your a: and b:
  115.     drives by switching ribbon cables and changing the setup in your
  116.     BIOS.  From an article posted 27 Jan 1993 on another newsgroup:
  117.  
  118.     Take the "ribbon" connector, as you call it, and switch them.  To
  119.     double check, start at the end of the cable that connects to the
  120.     motherboard or floppy controller.  Follow the cable until you get to
  121.     the first connector.  Connect this to the drive you want to be b:.
  122.     After this, there should be a few lines on the cable that get
  123.     flipped left to right.  (On most cables, they just cut the lines and
  124.     physically reverse them.  It should be quite obvious from looking at
  125.     the cable.)  Anyway, the connector after the pins get flipped right
  126.     to left is the connector for your a: drive.
  127.  
  128. ------------------------------
  129.  
  130. Subject: <q:5.03> - Which real and virtual disk drives are valid? 
  131. Date: Wed, 11 Jan 95 15:34:00 CDT
  132.  
  133.     Use INT 21 AH=29 (parse filename).  Point DS:SI at a null-terminated
  134.     ASCII string that contains the drive letter and a colon, point ES:DI
  135.     at a 37-byte dummy FCB buffer, and call INT 21 AX=2900.  On return,
  136.     AL is FF if the drive is invalid, something else if the drive is
  137.     valid.  RAM disks and SUBSTed drives are considered valid.
  138.  
  139.     You can detect whether the drive is ASSIGNed by using INT 2F
  140.     AX=0601.  To check whether the drive is SUBSTed, use INT 21 AX=4409;
  141.     or use INT 21 AH=52 to test for both JOIN and SUBST.  See Ralf
  142.     Brown's interrupt list <q:2.03>.
  143.  
  144.     Unfortunately, the b: drive is considered valid even on a single-
  145.     diskette system.  You can check that special case by interrogating
  146.     the BIOS equipment byte at 0040:0010.  Bits 7-6 contain the one less
  147.     than the number of diskette drives, so if those bits are zero you
  148.     know that b: is an invalid drive even though function 29 says it's
  149.     valid.
  150.  
  151.     Following is some code originally posted by Doug Dougherty to test
  152.     valid drives (treating SUBSTed and JOINed drives as valid), with my
  153.     fix for the b: special case, tested in Borland C++ 4.5 (in the large
  154.     model):
  155.  
  156.         #include <dos.h>
  157.         #include <stdio.h>
  158.         void drvlist(void) {
  159.             char s[3] = "A:", fcb_buff[37];
  160.             int valid;
  161.             for (   ;  *s<='Z';  (*s)++) {
  162.                 _SI = (unsigned) s;
  163.                 _DI = (unsigned) fcb_buff;
  164.                 _ES = _DS;
  165.                 _AX = 0x2900;
  166.                 geninterrupt(0x21);
  167.                 valid = _AL != 0xFF;
  168.                 if (*s == 'B'  &&  valid) {
  169.                     char far *equipbyte = (char far *)0x00400010UL;
  170.                     valid = (*equipbyte & (3 << 6)) != 0;
  171.                 }
  172.                 printf("Drive '%s' is %sa valid drive.\n",
  173.                         s, valid ? "" : "not ");
  174.             }
  175.         }
  176.  
  177.     This code was translated to MSC 7.0 and tested it in small model:
  178.  
  179.         #include <dos.h>
  180.         #include <stdio.h>
  181.         void drvlist(void) {
  182.             char s[3] = "A:", fcb_buff[37], *buff=fcb_buff;
  183.             int valid;
  184.             for (   ;  *s<='Z';  (*s)++) {
  185.                 __asm mov si,s      __asm mov di,buff
  186.                 __asm mov ax,ds     __asm mov es,ax
  187.                 __asm mov ax,0x2900 __asm int 21h
  188.                 __asm xor ah,ah     __asm mov valid,ax
  189.                 valid = (valid != 0xFF);
  190.                 if (*s == 'B'  &&  valid) {
  191.                     char far *equipbyte = (char far *)0x00400010UL;
  192.                     valid = (*equipbyte & (3 << 6)) != 0;
  193.                 }
  194.                 printf("Drive '%s' is %sa valid drive.\n",
  195.                         s, valid ? "" : "not ");
  196.             }
  197.         }
  198.  
  199. ------------------------------
  200.  
  201. Subject: <q:5.04> - How can I make my single floppy drive both a: and b:?
  202.  
  203.     Under any DOS since DOS 2.0, you can put the command
  204.  
  205.         assign b=a
  206.  
  207.     into your AUTOEXEC.BAT file.  Then, when you type "dir b:" you'll no
  208.     longer get the annoying prompt to insert diskette B (and the even
  209.     more annoying prompt to insert A the next time you type "dir a:").
  210.  
  211.     You may be wondering why anybody would want to do this.  Suppose you
  212.     use two different machines, maybe one at home and one at work.  One
  213.     of them has only a 3.5" diskette drive; the other machine has two
  214.     drives, and b: is the 3.5" one.  You're bound to type "dir b:" on
  215.     the first one, and get the nuisance message
  216.  
  217.         Insert diskette for drive B: and press any key when ready.
  218.  
  219.     But if you assign drive b: to point to a:, you avoid this problem.
  220.  
  221.     Caution:  there are a few commands, such as DISKCOPY, that will not
  222.     work right on ASSIGNed or SUBSTed drives.  See the DOS manual for
  223.     the full list.  Before typing one of those commands, be sure to turn
  224.     off the mapping by typing "assign" without arguments.
  225.  
  226.     The DOS 5.0 manual says that ASSIGN is obsolete, and recommends the
  227.     equivalent form of SUBST: "subst b: a:\".  Unfortunately, if this
  228.     command is executed when a: doesn't hold a diskette, the command
  229.     fails.  ASSIGN doesn't have this problem, so under DOS 5.0 you
  230.     should disregard that particular bit of advice in the manual.
  231.  
  232. ------------------------------
  233.  
  234. Subject: <q:5.05> - How can I disable access to a drive?
  235.  
  236.     Reader Eric DeVolder writes that he has made available a program to
  237.     do this.  I haven't tried it, but it's downloadable as
  238.  
  239.     <ftp://oak.oakland.edu/pub/msdos/diskutil/rmdriv20.zip>
  240.     <ftp://garbo.uwasa.fi/pc/sysutil/rmdriv20.zip>
  241.  
  242. ------------------------------
  243.  
  244. Subject: <q:5.06> - How can a batch file test existence of a directory?
  245. Date: Tue, 7 Mar 95 12:00:00 CDT
  246.  
  247.     The standard way, which in fact is documented in the DOS manual, is
  248.  
  249.         if exist d:\path\nul goto found
  250.  
  251.     Unfortunately, this is not entirely reliable.  I found it failed in
  252.     Pathworks (a/k/a PCSA, DEC's network that connects PCs and VAXes),
  253.     or on a MARS box that uses an OEM version of MS-DOS 5.0.  Readers
  254.     have reported that it gave the wrong answer on Novell networks, on
  255.     DR-DOS, and in a DOS window under OS/2.  By "failed" I mean that it
  256.     "found" a directory that didn't exist, or failed to find one that
  257.     did exist, or both.  (I'm told that IBM fixed the OS/2 bug in
  258.     version 2.11 of OS/2.) As a legacy from earlier versions of DOS it
  259.     always succeedes if the path is DEV.
  260.  
  261.     There appears to be no foolproof way to use pure batch commands to
  262.     test for existence of a directory.  The real solution is to write a
  263.     program, which returns a value that your batch program can then test
  264.     with an "if errorlevel".  Reader Duncan Murdoch kindly posted the
  265.     following Turbo Pascal version:
  266.  
  267.         program existdir;
  268.             { Confirms the existence of a directory given on the command
  269.             line.  Returns errorlevel 2 on error, 1 if not found, 0 if
  270.             found. }
  271.  
  272.         uses
  273.             dos;
  274.  
  275.         var
  276.             s : searchrec;
  277.  
  278.         begin
  279.             if paramcount <> 1 then
  280.             begin
  281.                 writeln('Syntax:  EXISTDIR directory');
  282.                 halt(2);
  283.             end
  284.             else
  285.             begin
  286.                 findfirst(paramstr(1),Directory,S);
  287.                 while (Doserror = 0) and ((Directory and S.Attr) = 0) do
  288.                     findnext(S);
  289.                 if Doserror <> 0 then
  290.                 begin
  291.                     Writeln('Directory not found.');
  292.                     halt(1);
  293.                 end
  294.                 else
  295.                 begin
  296.                     Writeln('Directory found.');
  297.                     halt(0);
  298.                 end;
  299.             end;
  300.         end.
  301.  
  302.     Timo Salmi also has a Turbo Pascal version in his Turbo Pascal FAQ,
  303.     which is downloadable as
  304.  
  305.     <ftp://garbo.uwasa.fi/pc/ts/tsfaqp*.zip>
  306.  
  307. ------------------------------
  308.  
  309. Subject: <q:5.07> - Why won't my C program open a file with a path?
  310.  
  311.     You've probably got something like the following code:
  312.  
  313.         char *filename = "c:\foo\bar\mumble.dat";
  314.         FILE *fptr;
  315.         . . .
  316.         fptr = fopen(filename, "r");
  317.  
  318.     The problem is that \f is a form feed, \b is a backspace, and \m is
  319.     m.  Whenever you want a backslash in a string constant in C, you
  320.     must use two backslashes:
  321.  
  322.         char *filename = "c:\\foo\\bar\\mumble.dat";
  323.  
  324.     This is a feature of every C compiler, because Dennis Ritchie
  325.     designed C this way.  It's a problem only on MS-DOS systems, because
  326.     only DOS (and Atari ST/TT running TOS) uses the backslash in
  327.     directory paths.  But even in DOS this backslash convention applies
  328.     _only_ to string constants in your source code.  For file and
  329.     keyboard input at run time, \ is just a normal character, so users
  330.     running your program would type in file specs the same way as in DOS
  331.     commands, with single \ characters.
  332.  
  333.     Another possibility is to code all paths in source programs with /
  334.     rather than \ characters:
  335.  
  336.         char *filename = "c:/foo/bar/mumble.dat";
  337.  
  338.     Ralf Brown writes, "All versions of the DOS kernel accept either
  339.     forward or backslashes as directory separators.  I tend to use this
  340.     form more frequently than backslashes since it is easier to type and
  341.     read."  This applies to DOS function calls (and therefore to calls
  342.     to the file library of every programming language), but not to DOS
  343.     commands.
  344.  
  345. ------------------------------
  346.  
  347. Subject: <q:5.08> - How can I redirect printer output to a file?
  348.  
  349.     Recommended: PRN2FILE from PC Magazine, downloadable as:
  350.  
  351.     <ftp://oak.oakland.edu/pub/msdos/printer/prn2file.zip>
  352.     <ftp://garbo.uwasa.fi/pc/printer/prn2file.zip>
  353.  
  354.     PC Magazine has given copies away as part of its utilities disks, so
  355.     you may already have a copy.
  356.  
  357.     The directories mentioned above have lots of other utilities to
  358.     redirect printer output.
  359.  
  360. ------------------------------
  361.  
  362. Subject: <q:5.09> - How can I redirect the output of a batch file?
  363.  
  364.     Assuming the batch file is called batch.bat, to send its output
  365.     (stdout) to another file, just invoke COMMAND.COM as a secondary
  366.     command processor:
  367.  
  368.         command /c batch parameters_if_any >outfile
  369.  
  370.     Timo Salmi's notes on this and other batch tricks are downloadable:
  371.  
  372.     <ftp://oak.oakland.edu/pub/msdos/batutil/tsbat44.zip>
  373.     <ftp://garbo.uwasa.fi/pc/ts/tsbat44.zip>
  374.  
  375. ------------------------------
  376.  
  377. Subject: <q:5.10> - How can I redirect stderr?
  378.  
  379.     Use freopen(..., stderr) and then execute the desired command via
  380.     system().  There are downloadable versions of programs to do this.
  381.     I recommend this file, which includes TP4 source and executable:
  382.  
  383.     <ftp://oak.oakland.edu/pub/msdos/sysutil/rdstderr.zip>
  384.  
  385.     A C example is downloadable as
  386.  
  387.     <ftp://oak.oakland.edu/pub/msdos/c/redirect.c>
  388.  
  389.     I compiled it with MSC 7.0, and it works fine with one exception:
  390.     Contrary to the included comments, redirected output starts writing
  391.     at the beginning of the output file rather than appending.  That is
  392.     easily solved by adding "fseek(stderr, 0L, SEEK_END);" after the
  393.     freopen() call for stderr.
  394.  
  395. ------------------------------
  396.  
  397. Subject: <q:5.11> - How can my program open more files than DOS's
  398.         limit of 20?
  399.  
  400.     This is a summary of an article Ralf Brown posted on 8 August 1992,
  401.     with some additions from a Microsoft tech note and information from
  402.     Chin Huang.)
  403.  
  404.     DOS imposes some limits.  Once you overcome those, which is pretty
  405.     easy, you may have to take additional measures to overcome the
  406.     limitations built into your compiler's run-time library.
  407.  
  408.     1) Limitations imposed by DOS
  409.  
  410.     There are separate limits on files and file handles.  For example,
  411.     DOS opens three files but five file handles:  CON (stdin, stdout,
  412.     and stderr), AUX (stdaux), and PRN (stdprn).
  413.  
  414.     The limit in FILES= in CONFIG.SYS is a system-wide limit on files
  415.     opened by all programs (including the three that DOS opens and any
  416.     opened by TSRs); each process has a limit of 20 handles (including
  417.     the five that DOS opens).  Example:  CONFIG.SYS has FILES=40.  Then
  418.     program #1 will be able to open 15 file handles.  Assuming that the
  419.     program actually does open 15 handles pointing to 15 different
  420.     files, other programs could still open a total of 22 files (40-3-15
  421.     = 22), though no one program could open more than 15 file handles.
  422.  
  423.     If you're running DOS 3.3 or later, you can increase the per-process
  424.     limit of 20 file handles by a call to INT 21 AH=67, Set Handle
  425.     Count.  Your program is still limited by the system-wide limit on
  426.     open files, so you may also need to increase the FILES= value in
  427.     your CONFIG.SYS file (and reboot).  The run-time library that you're
  428.     using may have a fixed-size table of file handles, so you may also
  429.     need to get source code for the module that contains the table,
  430.     increase the table size, and recompile it.
  431.  
  432.     2) Limitations in Microsoft C run-time library
  433.  
  434.     In Microsoft C the run-time library limits you to 20 file handles.
  435.     To change this, you must be aware of two limits:
  436.  
  437.     - file handles used with _open(), _read(), etc.: Edit _NFILE_ in
  438.       CRT0DAT.ASM.
  439.  
  440.     - stream files used with fopen(), fread(), etc.: Edit _NFILE_ in
  441.       _FILE.C for DOS or FILE.ASM for Windows/QuickWin.  This must not
  442.       exceed the value of _NFILE_ in CRT0DAT.ASM.
  443.  
  444.     (QuickWin uses the constant _WFILE_ in CRT0DAT.ASM and WFILE.ASM for
  445.     the maximum number of child text windows.)
  446.  
  447.     After changing the limits, recompile using CSTARTUP.BAT.  Microsoft
  448.     recommends that you first read README.TXT in the same directory.
  449.  
  450.     3) Limitations in Borland C++ run-time library
  451.  
  452.     (Reader Chin Huang provided this information on 12 Sep 1993.)
  453.  
  454.     To increase the open file limit for a program you compile with
  455.     Borland C++ 3.1, edit the file _NFILE.H in the include directory and
  456.     change the _NFILE_ value.  Compile and link the modules FILES.C and
  457.     FILES2.C from the lib directory into your program.
  458.  
  459. ------------------------------
  460.  
  461. Subject: <q:5.12> - How can I read, create, change, or delete the volume
  462.         label?
  463.  
  464.     In DOS 5.0 (and possibly in 4.0 as well), there are actually two
  465.     volume labels: the LABEL command reports only the first but changes
  466.     both of them.
  467.  
  468.     - The traditional volume label is an entry with "volume label"
  469.       attribute in the root directory of the disk.  The DIR, VOL, and
  470.       LABEL commands report this volume label, and LABEL sets it.
  471.  
  472.     - There is a second volume label, which may be different, in the
  473.       boot record along with the serial number. In DOS 4.0 and later,
  474.       INT 21 AH=69 gets or sets the boot record's serial number and
  475.       volume label together; see "<q:5.13> - How can I get the disk serial
  476.       number?"  DIR and VOL ignore this volume label; the LABEL command
  477.       doesn't report it but does set it.
  478.  
  479.     The rest of this answer assumes that by "volume label" you mean the
  480.     traditional one, the one that DIR and VOL display.  Though it's a
  481.     directory entry in the root directory, you can't change it using the
  482.     newer DOS file-access functions (INT 21 AH=3C, 41, 43); instead, use
  483.     the old FCB-oriented directory functions.  Specifically, you need to
  484.     allocate a 64-byte buffer and a 41- byte extended FCB (file control
  485.     block).  Call INT 21 AH=1A to find out whether there is a volume
  486.     label.  If there is, AL returns 0 and you can change the label using
  487.     DOS function 17 or delete it using DOS function 13.  If there's no
  488.     volume label, function 1A will return FF and you can create a label
  489.     via function 16.  Important points to notice are that ? wildcards
  490.     are allowed but * are not; the volume label must be space filled not
  491.     null terminated.
  492.  
  493.     The following MSC 7.0 code worked for me in DOS 5.0; the functions
  494.     it uses have been around since DOS 2.0.  The function parameter is 0
  495.     for the current disk, 1 for a:, 2 for b:, etc.  It doesn't matter
  496.     what your current directory is; these functions always search the
  497.     root directory for volume labels.  (I didn't try to change the
  498.     volume label of any networked drives.)
  499.  
  500.         // Requires DOS.H, STDIO.H, STRING.H
  501.         void vollabel(unsigned char drivenum) {
  502.             static unsigned char extfcb[41], dta[64], status, *newlabel;
  503.             int chars_got = 0;
  504.             #define DOS(buff,func) __asm { __asm mov dx,offset buff   \
  505.                 __asm mov ax,seg buff  __asm push ds  __asm mov ds,ax \
  506.                 __asm mov ah,func  __asm int 21h  __asm pop ds        \
  507.                 __asm mov status,al }
  508.             #define getlabel(buff,prompt) newlabel = buff;  \
  509.                 memset(newlabel,' ',11);  printf(prompt);   \
  510.                 scanf("%11[^\n]%n", newlabel, &chars_got);  \
  511.                 if (chars_got < 11) newlabel[chars_got] = ' ';
  512.  
  513.             // Set up the 64-byte transfer area used by function 1A.
  514.             DOS(dta, 1Ah)
  515.             // Set up an extended FCB and search for the volume label.
  516.             memset(extfcb, 0, sizeof extfcb);
  517.             extfcb[0] = 0xFF;           // denotes extended FCB
  518.             extfcb[6] = 8;              // volume-label attribute bit
  519.             extfcb[7] = drivenum;       // 1=A,2=B,...; 0=current drive
  520.             memset(&extfcb[8], '?', 11);// wildcard *.*
  521.             DOS(extfcb,11h)
  522.             if (status == 0) {          // DTA has volume label's FCB
  523.                 printf("volume label is %11.11s\n", &dta[8]);
  524.                 getlabel(&dta[0x18],
  525.                     "new label (\"delete\" to delete): ");
  526.                 if (chars_got == 0)
  527.                     printf("label not changed\n");
  528.                 else if (strncmp(newlabel,"delete  ",11) == 0) {
  529.                     DOS(dta,13h)
  530.                     printf(status ? "label failed\n" :
  531.                                     "label deleted\n");
  532.                 }
  533.                 else {                  // user wants to change label
  534.                     DOS(dta,17h)
  535.                     printf(status ? "label failed\n" :
  536.                                     "label changed\n");
  537.                 }
  538.             }
  539.             else {                      // no volume label was found
  540.                 printf("disk has no volume label.\n");
  541.                 getlabel(&extfcb[8], "new label (<Enter> for none): ");
  542.                 if (chars_got > 0) {
  543.                     DOS(extfcb,16h)
  544.                     printf(status ? "label failed\n" :
  545.                                     "label created\n");
  546.                 }
  547.             }
  548.         }        // end function vollabel
  549.  
  550. ------------------------------
  551.  
  552. Subject: <q:5.13> - How can I get the disk serial number?
  553.  
  554.     If the disk was formattted by DOS 4.0 or later, use INT 21: AX=6900
  555.     gets the serial number; AX=6901 sets it.  (The disk serial number
  556.     doesn't exist if the disk was formatted with an earlier version of
  557.     DOS, or with some third-party formatters.)  See Ralf Brown's
  558.     interrupt list <q:2.03>, or PC Magazine July 1992 (xi:13) page 496,
  559.     for details.
  560.  
  561.     INT 21 AH=69 also gets and sets the volume label in the boot record,
  562.     which is not necessarily the same as "the" volume label displayed by
  563.     the DIR, VOL, and LABEL commands.  For that volume label, see
  564.     <q:5.12> - "How can I read, create, change, or delete the volume
  565.     label?"
  566.  
  567. ------------------------------
  568.  
  569. Subject: <q:5.14> - What's the format of .OBJ, .EXE., .COM files?
  570.  
  571.     Please see <q:3.06> "What's the format of an .OBJ file?"; <q:3.07>
  572.     "What's the format of an .EXE header?"; and <q:3.08> "What's the
  573.     difference between .COM and .EXE formats?"
  574.  
  575. ------------------------------
  576.  
  577. Subject: <q:5.15> - How can I flush the software disk cache?
  578.  
  579.     Please see "<q:8.01> - How can a program reboot my PC?"
  580.  
  581. ------------------------------
  582.  
  583. Subject: <q:5.16> - How can I see if a drive is a RAM drive? 
  584. Date: Tue, 7 Mar 95 12:00:00 CDT
  585.  
  586.     Use INT 21 AX=4409h. See Ralph Brown's interrupt list <q:2.03> for
  587.     more information.
  588.  
  589. ------------------------------
  590.  
  591. Subject: Section 6.  Serial ports (COM ports)
  592.  
  593.   <q:6.01> - How do I set my machine up to use COM3 and COM4?
  594.   <q:6.02> - How do I find the I/O address of a COM port? 
  595.   <q:6.03> - But aren't the COM ports always at I/O addresses 3F8, 2F8,
  596.              3E8, and 2E8?
  597.   <q:6.04> - How do I configure a COM port and use it to transmit data?
  598.  
  599. ------------------------------
  600.  
  601. Subject: <q:6.01> - How do I set my machine up to use COM3 and COM4?
  602.  
  603.     Unless your machine is fairly old, it's probably already set up.
  604.     After installing the board that contains the extra COM port(s),
  605.     check the I/O addresses in word 0040:0004 or 0040:0006.  (In DEBUG,
  606.     type "D 40:4 L4" and remember that every word is displayed low byte
  607.     first, so if you see "03 56" the word is 5603.)  If those addresses
  608.     are nonzero, your PC is ready to use the ports and you don't need
  609.     the rest of this answer.
  610.  
  611.     If the I/O address words in the 0040 segment are zero after you've
  612.     installed the I/O board, you need some code to store these values
  613.     into the BIOS data segment:
  614.  
  615.         0040:0004  word  I/O address of COM3
  616.         0040:0006  word  I/O address of COM4
  617.         0040:0011  byte (bits 3-1): number of serial ports installed
  618.  
  619.     The documentation with your I/O board should tell you the port
  620.     addresses.  When you know the proper port addresses, you can add
  621.     code to your program to store them and the number of serial ports
  622.     into the BIOS data area before you open communications.  Or you can
  623.     use DEBUG to create a little program to include in your AUTOEXEC.BAT
  624.     file, using this script:
  625.  
  626.         n SET_ADDR.COM      <--- or a different name ending in .COM
  627.         a 100
  628.         mov  AX,0040
  629.         mov  DS,AX
  630.         mov  wo [0004],aaaa <--- replace aaaa with COM3 address or 0
  631.         mov  wo [0006],ffff <--- replace ffff with COM4 address or 0
  632.         and  by [0011],f1
  633.         or   by [0011],8    <--- use number of serial ports times 2
  634.         mov  AH,0
  635.         int  21
  636.                             <--- this line must be blank
  637.         rCX
  638.         1f
  639.         rBX
  640.         0
  641.         w
  642.         q
  643.  
  644. ------------------------------
  645.  
  646. Subject: <q:6.02> - How do I find the I/O address of a COM port?
  647.  
  648.     Look in the four words beginning at 0040:0000 for COM1 through COM4.
  649.     (The DEBUG command "D 40:0 L8" will do this.  Remember that words
  650.     are stored and displayed low byte first, so a word value of 03F8
  651.     will be displayed as F8 03.)  If the value is zero, that COM port is
  652.     not installed (or you've got an old BIOS; see "5.01> - How do I set my
  653.     machine up to use COM3 and COM4?").  If the value is nonzero, it is
  654.     the I/O address of the transmit/receive register for the COM port.
  655.     Each COM port occupies eight consecutive I/O addresses (though many
  656.     chips use only the first seven).
  657.  
  658.     Here's some C code to find the I/O address:
  659.  
  660.         unsigned ptSel(unsigned comport) {
  661.             unsigned io_addr;
  662.             if (comport >= 1  &&  comport <= 4) {
  663.                 unsigned far *com_addr = (unsigned far *)0x00400000UL;
  664.                 io_addr = com_addr[comport-1];
  665.             }
  666.             else
  667.                 io_addr = 0;
  668.             return io_addr;
  669.         }
  670.  
  671.     You might also want to explore Port Finder, downloadable as
  672.  
  673.     <ftp://oak.oakland.edu/pub/msdos/io_util/pf271.zip>
  674.     <ftp://nic.funet.fi/pub/msdos/utilities/sysutl/pf271.zip>
  675.  
  676.     I haven't tried it myself, but a posted article reviewed it very
  677.     favorably and said it also lets you swap ports around.
  678.  
  679. ------------------------------
  680.  
  681. Subject: <q:6.03> - But aren't the COM ports always at I/O addresses 3F8,
  682.                 2F8, 3E8, and 2E8?
  683.  
  684.     The first two are usually right (though not always); the last two
  685.     are different on many machines.
  686.  
  687. ------------------------------
  688.  
  689. Subject: <q:6.04> - How do I configure a COM port and use it to transmit
  690.         data?
  691. Date: Sun, 21 May 95 12:00:00 CDT
  692.  
  693.     Do you want actual code, or do you want books that explain what's
  694.     going on?
  695.  
  696.     1) Source code
  697.  
  698.     First, check your compiler's run-time library.  Many compilers offer
  699.     functions similar to Microsoft C's _bios_serialcom() or Borland's
  700.     bioscom(), which may meet your needs.
  701.  
  702.     Second, check for downloadable resources at SimTel and Garbo.  At
  703.     SimTel, <ftp://oak.oakland.edu/pub/msdos/c/pcl4c34.zip> (March 1993)
  704.     is described as "Asynchronous communications library for C"; Garbo
  705.     has a whole <ftp://garbo.uwasa.fi/pc/comm> directory.  Also, an
  706.     extended example is in Borland's TechFax TI445, downloadable as
  707.     part of
  708.  
  709.     <ftp://oak.oakland.edu/pub/msdos/turbo-c/bchelp10.zip>
  710.     <ftp://garbo.uwasa.fi/pc/turbopas/bchelp10.zip>
  711.  
  712.     Though written by Borland, much of it is applicable to other forms
  713.     of C, and it should give you ideas for other programming languages.
  714.  
  715.     2) Reference books
  716.  
  717.     Highly recommended: Joe Campbell's {C Programmer's Guide to Serial
  718.     Communications}, ISBN 0-672-22584-0.  He gives complete details on
  719.     how serial ports work, along with complete programs for doing polled
  720.     or interrupt-driver I/O.  The book is quite thick, and none of it
  721.     looks like filler.
  722.  
  723.     If Campbell's book is overkill for you, you'll find a good short
  724.     description of serial I/O in {DOS 5: A Developer's Guide}, ISBN
  725.     1-55851-177-6, by Al Williams.
  726.  
  727.     Finally, a reader has recommended {Serial Communications Programming
  728.     in C/C++} by Mark Goodwin (ISBN 1558281983), with source code in the
  729.     book and on disk.  Topics include the basics, various methods of
  730.     serial communications on the PC (with consideration of high-speed
  731.     modems), ANSI screen interface, file transfer protocols (Xmodem and
  732.     Ymodem), etc.  There is code in C, and that code is extended into a
  733.     C++ class for those who use C++.  There are also subroutines in
  734.     Assembly.
  735.  
  736.     3) Downloadable information files
  737.  
  738.     A "Serial Port FAQ" is occasionally posted to this newsgroup, and is
  739.     downloadable as multiple files:
  740.  
  741.     <ftp://ftp.phil.uni-sb.de/pub/staff/chris/*Serial*>
  742.     <ftp://rtfm.mit.edu/pub/usenet/comp.os.msdos.programmer/
  743.            The_Serial_Port*>
  744.  
  745.     For rtfm.mit.edu instructions, see <q:1.13> "Where are FAQ lists
  746.     archived?"
  747.  
  748. ------------------------------
  749.  
  750. Subject: End
  751.  
  752. (End of comp.os.msdos.programmer FAQ Version 2.06 Part 3/5)
  753. (This text is copyright 1996 by Jeffrey Carlyle. All rights reserved.)
  754.  
  755.  
  756. // Jeffrey Carlyle, Stratoware, Bowling Green, KY USA _,,-^`--. 
  757. // comp.os.msdos.programmer FAQ maintainer      .__,-'         \
  758. // <mailto:carlyle@tocnet.com>                _/     *        ,/
  759. // <http://users.aol.com/jc101>              (__,-----------''
  760.  
  761.