4 * by JH <jheinonen@users.sourceforge.net>
6 * Copyright (C) Jaakko Heinonen
21 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
39 static void init_abook();
40 static void quit_abook_sig(int i);
41 static void set_filenames();
42 static void parse_command_line(int argc, char **argv);
43 static void show_usage();
44 static void mutt_query(char *str);
45 static void init_mutt_query();
46 static void convert(char *srcformat, char *srcfile,
47 char *dstformat, char *dstfile);
48 static void add_email(int);
50 char *datafile = NULL;
51 static char *rcfile = NULL;
53 bool alternative_datafile = FALSE;
54 bool alternative_rcfile = FALSE;
62 assert(datafile != NULL);
64 if( (f = fopen(datafile, "a")) == NULL)
73 check_abook_directory()
78 assert(!is_ui_initialized());
80 if(alternative_datafile)
83 dir = strconcat(getenv("HOME"), "/" DIR_IN_HOME, NULL);
86 if(stat(dir, &s) == -1) {
92 if(mkdir(dir, 0700) == -1) {
93 printf(_("Cannot create directory %s\n"), dir);
98 } else if(!S_ISDIR(s.st_mode)) {
99 printf(_("%s is not a directory\n"), dir);
108 xmalloc_error_handler(int err)
111 * We don't try to save addressbook here because we don't know
112 * if it's fully loaded to memory.
114 if(is_ui_initialized())
117 fprintf(stderr, _("Memory allocation failure: %s\n"), strerror(err));
125 check_abook_directory();
127 if(load_opts(rcfile) > 0) {
128 printf(_("Press enter to continue...\n"));
131 init_default_views();
133 signal(SIGTERM, quit_abook_sig);
140 umask(DEFAULT_UMASK);
142 if(!datafile_writeable()) {
143 char *s = strdup_printf(_("File %s is not writeable"), datafile);
147 if(load_database(datafile) || !statusline_ask_boolean(
148 _("If you continue all changes will "
149 "be lost. Do you want to continue?"), FALSE)) {
151 /*close_database();*/
156 load_database(datafile);
162 quit_abook(int save_db)
165 if(opt_get_bool(BOOL_AUTOSAVE))
167 else if(statusline_ask_boolean(_("Save database"), TRUE))
169 } else if(!statusline_ask_boolean(_("Quit without saving"), FALSE))
181 quit_abook_sig(int i)
183 quit_abook(QUIT_SAVE);
187 main(int argc, char **argv)
189 #if defined(HAVE_SETLOCALE) && defined(HAVE_LOCALE_H)
190 setlocale(LC_MESSAGES, "");
191 setlocale(LC_TIME, "");
192 setlocale(LC_CTYPE, "");
193 setlocale(LC_COLLATE, "");
195 bindtextdomain(PACKAGE, LOCALEDIR);
198 xmalloc_set_error_handler(xmalloc_error_handler);
200 prepare_database_internals();
202 parse_command_line(argc, argv);
208 quit_abook(QUIT_SAVE);
226 if( (stat(getenv("HOME"), &s)) == -1 || ! S_ISDIR(s.st_mode) ) {
227 fprintf(stderr,_("%s is not a valid HOME directory\n"), getenv("HOME") );
232 datafile = strconcat(getenv("HOME"), "/" DIR_IN_HOME "/"
236 rcfile = strconcat(getenv("HOME"), "/" DIR_IN_HOME "/"
239 atexit(free_filenames);
249 MODE_ADD_EMAIL_QUIET,
255 change_mode(int *current, int mode)
257 if(*current != MODE_CONT) {
258 fprintf(stderr, _("Cannot combine options --mutt-query, "
260 "--add-email or --add-email-quiet\n"));
268 set_filename(char **var, char *path)
273 assert(*var == NULL); /* or else we probably leak memory */
274 assert(path != NULL);
277 *var = xstrdup(path);
283 *var = strconcat(cwd, "/", path, NULL);
288 #define set_convert_var(X) do { if(mode != MODE_CONVERT) {\
289 fprintf(stderr, _("please use option --%s after --convert option\n"),\
290 long_options[option_index].name);\
297 parse_command_line(int argc, char **argv)
299 int mode = MODE_CONT;
300 char *query_string = NULL;
301 char *informat = "abook",
308 int option_index = 0;
320 static struct option long_options[] = {
321 { "help", 0, 0, 'h' },
322 { "add-email", 0, 0, OPT_ADD_EMAIL },
323 { "add-email-quiet", 0, 0, OPT_ADD_EMAIL_QUIET },
324 { "datafile", 1, 0, 'f' },
325 { "mutt-query", 1, 0, OPT_MUTT_QUERY },
326 { "config", 1, 0, 'C' },
327 { "convert", 0, 0, OPT_CONVERT },
328 { "informat", 1, 0, OPT_INFORMAT },
329 { "outformat", 1, 0, OPT_OUTFORMAT },
330 { "infile", 1, 0, OPT_INFILE },
331 { "outfile", 1, 0, OPT_OUTFILE },
332 { "formats", 0, 0, OPT_FORMATS },
336 c = getopt_long(argc, argv, "hC:",
337 long_options, &option_index);
347 change_mode(&mode, MODE_ADD_EMAIL);
349 case OPT_ADD_EMAIL_QUIET:
350 change_mode(&mode, MODE_ADD_EMAIL_QUIET);
353 set_filename(&datafile, optarg);
354 alternative_datafile = TRUE;
357 query_string = optarg;
358 change_mode(&mode, MODE_QUERY);
361 set_filename(&rcfile, optarg);
362 alternative_rcfile = TRUE;
365 change_mode(&mode, MODE_CONVERT);
368 set_convert_var(informat);
371 set_convert_var(outformat);
374 set_convert_var(infile);
377 set_convert_var(outfile);
388 fprintf(stderr, _("%s: unrecognized arguments on command line\n"),
396 case MODE_ADD_EMAIL_QUIET:
399 mutt_query(query_string);
401 convert(informat, infile, outformat, outfile);
409 puts (PACKAGE " v " VERSION "\n");
410 puts (_(" -h --help show usage"));
411 puts (_(" -C --config <file> use an alternative configuration file"));
412 puts (_(" --datafile <file> use an alternative addressbook file"));
413 puts (_(" --mutt-query <string> make a query for mutt"));
414 puts (_(" --add-email "
415 "read an e-mail message from stdin and\n"
417 "add the sender to the addressbook"));
418 puts (_(" --add-email-quiet "
419 "same as --add-email but doesn't\n"
420 " require to confirm adding"));
422 puts (_(" --convert convert address book files"));
423 puts (_(" options to use with --convert:"));
424 puts (_(" --informat <format> format for input file"));
425 puts (_(" (default: abook)"));
426 puts (_(" --infile <file> source file"));
427 puts (_(" (default: stdin)"));
428 puts (_(" --outformat <format> format for output file"));
429 puts (_(" (default: text)"));
430 puts (_(" --outfile <file> destination file"));
431 puts (_(" (default: stdout)"));
432 puts (_(" --formats list available formats"));
441 quit_mutt_query(int status)
450 muttq_print_item(FILE *file, int item)
452 abook_list *emails, *e;
453 char *tmp = db_email_get(item);
455 emails = csv_to_abook_list(tmp);
458 for(e = emails; e; e = e->next) {
459 fprintf(file, "%s\t%s\t%s\n", e->data, db_name_get(item),
460 !db_fget(item, NOTES) ?" " :db_fget(item, NOTES)
462 if(!opt_get_bool(BOOL_MUTT_RETURN_ALL_EMAILS))
465 abook_list_free(&emails);
469 mutt_query(char *str)
473 if( str == NULL || !strcasecmp(str, "all") ) {
474 struct db_enumerator e = init_db_enumerator(ENUM_ALL);
475 printf("All items\n");
476 db_enumerate_items(e)
477 muttq_print_item(stdout, e.item);
479 int search_fields[] = {NAME, EMAIL, NICK, -1};
481 if( (i = find_item(str, 0, search_fields)) < 0 ) {
482 printf("Not found\n");
483 quit_mutt_query(EXIT_FAILURE);
487 muttq_print_item(stdout, i);
488 i = find_item(str, i + 1, search_fields);
492 quit_mutt_query(EXIT_SUCCESS);
502 if( load_database(datafile) ) {
503 printf(_("Cannot open database\n"));
504 quit_mutt_query(EXIT_FAILURE);
511 make_mailstr(int item)
513 char email[MAX_EMAIL_LEN];
515 char *name = strdup_printf("\"%s\"", db_name_get(item));
517 get_first_email(email, item);
520 strdup_printf("%s <%s>", name, email) :
529 print_stderr(int item)
531 fprintf (stderr, "%c", '\n');
533 if( is_valid_item(item) )
534 muttq_print_item(stderr, item);
536 struct db_enumerator e = init_db_enumerator(ENUM_SELECTED);
537 db_enumerate_items(e) {
538 muttq_print_item(stderr, e.item);
545 launch_mutt(int item)
547 char *cmd = NULL, *mailstr = NULL;
548 char *mutt_command = opt_get_str(STR_MUTT_COMMAND);
550 if(mutt_command == NULL || !*mutt_command)
553 if( is_valid_item(item) )
554 mailstr = make_mailstr(item);
556 struct db_enumerator e = init_db_enumerator(ENUM_SELECTED);
558 db_enumerate_items(e) {
561 strconcat(tmp, ",", make_mailstr(e.item), NULL):
562 strconcat(make_mailstr(e.item), NULL);
567 cmd = strconcat(mutt_command, " \'", mailstr, "\'", NULL);
570 fprintf(stderr, "cmd: %s\n", cmd);
576 * we need to make sure that curses settings are correct
582 launch_wwwbrowser(int item)
586 if( !is_valid_item(item) )
589 if(db_fget(item, URL))
590 cmd = strdup_printf("%s '%s'",
591 opt_get_str(STR_WWW_COMMAND),
592 safe_str(db_fget(item, URL)));
602 * we need to make sure that curses settings are correct
608 abook_fopen (const char *path, const char *mode)
613 stat_ok = (stat(path, &s) != -1);
615 if(strchr(mode, 'r'))
616 return (stat_ok && S_ISREG(s.st_mode)) ?
617 fopen(path, mode) : NULL;
619 return (stat_ok && S_ISDIR(s.st_mode)) ?
620 NULL : fopen(path, mode);
624 convert(char *srcformat, char *srcfile, char *dstformat, char *dstfile)
628 if( !srcformat || !srcfile || !dstformat || !dstfile ) {
629 fprintf(stderr, _("too few arguments to make conversion\n"));
630 fprintf(stderr, _("try --help\n"));
634 if( !strcasecmp(srcformat, dstformat) ) {
635 printf( _("input and output formats are the same\n"
644 init_standard_fields();
646 switch(import_file(srcformat, srcfile)) {
649 _("input format %s not supported\n"), srcformat);
653 fprintf(stderr, _("cannot read file %s\n"), srcfile);
659 switch(export_file(dstformat, dstfile)) {
662 _("output format %s not supported\n"),
668 _("cannot write file %s\n"), dstfile);
679 * --add-email handling
682 static int add_email_count = 0;
687 if(add_email_count > 0) {
688 if(save_database() < 0) {
689 fprintf(stderr, _("cannot open %s\n"), datafile);
692 printf(_("%d item(s) added to %s\n"), add_email_count, datafile);
694 puts(_("Valid sender address not found"));
701 quit_add_email_sig(int signal)
710 check_abook_directory();
713 init_standard_fields();
717 * we don't actually care if loading fails or not
719 load_database(datafile);
721 atexit(close_database);
723 signal(SIGINT, quit_add_email_sig);
727 add_email_add_item(int quiet, char *name, char *email)
731 if(opt_get_bool(BOOL_ADD_EMAIL_PREVENT_DUPLICATES)) {
732 int search_fields[] = { EMAIL, -1 };
733 if(find_item(email, 0, search_fields) >= 0) {
735 printf(_("Address %s already in addressbook\n"),
742 FILE *in = fopen("/dev/tty", "r");
745 fprintf(stderr, _("cannot open /dev/tty\n"
746 "you may want to use --add-email-quiet\n"));
751 printf(_("Add \"%s <%s>\" to %s? (%c/%c)\n"),
755 *S_("keybinding for yes|y"),
756 *S_("keybinding for no|n"));
757 c = tolower(getc(in));
758 if(c == *S_("keybinding for no|n")) {
762 } while(c != *S_("keybinding for yes|y"));
766 item = item_create();
767 item_fput(item, NAME, xstrdup(name));
768 item_fput(item, EMAIL, xstrdup(email));
769 add_item2database(item);
779 char *name = NULL, *email = NULL;
782 if( (fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode) ) {
783 fprintf(stderr, _("stdin is a directory or cannot stat stdin\n"));
790 line = getaline(stdin);
791 if(line && !strncasecmp("From:", line, 5) ) {
792 getname(line, &name, &email);
793 add_email_count += add_email_add_item(quiet,
799 } while( !feof(stdin) );
805 * end of --add-email handling