#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netdb.h>
#include <pthread.h>
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
-
+
dirlen = strlen (dir);
while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
dir[--dirlen] = '\0';
- if (dirlen <= 0)
+ if (dirlen <= 0) {
+ free (dir);
return (-1);
+ }
status = chdir (dir);
if (status == 0)
*/
static void exit_usage (int status)
{
- printf ("Usage: "PACKAGE" [OPTIONS]\n\n"
-
+ printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n"
+
"Available options:\n"
" General:\n"
" -C <file> Configuration file.\n"
" PID file "PIDFILE"\n"
" Plugin directory "PLUGINDIR"\n"
" Data directory "PKGLOCALSTATEDIR"\n"
- "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+ "\n"PACKAGE_NAME" "PACKAGE_VERSION", http://collectd.org/\n"
"by Florian octo Forster <octo@collectd.org>\n"
"for contributions see `AUTHORS'\n");
exit (status);
#if HAVE_LIBSTATGRAB
if (sg_init (
-# if HAVE_LIBSTATGRAB_INIT_ARG
+# if HAVE_LIBSTATGRAB_0_90
0
# endif
))
static int pidfile_remove (void)
{
const char *file = global_option_get ("PIDFile");
+ if (file == NULL)
+ return 0;
- DEBUG ("unlink (%s)", (file != NULL) ? file : "<null>");
return (unlink (file));
} /* static int pidfile_remove (const char *file) */
#endif /* COLLECT_DAEMON */
+#ifdef KERNEL_LINUX
+int notify_upstart (void)
+{
+ const char *upstart_job = getenv("UPSTART_JOB");
+
+ if (upstart_job == NULL)
+ return 0;
+
+ if (strcmp(upstart_job, "collectd") != 0)
+ return 0;
+
+ WARNING ("supervised by upstart, will stop to signal readyness");
+ raise(SIGSTOP);
+ unsetenv("UPSTART_JOB");
+
+ return 1;
+}
+
+int notify_systemd (void)
+{
+ int fd = -1;
+ const char *notifysocket = getenv("NOTIFY_SOCKET");
+ struct sockaddr_un su;
+ struct iovec iov;
+ struct msghdr hdr;
+
+ if (notifysocket == NULL)
+ return 0;
+
+ if ((strchr("@/", notifysocket[0])) == NULL ||
+ strlen(notifysocket) < 2)
+ return 0;
+
+ WARNING ("supervised by systemd, will signal readyness");
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ WARNING ("cannot contact systemd socket %s", notifysocket);
+ return 0;
+ }
+
+ bzero(&su, sizeof(su));
+ su.sun_family = AF_UNIX;
+ sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
+
+ if (notifysocket[0] == '@')
+ su.sun_path[0] = 0;
+
+ bzero(&iov, sizeof(iov));
+ iov.iov_base = "READY=1";
+ iov.iov_len = strlen("READY=1");
+
+ bzero(&hdr, sizeof(hdr));
+ hdr.msg_name = &su;
+ hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
+ strlen(notifysocket);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+ unsetenv("NOTIFY_SOCKET");
+ if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
+ WARNING ("cannot send notification to systemd");
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ return 1;
+}
+#endif /* KERNEL_LINUX */
+
int main (int argc, char **argv)
{
struct sigaction sig_int_action;
sig_chld_action.sa_handler = SIG_IGN;
sigaction (SIGCHLD, &sig_chld_action, NULL);
- if (daemonize)
+ /*
+ * Only daemonize if we're not being supervised
+ * by upstart or systemd (when using Linux).
+ */
+ if (daemonize
+#ifdef KERNEL_LINUX
+ && notify_upstart() == 0 && notify_systemd() == 0
+#endif
+ )
{
if ((pid = fork ()) == -1)
{