2 * This file Copyright (C) 2008-2014 Mnemosyne LLC
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
7 * $Id: daemon.c 14270 2014-05-05 21:08:30Z jordan $
11 #include <stdio.h> /* printf */
12 #include <stdlib.h> /* exit, atoi */
14 #include <fcntl.h> /* open */
19 #include <unistd.h> /* daemon */
21 #include <event2/buffer.h>
22 #include <event2/event.h>
24 #include <libtransmission/transmission.h>
25 #include <libtransmission/tr-getopt.h>
26 #include <libtransmission/log.h>
27 #include <libtransmission/utils.h>
28 #include <libtransmission/variant.h>
29 #include <libtransmission/version.h>
31 #ifdef USE_SYSTEMD_DAEMON
32 #include <systemd/sd-daemon.h>
34 static void sd_notify (int status UNUSED
, const char * str UNUSED
) { }
35 static void sd_notifyf (int status UNUSED
, const char * fmt UNUSED
, ...) { }
40 #define MY_NAME "transmission-daemon"
43 #define MEM_K_STR "KiB"
44 #define MEM_M_STR "MiB"
45 #define MEM_G_STR "GiB"
46 #define MEM_T_STR "TiB"
49 #define DISK_B_STR "B"
50 #define DISK_K_STR "kB"
51 #define DISK_M_STR "MB"
52 #define DISK_G_STR "GB"
53 #define DISK_T_STR "TB"
56 #define SPEED_B_STR "B/s"
57 #define SPEED_K_STR "kB/s"
58 #define SPEED_M_STR "MB/s"
59 #define SPEED_G_STR "GB/s"
60 #define SPEED_T_STR "TB/s"
62 #define LOGFILE_MODE_STR "a+"
64 static bool paused
= false;
65 static bool seenHUP
= false;
66 static const char *logfileName
= NULL
;
67 static FILE *logfile
= NULL
;
68 static tr_session
* mySession
= NULL
;
69 static tr_quark key_pidfile
= 0;
70 static struct event_base
*ev_base
= NULL
;
79 return "Transmission " LONG_VERSION_STRING
80 " http://www.transmissionbt.com/\n"
81 "A fast and easy BitTorrent client\n"
83 MY_NAME
" is a headless Transmission session\n"
84 "that can be controlled via transmission-remote\n"
85 "or the web interface.\n"
87 "Usage: " MY_NAME
" [options]";
90 static const struct tr_option options
[] =
93 { 'a', "allowed", "Allowed IP addresses. (Default: " TR_DEFAULT_RPC_WHITELIST
")", "a", 1, "<list>" },
94 { 'b', "blocklist", "Enable peer blocklists", "b", 0, NULL
},
95 { 'B', "no-blocklist", "Disable peer blocklists", "B", 0, NULL
},
96 { 'c', "watch-dir", "Where to watch for new .torrent files", "c", 1, "<directory>" },
97 { 'C', "no-watch-dir", "Disable the watch-dir", "C", 0, NULL
},
98 { 941, "incomplete-dir", "Where to store new torrents until they're complete", NULL
, 1, "<directory>" },
99 { 942, "no-incomplete-dir", "Don't store incomplete torrents in a different location", NULL
, 0, NULL
},
100 { 'd', "dump-settings", "Dump the settings and exit", "d", 0, NULL
},
101 { 'e', "logfile", "Dump the log messages to this filename", "e", 1, "<filename>" },
102 { 'f', "foreground", "Run in the foreground instead of daemonizing", "f", 0, NULL
},
103 { 'g', "config-dir", "Where to look for configuration files", "g", 1, "<path>" },
104 { 'p', "port", "RPC port (Default: " TR_DEFAULT_RPC_PORT_STR
")", "p", 1, "<port>" },
105 { 't', "auth", "Require authentication", "t", 0, NULL
},
106 { 'T', "no-auth", "Don't require authentication", "T", 0, NULL
},
107 { 'u', "username", "Set username for authentication", "u", 1, "<username>" },
108 { 'v', "password", "Set password for authentication", "v", 1, "<password>" },
109 { 'V', "version", "Show version number and exit", "V", 0, NULL
},
110 { 810, "log-error", "Show error messages", NULL
, 0, NULL
},
111 { 811, "log-info", "Show error and info messages", NULL
, 0, NULL
},
112 { 812, "log-debug", "Show error, info, and debug messages", NULL
, 0, NULL
},
113 { 'w', "download-dir", "Where to save downloaded data", "w", 1, "<path>" },
114 { 800, "paused", "Pause all torrents on startup", NULL
, 0, NULL
},
115 { 'o', "dht", "Enable distributed hash tables (DHT)", "o", 0, NULL
},
116 { 'O', "no-dht", "Disable distributed hash tables (DHT)", "O", 0, NULL
},
117 { 'y', "lpd", "Enable local peer discovery (LPD)", "y", 0, NULL
},
118 { 'Y', "no-lpd", "Disable local peer discovery (LPD)", "Y", 0, NULL
},
119 { 830, "utp", "Enable uTP for peer connections", NULL
, 0, NULL
},
120 { 831, "no-utp", "Disable uTP for peer connections", NULL
, 0, NULL
},
121 { 'P', "peerport", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR
")", "P", 1, "<port>" },
122 { 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", 0, NULL
},
123 { 'M', "no-portmap", "Disable portmapping", "M", 0, NULL
},
124 { 'L', "peerlimit-global", "Maximum overall number of peers (Default: " TR_DEFAULT_PEER_LIMIT_GLOBAL_STR
")", "L", 1, "<limit>" },
125 { 'l', "peerlimit-torrent", "Maximum number of peers per torrent (Default: " TR_DEFAULT_PEER_LIMIT_TORRENT_STR
")", "l", 1, "<limit>" },
126 { 910, "encryption-required", "Encrypt all peer connections", "er", 0, NULL
},
127 { 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", 0, NULL
},
128 { 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", 0, NULL
},
129 { 'i', "bind-address-ipv4", "Where to listen for peer connections", "i", 1, "<ipv4 addr>" },
130 { 'I', "bind-address-ipv6", "Where to listen for peer connections", "I", 1, "<ipv6 addr>" },
131 { 'r', "rpc-bind-address", "Where to listen for RPC connections", "r", 1, "<ipv4 addr>" },
132 { 953, "global-seedratio", "All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio", "gsr", 1, "ratio" },
133 { 954, "no-global-seedratio", "All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio", "GSR", 0, NULL
},
134 { 'x', "pid-file", "Enable PID file", "x", 1, "<pid-file>" },
135 { 0, NULL
, NULL
, NULL
, 0, NULL
}
141 tr_getopt_usage (MY_NAME
, getUsage (), options
);
154 tr_logAddInfo ("Deferring reload until session is fully started.");
160 const char * configDir
;
162 /* reopen the logfile to allow for log rotation */
164 logfile
= freopen (logfileName
, LOGFILE_MODE_STR
, logfile
);
166 fprintf (stderr
, "Couldn't reopen \"%s\": %s\n", logfileName
, tr_strerror (errno
));
169 configDir
= tr_sessionGetConfigDir (mySession
);
170 tr_logAddInfo ("Reloading settings from \"%s\"", configDir
);
171 tr_variantInitDict (&settings
, 0);
172 tr_variantDictAddBool (&settings
, TR_KEY_rpc_enabled
, true);
173 tr_sessionLoadSettings (&settings
, configDir
, MY_NAME
);
174 tr_sessionSet (mySession
, &settings
);
175 tr_variantFree (&settings
);
176 tr_sessionReloadBlocklists (mySession
);
182 tr_logAddError ("Unexpected signal (%d) in daemon, closing.", sig
);
187 event_base_loopexit(ev_base
, NULL
);
193 #define USE_NO_DAEMON
194 #elif !defined (HAVE_DAEMON) || defined (__UCLIBC__)
195 #define USE_TR_DAEMON
197 #define USE_OS_DAEMON
201 tr_daemon (int nochdir
, int noclose
)
203 #if defined (USE_OS_DAEMON)
205 return daemon (nochdir
, noclose
);
207 #elif defined (USE_TR_DAEMON)
209 /* this is loosely based off of glibc's daemon () implementation
210 * http://sourceware.org/git/?p=glibc.git;a=blob_plain;f=misc/daemon.c */
225 int fd
= open ("/dev/null", O_RDWR
, 0);
226 dup2 (fd
, STDIN_FILENO
);
227 dup2 (fd
, STDOUT_FILENO
);
228 dup2 (fd
, STDERR_FILENO
);
234 #else /* USE_NO_DAEMON */
240 getConfigDir (int argc
, const char ** argv
)
243 const char * configDir
= NULL
;
245 const int ind
= tr_optind
;
247 while ((c
= tr_getopt (getUsage (), argc
, argv
, options
, &optarg
))) {
256 if (configDir
== NULL
)
257 configDir
= tr_getDefaultConfigDir (MY_NAME
);
263 onFileAdded (tr_session
* session
, const char * dir
, const char * file
)
265 char * filename
= tr_buildPath (dir
, file
, NULL
);
266 tr_ctor
* ctor
= tr_ctorNew (session
);
267 int err
= tr_ctorSetMetainfoFromFile (ctor
, filename
);
271 tr_torrentNew (ctor
, &err
, NULL
);
273 if (err
== TR_PARSE_ERR
)
274 tr_logAddError ("Error parsing .torrent file \"%s\"", file
);
278 int test
= tr_ctorGetDeleteSource (ctor
, &trash
);
280 tr_logAddInfo ("Parsing .torrent file successful \"%s\"", file
);
284 tr_logAddInfo ("Deleting input .torrent file \"%s\"", file
);
285 if (tr_remove (filename
))
286 tr_logAddError ("Error deleting .torrent file: %s", tr_strerror (errno
));
290 char * new_filename
= tr_strdup_printf ("%s.added", filename
);
291 tr_rename (filename
, new_filename
);
292 tr_free (new_filename
);
302 printMessage (FILE * logfile
, int level
, const char * name
, const char * message
, const char * file
, int line
)
307 tr_logGetTimeStr (timestr
, sizeof (timestr
));
309 fprintf (logfile
, "[%s] %s %s (%s:%d)\n", timestr
, name
, message
, file
, line
);
311 fprintf (logfile
, "[%s] %s (%s:%d)\n", timestr
, message
, file
, line
);
314 else /* daemon... write to syslog */
318 /* figure out the syslog priority */
320 case TR_LOG_ERROR
: priority
= LOG_ERR
; break;
321 case TR_LOG_DEBUG
: priority
= LOG_DEBUG
; break;
322 default: priority
= LOG_INFO
; break;
326 syslog (priority
, "%s %s (%s:%d)", name
, message
, file
, line
);
328 syslog (priority
, "%s (%s:%d)", message
, file
, line
);
334 pumpLogMessages (FILE * logfile
)
336 const tr_log_message
* l
;
337 tr_log_message
* list
= tr_logGetQueue ();
339 for (l
=list
; l
!=NULL
; l
=l
->next
)
340 printMessage (logfile
, l
->level
, l
->name
, l
->message
, l
->file
, l
->line
);
345 tr_logFreeQueue (list
);
351 const double up
= tr_sessionGetRawSpeed_KBps (mySession
, TR_UP
);
352 const double dn
= tr_sessionGetRawSpeed_KBps (mySession
, TR_DOWN
);
355 sd_notifyf (0, "STATUS=Uploading %.2f KBps, Downloading %.2f KBps.\n", up
, dn
);
357 sd_notify (0, "STATUS=Idle.\n");
361 periodicUpdate (evutil_socket_t fd UNUSED
, short what UNUSED
, void *watchdir
)
363 dtr_watchdir_update (watchdir
);
365 pumpLogMessages (logfile
);
370 static tr_rpc_callback_status
371 on_rpc_callback (tr_session
* session UNUSED
,
372 tr_rpc_callback_type type
,
373 struct tr_torrent
* tor UNUSED
,
374 void * user_data UNUSED
)
376 if (type
== TR_RPC_SESSION_CLOSE
)
377 event_base_loopexit(ev_base
, NULL
);
382 main (int argc
, char ** argv
)
389 bool foreground
= false;
390 bool dumpSettings
= false;
391 const char * configDir
= NULL
;
392 const char * pid_filename
;
393 dtr_watchdir
* watchdir
= NULL
;
394 bool pidfile_created
= false;
395 tr_session
* session
= NULL
;
396 struct event
*status_ev
;
398 key_pidfile
= tr_quark_new ("pidfile", 7);
400 signal (SIGINT
, gotsig
);
401 signal (SIGTERM
, gotsig
);
403 signal (SIGHUP
, gotsig
);
406 /* load settings from defaults + config file */
407 tr_variantInitDict (&settings
, 0);
408 tr_variantDictAddBool (&settings
, TR_KEY_rpc_enabled
, true);
409 configDir
= getConfigDir (argc
, (const char**)argv
);
410 loaded
= tr_sessionLoadSettings (&settings
, configDir
, MY_NAME
);
412 /* overwrite settings from the comamndline */
414 while ((c
= tr_getopt (getUsage (), argc
, (const char**)argv
, options
, &optarg
))) {
416 case 'a': tr_variantDictAddStr (&settings
, TR_KEY_rpc_whitelist
, optarg
);
417 tr_variantDictAddBool (&settings
, TR_KEY_rpc_whitelist_enabled
, true);
419 case 'b': tr_variantDictAddBool (&settings
, TR_KEY_blocklist_enabled
, true);
421 case 'B': tr_variantDictAddBool (&settings
, TR_KEY_blocklist_enabled
, false);
423 case 'c': tr_variantDictAddStr (&settings
, TR_KEY_watch_dir
, optarg
);
424 tr_variantDictAddBool (&settings
, TR_KEY_watch_dir_enabled
, true);
426 case 'C': tr_variantDictAddBool (&settings
, TR_KEY_watch_dir_enabled
, false);
428 case 941: tr_variantDictAddStr (&settings
, TR_KEY_incomplete_dir
, optarg
);
429 tr_variantDictAddBool (&settings
, TR_KEY_incomplete_dir_enabled
, true);
431 case 942: tr_variantDictAddBool (&settings
, TR_KEY_incomplete_dir_enabled
, false);
433 case 'd': dumpSettings
= true;
435 case 'e': logfile
= fopen (optarg
, LOGFILE_MODE_STR
);
437 logfileName
= optarg
;
439 fprintf (stderr
, "Couldn't open \"%s\": %s\n", optarg
, tr_strerror (errno
));
441 case 'f': foreground
= true;
443 case 'g': /* handled above */
445 case 'V': /* version */
446 fprintf (stderr
, "%s %s\n", MY_NAME
, LONG_VERSION_STRING
);
448 case 'o': tr_variantDictAddBool (&settings
, TR_KEY_dht_enabled
, true);
450 case 'O': tr_variantDictAddBool (&settings
, TR_KEY_dht_enabled
, false);
452 case 'p': tr_variantDictAddInt (&settings
, TR_KEY_rpc_port
, atoi (optarg
));
454 case 't': tr_variantDictAddBool (&settings
, TR_KEY_rpc_authentication_required
, true);
456 case 'T': tr_variantDictAddBool (&settings
, TR_KEY_rpc_authentication_required
, false);
458 case 'u': tr_variantDictAddStr (&settings
, TR_KEY_rpc_username
, optarg
);
460 case 'v': tr_variantDictAddStr (&settings
, TR_KEY_rpc_password
, optarg
);
462 case 'w': tr_variantDictAddStr (&settings
, TR_KEY_download_dir
, optarg
);
464 case 'P': tr_variantDictAddInt (&settings
, TR_KEY_peer_port
, atoi (optarg
));
466 case 'm': tr_variantDictAddBool (&settings
, TR_KEY_port_forwarding_enabled
, true);
468 case 'M': tr_variantDictAddBool (&settings
, TR_KEY_port_forwarding_enabled
, false);
470 case 'L': tr_variantDictAddInt (&settings
, TR_KEY_peer_limit_global
, atoi (optarg
));
472 case 'l': tr_variantDictAddInt (&settings
, TR_KEY_peer_limit_per_torrent
, atoi (optarg
));
474 case 800: paused
= true;
476 case 910: tr_variantDictAddInt (&settings
, TR_KEY_encryption
, TR_ENCRYPTION_REQUIRED
);
478 case 911: tr_variantDictAddInt (&settings
, TR_KEY_encryption
, TR_ENCRYPTION_PREFERRED
);
480 case 912: tr_variantDictAddInt (&settings
, TR_KEY_encryption
, TR_CLEAR_PREFERRED
);
482 case 'i': tr_variantDictAddStr (&settings
, TR_KEY_bind_address_ipv4
, optarg
);
484 case 'I': tr_variantDictAddStr (&settings
, TR_KEY_bind_address_ipv6
, optarg
);
486 case 'r': tr_variantDictAddStr (&settings
, TR_KEY_rpc_bind_address
, optarg
);
488 case 953: tr_variantDictAddReal (&settings
, TR_KEY_ratio_limit
, atof (optarg
));
489 tr_variantDictAddBool (&settings
, TR_KEY_ratio_limit_enabled
, true);
491 case 954: tr_variantDictAddBool (&settings
, TR_KEY_ratio_limit_enabled
, false);
493 case 'x': tr_variantDictAddStr (&settings
, key_pidfile
, optarg
);
495 case 'y': tr_variantDictAddBool (&settings
, TR_KEY_lpd_enabled
, true);
497 case 'Y': tr_variantDictAddBool (&settings
, TR_KEY_lpd_enabled
, false);
499 case 810: tr_variantDictAddInt (&settings
, TR_KEY_message_level
, TR_LOG_ERROR
);
501 case 811: tr_variantDictAddInt (&settings
, TR_KEY_message_level
, TR_LOG_INFO
);
503 case 812: tr_variantDictAddInt (&settings
, TR_KEY_message_level
, TR_LOG_DEBUG
);
505 case 830: tr_variantDictAddBool (&settings
, TR_KEY_utp_enabled
, true);
507 case 831: tr_variantDictAddBool (&settings
, TR_KEY_utp_enabled
, false);
509 default: showUsage ();
514 if (foreground
&& !logfile
)
519 printMessage (logfile
, TR_LOG_ERROR
, MY_NAME
, "Error loading config file -- exiting.", __FILE__
, __LINE__
);
525 char * str
= tr_variantToStr (&settings
, TR_VARIANT_FMT_JSON
, NULL
);
526 fprintf (stderr
, "%s", str
);
531 if (!foreground
&& tr_daemon (true, false) < 0)
534 tr_snprintf (buf
, sizeof (buf
), "Failed to daemonize: %s", tr_strerror (errno
));
535 printMessage (logfile
, TR_LOG_ERROR
, MY_NAME
, buf
, __FILE__
, __LINE__
);
539 sd_notifyf (0, "MAINPID=%d\n", (int)getpid());
541 /* setup event state */
542 ev_base
= event_base_new();
546 tr_snprintf(buf
, sizeof(buf
), "Failed to init daemon event state: %s", tr_strerror(errno
));
547 printMessage (logfile
, TR_LOG_ERROR
, MY_NAME
, buf
, __FILE__
, __LINE__
);
551 /* start the session */
552 tr_formatter_mem_init (MEM_K
, MEM_K_STR
, MEM_M_STR
, MEM_G_STR
, MEM_T_STR
);
553 tr_formatter_size_init (DISK_K
, DISK_K_STR
, DISK_M_STR
, DISK_G_STR
, DISK_T_STR
);
554 tr_formatter_speed_init (SPEED_K
, SPEED_K_STR
, SPEED_M_STR
, SPEED_G_STR
, SPEED_T_STR
);
555 session
= tr_sessionInit ("daemon", configDir
, true, &settings
);
556 tr_sessionSetRPCCallback (session
, on_rpc_callback
, NULL
);
557 tr_logAddNamedInfo (NULL
, "Using settings from \"%s\"", configDir
);
558 tr_sessionSaveSettings (session
, configDir
, &settings
);
561 tr_variantDictFindStr (&settings
, key_pidfile
, &pid_filename
, NULL
);
562 if (pid_filename
&& *pid_filename
)
564 FILE * fp
= fopen (pid_filename
, "w+");
567 fprintf (fp
, "%d", (int)getpid ());
569 tr_logAddInfo ("Saved pidfile \"%s\"", pid_filename
);
570 pidfile_created
= true;
573 tr_logAddError ("Unable to save pidfile \"%s\": %s", pid_filename
, tr_strerror (errno
));
576 if (tr_variantDictFindBool (&settings
, TR_KEY_rpc_authentication_required
, &boolVal
) && boolVal
)
577 tr_logAddNamedInfo (MY_NAME
, "requiring authentication");
581 /* If we got a SIGHUP during startup, process that now. */
585 /* maybe add a watchdir */
589 if (tr_variantDictFindBool (&settings
, TR_KEY_watch_dir_enabled
, &boolVal
)
591 && tr_variantDictFindStr (&settings
, TR_KEY_watch_dir
, &dir
, NULL
)
595 tr_logAddInfo ("Watching \"%s\" for new .torrent files", dir
);
596 watchdir
= dtr_watchdir_new (mySession
, dir
, onFileAdded
);
600 /* load the torrents */
602 tr_torrent
** torrents
;
603 tr_ctor
* ctor
= tr_ctorNew (mySession
);
605 tr_ctorSetPaused (ctor
, TR_FORCE
, true);
606 torrents
= tr_sessionLoadTorrents (mySession
, ctor
, NULL
);
613 openlog (MY_NAME
, LOG_CONS
|LOG_PID
, LOG_DAEMON
);
616 /* Create new timer event to report daemon status */
618 struct timeval one_sec
= { 1, 0 };
619 status_ev
= event_new(ev_base
, -1, EV_PERSIST
, &periodicUpdate
, watchdir
);
620 if (status_ev
== NULL
)
622 tr_logAddError("Failed to create status event %s", tr_strerror(errno
));
625 if (event_add(status_ev
, &one_sec
) == -1)
627 tr_logAddError("Failed to add status event %s", tr_strerror(errno
));
632 sd_notify( 0, "READY=1\n" );
634 /* Run daemon event loop */
635 if (event_base_dispatch(ev_base
) == -1)
637 tr_logAddError("Failed to launch daemon event loop: %s", tr_strerror(errno
));
642 sd_notify( 0, "STATUS=Closing transmission session...\n" );
643 printf ("Closing transmission session...");
647 event_del(status_ev
);
648 event_free(status_ev
);
650 event_base_free(ev_base
);
652 tr_sessionSaveSettings (mySession
, configDir
, &settings
);
653 dtr_watchdir_free (watchdir
);
654 tr_sessionClose (mySession
);
655 pumpLogMessages (logfile
);
662 syslog (LOG_INFO
, "%s", "Closing session");
669 tr_remove (pid_filename
);
670 tr_variantFree (&settings
);
671 sd_notify (0, "STATUS=\n");