/* Compile with HiTech C for CP/M-80 v3.09 */

/* c -c b:ls.c */
/* c ls.obj parseafn.obj datetime.obj bdos.obj */

#include <cpm.h>
#include <stddef.h>
#include <ctype.h>
#include <stat.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> 
/* #include <malloc.h> */
#include "B:BDOS.H"
#include "B:PARSEAFN.H"
#include "B:DATETIME.H"

char * ptrInvoked;
char * ptrDirName;
int optLong=0;
int optAll=0;
int optSort=0;
int optFE=0;
int optVerbose=0;
int optBlkSize=0;
int optUorCdts=0;
int optDate=0;
int optPassword=0;

int ACflag=0;
int Uflag=0;

short CPMversion;

short DMsize;
short BLKsize;
short BLKcount;
short SPB;
short BlksFree;
long SecsFree;

unsigned short DSM;
int aUser[16];

int TotalDelEnts ;
int TotalUsedEnts ;
int TotalDTSEnts ;
int TotalPWSEnts ;
int TotalLBLEnts ;
int TotalFILEnts ;

int TotalDirs=0; 
int TotalBlks=0; 
int TotalFils=0;
int TotalPWSs=0;

/* short bdoshl(int func, int arg); */
/* char bdos(int func, int arg); */

struct cpmListEntry
{
	uchar dr;
	uchar usr;
	char  name[8];
	char  ft[3];
	unsigned short BlkCnt;
	unsigned short DirCnt;
	unsigned short ExtCnt;
	struct	DTS ACdts;
	struct	DTS Udts;
	char pw[8];
	uchar pm;
}
struct cpmListEntry  tListEntry;
struct cpmListEntry * ptrListEntry;
struct cpmListEntry **ptrList;
int NextAvail=-1;

struct CPMfcbLabel DiskLabel;

struct CPMfcb srcFCB;
struct CPMfcb * ptrFCB;

struct CPMfcb cfsFCB;

struct CPMdpb * ptrDPB;

struct RegisterSet Regs;

void usage(int pErr)
{
  fprintf(stderr, "Usage: %s [-a] [-s] [-b] [-f|-e] [-d] [-u|c] [-w|-l] [-v|-q] [<AFN>]\n", ptrInvoked);
  fprintf(stderr, " <AFN>= [[<d>[[:]<u>]]:][<filename>[.<ext>]]\n");
  fprintf(stderr, " -a All Users, -w Wide, -l Long, -v Verbose, -q Quiet -p Show Passwords\n");
  fprintf(stderr, " -s Sorted, -b by Blocks, -f by Filename, -e by Ext\n");
  fprintf(stderr, " -d by Date, - u by Update, -c by Create/Access\n");
  exit(pErr);
}

void GetOptions(int argc, char * argv[], char * env[])
{
int i;
int j;
char c1,c0;

  for(i = 1; i < argc; i++)
    {
	c0=argv[i][0];
	if (c0 == '-')
	{
	for (j=1 ; j<strlen(argv[i]) ; j++)
		{
		c1=argv[i][j];

		if(c1 == 'L')optLong=1;	
		else if(c1 == 'W')optLong=0;
		else if(c1 == 'A')optAll=1;
		else if(c1 == 'S')optSort=1;
		else if(c1 == 'C'){optUorCdts=0;optSort=1;optDate=1;}
		else if(c1 == 'U'){optUorCdts=1;optSort=1;optDate=1;}
		else if(c1 == 'D'){optSort=1;optDate=1;}
		else if(c1 == 'F'){optFE=0;optSort=1;}
		else if(c1 == 'E'){optFE=1;optSort=1;}
		else if(c1 == 'B'){optBlkSize=1;optSort=1;}
		else if(c1 == 'P'){optPassword=1;optLong=1;}
		else if(c1 == 'V')optVerbose=1;	
		else if(c1 == 'Q')optVerbose=0;	
		else if((c1 == 'H') || (c1 == '?'))usage(0);
		else	{
			fprintf(stderr, "Unknown option %s\n", argv[i]);
			usage(1);
			}
		} /* for j */
	}
	else	ptrDirName = argv[i];
   }    /* for i */
}


int AllocList(long pCount)
{
int k;
short sz;

struct cpmListEntry * tempPtrListEntry;
	NextAvail=0;
	ptrList=(struct cpmListEntry **)calloc(pCount , sizeof(struct cpmListEntry **));
	if (ptrList==0)
	{
	fprintf (stderr,"Out of Memory");
	exit(1);	
	}

	sz=sizeof(struct cpmListEntry);
/*	sz-=8;  */
/*	if (TotalDTSEnts==0) sz-=8; */

	if( (TotalDTSEnts==0) && ( (TotalPWSEnts==0) || (optPassword==0) ) )sz-=17; 
	if( (TotalDTSEnts!=0) && ( (TotalPWSEnts==0) || (optPassword==0) ) )sz-=9; 

	for (k=0; k<pCount; k++)
	{

		tempPtrListEntry=(struct cpmListEntry *)calloc(1 , sz);
		if (tempPtrListEntry==0)
		{
		fprintf (stderr,"Out of Memory");
		exit(1);	
		}

		ptrList[k]=tempPtrListEntry;
	}
}

int FreeList(long pCount)
{
int k;
struct cpmListEntry * tempPtrListEntry;

	for (k=0;k<pCount;k++)
	{
		tempPtrListEntry=ptrList[k];
		free (tempPtrListEntry);
		/* free (*(ptrList+(k*sizeof(struct cpmListEntry *)))); */
	}
	free (ptrList);
	NextAvail=-1;
}

int Cmp7bits(char pC1, char pC2)
{
 pC1 &= 0x7f;
 pC2 &= 0x7f;
 if( (pC1 == pC2) || (pC1 == '?') || (pC2  == '?') ) return(0);
 if (pC1  < pC2) return(-1);
 if (pC1  > pC2) return(1);

}

int memcmp7bits(char * pBuf1, char * pBuf2, short pCount)
{
int i;
int cRTN;
	for (i=0; i<pCount; i++)
	{
	if ( (cRTN = Cmp7bits( pBuf1[i], pBuf2[i] ))!=0 ) return( cRTN );
	}
return(0);
}

int FindInList(struct CPMfcb * pFCB)
{
struct cpmListEntry * tempPtrListEntry;
int j;
	for (j=0;j<=NextAvail;j++)
	{
		tempPtrListEntry=ptrList[j];
		/* if(( tempPtrListEntry->usr != pFCB->dr) || ( (tempPtrListEntry->usr | 0x10) != pFCB->dr)) continue; */
		if( memcmp7bits( tempPtrListEntry->name, pFCB->name, 8) !=0 ) continue;
		if( memcmp7bits( tempPtrListEntry->ft, pFCB->ft, 3) !=0 ) continue;
		return(j);
	}
return (-1);
}

int cmpFCB (struct CPMfcb * pFCB1,struct CPMfcb * pFCB2)
{
	return( memcmp7bits( pFCB1->name, pFCB2->name, 11) ) ;
}

int cmpListEntry (struct cpmListEntry * pE1,struct cpmListEntry * pE2)
{
int cRTN;
	if ( (optDate==1) && (TotalDTSEnts>0) )
	{
	if (optUorCdts==0)
		{
		if ( (cRTN = cmpDTS( &pE1->Udts, &pE2->Udts ))!=0 ) return( cRTN );
		}
	else
		{
		if ( (cRTN = cmpDTS( &pE1->ACdts, &pE2->ACdts ))!=0 ) return( cRTN );
		}
	}
	if (optBlkSize==1)
		{
		if ( pE1->BlkCnt < pE2->BlkCnt ) return(-1);
		if ( pE1->BlkCnt > pE2->BlkCnt ) return(1);
		}

	if (optFE==0)
	if( (cRTN= memcmp7bits( pE1->name, pE2->name, 8)) !=0 ) return( cRTN );

	if( (cRTN= memcmp7bits( pE1->ft, pE2->ft, 3)) !=0 ) return( cRTN );

	if (optFE==1) 
	if( (cRTN= memcmp7bits( pE1->name, pE2->name, 8)) !=0 ) return( cRTN );

return (0);
}

void Sort()
{
struct cpmListEntry * tempPtrListEntry;
int t,s;
for (t=0 ; t < NextAvail-1 ; t++)
 for (s=t+1 ; s < NextAvail ; s++)
  if ( cmpListEntry (ptrList[t],ptrList[s]) > 0 )
   {
    tempPtrListEntry=ptrList[t];
    ptrList[t]=ptrList[s];
    ptrList[s]=tempPtrListEntry;
   }
}

int memcpyor(char * pS1, char * pS2, int pCount)
{
int i;
for (i=0 ; i<pCount; i++)pS1[i]|=pS2[i];
}

int AddToList(struct CPMfcb * pFCB,unsigned char * pDMA,char paRTN)
{
struct cpmListEntry * tempPtrListEntry;
int i;
int Rtn;
struct CPMsfcb * sPtr;
struct CPMxfcb * pwPtr;

if (NextAvail != -1)
	{
		Rtn=FindInList(pFCB);

		if (Rtn!=-1)
			tempPtrListEntry=ptrList[ Rtn ];
		else
		{
			tempPtrListEntry=ptrList[ NextAvail ];
			tempPtrListEntry->usr = pFCB->dr;
			memcpyor(tempPtrListEntry->name,pFCB->name,11);
			NextAvail++;
		}
	if ( (pFCB->dr >15) && (pFCB->dr <32) )/* password entry */
		{
		if (optPassword==1) 
			{
			pwPtr=(struct CPMxfcb *)(pFCB);
			/* memcpy (tempPtrListEntry->pw, pwPtr->pw,8); */

			for (i=7;i>=0;i--) tempPtrListEntry->pw[7-i] = pwPtr->pw[i] ^ pwPtr->pd ;

			tempPtrListEntry->pm = pwPtr->pm;
			}
		}
	else /* not password entry */
		{
		if ( ((pFCB->ex & 0x1f) == 0) && ((pFCB->exh & 0x3f) == 0) ) 
			{
			memcpyor(tempPtrListEntry->name,pFCB->name,11); /* to ensure attrib are set */
			if  (TotalDTSEnts!=0)
				{
				sPtr=(struct CPMsfcb *)(pDMA +96);
				tempPtrListEntry->ACdts = sPtr->Stamps[paRTN].ACdts; 
				tempPtrListEntry->Udts = sPtr->Stamps[paRTN].Udts;
				}
			}

		if (DMsize==8)
			{for (i=0;i<16;i++) if (pFCB->dm[i] != 0) tempPtrListEntry->BlkCnt++;}
		else
			{for (i=0;i<8;i++) if ((pFCB->dm[i*2] != 0) || (pFCB->dm[(i*2)+1] != 0)) tempPtrListEntry->BlkCnt++;}
		}

		tempPtrListEntry->DirCnt++;
		return (tempPtrListEntry->DirCnt);
	}
else
	return (NextAvail);
}


int CountFiles(int pDisk, int pUser, struct CPMfcb* pCPMfcb)
{
char aRTN;

int tempDR;
int FilesCount=0;
int i;

struct CPMfcb * tempPTR;
struct CPMfcb srcFCB;

TotalDelEnts=0;
TotalUsedEnts=0;
TotalPWSEnts=0;
TotalDTSEnts=0;
TotalLBLEnts=0;
TotalFILEnts=0;

for(i = 0 ; i < 16 ; i++) aUser[i]=0;

InitFCB (&srcFCB,' ');
memcpy(&srcFCB, pCPMfcb, 12);
srcFCB.dr='?'; 

aRTN=FindFirst(&srcFCB);

while (aRTN !=-1)
	{
 	if (aRTN!=-1)
		{ 	tempPTR=(struct CPMfcb *)(0x0080+(aRTN*32));
			tempDR=tempPTR->dr;
			/* fprintf(stderr,"ptr= %x, dr=%d aRTN=%d\n",tempPTR,tempDR,aRTN); */
			/* PrintFCB((struct CPMfcb *)(0x0080+(aRTN*32)),0); */
			if (tempDR==0xe5) TotalDelEnts++;
			if (tempDR==0x20) 
			{
				memcpy( &DiskLabel,tempPTR, 32);
				if ((DiskLabel.dl & 0x40)!=0)ACflag=1;
				if ((DiskLabel.dl & 0x20)!=0)Uflag=1;
				if ((DiskLabel.dl & 0x10)!=0)ACflag=1;
				TotalLBLEnts++;
			}
			if (tempDR==0x21) TotalDTSEnts++;
			if ( (tempDR>=0x10)&&(tempDR<0x20) )TotalPWSEnts++;
			if ( (tempDR>=0x0)&&(tempDR<0x10) ){TotalFILEnts++;aUser[tempDR]++;}
			if (tempDR==pUser) FilesCount++;	/* this counts too many files( ='s TotalFILEnts) */
		}
 	aRTN=FindNext(&srcFCB);
	}
return (FilesCount);
}

int ProcessFiles(int pDisk, int pUser, struct CPMfcb* pCPMfcb)
{
char aRTN;
int lRTN;

int FilesCount=0;
int tempDR;

struct CPMfcb * tempPTR;
struct CPMfcb srcFCB;

InitFCB (&srcFCB,' ');
memcpy(&srcFCB, pCPMfcb, 12);
srcFCB.dr='?'; 

aRTN=FindFirst(&srcFCB);

while (aRTN !=-1)
	{
 	if (aRTN!=-1)
		{ 	tempPTR=(struct CPMfcb *)(0x0080+(aRTN*32));
			tempDR=tempPTR->dr;
			/* fprintf(stderr,"ptr= %x, dr=%d \n",tempPTR,tempDR); */
			if ( ( (pUser == tempDR) || ((pUser | 0x10) == tempDR) ) && (cmpFCB(tempPTR,&srcFCB)==0) )
			{
				lRTN=AddToList(tempPTR,(unsigned char *)0x0080,aRTN);
				if ( (lRTN==1)||(lRTN==-1) ) FilesCount++;
			}
 			/* PrintFCB((struct CPMfcb *)(0x0080+(aRTN*32)),0); */	
		}
 	aRTN=FindNext(&srcFCB);
	}
return (FilesCount);
}

int PrintDTSs(struct cpmListEntry * pPtrListEntry)
{
char tStr[20];
if (ACflag==1)
	{
	dts2str( &pPtrListEntry->ACdts ,tStr );
	fprintf( stdout,"%s ", tStr);
	}
if (Uflag==1)
	{
	dts2str( &pPtrListEntry->Udts ,tStr );
	fprintf( stdout,"%s ", tStr);
	}
}

int PrintLabel()
{
int i;
char tStr[20];
	fprintf(stdout,"\nDisk Label = ");
	for (i=0;i<8;i++)fprintf( stdout,"%c",DiskLabel.name[i] & 0x7f );
	fprintf(stdout,".");
	for (i=0;i<3;i++)fprintf( stdout,"%c",DiskLabel.ft[i] & 0x7f );

	fprintf(stdout,"    Password=");
	for (i=7;i>=0;i--)fprintf( stdout,"%c",DiskLabel.pw[i] ^ DiskLabel.pd );

	fprintf(stdout,"\n\n    ");
	dts2str( &DiskLabel.ACdts ,tStr );
	fprintf( stdout," %s ", tStr);
	dts2str( &DiskLabel.Udts ,tStr );
	fprintf( stdout," %s ", tStr);

	if ((DiskLabel.dl & 0x80)!=0)fprintf(stdout," Protected ");
	if ((DiskLabel.dl & 0x10)!=0)fprintf(stdout," Create ");
	if ((DiskLabel.dl & 0x40)!=0)fprintf(stdout," Access ");
	if ((DiskLabel.dl & 0x20)!=0)fprintf(stdout," Update ");
	if ((DiskLabel.dl & 0x01)!=0)fprintf(stdout," Labeled ");

	fprintf(stdout,"\n");

}

int Print()
{
struct cpmListEntry * tempPtrListEntry;

int i,j;
int cUser, cBlks, cDirs,  cExts;
int tBlks=0, tDirs=0;

for (j=0; j<NextAvail;j++)
	{
		tempPtrListEntry=ptrList[j];
		cUser=tempPtrListEntry->usr;
		cBlks=tempPtrListEntry->BlkCnt;
		cDirs=tempPtrListEntry->DirCnt;
		cExts=tempPtrListEntry->ExtCnt;

		tBlks+=cBlks; tDirs+=cDirs;

		TotalDirs+=cDirs; TotalBlks+=cBlks; TotalFils++; 

		if (optLong==1)
		 {
			fprintf(stdout,"\n%4d %5d ", cDirs ,cBlks);
		 	if (TotalDTSEnts!=0) PrintDTSs(tempPtrListEntry);
		 	fprintf(stdout,"%2d:", cUser);
		 }
		else
		 {if ((j % 5)==0)fprintf(stdout,"\n");else fprintf(stdout," : ");}

		for (i=0;i<8;i++)fprintf( stdout,"%c",tempPtrListEntry->name[i] & 0x7f );
		fprintf(stdout,".");
		for (i=0;i<3;i++)fprintf( stdout,"%c",tempPtrListEntry->ft[i] & 0x7f );

		if (optLong==1)
		{
		if ((tempPtrListEntry->ft[0] & 0x80)!=0 )fprintf(stdout," (R/O)");
		if ((tempPtrListEntry->ft[1] & 0x80)!=0 )fprintf(stdout," (SYS)");
		if ((tempPtrListEntry->ft[2] & 0x80)!=0 )fprintf(stdout," (ARC)");
		if ((tempPtrListEntry->name[1] & 0x80)!=0 )fprintf(stdout," (PUB)");
		if ((tempPtrListEntry->name[2] & 0x80)!=0 )fprintf(stdout," (DTS)");
		if ((tempPtrListEntry->name[7] & 0x80)!=0 )fprintf(stdout," (WHL)");
		}
		if ( (optPassword) && (TotalPWSEnts > 0) && (tempPtrListEntry->pm != 0 ) )
		{
		fprintf(stdout," PW(");
		if ((tempPtrListEntry->pm & 0x80)!=0 )fprintf(stdout,"R");
		if ((tempPtrListEntry->pm & 0x40)!=0 )fprintf(stdout,"W");
		if ((tempPtrListEntry->pm & 0x20)!=0 )fprintf(stdout,"D");
		fprintf(stdout,")=");
		for (i=0;i<8;i++)fprintf( stdout,"%c",tempPtrListEntry->pw[i] );
		}
	}
fprintf(stdout,"\n\n Files = %d  Dir Ents Listed = %d  Blks Listed = %d \n",j,tDirs,tBlks);
}

int TallyOnes(uchar pByte,int pBits)
{
int t=0;
if (((pByte & 128)!=0)&& (pBits>0))t++;
if (((pByte & 64)!=0)&& (pBits>1))t++;
if (((pByte & 32)!=0)&& (pBits>2))t++;
if (((pByte & 16)!=0)&& (pBits>3))t++;
if (((pByte & 8)!=0)&& (pBits>4))t++;
if (((pByte & 4)!=0)&& (pBits>5))t++;
if (((pByte & 2)!=0)&& (pBits>6))t++;
if (((pByte & 1)!=0)&& (pBits>7))t++;
return(t);
}

int CountBits(uchar * pArray, int pMaxBits)
{
int i,t=0;
for (i=0;i<(pMaxBits/8);i++) {t+=TallyOnes(pArray[i],8);}
	if ( (pMaxBits%8)!=0 )t+=TallyOnes(pArray[i],pMaxBits%8);
	return (t);
}

int main(int argc, char * argv[], char * env[])
{
long FileEntries;
int cUser,cDisk;
int StartUpDrive;
int StartUpUser;
int Un,Ux;
int BlksUsed,BlksDir;
int TotalAvailEnts;

int i;
int nUser;
int RTN;

uchar * ptrALV;

CPMversion=GetCPMVERS();

if (CPMversion == 0x00) CPMversion=1;
else if ((CPMversion >= 0x20) && (CPMversion <0x30)) CPMversion=2;
else if ((CPMversion >= 0x30) && (CPMversion <0x40)) CPMversion=3;
else CPMversion=0;

if (CPMversion==1)
	{
	fprintf(stderr,"\n Not for CPM 1.x\n");
	exit(1);
	}

ptrInvoked="LS";

StartUpDrive=GetCURDISK();
StartUpUser=GetUSER();

GetOptions(argc,argv,env);

if (optVerbose==1)fprintf(stdout,"%s Version 1.1 for CPM-80\n",ptrInvoked);
/* if (optVerbose==1)fprintf(stdout,"   %s %s\n",ptrInvoked,ptrDirName); */

/* PrintFCB((struct CPMfcb *) 0x5c,1); */

InitFCB(&srcFCB,' ');
/* memcpy(&srcFCB,(void *) 0x5c,12); */
/* PrintFCB(&srcFCB,1); */

if (ptrDirName==0)
	nUser=-1;
else
	nUser=ParseDRU(&srcFCB,ptrDirName);

if (nUser<-1) {fprintf(stderr,"Bad User/Drive\n");usage(1);}
if (nUser==-1) nUser=StartUpUser;

if (ptrDirName==0)
	RTN=1;
else
	RTN=ParseFN(&srcFCB,ptrDirName,0);

if ( (RTN!=0) && (RTN!=1) ) {fprintf(stderr,"Bad Filename\n");usage (1);}
if ( (RTN==1) || (ptrDirName==0) )
{
 for (i=0;i<8;i++)srcFCB.name[i]='?';
 for (i=0;i<3;i++)srcFCB.ft[i]='?';
}

if ( srcFCB.dr != 0 ){cDisk=(srcFCB.dr)-1; Seldsk(cDisk);}else {cDisk=StartUpDrive;}

	ptrDPB=GetDPB();
	if (ptrDPB->BSH ==3) {BLKsize=1024;SPB=8;}
	if (ptrDPB->BSH ==4) {BLKsize=2048;SPB=16;}
	if (ptrDPB->BSH ==5) {BLKsize=4096;SPB=32;}
	if (ptrDPB->BSH ==6) {BLKsize=8192;SPB=64;}
	if (ptrDPB->BSH ==7) {BLKsize=16384;SPB=128;}
	BLKcount=(ptrDPB->DSM)+1;
	if (BLKcount > 256) DMsize=16; else DMsize=8;

	if (CPMversion==2)
		{
		ptrALV=GetALV();
		BlksUsed=CountBits(ptrALV,BLKcount);
		BlksFree=BLKcount-BlksUsed;
		}
	if (CPMversion==3)
		{
		SecsFree=GetFSP(cDisk,(char*)0x80);
		BlksFree=SecsFree/SPB;
		BlksUsed=BLKcount-BlksFree;
		}

	ptrALV=(uchar *)(&(ptrDPB->AL0));
	BlksDir=CountBits(ptrALV,16);

	if (optAll){Un=0;Ux=16;}else{Un=nUser;Ux=nUser+1;}

	for (cUser=Un;cUser<Ux;cUser++)
	{
		FileEntries = CountFiles(cDisk+1, cUser, &srcFCB);
		AllocList(FileEntries);

		FileEntries = ProcessFiles(cDisk+1, cUser, &srcFCB);

		if ((TotalLBLEnts>0) && (cUser==Un)) PrintLabel();

		if (FileEntries!=0)
	 	{
	 	fprintf (stdout,"\nDisk %c: User %d\n",cDisk+'A',cUser); 
		if (optSort==1) Sort();
		Print();
	 	}

		FreeList(FileEntries);
	}

	if (optAll==1)fprintf(stdout,"\n Total Files = %d  Total Dir Listed = %d  Total Blks Listed = %d \n",
			TotalFils,TotalDirs,TotalBlks);
if (optVerbose==1)
{
	if(CPMversion==3)
		{
		if (TotalDTSEnts!=0) TotalDTSEnts=((ptrDPB->DRM)+1)/4;
		}
	TotalUsedEnts=TotalLBLEnts + TotalPWSEnts + TotalFILEnts + TotalDTSEnts;
	TotalAvailEnts=(((ptrDPB->DRM)+1)- TotalUsedEnts);

	fprintf (stdout,"\n %d Total (%d byte) Blocks (%d Reserved)", BLKcount,BLKsize,BlksDir);

	fprintf (stdout," (%d Available) (%d Used)", BlksFree,BlksUsed);
	fprintf (stdout,"\n %d Total Directory Entries (%d Available) (%d Used) (%d Deleted)\n",
			(ptrDPB->DRM)+1, TotalAvailEnts, TotalUsedEnts,TotalDelEnts);
	fprintf (stdout,"    (%d Label) (%d File) (%d Passwords) (%d Date/Time) (%d Checked)\n", 
			TotalLBLEnts, TotalFILEnts, TotalPWSEnts,TotalDTSEnts,(ptrDPB->CKS)*4);

	fprintf(stdout," User Numbers with Files:" );
	/* for (i=0;i<16;i++) if (aUser[i]!=0)fprintf (stdout, " %d(%d)",i,aUser[i]); */
	for (i=0;i<16;i++) if (aUser[i]!=0)fprintf (stdout, " %d",i);
	fprintf (stdout, "\n");

	fprintf (stdout," %d System Tracks \n",ptrDPB->OFF);
}

if ( srcFCB.dr != 0 )Seldsk(StartUpDrive);
exit(0);
}
