=======
DOS.H
=======
Functions
=========
absread
abswrite
allocmem
bdos
bdosptr
_chain_intr
country
ctrlbrk
delay
disable
_dos_allocmem
_dos_close
_dos_creat
_dos_creatnew
dosexterr
_dos_findfirst
_dos_findnext
_dos_freemem
_dos_getdate
_dos_getdiskfree
_dos_getdrive
_dos_getfileattr
_dos_getftime
_dos_gettime
_dos_getvect
_dos_keep
_dos_open
_dos_read
_dos_setblock
_dos_setdate
_dos_setdrive
_dos_setfileattr
_dos_setftime
_dos_settime
_dos_setvect
dostounix
_dos_write
_emit_
enable
FP_OFF
FP_SEG
freemem
geninterrupt
getcbrk
getdate
getdfree
_getdrive
getdta
getfat
getfatd
getftime
getpsp
gettime
getvect
getverify
_harderr
harderr
_hardresume
hardresume
_hardretn
hardretn
inp
inport
inportb
int86
int86x
intdos
intdosx
intr
keep
MK_FP
nosound
outp
outport
outportb
_OvrInitEms
_OvrInitExt
parsfnm
peek
peekb
poke
pokeb
randbrd
randbwr
segread
setblock
setcbrk
setdate
setdta
settime
setvect
setverify
sleep
sound
unixtodos
unlink
Constants, data types, and global variables
===========================================
_8087
_argc
_argv
BYTEREGS
COUNTRY
date
devhdr
dfree
diskfree_t
dosdate_t
DOSERROR
dostime_t
_doserrno
dosSearchInfo
environ
fatinfo
fcb
FA_*
ffblk
_heaplen
NFDS
_osmajor
_osminor
_osversion
_psp
REGPACK
REGS
SEEK_CUR
SEEK_END
SEEK_SET
SREGS
_stklen
time
_version
WORDREGS
xfcb
See Also
========
List of all Header files
FA_xxxx <DOS.H>
=========
DOS file attributes
Constant | Description
-----------+---------------------
FA_RDONLY | Read-only attribute
FA_HIDDEN | Hidden file
FA_SYSTEM | System file
FA_LABEL | Volume label
FA_DIREC | Directory
FA_ARCH | Archive
For more detailed information about these
attributes, refer to your DOS reference
manuals.
NFDS <DOS.H>
======
Maximum number of file descriptors.
fcb <DOS.H>
=====
The structure of the MS-DOS file control
blocks.
struct fcb {
char fcb_drive;
char fcb_name[8], fcb_ext[3];
short fcb_curblk, fcb_recsize;
long fcb_filsize;
short fcb_date;
char fcb_resv[10], fcb_currec;
long fcb_random;
};
xfcb <DOS.H>
======
The MS-DOS extended file control block
structure.
struct xfcb {
char xfcb_flag;
char xfcb_resv[5];
char xfcb_attr;
struct fcb xfcb_fcb;
};
dfree <DOS.H>
=======
The structure of the information returned
by the getdfree function.
struct dfree {
unsigned df_avail; /* Available clusters */
unsigned df_total; /* Total clusters */
unsigned df_bsec; /* Bytes per sector */
unsigned df_sclus; /* Sectors per cluster */
};
fatinfo <DOS.H>
=========
The structure of the file allocation table
information filled in by the getfat and
getfatd functions.
struct fatinfo {
char fi_sclus; /* sectors per cluster */
char fi_fatid; /* the FAT id byte */
int fi_nclus; /* number of clusters */
int fi_bysec; /* bytes per sector */
};
time <DOS.H>
======
Structure of the time as used by these
functions:
dostounix
gettime
settime
unixtodos
struct time {
unsigned char ti_min; /* minutes */
unsigned char ti_hour; /* hours */
unsigned char ti_hund; /* hundredths of seconds */
unsigned char ti_sec; /* seconds */
};
date <DOS.H>
======
Structure of the date as used by these
functions:
dostounix
getdate
setdate
unixtodos
struct date {
int da_year; /* current year */
char da_day; /* day of the month */
char da_mon; /* month (1 = Jan) */
};
REGS (union) <DOS.H>
======
The union REGS is used to pass information to
and from these functions:
int86
int86x
intdos
intdosx
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
See Also:
struct REGPACK
BYTEREGS and WORDREGS <DOS.H>
=======================
Structures for storing byte and word registers
struct BYTEREGS {
unsigned char al, ah, bl, bh;
unsigned char cl, ch, dl, dh;
};
struct WORDREGS {
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
SREGS <DOS.H>
=======
The structure of the segment registers passed
to and filled in by these functions:
int86x
intdosx
segread
struct SREGS {
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
REGPACK <DOS.H>
=========
The structure of the values passsed to and
returned by the intr function call.
struct REGPACK {
unsigned r_ax, r_bx, r_cx, r_dx;
unsigned r_bp, r_si, r_di;
unsigned r_ds, r_es, r_flags;
};
See Also:
REGS
COUNTRY <DOS.H>
=========
The structure country specifies how
certain country-dependent data is to be
formatted.
struct COUNTRY {
int co_date; /* date format */
char co_curr[5]; /* currency symbol */
char co_thsep[2]; /* thousands separator */
char co_desep[2]; /* decimal separator */
char co_dtsep[2]; /* date separator */
char co_tmsep[2]; /* time separator */
char co_currstyle; /* currency style */
char co_digits; /* significant digits in currency */
char co_time; /* time format */
long co_case; /* case map */
char co_dasep[2]; /* data separator */
char co_fill[10]; /* filler */
};
This is the date format in co_date:
Value| Format
-----+--------------------------------------
0 | U.S. style (Month, Day, Year)
1 | European style (Day, Month, Year)
2 | Japanese style (Year, Month, Day )
This is the currency display style in
co_currstyle:
Style| Meaning | Example
-----+------------------------------------------+---------
0 | Currency symbol precedes value with no | $10.52
| spaces between the symbol and the number |
1 | Currency symbol follows value with no | 10.52$
| spaces between the number and the symbol |
2 | Currency symbol precedes value with a | $ 10.52
| space after the symbol. |
3 | Currency symbol follows the number with | 10.52 $
| a space before the symbol. |
devhdr <DOS.H>
========
Header structure for MS-DOS device drivers.
struct devhdr {
long dh_next;
short dh_attr;
unsigned short dh_strat;
unsigned short dh_inter;
char dh_name[8];
};
DOSERROR <DOS.H>
==========
Used by dosexterr to return extended DOS
errors.
struct DOSERROR {
int de_exterror; /* extended error */
char de_class; /* error class */
char de_action; /* action */
char de_locus; /* error locus */
};
See Also:
_doserrno
errno
Example:
#include <stdio.h>
#include <dos.h>
int main(void)
{
FILE *fp;
struct DOSERROR info;
fp = fopen("perror.dat","r");
if (!fp) perror("Unable to open file for reading");
dosexterr(&info);
printf("Extended DOS error information:\n");
printf(" Extended error: %d\n",info.de_exterror);
printf(" Class: %x\n",info.de_class);
printf(" Action: %x\n",info.de_action);
printf(" Error Locus: %x\n",info.de_locus);
return 0;
}
find_t <DOS.H>
========
DOS file control block structure used by
_dos_findfirst and _dos_findnext.
The find_t structure corresponds exactly to
the ffblk structure.
struct find_t {
char reserved[21]; /* Microsoft reserved - do not change*/
char attrib; /* attribute byte for matched file */
unsigned wr_time; /* time of last write to file */
unsigned wr_date; /* date of last write to file */
long size; /* size of file */
char name[13]; /* asciiz name of matched file */
};
dosdate_t <DOS.H>
===========
Structure used by _dos_getdate and
_dos_setdate.
struct dosdate_t {
unsigned char day; /* 1--31 */
unsigned char month; /* 1--12 */
unsigned int year; /* 1980--2099 */
unsigned char dayofweek; /* 0--6; 0 = Sunday */
};
dostime_t <DOS.H>
===========
Structure used by _dos_gettime and
_dos_settime.
struct dostime_t {
unsigned char hour; /* Hours */
unsigned char minute; /* Minutes */
unsigned char second; /* Seconds */
unsigned char hsecond; /* Hundredths of seconds */
};
diskfree_t <DOS.H>
============
Structure used by _dos_getdiskfree.
struct diskfree_t {
unsigned total_clusters;
unsigned avail_clusters;
unsigned sectors_per_cluster;
unsigned bytes_per_sector;
};
dosSearchInfo <DOS.H>
===============
typedef struct {
char drive;
char pattern [13];
char reserved [7];
char attrib;
short time;
short date;
long size;
char nameZ [13];
} dosSearchInfo;
int _8087 <DOS.H>
===========
Coprocessor chip flag
Declaration: extern int _8087
If the program is running on a machine with
a math coprocessor, _8087 is nonzero:
_8087 | Math
value | coprocessor
-------+----------------
1 | 8087
2 | 80287
3 | 80387
-------+----------------
0 | (none detected)
You can override the autodetection logic with
the DOS commands SET 87=NO or SET 87=YES.
See Also:
List of all global variables
_argc <DOS.H>
=======
Keeps a count of command-line arguments.
Declaration: extern int _argc;
_argc has the value of argc passed to main()
when the program starts.
See Also:
_argv
List of all global variables
_argv <DOS.H>
=======
Array of pointers to command-line arguments
Declaration: extern char *_argv[]
See Also:
_argc
List of all global variables
_doserrno <DOS.H, ERRNO.H, STDLIB.H>
===========
Variable indicating actual DOS error code.
Declaration: int _doserrno
When an MS-DOS system call results in an
error, _doserrno is set to the actual
DOS error code.
These are the mnemonics for the actual DOS
error codes to which _doserrno can be set:
Mnemonic | DOS error code
---------+------------------------------
E2BIG | Bad environ
EACCES | Access denied
EACCES | Bad access
EACCES | Is current dir
EBADF | Bad handle
EFAULT | Reserved
EINVAL | Bad data
EINVAL | Bad function
EMFILE | Too many open
ENOENT | No such file or directory
ENOEXEC | Bad format
ENOMEM | Mcb destroyed
ENOMEM | Out of memory
ENOMEM | Bad block
EXDEV | Bad drive
EXDEV | Not same device
See Also:
errno
sys_errlist
List of all global variables
environ <DOS.H, STDLIB.H>
==========
Array of strings used to access and alter
a process environment.
Declaration: extern char **environ
See Also:
getenv
putenv
List of all global variables
_heaplen <DOS.H>
==========
Holds the length of the near heap, in bytes
Declaration: extern unsigned _heaplen
_heaplen specifies the size (in bytes) of the
near heap in the small data models (tiny,
small, and medium).
_heaplen does not exist in the large data
models (compact, large, and huge), because
they do not have a near heap.
The value of _heaplen at the start of program
execution determines the size of the near
heap that will be allocated.
Default = 0 (Makes a maximum-sized heap)
_heaplen is not used in the large data models.
* In the tiny model, if _heaplen = 0, the
effective heap size is
64K - (256 + code + global data + stack) bytes
* In the small and medium models, if _heaplen
= 0, the program allocates 64K bytes for the
data segment, and the effective heap size is
64K - (global data + stack) bytes
See Also:
_stklen
List of all global variables
_ovrbuffer <DOS.H>
============
Changes the size of the overlay buffer
Declaration: unsigned _ovrbuffer = size;
The default overlay buffer size is twice the
size of the largest overlay. This is adequate
for some applications.
However, consider the case of a particular
function of a program that is implemented
through many modules (each of which is
overlaid).
If the total size of those modules is larger
than the overlay buffer, a substantial amount
of swapping will occur if the modules make
frequent calls to each other.
The solution is to increase the size of the
overlay buffer so that enough memory is
available at any given time to contain all
overlays that make frequent calls to each
other.
You can do this by setting _ovrbuffer to the
required size in paragraphs.
For example, to set the overlay buffer to
128K, include the following statement in your
code:
unsigned _ovrbuffer = 0x2000;
There is no general formula for determining
the ideal overlay buffer size. Borland's
Turbo Profiler can help provide a suitable
value.
See Also:
_OvrInitEms
_OvrInitExt
_psp <DOS.H, PROCESS.H, STDLIB.H>
======
Segment address of the program's Program
Segment Prefix.
Declaration: extern unsigned int _psp;
See Also:
List of all global variables
_stklen <DOS.H>
=========
Stack length variable
Declaration: extern unsigned _stklen;
_stklen specifies the size of the stack for
all six memory models. _stklen is used before
main() is called.
The minimum stack size allowed is 128 words;
if you give a smaller value, _stklen is
automatically adjusted to the minimum.
The default stack size is 4K.
To set a different stack size, you must
declare _stklen in your source file as a
global variable. (Place it outside all
functions.)
See Also:
List of all global variables
Example:
#include <stdio.h>
/* Set the stack size to be greater than the default. */
/* This declaration must go in the global data area. */
extern unsigned _stklen = 543210U;
int main(void)
{ /* Show the current stack length */
printf("The stack length is %u\n", _stklen);
return 0;
}
_osmajor, _osminor, _version <DOS.H>
==============================
The version of DOS that the program is currently running under
Declaration:
* extern unsigned char _osmajor /* major version # */
* extern unsigned char _osminor /* minor version # */
* extern unsigned int _version /* full version # */
_osmajor and _osminor can be useful when you
want to write modules that will run on DOS
versions 2.x and 3.x.
Some BC++ library routines behave differently
depending on the DOS version number, while
others only work under DOS 3.x.
_version contains the major version number in
the low byte and the minor version number in
the high byte.
See Also:
List of all global variables
======================
absread and abswrite <DOS.H>
======================
* absread reads absolute disk sectors
* abswrite writes absolute disk sectors
Declaration:
* int absread(int drive, int nsects, long lsect, void *buffer);
* int abswrite(int drive, int nsects, long lsect, void *buffer);
Remarks:
* absread uses DOS interrupt 0x25 to read specific disk sectors.
* abswrite uses DOS interrupt 0x26 to write specific disk sectors.
Both functions ignore the logical structure
of a disk and pay no attention to files,
FATs, or directories.
If used improperly, abswrite can overwrite
files, directories, and FATs.
Param. | What It Is/Does
--------+----------------------------------------------------------
drive | Drive number to read (or write): 0 = A, 1 = B, etc.
nsects | Number of sectors to read (or write)
lsect | Beginning logical sector number
buffer | Memory address where the data is to be read (or written)
The number of sectors to read (or write) is
limited to 64K or the size of the buffer,
whichever is smaller.
Return Value:
* On success, both return 0.
* On error, both return -1 and set errno to the value of the AX register
returned by the system call.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
biosdisk
Example (absread only):
/* absread example */
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <dos.h>
int main(void)
{
int i, strt, ch_out, sector;
char buf[512];
printf("Insert a diskette into drive A and press any key\n");
getch();
sector = 0;
if (absread(0, 1, sector, &buf) != 0)
{
perror("Disk problem");
exit(1);
}
printf("Read OK\n");
strt = 3;
for (i=0; i<80; i++)
{
ch_out = buf[strt+i];
putchar(ch_out);
}
printf("\n");
return(0);
}
=========================
allocmem, _dos_allocmem <DOS.H>
=========================
Allocates DOS memory segment
Declaration:
* int allocmem(unsigned size, unsigned *segp);
* unsigned _dos_allocmem(unsigned size, unsigned *segp);
Remarks:
allocmem and _dos_allocmem use the DOS system
call 0x48 to allocate a block of free memory
and return the segment address of the
allocated block.
Arg. | What It Is
------+-----------------------------------------------
size | The number of 16-byte paragraphs requested
segp | Pointer to a word that will be assigned the
| segment address of the newly allocated block
If not enough room is available,
* allocmem makes no assignment to the word *segp
* _dos_allocmem stores the size of the largest
available block in the word *segp.
All allocated blocks are paragraph-aligned.
* NOTE: malloc can't coexist with either
allocmem or _dos_allocmem.
Return Value:
* On success,
* allocmem returns -1
* _dos_allocmem returns 0
* On error,
* allocmem returns the size of the largest available block and
sets both _doserrno and errno to ENOMEM (Not enough memory)
* _dos_allocmem returns the DOS error code and sets errno to ENOMEM
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
coreleft
_dos_freemem
_dos_setblock
freemem
malloc
setblock
Examples:
allocmem example
_dos_allocmem example
allocmem example
==================
#include <dos.h>
#include <alloc.h>
#include <stdio.h>
int main(void)
{
unsigned int size, segp;
int stat;
size = 64; /* (64 x 16) = 1024 bytes */
stat = allocmem(size, &segp);
if (stat == -1)
printf("Allocated memory at segment: %x\n", segp);
else
printf("Failed: maximum number of paragraphs available is %u\n", stat);
return 0;
}
_dos_allocmem example
=======================
#include <dos.h>
#include <stdio.h>
int main(void)
{
unsigned int size, segp, err, maxb;
size = 64; /* (64 x 16) = 1024 bytes */
err = _dos_allocmem(size, &segp);
if (err == 0)
printf("Allocated memory at segment: %x\n", segp);
else {
perror("Unable to allocate block");
printf("Maximum no. of paragraphs available is %u\n", segp);
return 1;
}
if (_dos_setblock(size * 2, segp, &maxb) == 0)
printf("Expanded memory block at segment: %X\n", segp);
else {
perror("Unable to expand block");
printf("Maximum no. of paragraphs available is %u\n", maxb);
}
_dos_freemem(segp);
return 0;
}
======
bdos <DOS.H>
======
Accesses DOS system calls
Declaration: int bdos(int dosfun, unsigned dosdx, unsigned dosal);
Remarks:
bdos provides direct access to many of the
DOS system calls.
See your DOS reference manuals for details on
each system call.
* Use bdos for system calls that require an integer argument.
* Use bdosptr if system calls require a pointer argument; this is
important in the large data models (compact, large, and huge).
Param. | What It Is/Does
--------+----------------------------------------
dosfun | Defined in your DOS reference manuals
dosdx | Value of register DX
dosal | Value of register AL
Return Value:
Returns the value of AX set by the system call.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
bdosptr
geninterrupt
int86
int86x
intdos
intdosx
Example:
#include <stdio.h>
#include <dos.h>
/* Get current drive as 'A', 'B', ... */
char current_drive(void)
{
char curdrive;
/* Get current disk as 0, 1, ... */
curdrive = bdos(0x19, 0, 0);
return('A' + curdrive);
}
int main(void)
{
printf("The current drive is %c:\n", current_drive());
return 0;
}
=========
bdosptr <DOS.H>
=========
MS-DOS system call
Declaration: int bdosptr(int dosfun, void *argument, unsigned dosal);
Remarks:
bdosptr provides direct access to many of the
DOS system calls.
See your DOS reference manuals for details of
each system call.
* Use bdos for system calls that require an integer argument.
* Use bdosptr if system calls require a pointer argument; this is
important in the large data models (compact, large, and huge).
Parameter| What It Is/Does
----------+----------------------------------------
dosfun | Defined in your DOS reference manuals
argument | In small data models, specifies DX
| In large data models, gives the DS:DX
| values to be used by the system call
dosal | Value of register AL
Return Value:
* On success, returns the value of AX
* On error, returns -1 and sets errno and _doserrno.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
bdos
geninterrupt
int86
int86x
intdos
intdosx
Example:
#include <string.h>
#include <stdio.h>
#include <dir.h>
#include <dos.h>
#include <errno.h>
#include <stdlib.h>
#define BUFLEN 80
int main(void)
{
char buffer[BUFLEN];
int test;
printf("Enter full pathname of a directory\n");
gets(buffer);
test = bdosptr(0x3B,buffer,0);
if(test)
{
printf("DOS error message: %d\n", errno);
/* See errno.h for error listings */
exit (1);
}
getcwd(buffer, BUFLEN);
printf("The current directory is: %s\n", buffer);
return 0;
}
=============
_chain_intr <DOS.H>
=============
Chains to another interrupt handler
Declaration: void _chain_intr(void (interrupt far *newhandler)());
Remarks:
_chain_intr passes control from the currently
executing interrupt handler to a new
interrupt handler.
Argument | What It Is
------------+----------------------------------
newhandler | Address of new interrupt handler
The current register set is NOT passed to the
new handler. Instead, the new handler
receives the registers that were stacked (and
possibly modified in the stack) by the old
handler.
The new handler can simply return, as if it
were the original handler. The old handler
is not entered again.
_chain_intr can be called only by C interrupt
functions. It is useful when writing a TSR
that needs to insert itself in a chain of
interrupt handlers (such as the keyboard
interrupt).
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
_dos_getvect
_dos_setvect
_dos_keep
Example:
#include <dos.h>
#include <stdio.h>
#include <process.h>
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
typedef void interrupt (*fptr)(__CPPARGS);
static void mesg(char *s)
{
while (*s)
bdos(2,*s++,0);
}
#pragma argsused
void interrupt handler2(unsigned bp, unsigned di)
{
_enable();
mesg("In handler 2.\r\n");
if (di == 1)
mesg("DI is 1\r\n");
else
mesg("DI is not 1\r\n");
di++;
}
#pragma argsused
void interrupt handler1(unsigned bp, unsigned di)
{
_enable();
mesg("In handler 1.\r\n");
if (di == 0)
mesg("DI is 0\r\n");
else
mesg("DI is not 0\r\n");
di++;
mesg("Chaining to handler 2.\r\n");
_chain_intr((fptr) handler2);
}
int main()
{
_dos_setvect(128,(fptr) handler1);
printf("About to generate interrupt 128\n");
_DI = 0;
geninterrupt(128);
printf("DI was 0 before interrupt, is now 0x%x\n",_DI);
return 0;
}
=========
country <DOS.H>
=========
Returns country-dependent information
Declaration: struct COUNTRY *country(int xcode, struct country *cp);
Remarks:
country specifies how to format certain
country-dependent data (such as dates,
times, and currency).
The values set by this function depend on the
DOS version being used.
Arg. | What It Is/Does
-------+----------------------------------------------------------------
cp | Points to a COUNTRY structure to be filled with the country-
| dependent information of
| * the current country (if xcode = 0), or
| * the country given by xcode
| If cp = -1, the current country is set to the value of xcode,
| which must be non-zero.
xcode | Specifies the country whose information will fill the
| structure *cp (if cp <= 0)
Return Value:
* On success, returns the pointer argument cp.
* On error, returns null.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
Example:
#include <dos.h>
#include <stdio.h>
#define USA 0
int main(void)
{
struct COUNTRY country_info;
country(USA, &country_info);
printf("The currency symbol for the USA is: %s\n",
country_info.co_curr);
return 0;
}
=========
ctrlbrk <DOS.H>
=========
Sets control-break handler
Declaration: void ctrlbrk(int (*handler)(void));
Remarks:
ctrlbrk sets a new control-break handler
function *handler.
The interrupt vector 0x23 is modified to call
the named function.
ctrlbrk establishes a DOS interrupt handler
that calls the handler function. The handler
function is not called directly.
The handler function can perform any number
of operations and system calls.
The handler does not have to return. It can
use longjmp to return to an arbitrary point
in the program.
The handler function returns 0 to abort the
current program. Any other value causes the
program to resume execution.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
getcbrk
signal
Example:
#include <stdio.h>
#include <dos.h>
#define ABORT 0
int c_break(void)
{
printf("Control-Break pressed. Program aborting ...\n");
return (ABORT);
}
void main(void)
{
ctrlbrk(c_break);
for(;;)
{
printf("Looping... Press <Ctrl-Break> to quit:\n");
}
}
=======
delay <DOS.H>
=======
Suspends execution for interval (milliseconds)
Declaration: void delay(unsigned milliseconds);
Remarks:
With a call to delay, the current program is
suspended from execution for the time
specified by the argument milliseconds.
It is not necessary to make a calibration
call to delay before using it.
delay is accurate to one millisecond.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
nosound
sleep
sound
Example:
/* Emits a 440-Hz tone for 500 milliseconds */
#include <dos.h>
int main(void)
{
sound(440);
delay(500);
nosound();
return 0;
}
=====================
disable, _disable <DOS.H>
enable, and _enable
=====================
Macros that disable and enable interrupts
Declaration:
* void disable(void);
* void _disable(void);
* void enable(void);
* void _enable(void);
Remarks:
These macros provide programmers with
flexible hardware interrupt control.
* disable and _disable disable interrupts.
* enable and _enable enable interrupts,
allowing any device interrupts to occur.
Only the NMI (non-maskable interrupt) is
allowed from any external device.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
_dos_getvect
_dos_setvect
getvect
Examples:
disable example
_disable example
enable example
_enable example
disable example
=================
/* NOTE: This is an interrupt service
routine. You cannot compile this program
with Test Stack Overflow turned on and
get an executable file that operates
correctly. */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define INTR 0X1C /* The clock tick
interrupt */
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt (*oldhandler)(__CPPARGS);
int count=0;
void interrupt handler(__CPPARGS) /* if C++, need the the ellipsis */
{
/* disable interrupts during the handling of the interrupt */
disable();
/* increase the global counter */
count++;
/* reenable interrupts at the end of the handler */
enable();
/* call the old routine */
oldhandler();
}
int main(void)
{
/* save the old interrupt vector */
oldhandler = getvect(INTR);
/* install the new interrupt handler */
setvect(INTR, handler);
/* loop until the counter exceeds 20 */
while (count < 20)
printf("count is %d\n",count);
/* reset the old interrupt handler */
setvect(INTR, oldhandler);
return 0;
}
_disable example
==================
/* NOTE: This is an interrupt service
routine. You cannot compile this program
with Test Stack Overflow turned on and
get an executable file that operates
correctly. */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define INTR 0X1C /* The clock tick
interrupt */
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt (*oldhandler)(__CPPARGS);
int count=0;
void interrupt handler(__CPPARGS) /* if C++, need the the ellipsis */
{
/* disable interrupts during the handling of the interrupt */
_disable();
/* increase the global counter */
count++;
/* reenable interrupts at the end of the handler */
enable();
/* call the old routine */
oldhandler();
}
int main(void)
{
/* save the old interrupt vector */
oldhandler = _dos_getvect(INTR);
/* install the new interrupt handler */
_dos_setvect(INTR, handler);
/* loop until the counter exceeds 20 */
while (count < 20)
printf("count is %d\n",count);
/* reset the old interrupt handler */
_dos_setvect(INTR, oldhandler);
return 0;
}
enable example
================
/* NOTE: This is an interrupt service
routine. You cannot compile this program
with Test Stack Overflow turned on and
get an executable file that operates
correctly. */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define INTR 0X1C /* The clock tick
interrupt */
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt (*oldhandler)(__CPPARGS);
int count=0;
void interrupt handler(__CPPARGS) /* if C++, need the the ellipsis */
{
/* disable interrupts during the handling of the interrupt */
disable();
/* increase the global counter */
count++;
/* reenable interrupts at the end of the handler */
enable();
/* call the old routine */
oldhandler();
}
int main(void)
{
/* save the old interrupt vector */
oldhandler = getvect(INTR);
/* install the new interrupt handler */
setvect(INTR, handler);
/* loop until the counter exceeds 20 */
while (count < 20)
printf("count is %d\n",count);
/* reset the old interrupt handler */
setvect(INTR, oldhandler);
return 0;
}
_enable example
=================
/* NOTE: This is an interrupt service
routine. You cannot compile this program
with Test Stack Overflow turned on and
get an executable file that operates
correctly. */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define INTR 0X1C /* The clock tick
interrupt */
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt (*oldhandler)(__CPPARGS);
int count=0;
void interrupt handler(__CPPARGS) /* if C++, need the the ellipsis */
{
/* disable interrupts during the handling of the interrupt */
disable();
/* increase the global counter */
count++;
/* reenable interrupts at the end of the handler */
_enable();
/* call the old routine */
oldhandler();
}
int main(void)
{
/* save the old interrupt vector */
oldhandler = _dos_getvect(INTR);
/* install the new interrupt handler */
_dos_setvect(INTR, handler);
/* loop until the counter exceeds 20 */
while (count < 20)
printf("count is %d\n",count);
/* reset the old interrupt handler */
_dos_setvect(INTR, oldhandler);
return 0;
}
===========
dosexterr <DOS.H>
===========
Gets DOS extended error information
Declaration: int dosexterr(struct DOSERROR *eblkp);
Remarks:
This function fills in the DOSERROR structure
*eblkp with extended error information after
a DOS call has failed.
The values in this structure are obtained by
DOS call 0x59.
Return Value:
Returns the value de_exterror.
NOTE: If de_exterror = 0, the prior DOS call
did not result in an error.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
Example:
#include <stdio.h>
#include <dos.h>
int main(void)
{
FILE *fp;
struct DOSERROR info;
fp = fopen("perror.dat","r");
if (!fp) perror("Unable to open file for reading");
dosexterr(&info);
printf("Extended DOS error information:\n");
printf(" Extended error: %d\n",info.de_exterror);
printf(" Class: %x\n",info.de_class);
printf(" Action: %x\n",info.de_action);
printf(" Error Locus: %x\n",info.de_locus);
return 0;
}
===========
dostounix <DOS.H>
===========
Converts date and time to UNIX time
Declaration: long dostounix(struct date *d, struct dostime *t);
Remarks:
dostounix converts a date and time (as
returned from getdate and gettime) into
UNIX time format.
Arg| What It Does
---+-----------------------------------------
d | Points to a date structure
t | Points to a dostime structure containing
| valid DOS date and time information
Return Value:
* The UNIX version of the date and time parameters (number of seconds
since 00:00:00 on January 1, 1970 (GMT)).
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
unixtodos
Example:
#include <time.h>
#include <stddef.h>
#include <dos.h>
#include <stdio.h>
int main(void)
{
time_t t;
struct time d_time;
struct date d_date;
struct tm *local;
getdate(&d_date);
gettime(&d_time);
t = dostounix(&d_date, &d_time);
local = localtime(&t);
printf("Time and Date: %s\n", asctime(local));
return 0;
}
==========
__emit__ <DOS.H>
==========
Inserts literal values directly into code
Declaration: void __emit__(argument, ...);
Remarks:
__emit__ is an inline function you use to
insert literal values directly into object
code as the code is compiling.
You use it to generate machine language
instructions without using inline assembly
language or an assembler.
Generally the arguments of an __emit__ call
are single-byte machine instructions.
However, you can construct more complex
instructions, complete with references to C
variables.
+------------------------------------------+
| NOTE |
|------------------------------------------|
| You should only use this function if you |
| are familiar with the machine language |
| of the 80x86 processor family. |
| |
| You can use this function to place |
| arbitrary bytes in the instruction code |
| of a function. If any of these bytes are |
| incorrect, the program misbehaves and |
| can easily crash your machine. |
| |
| Borland C++ does not attempt to analyze |
| your calls for correctness in any way. |
| If you encode instructions that change |
| machine registers or memory, Borland C++ |
| will not be aware of it and might not |
| properly preserve registers. |
| |
| You are completely on your own with this |
| function. |
+------------------------------------------+
You must pass at least one argument to
__emit__ (any number can be given). The
arguments to __emit__ are not treated like
any other function call arguments in the
language.
An argument passed to __emit__ will not be
converted in any way.
There are special restrictions on the form of
the arguments to __emit__:
* They must be in the form of expressions
that can be used to initialize a static
object.
This means that you can use floating-point
and integer constants and the addresses of
static objects.
* The values of such expressions are written
to the object code at the point of the call,
exactly as if they were being used to
initialize data.
* You can also use the address of a parameter
or auto variable, plus or minus a constant
offset. For these arguments, the offset of the
variable from BP is stored.
The number of bytes placed in the object code
is determined from the type of the argument,
except in the following cases:
* If a signed integer constant (i.e. 0x90) appears that fits within the
range 0--255, it is treated as if it were a character.
* If you use the address of an auto or parameter variable, __emit__ writes
a byte if the offset of the variable from BP is between -128 and 127.
Otherwise, __emit__ writes a word.
Writing Simple Bytes
====================
Simple bytes are written as follows:
__emit__(0x90);
Writing Words
=============
To write a word when you're passing a value
under 255, cast it to unsigned as follows:
__emit__(0xB8, (unsigned)17);
or
__emit__(0xB8, 17u);
Writing Address Values
======================
Two- or four-byte address values can be
forced by casting an address to void near *
or void far *, respectively.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
Example:
#include <dos.h>
int main(void)
{
/* Emit code that will generate a print screen via int 5 */
__emit__(0xcd,0x05);
return 0;
}
================================
_dos_findfirst, _dos_findnext, <DOS.H>
findfirst, and findnext <DIR.H>
================================
* _dos_findfirst and findfirst search a disk directory for files
* _dos_findnext and findnext continue the search
Declaration:
* unsigned _dos_findfirst(const char *pathname, int attrib,
struct find_t *ffblk);
* unsigned _dos_findnext(struct find_t *ffblk);
* int findfirst(const char *pathname, struct ffblk *ffblk, int attrib);
* int findnext(struct ffblk *ffblk);
Remarks:
_dos_findfirst and findfirst use the DOS
system call 0x4E to begin a search of a disk
directory.
_dos_findnext and findnext find subsequent
files that match the pathname argument of
_dos_findfirst and findfirst.
Argument | Function | What Argument Is/Does
----------+-----------------+----------------------------------------------
pathname | _dos_findfirst, | String with an optional drive specifier,
| findfirst | path, and file name of the file to be found.
| | The file name portion can contain wildcard
| | match characters (? and *).
----------+-----------------+----------------------------------------------
ffblk | findfirst, | Points to ffblk structure that is filled
| findnext | with the file-directory information if
| | findfirst or findnext finds a file that
| | matches pathname.
| |
ffblk | _dos_findfirst, | Points to find_t structure that is filled
| _dos_findnext | with the file-directory information if
| | _dos_findfirst or _dos_findnext finds a file
| | that matches pathname.
----------+-----------------+----------------------------------------------
attrib | _dos_findfirst, | DOS file-attribute byte (defined in DOS.H)
| findfirst | used to select eligible files for the search
For each call to _dos_findnext or findnext,
one file name will be returned until no more
files are found in the directory specified in
pathname.
Return Value:
* On success, (a match was found) these functions return 0
* On error (no more files can be found, or there is some error in the
file name),
* _dos_findfirst and _dos_findnext return the DOS error code and set
errno to ENOENT (Path or file name not found)
* findfirst and findnext return -1 and set errno to either ENOENT or
EMFILE (No more files)
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
All are unique to DOS.
Examples:
_dos_findfirst and _dos_findnext example
findfirst and findnext example
_dos_findnext example
=======================
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct find_t ffblk;
int done;
printf("Directory listing of *.*\n");
done = _dos_findfirst("*.*",_A_NORMAL,&ffblk);
while (!done) {
printf(" %s\n", ffblk.name);
done = _dos_findnext(&ffblk);
}
return 0;
}
/* Program output
Directory listing of *.*
FINDFRST.C
FINDFRST.OBJ
FINDFRST.MAP
FINDFRST.EXE */
findnext example
==================
/* findfirst and findnext example */
#include <stdio.h>
#include <dir.h>
int main(void)
{
struct ffblk ffblk;
int done;
printf("Directory listing of *.*\n");
done = findfirst("*.*",&ffblk,0);
while (!done)
{
printf(" %s\n", ffblk.ff_name);
done = findnext(&ffblk);
}
return 0;
}
==================================
FP_OFF, FP_SEG, and MK_FP macros <DOS.H>
==================================
* FP_OFF gets a far address offset
* FP_SEG gets a far address segment
* MK_FP makes a far pointer
Declaration:
* unsigned FP_OFF(void far *p);
* unsigned FP_SEG(void far *p);
* void far *MK_FP(unsigned seg, unsigned ofs);
Remarks:
FP_OFF is a macro that can get or set the
offset of the far pointer *p.
FP_SEG is a macro that gets or sets the
segment value of the far pointer *p.
MK_FP is a macro that makes a far pointer
from its component segment (seg) and offset
(ofs) parts.
Return Value:
* FP_OFF returns an unsigned integer value representing an offset value.
* FP_SEG returns an unsigned integer representing a segment value.
* MK_FP returns a far pointer.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
movedata
segread
Example (for all three macros):
#include <dos.h>
#include <stdio.h>
#include <graphics.h>
/* FP_OFF */
int fp_off(void)
{
char *str = "fpoff.c";
printf("The offset of this file name in memory\
is: %Fp\n", FP_OFF(str));
return 0;
}
/* FP_SEG */
int fp_seg(void)
{
char *filename = "fpseg.c";
printf("The segment of this file in memory\
is: %Fp\n", FP_SEG(filename));
return(0);
/* MK_FP */
int main(void)
{
int gd, gm, i;
unsigned int far *screen;
detectgraph(&gd, &gm);
if (gd == HERCMONO)
screen = (unsigned int *) MK_FP(0xB000, 0);
else
screen = (unsigned int *) MK_FP(0xB800, 0);
for (i=0; i<26; i++)
screen[i] = 0x0700 + ('a' + i);
return 0;
}
==========================
_dos_freemem and freemem <DOS.H>
==========================
Frees a previously allocated DOS memory block
Declaration:
* unsigned _dos_freemem(unsigned segx);
* int freemem(unsigned segx);
Remarks:
* freemem frees a memory block allocated by a previous call to allocmem.
* _dos_freemem frees a memory block allocated by a previous call to
_dos_allocmem.
segx is the segment address of the block.
Return Value:
* On success, both functions return 0
* On error,
* _dos_freemem returns the DOS error code and sets errno to
ENOMEM (Bad memory pointer)
* freemem returns -1 and sets errno to
ENOMEM (Insufficient memory)
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
allocmem
free
Examples:
_dos_freemem example
freemem example
_dos_freemem example
======================
#include <dos.h>
#include <stdio.h>
int main(void)
{
unsigned int size, segp, err, maxb;
size = 64; /* (64 x 16) = 1024 bytes */
err = _dos_allocmem(size, &segp);
if (err == 0)
printf("Allocated memory at segment: %x\n", segp);
else {
perror("Unable to allocate block");
printf("Maximum no. of paragraphs available is %u\n", segp);
return 1;
}
if (_dos_setblock(size * 2, segp, &maxb) == 0)
printf("Expanded memory block at segment: %X\n", segp);
else {
perror("Unable to expand block");
printf("Maximum no. of paragraphs available is %u\n", maxb);
}
_dos_freemem(segp);
return 0;
}
freemem example
=================
#include <dos.h>
#include <alloc.h>
#include <stdio.h>
int main(void)
{
unsigned int size, segp;
int stat;
size = 64; /* (64 x 16) = 1024 bytes */
stat = allocmem(size, &segp);
if (stat < 0)
printf("Allocated memory at segment: %x\n", segp);
else
printf("Failed: maximum number of\
paragraphs available is %u\n", stat);
freemem(segp);
return 0;
}
==============
geninterrupt <DOS.H>
==============
Macro that generates a software interrupt
Declaration: void geninterrupt(int intr_num);
Remarks:
The geninterrupt macro triggers a software
trap for the interrupt given by intr_num.
The state of all registers after the call
depends on the interrupt called.
NOTE: Interrupts can leave registers used by
C in unpredictable states.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
bdos
bdosptr
disable
enable
getvect
int86
int86x
intdos
intdosx
intr
Example:
#include <conio.h>
#include <dos.h>
/* function prototype */
void writechar(char ch);
int main(void)
{
clrscr();
gotoxy(80,25);
writechar('*');
getch();
return 0;
}
/*
outputs a character at the current cursor
position using the video BIOS to avoid
the scrolling of the screen when writing
to location (80,25).
*/
void writechar(char ch)
{
struct text_info ti;
/* grab current text settings */
gettextinfo(&ti);
/* interrupt 0x10 sub-function 9 */
_AH = 9;
/* character to be output */
_AL = ch;
_BH = 0; /* video page */
_BL = ti.attribute; /* video attribute */
_CX = 1; /* repetition factor */
geninterrupt(0x10); /* output the char */
}
==================
getcbrk, setcbrk <DOS.H>
==================
* getcbrk gets current setting for control-break checking
* setcbrk sets control-break checking
Declaration:
* int getcbrk(void);
* int setcbrk(int cbrkvalue);
Remarks:
Both getcbrk and setcbrk use DOS system call
0x33:
* getcbrk uses it to return the current
setting of control-break checking
* setcbrk uses it to turn control-break
checking on or off
If cbrkvalue = 0, setcbrk turns checking off.
(It checks only during I/O to console,
printer, or communications devices.)
If cbrkvalue = 1, setcbrk turns checking on.
(It checks at every system call.)
Return Value:
* getcbrk returns
0 if control-break checking is off
1 if checking is on.
* setcbrk returns cbrkvalue, the value
passed.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
ctrlbrk
Example (for both functions):
#include <dos.h>
#include <conio.h>
#include <stdio.h>
int main(void)
{
int break_flag;
printf("Enter 0 to turn control break off\n");
printf("Enter 1 to turn control break on\n");
break_flag = getch() - 0;
setcbrk(break_flag);
if (getcbrk())
printf("Cntrl-brk flag is on\n");
else
printf("Cntrl-brk flag is off\n");
return 0;
}
=============================
_dos_getdate, _dos_setdate,
getdate, and setdate <DOS.H>
=============================
Gets or sets DOS system date
Declaration:
* void _dos_getdate(struct dosdate_t *datep);
* void _dos_setdate(struct dosdate_t *datep);
* void getdate(struct date *datep);
* void setdate(struct date *datep);
Remarks:
* _dos_getdate fills in the dosdate_t
structure *datep with the system's current
date.
* _dos_setdate sets the system date to the
date in *datep.
* getdate fills in the date structure *datep
with the system's current date.
* setdate sets the system date to the date in
*datep.
Return Value:
* _dos_getdate, _dos_setdate, getdate: None
* _dos_setdate:
* On success, returns 0
* Otherwise, returns a non-zero value and
sets errno to EINVAL (Invalid date)
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
ctime
gettime
settime
Examples:
_dos_getdate example
_dos_setdate example
getdate example
setdate example
_dos_getdate example
======================
#include <dos.h>
#include <stdio.h>
int main(void)
{
struct dosdate_t d;
_dos_getdate(&d);
printf("The current year is: %d\n", d.year);
printf("The current day is: %d\n", d.day);
printf("The current month is: %d\n", d.month);
return 0;
}
_dos_setdate example
======================
#include <dos.h>
#include <process.h>
#include <stdio.h>
int main(void)
{
struct dosdate_t reset;
reset.year = 2001;
reset.day = 1;
reset.month = 1;
printf("Setting date to 1/1/2001.\n");
_dos_setdate(&reset);
system("date");
return 0;
}
getdate example
=================
#include <dos.h>
#include <stdio.h>
int main(void)
{
struct date d;
getdate(&d);
printf("The current year is: %d\n", d.da_year);
printf("The current day is: %d\n", d.da_day);
printf("The current month is: %d\n", d.da_mon);
return 0;
}
setdate example
=================
#include <stdio.h>
#include <process.h>
#include <dos.h>
int main(void)
{
struct date reset;
struct date save_date;
getdate(&save_date);
printf("Original date:\n");
system("date");
reset.da_year = 2001;
reset.da_day = 1;
reset.da_mon = 1;
setdate(&reset);
printf("Date after setting:\n");
system("date");
setdate(&save_date);
printf("Back to original date:\n");
system("date");
return 0;
}
===============================
_dos_getdiskfree and getdfree <DOS.H>
===============================
Get disk free space
Declaration:
* unsigned _dos_getdiskfree(unsigned char drive,
struct diskfree_t *dtable);
* void getdfree(unsigned char drive,
struct dfree *dtable);
Remarks:
getdfree accepts a drive specifier in drive
and fills the dfree structure *dtable with
disk characteristics.
_dos_getdiskfree accepts a drive specifier in
drive and fills in the diskfree_t structure
*dtable with disk characteristics.
drive specifies a drive number (0 = default,
1 = A, 2 = B, etc.).
Return Value
* On success,
* _dos_getdiskfree returns 0
* getdfree does not return
* On error,
* _dos_getdiskfree returns a non-zero value and sets errno to
EINVAL (Invalid drive specified)
* getdfree sets df_sclus in the dfree structure to 0xFFFF
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
Examples:
_dos_getdiskfree example
getdfree example
See Also:
getfat/getfatd
_dos_getdiskfree example
==========================
#include <stdio.h>
#include <dos.h>
#include <process.h>
int main(void)
{
struct diskfree_t free;
long avail;
if (_dos_getdiskfree(0, &free) != 0) {
printf("Error in _dos_getdiskfree() call\n");
exit(1);
}
avail = (long) free.avail_clusters
* (long) free.bytes_per_sector
* (long) free.sectors_per_cluster;
printf("The current drive has %ld bytes available\n", avail);
return 0;
}
getdfree example
==================
#include <stdio.h>
#include <stdlib.h>
#include <dir.h>
#include <dos.h>
int main(void)
{
struct dfree free;
long avail;
int drive;
drive = getdisk();
getdfree(drive+1, &free);
if (free.df_sclus == 0xFFFF)
{
printf("Error in getdfree() call\n");
exit(1);
}
avail = (long) free.df_avail
* (long) free.df_bsec
* (long) free.df_sclus;
printf("Drive %c: has %ld bytes available\n", 'A' + drive, avail);
return 0;
}
================
getdta, setdta <DOS.H>
================
* getdta gets disk-transfer address
* setdta sets disk-transfer address
Declaration:
* char far *getdta(void);
* void setdta(char far *dta);
Remarks:
getdta returns the current setting of the
disk transfer address (DTA).
setdta changes the current setting of the DTA
to the value given by dta.
In the small and medium memory models
=====================================
getdta assumes the segment is the current
data segment. If you use C exclusively, this
will be the case; however, assembly routines
can set the DTA to any hardware address.
In the compact, large, or huge memory models
============================================
The address returned by getdta is the correct
hardware address and can be located outside
the program.
Return Value:
* getdta returns a far pointer to the current DTA
* setdta does not return
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
fcb (structure)
Examples:
getdta example
setdta example
getdta example
================
#include <dos.h>
#include <stdio.h>
int main(void)
{
char far *dta;
dta = getdta();
printf("The current disk transfer address is: %Fp\n", dta);
return 0;
}
setdta example
================
#include <process.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>
int main(void)
{
char line[80], far *save_dta;
char buffer[256] = "SETDTA test!";
struct fcb blk;
int result;
/* get new file name from user */
printf("Enter a file name to create:");
gets(line);
/* parse the new file name to the dta */
parsfnm(line, &blk, 1);
printf("%d %s\n", blk.fcb_drive, blk.fcb_name);
/* request DOS services to create file */
if (bdosptr(0x16, &blk, 0) == -1)
{
perror("Error creating file");
exit(1);
}
/* save old dta and set new dta */
save_dta = getdta();
setdta(buffer);
/* write new records */
blk.fcb_recsize = 256;
blk.fcb_random = 0L;
result = randbwr(&blk, 1);
printf("result = %d\n", result);
if (!result)
printf("Write OK\n");
else
{
perror("Disk error");
exit(1);
}
/* request DOS services to close the file */
if (bdosptr(0x10, &blk, 0) == -1)
{
perror("Error closing file");
exit(1);
}
/* reset the old dta */
setdta(save_dta);
return 0;
}
====================
getfat and getfatd <DOS.H>
====================
Gets file-allocation table information
Declaration:
* void getfat(unsigned char drive, struct fatinfo *dtable);
* void getfatd(struct fatinfo *dtable);
Remarks:
These functions get information from the FAT
(file allocation table) for a certain drive
and fill in a fatinfo structure with the
information.
Function | Gets FAT information for...
----------+----------------------------------
getfat | The drive specified by drive
getfatd | The default drive
Argument | What Arg. Is/Does
----------+-------------------------------------------------
drive | Specific drive that getfat gets FAT info for
| (0 = default, 1 = A, 2 = B, etc.).
dtable | Points to the fatinfo structure to be filled in
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
getdfree
Examples:
getfat example
getfatd example
getfat example
================
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct fatinfo diskinfo;
int flag = 0;
printf("Please insert disk in drive A\n");
getchar();
getfat(1, &diskinfo);
/* get drive information */
printf("\nDrive A: is ");
switch((unsigned char) diskinfo.fi_fatid)
{
case 0xFD:
printf("360K low density\n");
break;
case 0xF9:
printf("1.2 Meg high density\n");
break;
default:
printf("unformatted\n");
flag = 1;
}
if (!flag)
{
printf(" sectors per cluster %5d\n", diskinfo.fi_sclus);
printf(" number of clusters %5d\n", diskinfo.fi_nclus);
printf(" bytes per sector %5d\n", diskinfo.fi_bysec);
}
return 0;
}
getfatd example
=================
#include <stdio.h>
#include <dos.h>
int main()
{
struct fatinfo diskinfo;
/* get default drive information */
getfatd(&diskinfo);
printf("\nDefault Drive:\n");
printf("sectors per cluster: %5d\n",diskinfo.fi_sclus);
printf("FAT ID byte: %5X\n",diskinfo.fi_fatid & 0xFF);
printf("number of clusters %5d\n",diskinfo.fi_nclus);
printf("bytes per sector %5d\n",diskinfo.fi_bysec);
return 0;
}
==============================
_dos_getftime, _dos_setftime <DOS.H>
getftime, setftime <IO.H>
==============================
Gets or sets file date and time
Declaration:
* unsigned _dos_getftime(int handle, unsigned *datep, unsigned *timep);
* unsigned _dos_setftime(int handle, unsigned date, unsigned time);
* int getftime(int handle, struct ftime *ftimep);
* int setftime(int handle, struct ftime *ftimep);
Remarks:
* getftime and _dos_getftime retrieve the
file date and time.
* setftime and _dos_setftime set the file
date and time.
Argument| What It Is/Does
--------+-----------------------------------------------------------------
handle | Open handle for file whose time and date are retrieved or set
ftimep | Points to ftime structure
| * getftime fills *ftimep with the file's date and time.
| * setftime sets the file's date and time to values in *ftimep
|
datep | Points to location where file's date is stored
timep | Points to location where file's time is stored
|
date | Specifies the file's new date value
time | Specifies the file's new time value
With _dos_getftime and _dos_setftime, the
file must have been previously opened with
_dos_open, _dos_creat, or _dos_creatnew.
Return Value:
* On success, these functions all return 0
* On error,
* getftime and setftime return -1 and
set errno to one of the following:
EINVFNC (Invalid function number)
EBADF (Bad file number)
* _dos_getftime and _dos_setftime return
the DOS error code and set errno to
EBADF.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
fstat
open
stat
utime
Examples:
_dos_getftime example
_dos_setftime example
getftime example
setftime example
getftime example
==================
#include <stdio.h>
#include <io.h>
int main(void)
{
FILE *stream;
struct ftime ft;
if ((stream = fopen("TEST.$$$",
"wt")) == NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
getftime(fileno(stream), &ft);
printf("File time: %u:%u:%u\n",
ft.ft_hour, ft.ft_min,
ft.ft_tsec * 2);
printf("File date: %u/%u/%u\n",
ft.ft_month, ft.ft_day,
ft.ft_year+1980);
fclose(stream);
return 0;
}
setftime example
=================
#include <stdio.h>
#include <process.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
struct ftime filet;
FILE *fp;
if ((fp = fopen("TEST.$$$", "w")) == NULL)
{
perror("Error:");
exit(1);
}
fprintf(fp, "testing...\n");
/* load ftime structure with new time and date */
filet.ft_tsec = 1;
filet.ft_min = 1;
filet.ft_hour = 1;
filet.ft_day = 1;
filet.ft_month = 1;
filet.ft_year = 21;
/* show current directory for time and date */
system("dir TEST.$$$");
/* change the time and date stamp*/
fflush(fp);
setftime(fileno(fp), &filet);
/* close and remove the temporary file */
fclose(fp);
system("dir TEST.$$$");
unlink("TEST.$$$");
return 0;
}
_dos_getftime example
=======================
#include <stdio.h>
#include <dos.h>
int main()
{
FILE *stream;
unsigned date, time;
if ((stream = fopen("TEST.$$$", "w")) == NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
_dos_getftime(fileno(stream), &date, &time);
printf("@$File date: 0x%x\n",date);
printf("@$File time: 0x%x\n",time);
fclose(stream);
return 0;
}
_dos_setftime example
=======================
#include <stdio.h>
#include <dos.h>
int main()
{
FILE *stream;
unsigned date, time;
if ((stream = fopen("TEST.$$$", "w")) == NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
_dos_getftime(fileno(stream), &date, &time);
printf("File year of TEST.$$$: %d\n",((date >> 9) & 0x7f) + 1980);
date = (date & 0x1ff) | (21 << 9);
_dos_setftime(fileno(stream), date, time);
printf("Set file year to 2001.\n");
fclose(stream);
return 0;
}
========
getpsp <DOS.H>
========
Gets the program segment prefix
Declaration: unsigned getpsp(void);
Remarks:
getpsp uses DOS call 0x62 to get the segment
address of the PSP (program segment prefix).
getpsp exists only in DOS 3.x. For versions
of DOS 2.x and 3.x, you can use the global
variable _psp set by the start-up code
instead.
Return Value:
Returns the segment address of the PSP.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
_psp
getenv
Example:
#include <stdio.h>
#include <dos.h>
int main(void)
{
static char command[128];
char far *cp;
int len, i;
printf("The program segment prefix is: %u\n", getpsp());
/*
_psp is preset to segment of the PSP
Command line is located at offset 0x81
from start of PSP
*/
cp = (char *) MK_FP(_psp, 0x80);
len = *cp;
for (i = 0; i < len; i++)
command[i] = cp[i+1];
printf("Command line: %s\n", command);
return 0;
}
============================
_dos_gettime, _dos_settime <DOS.H>
gettime, settime
============================
Get and set system time
Declaration:
* void _dos_gettime(struct dostime_t *timep);
* unsigned _dos_settime(struct dostime_t *timep);
* void gettime(struct time *timep);
* void settime(struct time *timep);
Remarks:
* _dos_gettime fills in a dostime_t structure
with system's current time.
* _dos_settime sets the system time to the
values in a time structure.
* gettime fills in a time structure with the
system's current time.
* settime sets the system time to the values
in a time structure.
Return Value:
* gettime, settime, and _dos_gettime
do not return.
* On success, _dos_settime returns 0
* On error, _dos_settime returns the DOS
error code and sets errno to
EINVAL (Invalid time)
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
ctime
_dos_getdate
_dos_setdate
getdate
setdate
stime
time
Examples:
_dos_gettime example
_dos_settime example
gettime example
settime example
_dos_gettime example
======================
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct dostime_t t;
_dos_gettime(&t);
printf("@$The current time is: %2d:%02d:%02d.%02d\n", t.hour, t.minute,
t.second, t.hsecond);
return 0;
}
_dos_settime example
======================
#include <dos.h>
#include <process.h>
#include <stdio.h>
int main(void)
{
struct dostime_t reset;
reset.hour = 17;
reset.minute = 0;
reset.second = 0;
reset.hsecond = 0;
printf("Setting time to 5 PM.\n");
_dos_settime(&reset);
system("time");
return 0;
}
gettime example
=================
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct time t;
gettime(&t);
printf("The current time is: %2d:%02d:%02d.%02d\n",
t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
return 0;
}
settime example
=================
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct time t;
gettime(&t);
printf("The current minute is: %d\n", t.ti_min);
printf("The current hour is: %d\n", t.ti_hour);
printf("The current hundredth of a second is: %d\n", t.ti_hund);
printf("The current second is: %d\n", t.ti_sec);
/* Add one to the minutes struct element and then call settime */
t.ti_min++;
settime(&t);
return 0;
}
============================
_dos_getvect, _dos_setvect
getvect, and setvect <DOS.H>
============================
Get interrupt vector, set interrupt vector entry
Declaration:
* void interrupt (*getvect(int interruptno))();
* void setvect(int interruptno, void interrupt (*isr) ( ));
* void interrupt(*_dos_getvect(unsigned interruptno)) ();
* void _dos_setvect(unsigned interruptno, void interrupt (*isr) ());
Remarks:
* _dos_getvect and getvect read the value of
the interrupt vector given by interruptno and
return that value as a (far) pointer to an
interrupt function.
* _dos_setvect and setvect set the value of
the interrupt vector named by interruptno to
a new value, isr, which is a (far) pointer
containing the address of a new interrupt
function.
Every processor of the 8086 family includes a
set of interrupt vectors, numbered 0 to 255.
The 4-byte value in each vector is actually
an address, which is the location of an
interrupt function.
Argument | What It Is/Does
-------------+-------------------------------------------------------------
interruptno | Interrupt vector (value = 0 to 255). The value stored in
| the vector is the address of an interrupt function.
isr | Far pointer containing the address of a new interrupt
| function.
The address of a C routine can only be passed
to isr if that routine is declared to be an
interrupt routine.
If you use the prototypes declared in DOS.H,
simply pass the address of an interrupt
function to setvect or _dos_setvect in any
memory model.
Return Value:
* getvect and _dos_getvect return the current 4-byte value stored in the
interrupt vector named by interruptno.
* setvect and _dos_setvect do not return.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
disable/_disable
enable/_enable
geninterrupt
Examples:
_dos_getvect and _dos_setvect example
getvect and setvect example
_dos_getvect and _dos_setvect example
=======================================
#include <stdio.h>
#include <dos.h>
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt get_out(__CPPARGS); /* interrupt prototype */
void interrupt (*oldfunc)(__CPPARGS); /* interrupt function pointer */
int looping = 1;
int main(void)
{
puts("Press <Shift><PrtSc> to terminate");
/* save the old interrupt */
oldfunc = _dos_getvect(5);
/* install interrupt handler */
_dos_setvect(5,get_out);
/* do nothing */
while (looping);
/* restore to original interrupt routine */
_dos_setvect(5,oldfunc);
puts("Success");
return 0;
}
void interrupt get_out(__CPPARGS) {
looping = 0; /* change global var to get out of loop */
}
getvect and setvect example
=============================
/***NOTE:
This is an interrupt service routine. You can NOT compile this
program with Test Stack Overflow turned on and get an executable
file which will operate correctly. */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#define INTR 0X1C /* The clock tick interrupt */
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt ( *oldhandler)(__CPPARGS);
int count=0;
void interrupt handler(__CPPARGS)
{
/* increase the global counter */
count++;
/* call the old routine */
oldhandler();
}
int main(void)
{
/* save the old interrupt vector */
oldhandler = getvect(INTR);
/* install the new interrupt handler */
setvect(INTR, handler);
/* loop until the counter exceeds 20 */
while (count < 20)
printf("count is %d\n",count);
/* reset the old interrupt handler */
setvect(INTR, oldhandler);
return 0;
}
======================
getverify, setverify <DOS.H>
======================
* getverify gets the verify state
* setverify sets the verify state
Declaration:
* int getverify(void);
* void setverify(int value);
Remarks:
* getverify gets the current state of the
verify flag.
* setverify sets the current state of the
verify flag to value.
The verify flag controls output to the disk.
* When it is off, writes are not verified.
* When it is on, disk writes are verified
to ensure the data is written properly.
Return Value:
* getverify returns 0 if the verify flag
is off, 1 if the flag is on
* setverify does not return
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
Example (for both functions):
#include <stdio.h>
#include <conio.h>
#include <dos.h>
int main(void)
{
int verify_flag;
printf("Enter 0 to set verify flag off\n");
printf("Enter 1 to set verify flag on\n");
verify_flag = getch() - 0;
setverify(verify_flag);
if (getverify())
printf("DOS verify flag is on\n");
else
printf("DOS verify flag is off\n");
return 0;
}
===============================
harderr, hardresume, hardretn <DOS.H>
===============================
Hardware error handler routines
Declaration:
* void harderr(int (*handler)());
* void hardresume(int axret);
* void hardretn(int retn);
Remarks:
harderr establishes a hardware error handler
for the current program. This error handler
is invoked whenever an interrupt 0x24 occurs.
(See your DOS reference manuals for a
discussion of interrupt 0x24.)
The error handler established by harderr can
* call hardresume to return to DOS, or
* call hardretn to return directly to the
application program
Argument| Function | What Argument Is/Does
---------+------------+----------------------------------------------------
handler | harderr | Points to a hardware error handler function.
| | This function is not called directly; harderr
| | establishes a DOS interrupt handler that calls it
| | whenever an interrupt 0x24 occurs.
| |
axret | hardresume | Result code: The return value of this code contains
| | one of the following values:
| | ------------------+-------------------------------
| | _HARDERR_ABORT | Abort the program; Invoke DOS
| | | interrupt 0x23 (control-break
| | | interrupt)
| | _HARDERR_IGNORE | Ignore the error
| | _HARDERR_RETRY | Retry the operation
| | _HARDERR_FAIL | Fail the operation. Use this
| | | value only on DOS 3.0 or later
| |
retn | hardretn | Value returned to the user program (in place of
| | the normal value returned from the DOS function
| | that generated the critical error).
Return Value:
These functions do not return.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
peek
poke
Example (for all three functions):
/*
This program will trap disk errors and
prompt the user for action. Try running it
with no disk in drive A: to invoke its
functions.
*/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define IGNORE 0
#define RETRY 1
#define ABORT 2
int buf[500];
/*
define the error messages for trapping disk problems
*/
static char *err_msg[] = {
"write protect",
"unknown unit",
"drive not ready",
"unknown command",
"data error (CRC)",
"bad request",
"seek error",
"unknown media type",
"sector not found",
"printer out of paper",
"write fault",
"read fault",
"general failure",
"reserved",
"reserved",
"invalid disk change"
};
error_win(char *msg)
{
int retval;
cputs(msg);
/*
prompt for user to press a key to abort, retry, ignore
*/
while(1)
{
retval= getch();
if (retval == 'a' || retval == 'A')
{
retval = ABORT;
break;
}
if (retval == 'r' || retval == 'R')
{
retval = RETRY;
break;
}
if (retval == 'i' || retval == 'I')
{
retval = IGNORE;
break;
}
}
return(retval);
}
/*
pragma warn -par reduces warnings which occur
due to the non use of the parameters errval,
bp and si to the handler.
*/
#pragma warn -par
int handler(int errval,int ax,int bp,int si)
{
static char msg[80];
unsigned di;
int drive;
int errorno;
di= _DI;
/*
if this is not a disk error then it was
another device having trouble
*/
if (ax < 0)
{
/* report the error */
error_win("Device error");
/* and return to the program directly requesting abort */
hardretn(ABORT);
}
/* otherwise it was a disk error */
drive = ax & 0x00FF;
errorno = di & 0x00FF;
/* report which error it was */
sprintf(msg, "Error: %s on drive %c\r\nA)bort, R)etry, I)gnore: ",
err_msg[errorno], 'A' + drive);
/*
return to the program via dos interrupt 0x23 with abort, retry,
or ignore as input by the user.
*/
hardresume(error_win(msg));
return ABORT;
}
#pragma warn +par
int main(void)
{
/*
install our handler on the hardware problem interrupt
*/
harderr(handler);
clrscr();
printf("Make sure there is no disk in drive A:\n");
printf("Press any key ....\n");
getch();
printf("Trying to access drive A:\n");
printf("fopen returned %p\n",fopen("A:temp.dat", "w"));
return 0;
}
Hardware error handler function established by harderr
========================================================
The handler function established by harderr
is called with the following arguments:
handler(int errval, int ax, int bp, int si);
Argument| What It Is/Does
--------+-----------------------------------------------------------------
errval | Error code set in the DI register by DOS.
--------+-----------------------------------------------------------------
ax | Value DOS sets for the AX register.
| Indicates whether a disk error or other device error occurred.
| * Disk error: ax is non-negative. ax ANDed with 0x00FF gives
| the failing drive number (0 = A, 1 = B, etc.)
| * Device error: ax is negative.
--------+-----------------------------------------------------------------
| --+ Values set by DOS for the BP and SI
bp | Segment address |- registers. bp and si together point
si | Offset | to the device driver header of the
| --+ failing driver.
The handler function can issue DOS calls 1
through 0xC. Any other DOS call corrupts DOS.
In particular, none of the C standard I/O or
UNIX-emulation I/O calls can be used.
The handler function can call:
* hardresume to return to DOS, or
* hardretn to return directly to the
application program
Return Value:
The handler function must return:
* 0 for ignore
* 1 for retry
* 2 for abort
==================================
_harderr, _hardresume, _hardretn <DOS.H>
==================================
Hardware error handler routines
Declaration:
* void _harderr(int (far *handler)());
* void _hardresume(int rescode);
* void _hardretn(int retn);
Remarks:
_harderr establishes a hardware error handler
for the current program. This error handler
is invoked whenever an interrupt 0x24 occurs.
(See your DOS reference manuals for a
discussion of interrupt 0x24.)
The error handler established by _harderr can
* call _hardresume to return to DOS, or
* call _hardretn to return directly to
the application program
Argument| Function | What Argument Is/Does
---------+------------+----------------------------------------------------
handler | _harderr | Points to a hardware error handler function.
| | This function is not called directly; harderr
| | establishes a DOS interrupt handler that calls
| | it whenever an interrupt 0x24 occurs.
| |
rescode | _hardresume| Result code: The return value of rescode contains
| | one of the following values:
| | ------------------+-------------------------------
| | _HARDERR_ABORT | Abort the program; Invoke DOS
| | | interrupt 0x23 (control-break
| | | interrupt)
| | _HARDERR_IGNORE | Ignore the error
| | _HARDERR_RETRY | Retry the operation
| | _HARDERR_FAIL | Fail the operation. Use this
| | | value only on DOS 3.0 or later
| |
retn | _hardretn | Value returned to the user program (in place of
| | the normal value returned from the DOS function
| | that generated the critical error).
_hardretn
=========
The retn argument of _hardretn is ignored for
all DOS functions less than 0x38.
* If the DOS function that caused the error is less than 0x38, and it is
a function that can indicate an error condition, _hardretn will return
to the application program with the AL register set to 0xFF.
* If the DOS function is greater than or equal to 0x38, the retn argument
should be a DOS error code; it is returned to the application program
in the AX register.
The carry flag is also set to indicate to the
application that the operation resulted in an
error.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
Return Value
* _harderr: None
* _hardresume: Does not return a value, and
does not return to the caller
* _hardretn: Does not return a value, and
does not return to the caller
See Also:
harderr
Example (for all three functions):
/* This program traps disk errors and prompts the user for action. */
/* Try running it with no disk in drive A to invoke its functions. */
#include <stdio.h>
#include <ctype.h>
#include <dos.h>
#include <fcntl.h>
int buf[500];
/* define the error messages for trapping disk problems */
static char *err_msg[] =
{
"write protect", "unknown unit",
"drive not ready", "unknown command",
"data error (CRC)","bad request",
"seek error", "unknown media type",
"sector not found","printer out of paper",
"write fault", "read fault",
"general failure", "reserved",
"reserved", "invalid disk change"
};
static void mesg(char *s)
{
while (*s)
bdos(2,*s++,0);
}
static int getkey(void)
{
return (bdos(7, 0, 0) & 0xff);
}
error_win(char *msg)
{
int c;
/* prompt user to press a key to abort, retry, ignore, fail */
while(1)
{
mesg(msg);
c = tolower(getkey());
mesg("\r\n");
switch (c)
{
case 'a':
return (_HARDERR_ABORT);
case 'r':
return (_HARDERR_RETRY);
case 'i':
return (_HARDERR_IGNORE);
case 'f':
return (_HARDERR_FAIL);
}
}
}
/* pragma warn -par reduces warnings which occur due to the */
/* nonuse of the parameter devhdr */
#pragma warn -par
void far handler(unsigned deverr, unsigned errval, unsigned far *devhdr)
{
static char msg[80];
int drive;
int errorno;
/* if this not disk error then another device having trouble */
if (deverr & 0x8000) {
error_win("Device error"); /* report the error */
/* return to the program directly requesting abort */
_hardretn(5); /* 5 = DOS "access denied" error */
}
drive = deverr & 0x00FF; /* otherwise it was disk error */
errorno = errval & 0x00FF;
/* report which error it was */
sprintf(msg, "Error: %s on drive %c\r\nA)bort, R)etry, I)gnore, F)ail: ",
err_msg[errorno], 'A' + drive);
/* return to program via dos interrupt 0x23 with abort, retry */
/* or ignore as input by the user */
_hardresume(error_win(msg));
}
#pragma warn +par
int main(void)
{
int handle;
/* install our handler on the hardware problem interrupt */
_harderr(handler);
printf("Make sure there is no disk in drive A:\n");
printf("Press any key ....\n");
getkey();
printf("Trying to access drive A:\n");
printf("_dos_open returned 0x%x\n",
_dos_open("A:temp.dat", O_RDONLY, &handle));
return 0;
}
Hardware error handler function established by _harderr
=========================================================
The handler function established by _harderr
is called with the following arguments:
void far handler(unsigned deverr, unsigned errval, unsigned far *devhdr);
Argument| What It Is/Does
--------+-----------------------------------------------------------------
deverr | Device error code passed to the handler by DOS in the AX
| register. Indicates whether a disk error or other device error
| was encountered.
| * Disk error: bit 15 of deverr = 0. deverr ANDed with 0x00FF
| gives the failing drive number (0 = A, 1 = B, etc.)
| * Device error: bit 15 of deverr = 1
|
errval | Error code (passed to the handler by DOS in the DI register)
|
devhdr | Far pointer to the driver header of the device that caused the
| error (passed to the handler by DOS in the BP:SI register pair)
The handler function should use these
arguments instead of referring directly
to the CPU registers.
The handler function can issue DOS calls 1
through 0xC; any other DOS call corrupts DOS.
In particular, none of the C standard I/O or
UNIX-emulation I/O calls can be used.
The handler can
* call _hardresume to return to DOS, or
* call _hardretn to return directly to
the application program
The handler does not return a value, and it
must exit using _hardretn or _hardresume.
====================================
inport, inportb, outport, outportb <DOS.H>
====================================
* inport reads a word from a hardware port
* inportb reads a byte from a hardware port
* outport outputs a word to a hardware port
* outportb outputs a byte to a hardware port
Declaration:
* unsigned inport (unsigned portid);
* unsigned char inportb (unsigned portid);
* void outport (unsigned portid, unsigned value);
* void outportb(unsigned portid, unsigned char value);
Remarks:
* inport works just like the 80x86 instruction IN. It reads the low
byte of a word from portid, the high byte from portid + 2.
* inportb is a macro that reads a byte
* outport works just like the 80x86 instruction OUT. It writes the
low byte of value to portid, the high byte to portid + 1.
* outportb is a macro that writes value
Argument| What It Is
--------+-------------------------------------------------
portid | Inport port that inport and inportb read from;
| outport port that outport and outportb write to
value | Word that outport writes to portid;
| byte that outportb writes to portid.
If you call inportb or outportb when DOS.H
has been included, they are treated as macros
that expand to inline code.
If you don't include DOS.H, or if you do
include DOS.H and #undef the macro(s), you
get the function(s) of the same name.
Return Value:
* inport and inportb return the value read
* outport and outportb do not return
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
inp, inpw
outp, outpw
Examples:
inport example
inportb example
outport example
outportb example
inport example
================
#include <stdio.h>
#include <dos.h>
int main(void)
{
int result;
int port = 0;
result = inport(port);
printf("Word read from port %d = 0x%X\n", port, result);
return 0;
inportb example
=================
#include <stdio.h>
#include <dos.h>
int main(void)
{
unsigned char result;
int port = 0; /* serial port 1 */
result = inportb(port);
printf("Byte read from port %d = 0x%X\n", port, result);
return 0;
}
outport example
=================
#include <stdio.h>
#include <dos.h>
int main(void)
{
int port = 0;
int value = 'C';
outport(port, value);
printf("Value %d sent to port number %d\n", value, port);
return 0;
}
outportb example
==================
#include <stdio.h>
#include <dos.h>
int main(void)
{
int port = 0;
char value = 'C';
outportb(port, value);
printf("Value %c sent to port number %d\n", value, port);
return 0;
}
===============
int86, int86x <DOS.H>
===============
General 8086 software interrupt interfaces
Declaration:
* int int86(int intno, union REGS *inregs, union REGS *outregs);
* int int86x(int intno, union REGS *inregs, union REGS *outregs,
struct SREGS *segregs);
Remarks:
int86 and int86x execute an 8086 software
interrupt specified by the argument intno.
With int86x, you can invoke an 8086 software
interrupt that takes a value of DS different
from the default data segment, and/or takes
an argument in ES.
Before the interrupt
====================
Before executing the software interrupt,
these functions copy register values from
inregs into the registers.
int86x also copies the segregs->ds and
segregs->es values into the corresponding
registers before executing the software
interrupt.
This feature allows programs that use far
pointers or a large data memory model to
specify which segment is to be used for the
software interrupt.
After the interrupt
===================
After the software interrupt returns, these
functions copy the following:
* current register values to outregs
* status of the carry flag to the x.cflag field in outregs
* value of the 8086 flags register to the x.flags field in outregs
int86x also restores DS and sets the
segregs->es and segregs->ds fields to
the values of the corresponding segment
registers.
If the carry flag is set, it usually
indicates that an error has occurred.
* NOTE: inregs can point to the same
structure that outregs points to.
Return Value:
Both functions return the value of AX after
completion of the software interrupt.
If the carry flag is set, indicating an
error (outregs -> x.cflag != 0), these
functions set _doserrno to the error code.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
bdos
bdosptr
geninterrupt
intdos
intdosx
intr
Examples:
int86 example
int86x example
int86 example
===============
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define VIDEO 0x10
void movetoxy(int x, int y)
{
union REGS regs;
regs.h.ah = 2; /* set cursor position */
regs.h.dh = y;
regs.h.dl = x;
regs.h.bh = 0; /* video page 0 */
int86(VIDEO, ®s, ®s);
}
int main(void)
{
clrscr();
movetoxy(35, 10);
printf("Hello\n");
return 0;
}
int86x example
================
#include <dos.h>
#include <process.h>
#include <stdio.h>
int main(void)
{
char filename[80];
union REGS inregs, outregs;
struct SREGS segregs;
printf("Enter filename: ");
gets(filename);
inregs.h.ah = 0x43;
inregs.h.al = 0x21;
inregs.x.dx = FP_OFF(filename);
segregs.ds = FP_SEG(filename);
int86x(0x21, &inregs, &outregs, &segregs);
printf("File attribute: %X\n", outregs.x.cx);
return 0;
}
=================
intdos, intdosx <DOS.H>
=================
General DOS interrupt interfaces
Declaration:
* int intdos(union REGS *inregs, union REGS *outregs);
* int intdosx(union REGS *inregs, union REGS *outregs,
struct SREGS *segregs);
Remarks:
intdos and intdosx execute DOS interrupt 0x21
to invoke a specified DOS function. The value
of inregs->h.ah specifies the DOS function to
be invoked.
intdosx also copies the segregs ->ds and
segregs ->es values into the corresponding
registers before invoking the DOS function.
This feature lets programs that use far
pointers or a large data memory model specify
which segment is to be used for the function
execution.
With intdosx, you can invoke a DOS function
that takes a value of DS different from the
default data segment and/or takes an argument
in ES.
After the interrupt
===================
After the interrupt 0x21 returns, these
functions copy the following:
* current register values to outregs
* status of the carry flag to the x.cflag field in outregs
* value of the 8086 flags register to the x.flags field in outregs
intdosx also sets the segregs->es and
segregs->ds fields to the values of the
corresponding segment registers and then
restores DS.
If the carry flag is set, it indicates that
an error occurred.
* NOTE: inregs can point to the same
structure that outregs points to.
Return Value:
Both functions return the value of AX after
completion of the DOS function call.
If the carry flag is set, indicating an
error (outregs -> x.cflag != 0), these
functions set _doserrno to the error code.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
bdos
bdosptr
geninterrupt
int86/int86x
intr
segread
Example:
intdos example
intdosx example
intdos example
================
#include <stdio.h>
#include <dos.h>
/* deletes file name; returns 0 on success, nonzero on failure */
int delete_file(char near *filename)
{
union REGS regs;
int ret;
regs.h.ah = 0x41;
/* delete file */
regs.x.dx = (unsigned) filename;
ret = intdos(®s, ®s);
/* if carry flag is set, there was an error */
return(regs.x.cflag ? ret : 0);
}
int main(void)
{
int err;
err = delete_file("NOTEXIST.$$$");
if (!err)
printf("Able to delete NOTEXIST.$$$\n");
else
printf("Not Able to delete NOTEXIST.$$$\n");
return 0;
}
intdosx example
=================
#include <stdio.h>
#include <dos.h>
/* deletes file name; returns 0 on success,
nonzero on failure */
int delete_file(char far *filename)
{
union REGS regs; struct SREGS sregs;
int ret;
regs.h.ah = 0x41; /* delete file */
regs.x.dx = FP_OFF(filename);
sregs.ds = FP_SEG(filename);
ret = intdosx(®s, ®s, &sregs);
/* if carry flag is set, there was an error */
return(regs.x.cflag ? ret : 0);
}
int main(void)
{
int err;
err = delete_file("NOTEXIST.$$$");
if (!err)
printf("Able to delete NOTEXIST.$$$\n");
else
printf("Not Able to delete NOTEXIST.$$$\n");
return 0;
}
======
intr <DOS.H>
======
Alternate 8086 software interrupt interface
Declaration: void intr(int intno, struct REGPACK *preg);
Remarks:
The intr function, an alternate interface for
executing software interrupts, generates an
8086 software interrupt specified by intno.
intr copies register values from a REGPACK
structure into the registers before executing
the software interrupt.
After the software interrupt completes, intr
copies the current register values, including
the flags, into the same REGPACK.
Argument | What It Is/Does
----------+--------------------------------------------------------
intno | Interrupt number to be executed
preg | Address of a REGPACK structure containing
| * the input registers before the interrupt call and
| * the value of the registers after the interrupt call
Return Value:
intr does not return. The REGPACK structure
*preg contains the value of the registers
after the interrupt call.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
geninterrupt
int86/int86x
intdos/intdosx
Example:
#include <stdio.h>
#include <string.h>
#include <dir.h>
#include <dos.h>
#define CF 1 /* Carry flag */
int main(void)
{
char directory[80];
struct REGPACK reg;
printf("Enter directory to change to: ");
gets(directory);
reg.r_ax = 0x3B << 8; /* shift 3Bh into AH */
reg.r_dx = FP_OFF(directory);
reg.r_ds = FP_SEG(directory);
intr(0x21, ®);
if (reg.r_flags & CF)
printf("Directory change failed\n");
getcwd(directory, 80);
printf("The current directory is: %s\n", directory);
return 0;
}
====================
_dos_keep and keep <DOS.H>
====================
Exits and remains resident
Declaration:
* void _dos_keep(unsigned char status, unsigned size);
* void keep(unsigned char status, unsigned size);
Remarks:
Both _dos_keep and keep use DOS function 0x31
to return to DOS with the exit status in
status.
The current program remains resident.
These functions set the program to size
paragraphs in length, and free the remainder
of the memory of the program.
You can use _dos_keep and keep when
installing TSR programs.
Before _dos_keep exits, it does the following:
* calls any registered "exit functions"
(posted with atexit)
* flushes file buffers
* restores interrupt vectors modified by
the startup code
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
abort
exit
Examples:
_dos_keep example
keep example
_dos_keep example
===================
/* NOTE:
This is an interrupt service routine.
You can NOT compile this program with Test
Stack Overflow turned on and get an
executable file which will operate
correctly. Due to the nature of this
function the formula used to compute
the number of paragraphs may not
necessarily work in all cases. Use with
care! Terminate Stay Resident (TSR)
programs are complex and no other support
for them is provided. Refer to the
MS-DOS technical documentation
for more information. */
#include <dos.h>
/* The clock tick interrupt */
#define INTR 0x1C
/* Screen attribute (blue on grey) */
#define ATTR 0x7900
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
/* reduce heaplength and stacklength to make a smaller program in memory */
extern unsigned _heaplen = 1024;
extern unsigned _stklen = 512;
void interrupt ( *oldhandler)(__CPPARGS);
typedef unsigned int (far *s_arrayptr);
void interrupt handler(__CPPARGS)
{
s_arrayptr screen[80];
static int count;
/* For a color screen the video memory is at B800:0000.
For a monochrome system use B000:000 */
screen[0] = (s_arrayptr) MK_FP(0xB800,0);
/* increase the counter and keep it within 0 to 9 */
count++;
count %= 10;
/* put the number on the screen */
screen[0][79] = count + '0' + ATTR;
/* call the old interrupt handler */
oldhandler();
}
int main(void)
{
/* get the address of the current clock
tick interrupt */
oldhandler = _dos_getvect(INTR);
/* install the new interrupt handler */
_dos_setvect(INTR, handler);
/* _psp is the starting address of the
program in memory. The top of the stack
is the end of the program. Using _SS and
_SP together we can get the end of the
stack. You may want to allow a bit of
saftey space to insure that enough room
is being allocated ie:
(_SS + ((_SP + safety space)/16) - _psp)
*/
_dos_keep(0, (_SS + (_SP/16) - _psp));
return 0;
}
keep example
==============
/* NOTE:
This is an interrupt service routine.
You can NOT compile this program with Test
Stack Overflow turned on and get an
executable file which will operate
correctly. Due to the nature of this
function the formula used to compute
the number of paragraphs may not
necessarily work in all cases. Use with
care! Terminate Stay Resident (TSR)
programs are complex and no other support
for them is provided. Refer to the
MS-DOS technical documentation
for more information. */
#include <dos.h>
/* The clock tick interrupt */
#define INTR 0x1C
/* Screen attribute (blue on grey) */
#define ATTR 0x7900
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
/* reduce heaplength and stacklength to make a smaller program in memory */
extern unsigned _heaplen = 1024;
extern unsigned _stklen = 512;
void interrupt ( *oldhandler)(__CPPARGS);
typedef unsigned int (far *s_arrayptr);
void interrupt handler(__CPPARGS)
{
s_arrayptr screen[80];
static int count;
/* For a color screen the video memory is at B800:0000.
For a monochrome system use B000:000 */
screen[0] = (s_arrayptr) MK_FP(0xB800,0);
/* increase the counter and keep it within 0 to 9 */
count++;
count %= 10;
/* put the number on the screen */
screen[0][79] = count + '0' + ATTR;
/* call the old interrupt handler */
oldhandler();
}
int main(void)
{
/* get the address of the current clock
tick interrupt */
oldhandler = getvect(INTR);
/* install the new interrupt handler */
setvect(INTR, handler);
/* _psp is the starting address of the
program in memory. The top of the stack
is the end of the program. Using _SS and
_SP together we can get the end of the
stack. You may want to allow a bit of
saftey space to insure that enough room
is being allocated ie:
(_SS + ((_SP + safety space)/16) - _psp)
*/
keep(0, (_SS + (_SP/16) - _psp));
return 0;
}
===========
_dos_open <DOS.H>
_open <IO.H>
===========
Open a file for reading or writing
Declaration:
* _dos_open:
#include <fcntl.h>
#include <share.h>
#include <dos.h>
unsigned _dos_open(const char *filename, unsigned oflags,
int *handlep);
* _open:
#include <fcntl.h>
int _open(const char *filename, int oflags);
Remarks:
_dos_open and _open both open the file
specified by filename, then prepare it for
reading or writing. The file is always opened
in binary mode.
Argument | What Argument Is/Does
----------+---------------------------------------------------------------
filename | File that the function opens and prepares for reading and/or
| writing
oflags | Open-mode symbolic constants (defined in FCNTL.H) and
| file-sharing symbolic constants (defined in SHARE.H) that
| specify the file's open mode (read, write, share, etc.)
handlep | Points to the location where the function stores
| the file's handle.
On successfully opening the file, both
functions set the file pointer (which marks
the current position in the file) to the
beginning of the file.
The maximum number of simultaneously open
files is defined by HANDLE_MAX.
About the oflags Argument
=========================
Under DOS 2.x, the value of oflags for _open
is limited to O_RDONLY, O_WRONLY, and O_RDWR.
Under DOS 3.x, you can OR the following
file-sharing symbolic constants in the oflags
argument:
* SH_xxx (for _dos_open)
* O_DENYxxx (for _open)
Only one of the SH_DENYxxx values can be
included in a single call to _dos_open.
Only one of the O_DENYxxx values can be
included in a single call to _open.
These file-sharing attributes are in addition
to any locking performed on the files.
Return Value:
* On success,
* _dos_open returns 0, stores the file handle at the location *handlep
* _open returns the file handle (a non-negative integer)
* On error,
* _dos_open returns the DOS error code
* _open returns -1
* Both functions set errno to one of the following:
ENOENT (Path or file not found)
EMFILE (Too many open files)
EACCES (Permission denied)
EINVACC (Invalid access code)
Portability
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
_dos_creat
_dos_read
_dos_write
_read
open
sopen
Examples:
_dos_open example
_open example
_dos_open example
===================
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <dos.h>
int main(void)
{
int handle;
unsigned nbytes;
char msg[] = "Hello world\n";
if (_dos_open("TEST.$$$", O_RDWR, &handle) != 0) {
perror("Unable to open TEST.$$$");
return 1;
}
if (_dos_write(handle, msg, strlen(msg),&nbytes) != 0)
perror("Unable to write to TEST.$$$");
printf("%u bytes written to TEST.$$$\n",nbytes);
_dos_close(handle);
return 0;
}
_open example
===============
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "Hello world";
if ((handle = _open("TEST.$$$", O_RDWR)) == -1)
{
perror("Error:");
return 1;
}
_write(handle, msg, strlen(msg));
_close(handle);
return 0;
}
=============
_OvrInitEms <DOS.H>
=============
Initializes expanded memory swapping for overlay manager
Declaration:
int _OvrInitEms(unsigned emsHandle, unsigned firstPage, unsigned pages);
Remarks:
_OvrInitEms checks for the presence of
expanded memory by looking for an EMS driver
and allocating memory from it.
If emsHandle == 0, the overlay manager
allocates EMS pages and uses them for
swapping.
If emsHandle != 0, it should be a valid EMS
handle; the overlay manager will use it for
swapping. In that case, you can specify
firstPage; the swapping can start inside that
area.
A non-zero pages parameter gives the limit of
the pages that the overlay manager can use.
Return Value:
Returns 0 if the overlay manager is able to
use expanded memory for swapping.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
_OvrInitExt
Example:
#include <dos.h>
int main(void)
{
/*
Ask overlay manager to check for expanded
memory and allow it to use 16 pages
(256K); available only in medium, large
and huge memory models
*/
/* In the IDE, set Options|Applications to Dos Overlay */
_OvrInitEms (0, 0, 16);
return 0;
}
=============
_OvrInitExt <DOS.H>
=============
Initializes extended memory swapping for overlay manager
Declaration:
int _OvrInitExt(unsigned long startAddress, unsigned long length);
Remarks:
_OvrinitExt checks for the presence of
extended memory (using the known methods to
detect the presence of other programs using
extended memory) and allocates memory from it.
If startAddress == 0, the overlay manager
determines the start address and uses, at
most, the size of the overlays.
If startAddress != 0, the overlay manager
uses the extended memory above that address.
A non-zero length parameter gives the limit
of the extended memory that the overlay
manager can use
Return Value:
Returns 0 if the overlay manager is able to
use extended memory for swapping.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
_OvrInitEms
Example:
#include <dos.h>
int main(void)
{
/*
Available only in medium, large and
huge memory models
*/
/*
Use the extended memory from the linear
address 0x200000L (2MB), as much as
necessary
*/
/* In the IDE, set Options|Applications to Dos Overlay */
_OvrInitExt (0x200000L, 0);
return 0;
}
=========
parsfnm <DOS.H>
=========
Parses file name and builds a File Control Block (FCB)
Declaration:
char *parsfnm(const char *cmdline, struct fcb *fcb, int opt);
Remarks:
parsfnm parses a string for a file name.
Argument | What It Is/Does
----------+-----------------------------------------------------------
cmdline | Points to a string (normally a command line)
fcb | Points to a file control block (FCB) where parsfnm places
| the file name as a drive, file name, and extension
opt | The value documented for AL in the DOS parse system call
See your DOS reference manuals under system
call 0x29 for a description of the parsing
operations performed on the file name.
Return Value
* On success, returns a pointer to the next
byte after the end of the file name.
* On error, returns null.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
Example:
#include <process.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>
int main(void)
{
char line[80];
struct fcb blk;
/* get file name */
printf("Enter drive and file name (no path; e.g., a:file.dat)\n");
gets(line);
/* put file name in fcb */
if (parsfnm(line, &blk, 1) == NULL)
printf("Error in parsfm call\n");
else
printf("Drive #%d Name: %11s\n", blk.fcb_drive, blk.fcb_name);
return 0;
}
=============
peek, peekb <DOS.H>
=============
* peek returns the word at memory location specified by segment:offset
* peekb returns the byte at memory location specified by segment:offset
Declaration:
* int peek(unsigned segment, unsigned offset);
* char peekb(unsigned segment, unsigned offset);
Remarks:
* peek returns the word at the memory
location segment:offset.
* peekb returns the byte at the memory
location addressed by segment:offset.
If you call peek or peekb when DOS.H has been
included, each is treated as a macro that
expands to inline code.
If you don't include DOS.H, or if you do
include it and #undef peek (or peekb), you'll
get the function rather than the macro.
Return Value:
* peek returns the word of data stored at
memory location segment:offset
* peekb returns the byte of data stored at
memory location segment:offset
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
harderr
poke
Example:
#include <stdio.h>
#include <conio.h>
#include <dos.h>
int main(void)
{
int value = 0;
printf("The current status of your keyboard is:\n");
value = peek(0x0040, 0x0017);
if (value & 1)
printf("Right shift on\n");
else
printf("Right shift off\n");
if (value & 2)
printf("Left shift on\n");
else
printf("Left shift off\n");
if (value & 4)
printf("Control key on\n");
else
printf("Control key off\n");
if (value & 8)
printf("Alt key on\n");
else
printf("Alt key off\n");
if (value & 16)
printf("Scroll lock on\n");
else
printf("Scroll lock off\n");
if (value & 32)
printf("Num lock on\n");
else
printf("Num lock off\n");
if (value & 64)
printf("Caps lock on\n");
else
printf("Caps lock off\n");
return 0;
}
=============
poke, pokeb <DOS.H>
=============
* poke stores an integer value at the memory location segment:offset
* pokeb stores a byte value at the memory location segment:offset
Declaration:
* void poke(unsigned segment, unsigned offset, int value);
* void pokeb(unsigned segment, unsigned offset, char value);
Remarks:
* poke stores the integer value at the memory
location segment:offset.
* pokeb stores the byte value at the memory
location segment:offset.
If you call either of these routines when
DOS.H has been included, the routine will be
treated as a macro that expands to inline
code.
If you don't include DOS.H, or if you do
include it and #undef poke (or pokeb),
you'll get the function rather than the
macro.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
harderr
peek/peekb
Example:
#include <dos.h>
#include <conio.h>
int main(void)
{
clrscr();
cprintf("Make sure the scroll lock key is off and press any key\r\n");
getch();
poke(0x0000,0x0417,16);
cprintf("The scroll lock is now on\r\n");
return 0;
}
==================
randbrd, randbwr <DOS.H>
==================
* randbrd performs a random block read using FCB
* randbwr perfroms a random block write using FCB
Declaration:
* int randbrd(struct fcb *fcb, int rcnt);
* int randbwr(struct fcb *fcb, int rcnt);
Remarks:
* randbrd reads records into memory at the
current disk transfer address (DTA), using
an open file control block (FCB).
* randbwr writes records to disk, using an
open FCB.
Arg. | What It Is/Does
------+-------------------------------------
rcnt | Number of records read or written.
| With randbwr, if rcnt is 0, the file
| is truncated to the length indicated
| by the random record field.
fcb | Points to the open FCB
randbrd uses DOS system call 0x27 to read
from the disk record indicated in the random
record field of the FCB.
randbwr uses DOS system call 0x28 to write to
the disk.
To determine the actual number of records
read or written, examine the random record
field of the FCB. The random record field is
advanced by the number of records actually
read or written.
Return Value:
Value| Result of randbrd | Result of randbwr
------+--------------------------+----------------------------------------
0 | All records are read | All records are written
1 | End-of-file; last record | There is not enough disk space to write
| read is complete | the records (no records are written)
2 | Reading records would | Writing records would have wrapped
| have wrapped around | around address 0xFFFF (as many records
| | as possible are written)
3 | End-of-file; last record | ---
| read is incomplete | ---
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
getdta
setdta
Examples:
randbrd example
randbwr example
randbrd example
=================
#include <process.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>
int main(void)
{
char far *save_dta;
char line[80], buffer[256];
struct fcb blk;
int i, result;
/* get user input file name for dta */
printf("Enter drive and file name (no path - i.e. a:file.dat)\n");
gets(line);
/* put file name in fcb */
if (!parsfnm(line, &blk, 1))
{
printf("Error in call to parsfnm\n");
exit(1);
}
printf("Drive #%d File: %s\n\n", blk.fcb_drive, blk.fcb_name);
/* open file with DOS FCB open file */
bdosptr(0x0F, &blk, 0);
/* save old dta, and set new one */
save_dta = getdta();
setdta(buffer);
/* set up info for the new dta */
blk.fcb_recsize = 128;
blk.fcb_random = 0L;
result = randbrd(&blk, 1);
/* check results from randbrd */
if (!result)
printf("Read OK\n\n");
else
{
perror("Error during read");
exit(1);
}
/* read in data from the new dta */
printf("The first 128 characters are:\n");
for (i=0; i<128; i++)
putchar(buffer[i]);
/* restore previous dta */
setdta(save_dta);
return 0;
}
randbwr example
=================
#include <process.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>
int main(void)
{
char far *save_dta;
char line[80];
char buffer[256] = "RANDBWR test!";
struct fcb blk;
int result;
/* get new file name from user */
printf("Enter a file name to create (no path - ie. a:file.dat\n");
gets(line);
/* parse the new file name to the dta */
parsfnm(line,&blk,1);
printf("Drive #%d File: %s\n", blk.fcb_drive, blk.fcb_name);
/* request DOS services to create file */
if (bdosptr(0x16, &blk, 0) == -1)
{
perror("Error creating file");
exit(1);
}
/* save old dta and set new dta */
save_dta = getdta();
setdta(buffer);
/* write new records */
blk.fcb_recsize = 256;
blk.fcb_random = 0L;
result = randbwr(&blk, 1);
if (!result)
printf("Write OK\n");
else
{
perror("Disk error");
exit(1);
}
/* request DOS services to close the file */
if (bdosptr(0x10, &blk, 0) == -1)
{
perror("Error closing file");
exit(1);
}
/* reset the old dta */
setdta(save_dta);
return 0;
}
=============
_dos_read <DOS.H>
_read, read <IO.H>
=============
Reads from file
Declaration:
* unsigned _dos_read(int handle, void far *buf, unsigned len,
unsigned *nread);
* int _read(int handle, void *buf, unsigned len);
* int read(int handle, void *buf, unsigned len);
Remarks:
* _dos_read and _read use DOS function 0x3F
(read system call) to read bytes from a file
into a buffer.
* read attempts to read bytes from a file
into a buffer.
Argument| Function | What Argument Is/Does
--------+------------+---------------------------------------------------
handle | _read, read| File handle obtained from a creat, open, dup, or
| | dup2 call.
handle | _dos_read | File handle obtained from a _dos_creat, _dos_open,
| | or _doscreatnew call.
| |
nread | _dos_read | Points to the location where the function stores
| | the actual number of bytes read
buf | (all) | Points to a buffer that the function reads the
| | bytes into.
len | (all) | Number of bytes that the function attempts to read
When _dos_read encounters an error or the
end-of-file, nread might be less than len.
| Max. Bytes |
Function | Read | Comment
----------+------------+---------------------------------------------------
_dos_read| 65,535 | ---
_read | 65,534 | Maximum number of bytes read = 65,534 because
read | 65,534 | 65,535 (0xFFFF) is the same as -1, the error
| | return indicator.
Carriage Returns
================
_dos_read does not remove carriage returns
because all its files are binary files.
When a file is opened in text mode,
* _read does not remove carriage returns
* read removes carriage returns and reports
end-of-file when it reaches a Ctrl-Z.
If the file is opened in text mode, read does
not count carriage returns or Ctrl-Z
characters in the number of bytes read.
See "Disk Files and Devices" for more
information.
Return Value:
* On success,
* _dos_read returns 0
* _read and read return a positive integer indicating the number of
bytes placed in the buffer.
* On end-of-file, _read and read return 0
* On error,
* _dos_read returns the DOS error code and sets errno to one of the
following:
EACCES Permission denied
EBADF Bad file number
* _read and read return -1 and set errno to EACCES or EBADF
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
_dos_read | Yes | | Yes | | |
_read | Yes | | Yes | | |
read | Yes | Yes | Yes | | |
+-----+------+---------+--------+----------+
See Also:
_dos_open
_dos_write
_open
open
write/_write
Examples:
_dos_read example
_read example
read example
_dos_read example
===================
#include <stdio.h>
#include <fcntl.h>
#include <dos.h>
int main(void)
{
int handle;
unsigned bytes;
char buf[10];
/* Looks for a file in the current directory named TEST.$$$ and
attempts to read 10 bytes from it. To use this example you
should create the file TEST.$$$ */
if (_dos_open("TEST.$$$", O_RDONLY, &handle) != 0) {
perror("Unable to open TEST.$$$");
return 1;
}
if (_dos_read(handle, buf, 10, &bytes) != 0) {
perror("Unable to read from TEST.$$$");
return 1;
}
else
printf("_dos_read: %d bytes read.\n", bytes);
return 0;
}
_read example
===============
#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{
void *buf;
int handle, bytes;
buf = malloc(10);
/*
Looks for a file in the current directory
named TEST.$$$ and attempts to read 10
bytes from it. To use this example you
should create the file TEST.$$$
*/
if ((handle =
open("TEST.$$$", O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1)
{
printf("Error Opening File\n");
exit(1);
}
if ((bytes = _read(handle, buf, 10)) == -1) {
printf("Read Failed.\n");
exit(1);
}
else {
printf("_read: %d bytes read.\n", bytes);
}
return 0;
}
read example
==============
#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{
void *buf;
int handle, bytes;
buf = malloc(10);
/*
Looks for a file in the current directory named TEST.$$$ and attempts
to read 10 bytes from it. To use this example you should create the
file TEST.$$$
*/
if ((handle =
open("TEST.$$$", O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1)
{
printf("Error Opening File\n");
exit(1);
}
if ((bytes = read(handle, buf, 10)) == -1) {
printf("Read Failed.\n");
exit(1);
}
else {
printf("Read: %d bytes read.\n", bytes);
}
return 0;
}
Disk Files and Devices
========================
With disk files, _dos_read, read, and _read
all begin reading at the current file
pointer.
When the reading is complete, the functions
increment the file pointer by the number of
bytes read.
With devices, these functions read the bytes
directly from the device.
=========
segread <DOS.H>
=========
Reads segment registers
Declaration: void segread(struct SREGS *segp);
Remarks:
segread places the current values of the
segment registers into the structure *segp.
This call is intended for use with intdosx
and int86x.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
FP_OFF
int86
int86x
intdos
intdosx
MK_FP
movedata
Example:
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct SREGS segs;
segread(&segs);
printf("Current segment register settings\n\n");
printf("CS: %X DS: %X\n", segs.cs, segs.ds);
printf("ES: %X SS: %X\n", segs.es, segs.ss);
return 0;
}
=========================
_dos_setblock, setblock <DOS.H>
=========================
Modifies the size of a previously allocated block
Declaration:
* unsigned _dos_setblock(unsigned newsize, unsigned segx, unsigned *maxp);
* int setblock(unsigned segx, unsigned newsize);
Remarks:
_dos_setblock and setblock modify the size
of a memory segment.
Argument | What It Is/Does
----------+----------------------------------------------------------------
segx | Segment address returned by a previous call to allocmem
newsize | New, requested size in paragraphs
maxp | Points to location where the size of the largest possible
| segment is stored (if the segment can't be changed to the
| new size)
Return Value:
* On success,
* _dos_setblock returns 0
* setblock returns -1
* On error,
* _dos_setblock returns the DOS error code and sets errno to
ENOMEM Not enough memory or bad segment address
* setblock returns the size of the largest possible block (in
paragraphs), and sets _doserrno.
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
_dos_allocmem
_dos_freemem
allocmem
freemem
Examples:
_dos_setblock example
setblock example
_dos_setblock example
=======================
#include <dos.h>
#include <stdio.h>
int main(void)
{
unsigned int size, segp, err, maxb;
size = 64; /* (64 x 16) = 1024 bytes */
err = _dos_allocmem(size, &segp);
if (err == 0)
printf("Allocated memory at segment: %x\n", segp);
else {
perror("Unable to allocate block");
printf("Maximum no. of paragraphs available is %u\n", segp);
return 1;
}
if (_dos_setblock(size * 2, segp, &maxb) == 0)
printf("Expanded memory block at segment: %X\n", segp);
else {
perror("Unable to expand block");
printf("Maximum no. of paragraphs available is %u\n", maxb);
}
_dos_freemem(segp);
return 0;
}
setblock example
==================
#include <dos.h>
#include <alloc.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned int size, segp;
int stat;
size = 64; /* (64 x 16) = 1024 bytes */
stat = allocmem(size, &segp);
if (stat == -1)
printf("Allocated memory at segment: %X\n", segp);
else
{
printf("Failed: maximum number of paragraphs available is %d\n",
stat);
exit(1);
}
stat = setblock(segp, size * 2);
if (stat == -1)
printf("Expanded memory block at segment: %X\n", segp);
else
printf("Failed: maximum number of paragraphs available is %d\n",
stat);
freemem(segp);
return 0;
}
=======
sleep <DOS.H>
=======
Suspends execution for interval
Declaration: void sleep(unsigned seconds);
Remarks:
With a call to sleep, the current program is
suspended from execution for the number of
seconds specified by the argument seconds.
The interval is only accurate to the nearest
hundredth of a second or the accuracy of the
DOS clock, whichever is less accurate.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | Yes | | | |
+-----+------+---------+--------+----------+
See Also:
delay
Example:
#include <dos.h>
#include <stdio.h>
int main(void)
{
int i;
for (i=1; i<5; i++)
{
printf("Sleeping for %d seconds\n", i);
sleep(i);
}
return 0;
}
================
sound, nosound <DOS.H>
================
* sound turns the PC speaker on at the specified frequency
* nosound turns the PC speaker off
Declaration:
* void sound(unsigned frequency);
* void nosound(void);
Remarks:
* sound turns on the PC's speaker at a given
frequency.
* nosound turns the speaker off after it has
been turned on by a call to sound.
frequency specifies the frequency of the
sound in hertz (cycles per second).
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | | | |
+-----+------+---------+--------+----------+
See Also:
delay
Example (for both functions):
/* Emits a 7-Hz tone for 10 seconds.
True story: 7 Hz is the resonant
frequency of a chicken's skull cavity.
This was determined empirically in
Australia, where a new factory
generating 7-Hz tones was located too
close to a chicken ranch: When the
factory started up, all the chickens
died.
Your PC may not be able to emit a 7-Hz tone. */
#include <dos.h>
int main(void)
{
sound(7);
delay(10000);
nosound();
return 0;
}
===========
unixtodos <DOS.H>
===========
Converts date and time from UNIX to DOS format
Declaration:
void unixtodos(long time, struct date *d, struct time *t);
Remarks:
unixtodos converts the UNIX-format time given
in time to DOS format and fills in the date
and time structures *d and *t.
Return Value: None
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | | Yes | | |
+-----+------+---------+--------+----------+
See Also:
dostounix
Example:
#include <stdio.h>
#include <dos.h>
char *month[] = {"---", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
#define SECONDS_PER_DAY 86400L /* the number of seconds in one day */
struct date dt;
struct time tm;
int main(void)
{
unsigned long val;
/* get today's date and time */
getdate(&dt);
gettime(&tm);
printf("today is %d %s %d\n", dt.da_day, month[dt.da_mon], dt.da_year);
/*convert date and time to unix format (num of seconds since Jan 1, 1970*/
val = dostounix(&dt, &tm);
/* subtract 42 days worth of seconds */
val -= (SECONDS_PER_DAY * 42);
/* convert back to dos time and date */
unixtodos(val, &dt, &tm);
printf("42 days ago it was %d %s %d\n",
dt.da_day, month[dt.da_mon], dt.da_year);
return 0;
}
========
unlink <DOS.H, IO.H, STDIO.H>
========
Deletes a file
Declaration: int unlink(const char *filename);
Remarks:
unlink deletes a file specified by filename.
Any DOS drive, path, and file name can be
used as filename. Wildcards are not allowed.
Read-only files can't be deleted by this
call. To remove read-only files, first use
chmod or _chmod to change the read-only
attribute.
If your file is open, be sure to close it
before unlinking it.
Return Value:
* On success, unlink returns 0.
* On error, it returns -1 and sets errno to
one of the following:
ENOENT Path or file name not found
EACCES Permission denied
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
| Yes | Yes | Yes | | |
+-----+------+---------+--------+----------+
See Also:
chmod
remove
Example:
#include <stdio.h>
#include <io.h>
int main(void)
{
FILE *fp = fopen("junk.jnk","w");
int status;
fprintf(fp,"junk");
status = access("junk.jnk",0);
if (status == 0)
printf("File exists\n");
else
printf("File doesn't exist\n");
fclose(fp);
unlink("junk.jnk");
status = access("junk.jnk",0);
if (status == 0)
printf("File exists\n");
else
printf("File doesn't exist\n");
return 0;
}
===============
_dos_write <DOS.H>
_write, write <IO.H>
===============
Writes to a file
Declaration:
* unsigned _dos_write(int handle, void far *buf, unsigned len,
unsigned *nwritten);
* int _write(int handle, void *buf, unsigned len);
* int write(int handle, void *buf, unsigned len);
Remarks:
_dos_write and _write use DOS function 0x40
to write bytes from a buffer to a file.
write writes a buffer of data to a file or
device.
Argument | Function | What Argument Is/Does
---------+------------+---------------------------------------------------
handle | _write, | File handle obtained from a creat, open, dup, or
| write | dup2 call.
handle | _dos_write | File handle obtained from a _dos_creat, _dos_open,
| | or _doscreatnew call.
| |
nwritten| _dos_write | Points to the location where the function stores
| | the actual number of bytes written
buf | (all) | Points to a buffer that the function writes the
| | bytes from
len | (all) | Number of bytes the function attempts to write
Except when you use write to write to a text
file, the number of bytes written to the file
will be no more than the number requested.
For all of these functions, if the number of
bytes actually written is less than that
requested, this is probably an error (most
likely a full disk).
| Max. Bytes |
Function | Written | Comment
-----------+------------+-------------------------------------------------
_dos_write| 65,535 | ---
_write | 65,534 | Maximum number of bytes written = 65,534 because
write | 65,534 | 65,535 (0xFFFF) is the same as -1, the error
| | return indicator.
Carriage Returns and Line Feeds
===============================
On text files, when write sees an LF
(linefeed) character, it outputs a CR/LF
(carriage-return/linefeed) pair.
_write and _dos_write do not translate LF
(linefeed) characters to CR/LF pairs, because
all of their files are binary files.
A write to a text file does not count
generated carriage returns.
Disk Files and Devices
======================
With disks or disk files, writing always
proceeds from the current file pointer.
With devices, these functions send bytes
directly to the device.
For files opened with the O_APPEND option,
* write positions the file pointer to EOF
before writing the data.
* _write does not position the file pointer
to EOF before writing the data.
Return Value:
* On success,
* _dos_write returns 0
* _write and write return the number of bytes written.
* On error
* _dos_write returns the DOS error code and sets errno to one of the
following:
EACCES Permission denied
EBADF Bad file number
* _write and write return -1 and set errno to EACCES or EBADF
Portability:
+ DOS + UNIX + Windows + ANSI C + C++ Only +
_dos_write | Yes | | Yes | | |
_write | Yes | | Yes | | |
write | Yes | Yes | Yes | | |
+-----+------+---------+--------+----------+
See Also:
creat
_dos_creat
_dos_open
_dos_read
lseek
open
read/_read
Examples:
_dos_write example
_write example
write example
_dos_write example
====================
#include <dos.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
unsigned count;
int handle;
char buf[11] = "0123456789";
/* create a file containing 10 bytes */
if (_dos_creat("DUMMY.FIL", _A_NORMAL, &handle) != 0)
{
perror("Unable to create DUMMY.FIL");
return 1;
}
if (_dos_write(handle, buf, strlen(buf), &count) != 0)
{
perror("Unable to write to DUMMY.FIL");
return 1;
}
/* close the file */
_dos_close(handle);
return 0;
}
_write example
================
#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{
void *buf;
int handle, bytes;
buf = malloc(200);
/*
Create a file name TEST.$$$ in the current directory and writes
200 bytes to it. If TEST.$$$ already exists, it's overwritten.
*/
if ((handle = open("TEST.$$$", O_CREAT | O_WRONLY | O_BINARY,
S_IWRITE | S_IREAD)) == -1)
{
printf("Error Opening File\n");
exit(1);
}
if ((bytes = _write(handle, buf, 200)) == -1) {
printf("Write Failed.\n");
exit(1);
}
printf("_write: %d bytes written.\n",bytes);
return 0;
}
write example
===============
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <io.h>
#include <string.h>
int main(void)
{
int handle;
char string[40];
int length, res;
/*
Create a file named "TEST.$$$" in the current directory and write
a string to it. If "TEST.$$$" already exists, it will be overwritten.
*/
if ((handle = open("TEST.$$$", O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE)) == -1)
{
printf("Error opening file.\n");
exit(1);
}
strcpy(string, "Hello, world!\n");
length = strlen(string);
if ((res = write(handle, string, length)) != length)
{
printf("Error writing to the file.\n");
exit(1);
}
printf("Wrote %d bytes to the file.\n", res);
close(handle);
return 0;
}