Add pancyrillic font
[platform/upstream/kbd.git] / src / showkey.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <getopt.h>
4 #include <fcntl.h>
5 #include <signal.h>
6 #include <termios.h>
7 #include <sys/ioctl.h>
8 #include <linux/kd.h>
9 #include <linux/keyboard.h>
10 #include "getfd.h"
11 #include "nls.h"
12 #include "version.h"
13
14 int tmp;        /* for debugging */
15
16 int fd;
17 int oldkbmode;
18 struct termios old;
19
20 /*
21  * version 0.81 of showkey would restore kbmode unconditially to XLATE,
22  * thus making the console unusable when it was called under X.
23  */
24 static void
25 get_mode(void) {
26         char *m;
27
28         if (ioctl(fd, KDGKBMODE, &oldkbmode)) {
29                 perror("KDGKBMODE");
30                 exit(1);
31         }
32         switch(oldkbmode) {
33           case K_RAW:
34             m = "RAW"; break;
35           case K_XLATE:
36             m = "XLATE"; break;
37           case K_MEDIUMRAW:
38             m = "MEDIUMRAW"; break;
39           case K_UNICODE:
40             m = "UNICODE"; break;
41           default:
42             m = _("?UNKNOWN?"); break;
43         }
44         printf(_("kb mode was %s\n"), m);
45         if (oldkbmode != K_XLATE) {
46             printf(_("[ if you are trying this under X, it might not work\n"
47                      "since the X server is also reading /dev/console ]\n"));
48         }
49         printf("\n");
50 }
51
52 static void
53 clean_up(void) {
54         if (ioctl(fd, KDSKBMODE, oldkbmode)) {
55                 perror("KDSKBMODE");
56                 exit(1);
57         }
58         if (tcsetattr(fd, 0, &old) == -1)
59                 perror("tcsetattr");
60         close(fd);
61 }
62
63 static void __attribute__ ((noreturn))
64 die(int x) {
65         printf(_("caught signal %d, cleaning up...\n"), x);
66         clean_up();
67         exit(1);
68 }
69
70 static void __attribute__ ((noreturn))
71 watch_dog(int x __attribute__ ((unused))) {
72         clean_up();
73         exit(0);
74 }
75
76 static void __attribute__ ((noreturn))
77 usage(void) {
78         fprintf(stderr, _(
79 "showkey version %s\n\n"
80 "usage: showkey [options...]\n"
81 "\n"
82 "valid options are:\n"
83 "\n"
84 "       -h --help       display this help text\n"
85 "       -a --ascii      display the decimal/octal/hex values of the keys\n"
86 "       -s --scancodes  display only the raw scan-codes\n"
87 "       -k --keycodes   display only the interpreted keycodes (default)\n"
88 ), PACKAGE_VERSION);
89         exit(1);
90 }
91
92 int
93 main (int argc, char *argv[]) {
94         const char *short_opts = "haskV";
95         const struct option long_opts[] = {
96                 { "help",       no_argument, NULL, 'h' },
97                 { "ascii",      no_argument, NULL, 'a' },
98                 { "scancodes",  no_argument, NULL, 's' },
99                 { "keycodes",   no_argument, NULL, 'k' },
100                 { "version",    no_argument, NULL, 'V' },
101                 { NULL, 0, NULL, 0 }
102         };
103         int c;
104         int show_keycodes = 1;
105         int print_ascii = 0;
106
107         struct termios new;
108         unsigned char buf[18];  /* divisible by 3 */
109         int i, n;
110
111         set_progname(argv[0]);
112
113         setlocale(LC_ALL, "");
114         bindtextdomain(PACKAGE_NAME, LOCALEDIR);
115         textdomain(PACKAGE_NAME);
116
117         while ((c = getopt_long(argc, argv,
118                                 short_opts, long_opts, NULL)) != -1) {
119                 switch (c) {
120                 case 's':
121                         show_keycodes = 0;
122                         break;
123                 case 'k':
124                         show_keycodes = 1;
125                         break;
126                 case 'a':
127                         print_ascii = 1;
128                         break;
129                 case 'V':
130                         print_version_and_exit();
131                 case 'h':
132                 case '?':
133                         usage();
134                 }
135         }
136
137         if (optind < argc)
138                 usage();
139
140         if (print_ascii) {
141                 /* no mode and signal and timer stuff - just read stdin */
142                 fd = 0;
143
144                 if (tcgetattr(fd, &old) == -1)
145                         perror("tcgetattr");
146                 if (tcgetattr(fd, &new) == -1)
147                         perror("tcgetattr");
148
149                 new.c_lflag &= ~ (ICANON | ISIG);
150                 new.c_lflag |= (ECHO | ECHOCTL);
151                 new.c_iflag = 0;
152                 new.c_cc[VMIN] = 1;
153                 new.c_cc[VTIME] = 0;
154
155                 if (tcsetattr(fd, TCSAFLUSH, &new) == -1)
156                         perror("tcgetattr");
157                 printf(_("\nPress any keys - "
158                          "Ctrl-D will terminate this program\n\n"));
159
160                 while (1) {
161                         n = read(fd, buf, 1);
162                         if (n == 1)
163                                 printf(" \t%3d 0%03o 0x%02x\n",
164                                        buf[0], buf[0], buf[0]);
165                         if (n != 1 || buf[0] == 04)
166                                 break;
167                 }
168
169                 if (tcsetattr(fd, 0, &old) == -1)
170                         perror("tcsetattr");
171                 exit(0);
172         }
173
174
175         fd = getfd(NULL);
176
177         /* the program terminates when there is no input for 10 secs */
178         signal(SIGALRM, watch_dog);
179
180         /*
181           if we receive a signal, we want to exit nicely, in
182           order not to leave the keyboard in an unusable mode
183         */
184         signal(SIGHUP, die);
185         signal(SIGINT, die);
186         signal(SIGQUIT, die);
187         signal(SIGILL, die);
188         signal(SIGTRAP, die);
189         signal(SIGABRT, die);
190         signal(SIGIOT, die);
191         signal(SIGFPE, die);
192         signal(SIGKILL, die);
193         signal(SIGUSR1, die);
194         signal(SIGSEGV, die);
195         signal(SIGUSR2, die);
196         signal(SIGPIPE, die);
197         signal(SIGTERM, die);
198 #ifdef SIGSTKFLT
199         signal(SIGSTKFLT, die);
200 #endif
201         signal(SIGCHLD, die);
202         signal(SIGCONT, die);
203         signal(SIGSTOP, die);
204         signal(SIGTSTP, die);
205         signal(SIGTTIN, die);
206         signal(SIGTTOU, die);
207
208         get_mode();
209         if (tcgetattr(fd, &old) == -1)
210                 perror("tcgetattr");
211         if (tcgetattr(fd, &new) == -1)
212                 perror("tcgetattr");
213
214         new.c_lflag &= ~ (ICANON | ECHO | ISIG);
215         new.c_iflag = 0;
216         new.c_cc[VMIN] = sizeof(buf);
217         new.c_cc[VTIME] = 1;    /* 0.1 sec intercharacter timeout */
218
219         if (tcsetattr(fd, TCSAFLUSH, &new) == -1)
220                 perror("tcsetattr");
221         if (ioctl(fd, KDSKBMODE, show_keycodes ? K_MEDIUMRAW : K_RAW)) {
222                 perror("KDSKBMODE");
223                 exit(1);
224         }
225
226         printf(_("press any key (program terminates 10s after last keypress)...\n"));
227
228         /* show scancodes */
229         if (!show_keycodes) {
230                 while (1) {
231                         alarm(10);
232                         n = read(fd, buf, sizeof(buf));
233                         for (i = 0; i < n; i++)
234                                 printf("0x%02x ", buf[i]);
235                         printf("\n");
236                 }
237                 clean_up();
238                 exit(0);
239         }
240
241         /* show keycodes - 2.6 allows 3-byte reports */
242         while (1) {
243                 alarm(10);
244                 n = read(fd, buf, sizeof(buf));
245                 i = 0;
246                 while (i < n) {
247                         int kc;
248                         char *s;
249
250                         s = (buf[i] & 0x80) ? _("release") : _("press");
251
252                         if (i+2 < n && (buf[i] & 0x7f) == 0
253                                 && (buf[i+1] & 0x80) != 0
254                                 && (buf[i+2] & 0x80) != 0) {
255                                 kc = ((buf[i+1] & 0x7f) << 7) |
256                                         (buf[i+2] & 0x7f);
257                                 i += 3;
258                         } else {
259                                 kc = (buf[i] & 0x7f);
260                                 i++;
261                         }
262                         printf(_("keycode %3d %s\n"), kc, s);
263                 }
264         }
265
266         clean_up();
267         exit(0);
268 }