4 /* Copyright (c) 2009 - 2011 Michal Cihar <michal@cihar.com> */
5 /* Licensend under GNU GPL 2 */
7 #include <gammu-smsd.h>
14 #ifdef HAVE_GETOPT_LONG
17 #ifdef HAVE_WINDOWS_SERVICE
18 #include "winservice.h"
27 #if defined(HAVE_GETPWNAM) && defined(HAVE_GETGRNAM) && defined(HAVE_SETUID) && defined(HAVE_SETGID) && defined(HAVE_INITGROUPS)
33 #define HAVE_DEFAULT_CONFIG
34 const char default_config
[] = "/etc/gammu-smsdrc";
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
)
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");
59 printf(" - %s\n", "SHM");
62 printf(" - %s\n", "DAEMON");
65 printf(" - %s\n", "PID");
68 printf(" - %s\n", "ALARM");
72 #ifdef HAVE_WINDOWS_SERVICE
73 printf(" - %s\n", "WINDOWS_SERVICE");
76 printf(" - %s\n", "GETOPT");
78 #ifdef HAVE_GETOPT_LONG
79 printf(" - %s\n", "GETOPT_LONG");
81 #ifdef HAVE_WINDOWS_EVENT_LOG
82 printf(" - %s\n", "EVENT_LOG");
85 printf(" - %s\n", "SYSLOG");
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");
93 #ifdef HAVE_POSTGRESQL_LIBPQ_FE_H
94 printf(" - %s\n", "POSTGRESQL");
97 printf(" - %s\n", "DBI");
100 printf(" - %s\n", "ODBC");
103 printf("Copyright (C) 2003 - 2011 Michal Cihar <michal@cihar.com> and other authors.\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");
109 printf("Check <http://wammu.eu/gammu/> for updates.\n");
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);
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);
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");
134 print_option("d", "daemon", "daemonizes program after startup");
137 print_option_param("p", "pid", "PID_FILE", "defines path to pid file");
140 print_option_param("U", "user", "USER", "run daemon as a user");
141 print_option_param("G", "group", "GROUP", "run daemon as a group");
143 print_option_param("f", "max-failures", "NUM", "number of failures before terminating");
145 print_option_param("X", "suicide", "SECONDS", "kills itself after number of seconds");
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)");
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");
165 void process_commandline(int argc
, char **argv
, SMSD_Parameters
* params
)
169 #ifdef HAVE_GETOPT_LONG
170 struct option long_options
[] = {
172 {"version", 0, 0, 'v'},
173 {"config", 1, 0, 'c'},
174 {"daemon", 0, 0, 'd'},
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'},
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'},
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) {
196 /* Poor mans getopt replacement */
199 #define optarg argv[++i]
201 for (i
= 1; i
< argc
; i
++) {
202 if (strlen(argv
[i
]) != 2 || argv
[i
][0] != '-') {
209 params
->config_file
= optarg
;
213 params
->pid_file
= optarg
;
218 if (!fill_uid(params
, optarg
)) {
219 fprintf(stderr
, "Wrong user name/ID!\n");
224 if (!fill_gid(params
, optarg
)) {
225 fprintf(stderr
, "Wrong group name/ID!\n");
231 params
->max_failures
= atoi(optarg
);
240 params
->daemonize
= TRUE
;
243 #ifdef HAVE_WINDOWS_SERVICE
245 params
->install_service
= TRUE
;
248 params
->uninstall_service
= TRUE
;
251 params
->start_service
= TRUE
;
254 params
->stop_service
= TRUE
;
257 params
->run_service
= TRUE
;
260 strncpy(smsd_service_name
, optarg
, SERVICE_NAME_LENGTH
);
261 smsd_service_name
[SERVICE_NAME_LENGTH
- 1] = 0;
268 params
->use_log
= TRUE
;
271 params
->use_log
= FALSE
;
284 #if defined(HAVE_GETOPT) || defined(HAVE_GETOPT_LONG)
292 void configure_daemon(SMSD_Parameters
* params
)
294 signal(SIGINT
, smsd_interrupt
);
295 signal(SIGTERM
, smsd_interrupt
);
297 signal(SIGHUP
, smsd_reconfigure
);
300 signal(SIGALRM
, smsd_interrupt
);
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
));
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
);
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
));
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");
338 SMSD_FreeConfig(config
);
345 int main(int argc
, char **argv
)
348 const char program_name
[] = "gammu-smsd";
350 SMSD_Parameters params
= {
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
, ¶ms
);
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
);
381 printf("Error stopping %s service\n", smsd_service_name
);
382 service_print_error("Error stopping service");
386 if (params
.uninstall_service
) {
387 if (uninstall_smsd_service()) {
388 printf("Service %s uninstalled sucessfully\n", smsd_service_name
);
391 printf("Error uninstalling %s service\n", smsd_service_name
);
392 service_print_error("Error uninstalling service");
398 if (params
.config_file
== NULL
) {
399 #ifdef HAVE_DEFAULT_CONFIG
400 params
.config_file
= default_config
;
402 fprintf(stderr
, "No config file specified!\n");
407 #ifdef HAVE_WINDOWS_SERVICE
408 if (params
.install_service
) {
409 if (install_smsd_service(¶ms
)) {
410 printf("Service %s installed sucessfully\n", smsd_service_name
);
413 printf("Error installing %s service\n", smsd_service_name
);
414 service_print_error("Error installing service");
418 if (params
.start_service
) {
419 if (start_smsd_service()) {
420 printf("Service %s started sucessfully\n", smsd_service_name
);
423 printf("Error starting %s service\n", smsd_service_name
);
424 service_print_error("Error starting service");
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
);
442 configure_daemon(¶ms
);
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
);
452 SMSD_FreeConfig(config
);
461 /* How should editor hadle tabs in this file? Add editor commands here.
462 * vim: noexpandtab sw=8 ts=8 sts=8: