4 * by JH <jheinonen@users.sourceforge.net>
6 * Copyright (C) Jaakko Heinonen
20 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
37 static void init_abook();
38 static void quit_abook_sig(int i);
39 static void set_filenames();
40 static void parse_command_line(int argc, char **argv);
41 static void show_usage();
42 static void mutt_query(char *str);
43 static void init_mutt_query();
44 static void convert(char *srcformat, char *srcfile,
45 char *dstformat, char *dstfile);
46 static void add_email(int);
48 char *datafile = NULL;
49 static char *rcfile = NULL;
51 bool alternative_datafile = FALSE;
52 bool alternative_rcfile = FALSE;
59 assert(datafile != NULL);
61 if( (f = fopen(datafile, "a")) == NULL)
70 check_abook_directory()
75 assert(!is_ui_initialized());
77 if(alternative_datafile)
80 dir = strconcat(getenv("HOME"), "/" DIR_IN_HOME, NULL);
83 if(stat(dir, &s) == -1) {
89 if(mkdir(dir, 0700) == -1) {
90 printf(_("Cannot create directory %s\n"), dir);
95 } else if(!S_ISDIR(s.st_mode)) {
96 printf(_("%s is not a directory\n"), dir);
105 xmalloc_error_handler(int err)
108 * We don't try to save addressbook here because we don't know
109 * if it's fully loaded to memory.
111 if(is_ui_initialized())
114 fprintf(stderr, _("Memory allocation failure: %s\n"), strerror(err));
122 check_abook_directory();
124 if(load_opts(rcfile) > 0) {
125 printf(_("Press enter to continue...\n"));
129 signal(SIGTERM, quit_abook_sig);
134 umask(DEFAULT_UMASK);
136 if(!datafile_writeable()) {
137 char *s = mkstr(_("File %s is not writeable"), datafile);
141 if(load_database(datafile) || !statusline_ask_boolean(
142 _("If you continue all changes will "
143 "be lost. Do you want to continue?"), FALSE)) {
145 /*close_database();*/
150 load_database(datafile);
156 quit_abook(int save_db)
159 if(opt_get_bool(BOOL_AUTOSAVE))
161 else if(statusline_ask_boolean(_("Save database"), TRUE))
163 } else if(!statusline_ask_boolean(_("Quit without saving"), FALSE))
175 quit_abook_sig(int i)
177 quit_abook(QUIT_SAVE);
181 main(int argc, char **argv)
183 #if defined(HAVE_SETLOCALE) && defined(HAVE_LOCALE_H)
184 setlocale(LC_ALL, "");
187 bindtextdomain(PACKAGE, LOCALEDIR);
190 xmalloc_set_error_handler(xmalloc_error_handler);
192 parse_command_line(argc, argv);
198 quit_abook(QUIT_SAVE);
216 if( (stat(getenv("HOME"), &s)) == -1 || ! S_ISDIR(s.st_mode) ) {
217 fprintf(stderr,_("%s is not a valid HOME directory\n"), getenv("HOME") );
222 datafile = strconcat(getenv("HOME"), "/" DIR_IN_HOME "/"
226 rcfile = strconcat(getenv("HOME"), "/" DIR_IN_HOME "/"
229 atexit(free_filenames);
239 MODE_ADD_EMAIL_QUIET,
245 change_mode(int *current, int mode)
247 if(*current != MODE_CONT) {
248 fprintf(stderr, _("Cannot combine options --mutt-query, "
250 "--add-email or --add-email-quiet\n"));
258 set_filename(char **var, char *path)
263 assert(*var == NULL); /* or else we probably leak memory */
264 assert(path != NULL);
267 *var = xstrdup(path);
273 *var = strconcat(cwd, "/", path, NULL);
278 #define set_convert_var(X) do { if(mode != MODE_CONVERT) {\
279 fprintf(stderr, _("please use option --%s after --convert option\n"),\
280 long_options[option_index].name);\
287 parse_command_line(int argc, char **argv)
289 int mode = MODE_CONT;
290 char *query_string = NULL;
291 char *informat = "abook",
298 int option_index = 0;
310 static struct option long_options[] = {
311 { "help", 0, 0, 'h' },
312 { "add-email", 0, 0, OPT_ADD_EMAIL },
313 { "add-email-quiet", 0, 0, OPT_ADD_EMAIL_QUIET },
314 { "datafile", 1, 0, 'f' },
315 { "mutt-query", 1, 0, OPT_MUTT_QUERY },
316 { "config", 1, 0, 'C' },
317 { "convert", 0, 0, OPT_CONVERT },
318 { "informat", 1, 0, OPT_INFORMAT },
319 { "outformat", 1, 0, OPT_OUTFORMAT },
320 { "infile", 1, 0, OPT_INFILE },
321 { "outfile", 1, 0, OPT_OUTFILE },
322 { "formats", 0, 0, OPT_FORMATS },
326 c = getopt_long(argc, argv, "hC:",
327 long_options, &option_index);
337 change_mode(&mode, MODE_ADD_EMAIL);
339 case OPT_ADD_EMAIL_QUIET:
340 change_mode(&mode, MODE_ADD_EMAIL_QUIET);
343 set_filename(&datafile, optarg);
344 alternative_datafile = TRUE;
347 query_string = optarg;
348 change_mode(&mode, MODE_QUERY);
351 set_filename(&rcfile, optarg);
352 alternative_rcfile = TRUE;
355 change_mode(&mode, MODE_CONVERT);
358 set_convert_var(informat);
361 set_convert_var(outformat);
364 set_convert_var(infile);
367 set_convert_var(outfile);
378 fprintf(stderr, _("%s: unrecognized arguments on command line\n"),
386 case MODE_ADD_EMAIL_QUIET:
389 mutt_query(query_string);
391 convert(informat, infile, outformat, outfile);
399 puts (PACKAGE " v " VERSION "\n");
400 puts (_(" -h --help show usage"));
401 puts (_(" -C --config <file> use an alternative configuration file"));
402 puts (_(" --datafile <file> use an alternative addressbook file"));
403 puts (_(" --mutt-query <string> make a query for mutt"));
404 puts (_(" --add-email "
405 "read an e-mail message from stdin and\n"
407 "add the sender to the addressbook"));
408 puts (_(" --add-email-quiet "
409 "same as --add-email but doesn't\n"
412 puts (_(" --convert convert address book files"));
413 puts (_(" options to use with --convert:"));
414 puts (_(" --informat <format> format for input file"));
415 puts (_(" (default: abook)"));
416 puts (_(" --infile <file> source file"));
417 puts (_(" (default: stdin)"));
418 puts (_(" --outformat <format> format for output file"));
419 puts (_(" (default: text)"));
420 puts (_(" --outfile <file> destination file"));
421 puts (_(" (default: stdout)"));
422 puts (_(" --formats list available formats"));
429 extern list_item *database;
432 quit_mutt_query(int status)
441 muttq_print_item(FILE *file, int item)
443 char emails[MAX_EMAILS][MAX_EMAIL_LEN];
446 split_emailstr(item, emails);
448 for(i = 0; i < (opt_get_bool(BOOL_MUTT_RETURN_ALL_EMAILS) ?
449 MAX_EMAILS : 1) ; i++)
451 fprintf(file, "%s\t%s\t%s\n", emails[i],
452 database[item][NAME],
453 database[item][NOTES] == NULL ? " " :
454 database[item][NOTES]
459 mutt_query(char *str)
463 if( str == NULL || !strcasecmp(str, "all") ) {
464 struct db_enumerator e = init_db_enumerator(ENUM_ALL);
465 printf("All items\n");
466 db_enumerate_items(e)
467 muttq_print_item(stdout, e.item);
469 int search_fields[] = {NAME, EMAIL, NICK, -1};
471 if( (i = find_item(str, 0, search_fields)) < 0 ) {
472 printf("Not found\n");
473 quit_mutt_query(EXIT_FAILURE);
477 muttq_print_item(stdout, i);
478 i = find_item(str, i + 1, search_fields);
482 quit_mutt_query(EXIT_SUCCESS);
492 if( load_database(datafile) ) {
493 printf(_("Cannot open database\n"));
494 quit_mutt_query(EXIT_FAILURE);
501 make_mailstr(int item)
503 char email[MAX_EMAIL_LEN];
505 char *name = mkstr("\"%s\"", database[item][NAME]);
507 get_first_email(email, item);
509 ret = *database[item][EMAIL] ?
510 mkstr("%s <%s>", name, email) :
519 print_stderr(int item)
521 fprintf (stderr, "%c", '\n');
523 if( is_valid_item(item) )
524 muttq_print_item(stderr, item);
526 struct db_enumerator e = init_db_enumerator(ENUM_SELECTED);
527 db_enumerate_items(e) {
528 muttq_print_item(stderr, e.item);
535 launch_mutt(int item)
537 char *cmd = NULL, *mailstr = NULL;
538 char *mutt_command = opt_get_str(STR_MUTT_COMMAND);
540 if(mutt_command == NULL || !*mutt_command)
543 if( is_valid_item(item) )
544 mailstr = make_mailstr(item);
546 struct db_enumerator e = init_db_enumerator(ENUM_SELECTED);
548 db_enumerate_items(e) {
551 strconcat(tmp, ",", make_mailstr(e.item), NULL):
552 strconcat(make_mailstr(e.item), NULL);
557 cmd = strconcat(mutt_command, " \'", mailstr, "\'", NULL);
560 fprintf(stderr, "cmd: %s\n", cmd);
566 * we need to make sure that curses settings are correct
572 launch_wwwbrowser(int item)
576 if( !is_valid_item(item) )
579 if( database[item][URL] )
580 cmd = mkstr("%s '%s'",
581 opt_get_str(STR_WWW_COMMAND),
582 safe_str(database[item][URL]));
592 * we need to make sure that curses settings are correct
598 abook_fopen (const char *path, const char *mode)
603 stat_ok = (stat(path, &s) != -1);
605 if(strchr(mode, 'r'))
606 return (stat_ok && S_ISREG(s.st_mode)) ?
607 fopen(path, mode) : NULL;
609 return (stat_ok && S_ISDIR(s.st_mode)) ?
610 NULL : fopen(path, mode);
614 convert(char *srcformat, char *srcfile, char *dstformat, char *dstfile)
618 if( !srcformat || !srcfile || !dstformat || !dstfile ) {
619 fprintf(stderr, _("too few arguments to make conversion\n"));
620 fprintf(stderr, _("try --help\n"));
624 if( !strcasecmp(srcformat, dstformat) ) {
625 printf( _("input and output formats are the same\n"
635 switch(import_file(srcformat, srcfile)) {
638 _("input format %s not supported\n"), srcformat);
642 fprintf(stderr, _("cannot read file %s\n"), srcfile);
648 switch(export_file(dstformat, dstfile)) {
651 _("output format %s not supported\n"),
657 _("cannot write file %s\n"), dstfile);
668 * --add-email handling
671 static int add_email_count = 0;
676 if(add_email_count > 0) {
677 if(save_database() < 0) {
678 fprintf(stderr, _("cannot open %s\n"), datafile);
681 printf(_("%d item(s) added to %s\n"), add_email_count, datafile);
683 puts(_("Valid sender address not found"));
690 quit_add_email_sig(int signal)
699 check_abook_directory();
705 * we don't actually care if loading fails or not
707 load_database(datafile);
709 atexit(close_database);
711 signal(SIGINT, quit_add_email_sig);
715 add_email_add_item(int quiet, char *name, char *email)
719 if(opt_get_bool(BOOL_ADD_EMAIL_PREVENT_DUPLICATES)) {
720 int search_fields[] = { EMAIL, -1 };
721 if(find_item(email, 0, search_fields) >= 0) {
723 printf(_("Address %s already in addressbook\n"),
730 FILE *in = fopen("/dev/tty", "r");
733 fprintf(stderr, _("cannot open /dev/tty\n"
734 "you may want to use --add-email-quiet\n"));
739 /* TODO gettext: handle translated keypresses? */
740 printf(_("Add ``%s <%s>'' to %s ? (y/n)\n"),
745 if(c == 'n' || c == 'N') {
749 } while(c != 'y' && c != 'Y');
753 memset(item, 0, sizeof(item));
754 item[NAME] = xstrdup(name);
755 item[EMAIL] = xstrdup(email);
756 add_item2database(item);
765 char *name = NULL, *email = NULL;
768 if( (fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode) ) {
769 fprintf(stderr, _("stdin is a directory or cannot stat stdin\n"));
776 line = getaline(stdin);
777 if(line && !strncasecmp("From:", line, 5) ) {
778 getname(line, &name, &email);
779 add_email_count += add_email_add_item(quiet,
785 } while( !feof(stdin) );
791 * end of --add-email handling