/* XMMS2 - X Music Multiplexer System * Copyright (C) 2003-2007 XMMS2 Team * * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!! * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ /** @file * Simple launcher that spawns off xmms2d in the background. * The launcher exits when xmms2d's ipc is up. */ #include #include #include #include #include #include #include #include #include #include "xmms_configuration.h" #include "xmmsc/xmmsc_util.h" #include #include static char startup_msg[] = "\n--- Starting new xmms2d ---\n"; int main (int argc, char **argv) { pid_t pid; int i, fd, max_fd; int pipefd[2]; const gchar *logfile = NULL; const gchar *pidfile = NULL; GError *error = NULL; GOptionContext* context = NULL; GOptionEntry opts[] = { {"logfile", 'l', 0, G_OPTION_ARG_FILENAME, &logfile, "Redirect logs to ", ""}, {"pidfile", 'P', 0, G_OPTION_ARG_FILENAME, &pidfile, "Save xmms2d pid in ", ""}, {NULL} }; context = g_option_context_new ("- XMMS2 launcher"); g_option_context_set_ignore_unknown_options (context, TRUE); g_option_context_add_main_entries (context, opts, NULL); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_print ("xmms2-launcher: %s\n", error->message); g_clear_error (&error); } g_option_context_free (context); if (pipe (&pipefd[0]) == -1) { perror ("pipe"); exit (1); } if (!logfile) { char cache[PATH_MAX]; xmms_usercachedir_get (cache, PATH_MAX); logfile = g_build_filename (cache, "xmms2d.log", NULL); if (!g_file_test (cache, G_FILE_TEST_IS_DIR)) { g_mkdir_with_parents (cache, 0755); } } g_print ("Log output will be stored in %s\n", logfile); pid = fork (); if (pid) { char t; int res; close (pipefd[1]); for (;;) { res = read (pipefd[0], &t, 1); if (res != -1 || errno == EINTR) break; } if (res == -1) perror ("read"); if (res == 0) { printf ("startup failed!\n"); exit (1); } printf("xmms2 started\n"); exit(0); } /* Change stdin/out/err */ fd = open ("/dev/null", O_RDONLY); dup2 (fd, STDIN_FILENO); fd = open (logfile, O_WRONLY|O_CREAT|O_APPEND, 0644); write(fd, startup_msg, sizeof (startup_msg) - 1); dup2 (fd, STDOUT_FILENO); dup2 (fd, STDERR_FILENO); /* Close all unused file descriptors */ max_fd = sysconf (_SC_OPEN_MAX); for (i = 3; i <= max_fd; i++) { if (pipefd[1] != i) close (i); } /* make us process group leader */ setsid (); /* fork again to reparent to init */ pid = fork(); if (pid && pidfile) { FILE *pfile = NULL; pfile = g_fopen (pidfile, "w"); if (pfile) { g_fprintf (pfile, "%d", (int) pid); } } if (!pid) { char *args[32]; char buf[32]; int i; args[0] = BINDIR "/xmms2d"; snprintf (buf, 32, "--status-fd=%d", pipefd[1]); args[1] = buf; for (i = 1; i < argc && i < 30; i++) { args[i + 1] = argv[i]; } args[i + 1] = NULL; execvp (args[0], args); exit (1); } exit (0); }