1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1994-1995 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <ctype.h> 35 #include <err.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <fcntl.h> 41 #include <sys/kbio.h> 42 #include <sys/consio.h> 43 #include <sys/queue.h> 44 #include <sys/sysctl.h> 45 #include "path.h" 46 #include "lex.h" 47 48 /* 49 * HALT, PDWN, and PASTE aren't defined in 4.x, but we need them to bridge 50 * to 5.0-current so define them here as a stop gap transition measure. 51 */ 52 #ifndef HALT 53 #define HALT 0xa1 /* halt machine */ 54 #endif 55 #ifndef PDWN 56 #define PDWN 0xa2 /* halt machine and power down */ 57 #endif 58 #ifndef PASTE 59 #define PASTE 0xa3 /* paste from cut-paste buffer */ 60 #endif 61 62 #define SPECIAL 0x80000000 63 64 static const char ctrl_names[32][4] = { 65 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 66 "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 67 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 68 "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 69 }; 70 71 static const char acc_names[15][5] = { 72 "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 73 "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 74 "dcar", 75 }; 76 77 static const char acc_names_u[15][5] = { 78 "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 79 "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 80 "DCAR", 81 }; 82 83 static const char fkey_table[96][MAXFK] = { 84 /* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 85 /* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 86 /* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 87 /* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 88 /* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 89 /* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 90 /* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 91 /* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 92 /* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 93 /* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 94 /* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 95 /* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 96 /* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 97 /* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 98 /* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 99 /* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 100 /* 65-68 */ "" , "" , "" , "" , 101 /* 69-72 */ "" , "" , "" , "" , 102 /* 73-76 */ "" , "" , "" , "" , 103 /* 77-80 */ "" , "" , "" , "" , 104 /* 81-84 */ "" , "" , "" , "" , 105 /* 85-88 */ "" , "" , "" , "" , 106 /* 89-92 */ "" , "" , "" , "" , 107 /* 93-96 */ "" , "" , "" , "" , 108 }; 109 110 static const int delays[] = {250, 500, 750, 1000}; 111 static const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 112 68, 76, 84, 92, 100, 110, 118, 126, 113 136, 152, 168, 184, 200, 220, 236, 252, 114 272, 304, 336, 368, 400, 440, 472, 504}; 115 static const int ndelays = (sizeof(delays) / sizeof(int)); 116 static const int nrepeats = (sizeof(repeats) / sizeof(int)); 117 static int hex = 0; 118 static int paths_configured = 0; 119 static int token; 120 121 int number; 122 char letter; 123 124 static void add_keymap_path(const char *path); 125 static void dump_accent_definition(char *name, accentmap_t *accentmap); 126 static void dump_entry(int value); 127 static void dump_key_definition(char *name, keymap_t *keymap); 128 static int get_accent_definition_line(accentmap_t *); 129 static int get_entry(void); 130 static int get_key_definition_line(keymap_t *); 131 static void load_keymap(char *opt, int dumponly); 132 static void load_default_functionkeys(void); 133 static char * nextarg(int ac, char **av, int *indp, int oc); 134 static char * mkfullname(const char *s1, const char *s2, const char *s3); 135 static void print_accent_definition_line(FILE *fp, int accent, 136 struct acc_t *key); 137 static void print_entry(FILE *fp, int value); 138 static void print_key_definition_line(FILE *fp, int scancode, 139 struct keyent_t *key); 140 static void print_keymap(void); 141 static void release_keyboard(void); 142 static void mux_keyboard(u_int op, char *kbd); 143 static void set_bell_values(char *opt); 144 static void set_functionkey(char *keynumstr, char *string); 145 static void set_keyboard(char *device); 146 static void set_keyrates(char *opt); 147 static void show_kbd_info(void); 148 static void usage(void) __dead2; 149 150 struct pathent { 151 STAILQ_ENTRY(pathent) next; 152 char *path; 153 }; 154 static STAILQ_HEAD(, pathent) pathlist = STAILQ_HEAD_INITIALIZER(pathlist); 155 156 /* Detect presence of vt(4). */ 157 static int 158 is_vt4(void) 159 { 160 char vty_name[4] = ""; 161 size_t len = sizeof(vty_name); 162 163 if (sysctlbyname("kern.vty", vty_name, &len, NULL, 0) != 0) 164 return (0); 165 return (strcmp(vty_name, "vt") == 0); 166 } 167 168 static char * 169 nextarg(int ac, char **av, int *indp, int oc) 170 { 171 if (*indp < ac) 172 return(av[(*indp)++]); 173 warnx("option requires two arguments -- %c", oc); 174 usage(); 175 } 176 177 178 static char * 179 mkfullname(const char *s1, const char *s2, const char *s3) 180 { 181 static char *buf = NULL; 182 static int bufl = 0; 183 int f; 184 185 f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 186 if (f > bufl) { 187 if (buf) 188 buf = (char *)realloc(buf, f); 189 else 190 buf = (char *)malloc(f); 191 } 192 if (!buf) { 193 bufl = 0; 194 return(NULL); 195 } 196 197 bufl = f; 198 strcpy(buf, s1); 199 strcat(buf, s2); 200 strcat(buf, s3); 201 return(buf); 202 } 203 204 205 static int 206 get_entry(void) 207 { 208 switch ((token = yylex())) { 209 case TNOP: 210 return NOP | SPECIAL; 211 case TLSH: 212 return LSH | SPECIAL; 213 case TRSH: 214 return RSH | SPECIAL; 215 case TCLK: 216 return CLK | SPECIAL; 217 case TNLK: 218 return NLK | SPECIAL; 219 case TSLK: 220 return SLK | SPECIAL; 221 case TBTAB: 222 return BTAB | SPECIAL; 223 case TLALT: 224 return LALT | SPECIAL; 225 case TLCTR: 226 return LCTR | SPECIAL; 227 case TNEXT: 228 return NEXT | SPECIAL; 229 case TPREV: 230 return PREV | SPECIAL; 231 case TRCTR: 232 return RCTR | SPECIAL; 233 case TRALT: 234 return RALT | SPECIAL; 235 case TALK: 236 return ALK | SPECIAL; 237 case TASH: 238 return ASH | SPECIAL; 239 case TMETA: 240 return META | SPECIAL; 241 case TRBT: 242 return RBT | SPECIAL; 243 case TDBG: 244 return DBG | SPECIAL; 245 case TSUSP: 246 return SUSP | SPECIAL; 247 case TSPSC: 248 return SPSC | SPECIAL; 249 case TPANIC: 250 return PNC | SPECIAL; 251 case TLSHA: 252 return LSHA | SPECIAL; 253 case TRSHA: 254 return RSHA | SPECIAL; 255 case TLCTRA: 256 return LCTRA | SPECIAL; 257 case TRCTRA: 258 return RCTRA | SPECIAL; 259 case TLALTA: 260 return LALTA | SPECIAL; 261 case TRALTA: 262 return RALTA | SPECIAL; 263 case THALT: 264 return HALT | SPECIAL; 265 case TPDWN: 266 return PDWN | SPECIAL; 267 case TPASTE: 268 return PASTE | SPECIAL; 269 case TACC: 270 if (ACC(number) > L_ACC) 271 return -1; 272 return ACC(number) | SPECIAL; 273 case TFUNC: 274 if (F(number) > L_FN) 275 return -1; 276 return F(number) | SPECIAL; 277 case TSCRN: 278 if (S(number) > L_SCR) 279 return -1; 280 return S(number) | SPECIAL; 281 case TLET: 282 return (unsigned char)letter; 283 case TNUM: 284 if (number < 0x000000 || number > 0x10FFFF) 285 return -1; 286 return number; 287 default: 288 return -1; 289 } 290 } 291 292 static int 293 get_definition_line(FILE *file, keymap_t *keymap, accentmap_t *accentmap) 294 { 295 int c; 296 297 yyin = file; 298 299 if (token < 0) 300 token = yylex(); 301 switch (token) { 302 case TNUM: 303 c = get_key_definition_line(keymap); 304 if (c < 0) 305 errx(1, "invalid key definition"); 306 if (c > keymap->n_keys) 307 keymap->n_keys = c; 308 break; 309 case TACC: 310 c = get_accent_definition_line(accentmap); 311 if (c < 0) 312 errx(1, "invalid accent key definition"); 313 if (c > accentmap->n_accs) 314 accentmap->n_accs = c; 315 break; 316 case 0: 317 /* EOF */ 318 return -1; 319 default: 320 errx(1, "illegal definition line"); 321 } 322 return c; 323 } 324 325 static int 326 get_key_definition_line(keymap_t *map) 327 { 328 int i, def, scancode; 329 330 /* check scancode number */ 331 if (number < 0 || number >= NUM_KEYS) 332 return -1; 333 scancode = number; 334 335 /* get key definitions */ 336 map->key[scancode].spcl = 0; 337 for (i=0; i<NUM_STATES; i++) { 338 if ((def = get_entry()) == -1) 339 return -1; 340 if (def & SPECIAL) 341 map->key[scancode].spcl |= (0x80 >> i); 342 map->key[scancode].map[i] = def & ~SPECIAL; 343 } 344 /* get lock state key def */ 345 if ((token = yylex()) != TFLAG) 346 return -1; 347 map->key[scancode].flgs = number; 348 token = yylex(); 349 return (scancode + 1); 350 } 351 352 static int 353 get_accent_definition_line(accentmap_t *map) 354 { 355 int accent; 356 int c1, c2; 357 int i; 358 359 if (ACC(number) < F_ACC || ACC(number) > L_ACC) 360 /* number out of range */ 361 return -1; 362 accent = number; 363 if (map->acc[accent].accchar != 0) { 364 /* this entry has already been defined before! */ 365 errx(1, "duplicated accent key definition"); 366 } 367 368 switch ((token = yylex())) { 369 case TLET: 370 map->acc[accent].accchar = letter; 371 break; 372 case TNUM: 373 map->acc[accent].accchar = number; 374 break; 375 default: 376 return -1; 377 } 378 379 for (i = 0; (token = yylex()) == '(';) { 380 switch ((token = yylex())) { 381 case TLET: 382 c1 = letter; 383 break; 384 case TNUM: 385 c1 = number; 386 break; 387 default: 388 return -1; 389 } 390 switch ((token = yylex())) { 391 case TLET: 392 c2 = letter; 393 break; 394 case TNUM: 395 c2 = number; 396 break; 397 default: 398 return -1; 399 } 400 if ((token = yylex()) != ')') 401 return -1; 402 if (i >= NUM_ACCENTCHARS) { 403 warnx("too many accented characters, ignored"); 404 continue; 405 } 406 map->acc[accent].map[i][0] = c1; 407 map->acc[accent].map[i][1] = c2; 408 ++i; 409 } 410 return (accent + 1); 411 } 412 413 static void 414 print_entry(FILE *fp, int value) 415 { 416 int val = value & ~SPECIAL; 417 418 switch (value) { 419 case NOP | SPECIAL: 420 fprintf(fp, " nop "); 421 break; 422 case LSH | SPECIAL: 423 fprintf(fp, " lshift"); 424 break; 425 case RSH | SPECIAL: 426 fprintf(fp, " rshift"); 427 break; 428 case CLK | SPECIAL: 429 fprintf(fp, " clock "); 430 break; 431 case NLK | SPECIAL: 432 fprintf(fp, " nlock "); 433 break; 434 case SLK | SPECIAL: 435 fprintf(fp, " slock "); 436 break; 437 case BTAB | SPECIAL: 438 fprintf(fp, " btab "); 439 break; 440 case LALT | SPECIAL: 441 fprintf(fp, " lalt "); 442 break; 443 case LCTR | SPECIAL: 444 fprintf(fp, " lctrl "); 445 break; 446 case NEXT | SPECIAL: 447 fprintf(fp, " nscr "); 448 break; 449 case PREV | SPECIAL: 450 fprintf(fp, " pscr "); 451 break; 452 case RCTR | SPECIAL: 453 fprintf(fp, " rctrl "); 454 break; 455 case RALT | SPECIAL: 456 fprintf(fp, " ralt "); 457 break; 458 case ALK | SPECIAL: 459 fprintf(fp, " alock "); 460 break; 461 case ASH | SPECIAL: 462 fprintf(fp, " ashift"); 463 break; 464 case META | SPECIAL: 465 fprintf(fp, " meta "); 466 break; 467 case RBT | SPECIAL: 468 fprintf(fp, " boot "); 469 break; 470 case DBG | SPECIAL: 471 fprintf(fp, " debug "); 472 break; 473 case SUSP | SPECIAL: 474 fprintf(fp, " susp "); 475 break; 476 case SPSC | SPECIAL: 477 fprintf(fp, " saver "); 478 break; 479 case PNC | SPECIAL: 480 fprintf(fp, " panic "); 481 break; 482 case LSHA | SPECIAL: 483 fprintf(fp, " lshifta"); 484 break; 485 case RSHA | SPECIAL: 486 fprintf(fp, " rshifta"); 487 break; 488 case LCTRA | SPECIAL: 489 fprintf(fp, " lctrla"); 490 break; 491 case RCTRA | SPECIAL: 492 fprintf(fp, " rctrla"); 493 break; 494 case LALTA | SPECIAL: 495 fprintf(fp, " lalta "); 496 break; 497 case RALTA | SPECIAL: 498 fprintf(fp, " ralta "); 499 break; 500 case HALT | SPECIAL: 501 fprintf(fp, " halt "); 502 break; 503 case PDWN | SPECIAL: 504 fprintf(fp, " pdwn "); 505 break; 506 case PASTE | SPECIAL: 507 fprintf(fp, " paste "); 508 break; 509 default: 510 if (value & SPECIAL) { 511 if (val >= F_FN && val <= L_FN) 512 fprintf(fp, " fkey%02d", val - F_FN + 1); 513 else if (val >= F_SCR && val <= L_SCR) 514 fprintf(fp, " scr%02d ", val - F_SCR + 1); 515 else if (val >= F_ACC && val <= L_ACC) 516 fprintf(fp, " %-6s", acc_names[val - F_ACC]); 517 else if (hex) 518 fprintf(fp, " 0x%02x ", val); 519 else 520 fprintf(fp, " %3d ", val); 521 } 522 else { 523 if (val < ' ') 524 fprintf(fp, " %s ", ctrl_names[val]); 525 else if (val == 127) 526 fprintf(fp, " del "); 527 else if (isascii(val) && isprint(val)) 528 fprintf(fp, " '%c' ", val); 529 else if (hex) 530 fprintf(fp, " 0x%02x ", val); 531 else 532 fprintf(fp, " %3d ", val); 533 } 534 } 535 } 536 537 static void 538 print_key_definition_line(FILE *fp, int scancode, struct keyent_t *key) 539 { 540 int i; 541 542 /* print scancode number */ 543 if (hex) 544 fprintf(fp, " 0x%02x ", scancode); 545 else 546 fprintf(fp, " %03d ", scancode); 547 548 /* print key definitions */ 549 for (i=0; i<NUM_STATES; i++) { 550 if (key->spcl & (0x80 >> i)) 551 print_entry(fp, key->map[i] | SPECIAL); 552 else 553 print_entry(fp, key->map[i]); 554 } 555 556 /* print lock state key def */ 557 switch (key->flgs) { 558 case 0: 559 fprintf(fp, " O\n"); 560 break; 561 case 1: 562 fprintf(fp, " C\n"); 563 break; 564 case 2: 565 fprintf(fp, " N\n"); 566 break; 567 case 3: 568 fprintf(fp, " B\n"); 569 break; 570 } 571 } 572 573 static void 574 print_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 575 { 576 int c; 577 int i; 578 579 if (key->accchar == 0) 580 return; 581 582 /* print accent number */ 583 fprintf(fp, " %-6s", acc_names[accent]); 584 if (isascii(key->accchar) && isprint(key->accchar)) 585 fprintf(fp, "'%c' ", key->accchar); 586 else if (hex) 587 fprintf(fp, "0x%02x ", key->accchar); 588 else 589 fprintf(fp, "%03d ", key->accchar); 590 591 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 592 c = key->map[i][0]; 593 if (c == 0) 594 break; 595 if ((i > 0) && ((i % 4) == 0)) 596 fprintf(fp, "\n "); 597 if (isascii(c) && isprint(c)) 598 fprintf(fp, "( '%c' ", c); 599 else if (hex) 600 fprintf(fp, "(0x%02x ", c); 601 else 602 fprintf(fp, "( %03d ", c); 603 c = key->map[i][1]; 604 if (isascii(c) && isprint(c)) 605 fprintf(fp, "'%c' ) ", c); 606 else if (hex) 607 fprintf(fp, "0x%02x) ", c); 608 else 609 fprintf(fp, "%03d ) ", c); 610 } 611 fprintf(fp, "\n"); 612 } 613 614 static void 615 dump_entry(int value) 616 { 617 if (value & SPECIAL) { 618 value &= ~SPECIAL; 619 switch (value) { 620 case NOP: 621 printf(" NOP, "); 622 break; 623 case LSH: 624 printf(" LSH, "); 625 break; 626 case RSH: 627 printf(" RSH, "); 628 break; 629 case CLK: 630 printf(" CLK, "); 631 break; 632 case NLK: 633 printf(" NLK, "); 634 break; 635 case SLK: 636 printf(" SLK, "); 637 break; 638 case BTAB: 639 printf(" BTAB, "); 640 break; 641 case LALT: 642 printf(" LALT, "); 643 break; 644 case LCTR: 645 printf(" LCTR, "); 646 break; 647 case NEXT: 648 printf(" NEXT, "); 649 break; 650 case PREV: 651 printf(" PREV, "); 652 break; 653 case RCTR: 654 printf(" RCTR, "); 655 break; 656 case RALT: 657 printf(" RALT, "); 658 break; 659 case ALK: 660 printf(" ALK, "); 661 break; 662 case ASH: 663 printf(" ASH, "); 664 break; 665 case META: 666 printf(" META, "); 667 break; 668 case RBT: 669 printf(" RBT, "); 670 break; 671 case DBG: 672 printf(" DBG, "); 673 break; 674 case SUSP: 675 printf(" SUSP, "); 676 break; 677 case SPSC: 678 printf(" SPSC, "); 679 break; 680 case PNC: 681 printf(" PNC, "); 682 break; 683 case LSHA: 684 printf(" LSHA, "); 685 break; 686 case RSHA: 687 printf(" RSHA, "); 688 break; 689 case LCTRA: 690 printf("LCTRA, "); 691 break; 692 case RCTRA: 693 printf("RCTRA, "); 694 break; 695 case LALTA: 696 printf("LALTA, "); 697 break; 698 case RALTA: 699 printf("RALTA, "); 700 break; 701 case HALT: 702 printf(" HALT, "); 703 break; 704 case PDWN: 705 printf(" PDWN, "); 706 break; 707 case PASTE: 708 printf("PASTE, "); 709 break; 710 default: 711 if (value >= F_FN && value <= L_FN) 712 printf(" F(%2d),", value - F_FN + 1); 713 else if (value >= F_SCR && value <= L_SCR) 714 printf(" S(%2d),", value - F_SCR + 1); 715 else if (value >= F_ACC && value <= L_ACC) 716 printf(" %-4s, ", acc_names_u[value - F_ACC]); 717 else 718 printf(" 0x%02X, ", value); 719 break; 720 } 721 } else if (value == '\'') { 722 printf(" '\\'', "); 723 } else if (value == '\\') { 724 printf(" '\\\\', "); 725 } else if (isascii(value) && isprint(value)) { 726 printf(" '%c', ", value); 727 } else { 728 printf(" 0x%02X, ", value); 729 } 730 } 731 732 static void 733 dump_key_definition(char *name, keymap_t *keymap) 734 { 735 int i, j; 736 737 printf("static keymap_t keymap_%s = { 0x%02x, {\n", 738 name, (unsigned)keymap->n_keys); 739 printf( 740 "/* alt\n" 741 " * scan cntrl alt alt cntrl\n" 742 " * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 743 " * ---------------------------------------------------------------------------\n" 744 " */\n"); 745 for (i = 0; i < keymap->n_keys; i++) { 746 printf("/*%02x*/{{", i); 747 for (j = 0; j < NUM_STATES; j++) { 748 if (keymap->key[i].spcl & (0x80 >> j)) 749 dump_entry(keymap->key[i].map[j] | SPECIAL); 750 else 751 dump_entry(keymap->key[i].map[j]); 752 } 753 printf("}, 0x%02X,0x%02X },\n", 754 (unsigned)keymap->key[i].spcl, 755 (unsigned)keymap->key[i].flgs); 756 } 757 printf("} };\n\n"); 758 } 759 760 static void 761 dump_accent_definition(char *name, accentmap_t *accentmap) 762 { 763 int i, j; 764 int c; 765 766 printf("static accentmap_t accentmap_%s = { %d", 767 name, accentmap->n_accs); 768 if (accentmap->n_accs <= 0) { 769 printf(" };\n\n"); 770 return; 771 } 772 printf(", {\n"); 773 for (i = 0; i < NUM_DEADKEYS; i++) { 774 printf(" /* %s=%d */\n {", acc_names[i], i); 775 c = accentmap->acc[i].accchar; 776 if (c == '\'') 777 printf(" '\\'', {"); 778 else if (c == '\\') 779 printf(" '\\\\', {"); 780 else if (isascii(c) && isprint(c)) 781 printf(" '%c', {", c); 782 else if (c == 0) { 783 printf(" 0x00 }, \n"); 784 continue; 785 } else 786 printf(" 0x%02x, {", c); 787 for (j = 0; j < NUM_ACCENTCHARS; j++) { 788 c = accentmap->acc[i].map[j][0]; 789 if (c == 0) 790 break; 791 if ((j > 0) && ((j % 4) == 0)) 792 printf("\n\t "); 793 if (isascii(c) && isprint(c)) 794 printf(" { '%c',", c); 795 else 796 printf(" { 0x%02x,", c); 797 printf("0x%02x },", accentmap->acc[i].map[j][1]); 798 } 799 printf(" }, },\n"); 800 } 801 printf("} };\n\n"); 802 } 803 804 static void 805 add_keymap_path(const char *path) 806 { 807 struct pathent* pe; 808 size_t len; 809 810 len = strlen(path); 811 if ((pe = malloc(sizeof(*pe))) == NULL || 812 (pe->path = malloc(len + 2)) == NULL) 813 err(1, "malloc"); 814 memcpy(pe->path, path, len); 815 if (len > 0 && path[len - 1] != '/') 816 pe->path[len++] = '/'; 817 pe->path[len] = '\0'; 818 STAILQ_INSERT_TAIL(&pathlist, pe, next); 819 } 820 821 static void 822 load_keymap(char *opt, int dumponly) 823 { 824 keymap_t keymap; 825 accentmap_t accentmap; 826 struct pathent *pe; 827 FILE *file; 828 int j; 829 char *name, *cp; 830 char blank[] = "", keymap_path[] = KEYMAP_PATH; 831 char vt_keymap_path[] = VT_KEYMAP_PATH, dotkbd[] = ".kbd"; 832 char *postfix[] = {blank, dotkbd, NULL}; 833 834 if (!paths_configured) { 835 cp = getenv("KEYMAP_PATH"); 836 if (cp != NULL) 837 add_keymap_path(cp); 838 add_keymap_path(""); 839 if (is_vt4()) 840 add_keymap_path(vt_keymap_path); 841 else 842 add_keymap_path(keymap_path); 843 paths_configured = 1; 844 } 845 846 file = NULL; 847 STAILQ_FOREACH(pe, &pathlist, next) { 848 for (j=0; postfix[j] && file == NULL; j++) { 849 name = mkfullname(pe->path, opt, postfix[j]); 850 file = fopen(name, "r"); 851 if (file != NULL) 852 break; 853 } 854 } 855 if (file == NULL) { 856 warn("keymap file \"%s\" not found", opt); 857 return; 858 } 859 memset(&keymap, 0, sizeof(keymap)); 860 memset(&accentmap, 0, sizeof(accentmap)); 861 token = -1; 862 while (1) { 863 if (get_definition_line(file, &keymap, &accentmap) < 0) 864 break; 865 } 866 if (dumponly) { 867 /* fix up the filename to make it a valid C identifier */ 868 for (cp = opt; *cp; cp++) 869 if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 870 printf("/*\n" 871 " * Automatically generated from %s.\n" 872 " * DO NOT EDIT!\n" 873 " */\n", name); 874 dump_key_definition(opt, &keymap); 875 dump_accent_definition(opt, &accentmap); 876 return; 877 } 878 if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 879 warn("setting keymap"); 880 fclose(file); 881 return; 882 } 883 if ((accentmap.n_accs > 0) 884 && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 885 warn("setting accentmap"); 886 fclose(file); 887 return; 888 } 889 } 890 891 static void 892 print_keymap(void) 893 { 894 keymap_t keymap; 895 accentmap_t accentmap; 896 int i; 897 898 if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 899 err(1, "getting keymap"); 900 if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 901 memset(&accentmap, 0, sizeof(accentmap)); 902 printf( 903 "# alt\n" 904 "# scan cntrl alt alt cntrl lock\n" 905 "# code base shift cntrl shift alt shift cntrl shift state\n" 906 "# ------------------------------------------------------------------\n" 907 ); 908 for (i=0; i<keymap.n_keys; i++) 909 print_key_definition_line(stdout, i, &keymap.key[i]); 910 911 printf("\n"); 912 for (i = 0; i < NUM_DEADKEYS; i++) 913 print_accent_definition_line(stdout, i, &accentmap.acc[i]); 914 915 } 916 917 static void 918 load_default_functionkeys(void) 919 { 920 fkeyarg_t fkey; 921 int i; 922 923 for (i=0; i<NUM_FKEYS; i++) { 924 fkey.keynum = i; 925 strcpy(fkey.keydef, fkey_table[i]); 926 fkey.flen = strlen(fkey_table[i]); 927 if (ioctl(0, SETFKEY, &fkey) < 0) 928 warn("setting function key"); 929 } 930 } 931 932 static void 933 set_functionkey(char *keynumstr, char *string) 934 { 935 fkeyarg_t fkey; 936 937 if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 938 load_default_functionkeys(); 939 return; 940 } 941 fkey.keynum = atoi(keynumstr); 942 if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 943 warnx("function key number must be between 1 and %d", 944 NUM_FKEYS); 945 return; 946 } 947 if ((fkey.flen = strlen(string)) > MAXFK) { 948 warnx("function key string too long (%d > %d)", 949 fkey.flen, MAXFK); 950 return; 951 } 952 strncpy(fkey.keydef, string, MAXFK); 953 fkey.keynum -= 1; 954 if (ioctl(0, SETFKEY, &fkey) < 0) 955 warn("setting function key"); 956 } 957 958 static void 959 set_bell_values(char *opt) 960 { 961 int bell, duration, pitch; 962 963 bell = 0; 964 duration = 0; 965 pitch = 0; 966 if (!strncmp(opt, "quiet.", 6)) { 967 bell = CONS_QUIET_BELL; 968 opt += 6; 969 } 970 if (!strcmp(opt, "visual")) 971 bell |= CONS_VISUAL_BELL; 972 else if (!strcmp(opt, "normal")) 973 duration = 5, pitch = 800; 974 else if (!strcmp(opt, "off")) 975 duration = 0, pitch = 0; 976 else { 977 char *v1; 978 979 bell = 0; 980 duration = strtol(opt, &v1, 0); 981 if ((duration < 0) || (*v1 != '.')) 982 goto badopt; 983 opt = ++v1; 984 pitch = strtol(opt, &v1, 0); 985 if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 986 badopt: 987 warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off"); 988 return; 989 } 990 if (pitch != 0) 991 pitch = 1193182 / pitch; /* in Hz */ 992 duration /= 10; /* in 10 m sec */ 993 } 994 995 ioctl(0, CONS_BELLTYPE, &bell); 996 if (duration > 0 && pitch > 0) 997 fprintf(stderr, "\e[=%d;%dB", pitch, duration); 998 } 999 1000 static void 1001 set_keyrates(char *opt) 1002 { 1003 int arg[2]; 1004 int repeat; 1005 int delay; 1006 int r, d; 1007 1008 if (!strcmp(opt, "slow")) { 1009 delay = 1000, repeat = 500; 1010 d = 3, r = 31; 1011 } else if (!strcmp(opt, "normal")) { 1012 delay = 500, repeat = 125; 1013 d = 1, r = 15; 1014 } else if (!strcmp(opt, "fast")) { 1015 delay = repeat = 0; 1016 d = r = 0; 1017 } else { 1018 int n; 1019 char *v1; 1020 1021 delay = strtol(opt, &v1, 0); 1022 if ((delay < 0) || (*v1 != '.')) 1023 goto badopt; 1024 opt = ++v1; 1025 repeat = strtol(opt, &v1, 0); 1026 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 1027 badopt: 1028 warnx("argument to -r must be delay.repeat or slow|normal|fast"); 1029 return; 1030 } 1031 for (n = 0; n < ndelays - 1; n++) 1032 if (delay <= delays[n]) 1033 break; 1034 d = n; 1035 for (n = 0; n < nrepeats - 1; n++) 1036 if (repeat <= repeats[n]) 1037 break; 1038 r = n; 1039 } 1040 1041 arg[0] = delay; 1042 arg[1] = repeat; 1043 if (ioctl(0, KDSETREPEAT, arg)) { 1044 if (ioctl(0, KDSETRAD, (d << 5) | r)) 1045 warn("setting keyboard rate"); 1046 } 1047 } 1048 1049 static const char * 1050 get_kbd_type_name(int type) 1051 { 1052 static struct { 1053 int type; 1054 const char *name; 1055 } name_table[] = { 1056 { KB_84, "AT 84" }, 1057 { KB_101, "AT 101/102" }, 1058 { KB_OTHER, "generic" }, 1059 }; 1060 unsigned int i; 1061 1062 for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 1063 if (type == name_table[i].type) 1064 return name_table[i].name; 1065 } 1066 return "unknown"; 1067 } 1068 1069 static void 1070 show_kbd_info(void) 1071 { 1072 keyboard_info_t info; 1073 1074 if (ioctl(0, KDGKBINFO, &info) == -1) { 1075 warn("unable to obtain keyboard information"); 1076 return; 1077 } 1078 printf("kbd%d:\n", info.kb_index); 1079 printf(" %.*s%d, type:%s (%d)\n", 1080 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1081 get_kbd_type_name(info.kb_type), info.kb_type); 1082 } 1083 1084 static void 1085 set_keyboard(char *device) 1086 { 1087 keyboard_info_t info; 1088 int fd; 1089 1090 fd = open(device, O_RDONLY); 1091 if (fd < 0) { 1092 warn("cannot open %s", device); 1093 return; 1094 } 1095 if (ioctl(fd, KDGKBINFO, &info) == -1) { 1096 warn("unable to obtain keyboard information"); 1097 close(fd); 1098 return; 1099 } 1100 /* 1101 * The keyboard device driver won't release the keyboard by 1102 * the following ioctl, but it automatically will, when the device 1103 * is closed. So, we don't check error here. 1104 */ 1105 ioctl(fd, CONS_RELKBD, 0); 1106 close(fd); 1107 #if 1 1108 printf("kbd%d\n", info.kb_index); 1109 printf(" %.*s%d, type:%s (%d)\n", 1110 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1111 get_kbd_type_name(info.kb_type), info.kb_type); 1112 #endif 1113 1114 if (ioctl(0, CONS_SETKBD, info.kb_index) == -1) 1115 warn("unable to set keyboard"); 1116 } 1117 1118 static void 1119 release_keyboard(void) 1120 { 1121 keyboard_info_t info; 1122 1123 /* 1124 * If stdin is not associated with a keyboard, the following ioctl 1125 * will fail. 1126 */ 1127 if (ioctl(0, KDGKBINFO, &info) == -1) { 1128 warn("unable to obtain keyboard information"); 1129 return; 1130 } 1131 #if 1 1132 printf("kbd%d\n", info.kb_index); 1133 printf(" %.*s%d, type:%s (%d)\n", 1134 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1135 get_kbd_type_name(info.kb_type), info.kb_type); 1136 #endif 1137 if (ioctl(0, CONS_RELKBD, 0) == -1) 1138 warn("unable to release the keyboard"); 1139 } 1140 1141 static void 1142 mux_keyboard(u_int op, char *kbd) 1143 { 1144 keyboard_info_t info; 1145 char *unit, *ep; 1146 1147 /* 1148 * If stdin is not associated with a keyboard, the following ioctl 1149 * will fail. 1150 */ 1151 if (ioctl(0, KDGKBINFO, &info) == -1) { 1152 warn("unable to obtain keyboard information"); 1153 return; 1154 } 1155 #if 1 1156 printf("kbd%d\n", info.kb_index); 1157 printf(" %.*s%d, type:%s (%d)\n", 1158 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1159 get_kbd_type_name(info.kb_type), info.kb_type); 1160 #endif 1161 /* 1162 * split kbd into name and unit. find the right most part of the 1163 * kbd string that consist of only digits. 1164 */ 1165 1166 memset(&info, 0, sizeof(info)); 1167 1168 info.kb_unit = -1; 1169 ep = kbd - 1; 1170 1171 do { 1172 unit = strpbrk(ep + 1, "0123456789"); 1173 if (unit != NULL) { 1174 info.kb_unit = strtol(unit, &ep, 10); 1175 if (*ep != '\0') 1176 info.kb_unit = -1; 1177 } 1178 } while (unit != NULL && info.kb_unit == -1); 1179 1180 if (info.kb_unit == -1) { 1181 warnx("unable to find keyboard driver unit in '%s'", kbd); 1182 return; 1183 } 1184 1185 if (unit == kbd) { 1186 warnx("unable to find keyboard driver name in '%s'", kbd); 1187 return; 1188 } 1189 if (unit - kbd >= (int) sizeof(info.kb_name)) { 1190 warnx("keyboard name '%s' is too long", kbd); 1191 return; 1192 } 1193 1194 strncpy(info.kb_name, kbd, unit - kbd); 1195 1196 /* 1197 * If stdin is not associated with a kbdmux(4) keyboard, the following 1198 * ioctl will fail. 1199 */ 1200 1201 if (ioctl(0, op, &info) == -1) 1202 warn("unable to (un)mux the keyboard"); 1203 } 1204 1205 static void 1206 usage(void) 1207 { 1208 fprintf(stderr, "%s\n%s\n%s\n", 1209 "usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]", 1210 " [-r delay.repeat | speed] [-l mapfile] [-f # string]", 1211 " [-k device] [-L mapfile] [-P path]"); 1212 exit(1); 1213 } 1214 1215 1216 int 1217 main(int argc, char **argv) 1218 { 1219 const char *optstring = "A:a:b:df:iKk:Fl:L:P:r:x"; 1220 int opt; 1221 1222 /* Collect any -P arguments, regardless of where they appear. */ 1223 while ((opt = getopt(argc, argv, optstring)) != -1) 1224 if (opt == 'P') 1225 add_keymap_path(optarg); 1226 1227 optind = optreset = 1; 1228 while ((opt = getopt(argc, argv, optstring)) != -1) 1229 switch(opt) { 1230 case 'A': 1231 case 'a': 1232 mux_keyboard((opt == 'A')? KBRELKBD : KBADDKBD, optarg); 1233 break; 1234 case 'b': 1235 set_bell_values(optarg); 1236 break; 1237 case 'd': 1238 print_keymap(); 1239 break; 1240 case 'l': 1241 load_keymap(optarg, 0); 1242 break; 1243 case 'L': 1244 load_keymap(optarg, 1); 1245 break; 1246 case 'P': 1247 break; 1248 case 'f': 1249 set_functionkey(optarg, 1250 nextarg(argc, argv, &optind, 'f')); 1251 break; 1252 case 'F': 1253 load_default_functionkeys(); 1254 break; 1255 case 'i': 1256 show_kbd_info(); 1257 break; 1258 case 'K': 1259 release_keyboard(); 1260 break; 1261 case 'k': 1262 set_keyboard(optarg); 1263 break; 1264 case 'r': 1265 set_keyrates(optarg); 1266 break; 1267 case 'x': 1268 hex = 1; 1269 break; 1270 default: 1271 usage(); 1272 } 1273 if ((optind != argc) || (argc == 1)) 1274 usage(); 1275 exit(0); 1276 } 1277