1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 open CommonInteractive
37 open Gettext
(* open last as most modules redefine _s and _b *)
39 let _s x
= _s "DriverMain" x
40 let _b x
= _b "DriverMain" x
42 let log_prefix = "[dMain]"
45 lprintf_nl2
log_prefix fmt
48 lprintf2
log_prefix fmt
56 DriverInteractive.hdd_check
();
57 CommonUploads.upload_credit_timer
();
58 CommonInteractive.force_download_quotas
();
59 CommonResult.dummy_result
.result_time
<- last_time
();
61 CommonSwarming.verify_some_chunks
()
63 CommonClient.clear_upload_slots
()
65 let hourly_timer timer
=
67 CommonWeb.load_web_infos
false false;
68 if !CommonWeb.hours
mod !!compaction_delay
= 0 then Gc.compact
();
69 if !!backup_options_delay
<> 0
70 && !CommonWeb.hours
mod !!backup_options_delay
= 0 then
71 CommonComplexOptions.backup_options
();
72 DriverControlers.check_calendar
();
73 CommonFile.propose_filenames
()
75 let ten_second_timer timer
=
77 List.iter
(fun file
->
79 ) !!CommonComplexOptions.done_files
81 let second_timer timer
=
85 lprintf_nl (_b "Exception %s") (Printexc2.to_string e
));
87 CommonUploads.refill_upload_slots
()
89 lprintf_nl (_b "Exception %s") (Printexc2.to_string e
));
90 CommonUploads.shared_files_timer
();
93 let start_interfaces () =
95 (* option_hook(s) are not called when ini files are created the first time
96 force re-load of allowed_ips to call option_hook which fills the IP blocklist *)
98 match !created_new_base_directory
with
100 | Some dir
-> allowed_ips
=:= !!allowed_ips
103 if !!http_port
<> 0 then begin
105 ignore
(DriverControlers.create_http_handler
());
107 lprintf_nl (_b "Exception %s while starting HTTP interface")
108 (Printexc2.to_string e
);
111 if !!telnet_port
<> 0 then begin
113 ignore
(find_port
"telnet server" !!telnet_bind_addr
114 telnet_port
DriverControlers.telnet_handler
);
116 lprintf_nl (_b "Exception %s while starting Telnet interface")
117 (Printexc2.to_string e
);
120 if !!gui_port
<> 0 then begin
122 ignore
(find_port
"gui server" !!gui_bind_addr
123 gui_port gui_handler
);
125 lprintf_nl (_b "Exception %s while starting GUI interface")
126 (Printexc2.to_string e
);
129 if !!gift_port
<> 0 then begin
131 ignore
(find_port
"gift server" !!gui_bind_addr
132 gift_port gift_handler
);
134 lprintf_nl (_b "Exception %s while starting GUI interface")
135 (Printexc2.to_string e
);
138 add_infinite_option_timer update_gui_delay
DriverInterface.update_gui_info
;
139 add_infinite_timer
1. second_timer
142 let save_mlsubmit_reg () =
144 (* Generate the mlsubmit.reg file *)
146 let file = Printf.sprintf
148 "Windows Registry Editor Version 5.00
150 [HKEY_CLASSES_ROOT\\ed2k]
151 @=\"URL: ed2k Protocol\"
152 \"URL Protocol\"=\"\"
154 [HKEY_CLASSES_ROOT\\ed2k\\shell]
156 [HKEY_CLASSES_ROOT\\ed2k\\shell\\open]
158 [HKEY_CLASSES_ROOT\\ed2k\\shell\\open\\command]
159 @=\"\\\"IEXPLORE.EXE\\\" \\\"http://%s:%s@%s:%d/submit?q=dllink+%%1\\\"\"
162 "admin" "" (Ip.to_string
(client_ip None
)) !!http_port
164 File.from_string
(Filename.concat file_basedir
"mlsubmit.reg") file;
166 (* Generate the mldonkey_submit file *)
168 let file = Printf.sprintf
172 # Submit an eDonkey download request to mldonkey
174 # Argument(s): An ed2k URI of the form:
176 # ed2k://|file|<filename>|<filesize>|<MD4-sum|
179 ($#ARGV >= 0) || die \"Usage: mldonkey_submit <ed2kURI> ...\n\";
181 $vars{'HTTPURL'} = \"http://%s:%d\";
182 $vars{'HTTPUSER'} = \"%s\";
183 $vars{'HTTPPASS'} = \"%s\";
185 my $ua = LWP::UserAgent->new;
187 while (my $uri = shift @ARGV) {
188 $_ = URI::Escape::uri_unescape($uri);
189 if (/^ed2k:\\/\\/\\|file\\|[^|]+\\|(\\d+)\\|([\\dabcdef]+)\\|$/) {
192 my $req = HTTP::Request->new(
193 GET => \"$vars{'HTTPURL'}/submit?q=dllink+$uri\"
195 if (($vars{'HTTPUSER'}) && ($vars{'HTTPPASS'})) {
196 $req->authorization_basic($vars{'HTTPUSER'},
199 my $response = $ua->request($req);
200 if (!($response->is_success)) {
201 print $response->error_as_HTML;
205 print \"Not an ed2k URI: $_\n\";
210 (Ip.to_string
(client_ip None
)) !!http_port
213 File.from_string
(Filename.concat file_basedir
"mldonkey_submit") file;
214 Unix2.chmod
(Filename.concat file_basedir
"mldonkey_submit") 0o755
218 DriverInterface.install_hooks
();
220 (**** LOAD OPTIONS ****)
222 let exists_downloads_ini =
223 Sys.file_exists
(options_file_name downloads_ini
) in
224 let exists_users_ini =
225 Sys.file_exists
(options_file_name users_ini
)
227 if not
exists_users_ini && exists_downloads_ini then
229 lprintf_nl "No config file (users.ini) found. Importing users from downloads.ini.";
230 ( try Unix2.copy
"downloads.ini" "users.ini" with _
-> () );
233 let ini_files_exist = Sys.file_exists
(options_file_name downloads_ini
) in
236 Options.load downloads_ini
;
237 Options.load users_ini
;
238 DriverInteractive.hdd_check
()
240 lprintf_nl "Exception %s during options load" (Printexc2.to_string e
);
243 (* Here, we try to update options when a new version of mldonkey is
244 used. For example, we can add new web_infos... *)
245 CommonOptions.update_options
();
247 CommonMessages.load_message_file
();
248 if !!html_mods
then begin
249 if !!html_mods_style
> 0 && !!html_mods_style
< Array.length
CommonMessages.styles
then
250 commands_frame_height
=:= CommonMessages.styles
.(!!html_mods_style
).CommonMessages.frame_height
;
251 CommonMessages.colour_changer
();
253 networks_iter_all
(fun r
->
254 (* lprintf "(n) loading network config file\n"; *)
255 List.iter
(fun opfile
->
259 Options.save_with_help opfile
261 r
.network_config_file
265 (**** PARSE ARGUMENTS ***)
267 let more_args = ref [] in
270 more_args := !more_args
271 @ (Options.simple_args
"" downloads_ini
);
272 more_args := !more_args
273 @ (Options.simple_args
"" users_ini
);
275 networks_iter_all
(fun r
->
276 List.iter
(fun opfile
->
277 let prefix = r
.network_shortname ^
"-" in
278 let args = simple_args
prefix opfile
in
279 let args = List2.tail_map
(fun (arg
, spec
, help
) ->
280 (Printf.sprintf
"-%s" arg
, spec
, help
)) args
282 more_args := !more_args @ args
283 ) r
.network_config_file
287 "-v", Arg.Unit
(fun _
->
288 lprintf_nl "%s" (CommonGlobals.version
());
289 exit
0), _s " : print version number and exit";
290 "-exit", Arg.Unit
(fun _
-> exit
0), ": exit immediatly";
291 "-format", Arg.String
(fun file ->
292 ignore
(CommonMultimedia.get_info
file)),
293 _s " <filename> : check file format";
294 "-test_ip", Arg.String
(fun ip
->
295 lprintf_nl "%s = %s" ip
(Ip.to_string
(Ip.of_string ip
));
296 exit
0), _s "<ip> : undocumented";
297 "-check_impl", Arg.Unit
(fun _
->
298 CommonNetwork.check_network_implementations
();
299 CommonClient.check_client_implementations
();
300 CommonServer.check_server_implementations
();
301 CommonFile.check_file_implementations
();
302 (* CommonResult.check_result_implementations (); *)
305 _s " : display information on the implementations";
306 "-stdout", Arg.Unit
(fun _
->
307 lprintf_original_output
:= (Some stdout
);
310 _s ": keep output to stdout after startup";
311 "-stderr", Arg.Unit
(fun _
->
312 lprintf_original_output
:= (Some stderr
);
315 _s ": keep output to stderr after startup";
316 "-daemon", Arg.Unit
(fun _
->
317 (* Removed due to savannah bug #11514 . *)
318 lprintf_nl "\n\nOption -daemon was removed.\nUse 'mlnet > /dev/null 2>&1 &' instead. Exiting...";
319 exit
64), _s " : this argument was removed, core will exit";
320 "-find_port", Arg.Set find_other_port
,
321 _s " : find another port when one is already used";
322 "-pid", Arg.String
(fun s
-> pid := s
;
324 _s ": directory for pid file";
325 "-useradd", Arg.Rest
(fun s
->
326 (match String2.split s ' '
with
327 | user
:: pass
:: _
->
328 if user2_user_exists user
then
330 user2_user_set_password
(user2_user_find user
) pass
;
331 Printf.printf
"%sPassword of user %s changed\n%!" (log_time
()) user
335 user2_user_add user
(Md4.Md4.string pass
) ();
336 Printf.printf
"%sUser %s added\n%!" (log_time
()) user
338 Options.save_with_help_private users_ini
;
339 Printf.printf
"%sSaved changes to users.ini\n%!" (log_time
())
340 | _
-> raise
(Arg.Bad
"invalid syntax"));
341 exit
0), _s "\"<user> <pass>\" : create user/change password";
347 (* Files.dump_file file; exit 0 *)
350 if not
ini_files_exist && not
(keep_console_output
()) then log_file
=:= "mlnet.log";
352 (**** CREATE DIRS ****)
355 Unix2.safe_mkdir s
.shdir_dirname
;
356 if s
.shdir_strategy
= "incoming_directories" ||
357 s
.shdir_strategy
= "incoming_files" then
358 Unix2.can_write_to_directory s
.shdir_dirname
359 ) !!CommonComplexOptions.shared_directories
;
360 Unix2.safe_mkdir
"searches";
361 Unix2.can_write_to_directory
"searches";
362 Unix2.safe_mkdir
"web_infos";
363 Unix2.can_write_to_directory
"web_infos";
364 Unix2.safe_mkdir
!!temp_directory
;
365 Unix2.can_write_to_directory
!!temp_directory
369 let t = Unix.localtime
(Unix.time
()) in
370 if (t.Unix.tm_year
<=104) then
372 lprintf_nl (_b "\n\n\nYour system has a system date earlier than 2004, please correct it.");
373 lprintf_nl (_b "MLdonkey can not work with such a system date, exiting...");
374 CommonGlobals.exit_properly
71
377 ( let resolve_name hostname
=
379 ignore
(Ip.from_name hostname
);
384 ["www.mldonkey.org"; "mldonkey.sf.net"; "www.mldonkey.net"; "www.google.com"]
386 DriverInteractive.dns_works
:= List.exists
resolve_name hostnames;
388 if not
!DriverInteractive.dns_works
then lprintf
"
389 The core therefore is unable to get eDonkey serverlists and loading
390 .torrent files via dllink from websites is also impossible.
391 If you are using MLDonkey in a chroot environment you should
392 consider reading this article to get DNS support back:
393 http://mldonkey.sourceforge.net/Chroot\n\n");
395 let real_glibc_version = MlUnix.glibc_version_num
() in
396 if real_glibc_version <> Autoconf.glibc_version
397 && real_glibc_version <> "" then
400 This core is running with glibc %s but it was compiled with glibc %s.
401 This can lead to unexpected behaviour. Consider compiling the core yourself
402 or getting a binary compiled with glibc %s.\n\n")
403 real_glibc_version Autoconf.glibc_version
Autoconf.glibc_version
406 if Autoconf.magic
then begin
407 (if Sys.file_exists
"./magic/magic" then
408 try Unix.putenv
"MAGIC" "./magic/magic" with _ -> ());
409 if Magic.M.magic_works
() then
411 Autoconf.magic_works
:= true;
412 lprintf_nl (_b "Libmagic file-type recognition database present")
416 Autoconf.magic_works
:= false;
417 lprintf_nl (_b "Libmagic file-type recognition database not present")
421 if not
!Charset.Locale.conversion_enabled
then
422 lprintf_nl (_b "Self-test failed, charset conversion disabled.");
426 add_infinite_option_timer download_sample_rate
CommonFile.sample_timer
;
428 (* lprintf "(1) CommonComplexOptions.load\n"; *)
429 CommonComplexOptions.load
();
430 CommonUploads.load
();
433 (* lprintf "(2) CommonComplexOptions.load done\n"; *)
435 let old_save_results = !!save_results
in
437 CommonComplexOptions.save
();
438 CommonUploads.save
();
439 save_results
=:= old_save_results;
442 CommonGlobals.is_startup_phase
:= false;
444 (* before activating network modules load all local files from web_infos/
445 to avoid security holes, especially for IP blocking *)
446 Hashtbl.iter
(fun key w
->
447 let file = Filename.concat
"web_infos" (Filename.basename w
.url
) in
448 if Sys.file_exists
file then
450 lprintf_nl "loading %s from %s" w
.kind
file;
451 ((List.assoc w
.kind
!CommonWeb.file_kinds
).f w
.url
) file;
452 w
.state
<- Some FileLoaded
;
458 lprintf_nl (_b "Check http://www.mldonkey.org for updates");
459 networks_iter
(fun r
-> network_load_complex_options r
);
460 lprintf_nl (_b "enabling networks: ");
461 networks_iter
(fun r
->
462 lprintf_nl (_b "---- enabling %s ----") r
.network_name
;
464 List.iter
(fun (p
,s
) -> if p
<> 0 then lprintf_nl "using port %d (%s)" p s
) (network_ports r
);
465 (* are there drawbacks to start recover_temp unconditionally here ? *)
466 if !!recover_temp_on_startup
then
467 network_recover_temp r
;
469 lprintf_nl (_b "---- enabling interfaces ----");
470 List.iter
(fun (p
,s
) -> if p
<> 0 then lprintf_nl "using port %d (%s)" p s
)
471 (network_ports
(network_find_by_name
"Global Shares"));
472 lprintf
(_b "%s[dMain] disabled networks: ") (log_time
());
473 let found = ref false in
474 networks_iter_all
(fun r
->
475 if not
(network_is_enabled r
) then
478 lprintf
(_b "%s ") r
.network_name
480 if not
!found then lprintf
(_b "none");
482 networks_iter_all
(fun n
-> network_update_options n
);
483 CommonOptions.start_running_plugins
:= true;
484 CommonInteractive.force_download_quotas
();
486 TcpBufferedSocket.set_max_connections_per_second
487 (fun _ -> !!max_connections_per_second
);
489 add_infinite_option_timer save_options_delay
(fun timer
->
490 DriverInteractive.save_config
());
493 add_infinite_timer
60. minute_timer;
494 add_infinite_timer
10. ten_second_timer;
495 add_infinite_timer
3600. hourly_timer;
496 add_infinite_timer
0.1 CommonUploads.upload_download_timer
;
497 add_infinite_timer
!!buffer_writes_delay
(fun _ -> Unix32.flush
());
499 if !!share_scan_interval
<> 0 then
500 add_infinite_timer
((float_of_int
!!share_scan_interval
) *. 60.)
501 (fun _ -> CommonShared.shared_check_files
());
502 CommonShared.shared_check_files
();
504 history_timeflag
:= (Unix.time
());
505 update_download_history
();
506 update_upload_history
();
507 history_h_timeflag
:= (Unix.time
());
508 update_h_download_history
();
509 update_h_upload_history
();
510 history_size_for_h_graph
:= history_size
* !!html_mods_vd_gfx_h_intervall
/ 60;
511 history_h_step
:= 60 * !!html_mods_vd_gfx_h_intervall
;
513 add_infinite_timer
(float_of_int history_step
) (fun timer
->
514 history_timeflag
:= (Unix.time
());
515 update_download_history
();
516 update_upload_history
());
518 add_infinite_timer
(float_of_int
!history_h_step
) (fun timer
->
519 history_h_timeflag
:= (Unix.time
());
520 update_h_download_history
();
521 update_h_upload_history
());
523 if Autoconf.system
= "mingw" then
524 add_infinite_timer
1. (fun timer
->
525 MlUnix.set_console_title
(DriverInteractive.console_topic
()));
528 CommonShared.shared_add_directory
529 !!CommonComplexOptions.shared_directories
;
531 add_infinite_timer
1800. (fun timer
->
532 DriverInteractive.browse_friends
());
534 Options.prune_file downloads_ini
;
535 Options.prune_file users_ini
;
536 add_timer
1. (fun _ -> try CommonWeb.load_web_infos
true false with _ -> ());
537 if !!telnet_port
<> 0 then lprintf_nl (_b "To command: telnet %s %d")
538 (if !!telnet_bind_addr
= Ip.any
then "127.0.0.1"
539 else Ip.to_string
!!telnet_bind_addr
) !!telnet_port
;
540 if !!http_port
<> 0 then begin
541 lprintf_nl (_b "Or with browser: http://%s:%d")
542 (if !!http_bind_addr
= Ip.any
then "127.0.0.1"
543 else Ip.to_string
!!http_bind_addr
) !!http_port
;
544 lprintf_nl (_b "For a GUI check out http://sancho-gui.sourceforge.net")
546 if !!gui_port
<> 0 then lprintf_nl (_b "Connect to IP %s, port %d")
547 (if !!gui_bind_addr
= Ip.any
then "127.0.0.1"
548 else Ip.to_string
!!gui_bind_addr
) !!gui_port
;
549 lprintf_nl (_b "If you connect from a remote machine adjust allowed_ips");
550 if Autoconf.system
= "cygwin" && not
(keep_console_output
()) then lprintf
(_b "%s") win_message
;
552 add_init_hook
(fun _ ->
553 if not
!gui_included
&& ( !!start_gui
|| !!ask_for_gui
) then
555 let _ = Sys.getenv
("DISPLAY") in
556 if !!start_gui
&& Sys.file_exists
!!mldonkey_gui
then
557 ignore
(Sys.command
(Printf.sprintf
"%s &" !!mldonkey_gui
))
559 let asker = Filename.concat
!!mldonkey_bin
"mlguistarter" in
560 if !!ask_for_gui
&& Sys.file_exists
!!mldonkey_gui
&&
561 Sys.file_exists
asker then
562 ignore
(Sys.command
(Printf.sprintf
"%s %s&" asker !!mldonkey_gui
));
564 lprintf_nl (_b "Not running under X, not trying to start the GUI")
568 if !!run_as_group
<> "" then begin
570 let new_gr = Unix.getgrnam
!!run_as_group
in
571 MlUnix.setgid
new_gr.Unix.gr_gid
;
572 let gr = Unix.getgrgid
(Unix.getgid
()) in
573 lprintf_nl (_b "mldonkey is now running as group %s") gr.Unix.gr_name
;
575 lprintf_nl (_b "Exception %s trying to set group_gid [%s]")
576 (Printexc2.to_string e
) !!run_as_group
;
580 if !!run_as_groupgid
<> 0 then begin
582 MlUnix.setgid
!!run_as_groupgid
;
583 lprintf_nl (_b "mldonkey is now running as gid %d") !!run_as_groupgid
;
585 lprintf_nl (_b "Exception %s trying to set group_gid [%d]")
586 (Printexc2.to_string e
) !!run_as_groupgid
;
590 if !!run_as_user
<> "" then begin
592 let new_pw = Unix.getpwnam
!!run_as_user
in
593 MlUnix.setuid
new_pw.Unix.pw_uid
;
594 let pw = Unix.getpwuid
(Unix.getuid
()) in
595 lprintf_nl (_b "mldonkey is now running as user %s") pw.Unix.pw_name
;
597 lprintf_nl (_b "Exception %s trying to set user_uid [%s]")
598 (Printexc2.to_string e
) !!run_as_user
;
602 if !!run_as_useruid
<> 0 then begin
604 MlUnix.setuid
!!run_as_useruid
;
605 lprintf_nl (_b "mldonkey is now running as uid %d") !!run_as_useruid
;
607 lprintf_nl (_b "Exception %s trying to set user_uid [%d]")
608 (Printexc2.to_string e
) !!run_as_useruid
;
612 if !!create_mlsubmit
then save_mlsubmit_reg ();
613 DriverInteractive.initialization_completed
:= true;
614 DriverInteractive.save_config
();
616 if not
Autoconf.windows
then
617 MlUnix.set_signal
Sys.sigchld
618 (Sys.Signal_handle
(fun _ -> if !verbose
then lprintf_nl (_b "Received SIGCHLD, doing nothing")));
620 if not
Autoconf.windows
then
621 MlUnix.set_signal
Sys.sighup
622 (Sys.Signal_handle
(fun _ -> lprintf_nl (_b "Received SIGHUP, closing all files and client/server sockets, start IP discovery");
623 networks_iter
(fun r
-> CommonNetwork.network_reset r
); (* stop_all_bt *)
624 CommonServer.disconnect_all_servers
();
625 CommonClient.disconnect_all_clients
();
626 Unix32.close_all
(); (* close all files *)
630 if not
Autoconf.windows
then
631 MlUnix.set_signal
Sys.sigpipe
632 (Sys.Signal_handle
(fun _ -> if !verbose
then lprintf_nl (_b "Received SIGPIPE, doing nothing")));
634 MlUnix.set_signal
Sys.sigint
635 (Sys.Signal_handle
(fun _ -> lprintf_nl (_b "Received SIGINT, stopping MLDonkey...");
636 CommonInteractive.clean_exit
0));
638 MlUnix.set_signal
Sys.sigterm
639 (Sys.Signal_handle
(fun _ -> lprintf_nl (_b "Received SIGTERM, stopping MLDonkey...");
640 CommonInteractive.clean_exit
0));
642 if not
Autoconf.windows
then
643 MlUnix.set_signal
Sys.sigusr1
644 (Sys.Signal_handle
(fun _ -> lprintf_nl (_b "Received SIGUSR1, saving options...");
645 DriverInteractive.save_config
()));
647 if not
Autoconf.windows
then
648 MlUnix.set_signal
Sys.sigusr2
649 (Sys.Signal_handle
(fun _ -> lprintf_n (_b "Received SIGUSR2, starting garbage collection...");
654 if !verbose
then lprintf_nl (_b "Activated system signal handling")
657 let security_space_oc = ref None
in
659 (* Create a 'config_files_security_space' megabytes file to protect some space
660 for config files at the end. *)
662 let oc = Unix.openfile security_space_filename
[Unix.O_WRONLY
; Unix.O_CREAT
] 0o600
in
664 let s = String.make
len ' '
in
665 let pos = ref zero
in
666 for i
= 1 to !!config_files_security_space
do
667 for j
= 1 to 32 do (* 32 = 1 MB / 32kB *)
668 ignore
(Unix2.c_seek64
oc !pos Unix.SEEK_SET
);
669 Unix2.really_write
oc s 0 len;
670 pos := !pos ++ (Int64.of_int
len)
673 ignore
(Unix2.c_seek64
oc zero
Unix.SEEK_SET
);
674 (try Unix.lockf
oc Unix.F_LOCK
(!!config_files_security_space
* 1024 * 1024) with _ -> ());
675 security_space_oc := Some
oc
677 lprintf_nl (_b "Cannot create Security space file: %s") (Printexc2.to_string e
);
678 lprintf_nl (_b " not enough space on device or bad permissions");
679 lprintf_nl (_b "Exiting...");
682 Unix32.external_start
();
686 Filename.concat
!pid pid_filename
,
687 Printf.sprintf
"%s\n" (string_of_int
(Unix.getpid
()))
689 Unix2.tryopen_write
pid_file (fun oc -> output_string
oc s);
690 CommonGlobals.do_at_exit
(fun _ -> try Sys.remove
pid_file with _ -> ());
692 lprintf_nl (_b "Starting with pid %s") (string_of_int
(Unix.getpid
()))
695 (* When a core is spawned from a gui, the only way to know the startup has
696 succeeded is the string token "Core started". *)
697 if not
(keep_console_output
()) then
700 Printf.eprintf
"%s[dMain] Core started\n%!" (log_time
());
704 lprintf_nl (_b "Core started");
705 pause_new_downloads
=:= false;
706 core_included
:= true;
708 CommonGlobals.do_at_exit
(fun _ ->
709 (* If we have an error with too many file-descriptors,
710 just close all of them *)
712 BasicSocket.close_all
();
714 lprintf_nl "Exception %s in do_at_exit while closing sockets."
715 (Printexc2.to_string e
);
717 DriverGraphics.G.remove_files
();
718 (* In case we have no more space on filesystem for
719 config files, remove the security space file *)
720 (match !security_space_oc with
722 | Some
oc -> Unix.close
oc);
723 (try Sys.remove security_space_filename
with _ -> ());
724 CommonComplexOptions.allow_saving_ini_files
:= true;
725 DriverInteractive.save_config
();
726 CommonComplexOptions.save_sources
();
727 CommonComplexOptions.backup_options
();
729 Unix32.external_exit
();
730 lprintf_nl (_b "Core stopped")
733 if not
(keep_console_output
()) then
734 if !!log_file
= "" then
736 lprintf_nl (_b "Option log_file is empty, disable logging completely...");
737 lprintf_nl (_b "Disabling output to console, to enable: stdout true");