/*
* "$Id: nmzmail.c,v 1.9 2005/05/23 18:47:18 hofmann Exp $"
*
* flpsed program.
*
* Copyright 2004,2005 by Johannes Hofmann
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <libgen.h>
#include <strings.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "util.h"
#include "../config.h"
char *get_query();
int create_result_dir(char *nmz_result);
int generate_result(char *query, char *nmz_index,
char *nmz_result, int result_limit);
void build_index(char *nmz_index, char *mail_dirs[], int num_mail_dirs);
void usage();
#define BUF_LEN 1024
#define MAX_MAIL_DIRS 32
int
main(int argc, char **argv) {
char *query, *home, *result = 0, **my_argv;
int c, errflg = 0, count, index_flag = 0, num_mail_dirs = 0, my_argc, i;
char nmz_base[BUF_LEN];
char nmz_result[BUF_LEN];
char nmz_index[BUF_LEN];
char *mail_dirs[MAX_MAIL_DIRS];
int result_limit = 2000;
home = getenv("HOME");
if (!home) {
perror("getenv");
exit(1);
}
snprintf(nmz_base, sizeof(nmz_base), "%s/.nmzmail", home);
mkdir(nmz_base, 0777);
while ((c = getopt(argc, argv, "b:r:im:n:")) != -1) {
switch (c) {
case 'b':
strncpy(nmz_base, optarg, sizeof(nmz_base));
break;
case 'r':
result = optarg;
break;
case 'i':
index_flag = 1;
break;
case 'm':
fprintf(stderr, "Warning: -m option is deprecated.\n");
if (num_mail_dirs < MAX_MAIL_DIRS) {
mail_dirs[num_mail_dirs++] = optarg;
} else {
fprintf(stderr,
"maximum number (%d) of mail directories exceeded.\n",
MAX_MAIL_DIRS);
}
break;
case 'n':
result_limit = atoi(optarg);
if (result_limit <= 0) {
errflg++;
}
break;
case '?':
errflg++;
}
}
if (errflg) {
usage();
exit(1);
}
my_argc = argc - optind;
my_argv = argv + optind;
for (i=0; i<my_argc; i++) {
if (num_mail_dirs < MAX_MAIL_DIRS) {
mail_dirs[num_mail_dirs++] = my_argv[i];
} else {
fprintf(stderr,
"maximum number (%d) of mail directories exceeded.\n",
MAX_MAIL_DIRS);
break;
}
}
if (result) {
strncpy(nmz_result, result, sizeof(nmz_result));
} else {
snprintf(nmz_result, sizeof(nmz_result), "%s/result", nmz_base);
}
snprintf(nmz_index, sizeof(nmz_index), "%s/index", nmz_base);
if (index_flag) {
build_index(nmz_index, mail_dirs, num_mail_dirs);
} else {
query = get_query(nmz_base);
if (query == NULL) {
fprintf(stderr, "Could not get query string.\n");
exit(1);
}
if (create_result_dir(nmz_result) != 0) {
fprintf(stderr, "Could not setup result directory %s.\n", nmz_result);
exit(1);
}
count = generate_result(query, nmz_index, nmz_result, result_limit);
printf("%d matches.\n", count);
}
exit(0);
}
char *
get_query(char *nmz_base) {
char *query;
char nmz_history[BUF_LEN];
snprintf(nmz_history, sizeof(nmz_history), "%s/history", nmz_base);
using_history();
read_history(nmz_history);
query = readline("Query: ");
if (query != NULL) {
add_history(query);
write_history(nmz_history);
history_truncate_file(nmz_history, 50);
}
return query;
}
int
remove_links(char *dir) {
DIR *dirp;
struct dirent *dp;
struct stat stat_buf;
int retval = 0;
char buf[BUF_LEN];
dirp = opendir(dir);
if (!dirp) {
if (errno == ENOENT) {
return 0;
} else {
perror("opendir");
return 1;
}
}
while(dirp) {
errno = 0;
if ((dp = readdir(dirp)) != NULL) {
snprintf(buf, sizeof(buf), "%s/%s", dir, dp->d_name);
if (lstat(buf, &stat_buf) != 0) {
perror("lstat");
} else {
if ((stat_buf.st_mode&S_IFMT)==S_IFLNK) {
unlink(buf);
} else if ((stat_buf.st_mode&S_IFMT)!=S_IFDIR) {
fprintf(stderr, "%s is not a symbolic link; aborting.\n", buf);
retval = 1;
break;
}
}
} else if (errno != 0) {
perror("readdir");
retval = 1;
break;
} else {
break;
}
}
closedir(dirp);
return retval;
}
int
create_result_dir(char *nmz_result) {
char buf[BUF_LEN];
snprintf(buf, sizeof(buf), "%s/cur", nmz_result);
if (remove_links(buf) != 0) {
return 1;
}
mkdir(nmz_result, 0777);
snprintf(buf, sizeof(buf), "%s/cur", nmz_result);
mkdir(buf, 0777);
snprintf(buf, sizeof(buf), "%s/new", nmz_result);
mkdir(buf, 0777);
snprintf(buf, sizeof(buf), "%s/tmp", nmz_result);
mkdir(buf, 0777);
return 0;
}
int
generate_result(char *query, char *nmz_index,
char *nmz_result, int result_limit) {
char buf[BUF_LEN], buf1[BUF_LEN], result_limit_str[BUF_LEN];
int count = 0;
FILE *fp;
char *args[32];
int status, i;
pid_t pid;
snprintf(result_limit_str, sizeof(result_limit_str), "%d", result_limit);
i = 0;
args[i++] = "namazu";
args[i++] = "-q";
args[i++] = "-n";
args[i++] = result_limit_str;
args[i++] = "-l";
args[i++] = "-s";
args[i++] = query;
args[i++] = nmz_index;
args[i++] = NULL;
fp = pexecvp("namazu", args, &pid, "r");
if (!fp) {
perror("pexecvp");
return 0;
}
while (fgets(buf, sizeof(buf), fp)) {
int ret;
char *newl = strchr(buf, (int) '\n');
if (*newl) {
*newl = '\0';
}
snprintf(buf1, sizeof(buf1), "%s/cur/%s", nmz_result, basename(buf));
ret = symlink(buf, buf1);
if (ret != 0) {
perror("symlink");
} else {
count++;
}
}
fclose(fp);
waitpid(pid, &status, 0);
if(WEXITSTATUS(status) == 127) {
fprintf(stderr, "namazu executable not found.\n");
}
return count;
}
void
build_index(char *nmz_index, char *mail_dirs[], int num_mail_dirs) {
char *args[MAX_MAIL_DIRS + 10];
int j, i = 0;
mkdir(nmz_index, 0777);
args[i++] = "mknmz";
args[i++] = "-Len_US.ISO8859-1";
args[i++] = "-O";
args[i++] = nmz_index;
args[i++] = "--mailnews";
args[i++] = "--allow=.*";
for (j = 0; j<num_mail_dirs && i<MAX_MAIL_DIRS+10; j++) {
args[i++] = mail_dirs[j];
}
args[i] = NULL;
execvp("mknmz", args);
perror("execvp");
}
void
usage() {
fprintf(stderr,
"nmzmail version %s\n"
"usage: nmzmail [-b <base>] [-r <result>] -i <maildirs> |\n"
" [-b <base>] [-r <result>] [-n <limit>]\n"
, VERSION);
}
syntax highlighted by Code2HTML, v. 0.9.1