main.c 9.92 KB
Newer Older
Slava Monich's avatar
Slava Monich committed
1
/*
2
 * Copyright (C) 2013-2016 Jolla Ltd.
3
 * Contact: Slava Monich <slava.monich@jolla.com>
Slava Monich's avatar
Slava Monich committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <syslog.h>
#include <glib-unix.h>

#include "mms_engine.h"
#include "mms_lib_log.h"
#include "mms_lib_util.h"
22
#include "mms_settings.h"
Slava Monich's avatar
Slava Monich committed
23

24 25 26 27 28 29
#ifdef MMS_CONNMAN_NEMO
#  include "mms_connman_nemo_log.h"
#else
#  include "mms_connman_ofono_log.h"
#endif

30 31 32
#define RET_OK  (0)
#define RET_ERR (1)

Slava Monich's avatar
Slava Monich committed
33 34 35
/* Options configurable from the command line */
typedef struct mms_app_options {
    GBusType bus_type;
36
    int flags;
Slava Monich's avatar
Slava Monich committed
37
    char* dir;
38
    char* user_agent;
39
    char* uaprof;
Slava Monich's avatar
Slava Monich committed
40
    MMSConfig config;
41
    MMSSettingsSimData settings;
Slava Monich's avatar
Slava Monich committed
42 43 44 45 46 47 48
} MMSAppOptions;

/* All known log modules */
static MMSLogModule* mms_app_log_modules[] = {
    &mms_log_default,
#define MMS_LIB_LOG_MODULE(m) &(m),
    MMS_LIB_LOG_MODULES(MMS_LIB_LOG_MODULE)
49
    MMS_CONNMAN_LOG_MODULES(MMS_LIB_LOG_MODULE)
Slava Monich's avatar
Slava Monich committed
50 51 52 53 54 55 56 57 58
#undef MMS_LIB_LOG_MODULE
};

/* Signal handler */
static
gboolean
mms_app_signal(
    gpointer arg)
{
59
    MMSEngine* engine = arg;
Slava Monich's avatar
Slava Monich committed
60
    MMS_INFO("Caught signal, shutting down...");
61 62
    mms_engine_stop(engine);
    return TRUE;
Slava Monich's avatar
Slava Monich committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
}

/* D-Bus event handlers */
static
void
mms_app_bus_acquired(
    GDBusConnection* bus,
    const gchar* name,
    gpointer arg)
{
    MMSEngine* engine = arg;
    GError* error = NULL;
    MMS_DEBUG("Bus acquired, starting...");
    if (!mms_engine_register(engine, bus, &error)) {
        MMS_ERR("Could not start: %s", MMS_ERRMSG(error));
        g_error_free(error);
        mms_engine_stop(engine);
    }
}

static
void
mms_app_name_acquired(
    GDBusConnection* bus,
    const gchar* name,
    gpointer arg)
{
    MMS_DEBUG("Acquired service name '%s'", name);
}

static
void
mms_app_name_lost(
    GDBusConnection* bus,
    const gchar* name,
    gpointer arg)
{
    MMSEngine* engine = arg;
    MMS_ERR("'%s' service already running or access denied", name);
    mms_engine_stop(engine);
}

/* Option parsing callbacks */
static
gboolean
mms_app_option_loglevel(
    const gchar* name,
    const gchar* value,
    gpointer data,
    GError** error)
{
    return mms_log_parse_option(value, mms_app_log_modules,
        G_N_ELEMENTS(mms_app_log_modules), error);
}

static
gboolean
mms_app_option_logtype(
    const gchar* name,
    const gchar* value,
    gpointer data,
    GError** error)
{
    if (mms_log_set_type(value, MMS_APP_LOG_PREFIX)) {
        return TRUE;
    } else {
        if (error) {
            *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
                "Invalid log type \'%s\'", value);
        }
        return FALSE;
    }
}

static
gboolean
mms_app_option_verbose(
    const gchar* name,
    const gchar* value,
    gpointer data,
    GError** error)
{
    mms_log_default.level = MMS_LOGLEVEL_VERBOSE;
    return TRUE;
}

149 150 151 152 153
/**
 * Parses command line and sets up application options. Returns TRUE if
 * we should go ahead and run the application, FALSE if we should exit
 * immediately.
 */
Slava Monich's avatar
Slava Monich committed
154 155 156 157 158
static
gboolean
mms_app_parse_options(
    MMSAppOptions* opt,
    int argc,
159 160
    char* argv[],
    int* result)
Slava Monich's avatar
Slava Monich committed
161 162 163 164
{
    gboolean ok;
    GError* error = NULL;
    gboolean session_bus = FALSE;
165
#ifdef MMS_VERSION_STRING
166 167
    gboolean print_version = FALSE;
#endif
168
    gboolean log_modules = FALSE;
169 170 171
    gboolean keep_running = FALSE;
    gint size_limit_kb = -1;
    gdouble megapixels = -1;
Slava Monich's avatar
Slava Monich committed
172 173 174 175 176 177 178 179 180
    char* root_dir_help = g_strdup_printf(
        "Root directory for MMS files [%s]",
        opt->config.root_dir);
    char* retry_secs_help = g_strdup_printf(
        "Retry period in seconds [%d]",
        opt->config.retry_secs);
    char* idle_secs_help = g_strdup_printf(
        "Inactivity timeout in seconds [%d]",
        opt->config.idle_secs);
181
    char* description = mms_log_description(NULL, 0);
Slava Monich's avatar
Slava Monich committed
182 183 184 185 186 187

    GOptionContext* options;
    GOptionEntry entries[] = {
        { "session", 0, 0, G_OPTION_ARG_NONE, &session_bus,
          "Use session bus (default is system)", NULL },
        { "root-dir", 'd', 0, G_OPTION_ARG_FILENAME,
Slava Monich's avatar
Slava Monich committed
188
          &opt->dir, root_dir_help, "DIR" },
Slava Monich's avatar
Slava Monich committed
189 190 191 192
        { "retry-secs", 'r', 0, G_OPTION_ARG_INT,
          &opt->config.retry_secs, retry_secs_help, "SEC" },
        { "idle-secs", 'i', 0, G_OPTION_ARG_INT,
          &opt->config.idle_secs, idle_secs_help, "SEC" },
193
        { "size-limit", 's', 0, G_OPTION_ARG_INT,
194
          &size_limit_kb, "Maximum size for outgoing messages", "KB" },
195
        { "pix-limit", 'p', 0, G_OPTION_ARG_DOUBLE,
196
          &megapixels, "Maximum pixel count for outgoing images", "MPIX" },
197
        { "user-agent", 'u', 0, G_OPTION_ARG_STRING,
198 199 200
          &opt->user_agent, "The value of the User-Agent header", "STRING" },
        { "x-wap-profile", 'x', 0, G_OPTION_ARG_STRING,
          &opt->uaprof, "User agent profile", "URL" },
201
        { "keep-running", 'k', 0, G_OPTION_ARG_NONE, &keep_running,
Slava Monich's avatar
Slava Monich committed
202 203 204 205 206 207 208 209 210 211 212
          "Keep running after everything is done", NULL },
        { "keep-temp-files", 't', 0, G_OPTION_ARG_NONE,
           &opt->config.keep_temp_files,
          "Don't delete temporary files", NULL },
        { "attic", 'a', 0, G_OPTION_ARG_NONE,
          &opt->config.attic_enabled,
          "Store unrecognized push messages in the attic", NULL },
        { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
          mms_app_option_verbose, "Be verbose (equivalent to -l=verbose)",
          NULL },
        { "log-output", 'o', 0, G_OPTION_ARG_CALLBACK, mms_app_option_logtype,
213
          "Log output (stdout|syslog|glib) [stdout]", "TYPE" },
Slava Monich's avatar
Slava Monich committed
214 215
        { "log-level", 'l', 0, G_OPTION_ARG_CALLBACK, mms_app_option_loglevel,
          "Set log level (repeatable)", "[MODULE:]LEVEL" },
216 217
        { "log-modules", 0, 0, G_OPTION_ARG_NONE, &log_modules,
          "List available log modules", NULL },
218
#ifdef MMS_VERSION_STRING
219 220 221
        { "version", 0, 0, G_OPTION_ARG_NONE, &print_version,
          "Print program version and exit", NULL },
#endif
Slava Monich's avatar
Slava Monich committed
222 223 224 225 226 227 228 229 230 231 232 233 234
        { NULL }
    };

    options = g_option_context_new("- part of Jolla MMS system");
    g_option_context_add_main_entries(options, entries, NULL);
    g_option_context_set_description(options, description);
    ok = g_option_context_parse(options, &argc, &argv, &error);
    g_option_context_free(options);
    g_free(root_dir_help);
    g_free(retry_secs_help);
    g_free(idle_secs_help);
    g_free(description);

235 236 237 238 239 240 241 242 243 244 245 246
    if (!ok) {
        fprintf(stderr, "%s\n", MMS_ERRMSG(error));
        g_error_free(error);
        *result = RET_ERR;
        return FALSE;
    } else if (log_modules) {
        unsigned int i;
        for (i=0; i<G_N_ELEMENTS(mms_app_log_modules); i++) {
            printf("%s\n", mms_app_log_modules[i]->name);
        }
        *result = RET_OK;
        return FALSE;
247
#ifdef MMS_VERSION_STRING
248
    } else if (print_version) {
249
        printf("MMS engine %s\n", MMS_VERSION_STRING);
250 251 252
        *result = RET_OK;
        return FALSE;
#endif
253
    } else {
254 255
#ifdef MMS_VERSION_STRING
        MMS_INFO("Version %s starting", MMS_VERSION_STRING);
256
#else
Slava Monich's avatar
Slava Monich committed
257
        MMS_INFO("Starting");
258
#endif
259
        if (size_limit_kb >= 0) {
260 261
            opt->settings.size_limit = size_limit_kb * 1024;
            opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_SIZE_LIMIT;
262 263
        }
        if (megapixels >= 0) {
264 265 266 267 268 269
            opt->settings.max_pixels = (int)(megapixels*1000)*1000;
            opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_MAX_PIXELS;
        }
        if (opt->user_agent) {
            opt->settings.user_agent = opt->user_agent;
            opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_USER_AGENT;
270
        }
271 272 273 274
        if (opt->uaprof) {
            opt->settings.uaprof = opt->uaprof;
            opt->flags |= MMS_ENGINE_FLAG_OVERRIDE_UAPROF;
        }
Slava Monich's avatar
Slava Monich committed
275
        if (opt->dir) opt->config.root_dir = opt->dir;
276
        if (keep_running) opt->flags |= MMS_ENGINE_FLAG_KEEP_RUNNING;
Slava Monich's avatar
Slava Monich committed
277 278 279 280 281 282 283
        if (session_bus) {
            MMS_DEBUG("Attaching to session bus");
            opt->bus_type = G_BUS_TYPE_SESSION;
        } else {
            MMS_DEBUG("Attaching to system bus");
            opt->bus_type = G_BUS_TYPE_SYSTEM;
        }
284
        *result = RET_OK;
Slava Monich's avatar
Slava Monich committed
285 286 287 288 289 290
        return TRUE;
    }
}

int main(int argc, char* argv[])
{
291
    int result = RET_ERR;
Slava Monich's avatar
Slava Monich committed
292
    MMSAppOptions opt = {0};
293
    mms_lib_init(argv[0]);
294
    gofono_log.name = "mms-ofono";
Slava Monich's avatar
Slava Monich committed
295 296
    mms_log_default.name = MMS_APP_LOG_PREFIX;
    mms_lib_default_config(&opt.config);
297
    mms_settings_sim_data_default(&opt.settings);
298
    if (mms_app_parse_options(&opt, argc, argv, &result)) {
Slava Monich's avatar
Slava Monich committed
299 300 301
        MMSEngine* engine;

        /* Create engine instance. This may fail */
302
        engine = mms_engine_new(&opt.config, &opt.settings, opt.flags,
Slava Monich's avatar
Slava Monich committed
303 304 305 306 307
            mms_app_log_modules, G_N_ELEMENTS(mms_app_log_modules));
        if (engine) {

            /* Setup main loop */
            GMainLoop* loop = g_main_loop_new(NULL, FALSE);
308 309
            guint sigtrm = g_unix_signal_add(SIGTERM, mms_app_signal, engine);
            guint sigint = g_unix_signal_add(SIGINT, mms_app_signal, engine);
Slava Monich's avatar
Slava Monich committed
310 311

            /* Acquire name, don't allow replacement */
312
            guint name_id = g_bus_own_name(opt.bus_type, MMS_ENGINE_SERVICE,
Slava Monich's avatar
Slava Monich committed
313 314 315 316 317 318 319
                G_BUS_NAME_OWNER_FLAGS_REPLACE, mms_app_bus_acquired,
                mms_app_name_acquired, mms_app_name_lost, engine, NULL);

            /* Run the main loop */
            mms_engine_run(engine, loop);

            /* Cleanup and exit */
320 321
            if (sigtrm) g_source_remove(sigtrm);
            if (sigint) g_source_remove(sigint);
Slava Monich's avatar
Slava Monich committed
322 323 324 325 326 327 328 329 330
            g_bus_unown_name(name_id);
            g_main_loop_unref(loop);
            mms_engine_unref(engine);
        }
        MMS_INFO("Exiting");
    }
    if (mms_log_func == mms_log_syslog) {
        closelog();
    }
Slava Monich's avatar
Slava Monich committed
331
    g_free(opt.dir);
332
    g_free(opt.user_agent);
333
    g_free(opt.uaprof);
334
    mms_lib_deinit();
Slava Monich's avatar
Slava Monich committed
335 336
    return result;
}