~ubuntu-branches/ubuntu/jaunty/transmission/jaunty-security

« back to all changes in this revision

Viewing changes to daemon/daemon.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2008-11-28 15:33:48 UTC
  • mfrom: (1.1.19 upstream)
  • Revision ID: james.westby@ubuntu.com-20081128153348-it70trfnxiroblmc
Tags: 1.40-0ubuntu1
* New upstream release (LP: #302672)
  - Tracker communication uses fewer resources
  - More accurate bandwidth limits
  - Reduce disk fragmentation by preallocating files (LP: #287726)
  - Stability, security and performance improvements to the RPC /
    Web UI server (closes LP: #290423)
  - Support compression when serving Web UI and RPC responses
  - Simplify the RPC whitelist
  - Fix bug that prevented handshakes with encrypted BitComet peers
  - Fix 1.3x bug that could re-download some data unnecessarily
    (LP: #295040)
  - Option to automatically update the blocklist weekly
  - Added off-hour bandwidth scheduling
  - Simplify file/priority selection in the details dialog
  - Fix a couple of crashes
  - New / updated translations
  - Don't inhibit hibernation by default (LP: #292929)
  - Use "close" animation when sending to notification area (LP: #130811)
  - Fix resize problems (LP: #269872)
  - Support "--version" option when launching from command line
    (LP: #292011)
  - Correctly parse announce URLs that have leading or trailing
    spaces (LP: #262411)
  - Display an error when "Open Torrent" fails (LP: #281463)
* Dropped 10_fix_crasher_from_upstream.dpatch: Fix is in this
  upstream release.
* debian/control: Don't just build-depend on libcurl-dev, which is
  a virtual package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * This file is licensed by the GPL version 2.  Works owned by the
5
5
 * Transmission project are granted a special exemption to clause 2(b)
6
 
 * so that the bulk of its code can remain under the MIT license. 
 
6
 * so that the bulk of its code can remain under the MIT license.
7
7
 * This exemption does not extend to derived works not owned by
8
8
 * the Transmission project.
9
9
 *
10
 
 * $Id: daemon.c 6489 2008-08-11 19:05:00Z charles $
 
10
 * $Id: daemon.c 6978 2008-10-28 19:49:33Z charles $
11
11
 */
12
12
 
13
13
#include <assert.h>
14
14
#include <errno.h>
15
 
#include <stdio.h> /* printf */ 
 
15
#include <stdio.h> /* printf */
16
16
#include <stdlib.h> /* exit, atoi */
17
17
#include <string.h> /* strcmp */
18
18
 
19
19
#include <fcntl.h> /* open */
20
20
#include <signal.h>
21
 
#include <unistd.h> /* daemon, getcwd */
 
21
#include <unistd.h> /* daemon */
22
22
 
23
23
#include <libtransmission/transmission.h>
24
24
#include <libtransmission/bencode.h>
25
 
#include <libtransmission/rpc.h>
 
25
#include <libtransmission/rpcimpl.h>
26
26
#include <libtransmission/tr-getopt.h>
27
27
#include <libtransmission/utils.h>
28
28
#include <libtransmission/version.h>
29
29
 
30
30
#define MY_NAME "transmission-daemon"
31
31
 
32
 
static int closing = FALSE;
33
 
static tr_handle * mySession;
34
 
static char myConfigFilename[MAX_PATH_LENGTH];
35
 
 
36
 
#define KEY_BLOCKLIST        "blocklist-enabled"
37
 
#define KEY_DOWNLOAD_DIR     "download-dir"
38
 
#define KEY_ENCRYPTION       "encryption"
39
 
#define KEY_PEER_LIMIT       "max-peers-global"
40
 
#define KEY_PEER_PORT        "peer-port"
41
 
#define KEY_PORT_FORWARDING  "port-forwarding-enabled"
42
 
#define KEY_PEX_ENABLED      "pex-enabled"
43
 
#define KEY_AUTH_REQUIRED    "rpc-authentication-required"
44
 
#define KEY_USERNAME         "rpc-username"
45
 
#define KEY_PASSWORD         "rpc-password"
46
 
#define KEY_ACL              "rpc-access-control-list"
47
 
#define KEY_RPC_PORT         "rpc-port"
48
 
#define KEY_DSPEED           "download-limit"
49
 
#define KEY_DSPEED_ENABLED   "download-limit-enabled"
50
 
#define KEY_USPEED           "upload-limit"
51
 
#define KEY_USPEED_ENABLED   "upload-limit-enabled"
52
 
 
53
 
#define CONFIG_FILE          "settings.json"
 
32
static int           closing = FALSE;
 
33
static tr_session  * mySession = NULL;
 
34
static char        * myConfigFilename = NULL;
 
35
 
 
36
#define KEY_BLOCKLIST         "blocklist-enabled"
 
37
#define KEY_DOWNLOAD_DIR      "download-dir"
 
38
#define KEY_ENCRYPTION        "encryption"
 
39
#define KEY_LAZY_BITFIELD     "lazy-bitfield-enabled"
 
40
#define KEY_PEER_LIMIT        "max-peers-global"
 
41
#define KEY_PEER_PORT         "peer-port"
 
42
#define KEY_PORT_FORWARDING   "port-forwarding-enabled"
 
43
#define KEY_PEX_ENABLED       "pex-enabled"
 
44
#define KEY_AUTH_REQUIRED     "rpc-authentication-required"
 
45
#define KEY_USERNAME          "rpc-username"
 
46
#define KEY_PASSWORD          "rpc-password"
 
47
#define KEY_WHITELIST         "rpc-whitelist"
 
48
#define KEY_WHITELIST_ENABLED "rpc-whitelist-enabled"
 
49
#define KEY_RPC_PORT          "rpc-port"
 
50
#define KEY_DSPEED            "download-limit"
 
51
#define KEY_DSPEED_ENABLED    "download-limit-enabled"
 
52
#define KEY_USPEED            "upload-limit"
 
53
#define KEY_USPEED_ENABLED    "upload-limit-enabled"
 
54
 
 
55
#define CONFIG_FILE           "settings.json"
54
56
 
55
57
/***
56
58
****  Config File
57
59
***/
58
60
 
59
61
static void
60
 
replaceInt( tr_benc * dict, const char * key, int64_t value )
 
62
replaceInt( tr_benc *    dict,
 
63
            const char * key,
 
64
            int64_t      value )
61
65
{
62
66
    tr_bencDictRemove( dict, key );
63
67
    tr_bencDictAddInt( dict, key, value );
64
68
}
 
69
 
65
70
static void
66
 
replaceStr( tr_benc * dict, const char * key, const char* value )
 
71
replaceStr( tr_benc *    dict,
 
72
            const char * key,
 
73
            const char*  value )
67
74
{
68
75
    tr_bencDictRemove( dict, key );
69
76
    tr_bencDictAddStr( dict, key, value );
70
77
}
 
78
 
71
79
static void
72
80
saveState( tr_session * s )
73
81
{
74
 
    int i, n = 0;
75
 
    char * strs[4];
 
82
    int     i, n = 0;
 
83
    char *  strs[4];
76
84
 
77
85
    tr_benc d;
 
86
 
78
87
    if( tr_bencLoadJSONFile( myConfigFilename, &d ) )
79
88
        tr_bencInitDict( &d, 16 );
80
 
    
 
89
 
81
90
    replaceInt( &d, KEY_BLOCKLIST,       tr_blocklistIsEnabled( s ) );
82
91
    replaceStr( &d, KEY_DOWNLOAD_DIR,    tr_sessionGetDownloadDir( s ) );
83
92
    replaceInt( &d, KEY_PEER_LIMIT,      tr_sessionGetPeerLimit( s ) );
84
93
    replaceInt( &d, KEY_PEER_PORT,       tr_sessionGetPeerPort( s ) );
85
 
    replaceInt( &d, KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
 
94
    replaceInt( &d, KEY_PORT_FORWARDING,
 
95
               tr_sessionIsPortForwardingEnabled( s ) );
86
96
    replaceInt( &d, KEY_PEX_ENABLED,     tr_sessionIsPexEnabled( s ) );
87
 
    replaceStr( &d, KEY_USERNAME,        strs[n++] = tr_sessionGetRPCUsername( s ) );
88
 
    replaceStr( &d, KEY_PASSWORD,        strs[n++] = tr_sessionGetRPCPassword( s ) );
89
 
    replaceStr( &d, KEY_ACL,             strs[n++] = tr_sessionGetRPCACL( s ) );
 
97
    replaceStr( &d, KEY_USERNAME,        strs[n++] =
 
98
                   tr_sessionGetRPCUsername(
 
99
                       s ) );
 
100
    replaceStr( &d, KEY_PASSWORD,        strs[n++] =
 
101
                   tr_sessionGetRPCPassword(
 
102
                       s ) );
 
103
    replaceStr( &d, KEY_WHITELIST,       strs[n++] = tr_sessionGetRPCWhitelist( s ) );
90
104
    replaceInt( &d, KEY_RPC_PORT,        tr_sessionGetRPCPort( s ) );
91
105
    replaceInt( &d, KEY_AUTH_REQUIRED,   tr_sessionIsRPCPasswordEnabled( s ) );
92
 
    replaceInt( &d, KEY_DSPEED,          tr_sessionGetSpeedLimit( s, TR_DOWN ) );
93
 
    replaceInt( &d, KEY_DSPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) );
 
106
    replaceInt( &d, KEY_DSPEED,
 
107
               tr_sessionGetSpeedLimit( s, TR_DOWN ) );
 
108
    replaceInt( &d, KEY_DSPEED_ENABLED,
 
109
               tr_sessionIsSpeedLimitEnabled( s, TR_DOWN ) );
94
110
    replaceInt( &d, KEY_USPEED,          tr_sessionGetSpeedLimit( s, TR_UP ) );
95
 
    replaceInt( &d, KEY_USPEED_ENABLED,  tr_sessionIsSpeedLimitEnabled( s, TR_UP ) );
 
111
    replaceInt( &d, KEY_USPEED_ENABLED,
 
112
               tr_sessionIsSpeedLimitEnabled( s, TR_UP ) );
96
113
    replaceInt( &d, KEY_ENCRYPTION,      tr_sessionGetEncryption( s ) );
97
114
 
98
115
    tr_bencSaveJSONFile( myConfigFilename, &d );
99
116
    tr_bencFree( &d );
100
117
    tr_ninf( MY_NAME, "saved \"%s\"", myConfigFilename );
101
118
 
102
 
    for( i=0; i<n; ++i )
 
119
    for( i = 0; i < n; ++i )
103
120
        tr_free( strs[i] );
104
121
}
105
122
 
106
123
static void
107
 
getConfigInt( tr_benc     * dict,
108
 
              const char  * key,
109
 
              int         * setme,
110
 
              int           defaultVal )
 
124
getConfigInt( tr_benc *    dict,
 
125
              const char * key,
 
126
              int *        setme,
 
127
              int          defaultVal )
111
128
{
112
 
    if( *setme < 0 ) {
 
129
    if( *setme < 0 )
 
130
    {
113
131
        int64_t i;
114
132
        if( tr_bencDictFindInt( dict, key, &i ) )
115
133
            *setme = i;
119
137
}
120
138
 
121
139
static void
122
 
getConfigStr( tr_benc      * dict,
123
 
              const char   * key,
124
 
              const char  ** setme,
125
 
              const char   * defaultVal )
 
140
getConfigStr( tr_benc *     dict,
 
141
              const char *  key,
 
142
              const char ** setme,
 
143
              const char *  defaultVal )
126
144
{
127
 
    if( !*setme ) {
 
145
    if( !*setme )
 
146
    {
128
147
        const char * s;
129
148
        if( tr_bencDictFindStr( dict, key, &s ) )
130
149
            *setme = s;
139
158
 * @param blocklist TRUE, FALSE, or -1 if not set on the command line
140
159
 */
141
160
static void
142
 
session_init( const char * configDir, const char * downloadDir,
143
 
              int rpcPort, const char * acl,
144
 
              int authRequired, const char * username, const char * password,
145
 
              int blocklistEnabled )
 
161
session_init( const char * configDir,
 
162
              const char * downloadDir,
 
163
              int          rpcPort,
 
164
              const char * whitelist,
 
165
              int          authRequired,
 
166
              const char * username,
 
167
              const char * password,
 
168
              int          blocklistEnabled )
146
169
{
147
 
    char mycwd[MAX_PATH_LENGTH];
148
 
    tr_benc state, *dict = NULL;
149
 
    int peerPort=-1, peers=-1;
150
 
    int pexEnabled = -1;
151
 
    int fwdEnabled = -1;
152
 
    int upLimit=-1, upLimited=-1, downLimit=-1, downLimited=-1;
153
 
    int encryption = -1;
154
 
    tr_ctor * ctor;
 
170
    char        * mycwd;
 
171
    tr_benc       state, *dict = NULL;
 
172
    int           peerPort = -1, peers = -1;
 
173
    int           whitelistEnabled = -1;
 
174
    int           pexEnabled = -1;
 
175
    int           fwdEnabled = -1;
 
176
    int           upLimit = -1, upLimited = -1, downLimit = -1,
 
177
                  downLimited = -1;
 
178
    int           encryption = -1;
 
179
    int           useLazyBitfield = -1;
 
180
    tr_ctor *     ctor;
155
181
    tr_torrent ** torrents;
156
182
 
157
183
    if( !tr_bencLoadJSONFile( myConfigFilename, &state ) )
164
190
    ****  If neither of those can be found, the TR_DEFAULT fields are used .
165
191
    ***/
166
192
 
167
 
    getcwd( mycwd, sizeof( mycwd ) );
 
193
    mycwd = tr_getcwd( );
168
194
    getConfigStr( dict, KEY_DOWNLOAD_DIR,    &downloadDir,       mycwd );
169
 
    getConfigInt( dict, KEY_PEX_ENABLED,     &pexEnabled,        TR_DEFAULT_PEX_ENABLED );
170
 
    getConfigInt( dict, KEY_PORT_FORWARDING, &fwdEnabled,        TR_DEFAULT_PORT_FORWARDING_ENABLED );
171
 
    getConfigInt( dict, KEY_PEER_PORT,       &peerPort,          TR_DEFAULT_PORT );
 
195
    getConfigInt( dict, KEY_PEX_ENABLED,     &pexEnabled,
 
196
                  TR_DEFAULT_PEX_ENABLED );
 
197
    getConfigInt( dict, KEY_PORT_FORWARDING, &fwdEnabled,
 
198
                  TR_DEFAULT_PORT_FORWARDING_ENABLED );
 
199
    getConfigInt( dict, KEY_PEER_PORT,       &peerPort,
 
200
                  TR_DEFAULT_PORT );
172
201
    getConfigInt( dict, KEY_DSPEED,          &downLimit,         100 );
173
202
    getConfigInt( dict, KEY_DSPEED_ENABLED,  &downLimited,       FALSE );
174
203
    getConfigInt( dict, KEY_USPEED,          &upLimit,           100 );
175
204
    getConfigInt( dict, KEY_USPEED_ENABLED,  &upLimited,         FALSE );
176
 
    getConfigInt( dict, KEY_PEER_LIMIT,      &peers,             TR_DEFAULT_GLOBAL_PEER_LIMIT );
177
 
    getConfigInt( dict, KEY_BLOCKLIST,       &blocklistEnabled,  TR_DEFAULT_BLOCKLIST_ENABLED );
178
 
    getConfigInt( dict, KEY_RPC_PORT,        &rpcPort,           TR_DEFAULT_RPC_PORT );
179
 
    getConfigStr( dict, KEY_ACL,             &acl,               TR_DEFAULT_RPC_ACL );
 
205
    getConfigInt( dict, KEY_LAZY_BITFIELD,   &useLazyBitfield,
 
206
                  TR_DEFAULT_LAZY_BITFIELD_ENABLED );
 
207
    getConfigInt( dict, KEY_PEER_LIMIT,      &peers,
 
208
                  TR_DEFAULT_GLOBAL_PEER_LIMIT );
 
209
    getConfigInt( dict, KEY_BLOCKLIST,       &blocklistEnabled,
 
210
                  TR_DEFAULT_BLOCKLIST_ENABLED );
 
211
    getConfigInt( dict, KEY_RPC_PORT,        &rpcPort,
 
212
                  TR_DEFAULT_RPC_PORT );
 
213
    getConfigInt( dict, KEY_WHITELIST_ENABLED, &whitelistEnabled,
 
214
                  TR_DEFAULT_RPC_WHITELIST_ENABLED );
 
215
    getConfigStr( dict, KEY_WHITELIST,       &whitelist,
 
216
                  TR_DEFAULT_RPC_WHITELIST );
180
217
    getConfigInt( dict, KEY_AUTH_REQUIRED,   &authRequired,      FALSE );
181
218
    getConfigStr( dict, KEY_USERNAME,        &username,          NULL );
182
219
    getConfigStr( dict, KEY_PASSWORD,        &password,          NULL );
183
 
    getConfigInt( dict, KEY_ENCRYPTION,      &encryption,        TR_ENCRYPTION_PREFERRED );
 
220
    getConfigInt( dict, KEY_ENCRYPTION,      &encryption,
 
221
                  TR_DEFAULT_ENCRYPTION );
184
222
 
185
223
    /***
186
224
    ****
190
228
    mySession = tr_sessionInitFull( configDir, "daemon", downloadDir,
191
229
                                    pexEnabled, fwdEnabled, peerPort,
192
230
                                    encryption,
 
231
                                    useLazyBitfield,
193
232
                                    upLimited, upLimit,
194
233
                                    downLimited, downLimit,
195
234
                                    peers,
196
235
                                    TR_MSG_INF, 0,
197
236
                                    blocklistEnabled,
198
237
                                    TR_DEFAULT_PEER_SOCKET_TOS,
199
 
                                    TRUE, rpcPort, acl, authRequired, username, password,
 
238
                                    TRUE, rpcPort,
 
239
                                    whitelistEnabled, whitelist,
 
240
                                    authRequired, username, password,
200
241
                                    TR_DEFAULT_PROXY_ENABLED,
201
242
                                    TR_DEFAULT_PROXY,
202
243
                                    TR_DEFAULT_PROXY_PORT,
217
258
 
218
259
    if( dict )
219
260
        tr_bencFree( &state );
 
261
 
 
262
    tr_free( mycwd );
220
263
}
221
264
 
222
265
static const char *
223
266
getUsage( void )
224
267
{
225
 
    return "Transmission "LONG_VERSION_STRING"  http://www.transmissionbt.com/\n"
 
268
    return "Transmission " LONG_VERSION_STRING
 
269
           "  http://www.transmissionbt.com/\n"
226
270
           "A fast and easy BitTorrent client\n"
227
271
           "\n"
228
 
           MY_NAME" is a headless Transmission session\n"
229
 
           "that can be controlled via transmission-remote or Clutch.\n"
230
 
           "\n"
231
 
           "Usage: "MY_NAME" [options]";
 
272
           MY_NAME " is a headless Transmission session\n"
 
273
                   "that can be controlled via transmission-remote or Clutch.\n"
 
274
                   "\n"
 
275
                   "Usage: " MY_NAME " [options]";
232
276
}
233
277
 
234
 
static const struct tr_option options[] = {
235
 
    { 'a', "acl",       "Access Control List.  (Default: "TR_DEFAULT_RPC_ACL")", "a", 1, "<list>" },
236
 
    { 'b', "blocklist", "Enable peer blocklists",             "b", 0, NULL },
237
 
    { 'B', "no-blocklist", "Disable peer blocklists",         "B", 0, NULL },
238
 
    { 'f', "foreground", "Run in the foreground instead of daemonizing", "f", 0, NULL },
239
 
    { 'g', "config-dir",   "Where to look for configuration files", "g", 1, "<path>" },
240
 
    { 'p', "port", "RPC port (Default: "TR_DEFAULT_RPC_PORT_STR")", "p", 1, "<port>" },
241
 
    { 't', "auth",         "Require authentication",          "t", 0, NULL },
242
 
    { 'T', "no-auth",      "Don't require authentication",    "T", 0, NULL },
243
 
    { 'u', "username",     "Set username for authentication", "u", 1, "<username>" },
244
 
    { 'v', "password",     "Set password for authentication", "v", 1, "<password>" },
245
 
    { 'w', "download-dir", "Where to save downloaded data",   "w", 1, "<path>" },
246
 
    { 0, NULL, NULL, NULL, 0, NULL }
 
278
static const struct tr_option options[] =
 
279
{
 
280
    { 'a', "allowed",
 
281
      "Allowed IP addresses.  (Default: " TR_DEFAULT_RPC_WHITELIST ")",       "a",
 
282
      1, "<list>"     },
 
283
    { 'b', "blocklist",    "Enable peer blocklists",
 
284
      "b",             0, NULL         },
 
285
    { 'B', "no-blocklist", "Disable peer blocklists",
 
286
      "B",             0, NULL         },
 
287
    { 'f', "foreground",   "Run in the foreground instead of daemonizing",
 
288
      "f",             0, NULL         },
 
289
    { 'g', "config-dir",   "Where to look for configuration files",
 
290
      "g",             1, "<path>"     },
 
291
    { 'p', "port",
 
292
      "RPC port (Default: " TR_DEFAULT_RPC_PORT_STR ")",               "p",
 
293
      1, "<port>"     },
 
294
    { 't', "auth",         "Require authentication",
 
295
      "t",             0, NULL         },
 
296
    { 'T', "no-auth",      "Don't require authentication",
 
297
      "T",             0, NULL         },
 
298
    { 'u', "username",     "Set username for authentication",
 
299
      "u",             1, "<username>" },
 
300
    { 'v', "password",     "Set password for authentication",
 
301
      "v",             1, "<password>" },
 
302
    { 'w', "download-dir", "Where to save downloaded data",
 
303
      "w",             1, "<path>"     },
 
304
    {   0, NULL,           NULL,
 
305
        NULL,            0, NULL         }
247
306
};
248
307
 
249
308
static void
250
309
showUsage( void )
251
310
{
252
 
    tr_getopt_usage( MY_NAME, getUsage(), options );
 
311
    tr_getopt_usage( MY_NAME, getUsage( ), options );
253
312
    exit( 0 );
254
313
}
255
314
 
256
315
static void
257
 
readargs( int argc, const char ** argv,
258
 
          int * nofork, const char ** configDir, const char ** downloadDir,
259
 
          int * rpcPort, const char ** acl,
260
 
          int * authRequired, const char ** username, const char ** password,
261
 
          int * blocklistEnabled )
 
316
readargs( int           argc,
 
317
          const char ** argv,
 
318
          int *         nofork,
 
319
          const char ** configDir,
 
320
          const char ** downloadDir,
 
321
          int *         rpcPort,
 
322
          const char ** whitelist,
 
323
          int *         authRequired,
 
324
          const char ** username,
 
325
          const char ** password,
 
326
          int *         blocklistEnabled )
262
327
{
263
 
    int c;
 
328
    int          c;
264
329
    const char * optarg;
265
 
    while(( c = tr_getopt( getUsage(), argc, argv, options, &optarg )))
 
330
 
 
331
    while( ( c = tr_getopt( getUsage( ), argc, argv, options, &optarg ) ) )
266
332
    {
267
333
        switch( c )
268
334
        {
269
 
            case 'a': *acl = optarg; break;
270
 
            case 'b': *blocklistEnabled = 1; break;
271
 
            case 'B': *blocklistEnabled = 0; break;
272
 
            case 'f': *nofork = 1; break;
273
 
            case 'g': *configDir = optarg; break;
274
 
            case 'p': *rpcPort = atoi( optarg ); break;
275
 
            case 't': *authRequired = TRUE; break;
276
 
            case 'T': *authRequired = FALSE; break;
277
 
            case 'u': *username = optarg; break; 
278
 
            case 'v': *password = optarg; break; 
279
 
            case 'w': *downloadDir = optarg; break;
280
 
            default: showUsage( ); break;
 
335
            case 'a':
 
336
                *whitelist = optarg; break;
 
337
 
 
338
            case 'b':
 
339
                *blocklistEnabled = 1; break;
 
340
 
 
341
            case 'B':
 
342
                *blocklistEnabled = 0; break;
 
343
 
 
344
            case 'f':
 
345
                *nofork = 1; break;
 
346
 
 
347
            case 'g':
 
348
                *configDir = optarg; break;
 
349
 
 
350
            case 'p':
 
351
                *rpcPort = atoi( optarg ); break;
 
352
 
 
353
            case 't':
 
354
                *authRequired = TRUE; break;
 
355
 
 
356
            case 'T':
 
357
                *authRequired = FALSE; break;
 
358
 
 
359
            case 'u':
 
360
                *username = optarg; break;
 
361
 
 
362
            case 'v':
 
363
                *password = optarg; break;
 
364
 
 
365
            case 'w':
 
366
                *downloadDir = optarg; break;
 
367
 
 
368
            default:
 
369
                showUsage( ); break;
281
370
        }
282
371
    }
283
372
}
288
377
    closing = TRUE;
289
378
}
290
379
 
291
 
#if !defined(HAVE_DAEMON)
 
380
#if !defined( WIN32 )
 
381
#if !defined( HAVE_DAEMON )
292
382
static int
293
 
daemon( int nochdir, int noclose )
 
383
daemon( int nochdir,
 
384
        int noclose )
294
385
{
295
 
    switch( fork( ) ) {
296
 
        case 0:
297
 
            break;
298
 
        case -1:
299
 
            tr_nerr( MY_NAME, "Error daemonizing (fork)! %d - %s", errno, strerror(errno) );
300
 
            return -1;
301
 
        default:
302
 
            _exit(0);
303
 
    }
304
 
 
305
 
    if( setsid() < 0 ) {
306
 
        tr_nerr( MY_NAME, "Error daemonizing (setsid)! %d - %s", errno, strerror(errno) );
307
 
        return -1;
308
 
    }
309
 
 
310
 
    switch( fork( ) ) {
311
 
        case 0:
312
 
            break;
313
 
        case -1:
314
 
            tr_nerr( MY_NAME, "Error daemonizing (fork2)! %d - %s", errno, strerror(errno) );
315
 
            return -1;
316
 
        default:
317
 
            _exit(0);
318
 
    }
319
 
 
320
 
    if( !nochdir && 0 > chdir( "/" ) ) {
321
 
        tr_nerr( MY_NAME, "Error daemonizing (chdir)! %d - %s", errno, strerror(errno) );
322
 
        return -1;
323
 
    }
324
 
 
325
 
    if( !noclose ) {
 
386
    switch( fork( ) )
 
387
    {
 
388
        case 0:
 
389
            break;
 
390
 
 
391
        case - 1:
 
392
            tr_nerr( MY_NAME, "Error daemonizing (fork)! %d - %s", errno,
 
393
                    strerror(
 
394
                        errno ) );
 
395
            return -1;
 
396
 
 
397
        default:
 
398
            _exit( 0 );
 
399
    }
 
400
 
 
401
    if( setsid( ) < 0 )
 
402
    {
 
403
        tr_nerr( MY_NAME, "Error daemonizing (setsid)! %d - %s", errno,
 
404
                strerror(
 
405
                    errno ) );
 
406
        return -1;
 
407
    }
 
408
 
 
409
    switch( fork( ) )
 
410
    {
 
411
        case 0:
 
412
            break;
 
413
 
 
414
        case - 1:
 
415
            tr_nerr( MY_NAME, "Error daemonizing (fork2)! %d - %s", errno,
 
416
                    strerror(
 
417
                        errno ) );
 
418
            return -1;
 
419
 
 
420
        default:
 
421
            _exit( 0 );
 
422
    }
 
423
 
 
424
    if( !nochdir && 0 > chdir( "/" ) )
 
425
    {
 
426
        tr_nerr( MY_NAME, "Error daemonizing (chdir)! %d - %s", errno,
 
427
                strerror(
 
428
                    errno ) );
 
429
        return -1;
 
430
    }
 
431
 
 
432
    if( !noclose )
 
433
    {
326
434
        int fd;
327
 
        if((( fd = open("/dev/null", O_RDONLY))) != 0 ) {
 
435
        if( ( ( fd = open( "/dev/null", O_RDONLY ) ) ) != 0 )
 
436
        {
328
437
            dup2( fd,  0 );
329
438
            close( fd );
330
439
        }
331
 
        if((( fd = open("/dev/null", O_WRONLY))) != 1 ) {
 
440
        if( ( ( fd = open( "/dev/null", O_WRONLY ) ) ) != 1 )
 
441
        {
332
442
            dup2( fd, 1 );
333
443
            close( fd );
334
444
        }
335
 
        if((( fd = open("/dev/null", O_WRONLY))) != 2 ) {
 
445
        if( ( ( fd = open( "/dev/null", O_WRONLY ) ) ) != 2 )
 
446
        {
336
447
            dup2( fd, 2 );
337
448
            close( fd );
338
449
        }
341
452
    return 0;
342
453
}
343
454
#endif
 
455
#endif
344
456
 
345
457
int
346
 
main( int argc, char ** argv )
 
458
main( int     argc,
 
459
      char ** argv )
347
460
{
348
 
    int nofork = 0;
349
 
    int rpcPort = -1;
350
 
    int authRequired = -1;
351
 
    int blocklistEnabled = -1;
352
 
    char * freeme = NULL;
 
461
    int          nofork = 0;
 
462
    int          rpcPort = -1;
 
463
    int          authRequired = -1;
 
464
    int          blocklistEnabled = -1;
 
465
    char *       freeme = NULL;
353
466
    const char * configDir = NULL;
354
467
    const char * downloadDir = NULL;
355
 
    const char * acl = NULL;
 
468
    const char * whitelist = NULL;
356
469
    const char * username = NULL;
357
470
    const char * password = NULL;
358
471
 
359
472
    signal( SIGINT, gotsig );
 
473
    signal( SIGTERM, gotsig );
 
474
#ifndef WIN32 
360
475
    signal( SIGQUIT, gotsig );
361
 
    signal( SIGTERM, gotsig );
362
476
    signal( SIGPIPE, SIG_IGN );
363
477
    signal( SIGHUP, SIG_IGN );
 
478
#endif
364
479
 
365
480
    readargs( argc, (const char**)argv, &nofork, &configDir, &downloadDir,
366
 
              &rpcPort, &acl, &authRequired, &username, &password,
 
481
              &rpcPort, &whitelist, &authRequired, &username, &password,
367
482
              &blocklistEnabled );
368
483
    if( configDir == NULL )
369
 
        configDir = freeme = tr_strdup_printf( "%s-daemon", tr_getDefaultConfigDir() );
370
 
    tr_buildPath( myConfigFilename, sizeof( myConfigFilename ),
371
 
                  configDir, CONFIG_FILE, NULL );
 
484
        configDir = getenv( "TRANSMISSION_HOME" );
 
485
    if( configDir == NULL )
 
486
        configDir = freeme = tr_strdup_printf( "%s-daemon",
 
487
                                               tr_getDefaultConfigDir( ) );
 
488
    myConfigFilename = tr_buildPath( configDir, CONFIG_FILE, NULL );
372
489
 
373
 
    if( !nofork ) {
374
 
        if( 0 > daemon( 1, 0 ) ) {
 
490
#ifndef WIN32
 
491
    if( !nofork )
 
492
    {
 
493
        if( 0 > daemon( 1, 0 ) )
 
494
        {
375
495
            fprintf( stderr, "failed to daemonize: %s\n", strerror( errno ) );
376
496
            exit( 1 );
377
497
        }
378
498
    }
 
499
#endif
379
500
 
380
501
    session_init( configDir, downloadDir,
381
 
                  rpcPort, acl, authRequired, username, password,
 
502
                  rpcPort, whitelist, authRequired, username, password,
382
503
                  blocklistEnabled );
383
504
 
384
505
    while( !closing )
385
 
        sleep( 1 );
 
506
        tr_wait( 1000 ); /* sleep one second */
386
507
 
387
508
    saveState( mySession );
388
509
    printf( "Closing transmission session..." );
390
511
    printf( " done.\n" );
391
512
 
392
513
    tr_free( freeme );
 
514
    tr_free( myConfigFilename );
393
515
    return 0;
394
516
}
 
517