4 * Copyright(C) 2007,2008 Ixonos Plc
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Boston, MA 02111.
33 * \section intro Introduction
35 * This is the documentation of GSM daemon called GSMD2.
37 * \section install_sec Installation
51 #include <dbus/dbus-glib-bindings.h>
52 #include <glib-object.h>
53 #include <glib/gquark.h>
55 #include "modem_internal.h"
56 #include "dbus_objects.h"
59 #define RUNNING_DIR "/"
60 #define LOCK_FILE "/var/lock/LCK..gsmd2.lock"
62 #define DEFAULT_VENDOR "generic"
63 #define DEFAULT_SERIAL_PLUGIN "generic"
64 #define DEFAULT_DEVICE "/dev/ttyS2"
65 #define DEFAULT_CONFFILE "/etc/gsmd2/gsmd2.conf"
66 static gchar
**devices
= NULL
;
67 static gchar
*vendor
= DEFAULT_VENDOR
;
68 static gchar
*serial_plugin
= DEFAULT_SERIAL_PLUGIN
;
69 static gchar
*conffile
= DEFAULT_CONFFILE
;
70 static gboolean no_conf
= FALSE
; //Should the conf file be read
71 static gboolean no_cache
= FALSE
; //Should we cache values
72 static gboolean no_daemon
= FALSE
; //Should the process be daemon (FALSE)
73 //or a normal process (TRUE)
74 static gint interface_devices
[INTERFACE_LAST
] = {0};
76 //Command line parameters
77 static GOptionEntry options
[] = {
78 { "conf", 'c',G_OPTION_FLAG_FILENAME
, G_OPTION_ARG_STRING
, &conffile
,
79 "The configuration file to use. "
80 "The configuration file defaults to '" DEFAULT_CONFFILE
"'.", NULL
},
81 { "no-conf", 0, 0, G_OPTION_ARG_NONE
, &no_conf
,
82 "Do not try to read configuration file. "
83 "The configuration file is read by default.", NULL
},
84 { "no-cache", 0, 0, G_OPTION_ARG_NONE
, &no_cache
,
85 "Do not cache any responses."
86 "The configuration file is read by default.", NULL
},
87 { "device", 'd', 0, G_OPTION_ARG_STRING_ARRAY
, &devices
,
88 "The device of the modem. "
89 "The device defaults to '" DEFAULT_DEVICE
"'.", NULL
},
90 { "vendor", 'v', 0, G_OPTION_ARG_STRING
, &vendor
,
92 "The vendor defaults to '" DEFAULT_VENDOR
"'.", NULL
},
93 { "serial", 's', 0, G_OPTION_ARG_STRING
, &serial_plugin
,
95 "The vendor defaults to '" DEFAULT_SERIAL_PLUGIN
"'.", NULL
},
96 { "no-daemon", 'n', 0, G_OPTION_ARG_NONE
, &no_daemon
,
97 "Run without making this process a daemon"
99 { "general_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_GENERAL
],
100 "Specify index of the the device to be used in general communication"
102 { "call_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_CALL
],
103 "Specify the index of the device used in call interface's communication"
105 { "device_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_DEVICE
],
106 "Specify the index of the device used in device interface's communication"
108 { "network_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_NETWORK
],
109 "Specify the index of the device used in network interface's communication"
111 { "pdp_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_PDP
],
112 "Specify the index of the device used in pdp interface's communication"
114 { "sim_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_SIM
],
115 "Specify the index of the device used in sim interface's communication"
117 { "sms_index",0, 0, G_OPTION_ARG_INT
, &interface_devices
[INTERFACE_SMS
],
118 "Specify the index of the device used in sms interface's communication"
123 GMainLoop
*loop
= NULL
;
127 * @brief Wrapper to the syslog function
129 * @param priority priority of the message to log
130 * @param message message to log
132 void syslog_message(int priority
, const char *message
)
135 syslog(priority
, message
);
140 * @brief Custom signal handler to SIGHUP,SIGTERM,SIGQUIT and SIGINT.
142 * - SIGHUP writes to syslog
143 * - SIGTEMR/SIGQUIT/SIGINT quits main loop and closes the log.
145 * @param sig signal to handle
147 void signal_handler(int sig
)
151 syslog_message(LOG_INFO
, "SIGHUP signal catched");
157 if (loop
&& g_main_loop_is_running(loop
))
158 g_main_loop_quit( loop
);
159 syslog_message(LOG_INFO
, "SIGTERM, SIGINT or SIGQUIT signal catched. Daemon stopped.");
167 GKeyFile
* gsmd_read_configuration_file(const gchar
*file
)
169 GKeyFile
*conf
= g_key_file_new();
170 GError
*error
= NULL
;
171 gchar
**string_list
= NULL
;
172 gchar
*string
= NULL
;
173 gboolean
bool = FALSE
;
174 if( !g_key_file_load_from_file(conf
, conffile
, G_KEY_FILE_NONE
, &error
) ) {
175 g_warning("%s : %s", __func__
, error
->message
);
176 g_error_free( error
);
177 g_key_file_free( conf
);
180 string_list
= g_key_file_get_string_list(conf
, "Default", "devices", NULL
, NULL
);
183 g_debug("%s : Using devices from %s", __func__
, conffile
);
184 devices
= string_list
;
187 g_strfreev( string_list
);
190 string
= g_key_file_get_string(conf
, "Default", "vendor",NULL
);
192 if( (gpointer
)vendor
== (gpointer
)DEFAULT_VENDOR
) {
193 g_debug("%s : Using vendor %s from %s", __func__
, string
, conffile
);
200 string
= g_key_file_get_string(conf
, "Default", "serial",NULL
);
202 if( (gpointer
)serial_plugin
== (gpointer
)DEFAULT_SERIAL_PLUGIN
) {
203 g_debug("%s : Using serial plugin %s from %s", __func__
, string
, conffile
);
204 serial_plugin
= string
;
210 bool = g_key_file_get_boolean(conf
, "Default", "no-daemon",&error
);
212 g_debug("%s : no-daemon: %s", __func__
, bool ? "yes": "no");
215 g_debug("%s : no-daemon error: %s", __func__
, error
->message
);
216 g_error_free( error
);
219 bool = g_key_file_get_boolean(conf
, "Default", "no-cache",&error
);
221 g_debug("%s : no-cache: %s", __func__
, bool ? "yes": "no");
224 g_debug("%s : no-cache error: %s", __func__
, error
->message
);
225 g_error_free( error
);
232 * @brief Daemonizes the process.
242 openlog("gsmd2", (LOG_CONS
|LOG_PERROR
|LOG_PID
), LOG_DAEMON
);
249 syslog_message(LOG_ERR
, "Can not fork process! Daemon not started.");
257 /* daemon must have own process group */
260 /* close all open descriptors */
261 for (i
=getdtablesize(); i
>=0; --i
)
264 /* Redirect standard files to /dev/null */
265 freopen( "/dev/null", "r", stdin
);
266 freopen( "/dev/null", "w", stdout
);
267 freopen( "/dev/null", "w", stderr
);
269 /* change running directory to "/" */
271 lock_file
= open(LOCK_FILE
, O_RDWR
|O_CREAT
, 0640);
273 /* can't open lock file*/
275 syslog_message(LOG_ERR
, "Can't open lock file");
280 if (lockf(lock_file
, F_TLOCK
, 0) < 0) {
281 syslog_message(LOG_ERR
, "Can't set F_TLOCK to the lock file.");
282 syslog_message(LOG_ERR
, "Daemon is probably already running!");
286 /* record program ID to lockfile */
287 sprintf(str
, "%d\n", getpid());
288 write(lock_file
, str
, strlen(str
));
290 /* set signal handlers */
291 signal(SIGCHLD
, SIG_IGN
);
292 signal(SIGTSTP
, SIG_IGN
);
293 signal(SIGTTOU
, SIG_IGN
);
294 signal(SIGTTIN
, SIG_IGN
);
295 signal(SIGHUP
, signal_handler
);
296 signal(SIGTERM
, signal_handler
);
297 signal(SIGQUIT
, signal_handler
);
298 signal(SIGINT
, signal_handler
);
300 syslog_message(LOG_INFO
, "daemon is running successfully");
303 int main(int argc
, char**argv
)
305 GOptionContext
*ctx
= NULL
;
306 GError
*error
= NULL
;
307 ModemInterface
* modem
= NULL
;
308 GKeyFile
*conf
= NULL
;
309 if(!g_module_supported()) {
310 g_critical("%s : Current platform does not support GModule",__func__
);
314 /* To be able to use GObjects or GType's */
317 //Parse commandline parameters
318 ctx
= g_option_context_new(NULL
);
319 g_option_context_add_main_entries (ctx
, options
, NULL
);
321 if (!g_option_context_parse (ctx
, &argc
, &argv
, &error
)) {
322 g_print ("%s\n", error
->message
);
325 g_option_context_free(ctx
);
328 conf
= gsmd_read_configuration_file(conffile
);
330 g_warning("%s : Failed to read configuration file '%s'", __func__
, conffile
);
334 //Check if we need to daemonize the process
336 g_debug("demonizing");
341 loop
= g_main_loop_new (NULL
, FALSE
);
343 g_warning("Loop was NULL");
347 //Create a new modem device
348 if (devices
== NULL
) {
349 devices
= g_new0(char*,2);
350 devices
[0] = DEFAULT_DEVICE
;
353 modem
= gsmd_modem_open (devices
,
358 &gsmd_dbus_initialize
,
364 g_warning ("cannot open modem\n");
368 //Start the main loop
369 g_main_loop_run (loop
);
370 gsmd_modem_free (modem
);
371 gsmd_dbus_uninitialize((DBusObjects
*)modem
->ipc_data
);