=======
  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; }