Translation update done using Pootle.
[gammu.git] / smsd / main.c
blobf7d6da75f21bdea9d4002420cfe2495fbb17281a
1 /**
2 * Main SMSD program
3 */
4 /* Copyright (c) 2009 - 2011 Michal Cihar <michal@cihar.com> */
5 /* Licensend under GNU GPL 2 */
7 #include <gammu-smsd.h>
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <signal.h>
11 #ifdef HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #ifdef HAVE_GETOPT_LONG
15 #include <getopt.h>
16 #endif
17 #ifdef HAVE_WINDOWS_SERVICE
18 #include "winservice.h"
19 #endif
20 #ifdef HAVE_KILL
21 #include "pidfile.h"
22 #define HAVE_PIDFILE
23 #endif
24 #include <errno.h>
25 #include <string.h>
26 #include "common.h"
27 #if defined(HAVE_GETPWNAM) && defined(HAVE_GETGRNAM) && defined(HAVE_SETUID) && defined(HAVE_SETGID) && defined(HAVE_INITGROUPS)
28 #define HAVE_UID
29 #include "uid.h"
30 #endif
32 #if !defined(WIN32)
33 #define HAVE_DEFAULT_CONFIG
34 const char default_config[] = "/etc/gammu-smsdrc";
35 #endif
37 GSM_SMSDConfig *config;
38 volatile gboolean reconfigure = FALSE;
40 void smsd_interrupt(int signum)
42 SMSD_Shutdown(config);
43 signal(signum, SIG_IGN);
46 void smsd_reconfigure(int signum)
48 reconfigure = TRUE;
49 SMSD_Shutdown(config);
52 NORETURN void version(void)
54 printf("Gammu-smsd version %s\n", GAMMU_VERSION);
55 printf("Built %s on %s using %s\n", __TIME__, __DATE__, GetCompiler());
56 printf("Compiled in features:\n");
57 printf("OS support:\n");
58 #ifdef HAVE_SHM
59 printf(" - %s\n", "SHM");
60 #endif
61 #ifdef HAVE_DAEMON
62 printf(" - %s\n", "DAEMON");
63 #endif
64 #ifdef HAVE_PIDFILE
65 printf(" - %s\n", "PID");
66 #endif
67 #ifdef HAVE_ALARM
68 printf(" - %s\n", "ALARM");
69 #endif
70 #ifdef HAVE_UID
71 #endif
72 #ifdef HAVE_WINDOWS_SERVICE
73 printf(" - %s\n", "WINDOWS_SERVICE");
74 #endif
75 #ifdef HAVE_GETOPT
76 printf(" - %s\n", "GETOPT");
77 #endif
78 #ifdef HAVE_GETOPT_LONG
79 printf(" - %s\n", "GETOPT_LONG");
80 #endif
81 #ifdef HAVE_WINDOWS_EVENT_LOG
82 printf(" - %s\n", "EVENT_LOG");
83 #endif
84 #ifdef HAVE_SYSLOG
85 printf(" - %s\n", "SYSLOG");
86 #endif
87 printf("Backend services:\n");
88 printf(" - %s\n", "NULL");
89 printf(" - %s\n", "FILES");
90 #ifdef HAVE_MYSQL_MYSQL_H
91 printf(" - %s\n", "MYSQL");
92 #endif
93 #ifdef HAVE_POSTGRESQL_LIBPQ_FE_H
94 printf(" - %s\n", "POSTGRESQL");
95 #endif
96 #ifdef LIBDBI_FOUND
97 printf(" - %s\n", "DBI");
98 #endif
99 #ifdef ODBC_FOUND
100 printf(" - %s\n", "ODBC");
101 #endif
102 printf("\n");
103 printf("Copyright (C) 2003 - 2011 Michal Cihar <michal@cihar.com> and other authors.\n");
104 printf("\n");
105 printf("License GPLv2: GNU GPL version 2 <http://creativecommons.org/licenses/GPL/2.0/>.\n");
106 printf("This is free software: you are free to change and redistribute it.\n");
107 printf("There is NO WARRANTY, to the extent permitted by law.\n");
108 printf("\n");
109 printf("Check <http://wammu.eu/gammu/> for updates.\n");
110 printf("\n");
111 exit(0);
114 #ifdef HAVE_GETOPT_LONG
115 #define print_option(name, longname, help) \
116 printf("-%s / --%s - %s\n", name, longname, help);
117 #define print_option_param(name, longname, paramname, help) \
118 printf("-%s / --%s %s - %s\n", name, longname, paramname, help);
119 #else
120 #define print_option(name, longname, help) \
121 printf("-%s - %s\n", name, help);
122 #define print_option_param(name, longname, paramname, help) \
123 printf("-%s %s - %s\n", name, paramname, help);
124 #endif
126 void help(void)
128 printf("usage: gammu-smsd [OPTION]...\n");
129 printf("options:\n");
130 print_option("h", "help", "shows this help");
131 print_option("v", "version", "shows version information");
132 print_option_param("c", "config", "CONFIG_FILE", "defines path to config file");
133 #ifdef HAVE_DAEMON
134 print_option("d", "daemon", "daemonizes program after startup");
135 #endif
136 #ifdef HAVE_PIDFILE
137 print_option_param("p", "pid", "PID_FILE", "defines path to pid file");
138 #endif
139 #ifdef HAVE_UID
140 print_option_param("U", "user", "USER", "run daemon as a user");
141 print_option_param("G", "group", "GROUP", "run daemon as a group");
142 #endif
143 print_option_param("f", "max-failures", "NUM", "number of failures before terminating");
144 #ifdef HAVE_ALARM
145 print_option_param("X", "suicide", "SECONDS", "kills itself after number of seconds");
146 #endif
147 #ifdef HAVE_WINDOWS_SERVICE
148 print_option("i", "install-service", "installs SMSD as a Windows service");
149 print_option("u", "uninstall-service", "uninstalls SMSD as a Windows service");
150 print_option("s", "start-service", "starts SMSD Windows service");
151 print_option("k", "stop-service", "stops SMSD Windows service");
152 print_option("S", "run-as-service", "runs as a SMSD Windows service");
153 print_option_param("n", "service-name", "NAME", "name of a Windows service (default: GammuSMSD)");
154 #endif
155 print_option("l", "use-log", "use logging configuration from config file (default)");
156 print_option("L", "no-use-log", "do not use logging configuration from config file");
159 NORETURN void wrong_params(void)
161 fprintf(stderr, "Invalid parameter, use -h for help.\n");
162 exit(1);
165 void process_commandline(int argc, char **argv, SMSD_Parameters * params)
167 int opt;
169 #ifdef HAVE_GETOPT_LONG
170 struct option long_options[] = {
171 {"help", 0, 0, 'h'},
172 {"version", 0, 0, 'v'},
173 {"config", 1, 0, 'c'},
174 {"daemon", 0, 0, 'd'},
175 {"pid", 1, 0, 'p'},
176 {"install-service", 0, 0, 'i'},
177 {"uninstall-service", 0, 0, 'u'},
178 {"start-service", 0, 0, 's'},
179 {"stop-service", 0, 0, 'k'},
180 {"run-as-service", 0, 0, 'S'},
181 {"user", 1, 0, 'U'},
182 {"group", 1, 0, 'G'},
183 {"service-name", 1, 0, 'n'},
184 {"suicide", 1, 0, 'X'},
185 {"max-failures", 1, 0, 'f'},
186 {"use-log", 0, 0, 'l'},
187 {"no-use-log", 0, 0, 'L'},
188 {0, 0, 0, 0}
190 int option_index;
192 while ((opt = getopt_long(argc, argv, "hvdc:p:iusSkU:G:n:X:f:lL", long_options, &option_index)) != -1) {
193 #elif defined(HAVE_GETOPT)
194 while ((opt = getopt(argc, argv, "hvdc:p:iusSkU:G:n:X:f:lL")) != -1) {
195 #else
196 /* Poor mans getopt replacement */
197 int i;
199 #define optarg argv[++i]
201 for (i = 1; i < argc; i++) {
202 if (strlen(argv[i]) != 2 || argv[i][0] != '-') {
203 wrong_params();
205 opt = argv[i][1];
206 #endif
207 switch (opt) {
208 case 'c':
209 params->config_file = optarg;
210 break;
211 #ifdef HAVE_PIDFILE
212 case 'p':
213 params->pid_file = optarg;
214 break;
215 #endif
216 #ifdef HAVE_UID
217 case 'U':
218 if (!fill_uid(params, optarg)) {
219 fprintf(stderr, "Wrong user name/ID!\n");
220 exit(1);
222 break;
223 case 'G':
224 if (!fill_gid(params, optarg)) {
225 fprintf(stderr, "Wrong group name/ID!\n");
226 exit(1);
228 break;
229 #endif
230 case 'f':
231 params->max_failures = atoi(optarg);
232 break;
233 #ifdef HAVE_ALARM
234 case 'X':
235 alarm(atoi(optarg));
236 break;
237 #endif
238 #ifdef HAVE_DAEMON
239 case 'd':
240 params->daemonize = TRUE;
241 break;
242 #endif
243 #ifdef HAVE_WINDOWS_SERVICE
244 case 'i':
245 params->install_service = TRUE;
246 break;
247 case 'u':
248 params->uninstall_service = TRUE;
249 break;
250 case 's':
251 params->start_service = TRUE;
252 break;
253 case 'k':
254 params->stop_service = TRUE;
255 break;
256 case 'S':
257 params->run_service = TRUE;
258 break;
259 case 'n':
260 strncpy(smsd_service_name, optarg, SERVICE_NAME_LENGTH);
261 smsd_service_name[SERVICE_NAME_LENGTH - 1] = 0;
262 break;
263 #endif
264 case 'v':
265 version();
266 break;
267 case 'l':
268 params->use_log = TRUE;
269 break;
270 case 'L':
271 params->use_log = FALSE;
272 break;
273 case '?':
274 wrong_params();
275 case 'h':
276 help();
277 exit(0);
278 default:
279 wrong_params();
280 break;
284 #if defined(HAVE_GETOPT) || defined(HAVE_GETOPT_LONG)
285 if (optind < argc) {
286 wrong_params();
288 #endif
292 void configure_daemon(SMSD_Parameters * params)
294 signal(SIGINT, smsd_interrupt);
295 signal(SIGTERM, smsd_interrupt);
296 #ifdef HAVE_SIGHUP
297 signal(SIGHUP, smsd_reconfigure);
298 #endif
299 #ifdef HAVE_ALARM
300 signal(SIGALRM, smsd_interrupt);
301 #endif
303 #ifdef HAVE_DAEMON
304 /* Daemonize has to be before writing PID as it changes it */
305 if (params->daemonize) {
306 if (daemon(1, 0) != 0) {
307 fprintf(stderr, "daemonizing failed! (%s)\n", strerror(errno));
308 exit(1);
311 #endif
313 #ifdef HAVE_PIDFILE
314 /* Writing PID file has to happen before dropping privileges */
315 if (params->pid_file != NULL && strlen(params->pid_file) > 0) {
316 check_pid(params->pid_file);
317 write_pid(params->pid_file);
319 #endif
321 #ifdef HAVE_UID
322 if (params->gid != -1 || params->uid != -1) {
323 if (!set_uid_gid(params)) {
324 fprintf(stderr, "changing uid/gid failed! (%s)\n", strerror(errno));
325 exit(1);
328 #endif
330 #ifdef HAVE_WINDOWS_SERVICE
331 if (params->run_service) {
332 if (!start_smsd_service_dispatcher()) {
333 printf("Error starting %s service\n", smsd_service_name);
334 service_print_error("Error running service");
335 exit(1);
338 SMSD_FreeConfig(config);
340 exit(0);
342 #endif
345 int main(int argc, char **argv)
347 GSM_Error error;
348 const char program_name[] = "gammu-smsd";
350 SMSD_Parameters params = {
351 NULL,
352 NULL,
355 NULL,
356 NULL,
357 FALSE,
358 FALSE,
359 FALSE,
360 FALSE,
361 FALSE,
362 FALSE,
363 TRUE,
368 * We don't need gettext, but need to set locales so that
369 * charset conversion works.
371 GSM_InitLocales(NULL);
373 process_commandline(argc, argv, &params);
375 #ifdef HAVE_WINDOWS_SERVICE
376 if (params.stop_service) {
377 if (stop_smsd_service()) {
378 printf("Service %s stopped sucessfully\n", smsd_service_name);
379 exit(0);
380 } else {
381 printf("Error stopping %s service\n", smsd_service_name);
382 service_print_error("Error stopping service");
383 exit(1);
386 if (params.uninstall_service) {
387 if (uninstall_smsd_service()) {
388 printf("Service %s uninstalled sucessfully\n", smsd_service_name);
389 exit(0);
390 } else {
391 printf("Error uninstalling %s service\n", smsd_service_name);
392 service_print_error("Error uninstalling service");
393 exit(1);
396 #endif
398 if (params.config_file == NULL) {
399 #ifdef HAVE_DEFAULT_CONFIG
400 params.config_file = default_config;
401 #else
402 fprintf(stderr, "No config file specified!\n");
403 help();
404 exit(1);
405 #endif
407 #ifdef HAVE_WINDOWS_SERVICE
408 if (params.install_service) {
409 if (install_smsd_service(&params)) {
410 printf("Service %s installed sucessfully\n", smsd_service_name);
411 exit(0);
412 } else {
413 printf("Error installing %s service\n", smsd_service_name);
414 service_print_error("Error installing service");
415 exit(1);
418 if (params.start_service) {
419 if (start_smsd_service()) {
420 printf("Service %s started sucessfully\n", smsd_service_name);
421 exit(0);
422 } else {
423 printf("Error starting %s service\n", smsd_service_name);
424 service_print_error("Error starting service");
425 exit(1);
428 #endif
430 read_config:
431 config = SMSD_NewConfig(program_name);
432 assert(config != NULL);
434 error = SMSD_ReadConfig(params.config_file, config, params.use_log);
435 if (error != ERR_NONE) {
436 printf("Failed to read config: %s\n", GSM_ErrorString(error));
437 SMSD_FreeConfig(config);
438 return 2;
441 if (!reconfigure)
442 configure_daemon(&params);
444 reconfigure = FALSE;
445 error = SMSD_MainLoop(config, FALSE, params.max_failures);
446 if (error != ERR_NONE) {
447 printf("Failed to run SMSD: %s\n", GSM_ErrorString(error));
448 SMSD_FreeConfig(config);
449 return 2;
452 SMSD_FreeConfig(config);
454 if (reconfigure) {
455 goto read_config;
458 return 0;
461 /* How should editor hadle tabs in this file? Add editor commands here.
462 * vim: noexpandtab sw=8 ts=8 sts=8: