~ubuntu-branches/ubuntu/wily/nbdkit/wily

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Package Import Robot
  • Author(s): Hilko Bengen
  • Date: 2014-02-17 19:31:33 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20140217193133-xvmd9uadu73nslod
Tags: 1.1.6-1
* New upstream version
* Split package
* Cherry-picked post-1.1.6-bugfix from upstream git

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
#include <pwd.h>
45
45
#include <grp.h>
46
46
#include <sys/types.h>
 
47
#include <sys/wait.h>
47
48
#include <errno.h>
48
49
 
49
50
#include <pthread.h>
56
57
static void open_plugin_so (const char *filename);
57
58
static void start_serving (void);
58
59
static void set_up_signals (void);
 
60
static void run_command (void);
59
61
static void change_user (void);
60
62
static void write_pidfile (void);
61
63
static void fork_into_background (void);
68
70
char *pidfile;                  /* -P */
69
71
const char *port;               /* -p */
70
72
int readonly;                   /* -r */
 
73
char *run;                      /* --run */
71
74
char *unixsocket;               /* -U */
72
75
const char *user, *group;       /* -u & -g */
73
76
int verbose;                    /* -v */
90
93
  { "port",       1, NULL, 'p' },
91
94
  { "read-only",  0, NULL, 'r' },
92
95
  { "readonly",   0, NULL, 'r' },
 
96
  { "run",        1, NULL, 0 },
93
97
  { "single",     0, NULL, 's' },
94
98
  { "stdin",      0, NULL, 's' },
95
99
  { "unix",       1, NULL, 'U' },
102
106
usage (void)
103
107
{
104
108
  printf ("nbdkit [--dump-config] [-f] [-g GROUP] [-i IPADDR]\n"
105
 
          "       [-P PIDFILE] [-p PORT] [-r] [-s]\n"
 
109
          "       [-P PIDFILE] [-p PORT] [-r] [--run CMD] [-s]\n"
106
110
          "       [-U SOCKET] [-u USER] [-v] [-V]\n"
107
111
          "       PLUGIN [key=value [key=value [...]]]\n"
108
112
          "\n"
142
146
        dump_config ();
143
147
        exit (EXIT_SUCCESS);
144
148
      }
 
149
      else if (strcmp (long_options[option_index].name, "run") == 0) {
 
150
        run = optarg;
 
151
        foreground = 1;
 
152
      }
145
153
      else {
146
154
        fprintf (stderr, "%s: unknown long option: %s (%d)\n",
147
155
                 program_name, long_options[option_index].name, option_index);
148
156
        exit (EXIT_FAILURE);
149
157
      }
 
158
      break;
150
159
 
151
160
    case 'f':
152
161
      foreground = 1;
341
350
   * TCP/IP and Unix sockets, or even multiple TCP/IP ports.
342
351
   */
343
352
  if ((port && unixsocket) || (port && listen_stdin) ||
344
 
      (unixsocket && listen_stdin)) {
345
 
    fprintf (stderr, "%s: -p, -U and -s options cannot appear at the same time\n",
 
353
      (unixsocket && listen_stdin) || (listen_stdin && run)) {
 
354
    fprintf (stderr,
 
355
             "%s: -p, -U and -s options cannot appear at the same time\n",
346
356
             program_name);
347
357
    exit (EXIT_FAILURE);
348
358
  }
365
375
  else
366
376
    socks = bind_tcpip_socket (&nr_socks);
367
377
 
 
378
  run_command ();
368
379
  change_user ();
369
380
  fork_into_background ();
370
381
  write_pidfile ();
492
503
  debug ("forked into background (new pid = %d)", getpid ());
493
504
}
494
505
 
 
506
static void
 
507
run_command (void)
 
508
{
 
509
  char *url;
 
510
  char *cmd;
 
511
  int r;
 
512
  pid_t pid;
 
513
 
 
514
  if (!run)
 
515
    return;
 
516
 
 
517
  /* Construct an nbd "URL".  Unfortunately guestfish and qemu take
 
518
   * different syntax, so try to guess which one we need.
 
519
   */
 
520
  if (strstr (run, "guestfish")) {
 
521
    if (port)
 
522
      r = asprintf (&url, "nbd://localhost:%s", port);
 
523
    else if (unixsocket)
 
524
      /* XXX escaping? */
 
525
      r = asprintf (&url, "nbd://?socket=%s", unixsocket);
 
526
    else
 
527
      abort ();
 
528
  }
 
529
  else /* qemu */ {
 
530
    if (port)
 
531
      r = asprintf (&url, "nbd:localhost:%s", port);
 
532
    else if (unixsocket)
 
533
      r = asprintf (&url, "nbd:unix:%s", unixsocket);
 
534
    else
 
535
      abort ();
 
536
  }
 
537
  if (r == -1) {
 
538
    perror ("asprintf");
 
539
    exit (EXIT_FAILURE);
 
540
  }
 
541
 
 
542
  /* Construct the final command including shell variables. */
 
543
  /* XXX Escaping again. */
 
544
  r = asprintf (&cmd,
 
545
                "nbd='%s'\n"
 
546
                "port='%s'\n"
 
547
                "unixsocket='%s'\n"
 
548
                "%s",
 
549
                url, port ? port : "", unixsocket ? unixsocket : "", run);
 
550
  if (r == -1) {
 
551
    perror ("asprintf");
 
552
    exit (EXIT_FAILURE);
 
553
  }
 
554
 
 
555
  free (url);
 
556
 
 
557
  /* Fork.  Captive nbdkit runs as the child process. */
 
558
  pid = fork ();
 
559
  if (pid == -1) {
 
560
    perror ("fork");
 
561
    exit (EXIT_FAILURE);
 
562
  }
 
563
 
 
564
  if (pid > 0) {              /* Parent process is the run command. */
 
565
    r = system (cmd);
 
566
    if (WIFEXITED (r))
 
567
      r = WEXITSTATUS (r);
 
568
    else if (WIFSIGNALED (r)) {
 
569
      fprintf (stderr, "%s: external command was killed by signal %d\n",
 
570
               program_name, WTERMSIG (r));
 
571
      r = 1;
 
572
    }
 
573
    else if (WIFSTOPPED (r)) {
 
574
      fprintf (stderr, "%s: external command was stopped by signal %d\n",
 
575
               program_name, WSTOPSIG (r));
 
576
      r = 1;
 
577
    }
 
578
 
 
579
    kill (pid, SIGTERM);        /* Kill captive nbdkit. */
 
580
 
 
581
    _exit (r);
 
582
  }
 
583
 
 
584
  free (cmd);
 
585
 
 
586
  debug ("forked into background (new pid = %d)", getpid ());
 
587
}
 
588
 
495
589
static uid_t
496
590
parseuser (const char *id)
497
591
{