--- /dev/null
+#include <stdio.h>
+#include <errno.h>
+#include <error.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/kd.h>
+#include <getopt.h>
+#include "getfd.h"
+#include "nls.h"
+#include "version.h"
+
+static const char *action = NULL;
+static const char *value = NULL;
+
+static void attr_noreturn
+usage(int code) {
+ fprintf(stderr, _("Usage: %s [-C DEVICE] getmode [text|graphics]\n"), progname);
+ fprintf(stderr, _(" or: %s [-C DEVICE] gkbmode [raw|xlate|mediumraw|unicode]\n"), progname);
+ fprintf(stderr, _(" or: %s [-C DEVICE] gkbmeta [metabit|escprefix]\n"), progname);
+ fprintf(stderr, _(" or: %s [-C DEVICE] gkbled [scrolllock|numlock|capslock]\n"), progname);
+ exit(code);
+}
+
+static int
+answer(const char *ans) {
+ if (value)
+ return strcasecmp(value, ans) ? EXIT_FAILURE : EXIT_SUCCESS;
+
+ printf("%s\n", ans);
+ return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char **argv) {
+ int fd, mode, c;
+ int rc = EXIT_FAILURE;
+ char flags;
+ const char *console = NULL;
+
+ set_progname(argv[0]);
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE_NAME, LOCALEDIR);
+ textdomain(PACKAGE_NAME);
+
+ while ((c = getopt(argc, argv, "C:hV")) != EOF) {
+ switch (c) {
+ case 'C':
+ if (optarg == NULL || optarg[0] == '\0')
+ usage(EXIT_FAILURE);
+ console = optarg;
+ break;
+ case 'V':
+ print_version_and_exit();
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, _("Error: Not enough arguments.\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ action = argv[optind++];
+
+ if (optind < argc)
+ value = argv[optind++];
+
+ fd = getfd(console);
+
+ if (!strcasecmp("GETMODE", action)) {
+ if (ioctl(fd, KDGETMODE, &mode) == -1)
+ error(EXIT_FAILURE, errno, "ioctl");
+
+ switch (mode) {
+ case KD_TEXT: rc = answer("text"); break;
+ case KD_GRAPHICS: rc = answer("graphics"); break;
+ }
+
+ } else if (!strcasecmp("GKBMODE", action)) {
+ if (ioctl(fd, KDGKBMODE, &mode) == -1)
+ error(EXIT_FAILURE, errno, "ioctl");
+
+ switch (mode) {
+ case K_RAW: rc = answer("raw"); break;
+ case K_XLATE: rc = answer("xlate"); break;
+ case K_MEDIUMRAW: rc = answer("mediumraw"); break;
+ case K_UNICODE: rc = answer("unicode"); break;
+ }
+
+ } else if (!strcasecmp("GKBMETA", action)) {
+ if (ioctl(fd, KDGKBMETA, &mode) == -1)
+ error(EXIT_FAILURE, errno, "ioctl");
+
+ switch (mode) {
+ case K_METABIT: rc = answer("metabit"); break;
+ case K_ESCPREFIX: rc = answer("escprefix"); break;
+ }
+
+ } else if (!strcasecmp("GKBLED", action)) {
+ if (ioctl(fd, KDGKBLED, &flags) == -1)
+ error(EXIT_FAILURE, errno, "ioctl");
+
+ mode = (flags & 0x7);
+
+ if (value) {
+ if (((mode & LED_SCR) && !strcasecmp(value, "scrolllock")) ||
+ ((mode & LED_NUM) && !strcasecmp(value, "numlock")) ||
+ ((mode & LED_CAP) && !strcasecmp(value, "capslock")))
+ rc = EXIT_SUCCESS;
+ } else {
+ printf("scrolllock:%s ", (mode & LED_SCR) ? "on" : "off");
+ printf("numlock:%s ", (mode & LED_NUM) ? "on" : "off");
+ printf("capslock:%s\n", (mode & LED_CAP) ? "on" : "off");
+ rc = EXIT_SUCCESS;
+ }
+
+ } else {
+ fprintf(stderr, _("Error: Unrecognized action: %s\n"), action);
+ }
+
+ close(fd);
+ return rc;
+}