1 /*
2  * Copyright © 2004-2010 Jens Oknelid, paskharen@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * In addition, as a special exception, compiling, linking, and/or
19  * using OpenSSL with this program is allowed.
20  */
21 
22 #include <gtk/gtk.h>
23 #include <glib/gi18n.h>
24 #include <dcpp/stdinc.h>
25 #include <dcpp/DCPlusPlus.h>
26 #include "bacon-message-connection.h"
27 #include "settingsmanager.hh"
28 #include "wulformanager.hh"
29 #include "WulforUtil.hh"
30 #include <iostream>
31 #include <signal.h>
32 
33 #define GUI_LOCALE_DIR LOCALE_DIR
34 
35 #define GUI_PACKAGE "eiskaltdcpp-gtk"
36 
37 #include "VersionGlobal.h"
38 
39 #ifdef ENABLE_STACKTRACE
40 #include "extra/stacktrace.h"
41 #endif // ENABLE_STACKTRACE
42 
printHelp()43 void printHelp()
44 {
45     printf(_(
46             "Using:\n"
47             "  eiskaltdcpp-gtk <magnet link> <dchub://link> <adc(s)://link>\n"
48             "  eiskaltdcpp-gtk <Key>\n"
49             "EiskaltDC++ is a cross-platform program that uses the Direct Connect and ADC protocol.\n"
50             "\n"
51             "Keys:\n"
52             "  -h, --help\t Show this message\n"
53             "  -V, --version\t Show version string\n"
54             )
55            );
56 }
57 
printVersion()58 void printVersion()
59 {
60     printf("%s version: %s (%s)\n", APPNAME, EISKALTDCPP_VERSION, EISKALTDCPP_VERSION_SFX);
61     printf("GTK+ version: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
62     printf("Glib version: %d.%d.%d\n", glib_major_version, glib_minor_version, glib_micro_version);
63 }
64 
65 BaconMessageConnection *connection = NULL;
66 
receiver(const char * link,gpointer data)67 void receiver(const char *link, gpointer data)
68 {
69     g_return_if_fail(link != NULL);
70     WulforManager::get()->onReceived_gui(link);
71 }
72 
callBack(void * x,const std::string & a)73 void callBack(void* x, const std::string& a)
74 {
75     std::cout << _("Loading: ") << a << std::endl;
76 }
77 
catchSIG(int sigNum)78 void catchSIG(int sigNum) {
79     psignal(sigNum, _("Catching signal "));
80 
81 #ifdef ENABLE_STACKTRACE
82     printBacktrace(sigNum);
83 #endif // ENABLE_STACKTRACE
84 
85     raise(SIGINT);
86 
87     std::abort();
88 }
89 
90 template <int sigNum = 0, int ... Params>
catchSignals()91 void catchSignals() {
92     if (!sigNum)
93         return;
94 
95     psignal(sigNum, _("Installing handler for"));
96 
97     signal(sigNum, catchSIG);
98 
99     catchSignals<Params ... >();
100 }
101 
installHandlers()102 void installHandlers(){
103     struct sigaction sa;
104     memset(&sa, 0, sizeof(sa));
105     sa.sa_handler = SIG_IGN;
106 
107     if (sigaction(SIGPIPE, &sa, NULL) == -1)
108         printf(_("Cannot handle SIGPIPE\n"));
109     else {
110         sigset_t set;
111         sigemptyset (&set);
112         sigaddset (&set, SIGPIPE);
113         pthread_sigmask(SIG_BLOCK, &set, NULL);
114     }
115 
116     catchSignals<SIGSEGV, SIGABRT, SIGBUS, SIGTERM>();
117 
118     printf(_("Signal handlers installed.\n"));
119 }
120 
main(int argc,char * argv[])121 int main(int argc, char *argv[])
122 {
123 
124     for (int i = 0; i < argc; i++){
125         if (!strcmp(argv[i],"--help") || !strcmp(argv[i],"-h")){
126             printHelp();
127             exit(0);
128     }
129             else if (!strcmp(argv[i],"--version") || !strcmp(argv[i],"-V")){
130                 printVersion();
131                 exit(0);
132             }
133     }
134 
135     // Initialize i18n support
136     bindtextdomain(GUI_PACKAGE, GUI_LOCALE_DIR);
137     textdomain(GUI_PACKAGE);
138     bind_textdomain_codeset(GUI_PACKAGE, "UTF-8");
139 
140     connection = bacon_message_connection_new(GUI_PACKAGE);
141 
142     dcdebug(connection ? "eiskaltdcpp-gtk: connection yes...\n" : "eiskaltdcpp-gtk: connection no...\n");
143 
144     // Check if profile is locked
145     if (WulforUtil::profileIsLocked())
146     {
147         if (!bacon_message_connection_get_is_server(connection))
148         {
149             dcdebug("eiskaltdcpp-gtk: is client...\n");
150 
151             if (argc > 1)
152             {
153                 dcdebug("eiskaltdcpp-gtk: send %s\n", argv[1]);
154                 bacon_message_connection_send(connection, argv[1]);
155             }
156         }
157 
158         bacon_message_connection_free(connection);
159 
160         return 0;
161     }
162 
163     if (bacon_message_connection_get_is_server(connection))
164     {
165         dcdebug("eiskaltdcpp-gtk: is server...\n");
166         bacon_message_connection_set_callback(connection, receiver, NULL);
167     }
168 
169     // Start the DC++ client core
170     dcpp::startup(callBack, NULL);
171 
172     dcpp::TimerManager::getInstance()->start();
173 
174 #if !GLIB_CHECK_VERSION(2,32,0)
175     g_thread_init(NULL);
176 #endif
177     gdk_threads_init();
178     gtk_init(&argc, &argv);
179     g_set_application_name("EiskaltDC++ Gtk");
180 
181     installHandlers();
182 
183     WulforSettingsManager::newInstance();
184     WulforManager::start(argc, argv);
185     gdk_threads_enter();
186     gtk_main();
187     bacon_message_connection_free(connection);
188     gdk_threads_leave();
189     WulforManager::stop();
190     WulforSettingsManager::deleteInstance();
191 
192     std::cout << _("Shutting down libdcpp...") << std::endl;
193     dcpp::shutdown();
194     std::cout << _("Quit...") << std::endl;
195     return 0;
196 }
197