Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / daemons / cmirrord / clogd.c
blob677506439892943bcfe235c1b67014e811f2f18a
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU General Public License v.2.
10 * You should have received a copy of the GNU General Public License
11 * along with this program; if not, write to the Free Software Foundation,
12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 #include "configure.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdint.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <sched.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <sys/stat.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <linux/types.h>
30 #include <sys/socket.h>
31 #include <linux/netlink.h>
32 #include <linux/dm-ioctl.h>
34 #include "dm-log-userspace.h"
35 #include "functions.h"
36 #include "local.h"
37 #include "cluster.h"
38 #include "common.h"
39 #include "logging.h"
40 #include "link_mon.h"
42 static int exit_now = 0;
43 static sigset_t signal_mask;
44 static int signal_received;
46 static void process_signals(void);
47 static void daemonize(void);
48 static void init_all(void);
49 static void cleanup_all(void);
51 int main(int argc, char *argv[])
53 daemonize();
55 init_all();
57 /* Parent can now exit, we're ready to handle requests */
58 kill(getppid(), SIGTERM);
60 LOG_PRINT("Starting cmirrord:");
61 LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
62 LOG_DBG(" Compiled with debugging.");
64 while (!exit_now) {
65 links_monitor();
67 links_issue_callbacks();
69 process_signals();
71 exit(EXIT_SUCCESS);
75 * parent_exit_handler: exit the parent
76 * @sig: the signal
79 static void parent_exit_handler(int sig)
81 exit_now = 1;
85 * create_lockfile - create and lock a lock file
86 * @lockfile: location of lock file
88 * Returns: 0 on success, -1 otherwise
90 static int create_lockfile(char *lockfile)
92 int fd;
93 struct flock lock;
94 char buffer[50];
96 if((fd = open(lockfile, O_CREAT | O_WRONLY,
97 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0)
98 return -errno;
100 lock.l_type = F_WRLCK;
101 lock.l_start = 0;
102 lock.l_whence = SEEK_SET;
103 lock.l_len = 0;
105 if (fcntl(fd, F_SETLK, &lock) < 0) {
106 close(fd);
107 return -errno;
110 if (ftruncate(fd, 0) < 0) {
111 close(fd);
112 return -errno;
115 sprintf(buffer, "%d\n", getpid());
117 if(write(fd, buffer, strlen(buffer)) < strlen(buffer)){
118 close(fd);
119 unlink(lockfile);
120 return -errno;
123 return 0;
126 static void sig_handler(int sig)
128 sigaddset(&signal_mask, sig);
129 ++signal_received;
132 static void process_signal(int sig){
133 int r = 0;
135 switch(sig) {
136 case SIGINT:
137 case SIGQUIT:
138 case SIGTERM:
139 case SIGHUP:
140 r += log_status();
141 break;
142 case SIGUSR1:
143 case SIGUSR2:
144 log_debug();
145 /*local_debug();*/
146 cluster_debug();
147 return;
148 default:
149 LOG_PRINT("Unknown signal received... ignoring");
150 return;
153 if (!r) {
154 LOG_DBG("No current cluster logs... safe to exit.");
155 cleanup_all();
156 exit(EXIT_SUCCESS);
159 LOG_ERROR("Cluster logs exist. Refusing to exit.");
162 static void process_signals(void)
164 int x;
166 if (!signal_received)
167 return;
169 signal_received = 0;
171 for (x = 1; x < _NSIG; x++) {
172 if (sigismember(&signal_mask, x)) {
173 sigdelset(&signal_mask, x);
174 process_signal(x);
180 * daemonize
182 * Performs the steps necessary to become a daemon.
184 static void daemonize(void)
186 int pid;
187 int status;
189 signal(SIGTERM, &parent_exit_handler);
191 pid = fork();
193 if (pid < 0) {
194 LOG_ERROR("Unable to fork()");
195 exit(EXIT_FAILURE);
198 if (pid) {
199 /* Parent waits here for child to get going */
200 while (!waitpid(pid, &status, WNOHANG) && !exit_now);
201 if (exit_now)
202 exit(EXIT_SUCCESS);
204 switch (WEXITSTATUS(status)) {
205 case EXIT_LOCKFILE:
206 LOG_ERROR("Failed to create lockfile");
207 LOG_ERROR("Process already running?");
208 break;
209 case EXIT_KERNEL_SOCKET:
210 LOG_ERROR("Unable to create netlink socket");
211 break;
212 case EXIT_KERNEL_BIND:
213 LOG_ERROR("Unable to bind to netlink socket");
214 break;
215 case EXIT_KERNEL_SETSOCKOPT:
216 LOG_ERROR("Unable to setsockopt on netlink socket");
217 break;
218 case EXIT_CLUSTER_CKPT_INIT:
219 LOG_ERROR("Unable to initialize checkpoint service");
220 LOG_ERROR("Has the cluster infrastructure been started?");
221 break;
222 case EXIT_FAILURE:
223 LOG_ERROR("Failed to start: Generic error");
224 break;
225 default:
226 LOG_ERROR("Failed to start: Unknown error");
227 break;
229 exit(EXIT_FAILURE);
232 setsid();
233 chdir("/");
234 umask(0);
236 close(0); close(1); close(2);
237 open("/dev/null", O_RDONLY); /* reopen stdin */
238 open("/dev/null", O_WRONLY); /* reopen stdout */
239 open("/dev/null", O_WRONLY); /* reopen stderr */
241 LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
243 if (create_lockfile(CMIRRORD_PIDFILE))
244 exit(EXIT_LOCKFILE);
246 signal(SIGINT, &sig_handler);
247 signal(SIGQUIT, &sig_handler);
248 signal(SIGTERM, &sig_handler);
249 signal(SIGHUP, &sig_handler);
250 signal(SIGPIPE, SIG_IGN);
251 signal(SIGUSR1, &sig_handler);
252 signal(SIGUSR2, &sig_handler);
253 sigemptyset(&signal_mask);
254 signal_received = 0;
258 * init_all
260 * Initialize modules. Exit on failure.
262 static void init_all(void)
264 int r;
266 if ((r = init_local()) ||
267 (r = init_cluster())) {
268 exit(r);
273 * cleanup_all
275 * Clean up before exiting
277 static void cleanup_all(void)
279 cleanup_local();
280 cleanup_cluster();