blob: 6546616b79ee711386bf5a731d6eb9b2fdf24dad [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{
27 char* end;
28 readlink("/proc/self/exe", buffer, buffer_size);
29 end = strrchr(buffer, '/');
30 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;
58 execv(argv[0], argv);
59 exit(0);
60 }
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010061}
62
63static int read_pids(char ***pid_strv)
64{
65 FILE *f = fopen(pid_file, "r");
66 int read = 0, allocated = 8;
67 char pid_str[10];
68
69 if (!f)
70 return 0;
71
72 *pid_strv = malloc(allocated * sizeof(char *));
73 while (1 == fscanf(f, "%s\n", pid_str)) {
74 if (read == allocated) {
75 allocated *= 2;
76 *pid_strv = realloc(*pid_strv, allocated * sizeof(char *));
77 }
78 (*pid_strv)[read++] = strdup(pid_str);
79 }
80
81 fclose(f);
82
83 return read;
84}
85
86static void signal_handler(int signum __attribute__((unused)))
87{
88 int i;
89 char **pid_strv = NULL;
90 int nb_pid = read_pids(&pid_strv);
91
Marc-Antoine Perennou47f922d2013-04-02 13:53:21 +020092 spawn_haproxy(pid_strv, nb_pid);
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +010093
94 for (i = 0; i < nb_pid; ++i)
95 free(pid_strv[i]);
96 free(pid_strv);
97}
98
99static void init(int argc, char **argv)
100{
101 while (argc > 1) {
102 if (**argv == '-') {
103 char *flag = *argv + 1;
104 --argc; ++argv;
105 if (*flag == 'p')
106 pid_file = *argv;
107 }
108 --argc; ++argv;
109 }
110}
111
112int main(int argc, char **argv)
113{
114 --argc; ++argv;
115 main_argc = argc;
116 main_argv = argv;
117
118 init(argc, argv);
119
120 signal(SIGUSR2, &signal_handler);
121
Marc-Antoine Perennou47f922d2013-04-02 13:53:21 +0200122 spawn_haproxy(NULL, 0);
123 while (-1 != wait(NULL) || errno == EINTR);
Marc-Antoine Perennoued9803e2013-02-12 10:53:53 +0100124
125 return EXIT_SUCCESS;
126}