1 /*
2 * Copyright (c) 2008-2010 Lu, Chao-Ming (Tetralet). All rights reserved.
3 *
4 * This file is part of LilyTerm.
5 *
6 * LilyTerm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * LilyTerm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with LilyTerm. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "main.h"
21
22 // for using in socket
23 gboolean single_process = TRUE;
24 gint socket_fd = 0;
25 struct sockaddr_un address = {0};
26 int address_len = 0;
27 GIOChannel *main_channel = NULL;
28 GtkClipboard *selection_clipboard = NULL;
29 GtkClipboard *selection_primary = NULL;
30
31 // gchar *command_line_path;
32 // gchar **empty_environ;
33 gchar *system_locale_list;
34 gchar *init_LC_CTYPE;
35 gchar *init_encoding;
36 gchar *init_LC_MESSAGES;
37 const gchar *SYSTEM_VTE_CJK_WIDTH_STR = NULL;
38
39 const gchar *wmclass_name = NULL;
40 gchar *wmclass_class = NULL;
41 const gchar *shell = NULL;
42 const gchar *pwd = NULL;
43 const gchar *home = NULL;
44
45 GList *window_list = NULL;
46 gchar *profile_dir = NULL;
47 gboolean proc_exist = TRUE;
48
49 extern gboolean force_to_quit;
50 extern gchar *restricted_locale_message;
51
52 //
53 // single_process ----------------(N)------------------------------------> new_window() ------> shutdown_socket_serve()
54 // | ^ ^ unlink
55 // init_socket_data() | | + clear_channel()
56 // socket_fd -------------------(N)---| | g_io_channel_shutdown
57 // set_fd_non_block ------------(N)---/ | (g_io_channel_unref)
58 // | |
59 // query_socket() |
60 // connect ---------------------(N)-------> init_socket_server() -------------|
61 // | ^ unlink |
62 // send_socket() | bind -----------------------(N)-|
63 // * g_io_channel_unix_new -------(N)---| listen ---------------------(N)-|
64 // g_io_channel_set_encoding ---(N)---| * g_io_channel_unix_new ------(N)-|
65 // g_io_channel_set_buffered | g_io_channel_set_encoding --(N)-|
66 // g_io_channel_write_chars ----(N)---| g_io_add_watch -------------(N)-/
67 // g_io_channel_flush ----------(N)---/ |
68 // + clear_channel() `---- accept_socket()
69 // g_io_channel_shutdown (condition)
70 // (g_io_channel_unref) accept
71 // | set_fd_non_block
72 // exit() * g_io_channel_unix_new
73 // g_io_channel_set_encoding
74 // g_io_add_watch
75 // |
76 // `-- read_socket()
77 // g_io_channel_read_line
78 // new_window()
79 // + clear_channel()
80 // g_io_channel_shutdown
81 // (g_io_channel_unref)
82 //
83 #ifdef UNIT_TEST
fake_main(int argc,char * argv[])84 int fake_main(int argc,
85 char *argv[])
86 #else
87 int main( int argc,
88 char *argv[])
89 #endif
90 {
91 // command_line_path = argv[0];
92
93 // g_debug ("argc = %d", argc);
94 // print_array ("argv", argv);
95 // i18n support. We need to support i18n under console, too.
96 setlocale(LC_ALL, "");
97 bindtextdomain (BINARY, LOCALEDIR);
98 bind_textdomain_codeset (BINARY, "UTF-8");
99 textdomain (BINARY);
100
101 const gchar *user_config_dir = g_get_user_config_dir();
102
103 #ifdef OUT_OF_MEMORY
104 # undef g_strdup_printf
105 #endif
106 if (user_config_dir) profile_dir = g_strdup_printf("%s/%s", user_config_dir, BINARY);
107 #ifdef OUT_OF_MEMORY
108 #define g_strdup_printf(...) NULL
109 #endif
110
111 // g_debug("profile_dir = %s", profile_dir);
112 proc_exist = g_file_test("/proc", G_FILE_TEST_EXISTS);
113
114 if (proc_exist)
115 {
116 gboolean proc_is_exist = FALSE;
117 GDir *dir = g_dir_open ("/proc", 0, NULL);
118 if (dir)
119 {
120 const gchar *entry = g_dir_read_name(dir);
121 if (entry) proc_is_exist = TRUE;
122 }
123 g_dir_close(dir);
124 // g_debug ("Got proc_is_exist = %d", proc_is_exist);
125 proc_exist = proc_is_exist;
126 }
127
128 shell = g_getenv("SHELL");
129 if (shell==NULL) shell = "";
130
131 pwd = g_getenv("PWD");
132 // pwd = g_get_current_dir();
133 #ifdef SAFEMODE
134 if (pwd==NULL) pwd = g_strdup("");
135 #endif
136 // g_debug("Got $PWD = %s", pwd);
137 home = g_getenv("HOME");
138 if (home==NULL) home = "";
139 // g_debug("Get $HOME = %s", home);
140
141 // deal the command line options
142 command_option(argc, argv);
143 if (wmclass_name==NULL) wmclass_name = g_getenv("RESOURCE_NAME");
144 if (wmclass_name==NULL) wmclass_name = "";
145 if (wmclass_class==NULL) wmclass_class = "";
146 // g_debug("Got wmclass_name = %s, wmclass_class = %s", wmclass_name, wmclass_class);
147
148 // init the gtk+2 engine
149 #ifndef UNIT_TEST
150 gtk_init(&argc, &argv);
151 #endif
152 // FIXME: we should get the single_process from profile. Current is command-line option only.
153 if (single_process)
154 {
155 // init socket data
156 if (init_socket_data())
157 {
158 // trying to connect to an existing LilyTerm
159 if (query_socket())
160 {
161 // success, sent the argc/argv to socket then quit
162 // g_debug("A LilyTerm socket server is exist already. exiting...");
163 if (send_socket(argc, argv, TRUE))
164 {
165 g_free(profile_dir);
166 exit (0);
167 }
168 }
169 // no LilyTerm exist. create a socket server
170 // g_debug("Creating a LilyTerm socket server...");
171 init_socket_server();
172 g_atexit((GVoidFunc)shutdown_socket_server);
173 }
174 }
175
176 // start LilyTerm
177
178 // empty_environ = g_strsplit("", " ", -1);
179 extern gchar **environ;
180 // print_array("main(): environ", environ);
181 gchar *environ_str = convert_array_to_string(environ, '\t');
182 window_list = NULL;
183 // g_debug("Got environ_str (in main.c) = %s", environ_str);
184 selection_clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
185 selection_primary = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
186 system_locale_list = get_locale_list();
187 // g_debug("Got system_locale_list = %s", system_locale_list);
188 init_LC_CTYPE = g_strdup(get_default_lc_data(LC_CTYPE));
189 // g_debug("Got init_LC_CTYPE = %s", init_LC_CTYPE);
190 init_LC_MESSAGES = g_strdup(get_default_lc_data(LC_MESSAGES));
191 // g_debug("init_LC_MESSAGES = %s", init_LC_MESSAGES);
192 init_encoding = (gchar *)get_encoding_from_locale(NULL);
193 if (! compare_strings(init_encoding, "ANSI_X3.4-1968", TRUE))
194 {
195 g_free(init_encoding);
196 init_encoding = g_strdup("UTF-8");
197 }
198 // g_debug("init_encoding = %s", init_encoding);
199 SYSTEM_VTE_CJK_WIDTH_STR = g_getenv("VTE_CJK_WIDTH");
200 // g_debug ("Got SYSTEM_VTE_CJK_WIDTH_STR = %s", SYSTEM_VTE_CJK_WIDTH_STR);
201 // FIXME: signal(SIGCHLD, SIG_IGN);
202 // The first window of LilyTerm
203
204 // g_debug("Got original encoding = %s", get_encoding_from_locale(NULL));
205 //GtkNotebook *new_window(int argc,
206 // char *argv[],
207 // gchar *shell,
208 // gchar *environment,
209 // gchar *locale_list,
210 // gchar *PWD,
211 // gchar *HOME,
212 // gchar *VTE_CJK_WIDTH_STR,
213 // gboolean VTE_CJK_WIDTH_STR_overwrite_profile,
214 // gchar *wmclass_name,
215 // gchar *wmclass_class,
216 // gchar *user_environ,
217 // gchar *encoding,
218 // gboolean encoding_overwrite_profile,
219 // gchar *lc_messages,
220 // struct Window *win_data_orig,
221 // struct Page *page_data_orig)
222
223 if ((new_window(argc,
224 argv,
225 (gchar *) shell,
226 environ_str,
227 system_locale_list,
228 (gchar *) pwd,
229 (gchar *) home,
230 SYSTEM_VTE_CJK_WIDTH_STR,
231 FALSE,
232 wmclass_name,
233 wmclass_class,
234 NULL,
235 init_encoding,
236 FALSE,
237 init_LC_MESSAGES,
238 NULL,
239 NULL)) ||
240 window_list)
241 {
242 // The argv of "main" LilyTerm can't be free.
243 // Set it to NULL here to avoid double_free().
244 argv=NULL;
245 // g_debug("gtk_main_level = %d", gtk_main_level());
246 if (! gtk_main_level())
247 gtk_main();
248 }
249 #ifdef DETAIL
250 else
251 {
252 // g_debug("Got window_list = %p", window_list);
253 // GList *win_list = window_list;
254 // gint i=0;
255 //
256 // while (win_list)
257 // {
258 // g_debug("Got %d win_data = %p", ++i, win_list->data);
259 // win_list = win_list->next;
260 // }
261 g_debug("??? The creation of first window is FAIL!!!");
262 }
263 #endif
264 extern struct KeyValue system_keys[KEYS];
265 gint i;
266 // g_debug("Clear function key data!!");
267 for (i=KEY_SWITCH_TO_TAB_1; i<=KEY_SWITCH_TO_TAB_12; i++)
268 {
269 g_free(system_keys[i].name);
270 g_free(system_keys[i].topic);
271 g_free(system_keys[i].comment);
272 g_free(system_keys[i].translation);
273 #ifdef UNIT_TEST
274 system_keys[i].name = NULL;
275 system_keys[i].topic = NULL;
276 system_keys[i].comment = NULL;
277 system_keys[i].translation = NULL;
278 #endif
279 }
280
281 // g_free(pwd);
282 // g_strfreev(empty_environ);
283 g_free(environ_str);
284 g_free(init_encoding);
285 g_free(system_locale_list);
286 g_free(profile_dir);
287 g_free(restricted_locale_message);
288 g_list_free(window_list);
289 g_free(init_LC_CTYPE);
290 g_free(init_LC_MESSAGES);
291 #ifdef UNIT_TEST
292 // empty_environ = NULL;
293 environ_str = NULL;
294 init_encoding = NULL;
295 system_locale_list = NULL;
296 profile_dir = NULL;
297 restricted_locale_message = NULL;
298 window_list = NULL;
299 init_LC_CTYPE = NULL;
300 init_LC_MESSAGES = NULL;
301 #endif
302 return 0;
303 }
304
305
306 // it will return TRUE if init socket data successfully
init_socket_data()307 gboolean init_socket_data()
308 {
309 #ifdef DETAIL
310 g_debug("! Launch init_socket_data() to init LilyTerm socket!");
311 #endif
312 GError *error = NULL;
313
314 // clean data first
315 bzero(&address, sizeof(address));
316 // init the address of socket
317 address.sun_family = AF_UNIX;
318
319 const gchar *tmp_dir = g_get_tmp_dir();
320 #ifdef SAFEMODE
321 if (tmp_dir)
322 {
323 #endif
324 gchar *display = gdk_get_display();
325 #if defined(DEVELOP)
326 g_snprintf(address.sun_path, UNIX_PATH_MAX, "%s/.%s_dev_%s%s",
327 tmp_dir ,BINARY, g_get_user_name(), display);
328 #elif defined(DEBUG)
329 g_snprintf(address.sun_path, UNIX_PATH_MAX, "%s/.%s_dbg_%s%s",
330 tmp_dir ,BINARY, g_get_user_name(), display);
331 #else
332 g_snprintf(address.sun_path, UNIX_PATH_MAX, "%s/.%s_%s%s",
333 tmp_dir ,BINARY, g_get_user_name(), display);
334 #endif
335 g_free(display);
336 #ifdef SAFEMODE
337 }
338 #endif
339 address.sun_path[UNIX_PATH_MAX-1] = address.sun_path[UNIX_PATH_MAX-2] = '\0';
340 // g_debug("The socket file is %s", address.sun_path);
341 address_len = sizeof(address);
342
343 // init socket
344 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
345 if (socket_fd < 0)
346 // main_channel is NULL, so that we don't need to launch clear_channel()
347 return socket_fault(1, error, NULL, FALSE);
348
349 // set this socket is non-block
350 return set_fd_non_block(&socket_fd);
351 }
352
353 // it will return TRUE if scucceed
set_fd_non_block(gint * fd)354 gboolean set_fd_non_block(gint *fd)
355 {
356 #ifdef DETAIL
357 if (fd)
358 g_debug("! Launch set_fd_non_block() with fd = %d!", *fd);
359 else
360 g_debug("! Launch set_fd_non_block() with fd = (%p)!", fd);
361 #endif
362 #ifdef SAFEMODE
363 if (fd==NULL) return FALSE;
364 #endif
365 GError *error = NULL;
366 gint flags = fcntl(*fd, F_GETFL, 0);
367 if (fcntl(*fd, F_SETFL, O_NONBLOCK|flags) < 0)
368 // main_channel is NULL, so that we don't need to launch clear_channel()
369 return socket_fault(8, error, NULL, FALSE);
370 return TRUE;
371 }
372
373 // it will return TRUE if scucceed
query_socket()374 gboolean query_socket()
375 {
376 #ifdef DETAIL
377 g_debug("! Launch query_socket() to connect to an existing LilyTerm !");
378 #endif
379 GError *error = NULL;
380
381 if (connect(socket_fd, (struct sockaddr *)&address, address_len) < 0)
382 // main_channel is NULL, so that we don't need to launch clear_channel()
383 return socket_fault(2, error, NULL, FALSE);
384 return TRUE;
385 }
386
387 // it will return TRUE if scucceed
send_socket(int argc,char * argv[],gboolean wait)388 gboolean send_socket( int argc,
389 char *argv[],
390 gboolean wait)
391 {
392 #ifdef DETAIL
393 g_debug("! Launch send_socket() to send data to the exiting LilyTerm !");
394 g_debug("! send_socket() argc = %d, wait = %d", argc, wait);
395 print_array("! send_socket() argv", argv);
396 #endif
397
398 GError *error = NULL;
399 gsize len;
400 extern gchar **environ;
401
402 gchar *locale_list = get_locale_list();
403
404 const gchar *VTE_CJK_WIDTH_STR = g_getenv("VTE_CJK_WIDTH");
405 // VTE_CJK_WIDTH can't = NULL
406 if (VTE_CJK_WIDTH_STR == NULL) VTE_CJK_WIDTH_STR = "";
407
408 // g_debug("Got LOCALE = %s in send_socket...", get_encoding_from_locale(NULL));
409 gchar *encoding = get_encoding_from_locale(NULL);
410 if (! compare_strings(encoding, "ANSI_X3.4-1968", TRUE))
411 {
412 g_free(encoding);
413 encoding = g_strdup("UTF-8");
414 }
415 // g_debug("Got encoding = %s in send_socket...", encoding);
416 gchar *lc_messages = g_strdup(get_default_lc_data(LC_MESSAGES));
417
418 gchar *environ_str = convert_array_to_string(environ, '\t');
419 // print_array("! send_socket() environ", environ);
420 // g_debug("environ_str = %s", environ_str);
421 gchar *argv_str = convert_array_to_string(argv, '\x10');
422 #ifdef SAFEMODE
423 gboolean need_free_argv_str = TRUE;
424 if (argv_str==NULL) argv_str=g_strdup("");
425 if (argv_str==NULL)
426 {
427 need_free_argv_str = FALSE;
428 argv_str = "";
429 }
430 #endif
431 // g_debug("argv_str = %s", argv_str);
432
433 // g_debug("SEND DATA: SOCKET_DATA_VERSION = %s", SOCKET_DATA_VERSION);
434 // g_debug("SEND DATA: locale_list = %s", locale_list);
435 // g_debug("SEND DATA: encoding = %s", encoding);
436 // g_debug("SEND DATA: PWD = %s", PWD);
437 // g_debug("SEND DATA: VTE_CJK_WIDTH_STR = %s", VTE_CJK_WIDTH_STR);
438 // g_debug("SEND DATA: wmclass_name = %s", wmclass_name);
439 // g_debug("SEND DATA: wmclass_class = %s", wmclass_class);
440 // g_debug("SEND DATA: environ_str = %s", environ_str);
441 // g_debug("SEND DATA: argv_str = %s", argv_str);
442 // 0 1 2 3 4 5 6 7 8 9 10 11
443 // send data: SOCKET_DATA_VERSION SHELL LOCALE_LIST ENCODING LC_MESSAGES PWD HOME VTE_CJK_WIDTH_STR wmclass_name wmclass_class ENVIRON ARGV
444 // 0 1 2 3 4 5 6 7 8 9 10 11
445 gchar *arg_str = g_strdup_printf("%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10%s\x10",
446 SOCKET_DATA_VERSION,
447 shell,
448 locale_list,
449 encoding,
450 lc_messages,
451 pwd,
452 home,
453 VTE_CJK_WIDTH_STR,
454 wmclass_name,
455 wmclass_class,
456 environ_str,
457 argv_str);
458 // g_debug("arg_str = %s", arg_str);
459 g_free(locale_list);
460 g_free(encoding);
461 g_free(lc_messages);
462 g_free(environ_str);
463 #ifdef SAFEMODE
464 if (need_free_argv_str)
465 #endif
466 g_free(argv_str);
467
468 // write data!
469 #ifdef SAFEMODE
470 if (fcntl(socket_fd, F_GETFL) < 0) return FALSE;
471 #endif
472 GIOChannel *channel = g_io_channel_unix_new(socket_fd);
473 // main_channel is NULL, so that we don't need to launch clear_channel()
474 if (!channel) return socket_fault(12, NULL, NULL, FALSE);
475 // set the channel to read binary file
476 if (g_io_channel_set_encoding(channel, NULL, &error) == G_IO_STATUS_ERROR)
477 return socket_fault(9, error, channel, TRUE);
478 g_io_channel_set_buffered (channel, FALSE);
479
480 #ifdef SAFEMODE
481 if ((arg_str == NULL) ||
482 (g_io_channel_write_chars(channel, arg_str, -1, &len, &error)==G_IO_STATUS_ERROR))
483 #else
484 if (g_io_channel_write_chars(channel, arg_str, -1, &len, &error)==G_IO_STATUS_ERROR)
485 #endif
486 // main_channel is NULL, so that we don't need to launch clear_channel()
487 return socket_fault(11, error, channel, TRUE);
488 // flush writing datas
489 if (g_io_channel_flush(channel, &error) == G_IO_STATUS_ERROR)
490 // main_channel is NULL, so that we don't need to launch clear_channel()
491 return socket_fault(13, error, channel, TRUE);
492
493 g_free(arg_str);
494
495 // So far so good. shutdown and clear channel!
496 clear_channel(channel, TRUE);
497
498 // FIXME: sleep for 1 sec to wait the socket server. any better idea?
499 if (wait) sleep(1);
500
501 return TRUE;
502 }
503
504 // it will return TRUE if succeed
init_socket_server()505 gboolean init_socket_server()
506 {
507 #ifdef DETAIL
508 g_debug("! Launch init_socket_server() to init a LilyTerm socket server !");
509 #endif
510 GError *error = NULL;
511
512 // clear the prev file
513 if (address.sun_path) unlink(address.sun_path);
514
515 // bind the socket on a file
516 if (bind(socket_fd, (struct sockaddr *)&address, address_len) < 0)
517 // main_channel is NULL, so that we don't need to launch clear_channel()
518 return socket_fault(3, error, NULL, FALSE);
519
520 // create socket queue
521 if (listen(socket_fd, 5) < 0)
522 // main_channel is NULL, so that we don't need to launch clear_channel()
523 return socket_fault(4, error, NULL, FALSE);
524
525 main_channel = g_io_channel_unix_new(socket_fd);
526 if (!main_channel) return socket_fault(12, NULL, NULL, FALSE);
527 // set the channel to read binary file
528 if (g_io_channel_set_encoding(main_channel, NULL, &error) == G_IO_STATUS_ERROR)
529 return socket_fault(9, error, main_channel, TRUE);
530
531 // if any request from client, call accept_socket().
532 // the channel will be clean when main_quit()
533 if ( ! g_io_add_watch ( main_channel, G_IO_IN|G_IO_HUP, (GIOFunc)accept_socket, NULL))
534 return socket_fault(5, error, NULL, TRUE);
535
536 return TRUE;
537 }
538
539 // it will return TRUE if succeed
accept_socket(GIOChannel * source,GIOCondition condition,gpointer user_data)540 gboolean accept_socket(GIOChannel *source, GIOCondition condition, gpointer user_data)
541 {
542 #ifdef DETAIL
543 g_debug("! Launch accept_socket() to accept the request from client !");
544 #endif
545 #ifdef SAFEMODE
546 if (source==NULL) return FALSE;
547 #endif
548
549 GError *error = NULL;
550
551 if (condition & G_IO_HUP)
552 return socket_fault(6, error, source, FALSE);
553 else
554 {
555 gint read_fd = accept(g_io_channel_unix_get_fd(source), NULL, NULL);
556 if (read_fd < 0)
557 return socket_fault(1, error, source, FALSE);
558 if ( ! set_fd_non_block(&read_fd)) return FALSE;
559
560 GIOChannel* channel = g_io_channel_unix_new(read_fd);
561 // channel is NULL, so that we don't need to launch clear_channel()
562 if (!channel) return socket_fault(12, NULL, channel, FALSE);
563 // set the channel to read binary file
564 if (g_io_channel_set_encoding(channel, NULL, &error) == G_IO_STATUS_ERROR)
565 return socket_fault(9, error, channel, TRUE);
566
567 // read the data that client sent.
568 if ( ! g_io_add_watch(channel, G_IO_HUP, read_socket, NULL))
569 return socket_fault(5, error, channel, TRUE);
570 }
571 return TRUE;
572 }
573
574 // it will return TRUE if succeed
read_socket(GIOChannel * channel,GIOCondition condition,gpointer user_data)575 gboolean read_socket(GIOChannel *channel, GIOCondition condition, gpointer user_data)
576 {
577 #ifdef DETAIL
578 g_debug("! Launch read_socket() to read data !");
579 #endif
580 #ifdef SAFEMODE
581 if (channel==NULL) return FALSE;
582 #endif
583
584 GError *error = NULL;
585 gchar *data = NULL, **datas;
586 gsize len = 0;
587 gsize term;
588
589 if (g_io_channel_read_line (channel, &data, &len, &term, &error) == G_IO_STATUS_ERROR)
590 return socket_fault(7, error, channel, TRUE);
591 // g_debug("Read %ld bytes from Lilyterm socket: '%s'", len, data);
592 if (len > 0)
593 {
594 // 0 1 2 3 4 5 6 7 8 9 10 11
595 // get data: SOCKET_DATA_VERSION SHELL LOCALE_LIST ENCODING LC_MESSAGES PWD HOME VTE_CJK_WIDTH_STR wmclass_name wmclass_class ENVIRON ARGV
596 // clear '\n' at the end of data[]
597 data[len-1] = 0;
598
599 datas = split_string(data, "\x10", 12);
600 // g_debug("The SOCKET_DATA_VERSION = %s ,and the data sent via socket is %s",
601 // SOCKET_DATA_VERSION, datas[0]);
602 if ((datas==NULL) || compare_strings(SOCKET_DATA_VERSION, datas[0], TRUE))
603 {
604 // The SOCKET_DATA_VERSION != the data sent via socket
605 gchar *received_socket_version = NULL;
606 if (datas) received_socket_version = datas[0];
607
608 gchar *message = g_strdup_printf(_("The data got from socket seems incorrect.\n\n"
609 "\tReceived socket version: %s\n"
610 "\tExpected socket version: %s\n\n"
611 "If you just updated %s recently,\n"
612 "Please close all the windows of %s and try again."),
613 received_socket_version, SOCKET_DATA_VERSION,
614 PACKAGE, PACKAGE);
615 error_dialog(NULL,
616 _("The format of socket data is out of date"),
617 "The format of socket data is out of date",
618 GTK_STOCK_DIALOG_ERROR,
619 message,
620 NULL);
621 g_free(message);
622 }
623 else
624 {
625 gchar **argv = split_string(datas[11], "\x10", -1);
626 gint argc = 0;
627 if (argv)
628 while (argv[argc])
629 argc ++;
630
631 // g_debug("Final:");
632 // g_debug("\targc =%d", argc);
633 // print_array("\targv", argv);
634 // g_debug("\tSHELL = %s", datas[1]);
635 // g_debug("\tenvironments = %s", datas[10]);
636 // g_debug("\tlocale_list = %s", datas[2]);
637 // g_debug("\tPWD = %s", datas[5]);
638 // g_debug("\tHOME = %s", datas[6]);
639 // g_debug("\tVTE_CJK_WIDTH_STR = %s", datas[7]);
640 // g_debug("\twmclass_name = %s", datas[8]);
641 // g_debug("\twmclass_class= %s", datas[9]);
642 // g_debug("\tencoding = %s", datas[3]);
643 // g_debug("\tlc_messages = %s", datas[4]);
644
645 //GtkNotebook *new_window(int argc,
646 // char *argv[],
647 // gchar *shell, // 1
648 // gchar *environment, // 10
649 // gchar *locale_list, // 2
650 // gchar *PWD, // 5
651 // gchar *HOME, // 6
652 // gchar *VTE_CJK_WIDTH_STR, // 7
653 // gboolean VTE_CJK_WIDTH_STR_overwrite_profile,
654 // gchar *wmclass_name, // 8
655 // gchar *wmclass_class, // 9
656 // gchar *user_environ,
657 // gchar *encoding, // 3
658 // gboolean encoding_overwrite_profile,
659 // gchar *lc_messages, // 4
660 // struct Window *win_data_orig,
661 // struct Page *page_data_orig)
662
663 new_window(argc,
664 argv,
665 datas[1],
666 datas[10],
667 datas[2],
668 datas[5],
669 datas[6],
670 datas[7],
671 FALSE,
672 datas[8],
673 datas[9],
674 NULL,
675 datas[3],
676 FALSE,
677 datas[4],
678 NULL,
679 NULL);
680 g_strfreev(argv);
681 }
682 g_strfreev(datas);
683 data[len-1] = '\n';
684 g_free(data);
685 }
686 clear_channel(channel, TRUE);
687 // return FALSE means this connection is finish.
688 return FALSE;
689 }
690
691 // it will always return FALSE
socket_fault(int type,GError * error,GIOChannel * channel,gboolean unref)692 gboolean socket_fault(int type, GError *error, GIOChannel *channel, gboolean unref)
693 {
694 #ifdef DETAIL
695 g_debug("! Launch socket_fault() to show the error message !");
696 #endif
697 #ifdef UNIT_TEST
698 # define G_WARNING g_message
699 #else
700 # define G_WARNING g_warning
701 #endif
702 switch (type)
703 {
704 case 1:
705 G_WARNING("Error when create %s socket(%s): %s",
706 PACKAGE, address.sun_path, g_strerror (errno));
707 break;
708 case 2:
709 g_message("Can NOT connect to a existing %s socket!", PACKAGE);
710 break;
711 case 3:
712 G_WARNING("Can NOT bind on the socket!");
713 break;
714 case 4:
715 G_WARNING("Can NOT listen on the socket!");
716 break;
717 case 5:
718 G_WARNING("Can not watch on the socket!");
719 break;
720 case 6:
721 G_WARNING("Error when accepting client request via socket!");
722 break;
723 case 7:
724 G_WARNING("Error when reading the data client sent via socket!");
725 break;
726 case 8:
727 G_WARNING("Error when running fcntl command on socket!");
728 break;
729 case 9:
730 #ifdef SAFEMODE
731 if (error)
732 #endif
733 G_WARNING("Error when setting the encoding of channel: %s", error->message);
734 break;
735 case 10:
736 #ifdef SAFEMODE
737 if (error)
738 #endif
739 G_WARNING("Error when shutdowning a channel: %s", error->message);
740 break;
741 case 11:
742 #ifdef SAFEMODE
743 if (error)
744 #endif
745 G_WARNING("Error when writing data to the channel: %s", error->message);
746 break;
747 case 12:
748 G_WARNING("Can NOT create a channel for this socket");
749 break;
750 case 13:
751 #ifdef SAFEMODE
752 if (error)
753 #endif
754 G_WARNING("Error when flushing the write buffer for the channel: %s", error->message);
755 break;
756 default:
757 #ifdef FATAL
758 print_switch_out_of_range_error_dialog("socket_fault", "type", type);
759 #endif
760 break;
761 }
762 if (error) g_clear_error (&error);
763 clear_channel(channel, unref);
764 #ifdef UNIT_TEST
765 # undef G_WARNING
766 #endif
767 return FALSE;
768 }
769
770 // it will return TRUE if scucceed
clear_channel(GIOChannel * channel,gboolean unref)771 gboolean clear_channel(GIOChannel *channel, gboolean unref)
772 {
773 #ifdef DETAIL
774 g_debug("! Launch clear_channel() to clear channel data !");
775 #endif
776 if (channel == NULL) return TRUE;
777
778 gboolean return_value = TRUE;
779 GError *error = NULL;
780
781 if (g_io_channel_shutdown(channel, TRUE, &error) == G_IO_STATUS_ERROR)
782 return_value = socket_fault(10, error, NULL, FALSE);
783
784 if (return_value && unref)
785 {
786 g_io_channel_unref(channel);
787 channel = NULL;
788 }
789
790 return return_value;
791 }
792
793 // It should always return 0.
shutdown_socket_server(gpointer data)794 gint shutdown_socket_server(gpointer data)
795 {
796 #ifdef DETAIL
797 g_debug("! Launch shutdown_socket_server() to shutdown the LilyTerm socket server!");
798 #endif
799 if (main_channel) clear_channel(main_channel, TRUE);
800 if (address.sun_path) unlink(address.sun_path);
801 return 0;
802 }
803
main_quit(GtkWidget * widget,struct Window * win_data)804 void main_quit(GtkWidget *widget, struct Window *win_data)
805 {
806 #ifdef DETAIL
807 g_debug("! Launch main_quit() with win_data = %p!", win_data);
808 #endif
809 // g_debug("Total window = %d", g_list_length(window_list));
810 if (g_list_length(window_list)==1)
811 {
812 #ifdef SAFEMODE
813 // g_debug ("main_quit(): win_data==NULL, call gtk_main_quit()");
814 if (win_data==NULL) return quit_gtk();
815 #endif
816 window_quit(win_data->window, NULL, win_data);
817 }
818 else
819 {
820 GString *all_process_list = g_string_new(NULL);
821 GString *child_process_list;
822 GList *win_list = window_list;
823 struct Window *temp_win_data;
824 gint i = 1;
825 while (win_list)
826 {
827 temp_win_data = win_list->data;
828 child_process_list = close_multi_tabs(temp_win_data, i);
829 #ifdef SAFEMODE
830 if (child_process_list)
831 #endif
832 g_string_append (all_process_list, child_process_list->str);
833 g_string_free(child_process_list, TRUE);
834 win_list = win_list->next;
835 i++;
836 }
837
838 // g_debug("Got all_process_list =%s", all_process_list->str);
839 #ifdef SAFEMODE
840 if ((all_process_list==NULL) || (all_process_list->len==0) ||
841 (display_child_process_dialog (all_process_list, win_data,
842 CONFIRM_TO_EXIT_WITH_CHILD_PROCESS)))
843 #else
844 if ((all_process_list->len==0) ||
845 (display_child_process_dialog (all_process_list, win_data,
846 CONFIRM_TO_EXIT_WITH_CHILD_PROCESS)))
847 #endif
848 {
849 force_to_quit = TRUE;
850 // g_debug ("main_quit(): call gtk_main_quit()");
851 quit_gtk();
852 }
853 g_string_free(all_process_list, TRUE);
854 }
855 }
856
quit_gtk()857 void quit_gtk()
858 {
859 #ifdef DETAIL
860 g_debug("! Launch quit_gtk()");
861 #endif
862 if (gtk_main_level()) gtk_main_quit();
863 }
864
get_locale_list()865 gchar *get_locale_list()
866 {
867 #ifdef DETAIL
868 g_debug("! Launch get_locale_list()!");
869 #endif
870 #ifdef OUT_OF_MEMORY
871 # undef g_getenv
872 #endif
873 return join_strings_to_string(' ',
874 14,
875 g_getenv("LANG"),
876 g_getenv("LC_CTYPE"),
877 g_getenv("LC_NUMERIC"),
878 g_getenv("LC_TIME"),
879 g_getenv("LC_COLLATE"),
880 g_getenv("LC_MONETARY"),
881 g_getenv("LC_MESSAGES"),
882 g_getenv("LC_PAPER"),
883 g_getenv("LC_NAME"),
884 g_getenv("LC_ADDRESS"),
885 g_getenv("LC_TELEPHONE"),
886 g_getenv("LC_MEASUREMENT"),
887 g_getenv("LC_IDENTIFICATION"),
888 g_getenv("LC_ALL"));
889 #ifdef OUT_OF_MEMORY
890 #define g_getenv(x) NULL
891 #endif
892 }
893
894 //// The returned GString should be freed when no longer needed.
895 //GString *convert_string_array_to_0x9_separated_gstring (gchar **string_array)
896 //{
897 // gint i = 0;
898 // GString *string = g_string_new("");
899 //
900 // if (string_array!=NULL)
901 // {
902 // while (string_array[i]!=NULL)
903 // {
904 // // g_debug("%d: %s", i, string_array[i]);
905 // g_string_append_printf(string, "%s\x10", string_array[i]);
906 // i++;
907 // }
908 // }
909 // return string ;
910 //}
911