migration from private to rsa
[external/bash.git] / debian / clear_console.c
1 /*
2 Copyright (C) 2006-2008 Canonical Ltd.
3
4 clear_console and it's man page are free software; you can redistribute it
5 and/or modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2, or (at your
7 option) any later version.
8 */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <getopt.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #include <sys/ioctl.h>
18 #if defined(__linux)
19 #include <linux/kd.h>
20 #include <linux/vt.h>
21 #elif defined(__FreeBSD_kernel__)
22 #include <sys/consio.h>
23 #include <sys/kbio.h>
24 #endif
25
26 #include <curses.h>
27 #include <term.h>
28
29 #define VERSION "0.1"
30
31 char* progname;
32 int quiet = 0;
33
34 void usage()
35 {
36   fprintf(stderr, "Usage: %s [option]\n", progname);
37   fprintf(stderr, "valid options are:\n");
38   fprintf(stderr, "\t-q  --quiet    don't print error messages\n");
39   fprintf(stderr, "\t-h --help      display this help text and exit\n");
40   fprintf(stderr, "\t-V --version   display version information and exit\n");
41 }
42
43 const struct option opts[] =
44 {
45   /* operations */
46     {"help", no_argument, 0, 'h'},
47     {"version", no_argument, 0, 'V'},
48     {"quiet", no_argument, 0, 'q'},
49     {0, 0, 0, 0}
50 };
51
52 static int putch(int c)
53 {
54         return putchar(c);
55 }
56
57
58 /* taken from console-utils, lib/misc-console-utils.c */
59
60 int is_a_console(int fd)
61 {
62 #if defined(__linux__)
63   char arg;
64 #elif defined(__FreeBSD_kernel__)
65   int arg;
66 #endif
67
68   arg = 0;
69   return (ioctl(fd, KDGKBTYPE, &arg) == 0
70           && ((arg == KB_OTHER) || (arg == KB_101) || (arg == KB_84)));
71 }
72
73 static int open_a_console(char *fnam)
74 {
75   int fd;
76
77   /* try read-only */
78   fd = open(fnam, O_RDWR);
79
80   /* if failed, try read-only */
81   if (fd < 0 && errno == EACCES)
82       fd = open(fnam, O_RDONLY);
83
84   /* if failed, try write-only */
85   if (fd < 0 && errno == EACCES)
86       fd = open(fnam, O_WRONLY);
87
88   /* if failed, fail */
89   if (fd < 0)
90       return -1;
91
92   /* if not a console, fail */
93   if (! is_a_console(fd))
94     {
95       close(fd);
96       return -1;
97     }
98
99   /* success */
100   return fd;
101 }
102
103 /*
104  * Get an fd for use with kbd/console ioctls.
105  * We try several things because opening /dev/console will fail
106  * if someone else used X (which does a chown on /dev/console).
107  *
108  * if tty_name is non-NULL, try this one instead.
109  */
110
111 int get_console_fd(char* tty_name)
112 {
113   int fd;
114
115   if (tty_name)
116     {
117       if (-1 == (fd = open_a_console(tty_name)))
118         return -1;
119       else
120         return fd;
121     }
122
123   fd = open_a_console("/dev/tty");
124   if (fd >= 0)
125     return fd;
126
127   fd = open_a_console("/dev/tty0");
128   if (fd >= 0)
129     return fd;
130
131   fd = open_a_console("/dev/console");
132   if (fd >= 0)
133     return fd;
134
135   for (fd = 0; fd < 3; fd++)
136     if (is_a_console(fd))
137       return fd;
138
139 #if 0
140   fprintf(stderr,
141           _("Couldnt get a file descriptor referring to the console\n"));
142 #endif
143   return -1;            /* total failure */
144 }
145
146
147 int is_pseudo_tty(int fd)
148 {
149   char *tty = ttyname(fd);
150
151   if (!tty)
152     {
153       if (!quiet)
154         perror("ttyname");
155       return 0;
156     }
157
158   if (strlen(tty) >= 9 && !strncmp(tty, "/dev/pts/", 9))
159     return 1;
160
161   if (strlen(tty) >= 8 && !strncmp(tty, "/dev/tty", 8)
162       && tty[8] >= 'a' && tty[8] <= 'z')
163     return 1;
164
165   return 0;
166 }
167
168 int clear_console(int fd)
169 {
170   int num, tmp_num;
171 #if defined(__linux__)
172   struct vt_stat vtstat;
173 #endif
174
175   /* clear screen */
176   setupterm((char *) 0, 1, (int *) 0);
177   if (tputs(clear_screen, lines > 0 ? lines : 1, putch) == ERR)
178     {
179       exit(1);
180     }
181
182   if (is_pseudo_tty(STDIN_FILENO))
183     return 0;
184
185   if (!strcmp(getenv("TERM"), "screen"))
186       return 0;
187
188   /* get current vt */
189 #if defined(__linux__)
190   if (ioctl(fd, VT_GETSTATE, &vtstat) < 0)
191 #elif defined(__FreeBSD_kernel__)
192   if (ioctl(fd, VT_ACTIVATE, &num) < 0)
193 #endif
194     {
195       if (!quiet)
196         fprintf(stderr, "%s: cannot get VTstate\n", progname);
197       exit(1);
198     }
199 #if defined(__linux__)
200   num = vtstat.v_active;
201 #endif
202   tmp_num = (num == 1 ? 2 : 1);
203
204   /* switch vt to clear the scrollback buffer */
205   if (ioctl(fd, VT_ACTIVATE, tmp_num))
206     {
207       if (!quiet)
208         perror("chvt: VT_ACTIVATE");
209       exit(1);
210     }
211
212   if (ioctl(fd, VT_WAITACTIVE, tmp_num))
213     {
214       if (!quiet)
215         perror("VT_WAITACTIVE");
216       exit(1);
217     }
218
219   /* switch back */
220   if (ioctl(fd, VT_ACTIVATE, num))
221     {
222       if (!quiet)
223         perror("chvt: VT_ACTIVATE");
224       exit(1);
225     }
226
227   if (ioctl(fd, VT_WAITACTIVE, num))
228     {
229       if (!quiet)
230         perror("VT_WAITACTIVE");
231       exit(1);
232     }
233   return 0;
234 }
235
236 int main (int argc, char* argv[])
237 {
238   int fd;
239   int result;                          /* option handling */
240   int an_option;
241
242   if ((progname = strrchr(argv[0], '/')) == NULL)
243     progname = argv[0];
244   else
245     progname++;
246
247   while (1)
248     {
249       result = getopt_long(argc, argv, "Vhq", opts, &an_option);
250       
251       if (result == EOF)
252         break;
253
254       switch (result)
255         {
256         case 'V':
257           fprintf(stdout, "%s: Version %s\n", progname, VERSION);
258           exit (0);
259         case 'h':
260           usage();
261           exit (0);
262           
263         case 'q':
264           quiet = 1;
265         }
266     }
267
268   if (optind < argc)
269     {
270       if (!quiet)
271         fprintf(stderr, "%s: no non-option arguments are valid", progname);
272       exit(1);
273     }
274
275   if ((fd = get_console_fd(NULL)) == -1)
276     {
277       if (!quiet)
278         fprintf(stderr, "%s: terminal is not a console\n", progname);
279       exit(1);
280     }
281
282   clear_console(fd);
283
284   return 0;
285 }