aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-01-12 11:22:08 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-01-12 11:22:08 +0000
commitb9ca7b1ef5cd1f96ae6e28ae78d12c1e3258c23f (patch)
tree1203adec5f70af1ddd49868528d8d3a5b9004329 /src/main.c
Initial import of Sylpheed (GTK2 version).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c721
1 files changed, 721 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 00000000..0f46186a
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,721 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2004 Hiroyuki Yamamoto
+ *
+ * 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 program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "defs.h"
+
+#include <glib.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkrc.h>
+
+#if HAVE_GDK_IMLIB
+# include <gdk_imlib.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#if USE_GPGME
+# include <gpgme.h>
+#endif
+
+#include "intl.h"
+#include "main.h"
+#include "mainwindow.h"
+#include "folderview.h"
+#include "summaryview.h"
+#include "prefs_common.h"
+#include "prefs_account.h"
+#include "prefs_actions.h"
+#include "prefs_display_header.h"
+#include "account.h"
+#include "procmsg.h"
+#include "filter.h"
+#include "inc.h"
+#include "import.h"
+#include "manage_window.h"
+#include "alertpanel.h"
+#include "statusbar.h"
+#include "addressbook.h"
+#include "compose.h"
+#include "folder.h"
+#include "setup.h"
+#include "utils.h"
+#include "gtkutils.h"
+#include "socket.h"
+
+#if USE_GPGME
+# include "rfc2015.h"
+#endif
+#if USE_SSL
+# include "ssl.h"
+#endif
+
+#include "version.h"
+
+gchar *prog_version;
+gchar *startup_dir;
+gboolean debug_mode = FALSE;
+
+static gint lock_socket = -1;
+static gint lock_socket_tag = 0;
+
+static struct RemoteCmd {
+ gboolean receive;
+ gboolean receive_all;
+ gboolean compose;
+ const gchar *compose_mailto;
+ GPtrArray *attach_files;
+ gboolean status;
+ gboolean status_full;
+ GPtrArray *status_folders;
+ GPtrArray *status_full_folders;
+ gboolean send;
+} cmd;
+
+static void parse_cmd_opt(int argc, char *argv[]);
+
+#if USE_GPGME
+static void idle_function_for_gpgme(void);
+#endif /* USE_GPGME */
+
+static gint prohibit_duplicate_launch (void);
+static gint lock_socket_remove (void);
+static void lock_socket_input_cb (gpointer data,
+ gint source,
+ GdkInputCondition condition);
+static gchar *get_socket_name (void);
+
+static void open_compose_new (const gchar *address,
+ GPtrArray *attach_files);
+
+static void send_queue (void);
+
+#if 0
+/* for gettext */
+_("File `%s' already exists.\n"
+ "Can't create folder.")
+#endif
+
+#define MAKE_DIR_IF_NOT_EXIST(dir) \
+{ \
+ if (!is_dir_exist(dir)) { \
+ if (is_file_exist(dir)) { \
+ alertpanel_warning \
+ (_("File `%s' already exists.\n" \
+ "Can't create folder."), \
+ dir); \
+ return 1; \
+ } \
+ if (make_dir(dir) < 0) \
+ return 1; \
+ } \
+}
+
+int main(int argc, char *argv[])
+{
+ gchar *userrc;
+ MainWindow *mainwin;
+ FolderView *folderview;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset(PACKAGE, CS_UTF_8);
+ textdomain(PACKAGE);
+
+ prog_version = PROG_VERSION;
+ startup_dir = g_get_current_dir();
+
+ parse_cmd_opt(argc, argv);
+
+ /* check and create unix domain socket for remote operation */
+ lock_socket = prohibit_duplicate_launch();
+ if (lock_socket < 0) return 0;
+
+ if (cmd.status || cmd.status_full) {
+ puts("0 Sylpheed not running.");
+ lock_socket_remove();
+ return 0;
+ }
+
+ gtk_set_locale();
+ gtk_init(&argc, &argv);
+
+ gdk_rgb_init();
+ gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
+ gtk_widget_set_default_visual(gdk_rgb_get_visual());
+
+#if USE_THREADS || USE_LDAP
+ g_thread_init(NULL);
+ if (!g_thread_supported())
+ g_error(_("g_thread is not supported by glib.\n"));
+#endif
+
+#if HAVE_GDK_IMLIB
+ gdk_imlib_init();
+ gtk_widget_push_visual(gdk_imlib_get_visual());
+ gtk_widget_push_colormap(gdk_imlib_get_colormap());
+#endif
+
+#if USE_SSL
+ ssl_init();
+#endif
+
+ srandom((gint)time(NULL));
+
+ /* parse gtkrc files */
+ userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
+ NULL);
+ gtk_rc_parse(userrc);
+ g_free(userrc);
+ userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
+ G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
+ gtk_rc_parse(userrc);
+ g_free(userrc);
+ userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
+ gtk_rc_parse(userrc);
+ g_free(userrc);
+
+ userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
+ gtk_accel_map_load(userrc);
+ g_free(userrc);
+
+ CHDIR_RETURN_VAL_IF_FAIL(get_home_dir(), 1);
+
+ /* backup if old rc file exists */
+ if (is_file_exist(RC_DIR)) {
+ if (rename(RC_DIR, RC_DIR ".bak") < 0)
+ FILE_OP_ERROR(RC_DIR, "rename");
+ }
+ MAKE_DIR_IF_NOT_EXIST(RC_DIR);
+ MAKE_DIR_IF_NOT_EXIST(get_imap_cache_dir());
+ MAKE_DIR_IF_NOT_EXIST(get_news_cache_dir());
+ MAKE_DIR_IF_NOT_EXIST(get_mime_tmp_dir());
+ MAKE_DIR_IF_NOT_EXIST(get_tmp_dir());
+ MAKE_DIR_IF_NOT_EXIST(RC_DIR G_DIR_SEPARATOR_S "uidl");
+
+ if (is_file_exist(RC_DIR G_DIR_SEPARATOR_S "sylpheed.log")) {
+ if (rename(RC_DIR G_DIR_SEPARATOR_S "sylpheed.log",
+ RC_DIR G_DIR_SEPARATOR_S "sylpheed.log.bak") < 0)
+ FILE_OP_ERROR("sylpheed.log", "rename");
+ }
+ set_log_file(RC_DIR G_DIR_SEPARATOR_S "sylpheed.log");
+
+ prefs_common_read_config();
+
+#if USE_GPGME
+ if (gpgme_check_engine()) { /* Also does some gpgme init */
+ rfc2015_disable_all();
+ debug_print("gpgme_engine_version:\n%s\n",
+ gpgme_get_engine_info());
+
+ if (prefs_common.gpg_warning) {
+ AlertValue val;
+
+ val = alertpanel_message_with_disable
+ (_("Warning"),
+ _("GnuPG is not installed properly, or its version is too old.\n"
+ "OpenPGP support disabled."),
+ ALERT_WARNING);
+ if (val & G_ALERTDISABLE)
+ prefs_common.gpg_warning = FALSE;
+ }
+ }
+ gpgme_register_idle(idle_function_for_gpgme);
+#endif
+
+ sock_set_io_timeout(prefs_common.io_timeout_secs);
+
+ prefs_filter_read_config();
+ prefs_actions_read_config();
+ prefs_display_header_read_config();
+
+ gtkut_widget_init();
+
+ mainwin = main_window_create
+ (prefs_common.sep_folder | prefs_common.sep_msg << 1);
+ folderview = mainwin->folderview;
+
+ /* register the callback of unix domain socket input */
+ lock_socket_tag = gdk_input_add(lock_socket,
+ GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
+ lock_socket_input_cb,
+ mainwin);
+
+ account_read_config_all();
+
+ if (folder_read_list() < 0) {
+ setup(mainwin);
+ folder_write_list();
+ }
+ if (!account_get_list()) {
+ account_edit_open();
+ account_add();
+ }
+
+ account_set_missing_folder();
+ folder_set_missing_folders();
+ folderview_set(folderview);
+
+ addressbook_read_file();
+
+ inc_autocheck_timer_init(mainwin);
+
+ /* ignore SIGPIPE signal for preventing sudden death of program */
+ signal(SIGPIPE, SIG_IGN);
+
+ if (cmd.receive_all)
+ inc_all_account_mail(mainwin, FALSE);
+ else if (prefs_common.chk_on_startup)
+ inc_all_account_mail(mainwin, TRUE);
+ else if (cmd.receive)
+ inc_mail(mainwin);
+ else
+ gtk_widget_grab_focus(folderview->ctree);
+
+ if (cmd.compose)
+ open_compose_new(cmd.compose_mailto, cmd.attach_files);
+ if (cmd.attach_files) {
+ ptr_array_free_strings(cmd.attach_files);
+ g_ptr_array_free(cmd.attach_files, TRUE);
+ cmd.attach_files = NULL;
+ }
+ if (cmd.send)
+ send_queue();
+ if (cmd.status_folders) {
+ g_ptr_array_free(cmd.status_folders, TRUE);
+ cmd.status_folders = NULL;
+ }
+ if (cmd.status_full_folders) {
+ g_ptr_array_free(cmd.status_full_folders, TRUE);
+ cmd.status_full_folders = NULL;
+ }
+
+ gtk_main();
+
+ return 0;
+}
+
+static void parse_cmd_opt(int argc, char *argv[])
+{
+ gint i;
+
+ for (i = 1; i < argc; i++) {
+ if (!strncmp(argv[i], "--debug", 7))
+ debug_mode = TRUE;
+ else if (!strncmp(argv[i], "--receive-all", 13))
+ cmd.receive_all = TRUE;
+ else if (!strncmp(argv[i], "--receive", 9))
+ cmd.receive = TRUE;
+ else if (!strncmp(argv[i], "--compose", 9)) {
+ const gchar *p = argv[i + 1];
+
+ cmd.compose = TRUE;
+ cmd.compose_mailto = NULL;
+ if (p && *p != '\0' && *p != '-') {
+ if (!strncmp(p, "mailto:", 7))
+ cmd.compose_mailto = p + 7;
+ else
+ cmd.compose_mailto = p;
+ i++;
+ }
+ } else if (!strncmp(argv[i], "--attach", 8)) {
+ const gchar *p = argv[i + 1];
+ gchar *file;
+
+ while (p && *p != '\0' && *p != '-') {
+ if (!cmd.attach_files)
+ cmd.attach_files = g_ptr_array_new();
+ if (*p != G_DIR_SEPARATOR)
+ file = g_strconcat(startup_dir,
+ G_DIR_SEPARATOR_S,
+ p, NULL);
+ else
+ file = g_strdup(p);
+ g_ptr_array_add(cmd.attach_files, file);
+ i++;
+ p = argv[i + 1];
+ }
+ } else if (!strncmp(argv[i], "--send", 6)) {
+ cmd.send = TRUE;
+ } else if (!strncmp(argv[i], "--version", 9)) {
+ puts("Sylpheed version " VERSION);
+ exit(0);
+ } else if (!strncmp(argv[i], "--status-full", 13)) {
+ const gchar *p = argv[i + 1];
+
+ cmd.status_full = TRUE;
+ while (p && *p != '\0' && *p != '-') {
+ if (!cmd.status_full_folders)
+ cmd.status_full_folders =
+ g_ptr_array_new();
+ g_ptr_array_add(cmd.status_full_folders,
+ g_strdup(p));
+ i++;
+ p = argv[i + 1];
+ }
+ } else if (!strncmp(argv[i], "--status", 8)) {
+ const gchar *p = argv[i + 1];
+
+ cmd.status = TRUE;
+ while (p && *p != '\0' && *p != '-') {
+ if (!cmd.status_folders)
+ cmd.status_folders = g_ptr_array_new();
+ g_ptr_array_add(cmd.status_folders,
+ g_strdup(p));
+ i++;
+ p = argv[i + 1];
+ }
+ } else if (!strncmp(argv[i], "--help", 6)) {
+ g_print(_("Usage: %s [OPTION]...\n"),
+ g_basename(argv[0]));
+
+ puts(_(" --compose [address] open composition window"));
+ puts(_(" --attach file1 [file2]...\n"
+ " open composition window with specified files\n"
+ " attached"));
+ puts(_(" --receive receive new messages"));
+ puts(_(" --receive-all receive new messages of all accounts"));
+ puts(_(" --send send all queued messages"));
+ puts(_(" --status [folder]... show the total number of messages"));
+ puts(_(" --status-full [folder]...\n"
+ " show the status of each folder"));
+ puts(_(" --debug debug mode"));
+ puts(_(" --help display this help and exit"));
+ puts(_(" --version output version information and exit"));
+
+ exit(1);
+ }
+ }
+
+ if (cmd.attach_files && cmd.compose == FALSE) {
+ cmd.compose = TRUE;
+ cmd.compose_mailto = NULL;
+ }
+}
+
+static gint get_queued_message_num(void)
+{
+ FolderItem *queue;
+
+ queue = folder_get_default_queue();
+ if (!queue) return -1;
+
+ folder_item_scan(queue);
+ return queue->total;
+}
+
+void app_will_exit(GtkWidget *widget, gpointer data)
+{
+ MainWindow *mainwin = data;
+ gchar *filename;
+
+ if (compose_get_compose_list()) {
+ if (alertpanel(_("Notice"),
+ _("Composing message exists. Really quit?"),
+ _("OK"), _("Cancel"), NULL) != G_ALERTDEFAULT)
+ return;
+ manage_window_focus_in(mainwin->window, NULL, NULL);
+ }
+
+ if (prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
+ if (alertpanel(_("Queued messages"),
+ _("Some unsent messages are queued. Exit now?"),
+ _("OK"), _("Cancel"), NULL) != G_ALERTDEFAULT)
+ return;
+ manage_window_focus_in(mainwin->window, NULL, NULL);
+ }
+
+ inc_autocheck_timer_remove();
+
+ if (prefs_common.clean_on_exit)
+ main_window_empty_trash(mainwin, prefs_common.ask_on_clean);
+
+ /* save all state before exiting */
+ folder_write_list();
+ summary_write_cache(mainwin->summaryview);
+
+ main_window_get_size(mainwin);
+ main_window_get_position(mainwin);
+ prefs_common_write_config();
+ prefs_filter_write_config();
+ account_write_config_all();
+ addressbook_export_to_file();
+
+ filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
+ gtk_accel_map_save(filename);
+ g_free(filename);
+
+ /* delete temporary files */
+ remove_all_files(get_mime_tmp_dir());
+
+ close_log_file();
+ lock_socket_remove();
+
+#if USE_SSL
+ ssl_done();
+#endif
+
+ gtk_main_quit();
+}
+
+#if USE_GPGME
+static void idle_function_for_gpgme(void)
+{
+ while (gtk_events_pending())
+ gtk_main_iteration();
+}
+#endif /* USE_GPGME */
+
+static gchar *get_socket_name(void)
+{
+ static gchar *filename = NULL;
+
+ if (filename == NULL) {
+ filename = g_strdup_printf("%s%csylpheed-%d",
+ g_get_tmp_dir(), G_DIR_SEPARATOR,
+ getuid());
+ }
+
+ return filename;
+}
+
+static gint prohibit_duplicate_launch(void)
+{
+ gint uxsock;
+ gchar *path;
+
+ path = get_socket_name();
+ uxsock = fd_connect_unix(path);
+ if (uxsock < 0) {
+ unlink(path);
+ return fd_open_unix(path);
+ }
+
+ /* remote command mode */
+
+ debug_print(_("another Sylpheed is already running.\n"));
+
+ if (cmd.receive_all)
+ fd_write_all(uxsock, "receive_all\n", 12);
+ else if (cmd.receive)
+ fd_write_all(uxsock, "receive\n", 8);
+ else if (cmd.compose && cmd.attach_files) {
+ gchar *str, *compose_str;
+ gint i;
+
+ if (cmd.compose_mailto)
+ compose_str = g_strdup_printf("compose_attach %s\n",
+ cmd.compose_mailto);
+ else
+ compose_str = g_strdup("compose_attach\n");
+
+ fd_write_all(uxsock, compose_str, strlen(compose_str));
+ g_free(compose_str);
+
+ for (i = 0; i < cmd.attach_files->len; i++) {
+ str = g_ptr_array_index(cmd.attach_files, i);
+ fd_write_all(uxsock, str, strlen(str));
+ fd_write_all(uxsock, "\n", 1);
+ }
+
+ fd_write_all(uxsock, ".\n", 2);
+ } else if (cmd.compose) {
+ gchar *compose_str;
+
+ if (cmd.compose_mailto)
+ compose_str = g_strdup_printf
+ ("compose %s\n", cmd.compose_mailto);
+ else
+ compose_str = g_strdup("compose\n");
+
+ fd_write_all(uxsock, compose_str, strlen(compose_str));
+ g_free(compose_str);
+ } else if (cmd.send) {
+ fd_write_all(uxsock, "send\n", 5);
+ } else if (cmd.status || cmd.status_full) {
+ gchar buf[BUFFSIZE];
+ gint i;
+ const gchar *command;
+ GPtrArray *folders;
+ gchar *folder;
+
+ command = cmd.status_full ? "status-full\n" : "status\n";
+ folders = cmd.status_full ? cmd.status_full_folders :
+ cmd.status_folders;
+
+ fd_write_all(uxsock, command, strlen(command));
+ for (i = 0; folders && i < folders->len; ++i) {
+ folder = g_ptr_array_index(folders, i);
+ fd_write_all(uxsock, folder, strlen(folder));
+ fd_write_all(uxsock, "\n", 1);
+ }
+ fd_write_all(uxsock, ".\n", 2);
+ for (;;) {
+ fd_gets(uxsock, buf, sizeof(buf));
+ if (!strncmp(buf, ".\n", 2)) break;
+ fputs(buf, stdout);
+ }
+ } else
+ fd_write_all(uxsock, "popup\n", 6);
+
+ fd_close(uxsock);
+ return -1;
+}
+
+static gint lock_socket_remove(void)
+{
+ gchar *filename;
+
+ if (lock_socket < 0) return -1;
+
+ if (lock_socket_tag > 0)
+ gdk_input_remove(lock_socket_tag);
+ fd_close(lock_socket);
+ filename = get_socket_name();
+ unlink(filename);
+
+ return 0;
+}
+
+static GPtrArray *get_folder_item_list(gint sock)
+{
+ gchar buf[BUFFSIZE];
+ FolderItem *item;
+ GPtrArray *folders = NULL;
+
+ for (;;) {
+ fd_gets(sock, buf, sizeof(buf));
+ if (!strncmp(buf, ".\n", 2)) break;
+ strretchomp(buf);
+ if (!folders) folders = g_ptr_array_new();
+ item = folder_find_item_from_identifier(buf);
+ if (item)
+ g_ptr_array_add(folders, item);
+ else
+ g_warning("no such folder: %s\n", buf);
+ }
+
+ return folders;
+}
+
+static void lock_socket_input_cb(gpointer data,
+ gint source,
+ GdkInputCondition condition)
+{
+ MainWindow *mainwin = (MainWindow *)data;
+ gint sock;
+ gchar buf[BUFFSIZE];
+
+ sock = fd_accept(source);
+ fd_gets(sock, buf, sizeof(buf));
+
+ if (!strncmp(buf, "popup", 5)) {
+ main_window_popup(mainwin);
+ } else if (!strncmp(buf, "receive_all", 11)) {
+ main_window_popup(mainwin);
+ inc_all_account_mail(mainwin, FALSE);
+ } else if (!strncmp(buf, "receive", 7)) {
+ main_window_popup(mainwin);
+ inc_mail(mainwin);
+ } else if (!strncmp(buf, "compose_attach", 14)) {
+ GPtrArray *files;
+ gchar *mailto;
+
+ mailto = g_strdup(buf + strlen("compose_attach") + 1);
+ files = g_ptr_array_new();
+ while (fd_gets(sock, buf, sizeof(buf)) > 0) {
+ if (buf[0] == '.' && buf[1] == '\n') break;
+ strretchomp(buf);
+ g_ptr_array_add(files, g_strdup(buf));
+ }
+ open_compose_new(mailto, files);
+ ptr_array_free_strings(files);
+ g_ptr_array_free(files, TRUE);
+ g_free(mailto);
+ } else if (!strncmp(buf, "compose", 7)) {
+ open_compose_new(buf + strlen("compose") + 1, NULL);
+ } else if (!strncmp(buf, "send", 4)) {
+ send_queue();
+ } else if (!strncmp(buf, "status-full", 11) ||
+ !strncmp(buf, "status", 6)) {
+ gchar *status;
+ GPtrArray *folders;
+
+ folders = get_folder_item_list(sock);
+ status = folder_get_status
+ (folders, !strncmp(buf, "status-full", 11));
+ fd_write_all(sock, status, strlen(status));
+ fd_write_all(sock, ".\n", 2);
+ g_free(status);
+ if (folders) g_ptr_array_free(folders, TRUE);
+ }
+
+ fd_close(sock);
+}
+
+static void open_compose_new(const gchar *address, GPtrArray *attach_files)
+{
+ gchar *addr = NULL;
+
+ if (address) {
+ Xstrdup_a(addr, address, return);
+ g_strstrip(addr);
+ }
+
+ compose_new(NULL, NULL, addr, attach_files);
+}
+
+static void send_queue(void)
+{
+ GList *list;
+
+ if (!main_window_toggle_online_if_offline(main_window_get()))
+ return;
+
+ for (list = folder_get_list(); list != NULL; list = list->next) {
+ Folder *folder = list->data;
+
+ if (folder->queue) {
+ gint ret;
+
+ ret = procmsg_send_queue(folder->queue,
+ prefs_common.savemsg);
+ statusbar_pop_all();
+ if (ret > 0)
+ folder_item_scan(folder->queue);
+ }
+ }
+
+ folderview_update_all_updated(TRUE);
+}