1 /*\
2  *  Copyright (C) International Business Machines  Corp., 2005
3  *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
4  *
5  *  Xen Console Daemon
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; under version 2 of the License.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; If not, see <http://www.gnu.org/licenses/>.
18 \*/
19 
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <getopt.h>
30 #include <stdbool.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <string.h>
34 #include <signal.h>
35 
36 #include "utils.h"
37 
38 struct xs_handle *xs;
39 xc_interface *xc;
40 
child_exit(int sig)41 static void child_exit(int sig)
42 {
43 	while (waitpid(-1, NULL, WNOHANG) > 0);
44 }
45 
daemonize(const char * pidfile)46 void daemonize(const char *pidfile)
47 {
48 	pid_t pid;
49 	int fd;
50 	int len;
51 	int i;
52 	char buf[100];
53 
54 	if ((pid = fork()) > 0) {
55 		exit(0);
56 	} else if (pid == -1) {
57 		err(errno, "fork() failed");
58 	}
59 
60 	setsid();
61 
62 	if ((pid = fork()) > 0) {
63 		exit(0);
64 	} else if (pid == -1) {
65 		err(errno, "fork() failed");
66 	}
67 
68 	/* redirect fd 0,1,2 to /dev/null */
69 	if ((fd = open("/dev/null",O_RDWR)) == -1) {
70 		exit(1);
71 	}
72 
73 	for (i = 0; i <= 2; i++) {
74 		close(i);
75 		dup2(fd, i);
76 	}
77 
78 	close(fd);
79 
80 	umask(027);
81 	if (chdir("/") < 0)
82 		exit (1);
83 
84 	fd = open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR);
85 	if (fd == -1) {
86 		exit(1);
87 	}
88 
89 	if (lockf(fd, F_TLOCK, 0) == -1) {
90 		exit(1);
91 	}
92 
93 	len = snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
94 	if (write(fd, buf, len) < 0)
95 		exit(1);
96 
97 	signal(SIGCHLD, child_exit);
98 	signal(SIGTSTP, SIG_IGN);
99 	signal(SIGTTOU, SIG_IGN);
100 	signal(SIGTTIN, SIG_IGN);
101 	close(fd);
102 }
103 
xen_setup(void)104 bool xen_setup(void)
105 {
106 
107 	xs = xs_daemon_open();
108 	if (xs == NULL) {
109 		dolog(LOG_ERR,
110 		      "Failed to contact xenstore (%m).  Is it running?");
111 		goto out;
112 	}
113 
114 	xc = xc_interface_open(0,0,0);
115 	if (!xc) {
116 		dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
117 		goto out;
118 	}
119 
120 	if (!xs_watch(xs, "@introduceDomain", "domlist")) {
121 		dolog(LOG_ERR, "xenstore watch on @introduceDomain fails.");
122 		goto out;
123 	}
124 
125 	if (!xs_watch(xs, "@releaseDomain", "domlist")) {
126 		dolog(LOG_ERR, "xenstore watch on @releaseDomain fails.");
127 		goto out;
128 	}
129 
130 	return true;
131 
132  out:
133 	if (xs)
134 		xs_daemon_close(xs);
135 	if (xc)
136 		xc_interface_close(xc);
137 	return false;
138 }
139 
140