00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <sys/types.h>
00034 #include <pwd.h>
00035 #include <grp.h>
00036
00037 #include <libmnt/libmnt.h>
00038
00039 #define _GNU_SOURCE
00040 #include <getopt.h>
00041
00042 #include "errmanager.h"
00043 #include "file.h"
00044 #include "mntd_dbus_manager.h"
00045 #include "mntd_volume_manager.h"
00046 #include "mntd_volume_config.h"
00047 #include "daemonize.h"
00048 #include "main.h"
00049 #include "sig.h"
00050 #include "dbug_mem.h"
00051
00052
00054 PMNTDDATA pmd = NULL;
00055
00056
00057 void usage(void);
00058 void sig_quit(int signum);
00059 void sig_reload(int signum);
00060
00061
00072 void
00073 usage(void)
00074 {
00075 printf("Mount Daemon " PACKAGE_VERSION "\n");
00076 printf("Mounts devices automatically and unmount it again. It's meant\n");
00077 printf("to handle hotplug devices like USB storage or similar stuff.\n");
00078 printf("\n");
00079 printf("usage: mntd [-h] [-d] [-f configfile]\n");
00080 printf("\n");
00081 printf(" -h Help (this text)\n");
00082 printf(" -d Daemonize it\n");
00083 printf(" -r,--reload Reload daemons configuration\n");
00084 printf(" -q,--quit Quit daemon\n");
00085 printf(" -f,--file Use given configfile\n");
00086 printf(" -p,--pidfile Use given pidfile\n");
00087 printf("\n");
00088 }
00089
00090
00095 void sig_quit(int signum)
00096 {
00097 sb_signal_handler_t old = signal(signum, SIG_IGN);
00098
00099
00100 pmd->quit_reason = QUIT_NORMAL;
00101
00102
00103 g_main_loop_quit(pmd->loop);
00104
00105 signal(signum, old);
00106 }
00107
00108
00113 void sig_reload(int signum)
00114 {
00115 sb_signal_handler_t old = signal(signum, SIG_IGN);
00116
00117
00118 pmd->quit_reason = QUIT_RELOAD;
00119
00120
00121 g_main_loop_quit(pmd->loop);
00122
00123 signal(signum, old);
00124 }
00125
00126
00131 void mntd_cb_disconnect(void *user_data);
00132 void mntd_cb_disconnect(void *user_data)
00133 {
00134 PMNTDDATA pmntddata = (PMNTDDATA) user_data;
00135
00136
00137 pmntddata->quit_reason = QUIT_DISCONNECTED;
00138
00139
00140 g_main_loop_quit(pmntddata->loop);
00141 }
00142
00143
00150 int main(int argc, char* argv[])
00151 {
00152 char *config = NULL;
00153 char *pidfile = DEFAULT_PIDFILE;
00154 int i=0;
00155 char *configfile = NULL;
00156 char *configfiles[] = {
00157 #ifdef DEBUG
00158 "./mntd.conf",
00159 "../mntd.conf",
00160 #endif
00161 MNTD_CONF_DIR "/mntd.conf",
00162 "/etc/mntd/mntd.conf",
00163 "/etc/mntd.conf",
00164 NULL
00165 };
00166 int daemonize = FALSE;
00167 int reload = FALSE;
00168 int quit = FALSE;
00169
00170 struct passwd *pwd;
00171 struct group *grp;
00172
00173
00174 while(1) {
00175 int c;
00176 int option_index = 0;
00177 static struct option long_options[] = {
00178 {"help", no_argument, 0, 'h'},
00179 {"daemonize", no_argument, 0, 'd'},
00180 {"reload", no_argument, 0, 'r'},
00181 {"quit", no_argument, 0, 'q'},
00182 {"file", required_argument, 0, 'f'},
00183 {"pidfile", required_argument, 0, 'p'},
00184 {0, 0, 0, 0}
00185 };
00186 c = getopt_long (argc, argv, "hf:dqrp:", long_options, &option_index);
00187 if (c == -1) {
00188 break;
00189 }
00190 switch (c) {
00191 case 'h':
00192 usage();
00193 exit(EXIT_SUCCESS);
00194 break;
00195
00196 case 'd':
00197 daemonize = TRUE;
00198 break;
00199
00200 case 'r':
00201 reload = TRUE;
00202 break;
00203
00204 case 'q':
00205 quit = TRUE;
00206 break;
00207
00208 case 'f':
00209 config = optarg;
00210 break;
00211
00212 case 'p':
00213 pidfile = optarg;
00214 break;
00215
00216 default:
00217 usage();
00218 exit(EXIT_FAILURE);
00219 break;
00220 }
00221 }
00222
00223
00224 #ifdef DEBUG
00225 emInit(LOG_DEBUG, EM_TYPE_SYSLOG, NULL, NULL, NULL, PACKAGE);
00226 #else
00227 emInit(LOG_NOTICE, EM_TYPE_SYSLOG, NULL, NULL, NULL, PACKAGE);
00228 #endif
00229
00230
00231 DBUG_MEM_INIT();
00232
00233
00234 MSG_NOTICE("MNT daemon version " PACKAGE_VERSION " starting up");
00235
00236
00237 pmd = (PMNTDDATA) malloc(sizeof(MNTDDATA));
00238 if (pmd==NULL) {
00239 MSG_ERR("No memory for mntd data structure left -> exiting ...");
00240 exit(EXIT_FAILURE);
00241 }
00242
00243
00244 memset(pmd, 0, sizeof(MNTDDATA));
00245
00246
00247 pmd->disconnect = mntd_cb_disconnect;
00248
00249
00250 if (config == NULL) {
00251 MSG_DEBUG("No config file specified. trying to find it.");
00252 i=0;
00253 while (configfiles[i]!=NULL) {
00254 configfile = configfiles[i];
00255 MSG_DEBUG("trying '%s' ...", configfile);
00256 if (sb_file_is_file(configfile)) {
00257 MSG_DEBUG("found '%s'", configfile);
00258 config = configfile;
00259 break;
00260 }
00261 i++;
00262 }
00263 }
00264
00265 if (config == NULL) {
00266 MSG_EMERG("No config file given and nothing found. exiting.");
00267 exit(EXIT_FAILURE);
00268 }
00269 if (!sb_file_is_file(config)) {
00270 MSG_EMERG("Config file '%s' cannot be accessed.", config);
00271 exit(EXIT_FAILURE);
00272 }
00273
00274
00275 pmd->configdata = mntd_volume_config_parse(config, pidfile);
00276 if (pmd->configdata==NULL) {
00277 MSG_ERR("Error reading configfile '%s'.", config);
00278 exit(EXIT_FAILURE);
00279 }
00280
00281
00282 #ifndef DEBUG
00283 emInit(pmd->configdata->loglevel, EM_TYPE_SYSLOG, NULL, NULL, NULL, PACKAGE);
00284 #endif
00285
00286
00287 if (quit == TRUE) {
00288
00289 if (sb_daemon_is_running(pmd->configdata->pidfile) == 1) {
00290 pid_t pid = sb_daemon_pidfile_read(pmd->configdata->pidfile);
00291 if (pid != -1) {
00292 MSG_DEBUG("running daemon has pid %d -> sending SIGTERM", pid);
00293 kill(pid, SIGTERM);
00294 }
00295 } else {
00296 MSG_ERR("No daemon to shutdown found! (If running with another pidfile than '%s', shutdown it manually by sending SIGTERM to it)", pmd->configdata->pidfile);
00297 exit(EXIT_FAILURE);
00298 }
00299 mntd_volume_config_free(&(pmd->configdata));
00300 exit(EXIT_SUCCESS);
00301 }
00302
00303
00304 if (reload == TRUE) {
00305
00306 if (sb_daemon_is_running(pmd->configdata->pidfile) == 1) {
00307 pid_t pid = sb_daemon_pidfile_read(pmd->configdata->pidfile);
00308 if (pid != -1) {
00309 MSG_DEBUG("running daemon has pid %d -> sending SIGHUP", pid);
00310 kill(pid, SIGHUP);
00311 }
00312 } else {
00313 MSG_ERR("No daemon to reload found! (If running with another pidfile than '%s', reload it manually by sending SIGHUP to it)", pmd->configdata->pidfile);
00314 exit(EXIT_FAILURE);
00315 }
00316 mntd_volume_config_free(&(pmd->configdata));
00317 exit(EXIT_SUCCESS);
00318 }
00319
00320
00321 if (daemonize == TRUE) {
00322
00323 if (sb_daemon_is_started_by_root() == 0) {
00324 MSG_ERR("You have to be root to start this daemon!");
00325 exit(EXIT_FAILURE);
00326 }
00327
00328 if (sb_daemon_is_started_suid() == 1) {
00329 MSG_ERR("Do not start this daemon with suid bits set!");
00330 exit(EXIT_FAILURE);
00331 }
00332
00333 sb_daemon_drop_privileges();
00334
00335 sb_daemon_no_corefile();
00336
00337 if (sb_daemon_is_running(pmd->configdata->pidfile) == 1) {
00338 pid_t pid = sb_daemon_pidfile_read(pmd->configdata->pidfile);
00339 MSG_ERR("Daemon (pid=%d) already running. exiting.", pid);
00340 exit(EXIT_FAILURE);
00341 }
00342
00343 if (sb_daemon_init(PACKAGE, pmd->configdata->wdir,
00344 pmd->configdata->pidfile) != 0) {
00345 MSG_EMERG("Couldn't daemonize.");
00346 exit(EXIT_FAILURE);
00347 }
00348 } else {
00349
00350 int fd = -1;
00351 if (pmd->configdata->pidfile != NULL) {
00352 if ((fd = sb_daemon_pidfile_create_and_lock(pmd->configdata->pidfile)) == -1) {
00353 return -1;
00354 }
00355 if (sb_daemon_pidfile_write(fd) == -1) {
00356 return -1;
00357 }
00358 }
00359 }
00360
00361
00362 pwd = getpwuid(getuid());
00363 if (pwd == NULL) {
00364 MSG_ERR("Couldn't get user entry.");
00365 exit(EXIT_FAILURE);
00366 }
00367 grp = getgrgid(pwd->pw_gid);
00368 if (grp == NULL) {
00369 MSG_ERR("Couldn't get group entry.");
00370 exit(EXIT_FAILURE);
00371 }
00372
00373
00374 MSG_INF("running as user '%s' (%d) and group '%s' (%d)",
00375 pwd->pw_name, pwd->pw_uid, grp->gr_name, pwd->pw_gid);
00376
00377
00378 sb_signal_set_handler(SIGTERM, sig_quit);
00379 sb_signal_set_handler(SIGINT, sig_quit);
00380 sb_signal_set_handler(SIGQUIT, sig_quit);
00381 sb_signal_set_handler(SIGABRT, sig_quit);
00382 sb_signal_set_handler(SIGHUP, sig_reload);
00383
00384
00385 pmd->vols = new_VolumeManager(pmd->configdata->mountpath,
00386 pmd->configdata->mountprefix);
00387 if (pmd->vols == NULL) {
00388 MSG_EMERG("Couldn't not initialize system.");
00389 exit(EXIT_FAILURE);
00390 }
00391
00392 pmd->loop = g_main_loop_new(NULL, FALSE);
00393
00394
00395 int retries = 0;
00396 while(1) {
00397 int isconnected = -1;
00398
00399
00400 isconnected = mntd_dbus_init(pmd);
00401 if (isconnected == 0) {
00402
00403
00404 retries = 0;
00405
00406
00407 pmd->vols->rescan(pmd->vols);
00408
00409
00410 g_main_loop_run(pmd->loop);
00411
00412 } else {
00413
00414 pmd->quit_reason = QUIT_NOT_CONNECTED;
00415
00416 }
00417
00418
00419 if (pmd->quit_reason == QUIT_DISCONNECTED) {
00420
00421 MSG_WARNING("Disconnected from DBUS (Retrying if configured).");
00422
00423
00424 mntd_dbus_quit();
00425
00426
00427 retries++;
00428
00429
00430 if (pmd->configdata->dbus_reconnect != -1) {
00431 usleep((pmd->configdata->sleep_millis)*1000);
00432 }
00433
00434 } else if (pmd->quit_reason == QUIT_NOT_CONNECTED) {
00435
00436 MSG_WARNING("Not connected to DBUS (Retrying if configured).");
00437
00438
00439 retries++;
00440
00441
00442 if (pmd->configdata->dbus_reconnect != -1) {
00443 usleep((pmd->configdata->sleep_millis)*1000);
00444 }
00445
00446 }
00447
00448
00449 if (pmd->quit_reason == QUIT_NORMAL) {
00450
00451 MSG_INF("QUIT requested -> shutting down daemon ...");
00452
00453
00454 break;
00455
00456 } else if (pmd->quit_reason == QUIT_RELOAD) {
00457
00458 MSG_INF("RELOAD requested -> reloading configuration ...");
00459
00460
00461 mntd_volume_config_reload(&(pmd->configdata), pidfile);
00462
00463
00464 continue;
00465
00466 }
00467
00468
00469 if (pmd->configdata->dbus_reconnect == -1) {
00470 break;
00471 } else if (pmd->configdata->dbus_reconnect == 0) {
00472 continue;
00473 }
00474
00475 MSG_DEBUG("trying to connect... %d", retries);
00476
00477
00478 if (retries >= pmd->configdata->dbus_reconnect) {
00479 MSG_INF("maximum retries reached -> exit");
00480 break;
00481 }
00482
00483 }
00484
00485
00486 sb_signal_restore_all_handlers();
00487
00488
00489 mntd_dbus_quit();
00490
00491
00492 g_assert(pmd->vols!=NULL);
00493 pmd->vols->destroy(pmd->vols);
00494
00495
00496 g_assert(pmd->configdata!=NULL);
00497 sb_daemon_destroy(pmd->configdata->pidfile);
00498
00499
00500 mntd_volume_config_free(&(pmd->configdata));
00501
00502
00503 if (pmd != NULL) {
00504 memset(pmd, 0, sizeof(MNTDDATA));
00505 free(pmd);
00506 pmd = NULL;
00507 }
00508
00509
00510 MSG_NOTICE("MNT daemon version " PACKAGE_VERSION " exited.");
00511
00512
00513 DBUG_MEM_QUIT();
00514
00515 return 0;
00516 }
00517