Convert To PDF Text

実行の際は[pdftotext]をインストールする必要があります.
PDFの中を調べることがありまして, こんなプログラムを作ってしまいました.
誰得って分けではないけど自己満足で作ってしまいました.

ちなみに実行すると, コマンドを入力したディレクトリに[txt_pdf]というディレクトリを作り, その中に変換(改行スペースなし)したテキストを格納するプログラムです.
[pdftotext]でテキスト変換はできるのですが, テキストの中に空白があって思うように検索できなかったので, 無理やりつめて変換させました.
ソースコードは, [ctx.c] と [con.h] がありますので, 使う場合がありましたら同じところに入れてコンパイルしてください.

H25.1.8(Tue) Upadate
ロングオプションを対応
フラグを用いて動作の安定化
H25.3.8(Fri) Update
ソースコードの整頓

/* Cotnvert PDF to Text - ctx.c
 * Ver: 1.3.0
 * Author: Jin
 * ***************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <getopt.h>

#define  ON_MODE 1
#define OFF_MODE 0

static struct option long_opt[] = {
    {"convert", optional_argument, 0, 'c'},
    {"delete",        no_argument, 0, 'd'},
    {"help",          no_argument, 0, 'h'},
    {"version",       no_argument, 0, 'v'},
    {0, 0, 0, 0},
};

extern void comv_pdf(const char *name);
extern void delete_file(void);
extern char getkey(void);

void print_help(void);
void print_version(void);
void ctx_err(const char *path);

int main(int argc, char **argv)
{
    int opt, opt_index, i;
    int f_help, f_del, f_ver, f_conv;
    char c;
    f_help = f_del = f_ver = OFF_MODE;
    f_conv = ON_MODE; /* Default */

    if(argc < 2) {
        print_help();
        exit(EXIT_FAILURE);
    }

    while((opt = getopt_long(argc, argv, "cdhva:",
                    long_opt, &opt_index)) != EOF) {
        switch (opt) {
            case 'h':
                f_help = ON_MODE;
                break;
            case 'v':
                f_ver = ON_MODE;
                break;
            case 'd':
                f_del  = ON_MODE;
                f_conv = OFF_MODE;
                break;
            case 'c':
                f_conv = ON_MODE;
                break;
            case '?':
                f_help = ON_MODE;
                break;
            default:
                f_help = ON_MODE;
                break;
        }
    }
    if(f_help || f_ver) {
        if(f_help) print_help();
        if(f_ver) print_version();
        exit(EXIT_SUCCESS);
    }

    else if(f_conv) {
        /* pdftotext を用いた変換関数 */
        if(argc == optind)
            ctx_err(argv[0]);

        for(i = optind; i < argc; i++) {
            if(access(argv[i], F_OK) == EOF) {
                fprintf(stderr, "`%s`が存在しません.\n", argv[i]);
                exit(EXIT_FAILURE);
            }

            else comv_pdf(argv[i]);
        }
    }

    else if(f_del) {
        /* unlink 関数 */
        if(access("./txt_pdf", F_OK) == EOF) {
            printf("ディレクトリが存在しません.\n");
            exit(EXIT_FAILURE);
        }

        printf("[txt_pdf]を削除します.\n");
        do {
            printf("[y / n] : ");
            fflush(stdout);
            c = getkey();
            if(c != 'y' && c != 'n')
                printf("\n無効な操作\n");
            else if(c == 'y')
                delete_file();
        } while(c != 'y' && c != 'n');
        putchar('\n');
    }

    else 
        /* 想定外のエラー */
        ctx_err(argv[0]);

    return 0;
}

void print_help(void) {
    char *dir = "txt_pdf";
    char *nowdir;

    nowdir = (char *)calloc(sizeof(char), 128);

    printf("Usage: ./ctx [Option] [PDF File]...\n");

    printf("このプログラムはPDFに含まれるテキストを,\n");
    printf("改行と空白を削除しテキストファイルに転写します。\n\n");
    printf("なお, 製作されたファイルは, [%s] 中に新しく [%s] を作り,\n", getcwd(nowdir, 128), dir);
    printf("その中に入っております。\n\n");
    printf("\t -c, --convert: PDFをテキストデータにします.\n");
    printf("\t -d,  --delete: 作成したディレクトリをテキストデータを削除します.\n");
    printf("\t -h,    --help: ヘルプを表示します.\n");
    printf("\t -v, --version: バージョンを表示します.\n\n");

    free(nowdir);
}

void print_version(void) {
    printf("Version: 1.3.0\n");
    printf("Copyright (C) 2013 Jin.\n");
}

void ctx_err(const char *path) {
    printf("%s: 引数がありません.\n", path);
    printf("詳しくは`%s --help`を実行してください.\n", path);
    exit(1);
}
/* funcs.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

#define PATH "./txt_pdf"

extern void open_create(const char *name);

void delete_file(void) {
    DIR *dopen;
    struct dirent *read_dir;
    char *dir;

    dir = (char *)calloc(sizeof(char), 128);

    if(getcwd(dir, 128) == NULL) {
        perror("getcwd(3)");
        free(dir);
        exit(EXIT_FAILURE);
    }

    if(access(PATH, F_OK) == EOF) {
        printf("ディレクトリが存在しません.\n");
        free(dir);
        exit(EXIT_FAILURE);
    }

    if(rmdir(PATH) == EOF) {
        if((dopen = opendir(PATH)) == NULL) {
            perror("opendir(3)");
            free(dir);
            printf("`%s`のオープンに失敗.\n", PATH);
            exit(EXIT_FAILURE);
        }

        else if(chdir(PATH) == EOF) {
            perror("chdir(2)");
            free(dir);
            closedir(dopen);
            exit(EXIT_FAILURE);
        }

        while((read_dir = readdir(dopen)) != NULL) {
            if(strcmp(read_dir->d_name, ".") != 0 &&
                        strcmp(read_dir->d_name, "..") != 0) {
                if(unlink(read_dir->d_name) == EOF) {
                    perror("unlink(2)");
                    free(dir);
                    closedir(dopen);
                    exit(EXIT_FAILURE);
                }
            }
        }

        closedir(dopen);
        chdir(dir);

        if(rmdir(PATH) == EOF) {
            perror("rmdir(2)");
            free(dir);
            exit(EXIT_FAILURE);
        }
    }

    free(dir);
}

void comv_pdf(const char *name) {
    pid_t pid;
    int status;

    if(access(PATH, F_OK) == EOF) {
        if(mkdir(PATH, 0755) == EOF) {
            perror("mkdir(2)");
            exit(EXIT_FAILURE);
        }
    }

    if((pid = fork()) == EOF) {
        perror("fork(2)");
        exit(EXIT_FAILURE);
    }

    else if(pid == 0)
        /* Child Process */
        execlp("pdftotext", "pdftotext", name, NULL);

    else if(pid > 0) {
        /* Parent Process */
        waitpid(pid, &status, 0);
        open_create(name);
    }
}

char getkey(void) {
    char c;
    struct termios tty, save;
    ioctl(0, TCGETS, &tty);
    save = tty;
    tty.c_lflag = ~ICANON;
    tty.c_cc[VMIN]  = 1;
    tty.c_cc[VTIME] = 0;
    ioctl(0, TCSETS, &tty);

    if(read(0, &c, 1) == EOF) {
        perror("read(2)");
        ioctl(0, TCSETS, &save);
        exit(EXIT_FAILURE);
    }
    else {
        ioctl(0, TCSETS, &save);
        write(1, &c, 1);
        return c;
    }
}
/* open.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PATH "./txt_pdf"

void free_str(char *str1, char *str2);
void comv_str(const char *name, char *new_name);

void open_create(const char *name) {
    int fd_old, fd_new;
    char c;
    char *dir; /* DirName BackUp */
    char *txt_name; /* Convert Text Name */

    dir      = (char *)calloc(sizeof(char), 128);
    txt_name = (char *)calloc(sizeof(char), 64);

    comv_str(name, txt_name);

    if(getcwd(dir, 128) == NULL) {
        perror("getcwd(3)");
        free_str(dir, txt_name);
        exit(EXIT_FAILURE);
    }

    if((fd_old = open(txt_name, O_RDONLY)) == EOF) {
        perror("open(2)-RD");
        free_str(dir, txt_name);
        exit(EXIT_FAILURE);
    }

    if(chdir(PATH) == EOF) {
        perror("chdir(3)");
        close(fd_old);
        free_str(dir, txt_name);
        exit(EXIT_FAILURE);
    }

    else if((fd_new = open(txt_name, O_WRONLY | O_CREAT, 0666)) == EOF) {
        perror("open(2)-WR");
        close(fd_old);
        free_str(dir, txt_name);
        exit(EXIT_FAILURE);
    }

    while(read(fd_old, &c, 1) > 0) {
        if(c != '\n' && c != ' ')
            write(fd_new, &c, 1);
    }

    chdir(dir);
    unlink(txt_name);
    free_str(dir, txt_name);
    close(fd_old);
    close(fd_new);
}

void free_str(char *str1, char *str2) {
    free(str1);
    free(str2);
}

void comv_str(const char *name, char *new_name) {
    int i, j;
    strcpy(new_name, name);
    char *exten = "txt";

    for(i = strlen(name) - 3, j = 0; i < strlen(name); i++, j++) {
        new_name[i] = exten[j];
    }

}
実行例:

$ gcc main.c open.c funcs.c -c -g -Wall
$ gcc -o ctx main.o open.o funcs.o -g -Wall

$ ./ctx *.pdf