aboutsummaryrefslogtreecommitdiff
path: root/bbot/agent.cxx
blob: 26b00739a3f78c4aa98b665d827e1d41a7906eb3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// file      : bbot/agent.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <signal.h> // signal()
#include <unistd.h> // sleep()

#include <iostream>

#include <butl/pager>

#include <bbot/types>
#include <bbot/utility>

#include <bbot/diagnostics>
#include <bbot/agent-options>

using namespace std;
using namespace butl;
using namespace bbot;

extern "C" void
handle_signal (int sig)
{
  switch (sig)
  {
  case SIGHUP:  exit (3); // Unimplemented feature.
  case SIGTERM: exit (0);
  default:      assert (false);
  }
}

int
main (int argc, char* argv[])
try
{
  // Map to systemd severity prefixes (see sd-daemon(3) for details). Note
  // that here we assume we will never have location (like file name which
  // would end up being before the prefix).
  //
  const char indent[] = "\xE2\x86\xB2\n"; // Right arrow followed by newline.

  trace_indent    =
    fail.indent_  =
    error.indent_ =
    warn.indent_  =
    info.indent_  =
    text.indent_  = indent;

  fail.type_  = "<3>";
  error.type_ = "<3>";
  warn.type_  = "<4>";
  info.type_  = "<6>";
  trace_type  = "<7>";

  tracer trace ("main");

  // On POSIX ignore SIGPIPE which is signaled to a pipe-writing process if
  // the pipe reading end is closed. Note that by default this signal
  // terminates a process. Also note that there is no way to disable this
  // behavior on a file descriptor basis or for the write() function call.
  //
  if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
    fail << "unable to ignore broken pipe (SIGPIPE) signal: "
         << system_error (errno, generic_category ()); // Sanitize.

  // Handle SIGHUP and SIGTERM.
  //
  if (signal (SIGHUP,  &handle_signal) == SIG_ERR ||
      signal (SIGTERM, &handle_signal) == SIG_ERR)
    fail << "unable to set signal handler: "
         << system_error (errno, generic_category ()); // Sanitize.

  cli::argv_scanner scan (argc, argv, true);
  agent_options ops (scan);

  // Version.
  //
  if (ops.version ())
  {
    cout << "bbot-agent " << BBOT_VERSION_STR << endl
         << "libbbot " << LIBBBOT_VERSION_STR << endl
         << "libbutl " << LIBBUTL_VERSION_STR << endl
         << "Copyright (c) 2014-2017 Code Synthesis Ltd" << endl
         << "MIT; see accompanying LICENSE file" << endl;

    return 0;
  }

  // Help.
  //
  if (ops.help ())
  {
    pager p ("bbot-agent help", false);
    print_bbot_agent_usage (p.stream ());

    // If the pager failed, assume it has issued some diagnostics.
    //
    return p.wait () ? 0 : 1;
  }

  for (;;)
  {
    error << "sleeping" <<
      warn << "lightly";
    sleep (10);
  }
}
catch (const failed&)
{
  return 1; // Diagnostics has already been issued.
}
catch (const cli::exception& e)
{
  error << e;
  return 1;
}