Category : C Source Code
Archive   : DIRECT.ZIP
Filename : DIRECT.C

 
Output of file : DIRECT.C contained in archive : DIRECT.ZIP
/* DIRECT.C was written because I was interested in how programs like CSHOW
* were able to display the contents of a directory. I was not clear about
* how DOS read directories. DIRECT is basically a replacement for DIR.
* The function DOS_to_dir() accepts the directory entry in raw form and
* converts it to a string. DOS returns the date and time in packed mode.
* These modes are described in "The New Peter Norton's Programmer's Guide
* to the IBM PC & PS/2" on page 116. Unpacking leads to all the bit shifting.
* Rick Davis, NIOSH 7/9/91
*/
#include
#include
#include
#include

void DOS_to_dir(char *, char *);

char directory[1680]; /* final resting place for file entries */

main()
{
union REGS toregs,fromregs;
struct SREGS segregs;

char _far *transfer; /* pointers to arrays */
char _far *wild_card;

char cTransfer[50];
char cWild_card[13];

int i,j,k;


/* first, let's register the Disk Transfer Area */

transfer = cTransfer;
wild_card = cWild_card;


toregs.x.dx = FP_OFF(transfer);

segregs.ds = FP_SEG(transfer);

toregs.h.ah = 0x1a; /* Set Disk Transfer Area */

int86x( 0x21, &toregs , &fromregs , &segregs ); /* DOS interupt */


/* Next, lets get the first file in the directory */

sprintf(cWild_card,"*.*");

toregs.x.dx = FP_OFF( wild_card );

segregs.ds = FP_SEG( wild_card );

toregs.h.ah = 0x4e; /* get first matching file */

toregs.x.cx = 0; /* no special attributes */

int86x( 0x21 , &toregs , &fromregs , &segregs); /* DOS interupt */

if(fromregs.x.cflag)printf("Error: AX = %x hex\n",fromregs.x.ax); //error code*

/* next move the file name returned from the interupt to someplace safe */

DOS_to_dir(cTransfer, directory );


fromregs.x.cflag = 0; // carry flag indicates error

while(!fromregs.x.cflag){

toregs.h.ah = 0x4f; // read next directory entry

int86x( 0x21, &toregs , &fromregs , &segregs ); // DOS interupt

if(!fromregs.x.cflag){ // Skip on last go around, else dup last entries

DOS_to_dir(cTransfer, directory);

}
}

if(fromregs.x.cflag == 1 && fromregs.x.ax == 0x12){
printf("\n Dir Program\n");
printf("-----------------\n\n");
}
else printf("cflags = %d, AX = %d\n",fromregs.x.cflag, fromregs.x.ax);

printf("%s",directory);
}



void DOS_to_dir(char *input, char *outstring)
{
char month[12][4] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep",
"Oct","Nov","Dec"};
int i,j,k;

char c_to_str[60][3] = {"00","01","02","03","04","05","06","07","08","09",
"10","11","12","13","14","15","16","17","18","19",
"20","21","22","23","24","25","26","27","28","29",
"30","31","32","33","34","35","36","37","38","39",
"40","41","42","43","44","45","46","47","48","49",
"50","51","52","53","54","55","56","57","58","59"};
char temp[20];

struct dos_dir{ /* structure of a dos directory entry */
char DOS[21];
char attribute;
unsigned int time;
unsigned int date;
unsigned long size;
char filename[13];
};
union{
struct dos_dir dir_entry;
char dd[43];
}de;


for(k=0;k<43;k++){ /* copy over the raw DOS entry */
de.dd[k] = *(input + k);
}

/* move the file name to the calling argument string */

if((i = strlen(de.dir_entry.filename)) < 7 ){ /* if FILENAME is less than 7 */
strcat(outstring,de.dir_entry.filename); /* copy it and pad with blanks */
for( j = 0; j < 12 - i; j++){
strcat(outstring," ");
}
}
else strcat(outstring,de.dir_entry.filename); /* otherwise just copy it */

strcat(outstring,"\t");

/* build the date in the temporary string */

i = (de.dir_entry.date >> 5) & 0x0f; /* index into month array */

j = de.dir_entry.date & 0x001f; /* index into day */

if(sprintf(temp,"%s %s, %d",month[i-1],c_to_str[j],(de.dir_entry.date >> 9) + 1980)==0){
perror("sprintf");
}

/* move the temporary string to the calling argument string */

strcat(outstring,temp);

if(sprintf(temp,"\t") == 0){
perror("sprintf");
}

/* move the tab to the calling argument */

strcat(outstring,temp);

/* build the file size into the temporary string */

if(sprintf( temp, "%lu bytes",de.dir_entry.size)==0){
perror("sprintf");
}

/* pad it with blanks to a reasonable size */

if((i = strlen(temp)) < 14){
for(j=0;j<14 - i;j++){
strcat(outstring," ");
}
}
strcat(outstring,temp); /* move file length to calling string */

strcat(outstring,"\t");

/* build the file time stamp to the temporary string */

sprintf(temp,"%s:",c_to_str[(de.dir_entry.time >> 11)] ); /* hours */

strcat(outstring,temp);

sprintf(temp,"%s:",c_to_str[(de.dir_entry.time >> 5 & 0x3f)]); /* minutes */

strcat(outstring,temp);

sprintf(temp,"%s",c_to_str[((de.dir_entry.time & 0x1f) * 2)]); /* seconds */

strcat(outstring,temp);

strcat(outstring,"\n"); /* end the file entry */

#if DEBUG
printf("DOS_to_dir: %s", outstring);
printf("length = %lu",de.dir_entry.size);
#endif

}


  3 Responses to “Category : C Source Code
Archive   : DIRECT.ZIP
Filename : DIRECT.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/