upgrade obexd to 0.47
[profile/ivi/obexd.git] / client / main.c
1 /*
2  *
3  *  OBEX Client
4  *
5  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program 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 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program 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 this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <signal.h>
32 #include <syslog.h>
33 #include <unistd.h>
34 #include <sys/signalfd.h>
35
36 #include <glib.h>
37 #include <gdbus.h>
38
39 #include "log.h"
40 #include "manager.h"
41
42 static GMainLoop *event_loop = NULL;
43
44 static unsigned int __terminated = 0;
45
46 static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
47                                                         gpointer user_data)
48 {
49         struct signalfd_siginfo si;
50         ssize_t result;
51         int fd;
52
53         if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
54                 return FALSE;
55
56         fd = g_io_channel_unix_get_fd(channel);
57
58         result = read(fd, &si, sizeof(si));
59         if (result != sizeof(si))
60                 return FALSE;
61
62         switch (si.ssi_signo) {
63         case SIGINT:
64         case SIGTERM:
65                 if (__terminated == 0) {
66                         info("Terminating");
67                         g_main_loop_quit(event_loop);
68                 }
69
70                 __terminated = 1;
71                 break;
72         case SIGUSR2:
73                 __obex_log_enable_debug();
74                 break;
75         case SIGPIPE:
76                 /* ignore */
77                 break;
78         }
79
80         return TRUE;
81 }
82
83 static guint setup_signalfd(void)
84 {
85         GIOChannel *channel;
86         guint source;
87         sigset_t mask;
88         int fd;
89
90         sigemptyset(&mask);
91         sigaddset(&mask, SIGINT);
92         sigaddset(&mask, SIGTERM);
93         sigaddset(&mask, SIGUSR2);
94         sigaddset(&mask, SIGPIPE);
95
96         if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
97                 perror("Failed to set signal mask");
98                 return 0;
99         }
100
101         fd = signalfd(-1, &mask, 0);
102         if (fd < 0) {
103                 perror("Failed to create signal descriptor");
104                 return 0;
105         }
106
107         channel = g_io_channel_unix_new(fd);
108
109         g_io_channel_set_close_on_unref(channel, TRUE);
110         g_io_channel_set_encoding(channel, NULL, NULL);
111         g_io_channel_set_buffered(channel, FALSE);
112
113         source = g_io_add_watch(channel,
114                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
115                                 signal_handler, NULL);
116
117         g_io_channel_unref(channel);
118
119         return source;
120 }
121
122 static char *option_debug = NULL;
123 static gboolean option_stderr = FALSE;
124
125 static gboolean parse_debug(const char *key, const char *value,
126                                 gpointer user_data, GError **error)
127 {
128         if (value)
129                 option_debug = g_strdup(value);
130         else
131                 option_debug = g_strdup("*");
132
133         return TRUE;
134 }
135
136 static GOptionEntry options[] = {
137         { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
138                                 G_OPTION_ARG_CALLBACK, parse_debug,
139                                 "Enable debug information output", "DEBUG" },
140         { "stderr", 's', 0, G_OPTION_ARG_NONE, &option_stderr,
141                                 "Write log information to stderr" },
142         { NULL },
143 };
144
145
146 int main(int argc, char *argv[])
147 {
148         GOptionContext *context;
149         GError *gerr = NULL;
150         guint signal;
151
152         context = g_option_context_new(NULL);
153         g_option_context_add_main_entries(context, options, NULL);
154
155         g_option_context_parse(context, &argc, &argv, &gerr);
156         if (gerr != NULL) {
157                 g_printerr("%s\n", gerr->message);
158                 g_error_free(gerr);
159                 exit(EXIT_FAILURE);
160         }
161
162         g_option_context_free(context);
163
164         event_loop = g_main_loop_new(NULL, FALSE);
165
166         signal = setup_signalfd();
167
168         __obex_log_init("obex-client", option_debug, !option_stderr);
169
170         if (manager_init() < 0)
171                 exit(EXIT_FAILURE);
172
173         DBG("Entering main loop");
174
175         g_main_loop_run(event_loop);
176
177         g_source_remove(signal);
178
179         manager_exit();
180
181         g_main_loop_unref(event_loop);
182
183         __obex_log_cleanup();
184
185         return 0;
186 }