summaryrefslogtreecommitdiffstats
path: root/debian/clear_console.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/clear_console.c')
-rw-r--r--debian/clear_console.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/debian/clear_console.c b/debian/clear_console.c
new file mode 100644
index 0000000..4cd3f26
--- /dev/null
+++ b/debian/clear_console.c
@@ -0,0 +1,291 @@
+/*
+Copyright (C) 2006-2019 Canonical Ltd.
+
+clear_console and it's man page are 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, or (at your
+option) any later version.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#if defined(__linux)
+#include <linux/kd.h>
+#include <linux/vt.h>
+#elif defined(__FreeBSD_kernel__)
+#include <sys/consio.h>
+#include <sys/kbio.h>
+#endif
+
+#include <curses.h>
+#include <term.h>
+
+#define VERSION "0.1"
+
+char* progname;
+int quiet = 0;
+
+void usage()
+{
+ fprintf(stderr, "Usage: %s [option]\n", progname);
+ fprintf(stderr, "valid options are:\n");
+ fprintf(stderr, "\t-q --quiet don't print error messages\n");
+ fprintf(stderr, "\t-h --help display this help text and exit\n");
+ fprintf(stderr, "\t-V --version display version information and exit\n");
+}
+
+const struct option opts[] =
+{
+ /* operations */
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"quiet", no_argument, 0, 'q'},
+ {0, 0, 0, 0}
+};
+
+static int putch(int c)
+{
+ return putchar(c);
+}
+
+
+/* taken from console-utils, lib/misc-console-utils.c */
+
+int is_a_console(int fd)
+{
+#if defined(__linux__)
+ char arg;
+#elif defined(__FreeBSD_kernel__)
+ int arg;
+#endif
+
+ arg = 0;
+ return (ioctl(fd, KDGKBTYPE, &arg) == 0
+ && ((arg == KB_OTHER) || (arg == KB_101) || (arg == KB_84)));
+}
+
+static int open_a_console(char *fnam)
+{
+ int fd;
+
+ /* try read-only */
+ fd = open(fnam, O_RDWR);
+
+ /* if failed, try read-only */
+ if (fd < 0 && errno == EACCES)
+ fd = open(fnam, O_RDONLY);
+
+ /* if failed, try write-only */
+ if (fd < 0 && errno == EACCES)
+ fd = open(fnam, O_WRONLY);
+
+ /* if failed, fail */
+ if (fd < 0)
+ return -1;
+
+ /* if not a console, fail */
+ if (! is_a_console(fd))
+ {
+ close(fd);
+ return -1;
+ }
+
+ /* success */
+ return fd;
+}
+
+/*
+ * Get an fd for use with kbd/console ioctls.
+ * We try several things because opening /dev/console will fail
+ * if someone else used X (which does a chown on /dev/console).
+ *
+ * if tty_name is non-NULL, try this one instead.
+ */
+
+int get_console_fd(char* tty_name)
+{
+ int fd;
+
+ if (tty_name)
+ {
+ if (-1 == (fd = open_a_console(tty_name)))
+ return -1;
+ else
+ return fd;
+ }
+
+ fd = open_a_console("/dev/tty");
+ if (fd >= 0)
+ return fd;
+
+ fd = open_a_console("/dev/tty0");
+ if (fd >= 0)
+ return fd;
+
+ fd = open_a_console("/dev/console");
+ if (fd >= 0)
+ return fd;
+
+ for (fd = 0; fd < 3; fd++)
+ if (is_a_console(fd))
+ return fd;
+
+#if 0
+ fprintf(stderr,
+ _("Couldnt get a file descriptor referring to the console\n"));
+#endif
+ return -1; /* total failure */
+}
+
+
+int is_pseudo_tty(int fd)
+{
+ char *tty = ttyname(fd);
+
+ if (!tty)
+ {
+ if (!quiet)
+ perror("ttyname");
+ return 0;
+ }
+
+ if (strlen(tty) >= 9 && !strncmp(tty, "/dev/pts/", 9))
+ return 1;
+
+ if (strlen(tty) >= 8 && !strncmp(tty, "/dev/tty", 8)
+ && tty[8] >= 'a' && tty[8] <= 'z')
+ return 1;
+
+ return 0;
+}
+
+int clear_console(int fd)
+{
+ int num, tmp_num;
+#if defined(__linux__)
+ struct vt_stat vtstat;
+#endif
+
+ /* Linux console secure erase (since 2.6.39), this is sufficient there;
+ other terminals silently ignore this code. If they don't and write junk
+ instead, well, we're clearing the screen anyway.
+ */
+ write(1, "\e[3J", 4);
+
+ /* clear screen */
+ setupterm((char *) 0, 1, (int *) 0);
+ if (tputs(clear_screen, lines > 0 ? lines : 1, putch) == ERR)
+ {
+ exit(1);
+ }
+
+ if (is_pseudo_tty(STDIN_FILENO))
+ return 0;
+
+ if (!strcmp(getenv("TERM"), "screen"))
+ return 0;
+
+ /* get current vt */
+#if defined(__linux__)
+ if (ioctl(fd, VT_GETSTATE, &vtstat) < 0)
+#elif defined(__FreeBSD_kernel__)
+ if (ioctl(fd, VT_ACTIVATE, &num) < 0)
+#endif
+ {
+ if (!quiet)
+ fprintf(stderr, "%s: cannot get VTstate\n", progname);
+ exit(1);
+ }
+#if defined(__linux__)
+ num = vtstat.v_active;
+#endif
+ tmp_num = (num == 6 ? 5 : 6);
+
+ /* switch vt to clear the scrollback buffer */
+ if (ioctl(fd, VT_ACTIVATE, tmp_num))
+ {
+ if (!quiet)
+ perror("chvt: VT_ACTIVATE");
+ exit(1);
+ }
+
+ if (ioctl(fd, VT_WAITACTIVE, tmp_num))
+ {
+ if (!quiet)
+ perror("VT_WAITACTIVE");
+ exit(1);
+ }
+
+ /* switch back */
+ if (ioctl(fd, VT_ACTIVATE, num))
+ {
+ if (!quiet)
+ perror("chvt: VT_ACTIVATE");
+ exit(1);
+ }
+
+ if (ioctl(fd, VT_WAITACTIVE, num))
+ {
+ if (!quiet)
+ perror("VT_WAITACTIVE");
+ exit(1);
+ }
+ return 0;
+}
+
+int main (int argc, char* argv[])
+{
+ int fd;
+ int result; /* option handling */
+ int an_option;
+
+ if ((progname = strrchr(argv[0], '/')) == NULL)
+ progname = argv[0];
+ else
+ progname++;
+
+ while (1)
+ {
+ result = getopt_long(argc, argv, "Vhq", opts, &an_option);
+
+ if (result == EOF)
+ break;
+
+ switch (result)
+ {
+ case 'V':
+ fprintf(stdout, "%s: Version %s\n", progname, VERSION);
+ exit (0);
+ case 'h':
+ usage();
+ exit (0);
+
+ case 'q':
+ quiet = 1;
+ }
+ }
+
+ if (optind < argc)
+ {
+ if (!quiet)
+ fprintf(stderr, "%s: no non-option arguments are valid", progname);
+ exit(1);
+ }
+
+ if ((fd = get_console_fd(NULL)) == -1)
+ {
+ if (!quiet)
+ fprintf(stderr, "%s: terminal is not a console\n", progname);
+ exit(1);
+ }
+
+ clear_console(fd);
+
+ return 0;
+}