blob: e3fe26075ea2cb73f63ad42de2a21a8a35118552 [file] [log] [blame]
Scott James Remnant8092e792008-04-29 23:36:16 +01001/* upstart
2 *
3 * system.c - core system functions
4 *
Scott James Remnantd69c1da2010-02-26 15:29:07 +00005 * Copyright © 2010 Canonical Ltd.
Scott James Remnant7d5b2ea2009-05-22 15:20:12 +02006 * Author: Scott James Remnant <scott@netsplit.com>.
Scott James Remnant8092e792008-04-29 23:36:16 +01007 *
Scott James Remnant0c0c5a52009-06-23 10:29:35 +01008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2, as
Scott James Remnant75123022009-05-22 13:27:56 +020010 * published by the Free Software Foundation.
Scott James Remnant8092e792008-04-29 23:36:16 +010011 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
Scott James Remnant0c0c5a52009-06-23 10:29:35 +010017 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Scott James Remnant8092e792008-04-29 23:36:16 +010020 */
Scott James Remnant8092e792008-04-29 23:36:16 +010021
22#ifdef HAVE_CONFIG_H
23# include <config.h>
24#endif /* HAVE_CONFIG_H */
25
26#include <sys/types.h>
27#include <sys/ioctl.h>
28#include <sys/stat.h>
Scott James Remnantd69c1da2010-02-26 15:29:07 +000029#include <sys/mount.h>
Scott James Remnant8092e792008-04-29 23:36:16 +010030
31#include <fcntl.h>
32#include <signal.h>
Scott James Remnantd69c1da2010-02-26 15:29:07 +000033#include <string.h>
Scott James Remnant8092e792008-04-29 23:36:16 +010034#include <unistd.h>
35#include <termios.h>
36
37#include <nih/macros.h>
Scott James Remnantd69c1da2010-02-26 15:29:07 +000038#include <nih/alloc.h>
39#include <nih/string.h>
Scott James Remnant8092e792008-04-29 23:36:16 +010040#include <nih/error.h>
41#include <nih/logging.h>
42
43#include "paths.h"
44#include "system.h"
45#include "job_class.h"
46
47
48/**
49 * system_kill:
50 * @pid: process id of process,
51 * @force: force the death.
52 *
53 * Kill all processes in the same process group as @pid, which may not
54 * necessarily be the group leader.
55 *
56 * When @force is FALSE, the TERM signal is sent; when it is TRUE, KILL
57 * is sent instead.
58 *
59 * Returns: zero on success, negative value on raised error.
60 **/
61int
62system_kill (pid_t pid,
63 int force)
64{
65 int signal;
66 pid_t pgid;
67
68 nih_assert (pid > 0);
69
70 signal = (force ? SIGKILL : SIGTERM);
71
72 pgid = getpgid (pid);
73
74 if (kill (pgid > 0 ? -pgid : pid, signal) < 0)
75 nih_return_system_error (-1);
76
77 return 0;
78}
79
80
81/**
82 * system_setup_console:
83 * @type: console type,
84 * @reset: reset console to sane defaults.
85 *
86 * Set up the standard input, output and error file descriptors for the
87 * current process based on the console @type given. If @reset is TRUE then
88 * the console device will be reset to sane defaults.
89 *
90 * Returns: zero on success, negative value on raised error.
91 **/
92int
93system_setup_console (ConsoleType type,
94 int reset)
95{
96 int fd = -1, i;
97
98 /* Close the standard file descriptors since we're about to re-open
99 * them; it may be that some of these aren't already open, we get
100 * called in some very strange ways.
101 */
102 for (i = 0; i < 3; i++)
103 close (i);
104
105 /* Open the new first file descriptor, which should always become
106 * file zero.
107 */
108 switch (type) {
109 case CONSOLE_OUTPUT:
110 case CONSOLE_OWNER:
111 /* Ordinary console input and output */
112 fd = open (CONSOLE, O_RDWR | O_NOCTTY);
113 if (fd < 0)
114 nih_return_system_error (-1);
115
116 if (type == CONSOLE_OWNER)
117 ioctl (fd, TIOCSCTTY, 1);
118 break;
119 case CONSOLE_NONE:
120 /* No console really means /dev/null */
121 fd = open (DEV_NULL, O_RDWR | O_NOCTTY);
122 if (fd < 0)
123 nih_return_system_error (-1);
124 break;
125 }
126
127 /* Reset to sane defaults, cribbed from sysvinit, initng, etc. */
128 if (reset) {
129 struct termios tty;
130
131 tcgetattr (0, &tty);
132
133 tty.c_cflag &= (CBAUD | CBAUDEX | CSIZE | CSTOPB
134 | PARENB | PARODD);
135 tty.c_cflag |= (HUPCL | CLOCAL | CREAD);
136
137 /* Set up usual keys */
138 tty.c_cc[VINTR] = 3; /* ^C */
139 tty.c_cc[VQUIT] = 28; /* ^\ */
140 tty.c_cc[VERASE] = 127;
141 tty.c_cc[VKILL] = 24; /* ^X */
142 tty.c_cc[VEOF] = 4; /* ^D */
143 tty.c_cc[VTIME] = 0;
144 tty.c_cc[VMIN] = 1;
145 tty.c_cc[VSTART] = 17; /* ^Q */
146 tty.c_cc[VSTOP] = 19; /* ^S */
147 tty.c_cc[VSUSP] = 26; /* ^Z */
148
149 /* Pre and post processing */
150 tty.c_iflag = (IGNPAR | ICRNL | IXON | IXANY);
151 tty.c_oflag = (OPOST | ONLCR);
152 tty.c_lflag = (ISIG | ICANON | ECHO | ECHOCTL
153 | ECHOPRT | ECHOKE);
154
155 /* Set the terminal line and flush it */
156 tcsetattr (0, TCSANOW, &tty);
157 tcflush (0, TCIOFLUSH);
158 }
159
160 /* Copy to standard output and standard error */
161 while (dup (fd) < 2)
162 ;
163
164 return 0;
165}
Scott James Remnantd69c1da2010-02-26 15:29:07 +0000166
167
168/**
169 * system_mount:
170 * @type: filesystem type,
171 * @dir: mountpoint.
172 *
173 * Mount the kernel filesystem @type at @dir, if not already mounted. This
174 * is used to ensure that the proc and sysfs filesystems are always
175 * available.
176 *
177 * Filesystems are always mounted with the MS_NODEV, MS_NOEXEC and MS_NOSUID
178 * mount options, which are sensible for /proc and /sys.
179 *
180 * Returns: zero on success, negative value on raised error.
181 **/
182int
183system_mount (const char *type,
184 const char *dir)
185{
186 nih_local char *parent = NULL;
187 char * ptr;
188 struct stat parent_stat;
189 struct stat dir_stat;
190
191 nih_assert (type != NULL);
192 nih_assert (dir != NULL);
193
194 /* Stat the parent directory of the mountpoint to obtain the dev_t */
195 ptr = strrchr (dir, '/');
196 nih_assert (ptr != NULL);
197
198 parent = NIH_MUST (nih_strndup (NULL, dir, ptr == dir ? 1 : ptr - dir));
199 if (stat (parent, &parent_stat) < 0)
200 nih_return_system_error (-1);
201
202 /* Also stat the mountpoint to obtain the dev_t */
203 if (stat (dir, &dir_stat) < 0)
204 nih_return_system_error (-1);
205
206 /* If the two dev_ts do not match, then there is already a filesystem
207 * mounted and we needn't do anything.
208 */
209 if (parent_stat.st_dev != dir_stat.st_dev)
210 return 0;
211
212 /* Mount the filesystem */
213 if (mount ("none", dir, type,
214 MS_NODEV | MS_NOEXEC | MS_NOSUID, NULL) < 0)
215 nih_return_system_error (-1);
216
217 return 0;
218}