Listing 3: The Delete Directory program using the setjmp/longjmp mechanism

/* ddir3.c:  Remove subdirectory tree */

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <dir.h>

#include <setjmp.h>

/* Calling environment buffer (global!) */
jmp_buf env;

main(volatile int argc, volatile char **argv)
{
    volatile char *old_path = getcwd(NULL,64);
    void rd(char *);

    switch(setjmp(env))     /* returns 0 once */
    {
        case BAD_DIR:
            puts("Invalid directory");
            break;
        case DIR_OPEN_ERR:
            puts("Error opening directory");
            break;
        case FILE_DEL_ERR:
            puts("Error deleting file");
            break;
        case DIR_DEL_ERR:
            puts("Error deleting directory");
            break;
    }

    /* Delete the directories (re-entrant!) */
    while (--argc)
        rd((char *) *++argv);

    chdir((char *) old_path);
    return 0;
}

void rd(char* dir)
{
    void erase_dir(void);

    if (chdir(dir))
        longjmp(env,BAD_DIR);
    system("del /q *.* > nul");
    erase_dir();

    chdir("..");
    if (rmdir(dir))
        longjmp(env,DIR_DEL_ERR);
}
void erase_dir(void)
{
    DIR *dirp;
    struct dirent *entry;
    struct stat finfo;
    
    if ((dirp = opendir(".")) == NULL)
        longjmp(env,DIR_OPEN_ERR);

    while ((entry = readdir(dirp)) != NULL)
    {
        if (entry->d_name[0] == '.')
            continue;
        stat(entry->d_name,&finfo); if (finfo.st_mode & S_IFDIR)
            rd(entry->d_name);      
        else
        {
            chmod(entry->d_name,S_IWRITE);
            if (unlink(entry->d_name))
            {
                closedir(dirp);
                longjmp(env,FILE_DEL_ERR);
            }
        }
    }
    closedir(dirp);
}
//End of File