Bugfix: parsing of plugins.d failed with some file-systems
[profile/ivi/automotive-message-broker.git] / ambd / main.cpp
1 /*
2 Copyright (C) 2012 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include <iostream>
20 #include <string>
21 #include <getopt.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <pwd.h>
26 #include <grp.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <signal.h>
32 #include <string.h>
33 #include <stdexcept>
34 #include <glib-object.h>
35
36 #ifdef USE_QT_CORE
37
38 #include <QCoreApplication>
39
40 #else
41
42 #include <glib.h>
43
44 #endif
45
46 #include "pluginloader.h"
47 #include <debugout.h>
48
49 using namespace std;
50
51 IMainLoop* mainloop = nullptr;
52
53 void interrupt(int sign)
54 {
55         signal(sign, SIG_IGN);
56         cout<<"Signal caught. Exiting gracefully.\n"<<endl;
57
58         /// this will cause the application to terminate and clean up:
59         delete mainloop;
60 }
61
62 void daemonize();
63
64 void printhelp(const char *argv0);
65
66 static const char shortopts[] = "hvDc:d:l:we";
67
68 static const struct option longopts[] = {
69         { "help", no_argument, NULL, 'h' }, ///< Print the help text
70         { "version", no_argument, NULL, 'v' }, ///< Print the version text
71         { "daemonise", no_argument, NULL, 'D' }, ///< Daemonise
72         { "config", required_argument, NULL, 'c' },
73         { "debug", required_argument, NULL, 'd' },
74         { "log", required_argument, NULL, 'l' },
75         { "warn", no_argument, NULL, 'w' },
76         { "err", no_argument, NULL, 'e' },
77         { NULL, 0, NULL, 0 } ///< End
78 };
79
80 void printVersion()
81 {
82         DebugOut(0) << PROJECT_NAME << endl;
83         DebugOut(0)<<"Version: " << PROJECT_VERSION<<" Series: " << PROJECT_SERIES <<" (" << PROJECT_CODENAME<<" " << PROJECT_QUALITY << ")" << endl;
84 }
85
86 static void glibLogHandler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
87 {
88         if(log_level == G_LOG_LEVEL_CRITICAL)
89                 DebugOut(DebugOut::Error) << message << endl;
90         else if(log_level == G_LOG_LEVEL_WARNING)
91                 DebugOut(DebugOut::Warning) << message << endl;
92         else
93                 DebugOut() << message << endl;
94 }
95
96 int main(int argc, char **argv)
97 {
98
99         bool isdeamonize=false;
100         int optc;
101         int th = 0;
102         string config="/etc/ambd/config";
103         ofstream logfile;
104         string logfn;
105
106         g_log_set_handler(G_LOG_DOMAIN, GLogLevelFlags(G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL), glibLogHandler, nullptr);
107
108         while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
109         {
110                 switch (optc)
111                 {
112                         case 'D':
113                                 isdeamonize = true;
114                                 break;
115
116                         case 'v':
117                                 printVersion();
118                                 return (0);
119                                 break;
120                         case 'c':
121                                 DebugOut(0)<<"Config: "<<optarg<<endl;
122                                 config=optarg;
123                                 break;
124                         case 'd':
125                                 th = atoi(optarg);
126                                 DebugOut::setDebugThreshhold(th);
127                                 break;
128                         case 'l':
129                                 logfn = optarg;
130                                 break;
131                         case 'w':
132                                 DebugOut::setThrowWarn(true);
133                                 break;
134                         case 'e':
135                                 DebugOut::setThrowErr(true);
136                                 break;
137                         default:
138                                 DebugOut(0)<<"Unknown option "<<optc<<endl;
139                                 printhelp(argv[0]);
140                                 return (0);
141                                 break;
142                 }
143         }
144
145         if(isdeamonize)
146                 daemonize();
147
148         if(!logfn.empty())
149         {
150                 logfile.open(logfn, ios::out | ios::trunc);
151                 DebugOut::setOutput(logfile);
152         }
153
154         printVersion();
155
156         if(getuid() == 0)
157         {
158                 DebugOut(DebugOut::Warning)<<"Running as root.  This is dangerous."<<endl;
159         }
160
161 #ifndef GLIB_VERSION_2_36
162         g_type_init();
163 #endif
164
165         VehicleProperty::factory();
166
167         PluginLoader loader(config, argc, argv);
168
169         mainloop = loader.mainloop();
170
171         /* Register signal handler */
172         signal(SIGINT, interrupt);
173         signal(SIGTERM, interrupt);
174
175         mainloop->exec();
176
177         if(logfile.is_open())
178                 logfile.close();
179
180         return 0;
181 }
182
183 void daemonize()
184 {
185         int i=0;
186         if(getppid() == 1)
187         {
188                 return; // already a daemon
189         }
190         if((i = fork()) < 0)
191         {
192                 fprintf(stderr, "%s:%s(%d) - fork error: %s", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
193                 exit(1);
194         }
195         if(i > 0)
196         {
197                 exit(0);        // parent exits
198         }       // child (daemon) continues
199         setsid();       // obtain a new process group
200         for(i = getdtablesize(); i >= 0; --i)
201         {
202                 close(i);       // close all descriptors
203         }
204         {       // handle standard I/O
205                 i = open("/dev/null", O_RDWR);
206                 dup(i);
207                 dup(i);
208         }
209         // first instance continues
210 }
211
212 void printhelp(const char *argv0)
213 {
214         printf("Usage: %s [args]\n"
215                    "   [-D|--daemonise] run ambd in daemon mode\n"
216                    "   [-v|--version] spit out the version then exit\n"
217                    "   [-c|--config </path/to/config> ] specify which config to use\n"
218                    "   [-d|--debug <level (0-5)> ] set the debug level\n"
219                    "   [-l]--log </path/to/logfile> ] specify an debug output log file\n"
220                    "   [-w]--warn] throw on warnings\n"
221                    "   [-e]--err] throw on errors\n"
222                    "   [-h|--help] print this menu and exit\n"
223                    , argv0);
224 }
225
226