blob: c63f41ff7df6f538721b3b0f1cb50fc8f39e642e [file] [log] [blame]
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +01001/*
2 * Wrapper to make haproxy systemd-compliant.
3 *
4 * Copyright 2013 Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <errno.h>
14#include <signal.h>
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010015#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19#include <sys/wait.h>
20
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010021static char *pid_file = "/run/haproxy.pid";
22static int main_argc;
23static char **main_argv;
24
Kristoffer Grönlund1b6e75f2013-11-22 11:06:34 +010025static void locate_haproxy(char *buffer, size_t buffer_size)
26{
Lukas Tribus439cfde2013-12-10 08:32:56 +010027 char* end = NULL;
28 if (readlink("/proc/self/exe", buffer, buffer_size) > 0)
29 end = strrchr(buffer, '/');
Kristoffer Grönlund1b6e75f2013-11-22 11:06:34 +010030 if (end == NULL)
31 strncpy(buffer, "/usr/sbin/haproxy", buffer_size);
32 end[1] = '\0';
33 strncat(buffer, "haproxy", buffer_size);
34}
35
Marc-Antoine Perennou47f922d2013-04-02 13:53:21 +020036static void spawn_haproxy(char **pid_strv, int nb_pid)
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010037{
Kristoffer Grönlund1b6e75f2013-11-22 11:06:34 +010038 char haproxy_bin[512];
39 pid_t pid;
40
41 pid = fork();
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010042 if (!pid) {
43 /* 3 for "haproxy -Ds -sf" */
44 char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *));
45 int i;
46 int argno = 0;
Kristoffer Grönlund1b6e75f2013-11-22 11:06:34 +010047 locate_haproxy(haproxy_bin, 512);
48 argv[argno++] = haproxy_bin;
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010049 for (i = 0; i < main_argc; ++i)
50 argv[argno++] = main_argv[i];
51 argv[argno++] = "-Ds";
52 if (nb_pid > 0) {
53 argv[argno++] = "-sf";
54 for (i = 0; i < nb_pid; ++i)
55 argv[argno++] = pid_strv[i];
56 }
57 argv[argno] = NULL;
Kristoffer Grönlundf65194a2013-11-22 11:11:54 +010058
59 printf("%s", "haproxy-systemd-wrapper: executing ");
60 for (i = 0; argv[i]; ++i)
61 printf("%s ", argv[i]);
62 puts("");
63
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010064 execv(argv[0], argv);
65 exit(0);
66 }
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010067}
68
69static int read_pids(char ***pid_strv)
70{
71 FILE *f = fopen(pid_file, "r");
72 int read = 0, allocated = 8;
73 char pid_str[10];
74
75 if (!f)
76 return 0;
77
78 *pid_strv = malloc(allocated * sizeof(char *));
79 while (1 == fscanf(f, "%s\n", pid_str)) {
80 if (read == allocated) {
81 allocated *= 2;
82 *pid_strv = realloc(*pid_strv, allocated * sizeof(char *));
83 }
84 (*pid_strv)[read++] = strdup(pid_str);
85 }
86
87 fclose(f);
88
89 return read;
90}
91
Kristoffer Grönlund66fd1d82013-11-22 11:09:39 +010092static void sigusr2_handler(int signum __attribute__((unused)))
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010093{
94 int i;
95 char **pid_strv = NULL;
96 int nb_pid = read_pids(&pid_strv);
97
Marc-Antoine Perennou47f922d2013-04-02 13:53:21 +020098 spawn_haproxy(pid_strv, nb_pid);
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010099
100 for (i = 0; i < nb_pid; ++i)
101 free(pid_strv[i]);
102 free(pid_strv);
103}
104
Kristoffer Grönlund66fd1d82013-11-22 11:09:39 +0100105static void sigint_handler(int signum __attribute__((unused)))
106{
107 int i, pid;
108 char **pid_strv = NULL;
109 int nb_pid = read_pids(&pid_strv);
110 for (i = 0; i < nb_pid; ++i) {
111 pid = atoi(pid_strv[i]);
112 if (pid > 0) {
Kristoffer Grönlundf65194a2013-11-22 11:11:54 +0100113 printf("haproxy-systemd-wrapper: SIGINT -> %d\n", pid);
Kristoffer Grönlund66fd1d82013-11-22 11:09:39 +0100114 kill(pid, SIGINT);
115 free(pid_strv[i]);
116 }
117 }
118 free(pid_strv);
119}
120
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100121static void init(int argc, char **argv)
122{
123 while (argc > 1) {
124 if (**argv == '-') {
125 char *flag = *argv + 1;
126 --argc; ++argv;
127 if (*flag == 'p')
128 pid_file = *argv;
129 }
130 --argc; ++argv;
131 }
132}
133
134int main(int argc, char **argv)
135{
Kristoffer Grönlundf65194a2013-11-22 11:11:54 +0100136 int status;
137
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100138 --argc; ++argv;
Kristoffer Grönlundf65194a2013-11-22 11:11:54 +0100139 main_argc = argc;
140 main_argv = argv;
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100141
142 init(argc, argv);
143
Kristoffer Grönlund66fd1d82013-11-22 11:09:39 +0100144 signal(SIGINT, &sigint_handler);
145 signal(SIGUSR2, &sigusr2_handler);
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100146
Marc-Antoine Perennou47f922d2013-04-02 13:53:21 +0200147 spawn_haproxy(NULL, 0);
Kristoffer Grönlundf65194a2013-11-22 11:11:54 +0100148 status = -1;
149 while (-1 != wait(&status) || errno == EINTR)
150 ;
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100151
Kristoffer Grönlundf65194a2013-11-22 11:11:54 +0100152 printf("haproxy-systemd-wrapper: exit, haproxy RC=%d\n", status);
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100153 return EXIT_SUCCESS;
154}