_NT-STYLE THREADS FOR MS-DOS_ by Al Williams Listing One /* XPRUNE.C -- (T)NT directory removal -- Williams */ #include #include #include #include #include "tntsem.h" /* Arguments to thread function */ struct pkt { char *dir; TNT_SEM sem; }; void erase_all(struct pkt *); void del(char *,WIN32_FIND_DATA *,TNT_SEM); /* Delete file of directory */ void del(char *dir,WIN32_FIND_DATA *fd,TNT_SEM wait) { char path[MAX_PATH]; strcpy(path,dir); strcat(path,fd->cFileName); if (fd->dwFileAttributes!=FILE_ATTRIBUTE_DIRECTORY) { if (!DeleteFile(path)) { printf("Failed to delete file: %s\n",path); } } else { /* Build arguments to new thread */ struct pkt *packet=malloc(sizeof(struct pkt)); if (fd->cFileName[0]=='.') return; /* skip . and .. */ strcat(path,"\\"); packet->dir=strdup(path); packet->sem=wait; /* Bump semaphore count up by 1 */ sem_signal(wait,1); /* Launch new thread to delete subdirectory */ #ifndef SINGLE _beginthread(erase_all,8192,packet); #else erase_all(packet); #endif } } void erase_all(struct pkt *packet) { char path[MAX_PATH]; WIN32_FIND_DATA fd; HANDLE findhandle; BOOL found=TRUE; TNT_SEM wait; /* Wait on subthreads before deleting directory */ wait=sem_create(0); strcpy(path,packet->dir); strcat(path,"*.*"); /* Find all files and call del() */ for (findhandle=FindFirstFile(path,&fd); found; found=FindNextFile(findhandle,&fd)) { del(packet->dir,&fd,wait); } /* Wait */ sem_wait(wait,-1); sem_delete(wait); /* Remove backslash */ packet->dir[strlen(packet->dir)-1]='\0'; if (!RemoveDirectory(packet->dir)) { printf("Failed to remove directory: %s\n",packet->dir); if (GetLastError()==5) printf("Directory probably contains hidden or read only files.\n"); }; /* Clean up malloc'd pointers */ free(packet->dir); free(packet); /* Signal parent thread that we are done */ sem_signal(packet->sem,-1); } main(int argc,char *argv[]) { int i; struct pkt *p; TNT_SEM sem; char dir[MAX_PATH]; if (argc>=2) { strcpy(dir,argv[1]); if (dir[strlen(dir)-1]!='\\') strcat(dir,"\\"); p=malloc(sizeof(struct pkt)); p->dir=strdup(dir); p->sem=sem=sem_create(1); erase_all(p); sem_wait(sem,-1); sem_delete(sem); } else { printf("XPRUNE by Al Williams\nUsage:\n" "XPRUNE directory_name\n\nRemoves directory and " "all files within it."); } } [Listing Two] /* TNT semaphores -- usable with NT, too. Al Williams */ #ifndef _TNT_SEM #define _TNT_SEM typedef struct _tnt_sem { int count; /* count */ HANDLE event; /* semaphore wait event */ CRITICAL_SECTION cs; /* controls access to count */ } *TNT_SEM; TNT_SEM sem_create(int count); void sem_delete(TNT_SEM p); int sem_signal(TNT_SEM p,int how); int sem_wait(TNT_SEM p,int timeout); #endif [Listing Three] /* TNT semaphores -- usable with NT, too. Al Williams */ #include #include #include "tntsem.h" /* Create a semaphore */ TNT_SEM sem_create(int count) { TNT_SEM p=(TNT_SEM)malloc(sizeof(struct _tnt_sem)); if (p) { p->count=count; p->event=CreateEvent(NULL,TRUE,count==0?TRUE:FALSE,NULL); if (!p->event) { free(p); p=NULL; } } InitializeCriticalSection(&p->cs); return p; } /* Destroy semaphore */ void sem_delete(TNT_SEM p) { if (p&&p->event) CloseHandle(p->event); if (p) DeleteCriticalSection(&p->cs); free(p); } /* Signal a semaphore how == -x ; decrement by x how == 0 ; read semaphore count how == x ; increment by x */ int sem_signal(TNT_SEM p,int how) { if (!p) return 0; EnterCriticalSection(&p->cs); p->count+=how; if (p->count) ResetEvent(p->event); else SetEvent(p->event); LeaveCriticalSection(&p->cs); return p->count; } /* Wait for semaphore to reach zero count */ int sem_wait(TNT_SEM p,int timeout) { return WaitForSingleObject(p->event,timeout); }