1987da915Sopenharmony_ci/*
2987da915Sopenharmony_ci    FUSE: Filesystem in Userspace
3987da915Sopenharmony_ci    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4987da915Sopenharmony_ci
5987da915Sopenharmony_ci    This program can be distributed under the terms of the GNU LGPLv2.
6987da915Sopenharmony_ci    See the file COPYING.LIB
7987da915Sopenharmony_ci*/
8987da915Sopenharmony_ci
9987da915Sopenharmony_ci#include "config.h"
10987da915Sopenharmony_ci#include "fuse_lowlevel.h"
11987da915Sopenharmony_ci
12987da915Sopenharmony_ci#include <stdio.h>
13987da915Sopenharmony_ci#include <string.h>
14987da915Sopenharmony_ci#include <signal.h>
15987da915Sopenharmony_ci
16987da915Sopenharmony_cistatic struct fuse_session *fuse_instance;
17987da915Sopenharmony_ci
18987da915Sopenharmony_cistatic void exit_handler(int sig)
19987da915Sopenharmony_ci{
20987da915Sopenharmony_ci    (void) sig;
21987da915Sopenharmony_ci    if (fuse_instance)
22987da915Sopenharmony_ci        fuse_session_exit(fuse_instance);
23987da915Sopenharmony_ci}
24987da915Sopenharmony_ci
25987da915Sopenharmony_cistatic int set_one_signal_handler(int sig, void (*handler)(int), int remove)
26987da915Sopenharmony_ci{
27987da915Sopenharmony_ci    struct sigaction sa;
28987da915Sopenharmony_ci    struct sigaction old_sa;
29987da915Sopenharmony_ci
30987da915Sopenharmony_ci    memset(&sa, 0, sizeof(struct sigaction));
31987da915Sopenharmony_ci    sa.sa_handler = remove ? SIG_DFL : handler;
32987da915Sopenharmony_ci    sigemptyset(&(sa.sa_mask));
33987da915Sopenharmony_ci    sa.sa_flags = 0;
34987da915Sopenharmony_ci
35987da915Sopenharmony_ci    if (sigaction(sig, NULL, &old_sa) == -1) {
36987da915Sopenharmony_ci        perror("fuse: cannot get old signal handler");
37987da915Sopenharmony_ci        return -1;
38987da915Sopenharmony_ci    }
39987da915Sopenharmony_ci
40987da915Sopenharmony_ci    if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
41987da915Sopenharmony_ci        sigaction(sig, &sa, NULL) == -1) {
42987da915Sopenharmony_ci        perror("fuse: cannot set signal handler");
43987da915Sopenharmony_ci        return -1;
44987da915Sopenharmony_ci    }
45987da915Sopenharmony_ci    return 0;
46987da915Sopenharmony_ci}
47987da915Sopenharmony_ci
48987da915Sopenharmony_ciint fuse_set_signal_handlers(struct fuse_session *se)
49987da915Sopenharmony_ci{
50987da915Sopenharmony_ci    if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
51987da915Sopenharmony_ci        set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
52987da915Sopenharmony_ci        set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
53987da915Sopenharmony_ci        set_one_signal_handler(SIGPIPE, SIG_IGN, 0) == -1)
54987da915Sopenharmony_ci        return -1;
55987da915Sopenharmony_ci
56987da915Sopenharmony_ci    fuse_instance = se;
57987da915Sopenharmony_ci    return 0;
58987da915Sopenharmony_ci}
59987da915Sopenharmony_ci
60987da915Sopenharmony_civoid fuse_remove_signal_handlers(struct fuse_session *se)
61987da915Sopenharmony_ci{
62987da915Sopenharmony_ci    if (fuse_instance != se)
63987da915Sopenharmony_ci        fprintf(stderr,
64987da915Sopenharmony_ci                "fuse: fuse_remove_signal_handlers: unknown session\n");
65987da915Sopenharmony_ci    else
66987da915Sopenharmony_ci        fuse_instance = NULL;
67987da915Sopenharmony_ci
68987da915Sopenharmony_ci    set_one_signal_handler(SIGHUP, exit_handler, 1);
69987da915Sopenharmony_ci    set_one_signal_handler(SIGINT, exit_handler, 1);
70987da915Sopenharmony_ci    set_one_signal_handler(SIGTERM, exit_handler, 1);
71987da915Sopenharmony_ci    set_one_signal_handler(SIGPIPE, SIG_IGN, 1);
72987da915Sopenharmony_ci}
73987da915Sopenharmony_ci
74