home *** CD-ROM | disk | FTP | other *** search
- /*
- FILES.C -- list all files in system file table
-
- cl files.c
- cl -DFREEUP -Fefreeup.exe files.c
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <dos.h>
-
- #ifdef __TURBOC__
- #define ASM asm
- #else
- #define ASM _asm
- #endif
-
- typedef unsigned char BYTE;
- typedef unsigned USHORT;
- typedef unsigned long ULONG;
- typedef BYTE far *FP;
-
- #pragma pack(1)
-
- typedef struct file {
- USHORT num_handles, open_mode;
- BYTE fattr;
- USHORT dev_info; // includes drive number
- FP ptr;
- USHORT start_cluster, time, date;
- ULONG fsize, offset;
- USHORT rel_cluster, abs_cluster, dir_sector;
- BYTE dir_entry;
- BYTE filename[11];
- ULONG share_prev_sft;
- USHORT share_net_machine;
- USHORT owner_psp;
- // ...
- } file; // for DOS 3.x, 4.x
-
- typedef struct sysftab {
- struct sysftab far *next;
- USHORT num_files;
- file f[1];
- } SYS_FTAB;
-
- typedef struct {
- BYTE type;
- USHORT owner; /* PSP of the owner */
- USHORT size;
- BYTE unused[3];
- BYTE dos4[8];
- } MCB;
-
- void fail(char *s) { puts(s); exit(1); }
-
- #ifdef __TURBOC__
- #define GETVECT(intno) getvect(intno)
- #define ASM asm
- #else
- #define GETVECT(intno) _dos_getvect(intno)
- #define ASM _asm
- #endif
-
- #ifndef MK_FP
- #define MK_FP(seg,ofs) ((FP)(((ULONG)(seg) << 16) | (ofs)))
- #endif
-
- #define NEXT(mcb) (MK_FP(FP_SEG(mcb) + (mcb)->size + 1, 0))
-
- int belongs(FP vec, USHORT start, USHORT size)
- {
- USHORT seg = FP_SEG(vec);
- return (seg >= start) && (seg <= (start + size));
- }
-
- int is_psp(USHORT seg)
- {
- return ((((MCB far *) MK_FP(seg-1,0))->owner == seg) &&
- (*((USHORT far *) MK_FP(seg,0)) == 0x20CD));
- }
-
- /*
- Look for "orphaned" file handles: e.g., TSR>FOO.BAR or TSR>NUL
- will leave FOO.BAR or NUL entry in SFT, consuming file handle. If
- the PSP of the file's owner is COMMAND.COM, and if there's only
- one owner, then we decide it's an orphaned handle.
- */
- int orphan(file far *ff)
- {
- static command_com_psp = 0;
- if (! ff->num_handles)
- return 0;
- if (! command_com_psp) /* do just one time */
- {
- FP int2e = (FP) GETVECT(0x2E);
- MCB far *mcb;
- ASM mov ah, 52h
- ASM int 21h
- ASM mov ax, es:[bx-2]
- ASM mov word ptr mcb+2, ax
- ASM mov word ptr mcb, 0
- while (mcb->type != 'Z')
- if (belongs(int2e, FP_SEG(mcb), mcb->size))
- {
- command_com_psp = mcb->owner;
- break;
- }
- else
- mcb = (MCB far *) NEXT(mcb);
- }
- return ((ff->owner_psp == command_com_psp) &&
- (ff->num_handles == 1));
- }
-
- #define IS_AUX(s) ((s[0]=='A') && (s[1]=='U') && (s[2]=='X'))
- #define IS_CON(s) ((s[0]=='C') && (s[1]=='O') && (s[2]=='N'))
- #define IS_PRN(s) ((s[0]=='P') && (s[1]=='R') && (s[2]=='N'))
-
- main(void)
- {
- SYS_FTAB far *sys_filetab;
- file far *ff;
- int size;
- int i;
-
- ASM mov ah, 52h
- ASM int 21h
- ASM les bx, dword ptr es:[bx+4] /* ptr to list of DOS file tables */
- ASM mov word ptr sys_filetab, bx
- ASM mov word ptr sys_filetab+2, es
-
- /* DOS box of OS/2 1.x doesn't provide system file tbl */
- if (sys_filetab == (SYS_FTAB far *) -1L)
- fail("system file table not supported");
-
- switch (_osmajor)
- {
- case 2: size = 0x28; break;
- case 3: size = 0x35; break;
- default: size = 0x3b; break;
- }
-
- /* Perform sanity check: determine size of file structure
- empirically from difference between strings "CON" and
- "AUX." If this equals size computed via _osmajor, everything
- is fine. Otherwise, we reset size. */
- {
- FP p, q;
- int i;
- /* i=1000: set upper limit on string search in memory */
- for (p=(FP)sys_filetab->f, i=1000; i--, p++; )
- if (IS_AUX(p))
- break;
- if (! i) return 1;
- for (q=p, i=1000; i--, q++; )
- if (IS_CON(q))
- break;
- if (! i) return 1;
- /* size of file structure must equal span from AUX to CON */
- if (size != (q - p))
- {
- puts("size based on _osmajor looks wrong");
- size = q - p;
- }
- }
-
- printf("Filename Size Attr Handles Owner\n");
- printf("-------- ---- ---- ------- -----\n");
-
- do { /* FOR EACH SFT */
-
- /* FOR EACH ENTRY IN THIS SFT */
- for (i=sys_filetab->num_files, ff=sys_filetab->f;
- i--;
- ((FP) ff) += size)
- if (ff->num_handles)
- {
- if (_osmajor == 2)
- {
- // didn't bother with struct for DOS2
- FP ff2 = (FP) ff;
- printf("%.8Fs.", ff2 + 0x04);
- printf("%.3Fs\t", ff2 + 0x0c);
- printf("%10lu\t", *((ULONG far *) (ff2 + 0x13)));
- printf("%04X\t", ff2[0x02]);
- }
- else
- {
- printf("%.8Fs.", ff->filename);
- printf("%.3Fs\t", ff->filename + 8);
- printf("%10lu\t", ff->fsize);
- printf("%04X\t", ff->fattr);
- printf("%d\t", ff->num_handles);
- printf("%04X\t", ff->owner_psp);
- if (! is_psp(ff->owner_psp))
- printf("[NOT PSP]");
- if (orphan(ff))
- printf("[ORPHAN]");
- }
- #ifdef FREEUP
- // only DOS 3+
- if (! IS_AUX(ff->filename))
- if (! IS_CON(ff->filename))
- if (! IS_PRN(ff->filename))
- if (orphan(ff) || (! is_psp(ff->owner_psp)))
- {
- if (! (-- ff->num_handles)) // decrement owners
- printf(" [FREED]");
- else
- printf(" [NOW %d]", ff->num_handles);
- }
- #endif
- printf("\n");
- }
- sys_filetab = sys_filetab->next; /* FOLLOWED LINKED LIST... */
- } while (FP_SEG(sys_filetab) &&
- FP_OFF(sys_filetab) != (unsigned) -1); /* ...UNTIL END */
- return 0;
- }
-