1
/*
2
    Copyright (c) 2009, 2010 digitalSTROM.org, Zurich, Switzerland
3
4
    Author: Patrick Staehlin, futureLAB AG <pstaehlin@futurelab.ch>
5
6
    This file is part of digitalSTROM Server.
7
8
    digitalSTROM Server 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 3 of the License, or
11
    (at your option) any later version.
12
13
    digitalSTROM Server is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU General Public License for more details.
17
18
    You should have received a copy of the GNU General Public License
19
    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
20
21
*/
22
23
24
#ifdef HAVE_CONFIG_H
25
  #include "config.h"
26
#endif
27
28
#include "src/base.h"
29
#include "src/dss.h"
30
#include "src/logger.h"
31
#include "src/datetools.h"
32
#ifdef WITH_TESTS
33
#include "tests/tests.h"
34
#endif
35
36
#include <ctime>
37
#include <csignal>
38
#include <getopt.h>
39
40
#include <boost/program_options.hpp>
41
42
#ifdef USE_LIBXML
43
  #include <libxml/tree.h>
44
  #include <libxml/encoding.h>
45
#endif
46
47
#include <iostream>
48
49
using namespace std;
50
namespace po = boost::program_options;
51
52
pair<string, string> parse_prop(const string& s) {
53
    if ((s.find("--prop") == 0) && (s.length() >=7)) {
54
      return make_pair("prop", s.substr(7));
55
    } else {
56
      return make_pair(string(), string());
57
    }
58
} // parse_prop
59
60
void platformSpecificStartup() {
61
#ifndef WIN32
62
  srand((getpid() << 16) ^ getuid() ^ time(0));
63
  // disable broken pipe signal
64
  signal(SIGPIPE, SIG_IGN);
65
  signal(SIGUSR1, dss::DSS::handleSignal);
66
  signal(SIGTERM, dss::DSS::handleSignal);
67
  signal(SIGINT, dss::DSS::handleSignal);
68
  signal(SIGSEGV, dss::DSS::handleSignal);
69
  signal(SIGABRT, dss::DSS::handleSignal);
70
#else
71
  srand( (int)time( (time_t)NULL ) );
72
  WSAData dat;
73
  WSAStartup( 0x1010, &dat );
74
#endif
75
} // platformSpecificStartup
76
77
char* tzNameCopy;
78
79
bool setupLocale() {
80
  if (!setlocale(LC_CTYPE, "")) {
81
    dss::Logger::getInstance()->log("Can't set the specified locale! Check LANG, LC_CTYPE, LC_ALL.", lsError);
82
    return false;
83
  }
84
85
  return true;
86
}
87
88
int main (int argc, char* argv[]) {
89
90
  if(!setupLocale()) {
91
    return -1;
92
  }
93
  platformSpecificStartup();
94
95
  vector<string> properties;
96
97
  po::options_description desc("Allowed options");
98
  desc.add_options()
99
      ("help", "produce help message")
100
      ("prop", po::value<vector<string> >(), "sets a property")
101
      ("version,v", "print version information and exit")
102
      ("datadir,D", po::value<string>(), "set data directory")
103
      ("webrootdir,w", po::value<string>(), "set webroot directory")
104
      ("configdir,c", po::value<string>(), "set config directory")
105
      ("config,C", po::value<string>(), "set configuration file to use")
106
      ("savedpropsdir,p", po::value<string>(), "set saved properties directory")
107
#ifndef __APPLE__ // daemon() is marked as deprecated on OS X
108
      ("daemonize,d", "start as a daemon")
109
#endif
110
  ;
111
112
  po::variables_map vm;
113
  try {
114
    po::store(po::command_line_parser(argc, argv).options(desc).extra_parser(parse_prop)
115
          .run(), vm);
116
  } catch (const po::error& e) {
117
    cout << "Error parsing command line: " << e.what() << endl;
118
    return 1;
119
  }
120
  po::notify(vm);
121
122
  if (vm.count("help")) {
123
      cout << desc << "\n";
124
      return 1;
125
  }
126
127
  if (vm.count("version")) {
128
    std::cout << dss::DSS::versionString() << std::endl;
129
    return 1;
130
  }
131
132
  if(vm.count("prop")) {
133
      properties = vm["prop"].as< vector<string> >();
134
  }
135
136
  if(vm.count("datadir")) {
137
    properties.push_back("/config/datadirectory=" +
138
                         vm["datadir"].as<string>());
139
  }
140
141
  if(vm.count("webrootdir")) {
142
    properties.push_back("/config/webrootdirectory=" +
143
                          vm["webrootdir"].as<string>());
144
  }
145
146
  if(vm.count("configdir")) {
147
    properties.push_back("/config/configdirectory=" +
148
                         vm["configdir"].as<string>());
149
  }
150
151
  string config_file;
152
  if(vm.count("config")) {
153
    config_file = vm["config"].as<string>();
154
  }
155
156
  if(vm.count("savedpropsdir")) {
157
    properties.push_back("/config/savedpropsdirectory=" +
158
                         vm["savedpropsdir"].as<string>());
159
  }
160
161
  string snifferDev;
162
  bool startSniffer = false;
163
164
  if(vm.count("sniff")) {
165
    startSniffer = true;
166
    snifferDev = vm["sniff"].as<string>();
167
  }
168
169
#ifndef __APPLE__
170
  bool daemonize = vm.count("daemonize") != 0;
171
#endif
172
173
  // start DSS
174
  if (dss::DSS::getInstance()->initialize(properties, config_file)) {
175
#ifndef __APPLE__
176
    if(daemonize) {
177
      int result = daemon(1,0);
178
      if(result != 0) {
179
        perror("daemon()");
180
        return 0;
181
      }
182
    }
183
#endif
184
    dss::DSS::getInstance()->run();
185
  } else {
186
    dss::Logger::getInstance()->log("Failed to initialize dss. Exiting", lsFatal);
187
  }
188
  if(dss::DSS::hasInstance()) {
189
    dss::DSS::shutdown();
190
  }
191
  dss::Logger::shutdown();
192
193
  free(tzNameCopy);
194
195
  return 0;
196
}