~ubuntu-branches/ubuntu/utopic/binkd/utopic-proposed

« back to all changes in this revision

Viewing changes to binkd.c

  • Committer: Bazaar Package Importer
  • Author(s): Marco d'Itri
  • Date: 2002-03-24 22:52:25 UTC
  • Revision ID: james.westby@ubuntu.com-20020324225225-7ru6itlapn03nl35
Tags: upstream-0.9.5a
ImportĀ upstreamĀ versionĀ 0.9.5a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  binkd.c -- binkd's main
 
3
 *
 
4
 *  binkd.c is a part of binkd project
 
5
 *
 
6
 *  Copyright (C) 1996-1998  Dima Maloff, 5047/13
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 2 of the License, or
 
11
 *  (at your option) any later version. See COPYING.
 
12
 */
 
13
 
 
14
/*
 
15
 * $Id: binkd.c,v 2.1 2001/01/15 22:04:52 gul Exp $
 
16
 *
 
17
 * $Log: binkd.c,v $
 
18
 * Revision 2.1  2001/01/15 22:04:52  gul
 
19
 * Added -D switch (run as daemon)
 
20
 *
 
21
 * Revision 2.0  2001/01/10 12:12:37  gul
 
22
 * Binkd is under CVS again
 
23
 *
 
24
 *
 
25
 * nsoveiko@doe.carleton.ca 1998/12/14
 
26
 * creation of pid_file is now logged and warnings produced
 
27
 *
 
28
 * Revision 1.15  1998/05/08  03:35:47  mff
 
29
 * Added -P switch, brushed up error msgs
 
30
 *
 
31
 * Revision 1.14  1997/11/03  06:10:39  mff
 
32
 * +nodes_init()
 
33
 *
 
34
 * Revision 1.13  1997/10/23  04:20:53  mff
 
35
 * pidfiles fixed, ...
 
36
 *
 
37
 * Revision 1.12  1997/06/16  05:52:07  mff
 
38
 * Added -C, copyright note
 
39
 *
 
40
 * Revision 1.10  1997/05/17  08:44:42  mff
 
41
 * Changed cmd line processing a bit
 
42
 *
 
43
 * Revision 1.9  1997/03/09  07:16:31  mff
 
44
 * Added command line parsing, support for inetd
 
45
 *
 
46
 * Revision 1.8  1997/02/07  06:42:59  mff
 
47
 * Under UNIXs SIGHUP forces binkd to restart
 
48
 *
 
49
 * Revision 1.7  1997/02/01  05:55:24  mff
 
50
 * Changed SIGCHLD support
 
51
 *
 
52
 * Revision 1.5  1996/12/14  07:00:32  mff
 
53
 * Now we use branch() and set_break_handlers()
 
54
 *
 
55
 * Revision 1.3  1996/12/07  12:26:37  mff
 
56
 * SOCKS support by msh
 
57
 *
 
58
 * Revision 1.1.1 1996/12/02  18:26:00  ufm
 
59
 *    Port to NT
 
60
 */
 
61
 
 
62
#include <string.h>
 
63
#include <stdio.h>
 
64
#include <stdlib.h>
 
65
#include <errno.h>
 
66
#include <signal.h>
 
67
#include <setjmp.h>
 
68
#if defined(__IBMC__) || defined(__MSC__)
 
69
#include <time.h>
 
70
#endif
 
71
 
 
72
#include "Config.h"
 
73
#include "sys.h"
 
74
#include "iphdr.h"
 
75
#include "readcfg.h"
 
76
#include "server.h"
 
77
#include "client.h"
 
78
#include "tools.h"
 
79
#include "bsy.h"
 
80
#include "protocol.h"
 
81
#include "assert.h"
 
82
#include "binlog.h"
 
83
#include "setpttl.h"
 
84
#ifndef DOS
 
85
#include "daemonize.h"
 
86
#endif
 
87
 
 
88
#ifdef WIN32
 
89
#include "nt/service.h"
 
90
#endif
 
91
 
 
92
#ifdef USE_SOCKS
 
93
#include "socks.h"
 
94
#endif
 
95
 
 
96
#ifdef HAVE_THREADS
 
97
#include "sem.h"
 
98
MUTEXSEM hostsem = 0; 
 
99
#ifdef OS2
 
100
MUTEXSEM fhsem = 0;
 
101
#endif
 
102
#endif
 
103
 
 
104
/*
 
105
 * Global variables
 
106
 */
 
107
int pidcmgr = 0;                       /* pid for clientmgr */
 
108
int pidsmgr = 0;                       /* pid for server */
 
109
SOCKET inetd_socket = 0;
 
110
 
 
111
#ifdef HAVE_FORK
 
112
static void chld (int signo)
 
113
{
 
114
#include "reapchld.inc"
 
115
}
 
116
#endif
 
117
 
 
118
#if defined(UNIX) || defined(AMIGA) || (defined(OS2) && defined(HAVE_FORK))
 
119
jmp_buf jb;
 
120
static void hup (int signo)
 
121
{
 
122
  Log (2, "got SIGHUP");
 
123
  longjmp (jb, 1);
 
124
}
 
125
#endif
 
126
 
 
127
void usage ()
 
128
{
 
129
#if defined(WIN32)      
 
130
        char *s=NULL;
 
131
        switch(checkservice())
 
132
        {
 
133
        case 1: s="i\0  -i       install WindowsNT service\n"; break;
 
134
        case 2: s="u\0  -u       UNinstall WindowsNT service\n"; break;
 
135
        }
 
136
#endif
 
137
 
 
138
  printf ("usage: binkd [-Cc"
 
139
#if defined(HAVE_DAEMON) || defined(HAVE_SETSID) || defined(HAVE_TIOCNOTTY)
 
140
          "D"
 
141
#endif
 
142
#if defined(UNIX) || defined(OS2) || defined(AMIGA)
 
143
          "i"
 
144
#elif defined(WIN32)
 
145
          "%s"
 
146
#endif
 
147
          "pqsv] [-Pnode] config"
 
148
#ifdef OS2
 
149
          " [socket]"
 
150
#endif
 
151
          "\n"
 
152
#if defined(HAVE_DAEMON) || defined(HAVE_SETSID) || defined(HAVE_TIOCNOTTY)
 
153
          "  -D       run as daemon\n"
 
154
#endif
 
155
          "  -C       exit(3) on config change\n"
 
156
          "  -c       run client only\n"
 
157
#if defined(UNIX) || defined(OS2) || defined(AMIGA)
 
158
          "  -i       run from inetd\n"
 
159
#elif defined(WIN32)
 
160
          "%s"
 
161
#endif
 
162
          "  -P node  poll a node\n"
 
163
          "  -p       run client only, poll, quit\n"
 
164
          "  -q       be quiet\n"
 
165
          "  -s       run server only\n"
 
166
          "  -v       be verbose / dump version and quit\n"
 
167
          "  -m       disable CRAM-MD5 authorization\n"
 
168
          "\n"
 
169
          "Copyright (c) 1996-2000 Dima Maloff and others.\n"
 
170
          "\n"
 
171
    "This program is free software; you can redistribute it and/or modify\n"
 
172
    "it under the terms of the GNU General Public License as published by\n"
 
173
          "the Free Software Foundation. See COPYING.\n"
 
174
          "\n"
 
175
          "Report bugs to 2:463/68 or binkd-bugs@happy.kiev.ua.\n"
 
176
#if defined(WIN32)      
 
177
          ,s?s:"", s?s+2:""
 
178
#endif
 
179
          );
 
180
  exit (1);
 
181
}
 
182
 
 
183
/* Command line flags */
 
184
int inetd_flag = 0;                    /* Run from inetd (-i) */
 
185
#if defined(HAVE_DAEMON) || defined(HAVE_SETSID) || defined(HAVE_TIOCNOTTY)
 
186
int daemon_flag = 0;                   /* Run as daemon (-D) */
 
187
#endif
 
188
int server_flag = 0;                   /* Run servermgr (-s) */
 
189
int client_flag = 0;                   /* Run clientmgr (-c) */
 
190
int poll_flag = 0;                     /* Run clientmgr, make all jobs, quit
 
191
                                        * (-p) */
 
192
int quiet_flag = 0;                    /* Be quiet (-q) */
 
193
int verbose_flag = 0;                  /* Be verbose / print version (-v) */
 
194
int checkcfg_flag = 0;                 /* exit(3) on config change (-C) */
 
195
int no_MD5 = 0;                        /* disable MD5 flag (-m) */
 
196
 
 
197
extern int nNod;
 
198
 
 
199
int main (int argc, char *argv[], char *envp[])
 
200
{
 
201
  char tmp[128];
 
202
  int i;
 
203
/* Config file name */
 
204
  char *config = NULL;
 
205
  char **saved_argv;
 
206
#if defined(HAVE_DAEMON) || defined(HAVE_SETSID) || defined(HAVE_TIOCNOTTY)
 
207
  int  nochdir;
 
208
#endif
 
209
 
 
210
#if defined(__IBMC__) || defined(__MSC__)
 
211
  tzset();
 
212
#endif
 
213
 
 
214
#ifdef WIN32
 
215
  service(argc, argv, envp);
 
216
#endif
 
217
  /* save argv as setproctitle() under some systems will change it */
 
218
  saved_argv = mkargv (argc, argv);
 
219
 
 
220
  for (i = 1; i < argc; ++i)
 
221
  {
 
222
    if (argv[i][0] == '-')
 
223
    {
 
224
      char *s = argv[i] + 1;
 
225
 
 
226
      do
 
227
      {
 
228
        switch (*s)
 
229
          {
 
230
            case '-':
 
231
              /* GNU-style options */
 
232
              if (!strcmp (s + 1, "help"))
 
233
                usage ();
 
234
              else
 
235
                Log (0, "%s: --%s: unknown command line switch", argv[0], s + 1);
 
236
            case 'C':
 
237
              checkcfg_flag = 1;
 
238
              break;
 
239
            case 'c':
 
240
              client_flag = 1;
 
241
              break;
 
242
#if defined(UNIX) || defined(OS2) || defined(AMIGA)
 
243
            case 'i':
 
244
              inetd_flag = 1;
 
245
              break;
 
246
#endif
 
247
            case 'P':
 
248
              if (argv[i][2] == 0)
 
249
              {
 
250
                ++i;
 
251
                if (argv[i] == 0)
 
252
                  Log (0, "%s: -P: missing requred argument", argv[0]);
 
253
              }
 
254
              goto BREAK_WHILE;
 
255
            case 'p':
 
256
              poll_flag = client_flag = 1;
 
257
              break;
 
258
            case 'q':
 
259
              quiet_flag = 1;
 
260
              break;
 
261
            case 's':
 
262
              server_flag = 1;
 
263
              break;
 
264
            case 'm':
 
265
              no_MD5 = 1;
 
266
              break;
 
267
            case 'v':
 
268
              ++verbose_flag;
 
269
              break;
 
270
#if defined(HAVE_DAEMON) || defined(HAVE_SETSID) || defined(HAVE_TIOCNOTTY)
 
271
            case 'D':
 
272
              daemon_flag = 1;
 
273
              /* remove this switch from saved_argv */
 
274
              { int j;
 
275
                free(saved_argv[i]);
 
276
                for (j=i; j<argc; j++)
 
277
                  saved_argv[j]=saved_argv[j+1];
 
278
              }
 
279
              break;
 
280
#endif
 
281
            default:
 
282
              Log (0, "%s: -%c: unknown command line switch", argv[0], *s);
 
283
            case 0:
 
284
              usage ();
 
285
          }
 
286
        ++s;
 
287
      }
 
288
      while (*s);
 
289
  BREAK_WHILE:;
 
290
    }
 
291
    else if (!config)
 
292
    {
 
293
      config = argv[i];
 
294
    }
 
295
  }
 
296
 
 
297
  if (poll_flag && server_flag)
 
298
    Log (0, "-p and -s cannot be used together");
 
299
 
 
300
  /* No command line options: run both client and server */
 
301
  if (!client_flag && !server_flag)
 
302
    client_flag = server_flag = 1;
 
303
 
 
304
#if defined(UNIX) || defined(OS2) || defined(AMIGA)
 
305
  if (inetd_flag)
 
306
  {
 
307
    inetd_socket = 0;
 
308
#ifdef OS2
 
309
    if ((inetd_socket = atoi (argv[argc - 1])) == 0)
 
310
      Log (0, "%s: bad socket number", argv[argc - 1]);
 
311
#endif
 
312
#ifdef EMX
 
313
    if ((inetd_socket = _impsockhandle (inetd_socket, 0)) == -1)
 
314
      Log (0, "_impsockhandle: %s", strerror (errno));
 
315
#endif
 
316
  }
 
317
#endif
 
318
 
 
319
  if (verbose_flag >= 3)
 
320
    debugcfg = 1;
 
321
 
 
322
  /* Init for ftnnode.c */
 
323
  nodes_init ();
 
324
 
 
325
  if (config)
 
326
    readcfg (config);
 
327
  else if (verbose_flag)
 
328
  {
 
329
    printf ("Binkd " MYVER " (" __DATE__ " " __TIME__ "%s)\n", get_os_string ());
 
330
    exit (0);
 
331
  }
 
332
  else if (argc == 1)
 
333
    usage ();
 
334
  else
 
335
  {
 
336
    Log (0, "%s: invalid command line: config name must be specified", argv[0]);
 
337
    exit (1);
 
338
  }
 
339
 
 
340
  if (quiet_flag)
 
341
  {
 
342
    percents = 0;
 
343
    conlog = 0;
 
344
    printq = 0;
 
345
  }
 
346
  switch (verbose_flag)
 
347
    {
 
348
      case 0:
 
349
        break;
 
350
      case 1:
 
351
        percents = printq = 1;
 
352
        loglevel = conlog = 4;
 
353
        break;
 
354
      case 2:
 
355
      case 3:
 
356
      default:
 
357
        percents = printq = 1;
 
358
        loglevel = conlog = 6;
 
359
        break;
 
360
    }
 
361
 
 
362
  print_args (tmp, sizeof (tmp), argc - 1, argv + 1);
 
363
  Log (4, "BEGIN, " MYNAME "/" MYVER "%s", tmp);
 
364
 
 
365
  if (sock_init ())
 
366
    Log (0, "sock_init: %s", TCPERR ());
 
367
 
 
368
  bsy_init ();
 
369
  BinLogInit ();
 
370
  rnd ();
 
371
  initsetproctitle (argc, argv, envp);
 
372
 
 
373
  /* Set up break handler, set up exit list if needed */
 
374
  if (!set_break_handlers ())
 
375
    Log (0, "cannot install break handlers");
 
376
 
 
377
#ifdef HAVE_FORK
 
378
  signal (SIGCHLD, chld);
 
379
#else
 
380
  InitSem (&hostsem);
 
381
#ifdef OS2
 
382
  InitSem (&fhsem);
 
383
#endif
 
384
#endif
 
385
 
 
386
  for (i = 1; i < argc; ++i)
 
387
    if (argv[i][0] == '-' && argv[i][1] == 'P')
 
388
    {
 
389
      if (argv[i][2] == 0)
 
390
        poll_node (argv[++i]);
 
391
      else
 
392
        poll_node (argv[i] + 2);
 
393
    }
 
394
 
 
395
#if defined(UNIX) || defined(OS2) || defined(AMIGA)
 
396
  if (inetd_flag)
 
397
  {
 
398
    protocol (inetd_socket, 0);
 
399
    soclose (inetd_socket);
 
400
    exit (0);
 
401
  }
 
402
#endif
 
403
 
 
404
#if defined(HAVE_DAEMON) || defined(HAVE_SETSID) || defined(HAVE_TIOCNOTTY)
 
405
  if (daemon_flag)
 
406
  {
 
407
         if (!server_flag)
 
408
                 Log (0, "Only server can be run in the daemon mode");
 
409
         else
 
410
         {
 
411
                 if (saved_argv[0][0] == '/')
 
412
                        nochdir = 0;
 
413
                 else
 
414
                 {
 
415
                        nochdir = 1;
 
416
                        // Log (6, "Run with relative path, will not chdir to /");
 
417
                 }
 
418
 
 
419
                 if (binkd_daemonize(nochdir) < 0)
 
420
                 Log (0, "Cannot daemonize");
 
421
         }
 
422
  }
 
423
#endif
 
424
 
 
425
  if (client_flag && !server_flag)
 
426
  {
 
427
#if defined(UNIX) || defined(AMIGA) || (defined(OS2) && defined(HAVE_FORK))
 
428
    if (setjmp(jb))
 
429
      goto binkdrestart;
 
430
    else
 
431
      signal (SIGHUP, hup);
 
432
#endif
 
433
    clientmgr (0);
 
434
    exit (0);
 
435
  }
 
436
 
 
437
  pidsmgr = (int) getpid ();
 
438
  if (client_flag && (pidcmgr = branch (clientmgr, 0, 0)) < 0)
 
439
  {
 
440
    Log (0, "cannot branch out");
 
441
  }
 
442
 
 
443
#if defined(UNIX) || defined(AMIGA) || (defined(OS2) && defined(HAVE_FORK))
 
444
  if (setjmp (jb))
 
445
  {
 
446
    extern SOCKET sockfd;
 
447
 
 
448
    Log (5, "Closing socket # %i", sockfd);
 
449
    soclose (sockfd);
 
450
binkdrestart:
 
451
    exitfunc();
 
452
    print_args (tmp, sizeof (tmp), argc - 1, saved_argv + 1);
 
453
    Log (2, "exec %s%s", saved_argv[0], tmp);
 
454
    if (execv (saved_argv[0], saved_argv) == -1)
 
455
      Log (1, "execv: %s", strerror (errno));
 
456
  }
 
457
  else
 
458
  {
 
459
    signal (SIGHUP, hup);
 
460
  }
 
461
#endif
 
462
 
 
463
  if (*pid_file)
 
464
  {
 
465
    if ( unlink (pid_file) == 0 ) /* successfully unlinked, i.e.
 
466
                                     an old pid_file was found */
 
467
        Log (1, "unexpected pid_file: %s: unlinked", pid_file);
 
468
    else
 
469
    {
 
470
        int current_log_level = 1;
 
471
        switch ( errno )
 
472
        {
 
473
           case ENOENT :        /* file not found or null pathname */
 
474
                current_log_level = 8; /* it's ok */
 
475
                break;
 
476
           default :
 
477
                break;
 
478
        }
 
479
        Log (current_log_level, "unlink_pid_file: %s: %s", pid_file, strerror (errno));
 
480
    }
 
481
    if ( create_sem_file (pid_file) == 0 ) /* could not create pid_file */
 
482
        if (loglevel < 5) /* not logged in create_sem_file() */
 
483
            Log (1, "create_sem_file: %s: %s", pid_file, strerror (errno));
 
484
  }
 
485
 
 
486
  servmgr (0);
 
487
 
 
488
  return 0;
 
489
}