systemd-remount-api-vfs
test-hostname
systemd-modules-load
-systemd-auto-serial-getty
+systemd-vconsole-setup
systemd-shutdownd
systemd-random-seed
systemd-update-utmp
systemd-shutdownd \
systemd-modules-load \
systemd-remount-api-vfs \
- systemd-kmsg-syslogd
+ systemd-kmsg-syslogd \
+ systemd-vconsole-setup
noinst_PROGRAMS = \
test-engine \
units/systemd-shutdownd.service \
units/systemd-kmsg-syslogd.service \
units/systemd-modules-load.service \
+ units/systemd-vconsole-setup.service \
units/systemd-remount-api-vfs.service \
units/systemd-update-utmp-runlevel.service \
units/systemd-update-utmp-shutdown.service \
units/systemd-shutdownd.service.in \
units/systemd-kmsg-syslogd.service.in \
units/systemd-modules-load.service.in \
+ units/systemd-vconsole-setup.service.in \
units/systemd-remount-api-vfs.service.in \
units/systemd-update-utmp-runlevel.service.in \
units/systemd-update-utmp-shutdown.service.in \
systemd_modules_load_LDADD = \
libsystemd-basic.la
+systemd_vconsole_setup_SOURCES = \
+ src/vconsole-setup.c
+
+systemd_vconsole_setup_CFLAGS = \
+ $(AM_CFLAGS)
+
+systemd_vconsole_setup_LDADD = \
+ libsystemd-basic.la
+
systemd_remount_api_vfs_SOURCES = \
src/remount-api-vfs.c \
src/mount-setup.c
#include "strv.h"
#include "log.h"
-#define COMMENTS "#;\n"
-
/* Run the user supplied parser for an assignment */
static int next_assignment(
const char *filename,
ExecContext context;
pid_t pid;
int r;
- siginfo_t status;
for (i = 0; i < ELEMENTSOF(kmod_table); i += 2) {
r = exec_spawn(&command, NULL, &context, NULL, 0, NULL, false, false, false, false, NULL, &pid);
exec_context_done(&context);
- if (r < 0)
+ if (r < 0) {
+ log_error("Failed to spawn %s: %s", cmdline[0], strerror(-r));
return r;
-
- if ((r = wait_for_terminate(pid, &status)) < 0)
- return -errno;
-
- if (status.si_code == CLD_EXITED) {
- if (status.si_status != 0) {
- log_warning("/sbin/modprobe failed with error code %i.", status.si_status);
- return -EPROTO;
- }
-
- log_debug("/sbin/modprobe succeeded.");
- return 0;
-
- } else if (status.si_code == CLD_KILLED ||
- status.si_code == CLD_DUMPED) {
-
- log_warning("/sbin/modprobe terminated by signal %s.", signal_to_string(status.si_status));
- return -EPROTO;
}
- log_warning("/sbin/modprobe failed due to unknown reason.");
- return -EPROTO;
+ return wait_for_terminate_and_warn(cmdline[0], pid);
}
#include "unit-name.h"
#include "bus-errors.h"
-#define COMMENTS "#;\n"
-
static int config_parse_deps(
const char *filename,
unsigned line,
if (startswith(p, "LABEL=")) {
- if (!(u = unquote(p+6, '"')))
+ if (!(u = unquote(p+6, "\"\'")))
return NULL;
t = xescape(u, "/ ");
if (startswith(p, "UUID=")) {
- if (!(u = unquote(p+5, '"')))
+ if (!(u = unquote(p+5, "\"\'")))
return NULL;
t = xescape(u, "/ ");
int read_one_line_file(const char *fn, char **line) {
FILE *f;
int r;
- char t[2048], *c;
+ char t[LINE_MAX], *c;
assert(fn);
assert(line);
return r;
}
+int read_full_file(const char *fn, char **contents) {
+ FILE *f;
+ int r;
+ size_t n, l;
+ char *buf = NULL;
+ struct stat st;
+
+ if (!(f = fopen(fn, "re")))
+ return -errno;
+
+ if (fstat(fileno(f), &st) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ n = st.st_size > 0 ? st.st_size : LINE_MAX;
+ l = 0;
+
+ for (;;) {
+ char *t;
+ size_t k;
+
+ if (!(t = realloc(buf, n+1))) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ buf = t;
+ k = fread(buf + l, 1, n - l, f);
+
+ if (k <= 0) {
+ if (ferror(f)) {
+ r = -errno;
+ goto finish;
+ }
+
+ break;
+ }
+
+ l += k;
+ n *= 2;
+
+ /* Safety check */
+ if (n > 4*1024*1024) {
+ r = -E2BIG;
+ goto finish;
+ }
+ }
+
+ if (buf)
+ buf[l] = 0;
+ else if (!(buf = calloc(1, 1))) {
+ r = -errno;
+ goto finish;
+ }
+
+ *contents = buf;
+ buf = NULL;
+
+ r = 0;
+
+finish:
+ fclose(f);
+ free(buf);
+
+ return r;
+}
+
+int parse_env_file(
+ const char *fname,
+ const char *seperator, ...) {
+
+ int r;
+ char *contents, *p;
+
+ assert(fname);
+ assert(seperator);
+
+ if ((r = read_full_file(fname, &contents)) < 0)
+ return r;
+
+ p = contents;
+ for (;;) {
+ const char *key = NULL;
+
+ p += strspn(p, seperator);
+ p += strspn(p, WHITESPACE);
+
+ if (!*p)
+ break;
+
+ if (!strchr(COMMENTS, *p)) {
+ va_list ap;
+ char **value;
+
+ va_start(ap, seperator);
+ while ((key = va_arg(ap, char *))) {
+ size_t n;
+ char *v;
+
+ value = va_arg(ap, char **);
+
+ n = strlen(key);
+ if (strncmp(p, key, n) != 0 ||
+ p[n] != '=')
+ continue;
+
+ p += n + 1;
+ n = strcspn(p, seperator);
+
+ if (n >= 2 &&
+ strchr(QUOTES, v[0]) &&
+ v[n-1] == v[0])
+ v = strndup(p+1, n-2);
+ else
+ v = strndup(p, n);
+
+ if (!v) {
+ r = -ENOMEM;
+ va_end(ap);
+ goto fail;
+ }
+
+ free(*value);
+ *value = v;
+
+ p += n;
+ break;
+ }
+ va_end(ap);
+ }
+
+ if (!key)
+ p += strcspn(p, seperator);
+ }
+
+ r = 0;
+
+fail:
+ free(contents);
+ return r;
+}
+
char *truncate_nl(char *s) {
assert(s);
return 0;
}
-char *unquote(const char *s, const char quote) {
+char *unquote(const char *s, const char* quotes) {
size_t l;
assert(s);
if ((l = strlen(s)) < 2)
return strdup(s);
- if (s[0] == quote && s[l-1] == quote)
+ if (strchr(quotes, s[0]) && s[l-1] == s[0])
return strndup(s+1, l-2);
return strdup(s);
}
}
+int wait_for_terminate_and_warn(const char *name, pid_t pid) {
+ int r;
+ siginfo_t status;
+
+ assert(name);
+ assert(pid > 1);
+
+ if ((r = wait_for_terminate(pid, &status)) < 0) {
+ log_warning("Failed to wait for %s: %s", name, strerror(-r));
+ return r;
+ }
+
+ if (status.si_code == CLD_EXITED) {
+ if (status.si_status != 0) {
+ log_warning("%s failed with error code %i.", name, status.si_status);
+ return -EPROTO;
+ }
+
+ log_debug("%s succeeded.", name);
+ return 0;
+
+ } else if (status.si_code == CLD_KILLED ||
+ status.si_code == CLD_DUMPED) {
+
+ log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
+ return -EPROTO;
+ }
+
+ log_warning("%s failed due to unknown reason.", name);
+ return -EPROTO;
+
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
#define NEWLINE "\n\r"
+#define QUOTES "\"\'"
+#define COMMENTS "#;\n"
#define FORMAT_TIMESTAMP_MAX 64
#define FORMAT_TIMESTAMP_PRETTY_MAX 256
int write_one_line_file(const char *fn, const char *line);
int read_one_line_file(const char *fn, char **line);
+int read_full_file(const char *fn, char **contents);
+
+int parse_env_file(const char *fname, const char *seperator, ...) _sentinel_;
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
int touch(const char *path);
-char *unquote(const char *s, const char quote);
+char *unquote(const char *s, const char *quotes);
int wait_for_terminate(pid_t pid, siginfo_t *status);
+int wait_for_terminate_and_warn(const char *name, pid_t pid);
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
--- /dev/null
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Kay Sievers
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <linux/tiocl.h>
+#include <linux/kd.h>
+
+#include "util.h"
+#include "log.h"
+#include "macro.h"
+
+static bool is_console(int fd) {
+ unsigned char data[1];
+
+ data[0] = TIOCL_GETFGCONSOLE;
+ return ioctl(fd, TIOCLINUX, data) >= 0;
+}
+
+static bool is_locale_utf8(void) {
+ const char *set;
+
+ if (!setlocale(LC_ALL, ""))
+ return true;
+
+ set = nl_langinfo(CODESET);
+ if (!set)
+ return true;
+
+ return streq(set, "UTF-8");
+}
+
+static int disable_utf8(int fd) {
+ int r = 0, k;
+
+ if (ioctl(fd, KDSKBMODE, K_XLATE) < 0)
+ r = -errno;
+
+ if (loop_write(fd, "\033%@", 3, false) < 0)
+ r = -errno;
+
+ if ((k = write_one_line_file("/sys/module/vt/parameters/default_utf8", "0")) < 0)
+ r = k;
+
+ if (r < 0)
+ log_warning("Failed to disable UTF-8: %s", strerror(errno));
+
+ return r;
+}
+
+static int load_keymap(const char *vc, const char *map, bool utf8, pid_t *_pid) {
+ const char *args[7];
+ int i = 0;
+ pid_t pid;
+
+ args[i++] = "/bin/loadkeys";
+ args[i++] = "-q";
+ args[i++] = "-C";
+ args[i++] = vc;
+ if (utf8)
+ args[i++] = "-u";
+ args[i++] = map;
+ args[i++] = NULL;
+
+ if ((pid = fork()) < 0) {
+ log_error("Failed to fork: %m");
+ return -errno;
+ } else if (pid == 0) {
+ execv(args[0], (char **) args);
+ _exit(EXIT_FAILURE);
+ }
+
+ *_pid = pid;
+ return 0;
+}
+
+static int load_font(const char *vc, const char *font, const char *map, const char *unimap, pid_t *_pid) {
+ const char *args[9];
+ int i = 0;
+ pid_t pid;
+
+ args[i++] = "/bin/setfont";
+ args[i++] = "-C";
+ args[i++] = vc;
+ args[i++] = font;
+ if (map) {
+ args[i++] = "-m";
+ args[i++] = map;
+ }
+ if (unimap) {
+ args[i++] = "-u";
+ args[i++] = unimap;
+ }
+ args[i++] = NULL;
+
+ if ((pid = fork()) < 0) {
+ log_error("Failed to fork: %m");
+ return -errno;
+ } else if (pid == 0) {
+ execv(args[0], (char **) args);
+ _exit(EXIT_FAILURE);
+ }
+
+ *_pid = pid;
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const char *vc;
+ char *vc_keymap = NULL;
+ char *vc_font = NULL;
+ char *vc_font_map = NULL;
+ char *vc_font_unimap = NULL;
+ int fd = -1;
+ bool utf8;
+ int r = EXIT_FAILURE;
+ pid_t font_pid = 0, keymap_pid = 0;
+
+ log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
+ log_parse_environment();
+ log_open();
+
+ if (argv[1])
+ vc = argv[1];
+ else
+ vc = "/dev/tty0";
+
+ if ((fd = open(vc, O_RDWR|O_CLOEXEC)) < 0) {
+ log_error("Failed to open %s: %m", vc);
+ goto finish;
+ }
+
+ if (!is_console(fd)) {
+ log_error("Device %s is not a virtual console.", vc);
+ goto finish;
+ }
+
+ if (!(utf8 = is_locale_utf8()))
+ disable_utf8(fd);
+
+ if ((r = parse_env_file(
+ "/etc/vconsole",
+ NEWLINE,
+ "VCONSOLE_KEYMAP", &vc_keymap,
+ "VCONSOLE_FONT", &vc_font,
+ "VCONSOLE_FONT_MAP", &vc_font_map,
+ "VCONSOLE_FONT_UNIMAP", &vc_font_unimap,
+ NULL)) < 0) {
+
+ if (r != -ENOENT)
+ log_warning("Failed to read /etc/vconsole: %s", strerror(-r));
+ }
+
+ if ((r = parse_env_file(
+ "/proc/cmdline",
+ WHITESPACE,
+#ifdef TARGET_FEDORA
+ "SYSFONT", &vc_font,
+ "KEYTABLE", &vc_keymap,
+#endif
+ "vconsole.keymap", &vc_keymap,
+ "vconsole.font", &vc_font,
+ "vconsole.font.map", &vc_font_map,
+ "vconsole.font.unimap", &vc_font_unimap,
+ NULL)) < 0) {
+
+ if (r != -ENOENT)
+ log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
+ }
+
+ if (!vc_keymap)
+ vc_keymap = strdup("us");
+ if (!vc_font)
+ vc_font = strdup("latarcyrheb-sun16");
+
+ if (!vc_keymap || !vc_font) {
+ log_error("Failed to allocate strings.");
+ goto finish;
+ }
+
+ if (load_keymap(vc, vc_keymap, utf8, &keymap_pid) >= 0 &&
+ load_font(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0)
+ r = EXIT_SUCCESS;
+
+finish:
+ if (keymap_pid > 0)
+ wait_for_terminate_and_warn("/bin/loadkeys", keymap_pid);
+
+ if (font_pid > 0)
+ wait_for_terminate_and_warn("/bin/setfont", font_pid);
+
+ free(vc_keymap);
+ free(vc_font);
+ free(vc_font_map);
+ free(vc_font_unimap);
+
+ if (fd >= 0)
+ close_nointr_nofail(fd);
+
+ return r;
+}
systemd-kmsg-syslogd.service
systemd-modules-load.service
systemd-remount-api-vfs.service
+systemd-vconsole-setup.service
systemd-auto-serial-getty.service
systemd-shutdownd.service
systemd-random-seed-load.service
--- /dev/null
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Setup Virtual Console
+DefaultDependencies=no
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@rootlibexecdir@/systemd-vconsole-setup
+
+[Install]
+WantedBy=sysinit.target